diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 8dbe8ebc5e..c81647f94f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,18 +1,28 @@ [bumpversion] -current_version = 2023.10.6 +current_version = 2024.4.2 tag = True commit = True -parse = (?P\d+)\.(?P\d+)\.(?P\d+) -serialize = {major}.{minor}.{patch} +parse = (?P\d+)\.(?P\d+)\.(?P\d+)(?:-(?P[a-zA-Z-]+)(?P[1-9]\\d*))? +serialize = + {major}.{minor}.{patch}-{rc_t}{rc_n} + {major}.{minor}.{patch} message = release: {new_version} tag_name = version/{new_version} +[bumpversion:part:rc_t] +values = + rc + final +optional_value = final + [bumpversion:file:pyproject.toml] [bumpversion:file:docker-compose.yml] [bumpversion:file:schema.yml] +[bumpversion:file:blueprints/schema.json] + [bumpversion:file:authentik/__init__.py] [bumpversion:file:internal/constants/constants.go] diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 178ae15132..19c71ebaaa 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: [BeryJu] +custom: https://goauthentik.io/pricing/ diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index d966aee973..6c083bd864 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -9,7 +9,7 @@ assignees: "" **Describe your question/** A clear and concise description of what you're trying to do. -**Relevant infos** +**Relevant info** i.e. Version of other software you're using, specifics of your setup **Screenshots** diff --git a/.github/actions/comment-pr-instructions/action.yml b/.github/actions/comment-pr-instructions/action.yml index b8fb31eaaa..f74a99fafb 100644 --- a/.github/actions/comment-pr-instructions/action.yml +++ b/.github/actions/comment-pr-instructions/action.yml @@ -9,9 +9,6 @@ inputs: runs: using: "composite" steps: - - name: Generate config - id: ev - uses: ./.github/actions/docker-push-variables - name: Find Comment uses: peter-evans/find-comment@v2 id: fc diff --git a/.github/actions/docker-push-variables/action.yml b/.github/actions/docker-push-variables/action.yml index 7ae3d1adf9..f322c2ab66 100644 --- a/.github/actions/docker-push-variables/action.yml +++ b/.github/actions/docker-push-variables/action.yml @@ -1,64 +1,47 @@ +--- name: "Prepare docker environment variables" description: "Prepare docker environment variables" +inputs: + image-name: + required: true + description: "Docker image prefix" + image-arch: + required: false + description: "Docker image arch" + outputs: shouldBuild: description: "Whether to build image or not" value: ${{ steps.ev.outputs.shouldBuild }} - branchName: - description: "Branch name" - value: ${{ steps.ev.outputs.branchName }} - branchNameContainer: - description: "Branch name (for containers)" - value: ${{ steps.ev.outputs.branchNameContainer }} - timestamp: - description: "Timestamp" - value: ${{ steps.ev.outputs.timestamp }} + sha: description: "sha" value: ${{ steps.ev.outputs.sha }} - shortHash: - description: "shortHash" - value: ${{ steps.ev.outputs.shortHash }} + version: - description: "version" + description: "Version" value: ${{ steps.ev.outputs.version }} - versionFamily: - description: "versionFamily" - value: ${{ steps.ev.outputs.versionFamily }} + prerelease: + description: "Prerelease" + value: ${{ steps.ev.outputs.prerelease }} + + imageTags: + description: "Docker image tags" + value: ${{ steps.ev.outputs.imageTags }} + imageMainTag: + description: "Docker image main tag" + value: ${{ steps.ev.outputs.imageMainTag }} runs: using: "composite" steps: - name: Generate config id: ev - shell: python + shell: bash + env: + IMAGE_NAME: ${{ inputs.image-name }} + IMAGE_ARCH: ${{ inputs.image-arch }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | - """Helper script to get the actual branch name, docker safe""" - import configparser - import os - from time import time - - parser = configparser.ConfigParser() - parser.read(".bumpversion.cfg") - - branch_name = os.environ["GITHUB_REF"] - if os.environ.get("GITHUB_HEAD_REF", "") != "": - branch_name = os.environ["GITHUB_HEAD_REF"] - - should_build = str(os.environ.get("DOCKER_USERNAME", "") != "").lower() - version = parser.get("bumpversion", "current_version") - version_family = ".".join(version.split(".")[:-1]) - safe_branch_name = branch_name.replace("refs/heads/", "").replace("/", "-") - - sha = os.environ["GITHUB_SHA"] if not "${{ github.event.pull_request.head.sha }}" else "${{ github.event.pull_request.head.sha }}" - - with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output: - print("branchName=%s" % branch_name, file=_output) - print("branchNameContainer=%s" % safe_branch_name, file=_output) - print("timestamp=%s" % int(time()), file=_output) - print("sha=%s" % sha, file=_output) - print("shortHash=%s" % sha[:7], file=_output) - print("shouldBuild=%s" % should_build, file=_output) - print("version=%s" % version, file=_output) - print("versionFamily=%s" % version_family, file=_output) + python3 ${{ github.action_path }}/push_vars.py diff --git a/.github/actions/docker-push-variables/push_vars.py b/.github/actions/docker-push-variables/push_vars.py new file mode 100644 index 0000000000..28572b8ca4 --- /dev/null +++ b/.github/actions/docker-push-variables/push_vars.py @@ -0,0 +1,62 @@ +"""Helper script to get the actual branch name, docker safe""" + +import configparser +import os +from time import time + +parser = configparser.ConfigParser() +parser.read(".bumpversion.cfg") + +should_build = str(os.environ.get("DOCKER_USERNAME", None) is not None).lower() + +branch_name = os.environ["GITHUB_REF"] +if os.environ.get("GITHUB_HEAD_REF", "") != "": + branch_name = os.environ["GITHUB_HEAD_REF"] +safe_branch_name = branch_name.replace("refs/heads/", "").replace("/", "-").replace("'", "-") + +image_names = os.getenv("IMAGE_NAME").split(",") +image_arch = os.getenv("IMAGE_ARCH") or None + +is_pull_request = bool(os.getenv("PR_HEAD_SHA")) +is_release = "dev" not in image_names[0] + +sha = os.environ["GITHUB_SHA"] if not is_pull_request else os.getenv("PR_HEAD_SHA") + +# 2042.1.0 or 2042.1.0-rc1 +version = parser.get("bumpversion", "current_version") +# 2042.1 +version_family = ".".join(version.split("-", 1)[0].split(".")[:-1]) +prerelease = "-" in version + +image_tags = [] +if is_release: + for name in image_names: + image_tags += [ + f"{name}:{version}", + ] + if not prerelease: + image_tags += [ + f"{name}:latest", + f"{name}:{version_family}", + ] +else: + suffix = "" + if image_arch and image_arch != "amd64": + suffix = f"-{image_arch}" + for name in image_names: + image_tags += [ + f"{name}:gh-{sha}{suffix}", # Used for ArgoCD and PR comments + f"{name}:gh-{safe_branch_name}{suffix}", # For convenience + f"{name}:gh-{safe_branch_name}-{int(time())}-{sha[:7]}{suffix}", # Use by FluxCD + ] + +image_main_tag = image_tags[0] +image_tags_rendered = ",".join(image_tags) + +with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output: + print(f"shouldBuild={should_build}", file=_output) + print(f"sha={sha}", file=_output) + print(f"version={version}", file=_output) + print(f"prerelease={prerelease}", file=_output) + print(f"imageTags={image_tags_rendered}", file=_output) + print(f"imageMainTag={image_main_tag}", file=_output) diff --git a/.github/actions/docker-push-variables/test.sh b/.github/actions/docker-push-variables/test.sh new file mode 100755 index 0000000000..bfb6cca8af --- /dev/null +++ b/.github/actions/docker-push-variables/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash -x +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +GITHUB_OUTPUT=/dev/stdout \ + GITHUB_REF=ref \ + GITHUB_SHA=sha \ + IMAGE_NAME=ghcr.io/goauthentik/server,beryju/authentik \ + python $SCRIPT_DIR/push_vars.py diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index b2f2865ef5..20501b3f0f 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -16,25 +16,25 @@ runs: sudo apt-get update sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext - name: Setup python and restore poetry - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version-file: "pyproject.toml" cache: "poetry" - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: web/package.json cache: "npm" cache-dependency-path: web/package-lock.json - name: Setup go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version-file: "go.mod" - name: Setup dependencies shell: bash run: | export PSQL_TAG=${{ inputs.postgresql_version }} - docker-compose -f .github/actions/setup/docker-compose.yml up -d + docker compose -f .github/actions/setup/docker-compose.yml up -d poetry install cd web && npm ci - name: Generate config diff --git a/.github/actions/setup/docker-compose.yml b/.github/actions/setup/docker-compose.yml index d012dd21f4..10125a8506 100644 --- a/.github/actions/setup/docker-compose.yml +++ b/.github/actions/setup/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.7" - services: postgresql: image: docker.io/library/postgres:${PSQL_TAG:-16} diff --git a/.github/codespell-words.txt b/.github/codespell-words.txt index 29fb248325..7a7f5ef317 100644 --- a/.github/codespell-words.txt +++ b/.github/codespell-words.txt @@ -3,3 +3,5 @@ keypairs hass warmup ontext +singed +assertIn diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4003002367..0210696684 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -52,6 +52,10 @@ updates: esbuild: patterns: - "@esbuild/*" + rollup: + patterns: + - "@rollup/*" + - "rollup-*" - package-ecosystem: npm directory: "/tests/wdio" schedule: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9deccbc2ec..54e9b8b5b0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -27,7 +27,6 @@ If an API change has been made If changes to the frontend have been made - [ ] The code has been formatted (`make web`) -- [ ] The translation files have been updated (`make i18n-extract`) If applicable diff --git a/.github/workflows/api-py-publish.yml b/.github/workflows/api-py-publish.yml new file mode 100644 index 0000000000..79a1d274e0 --- /dev/null +++ b/.github/workflows/api-py-publish.yml @@ -0,0 +1,65 @@ +name: authentik-api-py-publish +on: + push: + branches: [main] + paths: + - "schema.yml" + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - id: generate_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.GH_APP_ID }} + private_key: ${{ secrets.GH_APP_PRIVATE_KEY }} + - uses: actions/checkout@v4 + with: + token: ${{ steps.generate_token.outputs.token }} + - name: Install poetry & deps + shell: bash + run: | + pipx install poetry || true + sudo apt-get update + sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext + - name: Setup python and restore poetry + uses: actions/setup-python@v5 + with: + python-version-file: "pyproject.toml" + cache: "poetry" + - name: Generate API Client + run: make gen-client-py + - name: Publish package + working-directory: gen-py-api/ + run: | + poetry build + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: gen-py-api/dist/ + # We can't easily upgrade the API client being used due to poetry being poetry + # so we'll have to rely on dependabot + # - name: Upgrade / + # run: | + # export VERSION=$(cd gen-py-api && poetry version -s) + # poetry add "authentik_client=$VERSION" --allow-prereleases --lock + # - uses: peter-evans/create-pull-request@v6 + # id: cpr + # with: + # token: ${{ steps.generate_token.outputs.token }} + # branch: update-root-api-client + # commit-message: "root: bump API Client version" + # title: "root: bump API Client version" + # body: "root: bump API Client version" + # delete-branch: true + # signoff: true + # # ID from https://api.github.com/users/authentik-automation[bot] + # author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com> + # - uses: peter-evans/enable-pull-request-automerge@v3 + # with: + # token: ${{ steps.generate_token.outputs.token }} + # pull-request-number: ${{ steps.cpr.outputs.pull-request-number }} + # merge-method: squash diff --git a/.github/workflows/web-api-publish.yml b/.github/workflows/api-ts-publish.yml similarity index 95% rename from .github/workflows/web-api-publish.yml rename to .github/workflows/api-ts-publish.yml index 4c617a1992..8920a0b602 100644 --- a/.github/workflows/web-api-publish.yml +++ b/.github/workflows/api-ts-publish.yml @@ -1,4 +1,4 @@ -name: authentik-web-api-publish +name: authentik-api-ts-publish on: push: branches: [main] @@ -35,7 +35,7 @@ jobs: run: | export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'` npm i @goauthentik/api@$VERSION - - uses: peter-evans/create-pull-request@v5 + - uses: peter-evans/create-pull-request@v6 id: cpr with: token: ${{ steps.generate_token.outputs.token }} diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 24d4f71e9f..20b2c1dfb9 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -1,3 +1,4 @@ +--- name: authentik-ci-main on: @@ -6,8 +7,6 @@ on: - main - next - version-* - paths-ignore: - - website pull_request: branches: - main @@ -27,10 +26,7 @@ jobs: - bandit - black - codespell - - isort - pending-migrations - - pylint - - pyright - ruff runs-on: ubuntu-latest steps: @@ -69,7 +65,7 @@ jobs: cp authentik/lib/default.yml local.env.yml cp -R .github .. cp -R scripts .. - git checkout version/$(python -c "from authentik import __version__; print(__version__)") + git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1) rm -rf .github/ scripts/ mv ../.github ../scripts . - name: Setup authentik env (stable) @@ -122,9 +118,10 @@ jobs: poetry run make test poetry run coverage xml - if: ${{ always() }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: flags: unit + token: ${{ secrets.CODECOV_TOKEN }} test-integration: runs-on: ubuntu-latest timeout-minutes: 30 @@ -133,15 +130,16 @@ jobs: - name: Setup authentik env uses: ./.github/actions/setup - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@v1.10.0 - name: run integration run: | poetry run coverage run manage.py test tests/integration poetry run coverage xml - if: ${{ always() }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: flags: integration + token: ${{ secrets.CODECOV_TOKEN }} test-e2e: name: test-e2e (${{ matrix.job.name }}) runs-on: ubuntu-latest @@ -162,6 +160,8 @@ jobs: glob: tests/e2e/test_provider_ldap* tests/e2e/test_source_ldap* - name: radius glob: tests/e2e/test_provider_radius* + - name: scim + glob: tests/e2e/test_source_scim* - name: flows glob: tests/e2e/test_flows* steps: @@ -170,7 +170,7 @@ jobs: uses: ./.github/actions/setup - name: Setup e2e env (chrome, etc) run: | - docker-compose -f tests/e2e/docker-compose.yml up -d + docker compose -f tests/e2e/docker-compose.yml up -d - id: cache-web uses: actions/cache@v4 with: @@ -188,9 +188,10 @@ jobs: poetry run coverage run manage.py test ${{ matrix.job.glob }} poetry run coverage xml - if: ${{ always() }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: flags: e2e + token: ${{ secrets.CODECOV_TOKEN }} ci-core-mark: needs: - lint @@ -203,6 +204,12 @@ jobs: steps: - run: echo mark build: + strategy: + fail-fast: false + matrix: + arch: + - amd64 + - arm64 needs: ci-core-mark runs-on: ubuntu-latest permissions: @@ -222,9 +229,12 @@ jobs: id: ev env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/dev-server + image-arch: ${{ matrix.arch }} - name: Login to Container Registry - uses: docker/login-action@v3 if: ${{ steps.ev.outputs.shouldBuild == 'true' }} + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -238,69 +248,16 @@ jobs: secrets: | GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }} GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }} + tags: ${{ steps.ev.outputs.imageTags }} push: ${{ steps.ev.outputs.shouldBuild == 'true' }} - tags: | - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }} - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.sha }} - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }} build-args: | GIT_BUILD_HASH=${{ steps.ev.outputs.sha }} - VERSION=${{ steps.ev.outputs.version }} - VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} - cache-from: type=gha - cache-to: type=gha,mode=max - build-arm64: - needs: ci-core-mark - runs-on: ubuntu-latest - permissions: - # Needed to upload contianer images to ghcr.io - packages: write - timeout-minutes: 120 - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v3.0.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: prepare variables - uses: ./.github/actions/docker-push-variables - id: ev - env: - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - - name: Login to Container Registry - uses: docker/login-action@v3 - if: ${{ steps.ev.outputs.shouldBuild == 'true' }} - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: generate ts client - run: make gen-client-ts - - name: Build Docker Image - uses: docker/build-push-action@v5 - with: - context: . - secrets: | - GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }} - GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }} - push: ${{ steps.ev.outputs.shouldBuild == 'true' }} - tags: | - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-arm64 - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.sha }}-arm64 - ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }}-arm64 - build-args: | - GIT_BUILD_HASH=${{ steps.ev.outputs.sha }} - VERSION=${{ steps.ev.outputs.version }} - VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} - platforms: linux/arm64 - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/goauthentik/dev-server:buildcache + cache-to: type=registry,ref=ghcr.io/goauthentik/dev-server:buildcache,mode=max + platforms: linux/${{ matrix.arch }} pr-comment: needs: - build - - build-arm64 runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} permissions: @@ -316,7 +273,9 @@ jobs: id: ev env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/dev-server - name: Comment on PR uses: ./.github/actions/comment-pr-instructions with: - tag: gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }} + tag: gh-${{ steps.ev.outputs.imageMainTag }} diff --git a/.github/workflows/ci-outpost.yml b/.github/workflows/ci-outpost.yml index 35c83ac860..2d160cb9cf 100644 --- a/.github/workflows/ci-outpost.yml +++ b/.github/workflows/ci-outpost.yml @@ -1,3 +1,4 @@ +--- name: authentik-ci-outpost on: @@ -28,7 +29,7 @@ jobs: - name: Generate API run: make gen-client-go - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: version: v1.54.2 args: --timeout 5000s --verbose @@ -83,9 +84,11 @@ jobs: id: ev env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/dev-${{ matrix.type }} - name: Login to Container Registry - uses: docker/login-action@v3 if: ${{ steps.ev.outputs.shouldBuild == 'true' }} + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -95,19 +98,15 @@ jobs: - name: Build Docker Image uses: docker/build-push-action@v5 with: - push: ${{ steps.ev.outputs.shouldBuild == 'true' }} - tags: | - ghcr.io/goauthentik/dev-${{ matrix.type }}:gh-${{ steps.ev.outputs.branchNameContainer }} - ghcr.io/goauthentik/dev-${{ matrix.type }}:gh-${{ steps.ev.outputs.sha }} + tags: ${{ steps.ev.outputs.imageTags }} file: ${{ matrix.type }}.Dockerfile + push: ${{ steps.ev.outputs.shouldBuild == 'true' }} build-args: | GIT_BUILD_HASH=${{ steps.ev.outputs.sha }} - VERSION=${{ steps.ev.outputs.version }} - VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} platforms: linux/amd64,linux/arm64 context: . - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=ghcr.io/goauthentik/dev-${{ matrix.type }}:buildcache + cache-to: type=registry,ref=ghcr.io/goauthentik/dev-${{ matrix.type }}:buildcache,mode=max build-binary: timeout-minutes: 120 needs: diff --git a/.github/workflows/ci-web.yml b/.github/workflows/ci-web.yml index 43ca0a168f..897104bb14 100644 --- a/.github/workflows/ci-web.yml +++ b/.github/workflows/ci-web.yml @@ -34,6 +34,13 @@ jobs: - name: Eslint working-directory: ${{ matrix.project }}/ run: npm run lint + lint-lockfile: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - working-directory: web/ + run: | + [ -z "$(jq -r '.packages | to_entries[] | select((.key | startswith("node_modules")) and (.value | has("resolved") | not)) | .key' < package-lock.json)" ] lint-build: runs-on: ubuntu-latest steps: @@ -95,6 +102,7 @@ jobs: run: npm run lit-analyse ci-web-mark: needs: + - lint-lockfile - lint-eslint - lint-prettier - lint-lit-analyse diff --git a/.github/workflows/ci-website.yml b/.github/workflows/ci-website.yml index 78a3a8f8a1..001b0d8041 100644 --- a/.github/workflows/ci-website.yml +++ b/.github/workflows/ci-website.yml @@ -12,6 +12,13 @@ on: - version-* jobs: + lint-lockfile: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - working-directory: website/ + run: | + [ -z "$(jq -r '.packages | to_entries[] | select((.key | startswith("node_modules")) and (.value | has("resolved") | not)) | .key' < package-lock.json)" ] lint-prettier: runs-on: ubuntu-latest steps: @@ -48,7 +55,6 @@ jobs: matrix: job: - build - - build-docs-only steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -63,6 +69,7 @@ jobs: run: npm run ${{ matrix.job }} ci-website-mark: needs: + - lint-lockfile - lint-prettier - test - build diff --git a/.github/workflows/gen-update-webauthn-mds.yml b/.github/workflows/gen-update-webauthn-mds.yml new file mode 100644 index 0000000000..c89aa4c2f6 --- /dev/null +++ b/.github/workflows/gen-update-webauthn-mds.yml @@ -0,0 +1,43 @@ +name: authentik-gen-update-webauthn-mds +on: + workflow_dispatch: + schedule: + - cron: '30 1 1,15 * *' + +env: + POSTGRES_DB: authentik + POSTGRES_USER: authentik + POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - id: generate_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.GH_APP_ID }} + private_key: ${{ secrets.GH_APP_PRIVATE_KEY }} + - uses: actions/checkout@v4 + with: + token: ${{ steps.generate_token.outputs.token }} + - name: Setup authentik env + uses: ./.github/actions/setup + - run: poetry run ak update_webauthn_mds + - uses: peter-evans/create-pull-request@v6 + id: cpr + with: + token: ${{ steps.generate_token.outputs.token }} + branch: update-fido-mds-client + commit-message: "stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs" + title: "stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs" + body: "stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs" + delete-branch: true + signoff: true + # ID from https://api.github.com/users/authentik-automation[bot] + author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com> + - uses: peter-evans/enable-pull-request-automerge@v3 + with: + token: ${{ steps.generate_token.outputs.token }} + pull-request-number: ${{ steps.cpr.outputs.pull-request-number }} + merge-method: squash diff --git a/.github/workflows/image-compress.yml b/.github/workflows/image-compress.yml index 02a18553bc..4c186d220f 100644 --- a/.github/workflows/image-compress.yml +++ b/.github/workflows/image-compress.yml @@ -42,7 +42,7 @@ jobs: with: githubToken: ${{ steps.generate_token.outputs.token }} compressOnly: ${{ github.event_name != 'pull_request' }} - - uses: peter-evans/create-pull-request@v5 + - uses: peter-evans/create-pull-request@v6 if: "${{ github.event_name != 'pull_request' && steps.compress.outputs.markdown != '' }}" id: cpr with: diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index c002ab8a54..32016bf004 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -1,3 +1,4 @@ +--- name: authentik-on-release on: @@ -19,6 +20,10 @@ jobs: - name: prepare variables uses: ./.github/actions/docker-push-variables id: ev + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/server,beryju/authentik - name: Docker Login Registry uses: docker/login-action@v3 with: @@ -38,21 +43,12 @@ jobs: uses: docker/build-push-action@v5 with: context: . - push: ${{ github.event_name == 'release' }} + push: true secrets: | GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }} GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }} - tags: | - beryju/authentik:${{ steps.ev.outputs.version }}, - beryju/authentik:${{ steps.ev.outputs.versionFamily }}, - beryju/authentik:latest, - ghcr.io/goauthentik/server:${{ steps.ev.outputs.version }}, - ghcr.io/goauthentik/server:${{ steps.ev.outputs.versionFamily }}, - ghcr.io/goauthentik/server:latest + tags: ${{ steps.ev.outputs.imageTags }} platforms: linux/amd64,linux/arm64 - build-args: | - VERSION=${{ steps.ev.outputs.version }} - VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} build-outpost: runs-on: ubuntu-latest permissions: @@ -78,6 +74,10 @@ jobs: - name: prepare variables uses: ./.github/actions/docker-push-variables id: ev + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/${{ matrix.type }},beryju/authentik-${{ matrix.type }} - name: make empty clients run: | mkdir -p ./gen-ts-api @@ -96,20 +96,11 @@ jobs: - name: Build Docker Image uses: docker/build-push-action@v5 with: - push: ${{ github.event_name == 'release' }} - tags: | - beryju/authentik-${{ matrix.type }}:${{ steps.ev.outputs.version }}, - beryju/authentik-${{ matrix.type }}:${{ steps.ev.outputs.versionFamily }}, - beryju/authentik-${{ matrix.type }}:latest, - ghcr.io/goauthentik/${{ matrix.type }}:${{ steps.ev.outputs.version }}, - ghcr.io/goauthentik/${{ matrix.type }}:${{ steps.ev.outputs.versionFamily }}, - ghcr.io/goauthentik/${{ matrix.type }}:latest + push: true + tags: ${{ steps.ev.outputs.imageTags }} file: ${{ matrix.type }}.Dockerfile platforms: linux/amd64,linux/arm64 context: . - build-args: | - VERSION=${{ steps.ev.outputs.version }} - VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} build-outpost-binary: timeout-minutes: 120 runs-on: ubuntu-latest @@ -164,12 +155,12 @@ jobs: - uses: actions/checkout@v4 - name: Run test suite in final docker images run: | - echo "PG_PASS=$(openssl rand -base64 32)" >> .env - echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env - docker-compose pull -q - docker-compose up --no-start - docker-compose start postgresql redis - docker-compose run -u root server test-all + echo "PG_PASS=$(openssl rand 32 | base64)" >> .env + echo "AUTHENTIK_SECRET_KEY=$(openssl rand 32 | base64)" >> .env + docker compose pull -q + docker compose up --no-start + docker compose start postgresql redis + docker compose run -u root server test-all sentry-release: needs: - build-server @@ -181,15 +172,18 @@ jobs: - name: prepare variables uses: ./.github/actions/docker-push-variables id: ev + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + with: + image-name: ghcr.io/goauthentik/server - name: Get static files from docker image run: | - docker pull ghcr.io/goauthentik/server:latest - container=$(docker container create ghcr.io/goauthentik/server:latest) + docker pull ${{ steps.ev.outputs.imageMainTag }} + container=$(docker container create ${{ steps.ev.outputs.imageMainTag }}) docker cp ${container}:web/ . - name: Create a Sentry.io release uses: getsentry/action-release@v1 continue-on-error: true - if: ${{ github.event_name == 'release' }} env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: authentik-security-inc diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index a0b896a92b..0da13b3c33 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -1,3 +1,4 @@ +--- name: authentik-on-tag on: @@ -13,28 +14,28 @@ jobs: - uses: actions/checkout@v4 - name: Pre-release test run: | - echo "PG_PASS=$(openssl rand -base64 32)" >> .env - echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env + echo "PG_PASS=$(openssl rand 32 | base64)" >> .env + echo "AUTHENTIK_SECRET_KEY=$(openssl rand 32 | base64)" >> .env docker buildx install mkdir -p ./gen-ts-api docker build -t testing:latest . echo "AUTHENTIK_IMAGE=testing" >> .env echo "AUTHENTIK_TAG=latest" >> .env - docker-compose up --no-start - docker-compose start postgresql redis - docker-compose run -u root server test-all + docker compose up --no-start + docker compose start postgresql redis + docker compose run -u root server test-all - id: generate_token uses: tibdex/github-app-token@v2 with: app_id: ${{ secrets.GH_APP_ID }} private_key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - name: Extract version number - id: get_version - uses: actions/github-script@v7 + - name: prepare variables + uses: ./.github/actions/docker-push-variables + id: ev + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} with: - github-token: ${{ steps.generate_token.outputs.token }} - script: | - return context.payload.ref.replace(/\/refs\/tags\/version\//, ''); + image-name: ghcr.io/goauthentik/server - name: Create Release id: create_release uses: actions/create-release@v1.1.4 @@ -42,6 +43,6 @@ jobs: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} with: tag_name: ${{ github.ref }} - release_name: Release ${{ steps.get_version.outputs.result }} + release_name: Release ${{ steps.ev.outputs.version }} draft: true - prerelease: false + prerelease: ${{ steps.ev.outputs.prerelease == 'true' }} diff --git a/.github/workflows/repo-stale.yml b/.github/workflows/repo-stale.yml index 24f0ac0fb0..4918171953 100644 --- a/.github/workflows/repo-stale.yml +++ b/.github/workflows/repo-stale.yml @@ -23,7 +23,7 @@ jobs: repo-token: ${{ steps.generate_token.outputs.token }} days-before-stale: 60 days-before-close: 7 - exempt-issue-labels: pinned,security,pr_wanted,enhancement,bug/confirmed,enhancement/confirmed,question + exempt-issue-labels: pinned,security,pr_wanted,enhancement,bug/confirmed,enhancement/confirmed,question,status/reviewing stale-issue-label: wontfix stale-issue-message: > This issue has been automatically marked as stale because it has not had diff --git a/.github/workflows/translation-advice.yml b/.github/workflows/translation-advice.yml index ad76424fa4..c79c450474 100644 --- a/.github/workflows/translation-advice.yml +++ b/.github/workflows/translation-advice.yml @@ -19,14 +19,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Find Comment - uses: peter-evans/find-comment@v2 + uses: peter-evans/find-comment@v3 id: fc with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" body-includes: authentik translations instructions - name: Create or update comment - uses: peter-evans/create-or-update-comment@v3 + uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/translation-compile.yml b/.github/workflows/translation-extract-compile.yml similarity index 57% rename from .github/workflows/translation-compile.yml rename to .github/workflows/translation-extract-compile.yml index e6d075af7b..eee769ff2e 100644 --- a/.github/workflows/translation-compile.yml +++ b/.github/workflows/translation-extract-compile.yml @@ -1,9 +1,8 @@ -name: authentik-backend-translate-compile +--- +name: authentik-backend-translate-extract-compile on: - push: - branches: [main] - paths: - - "locale/**" + schedule: + - cron: "0 0 * * *" # every day at midnight workflow_dispatch: env: @@ -25,16 +24,20 @@ jobs: token: ${{ steps.generate_token.outputs.token }} - name: Setup authentik env uses: ./.github/actions/setup + - name: run extract + run: | + poetry run make i18n-extract - name: run compile - run: poetry run ak compilemessages + run: | + poetry run ak compilemessages + make web-check-compile - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 - id: cpr + uses: peter-evans/create-pull-request@v6 with: token: ${{ steps.generate_token.outputs.token }} - branch: compile-backend-translation - commit-message: "core: compile backend translations" - title: "core: compile backend translations" - body: "core: compile backend translations" + branch: extract-compile-backend-translation + commit-message: "core, web: update translations" + title: "core, web: update translations" + body: "core, web: update translations" delete-branch: true signoff: true diff --git a/.vscode/extensions.json b/.vscode/extensions.json index dd280d682e..53a07a56d2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -10,8 +10,7 @@ "Gruntfuggly.todo-tree", "mechatroner.rainbow-csv", "ms-python.black-formatter", - "ms-python.isort", - "ms-python.pylint", + "charliermarsh.ruff", "ms-python.python", "ms-python.vscode-pylance", "ms-python.black-formatter", diff --git a/.vscode/settings.json b/.vscode/settings.json index 218800d1ed..ed87f96869 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,20 +4,21 @@ "asgi", "authentik", "authn", + "entra", "goauthentik", "jwks", + "kubernetes", "oidc", "openid", + "passwordless", "plex", "saml", - "totp", - "webauthn", - "traefik", - "passwordless", - "kubernetes", - "sso", - "slo", "scim", + "slo", + "sso", + "totp", + "traefik", + "webauthn", ], "todo-tree.tree.showCountsInTree": true, "todo-tree.tree.showBadges": true, diff --git a/Dockerfile b/Dockerfile index 780e9ce3db..ceedb0f8d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # Stage 1: Build website -FROM --platform=${BUILDPLATFORM} docker.io/node:21 as website-builder +FROM --platform=${BUILDPLATFORM} docker.io/node:22 as website-builder ENV NODE_ENV=production @@ -14,12 +14,13 @@ RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.js COPY ./website /work/website/ COPY ./blueprints /work/blueprints/ +COPY ./schema.yml /work/ COPY ./SECURITY.md /work/ -RUN npm run build-docs-only +RUN npm run build-bundled # Stage 2: Build webui -FROM --platform=${BUILDPLATFORM} docker.io/node:21 as web-builder +FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder ENV NODE_ENV=production @@ -37,7 +38,7 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api RUN npm run build # Stage 3: Build go proxy -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.6-bookworm AS go-builder +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.22-fips-bookworm AS go-builder ARG TARGETOS ARG TARGETARCH @@ -48,6 +49,11 @@ ARG GOARCH=$TARGETARCH WORKDIR /go/src/goauthentik.io +RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ + dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu + RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \ --mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \ --mount=type=cache,target=/go/pkg/mod \ @@ -62,17 +68,17 @@ COPY ./internal /go/src/goauthentik.io/internal COPY ./go.mod /go/src/goauthentik.io/go.mod COPY ./go.sum /go/src/goauthentik.io/go.sum -ENV CGO_ENABLED=0 - RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \ - GOARM="${TARGETVARIANT#v}" go build -o /go/authentik ./cmd/server + if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \ + CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \ + go build -o /go/authentik ./cmd/server # Stage 4: MaxMind GeoIP -FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v6.1 as geoip +FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.0.1 as geoip ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" -ENV GEOIPUPDATE_VERBOSE="true" +ENV GEOIPUPDATE_VERBOSE="1" ENV GEOIPUPDATE_ACCOUNT_ID_FILE="/run/secrets/GEOIPUPDATE_ACCOUNT_ID" ENV GEOIPUPDATE_LICENSE_KEY_FILE="/run/secrets/GEOIPUPDATE_LICENSE_KEY" @@ -83,7 +89,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ /bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" # Stage 5: Python dependencies -FROM docker.io/python:3.12.1-slim-bookworm AS python-deps +FROM ghcr.io/goauthentik/fips-python:3.12.3-slim-bookworm-fips-full AS python-deps WORKDIR /ak-root/poetry @@ -96,19 +102,21 @@ RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloa RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ apt-get update && \ # Required for installing pip packages - apt-get install -y --no-install-recommends build-essential pkg-config libxmlsec1-dev zlib1g-dev libpq-dev + apt-get install -y --no-install-recommends build-essential pkg-config libpq-dev RUN --mount=type=bind,target=./pyproject.toml,src=./pyproject.toml \ --mount=type=bind,target=./poetry.lock,src=./poetry.lock \ --mount=type=cache,target=/root/.cache/pip \ --mount=type=cache,target=/root/.cache/pypoetry \ python -m venv /ak-root/venv/ && \ + bash -c "source ${VENV_PATH}/bin/activate && \ pip3 install --upgrade pip && \ pip3 install poetry && \ - poetry install --only=main --no-ansi --no-interaction + poetry install --only=main --no-ansi --no-interaction --no-root && \ + pip install --force-reinstall /wheels/*" # Stage 6: Run -FROM docker.io/python:3.12.1-slim-bookworm AS final-image +FROM ghcr.io/goauthentik/fips-python:3.12.3-slim-bookworm-fips-full AS final-image ARG GIT_BUILD_HASH ARG VERSION @@ -125,7 +133,7 @@ WORKDIR / # We cannot cache this layer otherwise we'll end up with a bigger image RUN apt-get update && \ # Required for runtime - apt-get install -y --no-install-recommends libpq5 openssl libxmlsec1-openssl libmaxminddb0 ca-certificates && \ + apt-get install -y --no-install-recommends libpq5 libmaxminddb0 ca-certificates && \ # Required for bootstrap & healtcheck apt-get install -y --no-install-recommends runit && \ apt-get clean && \ @@ -149,7 +157,7 @@ COPY --from=go-builder /go/authentik /bin/authentik COPY --from=python-deps /ak-root/venv /ak-root/venv COPY --from=web-builder /work/web/dist/ /web/dist/ COPY --from=web-builder /work/web/authentik/ /web/authentik/ -COPY --from=website-builder /work/website/help/ /website/help/ +COPY --from=website-builder /work/website/build/ /website/help/ COPY --from=geoip /usr/share/GeoIP /geoip USER 1000 @@ -161,6 +169,8 @@ ENV TMPDIR=/dev/shm/ \ VENV_PATH="/ak-root/venv" \ POETRY_VIRTUALENVS_CREATE=false +ENV GOFIPS=1 + HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 CMD [ "ak", "healthcheck" ] ENTRYPOINT [ "dumb-init", "--", "ak" ] diff --git a/Makefile b/Makefile index e72db46279..438992e41d 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,13 @@ PWD = $(shell pwd) UID = $(shell id -u) GID = $(shell id -g) NPM_VERSION = $(shell python -m scripts.npm_version) -PY_SOURCES = authentik tests scripts lifecycle +PY_SOURCES = authentik tests scripts lifecycle .github DOCKER_IMAGE ?= "authentik:test" +GEN_API_TS = "gen-ts-api" +GEN_API_PY = "gen-py-api" +GEN_API_GO = "gen-go-api" + pg_user := $(shell python -m authentik.lib.config postgresql.user 2>/dev/null) pg_host := $(shell python -m authentik.lib.config postgresql.host 2>/dev/null) pg_name := $(shell python -m authentik.lib.config postgresql.name 2>/dev/null) @@ -15,6 +19,7 @@ pg_name := $(shell python -m authentik.lib.config postgresql.name 2>/dev/null) CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \ -I .github/codespell-words.txt \ -S 'web/src/locales/**' \ + -S 'website/developer-docs/api/reference/**' \ authentik \ internal \ cmd \ @@ -42,12 +47,12 @@ test-go: go test -timeout 0 -v -race -cover ./... test-docker: ## Run all tests in a docker-compose - echo "PG_PASS=$(openssl rand -base64 32)" >> .env - echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env - docker-compose pull -q - docker-compose up --no-start - docker-compose start postgresql redis - docker-compose run -u root server test-all + echo "PG_PASS=$(shell openssl rand 32 | base64)" >> .env + echo "AUTHENTIK_SECRET_KEY=$(shell openssl rand 32 | base64)" >> .env + docker compose pull -q + docker compose up --no-start + docker compose start postgresql redis + docker compose run -u root server test-all rm -f .env test: ## Run the server tests and produce a coverage report (locally) @@ -56,15 +61,12 @@ test: ## Run the server tests and produce a coverage report (locally) coverage report lint-fix: ## Lint and automatically fix errors in the python source code. Reports spelling errors. - isort $(PY_SOURCES) black $(PY_SOURCES) - ruff --fix $(PY_SOURCES) + ruff check --fix $(PY_SOURCES) codespell -w $(CODESPELL_ARGS) lint: ## Lint the python and golang sources - bandit -r $(PY_SOURCES) -x node_modules - ./web/node_modules/.bin/pyright $(PY_SOURCES) - pylint $(PY_SOURCES) + bandit -r $(PY_SOURCES) -x web/node_modules -x tests/wdio/node_modules -x website/node_modules golangci-lint run -v core-install: @@ -76,7 +78,15 @@ migrate: ## Run the Authentik Django server's migrations i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service core-i18n-extract: - ak makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en + ak makemessages \ + --add-location file \ + --no-obsolete \ + --ignore web \ + --ignore internal \ + --ignore ${GEN_API_TS} \ + --ignore ${GEN_API_GO} \ + --ignore website \ + -l en install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core` @@ -114,7 +124,7 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a docker run \ --rm -v ${PWD}:/local \ --user ${UID}:${GID} \ - docker.io/openapitools/openapi-diff:2.1.0-beta.6 \ + docker.io/openapitools/openapi-diff:2.1.0-beta.8 \ --markdown /local/diff.md \ /local/old_schema.yml /local/schema.yml rm old_schema.yml @@ -123,13 +133,16 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a npx prettier --write diff.md gen-clean-ts: ## Remove generated API client for Typescript - rm -rf gen-ts-api/ - rm -rf web/node_modules/@goauthentik/api/ + rm -rf ./${GEN_API_TS}/ + rm -rf ./web/node_modules/@goauthentik/api/ gen-clean-go: ## Remove generated API client for Go - rm -rf gen-go-api/ + rm -rf ./${GEN_API_GO}/ -gen-clean: gen-clean-ts gen-clean-go ## Remove generated API clients +gen-clean-py: ## Remove generated API client for Python + rm -rf ./${GEN_API_PY}/ + +gen-clean: gen-clean-ts gen-clean-go gen-clean-py ## Remove generated API clients gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescript into the authentik UI Application docker run \ @@ -138,31 +151,45 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri docker.io/openapitools/openapi-generator-cli:v6.5.0 generate \ -i /local/schema.yml \ -g typescript-fetch \ - -o /local/gen-ts-api \ + -o /local/${GEN_API_TS} \ -c /local/scripts/api-ts-config.yaml \ --additional-properties=npmVersion=${NPM_VERSION} \ --git-repo-id authentik \ --git-user-id goauthentik mkdir -p web/node_modules/@goauthentik/api - cd gen-ts-api && npm i - \cp -rfv gen-ts-api/* web/node_modules/@goauthentik/api + cd ./${GEN_API_TS} && npm i + \cp -rf ./${GEN_API_TS}/* web/node_modules/@goauthentik/api + +gen-client-py: gen-clean-py ## Build and install the authentik API for Python + docker run \ + --rm -v ${PWD}:/local \ + --user ${UID}:${GID} \ + docker.io/openapitools/openapi-generator-cli:v7.4.0 generate \ + -i /local/schema.yml \ + -g python \ + -o /local/${GEN_API_PY} \ + -c /local/scripts/api-py-config.yaml \ + --additional-properties=packageVersion=${NPM_VERSION} \ + --git-repo-id authentik \ + --git-user-id goauthentik + pip install ./${GEN_API_PY} gen-client-go: gen-clean-go ## Build and install the authentik API for Golang - mkdir -p ./gen-go-api ./gen-go-api/templates - wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./gen-go-api/config.yaml - wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./gen-go-api/templates/README.mustache - wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O ./gen-go-api/templates/go.mod.mustache - cp schema.yml ./gen-go-api/ + mkdir -p ./${GEN_API_GO} ./${GEN_API_GO}/templates + wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./${GEN_API_GO}/config.yaml + wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./${GEN_API_GO}/templates/README.mustache + wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O ./${GEN_API_GO}/templates/go.mod.mustache + cp schema.yml ./${GEN_API_GO}/ docker run \ - --rm -v ${PWD}/gen-go-api:/local \ + --rm -v ${PWD}/${GEN_API_GO}:/local \ --user ${UID}:${GID} \ docker.io/openapitools/openapi-generator-cli:v6.5.0 generate \ -i /local/schema.yml \ -g go \ -o /local/ \ -c /local/config.yaml - go mod edit -replace goauthentik.io/api/v3=./gen-go-api - rm -rf ./gen-go-api/config.yaml ./gen-go-api/templates/ + go mod edit -replace goauthentik.io/api/v3=./${GEN_API_GO} + rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/ gen-dev-config: ## Generate a local development config file python -m scripts.generate_config @@ -176,7 +203,7 @@ gen: gen-build gen-client-ts web-build: web-install ## Build the Authentik UI cd web && npm run build -web: web-lint-fix web-lint web-check-compile web-i18n-extract ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it +web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it web-install: ## Install the necessary libraries to build the Authentik UI cd web && npm ci @@ -238,9 +265,6 @@ ci--meta-debug: python -V node --version -ci-pylint: ci--meta-debug - pylint $(PY_SOURCES) - ci-black: ci--meta-debug black --check $(PY_SOURCES) @@ -250,14 +274,8 @@ ci-ruff: ci--meta-debug ci-codespell: ci--meta-debug codespell $(CODESPELL_ARGS) -s -ci-isort: ci--meta-debug - isort --check $(PY_SOURCES) - ci-bandit: ci--meta-debug bandit -r $(PY_SOURCES) -ci-pyright: ci--meta-debug - ./web/node_modules/.bin/pyright $(PY_SOURCES) - ci-pending-migrations: ci--meta-debug ak makemigrations --check diff --git a/README.md b/README.md index 8f5f9c2a95..e87db3f214 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,10 @@ For bigger setups, there is a Helm Chart [here](https://github.com/goauthentik/h ## Screenshots -| Light | Dark | -| ------------------------------------------------------ | ----------------------------------------------------- | -| ![](https://goauthentik.io/img/screen_apps_light.jpg) | ![](https://goauthentik.io/img/screen_apps_dark.jpg) | -| ![](https://goauthentik.io/img/screen_admin_light.jpg) | ![](https://goauthentik.io/img/screen_admin_dark.jpg) | +| Light | Dark | +| ----------------------------------------------------------- | ---------------------------------------------------------- | +| ![](https://docs.goauthentik.io/img/screen_apps_light.jpg) | ![](https://docs.goauthentik.io/img/screen_apps_dark.jpg) | +| ![](https://docs.goauthentik.io/img/screen_admin_light.jpg) | ![](https://docs.goauthentik.io/img/screen_admin_dark.jpg) | ## Development diff --git a/SECURITY.md b/SECURITY.md index 9bb674f232..4fefed8ce3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -18,10 +18,10 @@ Even if the issue is not a CVE, we still greatly appreciate your help in hardeni (.x being the latest patch release for each version) -| Version | Supported | -| --- | --- | -| 2023.6.x | ✅ | -| 2023.8.x | ✅ | +| Version | Supported | +| --------- | --------- | +| 2023.10.x | ✅ | +| 2024.2.x | ✅ | ## Reporting a Vulnerability @@ -31,12 +31,12 @@ To report a vulnerability, send an email to [security@goauthentik.io](mailto:se authentik reserves the right to reclassify CVSS as necessary. To determine severity, we will use the CVSS calculator from NVD (https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator). The calculated CVSS score will then be translated into one of the following categories: -| Score | Severity | -| --- | --- | -| 0.0 | None | -| 0.1 – 3.9 | Low | -| 4.0 – 6.9 | Medium | -| 7.0 – 8.9 | High | +| Score | Severity | +| ---------- | -------- | +| 0.0 | None | +| 0.1 – 3.9 | Low | +| 4.0 – 6.9 | Medium | +| 7.0 – 8.9 | High | | 9.0 – 10.0 | Critical | ## Disclosure process diff --git a/authentik/__init__.py b/authentik/__init__.py index 352d7580f9..468069e6e1 100644 --- a/authentik/__init__.py +++ b/authentik/__init__.py @@ -1,12 +1,12 @@ """authentik root module""" -from os import environ -from typing import Optional -__version__ = "2023.10.6" +from os import environ + +__version__ = "2024.4.2" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" -def get_build_hash(fallback: Optional[str] = None) -> str: +def get_build_hash(fallback: str | None = None) -> str: """Get build hash""" build_hash = environ.get(ENV_GIT_HASH_KEY, fallback if fallback else "") return fallback if build_hash == "" and fallback else build_hash diff --git a/authentik/admin/api/meta.py b/authentik/admin/api/meta.py index 52640b8c50..bdece26f5c 100644 --- a/authentik/admin/api/meta.py +++ b/authentik/admin/api/meta.py @@ -1,4 +1,5 @@ """Meta API""" + from drf_spectacular.utils import extend_schema from rest_framework.fields import CharField from rest_framework.permissions import IsAuthenticated diff --git a/authentik/admin/api/metrics.py b/authentik/admin/api/metrics.py index af32662b17..6929767ecf 100644 --- a/authentik/admin/api/metrics.py +++ b/authentik/admin/api/metrics.py @@ -1,4 +1,5 @@ """authentik administration metrics""" + from datetime import timedelta from django.db.models.functions import ExtractHour diff --git a/authentik/admin/api/system.py b/authentik/admin/api/system.py index 16637067a2..b0e7f074fd 100644 --- a/authentik/admin/api/system.py +++ b/authentik/admin/api/system.py @@ -1,17 +1,20 @@ """authentik administration overview""" + import platform from datetime import datetime +from ssl import OPENSSL_VERSION from sys import version as python_version from typing import TypedDict +from cryptography.hazmat.backends.openssl.backend import backend from django.utils.timezone import now from drf_spectacular.utils import extend_schema -from gunicorn import version_info as gunicorn_version from rest_framework.fields import SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response from rest_framework.views import APIView +from authentik import get_full_version from authentik.core.api.utils import PassiveSerializer from authentik.lib.config import CONFIG from authentik.lib.utils.reflection import get_env @@ -24,11 +27,13 @@ class RuntimeDict(TypedDict): """Runtime information""" python_version: str - gunicorn_version: str environment: str architecture: str platform: str uname: str + openssl_version: str + openssl_fips_mode: bool + authentik_version: str class SystemInfoSerializer(PassiveSerializer): @@ -63,11 +68,13 @@ class SystemInfoSerializer(PassiveSerializer): def get_runtime(self, request: Request) -> RuntimeDict: """Get versions""" return { - "python_version": python_version, - "gunicorn_version": ".".join(str(x) for x in gunicorn_version), - "environment": get_env(), "architecture": platform.machine(), + "authentik_version": get_full_version(), + "environment": get_env(), + "openssl_fips_enabled": backend._fips_enabled, + "openssl_version": OPENSSL_VERSION, "platform": platform.platform(), + "python_version": python_version, "uname": " ".join(platform.uname()), } diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py index e0cc2c5b48..3985bef9b0 100644 --- a/authentik/admin/api/version.py +++ b/authentik/admin/api/version.py @@ -1,4 +1,5 @@ """authentik administration overview""" + from django.core.cache import cache from drf_spectacular.utils import extend_schema from packaging.version import parse @@ -9,7 +10,7 @@ from rest_framework.response import Response from rest_framework.views import APIView from authentik import __version__, get_build_hash -from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version +from authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version from authentik.core.api.utils import PassiveSerializer @@ -18,6 +19,7 @@ class VersionSerializer(PassiveSerializer): version_current = SerializerMethodField() version_latest = SerializerMethodField() + version_latest_valid = SerializerMethodField() build_hash = SerializerMethodField() outdated = SerializerMethodField() @@ -37,6 +39,10 @@ class VersionSerializer(PassiveSerializer): return __version__ return version_in_cache + def get_version_latest_valid(self, _) -> bool: + """Check if latest version is valid""" + return cache.get(VERSION_CACHE_KEY) != VERSION_NULL + def get_outdated(self, instance) -> bool: """Check if we're running the latest version""" return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance)) diff --git a/authentik/admin/api/workers.py b/authentik/admin/api/workers.py index 3b5da05948..86578a50eb 100644 --- a/authentik/admin/api/workers.py +++ b/authentik/admin/api/workers.py @@ -1,4 +1,5 @@ """authentik administration overview""" + from django.conf import settings from drf_spectacular.utils import extend_schema, inline_serializer from rest_framework.fields import IntegerField diff --git a/authentik/admin/apps.py b/authentik/admin/apps.py index 6cc7ba8655..d151a6f953 100644 --- a/authentik/admin/apps.py +++ b/authentik/admin/apps.py @@ -1,4 +1,5 @@ """authentik admin app config""" + from prometheus_client import Gauge, Info from authentik.blueprints.apps import ManagedAppConfig @@ -14,7 +15,3 @@ class AuthentikAdminConfig(ManagedAppConfig): label = "authentik_admin" verbose_name = "authentik Admin" default = True - - def reconcile_global_load_admin_signals(self): - """Load admin signals""" - self.import_module("authentik.admin.signals") diff --git a/authentik/admin/settings.py b/authentik/admin/settings.py index 37b9d8bda1..7c5b561ff0 100644 --- a/authentik/admin/settings.py +++ b/authentik/admin/settings.py @@ -1,4 +1,5 @@ """authentik admin settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/admin/signals.py b/authentik/admin/signals.py index aa081724b5..6bd906972c 100644 --- a/authentik/admin/signals.py +++ b/authentik/admin/signals.py @@ -1,4 +1,5 @@ """admin signals""" + from django.dispatch import receiver from authentik.admin.apps import GAUGE_WORKERS diff --git a/authentik/admin/tasks.py b/authentik/admin/tasks.py index 6a75f51c91..8bafb3bef4 100644 --- a/authentik/admin/tasks.py +++ b/authentik/admin/tasks.py @@ -1,4 +1,5 @@ """authentik admin tasks""" + import re from django.core.cache import cache @@ -17,6 +18,7 @@ from authentik.lib.utils.http import get_http_session from authentik.root.celery import CELERY_APP LOGGER = get_logger() +VERSION_NULL = "0.0.0" VERSION_CACHE_KEY = "authentik_latest_version" VERSION_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours # Chop of the first ^ because we want to search the entire string @@ -54,7 +56,7 @@ def clear_update_notifications(): def update_latest_version(self: SystemTask): """Update latest version info""" if CONFIG.get_bool("disable_update_check"): - cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT) + cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT) self.set_status(TaskStatus.WARNING, "Version check disabled.") return try: @@ -81,7 +83,7 @@ def update_latest_version(self: SystemTask): event_dict["message"] = f"Changelog: {match.group()}" Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save() except (RequestException, IndexError) as exc: - cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT) + cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT) self.set_error(exc) diff --git a/authentik/admin/tests/test_api.py b/authentik/admin/tests/test_api.py index f7bd03ff5c..8d7d5eb44a 100644 --- a/authentik/admin/tests/test_api.py +++ b/authentik/admin/tests/test_api.py @@ -1,4 +1,5 @@ """test admin api""" + from json import loads from django.test import TestCase diff --git a/authentik/admin/tests/test_tasks.py b/authentik/admin/tests/test_tasks.py index b6720623e5..0ea3457f61 100644 --- a/authentik/admin/tests/test_tasks.py +++ b/authentik/admin/tests/test_tasks.py @@ -1,4 +1,5 @@ """test admin tasks""" + from django.core.cache import cache from django.test import TestCase from requests_mock import Mocker diff --git a/authentik/admin/urls.py b/authentik/admin/urls.py index 6ef21e93e9..2be8af5756 100644 --- a/authentik/admin/urls.py +++ b/authentik/admin/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from django.urls import path from authentik.admin.api.meta import AppsViewSet, ModelViewSet diff --git a/authentik/api/apps.py b/authentik/api/apps.py index 7b91d99a9e..8ae859a54d 100644 --- a/authentik/api/apps.py +++ b/authentik/api/apps.py @@ -10,26 +10,3 @@ class AuthentikAPIConfig(AppConfig): label = "authentik_api" mountpoint = "api/" verbose_name = "authentik API" - - def ready(self) -> None: - from drf_spectacular.extensions import OpenApiAuthenticationExtension - - from authentik.api.authentication import TokenAuthentication - - # Class is defined here as it needs to be created early enough that drf-spectacular will - # find it, but also won't cause any import issues - # pylint: disable=unused-variable - class TokenSchema(OpenApiAuthenticationExtension): - """Auth schema""" - - target_class = TokenAuthentication - name = "authentik" - - def get_security_definition(self, auto_schema): - """Auth schema""" - return { - "type": "apiKey", - "in": "header", - "name": "Authorization", - "scheme": "bearer", - } diff --git a/authentik/api/authentication.py b/authentik/api/authentication.py index 8aa402384f..ab4b67d731 100644 --- a/authentik/api/authentication.py +++ b/authentik/api/authentication.py @@ -1,8 +1,10 @@ """API Authentication""" + from hmac import compare_digest -from typing import Any, Optional +from typing import Any from django.conf import settings +from drf_spectacular.extensions import OpenApiAuthenticationExtension from rest_framework.authentication import BaseAuthentication, get_authorization_header from rest_framework.exceptions import AuthenticationFailed from rest_framework.request import Request @@ -16,7 +18,7 @@ from authentik.providers.oauth2.constants import SCOPE_AUTHENTIK_API LOGGER = get_logger() -def validate_auth(header: bytes) -> Optional[str]: +def validate_auth(header: bytes) -> str | None: """Validate that the header is in a correct format, returns type and credentials""" auth_credentials = header.decode().strip() @@ -31,7 +33,7 @@ def validate_auth(header: bytes) -> Optional[str]: return auth_credentials -def bearer_auth(raw_header: bytes) -> Optional[User]: +def bearer_auth(raw_header: bytes) -> User | None: """raw_header in the Format of `Bearer ....`""" user = auth_user_lookup(raw_header) if not user: @@ -41,7 +43,7 @@ def bearer_auth(raw_header: bytes) -> Optional[User]: return user -def auth_user_lookup(raw_header: bytes) -> Optional[User]: +def auth_user_lookup(raw_header: bytes) -> User | None: """raw_header in the Format of `Bearer ....`""" from authentik.providers.oauth2.models import AccessToken @@ -74,7 +76,7 @@ def auth_user_lookup(raw_header: bytes) -> Optional[User]: raise AuthenticationFailed("Token invalid/expired") -def token_secret_key(value: str) -> Optional[User]: +def token_secret_key(value: str) -> User | None: """Check if the token is the secret key and return the service account for the managed outpost""" from authentik.outposts.apps import MANAGED_OUTPOST @@ -101,3 +103,14 @@ class TokenAuthentication(BaseAuthentication): return None return (user, None) # pragma: no cover + + +class TokenSchema(OpenApiAuthenticationExtension): + """Auth schema""" + + target_class = TokenAuthentication + name = "authentik" + + def get_security_definition(self, auto_schema): + """Auth schema""" + return {"type": "http", "scheme": "bearer"} diff --git a/authentik/api/authorization.py b/authentik/api/authorization.py index e3ae48e5c6..a79cb1803f 100644 --- a/authentik/api/authorization.py +++ b/authentik/api/authorization.py @@ -1,4 +1,5 @@ """API Authorization""" + from django.conf import settings from django.db.models import Model from django.db.models.query import QuerySet diff --git a/authentik/api/pagination.py b/authentik/api/pagination.py index 402dbac9b7..a49a6811b0 100644 --- a/authentik/api/pagination.py +++ b/authentik/api/pagination.py @@ -1,4 +1,5 @@ """Pagination which includes total pages and current page""" + from rest_framework import pagination from rest_framework.response import Response diff --git a/authentik/api/schema.py b/authentik/api/schema.py index e70caaf3e1..f95d575db4 100644 --- a/authentik/api/schema.py +++ b/authentik/api/schema.py @@ -1,4 +1,5 @@ """Error Response schema, from https://github.com/axnsan12/drf-yasg/issues/224""" + from django.utils.translation import gettext_lazy as _ from drf_spectacular.generators import SchemaGenerator from drf_spectacular.plumbing import ( @@ -11,6 +12,7 @@ from drf_spectacular.settings import spectacular_settings from drf_spectacular.types import OpenApiTypes from rest_framework.settings import api_settings +from authentik.api.apps import AuthentikAPIConfig from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA @@ -100,3 +102,12 @@ def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): comp = result["components"]["schemas"][component] comp["additionalProperties"] = {} return result + + +def preprocess_schema_exclude_non_api(endpoints, **kwargs): + """Filter out all API Views which are not mounted under /api""" + return [ + (path, path_regex, method, callback) + for path, path_regex, method, callback in endpoints + if path.startswith("/" + AuthentikAPIConfig.mountpoint) + ] diff --git a/authentik/api/tests/test_auth.py b/authentik/api/tests/test_auth.py index c09bca5a32..f449b88b60 100644 --- a/authentik/api/tests/test_auth.py +++ b/authentik/api/tests/test_auth.py @@ -1,4 +1,5 @@ """Test API Authentication""" + import json from base64 import b64encode @@ -24,17 +25,17 @@ class TestAPIAuth(TestCase): def test_invalid_type(self): """Test invalid type""" with self.assertRaises(AuthenticationFailed): - bearer_auth("foo bar".encode()) + bearer_auth(b"foo bar") def test_invalid_empty(self): """Test invalid type""" - self.assertIsNone(bearer_auth("Bearer ".encode())) - self.assertIsNone(bearer_auth("".encode())) + self.assertIsNone(bearer_auth(b"Bearer ")) + self.assertIsNone(bearer_auth(b"")) def test_invalid_no_token(self): """Test invalid with no token""" with self.assertRaises(AuthenticationFailed): - auth = b64encode(":abc".encode()).decode() + auth = b64encode(b":abc").decode() self.assertIsNone(bearer_auth(f"Basic :{auth}".encode())) def test_bearer_valid(self): diff --git a/authentik/api/tests/test_config.py b/authentik/api/tests/test_config.py index 6f6f60f319..afee3fa177 100644 --- a/authentik/api/tests/test_config.py +++ b/authentik/api/tests/test_config.py @@ -1,4 +1,5 @@ """Test config API""" + from json import loads from django.urls import reverse diff --git a/authentik/api/tests/test_decorators.py b/authentik/api/tests/test_decorators.py deleted file mode 100644 index 2370683564..0000000000 --- a/authentik/api/tests/test_decorators.py +++ /dev/null @@ -1,34 +0,0 @@ -"""test decorators api""" -from django.urls import reverse -from guardian.shortcuts import assign_perm -from rest_framework.test import APITestCase - -from authentik.core.models import Application, User -from authentik.lib.generators import generate_id - - -class TestAPIDecorators(APITestCase): - """test decorators api""" - - def setUp(self) -> None: - super().setUp() - self.user = User.objects.create(username="test-user") - - def test_obj_perm_denied(self): - """Test object perm denied""" - self.client.force_login(self.user) - app = Application.objects.create(name=generate_id(), slug=generate_id()) - response = self.client.get( - reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) - ) - self.assertEqual(response.status_code, 403) - - def test_other_perm_denied(self): - """Test other perm denied""" - self.client.force_login(self.user) - app = Application.objects.create(name=generate_id(), slug=generate_id()) - assign_perm("authentik_core.view_application", self.user, app) - response = self.client.get( - reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) - ) - self.assertEqual(response.status_code, 403) diff --git a/authentik/api/tests/test_schema.py b/authentik/api/tests/test_schema.py index d86597d964..e33a31f9df 100644 --- a/authentik/api/tests/test_schema.py +++ b/authentik/api/tests/test_schema.py @@ -1,4 +1,5 @@ """Schema generation tests""" + from django.urls import reverse from rest_framework.test import APITestCase from yaml import safe_load diff --git a/authentik/api/tests/test_viewsets.py b/authentik/api/tests/test_viewsets.py index ac3d7da62d..da16e801c9 100644 --- a/authentik/api/tests/test_viewsets.py +++ b/authentik/api/tests/test_viewsets.py @@ -1,5 +1,6 @@ """authentik API Modelviewset tests""" -from typing import Callable + +from collections.abc import Callable from django.test import TestCase from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet @@ -25,6 +26,6 @@ def viewset_tester_factory(test_viewset: type[ModelViewSet]) -> Callable: for _, viewset, _ in router.registry: - if not issubclass(viewset, (ModelViewSet, ReadOnlyModelViewSet)): + if not issubclass(viewset, ModelViewSet | ReadOnlyModelViewSet): continue setattr(TestModelViewSets, f"test_viewset_{viewset.__name__}", viewset_tester_factory(viewset)) diff --git a/authentik/api/urls.py b/authentik/api/urls.py index 461fe5b94a..43b8827719 100644 --- a/authentik/api/urls.py +++ b/authentik/api/urls.py @@ -1,4 +1,5 @@ """authentik api urls""" + from django.urls import include, path from authentik.api.v3.urls import urlpatterns as v3_urls diff --git a/authentik/api/v3/config.py b/authentik/api/v3/config.py index 49493234bc..151796afc4 100644 --- a/authentik/api/v3/config.py +++ b/authentik/api/v3/config.py @@ -1,4 +1,5 @@ """core Configs API""" + from pathlib import Path from django.conf import settings @@ -67,7 +68,11 @@ class ConfigView(APIView): """Get all capabilities this server instance supports""" caps = [] deb_test = settings.DEBUG or settings.TEST - if Path(settings.MEDIA_ROOT).is_mount() or deb_test: + if ( + CONFIG.get("storage.media.backend", "file") == "s3" + or Path(settings.STORAGES["default"]["OPTIONS"]["location"]).is_mount() + or deb_test + ): caps.append(Capabilities.CAN_SAVE_MEDIA) for processor in get_context_processors(): if cap := processor.capability(): diff --git a/authentik/api/v3/urls.py b/authentik/api/v3/urls.py index a7e610efac..735197dbd1 100644 --- a/authentik/api/v3/urls.py +++ b/authentik/api/v3/urls.py @@ -1,4 +1,5 @@ """api v3 urls""" + from importlib import import_module from django.urls import path @@ -32,7 +33,7 @@ for _authentik_app in get_apps(): app_name=_authentik_app.name, ) continue - urls: list = getattr(api_urls, "api_urlpatterns") + urls: list = api_urls.api_urlpatterns for url in urls: if isinstance(url, URLPattern): _other_urls.append(url) diff --git a/authentik/api/views.py b/authentik/api/views.py index 36193ed170..1e3f9eb242 100644 --- a/authentik/api/views.py +++ b/authentik/api/views.py @@ -1,4 +1,5 @@ """General API Views""" + from typing import Any from django.urls import reverse diff --git a/authentik/blueprints/api.py b/authentik/blueprints/api.py index 7abf488dae..993121e705 100644 --- a/authentik/blueprints/api.py +++ b/authentik/blueprints/api.py @@ -1,4 +1,5 @@ """Serializer mixin for managed models""" + from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema, inline_serializer from rest_framework.decorators import action @@ -9,13 +10,13 @@ from rest_framework.response import Response from rest_framework.serializers import ListSerializer, ModelSerializer from rest_framework.viewsets import ModelViewSet -from authentik.api.decorators import permission_required from authentik.blueprints.models import BlueprintInstance from authentik.blueprints.v1.importer import Importer from authentik.blueprints.v1.oci import OCI_PREFIX from authentik.blueprints.v1.tasks import apply_blueprint, blueprints_find_dict from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import JSONDictField, PassiveSerializer +from authentik.rbac.decorators import permission_required class ManagedSerializer: @@ -51,7 +52,9 @@ class BlueprintInstanceSerializer(ModelSerializer): valid, logs = Importer.from_string(content, context).validate() if not valid: text_logs = "\n".join([x["event"] for x in logs]) - raise ValidationError(_("Failed to validate blueprint: %(logs)s" % {"logs": text_logs})) + raise ValidationError( + _("Failed to validate blueprint: {logs}".format_map({"logs": text_logs})) + ) return content def validate(self, attrs: dict) -> dict: diff --git a/authentik/blueprints/apps.py b/authentik/blueprints/apps.py index 0d31f42335..eeef482764 100644 --- a/authentik/blueprints/apps.py +++ b/authentik/blueprints/apps.py @@ -1,5 +1,6 @@ """authentik Blueprints app""" +from collections.abc import Callable from importlib import import_module from inspect import ismethod @@ -7,24 +8,46 @@ from django.apps import AppConfig from django.db import DatabaseError, InternalError, ProgrammingError from structlog.stdlib import BoundLogger, get_logger +from authentik.root.signals import startup + class ManagedAppConfig(AppConfig): """Basic reconciliation logic for apps""" logger: BoundLogger - RECONCILE_GLOBAL_PREFIX: str = "reconcile_global_" - RECONCILE_TENANT_PREFIX: str = "reconcile_tenant_" + RECONCILE_GLOBAL_CATEGORY: str = "global" + RECONCILE_TENANT_CATEGORY: str = "tenant" def __init__(self, app_name: str, *args, **kwargs) -> None: super().__init__(app_name, *args, **kwargs) self.logger = get_logger().bind(app_name=app_name) def ready(self) -> None: - self.reconcile_global() - self.reconcile_tenant() + self.import_related() + startup.connect(self._on_startup_callback, dispatch_uid=self.label) return super().ready() + def _on_startup_callback(self, sender, **_): + self._reconcile_global() + self._reconcile_tenant() + + def import_related(self): + """Automatically import related modules which rely on just being imported + to register themselves (mainly django signals and celery tasks)""" + + def import_relative(rel_module: str): + try: + module_name = f"{self.name}.{rel_module}" + import_module(module_name) + self.logger.info("Imported related module", module=module_name) + except ModuleNotFoundError: + pass + + import_relative("checks") + import_relative("tasks") + import_relative("signals") + def import_module(self, path: str): """Load module""" import_module(path) @@ -34,7 +57,8 @@ class ManagedAppConfig(AppConfig): meth = getattr(self, meth_name) if not ismethod(meth): continue - if not meth_name.startswith(prefix): + category = getattr(meth, "_authentik_managed_reconcile", None) + if category != prefix: continue name = meth_name.replace(prefix, "") try: @@ -44,7 +68,19 @@ class ManagedAppConfig(AppConfig): except (DatabaseError, ProgrammingError, InternalError) as exc: self.logger.warning("Failed to run reconcile", name=name, exc=exc) - def reconcile_tenant(self) -> None: + @staticmethod + def reconcile_tenant(func: Callable): + """Mark a function to be called on startup (for each tenant)""" + func._authentik_managed_reconcile = ManagedAppConfig.RECONCILE_TENANT_CATEGORY + return func + + @staticmethod + def reconcile_global(func: Callable): + """Mark a function to be called on startup (globally)""" + func._authentik_managed_reconcile = ManagedAppConfig.RECONCILE_GLOBAL_CATEGORY + return func + + def _reconcile_tenant(self) -> None: """reconcile ourselves for tenanted methods""" from authentik.tenants.models import Tenant @@ -55,9 +91,9 @@ class ManagedAppConfig(AppConfig): return for tenant in tenants: with tenant: - self._reconcile(self.RECONCILE_TENANT_PREFIX) + self._reconcile(self.RECONCILE_TENANT_CATEGORY) - def reconcile_global(self) -> None: + def _reconcile_global(self) -> None: """ reconcile ourselves for global methods. Used for signals, tasks, etc. Database queries should not be made in here. @@ -65,7 +101,7 @@ class ManagedAppConfig(AppConfig): from django_tenants.utils import get_public_schema_name, schema_context with schema_context(get_public_schema_name()): - self._reconcile(self.RECONCILE_GLOBAL_PREFIX) + self._reconcile(self.RECONCILE_GLOBAL_CATEGORY) class AuthentikBlueprintsConfig(ManagedAppConfig): @@ -76,11 +112,13 @@ class AuthentikBlueprintsConfig(ManagedAppConfig): verbose_name = "authentik Blueprints" default = True - def reconcile_global_load_blueprints_v1_tasks(self): + @ManagedAppConfig.reconcile_global + def load_blueprints_v1_tasks(self): """Load v1 tasks""" self.import_module("authentik.blueprints.v1.tasks") - def reconcile_tenant_blueprints_discovery(self): + @ManagedAppConfig.reconcile_tenant + def blueprints_discovery(self): """Run blueprint discovery""" from authentik.blueprints.v1.tasks import blueprints_discovery, clear_failed_blueprints diff --git a/authentik/blueprints/management/commands/apply_blueprint.py b/authentik/blueprints/management/commands/apply_blueprint.py index adc76c207c..698ff4b5c0 100644 --- a/authentik/blueprints/management/commands/apply_blueprint.py +++ b/authentik/blueprints/management/commands/apply_blueprint.py @@ -1,4 +1,5 @@ """Apply blueprint from commandline""" + from sys import exit as sys_exit from django.core.management.base import BaseCommand, no_translations diff --git a/authentik/blueprints/management/commands/export_blueprint.py b/authentik/blueprints/management/commands/export_blueprint.py index a7a0ccdf83..c8371595e2 100644 --- a/authentik/blueprints/management/commands/export_blueprint.py +++ b/authentik/blueprints/management/commands/export_blueprint.py @@ -1,4 +1,5 @@ """Export blueprint of current authentik install""" + from django.core.management.base import no_translations from structlog.stdlib import get_logger diff --git a/authentik/blueprints/management/commands/make_blueprint_schema.py b/authentik/blueprints/management/commands/make_blueprint_schema.py index f75b6ab0bc..6e482665d5 100644 --- a/authentik/blueprints/management/commands/make_blueprint_schema.py +++ b/authentik/blueprints/management/commands/make_blueprint_schema.py @@ -1,14 +1,17 @@ """Generate JSON Schema for blueprints""" + from json import dumps from typing import Any from django.core.management.base import BaseCommand, no_translations -from django.db.models import Model -from drf_jsonschema_serializer.convert import field_to_converter +from django.db.models import Model, fields +from drf_jsonschema_serializer.convert import converter, field_to_converter from rest_framework.fields import Field, JSONField, UUIDField +from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.serializers import Serializer from structlog.stdlib import get_logger +from authentik import __version__ from authentik.blueprints.v1.common import BlueprintEntryDesiredState from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, is_model_allowed from authentik.blueprints.v1.meta.registry import BaseMetaModel, registry @@ -17,6 +20,23 @@ from authentik.lib.models import SerializerModel LOGGER = get_logger() +@converter +class PrimaryKeyRelatedFieldConverter: + """Custom primary key field converter which is aware of non-integer based PKs + + This is not an exhaustive fix for other non-int PKs, however in authentik we either + use UUIDs or ints""" + + field_class = PrimaryKeyRelatedField + + def convert(self, field: PrimaryKeyRelatedField): + model: Model = field.queryset.model + pk_field = model._meta.pk + if isinstance(pk_field, fields.UUIDField): + return {"type": "string", "format": "uuid"} + return {"type": "integer"} + + class Command(BaseCommand): """Generate JSON Schema for blueprints""" @@ -28,7 +48,7 @@ class Command(BaseCommand): "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://goauthentik.io/blueprints/schema.json", "type": "object", - "title": "authentik Blueprint schema", + "title": f"authentik {__version__} Blueprint schema", "required": ["version", "entries"], "properties": { "version": { diff --git a/authentik/blueprints/models.py b/authentik/blueprints/models.py index 2551beacc2..a3abcba59f 100644 --- a/authentik/blueprints/models.py +++ b/authentik/blueprints/models.py @@ -1,4 +1,5 @@ """blueprint models""" + from pathlib import Path from uuid import uuid4 @@ -70,6 +71,19 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): enabled = models.BooleanField(default=True) managed_models = ArrayField(models.TextField(), default=list) + class Meta: + verbose_name = _("Blueprint Instance") + verbose_name_plural = _("Blueprint Instances") + unique_together = ( + ( + "name", + "path", + ), + ) + + def __str__(self) -> str: + return f"Blueprint Instance {self.name}" + def retrieve_oci(self) -> str: """Get blueprint from an OCI registry""" client = BlueprintOCIClient(self.path.replace(OCI_PREFIX, "https://")) @@ -88,7 +102,7 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): raise BlueprintRetrievalFailed("Invalid blueprint path") with full_path.open("r", encoding="utf-8") as _file: return _file.read() - except (IOError, OSError) as exc: + except OSError as exc: raise BlueprintRetrievalFailed(exc) from exc def retrieve(self) -> str: @@ -104,16 +118,3 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): from authentik.blueprints.api import BlueprintInstanceSerializer return BlueprintInstanceSerializer - - def __str__(self) -> str: - return f"Blueprint Instance {self.name}" - - class Meta: - verbose_name = _("Blueprint Instance") - verbose_name_plural = _("Blueprint Instances") - unique_together = ( - ( - "name", - "path", - ), - ) diff --git a/authentik/blueprints/settings.py b/authentik/blueprints/settings.py index c9ce11057c..da0029d678 100644 --- a/authentik/blueprints/settings.py +++ b/authentik/blueprints/settings.py @@ -1,4 +1,5 @@ """blueprint Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/blueprints/tests/__init__.py b/authentik/blueprints/tests/__init__.py index e407db13a8..69ded34098 100644 --- a/authentik/blueprints/tests/__init__.py +++ b/authentik/blueprints/tests/__init__.py @@ -1,6 +1,7 @@ """Blueprint helpers""" + +from collections.abc import Callable from functools import wraps -from typing import Callable from django.apps import apps @@ -38,7 +39,7 @@ def reconcile_app(app_name: str): def wrapper(*args, **kwargs): config = apps.get_app_config(app_name) if isinstance(config, ManagedAppConfig): - config.ready() + config._on_startup_callback(None) return func(*args, **kwargs) return wrapper diff --git a/authentik/blueprints/tests/test_models.py b/authentik/blueprints/tests/test_models.py index 2c04b64ef0..a2ceac828b 100644 --- a/authentik/blueprints/tests/test_models.py +++ b/authentik/blueprints/tests/test_models.py @@ -1,4 +1,5 @@ """authentik managed models tests""" + from django.test import TestCase from authentik.blueprints.models import BlueprintInstance, BlueprintRetrievalFailed diff --git a/authentik/blueprints/tests/test_oci.py b/authentik/blueprints/tests/test_oci.py index 963e3797ff..71b0d34807 100644 --- a/authentik/blueprints/tests/test_oci.py +++ b/authentik/blueprints/tests/test_oci.py @@ -1,4 +1,5 @@ """Test blueprints OCI""" + from django.test import TransactionTestCase from requests_mock import Mocker diff --git a/authentik/blueprints/tests/test_packaged.py b/authentik/blueprints/tests/test_packaged.py index e94c750172..443173bac2 100644 --- a/authentik/blueprints/tests/test_packaged.py +++ b/authentik/blueprints/tests/test_packaged.py @@ -1,6 +1,7 @@ """test packaged blueprints""" + +from collections.abc import Callable from pathlib import Path -from typing import Callable from django.test import TransactionTestCase diff --git a/authentik/blueprints/tests/test_serializer_models.py b/authentik/blueprints/tests/test_serializer_models.py index 78dc553483..a3ae6005aa 100644 --- a/authentik/blueprints/tests/test_serializer_models.py +++ b/authentik/blueprints/tests/test_serializer_models.py @@ -1,5 +1,6 @@ """authentik managed models tests""" -from typing import Callable, Type + +from collections.abc import Callable from django.apps import apps from django.test import TestCase @@ -13,7 +14,7 @@ class TestModels(TestCase): """Test Models""" -def serializer_tester_factory(test_model: Type[SerializerModel]) -> Callable: +def serializer_tester_factory(test_model: type[SerializerModel]) -> Callable: """Test serializer""" def tester(self: TestModels): diff --git a/authentik/blueprints/tests/test_v1.py b/authentik/blueprints/tests/test_v1.py index f7f53f780d..5f85e69477 100644 --- a/authentik/blueprints/tests/test_v1.py +++ b/authentik/blueprints/tests/test_v1.py @@ -1,4 +1,5 @@ """Test blueprints v1""" + from os import environ from django.test import TransactionTestCase diff --git a/authentik/blueprints/tests/test_v1_api.py b/authentik/blueprints/tests/test_v1_api.py index 6ee4bd7f6a..681260d690 100644 --- a/authentik/blueprints/tests/test_v1_api.py +++ b/authentik/blueprints/tests/test_v1_api.py @@ -1,4 +1,5 @@ """Test blueprints v1 api""" + from json import loads from tempfile import NamedTemporaryFile, mkdtemp diff --git a/authentik/blueprints/tests/test_v1_conditional_fields.py b/authentik/blueprints/tests/test_v1_conditional_fields.py index 4b7cb45915..d260e9599b 100644 --- a/authentik/blueprints/tests/test_v1_conditional_fields.py +++ b/authentik/blueprints/tests/test_v1_conditional_fields.py @@ -1,4 +1,5 @@ """Test blueprints v1""" + from django.test import TransactionTestCase from authentik.blueprints.v1.importer import Importer diff --git a/authentik/blueprints/tests/test_v1_conditions.py b/authentik/blueprints/tests/test_v1_conditions.py index dd633a22a6..8dd79563e1 100644 --- a/authentik/blueprints/tests/test_v1_conditions.py +++ b/authentik/blueprints/tests/test_v1_conditions.py @@ -1,4 +1,5 @@ """Test blueprints v1""" + from django.test import TransactionTestCase from authentik.blueprints.v1.importer import Importer diff --git a/authentik/blueprints/tests/test_v1_state.py b/authentik/blueprints/tests/test_v1_state.py index ad12c239c8..96a2d0f602 100644 --- a/authentik/blueprints/tests/test_v1_state.py +++ b/authentik/blueprints/tests/test_v1_state.py @@ -1,4 +1,5 @@ """Test blueprints v1""" + from django.test import TransactionTestCase from authentik.blueprints.v1.importer import Importer diff --git a/authentik/blueprints/tests/test_v1_tasks.py b/authentik/blueprints/tests/test_v1_tasks.py index 913431d66b..b1d201419d 100644 --- a/authentik/blueprints/tests/test_v1_tasks.py +++ b/authentik/blueprints/tests/test_v1_tasks.py @@ -1,4 +1,5 @@ """Test blueprints v1 tasks""" + from hashlib import sha512 from tempfile import NamedTemporaryFile, mkdtemp @@ -53,7 +54,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): file.seek(0) file_hash = sha512(file.read().encode()).hexdigest() file.flush() - blueprints_discovery() # pylint: disable=no-value-for-parameter + blueprints_discovery() instance = BlueprintInstance.objects.filter(name=blueprint_id).first() self.assertEqual(instance.last_applied_hash, file_hash) self.assertEqual( @@ -81,7 +82,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): ) ) file.flush() - blueprints_discovery() # pylint: disable=no-value-for-parameter + blueprints_discovery() blueprint = BlueprintInstance.objects.filter(name="foo").first() self.assertEqual( blueprint.last_applied_hash, @@ -106,7 +107,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): ) ) file.flush() - blueprints_discovery() # pylint: disable=no-value-for-parameter + blueprints_discovery() blueprint.refresh_from_db() self.assertEqual( blueprint.last_applied_hash, @@ -148,7 +149,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): instance.status, BlueprintInstanceStatus.UNKNOWN, ) - apply_blueprint(instance.pk) # pylint: disable=no-value-for-parameter + apply_blueprint(instance.pk) instance.refresh_from_db() self.assertEqual(instance.last_applied_hash, "") self.assertEqual( diff --git a/authentik/blueprints/urls.py b/authentik/blueprints/urls.py index 7f18c0094c..bea95598ea 100644 --- a/authentik/blueprints/urls.py +++ b/authentik/blueprints/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.blueprints.api import BlueprintInstanceViewSet api_urlpatterns = [ diff --git a/authentik/blueprints/v1/common.py b/authentik/blueprints/v1/common.py index 997fecc6f8..21b923f2e7 100644 --- a/authentik/blueprints/v1/common.py +++ b/authentik/blueprints/v1/common.py @@ -1,12 +1,14 @@ """transfer common classes""" + from collections import OrderedDict +from collections.abc import Iterable, Mapping from copy import copy from dataclasses import asdict, dataclass, field, is_dataclass from enum import Enum from functools import reduce from operator import ixor from os import getenv -from typing import Any, Iterable, Literal, Mapping, Optional, Union +from typing import Any, Literal, Union from uuid import UUID from deepmerge import always_merger @@ -44,7 +46,7 @@ def get_attrs(obj: SerializerModel) -> dict[str, Any]: class BlueprintEntryState: """State of a single instance""" - instance: Optional[Model] = None + instance: Model | None = None class BlueprintEntryDesiredState(Enum): @@ -66,14 +68,14 @@ class BlueprintEntry: ) conditions: list[Any] = field(default_factory=list) identifiers: dict[str, Any] = field(default_factory=dict) - attrs: Optional[dict[str, Any]] = field(default_factory=dict) + attrs: dict[str, Any] | None = field(default_factory=dict) - id: Optional[str] = None + id: str | None = None _state: BlueprintEntryState = field(default_factory=BlueprintEntryState) def __post_init__(self, *args, **kwargs) -> None: - self.__tag_contexts: list["YAMLTagContext"] = [] + self.__tag_contexts: list[YAMLTagContext] = [] @staticmethod def from_model(model: SerializerModel, *extra_identifier_names: str) -> "BlueprintEntry": @@ -91,10 +93,10 @@ class BlueprintEntry: attrs=all_attrs, ) - def _get_tag_context( + def get_tag_context( self, depth: int = 0, - context_tag_type: Optional[type["YAMLTagContext"] | tuple["YAMLTagContext", ...]] = None, + context_tag_type: type["YAMLTagContext"] | tuple["YAMLTagContext", ...] | None = None, ) -> "YAMLTagContext": """Get a YAMLTagContext object located at a certain depth in the tag tree""" if depth < 0: @@ -107,8 +109,8 @@ class BlueprintEntry: try: return contexts[-(depth + 1)] - except IndexError: - raise ValueError(f"invalid depth: {depth}. Max depth: {len(contexts) - 1}") + except IndexError as exc: + raise ValueError(f"invalid depth: {depth}. Max depth: {len(contexts) - 1}") from exc def tag_resolver(self, value: Any, blueprint: "Blueprint") -> Any: """Check if we have any special tags that need handling""" @@ -169,7 +171,7 @@ class Blueprint: entries: list[BlueprintEntry] = field(default_factory=list) context: dict = field(default_factory=dict) - metadata: Optional[BlueprintMetadata] = field(default=None) + metadata: BlueprintMetadata | None = field(default=None) class YAMLTag: @@ -217,7 +219,7 @@ class Env(YAMLTag): """Lookup environment variable with optional default""" key: str - default: Optional[Any] + default: Any | None def __init__(self, loader: "BlueprintLoader", node: ScalarNode | SequenceNode) -> None: super().__init__() @@ -236,7 +238,7 @@ class Context(YAMLTag): """Lookup key from instance context""" key: str - default: Optional[Any] + default: Any | None def __init__(self, loader: "BlueprintLoader", node: ScalarNode | SequenceNode) -> None: super().__init__() @@ -280,7 +282,7 @@ class Format(YAMLTag): try: return self.format_string % tuple(args) except TypeError as exc: - raise EntryInvalidError.from_entry(exc, entry) + raise EntryInvalidError.from_entry(exc, entry) from exc class Find(YAMLTag): @@ -365,7 +367,7 @@ class Condition(YAMLTag): comparator = self._COMPARATORS[self.mode.upper()] return comparator(tuple(bool(x) for x in args)) except (TypeError, KeyError) as exc: - raise EntryInvalidError.from_entry(exc, entry) + raise EntryInvalidError.from_entry(exc, entry) from exc class If(YAMLTag): @@ -397,7 +399,7 @@ class If(YAMLTag): blueprint, ) except TypeError as exc: - raise EntryInvalidError.from_entry(exc, entry) + raise EntryInvalidError.from_entry(exc, entry) from exc class Enumerate(YAMLTag, YAMLTagContext): @@ -411,9 +413,7 @@ class Enumerate(YAMLTag, YAMLTagContext): "SEQ": (list, lambda a, b: [*a, b]), "MAP": ( dict, - lambda a, b: always_merger.merge( - a, {b[0]: b[1]} if isinstance(b, (tuple, list)) else b - ), + lambda a, b: always_merger.merge(a, {b[0]: b[1]} if isinstance(b, tuple | list) else b), ), } @@ -455,7 +455,7 @@ class Enumerate(YAMLTag, YAMLTagContext): try: output_class, add_fn = self._OUTPUT_BODIES[self.output_body.upper()] except KeyError as exc: - raise EntryInvalidError.from_entry(exc, entry) + raise EntryInvalidError.from_entry(exc, entry) from exc result = output_class() @@ -483,13 +483,13 @@ class EnumeratedItem(YAMLTag): _SUPPORTED_CONTEXT_TAGS = (Enumerate,) - def __init__(self, loader: "BlueprintLoader", node: ScalarNode) -> None: + def __init__(self, _loader: "BlueprintLoader", node: ScalarNode) -> None: super().__init__() self.depth = int(node.value) def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any: try: - context_tag: Enumerate = entry._get_tag_context( + context_tag: Enumerate = entry.get_tag_context( depth=self.depth, context_tag_type=EnumeratedItem._SUPPORTED_CONTEXT_TAGS, ) @@ -499,9 +499,11 @@ class EnumeratedItem(YAMLTag): f"{self.__class__.__name__} tags are only usable " f"inside an {Enumerate.__name__} tag", entry, - ) + ) from exc - raise EntryInvalidError.from_entry(f"{self.__class__.__name__} tag: {exc}", entry) + raise EntryInvalidError.from_entry( + f"{self.__class__.__name__} tag: {exc}", entry + ) from exc return context_tag.get_context(entry, blueprint) @@ -514,8 +516,8 @@ class Index(EnumeratedItem): try: return context[0] - except IndexError: # pragma: no cover - raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry) + except IndexError as exc: # pragma: no cover + raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry) from exc class Value(EnumeratedItem): @@ -526,8 +528,8 @@ class Value(EnumeratedItem): try: return context[1] - except IndexError: # pragma: no cover - raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry) + except IndexError as exc: # pragma: no cover + raise EntryInvalidError.from_entry(f"Empty/invalid context: {context}", entry) from exc class BlueprintDumper(SafeDumper): @@ -554,7 +556,11 @@ class BlueprintDumper(SafeDumper): def factory(items): final_dict = dict(items) + # Remove internal state variables final_dict.pop("_state", None) + # Future-proof to only remove the ID if we don't set a value + if "id" in final_dict and final_dict.get("id") is None: + final_dict.pop("id") return final_dict data = asdict(data, dict_factory=factory) @@ -581,13 +587,13 @@ class BlueprintLoader(SafeLoader): class EntryInvalidError(SentryIgnoredException): """Error raised when an entry is invalid""" - entry_model: Optional[str] - entry_id: Optional[str] - validation_error: Optional[ValidationError] - serializer: Optional[Serializer] = None + entry_model: str | None + entry_id: str | None + validation_error: ValidationError | None + serializer: Serializer | None = None def __init__( - self, *args: object, validation_error: Optional[ValidationError] = None, **kwargs + self, *args: object, validation_error: ValidationError | None = None, **kwargs ) -> None: super().__init__(*args) self.entry_model = None diff --git a/authentik/blueprints/v1/exporter.py b/authentik/blueprints/v1/exporter.py index b3f6ca0422..89ed20be04 100644 --- a/authentik/blueprints/v1/exporter.py +++ b/authentik/blueprints/v1/exporter.py @@ -1,5 +1,6 @@ """Blueprint exporter""" -from typing import Iterable + +from collections.abc import Iterable from uuid import UUID from django.apps import apps @@ -7,7 +8,6 @@ from django.contrib.auth import get_user_model from django.db.models import Model, Q, QuerySet from django.utils.timezone import now from django.utils.translation import gettext as _ -from guardian.shortcuts import get_anonymous_user from yaml import dump from authentik.blueprints.v1.common import ( @@ -48,7 +48,7 @@ class Exporter: """Return a queryset for `model`. Can be used to filter some objects on some models""" if model == get_user_model(): - return model.objects.exclude(pk=get_anonymous_user().pk) + return model.objects.exclude_anonymous() return model.objects.all() def _pre_export(self, blueprint: Blueprint): @@ -59,7 +59,7 @@ class Exporter: blueprint = Blueprint() self._pre_export(blueprint) blueprint.metadata = BlueprintMetadata( - name=_("authentik Export - %(date)s" % {"date": str(now())}), + name=_("authentik Export - {date}".format_map({"date": str(now())})), labels={ LABEL_AUTHENTIK_GENERATED: "true", }, @@ -74,7 +74,7 @@ class Exporter: class FlowExporter(Exporter): - """Exporter customised to only return objects related to `flow`""" + """Exporter customized to only return objects related to `flow`""" flow: Flow with_policies: bool diff --git a/authentik/blueprints/v1/importer.py b/authentik/blueprints/v1/importer.py index 6a648d06a4..7ea645c467 100644 --- a/authentik/blueprints/v1/importer.py +++ b/authentik/blueprints/v1/importer.py @@ -1,7 +1,8 @@ """Blueprint importer""" + from contextlib import contextmanager from copy import deepcopy -from typing import Any, Optional +from typing import Any from dacite.config import Config from dacite.core import from_dict @@ -18,8 +19,6 @@ from guardian.models import UserObjectPermission from rest_framework.exceptions import ValidationError from rest_framework.serializers import BaseSerializer, Serializer from structlog.stdlib import BoundLogger, get_logger -from structlog.testing import capture_logs -from structlog.types import EventDict from yaml import load from authentik.blueprints.v1.common import ( @@ -38,8 +37,18 @@ from authentik.core.models import ( Source, UserSourceConnection, ) -from authentik.enterprise.models import LicenseKey, LicenseUsage +from authentik.enterprise.license import LicenseKey +from authentik.enterprise.models import LicenseUsage +from authentik.enterprise.providers.google_workspace.models import ( + GoogleWorkspaceProviderGroup, + GoogleWorkspaceProviderUser, +) +from authentik.enterprise.providers.microsoft_entra.models import ( + MicrosoftEntraProviderGroup, + MicrosoftEntraProviderUser, +) from authentik.enterprise.providers.rac.models import ConnectionToken +from authentik.events.logs import LogEvent, capture_logs from authentik.events.models import SystemTask from authentik.events.utils import cleanse_dict from authentik.flows.models import FlowToken, Stage @@ -50,6 +59,8 @@ from authentik.policies.models import Policy, PolicyBindingModel from authentik.policies.reputation.models import Reputation from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken from authentik.providers.scim.models import SCIMGroup, SCIMUser +from authentik.sources.scim.models import SCIMSourceGroup, SCIMSourceUser +from authentik.stages.authenticator_webauthn.models import WebAuthnDeviceType from authentik.tenants.models import Tenant # Context set when the serializer is created in a blueprint context @@ -60,7 +71,7 @@ SERIALIZER_CONTEXT_BLUEPRINT = "blueprint_entry" def excluded_models() -> list[type[Model]]: """Return a list of all excluded models that shouldn't be exposed via API or other means (internal only, base classes, non-used objects, etc)""" - # pylint: disable=imported-auth-user + from django.contrib.auth.models import Group as DjangoGroup from django.contrib.auth.models import User as DjangoUser @@ -83,6 +94,7 @@ def excluded_models() -> list[type[Model]]: # Classes that have other dependencies AuthenticatedSession, # Classes which are only internally managed + # FIXME: these shouldn't need to be explicitly listed, but rather based off of a mixin FlowToken, LicenseUsage, SCIMGroup, @@ -94,12 +106,19 @@ def excluded_models() -> list[type[Model]]: AccessToken, RefreshToken, Reputation, + WebAuthnDeviceType, + SCIMSourceUser, + SCIMSourceGroup, + GoogleWorkspaceProviderUser, + GoogleWorkspaceProviderGroup, + MicrosoftEntraProviderUser, + MicrosoftEntraProviderGroup, ) def is_model_allowed(model: type[Model]) -> bool: """Check if model is allowed""" - return model not in excluded_models() and issubclass(model, (SerializerModel, BaseMetaModel)) + return model not in excluded_models() and issubclass(model, SerializerModel | BaseMetaModel) class DoRollback(SentryIgnoredException): @@ -123,7 +142,7 @@ class Importer: logger: BoundLogger _import: Blueprint - def __init__(self, blueprint: Blueprint, context: Optional[dict] = None): + def __init__(self, blueprint: Blueprint, context: dict | None = None): self.__pk_map: dict[Any, Model] = {} self._import = blueprint self.logger = get_logger() @@ -159,14 +178,14 @@ class Importer: def updater(value) -> Any: if value in self.__pk_map: - self.logger.debug("updating reference in entry", value=value) + self.logger.debug("Updating reference in entry", value=value) return self.__pk_map[value] return value for key, value in attrs.items(): try: if isinstance(value, dict): - for idx, _inner_key in enumerate(value): + for _, _inner_key in enumerate(value): value[_inner_key] = updater(value[_inner_key]) elif isinstance(value, list): for idx, _inner_value in enumerate(value): @@ -195,8 +214,7 @@ class Importer: return main_query | sub_query - # pylint: disable-msg=too-many-locals - def _validate_single(self, entry: BlueprintEntry) -> Optional[BaseSerializer]: + def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None: """Validate a single entry""" if not entry.check_all_conditions_match(self._import): self.logger.debug("One or more conditions of this entry are not fulfilled, skipping") @@ -249,7 +267,7 @@ class Importer: model_instance = existing_models.first() if not isinstance(model(), BaseMetaModel) and model_instance: self.logger.debug( - "initialise serializer with instance", + "Initialise serializer with instance", model=model, instance=model_instance, pk=model_instance.pk, @@ -259,14 +277,14 @@ class Importer: elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED: raise EntryInvalidError.from_entry( ( - f"state is set to {BlueprintEntryDesiredState.MUST_CREATED} " + f"State is set to {BlueprintEntryDesiredState.MUST_CREATED} " "and object exists already", ), entry, ) else: self.logger.debug( - "initialised new serializer instance", + "Initialised new serializer instance", model=model, **cleanse_dict(updated_identifiers), ) @@ -323,7 +341,7 @@ class Importer: model: type[SerializerModel] = registry.get_model(model_app_label, model_name) except LookupError: self.logger.warning( - "app or model does not exist", app=model_app_label, model=model_name + "App or Model does not exist", app=model_app_label, model=model_name ) return False # Validate each single entry @@ -335,7 +353,7 @@ class Importer: if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT: serializer = exc.serializer else: - self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc) + self.logger.warning(f"Entry invalid: {exc}", entry=entry, error=exc) if raise_errors: raise exc return False @@ -355,27 +373,27 @@ class Importer: and state == BlueprintEntryDesiredState.CREATED ): self.logger.debug( - "instance exists, skipping", + "Instance exists, skipping", model=model, instance=instance, pk=instance.pk, ) else: instance = serializer.save() - self.logger.debug("updated model", model=instance) + self.logger.debug("Updated model", model=instance) if "pk" in entry.identifiers: self.__pk_map[entry.identifiers["pk"]] = instance.pk entry._state = BlueprintEntryState(instance) elif state == BlueprintEntryDesiredState.ABSENT: - instance: Optional[Model] = serializer.instance + instance: Model | None = serializer.instance if instance.pk: instance.delete() - self.logger.debug("deleted model", mode=instance) + self.logger.debug("Deleted model", mode=instance) continue - self.logger.debug("entry to delete with no instance, skipping") + self.logger.debug("Entry to delete with no instance, skipping") return True - def validate(self, raise_validation_errors=False) -> tuple[bool, list[EventDict]]: + def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]: """Validate loaded blueprint export, ensure all models are allowed and serializers have no errors""" self.logger.debug("Starting blueprint import validation") @@ -389,9 +407,7 @@ class Importer: ): successful = self._apply_models(raise_errors=raise_validation_errors) if not successful: - self.logger.debug("Blueprint validation failed") - for log in logs: - getattr(self.logger, log.get("log_level"))(**log) + self.logger.warning("Blueprint validation failed") self.logger.debug("Finished blueprint import validation") self._import = orig_import return successful, logs diff --git a/authentik/blueprints/v1/meta/apply_blueprint.py b/authentik/blueprints/v1/meta/apply_blueprint.py index 0a8d84e661..abd593c045 100644 --- a/authentik/blueprints/v1/meta/apply_blueprint.py +++ b/authentik/blueprints/v1/meta/apply_blueprint.py @@ -1,4 +1,5 @@ """Apply Blueprint meta model""" + from typing import TYPE_CHECKING from rest_framework.exceptions import ValidationError @@ -42,7 +43,7 @@ class ApplyBlueprintMetaSerializer(PassiveSerializer): LOGGER.info("Blueprint does not exist, but not required") return MetaResult() LOGGER.debug("Applying blueprint from meta model", blueprint=self.blueprint_instance) - # pylint: disable=no-value-for-parameter + apply_blueprint(str(self.blueprint_instance.pk)) return MetaResult() diff --git a/authentik/blueprints/v1/meta/registry.py b/authentik/blueprints/v1/meta/registry.py index 70e409f9c4..7d64815914 100644 --- a/authentik/blueprints/v1/meta/registry.py +++ b/authentik/blueprints/v1/meta/registry.py @@ -1,4 +1,5 @@ """Base models""" + from django.apps import apps from django.db.models import Model from rest_framework.serializers import Serializer @@ -7,15 +8,15 @@ from rest_framework.serializers import Serializer class BaseMetaModel(Model): """Base models""" + class Meta: + abstract = True + @staticmethod def serializer() -> Serializer: """Serializer similar to SerializerModel, but as a static method since this is an abstract model""" raise NotImplementedError - class Meta: - abstract = True - class MetaResult: """Result returned by Meta Models' serializers. Empty class but we can't return none as diff --git a/authentik/blueprints/v1/oci.py b/authentik/blueprints/v1/oci.py index d02f3fa2f0..6a22c4037f 100644 --- a/authentik/blueprints/v1/oci.py +++ b/authentik/blueprints/v1/oci.py @@ -1,4 +1,5 @@ """OCI Client""" + from typing import Any from urllib.parse import ParseResult, urlparse diff --git a/authentik/blueprints/v1/tasks.py b/authentik/blueprints/v1/tasks.py index cf3e1ca1a5..c8b72a5dc2 100644 --- a/authentik/blueprints/v1/tasks.py +++ b/authentik/blueprints/v1/tasks.py @@ -1,8 +1,9 @@ """v1 blueprints tasks""" + from dataclasses import asdict, dataclass, field from hashlib import sha512 from pathlib import Path -from typing import Optional +from sys import platform from dacite.core import from_dict from django.db import DatabaseError, InternalError, ProgrammingError @@ -29,6 +30,7 @@ from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata, E from authentik.blueprints.v1.importer import Importer from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_INSTANTIATE from authentik.blueprints.v1.oci import OCI_PREFIX +from authentik.events.logs import capture_logs from authentik.events.models import TaskStatus from authentik.events.system_tasks import SystemTask, prefill_task from authentik.events.utils import sanitize_dict @@ -48,18 +50,23 @@ class BlueprintFile: version: int hash: str last_m: int - meta: Optional[BlueprintMetadata] = field(default=None) + meta: BlueprintMetadata | None = field(default=None) def start_blueprint_watcher(): """Start blueprint watcher, if it's not running already.""" # This function might be called twice since it's called on celery startup - # pylint: disable=global-statement - global _file_watcher_started + + global _file_watcher_started # noqa: PLW0603 if _file_watcher_started: return observer = Observer() - observer.schedule(BlueprintEventHandler(), CONFIG.get("blueprints_dir"), recursive=True) + kwargs = {} + if platform.startswith("linux"): + kwargs["event_filter"] = (FileCreatedEvent, FileModifiedEvent) + observer.schedule( + BlueprintEventHandler(), CONFIG.get("blueprints_dir"), recursive=True, **kwargs + ) observer.start() _file_watcher_started = True @@ -67,26 +74,36 @@ def start_blueprint_watcher(): class BlueprintEventHandler(FileSystemEventHandler): """Event handler for blueprint events""" - def on_any_event(self, event: FileSystemEvent): - if not isinstance(event, (FileCreatedEvent, FileModifiedEvent)): - return + # We only ever get creation and modification events. + # See the creation of the Observer instance above for the event filtering. + + # Even though we filter to only get file events, we might still get + # directory events as some implementations such as inotify do not support + # filtering on file/directory. + + def dispatch(self, event: FileSystemEvent) -> None: + """Call specific event handler method. Ignores directory changes.""" if event.is_directory: - return + return None + return super().dispatch(event) + + def on_created(self, event: FileSystemEvent): + """Process file creation""" + LOGGER.debug("new blueprint file created, starting discovery") + for tenant in Tenant.objects.filter(ready=True): + with tenant: + blueprints_discovery.delay() + + def on_modified(self, event: FileSystemEvent): + """Process file modification""" + path = Path(event.src_path) root = Path(CONFIG.get("blueprints_dir")).absolute() - path = Path(event.src_path).absolute() rel_path = str(path.relative_to(root)) for tenant in Tenant.objects.filter(ready=True): with tenant: - root = Path(CONFIG.get("blueprints_dir")).absolute() - path = Path(event.src_path).absolute() - rel_path = str(path.relative_to(root)) - if isinstance(event, FileCreatedEvent): - LOGGER.debug("new blueprint file created, starting discovery", path=rel_path) - blueprints_discovery.delay(rel_path) - if isinstance(event, FileModifiedEvent): - for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True): - LOGGER.debug("modified blueprint file, starting apply", instance=instance) - apply_blueprint.delay(instance.pk.hex) + for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True): + LOGGER.debug("modified blueprint file, starting apply", instance=instance) + apply_blueprint.delay(instance.pk.hex) @CELERY_APP.task( @@ -109,7 +126,7 @@ def blueprints_find() -> list[BlueprintFile]: # Check if any part in the path starts with a dot and assume a hidden file if any(part for part in path.parts if part.startswith(".")): continue - with open(path, "r", encoding="utf-8") as blueprint_file: + with open(path, encoding="utf-8") as blueprint_file: try: raw_blueprint = load(blueprint_file.read(), BlueprintLoader) except YAMLError as exc: @@ -133,7 +150,7 @@ def blueprints_find() -> list[BlueprintFile]: throws=(DatabaseError, ProgrammingError, InternalError), base=SystemTask, bind=True ) @prefill_task -def blueprints_discovery(self: SystemTask, path: Optional[str] = None): +def blueprints_discovery(self: SystemTask, path: str | None = None): """Find blueprints and check if they need to be created in the database""" count = 0 for blueprint in blueprints_find(): @@ -180,7 +197,7 @@ def check_blueprint_v1_file(blueprint: BlueprintFile): def apply_blueprint(self: SystemTask, instance_pk: str): """Apply single blueprint""" self.save_on_success = False - instance: Optional[BlueprintInstance] = None + instance: BlueprintInstance | None = None try: instance: BlueprintInstance = BlueprintInstance.objects.filter(pk=instance_pk).first() if not instance or not instance.enabled: @@ -195,23 +212,24 @@ def apply_blueprint(self: SystemTask, instance_pk: str): if not valid: instance.status = BlueprintInstanceStatus.ERROR instance.save() - self.set_status(TaskStatus.ERROR, *[x["event"] for x in logs]) - return - applied = importer.apply() - if not applied: - instance.status = BlueprintInstanceStatus.ERROR - instance.save() - self.set_status(TaskStatus.ERROR, "Failed to apply") + self.set_status(TaskStatus.ERROR, *logs) return + with capture_logs() as logs: + applied = importer.apply() + if not applied: + instance.status = BlueprintInstanceStatus.ERROR + instance.save() + self.set_status(TaskStatus.ERROR, *logs) + return instance.status = BlueprintInstanceStatus.SUCCESSFUL instance.last_applied_hash = file_hash instance.last_applied = now() self.set_status(TaskStatus.SUCCESSFUL) except ( + OSError, DatabaseError, ProgrammingError, InternalError, - IOError, BlueprintRetrievalFailed, EntryInvalidError, ) as exc: diff --git a/authentik/brands/api.py b/authentik/brands/api.py index 2b22a35089..a856cee485 100644 --- a/authentik/brands/api.py +++ b/authentik/brands/api.py @@ -1,4 +1,5 @@ """Serializer for brands models""" + from typing import Any from django.db import models @@ -11,6 +12,7 @@ from rest_framework.permissions import AllowAny from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer +from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet from authentik.api.authorization import SecretKeyFilter @@ -57,6 +59,11 @@ class BrandSerializer(ModelSerializer): "web_certificate", "attributes", ] + extra_kwargs = { + # TODO: This field isn't unique on the database which is hard to backport + # hence we just validate the uniqueness here + "domain": {"validators": [UniqueValidator(Brand.objects.all())]}, + } class Themes(models.TextChoices): diff --git a/authentik/brands/apps.py b/authentik/brands/apps.py index a116f7c4bc..43c20acc75 100644 --- a/authentik/brands/apps.py +++ b/authentik/brands/apps.py @@ -1,4 +1,5 @@ """authentik brands app""" + from django.apps import AppConfig diff --git a/authentik/brands/middleware.py b/authentik/brands/middleware.py index 744b700c9e..71650cc621 100644 --- a/authentik/brands/middleware.py +++ b/authentik/brands/middleware.py @@ -1,5 +1,6 @@ """Inject brand into current request""" -from typing import Callable + +from collections.abc import Callable from django.http.request import HttpRequest from django.http.response import HttpResponse @@ -19,7 +20,7 @@ class BrandMiddleware: def __call__(self, request: HttpRequest) -> HttpResponse: if not hasattr(request, "brand"): brand = get_brand_for_request(request) - setattr(request, "brand", brand) + request.brand = brand locale = brand.default_locale if locale != "": activate(locale) diff --git a/authentik/brands/migrations/0006_brand_authentik_b_domain_b9b24a_idx_and_more.py b/authentik/brands/migrations/0006_brand_authentik_b_domain_b9b24a_idx_and_more.py new file mode 100644 index 0000000000..edcbd34f8d --- /dev/null +++ b/authentik/brands/migrations/0006_brand_authentik_b_domain_b9b24a_idx_and_more.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.4 on 2024-04-18 18:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_brands", "0005_tenantuuid_to_branduuid"), + ] + + operations = [ + migrations.AddIndex( + model_name="brand", + index=models.Index(fields=["domain"], name="authentik_b_domain_b9b24a_idx"), + ), + migrations.AddIndex( + model_name="brand", + index=models.Index(fields=["default"], name="authentik_b_default_3ccf12_idx"), + ), + ] diff --git a/authentik/brands/models.py b/authentik/brands/models.py index 268aa5c26a..0193774935 100644 --- a/authentik/brands/models.py +++ b/authentik/brands/models.py @@ -1,4 +1,5 @@ """brand models""" + from uuid import uuid4 from django.db import models @@ -70,7 +71,7 @@ class Brand(SerializerModel): """Get default locale""" try: return self.attributes.get("settings", {}).get("locale", "") - # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Failed to get default locale", exc=exc) return "" @@ -83,3 +84,7 @@ class Brand(SerializerModel): class Meta: verbose_name = _("Brand") verbose_name_plural = _("Brands") + indexes = [ + models.Index(fields=["domain"]), + models.Index(fields=["default"]), + ] diff --git a/authentik/brands/tests.py b/authentik/brands/tests.py index 71f18ca4e9..712818fda1 100644 --- a/authentik/brands/tests.py +++ b/authentik/brands/tests.py @@ -1,4 +1,5 @@ """Test brands""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/brands/urls.py b/authentik/brands/urls.py index b71406d1c9..85b0ea2432 100644 --- a/authentik/brands/urls.py +++ b/authentik/brands/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.brands.api import BrandViewSet api_urlpatterns = [ diff --git a/authentik/brands/utils.py b/authentik/brands/utils.py index ab1778148a..5e6ef40ed3 100644 --- a/authentik/brands/utils.py +++ b/authentik/brands/utils.py @@ -1,4 +1,5 @@ """Brand utilities""" + from typing import Any from django.db.models import F, Q @@ -8,7 +9,7 @@ from sentry_sdk.hub import Hub from authentik import get_full_version from authentik.brands.models import Brand -from authentik.tenants.utils import get_current_tenant +from authentik.tenants.models import Tenant _q_default = Q(default=True) DEFAULT_BRAND = Brand(domain="fallback") @@ -30,13 +31,14 @@ def get_brand_for_request(request: HttpRequest) -> Brand: def context_processor(request: HttpRequest) -> dict[str, Any]: """Context Processor that injects brand object into every template""" brand = getattr(request, "brand", DEFAULT_BRAND) + tenant = getattr(request, "tenant", Tenant()) trace = "" span = Hub.current.scope.span if span: trace = span.to_traceparent() return { "brand": brand, - "footer_links": get_current_tenant().footer_links, + "footer_links": tenant.footer_links, "sentry_trace": trace, "version": get_full_version(), } diff --git a/authentik/core/api/applications.py b/authentik/core/api/applications.py index cb4c01e768..eddad64bf8 100644 --- a/authentik/core/api/applications.py +++ b/authentik/core/api/applications.py @@ -1,16 +1,18 @@ """Application API Views""" + +from collections.abc import Iterator +from copy import copy from datetime import timedelta -from typing import Optional from django.core.cache import cache from django.db.models import QuerySet from django.db.models.functions import ExtractHour -from django.http.response import HttpResponseBadRequest from django.shortcuts import get_object_or_404 from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action +from rest_framework.exceptions import ValidationError from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodField from rest_framework.parsers import MultiPartParser from rest_framework.request import Request @@ -18,16 +20,15 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger -from structlog.testing import capture_logs from authentik.admin.api.metrics import CoordinateSerializer -from authentik.api.decorators import permission_required +from authentik.api.pagination import Pagination from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.models import Application, User +from authentik.events.logs import LogEventSerializer, capture_logs from authentik.events.models import EventAction -from authentik.events.utils import sanitize_dict from authentik.lib.utils.file import ( FilePathSerializer, FileUploadSerializer, @@ -36,15 +37,19 @@ from authentik.lib.utils.file import ( ) from authentik.policies.api.exec import PolicyTestResultSerializer from authentik.policies.engine import PolicyEngine -from authentik.policies.types import PolicyResult +from authentik.policies.types import CACHE_PREFIX, PolicyResult +from authentik.rbac.decorators import permission_required from authentik.rbac.filters import ObjectFilter LOGGER = get_logger() -def user_app_cache_key(user_pk: str) -> str: +def user_app_cache_key(user_pk: str, page_number: int | None = None) -> str: """Cache key where application list for user is saved""" - return f"goauthentik.io/core/app_access/{user_pk}" + key = f"{CACHE_PREFIX}/app_access/{user_pk}" + if page_number: + key += f"/{page_number}" + return key class ApplicationSerializer(ModelSerializer): @@ -58,7 +63,7 @@ class ApplicationSerializer(ModelSerializer): meta_icon = ReadOnlyField(source="get_meta_icon") - def get_launch_url(self, app: Application) -> Optional[str]: + def get_launch_url(self, app: Application) -> str | None: """Allow formatting of launch URL""" user = None if "request" in self.context: @@ -98,7 +103,6 @@ class ApplicationSerializer(ModelSerializer): class ApplicationViewSet(UsedByMixin, ModelViewSet): """Application Viewset""" - # pylint: disable=no-member queryset = Application.objects.all().prefetch_related("provider") serializer_class = ApplicationSerializer search_fields = [ @@ -128,10 +132,16 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): queryset = backend().filter_queryset(self.request, queryset, self) return queryset - def _get_allowed_applications(self, queryset: QuerySet) -> list[Application]: + def _get_allowed_applications( + self, pagined_apps: Iterator[Application], user: User | None = None + ) -> list[Application]: applications = [] - for application in queryset: - engine = PolicyEngine(application, self.request.user, self.request) + request = self.request._request + if user: + request = copy(request) + request.user = user + for application in pagined_apps: + engine = PolicyEngine(application, request.user, request) engine.build() if engine.passing: applications.append(application) @@ -147,7 +157,6 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): ], responses={ 200: PolicyTestResultSerializer(), - 404: OpenApiResponse(description="for_user user not found"), }, ) @action(detail=True, methods=["GET"]) @@ -160,9 +169,11 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): for_user = request.user if request.user.is_superuser and "for_user" in request.query_params: try: - for_user = get_object_or_404(User, pk=request.query_params.get("for_user")) + for_user = User.objects.filter(pk=request.query_params.get("for_user")).first() except ValueError: - return HttpResponseBadRequest("for_user must be numerical") + raise ValidationError({"for_user": "for_user must be numerical"}) from None + if not for_user: + raise ValidationError({"for_user": "User not found"}) engine = PolicyEngine(application, for_user, request) engine.use_cache = False with capture_logs() as logs: @@ -174,9 +185,9 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): if request.user.is_superuser: log_messages = [] for log in logs: - if log.get("process", "") == "PolicyProcess": + if log.attributes.get("process", "") == "PolicyProcess": continue - log_messages.append(sanitize_dict(log)) + log_messages.append(LogEventSerializer(log).data) result.log_messages = log_messages response = PolicyTestResultSerializer(result) return Response(response.data) @@ -187,30 +198,56 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet): name="superuser_full_list", location=OpenApiParameter.QUERY, type=OpenApiTypes.BOOL, - ) + ), + OpenApiParameter( + name="for_user", + location=OpenApiParameter.QUERY, + type=OpenApiTypes.INT, + ), ] ) def list(self, request: Request) -> Response: """Custom list method that checks Policy based access instead of guardian""" - should_cache = request.GET.get("search", "") == "" + should_cache = request.query_params.get("search", "") == "" - superuser_full_list = str(request.GET.get("superuser_full_list", "false")).lower() == "true" + superuser_full_list = ( + str(request.query_params.get("superuser_full_list", "false")).lower() == "true" + ) if superuser_full_list and request.user.is_superuser: return super().list(request) queryset = self._filter_queryset_for_list(self.get_queryset()) - self.paginate_queryset(queryset) + paginator: Pagination = self.paginator + paginated_apps = paginator.paginate_queryset(queryset, request) + + if "for_user" in request.query_params: + try: + for_user: int = int(request.query_params.get("for_user", 0)) + for_user = ( + get_objects_for_user(request.user, "authentik_core.view_user_applications") + .filter(pk=for_user) + .first() + ) + if not for_user: + raise ValidationError({"for_user": "User not found"}) + except ValueError as exc: + raise ValidationError from exc + allowed_applications = self._get_allowed_applications(paginated_apps, user=for_user) + serializer = self.get_serializer(allowed_applications, many=True) + return self.get_paginated_response(serializer.data) allowed_applications = [] if not should_cache: - allowed_applications = self._get_allowed_applications(queryset) + allowed_applications = self._get_allowed_applications(paginated_apps) if should_cache: - allowed_applications = cache.get(user_app_cache_key(self.request.user.pk)) + allowed_applications = cache.get( + user_app_cache_key(self.request.user.pk, paginator.page.number) + ) if not allowed_applications: - LOGGER.debug("Caching allowed application list") - allowed_applications = self._get_allowed_applications(queryset) + LOGGER.debug("Caching allowed application list", page=paginator.page.number) + allowed_applications = self._get_allowed_applications(paginated_apps) cache.set( - user_app_cache_key(self.request.user.pk), + user_app_cache_key(self.request.user.pk, paginator.page.number), allowed_applications, timeout=86400, ) diff --git a/authentik/core/api/authenticated_sessions.py b/authentik/core/api/authenticated_sessions.py index 2d77937be0..b8094238bf 100644 --- a/authentik/core/api/authenticated_sessions.py +++ b/authentik/core/api/authenticated_sessions.py @@ -1,5 +1,6 @@ """AuthenticatedSessions API Viewset""" -from typing import Optional, TypedDict + +from typing import TypedDict from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user @@ -71,11 +72,11 @@ class AuthenticatedSessionSerializer(ModelSerializer): """Get parsed user agent""" return user_agent_parser.Parse(instance.last_user_agent) - def get_geo_ip(self, instance: AuthenticatedSession) -> Optional[GeoIPDict]: # pragma: no cover + def get_geo_ip(self, instance: AuthenticatedSession) -> GeoIPDict | None: # pragma: no cover """Get GeoIP Data""" return GEOIP_CONTEXT_PROCESSOR.city_dict(instance.last_ip) - def get_asn(self, instance: AuthenticatedSession) -> Optional[ASNDict]: # pragma: no cover + def get_asn(self, instance: AuthenticatedSession) -> ASNDict | None: # pragma: no cover """Get ASN Data""" return ASN_CONTEXT_PROCESSOR.asn_dict(instance.last_ip) diff --git a/authentik/core/api/devices.py b/authentik/core/api/devices.py index 7773615332..528d1775f7 100644 --- a/authentik/core/api/devices.py +++ b/authentik/core/api/devices.py @@ -1,4 +1,5 @@ """Authenticator Devices API Views""" + from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, extend_schema from rest_framework.fields import BooleanField, CharField, IntegerField, SerializerMethodField diff --git a/authentik/core/api/groups.py b/authentik/core/api/groups.py index 04670844d5..12c7675438 100644 --- a/authentik/core/api/groups.py +++ b/authentik/core/api/groups.py @@ -1,24 +1,30 @@ """Groups API Viewset""" + from json import loads -from typing import Optional from django.http import Http404 from django_filters.filters import CharFilter, ModelMultipleChoiceFilter from django_filters.filterset import FilterSet -from drf_spectacular.utils import OpenApiResponse, extend_schema +from drf_spectacular.utils import ( + OpenApiParameter, + OpenApiResponse, + extend_schema, + extend_schema_field, +) from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action -from rest_framework.fields import CharField, IntegerField +from rest_framework.fields import CharField, IntegerField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError +from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet -from authentik.api.decorators import permission_required from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import JSONDictField, PassiveSerializer from authentik.core.models import Group, User from authentik.rbac.api.roles import RoleSerializer +from authentik.rbac.decorators import permission_required class GroupMemberSerializer(ModelSerializer): @@ -45,9 +51,7 @@ class GroupSerializer(ModelSerializer): """Group Serializer""" attributes = JSONDictField(required=False) - users_obj = ListSerializer( - child=GroupMemberSerializer(), read_only=True, source="users", required=False - ) + users_obj = SerializerMethodField(allow_null=True) roles_obj = ListSerializer( child=RoleSerializer(), read_only=True, @@ -58,7 +62,20 @@ class GroupSerializer(ModelSerializer): num_pk = IntegerField(read_only=True) - def validate_parent(self, parent: Optional[Group]): + @property + def _should_include_users(self) -> bool: + request: Request = self.context.get("request", None) + if not request: + return True + return str(request.query_params.get("include_users", "true")).lower() == "true" + + @extend_schema_field(GroupMemberSerializer(many=True)) + def get_users_obj(self, instance: Group) -> list[GroupMemberSerializer] | None: + if not self._should_include_users: + return None + return GroupMemberSerializer(instance.users, many=True).data + + def validate_parent(self, parent: Group | None): """Validate group parent (if set), ensuring the parent isn't itself""" if not self.instance or not parent: return parent @@ -84,7 +101,10 @@ class GroupSerializer(ModelSerializer): extra_kwargs = { "users": { "default": list, - } + }, + # TODO: This field isn't unique on the database which is hard to backport + # hence we just validate the uniqueness here + "name": {"validators": [UniqueValidator(Group.objects.all())]}, } @@ -113,7 +133,7 @@ class GroupFilter(FilterSet): try: value = loads(value) except ValueError: - raise ValidationError(detail="filter: failed to parse JSON") + raise ValidationError(detail="filter: failed to parse JSON") from None if not isinstance(value, dict): raise ValidationError(detail="filter: value must be key:value mapping") qs = {} @@ -130,23 +150,43 @@ class GroupFilter(FilterSet): fields = ["name", "is_superuser", "members_by_pk", "attributes", "members_by_username"] -class UserAccountSerializer(PassiveSerializer): - """Account adding/removing operations""" - - pk = IntegerField(required=True) - - class GroupViewSet(UsedByMixin, ModelViewSet): """Group Viewset""" - # pylint: disable=no-member - queryset = Group.objects.all().select_related("parent").prefetch_related("users") + class UserAccountSerializer(PassiveSerializer): + """Account adding/removing operations""" + + pk = IntegerField(required=True) + + queryset = Group.objects.none() serializer_class = GroupSerializer search_fields = ["name", "is_superuser"] filterset_class = GroupFilter ordering = ["name"] - @permission_required(None, ["authentik_core.add_user"]) + def get_queryset(self): + base_qs = Group.objects.all().select_related("parent").prefetch_related("roles") + if self.serializer_class(context={"request": self.request})._should_include_users: + base_qs = base_qs.prefetch_related("users") + return base_qs + + @extend_schema( + parameters=[ + OpenApiParameter("include_users", bool, default=True), + ] + ) + def list(self, request, *args, **kwargs): + return super().list(request, *args, **kwargs) + + @extend_schema( + parameters=[ + OpenApiParameter("include_users", bool, default=True), + ] + ) + def retrieve(self, request, *args, **kwargs): + return super().retrieve(request, *args, **kwargs) + + @permission_required("authentik_core.add_user_to_group") @extend_schema( request=UserAccountSerializer, responses={ @@ -154,7 +194,13 @@ class GroupViewSet(UsedByMixin, ModelViewSet): 404: OpenApiResponse(description="User not found"), }, ) - @action(detail=True, methods=["POST"], pagination_class=None, filter_backends=[]) + @action( + detail=True, + methods=["POST"], + pagination_class=None, + filter_backends=[], + permission_classes=[], + ) def add_user(self, request: Request, pk: str) -> Response: """Add user to group""" group: Group = self.get_object() @@ -170,7 +216,7 @@ class GroupViewSet(UsedByMixin, ModelViewSet): group.users.add(user) return Response(status=204) - @permission_required(None, ["authentik_core.add_user"]) + @permission_required("authentik_core.remove_user_from_group") @extend_schema( request=UserAccountSerializer, responses={ @@ -178,7 +224,13 @@ class GroupViewSet(UsedByMixin, ModelViewSet): 404: OpenApiResponse(description="User not found"), }, ) - @action(detail=True, methods=["POST"], pagination_class=None, filter_backends=[]) + @action( + detail=True, + methods=["POST"], + pagination_class=None, + filter_backends=[], + permission_classes=[], + ) def remove_user(self, request: Request, pk: str) -> Response: """Add user to group""" group: Group = self.get_object() diff --git a/authentik/core/api/object_types.py b/authentik/core/api/object_types.py new file mode 100644 index 0000000000..12acd4e4a7 --- /dev/null +++ b/authentik/core/api/object_types.py @@ -0,0 +1,79 @@ +"""API Utilities""" + +from drf_spectacular.utils import extend_schema +from rest_framework.decorators import action +from rest_framework.fields import ( + BooleanField, + CharField, +) +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.core.api.utils import PassiveSerializer +from authentik.enterprise.apps import EnterpriseConfig +from authentik.lib.utils.reflection import all_subclasses + + +class TypeCreateSerializer(PassiveSerializer): + """Types of an object that can be created""" + + name = CharField(required=True) + description = CharField(required=True) + component = CharField(required=True) + model_name = CharField(required=True) + + icon_url = CharField(required=False) + requires_enterprise = BooleanField(default=False) + + +class CreatableType: + """Class to inherit from to mark a model as creatable, even if the model itself is marked + as abstract""" + + +class NonCreatableType: + """Class to inherit from to mark a model as non-creatable even if it is not abstract""" + + +class TypesMixin: + """Mixin which adds an API endpoint to list all possible types that can be created""" + + @extend_schema(responses={200: TypeCreateSerializer(many=True)}) + @action(detail=False, pagination_class=None, filter_backends=[]) + def types(self, request: Request, additional: list[dict] | None = None) -> Response: + """Get all creatable types""" + data = [] + for subclass in all_subclasses(self.queryset.model): + instance = None + if subclass._meta.abstract: + if not issubclass(subclass, CreatableType): + continue + # Circumvent the django protection for not being able to instantiate + # abstract models. We need a model instance to access .component + # and further down .icon_url + instance = subclass.__new__(subclass) + # Django re-sets abstract = False so we need to override that + instance.Meta.abstract = True + else: + if issubclass(subclass, NonCreatableType): + continue + instance = subclass() + try: + data.append( + { + "name": subclass._meta.verbose_name, + "description": subclass.__doc__, + "component": instance.component, + "model_name": subclass._meta.model_name, + "icon_url": getattr(instance, "icon_url", None), + "requires_enterprise": isinstance( + subclass._meta.app_config, EnterpriseConfig + ), + } + ) + except NotImplementedError: + continue + if additional: + data.extend(additional) + data = sorted(data, key=lambda x: x["name"]) + return Response(TypeCreateSerializer(data, many=True).data) diff --git a/authentik/core/api/propertymappings.py b/authentik/core/api/property_mappings.py similarity index 61% rename from authentik/core/api/propertymappings.py rename to authentik/core/api/property_mappings.py index 1e7436be93..fb7d6c0778 100644 --- a/authentik/core/api/propertymappings.py +++ b/authentik/core/api/property_mappings.py @@ -1,4 +1,5 @@ """PropertyMapping API Views""" + from json import dumps from drf_spectacular.types import OpenApiTypes @@ -8,20 +9,24 @@ from rest_framework import mixins from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied from rest_framework.fields import BooleanField, CharField +from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet -from authentik.api.decorators import permission_required from authentik.blueprints.api import ManagedSerializer +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer, PassiveSerializer, TypeCreateSerializer +from authentik.core.api.utils import ( + MetaNameSerializer, + PassiveSerializer, +) from authentik.core.expression.evaluator import PropertyMappingEvaluator -from authentik.core.models import PropertyMapping +from authentik.core.models import Group, PropertyMapping, User from authentik.events.utils import sanitize_item -from authentik.lib.utils.reflection import all_subclasses from authentik.policies.api.exec import PolicyTestSerializer +from authentik.rbac.decorators import permission_required class PropertyMappingTestResultSerializer(PassiveSerializer): @@ -63,6 +68,7 @@ class PropertyMappingSerializer(ManagedSerializer, ModelSerializer, MetaNameSeri class PropertyMappingViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -71,7 +77,13 @@ class PropertyMappingViewSet( ): """PropertyMapping Viewset""" - queryset = PropertyMapping.objects.none() + class PropertyMappingTestSerializer(PolicyTestSerializer): + """Test property mapping execution for a user/group with context""" + + user = PrimaryKeyRelatedField(queryset=User.objects.all(), required=False) + group = PrimaryKeyRelatedField(queryset=Group.objects.all(), required=False) + + queryset = PropertyMapping.objects.select_subclasses() serializer_class = PropertyMappingSerializer search_fields = [ "name", @@ -79,29 +91,9 @@ class PropertyMappingViewSet( filterset_fields = {"managed": ["isnull"]} ordering = ["name"] - def get_queryset(self): # pragma: no cover - return PropertyMapping.objects.select_subclasses() - - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable property-mapping types""" - data = [] - for subclass in all_subclasses(self.queryset.model): - subclass: PropertyMapping - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": subclass().component, - "model_name": subclass._meta.model_name, - } - ) - return Response(TypeCreateSerializer(data, many=True).data) - @permission_required("authentik_core.view_propertymapping") @extend_schema( - request=PolicyTestSerializer(), + request=PropertyMappingTestSerializer(), responses={ 200: PropertyMappingTestResultSerializer, 400: OpenApiResponse(description="Invalid parameters"), @@ -117,31 +109,45 @@ class PropertyMappingViewSet( @action(detail=True, pagination_class=None, filter_backends=[], methods=["POST"]) def test(self, request: Request, pk: str) -> Response: """Test Property Mapping""" - mapping: PropertyMapping = self.get_object() - test_params = PolicyTestSerializer(data=request.data) + _mapping: PropertyMapping = self.get_object() + # Use `get_subclass` to get correct class and correct `.evaluate` implementation + mapping: PropertyMapping = PropertyMapping.objects.get_subclass(pk=_mapping.pk) + # FIXME: when we separate policy mappings between ones for sources + # and ones for providers, we need to make the user field optional for the source mapping + test_params = self.PropertyMappingTestSerializer(data=request.data) if not test_params.is_valid(): return Response(test_params.errors, status=400) format_result = str(request.GET.get("format_result", "false")).lower() == "true" - # User permission check, only allow mapping testing for users that are readable - users = get_objects_for_user(request.user, "authentik_core.view_user").filter( - pk=test_params.validated_data["user"].pk - ) - if not users.exists(): - raise PermissionDenied() + context: dict = test_params.validated_data.get("context", {}) + context.setdefault("user", None) + + if user := test_params.validated_data.get("user"): + # User permission check, only allow mapping testing for users that are readable + users = get_objects_for_user(request.user, "authentik_core.view_user").filter( + pk=user.pk + ) + if not users.exists(): + raise PermissionDenied() + context["user"] = user + if group := test_params.validated_data.get("group"): + # Group permission check, only allow mapping testing for groups that are readable + groups = get_objects_for_user(request.user, "authentik_core.view_group").filter( + pk=group.pk + ) + if not groups.exists(): + raise PermissionDenied() + context["group"] = group + context["request"] = self.request response_data = {"successful": True, "result": ""} try: - result = mapping.evaluate( - users.first(), - self.request, - **test_params.validated_data.get("context", {}), - ) + result = mapping.evaluate(**context) response_data["result"] = dumps( sanitize_item(result), indent=(4 if format_result else None) ) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: response_data["result"] = str(exc) response_data["successful"] = False response = PropertyMappingTestResultSerializer(response_data) diff --git a/authentik/core/api/providers.py b/authentik/core/api/providers.py index 6c0f4db061..2c33ccf1f6 100644 --- a/authentik/core/api/providers.py +++ b/authentik/core/api/providers.py @@ -1,23 +1,19 @@ """Provider API Views""" + from django.db.models import QuerySet from django.db.models.query import Q from django.utils.translation import gettext_lazy as _ from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet -from drf_spectacular.utils import extend_schema from rest_framework import mixins -from rest_framework.decorators import action from rest_framework.fields import ReadOnlyField -from rest_framework.request import Request -from rest_framework.response import Response from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer +from authentik.core.api.utils import MetaNameSerializer from authentik.core.models import Provider -from authentik.enterprise.apps import EnterpriseConfig -from authentik.lib.utils.reflection import all_subclasses class ProviderSerializer(ModelSerializer, MetaNameSerializer): @@ -62,8 +58,12 @@ class ProviderFilter(FilterSet): """Filter for providers""" application__isnull = BooleanFilter(method="filter_application__isnull") - backchannel_only = BooleanFilter( - method="filter_backchannel_only", + backchannel = BooleanFilter( + method="filter_backchannel", + label=_( + "When not set all providers are returned. When set to true, only backchannel " + "providers are returned. When set to false, backchannel providers are excluded" + ), ) def filter_application__isnull(self, queryset: QuerySet, name, value): @@ -74,12 +74,14 @@ class ProviderFilter(FilterSet): | Q(application__isnull=value) ) - def filter_backchannel_only(self, queryset: QuerySet, name, value): - """Only return backchannel providers""" + def filter_backchannel(self, queryset: QuerySet, name, value): + """By default all providers are returned. When set to true, only backchannel providers are + returned. When set to false, backchannel providers are excluded""" return queryset.filter(is_backchannel=value) class ProviderViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -98,31 +100,3 @@ class ProviderViewSet( def get_queryset(self): # pragma: no cover return Provider.objects.select_subclasses() - - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable provider types""" - data = [] - for subclass in all_subclasses(self.queryset.model): - subclass: Provider - if subclass._meta.abstract: - continue - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": subclass().component, - "model_name": subclass._meta.model_name, - "requires_enterprise": isinstance(subclass._meta.app_config, EnterpriseConfig), - } - ) - data.append( - { - "name": _("SAML Provider from Metadata"), - "description": _("Create a SAML Provider by importing its Metadata."), - "component": "ak-provider-saml-import-form", - "model_name": "", - } - ) - return Response(TypeCreateSerializer(data, many=True).data) diff --git a/authentik/core/api/sources.py b/authentik/core/api/sources.py index eff2c9211d..977696c407 100644 --- a/authentik/core/api/sources.py +++ b/authentik/core/api/sources.py @@ -1,5 +1,6 @@ """Source API Views""" -from typing import Iterable + +from collections.abc import Iterable from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import OpenApiResponse, extend_schema @@ -15,10 +16,10 @@ from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions -from authentik.api.decorators import permission_required from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer +from authentik.core.api.utils import MetaNameSerializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UserSettingSerializer from authentik.lib.utils.file import ( @@ -27,8 +28,8 @@ from authentik.lib.utils.file import ( set_file, set_file_url, ) -from authentik.lib.utils.reflection import all_subclasses from authentik.policies.engine import PolicyEngine +from authentik.rbac.decorators import permission_required LOGGER = get_logger() @@ -73,6 +74,7 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer): class SourceViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -131,30 +133,6 @@ class SourceViewSet( source: Source = self.get_object() return set_file_url(request, source, "icon") - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable source types""" - data = [] - for subclass in all_subclasses(self.queryset.model): - subclass: Source - component = "" - if len(subclass.__subclasses__()) > 0: - continue - if subclass._meta.abstract: - component = subclass.__bases__[0]().component - else: - component = subclass().component - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": component, - "model_name": subclass._meta.model_name, - } - ) - return Response(TypeCreateSerializer(data, many=True).data) - @extend_schema(responses={200: UserSettingSerializer(many=True)}) @action(detail=False, pagination_class=None, filter_backends=[]) def user_settings(self, request: Request) -> Response: diff --git a/authentik/core/api/tokens.py b/authentik/core/api/tokens.py index e3c2d46bf0..43637f10d7 100644 --- a/authentik/core/api/tokens.py +++ b/authentik/core/api/tokens.py @@ -1,6 +1,8 @@ """Tokens API Viewset""" + from typing import Any +from django.utils.timezone import now from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer from guardian.shortcuts import assign_perm, get_anonymous_user @@ -14,15 +16,23 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.api.authorization import OwnerSuperuserPermissions -from authentik.api.decorators import permission_required from authentik.blueprints.api import ManagedSerializer from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.core.api.utils import PassiveSerializer -from authentik.core.models import USER_ATTRIBUTE_TOKEN_EXPIRING, Token, TokenIntents +from authentik.core.models import ( + USER_ATTRIBUTE_TOKEN_EXPIRING, + USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME, + Token, + TokenIntents, + User, + default_token_duration, +) from authentik.events.models import Event, EventAction from authentik.events.utils import model_to_dict +from authentik.lib.utils.time import timedelta_from_string +from authentik.rbac.decorators import permission_required class TokenSerializer(ManagedSerializer, ModelSerializer): @@ -48,6 +58,32 @@ class TokenSerializer(ManagedSerializer, ModelSerializer): attrs.setdefault("intent", TokenIntents.INTENT_API) if attrs.get("intent") not in [TokenIntents.INTENT_API, TokenIntents.INTENT_APP_PASSWORD]: raise ValidationError({"intent": f"Invalid intent {attrs.get('intent')}"}) + + if attrs.get("intent") == TokenIntents.INTENT_APP_PASSWORD: + # user IS in attrs + user: User = attrs.get("user") + max_token_lifetime = user.group_attributes(request).get( + USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME, + ) + max_token_lifetime_dt = default_token_duration() + if max_token_lifetime is not None: + try: + max_token_lifetime_dt = now() + timedelta_from_string(max_token_lifetime) + except ValueError: + pass + + if "expires" in attrs and attrs.get("expires") > max_token_lifetime_dt: + raise ValidationError( + { + "expires": ( + f"Token expires exceeds maximum lifetime ({max_token_lifetime_dt} UTC)." + ) + } + ) + elif attrs.get("intent") == TokenIntents.INTENT_API: + # For API tokens, expires cannot be overridden + attrs["expires"] = default_token_duration() + return attrs class Meta: diff --git a/authentik/core/api/transactional_applications.py b/authentik/core/api/transactional_applications.py index 19b6ea4656..1e47096ca6 100644 --- a/authentik/core/api/transactional_applications.py +++ b/authentik/core/api/transactional_applications.py @@ -1,4 +1,5 @@ """transactional application and provider creation""" + from django.apps import apps from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema, extend_schema_field from rest_framework.exceptions import ValidationError @@ -64,7 +65,7 @@ class TransactionApplicationSerializer(PassiveSerializer): raise ValidationError("Invalid provider model") self._provider_model = model except LookupError: - raise ValidationError("Invalid provider model") + raise ValidationError("Invalid provider model") from None return fq_model_name def validate(self, attrs: dict) -> dict: @@ -105,7 +106,7 @@ class TransactionApplicationSerializer(PassiveSerializer): { exc.entry_id: exc.validation_error.detail, } - ) + ) from None return blueprint diff --git a/authentik/core/api/used_by.py b/authentik/core/api/used_by.py index 3f7d4fc8a5..73c3a6a790 100644 --- a/authentik/core/api/used_by.py +++ b/authentik/core/api/used_by.py @@ -1,4 +1,5 @@ """used_by mixin""" + from enum import Enum from inspect import getmembers @@ -53,7 +54,6 @@ class UsedByMixin: responses={200: UsedBySerializer(many=True)}, ) @action(detail=True, pagination_class=None, filter_backends=[]) - # pylint: disable=too-many-locals def used_by(self, request: Request, *args, **kwargs) -> Response: """Get a list of all objects that use this object""" model: Model = self.get_object() diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index a970e6d0bc..a617c1ce2e 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -1,7 +1,8 @@ """User API Views""" + from datetime import timedelta from json import loads -from typing import Any, Optional +from typing import Any from django.contrib.auth import update_session_auth_hash from django.contrib.sessions.backends.cache import KEY_PREFIX @@ -30,7 +31,7 @@ from drf_spectacular.utils import ( extend_schema_field, inline_serializer, ) -from guardian.shortcuts import get_anonymous_user, get_objects_for_user +from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action from rest_framework.fields import CharField, IntegerField, ListField, SerializerMethodField from rest_framework.request import Request @@ -48,7 +49,6 @@ from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.admin.api.metrics import CoordinateSerializer -from authentik.api.decorators import permission_required from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.brands.models import Brand from authentik.core.api.used_by import UsedByMixin @@ -72,6 +72,8 @@ from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import FlowToken from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner from authentik.flows.views.executor import QS_KEY_TOKEN +from authentik.lib.avatars import get_avatar +from authentik.rbac.decorators import permission_required from authentik.stages.email.models import EmailStage from authentik.stages.email.tasks import send_mails from authentik.stages.email.utils import TemplateEmailMessage @@ -83,7 +85,7 @@ class UserGroupSerializer(ModelSerializer): """Simplified Group Serializer for user's groups""" attributes = JSONDictField(required=False) - parent_name = CharField(source="parent.name", read_only=True) + parent_name = CharField(source="parent.name", read_only=True, allow_null=True) class Meta: model = Group @@ -102,14 +104,34 @@ class UserSerializer(ModelSerializer): """User Serializer""" is_superuser = BooleanField(read_only=True) - avatar = CharField(read_only=True) + avatar = SerializerMethodField() attributes = JSONDictField(required=False) groups = PrimaryKeyRelatedField( - allow_empty=True, many=True, source="ak_groups", queryset=Group.objects.all(), default=list + allow_empty=True, + many=True, + source="ak_groups", + queryset=Group.objects.all().order_by("name"), + default=list, ) - groups_obj = ListSerializer(child=UserGroupSerializer(), read_only=True, source="ak_groups") + groups_obj = SerializerMethodField(allow_null=True) uid = CharField(read_only=True) - username = CharField(max_length=150, validators=[UniqueValidator(queryset=User.objects.all())]) + username = CharField( + max_length=150, + validators=[UniqueValidator(queryset=User.objects.all().order_by("username"))], + ) + + @property + def _should_include_groups(self) -> bool: + request: Request = self.context.get("request", None) + if not request: + return True + return str(request.query_params.get("include_groups", "true")).lower() == "true" + + @extend_schema_field(UserGroupSerializer(many=True)) + def get_groups_obj(self, instance: User) -> list[UserGroupSerializer] | None: + if not self._should_include_groups: + return None + return UserGroupSerializer(instance.ak_groups, many=True).data def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -133,7 +155,7 @@ class UserSerializer(ModelSerializer): self._set_password(instance, password) return instance - def _set_password(self, instance: User, password: Optional[str]): + def _set_password(self, instance: User, password: str | None): """Set password of user if we're in a blueprint context, and if it's an empty string then use an unusable password""" if SERIALIZER_CONTEXT_BLUEPRINT in self.context and password: @@ -143,6 +165,10 @@ class UserSerializer(ModelSerializer): instance.set_unusable_password() instance.save() + def get_avatar(self, user: User) -> str: + """User's avatar, either a http/https URL or a data URI""" + return get_avatar(user, self.context.get("request")) + def validate_path(self, path: str) -> str: """Validate path""" if path[:1] == "/" or path[-1] == "/": @@ -197,12 +223,16 @@ class UserSelfSerializer(ModelSerializer): """User Serializer for information a user can retrieve about themselves""" is_superuser = BooleanField(read_only=True) - avatar = CharField(read_only=True) + avatar = SerializerMethodField() groups = SerializerMethodField() uid = CharField(read_only=True) settings = SerializerMethodField() system_permissions = SerializerMethodField() + def get_avatar(self, user: User) -> str: + """User's avatar, either a http/https URL or a data URI""" + return get_avatar(user, self.context.get("request")) + @extend_schema_field( ListSerializer( child=inline_serializer( @@ -329,11 +359,11 @@ class UsersFilter(FilterSet): groups_by_name = ModelMultipleChoiceFilter( field_name="ak_groups__name", to_field_name="name", - queryset=Group.objects.all(), + queryset=Group.objects.all().order_by("name"), ) groups_by_pk = ModelMultipleChoiceFilter( field_name="ak_groups", - queryset=Group.objects.all(), + queryset=Group.objects.all().order_by("name"), ) def filter_attributes(self, queryset, name, value): @@ -341,7 +371,7 @@ class UsersFilter(FilterSet): try: value = loads(value) except ValueError: - raise ValidationError(detail="filter: failed to parse JSON") + raise ValidationError(detail="filter: failed to parse JSON") from None if not isinstance(value, dict): raise ValidationError(detail="filter: value must be key:value mapping") qs = {} @@ -377,18 +407,28 @@ class UserViewSet(UsedByMixin, ModelViewSet): search_fields = ["username", "name", "is_active", "email", "uuid"] filterset_class = UsersFilter - def get_queryset(self): # pragma: no cover - return User.objects.all().exclude(pk=get_anonymous_user().pk) + def get_queryset(self): + base_qs = User.objects.all().exclude_anonymous() + if self.serializer_class(context={"request": self.request})._should_include_groups: + base_qs = base_qs.prefetch_related("ak_groups") + return base_qs - def _create_recovery_link(self) -> tuple[Optional[str], Optional[Token]]: + @extend_schema( + parameters=[ + OpenApiParameter("include_groups", bool, default=True), + ] + ) + def list(self, request, *args, **kwargs): + return super().list(request, *args, **kwargs) + + def _create_recovery_link(self) -> tuple[str, Token]: """Create a recovery link (when the current brand has a recovery flow set), that can either be shown to an admin or sent to the user directly""" brand: Brand = self.request._request.brand # Check that there is a recovery flow, if not return an error flow = brand.flow_recovery if not flow: - LOGGER.debug("No recovery flow set") - return None, None + raise ValidationError({"non_field_errors": "No recovery flow set."}) user: User = self.get_object() planner = FlowPlanner(flow) planner.allow_empty_flows = True @@ -400,8 +440,9 @@ class UserViewSet(UsedByMixin, ModelViewSet): }, ) except FlowNonApplicableException: - LOGGER.warning("Recovery flow not applicable to user") - return None, None + raise ValidationError( + {"non_field_errors": "Recovery flow not applicable to user"} + ) from None token, __ = FlowToken.objects.update_or_create( identifier=f"{user.uid}-password-reset", defaults={ @@ -516,7 +557,7 @@ class UserViewSet(UsedByMixin, ModelViewSet): 400: OpenApiResponse(description="Bad request"), }, ) - @action(detail=True, methods=["POST"]) + @action(detail=True, methods=["POST"], permission_classes=[]) def set_password(self, request: Request, pk: int) -> Response: """Set password for user""" user: User = self.get_object() @@ -546,16 +587,13 @@ class UserViewSet(UsedByMixin, ModelViewSet): @extend_schema( responses={ "200": LinkSerializer(many=False), - "404": LinkSerializer(many=False), }, + request=None, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[], methods=["POST"]) def recovery(self, request: Request, pk: int) -> Response: """Create a temporary link that a user can use to recover their accounts""" link, _ = self._create_recovery_link() - if not link: - LOGGER.debug("Couldn't create token") - return Response({"link": ""}, status=404) return Response({"link": link}) @permission_required("authentik_core.reset_user_password") @@ -570,31 +608,28 @@ class UserViewSet(UsedByMixin, ModelViewSet): ], responses={ "204": OpenApiResponse(description="Successfully sent recover email"), - "404": OpenApiResponse(description="Bad request"), }, + request=None, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[], methods=["POST"]) def recovery_email(self, request: Request, pk: int) -> Response: """Create a temporary link that a user can use to recover their accounts""" for_user: User = self.get_object() if for_user.email == "": LOGGER.debug("User doesn't have an email address") - return Response(status=404) + raise ValidationError({"non_field_errors": "User does not have an email address set."}) link, token = self._create_recovery_link() - if not link: - LOGGER.debug("Couldn't create token") - return Response(status=404) # Lookup the email stage to assure the current user can access it stages = get_objects_for_user( request.user, "authentik_stages_email.view_emailstage" ).filter(pk=request.query_params.get("email_stage")) if not stages.exists(): LOGGER.debug("Email stage does not exist/user has no permissions") - return Response(status=404) + raise ValidationError({"non_field_errors": "Email stage does not exist."}) email_stage: EmailStage = stages.first() message = TemplateEmailMessage( subject=_(email_stage.subject), - to=[for_user.email], + to=[(for_user.name, for_user.email)], template_name=email_stage.template, language=for_user.locale(request), template_context={ @@ -614,7 +649,7 @@ class UserViewSet(UsedByMixin, ModelViewSet): "401": OpenApiResponse(description="Access denied"), }, ) - @action(detail=True, methods=["POST"]) + @action(detail=True, methods=["POST"], permission_classes=[]) def impersonate(self, request: Request, pk: int) -> Response: """Impersonate a user""" if not request.tenant.impersonation: diff --git a/authentik/core/api/utils.py b/authentik/core/api/utils.py index c79fec22e1..08e4a66f22 100644 --- a/authentik/core/api/utils.py +++ b/authentik/core/api/utils.py @@ -1,12 +1,21 @@ """API Utilities""" + from typing import Any from django.db.models import Model from drf_spectacular.extensions import OpenApiSerializerFieldExtension from drf_spectacular.plumbing import build_basic_type from drf_spectacular.types import OpenApiTypes -from rest_framework.fields import BooleanField, CharField, IntegerField, JSONField -from rest_framework.serializers import Serializer, SerializerMethodField, ValidationError +from rest_framework.fields import ( + CharField, + IntegerField, + JSONField, + SerializerMethodField, +) +from rest_framework.serializers import ( + Serializer, + ValidationError, +) def is_dict(value: Any): @@ -67,16 +76,6 @@ class MetaNameSerializer(PassiveSerializer): return f"{obj._meta.app_label}.{obj._meta.model_name}" -class TypeCreateSerializer(PassiveSerializer): - """Types of an object that can be created""" - - name = CharField(required=True) - description = CharField(required=True) - component = CharField(required=True) - model_name = CharField(required=True) - requires_enterprise = BooleanField(default=False) - - class CacheSerializer(PassiveSerializer): """Generic cache stats for an object""" diff --git a/authentik/core/apps.py b/authentik/core/apps.py index f158cd4a8f..6fff9cb89f 100644 --- a/authentik/core/apps.py +++ b/authentik/core/apps.py @@ -1,4 +1,5 @@ """authentik core app config""" + from django.conf import settings from authentik.blueprints.apps import ManagedAppConfig @@ -13,18 +14,16 @@ class AuthentikCoreConfig(ManagedAppConfig): mountpoint = "" default = True - def reconcile_global_load_core_signals(self): - """Load core signals""" - self.import_module("authentik.core.signals") - - def reconcile_global_debug_worker_hook(self): + @ManagedAppConfig.reconcile_global + def debug_worker_hook(self): """Dispatch startup tasks inline when debugging""" if settings.DEBUG: from authentik.root.celery import worker_ready_hook worker_ready_hook() - def reconcile_tenant_source_inbuilt(self): + @ManagedAppConfig.reconcile_tenant + def source_inbuilt(self): """Reconcile inbuilt source""" from authentik.core.models import Source diff --git a/authentik/core/auth.py b/authentik/core/auth.py index a4ede1387d..4eef71556c 100644 --- a/authentik/core/auth.py +++ b/authentik/core/auth.py @@ -1,6 +1,6 @@ """Authenticate with tokens""" -from typing import Any, Optional +from typing import Any from django.contrib.auth.backends import ModelBackend from django.http.request import HttpRequest @@ -16,23 +16,24 @@ class InbuiltBackend(ModelBackend): """Inbuilt backend""" def authenticate( - self, request: HttpRequest, username: Optional[str], password: Optional[str], **kwargs: Any - ) -> Optional[User]: + self, request: HttpRequest, username: str | None, password: str | None, **kwargs: Any + ) -> User | None: user = super().authenticate(request, username=username, password=password, **kwargs) if not user: return None self.set_method("password", request) return user - def set_method(self, method: str, request: Optional[HttpRequest], **kwargs): + def set_method(self, method: str, request: HttpRequest | None, **kwargs): """Set method data on current flow, if possbiel""" if not request: return # Since we can't directly pass other variables to signals, and we want to log the method # and the token used, we assume we're running in a flow and set a variable in the context flow_plan: FlowPlan = request.session.get(SESSION_KEY_PLAN, FlowPlan("")) - flow_plan.context[PLAN_CONTEXT_METHOD] = method - flow_plan.context[PLAN_CONTEXT_METHOD_ARGS] = cleanse_dict(sanitize_dict(kwargs)) + flow_plan.context.setdefault(PLAN_CONTEXT_METHOD, method) + flow_plan.context.setdefault(PLAN_CONTEXT_METHOD_ARGS, {}) + flow_plan.context[PLAN_CONTEXT_METHOD_ARGS].update(cleanse_dict(sanitize_dict(kwargs))) request.session[SESSION_KEY_PLAN] = flow_plan @@ -40,16 +41,18 @@ class TokenBackend(InbuiltBackend): """Authenticate with token""" def authenticate( - self, request: HttpRequest, username: Optional[str], password: Optional[str], **kwargs: Any - ) -> Optional[User]: + self, request: HttpRequest, username: str | None, password: str | None, **kwargs: Any + ) -> User | None: try: + user = User._default_manager.get_by_natural_key(username) + except User.DoesNotExist: # Run the default password hasher once to reduce the timing # difference between an existing and a nonexistent user (#20760). User().set_password(password) return None - # pylint: disable=no-member + tokens = Token.filter_not_expired( user=user, key=password, intent=TokenIntents.INTENT_APP_PASSWORD ) diff --git a/authentik/core/channels.py b/authentik/core/channels.py index 722e9e03f7..4b0de49aa7 100644 --- a/authentik/core/channels.py +++ b/authentik/core/channels.py @@ -1,4 +1,5 @@ """Channels base classes""" + from channels.db import database_sync_to_async from channels.exceptions import DenyConnection from rest_framework.exceptions import AuthenticationFailed @@ -37,6 +38,6 @@ class TokenOutpostMiddleware: raise DenyConnection() except AuthenticationFailed as exc: LOGGER.warning("Failed to authenticate", exc=exc) - raise DenyConnection() + raise DenyConnection() from None scope["user"] = user diff --git a/authentik/core/exceptions.py b/authentik/core/exceptions.py deleted file mode 100644 index 7b157fc269..0000000000 --- a/authentik/core/exceptions.py +++ /dev/null @@ -1,6 +0,0 @@ -"""authentik core exceptions""" -from authentik.lib.sentry import SentryIgnoredException - - -class PropertyMappingExpressionException(SentryIgnoredException): - """Error when a PropertyMapping Exception expression could not be parsed or evaluated.""" diff --git a/authentik/core/expression/evaluator.py b/authentik/core/expression/evaluator.py index 480caea21b..23ebeffb77 100644 --- a/authentik/core/expression/evaluator.py +++ b/authentik/core/expression/evaluator.py @@ -1,10 +1,13 @@ """Property Mapping Evaluator""" -from typing import Any, Optional + +from types import CodeType +from typing import Any from django.db.models import Model from django.http import HttpRequest from prometheus_client import Histogram +from authentik.core.expression.exceptions import SkipObjectException from authentik.core.models import User from authentik.events.models import Event, EventAction from authentik.lib.expression.evaluator import BaseEvaluator @@ -22,31 +25,43 @@ class PropertyMappingEvaluator(BaseEvaluator): """Custom Evaluator that adds some different context variables.""" dry_run: bool + model: Model + _compiled: CodeType | None = None def __init__( self, model: Model, - user: Optional[User] = None, - request: Optional[HttpRequest] = None, - dry_run: Optional[bool] = False, + user: User | None = None, + request: HttpRequest | None = None, + dry_run: bool | None = False, **kwargs, ): + self.model = model if hasattr(model, "name"): _filename = model.name else: _filename = str(model) super().__init__(filename=_filename) + self.dry_run = dry_run + self.set_context(user, request, **kwargs) + + def set_context( + self, + user: User | None = None, + request: HttpRequest | None = None, + **kwargs, + ): req = PolicyRequest(user=User()) - req.obj = model + req.obj = self.model if user: req.user = user self._context["user"] = user if request: req.http_request = request - self._context["request"] = req req.context.update(**kwargs) + self._context["request"] = req self._context.update(**kwargs) - self.dry_run = dry_run + self._globals["SkipObject"] = SkipObjectException def handle_error(self, exc: Exception, expression_source: str): """Exception Handler""" @@ -68,3 +83,9 @@ class PropertyMappingEvaluator(BaseEvaluator): def evaluate(self, *args, **kwargs) -> Any: with PROPERTY_MAPPING_TIME.labels(mapping_name=self._filename).time(): return super().evaluate(*args, **kwargs) + + def compile(self, expression: str | None = None) -> Any: + if not self._compiled: + compiled = super().compile(expression or self.model.expression) + self._compiled = compiled + return self._compiled diff --git a/authentik/core/expression/exceptions.py b/authentik/core/expression/exceptions.py new file mode 100644 index 0000000000..05571e59f4 --- /dev/null +++ b/authentik/core/expression/exceptions.py @@ -0,0 +1,18 @@ +"""authentik core exceptions""" + +from authentik.lib.sentry import SentryIgnoredException + + +class PropertyMappingExpressionException(SentryIgnoredException): + """Error when a PropertyMapping Exception expression could not be parsed or evaluated.""" + + def __init__(self, exc: Exception, mapping) -> None: + super().__init__() + self.exc = exc + self.mapping = mapping + + +class SkipObjectException(PropertyMappingExpressionException): + """Exception which can be raised in a property mapping to skip syncing an object. + Only applies to Property mappings which sync objects, and not on mappings which transitively + apply to a single user""" diff --git a/authentik/core/management/commands/bootstrap_tasks.py b/authentik/core/management/commands/bootstrap_tasks.py index 89258eaf4c..1038796b9a 100644 --- a/authentik/core/management/commands/bootstrap_tasks.py +++ b/authentik/core/management/commands/bootstrap_tasks.py @@ -1,4 +1,5 @@ """Run bootstrap tasks""" + from django.core.management.base import BaseCommand from django_tenants.utils import get_public_schema_name diff --git a/authentik/core/management/commands/build_source_docs.py b/authentik/core/management/commands/build_source_docs.py index 1c69d5a5f5..d7174f8bc7 100644 --- a/authentik/core/management/commands/build_source_docs.py +++ b/authentik/core/management/commands/build_source_docs.py @@ -1,4 +1,5 @@ """Build source docs""" + from pathlib import Path from django.core.management.base import BaseCommand diff --git a/authentik/core/management/commands/dev_server.py b/authentik/core/management/commands/dev_server.py index ea53167cdb..e9a6af4fa7 100644 --- a/authentik/core/management/commands/dev_server.py +++ b/authentik/core/management/commands/dev_server.py @@ -1,9 +1,34 @@ """custom runserver command""" + +from typing import TextIO + from daphne.management.commands.runserver import Command as RunServer +from daphne.server import Server + +from authentik.root.signals import post_startup, pre_startup, startup + + +class SignalServer(Server): + """Server which signals back to authentik when it finished starting up""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def ready_callable(): + pre_startup.send(sender=self) + startup.send(sender=self) + post_startup.send(sender=self) + + self.ready_callable = ready_callable class Command(RunServer): """custom runserver command, which doesn't show the misleading django startup message""" - def on_bind(self, server_port): - pass + server_cls = SignalServer + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Redirect standard stdout banner from Daphne into the void + # as there are a couple more steps that happen before startup is fully done + self.stdout = TextIO() diff --git a/authentik/core/management/commands/repair_permissions.py b/authentik/core/management/commands/repair_permissions.py index 25200b2ad0..3dfa9b8d7d 100644 --- a/authentik/core/management/commands/repair_permissions.py +++ b/authentik/core/management/commands/repair_permissions.py @@ -1,4 +1,5 @@ """Repair missing permissions""" + from django.apps import apps from django.contrib.auth.management import create_permissions from django.core.management.base import BaseCommand, no_translations diff --git a/authentik/core/management/commands/shell.py b/authentik/core/management/commands/shell.py index dcaf70e9c6..6731069ae3 100644 --- a/authentik/core/management/commands/shell.py +++ b/authentik/core/management/commands/shell.py @@ -1,4 +1,5 @@ """authentik shell command""" + import code import platform import sys @@ -15,13 +16,8 @@ from authentik.events.middleware import should_log_model from authentik.events.models import Event, EventAction from authentik.events.utils import model_to_dict -BANNER_TEXT = """### authentik shell ({authentik}) -### Node {node} | Arch {arch} | Python {python} """.format( - node=platform.node(), - python=platform.python_version(), - arch=platform.machine(), - authentik=get_full_version(), -) +BANNER_TEXT = f"""### authentik shell ({get_full_version()}) +### Node {platform.node()} | Arch {platform.machine()} | Python {platform.python_version()} """ class Command(BaseCommand): @@ -85,7 +81,7 @@ class Command(BaseCommand): # If Python code has been passed, execute it and exit. if options["command"]: - # pylint: disable=exec-used + exec(options["command"], namespace) # nosec # noqa return @@ -98,7 +94,7 @@ class Command(BaseCommand): else: try: hook() - except Exception: # pylint: disable=broad-except + except Exception: # Match the behavior of the cpython shell where an error in # sys.__interactivehook__ prints a warning and the exception # and continues. diff --git a/authentik/core/management/commands/worker.py b/authentik/core/management/commands/worker.py index f85c36cc9e..06d32839b2 100644 --- a/authentik/core/management/commands/worker.py +++ b/authentik/core/management/commands/worker.py @@ -1,4 +1,5 @@ """Run worker""" + from sys import exit as sysexit from tempfile import tempdir diff --git a/authentik/core/middleware.py b/authentik/core/middleware.py index 2cda0b0c39..f59b9aa6b7 100644 --- a/authentik/core/middleware.py +++ b/authentik/core/middleware.py @@ -1,6 +1,7 @@ """authentik admin Middleware to impersonate users""" + +from collections.abc import Callable from contextvars import ContextVar -from typing import Callable, Optional from uuid import uuid4 from django.http import HttpRequest, HttpResponse @@ -14,9 +15,9 @@ RESPONSE_HEADER_ID = "X-authentik-id" KEY_AUTH_VIA = "auth_via" KEY_USER = "user" -CTX_REQUEST_ID = ContextVar[Optional[str]](STRUCTLOG_KEY_PREFIX + "request_id", default=None) -CTX_HOST = ContextVar[Optional[str]](STRUCTLOG_KEY_PREFIX + "host", default=None) -CTX_AUTH_VIA = ContextVar[Optional[str]](STRUCTLOG_KEY_PREFIX + KEY_AUTH_VIA, default=None) +CTX_REQUEST_ID = ContextVar[str | None](STRUCTLOG_KEY_PREFIX + "request_id", default=None) +CTX_HOST = ContextVar[str | None](STRUCTLOG_KEY_PREFIX + "host", default=None) +CTX_AUTH_VIA = ContextVar[str | None](STRUCTLOG_KEY_PREFIX + KEY_AUTH_VIA, default=None) class ImpersonateMiddleware: @@ -54,7 +55,7 @@ class RequestIDMiddleware: def __call__(self, request: HttpRequest) -> HttpResponse: if not hasattr(request, "request_id"): request_id = uuid4().hex - setattr(request, "request_id", request_id) + request.request_id = request_id CTX_REQUEST_ID.set(request_id) CTX_HOST.set(request.get_host()) set_tag("authentik.request_id", request_id) @@ -66,7 +67,7 @@ class RequestIDMiddleware: response = self.get_response(request) response[RESPONSE_HEADER_ID] = request.request_id - setattr(response, "ak_context", {}) + response.ak_context = {} response.ak_context["request_id"] = CTX_REQUEST_ID.get() response.ak_context["host"] = CTX_HOST.get() response.ak_context[KEY_AUTH_VIA] = CTX_AUTH_VIA.get() diff --git a/authentik/core/migrations/0012_auto_20201003_1737_squashed_0016_auto_20201202_2234.py b/authentik/core/migrations/0012_auto_20201003_1737_squashed_0016_auto_20201202_2234.py index 8d1d0dd97f..5b8cb38ab2 100644 --- a/authentik/core/migrations/0012_auto_20201003_1737_squashed_0016_auto_20201202_2234.py +++ b/authentik/core/migrations/0012_auto_20201003_1737_squashed_0016_auto_20201202_2234.py @@ -5,6 +5,7 @@ from django.db import migrations, models from django.db.backends.base.schema import BaseDatabaseSchemaEditor import authentik.core.models +from authentik.lib.generators import generate_id def set_default_token_key(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): @@ -16,6 +17,10 @@ def set_default_token_key(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): token.save() +def default_token_key(): + return generate_id(60) + + class Migration(migrations.Migration): replaces = [ ("authentik_core", "0012_auto_20201003_1737"), @@ -62,7 +67,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name="token", name="key", - field=models.TextField(default=authentik.core.models.default_token_key), + field=models.TextField(default=default_token_key), ), migrations.AlterUniqueTogether( name="token", diff --git a/authentik/core/migrations/0029_provider_backchannel_applications_and_more.py b/authentik/core/migrations/0029_provider_backchannel_applications_and_more.py index f34c59ccbd..d6245df749 100644 --- a/authentik/core/migrations/0029_provider_backchannel_applications_and_more.py +++ b/authentik/core/migrations/0029_provider_backchannel_applications_and_more.py @@ -7,9 +7,10 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor def backport_is_backchannel(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): - from authentik.core.models import BackchannelProvider + from authentik.providers.ldap.models import LDAPProvider + from authentik.providers.scim.models import SCIMProvider - for model in BackchannelProvider.__subclasses__(): + for model in [LDAPProvider, SCIMProvider]: try: for obj in model.objects.only("is_backchannel"): obj.is_backchannel = True diff --git a/authentik/core/migrations/0033_alter_user_options.py b/authentik/core/migrations/0033_alter_user_options.py new file mode 100644 index 0000000000..89893251ae --- /dev/null +++ b/authentik/core/migrations/0033_alter_user_options.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.1 on 2024-01-29 12:50 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("authentik_core", "0032_group_roles"), + ] + + operations = [ + migrations.AlterModelOptions( + name="user", + options={ + "permissions": [ + ("reset_user_password", "Reset Password"), + ("impersonate", "Can impersonate other users"), + ("assign_user_permissions", "Can assign permissions to users"), + ("unassign_user_permissions", "Can unassign permissions from users"), + ("preview_user", "Can preview user data sent to providers"), + ("view_user_applications", "View applications the user has access to"), + ], + "verbose_name": "User", + "verbose_name_plural": "Users", + }, + ), + ] diff --git a/authentik/core/migrations/0034_alter_authenticatedsession_expires_and_more.py b/authentik/core/migrations/0034_alter_authenticatedsession_expires_and_more.py new file mode 100644 index 0000000000..dd62bcf852 --- /dev/null +++ b/authentik/core/migrations/0034_alter_authenticatedsession_expires_and_more.py @@ -0,0 +1,31 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + +import authentik.core.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_core", "0033_alter_user_options"), + ("authentik_tenants", "0002_tenant_default_token_duration_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="authenticatedsession", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + migrations.AlterField( + model_name="token", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + migrations.AlterField( + model_name="token", + name="key", + field=models.TextField(default=authentik.core.models.default_token_key), + ), + ] diff --git a/authentik/core/migrations/0035_alter_group_options_and_more.py b/authentik/core/migrations/0035_alter_group_options_and_more.py new file mode 100644 index 0000000000..f48091c70c --- /dev/null +++ b/authentik/core/migrations/0035_alter_group_options_and_more.py @@ -0,0 +1,52 @@ +# Generated by Django 5.0.4 on 2024-04-15 11:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ("authentik_core", "0034_alter_authenticatedsession_expires_and_more"), + ("authentik_rbac", "0003_alter_systempermission_options"), + ] + + operations = [ + migrations.AlterModelOptions( + name="group", + options={ + "permissions": [ + ("add_user_to_group", "Add user to group"), + ("remove_user_from_group", "Remove user from group"), + ], + "verbose_name": "Group", + "verbose_name_plural": "Groups", + }, + ), + migrations.AddIndex( + model_name="group", + index=models.Index(fields=["name"], name="authentik_c_name_9ba8e4_idx"), + ), + migrations.AddIndex( + model_name="user", + index=models.Index(fields=["last_login"], name="authentik_c_last_lo_f0179a_idx"), + ), + migrations.AddIndex( + model_name="user", + index=models.Index( + fields=["password_change_date"], name="authentik_c_passwor_eec915_idx" + ), + ), + migrations.AddIndex( + model_name="user", + index=models.Index(fields=["uuid"], name="authentik_c_uuid_3dae2f_idx"), + ), + migrations.AddIndex( + model_name="user", + index=models.Index(fields=["path"], name="authentik_c_path_b1f502_idx"), + ), + migrations.AddIndex( + model_name="user", + index=models.Index(fields=["type"], name="authentik_c_type_ecf60d_idx"), + ), + ] diff --git a/authentik/core/models.py b/authentik/core/models.py index 6c2d5e34fb..67a6710c25 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -1,5 +1,6 @@ """authentik core models""" -from datetime import timedelta + +from datetime import datetime from hashlib import sha256 from typing import Any, Optional, Self from uuid import uuid4 @@ -14,24 +15,26 @@ from django.http import HttpRequest from django.utils.functional import SimpleLazyObject, cached_property from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ +from guardian.conf import settings from guardian.mixins import GuardianUserMixin from model_utils.managers import InheritanceManager from rest_framework.serializers import Serializer from structlog.stdlib import get_logger from authentik.blueprints.models import ManagedModel -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.lib.avatars import get_avatar -from authentik.lib.config import CONFIG from authentik.lib.generators import generate_id from authentik.lib.models import ( CreatedUpdatedModel, DomainlessFormattedURLValidator, SerializerModel, ) +from authentik.lib.utils.time import timedelta_from_string from authentik.policies.models import PolicyBindingModel -from authentik.root.install_id import get_install_id +from authentik.tenants.models import DEFAULT_TOKEN_DURATION, DEFAULT_TOKEN_LENGTH +from authentik.tenants.utils import get_current_tenant, get_unique_identifier LOGGER = get_logger() USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug" @@ -40,33 +43,42 @@ USER_ATTRIBUTE_EXPIRES = "goauthentik.io/user/expires" USER_ATTRIBUTE_DELETE_ON_LOGOUT = "goauthentik.io/user/delete-on-logout" USER_ATTRIBUTE_SOURCES = "goauthentik.io/user/sources" USER_ATTRIBUTE_TOKEN_EXPIRING = "goauthentik.io/user/token-expires" # nosec +USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME = "goauthentik.io/user/token-maximum-lifetime" # nosec USER_ATTRIBUTE_CHANGE_USERNAME = "goauthentik.io/user/can-change-username" USER_ATTRIBUTE_CHANGE_NAME = "goauthentik.io/user/can-change-name" USER_ATTRIBUTE_CHANGE_EMAIL = "goauthentik.io/user/can-change-email" USER_PATH_SYSTEM_PREFIX = "goauthentik.io" USER_PATH_SERVICE_ACCOUNT = USER_PATH_SYSTEM_PREFIX + "/service-accounts" - options.DEFAULT_NAMES = options.DEFAULT_NAMES + ( # used_by API that allows models to specify if they shadow an object # for example the proxy provider which is built on top of an oauth provider "authentik_used_by_shadows", - # List fields for which changes are not logged (due to them having dedicated objects) - # for example user's password and last_login - "authentik_signals_ignored_fields", ) -def default_token_duration(): +def default_token_duration() -> datetime: """Default duration a Token is valid""" - return now() + timedelta(minutes=30) + current_tenant = get_current_tenant() + token_duration = ( + current_tenant.default_token_duration + if hasattr(current_tenant, "default_token_duration") + else DEFAULT_TOKEN_DURATION + ) + return now() + timedelta_from_string(token_duration) -def default_token_key(): +def default_token_key() -> str: """Default token key""" + current_tenant = get_current_tenant() + token_length = ( + current_tenant.default_token_length + if hasattr(current_tenant, "default_token_length") + else DEFAULT_TOKEN_LENGTH + ) # We use generate_id since the chars in the key should be easy # to use in Emails (for verification) and URLs (for recovery) - return generate_id(CONFIG.get_int("default_token_length")) + return generate_id(token_length) class UserTypes(models.TextChoices): @@ -165,17 +177,38 @@ class Group(SerializerModel): "parent", ), ) + indexes = [models.Index(fields=["name"])] verbose_name = _("Group") verbose_name_plural = _("Groups") + permissions = [ + ("add_user_to_group", _("Add user to group")), + ("remove_user_from_group", _("Remove user from group")), + ] + + +class UserQuerySet(models.QuerySet): + """User queryset""" + + def exclude_anonymous(self): + """Exclude anonymous user""" + return self.exclude(**{User.USERNAME_FIELD: settings.ANONYMOUS_USER_NAME}) class UserManager(DjangoUserManager): """User manager that doesn't assign is_superuser and is_staff""" + def get_queryset(self): + """Create special user queryset""" + return UserQuerySet(self.model, using=self._db) + def create_user(self, username, email=None, password=None, **extra_fields): """User manager that doesn't assign is_superuser and is_staff""" return self._create_user(username, email, password, **extra_fields) + def exclude_anonymous(self) -> QuerySet: + """Exclude anonymous user""" + return self.get_queryset().exclude_anonymous() + class User(SerializerModel, GuardianUserMixin, AbstractUser): """authentik User model, based on django's contrib auth user model.""" @@ -204,7 +237,7 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser): there are at most 3 queries done""" return Group.children_recursive(self.ak_groups.all()) - def group_attributes(self, request: Optional[HttpRequest] = None) -> dict[str, Any]: + def group_attributes(self, request: HttpRequest | None = None) -> dict[str, Any]: """Get a dictionary containing the attributes from all groups the user belongs to, including the users attributes""" final_attributes = {} @@ -258,13 +291,13 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser): @property def uid(self) -> str: """Generate a globally unique UID, based on the user ID and the hashed secret key""" - return sha256(f"{self.id}-{get_install_id()}".encode("ascii")).hexdigest() + return sha256(f"{self.id}-{get_unique_identifier()}".encode("ascii")).hexdigest() - def locale(self, request: Optional[HttpRequest] = None) -> str: + def locale(self, request: HttpRequest | None = None) -> str: """Get the locale the user has configured""" try: return self.attributes.get("settings", {}).get("locale", "") - # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Failed to get default locale", exc=exc) if request: @@ -284,14 +317,15 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser): ("impersonate", _("Can impersonate other users")), ("assign_user_permissions", _("Can assign permissions to users")), ("unassign_user_permissions", _("Can unassign permissions from users")), + ("preview_user", _("Can preview user data sent to providers")), + ("view_user_applications", _("View applications the user has access to")), ] - authentik_signals_ignored_fields = [ - # Logged by the events `password_set` - # the `password_set` action/signal doesn't currently convey which user - # initiated the password change, so for now we'll log two actions - # ("password", "password_change_date"), - # Logged by `login` - ("last_login",), + indexes = [ + models.Index(fields=["last_login"]), + models.Index(fields=["password_change_date"]), + models.Index(fields=["uuid"]), + models.Index(fields=["path"]), + models.Index(fields=["type"]), ] @@ -338,11 +372,15 @@ class Provider(SerializerModel): objects = InheritanceManager() @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """URL to this provider and initiate authorization for the user. Can return None for providers that are not URL-based""" return None + @property + def icon_url(self) -> str | None: + return None + @property def component(self) -> str: """Return component used to edit this object""" @@ -415,7 +453,7 @@ class Application(SerializerModel, PolicyBindingModel): return ApplicationSerializer @property - def get_meta_icon(self) -> Optional[str]: + def get_meta_icon(self) -> str | None: """Get the URL to the App Icon image. If the name is /static or starts with http it is returned as-is""" if not self.meta_icon: @@ -424,7 +462,7 @@ class Application(SerializerModel, PolicyBindingModel): return self.meta_icon.name return self.meta_icon.url - def get_launch_url(self, user: Optional["User"] = None) -> Optional[str]: + def get_launch_url(self, user: Optional["User"] = None) -> str | None: """Get launch URL if set, otherwise attempt to get launch URL based on provider.""" url = None if self.meta_launch_url: @@ -437,13 +475,13 @@ class Application(SerializerModel, PolicyBindingModel): user = user._wrapped try: return url % user.__dict__ - # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Failed to format launch url", exc=exc) return url return url - def get_provider(self) -> Optional[Provider]: + def get_provider(self) -> Provider | None: """Get casted provider instance""" if not self.provider: return None @@ -531,7 +569,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel): objects = InheritanceManager() @property - def icon_url(self) -> Optional[str]: + def icon_url(self) -> str | None: """Get the URL to the Icon. If the name is /static or starts with http it is returned as-is""" if not self.icon: @@ -546,7 +584,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel): return self.user_path_template % { "slug": self.slug, } - # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Failed to template user path", exc=exc, source=self) return User.default_path() @@ -556,12 +594,12 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel): """Return component used to edit this object""" raise NotImplementedError - def ui_login_button(self, request: HttpRequest) -> Optional[UILoginButton]: + def ui_login_button(self, request: HttpRequest) -> UILoginButton | None: """If source uses a http-based flow, return UI Information about the login button. If source doesn't use http-based flow, return None.""" return None - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: """Entrypoint to integrate with User settings. Can either return None if no user settings are available, or UserSettingSerializer.""" return None @@ -597,6 +635,9 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel): """Get serializer for this model""" raise NotImplementedError + def __str__(self) -> str: + return f"User-source connection (user={self.user_id}, source={self.source_id})" + class Meta: unique_together = (("user", "source"),) @@ -604,9 +645,12 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel): class ExpiringModel(models.Model): """Base Model which can expire, and is automatically cleaned up.""" - expires = models.DateTimeField(default=default_token_duration) + expires = models.DateTimeField(default=None, null=True) expiring = models.BooleanField(default=True) + class Meta: + abstract = True + def expire_action(self, *args, **kwargs): """Handler which is called when this object is expired. By default the object is deleted. This is less efficient compared @@ -615,7 +659,7 @@ class ExpiringModel(models.Model): return self.delete(*args, **kwargs) @classmethod - def filter_not_expired(cls, **kwargs) -> QuerySet: + def filter_not_expired(cls, **kwargs) -> QuerySet["Token"]: """Filer for tokens which are not expired yet or are not expiring, and match filters in `kwargs`""" for obj in cls.objects.filter(**kwargs).filter(Q(expires__lt=now(), expiring=True)): @@ -629,9 +673,6 @@ class ExpiringModel(models.Model): return False return now() > self.expires - class Meta: - abstract = True - class TokenIntents(models.TextChoices): """Intents a Token can be created for.""" @@ -661,6 +702,21 @@ class Token(SerializerModel, ManagedModel, ExpiringModel): user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+") description = models.TextField(default="", blank=True) + class Meta: + verbose_name = _("Token") + verbose_name_plural = _("Tokens") + indexes = [ + models.Index(fields=["identifier"]), + models.Index(fields=["key"]), + ] + permissions = [("view_token_key", _("View token's key"))] + + def __str__(self): + description = f"{self.identifier}" + if self.expiring: + description += f" (expires={self.expires})" + return description + @property def serializer(self) -> type[Serializer]: from authentik.core.api.tokens import TokenSerializer @@ -688,21 +744,6 @@ class Token(SerializerModel, ManagedModel, ExpiringModel): message=f"Token {self.identifier}'s secret was rotated.", ).save() - def __str__(self): - description = f"{self.identifier}" - if self.expiring: - description += f" (expires={self.expires})" - return description - - class Meta: - verbose_name = _("Token") - verbose_name_plural = _("Tokens") - indexes = [ - models.Index(fields=["identifier"]), - models.Index(fields=["key"]), - ] - permissions = [("view_token_key", _("View token's key"))] - class PropertyMapping(SerializerModel, ManagedModel): """User-defined key -> x mapping which can be used by providers to expose extra data.""" @@ -723,7 +764,7 @@ class PropertyMapping(SerializerModel, ManagedModel): """Get serializer for this model""" raise NotImplementedError - def evaluate(self, user: Optional[User], request: Optional[HttpRequest], **kwargs) -> Any: + def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any: """Evaluate `self.expression` using `**kwargs` as Context.""" from authentik.core.expression.evaluator import PropertyMappingEvaluator @@ -731,7 +772,7 @@ class PropertyMapping(SerializerModel, ManagedModel): try: return evaluator.evaluate(self.expression) except Exception as exc: - raise PropertyMappingExpressionException(exc) from exc + raise PropertyMappingExpressionException(self, exc) from exc def __str__(self): return f"Property Mapping {self.name}" @@ -759,6 +800,13 @@ class AuthenticatedSession(ExpiringModel): last_user_agent = models.TextField(blank=True) last_used = models.DateTimeField(auto_now=True) + class Meta: + verbose_name = _("Authenticated Session") + verbose_name_plural = _("Authenticated Sessions") + + def __str__(self) -> str: + return f"Authenticated Session {self.session_key[:10]}" + @staticmethod def from_request(request: HttpRequest, user: User) -> Optional["AuthenticatedSession"]: """Create a new session from a http request""" @@ -773,7 +821,3 @@ class AuthenticatedSession(ExpiringModel): last_user_agent=request.META.get("HTTP_USER_AGENT", ""), expires=request.session.get_expiry_date(), ) - - class Meta: - verbose_name = _("Authenticated Session") - verbose_name_plural = _("Authenticated Sessions") diff --git a/authentik/core/signals.py b/authentik/core/signals.py index 31340fce91..228d59ce4c 100644 --- a/authentik/core/signals.py +++ b/authentik/core/signals.py @@ -1,4 +1,5 @@ """authentik core signals""" + from django.contrib.auth.signals import user_logged_in, user_logged_out from django.contrib.sessions.backends.cache import KEY_PREFIX from django.core.cache import cache @@ -9,7 +10,14 @@ from django.dispatch import receiver from django.http.request import HttpRequest from structlog.stdlib import get_logger -from authentik.core.models import Application, AuthenticatedSession, BackchannelProvider, User +from authentik.core.models import ( + Application, + AuthenticatedSession, + BackchannelProvider, + ExpiringModel, + User, + default_token_duration, +) # Arguments: user: User, password: str password_changed = Signal() @@ -60,3 +68,12 @@ def backchannel_provider_pre_save(sender: type[Model], instance: Model, **_): if not isinstance(instance, BackchannelProvider): return instance.is_backchannel = True + + +@receiver(pre_save) +def expiring_model_pre_save(sender: type[Model], instance: Model, **_): + """Ensure expires is set on ExpiringModels that are set to expire""" + if not issubclass(sender, ExpiringModel): + return + if instance.expiring and instance.expires is None: + instance.expires = default_token_duration() diff --git a/authentik/core/sources/flow_manager.py b/authentik/core/sources/flow_manager.py index 0fb038d909..ce55611d18 100644 --- a/authentik/core/sources/flow_manager.py +++ b/authentik/core/sources/flow_manager.py @@ -1,6 +1,7 @@ """Source decision helper""" + from enum import Enum -from typing import Any, Optional +from typing import Any from django.contrib import messages from django.db import IntegrityError @@ -12,11 +13,12 @@ from django.utils.translation import gettext as _ from structlog.stdlib import get_logger from authentik.core.models import Source, SourceUserMatchingModes, User, UserSourceConnection -from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION, PostUserEnrollmentStage +from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION, PostSourceStage from authentik.events.models import Event, EventAction from authentik.flows.exceptions import FlowNonApplicableException -from authentik.flows.models import Flow, Stage, in_memory_stage +from authentik.flows.models import Flow, FlowToken, Stage, in_memory_stage from authentik.flows.planner import ( + PLAN_CONTEXT_IS_RESTORED, PLAN_CONTEXT_PENDING_USER, PLAN_CONTEXT_REDIRECT, PLAN_CONTEXT_SOURCE, @@ -34,6 +36,8 @@ from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT from authentik.stages.user_write.stage import PLAN_CONTEXT_USER_PATH +SESSION_KEY_OVERRIDE_FLOW_TOKEN = "authentik/flows/source_override_flow_token" # nosec + class Action(Enum): """Actions that can be decided based on the request @@ -89,16 +93,13 @@ class SourceFlowManager: self._logger = get_logger().bind(source=source, identifier=identifier) self.policy_context = {} - # pylint: disable=too-many-return-statements - def get_action(self, **kwargs) -> tuple[Action, Optional[UserSourceConnection]]: + def get_action(self, **kwargs) -> tuple[Action, UserSourceConnection | None]: # noqa: PLR0911 """decide which action should be taken""" new_connection = self.connection_type(source=self.source, identifier=self.identifier) # When request is authenticated, always link if self.request.user.is_authenticated: new_connection.user = self.request.user new_connection = self.update_connection(new_connection, **kwargs) - # pylint: disable=no-member - new_connection.save() return Action.LINK, new_connection existing_connections = self.connection_type.objects.filter( @@ -145,7 +146,6 @@ class SourceFlowManager: ]: new_connection.user = user new_connection = self.update_connection(new_connection, **kwargs) - new_connection.save() return Action.LINK, new_connection if self.source.user_matching_mode in [ SourceUserMatchingModes.EMAIL_DENY, @@ -187,8 +187,10 @@ class SourceFlowManager: # Default case, assume deny error = Exception( _( - "Request to authenticate with %(source)s has been denied. Please authenticate " - "with the source you've previously signed up with." % {"source": self.source.name} + "Request to authenticate with {source} has been denied. Please authenticate " + "with the source you've previously signed up with.".format_map( + {"source": self.source.name} + ) ), ) return self.error_handler(error) @@ -204,38 +206,55 @@ class SourceFlowManager: def get_stages_to_append(self, flow: Flow) -> list[Stage]: """Hook to override stages which are appended to the flow""" - if not self.source.enrollment_flow: - return [] - if flow.slug == self.source.enrollment_flow.slug: - return [ - in_memory_stage(PostUserEnrollmentStage), - ] - return [] + return [ + in_memory_stage(PostSourceStage), + ] def _prepare_flow( self, flow: Flow, connection: UserSourceConnection, - stages: Optional[list[StageView]] = None, + stages: list[StageView] | None = None, **kwargs, ) -> HttpResponse: """Prepare Authentication Plan, redirect user FlowExecutor""" - # Ensure redirect is carried through when user was trying to - # authorize application - final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get( - NEXT_ARG_NAME, "authentik_core:if-user" - ) kwargs.update( { # Since we authenticate the user by their token, they have no backend set PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_INBUILT, PLAN_CONTEXT_SSO: True, PLAN_CONTEXT_SOURCE: self.source, - PLAN_CONTEXT_REDIRECT: final_redirect, PLAN_CONTEXT_SOURCES_CONNECTION: connection, } ) kwargs.update(self.policy_context) + if SESSION_KEY_OVERRIDE_FLOW_TOKEN in self.request.session: + token: FlowToken = self.request.session.get(SESSION_KEY_OVERRIDE_FLOW_TOKEN) + self._logger.info("Replacing source flow with overridden flow", flow=token.flow.slug) + plan = token.plan + plan.context[PLAN_CONTEXT_IS_RESTORED] = token + plan.context.update(kwargs) + for stage in self.get_stages_to_append(flow): + plan.append_stage(stage) + if stages: + for stage in stages: + plan.append_stage(stage) + self.request.session[SESSION_KEY_PLAN] = plan + flow_slug = token.flow.slug + token.delete() + return redirect_with_qs( + "authentik_core:if-flow", + self.request.GET, + flow_slug=flow_slug, + ) + # Ensure redirect is carried through when user was trying to + # authorize application + final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get( + NEXT_ARG_NAME, "authentik_core:if-user" + ) + if PLAN_CONTEXT_REDIRECT not in kwargs: + kwargs[PLAN_CONTEXT_REDIRECT] = final_redirect + if not flow: return bad_request_message( self.request, @@ -243,6 +262,9 @@ class SourceFlowManager: ) # We run the Flow planner here so we can pass the Pending user in the context planner = FlowPlanner(flow) + # We append some stages so the initial flow we get might be empty + planner.allow_empty_flows = True + planner.use_cache = False plan = planner.plan(self.request, kwargs) for stage in self.get_stages_to_append(flow): plan.append_stage(stage) @@ -269,7 +291,9 @@ class SourceFlowManager: in_memory_stage( MessageStage, message=_( - "Successfully authenticated with %(source)s!" % {"source": self.source.name} + "Successfully authenticated with {source}!".format_map( + {"source": self.source.name} + ) ), ) ], @@ -293,13 +317,13 @@ class SourceFlowManager: ).from_http(self.request) messages.success( self.request, - _("Successfully linked %(source)s!" % {"source": self.source.name}), + _("Successfully linked {source}!".format_map({"source": self.source.name})), ) return redirect( reverse( "authentik_core:if-user", ) - + f"#/settings;page-{self.source.slug}" + + "#/settings;page-sources" ) def handle_enroll( @@ -321,7 +345,9 @@ class SourceFlowManager: in_memory_stage( MessageStage, message=_( - "Successfully authenticated with %(source)s!" % {"source": self.source.name} + "Successfully authenticated with {source}!".format_map( + {"source": self.source.name} + ) ), ) ], diff --git a/authentik/core/sources/stage.py b/authentik/core/sources/stage.py index 385db38922..de863f1982 100644 --- a/authentik/core/sources/stage.py +++ b/authentik/core/sources/stage.py @@ -1,4 +1,5 @@ """Source flow manager stages""" + from django.http import HttpRequest, HttpResponse from authentik.core.models import User, UserSourceConnection @@ -9,7 +10,7 @@ from authentik.flows.stage import StageView PLAN_CONTEXT_SOURCES_CONNECTION = "goauthentik.io/sources/connection" -class PostUserEnrollmentStage(StageView): +class PostSourceStage(StageView): """Dynamically injected stage which saves the Connection after the user has been enrolled.""" @@ -20,10 +21,12 @@ class PostUserEnrollmentStage(StageView): ] user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] connection.user = user + linked = connection.pk is None connection.save() - Event.new( - EventAction.SOURCE_LINKED, - message="Linked Source", - source=connection.source, - ).from_http(self.request) + if linked: + Event.new( + EventAction.SOURCE_LINKED, + message="Linked Source", + source=connection.source, + ).from_http(self.request) return self.executor.stage_ok() diff --git a/authentik/core/tasks.py b/authentik/core/tasks.py index c3cd5df374..1a565d8f7f 100644 --- a/authentik/core/tasks.py +++ b/authentik/core/tasks.py @@ -1,7 +1,10 @@ """authentik core tasks""" + from datetime import datetime, timedelta +from django.conf import ImproperlyConfigured from django.contrib.sessions.backends.cache import KEY_PREFIX +from django.contrib.sessions.backends.db import SessionStore as DBSessionStore from django.core.cache import cache from django.utils.timezone import now from structlog.stdlib import get_logger @@ -14,6 +17,7 @@ from authentik.core.models import ( User, ) from authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task +from authentik.lib.config import CONFIG from authentik.root.celery import CELERY_APP LOGGER = get_logger() @@ -36,18 +40,35 @@ def clean_expired_models(self: SystemTask): messages.append(f"Expired {amount} {cls._meta.verbose_name_plural}") # Special case amount = 0 + for session in AuthenticatedSession.objects.all(): - cache_key = f"{KEY_PREFIX}{session.session_key}" - value = None - try: - value = cache.get(cache_key) - # pylint: disable=broad-except - except Exception as exc: - LOGGER.debug("Failed to get session from cache", exc=exc) - if not value: - session.delete() - amount += 1 + match CONFIG.get("session_storage", "cache"): + case "cache": + cache_key = f"{KEY_PREFIX}{session.session_key}" + value = None + try: + value = cache.get(cache_key) + + except Exception as exc: + LOGGER.debug("Failed to get session from cache", exc=exc) + if not value: + session.delete() + amount += 1 + case "db": + if not ( + DBSessionStore.get_model_class() + .objects.filter(session_key=session.session_key, expire_date__gt=now()) + .exists() + ): + session.delete() + amount += 1 + case _: + # Should never happen, as we check for other values in authentik/root/settings.py + raise ImproperlyConfigured( + "Invalid session_storage setting, allowed values are db and cache" + ) LOGGER.debug("Expired sessions", model=AuthenticatedSession, amount=amount) + messages.append(f"Expired {amount} {AuthenticatedSession._meta.verbose_name_plural}") self.set_status(TaskStatus.SUCCESSFUL, *messages) diff --git a/authentik/core/tests/test_api_utils.py b/authentik/core/tests/test_api_utils.py index 00736de28c..25a317ebd1 100644 --- a/authentik/core/tests/test_api_utils.py +++ b/authentik/core/tests/test_api_utils.py @@ -1,4 +1,5 @@ """Test API Utils""" + from rest_framework.exceptions import ValidationError from rest_framework.test import APITestCase diff --git a/authentik/core/tests/test_applications_api.py b/authentik/core/tests/test_applications_api.py index 2bed87237e..6e970b2079 100644 --- a/authentik/core/tests/test_applications_api.py +++ b/authentik/core/tests/test_applications_api.py @@ -1,4 +1,5 @@ """Test Applications API""" + from json import loads from django.core.files.base import ContentFile diff --git a/authentik/core/tests/test_applications_views.py b/authentik/core/tests/test_applications_views.py index d71e8406ba..248a595428 100644 --- a/authentik/core/tests/test_applications_views.py +++ b/authentik/core/tests/test_applications_views.py @@ -1,4 +1,5 @@ """Test Applications API""" + from unittest.mock import MagicMock, patch from django.urls import reverse diff --git a/authentik/core/tests/test_authenticated_sessions_api.py b/authentik/core/tests/test_authenticated_sessions_api.py index 51430346bc..a079dd5f84 100644 --- a/authentik/core/tests/test_authenticated_sessions_api.py +++ b/authentik/core/tests/test_authenticated_sessions_api.py @@ -1,4 +1,5 @@ """Test AuthenticatedSessions API""" + from json import loads from django.urls.base import reverse diff --git a/authentik/core/tests/test_groups.py b/authentik/core/tests/test_groups.py index 65a0cc3e60..fa60e6d8ba 100644 --- a/authentik/core/tests/test_groups.py +++ b/authentik/core/tests/test_groups.py @@ -1,4 +1,5 @@ """group tests""" + from django.test.testcases import TestCase from authentik.core.models import Group, User diff --git a/authentik/core/tests/test_groups_api.py b/authentik/core/tests/test_groups_api.py index cff643f5a7..eb31bf4095 100644 --- a/authentik/core/tests/test_groups_api.py +++ b/authentik/core/tests/test_groups_api.py @@ -1,9 +1,11 @@ """Test Groups API""" + from django.urls.base import reverse +from guardian.shortcuts import assign_perm from rest_framework.test import APITestCase from authentik.core.models import Group, User -from authentik.core.tests.utils import create_test_admin_user +from authentik.core.tests.utils import create_test_admin_user, create_test_user from authentik.lib.generators import generate_id @@ -11,13 +13,33 @@ class TestGroupsAPI(APITestCase): """Test Groups API""" def setUp(self) -> None: - self.admin = create_test_admin_user() + self.login_user = create_test_user() self.user = User.objects.create(username="test-user") + def test_list_with_users(self): + """Test listing with users""" + admin = create_test_admin_user() + self.client.force_login(admin) + response = self.client.get(reverse("authentik_api:group-list"), {"include_users": "true"}) + self.assertEqual(response.status_code, 200) + + def test_retrieve_with_users(self): + """Test retrieve with users""" + admin = create_test_admin_user() + group = Group.objects.create(name=generate_id()) + self.client.force_login(admin) + response = self.client.get( + reverse("authentik_api:group-detail", kwargs={"pk": group.pk}), + {"include_users": "true"}, + ) + self.assertEqual(response.status_code, 200) + def test_add_user(self): """Test add_user""" group = Group.objects.create(name=generate_id()) - self.client.force_login(self.admin) + assign_perm("authentik_core.add_user_to_group", self.login_user, group) + assign_perm("authentik_core.view_user", self.login_user) + self.client.force_login(self.login_user) res = self.client.post( reverse("authentik_api:group-add-user", kwargs={"pk": group.pk}), data={ @@ -31,7 +53,9 @@ class TestGroupsAPI(APITestCase): def test_add_user_404(self): """Test add_user""" group = Group.objects.create(name=generate_id()) - self.client.force_login(self.admin) + assign_perm("authentik_core.add_user_to_group", self.login_user, group) + assign_perm("authentik_core.view_user", self.login_user) + self.client.force_login(self.login_user) res = self.client.post( reverse("authentik_api:group-add-user", kwargs={"pk": group.pk}), data={ @@ -43,8 +67,10 @@ class TestGroupsAPI(APITestCase): def test_remove_user(self): """Test remove_user""" group = Group.objects.create(name=generate_id()) + assign_perm("authentik_core.remove_user_from_group", self.login_user, group) + assign_perm("authentik_core.view_user", self.login_user) group.users.add(self.user) - self.client.force_login(self.admin) + self.client.force_login(self.login_user) res = self.client.post( reverse("authentik_api:group-remove-user", kwargs={"pk": group.pk}), data={ @@ -58,8 +84,10 @@ class TestGroupsAPI(APITestCase): def test_remove_user_404(self): """Test remove_user""" group = Group.objects.create(name=generate_id()) + assign_perm("authentik_core.remove_user_from_group", self.login_user, group) + assign_perm("authentik_core.view_user", self.login_user) group.users.add(self.user) - self.client.force_login(self.admin) + self.client.force_login(self.login_user) res = self.client.post( reverse("authentik_api:group-remove-user", kwargs={"pk": group.pk}), data={ @@ -71,11 +99,12 @@ class TestGroupsAPI(APITestCase): def test_parent_self(self): """Test parent""" group = Group.objects.create(name=generate_id()) - self.client.force_login(self.admin) + assign_perm("view_group", self.login_user, group) + assign_perm("change_group", self.login_user, group) + self.client.force_login(self.login_user) res = self.client.patch( reverse("authentik_api:group-detail", kwargs={"pk": group.pk}), data={ - "pk": self.user.pk + 3, "parent": group.pk, }, ) diff --git a/authentik/core/tests/test_impersonation.py b/authentik/core/tests/test_impersonation.py index 4411fbfe7a..ad3fba32be 100644 --- a/authentik/core/tests/test_impersonation.py +++ b/authentik/core/tests/test_impersonation.py @@ -1,4 +1,5 @@ """impersonation tests""" + from json import loads from django.urls import reverse diff --git a/authentik/core/tests/test_models.py b/authentik/core/tests/test_models.py index a08dbb5af6..6f95fcce9e 100644 --- a/authentik/core/tests/test_models.py +++ b/authentik/core/tests/test_models.py @@ -1,13 +1,14 @@ """authentik core models tests""" -from time import sleep -from typing import Callable + +from collections.abc import Callable +from datetime import timedelta from django.test import RequestFactory, TestCase from django.utils.timezone import now +from freezegun import freeze_time from guardian.shortcuts import get_anonymous_user from authentik.core.models import Provider, Source, Token -from authentik.flows.models import Stage from authentik.lib.utils.reflection import all_subclasses @@ -16,18 +17,20 @@ class TestModels(TestCase): def test_token_expire(self): """Test token expiring""" - token = Token.objects.create(expires=now(), user=get_anonymous_user()) - sleep(0.5) - self.assertTrue(token.is_expired) + with freeze_time() as freeze: + token = Token.objects.create(expires=now(), user=get_anonymous_user()) + freeze.tick(timedelta(seconds=1)) + self.assertTrue(token.is_expired) def test_token_expire_no_expire(self): """Test token expiring with "expiring" set""" - token = Token.objects.create(expires=now(), user=get_anonymous_user(), expiring=False) - sleep(0.5) - self.assertFalse(token.is_expired) + with freeze_time() as freeze: + token = Token.objects.create(expires=now(), user=get_anonymous_user(), expiring=False) + freeze.tick(timedelta(seconds=1)) + self.assertFalse(token.is_expired) -def source_tester_factory(test_model: type[Stage]) -> Callable: +def source_tester_factory(test_model: type[Source]) -> Callable: """Test source""" factory = RequestFactory() @@ -35,19 +38,19 @@ def source_tester_factory(test_model: type[Stage]) -> Callable: def tester(self: TestModels): model_class = None - if test_model._meta.abstract: # pragma: no cover - model_class = test_model.__bases__[0]() + if test_model._meta.abstract: + model_class = [x for x in test_model.__bases__ if issubclass(x, Source)][0]() else: model_class = test_model() model_class.slug = "test" self.assertIsNotNone(model_class.component) - _ = model_class.ui_login_button(request) - _ = model_class.ui_user_settings() + model_class.ui_login_button(request) + model_class.ui_user_settings() return tester -def provider_tester_factory(test_model: type[Stage]) -> Callable: +def provider_tester_factory(test_model: type[Provider]) -> Callable: """Test provider""" def tester(self: TestModels): diff --git a/authentik/core/tests/test_property_mapping.py b/authentik/core/tests/test_property_mapping.py index ff73b7d228..d235e41daf 100644 --- a/authentik/core/tests/test_property_mapping.py +++ b/authentik/core/tests/test_property_mapping.py @@ -1,8 +1,9 @@ """authentik core property mapping tests""" + from django.test import RequestFactory, TestCase from guardian.shortcuts import get_anonymous_user -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.core.models import PropertyMapping from authentik.core.tests.utils import create_test_admin_user from authentik.events.models import Event, EventAction @@ -65,14 +66,11 @@ class TestPropertyMappings(TestCase): expression="return request.http_request.path", ) http_request = self.factory.get("/") - tmpl = ( - """ - res = ak_call_policy('%s') + tmpl = f""" + res = ak_call_policy('{expr.name}') result = [request.http_request.path, res.raw_result] return result """ - % expr.name - ) evaluator = PropertyMapping(expression=tmpl, name=generate_id()) res = evaluator.evaluate(self.user, http_request) self.assertEqual(res, ["/", "/"]) diff --git a/authentik/core/tests/test_property_mapping_api.py b/authentik/core/tests/test_property_mapping_api.py index 29e608c056..6afe40a181 100644 --- a/authentik/core/tests/test_property_mapping_api.py +++ b/authentik/core/tests/test_property_mapping_api.py @@ -1,13 +1,15 @@ """Test property mappings API""" + from json import dumps from django.urls import reverse from rest_framework.serializers import ValidationError from rest_framework.test import APITestCase -from authentik.core.api.propertymappings import PropertyMappingSerializer -from authentik.core.models import PropertyMapping +from authentik.core.api.property_mappings import PropertyMappingSerializer +from authentik.core.models import Group, PropertyMapping from authentik.core.tests.utils import create_test_admin_user +from authentik.lib.generators import generate_id class TestPropertyMappingAPI(APITestCase): @@ -15,23 +17,40 @@ class TestPropertyMappingAPI(APITestCase): def setUp(self) -> None: super().setUp() - self.mapping = PropertyMapping.objects.create( - name="dummy", expression="""return {'foo': 'bar'}""" - ) self.user = create_test_admin_user() self.client.force_login(self.user) def test_test_call(self): - """Test PropertMappings's test endpoint""" + """Test PropertyMappings's test endpoint""" + mapping = PropertyMapping.objects.create( + name="dummy", expression="""return {'foo': 'bar', 'baz': user.username}""" + ) response = self.client.post( - reverse("authentik_api:propertymapping-test", kwargs={"pk": self.mapping.pk}), + reverse("authentik_api:propertymapping-test", kwargs={"pk": mapping.pk}), data={ "user": self.user.pk, }, ) self.assertJSONEqual( response.content.decode(), - {"result": dumps({"foo": "bar"}), "successful": True}, + {"result": dumps({"foo": "bar", "baz": self.user.username}), "successful": True}, + ) + + def test_test_call_group(self): + """Test PropertyMappings's test endpoint""" + mapping = PropertyMapping.objects.create( + name="dummy", expression="""return {'foo': 'bar', 'baz': group.name}""" + ) + group = Group.objects.create(name=generate_id()) + response = self.client.post( + reverse("authentik_api:propertymapping-test", kwargs={"pk": mapping.pk}), + data={ + "group": group.pk, + }, + ) + self.assertJSONEqual( + response.content.decode(), + {"result": dumps({"foo": "bar", "baz": group.name}), "successful": True}, ) def test_validate(self): diff --git a/authentik/core/tests/test_providers_api.py b/authentik/core/tests/test_providers_api.py index 0b09686b9a..eac36132ec 100644 --- a/authentik/core/tests/test_providers_api.py +++ b/authentik/core/tests/test_providers_api.py @@ -1,4 +1,5 @@ """Test providers API""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/core/tests/test_source_flow_manager.py b/authentik/core/tests/test_source_flow_manager.py index a16201a6f1..5b75ec7859 100644 --- a/authentik/core/tests/test_source_flow_manager.py +++ b/authentik/core/tests/test_source_flow_manager.py @@ -1,11 +1,16 @@ """Test Source flow_manager""" + from django.contrib.auth.models import AnonymousUser from django.test import TestCase +from django.urls import reverse from guardian.utils import get_anonymous_user from authentik.core.models import SourceUserMatchingModes, User from authentik.core.sources.flow_manager import Action +from authentik.core.sources.stage import PostSourceStage from authentik.core.tests.utils import create_test_flow +from authentik.flows.planner import FlowPlan +from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.lib.generators import generate_id from authentik.lib.tests.utils import get_request from authentik.policies.denied import AccessDeniedResponse @@ -20,42 +25,62 @@ class TestSourceFlowManager(TestCase): def setUp(self) -> None: super().setUp() - self.source: OAuthSource = OAuthSource.objects.create(name="test") + self.authentication_flow = create_test_flow() + self.enrollment_flow = create_test_flow() + self.source: OAuthSource = OAuthSource.objects.create( + name=generate_id(), + slug=generate_id(), + authentication_flow=self.authentication_flow, + enrollment_flow=self.enrollment_flow, + ) self.identifier = generate_id() def test_unauthenticated_enroll(self): """Test un-authenticated user enrolling""" - flow_manager = OAuthSourceFlowManager( - self.source, get_request("/", user=AnonymousUser()), self.identifier, {} - ) + request = get_request("/", user=AnonymousUser()) + flow_manager = OAuthSourceFlowManager(self.source, request, self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.ENROLL) - flow_manager.get_flow() + response = flow_manager.get_flow() + self.assertEqual(response.status_code, 302) + flow_plan: FlowPlan = request.session[SESSION_KEY_PLAN] + self.assertEqual(flow_plan.bindings[0].stage.view, PostSourceStage) def test_unauthenticated_auth(self): """Test un-authenticated user authenticating""" UserOAuthSourceConnection.objects.create( user=get_anonymous_user(), source=self.source, identifier=self.identifier ) - - flow_manager = OAuthSourceFlowManager( - self.source, get_request("/", user=AnonymousUser()), self.identifier, {} - ) + request = get_request("/", user=AnonymousUser()) + flow_manager = OAuthSourceFlowManager(self.source, request, self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.AUTH) - flow_manager.get_flow() + response = flow_manager.get_flow() + self.assertEqual(response.status_code, 302) + flow_plan: FlowPlan = request.session[SESSION_KEY_PLAN] + self.assertEqual(flow_plan.bindings[0].stage.view, PostSourceStage) def test_authenticated_link(self): """Test authenticated user linking""" - UserOAuthSourceConnection.objects.create( - user=get_anonymous_user(), source=self.source, identifier=self.identifier - ) user = User.objects.create(username="foo", email="foo@bar.baz") - flow_manager = OAuthSourceFlowManager( - self.source, get_request("/", user=user), self.identifier, {} - ) - action, _ = flow_manager.get_action() + request = get_request("/", user=user) + flow_manager = OAuthSourceFlowManager(self.source, request, self.identifier, {}) + action, connection = flow_manager.get_action() self.assertEqual(action, Action.LINK) + self.assertIsNone(connection.pk) + response = flow_manager.get_flow() + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, + reverse("authentik_core:if-user") + "#/settings;page-sources", + ) + + def test_unauthenticated_link(self): + """Test un-authenticated user linking""" + flow_manager = OAuthSourceFlowManager(self.source, get_request("/"), self.identifier, {}) + action, connection = flow_manager.get_action() + self.assertEqual(action, Action.LINK) + self.assertIsNone(connection.pk) flow_manager.get_flow() def test_unauthenticated_enroll_email(self): @@ -172,5 +197,5 @@ class TestSourceFlowManager(TestCase): self.assertEqual(action, Action.ENROLL) response = flow_manager.get_flow() self.assertIsInstance(response, AccessDeniedResponse) - # pylint: disable=no-member + self.assertEqual(response.error_message, "foo") diff --git a/authentik/core/tests/test_tasks.py b/authentik/core/tests/test_tasks.py index 2212dbccc2..261b19ae6a 100644 --- a/authentik/core/tests/test_tasks.py +++ b/authentik/core/tests/test_tasks.py @@ -1,4 +1,5 @@ """Test tasks""" + from time import mktime from django.utils.timezone import now diff --git a/authentik/core/tests/test_token_api.py b/authentik/core/tests/test_token_api.py index 3584e01a78..c70d1b98d3 100644 --- a/authentik/core/tests/test_token_api.py +++ b/authentik/core/tests/test_token_api.py @@ -1,4 +1,6 @@ """Test token API""" + +from datetime import datetime, timedelta from json import loads from django.urls.base import reverse @@ -6,7 +8,13 @@ from guardian.shortcuts import get_anonymous_user from rest_framework.test import APITestCase from authentik.core.api.tokens import TokenSerializer -from authentik.core.models import USER_ATTRIBUTE_TOKEN_EXPIRING, Token, TokenIntents, User +from authentik.core.models import ( + USER_ATTRIBUTE_TOKEN_EXPIRING, + USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME, + Token, + TokenIntents, + User, +) from authentik.core.tests.utils import create_test_admin_user from authentik.lib.generators import generate_id @@ -75,6 +83,77 @@ class TestTokenAPI(APITestCase): self.assertEqual(token.intent, TokenIntents.INTENT_API) self.assertEqual(token.expiring, False) + def test_token_create_expiring(self): + """Test token creation endpoint""" + self.user.attributes[USER_ATTRIBUTE_TOKEN_EXPIRING] = True + self.user.save() + response = self.client.post( + reverse("authentik_api:token-list"), {"identifier": "test-token"} + ) + self.assertEqual(response.status_code, 201) + token = Token.objects.get(identifier="test-token") + self.assertEqual(token.user, self.user) + self.assertEqual(token.intent, TokenIntents.INTENT_API) + self.assertEqual(token.expiring, True) + + def test_token_create_expiring_custom_ok(self): + """Test token creation endpoint""" + self.user.attributes[USER_ATTRIBUTE_TOKEN_EXPIRING] = True + self.user.attributes[USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME] = "hours=2" + self.user.save() + expires = datetime.now() + timedelta(hours=1) + response = self.client.post( + reverse("authentik_api:token-list"), + { + "identifier": "test-token", + "expires": expires, + "intent": TokenIntents.INTENT_APP_PASSWORD, + }, + ) + self.assertEqual(response.status_code, 201) + token = Token.objects.get(identifier="test-token") + self.assertEqual(token.user, self.user) + self.assertEqual(token.intent, TokenIntents.INTENT_APP_PASSWORD) + self.assertEqual(token.expiring, True) + self.assertEqual(token.expires.timestamp(), expires.timestamp()) + + def test_token_create_expiring_custom_nok(self): + """Test token creation endpoint""" + self.user.attributes[USER_ATTRIBUTE_TOKEN_EXPIRING] = True + self.user.attributes[USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME] = "hours=2" + self.user.save() + expires = datetime.now() + timedelta(hours=3) + response = self.client.post( + reverse("authentik_api:token-list"), + { + "identifier": "test-token", + "expires": expires, + "intent": TokenIntents.INTENT_APP_PASSWORD, + }, + ) + self.assertEqual(response.status_code, 400) + + def test_token_create_expiring_custom_api(self): + """Test token creation endpoint""" + self.user.attributes[USER_ATTRIBUTE_TOKEN_EXPIRING] = True + self.user.attributes[USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME] = "hours=2" + self.user.save() + expires = datetime.now() + timedelta(seconds=3) + response = self.client.post( + reverse("authentik_api:token-list"), + { + "identifier": "test-token", + "expires": expires, + "intent": TokenIntents.INTENT_API, + }, + ) + self.assertEqual(response.status_code, 201) + token = Token.objects.get(identifier="test-token") + self.assertEqual(token.user, self.user) + self.assertEqual(token.intent, TokenIntents.INTENT_API) + self.assertEqual(token.expiring, True) + self.assertNotEqual(token.expires.timestamp(), expires.timestamp()) + def test_list(self): """Test Token List (Test normal authentication)""" Token.objects.all().delete() diff --git a/authentik/core/tests/test_token_auth.py b/authentik/core/tests/test_token_auth.py index 399e81d135..87e3df3818 100644 --- a/authentik/core/tests/test_token_auth.py +++ b/authentik/core/tests/test_token_auth.py @@ -1,4 +1,5 @@ """Test token auth""" + from django.test import TestCase from authentik.core.auth import TokenBackend diff --git a/authentik/core/tests/test_transactional_applications_api.py b/authentik/core/tests/test_transactional_applications_api.py index cd042bdb65..3d18e8cd9b 100644 --- a/authentik/core/tests/test_transactional_applications_api.py +++ b/authentik/core/tests/test_transactional_applications_api.py @@ -1,4 +1,5 @@ """Test Transactional API""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/core/tests/test_users_api.py b/authentik/core/tests/test_users_api.py index 9f7b59a4dd..140746f7c7 100644 --- a/authentik/core/tests/test_users_api.py +++ b/authentik/core/tests/test_users_api.py @@ -41,6 +41,12 @@ class TestUsersAPI(APITestCase): ) self.assertEqual(response.status_code, 200) + def test_list_with_groups(self): + """Test listing with groups""" + self.client.force_login(self.admin) + response = self.client.get(reverse("authentik_api:user-list"), {"include_groups": "true"}) + self.assertEqual(response.status_code, 200) + def test_metrics(self): """Test user's metrics""" self.client.force_login(self.admin) @@ -60,10 +66,11 @@ class TestUsersAPI(APITestCase): def test_recovery_no_flow(self): """Test user recovery link (no recovery flow set)""" self.client.force_login(self.admin) - response = self.client.get( + response = self.client.post( reverse("authentik_api:user-recovery", kwargs={"pk": self.user.pk}) ) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual(response.content, {"non_field_errors": "No recovery flow set."}) def test_set_password(self): """Test Direct password set""" @@ -84,7 +91,7 @@ class TestUsersAPI(APITestCase): brand.flow_recovery = flow brand.save() self.client.force_login(self.admin) - response = self.client.get( + response = self.client.post( reverse("authentik_api:user-recovery", kwargs={"pk": self.user.pk}) ) self.assertEqual(response.status_code, 200) @@ -92,16 +99,20 @@ class TestUsersAPI(APITestCase): def test_recovery_email_no_flow(self): """Test user recovery link (no recovery flow set)""" self.client.force_login(self.admin) - response = self.client.get( + response = self.client.post( reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk}) ) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content, {"non_field_errors": "User does not have an email address set."} + ) self.user.email = "foo@bar.baz" self.user.save() - response = self.client.get( + response = self.client.post( reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk}) ) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual(response.content, {"non_field_errors": "No recovery flow set."}) def test_recovery_email_no_stage(self): """Test user recovery link (no email stage)""" @@ -112,10 +123,11 @@ class TestUsersAPI(APITestCase): brand.flow_recovery = flow brand.save() self.client.force_login(self.admin) - response = self.client.get( + response = self.client.post( reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk}) ) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual(response.content, {"non_field_errors": "Email stage does not exist."}) def test_recovery_email(self): """Test user recovery link""" @@ -129,7 +141,7 @@ class TestUsersAPI(APITestCase): stage = EmailStage.objects.create(name="email") self.client.force_login(self.admin) - response = self.client.get( + response = self.client.post( reverse( "authentik_api:user-recovery-email", kwargs={"pk": self.user.pk}, @@ -261,7 +273,14 @@ class TestUsersAPI(APITestCase): reverse("authentik_api:user-paths"), ) self.assertEqual(response.status_code, 200) - self.assertJSONEqual(response.content.decode(), {"paths": ["users"]}) + expected = list( + User.objects.all() + .values("path") + .distinct() + .order_by("path") + .values_list("path", flat=True) + ) + self.assertJSONEqual(response.content.decode(), {"paths": expected}) def test_path_valid(self): """Test path""" diff --git a/authentik/core/tests/test_users_avatars.py b/authentik/core/tests/test_users_avatars.py index 01f703c616..b27fff8495 100644 --- a/authentik/core/tests/test_users_avatars.py +++ b/authentik/core/tests/test_users_avatars.py @@ -1,4 +1,5 @@ """Test Users Avatars""" + from json import loads from django.urls.base import reverse @@ -7,7 +8,6 @@ from rest_framework.test import APITestCase from authentik.core.models import User from authentik.core.tests.utils import create_test_admin_user -from authentik.lib.config import CONFIG from authentik.tenants.utils import get_current_tenant @@ -24,7 +24,6 @@ class TestUsersAvatars(APITestCase): tenant.avatars = mode tenant.save() - @CONFIG.patch("avatars", "none") def test_avatars_none(self): """Test avatars none""" self.set_avatar_mode("none") @@ -43,8 +42,8 @@ class TestUsersAvatars(APITestCase): with Mocker() as mocker: mocker.head( ( - "https://secure.gravatar.com/avatar/84730f9c1851d1ea03f1a" - "a9ed85bd1ea?size=158&rating=g&default=404" + "https://www.gravatar.com/avatar/76eb3c74c8beb6faa037f1b6e2ecb3e252bdac" + "6cf71fb567ae36025a9d4ea86b?size=158&rating=g&default=404" ), text="foo", ) diff --git a/authentik/core/tests/utils.py b/authentik/core/tests/utils.py index 6373d31d74..7e66c382f7 100644 --- a/authentik/core/tests/utils.py +++ b/authentik/core/tests/utils.py @@ -1,11 +1,10 @@ """Test Utils""" -from typing import Optional from django.utils.text import slugify from authentik.brands.models import Brand from authentik.core.models import Group, User -from authentik.crypto.builder import CertificateBuilder +from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg from authentik.crypto.models import CertificateKeyPair from authentik.flows.models import Flow, FlowDesignation from authentik.lib.generators import generate_id @@ -21,7 +20,7 @@ def create_test_flow( ) -def create_test_user(name: Optional[str] = None, **kwargs) -> User: +def create_test_user(name: str | None = None, **kwargs) -> User: """Generate a test user""" uid = generate_id(20) if not name else name kwargs.setdefault("email", f"{uid}@goauthentik.io") @@ -35,7 +34,7 @@ def create_test_user(name: Optional[str] = None, **kwargs) -> User: return user -def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User: +def create_test_admin_user(name: str | None = None, **kwargs) -> User: """Generate a test-admin user""" user = create_test_user(name, **kwargs) group = Group.objects.create(name=user.name or name, is_superuser=True) @@ -51,12 +50,10 @@ def create_test_brand(**kwargs) -> Brand: return Brand.objects.create(domain=uid, default=True, **kwargs) -def create_test_cert(use_ec_private_key=False) -> CertificateKeyPair: +def create_test_cert(alg=PrivateKeyAlg.RSA) -> CertificateKeyPair: """Generate a certificate for testing""" - builder = CertificateBuilder( - name=f"{generate_id()}.self-signed.goauthentik.io", - use_ec_private_key=use_ec_private_key, - ) + builder = CertificateBuilder(f"{generate_id()}.self-signed.goauthentik.io") + builder.alg = alg builder.build( subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"], validity_days=360, diff --git a/authentik/core/types.py b/authentik/core/types.py index 036b17c783..32468674c0 100644 --- a/authentik/core/types.py +++ b/authentik/core/types.py @@ -1,6 +1,6 @@ """authentik core dataclasses""" + from dataclasses import dataclass -from typing import Optional from rest_framework.fields import CharField @@ -19,7 +19,7 @@ class UILoginButton: challenge: Challenge # Icon URL, used as-is - icon_url: Optional[str] = None + icon_url: str | None = None class UserSettingSerializer(PassiveSerializer): diff --git a/authentik/core/urls.py b/authentik/core/urls.py index 32f2978155..0d415bd176 100644 --- a/authentik/core/urls.py +++ b/authentik/core/urls.py @@ -1,4 +1,5 @@ """authentik URL Configuration""" + from channels.auth import AuthMiddleware from channels.sessions import CookieMiddleware from django.conf import settings @@ -11,7 +12,7 @@ from authentik.core.api.applications import ApplicationViewSet from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet from authentik.core.api.devices import AdminDeviceViewSet, DeviceViewSet from authentik.core.api.groups import GroupViewSet -from authentik.core.api.propertymappings import PropertyMappingViewSet +from authentik.core.api.property_mappings import PropertyMappingViewSet from authentik.core.api.providers import ProviderViewSet from authentik.core.api.sources import SourceViewSet, UserSourceConnectionViewSet from authentik.core.api.tokens import TokenViewSet diff --git a/authentik/core/views/apps.py b/authentik/core/views/apps.py index e52ba12d62..9843cd1257 100644 --- a/authentik/core/views/apps.py +++ b/authentik/core/views/apps.py @@ -1,4 +1,5 @@ """app views""" + from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.utils.translation import gettext_lazy as _ @@ -56,7 +57,7 @@ class RedirectToAppLaunch(View): }, ) except FlowNonApplicableException: - raise Http404 + raise Http404 from None plan.insert_stage(in_memory_stage(RedirectToAppStage)) request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs("authentik_core:if-flow", request.GET, flow_slug=flow.slug) diff --git a/authentik/core/views/debug.py b/authentik/core/views/debug.py index 5ec6fd860a..96bb04a101 100644 --- a/authentik/core/views/debug.py +++ b/authentik/core/views/debug.py @@ -1,4 +1,5 @@ """debug view""" + from django.http import HttpRequest, HttpResponse from django.views.generic import View diff --git a/authentik/core/views/error.py b/authentik/core/views/error.py index 51868d9971..68c40ed4a5 100644 --- a/authentik/core/views/error.py +++ b/authentik/core/views/error.py @@ -61,7 +61,6 @@ class ServerErrorView(TemplateView): response_class = ServerErrorTemplateResponse template_name = "if/error.html" - # pylint: disable=useless-super-delegation def dispatch(self, *args, **kwargs): # pragma: no cover """Little wrapper so django accepts this function""" return super().dispatch(*args, **kwargs) diff --git a/authentik/core/views/interface.py b/authentik/core/views/interface.py index faeb40b821..2a7dbda558 100644 --- a/authentik/core/views/interface.py +++ b/authentik/core/views/interface.py @@ -1,4 +1,5 @@ """Interface views""" + from json import dumps from typing import Any diff --git a/authentik/core/views/session.py b/authentik/core/views/session.py index 11d5ad9409..c0ad9d7714 100644 --- a/authentik/core/views/session.py +++ b/authentik/core/views/session.py @@ -1,4 +1,5 @@ """authentik Session Views""" + from typing import Any from django.shortcuts import get_object_or_404 diff --git a/authentik/crypto/api.py b/authentik/crypto/api.py index af9b1d066d..a3e174387d 100644 --- a/authentik/crypto/api.py +++ b/authentik/crypto/api.py @@ -1,6 +1,6 @@ """Crypto API Views""" + from datetime import datetime -from typing import Optional from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import load_pem_private_key @@ -14,7 +14,13 @@ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema from rest_framework.decorators import action from rest_framework.exceptions import ValidationError -from rest_framework.fields import CharField, DateTimeField, IntegerField, SerializerMethodField +from rest_framework.fields import ( + CharField, + ChoiceField, + DateTimeField, + IntegerField, + SerializerMethodField, +) from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.request import Request from rest_framework.response import Response @@ -23,13 +29,13 @@ from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.api.authorization import SecretKeyFilter -from authentik.api.decorators import permission_required from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.crypto.apps import MANAGED_KEY -from authentik.crypto.builder import CertificateBuilder +from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction +from authentik.rbac.decorators import permission_required LOGGER = get_logger() @@ -55,25 +61,25 @@ class CertificateKeyPairSerializer(ModelSerializer): return True return str(request.query_params.get("include_details", "true")).lower() == "true" - def get_fingerprint_sha256(self, instance: CertificateKeyPair) -> Optional[str]: + def get_fingerprint_sha256(self, instance: CertificateKeyPair) -> str | None: "Get certificate Hash (SHA256)" if not self._should_include_details: return None return instance.fingerprint_sha256 - def get_fingerprint_sha1(self, instance: CertificateKeyPair) -> Optional[str]: + def get_fingerprint_sha1(self, instance: CertificateKeyPair) -> str | None: "Get certificate Hash (SHA1)" if not self._should_include_details: return None return instance.fingerprint_sha1 - def get_cert_expiry(self, instance: CertificateKeyPair) -> Optional[datetime]: + def get_cert_expiry(self, instance: CertificateKeyPair) -> datetime | None: "Get certificate expiry" if not self._should_include_details: return None - return DateTimeField().to_representation(instance.certificate.not_valid_after) + return DateTimeField().to_representation(instance.certificate.not_valid_after_utc) - def get_cert_subject(self, instance: CertificateKeyPair) -> Optional[str]: + def get_cert_subject(self, instance: CertificateKeyPair) -> str | None: """Get certificate subject as full rfc4514""" if not self._should_include_details: return None @@ -83,7 +89,7 @@ class CertificateKeyPairSerializer(ModelSerializer): """Show if this keypair has a private key configured or not""" return instance.key_data != "" and instance.key_data is not None - def get_private_key_type(self, instance: CertificateKeyPair) -> Optional[str]: + def get_private_key_type(self, instance: CertificateKeyPair) -> str | None: """Get the private key's type, if set""" if not self._should_include_details: return None @@ -120,7 +126,7 @@ class CertificateKeyPairSerializer(ModelSerializer): str(load_pem_x509_certificate(value.encode("utf-8"), default_backend())) except ValueError as exc: LOGGER.warning("Failed to load certificate", exc=exc) - raise ValidationError("Unable to load certificate.") + raise ValidationError("Unable to load certificate.") from None return value def validate_key_data(self, value: str) -> str: @@ -139,7 +145,7 @@ class CertificateKeyPairSerializer(ModelSerializer): ) except (ValueError, TypeError) as exc: LOGGER.warning("Failed to load private key", exc=exc) - raise ValidationError("Unable to load private key (possibly encrypted?).") + raise ValidationError("Unable to load private key (possibly encrypted?).") from None return value class Meta: @@ -178,6 +184,7 @@ class CertificateGenerationSerializer(PassiveSerializer): common_name = CharField() subject_alt_name = CharField(required=False, allow_blank=True, label=_("Subject-alt name")) validity_days = IntegerField(initial=365) + alg = ChoiceField(default=PrivateKeyAlg.RSA, choices=PrivateKeyAlg.choices) class CertificateKeyPairFilter(FilterSet): @@ -240,6 +247,7 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet): raw_san = data.validated_data.get("subject_alt_name", "") sans = raw_san.split(",") if raw_san != "" else [] builder = CertificateBuilder(data.validated_data["common_name"]) + builder.alg = data.validated_data["alg"] builder.build( subject_alt_names=sans, validity_days=int(data.validated_data["validity_days"]), @@ -272,9 +280,9 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet): response = HttpResponse( certificate.certificate_data, content_type="application/x-pem-file" ) - response[ - "Content-Disposition" - ] = f'attachment; filename="{certificate.name}_certificate.pem"' + response["Content-Disposition"] = ( + f'attachment; filename="{certificate.name}_certificate.pem"' + ) return response return Response(CertificateDataSerializer({"data": certificate.certificate_data}).data) @@ -300,8 +308,8 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet): if "download" in request.query_params: # Mime type from https://pki-tutorial.readthedocs.io/en/latest/mime.html response = HttpResponse(certificate.key_data, content_type="application/x-pem-file") - response[ - "Content-Disposition" - ] = f'attachment; filename="{certificate.name}_private_key.pem"' + response["Content-Disposition"] = ( + f'attachment; filename="{certificate.name}_private_key.pem"' + ) return response return Response(CertificateDataSerializer({"data": certificate.key_data}).data) diff --git a/authentik/crypto/apps.py b/authentik/crypto/apps.py index 24d63e92a7..cdb01b3a1b 100644 --- a/authentik/crypto/apps.py +++ b/authentik/crypto/apps.py @@ -1,6 +1,6 @@ """authentik crypto app config""" -from datetime import datetime -from typing import Optional + +from datetime import UTC, datetime from authentik.blueprints.apps import ManagedAppConfig from authentik.lib.generators import generate_id @@ -16,10 +16,6 @@ class AuthentikCryptoConfig(ManagedAppConfig): verbose_name = "authentik Crypto" default = True - def reconcile_global_load_crypto_tasks(self): - """Load crypto tasks""" - self.import_module("authentik.crypto.tasks") - def _create_update_cert(self): from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair @@ -39,20 +35,22 @@ class AuthentikCryptoConfig(ManagedAppConfig): }, ) - def reconcile_tenant_managed_jwt_cert(self): + @ManagedAppConfig.reconcile_tenant + def managed_jwt_cert(self): """Ensure managed JWT certificate""" from authentik.crypto.models import CertificateKeyPair - cert: Optional[CertificateKeyPair] = CertificateKeyPair.objects.filter( + cert: CertificateKeyPair | None = CertificateKeyPair.objects.filter( managed=MANAGED_KEY ).first() - now = datetime.now() + now = datetime.now(tz=UTC) if not cert or ( - now < cert.certificate.not_valid_before or now > cert.certificate.not_valid_after + now < cert.certificate.not_valid_after_utc or now > cert.certificate.not_valid_after_utc ): self._create_update_cert() - def reconcile_tenant_self_signed(self): + @ManagedAppConfig.reconcile_tenant + def self_signed(self): """Create self-signed keypair""" from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair diff --git a/authentik/crypto/builder.py b/authentik/crypto/builder.py index d560901bda..d9be0bfb2d 100644 --- a/authentik/crypto/builder.py +++ b/authentik/crypto/builder.py @@ -1,7 +1,7 @@ """Create self-signed certificates""" + import datetime import uuid -from typing import Optional from cryptography import x509 from cryptography.hazmat.backends import default_backend @@ -9,20 +9,28 @@ from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes from cryptography.x509.oid import NameOID +from django.db import models +from django.utils.translation import gettext_lazy as _ from authentik import __version__ from authentik.crypto.models import CertificateKeyPair +class PrivateKeyAlg(models.TextChoices): + """Algorithm to create private key with""" + + RSA = "rsa", _("rsa") + ECDSA = "ecdsa", _("ecdsa") + + class CertificateBuilder: """Build self-signed certificates""" common_name: str + alg: PrivateKeyAlg - _use_ec_private_key: bool - - def __init__(self, name: str, use_ec_private_key=False): - self._use_ec_private_key = use_ec_private_key + def __init__(self, name: str): + self.alg = PrivateKeyAlg.RSA self.__public_key = None self.__private_key = None self.__builder = None @@ -42,16 +50,18 @@ class CertificateBuilder: def generate_private_key(self) -> PrivateKeyTypes: """Generate private key""" - if self._use_ec_private_key: - return ec.generate_private_key(curve=ec.SECP256R1) - return rsa.generate_private_key( - public_exponent=65537, key_size=4096, backend=default_backend() - ) + if self.alg == PrivateKeyAlg.ECDSA: + return ec.generate_private_key(curve=ec.SECP256R1()) + if self.alg == PrivateKeyAlg.RSA: + return rsa.generate_private_key( + public_exponent=65537, key_size=4096, backend=default_backend() + ) + raise ValueError(f"Invalid alg: {self.alg}") def build( self, validity_days: int = 365, - subject_alt_names: Optional[list[str]] = None, + subject_alt_names: list[str] | None = None, ): """Build self-signed certificate""" one_day = datetime.timedelta(1, 0, 0) diff --git a/authentik/crypto/management/commands/import_certificate.py b/authentik/crypto/management/commands/import_certificate.py index 6f84a1ddc1..708e908207 100644 --- a/authentik/crypto/management/commands/import_certificate.py +++ b/authentik/crypto/management/commands/import_certificate.py @@ -1,4 +1,5 @@ """Import certificate""" + from sys import exit as sys_exit from django.core.management.base import no_translations @@ -23,13 +24,13 @@ class Command(TenantCommand): if not keypair: keypair = CertificateKeyPair(name=options["name"]) dirty = True - with open(options["certificate"], mode="r", encoding="utf-8") as _cert: + with open(options["certificate"], encoding="utf-8") as _cert: cert_data = _cert.read() if keypair.certificate_data != cert_data: dirty = True keypair.certificate_data = cert_data if options["private_key"]: - with open(options["private_key"], mode="r", encoding="utf-8") as _key: + with open(options["private_key"], encoding="utf-8") as _key: key_data = _key.read() if keypair.key_data != key_data: dirty = True diff --git a/authentik/crypto/models.py b/authentik/crypto/models.py index d6543fe318..977c1e83b4 100644 --- a/authentik/crypto/models.py +++ b/authentik/crypto/models.py @@ -1,7 +1,7 @@ """authentik crypto models""" + from binascii import hexlify from hashlib import md5 -from typing import Optional from uuid import uuid4 from cryptography.hazmat.backends import default_backend @@ -36,9 +36,9 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): default="", ) - _cert: Optional[Certificate] = None - _private_key: Optional[PrivateKeyTypes] = None - _public_key: Optional[PublicKeyTypes] = None + _cert: Certificate | None = None + _private_key: PrivateKeyTypes | None = None + _public_key: PublicKeyTypes | None = None @property def serializer(self) -> Serializer: @@ -56,7 +56,7 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): return self._cert @property - def public_key(self) -> Optional[PublicKeyTypes]: + def public_key(self) -> PublicKeyTypes | None: """Get public key of the private key""" if not self._public_key: self._public_key = self.private_key.public_key() @@ -65,7 +65,7 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): @property def private_key( self, - ) -> Optional[PrivateKeyTypes]: + ) -> PrivateKeyTypes | None: """Get python cryptography PrivateKey instance""" if not self._private_key and self.key_data != "": try: @@ -92,7 +92,11 @@ class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel): @property def kid(self): """Get Key ID used for JWKS""" - return md5(self.key_data.encode("utf-8")).hexdigest() if self.key_data else "" # nosec + return ( + md5(self.key_data.encode("utf-8"), usedforsecurity=False).hexdigest() + if self.key_data + else "" + ) # nosec def __str__(self) -> str: return f"Certificate-Key Pair {self.name}" diff --git a/authentik/crypto/settings.py b/authentik/crypto/settings.py index 939473a96e..8316e9b84d 100644 --- a/authentik/crypto/settings.py +++ b/authentik/crypto/settings.py @@ -1,4 +1,5 @@ """Crypto task Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/crypto/tasks.py b/authentik/crypto/tasks.py index 066fee8ac8..43704e7682 100644 --- a/authentik/crypto/tasks.py +++ b/authentik/crypto/tasks.py @@ -1,4 +1,5 @@ """Crypto tasks""" + from glob import glob from pathlib import Path @@ -57,7 +58,7 @@ def certificate_discovery(self: SystemTask): else: cert_name = path.name.replace(path.suffix, "") try: - with open(path, "r", encoding="utf-8") as _file: + with open(path, encoding="utf-8") as _file: body = _file.read() if "PRIVATE KEY" in body: private_keys[cert_name] = ensure_private_key_valid(body) diff --git a/authentik/crypto/tests.py b/authentik/crypto/tests.py index 3a4f05ea5c..1d43367413 100644 --- a/authentik/crypto/tests.py +++ b/authentik/crypto/tests.py @@ -1,5 +1,5 @@ """Crypto tests""" -import datetime + from json import loads from os import makedirs from tempfile import TemporaryDirectory @@ -7,6 +7,7 @@ from tempfile import TemporaryDirectory from cryptography.x509.extensions import SubjectAlternativeName from cryptography.x509.general_name import DNSName from django.urls import reverse +from django.utils.timezone import now from rest_framework.test import APITestCase from authentik.core.api.used_by import DeleteAction @@ -67,9 +68,9 @@ class TestCrypto(APITestCase): validity_days=3, ) instance = builder.save() - now = datetime.datetime.today() + _now = now() self.assertEqual(instance.name, name) - self.assertEqual((instance.certificate.not_valid_after - now).days, 2) + self.assertEqual((instance.certificate.not_valid_after_utc - _now).days, 2) def test_builder_api(self): """Test Builder (via API)""" @@ -266,7 +267,7 @@ class TestCrypto(APITestCase): with open(f"{temp_dir}/foo.bar/privkey.pem", "w+", encoding="utf-8") as _key: _key.write(builder.private_key) with CONFIG.patch("cert_discovery_dir", temp_dir): - certificate_discovery() # pylint: disable=no-value-for-parameter + certificate_discovery() keypair: CertificateKeyPair = CertificateKeyPair.objects.filter( managed=MANAGED_DISCOVERED % "foo" ).first() diff --git a/authentik/crypto/urls.py b/authentik/crypto/urls.py index a71a890848..e98009e316 100644 --- a/authentik/crypto/urls.py +++ b/authentik/crypto/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.crypto.api import CertificateKeyPairViewSet api_urlpatterns = [ diff --git a/authentik/enterprise/api.py b/authentik/enterprise/api.py index c13e34b6da..fbe5a4bee5 100644 --- a/authentik/enterprise/api.py +++ b/authentik/enterprise/api.py @@ -1,5 +1,7 @@ """Enterprise API Views""" -from datetime import datetime, timedelta + +from dataclasses import asdict +from datetime import timedelta from django.utils.timezone import now from django.utils.translation import gettext as _ @@ -7,29 +9,29 @@ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema, inline_serializer from rest_framework.decorators import action from rest_framework.exceptions import ValidationError -from rest_framework.fields import BooleanField, CharField, DateTimeField, IntegerField +from rest_framework.fields import CharField, IntegerField from rest_framework.permissions import IsAuthenticated from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet -from authentik.api.decorators import permission_required from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User, UserTypes -from authentik.enterprise.models import License, LicenseKey -from authentik.root.install_id import get_install_id +from authentik.enterprise.license import LicenseKey, LicenseSummarySerializer +from authentik.enterprise.models import License +from authentik.rbac.decorators import permission_required +from authentik.tenants.utils import get_unique_identifier class EnterpriseRequiredMixin: """Mixin to validate that a valid enterprise license - exists before allowing to safe the object""" + exists before allowing to save the object""" def validate(self, attrs: dict) -> dict: """Check that a valid license exists""" - total = LicenseKey.get_total() - if not total.is_valid(): + if not LicenseKey.cached_summary().has_license: raise ValidationError(_("Enterprise is required to create/update this object.")) return super().validate(attrs) @@ -60,19 +62,6 @@ class LicenseSerializer(ModelSerializer): } -class LicenseSummary(PassiveSerializer): - """Serializer for license status""" - - internal_users = IntegerField(required=True) - external_users = IntegerField(required=True) - valid = BooleanField() - show_admin_warning = BooleanField() - show_user_warning = BooleanField() - read_only = BooleanField() - latest_valid = DateTimeField() - has_license = BooleanField() - - class LicenseForecastSerializer(PassiveSerializer): """Serializer for license forecast""" @@ -103,38 +92,20 @@ class LicenseViewSet(UsedByMixin, ModelViewSet): """Get install_id""" return Response( data={ - "install_id": get_install_id(), + "install_id": get_unique_identifier(), } ) @extend_schema( request=OpenApiTypes.NONE, responses={ - 200: LicenseSummary(), + 200: LicenseSummarySerializer(), }, ) @action(detail=False, methods=["GET"], permission_classes=[IsAuthenticated]) def summary(self, request: Request) -> Response: """Get the total license status""" - total = LicenseKey.get_total() - last_valid = LicenseKey.last_valid_date() - # TODO: move this to a different place? - show_admin_warning = last_valid < now() - timedelta(weeks=2) - show_user_warning = last_valid < now() - timedelta(weeks=4) - read_only = last_valid < now() - timedelta(weeks=6) - latest_valid = datetime.fromtimestamp(total.exp) - response = LicenseSummary( - data={ - "internal_users": total.internal_users, - "external_users": total.external_users, - "valid": total.is_valid(), - "show_admin_warning": show_admin_warning, - "show_user_warning": show_user_warning, - "read_only": read_only, - "latest_valid": latest_valid, - "has_license": License.objects.all().count() > 0, - } - ) + response = LicenseSummarySerializer(data=asdict(LicenseKey.cached_summary())) response.is_valid(raise_exception=True) return Response(response.data) diff --git a/authentik/enterprise/apps.py b/authentik/enterprise/apps.py index 166ab55c88..83dbefa06a 100644 --- a/authentik/enterprise/apps.py +++ b/authentik/enterprise/apps.py @@ -1,4 +1,5 @@ """Enterprise app config""" + from django.conf import settings from authentik.blueprints.apps import ManagedAppConfig @@ -16,16 +17,12 @@ class AuthentikEnterpriseConfig(EnterpriseConfig): verbose_name = "authentik Enterprise" default = True - def reconcile_global_load_enterprise_signals(self): - """Load enterprise signals""" - self.import_module("authentik.enterprise.signals") - def enabled(self): """Return true if enterprise is enabled and valid""" return self.check_enabled() or settings.TEST def check_enabled(self): """Actual enterprise check, cached""" - from authentik.enterprise.models import LicenseKey + from authentik.enterprise.license import LicenseKey - return LicenseKey.get_total().is_valid() + return LicenseKey.cached_summary().valid diff --git a/authentik/enterprise/audit/apps.py b/authentik/enterprise/audit/apps.py index 04c9f3686d..8d298d8b25 100644 --- a/authentik/enterprise/audit/apps.py +++ b/authentik/enterprise/audit/apps.py @@ -1,4 +1,5 @@ """Enterprise app config""" + from django.conf import settings from authentik.enterprise.apps import EnterpriseConfig @@ -12,8 +13,9 @@ class AuthentikEnterpriseAuditConfig(EnterpriseConfig): verbose_name = "authentik Enterprise.Audit" default = True - def reconcile_global_install_middleware(self): + def ready(self): """Install enterprise audit middleware""" orig_import = "authentik.events.middleware.AuditMiddleware" new_import = "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware" settings.MIDDLEWARE = [new_import if x == orig_import else x for x in settings.MIDDLEWARE] + return super().ready() diff --git a/authentik/enterprise/audit/middleware.py b/authentik/enterprise/audit/middleware.py index 889ce25e58..e11952e09f 100644 --- a/authentik/enterprise/audit/middleware.py +++ b/authentik/enterprise/audit/middleware.py @@ -1,16 +1,17 @@ """Enterprise audit middleware""" + from copy import deepcopy from functools import partial +from typing import Any from django.apps.registry import apps from django.core.files import File from django.db import connection -from django.db.models import Model +from django.db.models import ManyToManyRel, Model from django.db.models.expressions import BaseExpression, Combinable from django.db.models.signals import post_init from django.http import HttpRequest -from authentik.core.models import User from authentik.events.middleware import AuditMiddleware, should_log_model from authentik.events.utils import cleanse_dict, sanitize_item @@ -18,26 +19,19 @@ from authentik.events.utils import cleanse_dict, sanitize_item class EnterpriseAuditMiddleware(AuditMiddleware): """Enterprise audit middleware""" - _enabled = None - @property def enabled(self): - """Lazy check if audit logging is enabled""" - if self._enabled is None: - self._enabled = apps.get_app_config("authentik_enterprise").enabled() - return self._enabled + """Check if audit logging is enabled""" + return apps.get_app_config("authentik_enterprise").enabled() def connect(self, request: HttpRequest): super().connect(request) if not self.enabled: return - user = getattr(request, "user", self.anonymous_user) - if not user.is_authenticated: - user = self.anonymous_user if not hasattr(request, "request_id"): return post_init.connect( - partial(self.post_init_handler, user=user, request=request), + partial(self.post_init_handler, request=request), dispatch_uid=request.request_id, weak=False, ) @@ -51,7 +45,7 @@ class EnterpriseAuditMiddleware(AuditMiddleware): post_init.disconnect(dispatch_uid=request.request_id) def serialize_simple(self, model: Model) -> dict: - """Serialize a model in a very simple way. No ForeginKeys or other relationships are + """Serialize a model in a very simple way. No ForeignKeys or other relationships are resolved""" data = {} deferred_fields = model.get_deferred_fields() @@ -65,7 +59,7 @@ class EnterpriseAuditMiddleware(AuditMiddleware): field_value = value.name # If current field value is an expression, we are not evaluating it - if isinstance(field_value, (BaseExpression, Combinable)): + if isinstance(field_value, BaseExpression | Combinable): continue field_value = field.to_python(field_value) data[field.name] = deepcopy(field_value) @@ -77,24 +71,25 @@ class EnterpriseAuditMiddleware(AuditMiddleware): for key, value in before.items(): if after.get(key) != value: diff[key] = {"previous_value": value, "new_value": after.get(key)} + for key, value in after.items(): + if key not in before and key not in diff and before.get(key) != value: + diff[key] = {"previous_value": before.get(key), "new_value": value} return sanitize_item(diff) - def post_init_handler(self, user: User, request: HttpRequest, sender, instance: Model, **_): + def post_init_handler(self, request: HttpRequest, sender, instance: Model, **_): """post_init django model handler""" if not should_log_model(instance): return if hasattr(instance, "_previous_state"): return before = len(connection.queries) - setattr(instance, "_previous_state", self.serialize_simple(instance)) + instance._previous_state = self.serialize_simple(instance) after = len(connection.queries) if after > before: raise AssertionError("More queries generated by serialize_simple") - # pylint: disable=too-many-arguments def post_save_handler( self, - user: User, request: HttpRequest, sender, instance: Model, @@ -107,15 +102,37 @@ class EnterpriseAuditMiddleware(AuditMiddleware): thread_kwargs = {} if hasattr(instance, "_previous_state") or created: prev_state = getattr(instance, "_previous_state", {}) + if created: + prev_state = {} # Get current state new_state = self.serialize_simple(instance) diff = self.diff(prev_state, new_state) thread_kwargs["diff"] = diff - if not created: - ignored_field_sets = getattr(instance._meta, "authentik_signals_ignored_fields", []) - for field_set in ignored_field_sets: - if set(diff.keys()) == set(field_set): - return None - return super().post_save_handler( - user, request, sender, instance, created, thread_kwargs, **_ - ) + return super().post_save_handler(request, sender, instance, created, thread_kwargs, **_) + + def m2m_changed_handler( # noqa: PLR0913 + self, + request: HttpRequest, + sender, + instance: Model, + action: str, + pk_set: set[Any], + thread_kwargs: dict | None = None, + **_, + ): + thread_kwargs = {} + m2m_field = None + # For the audit log we don't care about `pre_` or `post_` so we trim that part off + _, _, action_direction = action.partition("_") + # resolve the "through" model to an actual field + for field in instance._meta.get_fields(): + if not isinstance(field, ManyToManyRel): + continue + if field.through == sender: + m2m_field = field + if m2m_field: + # If we're clearing we just set the "flag" to True + if action_direction == "clear": + pk_set = True + thread_kwargs["diff"] = {m2m_field.related_name: {action_direction: pk_set}} + return super().m2m_changed_handler(request, sender, instance, action, thread_kwargs) diff --git a/authentik/enterprise/audit/tests.py b/authentik/enterprise/audit/tests.py new file mode 100644 index 0000000000..31b6556ef6 --- /dev/null +++ b/authentik/enterprise/audit/tests.py @@ -0,0 +1,210 @@ +from unittest.mock import PropertyMock, patch + +from django.apps import apps +from django.conf import settings +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.core.models import Group, User +from authentik.core.tests.utils import create_test_admin_user +from authentik.events.models import Event, EventAction +from authentik.events.utils import sanitize_item +from authentik.lib.generators import generate_id + + +class TestEnterpriseAudit(APITestCase): + """Test audit middleware""" + + def setUp(self) -> None: + self.user = create_test_admin_user() + + def test_import(self): + """Ensure middleware is imported when app.ready is called""" + # Revert import swap + orig_import = "authentik.events.middleware.AuditMiddleware" + new_import = "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware" + settings.MIDDLEWARE = [orig_import if x == new_import else x for x in settings.MIDDLEWARE] + # Re-call ready() + apps.get_app_config("authentik_enterprise_audit").ready() + self.assertIn( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware", settings.MIDDLEWARE + ) + + @patch( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled", + PropertyMock(return_value=True), + ) + def test_create(self): + """Test create audit log""" + self.client.force_login(self.user) + username = generate_id() + response = self.client.post( + reverse("authentik_api:user-list"), + data={"name": generate_id(), "username": username, "groups": [], "path": "foo"}, + ) + user = User.objects.get(username=username) + self.assertEqual(response.status_code, 201) + events = Event.objects.filter( + action=EventAction.MODEL_CREATED, + context__model__model_name="user", + context__model__app="authentik_core", + context__model__pk=user.pk, + ) + event = events.first() + self.assertIsNotNone(event) + self.assertIsNotNone(event.context["diff"]) + diff = event.context["diff"] + self.assertEqual( + diff, + { + "name": { + "new_value": user.name, + "previous_value": None, + }, + "path": {"new_value": "foo", "previous_value": None}, + "type": {"new_value": "internal", "previous_value": None}, + "uuid": { + "new_value": user.uuid.hex, + "previous_value": None, + }, + "email": {"new_value": "", "previous_value": None}, + "username": { + "new_value": user.username, + "previous_value": None, + }, + "is_active": {"new_value": True, "previous_value": None}, + "attributes": {"new_value": {}, "previous_value": None}, + "date_joined": { + "new_value": sanitize_item(user.date_joined), + "previous_value": None, + }, + "first_name": {"new_value": "", "previous_value": None}, + "id": {"new_value": user.pk, "previous_value": None}, + "last_name": {"new_value": "", "previous_value": None}, + "password": {"new_value": "********************", "previous_value": None}, + "password_change_date": { + "new_value": sanitize_item(user.password_change_date), + "previous_value": None, + }, + }, + ) + + @patch( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled", + PropertyMock(return_value=True), + ) + def test_update(self): + """Test update audit log""" + self.client.force_login(self.user) + user = create_test_admin_user() + current_name = user.name + new_name = generate_id() + response = self.client.patch( + reverse("authentik_api:user-detail", kwargs={"pk": user.id}), + data={"name": new_name}, + ) + user.refresh_from_db() + self.assertEqual(response.status_code, 200) + events = Event.objects.filter( + action=EventAction.MODEL_UPDATED, + context__model__model_name="user", + context__model__app="authentik_core", + context__model__pk=user.pk, + ) + event = events.first() + self.assertIsNotNone(event) + self.assertIsNotNone(event.context["diff"]) + diff = event.context["diff"] + self.assertEqual( + diff, + { + "name": { + "new_value": new_name, + "previous_value": current_name, + }, + }, + ) + + @patch( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled", + PropertyMock(return_value=True), + ) + def test_delete(self): + """Test delete audit log""" + self.client.force_login(self.user) + user = create_test_admin_user() + response = self.client.delete( + reverse("authentik_api:user-detail", kwargs={"pk": user.id}), + ) + self.assertEqual(response.status_code, 204) + events = Event.objects.filter( + action=EventAction.MODEL_DELETED, + context__model__model_name="user", + context__model__app="authentik_core", + context__model__pk=user.pk, + ) + event = events.first() + self.assertIsNotNone(event) + self.assertNotIn("diff", event.context) + + @patch( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled", + PropertyMock(return_value=True), + ) + def test_m2m_add(self): + """Test m2m add audit log""" + self.client.force_login(self.user) + user = create_test_admin_user() + group = Group.objects.create(name=generate_id()) + response = self.client.post( + reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}), + data={ + "pk": user.pk, + }, + ) + self.assertEqual(response.status_code, 204) + events = Event.objects.filter( + action=EventAction.MODEL_UPDATED, + context__model__model_name="group", + context__model__app="authentik_core", + context__model__pk=group.pk.hex, + ) + event = events.first() + self.assertIsNotNone(event) + self.assertIsNotNone(event.context["diff"]) + diff = event.context["diff"] + self.assertEqual( + diff, + {"users": {"add": [user.pk]}}, + ) + + @patch( + "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled", + PropertyMock(return_value=True), + ) + def test_m2m_remove(self): + """Test m2m remove audit log""" + self.client.force_login(self.user) + user = create_test_admin_user() + group = Group.objects.create(name=generate_id()) + response = self.client.post( + reverse("authentik_api:group-remove-user", kwargs={"pk": group.group_uuid}), + data={ + "pk": user.pk, + }, + ) + self.assertEqual(response.status_code, 204) + events = Event.objects.filter( + action=EventAction.MODEL_UPDATED, + context__model__model_name="group", + context__model__app="authentik_core", + context__model__pk=group.pk.hex, + ) + event = events.first() + self.assertIsNotNone(event) + self.assertIsNotNone(event.context["diff"]) + diff = event.context["diff"] + self.assertEqual( + diff, + {"users": {"remove": [user.pk]}}, + ) diff --git a/authentik/enterprise/license.py b/authentik/enterprise/license.py new file mode 100644 index 0000000000..1d2062811e --- /dev/null +++ b/authentik/enterprise/license.py @@ -0,0 +1,208 @@ +"""Enterprise license""" + +from base64 import b64decode +from binascii import Error +from dataclasses import asdict, dataclass, field +from datetime import datetime, timedelta +from enum import Enum +from functools import lru_cache +from time import mktime + +from cryptography.exceptions import InvalidSignature +from cryptography.x509 import Certificate, load_der_x509_certificate, load_pem_x509_certificate +from dacite import from_dict +from django.core.cache import cache +from django.db.models.query import QuerySet +from django.utils.timezone import now +from jwt import PyJWTError, decode, get_unverified_header +from rest_framework.exceptions import ValidationError +from rest_framework.fields import BooleanField, DateTimeField, IntegerField + +from authentik.core.api.utils import PassiveSerializer +from authentik.core.models import User, UserTypes +from authentik.enterprise.models import License, LicenseUsage +from authentik.tenants.utils import get_unique_identifier + +CACHE_KEY_ENTERPRISE_LICENSE = "goauthentik.io/enterprise/license" +CACHE_EXPIRY_ENTERPRISE_LICENSE = 3 * 60 * 60 # 2 Hours + + +@lru_cache +def get_licensing_key() -> Certificate: + """Get Root CA PEM""" + with open("authentik/enterprise/public.pem", "rb") as _key: + return load_pem_x509_certificate(_key.read()) + + +def get_license_aud() -> str: + """Get the JWT audience field""" + return f"enterprise.goauthentik.io/license/{get_unique_identifier()}" + + +class LicenseFlags(Enum): + """License flags""" + + +@dataclass +class LicenseSummary: + """Internal representation of a license summary""" + + internal_users: int + external_users: int + valid: bool + show_admin_warning: bool + show_user_warning: bool + read_only: bool + latest_valid: datetime + has_license: bool + + +class LicenseSummarySerializer(PassiveSerializer): + """Serializer for license status""" + + internal_users = IntegerField(required=True) + external_users = IntegerField(required=True) + valid = BooleanField() + show_admin_warning = BooleanField() + show_user_warning = BooleanField() + read_only = BooleanField() + latest_valid = DateTimeField() + has_license = BooleanField() + + +@dataclass +class LicenseKey: + """License JWT claims""" + + aud: str + exp: int + + name: str + internal_users: int = 0 + external_users: int = 0 + flags: list[LicenseFlags] = field(default_factory=list) + + @staticmethod + def validate(jwt: str) -> "LicenseKey": + """Validate the license from a given JWT""" + try: + headers = get_unverified_header(jwt) + except PyJWTError: + raise ValidationError("Unable to verify license") from None + x5c: list[str] = headers.get("x5c", []) + if len(x5c) < 1: + raise ValidationError("Unable to verify license") + try: + our_cert = load_der_x509_certificate(b64decode(x5c[0])) + intermediate = load_der_x509_certificate(b64decode(x5c[1])) + our_cert.verify_directly_issued_by(intermediate) + intermediate.verify_directly_issued_by(get_licensing_key()) + except (InvalidSignature, TypeError, ValueError, Error): + raise ValidationError("Unable to verify license") from None + try: + body = from_dict( + LicenseKey, + decode( + jwt, + our_cert.public_key(), + algorithms=["ES512"], + audience=get_license_aud(), + ), + ) + except PyJWTError: + raise ValidationError("Unable to verify license") from None + return body + + @staticmethod + def get_total() -> "LicenseKey": + """Get a summarized version of all (not expired) licenses""" + active_licenses = License.objects.filter(expiry__gte=now()) + total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0) + for lic in active_licenses: + total.internal_users += lic.internal_users + total.external_users += lic.external_users + exp_ts = int(mktime(lic.expiry.timetuple())) + if total.exp == 0: + total.exp = exp_ts + if exp_ts <= total.exp: + total.exp = exp_ts + total.flags.extend(lic.status.flags) + return total + + @staticmethod + def base_user_qs() -> QuerySet: + """Base query set for all users""" + return User.objects.all().exclude_anonymous().exclude(is_active=False) + + @staticmethod + def get_default_user_count(): + """Get current default user count""" + return LicenseKey.base_user_qs().filter(type=UserTypes.INTERNAL).count() + + @staticmethod + def get_external_user_count(): + """Get current external user count""" + return LicenseKey.base_user_qs().filter(type=UserTypes.EXTERNAL).count() + + def is_valid(self) -> bool: + """Check if the given license body covers all users + + Only checks the current count, no historical data is checked""" + default_users = self.get_default_user_count() + if default_users > self.internal_users: + return False + active_users = self.get_external_user_count() + if active_users > self.external_users: + return False + return True + + def record_usage(self): + """Capture the current validity status and metrics and save them""" + threshold = now() - timedelta(hours=8) + if not LicenseUsage.objects.filter(record_date__gte=threshold).exists(): + LicenseUsage.objects.create( + user_count=self.get_default_user_count(), + external_user_count=self.get_external_user_count(), + within_limits=self.is_valid(), + ) + summary = asdict(self.summary()) + # Also cache the latest summary for the middleware + cache.set(CACHE_KEY_ENTERPRISE_LICENSE, summary, timeout=CACHE_EXPIRY_ENTERPRISE_LICENSE) + return summary + + @staticmethod + def last_valid_date() -> datetime: + """Get the last date the license was valid""" + usage: LicenseUsage = ( + LicenseUsage.filter_not_expired(within_limits=True).order_by("-record_date").first() + ) + if not usage: + return now() + return usage.record_date + + def summary(self) -> LicenseSummary: + """Summary of license status""" + has_license = License.objects.all().count() > 0 + last_valid = LicenseKey.last_valid_date() + show_admin_warning = last_valid < now() - timedelta(weeks=2) + show_user_warning = last_valid < now() - timedelta(weeks=4) + read_only = last_valid < now() - timedelta(weeks=6) + latest_valid = datetime.fromtimestamp(self.exp) + return LicenseSummary( + show_admin_warning=show_admin_warning and has_license, + show_user_warning=show_user_warning and has_license, + read_only=read_only and has_license, + latest_valid=latest_valid, + internal_users=self.internal_users, + external_users=self.external_users, + valid=self.is_valid(), + has_license=has_license, + ) + + @staticmethod + def cached_summary() -> LicenseSummary: + """Helper method which looks up the last summary""" + summary = cache.get(CACHE_KEY_ENTERPRISE_LICENSE) + if not summary: + return LicenseKey.get_total().summary() + return from_dict(LicenseSummary, summary) diff --git a/authentik/enterprise/middleware.py b/authentik/enterprise/middleware.py new file mode 100644 index 0000000000..83ff8af05f --- /dev/null +++ b/authentik/enterprise/middleware.py @@ -0,0 +1,64 @@ +"""Enterprise middleware""" + +from collections.abc import Callable + +from django.http import HttpRequest, HttpResponse, JsonResponse +from django.urls import resolve +from structlog.stdlib import BoundLogger, get_logger + +from authentik.enterprise.api import LicenseViewSet +from authentik.enterprise.license import LicenseKey +from authentik.flows.views.executor import FlowExecutorView +from authentik.lib.utils.reflection import class_to_path + + +class EnterpriseMiddleware: + """Enterprise middleware""" + + get_response: Callable[[HttpRequest], HttpResponse] + logger: BoundLogger + + def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]): + self.get_response = get_response + self.logger = get_logger().bind() + + def __call__(self, request: HttpRequest) -> HttpResponse: + resolver_match = resolve(request.path_info) + request.resolver_match = resolver_match + if not self.is_request_allowed(request): + self.logger.warning("Refusing request due to expired/invalid license") + return JsonResponse( + { + "detail": "Request denied due to expired/invalid license.", + "code": "denied_license", + }, + status=400, + ) + return self.get_response(request) + + def is_request_allowed(self, request: HttpRequest) -> bool: + """Check if a specific request is allowed""" + if self.is_request_always_allowed(request): + return True + cached_status = LicenseKey.cached_summary() + if not cached_status: + return True + if cached_status.read_only: + return False + return True + + def is_request_always_allowed(self, request: HttpRequest): + """Check if a request is always allowed""" + # Always allow "safe" methods + if request.method.lower() in ["get", "head", "options", "trace"]: + return True + # Always allow requests to manage licenses + if class_to_path(request.resolver_match.func) == class_to_path(LicenseViewSet): + return True + # Flow executor is mounted as an API path but explicitly allowed + if class_to_path(request.resolver_match.func) == class_to_path(FlowExecutorView): + return True + # Only apply these restrictions to the API + if "authentik_api" not in request.resolver_match.app_names: + return True + return False diff --git a/authentik/enterprise/models.py b/authentik/enterprise/models.py index ee9da113e0..6600e5c07a 100644 --- a/authentik/enterprise/models.py +++ b/authentik/enterprise/models.py @@ -1,159 +1,20 @@ """Enterprise models""" -from base64 import b64decode -from binascii import Error -from dataclasses import dataclass, field -from datetime import datetime, timedelta -from enum import Enum -from functools import lru_cache -from time import mktime + +from datetime import timedelta +from typing import TYPE_CHECKING from uuid import uuid4 -from cryptography.exceptions import InvalidSignature -from cryptography.x509 import Certificate, load_der_x509_certificate, load_pem_x509_certificate -from dacite import from_dict from django.contrib.postgres.indexes import HashIndex from django.db import models -from django.db.models.query import QuerySet from django.utils.timezone import now from django.utils.translation import gettext as _ -from guardian.shortcuts import get_anonymous_user -from jwt import PyJWTError, decode, get_unverified_header -from rest_framework.exceptions import ValidationError from rest_framework.serializers import BaseSerializer -from authentik.core.models import ExpiringModel, User, UserTypes +from authentik.core.models import ExpiringModel from authentik.lib.models import SerializerModel -from authentik.root.install_id import get_install_id - -@lru_cache() -def get_licensing_key() -> Certificate: - """Get Root CA PEM""" - with open("authentik/enterprise/public.pem", "rb") as _key: - return load_pem_x509_certificate(_key.read()) - - -def get_license_aud() -> str: - """Get the JWT audience field""" - return f"enterprise.goauthentik.io/license/{get_install_id()}" - - -class LicenseFlags(Enum): - """License flags""" - - -@dataclass -class LicenseKey: - """License JWT claims""" - - aud: str - exp: int - - name: str - internal_users: int = 0 - external_users: int = 0 - flags: list[LicenseFlags] = field(default_factory=list) - - @staticmethod - def validate(jwt: str) -> "LicenseKey": - """Validate the license from a given JWT""" - try: - headers = get_unverified_header(jwt) - except PyJWTError: - raise ValidationError("Unable to verify license") - x5c: list[str] = headers.get("x5c", []) - if len(x5c) < 1: - raise ValidationError("Unable to verify license") - try: - our_cert = load_der_x509_certificate(b64decode(x5c[0])) - intermediate = load_der_x509_certificate(b64decode(x5c[1])) - our_cert.verify_directly_issued_by(intermediate) - intermediate.verify_directly_issued_by(get_licensing_key()) - except (InvalidSignature, TypeError, ValueError, Error): - raise ValidationError("Unable to verify license") - try: - body = from_dict( - LicenseKey, - decode( - jwt, - our_cert.public_key(), - algorithms=["ES512"], - audience=get_license_aud(), - ), - ) - except PyJWTError: - raise ValidationError("Unable to verify license") - return body - - @staticmethod - def get_total() -> "LicenseKey": - """Get a summarized version of all (not expired) licenses""" - active_licenses = License.objects.filter(expiry__gte=now()) - total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0) - for lic in active_licenses: - total.internal_users += lic.internal_users - total.external_users += lic.external_users - exp_ts = int(mktime(lic.expiry.timetuple())) - if total.exp == 0: - total.exp = exp_ts - if exp_ts <= total.exp: - total.exp = exp_ts - total.flags.extend(lic.status.flags) - return total - - @staticmethod - def base_user_qs() -> QuerySet: - """Base query set for all users""" - return User.objects.all().exclude(is_active=False).exclude(pk=get_anonymous_user().pk) - - @staticmethod - def get_default_user_count(): - """Get current default user count""" - return LicenseKey.base_user_qs().filter(type=UserTypes.INTERNAL).count() - - @staticmethod - def get_external_user_count(): - """Get current external user count""" - # Count since start of the month - last_month = now().replace(day=1) - return ( - LicenseKey.base_user_qs() - .filter(type=UserTypes.EXTERNAL, last_login__gte=last_month) - .count() - ) - - def is_valid(self) -> bool: - """Check if the given license body covers all users - - Only checks the current count, no historical data is checked""" - default_users = self.get_default_user_count() - if default_users > self.internal_users: - return False - active_users = self.get_external_user_count() - if active_users > self.external_users: - return False - return True - - def record_usage(self): - """Capture the current validity status and metrics and save them""" - threshold = now() - timedelta(hours=8) - if LicenseUsage.objects.filter(record_date__gte=threshold).exists(): - return - LicenseUsage.objects.create( - user_count=self.get_default_user_count(), - external_user_count=self.get_external_user_count(), - within_limits=self.is_valid(), - ) - - @staticmethod - def last_valid_date() -> datetime: - """Get the last date the license was valid""" - usage: LicenseUsage = ( - LicenseUsage.filter_not_expired(within_limits=True).order_by("-record_date").first() - ) - if not usage: - return now() - return usage.record_date +if TYPE_CHECKING: + from authentik.enterprise.license import LicenseKey class License(SerializerModel): @@ -174,8 +35,10 @@ class License(SerializerModel): return LicenseSerializer @property - def status(self) -> LicenseKey: + def status(self) -> "LicenseKey": """Get parsed license status""" + from authentik.enterprise.license import LicenseKey + return LicenseKey.validate(self.key) class Meta: diff --git a/authentik/enterprise/policy.py b/authentik/enterprise/policy.py index 20bf438a0e..904c3f73ee 100644 --- a/authentik/enterprise/policy.py +++ b/authentik/enterprise/policy.py @@ -1,10 +1,9 @@ """Enterprise license policies""" -from typing import Optional from django.utils.translation import gettext_lazy as _ from authentik.core.models import User, UserTypes -from authentik.enterprise.models import LicenseKey +from authentik.enterprise.license import LicenseKey from authentik.policies.types import PolicyRequest, PolicyResult from authentik.policies.views import PolicyAccessView @@ -20,7 +19,7 @@ class EnterprisePolicyAccessView(PolicyAccessView): return PolicyResult(False, _("Feature only accessible for internal users.")) return PolicyResult(True) - def user_has_access(self, user: Optional[User] = None) -> PolicyResult: + def user_has_access(self, user: User | None = None) -> PolicyResult: user = user or self.request.user request = PolicyRequest(user) request.http_request = self.request diff --git a/website/help/.gitkeep b/authentik/enterprise/providers/google_workspace/__init__.py similarity index 100% rename from website/help/.gitkeep rename to authentik/enterprise/providers/google_workspace/__init__.py diff --git a/authentik/enterprise/providers/google_workspace/api/__init__.py b/authentik/enterprise/providers/google_workspace/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/google_workspace/api/groups.py b/authentik/enterprise/providers/google_workspace/api/groups.py new file mode 100644 index 0000000000..7317a5a733 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/api/groups.py @@ -0,0 +1,33 @@ +"""GoogleWorkspaceProviderGroup API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.users import UserGroupSerializer +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderGroup + + +class GoogleWorkspaceProviderGroupSerializer(SourceSerializer): + """GoogleWorkspaceProviderGroup Serializer""" + + group_obj = UserGroupSerializer(source="group", read_only=True) + + class Meta: + + model = GoogleWorkspaceProviderGroup + fields = [ + "id", + "group", + "group_obj", + ] + + +class GoogleWorkspaceProviderGroupViewSet(UsedByMixin, ModelViewSet): + """GoogleWorkspaceProviderGroup Viewset""" + + queryset = GoogleWorkspaceProviderGroup.objects.all().select_related("group") + serializer_class = GoogleWorkspaceProviderGroupSerializer + filterset_fields = ["provider__id", "group__name", "group__group_uuid"] + search_fields = ["provider__name", "group__name"] + ordering = ["group__name"] diff --git a/authentik/enterprise/providers/google_workspace/api/property_mappings.py b/authentik/enterprise/providers/google_workspace/api/property_mappings.py new file mode 100644 index 0000000000..effb55e0b4 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/api/property_mappings.py @@ -0,0 +1,39 @@ +"""google Property mappings API Views""" + +from django_filters.filters import AllValuesMultipleFilter +from django_filters.filterset import FilterSet +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema_field +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.property_mappings import PropertyMappingSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderMapping + + +class GoogleWorkspaceProviderMappingSerializer(PropertyMappingSerializer): + """GoogleWorkspaceProviderMapping Serializer""" + + class Meta: + model = GoogleWorkspaceProviderMapping + fields = PropertyMappingSerializer.Meta.fields + + +class GoogleWorkspaceProviderMappingFilter(FilterSet): + """Filter for GoogleWorkspaceProviderMapping""" + + managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed")) + + class Meta: + model = GoogleWorkspaceProviderMapping + fields = "__all__" + + +class GoogleWorkspaceProviderMappingViewSet(UsedByMixin, ModelViewSet): + """GoogleWorkspaceProviderMapping Viewset""" + + queryset = GoogleWorkspaceProviderMapping.objects.all() + serializer_class = GoogleWorkspaceProviderMappingSerializer + filterset_class = GoogleWorkspaceProviderMappingFilter + search_fields = ["name"] + ordering = ["name"] diff --git a/authentik/enterprise/providers/google_workspace/api/providers.py b/authentik/enterprise/providers/google_workspace/api/providers.py new file mode 100644 index 0000000000..392ff9ea4f --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/api/providers.py @@ -0,0 +1,54 @@ +"""Google Provider API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.api import EnterpriseRequiredMixin +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider +from authentik.enterprise.providers.google_workspace.tasks import google_workspace_sync +from authentik.lib.sync.outgoing.api import OutgoingSyncProviderStatusMixin + + +class GoogleWorkspaceProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer): + """GoogleWorkspaceProvider Serializer""" + + class Meta: + model = GoogleWorkspaceProvider + fields = [ + "pk", + "name", + "property_mappings", + "property_mappings_group", + "component", + "assigned_backchannel_application_slug", + "assigned_backchannel_application_name", + "verbose_name", + "verbose_name_plural", + "meta_model_name", + "delegated_subject", + "credentials", + "scopes", + "exclude_users_service_account", + "filter_group", + "user_delete_action", + "group_delete_action", + "default_group_email_domain", + ] + extra_kwargs = {} + + +class GoogleWorkspaceProviderViewSet(OutgoingSyncProviderStatusMixin, UsedByMixin, ModelViewSet): + """GoogleWorkspaceProvider Viewset""" + + queryset = GoogleWorkspaceProvider.objects.all() + serializer_class = GoogleWorkspaceProviderSerializer + filterset_fields = [ + "name", + "exclude_users_service_account", + "delegated_subject", + "filter_group", + ] + search_fields = ["name"] + ordering = ["name"] + sync_single_task = google_workspace_sync diff --git a/authentik/enterprise/providers/google_workspace/api/users.py b/authentik/enterprise/providers/google_workspace/api/users.py new file mode 100644 index 0000000000..a0fa658e3d --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/api/users.py @@ -0,0 +1,33 @@ +"""GoogleWorkspaceProviderUser API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.groups import GroupMemberSerializer +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderUser + + +class GoogleWorkspaceProviderUserSerializer(SourceSerializer): + """GoogleWorkspaceProviderUser Serializer""" + + user_obj = GroupMemberSerializer(source="user", read_only=True) + + class Meta: + + model = GoogleWorkspaceProviderUser + fields = [ + "id", + "user", + "user_obj", + ] + + +class GoogleWorkspaceProviderUserViewSet(UsedByMixin, ModelViewSet): + """GoogleWorkspaceProviderUser Viewset""" + + queryset = GoogleWorkspaceProviderUser.objects.all().select_related("user") + serializer_class = GoogleWorkspaceProviderUserSerializer + filterset_fields = ["provider__id", "user__username", "user__id"] + search_fields = ["provider__name", "user__username"] + ordering = ["user__username"] diff --git a/authentik/enterprise/providers/google_workspace/apps.py b/authentik/enterprise/providers/google_workspace/apps.py new file mode 100644 index 0000000000..dc79da2fc1 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/apps.py @@ -0,0 +1,9 @@ +from authentik.enterprise.apps import EnterpriseConfig + + +class AuthentikEnterpriseProviderGoogleConfig(EnterpriseConfig): + + name = "authentik.enterprise.providers.google_workspace" + label = "authentik_providers_google_workspace" + verbose_name = "authentik Enterprise.Providers.Google Workspace" + default = True diff --git a/authentik/enterprise/providers/google_workspace/clients/__init__.py b/authentik/enterprise/providers/google_workspace/clients/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/google_workspace/clients/base.py b/authentik/enterprise/providers/google_workspace/clients/base.py new file mode 100644 index 0000000000..8eebe13f6c --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/clients/base.py @@ -0,0 +1,74 @@ +from django.db.models import Model +from django.http import HttpResponseBadRequest, HttpResponseNotFound +from google.auth.exceptions import GoogleAuthError, TransportError +from googleapiclient.discovery import build +from googleapiclient.errors import Error, HttpError +from googleapiclient.http import HttpRequest +from httplib2 import HttpLib2Error, HttpLib2ErrorWithResponse + +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider +from authentik.lib.sync.outgoing import HTTP_CONFLICT +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.exceptions import ( + BadRequestSyncException, + NotFoundSyncException, + ObjectExistsSyncException, + StopSync, + TransientSyncException, +) + + +class GoogleWorkspaceSyncClient[TModel: Model, TConnection: Model, TSchema: dict]( + BaseOutgoingSyncClient[TModel, TConnection, TSchema, GoogleWorkspaceProvider] +): + """Base client for syncing to google workspace""" + + domains: list + + def __init__(self, provider: GoogleWorkspaceProvider) -> None: + super().__init__(provider) + self.directory_service = build( + "admin", + "directory_v1", + cache_discovery=False, + **provider.google_credentials(), + ) + self.__prefetch_domains() + + def __prefetch_domains(self): + self.domains = [] + domains = self._request(self.directory_service.domains().list(customer="my_customer")) + for domain in domains.get("domains", []): + domain_name = domain.get("domainName") + self.domains.append(domain_name) + + def _request(self, request: HttpRequest): + try: + response = request.execute() + except GoogleAuthError as exc: + if isinstance(exc, TransportError): + raise TransientSyncException(f"Failed to send request: {str(exc)}") from exc + raise StopSync(exc) from exc + except HttpLib2Error as exc: + if isinstance(exc, HttpLib2ErrorWithResponse): + self._response_handle_status_code(request.body, exc.response.status, exc) + raise TransientSyncException(f"Failed to send request: {str(exc)}") from exc + except HttpError as exc: + self._response_handle_status_code(request.body, exc.status_code, exc) + raise TransientSyncException(f"Failed to send request: {str(exc)}") from exc + except Error as exc: + raise TransientSyncException(f"Failed to send request: {str(exc)}") from exc + return response + + def _response_handle_status_code(self, request: dict, status_code: int, root_exc: Exception): + if status_code == HttpResponseNotFound.status_code: + raise NotFoundSyncException("Object not found") from root_exc + if status_code == HTTP_CONFLICT: + raise ObjectExistsSyncException("Object exists") from root_exc + if status_code == HttpResponseBadRequest.status_code: + raise BadRequestSyncException("Bad request", request) from root_exc + + def check_email_valid(self, *emails: str): + for email in emails: + if not any(email.endswith(f"@{domain_name}") for domain_name in self.domains): + raise BadRequestSyncException(f"Invalid email domain: {email}") diff --git a/authentik/enterprise/providers/google_workspace/clients/groups.py b/authentik/enterprise/providers/google_workspace/clients/groups.py new file mode 100644 index 0000000000..aeb0ac63e8 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/clients/groups.py @@ -0,0 +1,207 @@ +from django.db import transaction +from django.utils.text import slugify + +from authentik.core.models import Group +from authentik.enterprise.providers.google_workspace.clients.base import GoogleWorkspaceSyncClient +from authentik.enterprise.providers.google_workspace.models import ( + GoogleWorkspaceProvider, + GoogleWorkspaceProviderGroup, + GoogleWorkspaceProviderMapping, + GoogleWorkspaceProviderUser, +) +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.base import Direction +from authentik.lib.sync.outgoing.exceptions import ( + NotFoundSyncException, + ObjectExistsSyncException, + TransientSyncException, +) +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction + + +class GoogleWorkspaceGroupClient( + GoogleWorkspaceSyncClient[Group, GoogleWorkspaceProviderGroup, dict] +): + """Google client for groups""" + + connection_type = GoogleWorkspaceProviderGroup + connection_type_query = "group" + can_discover = True + + def __init__(self, provider: GoogleWorkspaceProvider) -> None: + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings_group.all().order_by("name").select_subclasses(), + GoogleWorkspaceProviderMapping, + ["group", "provider", "creating"], + ) + + def to_schema(self, obj: Group, creating: bool) -> dict: + """Convert authentik group""" + return super().to_schema( + obj, + creating, + email=f"{slugify(obj.name)}@{self.provider.default_group_email_domain}", + ) + + def delete(self, obj: Group): + """Delete group""" + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=obj + ).first() + if not google_group: + self.logger.debug("Group does not exist in Google, skipping") + return None + with transaction.atomic(): + if self.provider.group_delete_action == OutgoingSyncDeleteAction.DELETE: + self._request( + self.directory_service.groups().delete(groupKey=google_group.google_id) + ) + google_group.delete() + + def create(self, group: Group): + """Create group from scratch and create a connection object""" + google_group = self.to_schema(group, True) + self.check_email_valid(google_group["email"]) + with transaction.atomic(): + try: + response = self._request(self.directory_service.groups().insert(body=google_group)) + except ObjectExistsSyncException: + # group already exists in google workspace, so we can connect them manually + # for groups we need to fetch the group from google as we connect on + # ID and not group email + group_data = self._request( + self.directory_service.groups().get(groupKey=google_group["email"]) + ) + return GoogleWorkspaceProviderGroup.objects.create( + provider=self.provider, group=group, google_id=group_data["id"] + ) + else: + return GoogleWorkspaceProviderGroup.objects.create( + provider=self.provider, group=group, google_id=response["id"] + ) + + def update(self, group: Group, connection: GoogleWorkspaceProviderGroup): + """Update existing group""" + google_group = self.to_schema(group, False) + self.check_email_valid(google_group["email"]) + try: + return self._request( + self.directory_service.groups().update( + groupKey=connection.google_id, + body=google_group, + ) + ) + except NotFoundSyncException: + # Resource missing is handled by self.write, which will re-create the group + raise + + def write(self, obj: Group): + google_group, created = super().write(obj) + self.create_sync_members(obj, google_group) + return google_group, created + + def create_sync_members(self, obj: Group, google_group: GoogleWorkspaceProviderGroup): + """Sync all members after a group was created""" + users = list(obj.users.order_by("id").values_list("id", flat=True)) + connections = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user__pk__in=users + ).values_list("google_id", flat=True) + self._patch(google_group.google_id, Direction.add, connections) + + def update_group(self, group: Group, action: Direction, users_set: set[int]): + """Update a groups members""" + if action == Direction.add: + return self._patch_add_users(group, users_set) + if action == Direction.remove: + return self._patch_remove_users(group, users_set) + + def _patch(self, google_group_id: str, direction: Direction, members: list[str]): + for user in members: + try: + if direction == Direction.add: + self._request( + self.directory_service.members().insert( + groupKey=google_group_id, body={"email": user} + ) + ) + if direction == Direction.remove: + self._request( + self.directory_service.members().delete( + groupKey=google_group_id, memberKey=user + ) + ) + except ObjectExistsSyncException: + pass + except TransientSyncException: + raise + + def _patch_add_users(self, group: Group, users_set: set[int]): + """Add users in users_set to group""" + if len(users_set) < 1: + return + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + if not google_group: + self.logger.warning( + "could not sync group membership, group does not exist", group=group + ) + return + user_ids = list( + GoogleWorkspaceProviderUser.objects.filter( + user__pk__in=users_set, provider=self.provider + ).values_list("google_id", flat=True) + ) + if len(user_ids) < 1: + return + self._patch(google_group.google_id, Direction.add, user_ids) + + def _patch_remove_users(self, group: Group, users_set: set[int]): + """Remove users in users_set from group""" + if len(users_set) < 1: + return + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + if not google_group: + self.logger.warning( + "could not sync group membership, group does not exist", group=group + ) + return + user_ids = list( + GoogleWorkspaceProviderUser.objects.filter( + user__pk__in=users_set, provider=self.provider + ).values_list("google_id", flat=True) + ) + if len(user_ids) < 1: + return + self._patch(google_group.google_id, Direction.remove, user_ids) + + def discover(self): + """Iterate through all groups and connect them with authentik groups if possible""" + request = self.directory_service.groups().list( + customer="my_customer", maxResults=500, orderBy="email" + ) + while request: + response = request.execute() + for group in response.get("groups", []): + self._discover_single_group(group) + request = self.directory_service.groups().list_next( + previous_request=request, previous_response=response + ) + + def _discover_single_group(self, group: dict): + """handle discovery of a single group""" + google_name = group["name"] + google_id = group["id"] + matching_authentik_group = ( + self.provider.get_object_qs(Group).filter(name=google_name).first() + ) + if not matching_authentik_group: + return + GoogleWorkspaceProviderGroup.objects.get_or_create( + provider=self.provider, + group=matching_authentik_group, + google_id=google_id, + ) diff --git a/authentik/enterprise/providers/google_workspace/clients/test_http.py b/authentik/enterprise/providers/google_workspace/clients/test_http.py new file mode 100644 index 0000000000..307840f36c --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/clients/test_http.py @@ -0,0 +1,41 @@ +from json import dumps + +from httplib2 import Response + + +class MockHTTP: + + _recorded_requests = [] + _responses = {} + + def __init__( + self, + raise_on_unrecorded=True, + ) -> None: + self._recorded_requests = [] + self._responses = {} + self.raise_on_unrecorded = raise_on_unrecorded + + def add_response(self, uri: str, body: str | dict = "", meta: dict | None = None, method="GET"): + if isinstance(body, dict): + body = dumps(body) + self._responses[(uri, method.upper())] = (body, meta or {"status": "200"}) + + def requests(self): + return self._recorded_requests + + def request( + self, + uri, + method="GET", + body=None, + headers=None, + redirections=1, + connection_type=None, + ): + key = (uri, method.upper()) + self._recorded_requests.append((uri, method, body, headers)) + if key not in self._responses and self.raise_on_unrecorded: + raise AssertionError(key) + body, meta = self._responses[key] + return Response(meta), body.encode("utf-8") diff --git a/authentik/enterprise/providers/google_workspace/clients/users.py b/authentik/enterprise/providers/google_workspace/clients/users.py new file mode 100644 index 0000000000..52d60046bd --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/clients/users.py @@ -0,0 +1,118 @@ +from django.db import transaction + +from authentik.core.models import User +from authentik.enterprise.providers.google_workspace.clients.base import GoogleWorkspaceSyncClient +from authentik.enterprise.providers.google_workspace.models import ( + GoogleWorkspaceProvider, + GoogleWorkspaceProviderMapping, + GoogleWorkspaceProviderUser, +) +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.exceptions import ( + ObjectExistsSyncException, + TransientSyncException, +) +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.policies.utils import delete_none_values + + +class GoogleWorkspaceUserClient(GoogleWorkspaceSyncClient[User, GoogleWorkspaceProviderUser, dict]): + """Sync authentik users into google workspace""" + + connection_type = GoogleWorkspaceProviderUser + connection_type_query = "user" + can_discover = True + + def __init__(self, provider: GoogleWorkspaceProvider) -> None: + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings.all().order_by("name").select_subclasses(), + GoogleWorkspaceProviderMapping, + ["provider", "creating"], + ) + + def to_schema(self, obj: User, creating: bool) -> dict: + """Convert authentik user""" + raw_google_user = super().to_schema(obj, creating) + if "primaryEmail" not in raw_google_user: + raw_google_user["primaryEmail"] = str(obj.email) + return delete_none_values(raw_google_user) + + def delete(self, obj: User): + """Delete user""" + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=obj + ).first() + if not google_user: + self.logger.debug("User does not exist in Google, skipping") + return None + with transaction.atomic(): + response = None + if self.provider.user_delete_action == OutgoingSyncDeleteAction.DELETE: + response = self._request( + self.directory_service.users().delete(userKey=google_user.google_id) + ) + elif self.provider.user_delete_action == OutgoingSyncDeleteAction.SUSPEND: + response = self._request( + self.directory_service.users().update( + userKey=google_user.google_id, body={"suspended": True} + ) + ) + google_user.delete() + return response + + def create(self, user: User): + """Create user from scratch and create a connection object""" + google_user = self.to_schema(user, True) + self.check_email_valid( + google_user["primaryEmail"], *[x["address"] for x in google_user.get("emails", [])] + ) + with transaction.atomic(): + try: + response = self._request(self.directory_service.users().insert(body=google_user)) + except ObjectExistsSyncException: + # user already exists in google workspace, so we can connect them manually + return GoogleWorkspaceProviderUser.objects.create( + provider=self.provider, user=user, google_id=user.email + ) + except TransientSyncException as exc: + raise exc + else: + return GoogleWorkspaceProviderUser.objects.create( + provider=self.provider, user=user, google_id=response["primaryEmail"] + ) + + def update(self, user: User, connection: GoogleWorkspaceProviderUser): + """Update existing user""" + google_user = self.to_schema(user, False) + self.check_email_valid( + google_user["primaryEmail"], *[x["address"] for x in google_user.get("emails", [])] + ) + self._request( + self.directory_service.users().update(userKey=connection.google_id, body=google_user) + ) + + def discover(self): + """Iterate through all users and connect them with authentik users if possible""" + request = self.directory_service.users().list( + customer="my_customer", maxResults=500, orderBy="email" + ) + while request: + response = request.execute() + for user in response.get("users", []): + self._discover_single_user(user) + request = self.directory_service.users().list_next( + previous_request=request, previous_response=response + ) + + def _discover_single_user(self, user: dict): + """handle discovery of a single user""" + email = user["primaryEmail"] + matching_authentik_user = self.provider.get_object_qs(User).filter(email=email).first() + if not matching_authentik_user: + return + GoogleWorkspaceProviderUser.objects.get_or_create( + provider=self.provider, + user=matching_authentik_user, + google_id=email, + ) diff --git a/authentik/enterprise/providers/google_workspace/migrations/0001_initial.py b/authentik/enterprise/providers/google_workspace/migrations/0001_initial.py new file mode 100644 index 0000000000..502891eb12 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/migrations/0001_initial.py @@ -0,0 +1,167 @@ +# Generated by Django 5.0.4 on 2024-05-07 16:03 + +import django.db.models.deletion +import uuid +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("authentik_core", "0035_alter_group_options_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="GoogleWorkspaceProviderMapping", + fields=[ + ( + "propertymapping_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Google Workspace Provider Mapping", + "verbose_name_plural": "Google Workspace Provider Mappings", + }, + bases=("authentik_core.propertymapping",), + ), + migrations.CreateModel( + name="GoogleWorkspaceProvider", + fields=[ + ( + "provider_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.provider", + ), + ), + ("delegated_subject", models.EmailField(max_length=254)), + ("credentials", models.JSONField()), + ( + "scopes", + models.TextField( + default="https://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.group.member,https://www.googleapis.com/auth/admin.directory.domain.readonly" + ), + ), + ("default_group_email_domain", models.TextField()), + ("exclude_users_service_account", models.BooleanField(default=False)), + ( + "user_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "group_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "filter_group", + models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_core.group", + ), + ), + ( + "property_mappings_group", + models.ManyToManyField( + blank=True, + default=None, + help_text="Property mappings used for group creation/updating.", + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Google Workspace Provider", + "verbose_name_plural": "Google Workspace Providers", + }, + bases=("authentik_core.provider", models.Model), + ), + migrations.CreateModel( + name="GoogleWorkspaceProviderGroup", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("google_id", models.TextField()), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group" + ), + ), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_google_workspace.googleworkspaceprovider", + ), + ), + ], + options={ + "unique_together": {("google_id", "group", "provider")}, + }, + ), + migrations.CreateModel( + name="GoogleWorkspaceProviderUser", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("google_id", models.TextField()), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_google_workspace.googleworkspaceprovider", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ], + options={ + "unique_together": {("google_id", "user", "provider")}, + }, + ), + ] diff --git a/authentik/enterprise/providers/google_workspace/migrations/0001_squashed_0002_alter_googleworkspaceprovidergroup_options_and_more.py b/authentik/enterprise/providers/google_workspace/migrations/0001_squashed_0002_alter_googleworkspaceprovidergroup_options_and_more.py new file mode 100644 index 0000000000..e430328f75 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/migrations/0001_squashed_0002_alter_googleworkspaceprovidergroup_options_and_more.py @@ -0,0 +1,179 @@ +# Generated by Django 5.0.6 on 2024-05-09 12:57 + +import django.db.models.deletion +import uuid +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [ + ("authentik_providers_google_workspace", "0001_initial"), + ( + "authentik_providers_google_workspace", + "0002_alter_googleworkspaceprovidergroup_options_and_more", + ), + ] + + initial = True + + dependencies = [ + ("authentik_core", "0035_alter_group_options_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="GoogleWorkspaceProviderMapping", + fields=[ + ( + "propertymapping_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Google Workspace Provider Mapping", + "verbose_name_plural": "Google Workspace Provider Mappings", + }, + bases=("authentik_core.propertymapping",), + ), + migrations.CreateModel( + name="GoogleWorkspaceProvider", + fields=[ + ( + "provider_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.provider", + ), + ), + ("delegated_subject", models.EmailField(max_length=254)), + ("credentials", models.JSONField()), + ( + "scopes", + models.TextField( + default="https://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.group.member,https://www.googleapis.com/auth/admin.directory.domain.readonly" + ), + ), + ("default_group_email_domain", models.TextField()), + ("exclude_users_service_account", models.BooleanField(default=False)), + ( + "user_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "group_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "filter_group", + models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_core.group", + ), + ), + ( + "property_mappings_group", + models.ManyToManyField( + blank=True, + default=None, + help_text="Property mappings used for group creation/updating.", + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Google Workspace Provider", + "verbose_name_plural": "Google Workspace Providers", + }, + bases=("authentik_core.provider", models.Model), + ), + migrations.CreateModel( + name="GoogleWorkspaceProviderGroup", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("google_id", models.TextField()), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group" + ), + ), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_google_workspace.googleworkspaceprovider", + ), + ), + ], + options={ + "unique_together": {("google_id", "group", "provider")}, + "verbose_name": "Google Workspace Provider Group", + "verbose_name_plural": "Google Workspace Provider Groups", + }, + ), + migrations.CreateModel( + name="GoogleWorkspaceProviderUser", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("google_id", models.TextField()), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_google_workspace.googleworkspaceprovider", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ], + options={ + "unique_together": {("google_id", "user", "provider")}, + "verbose_name": "Google Workspace Provider User", + "verbose_name_plural": "Google Workspace Provider Users", + }, + ), + ] diff --git a/authentik/enterprise/providers/google_workspace/migrations/0002_alter_googleworkspaceprovidergroup_options_and_more.py b/authentik/enterprise/providers/google_workspace/migrations/0002_alter_googleworkspaceprovidergroup_options_and_more.py new file mode 100644 index 0000000000..4f27a327e0 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/migrations/0002_alter_googleworkspaceprovidergroup_options_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.6 on 2024-05-08 14:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_providers_google_workspace", "0001_initial"), + ] + + operations = [ + migrations.AlterModelOptions( + name="googleworkspaceprovidergroup", + options={ + "verbose_name": "Google Workspace Provider Group", + "verbose_name_plural": "Google Workspace Provider Groups", + }, + ), + migrations.AlterModelOptions( + name="googleworkspaceprovideruser", + options={ + "verbose_name": "Google Workspace Provider User", + "verbose_name_plural": "Google Workspace Provider Users", + }, + ), + ] diff --git a/authentik/enterprise/providers/google_workspace/migrations/__init__.py b/authentik/enterprise/providers/google_workspace/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/google_workspace/models.py b/authentik/enterprise/providers/google_workspace/models.py new file mode 100644 index 0000000000..12ace4cb39 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/models.py @@ -0,0 +1,196 @@ +"""Google workspace sync provider""" + +from typing import Any, Self +from uuid import uuid4 + +from django.db import models +from django.db.models import QuerySet +from django.templatetags.static import static +from django.utils.translation import gettext_lazy as _ +from google.oauth2.service_account import Credentials +from rest_framework.serializers import Serializer + +from authentik.core.models import ( + BackchannelProvider, + Group, + PropertyMapping, + User, + UserTypes, +) +from authentik.lib.models import SerializerModel +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction, OutgoingSyncProvider + + +def default_scopes() -> list[str]: + return [ + "https://www.googleapis.com/auth/admin.directory.user", + "https://www.googleapis.com/auth/admin.directory.group", + "https://www.googleapis.com/auth/admin.directory.group.member", + "https://www.googleapis.com/auth/admin.directory.domain.readonly", + ] + + +class GoogleWorkspaceProvider(OutgoingSyncProvider, BackchannelProvider): + """Sync users from authentik into Google Workspace.""" + + delegated_subject = models.EmailField() + credentials = models.JSONField() + scopes = models.TextField(default=",".join(default_scopes())) + + default_group_email_domain = models.TextField() + exclude_users_service_account = models.BooleanField(default=False) + user_delete_action = models.TextField( + choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE + ) + group_delete_action = models.TextField( + choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE + ) + + filter_group = models.ForeignKey( + "authentik_core.group", on_delete=models.SET_DEFAULT, default=None, null=True + ) + + property_mappings_group = models.ManyToManyField( + PropertyMapping, + default=None, + blank=True, + help_text=_("Property mappings used for group creation/updating."), + ) + + def client_for_model( + self, model: type[User | Group] + ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: + if issubclass(model, User): + from authentik.enterprise.providers.google_workspace.clients.users import ( + GoogleWorkspaceUserClient, + ) + + return GoogleWorkspaceUserClient(self) + if issubclass(model, Group): + from authentik.enterprise.providers.google_workspace.clients.groups import ( + GoogleWorkspaceGroupClient, + ) + + return GoogleWorkspaceGroupClient(self) + raise ValueError(f"Invalid model {model}") + + def get_object_qs(self, type: type[User | Group]) -> QuerySet[User | Group]: + if type == User: + # Get queryset of all users with consistent ordering + # according to the provider's settings + base = User.objects.all().exclude_anonymous() + if self.exclude_users_service_account: + base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( + type=UserTypes.INTERNAL_SERVICE_ACCOUNT + ) + if self.filter_group: + base = base.filter(ak_groups__in=[self.filter_group]) + return base.order_by("pk") + if type == Group: + # Get queryset of all groups with consistent ordering + return Group.objects.all().order_by("pk") + raise ValueError(f"Invalid type {type}") + + def google_credentials(self): + return { + "credentials": Credentials.from_service_account_info( + self.credentials, scopes=self.scopes.split(",") + ).with_subject(self.delegated_subject), + } + + @property + def icon_url(self) -> str | None: + return static("authentik/sources/google.svg") + + @property + def component(self) -> str: + return "ak-provider-google-workspace-form" + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.google_workspace.api.providers import ( + GoogleWorkspaceProviderSerializer, + ) + + return GoogleWorkspaceProviderSerializer + + def __str__(self): + return f"Google Workspace Provider {self.name}" + + class Meta: + verbose_name = _("Google Workspace Provider") + verbose_name_plural = _("Google Workspace Providers") + + +class GoogleWorkspaceProviderMapping(PropertyMapping): + """Map authentik data to outgoing Google requests""" + + @property + def component(self) -> str: + return "ak-property-mapping-google-workspace-form" + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.google_workspace.api.property_mappings import ( + GoogleWorkspaceProviderMappingSerializer, + ) + + return GoogleWorkspaceProviderMappingSerializer + + def __str__(self): + return f"Google Workspace Provider Mapping {self.name}" + + class Meta: + verbose_name = _("Google Workspace Provider Mapping") + verbose_name_plural = _("Google Workspace Provider Mappings") + + +class GoogleWorkspaceProviderUser(SerializerModel): + """Mapping of a user and provider to a Google user ID""" + + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + google_id = models.TextField() + user = models.ForeignKey(User, on_delete=models.CASCADE) + provider = models.ForeignKey(GoogleWorkspaceProvider, on_delete=models.CASCADE) + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.google_workspace.api.users import ( + GoogleWorkspaceProviderUserSerializer, + ) + + return GoogleWorkspaceProviderUserSerializer + + class Meta: + verbose_name = _("Google Workspace Provider User") + verbose_name_plural = _("Google Workspace Provider Users") + unique_together = (("google_id", "user", "provider"),) + + def __str__(self) -> str: + return f"Google Workspace Provider User {self.user_id} to {self.provider_id}" + + +class GoogleWorkspaceProviderGroup(SerializerModel): + """Mapping of a group and provider to a Google group ID""" + + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + google_id = models.TextField() + group = models.ForeignKey(Group, on_delete=models.CASCADE) + provider = models.ForeignKey(GoogleWorkspaceProvider, on_delete=models.CASCADE) + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.google_workspace.api.groups import ( + GoogleWorkspaceProviderGroupSerializer, + ) + + return GoogleWorkspaceProviderGroupSerializer + + class Meta: + verbose_name = _("Google Workspace Provider Group") + verbose_name_plural = _("Google Workspace Provider Groups") + unique_together = (("google_id", "group", "provider"),) + + def __str__(self) -> str: + return f"Google Workspace Provider Group {self.group_id} to {self.provider_id}" diff --git a/authentik/enterprise/providers/google_workspace/settings.py b/authentik/enterprise/providers/google_workspace/settings.py new file mode 100644 index 0000000000..443a1a1884 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/settings.py @@ -0,0 +1,13 @@ +"""Google workspace provider task Settings""" + +from celery.schedules import crontab + +from authentik.lib.utils.time import fqdn_rand + +CELERY_BEAT_SCHEDULE = { + "providers_google_workspace_sync": { + "task": "authentik.enterprise.providers.google_workspace.tasks.google_workspace_sync_all", + "schedule": crontab(minute=fqdn_rand("google_workspace_sync_all"), hour="*/4"), + "options": {"queue": "authentik_scheduled"}, + }, +} diff --git a/authentik/enterprise/providers/google_workspace/signals.py b/authentik/enterprise/providers/google_workspace/signals.py new file mode 100644 index 0000000000..2e7eb70a94 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/signals.py @@ -0,0 +1,16 @@ +"""Google provider signals""" + +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider +from authentik.enterprise.providers.google_workspace.tasks import ( + google_workspace_sync, + google_workspace_sync_direct, + google_workspace_sync_m2m, +) +from authentik.lib.sync.outgoing.signals import register_signals + +register_signals( + GoogleWorkspaceProvider, + task_sync_single=google_workspace_sync, + task_sync_direct=google_workspace_sync_direct, + task_sync_m2m=google_workspace_sync_m2m, +) diff --git a/authentik/enterprise/providers/google_workspace/tasks.py b/authentik/enterprise/providers/google_workspace/tasks.py new file mode 100644 index 0000000000..237076411a --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/tasks.py @@ -0,0 +1,37 @@ +"""Google Provider tasks""" + +from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider +from authentik.events.system_tasks import SystemTask +from authentik.lib.sync.outgoing.exceptions import TransientSyncException +from authentik.lib.sync.outgoing.tasks import SyncTasks +from authentik.root.celery import CELERY_APP + +sync_tasks = SyncTasks(GoogleWorkspaceProvider) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def google_workspace_sync_objects(*args, **kwargs): + return sync_tasks.sync_objects(*args, **kwargs) + + +@CELERY_APP.task( + base=SystemTask, bind=True, autoretry_for=(TransientSyncException,), retry_backoff=True +) +def google_workspace_sync(self, provider_pk: int, *args, **kwargs): + """Run full sync for Google Workspace provider""" + return sync_tasks.sync_single(self, provider_pk, google_workspace_sync_objects) + + +@CELERY_APP.task() +def google_workspace_sync_all(): + return sync_tasks.sync_all(google_workspace_sync) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def google_workspace_sync_direct(*args, **kwargs): + return sync_tasks.sync_signal_direct(*args, **kwargs) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def google_workspace_sync_m2m(*args, **kwargs): + return sync_tasks.sync_signal_m2m(*args, **kwargs) diff --git a/authentik/enterprise/providers/google_workspace/tests/fixtures/domains_list_v1.json b/authentik/enterprise/providers/google_workspace/tests/fixtures/domains_list_v1.json new file mode 100644 index 0000000000..c3d1803628 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/tests/fixtures/domains_list_v1.json @@ -0,0 +1,14 @@ +{ + "kind": "admin#directory#domains", + "etag": "\"a1kA7zE2sFLsHiFwgXN9G3effoc9grR2OwUu8_95xD4/uvC5HsKHylhnUtnRV6ZxINODtV0\"", + "domains": [ + { + "kind": "admin#directory#domain", + "etag": "\"a1kA7zE2sFLsHiFwgXN9G3effoc9grR2OwUu8_95xD4/V4koSPWBFIWuIpAmUamO96QhTLo\"", + "domainName": "goauthentik.io", + "isPrimary": true, + "verified": true, + "creationTime": "1543048869840" + } + ] +} diff --git a/authentik/enterprise/providers/google_workspace/tests/test_groups.py b/authentik/enterprise/providers/google_workspace/tests/test_groups.py new file mode 100644 index 0000000000..fbc52a94aa --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/tests/test_groups.py @@ -0,0 +1,334 @@ +"""Google Workspace Group tests""" + +from unittest.mock import MagicMock, patch + +from django.test import TestCase + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, User +from authentik.core.tests.utils import create_test_user +from authentik.enterprise.providers.google_workspace.clients.test_http import MockHTTP +from authentik.enterprise.providers.google_workspace.models import ( + GoogleWorkspaceProvider, + GoogleWorkspaceProviderGroup, + GoogleWorkspaceProviderMapping, +) +from authentik.enterprise.providers.google_workspace.tasks import google_workspace_sync +from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.lib.tests.utils import load_fixture +from authentik.tenants.models import Tenant + +domains_list_v1_mock = load_fixture("fixtures/domains_list_v1.json") + + +class GoogleWorkspaceGroupTests(TestCase): + """Google workspace Group tests""" + + @apply_blueprint("system/providers-google-workspace.yaml") + def setUp(self) -> None: + # Delete all groups and groups as the mocked HTTP responses only return one ID + # which will cause errors with multiple groups + Tenant.objects.update(avatars="none") + User.objects.all().exclude_anonymous().delete() + Group.objects.all().delete() + self.provider: GoogleWorkspaceProvider = GoogleWorkspaceProvider.objects.create( + name=generate_id(), + credentials={}, + delegated_subject="", + exclude_users_service_account=True, + default_group_email_domain="goauthentik.io", + ) + self.app: Application = Application.objects.create( + name=generate_id(), + slug=generate_id(), + ) + self.app.backchannel_providers.add(self.provider) + self.provider.property_mappings.add( + GoogleWorkspaceProviderMapping.objects.get( + managed="goauthentik.io/providers/google_workspace/user" + ) + ) + self.provider.property_mappings_group.add( + GoogleWorkspaceProviderMapping.objects.get( + managed="goauthentik.io/providers/google_workspace/group" + ) + ) + self.api_key = generate_id() + + def test_group_create(self): + """Test group creation""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": generate_id()}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 2) + + def test_group_not_created(self): + """Test without group property mappings, no group is created""" + self.provider.property_mappings_group.clear() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNone(google_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 1) + + def test_group_create_update(self): + """Test group updating""" + uid = generate_id() + ext_id = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": ext_id}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{ext_id}?key={self.api_key}&alt=json", + method="PUT", + body={"id": ext_id}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + + group.name = "new name" + group.save() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 4) + + def test_group_create_delete(self): + """Test group deletion""" + uid = generate_id() + ext_id = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": ext_id}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{ext_id}?key={self.api_key}", + method="DELETE", + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + + group.delete() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 4) + + def test_group_create_member_add(self): + """Test group creation""" + uid = generate_id() + ext_id = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": ext_id}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}&alt=json", + method="PUT", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{ext_id}/members?key={self.api_key}&alt=json", + method="POST", + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = create_test_user(uid) + group = Group.objects.create(name=uid) + group.users.add(user) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 8) + + def test_group_create_member_remove(self): + """Test group creation""" + uid = generate_id() + ext_id = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": ext_id}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}&alt=json", + method="PUT", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{ext_id}/members/{uid}%40goauthentik.io?key={self.api_key}", + method="DELETE", + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{ext_id}/members?key={self.api_key}&alt=json", + method="POST", + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = create_test_user(uid) + group = Group.objects.create(name=uid) + group.users.add(user) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + group.users.remove(user) + + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 10) + + def test_group_create_delete_do_nothing(self): + """Test group deletion (delete action = do nothing)""" + self.provider.group_delete_action = OutgoingSyncDeleteAction.DO_NOTHING + self.provider.save() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?key={self.api_key}&alt=json", + method="POST", + body={"id": uid}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(google_group) + + group.delete() + self.assertEqual(len(http.requests()), 3) + self.assertFalse( + GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group__name=uid + ).exists() + ) + + def test_sync_task(self): + """Test group discovery""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?customer=my_customer&maxResults=500&orderBy=email&key={self.api_key}&alt=json", + method="GET", + body={"users": []}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?customer=my_customer&maxResults=500&orderBy=email&key={self.api_key}&alt=json", + method="GET", + body={"groups": [{"id": uid, "name": uid}]}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups/{uid}?key={self.api_key}&alt=json", + method="PUT", + body={"id": uid}, + ) + self.app.backchannel_providers.remove(self.provider) + different_group = Group.objects.create( + name=uid, + ) + self.app.backchannel_providers.add(self.provider) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + google_workspace_sync.delay(self.provider.pk).get() + self.assertTrue( + GoogleWorkspaceProviderGroup.objects.filter( + group=different_group, provider=self.provider + ).exists() + ) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 5) diff --git a/authentik/enterprise/providers/google_workspace/tests/test_users.py b/authentik/enterprise/providers/google_workspace/tests/test_users.py new file mode 100644 index 0000000000..0f7ec0d14e --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/tests/test_users.py @@ -0,0 +1,312 @@ +"""Google Workspace User tests""" + +from json import loads +from unittest.mock import MagicMock, patch + +from django.test import TestCase + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, User +from authentik.enterprise.providers.google_workspace.clients.test_http import MockHTTP +from authentik.enterprise.providers.google_workspace.models import ( + GoogleWorkspaceProvider, + GoogleWorkspaceProviderMapping, + GoogleWorkspaceProviderUser, +) +from authentik.enterprise.providers.google_workspace.tasks import google_workspace_sync +from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.lib.tests.utils import load_fixture +from authentik.tenants.models import Tenant + +domains_list_v1_mock = load_fixture("fixtures/domains_list_v1.json") + + +class GoogleWorkspaceUserTests(TestCase): + """Google workspace User tests""" + + @apply_blueprint("system/providers-google-workspace.yaml") + def setUp(self) -> None: + # Delete all users and groups as the mocked HTTP responses only return one ID + # which will cause errors with multiple users + Tenant.objects.update(avatars="none") + User.objects.all().exclude_anonymous().delete() + Group.objects.all().delete() + self.provider: GoogleWorkspaceProvider = GoogleWorkspaceProvider.objects.create( + name=generate_id(), + credentials={}, + delegated_subject="", + exclude_users_service_account=True, + default_group_email_domain="goauthentik.io", + ) + self.app: Application = Application.objects.create( + name=generate_id(), + slug=generate_id(), + ) + self.app.backchannel_providers.add(self.provider) + self.provider.property_mappings.add( + GoogleWorkspaceProviderMapping.objects.get( + managed="goauthentik.io/providers/google_workspace/user" + ) + ) + self.provider.property_mappings_group.add( + GoogleWorkspaceProviderMapping.objects.get( + managed="goauthentik.io/providers/google_workspace/group" + ) + ) + self.api_key = generate_id() + + def test_user_create(self): + """Test user creation""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(google_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 2) + + def test_user_not_created(self): + """Test without property mappings, no group is created""" + self.provider.property_mappings.clear() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNone(google_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 1) + + def test_user_create_update(self): + """Test user updating""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}&alt=json", + method="PUT", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(google_user) + + user.name = "new name" + user.save() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 4) + + def test_user_create_delete(self): + """Test user deletion""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}", + method="DELETE", + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(google_user) + + user.delete() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 4) + + def test_user_create_delete_suspend(self): + """Test user deletion (delete action = Suspend)""" + self.provider.user_delete_action = OutgoingSyncDeleteAction.SUSPEND + self.provider.save() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}&alt=json", + method="PUT", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(google_user) + + user.delete() + self.assertEqual(len(http.requests()), 4) + _, _, body, _ = http.requests()[3] + self.assertEqual( + loads(body), + { + "suspended": True, + }, + ) + self.assertFalse( + GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user__username=uid + ).exists() + ) + + def test_user_create_delete_do_nothing(self): + """Test user deletion (delete action = do nothing)""" + self.provider.user_delete_action = OutgoingSyncDeleteAction.DO_NOTHING + self.provider.save() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?key={self.api_key}&alt=json", + method="POST", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(google_user) + + user.delete() + self.assertEqual(len(http.requests()), 3) + self.assertFalse( + GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user__username=uid + ).exists() + ) + + def test_sync_task(self): + """Test user discovery""" + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users?customer=my_customer&maxResults=500&orderBy=email&key={self.api_key}&alt=json", + method="GET", + body={"users": [{"primaryEmail": f"{uid}@goauthentik.io"}]}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/groups?customer=my_customer&maxResults=500&orderBy=email&key={self.api_key}&alt=json", + method="GET", + body={"groups": []}, + ) + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/users/{uid}%40goauthentik.io?key={self.api_key}&alt=json", + method="PUT", + body={"primaryEmail": f"{uid}@goauthentik.io"}, + ) + self.app.backchannel_providers.remove(self.provider) + different_user = User.objects.create( + username=uid, + email=f"{uid}@goauthentik.io", + ) + self.app.backchannel_providers.add(self.provider) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + google_workspace_sync.delay(self.provider.pk).get() + self.assertTrue( + GoogleWorkspaceProviderUser.objects.filter( + user=different_user, provider=self.provider + ).exists() + ) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 5) diff --git a/authentik/enterprise/providers/google_workspace/urls.py b/authentik/enterprise/providers/google_workspace/urls.py new file mode 100644 index 0000000000..27a5ddd475 --- /dev/null +++ b/authentik/enterprise/providers/google_workspace/urls.py @@ -0,0 +1,21 @@ +"""google provider urls""" + +from authentik.enterprise.providers.google_workspace.api.groups import ( + GoogleWorkspaceProviderGroupViewSet, +) +from authentik.enterprise.providers.google_workspace.api.property_mappings import ( + GoogleWorkspaceProviderMappingViewSet, +) +from authentik.enterprise.providers.google_workspace.api.providers import ( + GoogleWorkspaceProviderViewSet, +) +from authentik.enterprise.providers.google_workspace.api.users import ( + GoogleWorkspaceProviderUserViewSet, +) + +api_urlpatterns = [ + ("providers/google_workspace", GoogleWorkspaceProviderViewSet), + ("providers/google_workspace_users", GoogleWorkspaceProviderUserViewSet), + ("providers/google_workspace_groups", GoogleWorkspaceProviderGroupViewSet), + ("propertymappings/provider/google_workspace", GoogleWorkspaceProviderMappingViewSet), +] diff --git a/authentik/enterprise/providers/microsoft_entra/__init__.py b/authentik/enterprise/providers/microsoft_entra/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/microsoft_entra/api/__init__.py b/authentik/enterprise/providers/microsoft_entra/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/microsoft_entra/api/groups.py b/authentik/enterprise/providers/microsoft_entra/api/groups.py new file mode 100644 index 0000000000..6934a841ce --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/api/groups.py @@ -0,0 +1,33 @@ +"""MicrosoftEntraProviderGroup API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.users import UserGroupSerializer +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderGroup + + +class MicrosoftEntraProviderGroupSerializer(SourceSerializer): + """MicrosoftEntraProviderGroup Serializer""" + + group_obj = UserGroupSerializer(source="group", read_only=True) + + class Meta: + + model = MicrosoftEntraProviderGroup + fields = [ + "id", + "group", + "group_obj", + ] + + +class MicrosoftEntraProviderGroupViewSet(UsedByMixin, ModelViewSet): + """MicrosoftEntraProviderGroup Viewset""" + + queryset = MicrosoftEntraProviderGroup.objects.all().select_related("group") + serializer_class = MicrosoftEntraProviderGroupSerializer + filterset_fields = ["provider__id", "group__name", "group__group_uuid"] + search_fields = ["provider__name", "group__name"] + ordering = ["group__name"] diff --git a/authentik/enterprise/providers/microsoft_entra/api/property_mappings.py b/authentik/enterprise/providers/microsoft_entra/api/property_mappings.py new file mode 100644 index 0000000000..791b60ced5 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/api/property_mappings.py @@ -0,0 +1,39 @@ +"""microsoft Property mappings API Views""" + +from django_filters.filters import AllValuesMultipleFilter +from django_filters.filterset import FilterSet +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema_field +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.property_mappings import PropertyMappingSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderMapping + + +class MicrosoftEntraProviderMappingSerializer(PropertyMappingSerializer): + """MicrosoftEntraProviderMapping Serializer""" + + class Meta: + model = MicrosoftEntraProviderMapping + fields = PropertyMappingSerializer.Meta.fields + + +class MicrosoftEntraProviderMappingFilter(FilterSet): + """Filter for MicrosoftEntraProviderMapping""" + + managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed")) + + class Meta: + model = MicrosoftEntraProviderMapping + fields = "__all__" + + +class MicrosoftEntraProviderMappingViewSet(UsedByMixin, ModelViewSet): + """MicrosoftEntraProviderMapping Viewset""" + + queryset = MicrosoftEntraProviderMapping.objects.all() + serializer_class = MicrosoftEntraProviderMappingSerializer + filterset_class = MicrosoftEntraProviderMappingFilter + search_fields = ["name"] + ordering = ["name"] diff --git a/authentik/enterprise/providers/microsoft_entra/api/providers.py b/authentik/enterprise/providers/microsoft_entra/api/providers.py new file mode 100644 index 0000000000..a5552c560e --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/api/providers.py @@ -0,0 +1,52 @@ +"""Microsoft Provider API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.api import EnterpriseRequiredMixin +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider +from authentik.enterprise.providers.microsoft_entra.tasks import microsoft_entra_sync +from authentik.lib.sync.outgoing.api import OutgoingSyncProviderStatusMixin + + +class MicrosoftEntraProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer): + """MicrosoftEntraProvider Serializer""" + + class Meta: + model = MicrosoftEntraProvider + fields = [ + "pk", + "name", + "property_mappings", + "property_mappings_group", + "component", + "assigned_backchannel_application_slug", + "assigned_backchannel_application_name", + "verbose_name", + "verbose_name_plural", + "meta_model_name", + "client_id", + "client_secret", + "tenant_id", + "exclude_users_service_account", + "filter_group", + "user_delete_action", + "group_delete_action", + ] + extra_kwargs = {} + + +class MicrosoftEntraProviderViewSet(OutgoingSyncProviderStatusMixin, UsedByMixin, ModelViewSet): + """MicrosoftEntraProvider Viewset""" + + queryset = MicrosoftEntraProvider.objects.all() + serializer_class = MicrosoftEntraProviderSerializer + filterset_fields = [ + "name", + "exclude_users_service_account", + "filter_group", + ] + search_fields = ["name"] + ordering = ["name"] + sync_single_task = microsoft_entra_sync diff --git a/authentik/enterprise/providers/microsoft_entra/api/users.py b/authentik/enterprise/providers/microsoft_entra/api/users.py new file mode 100644 index 0000000000..5b5efbafb8 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/api/users.py @@ -0,0 +1,33 @@ +"""MicrosoftEntraProviderUser API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.groups import GroupMemberSerializer +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderUser + + +class MicrosoftEntraProviderUserSerializer(SourceSerializer): + """MicrosoftEntraProviderUser Serializer""" + + user_obj = GroupMemberSerializer(source="user", read_only=True) + + class Meta: + + model = MicrosoftEntraProviderUser + fields = [ + "id", + "user", + "user_obj", + ] + + +class MicrosoftEntraProviderUserViewSet(UsedByMixin, ModelViewSet): + """MicrosoftEntraProviderUser Viewset""" + + queryset = MicrosoftEntraProviderUser.objects.all().select_related("user") + serializer_class = MicrosoftEntraProviderUserSerializer + filterset_fields = ["provider__id", "user__username", "user__id"] + search_fields = ["provider__name", "user__username"] + ordering = ["user__username"] diff --git a/authentik/enterprise/providers/microsoft_entra/apps.py b/authentik/enterprise/providers/microsoft_entra/apps.py new file mode 100644 index 0000000000..f58b3045be --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/apps.py @@ -0,0 +1,9 @@ +from authentik.enterprise.apps import EnterpriseConfig + + +class AuthentikEnterpriseProviderMicrosoftEntraConfig(EnterpriseConfig): + + name = "authentik.enterprise.providers.microsoft_entra" + label = "authentik_providers_microsoft_entra" + verbose_name = "authentik Enterprise.Providers.Microsoft Entra" + default = True diff --git a/authentik/enterprise/providers/microsoft_entra/clients/__init__.py b/authentik/enterprise/providers/microsoft_entra/clients/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/microsoft_entra/clients/base.py b/authentik/enterprise/providers/microsoft_entra/clients/base.py new file mode 100644 index 0000000000..f2a3747363 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/clients/base.py @@ -0,0 +1,100 @@ +from asyncio import run +from collections.abc import Coroutine +from typing import Any + +from azure.core.exceptions import ( + ClientAuthenticationError, + ServiceRequestError, + ServiceResponseError, +) +from azure.identity.aio import ClientSecretCredential +from django.db.models import Model +from django.http import HttpResponseBadRequest, HttpResponseNotFound +from kiota_abstractions.api_error import APIError +from kiota_authentication_azure.azure_identity_authentication_provider import ( + AzureIdentityAuthenticationProvider, +) +from kiota_http.kiota_client_factory import KiotaClientFactory +from msgraph.generated.models.o_data_errors.o_data_error import ODataError +from msgraph.graph_request_adapter import GraphRequestAdapter, options +from msgraph.graph_service_client import GraphServiceClient +from msgraph_core import GraphClientFactory + +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider +from authentik.lib.sync.outgoing import HTTP_CONFLICT +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.exceptions import ( + BadRequestSyncException, + NotFoundSyncException, + ObjectExistsSyncException, + StopSync, + TransientSyncException, +) + + +def get_request_adapter( + credentials: ClientSecretCredential, scopes: list[str] | None = None +) -> GraphRequestAdapter: + if scopes: + auth_provider = AzureIdentityAuthenticationProvider(credentials=credentials, scopes=scopes) + else: + auth_provider = AzureIdentityAuthenticationProvider(credentials=credentials) + + return GraphRequestAdapter( + auth_provider=auth_provider, + client=GraphClientFactory.create_with_default_middleware( + options=options, client=KiotaClientFactory.get_default_client() + ), + ) + + +class MicrosoftEntraSyncClient[TModel: Model, TConnection: Model, TSchema: dict]( + BaseOutgoingSyncClient[TModel, TConnection, TSchema, MicrosoftEntraProvider] +): + """Base client for syncing to microsoft entra""" + + domains: list + + def __init__(self, provider: MicrosoftEntraProvider) -> None: + super().__init__(provider) + self.credentials = provider.microsoft_credentials() + self.__prefetch_domains() + + @property + def client(self): + return GraphServiceClient(request_adapter=get_request_adapter(**self.credentials)) + + def _request[T](self, request: Coroutine[Any, Any, T]) -> T: + try: + return run(request) + except ClientAuthenticationError as exc: + raise StopSync(exc, None, None) from exc + except ODataError as exc: + raise StopSync(exc, None, None) from exc + except (ServiceRequestError, ServiceResponseError) as exc: + raise TransientSyncException("Failed to sent request") from exc + except APIError as exc: + if exc.response_status_code == HttpResponseNotFound.status_code: + raise NotFoundSyncException("Object not found") from exc + if exc.response_status_code == HttpResponseBadRequest.status_code: + raise BadRequestSyncException("Bad request", exc.response_headers) from exc + if exc.response_status_code == HTTP_CONFLICT: + raise ObjectExistsSyncException("Object exists", exc.response_headers) from exc + raise exc + + def __prefetch_domains(self): + self.domains = [] + organizations = self._request(self.client.organization.get()) + next_link = True + while next_link: + for org in organizations.value: + self.domains.extend([x.name for x in org.verified_domains]) + next_link = organizations.odata_next_link + if not next_link: + break + organizations = self._request(self.client.organization.with_url(next_link).get()) + + def check_email_valid(self, *emails: str): + for email in emails: + if not any(email.endswith(f"@{domain_name}") for domain_name in self.domains): + raise BadRequestSyncException(f"Invalid email domain: {email}") diff --git a/authentik/enterprise/providers/microsoft_entra/clients/groups.py b/authentik/enterprise/providers/microsoft_entra/clients/groups.py new file mode 100644 index 0000000000..0121c132be --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/clients/groups.py @@ -0,0 +1,216 @@ +from django.db import transaction +from msgraph.generated.groups.groups_request_builder import GroupsRequestBuilder +from msgraph.generated.models.group import Group as MSGroup +from msgraph.generated.models.reference_create import ReferenceCreate + +from authentik.core.models import Group +from authentik.enterprise.providers.microsoft_entra.clients.base import MicrosoftEntraSyncClient +from authentik.enterprise.providers.microsoft_entra.models import ( + MicrosoftEntraProvider, + MicrosoftEntraProviderGroup, + MicrosoftEntraProviderMapping, + MicrosoftEntraProviderUser, +) +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.base import Direction +from authentik.lib.sync.outgoing.exceptions import ( + NotFoundSyncException, + ObjectExistsSyncException, + StopSync, + TransientSyncException, +) +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction + + +class MicrosoftEntraGroupClient( + MicrosoftEntraSyncClient[Group, MicrosoftEntraProviderGroup, MSGroup] +): + """Microsoft client for groups""" + + connection_type = MicrosoftEntraProviderGroup + connection_type_query = "group" + can_discover = True + + def __init__(self, provider: MicrosoftEntraProvider) -> None: + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings_group.all().order_by("name").select_subclasses(), + MicrosoftEntraProviderMapping, + ["group", "provider", "creating"], + ) + + def to_schema(self, obj: Group, creating: bool) -> MSGroup: + """Convert authentik group""" + raw_microsoft_group = super().to_schema(obj, creating) + try: + return MSGroup(**raw_microsoft_group) + except TypeError as exc: + raise StopSync(exc, obj) from exc + + def delete(self, obj: Group): + """Delete group""" + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=obj + ).first() + if not microsoft_group: + self.logger.debug("Group does not exist in Microsoft, skipping") + return None + with transaction.atomic(): + if self.provider.group_delete_action == OutgoingSyncDeleteAction.DELETE: + self._request(self.client.groups.by_group_id(microsoft_group.microsoft_id).delete()) + microsoft_group.delete() + + def create(self, group: Group): + """Create group from scratch and create a connection object""" + microsoft_group = self.to_schema(group, True) + with transaction.atomic(): + try: + response = self._request(self.client.groups.post(microsoft_group)) + except ObjectExistsSyncException: + # group already exists in microsoft entra, so we can connect them manually + # for groups we need to fetch the group from microsoft as we connect on + # ID and not group email + query_params = GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters( + filter=f"displayName eq '{microsoft_group.display_name}'", + ) + request_configuration = ( + GroupsRequestBuilder.GroupsRequestBuilderGetRequestConfiguration( + query_parameters=query_params, + ) + ) + group_data = self._request(self.client.groups.get(request_configuration)) + if group_data.odata_count < 1: + self.logger.warning( + "Group which could not be created also does not exist", group=group + ) + return + return MicrosoftEntraProviderGroup.objects.create( + provider=self.provider, group=group, microsoft_id=group_data.value[0].id + ) + else: + return MicrosoftEntraProviderGroup.objects.create( + provider=self.provider, group=group, microsoft_id=response.id + ) + + def update(self, group: Group, connection: MicrosoftEntraProviderGroup): + """Update existing group""" + microsoft_group = self.to_schema(group, False) + microsoft_group.id = connection.microsoft_id + try: + return self._request( + self.client.groups.by_group_id(connection.microsoft_id).patch(microsoft_group) + ) + except NotFoundSyncException: + # Resource missing is handled by self.write, which will re-create the group + raise + + def write(self, obj: Group): + microsoft_group, created = super().write(obj) + self.create_sync_members(obj, microsoft_group) + return microsoft_group, created + + def create_sync_members(self, obj: Group, microsoft_group: MicrosoftEntraProviderGroup): + """Sync all members after a group was created""" + users = list(obj.users.order_by("id").values_list("id", flat=True)) + connections = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user__pk__in=users + ).values_list("microsoft_id", flat=True) + self._patch(microsoft_group.microsoft_id, Direction.add, connections) + + def update_group(self, group: Group, action: Direction, users_set: set[int]): + """Update a groups members""" + if action == Direction.add: + return self._patch_add_users(group, users_set) + if action == Direction.remove: + return self._patch_remove_users(group, users_set) + + def _patch(self, microsoft_group_id: str, direction: Direction, members: list[str]): + for user in members: + try: + if direction == Direction.add: + request_body = ReferenceCreate( + odata_id=f"https://graph.microsoft.com/v1.0/directoryObjects/{user}", + ) + self._request( + self.client.groups.by_group_id(microsoft_group_id).members.ref.post( + request_body + ) + ) + if direction == Direction.remove: + self._request( + self.client.groups.by_group_id(microsoft_group_id) + .members.by_directory_object_id(user) + .ref.delete() + ) + except ObjectExistsSyncException: + pass + except TransientSyncException: + raise + + def _patch_add_users(self, group: Group, users_set: set[int]): + """Add users in users_set to group""" + if len(users_set) < 1: + return + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + if not microsoft_group: + self.logger.warning( + "could not sync group membership, group does not exist", group=group + ) + return + user_ids = list( + MicrosoftEntraProviderUser.objects.filter( + user__pk__in=users_set, provider=self.provider + ).values_list("microsoft_id", flat=True) + ) + if len(user_ids) < 1: + return + self._patch(microsoft_group.microsoft_id, Direction.add, user_ids) + + def _patch_remove_users(self, group: Group, users_set: set[int]): + """Remove users in users_set from group""" + if len(users_set) < 1: + return + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + if not microsoft_group: + self.logger.warning( + "could not sync group membership, group does not exist", group=group + ) + return + user_ids = list( + MicrosoftEntraProviderUser.objects.filter( + user__pk__in=users_set, provider=self.provider + ).values_list("microsoft_id", flat=True) + ) + if len(user_ids) < 1: + return + self._patch(microsoft_group.microsoft_id, Direction.remove, user_ids) + + def discover(self): + """Iterate through all groups and connect them with authentik groups if possible""" + groups = self._request(self.client.groups.get()) + next_link = True + while next_link: + for group in groups.value: + self._discover_single_group(group) + next_link = groups.odata_next_link + if not next_link: + break + groups = self._request(self.client.groups.with_url(next_link).get()) + + def _discover_single_group(self, group: MSGroup): + """handle discovery of a single group""" + microsoft_name = group.unique_name + matching_authentik_group = ( + self.provider.get_object_qs(Group).filter(name=microsoft_name).first() + ) + if not matching_authentik_group: + return + MicrosoftEntraProviderGroup.objects.get_or_create( + provider=self.provider, + group=matching_authentik_group, + microsoft_id=group.id, + ) diff --git a/authentik/enterprise/providers/microsoft_entra/clients/users.py b/authentik/enterprise/providers/microsoft_entra/clients/users.py new file mode 100644 index 0000000000..a9539ba465 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/clients/users.py @@ -0,0 +1,128 @@ +from django.db import transaction +from msgraph.generated.models.user import User as MSUser +from msgraph.generated.users.users_request_builder import UsersRequestBuilder + +from authentik.core.models import User +from authentik.enterprise.providers.microsoft_entra.clients.base import MicrosoftEntraSyncClient +from authentik.enterprise.providers.microsoft_entra.models import ( + MicrosoftEntraProvider, + MicrosoftEntraProviderMapping, + MicrosoftEntraProviderUser, +) +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.exceptions import ( + ObjectExistsSyncException, + StopSync, + TransientSyncException, +) +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.policies.utils import delete_none_values + + +class MicrosoftEntraUserClient(MicrosoftEntraSyncClient[User, MicrosoftEntraProviderUser, MSUser]): + """Sync authentik users into microsoft entra""" + + connection_type = MicrosoftEntraProviderUser + connection_type_query = "user" + can_discover = True + + def __init__(self, provider: MicrosoftEntraProvider) -> None: + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings.all().order_by("name").select_subclasses(), + MicrosoftEntraProviderMapping, + ["provider", "creating"], + ) + + def to_schema(self, obj: User, creating: bool) -> MSUser: + """Convert authentik user""" + raw_microsoft_user = super().to_schema(obj, creating) + try: + return MSUser(**delete_none_values(raw_microsoft_user)) + except TypeError as exc: + raise StopSync(exc, obj) from exc + + def delete(self, obj: User): + """Delete user""" + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=obj + ).first() + if not microsoft_user: + self.logger.debug("User does not exist in Microsoft, skipping") + return None + with transaction.atomic(): + response = None + if self.provider.user_delete_action == OutgoingSyncDeleteAction.DELETE: + response = self._request( + self.client.users.by_user_id(microsoft_user.microsoft_id).delete() + ) + elif self.provider.user_delete_action == OutgoingSyncDeleteAction.SUSPEND: + response = self._request( + self.client.users.by_user_id(microsoft_user.microsoft_id).patch( + MSUser(account_enabled=False) + ) + ) + microsoft_user.delete() + return response + + def create(self, user: User): + """Create user from scratch and create a connection object""" + microsoft_user = self.to_schema(user, True) + self.check_email_valid(microsoft_user.user_principal_name) + with transaction.atomic(): + try: + response = self._request(self.client.users.post(microsoft_user)) + except ObjectExistsSyncException: + # user already exists in microsoft entra, so we can connect them manually + query_params = UsersRequestBuilder.UsersRequestBuilderGetQueryParameters()( + filter=f"mail eq '{microsoft_user.mail}'", + ) + request_configuration = ( + UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=query_params, + ) + ) + user_data = self._request(self.client.users.get(request_configuration)) + if user_data.odata_count < 1: + self.logger.warning( + "User which could not be created also does not exist", user=user + ) + return + return MicrosoftEntraProviderUser.objects.create( + provider=self.provider, user=user, microsoft_id=user_data.value[0].id + ) + except TransientSyncException as exc: + raise exc + else: + return MicrosoftEntraProviderUser.objects.create( + provider=self.provider, user=user, microsoft_id=response.id + ) + + def update(self, user: User, connection: MicrosoftEntraProviderUser): + """Update existing user""" + microsoft_user = self.to_schema(user, False) + self.check_email_valid(microsoft_user.user_principal_name) + self._request(self.client.users.by_user_id(connection.microsoft_id).patch(microsoft_user)) + + def discover(self): + """Iterate through all users and connect them with authentik users if possible""" + users = self._request(self.client.users.get()) + next_link = True + while next_link: + for user in users.value: + self._discover_single_user(user) + next_link = users.odata_next_link + if not next_link: + break + users = self._request(self.client.users.with_url(next_link).get()) + + def _discover_single_user(self, user: MSUser): + """handle discovery of a single user""" + matching_authentik_user = self.provider.get_object_qs(User).filter(email=user.mail).first() + if not matching_authentik_user: + return + MicrosoftEntraProviderUser.objects.get_or_create( + provider=self.provider, + user=matching_authentik_user, + microsoft_id=user.id, + ) diff --git a/authentik/enterprise/providers/microsoft_entra/migrations/0001_initial.py b/authentik/enterprise/providers/microsoft_entra/migrations/0001_initial.py new file mode 100644 index 0000000000..97bb770b70 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/migrations/0001_initial.py @@ -0,0 +1,165 @@ +# Generated by Django 5.0.6 on 2024-05-08 14:35 + +import django.db.models.deletion +import uuid +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("authentik_core", "0035_alter_group_options_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="MicrosoftEntraProviderMapping", + fields=[ + ( + "propertymapping_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Microsoft Entra Provider Mapping", + "verbose_name_plural": "Microsoft Entra Provider Mappings", + }, + bases=("authentik_core.propertymapping",), + ), + migrations.CreateModel( + name="MicrosoftEntraProvider", + fields=[ + ( + "provider_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.provider", + ), + ), + ("client_id", models.TextField()), + ("client_secret", models.TextField()), + ("tenant_id", models.TextField()), + ("exclude_users_service_account", models.BooleanField(default=False)), + ( + "user_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "group_delete_action", + models.TextField( + choices=[ + ("do_nothing", "Do Nothing"), + ("delete", "Delete"), + ("suspend", "Suspend"), + ], + default="delete", + ), + ), + ( + "filter_group", + models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_core.group", + ), + ), + ( + "property_mappings_group", + models.ManyToManyField( + blank=True, + default=None, + help_text="Property mappings used for group creation/updating.", + to="authentik_core.propertymapping", + ), + ), + ], + options={ + "verbose_name": "Microsoft Entra Provider", + "verbose_name_plural": "Microsoft Entra Providers", + }, + bases=("authentik_core.provider", models.Model), + ), + migrations.CreateModel( + name="MicrosoftEntraProviderGroup", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("microsoft_id", models.TextField()), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group" + ), + ), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_microsoft_entra.microsoftentraprovider", + ), + ), + ], + options={ + "verbose_name": "Microsoft Entra Provider Group", + "verbose_name_plural": "Microsoft Entra Provider Groups", + "unique_together": {("microsoft_id", "group", "provider")}, + }, + ), + migrations.CreateModel( + name="MicrosoftEntraProviderUser", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("microsoft_id", models.TextField()), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_microsoft_entra.microsoftentraprovider", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ], + options={ + "verbose_name": "Microsoft Entra Provider User", + "verbose_name_plural": "Microsoft Entra Provider User", + "unique_together": {("microsoft_id", "user", "provider")}, + }, + ), + ] diff --git a/authentik/enterprise/providers/microsoft_entra/migrations/__init__.py b/authentik/enterprise/providers/microsoft_entra/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/microsoft_entra/models.py b/authentik/enterprise/providers/microsoft_entra/models.py new file mode 100644 index 0000000000..92d1725107 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/models.py @@ -0,0 +1,185 @@ +"""Microsoft Entra sync provider""" + +from typing import Any, Self +from uuid import uuid4 + +from azure.identity.aio import ClientSecretCredential +from django.db import models +from django.db.models import QuerySet +from django.templatetags.static import static +from django.utils.translation import gettext_lazy as _ +from rest_framework.serializers import Serializer + +from authentik.core.models import ( + BackchannelProvider, + Group, + PropertyMapping, + User, + UserTypes, +) +from authentik.lib.models import SerializerModel +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction, OutgoingSyncProvider + + +class MicrosoftEntraProvider(OutgoingSyncProvider, BackchannelProvider): + """Sync users from authentik into Microsoft Entra.""" + + client_id = models.TextField() + client_secret = models.TextField() + tenant_id = models.TextField() + + exclude_users_service_account = models.BooleanField(default=False) + user_delete_action = models.TextField( + choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE + ) + group_delete_action = models.TextField( + choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE + ) + filter_group = models.ForeignKey( + "authentik_core.group", on_delete=models.SET_DEFAULT, default=None, null=True + ) + + property_mappings_group = models.ManyToManyField( + PropertyMapping, + default=None, + blank=True, + help_text=_("Property mappings used for group creation/updating."), + ) + + def client_for_model( + self, model: type[User | Group] + ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: + if issubclass(model, User): + from authentik.enterprise.providers.microsoft_entra.clients.users import ( + MicrosoftEntraUserClient, + ) + + return MicrosoftEntraUserClient(self) + if issubclass(model, Group): + from authentik.enterprise.providers.microsoft_entra.clients.groups import ( + MicrosoftEntraGroupClient, + ) + + return MicrosoftEntraGroupClient(self) + raise ValueError(f"Invalid model {model}") + + def get_object_qs(self, type: type[User | Group]) -> QuerySet[User | Group]: + if type == User: + # Get queryset of all users with consistent ordering + # according to the provider's settings + base = User.objects.all().exclude_anonymous() + if self.exclude_users_service_account: + base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( + type=UserTypes.INTERNAL_SERVICE_ACCOUNT + ) + if self.filter_group: + base = base.filter(ak_groups__in=[self.filter_group]) + return base.order_by("pk") + if type == Group: + # Get queryset of all groups with consistent ordering + return Group.objects.all().order_by("pk") + raise ValueError(f"Invalid type {type}") + + def microsoft_credentials(self): + return { + "credentials": ClientSecretCredential( + self.tenant_id, self.client_id, self.client_secret + ) + } + + @property + def icon_url(self) -> str | None: + return static("authentik/sources/azuread.svg") + + @property + def component(self) -> str: + return "ak-provider-microsoft-entra-form" + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.microsoft_entra.api.providers import ( + MicrosoftEntraProviderSerializer, + ) + + return MicrosoftEntraProviderSerializer + + def __str__(self): + return f"Microsoft Entra Provider {self.name}" + + class Meta: + verbose_name = _("Microsoft Entra Provider") + verbose_name_plural = _("Microsoft Entra Providers") + + +class MicrosoftEntraProviderMapping(PropertyMapping): + """Map authentik data to outgoing Microsoft requests""" + + @property + def component(self) -> str: + return "ak-property-mapping-microsoft-entra-form" + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.microsoft_entra.api.property_mappings import ( + MicrosoftEntraProviderMappingSerializer, + ) + + return MicrosoftEntraProviderMappingSerializer + + def __str__(self): + return f"Microsoft Entra Provider Mapping {self.name}" + + class Meta: + verbose_name = _("Microsoft Entra Provider Mapping") + verbose_name_plural = _("Microsoft Entra Provider Mappings") + + +class MicrosoftEntraProviderUser(SerializerModel): + """Mapping of a user and provider to a Microsoft user ID""" + + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + microsoft_id = models.TextField() + user = models.ForeignKey(User, on_delete=models.CASCADE) + provider = models.ForeignKey(MicrosoftEntraProvider, on_delete=models.CASCADE) + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.microsoft_entra.api.users import ( + MicrosoftEntraProviderUserSerializer, + ) + + return MicrosoftEntraProviderUserSerializer + + class Meta: + verbose_name = _("Microsoft Entra Provider User") + verbose_name_plural = _("Microsoft Entra Provider User") + unique_together = (("microsoft_id", "user", "provider"),) + + def __str__(self) -> str: + return f"Microsoft Entra Provider User {self.user_id} to {self.provider_id}" + + +class MicrosoftEntraProviderGroup(SerializerModel): + """Mapping of a group and provider to a Microsoft group ID""" + + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + microsoft_id = models.TextField() + group = models.ForeignKey(Group, on_delete=models.CASCADE) + provider = models.ForeignKey(MicrosoftEntraProvider, on_delete=models.CASCADE) + + @property + def serializer(self) -> type[Serializer]: + from authentik.enterprise.providers.microsoft_entra.api.groups import ( + MicrosoftEntraProviderGroupSerializer, + ) + + return MicrosoftEntraProviderGroupSerializer + + class Meta: + verbose_name = _("Microsoft Entra Provider Group") + verbose_name_plural = _("Microsoft Entra Provider Groups") + unique_together = (("microsoft_id", "group", "provider"),) + + def __str__(self) -> str: + return f"Microsoft Entra Provider Group {self.group_id} to {self.provider_id}" diff --git a/authentik/enterprise/providers/microsoft_entra/settings.py b/authentik/enterprise/providers/microsoft_entra/settings.py new file mode 100644 index 0000000000..08ef592de8 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/settings.py @@ -0,0 +1,13 @@ +"""Microsoft Entra provider task Settings""" + +from celery.schedules import crontab + +from authentik.lib.utils.time import fqdn_rand + +CELERY_BEAT_SCHEDULE = { + "providers_microsoft_entra_sync": { + "task": "authentik.enterprise.providers.microsoft_entra.tasks.microsoft_entra_sync_all", + "schedule": crontab(minute=fqdn_rand("microsoft_entra_sync_all"), hour="*/4"), + "options": {"queue": "authentik_scheduled"}, + }, +} diff --git a/authentik/enterprise/providers/microsoft_entra/signals.py b/authentik/enterprise/providers/microsoft_entra/signals.py new file mode 100644 index 0000000000..b9063ccb8b --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/signals.py @@ -0,0 +1,16 @@ +"""Microsoft provider signals""" + +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider +from authentik.enterprise.providers.microsoft_entra.tasks import ( + microsoft_entra_sync, + microsoft_entra_sync_direct, + microsoft_entra_sync_m2m, +) +from authentik.lib.sync.outgoing.signals import register_signals + +register_signals( + MicrosoftEntraProvider, + task_sync_single=microsoft_entra_sync, + task_sync_direct=microsoft_entra_sync_direct, + task_sync_m2m=microsoft_entra_sync_m2m, +) diff --git a/authentik/enterprise/providers/microsoft_entra/tasks.py b/authentik/enterprise/providers/microsoft_entra/tasks.py new file mode 100644 index 0000000000..6985b8acfa --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/tasks.py @@ -0,0 +1,37 @@ +"""Microsoft Entra Provider tasks""" + +from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider +from authentik.events.system_tasks import SystemTask +from authentik.lib.sync.outgoing.exceptions import TransientSyncException +from authentik.lib.sync.outgoing.tasks import SyncTasks +from authentik.root.celery import CELERY_APP + +sync_tasks = SyncTasks(MicrosoftEntraProvider) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def microsoft_entra_sync_objects(*args, **kwargs): + return sync_tasks.sync_objects(*args, **kwargs) + + +@CELERY_APP.task( + base=SystemTask, bind=True, autoretry_for=(TransientSyncException,), retry_backoff=True +) +def microsoft_entra_sync(self, provider_pk: int, *args, **kwargs): + """Run full sync for Microsoft Entra provider""" + return sync_tasks.sync_single(self, provider_pk, microsoft_entra_sync_objects) + + +@CELERY_APP.task() +def microsoft_entra_sync_all(): + return sync_tasks.sync_all(microsoft_entra_sync) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def microsoft_entra_sync_direct(*args, **kwargs): + return sync_tasks.sync_signal_direct(*args, **kwargs) + + +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def microsoft_entra_sync_m2m(*args, **kwargs): + return sync_tasks.sync_signal_m2m(*args, **kwargs) diff --git a/authentik/enterprise/providers/microsoft_entra/tests/__init__.py b/authentik/enterprise/providers/microsoft_entra/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py b/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py new file mode 100644 index 0000000000..c39d0ca206 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py @@ -0,0 +1,424 @@ +"""Microsoft Entra Group tests""" + +from unittest.mock import AsyncMock, MagicMock, patch + +from azure.identity.aio import ClientSecretCredential +from django.test import TestCase +from msgraph.generated.models.group import Group as MSGroup +from msgraph.generated.models.group_collection_response import GroupCollectionResponse +from msgraph.generated.models.organization import Organization +from msgraph.generated.models.organization_collection_response import OrganizationCollectionResponse +from msgraph.generated.models.user import User as MSUser +from msgraph.generated.models.user_collection_response import UserCollectionResponse +from msgraph.generated.models.verified_domain import VerifiedDomain + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, User +from authentik.core.tests.utils import create_test_user +from authentik.enterprise.providers.microsoft_entra.models import ( + MicrosoftEntraProvider, + MicrosoftEntraProviderGroup, + MicrosoftEntraProviderMapping, + MicrosoftEntraProviderUser, +) +from authentik.enterprise.providers.microsoft_entra.tasks import microsoft_entra_sync +from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.tenants.models import Tenant + + +class MicrosoftEntraGroupTests(TestCase): + """Microsoft Entra Group tests""" + + @apply_blueprint("system/providers-microsoft-entra.yaml") + def setUp(self) -> None: + # Delete all groups and groups as the mocked HTTP responses only return one ID + # which will cause errors with multiple groups + Tenant.objects.update(avatars="none") + User.objects.all().exclude_anonymous().delete() + Group.objects.all().delete() + self.provider: MicrosoftEntraProvider = MicrosoftEntraProvider.objects.create( + name=generate_id(), + client_id=generate_id(), + client_secret=generate_id(), + tenant_id=generate_id(), + exclude_users_service_account=True, + ) + self.app: Application = Application.objects.create( + name=generate_id(), + slug=generate_id(), + ) + self.app.backchannel_providers.add(self.provider) + self.provider.property_mappings.add( + MicrosoftEntraProviderMapping.objects.get( + managed="goauthentik.io/providers/microsoft_entra/user" + ) + ) + self.provider.property_mappings_group.add( + MicrosoftEntraProviderMapping.objects.get( + managed="goauthentik.io/providers/microsoft_entra/group" + ) + ) + self.creds = ClientSecretCredential(generate_id(), generate_id(), generate_id()) + + def test_group_create(self): + """Test group creation""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=generate_id())), + ) as group_create, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + group_create.assert_called_once() + + def test_group_not_created(self): + """Test without group property mappings, no group is created""" + self.provider.property_mappings_group.clear() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=generate_id())), + ) as group_create, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNone(microsoft_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + group_create.assert_not_called() + + def test_group_create_update(self): + """Test group updating""" + uid = generate_id() + ext_id = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=ext_id)), + ) as group_create, + patch( + "msgraph.generated.groups.item.group_item_request_builder.GroupItemRequestBuilder.patch", + AsyncMock(return_value=MSGroup(id=ext_id)), + ) as group_patch, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + + group.name = "new name" + group.save() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + group_create.assert_called_once() + group_patch.assert_called_once() + + def test_group_create_delete(self): + """Test group deletion""" + uid = generate_id() + ext_id = generate_id() + with ( + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=ext_id)), + ) as group_create, + patch( + "msgraph.generated.groups.item.group_item_request_builder.GroupItemRequestBuilder.delete", + AsyncMock(return_value=MSGroup(id=ext_id)), + ) as group_delete, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + + group.delete() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + group_create.assert_called_once() + group_delete.assert_called_once() + + def test_group_create_member_add(self): + """Test group creation""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=uid)), + ) as group_create, + patch( + "msgraph.generated.groups.item.members.ref.ref_request_builder.RefRequestBuilder.post", + AsyncMock(), + ) as member_add, + ): + user = create_test_user(uid) + group = Group.objects.create(name=uid) + group.users.add(user) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_called_once() + group_create.assert_called_once() + member_add.assert_called_once() + self.assertEqual( + member_add.call_args[0][0].odata_id, + f"https://graph.microsoft.com/v1.0/directoryObjects/{MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, + ).first().microsoft_id}", + ) + + def test_group_create_member_remove(self): + """Test group creation""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=uid)), + ) as group_create, + patch( + "msgraph.generated.groups.item.members.ref.ref_request_builder.RefRequestBuilder.post", + AsyncMock(), + ) as member_add, + patch( + "msgraph.generated.groups.item.members.item.ref.ref_request_builder.RefRequestBuilder.delete", + AsyncMock(), + ) as member_remove, + ): + user = create_test_user(uid) + group = Group.objects.create(name=uid) + group.users.add(user) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + group.users.remove(user) + + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_called_once() + group_create.assert_called_once() + member_add.assert_called_once() + self.assertEqual( + member_add.call_args[0][0].odata_id, + f"https://graph.microsoft.com/v1.0/directoryObjects/{MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, + ).first().microsoft_id}", + ) + member_remove.assert_called_once() + + def test_group_create_delete_do_nothing(self): + """Test group deletion (delete action = do nothing)""" + self.provider.group_delete_action = OutgoingSyncDeleteAction.DO_NOTHING + self.provider.save() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=uid)), + ) as group_create, + patch( + "msgraph.generated.groups.item.group_item_request_builder.GroupItemRequestBuilder.delete", + AsyncMock(return_value=MSGroup(id=uid)), + ) as group_delete, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNotNone(microsoft_group) + + group.delete() + self.assertFalse( + MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group__name=uid + ).exists() + ) + group_create.assert_called_once() + group_delete.assert_not_called() + + def test_sync_task(self): + """Test group discovery""" + uid = generate_id() + self.app.backchannel_providers.remove(self.provider) + different_group = Group.objects.create( + name=uid, + ) + self.app.backchannel_providers.add(self.provider) + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=generate_id())), + ), + patch( + "msgraph.generated.groups.item.group_item_request_builder.GroupItemRequestBuilder.patch", + AsyncMock(return_value=MSGroup(id=uid)), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.get", + AsyncMock( + return_value=UserCollectionResponse( + value=[MSUser(mail=f"{uid}@goauthentik.io", id=uid)] + ) + ), + ) as user_list, + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.get", + AsyncMock( + return_value=GroupCollectionResponse( + value=[MSGroup(display_name=uid, unique_name=uid, id=uid)] + ) + ), + ) as group_list, + ): + microsoft_entra_sync.delay(self.provider.pk).get() + self.assertTrue( + MicrosoftEntraProviderGroup.objects.filter( + group=different_group, provider=self.provider + ).exists() + ) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_list.assert_called_once() + group_list.assert_called_once() diff --git a/authentik/enterprise/providers/microsoft_entra/tests/test_users.py b/authentik/enterprise/providers/microsoft_entra/tests/test_users.py new file mode 100644 index 0000000000..7a00213efc --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/tests/test_users.py @@ -0,0 +1,373 @@ +"""Microsoft Entra User tests""" + +from unittest.mock import AsyncMock, MagicMock, patch + +from azure.identity.aio import ClientSecretCredential +from django.test import TestCase +from msgraph.generated.models.group_collection_response import GroupCollectionResponse +from msgraph.generated.models.organization import Organization +from msgraph.generated.models.organization_collection_response import OrganizationCollectionResponse +from msgraph.generated.models.user import User as MSUser +from msgraph.generated.models.user_collection_response import UserCollectionResponse +from msgraph.generated.models.verified_domain import VerifiedDomain + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, User +from authentik.enterprise.providers.microsoft_entra.models import ( + MicrosoftEntraProvider, + MicrosoftEntraProviderMapping, + MicrosoftEntraProviderUser, +) +from authentik.enterprise.providers.microsoft_entra.tasks import microsoft_entra_sync +from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id +from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction +from authentik.tenants.models import Tenant + + +class MicrosoftEntraUserTests(TestCase): + """Microsoft Entra User tests""" + + @apply_blueprint("system/providers-microsoft-entra.yaml") + def setUp(self) -> None: + # Delete all users and groups as the mocked HTTP responses only return one ID + # which will cause errors with multiple users + Tenant.objects.update(avatars="none") + User.objects.all().exclude_anonymous().delete() + Group.objects.all().delete() + self.provider: MicrosoftEntraProvider = MicrosoftEntraProvider.objects.create( + name=generate_id(), + client_id=generate_id(), + client_secret=generate_id(), + tenant_id=generate_id(), + exclude_users_service_account=True, + ) + self.app: Application = Application.objects.create( + name=generate_id(), + slug=generate_id(), + ) + self.app.backchannel_providers.add(self.provider) + self.provider.property_mappings.add( + MicrosoftEntraProviderMapping.objects.get( + managed="goauthentik.io/providers/microsoft_entra/user" + ) + ) + self.provider.property_mappings_group.add( + MicrosoftEntraProviderMapping.objects.get( + managed="goauthentik.io/providers/microsoft_entra/group" + ) + ) + self.creds = ClientSecretCredential(generate_id(), generate_id(), generate_id()) + + def test_user_create(self): + """Test user creation""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(microsoft_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_called_once() + + def test_user_not_created(self): + """Test without property mappings, no group is created""" + self.provider.property_mappings.clear() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNone(microsoft_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_not_called() + + def test_user_create_update(self): + """Test user updating""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_patch, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(microsoft_user) + + user.name = "new name" + user.save() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_called_once() + user_patch.assert_called_once() + + def test_user_create_delete(self): + """Test user deletion""" + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.delete", + AsyncMock(), + ) as user_delete, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(microsoft_user) + + user.delete() + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_called_once() + user_delete.assert_called_once() + + def test_user_create_delete_suspend(self): + """Test user deletion (delete action = Suspend)""" + self.provider.user_delete_action = OutgoingSyncDeleteAction.SUSPEND + self.provider.save() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_patch, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.delete", + AsyncMock(), + ) as user_delete, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(microsoft_user) + + user.delete() + self.assertFalse( + MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user__username=uid + ).exists() + ) + user_create.assert_called_once() + user_patch.assert_called_once() + self.assertFalse(user_patch.call_args[0][0].account_enabled) + user_delete.assert_not_called() + + def test_user_create_delete_do_nothing(self): + """Test user deletion (delete action = do nothing)""" + self.provider.user_delete_action = OutgoingSyncDeleteAction.DO_NOTHING + self.provider.save() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_patch, + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.delete", + AsyncMock(), + ) as user_delete, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNotNone(microsoft_user) + + user.delete() + self.assertFalse( + MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user__username=uid + ).exists() + ) + user_create.assert_called_once() + user_patch.assert_not_called() + user_delete.assert_not_called() + + def test_sync_task(self): + """Test user discovery""" + uid = generate_id() + self.app.backchannel_providers.remove(self.provider) + different_user = User.objects.create( + username=uid, + email=f"{uid}@goauthentik.io", + ) + self.app.backchannel_providers.add(self.provider) + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.item.user_item_request_builder.UserItemRequestBuilder.patch", + AsyncMock(return_value=MSUser(id=generate_id())), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.get", + AsyncMock( + return_value=UserCollectionResponse( + value=[MSUser(mail=f"{uid}@goauthentik.io", id=uid)] + ) + ), + ) as user_list, + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.get", + AsyncMock(return_value=GroupCollectionResponse(value=[])), + ), + ): + microsoft_entra_sync.delay(self.provider.pk).get() + self.assertTrue( + MicrosoftEntraProviderUser.objects.filter( + user=different_user, provider=self.provider + ).exists() + ) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_list.assert_called_once() diff --git a/authentik/enterprise/providers/microsoft_entra/urls.py b/authentik/enterprise/providers/microsoft_entra/urls.py new file mode 100644 index 0000000000..269e5bfc98 --- /dev/null +++ b/authentik/enterprise/providers/microsoft_entra/urls.py @@ -0,0 +1,21 @@ +"""microsoft provider urls""" + +from authentik.enterprise.providers.microsoft_entra.api.groups import ( + MicrosoftEntraProviderGroupViewSet, +) +from authentik.enterprise.providers.microsoft_entra.api.property_mappings import ( + MicrosoftEntraProviderMappingViewSet, +) +from authentik.enterprise.providers.microsoft_entra.api.providers import ( + MicrosoftEntraProviderViewSet, +) +from authentik.enterprise.providers.microsoft_entra.api.users import ( + MicrosoftEntraProviderUserViewSet, +) + +api_urlpatterns = [ + ("providers/microsoft_entra", MicrosoftEntraProviderViewSet), + ("providers/microsoft_entra_users", MicrosoftEntraProviderUserViewSet), + ("providers/microsoft_entra_groups", MicrosoftEntraProviderGroupViewSet), + ("propertymappings/provider/microsoft_entra", MicrosoftEntraProviderMappingViewSet), +] diff --git a/authentik/enterprise/providers/rac/api/connection_tokens.py b/authentik/enterprise/providers/rac/api/connection_tokens.py new file mode 100644 index 0000000000..00fb8f546f --- /dev/null +++ b/authentik/enterprise/providers/rac/api/connection_tokens.py @@ -0,0 +1,53 @@ +"""RAC Provider API Views""" + +from django_filters.rest_framework.backends import DjangoFilterBackend +from rest_framework import mixins +from rest_framework.filters import OrderingFilter, SearchFilter +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import GenericViewSet + +from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions +from authentik.core.api.groups import GroupMemberSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.enterprise.api import EnterpriseRequiredMixin +from authentik.enterprise.providers.rac.api.endpoints import EndpointSerializer +from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer +from authentik.enterprise.providers.rac.models import ConnectionToken + + +class ConnectionTokenSerializer(EnterpriseRequiredMixin, ModelSerializer): + """ConnectionToken Serializer""" + + provider_obj = RACProviderSerializer(source="provider", read_only=True) + endpoint_obj = EndpointSerializer(source="endpoint", read_only=True) + user = GroupMemberSerializer(source="session.user", read_only=True) + + class Meta: + model = ConnectionToken + fields = [ + "pk", + "provider", + "provider_obj", + "endpoint", + "endpoint_obj", + "user", + ] + + +class ConnectionTokenViewSet( + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + mixins.DestroyModelMixin, + UsedByMixin, + mixins.ListModelMixin, + GenericViewSet, +): + """ConnectionToken Viewset""" + + queryset = ConnectionToken.objects.all().select_related("session", "endpoint") + serializer_class = ConnectionTokenSerializer + filterset_fields = ["endpoint", "session__user", "provider"] + search_fields = ["endpoint__name", "provider__name"] + ordering = ["endpoint__name", "provider__name"] + permission_classes = [OwnerSuperuserPermissions] + filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter] diff --git a/authentik/enterprise/providers/rac/api/endpoints.py b/authentik/enterprise/providers/rac/api/endpoints.py index 1af281ef85..0dab4ca5f2 100644 --- a/authentik/enterprise/providers/rac/api/endpoints.py +++ b/authentik/enterprise/providers/rac/api/endpoints.py @@ -1,5 +1,4 @@ """RAC Provider API Views""" -from typing import Optional from django.core.cache import cache from django.db.models import QuerySet @@ -35,11 +34,11 @@ class EndpointSerializer(EnterpriseRequiredMixin, ModelSerializer): provider_obj = RACProviderSerializer(source="provider", read_only=True) launch_url = SerializerMethodField() - def get_launch_url(self, endpoint: Endpoint) -> Optional[str]: + def get_launch_url(self, endpoint: Endpoint) -> str | None: """Build actual launch URL (the provider itself does not have one, just individual endpoints)""" try: - # pylint: disable=no-member + return reverse( "authentik_providers_rac:start", kwargs={"app": endpoint.provider.application.slug, "endpoint": endpoint.pk}, diff --git a/authentik/enterprise/providers/rac/api/property_mappings.py b/authentik/enterprise/providers/rac/api/property_mappings.py index 360ad978a1..d41a4eb16c 100644 --- a/authentik/enterprise/providers/rac/api/property_mappings.py +++ b/authentik/enterprise/providers/rac/api/property_mappings.py @@ -1,4 +1,5 @@ """RAC Provider API Views""" + from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes @@ -6,7 +7,7 @@ from drf_spectacular.utils import extend_schema_field from rest_framework.fields import CharField from rest_framework.viewsets import ModelViewSet -from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.property_mappings import PropertyMappingSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import JSONDictField from authentik.enterprise.providers.rac.models import RACPropertyMapping diff --git a/authentik/enterprise/providers/rac/api/providers.py b/authentik/enterprise/providers/rac/api/providers.py index cda6c2af36..892e081c96 100644 --- a/authentik/enterprise/providers/rac/api/providers.py +++ b/authentik/enterprise/providers/rac/api/providers.py @@ -1,4 +1,5 @@ """RAC Provider API Views""" + from rest_framework.fields import CharField, ListField from rest_framework.viewsets import ModelViewSet @@ -15,7 +16,12 @@ class RACProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer): class Meta: model = RACProvider - fields = ProviderSerializer.Meta.fields + ["settings", "outpost_set", "connection_expiry"] + fields = ProviderSerializer.Meta.fields + [ + "settings", + "outpost_set", + "connection_expiry", + "delete_token_on_disconnect", + ] extra_kwargs = ProviderSerializer.Meta.extra_kwargs diff --git a/authentik/enterprise/providers/rac/apps.py b/authentik/enterprise/providers/rac/apps.py index d5958eb941..6359c5594b 100644 --- a/authentik/enterprise/providers/rac/apps.py +++ b/authentik/enterprise/providers/rac/apps.py @@ -1,4 +1,5 @@ """RAC app config""" + from authentik.enterprise.apps import EnterpriseConfig @@ -11,7 +12,3 @@ class AuthentikEnterpriseProviderRAC(EnterpriseConfig): default = True mountpoint = "" ws_mountpoint = "authentik.enterprise.providers.rac.urls" - - def reconcile_global_load_rac_signals(self): - """Load rac signals""" - self.import_module("authentik.enterprise.providers.rac.signals") diff --git a/authentik/enterprise/providers/rac/consumer_client.py b/authentik/enterprise/providers/rac/consumer_client.py index 57fef7d744..b6331ca563 100644 --- a/authentik/enterprise/providers/rac/consumer_client.py +++ b/authentik/enterprise/providers/rac/consumer_client.py @@ -1,4 +1,5 @@ """RAC Client consumer""" + from asgiref.sync import async_to_sync from channels.db import database_sync_to_async from channels.exceptions import ChannelFull, DenyConnection @@ -42,6 +43,7 @@ class RACClientConsumer(AsyncWebsocketConsumer): logger: BoundLogger async def connect(self): + self.logger = get_logger() await self.accept("guacamole") await self.channel_layer.group_add(RAC_CLIENT_GROUP, self.channel_name) await self.channel_layer.group_add( @@ -63,9 +65,11 @@ class RACClientConsumer(AsyncWebsocketConsumer): @database_sync_to_async def init_outpost_connection(self): """Initialize guac connection settings""" - self.token = ConnectionToken.filter_not_expired( - token=self.scope["url_route"]["kwargs"]["token"] - ).first() + self.token = ( + ConnectionToken.filter_not_expired(token=self.scope["url_route"]["kwargs"]["token"]) + .select_related("endpoint", "provider", "session", "session__user") + .first() + ) if not self.token: raise DenyConnection() self.provider = self.token.provider @@ -106,6 +110,9 @@ class RACClientConsumer(AsyncWebsocketConsumer): OUTPOST_GROUP_INSTANCE % {"outpost_pk": str(outpost.pk), "instance": states[0].uid}, msg, ) + if self.provider and self.provider.delete_token_on_disconnect: + self.logger.info("Deleting connection token to prevent reconnect", token=self.token) + self.token.delete() async def receive(self, text_data=None, bytes_data=None): """Mirror data received from client to the dest_channel_id diff --git a/authentik/enterprise/providers/rac/consumer_outpost.py b/authentik/enterprise/providers/rac/consumer_outpost.py index 8fa42d8598..a1119d85a8 100644 --- a/authentik/enterprise/providers/rac/consumer_outpost.py +++ b/authentik/enterprise/providers/rac/consumer_outpost.py @@ -1,4 +1,5 @@ """RAC consumer""" + from channels.exceptions import ChannelFull from channels.generic.websocket import AsyncWebsocketConsumer diff --git a/authentik/enterprise/providers/rac/controllers/docker.py b/authentik/enterprise/providers/rac/controllers/docker.py index 8dac04d061..56fca7b4a2 100644 --- a/authentik/enterprise/providers/rac/controllers/docker.py +++ b/authentik/enterprise/providers/rac/controllers/docker.py @@ -1,4 +1,5 @@ """RAC Provider Docker Controller""" + from authentik.outposts.controllers.docker import DockerController from authentik.outposts.models import DockerServiceConnection, Outpost diff --git a/authentik/enterprise/providers/rac/controllers/kubernetes.py b/authentik/enterprise/providers/rac/controllers/kubernetes.py index f7768735e7..b6eda83db9 100644 --- a/authentik/enterprise/providers/rac/controllers/kubernetes.py +++ b/authentik/enterprise/providers/rac/controllers/kubernetes.py @@ -1,4 +1,5 @@ """RAC Provider Kubernetes Controller""" + from authentik.outposts.controllers.k8s.service import ServiceReconciler from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.models import KubernetesServiceConnection, Outpost diff --git a/authentik/enterprise/providers/rac/migrations/0001_squashed_0003_alter_connectiontoken_options_and_more.py b/authentik/enterprise/providers/rac/migrations/0001_squashed_0003_alter_connectiontoken_options_and_more.py new file mode 100644 index 0000000000..3c6626f1a7 --- /dev/null +++ b/authentik/enterprise/providers/rac/migrations/0001_squashed_0003_alter_connectiontoken_options_and_more.py @@ -0,0 +1,181 @@ +# Generated by Django 5.0.1 on 2024-02-11 19:04 + +import uuid + +import django.db.models.deletion +from django.db import migrations, models + +import authentik.core.models +import authentik.lib.utils.time + + +class Migration(migrations.Migration): + + replaces = [ + ("authentik_providers_rac", "0001_initial"), + ("authentik_providers_rac", "0002_endpoint_maximum_connections"), + ("authentik_providers_rac", "0003_alter_connectiontoken_options_and_more"), + ] + + initial = True + + dependencies = [ + ("authentik_core", "0032_group_roles"), + ("authentik_policies", "0011_policybinding_failure_result_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="RACPropertyMapping", + fields=[ + ( + "propertymapping_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.propertymapping", + ), + ), + ("static_settings", models.JSONField(default=dict)), + ], + options={ + "verbose_name": "RAC Property Mapping", + "verbose_name_plural": "RAC Property Mappings", + }, + bases=("authentik_core.propertymapping",), + ), + migrations.CreateModel( + name="RACProvider", + fields=[ + ( + "provider_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.provider", + ), + ), + ("settings", models.JSONField(default=dict)), + ( + "auth_mode", + models.TextField( + choices=[("static", "Static"), ("prompt", "Prompt")], default="prompt" + ), + ), + ( + "connection_expiry", + models.TextField( + default="hours=8", + help_text="Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)", + validators=[authentik.lib.utils.time.timedelta_string_validator], + ), + ), + ( + "delete_token_on_disconnect", + models.BooleanField( + default=False, + help_text="When set to true, connection tokens will be deleted upon disconnect.", + ), + ), + ], + options={ + "verbose_name": "RAC Provider", + "verbose_name_plural": "RAC Providers", + }, + bases=("authentik_core.provider",), + ), + migrations.CreateModel( + name="Endpoint", + fields=[ + ( + "policybindingmodel_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_policies.policybindingmodel", + ), + ), + ("name", models.TextField()), + ("host", models.TextField()), + ( + "protocol", + models.TextField(choices=[("rdp", "Rdp"), ("vnc", "Vnc"), ("ssh", "Ssh")]), + ), + ("settings", models.JSONField(default=dict)), + ( + "auth_mode", + models.TextField(choices=[("static", "Static"), ("prompt", "Prompt")]), + ), + ( + "property_mappings", + models.ManyToManyField( + blank=True, default=None, to="authentik_core.propertymapping" + ), + ), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_rac.racprovider", + ), + ), + ("maximum_connections", models.IntegerField(default=1)), + ], + options={ + "verbose_name": "RAC Endpoint", + "verbose_name_plural": "RAC Endpoints", + }, + bases=("authentik_policies.policybindingmodel", models.Model), + ), + migrations.CreateModel( + name="ConnectionToken", + fields=[ + ( + "expires", + models.DateTimeField(default=authentik.core.models.default_token_duration), + ), + ("expiring", models.BooleanField(default=True)), + ( + "connection_token_uuid", + models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False), + ), + ("token", models.TextField(default=authentik.core.models.default_token_key)), + ("settings", models.JSONField(default=dict)), + ( + "endpoint", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_rac.endpoint", + ), + ), + ( + "provider", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_providers_rac.racprovider", + ), + ), + ( + "session", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_core.authenticatedsession", + ), + ), + ], + options={ + "abstract": False, + "verbose_name": "RAC Connection token", + "verbose_name_plural": "RAC Connection tokens", + }, + ), + ] diff --git a/authentik/enterprise/providers/rac/migrations/0003_alter_connectiontoken_options_and_more.py b/authentik/enterprise/providers/rac/migrations/0003_alter_connectiontoken_options_and_more.py new file mode 100644 index 0000000000..c333fedadd --- /dev/null +++ b/authentik/enterprise/providers/rac/migrations/0003_alter_connectiontoken_options_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.1 on 2024-02-11 19:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_providers_rac", "0002_endpoint_maximum_connections"), + ] + + operations = [ + migrations.AlterModelOptions( + name="connectiontoken", + options={ + "verbose_name": "RAC Connection token", + "verbose_name_plural": "RAC Connection tokens", + }, + ), + migrations.AddField( + model_name="racprovider", + name="delete_token_on_disconnect", + field=models.BooleanField( + default=False, + help_text="When set to true, connection tokens will be deleted upon disconnect.", + ), + ), + ] diff --git a/authentik/enterprise/providers/rac/migrations/0004_alter_connectiontoken_expires.py b/authentik/enterprise/providers/rac/migrations/0004_alter_connectiontoken_expires.py new file mode 100644 index 0000000000..60d1f7a253 --- /dev/null +++ b/authentik/enterprise/providers/rac/migrations/0004_alter_connectiontoken_expires.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_providers_rac", "0001_squashed_0003_alter_connectiontoken_options_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="connectiontoken", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + ] diff --git a/authentik/enterprise/providers/rac/models.py b/authentik/enterprise/providers/rac/models.py index 927bd23fec..42e7a266e0 100644 --- a/authentik/enterprise/providers/rac/models.py +++ b/authentik/enterprise/providers/rac/models.py @@ -1,16 +1,19 @@ """RAC Models""" -from typing import Optional + +from typing import Any from uuid import uuid4 from deepmerge import always_merger from django.db import models from django.db.models import QuerySet +from django.http import HttpRequest +from django.templatetags.static import static from django.utils.translation import gettext as _ from rest_framework.serializers import Serializer from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException -from authentik.core.models import ExpiringModel, PropertyMapping, Provider, default_token_key +from authentik.core.expression.exceptions import PropertyMappingExpressionException +from authentik.core.models import ExpiringModel, PropertyMapping, Provider, User, default_token_key from authentik.events.models import Event, EventAction from authentik.lib.models import SerializerModel from authentik.lib.utils.time import timedelta_string_validator @@ -50,13 +53,21 @@ class RACProvider(Provider): "(Format: hours=-1;minutes=-2;seconds=-3)" ), ) + delete_token_on_disconnect = models.BooleanField( + default=False, + help_text=_("When set to true, connection tokens will be deleted upon disconnect."), + ) @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """URL to this provider and initiate authorization for the user. Can return None for providers that are not URL-based""" return "goauthentik.io://providers/rac/launch" + @property + def icon_url(self) -> str | None: + return static("authentik/sources/rac.svg") + @property def component(self) -> str: return "ak-provider-rac-form" @@ -106,6 +117,12 @@ class RACPropertyMapping(PropertyMapping): static_settings = models.JSONField(default=dict) + def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any: + """Evaluate `self.expression` using `**kwargs` as Context.""" + if len(self.static_settings) > 0: + return self.static_settings + return super().evaluate(user, request, **kwargs) + @property def component(self) -> str: return "ak-property-mapping-rac-form" @@ -154,9 +171,6 @@ class ConnectionToken(ExpiringModel): def mapping_evaluator(mappings: QuerySet): for mapping in mappings: mapping: RACPropertyMapping - if len(mapping.static_settings) > 0: - always_merger.merge(settings, mapping.static_settings) - continue try: mapping_settings = mapping.evaluate( self.session.user, None, endpoint=self.endpoint, provider=self.provider @@ -190,3 +204,10 @@ class ConnectionToken(ExpiringModel): continue settings[key] = str(value) return settings + + def __str__(self): + return f"RAC Connection token {self.session_id} to {self.provider_id}/{self.endpoint_id}" + + class Meta: + verbose_name = _("RAC Connection token") + verbose_name_plural = _("RAC Connection tokens") diff --git a/authentik/enterprise/providers/rac/signals.py b/authentik/enterprise/providers/rac/signals.py index 21f7276902..28cece00ab 100644 --- a/authentik/enterprise/providers/rac/signals.py +++ b/authentik/enterprise/providers/rac/signals.py @@ -1,4 +1,5 @@ """RAC Signals""" + from asgiref.sync import async_to_sync from channels.layers import get_channel_layer from django.contrib.auth.signals import user_logged_out @@ -44,8 +45,8 @@ def pre_delete_connection_token_disconnect(sender, instance: ConnectionToken, ** @receiver(post_save, sender=Endpoint) -def post_save_application(sender: type[Model], instance, created: bool, **_): - """Clear user's application cache upon application creation""" +def post_save_endpoint(sender: type[Model], instance, created: bool, **_): + """Clear user's endpoint cache upon endpoint creation""" if not created: # pragma: no cover return diff --git a/authentik/enterprise/providers/rac/tests/test_endpoints_api.py b/authentik/enterprise/providers/rac/tests/test_endpoints_api.py index 3000b345ce..1ad9b70daf 100644 --- a/authentik/enterprise/providers/rac/tests/test_endpoints_api.py +++ b/authentik/enterprise/providers/rac/tests/test_endpoints_api.py @@ -70,6 +70,7 @@ class TestEndpointsAPI(APITestCase): "authorization_flow": None, "property_mappings": [], "connection_expiry": "hours=8", + "delete_token_on_disconnect": False, "component": "ak-provider-rac-form", "assigned_application_slug": self.app.slug, "assigned_application_name": self.app.name, @@ -124,6 +125,7 @@ class TestEndpointsAPI(APITestCase): "assigned_application_slug": self.app.slug, "assigned_application_name": self.app.name, "connection_expiry": "hours=8", + "delete_token_on_disconnect": False, "verbose_name": "RAC Provider", "verbose_name_plural": "RAC Providers", "meta_model_name": "authentik_providers_rac.racprovider", @@ -152,6 +154,7 @@ class TestEndpointsAPI(APITestCase): "assigned_application_slug": self.app.slug, "assigned_application_name": self.app.name, "connection_expiry": "hours=8", + "delete_token_on_disconnect": False, "verbose_name": "RAC Provider", "verbose_name_plural": "RAC Providers", "meta_model_name": "authentik_providers_rac.racprovider", diff --git a/authentik/enterprise/providers/rac/tests/test_models.py b/authentik/enterprise/providers/rac/tests/test_models.py index 48218f41ba..5e583d7b6d 100644 --- a/authentik/enterprise/providers/rac/tests/test_models.py +++ b/authentik/enterprise/providers/rac/tests/test_models.py @@ -1,4 +1,5 @@ """Test RAC Models""" + from django.test import TransactionTestCase from authentik.core.models import Application, AuthenticatedSession diff --git a/authentik/enterprise/providers/rac/tests/test_views.py b/authentik/enterprise/providers/rac/tests/test_views.py index e2fb14a11f..a63f27fba0 100644 --- a/authentik/enterprise/providers/rac/tests/test_views.py +++ b/authentik/enterprise/providers/rac/tests/test_views.py @@ -1,4 +1,5 @@ """RAC Views tests""" + from datetime import timedelta from json import loads from time import mktime @@ -10,7 +11,8 @@ from rest_framework.test import APITestCase from authentik.core.models import Application from authentik.core.tests.utils import create_test_admin_user, create_test_flow -from authentik.enterprise.models import License, LicenseKey +from authentik.enterprise.license import LicenseKey +from authentik.enterprise.models import License from authentik.enterprise.providers.rac.models import Endpoint, Protocols, RACProvider from authentik.lib.generators import generate_id from authentik.policies.denied import AccessDeniedResponse @@ -38,7 +40,7 @@ class TestRACViews(APITestCase): ) @patch( - "authentik.enterprise.models.LicenseKey.validate", + "authentik.enterprise.license.LicenseKey.validate", MagicMock( return_value=LicenseKey( aud="", @@ -69,7 +71,7 @@ class TestRACViews(APITestCase): self.assertEqual(final_response.status_code, 200) @patch( - "authentik.enterprise.models.LicenseKey.validate", + "authentik.enterprise.license.LicenseKey.validate", MagicMock( return_value=LicenseKey( aud="", @@ -98,7 +100,7 @@ class TestRACViews(APITestCase): self.assertIsInstance(response, AccessDeniedResponse) @patch( - "authentik.enterprise.models.LicenseKey.validate", + "authentik.enterprise.license.LicenseKey.validate", MagicMock( return_value=LicenseKey( aud="", diff --git a/authentik/enterprise/providers/rac/urls.py b/authentik/enterprise/providers/rac/urls.py index 383619a3a5..8ee5e32089 100644 --- a/authentik/enterprise/providers/rac/urls.py +++ b/authentik/enterprise/providers/rac/urls.py @@ -1,10 +1,12 @@ """rac urls""" + from channels.auth import AuthMiddleware from channels.sessions import CookieMiddleware from django.urls import path from django.views.decorators.csrf import ensure_csrf_cookie from authentik.core.channels import TokenOutpostMiddleware +from authentik.enterprise.providers.rac.api.connection_tokens import ConnectionTokenViewSet from authentik.enterprise.providers.rac.api.endpoints import EndpointViewSet from authentik.enterprise.providers.rac.api.property_mappings import RACPropertyMappingViewSet from authentik.enterprise.providers.rac.api.providers import RACProviderViewSet @@ -44,4 +46,5 @@ api_urlpatterns = [ ("providers/rac", RACProviderViewSet), ("propertymappings/rac", RACPropertyMappingViewSet), ("rac/endpoints", EndpointViewSet), + ("rac/connection_tokens", ConnectionTokenViewSet), ] diff --git a/authentik/enterprise/providers/rac/views.py b/authentik/enterprise/providers/rac/views.py index c1dc2c6673..3cdcce2e0a 100644 --- a/authentik/enterprise/providers/rac/views.py +++ b/authentik/enterprise/providers/rac/views.py @@ -1,4 +1,5 @@ """RAC Views""" + from typing import Any from django.http import Http404, HttpRequest, HttpResponse @@ -46,7 +47,7 @@ class RACStartView(EnterprisePolicyAccessView): }, ) except FlowNonApplicableException: - raise Http404 + raise Http404 from None plan.insert_stage( in_memory_stage( RACFinalStage, @@ -103,14 +104,15 @@ class RACFinalStage(RedirectStage): # Check if we're already at the maximum connection limit all_tokens = ConnectionToken.filter_not_expired( endpoint=self.endpoint, - ).exclude(endpoint__maximum_connections__lte=-1) - if all_tokens.count() >= self.endpoint.maximum_connections: - msg = [_("Maximum connection limit reached.")] - # Check if any other tokens exist for the current user, and inform them - # they are already connected - if all_tokens.filter(session__user=self.request.user).exists(): - msg.append(_("(You are already connected in another tab/window)")) - return self.executor.stage_invalid(" ".join(msg)) + ) + if self.endpoint.maximum_connections > -1: + if all_tokens.count() >= self.endpoint.maximum_connections: + msg = [_("Maximum connection limit reached.")] + # Check if any other tokens exist for the current user, and inform them + # they are already connected + if all_tokens.filter(session__user=self.request.user).exists(): + msg.append(_("(You are already connected in another tab/window)")) + return self.executor.stage_invalid(" ".join(msg)) return super().dispatch(request, *args, **kwargs) def get_challenge(self, *args, **kwargs) -> RedirectChallenge: @@ -130,16 +132,7 @@ class RACFinalStage(RedirectStage): flow=self.executor.plan.flow_pk, endpoint=self.endpoint.name, ).from_http(self.request) - setattr( - self.executor.current_stage, - "destination", - self.request.build_absolute_uri( - reverse( - "authentik_providers_rac:if-rac", - kwargs={ - "token": str(token.token), - }, - ) - ), + self.executor.current_stage.destination = self.request.build_absolute_uri( + reverse("authentik_providers_rac:if-rac", kwargs={"token": str(token.token)}) ) return super().get_challenge(*args, **kwargs) diff --git a/authentik/enterprise/settings.py b/authentik/enterprise/settings.py index cc3ed2ae8d..0a35d52d35 100644 --- a/authentik/enterprise/settings.py +++ b/authentik/enterprise/settings.py @@ -1,17 +1,23 @@ """Enterprise additional settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand CELERY_BEAT_SCHEDULE = { - "enterprise_calculate_license": { - "task": "authentik.enterprise.tasks.calculate_license", - "schedule": crontab(minute=fqdn_rand("calculate_license"), hour="*/2"), + "enterprise_update_usage": { + "task": "authentik.enterprise.tasks.enterprise_update_usage", + "schedule": crontab(minute=fqdn_rand("enterprise_update_usage"), hour="*/2"), "options": {"queue": "authentik_scheduled"}, } } TENANT_APPS = [ "authentik.enterprise.audit", + "authentik.enterprise.providers.google_workspace", + "authentik.enterprise.providers.microsoft_entra", "authentik.enterprise.providers.rac", + "authentik.enterprise.stages.source", ] + +MIDDLEWARE = ["authentik.enterprise.middleware.EnterpriseMiddleware"] diff --git a/authentik/enterprise/signals.py b/authentik/enterprise/signals.py index 67e7c57455..c921f49466 100644 --- a/authentik/enterprise/signals.py +++ b/authentik/enterprise/signals.py @@ -1,11 +1,15 @@ """Enterprise signals""" + from datetime import datetime -from django.db.models.signals import pre_save +from django.core.cache import cache +from django.db.models.signals import post_save, pre_save from django.dispatch import receiver from django.utils.timezone import get_current_timezone +from authentik.enterprise.license import CACHE_KEY_ENTERPRISE_LICENSE from authentik.enterprise.models import License +from authentik.enterprise.tasks import enterprise_update_usage @receiver(pre_save, sender=License) @@ -16,3 +20,10 @@ def pre_save_license(sender: type[License], instance: License, **_): instance.internal_users = status.internal_users instance.external_users = status.external_users instance.expiry = datetime.fromtimestamp(status.exp, tz=get_current_timezone()) + + +@receiver(post_save, sender=License) +def post_save_license(sender: type[License], instance: License, **_): + """Trigger license usage calculation when license is saved""" + cache.delete(CACHE_KEY_ENTERPRISE_LICENSE) + enterprise_update_usage.delay() diff --git a/authentik/enterprise/stages/__init__.py b/authentik/enterprise/stages/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/stages/source/__init__.py b/authentik/enterprise/stages/source/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/stages/source/api.py b/authentik/enterprise/stages/source/api.py new file mode 100644 index 0000000000..97afcffa8b --- /dev/null +++ b/authentik/enterprise/stages/source/api.py @@ -0,0 +1,41 @@ +"""Source Stage API Views""" + +from rest_framework.exceptions import ValidationError +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.used_by import UsedByMixin +from authentik.core.models import Source +from authentik.enterprise.api import EnterpriseRequiredMixin +from authentik.enterprise.stages.source.models import SourceStage +from authentik.flows.api.stages import StageSerializer + + +class SourceStageSerializer(EnterpriseRequiredMixin, StageSerializer): + """SourceStage Serializer""" + + def validate_source(self, _source: Source) -> Source: + """Ensure configured source supports web-based login""" + source = Source.objects.filter(pk=_source.pk).select_subclasses().first() + if not source: + raise ValidationError("Invalid source") + if "request" in self.context: + login_button = source.ui_login_button(self.context["request"]) + if not login_button: + raise ValidationError( + "Invalid source selected, only web-based sources are supported." + ) + return source + + class Meta: + model = SourceStage + fields = StageSerializer.Meta.fields + ["source", "resume_timeout"] + + +class SourceStageViewSet(UsedByMixin, ModelViewSet): + """SourceStage Viewset""" + + queryset = SourceStage.objects.all() + serializer_class = SourceStageSerializer + filterset_fields = "__all__" + ordering = ["name"] + search_fields = ["name"] diff --git a/authentik/enterprise/stages/source/apps.py b/authentik/enterprise/stages/source/apps.py new file mode 100644 index 0000000000..2da1c768f6 --- /dev/null +++ b/authentik/enterprise/stages/source/apps.py @@ -0,0 +1,12 @@ +"""authentik stage app config""" + +from authentik.enterprise.apps import EnterpriseConfig + + +class AuthentikEnterpriseStageSourceConfig(EnterpriseConfig): + """authentik source stage config""" + + name = "authentik.enterprise.stages.source" + label = "authentik_stages_source" + verbose_name = "authentik Enterprise.Stages.Source" + default = True diff --git a/authentik/enterprise/stages/source/migrations/0001_initial.py b/authentik/enterprise/stages/source/migrations/0001_initial.py new file mode 100644 index 0000000000..e2c9144a29 --- /dev/null +++ b/authentik/enterprise/stages/source/migrations/0001_initial.py @@ -0,0 +1,53 @@ +# Generated by Django 5.0.2 on 2024-02-25 20:44 + +import authentik.lib.utils.time +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("authentik_core", "0033_alter_user_options"), + ("authentik_flows", "0027_auto_20231028_1424"), + ] + + operations = [ + migrations.CreateModel( + name="SourceStage", + fields=[ + ( + "stage_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_flows.stage", + ), + ), + ( + "resume_timeout", + models.TextField( + default="minutes=10", + help_text="Amount of time a user can take to return from the source to continue the flow (Format: hours=-1;minutes=-2;seconds=-3)", + validators=[authentik.lib.utils.time.timedelta_string_validator], + ), + ), + ( + "source", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="authentik_core.source" + ), + ), + ], + options={ + "verbose_name": "Source Stage", + "verbose_name_plural": "Source Stages", + }, + bases=("authentik_flows.stage",), + ), + ] diff --git a/authentik/enterprise/stages/source/migrations/__init__.py b/authentik/enterprise/stages/source/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/enterprise/stages/source/models.py b/authentik/enterprise/stages/source/models.py new file mode 100644 index 0000000000..ac3fedeb7f --- /dev/null +++ b/authentik/enterprise/stages/source/models.py @@ -0,0 +1,45 @@ +"""Source stage models""" + +from django.db import models +from django.utils.translation import gettext_lazy as _ +from django.views import View +from rest_framework.serializers import BaseSerializer + +from authentik.flows.models import Stage +from authentik.lib.utils.time import timedelta_string_validator + + +class SourceStage(Stage): + """Suspend the current flow execution and send the user to a source, + after which this flow execution is resumed.""" + + source = models.ForeignKey("authentik_core.Source", on_delete=models.CASCADE) + + resume_timeout = models.TextField( + default="minutes=10", + validators=[timedelta_string_validator], + help_text=_( + "Amount of time a user can take to return from the source to continue the flow " + "(Format: hours=-1;minutes=-2;seconds=-3)" + ), + ) + + @property + def serializer(self) -> type[BaseSerializer]: + from authentik.enterprise.stages.source.api import SourceStageSerializer + + return SourceStageSerializer + + @property + def view(self) -> type[View]: + from authentik.enterprise.stages.source.stage import SourceStageView + + return SourceStageView + + @property + def component(self) -> str: + return "ak-stage-source-form" + + class Meta: + verbose_name = _("Source Stage") + verbose_name_plural = _("Source Stages") diff --git a/authentik/enterprise/stages/source/stage.py b/authentik/enterprise/stages/source/stage.py new file mode 100644 index 0000000000..44d405d33a --- /dev/null +++ b/authentik/enterprise/stages/source/stage.py @@ -0,0 +1,79 @@ +"""Source stage logic""" + +from typing import Any +from uuid import uuid4 + +from django.http import HttpRequest, HttpResponse +from django.utils.text import slugify +from django.utils.timezone import now +from guardian.shortcuts import get_anonymous_user + +from authentik.core.models import Source, User +from authentik.core.sources.flow_manager import SESSION_KEY_OVERRIDE_FLOW_TOKEN +from authentik.core.types import UILoginButton +from authentik.enterprise.stages.source.models import SourceStage +from authentik.flows.challenge import Challenge, ChallengeResponse +from authentik.flows.models import FlowToken +from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED +from authentik.flows.stage import ChallengeStageView +from authentik.lib.utils.time import timedelta_from_string + +PLAN_CONTEXT_RESUME_TOKEN = "resume_token" # nosec + + +class SourceStageView(ChallengeStageView): + """Suspend the current flow execution and send the user to a source, + after which this flow execution is resumed.""" + + login_button: UILoginButton + + def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: + current_stage: SourceStage = self.executor.current_stage + source: Source = ( + Source.objects.filter(pk=current_stage.source_id).select_subclasses().first() + ) + if not source: + self.logger.warning("Source does not exist") + return self.executor.stage_invalid("Source does not exist") + self.login_button = source.ui_login_button(self.request) + if not self.login_button: + self.logger.warning("Source does not have a UI login button") + return self.executor.stage_invalid("Invalid source") + restore_token = self.executor.plan.context.get(PLAN_CONTEXT_IS_RESTORED) + override_token = self.request.session.get(SESSION_KEY_OVERRIDE_FLOW_TOKEN) + if restore_token and override_token and restore_token.pk == override_token.pk: + del self.request.session[SESSION_KEY_OVERRIDE_FLOW_TOKEN] + return self.executor.stage_ok() + return super().dispatch(request, *args, **kwargs) + + def get_challenge(self, *args, **kwargs) -> Challenge: + resume_token = self.create_flow_token() + self.request.session[SESSION_KEY_OVERRIDE_FLOW_TOKEN] = resume_token + return self.login_button.challenge + + def create_flow_token(self) -> FlowToken: + """Save the current flow state in a token that can be used to resume this flow""" + pending_user: User = self.get_pending_user() + if pending_user.is_anonymous or not pending_user.pk: + pending_user = get_anonymous_user() + current_stage: SourceStage = self.executor.current_stage + identifier = slugify(f"ak-source-stage-{current_stage.name}-{str(uuid4())}") + # Don't check for validity here, we only care if the token exists + tokens = FlowToken.objects.filter(identifier=identifier) + valid_delta = timedelta_from_string(current_stage.resume_timeout) + if not tokens.exists(): + return FlowToken.objects.create( + expires=now() + valid_delta, + user=pending_user, + identifier=identifier, + flow=self.executor.flow, + _plan=FlowToken.pickle(self.executor.plan), + ) + token = tokens.first() + # Check if token is expired and rotate key if so + if token.is_expired: + token.expire_action() + return token + + def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: + return self.executor.stage_ok() diff --git a/authentik/enterprise/stages/source/tests.py b/authentik/enterprise/stages/source/tests.py new file mode 100644 index 0000000000..954f2c3206 --- /dev/null +++ b/authentik/enterprise/stages/source/tests.py @@ -0,0 +1,99 @@ +"""Source stage tests""" + +from django.urls import reverse + +from authentik.core.tests.utils import create_test_flow, create_test_user +from authentik.enterprise.stages.source.models import SourceStage +from authentik.flows.models import FlowDesignation, FlowStageBinding, FlowToken +from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, FlowPlan +from authentik.flows.tests import FlowTestCase +from authentik.flows.views.executor import SESSION_KEY_PLAN +from authentik.lib.generators import generate_id +from authentik.sources.saml.models import SAMLSource +from authentik.stages.identification.models import IdentificationStage, UserFields +from authentik.stages.password import BACKEND_INBUILT +from authentik.stages.password.models import PasswordStage +from authentik.stages.user_login.models import UserLoginStage + + +class TestSourceStage(FlowTestCase): + """Source stage tests""" + + def setUp(self): + self.source = SAMLSource.objects.create( + slug=generate_id(), + issuer="authentik", + allow_idp_initiated=True, + pre_authentication_flow=create_test_flow(), + ) + + def test_source_success(self): + """Test""" + user = create_test_user() + flow = create_test_flow(FlowDesignation.AUTHENTICATION) + stage = SourceStage.objects.create(name=generate_id(), source=self.source) + FlowStageBinding.objects.create( + target=flow, + stage=IdentificationStage.objects.create( + name=generate_id(), + user_fields=[UserFields.USERNAME], + ), + order=0, + ) + FlowStageBinding.objects.create( + target=flow, + stage=PasswordStage.objects.create(name=generate_id(), backends=[BACKEND_INBUILT]), + order=5, + ) + FlowStageBinding.objects.create(target=flow, stage=stage, order=10) + FlowStageBinding.objects.create( + target=flow, + stage=UserLoginStage.objects.create( + name=generate_id(), + ), + order=15, + ) + + # Get user identification stage + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + ) + self.assertEqual(response.status_code, 200) + self.assertStageResponse(response, flow, component="ak-stage-identification") + # Send username + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + data={"uid_field": user.username}, + follow=True, + ) + self.assertEqual(response.status_code, 200) + self.assertStageResponse(response, flow, component="ak-stage-password") + # Send password + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + data={"password": user.username}, + follow=True, + ) + self.assertEqual(response.status_code, 200) + self.assertStageRedirects( + response, + reverse("authentik_sources_saml:login", kwargs={"source_slug": self.source.slug}), + ) + + # Hijack flow plan so we don't have to emulate the source + flow_token = FlowToken.objects.filter( + identifier__startswith=f"ak-source-stage-{stage.name.lower()}" + ).first() + self.assertIsNotNone(flow_token) + session = self.client.session + plan: FlowPlan = session[SESSION_KEY_PLAN] + plan.context[PLAN_CONTEXT_IS_RESTORED] = flow_token + session[SESSION_KEY_PLAN] = plan + session.save() + + # Pretend we've just returned from the source + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), follow=True + ) + self.assertEqual(response.status_code, 200) + self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) diff --git a/authentik/enterprise/stages/source/urls.py b/authentik/enterprise/stages/source/urls.py new file mode 100644 index 0000000000..d0eb9786f9 --- /dev/null +++ b/authentik/enterprise/stages/source/urls.py @@ -0,0 +1,5 @@ +"""API URLs""" + +from authentik.enterprise.stages.source.api import SourceStageViewSet + +api_urlpatterns = [("stages/source", SourceStageViewSet)] diff --git a/authentik/enterprise/tasks.py b/authentik/enterprise/tasks.py index 2063cf07ac..a55ab5e13d 100644 --- a/authentik/enterprise/tasks.py +++ b/authentik/enterprise/tasks.py @@ -1,9 +1,14 @@ """Enterprise tasks""" -from authentik.enterprise.models import LicenseKey + +from authentik.enterprise.license import LicenseKey +from authentik.events.models import TaskStatus +from authentik.events.system_tasks import SystemTask, prefill_task from authentik.root.celery import CELERY_APP -@CELERY_APP.task() -def calculate_license(): - """Calculate licensing status""" +@CELERY_APP.task(bind=True, base=SystemTask) +@prefill_task +def enterprise_update_usage(self: SystemTask): + """Update enterprise license status""" LicenseKey.get_total().record_usage() + self.set_status(TaskStatus.SUCCESSFUL) diff --git a/authentik/enterprise/tests/test_license.py b/authentik/enterprise/tests/test_license.py index dd91af1a6f..efa45e0eb6 100644 --- a/authentik/enterprise/tests/test_license.py +++ b/authentik/enterprise/tests/test_license.py @@ -1,4 +1,5 @@ """Enterprise license tests""" + from datetime import timedelta from time import mktime from unittest.mock import MagicMock, patch @@ -7,7 +8,8 @@ from django.test import TestCase from django.utils.timezone import now from rest_framework.exceptions import ValidationError -from authentik.enterprise.models import License, LicenseKey +from authentik.enterprise.license import LicenseKey +from authentik.enterprise.models import License from authentik.lib.generators import generate_id _exp = int(mktime((now() + timedelta(days=3000)).timetuple())) @@ -17,7 +19,7 @@ class TestEnterpriseLicense(TestCase): """Enterprise license tests""" @patch( - "authentik.enterprise.models.LicenseKey.validate", + "authentik.enterprise.license.LicenseKey.validate", MagicMock( return_value=LicenseKey( aud="", @@ -40,7 +42,7 @@ class TestEnterpriseLicense(TestCase): License.objects.create(key=generate_id()) @patch( - "authentik.enterprise.models.LicenseKey.validate", + "authentik.enterprise.license.LicenseKey.validate", MagicMock( return_value=LicenseKey( aud="", diff --git a/authentik/events/api/events.py b/authentik/events/api/events.py index dbec7a5149..2e4ae6f307 100644 --- a/authentik/events/api/events.py +++ b/authentik/events/api/events.py @@ -1,4 +1,5 @@ """Events API Views""" + from datetime import timedelta from json import loads @@ -18,7 +19,8 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.admin.api.metrics import CoordinateSerializer -from authentik.core.api.utils import PassiveSerializer, TypeCreateSerializer +from authentik.core.api.object_types import TypeCreateSerializer +from authentik.core.api.utils import PassiveSerializer from authentik.events.models import Event, EventAction diff --git a/authentik/events/api/notification_mappings.py b/authentik/events/api/notification_mappings.py index 6e84332ea4..86a23fa810 100644 --- a/authentik/events/api/notification_mappings.py +++ b/authentik/events/api/notification_mappings.py @@ -1,4 +1,5 @@ """NotificationWebhookMapping API Views""" + from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet diff --git a/authentik/events/api/notification_rules.py b/authentik/events/api/notification_rules.py index 6258f57bda..ada4332bb9 100644 --- a/authentik/events/api/notification_rules.py +++ b/authentik/events/api/notification_rules.py @@ -1,4 +1,5 @@ """NotificationRule API Views""" + from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet diff --git a/authentik/events/api/notification_transports.py b/authentik/events/api/notification_transports.py index 30cd88d17d..682bb7248f 100644 --- a/authentik/events/api/notification_transports.py +++ b/authentik/events/api/notification_transports.py @@ -1,4 +1,5 @@ """NotificationTransport API Views""" + from typing import Any from drf_spectacular.types import OpenApiTypes @@ -11,7 +12,6 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet -from authentik.api.decorators import permission_required from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.events.models import ( @@ -23,6 +23,7 @@ from authentik.events.models import ( TransportMode, ) from authentik.events.utils import get_user +from authentik.rbac.decorators import permission_required class NotificationTransportSerializer(ModelSerializer): @@ -86,7 +87,6 @@ class NotificationTransportViewSet(UsedByMixin, ModelViewSet): event = Event.new( action="notification_test", user=get_user(request.user), - app=self.__class__.__module__, context={"foo": "bar"}, ) event.save() diff --git a/authentik/events/api/notifications.py b/authentik/events/api/notifications.py index 32608ec28d..3df2744ace 100644 --- a/authentik/events/api/notifications.py +++ b/authentik/events/api/notifications.py @@ -1,4 +1,5 @@ """Notification API Views""" + from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema diff --git a/authentik/events/api/tasks.py b/authentik/events/api/tasks.py index c89724059e..529464ad5f 100644 --- a/authentik/events/api/tasks.py +++ b/authentik/events/api/tasks.py @@ -1,5 +1,5 @@ """Tasks API""" -from datetime import datetime, timezone + from importlib import import_module from django.contrib import messages @@ -7,15 +7,22 @@ from django.utils.translation import gettext_lazy as _ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework.decorators import action -from rest_framework.fields import CharField, ChoiceField, ListField, SerializerMethodField +from rest_framework.fields import ( + CharField, + ChoiceField, + DateTimeField, + FloatField, + SerializerMethodField, +) from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet from structlog.stdlib import get_logger -from authentik.api.decorators import permission_required +from authentik.events.logs import LogEventSerializer from authentik.events.models import SystemTask, TaskStatus +from authentik.rbac.decorators import permission_required LOGGER = get_logger() @@ -27,12 +34,12 @@ class SystemTaskSerializer(ModelSerializer): full_name = SerializerMethodField() uid = CharField(required=False) description = CharField() - start_timestamp = SerializerMethodField() - finish_timestamp = SerializerMethodField() - duration = SerializerMethodField() + start_timestamp = DateTimeField(read_only=True) + finish_timestamp = DateTimeField(read_only=True) + duration = FloatField(read_only=True) status = ChoiceField(choices=[(x.value, x.name) for x in TaskStatus]) - messages = ListField(child=CharField()) + messages = LogEventSerializer(many=True) def get_full_name(self, instance: SystemTask) -> str: """Get full name with UID""" @@ -40,18 +47,6 @@ class SystemTaskSerializer(ModelSerializer): return f"{instance.name}:{instance.uid}" return instance.name - def get_start_timestamp(self, instance: SystemTask) -> datetime: - """Timestamp when the task started""" - return datetime.fromtimestamp(instance.start_timestamp, tz=timezone.utc) - - def get_finish_timestamp(self, instance: SystemTask) -> datetime: - """Timestamp when the task finished""" - return datetime.fromtimestamp(instance.finish_timestamp, tz=timezone.utc) - - def get_duration(self, instance: SystemTask) -> float: - """Get the duration a task took to run""" - return max(instance.finish_timestamp - instance.start_timestamp, 0) - class Meta: model = SystemTask fields = [ @@ -65,6 +60,8 @@ class SystemTaskSerializer(ModelSerializer): "duration", "status", "messages", + "expires", + "expiring", ] @@ -86,7 +83,7 @@ class SystemTaskViewSet(ReadOnlyModelViewSet): 500: OpenApiResponse(description="Failed to retry task"), }, ) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=["POST"], permission_classes=[]) def run(self, request: Request, pk=None) -> Response: """Run task""" task: SystemTask = self.get_object() @@ -97,7 +94,7 @@ class SystemTaskViewSet(ReadOnlyModelViewSet): task_func.delay(*task.task_call_args, **task.task_call_kwargs) messages.success( self.request, - _("Successfully started task %(name)s." % {"name": task.name}), + _("Successfully started task {name}.".format_map({"name": task.name})), ) return Response(status=204) except (ImportError, AttributeError) as exc: # pragma: no cover diff --git a/authentik/events/apps.py b/authentik/events/apps.py index af5461f368..915b923afc 100644 --- a/authentik/events/apps.py +++ b/authentik/events/apps.py @@ -1,8 +1,12 @@ """authentik events app""" + +from celery.schedules import crontab from prometheus_client import Gauge, Histogram from authentik.blueprints.apps import ManagedAppConfig from authentik.lib.config import CONFIG, ENV_PREFIX +from authentik.lib.utils.reflection import path_to_class +from authentik.root.celery import CELERY_APP # TODO: Deprecated metric - remove in 2024.2 or later GAUGE_TASKS = Gauge( @@ -14,11 +18,12 @@ GAUGE_TASKS = Gauge( SYSTEM_TASK_TIME = Histogram( "authentik_system_tasks_time_seconds", "Runtime of system tasks", + ["tenant", "task_name", "task_uid"], ) SYSTEM_TASK_STATUS = Gauge( "authentik_system_tasks_status", "System task status", - ["task_name", "task_uid", "status"], + ["tenant", "task_name", "task_uid", "status"], ) @@ -30,11 +35,8 @@ class AuthentikEventsConfig(ManagedAppConfig): verbose_name = "authentik Events" default = True - def reconcile_global_load_events_signals(self): - """Load events signals""" - self.import_module("authentik.events.signals") - - def reconcile_global_check_deprecations(self): + @ManagedAppConfig.reconcile_global + def check_deprecations(self): """Check for config deprecations""" from authentik.events.models import Event, EventAction @@ -55,7 +57,8 @@ class AuthentikEventsConfig(ManagedAppConfig): message=msg, ).save() - def reconcile_prefill_tasks(self): + @ManagedAppConfig.reconcile_tenant + def prefill_tasks(self): """Prefill tasks""" from authentik.events.models import SystemTask from authentik.events.system_tasks import _prefill_tasks @@ -65,3 +68,29 @@ class AuthentikEventsConfig(ManagedAppConfig): continue task.save() self.logger.debug("prefilled task", task_name=task.name) + + @ManagedAppConfig.reconcile_tenant + def run_scheduled_tasks(self): + """Run schedule tasks which are behind schedule (only applies + to tasks of which we keep metrics)""" + from authentik.events.models import TaskStatus + from authentik.events.system_tasks import SystemTask as CelerySystemTask + + for task in CELERY_APP.conf["beat_schedule"].values(): + schedule = task["schedule"] + if not isinstance(schedule, crontab): + continue + task_class: CelerySystemTask = path_to_class(task["task"]) + if not isinstance(task_class, CelerySystemTask): + continue + db_task = task_class.db() + if not db_task: + continue + due, _ = schedule.is_due(db_task.finish_timestamp) + if due or db_task.status == TaskStatus.UNKNOWN: + self.logger.debug("Running past-due scheduled task", task=task["task"]) + task_class.apply_async( + args=task.get("args", None), + kwargs=task.get("kwargs", None), + **task.get("options", {}), + ) diff --git a/authentik/events/context_processors/asn.py b/authentik/events/context_processors/asn.py index 4478c7fb04..23288d55f7 100644 --- a/authentik/events/context_processors/asn.py +++ b/authentik/events/context_processors/asn.py @@ -1,4 +1,5 @@ """ASN Enricher""" + from typing import TYPE_CHECKING, Optional, TypedDict from django.http import HttpRequest @@ -45,7 +46,7 @@ class ASNContextProcessor(MMDBContextProcessor): "asn": self.asn_dict(ClientIPMiddleware.get_client_ip(request)), } - def asn(self, ip_address: str) -> Optional[ASN]: + def asn(self, ip_address: str) -> ASN | None: """Wrapper for Reader.asn""" with Hub.current.start_span( op="authentik.events.asn.asn", @@ -70,7 +71,7 @@ class ASNContextProcessor(MMDBContextProcessor): } return asn_dict - def asn_dict(self, ip_address: str) -> Optional[ASNDict]: + def asn_dict(self, ip_address: str) -> ASNDict | None: """Wrapper for self.asn that returns a dict""" asn = self.asn(ip_address) if not asn: diff --git a/authentik/events/context_processors/base.py b/authentik/events/context_processors/base.py index 96a46a65a0..fe94dd6d09 100644 --- a/authentik/events/context_processors/base.py +++ b/authentik/events/context_processors/base.py @@ -1,4 +1,5 @@ """Base event enricher""" + from functools import cache from typing import TYPE_CHECKING, Optional diff --git a/authentik/events/context_processors/geoip.py b/authentik/events/context_processors/geoip.py index 40ea0b0126..76de1a3ae4 100644 --- a/authentik/events/context_processors/geoip.py +++ b/authentik/events/context_processors/geoip.py @@ -1,4 +1,5 @@ """events GeoIP Reader""" + from typing import TYPE_CHECKING, Optional, TypedDict from django.http import HttpRequest @@ -46,7 +47,7 @@ class GeoIPContextProcessor(MMDBContextProcessor): # Different key `geoip` vs `geo` for legacy reasons return {"geoip": self.city(ClientIPMiddleware.get_client_ip(request))} - def city(self, ip_address: str) -> Optional[City]: + def city(self, ip_address: str) -> City | None: """Wrapper for Reader.city""" with Hub.current.start_span( op="authentik.events.geo.city", @@ -75,7 +76,7 @@ class GeoIPContextProcessor(MMDBContextProcessor): city_dict["city"] = city.city.name return city_dict - def city_dict(self, ip_address: str) -> Optional[GeoIPDict]: + def city_dict(self, ip_address: str) -> GeoIPDict | None: """Wrapper for self.city that returns a dict""" city = self.city(ip_address) if not city: diff --git a/authentik/events/context_processors/mmdb.py b/authentik/events/context_processors/mmdb.py index 45bd854115..4ba762fe84 100644 --- a/authentik/events/context_processors/mmdb.py +++ b/authentik/events/context_processors/mmdb.py @@ -1,6 +1,6 @@ """Common logic for reading MMDB files""" + from pathlib import Path -from typing import Optional from geoip2.database import Reader from structlog.stdlib import get_logger @@ -12,7 +12,7 @@ class MMDBContextProcessor(EventContextProcessor): """Common logic for reading MaxMind DB files, including re-loading if the file has changed""" def __init__(self): - self.reader: Optional[Reader] = None + self.reader: Reader | None = None self._last_mtime: float = 0.0 self.logger = get_logger() self.open() diff --git a/authentik/events/logs.py b/authentik/events/logs.py new file mode 100644 index 0000000000..30fd757ce2 --- /dev/null +++ b/authentik/events/logs.py @@ -0,0 +1,82 @@ +from collections.abc import Generator +from contextlib import contextmanager +from dataclasses import dataclass, field +from datetime import datetime +from typing import Any + +from django.utils.timezone import now +from rest_framework.fields import CharField, ChoiceField, DateTimeField, DictField +from structlog import configure, get_config +from structlog.stdlib import NAME_TO_LEVEL, ProcessorFormatter +from structlog.testing import LogCapture +from structlog.types import EventDict + +from authentik.core.api.utils import PassiveSerializer +from authentik.events.utils import sanitize_dict + + +@dataclass() +class LogEvent: + + event: str + log_level: str + logger: str + timestamp: datetime = field(default_factory=now) + attributes: dict[str, Any] = field(default_factory=dict) + + @staticmethod + def from_event_dict(item: EventDict) -> "LogEvent": + event = item.pop("event") + log_level = item.pop("level").lower() + timestamp = datetime.fromisoformat(item.pop("timestamp")) + item.pop("pid", None) + # Sometimes log entries have both `level` and `log_level` set, but `level` is always set + item.pop("log_level", None) + return LogEvent( + event, log_level, item.pop("logger"), timestamp, attributes=sanitize_dict(item) + ) + + +class LogEventSerializer(PassiveSerializer): + """Single log message with all context logged.""" + + timestamp = DateTimeField() + log_level = ChoiceField(choices=tuple((x, x) for x in NAME_TO_LEVEL.keys())) + logger = CharField() + event = CharField() + attributes = DictField() + + # TODO(2024.6?): This is a migration helper to return a correct API response for logs that + # have been saved in an older format (mostly just list[str] with just the messages) + def to_representation(self, instance): + if isinstance(instance, str): + instance = LogEvent(instance, "", "") + elif isinstance(instance, list): + instance = [LogEvent(x, "", "") for x in instance] + return super().to_representation(instance) + + +@contextmanager +def capture_logs(log_default_output=True) -> Generator[list[LogEvent], None, None]: + """Capture log entries created""" + logs = [] + cap = LogCapture() + # Modify `_Configuration.default_processors` set via `configure` but always + # keep the list instance intact to not break references held by bound + # loggers. + processors: list = get_config()["processors"] + old_processors = processors.copy() + try: + # clear processors list and use LogCapture for testing + if ProcessorFormatter.wrap_for_formatter in processors: + processors.remove(ProcessorFormatter.wrap_for_formatter) + processors.append(cap) + configure(processors=processors) + yield logs + for raw_log in cap.entries: + logs.append(LogEvent.from_event_dict(raw_log)) + finally: + # remove LogCapture and restore original processors + processors.clear() + processors.extend(old_processors) + configure(processors=processors) diff --git a/authentik/events/middleware.py b/authentik/events/middleware.py index e0f722ccfe..a3ff3c8b70 100644 --- a/authentik/events/middleware.py +++ b/authentik/events/middleware.py @@ -1,7 +1,11 @@ """Events middleware""" + +from collections.abc import Callable +from contextlib import contextmanager +from contextvars import ContextVar from functools import partial from threading import Thread -from typing import Any, Callable, Optional +from typing import Any from django.conf import settings from django.contrib.sessions.models import Session @@ -29,6 +33,9 @@ IGNORED_MODELS = tuple( ) ) +_CTX_OVERWRITE_USER = ContextVar[User | None]("authentik_events_log_overwrite_user", default=None) +_CTX_IGNORE = ContextVar[bool]("authentik_events_log_ignore", default=False) + def should_log_model(model: Model) -> bool: """Return true if operation on `model` should be logged""" @@ -42,15 +49,37 @@ def should_log_m2m(model: Model) -> bool: return False +@contextmanager +def audit_overwrite_user(user: User): + """Overwrite user being logged for model AuditMiddleware. Commonly used + for example in flows where a pending user is given, but the request is not authenticated yet""" + _CTX_OVERWRITE_USER.set(user) + try: + yield + finally: + _CTX_OVERWRITE_USER.set(None) + + +@contextmanager +def audit_ignore(): + """Ignore model operations in the block. Useful for objects which need to be modified + but are not excluded (e.g. WebAuthn devices)""" + _CTX_IGNORE.set(True) + try: + yield + finally: + _CTX_IGNORE.set(False) + + class EventNewThread(Thread): """Create Event in background thread""" action: str request: HttpRequest kwargs: dict[str, Any] - user: Optional[User] = None + user: User | None = None - def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs): + def __init__(self, action: str, request: HttpRequest, user: User | None = None, **kwargs): super().__init__() self.action = action self.request = request @@ -81,26 +110,32 @@ class AuditMiddleware: self.anonymous_user = get_anonymous_user() - def connect(self, request: HttpRequest): - """Connect signal for automatic logging""" - self._ensure_fallback_user() + def get_user(self, request: HttpRequest) -> User: + user = _CTX_OVERWRITE_USER.get() + if user: + return user user = getattr(request, "user", self.anonymous_user) if not user.is_authenticated: - user = self.anonymous_user + self._ensure_fallback_user() + return self.anonymous_user + return user + + def connect(self, request: HttpRequest): + """Connect signal for automatic logging""" if not hasattr(request, "request_id"): return post_save.connect( - partial(self.post_save_handler, user=user, request=request), + partial(self.post_save_handler, request=request), dispatch_uid=request.request_id, weak=False, ) pre_delete.connect( - partial(self.pre_delete_handler, user=user, request=request), + partial(self.pre_delete_handler, request=request), dispatch_uid=request.request_id, weak=False, ) m2m_changed.connect( - partial(self.m2m_changed_handler, user=user, request=request), + partial(self.m2m_changed_handler, request=request), dispatch_uid=request.request_id, weak=False, ) @@ -143,30 +178,34 @@ class AuditMiddleware: ) thread.run() - # pylint: disable=too-many-arguments def post_save_handler( self, - user: User, request: HttpRequest, sender, instance: Model, created: bool, - thread_kwargs: Optional[dict] = None, + thread_kwargs: dict | None = None, **_, ): """Signal handler for all object's post_save""" if not should_log_model(instance): return + if _CTX_IGNORE.get(): + return + user = self.get_user(request) action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED thread = EventNewThread(action, request, user=user, model=model_to_dict(instance)) thread.kwargs.update(thread_kwargs or {}) thread.run() - def pre_delete_handler(self, user: User, request: HttpRequest, sender, instance: Model, **_): + def pre_delete_handler(self, request: HttpRequest, sender, instance: Model, **_): """Signal handler for all object's pre_delete""" if not should_log_model(instance): # pragma: no cover return + if _CTX_IGNORE.get(): + return + user = self.get_user(request) EventNewThread( EventAction.MODEL_DELETED, @@ -176,17 +215,27 @@ class AuditMiddleware: ).run() def m2m_changed_handler( - self, user: User, request: HttpRequest, sender, instance: Model, action: str, **_ + self, + request: HttpRequest, + sender, + instance: Model, + action: str, + thread_kwargs: dict | None = None, + **_, ): """Signal handler for all object's m2m_changed""" if action not in ["pre_add", "pre_remove", "post_clear"]: return if not should_log_m2m(instance): return + if _CTX_IGNORE.get(): + return + user = self.get_user(request) EventNewThread( EventAction.MODEL_UPDATED, request, user=user, model=model_to_dict(instance), + **thread_kwargs, ).run() diff --git a/authentik/events/migrations/0004_systemtask_squashed_0005_remove_systemtask_finish_timestamp_and_more.py b/authentik/events/migrations/0004_systemtask_squashed_0005_remove_systemtask_finish_timestamp_and_more.py new file mode 100644 index 0000000000..b66db2af63 --- /dev/null +++ b/authentik/events/migrations/0004_systemtask_squashed_0005_remove_systemtask_finish_timestamp_and_more.py @@ -0,0 +1,68 @@ +# Generated by Django 5.0.1 on 2024-02-07 15:42 + +import uuid + +import django.utils.timezone +from django.db import migrations, models + +import authentik.core.models + + +class Migration(migrations.Migration): + + replaces = [ + ("authentik_events", "0004_systemtask"), + ("authentik_events", "0005_remove_systemtask_finish_timestamp_and_more"), + ] + + dependencies = [ + ("authentik_events", "0003_rename_tenant_event_brand"), + ] + + operations = [ + migrations.CreateModel( + name="SystemTask", + fields=[ + ( + "expires", + models.DateTimeField(default=authentik.core.models.default_token_duration), + ), + ("expiring", models.BooleanField(default=True)), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("name", models.TextField()), + ("uid", models.TextField(null=True)), + ( + "status", + models.TextField( + choices=[ + ("unknown", "Unknown"), + ("successful", "Successful"), + ("warning", "Warning"), + ("error", "Error"), + ] + ), + ), + ("description", models.TextField(null=True)), + ("messages", models.JSONField()), + ("task_call_module", models.TextField()), + ("task_call_func", models.TextField()), + ("task_call_args", models.JSONField(default=list)), + ("task_call_kwargs", models.JSONField(default=dict)), + ("duration", models.FloatField(default=0)), + ("finish_timestamp", models.DateTimeField(default=django.utils.timezone.now)), + ("start_timestamp", models.DateTimeField(default=django.utils.timezone.now)), + ], + options={ + "verbose_name": "System Task", + "verbose_name_plural": "System Tasks", + "permissions": [("run_task", "Run task")], + "default_permissions": ["view"], + "unique_together": {("name", "uid")}, + }, + ), + ] diff --git a/authentik/events/migrations/0005_remove_systemtask_finish_timestamp_and_more.py b/authentik/events/migrations/0005_remove_systemtask_finish_timestamp_and_more.py new file mode 100644 index 0000000000..8871965b7f --- /dev/null +++ b/authentik/events/migrations/0005_remove_systemtask_finish_timestamp_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 5.0.1 on 2024-02-06 18:02 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_events", "0004_systemtask"), + ] + + operations = [ + migrations.RemoveField( + model_name="systemtask", + name="finish_timestamp", + ), + migrations.RemoveField( + model_name="systemtask", + name="start_timestamp", + ), + migrations.AddField( + model_name="systemtask", + name="duration", + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name="systemtask", + name="finish_timestamp", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name="systemtask", + name="start_timestamp", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/authentik/events/migrations/0006_alter_systemtask_expires.py b/authentik/events/migrations/0006_alter_systemtask_expires.py new file mode 100644 index 0000000000..9b5c2738ca --- /dev/null +++ b/authentik/events/migrations/0006_alter_systemtask_expires.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "authentik_events", + "0004_systemtask_squashed_0005_remove_systemtask_finish_timestamp_and_more", + ), + ] + + operations = [ + migrations.AlterField( + model_name="systemtask", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + ] diff --git a/authentik/events/migrations/0007_event_authentik_e_action_9a9dd9_idx_and_more.py b/authentik/events/migrations/0007_event_authentik_e_action_9a9dd9_idx_and_more.py new file mode 100644 index 0000000000..e2dd02c3d1 --- /dev/null +++ b/authentik/events/migrations/0007_event_authentik_e_action_9a9dd9_idx_and_more.py @@ -0,0 +1,39 @@ +# Generated by Django 5.0.4 on 2024-04-15 16:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_events", "0006_alter_systemtask_expires"), + ] + + operations = [ + migrations.AddIndex( + model_name="event", + index=models.Index(fields=["action"], name="authentik_e_action_9a9dd9_idx"), + ), + migrations.AddIndex( + model_name="event", + index=models.Index(fields=["user"], name="authentik_e_user_1be48d_idx"), + ), + migrations.AddIndex( + model_name="event", + index=models.Index(fields=["app"], name="authentik_e_app_6a05ce_idx"), + ), + migrations.AddIndex( + model_name="event", + index=models.Index(fields=["created"], name="authentik_e_created_6f0834_idx"), + ), + migrations.AddIndex( + model_name="event", + index=models.Index(fields=["client_ip"], name="authentik_e_client__51f4dd_idx"), + ), + migrations.AddIndex( + model_name="event", + index=models.Index( + models.F("context__authorized_application"), name="authentik_e_ctx_app__idx" + ), + ), + ] diff --git a/authentik/events/models.py b/authentik/events/models.py index 2dc2c01f3e..92d934c55b 100644 --- a/authentik/events/models.py +++ b/authentik/events/models.py @@ -1,4 +1,5 @@ """authentik events models""" + import time from collections import Counter from datetime import timedelta @@ -6,11 +7,10 @@ from difflib import get_close_matches from functools import lru_cache from inspect import currentframe from smtplib import SMTPException -from typing import Optional from uuid import uuid4 from django.apps import apps -from django.db import models +from django.db import connection, models from django.db.models import Count, ExpressionWrapper, F from django.db.models.fields import DurationField from django.db.models.functions import Extract @@ -51,6 +51,8 @@ from authentik.stages.email.utils import TemplateEmailMessage from authentik.tenants.models import Tenant LOGGER = get_logger() +DISCORD_FIELD_LIMIT = 25 +NOTIFICATION_SUMMARY_LENGTH = 75 def default_event_duration(): @@ -64,7 +66,7 @@ def default_brand(): return sanitize_dict(model_to_dict(DEFAULT_BRAND)) -@lru_cache() +@lru_cache def django_app_names() -> list[str]: """Get a cached list of all django apps' names (not labels)""" return [x.name for x in apps.app_configs.values()] @@ -197,7 +199,7 @@ class Event(SerializerModel, ExpiringModel): @staticmethod def new( action: str | EventAction, - app: Optional[str] = None, + app: str | None = None, **kwargs, ) -> "Event": """Create new Event instance from arguments. Instance is NOT saved.""" @@ -209,8 +211,9 @@ class Event(SerializerModel, ExpiringModel): app = parent.f_globals["__name__"] # Attempt to match the calling module to the django app it belongs to # if we can't find a match, keep the module name - django_apps = get_close_matches(app, django_app_names(), n=1) - if len(django_apps) > 0: + django_apps: list[str] = get_close_matches(app, django_app_names(), n=1) + # Also ensure that closest django app has the correct prefix + if len(django_apps) > 0 and django_apps[0].startswith(app): app = django_apps[0] cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs)) event = Event(action=action, app=app, context=cleaned_kwargs) @@ -222,7 +225,7 @@ class Event(SerializerModel, ExpiringModel): self.user = get_user(user) return self - def from_http(self, request: HttpRequest, user: Optional[User] = None) -> "Event": + def from_http(self, request: HttpRequest, user: User | None = None) -> "Event": """Add data from a Django-HttpRequest, allowing the creation of Events independently from requests. `user` arguments optionally overrides user from requests.""" @@ -302,6 +305,16 @@ class Event(SerializerModel, ExpiringModel): class Meta: verbose_name = _("Event") verbose_name_plural = _("Events") + indexes = [ + models.Index(fields=["action"]), + models.Index(fields=["user"]), + models.Index(fields=["app"]), + models.Index(fields=["created"]), + models.Index(fields=["client_ip"]), + models.Index( + models.F("context__authorized_application"), name="authentik_e_ctx_app__idx" + ), + ] class TransportMode(models.TextChoices): @@ -416,7 +429,7 @@ class NotificationTransport(SerializerModel): if not isinstance(value, str): continue # https://birdie0.github.io/discord-webhooks-guide/other/field_limits.html - if len(fields) >= 25: + if len(fields) >= DISCORD_FIELD_LIMIT: continue fields.append({"title": key[:256], "value": value[:1024]}) body = { @@ -449,6 +462,13 @@ class NotificationTransport(SerializerModel): def send_email(self, notification: "Notification") -> list[str]: """Send notification via global email configuration""" + if notification.user.email.strip() == "": + LOGGER.info( + "Discarding notification as user has no email address", + user=notification.user, + notification=notification, + ) + return None subject_prefix = "authentik Notification: " context = { "key_value": { @@ -470,7 +490,7 @@ class NotificationTransport(SerializerModel): continue context["key_value"][key] = value else: - context["title"] += notification.body[:75] + context["title"] += notification.body[:NOTIFICATION_SUMMARY_LENGTH] # TODO: improve permission check if notification.user.is_superuser: context["source"] = { @@ -478,7 +498,7 @@ class NotificationTransport(SerializerModel): } mail = TemplateEmailMessage( subject=subject_prefix + context["title"], - to=[f"{notification.user.name} <{notification.user.email}>"], + to=[(notification.user.name, notification.user.email)], language=notification.user.locale(), template_name="email/event_notification.html", template_context=context, @@ -487,7 +507,7 @@ class NotificationTransport(SerializerModel): try: from authentik.stages.email.tasks import send_mail - return send_mail(mail.__dict__) # pylint: disable=no-value-for-parameter + return send_mail(mail.__dict__) except (SMTPException, ConnectionError, OSError) as exc: raise NotificationTransportError(exc) from exc @@ -531,8 +551,12 @@ class Notification(SerializerModel): return NotificationSerializer def __str__(self) -> str: - body_trunc = (self.body[:75] + "..") if len(self.body) > 75 else self.body - return f"Notification for user {self.user}: {body_trunc}" + body_trunc = ( + (self.body[:NOTIFICATION_SUMMARY_LENGTH] + "..") + if len(self.body) > NOTIFICATION_SUMMARY_LENGTH + else self.body + ) + return f"Notification for user {self.user_id}: {body_trunc}" class Meta: verbose_name = _("Notification") @@ -618,8 +642,9 @@ class SystemTask(SerializerModel, ExpiringModel): name = models.TextField() uid = models.TextField(null=True) - start_timestamp = models.FloatField() - finish_timestamp = models.FloatField() + start_timestamp = models.DateTimeField(default=now) + finish_timestamp = models.DateTimeField(default=now) + duration = models.FloatField(default=0) status = models.TextField(choices=TaskStatus.choices) @@ -639,15 +664,20 @@ class SystemTask(SerializerModel, ExpiringModel): def update_metrics(self): """Update prometheus metrics""" - duration = max(self.finish_timestamp - self.start_timestamp, 0) # TODO: Deprecated metric - remove in 2024.2 or later GAUGE_TASKS.labels( + tenant=connection.schema_name, task_name=self.name, task_uid=self.uid or "", status=self.status.lower(), - ).set(duration) - SYSTEM_TASK_TIME.observe(duration) + ).set(self.duration) + SYSTEM_TASK_TIME.labels( + tenant=connection.schema_name, + task_name=self.name, + task_uid=self.uid or "", + ).observe(self.duration) SYSTEM_TASK_STATUS.labels( + tenant=connection.schema_name, task_name=self.name, task_uid=self.uid or "", status=self.status.lower(), diff --git a/authentik/events/settings.py b/authentik/events/settings.py index 4e41e3953f..5fc978ef27 100644 --- a/authentik/events/settings.py +++ b/authentik/events/settings.py @@ -1,4 +1,5 @@ """Event Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/events/signals.py b/authentik/events/signals.py index ff1fb91d23..160cb219f3 100644 --- a/authentik/events/signals.py +++ b/authentik/events/signals.py @@ -1,5 +1,6 @@ """authentik events signal listener""" -from typing import Any, Optional + +from typing import Any from django.contrib.auth.signals import user_logged_in, user_logged_out from django.db.models.signals import post_save, pre_delete @@ -41,7 +42,7 @@ def on_user_logged_in(sender, request: HttpRequest, user: User, **_): request.session[SESSION_LOGIN_EVENT] = event -def get_login_event(request: HttpRequest) -> Optional[Event]: +def get_login_event(request: HttpRequest) -> Event | None: """Wrapper to get login event that can be mocked in tests""" return request.session.get(SESSION_LOGIN_EVENT, None) @@ -70,7 +71,7 @@ def on_login_failed( sender, credentials: dict[str, str], request: HttpRequest, - stage: Optional[Stage] = None, + stage: Stage | None = None, **kwargs, ): """Failed Login, authentik custom event""" diff --git a/authentik/events/system_tasks.py b/authentik/events/system_tasks.py index 6d36c81161..ebaf81abd8 100644 --- a/authentik/events/system_tasks.py +++ b/authentik/events/system_tasks.py @@ -1,36 +1,40 @@ """Monitored tasks""" -from datetime import timedelta -from timeit import default_timer -from typing import Any, Optional + +from datetime import datetime, timedelta +from time import perf_counter +from typing import Any from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ -from structlog.stdlib import get_logger +from structlog.stdlib import BoundLogger, get_logger from tenant_schemas_celery.task import TenantTask -from authentik.events.models import Event, EventAction +from authentik.events.logs import LogEvent +from authentik.events.models import Event, EventAction, TaskStatus from authentik.events.models import SystemTask as DBSystemTask -from authentik.events.models import TaskStatus from authentik.events.utils import sanitize_item from authentik.lib.utils.errors import exception_to_string -LOGGER = get_logger() - class SystemTask(TenantTask): """Task which can save its state to the cache""" + logger: BoundLogger + # For tasks that should only be listed if they failed, set this to False save_on_success: bool - _status: Optional[TaskStatus] - _messages: list[str] + _status: TaskStatus + _messages: list[LogEvent] - _uid: Optional[str] - _start: Optional[float] = None + _uid: str | None + # Precise start time from perf_counter + _start_precise: float | None = None + _start: datetime | None = None def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) + self._status = TaskStatus.SUCCESSFUL self.save_on_success = True self._uid = None self._status = None @@ -41,21 +45,34 @@ class SystemTask(TenantTask): """Set UID, so in the case of an unexpected error its saved correctly""" self._uid = uid - def set_status(self, status: TaskStatus, *messages: str): + def set_status(self, status: TaskStatus, *messages: LogEvent): """Set result for current run, will overwrite previous result.""" self._status = status - self._messages = messages + self._messages = list(messages) + for idx, msg in enumerate(self._messages): + if not isinstance(msg, LogEvent): + self._messages[idx] = LogEvent(msg, logger=self.__name__, log_level="info") def set_error(self, exception: Exception): """Set result to error and save exception""" self._status = TaskStatus.ERROR - self._messages = [exception_to_string(exception)] + self._messages = [ + LogEvent(exception_to_string(exception), logger=self.__name__, log_level="error") + ] def before_start(self, task_id, args, kwargs): - self._start = default_timer() + self._start_precise = perf_counter() + self._start = now() + self.logger = get_logger().bind(task_id=task_id) return super().before_start(task_id, args, kwargs) - # pylint: disable=too-many-arguments + def db(self) -> DBSystemTask | None: + """Get DB object for latest task""" + return DBSystemTask.objects.filter( + name=self.__name__, + uid=self._uid, + ).first() + def after_return(self, status, retval, task_id, args: list[Any], kwargs: dict[str, Any], einfo): super().after_return(status, retval, task_id, args, kwargs, einfo=einfo) if not self._status: @@ -71,12 +88,13 @@ class SystemTask(TenantTask): uid=self._uid, defaults={ "description": self.__doc__, - "start_timestamp": self._start or default_timer(), - "finish_timestamp": default_timer(), + "start_timestamp": self._start or now(), + "finish_timestamp": now(), + "duration": max(perf_counter() - self._start_precise, 0), "task_call_module": self.__module__, "task_call_func": self.__name__, - "task_call_args": args, - "task_call_kwargs": kwargs, + "task_call_args": sanitize_item(args), + "task_call_kwargs": sanitize_item(kwargs), "status": self._status, "messages": sanitize_item(self._messages), "expires": now() + timedelta(hours=self.result_timeout_hours), @@ -84,26 +102,25 @@ class SystemTask(TenantTask): }, ) - # pylint: disable=too-many-arguments def on_failure(self, exc, task_id, args, kwargs, einfo): super().on_failure(exc, task_id, args, kwargs, einfo=einfo) if not self._status: - self._status = TaskStatus.ERROR - self._messages = exception_to_string(exc) + self.set_error(exc) DBSystemTask.objects.update_or_create( name=self.__name__, uid=self._uid, defaults={ "description": self.__doc__, - "start_timestamp": self._start or default_timer(), - "finish_timestamp": default_timer(), + "start_timestamp": self._start or now(), + "finish_timestamp": now(), + "duration": max(perf_counter() - self._start_precise, 0), "task_call_module": self.__module__, "task_call_func": self.__name__, - "task_call_args": args, - "task_call_kwargs": kwargs, + "task_call_args": sanitize_item(args), + "task_call_kwargs": sanitize_item(kwargs), "status": self._status, "messages": sanitize_item(self._messages), - "expires": now() + timedelta(hours=self.result_timeout_hours), + "expires": now() + timedelta(hours=self.result_timeout_hours + 3), "expiring": True, }, ) @@ -122,11 +139,14 @@ def prefill_task(func): DBSystemTask( name=func.__name__, description=func.__doc__, + start_timestamp=now(), + finish_timestamp=now(), status=TaskStatus.UNKNOWN, messages=sanitize_item([_("Task has not been run yet.")]), task_call_module=func.__module__, task_call_func=func.__name__, expiring=False, + duration=0, ) ) return func diff --git a/authentik/events/tasks.py b/authentik/events/tasks.py index c896238080..0989dc8b5d 100644 --- a/authentik/events/tasks.py +++ b/authentik/events/tasks.py @@ -1,11 +1,10 @@ """Event notification tasks""" -from typing import Optional from django.db.models.query_utils import Q from guardian.shortcuts import get_anonymous_user from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.core.models import User from authentik.events.models import ( Event, @@ -37,7 +36,7 @@ def event_trigger_handler(event_uuid: str, trigger_name: str): if not event: LOGGER.warning("event doesn't exist yet or anymore", event_uuid=event_uuid) return - trigger: Optional[NotificationRule] = NotificationRule.objects.filter(name=trigger_name).first() + trigger: NotificationRule | None = NotificationRule.objects.filter(name=trigger_name).first() if not trigger: return diff --git a/authentik/events/tests/test_api.py b/authentik/events/tests/test_api.py index 98df7bc695..51028c8a8f 100644 --- a/authentik/events/tests/test_api.py +++ b/authentik/events/tests/test_api.py @@ -1,4 +1,5 @@ """Event API tests""" + from json import loads from django.urls import reverse diff --git a/authentik/events/tests/test_enrich_asn.py b/authentik/events/tests/test_enrich_asn.py index 2844c45919..185a60632e 100644 --- a/authentik/events/tests/test_enrich_asn.py +++ b/authentik/events/tests/test_enrich_asn.py @@ -1,4 +1,5 @@ """Test ASN Wrapper""" + from django.test import TestCase from authentik.events.context_processors.asn import ASNContextProcessor diff --git a/authentik/events/tests/test_enrich_geoip.py b/authentik/events/tests/test_enrich_geoip.py index 5317901a4f..83a8391558 100644 --- a/authentik/events/tests/test_enrich_geoip.py +++ b/authentik/events/tests/test_enrich_geoip.py @@ -1,4 +1,5 @@ """Test GeoIP Wrapper""" + from django.test import TestCase from authentik.events.context_processors.geoip import GeoIPContextProcessor diff --git a/authentik/events/tests/test_event.py b/authentik/events/tests/test_event.py index f9392014df..b40aad7be7 100644 --- a/authentik/events/tests/test_event.py +++ b/authentik/events/tests/test_event.py @@ -1,4 +1,5 @@ """event tests""" + from urllib.parse import urlencode from django.contrib.contenttypes.models import ContentType @@ -104,7 +105,7 @@ class TestEvents(TestCase): # Test brand request = self.factory.get("/") brand = Brand(domain="test-brand") - setattr(request, "brand", brand) + request.brand = brand event = Event.new("unittest").from_http(request) self.assertEqual( event.brand, diff --git a/authentik/events/tests/test_middleware.py b/authentik/events/tests/test_middleware.py index 1bd667d06e..a5d721a4f0 100644 --- a/authentik/events/tests/test_middleware.py +++ b/authentik/events/tests/test_middleware.py @@ -3,9 +3,11 @@ from django.urls import reverse from rest_framework.test import APITestCase -from authentik.core.models import Application +from authentik.core.models import Application, Token, TokenIntents from authentik.core.tests.utils import create_test_admin_user +from authentik.events.middleware import audit_ignore, audit_overwrite_user from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id class TestEventsMiddleware(APITestCase): @@ -15,35 +17,100 @@ class TestEventsMiddleware(APITestCase): super().setUp() self.user = create_test_admin_user() self.client.force_login(self.user) + Event.objects.all().delete() def test_create(self): """Test model creation event""" + uid = generate_id() self.client.post( reverse("authentik_api:application-list"), - data={"name": "test-create", "slug": "test-create"}, - ) - self.assertTrue(Application.objects.filter(name="test-create").exists()) - self.assertTrue( - Event.objects.filter( - action=EventAction.MODEL_CREATED, - context__model__model_name="application", - context__model__app="authentik_core", - context__model__name="test-create", - ).exists() + data={"name": uid, "slug": uid}, ) + self.assertTrue(Application.objects.filter(name=uid).exists()) + event = Event.objects.filter( + action=EventAction.MODEL_CREATED, + context__model__model_name="application", + context__model__app="authentik_core", + context__model__name=uid, + ).first() + self.assertIsNotNone(event) def test_delete(self): """Test model creation event""" - Application.objects.create(name="test-delete", slug="test-delete") - self.client.delete( - reverse("authentik_api:application-detail", kwargs={"slug": "test-delete"}) - ) + uid = generate_id() + Application.objects.create(name=uid, slug=uid) + self.client.delete(reverse("authentik_api:application-detail", kwargs={"slug": uid})) self.assertFalse(Application.objects.filter(name="test").exists()) self.assertTrue( Event.objects.filter( action=EventAction.MODEL_DELETED, context__model__model_name="application", context__model__app="authentik_core", - context__model__name="test-delete", + context__model__name=uid, ).exists() ) + + def test_audit_ignore(self): + """Test audit_ignore context manager""" + uid = generate_id() + with audit_ignore(): + self.client.post( + reverse("authentik_api:application-list"), + data={"name": uid, "slug": uid}, + ) + self.assertTrue(Application.objects.filter(name=uid).exists()) + self.assertFalse( + Event.objects.filter( + action=EventAction.MODEL_CREATED, + context__model__model_name="application", + context__model__app="authentik_core", + context__model__name=uid, + ).exists() + ) + + def test_audit_overwrite_user(self): + """Test audit_overwrite_user context manager""" + uid = generate_id() + new_user = create_test_admin_user() + with audit_overwrite_user(new_user): + self.client.post( + reverse("authentik_api:application-list"), + data={"name": uid, "slug": uid}, + ) + self.assertTrue(Application.objects.filter(name=uid).exists()) + self.assertTrue( + Event.objects.filter( + action=EventAction.MODEL_CREATED, + context__model__model_name="application", + context__model__app="authentik_core", + context__model__name=uid, + user__username=new_user.username, + ).exists() + ) + + def test_create_with_api(self): + """Test model creation event (with API token auth)""" + self.client.logout() + token = Token.objects.create(user=self.user, intent=TokenIntents.INTENT_API, expiring=False) + uid = generate_id() + self.client.post( + reverse("authentik_api:application-list"), + data={"name": uid, "slug": uid}, + HTTP_AUTHORIZATION=f"Bearer {token.key}", + ) + self.assertTrue(Application.objects.filter(name=uid).exists()) + event = Event.objects.filter( + action=EventAction.MODEL_CREATED, + context__model__model_name="application", + context__model__app="authentik_core", + context__model__name=uid, + ).first() + self.assertIsNotNone(event) + self.assertEqual( + event.user, + { + "pk": self.user.pk, + "email": self.user.email, + "username": self.user.username, + }, + ) diff --git a/authentik/events/tests/test_models.py b/authentik/events/tests/test_models.py new file mode 100644 index 0000000000..9be7b8b392 --- /dev/null +++ b/authentik/events/tests/test_models.py @@ -0,0 +1,35 @@ +"""authentik event models tests""" + +from collections.abc import Callable + +from django.db.models import Model +from django.test import TestCase + +from authentik.core.models import default_token_key +from authentik.lib.utils.reflection import get_apps + + +class TestModels(TestCase): + """Test Models""" + + +def model_tester_factory(test_model: type[Model]) -> Callable: + """Test models' __str__ and __repr__""" + + def tester(self: TestModels): + allowed = 0 + # Token-like objects need to lookup the current tenant to get the default token length + for field in test_model._meta.fields: + if field.default == default_token_key: + allowed += 1 + with self.assertNumQueries(allowed): + str(test_model()) + with self.assertNumQueries(allowed): + repr(test_model()) + + return tester + + +for app in get_apps(): + for model in app.get_models(): + setattr(TestModels, f"test_{app.label}_{model.__name__}", model_tester_factory(model)) diff --git a/authentik/events/tests/test_tasks.py b/authentik/events/tests/test_tasks.py index 0e3a3cd5d6..353c11b07f 100644 --- a/authentik/events/tests/test_tasks.py +++ b/authentik/events/tests/test_tasks.py @@ -1,4 +1,5 @@ """Test Monitored tasks""" + from json import loads from django.urls import reverse diff --git a/authentik/events/tests/test_transports.py b/authentik/events/tests/test_transports.py index 3633f1ed5c..23ea924376 100644 --- a/authentik/events/tests/test_transports.py +++ b/authentik/events/tests/test_transports.py @@ -1,4 +1,5 @@ """transport tests""" + from unittest.mock import PropertyMock, patch from django.core import mail diff --git a/authentik/events/urls.py b/authentik/events/urls.py index 523435819d..0beea59913 100644 --- a/authentik/events/urls.py +++ b/authentik/events/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.events.api.events import EventViewSet from authentik.events.api.notification_mappings import NotificationWebhookMappingViewSet from authentik.events.api.notification_rules import NotificationRuleViewSet diff --git a/authentik/events/utils.py b/authentik/events/utils.py index c0888375a1..ab1778f446 100644 --- a/authentik/events/utils.py +++ b/authentik/events/utils.py @@ -1,4 +1,5 @@ """event utilities""" + import re from copy import copy from dataclasses import asdict, is_dataclass @@ -6,7 +7,7 @@ from datetime import date, datetime, time, timedelta from enum import Enum from pathlib import Path from types import GeneratorType, NoneType -from typing import Any, Optional +from typing import Any from uuid import UUID from django.contrib.auth.models import AnonymousUser @@ -36,7 +37,7 @@ def cleanse_item(key: str, value: Any) -> Any: """Cleanse a single item""" if isinstance(value, dict): return cleanse_dict(value) - if isinstance(value, (list, tuple, set)): + if isinstance(value, list | tuple | set): for idx, item in enumerate(value): value[idx] = cleanse_item(key, item) return value @@ -73,7 +74,7 @@ def model_to_dict(model: Model) -> dict[str, Any]: } -def get_user(user: User | AnonymousUser, original_user: Optional[User] = None) -> dict[str, Any]: +def get_user(user: User | AnonymousUser, original_user: User | None = None) -> dict[str, Any]: """Convert user object to dictionary, optionally including the original user""" if isinstance(user, AnonymousUser): try: @@ -94,8 +95,7 @@ def get_user(user: User | AnonymousUser, original_user: Optional[User] = None) - return user_data -# pylint: disable=too-many-return-statements,too-many-branches -def sanitize_item(value: Any) -> Any: +def sanitize_item(value: Any) -> Any: # noqa: PLR0911, PLR0912 """Sanitize a single item, ensure it is JSON parsable""" if is_dataclass(value): # Because asdict calls `copy.deepcopy(obj)` on everything that's not tuple/dict, @@ -114,20 +114,20 @@ def sanitize_item(value: Any) -> Any: return sanitize_dict(value) if isinstance(value, GeneratorType): return sanitize_item(list(value)) - if isinstance(value, (list, tuple, set)): + if isinstance(value, list | tuple | set): new_values = [] for item in value: new_value = sanitize_item(item) if new_value: new_values.append(new_value) return new_values - if isinstance(value, (User, AnonymousUser)): + if isinstance(value, User | AnonymousUser): return sanitize_dict(get_user(value)) if isinstance(value, models.Model): return sanitize_dict(model_to_dict(value)) if isinstance(value, UUID): return value.hex - if isinstance(value, (HttpRequest, WSGIRequest)): + if isinstance(value, HttpRequest | WSGIRequest): return ... if isinstance(value, City): return GEOIP_CONTEXT_PROCESSOR.city_to_dict(value) @@ -170,7 +170,7 @@ def sanitize_item(value: Any) -> Any: "module": value.__module__, } # List taken from the stdlib's JSON encoder (_make_iterencode, encoder.py:415) - if isinstance(value, (bool, int, float, NoneType, list, tuple, dict)): + if isinstance(value, bool | int | float | NoneType | list | tuple | dict): return value try: return DjangoJSONEncoder().default(value) diff --git a/authentik/flows/api/bindings.py b/authentik/flows/api/bindings.py index 96e2e46629..7aa6098bce 100644 --- a/authentik/flows/api/bindings.py +++ b/authentik/flows/api/bindings.py @@ -1,4 +1,5 @@ """Flow Binding API Views""" + from typing import Any from rest_framework.exceptions import ValidationError @@ -46,3 +47,4 @@ class FlowStageBindingViewSet(UsedByMixin, ModelViewSet): filterset_fields = "__all__" search_fields = ["stage__name"] ordering = ["order"] + ordering_fields = ["order", "stage__name"] diff --git a/authentik/flows/api/flows.py b/authentik/flows/api/flows.py index 0508b2222b..121b3f8077 100644 --- a/authentik/flows/api/flows.py +++ b/authentik/flows/api/flows.py @@ -1,4 +1,5 @@ """Flow API Views""" + from django.core.cache import cache from django.http import HttpResponse from django.urls import reverse @@ -6,7 +7,7 @@ from django.utils.translation import gettext as _ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework.decorators import action -from rest_framework.fields import BooleanField, CharField, DictField, ListField, ReadOnlyField +from rest_framework.fields import BooleanField, CharField, ReadOnlyField from rest_framework.parsers import MultiPartParser from rest_framework.request import Request from rest_framework.response import Response @@ -14,12 +15,11 @@ from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger -from authentik.api.decorators import permission_required from authentik.blueprints.v1.exporter import FlowExporter from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, Importer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import CacheSerializer, LinkSerializer, PassiveSerializer -from authentik.events.utils import sanitize_dict +from authentik.events.logs import LogEventSerializer from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import Flow @@ -32,6 +32,7 @@ from authentik.lib.utils.file import ( set_file_url, ) from authentik.lib.views import bad_request_message +from authentik.rbac.decorators import permission_required LOGGER = get_logger() @@ -106,7 +107,7 @@ class FlowSetSerializer(FlowSerializer): class FlowImportResultSerializer(PassiveSerializer): """Logs of an attempted flow import""" - logs = ListField(child=DictField(), read_only=True) + logs = LogEventSerializer(many=True, read_only=True) success = BooleanField(read_only=True) @@ -183,7 +184,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet): importer = Importer.from_string(file.read().decode()) valid, logs = importer.validate() - import_response.initial_data["logs"] = [sanitize_dict(log) for log in logs] + import_response.initial_data["logs"] = [LogEventSerializer(log).data for log in logs] import_response.initial_data["success"] = valid import_response.is_valid() if not valid: @@ -292,8 +293,9 @@ class FlowViewSet(UsedByMixin, ModelViewSet): return bad_request_message( request, _( - "Flow not applicable to current user/request: %(messages)s" - % {"messages": exc.messages} + "Flow not applicable to current user/request: {messages}".format_map( + {"messages": exc.messages} + ) ), ) return Response( diff --git a/authentik/flows/api/flows_diagram.py b/authentik/flows/api/flows_diagram.py index ab75fa2355..784eeed8f3 100644 --- a/authentik/flows/api/flows_diagram.py +++ b/authentik/flows/api/flows_diagram.py @@ -1,6 +1,6 @@ """Flows Diagram API""" + from dataclasses import dataclass, field -from typing import Optional from django.utils.translation import gettext as _ from guardian.shortcuts import get_objects_for_user @@ -17,8 +17,8 @@ class DiagramElement: identifier: str description: str - action: Optional[str] = None - source: Optional[list["DiagramElement"]] = None + action: str | None = None + source: list["DiagramElement"] | None = None style: list[str] = field(default_factory=lambda: ["[", "]"]) @@ -65,10 +65,10 @@ class FlowDiagram: ): element = DiagramElement( f"flow_policy_{p_index}", - _("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name}) + _("Policy ({type})".format_map({"type": policy_binding.policy._meta.verbose_name})) + "\n" + policy_binding.policy.name, - _("Binding %(order)d" % {"order": policy_binding.order}), + _("Binding {order}".format_map({"order": policy_binding.order})), parent_elements, style=["{{", "}}"], ) @@ -91,7 +91,7 @@ class FlowDiagram: ): element = DiagramElement( f"stage_{stage_index}_policy_{p_index}", - _("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name}) + _("Policy ({type})".format_map({"type": policy_binding.policy._meta.verbose_name})) + "\n" + policy_binding.policy.name, "", @@ -119,7 +119,7 @@ class FlowDiagram: element = DiagramElement( f"stage_{s_index}", - _("Stage (%(type)s)" % {"type": stage_binding.stage._meta.verbose_name}) + _("Stage ({type})".format_map({"type": stage_binding.stage._meta.verbose_name})) + "\n" + stage_binding.stage.name, action, diff --git a/authentik/flows/api/stages.py b/authentik/flows/api/stages.py index 6f0d6e4ac5..a4973a62ec 100644 --- a/authentik/flows/api/stages.py +++ b/authentik/flows/api/stages.py @@ -1,4 +1,5 @@ """Flow Stage API Views""" + from django.urls.base import reverse from drf_spectacular.utils import extend_schema from rest_framework import mixins @@ -9,8 +10,9 @@ from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer +from authentik.core.api.utils import MetaNameSerializer from authentik.core.types import UserSettingSerializer from authentik.flows.api.flows import FlowSetSerializer from authentik.flows.models import ConfigurableStage, Stage @@ -45,6 +47,7 @@ class StageSerializer(ModelSerializer, MetaNameSerializer): class StageViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -61,24 +64,6 @@ class StageViewSet( def get_queryset(self): # pragma: no cover return Stage.objects.select_subclasses().prefetch_related("flow_set") - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable stage types""" - data = [] - for subclass in all_subclasses(self.queryset.model, False): - subclass: Stage - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": subclass().component, - "model_name": subclass._meta.model_name, - } - ) - data = sorted(data, key=lambda x: x["name"]) - return Response(TypeCreateSerializer(data, many=True).data) - @extend_schema(responses={200: UserSettingSerializer(many=True)}) @action(detail=False, pagination_class=None, filter_backends=[]) def user_settings(self, request: Request) -> Response: diff --git a/authentik/flows/apps.py b/authentik/flows/apps.py index b901160a86..95f50f735d 100644 --- a/authentik/flows/apps.py +++ b/authentik/flows/apps.py @@ -1,4 +1,5 @@ """authentik flows app config""" + from prometheus_client import Gauge, Histogram from authentik.blueprints.apps import ManagedAppConfig @@ -30,13 +31,9 @@ class AuthentikFlowsConfig(ManagedAppConfig): verbose_name = "authentik Flows" default = True - def reconcile_global_load_flows_signals(self): - """Load flows signals""" - self.import_module("authentik.flows.signals") - - def reconcile_global_load_stages(self): - """Ensure all stages are loaded""" + def import_related(self): from authentik.flows.models import Stage for stage in all_subclasses(Stage): - _ = stage().type + _ = stage().view + return super().import_related() diff --git a/authentik/flows/challenge.py b/authentik/flows/challenge.py index eb968ce791..03d6b5b819 100644 --- a/authentik/flows/challenge.py +++ b/authentik/flows/challenge.py @@ -1,4 +1,5 @@ """Challenge helpers""" + from dataclasses import asdict, is_dataclass from enum import Enum from typing import TYPE_CHECKING, Optional, TypedDict @@ -103,7 +104,7 @@ class FlowErrorChallenge(Challenge): error = CharField(required=False) traceback = CharField(required=False) - def __init__(self, request: Optional[Request] = None, error: Optional[Exception] = None): + def __init__(self, request: Request | None = None, error: Exception | None = None): super().__init__(data={}) if not request or not error: return diff --git a/authentik/flows/exceptions.py b/authentik/flows/exceptions.py index 7f903633e9..81b9793507 100644 --- a/authentik/flows/exceptions.py +++ b/authentik/flows/exceptions.py @@ -1,5 +1,4 @@ """flow exceptions""" -from typing import Optional from django.utils.translation import gettext_lazy as _ @@ -10,7 +9,7 @@ from authentik.policies.types import PolicyResult class FlowNonApplicableException(SentryIgnoredException): """Flow does not apply to current user (denied by policy, or otherwise).""" - policy_result: Optional[PolicyResult] = None + policy_result: PolicyResult | None = None @property def messages(self) -> str: diff --git a/authentik/flows/management/commands/benchmark.py b/authentik/flows/management/commands/benchmark.py index 66e27a9cbe..cab0f105e3 100644 --- a/authentik/flows/management/commands/benchmark.py +++ b/authentik/flows/management/commands/benchmark.py @@ -1,4 +1,5 @@ """authentik benchmark command""" + from csv import DictWriter from multiprocessing import Manager, cpu_count, get_context from sys import stdout diff --git a/authentik/flows/markers.py b/authentik/flows/markers.py index e59333e685..ac5509c958 100644 --- a/authentik/flows/markers.py +++ b/authentik/flows/markers.py @@ -1,6 +1,7 @@ """Stage Markers""" + from dataclasses import dataclass -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING from django.http.request import HttpRequest from structlog.stdlib import get_logger @@ -24,7 +25,7 @@ class StageMarker: plan: "FlowPlan", binding: FlowStageBinding, http_request: HttpRequest, - ) -> Optional[FlowStageBinding]: + ) -> FlowStageBinding | None: """Process callback for this marker. This should be overridden by sub-classes. If a stage should be removed, return None.""" return binding @@ -41,7 +42,7 @@ class ReevaluateMarker(StageMarker): plan: "FlowPlan", binding: FlowStageBinding, http_request: HttpRequest, - ) -> Optional[FlowStageBinding]: + ) -> FlowStageBinding | None: """Re-evaluate policies bound to stage, and if they fail, remove from plan""" from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER diff --git a/authentik/flows/migrations/0027_auto_20231028_1424.py b/authentik/flows/migrations/0027_auto_20231028_1424.py index 70784e6e37..49894c669d 100644 --- a/authentik/flows/migrations/0027_auto_20231028_1424.py +++ b/authentik/flows/migrations/0027_auto_20231028_1424.py @@ -16,7 +16,7 @@ def set_oobe_flow_authentication(apps: Apps, schema_editor: BaseDatabaseSchemaEd users = User.objects.using(db_alias).exclude(username="akadmin") try: users = users.exclude(pk=get_anonymous_user().pk) - # pylint: disable=broad-except + except Exception: # nosec pass diff --git a/authentik/flows/models.py b/authentik/flows/models.py index 7ed7448247..f34b0e3472 100644 --- a/authentik/flows/models.py +++ b/authentik/flows/models.py @@ -1,7 +1,8 @@ """Flow models""" + from base64 import b64decode, b64encode from pickle import dumps, loads # nosec -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING from uuid import uuid4 from django.db import models @@ -82,7 +83,7 @@ class Stage(SerializerModel): objects = InheritanceManager() @property - def type(self) -> type["StageView"]: + def view(self) -> type["StageView"]: """Return StageView class that implements logic for this stage""" # This is a bit of a workaround, since we can't set class methods with setattr if hasattr(self, "__in_memory_type"): @@ -94,7 +95,7 @@ class Stage(SerializerModel): """Return component used to edit this object""" raise NotImplementedError - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: """Entrypoint to integrate with User settings. Can either return None if no user settings are available, or a challenge.""" return None @@ -112,8 +113,8 @@ def in_memory_stage(view: type["StageView"], **kwargs) -> Stage: # we set the view as a separate property and reference a generic function # that returns that member setattr(stage, "__in_memory_type", view) - setattr(stage, "name", _("Dynamic In-memory stage: %(doc)s" % {"doc": view.__doc__})) - setattr(stage._meta, "verbose_name", class_to_path(view)) + stage.name = _("Dynamic In-memory stage: {doc}".format_map({"doc": view.__doc__})) + stage._meta.verbose_name = class_to_path(view) for key, value in kwargs.items(): setattr(stage, key, value) return stage diff --git a/authentik/flows/planner.py b/authentik/flows/planner.py index a74c432756..5e9e3b0d33 100644 --- a/authentik/flows/planner.py +++ b/authentik/flows/planner.py @@ -1,6 +1,7 @@ """Flows Planner""" + from dataclasses import dataclass, field -from typing import Any, Optional +from typing import Any from django.core.cache import cache from django.http import HttpRequest @@ -38,7 +39,7 @@ CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_flows") CACHE_PREFIX = "goauthentik.io/flows/planner/" -def cache_key(flow: Flow, user: Optional[User] = None) -> str: +def cache_key(flow: Flow, user: User | None = None) -> str: """Generate Cache key for flow""" prefix = CACHE_PREFIX + str(flow.pk) if user: @@ -57,16 +58,16 @@ class FlowPlan: context: dict[str, Any] = field(default_factory=dict) markers: list[StageMarker] = field(default_factory=list) - def append_stage(self, stage: Stage, marker: Optional[StageMarker] = None): - """Append `stage` to all stages, optionally with stage marker""" + def append_stage(self, stage: Stage, marker: StageMarker | None = None): + """Append `stage` to the end of the plan, optionally with stage marker""" return self.append(FlowStageBinding(stage=stage), marker) - def append(self, binding: FlowStageBinding, marker: Optional[StageMarker] = None): - """Append `stage` to all stages, optionally with stage marker""" + def append(self, binding: FlowStageBinding, marker: StageMarker | None = None): + """Append `stage` to the end of the plan, optionally with stage marker""" self.bindings.append(binding) self.markers.append(marker or StageMarker()) - def insert_stage(self, stage: Stage, marker: Optional[StageMarker] = None): + def insert_stage(self, stage: Stage, marker: StageMarker | None = None): """Insert stage into plan, as immediate next stage""" self.bindings.insert(1, FlowStageBinding(stage=stage, order=0)) self.markers.insert(1, marker or StageMarker()) @@ -77,7 +78,7 @@ class FlowPlan: self.insert_stage(in_memory_stage(RedirectStage, destination=destination)) - def next(self, http_request: Optional[HttpRequest]) -> Optional[FlowStageBinding]: + def next(self, http_request: HttpRequest | None) -> FlowStageBinding | None: """Return next pending stage from the bottom of the list""" if not self.has_stages: return None @@ -93,7 +94,7 @@ class FlowPlan: self.markers.remove(marker) if not self.has_stages: return None - # pylint: disable=not-callable + return self.next(http_request) return marked_stage @@ -147,9 +148,7 @@ class FlowPlanner: if not outpost_user: raise FlowNonApplicableException() - def plan( - self, request: HttpRequest, default_context: Optional[dict[str, Any]] = None - ) -> FlowPlan: + def plan(self, request: HttpRequest, default_context: dict[str, Any] | None = None) -> FlowPlan: """Check each of the flows' policies, check policies for each stage with PolicyBinding and return ordered list""" with Hub.current.start_span( @@ -204,7 +203,8 @@ class FlowPlanner: "f(plan): building plan", ) plan = self._build_plan(user, request, default_context) - cache.set(cache_key(self.flow, user), plan, CACHE_TIMEOUT) + if self.use_cache: + cache.set(cache_key(self.flow, user), plan, CACHE_TIMEOUT) if not plan.bindings and not self.allow_empty_flows: raise EmptyFlowException() return plan @@ -213,7 +213,7 @@ class FlowPlanner: self, user: User, request: HttpRequest, - default_context: Optional[dict[str, Any]], + default_context: dict[str, Any] | None, ) -> FlowPlan: """Build flow plan by checking each stage in their respective order and checking the applied policies""" diff --git a/authentik/flows/signals.py b/authentik/flows/signals.py index af645fa7e9..4ceda51520 100644 --- a/authentik/flows/signals.py +++ b/authentik/flows/signals.py @@ -1,4 +1,5 @@ """authentik flow signals""" + from django.core.cache import cache from django.db import connection from django.db.models.signals import post_save, pre_delete diff --git a/authentik/flows/stage.py b/authentik/flows/stage.py index 528a7bef59..b12838e96d 100644 --- a/authentik/flows/stage.py +++ b/authentik/flows/stage.py @@ -1,5 +1,6 @@ """authentik stage Base view""" -from typing import TYPE_CHECKING, Optional + +from typing import TYPE_CHECKING from django.contrib.auth.models import AnonymousUser from django.http import HttpRequest @@ -26,7 +27,7 @@ from authentik.flows.challenge import ( from authentik.flows.exceptions import StageInvalidException from authentik.flows.models import InvalidResponseAction from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER -from authentik.lib.avatars import DEFAULT_AVATAR +from authentik.lib.avatars import DEFAULT_AVATAR, get_avatar from authentik.lib.utils.reflection import class_to_path if TYPE_CHECKING: @@ -152,7 +153,7 @@ class ChallengeStageView(StageView): "app": self.executor.plan.context.get(PLAN_CONTEXT_APPLICATION, ""), "user": self.get_pending_user(for_display=True), } - # pylint: disable=broad-except + except Exception as exc: self.logger.warning("failed to template title", exc=exc) return self.executor.flow.title @@ -197,7 +198,7 @@ class ChallengeStageView(StageView): challenge.initial_data["pending_user"] = user.username challenge.initial_data["pending_user_avatar"] = DEFAULT_AVATAR if not isinstance(user, AnonymousUser): - challenge.initial_data["pending_user_avatar"] = user.avatar + challenge.initial_data["pending_user_avatar"] = get_avatar(user, self.request) return challenge def get_challenge(self, *args, **kwargs) -> Challenge: @@ -233,9 +234,9 @@ class ChallengeStageView(StageView): class AccessDeniedChallengeView(ChallengeStageView): """Used internally by FlowExecutor's stage_invalid()""" - error_message: Optional[str] + error_message: str | None - def __init__(self, executor: "FlowExecutorView", error_message: Optional[str] = None, **kwargs): + def __init__(self, executor: "FlowExecutorView", error_message: str | None = None, **kwargs): super().__init__(executor, **kwargs) self.error_message = error_message diff --git a/authentik/flows/tests/__init__.py b/authentik/flows/tests/__init__.py index bd7d8dc888..f846563b04 100644 --- a/authentik/flows/tests/__init__.py +++ b/authentik/flows/tests/__init__.py @@ -1,6 +1,7 @@ """Test helpers""" + from json import loads -from typing import Any, Optional +from typing import Any from django.http.response import HttpResponse from django.urls.base import reverse @@ -14,12 +15,11 @@ from authentik.flows.models import Flow class FlowTestCase(APITestCase): """Helpers for testing flows and stages.""" - # pylint: disable=invalid-name def assertStageResponse( self, response: HttpResponse, - flow: Optional[Flow] = None, - user: Optional[User] = None, + flow: Flow | None = None, + user: User | None = None, **kwargs, ) -> dict[str, Any]: """Assert various attributes of a stage response""" @@ -44,7 +44,6 @@ class FlowTestCase(APITestCase): self.assertEqual(raw_response[key], expected) return raw_response - # pylint: disable=invalid-name def assertStageRedirects(self, response: HttpResponse, to: str) -> dict[str, Any]: """Wrapper around assertStageResponse that checks for a redirect""" return self.assertStageResponse( diff --git a/authentik/flows/tests/test_api.py b/authentik/flows/tests/test_api.py index 3de7dd3f07..0e5adba432 100644 --- a/authentik/flows/tests/test_api.py +++ b/authentik/flows/tests/test_api.py @@ -1,10 +1,12 @@ """API flow tests""" + from django.urls import reverse from rest_framework.test import APITestCase from authentik.core.tests.utils import create_test_admin_user from authentik.flows.api.stages import StageSerializer, StageViewSet from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage +from authentik.lib.generators import generate_id from authentik.policies.dummy.models import DummyPolicy from authentik.policies.models import PolicyBinding from authentik.stages.dummy.models import DummyStage @@ -100,3 +102,21 @@ class TestFlowsAPI(APITestCase): reverse("authentik_api:stage-types"), ) self.assertEqual(response.status_code, 200) + + def test_execute(self): + """Test execute endpoint""" + user = create_test_admin_user() + self.client.force_login(user) + + flow = Flow.objects.create( + name=generate_id(), + slug=generate_id(), + designation=FlowDesignation.AUTHENTICATION, + ) + FlowStageBinding.objects.create( + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 + ) + response = self.client.get( + reverse("authentik_api:flow-execute", kwargs={"slug": flow.slug}) + ) + self.assertEqual(response.status_code, 200) diff --git a/authentik/flows/tests/test_challenges.py b/authentik/flows/tests/test_challenges.py index 4651e6ff80..fe1a6c288f 100644 --- a/authentik/flows/tests/test_challenges.py +++ b/authentik/flows/tests/test_challenges.py @@ -1,4 +1,5 @@ """flow views tests""" + from django.test import TestCase from authentik.flows.challenge import AutosubmitChallenge, ChallengeTypes diff --git a/authentik/flows/tests/test_executor.py b/authentik/flows/tests/test_executor.py index dfca805171..894a3ae7b2 100644 --- a/authentik/flows/tests/test_executor.py +++ b/authentik/flows/tests/test_executor.py @@ -1,5 +1,7 @@ """flow views tests""" + from unittest.mock import MagicMock, PropertyMock, patch +from urllib.parse import urlencode from django.http import HttpRequest, HttpResponse from django.test.client import RequestFactory @@ -17,7 +19,12 @@ from authentik.flows.models import ( from authentik.flows.planner import FlowPlan, FlowPlanner from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageView from authentik.flows.tests import FlowTestCase -from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_PLAN, FlowExecutorView +from authentik.flows.views.executor import ( + NEXT_ARG_NAME, + QS_QUERY, + SESSION_KEY_PLAN, + FlowExecutorView, +) from authentik.lib.generators import generate_id from authentik.policies.dummy.models import DummyPolicy from authentik.policies.models import PolicyBinding @@ -120,16 +127,73 @@ class TestFlowExecutor(FlowTestCase): TO_STAGE_RESPONSE_MOCK, ) def test_invalid_flow_redirect(self): - """Tests that an invalid flow still redirects""" + """Test invalid flow with valid redirect destination""" flow = create_test_flow( FlowDesignation.AUTHENTICATION, ) dest = "/unique-string" url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) - response = self.client.get(url + f"?{NEXT_ARG_NAME}={dest}") + response = self.client.get(url + f"?{QS_QUERY}={urlencode({NEXT_ARG_NAME: dest})}") self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, reverse("authentik_core:root-redirect")) + self.assertEqual(response.url, "/unique-string") + + @patch( + "authentik.flows.views.executor.to_stage_response", + TO_STAGE_RESPONSE_MOCK, + ) + def test_invalid_flow_invalid_redirect(self): + """Test invalid flow redirect with an invalid URL""" + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + + dest = "http://something.example.com/unique-string" + url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) + + response = self.client.get(url + f"?{QS_QUERY}={urlencode({NEXT_ARG_NAME: dest})}") + self.assertEqual(response.status_code, 200) + self.assertStageResponse( + response, + flow, + component="ak-stage-access-denied", + error_message="Invalid next URL", + ) + + @patch( + "authentik.flows.views.executor.to_stage_response", + TO_STAGE_RESPONSE_MOCK, + ) + def test_valid_flow_redirect(self): + """Test valid flow with valid redirect destination""" + flow = create_test_flow() + + dest = "/unique-string" + url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) + + response = self.client.get(url + f"?{QS_QUERY}={urlencode({NEXT_ARG_NAME: dest})}") + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, "/unique-string") + + @patch( + "authentik.flows.views.executor.to_stage_response", + TO_STAGE_RESPONSE_MOCK, + ) + def test_valid_flow_invalid_redirect(self): + """Test valid flow redirect with an invalid URL""" + flow = create_test_flow() + + dest = "http://something.example.com/unique-string" + url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) + + response = self.client.get(url + f"?{QS_QUERY}={urlencode({NEXT_ARG_NAME: dest})}") + self.assertEqual(response.status_code, 200) + self.assertStageResponse( + response, + flow, + component="ak-stage-access-denied", + error_message="Invalid next URL", + ) @patch( "authentik.flows.views.executor.to_stage_response", diff --git a/authentik/flows/tests/test_inspector.py b/authentik/flows/tests/test_inspector.py index 49ba593566..a12054fd37 100644 --- a/authentik/flows/tests/test_inspector.py +++ b/authentik/flows/tests/test_inspector.py @@ -53,6 +53,7 @@ class TestFlowInspector(APITestCase): "title": flow.title, "layout": "stacked", }, + "flow_designation": "authentication", "type": ChallengeTypes.NATIVE.value, "password_fields": False, "primary_action": "Log in", diff --git a/authentik/flows/tests/test_planner.py b/authentik/flows/tests/test_planner.py index f95462dc55..f7352a7cf5 100644 --- a/authentik/flows/tests/test_planner.py +++ b/authentik/flows/tests/test_planner.py @@ -1,4 +1,5 @@ """flow planner tests""" + from unittest.mock import MagicMock, Mock, PropertyMock, patch from django.contrib.auth.models import AnonymousUser diff --git a/authentik/flows/tests/test_stage_model.py b/authentik/flows/tests/test_stage_model.py index 2e1edd54b2..a6bac2a81b 100644 --- a/authentik/flows/tests/test_stage_model.py +++ b/authentik/flows/tests/test_stage_model.py @@ -1,5 +1,6 @@ """base model tests""" -from typing import Callable + +from collections.abc import Callable from django.test import TestCase @@ -21,7 +22,7 @@ def model_tester_factory(test_model: type[Stage]) -> Callable: model_class = test_model.__bases__[0]() else: model_class = test_model() - self.assertTrue(issubclass(model_class.type, StageView)) + self.assertTrue(issubclass(model_class.view, StageView)) self.assertIsNotNone(test_model.component) _ = model_class.ui_user_settings() diff --git a/authentik/flows/tests/test_stage_views.py b/authentik/flows/tests/test_stage_views.py index b116ddac4c..a9ec1e8a4a 100644 --- a/authentik/flows/tests/test_stage_views.py +++ b/authentik/flows/tests/test_stage_views.py @@ -1,5 +1,6 @@ """stage view tests""" -from typing import Callable + +from collections.abc import Callable from django.test import RequestFactory, TestCase diff --git a/authentik/flows/tests/test_views_helper.py b/authentik/flows/tests/test_views_helper.py index 1cf68fec2e..d5a64d84ae 100644 --- a/authentik/flows/tests/test_views_helper.py +++ b/authentik/flows/tests/test_views_helper.py @@ -1,4 +1,5 @@ """flow views tests""" + from django.test import TestCase from django.urls import reverse diff --git a/authentik/flows/urls.py b/authentik/flows/urls.py index 4642df07e6..a256437d46 100644 --- a/authentik/flows/urls.py +++ b/authentik/flows/urls.py @@ -1,4 +1,5 @@ """flow urls""" + from django.urls import path from authentik.flows.api.bindings import FlowStageBindingViewSet diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index 42c762779a..774206c9d3 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -1,6 +1,6 @@ """authentik multi-stage authentication engine""" + from copy import deepcopy -from typing import Optional from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin @@ -11,6 +11,7 @@ from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.urls import reverse from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ from django.views.decorators.clickjacking import xframe_options_sameorigin from django.views.generic import View from drf_spectacular.types import OpenApiTypes @@ -106,8 +107,8 @@ class FlowExecutorView(APIView): flow: Flow - plan: Optional[FlowPlan] = None - current_binding: Optional[FlowStageBinding] = None + plan: FlowPlan | None = None + current_binding: FlowStageBinding | None = None current_stage: Stage current_stage_view: View @@ -135,9 +136,9 @@ class FlowExecutorView(APIView): ) return to_stage_response(self.request, self.stage_invalid(error_message=exc.messages)) - def _check_flow_token(self, key: str) -> Optional[FlowPlan]: + def _check_flow_token(self, key: str) -> FlowPlan | None: """Check if the user is using a flow token to restore a plan""" - token: Optional[FlowToken] = FlowToken.filter_not_expired(key=key).first() + token: FlowToken | None = FlowToken.filter_not_expired(key=key).first() if not token: return None plan = None @@ -153,7 +154,6 @@ class FlowExecutorView(APIView): self._logger.debug("f(exec): restored flow plan from token", plan=plan) return plan - # pylint: disable=too-many-return-statements def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse: with Hub.current.start_span( op="authentik.flow.executor.dispatch", description=self.flow.slug @@ -177,6 +177,8 @@ class FlowExecutorView(APIView): self.cancel() self._logger.debug("f(exec): Continuing existing plan") + # Initial flow request, check if we have an upstream query string passed in + request.session[SESSION_KEY_GET] = get_params # Don't check session again as we've either already loaded the plan or we need to plan if not self.plan: request.session[SESSION_KEY_HISTORY] = [] @@ -191,8 +193,6 @@ class FlowExecutorView(APIView): # To match behaviour with loading an empty flow plan from cache, # we don't show an error message here, but rather call _flow_done() return self._flow_done() - # Initial flow request, check if we have an upstream query string passed in - request.session[SESSION_KEY_GET] = get_params # We don't save the Plan after getting the next stage # as it hasn't been successfully passed yet try: @@ -200,7 +200,7 @@ class FlowExecutorView(APIView): # if the cached plan is from an older version, it might have different attributes # in which case we just delete the plan and invalidate everything next_binding = self.plan.next(self.request) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: self._logger.warning( "f(exec): found incompatible flow plan, invalidating run", exc=exc ) @@ -218,7 +218,7 @@ class FlowExecutorView(APIView): flow_slug=self.flow.slug, ) try: - stage_cls = self.current_stage.type + stage_cls = self.current_stage.view except NotImplementedError as exc: self._logger.debug("Error getting stage type", exc=exc) return self.stage_invalid() @@ -274,19 +274,22 @@ class FlowExecutorView(APIView): stage=self.current_stage, ) try: - with Hub.current.start_span( - op="authentik.flow.executor.stage", - description=class_path, - ) as span, HIST_FLOW_EXECUTION_STAGE_TIME.labels( - method=request.method.upper(), - stage_type=class_path, - ).time(): + with ( + Hub.current.start_span( + op="authentik.flow.executor.stage", + description=class_path, + ) as span, + HIST_FLOW_EXECUTION_STAGE_TIME.labels( + method=request.method.upper(), + stage_type=class_path, + ).time(), + ): span.set_data("Method", request.method.upper()) span.set_data("authentik Stage", self.current_stage_view) span.set_data("authentik Flow", self.flow.slug) stage_response = self.current_stage_view.dispatch(request) return to_stage_response(request, stage_response) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: return self.handle_exception(exc) @extend_schema( @@ -322,19 +325,22 @@ class FlowExecutorView(APIView): stage=self.current_stage, ) try: - with Hub.current.start_span( - op="authentik.flow.executor.stage", - description=class_path, - ) as span, HIST_FLOW_EXECUTION_STAGE_TIME.labels( - method=request.method.upper(), - stage_type=class_path, - ).time(): + with ( + Hub.current.start_span( + op="authentik.flow.executor.stage", + description=class_path, + ) as span, + HIST_FLOW_EXECUTION_STAGE_TIME.labels( + method=request.method.upper(), + stage_type=class_path, + ).time(), + ): span.set_data("Method", request.method.upper()) span.set_data("authentik Stage", self.current_stage_view) span.set_data("authentik Flow", self.flow.slug) stage_response = self.current_stage_view.dispatch(request) return to_stage_response(request, stage_response) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: return self.handle_exception(exc) def _initiate_plan(self) -> FlowPlan: @@ -346,7 +352,7 @@ class FlowExecutorView(APIView): # there are no issues with the class we might've gotten # from the cache. If there are errors, just delete all cached flows _ = plan.has_stages - except Exception: # pylint: disable=broad-except + except Exception: keys = cache.keys(f"{CACHE_PREFIX}*") cache.delete_many(keys) return self._initiate_plan() @@ -385,7 +391,11 @@ class FlowExecutorView(APIView): NEXT_ARG_NAME, "authentik_core:root-redirect" ) self.cancel() - return to_stage_response(self.request, redirect_with_qs(next_param)) + if next_param and not is_url_absolute(next_param): + return to_stage_response(self.request, redirect_with_qs(next_param)) + return to_stage_response( + self.request, self.stage_invalid(error_message=_("Invalid next URL")) + ) def stage_ok(self) -> HttpResponse: """Callback called by stages upon successful completion. @@ -414,7 +424,7 @@ class FlowExecutorView(APIView): ) return self._flow_done() - def stage_invalid(self, error_message: Optional[str] = None) -> HttpResponse: + def stage_invalid(self, error_message: str | None = None) -> HttpResponse: """Callback used stage when data is correct but a policy denies access or the user account is disabled. @@ -440,7 +450,7 @@ class FlowExecutorView(APIView): return to_stage_response(self.request, challenge_view.get(self.request)) def cancel(self): - """Cancel current execution and return a redirect""" + """Cancel current flow execution""" keys_to_delete = [ SESSION_KEY_APPLICATION_PRE, SESSION_KEY_PLAN, @@ -459,7 +469,7 @@ class FlowExecutorView(APIView): class CancelView(View): - """View which canels the currently active plan""" + """View which cancels the currently active plan""" def get(self, request: HttpRequest) -> HttpResponse: """View which canels the currently active plan""" @@ -472,9 +482,9 @@ class CancelView(View): class ToDefaultFlow(View): """Redirect to default flow matching by designation""" - designation: Optional[FlowDesignation] = None + designation: FlowDesignation | None = None - def flow_by_policy(self, request: HttpRequest, **flow_filter) -> Optional[Flow]: + def flow_by_policy(self, request: HttpRequest, **flow_filter) -> Flow | None: """Get a Flow by `**flow_filter` and check if the request from `request` can access it.""" flows = Flow.objects.filter(**flow_filter).order_by("slug") for flow in flows: @@ -496,9 +506,7 @@ class ToDefaultFlow(View): if self.designation == FlowDesignation.AUTHENTICATION: flow = brand.flow_authentication # Check if we have a default flow from application - application: Optional[Application] = self.request.session.get( - SESSION_KEY_APPLICATION_PRE - ) + application: Application | None = self.request.session.get(SESSION_KEY_APPLICATION_PRE) if application and application.provider and application.provider.authentication_flow: flow = application.provider.authentication_flow elif self.designation == FlowDesignation.INVALIDATION: @@ -528,7 +536,10 @@ class ToDefaultFlow(View): def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpResponse: """Convert normal HttpResponse into JSON Response""" - if isinstance(source, HttpResponseRedirect) or source.status_code == 302: + if ( + isinstance(source, HttpResponseRedirect) + or source.status_code == HttpResponseRedirect.status_code + ): redirect_url = source["Location"] # Redirects to the same URL usually indicate an Error within a form if request.get_full_path() == redirect_url: @@ -592,7 +603,7 @@ class ConfigureFlowInitView(LoginRequiredMixin, View): ) except FlowNonApplicableException: LOGGER.warning("Flow not applicable to user") - raise Http404 + raise Http404 from None request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs( "authentik_core:if-flow", diff --git a/authentik/flows/views/inspector.py b/authentik/flows/views/inspector.py index 4800ead6d7..74ab56dec5 100644 --- a/authentik/flows/views/inspector.py +++ b/authentik/flows/views/inspector.py @@ -1,4 +1,5 @@ """Flow Inspector""" + from hashlib import sha256 from typing import Any @@ -23,7 +24,8 @@ from authentik.flows.api.bindings import FlowStageBindingSerializer from authentik.flows.models import Flow from authentik.flows.planner import FlowPlan from authentik.flows.views.executor import SESSION_KEY_HISTORY, SESSION_KEY_PLAN -from authentik.root.install_id import get_install_id + +MIN_FLOW_LENGTH = 2 class FlowInspectorPlanSerializer(PassiveSerializer): @@ -40,7 +42,7 @@ class FlowInspectorPlanSerializer(PassiveSerializer): def get_next_planned_stage(self, plan: FlowPlan) -> FlowStageBindingSerializer: """Get the next planned stage""" - if len(plan.bindings) < 2: + if len(plan.bindings) < MIN_FLOW_LENGTH: return FlowStageBindingSerializer().data return FlowStageBindingSerializer(instance=plan.bindings[1]).data @@ -48,12 +50,10 @@ class FlowInspectorPlanSerializer(PassiveSerializer): """Get the plan's context, sanitized""" return sanitize_dict(plan.context) - def get_session_id(self, plan: FlowPlan) -> str: + def get_session_id(self, _plan: FlowPlan) -> str: """Get a unique session ID""" request: Request = self.context["request"] - return sha256( - f"{request._request.session.session_key}-{get_install_id()}".encode("ascii") - ).hexdigest() + return sha256(request._request.session.session_key.encode("ascii")).hexdigest() class FlowInspectionSerializer(PassiveSerializer): diff --git a/authentik/lib/avatars.py b/authentik/lib/avatars.py index 61127e3b06..7f5fe0c72c 100644 --- a/authentik/lib/avatars.py +++ b/authentik/lib/avatars.py @@ -1,27 +1,31 @@ """Avatar utils""" + from base64 import b64encode from functools import cache as funccache -from hashlib import md5 -from typing import TYPE_CHECKING, Optional +from hashlib import md5, sha256 +from typing import TYPE_CHECKING from urllib.parse import urlencode from django.core.cache import cache +from django.http import HttpRequest, HttpResponseNotFound from django.templatetags.static import static from lxml import etree # nosec from lxml.etree import Element, SubElement # nosec -from requests.exceptions import RequestException +from requests.exceptions import ConnectionError, HTTPError, RequestException, Timeout from authentik.lib.config import get_path_from_dict from authentik.lib.utils.http import get_http_session from authentik.tenants.utils import get_current_tenant -GRAVATAR_URL = "https://secure.gravatar.com" -DEFAULT_AVATAR = static("dist/assets/images/user_default.png") -CACHE_KEY_GRAVATAR = "goauthentik.io/lib/avatars/" - if TYPE_CHECKING: from authentik.core.models import User +GRAVATAR_URL = "https://www.gravatar.com" +DEFAULT_AVATAR = static("dist/assets/images/user_default.png") +CACHE_KEY_GRAVATAR = "goauthentik.io/lib/avatars/" +CACHE_KEY_GRAVATAR_AVAILABLE = "goauthentik.io/lib/avatars/gravatar_available" +GRAVATAR_STATUS_TTL_SECONDS = 60 * 60 * 8 # 8 Hours + SVG_XML_NS = "http://www.w3.org/2000/svg" SVG_NS_MAP = {None: SVG_XML_NS} # Match fonts used in web UI @@ -35,23 +39,25 @@ SVG_FONTS = [ ] -def avatar_mode_none(user: "User", mode: str) -> Optional[str]: +def avatar_mode_none(user: "User", mode: str) -> str | None: """No avatar""" return DEFAULT_AVATAR -def avatar_mode_attribute(user: "User", mode: str) -> Optional[str]: +def avatar_mode_attribute(user: "User", mode: str) -> str | None: """Avatars based on a user attribute""" avatar = get_path_from_dict(user.attributes, mode[11:], default=None) return avatar -def avatar_mode_gravatar(user: "User", mode: str) -> Optional[str]: +def avatar_mode_gravatar(user: "User", mode: str) -> str | None: """Gravatar avatars""" - # gravatar uses md5 for their URLs, so md5 can't be avoided - mail_hash = md5(user.email.lower().encode("utf-8")).hexdigest() # nosec - parameters = [("size", "158"), ("rating", "g"), ("default", "404")] - gravatar_url = f"{GRAVATAR_URL}/avatar/{mail_hash}?{urlencode(parameters, doseq=True)}" + if not cache.get(CACHE_KEY_GRAVATAR_AVAILABLE, True): + return None + + mail_hash = sha256(user.email.lower().encode("utf-8")).hexdigest() # nosec + parameters = {"size": "158", "rating": "g", "default": "404"} + gravatar_url = f"{GRAVATAR_URL}/avatar/{mail_hash}?{urlencode(parameters)}" full_key = CACHE_KEY_GRAVATAR + mail_hash if cache.has_key(full_key): @@ -63,10 +69,12 @@ def avatar_mode_gravatar(user: "User", mode: str) -> Optional[str]: # (HEAD since we don't need the body) # so if that returns a 404, move onto the next mode res = get_http_session().head(gravatar_url, timeout=5) - if res.status_code == 404: + if res.status_code == HttpResponseNotFound.status_code: cache.set(full_key, None) return None res.raise_for_status() + except (Timeout, ConnectionError, HTTPError): + cache.set(CACHE_KEY_GRAVATAR_AVAILABLE, False, timeout=GRAVATAR_STATUS_TTL_SECONDS) except RequestException: return gravatar_url cache.set(full_key, gravatar_url) @@ -75,7 +83,9 @@ def avatar_mode_gravatar(user: "User", mode: str) -> Optional[str]: def generate_colors(text: str) -> tuple[str, str]: """Generate colours based on `text`""" - color = int(md5(text.lower().encode("utf-8")).hexdigest(), 16) % 0xFFFFFF # nosec + color = ( + int(md5(text.lower().encode("utf-8"), usedforsecurity=False).hexdigest(), 16) % 0xFFFFFF + ) # nosec # Get a (somewhat arbitrarily) reduced scope of colors # to avoid too dark or light backgrounds @@ -84,12 +94,13 @@ def generate_colors(text: str) -> tuple[str, str]: red = min(max((color >> 16) & 0xFF, 55), 200) bg_hex = f"{red:02x}{green:02x}{blue:02x}" # Contrasting text color (https://stackoverflow.com/a/3943023) - text_hex = "000" if (red * 0.299 + green * 0.587 + blue * 0.114) > 186 else "fff" + text_hex = ( + "000" if (red * 0.299 + green * 0.587 + blue * 0.114) > 186 else "fff" # noqa: PLR2004 + ) return bg_hex, text_hex @funccache -# pylint: disable=too-many-arguments,too-many-locals def generate_avatar_from_name( name: str, length: int = 2, @@ -105,7 +116,7 @@ def generate_avatar_from_name( """ name_parts = name.split() # Only abbreviate first and last name - if len(name_parts) > 2: + if len(name_parts) > 2: # noqa: PLR2004 name_parts = [name_parts[0], name_parts[-1]] if len(name_parts) == 1: @@ -153,7 +164,7 @@ def generate_avatar_from_name( return etree.tostring(root_element).decode() -def avatar_mode_generated(user: "User", mode: str) -> Optional[str]: +def avatar_mode_generated(user: "User", mode: str) -> str | None: """Wrapper that converts generated avatar to base64 svg""" # By default generate based off of user's display name name = user.name.strip() @@ -167,9 +178,9 @@ def avatar_mode_generated(user: "User", mode: str) -> Optional[str]: return f"data:image/svg+xml;base64,{b64encode(svg.encode('utf-8')).decode('utf-8')}" -def avatar_mode_url(user: "User", mode: str) -> Optional[str]: +def avatar_mode_url(user: "User", mode: str) -> str | None: """Format url""" - mail_hash = md5(user.email.lower().encode("utf-8")).hexdigest() # nosec + mail_hash = md5(user.email.lower().encode("utf-8"), usedforsecurity=False).hexdigest() # nosec return mode % { "username": user.username, "mail_hash": mail_hash, @@ -177,14 +188,19 @@ def avatar_mode_url(user: "User", mode: str) -> Optional[str]: } -def get_avatar(user: "User") -> str: +def get_avatar(user: "User", request: HttpRequest | None = None) -> str: """Get avatar with configured mode""" mode_map = { "none": avatar_mode_none, "initials": avatar_mode_generated, "gravatar": avatar_mode_gravatar, } - modes: str = get_current_tenant().avatars + tenant = None + if request: + tenant = request.tenant + else: + tenant = get_current_tenant() + modes: str = tenant.avatars for mode in modes.split(","): avatar = None if mode in mode_map: diff --git a/authentik/lib/config.py b/authentik/lib/config.py index 319be44125..f4a808c549 100644 --- a/authentik/lib/config.py +++ b/authentik/lib/config.py @@ -1,4 +1,5 @@ """authentik core config loader""" + import base64 import json import os @@ -12,8 +13,8 @@ from json.decoder import JSONDecodeError from pathlib import Path from sys import argv, stderr from time import time -from typing import Any, Optional -from urllib.parse import urlparse +from typing import Any +from urllib.parse import quote_plus, urlparse import yaml from django.conf import ImproperlyConfigured @@ -88,7 +89,7 @@ class Attr: # depending on source_type, might contain the environment variable or the path # to the config file containing this change or the file containing this value - source: Optional[str] = field(default=None) + source: str | None = field(default=None) def __post_init__(self): if isinstance(self.value, Attr): @@ -189,16 +190,18 @@ class ConfigLoader: def update(self, root: dict[str, Any], updatee: dict[str, Any]) -> dict[str, Any]: """Recursively update dictionary""" - for key, value in updatee.items(): - if isinstance(value, Mapping): - root[key] = self.update(root.get(key, {}), value) + for key, raw_value in updatee.items(): + if isinstance(raw_value, Mapping): + root[key] = self.update(root.get(key, {}), raw_value) else: - if isinstance(value, str): - value = self.parse_uri(value) - elif isinstance(value, Attr) and isinstance(value.value, str): - value = self.parse_uri(value.value) - elif not isinstance(value, Attr): - value = Attr(value) + if isinstance(raw_value, str): + value = self.parse_uri(raw_value) + elif isinstance(raw_value, Attr) and isinstance(raw_value.value, str): + value = self.parse_uri(raw_value.value) + elif not isinstance(raw_value, Attr): + value = Attr(raw_value) + else: + value = raw_value root[key] = value return root @@ -218,7 +221,7 @@ class ConfigLoader: parsed_value = os.getenv(url.netloc, url.query) if url.scheme == "file": try: - with open(url.path, "r", encoding="utf8") as _file: + with open(url.path, encoding="utf8") as _file: parsed_value = _file.read().strip() except OSError as exc: self.log("error", f"Failed to read config value from {url.path}: {exc}") @@ -256,7 +259,7 @@ class ConfigLoader: relative_key = key.replace(f"{ENV_PREFIX}_", "", 1).replace("__", ".").lower() # Check if the value is json, and try to load it try: - value = loads(value) + value = loads(value) # noqa: PLW2901 except JSONDecodeError: pass attr_value = Attr(value, Attr.Source.ENV, relative_key) @@ -301,6 +304,12 @@ class ConfigLoader: """Wrapper for get that converts value into boolean""" return str(self.get(path, default)).lower() == "true" + def get_keys(self, path: str, sep=".") -> list[str]: + """List attribute keys by using yaml path""" + root = self.raw + attr: Attr = get_path_from_dict(root, path, sep=sep, default=Attr({})) + return attr.keys() + def get_dict_from_b64_json(self, path: str, default=None) -> dict: """Wrapper for get that converts value from Base64 encoded string into dictionary""" config_value = self.get(path) @@ -328,8 +337,28 @@ class ConfigLoader: CONFIG = ConfigLoader() +def redis_url(db: int) -> str: + """Helper to create a Redis URL for a specific database""" + _redis_protocol_prefix = "redis://" + _redis_tls_requirements = "" + if CONFIG.get_bool("redis.tls", False): + _redis_protocol_prefix = "rediss://" + _redis_tls_requirements = f"?ssl_cert_reqs={CONFIG.get('redis.tls_reqs')}" + if _redis_ca := CONFIG.get("redis.tls_ca_cert", None): + _redis_tls_requirements += f"&ssl_ca_certs={_redis_ca}" + _redis_url = ( + f"{_redis_protocol_prefix}" + f"{quote_plus(CONFIG.get('redis.username'))}:" + f"{quote_plus(CONFIG.get('redis.password'))}@" + f"{quote_plus(CONFIG.get('redis.host'))}:" + f"{CONFIG.get_int('redis.port')}" + f"/{db}{_redis_tls_requirements}" + ) + return _redis_url + + if __name__ == "__main__": - if len(argv) < 2: + if len(argv) < 2: # noqa: PLR2004 print(dumps(CONFIG.raw, indent=4, cls=AttrEncoder)) else: print(CONFIG.get(argv[1])) diff --git a/authentik/lib/default.yml b/authentik/lib/default.yml index 22eda58ae8..183ad8341c 100644 --- a/authentik/lib/default.yml +++ b/authentik/lib/default.yml @@ -10,6 +10,10 @@ postgresql: use_pgpool: false test: name: test_authentik + read_replicas: {} + # For example + # 0: + # host: replica1.example.com listen: listen_http: 0.0.0.0:9000 @@ -35,6 +39,7 @@ redis: password: "" tls: false tls_reqs: "none" + tls_ca_cert: null # broker: # url: "" @@ -52,12 +57,15 @@ cache: # result_backend: # url: "" +# transport_options: "" debug: false remote_debug: false log_level: info +session_storage: cache + error_reporting: enabled: false sentry_dsn: https://151ba72610234c4c97c5bcff4e1cffd8@authentik.error-reporting.a7k.io/4504163677503489 @@ -110,7 +118,6 @@ events: asn: "/geoip/GeoLite2-ASN.mmdb" cert_discovery_dir: /certs -default_token_length: 60 tenants: enabled: false diff --git a/authentik/lib/expression/evaluator.py b/authentik/lib/expression/evaluator.py index 3e98843ffc..f17b346d90 100644 --- a/authentik/lib/expression/evaluator.py +++ b/authentik/lib/expression/evaluator.py @@ -1,12 +1,16 @@ """authentik expression policy evaluator""" + import re import socket +from collections.abc import Iterable from ipaddress import ip_address, ip_network from textwrap import indent -from typing import Any, Iterable, Optional +from types import CodeType +from typing import Any from cachetools import TLRUCache, cached from django.core.exceptions import FieldError +from django.utils.text import slugify from guardian.shortcuts import get_anonymous_user from rest_framework.serializers import ValidationError from sentry_sdk.hub import Hub @@ -35,7 +39,7 @@ class BaseEvaluator: # Filename used for exec _filename: str - def __init__(self, filename: Optional[str] = None): + def __init__(self, filename: str | None = None): self._filename = filename if filename else "BaseEvaluator" # update website/docs/expressions/_objects.md # update website/docs/expressions/_functions.md @@ -54,12 +58,13 @@ class BaseEvaluator: "requests": get_http_session(), "resolve_dns": BaseEvaluator.expr_resolve_dns, "reverse_dns": BaseEvaluator.expr_reverse_dns, + "slugify": slugify, } self._context = {} @cached(cache=TLRUCache(maxsize=32, ttu=lambda key, value, now: now + 180)) @staticmethod - def expr_resolve_dns(host: str, ip_version: Optional[int] = None) -> list[str]: + def expr_resolve_dns(host: str, ip_version: int | None = None) -> list[str]: """Resolve host to a list of IPv4 and/or IPv6 addresses.""" # Although it seems to be fine (raising OSError), docs warn # against passing `None` for both the host and the port @@ -69,9 +74,9 @@ class BaseEvaluator: ip_list = [] family = 0 - if ip_version == 4: + if ip_version == 4: # noqa: PLR2004 family = socket.AF_INET - if ip_version == 6: + if ip_version == 6: # noqa: PLR2004 family = socket.AF_INET6 try: @@ -91,7 +96,7 @@ class BaseEvaluator: return ip_addr @staticmethod - def expr_flatten(value: list[Any] | Any) -> Optional[Any]: + def expr_flatten(value: list[Any] | Any) -> Any | None: """Flatten `value` if its a list""" if isinstance(value, list): if len(value) < 1: @@ -115,7 +120,7 @@ class BaseEvaluator: return user.all_groups().filter(**group_filters).exists() @staticmethod - def expr_user_by(**filters) -> Optional[User]: + def expr_user_by(**filters) -> User | None: """Get user by filters""" try: users = User.objects.filter(**filters) @@ -126,7 +131,7 @@ class BaseEvaluator: return None @staticmethod - def expr_func_user_has_authenticator(user: User, device_type: Optional[str] = None) -> bool: + def expr_func_user_has_authenticator(user: User, device_type: str | None = None) -> bool: """Check if a user has any authenticator devices, optionally matching *device_type*""" user_devices = devices_for_user(user) if device_type: @@ -180,7 +185,7 @@ class BaseEvaluator: full_expression += f"\nresult = handler({handler_signature})" return full_expression - def compile(self, expression: str) -> Any: + def compile(self, expression: str) -> CodeType: """Parse expression. Raises SyntaxError or ValueError if the syntax is incorrect.""" param_keys = self._context.keys() return compile(self.wrap_expression(expression, param_keys), self._filename, "exec") @@ -203,7 +208,7 @@ class BaseEvaluator: # Yes this is an exec, yes it is potentially bad. Since we limit what variables are # available here, and these policies can only be edited by admins, this is a risk # we're willing to take. - # pylint: disable=exec-used + exec(ast_obj, self._globals, _locals) # nosec # noqa result = _locals["result"] except Exception as exc: diff --git a/authentik/lib/generators.py b/authentik/lib/generators.py index 2716cc93ea..67e0e9a459 100644 --- a/authentik/lib/generators.py +++ b/authentik/lib/generators.py @@ -1,4 +1,5 @@ """ID/Secret Generators""" + import string from random import SystemRandom diff --git a/authentik/lib/logging.py b/authentik/lib/logging.py index b93cd06e5f..60309658c4 100644 --- a/authentik/lib/logging.py +++ b/authentik/lib/logging.py @@ -1,4 +1,5 @@ """logging helpers""" + import logging from logging import Logger from os import getpid @@ -99,6 +100,8 @@ def get_logger_config(): "fsevents": "WARNING", "uvicorn": "WARNING", "gunicorn": "INFO", + "requests_mock": "WARNING", + "hpack": "WARNING", } for handler_name, level in handler_level_map.items(): base_config["loggers"][handler_name] = { diff --git a/authentik/lib/merge.py b/authentik/lib/merge.py index 99a6dab665..764188cb52 100644 --- a/authentik/lib/merge.py +++ b/authentik/lib/merge.py @@ -1,4 +1,5 @@ """merge utils""" + from deepmerge import Merger MERGE_LIST_UNIQUE = Merger( diff --git a/authentik/lib/migrations.py b/authentik/lib/migrations.py index 9239430e6f..8f86be4af1 100644 --- a/authentik/lib/migrations.py +++ b/authentik/lib/migrations.py @@ -1,5 +1,6 @@ """Migration helpers""" -from typing import Iterable + +from collections.abc import Iterable from django.apps.registry import Apps from django.db.backends.base.schema import BaseDatabaseSchemaEditor diff --git a/authentik/lib/models.py b/authentik/lib/models.py index 19029c57fb..0b2ec9ac68 100644 --- a/authentik/lib/models.py +++ b/authentik/lib/models.py @@ -1,4 +1,5 @@ """Generic models""" + import re from django.core.validators import URLValidator @@ -11,14 +12,14 @@ from rest_framework.serializers import BaseSerializer class SerializerModel(models.Model): """Base Abstract Model which has a serializer""" + class Meta: + abstract = True + @property def serializer(self) -> type[BaseSerializer]: """Get serializer for this model""" raise NotImplementedError - class Meta: - abstract = True - class CreatedUpdatedModel(models.Model): """Base Abstract Model to save created and update""" diff --git a/authentik/lib/sentry.py b/authentik/lib/sentry.py index 6ea34625e2..b42a299660 100644 --- a/authentik/lib/sentry.py +++ b/authentik/lib/sentry.py @@ -1,6 +1,7 @@ """authentik sentry integration""" + from asyncio.exceptions import CancelledError -from typing import Any, Optional +from typing import Any from billiard.exceptions import SoftTimeLimitExceeded, WorkerLostError from celery.exceptions import CeleryError @@ -60,7 +61,7 @@ def sentry_init(**sentry_init_kwargs): }, } kwargs.update(**sentry_init_kwargs) - # pylint: disable=abstract-class-instantiated + sentry_sdk_init( dsn=CONFIG.get("error_reporting.sentry_dsn"), integrations=[ @@ -95,9 +96,9 @@ def traces_sampler(sampling_context: dict) -> float: return float(CONFIG.get("error_reporting.sample_rate", 0.1)) -def before_send(event: dict, hint: dict) -> Optional[dict]: +def before_send(event: dict, hint: dict) -> dict | None: """Check if error is database error, and ignore if so""" - # pylint: disable=no-name-in-module + from psycopg.errors import Error ignored_classes = ( diff --git a/authentik/lib/sync/__init__.py b/authentik/lib/sync/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/lib/sync/mapper.py b/authentik/lib/sync/mapper.py new file mode 100644 index 0000000000..18211a1104 --- /dev/null +++ b/authentik/lib/sync/mapper.py @@ -0,0 +1,67 @@ +from collections.abc import Generator + +from django.db.models import QuerySet +from django.http import HttpRequest + +from authentik.core.expression.evaluator import PropertyMappingEvaluator +from authentik.core.expression.exceptions import PropertyMappingExpressionException +from authentik.core.models import PropertyMapping, User + + +class PropertyMappingManager: + """Pre-compile and cache property mappings when an identical + set is used multiple times""" + + query_set: QuerySet[PropertyMapping] + mapping_subclass: type[PropertyMapping] + + _evaluators: list[PropertyMappingEvaluator] + + def __init__( + self, + qs: QuerySet[PropertyMapping], + # Expected subclass of PropertyMappings, any objects in the queryset + # that are not an instance of this class will be discarded + mapping_subclass: type[PropertyMapping], + # As they keys of parameters are part of the compilation, + # we need a list of all parameter names that will be used during evaluation + context_keys: list[str], + ) -> None: + self.query_set = qs + self.mapping_subclass = mapping_subclass + self.context_keys = context_keys + self.compile() + + def compile(self): + self._evaluators = [] + for mapping in self.query_set: + if not isinstance(mapping, self.mapping_subclass): + continue + evaluator = PropertyMappingEvaluator( + mapping, **{key: None for key in self.context_keys} + ) + # Compile and cache expression + evaluator.compile() + self._evaluators.append(evaluator) + + def iter_eval( + self, + user: User | None, + request: HttpRequest | None, + return_mapping: bool = False, + **kwargs, + ) -> Generator[tuple[dict, PropertyMapping], None]: + """Iterate over all mappings that were pre-compiled and + execute all of them with the given context""" + for mapping in self._evaluators: + mapping.set_context(user, request, **kwargs) + try: + value = mapping.evaluate(mapping.model.expression) + except Exception as exc: + raise PropertyMappingExpressionException(exc, mapping.model) from exc + if value is None: + continue + if return_mapping: + yield value, mapping.model + else: + yield value diff --git a/authentik/lib/sync/outgoing/__init__.py b/authentik/lib/sync/outgoing/__init__.py new file mode 100644 index 0000000000..1005a6b242 --- /dev/null +++ b/authentik/lib/sync/outgoing/__init__.py @@ -0,0 +1,5 @@ +"""Sync constants""" + +PAGE_SIZE = 100 +PAGE_TIMEOUT = 60 * 60 * 0.5 # Half an hour +HTTP_CONFLICT = 409 diff --git a/authentik/lib/sync/outgoing/api.py b/authentik/lib/sync/outgoing/api.py new file mode 100644 index 0000000000..03f31ecc5b --- /dev/null +++ b/authentik/lib/sync/outgoing/api.py @@ -0,0 +1,56 @@ +from collections.abc import Callable + +from django.utils.text import slugify +from drf_spectacular.utils import OpenApiResponse, extend_schema +from guardian.shortcuts import get_objects_for_user +from rest_framework.decorators import action +from rest_framework.fields import BooleanField +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.core.api.utils import PassiveSerializer +from authentik.events.api.tasks import SystemTaskSerializer +from authentik.lib.sync.outgoing.models import OutgoingSyncProvider + + +class SyncStatusSerializer(PassiveSerializer): + """Provider sync status""" + + is_running = BooleanField(read_only=True) + tasks = SystemTaskSerializer(many=True, read_only=True) + + +class OutgoingSyncProviderStatusMixin: + """Common API Endpoints for Outgoing sync providers""" + + sync_single_task: Callable = None + + @extend_schema( + responses={ + 200: SyncStatusSerializer(), + 404: OpenApiResponse(description="Task not found"), + } + ) + @action( + methods=["GET"], + detail=True, + pagination_class=None, + url_path="sync/status", + filter_backends=[], + ) + def sync_status(self, request: Request, pk: int) -> Response: + """Get provider's sync status""" + provider: OutgoingSyncProvider = self.get_object() + tasks = list( + get_objects_for_user(request.user, "authentik_events.view_systemtask").filter( + name=self.sync_single_task.__name__, + uid=slugify(provider.name), + ) + ) + with provider.sync_lock as lock_acquired: + status = { + "tasks": tasks, + # If we could not acquire the lock, it means a task is using it, and thus is running + "is_running": not lock_acquired, + } + return Response(SyncStatusSerializer(status).data) diff --git a/authentik/lib/sync/outgoing/base.py b/authentik/lib/sync/outgoing/base.py new file mode 100644 index 0000000000..45b60cd2ce --- /dev/null +++ b/authentik/lib/sync/outgoing/base.py @@ -0,0 +1,117 @@ +"""Basic outgoing sync Client""" + +from enum import StrEnum +from typing import TYPE_CHECKING + +from deepmerge import always_merger +from django.db import DatabaseError +from structlog.stdlib import get_logger + +from authentik.core.expression.exceptions import ( + PropertyMappingExpressionException, + SkipObjectException, +) +from authentik.events.models import Event, EventAction +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.exceptions import NotFoundSyncException, StopSync +from authentik.lib.utils.errors import exception_to_string + +if TYPE_CHECKING: + from django.db.models import Model + + from authentik.lib.sync.outgoing.models import OutgoingSyncProvider + + +class Direction(StrEnum): + + add = "add" + remove = "remove" + + +class BaseOutgoingSyncClient[ + TModel: "Model", TConnection: "Model", TSchema: dict, TProvider: "OutgoingSyncProvider" +]: + """Basic Outgoing sync client Client""" + + provider: TProvider + connection_type: type[TConnection] + connection_type_query: str + mapper: PropertyMappingManager + + can_discover = False + + def __init__(self, provider: TProvider): + self.logger = get_logger().bind(provider=provider.name) + self.provider = provider + + def create(self, obj: TModel) -> TConnection: + """Create object in remote destination""" + raise NotImplementedError() + + def update(self, obj: TModel, connection: TConnection): + """Update object in remote destination""" + raise NotImplementedError() + + def write(self, obj: TModel) -> tuple[TConnection, bool]: + """Write object to destination. Uses self.create and self.update, but + can be overwritten for further logic""" + connection = self.connection_type.objects.filter( + provider=self.provider, **{self.connection_type_query: obj} + ).first() + try: + if not connection: + connection = self.create(obj) + return connection, True + try: + self.update(obj, connection) + return connection, False + except NotFoundSyncException: + connection.delete() + connection = self.create(obj) + return connection, True + except DatabaseError as exc: + self.logger.warning("Failed to write object", obj=obj, exc=exc) + if connection: + connection.delete() + return None, False + + def delete(self, obj: TModel): + """Delete object from destination""" + raise NotImplementedError() + + def to_schema(self, obj: TModel, creating: bool, **defaults) -> TSchema: + """Convert object to destination schema""" + raw_final_object = {} + try: + eval_kwargs = { + "request": None, + "provider": self.provider, + "creating": creating, + obj._meta.model_name: obj, + } + eval_kwargs.setdefault("user", None) + for value in self.mapper.iter_eval(**eval_kwargs): + try: + always_merger.merge(raw_final_object, value) + except SkipObjectException as exc: + raise exc from exc + except PropertyMappingExpressionException as exc: + # Value error can be raised when assigning invalid data to an attribute + Event.new( + EventAction.CONFIGURATION_ERROR, + message=f"Failed to evaluate property-mapping {exception_to_string(exc)}", + mapping=exc.mapping, + ).save() + raise StopSync(exc, obj, exc.mapping) from exc + if not raw_final_object: + raise StopSync(ValueError("No user mappings configured"), obj) + for key, value in defaults.items(): + raw_final_object.setdefault(key, value) + return raw_final_object + + def discover(self): + """Optional method. Can be used to implement a "discovery" where + upon creation of this provider, this function will be called and can + pre-link any users/groups in the remote system with the respective + object in authentik based on a common identifier""" + raise NotImplementedError() diff --git a/authentik/lib/sync/outgoing/exceptions.py b/authentik/lib/sync/outgoing/exceptions.py new file mode 100644 index 0000000000..8434368218 --- /dev/null +++ b/authentik/lib/sync/outgoing/exceptions.py @@ -0,0 +1,41 @@ +from authentik.lib.sentry import SentryIgnoredException + + +class BaseSyncException(SentryIgnoredException): + """Base class for all sync exceptions""" + + +class TransientSyncException(BaseSyncException): + """Transient sync exception which may be caused by network blips, etc""" + + +class NotFoundSyncException(BaseSyncException): + """Exception when an object was not found in the remote system""" + + +class ObjectExistsSyncException(BaseSyncException): + """Exception when an object already exists in the remote system""" + + +class BadRequestSyncException(BaseSyncException): + """Exception when invalid data was sent to the remote system""" + + +class StopSync(BaseSyncException): + """Exception raised when a configuration error should stop the sync process""" + + def __init__( + self, exc: Exception, obj: object | None = None, mapping: object | None = None + ) -> None: + self.exc = exc + self.obj = obj + self.mapping = mapping + + def detail(self) -> str: + """Get human readable details of this error""" + msg = f"Error {str(self.exc)}" + if self.obj: + msg += f", caused by {self.obj}" + if self.mapping: + msg += f" (mapping {self.mapping})" + return msg diff --git a/authentik/lib/sync/outgoing/models.py b/authentik/lib/sync/outgoing/models.py new file mode 100644 index 0000000000..e46fb529f7 --- /dev/null +++ b/authentik/lib/sync/outgoing/models.py @@ -0,0 +1,40 @@ +from typing import Any, Self + +import pglock +from django.db import connection +from django.db.models import Model, QuerySet, TextChoices + +from authentik.core.models import Group, User +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient + + +class OutgoingSyncDeleteAction(TextChoices): + """Action taken when a user/group is deleted in authentik. Suspend is not available for groups, + and will be treated as `do_nothing`""" + + DO_NOTHING = "do_nothing" + DELETE = "delete" + SUSPEND = "suspend" + + +class OutgoingSyncProvider(Model): + + class Meta: + abstract = True + + def client_for_model[ + T: User | Group + ](self, model: type[T]) -> BaseOutgoingSyncClient[T, Any, Any, Self]: + raise NotImplementedError + + def get_object_qs[T: User | Group](self, type: type[T]) -> QuerySet[T]: + raise NotImplementedError + + @property + def sync_lock(self) -> pglock.advisory: + """Postgres lock for syncing SCIM to prevent multiple parallel syncs happening""" + return pglock.advisory( + lock_id=f"goauthentik.io/{connection.schema_name}/providers/outgoing-sync/{str(self.pk)}", + timeout=0, + side_effect=pglock.Return, + ) diff --git a/authentik/lib/sync/outgoing/signals.py b/authentik/lib/sync/outgoing/signals.py new file mode 100644 index 0000000000..ff574de45e --- /dev/null +++ b/authentik/lib/sync/outgoing/signals.py @@ -0,0 +1,71 @@ +from collections.abc import Callable + +from django.core.paginator import Paginator +from django.db.models import Model +from django.db.models.signals import m2m_changed, post_save, pre_delete + +from authentik.core.models import Group, User +from authentik.lib.sync.outgoing import PAGE_SIZE, PAGE_TIMEOUT +from authentik.lib.sync.outgoing.base import Direction +from authentik.lib.sync.outgoing.models import OutgoingSyncProvider +from authentik.lib.utils.reflection import class_to_path + + +def register_signals( + provider_type: type[OutgoingSyncProvider], + task_sync_single: Callable[[int], None], + task_sync_direct: Callable[[int], None], + task_sync_m2m: Callable[[int], None], +): + """Register sync signals""" + uid = class_to_path(provider_type) + + def post_save_provider(sender: type[Model], instance: OutgoingSyncProvider, created: bool, **_): + """Trigger sync when Provider is saved""" + users_paginator = Paginator(instance.get_object_qs(User), PAGE_SIZE) + groups_paginator = Paginator(instance.get_object_qs(Group), PAGE_SIZE) + soft_time_limit = (users_paginator.num_pages + groups_paginator.num_pages) * PAGE_TIMEOUT + time_limit = soft_time_limit * 1.5 + task_sync_single.apply_async( + (instance.pk,), time_limit=int(time_limit), soft_time_limit=int(soft_time_limit) + ) + + post_save.connect(post_save_provider, provider_type, dispatch_uid=uid, weak=False) + + def model_post_save(sender: type[Model], instance: User | Group, created: bool, **_): + """Post save handler""" + if not provider_type.objects.filter(backchannel_application__isnull=False).exists(): + return + task_sync_direct.delay(class_to_path(instance.__class__), instance.pk, Direction.add.value) + + post_save.connect(model_post_save, User, dispatch_uid=uid, weak=False) + post_save.connect(model_post_save, Group, dispatch_uid=uid, weak=False) + + def model_pre_delete(sender: type[Model], instance: User | Group, **_): + """Pre-delete handler""" + if not provider_type.objects.filter(backchannel_application__isnull=False).exists(): + return + task_sync_direct.delay( + class_to_path(instance.__class__), instance.pk, Direction.remove.value + ).get(propagate=False) + + pre_delete.connect(model_pre_delete, User, dispatch_uid=uid, weak=False) + pre_delete.connect(model_pre_delete, Group, dispatch_uid=uid, weak=False) + + def model_m2m_changed( + sender: type[Model], instance, action: str, pk_set: set, reverse: bool, **kwargs + ): + """Sync group membership""" + if action not in ["post_add", "post_remove"]: + return + if not provider_type.objects.filter(backchannel_application__isnull=False).exists(): + return + # reverse: instance is a Group, pk_set is a list of user pks + # non-reverse: instance is a User, pk_set is a list of groups + if reverse: + task_sync_m2m.delay(str(instance.pk), action, list(pk_set)) + else: + for group_pk in pk_set: + task_sync_m2m.delay(group_pk, action, [instance.pk]) + + m2m_changed.connect(model_m2m_changed, User.ak_groups.through, dispatch_uid=uid, weak=False) diff --git a/authentik/lib/sync/outgoing/tasks.py b/authentik/lib/sync/outgoing/tasks.py new file mode 100644 index 0000000000..80f26c4883 --- /dev/null +++ b/authentik/lib/sync/outgoing/tasks.py @@ -0,0 +1,251 @@ +from collections.abc import Callable +from dataclasses import asdict + +from celery.exceptions import Retry +from celery.result import allow_join_result +from django.core.paginator import Paginator +from django.db.models import Model, QuerySet +from django.utils.text import slugify +from django.utils.translation import gettext_lazy as _ +from structlog.stdlib import BoundLogger, get_logger + +from authentik.core.expression.exceptions import SkipObjectException +from authentik.core.models import Group, User +from authentik.events.logs import LogEvent +from authentik.events.models import TaskStatus +from authentik.events.system_tasks import SystemTask +from authentik.lib.sync.outgoing import PAGE_SIZE, PAGE_TIMEOUT +from authentik.lib.sync.outgoing.base import Direction +from authentik.lib.sync.outgoing.exceptions import ( + BadRequestSyncException, + StopSync, + TransientSyncException, +) +from authentik.lib.sync.outgoing.models import OutgoingSyncProvider +from authentik.lib.utils.reflection import class_to_path, path_to_class + + +class SyncTasks: + """Container for all sync 'tasks' (this class doesn't actually contain celery + tasks due to celery's magic, however exposes a number of functions to be called from tasks)""" + + logger: BoundLogger + + def __init__(self, provider_model: type[OutgoingSyncProvider]) -> None: + super().__init__() + self._provider_model = provider_model + + def sync_all(self, single_sync: Callable[[int], None]): + for provider in self._provider_model.objects.filter(backchannel_application__isnull=False): + self.trigger_single_task(provider, single_sync) + + def trigger_single_task(self, provider: OutgoingSyncProvider, sync_task: Callable[[int], None]): + """Wrapper single sync task that correctly sets time limits based + on the amount of objects that will be synced""" + users_paginator = Paginator(provider.get_object_qs(User), PAGE_SIZE) + groups_paginator = Paginator(provider.get_object_qs(Group), PAGE_SIZE) + soft_time_limit = (users_paginator.num_pages + groups_paginator.num_pages) * PAGE_TIMEOUT + time_limit = soft_time_limit * 1.5 + return sync_task.apply_async( + (provider.pk,), time_limit=int(time_limit), soft_time_limit=int(soft_time_limit) + ) + + def sync_single( + self, + task: SystemTask, + provider_pk: int, + sync_objects: Callable[[int, int], list[str]], + ): + self.logger = get_logger().bind( + provider_type=class_to_path(self._provider_model), + provider_pk=provider_pk, + ) + provider = self._provider_model.objects.filter( + pk=provider_pk, backchannel_application__isnull=False + ).first() + if not provider: + return + task.set_uid(slugify(provider.name)) + messages = [] + messages.append(_("Starting full provider sync")) + self.logger.debug("Starting provider sync") + users_paginator = Paginator(provider.get_object_qs(User), PAGE_SIZE) + groups_paginator = Paginator(provider.get_object_qs(Group), PAGE_SIZE) + with allow_join_result(), provider.sync_lock as lock_acquired: + if not lock_acquired: + self.logger.debug("Failed to acquire sync lock, skipping", provider=provider.name) + return + try: + for page in users_paginator.page_range: + messages.append(_("Syncing page %(page)d of users" % {"page": page})) + for msg in sync_objects.apply_async( + args=(class_to_path(User), page, provider_pk), + time_limit=PAGE_TIMEOUT, + soft_time_limit=PAGE_TIMEOUT, + ).get(): + messages.append(LogEvent(**msg)) + for page in groups_paginator.page_range: + messages.append(_("Syncing page %(page)d of groups" % {"page": page})) + for msg in sync_objects.apply_async( + args=(class_to_path(Group), page, provider_pk), + time_limit=PAGE_TIMEOUT, + soft_time_limit=PAGE_TIMEOUT, + ).get(): + messages.append(LogEvent(**msg)) + except TransientSyncException as exc: + self.logger.warning("transient sync exception", exc=exc) + raise task.retry(exc=exc) from exc + except StopSync as exc: + task.set_error(exc) + return + task.set_status(TaskStatus.SUCCESSFUL, *messages) + + def sync_objects(self, object_type: str, page: int, provider_pk: int): + _object_type = path_to_class(object_type) + self.logger = get_logger().bind( + provider_type=class_to_path(self._provider_model), + provider_pk=provider_pk, + object_type=object_type, + ) + messages = [] + provider = self._provider_model.objects.filter(pk=provider_pk).first() + if not provider: + return messages + try: + client = provider.client_for_model(_object_type) + except TransientSyncException: + return messages + paginator = Paginator(provider.get_object_qs(_object_type), PAGE_SIZE) + if client.can_discover: + self.logger.debug("starting discover") + client.discover() + self.logger.debug("starting sync for page", page=page) + for obj in paginator.page(page).object_list: + obj: Model + try: + client.write(obj) + except SkipObjectException: + continue + except BadRequestSyncException as exc: + self.logger.warning("failed to sync object", exc=exc, obj=obj) + messages.append( + asdict( + LogEvent( + _( + ( + "Failed to sync {object_type} {object_name} " + "due to error: {error}" + ).format_map( + { + "object_type": obj._meta.verbose_name, + "object_name": str(obj), + "error": str(exc), + } + ) + ), + log_level="warning", + logger="", + attributes={"arguments": exc.args[1:]}, + ) + ) + ) + except TransientSyncException as exc: + self.logger.warning("failed to sync object", exc=exc, user=obj) + messages.append( + asdict( + LogEvent( + _( + ( + "Failed to sync {object_type} {object_name} " + "due to transient error: {error}" + ).format_map( + { + "object_type": obj._meta.verbose_name, + "object_name": str(obj), + "error": str(exc), + } + ) + ), + log_level="warning", + logger="", + ) + ) + ) + except StopSync as exc: + self.logger.warning("Stopping sync", exc=exc) + messages.append( + asdict( + LogEvent( + _( + "Stopping sync due to error: {error}".format_map( + { + "error": exc.detail(), + } + ) + ), + log_level="warning", + logger="", + ) + ) + ) + break + return messages + + def sync_signal_direct(self, model: str, pk: str | int, raw_op: str): + self.logger = get_logger().bind( + provider_type=class_to_path(self._provider_model), + ) + model_class: type[Model] = path_to_class(model) + instance = model_class.objects.filter(pk=pk).first() + if not instance: + return + operation = Direction(raw_op) + for provider in self._provider_model.objects.filter(backchannel_application__isnull=False): + client = provider.client_for_model(instance.__class__) + # Check if the object is allowed within the provider's restrictions + queryset = provider.get_object_qs(instance.__class__) + if not queryset: + continue + + # The queryset we get from the provider must include the instance we've got given + # otherwise ignore this provider + if not queryset.filter(pk=instance.pk).exists(): + continue + + try: + if operation == Direction.add: + client.write(instance) + if operation == Direction.remove: + client.delete(instance) + except TransientSyncException as exc: + raise Retry() from exc + except StopSync as exc: + self.logger.warning(exc, provider_pk=provider.pk) + + def sync_signal_m2m(self, group_pk: str, action: str, pk_set: list[int]): + self.logger = get_logger().bind( + provider_type=class_to_path(self._provider_model), + ) + group = Group.objects.filter(pk=group_pk).first() + if not group: + return + for provider in self._provider_model.objects.filter(backchannel_application__isnull=False): + # Check if the object is allowed within the provider's restrictions + queryset: QuerySet = provider.get_object_qs(Group) + # The queryset we get from the provider must include the instance we've got given + # otherwise ignore this provider + if not queryset.filter(pk=group_pk).exists(): + continue + + client = provider.client_for_model(Group) + try: + operation = None + if action == "post_add": + operation = Direction.add + if action == "post_remove": + operation = Direction.remove + client.update_group(group, operation, pk_set) + except TransientSyncException as exc: + raise Retry() from exc + except StopSync as exc: + self.logger.warning(exc, provider_pk=provider.pk) diff --git a/authentik/lib/tests/test_config.py b/authentik/lib/tests/test_config.py index 3c253663f9..81c1150839 100644 --- a/authentik/lib/tests/test_config.py +++ b/authentik/lib/tests/test_config.py @@ -1,4 +1,5 @@ """Test config loader""" + import base64 from json import dumps from os import chmod, environ, unlink, write @@ -58,7 +59,7 @@ class TestConfig(TestCase): """Test URI parsing (file load)""" config = ConfigLoader() file, file_name = mkstemp() - write(file, "foo".encode()) + write(file, b"foo") _, file2_name = mkstemp() chmod(file2_name, 0o000) # Remove all permissions so we can't read the file self.assertEqual(config.parse_uri(f"file://{file_name}").value, "foo") @@ -69,12 +70,12 @@ class TestConfig(TestCase): def test_uri_file_update(self): """Test URI parsing (file load and update)""" file, file_name = mkstemp() - write(file, "foo".encode()) + write(file, b"foo") config = ConfigLoader(file_test=f"file://{file_name}") self.assertEqual(config.get("file_test"), "foo") # Update config file - write(file, "bar".encode()) + write(file, b"bar") config.refresh("file_test") self.assertEqual(config.get("file_test"), "foobar") @@ -90,9 +91,9 @@ class TestConfig(TestCase): """Test update_from_file""" config = ConfigLoader() file, file_name = mkstemp() - write(file, "{".encode()) + write(file, b"{") file2, file2_name = mkstemp() - write(file2, "{".encode()) + write(file2, b"{") chmod(file2_name, 0o000) # Remove all permissions so we can't read the file with self.assertRaises(ImproperlyConfigured): config.update_from_file(file_name) @@ -115,7 +116,7 @@ class TestConfig(TestCase): def test_get_dict_from_b64_json(self): """Test get_dict_from_b64_json""" config = ConfigLoader() - test_value = ' { "foo": "bar" } '.encode("utf-8") + test_value = b' { "foo": "bar" } ' b64_value = base64.b64encode(test_value) config.set("foo", b64_value) self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"}) @@ -123,7 +124,7 @@ class TestConfig(TestCase): def test_get_dict_from_b64_json_missing_brackets(self): """Test get_dict_from_b64_json with missing brackets""" config = ConfigLoader() - test_value = ' "foo": "bar" '.encode("utf-8") + test_value = b' "foo": "bar" ' b64_value = base64.b64encode(test_value) config.set("foo", b64_value) self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"}) @@ -168,3 +169,9 @@ class TestConfig(TestCase): self.assertEqual(config.get("cache.timeout_flows"), "32m") self.assertEqual(config.get("cache.timeout_policies"), "3920ns") self.assertEqual(config.get("cache.timeout_reputation"), "298382us") + + def test_get_keys(self): + """Test get_keys""" + config = ConfigLoader() + config.set("foo.bar", "baz") + self.assertEqual(list(config.get_keys("foo")), ["bar"]) diff --git a/authentik/lib/tests/test_evaluator.py b/authentik/lib/tests/test_evaluator.py index bb029304d6..305fea5fec 100644 --- a/authentik/lib/tests/test_evaluator.py +++ b/authentik/lib/tests/test_evaluator.py @@ -1,4 +1,5 @@ """Test Evaluator base functions""" + from django.test import TestCase from authentik.core.tests.utils import create_test_admin_user diff --git a/authentik/lib/tests/test_http.py b/authentik/lib/tests/test_http.py index 92ec5b4259..4fa8ab6196 100644 --- a/authentik/lib/tests/test_http.py +++ b/authentik/lib/tests/test_http.py @@ -1,4 +1,5 @@ """Test HTTP Helpers""" + from django.test import RequestFactory, TestCase from authentik.core.models import Token, TokenIntents, UserTypes diff --git a/authentik/lib/tests/test_sentry.py b/authentik/lib/tests/test_sentry.py index 958ef50414..e54664d7d5 100644 --- a/authentik/lib/tests/test_sentry.py +++ b/authentik/lib/tests/test_sentry.py @@ -1,4 +1,5 @@ """test sentry integration""" + from django.test import TestCase from authentik.lib.sentry import SentryIgnoredException, before_send diff --git a/authentik/lib/tests/test_serializer_model.py b/authentik/lib/tests/test_serializer_model.py index 08907211ea..0d91884e31 100644 --- a/authentik/lib/tests/test_serializer_model.py +++ b/authentik/lib/tests/test_serializer_model.py @@ -1,5 +1,6 @@ """base model tests""" -from typing import Callable + +from collections.abc import Callable from django.test import TestCase from rest_framework.serializers import BaseSerializer diff --git a/authentik/lib/tests/test_utils_time.py b/authentik/lib/tests/test_utils_time.py index cc16550e15..43d8f34940 100644 --- a/authentik/lib/tests/test_utils_time.py +++ b/authentik/lib/tests/test_utils_time.py @@ -1,4 +1,5 @@ """Test time utils""" + from datetime import timedelta from django.core.exceptions import ValidationError diff --git a/authentik/lib/tests/utils.py b/authentik/lib/tests/utils.py index 6e15fe61b5..3e2d8aa0df 100644 --- a/authentik/lib/tests/utils.py +++ b/authentik/lib/tests/utils.py @@ -1,4 +1,5 @@ """Test utils""" + from inspect import currentframe from pathlib import Path @@ -19,13 +20,11 @@ def load_fixture(path: str, **kwargs) -> str: current = currentframe() parent = current.f_back calling_file_path = parent.f_globals["__file__"] - with open( - Path(calling_file_path).resolve().parent / Path(path), "r", encoding="utf-8" - ) as _fixture: + with open(Path(calling_file_path).resolve().parent / Path(path), encoding="utf-8") as _fixture: fixture = _fixture.read() try: return fixture % kwargs - except TypeError: + except (TypeError, ValueError): return fixture diff --git a/authentik/lib/utils/errors.py b/authentik/lib/utils/errors.py index f1207c3ced..67bfd43f33 100644 --- a/authentik/lib/utils/errors.py +++ b/authentik/lib/utils/errors.py @@ -1,4 +1,5 @@ """error utils""" + from traceback import extract_tb from authentik.lib.utils.reflection import class_to_path diff --git a/authentik/lib/utils/file.py b/authentik/lib/utils/file.py index 2dc1d84299..d5b6056eb1 100644 --- a/authentik/lib/utils/file.py +++ b/authentik/lib/utils/file.py @@ -1,4 +1,5 @@ """file utils""" + from django.db.models import Model from django.http import HttpResponseBadRequest from rest_framework.fields import BooleanField, CharField, FileField diff --git a/authentik/lib/utils/http.py b/authentik/lib/utils/http.py index f8d33db98c..b90885ea39 100644 --- a/authentik/lib/utils/http.py +++ b/authentik/lib/utils/http.py @@ -1,11 +1,12 @@ """http helpers""" + from uuid import uuid4 -from django.conf import settings from requests.sessions import PreparedRequest, Session from structlog.stdlib import get_logger from authentik import get_full_version +from authentik.lib.config import CONFIG LOGGER = get_logger() @@ -34,6 +35,6 @@ class DebugSession(Session): def get_http_session() -> Session: """Get a requests session with common headers""" - session = DebugSession() if settings.DEBUG else Session() + session = DebugSession() if CONFIG.get_bool("debug") else Session() session.headers["User-Agent"] = authentik_user_agent() return session diff --git a/authentik/lib/utils/reflection.py b/authentik/lib/utils/reflection.py index c7dda74149..b8f8e4c08e 100644 --- a/authentik/lib/utils/reflection.py +++ b/authentik/lib/utils/reflection.py @@ -1,15 +1,18 @@ """authentik lib reflection utilities""" + import os from importlib import import_module from pathlib import Path +from tempfile import gettempdir from django.conf import settings -from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME from authentik.lib.config import CONFIG +SERVICE_HOST_ENV_NAME = "KUBERNETES_SERVICE_HOST" -def all_subclasses(cls, sort=True): + +def all_subclasses[T](cls: T, sort=True) -> list[T] | set[T]: """Recursively return all subclassess of cls""" classes = set(cls.__subclasses__()).union( [s for c in cls.__subclasses__() for s in all_subclasses(c, sort=sort)] @@ -54,7 +57,7 @@ def get_env() -> str: return "dev" if SERVICE_HOST_ENV_NAME in os.environ: return "kubernetes" - if Path("/tmp/authentik-mode").exists(): # nosec + if (Path(gettempdir()) / "authentik-mode").exists(): return "compose" if "AK_APPLIANCE" in os.environ: return os.environ["AK_APPLIANCE"] diff --git a/authentik/lib/utils/time.py b/authentik/lib/utils/time.py index ebca0ca387..4e7338cdb4 100644 --- a/authentik/lib/utils/time.py +++ b/authentik/lib/utils/time.py @@ -1,4 +1,5 @@ """Time utilities""" + import datetime from hashlib import sha256 from random import randrange, seed diff --git a/authentik/lib/utils/urls.py b/authentik/lib/utils/urls.py index da724817f3..a374642404 100644 --- a/authentik/lib/utils/urls.py +++ b/authentik/lib/utils/urls.py @@ -1,5 +1,5 @@ """URL-related utils""" -from typing import Optional + from urllib.parse import urlparse from django.http import HttpResponse, QueryDict @@ -16,9 +16,7 @@ def is_url_absolute(url): return bool(urlparse(url).netloc) -def redirect_with_qs( - view: str, get_query_set: Optional[QueryDict] = None, **kwargs -) -> HttpResponse: +def redirect_with_qs(view: str, get_query_set: QueryDict | None = None, **kwargs) -> HttpResponse: """Wrapper to redirect whilst keeping GET Parameters""" try: target = reverse(view, kwargs=kwargs) @@ -32,7 +30,7 @@ def redirect_with_qs( return redirect(target) -def reverse_with_qs(view: str, query: Optional[QueryDict] = None, **kwargs) -> str: +def reverse_with_qs(view: str, query: QueryDict | None = None, **kwargs) -> str: """Reverse a view to it's url but include get params""" url = reverse(view, **kwargs) if query: diff --git a/authentik/lib/validators.py b/authentik/lib/validators.py index 7c67da8c1a..31fb3f6f03 100644 --- a/authentik/lib/validators.py +++ b/authentik/lib/validators.py @@ -1,5 +1,4 @@ """Serializer validators""" -from typing import Optional from django.utils.translation import gettext_lazy as _ from rest_framework.exceptions import ValidationError @@ -15,7 +14,7 @@ class RequiredTogetherValidator: requires_context = True message = _("The fields {field_names} must be used together.") - def __init__(self, fields: list[str], message: Optional[str] = None) -> None: + def __init__(self, fields: list[str], message: str | None = None) -> None: self.fields = fields self.message = message or self.message @@ -29,4 +28,4 @@ class RequiredTogetherValidator: raise ValidationError(message, code="required") def __repr__(self): - return "<%s(fields=%s)>" % (self.__class__.__name__, smart_repr(self.fields)) + return f"<{self.__class__.__name__}(fields={smart_repr(self.fields)})>" diff --git a/authentik/lib/views.py b/authentik/lib/views.py index f430b149af..51d4d3b6d1 100644 --- a/authentik/lib/views.py +++ b/authentik/lib/views.py @@ -1,4 +1,5 @@ """authentik helper views""" + from django.http import HttpRequest from django.template.response import TemplateResponse from django.utils.translation import gettext_lazy as _ diff --git a/authentik/lib/xml.py b/authentik/lib/xml.py index d5a7b61c37..ec65d3475a 100644 --- a/authentik/lib/xml.py +++ b/authentik/lib/xml.py @@ -1,4 +1,5 @@ """XML Utilities""" + from lxml.etree import XMLParser, fromstring # nosec diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index 182ec4dbfe..f5bde93c77 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -1,4 +1,5 @@ """Outpost API Views""" + from dacite.core import from_dict from dacite.exceptions import DaciteError from django_filters.filters import ModelMultipleChoiceFilter @@ -116,8 +117,12 @@ class OutpostHealthSerializer(PassiveSerializer): uid = CharField(read_only=True) last_seen = DateTimeField(read_only=True) version = CharField(read_only=True) - version_should = CharField(read_only=True) + golang_version = CharField(read_only=True) + openssl_enabled = BooleanField(read_only=True) + openssl_version = CharField(read_only=True) + fips_enabled = BooleanField(read_only=True) + version_should = CharField(read_only=True) version_outdated = BooleanField(read_only=True) build_hash = CharField(read_only=True, required=False) @@ -172,6 +177,10 @@ class OutpostViewSet(UsedByMixin, ModelViewSet): "version_should": state.version_should, "version_outdated": state.version_outdated, "build_hash": state.build_hash, + "golang_version": state.golang_version, + "openssl_enabled": state.openssl_enabled, + "openssl_version": state.openssl_version, + "fips_enabled": state.fips_enabled, "hostname": state.hostname, "build_hash_should": get_build_hash(), } diff --git a/authentik/outposts/api/service_connections.py b/authentik/outposts/api/service_connections.py index 7c988474a5..2c4484f83c 100644 --- a/authentik/outposts/api/service_connections.py +++ b/authentik/outposts/api/service_connections.py @@ -1,4 +1,5 @@ """Outpost API Views""" + from dataclasses import asdict from django.utils.translation import gettext_lazy as _ @@ -14,9 +15,12 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer, PassiveSerializer, TypeCreateSerializer -from authentik.lib.utils.reflection import all_subclasses +from authentik.core.api.utils import ( + MetaNameSerializer, + PassiveSerializer, +) from authentik.outposts.models import ( DockerServiceConnection, KubernetesServiceConnection, @@ -56,6 +60,7 @@ class ServiceConnectionStateSerializer(PassiveSerializer): class ServiceConnectionViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -69,23 +74,6 @@ class ServiceConnectionViewSet( search_fields = ["name"] filterset_fields = ["name"] - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable service connection types""" - data = [] - for subclass in all_subclasses(self.queryset.model): - subclass: OutpostServiceConnection - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": subclass().component, - "model_name": subclass._meta.model_name, - } - ) - return Response(TypeCreateSerializer(data, many=True).data) - @extend_schema(responses={200: ServiceConnectionStateSerializer(many=False)}) @action(detail=True, pagination_class=None, filter_backends=[]) def state(self, request: Request, pk: str) -> Response: @@ -132,7 +120,7 @@ class KubernetesServiceConnectionSerializer(ServiceConnectionSerializer): try: load_kube_config_from_dict(kubeconfig, client_configuration=config) except ConfigException: - raise serializers.ValidationError(_("Invalid kubeconfig")) + raise serializers.ValidationError(_("Invalid kubeconfig")) from None return kubeconfig class Meta: diff --git a/authentik/outposts/apps.py b/authentik/outposts/apps.py index dbdf26af41..a7680a9aa5 100644 --- a/authentik/outposts/apps.py +++ b/authentik/outposts/apps.py @@ -1,4 +1,5 @@ """authentik outposts app config""" + from prometheus_client import Gauge from structlog.stdlib import get_logger @@ -29,11 +30,8 @@ class AuthentikOutpostConfig(ManagedAppConfig): verbose_name = "authentik Outpost" default = True - def reconcile_global_load_outposts_signals(self): - """Load outposts signals""" - self.import_module("authentik.outposts.signals") - - def reconcile_tenant_embedded_outpost(self): + @ManagedAppConfig.reconcile_tenant + def embedded_outpost(self): """Ensure embedded outpost""" from authentik.outposts.models import ( DockerServiceConnection, @@ -47,14 +45,14 @@ class AuthentikOutpostConfig(ManagedAppConfig): outpost.managed = MANAGED_OUTPOST outpost.save() return - outpost, updated = Outpost.objects.update_or_create( + outpost, created = Outpost.objects.update_or_create( defaults={ "type": OutpostType.PROXY, "name": MANAGED_OUTPOST_NAME, }, managed=MANAGED_OUTPOST, ) - if updated: + if created: if KubernetesServiceConnection.objects.exists(): outpost.service_connection = KubernetesServiceConnection.objects.first() elif DockerServiceConnection.objects.exists(): diff --git a/authentik/outposts/consumer.py b/authentik/outposts/consumer.py index 03738b88fb..80b64999d5 100644 --- a/authentik/outposts/consumer.py +++ b/authentik/outposts/consumer.py @@ -1,8 +1,9 @@ """Outpost websocket handler""" + from dataclasses import asdict, dataclass, field from datetime import datetime from enum import IntEnum -from typing import Any, Optional +from typing import Any from asgiref.sync import async_to_sync from channels.exceptions import DenyConnection @@ -48,10 +49,10 @@ class WebsocketMessage: class OutpostConsumer(JsonWebsocketConsumer): """Handler for Outposts that connect over websockets for health checks and live updates""" - outpost: Optional[Outpost] = None + outpost: Outpost | None = None logger: BoundLogger - instance_uid: Optional[str] = None + instance_uid: str | None = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -70,7 +71,7 @@ class OutpostConsumer(JsonWebsocketConsumer): self.accept() except RuntimeError as exc: self.logger.warning("runtime error during accept", exc=exc) - raise DenyConnection() + raise DenyConnection() from None self.outpost = outpost query = QueryDict(self.scope["query_string"].decode()) self.instance_uid = query.get("instance_uuid", self.channel_name) @@ -120,6 +121,10 @@ class OutpostConsumer(JsonWebsocketConsumer): if msg.instruction == WebsocketMessageInstruction.HELLO: state.version = msg.args.pop("version", None) state.build_hash = msg.args.pop("buildHash", "") + state.golang_version = msg.args.pop("golangVersion", "") + state.openssl_enabled = msg.args.pop("opensslEnabled", False) + state.openssl_version = msg.args.pop("opensslVersion", "") + state.fips_enabled = msg.args.pop("fipsEnabled", False) state.args.update(msg.args) elif msg.instruction == WebsocketMessageInstruction.ACK: return diff --git a/authentik/outposts/controllers/base.py b/authentik/outposts/controllers/base.py index a3c0cb7d62..a7321e01cc 100644 --- a/authentik/outposts/controllers/base.py +++ b/authentik/outposts/controllers/base.py @@ -1,11 +1,11 @@ """Base Controller""" + from dataclasses import dataclass -from typing import Optional from structlog.stdlib import get_logger -from structlog.testing import capture_logs from authentik import __version__, get_build_hash +from authentik.events.logs import LogEvent, capture_logs from authentik.lib.config import CONFIG from authentik.lib.sentry import SentryIgnoredException from authentik.outposts.models import ( @@ -28,7 +28,7 @@ class DeploymentPort: port: int name: str protocol: str - inner_port: Optional[int] = None + inner_port: int | None = None class BaseClient: @@ -59,26 +59,25 @@ class BaseController: self.logger = get_logger() self.deployment_ports = [] - # pylint: disable=invalid-name def up(self): """Called by scheduled task to reconcile deployment/service/etc""" raise NotImplementedError - def up_with_logs(self) -> list[str]: + def up_with_logs(self) -> list[LogEvent]: """Call .up() but capture all log output and return it.""" with capture_logs() as logs: self.up() - return [x["event"] for x in logs] + return logs def down(self): """Handler to delete everything we've created""" raise NotImplementedError - def down_with_logs(self) -> list[str]: + def down_with_logs(self) -> list[LogEvent]: """Call .down() but capture all log output and return it.""" with capture_logs() as logs: self.down() - return [x["event"] for x in logs] + return logs def __enter__(self): return self diff --git a/authentik/outposts/controllers/docker.py b/authentik/outposts/controllers/docker.py index 48918e25e0..69ea01477f 100644 --- a/authentik/outposts/controllers/docker.py +++ b/authentik/outposts/controllers/docker.py @@ -1,6 +1,6 @@ """Docker controller""" + from time import sleep -from typing import Optional from urllib.parse import urlparse from django.conf import settings @@ -24,12 +24,14 @@ from authentik.outposts.models import ( ServiceConnectionInvalid, ) +DOCKER_MAX_ATTEMPTS = 10 + class DockerClient(UpstreamDockerClient, BaseClient): """Custom docker client, which can handle TLS and SSH from a database.""" - tls: Optional[DockerInlineTLS] - ssh: Optional[DockerInlineSSH] + tls: DockerInlineTLS | None + ssh: DockerInlineSSH | None def __init__(self, connection: DockerServiceConnection): self.tls = None @@ -225,11 +227,10 @@ class DockerController(BaseController): except NotFound: return - # pylint: disable=too-many-return-statements def up(self, depth=1): if self.outpost.managed == MANAGED_OUTPOST: return None - if depth >= 10: + if depth >= DOCKER_MAX_ATTEMPTS: raise ControllerException("Giving up since we exceeded recursion limit.") self._migrate_container_name() try: diff --git a/authentik/outposts/controllers/k8s/base.py b/authentik/outposts/controllers/k8s/base.py index ca8542a750..2a254ade09 100644 --- a/authentik/outposts/controllers/k8s/base.py +++ b/authentik/outposts/controllers/k8s/base.py @@ -1,9 +1,11 @@ """Base Kubernetes Reconciler""" + from dataclasses import asdict from json import dumps -from typing import TYPE_CHECKING, Generic, Optional, TypeVar +from typing import TYPE_CHECKING, Generic, TypeVar from dacite.core import from_dict +from django.http import HttpResponseNotFound from django.utils.text import slugify from jsonpatch import JsonPatchConflict, JsonPatchException, JsonPatchTestFailed, apply_patch from kubernetes.client import ApiClient, V1ObjectMeta @@ -99,7 +101,6 @@ class KubernetesObjectReconciler(Generic[T]): return result - # pylint: disable=invalid-name def up(self): """Create object if it doesn't exist, update if needed or recreate if needed.""" current = None @@ -111,8 +112,8 @@ class KubernetesObjectReconciler(Generic[T]): try: current = self.retrieve() except (OpenApiException, HTTPError) as exc: - # pylint: disable=no-member - if isinstance(exc, ApiException) and exc.status == 404: + + if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code: self.logger.debug("Failed to get current, triggering recreate") raise NeedsRecreate from exc self.logger.debug("Other unhandled error", exc=exc) @@ -123,8 +124,8 @@ class KubernetesObjectReconciler(Generic[T]): self.update(current, reference) self.logger.debug("Updating") except (OpenApiException, HTTPError) as exc: - # pylint: disable=no-member - if isinstance(exc, ApiException) and exc.status == 422: + + if isinstance(exc, ApiException) and exc.status == 422: # noqa: PLR2004 self.logger.debug("Failed to update current, triggering re-create") self._recreate(current=current, reference=reference) return @@ -135,7 +136,7 @@ class KubernetesObjectReconciler(Generic[T]): else: self.logger.debug("Object is up-to-date.") - def _recreate(self, reference: T, current: Optional[T] = None): + def _recreate(self, reference: T, current: T | None = None): """Recreate object""" self.logger.debug("Recreate requested") if current: @@ -156,8 +157,8 @@ class KubernetesObjectReconciler(Generic[T]): self.delete(current) self.logger.debug("Removing") except (OpenApiException, HTTPError) as exc: - # pylint: disable=no-member - if isinstance(exc, ApiException) and exc.status == 404: + + if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code: self.logger.debug("Failed to get current, assuming non-existent") return self.logger.debug("Other unhandled error", exc=exc) diff --git a/authentik/outposts/controllers/k8s/deployment.py b/authentik/outposts/controllers/k8s/deployment.py index e06d971395..fe12a4404e 100644 --- a/authentik/outposts/controllers/k8s/deployment.py +++ b/authentik/outposts/controllers/k8s/deployment.py @@ -1,4 +1,5 @@ """Kubernetes Deployment Reconciler""" + from typing import TYPE_CHECKING from django.utils.text import slugify diff --git a/authentik/outposts/controllers/k8s/secret.py b/authentik/outposts/controllers/k8s/secret.py index ddc3643c6e..ca765b6833 100644 --- a/authentik/outposts/controllers/k8s/secret.py +++ b/authentik/outposts/controllers/k8s/secret.py @@ -1,4 +1,5 @@ """Kubernetes Secret Reconciler""" + from base64 import b64encode from typing import TYPE_CHECKING diff --git a/authentik/outposts/controllers/k8s/service.py b/authentik/outposts/controllers/k8s/service.py index 374e942741..f3cbb75e0b 100644 --- a/authentik/outposts/controllers/k8s/service.py +++ b/authentik/outposts/controllers/k8s/service.py @@ -1,4 +1,5 @@ """Kubernetes Service Reconciler""" + from typing import TYPE_CHECKING from kubernetes.client import CoreV1Api, V1Service, V1ServicePort, V1ServiceSpec @@ -32,6 +33,8 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]): # priority than being updated. if current.spec.selector != reference.spec.selector: raise NeedsUpdate() + if current.spec.type != reference.spec.type: + raise NeedsUpdate() super().reconcile(current, reference) def get_reference_object(self) -> V1Service: diff --git a/authentik/outposts/controllers/k8s/service_monitor.py b/authentik/outposts/controllers/k8s/service_monitor.py index 8e00f9c50c..4e80e23ca3 100644 --- a/authentik/outposts/controllers/k8s/service_monitor.py +++ b/authentik/outposts/controllers/k8s/service_monitor.py @@ -1,4 +1,5 @@ """Kubernetes Prometheus ServiceMonitor Reconciler""" + from dataclasses import asdict, dataclass, field from typing import TYPE_CHECKING @@ -24,7 +25,6 @@ class PrometheusServiceMonitorSpecEndpoint: class PrometheusServiceMonitorSpecSelector: """Prometheus ServiceMonitor selector spec""" - # pylint: disable=invalid-name matchLabels: dict @@ -33,7 +33,7 @@ class PrometheusServiceMonitorSpec: """Prometheus ServiceMonitor spec""" endpoints: list[PrometheusServiceMonitorSpecEndpoint] - # pylint: disable=invalid-name + selector: PrometheusServiceMonitorSpecSelector @@ -50,7 +50,6 @@ class PrometheusServiceMonitorMetadata: class PrometheusServiceMonitor: """Prometheus ServiceMonitor""" - # pylint: disable=invalid-name apiVersion: str kind: str metadata: PrometheusServiceMonitorMetadata diff --git a/authentik/outposts/controllers/k8s/triggers.py b/authentik/outposts/controllers/k8s/triggers.py index 284acd3bc5..f9191a1ff0 100644 --- a/authentik/outposts/controllers/k8s/triggers.py +++ b/authentik/outposts/controllers/k8s/triggers.py @@ -1,4 +1,5 @@ """exceptions used by the kubernetes reconciler to trigger updates""" + from authentik.lib.sentry import SentryIgnoredException diff --git a/authentik/outposts/controllers/k8s/utils.py b/authentik/outposts/controllers/k8s/utils.py index e9c83f9753..c2f22f0c8e 100644 --- a/authentik/outposts/controllers/k8s/utils.py +++ b/authentik/outposts/controllers/k8s/utils.py @@ -1,6 +1,6 @@ """k8s utils""" + from pathlib import Path -from typing import Optional from kubernetes.client.models.v1_container_port import V1ContainerPort from kubernetes.client.models.v1_service_port import V1ServicePort @@ -13,7 +13,7 @@ def get_namespace() -> str: """Get the namespace if we're running in a pod, otherwise default to default""" path = Path(SERVICE_TOKEN_FILENAME.replace("token", "namespace")) if path.exists(): - with open(path, "r", encoding="utf8") as _namespace_file: + with open(path, encoding="utf8") as _namespace_file: return _namespace_file.read() return "default" @@ -38,8 +38,8 @@ def compare_port( def compare_ports( - current: Optional[list[V1ServicePort | V1ContainerPort]], - reference: Optional[list[V1ServicePort | V1ContainerPort]], + current: list[V1ServicePort | V1ContainerPort] | None, + reference: list[V1ServicePort | V1ContainerPort] | None, ): """Compare ports of a list""" if not current or not reference: diff --git a/authentik/outposts/controllers/kubernetes.py b/authentik/outposts/controllers/kubernetes.py index e3b3580787..5802d154ca 100644 --- a/authentik/outposts/controllers/kubernetes.py +++ b/authentik/outposts/controllers/kubernetes.py @@ -1,4 +1,5 @@ """Kubernetes deployment controller""" + from io import StringIO from kubernetes.client import VersionApi, VersionInfo @@ -8,10 +9,10 @@ from kubernetes.client.exceptions import OpenApiException from kubernetes.config.config_exception import ConfigException from kubernetes.config.incluster_config import load_incluster_config from kubernetes.config.kube_config import load_kube_config_from_dict -from structlog.testing import capture_logs from urllib3.exceptions import HTTPError from yaml import dump_all +from authentik.events.logs import LogEvent, capture_logs from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler @@ -90,7 +91,7 @@ class KubernetesController(BaseController): except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc: raise ControllerException(str(exc)) from exc - def up_with_logs(self) -> list[str]: + def up_with_logs(self) -> list[LogEvent]: try: all_logs = [] for reconcile_key in self.reconcile_order: @@ -103,7 +104,9 @@ class KubernetesController(BaseController): continue reconciler = reconciler_cls(self) reconciler.up() - all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] + for log in logs: + log.logger = reconcile_key.title() + all_logs.extend(logs) return all_logs except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc: raise ControllerException(str(exc)) from exc @@ -121,7 +124,7 @@ class KubernetesController(BaseController): except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc: raise ControllerException(str(exc)) from exc - def down_with_logs(self) -> list[str]: + def down_with_logs(self) -> list[LogEvent]: try: all_logs = [] for reconcile_key in self.reconcile_order: @@ -134,7 +137,9 @@ class KubernetesController(BaseController): continue reconciler = reconciler_cls(self) reconciler.down() - all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] + for log in logs: + log.logger = reconcile_key.title() + all_logs.extend(logs) return all_logs except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc: raise ControllerException(str(exc)) from exc diff --git a/authentik/outposts/docker_ssh.py b/authentik/outposts/docker_ssh.py index b146ca6c9d..ac2de3e125 100644 --- a/authentik/outposts/docker_ssh.py +++ b/authentik/outposts/docker_ssh.py @@ -1,4 +1,5 @@ """Docker SSH helper""" + import os from pathlib import Path from tempfile import gettempdir @@ -80,7 +81,7 @@ class DockerInlineSSH: """Cleanup when we're done""" try: os.unlink(self.key_path) - with open(self.config_path, "r", encoding="utf-8") as ssh_config: + with open(self.config_path, encoding="utf-8") as ssh_config: start = 0 end = 0 lines = ssh_config.readlines() diff --git a/authentik/outposts/docker_tls.py b/authentik/outposts/docker_tls.py index 79e9bdaca6..a16550e35d 100644 --- a/authentik/outposts/docker_tls.py +++ b/authentik/outposts/docker_tls.py @@ -1,8 +1,8 @@ """Create Docker TLSConfig from CertificateKeyPair""" + from os import unlink from pathlib import Path from tempfile import gettempdir -from typing import Optional from docker.tls import TLSConfig @@ -12,15 +12,15 @@ from authentik.crypto.models import CertificateKeyPair class DockerInlineTLS: """Create Docker TLSConfig from CertificateKeyPair""" - verification_kp: Optional[CertificateKeyPair] - authentication_kp: Optional[CertificateKeyPair] + verification_kp: CertificateKeyPair | None + authentication_kp: CertificateKeyPair | None _paths: list[str] def __init__( self, - verification_kp: Optional[CertificateKeyPair], - authentication_kp: Optional[CertificateKeyPair], + verification_kp: CertificateKeyPair | None, + authentication_kp: CertificateKeyPair | None, ) -> None: self.verification_kp = verification_kp self.authentication_kp = authentication_kp diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index 3460d4ada8..1a10e11c3d 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -1,7 +1,9 @@ """Outpost models""" + +from collections.abc import Iterable from dataclasses import asdict, dataclass, field from datetime import datetime -from typing import Any, Iterable, Optional +from typing import Any from uuid import uuid4 from dacite.core import from_dict @@ -48,7 +50,6 @@ class ServiceConnectionInvalid(SentryIgnoredException): @dataclass -# pylint: disable=too-many-instance-attributes class OutpostConfig: """Configuration an outpost uses to configure it self""" @@ -61,21 +62,21 @@ class OutpostConfig: log_level: str = CONFIG.get("log_level") object_naming_template: str = field(default="ak-outpost-%(name)s") - container_image: Optional[str] = field(default=None) + container_image: str | None = field(default=None) - docker_network: Optional[str] = field(default=None) + docker_network: str | None = field(default=None) docker_map_ports: bool = field(default=True) - docker_labels: Optional[dict[str, str]] = field(default=None) + docker_labels: dict[str, str] | None = field(default=None) kubernetes_replicas: int = field(default=1) kubernetes_namespace: str = field(default_factory=get_namespace) kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict) kubernetes_ingress_secret_name: str = field(default="authentik-outpost-tls") - kubernetes_ingress_class_name: Optional[str] = field(default=None) + kubernetes_ingress_class_name: str | None = field(default=None) kubernetes_service_type: str = field(default="ClusterIP") kubernetes_disabled_components: list[str] = field(default_factory=list) kubernetes_image_pull_secrets: list[str] = field(default_factory=list) - kubernetes_json_patches: Optional[dict[str, list[dict[str, Any]]]] = field(default=None) + kubernetes_json_patches: dict[str, list[dict[str, Any]]] | None = field(default=None) class OutpostModel(Model): @@ -98,7 +99,7 @@ class OutpostType(models.TextChoices): RAC = "rac" -def default_outpost_config(host: Optional[str] = None): +def default_outpost_config(host: str | None = None): """Get default outpost config""" return asdict(OutpostConfig(authentik_host=host or "")) @@ -126,6 +127,13 @@ class OutpostServiceConnection(models.Model): objects = InheritanceManager() + class Meta: + verbose_name = _("Outpost Service-Connection") + verbose_name_plural = _("Outpost Service-Connections") + + def __str__(self) -> str: + return f"Outpost service connection {self.name}" + @property def state_key(self) -> str: """Key used to save connection state in cache""" @@ -149,10 +157,6 @@ class OutpostServiceConnection(models.Model): # since the response doesn't use the correct inheritance return "" - class Meta: - verbose_name = _("Outpost Service-Connection") - verbose_name_plural = _("Outpost Service-Connections") - class DockerServiceConnection(SerializerModel, OutpostServiceConnection): """Service Connection to a Docker endpoint""" @@ -187,6 +191,13 @@ class DockerServiceConnection(SerializerModel, OutpostServiceConnection): ), ) + class Meta: + verbose_name = _("Docker Service-Connection") + verbose_name_plural = _("Docker Service-Connections") + + def __str__(self) -> str: + return f"Docker Service-Connection {self.name}" + @property def serializer(self) -> Serializer: from authentik.outposts.api.service_connections import DockerServiceConnectionSerializer @@ -197,13 +208,6 @@ class DockerServiceConnection(SerializerModel, OutpostServiceConnection): def component(self) -> str: return "ak-service-connection-docker-form" - def __str__(self) -> str: - return f"Docker Service-Connection {self.name}" - - class Meta: - verbose_name = _("Docker Service-Connection") - verbose_name_plural = _("Docker Service-Connections") - class KubernetesServiceConnection(SerializerModel, OutpostServiceConnection): """Service Connection to a Kubernetes cluster""" @@ -219,6 +223,13 @@ class KubernetesServiceConnection(SerializerModel, OutpostServiceConnection): default=True, help_text=_("Verify SSL Certificates of the Kubernetes API endpoint") ) + class Meta: + verbose_name = _("Kubernetes Service-Connection") + verbose_name_plural = _("Kubernetes Service-Connections") + + def __str__(self) -> str: + return f"Kubernetes Service-Connection {self.name}" + @property def serializer(self) -> Serializer: from authentik.outposts.api.service_connections import KubernetesServiceConnectionSerializer @@ -229,13 +240,6 @@ class KubernetesServiceConnection(SerializerModel, OutpostServiceConnection): def component(self) -> str: return "ak-service-connection-kubernetes-form" - def __str__(self) -> str: - return f"Kubernetes Service-Connection {self.name}" - - class Meta: - verbose_name = _("Kubernetes Service-Connection") - verbose_name_plural = _("Kubernetes Service-Connections") - class Outpost(SerializerModel, ManagedModel): """Outpost instance which manages a service user and token""" @@ -426,14 +430,18 @@ class OutpostState: """Outpost instance state, last_seen and version""" uid: str - last_seen: Optional[datetime] = field(default=None) - version: Optional[str] = field(default=None) + last_seen: datetime | None = field(default=None) + version: str | None = field(default=None) version_should: Version = field(default=OUR_VERSION) build_hash: str = field(default="") + golang_version: str = field(default="") + openssl_enabled: bool = field(default=False) + openssl_version: str = field(default="") + fips_enabled: bool = field(default=False) hostname: str = field(default="") args: dict = field(default_factory=dict) - _outpost: Optional[Outpost] = field(default=None) + _outpost: Outpost | None = field(default=None) @property def version_outdated(self) -> bool: @@ -466,7 +474,7 @@ class OutpostState: cache.delete(key) data = default_data state = from_dict(OutpostState, data) - # pylint: disable=protected-access + state._outpost = outpost return state diff --git a/authentik/outposts/settings.py b/authentik/outposts/settings.py index 6ce2d52c86..c29f9f64ab 100644 --- a/authentik/outposts/settings.py +++ b/authentik/outposts/settings.py @@ -1,4 +1,5 @@ """Outposts Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/outposts/signals.py b/authentik/outposts/signals.py index 0185dfcb3f..73d05a4b9a 100644 --- a/authentik/outposts/signals.py +++ b/authentik/outposts/signals.py @@ -1,4 +1,5 @@ """authentik outpost signals""" + from django.core.cache import cache from django.db.models import Model from django.db.models.signals import m2m_changed, post_save, pre_delete, pre_save diff --git a/authentik/outposts/tasks.py b/authentik/outposts/tasks.py index 72309a8e3d..cb4dac236a 100644 --- a/authentik/outposts/tasks.py +++ b/authentik/outposts/tasks.py @@ -1,8 +1,9 @@ """outpost tasks""" + from os import R_OK, access from pathlib import Path from socket import gethostname -from typing import Any, Optional +from typing import Any from urllib.parse import urlparse from asgiref.sync import async_to_sync @@ -48,8 +49,7 @@ LOGGER = get_logger() CACHE_KEY_OUTPOST_DOWN = "goauthentik.io/outposts/teardown/%s" -# pylint: disable=too-many-return-statements -def controller_for_outpost(outpost: Outpost) -> Optional[type[BaseController]]: +def controller_for_outpost(outpost: Outpost) -> type[BaseController] | None: """Get a controller for the outpost, when a service connection is defined""" if not outpost.service_connection: return None @@ -149,10 +149,8 @@ def outpost_controller( if not controller_type: return with controller_type(outpost, outpost.service_connection) as controller: - logs = getattr(controller, f"{action}_with_logs")() LOGGER.debug("---------------Outpost Controller logs starting----------------") - for log in logs: - LOGGER.debug(log) + logs = getattr(controller, f"{action}_with_logs")() LOGGER.debug("-----------------Outpost Controller logs end-------------------") except (ControllerException, ServiceConnectionInvalid) as exc: self.set_error(exc) @@ -192,15 +190,15 @@ def outpost_post_save(model_class: str, model_pk: Any): if isinstance(instance, Outpost): LOGGER.debug("Trigger reconcile for outpost", instance=instance) - outpost_controller.delay(instance.pk) + outpost_controller.delay(str(instance.pk)) - if isinstance(instance, (OutpostModel, Outpost)): + if isinstance(instance, OutpostModel | Outpost): LOGGER.debug("triggering outpost update from outpostmodel/outpost", instance=instance) outpost_send_update(instance) if isinstance(instance, OutpostServiceConnection): LOGGER.debug("triggering ServiceConnection state update", instance=instance) - outpost_service_connection_state.delay(instance.pk) + outpost_service_connection_state.delay(str(instance.pk)) for field in instance._meta.get_fields(): # Each field is checked if it has a `related_model` attribute (when ForeginKeys or M2Ms) diff --git a/authentik/outposts/tests/test_api.py b/authentik/outposts/tests/test_api.py index 3edaeb78ee..99b2da915b 100644 --- a/authentik/outposts/tests/test_api.py +++ b/authentik/outposts/tests/test_api.py @@ -1,4 +1,5 @@ """Test outpost service connection API""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/outposts/tests/test_commands.py b/authentik/outposts/tests/test_commands.py index 9e70e8b024..d2fa6229ab 100644 --- a/authentik/outposts/tests/test_commands.py +++ b/authentik/outposts/tests/test_commands.py @@ -1,4 +1,5 @@ """management command tests""" + from io import StringIO from django.core.management import call_command diff --git a/authentik/outposts/tests/test_controller_docker.py b/authentik/outposts/tests/test_controller_docker.py index 1fd00d9c92..8bf8d07ea5 100644 --- a/authentik/outposts/tests/test_controller_docker.py +++ b/authentik/outposts/tests/test_controller_docker.py @@ -1,4 +1,5 @@ """Docker controller tests""" + from django.test import TestCase from docker.models.containers import Container diff --git a/authentik/outposts/tests/test_sa.py b/authentik/outposts/tests/test_sa.py index de73071ae5..59238a2cf8 100644 --- a/authentik/outposts/tests/test_sa.py +++ b/authentik/outposts/tests/test_sa.py @@ -1,4 +1,5 @@ """outpost tests""" + from django.apps import apps from django.contrib.auth.management import create_permissions from django.test import TestCase diff --git a/authentik/outposts/tests/test_ws.py b/authentik/outposts/tests/test_ws.py index ec3d543a37..effb91a84a 100644 --- a/authentik/outposts/tests/test_ws.py +++ b/authentik/outposts/tests/test_ws.py @@ -1,4 +1,5 @@ """Websocket tests""" + from dataclasses import asdict from channels.exceptions import DenyConnection diff --git a/authentik/outposts/urls.py b/authentik/outposts/urls.py index 9d28a01ebd..42bb779241 100644 --- a/authentik/outposts/urls.py +++ b/authentik/outposts/urls.py @@ -1,4 +1,5 @@ """Outpost Websocket URLS""" + from django.urls import path from authentik.core.channels import TokenOutpostMiddleware diff --git a/authentik/policies/api/bindings.py b/authentik/policies/api/bindings.py index 59b28d262e..f9a5ab1c7e 100644 --- a/authentik/policies/api/bindings.py +++ b/authentik/policies/api/bindings.py @@ -1,5 +1,6 @@ """policy binding API Views""" -from typing import OrderedDict + +from collections import OrderedDict from django.core.exceptions import ObjectDoesNotExist from django_filters.filters import BooleanFilter, ModelMultipleChoiceFilter @@ -24,7 +25,6 @@ class PolicyBindingModelForeignKey(PrimaryKeyRelatedField): def use_pk_only_optimization(self): return False - # pylint: disable=inconsistent-return-statements def to_internal_value(self, data): if self.pk_field is not None: data = self.pk_field.to_internal_value(data) diff --git a/authentik/policies/api/exec.py b/authentik/policies/api/exec.py index 56fb42c907..a3b6285c3b 100644 --- a/authentik/policies/api/exec.py +++ b/authentik/policies/api/exec.py @@ -1,9 +1,11 @@ """Serializer for policy execution""" -from rest_framework.fields import BooleanField, CharField, DictField, ListField + +from rest_framework.fields import BooleanField, CharField, ListField from rest_framework.relations import PrimaryKeyRelatedField from authentik.core.api.utils import JSONDictField, PassiveSerializer from authentik.core.models import User +from authentik.events.logs import LogEventSerializer class PolicyTestSerializer(PassiveSerializer): @@ -18,4 +20,4 @@ class PolicyTestResultSerializer(PassiveSerializer): passing = BooleanField() messages = ListField(child=CharField(), read_only=True) - log_messages = ListField(child=DictField(), read_only=True) + log_messages = LogEventSerializer(many=True, read_only=True) diff --git a/authentik/policies/api/policies.py b/authentik/policies/api/policies.py index 11bdab1907..93137a0ce8 100644 --- a/authentik/policies/api/policies.py +++ b/authentik/policies/api/policies.py @@ -1,4 +1,5 @@ """policy API Views""" + from django.core.cache import cache from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema @@ -10,18 +11,20 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger -from structlog.testing import capture_logs -from authentik.api.decorators import permission_required from authentik.core.api.applications import user_app_cache_key +from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import CacheSerializer, MetaNameSerializer, TypeCreateSerializer -from authentik.events.utils import sanitize_dict -from authentik.lib.utils.reflection import all_subclasses +from authentik.core.api.utils import ( + CacheSerializer, + MetaNameSerializer, +) +from authentik.events.logs import LogEventSerializer, capture_logs from authentik.policies.api.exec import PolicyTestResultSerializer, PolicyTestSerializer from authentik.policies.models import Policy, PolicyBinding from authentik.policies.process import PolicyProcess from authentik.policies.types import CACHE_PREFIX, PolicyRequest +from authentik.rbac.decorators import permission_required LOGGER = get_logger() @@ -69,6 +72,7 @@ class PolicySerializer(ModelSerializer, MetaNameSerializer): class PolicyViewSet( + TypesMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, UsedByMixin, @@ -89,23 +93,6 @@ class PolicyViewSet( def get_queryset(self): # pragma: no cover return Policy.objects.select_subclasses().prefetch_related("bindings", "promptstage_set") - @extend_schema(responses={200: TypeCreateSerializer(many=True)}) - @action(detail=False, pagination_class=None, filter_backends=[]) - def types(self, request: Request) -> Response: - """Get all creatable policy types""" - data = [] - for subclass in all_subclasses(self.queryset.model): - subclass: Policy - data.append( - { - "name": subclass._meta.verbose_name, - "description": subclass.__doc__, - "component": subclass().component, - "model_name": subclass._meta.model_name, - } - ) - return Response(TypeCreateSerializer(data, many=True).data) - @permission_required(None, ["authentik_policies.view_policy_cache"]) @extend_schema(responses={200: CacheSerializer(many=False)}) @action(detail=False, pagination_class=None, filter_backends=[]) @@ -165,9 +152,9 @@ class PolicyViewSet( result = proc.execute() log_messages = [] for log in logs: - if log.get("process", "") == "PolicyProcess": + if log.attributes.get("process", "") == "PolicyProcess": continue - log_messages.append(sanitize_dict(log)) + log_messages.append(LogEventSerializer(log).data) result.log_messages = log_messages response = PolicyTestResultSerializer(result) return Response(response.data) diff --git a/authentik/policies/apps.py b/authentik/policies/apps.py index eca22c5f7f..107a801295 100644 --- a/authentik/policies/apps.py +++ b/authentik/policies/apps.py @@ -1,4 +1,5 @@ """authentik policies app config""" + from prometheus_client import Gauge, Histogram from authentik.blueprints.apps import ManagedAppConfig @@ -34,7 +35,3 @@ class AuthentikPoliciesConfig(ManagedAppConfig): label = "authentik_policies" verbose_name = "authentik Policies" default = True - - def reconcile_global_load_policies_signals(self): - """Load policies signals""" - self.import_module("authentik.policies.signals") diff --git a/authentik/policies/denied.py b/authentik/policies/denied.py index 7cb7d0bb88..b93348372d 100644 --- a/authentik/policies/denied.py +++ b/authentik/policies/denied.py @@ -1,5 +1,6 @@ """policy http response""" -from typing import Any, Optional + +from typing import Any from django.http.request import HttpRequest from django.template.response import TemplateResponse @@ -16,14 +17,14 @@ class AccessDeniedResponse(TemplateResponse): title: str - error_message: Optional[str] = None - policy_result: Optional[PolicyResult] = None + error_message: str | None = None + policy_result: PolicyResult | None = None def __init__(self, request: HttpRequest, template="policies/denied.html") -> None: super().__init__(request, template) self.title = _("Access denied") - def resolve_context(self, context: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]: + def resolve_context(self, context: dict[str, Any] | None) -> dict[str, Any] | None: if not context: context = {} context["title"] = self.title diff --git a/authentik/policies/dummy/api.py b/authentik/policies/dummy/api.py index 344089a0df..d19f2346c3 100644 --- a/authentik/policies/dummy/api.py +++ b/authentik/policies/dummy/api.py @@ -1,4 +1,5 @@ """Dummy Policy API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/policies/dummy/models.py b/authentik/policies/dummy/models.py index eb2c60441c..8167f8f935 100644 --- a/authentik/policies/dummy/models.py +++ b/authentik/policies/dummy/models.py @@ -1,4 +1,5 @@ """Dummy policy""" + from random import SystemRandom from time import sleep diff --git a/authentik/policies/dummy/tests.py b/authentik/policies/dummy/tests.py index 364ae54e7f..c510e3d363 100644 --- a/authentik/policies/dummy/tests.py +++ b/authentik/policies/dummy/tests.py @@ -1,4 +1,5 @@ """dummy policy tests""" + from django.test import TestCase from guardian.shortcuts import get_anonymous_user diff --git a/authentik/policies/dummy/urls.py b/authentik/policies/dummy/urls.py index 1ff9867b3a..1d0036bbe5 100644 --- a/authentik/policies/dummy/urls.py +++ b/authentik/policies/dummy/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.dummy.api import DummyPolicyViewSet api_urlpatterns = [("policies/dummy", DummyPolicyViewSet)] diff --git a/authentik/policies/engine.py b/authentik/policies/engine.py index 58295f3219..8b24334bf6 100644 --- a/authentik/policies/engine.py +++ b/authentik/policies/engine.py @@ -1,8 +1,9 @@ """authentik policy engine""" + +from collections.abc import Iterator from multiprocessing import Pipe, current_process from multiprocessing.connection import Connection -from timeit import default_timer -from typing import Iterator, Optional +from time import perf_counter from django.core.cache import cache from django.http import HttpRequest @@ -26,7 +27,7 @@ class PolicyProcessInfo: process: PolicyProcess connection: Connection - result: Optional[PolicyResult] + result: PolicyResult | None binding: PolicyBinding def __init__(self, process: PolicyProcess, connection: Connection, binding: PolicyBinding): @@ -83,10 +84,10 @@ class PolicyEngine: def _check_cache(self, binding: PolicyBinding): if not self.use_cache: return False - before = default_timer() + before = perf_counter() key = cache_key(binding, self.request) cached_policy = cache.get(key, None) - duration = max(default_timer() - before, 0) + duration = max(perf_counter() - before, 0) if not cached_policy: return False self.logger.debug( diff --git a/authentik/policies/event_matcher/api.py b/authentik/policies/event_matcher/api.py index ea81a8c054..866067322c 100644 --- a/authentik/policies/event_matcher/api.py +++ b/authentik/policies/event_matcher/api.py @@ -1,4 +1,5 @@ """Event Matcher Policy API""" + from django.utils.translation import gettext as _ from rest_framework.exceptions import ValidationError from rest_framework.fields import ChoiceField diff --git a/authentik/policies/event_matcher/migrations/0019_alter_eventmatcherpolicy_app.py b/authentik/policies/event_matcher/migrations/0019_alter_eventmatcherpolicy_app.py index 0c58538781..3162b17ea3 100644 --- a/authentik/policies/event_matcher/migrations/0019_alter_eventmatcherpolicy_app.py +++ b/authentik/policies/event_matcher/migrations/0019_alter_eventmatcherpolicy_app.py @@ -39,6 +39,7 @@ class Migration(migrations.Migration): ("authentik.sources.oauth", "authentik Sources.OAuth"), ("authentik.sources.plex", "authentik Sources.Plex"), ("authentik.sources.saml", "authentik Sources.SAML"), + ("authentik.sources.scim", "authentik Sources.SCIM"), ("authentik.stages.authenticator_duo", "authentik Stages.Authenticator.Duo"), ("authentik.stages.authenticator_sms", "authentik Stages.Authenticator.SMS"), ( diff --git a/authentik/policies/event_matcher/models.py b/authentik/policies/event_matcher/models.py index c4e3ca3736..78af38d5cf 100644 --- a/authentik/policies/event_matcher/models.py +++ b/authentik/policies/event_matcher/models.py @@ -1,4 +1,5 @@ """Event Matcher models""" + from itertools import chain from django.apps import apps diff --git a/authentik/policies/event_matcher/tests.py b/authentik/policies/event_matcher/tests.py index d703125e96..003a21d630 100644 --- a/authentik/policies/event_matcher/tests.py +++ b/authentik/policies/event_matcher/tests.py @@ -1,4 +1,5 @@ """event_matcher tests""" + from django.test import TestCase from guardian.shortcuts import get_anonymous_user diff --git a/authentik/policies/event_matcher/urls.py b/authentik/policies/event_matcher/urls.py index a9a2dfd856..793c8c63a8 100644 --- a/authentik/policies/event_matcher/urls.py +++ b/authentik/policies/event_matcher/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.event_matcher.api import EventMatcherPolicyViewSet api_urlpatterns = [("policies/event_matcher", EventMatcherPolicyViewSet)] diff --git a/authentik/policies/exceptions.py b/authentik/policies/exceptions.py index b6848fd411..83e97bd318 100644 --- a/authentik/policies/exceptions.py +++ b/authentik/policies/exceptions.py @@ -1,5 +1,4 @@ """policy exceptions""" -from typing import Optional from authentik.lib.sentry import SentryIgnoredException @@ -11,8 +10,8 @@ class PolicyEngineException(SentryIgnoredException): class PolicyException(SentryIgnoredException): """Exception that should be raised during Policy Evaluation, and can be recovered from.""" - src_exc: Optional[Exception] = None + src_exc: Exception | None = None - def __init__(self, src_exc: Optional[Exception] = None) -> None: + def __init__(self, src_exc: Exception | None = None) -> None: super().__init__() self.src_exc = src_exc diff --git a/authentik/policies/expiry/api.py b/authentik/policies/expiry/api.py index 2f72cc6e87..9f1d001106 100644 --- a/authentik/policies/expiry/api.py +++ b/authentik/policies/expiry/api.py @@ -1,4 +1,5 @@ """Password Expiry Policy API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/policies/expiry/models.py b/authentik/policies/expiry/models.py index b4f2b58f6d..6df91ef534 100644 --- a/authentik/policies/expiry/models.py +++ b/authentik/policies/expiry/models.py @@ -1,4 +1,5 @@ """authentik password_expiry_policy Models""" + from datetime import timedelta from django.db import models diff --git a/authentik/policies/expiry/urls.py b/authentik/policies/expiry/urls.py index d5945201ba..d2fef36a37 100644 --- a/authentik/policies/expiry/urls.py +++ b/authentik/policies/expiry/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.expiry.api import PasswordExpiryPolicyViewSet api_urlpatterns = [("policies/password_expiry", PasswordExpiryPolicyViewSet)] diff --git a/authentik/policies/expression/api.py b/authentik/policies/expression/api.py index c587f1b151..6e970eb39d 100644 --- a/authentik/policies/expression/api.py +++ b/authentik/policies/expression/api.py @@ -1,4 +1,5 @@ """Expression Policy API""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/policies/expression/evaluator.py b/authentik/policies/expression/evaluator.py index 4cc167f4bc..536b2634d8 100644 --- a/authentik/policies/expression/evaluator.py +++ b/authentik/policies/expression/evaluator.py @@ -1,4 +1,5 @@ """authentik expression policy evaluator""" + from ipaddress import ip_address from typing import TYPE_CHECKING, Optional @@ -23,7 +24,7 @@ class PolicyEvaluator(BaseEvaluator): policy: Optional["ExpressionPolicy"] = None - def __init__(self, policy_name: Optional[str] = None): + def __init__(self, policy_name: str | None = None): super().__init__(policy_name or "PolicyEvaluator") self._messages = [] # update website/docs/expressions/_objects.md @@ -65,7 +66,7 @@ class PolicyEvaluator(BaseEvaluator): # PolicyExceptions should be propagated back to the process, # which handles recording and returning a correct result raise exc - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Expression error", exc=exc) return PolicyResult(False, str(exc)) else: diff --git a/authentik/policies/expression/models.py b/authentik/policies/expression/models.py index c1b2c2062d..e70f780562 100644 --- a/authentik/policies/expression/models.py +++ b/authentik/policies/expression/models.py @@ -1,4 +1,5 @@ """authentik expression Policy Models""" + from django.db import models from django.utils.translation import gettext as _ from rest_framework.serializers import BaseSerializer diff --git a/authentik/policies/expression/tests.py b/authentik/policies/expression/tests.py index b94df250d5..ed8fac2c65 100644 --- a/authentik/policies/expression/tests.py +++ b/authentik/policies/expression/tests.py @@ -1,4 +1,5 @@ """evaluator tests""" + from django.test import RequestFactory, TestCase from guardian.shortcuts import get_anonymous_user from rest_framework.serializers import ValidationError @@ -95,19 +96,42 @@ class TestEvaluator(TestCase): execution_logging=True, expression="ak_message(request.http_request.path)\nreturn True", ) - tmpl = ( - """ - ak_message(request.http_request.path) - res = ak_call_policy('%s') - ak_message(request.http_request.path) - for msg in res.messages: - ak_message(msg) - """ - % expr.name + expr2 = ExpressionPolicy.objects.create( + name=generate_id(), + execution_logging=True, + expression=f""" + ak_message(request.http_request.path) + res = ak_call_policy('{expr.name}') + ak_message(request.http_request.path) + for msg in res.messages: + ak_message(msg) + """, ) - evaluator = PolicyEvaluator("test") - evaluator.set_policy_request(self.request) - res = evaluator.evaluate(tmpl) + proc = PolicyProcess(PolicyBinding(policy=expr2), request=self.request, connection=None) + res = proc.profiling_wrapper() + self.assertEqual(res.messages, ("/", "/", "/")) + + def test_call_policy_test_like(self): + """test ak_call_policy without `obj` set, as if it was when testing policies""" + expr = ExpressionPolicy.objects.create( + name=generate_id(), + execution_logging=True, + expression="ak_message(request.http_request.path)\nreturn True", + ) + expr2 = ExpressionPolicy.objects.create( + name=generate_id(), + execution_logging=True, + expression=f""" + ak_message(request.http_request.path) + res = ak_call_policy('{expr.name}') + ak_message(request.http_request.path) + for msg in res.messages: + ak_message(msg) + """, + ) + self.request.obj = None + proc = PolicyProcess(PolicyBinding(policy=expr2), request=self.request, connection=None) + res = proc.profiling_wrapper() self.assertEqual(res.messages, ("/", "/", "/")) diff --git a/authentik/policies/expression/urls.py b/authentik/policies/expression/urls.py index ad554fea9d..86acb4c2b4 100644 --- a/authentik/policies/expression/urls.py +++ b/authentik/policies/expression/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.expression.api import ExpressionPolicyViewSet api_urlpatterns = [("policies/expression", ExpressionPolicyViewSet)] diff --git a/authentik/policies/models.py b/authentik/policies/models.py index b99aeb5497..2364dfeb28 100644 --- a/authentik/policies/models.py +++ b/authentik/policies/models.py @@ -1,4 +1,5 @@ """Policy base models""" + from uuid import uuid4 from django.db import models @@ -39,13 +40,13 @@ class PolicyBindingModel(models.Model): objects = InheritanceManager() - def __str__(self) -> str: - return f"PolicyBindingModel {self.pbm_uuid}" - class Meta: verbose_name = _("Policy Binding Model") verbose_name_plural = _("Policy Binding Models") + def __str__(self) -> str: + return f"PolicyBindingModel {self.pbm_uuid}" + class PolicyBinding(SerializerModel): """Relationship between a Policy and a PolicyBindingModel.""" @@ -137,7 +138,7 @@ class PolicyBinding(SerializerModel): suffix = f"{self.target_type.title()} {self.target_name}" try: return f"Binding from {self.target} #{self.order} to {suffix}" - except PolicyBinding.target.RelatedObjectDoesNotExist: # pylint: disable=no-member + except PolicyBinding.target.RelatedObjectDoesNotExist: return f"Binding - #{self.order} to {suffix}" return "" diff --git a/authentik/policies/password/api.py b/authentik/policies/password/api.py index c42a0fee10..ec5fa10440 100644 --- a/authentik/policies/password/api.py +++ b/authentik/policies/password/api.py @@ -1,4 +1,5 @@ """Password Policy API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/policies/password/models.py b/authentik/policies/password/models.py index 31765bf20b..d8584617bc 100644 --- a/authentik/policies/password/models.py +++ b/authentik/policies/password/models.py @@ -1,4 +1,5 @@ """password policy""" + import re from hashlib import sha1 @@ -86,7 +87,6 @@ class PasswordPolicy(Policy): return zxcvbn_result return PolicyResult(True) - # pylint: disable=too-many-return-statements def passes_static(self, password: str, request: PolicyRequest) -> PolicyResult: """Check static rules""" if len(password) < self.length_min: diff --git a/authentik/policies/password/tests/test_flows.py b/authentik/policies/password/tests/test_flows.py index 8f2e7998e7..1dc18fc9c4 100644 --- a/authentik/policies/password/tests/test_flows.py +++ b/authentik/policies/password/tests/test_flows.py @@ -1,4 +1,5 @@ """Password flow tests""" + from django.urls.base import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow diff --git a/authentik/policies/password/tests/test_hibp.py b/authentik/policies/password/tests/test_hibp.py index 9ffd3b0d6f..03ad652d93 100644 --- a/authentik/policies/password/tests/test_hibp.py +++ b/authentik/policies/password/tests/test_hibp.py @@ -1,4 +1,5 @@ """Password Policy HIBP tests""" + from django.test import TestCase from guardian.shortcuts import get_anonymous_user diff --git a/authentik/policies/password/tests/test_policy.py b/authentik/policies/password/tests/test_policy.py index cef0c8156d..4e67a7c4a0 100644 --- a/authentik/policies/password/tests/test_policy.py +++ b/authentik/policies/password/tests/test_policy.py @@ -1,4 +1,5 @@ """Password Policy tests""" + from django.test import TestCase from guardian.shortcuts import get_anonymous_user diff --git a/authentik/policies/password/tests/test_zxcvbn.py b/authentik/policies/password/tests/test_zxcvbn.py index dc2f47c5c4..71a974eb1d 100644 --- a/authentik/policies/password/tests/test_zxcvbn.py +++ b/authentik/policies/password/tests/test_zxcvbn.py @@ -1,4 +1,5 @@ """Password Policy zxcvbn tests""" + from django.test import TestCase from guardian.shortcuts import get_anonymous_user diff --git a/authentik/policies/password/urls.py b/authentik/policies/password/urls.py index c979d62ee1..6a4ed1fc24 100644 --- a/authentik/policies/password/urls.py +++ b/authentik/policies/password/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.password.api import PasswordPolicyViewSet api_urlpatterns = [("policies/password", PasswordPolicyViewSet)] diff --git a/authentik/policies/process.py b/authentik/policies/process.py index 61ada16b73..cc208da103 100644 --- a/authentik/policies/process.py +++ b/authentik/policies/process.py @@ -1,7 +1,7 @@ """authentik policy task""" + from multiprocessing import get_context from multiprocessing.connection import Connection -from typing import Optional from django.core.cache import cache from sentry_sdk.hub import Hub @@ -45,7 +45,7 @@ class PolicyProcess(PROCESS_CLASS): self, binding: PolicyBinding, request: PolicyRequest, - connection: Optional[Connection], + connection: Connection | None, ): super().__init__() self.binding = binding @@ -128,8 +128,8 @@ class PolicyProcess(PROCESS_CLASS): binding_order=self.binding.order, binding_target_type=self.binding.target_type, binding_target_name=self.binding.target_name, - object_pk=str(self.request.obj.pk), - object_type=class_to_path(self.request.obj.__class__), + object_pk=str(self.request.obj.pk) if self.request.obj else "", + object_type=class_to_path(self.request.obj.__class__) if self.request.obj else "", mode="execute_process", ).time(), ): @@ -142,6 +142,6 @@ class PolicyProcess(PROCESS_CLASS): """Task wrapper to run policy checking""" try: self.connection.send(self.profiling_wrapper()) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: LOGGER.warning("Policy failed to run", exc=exception_to_string(exc)) self.connection.send(PolicyResult(False, str(exc))) diff --git a/authentik/policies/reputation/api.py b/authentik/policies/reputation/api.py index 885f6c1620..deb66eb1bb 100644 --- a/authentik/policies/reputation/api.py +++ b/authentik/policies/reputation/api.py @@ -1,4 +1,5 @@ """Reputation policy API Views""" + from django.utils.translation import gettext_lazy as _ from rest_framework import mixins from rest_framework.exceptions import ValidationError diff --git a/authentik/policies/reputation/apps.py b/authentik/policies/reputation/apps.py index 94a080a70f..60b2c77b05 100644 --- a/authentik/policies/reputation/apps.py +++ b/authentik/policies/reputation/apps.py @@ -1,6 +1,9 @@ """Authentik reputation_policy app config""" + from authentik.blueprints.apps import ManagedAppConfig +CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/" + class AuthentikPolicyReputationConfig(ManagedAppConfig): """Authentik reputation app config""" @@ -9,11 +12,3 @@ class AuthentikPolicyReputationConfig(ManagedAppConfig): label = "authentik_policies_reputation" verbose_name = "authentik Policies.Reputation" default = True - - def reconcile_global_load_policies_reputation_signals(self): - """Load policies.reputation signals""" - self.import_module("authentik.policies.reputation.signals") - - def reconcile_global_load_policies_reputation_tasks(self): - """Load policies.reputation tasks""" - self.import_module("authentik.policies.reputation.tasks") diff --git a/authentik/policies/reputation/models.py b/authentik/policies/reputation/models.py index ea8ac2bd6c..abcddac2cc 100644 --- a/authentik/policies/reputation/models.py +++ b/authentik/policies/reputation/models.py @@ -1,4 +1,5 @@ """authentik reputation request policy""" + from datetime import timedelta from uuid import uuid4 @@ -18,7 +19,6 @@ from authentik.policies.types import PolicyRequest, PolicyResult from authentik.root.middleware import ClientIPMiddleware LOGGER = get_logger() -CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/" def reputation_expiry(): diff --git a/authentik/policies/reputation/settings.py b/authentik/policies/reputation/settings.py index b51ecc1879..72abd27cf7 100644 --- a/authentik/policies/reputation/settings.py +++ b/authentik/policies/reputation/settings.py @@ -1,4 +1,5 @@ """Reputation Settings""" + from celery.schedules import crontab CELERY_BEAT_SCHEDULE = { diff --git a/authentik/policies/reputation/signals.py b/authentik/policies/reputation/signals.py index 5307672d45..5830143372 100644 --- a/authentik/policies/reputation/signals.py +++ b/authentik/policies/reputation/signals.py @@ -1,4 +1,5 @@ """authentik reputation request signals""" + from django.contrib.auth.signals import user_logged_in from django.core.cache import cache from django.dispatch import receiver @@ -7,7 +8,7 @@ from structlog.stdlib import get_logger from authentik.core.signals import login_failed from authentik.lib.config import CONFIG -from authentik.policies.reputation.models import CACHE_KEY_PREFIX +from authentik.policies.reputation.apps import CACHE_KEY_PREFIX from authentik.policies.reputation.tasks import save_reputation from authentik.root.middleware import ClientIPMiddleware from authentik.stages.identification.signals import identification_failed diff --git a/authentik/policies/reputation/tasks.py b/authentik/policies/reputation/tasks.py index 94d080d7c9..fcdceaa7e4 100644 --- a/authentik/policies/reputation/tasks.py +++ b/authentik/policies/reputation/tasks.py @@ -1,4 +1,5 @@ """Reputation tasks""" + from django.core.cache import cache from structlog.stdlib import get_logger @@ -6,8 +7,8 @@ from authentik.events.context_processors.asn import ASN_CONTEXT_PROCESSOR from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR from authentik.events.models import TaskStatus from authentik.events.system_tasks import SystemTask, prefill_task +from authentik.policies.reputation.apps import CACHE_KEY_PREFIX from authentik.policies.reputation.models import Reputation -from authentik.policies.reputation.signals import CACHE_KEY_PREFIX from authentik.root.celery import CELERY_APP LOGGER = get_logger() diff --git a/authentik/policies/reputation/tests.py b/authentik/policies/reputation/tests.py index 76a8cea4a5..534d808bf7 100644 --- a/authentik/policies/reputation/tests.py +++ b/authentik/policies/reputation/tests.py @@ -1,11 +1,13 @@ """test reputation signals and policy""" + from django.core.cache import cache from django.test import RequestFactory, TestCase from authentik.core.models import User from authentik.lib.generators import generate_id from authentik.policies.reputation.api import ReputationPolicySerializer -from authentik.policies.reputation.models import CACHE_KEY_PREFIX, Reputation, ReputationPolicy +from authentik.policies.reputation.apps import CACHE_KEY_PREFIX +from authentik.policies.reputation.models import Reputation, ReputationPolicy from authentik.policies.reputation.tasks import save_reputation from authentik.policies.types import PolicyRequest from authentik.stages.password import BACKEND_INBUILT diff --git a/authentik/policies/reputation/urls.py b/authentik/policies/reputation/urls.py index 7af81ae5c4..b3f1d55ad2 100644 --- a/authentik/policies/reputation/urls.py +++ b/authentik/policies/reputation/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.reputation.api import ReputationPolicyViewSet, ReputationViewSet api_urlpatterns = [ diff --git a/authentik/policies/signals.py b/authentik/policies/signals.py index 767d733cbd..7b806eeacc 100644 --- a/authentik/policies/signals.py +++ b/authentik/policies/signals.py @@ -1,4 +1,5 @@ """authentik policy signals""" + from django.core.cache import cache from django.db import connection from django.db.models.signals import post_save diff --git a/authentik/policies/tests/test_bindings_api.py b/authentik/policies/tests/test_bindings_api.py index 17046d6caa..3d1c42bba6 100644 --- a/authentik/policies/tests/test_bindings_api.py +++ b/authentik/policies/tests/test_bindings_api.py @@ -1,4 +1,5 @@ """Test bindings API""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/policies/tests/test_engine.py b/authentik/policies/tests/test_engine.py index d173e40ac4..89b49ef1cb 100644 --- a/authentik/policies/tests/test_engine.py +++ b/authentik/policies/tests/test_engine.py @@ -1,4 +1,5 @@ """policy engine tests""" + from django.core.cache import cache from django.test import TestCase diff --git a/authentik/policies/tests/test_policies_api.py b/authentik/policies/tests/test_policies_api.py index ecb83925b8..ad9f9fe23f 100644 --- a/authentik/policies/tests/test_policies_api.py +++ b/authentik/policies/tests/test_policies_api.py @@ -1,4 +1,5 @@ """Test policies API""" + from json import loads from unittest.mock import MagicMock, patch diff --git a/authentik/policies/tests/test_process.py b/authentik/policies/tests/test_process.py index 6c7c941c7c..20e6db9f51 100644 --- a/authentik/policies/tests/test_process.py +++ b/authentik/policies/tests/test_process.py @@ -1,4 +1,5 @@ """policy process tests""" + from django.contrib.auth.models import AnonymousUser from django.core.cache import cache from django.test import RequestFactory, TestCase diff --git a/authentik/policies/types.py b/authentik/policies/types.py index c9e2e8d869..dd95f6e7d9 100644 --- a/authentik/policies/types.py +++ b/authentik/policies/types.py @@ -1,8 +1,9 @@ """policy structures""" + from __future__ import annotations from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any from django.db.models import Model from django.http import HttpRequest @@ -12,6 +13,7 @@ from authentik.events.context_processors.base import get_context_processors if TYPE_CHECKING: from authentik.core.models import User + from authentik.events.logs import LogEvent from authentik.policies.models import PolicyBinding LOGGER = get_logger() @@ -23,8 +25,8 @@ class PolicyRequest: """Data-class to hold policy request data""" user: User - http_request: Optional[HttpRequest] - obj: Optional[Model] + http_request: HttpRequest | None + obj: Model | None context: dict[str, Any] debug: bool @@ -70,10 +72,10 @@ class PolicyResult: messages: tuple[str, ...] raw_result: Any - source_binding: Optional["PolicyBinding"] - source_results: Optional[list["PolicyResult"]] + source_binding: PolicyBinding | None + source_results: list[PolicyResult] | None - log_messages: Optional[list[dict]] + log_messages: list[LogEvent] | None def __init__(self, passing: bool, *messages: str): self.passing = passing diff --git a/authentik/policies/urls.py b/authentik/policies/urls.py index 377578080e..b8b5ba9191 100644 --- a/authentik/policies/urls.py +++ b/authentik/policies/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.policies.api.bindings import PolicyBindingViewSet from authentik.policies.api.policies import PolicyViewSet diff --git a/authentik/policies/utils.py b/authentik/policies/utils.py index 8ac49024e1..b4332f712a 100644 --- a/authentik/policies/utils.py +++ b/authentik/policies/utils.py @@ -1,4 +1,5 @@ """Policy Utils""" + from typing import Any diff --git a/authentik/policies/views.py b/authentik/policies/views.py index 293be99f72..23cf1cd51b 100644 --- a/authentik/policies/views.py +++ b/authentik/policies/views.py @@ -1,5 +1,6 @@ """authentik access helper classes""" -from typing import Any, Optional + +from typing import Any from django.contrib import messages from django.contrib.auth.mixins import AccessMixin @@ -22,9 +23,9 @@ LOGGER = get_logger() class RequestValidationError(SentryIgnoredException): """Error raised in pre_permission_check, when a request is invalid.""" - response: Optional[HttpResponse] + response: HttpResponse | None - def __init__(self, response: Optional[HttpResponse] = None): + def __init__(self, response: HttpResponse | None = None): super().__init__() if response: self.response = response @@ -94,7 +95,7 @@ class PolicyAccessView(AccessMixin, View): ) def handle_no_permission_authenticated( - self, result: Optional[PolicyResult] = None + self, result: PolicyResult | None = None ) -> HttpResponse: """Function called when user has no permissions but is authenticated""" response = AccessDeniedResponse(self.request) @@ -106,7 +107,7 @@ class PolicyAccessView(AccessMixin, View): """optionally modify the policy request""" return request - def user_has_access(self, user: Optional[User] = None) -> PolicyResult: + def user_has_access(self, user: User | None = None) -> PolicyResult: """Check if user has access to application.""" user = user or self.request.user policy_engine = PolicyEngine(self.application, user or self.request.user, self.request) diff --git a/authentik/providers/ldap/api.py b/authentik/providers/ldap/api.py index 21438ef432..70fa78ccae 100644 --- a/authentik/providers/ldap/api.py +++ b/authentik/providers/ldap/api.py @@ -1,4 +1,5 @@ """LDAPProvider API Views""" + from django.db.models import QuerySet from django.db.models.query import Q from django_filters.filters import BooleanFilter diff --git a/authentik/providers/ldap/apps.py b/authentik/providers/ldap/apps.py index 7adc551ffd..ffd5d75310 100644 --- a/authentik/providers/ldap/apps.py +++ b/authentik/providers/ldap/apps.py @@ -1,4 +1,5 @@ """authentik ldap provider app config""" + from django.apps import AppConfig diff --git a/authentik/providers/ldap/controllers/docker.py b/authentik/providers/ldap/controllers/docker.py index ccb9e0a328..f61066c9c4 100644 --- a/authentik/providers/ldap/controllers/docker.py +++ b/authentik/providers/ldap/controllers/docker.py @@ -1,4 +1,5 @@ """LDAP Provider Docker Controller""" + from authentik.outposts.controllers.base import DeploymentPort from authentik.outposts.controllers.docker import DockerController from authentik.outposts.models import DockerServiceConnection, Outpost diff --git a/authentik/providers/ldap/controllers/kubernetes.py b/authentik/providers/ldap/controllers/kubernetes.py index da55e838ec..e980f6f5d1 100644 --- a/authentik/providers/ldap/controllers/kubernetes.py +++ b/authentik/providers/ldap/controllers/kubernetes.py @@ -1,4 +1,5 @@ """LDAP Provider Kubernetes Controller""" + from authentik.outposts.controllers.base import DeploymentPort from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.models import KubernetesServiceConnection, Outpost diff --git a/authentik/providers/ldap/models.py b/authentik/providers/ldap/models.py index d03f5e1f3e..3288b71498 100644 --- a/authentik/providers/ldap/models.py +++ b/authentik/providers/ldap/models.py @@ -1,7 +1,9 @@ """LDAP Provider""" -from typing import Iterable, Optional + +from collections.abc import Iterable from django.db import models +from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer @@ -81,7 +83,7 @@ class LDAPProvider(OutpostModel, BackchannelProvider): ) @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """LDAP never has a launch URL""" return None @@ -89,6 +91,10 @@ class LDAPProvider(OutpostModel, BackchannelProvider): def component(self) -> str: return "ak-provider-ldap-form" + @property + def icon_url(self) -> str | None: + return static("authentik/sources/ldap.png") + @property def serializer(self) -> type[Serializer]: from authentik.providers.ldap.api import LDAPProviderSerializer diff --git a/authentik/providers/ldap/tests/test_api.py b/authentik/providers/ldap/tests/test_api.py index 1271f7640f..3ecec6dd2c 100644 --- a/authentik/providers/ldap/tests/test_api.py +++ b/authentik/providers/ldap/tests/test_api.py @@ -1,4 +1,5 @@ """LDAP Provider API tests""" + from json import loads from django.urls import reverse diff --git a/authentik/providers/ldap/urls.py b/authentik/providers/ldap/urls.py index ae916f9f74..24c339bfb8 100644 --- a/authentik/providers/ldap/urls.py +++ b/authentik/providers/ldap/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.providers.ldap.api import LDAPOutpostConfigViewSet, LDAPProviderViewSet api_urlpatterns = [ diff --git a/authentik/providers/oauth2/api/providers.py b/authentik/providers/oauth2/api/providers.py index 2b03dc4e67..632fabca5b 100644 --- a/authentik/providers/oauth2/api/providers.py +++ b/authentik/providers/oauth2/api/providers.py @@ -1,21 +1,27 @@ """OAuth2Provider API Views""" + +from copy import copy + from django.urls import reverse from django.utils import timezone -from drf_spectacular.utils import OpenApiResponse, extend_schema +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema +from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action +from rest_framework.exceptions import ValidationError from rest_framework.fields import CharField from rest_framework.generics import get_object_or_404 from rest_framework.request import Request from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet -from authentik.api.decorators import permission_required from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer, PropertyMappingPreviewSerializer from authentik.core.models import Provider from authentik.providers.oauth2.id_token import IDToken from authentik.providers.oauth2.models import AccessToken, OAuth2Provider, ScopeMapping +from authentik.rbac.decorators import permission_required class OAuth2ProviderSerializer(ProviderSerializer): @@ -129,7 +135,7 @@ class OAuth2ProviderViewSet(UsedByMixin, ModelViewSet): kwargs={"application_slug": provider.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: pass return Response(data) @@ -141,23 +147,45 @@ class OAuth2ProviderViewSet(UsedByMixin, ModelViewSet): 200: PropertyMappingPreviewSerializer(), 400: OpenApiResponse(description="Bad request"), }, + parameters=[ + OpenApiParameter( + name="for_user", + location=OpenApiParameter.QUERY, + type=OpenApiTypes.INT, + ) + ], ) @action(detail=True, methods=["GET"]) def preview_user(self, request: Request, pk: int) -> Response: """Preview user data for provider""" provider: OAuth2Provider = self.get_object() + for_user = request.user + if "for_user" in request.query_params: + try: + for_user = ( + get_objects_for_user(request.user, "authentik_core.preview_user") + .filter(pk=request.query_params.get("for_user")) + .first() + ) + if not for_user: + raise ValidationError({"for_user": "User not found"}) + except ValueError: + raise ValidationError({"for_user": "input must be numerical"}) from None + scope_names = ScopeMapping.objects.filter(provider=provider).values_list( "scope_name", flat=True ) + new_request = copy(request._request) + new_request.user = for_user temp_token = IDToken.new( provider, AccessToken( - user=request.user, + user=for_user, provider=provider, _scope=" ".join(scope_names), auth_time=timezone.now(), ), - request, + new_request, ) serializer = PropertyMappingPreviewSerializer(instance={"preview": temp_token.to_dict()}) return Response(serializer.data) diff --git a/authentik/providers/oauth2/api/scopes.py b/authentik/providers/oauth2/api/scopes.py index 5b88b698ac..ccb4a212e7 100644 --- a/authentik/providers/oauth2/api/scopes.py +++ b/authentik/providers/oauth2/api/scopes.py @@ -1,4 +1,5 @@ """OAuth2Provider API Views""" + from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes @@ -7,7 +8,7 @@ from rest_framework.fields import CharField from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet -from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.property_mappings import PropertyMappingSerializer from authentik.core.api.used_by import UsedByMixin from authentik.providers.oauth2.models import ScopeMapping diff --git a/authentik/providers/oauth2/api/tokens.py b/authentik/providers/oauth2/api/tokens.py index 86b12cef70..efe8dd9625 100644 --- a/authentik/providers/oauth2/api/tokens.py +++ b/authentik/providers/oauth2/api/tokens.py @@ -1,4 +1,5 @@ """OAuth2Provider API Views""" + from json import dumps from django_filters.rest_framework import DjangoFilterBackend diff --git a/authentik/providers/oauth2/apps.py b/authentik/providers/oauth2/apps.py index 75a39d7646..1a33aba798 100644 --- a/authentik/providers/oauth2/apps.py +++ b/authentik/providers/oauth2/apps.py @@ -1,4 +1,5 @@ """authentik oauth provider app config""" + from django.apps import AppConfig diff --git a/authentik/providers/oauth2/errors.py b/authentik/providers/oauth2/errors.py index fd124cb91b..e8c5fd9ed8 100644 --- a/authentik/providers/oauth2/errors.py +++ b/authentik/providers/oauth2/errors.py @@ -1,5 +1,5 @@ """OAuth errors""" -from typing import Optional + from urllib.parse import quote, urlparse from django.http import HttpRequest, HttpResponse, HttpResponseRedirect @@ -26,7 +26,7 @@ class OAuth2Error(SentryIgnoredException): def __repr__(self) -> str: return self.error - def to_event(self, message: Optional[str] = None, **kwargs) -> Event: + def to_event(self, message: str | None = None, **kwargs) -> Event: """Create configuration_error Event.""" return Event.new( EventAction.CONFIGURATION_ERROR, @@ -141,14 +141,13 @@ class AuthorizeError(OAuth2Error): ), } - # pylint: disable=too-many-arguments def __init__( self, redirect_uri: str, error: str, grant_type: str, state: str, - description: Optional[str] = None, + description: str | None = None, ): super().__init__() self.error = error diff --git a/authentik/providers/oauth2/id_token.py b/authentik/providers/oauth2/id_token.py index b51116f8d2..7b92804c62 100644 --- a/authentik/providers/oauth2/id_token.py +++ b/authentik/providers/oauth2/id_token.py @@ -1,12 +1,14 @@ """id_token utils""" + from dataclasses import asdict, dataclass, field -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any from django.db import models from django.http import HttpRequest from django.utils import timezone from django.utils.translation import gettext_lazy as _ +from authentik.core.models import default_token_duration from authentik.events.signals import get_login_event from authentik.lib.generators import generate_id from authentik.providers.oauth2.constants import ( @@ -42,7 +44,6 @@ class SubModes(models.TextChoices): @dataclass(slots=True) -# pylint: disable=too-many-instance-attributes class IDToken: """The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains @@ -53,42 +54,43 @@ class IDToken: https://openid.net/specs/openid-connect-core-1_0.html#IDToken""" # Issuer, https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.1 - iss: Optional[str] = None + iss: str | None = None # Subject, https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.2 - sub: Optional[str] = None + sub: str | None = None # Audience, https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.3 - aud: Optional[Union[str, list[str]]] = None + aud: str | list[str] | None = None # Expiration time, https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.4 - exp: Optional[int] = None + exp: int | None = None # Issued at, https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.6 - iat: Optional[int] = None + iat: int | None = None # Time when the authentication occurred, # https://openid.net/specs/openid-connect-core-1_0.html#IDToken - auth_time: Optional[int] = None + auth_time: int | None = None # Authentication Context Class Reference, # https://openid.net/specs/openid-connect-core-1_0.html#IDToken - acr: Optional[str] = ACR_AUTHENTIK_DEFAULT + acr: str | None = ACR_AUTHENTIK_DEFAULT # Authentication Methods References, # https://openid.net/specs/openid-connect-core-1_0.html#IDToken - amr: Optional[list[str]] = None + amr: list[str] | None = None # Code hash value, http://openid.net/specs/openid-connect-core-1_0.html - c_hash: Optional[str] = None + c_hash: str | None = None # Value used to associate a Client session with an ID Token, # http://openid.net/specs/openid-connect-core-1_0.html - nonce: Optional[str] = None + nonce: str | None = None # Access Token hash value, http://openid.net/specs/openid-connect-core-1_0.html - at_hash: Optional[str] = None + at_hash: str | None = None claims: dict[str, Any] = field(default_factory=dict) @staticmethod - # pylint: disable=too-many-locals def new( provider: "OAuth2Provider", token: "BaseGrantModel", request: HttpRequest, **kwargs ) -> "IDToken": """Create ID Token""" id_token = IDToken(provider, token, **kwargs) - id_token.exp = int(token.expires.timestamp()) + id_token.exp = int( + (token.expires if token.expires is not None else default_token_duration()).timestamp() + ) id_token.iss = provider.get_issuer(request) id_token.aud = provider.client_id id_token.claims = {} diff --git a/authentik/providers/oauth2/migrations/0018_alter_accesstoken_expires_and_more.py b/authentik/providers/oauth2/migrations/0018_alter_accesstoken_expires_and_more.py new file mode 100644 index 0000000000..249f2f3778 --- /dev/null +++ b/authentik/providers/oauth2/migrations/0018_alter_accesstoken_expires_and_more.py @@ -0,0 +1,36 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "authentik_providers_oauth2", + "0017_accesstoken_session_id_authorizationcode_session_id_and_more", + ), + ] + + operations = [ + migrations.AlterField( + model_name="accesstoken", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + migrations.AlterField( + model_name="authorizationcode", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + migrations.AlterField( + model_name="devicetoken", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + migrations.AlterField( + model_name="refreshtoken", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + ] diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 2917f607fe..45b2d9e0b8 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -1,11 +1,12 @@ """OAuth Provider Models""" + import base64 import binascii import json from dataclasses import asdict from functools import cached_property from hashlib import sha256 -from typing import Any, Optional +from typing import Any from urllib.parse import urlparse, urlunparse from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey @@ -14,6 +15,7 @@ from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes from dacite.core import from_dict from django.db import models from django.http import HttpRequest +from django.templatetags.static import static from django.urls import reverse from django.utils.translation import gettext_lazy as _ from jwt import encode @@ -232,7 +234,7 @@ class OAuth2Provider(Provider): return private_key, JWTAlgorithms.ES256 raise ValueError(f"Invalid private key type: {type(private_key)}") - def get_issuer(self, request: HttpRequest) -> Optional[str]: + def get_issuer(self, request: HttpRequest) -> str | None: """Get issuer, based on request""" if self.issuer_mode == IssuerMode.GLOBAL: return request.build_absolute_uri(reverse("authentik_core:root-redirect")) @@ -240,17 +242,16 @@ class OAuth2Provider(Provider): url = reverse( "authentik_providers_oauth2:provider-root", kwargs={ - # pylint: disable=no-member "application_slug": self.application.slug, }, ) return request.build_absolute_uri(url) - # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return None @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """Guess launch_url based on first redirect_uri""" if self.redirect_uris == "": return None @@ -262,6 +263,10 @@ class OAuth2Provider(Provider): LOGGER.warning("Failed to format launch url", exc=exc) return None + @property + def icon_url(self) -> str | None: + return static("authentik/sources/openidconnect.svg") + @property def component(self) -> str: return "ak-provider-oauth2-form" @@ -298,6 +303,9 @@ class BaseGrantModel(models.Model): auth_time = models.DateTimeField(verbose_name="Authentication time") session_id = models.CharField(default="", blank=True) + class Meta: + abstract = True + @property def scope(self) -> list[str]: """Return scopes as list of strings""" @@ -307,9 +315,6 @@ class BaseGrantModel(models.Model): def scope(self, value): self._scope = " ".join(value) - class Meta: - abstract = True - class AuthorizationCode(SerializerModel, ExpiringModel, BaseGrantModel): """OAuth2 Authorization Code""" @@ -321,6 +326,13 @@ class AuthorizationCode(SerializerModel, ExpiringModel, BaseGrantModel): max_length=255, null=True, verbose_name=_("Code Challenge Method") ) + class Meta: + verbose_name = _("Authorization Code") + verbose_name_plural = _("Authorization Codes") + + def __str__(self): + return f"Authorization code for {self.provider_id} for user {self.user_id}" + @property def serializer(self) -> Serializer: from authentik.providers.oauth2.api.tokens import ExpiringBaseGrantModelSerializer @@ -337,13 +349,6 @@ class AuthorizationCode(SerializerModel, ExpiringModel, BaseGrantModel): .decode("ascii") ) - class Meta: - verbose_name = _("Authorization Code") - verbose_name_plural = _("Authorization Codes") - - def __str__(self): - return f"Authorization code for {self.provider} for user {self.user}" - class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel): """OAuth2 access token, non-opaque using a JWT as identifier""" @@ -351,6 +356,13 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel): token = models.TextField() _id_token = models.TextField() + class Meta: + verbose_name = _("OAuth2 Access Token") + verbose_name_plural = _("OAuth2 Access Tokens") + + def __str__(self): + return f"Access Token for {self.provider_id} for user {self.user_id}" + @property def id_token(self) -> IDToken: """Load ID Token from json""" @@ -380,13 +392,6 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel): return TokenModelSerializer - class Meta: - verbose_name = _("OAuth2 Access Token") - verbose_name_plural = _("OAuth2 Access Tokens") - - def __str__(self): - return f"Access Token for {self.provider} for user {self.user}" - class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel): """OAuth2 Refresh Token, opaque""" @@ -394,6 +399,13 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel): token = models.TextField(default=generate_client_secret) _id_token = models.TextField(verbose_name=_("ID Token")) + class Meta: + verbose_name = _("OAuth2 Refresh Token") + verbose_name_plural = _("OAuth2 Refresh Tokens") + + def __str__(self): + return f"Refresh Token for {self.provider_id} for user {self.user_id}" + @property def id_token(self) -> IDToken: """Load ID Token from json""" @@ -410,13 +422,6 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel): return TokenModelSerializer - class Meta: - verbose_name = _("OAuth2 Refresh Token") - verbose_name_plural = _("OAuth2 Refresh Tokens") - - def __str__(self): - return f"Refresh Token for {self.provider} for user {self.user}" - class DeviceToken(ExpiringModel): """Temporary device token for OAuth device flow""" @@ -443,4 +448,4 @@ class DeviceToken(ExpiringModel): verbose_name_plural = _("Device Tokens") def __str__(self): - return f"Device Token for {self.provider}" + return f"Device Token for {self.provider_id}" diff --git a/authentik/providers/oauth2/tests/test_api.py b/authentik/providers/oauth2/tests/test_api.py index 5aecb3a0eb..827b68b0c4 100644 --- a/authentik/providers/oauth2/tests/test_api.py +++ b/authentik/providers/oauth2/tests/test_api.py @@ -1,4 +1,5 @@ """Test OAuth2 API""" + from json import loads from sys import version_info from unittest import skipUnless diff --git a/authentik/providers/oauth2/tests/test_authorize.py b/authentik/providers/oauth2/tests/test_authorize.py index cc82c3b9c3..36da518536 100644 --- a/authentik/providers/oauth2/tests/test_authorize.py +++ b/authentik/providers/oauth2/tests/test_authorize.py @@ -1,4 +1,5 @@ """Test authorize view""" + from unittest.mock import MagicMock, patch from django.test import RequestFactory @@ -35,8 +36,21 @@ class TestAuthorize(OAuthTestCase): def test_invalid_grant_type(self): """Test with invalid grant type""" + OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + authorization_flow=create_test_flow(), + redirect_uris="http://local.invalid/Foo", + ) with self.assertRaises(AuthorizeError): - request = self.factory.get("/", data={"response_type": "invalid"}) + request = self.factory.get( + "/", + data={ + "response_type": "invalid", + "client_id": "test", + "redirect_uri": "http://local.invalid/Foo", + }, + ) OAuthAuthorizationParams.from_request(request) def test_invalid_client_id(self): @@ -343,7 +357,12 @@ class TestAuthorize(OAuthTestCase): ] ) ) - Application.objects.create(name="app", slug="app", provider=provider) + provider.property_mappings.add( + ScopeMapping.objects.create( + name=generate_id(), scope_name="test", expression="""return {"sub": "foo"}""" + ) + ) + Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider) state = generate_id() user = create_test_admin_user() self.client.force_login(user) @@ -364,7 +383,7 @@ class TestAuthorize(OAuthTestCase): "response_type": "id_token", "client_id": "test", "state": state, - "scope": "openid", + "scope": "openid test", "redirect_uri": "http://localhost", "nonce": generate_id(), }, @@ -389,6 +408,7 @@ class TestAuthorize(OAuthTestCase): ) jwt = self.validate_jwt(token, provider) self.assertEqual(jwt["amr"], ["pwd"]) + self.assertEqual(jwt["sub"], "foo") self.assertAlmostEqual( jwt["exp"] - now().timestamp(), expires, diff --git a/authentik/providers/oauth2/tests/test_device_backchannel.py b/authentik/providers/oauth2/tests/test_device_backchannel.py index a191e128bf..6a30ce0310 100644 --- a/authentik/providers/oauth2/tests/test_device_backchannel.py +++ b/authentik/providers/oauth2/tests/test_device_backchannel.py @@ -1,4 +1,5 @@ """Device backchannel tests""" + from json import loads from django.urls import reverse diff --git a/authentik/providers/oauth2/tests/test_device_init.py b/authentik/providers/oauth2/tests/test_device_init.py index 5e36492014..9a763d9853 100644 --- a/authentik/providers/oauth2/tests/test_device_init.py +++ b/authentik/providers/oauth2/tests/test_device_init.py @@ -1,4 +1,5 @@ """Device init tests""" + from urllib.parse import urlencode from django.urls import reverse diff --git a/authentik/providers/oauth2/tests/test_introspect.py b/authentik/providers/oauth2/tests/test_introspect.py index dd35d5f6f9..26a8001644 100644 --- a/authentik/providers/oauth2/tests/test_introspect.py +++ b/authentik/providers/oauth2/tests/test_introspect.py @@ -1,4 +1,5 @@ """Test introspect view""" + import json from base64 import b64encode from dataclasses import asdict diff --git a/authentik/providers/oauth2/tests/test_jwks.py b/authentik/providers/oauth2/tests/test_jwks.py index 2a678b4a9a..0858df08e4 100644 --- a/authentik/providers/oauth2/tests/test_jwks.py +++ b/authentik/providers/oauth2/tests/test_jwks.py @@ -1,4 +1,5 @@ """JWKS tests""" + import base64 import json @@ -9,6 +10,7 @@ from jwt import PyJWKSet from authentik.core.models import Application from authentik.core.tests.utils import create_test_cert, create_test_flow +from authentik.crypto.builder import PrivateKeyAlg from authentik.crypto.models import CertificateKeyPair from authentik.lib.generators import generate_id from authentik.providers.oauth2.models import OAuth2Provider @@ -81,7 +83,7 @@ class TestJWKS(OAuthTestCase): client_id="test", authorization_flow=create_test_flow(), redirect_uris="http://local.invalid", - signing_key=create_test_cert(use_ec_private_key=True), + signing_key=create_test_cert(PrivateKeyAlg.ECDSA), ) app = Application.objects.create(name="test", slug="test", provider=provider) response = self.client.get( diff --git a/authentik/providers/oauth2/tests/test_revoke.py b/authentik/providers/oauth2/tests/test_revoke.py index 74acbec02f..a0312ef71a 100644 --- a/authentik/providers/oauth2/tests/test_revoke.py +++ b/authentik/providers/oauth2/tests/test_revoke.py @@ -1,4 +1,5 @@ """Test revoke view""" + import json from base64 import b64encode from dataclasses import asdict diff --git a/authentik/providers/oauth2/tests/test_token.py b/authentik/providers/oauth2/tests/test_token.py index 5904d38be4..0e3f074f6c 100644 --- a/authentik/providers/oauth2/tests/test_token.py +++ b/authentik/providers/oauth2/tests/test_token.py @@ -1,4 +1,5 @@ """Test token view""" + from base64 import b64encode from json import dumps @@ -207,7 +208,7 @@ class TestToken(OAuthTestCase): "token_type": TOKEN_TYPE, "expires_in": 3600, "id_token": provider.encode( - refresh.id_token.to_dict(), + access.id_token.to_dict(), ), }, ) @@ -266,7 +267,7 @@ class TestToken(OAuthTestCase): "token_type": TOKEN_TYPE, "expires_in": 3600, "id_token": provider.encode( - refresh.id_token.to_dict(), + access.id_token.to_dict(), ), }, ) diff --git a/authentik/providers/oauth2/tests/test_token_cc_jwt_source.py b/authentik/providers/oauth2/tests/test_token_cc_jwt_source.py index a95c7c3a5a..df508ce311 100644 --- a/authentik/providers/oauth2/tests/test_token_cc_jwt_source.py +++ b/authentik/providers/oauth2/tests/test_token_cc_jwt_source.py @@ -1,4 +1,5 @@ """Test token view""" + from datetime import datetime, timedelta from json import loads diff --git a/authentik/providers/oauth2/tests/test_token_cc_standard.py b/authentik/providers/oauth2/tests/test_token_cc_standard.py new file mode 100644 index 0000000000..7b233794cd --- /dev/null +++ b/authentik/providers/oauth2/tests/test_token_cc_standard.py @@ -0,0 +1,170 @@ +"""Test token view""" + +from json import loads + +from django.test import RequestFactory +from django.urls import reverse +from jwt import decode + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, Token, TokenIntents, UserTypes +from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow +from authentik.policies.models import PolicyBinding +from authentik.providers.oauth2.constants import ( + GRANT_TYPE_CLIENT_CREDENTIALS, + GRANT_TYPE_PASSWORD, + SCOPE_OPENID, + SCOPE_OPENID_EMAIL, + SCOPE_OPENID_PROFILE, + TOKEN_TYPE, +) +from authentik.providers.oauth2.errors import TokenError +from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping +from authentik.providers.oauth2.tests.utils import OAuthTestCase + + +class TestTokenClientCredentialsStandard(OAuthTestCase): + """Test token (client_credentials) view""" + + @apply_blueprint("system/providers-oauth2.yaml") + def setUp(self) -> None: + super().setUp() + self.factory = RequestFactory() + self.provider = OAuth2Provider.objects.create( + name="test", + authorization_flow=create_test_flow(), + redirect_uris="http://testserver", + signing_key=create_test_cert(), + ) + self.provider.property_mappings.set(ScopeMapping.objects.all()) + self.app = Application.objects.create(name="test", slug="test", provider=self.provider) + self.user = create_test_admin_user("sa") + self.user.type = UserTypes.SERVICE_ACCOUNT + self.user.save() + self.token = Token.objects.create( + identifier="sa-token", + user=self.user, + intent=TokenIntents.INTENT_APP_PASSWORD, + expiring=False, + ) + + def test_wrong_user(self): + """test invalid username""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": self.provider.client_secret + "foo", + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_no_provider(self): + """test no provider""" + self.app.provider = None + self.app.save() + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": self.provider.client_secret, + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_permission_denied(self): + """test permission denied""" + group = Group.objects.create(name="foo") + PolicyBinding.objects.create( + group=group, + target=self.app, + order=0, + ) + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": self.provider.client_secret, + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_successful(self): + """test successful""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}", + "client_id": self.provider.client_id, + "client_secret": self.provider.client_secret, + }, + ) + self.assertEqual(response.status_code, 200) + body = loads(response.content.decode()) + self.assertEqual(body["token_type"], TOKEN_TYPE) + _, alg = self.provider.jwt_key + jwt = decode( + body["access_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual( + jwt["given_name"], "Autogenerated user from application test (client credentials)" + ) + self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials") + jwt = decode( + body["id_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual( + jwt["given_name"], "Autogenerated user from application test (client credentials)" + ) + self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials") + + def test_successful_password(self): + """test successful (password grant)""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_PASSWORD, + "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}", + "client_id": self.provider.client_id, + "client_secret": self.provider.client_secret, + }, + ) + self.assertEqual(response.status_code, 200) + body = loads(response.content.decode()) + self.assertEqual(body["token_type"], TOKEN_TYPE) + _, alg = self.provider.jwt_key + jwt = decode( + body["access_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual( + jwt["given_name"], "Autogenerated user from application test (client credentials)" + ) + self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials") diff --git a/authentik/providers/oauth2/tests/test_token_cc_standard_compat.py b/authentik/providers/oauth2/tests/test_token_cc_standard_compat.py new file mode 100644 index 0000000000..1c54ad38f1 --- /dev/null +++ b/authentik/providers/oauth2/tests/test_token_cc_standard_compat.py @@ -0,0 +1,182 @@ +"""Test token view""" + +from base64 import b64encode +from json import loads + +from django.test import RequestFactory +from django.urls import reverse +from jwt import decode + +from authentik.blueprints.tests import apply_blueprint +from authentik.core.models import Application, Group, Token, TokenIntents, UserTypes +from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow +from authentik.policies.models import PolicyBinding +from authentik.providers.oauth2.constants import ( + GRANT_TYPE_CLIENT_CREDENTIALS, + GRANT_TYPE_PASSWORD, + SCOPE_OPENID, + SCOPE_OPENID_EMAIL, + SCOPE_OPENID_PROFILE, + TOKEN_TYPE, +) +from authentik.providers.oauth2.errors import TokenError +from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping +from authentik.providers.oauth2.tests.utils import OAuthTestCase + + +class TestTokenClientCredentialsStandardCompat(OAuthTestCase): + """Test token (client_credentials) view""" + + @apply_blueprint("system/providers-oauth2.yaml") + def setUp(self) -> None: + super().setUp() + self.factory = RequestFactory() + self.provider = OAuth2Provider.objects.create( + name="test", + authorization_flow=create_test_flow(), + redirect_uris="http://testserver", + signing_key=create_test_cert(), + ) + self.provider.property_mappings.set(ScopeMapping.objects.all()) + self.app = Application.objects.create(name="test", slug="test", provider=self.provider) + self.user = create_test_admin_user("sa") + self.user.type = UserTypes.SERVICE_ACCOUNT + self.user.save() + self.token = Token.objects.create( + identifier="sa-token", + user=self.user, + intent=TokenIntents.INTENT_APP_PASSWORD, + expiring=False, + ) + + def test_wrong_user(self): + """test invalid username""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": b64encode(f"saa:{self.token.key}".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_wrong_token(self): + """test invalid token""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": b64encode(f"sa:{self.token.key}foo".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_no_provider(self): + """test no provider""" + self.app.provider = None + self.app.save() + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": b64encode(f"sa:{self.token.key}".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_permission_denied(self): + """test permission denied""" + group = Group.objects.create(name="foo") + PolicyBinding.objects.create( + group=group, + target=self.app, + order=0, + ) + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": SCOPE_OPENID, + "client_id": self.provider.client_id, + "client_secret": b64encode(f"sa:{self.token.key}".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 400) + self.assertJSONEqual( + response.content.decode(), + {"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]}, + ) + + def test_successful(self): + """test successful""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS, + "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}", + "client_id": self.provider.client_id, + "client_secret": b64encode(f"sa:{self.token.key}".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 200) + body = loads(response.content.decode()) + self.assertEqual(body["token_type"], TOKEN_TYPE) + _, alg = self.provider.jwt_key + jwt = decode( + body["access_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual(jwt["given_name"], self.user.name) + self.assertEqual(jwt["preferred_username"], self.user.username) + jwt = decode( + body["id_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual(jwt["given_name"], self.user.name) + self.assertEqual(jwt["preferred_username"], self.user.username) + + def test_successful_password(self): + """test successful (password grant)""" + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + { + "grant_type": GRANT_TYPE_PASSWORD, + "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}", + "client_id": self.provider.client_id, + "client_secret": b64encode(f"sa:{self.token.key}".encode()).decode(), + }, + ) + self.assertEqual(response.status_code, 200) + body = loads(response.content.decode()) + self.assertEqual(body["token_type"], TOKEN_TYPE) + _, alg = self.provider.jwt_key + jwt = decode( + body["access_token"], + key=self.provider.signing_key.public_key, + algorithms=[alg], + audience=self.provider.client_id, + ) + self.assertEqual(jwt["given_name"], self.user.name) + self.assertEqual(jwt["preferred_username"], self.user.username) diff --git a/authentik/providers/oauth2/tests/test_token_cc.py b/authentik/providers/oauth2/tests/test_token_cc_user_pw.py similarity index 99% rename from authentik/providers/oauth2/tests/test_token_cc.py rename to authentik/providers/oauth2/tests/test_token_cc_user_pw.py index 81f595d63c..0af554c2b2 100644 --- a/authentik/providers/oauth2/tests/test_token_cc.py +++ b/authentik/providers/oauth2/tests/test_token_cc_user_pw.py @@ -1,4 +1,5 @@ """Test token view""" + from json import loads from django.test import RequestFactory @@ -22,7 +23,7 @@ from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping from authentik.providers.oauth2.tests.utils import OAuthTestCase -class TestTokenClientCredentials(OAuthTestCase): +class TestTokenClientCredentialsUserNamePassword(OAuthTestCase): """Test token (client_credentials) view""" @apply_blueprint("system/providers-oauth2.yaml") diff --git a/authentik/providers/oauth2/tests/test_token_device.py b/authentik/providers/oauth2/tests/test_token_device.py index 0d7474f927..308b8d2d28 100644 --- a/authentik/providers/oauth2/tests/test_token_device.py +++ b/authentik/providers/oauth2/tests/test_token_device.py @@ -1,4 +1,5 @@ """Test token view""" + from json import loads from django.test import RequestFactory diff --git a/authentik/providers/oauth2/tests/test_token_pkce.py b/authentik/providers/oauth2/tests/test_token_pkce.py index 23bcf359fa..f892ee4bd8 100644 --- a/authentik/providers/oauth2/tests/test_token_pkce.py +++ b/authentik/providers/oauth2/tests/test_token_pkce.py @@ -1,4 +1,5 @@ """Test token view""" + from base64 import b64encode, urlsafe_b64encode from hashlib import sha256 @@ -22,8 +23,9 @@ class TestTokenPKCE(OAuthTestCase): self.factory = RequestFactory() self.app = Application.objects.create(name=generate_id(), slug="test") - def test_pkce_missing_in_token(self): - """Test full with pkce""" + def test_pkce_missing_in_authorize(self): + """Test PKCE with code_challenge in authorize request + and missing verifier in token request""" flow = create_test_flow() provider = OAuth2Provider.objects.create( name=generate_id(), @@ -74,7 +76,77 @@ class TestTokenPKCE(OAuthTestCase): ) self.assertJSONEqual( response.content, - {"error": "invalid_request", "error_description": "The request is otherwise malformed"}, + { + "error": "invalid_grant", + "error_description": ( + "The provided authorization grant or refresh token is invalid, expired, " + "revoked, does not match the redirection URI used in the authorization " + "request, or was issued to another client" + ), + }, + ) + self.assertEqual(response.status_code, 400) + + def test_pkce_missing_in_token(self): + """Test PKCE with missing code_challenge in authorization request but verifier + set in token request""" + flow = create_test_flow() + provider = OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + authorization_flow=flow, + redirect_uris="foo://localhost", + access_code_validity="seconds=100", + ) + Application.objects.create(name="app", slug="app", provider=provider) + state = generate_id() + user = create_test_admin_user() + self.client.force_login(user) + header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode() + # Step 1, initiate params and get redirect to flow + self.client.get( + reverse("authentik_providers_oauth2:authorize"), + data={ + "response_type": "code", + "client_id": "test", + "state": state, + "redirect_uri": "foo://localhost", + # "code_challenge": challenge, + # "code_challenge_method": "S256", + }, + ) + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + ) + code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first() + self.assertJSONEqual( + response.content.decode(), + { + "component": "xak-flow-redirect", + "type": ChallengeTypes.REDIRECT.value, + "to": f"foo://localhost?code={code.code}&state={state}", + }, + ) + response = self.client.post( + reverse("authentik_providers_oauth2:token"), + data={ + "grant_type": GRANT_TYPE_AUTHORIZATION_CODE, + "code": code.code, + "code_verifier": generate_id(), + "redirect_uri": "foo://localhost", + }, + HTTP_AUTHORIZATION=f"Basic {header}", + ) + self.assertJSONEqual( + response.content, + { + "error": "invalid_grant", + "error_description": ( + "The provided authorization grant or refresh token is invalid, expired, " + "revoked, does not match the redirection URI used in the authorization " + "request, or was issued to another client" + ), + }, ) self.assertEqual(response.status_code, 400) diff --git a/authentik/providers/oauth2/tests/test_userinfo.py b/authentik/providers/oauth2/tests/test_userinfo.py index 431b2f18f7..96e48754f7 100644 --- a/authentik/providers/oauth2/tests/test_userinfo.py +++ b/authentik/providers/oauth2/tests/test_userinfo.py @@ -1,4 +1,5 @@ """Test userinfo view""" + import json from dataclasses import asdict diff --git a/authentik/providers/oauth2/tests/utils.py b/authentik/providers/oauth2/tests/utils.py index 77bad32529..8904f0224d 100644 --- a/authentik/providers/oauth2/tests/utils.py +++ b/authentik/providers/oauth2/tests/utils.py @@ -1,4 +1,5 @@ """OAuth test helpers""" + from typing import Any from django.test import TestCase diff --git a/authentik/providers/oauth2/urls.py b/authentik/providers/oauth2/urls.py index f310fa1bc1..9eefeb582e 100644 --- a/authentik/providers/oauth2/urls.py +++ b/authentik/providers/oauth2/urls.py @@ -1,4 +1,5 @@ """OAuth provider URLs""" + from django.urls import path from django.views.generic.base import RedirectView diff --git a/authentik/providers/oauth2/urls_root.py b/authentik/providers/oauth2/urls_root.py index 9f7fe05ac8..02d89e9dd6 100644 --- a/authentik/providers/oauth2/urls_root.py +++ b/authentik/providers/oauth2/urls_root.py @@ -1,4 +1,5 @@ """authentik oauth_provider urls""" + from django.contrib.auth.decorators import login_required from django.urls import include, path diff --git a/authentik/providers/oauth2/utils.py b/authentik/providers/oauth2/utils.py index 513994b805..5f36a3f891 100644 --- a/authentik/providers/oauth2/utils.py +++ b/authentik/providers/oauth2/utils.py @@ -1,8 +1,9 @@ """OAuth2/OpenID Utils""" + import re from base64 import b64decode from binascii import Error -from typing import Any, Optional +from typing import Any from urllib.parse import urlparse from django.http import HttpRequest, HttpResponse, JsonResponse @@ -72,7 +73,7 @@ def cors_allow(request: HttpRequest, response: HttpResponse, *allowed_origins: s return response -def extract_access_token(request: HttpRequest) -> Optional[str]: +def extract_access_token(request: HttpRequest) -> str | None: """ Get the access token using Authorization Request Header Field method. Or try getting via GET. @@ -161,14 +162,14 @@ def protected_resource_view(scopes: list[str]): raise BearerTokenError("insufficient_scope") except BearerTokenError as error: response = HttpResponse(status=error.status) - response[ - "WWW-Authenticate" - ] = f'error="{error.code}", error_description="{error.description}"' + response["WWW-Authenticate"] = ( + f'error="{error.code}", error_description="{error.description}"' + ) return response kwargs["token"] = token CTX_AUTH_VIA.set("oauth_token") response = view(request, *args, **kwargs) - setattr(response, "ak_context", {}) + response.ak_context = {} response.ak_context[KEY_USER] = token.user.username return response @@ -177,12 +178,12 @@ def protected_resource_view(scopes: list[str]): return wrapper -def authenticate_provider(request: HttpRequest) -> Optional[OAuth2Provider]: +def authenticate_provider(request: HttpRequest) -> OAuth2Provider | None: """Attempt to authenticate via Basic auth of client_id:client_secret""" client_id, client_secret = extract_client_auth(request) if client_id == client_secret == "": return None - provider: Optional[OAuth2Provider] = OAuth2Provider.objects.filter(client_id=client_id).first() + provider: OAuth2Provider | None = OAuth2Provider.objects.filter(client_id=client_id).first() if not provider: return None if client_id != provider.client_id or client_secret != provider.client_secret: @@ -199,7 +200,7 @@ class HttpResponseRedirectScheme(HttpResponseRedirect): self, redirect_to: str, *args: Any, - allowed_schemes: Optional[list[str]] = None, + allowed_schemes: list[str] | None = None, **kwargs: Any, ) -> None: self.allowed_schemes = allowed_schemes or ["http", "https", "ftp"] diff --git a/authentik/providers/oauth2/views/authorize.py b/authentik/providers/oauth2/views/authorize.py index 0baa942b49..c660f9c58d 100644 --- a/authentik/providers/oauth2/views/authorize.py +++ b/authentik/providers/oauth2/views/authorize.py @@ -1,11 +1,11 @@ """authentik OAuth2 Authorization views""" + from dataclasses import InitVar, dataclass, field from datetime import timedelta from hashlib import sha256 from json import dumps from re import error as RegexError from re import fullmatch -from typing import Optional from urllib.parse import parse_qs, urlencode, urlparse, urlsplit, urlunsplit from uuid import uuid4 @@ -80,28 +80,27 @@ FORBIDDEN_URI_SCHEMES = {"javascript", "data", "vbscript"} @dataclass(slots=True) -# pylint: disable=too-many-instance-attributes class OAuthAuthorizationParams: """Parameters required to authorize an OAuth Client""" client_id: str redirect_uri: str response_type: str - response_mode: Optional[str] + response_mode: str | None scope: set[str] state: str - nonce: Optional[str] + nonce: str | None prompt: set[str] grant_type: str provider: OAuth2Provider = field(default_factory=OAuth2Provider) - request: Optional[str] = None + request: str | None = None - max_age: Optional[int] = None + max_age: int | None = None - code_challenge: Optional[str] = None - code_challenge_method: Optional[str] = None + code_challenge: str | None = None + code_challenge_method: str | None = None github_compat: InitVar[bool] = False @@ -120,44 +119,18 @@ class OAuthAuthorizationParams: redirect_uri = query_dict.get("redirect_uri", "") response_type = query_dict.get("response_type", "") - grant_type = None - # Determine which flow to use. - if response_type in [ResponseTypes.CODE]: - grant_type = GrantTypes.AUTHORIZATION_CODE - elif response_type in [ - ResponseTypes.ID_TOKEN, - ResponseTypes.ID_TOKEN_TOKEN, - ]: - grant_type = GrantTypes.IMPLICIT - elif response_type in [ - ResponseTypes.CODE_TOKEN, - ResponseTypes.CODE_ID_TOKEN, - ResponseTypes.CODE_ID_TOKEN_TOKEN, - ]: - grant_type = GrantTypes.HYBRID - - # Grant type validation. - if not grant_type: - LOGGER.warning("Invalid response type", type=response_type) - raise AuthorizeError(redirect_uri, "unsupported_response_type", "", state) # Validate and check the response_mode against the predefined dict # Set to Query or Fragment if not defined in request response_mode = query_dict.get("response_mode", False) - if response_mode not in ResponseMode.values: - response_mode = ResponseMode.QUERY - - if grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]: - response_mode = ResponseMode.FRAGMENT - max_age = query_dict.get("max_age") return OAuthAuthorizationParams( client_id=query_dict.get("client_id", ""), redirect_uri=redirect_uri, response_type=response_type, response_mode=response_mode, - grant_type=grant_type, + grant_type="", scope=set(query_dict.get("scope", "").split()), state=state, nonce=query_dict.get("nonce"), @@ -177,6 +150,7 @@ class OAuthAuthorizationParams: LOGGER.warning("Invalid client identifier", client_id=self.client_id) raise ClientIdError(client_id=self.client_id) self.check_redirect_uri() + self.check_grant() self.check_scope(github_compat) self.check_nonce() self.check_code_challenge() @@ -185,6 +159,34 @@ class OAuthAuthorizationParams: self.redirect_uri, "request_not_supported", self.grant_type, self.state ) + def check_grant(self): + """Check grant""" + # Determine which flow to use. + if self.response_type in [ResponseTypes.CODE]: + self.grant_type = GrantTypes.AUTHORIZATION_CODE + elif self.response_type in [ + ResponseTypes.ID_TOKEN, + ResponseTypes.ID_TOKEN_TOKEN, + ]: + self.grant_type = GrantTypes.IMPLICIT + elif self.response_type in [ + ResponseTypes.CODE_TOKEN, + ResponseTypes.CODE_ID_TOKEN, + ResponseTypes.CODE_ID_TOKEN_TOKEN, + ]: + self.grant_type = GrantTypes.HYBRID + + # Grant type validation. + if not self.grant_type: + LOGGER.warning("Invalid response type", type=self.response_type) + raise AuthorizeError(self.redirect_uri, "unsupported_response_type", "", self.state) + + if self.response_mode not in ResponseMode.values: + self.response_mode = ResponseMode.QUERY + + if self.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]: + self.response_mode = ResponseMode.FRAGMENT + def check_redirect_uri(self): """Redirect URI validation.""" allowed_redirect_urls = self.provider.redirect_uris.split() @@ -220,7 +222,7 @@ class OAuthAuthorizationParams: redirect_uri_given=self.redirect_uri, redirect_uri_expected=allowed_redirect_urls, ) - raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) + raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) from None # Check against forbidden schemes if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES: raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) @@ -256,9 +258,9 @@ class OAuthAuthorizationParams: if SCOPE_OFFLINE_ACCESS in self.scope: # https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess if PROMPT_CONSENT not in self.prompt: - raise AuthorizeError( - self.redirect_uri, "consent_required", self.grant_type, self.state - ) + # Instead of ignoring the `offline_access` scope when `prompt` + # isn't set to `consent`, we set override it ourselves + self.prompt.add(PROMPT_CONSENT) if self.response_type not in [ ResponseTypes.CODE, ResponseTypes.CODE_TOKEN, @@ -347,14 +349,14 @@ class AuthorizationFlowInitView(PolicyAccessView): ) except AuthorizeError as error: LOGGER.warning(error.description, redirect_uri=error.redirect_uri) - raise RequestValidationError(error.get_response(self.request)) + raise RequestValidationError(error.get_response(self.request)) from None except OAuth2Error as error: LOGGER.warning(error.description) raise RequestValidationError( bad_request_message(self.request, error.description, title=error.error) - ) + ) from None except OAuth2Provider.DoesNotExist: - raise Http404 + raise Http404 from None if PROMPT_NONE in self.params.prompt and not self.request.user.is_authenticated: # When "prompt" is set to "none" but the user is not logged in, show an error message error = AuthorizeError( @@ -486,7 +488,7 @@ class OAuthFulfillmentStage(StageView): "component": "ak-stage-autosubmit", "title": self.executor.plan.context.get( PLAN_CONTEXT_TITLE, - _("Redirecting to %(app)s..." % {"app": self.application.name}), + _("Redirecting to {app}...".format_map({"app": self.application.name})), ), "url": self.params.redirect_uri, "attrs": query_params, @@ -532,7 +534,7 @@ class OAuthFulfillmentStage(StageView): except (ClientIdError, RedirectUriError) as error: error.to_event(application=self.application).from_http(request) self.executor.stage_invalid() - # pylint: disable=no-member + return bad_request_message(request, error.description, title=error.error) except AuthorizeError as error: error.to_event(application=self.application).from_http(request) @@ -595,9 +597,9 @@ class OAuthFulfillmentStage(StageView): "server_error", self.params.grant_type, self.params.state, - ) + ) from None - def create_implicit_response(self, code: Optional[AuthorizationCode]) -> dict: + def create_implicit_response(self, code: AuthorizationCode | None) -> dict: """Create implicit response's URL Fragment dictionary""" query_fragment = {} auth_event = get_login_event(self.request) diff --git a/authentik/providers/oauth2/views/device_backchannel.py b/authentik/providers/oauth2/views/device_backchannel.py index 79f723a737..453ec17fd6 100644 --- a/authentik/providers/oauth2/views/device_backchannel.py +++ b/authentik/providers/oauth2/views/device_backchannel.py @@ -1,5 +1,5 @@ """Device flow views""" -from typing import Optional + from urllib.parse import urlencode from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest, JsonResponse @@ -27,7 +27,7 @@ class DeviceView(View): provider: OAuth2Provider scopes: list[str] = [] - def parse_request(self) -> Optional[HttpResponse]: + def parse_request(self) -> HttpResponse | None: """Parse incoming request""" client_id = self.request.POST.get("client_id", None) if not client_id: diff --git a/authentik/providers/oauth2/views/device_finish.py b/authentik/providers/oauth2/views/device_finish.py index 774ef1df03..61bda6ae3e 100644 --- a/authentik/providers/oauth2/views/device_finish.py +++ b/authentik/providers/oauth2/views/device_finish.py @@ -1,4 +1,5 @@ """Device flow finish stage""" + from django.http import HttpResponse from rest_framework.fields import CharField @@ -24,7 +25,7 @@ class OAuthDeviceCodeFinishChallengeResponse(ChallengeResponse): class OAuthDeviceCodeFinishStage(ChallengeStageView): - """Stage show at the end of a device flow""" + """Stage to finish the OAuth device code flow""" response_class = OAuthDeviceCodeFinishChallengeResponse diff --git a/authentik/providers/oauth2/views/device_init.py b/authentik/providers/oauth2/views/device_init.py index 35123b7450..f6e81b0417 100644 --- a/authentik/providers/oauth2/views/device_init.py +++ b/authentik/providers/oauth2/views/device_init.py @@ -1,10 +1,9 @@ """Device flow views""" -from typing import Optional from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ from django.views import View -from rest_framework.exceptions import ErrorDetail +from rest_framework.exceptions import ValidationError from rest_framework.fields import CharField, IntegerField from structlog.stdlib import get_logger @@ -32,7 +31,7 @@ LOGGER = get_logger() QS_KEY_CODE = "code" # nosec -def get_application(provider: OAuth2Provider) -> Optional[Application]: +def get_application(provider: OAuth2Provider) -> Application | None: """Get application from provider""" try: app = provider.application @@ -43,7 +42,7 @@ def get_application(provider: OAuth2Provider) -> Optional[Application]: return None -def validate_code(code: int, request: HttpRequest) -> Optional[HttpResponse]: +def validate_code(code: int, request: HttpRequest) -> HttpResponse | None: """Validate user token""" token = DeviceToken.objects.filter( user_code=code, @@ -58,6 +57,7 @@ def validate_code(code: int, request: HttpRequest) -> Optional[HttpResponse]: scope_descriptions = UserInfoView().get_scope_descriptions(token.scope, token.provider) planner = FlowPlanner(token.provider.authorization_flow) planner.allow_empty_flows = True + planner.use_cache = False try: plan = planner.plan( request, @@ -129,6 +129,13 @@ class OAuthDeviceCodeChallengeResponse(ChallengeResponse): code = IntegerField() component = CharField(default="ak-provider-oauth2-device-code") + def validate_code(self, code: int) -> HttpResponse | None: + """Validate code and save the returned http response""" + response = validate_code(code, self.stage.request) + if not response: + raise ValidationError(_("Invalid code"), "invalid") + return response + class OAuthDeviceCodeStage(ChallengeStageView): """Flow challenge for users to enter device codes""" @@ -144,12 +151,4 @@ class OAuthDeviceCodeStage(ChallengeStageView): ) def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: - code = response.validated_data["code"] - validation = validate_code(code, self.request) - if not validation: - response._errors.setdefault("code", []) - response._errors["code"].append(ErrorDetail(_("Invalid code"), "invalid")) - return self.challenge_invalid(response) - # Run cancel to cleanup the current flow - self.executor.cancel() - return validation + return response.validated_data["code"] diff --git a/authentik/providers/oauth2/views/introspection.py b/authentik/providers/oauth2/views/introspection.py index ca702eda73..7c2d096f70 100644 --- a/authentik/providers/oauth2/views/introspection.py +++ b/authentik/providers/oauth2/views/introspection.py @@ -1,4 +1,5 @@ """authentik OAuth2 Token Introspection Views""" + from dataclasses import dataclass, field from django.http import HttpRequest, HttpResponse diff --git a/authentik/providers/oauth2/views/jwks.py b/authentik/providers/oauth2/views/jwks.py index 166d583f4e..ea95c4c28c 100644 --- a/authentik/providers/oauth2/views/jwks.py +++ b/authentik/providers/oauth2/views/jwks.py @@ -1,6 +1,6 @@ """authentik OAuth2 JWKS Views""" + from base64 import b64encode, urlsafe_b64encode -from typing import Optional from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.ec import ( @@ -64,7 +64,7 @@ def to_base64url_uint(val: int, min_length: int = 0) -> bytes: class JWKSView(View): """Show RSA Key data for Provider""" - def get_jwk_for_key(self, key: CertificateKeyPair) -> Optional[dict]: + def get_jwk_for_key(self, key: CertificateKeyPair) -> dict | None: """Convert a certificate-key pair into JWK""" private_key = key.private_key key_data = None diff --git a/authentik/providers/oauth2/views/provider.py b/authentik/providers/oauth2/views/provider.py index ab6fbc328e..06bdceab25 100644 --- a/authentik/providers/oauth2/views/provider.py +++ b/authentik/providers/oauth2/views/provider.py @@ -1,4 +1,5 @@ """authentik OAuth2 OpenID well-known views""" + from typing import Any from django.http import HttpRequest, HttpResponse, JsonResponse @@ -7,7 +8,7 @@ from django.views import View from guardian.shortcuts import get_anonymous_user from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.core.models import Application from authentik.providers.oauth2.constants import ( ACR_AUTHENTIK_DEFAULT, diff --git a/authentik/providers/oauth2/views/token.py b/authentik/providers/oauth2/views/token.py index 4168edb1eb..747d6413d7 100644 --- a/authentik/providers/oauth2/views/token.py +++ b/authentik/providers/oauth2/views/token.py @@ -1,11 +1,13 @@ """authentik OAuth2 Token views""" -from base64 import urlsafe_b64encode + +from base64 import b64decode, urlsafe_b64encode +from binascii import Error from dataclasses import InitVar, dataclass from datetime import datetime from hashlib import sha256 from re import error as RegexError from re import fullmatch -from typing import Any, Optional +from typing import Any from urllib.parse import urlparse from django.http import HttpRequest, HttpResponse @@ -22,11 +24,14 @@ from authentik.core.middleware import CTX_AUTH_VIA from authentik.core.models import ( USER_ATTRIBUTE_EXPIRES, USER_ATTRIBUTE_GENERATED, + USER_PATH_SYSTEM_PREFIX, Application, Token, TokenIntents, User, + UserTypes, ) +from authentik.events.middleware import audit_ignore from authentik.events.models import Event, EventAction from authentik.events.signals import get_login_event from authentik.flows.planner import PLAN_CONTEXT_APPLICATION @@ -64,7 +69,6 @@ LOGGER = get_logger() @dataclass(slots=True) -# pylint: disable=too-many-instance-attributes class TokenParams: """Token params""" @@ -77,16 +81,16 @@ class TokenParams: provider: OAuth2Provider - authorization_code: Optional[AuthorizationCode] = None - refresh_token: Optional[RefreshToken] = None - device_code: Optional[DeviceToken] = None - user: Optional[User] = None + authorization_code: AuthorizationCode | None = None + refresh_token: RefreshToken | None = None + device_code: DeviceToken | None = None + user: User | None = None - code_verifier: Optional[str] = None + code_verifier: str | None = None raw_code: InitVar[str] = "" raw_token: InitVar[str] = "" - request: InitVar[Optional[HttpRequest]] = None + request: InitVar[HttpRequest | None] = None @staticmethod def parse( @@ -206,7 +210,7 @@ class TokenParams: message="Invalid redirect_uri configured", provider=self.provider, ).from_http(request) - raise TokenError("invalid_client") + raise TokenError("invalid_client") from None # Check against forbidden schemes if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES: @@ -232,7 +236,7 @@ class TokenParams: if self.authorization_code.code_challenge: # Authorization code had PKCE but we didn't get one if not self.code_verifier: - raise TokenError("invalid_request") + raise TokenError("invalid_grant") if self.authorization_code.code_challenge_method == PKCE_METHOD_S256: new_code_challenge = ( urlsafe_b64encode(sha256(self.code_verifier.encode("ascii")).digest()) @@ -245,6 +249,10 @@ class TokenParams: if new_code_challenge != self.authorization_code.code_challenge: LOGGER.warning("Code challenge not matching") raise TokenError("invalid_grant") + # Token request had a code_verifier but code did not have a code challenge + # Prevent downgrade + if not self.authorization_code.code_challenge and self.code_verifier: + raise TokenError("invalid_grant") def __post_init_refresh(self, raw_token: str, request: HttpRequest): if not raw_token: @@ -281,11 +289,29 @@ class TokenParams: raise TokenError("invalid_grant") def __post_init_client_credentials(self, request: HttpRequest): + # client_credentials flow with client assertion if request.POST.get(CLIENT_ASSERTION_TYPE, "") != "": return self.__post_init_client_credentials_jwt(request) + # authentik-custom-ish client credentials flow + if request.POST.get("username", "") != "": + return self.__post_init_client_credentials_creds( + request, request.POST.get("username"), request.POST.get("password") + ) + # Standard method which creates an automatic user + if self.client_secret == self.provider.client_secret: + return self.__post_init_client_credentials_generated(request) + # Standard workaround method which stores username:password + # as client_secret + try: + user, _, password = b64decode(self.client_secret).decode("utf-8").partition(":") + return self.__post_init_client_credentials_creds(request, user, password) + except (ValueError, Error): + raise TokenError("invalid_grant") from None + + def __post_init_client_credentials_creds( + self, request: HttpRequest, username: str, password: str + ): # Authenticate user based on credentials - username = request.POST.get("username") - password = request.POST.get("password") user = User.objects.filter(username=username).first() if not user: raise TokenError("invalid_grant") @@ -311,9 +337,7 @@ class TokenParams: PLAN_CONTEXT_APPLICATION: app, }, ).from_http(request, user=user) - return None - # pylint: disable=too-many-locals def __post_init_client_credentials_jwt(self, request: HttpRequest): assertion_type = request.POST.get(CLIENT_ASSERTION_TYPE, "") if assertion_type != CLIENT_ASSERTION_TYPE_JWT: @@ -328,8 +352,8 @@ class TokenParams: token = None - source: Optional[OAuthSource] = None - parsed_key: Optional[PyJWK] = None + source: OAuthSource | None = None + parsed_key: PyJWK | None = None # Fully decode the JWT without verifying the signature, so we can get access to # the header. @@ -343,7 +367,7 @@ class TokenParams: ) except (PyJWTError, ValueError, TypeError, AttributeError) as exc: LOGGER.warning("failed to parse JWT for kid lookup", exc=exc) - raise TokenError("invalid_grant") + raise TokenError("invalid_grant") from None expected_kid = decode_unvalidated["header"]["kid"] for source in self.provider.jwks_sources.filter( oidc_jwks__keys__contains=[{"kid": expected_kid}] @@ -404,6 +428,35 @@ class TokenParams: }, ).from_http(request, user=self.user) + def __post_init_client_credentials_generated(self, request: HttpRequest): + # Authorize user access + app = Application.objects.filter(provider=self.provider).first() + if not app or not app.provider: + raise TokenError("invalid_grant") + self.user, _ = User.objects.update_or_create( + # trim username to ensure the entire username is max 150 chars + # (22 chars being the length of the "template") + username=f"ak-{self.provider.name[:150-22]}-client_credentials", + defaults={ + "attributes": { + USER_ATTRIBUTE_GENERATED: True, + }, + "last_login": timezone.now(), + "name": f"Autogenerated user from application {app.name} (client credentials)", + "path": f"{USER_PATH_SYSTEM_PREFIX}/apps/{app.slug}", + "type": UserTypes.SERVICE_ACCOUNT, + }, + ) + self.__check_policy_access(app, request) + + Event.new( + action=EventAction.LOGIN, + **{ + PLAN_CONTEXT_METHOD: "oauth_client_secret", + PLAN_CONTEXT_APPLICATION: app, + }, + ).from_http(request, user=self.user) + def __post_init_device_code(self, request: HttpRequest): device_code = request.POST.get("device_code", "") code = DeviceToken.objects.filter(device_code=device_code, provider=self.provider).first() @@ -413,29 +466,33 @@ class TokenParams: def __create_user_from_jwt(self, token: dict[str, Any], app: Application, source: OAuthSource): """Create user from JWT""" - exp = token.get("exp") - self.user, created = User.objects.update_or_create( - username=f"{self.provider.name}-{token.get('sub')}", - defaults={ - "attributes": { - USER_ATTRIBUTE_GENERATED: True, + with audit_ignore(): + self.user, created = User.objects.update_or_create( + username=f"{self.provider.name}-{token.get('sub')}", + defaults={ + "attributes": { + USER_ATTRIBUTE_GENERATED: True, + }, + "last_login": timezone.now(), + "name": ( + f"Autogenerated user from application {app.name} (client credentials JWT)" + ), + "path": source.get_user_path(), + "type": UserTypes.SERVICE_ACCOUNT, }, - "last_login": timezone.now(), - "name": f"Autogenerated user from application {app.name} (client credentials JWT)", - "path": source.get_user_path(), - }, - ) - if created and exp: - self.user.attributes[USER_ATTRIBUTE_EXPIRES] = exp - self.user.save() + ) + exp = token.get("exp") + if created and exp: + self.user.attributes[USER_ATTRIBUTE_EXPIRES] = exp + self.user.save() @method_decorator(csrf_exempt, name="dispatch") class TokenView(View): """Generate tokens for clients""" - provider: Optional[OAuth2Provider] = None - params: Optional[TokenParams] = None + provider: OAuth2Provider | None = None + params: TokenParams | None = None def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: response = super().dispatch(request, *args, **kwargs) @@ -594,7 +651,7 @@ class TokenView(View): "expires_in": int( timedelta_from_string(self.provider.access_token_validity).total_seconds() ), - "id_token": id_token.to_jwt(self.provider), + "id_token": access_token.id_token.to_jwt(self.provider), } def create_client_credentials_response(self) -> dict[str, Any]: diff --git a/authentik/providers/oauth2/views/token_revoke.py b/authentik/providers/oauth2/views/token_revoke.py index e4a5bd0788..c0809ba725 100644 --- a/authentik/providers/oauth2/views/token_revoke.py +++ b/authentik/providers/oauth2/views/token_revoke.py @@ -1,4 +1,5 @@ """Token revocation endpoint""" + from dataclasses import dataclass from django.http import Http404, HttpRequest, HttpResponse diff --git a/authentik/providers/oauth2/views/userinfo.py b/authentik/providers/oauth2/views/userinfo.py index 061e43fc8e..2a569308de 100644 --- a/authentik/providers/oauth2/views/userinfo.py +++ b/authentik/providers/oauth2/views/userinfo.py @@ -1,5 +1,6 @@ """authentik OAuth2 OpenID Userinfo views""" -from typing import Any, Optional + +from typing import Any from deepmerge import always_merger from django.http import HttpRequest, HttpResponse @@ -10,7 +11,7 @@ from django.views import View from django.views.decorators.csrf import csrf_exempt from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.events.models import Event, EventAction from authentik.flows.challenge import PermissionDict from authentik.providers.oauth2.constants import ( @@ -38,7 +39,7 @@ class UserInfoView(View): """Create a dictionary with all the requested claims about the End-User. See: http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse""" - token: Optional[RefreshToken] + token: RefreshToken | None def get_scope_descriptions( self, scopes: list[str], provider: OAuth2Provider @@ -100,8 +101,8 @@ class UserInfoView(View): value=value, ) continue - LOGGER.debug("updated scope", scope=scope) always_merger.merge(final_claims, value) + LOGGER.debug("updated scope", scope=scope) return final_claims def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: @@ -120,8 +121,9 @@ class UserInfoView(View): """Handle GET Requests for UserInfo""" if not self.token: return HttpResponseBadRequest() - claims = self.get_claims(self.token.provider, self.token) - claims["sub"] = self.token.id_token.sub + claims = {} + claims.setdefault("sub", self.token.id_token.sub) + claims.update(self.get_claims(self.token.provider, self.token)) if self.token.id_token.nonce: claims["nonce"] = self.token.id_token.nonce response = TokenResponse(claims) diff --git a/authentik/providers/proxy/api.py b/authentik/providers/proxy/api.py index 30f77d83d1..70c81d6d4c 100644 --- a/authentik/providers/proxy/api.py +++ b/authentik/providers/proxy/api.py @@ -1,5 +1,6 @@ """ProxyProvider API Views""" -from typing import Any, Optional + +from typing import Any from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema_field @@ -142,7 +143,7 @@ class ProxyOutpostConfigSerializer(ModelSerializer): """Embed OpenID Connect provider information""" return ProviderInfoView(request=self.context["request"]._request).get_info(obj) - def get_access_token_validity(self, obj: ProxyProvider) -> Optional[float]: + def get_access_token_validity(self, obj: ProxyProvider) -> float | None: """Get token validity as second count""" return timedelta_from_string(obj.access_token_validity).total_seconds() diff --git a/authentik/providers/proxy/apps.py b/authentik/providers/proxy/apps.py index 2149bc7eff..c5a384f748 100644 --- a/authentik/providers/proxy/apps.py +++ b/authentik/providers/proxy/apps.py @@ -1,4 +1,5 @@ """authentik Proxy app""" + from authentik.blueprints.apps import ManagedAppConfig @@ -9,7 +10,3 @@ class AuthentikProviderProxyConfig(ManagedAppConfig): label = "authentik_providers_proxy" verbose_name = "authentik Providers.Proxy" default = True - - def reconcile_global_load_providers_proxy_signals(self): - """Load proxy signals""" - self.import_module("authentik.providers.proxy.signals") diff --git a/authentik/providers/proxy/controllers/docker.py b/authentik/providers/proxy/controllers/docker.py index 32cc9ff337..a95f699599 100644 --- a/authentik/providers/proxy/controllers/docker.py +++ b/authentik/providers/proxy/controllers/docker.py @@ -1,4 +1,5 @@ """Proxy Provider Docker Controller""" + from urllib.parse import urlparse from authentik.outposts.controllers.base import DeploymentPort @@ -26,16 +27,16 @@ class ProxyDockerController(DockerController): traefik_name = self.name labels = super()._get_labels() labels["traefik.enable"] = "true" - labels[ - f"traefik.http.routers.{traefik_name}-router.rule" - ] = f"Host({','.join(hosts)}) && PathPrefix(`/outpost.goauthentik.io`)" + labels[f"traefik.http.routers.{traefik_name}-router.rule"] = ( + f"Host({','.join(hosts)}) && PathPrefix(`/outpost.goauthentik.io`)" + ) labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true" labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service" - labels[ - f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.path" - ] = "/outpost.goauthentik.io/ping" - labels[ - f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.port" - ] = "9300" + labels[f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.path"] = ( + "/outpost.goauthentik.io/ping" + ) + labels[f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.port"] = ( + "9300" + ) labels[f"traefik.http.services.{traefik_name}-service.loadbalancer.server.port"] = "9000" return labels diff --git a/authentik/providers/proxy/controllers/k8s/ingress.py b/authentik/providers/proxy/controllers/k8s/ingress.py index e0cc54dba6..9c3c6755a6 100644 --- a/authentik/providers/proxy/controllers/k8s/ingress.py +++ b/authentik/providers/proxy/controllers/k8s/ingress.py @@ -1,4 +1,5 @@ """Kubernetes Ingress Reconciler""" + from typing import TYPE_CHECKING from urllib.parse import urlparse @@ -55,7 +56,10 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]): proxy_provider: ProxyProvider external_host_name = urlparse(proxy_provider.external_host) expected_hosts.append(external_host_name.hostname) - if external_host_name.scheme == "https": + if ( + external_host_name.scheme == "https" + and self.controller.outpost.config.kubernetes_ingress_secret_name + ): expected_hosts_tls.append(external_host_name.hostname) expected_hosts.sort() expected_hosts_tls.sort() @@ -115,7 +119,10 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]): ): proxy_provider: ProxyProvider external_host_name = urlparse(proxy_provider.external_host) - if external_host_name.scheme == "https": + if ( + external_host_name.scheme == "https" + and self.controller.outpost.config.kubernetes_ingress_secret_name + ): tls_hosts.append(external_host_name.hostname) if proxy_provider.mode in [ ProxyMode.FORWARD_SINGLE, @@ -159,13 +166,15 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]): rules.append(rule) tls_config = None if tls_hosts: - tls_config = V1IngressTLS( - hosts=tls_hosts, - secret_name=self.controller.outpost.config.kubernetes_ingress_secret_name, - ) + tls_config = [ + V1IngressTLS( + hosts=tls_hosts, + secret_name=self.controller.outpost.config.kubernetes_ingress_secret_name, + ) + ] spec = V1IngressSpec( rules=rules, - tls=[tls_config], + tls=tls_config, ) if self.controller.outpost.config.kubernetes_ingress_class_name: spec.ingress_class_name = self.controller.outpost.config.kubernetes_ingress_class_name diff --git a/authentik/providers/proxy/controllers/k8s/traefik.py b/authentik/providers/proxy/controllers/k8s/traefik.py index 4be6438674..406619231f 100644 --- a/authentik/providers/proxy/controllers/k8s/traefik.py +++ b/authentik/providers/proxy/controllers/k8s/traefik.py @@ -1,4 +1,5 @@ """Kubernetes Traefik Middleware Reconciler""" + from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.providers.proxy.controllers.k8s.traefik_2 import Traefik2MiddlewareReconciler diff --git a/authentik/providers/proxy/controllers/k8s/traefik_2.py b/authentik/providers/proxy/controllers/k8s/traefik_2.py index 907659efa0..16e4011bc2 100644 --- a/authentik/providers/proxy/controllers/k8s/traefik_2.py +++ b/authentik/providers/proxy/controllers/k8s/traefik_2.py @@ -1,4 +1,5 @@ """Kubernetes Traefik Middleware Reconciler""" + from typing import TYPE_CHECKING from authentik.providers.proxy.controllers.k8s.traefik_3 import Traefik3MiddlewareReconciler diff --git a/authentik/providers/proxy/controllers/k8s/traefik_3.py b/authentik/providers/proxy/controllers/k8s/traefik_3.py index c6c5a6c4c7..c807ecb630 100644 --- a/authentik/providers/proxy/controllers/k8s/traefik_3.py +++ b/authentik/providers/proxy/controllers/k8s/traefik_3.py @@ -1,4 +1,5 @@ """Kubernetes Traefik Middleware Reconciler""" + from dataclasses import asdict, dataclass, field from typing import TYPE_CHECKING @@ -19,11 +20,11 @@ class TraefikMiddlewareSpecForwardAuth: """traefik middleware forwardAuth spec""" address: str - # pylint: disable=invalid-name + authResponseHeadersRegex: str = field(default="") - # pylint: disable=invalid-name + authResponseHeaders: list[str] = field(default_factory=list) - # pylint: disable=invalid-name + trustForwardHeader: bool = field(default=True) @@ -31,7 +32,6 @@ class TraefikMiddlewareSpecForwardAuth: class TraefikMiddlewareSpec: """Traefik middleware spec""" - # pylint: disable=invalid-name forwardAuth: TraefikMiddlewareSpecForwardAuth @@ -48,7 +48,6 @@ class TraefikMiddlewareMetadata: class TraefikMiddleware: """Traefik Middleware""" - # pylint: disable=invalid-name apiVersion: str kind: str metadata: TraefikMiddlewareMetadata diff --git a/authentik/providers/proxy/controllers/kubernetes.py b/authentik/providers/proxy/controllers/kubernetes.py index 22d9f40838..73b0ea8bc0 100644 --- a/authentik/providers/proxy/controllers/kubernetes.py +++ b/authentik/providers/proxy/controllers/kubernetes.py @@ -1,4 +1,5 @@ """Proxy Provider Kubernetes Controller""" + from authentik.outposts.controllers.base import DeploymentPort from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.models import KubernetesServiceConnection, Outpost @@ -17,8 +18,8 @@ class ProxyKubernetesController(KubernetesController): DeploymentPort(9443, "https", "tcp"), ] self.reconcilers[IngressReconciler.reconciler_name()] = IngressReconciler - self.reconcilers[ - TraefikMiddlewareReconciler.reconciler_name() - ] = TraefikMiddlewareReconciler + self.reconcilers[TraefikMiddlewareReconciler.reconciler_name()] = ( + TraefikMiddlewareReconciler + ) self.reconcile_order.append(IngressReconciler.reconciler_name()) self.reconcile_order.append(TraefikMiddlewareReconciler.reconciler_name()) diff --git a/authentik/providers/proxy/models.py b/authentik/providers/proxy/models.py index 18aef3d3e8..f824495309 100644 --- a/authentik/providers/proxy/models.py +++ b/authentik/providers/proxy/models.py @@ -1,10 +1,12 @@ """authentik proxy models""" + import string +from collections.abc import Iterable from random import SystemRandom -from typing import Iterable, Optional from urllib.parse import urljoin from django.db import models +from django.templatetags.static import static from django.utils.translation import gettext as _ from rest_framework.serializers import Serializer @@ -114,6 +116,10 @@ class ProxyProvider(OutpostModel, OAuth2Provider): def component(self) -> str: return "ak-provider-proxy-form" + @property + def icon_url(self) -> str | None: + return static("authentik/sources/proxy.svg") + @property def serializer(self) -> type[Serializer]: from authentik.providers.proxy.api import ProxyProviderSerializer @@ -121,7 +127,7 @@ class ProxyProvider(OutpostModel, OAuth2Provider): return ProxyProviderSerializer @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """Use external_host as launch URL""" return self.external_host diff --git a/authentik/providers/proxy/signals.py b/authentik/providers/proxy/signals.py index 3e199d3c38..7ada0492b4 100644 --- a/authentik/providers/proxy/signals.py +++ b/authentik/providers/proxy/signals.py @@ -1,4 +1,5 @@ """Proxy provider signals""" + from django.contrib.auth.signals import user_logged_out from django.db.models.signals import pre_delete from django.dispatch import receiver diff --git a/authentik/providers/proxy/tasks.py b/authentik/providers/proxy/tasks.py index 1496ff6ec8..8b2f94c035 100644 --- a/authentik/providers/proxy/tasks.py +++ b/authentik/providers/proxy/tasks.py @@ -1,4 +1,5 @@ """proxy provider tasks""" + from hashlib import sha256 from asgiref.sync import async_to_sync diff --git a/authentik/providers/proxy/tests.py b/authentik/providers/proxy/tests.py index 5c5b77a6e2..b0686cc221 100644 --- a/authentik/providers/proxy/tests.py +++ b/authentik/providers/proxy/tests.py @@ -1,4 +1,5 @@ """proxy provider tests""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/providers/proxy/urls.py b/authentik/providers/proxy/urls.py index 384cc1d6f6..dc86a5dba8 100644 --- a/authentik/providers/proxy/urls.py +++ b/authentik/providers/proxy/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.providers.proxy.api import ProxyOutpostConfigViewSet, ProxyProviderViewSet api_urlpatterns = [ diff --git a/authentik/providers/radius/api.py b/authentik/providers/radius/api.py index af43424bfe..e2ac193b82 100644 --- a/authentik/providers/radius/api.py +++ b/authentik/providers/radius/api.py @@ -1,4 +1,5 @@ """RadiusProvider API Views""" + from rest_framework.fields import CharField, ListField from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet diff --git a/authentik/providers/radius/apps.py b/authentik/providers/radius/apps.py index 5972cdf76d..ac84219117 100644 --- a/authentik/providers/radius/apps.py +++ b/authentik/providers/radius/apps.py @@ -1,4 +1,5 @@ """authentik radius provider app config""" + from django.apps import AppConfig diff --git a/authentik/providers/radius/controllers/docker.py b/authentik/providers/radius/controllers/docker.py index cf17fd36a3..a05cdfed63 100644 --- a/authentik/providers/radius/controllers/docker.py +++ b/authentik/providers/radius/controllers/docker.py @@ -1,4 +1,5 @@ """Radius Provider Docker Controller""" + from authentik.outposts.controllers.base import DeploymentPort from authentik.outposts.controllers.docker import DockerController from authentik.outposts.models import DockerServiceConnection, Outpost diff --git a/authentik/providers/radius/controllers/kubernetes.py b/authentik/providers/radius/controllers/kubernetes.py index cdec2cd9ac..dbc0d45374 100644 --- a/authentik/providers/radius/controllers/kubernetes.py +++ b/authentik/providers/radius/controllers/kubernetes.py @@ -1,4 +1,5 @@ """Radius Provider Kubernetes Controller""" + from authentik.outposts.controllers.base import DeploymentPort from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.models import KubernetesServiceConnection, Outpost diff --git a/authentik/providers/radius/models.py b/authentik/providers/radius/models.py index 781023fd62..7e9784f191 100644 --- a/authentik/providers/radius/models.py +++ b/authentik/providers/radius/models.py @@ -1,7 +1,7 @@ """Radius Provider""" -from typing import Optional, Type from django.db import models +from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer @@ -39,7 +39,7 @@ class RadiusProvider(OutpostModel, Provider): ) @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """Radius never has a launch URL""" return None @@ -48,7 +48,11 @@ class RadiusProvider(OutpostModel, Provider): return "ak-provider-radius-form" @property - def serializer(self) -> Type[Serializer]: + def icon_url(self) -> str | None: + return static("authentik/sources/radius.svg") + + @property + def serializer(self) -> type[Serializer]: from authentik.providers.radius.api import RadiusProviderSerializer return RadiusProviderSerializer diff --git a/authentik/providers/radius/urls.py b/authentik/providers/radius/urls.py index 9cbef52ef0..56e304b0cf 100644 --- a/authentik/providers/radius/urls.py +++ b/authentik/providers/radius/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.providers.radius.api import RadiusOutpostConfigViewSet, RadiusProviderViewSet api_urlpatterns = [ diff --git a/authentik/providers/saml/api/property_mapping.py b/authentik/providers/saml/api/property_mappings.py similarity index 94% rename from authentik/providers/saml/api/property_mapping.py rename to authentik/providers/saml/api/property_mappings.py index 33ca6e4bd3..aff06dee74 100644 --- a/authentik/providers/saml/api/property_mapping.py +++ b/authentik/providers/saml/api/property_mappings.py @@ -1,11 +1,12 @@ """SAML Property mappings API Views""" + from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema_field from rest_framework.viewsets import ModelViewSet -from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.property_mappings import PropertyMappingSerializer from authentik.core.api.used_by import UsedByMixin from authentik.providers.saml.models import SAMLPropertyMapping diff --git a/authentik/providers/saml/api/providers.py b/authentik/providers/saml/api/providers.py index 226ec7e584..ecaf673e66 100644 --- a/authentik/providers/saml/api/providers.py +++ b/authentik/providers/saml/api/providers.py @@ -1,4 +1,6 @@ """SAMLProvider API Views""" + +from copy import copy from xml.etree.ElementTree import ParseError # nosec from defusedxml.ElementTree import fromstring @@ -9,6 +11,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema +from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action from rest_framework.fields import CharField, FileField, SerializerMethodField from rest_framework.parsers import MultiPartParser @@ -19,7 +22,6 @@ from rest_framework.serializers import PrimaryKeyRelatedField, ValidationError from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger -from authentik.api.decorators import permission_required from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer, PropertyMappingPreviewSerializer @@ -30,6 +32,7 @@ from authentik.providers.saml.processors.assertion import AssertionProcessor from authentik.providers.saml.processors.authn_request_parser import AuthNRequest from authentik.providers.saml.processors.metadata import MetadataProcessor from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser +from authentik.rbac.decorators import permission_required from authentik.sources.saml.processors.constants import SAML_BINDING_POST, SAML_BINDING_REDIRECT LOGGER = get_logger() @@ -67,7 +70,7 @@ class SAMLProviderSerializer(ProviderSerializer): kwargs={"application_slug": instance.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return "-" def get_url_sso_redirect(self, instance: SAMLProvider) -> str: @@ -82,7 +85,7 @@ class SAMLProviderSerializer(ProviderSerializer): kwargs={"application_slug": instance.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return "-" def get_url_sso_init(self, instance: SAMLProvider) -> str: @@ -97,7 +100,7 @@ class SAMLProviderSerializer(ProviderSerializer): kwargs={"application_slug": instance.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return "-" def get_url_slo_post(self, instance: SAMLProvider) -> str: @@ -112,7 +115,7 @@ class SAMLProviderSerializer(ProviderSerializer): kwargs={"application_slug": instance.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return "-" def get_url_slo_redirect(self, instance: SAMLProvider) -> str: @@ -127,7 +130,7 @@ class SAMLProviderSerializer(ProviderSerializer): kwargs={"application_slug": instance.application.slug}, ) ) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return "-" class Meta: @@ -213,19 +216,19 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet): try: provider = get_object_or_404(SAMLProvider, pk=pk) except ValueError: - raise Http404 + raise Http404 from None try: proc = MetadataProcessor(provider, request) proc.force_binding = request.query_params.get("force_binding", None) metadata = proc.build_entity_descriptor() if "download" in request.query_params: response = HttpResponse(metadata, content_type="application/xml") - response[ - "Content-Disposition" - ] = f'attachment; filename="{provider.name}_authentik_meta.xml"' + response["Content-Disposition"] = ( + f'attachment; filename="{provider.name}_authentik_meta.xml"' + ) return response return Response({"metadata": metadata}) - except Provider.application.RelatedObjectDoesNotExist: # pylint: disable=no-member + except Provider.application.RelatedObjectDoesNotExist: return Response({"metadata": ""}) @permission_required( @@ -255,7 +258,7 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet): try: fromstring(file.read()) except ParseError: - raise ValidationError(_("Invalid XML Syntax")) + raise ValidationError(_("Invalid XML Syntax")) from None file.seek(0) try: metadata = ServiceProviderMetadataParser().parse(file.read().decode()) @@ -265,8 +268,8 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet): except ValueError as exc: # pragma: no cover LOGGER.warning(str(exc)) raise ValidationError( - _("Failed to import Metadata: %(message)s" % {"message": str(exc)}), - ) + _("Failed to import Metadata: {messages}".format_map({"message": str(exc)})), + ) from None return Response(status=204) @permission_required( @@ -277,12 +280,35 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet): 200: PropertyMappingPreviewSerializer(), 400: OpenApiResponse(description="Bad request"), }, + parameters=[ + OpenApiParameter( + name="for_user", + location=OpenApiParameter.QUERY, + type=OpenApiTypes.INT, + ) + ], ) @action(detail=True, methods=["GET"]) def preview_user(self, request: Request, pk: int) -> Response: """Preview user data for provider""" provider: SAMLProvider = self.get_object() - processor = AssertionProcessor(provider, request._request, AuthNRequest()) + for_user = request.user + if "for_user" in request.query_params: + try: + for_user = ( + get_objects_for_user(request.user, "authentik_core.preview_user") + .filter(pk=request.query_params.get("for_user")) + .first() + ) + if not for_user: + raise ValidationError({"for_user": "User not found"}) + except ValueError: + raise ValidationError({"for_user": "input must be numerical"}) from None + + new_request = copy(request._request) + new_request.user = for_user + + processor = AssertionProcessor(provider, new_request, AuthNRequest()) attributes = processor.get_attributes() name_id = processor.get_name_id() data = [] diff --git a/authentik/providers/saml/exceptions.py b/authentik/providers/saml/exceptions.py index b32453c6c7..10f87a9724 100644 --- a/authentik/providers/saml/exceptions.py +++ b/authentik/providers/saml/exceptions.py @@ -1,4 +1,5 @@ """authentik SAML IDP Exceptions""" + from authentik.lib.sentry import SentryIgnoredException diff --git a/authentik/providers/saml/migrations/0014_alter_samlprovider_digest_algorithm_and_more.py b/authentik/providers/saml/migrations/0014_alter_samlprovider_digest_algorithm_and_more.py new file mode 100644 index 0000000000..0473b0835f --- /dev/null +++ b/authentik/providers/saml/migrations/0014_alter_samlprovider_digest_algorithm_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 5.0.4 on 2024-05-01 15:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_providers_saml", "0013_samlprovider_default_relay_state"), + ] + + operations = [ + migrations.AlterField( + model_name="samlprovider", + name="digest_algorithm", + field=models.TextField( + choices=[ + ("http://www.w3.org/2000/09/xmldsig#sha1", "SHA1"), + ("http://www.w3.org/2001/04/xmlenc#sha256", "SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#sha384", "SHA384"), + ("http://www.w3.org/2001/04/xmlenc#sha512", "SHA512"), + ], + default="http://www.w3.org/2001/04/xmlenc#sha256", + ), + ), + migrations.AlterField( + model_name="samlprovider", + name="signature_algorithm", + field=models.TextField( + choices=[ + ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "RSA-SHA1"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "RSA-SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "RSA-SHA384"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "RSA-SHA512"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", "ECDSA-SHA1"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "ECDSA-SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", "ECDSA-SHA384"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "ECDSA-SHA512"), + ("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "DSA-SHA1"), + ], + default="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + ), + ), + ] diff --git a/authentik/providers/saml/models.py b/authentik/providers/saml/models.py index 1a706df8e0..54448dd317 100644 --- a/authentik/providers/saml/models.py +++ b/authentik/providers/saml/models.py @@ -1,17 +1,22 @@ -"""authentik saml_idp Models""" -from typing import Optional +"""authentik SAML Provider Models""" from django.db import models +from django.templatetags.static import static from django.urls import reverse from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer from structlog.stdlib import get_logger +from authentik.core.api.object_types import CreatableType from authentik.core.models import PropertyMapping, Provider from authentik.crypto.models import CertificateKeyPair from authentik.lib.utils.time import timedelta_string_validator from authentik.sources.saml.processors.constants import ( DSA_SHA1, + ECDSA_SHA1, + ECDSA_SHA256, + ECDSA_SHA384, + ECDSA_SHA512, RSA_SHA1, RSA_SHA256, RSA_SHA384, @@ -93,8 +98,7 @@ class SAMLProvider(Provider): ), ) - digest_algorithm = models.CharField( - max_length=50, + digest_algorithm = models.TextField( choices=( (SHA1, _("SHA1")), (SHA256, _("SHA256")), @@ -103,13 +107,16 @@ class SAMLProvider(Provider): ), default=SHA256, ) - signature_algorithm = models.CharField( - max_length=50, + signature_algorithm = models.TextField( choices=( (RSA_SHA1, _("RSA-SHA1")), (RSA_SHA256, _("RSA-SHA256")), (RSA_SHA384, _("RSA-SHA384")), (RSA_SHA512, _("RSA-SHA512")), + (ECDSA_SHA1, _("ECDSA-SHA1")), + (ECDSA_SHA256, _("ECDSA-SHA256")), + (ECDSA_SHA384, _("ECDSA-SHA384")), + (ECDSA_SHA512, _("ECDSA-SHA512")), (DSA_SHA1, _("DSA-SHA1")), ), default=RSA_SHA256, @@ -143,10 +150,10 @@ class SAMLProvider(Provider): ) @property - def launch_url(self) -> Optional[str]: + def launch_url(self) -> str | None: """Use IDP-Initiated SAML flow as launch URL""" try: - # pylint: disable=no-member + return reverse( "authentik_providers_saml:sso-init", kwargs={"application_slug": self.application.slug}, @@ -154,6 +161,10 @@ class SAMLProvider(Provider): except Provider.application.RelatedObjectDoesNotExist: return None + @property + def icon_url(self) -> str | None: + return static("authentik/sources/saml.png") + @property def serializer(self) -> type[Serializer]: from authentik.providers.saml.api.providers import SAMLProviderSerializer @@ -184,7 +195,7 @@ class SAMLPropertyMapping(PropertyMapping): @property def serializer(self) -> type[Serializer]: - from authentik.providers.saml.api.property_mapping import SAMLPropertyMappingSerializer + from authentik.providers.saml.api.property_mappings import SAMLPropertyMappingSerializer return SAMLPropertyMappingSerializer @@ -195,3 +206,20 @@ class SAMLPropertyMapping(PropertyMapping): class Meta: verbose_name = _("SAML Property Mapping") verbose_name_plural = _("SAML Property Mappings") + + +class SAMLProviderImportModel(CreatableType, Provider): + """Create a SAML Provider by importing its Metadata.""" + + @property + def component(self): + return "ak-provider-saml-import-form" + + @property + def icon_url(self) -> str | None: + return static("authentik/sources/saml.png") + + class Meta: + abstract = True + verbose_name = _("SAML Provider from Metadata") + verbose_name_plural = _("SAML Providers from Metadata") diff --git a/authentik/providers/saml/processors/assertion.py b/authentik/providers/saml/processors/assertion.py index 15940dec63..8c18f10b90 100644 --- a/authentik/providers/saml/processors/assertion.py +++ b/authentik/providers/saml/processors/assertion.py @@ -1,4 +1,5 @@ """SAML Assertion generator""" + from hashlib import sha256 from types import GeneratorType @@ -8,7 +9,7 @@ from lxml import etree # nosec from lxml.etree import Element, SubElement # nosec from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.events.models import Event, EventAction from authentik.events.signals import get_login_event from authentik.lib.utils.time import timedelta_from_string @@ -91,16 +92,15 @@ class AssertionProcessor: attribute.attrib["FriendlyName"] = mapping.friendly_name attribute.attrib["Name"] = mapping.saml_name - if not isinstance(value, (list, GeneratorType)): + if not isinstance(value, list | GeneratorType): value = [value] for value_item in value: attribute_value = SubElement( attribute, f"{{{NS_SAML_ASSERTION}}}AttributeValue" ) - if not isinstance(value_item, str): - value_item = str(value_item) - attribute_value.text = value_item + str_value = str(value_item) if not isinstance(value_item, str) else value_item + attribute_value.text = str_value attribute_statement.append(attribute) @@ -165,7 +165,6 @@ class AssertionProcessor: audience.text = self.provider.audience return conditions - # pylint: disable=too-many-return-statements def get_name_id(self) -> Element: """Get NameID Element""" name_id = Element(f"{{{NS_SAML_ASSERTION}}}NameID") diff --git a/authentik/providers/saml/processors/authn_request_parser.py b/authentik/providers/saml/processors/authn_request_parser.py index 5587cb6951..16585dd12b 100644 --- a/authentik/providers/saml/processors/authn_request_parser.py +++ b/authentik/providers/saml/processors/authn_request_parser.py @@ -1,7 +1,7 @@ """SAML AuthNRequest Parser and dataclass""" + from base64 import b64decode from dataclasses import dataclass -from typing import Optional from urllib.parse import quote_plus from xml.etree.ElementTree import ParseError # nosec @@ -35,9 +35,9 @@ ERROR_FAILED_TO_VERIFY = "Failed to verify signature" class AuthNRequest: """AuthNRequest Dataclass""" - id: Optional[str] = None + id: str | None = None - relay_state: Optional[str] = None + relay_state: str | None = None name_id_policy: str = SAML_NAME_ID_FORMAT_UNSPECIFIED @@ -51,7 +51,7 @@ class AuthNRequestParser: self.provider = provider self.logger = get_logger().bind(provider=self.provider) - def _parse_xml(self, decoded_xml: str | bytes, relay_state: Optional[str]) -> AuthNRequest: + def _parse_xml(self, decoded_xml: str | bytes, relay_state: str | None) -> AuthNRequest: root = ElementTree.fromstring(decoded_xml) # http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf @@ -82,12 +82,12 @@ class AuthNRequestParser: return auth_n_request - def parse(self, saml_request: str, relay_state: Optional[str] = None) -> AuthNRequest: + def parse(self, saml_request: str, relay_state: str | None = None) -> AuthNRequest: """Validate and parse raw request with enveloped signautre.""" try: decoded_xml = b64decode(saml_request.encode()) except UnicodeDecodeError: - raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) + raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None verifier = self.provider.verification_kp if not verifier: @@ -120,15 +120,15 @@ class AuthNRequestParser: def parse_detached( self, saml_request: str, - relay_state: Optional[str], - signature: Optional[str] = None, - sig_alg: Optional[str] = None, + relay_state: str | None, + signature: str | None = None, + sig_alg: str | None = None, ) -> AuthNRequest: """Validate and parse raw request with detached signature""" try: decoded_xml = decode_base64_and_inflate(saml_request) except UnicodeDecodeError: - raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) + raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None verifier = self.provider.verification_kp if not verifier: diff --git a/authentik/providers/saml/processors/logout_request_parser.py b/authentik/providers/saml/processors/logout_request_parser.py index df15694fd9..f34d8031d6 100644 --- a/authentik/providers/saml/processors/logout_request_parser.py +++ b/authentik/providers/saml/processors/logout_request_parser.py @@ -1,7 +1,7 @@ """LogoutRequest parser""" + from base64 import b64decode from dataclasses import dataclass -from typing import Optional from defusedxml import ElementTree @@ -16,11 +16,11 @@ from authentik.sources.saml.processors.constants import NS_SAML_PROTOCOL class LogoutRequest: """Logout Request""" - id: Optional[str] = None + id: str | None = None - issuer: Optional[str] = None + issuer: str | None = None - relay_state: Optional[str] = None + relay_state: str | None = None class LogoutRequestParser: @@ -31,9 +31,7 @@ class LogoutRequestParser: def __init__(self, provider: SAMLProvider): self.provider = provider - def _parse_xml( - self, decoded_xml: str | bytes, relay_state: Optional[str] = None - ) -> LogoutRequest: + def _parse_xml(self, decoded_xml: str | bytes, relay_state: str | None = None) -> LogoutRequest: root = ElementTree.fromstring(decoded_xml) request = LogoutRequest( id=root.attrib["ID"], @@ -44,23 +42,23 @@ class LogoutRequestParser: request.relay_state = relay_state return request - def parse(self, saml_request: str, relay_state: Optional[str] = None) -> LogoutRequest: + def parse(self, saml_request: str, relay_state: str | None = None) -> LogoutRequest: """Validate and parse raw request with enveloped signautre.""" try: decoded_xml = b64decode(saml_request.encode()) except UnicodeDecodeError: - raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) + raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None return self._parse_xml(decoded_xml, relay_state) def parse_detached( self, saml_request: str, - relay_state: Optional[str] = None, + relay_state: str | None = None, ) -> LogoutRequest: """Validate and parse raw request with detached signature""" try: decoded_xml = decode_base64_and_inflate(saml_request) except UnicodeDecodeError: - raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) + raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None return self._parse_xml(decoded_xml, relay_state) diff --git a/authentik/providers/saml/processors/metadata.py b/authentik/providers/saml/processors/metadata.py index 5aecf24f67..e6a2dd0139 100644 --- a/authentik/providers/saml/processors/metadata.py +++ b/authentik/providers/saml/processors/metadata.py @@ -1,6 +1,8 @@ """SAML Identity Provider Metadata Processor""" + +from collections.abc import Iterator from hashlib import sha256 -from typing import Iterator, Optional +from typing import Optional import xmlsec # nosec from django.http import HttpRequest @@ -30,7 +32,7 @@ class MetadataProcessor: provider: SAMLProvider http_request: HttpRequest - force_binding: Optional[str] + force_binding: str | None def __init__(self, provider: SAMLProvider, request: HttpRequest): self.provider = provider @@ -38,7 +40,8 @@ class MetadataProcessor: self.force_binding = None self.xml_id = "_" + sha256(f"{provider.name}-{provider.pk}".encode("ascii")).hexdigest() - def get_signing_key_descriptor(self) -> Optional[Element]: + # Using type unions doesn't work with cython types (which is what lxml is) + def get_signing_key_descriptor(self) -> Optional[Element]: # noqa: UP007 """Get Signing KeyDescriptor, if enabled for the provider""" if not self.provider.signing_kp: return None diff --git a/authentik/providers/saml/processors/metadata_parser.py b/authentik/providers/saml/processors/metadata_parser.py index db284ee221..dd42b52af5 100644 --- a/authentik/providers/saml/processors/metadata_parser.py +++ b/authentik/providers/saml/processors/metadata_parser.py @@ -1,6 +1,6 @@ """SAML ServiceProvider Metadata Parser and dataclass""" + from dataclasses import dataclass -from typing import Optional import xmlsec from cryptography.hazmat.backends import default_backend @@ -47,7 +47,7 @@ class ServiceProviderMetadata: auth_n_request_signed: bool assertion_signed: bool - signing_keypair: Optional[CertificateKeyPair] = None + signing_keypair: CertificateKeyPair | None = None def to_provider(self, name: str, authorization_flow: Flow) -> SAMLProvider: """Create a SAMLProvider instance from the details. `name` is required, @@ -75,7 +75,7 @@ class ServiceProviderMetadata: class ServiceProviderMetadataParser: """Service-Provider Metadata Parser""" - def get_signing_cert(self, root: etree.Element) -> Optional[CertificateKeyPair]: + def get_signing_cert(self, root: etree.Element) -> CertificateKeyPair | None: """Extract X509Certificate from metadata, when given.""" signing_certs = root.xpath( '//md:SPSSODescriptor/md:KeyDescriptor[@use="signing"]//ds:X509Certificate/text()', diff --git a/authentik/providers/saml/tests/test_api.py b/authentik/providers/saml/tests/test_api.py index de86d5cbb2..8ccb0c29a2 100644 --- a/authentik/providers/saml/tests/test_api.py +++ b/authentik/providers/saml/tests/test_api.py @@ -1,4 +1,5 @@ """SAML Provider API Tests""" + from json import loads from tempfile import TemporaryFile diff --git a/authentik/providers/saml/tests/test_auth_n_request.py b/authentik/providers/saml/tests/test_auth_n_request.py index df19eb7368..88a563ef87 100644 --- a/authentik/providers/saml/tests/test_auth_n_request.py +++ b/authentik/providers/saml/tests/test_auth_n_request.py @@ -1,4 +1,5 @@ """Test AuthN Request generator and parser""" + from base64 import b64encode from django.http.request import QueryDict diff --git a/authentik/providers/saml/tests/test_logout_request.py b/authentik/providers/saml/tests/test_logout_request.py index f09361fb76..d7dde73e95 100644 --- a/authentik/providers/saml/tests/test_logout_request.py +++ b/authentik/providers/saml/tests/test_logout_request.py @@ -1,4 +1,5 @@ """logout request tests""" + from django.test import TestCase from authentik.blueprints.tests import apply_blueprint diff --git a/authentik/providers/saml/tests/test_metadata.py b/authentik/providers/saml/tests/test_metadata.py index bc4156b5b9..e61e50bad0 100644 --- a/authentik/providers/saml/tests/test_metadata.py +++ b/authentik/providers/saml/tests/test_metadata.py @@ -1,4 +1,5 @@ """Test Service-Provider Metadata Parser""" + import xmlsec from defusedxml.lxml import fromstring from django.test import RequestFactory, TestCase @@ -6,13 +7,14 @@ from lxml import etree # nosec from authentik.core.models import Application from authentik.core.tests.utils import create_test_cert, create_test_flow +from authentik.crypto.builder import PrivateKeyAlg from authentik.lib.generators import generate_id from authentik.lib.tests.utils import load_fixture from authentik.lib.xml import lxml_from_string from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider from authentik.providers.saml.processors.metadata import MetadataProcessor from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser -from authentik.sources.saml.processors.constants import NS_MAP, NS_SAML_METADATA +from authentik.sources.saml.processors.constants import ECDSA_SHA256, NS_MAP, NS_SAML_METADATA class TestServiceProviderMetadataParser(TestCase): @@ -106,12 +108,41 @@ class TestServiceProviderMetadataParser(TestCase): load_fixture("fixtures/cert.xml").replace("/apps/user_saml", "") ) - def test_signature(self): - """Test signature validation""" + def test_signature_rsa(self): + """Test signature validation (RSA)""" provider = SAMLProvider.objects.create( name=generate_id(), authorization_flow=self.flow, - signing_kp=create_test_cert(), + signing_kp=create_test_cert(PrivateKeyAlg.RSA), + ) + Application.objects.create( + name=generate_id(), + slug=generate_id(), + provider=provider, + ) + request = self.factory.get("/") + metadata = MetadataProcessor(provider, request).build_entity_descriptor() + + root = fromstring(metadata.encode()) + xmlsec.tree.add_ids(root, ["ID"]) + signature_nodes = root.xpath("/md:EntityDescriptor/ds:Signature", namespaces=NS_MAP) + signature_node = signature_nodes[0] + ctx = xmlsec.SignatureContext() + key = xmlsec.Key.from_memory( + provider.signing_kp.certificate_data, + xmlsec.constants.KeyDataFormatCertPem, + None, + ) + ctx.key = key + ctx.verify(signature_node) + + def test_signature_ecdsa(self): + """Test signature validation (ECDSA)""" + provider = SAMLProvider.objects.create( + name=generate_id(), + authorization_flow=self.flow, + signing_kp=create_test_cert(PrivateKeyAlg.ECDSA), + signature_algorithm=ECDSA_SHA256, ) Application.objects.create( name=generate_id(), diff --git a/authentik/providers/saml/tests/test_schema.py b/authentik/providers/saml/tests/test_schema.py index 479e993fdf..34e33cf8ac 100644 --- a/authentik/providers/saml/tests/test_schema.py +++ b/authentik/providers/saml/tests/test_schema.py @@ -1,4 +1,5 @@ """Test Requests and Responses against schema""" + from base64 import b64encode from django.test import TestCase diff --git a/authentik/providers/saml/urls.py b/authentik/providers/saml/urls.py index 02dda0c383..f0cf04e09c 100644 --- a/authentik/providers/saml/urls.py +++ b/authentik/providers/saml/urls.py @@ -1,7 +1,8 @@ """authentik SAML IDP URLs""" + from django.urls import path -from authentik.providers.saml.api.property_mapping import SAMLPropertyMappingViewSet +from authentik.providers.saml.api.property_mappings import SAMLPropertyMappingViewSet from authentik.providers.saml.api.providers import SAMLProviderViewSet from authentik.providers.saml.views import metadata, slo, sso diff --git a/authentik/providers/saml/utils/__init__.py b/authentik/providers/saml/utils/__init__.py index 16c18a18e7..41e474665d 100644 --- a/authentik/providers/saml/utils/__init__.py +++ b/authentik/providers/saml/utils/__init__.py @@ -1,4 +1,5 @@ """Small helper functions""" + import uuid diff --git a/authentik/providers/saml/utils/encoding.py b/authentik/providers/saml/utils/encoding.py index cdc0f7ce3b..0631e627c8 100644 --- a/authentik/providers/saml/utils/encoding.py +++ b/authentik/providers/saml/utils/encoding.py @@ -1,4 +1,5 @@ """Wrappers to de/encode and de/inflate strings""" + import base64 import zlib diff --git a/authentik/providers/saml/utils/time.py b/authentik/providers/saml/utils/time.py index c807315a28..dda87d5ca8 100644 --- a/authentik/providers/saml/utils/time.py +++ b/authentik/providers/saml/utils/time.py @@ -1,9 +1,9 @@ """Time utilities""" + import datetime -from typing import Optional -def get_time_string(delta: Optional[datetime.timedelta] = None) -> str: +def get_time_string(delta: datetime.timedelta | None = None) -> str: """Get Data formatted in SAML format""" if delta is None: delta = datetime.timedelta() diff --git a/authentik/providers/saml/views/flows.py b/authentik/providers/saml/views/flows.py index 479686bd03..afe18f8b20 100644 --- a/authentik/providers/saml/views/flows.py +++ b/authentik/providers/saml/views/flows.py @@ -1,4 +1,5 @@ """authentik SAML IDP Views""" + from django.core.validators import URLValidator from django.http import HttpRequest, HttpResponse from django.http.response import HttpResponseBadRequest @@ -84,7 +85,7 @@ class SAMLFlowFinalView(ChallengeStageView): "component": "ak-stage-autosubmit", "title": self.executor.plan.context.get( PLAN_CONTEXT_TITLE, - _("Redirecting to %(app)s..." % {"app": application.name}), + _("Redirecting to {app}...".format_map({"app": application.name})), ), "url": provider.acs_url, "attrs": form_attrs, diff --git a/authentik/providers/saml/views/metadata.py b/authentik/providers/saml/views/metadata.py index a4335839d0..e76b997804 100644 --- a/authentik/providers/saml/views/metadata.py +++ b/authentik/providers/saml/views/metadata.py @@ -1,4 +1,5 @@ """metadata redirect""" + from django.http import Http404, HttpRequest, HttpResponse from django.shortcuts import get_object_or_404, redirect from django.urls import reverse diff --git a/authentik/providers/saml/views/slo.py b/authentik/providers/saml/views/slo.py index aecdadec73..7f38b1f31a 100644 --- a/authentik/providers/saml/views/slo.py +++ b/authentik/providers/saml/views/slo.py @@ -1,5 +1,4 @@ """SLO Views""" -from typing import Optional from django.http import HttpRequest from django.http.response import HttpResponse @@ -35,7 +34,7 @@ class SAMLSLOView(PolicyAccessView): SAMLProvider, pk=self.application.provider_id ) - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: """Handler to verify the SAML Request. Must be implemented by a subclass""" raise NotImplementedError @@ -60,7 +59,7 @@ class SAMLSLOView(PolicyAccessView): class SAMLSLOBindingRedirectView(SAMLSLOView): """SAML Handler for SLO/Redirect bindings, which are sent via GET""" - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: if REQUEST_KEY_SAML_REQUEST not in self.request.GET: LOGGER.info("check_saml_request: SAML payload missing") return bad_request_message(self.request, "The SAML request payload is missing.") @@ -87,7 +86,7 @@ class SAMLSLOBindingRedirectView(SAMLSLOView): class SAMLSLOBindingPOSTView(SAMLSLOView): """SAML Handler for SLO/POST bindings""" - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: payload = self.request.POST if REQUEST_KEY_SAML_REQUEST not in payload: LOGGER.info("check_saml_request: SAML payload missing") diff --git a/authentik/providers/saml/views/sso.py b/authentik/providers/saml/views/sso.py index 99844150ae..fcc9f7bbf7 100644 --- a/authentik/providers/saml/views/sso.py +++ b/authentik/providers/saml/views/sso.py @@ -1,5 +1,4 @@ """authentik SAML IDP Views""" -from typing import Optional from django.http import Http404, HttpRequest, HttpResponse from django.shortcuts import get_object_or_404 @@ -47,7 +46,7 @@ class SAMLSSOView(PolicyAccessView): SAMLProvider, pk=self.application.provider_id ) - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: """Handler to verify the SAML Request. Must be implemented by a subclass""" raise NotImplementedError @@ -73,7 +72,7 @@ class SAMLSSOView(PolicyAccessView): }, ) except FlowNonApplicableException: - raise Http404 + raise Http404 from None plan.append_stage(in_memory_stage(SAMLFlowFinalView)) request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs( @@ -91,7 +90,7 @@ class SAMLSSOView(PolicyAccessView): class SAMLSSOBindingRedirectView(SAMLSSOView): """SAML Handler for SSO/Redirect bindings, which are sent via GET""" - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: """Handle REDIRECT bindings""" if REQUEST_KEY_SAML_REQUEST not in self.request.GET: LOGGER.info("SAML payload missing") @@ -121,7 +120,7 @@ class SAMLSSOBindingRedirectView(SAMLSSOView): class SAMLSSOBindingPOSTView(SAMLSSOView): """SAML Handler for SSO/POST bindings""" - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: """Handle POST bindings""" payload = self.request.POST # Restore the post body from the session @@ -148,7 +147,7 @@ class SAMLSSOBindingPOSTView(SAMLSSOView): class SAMLSSOBindingInitView(SAMLSSOView): """SAML Handler for for IdP Initiated login flows""" - def check_saml_request(self) -> Optional[HttpRequest]: + def check_saml_request(self) -> HttpRequest | None: """Create SAML Response from scratch""" LOGGER.debug("No SAML Request, using IdP-initiated flow.") auth_n_request = AuthNRequestParser(self.provider).idp_initiated() diff --git a/authentik/providers/scim/api/property_mapping.py b/authentik/providers/scim/api/property_mappings.py similarity index 93% rename from authentik/providers/scim/api/property_mapping.py rename to authentik/providers/scim/api/property_mappings.py index 80c9093294..37c5f09fb3 100644 --- a/authentik/providers/scim/api/property_mapping.py +++ b/authentik/providers/scim/api/property_mappings.py @@ -1,11 +1,12 @@ """scim Property mappings API Views""" + from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema_field from rest_framework.viewsets import ModelViewSet -from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.property_mappings import PropertyMappingSerializer from authentik.core.api.used_by import UsedByMixin from authentik.providers.scim.models import SCIMMapping diff --git a/authentik/providers/scim/api/providers.py b/authentik/providers/scim/api/providers.py index 1b095c7bb0..45b3c4556f 100644 --- a/authentik/providers/scim/api/providers.py +++ b/authentik/providers/scim/api/providers.py @@ -1,18 +1,12 @@ """SCIM Provider API Views""" -from django.utils.text import slugify -from drf_spectacular.utils import OpenApiResponse, extend_schema -from guardian.shortcuts import get_objects_for_user -from rest_framework.decorators import action -from rest_framework.fields import BooleanField -from rest_framework.request import Request -from rest_framework.response import Response + from rest_framework.viewsets import ModelViewSet from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer -from authentik.events.api.tasks import SystemTaskSerializer +from authentik.lib.sync.outgoing.api import OutgoingSyncProviderStatusMixin from authentik.providers.scim.models import SCIMProvider +from authentik.providers.scim.tasks import scim_sync class SCIMProviderSerializer(ProviderSerializer): @@ -39,14 +33,7 @@ class SCIMProviderSerializer(ProviderSerializer): extra_kwargs = {} -class SCIMSyncStatusSerializer(PassiveSerializer): - """SCIM Provider sync status""" - - is_running = BooleanField(read_only=True) - tasks = SystemTaskSerializer(many=True, read_only=True) - - -class SCIMProviderViewSet(UsedByMixin, ModelViewSet): +class SCIMProviderViewSet(OutgoingSyncProviderStatusMixin, UsedByMixin, ModelViewSet): """SCIMProvider Viewset""" queryset = SCIMProvider.objects.all() @@ -54,25 +41,4 @@ class SCIMProviderViewSet(UsedByMixin, ModelViewSet): filterset_fields = ["name", "exclude_users_service_account", "url", "filter_group"] search_fields = ["name", "url"] ordering = ["name", "url"] - - @extend_schema( - responses={ - 200: SCIMSyncStatusSerializer(), - 404: OpenApiResponse(description="Task not found"), - } - ) - @action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[]) - def sync_status(self, request: Request, pk: int) -> Response: - """Get provider's sync status""" - provider: SCIMProvider = self.get_object() - tasks = list( - get_objects_for_user(request.user, "authentik_events.view_systemtask").filter( - name="scim_sync", - uid=slugify(provider.name), - ) - ) - status = { - "tasks": tasks, - "is_running": provider.sync_lock.locked(), - } - return Response(SCIMSyncStatusSerializer(status).data) + sync_single_task = scim_sync diff --git a/authentik/providers/scim/apps.py b/authentik/providers/scim/apps.py index dffd4b8b57..9e6f3836f2 100644 --- a/authentik/providers/scim/apps.py +++ b/authentik/providers/scim/apps.py @@ -1,4 +1,5 @@ """authentik SCIM Provider app config""" + from authentik.blueprints.apps import ManagedAppConfig @@ -9,7 +10,3 @@ class AuthentikProviderSCIMConfig(ManagedAppConfig): label = "authentik_providers_scim" verbose_name = "authentik Providers.SCIM" default = True - - def reconcile_global_load_signals(self): - """Load signals""" - self.import_module("authentik.providers.scim.signals") diff --git a/authentik/providers/scim/clients/__init__.py b/authentik/providers/scim/clients/__init__.py index 0e2e573b5a..e69de29bb2 100644 --- a/authentik/providers/scim/clients/__init__.py +++ b/authentik/providers/scim/clients/__init__.py @@ -1,3 +0,0 @@ -"""SCIM constants""" -PAGE_SIZE = 100 -PAGE_TIMEOUT = 60 * 60 * 0.5 # Half an hour diff --git a/authentik/providers/scim/clients/base.py b/authentik/providers/scim/clients/base.py index b214c30e4c..27ba4eeb06 100644 --- a/authentik/providers/scim/clients/base.py +++ b/authentik/providers/scim/clients/base.py @@ -1,31 +1,37 @@ """SCIM Client""" -from typing import Generic, TypeVar +from typing import TYPE_CHECKING + +from django.http import HttpResponseBadRequest, HttpResponseNotFound from pydantic import ValidationError from requests import RequestException, Session -from structlog.stdlib import get_logger +from authentik.lib.sync.outgoing import HTTP_CONFLICT +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.exceptions import NotFoundSyncException, ObjectExistsSyncException from authentik.lib.utils.http import get_http_session -from authentik.providers.scim.clients.exceptions import ResourceMissing, SCIMRequestException +from authentik.providers.scim.clients.exceptions import SCIMRequestException from authentik.providers.scim.clients.schema import ServiceProviderConfiguration from authentik.providers.scim.models import SCIMProvider -T = TypeVar("T") -# pylint: disable=invalid-name -SchemaType = TypeVar("SchemaType") +if TYPE_CHECKING: + from django.db.models import Model + from pydantic import BaseModel -class SCIMClient(Generic[T, SchemaType]): +class SCIMClient[TModel: "Model", TConnection: "Model", TSchema: "BaseModel"]( + BaseOutgoingSyncClient[TModel, TConnection, TSchema, SCIMProvider] +): """SCIM Client""" base_url: str token: str - provider: SCIMProvider _session: Session _config: ServiceProviderConfiguration def __init__(self, provider: SCIMProvider): + super().__init__(provider) self._session = get_http_session() self.provider = provider # Remove trailing slashes as we assume the URL doesn't have any @@ -34,7 +40,6 @@ class SCIMClient(Generic[T, SchemaType]): base_url = base_url[:-1] self.base_url = base_url self.token = provider.token - self.logger = get_logger().bind(provider=provider.name) self._config = self.get_service_provider_config() def _request(self, method: str, path: str, **kwargs) -> dict: @@ -53,14 +58,16 @@ class SCIMClient(Generic[T, SchemaType]): except RequestException as exc: raise SCIMRequestException(message="Failed to send request") from exc self.logger.debug("scim request", path=path, method=method, **kwargs) - if response.status_code >= 400: - if response.status_code == 404: - raise ResourceMissing(response) + if response.status_code >= HttpResponseBadRequest.status_code: + if response.status_code == HttpResponseNotFound.status_code: + raise NotFoundSyncException(response) + if response.status_code == HTTP_CONFLICT: + raise ObjectExistsSyncException(response) self.logger.warning( "Failed to send SCIM request", path=path, method=method, response=response.text ) raise SCIMRequestException(response) - if response.status_code == 204: + if response.status_code == 204: # noqa: PLR2004 return {} return response.json() @@ -74,15 +81,3 @@ class SCIMClient(Generic[T, SchemaType]): except (ValidationError, SCIMRequestException) as exc: self.logger.warning("failed to get ServiceProviderConfig", exc=exc) return default_config - - def write(self, obj: T): - """Write object to SCIM""" - raise NotImplementedError() - - def delete(self, obj: T): - """Delete object from SCIM""" - raise NotImplementedError() - - def to_scim(self, obj: T) -> SchemaType: - """Convert object to scim""" - raise NotImplementedError() diff --git a/authentik/providers/scim/clients/exceptions.py b/authentik/providers/scim/clients/exceptions.py index 62c7e78c5c..5c4edfa2ce 100644 --- a/authentik/providers/scim/clients/exceptions.py +++ b/authentik/providers/scim/clients/exceptions.py @@ -1,37 +1,19 @@ """SCIM Client exceptions""" -from typing import Optional from pydantic import ValidationError from requests import Response -from authentik.lib.sentry import SentryIgnoredException +from authentik.lib.sync.outgoing.exceptions import TransientSyncException from authentik.providers.scim.clients.schema import SCIMError -class StopSync(SentryIgnoredException): - """Exception raised when a configuration error should stop the sync process""" - - def __init__(self, exc: Exception, obj: object, mapping: Optional[object] = None) -> None: - self.exc = exc - self.obj = obj - self.mapping = mapping - - def detail(self) -> str: - """Get human readable details of this error""" - msg = f"Error {str(self.exc)}, caused by {self.obj}" - - if self.mapping: - msg += f" (mapping {self.mapping})" - return msg - - -class SCIMRequestException(SentryIgnoredException): +class SCIMRequestException(TransientSyncException): """Exception raised when an SCIM request fails""" - _response: Optional[Response] - _message: Optional[str] + _response: Response | None + _message: str | None - def __init__(self, response: Optional[Response] = None, message: Optional[str] = None) -> None: + def __init__(self, response: Response | None = None, message: str | None = None) -> None: self._response = response self._message = message @@ -40,13 +22,8 @@ class SCIMRequestException(SentryIgnoredException): if not self._response: return self._message try: - error = SCIMError.parse_raw(self._response.text) + error = SCIMError.model_validate_json(self._response.text) return error.detail except ValidationError: pass return self._message - - -class ResourceMissing(SCIMRequestException): - """Error raised when the provider raises a 404, meaning that we - should delete our internal ID and re-create the object""" diff --git a/authentik/providers/scim/clients/group.py b/authentik/providers/scim/clients/groups.py similarity index 66% rename from authentik/providers/scim/clients/group.py rename to authentik/providers/scim/clients/groups.py index 306cc21f99..dc4fadb74e 100644 --- a/authentik/providers/scim/clients/group.py +++ b/authentik/providers/scim/clients/groups.py @@ -1,80 +1,49 @@ """Group client""" -from deepmerge import always_merger + from pydantic import ValidationError from pydanticscim.group import GroupMember from pydanticscim.responses import PatchOp, PatchOperation -from authentik.core.exceptions import PropertyMappingExpressionException from authentik.core.models import Group -from authentik.events.models import Event, EventAction -from authentik.lib.utils.errors import exception_to_string +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.base import Direction +from authentik.lib.sync.outgoing.exceptions import ( + NotFoundSyncException, + ObjectExistsSyncException, + StopSync, +) from authentik.policies.utils import delete_none_values from authentik.providers.scim.clients.base import SCIMClient from authentik.providers.scim.clients.exceptions import ( - ResourceMissing, SCIMRequestException, - StopSync, ) +from authentik.providers.scim.clients.schema import SCIM_GROUP_SCHEMA, PatchRequest from authentik.providers.scim.clients.schema import Group as SCIMGroupSchema -from authentik.providers.scim.clients.schema import PatchRequest -from authentik.providers.scim.models import SCIMGroup, SCIMMapping, SCIMUser +from authentik.providers.scim.models import SCIMGroup, SCIMMapping, SCIMProvider, SCIMUser -class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): +class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]): """SCIM client for groups""" - def write(self, obj: Group): - """Write a group""" - scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first() - if not scim_group: - return self._create(obj) - try: - return self._update(obj, scim_group) - except ResourceMissing: - scim_group.delete() - return self._create(obj) + connection_type = SCIMGroup + connection_type_query = "group" + mapper: PropertyMappingManager - def delete(self, obj: Group): - """Delete group""" - scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first() - if not scim_group: - self.logger.debug("Group does not exist in SCIM, skipping") - return None - response = self._request("DELETE", f"/Groups/{scim_group.id}") - scim_group.delete() - return response + def __init__(self, provider: SCIMProvider): + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings_group.all().order_by("name").select_subclasses(), + SCIMMapping, + ["group", "provider", "creating"], + ) - def to_scim(self, obj: Group) -> SCIMGroupSchema: + def to_schema(self, obj: Group, creating: bool) -> SCIMGroupSchema: """Convert authentik user into SCIM""" - raw_scim_group = { - "schemas": ("urn:ietf:params:scim:schemas:core:2.0:Group",), - } - for mapping in ( - self.provider.property_mappings_group.all().order_by("name").select_subclasses() - ): - if not isinstance(mapping, SCIMMapping): - continue - try: - mapping: SCIMMapping - value = mapping.evaluate( - user=None, - request=None, - group=obj, - provider=self.provider, - ) - if value is None: - continue - always_merger.merge(raw_scim_group, value) - except (PropertyMappingExpressionException, ValueError) as exc: - # Value error can be raised when assigning invalid data to an attribute - Event.new( - EventAction.CONFIGURATION_ERROR, - message=f"Failed to evaluate property-mapping {exception_to_string(exc)}", - mapping=mapping, - ).save() - raise StopSync(exc, obj, mapping) from exc - if not raw_scim_group: - raise StopSync(ValueError("No group mappings configured"), obj) + raw_scim_group = super().to_schema( + obj, + creating, + schemas=(SCIM_GROUP_SCHEMA,), + ) try: scim_group = SCIMGroupSchema.model_validate(delete_none_values(raw_scim_group)) except ValidationError as exc: @@ -88,16 +57,26 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): for user in connections: members.append( GroupMember( - value=user.id, + value=user.scim_id, ) ) if members: scim_group.members = members return scim_group - def _create(self, group: Group): + def delete(self, obj: Group): + """Delete group""" + scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first() + if not scim_group: + self.logger.debug("Group does not exist in SCIM, skipping") + return None + response = self._request("DELETE", f"/Groups/{scim_group.scim_id}") + scim_group.delete() + return response + + def create(self, group: Group): """Create group from scratch and create a connection object""" - scim_group = self.to_scim(group) + scim_group = self.to_schema(group, True) response = self._request( "POST", "/Groups", @@ -106,25 +85,28 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): exclude_unset=True, ), ) - SCIMGroup.objects.create(provider=self.provider, group=group, id=response["id"]) + scim_id = response.get("id") + if not scim_id or scim_id == "": + raise StopSync("SCIM Response with missing or invalid `id`") + return SCIMGroup.objects.create(provider=self.provider, group=group, scim_id=scim_id) - def _update(self, group: Group, connection: SCIMGroup): + def update(self, group: Group, connection: SCIMGroup): """Update existing group""" - scim_group = self.to_scim(group) - scim_group.id = connection.id + scim_group = self.to_schema(group, False) + scim_group.id = connection.scim_id try: return self._request( "PUT", - f"/Groups/{scim_group.id}", + f"/Groups/{connection.scim_id}", json=scim_group.model_dump( mode="json", exclude_unset=True, ), ) - except ResourceMissing: + except NotFoundSyncException: # Resource missing is handled by self.write, which will re-create the group raise - except SCIMRequestException: + except (SCIMRequestException, ObjectExistsSyncException): # Some providers don't support PUT on groups, so this is mainly a fix for the initial # sync, send patch add requests for all the users the group currently has users = list(group.users.order_by("id").values_list("id", flat=True)) @@ -139,12 +121,12 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): ), ) - def update_group(self, group: Group, action: PatchOp, users_set: set[int]): + def update_group(self, group: Group, action: Direction, users_set: set[int]): """Update a group, either using PUT to replace it or PATCH if supported""" if self._config.patch.supported: - if action == PatchOp.add: + if action == Direction.add: return self._patch_add_users(group, users_set) - if action == PatchOp.remove: + if action == Direction.remove: return self._patch_remove_users(group, users_set) try: return self.write(group) @@ -152,9 +134,9 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): if self._config.is_fallback: # Assume that provider does not support PUT and also doesn't support # ServiceProviderConfig, so try PATCH as a fallback - if action == PatchOp.add: + if action == Direction.add: return self._patch_add_users(group, users_set) - if action == PatchOp.remove: + if action == Direction.remove: return self._patch_remove_users(group, users_set) raise exc @@ -184,13 +166,13 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): return user_ids = list( SCIMUser.objects.filter(user__pk__in=users_set, provider=self.provider).values_list( - "id", flat=True + "scim_id", flat=True ) ) if len(user_ids) < 1: return self._patch( - scim_group.id, + scim_group.scim_id, PatchOperation( op=PatchOp.add, path="members", @@ -210,13 +192,13 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]): return user_ids = list( SCIMUser.objects.filter(user__pk__in=users_set, provider=self.provider).values_list( - "id", flat=True + "scim_id", flat=True ) ) if len(user_ids) < 1: return self._patch( - scim_group.id, + scim_group.scim_id, PatchOperation( op=PatchOp.remove, path="members", diff --git a/authentik/providers/scim/clients/schema.py b/authentik/providers/scim/clients/schema.py index b1c2682556..f56d6b0e46 100644 --- a/authentik/providers/scim/clients/schema.py +++ b/authentik/providers/scim/clients/schema.py @@ -1,35 +1,38 @@ """Custom SCIM schemas""" -from typing import Optional from pydanticscim.group import Group as BaseGroup from pydanticscim.responses import PatchRequest as BasePatchRequest from pydanticscim.responses import SCIMError as BaseSCIMError -from pydanticscim.service_provider import Bulk, ChangePassword, Filter, Patch +from pydanticscim.service_provider import Bulk, ChangePassword, Filter, Patch, Sort from pydanticscim.service_provider import ( ServiceProviderConfiguration as BaseServiceProviderConfiguration, ) -from pydanticscim.service_provider import Sort from pydanticscim.user import User as BaseUser +SCIM_USER_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:User" +SCIM_GROUP_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:Group" + class User(BaseUser): """Modified User schema with added externalId field""" - schemas: tuple[str] = ("urn:ietf:params:scim:schemas:core:2.0:User",) - externalId: Optional[str] = None + schemas: list[str] = [SCIM_USER_SCHEMA] + externalId: str | None = None + meta: dict | None = None class Group(BaseGroup): """Modified Group schema with added externalId field""" - schemas: tuple[str] = ("urn:ietf:params:scim:schemas:core:2.0:Group",) - externalId: Optional[str] = None + schemas: list[str] = [SCIM_GROUP_SCHEMA] + externalId: str | None = None + meta: dict | None = None class ServiceProviderConfiguration(BaseServiceProviderConfiguration): """ServiceProviderConfig with fallback""" - _is_fallback: Optional[bool] = False + _is_fallback: bool | None = False @property def is_fallback(self) -> bool: @@ -60,4 +63,4 @@ class PatchRequest(BasePatchRequest): class SCIMError(BaseSCIMError): """SCIM error with optional status code""" - status: Optional[int] + status: int | None diff --git a/authentik/providers/scim/clients/user.py b/authentik/providers/scim/clients/user.py deleted file mode 100644 index 11ef6a159c..0000000000 --- a/authentik/providers/scim/clients/user.py +++ /dev/null @@ -1,100 +0,0 @@ -"""User client""" -from deepmerge import always_merger -from pydantic import ValidationError - -from authentik.core.exceptions import PropertyMappingExpressionException -from authentik.core.models import User -from authentik.events.models import Event, EventAction -from authentik.lib.utils.errors import exception_to_string -from authentik.policies.utils import delete_none_values -from authentik.providers.scim.clients.base import SCIMClient -from authentik.providers.scim.clients.exceptions import ResourceMissing, StopSync -from authentik.providers.scim.clients.schema import User as SCIMUserSchema -from authentik.providers.scim.models import SCIMMapping, SCIMUser - - -class SCIMUserClient(SCIMClient[User, SCIMUserSchema]): - """SCIM client for users""" - - def write(self, obj: User): - """Write a user""" - scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first() - if not scim_user: - return self._create(obj) - try: - return self._update(obj, scim_user) - except ResourceMissing: - scim_user.delete() - return self._create(obj) - - def delete(self, obj: User): - """Delete user""" - scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first() - if not scim_user: - self.logger.debug("User does not exist in SCIM, skipping") - return None - response = self._request("DELETE", f"/Users/{scim_user.id}") - scim_user.delete() - return response - - def to_scim(self, obj: User) -> SCIMUserSchema: - """Convert authentik user into SCIM""" - raw_scim_user = { - "schemas": ("urn:ietf:params:scim:schemas:core:2.0:User",), - } - for mapping in self.provider.property_mappings.all().order_by("name").select_subclasses(): - if not isinstance(mapping, SCIMMapping): - continue - try: - mapping: SCIMMapping - value = mapping.evaluate( - user=obj, - request=None, - provider=self.provider, - ) - if value is None: - continue - always_merger.merge(raw_scim_user, value) - except (PropertyMappingExpressionException, ValueError) as exc: - # Value error can be raised when assigning invalid data to an attribute - Event.new( - EventAction.CONFIGURATION_ERROR, - message=f"Failed to evaluate property-mapping {exception_to_string(exc)}", - mapping=mapping, - ).save() - raise StopSync(exc, obj, mapping) from exc - if not raw_scim_user: - raise StopSync(ValueError("No user mappings configured"), obj) - try: - scim_user = SCIMUserSchema.model_validate(delete_none_values(raw_scim_user)) - except ValidationError as exc: - raise StopSync(exc, obj) from exc - if not scim_user.externalId: - scim_user.externalId = str(obj.uid) - return scim_user - - def _create(self, user: User): - """Create user from scratch and create a connection object""" - scim_user = self.to_scim(user) - response = self._request( - "POST", - "/Users", - json=scim_user.model_dump( - mode="json", - exclude_unset=True, - ), - ) - SCIMUser.objects.create(provider=self.provider, user=user, id=response["id"]) - - def _update(self, user: User, connection: SCIMUser): - """Update existing user""" - scim_user = self.to_scim(user) - scim_user.id = connection.id - self._request( - "PUT", - f"/Users/{connection.id}", - json=scim_user.model_dump( - mode="json", - exclude_unset=True, - ), - ) diff --git a/authentik/providers/scim/clients/users.py b/authentik/providers/scim/clients/users.py new file mode 100644 index 0000000000..350020d34f --- /dev/null +++ b/authentik/providers/scim/clients/users.py @@ -0,0 +1,82 @@ +"""User client""" + +from pydantic import ValidationError + +from authentik.core.models import User +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.exceptions import StopSync +from authentik.policies.utils import delete_none_values +from authentik.providers.scim.clients.base import SCIMClient +from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA +from authentik.providers.scim.clients.schema import User as SCIMUserSchema +from authentik.providers.scim.models import SCIMMapping, SCIMProvider, SCIMUser + + +class SCIMUserClient(SCIMClient[User, SCIMUser, SCIMUserSchema]): + """SCIM client for users""" + + connection_type = SCIMUser + connection_type_query = "user" + mapper: PropertyMappingManager + + def __init__(self, provider: SCIMProvider): + super().__init__(provider) + self.mapper = PropertyMappingManager( + self.provider.property_mappings.all().order_by("name").select_subclasses(), + SCIMMapping, + ["provider", "creating"], + ) + + def to_schema(self, obj: User, creating: bool) -> SCIMUserSchema: + """Convert authentik user into SCIM""" + raw_scim_user = super().to_schema( + obj, + creating, + schemas=(SCIM_USER_SCHEMA,), + ) + try: + scim_user = SCIMUserSchema.model_validate(delete_none_values(raw_scim_user)) + except ValidationError as exc: + raise StopSync(exc, obj) from exc + if not scim_user.externalId: + scim_user.externalId = str(obj.uid) + return scim_user + + def delete(self, obj: User): + """Delete user""" + scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first() + if not scim_user: + self.logger.debug("User does not exist in SCIM, skipping") + return None + response = self._request("DELETE", f"/Users/{scim_user.scim_id}") + scim_user.delete() + return response + + def create(self, user: User): + """Create user from scratch and create a connection object""" + scim_user = self.to_schema(user, True) + response = self._request( + "POST", + "/Users", + json=scim_user.model_dump( + mode="json", + exclude_unset=True, + ), + ) + scim_id = response.get("id") + if not scim_id or scim_id == "": + raise StopSync("SCIM Response with missing or invalid `id`") + return SCIMUser.objects.create(provider=self.provider, user=user, scim_id=scim_id) + + def update(self, user: User, connection: SCIMUser): + """Update existing user""" + scim_user = self.to_schema(user, False) + scim_user.id = connection.scim_id + self._request( + "PUT", + f"/Users/{connection.scim_id}", + json=scim_user.model_dump( + mode="json", + exclude_unset=True, + ), + ) diff --git a/authentik/providers/scim/management/commands/scim_sync.py b/authentik/providers/scim/management/commands/scim_sync.py index 40fa068a62..2458c1f826 100644 --- a/authentik/providers/scim/management/commands/scim_sync.py +++ b/authentik/providers/scim/management/commands/scim_sync.py @@ -1,8 +1,9 @@ """SCIM Sync""" + from structlog.stdlib import get_logger from authentik.providers.scim.models import SCIMProvider -from authentik.providers.scim.tasks import scim_sync +from authentik.providers.scim.tasks import scim_sync, sync_tasks from authentik.tenants.management import TenantCommand LOGGER = get_logger() @@ -20,4 +21,4 @@ class Command(TenantCommand): if not provider: LOGGER.warning("Provider does not exist", name=provider_name) continue - scim_sync.delay(provider.pk).get() + sync_tasks.trigger_single_task(provider, scim_sync).get() diff --git a/authentik/providers/scim/migrations/0007_scimgroup_scim_id_scimuser_scim_id_and_more.py b/authentik/providers/scim/migrations/0007_scimgroup_scim_id_scimuser_scim_id_and_more.py new file mode 100644 index 0000000000..61ee46c3dd --- /dev/null +++ b/authentik/providers/scim/migrations/0007_scimgroup_scim_id_scimuser_scim_id_and_more.py @@ -0,0 +1,76 @@ +# Generated by Django 5.0.4 on 2024-05-03 12:38 + +import uuid +from django.db import migrations, models +from django.apps.registry import Apps + +from django.db.backends.base.schema import BaseDatabaseSchemaEditor + +from authentik.lib.migrations import progress_bar + + +def fix_scim_user_group_pk(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): + SCIMUser = apps.get_model("authentik_providers_scim", "SCIMUser") + SCIMGroup = apps.get_model("authentik_providers_scim", "SCIMGroup") + db_alias = schema_editor.connection.alias + print("\nFixing primary key for SCIM users, this might take a couple of minutes...") + for user in progress_bar(SCIMUser.objects.using(db_alias).all()): + SCIMUser.objects.using(db_alias).filter( + pk=user.pk, user=user.user_id, provider=user.provider_id + ).update(scim_id=user.pk, id=uuid.uuid4()) + + print("\nFixing primary key for SCIM groups, this might take a couple of minutes...") + for group in progress_bar(SCIMGroup.objects.using(db_alias).all()): + SCIMGroup.objects.using(db_alias).filter( + pk=group.pk, group=group.group_id, provider=group.provider_id + ).update(scim_id=group.pk, id=uuid.uuid4()) + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "authentik_providers_scim", + "0001_squashed_0006_rename_parent_group_scimprovider_filter_group", + ), + ] + + operations = [ + migrations.AddField( + model_name="scimgroup", + name="scim_id", + field=models.TextField(default="temp"), + preserve_default=False, + ), + migrations.AddField( + model_name="scimuser", + name="scim_id", + field=models.TextField(default="temp"), + preserve_default=False, + ), + migrations.RunPython(fix_scim_user_group_pk), + migrations.AlterField( + model_name="scimgroup", + name="id", + field=models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + migrations.AlterField( + model_name="scimuser", + name="id", + field=models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + migrations.AlterField(model_name="scimuser", name="scim_id", field=models.TextField()), + migrations.AlterField(model_name="scimgroup", name="scim_id", field=models.TextField()), + migrations.AlterUniqueTogether( + name="scimgroup", + unique_together={("scim_id", "group", "provider")}, + ), + migrations.AlterUniqueTogether( + name="scimuser", + unique_together={("scim_id", "user", "provider")}, + ), + ] diff --git a/authentik/providers/scim/models.py b/authentik/providers/scim/models.py index b43a593753..e7e8a0987c 100644 --- a/authentik/providers/scim/models.py +++ b/authentik/providers/scim/models.py @@ -1,17 +1,20 @@ """SCIM Provider models""" -from django.core.cache import cache + +from typing import Any, Self +from uuid import uuid4 + from django.db import models from django.db.models import QuerySet +from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ -from guardian.shortcuts import get_anonymous_user -from redis.lock import Lock from rest_framework.serializers import Serializer from authentik.core.models import BackchannelProvider, Group, PropertyMapping, User, UserTypes -from authentik.providers.scim.clients import PAGE_TIMEOUT +from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient +from authentik.lib.sync.outgoing.models import OutgoingSyncProvider -class SCIMProvider(BackchannelProvider): +class SCIMProvider(OutgoingSyncProvider, BackchannelProvider): """SCIM 2.0 provider to create users and groups in external applications""" exclude_users_service_account = models.BooleanField(default=False) @@ -31,29 +34,38 @@ class SCIMProvider(BackchannelProvider): ) @property - def sync_lock(self) -> Lock: - """Redis lock for syncing SCIM to prevent multiple parallel syncs happening""" - return Lock( - cache.client.get_client(), - name=f"goauthentik.io/providers/scim/sync-{str(self.pk)}", - timeout=(60 * 60 * PAGE_TIMEOUT) * 3, - ) + def icon_url(self) -> str | None: + return static("authentik/sources/scim.png") - def get_user_qs(self) -> QuerySet[User]: - """Get queryset of all users with consistent ordering - according to the provider's settings""" - base = User.objects.all().exclude(pk=get_anonymous_user().pk) - if self.exclude_users_service_account: - base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( - type=UserTypes.INTERNAL_SERVICE_ACCOUNT - ) - if self.filter_group: - base = base.filter(ak_groups__in=[self.filter_group]) - return base.order_by("pk") + def client_for_model( + self, model: type[User | Group] + ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: + if issubclass(model, User): + from authentik.providers.scim.clients.users import SCIMUserClient - def get_group_qs(self) -> QuerySet[Group]: - """Get queryset of all groups with consistent ordering""" - return Group.objects.all().order_by("pk") + return SCIMUserClient(self) + if issubclass(model, Group): + from authentik.providers.scim.clients.groups import SCIMGroupClient + + return SCIMGroupClient(self) + raise ValueError(f"Invalid model {model}") + + def get_object_qs(self, type: type[User | Group]) -> QuerySet[User | Group]: + if type == User: + # Get queryset of all users with consistent ordering + # according to the provider's settings + base = User.objects.all().exclude_anonymous() + if self.exclude_users_service_account: + base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( + type=UserTypes.INTERNAL_SERVICE_ACCOUNT + ) + if self.filter_group: + base = base.filter(ak_groups__in=[self.filter_group]) + return base.order_by("pk") + if type == Group: + # Get queryset of all groups with consistent ordering + return Group.objects.all().order_by("pk") + raise ValueError(f"Invalid type {type}") @property def component(self) -> str: @@ -82,7 +94,7 @@ class SCIMMapping(PropertyMapping): @property def serializer(self) -> type[Serializer]: - from authentik.providers.scim.api.property_mapping import SCIMMappingSerializer + from authentik.providers.scim.api.property_mappings import SCIMMappingSerializer return SCIMMappingSerializer @@ -97,20 +109,28 @@ class SCIMMapping(PropertyMapping): class SCIMUser(models.Model): """Mapping of a user and provider to a SCIM user ID""" - id = models.TextField(primary_key=True) + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + scim_id = models.TextField() user = models.ForeignKey(User, on_delete=models.CASCADE) provider = models.ForeignKey(SCIMProvider, on_delete=models.CASCADE) class Meta: - unique_together = (("id", "user", "provider"),) + unique_together = (("scim_id", "user", "provider"),) + + def __str__(self) -> str: + return f"SCIM User {self.user_id} to {self.provider_id}" class SCIMGroup(models.Model): """Mapping of a group and provider to a SCIM user ID""" - id = models.TextField(primary_key=True) + id = models.UUIDField(primary_key=True, editable=False, default=uuid4) + scim_id = models.TextField() group = models.ForeignKey(Group, on_delete=models.CASCADE) provider = models.ForeignKey(SCIMProvider, on_delete=models.CASCADE) class Meta: - unique_together = (("id", "group", "provider"),) + unique_together = (("scim_id", "group", "provider"),) + + def __str__(self) -> str: + return f"SCIM Group {self.group_id} to {self.provider_id}" diff --git a/authentik/providers/scim/settings.py b/authentik/providers/scim/settings.py index 02b2e6e6ee..0a0963ea90 100644 --- a/authentik/providers/scim/settings.py +++ b/authentik/providers/scim/settings.py @@ -1,4 +1,5 @@ """SCIM task Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand @@ -6,7 +7,7 @@ from authentik.lib.utils.time import fqdn_rand CELERY_BEAT_SCHEDULE = { "providers_scim_sync": { "task": "authentik.providers.scim.tasks.scim_sync_all", - "schedule": crontab(minute=fqdn_rand("scim_sync_all"), hour="*"), + "schedule": crontab(minute=fqdn_rand("scim_sync_all"), hour="*/4"), "options": {"queue": "authentik_scheduled"}, }, } diff --git a/authentik/providers/scim/signals.py b/authentik/providers/scim/signals.py index e799044d60..be9855f26d 100644 --- a/authentik/providers/scim/signals.py +++ b/authentik/providers/scim/signals.py @@ -1,55 +1,12 @@ """SCIM provider signals""" -from django.db.models import Model -from django.db.models.signals import m2m_changed, post_save, pre_delete -from django.dispatch import receiver -from pydanticscim.responses import PatchOp -from structlog.stdlib import get_logger -from authentik.core.models import Group, User -from authentik.lib.utils.reflection import class_to_path +from authentik.lib.sync.outgoing.signals import register_signals from authentik.providers.scim.models import SCIMProvider -from authentik.providers.scim.tasks import scim_signal_direct, scim_signal_m2m, scim_sync +from authentik.providers.scim.tasks import scim_sync, scim_sync_direct, scim_sync_m2m -LOGGER = get_logger() - - -@receiver(post_save, sender=SCIMProvider) -def post_save_provider(sender: type[Model], instance, created: bool, **_): - """Trigger sync when SCIM provider is saved""" - scim_sync.delay(instance.pk) - - -@receiver(post_save, sender=User) -@receiver(post_save, sender=Group) -def post_save_scim(sender: type[Model], instance: User | Group, created: bool, **_): - """Post save handler""" - if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists(): - return - scim_signal_direct.delay(class_to_path(instance.__class__), instance.pk, PatchOp.add.value) - - -@receiver(pre_delete, sender=User) -@receiver(pre_delete, sender=Group) -def pre_delete_scim(sender: type[Model], instance: User | Group, **_): - """Pre-delete handler""" - if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists(): - return - scim_signal_direct.delay(class_to_path(instance.__class__), instance.pk, PatchOp.remove.value) - - -@receiver(m2m_changed, sender=User.ak_groups.through) -def m2m_changed_scim( - sender: type[Model], instance, action: str, pk_set: set, reverse: bool, **kwargs -): - """Sync group membership""" - if action not in ["post_add", "post_remove"]: - return - if not SCIMProvider.objects.filter(backchannel_application__isnull=False).exists(): - return - # reverse: instance is a Group, pk_set is a list of user pks - # non-reverse: instance is a User, pk_set is a list of groups - if reverse: - scim_signal_m2m.delay(str(instance.pk), action, list(pk_set)) - else: - for group_pk in pk_set: - scim_signal_m2m.delay(group_pk, action, [instance.pk]) +register_signals( + SCIMProvider, + task_sync_single=scim_sync, + task_sync_direct=scim_sync_direct, + task_sync_m2m=scim_sync_m2m, +) diff --git a/authentik/providers/scim/tasks.py b/authentik/providers/scim/tasks.py index 5b529dede5..f3c2e4d493 100644 --- a/authentik/providers/scim/tasks.py +++ b/authentik/providers/scim/tasks.py @@ -1,221 +1,37 @@ """SCIM Provider tasks""" -from typing import Any, Optional -from celery.result import allow_join_result -from django.core.paginator import Paginator -from django.db.models import Model, QuerySet -from django.utils.text import slugify -from django.utils.translation import gettext_lazy as _ -from pydanticscim.responses import PatchOp -from structlog.stdlib import get_logger - -from authentik.core.models import Group, User -from authentik.events.models import TaskStatus from authentik.events.system_tasks import SystemTask -from authentik.lib.utils.reflection import path_to_class -from authentik.providers.scim.clients import PAGE_SIZE, PAGE_TIMEOUT -from authentik.providers.scim.clients.base import SCIMClient -from authentik.providers.scim.clients.exceptions import SCIMRequestException, StopSync -from authentik.providers.scim.clients.group import SCIMGroupClient -from authentik.providers.scim.clients.user import SCIMUserClient +from authentik.lib.sync.outgoing.exceptions import TransientSyncException +from authentik.lib.sync.outgoing.tasks import SyncTasks from authentik.providers.scim.models import SCIMProvider from authentik.root.celery import CELERY_APP -LOGGER = get_logger(__name__) +sync_tasks = SyncTasks(SCIMProvider) -def client_for_model(provider: SCIMProvider, model: Model) -> SCIMClient: - """Get SCIM client for model""" - if isinstance(model, User): - return SCIMUserClient(provider) - if isinstance(model, Group): - return SCIMGroupClient(provider) - raise ValueError(f"Invalid model {model}") +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def scim_sync_objects(*args, **kwargs): + return sync_tasks.sync_objects(*args, **kwargs) + + +@CELERY_APP.task( + base=SystemTask, bind=True, autoretry_for=(TransientSyncException,), retry_backoff=True +) +def scim_sync(self, provider_pk: int, *args, **kwargs): + """Run full sync for SCIM provider""" + return sync_tasks.sync_single(self, provider_pk, scim_sync_objects) @CELERY_APP.task() def scim_sync_all(): - """Run sync for all providers""" - for provider in SCIMProvider.objects.filter(backchannel_application__isnull=False): - scim_sync.delay(provider.pk) + return sync_tasks.sync_all(scim_sync) -@CELERY_APP.task(bind=True, base=SystemTask) -def scim_sync(self: SystemTask, provider_pk: int) -> None: - """Run SCIM full sync for provider""" - provider: SCIMProvider = SCIMProvider.objects.filter( - pk=provider_pk, backchannel_application__isnull=False - ).first() - if not provider: - return - lock = provider.sync_lock - if lock.locked(): - LOGGER.debug("SCIM sync locked, skipping task", source=provider.name) - return - self.set_uid(slugify(provider.name)) - messages = [] - messages.append(_("Starting full SCIM sync")) - LOGGER.debug("Starting SCIM sync") - users_paginator = Paginator(provider.get_user_qs(), PAGE_SIZE) - groups_paginator = Paginator(provider.get_group_qs(), PAGE_SIZE) - self.soft_time_limit = self.time_limit = ( - users_paginator.count + groups_paginator.count - ) * PAGE_TIMEOUT - with allow_join_result(): - try: - for page in users_paginator.page_range: - messages.append(_("Syncing page %(page)d of users" % {"page": page})) - for msg in scim_sync_users.delay(page, provider_pk).get(): - messages.append(msg) - for page in groups_paginator.page_range: - messages.append(_("Syncing page %(page)d of groups" % {"page": page})) - for msg in scim_sync_group.delay(page, provider_pk).get(): - messages.append(msg) - except StopSync as exc: - self.set_error(exc) - return - self.set_status(TaskStatus.SUCCESSFUL, *messages) +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def scim_sync_direct(*args, **kwargs): + return sync_tasks.sync_signal_direct(*args, **kwargs) -@CELERY_APP.task( - soft_time_limit=PAGE_TIMEOUT, - task_time_limit=PAGE_TIMEOUT, -) -def scim_sync_users(page: int, provider_pk: int): - """Sync single or multiple users to SCIM""" - messages = [] - provider: SCIMProvider = SCIMProvider.objects.filter(pk=provider_pk).first() - if not provider: - return messages - try: - client = SCIMUserClient(provider) - except SCIMRequestException: - return messages - paginator = Paginator(provider.get_user_qs(), PAGE_SIZE) - LOGGER.debug("starting user sync for page", page=page) - for user in paginator.page(page).object_list: - try: - client.write(user) - except SCIMRequestException as exc: - LOGGER.warning("failed to sync user", exc=exc, user=user) - messages.append( - _( - "Failed to sync user %(user_name)s due to remote error: %(error)s" - % { - "user_name": user.username, - "error": exc.detail(), - } - ) - ) - except StopSync as exc: - LOGGER.warning("Stopping sync", exc=exc) - messages.append( - _( - "Stopping sync due to error: %(error)s" - % { - "error": exc.detail(), - } - ) - ) - break - return messages - - -@CELERY_APP.task() -def scim_sync_group(page: int, provider_pk: int): - """Sync single or multiple groups to SCIM""" - messages = [] - provider: SCIMProvider = SCIMProvider.objects.filter(pk=provider_pk).first() - if not provider: - return messages - try: - client = SCIMGroupClient(provider) - except SCIMRequestException: - return messages - paginator = Paginator(provider.get_group_qs(), PAGE_SIZE) - LOGGER.debug("starting group sync for page", page=page) - for group in paginator.page(page).object_list: - try: - client.write(group) - except SCIMRequestException as exc: - LOGGER.warning("failed to sync group", exc=exc, group=group) - messages.append( - _( - "Failed to sync group %(group_name)s due to remote error: %(error)s" - % { - "group_name": group.name, - "error": exc.detail(), - } - ) - ) - except StopSync as exc: - LOGGER.warning("Stopping sync", exc=exc) - messages.append( - _( - "Stopping sync due to error: %(error)s" - % { - "error": exc.detail(), - } - ) - ) - break - return messages - - -@CELERY_APP.task() -def scim_signal_direct(model: str, pk: Any, raw_op: str): - """Handler for post_save and pre_delete signal""" - model_class: type[Model] = path_to_class(model) - instance = model_class.objects.filter(pk=pk).first() - if not instance: - return - operation = PatchOp(raw_op) - for provider in SCIMProvider.objects.filter(backchannel_application__isnull=False): - client = client_for_model(provider, instance) - # Check if the object is allowed within the provider's restrictions - queryset: Optional[QuerySet] = None - if isinstance(instance, User): - queryset = provider.get_user_qs() - if isinstance(instance, Group): - queryset = provider.get_group_qs() - if not queryset: - continue - - # The queryset we get from the provider must include the instance we've got given - # otherwise ignore this provider - if not queryset.filter(pk=instance.pk).exists(): - continue - - try: - if operation == PatchOp.add: - client.write(instance) - if operation == PatchOp.remove: - client.delete(instance) - except (StopSync, SCIMRequestException) as exc: - LOGGER.warning(exc) - - -@CELERY_APP.task() -def scim_signal_m2m(group_pk: str, action: str, pk_set: list[int]): - """Update m2m (group membership)""" - group = Group.objects.filter(pk=group_pk).first() - if not group: - return - for provider in SCIMProvider.objects.filter(backchannel_application__isnull=False): - # Check if the object is allowed within the provider's restrictions - queryset: QuerySet = provider.get_group_qs() - # The queryset we get from the provider must include the instance we've got given - # otherwise ignore this provider - if not queryset.filter(pk=group_pk).exists(): - continue - - client = SCIMGroupClient(provider) - try: - operation = None - if action == "post_add": - operation = PatchOp.add - if action == "post_remove": - operation = PatchOp.remove - client.update_group(group, operation, pk_set) - except (StopSync, SCIMRequestException) as exc: - LOGGER.warning(exc) +@CELERY_APP.task(autoretry_for=(TransientSyncException,), retry_backoff=True) +def scim_sync_m2m(*args, **kwargs): + return sync_tasks.sync_signal_m2m(*args, **kwargs) diff --git a/authentik/providers/scim/tests/test_client.py b/authentik/providers/scim/tests/test_client.py index 2e298cb1b4..0d3dd57e51 100644 --- a/authentik/providers/scim/tests/test_client.py +++ b/authentik/providers/scim/tests/test_client.py @@ -1,4 +1,5 @@ """SCIM Client tests""" + from django.test import TestCase from requests_mock import Mocker diff --git a/authentik/providers/scim/tests/test_group.py b/authentik/providers/scim/tests/test_group.py index 6dd9d70ca5..b0b7058f52 100644 --- a/authentik/providers/scim/tests/test_group.py +++ b/authentik/providers/scim/tests/test_group.py @@ -1,8 +1,8 @@ """SCIM Group tests""" + from json import loads from django.test import TestCase -from guardian.shortcuts import get_anonymous_user from jsonschema import validate from requests_mock import Mocker @@ -19,7 +19,7 @@ class SCIMGroupTests(TestCase): def setUp(self) -> None: # Delete all users and groups as the mocked HTTP responses only return one ID # which will cause errors with multiple users - User.objects.all().exclude(pk=get_anonymous_user().pk).delete() + User.objects.all().exclude_anonymous().delete() Group.objects.all().delete() self.provider: SCIMProvider = SCIMProvider.objects.create( name=generate_id(), @@ -127,7 +127,7 @@ class SCIMGroupTests(TestCase): "id": scim_id, }, ) - mock.delete("https://localhost/Groups", status_code=204) + mock.delete(f"https://localhost/Groups/{scim_id}", status_code=204) uid = generate_id() group = Group.objects.create( name=uid, diff --git a/authentik/providers/scim/tests/test_membership.py b/authentik/providers/scim/tests/test_membership.py index c6a6d8951f..8b2b0dc9b3 100644 --- a/authentik/providers/scim/tests/test_membership.py +++ b/authentik/providers/scim/tests/test_membership.py @@ -1,6 +1,6 @@ """SCIM Membership tests""" + from django.test import TestCase -from guardian.shortcuts import get_anonymous_user from requests_mock import Mocker from authentik.blueprints.tests import apply_blueprint @@ -8,7 +8,7 @@ from authentik.core.models import Application, Group, User from authentik.lib.generators import generate_id from authentik.providers.scim.clients.schema import ServiceProviderConfiguration from authentik.providers.scim.models import SCIMMapping, SCIMProvider -from authentik.providers.scim.tasks import scim_sync +from authentik.providers.scim.tasks import scim_sync, sync_tasks from authentik.tenants.models import Tenant @@ -21,7 +21,7 @@ class SCIMMembershipTests(TestCase): def setUp(self) -> None: # Delete all users and groups as the mocked HTTP responses only return one ID # which will cause errors with multiple users - User.objects.all().exclude(pk=get_anonymous_user().pk).delete() + User.objects.all().exclude_anonymous().delete() Group.objects.all().delete() Tenant.objects.update(avatars="none") @@ -49,7 +49,7 @@ class SCIMMembershipTests(TestCase): def test_member_add(self): """Test member add""" config = ServiceProviderConfiguration.default() - # pylint: disable=assigning-non-slot + config.patch.supported = True user_scim_id = generate_id() group_scim_id = generate_id() @@ -79,7 +79,7 @@ class SCIMMembershipTests(TestCase): ) self.configure() - scim_sync.delay(self.provider.pk).get() + sync_tasks.trigger_single_task(self.provider, scim_sync).get() self.assertEqual(mocker.call_count, 6) self.assertEqual(mocker.request_history[0].method, "GET") @@ -139,7 +139,7 @@ class SCIMMembershipTests(TestCase): def test_member_remove(self): """Test member remove""" config = ServiceProviderConfiguration.default() - # pylint: disable=assigning-non-slot + config.patch.supported = True user_scim_id = generate_id() group_scim_id = generate_id() @@ -169,7 +169,7 @@ class SCIMMembershipTests(TestCase): ) self.configure() - scim_sync.delay(self.provider.pk).get() + sync_tasks.trigger_single_task(self.provider, scim_sync).get() self.assertEqual(mocker.call_count, 6) self.assertEqual(mocker.request_history[0].method, "GET") diff --git a/authentik/providers/scim/tests/test_user.py b/authentik/providers/scim/tests/test_user.py index 4d05b97763..a8ca5e8137 100644 --- a/authentik/providers/scim/tests/test_user.py +++ b/authentik/providers/scim/tests/test_user.py @@ -1,8 +1,8 @@ """SCIM User tests""" + from json import loads from django.test import TestCase -from guardian.shortcuts import get_anonymous_user from jsonschema import validate from requests_mock import Mocker @@ -10,7 +10,7 @@ from authentik.blueprints.tests import apply_blueprint from authentik.core.models import Application, Group, User from authentik.lib.generators import generate_id from authentik.providers.scim.models import SCIMMapping, SCIMProvider -from authentik.providers.scim.tasks import scim_sync +from authentik.providers.scim.tasks import scim_sync, sync_tasks from authentik.tenants.models import Tenant @@ -22,7 +22,7 @@ class SCIMUserTests(TestCase): # Delete all users and groups as the mocked HTTP responses only return one ID # which will cause errors with multiple users Tenant.objects.update(avatars="none") - User.objects.all().exclude(pk=get_anonymous_user().pk).delete() + User.objects.all().exclude_anonymous().delete() Group.objects.all().delete() self.provider: SCIMProvider = SCIMProvider.objects.create( name=generate_id(), @@ -88,6 +88,72 @@ class SCIMUserTests(TestCase): }, ) + @Mocker() + def test_user_create_different_provider_same_id(self, mock: Mocker): + """Test user creation with multiple providers that happen + to return the same object ID""" + # Create duplicate provider + provider: SCIMProvider = SCIMProvider.objects.create( + name=generate_id(), + url="https://localhost", + token=generate_id(), + exclude_users_service_account=True, + ) + app: Application = Application.objects.create( + name=generate_id(), + slug=generate_id(), + ) + app.backchannel_providers.add(provider) + provider.property_mappings.add( + SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/user") + ) + provider.property_mappings_group.add( + SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/group") + ) + + scim_id = generate_id() + mock.get( + "https://localhost/ServiceProviderConfig", + json={}, + ) + mock.post( + "https://localhost/Users", + json={ + "id": scim_id, + }, + ) + uid = generate_id() + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + self.assertEqual(mock.call_count, 4) + self.assertEqual(mock.request_history[0].method, "GET") + self.assertEqual(mock.request_history[1].method, "POST") + self.assertJSONEqual( + mock.request_history[1].body, + { + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], + "active": True, + "emails": [ + { + "primary": True, + "type": "other", + "value": f"{uid}@goauthentik.io", + } + ], + "externalId": user.uid, + "name": { + "familyName": uid, + "formatted": f"{uid} {uid}", + "givenName": uid, + }, + "displayName": f"{uid} {uid}", + "userName": uid, + }, + ) + @Mocker() def test_user_create_update(self, mock: Mocker): """Test user creation and update""" @@ -164,7 +230,7 @@ class SCIMUserTests(TestCase): "id": scim_id, }, ) - mock.delete("https://localhost/Users", status_code=204) + mock.delete(f"https://localhost/Users/{scim_id}", status_code=204) uid = generate_id() user = User.objects.create( username=uid, @@ -236,7 +302,7 @@ class SCIMUserTests(TestCase): email=f"{uid}@goauthentik.io", ) - scim_sync.delay(self.provider.pk).get() + sync_tasks.trigger_single_task(self.provider, scim_sync).get() self.assertEqual(mock.call_count, 5) self.assertEqual(mock.request_history[0].method, "GET") diff --git a/authentik/providers/scim/urls.py b/authentik/providers/scim/urls.py index 045862dba9..50ef596965 100644 --- a/authentik/providers/scim/urls.py +++ b/authentik/providers/scim/urls.py @@ -1,5 +1,6 @@ """API URLs""" -from authentik.providers.scim.api.property_mapping import SCIMMappingViewSet + +from authentik.providers.scim.api.property_mappings import SCIMMappingViewSet from authentik.providers.scim.api.providers import SCIMProviderViewSet api_urlpatterns = [ diff --git a/authentik/rbac/api/rbac.py b/authentik/rbac/api/rbac.py index 2ce5b8d33f..517217ec64 100644 --- a/authentik/rbac/api/rbac.py +++ b/authentik/rbac/api/rbac.py @@ -1,4 +1,5 @@ """common RBAC serializers""" + from django.apps import apps from django.contrib.auth.models import Permission from django.db.models import QuerySet diff --git a/authentik/rbac/api/rbac_assigned_by_roles.py b/authentik/rbac/api/rbac_assigned_by_roles.py index 5dcdcab129..e52815e4af 100644 --- a/authentik/rbac/api/rbac_assigned_by_roles.py +++ b/authentik/rbac/api/rbac_assigned_by_roles.py @@ -1,4 +1,5 @@ """common RBAC serializers""" + from django.db.models import Q, QuerySet from django.db.transaction import atomic from django_filters.filters import CharFilter, ChoiceFilter @@ -14,10 +15,10 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet -from authentik.api.decorators import permission_required from authentik.core.api.utils import PassiveSerializer from authentik.policies.event_matcher.models import model_choices from authentik.rbac.api.rbac import PermissionAssignSerializer +from authentik.rbac.decorators import permission_required from authentik.rbac.models import Role diff --git a/authentik/rbac/api/rbac_assigned_by_users.py b/authentik/rbac/api/rbac_assigned_by_users.py index d69b30a522..adf0c99c4c 100644 --- a/authentik/rbac/api/rbac_assigned_by_users.py +++ b/authentik/rbac/api/rbac_assigned_by_users.py @@ -1,4 +1,5 @@ """common RBAC serializers""" + from django.db.models import Q, QuerySet from django.db.transaction import atomic from django_filters.filters import CharFilter, ChoiceFilter @@ -15,11 +16,11 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet -from authentik.api.decorators import permission_required from authentik.core.api.groups import GroupMemberSerializer from authentik.core.models import User, UserTypes from authentik.policies.event_matcher.models import model_choices from authentik.rbac.api.rbac import PermissionAssignSerializer +from authentik.rbac.decorators import permission_required class UserObjectPermissionSerializer(ModelSerializer): diff --git a/authentik/rbac/api/rbac_roles.py b/authentik/rbac/api/rbac_roles.py index 1ef13c115e..60542dfc4f 100644 --- a/authentik/rbac/api/rbac_roles.py +++ b/authentik/rbac/api/rbac_roles.py @@ -1,5 +1,4 @@ """common RBAC serializers""" -from typing import Optional from django.apps import apps from django_filters.filters import UUIDFilter @@ -38,7 +37,7 @@ class ExtraRoleObjectPermissionSerializer(RoleObjectPermissionSerializer): except LookupError: return f"{instance.content_type.app_label}.{instance.content_type.model}" - def get_object_description(self, instance: GroupObjectPermission) -> Optional[str]: + def get_object_description(self, instance: GroupObjectPermission) -> str | None: """Get model description from attached model. This operation takes at least one additional query, and the description is only shown if the user/role has the view_ permission on the object""" diff --git a/authentik/rbac/api/rbac_users.py b/authentik/rbac/api/rbac_users.py index 6de2e8bcee..95a31de768 100644 --- a/authentik/rbac/api/rbac_users.py +++ b/authentik/rbac/api/rbac_users.py @@ -1,5 +1,4 @@ """common RBAC serializers""" -from typing import Optional from django.apps import apps from django_filters.filters import NumberFilter @@ -38,7 +37,7 @@ class ExtraUserObjectPermissionSerializer(UserObjectPermissionSerializer): except LookupError: return f"{instance.content_type.app_label}.{instance.content_type.model}" - def get_object_description(self, instance: UserObjectPermission) -> Optional[str]: + def get_object_description(self, instance: UserObjectPermission) -> str | None: """Get model description from attached model. This operation takes at least one additional query, and the description is only shown if the user/role has the view_ permission on the object""" diff --git a/authentik/rbac/api/roles.py b/authentik/rbac/api/roles.py index 36eef8a193..96df4a7039 100644 --- a/authentik/rbac/api/roles.py +++ b/authentik/rbac/api/roles.py @@ -1,4 +1,5 @@ """RBAC Roles""" + from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet diff --git a/authentik/rbac/apps.py b/authentik/rbac/apps.py index f4e8a43f6f..72424c244a 100644 --- a/authentik/rbac/apps.py +++ b/authentik/rbac/apps.py @@ -1,4 +1,5 @@ """authentik rbac app config""" + from authentik.blueprints.apps import ManagedAppConfig @@ -9,7 +10,3 @@ class AuthentikRBACConfig(ManagedAppConfig): label = "authentik_rbac" verbose_name = "authentik RBAC" default = True - - def reconcile_global_load_rbac_signals(self): - """Load rbac signals""" - self.import_module("authentik.rbac.signals") diff --git a/authentik/api/decorators.py b/authentik/rbac/decorators.py similarity index 55% rename from authentik/api/decorators.py rename to authentik/rbac/decorators.py index 0cd737c76d..0438819309 100644 --- a/authentik/api/decorators.py +++ b/authentik/rbac/decorators.py @@ -1,6 +1,7 @@ """API Decorators""" + +from collections.abc import Callable from functools import wraps -from typing import Callable, Optional from rest_framework.request import Request from rest_framework.response import Response @@ -10,21 +11,26 @@ from structlog.stdlib import get_logger LOGGER = get_logger() -def permission_required(obj_perm: Optional[str] = None, global_perms: Optional[list[str]] = None): +def permission_required(obj_perm: str | None = None, global_perms: list[str] | None = None): """Check permissions for a single custom action""" - def wrapper_outter(func: Callable): + def _check_obj_perm(self: ModelViewSet, request: Request): + # Check obj_perm both globally and on the specific object + # Having the global permission has higher priority + if request.user.has_perm(obj_perm): + return + obj = self.get_object() + if not request.user.has_perm(obj_perm, obj): + LOGGER.debug("denying access for object", user=request.user, perm=obj_perm, obj=obj) + self.permission_denied(request) + + def wrapper_outer(func: Callable): """Check permissions for a single custom action""" @wraps(func) def wrapper(self: ModelViewSet, request: Request, *args, **kwargs) -> Response: if obj_perm: - obj = self.get_object() - if not request.user.has_perm(obj_perm, obj): - LOGGER.debug( - "denying access for object", user=request.user, perm=obj_perm, obj=obj - ) - return self.permission_denied(request) + _check_obj_perm(self, request) if global_perms: for other_perm in global_perms: if not request.user.has_perm(other_perm): @@ -34,4 +40,4 @@ def permission_required(obj_perm: Optional[str] = None, global_perms: Optional[l return wrapper - return wrapper_outter + return wrapper_outer diff --git a/authentik/rbac/filters.py b/authentik/rbac/filters.py index 22f5a768e5..1b083fd75d 100644 --- a/authentik/rbac/filters.py +++ b/authentik/rbac/filters.py @@ -1,4 +1,5 @@ """RBAC API Filter""" + from django.db.models import QuerySet from rest_framework.exceptions import PermissionDenied from rest_framework.request import Request diff --git a/authentik/rbac/migrations/0004_alter_systempermission_options.py b/authentik/rbac/migrations/0004_alter_systempermission_options.py index eeca4c4e3b..8dbd2053f4 100644 --- a/authentik/rbac/migrations/0004_alter_systempermission_options.py +++ b/authentik/rbac/migrations/0004_alter_systempermission_options.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.1 on 2024-01-24 15:28 +# Generated by Django 5.0.6 on 2024-05-19 14:17 from django.db import migrations diff --git a/authentik/rbac/models.py b/authentik/rbac/models.py index 141d2f7736..973747a5b0 100644 --- a/authentik/rbac/models.py +++ b/authentik/rbac/models.py @@ -1,5 +1,5 @@ """RBAC models""" -from typing import Optional + from uuid import uuid4 from django.db import models @@ -30,7 +30,7 @@ class Role(SerializerModel): # name field has the same constraints as the group model name = models.TextField(max_length=150, unique=True) - def assign_permission(self, *perms: str, obj: Optional[models.Model] = None): + def assign_permission(self, *perms: str, obj: models.Model | None = None): """Assign permission to role, can handle multiple permissions, but when assigning multiple permissions to an object the permissions must all belong to the object given""" @@ -74,3 +74,6 @@ class SystemPermission(models.Model): ("view_system_settings", _("Can view system settings")), ("edit_system_settings", _("Can edit system settings")), ] + + def __str__(self) -> str: + return "System Permission" diff --git a/authentik/rbac/permissions.py b/authentik/rbac/permissions.py index 011a027158..16f9c5ae65 100644 --- a/authentik/rbac/permissions.py +++ b/authentik/rbac/permissions.py @@ -1,4 +1,5 @@ """RBAC Permissions""" + from django.db.models import Model from rest_framework.permissions import BasePermission, DjangoObjectPermissions from rest_framework.request import Request @@ -7,7 +8,16 @@ from rest_framework.request import Request class ObjectPermissions(DjangoObjectPermissions): """RBAC Permissions""" - def has_object_permission(self, request: Request, view, obj: Model): + def has_permission(self, request: Request, view) -> bool: + """Always grant permission for object-specific requests + as view permission checking is done by `ObjectFilter`, + and write permission checking is done by `has_object_permission`""" + lookup = getattr(view, "lookup_url_kwarg", None) or getattr(view, "lookup_field", None) + if lookup and lookup in view.kwargs: + return True + return super().has_permission(request, view) + + def has_object_permission(self, request: Request, view, obj: Model) -> bool: queryset = self._queryset(view) model_cls = queryset.model perms = self.get_required_object_permissions(request.method, model_cls) @@ -17,12 +27,10 @@ class ObjectPermissions(DjangoObjectPermissions): return super().has_object_permission(request, view, obj) -# pylint: disable=invalid-name def HasPermission(*perm: str) -> type[BasePermission]: """Permission checker for any non-object permissions, returns a BasePermission class that can be used with rest_framework""" - # pylint: disable=missing-class-docstring, invalid-name class checker(BasePermission): def has_permission(self, request: Request, view): return bool(request.user and request.user.has_perms(perm)) diff --git a/authentik/rbac/signals.py b/authentik/rbac/signals.py index f3bbbc036d..e96708c70c 100644 --- a/authentik/rbac/signals.py +++ b/authentik/rbac/signals.py @@ -1,8 +1,10 @@ """rbac signals""" + from django.contrib.auth.models import Group as DjangoGroup -from django.db.models.signals import m2m_changed, pre_save +from django.db.models.signals import m2m_changed, pre_delete, pre_save from django.db.transaction import atomic from django.dispatch import receiver +from rest_framework.exceptions import ValidationError from structlog.stdlib import get_logger from authentik.core.models import Group @@ -20,9 +22,26 @@ def rbac_role_pre_save(sender: type[Role], instance: Role, **_): instance.group = group +@receiver(pre_delete, sender=Role) +@receiver(pre_delete, sender=Group) +def rbac_pre_delete_cleanup(sender: type[Group] | type[Role], instance: Group | Role, **_): + """RBAC: remove permissions from users when a group is deleted""" + if sender == Group: + for role in instance.roles.all(): + role.group.user_set.clear() + if sender == Role: + instance.group.user_set.clear() + + @receiver(m2m_changed, sender=Group.roles.through) -def rbac_group_role_m2m(sender: type[Group], action: str, instance: Group, reverse: bool, **_): +def rbac_group_role_m2m( + sender: type[Group], action: str, instance: Group, reverse: bool, pk_set: set, **_ +): """RBAC: Sync group members into roles when roles are assigned""" + if action == "pre_add": + # Validation: check that any of the added roles are not used in any other groups + if Group.objects.filter(roles__in=pk_set).exclude(pk=instance.pk).exists(): + raise ValidationError("Roles can only be used with a single group.") if action not in ["post_add", "post_remove", "post_clear"]: return with atomic(): @@ -31,15 +50,15 @@ def rbac_group_role_m2m(sender: type[Group], action: str, instance: Group, rever .exclude(users__isnull=True) .values_list("users", flat=True) ) - if not group_users: - return - for role in instance.roles.all(): - role: Role - role.group.user_set.set(group_users) - LOGGER.debug("Updated users in group", group=instance) + for role in Role.objects.filter(pk__in=pk_set): + if action == "post_add": + role.group.user_set.add(*group_users) + # Role(s) in pk_set were removed from group, so remove the users that we added + if action == "post_remove": + role.group.user_set.remove(*group_users) + LOGGER.debug("Updated users in group", group=instance, direction=action, users=group_users) -# pylint: disable=no-member @receiver(m2m_changed, sender=Group.users.through) def rbac_group_users_m2m( sender: type[Group], action: str, instance: Group, pk_set: set, reverse: bool, **_ diff --git a/authentik/rbac/tests/test_api.py b/authentik/rbac/tests/test_api.py new file mode 100644 index 0000000000..5c44fd49e6 --- /dev/null +++ b/authentik/rbac/tests/test_api.py @@ -0,0 +1,27 @@ +"""Test RBACPermissionViewSet api""" + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.core.models import Group +from authentik.core.tests.utils import create_test_admin_user, create_test_user +from authentik.lib.generators import generate_id +from authentik.rbac.models import Role + + +class TestRBACAPI(APITestCase): + """Test RBACPermissionViewSet api""" + + def setUp(self) -> None: + self.superuser = create_test_admin_user() + + self.user = create_test_user() + self.role = Role.objects.create(name=generate_id()) + self.group = Group.objects.create(name=generate_id()) + self.group.roles.add(self.role) + self.group.users.add(self.user) + + def test_list(self): + self.client.force_login(self.superuser) + res = self.client.get(reverse("authentik_api:permission-list")) + self.assertEqual(res.status_code, 200) diff --git a/authentik/rbac/tests/test_api_assigned_by_roles.py b/authentik/rbac/tests/test_api_assigned_by_roles.py index 07032e8050..a7ea300721 100644 --- a/authentik/rbac/tests/test_api_assigned_by_roles.py +++ b/authentik/rbac/tests/test_api_assigned_by_roles.py @@ -1,4 +1,5 @@ """Test RoleAssignedPermissionViewSet api""" + from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/rbac/tests/test_api_assigned_by_users.py b/authentik/rbac/tests/test_api_assigned_by_users.py index fa1238495b..0d35ab845b 100644 --- a/authentik/rbac/tests/test_api_assigned_by_users.py +++ b/authentik/rbac/tests/test_api_assigned_by_users.py @@ -1,9 +1,10 @@ """Test UserAssignedPermissionViewSet api""" + from django.urls import reverse from guardian.shortcuts import assign_perm from rest_framework.test import APITestCase -from authentik.core.models import Group, UserTypes +from authentik.core.models import Group, User, UserTypes from authentik.core.tests.utils import create_test_admin_user, create_test_user from authentik.lib.generators import generate_id from authentik.rbac.api.rbac_assigned_by_users import UserAssignedObjectPermissionSerializer @@ -25,6 +26,7 @@ class TestRBACUserAPI(APITestCase): def test_filter_assigned(self): """Test UserAssignedPermissionViewSet's filters""" + User.objects.filter(username="akadmin").delete() inv = Invitation.objects.create( name=generate_id(), created_by=self.superuser, diff --git a/authentik/rbac/tests/test_api_filters.py b/authentik/rbac/tests/test_api_filters.py index 91bd707d7d..730e160667 100644 --- a/authentik/rbac/tests/test_api_filters.py +++ b/authentik/rbac/tests/test_api_filters.py @@ -1,4 +1,5 @@ """RBAC role tests""" + from django.urls import reverse from rest_framework.test import APITestCase @@ -120,3 +121,29 @@ class TestAPIPerms(APITestCase): }, ) self.assertEqual(res.status_code, 403) + + def test_update_simple(self): + """Test update with permission""" + self.client.force_login(self.user) + inv = Invitation.objects.create(name=generate_id(), created_by=self.superuser) + self.role.assign_permission("authentik_stages_invitation.view_invitation", obj=inv) + self.role.assign_permission("authentik_stages_invitation.change_invitation", obj=inv) + res = self.client.patch( + reverse("authentik_api:invitation-detail", kwargs={"pk": inv.pk}), + data={ + "name": generate_id(), + }, + ) + self.assertEqual(res.status_code, 200) + + def test_update_simple_denied(self): + """Test update without assigning permission""" + self.client.force_login(self.user) + inv = Invitation.objects.create(name=generate_id(), created_by=self.superuser) + res = self.client.patch( + reverse("authentik_api:invitation-detail", kwargs={"pk": inv.pk}), + data={ + "name": generate_id(), + }, + ) + self.assertEqual(res.status_code, 403) diff --git a/authentik/rbac/tests/test_api_permissions_roles.py b/authentik/rbac/tests/test_api_permissions_roles.py new file mode 100644 index 0000000000..3cd050f35b --- /dev/null +++ b/authentik/rbac/tests/test_api_permissions_roles.py @@ -0,0 +1,75 @@ +"""Test RolePermissionViewSet api""" + +from django.urls import reverse +from guardian.models import GroupObjectPermission +from rest_framework.test import APITestCase + +from authentik.core.models import Group +from authentik.core.tests.utils import create_test_admin_user, create_test_user +from authentik.lib.generators import generate_id +from authentik.rbac.models import Role +from authentik.stages.invitation.models import Invitation + + +class TestRBACPermissionRoles(APITestCase): + """Test RolePermissionViewSet api""" + + def setUp(self) -> None: + self.superuser = create_test_admin_user() + + self.user = create_test_user() + self.role = Role.objects.create(name=generate_id()) + self.group = Group.objects.create(name=generate_id()) + self.group.roles.add(self.role) + self.group.users.add(self.user) + + def test_list(self): + """Test list of all permissions""" + self.client.force_login(self.superuser) + inv = Invitation.objects.create( + name=generate_id(), + created_by=self.superuser, + ) + self.role.assign_permission("authentik_stages_invitation.view_invitation", obj=inv) + res = self.client.get(reverse("authentik_api:permissions-roles-list")) + self.assertEqual(res.status_code, 400) + + def test_list_role(self): + """Test list of all permissions""" + self.client.force_login(self.superuser) + inv = Invitation.objects.create( + name=generate_id(), + created_by=self.superuser, + ) + self.role.assign_permission("authentik_stages_invitation.view_invitation", obj=inv) + res = self.client.get( + reverse("authentik_api:permissions-roles-list") + f"?uuid={self.role.pk}" + ) + self.assertEqual(res.status_code, 200) + self.assertJSONEqual( + res.content, + { + "pagination": { + "next": 0, + "previous": 0, + "count": 1, + "current": 1, + "total_pages": 1, + "start_index": 1, + "end_index": 1, + }, + "results": [ + { + "id": GroupObjectPermission.objects.filter(object_pk=inv.pk).first().pk, + "codename": "view_invitation", + "model": "invitation", + "app_label": "authentik_stages_invitation", + "object_pk": str(inv.pk), + "name": "Can view Invitation", + "app_label_verbose": "authentik Stages.Invitation", + "model_verbose": "Invitation", + "object_description": str(inv), + } + ], + }, + ) diff --git a/authentik/rbac/tests/test_api_permissions_users.py b/authentik/rbac/tests/test_api_permissions_users.py new file mode 100644 index 0000000000..3386b8ed13 --- /dev/null +++ b/authentik/rbac/tests/test_api_permissions_users.py @@ -0,0 +1,76 @@ +"""Test UserPermissionViewSet api""" + +from django.urls import reverse +from guardian.models import UserObjectPermission +from guardian.shortcuts import assign_perm +from rest_framework.test import APITestCase + +from authentik.core.models import Group +from authentik.core.tests.utils import create_test_admin_user, create_test_user +from authentik.lib.generators import generate_id +from authentik.rbac.models import Role +from authentik.stages.invitation.models import Invitation + + +class TestRBACPermissionUsers(APITestCase): + """Test UserPermissionViewSet api""" + + def setUp(self) -> None: + self.superuser = create_test_admin_user() + + self.user = create_test_user() + self.role = Role.objects.create(name=generate_id()) + self.group = Group.objects.create(name=generate_id()) + self.group.roles.add(self.role) + self.group.users.add(self.user) + + def test_list(self): + """Test list of all permissions""" + self.client.force_login(self.superuser) + inv = Invitation.objects.create( + name=generate_id(), + created_by=self.superuser, + ) + assign_perm("authentik_stages_invitation.view_invitation", self.user, inv) + res = self.client.get(reverse("authentik_api:permissions-users-list")) + self.assertEqual(res.status_code, 400) + + def test_list_role(self): + """Test list of all permissions""" + self.client.force_login(self.superuser) + inv = Invitation.objects.create( + name=generate_id(), + created_by=self.superuser, + ) + assign_perm("authentik_stages_invitation.view_invitation", self.user, inv) + res = self.client.get( + reverse("authentik_api:permissions-users-list") + f"?user_id={self.user.pk}" + ) + self.assertEqual(res.status_code, 200) + self.assertJSONEqual( + res.content, + { + "pagination": { + "next": 0, + "previous": 0, + "count": 1, + "current": 1, + "total_pages": 1, + "start_index": 1, + "end_index": 1, + }, + "results": [ + { + "id": UserObjectPermission.objects.filter(object_pk=inv.pk).first().pk, + "codename": "view_invitation", + "model": "invitation", + "app_label": "authentik_stages_invitation", + "object_pk": str(inv.pk), + "name": "Can view Invitation", + "app_label_verbose": "authentik Stages.Invitation", + "model_verbose": "Invitation", + "object_description": str(inv), + } + ], + }, + ) diff --git a/authentik/rbac/tests/test_decorators.py b/authentik/rbac/tests/test_decorators.py new file mode 100644 index 0000000000..974ce97652 --- /dev/null +++ b/authentik/rbac/tests/test_decorators.py @@ -0,0 +1,58 @@ +"""test decorators api""" + +from django.urls import reverse +from guardian.shortcuts import assign_perm +from rest_framework.test import APITestCase + +from authentik.core.models import Application +from authentik.core.tests.utils import create_test_user +from authentik.lib.generators import generate_id + + +class TestAPIDecorators(APITestCase): + """test decorators api""" + + def setUp(self) -> None: + super().setUp() + self.user = create_test_user() + + def test_obj_perm_denied(self): + """Test object perm denied""" + self.client.force_login(self.user) + app = Application.objects.create(name=generate_id(), slug=generate_id()) + response = self.client.get( + reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) + ) + self.assertEqual(response.status_code, 403) + + def test_obj_perm_global(self): + """Test object perm successful (global)""" + assign_perm("authentik_core.view_application", self.user) + assign_perm("authentik_events.view_event", self.user) + self.client.force_login(self.user) + app = Application.objects.create(name=generate_id(), slug=generate_id()) + response = self.client.get( + reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) + ) + self.assertEqual(response.status_code, 200) + + def test_obj_perm_scoped(self): + """Test object perm successful (scoped)""" + assign_perm("authentik_events.view_event", self.user) + app = Application.objects.create(name=generate_id(), slug=generate_id()) + assign_perm("authentik_core.view_application", self.user, app) + self.client.force_login(self.user) + response = self.client.get( + reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) + ) + self.assertEqual(response.status_code, 200) + + def test_other_perm_denied(self): + """Test other perm denied""" + self.client.force_login(self.user) + app = Application.objects.create(name=generate_id(), slug=generate_id()) + assign_perm("authentik_core.view_application", self.user, app) + response = self.client.get( + reverse("authentik_api:application-metrics", kwargs={"slug": app.slug}) + ) + self.assertEqual(response.status_code, 403) diff --git a/authentik/rbac/tests/test_roles.py b/authentik/rbac/tests/test_roles.py index f9cbfdabb8..76ee8f46ab 100644 --- a/authentik/rbac/tests/test_roles.py +++ b/authentik/rbac/tests/test_roles.py @@ -1,8 +1,10 @@ """RBAC role tests""" + +from rest_framework.exceptions import ValidationError from rest_framework.test import APITestCase -from authentik.core.models import Group -from authentik.core.tests.utils import create_test_admin_user +from authentik.core.models import Group, User +from authentik.core.tests.utils import create_test_user from authentik.lib.generators import generate_id from authentik.rbac.models import Role @@ -12,18 +14,30 @@ class TestRoles(APITestCase): def test_role_create(self): """Test creation""" - user = create_test_admin_user() + user = create_test_user() group = Group.objects.create(name=generate_id()) role = Role.objects.create(name=generate_id()) + role.save() role.assign_permission("authentik_core.view_application") group.roles.add(role) group.users.add(user) self.assertEqual(list(role.group.user_set.all()), [user]) self.assertTrue(user.has_perm("authentik_core.view_application")) - def test_role_create_remove(self): + def test_role_create_add_reverse(self): + """Test creation (add user in reverse)""" + user = create_test_user() + group = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group.roles.add(role) + user.ak_groups.add(group) + self.assertEqual(list(role.group.user_set.all()), [user]) + self.assertTrue(user.has_perm("authentik_core.view_application")) + + def test_remove_group_delete(self): """Test creation and remove""" - user = create_test_admin_user() + user = create_test_user() group = Group.objects.create(name=generate_id()) role = Role.objects.create(name=generate_id()) role.assign_permission("authentik_core.view_application") @@ -31,5 +45,77 @@ class TestRoles(APITestCase): group.users.add(user) self.assertEqual(list(role.group.user_set.all()), [user]) self.assertTrue(user.has_perm("authentik_core.view_application")) - user.delete() + group.delete() + user = User.objects.get(username=user.username) + self.assertFalse(user.has_perm("authentik_core.view_application")) + self.assertEqual(list(role.group.user_set.all()), []) + + def test_remove_roles_remove(self): + """Test assigning permission to role, then removing role from group""" + user = create_test_user() + group = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group.roles.add(role) + group.users.add(user) + self.assertEqual(list(role.group.user_set.all()), [user]) + self.assertTrue(user.has_perm("authentik_core.view_application")) + group.roles.remove(role) + user = User.objects.get(username=user.username) + self.assertFalse(user.has_perm("authentik_core.view_application")) + self.assertEqual(list(role.group.user_set.all()), []) + + def test_remove_role_delete(self): + """Test assigning permissions to role, then removing role""" + user = create_test_user() + group = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group.roles.add(role) + group.users.add(user) + self.assertEqual(list(role.group.user_set.all()), [user]) + self.assertTrue(user.has_perm("authentik_core.view_application")) + role.delete() + user = User.objects.get(username=user.username) + self.assertFalse(user.has_perm("authentik_core.view_application")) + self.assertEqual(list(role.group.user_set.all()), []) + + def test_role_assign_twice(self): + """Test assigning role to two groups""" + group1 = Group.objects.create(name=generate_id()) + group2 = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group1.roles.add(role) + with self.assertRaises(ValidationError): + group2.roles.add(role) + + def test_remove_users_remove(self): + """Test assigning permission to role, then removing user from group""" + user = create_test_user() + group = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group.roles.add(role) + group.users.add(user) + self.assertEqual(list(role.group.user_set.all()), [user]) + self.assertTrue(user.has_perm("authentik_core.view_application")) + group.users.remove(user) + user = User.objects.get(username=user.username) + self.assertFalse(user.has_perm("authentik_core.view_application")) + self.assertEqual(list(role.group.user_set.all()), []) + + def test_remove_users_remove_reverse(self): + """Test assigning permission to role, then removing user from group in reverse""" + user = create_test_user() + group = Group.objects.create(name=generate_id()) + role = Role.objects.create(name=generate_id()) + role.assign_permission("authentik_core.view_application") + group.roles.add(role) + group.users.add(user) + self.assertEqual(list(role.group.user_set.all()), [user]) + self.assertTrue(user.has_perm("authentik_core.view_application")) + user.ak_groups.remove(group) + user = User.objects.get(username=user.username) + self.assertFalse(user.has_perm("authentik_core.view_application")) self.assertEqual(list(role.group.user_set.all()), []) diff --git a/authentik/rbac/urls.py b/authentik/rbac/urls.py index 586264a503..e39ef8f1bb 100644 --- a/authentik/rbac/urls.py +++ b/authentik/rbac/urls.py @@ -1,4 +1,5 @@ """RBAC API urls""" + from authentik.rbac.api.rbac import RBACPermissionViewSet from authentik.rbac.api.rbac_assigned_by_roles import RoleAssignedPermissionViewSet from authentik.rbac.api.rbac_assigned_by_users import UserAssignedPermissionViewSet diff --git a/authentik/recovery/apps.py b/authentik/recovery/apps.py index e9f33fd6b1..85bbfa7b71 100644 --- a/authentik/recovery/apps.py +++ b/authentik/recovery/apps.py @@ -1,4 +1,5 @@ """authentik Recovery app config""" + from django.apps import AppConfig diff --git a/authentik/recovery/lib.py b/authentik/recovery/lib.py index b700c4a8ff..3aa386a2f9 100644 --- a/authentik/recovery/lib.py +++ b/authentik/recovery/lib.py @@ -1,4 +1,5 @@ """Recovery helper functions.""" + from datetime import datetime from django.urls import reverse diff --git a/authentik/recovery/management/commands/create_admin_group.py b/authentik/recovery/management/commands/create_admin_group.py index cb2b1fe11c..979717877e 100644 --- a/authentik/recovery/management/commands/create_admin_group.py +++ b/authentik/recovery/management/commands/create_admin_group.py @@ -1,4 +1,5 @@ """authentik recovery create_admin_group""" + from django.utils.translation import gettext as _ from authentik.core.models import User diff --git a/authentik/recovery/management/commands/create_recovery_key.py b/authentik/recovery/management/commands/create_recovery_key.py index 9e41ba9445..870daefd29 100644 --- a/authentik/recovery/management/commands/create_recovery_key.py +++ b/authentik/recovery/management/commands/create_recovery_key.py @@ -1,4 +1,5 @@ """authentik recovery createkey command""" + from datetime import timedelta from getpass import getuser diff --git a/authentik/recovery/tests.py b/authentik/recovery/tests.py index 0d886a5d7f..b6cca0c59d 100644 --- a/authentik/recovery/tests.py +++ b/authentik/recovery/tests.py @@ -1,4 +1,5 @@ """recovery tests""" + from io import StringIO from django.core.management import call_command @@ -18,7 +19,7 @@ class TestRecovery(TestCase): def test_create_key(self): """Test creation of a new key""" out = StringIO() - self.assertEqual(len(Token.objects.all()), 0) + self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 0) call_command( "create_recovery_key", "1", @@ -28,12 +29,12 @@ class TestRecovery(TestCase): ) token = Token.objects.get(intent=TokenIntents.INTENT_RECOVERY, user=self.user) self.assertIn(token.key, out.getvalue()) - self.assertEqual(len(Token.objects.all()), 1) + self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 1) def test_create_key_invalid(self): """Test creation of a new key (invalid)""" out = StringIO() - self.assertEqual(len(Token.objects.all()), 0) + self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 0) call_command("create_recovery_key", "1", "foo", schema=get_public_schema_name(), stderr=out) self.assertIn("not found", out.getvalue()) diff --git a/authentik/recovery/views.py b/authentik/recovery/views.py index 200b44f52d..db06c58b8a 100644 --- a/authentik/recovery/views.py +++ b/authentik/recovery/views.py @@ -1,4 +1,5 @@ """recovery views""" + from django.contrib import messages from django.contrib.auth import login from django.http import Http404, HttpRequest, HttpResponse diff --git a/authentik/root/asgi.py b/authentik/root/asgi.py index 6412c114e0..4aaddf83d6 100644 --- a/authentik/root/asgi.py +++ b/authentik/root/asgi.py @@ -6,6 +6,7 @@ It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ """ + import django from channels.routing import ProtocolTypeRouter, URLRouter from defusedxml import defuse_stdlib @@ -17,8 +18,8 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware defuse_stdlib() django.setup() -# pylint: disable=wrong-import-position -from authentik.root import websocket # noqa # isort:skip + +from authentik.root import websocket # noqa class LifespanApp: @@ -59,7 +60,18 @@ class RouteNotFoundMiddleware: raise exc -application = SentryAsgiMiddleware( +class AuthentikAsgi(SentryAsgiMiddleware): + """Root ASGI App wrapper""" + + def call_startup(self): + from authentik.root.signals import post_startup, pre_startup, startup + + pre_startup.send(sender=self) + startup.send(sender=self) + post_startup.send(sender=self) + + +application = AuthentikAsgi( ProtocolTypeRouter( { "http": get_asgi_application(), diff --git a/authentik/root/asgi_middleware.py b/authentik/root/asgi_middleware.py index 33c5195e2c..cecdb54e05 100644 --- a/authentik/root/asgi_middleware.py +++ b/authentik/root/asgi_middleware.py @@ -1,4 +1,5 @@ """ASGI middleware""" + from channels.db import database_sync_to_async from channels.sessions import InstanceSessionWrapper as UpstreamInstanceSessionWrapper from channels.sessions import SessionMiddleware as UpstreamSessionMiddleware diff --git a/authentik/root/celery.py b/authentik/root/celery.py index d88cb44d97..57105a75e3 100644 --- a/authentik/root/celery.py +++ b/authentik/root/celery.py @@ -1,10 +1,11 @@ """authentik core celery""" + import os +from collections.abc import Callable from contextvars import ContextVar from logging.config import dictConfig from pathlib import Path from tempfile import gettempdir -from typing import Callable from celery import bootsteps from celery.apps.worker import Worker @@ -62,7 +63,7 @@ def task_prerun_hook(task_id: str, task, *args, **kwargs): @task_postrun.connect -def task_postrun_hook(task_id, task, *args, retval=None, state=None, **kwargs): +def task_postrun_hook(task_id: str, task, *args, retval=None, state=None, **kwargs): """Log task_id on worker""" CTX_TASK_ID.set(...) LOGGER.info( @@ -72,14 +73,16 @@ def task_postrun_hook(task_id, task, *args, retval=None, state=None, **kwargs): @task_failure.connect @task_internal_error.connect -def task_error_hook(task_id, exception: Exception, traceback, *args, **kwargs): +def task_error_hook(task_id: str, exception: Exception, traceback, *args, **kwargs): """Create system event for failed task""" from authentik.events.models import Event, EventAction - LOGGER.warning("Task failure", exc=exception) + LOGGER.warning("Task failure", task_id=task_id.replace("-", ""), exc=exception) CTX_TASK_ID.set(...) if before_send({}, {"exc_info": (None, exception, None)}) is not None: - Event.new(EventAction.SYSTEM_EXCEPTION, message=exception_to_string(exception)).save() + Event.new( + EventAction.SYSTEM_EXCEPTION, message=exception_to_string(exception), task_id=task_id + ).save() def _get_startup_tasks_default_tenant() -> list[Callable]: @@ -90,13 +93,10 @@ def _get_startup_tasks_default_tenant() -> list[Callable]: def _get_startup_tasks_all_tenants() -> list[Callable]: """Get all tasks to be run on startup for all tenants""" from authentik.admin.tasks import clear_update_notifications - from authentik.outposts.tasks import outpost_connection_discovery, outpost_controller_all from authentik.providers.proxy.tasks import proxy_set_defaults return [ clear_update_notifications, - outpost_connection_discovery, - outpost_controller_all, proxy_set_defaults, ] diff --git a/authentik/root/db/base.py b/authentik/root/db/base.py index 70e8595f71..2385e1b972 100644 --- a/authentik/root/db/base.py +++ b/authentik/root/db/base.py @@ -1,4 +1,5 @@ """authentik database backend""" + from django_tenants.postgresql_backend.base import DatabaseWrapper as BaseDatabaseWrapper from authentik.lib.config import CONFIG @@ -9,8 +10,15 @@ class DatabaseWrapper(BaseDatabaseWrapper): def get_connection_params(self): """Refresh DB credentials before getting connection params""" - CONFIG.refresh("postgresql.password") conn_params = super().get_connection_params() - conn_params["user"] = CONFIG.get("postgresql.user") - conn_params["password"] = CONFIG.get("postgresql.password") + + prefix = "postgresql" + if self.alias.startswith("replica_"): + prefix = f"postgresql.read_replicas.{self.alias.removeprefix('replica_')}" + + for setting in ("host", "port", "user", "password"): + conn_params[setting] = CONFIG.refresh(f"{prefix}.{setting}") + if conn_params[setting] is None and self.alias.startswith("replica_"): + conn_params[setting] = CONFIG.refresh(f"postgresql.{setting}") + return conn_params diff --git a/authentik/root/install_id.py b/authentik/root/install_id.py index e786b2b659..f0f319aa7c 100644 --- a/authentik/root/install_id.py +++ b/authentik/root/install_id.py @@ -1,4 +1,5 @@ """install ID""" + from functools import lru_cache from uuid import uuid4 @@ -6,6 +7,8 @@ from psycopg import connect from authentik.lib.config import CONFIG +QUERY = """SELECT id FROM public.authentik_install_id ORDER BY id LIMIT 1;""" + @lru_cache def get_install_id() -> str: @@ -17,7 +20,7 @@ def get_install_id() -> str: if settings.TEST: return str(uuid4()) with connection.cursor() as cursor: - cursor.execute("SELECT id FROM public.authentik_install_id LIMIT 1;") + cursor.execute(QUERY) return cursor.fetchone()[0] @@ -37,5 +40,5 @@ def get_install_id_raw(): sslkey=CONFIG.get("postgresql.sslkey"), ) cursor = conn.cursor() - cursor.execute("SELECT id FROM public.authentik_install_id LIMIT 1;") + cursor.execute(QUERY) return cursor.fetchone()[0] diff --git a/authentik/root/messages/consumer.py b/authentik/root/messages/consumer.py index 3fa9301b10..964ea6bba1 100644 --- a/authentik/root/messages/consumer.py +++ b/authentik/root/messages/consumer.py @@ -1,4 +1,5 @@ """websocket Message consumer""" + from channels.generic.websocket import JsonWebsocketConsumer from django.core.cache import cache diff --git a/authentik/root/messages/storage.py b/authentik/root/messages/storage.py index 4f9262d8d5..4fb9760254 100644 --- a/authentik/root/messages/storage.py +++ b/authentik/root/messages/storage.py @@ -1,4 +1,5 @@ """Channels Messages storage""" + from asgiref.sync import async_to_sync from channels.layers import get_channel_layer from django.contrib.messages.storage.base import Message diff --git a/authentik/root/middleware.py b/authentik/root/middleware.py index ba5465d4f8..88edae6143 100644 --- a/authentik/root/middleware.py +++ b/authentik/root/middleware.py @@ -1,15 +1,16 @@ """Dynamically set SameSite depending if the upstream connection is TLS or not""" + +from collections.abc import Callable from hashlib import sha512 -from time import time -from timeit import default_timer -from typing import Any, Callable, Optional +from time import perf_counter, time +from typing import Any from django.conf import settings from django.contrib.sessions.backends.base import UpdateError from django.contrib.sessions.exceptions import SessionInterrupted from django.contrib.sessions.middleware import SessionMiddleware as UpstreamSessionMiddleware from django.http.request import HttpRequest -from django.http.response import HttpResponse +from django.http.response import HttpResponse, HttpResponseServerError from django.middleware.csrf import CSRF_SESSION_KEY from django.middleware.csrf import CsrfViewMiddleware as UpstreamCsrfViewMiddleware from django.utils.cache import patch_vary_headers @@ -99,7 +100,7 @@ class SessionMiddleware(UpstreamSessionMiddleware): expires = http_date(expires_time) # Save the session data and refresh the client cookie. # Skip session save for 500 responses, refs #3881. - if response.status_code != 500: + if response.status_code != HttpResponseServerError.status_code: try: request.session.save() except UpdateError: @@ -107,7 +108,7 @@ class SessionMiddleware(UpstreamSessionMiddleware): "The request's session was deleted before the " "request completed. The user may have logged " "out in a concurrent request, for example." - ) + ) from None payload = { "sid": request.session.session_key, "iss": "authentik", @@ -191,7 +192,7 @@ class ClientIPMiddleware: # FIXME: this should probably not be in `root` but rather in a middleware in `outposts` # but for now it's fine - def _get_outpost_override_ip(self, request: HttpRequest) -> Optional[str]: + def _get_outpost_override_ip(self, request: HttpRequest) -> str | None: """Get the actual remote IP when set by an outpost. Only allowed when the request is authenticated, by an outpost internal service account""" if ( @@ -228,7 +229,7 @@ class ClientIPMiddleware: setattr(request, self.request_attr_outpost_user, user) return delegated_ip - def _get_client_ip(self, request: Optional[HttpRequest]) -> str: + def _get_client_ip(self, request: HttpRequest | None) -> str: """Attempt to get the client's IP by checking common HTTP Headers. Returns none if no IP Could be found""" if not request: @@ -239,7 +240,7 @@ class ClientIPMiddleware: return self._get_client_ip_from_meta(request.META) @staticmethod - def get_outpost_user(request: HttpRequest) -> Optional[User]: + def get_outpost_user(request: HttpRequest) -> User | None: """Get outpost user that authenticated this request""" return getattr(request, ClientIPMiddleware.request_attr_outpost_user, None) @@ -293,14 +294,14 @@ class LoggingMiddleware: self.get_response = get_response def __call__(self, request: HttpRequest) -> HttpResponse: - start = default_timer() + start = perf_counter() response = self.get_response(request) status_code = response.status_code kwargs = { "request_id": getattr(request, "request_id", None), } kwargs.update(getattr(response, "ak_context", {})) - self.log(request, status_code, int((default_timer() - start) * 1000), **kwargs) + self.log(request, status_code, int((perf_counter() - start) * 1000), **kwargs) return response def log(self, request: HttpRequest, status_code: int, runtime: int, **kwargs): diff --git a/authentik/root/monitoring.py b/authentik/root/monitoring.py index 7b4ba1e4f6..b6ce04306e 100644 --- a/authentik/root/monitoring.py +++ b/authentik/root/monitoring.py @@ -1,4 +1,5 @@ """Metrics view""" + from base64 import b64encode from django.conf import settings @@ -46,8 +47,8 @@ class ReadyView(View): def dispatch(self, request: HttpRequest) -> HttpResponse: try: - db_conn = connections["default"] - _ = db_conn.cursor() + for db_conn in connections.all(): + _ = db_conn.cursor() except OperationalError: # pragma: no cover return HttpResponse(status=503) try: diff --git a/authentik/root/sessions/pickle.py b/authentik/root/sessions/pickle.py index 94c7f6fc04..a01eaaf8ad 100644 --- a/authentik/root/sessions/pickle.py +++ b/authentik/root/sessions/pickle.py @@ -1,6 +1,7 @@ """ Module for abstract serializer/unserializer base classes. """ + import pickle # nosec diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 4798e4392c..15e689b06e 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -1,16 +1,17 @@ """root settings for authentik""" + import importlib import os from collections import OrderedDict from hashlib import sha512 from pathlib import Path -from urllib.parse import quote_plus from celery.schedules import crontab +from django.conf import ImproperlyConfigured from sentry_sdk import set_tag from authentik import ENV_GIT_HASH_KEY, __version__ -from authentik.lib.config import CONFIG +from authentik.lib.config import CONFIG, redis_url from authentik.lib.logging import get_logger_config, structlog_configure from authentik.lib.sentry import sentry_init from authentik.lib.utils.reflection import get_env @@ -59,6 +60,8 @@ SHARED_APPS = [ "django_filters", "drf_spectacular", "django_prometheus", + "pgactivity", + "pglock", "channels", ] TENANT_APPS = [ @@ -68,7 +71,6 @@ TENANT_APPS = [ "authentik.admin", "authentik.api", "authentik.crypto", - "authentik.events", "authentik.flows", "authentik.outposts", "authentik.policies.dummy", @@ -90,6 +92,7 @@ TENANT_APPS = [ "authentik.sources.oauth", "authentik.sources.plex", "authentik.sources.saml", + "authentik.sources.scim", "authentik.stages.authenticator", "authentik.stages.authenticator_duo", "authentik.stages.authenticator_sms", @@ -154,8 +157,13 @@ SPECTACULAR_SETTINGS = { "LDAPAPIAccessMode": "authentik.providers.ldap.models.APIAccessMode", "UserVerificationEnum": "authentik.stages.authenticator_webauthn.models.UserVerification", "UserTypeEnum": "authentik.core.models.UserTypes", + "OutgoingSyncDeleteAction": "authentik.lib.sync.outgoing.models.OutgoingSyncDeleteAction", }, "ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False, + "ENUM_GENERATE_CHOICE_DESCRIPTION": False, + "PREPROCESSING_HOOKS": [ + "authentik.api.schema.preprocess_schema_exclude_non_api", + ], "POSTPROCESSING_HOOKS": [ "authentik.api.schema.postprocess_schema_responses", "drf_spectacular.hooks.postprocess_schema_enums", @@ -190,23 +198,15 @@ REST_FRAMEWORK = { }, } -_redis_protocol_prefix = "redis://" -_redis_celery_tls_requirements = "" -if CONFIG.get_bool("redis.tls", False): - _redis_protocol_prefix = "rediss://" - _redis_celery_tls_requirements = f"?ssl_cert_reqs={CONFIG.get('redis.tls_reqs')}" -_redis_url = ( - f"{_redis_protocol_prefix}:" - f"{quote_plus(CONFIG.get('redis.password'))}@{quote_plus(CONFIG.get('redis.host'))}:" - f"{CONFIG.get_int('redis.port')}" -) CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", - "LOCATION": CONFIG.get("cache.url") or f"{_redis_url}/{CONFIG.get('redis.db')}", + "LOCATION": CONFIG.get("cache.url") or redis_url(CONFIG.get("redis.db")), "TIMEOUT": CONFIG.get_int("cache.timeout", 300), - "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, "KEY_PREFIX": "authentik_cache", "KEY_FUNCTION": "django_tenants.cache.make_key", "REVERSE_KEY_FUNCTION": "django_tenants.cache.reverse_key", @@ -215,7 +215,15 @@ CACHES = { DJANGO_REDIS_SCAN_ITERSIZE = 1000 DJANGO_REDIS_IGNORE_EXCEPTIONS = True DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True -SESSION_ENGINE = "django.contrib.sessions.backends.cache" +match CONFIG.get("session_storage", "cache"): + case "cache": + SESSION_ENGINE = "django.contrib.sessions.backends.cache" + case "db": + SESSION_ENGINE = "django.contrib.sessions.backends.db" + case _: + raise ImproperlyConfigured( + "Invalid session_storage setting, allowed values are db and cache" + ) SESSION_SERIALIZER = "authentik.root.sessions.pickle.PickleSerializer" SESSION_CACHE_ALIAS = "default" # Configured via custom SessionMiddleware @@ -269,7 +277,7 @@ CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer", "CONFIG": { - "hosts": [CONFIG.get("channel.url", f"{_redis_url}/{CONFIG.get('redis.db')}")], + "hosts": [CONFIG.get("channel.url") or redis_url(CONFIG.get("redis.db"))], "prefix": "authentik_channels_", }, }, @@ -287,7 +295,7 @@ DATABASES = { "NAME": CONFIG.get("postgresql.name"), "USER": CONFIG.get("postgresql.user"), "PASSWORD": CONFIG.get("postgresql.password"), - "PORT": CONFIG.get_int("postgresql.port"), + "PORT": CONFIG.get("postgresql.port"), "SSLMODE": CONFIG.get("postgresql.sslmode"), "SSLROOTCERT": CONFIG.get("postgresql.sslrootcert"), "SSLCERT": CONFIG.get("postgresql.sslcert"), @@ -307,7 +315,23 @@ if CONFIG.get_bool("postgresql.use_pgbouncer", False): # https://docs.djangoproject.com/en/4.0/ref/databases/#persistent-connections DATABASES["default"]["CONN_MAX_AGE"] = None # persistent -DATABASE_ROUTERS = ("django_tenants.routers.TenantSyncRouter",) +for replica in CONFIG.get_keys("postgresql.read_replicas"): + _database = DATABASES["default"].copy() + for setting in DATABASES["default"].keys(): + default = object() + if setting in ("TEST",): + continue + override = CONFIG.get( + f"postgresql.read_replicas.{replica}.{setting.lower()}", default=default + ) + if override is not default: + _database[setting] = override + DATABASES[f"replica_{replica}"] = _database + +DATABASE_ROUTERS = ( + "authentik.tenants.db.FailoverRouter", + "django_tenants.routers.TenantSyncRouter", +) # Email # These values should never actually be used, emails are only sent from email stages, which @@ -369,11 +393,15 @@ CELERY = { "beat_scheduler": "authentik.tenants.scheduler:TenantAwarePersistentScheduler", "task_create_missing_queues": True, "task_default_queue": "authentik", - "broker_url": CONFIG.get("broker.url") - or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", - "broker_transport_options": CONFIG.get_dict_from_b64_json("broker.transport_options"), - "result_backend": CONFIG.get("result_backend.url") - or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", + "broker_url": CONFIG.get("broker.url") or redis_url(CONFIG.get("redis.db")), + "result_backend": CONFIG.get("result_backend.url") or redis_url(CONFIG.get("redis.db")), + "broker_transport_options": CONFIG.get_dict_from_b64_json( + "broker.transport_options", {"retry_policy": {"timeout": 5.0}} + ), + "result_backend_transport_options": CONFIG.get_dict_from_b64_json( + "result_backend.transport_options", {"retry_policy": {"timeout": 5.0}} + ), + "redis_retry_on_timeout": True, } # Sentry integration @@ -417,9 +445,9 @@ if CONFIG.get("storage.media.backend", "file") == "s3": "signature_version": "s3v4", "file_overwrite": False, "location": "media", - "url_protocol": "https:" - if CONFIG.get("storage.media.s3.secure_urls", True) - else "http:", + "url_protocol": ( + "https:" if CONFIG.get("storage.media.s3.secure_urls", True) else "http:" + ), "custom_domain": CONFIG.get("storage.media.s3.custom_domain", None), }, } @@ -481,13 +509,6 @@ def _update_settings(app_path: str): pass -# Load subapps's settings -for _app in set(SHARED_APPS + TENANT_APPS): - if not _app.startswith("authentik"): - continue - _update_settings(f"{_app}.settings") -_update_settings("data.user_settings") - if DEBUG: CELERY["task_always_eager"] = True os.environ[ENV_GIT_HASH_KEY] = "dev" @@ -508,5 +529,17 @@ try: except ImportError: pass +# Import events after other apps since it relies on tasks and other things from all apps +# being imported for @prefill_task +TENANT_APPS.append("authentik.events") + + +# Load subapps's settings +for _app in set(SHARED_APPS + TENANT_APPS): + if not _app.startswith("authentik"): + continue + _update_settings(f"{_app}.settings") +_update_settings("data.user_settings") + SHARED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS)) INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS)) diff --git a/authentik/root/signals.py b/authentik/root/signals.py new file mode 100644 index 0000000000..51543dbd03 --- /dev/null +++ b/authentik/root/signals.py @@ -0,0 +1,26 @@ +from datetime import timedelta + +from django.core.signals import Signal +from django.dispatch import receiver +from django.utils.timezone import now +from structlog.stdlib import get_logger + +# Signal dispatched before actual startup trigger +pre_startup = Signal() +# Signal dispatched which should trigger all startup logic +startup = Signal() +# Signal dispatched after the startup logic +post_startup = Signal() + +LOGGER = get_logger() + + +@receiver(pre_startup) +def pre_startup_log(sender, **_): + sender._start_time = now() + + +@receiver(post_startup) +def post_startup_log(sender, **_): + took: timedelta = now() - sender._start_time + LOGGER.info("authentik Core Worker finished starting", took_s=took.total_seconds()) diff --git a/authentik/root/storages.py b/authentik/root/storages.py index 347200f964..f1c6f516be 100644 --- a/authentik/root/storages.py +++ b/authentik/root/storages.py @@ -1,4 +1,5 @@ """authentik storage backends""" + import os from django.conf import settings @@ -14,19 +15,16 @@ from authentik.lib.config import CONFIG class FileStorage(FileSystemStorage): """File storage backend""" - # pylint: disable=invalid-overridden-method @property def base_location(self): return os.path.join( self._value_or_setting(self._location, settings.MEDIA_ROOT), connection.schema_name ) - # pylint: disable=invalid-overridden-method @property def location(self): return os.path.abspath(self.base_location) - # pylint: disable=invalid-overridden-method @property def base_url(self): if self._base_url is not None and not self._base_url.endswith("/"): @@ -34,7 +32,6 @@ class FileStorage(FileSystemStorage): return f"{self._base_url}/{connection.schema_name}/" -# pylint: disable=abstract-method class S3Storage(BaseS3Storage): """S3 storage backend""" @@ -76,13 +73,12 @@ class S3Storage(BaseS3Storage): def _normalize_name(self, name): try: - # pylint: disable=no-member + return safe_join(self.location, connection.schema_name, name) except ValueError: - raise SuspiciousOperation("Attempted access to '%s' denied." % name) + raise SuspiciousOperation(f"Attempted access to '{name}' denied.") from None # This is a fix for https://github.com/jschneier/django-storages/pull/839 - # pylint: disable=arguments-differ,no-member def url(self, name, parameters=None, expire=None, http_method=None): # Preserve the trailing slash after normalizing the path. name = self._normalize_name(clean_name(name)) @@ -108,7 +104,7 @@ class S3Storage(BaseS3Storage): # Remove signing parameter and previously added key "/". root_url = self._strip_signing_parameters(root_url_signed)[:-1] # Replace bucket domain with custom domain. - custom_url = "{}//{}/".format(self.url_protocol, self.custom_domain) + custom_url = f"{self.url_protocol}//{self.custom_domain}/" url = url.replace(root_url, custom_url) if self.querystring_auth: diff --git a/authentik/root/test_plugin.py b/authentik/root/test_plugin.py new file mode 100644 index 0000000000..815b8e485b --- /dev/null +++ b/authentik/root/test_plugin.py @@ -0,0 +1,26 @@ +from os import environ +from ssl import OPENSSL_VERSION + +import pytest +from cryptography.hazmat.backends.openssl.backend import backend + +from authentik import get_full_version + +IS_CI = "CI" in environ + + +@pytest.hookimpl(hookwrapper=True) +def pytest_sessionstart(*_, **__): + """Clear the console ahead of the pytest output starting""" + if not IS_CI: + print("\x1b[2J\x1b[H") + yield + + +@pytest.hookimpl(trylast=True) +def pytest_report_header(*_, **__): + """Add authentik version to pytest output""" + return [ + f"authentik version: {get_full_version()}", + f"OpenSSL version: {OPENSSL_VERSION}, FIPS: {backend._fips_enabled}", + ] diff --git a/authentik/root/test_runner.py b/authentik/root/test_runner.py index 59956febb8..867469d2b0 100644 --- a/authentik/root/test_runner.py +++ b/authentik/root/test_runner.py @@ -1,13 +1,16 @@ """Integrate ./manage.py test with pytest""" + import os from argparse import ArgumentParser from unittest import TestCase +import pytest from django.conf import settings from django.test.runner import DiscoverRunner from authentik.lib.config import CONFIG from authentik.lib.sentry import sentry_init +from authentik.root.signals import post_startup, pre_startup, startup from tests.e2e.utils import get_docker_tag # globally set maxDiff to none to show full assert error @@ -45,6 +48,10 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover CONFIG.set("error_reporting.send_pii", True) sentry_init() + pre_startup.send(sender=self, mode="test") + startup.send(sender=self, mode="test") + post_startup.send(sender=self, mode="test") + @classmethod def add_arguments(cls, parser: ArgumentParser): """Add more pytest-specific arguments""" @@ -76,23 +83,21 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover if os.path.exists(label_as_path): self.args.append(label_as_path) valid_label_found = True + elif "::" in label: + self.args.append(label) + valid_label_found = True + # Convert dotted module path to file_path::class::method else: - # Already correctly formatted test found (file_path::class::method) - if "::" in label: - self.args.append(label) - valid_label_found = True - # Convert dotted module path to file_path::class::method - else: - path_pieces = label.split(".") - # Check whether only class or class and method are specified - for i in range(-1, -3, -1): - path = os.path.join(*path_pieces[:i]) + ".py" - label_as_path = os.path.abspath(path) - if os.path.exists(label_as_path): - path_method = label_as_path + "::" + "::".join(path_pieces[i:]) - self.args.append(path_method) - valid_label_found = True - break + path_pieces = label.split(".") + # Check whether only class or class and method are specified + for i in range(-1, -3, -1): + path = os.path.join(*path_pieces[:i]) + ".py" + label_as_path = os.path.abspath(path) + if os.path.exists(label_as_path): + path_method = label_as_path + "::" + "::".join(path_pieces[i:]) + self.args.append(path_method) + valid_label_found = True + break if not valid_label_found: raise RuntimeError( @@ -101,6 +106,4 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover f"path instead." ) - import pytest - return pytest.main(self.args) diff --git a/authentik/root/tests.py b/authentik/root/tests.py index 444a4ada63..f0cee99fe9 100644 --- a/authentik/root/tests.py +++ b/authentik/root/tests.py @@ -1,4 +1,5 @@ """root tests""" + from base64 import b64encode from django.conf import settings diff --git a/authentik/root/urls.py b/authentik/root/urls.py index b3913090a4..1b03051fdd 100644 --- a/authentik/root/urls.py +++ b/authentik/root/urls.py @@ -1,4 +1,5 @@ """authentik URL Configuration""" + from django.urls import include, path from structlog.stdlib import get_logger @@ -19,10 +20,10 @@ for _authentik_app in get_apps(): mountpoints = None base_url_module = _authentik_app.name + ".urls" if hasattr(_authentik_app, "mountpoint"): - mountpoint = getattr(_authentik_app, "mountpoint") + mountpoint = _authentik_app.mountpoint mountpoints = {base_url_module: mountpoint} if hasattr(_authentik_app, "mountpoints"): - mountpoints = getattr(_authentik_app, "mountpoints") + mountpoints = _authentik_app.mountpoints if not mountpoints: continue for module, mountpoint in mountpoints.items(): diff --git a/authentik/root/websocket.py b/authentik/root/websocket.py index df32a35af1..560a39c07d 100644 --- a/authentik/root/websocket.py +++ b/authentik/root/websocket.py @@ -1,4 +1,5 @@ """root Websocket URLS""" + from importlib import import_module from structlog.stdlib import get_logger @@ -15,7 +16,7 @@ for _authentik_app in get_apps(): continue if not hasattr(api_urls, "websocket_urlpatterns"): continue - urls: list = getattr(api_urls, "websocket_urlpatterns") + urls: list = api_urls.websocket_urlpatterns websocket_urlpatterns.extend(urls) LOGGER.debug( "Mounted Websocket URLs", diff --git a/authentik/sources/ldap/api.py b/authentik/sources/ldap/api.py index e4bdf79d73..faaca0a533 100644 --- a/authentik/sources/ldap/api.py +++ b/authentik/sources/ldap/api.py @@ -1,5 +1,6 @@ """Source API Views""" -from typing import Any, Optional + +from typing import Any from django.core.cache import cache from django_filters.filters import AllValuesMultipleFilter @@ -9,18 +10,17 @@ from drf_spectacular.utils import extend_schema, extend_schema_field, inline_ser from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action from rest_framework.exceptions import ValidationError -from rest_framework.fields import BooleanField, DictField, ListField, SerializerMethodField +from rest_framework.fields import DictField, ListField, SerializerMethodField from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.request import Request from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet -from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.property_mappings import PropertyMappingSerializer from authentik.core.api.sources import SourceSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer from authentik.crypto.models import CertificateKeyPair -from authentik.events.api.tasks import SystemTaskSerializer +from authentik.lib.sync.outgoing.api import SyncStatusSerializer from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.tasks import CACHE_KEY_STATUS, SYNC_CLASSES @@ -38,7 +38,7 @@ class LDAPSourceSerializer(SourceSerializer): required=False, ) - def get_connectivity(self, source: LDAPSource) -> Optional[dict[str, dict[str, str]]]: + def get_connectivity(self, source: LDAPSource) -> dict[str, dict[str, str]] | None: """Get cached source connectivity""" return cache.get(CACHE_KEY_STATUS + source.slug, None) @@ -76,6 +76,7 @@ class LDAPSourceSerializer(SourceSerializer): "group_object_filter", "group_membership_field", "object_uniqueness_field", + "password_login_update_internal_password", "sync_users", "sync_users_password", "sync_groups", @@ -87,13 +88,6 @@ class LDAPSourceSerializer(SourceSerializer): extra_kwargs = {"bind_password": {"write_only": True}} -class LDAPSyncStatusSerializer(PassiveSerializer): - """LDAP Source sync status""" - - is_running = BooleanField(read_only=True) - tasks = SystemTaskSerializer(many=True, read_only=True) - - class LDAPSourceViewSet(UsedByMixin, ModelViewSet): """LDAP Source Viewset""" @@ -117,6 +111,7 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): "group_object_filter", "group_membership_field", "object_uniqueness_field", + "password_login_update_internal_password", "sync_users", "sync_users_password", "sync_groups", @@ -129,10 +124,16 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): @extend_schema( responses={ - 200: LDAPSyncStatusSerializer(), + 200: SyncStatusSerializer(), } ) - @action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[]) + @action( + methods=["GET"], + detail=True, + pagination_class=None, + url_path="sync/status", + filter_backends=[], + ) def sync_status(self, request: Request, slug: str) -> Response: """Get source's sync status""" source: LDAPSource = self.get_object() @@ -142,11 +143,13 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): uid__startswith=source.slug, ) ) - status = { - "tasks": tasks, - "is_running": source.sync_lock.locked(), - } - return Response(LDAPSyncStatusSerializer(status).data) + with source.sync_lock as lock_acquired: + status = { + "tasks": tasks, + # If we could not acquire the lock, it means a task is using it, and thus is running + "is_running": not lock_acquired, + } + return Response(SyncStatusSerializer(status).data) @extend_schema( responses={ diff --git a/authentik/sources/ldap/apps.py b/authentik/sources/ldap/apps.py index eb1f5e2c08..808a048a25 100644 --- a/authentik/sources/ldap/apps.py +++ b/authentik/sources/ldap/apps.py @@ -1,4 +1,5 @@ """authentik ldap source config""" + from authentik.blueprints.apps import ManagedAppConfig @@ -9,7 +10,3 @@ class AuthentikSourceLDAPConfig(ManagedAppConfig): label = "authentik_sources_ldap" verbose_name = "authentik Sources.LDAP" default = True - - def reconcile_global_load_sources_ldap_signals(self): - """Load sources.ldap signals""" - self.import_module("authentik.sources.ldap.signals") diff --git a/authentik/sources/ldap/auth.py b/authentik/sources/ldap/auth.py index 508aacb3ea..37321ea05f 100644 --- a/authentik/sources/ldap/auth.py +++ b/authentik/sources/ldap/auth.py @@ -1,5 +1,4 @@ """authentik LDAP Authentication Backend""" -from typing import Optional from django.http import HttpRequest from ldap3.core.exceptions import LDAPException, LDAPInvalidCredentialsResult @@ -28,7 +27,7 @@ class LDAPBackend(InbuiltBackend): return user return None - def auth_user(self, source: LDAPSource, password: str, **filters: str) -> Optional[User]: + def auth_user(self, source: LDAPSource, password: str, **filters: str) -> User | None: """Try to bind as either user_dn or mail with password. Returns True on success, otherwise False""" users = User.objects.filter(**filters) @@ -42,16 +41,17 @@ class LDAPBackend(InbuiltBackend): # or has a password, but couldn't be authenticated by ModelBackend. # This means we check with a bind to see if the LDAP password has changed if self.auth_user_by_bind(source, user, password): - # Password given successfully binds to LDAP, so we save it in our Database - LOGGER.debug("Updating user's password in DB", user=user) - user.set_password(password, signal=False) - user.save() + if source.password_login_update_internal_password: + # Password given successfully binds to LDAP, so we save it in our Database + LOGGER.debug("Updating user's password in DB", user=user) + user.set_password(password, signal=False) + user.save() return user # Password doesn't match LOGGER.debug("Failed to bind, password invalid") return None - def auth_user_by_bind(self, source: LDAPSource, user: User, password: str) -> Optional[User]: + def auth_user_by_bind(self, source: LDAPSource, user: User, password: str) -> User | None: """Attempt authentication by binding to the LDAP server as `user`. This method should be avoided as its slow to do the bind.""" # Try to bind as new user diff --git a/authentik/sources/ldap/management/commands/ldap_check_connection.py b/authentik/sources/ldap/management/commands/ldap_check_connection.py index c3caed86b7..0bde7bfec5 100644 --- a/authentik/sources/ldap/management/commands/ldap_check_connection.py +++ b/authentik/sources/ldap/management/commands/ldap_check_connection.py @@ -1,4 +1,5 @@ """LDAP Connection check""" + from json import dumps from structlog.stdlib import get_logger diff --git a/authentik/sources/ldap/management/commands/ldap_sync.py b/authentik/sources/ldap/management/commands/ldap_sync.py index fd0a48d635..22404ad49e 100644 --- a/authentik/sources/ldap/management/commands/ldap_sync.py +++ b/authentik/sources/ldap/management/commands/ldap_sync.py @@ -1,4 +1,5 @@ """LDAP Sync""" + from structlog.stdlib import get_logger from authentik.sources.ldap.models import LDAPSource diff --git a/authentik/sources/ldap/migrations/0004_ldapsource_password_login_update_internal_password.py b/authentik/sources/ldap/migrations/0004_ldapsource_password_login_update_internal_password.py new file mode 100644 index 0000000000..cacbe62684 --- /dev/null +++ b/authentik/sources/ldap/migrations/0004_ldapsource_password_login_update_internal_password.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.1 on 2024-01-31 18:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_sources_ldap", "0003_ldapsource_client_certificate_ldapsource_sni_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="ldapsource", + name="password_login_update_internal_password", + field=models.BooleanField( + default=True, + help_text="Update internal authentik password when login succeeds with LDAP", + ), + ), + migrations.AlterField( + model_name="ldapsource", + name="password_login_update_internal_password", + field=models.BooleanField( + default=False, + help_text="Update internal authentik password when login succeeds with LDAP", + ), + ), + ] diff --git a/authentik/sources/ldap/models.py b/authentik/sources/ldap/models.py index c9ecda4efd..7752276d52 100644 --- a/authentik/sources/ldap/models.py +++ b/authentik/sources/ldap/models.py @@ -1,17 +1,17 @@ """authentik LDAP Models""" + from os import chmod from os.path import dirname, exists from shutil import rmtree from ssl import CERT_REQUIRED from tempfile import NamedTemporaryFile, mkdtemp -from typing import Optional -from django.core.cache import cache +import pglock from django.db import connection, models +from django.templatetags.static import static from django.utils.translation import gettext_lazy as _ from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls from ldap3.core.exceptions import LDAPException, LDAPInsufficientAccessRightsResult, LDAPSchemaError -from redis.lock import Lock from rest_framework.serializers import Serializer from authentik.core.models import Group, PropertyMapping, Source @@ -98,6 +98,11 @@ class LDAPSource(Source): help_text=_("Property mappings used for group creation/updating."), ) + password_login_update_internal_password = models.BooleanField( + default=False, + help_text=_("Update internal authentik password when login succeeds with LDAP"), + ) + sync_users = models.BooleanField(default=True) sync_users_password = models.BooleanField( default=True, @@ -121,6 +126,10 @@ class LDAPSource(Source): return LDAPSourceSerializer + @property + def icon_url(self) -> str: + return static("authentik/sources/ldap.png") + def server(self, **kwargs) -> ServerPool: """Get LDAP Server/ServerPool""" servers = [] @@ -159,9 +168,9 @@ class LDAPSource(Source): def connection( self, - server: Optional[Server] = None, - server_kwargs: Optional[dict] = None, - connection_kwargs: Optional[dict] = None, + server: Server | None = None, + server_kwargs: dict | None = None, + connection_kwargs: dict | None = None, ) -> Connection: """Get a fully connected and bound LDAP Connection""" server_kwargs = server_kwargs or {} @@ -199,15 +208,12 @@ class LDAPSource(Source): return RuntimeError("Failed to bind") @property - def sync_lock(self) -> Lock: - """Redis lock for syncing LDAP to prevent multiple parallel syncs happening""" - return Lock( - cache.client.get_client(), - name=f"goauthentik.io/sources/ldap/sync/{connection.schema_name}-{self.slug}", - # Convert task timeout hours to seconds, and multiply times 3 - # (see authentik/sources/ldap/tasks.py:54) - # multiply by 3 to add even more leeway - timeout=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3, + def sync_lock(self) -> pglock.advisory: + """Postgres lock for syncing LDAP to prevent multiple parallel syncs happening""" + return pglock.advisory( + lock_id=f"goauthentik.io/{connection.schema_name}/sources/ldap/sync/{self.slug}", + timeout=0, + side_effect=pglock.Return, ) def check_connection(self) -> dict[str, dict[str, str]]: diff --git a/authentik/sources/ldap/password.py b/authentik/sources/ldap/password.py index 0593b2078f..662778aa8d 100644 --- a/authentik/sources/ldap/password.py +++ b/authentik/sources/ldap/password.py @@ -1,7 +1,7 @@ """Help validate and update passwords in LDAP""" + from enum import IntFlag from re import split -from typing import Optional from ldap3 import BASE from ldap3.core.exceptions import ( @@ -19,6 +19,7 @@ LOGGER = get_logger() NON_ALPHA = r"~!@#$%^&*_-+=`|\(){}[]:;\"'<>,.?/" RE_DISPLAYNAME_SEPARATORS = r",\.–—_\s#\t" +MIN_TOKEN_SIZE = 3 class PwdProperties(IntFlag): @@ -118,7 +119,7 @@ class LDAPPasswordChanger: raise AssertionError() user_attributes = users[0]["attributes"] # If sAMAccountName is longer than 3 chars, check if its contained in password - if len(user_attributes["sAMAccountName"]) >= 3: + if len(user_attributes["sAMAccountName"]) >= MIN_TOKEN_SIZE: if password.lower() in user_attributes["sAMAccountName"].lower(): return False # No display name set, can't check any further @@ -128,13 +129,13 @@ class LDAPPasswordChanger: display_name_tokens = split(RE_DISPLAYNAME_SEPARATORS, display_name) for token in display_name_tokens: # Ignore tokens under 3 chars - if len(token) < 3: + if len(token) < MIN_TOKEN_SIZE: continue if token.lower() in password.lower(): return False return True - def ad_password_complexity(self, password: str, user: Optional[User] = None) -> bool: + def ad_password_complexity(self, password: str, user: User | None = None) -> bool: """Check if password matches Active directory password policies https://docs.microsoft.com/en-us/windows/security/threat-protection/ diff --git a/authentik/sources/ldap/settings.py b/authentik/sources/ldap/settings.py index b141687f59..c82dbeb0cb 100644 --- a/authentik/sources/ldap/settings.py +++ b/authentik/sources/ldap/settings.py @@ -1,4 +1,5 @@ """LDAP Settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/sources/ldap/signals.py b/authentik/sources/ldap/signals.py index f95662e335..3213f9fc2a 100644 --- a/authentik/sources/ldap/signals.py +++ b/authentik/sources/ldap/signals.py @@ -1,4 +1,5 @@ """authentik ldap source signals""" + from typing import Any from django.db.models.signals import post_save diff --git a/authentik/sources/ldap/sync/base.py b/authentik/sources/ldap/sync/base.py index d3ae11f321..8435b80d5c 100644 --- a/authentik/sources/ldap/sync/base.py +++ b/authentik/sources/ldap/sync/base.py @@ -1,18 +1,25 @@ """Sync LDAP Users and groups into authentik""" -from typing import Any, Generator + +from collections.abc import Generator +from typing import Any from django.conf import settings from django.db.models.base import Model -from django.db.models.query import QuerySet from ldap3 import DEREF_ALWAYS, SUBTREE, Connection from structlog.stdlib import BoundLogger, get_logger -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import ( + PropertyMappingExpressionException, + SkipObjectException, +) from authentik.events.models import Event, EventAction from authentik.lib.config import CONFIG, set_path_in_dict from authentik.lib.merge import MERGE_LIST_UNIQUE +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.lib.sync.outgoing.exceptions import StopSync +from authentik.lib.utils.errors import exception_to_string from authentik.sources.ldap.auth import LDAP_DISTINGUISHED_NAME -from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource +from authentik.sources.ldap.models import LDAPSource LDAP_UNIQUENESS = "ldap_uniq" @@ -33,6 +40,7 @@ class BaseLDAPSynchronizer: _logger: BoundLogger _connection: Connection _messages: list[str] + mapper: PropertyMappingManager def __init__(self, source: LDAPSource): self._source = source @@ -89,8 +97,7 @@ class BaseLDAPSynchronizer: """Get objects from LDAP, implemented in subclass""" raise NotImplementedError() - # pylint: disable=too-many-arguments - def search_paginator( + def search_paginator( # noqa: PLR0913 self, search_base, search_filter, @@ -102,11 +109,13 @@ class BaseLDAPSynchronizer: types_only=False, get_operational_attributes=False, controls=None, - paged_size=CONFIG.get_int("ldap.page_size", 50), + paged_size=None, paged_criticality=False, ): """Search in pages, returns each page""" cookie = True + if not paged_size: + paged_size = CONFIG.get_int("ldap.page_size", 50) while cookie: self._connection.search( search_base, @@ -133,50 +142,47 @@ class BaseLDAPSynchronizer: def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]: """Build attributes for User object based on property mappings.""" - props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs) + props = self._build_object_properties(user_dn, **kwargs) props.setdefault("path", self._source.get_user_path()) return props def build_group_properties(self, group_dn: str, **kwargs) -> dict[str, Any]: """Build attributes for Group object based on property mappings.""" - return self._build_object_properties( - group_dn, self._source.property_mappings_group, **kwargs - ) + return self._build_object_properties(group_dn, **kwargs) - def _build_object_properties( - self, object_dn: str, mappings: QuerySet, **kwargs - ) -> dict[str, dict[Any, Any]]: + def _build_object_properties(self, object_dn: str, **kwargs) -> dict[str, dict[Any, Any]]: properties = {"attributes": {}} - for mapping in mappings.all().select_subclasses(): - if not isinstance(mapping, LDAPPropertyMapping): - continue - mapping: LDAPPropertyMapping - try: - value = mapping.evaluate( - user=None, request=None, ldap=kwargs, dn=object_dn, source=self._source - ) - if value is None: - self._logger.warning("property mapping returned None", mapping=mapping) - continue - if isinstance(value, (bytes)): - self._logger.warning("property mapping returned bytes", mapping=mapping) - continue - object_field = mapping.object_field - if object_field.startswith("attributes."): - # Because returning a list might desired, we can't - # rely on flatten here. Instead, just save the result as-is - set_path_in_dict(properties, object_field, value) - else: - properties[object_field] = flatten(value) - except PropertyMappingExpressionException as exc: - Event.new( - EventAction.CONFIGURATION_ERROR, - message=f"Failed to evaluate property-mapping: '{mapping.name}'", - source=self._source, - mapping=mapping, - ).save() - self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping) - continue + try: + for value, mapping in self.mapper.iter_eval( + user=None, + request=None, + return_mapping=True, + ldap=kwargs, + dn=object_dn, + source=self._source, + ): + try: + if isinstance(value, (bytes)): + self._logger.warning("property mapping returned bytes", mapping=mapping) + continue + object_field = mapping.object_field + if object_field.startswith("attributes."): + # Because returning a list might desired, we can't + # rely on flatten here. Instead, just save the result as-is + set_path_in_dict(properties, object_field, value) + else: + properties[object_field] = flatten(value) + except SkipObjectException as exc: + raise exc from exc + except PropertyMappingExpressionException as exc: + # Value error can be raised when assigning invalid data to an attribute + Event.new( + EventAction.CONFIGURATION_ERROR, + message=f"Failed to evaluate property-mapping {exception_to_string(exc)}", + mapping=exc.mapping, + ).save() + self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=exc.mapping) + raise StopSync(exc, None, exc.mapping) from exc if self._source.object_uniqueness_field in kwargs: properties["attributes"][LDAP_UNIQUENESS] = flatten( kwargs.get(self._source.object_uniqueness_field) diff --git a/authentik/sources/ldap/sync/groups.py b/authentik/sources/ldap/sync/groups.py index 92781c3ac9..739e1af911 100644 --- a/authentik/sources/ldap/sync/groups.py +++ b/authentik/sources/ldap/sync/groups.py @@ -1,18 +1,30 @@ """Sync LDAP Users and groups into authentik""" -from typing import Generator + +from collections.abc import Generator from django.core.exceptions import FieldError from django.db.utils import IntegrityError from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE +from authentik.core.expression.exceptions import SkipObjectException from authentik.core.models import Group from authentik.events.models import Event, EventAction +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten class GroupLDAPSynchronizer(BaseLDAPSynchronizer): """Sync LDAP Users and groups into authentik""" + def __init__(self, source: LDAPSource): + super().__init__(source) + self.mapper = PropertyMappingManager( + self._source.property_mappings_group.all().order_by("name").select_subclasses(), + LDAPPropertyMapping, + ["ldap", "dn", "source"], + ) + @staticmethod def name() -> str: return "groups" @@ -64,6 +76,8 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer): defaults, ) self._logger.debug("Created group with attributes", **defaults) + except SkipObjectException: + continue except (IntegrityError, FieldError, TypeError, AttributeError) as exc: Event.new( EventAction.CONFIGURATION_ERROR, diff --git a/authentik/sources/ldap/sync/membership.py b/authentik/sources/ldap/sync/membership.py index 134f12380d..7d2a60f5d4 100644 --- a/authentik/sources/ldap/sync/membership.py +++ b/authentik/sources/ldap/sync/membership.py @@ -1,5 +1,7 @@ """Sync LDAP Users and groups into authentik""" -from typing import Any, Generator, Optional + +from collections.abc import Generator +from typing import Any from django.db.models import Q from ldap3 import SUBTREE @@ -75,7 +77,7 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer): self._logger.debug("Successfully updated group membership") return membership_count - def get_group(self, group_dict: dict[str, Any]) -> Optional[Group]: + def get_group(self, group_dict: dict[str, Any]) -> Group | None: """Check if we fetched the group already, and if not cache it for later""" group_dn = group_dict.get("attributes", {}).get(LDAP_DISTINGUISHED_NAME, []) group_uniq = group_dict.get("attributes", {}).get(self._source.object_uniqueness_field, []) diff --git a/authentik/sources/ldap/sync/users.py b/authentik/sources/ldap/sync/users.py index 6c4d3bd0e5..188dad1771 100644 --- a/authentik/sources/ldap/sync/users.py +++ b/authentik/sources/ldap/sync/users.py @@ -1,12 +1,16 @@ """Sync LDAP Users into authentik""" -from typing import Generator + +from collections.abc import Generator from django.core.exceptions import FieldError from django.db.utils import IntegrityError from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE +from authentik.core.expression.exceptions import SkipObjectException from authentik.core.models import User from authentik.events.models import Event, EventAction +from authentik.lib.sync.mapper import PropertyMappingManager +from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory @@ -15,6 +19,14 @@ from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory class UserLDAPSynchronizer(BaseLDAPSynchronizer): """Sync LDAP Users into authentik""" + def __init__(self, source: LDAPSource): + super().__init__(source) + self.mapper = PropertyMappingManager( + self._source.property_mappings.all().order_by("name").select_subclasses(), + LDAPPropertyMapping, + ["ldap", "dn", "source"], + ) + @staticmethod def name() -> str: return "users" @@ -58,6 +70,8 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): ak_user, created = self.update_or_create_attributes( User, {f"attributes__{LDAP_UNIQUENESS}": uniq}, defaults ) + except SkipObjectException: + continue except (IntegrityError, FieldError, TypeError, AttributeError) as exc: Event.new( EventAction.CONFIGURATION_ERROR, diff --git a/authentik/sources/ldap/sync/vendor/freeipa.py b/authentik/sources/ldap/sync/vendor/freeipa.py index d8014f7161..83405ddd19 100644 --- a/authentik/sources/ldap/sync/vendor/freeipa.py +++ b/authentik/sources/ldap/sync/vendor/freeipa.py @@ -1,6 +1,8 @@ """FreeIPA specific""" -from datetime import datetime, timezone -from typing import Any, Generator + +from collections.abc import Generator +from datetime import UTC, datetime +from typing import Any from authentik.core.models import User from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer, flatten @@ -25,7 +27,7 @@ class FreeIPA(BaseLDAPSynchronizer): if "krbLastPwdChange" not in attributes: return pwd_last_set: datetime = attributes.get("krbLastPwdChange", datetime.now()) - pwd_last_set = pwd_last_set.replace(tzinfo=timezone.utc) + pwd_last_set = pwd_last_set.replace(tzinfo=UTC) if created or pwd_last_set >= user.password_change_date: self.message(f"'{user.username}': Reset user's password") self._logger.debug( diff --git a/authentik/sources/ldap/sync/vendor/ms_ad.py b/authentik/sources/ldap/sync/vendor/ms_ad.py index 342b104d97..e8fdf831c8 100644 --- a/authentik/sources/ldap/sync/vendor/ms_ad.py +++ b/authentik/sources/ldap/sync/vendor/ms_ad.py @@ -1,7 +1,9 @@ """Active Directory specific""" -from datetime import datetime, timezone + +from collections.abc import Generator +from datetime import UTC, datetime from enum import IntFlag -from typing import Any, Generator +from typing import Any from authentik.core.models import User from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer @@ -56,7 +58,7 @@ class MicrosoftActiveDirectory(BaseLDAPSynchronizer): if "pwdLastSet" not in attributes: return pwd_last_set: datetime = attributes.get("pwdLastSet", datetime.now()) - pwd_last_set = pwd_last_set.replace(tzinfo=timezone.utc) + pwd_last_set = pwd_last_set.replace(tzinfo=UTC) if created or pwd_last_set >= user.password_change_date: self.message(f"'{user.username}': Reset user's password") self._logger.debug( diff --git a/authentik/sources/ldap/tasks.py b/authentik/sources/ldap/tasks.py index 0b5dd5ab26..2f0547a6ab 100644 --- a/authentik/sources/ldap/tasks.py +++ b/authentik/sources/ldap/tasks.py @@ -1,17 +1,17 @@ """LDAP Sync tasks""" -from typing import Optional + from uuid import uuid4 from celery import chain, group from django.core.cache import cache from ldap3.core.exceptions import LDAPException -from redis.exceptions import LockError from structlog.stdlib import get_logger from authentik.events.models import SystemTask as DBSystemTask from authentik.events.models import TaskStatus from authentik.events.system_tasks import SystemTask from authentik.lib.config import CONFIG +from authentik.lib.sync.outgoing.exceptions import StopSync from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.reflection import class_to_path, path_to_class from authentik.root.celery import CELERY_APP @@ -39,7 +39,7 @@ def ldap_sync_all(): @CELERY_APP.task() -def ldap_connectivity_check(pk: Optional[str] = None): +def ldap_connectivity_check(pk: str | None = None): """Check connectivity for LDAP Sources""" # 2 hour timeout, this task should run every hour timeout = 60 * 60 * 2 @@ -63,30 +63,24 @@ def ldap_sync_single(source_pk: str): source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first() if not source: return - lock = source.sync_lock - if lock.locked(): - LOGGER.debug("LDAP sync locked, skipping task", source=source.slug) - return - try: - with lock: - # Delete all sync tasks from the cache - DBSystemTask.objects.filter(name="ldap_sync", uid__startswith=source.slug).delete() - task = chain( - # User and group sync can happen at once, they have no dependencies on each other - group( - ldap_sync_paginator(source, UserLDAPSynchronizer) - + ldap_sync_paginator(source, GroupLDAPSynchronizer), - ), - # Membership sync needs to run afterwards - group( - ldap_sync_paginator(source, MembershipLDAPSynchronizer), - ), - ) - task() - except LockError: - # This should never happen, we check if the lock is locked above so this - # would only happen if there was some other timeout - LOGGER.debug("Failed to acquire lock for LDAP sync", source=source.slug) + with source.sync_lock as lock_acquired: + if not lock_acquired: + LOGGER.debug("Failed to acquire lock for LDAP sync, skipping task", source=source.slug) + return + # Delete all sync tasks from the cache + DBSystemTask.objects.filter(name="ldap_sync", uid__startswith=source.slug).delete() + task = chain( + # User and group sync can happen at once, they have no dependencies on each other + group( + ldap_sync_paginator(source, UserLDAPSynchronizer) + + ldap_sync_paginator(source, GroupLDAPSynchronizer), + ), + # Membership sync needs to run afterwards + group( + ldap_sync_paginator(source, MembershipLDAPSynchronizer), + ), + ) + task() def ldap_sync_paginator(source: LDAPSource, sync: type[BaseLDAPSynchronizer]) -> list: @@ -138,7 +132,7 @@ def ldap_sync(self: SystemTask, source_pk: str, sync_class: str, page_cache_key: *messages, ) cache.delete(page_cache_key) - except LDAPException as exc: + except (LDAPException, StopSync) as exc: # No explicit event is created here as .set_status with an error will do that LOGGER.warning(exception_to_string(exc)) self.set_error(exc) diff --git a/authentik/sources/ldap/tests/mock_ad.py b/authentik/sources/ldap/tests/mock_ad.py index b0914bda4f..9c0be2109c 100644 --- a/authentik/sources/ldap/tests/mock_ad.py +++ b/authentik/sources/ldap/tests/mock_ad.py @@ -34,7 +34,7 @@ def mock_ad_connection(password: str) -> Connection: "objectSid": "unique-test-group", "objectClass": "group", "distinguishedName": "cn=group1,ou=groups,dc=goauthentik,dc=io", - "member": ["cn=user0,ou=users,dc=goauthentik,dc=io"], + "member": ["cn=user,ou=users,dc=goauthentik,dc=io"], }, ) # Group without SID @@ -47,7 +47,7 @@ def mock_ad_connection(password: str) -> Connection: }, ) connection.strategy.add_entry( - "cn=user0,ou=users,dc=goauthentik,dc=io", + "cn=user0,ou=foo,ou=users,dc=goauthentik,dc=io", { "userPassword": password, "sAMAccountName": "user0_sn", diff --git a/authentik/sources/ldap/tests/test_api.py b/authentik/sources/ldap/tests/test_api.py index 9618fa6aed..e7dcf42320 100644 --- a/authentik/sources/ldap/tests/test_api.py +++ b/authentik/sources/ldap/tests/test_api.py @@ -1,4 +1,5 @@ """LDAP Source API tests""" + from rest_framework.test import APITestCase from authentik.lib.generators import generate_key diff --git a/authentik/sources/ldap/tests/test_auth.py b/authentik/sources/ldap/tests/test_auth.py index d764715b1a..0e634e3a37 100644 --- a/authentik/sources/ldap/tests/test_auth.py +++ b/authentik/sources/ldap/tests/test_auth.py @@ -1,4 +1,5 @@ """LDAP Source tests""" + from unittest.mock import MagicMock, Mock, patch from django.db.models import Q @@ -54,7 +55,7 @@ class LDAPSyncTests(TestCase): ) connection.assert_called_with( connection_kwargs={ - "user": "cn=user0,ou=users,dc=goauthentik,dc=io", + "user": "cn=user0,ou=foo,ou=users,dc=goauthentik,dc=io", "password": LDAP_PASSWORD, } ) diff --git a/authentik/sources/ldap/tests/test_password.py b/authentik/sources/ldap/tests/test_password.py index aa01016794..18fadaceb9 100644 --- a/authentik/sources/ldap/tests/test_password.py +++ b/authentik/sources/ldap/tests/test_password.py @@ -1,4 +1,5 @@ """LDAP Source tests""" + from unittest.mock import MagicMock, patch from django.test import TestCase diff --git a/authentik/sources/ldap/tests/test_sync.py b/authentik/sources/ldap/tests/test_sync.py index 5012007bd0..1c171f2323 100644 --- a/authentik/sources/ldap/tests/test_sync.py +++ b/authentik/sources/ldap/tests/test_sync.py @@ -1,4 +1,5 @@ """LDAP Source tests""" + from unittest.mock import MagicMock, patch from django.db.models import Q @@ -10,6 +11,7 @@ from authentik.core.tests.utils import create_test_admin_user from authentik.events.models import Event, EventAction, SystemTask from authentik.events.system_tasks import TaskStatus from authentik.lib.generators import generate_id, generate_key +from authentik.lib.sync.outgoing.exceptions import StopSync from authentik.lib.utils.reflection import class_to_path from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer @@ -62,12 +64,13 @@ class LDAPSyncTests(TestCase): connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD)) with patch("authentik.sources.ldap.models.LDAPSource.connection", connection): user_sync = UserLDAPSynchronizer(self.source) - user_sync.sync_full() + with self.assertRaises(StopSync): + user_sync.sync_full() self.assertFalse(User.objects.filter(username="user0_sn").exists()) self.assertFalse(User.objects.filter(username="user1_sn").exists()) events = Event.objects.filter( action=EventAction.CONFIGURATION_ERROR, - context__message="Failed to evaluate property-mapping: 'name'", + context__mapping__pk=mapping.pk.hex, ) self.assertTrue(events.exists()) diff --git a/authentik/sources/ldap/urls.py b/authentik/sources/ldap/urls.py index 30390f3326..361e9dccde 100644 --- a/authentik/sources/ldap/urls.py +++ b/authentik/sources/ldap/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet api_urlpatterns = [ diff --git a/authentik/sources/oauth/api/source.py b/authentik/sources/oauth/api/source.py index 398ce96719..28de050faf 100644 --- a/authentik/sources/oauth/api/source.py +++ b/authentik/sources/oauth/api/source.py @@ -1,4 +1,5 @@ """OAuth Source Serializer""" + from django.urls.base import reverse_lazy from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet @@ -56,7 +57,6 @@ class OAuthSourceSerializer(SourceSerializer): """Get source's type configuration""" return SourceTypeSerializer(instance.source_type).data - # pylint: disable=too-many-locals def validate(self, attrs: dict) -> dict: session = get_http_session() source_type = registry.find_type(attrs["provider_type"]) @@ -70,7 +70,7 @@ class OAuthSourceSerializer(SourceSerializer): well_known_config.raise_for_status() except RequestException as exc: text = exc.response.text if exc.response else str(exc) - raise ValidationError({"oidc_well_known_url": text}) + raise ValidationError({"oidc_well_known_url": text}) from None config = well_known_config.json() if "issuer" not in config: raise ValidationError({"oidc_well_known_url": "Invalid well-known configuration"}) @@ -96,7 +96,7 @@ class OAuthSourceSerializer(SourceSerializer): jwks_config.raise_for_status() except RequestException as exc: text = exc.response.text if exc.response else str(exc) - raise ValidationError({"oidc_jwks_url": text}) + raise ValidationError({"oidc_jwks_url": text}) from None config = jwks_config.json() attrs["oidc_jwks"] = config @@ -130,7 +130,13 @@ class OAuthSourceSerializer(SourceSerializer): "oidc_jwks_url", "oidc_jwks", ] - extra_kwargs = {"consumer_secret": {"write_only": True}} + extra_kwargs = { + "consumer_secret": {"write_only": True}, + "request_token_url": {"allow_blank": True}, + "authorization_url": {"allow_blank": True}, + "access_token_url": {"allow_blank": True}, + "profile_url": {"allow_blank": True}, + } class OAuthSourceFilter(FilterSet): diff --git a/authentik/sources/oauth/api/source_connection.py b/authentik/sources/oauth/api/source_connection.py index 311ce5bad9..2ae1dc421a 100644 --- a/authentik/sources/oauth/api/source_connection.py +++ b/authentik/sources/oauth/api/source_connection.py @@ -1,4 +1,5 @@ """OAuth Source Serializer""" + from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import ModelViewSet diff --git a/authentik/sources/oauth/apps.py b/authentik/sources/oauth/apps.py index e497c56476..1c189579f3 100644 --- a/authentik/sources/oauth/apps.py +++ b/authentik/sources/oauth/apps.py @@ -1,4 +1,5 @@ """authentik oauth_client config""" + from structlog.stdlib import get_logger from authentik.blueprints.apps import ManagedAppConfig @@ -11,6 +12,7 @@ AUTHENTIK_SOURCES_OAUTH_TYPES = [ "authentik.sources.oauth.types.discord", "authentik.sources.oauth.types.facebook", "authentik.sources.oauth.types.github", + "authentik.sources.oauth.types.gitlab", "authentik.sources.oauth.types.google", "authentik.sources.oauth.types.mailcow", "authentik.sources.oauth.types.oidc", @@ -31,10 +33,10 @@ class AuthentikSourceOAuthConfig(ManagedAppConfig): mountpoint = "source/oauth/" default = True - def reconcile_global_sources_loaded(self): - """Load source_types from config file""" + def import_related(self): for source_type in AUTHENTIK_SOURCES_OAUTH_TYPES: try: self.import_module(source_type) except ImportError as exc: LOGGER.warning("Failed to load OAuth Source", exc=exc) + return super().import_related() diff --git a/authentik/sources/oauth/clients/base.py b/authentik/sources/oauth/clients/base.py index 2c3f972485..a580786e32 100644 --- a/authentik/sources/oauth/clients/base.py +++ b/authentik/sources/oauth/clients/base.py @@ -1,5 +1,6 @@ """OAuth Clients""" -from typing import Any, Optional + +from typing import Any from urllib.parse import parse_qs, quote, urlencode, urlparse, urlunparse from django.http import HttpRequest @@ -21,20 +22,20 @@ class BaseOAuthClient: source: OAuthSource request: HttpRequest - callback: Optional[str] + callback: str | None - def __init__(self, source: OAuthSource, request: HttpRequest, callback: Optional[str] = None): + def __init__(self, source: OAuthSource, request: HttpRequest, callback: str | None = None): self.source = source self.session = get_http_session() self.request = request self.callback = callback self.logger = get_logger().bind(source=source.slug) - def get_access_token(self, **request_kwargs) -> Optional[dict[str, Any]]: + def get_access_token(self, **request_kwargs) -> dict[str, Any] | None: """Fetch access token from callback request.""" raise NotImplementedError("Defined in a sub-class") # pragma: no cover - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: """Fetch user profile information.""" profile_url = self.source.source_type.profile_url or "" if self.source.source_type.urls_customizable and self.source.profile_url: diff --git a/authentik/sources/oauth/clients/oauth1.py b/authentik/sources/oauth/clients/oauth1.py index 1299a585c0..2617556dd8 100644 --- a/authentik/sources/oauth/clients/oauth1.py +++ b/authentik/sources/oauth/clients/oauth1.py @@ -1,5 +1,6 @@ """OAuth 1 Clients""" -from typing import Any, Optional + +from typing import Any from urllib.parse import parse_qsl from requests.exceptions import RequestException @@ -20,7 +21,7 @@ class OAuthClient(BaseOAuthClient): "Accept": "application/json", } - def get_access_token(self, **request_kwargs) -> Optional[dict[str, Any]]: + def get_access_token(self, **request_kwargs) -> dict[str, Any] | None: """Fetch access token from callback request.""" raw_token = self.request.session.get(self.session_key, None) verifier = self.request.GET.get("oauth_verifier", None) diff --git a/authentik/sources/oauth/clients/oauth2.py b/authentik/sources/oauth/clients/oauth2.py index b29f366636..cad0bff413 100644 --- a/authentik/sources/oauth/clients/oauth2.py +++ b/authentik/sources/oauth/clients/oauth2.py @@ -1,6 +1,7 @@ """OAuth 2 Clients""" + from json import loads -from typing import Any, Optional +from typing import Any from urllib.parse import parse_qsl from django.utils.crypto import constant_time_compare, get_random_string @@ -22,7 +23,7 @@ class OAuth2Client(BaseOAuthClient): "Accept": "application/json", } - def get_request_arg(self, key: str, default: Optional[Any] = None) -> Any: + def get_request_arg(self, key: str, default: Any | None = None) -> Any: """Depending on request type, get data from post or get""" if self.request.method == "POST": return self.request.POST.get(key, default) @@ -54,7 +55,7 @@ class OAuth2Client(BaseOAuthClient): """Get client secret""" return self.source.consumer_secret - def get_access_token(self, **request_kwargs) -> Optional[dict[str, Any]]: + def get_access_token(self, **request_kwargs) -> dict[str, Any] | None: """Fetch access token from callback request.""" callback = self.request.build_absolute_uri(self.callback or self.request.path) if not self.check_application_state(): @@ -79,7 +80,7 @@ class OAuth2Client(BaseOAuthClient): access_token_url = self.source.source_type.access_token_url or "" if self.source.source_type.urls_customizable and self.source.access_token_url: access_token_url = self.source.access_token_url - response = self.session.request( + response = self.do_request( "post", access_token_url, data=args, headers=self._default_headers, **request_kwargs ) response.raise_for_status() @@ -138,7 +139,7 @@ class OAuth2Client(BaseOAuthClient): class UserprofileHeaderAuthClient(OAuth2Client): """OAuth client which only sends authentication via header, not querystring""" - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: "Fetch user profile information." profile_url = self.source.source_type.profile_url or "" if self.source.source_type.urls_customizable and self.source.profile_url: diff --git a/authentik/sources/oauth/exceptions.py b/authentik/sources/oauth/exceptions.py index 0929e74c45..0798638dfa 100644 --- a/authentik/sources/oauth/exceptions.py +++ b/authentik/sources/oauth/exceptions.py @@ -1,4 +1,5 @@ """OAuth Source Exception""" + from authentik.lib.sentry import SentryIgnoredException diff --git a/authentik/sources/oauth/models.py b/authentik/sources/oauth/models.py index 7acbb92230..d05665bcb4 100644 --- a/authentik/sources/oauth/models.py +++ b/authentik/sources/oauth/models.py @@ -1,5 +1,6 @@ """OAuth Client models""" -from typing import TYPE_CHECKING, Optional + +from typing import TYPE_CHECKING from django.db import models from django.http.request import HttpRequest @@ -7,6 +8,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from rest_framework.serializers import Serializer +from authentik.core.api.object_types import CreatableType, NonCreatableType from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UILoginButton, UserSettingSerializer @@ -14,7 +16,7 @@ if TYPE_CHECKING: from authentik.sources.oauth.types.registry import SourceType -class OAuthSource(Source): +class OAuthSource(NonCreatableType, Source): """Login using a Generic OAuth provider.""" provider_type = models.CharField(max_length=255) @@ -71,23 +73,35 @@ class OAuthSource(Source): return OAuthSourceSerializer + @property + def icon_url(self) -> str | None: + # When listing source types, this property might be retrieved from an abstract + # model. In that case we can't check self.provider_type or self.icon_url + # and as such we attempt to find the correct provider type based on the mode name + if self.Meta.abstract: + from authentik.sources.oauth.types.registry import registry + + provider_type = registry.find_type( + self._meta.model_name.replace(OAuthSource._meta.model_name, "") + ) + return provider_type().icon_url() + icon = super().icon_url + if not icon: + provider_type = self.source_type + provider = provider_type() + icon = provider.icon_url() + return icon + def ui_login_button(self, request: HttpRequest) -> UILoginButton: provider_type = self.source_type provider = provider_type() - icon = self.icon_url - if not icon: - icon = provider.icon_url() return UILoginButton( name=self.name, challenge=provider.login_challenge(self, request), - icon_url=icon, + icon_url=self.icon_url, ) - def ui_user_settings(self) -> Optional[UserSettingSerializer]: - provider_type = self.source_type - icon = self.icon_url - if not icon: - icon = provider_type().icon_url() + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.name, @@ -96,7 +110,7 @@ class OAuthSource(Source): "authentik_sources_oauth:oauth-client-login", kwargs={"source_slug": self.slug}, ), - "icon_url": icon, + "icon_url": self.icon_url, } ) @@ -108,7 +122,7 @@ class OAuthSource(Source): verbose_name_plural = _("OAuth Sources") -class GitHubOAuthSource(OAuthSource): +class GitHubOAuthSource(CreatableType, OAuthSource): """Social Login using GitHub.com or a GitHub-Enterprise Instance.""" class Meta: @@ -117,7 +131,16 @@ class GitHubOAuthSource(OAuthSource): verbose_name_plural = _("GitHub OAuth Sources") -class TwitchOAuthSource(OAuthSource): +class GitLabOAuthSource(CreatableType, OAuthSource): + """Social Login using GitLab.com or a GitLab Instance.""" + + class Meta: + abstract = True + verbose_name = _("GitLab OAuth Source") + verbose_name_plural = _("GitLab OAuth Sources") + + +class TwitchOAuthSource(CreatableType, OAuthSource): """Social Login using Twitch.""" class Meta: @@ -126,7 +149,7 @@ class TwitchOAuthSource(OAuthSource): verbose_name_plural = _("Twitch OAuth Sources") -class MailcowOAuthSource(OAuthSource): +class MailcowOAuthSource(CreatableType, OAuthSource): """Social Login using Mailcow.""" class Meta: @@ -135,7 +158,7 @@ class MailcowOAuthSource(OAuthSource): verbose_name_plural = _("Mailcow OAuth Sources") -class TwitterOAuthSource(OAuthSource): +class TwitterOAuthSource(CreatableType, OAuthSource): """Social Login using Twitter.com""" class Meta: @@ -144,7 +167,7 @@ class TwitterOAuthSource(OAuthSource): verbose_name_plural = _("Twitter OAuth Sources") -class FacebookOAuthSource(OAuthSource): +class FacebookOAuthSource(CreatableType, OAuthSource): """Social Login using Facebook.com.""" class Meta: @@ -153,7 +176,7 @@ class FacebookOAuthSource(OAuthSource): verbose_name_plural = _("Facebook OAuth Sources") -class DiscordOAuthSource(OAuthSource): +class DiscordOAuthSource(CreatableType, OAuthSource): """Social Login using Discord.""" class Meta: @@ -162,7 +185,7 @@ class DiscordOAuthSource(OAuthSource): verbose_name_plural = _("Discord OAuth Sources") -class PatreonOAuthSource(OAuthSource): +class PatreonOAuthSource(CreatableType, OAuthSource): """Social Login using Patreon.""" class Meta: @@ -171,7 +194,7 @@ class PatreonOAuthSource(OAuthSource): verbose_name_plural = _("Patreon OAuth Sources") -class GoogleOAuthSource(OAuthSource): +class GoogleOAuthSource(CreatableType, OAuthSource): """Social Login using Google or Google Workspace (GSuite).""" class Meta: @@ -180,7 +203,7 @@ class GoogleOAuthSource(OAuthSource): verbose_name_plural = _("Google OAuth Sources") -class AzureADOAuthSource(OAuthSource): +class AzureADOAuthSource(CreatableType, OAuthSource): """Social Login using Azure AD.""" class Meta: @@ -189,7 +212,7 @@ class AzureADOAuthSource(OAuthSource): verbose_name_plural = _("Azure AD OAuth Sources") -class OpenIDConnectOAuthSource(OAuthSource): +class OpenIDConnectOAuthSource(CreatableType, OAuthSource): """Login using a Generic OpenID-Connect compliant provider.""" class Meta: @@ -198,7 +221,7 @@ class OpenIDConnectOAuthSource(OAuthSource): verbose_name_plural = _("OpenID OAuth Sources") -class AppleOAuthSource(OAuthSource): +class AppleOAuthSource(CreatableType, OAuthSource): """Social Login using Apple.""" class Meta: @@ -207,7 +230,7 @@ class AppleOAuthSource(OAuthSource): verbose_name_plural = _("Apple OAuth Sources") -class OktaOAuthSource(OAuthSource): +class OktaOAuthSource(CreatableType, OAuthSource): """Social Login using Okta.""" class Meta: @@ -216,7 +239,7 @@ class OktaOAuthSource(OAuthSource): verbose_name_plural = _("Okta OAuth Sources") -class RedditOAuthSource(OAuthSource): +class RedditOAuthSource(CreatableType, OAuthSource): """Social Login using reddit.com.""" class Meta: diff --git a/authentik/sources/oauth/settings.py b/authentik/sources/oauth/settings.py index c839c338db..6580a906f5 100644 --- a/authentik/sources/oauth/settings.py +++ b/authentik/sources/oauth/settings.py @@ -1,4 +1,5 @@ """OAuth source settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/sources/oauth/tasks.py b/authentik/sources/oauth/tasks.py index cfac09f093..871bc2f2b1 100644 --- a/authentik/sources/oauth/tasks.py +++ b/authentik/sources/oauth/tasks.py @@ -1,4 +1,5 @@ """OAuth Source tasks""" + from json import dumps from requests import RequestException diff --git a/authentik/sources/oauth/tests/test_tasks.py b/authentik/sources/oauth/tests/test_tasks.py index 54f1290b6f..9ab3aab4bf 100644 --- a/authentik/sources/oauth/tests/test_tasks.py +++ b/authentik/sources/oauth/tests/test_tasks.py @@ -1,4 +1,5 @@ """Test OAuth Source tasks""" + from django.test import TestCase from requests_mock import Mocker @@ -34,7 +35,7 @@ class TestOAuthSourceTasks(TestCase): }, ) mock.get("http://foo/jwks", json={"foo": "bar"}) - update_well_known_jwks() # pylint: disable=no-value-for-parameter + update_well_known_jwks() self.source.refresh_from_db() self.assertEqual(self.source.authorization_url, "foo") self.assertEqual(self.source.access_token_url, "foo") diff --git a/authentik/sources/oauth/tests/test_type_apple.py b/authentik/sources/oauth/tests/test_type_apple.py new file mode 100644 index 0000000000..bfe88d07f0 --- /dev/null +++ b/authentik/sources/oauth/tests/test_type_apple.py @@ -0,0 +1,37 @@ +"""Apple Type tests""" + +from django.test import RequestFactory, TestCase +from guardian.shortcuts import get_anonymous_user + +from authentik.lib.generators import generate_id +from authentik.lib.tests.utils import dummy_get_response +from authentik.root.middleware import SessionMiddleware +from authentik.sources.oauth.models import OAuthSource +from authentik.sources.oauth.types.registry import registry + + +class TestTypeApple(TestCase): + """OAuth Source tests""" + + def setUp(self): + self.source = OAuthSource.objects.create( + name="test", + slug="test", + provider_type="apple", + authorization_url="", + profile_url="", + consumer_key=generate_id(), + ) + self.factory = RequestFactory() + + def test_login_challenge(self): + """Test login_challenge""" + request = self.factory.get("/") + request.user = get_anonymous_user() + + middleware = SessionMiddleware(dummy_get_response) + middleware.process_request(request) + request.session.save() + oauth_type = registry.find_type("apple") + challenge = oauth_type().login_challenge(self.source, request) + self.assertTrue(challenge.is_valid(raise_exception=True)) diff --git a/authentik/sources/oauth/tests/test_type_azure_ad.py b/authentik/sources/oauth/tests/test_type_azure_ad.py index 2f1e1731e0..e34892fad3 100644 --- a/authentik/sources/oauth/tests/test_type_azure_ad.py +++ b/authentik/sources/oauth/tests/test_type_azure_ad.py @@ -1,4 +1,5 @@ """azure ad Type tests""" + from django.test import TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_type_discord.py b/authentik/sources/oauth/tests/test_type_discord.py index c3aa56efc1..e1c996a2d1 100644 --- a/authentik/sources/oauth/tests/test_type_discord.py +++ b/authentik/sources/oauth/tests/test_type_discord.py @@ -1,4 +1,5 @@ """Discord Type tests""" + from django.test import TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_type_github.py b/authentik/sources/oauth/tests/test_type_github.py index ad62a6f50e..a24cdaaa75 100644 --- a/authentik/sources/oauth/tests/test_type_github.py +++ b/authentik/sources/oauth/tests/test_type_github.py @@ -1,4 +1,5 @@ """GitHub Type tests""" + from copy import copy from django.test import RequestFactory, TestCase diff --git a/authentik/sources/oauth/tests/test_type_gitlab.py b/authentik/sources/oauth/tests/test_type_gitlab.py new file mode 100644 index 0000000000..99bfa25bae --- /dev/null +++ b/authentik/sources/oauth/tests/test_type_gitlab.py @@ -0,0 +1,30 @@ +"""GitLab Type tests""" + +from django.test import TestCase + +from authentik.sources.oauth.models import OAuthSource +from authentik.sources.oauth.types.gitlab import GitLabOAuthCallback + +GITLAB_USER = { + "preferred_username": "dev_gitlab", + "email": "dev@gitlab.com", + "name": "Dev", +} + + +class TestTypeGitLab(TestCase): + """OAuth Source tests for GitLab""" + + def setUp(self): + self.source = OAuthSource.objects.create( + name="gitlab_test", + slug="gitlab_test", + provider_type="gitlab", + ) + + def test_enroll_context(self): + """Test GitLab Enrollment context""" + ak_context = GitLabOAuthCallback().get_user_enroll_context(GITLAB_USER) + self.assertEqual(ak_context["username"], GITLAB_USER["preferred_username"]) + self.assertEqual(ak_context["email"], GITLAB_USER["email"]) + self.assertEqual(ak_context["name"], GITLAB_USER["name"]) diff --git a/authentik/sources/oauth/tests/test_type_google.py b/authentik/sources/oauth/tests/test_type_google.py index 5b1780e9bd..0b6d3888e2 100644 --- a/authentik/sources/oauth/tests/test_type_google.py +++ b/authentik/sources/oauth/tests/test_type_google.py @@ -1,4 +1,5 @@ """google Type tests""" + from django.contrib.sessions.middleware import SessionMiddleware from django.test import TestCase from django.test.client import RequestFactory diff --git a/authentik/sources/oauth/tests/test_type_mailcow.py b/authentik/sources/oauth/tests/test_type_mailcow.py index 2687bf3cfe..8a7a4b30db 100644 --- a/authentik/sources/oauth/tests/test_type_mailcow.py +++ b/authentik/sources/oauth/tests/test_type_mailcow.py @@ -1,4 +1,5 @@ """Mailcow Type tests""" + from django.test import TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_type_openid.py b/authentik/sources/oauth/tests/test_type_openid.py index e04bea4b0c..f8c7805489 100644 --- a/authentik/sources/oauth/tests/test_type_openid.py +++ b/authentik/sources/oauth/tests/test_type_openid.py @@ -1,4 +1,5 @@ """OpenID Type tests""" + from django.test import RequestFactory, TestCase from requests_mock import Mocker diff --git a/authentik/sources/oauth/tests/test_type_patreon.py b/authentik/sources/oauth/tests/test_type_patreon.py index 670b7d6657..680df0724c 100644 --- a/authentik/sources/oauth/tests/test_type_patreon.py +++ b/authentik/sources/oauth/tests/test_type_patreon.py @@ -1,4 +1,5 @@ """Patreon Type tests""" + from django.test import RequestFactory, TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_type_twitch.py b/authentik/sources/oauth/tests/test_type_twitch.py index f18e4eaf22..e9fbe4acd7 100644 --- a/authentik/sources/oauth/tests/test_type_twitch.py +++ b/authentik/sources/oauth/tests/test_type_twitch.py @@ -1,4 +1,5 @@ """Twitch Type tests""" + from django.test import TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_type_twitter.py b/authentik/sources/oauth/tests/test_type_twitter.py index 80abefd6dc..8ff9f2ffd5 100644 --- a/authentik/sources/oauth/tests/test_type_twitter.py +++ b/authentik/sources/oauth/tests/test_type_twitter.py @@ -1,4 +1,5 @@ """Twitter Type tests""" + from django.test import TestCase from authentik.sources.oauth.models import OAuthSource diff --git a/authentik/sources/oauth/tests/test_views.py b/authentik/sources/oauth/tests/test_views.py index 2a849d0a9c..3a3152f5e0 100644 --- a/authentik/sources/oauth/tests/test_views.py +++ b/authentik/sources/oauth/tests/test_views.py @@ -1,4 +1,5 @@ """OAuth Source tests""" + from django.urls import reverse from requests_mock import Mocker from rest_framework.test import APITestCase diff --git a/authentik/sources/oauth/types/apple.py b/authentik/sources/oauth/types/apple.py index 5ead5bdbda..08f3968a94 100644 --- a/authentik/sources/oauth/types/apple.py +++ b/authentik/sources/oauth/types/apple.py @@ -1,6 +1,7 @@ """Apple OAuth Views""" + from time import time -from typing import Any, Optional +from typing import Any from django.http.request import HttpRequest from django.urls.base import reverse @@ -16,6 +17,7 @@ from authentik.sources.oauth.views.callback import OAuthCallback from authentik.sources.oauth.views.redirect import OAuthRedirect LOGGER = get_logger() +APPLE_CLIENT_ID_PARTS = 3 class AppleLoginChallenge(Challenge): @@ -29,7 +31,7 @@ class AppleLoginChallenge(Challenge): class AppleChallengeResponse(ChallengeResponse): - """Pseudo class for plex response""" + """Pseudo class for apple response""" component = CharField(default="ak-source-oauth-apple") @@ -39,14 +41,14 @@ class AppleOAuthClient(OAuth2Client): def get_client_id(self) -> str: parts: list[str] = self.source.consumer_key.split(";") - if len(parts) < 3: + if len(parts) < APPLE_CLIENT_ID_PARTS: return self.source.consumer_key return parts[0].strip() def get_client_secret(self) -> str: now = time() parts: list[str] = self.source.consumer_key.split(";") - if len(parts) < 3: + if len(parts) < APPLE_CLIENT_ID_PARTS: raise ValueError( "Apple Source client_id should be formatted like " "services_id_identifier;apple_team_id;key_id" @@ -63,7 +65,7 @@ class AppleOAuthClient(OAuth2Client): LOGGER.debug("signing payload as secret key", payload=payload, jwt=jwt) return jwt - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: id_token = token.get("id_token") return decode(id_token, options={"verify_signature": False}) @@ -85,7 +87,7 @@ class AppleOAuth2Callback(OAuthCallback): client_class = AppleOAuthClient - def get_user_id(self, info: dict[str, Any]) -> Optional[str]: + def get_user_id(self, info: dict[str, Any]) -> str | None: return info["sub"] def get_user_enroll_context( @@ -123,7 +125,7 @@ class AppleType(SourceType): ) args = apple_client.get_redirect_args() return AppleLoginChallenge( - instance={ + data={ "client_id": apple_client.get_client_id(), "scope": "name email", "redirect_uri": args["redirect_uri"], diff --git a/authentik/sources/oauth/types/azure_ad.py b/authentik/sources/oauth/types/azure_ad.py index 80c92141b0..341831138f 100644 --- a/authentik/sources/oauth/types/azure_ad.py +++ b/authentik/sources/oauth/types/azure_ad.py @@ -1,4 +1,5 @@ """AzureAD OAuth2 Views""" + from typing import Any from structlog.stdlib import get_logger diff --git a/authentik/sources/oauth/types/discord.py b/authentik/sources/oauth/types/discord.py index 4fb34c6726..a67c07bf13 100644 --- a/authentik/sources/oauth/types/discord.py +++ b/authentik/sources/oauth/types/discord.py @@ -1,4 +1,5 @@ """Discord OAuth Views""" + from typing import Any from authentik.sources.oauth.types.registry import SourceType, registry diff --git a/authentik/sources/oauth/types/facebook.py b/authentik/sources/oauth/types/facebook.py index 69893298b7..1d1ac9d42a 100644 --- a/authentik/sources/oauth/types/facebook.py +++ b/authentik/sources/oauth/types/facebook.py @@ -1,5 +1,6 @@ """Facebook OAuth Views""" -from typing import Any, Optional + +from typing import Any from facebook import GraphAPI @@ -21,7 +22,7 @@ class FacebookOAuthRedirect(OAuthRedirect): class FacebookOAuth2Client(OAuth2Client): """Facebook OAuth2 Client""" - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: api = GraphAPI(access_token=token["access_token"]) return api.get_object("me", fields="id,name,email") diff --git a/authentik/sources/oauth/types/github.py b/authentik/sources/oauth/types/github.py index b9e5ed17cb..ce88ae78d0 100644 --- a/authentik/sources/oauth/types/github.py +++ b/authentik/sources/oauth/types/github.py @@ -1,4 +1,5 @@ """GitHub OAuth Views""" + from typing import Any from requests.exceptions import RequestException diff --git a/authentik/sources/oauth/types/gitlab.py b/authentik/sources/oauth/types/gitlab.py new file mode 100644 index 0000000000..3d90ea7e5d --- /dev/null +++ b/authentik/sources/oauth/types/gitlab.py @@ -0,0 +1,54 @@ +""" +GitLab OAuth Views + +See https://docs.gitlab.com/ee/integration/oauth_provider.html +and https://docs.gitlab.com/ee/integration/openid_connect_provider.html +""" + +from typing import Any + +from authentik.sources.oauth.models import OAuthSource +from authentik.sources.oauth.types.registry import SourceType, registry +from authentik.sources.oauth.views.callback import OAuthCallback +from authentik.sources.oauth.views.redirect import OAuthRedirect + + +class GitLabOAuthRedirect(OAuthRedirect): + """GitLab OAuth2 Redirect""" + + def get_additional_parameters(self, source: OAuthSource): + return { + "scope": ["read_user", "openid", "profile", "email"], + } + + +class GitLabOAuthCallback(OAuthCallback): + """GitLab OAuth2 Callback""" + + def get_user_enroll_context( + self, + info: dict[str, Any], + ) -> dict[str, Any]: + return { + "username": info.get("preferred_username"), + "email": info.get("email"), + "name": info.get("name"), + } + + +@registry.register() +class GitLabType(SourceType): + """GitLab Type definition""" + + callback_view = GitLabOAuthCallback + redirect_view = GitLabOAuthRedirect + verbose_name = "GitLab" + name = "gitlab" + + urls_customizable = True + + authorization_url = "https://gitlab.com/oauth/authorize" + access_token_url = "https://gitlab.com/oauth/token" # nosec + profile_url = "https://gitlab.com/oauth/userinfo" + oidc_well_known_url = "https://gitlab.com/.well-known/openid-configuration" + oidc_jwks_url = "https://gitlab.com/oauth/discovery/keys" diff --git a/authentik/sources/oauth/types/google.py b/authentik/sources/oauth/types/google.py index 94b6f78428..add0eab845 100644 --- a/authentik/sources/oauth/types/google.py +++ b/authentik/sources/oauth/types/google.py @@ -1,4 +1,5 @@ """Google OAuth Views""" + from typing import Any from authentik.sources.oauth.types.registry import SourceType, registry diff --git a/authentik/sources/oauth/types/mailcow.py b/authentik/sources/oauth/types/mailcow.py index 8bff86af55..37895e114a 100644 --- a/authentik/sources/oauth/types/mailcow.py +++ b/authentik/sources/oauth/types/mailcow.py @@ -1,5 +1,6 @@ """Mailcow OAuth Views""" -from typing import Any, Optional + +from typing import Any from requests.exceptions import RequestException from structlog.stdlib import get_logger @@ -24,7 +25,7 @@ class MailcowOAuthRedirect(OAuthRedirect): class MailcowOAuth2Client(OAuth2Client): """MailcowOAuth2Client, for some reason, mailcow does not like the default headers""" - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: "Fetch user profile information." profile_url = self.source.source_type.profile_url or "" if self.source.source_type.urls_customizable and self.source.profile_url: diff --git a/authentik/sources/oauth/types/oidc.py b/authentik/sources/oauth/types/oidc.py index 4e32f3fee5..017e04b5e2 100644 --- a/authentik/sources/oauth/types/oidc.py +++ b/authentik/sources/oauth/types/oidc.py @@ -1,4 +1,5 @@ """OpenID Connect OAuth Views""" + from typing import Any from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient diff --git a/authentik/sources/oauth/types/okta.py b/authentik/sources/oauth/types/okta.py index 1f1f07dc7e..1698cf2d1f 100644 --- a/authentik/sources/oauth/types/okta.py +++ b/authentik/sources/oauth/types/okta.py @@ -1,4 +1,5 @@ """Okta OAuth Views""" + from typing import Any from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient diff --git a/authentik/sources/oauth/types/patreon.py b/authentik/sources/oauth/types/patreon.py index 8d11bf27ad..07bf307f09 100644 --- a/authentik/sources/oauth/types/patreon.py +++ b/authentik/sources/oauth/types/patreon.py @@ -1,4 +1,5 @@ """Patreon OAuth Views""" + from typing import Any from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient diff --git a/authentik/sources/oauth/types/reddit.py b/authentik/sources/oauth/types/reddit.py index 7d558cbb3c..1b901bb37a 100644 --- a/authentik/sources/oauth/types/reddit.py +++ b/authentik/sources/oauth/types/reddit.py @@ -1,4 +1,5 @@ """Reddit OAuth Views""" + from typing import Any from requests.auth import HTTPBasicAuth diff --git a/authentik/sources/oauth/types/registry.py b/authentik/sources/oauth/types/registry.py index 99cb87dd5d..acb59c69bd 100644 --- a/authentik/sources/oauth/types/registry.py +++ b/authentik/sources/oauth/types/registry.py @@ -1,6 +1,7 @@ """Source type manager""" + +from collections.abc import Callable from enum import Enum -from typing import Callable, Optional, Type from django.http.request import HttpRequest from django.templatetags.static import static @@ -32,12 +33,12 @@ class SourceType: urls_customizable = False - request_token_url: Optional[str] = None - authorization_url: Optional[str] = None - access_token_url: Optional[str] = None - profile_url: Optional[str] = None - oidc_well_known_url: Optional[str] = None - oidc_jwks_url: Optional[str] = None + request_token_url: str | None = None + authorization_url: str | None = None + access_token_url: str | None = None + profile_url: str | None = None + oidc_well_known_url: str | None = None + oidc_jwks_url: str | None = None def icon_url(self) -> str: """Get Icon URL for login""" @@ -46,7 +47,7 @@ class SourceType: def login_challenge(self, source: OAuthSource, request: HttpRequest) -> Challenge: """Allow types to return custom challenges""" return RedirectChallenge( - instance={ + data={ "type": ChallengeTypes.REDIRECT.value, "to": reverse( "authentik_sources_oauth:oauth-client-login", @@ -79,7 +80,7 @@ class SourceTypeRegistry: """Get list of tuples of all registered names""" return [(x.name, x.verbose_name) for x in self.__sources] - def find_type(self, type_name: str) -> Type[SourceType]: + def find_type(self, type_name: str) -> type[SourceType]: """Find type based on source""" found_type = None for src_type in self.__sources: diff --git a/authentik/sources/oauth/types/twitch.py b/authentik/sources/oauth/types/twitch.py index 52b8bae0bc..777d457867 100644 --- a/authentik/sources/oauth/types/twitch.py +++ b/authentik/sources/oauth/types/twitch.py @@ -1,6 +1,7 @@ """Twitch OAuth Views""" + from json import dumps -from typing import Any, Optional +from typing import Any from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback @@ -11,7 +12,7 @@ from authentik.sources.oauth.views.redirect import OAuthRedirect class TwitchClient(UserprofileHeaderAuthClient): """Twitch needs the token_type to be capitalized for the request header.""" - def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]: + def get_profile_info(self, token: dict[str, str]) -> dict[str, Any] | None: token["token_type"] = token["token_type"].capitalize() return super().get_profile_info(token) diff --git a/authentik/sources/oauth/types/twitter.py b/authentik/sources/oauth/types/twitter.py index 7b75f04ea8..8b1aa66124 100644 --- a/authentik/sources/oauth/types/twitter.py +++ b/authentik/sources/oauth/types/twitter.py @@ -1,5 +1,6 @@ """Twitter OAuth Views""" -from typing import Any, Optional + +from typing import Any from authentik.lib.generators import generate_id from authentik.sources.oauth.clients.oauth2 import ( @@ -19,7 +20,7 @@ class TwitterClient(UserprofileHeaderAuthClient): # is set via query parameter, so we reuse the azure client # see https://github.com/goauthentik/authentik/issues/1910 - def get_access_token(self, **request_kwargs) -> Optional[dict[str, Any]]: + def get_access_token(self, **request_kwargs) -> dict[str, Any] | None: return super().get_access_token( auth=( self.source.consumer_key, diff --git a/authentik/sources/oauth/views/base.py b/authentik/sources/oauth/views/base.py index 399f3f4931..e308778b6d 100644 --- a/authentik/sources/oauth/views/base.py +++ b/authentik/sources/oauth/views/base.py @@ -1,5 +1,4 @@ """OAuth Base views""" -from typing import Optional from django.http.request import HttpRequest from structlog.stdlib import get_logger @@ -12,18 +11,17 @@ from authentik.sources.oauth.models import OAuthSource LOGGER = get_logger() -# pylint: disable=too-few-public-methods class OAuthClientMixin: "Mixin for getting OAuth client for a source." request: HttpRequest # Set by View class - client_class: Optional[type[BaseOAuthClient]] = None + client_class: type[BaseOAuthClient] | None = None def get_client(self, source: OAuthSource, **kwargs) -> BaseOAuthClient: "Get instance of the OAuth client for this source." if self.client_class is not None: - # pylint: disable=not-callable + return self.client_class(source, self.request, **kwargs) if source.source_type.request_token_url or source.request_token_url: client = OAuthClient(source, self.request, **kwargs) diff --git a/authentik/sources/oauth/views/callback.py b/authentik/sources/oauth/views/callback.py index 893a5003c5..79dae2e2ca 100644 --- a/authentik/sources/oauth/views/callback.py +++ b/authentik/sources/oauth/views/callback.py @@ -1,6 +1,7 @@ """OAuth Callback Views""" + from json import JSONDecodeError -from typing import Any, Optional +from typing import Any from django.conf import settings from django.contrib import messages @@ -22,16 +23,15 @@ class OAuthCallback(OAuthClientMixin, View): "Base OAuth callback view." source: OAuthSource - token: Optional[dict] = None + token: dict | None = None - # pylint: disable=too-many-return-statements def dispatch(self, request: HttpRequest, *_, **kwargs) -> HttpResponse: """View Get handler""" slug = kwargs.get("source_slug", "") try: self.source = OAuthSource.objects.get(slug=slug) except OAuthSource.DoesNotExist: - raise Http404(f"Unknown OAuth source '{slug}'.") + raise Http404(f"Unknown OAuth source '{slug}'.") from None if not self.source.enabled: raise Http404(f"Source {slug} is not enabled.") @@ -54,7 +54,7 @@ class OAuthCallback(OAuthClientMixin, View): raw_profile=exc.doc, ).from_http(self.request) return self.handle_login_failure("Could not retrieve profile.") - identifier = self.get_user_id(raw_info) + identifier = self.get_user_id(info=raw_info) if identifier is None: return self.handle_login_failure("Could not determine id.") # Get or create access record @@ -67,6 +67,7 @@ class OAuthCallback(OAuthClientMixin, View): ) sfm.policy_context = {"oauth_userinfo": raw_info} return sfm.get_flow( + raw_info=raw_info, access_token=self.token.get("access_token"), ) @@ -85,7 +86,7 @@ class OAuthCallback(OAuthClientMixin, View): """Create a dict of User data""" raise NotImplementedError() - def get_user_id(self, info: dict[str, Any]) -> Optional[str]: + def get_user_id(self, info: dict[str, Any]) -> str | None: """Return unique identifier from the profile info.""" if "id" in info: return info["id"] @@ -97,10 +98,11 @@ class OAuthCallback(OAuthClientMixin, View): messages.error( self.request, _( - "Authentication failed: %(reason)s" - % { - "reason": reason, - } + "Authentication failed: {reason}".format_map( + { + "reason": reason, + } + ) ), ) return redirect(self.get_error_redirect(self.source, reason)) @@ -114,7 +116,8 @@ class OAuthSourceFlowManager(SourceFlowManager): def update_connection( self, connection: UserOAuthSourceConnection, - access_token: Optional[str] = None, + access_token: str | None = None, + **_, ) -> UserOAuthSourceConnection: """Set the access_token on the connection""" connection.access_token = access_token diff --git a/authentik/sources/oauth/views/dispatcher.py b/authentik/sources/oauth/views/dispatcher.py index 234b936b3e..9fe4339fd6 100644 --- a/authentik/sources/oauth/views/dispatcher.py +++ b/authentik/sources/oauth/views/dispatcher.py @@ -1,4 +1,5 @@ """Dispatch OAuth views to respective views""" + from django.shortcuts import get_object_or_404 from django.utils.decorators import method_decorator from django.views import View diff --git a/authentik/sources/oauth/views/redirect.py b/authentik/sources/oauth/views/redirect.py index d5d38050d3..2a68060906 100644 --- a/authentik/sources/oauth/views/redirect.py +++ b/authentik/sources/oauth/views/redirect.py @@ -1,4 +1,5 @@ """OAuth Redirect Views""" + from typing import Any from django.http import Http404 @@ -35,7 +36,7 @@ class OAuthRedirect(OAuthClientMixin, RedirectView): try: source: OAuthSource = OAuthSource.objects.get(slug=slug) except OAuthSource.DoesNotExist: - raise Http404(f"Unknown OAuth source '{slug}'.") + raise Http404(f"Unknown OAuth source '{slug}'.") from None if not source.enabled: raise Http404(f"source {slug} is not enabled.") client = self.get_client(source, callback=self.get_callback_url(source)) diff --git a/authentik/sources/plex/api/source.py b/authentik/sources/plex/api/source.py index dd15b9a2b3..6d30b6c1e5 100644 --- a/authentik/sources/plex/api/source.py +++ b/authentik/sources/plex/api/source.py @@ -1,4 +1,5 @@ """Plex Source Serializer""" + from django.shortcuts import get_object_or_404 from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema @@ -12,12 +13,12 @@ from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger -from authentik.api.decorators import permission_required from authentik.core.api.sources import SourceSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.flows.challenge import RedirectChallenge from authentik.flows.views.executor import to_stage_response +from authentik.rbac.decorators import permission_required from authentik.sources.plex.models import PlexSource, PlexSourceConnection from authentik.sources.plex.plex import PlexAuth, PlexSourceFlowManager diff --git a/authentik/sources/plex/api/source_connection.py b/authentik/sources/plex/api/source_connection.py index f046a300f3..dcda9279a6 100644 --- a/authentik/sources/plex/api/source_connection.py +++ b/authentik/sources/plex/api/source_connection.py @@ -1,4 +1,5 @@ """Plex Source connection Serializer""" + from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import ModelViewSet diff --git a/authentik/sources/plex/apps.py b/authentik/sources/plex/apps.py index a8c89447b7..2170a61dc8 100644 --- a/authentik/sources/plex/apps.py +++ b/authentik/sources/plex/apps.py @@ -1,4 +1,5 @@ """authentik plex config""" + from django.apps import AppConfig diff --git a/authentik/sources/plex/models.py b/authentik/sources/plex/models.py index e20c809a33..13734cb3b3 100644 --- a/authentik/sources/plex/models.py +++ b/authentik/sources/plex/models.py @@ -1,5 +1,4 @@ """Plex source""" -from typing import Optional from django.contrib.postgres.fields import ArrayField from django.db import models @@ -61,33 +60,34 @@ class PlexSource(Source): return PlexSourceSerializer - def ui_login_button(self, request: HttpRequest) -> UILoginButton: - icon = self.icon_url + @property + def icon_url(self) -> str: + icon = super().icon_url if not icon: icon = static("authentik/sources/plex.svg") + return icon + + def ui_login_button(self, request: HttpRequest) -> UILoginButton: return UILoginButton( challenge=PlexAuthenticationChallenge( - { + data={ "type": ChallengeTypes.NATIVE.value, "component": "ak-source-plex", "client_id": self.client_id, "slug": self.slug, } ), - icon_url=icon, + icon_url=self.icon_url, name=self.name, ) - def ui_user_settings(self) -> Optional[UserSettingSerializer]: - icon = self.icon_url - if not icon: - icon = static("authentik/sources/plex.svg") + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.name, "component": "ak-user-settings-source-plex", "configure_url": self.client_id, - "icon_url": icon, + "icon_url": self.icon_url, } ) diff --git a/authentik/sources/plex/plex.py b/authentik/sources/plex/plex.py index 1c30db551d..caf245888f 100644 --- a/authentik/sources/plex/plex.py +++ b/authentik/sources/plex/plex.py @@ -1,4 +1,5 @@ """Plex Views""" + from urllib.parse import urlencode from django.http.response import Http404 @@ -84,7 +85,7 @@ class PlexAuth: resources = self.get_resources() except RequestException as exc: LOGGER.warning("Unable to fetch user resources", exc=exc) - raise Http404 + raise Http404 from None for resource in resources: if resource["provides"] != "server": continue diff --git a/authentik/sources/plex/settings.py b/authentik/sources/plex/settings.py index c231434843..5884bbe220 100644 --- a/authentik/sources/plex/settings.py +++ b/authentik/sources/plex/settings.py @@ -1,4 +1,5 @@ """Plex source settings""" + from celery.schedules import crontab from authentik.lib.utils.time import fqdn_rand diff --git a/authentik/sources/plex/tasks.py b/authentik/sources/plex/tasks.py index 63c8b83b0d..06b108edb6 100644 --- a/authentik/sources/plex/tasks.py +++ b/authentik/sources/plex/tasks.py @@ -1,4 +1,5 @@ """Plex tasks""" + from requests import RequestException from authentik.events.models import Event, EventAction, TaskStatus diff --git a/authentik/sources/plex/tests.py b/authentik/sources/plex/tests.py index 6a60433f7a..3b78e714cf 100644 --- a/authentik/sources/plex/tests.py +++ b/authentik/sources/plex/tests.py @@ -1,4 +1,5 @@ """plex Source tests""" + from django.test import TestCase from requests.exceptions import RequestException from requests_mock import Mocker @@ -39,6 +40,11 @@ class TestPlexSource(TestCase): slug="test", ) + def test_login_challenge(self): + """Test login_challenge""" + ui_login_button = self.source.ui_login_button(None) + self.assertTrue(ui_login_button.challenge.is_valid(raise_exception=True)) + def test_get_user_info(self): """Test get_user_info""" token = generate_key() diff --git a/authentik/sources/plex/urls.py b/authentik/sources/plex/urls.py index d47b269309..d1fa679dad 100644 --- a/authentik/sources/plex/urls.py +++ b/authentik/sources/plex/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.sources.plex.api.source import PlexSourceViewSet from authentik.sources.plex.api.source_connection import PlexSourceConnectionViewSet diff --git a/authentik/sources/saml/api/source.py b/authentik/sources/saml/api/source.py index e0dacad046..a3f0e9bd41 100644 --- a/authentik/sources/saml/api/source.py +++ b/authentik/sources/saml/api/source.py @@ -1,4 +1,5 @@ """SAMLSource API Views""" + from django.urls import reverse from drf_spectacular.utils import extend_schema from rest_framework.decorators import action diff --git a/authentik/sources/saml/api/source_connection.py b/authentik/sources/saml/api/source_connection.py index 25351569d8..8e81b78cf9 100644 --- a/authentik/sources/saml/api/source_connection.py +++ b/authentik/sources/saml/api/source_connection.py @@ -1,4 +1,5 @@ """SAML Source Serializer""" + from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import ModelViewSet diff --git a/authentik/sources/saml/apps.py b/authentik/sources/saml/apps.py index f7c2847e77..4d6feb54b5 100644 --- a/authentik/sources/saml/apps.py +++ b/authentik/sources/saml/apps.py @@ -1,4 +1,5 @@ """Authentik SAML app config""" + from authentik.blueprints.apps import ManagedAppConfig @@ -10,7 +11,3 @@ class AuthentikSourceSAMLConfig(ManagedAppConfig): verbose_name = "authentik Sources.SAML" mountpoint = "source/saml/" default = True - - def reconcile_global_load_sources_saml_signals(self): - """Load sources.saml signals""" - self.import_module("authentik.sources.saml.signals") diff --git a/authentik/sources/saml/exceptions.py b/authentik/sources/saml/exceptions.py index 344ee005bf..057a040aa2 100644 --- a/authentik/sources/saml/exceptions.py +++ b/authentik/sources/saml/exceptions.py @@ -1,4 +1,5 @@ """authentik saml source exceptions""" + from authentik.lib.sentry import SentryIgnoredException diff --git a/authentik/sources/saml/migrations/0014_alter_samlsource_digest_algorithm_and_more.py b/authentik/sources/saml/migrations/0014_alter_samlsource_digest_algorithm_and_more.py new file mode 100644 index 0000000000..12c0c853bc --- /dev/null +++ b/authentik/sources/saml/migrations/0014_alter_samlsource_digest_algorithm_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 5.0.4 on 2024-05-01 15:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_sources_saml", "0013_samlsource_verification_kp_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="samlsource", + name="digest_algorithm", + field=models.TextField( + choices=[ + ("http://www.w3.org/2000/09/xmldsig#sha1", "SHA1"), + ("http://www.w3.org/2001/04/xmlenc#sha256", "SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#sha384", "SHA384"), + ("http://www.w3.org/2001/04/xmlenc#sha512", "SHA512"), + ], + default="http://www.w3.org/2001/04/xmlenc#sha256", + ), + ), + migrations.AlterField( + model_name="samlsource", + name="signature_algorithm", + field=models.TextField( + choices=[ + ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "RSA-SHA1"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "RSA-SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "RSA-SHA384"), + ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "RSA-SHA512"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", "ECDSA-SHA1"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "ECDSA-SHA256"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", "ECDSA-SHA384"), + ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "ECDSA-SHA512"), + ("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "DSA-SHA1"), + ], + default="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + ), + ), + ] diff --git a/authentik/sources/saml/models.py b/authentik/sources/saml/models.py index 6c24abf8d4..c4b998bf26 100644 --- a/authentik/sources/saml/models.py +++ b/authentik/sources/saml/models.py @@ -1,5 +1,4 @@ """saml sp models""" -from typing import Optional from django.db import models from django.http import HttpRequest @@ -16,6 +15,10 @@ from authentik.flows.models import Flow from authentik.lib.utils.time import timedelta_string_validator from authentik.sources.saml.processors.constants import ( DSA_SHA1, + ECDSA_SHA1, + ECDSA_SHA256, + ECDSA_SHA384, + ECDSA_SHA512, RSA_SHA1, RSA_SHA256, RSA_SHA384, @@ -144,8 +147,7 @@ class SAMLSource(Source): verbose_name=_("Signing Keypair"), ) - digest_algorithm = models.CharField( - max_length=50, + digest_algorithm = models.TextField( choices=( (SHA1, _("SHA1")), (SHA256, _("SHA256")), @@ -154,13 +156,16 @@ class SAMLSource(Source): ), default=SHA256, ) - signature_algorithm = models.CharField( - max_length=50, + signature_algorithm = models.TextField( choices=( (RSA_SHA1, _("RSA-SHA1")), (RSA_SHA256, _("RSA-SHA256")), (RSA_SHA384, _("RSA-SHA384")), (RSA_SHA512, _("RSA-SHA512")), + (ECDSA_SHA1, _("ECDSA-SHA1")), + (ECDSA_SHA256, _("ECDSA-SHA256")), + (ECDSA_SHA384, _("ECDSA-SHA384")), + (ECDSA_SHA512, _("ECDSA-SHA512")), (DSA_SHA1, _("DSA-SHA1")), ), default=RSA_SHA256, @@ -176,6 +181,13 @@ class SAMLSource(Source): return SAMLSourceSerializer + @property + def icon_url(self) -> str: + icon = super().icon_url + if not icon: + return static("authentik/sources/saml.png") + return icon + def get_issuer(self, request: HttpRequest) -> str: """Get Source's Issuer, falling back to our Metadata URL if none is set""" if self.issuer is None: @@ -191,7 +203,7 @@ class SAMLSource(Source): def ui_login_button(self, request: HttpRequest) -> UILoginButton: return UILoginButton( challenge=RedirectChallenge( - instance={ + data={ "type": ChallengeTypes.REDIRECT.value, "to": reverse( "authentik_sources_saml:login", @@ -203,10 +215,7 @@ class SAMLSource(Source): icon_url=self.icon_url, ) - def ui_user_settings(self) -> Optional[UserSettingSerializer]: - icon = self.icon_url - if not icon: - icon = static(f"authentik/sources/{self.slug}.svg") + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.name, @@ -215,7 +224,7 @@ class SAMLSource(Source): "authentik_sources_saml:login", kwargs={"source_slug": self.slug}, ), - "icon_url": icon, + "icon_url": self.icon_url, } ) diff --git a/authentik/sources/saml/processors/constants.py b/authentik/sources/saml/processors/constants.py index d7e4bcd07e..e0eed95ada 100644 --- a/authentik/sources/saml/processors/constants.py +++ b/authentik/sources/saml/processors/constants.py @@ -1,4 +1,5 @@ """SAML Source processor constants""" + import xmlsec NS_SAML_PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol" @@ -25,9 +26,16 @@ SAML_BINDING_REDIRECT = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1" RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" +# https://datatracker.ietf.org/doc/html/rfc4051#section-2.3.2 RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384" RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" +# https://datatracker.ietf.org/doc/html/rfc4051#section-2.3.6 +ECDSA_SHA1 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1" +ECDSA_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224" +ECDSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256" +ECDSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384" +ECDSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512" SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1" SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256" @@ -40,6 +48,11 @@ SIGN_ALGORITHM_TRANSFORM_MAP = { RSA_SHA256: xmlsec.constants.TransformRsaSha256, RSA_SHA384: xmlsec.constants.TransformRsaSha384, RSA_SHA512: xmlsec.constants.TransformRsaSha512, + ECDSA_SHA1: xmlsec.constants.TransformEcdsaSha1, + ECDSA_SHA224: xmlsec.constants.TransformEcdsaSha224, + ECDSA_SHA256: xmlsec.constants.TransformEcdsaSha256, + ECDSA_SHA384: xmlsec.constants.TransformEcdsaSha384, + ECDSA_SHA512: xmlsec.constants.TransformEcdsaSha512, } DIGEST_ALGORITHM_TRANSLATION_MAP = { diff --git a/authentik/sources/saml/processors/metadata.py b/authentik/sources/saml/processors/metadata.py index 4ea8257106..34bd4b5b66 100644 --- a/authentik/sources/saml/processors/metadata.py +++ b/authentik/sources/saml/processors/metadata.py @@ -1,5 +1,7 @@ """SAML Service Provider Metadata Processor""" -from typing import Iterator, Optional + +from collections.abc import Iterator +from typing import Optional from django.http import HttpRequest from lxml.etree import Element, SubElement, tostring # nosec @@ -29,7 +31,8 @@ class MetadataProcessor: self.source = source self.http_request = request - def get_signing_key_descriptor(self) -> Optional[Element]: + # Using type unions doesn't work with cython types (which is what lxml is) + def get_signing_key_descriptor(self) -> Optional[Element]: # noqa: UP007 """Get Signing KeyDescriptor, if enabled for the source""" if self.source.signing_kp: key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor") @@ -63,9 +66,9 @@ class MetadataProcessor: entity_descriptor.attrib["entityID"] = self.source.get_issuer(self.http_request) sp_sso_descriptor = SubElement(entity_descriptor, f"{{{NS_SAML_METADATA}}}SPSSODescriptor") - sp_sso_descriptor.attrib[ - "protocolSupportEnumeration" - ] = "urn:oasis:names:tc:SAML:2.0:protocol" + sp_sso_descriptor.attrib["protocolSupportEnumeration"] = ( + "urn:oasis:names:tc:SAML:2.0:protocol" + ) signing_descriptor = self.get_signing_key_descriptor() if signing_descriptor is not None: diff --git a/authentik/sources/saml/processors/request.py b/authentik/sources/saml/processors/request.py index c7a81029c8..ff36812a1f 100644 --- a/authentik/sources/saml/processors/request.py +++ b/authentik/sources/saml/processors/request.py @@ -1,4 +1,5 @@ """SAML AuthnRequest Processor""" + from base64 import b64encode from urllib.parse import quote_plus diff --git a/authentik/sources/saml/processors/response.py b/authentik/sources/saml/processors/response.py index 78a8d19930..508a77ba05 100644 --- a/authentik/sources/saml/processors/response.py +++ b/authentik/sources/saml/processors/response.py @@ -1,4 +1,5 @@ """authentik saml source processor""" + from base64 import b64decode from time import mktime from typing import TYPE_CHECKING, Any @@ -233,12 +234,14 @@ class ResponseProcessor: if name_id.attrib["Format"] == SAML_NAME_ID_FORMAT_TRANSIENT: return self._handle_name_id_transient() - return SAMLSourceFlowManager( + flow_manager = SAMLSourceFlowManager( self._source, self._http_request, name_id.text, delete_none_values(self.get_attributes()), ) + flow_manager.policy_context["saml_response"] = self._root + return flow_manager class SAMLSourceFlowManager(SourceFlowManager): diff --git a/authentik/sources/saml/signals.py b/authentik/sources/saml/signals.py index 6c37b1aaf1..ebcb8bae99 100644 --- a/authentik/sources/saml/signals.py +++ b/authentik/sources/saml/signals.py @@ -1,4 +1,5 @@ """authentik saml source signal listener""" + from django.contrib.auth.signals import user_logged_out from django.dispatch import receiver from django.http import HttpRequest diff --git a/authentik/sources/saml/tests/test_metadata.py b/authentik/sources/saml/tests/test_metadata.py index d81033e120..953745c2dc 100644 --- a/authentik/sources/saml/tests/test_metadata.py +++ b/authentik/sources/saml/tests/test_metadata.py @@ -1,4 +1,5 @@ """SAML Source tests""" + from defusedxml import ElementTree from django.test import RequestFactory, TestCase from lxml import etree # nosec diff --git a/authentik/sources/saml/tests/test_response.py b/authentik/sources/saml/tests/test_response.py index f66a28b231..b22957c8d3 100644 --- a/authentik/sources/saml/tests/test_response.py +++ b/authentik/sources/saml/tests/test_response.py @@ -1,4 +1,5 @@ """SAML Source tests""" + from base64 import b64encode from django.contrib.sessions.middleware import SessionMiddleware diff --git a/authentik/sources/saml/urls.py b/authentik/sources/saml/urls.py index ee95631db6..6abeb3f4db 100644 --- a/authentik/sources/saml/urls.py +++ b/authentik/sources/saml/urls.py @@ -1,4 +1,5 @@ """saml sp urls""" + from django.urls import path from authentik.sources.saml.api.source import SAMLSourceViewSet diff --git a/authentik/sources/saml/views.py b/authentik/sources/saml/views.py index 1ab6c860ab..37550d735e 100644 --- a/authentik/sources/saml/views.py +++ b/authentik/sources/saml/views.py @@ -1,4 +1,5 @@ """saml sp views""" + from urllib.parse import parse_qsl, urlparse, urlunparse from django.contrib.auth import logout @@ -87,7 +88,7 @@ class InitiateView(View): try: plan = planner.plan(self.request, kwargs) except FlowNonApplicableException: - raise Http404 + raise Http404 from None for stage in stages_to_append: plan.append_stage(stage) self.request.session[SESSION_KEY_PLAN] = plan diff --git a/authentik/sources/scim/__init__.py b/authentik/sources/scim/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/api/__init__.py b/authentik/sources/scim/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/api/groups.py b/authentik/sources/scim/api/groups.py new file mode 100644 index 0000000000..8d7a6ccfe3 --- /dev/null +++ b/authentik/sources/scim/api/groups.py @@ -0,0 +1,35 @@ +"""SCIMSourceGroup API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.users import UserGroupSerializer +from authentik.sources.scim.models import SCIMSourceGroup + + +class SCIMSourceGroupSerializer(SourceSerializer): + """SCIMSourceGroup Serializer""" + + group_obj = UserGroupSerializer(source="group", read_only=True) + + class Meta: + + model = SCIMSourceGroup + fields = [ + "id", + "group", + "group_obj", + "source", + "attributes", + ] + + +class SCIMSourceGroupViewSet(UsedByMixin, ModelViewSet): + """SCIMSourceGroup Viewset""" + + queryset = SCIMSourceGroup.objects.all().select_related("group") + serializer_class = SCIMSourceGroupSerializer + filterset_fields = ["source__slug", "group__name", "group__group_uuid"] + search_fields = ["source__slug", "group__name", "attributes"] + ordering = ["group__name"] diff --git a/authentik/sources/scim/api/sources.py b/authentik/sources/scim/api/sources.py new file mode 100644 index 0000000000..f89830f8fe --- /dev/null +++ b/authentik/sources/scim/api/sources.py @@ -0,0 +1,57 @@ +"""SCIMSource API Views""" + +from django.urls import reverse_lazy +from rest_framework.fields import SerializerMethodField +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.tokens import TokenSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.sources.scim.models import SCIMSource + + +class SCIMSourceSerializer(SourceSerializer): + """SCIMSource Serializer""" + + root_url = SerializerMethodField() + token_obj = TokenSerializer(source="token", required=False, read_only=True) + + def get_root_url(self, instance: SCIMSource) -> str: + """Get Root URL""" + relative_url = reverse_lazy( + "authentik_sources_scim:v2-root", + kwargs={"source_slug": instance.slug}, + ) + if "request" not in self.context: + return relative_url + return self.context["request"].build_absolute_uri(relative_url) + + class Meta: + + model = SCIMSource + fields = [ + "pk", + "name", + "slug", + "enabled", + "component", + "verbose_name", + "verbose_name_plural", + "meta_model_name", + "user_matching_mode", + "managed", + "user_path_template", + "root_url", + "token_obj", + ] + + +class SCIMSourceViewSet(UsedByMixin, ModelViewSet): + """SCIMSource Viewset""" + + queryset = SCIMSource.objects.all() + serializer_class = SCIMSourceSerializer + lookup_field = "slug" + filterset_fields = ["name", "slug"] + search_fields = ["name", "slug", "token__identifier", "token__user__username"] + ordering = ["name"] diff --git a/authentik/sources/scim/api/users.py b/authentik/sources/scim/api/users.py new file mode 100644 index 0000000000..e50af1786a --- /dev/null +++ b/authentik/sources/scim/api/users.py @@ -0,0 +1,35 @@ +"""SCIMSourceUser API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.groups import GroupMemberSerializer +from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin +from authentik.sources.scim.models import SCIMSourceUser + + +class SCIMSourceUserSerializer(SourceSerializer): + """SCIMSourceUser Serializer""" + + user_obj = GroupMemberSerializer(source="user", read_only=True) + + class Meta: + + model = SCIMSourceUser + fields = [ + "id", + "user", + "user_obj", + "source", + "attributes", + ] + + +class SCIMSourceUserViewSet(UsedByMixin, ModelViewSet): + """SCIMSourceUser Viewset""" + + queryset = SCIMSourceUser.objects.all().select_related("user") + serializer_class = SCIMSourceUserSerializer + filterset_fields = ["source__slug", "user__username", "user__id"] + search_fields = ["source__slug", "user__username", "attributes"] + ordering = ["user__username"] diff --git a/authentik/sources/scim/apps.py b/authentik/sources/scim/apps.py new file mode 100644 index 0000000000..a4427c058f --- /dev/null +++ b/authentik/sources/scim/apps.py @@ -0,0 +1,13 @@ +"""Authentik SCIM app config""" + +from authentik.blueprints.apps import ManagedAppConfig + + +class AuthentikSourceSCIMConfig(ManagedAppConfig): + """authentik SCIM Source app config""" + + name = "authentik.sources.scim" + label = "authentik_sources_scim" + verbose_name = "authentik Sources.SCIM" + mountpoint = "source/scim/" + default = True diff --git a/authentik/sources/scim/errors.py b/authentik/sources/scim/errors.py new file mode 100644 index 0000000000..76c3f3a017 --- /dev/null +++ b/authentik/sources/scim/errors.py @@ -0,0 +1,8 @@ +"""SCIM Errors""" + +from authentik.lib.sentry import SentryIgnoredException + + +class PatchError(SentryIgnoredException): + """Error raised within an atomic block when an error happened + so nothing is saved""" diff --git a/authentik/sources/scim/migrations/0001_initial.py b/authentik/sources/scim/migrations/0001_initial.py new file mode 100644 index 0000000000..635a852ff0 --- /dev/null +++ b/authentik/sources/scim/migrations/0001_initial.py @@ -0,0 +1,94 @@ +# Generated by Django 5.0.4 on 2024-04-07 14:34 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("authentik_core", "0033_alter_user_options"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="SCIMSource", + fields=[ + ( + "source_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_core.source", + ), + ), + ( + "token", + models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="authentik_core.token", + ), + ), + ], + options={ + "verbose_name": "SCIM Source", + "verbose_name_plural": "SCIM Sources", + }, + bases=("authentik_core.source",), + ), + migrations.CreateModel( + name="SCIMSourceGroup", + fields=[ + ("id", models.TextField(primary_key=True, serialize=False)), + ("attributes", models.JSONField(default=dict)), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group" + ), + ), + ( + "source", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_sources_scim.scimsource", + ), + ), + ], + options={ + "unique_together": {("id", "group", "source")}, + }, + ), + migrations.CreateModel( + name="SCIMSourceUser", + fields=[ + ("id", models.TextField(primary_key=True, serialize=False)), + ("attributes", models.JSONField(default=dict)), + ( + "source", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="authentik_sources_scim.scimsource", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ], + options={ + "unique_together": {("id", "user", "source")}, + }, + ), + ] diff --git a/authentik/sources/scim/migrations/__init__.py b/authentik/sources/scim/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/models.py b/authentik/sources/scim/models.py new file mode 100644 index 0000000000..de2149ee67 --- /dev/null +++ b/authentik/sources/scim/models.py @@ -0,0 +1,89 @@ +"""SCIM Source""" + +from uuid import uuid4 + +from django.db import models +from django.templatetags.static import static +from django.utils.translation import gettext_lazy as _ +from rest_framework.serializers import BaseSerializer + +from authentik.core.models import Group, Source, Token, User +from authentik.lib.models import SerializerModel + + +class SCIMSource(Source): + """System for Cross-domain Identity Management Source, allows for + cross-system user provisioning""" + + token = models.ForeignKey(Token, on_delete=models.CASCADE, null=True, default=None) + + @property + def service_account_identifier(self) -> str: + if not self.pk: + self.pk = uuid4() + return f"ak-source-scim-{self.pk}" + + @property + def component(self) -> str: + """Return component used to edit this object""" + return "ak-source-scim-form" + + @property + def icon_url(self) -> str: + return static("authentik/sources/scim.png") + + @property + def serializer(self) -> BaseSerializer: + from authentik.sources.scim.api.sources import SCIMSourceSerializer + + return SCIMSourceSerializer + + def __str__(self) -> str: + return f"SCIM Source {self.name}" + + class Meta: + + verbose_name = _("SCIM Source") + verbose_name_plural = _("SCIM Sources") + + +class SCIMSourceUser(SerializerModel): + """Mapping of a user and source to a SCIM user ID""" + + id = models.TextField(primary_key=True) + user = models.ForeignKey(User, on_delete=models.CASCADE) + source = models.ForeignKey(SCIMSource, on_delete=models.CASCADE) + attributes = models.JSONField(default=dict) + + @property + def serializer(self) -> BaseSerializer: + from authentik.sources.scim.api.users import SCIMSourceUserSerializer + + return SCIMSourceUserSerializer + + class Meta: + unique_together = (("id", "user", "source"),) + + def __str__(self) -> str: + return f"SCIM User {self.user_id} to {self.source_id}" + + +class SCIMSourceGroup(SerializerModel): + """Mapping of a group and source to a SCIM user ID""" + + id = models.TextField(primary_key=True) + group = models.ForeignKey(Group, on_delete=models.CASCADE) + source = models.ForeignKey(SCIMSource, on_delete=models.CASCADE) + attributes = models.JSONField(default=dict) + + @property + def serializer(self) -> BaseSerializer: + from authentik.sources.scim.api.groups import SCIMSourceGroupSerializer + + return SCIMSourceGroupSerializer + + class Meta: + unique_together = (("id", "group", "source"),) + + def __str__(self) -> str: + return f"SCIM Group {self.group_id} to {self.source_id}" diff --git a/authentik/sources/scim/schemas/schema.json b/authentik/sources/scim/schemas/schema.json new file mode 100644 index 0000000000..dc9cc2c9a7 --- /dev/null +++ b/authentik/sources/scim/schemas/schema.json @@ -0,0 +1,1796 @@ +[ + { + "id": "urn:ietf:params:scim:schemas:core:2.0:Meta", + "name": "Meta", + "description": "A complex attribute containing resource metadata. All \"meta\" sub-attributes are assigned, by the service provider (have a \"mutability\" of \"readOnly\"), and all of these sub-attributes have a \"returned\" characteristic of \"default\". This attribute SHALL be ignored when provided by clients. ", + "attributes": [ + { + "name": "meta", + "type": "complex", + "multiValued": false, + "description": "the meta attribute", + "required": false, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "resourceType", + "type": "string", + "multiValued": false, + "description": "The name of the resource type of the resource. This attribute has a mutability of \"readOnly\" and \"caseExact\" as \"True\".", + "required": false, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "created", + "type": "dateTime", + "multiValued": false, + "description": "The \"DateTime\" that the resource was added to the service provider. This attribute MUST be a DateTime.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "lastModified", + "type": "dateTime", + "multiValued": false, + "description": "The most recent DateTime that the details of this resource were updated at the service provider. If this resource has never been modified since its initial creation, the value MUST be the same as the value of \"created\".", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "location", + "type": "reference", + "multiValued": false, + "description": "The URI of the resource being returned. This value MUST be the same as the \"Content-Location\" HTTP response header (see Section 3.1.4.2 of [RFC7231])", + "required": false, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["uri"] + }, + { + "name": "version", + "type": "string", + "multiValued": false, + "description": "The version of the resource being returned. This value must be the same as the entity-tag (ETag) HTTP response header (see Sections 2.1 and 2.3 of [RFC7232]). This attribute has \"caseExact\" as \"True\". Service provider support for this attribute is optional and subject to the service provider's support for versioning (see Section 3.14 of [RFC7644]). If a service provider provides \"version\" (entity-tag) for a representation and the generation of that entity-tag does not satisfy all of the characteristics of a strong validator (see Section 2.1 of [RFC7232]), then the origin server MUST mark the \"version\" (entity-tag) as weak by prefixing its opaque value with \"W/\" (case sensitive).", + "required": false, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:core:2.0:Group", + "name": "Group", + "description": "Group", + "attributes": [ + { + "name": "id", + "type": "string", + "multiValued": false, + "description": "Unique identifier for the SCIM Resource as defined by the Service Provider.", + "required": true, + "caseExact": true, + "mutability": "readOnly", + "returned": "always", + "uniqueness": "server" + }, + { + "name": "externalId", + "type": "string", + "multiValued": false, + "description": "A String that is an identifier for the resource as defined by the provisioning client.The service provider MUST always interpret the externalId as scoped to the provisioning domain.", + "required": false, + "caseExact": true, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "displayName", + "type": "string", + "multiValued": false, + "description": "A human-readable name for the Group. REQUIRED.", + "required": true, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "members", + "type": "complex", + "multiValued": true, + "description": "A list of members of the Group.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "Identifier of the member of this Group.", + "required": true, + "caseExact": false, + "mutability": "immutable", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "$ref", + "type": "reference", + "multiValued": false, + "description": "The uri corresponding to a SCIM resource that is a member of this Group.", + "required": false, + "caseExact": false, + "mutability": "immutable", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["resource"] + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name for the Member", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the type of resource, e.g. 'User' or 'Group'", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:core:2.0:Schema", + "name": "Schema", + "description": "Specifies the schema that describes a SCIM schema", + "attributes": [ + { + "name": "id", + "type": "string", + "multiValued": false, + "description": "The unique URI of the schema. When applicable, service providers MUST specify the URI.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "name", + "type": "string", + "multiValued": false, + "description": "The schema's human-readable name. When applicable, service providers MUST specify the name, e.g., 'User'.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "description", + "type": "string", + "multiValued": false, + "description": "The schema's human-readable name. When applicable, service providers MUST specify the name, e.g., 'User'.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "attributes", + "type": "complex", + "multiValued": true, + "description": "A complex attribute that includes the attributes of a schema.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "name", + "type": "string", + "multiValued": false, + "description": "The attribute's name.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "The attribute's data type. Valid values include 'string', 'complex', 'boolean', 'decimal', 'integer', 'dateTime', 'reference'.", + "required": true, + "canonicalValues": [ + "string", + "complex", + "boolean", + "decimal", + "integer", + "dateTime", + "reference", + "any" + ], + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "multiValued", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating an attribute's plurality.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "description", + "type": "string", + "multiValued": false, + "description": "A human-readable description of the attribute.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "required", + "type": "boolean", + "multiValued": false, + "description": "A boolean value indicating whether or not the attribute is required.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "canonicalValues", + "type": "string", + "multiValued": true, + "description": "A collection of canonical values. When applicable, service providers MUST specify the canonical types, e.g., 'work', 'home'.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "caseExact", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating whether or not a string attribute is case sensitive.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "mutability", + "type": "string", + "multiValued": false, + "description": "Indicates whether or not an attribute is modifiable.", + "required": false, + "canonicalValues": [ + "readOnly", + "readWrite", + "immutable", + "writeOnly" + ], + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "returned", + "type": "string", + "multiValued": false, + "description": "Indicates when an attribute is returned in a response (e.g., to a query).", + "required": false, + "canonicalValues": [ + "always", + "never", + "default", + "request" + ], + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "uniqueness", + "type": "string", + "multiValued": false, + "description": "Indicates how unique a value must be.", + "required": false, + "canonicalValues": ["none", "server", "global"], + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "referenceTypes", + "type": "string", + "multiValued": true, + "description": "Used only with an attribute of type 'reference'. Specifies a SCIM resourceType that a reference attribute MAY refer to, e.g., 'User'.", + "required": false, + "canonicalValues": [ + "resource", + "external", + "uri", + "url" + ], + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "multipleOf", + "type": "decimal", + "multiValued": false, + "description": "The value of \"multipleOf\" MUST be a number, strictly greater than 0. A numeric instance is valid only if division by this keyword's value results in an integer.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "minimum", + "type": "decimal", + "multiValued": false, + "description": "The value of \"minimum\" MUST be a number, representing an inclusive lower limit for a numeric instance. If the instance is a number, then this keyword validates only if the instance is greater than or exactly equal to \"minimum\".", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maximum", + "type": "decimal", + "multiValued": false, + "description": "The value of \"maximum\" MUST be a number, representing an inclusive upper limit for a numeric instance. If the instance is a number, then this keyword validates only if the instance is less than or exactly equal to \"maximum\".", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maxLength", + "type": "integer", + "multiValued": false, + "description": "The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 8259 [RFC8259].", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "minLength", + "type": "integer", + "multiValued": false, + "description": "The value of this keyword MUST be a non-negative integer. A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. The length of a string instance is defined as the number of its characters as defined by RFC 8259 [RFC8259]. Omitting this keyword has the same behavior as a value of 0.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "pattern", + "type": "string", + "multiValued": false, + "description": "The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the Java regular expression dialect. A string instance is considered valid if the regular expression matches the instance successfully.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "minItems", + "type": "integer", + "multiValued": false, + "description": "The value of this keyword MUST be a non-negative integer. An array instance is valid against \"minItems\" if its size is greater than, or equal to, the value of this keyword. Omitting this keyword has the same behavior as a value of 0.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maxItems", + "type": "integer", + "multiValued": false, + "description": "The value of this keyword MUST be a non-negative integer. An array instance is valid against \"maxItems\" if its size is less than, or equal to, the value of this keyword.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "notBefore", + "type": "dateTime", + "multiValued": false, + "description": "The value of this keyword MUST be a dateTime. It will verify that a given dateTime will not a have a value that is before this dateTime.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "notAfter", + "type": "dateTime", + "multiValued": false, + "description": "The value of this keyword MUST be a dateTime. It will verify that a given dateTime will not a have a value that is after this dateTime.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "subAttributes", + "type": "complex", + "multiValued": true, + "description": "Used to define the sub-attributes of a complex attribute.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig", + "name": "Service Provider Configuration", + "description": "Schema for representing the service provider's configuration", + "attributes": [ + { + "name": "documentationUri", + "type": "reference", + "multiValued": false, + "description": "An HTTP-addressable URL pointing to the service provider's human-consumable help documentation.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "patch", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies PATCH configuration options.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "etag", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies ETag configuration options.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "bulk", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies bulk configuration options.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maxOperations", + "type": "integer", + "multiValued": false, + "description": "An integer value specifying the maximum number of operations.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maxPayloadSize", + "type": "integer", + "multiValued": false, + "description": "An integer value specifying the maximum payload size in bytes.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "filter", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies FILTER options.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "maxResults", + "type": "integer", + "multiValued": false, + "description": "An integer value specifying the maximum number of resources returned in a response.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "changePassword", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies configuration options related to changing a password.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "sort", + "type": "complex", + "multiValued": false, + "description": "A complex type that specifies sort result options.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "supported", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value specifying whether or not the operation is supported.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "authenticationSchemes", + "type": "complex", + "multiValued": true, + "description": "A complex type that specifies supported authentication scheme properties.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "name", + "type": "string", + "multiValued": false, + "description": "The common authentication scheme name, e.g., HTTP Basic.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "description", + "type": "string", + "multiValued": false, + "description": "A description of the authentication scheme.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "specUri", + "type": "reference", + "multiValued": false, + "description": "An HTTP-addressable URL pointing to the authentication scheme's specification.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "documentationUri", + "type": "reference", + "multiValued": false, + "description": "An HTTP-addressable URL pointing to the authentication scheme's usage documentation.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "The authentication scheme. This specification defines the values \"oauth\", \"oauth2\", \"oauthbearertoken\", \"httpbasic\", and \"httpdigest\". REQUIRED.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + "name": "ResourceType", + "description": "Specifies the schema that describes a SCIM resource type", + "attributes": [ + { + "name": "id", + "type": "string", + "multiValued": false, + "description": "The resource type's server unique id. May be the same as the 'name' attribute.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "name", + "type": "string", + "multiValued": false, + "description": "The resource type name. When applicable, service providers MUST specify the name, e.g., 'User'.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "description", + "type": "string", + "multiValued": false, + "description": "The resource type's human-readable description. When applicable, service providers MUST specify the description.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "endpoint", + "type": "reference", + "multiValued": false, + "description": "The resource type's HTTP-addressable endpoint relative to the Base URL, e.g., '/Users'.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["uri"] + }, + { + "name": "schema", + "type": "reference", + "multiValued": false, + "description": "The resource type's primary/base schema URI.", + "required": true, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["uri"] + }, + { + "name": "schemaExtensions", + "type": "complex", + "multiValued": true, + "description": "A list of URIs of the resource type's schema extensions.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "schema", + "type": "reference", + "multiValued": false, + "description": "The URI of a schema extension.", + "required": true, + "caseExact": true, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["uri"] + }, + { + "name": "required", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value that specifies whether or not the schema extension is required for the resource type. If True, a resource of this type MUST include this schema extension and also include any attributes declared as required in this schema extension. If False, a resource of this type MAY omit this schema extension.", + "required": true, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:core:2.0:User", + "name": "User", + "description": "User Account", + "attributes": [ + { + "name": "id", + "type": "string", + "multiValued": false, + "description": "Unique identifier for the SCIM Resource as defined by the Service Provider.", + "required": true, + "caseExact": true, + "mutability": "readOnly", + "returned": "always", + "uniqueness": "server" + }, + { + "name": "externalId", + "type": "string", + "multiValued": false, + "description": "A String that is an identifier for the resource as defined by the provisioning client.The service provider MUST always interpret the externalId as scoped to the provisioning domain.", + "required": false, + "caseExact": true, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "userName", + "type": "string", + "multiValued": false, + "description": "A service provider's unique identifier for the user, typically\nused by the user to directly authenticate to the service provider.Each User MUST include a non-empty userName value. This identifier\nMUST be unique across the service provider's entire set of Users.", + "required": true, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "server", + "pattern": "^(?!\\s*$).+" + }, + { + "name": "name", + "type": "complex", + "multiValued": false, + "description": "The components of the user's real name.Providers MAY return just the full name as a single string in the\nformatted sub-attribute, or they MAY return just the individual component attributes using the other sub-attributes, or they MAY\nreturn both. If both variants are returned, they SHOULD be describing the same name, with the formatted name indicating how the\ncomponent attributes should be combined.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "formatted", + "type": "string", + "multiValued": false, + "description": "The full name, including all middle names, titles, and suffixes as appropriate, formatted for display\n(e.g., 'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "familyName", + "type": "string", + "multiValued": false, + "description": "The family name of the User, or last name in most Western languages (e.g., 'Jensen' given the full\nname 'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "givenName", + "type": "string", + "multiValued": false, + "description": "The given name of the User, or first name in most Western languages (e.g., 'Barbara' given the\nfull name 'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "middleName", + "type": "string", + "multiValued": false, + "description": "The middle name(s) of the User (e.g., 'Jane' given the full name 'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "honorificPrefix", + "type": "string", + "multiValued": false, + "description": "The honorific prefix(es) of the User, or title in most Western languages (e.g., 'Ms.' given the full name\n'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "honorificSuffix", + "type": "string", + "multiValued": false, + "description": "The honorific suffix(es) of the User, or suffix in most Western languages (e.g., 'III' given the full name\n'Ms. Barbara J Jensen, III').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "displayName", + "type": "string", + "multiValued": false, + "description": "The name of the User, suitable for display\nto end-users. The name SHOULD be the full name of the User being described, if known.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "nickName", + "type": "string", + "multiValued": false, + "description": "The casual way to address the user in real life, e.g., 'Bob' or 'Bobby' instead of 'Robert'. This attribute\nSHOULD NOT be used to represent a User's username (e.g., 'bjensen' or 'mpepperidge').", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "profileUrl", + "type": "reference", + "multiValued": false, + "description": "A fully qualified URL pointing to a page\nrepresenting the User's online profile.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "title", + "type": "string", + "multiValued": false, + "description": "The user's title, such as \\\"VicePresident.\\\"", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "userType", + "type": "string", + "multiValued": false, + "description": "Used to identify the relationship between the organization and the user. Typical values used might be\n'Contractor', 'Employee', 'Intern', 'Temp', 'External', and 'Unknown', but any value may be used.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "preferredLanguage", + "type": "string", + "multiValued": false, + "description": "Indicates the User's preferred written or\nspoken language. Generally used for selecting a localized user interface; e.g., 'en_US' specifies the language English and country", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "locale", + "type": "string", + "multiValued": false, + "description": "Used to indicate the User's default location\nfor purposes of localizing items such as currency, date time format, or numerical representations.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "timezone", + "type": "string", + "multiValued": false, + "description": "The User's time zone in the 'Olson' time zone\ndatabase format, e.g., 'America/Los_Angeles'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "active", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the User's administrative status.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "password", + "type": "string", + "multiValued": false, + "description": "The User's cleartext password. This attribute is intended to be used as a means to specify an initial\npassword when creating a new User or to reset an existing User's password.", + "required": false, + "caseExact": false, + "mutability": "writeOnly", + "returned": "never", + "uniqueness": "none" + }, + { + "name": "emails", + "type": "complex", + "multiValued": true, + "description": "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g.,\n'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'.Canonical type values of 'work', 'home', and 'other'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g.,\n'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'.Canonical type values of 'work', 'home', and 'other'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, e.g., 'work' or 'home'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the psreferred mailing address or primary email address. The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "phoneNumbers", + "type": "complex", + "multiValued": true, + "description": "Phone numbers for the User. The value SHOULD be canonicalized by the service provider according to the\nformat specified in RFC 3966, e.g., 'tel:+1-201-555-0123'.Canonical type values of 'work', 'home', 'mobile', 'fax', 'pager", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "Phone number of the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, e.g., 'work', 'home', 'mobile'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred\nphone number or primary phone number. The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "ims", + "type": "complex", + "multiValued": true, + "description": "Instant messaging addresses for the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "Instant messaging address for the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, e.g., 'aim', 'gtalk', 'xmpp'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred\nmessenger or primary messenger. The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "photos", + "type": "complex", + "multiValued": true, + "description": "URLs of photos of the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "reference", + "multiValued": false, + "description": "URLs of photos of the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, i.e., 'photo' or 'thumbnail'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred\nphone number or primary phone number. The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "addresses", + "type": "complex", + "multiValued": true, + "description": "A physical mailing address for this User.\nCanonical type values of 'work', 'home', and 'other'. This attribute is a complex type with the following sub-attributes.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "formatted", + "type": "string", + "multiValued": false, + "description": "The full mailing address, formatted for display or use with a mailing label. This attribute MAY contain\nnewlines.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "streetAddress", + "type": "string", + "multiValued": false, + "description": "The full street address component, which may include house number, street name, P.O. box, and multi-line\nextended street address information. This attribute MAY contain newlines.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "locality", + "type": "string", + "multiValued": false, + "description": "The city or locality component.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "region", + "type": "string", + "multiValued": false, + "description": "The state or region component.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "postalCode", + "type": "string", + "multiValued": false, + "description": "The zip code or postal code component.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "country", + "type": "string", + "multiValued": false, + "description": "The country name component.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, e.g., 'work' or 'home'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute. The primary\nattribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "groups", + "type": "complex", + "multiValued": true, + "description": "A list of groups to which the user belongs,\neither through direct membership, through nested groups, or dynamically calculated.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "The identifier of the User's group.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "$ref", + "type": "reference", + "multiValued": false, + "description": "The uri of the corresponding 'Group' resource to which the user belongs.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["resource"] + }, + { + "name": "display", + "type": "string", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function, e.g., 'direct' or 'indirect'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "entitlements", + "type": "complex", + "multiValued": true, + "description": "A list of entitlements for the User that represent a thing the User has.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "The value of an entitlement.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "reference", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute. The primary\nattribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "roles", + "type": "complex", + "multiValued": true, + "description": "A list of roles for the User that collectively represent who the User is, e.g., 'Student', 'Faculty'.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "The value of a role.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "reference", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute. The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + }, + { + "name": "x509Certificates", + "type": "complex", + "multiValued": true, + "description": "A list of certificates issued to the User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "server", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "The value of an X.509 certificate.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "display", + "type": "reference", + "multiValued": false, + "description": "A human-readable name, primarily used for display purposes. READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["external"] + }, + { + "name": "type", + "type": "string", + "multiValued": false, + "description": "A label indicating the attribute's function.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "primary", + "type": "boolean", + "multiValued": false, + "description": "A Boolean value indicating the 'primary' or preferred attribute value for this attribute.The primary attribute value 'True' MUST appear no more than once.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + }, + { + "id": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", + "name": "EnterpriseUser", + "description": "Enterprise User", + "attributes": [ + { + "name": "employeeNumber", + "type": "string", + "multiValued": false, + "description": "Numeric or alphanumeric identifier assigned to a person, typically based on order of hire or association with an organization.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "costCenter", + "type": "string", + "multiValued": false, + "description": "Identifies the name of a cost center.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "organization", + "type": "string", + "multiValued": false, + "description": "Identifies the name of an organization.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "division", + "type": "string", + "multiValued": false, + "description": "Identifies the name of a division.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "department", + "type": "string", + "multiValued": false, + "description": "Identifies the name of a department.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "manager", + "type": "complex", + "multiValued": false, + "description": "The User's manager. A complex type that optionally allows service providers to represent organizational hierarchy by referencing the 'id' attribute of another User.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "subAttributes": [ + { + "name": "value", + "type": "string", + "multiValued": false, + "description": "The id of the SCIM resource representing the User's manager. REQUIRED.", + "required": true, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none" + }, + { + "name": "$ref", + "type": "reference", + "multiValued": false, + "description": "The URI of the SCIM resource representing the User's manager. REQUIRED.", + "required": false, + "caseExact": false, + "mutability": "readWrite", + "returned": "default", + "uniqueness": "none", + "referenceTypes": ["resource"] + }, + { + "name": "displayName", + "type": "string", + "multiValued": false, + "description": "The displayName of the User's manager. OPTIONAL and READ-ONLY.", + "required": false, + "caseExact": false, + "mutability": "readOnly", + "returned": "default", + "uniqueness": "none" + } + ] + } + ], + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"], + "meta": { + "resourceType": "Schema" + } + } +] diff --git a/authentik/sources/scim/signals.py b/authentik/sources/scim/signals.py new file mode 100644 index 0000000000..8136a421a0 --- /dev/null +++ b/authentik/sources/scim/signals.py @@ -0,0 +1,41 @@ +from django.db.models import Model +from django.db.models.signals import pre_delete, pre_save +from django.dispatch import receiver + +from authentik.core.models import USER_PATH_SYSTEM_PREFIX, Token, TokenIntents, User, UserTypes +from authentik.sources.scim.models import SCIMSource + +USER_PATH_SOURCE_SCIM = USER_PATH_SYSTEM_PREFIX + "/sources/scim" + + +@receiver(pre_save, sender=SCIMSource) +def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_): + """Create service account before source is saved""" + # .service_account_identifier will auto-assign a primary key uuid to the source + # if none is set yet, just so we can get the identifier before we save + identifier = instance.service_account_identifier + user = User.objects.create( + username=identifier, + name=f"SCIM Source {instance.name} Service-Account", + type=UserTypes.INTERNAL_SERVICE_ACCOUNT, + path=USER_PATH_SOURCE_SCIM, + ) + token = Token.objects.create( + user=user, + identifier=identifier, + intent=TokenIntents.INTENT_API, + expiring=False, + managed=f"goauthentik.io/sources/scim/{instance.pk}", + ) + instance.token = token + + +@receiver(pre_delete, sender=SCIMSource) +def scim_source_pre_delete(sender: type[Model], instance: SCIMSource, **_): + """Delete SCIM Source service account before deleting source""" + Token.objects.filter( + identifier=instance.service_account_identifier, intent=TokenIntents.INTENT_API + ).delete() + User.objects.filter( + username=instance.service_account_identifier, type=UserTypes.INTERNAL_SERVICE_ACCOUNT + ).delete() diff --git a/authentik/sources/scim/tests/__init__.py b/authentik/sources/scim/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/tests/test_auth.py b/authentik/sources/scim/tests/test_auth.py new file mode 100644 index 0000000000..1fdf41b8bf --- /dev/null +++ b/authentik/sources/scim/tests/test_auth.py @@ -0,0 +1,73 @@ +"""Test SCIM Auth""" + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.core.models import Token, TokenIntents +from authentik.core.tests.utils import create_test_admin_user +from authentik.lib.generators import generate_id +from authentik.sources.scim.models import SCIMSource + + +class TestSCIMAuth(APITestCase): + """Test SCIM Auth view""" + + def setUp(self) -> None: + self.user = create_test_admin_user() + self.token3 = Token.objects.create( + user=self.user, + identifier=generate_id(), + intent=TokenIntents.INTENT_API, + ) + self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) + self.source2 = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) + + def test_auth_ok(self): + """Test successful auth""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_auth_missing(self): + """Test without header""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + }, + ), + ) + self.assertEqual(response.status_code, 403) + + def test_auth_wrong_token(self): + """Test with wrong token""" + # Token for wrong source + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source2.token.key}", + ) + self.assertEqual(response.status_code, 403) + # Token for no source + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.token3.key}", + ) + self.assertEqual(response.status_code, 403) diff --git a/authentik/sources/scim/tests/test_resource_types.py b/authentik/sources/scim/tests/test_resource_types.py new file mode 100644 index 0000000000..771a063a91 --- /dev/null +++ b/authentik/sources/scim/tests/test_resource_types.py @@ -0,0 +1,58 @@ +"""Test SCIM ResourceTypes""" + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.lib.generators import generate_id +from authentik.sources.scim.models import SCIMSource + + +class TestSCIMResourceTypes(APITestCase): + """Test SCIM ResourceTypes view""" + + def setUp(self) -> None: + self.source = SCIMSource.objects.create( + name=generate_id(), + slug=generate_id(), + ) + + def test_resource_type(self): + """Test full resource type view""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_resource_type_single(self): + """Test single resource type""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.source.slug, + "resource_type": "ServiceProviderConfig", + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_resource_type_single_404(self): + """Test single resource type (404""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.source.slug, + "resource_type": "foo", + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 404) diff --git a/authentik/sources/scim/tests/test_schemas.py b/authentik/sources/scim/tests/test_schemas.py new file mode 100644 index 0000000000..55b27a779a --- /dev/null +++ b/authentik/sources/scim/tests/test_schemas.py @@ -0,0 +1,55 @@ +"""Test SCIM Schema""" + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.lib.generators import generate_id +from authentik.sources.scim.models import SCIMSource + + +class TestSCIMSchemas(APITestCase): + """Test SCIM Schema view""" + + def setUp(self) -> None: + self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) + + def test_schema(self): + """Test full schema view""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_schema_single(self): + """Test single schema""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + "schema_uri": "urn:ietf:params:scim:schemas:core:2.0:Meta", + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_schema_single_404(self): + """Test single schema (404""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.source.slug, + "schema_uri": "foo", + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 404) diff --git a/authentik/sources/scim/tests/test_service_provider_config.py b/authentik/sources/scim/tests/test_service_provider_config.py new file mode 100644 index 0000000000..f932baee23 --- /dev/null +++ b/authentik/sources/scim/tests/test_service_provider_config.py @@ -0,0 +1,30 @@ +"""Test SCIM ServiceProviderConfig""" + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.lib.generators import generate_id +from authentik.sources.scim.models import SCIMSource + + +class TestSCIMServiceProviderConfig(APITestCase): + """Test SCIM ServiceProviderConfig view""" + + def setUp(self) -> None: + self.source = SCIMSource.objects.create( + name=generate_id(), + slug=generate_id(), + ) + + def test_config(self): + """Test full config view""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-service-provider-config", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) diff --git a/authentik/sources/scim/tests/test_signals.py b/authentik/sources/scim/tests/test_signals.py new file mode 100644 index 0000000000..f63e94d7cb --- /dev/null +++ b/authentik/sources/scim/tests/test_signals.py @@ -0,0 +1,27 @@ +"""Test SCIM Source creation""" + +from rest_framework.test import APITestCase + +from authentik.core.models import Token, User +from authentik.lib.generators import generate_id +from authentik.sources.scim.models import SCIMSource + + +class TestSCIMSignals(APITestCase): + """Test SCIM Signals view""" + + def setUp(self) -> None: + self.uid = generate_id() + + def test_create(self) -> None: + source = SCIMSource.objects.create(name=self.uid, slug=self.uid) + self.assertIsNotNone(source.token) + self.assertIsNotNone(source.token.user) + + def test_delete(self): + self.test_create() + source = SCIMSource.objects.filter(slug=self.uid).first() + identifier = source.service_account_identifier + source.delete() + self.assertFalse(User.objects.filter(username=identifier).exists()) + self.assertFalse(Token.objects.filter(identifier=identifier).exists()) diff --git a/authentik/sources/scim/tests/test_users.py b/authentik/sources/scim/tests/test_users.py new file mode 100644 index 0000000000..18ad33fc46 --- /dev/null +++ b/authentik/sources/scim/tests/test_users.py @@ -0,0 +1,89 @@ +"""Test SCIM User""" + +from json import dumps +from uuid import uuid4 + +from django.urls import reverse +from rest_framework.test import APITestCase + +from authentik.core.tests.utils import create_test_user +from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id +from authentik.providers.scim.clients.schema import User as SCIMUserSchema +from authentik.sources.scim.models import SCIMSource, SCIMSourceUser +from authentik.sources.scim.views.v2.base import SCIM_CONTENT_TYPE + + +class TestSCIMUsers(APITestCase): + """Test SCIM User view""" + + def setUp(self) -> None: + self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) + + def test_user_list(self): + """Test full user list""" + response = self.client.get( + reverse( + "authentik_sources_scim:v2-users", + kwargs={ + "source_slug": self.source.slug, + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + + def test_user_list_single(self): + """Test full user list (single user)""" + user = create_test_user() + SCIMSourceUser.objects.create( + source=self.source, + user=user, + id=str(uuid4()), + ) + response = self.client.get( + reverse( + "authentik_sources_scim:v2-users", + kwargs={ + "source_slug": self.source.slug, + "user_id": str(user.uuid), + }, + ), + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 200) + SCIMUserSchema.model_validate_json(response.content, strict=True) + + def test_user_create(self): + """Test user create""" + user = create_test_user() + ext_id = generate_id() + response = self.client.post( + reverse( + "authentik_sources_scim:v2-users", + kwargs={ + "source_slug": self.source.slug, + }, + ), + data=dumps( + { + "userName": generate_id(), + "externalId": ext_id, + "emails": [ + { + "primary": True, + "value": user.email, + } + ], + } + ), + content_type=SCIM_CONTENT_TYPE, + HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", + ) + self.assertEqual(response.status_code, 201) + self.assertTrue(SCIMSourceUser.objects.filter(source=self.source, id=ext_id).exists()) + self.assertTrue( + Event.objects.filter( + action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username + ).exists() + ) diff --git a/authentik/sources/scim/urls.py b/authentik/sources/scim/urls.py new file mode 100644 index 0000000000..84776bcbcb --- /dev/null +++ b/authentik/sources/scim/urls.py @@ -0,0 +1,74 @@ +"""SCIM URLs""" + +from django.urls import path + +from authentik.sources.scim.api.groups import SCIMSourceGroupViewSet +from authentik.sources.scim.api.sources import SCIMSourceViewSet +from authentik.sources.scim.api.users import SCIMSourceUserViewSet +from authentik.sources.scim.views.v2 import ( + base, + groups, + resource_types, + schemas, + service_provider_config, + users, +) + +urlpatterns = [ + path( + "/v2", + base.SCIMRootView.as_view(), + name="v2-root", + ), + path( + "/v2/Users", + users.UsersView.as_view(), + name="v2-users", + ), + path( + "/v2/Users/", + users.UsersView.as_view(), + name="v2-users", + ), + path( + "/v2/Groups", + groups.GroupsView.as_view(), + name="v2-groups", + ), + path( + "/v2/Groups/", + groups.GroupsView.as_view(), + name="v2-groups", + ), + path( + "/v2/Schemas", + schemas.SchemaView.as_view(), + name="v2-schema", + ), + path( + "/v2/Schemas/", + schemas.SchemaView.as_view(), + name="v2-schema", + ), + path( + "/v2/ServiceProviderConfig", + service_provider_config.ServiceProviderConfigView.as_view(), + name="v2-service-provider-config", + ), + path( + "/v2/ResourceTypes", + resource_types.ResourceTypesView.as_view(), + name="v2-resource-types", + ), + path( + "/v2/ResourceTypes/", + resource_types.ResourceTypesView.as_view(), + name="v2-resource-types", + ), +] + +api_urlpatterns = [ + ("sources/scim", SCIMSourceViewSet), + ("sources/scim_users", SCIMSourceUserViewSet), + ("sources/scim_groups", SCIMSourceGroupViewSet), +] diff --git a/authentik/sources/scim/views/__init__.py b/authentik/sources/scim/views/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/views/v2/__init__.py b/authentik/sources/scim/views/v2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/sources/scim/views/v2/auth.py b/authentik/sources/scim/views/v2/auth.py new file mode 100644 index 0000000000..26394ffde4 --- /dev/null +++ b/authentik/sources/scim/views/v2/auth.py @@ -0,0 +1,55 @@ +"""SCIM Token auth""" + +from base64 import b64decode +from typing import Any + +from django.conf import settings +from rest_framework.authentication import BaseAuthentication, get_authorization_header +from rest_framework.request import Request +from rest_framework.views import APIView + +from authentik.core.models import Token, TokenIntents, User +from authentik.sources.scim.models import SCIMSource + + +class SCIMTokenAuth(BaseAuthentication): + """SCIM Token auth""" + + def __init__(self, view: APIView) -> None: + super().__init__() + self.view = view + + def legacy(self, key: str, source_slug: str) -> Token | None: # pragma: no cover + """Legacy HTTP-Basic auth for testing""" + if not settings.TEST and not settings.DEBUG: + return None + _username, _, password = b64decode(key.encode()).decode().partition(":") + token = self.check_token(password, source_slug) + if token: + return (token.user, token) + return None + + def check_token(self, key: str, source_slug: str) -> Token | None: + """Check that a token exists, is not expired, and is assigned to the correct source""" + token = Token.filter_not_expired(key=key, intent=TokenIntents.INTENT_API).first() + if not token: + return None + source: SCIMSource = token.scimsource_set.first() + if not source: + return None + if source.slug != source_slug: + return None + self.view.source = source + return token + + def authenticate(self, request: Request) -> tuple[User, Any] | None: + kwargs = request._request.resolver_match.kwargs + source_slug = kwargs.get("source_slug", None) + auth = get_authorization_header(request).decode() + auth_type, _, key = auth.partition(" ") + if auth_type != "Bearer": + return self.legacy(key, source_slug) + token = self.check_token(key, source_slug) + if not token: + return None + return (token.user, token) diff --git a/authentik/sources/scim/views/v2/base.py b/authentik/sources/scim/views/v2/base.py new file mode 100644 index 0000000000..c32c8077fd --- /dev/null +++ b/authentik/sources/scim/views/v2/base.py @@ -0,0 +1,120 @@ +"""SCIM Utils""" + +from typing import Any +from urllib.parse import urlparse + +from django.conf import settings +from django.core.paginator import Page, Paginator +from django.db.models import Model, Q, QuerySet +from django.http import HttpRequest +from django.urls import resolve +from rest_framework.parsers import JSONParser +from rest_framework.permissions import IsAuthenticated +from rest_framework.renderers import JSONRenderer +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.views import APIView +from scim2_filter_parser.transpilers.django_q_object import get_query +from structlog import BoundLogger +from structlog.stdlib import get_logger + +from authentik.core.models import Group, User +from authentik.sources.scim.models import SCIMSource +from authentik.sources.scim.views.v2.auth import SCIMTokenAuth + +SCIM_CONTENT_TYPE = "application/scim+json" + + +class SCIMParser(JSONParser): + """SCIM clients use a custom content type""" + + media_type = SCIM_CONTENT_TYPE + + +class SCIMRenderer(JSONRenderer): + """SCIM clients also expect a custom content type""" + + media_type = SCIM_CONTENT_TYPE + + +class SCIMView(APIView): + """Base class for SCIM Views""" + + source: SCIMSource + logger: BoundLogger + + permission_classes = [IsAuthenticated] + parser_classes = [SCIMParser] + renderer_classes = [SCIMRenderer] + + model: type[Model] + + def setup(self, request: HttpRequest, *args: Any, **kwargs: Any) -> None: + self.logger = get_logger().bind() + return super().setup(request, *args, **kwargs) + + def get_authenticators(self): + return [SCIMTokenAuth(self)] + + def patch_resolve_value(self, raw_value: dict) -> User | Group | None: + """Attempt to resolve a raw `value` attribute of a patch operation into + a database model""" + model = User + query = {} + if "$ref" in raw_value: + url = urlparse(raw_value["$ref"]) + if match := resolve(url.path): + if match.url_name == "v2-users": + model = User + query = {"pk": int(match.kwargs["user_id"])} + elif "type" in raw_value: + match raw_value["type"]: + case "User": + model = User + query = {"pk": int(raw_value["value"])} + case "Group": + model = Group + else: + return None + return model.objects.filter(**query).first() + + def filter_parse(self, request: Request): + """Parse the path of a Patch Operation""" + path = request.query_params.get("filter") + if not path: + return Q() + attr_map = {} + if self.model == User: + attr_map = { + ("userName", None, None): "user__username", + ("active", None, None): "user__is_active", + ("name", "familyName", None): "attributes__familyName", + } + elif self.model == Group: + attr_map = { + ("displayName", None, None): "group__name", + ("members", None, None): "group__users", + } + return get_query( + path, + attr_map, + ) + + def paginate_query(self, query: QuerySet) -> Page: + per_page = 50 + start_index = 1 + try: + per_page = int(settings.REST_FRAMEWORK["PAGE_SIZE"]) + start_index = int(self.request.query_params.get("startIndex", 1)) + except ValueError: + pass + paginator = Paginator(query, per_page=per_page) + page = paginator.page(int(max(start_index / per_page, 1))) + return page + + +class SCIMRootView(SCIMView): + """Root SCIM View""" + + def dispatch(self, request: Request, *args, **kwargs) -> Response: + return Response({"message": "Use this base-URL with a SCIM-compatible system."}) diff --git a/authentik/sources/scim/views/v2/groups.py b/authentik/sources/scim/views/v2/groups.py new file mode 100644 index 0000000000..ff27efc162 --- /dev/null +++ b/authentik/sources/scim/views/v2/groups.py @@ -0,0 +1,142 @@ +"""SCIM Group Views""" + +from uuid import uuid4 + +from django.db.models import Q +from django.db.transaction import atomic +from django.http import Http404, QueryDict +from django.urls import reverse +from pydantic import ValidationError as PydanticValidationError +from pydanticscim.group import GroupMember +from rest_framework.exceptions import ValidationError +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.core.models import Group, User +from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA +from authentik.providers.scim.clients.schema import Group as SCIMGroupModel +from authentik.sources.scim.models import SCIMSourceGroup +from authentik.sources.scim.views.v2.base import SCIMView + + +class GroupsView(SCIMView): + """SCIM Group view""" + + model = Group + + def group_to_scim(self, scim_group: SCIMSourceGroup) -> dict: + """Convert Group to SCIM data""" + payload = SCIMGroupModel( + schemas=[SCIM_USER_SCHEMA], + id=str(scim_group.group.pk), + externalId=scim_group.id, + displayName=scim_group.group.name, + members=[], + meta={ + "resourceType": "Group", + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-groups", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "group_id": str(scim_group.group.pk), + }, + ) + ), + }, + ) + for member in scim_group.group.users.order_by("pk"): + member: User + payload.members.append(GroupMember(value=str(member.uuid))) + return payload.model_dump(mode="json", exclude_unset=True) + + def get(self, request: Request, group_id: str | None = None, **kwargs) -> Response: + """List Group handler""" + base_query = SCIMSourceGroup.objects.select_related("group").prefetch_related( + "group__users" + ) + if group_id: + connection = base_query.filter(source=self.source, group__group_uuid=group_id).first() + if not connection: + raise Http404 + return Response(self.group_to_scim(connection)) + connections = ( + base_query.filter(source=self.source).order_by("pk").filter(self.filter_parse(request)) + ) + page = self.paginate_query(connections) + return Response( + { + "totalResults": page.paginator.count, + "itemsPerPage": page.paginator.per_page, + "startIndex": page.start_index(), + "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], + "Resources": [self.group_to_scim(connection) for connection in page], + } + ) + + @atomic + def update_group(self, connection: SCIMSourceGroup | None, data: QueryDict): + """Partial update a group""" + group = connection.group if connection else Group() + if _group := Group.objects.filter(name=data.get("displayName")).first(): + group = _group + if "displayName" in data: + group.name = data.get("displayName") + if group.name == "": + raise ValidationError("Invalid group") + group.save() + if "members" in data: + query = Q() + for _member in data.get("members", []): + try: + member = GroupMember.model_validate(_member) + except PydanticValidationError as exc: + self.logger.warning("Invalid group member", exc=exc) + continue + query |= Q(uuid=member.value) + group.users.set(User.objects.filter(query)) + if not connection: + connection, _ = SCIMSourceGroup.objects.get_or_create( + source=self.source, + group=group, + attributes=data, + id=data.get("externalId") or str(uuid4()), + ) + else: + connection.attributes = data + connection.save() + return connection + + def post(self, request: Request, **kwargs) -> Response: + """Create group handler""" + connection = SCIMSourceGroup.objects.filter( + source=self.source, + group__group_uuid=request.data.get("id"), + ).first() + if connection: + self.logger.debug("Found existing group") + return Response(status=409) + connection = self.update_group(None, request.data) + return Response(self.group_to_scim(connection), status=201) + + def put(self, request: Request, group_id: str, **kwargs) -> Response: + """Update group handler""" + connection = SCIMSourceGroup.objects.filter( + source=self.source, group__group_uuid=group_id + ).first() + if not connection: + raise Http404 + connection = self.update_group(connection, request.data) + return Response(self.group_to_scim(connection), status=200) + + @atomic + def delete(self, request: Request, group_id: str, **kwargs) -> Response: + """Delete group handler""" + connection = SCIMSourceGroup.objects.filter( + source=self.source, group__group_uuid=group_id + ).first() + if not connection: + raise Http404 + connection.group.delete() + connection.delete() + return Response(status=204) diff --git a/authentik/sources/scim/views/v2/resource_types.py b/authentik/sources/scim/views/v2/resource_types.py new file mode 100644 index 0000000000..cecd5d225f --- /dev/null +++ b/authentik/sources/scim/views/v2/resource_types.py @@ -0,0 +1,150 @@ +"""SCIM Meta views""" + +from django.http import Http404 +from django.urls import reverse +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.sources.scim.views.v2.base import SCIMView + + +class ResourceTypesView(SCIMView): + """https://ldapwiki.com/wiki/SCIM%20ResourceTypes%20endpoint""" + + def get_resource_types(self): + """List all resource types""" + return [ + { + "id": "ServiceProviderConfig", + "name": "ServiceProviderConfig", + "description": "the service providers configuration", + "endpoint": "/ServiceProviderConfig", + "schema": "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig", + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + ], + "meta": { + "resourceType": "ResourceType", + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "resource_type": "ServiceProviderConfig", + }, + ) + ), + }, + }, + { + "id": "ResourceType", + "name": "ResourceType", + "description": "ResourceType", + "endpoint": "/ResourceTypes", + "schema": "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + ], + "meta": { + "resourceType": "ResourceType", + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "resource_type": "ResourceType", + }, + ) + ), + }, + }, + { + "id": "Schema", + "name": "Schema", + "description": "Schema endpoint description", + "endpoint": "/Schemas", + "schema": "urn:ietf:params:scim:schemas:core:2.0:Schema", + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + ], + "meta": { + "resourceType": "ResourceType", + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "resource_type": "Schema", + }, + ) + ), + }, + }, + { + "id": "User", + "name": "User", + "endpoint": "/Users", + "description": "https://tools.ietf.org/html/rfc7643#section-8.7.1", + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"], + "schema": "urn:ietf:params:scim:schemas:core:2.0:User", + "schemaExtensions": [ + { + "schema": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", + "required": True, + } + ], + "meta": { + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "resource_type": "User", + }, + ) + ), + "resourceType": "ResourceType", + }, + }, + { + "id": "Group", + "name": "Group", + "description": "Group", + "endpoint": "/Groups", + "schema": "urn:ietf:params:scim:schemas:core:2.0:Group", + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:ResourceType", + ], + "meta": { + "resourceType": "ResourceType", + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-resource-types", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "resource_type": "Group", + }, + ) + ), + }, + }, + ] + + # pylint: disable=unused-argument + def get(self, request: Request, source_slug: str, resource_type: str | None = None) -> Response: + """Get resource types as SCIM response""" + resource_types = self.get_resource_types() + if resource_type: + resource = [x for x in resource_types if x.get("id") == resource_type] + if resource: + return Response(resource[0]) + raise Http404 + return Response( + { + "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], + "totalResults": len(resource_types), + "itemsPerPage": len(resource_types), + "startIndex": 1, + "Resources": resource_types, + } + ) diff --git a/authentik/sources/scim/views/v2/schemas.py b/authentik/sources/scim/views/v2/schemas.py new file mode 100644 index 0000000000..64d3a8bb5e --- /dev/null +++ b/authentik/sources/scim/views/v2/schemas.py @@ -0,0 +1,52 @@ +"""Schema Views""" + +from json import loads + +from django.http import Http404 +from django.urls import reverse +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.sources.scim.views.v2.base import SCIMView + +with open("authentik/sources/scim/schemas/schema.json", encoding="utf-8") as SCHEMA_FILE: + _raw_schemas = loads(SCHEMA_FILE.read()) + + +class SchemaView(SCIMView): + """https://ldapwiki.com/wiki/SCIM%20Schemas%20Attribute""" + + def get_schemas(self): + """List of all schemas""" + schemas = [] + for raw_schema in _raw_schemas: + raw_schema["meta"]["location"] = self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-schema", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "schema_uri": raw_schema["id"], + }, + ) + ) + schemas.append(raw_schema) + return schemas + + # pylint: disable=unused-argument + def get(self, request: Request, source_slug: str, schema_uri: str | None = None) -> Response: + """Get schemas as SCIM response""" + schemas = self.get_schemas() + if schema_uri: + schema = [x for x in schemas if x.get("id") == schema_uri] + if schema: + return Response(schema[0]) + raise Http404 + return Response( + { + "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], + "totalResults": len(schemas), + "itemsPerPage": len(schemas), + "startIndex": 1, + "Resources": schemas, + } + ) diff --git a/authentik/sources/scim/views/v2/service_provider_config.py b/authentik/sources/scim/views/v2/service_provider_config.py new file mode 100644 index 0000000000..19c329177d --- /dev/null +++ b/authentik/sources/scim/views/v2/service_provider_config.py @@ -0,0 +1,46 @@ +"""SCIM Meta views""" + +from django.conf import settings +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.sources.scim.views.v2.base import SCIMView + + +class ServiceProviderConfigView(SCIMView): + """ServiceProviderConfig, https://ldapwiki.com/wiki/SCIM%20ServiceProviderConfig%20endpoint""" + + # pylint: disable=unused-argument + def get(self, request: Request, source_slug: str) -> Response: + """Get ServiceProviderConfig""" + auth_schemas = [ + { + "type": "oauthbearertoken", + "name": "OAuth Bearer Token", + "description": "Authentication scheme using the OAuth Bearer Token Standard", + "primary": True, + }, + ] + if settings.TEST or settings.DEBUG: + auth_schemas.append( + { + "type": "httpbasic", + "name": "HTTP Basic", + "description": "Authentication scheme using HTTP Basic authorization", + }, + ) + return Response( + { + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"], + "authenticationSchemes": auth_schemas, + "patch": {"supported": False}, + "bulk": {"supported": False, "maxOperations": 0, "maxPayloadSize": 0}, + "filter": { + "supported": True, + "maxResults": int(settings.REST_FRAMEWORK["PAGE_SIZE"]), + }, + "changePassword": {"supported": False}, + "sort": {"supported": False}, + "etag": {"supported": False}, + } + ) diff --git a/authentik/sources/scim/views/v2/users.py b/authentik/sources/scim/views/v2/users.py new file mode 100644 index 0000000000..84dd555f29 --- /dev/null +++ b/authentik/sources/scim/views/v2/users.py @@ -0,0 +1,155 @@ +"""SCIM User Views""" + +from uuid import uuid4 + +from django.db.transaction import atomic +from django.http import Http404, QueryDict +from django.urls import reverse +from pydanticscim.user import Email, EmailKind, Name +from rest_framework.exceptions import ValidationError +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.core.models import User +from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA +from authentik.providers.scim.clients.schema import User as SCIMUserModel +from authentik.sources.scim.models import SCIMSourceUser +from authentik.sources.scim.views.v2.base import SCIMView + + +class UsersView(SCIMView): + """SCIM User view""" + + model = User + + def get_email(self, data: list[dict]) -> str: + """Wrapper to get primary email or first email""" + for email in data: + if email.get("primary", False): + return email.get("value") + if len(data) < 1: + return "" + return data[0].get("value") + + def user_to_scim(self, scim_user: SCIMSourceUser) -> dict: + """Convert User to SCIM data""" + payload = SCIMUserModel( + schemas=[SCIM_USER_SCHEMA], + id=str(scim_user.user.uuid), + externalId=scim_user.id, + userName=scim_user.user.username, + name=Name( + formatted=scim_user.user.name, + ), + displayName=scim_user.user.name, + active=scim_user.user.is_active, + emails=( + [Email(value=scim_user.user.email, type=EmailKind.work, primary=True)] + if scim_user.user.email + else [] + ), + meta={ + "resourceType": "User", + "created": scim_user.user.date_joined, + # TODO: use events to find last edit? + "lastModified": scim_user.user.date_joined, + "location": self.request.build_absolute_uri( + reverse( + "authentik_sources_scim:v2-users", + kwargs={ + "source_slug": self.kwargs["source_slug"], + "user_id": str(scim_user.user.uuid), + }, + ) + ), + }, + ) + final_payload = payload.model_dump(mode="json", exclude_unset=True) + final_payload.update(scim_user.attributes) + return final_payload + + def get(self, request: Request, user_id: str | None = None, **kwargs) -> Response: + """List User handler""" + if user_id: + connection = ( + SCIMSourceUser.objects.filter(source=self.source, user__uuid=user_id) + .select_related("user") + .first() + ) + if not connection: + raise Http404 + return Response(self.user_to_scim(connection)) + connections = ( + SCIMSourceUser.objects.filter(source=self.source).select_related("user").order_by("pk") + ) + connections = connections.filter(self.filter_parse(request)) + page = self.paginate_query(connections) + return Response( + { + "totalResults": page.paginator.count, + "itemsPerPage": page.paginator.per_page, + "startIndex": page.start_index(), + "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], + "Resources": [self.user_to_scim(connection) for connection in page], + } + ) + + @atomic + def update_user(self, connection: SCIMSourceUser | None, data: QueryDict): + """Partial update a user""" + user = connection.user if connection else User() + if _user := User.objects.filter(username=data.get("userName")).first(): + user = _user + user.path = self.source.get_user_path() + if "userName" in data: + user.username = data.get("userName") + if "name" in data: + user.name = data.get("name", {}).get("formatted", data.get("displayName")) + if "emails" in data: + user.email = self.get_email(data.get("emails")) + if "active" in data: + user.is_active = data.get("active") + if user.username == "": + raise ValidationError("Invalid user") + user.save() + if not connection: + connection, _ = SCIMSourceUser.objects.get_or_create( + source=self.source, + user=user, + attributes=data, + id=data.get("externalId") or str(uuid4()), + ) + else: + connection.attributes = data + connection.save() + return connection + + def post(self, request: Request, **kwargs) -> Response: + """Create user handler""" + connection = SCIMSourceUser.objects.filter( + source=self.source, + user__uuid=request.data.get("id"), + ).first() + if connection: + self.logger.debug("Found existing user") + return Response(status=409) + connection = self.update_user(None, request.data) + return Response(self.user_to_scim(connection), status=201) + + def put(self, request: Request, user_id: str, **kwargs) -> Response: + """Update user handler""" + connection = SCIMSourceUser.objects.filter(source=self.source, user__uuid=user_id).first() + if not connection: + raise Http404 + self.update_user(connection, request.data) + return Response(self.user_to_scim(connection), status=200) + + @atomic + def delete(self, request: Request, user_id: str, **kwargs) -> Response: + """Delete user handler""" + connection = SCIMSourceUser.objects.filter(source=self.source, user__uuid=user_id).first() + if not connection: + raise Http404 + connection.user.delete() + connection.delete() + return Response(status=204) diff --git a/authentik/stages/authenticator/__init__.py b/authentik/stages/authenticator/__init__.py index a6d3087e8a..9601b13af3 100644 --- a/authentik/stages/authenticator/__init__.py +++ b/authentik/stages/authenticator/__init__.py @@ -1,4 +1,5 @@ """Authenticator devices helpers""" + from django.db import transaction @@ -120,7 +121,8 @@ def device_classes(): """ Returns an iterable of all loaded device models. """ - from django.apps import apps # isort: skip + from django.apps import apps + from authentik.stages.authenticator.models import Device for config in apps.get_app_configs(): diff --git a/authentik/stages/authenticator/apps.py b/authentik/stages/authenticator/apps.py index 5fb866e2db..dd33812bbf 100644 --- a/authentik/stages/authenticator/apps.py +++ b/authentik/stages/authenticator/apps.py @@ -1,4 +1,5 @@ """Authenticator""" + from django.apps import AppConfig diff --git a/authentik/stages/authenticator/models.py b/authentik/stages/authenticator/models.py index 0404a0668c..f7a6125c57 100644 --- a/authentik/stages/authenticator/models.py +++ b/authentik/stages/authenticator/models.py @@ -1,4 +1,5 @@ """Base authenticator models""" + from datetime import timedelta from django.apps import apps @@ -95,14 +96,14 @@ class Device(models.Model): except ObjectDoesNotExist: user = None - return "{0} ({1})".format(self.name, user) + return f"{self.name} ({user})" @property def persistent_id(self): """ A stable device identifier for forms and APIs. """ - return "{0}/{1}".format(self.model_label(), self.id) + return f"{self.model_label()}/{self.id}" @classmethod def model_label(cls): @@ -112,7 +113,7 @@ class Device(models.Model): This is just the standard "." form. """ - return "{0}.{1}".format(cls._meta.app_label, cls._meta.model_name) + return f"{cls._meta.app_label}.{cls._meta.model_name}" @classmethod def from_persistent_id(cls, persistent_id, for_verify=False): @@ -313,6 +314,9 @@ class ThrottlingMixin(models.Model): default=0, help_text="Number of successive failed attempts." ) + class Meta: + abstract = True + def verify_is_allowed(self): """ If verification is allowed, returns ``(True, None)``. @@ -396,6 +400,3 @@ class ThrottlingMixin(models.Model): """ raise NotImplementedError() - - class Meta: - abstract = True diff --git a/authentik/stages/authenticator/oath.py b/authentik/stages/authenticator/oath.py index 443079067f..9ba4a5604b 100644 --- a/authentik/stages/authenticator/oath.py +++ b/authentik/stages/authenticator/oath.py @@ -1,11 +1,11 @@ """OATH helpers""" + import hmac from hashlib import sha1 from struct import pack from time import time -# pylint: disable=invalid-name def hotp(key: bytes, counter: int, digits=6) -> int: """ Implementation of the HOTP algorithm from `RFC 4226 @@ -128,7 +128,6 @@ class TOTP: 359152 """ - # pylint: disable=too-many-arguments def __init__(self, key: bytes, step=30, t0=0, digits=6, drift=0): self.key = key self.step = step diff --git a/authentik/stages/authenticator/tests.py b/authentik/stages/authenticator/tests.py index 9a619828a9..5e17eb0360 100644 --- a/authentik/stages/authenticator/tests.py +++ b/authentik/stages/authenticator/tests.py @@ -1,4 +1,5 @@ """Base authenticator tests""" + from datetime import timedelta from threading import Thread diff --git a/authentik/stages/authenticator/util.py b/authentik/stages/authenticator/util.py index 26b9dc64df..e92f1a168e 100644 --- a/authentik/stages/authenticator/util.py +++ b/authentik/stages/authenticator/util.py @@ -1,4 +1,5 @@ """Authenticator utils""" + import random import string from binascii import unhexlify @@ -42,10 +43,10 @@ def hex_validator(length=0): unhexlify(value) except Exception: - raise ValidationError("{0} is not valid hex-encoded data.".format(value)) + raise ValidationError(f"{value} is not valid hex-encoded data.") from None if (length > 0) and (len(value) != length * 2): - raise ValidationError("{0} does not represent exactly {1} bytes.".format(value, length)) + raise ValidationError(f"{value} does not represent exactly {length} bytes.") return _validator diff --git a/authentik/stages/authenticator_duo/api.py b/authentik/stages/authenticator_duo/api.py index 3d038de31a..90825938ec 100644 --- a/authentik/stages/authenticator_duo/api.py +++ b/authentik/stages/authenticator_duo/api.py @@ -1,4 +1,5 @@ """AuthenticatorDuoStage API Views""" + from django.http import Http404 from django_filters.rest_framework.backends import DjangoFilterBackend from drf_spectacular.types import OpenApiTypes @@ -16,9 +17,9 @@ from rest_framework.viewsets import GenericViewSet, ModelViewSet from structlog.stdlib import get_logger from authentik.api.authorization import OwnerFilter, OwnerPermissions -from authentik.api.decorators import permission_required from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer +from authentik.rbac.decorators import permission_required from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice from authentik.stages.authenticator_duo.stage import SESSION_KEY_DUO_ENROLL from authentik.stages.authenticator_duo.tasks import duo_import_devices diff --git a/authentik/stages/authenticator_duo/apps.py b/authentik/stages/authenticator_duo/apps.py index 0e0e5d9271..3e9ceb3b1c 100644 --- a/authentik/stages/authenticator_duo/apps.py +++ b/authentik/stages/authenticator_duo/apps.py @@ -10,7 +10,3 @@ class AuthentikStageAuthenticatorDuoConfig(ManagedAppConfig): label = "authentik_stages_authenticator_duo" verbose_name = "authentik Stages.Authenticator.Duo" default = True - - def reconcile_global_load_tasks(self): - """Load tasks""" - self.import_module("authentik.stages.authenticator_duo.tasks") diff --git a/authentik/stages/authenticator_duo/models.py b/authentik/stages/authenticator_duo/models.py index d1dce81f09..f9726021d4 100644 --- a/authentik/stages/authenticator_duo/models.py +++ b/authentik/stages/authenticator_duo/models.py @@ -1,5 +1,4 @@ """Duo stage""" -from typing import Optional from django.contrib.auth import get_user_model from django.db import models @@ -34,7 +33,7 @@ class AuthenticatorDuoStage(ConfigurableStage, FriendlyNamedStage, Stage): return AuthenticatorDuoStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_duo.stage import AuthenticatorDuoStageView return AuthenticatorDuoStageView @@ -64,7 +63,7 @@ class AuthenticatorDuoStage(ConfigurableStage, FriendlyNamedStage, Stage): def component(self) -> str: return "ak-stage-authenticator-duo-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.friendly_name or str(self._meta.verbose_name), @@ -97,7 +96,7 @@ class DuoDevice(SerializerModel, Device): return DuoDeviceSerializer def __str__(self): - return str(self.name) or str(self.user) + return str(self.name) or str(self.user_id) class Meta: verbose_name = _("Duo Device") diff --git a/authentik/stages/authenticator_duo/stage.py b/authentik/stages/authenticator_duo/stage.py index df44a7259b..a19880fe38 100644 --- a/authentik/stages/authenticator_duo/stage.py +++ b/authentik/stages/authenticator_duo/stage.py @@ -1,4 +1,5 @@ """Duo stage""" + from django.http import HttpResponse from django.utils.timezone import now from rest_framework.fields import CharField diff --git a/authentik/stages/authenticator_duo/tasks.py b/authentik/stages/authenticator_duo/tasks.py index 338f6d8f0a..b97c1e39ee 100644 --- a/authentik/stages/authenticator_duo/tasks.py +++ b/authentik/stages/authenticator_duo/tasks.py @@ -1,4 +1,5 @@ """duo tasks""" + from structlog.stdlib import get_logger from authentik.core.models import User diff --git a/authentik/stages/authenticator_duo/tests.py b/authentik/stages/authenticator_duo/tests.py index a11bbd5847..3262589f69 100644 --- a/authentik/stages/authenticator_duo/tests.py +++ b/authentik/stages/authenticator_duo/tests.py @@ -1,4 +1,5 @@ """Test duo stage""" + from unittest.mock import MagicMock, patch from uuid import uuid4 diff --git a/authentik/stages/authenticator_duo/urls.py b/authentik/stages/authenticator_duo/urls.py index 8a41247415..dd7e083c7f 100644 --- a/authentik/stages/authenticator_duo/urls.py +++ b/authentik/stages/authenticator_duo/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.authenticator_duo.api import ( AuthenticatorDuoStageViewSet, DuoAdminDeviceViewSet, diff --git a/authentik/stages/authenticator_sms/api.py b/authentik/stages/authenticator_sms/api.py index bfa0b323e9..b8784ce210 100644 --- a/authentik/stages/authenticator_sms/api.py +++ b/authentik/stages/authenticator_sms/api.py @@ -1,4 +1,5 @@ """AuthenticatorSMSStage API Views""" + from django_filters.rest_framework.backends import DjangoFilterBackend from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter diff --git a/authentik/stages/authenticator_sms/apps.py b/authentik/stages/authenticator_sms/apps.py index 97d9d6ae0b..d5d6f749ee 100644 --- a/authentik/stages/authenticator_sms/apps.py +++ b/authentik/stages/authenticator_sms/apps.py @@ -1,4 +1,5 @@ """SMS""" + from django.apps import AppConfig diff --git a/authentik/stages/authenticator_sms/models.py b/authentik/stages/authenticator_sms/models.py index 042cbd6984..82ad6f61ee 100644 --- a/authentik/stages/authenticator_sms/models.py +++ b/authentik/stages/authenticator_sms/models.py @@ -1,9 +1,10 @@ """SMS Authenticator models""" + from hashlib import sha256 -from typing import Optional from django.contrib.auth import get_user_model from django.db import models +from django.http import HttpResponseBadRequest from django.utils.translation import gettext_lazy as _ from django.views import View from requests.exceptions import RequestException @@ -78,7 +79,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage): def get_message(self, token: str) -> str: """Get SMS message""" - return _("Use this code to authenticate in authentik: %(token)s" % {"token": token}) + return _("Use this code to authenticate in authentik: {token}".format_map({"token": token})) def send_twilio(self, token: str, device: "SMSDevice"): """send sms via twilio provider""" @@ -91,7 +92,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage): LOGGER.debug("Sent SMS", to=device, message=message.sid) except TwilioRestException as exc: LOGGER.warning("Error sending token by Twilio SMS", exc=exc, msg=exc.msg) - raise ValidationError(exc.msg) + raise ValidationError(exc.msg) from None def send_generic(self, token: str, device: "SMSDevice"): """Send SMS via outside API""" @@ -145,8 +146,8 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage): status_code=response.status_code, body=response.text, ).set_user(device.user).save() - if response.status_code >= 400: - raise ValidationError(response.text) + if response.status_code >= HttpResponseBadRequest.status_code: + raise ValidationError(response.text) from None raise @property @@ -156,7 +157,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage): return AuthenticatorSMSStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_sms.stage import AuthenticatorSMSStageView return AuthenticatorSMSStageView @@ -165,7 +166,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage): def component(self) -> str: return "ak-stage-authenticator-sms-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.friendly_name or str(self._meta.verbose_name), @@ -220,7 +221,7 @@ class SMSDevice(SerializerModel, SideChannelDevice): return valid def __str__(self): - return str(self.name) or str(self.user) + return str(self.name) or str(self.user_id) class Meta: verbose_name = _("SMS Device") diff --git a/authentik/stages/authenticator_sms/stage.py b/authentik/stages/authenticator_sms/stage.py index e2c6610896..159e5ede5a 100644 --- a/authentik/stages/authenticator_sms/stage.py +++ b/authentik/stages/authenticator_sms/stage.py @@ -1,5 +1,4 @@ """SMS Setup stage""" -from typing import Optional from django.db.models import Q from django.http import HttpRequest, HttpResponse @@ -75,7 +74,7 @@ class AuthenticatorSMSStageView(ChallengeStageView): device: SMSDevice = self.request.session[SESSION_KEY_SMS_DEVICE] stage.send(device.token, device) - def _has_phone_number(self) -> Optional[str]: + def _has_phone_number(self) -> str | None: context = self.executor.plan.context if PLAN_CONTEXT_PHONE in context.get(PLAN_CONTEXT_PROMPT, {}): self.logger.debug("got phone number from plan context") diff --git a/authentik/stages/authenticator_sms/tests.py b/authentik/stages/authenticator_sms/tests.py index 1ab16aa561..b3d5ec29c2 100644 --- a/authentik/stages/authenticator_sms/tests.py +++ b/authentik/stages/authenticator_sms/tests.py @@ -1,4 +1,5 @@ """Test SMS API""" + from unittest.mock import MagicMock, patch from urllib.parse import parse_qsl diff --git a/authentik/stages/authenticator_sms/urls.py b/authentik/stages/authenticator_sms/urls.py index 56b315f619..dd4274b787 100644 --- a/authentik/stages/authenticator_sms/urls.py +++ b/authentik/stages/authenticator_sms/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.authenticator_sms.api import ( AuthenticatorSMSStageViewSet, SMSAdminDeviceViewSet, diff --git a/authentik/stages/authenticator_static/api.py b/authentik/stages/authenticator_static/api.py index d9f474eb16..2bc0eb6e97 100644 --- a/authentik/stages/authenticator_static/api.py +++ b/authentik/stages/authenticator_static/api.py @@ -1,4 +1,5 @@ """AuthenticatorStaticStage API Views""" + from django_filters.rest_framework import DjangoFilterBackend from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter diff --git a/authentik/stages/authenticator_static/apps.py b/authentik/stages/authenticator_static/apps.py index 09c6202d6c..02dc8af690 100644 --- a/authentik/stages/authenticator_static/apps.py +++ b/authentik/stages/authenticator_static/apps.py @@ -1,4 +1,5 @@ """Authenticator Static stage""" + from authentik.blueprints.apps import ManagedAppConfig @@ -9,7 +10,3 @@ class AuthentikStageAuthenticatorStaticConfig(ManagedAppConfig): label = "authentik_stages_authenticator_static" verbose_name = "authentik Stages.Authenticator.Static" default = True - - def reconcile_global_load_stages_authenticator_static_signals(self): - """Load stages.authenticator_static signals""" - self.import_module("authentik.stages.authenticator_static.signals") diff --git a/authentik/stages/authenticator_static/models.py b/authentik/stages/authenticator_static/models.py index 3b1ade6297..77af9b24a0 100644 --- a/authentik/stages/authenticator_static/models.py +++ b/authentik/stages/authenticator_static/models.py @@ -1,7 +1,7 @@ """Static Authenticator models""" + from base64 import b32encode from os import urandom -from typing import Optional from django.conf import settings from django.db import models @@ -28,7 +28,7 @@ class AuthenticatorStaticStage(ConfigurableStage, FriendlyNamedStage, Stage): return AuthenticatorStaticStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_static.stage import AuthenticatorStaticStageView return AuthenticatorStaticStageView @@ -37,7 +37,7 @@ class AuthenticatorStaticStage(ConfigurableStage, FriendlyNamedStage, Stage): def component(self) -> str: return "ak-stage-authenticator-static-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.friendly_name or str(self._meta.verbose_name), @@ -115,6 +115,13 @@ class StaticToken(models.Model): device = models.ForeignKey(StaticDevice, related_name="token_set", on_delete=models.CASCADE) token = models.CharField(max_length=16, db_index=True) + class Meta: + verbose_name = _("Static Token") + verbose_name_plural = _("Static Tokens") + + def __str__(self) -> str: + return "Static Token" + @staticmethod def random_token(): """ @@ -124,7 +131,3 @@ class StaticToken(models.Model): """ return b32encode(urandom(5)).decode("utf-8").lower() - - class Meta: - verbose_name = _("Static Token") - verbose_name_plural = _("Static Tokens") diff --git a/authentik/stages/authenticator_static/signals.py b/authentik/stages/authenticator_static/signals.py index 5b0428eef8..a654b95160 100644 --- a/authentik/stages/authenticator_static/signals.py +++ b/authentik/stages/authenticator_static/signals.py @@ -1,4 +1,5 @@ """totp authenticator signals""" + from django.db.models.signals import pre_delete from django.dispatch import receiver diff --git a/authentik/stages/authenticator_static/stage.py b/authentik/stages/authenticator_static/stage.py index 47efbfad71..ef4a808b12 100644 --- a/authentik/stages/authenticator_static/stage.py +++ b/authentik/stages/authenticator_static/stage.py @@ -1,4 +1,5 @@ """Static OTP Setup stage""" + from django.http import HttpRequest, HttpResponse from rest_framework.fields import CharField, ListField diff --git a/authentik/stages/authenticator_static/tests.py b/authentik/stages/authenticator_static/tests.py index 92e40f752e..d002e5c040 100644 --- a/authentik/stages/authenticator_static/tests.py +++ b/authentik/stages/authenticator_static/tests.py @@ -1,4 +1,5 @@ """Test Static API""" + from django.test.utils import override_settings from django.urls import reverse from rest_framework.test import APITestCase diff --git a/authentik/stages/authenticator_static/urls.py b/authentik/stages/authenticator_static/urls.py index 57a79cae73..3bccfc3d4b 100644 --- a/authentik/stages/authenticator_static/urls.py +++ b/authentik/stages/authenticator_static/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.authenticator_static.api import ( AuthenticatorStaticStageViewSet, StaticAdminDeviceViewSet, diff --git a/authentik/stages/authenticator_totp/api.py b/authentik/stages/authenticator_totp/api.py index 3baffb3ff4..b0ca4d480e 100644 --- a/authentik/stages/authenticator_totp/api.py +++ b/authentik/stages/authenticator_totp/api.py @@ -1,4 +1,5 @@ """AuthenticatorTOTPStage API Views""" + from django_filters.rest_framework.backends import DjangoFilterBackend from rest_framework import mixins from rest_framework.fields import ChoiceField diff --git a/authentik/stages/authenticator_totp/apps.py b/authentik/stages/authenticator_totp/apps.py index 9ca682cda2..7e624a95dd 100644 --- a/authentik/stages/authenticator_totp/apps.py +++ b/authentik/stages/authenticator_totp/apps.py @@ -1,4 +1,5 @@ """TOTP""" + from django.apps import AppConfig diff --git a/authentik/stages/authenticator_totp/models.py b/authentik/stages/authenticator_totp/models.py index 9f4ccacdcc..6275af6a03 100644 --- a/authentik/stages/authenticator_totp/models.py +++ b/authentik/stages/authenticator_totp/models.py @@ -1,8 +1,8 @@ """OTP Time-based models""" + import time from base64 import b32encode from binascii import unhexlify -from typing import Optional from urllib.parse import quote, urlencode from django.conf import settings @@ -38,7 +38,7 @@ class AuthenticatorTOTPStage(ConfigurableStage, FriendlyNamedStage, Stage): return AuthenticatorTOTPStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_totp.stage import AuthenticatorTOTPStageView return AuthenticatorTOTPStageView @@ -47,7 +47,7 @@ class AuthenticatorTOTPStage(ConfigurableStage, FriendlyNamedStage, Stage): def component(self) -> str: return "ak-stage-authenticator-totp-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.friendly_name or str(self._meta.verbose_name), @@ -219,16 +219,16 @@ class TOTPDevice(SerializerModel, ThrottlingMixin, Device): issuer = self._read_str_from_settings("OTP_TOTP_ISSUER") if issuer: issuer = issuer.replace(":", "") - label = "{}:{}".format(issuer, label) - urlencoded_params += "&issuer={}".format( - quote(issuer) - ) # encode issuer as per RFC 3986, not quote_plus + label = f"{issuer}:{label}" + urlencoded_params += ( + f"&issuer={quote(issuer)}" # encode issuer as per RFC 3986, not quote_plus + ) image = self._read_str_from_settings("OTP_TOTP_IMAGE") if image: urlencoded_params += "&image={}".format(quote(image, safe=":/")) - url = "otpauth://totp/{}?{}".format(quote(label), urlencoded_params) + url = f"otpauth://totp/{quote(label)}?{urlencoded_params}" return url diff --git a/authentik/stages/authenticator_totp/stage.py b/authentik/stages/authenticator_totp/stage.py index d87cc6e3cc..1a0791f785 100644 --- a/authentik/stages/authenticator_totp/stage.py +++ b/authentik/stages/authenticator_totp/stage.py @@ -1,4 +1,5 @@ """TOTP Setup stage""" + from urllib.parse import quote from django.http import HttpRequest, HttpResponse diff --git a/authentik/stages/authenticator_totp/tests.py b/authentik/stages/authenticator_totp/tests.py index 8ee7577ad1..b5185d9396 100644 --- a/authentik/stages/authenticator_totp/tests.py +++ b/authentik/stages/authenticator_totp/tests.py @@ -1,4 +1,5 @@ """Test TOTP API""" + from time import time from urllib.parse import parse_qs, urlsplit @@ -45,7 +46,6 @@ class TOTPDeviceMixin: 784503, ] - # pylint: disable=invalid-name def setUp(self): """ Create a device at the fourth time step. The current token is 154567. diff --git a/authentik/stages/authenticator_totp/urls.py b/authentik/stages/authenticator_totp/urls.py index 7be8d5f795..3c20499df0 100644 --- a/authentik/stages/authenticator_totp/urls.py +++ b/authentik/stages/authenticator_totp/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.authenticator_totp.api import ( AuthenticatorTOTPStageViewSet, TOTPAdminDeviceViewSet, diff --git a/authentik/stages/authenticator_validate/api.py b/authentik/stages/authenticator_validate/api.py index f4ea36fc18..2ed053306f 100644 --- a/authentik/stages/authenticator_validate/api.py +++ b/authentik/stages/authenticator_validate/api.py @@ -1,4 +1,5 @@ """AuthenticatorValidateStage API Views""" + from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet @@ -6,11 +7,16 @@ from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.flows.models import NotConfiguredAction from authentik.stages.authenticator_validate.models import AuthenticatorValidateStage +from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeSerializer class AuthenticatorValidateStageSerializer(StageSerializer): """AuthenticatorValidateStage Serializer""" + webauthn_allowed_device_types_obj = WebAuthnDeviceTypeSerializer( + source="webauthn_allowed_device_types", many=True, read_only=True + ) + def validate_not_configured_action(self, value): """Ensure that a configuration stage is set when not_configured_action is configure""" configuration_stages = self.initial_data.get("configuration_stages", None) @@ -30,6 +36,8 @@ class AuthenticatorValidateStageSerializer(StageSerializer): "configuration_stages", "last_auth_threshold", "webauthn_user_verification", + "webauthn_allowed_device_types", + "webauthn_allowed_device_types_obj", ] diff --git a/authentik/stages/authenticator_validate/apps.py b/authentik/stages/authenticator_validate/apps.py index e50715bf8d..922440f955 100644 --- a/authentik/stages/authenticator_validate/apps.py +++ b/authentik/stages/authenticator_validate/apps.py @@ -1,4 +1,5 @@ """Authenticator Validation Stage""" + from django.apps import AppConfig diff --git a/authentik/stages/authenticator_validate/challenge.py b/authentik/stages/authenticator_validate/challenge.py index eeed5adcb3..c11439684f 100644 --- a/authentik/stages/authenticator_validate/challenge.py +++ b/authentik/stages/authenticator_validate/challenge.py @@ -1,6 +1,6 @@ """Validation stage challenge checking""" + from json import loads -from typing import Optional from urllib.parse import urlencode from django.http import HttpRequest @@ -14,13 +14,15 @@ from structlog.stdlib import get_logger from webauthn import options_to_json from webauthn.authentication.generate_authentication_options import generate_authentication_options from webauthn.authentication.verify_authentication_response import verify_authentication_response +from webauthn.helpers import parse_authentication_credential_json from webauthn.helpers.base64url_to_bytes import base64url_to_bytes -from webauthn.helpers.exceptions import InvalidAuthenticationResponse +from webauthn.helpers.exceptions import InvalidAuthenticationResponse, InvalidJSONStructure from webauthn.helpers.structs import UserVerificationRequirement from authentik.core.api.utils import JSONDictField, PassiveSerializer from authentik.core.models import Application, User from authentik.core.signals import login_failed +from authentik.events.middleware import audit_ignore from authentik.events.models import Event, EventAction from authentik.flows.stage import StageView from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE @@ -64,7 +66,7 @@ def get_webauthn_challenge_without_user( authentication_options = generate_authentication_options( rp_id=get_rp_id(request), allow_credentials=[], - user_verification=stage.webauthn_user_verification, + user_verification=UserVerificationRequirement(stage.webauthn_user_verification), ) request.session[SESSION_KEY_WEBAUTHN_CHALLENGE] = authentication_options.challenge @@ -72,7 +74,7 @@ def get_webauthn_challenge_without_user( def get_webauthn_challenge( - request: HttpRequest, stage: AuthenticatorValidateStage, device: Optional[WebAuthnDevice] = None + request: HttpRequest, stage: AuthenticatorValidateStage, device: WebAuthnDevice | None = None ) -> dict: """Send the client a challenge that we'll check later""" request.session.pop(SESSION_KEY_WEBAUTHN_CHALLENGE, None) @@ -120,7 +122,9 @@ def validate_challenge_code(code: str, stage_view: StageView, user: User) -> Dev stage=stage_view.executor.current_stage, device_class=DeviceClasses.TOTP.value, ) - raise ValidationError(_("Invalid Token")) + raise ValidationError( + _("Invalid Token. Please ensure the time on your device is accurate and try again.") + ) return device @@ -128,23 +132,40 @@ def validate_challenge_webauthn(data: dict, stage_view: StageView, user: User) - """Validate WebAuthn Challenge""" request = stage_view.request challenge = request.session.get(SESSION_KEY_WEBAUTHN_CHALLENGE) - credential_id = data.get("id") + stage: AuthenticatorValidateStage = stage_view.executor.current_stage + try: + credential = parse_authentication_credential_json(data) + except InvalidJSONStructure as exc: + LOGGER.warning("Invalid WebAuthn challenge response", exc=exc) + raise ValidationError("Invalid device", "invalid") from None - device = WebAuthnDevice.objects.filter(credential_id=credential_id).first() + device = WebAuthnDevice.objects.filter(credential_id=credential.id).first() if not device: - raise ValidationError("Invalid device") + raise ValidationError("Invalid device", "invalid") # We can only check the device's user if the user we're given isn't anonymous # as this validation is also used for password-less login where webauthn is the very first # step done by a user. Only if this validation happens at a later stage we can check # that the device belongs to the user if not user.is_anonymous and device.user != user: - raise ValidationError("Invalid device") - - stage: AuthenticatorValidateStage = stage_view.executor.current_stage - + raise ValidationError("Invalid device", "invalid") + # When a device_type was set when creating the device (2024.4+), and we have a limitation, + # make sure the device type is allowed. + if ( + device.device_type + and stage.webauthn_allowed_device_types.exists() + and not stage.webauthn_allowed_device_types.filter(pk=device.device_type.pk).exists() + ): + raise ValidationError( + _( + "Invalid device type. Contact your {brand} administrator for help.".format( + brand=stage_view.request.brand.branding_title + ) + ), + "invalid", + ) try: authentication_verification = verify_authentication_response( - credential=data, + credential=credential, expected_challenge=challenge, expected_rp_id=get_rp_id(request), expected_origin=get_origin(request), @@ -161,10 +182,12 @@ def validate_challenge_webauthn(data: dict, stage_view: StageView, user: User) - stage=stage_view.executor.current_stage, device=device, device_class=DeviceClasses.WEBAUTHN.value, + device_type=device.device_type, ) raise ValidationError("Assertion failed") from exc - device.set_sign_count(authentication_verification.new_sign_count) + with audit_ignore(): + device.set_sign_count(authentication_verification.new_sign_count) return device @@ -191,10 +214,11 @@ def validate_challenge_duo(device_pk: int, stage_view: StageView, user: User) -> user_id=device.duo_user_id, ipaddr=ClientIPMiddleware.get_client_ip(stage_view.request), type=__( - "%(brand_name)s Login request" - % { - "brand_name": stage_view.request.brand.branding_title, - } + "{brand_name} Login request".format_map( + { + "brand_name": stage_view.request.brand.branding_title, + } + ) ), display_username=user.username, device="auto", @@ -219,4 +243,4 @@ def validate_challenge_duo(device_pk: int, stage_view: StageView, user: User) -> message=f"Failed to DUO authenticate user: {str(exc)}", user=user, ).from_http(stage_view.request, user) - raise ValidationError("Duo denied access", code="denied") + raise ValidationError("Duo denied access", code="denied") from exc diff --git a/authentik/stages/authenticator_validate/migrations/0013_authenticatorvalidatestage_webauthn_allowed_device_types.py b/authentik/stages/authenticator_validate/migrations/0013_authenticatorvalidatestage_webauthn_allowed_device_types.py new file mode 100644 index 0000000000..52c4be8182 --- /dev/null +++ b/authentik/stages/authenticator_validate/migrations/0013_authenticatorvalidatestage_webauthn_allowed_device_types.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.3 on 2024-04-08 18:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "authentik_stages_authenticator_validate", + "0012_authenticatorvalidatestage_webauthn_user_verification", + ), + ( + "authentik_stages_authenticator_webauthn", + "0010_webauthndevicetype_authenticatorwebauthnstage_and_more", + ), + ] + + operations = [ + migrations.AddField( + model_name="authenticatorvalidatestage", + name="webauthn_allowed_device_types", + field=models.ManyToManyField( + blank=True, to="authentik_stages_authenticator_webauthn.webauthndevicetype" + ), + ), + ] diff --git a/authentik/stages/authenticator_validate/models.py b/authentik/stages/authenticator_validate/models.py index 45bf071b52..b0c6133685 100644 --- a/authentik/stages/authenticator_validate/models.py +++ b/authentik/stages/authenticator_validate/models.py @@ -71,6 +71,9 @@ class AuthenticatorValidateStage(Stage): choices=UserVerification.choices, default=UserVerification.PREFERRED, ) + webauthn_allowed_device_types = models.ManyToManyField( + "authentik_stages_authenticator_webauthn.WebAuthnDeviceType", blank=True + ) @property def serializer(self) -> type[BaseSerializer]: @@ -79,7 +82,7 @@ class AuthenticatorValidateStage(Stage): return AuthenticatorValidateStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_validate.stage import AuthenticatorValidateStageView return AuthenticatorValidateStageView diff --git a/authentik/stages/authenticator_validate/stage.py b/authentik/stages/authenticator_validate/stage.py index 8a730414ab..5e3a13fbc7 100644 --- a/authentik/stages/authenticator_validate/stage.py +++ b/authentik/stages/authenticator_validate/stage.py @@ -1,10 +1,11 @@ """Authenticator Validation""" + from datetime import datetime from hashlib import sha256 -from typing import Optional from django.conf import settings from django.http import HttpRequest, HttpResponse +from django.utils.translation import gettext_lazy as _ from jwt import PyJWTError, decode, encode from rest_framework.fields import CharField, IntegerField, ListField, UUIDField from rest_framework.serializers import ValidationError @@ -13,12 +14,11 @@ from authentik.core.api.utils import JSONDictField, PassiveSerializer from authentik.core.models import User from authentik.events.models import Event, EventAction from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge -from authentik.flows.exceptions import FlowSkipStageException +from authentik.flows.exceptions import FlowSkipStageException, StageInvalidException from authentik.flows.models import FlowDesignation, NotConfiguredAction, Stage from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import ChallengeStageView from authentik.lib.utils.time import timedelta_from_string -from authentik.root.install_id import get_install_id from authentik.stages.authenticator import devices_for_user from authentik.stages.authenticator.models import Device from authentik.stages.authenticator_sms.models import SMSDevice @@ -34,6 +34,7 @@ from authentik.stages.authenticator_validate.challenge import ( from authentik.stages.authenticator_validate.models import AuthenticatorValidateStage, DeviceClasses from authentik.stages.authenticator_webauthn.models import WebAuthnDevice from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS +from authentik.tenants.utils import get_unique_identifier COOKIE_NAME_MFA = "authentik_mfa" @@ -62,7 +63,7 @@ class AuthenticatorValidationChallenge(WithUserInfoChallenge): class AuthenticatorValidationChallengeResponse(ChallengeResponse): """Challenge used for Code-based and WebAuthn authenticators""" - device: Optional[Device] + device: Device | None selected_challenge = DeviceChallenge(required=False) selected_stage = CharField(required=False) @@ -153,6 +154,16 @@ class AuthenticatorValidateStageView(ChallengeStageView): def get_device_challenges(self) -> list[dict]: """Get a list of all device challenges applicable for the current stage""" challenges = [] + pending_user = self.get_pending_user() + if pending_user.is_anonymous: + # We shouldn't get here without any kind of authentication data + raise StageInvalidException() + # When `pretend_user_exists` is enabled in the identification stage, + # `pending_user` will be a user model that isn't save to the DB + # hence it doesn't have a PK. In that case we just return an empty list of + # authenticators + if not pending_user.pk: + return [] # Convert to a list to have usable log output instead of just user_devices = list(devices_for_user(self.get_pending_user())) self.logger.debug("Got devices for user", devices=user_devices) @@ -166,15 +177,30 @@ class AuthenticatorValidateStageView(ChallengeStageView): threshold = timedelta_from_string(stage.last_auth_threshold) allowed_devices = [] + has_webauthn_filters_set = stage.webauthn_allowed_device_types.exists() + for device in user_devices: device_class = device.__class__.__name__.lower().replace("device", "") if device_class not in stage.device_classes: self.logger.debug("device class not allowed", device_class=device_class) continue if isinstance(device, SMSDevice) and device.is_hashed: - self.logger.debug("Hashed SMS device, skipping") + self.logger.debug("Hashed SMS device, skipping", device=device) continue allowed_devices.append(device) + # Ignore WebAuthn devices which are not in the allowed types + if ( + isinstance(device, WebAuthnDevice) + and device.device_type + and has_webauthn_filters_set + ): + if not stage.webauthn_allowed_device_types.filter( + pk=device.device_type.pk + ).exists(): + self.logger.debug( + "WebAuthn device type not allowed", device=device, type=device.device_type + ) + continue # Ensure only one challenge per device class # WebAuthn does another device loop to find all WebAuthn devices if device_class in seen_classes: @@ -211,8 +237,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): challenge.is_valid() return [challenge.data] - # pylint: disable=too-many-return-statements - def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: + def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: # noqa: PLR0911 """Check if a user is set, and check if the user has any devices if not, we can skip this entire stage""" user = self.get_pending_user() @@ -242,7 +267,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): return self.executor.stage_ok() if stage.not_configured_action == NotConfiguredAction.DENY: self.logger.debug("Authenticator not configured, denying") - return self.executor.stage_invalid() + return self.executor.stage_invalid(_("No (allowed) MFA authenticator configured.")) if stage.not_configured_action == NotConfiguredAction.CONFIGURE: self.logger.debug("Authenticator not configured, forcing configure") return self.prepare_stages(user) @@ -322,7 +347,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): def cookie_jwt_key(self) -> str: """Signing key for MFA Cookie for this stage""" return sha256( - f"{get_install_id()}:{self.executor.current_stage.pk.hex}".encode("ascii") + f"{get_unique_identifier()}:{self.executor.current_stage.pk.hex}".encode("ascii") ).hexdigest() def check_mfa_cookie(self, allowed_devices: list[Device]): @@ -386,8 +411,12 @@ class AuthenticatorValidateStageView(ChallengeStageView): webauthn_device: WebAuthnDevice = response.device self.logger.debug("Set user from user-less flow", user=webauthn_device.user) self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = webauthn_device.user - self.executor.plan.context[PLAN_CONTEXT_METHOD] = "auth_webauthn_pwl" - self.executor.plan.context[PLAN_CONTEXT_METHOD_ARGS] = { - "device": webauthn_device, - } + self.executor.plan.context.setdefault(PLAN_CONTEXT_METHOD, "auth_webauthn_pwl") + self.executor.plan.context.setdefault(PLAN_CONTEXT_METHOD_ARGS, {}) + self.executor.plan.context[PLAN_CONTEXT_METHOD_ARGS].update( + { + "device": webauthn_device, + "device_type": webauthn_device.device_type, + } + ) return self.set_valid_mfa_cookie(response.device) diff --git a/authentik/stages/authenticator_validate/tests/test_duo.py b/authentik/stages/authenticator_validate/tests/test_duo.py index bdd1c59842..bc76442c8b 100644 --- a/authentik/stages/authenticator_validate/tests/test_duo.py +++ b/authentik/stages/authenticator_validate/tests/test_duo.py @@ -1,4 +1,5 @@ """Test validator stage""" + from unittest.mock import MagicMock, patch from django.contrib.sessions.middleware import SessionMiddleware @@ -36,7 +37,7 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase): middleware = SessionMiddleware(dummy_get_response) middleware.process_request(request) request.session.save() - setattr(request, "brand", get_brand_for_request(request)) + request.brand = get_brand_for_request(request) stage = AuthenticatorDuoStage.objects.create( name=generate_id(), diff --git a/authentik/stages/authenticator_validate/tests/test_sms.py b/authentik/stages/authenticator_validate/tests/test_sms.py index e171b1ef87..5cce796207 100644 --- a/authentik/stages/authenticator_validate/tests/test_sms.py +++ b/authentik/stages/authenticator_validate/tests/test_sms.py @@ -1,4 +1,5 @@ """Test validator stage""" + from unittest.mock import MagicMock, patch from django.test.client import RequestFactory diff --git a/authentik/stages/authenticator_validate/tests/test_stage.py b/authentik/stages/authenticator_validate/tests/test_stage.py index f5c8c281c5..98fe5d2fe4 100644 --- a/authentik/stages/authenticator_validate/tests/test_stage.py +++ b/authentik/stages/authenticator_validate/tests/test_stage.py @@ -1,4 +1,5 @@ """Test validator stage""" + from unittest.mock import MagicMock, patch from django.test.client import RequestFactory diff --git a/authentik/stages/authenticator_validate/tests/test_totp.py b/authentik/stages/authenticator_validate/tests/test_totp.py index 5873a4f691..8efcec7eb4 100644 --- a/authentik/stages/authenticator_validate/tests/test_totp.py +++ b/authentik/stages/authenticator_validate/tests/test_totp.py @@ -1,4 +1,5 @@ """Test validator stage""" + from datetime import datetime, timedelta from hashlib import sha256 from time import sleep diff --git a/authentik/stages/authenticator_validate/tests/test_webauthn.py b/authentik/stages/authenticator_validate/tests/test_webauthn.py index 8ea9c68560..c66ac0c20d 100644 --- a/authentik/stages/authenticator_validate/tests/test_webauthn.py +++ b/authentik/stages/authenticator_validate/tests/test_webauthn.py @@ -1,4 +1,5 @@ """Test validator stage""" + from time import sleep from django.test.client import RequestFactory @@ -25,8 +26,16 @@ from authentik.stages.authenticator_validate.stage import ( PLAN_CONTEXT_DEVICE_CHALLENGES, AuthenticatorValidateStageView, ) -from authentik.stages.authenticator_webauthn.models import UserVerification, WebAuthnDevice +from authentik.stages.authenticator_webauthn.models import ( + UserVerification, + WebAuthnDevice, + WebAuthnDeviceType, +) from authentik.stages.authenticator_webauthn.stage import SESSION_KEY_WEBAUTHN_CHALLENGE +from authentik.stages.authenticator_webauthn.tasks import ( + webauthn_aaguid_import, + webauthn_mds_import, +) from authentik.stages.identification.models import IdentificationStage, UserFields from authentik.stages.user_login.models import UserLoginStage @@ -119,7 +128,56 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): {}, StageView(FlowExecutorView(current_stage=stage), request=request), self.user ) - def test_get_challenge(self): + def test_device_challenge_webauthn_restricted(self): + """Test webauthn (getting device challenges with a webauthn + device that is not allowed due to aaguid restrictions)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() + request = get_request("/") + request.user = self.user + + WebAuthnDevice.objects.create( + user=self.user, + public_key=bytes_to_base64url(b"qwerqwerqre"), + credential_id=bytes_to_base64url(b"foobarbaz"), + sign_count=0, + rp_id=generate_id(), + device_type=WebAuthnDeviceType.objects.get( + aaguid="2fc0579f-8113-47ea-b116-bb5a8db9202a" + ), + ) + flow = create_test_flow() + stage = AuthenticatorValidateStage.objects.create( + name=generate_id(), + last_auth_threshold="milliseconds=0", + not_configured_action=NotConfiguredAction.DENY, + device_classes=[DeviceClasses.WEBAUTHN], + webauthn_user_verification=UserVerification.PREFERRED, + ) + stage.webauthn_allowed_device_types.set( + WebAuthnDeviceType.objects.filter( + description="Android Authenticator with SafetyNet Attestation" + ) + ) + session = self.client.session + plan = FlowPlan(flow_pk=flow.pk.hex) + plan.append_stage(stage) + plan.append_stage(UserLoginStage(name=generate_id())) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + session[SESSION_KEY_PLAN] = plan + session.save() + + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + ) + self.assertStageResponse( + response, + flow, + component="ak-stage-access-denied", + error_message="No (allowed) MFA authenticator configured.", + ) + + def test_raw_get_challenge(self): """Test webauthn""" request = get_request("/") request.user = self.user @@ -163,8 +221,9 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): """Test webauthn (userless)""" request = get_request("/") stage = AuthenticatorValidateStage.objects.create( - name=generate_id(), + name=generate_id(), webauthn_user_verification=UserVerification.PREFERRED ) + stage.refresh_from_db() WebAuthnDevice.objects.create( user=self.user, public_key=( @@ -188,17 +247,21 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): }, ) - def test_validate_challenge(self): - """Test webauthn""" + def test_validate_challenge_unrestricted(self): + """Test webauthn authentication (unrestricted webauthn device)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() device = WebAuthnDevice.objects.create( user=self.user, public_key=( - "pQECAyYgASFYIGsBLkklToCQkT7qJT_bJYN1sEc1oJdbnmoOc43i0J" - "H6IlggLTXytuhzFVYYAK4PQNj8_coGrbbzSfUxdiPAcZTQCyU" + "pQECAyYgASFYIF-N4GvQJdTJMAmTOxFX9_boL00zBiSrP0DY9xvJl_FFIlggnyZloVSVofdJNTLMeMdjQHgW2Rzmd5_Xt5AWtNztcdo" ), - credential_id="QKZ97ASJAOIDyipAs6mKUxDUZgDrWrbAsUb5leL7-oU", - sign_count=4, + credential_id="X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", + sign_count=2, rp_id=generate_id(), + device_type=WebAuthnDeviceType.objects.get( + aaguid="2fc0579f-8113-47ea-b116-bb5a8db9202a" + ), ) flow = create_test_flow() stage = AuthenticatorValidateStage.objects.create( @@ -220,7 +283,7 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): ] session[SESSION_KEY_PLAN] = plan session[SESSION_KEY_WEBAUTHN_CHALLENGE] = base64url_to_bytes( - "g98I51mQvZXo5lxLfhrD2zfolhZbLRyCgqkkYap1jwSaJ13BguoJWCF9_Lg3AgO4Wh-Bqa556JE20oKsYbl6RA" + "aCC6ak_DP45xMH1qyxzUM5iC2xc4QthQb09v7m4qDBmY8FvWvhxFzSuFlDYQmclrh5fWS5q0TPxgJGF4vimcFQ" ) session.save() @@ -228,24 +291,23 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), data={ "webauthn": { - "id": "QKZ97ASJAOIDyipAs6mKUxDUZgDrWrbAsUb5leL7-oU", - "rawId": "QKZ97ASJAOIDyipAs6mKUxDUZgDrWrbAsUb5leL7-oU", + "id": "X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", + "rawId": "X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", "type": "public-key", "assertionClientExtensions": "{}", "response": { "clientDataJSON": ( - "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZzk4STUxbVF2WlhvN" - "Wx4TGZockQyemZvbGhaYkxSeUNncWtrWWFwMWp3U2FKMTNCZ3VvSldDRjlfTGczQW" - "dPNFdoLUJxYTU1NkpFMjBvS3NZYmw2UkEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWx" - "ob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2Jl" - "X2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2Fpb" - "nN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ==" + "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiYUNDN" + "mFrX0RQNDV4TUgxcXl4elVNNWlDMnhjNFF0aFFiMDl2N200cURCbV" + "k4RnZXdmh4RnpTdUZsRFlRbWNscmg1ZldTNXEwVFB4Z0pHRjR2aW1" + "jRlEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJj" + "cm9zc09yaWdpbiI6ZmFsc2V9" ), "signature": ( - "MEQCIFNlrHf9ablJAalXLWkrqvHB8oIu8kwvRpH3X3rbJVpI" - "AiAqtOK6mIZPk62kZN0OzFsHfuvu_RlOl7zlqSNzDdz_Ag==" + "MEQCIAHQCGfE_PX1z6mBDaXUNqK_NrllhXylNOmETUD3Khv9AiBTl" + "rX3GDRj5OaOfTToOwUwAhtd74tu0T6DZAVHPb_hlQ==" ), - "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAABQ==", + "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAABg==", "userHandle": None, }, }, @@ -259,6 +321,96 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase): ) self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) + def test_validate_challenge_restricted(self): + """Test webauthn authentication (restricted device type, failure)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() + device = WebAuthnDevice.objects.create( + user=self.user, + public_key=( + "pQECAyYgASFYIF-N4GvQJdTJMAmTOxFX9_boL00zBiSrP0DY9xvJl_FFIlggnyZloVSVofdJNTLMeMdjQHgW2Rzmd5_Xt5AWtNztcdo" + ), + credential_id="X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", + sign_count=2, + rp_id=generate_id(), + device_type=WebAuthnDeviceType.objects.get( + aaguid="2fc0579f-8113-47ea-b116-bb5a8db9202a" + ), + ) + flow = create_test_flow() + stage = AuthenticatorValidateStage.objects.create( + name=generate_id(), + not_configured_action=NotConfiguredAction.CONFIGURE, + device_classes=[DeviceClasses.WEBAUTHN], + ) + stage.webauthn_allowed_device_types.set( + WebAuthnDeviceType.objects.filter( + description="Android Authenticator with SafetyNet Attestation" + ) + ) + session = self.client.session + plan = FlowPlan(flow_pk=flow.pk.hex) + plan.append_stage(stage) + plan.append_stage(UserLoginStage(name=generate_id())) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + plan.context[PLAN_CONTEXT_DEVICE_CHALLENGES] = [ + { + "device_class": device.__class__.__name__.lower().replace("device", ""), + "device_uid": device.pk, + "challenge": {}, + } + ] + session[SESSION_KEY_PLAN] = plan + session[SESSION_KEY_WEBAUTHN_CHALLENGE] = base64url_to_bytes( + "aCC6ak_DP45xMH1qyxzUM5iC2xc4QthQb09v7m4qDBmY8FvWvhxFzSuFlDYQmclrh5fWS5q0TPxgJGF4vimcFQ" + ) + session.save() + + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + data={ + "webauthn": { + "id": "X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", + "rawId": "X43ga9Al1MkwCZM7EXD1r8Sxj7aXnNsuR013XM7he4kZ-GS9TaA-u3i36wsswjPm", + "type": "public-key", + "assertionClientExtensions": "{}", + "response": { + "clientDataJSON": ( + "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiYUNDN" + "mFrX0RQNDV4TUgxcXl4elVNNWlDMnhjNFF0aFFiMDl2N200cURCbV" + "k4RnZXdmh4RnpTdUZsRFlRbWNscmg1ZldTNXEwVFB4Z0pHRjR2aW1" + "jRlEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjkwMDAiLCJj" + "cm9zc09yaWdpbiI6ZmFsc2V9" + ), + "signature": ( + "MEQCIAHQCGfE_PX1z6mBDaXUNqK_NrllhXylNOmETUD3Khv9AiBTl" + "rX3GDRj5OaOfTToOwUwAhtd74tu0T6DZAVHPb_hlQ==" + ), + "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAABg==", + "userHandle": None, + }, + } + }, + SERVER_NAME="localhost", + SERVER_PORT="9000", + ) + self.assertEqual(response.status_code, 200) + self.assertStageResponse( + response, + flow, + component="ak-stage-authenticator-validate", + response_errors={ + "webauthn": [ + { + "string": ( + "Invalid device type. Contact your authentik administrator for help." + ), + "code": "invalid", + } + ] + }, + ) + def test_validate_challenge_userless(self): """Test webauthn""" device = WebAuthnDevice.objects.create( diff --git a/authentik/stages/authenticator_validate/urls.py b/authentik/stages/authenticator_validate/urls.py index 30565eaee7..cb5ceae357 100644 --- a/authentik/stages/authenticator_validate/urls.py +++ b/authentik/stages/authenticator_validate/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageViewSet api_urlpatterns = [("stages/authenticator/validate", AuthenticatorValidateStageViewSet)] diff --git a/authentik/stages/authenticator_webauthn/api/__init__.py b/authentik/stages/authenticator_webauthn/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/stages/authenticator_webauthn/api/device_types.py b/authentik/stages/authenticator_webauthn/api/device_types.py new file mode 100644 index 0000000000..2bdac2a7d2 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/api/device_types.py @@ -0,0 +1,27 @@ +"""WebAuthnDeviceType API Views""" + +from rest_framework.viewsets import ReadOnlyModelViewSet + +from authentik.flows.api.stages import StageSerializer +from authentik.stages.authenticator_webauthn.models import WebAuthnDeviceType + + +class WebAuthnDeviceTypeSerializer(StageSerializer): + """WebAuthnDeviceType Serializer""" + + class Meta: + model = WebAuthnDeviceType + fields = [ + "aaguid", + "description", + ] + + +class WebAuthnDeviceTypeViewSet(ReadOnlyModelViewSet): + """WebAuthnDeviceType Viewset""" + + queryset = WebAuthnDeviceType.objects.all() + serializer_class = WebAuthnDeviceTypeSerializer + filterset_fields = "__all__" + ordering = ["description"] + search_fields = ["description", "aaguid"] diff --git a/authentik/stages/authenticator_webauthn/api.py b/authentik/stages/authenticator_webauthn/api/devices.py similarity index 60% rename from authentik/stages/authenticator_webauthn/api.py rename to authentik/stages/authenticator_webauthn/api/devices.py index 9d19143530..e1ccf85bbf 100644 --- a/authentik/stages/authenticator_webauthn/api.py +++ b/authentik/stages/authenticator_webauthn/api/devices.py @@ -1,4 +1,5 @@ -"""AuthenticateWebAuthnStage API Views""" +"""AuthenticatorWebAuthnStage API Views""" + from django_filters.rest_framework.backends import DjangoFilterBackend from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter @@ -8,41 +9,21 @@ from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin -from authentik.flows.api.stages import StageSerializer -from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage, WebAuthnDevice - - -class AuthenticateWebAuthnStageSerializer(StageSerializer): - """AuthenticateWebAuthnStage Serializer""" - - class Meta: - model = AuthenticateWebAuthnStage - fields = StageSerializer.Meta.fields + [ - "configure_flow", - "friendly_name", - "user_verification", - "authenticator_attachment", - "resident_key_requirement", - ] - - -class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet): - """AuthenticateWebAuthnStage Viewset""" - - queryset = AuthenticateWebAuthnStage.objects.all() - serializer_class = AuthenticateWebAuthnStageSerializer - filterset_fields = "__all__" - ordering = ["name"] - search_fields = ["name"] +from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeSerializer +from authentik.stages.authenticator_webauthn.models import WebAuthnDevice class WebAuthnDeviceSerializer(ModelSerializer): """Serializer for WebAuthn authenticator devices""" + device_type = WebAuthnDeviceTypeSerializer(read_only=True, allow_null=True) + class Meta: model = WebAuthnDevice - fields = ["pk", "name", "created_on"] - depth = 2 + fields = ["pk", "name", "created_on", "device_type", "aaguid"] + extra_kwargs = { + "aaguid": {"read_only": True}, + } class WebAuthnDeviceViewSet( diff --git a/authentik/stages/authenticator_webauthn/api/stages.py b/authentik/stages/authenticator_webauthn/api/stages.py new file mode 100644 index 0000000000..8fa57c7c76 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/api/stages.py @@ -0,0 +1,38 @@ +"""AuthenticatorWebAuthnStage API Views""" + +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.used_by import UsedByMixin +from authentik.flows.api.stages import StageSerializer +from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeSerializer +from authentik.stages.authenticator_webauthn.models import AuthenticatorWebAuthnStage + + +class AuthenticatorWebAuthnStageSerializer(StageSerializer): + """AuthenticatorWebAuthnStage Serializer""" + + device_type_restrictions_obj = WebAuthnDeviceTypeSerializer( + source="device_type_restrictions", many=True, read_only=True + ) + + class Meta: + model = AuthenticatorWebAuthnStage + fields = StageSerializer.Meta.fields + [ + "configure_flow", + "friendly_name", + "user_verification", + "authenticator_attachment", + "resident_key_requirement", + "device_type_restrictions", + "device_type_restrictions_obj", + ] + + +class AuthenticatorWebAuthnStageViewSet(UsedByMixin, ModelViewSet): + """AuthenticatorWebAuthnStage Viewset""" + + queryset = AuthenticatorWebAuthnStage.objects.all() + serializer_class = AuthenticatorWebAuthnStageSerializer + filterset_fields = "__all__" + ordering = ["name"] + search_fields = ["name"] diff --git a/authentik/stages/authenticator_webauthn/apps.py b/authentik/stages/authenticator_webauthn/apps.py index 36a2f3f0d4..745c659b75 100644 --- a/authentik/stages/authenticator_webauthn/apps.py +++ b/authentik/stages/authenticator_webauthn/apps.py @@ -1,10 +1,22 @@ """authentik webauthn app config""" -from django.apps import AppConfig + +from authentik.blueprints.apps import ManagedAppConfig -class AuthentikStageAuthenticatorWebAuthnConfig(AppConfig): +class AuthentikStageAuthenticatorWebAuthnConfig(ManagedAppConfig): """authentik webauthn config""" name = "authentik.stages.authenticator_webauthn" label = "authentik_stages_authenticator_webauthn" verbose_name = "authentik Stages.Authenticator.WebAuthn" + default = True + + @ManagedAppConfig.reconcile_tenant + def webauthn_device_types(self): + from authentik.stages.authenticator_webauthn.tasks import ( + webauthn_aaguid_import, + webauthn_mds_import, + ) + + webauthn_mds_import.delay() + webauthn_aaguid_import.delay() diff --git a/authentik/stages/authenticator_webauthn/management/commands/__init__.py b/authentik/stages/authenticator_webauthn/management/commands/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/authentik/stages/authenticator_webauthn/management/commands/update_webauthn_mds.py b/authentik/stages/authenticator_webauthn/management/commands/update_webauthn_mds.py new file mode 100644 index 0000000000..bffad1a7b2 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/management/commands/update_webauthn_mds.py @@ -0,0 +1,34 @@ +from django.core.management.base import BaseCommand +from fido2.mds3 import parse_blob +from structlog.stdlib import get_logger + +from authentik.lib.utils.http import get_http_session +from authentik.stages.authenticator_webauthn.tasks import AAGUID_BLOB_PATH, MDS_BLOB_PATH, mds_ca + +MDS3_URL = "https://mds3.fidoalliance.org/" +AAGUID_URL = "https://passkeydeveloper.github.io/passkey-authenticator-aaguids/aaguid.json" + + +class Command(BaseCommand): + """Update FIDO Alliances' MDS3 blob and validate it.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.logger = get_logger() + + def update_fido_mds(self): + with open(MDS_BLOB_PATH, "w", encoding="utf-8") as _raw_file: + _raw_file.write(get_http_session().get(MDS3_URL).text) + self.logger.info("Updated MDS blob") + with open(MDS_BLOB_PATH, mode="rb") as _raw_blob: + parse_blob(_raw_blob.read(), mds_ca()) + self.logger.info("Successfully validated MDS blob") + + def update_passkey_aaguids(self): + with open(AAGUID_BLOB_PATH, "w", encoding="utf-8") as _raw_file: + _raw_file.write(get_http_session().get(AAGUID_URL).text) + self.logger.info("Updated AAGUID blob") + + def handle(self, *args, **options): + self.update_fido_mds() + self.update_passkey_aaguids() diff --git a/authentik/stages/authenticator_webauthn/mds/aaguid.json b/authentik/stages/authenticator_webauthn/mds/aaguid.json new file mode 100644 index 0000000000..b10b0352d7 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/mds/aaguid.json @@ -0,0 +1,115 @@ +{ + "ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4": { + "name": "Google Password Manager", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE5MiAxOTIiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDE5MiAxOTIiIHdpZHRoPSIyNHB4Ij48cmVjdCBmaWxsPSJub25lIiBoZWlnaHQ9IjE5MiIgd2lkdGg9IjE5MiIgeT0iMCIvPjxnPjxwYXRoIGQ9Ik02OS4yOSwxMDZjLTMuNDYsNS45Ny05LjkxLDEwLTE3LjI5LDEwYy0xMS4wMywwLTIwLTguOTctMjAtMjBzOC45Ny0yMCwyMC0yMCBjNy4zOCwwLDEzLjgzLDQuMDMsMTcuMjksMTBoMjUuNTVDOTAuMyw2Ni41NCw3Mi44Miw1Miw1Miw1MkMyNy43NCw1Miw4LDcxLjc0LDgsOTZzMTkuNzQsNDQsNDQsNDRjMjAuODIsMCwzOC4zLTE0LjU0LDQyLjg0LTM0IEg2OS4yOXoiIGZpbGw9IiM0Mjg1RjQiLz48cmVjdCBmaWxsPSIjRkJCQzA0IiBoZWlnaHQ9IjI0IiB3aWR0aD0iNDQiIHg9Ijk0IiB5PSI4NCIvPjxwYXRoIGQ9Ik05NC4zMiw4NEg2OHYwLjA1YzIuNSwzLjM0LDQsNy40Nyw0LDExLjk1cy0xLjUsOC42MS00LDExLjk1VjEwOGgyNi4zMiBjMS4wOC0zLjgyLDEuNjgtNy44NCwxLjY4LTEyUzk1LjQxLDg3LjgyLDk0LjMyLDg0eiIgZmlsbD0iI0VBNDMzNSIvPjxwYXRoIGQ9Ik0xODQsMTA2djI2aC0xNnYtOGMwLTQuNDItMy41OC04LTgtOHMtOCwzLjU4LTgsOHY4aC0xNnYtMjZIMTg0eiIgZmlsbD0iIzM0QTg1MyIvPjxyZWN0IGZpbGw9IiMxODgwMzgiIGhlaWdodD0iMjQiIHdpZHRoPSI0OCIgeD0iMTM2IiB5PSI4NCIvPjwvZz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE5MiAxOTIiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDE5MiAxOTIiIHdpZHRoPSIyNHB4Ij48cmVjdCBmaWxsPSJub25lIiBoZWlnaHQ9IjE5MiIgd2lkdGg9IjE5MiIgeT0iMCIvPjxnPjxwYXRoIGQ9Ik02OS4yOSwxMDZjLTMuNDYsNS45Ny05LjkxLDEwLTE3LjI5LDEwYy0xMS4wMywwLTIwLTguOTctMjAtMjBzOC45Ny0yMCwyMC0yMCBjNy4zOCwwLDEzLjgzLDQuMDMsMTcuMjksMTBoMjUuNTVDOTAuMyw2Ni41NCw3Mi44Miw1Miw1Miw1MkMyNy43NCw1Miw4LDcxLjc0LDgsOTZzMTkuNzQsNDQsNDQsNDRjMjAuODIsMCwzOC4zLTE0LjU0LDQyLjg0LTM0IEg2OS4yOXoiIGZpbGw9IiM0Mjg1RjQiLz48cmVjdCBmaWxsPSIjRkJCQzA0IiBoZWlnaHQ9IjI0IiB3aWR0aD0iNDQiIHg9Ijk0IiB5PSI4NCIvPjxwYXRoIGQ9Ik05NC4zMiw4NEg2OHYwLjA1YzIuNSwzLjM0LDQsNy40Nyw0LDExLjk1cy0xLjUsOC42MS00LDExLjk1VjEwOGgyNi4zMiBjMS4wOC0zLjgyLDEuNjgtNy44NCwxLjY4LTEyUzk1LjQxLDg3LjgyLDk0LjMyLDg0eiIgZmlsbD0iI0VBNDMzNSIvPjxwYXRoIGQ9Ik0xODQsMTA2djI2aC0xNnYtOGMwLTQuNDItMy41OC04LTgtOHMtOCwzLjU4LTgsOHY4aC0xNnYtMjZIMTg0eiIgZmlsbD0iIzM0QTg1MyIvPjxyZWN0IGZpbGw9IiMxODgwMzgiIGhlaWdodD0iMjQiIHdpZHRoPSI0OCIgeD0iMTM2IiB5PSI4NCIvPjwvZz48L3N2Zz4=" + }, + "adce0002-35bc-c60a-648b-0b25f1f05503": { + "name": "Chrome on Mac", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNDggNDgiPgogIDxkZWZzPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMy4yMTczIiB5MT0iMTUiIHgyPSI0NC43ODEyIiB5Mj0iMTUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZDkzMDI1Ii8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2VhNDMzNSIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9IjIwLjcyMTkiIHkxPSI0Ny42NzkxIiB4Mj0iNDEuNTAzOSIgeTI9IjExLjY4MzciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmNjOTM0Ii8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZiYmMwNCIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9IjI2LjU5ODEiIHkxPSI0Ni41MDE1IiB4Mj0iNS44MTYxIiB5Mj0iMTAuNTA2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzFlOGUzZSIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMzNGE4NTMiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICAKICAgIDxwYXRoIGlkPSJwIiBkPSJNMTMuNjA4NiAzMC4wMDMxIDMuMjE4IDEyLjAwNkEyMy45OTQgMjMuOTk0IDAgMCAwIDI0LjAwMjUgNDhsMTAuMzkwNi0xNy45OTcxLS4wMDY3LS4wMDY4YTExLjk4NTIgMTEuOTg1MiAwIDAgMS0yMC43Nzc4LjAwN1oiLz4KICA8L2RlZnM+CiAgCiAgPHVzZSB4bGluazpocmVmPSIjcCIgZmlsbD0idXJsKCNhKSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDI0IDI0KSIvPgogIDx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGw9InVybCgjYikiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgMjQgMjQpIi8+CiAgPHVzZSB4bGluazpocmVmPSIjcCIgZmlsbD0idXJsKCNjKSIvPgogIAogIDxjaXJjbGUgY3g9IjI0IiBjeT0iMjQiIHI9IjEyIiBzdHlsZT0iZmlsbDojZmZmIi8+CiAgPGNpcmNsZSBjeD0iMjQiIGN5PSIyNCIgcj0iOS41IiBzdHlsZT0iZmlsbDojMWE3M2U4Ii8+Cjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNDggNDgiPgogIDxkZWZzPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMy4yMTczIiB5MT0iMTUiIHgyPSI0NC43ODEyIiB5Mj0iMTUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZDkzMDI1Ii8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2VhNDMzNSIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9IjIwLjcyMTkiIHkxPSI0Ny42NzkxIiB4Mj0iNDEuNTAzOSIgeTI9IjExLjY4MzciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmNjOTM0Ii8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZiYmMwNCIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9IjI2LjU5ODEiIHkxPSI0Ni41MDE1IiB4Mj0iNS44MTYxIiB5Mj0iMTAuNTA2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzFlOGUzZSIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMzNGE4NTMiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICAKICAgIDxwYXRoIGlkPSJwIiBkPSJNMTMuNjA4NiAzMC4wMDMxIDMuMjE4IDEyLjAwNkEyMy45OTQgMjMuOTk0IDAgMCAwIDI0LjAwMjUgNDhsMTAuMzkwNi0xNy45OTcxLS4wMDY3LS4wMDY4YTExLjk4NTIgMTEuOTg1MiAwIDAgMS0yMC43Nzc4LjAwN1oiLz4KICA8L2RlZnM+CiAgCiAgPHVzZSB4bGluazpocmVmPSIjcCIgZmlsbD0idXJsKCNhKSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDI0IDI0KSIvPgogIDx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGw9InVybCgjYikiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgMjQgMjQpIi8+CiAgPHVzZSB4bGluazpocmVmPSIjcCIgZmlsbD0idXJsKCNjKSIvPgogIAogIDxjaXJjbGUgY3g9IjI0IiBjeT0iMjQiIHI9IjEyIiBzdHlsZT0iZmlsbDojZmZmIi8+CiAgPGNpcmNsZSBjeD0iMjQiIGN5PSIyNCIgcj0iOS41IiBzdHlsZT0iZmlsbDojMWE3M2U4Ii8+Cjwvc3ZnPg==" + }, + "08987058-cadc-4b81-b6e1-30de50dcbe96": { + "name": "Windows Hello", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==" + }, + "9ddd1817-af5a-4672-a2b9-3e3dd95000a9": { + "name": "Windows Hello", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==" + }, + "6028b017-b1d4-4c02-b4b3-afcdafc96bb2": { + "name": "Windows Hello", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMDc4ZDQ7c3Ryb2tlLXdpZHRoOjBweDt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIyNC4yNSIgeT0iMjQuMjUiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iMTMzLjQiIHk9IjI0LjI1IiB3aWR0aD0iOTguMzUiIGhlaWdodD0iOTguMzUiLz48cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjI0LjI1IiB5PSIxMzMuNCIgd2lkdGg9Ijk4LjM1IiBoZWlnaHQ9Ijk4LjM1Ii8+PHJlY3QgY2xhc3M9ImNscy0xIiB4PSIxMzMuNCIgeT0iMTMzLjQiIHdpZHRoPSI5OC4zNSIgaGVpZ2h0PSI5OC4zNSIvPjwvc3ZnPg==" + }, + "dd4ec289-e01d-41c9-bb89-70fa845d4bf2": { + "name": "iCloud Keychain (Managed)", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBmaWxsPSJub25lIj48cGF0aCBkPSJtMjE3LjM2LDkwLjY5Yy0xNS41OCw5LjU0LTI1LjE3LDI2LjQxLTI1LjM4LDQ0LjY4LjA2LDIwLjY3LDEyLjQzLDM5LjMyLDMxLjQ2LDQ3LjQxLTMuNjcsMTEuODQtOS4xLDIzLjA2LTE2LjExLDMzLjI4LTEwLjAzLDE0LjQ0LTIwLjUyLDI4Ljg3LTM2LjQ3LDI4Ljg3cy0yMC4wNi05LjI3LTM4LjQ1LTkuMjctMjQuMzIsOS41Ny0zOC45LDkuNTctMjQuNzctMTMuMzctMzYuNDctMjkuNzljLTE1LjQ2LTIyLjk5LTIzLjk1LTQ5Ljk2LTI0LjQ3LTc3LjY2LDAtNDUuNTksMjkuNjMtNjkuNzUsNTguODEtNjkuNzUsMTUuNSwwLDI4LjQyLDEwLjE4LDM4LjE1LDEwLjE4czIzLjcxLTEwLjc5LDQxLjM0LTEwLjc5YzE4LjQxLS40NywzNS44NCw4LjI0LDQ2LjUsMjMuMjVabS01NC44Ni00Mi41NWM3Ljc3LTkuMTQsMTIuMTctMjAuNjcsMTIuNDYtMzIuNjcuMDEtMS41OC0uMTQtMy4xNi0uNDYtNC43MS0xMy4zNSwxLjMtMjUuNjksNy42Ny0zNC41LDE3Ljc4LTcuODUsOC43OC0xMi40MSwyMC0xMi45MiwzMS43NiwwLDEuNDMuMTYsMi44Ni40Niw0LjI2LDEuMDUuMiwyLjEyLjMsMy4xOS4zLDEyLjQzLS45OSwyMy45MS03LjA0LDMxLjc2LTE2LjczWiIgZmlsbD0iI0ZGRiIvPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBmaWxsPSJub25lIj48cGF0aCBkPSJtMjE3LjM2LDkwLjY5Yy0xNS41OCw5LjU0LTI1LjE3LDI2LjQxLTI1LjM4LDQ0LjY4LjA2LDIwLjY3LDEyLjQzLDM5LjMyLDMxLjQ2LDQ3LjQxLTMuNjcsMTEuODQtOS4xLDIzLjA2LTE2LjExLDMzLjI4LTEwLjAzLDE0LjQ0LTIwLjUyLDI4Ljg3LTM2LjQ3LDI4Ljg3cy0yMC4wNi05LjI3LTM4LjQ1LTkuMjctMjQuMzIsOS41Ny0zOC45LDkuNTctMjQuNzctMTMuMzctMzYuNDctMjkuNzljLTE1LjQ2LTIyLjk5LTIzLjk1LTQ5Ljk2LTI0LjQ3LTc3LjY2LDAtNDUuNTksMjkuNjMtNjkuNzUsNTguODEtNjkuNzUsMTUuNSwwLDI4LjQyLDEwLjE4LDM4LjE1LDEwLjE4czIzLjcxLTEwLjc5LDQxLjM0LTEwLjc5YzE4LjQxLS40NywzNS44NCw4LjI0LDQ2LjUsMjMuMjVabS01NC44Ni00Mi41NWM3Ljc3LTkuMTQsMTIuMTctMjAuNjcsMTIuNDYtMzIuNjcuMDEtMS41OC0uMTQtMy4xNi0uNDYtNC43MS0xMy4zNSwxLjMtMjUuNjksNy42Ny0zNC41LDE3Ljc4LTcuODUsOC43OC0xMi40MSwyMC0xMi45MiwzMS43NiwwLDEuNDMuMTYsMi44Ni40Niw0LjI2LDEuMDUuMiwyLjEyLjMsMy4xOS4zLDEyLjQzLS45OSwyMy45MS03LjA0LDMxLjc2LTE2LjczWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==" + }, + "531126d6-e717-415c-9320-3d9aa6981239": { + "name": "Dashlane", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0yNTcuNDc0IDM1OS4yMDlDMjU3LjQ3NCAzNTYuMTg5IDI1NC40NTQgMzUzLjE2OSAyNTAuMjE1IDM1MS45NTlMMTk5LjQxMSAzMzMuMjMxQzE5MC44OTUgMzI5LjYwMSAxODEuMjY0IDMzMy44MzEgMTgxLjI2NCAzMzkuODlWNDc1Ljc3OUMxODEuMjY0IDQ3OC44MDkgMTg0LjI4MyA0ODIuNDM4IDE4Ny4zMDMgNDgzLjY0OEwyMzkuMzI2IDUwMi4zNzZDMjQ3LjE5NSA1MDUuMzk2IDI1Ny40NzQgNTAxLjE2NiAyNTcuNDc0IDQ5NC41MDhWMzU5LjIwOVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0zNTIuNzM2IDMyMS4xMDRDMzUyLjczNiAzMTguMDg0IDM0OS43MTcgMzE1LjA2NCAzNDUuNDc3IDMxMy44NTRMMjk0LjY3NCAyOTUuMTI2QzI4Ni4xNTcgMjkxLjQ5NiAyNzYuNTI2IDI5NS43MjYgMjc2LjUyNiAzMDEuNzg1VjQzNy42NzRDMjc2LjUyNiA0NDAuNzA0IDI3OS41NDYgNDQ0LjMzMyAyODIuNTY2IDQ0NS41NDNMMzM0LjU4OSA0NjQuMjcxQzM0Mi40NTggNDY3LjI5MSAzNTIuNzM2IDQ2My4wNjEgMzUyLjczNiA0NTYuNDAzVjMyMS4xMDRaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjU3LjQ3NCAzNS4zMjExQzI1Ny40NzQgMzIuMzAxMyAyNTQuNDU0IDI5LjI4MTUgMjUwLjIxNSAyOC4wNzE3TDE5OS40MTEgOS4zNDM0M0MxOTAuODk1IDUuNzEzOTkgMTgxLjI2NCA5Ljk0MzU4IDE4MS4yNjQgMTYuMDAyMlYxNTEuODkyQzE4MS4yNjQgMTU0LjkyMSAxODQuMjgzIDE1OC41NTEgMTg3LjMwMyAxNTkuNzZMMjM5LjMyNiAxNzguNDg5QzI0Ny4xOTUgMTgxLjUwOSAyNTcuNDc0IDE3Ny4yNzkgMjU3LjQ3NCAxNzAuNjJWMzUuMzIxMVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0zNTIuNzM2IDkyLjQ3NzdDMzUyLjczNiA4OS40NTc5IDM0OS43MTcgODYuNDM4MiAzNDUuNDc3IDg1LjIyODNMMjk0LjY3NCA2Ni41QzI4Ni4xNTcgNjIuODcwNiAyNzYuNTI2IDY3LjEwMDIgMjc2LjUyNiA3My4xNTg4VjIwOS4wNDhDMjc2LjUyNiAyMTIuMDc4IDI3OS41NDYgMjE1LjcwNyAyODIuNTY2IDIxNi45MTdMMzM0LjU4OSAyMzUuNjQ1QzM0Mi40NTggMjM4LjY2NSAzNTIuNzM2IDIzNC40MzYgMzUyLjczNiAyMjcuNzc3VjkyLjQ3NzdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNDQ4IDE2OC42ODdDNDQ4IDE2NS42NjcgNDQ0Ljk4IDE2Mi42NDcgNDQwLjc0MSAxNjEuNDM3TDM4OS45MzcgMTQyLjcwOUMzODEuNDIxIDEzOS4wNzkgMzcxLjc5IDE0My4zMDkgMzcxLjc5IDE0OS4zNjhWMzYxLjQ2NkMzNzEuNzkgMzY0LjQ5NSAzNzQuODEgMzY4LjEyNSAzNzcuODI5IDM2OS4zMzVMNDI5Ljg1MiAzODguMDYzQzQzNy43MjEgMzkxLjA4MyA0NDggMzg2Ljg1MyA0NDggMzgwLjE5NFYxNjguNjg3WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTE2Mi4yMSAzNS4zMzA2QzE2Mi4yMSAzMi4zMTA4IDE1OS4xOSAyOS4yODE1IDE1NC45NTEgMjguMDcxN0wxMDQuMTQ4IDkuMzQzNDNDOTUuNjc4NyA1LjcxMzk5IDg2IDkuOTQzNTggODYgMTYuMDAyMlY0NzUuNzg5Qzg2IDQ3OC44MDggODkuMDE5OCA0ODIuNDM4IDkyLjA0OTIgNDgzLjY0OEwxNDQuMDYzIDUwMi4zNzZDMTUxLjkzMSA1MDUuMzk2IDE2Mi4yMSA1MDEuMTY2IDE2Mi4yMSA0OTQuNTA3VjM1LjMzMDZaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0yNTcuNDc0IDM1OS4yMDlDMjU3LjQ3NCAzNTYuMTg5IDI1NC40NTQgMzUzLjE2OSAyNTAuMjE1IDM1MS45NTlMMTk5LjQxMSAzMzMuMjMxQzE5MC44OTUgMzI5LjYwMSAxODEuMjY0IDMzMy44MzEgMTgxLjI2NCAzMzkuODlWNDc1Ljc3OUMxODEuMjY0IDQ3OC44MDkgMTg0LjI4MyA0ODIuNDM4IDE4Ny4zMDMgNDgzLjY0OEwyMzkuMzI2IDUwMi4zNzZDMjQ3LjE5NSA1MDUuMzk2IDI1Ny40NzQgNTAxLjE2NiAyNTcuNDc0IDQ5NC41MDhWMzU5LjIwOVoiIGZpbGw9IiMwOTM2M0YiLz4KPHBhdGggZD0iTTM1Mi43MzYgMzIxLjEwM0MzNTIuNzM2IDMxOC4wODQgMzQ5LjcxNyAzMTUuMDY0IDM0NS40NzcgMzEzLjg1NEwyOTQuNjc0IDI5NS4xMjZDMjg2LjE1NyAyOTEuNDk2IDI3Ni41MjYgMjk1LjcyNiAyNzYuNTI2IDMwMS43ODVWNDM3LjY3NEMyNzYuNTI2IDQ0MC43MDQgMjc5LjU0NiA0NDQuMzMzIDI4Mi41NjYgNDQ1LjU0M0wzMzQuNTg5IDQ2NC4yNzFDMzQyLjQ1OCA0NjcuMjkxIDM1Mi43MzYgNDYzLjA2MSAzNTIuNzM2IDQ1Ni40MDNWMzIxLjEwM1oiIGZpbGw9IiMwOTM2M0YiLz4KPHBhdGggZD0iTTI1Ny40NzQgMzUuMzIxMUMyNTcuNDc0IDMyLjMwMTMgMjU0LjQ1NCAyOS4yODE1IDI1MC4yMTUgMjguMDcxN0wxOTkuNDExIDkuMzQzNDNDMTkwLjg5NSA1LjcxMzk5IDE4MS4yNjQgOS45NDM1OCAxODEuMjY0IDE2LjAwMjJWMTUxLjg5MkMxODEuMjY0IDE1NC45MjEgMTg0LjI4MyAxNTguNTUxIDE4Ny4zMDMgMTU5Ljc2TDIzOS4zMjYgMTc4LjQ4OUMyNDcuMTk1IDE4MS41MDggMjU3LjQ3NCAxNzcuMjc5IDI1Ny40NzQgMTcwLjYyVjM1LjMyMTFaIiBmaWxsPSIjMDkzNjNGIi8+CjxwYXRoIGQ9Ik0zNTIuNzM2IDkyLjQ3NzdDMzUyLjczNiA4OS40NTc5IDM0OS43MTcgODYuNDM4MiAzNDUuNDc3IDg1LjIyODNMMjk0LjY3NCA2Ni41QzI4Ni4xNTcgNjIuODcwNiAyNzYuNTI2IDY3LjEwMDIgMjc2LjUyNiA3My4xNTg4VjIwOS4wNDhDMjc2LjUyNiAyMTIuMDc4IDI3OS41NDYgMjE1LjcwNyAyODIuNTY2IDIxNi45MTdMMzM0LjU4OSAyMzUuNjQ1QzM0Mi40NTggMjM4LjY2NSAzNTIuNzM2IDIzNC40MzYgMzUyLjczNiAyMjcuNzc3VjkyLjQ3NzdaIiBmaWxsPSIjMDkzNjNGIi8+CjxwYXRoIGQ9Ik00NDggMTY4LjY4N0M0NDggMTY1LjY2NyA0NDQuOTggMTYyLjY0NyA0NDAuNzQxIDE2MS40MzdMMzg5LjkzNyAxNDIuNzA5QzM4MS40MjEgMTM5LjA3OSAzNzEuNzkgMTQzLjMwOSAzNzEuNzkgMTQ5LjM2OFYzNjEuNDY2QzM3MS43OSAzNjQuNDk1IDM3NC44MSAzNjguMTI1IDM3Ny44MjkgMzY5LjMzNUw0MjkuODUyIDM4OC4wNjNDNDM3LjcyMSAzOTEuMDgzIDQ0OCAzODYuODUzIDQ0OCAzODAuMTk0VjE2OC42ODdaIiBmaWxsPSIjMDkzNjNGIi8+CjxwYXRoIGQ9Ik0xNjIuMjEgMzUuMzMwNkMxNjIuMjEgMzIuMzEwOCAxNTkuMTkgMjkuMjgxNSAxNTQuOTUxIDI4LjA3MTdMMTA0LjE0OCA5LjM0MzQzQzk1LjY3ODcgNS43MTM5OSA4NiA5Ljk0MzU4IDg2IDE2LjAwMjJWNDc1Ljc4OUM4NiA0NzguODA4IDg5LjAxOTggNDgyLjQzOCA5Mi4wNDkyIDQ4My42NDhMMTQ0LjA2MyA1MDIuMzc2QzE1MS45MzEgNTA1LjM5NiAxNjIuMjEgNTAxLjE2NiAxNjIuMjEgNDk0LjUwN1YzNS4zMzA2WiIgZmlsbD0iIzA5MzYzRiIvPgo8L3N2Zz4K" + }, + "bada5566-a7aa-401f-bd96-45619a55120d": { + "name": "1Password", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQwIiBoZWlnaHQ9IjI0MCIgdmlld0JveD0iMCAwIDI0MCAyNDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjM5LjI1NyAxMjAuNDE3QzIzOS4yNTcgNTQuNDE5MyAxODUuNzU1IDAuOTE2NTA0IDExOS43NTcgMC45MTY1MDRDNTMuNzYwMSAwLjkxNjUwNCAwLjI1NzMyNCA1NC40MTkzIDAuMjU3MzI0IDEyMC40MTdDMC4yNTczMjQgMTg2LjQxNyA1My43NjAxIDIzOS45MTcgMTE5Ljc1NyAyMzkuOTE3QzE4NS43NTUgMjM5LjkxNyAyMzkuMjU3IDE4Ni40MTcgMjM5LjI1NyAxMjAuNDE3Wk05OC4wMDY5IDU0LjAyNzZDOTcuMDY3NCA1NS44NzE0IDk3LjA2NzQgNTguMjg1MSA5Ny4wNjc0IDYzLjExMjZWOTAuNDcyOUM5Ny4wNjc0IDkxLjY3ODggOTcuMDY3NCA5Mi4yODE3IDk3LjIxOTYgOTIuODM5MkM5Ny4zNTQ1IDkzLjMzMzEgOTcuNTc2MyA5My43OTkgOTcuODc0NiA5NC4yMTVDOTguMjExMyA5NC42ODQ3IDk4LjY3OTIgOTUuMDY0OCA5OS42MTUyIDk1LjgyNTFMMTA2LjUzNiAxMDEuNDQ3QzEwNy42NjQgMTAyLjM2NCAxMDguMjI4IDEwMi44MjIgMTA4LjQzMyAxMDMuMzc0QzEwOC42MTMgMTAzLjg1NyAxMDguNjEzIDEwNC4zOSAxMDguNDMzIDEwNC44NzNDMTA4LjIyOCAxMDUuNDI1IDEwNy42NjQgMTA1Ljg4MyAxMDYuNTM2IDEwNi44TDk5LjYxNTIgMTEyLjQyMkM5OC42NzkzIDExMy4xODIgOTguMjExMyAxMTMuNTYyIDk3Ljg3NDYgMTE0LjAzMkM5Ny41NzYzIDExNC40NDggOTcuMzU0NSAxMTQuOTE0IDk3LjIxOTYgMTE1LjQwOEM5Ny4wNjc0IDExNS45NjUgOTcuMDY3NCAxMTYuNTY4IDk3LjA2NzQgMTE3Ljc3NFYxNzcuNzE5Qzk3LjA2NzQgMTgyLjU0NyA5Ny4wNjc0IDE4NC45NjEgOTguMDA2OSAxODYuODA1Qzk4LjgzMzMgMTg4LjQyNiAxMDAuMTUyIDE4OS43NDUgMTAxLjc3NCAxOTAuNTcxQzEwMy42MTggMTkxLjUxMSAxMDYuMDMxIDE5MS41MTEgMTEwLjg1OSAxOTEuNTExSDEyOC42NTZDMTMzLjQ4MyAxOTEuNTExIDEzNS44OTcgMTkxLjUxMSAxMzcuNzQxIDE5MC41NzFDMTM5LjM2MyAxODkuNzQ1IDE0MC42ODEgMTg4LjQyNiAxNDEuNTA4IDE4Ni44MDVDMTQyLjQ0NyAxODQuOTYxIDE0Mi40NDcgMTgyLjU0NyAxNDIuNDQ3IDE3Ny43MTlWMTUwLjM1OUMxNDIuNDQ3IDE0OS4xNTMgMTQyLjQ0NyAxNDguNTUgMTQyLjI5NSAxNDcuOTkzQzE0Mi4xNiAxNDcuNDk5IDE0MS45MzggMTQ3LjAzMyAxNDEuNjQgMTQ2LjYxN0MxNDEuMzAzIDE0Ni4xNDcgMTQwLjgzNSAxNDUuNzY3IDEzOS44OTkgMTQ1LjAwN0wxMzIuOTc4IDEzOS4zODVDMTMxLjg1IDEzOC40NjggMTMxLjI4NiAxMzguMDEgMTMxLjA4MiAxMzcuNDU5QzEzMC45MDIgMTM2Ljk3NSAxMzAuOTAyIDEzNi40NDMgMTMxLjA4MiAxMzUuOTU5QzEzMS4yODYgMTM1LjQwNyAxMzEuODUgMTM0Ljk0OSAxMzIuOTc4IDEzNC4wMzNMMTM5Ljg5OSAxMjguNDFDMTQwLjgzNSAxMjcuNjUgMTQxLjMwMyAxMjcuMjcgMTQxLjY0IDEyNi44QzE0MS45MzggMTI2LjM4NCAxNDIuMTYgMTI1LjkxOCAxNDIuMjk1IDEyNS40MjRDMTQyLjQ0NyAxMjQuODY3IDE0Mi40NDcgMTI0LjI2NCAxNDIuNDQ3IDEyMy4wNThWNjMuMTEyNkMxNDIuNDQ3IDU4LjI4NTEgMTQyLjQ0NyA1NS44NzE0IDE0MS41MDggNTQuMDI3NkMxNDAuNjgxIDUyLjQwNTcgMTM5LjM2MyA1MS4wODcgMTM3Ljc0MSA1MC4yNjA2QzEzNS44OTcgNDkuMzIxMSAxMzMuNDgzIDQ5LjMyMTEgMTI4LjY1NiA0OS4zMjExSDExMC44NTlDMTA2LjAzMSA0OS4zMjExIDEwMy42MTggNDkuMzIxMSAxMDEuNzc0IDUwLjI2MDZDMTAwLjE1MiA1MS4wODcgOTguODMzMyA1Mi40MDU3IDk4LjAwNjkgNTQuMDI3NloiIGZpbGw9IiNGRkZFRkIiLz4KPC9zdmc+Cg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQwIiBoZWlnaHQ9IjI0MCIgdmlld0JveD0iMCAwIDI0MCAyNDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjM5LjExNiAxMjAuNDE3QzIzOS4xMTYgNTQuNDE5MyAxODUuNjEzIDAuOTE2NTA0IDExOS42MTYgMC45MTY1MDRDNTMuNjE5IDAuOTE2NTA0IDAuMTE2MjExIDU0LjQxOTMgMC4xMTYyMTEgMTIwLjQxN0MwLjExNjIxMSAxODYuNDE3IDUzLjYxOSAyMzkuOTE3IDExOS42MTYgMjM5LjkxN0MxODUuNjEzIDIzOS45MTcgMjM5LjExNiAxODYuNDE3IDIzOS4xMTYgMTIwLjQxN1pNOTcuODY1OCA1NC4wMjc2Qzk2LjkyNjMgNTUuODcxNCA5Ni45MjYzIDU4LjI4NTEgOTYuOTI2MyA2My4xMTI2VjkwLjQ3MjlDOTYuOTI2MyA5MS42Nzg4IDk2LjkyNjMgOTIuMjgxNyA5Ny4wNzg1IDkyLjgzOTJDOTcuMjEzNCA5My4zMzMxIDk3LjQzNTIgOTMuNzk5IDk3LjczMzUgOTQuMjE1Qzk4LjA3MDIgOTQuNjg0NyA5OC41MzgxIDk1LjA2NDggOTkuNDc0MSA5NS44MjUxTDEwNi4zOTUgMTAxLjQ0N0MxMDcuNTIzIDEwMi4zNjQgMTA4LjA4NyAxMDIuODIyIDEwOC4yOTIgMTAzLjM3NEMxMDguNDcxIDEwMy44NTcgMTA4LjQ3MSAxMDQuMzkgMTA4LjI5MiAxMDQuODczQzEwOC4wODcgMTA1LjQyNSAxMDcuNTIzIDEwNS44ODMgMTA2LjM5NSAxMDYuOEw5OS40NzQxIDExMi40MjJDOTguNTM4MiAxMTMuMTgyIDk4LjA3MDIgMTEzLjU2MiA5Ny43MzM1IDExNC4wMzJDOTcuNDM1MiAxMTQuNDQ4IDk3LjIxMzQgMTE0LjkxNCA5Ny4wNzg1IDExNS40MDhDOTYuOTI2MyAxMTUuOTY1IDk2LjkyNjMgMTE2LjU2OCA5Ni45MjYzIDExNy43NzRWMTc3LjcxOUM5Ni45MjYzIDE4Mi41NDcgOTYuOTI2MyAxODQuOTYxIDk3Ljg2NTggMTg2LjgwNUM5OC42OTIyIDE4OC40MjYgMTAwLjAxMSAxODkuNzQ1IDEwMS42MzMgMTkwLjU3MUMxMDMuNDc3IDE5MS41MTEgMTA1Ljg5IDE5MS41MTEgMTEwLjcxOCAxOTEuNTExSDEyOC41MTVDMTMzLjM0MiAxOTEuNTExIDEzNS43NTYgMTkxLjUxMSAxMzcuNiAxOTAuNTcxQzEzOS4yMjEgMTg5Ljc0NSAxNDAuNTQgMTg4LjQyNiAxNDEuMzY3IDE4Ni44MDVDMTQyLjMwNiAxODQuOTYxIDE0Mi4zMDYgMTgyLjU0NyAxNDIuMzA2IDE3Ny43MTlWMTUwLjM1OUMxNDIuMzA2IDE0OS4xNTMgMTQyLjMwNiAxNDguNTUgMTQyLjE1NCAxNDcuOTkzQzE0Mi4wMTkgMTQ3LjQ5OSAxNDEuNzk3IDE0Ny4wMzMgMTQxLjQ5OSAxNDYuNjE3QzE0MS4xNjIgMTQ2LjE0NyAxNDAuNjk0IDE0NS43NjcgMTM5Ljc1OCAxNDUuMDA3TDEzMi44MzcgMTM5LjM4NUMxMzEuNzA5IDEzOC40NjggMTMxLjE0NSAxMzguMDEgMTMwLjk0IDEzNy40NTlDMTMwLjc2MSAxMzYuOTc1IDEzMC43NjEgMTM2LjQ0MyAxMzAuOTQgMTM1Ljk1OUMxMzEuMTQ1IDEzNS40MDcgMTMxLjcwOSAxMzQuOTQ5IDEzMi44MzcgMTM0LjAzM0wxMzkuNzU4IDEyOC40MUMxNDAuNjk0IDEyNy42NSAxNDEuMTYyIDEyNy4yNyAxNDEuNDk5IDEyNi44QzE0MS43OTcgMTI2LjM4NCAxNDIuMDE5IDEyNS45MTggMTQyLjE1NCAxMjUuNDI0QzE0Mi4zMDYgMTI0Ljg2NyAxNDIuMzA2IDEyNC4yNjQgMTQyLjMwNiAxMjMuMDU4VjYzLjExMjZDMTQyLjMwNiA1OC4yODUxIDE0Mi4zMDYgNTUuODcxNCAxNDEuMzY3IDU0LjAyNzZDMTQwLjU0IDUyLjQwNTcgMTM5LjIyMSA1MS4wODcgMTM3LjYgNTAuMjYwNkMxMzUuNzU2IDQ5LjMyMTEgMTMzLjM0MiA0OS4zMjExIDEyOC41MTUgNDkuMzIxMUgxMTAuNzE4QzEwNS44OSA0OS4zMjExIDEwMy40NzcgNDkuMzIxMSAxMDEuNjMzIDUwLjI2MDZDMTAwLjAxMSA1MS4wODcgOTguNjkyMiA1Mi40MDU3IDk3Ljg2NTggNTQuMDI3NloiIGZpbGw9IiMxQTI4NUYiLz4KPC9zdmc+Cg==" + }, + "b84e4048-15dc-4dd0-8640-f4f60813c8af": { + "name": "NordPass", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgODAgODAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjYxMzQgNzBDMi44MjQzNSA2My4zNTIgMCA1NS4xNzIyIDAgNDYuMzI3M0MwIDI0LjA1NTIgMTcuOTA4NiA2IDQwIDZDNjIuMDkxNCA2IDgwIDI0LjA1NTIgODAgNDYuMzI3M0M4MCA1NS4xNzIxIDc3LjE3NTcgNjMuMzUxOCA3Mi4zODY3IDY5Ljk5OTlMNTMuMTc0NyAzOC41NDY2TDUxLjMxOTUgNDEuNzA0Nkw1My4yMDE4IDUwLjQ4NzdMNDAgMjcuNzE0N0wzMS44MzM0IDQxLjYxNjFMMzMuNzM0NiA1MC40ODc3TDI2LjgxNDcgMzguNTY0Nkw3LjYxMzQgNzBaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgODAgODAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjYxMzQgNzBDMi44MjQzNSA2My4zNTIgMCA1NS4xNzIyIDAgNDYuMzI3M0MwIDI0LjA1NTIgMTcuOTA4NiA2IDQwIDZDNjIuMDkxNCA2IDgwIDI0LjA1NTIgODAgNDYuMzI3M0M4MCA1NS4xNzIxIDc3LjE3NTcgNjMuMzUxOCA3Mi4zODY3IDY5Ljk5OTlMNTMuMTc0NyAzOC41NDY2TDUxLjMxOTUgNDEuNzA0Nkw1My4yMDE4IDUwLjQ4NzdMNDAgMjcuNzE0N0wzMS44MzM0IDQxLjYxNjFMMzMuNzM0NiA1MC40ODc3TDI2LjgxNDcgMzguNTY0Nkw3LjYxMzQgNzBaIiBmaWxsPSIjMENBQUFCIi8+Cjwvc3ZnPgo=" + }, + "0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6": { + "name": "Keeper", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzYwMzRfMzM2MjcpIj4KPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMTIiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0yMiAxMkMyMiAxNy41MjI4IDE3LjUyMjggMjIgMTIgMjJDNi40NzcxNSAyMiAyIDE3LjUyMjggMiAxMkMyIDYuNDc3MTUgNi40NzcxNSAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNMTAuMTIxOCAzLjI3MzI1SDExLjY2NjZWOS41MTUyN0gxNC44NTc1TDE4LjY5NiA2LjQ2MzE3TDE5LjY2MDcgNy42NjgyMUwxNS4zOTg5IDExLjA1NjRIMTAuMTIxOFYzLjI3MzI1WiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNMTMuMTQzOCAzLjQ4MzY2TDE0LjY4ODcgMy44NzY5NFY2LjAzNDkyTDE2LjQxNzMgNC42MTgxMUwxNy43MDA4IDUuNTYwOTdMMTQuNDA3IDguMjYwMTNMMTMuMTQzOCA4LjI1MzQxVjMuNDgzNjZaIiBmaWxsPSIjRkZDNzAwIi8+CjxwYXRoIGQ9Ik00LjAzODcgMTUuMDg0OUw1LjU4MzU0IDE2LjM5NThWNy44MTQyN0w0LjAzODcgOS4yMjc3MlYxNS4wODQ5WiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNOC42MTI1NyAxOC4yNDExTDcuMDY2MDQgMTkuNTgwNlY0LjQ5NDg1TDguNjEyNTcgNS44MzQzNFYxOC4yNDExWiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNMTQuNjg4NyAxOC4xMTc0TDE2LjQxNzMgMTkuNTM0MkwxNy43MDA4IDE4LjU4OTdMMTQuNDA3IDE1Ljg5MjJMMTMuMTQzOCAxNS44OTg5VjIwLjY2ODdMMTQuNjg4NyAyMC4yNzU0VjE4LjExNzRaIiBmaWxsPSIjRkZDNzAwIi8+CjxwYXRoIGQ9Ik0xOC42OTYgMTcuNDc4NkwxNC44NTc1IDE0LjQyNDhIMTEuNjY2NlYyMC42NjY4SDEwLjEyMThWMTIuODg1M0gxNS4zOTg5TDE5LjY2MDcgMTYuMjczNUwxOC42OTYgMTcuNDc4NloiIGZpbGw9IiNGRkM3MDAiLz4KPHBhdGggZD0iTTE2LjczNzYgMTEuOTcwNkwxOS44OTgxIDE0LjU3MDZMMjAuODgzIDEzLjM4MjNMMTkuMTY2MSAxMS45NzA2TDIwLjg4MyAxMC41NTg4TDE5Ljg5ODEgOS4zNzA1NkwxNi43Mzc2IDExLjk3MDZaIiBmaWxsPSIjRkZDNzAwIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfNjAzNF8zMzYyNyI+CjxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzYwMzRfMzM2MjcpIj4KPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMTIiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0yMiAxMkMyMiAxNy41MjI4IDE3LjUyMjggMjIgMTIgMjJDNi40NzcxNSAyMiAyIDE3LjUyMjggMiAxMkMyIDYuNDc3MTUgNi40NzcxNSAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNMTAuMTIxOCAzLjI3MzI1SDExLjY2NjZWOS41MTUyN0gxNC44NTc1TDE4LjY5NiA2LjQ2MzE3TDE5LjY2MDcgNy42NjgyMUwxNS4zOTg5IDExLjA1NjRIMTAuMTIxOFYzLjI3MzI1WiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNMTMuMTQzOCAzLjQ4MzY2TDE0LjY4ODcgMy44NzY5NFY2LjAzNDkyTDE2LjQxNzMgNC42MTgxMUwxNy43MDA4IDUuNTYwOTdMMTQuNDA3IDguMjYwMTNMMTMuMTQzOCA4LjI1MzQxVjMuNDgzNjZaIiBmaWxsPSIjRkZDNzAwIi8+CjxwYXRoIGQ9Ik00LjAzODcgMTUuMDg0OUw1LjU4MzU0IDE2LjM5NThWNy44MTQyN0w0LjAzODcgOS4yMjc3MlYxNS4wODQ5WiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNOC42MTI1NyAxOC4yNDExTDcuMDY2MDQgMTkuNTgwNlY0LjQ5NDg1TDguNjEyNTcgNS44MzQzNFYxOC4yNDExWiIgZmlsbD0iI0ZGQzcwMCIvPgo8cGF0aCBkPSJNMTQuNjg4NyAxOC4xMTc0TDE2LjQxNzMgMTkuNTM0MkwxNy43MDA4IDE4LjU4OTdMMTQuNDA3IDE1Ljg5MjJMMTMuMTQzOCAxNS44OTg5VjIwLjY2ODdMMTQuNjg4NyAyMC4yNzU0VjE4LjExNzRaIiBmaWxsPSIjRkZDNzAwIi8+CjxwYXRoIGQ9Ik0xOC42OTYgMTcuNDc4NkwxNC44NTc1IDE0LjQyNDhIMTEuNjY2NlYyMC42NjY4SDEwLjEyMThWMTIuODg1M0gxNS4zOTg5TDE5LjY2MDcgMTYuMjczNUwxOC42OTYgMTcuNDc4NloiIGZpbGw9IiNGRkM3MDAiLz4KPHBhdGggZD0iTTE2LjczNzYgMTEuOTcwNkwxOS44OTgxIDE0LjU3MDZMMjAuODgzIDEzLjM4MjNMMTkuMTY2MSAxMS45NzA2TDIwLjg4MyAxMC41NTg4TDE5Ljg5ODEgOS4zNzA1NkwxNi43Mzc2IDExLjk3MDZaIiBmaWxsPSIjRkZDNzAwIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfNjAzNF8zMzYyNyI+CjxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K" + }, + "f3809540-7f14-49c1-a8b3-8f813b225541": { + "name": "Enpass", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0yNTYuNDgzIDI4LjA1NTRDMzEzLjg5OSAyOC4wNTU0IDM3MS4zMTUgMjcuODg1NiA0MjguNzQ1IDI4LjE0MDVDNDQwLjY4IDI3LjkwNzYgNDUyLjUyMSAzMC4yODg5IDQ2My40NDEgMzUuMTE3OUM0NzQuMzYyIDM5Ljk0NjkgNDg0LjA5OSA0Ny4xMDczIDQ5MS45NzEgNTYuMDk4NEM1MDQuMDYyIDY5LjY5NjIgNTExLjEzMiA4Ny4wMzg3IDUxMiAxMDUuMjNDNTEyLjAyOCAxMjEuOTMzIDUxMC4wMzUgMTM4LjU3OCA1MDYuMDYzIDE1NC44MDFDNDk4LjQ0NCAxOTguNzA2IDQ5MC41MTUgMjQyLjUyNyA0ODIuNzI2IDI4Ni4zNzZDNDc2LjAxMiAzMjQuMTM0IDQ2OS41ODEgMzYxLjk1IDQ2Mi41MTMgMzk5LjY4QzQ1Ny42NzIgNDIwLjk2OSA0NDYuNTQ1IDQ0MC4zMDMgNDMwLjU4IDQ1NS4xNjVDNDE0LjYxNiA0NzAuMDI3IDM5NC41NTUgNDc5LjcyNyAzNzMuMDExIDQ4My4wMDJDMzY3Ljc1MiA0ODMuNjI5IDM2Mi40NjIgNDgzLjk0NiAzNTcuMTY2IDQ4My45NUMyOTAuMDUzIDQ4NC4wMTcgMjIyLjk0IDQ4NC4wMTcgMTU1LjgyOCA0ODMuOTVDMTMwLjQ2NiA0ODMuOSAxMDUuOTMgNDc0LjkxNSA4Ni41MTMyIDQ1OC41NjZDNjcuMDk2NSA0NDIuMjE4IDU0LjAzNjIgNDE5LjU0OCA0OS42MTggMzk0LjUyNUMzNi4xODA0IDMxOS4xNzcgMjIuNjI5NyAyNDMuODUzIDguOTY1OTcgMTY4LjU1M0M2LjI4MDM0IDE1My42MzkgMy4zMTIgMTM4LjgxMSAxLjIwNTkgMTIzLjc4NEMtMi40NjEwNSAxMDIuNzI5IDIuMzEwOTMgODEuMDc0NCAxNC40ODUyIDYzLjUyNDRDMjYuNjU5NiA0NS45NzQ1IDQ1LjI1MjkgMzMuOTQ2MiA2Ni4yMjY2IDMwLjA1MjVDNzMuMDU1NyAyOC43NDUxIDc5Ljk5NTkgMjguMTA5NCA4Ni45NDg0IDI4LjE1NDZDMTQzLjQ2IDI3Ljk5NDEgMTk5Ljk3MSAyNy45NjEgMjU2LjQ4MyAyOC4wNTU0Wk0yMTAuOTI2IDMzOS42NDNDMjEwLjkyNiAzNTQuNjcgMjEwLjkyNiAzNjkuNjk3IDIxMC45MjYgMzg0LjczOEMyMTAuNzczIDM4OC4yMDUgMjExLjM0MyAzOTEuNjY1IDIxMi41OTcgMzk0Ljg5OUMyMTMuODUyIDM5OC4xMzQgMjE1Ljc2NCA0MDEuMDcxIDIxOC4yMTMgNDAzLjUyNUMyMjAuNjYyIDQwNS45NzkgMjIzLjU5MyA0MDcuODk1IDIyNi44MjEgNDA5LjE1MkMyMzAuMDQ5IDQxMC40MDkgMjMzLjUwMyA0MTAuOTc5IDIzNi45NjIgNDEwLjgyNkMyNDkuMzg3IDQxMC44MjYgMjYxLjgxMiA0MTAuODI2IDI3NC4yMzYgNDEwLjgyNkMyNzcuOTIyIDQxMS4xODMgMjgxLjY0MiA0MTAuNzE3IDI4NS4xMjcgNDA5LjQ2MkMyODguNjEyIDQwOC4yMDggMjkxLjc3NyA0MDYuMTk2IDI5NC4zOTQgNDAzLjU3QzI5Ny4wMTIgNDAwLjk0NSAyOTkuMDE3IDM5Ny43NzIgMzAwLjI2NSAzOTQuMjc4QzMwMS41MTQgMzkwLjc4NSAzMDEuOTc1IDM4Ny4wNTggMzAxLjYxNSAzODMuMzY0QzMwMS42MTUgMzUzLjkxOSAzMDEuNjE2IDMyNC40NiAzMDEuNDc0IDI5NS4wMTVDMzAxLjMxMSAyOTMuMzMxIDMwMS42NyAyOTEuNjM3IDMwMi41MDIgMjkwLjE2NUMzMDMuMzM0IDI4OC42OTIgMzA0LjU5OSAyODcuNTEyIDMwNi4xMjUgMjg2Ljc4NkMzMjMuNzkgMjc2LjI5OCAzMzcuNTUxIDI2MC4zMTQgMzQ1LjMxMyAyNDEuMjY2QzM1My4wNzUgMjIyLjIxOSAzNTQuNDEzIDIwMS4xNTEgMzQ5LjEyMyAxODEuMjcyQzM0Mi4zNTYgMTU2Ljg1MyAzMjYuMjg2IDEzNi4wNzUgMzA0LjM3NiAxMjMuNDE0QzI4Mi40NjYgMTEwLjc1NCAyNTYuNDY5IDEwNy4yMjUgMjMxLjk4NyAxMTMuNTg2QzIxNy42NjkgMTE2LjU0NCAyMDQuMjg5IDEyMi45NTkgMTkzLjAwNyAxMzIuMjc0QzE4MS43MjYgMTQxLjU4OCAxNzIuODg0IDE1My41MjIgMTY3LjI0OSAxNjcuMDM4QzE1OS4wMjcgMTg4LjY4NiAxNTguNTQ4IDIxMi41MjEgMTY1Ljg5MyAyMzQuNDg0QzE3My4yMzggMjU2LjQ0NyAxODcuOTU0IDI3NS4xODEgMjA3LjUzMyAyODcuNDk1QzIwOC42NyAyODguMDM4IDIwOS42MTMgMjg4LjkxNyAyMTAuMjM3IDI5MC4wMTNDMjEwLjg2MSAyOTEuMTA5IDIxMS4xMzYgMjkyLjM3IDIxMS4wMjUgMjkzLjYyN0MyMTAuODQxIDMwOS4wMDggMjEwLjkyNiAzMjQuMzMzIDIxMC45MjYgMzM5LjY3MVYzMzkuNjQzWiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0yNTYuNDgzIDI4LjA1NTRDMzEzLjg5OSAyOC4wNTU0IDM3MS4zMTUgMjcuODg1NiA0MjguNzQ1IDI4LjE0MDVDNDQwLjY4IDI3LjkwNzYgNDUyLjUyMSAzMC4yODg5IDQ2My40NDEgMzUuMTE3OUM0NzQuMzYyIDM5Ljk0NjkgNDg0LjA5OSA0Ny4xMDczIDQ5MS45NzEgNTYuMDk4NEM1MDQuMDYyIDY5LjY5NjIgNTExLjEzMiA4Ny4wMzg3IDUxMiAxMDUuMjNDNTEyLjAyOCAxMjEuOTMzIDUxMC4wMzUgMTM4LjU3OCA1MDYuMDYzIDE1NC44MDFDNDk4LjQ0NCAxOTguNzA2IDQ5MC41MTUgMjQyLjUyNyA0ODIuNzI2IDI4Ni4zNzZDNDc2LjAxMiAzMjQuMTM0IDQ2OS41ODEgMzYxLjk1IDQ2Mi41MTMgMzk5LjY4QzQ1Ny42NzIgNDIwLjk2OSA0NDYuNTQ1IDQ0MC4zMDMgNDMwLjU4IDQ1NS4xNjVDNDE0LjYxNiA0NzAuMDI3IDM5NC41NTUgNDc5LjcyNyAzNzMuMDExIDQ4My4wMDJDMzY3Ljc1MiA0ODMuNjI5IDM2Mi40NjIgNDgzLjk0NiAzNTcuMTY2IDQ4My45NUMyOTAuMDUzIDQ4NC4wMTcgMjIyLjk0IDQ4NC4wMTcgMTU1LjgyOCA0ODMuOTVDMTMwLjQ2NiA0ODMuOSAxMDUuOTMgNDc0LjkxNSA4Ni41MTMyIDQ1OC41NjZDNjcuMDk2NSA0NDIuMjE4IDU0LjAzNjIgNDE5LjU0OCA0OS42MTggMzk0LjUyNUMzNi4xODA0IDMxOS4xNzcgMjIuNjI5NyAyNDMuODUzIDguOTY1OTcgMTY4LjU1M0M2LjI4MDM0IDE1My42MzkgMy4zMTIgMTM4LjgxMSAxLjIwNTkgMTIzLjc4NEMtMi40NjEwNSAxMDIuNzI5IDIuMzEwOTMgODEuMDc0NCAxNC40ODUyIDYzLjUyNDRDMjYuNjU5NiA0NS45NzQ1IDQ1LjI1MjkgMzMuOTQ2MiA2Ni4yMjY2IDMwLjA1MjVDNzMuMDU1NyAyOC43NDUxIDc5Ljk5NTkgMjguMTA5NCA4Ni45NDg0IDI4LjE1NDZDMTQzLjQ2IDI3Ljk5NDEgMTk5Ljk3MSAyNy45NjEgMjU2LjQ4MyAyOC4wNTU0Wk0yMTAuOTI2IDMzOS42NDNDMjEwLjkyNiAzNTQuNjcgMjEwLjkyNiAzNjkuNjk3IDIxMC45MjYgMzg0LjczOEMyMTAuNzczIDM4OC4yMDUgMjExLjM0MyAzOTEuNjY1IDIxMi41OTcgMzk0Ljg5OUMyMTMuODUyIDM5OC4xMzQgMjE1Ljc2NCA0MDEuMDcxIDIxOC4yMTMgNDAzLjUyNUMyMjAuNjYyIDQwNS45NzkgMjIzLjU5MyA0MDcuODk1IDIyNi44MjEgNDA5LjE1MkMyMzAuMDQ5IDQxMC40MDkgMjMzLjUwMyA0MTAuOTc5IDIzNi45NjIgNDEwLjgyNkMyNDkuMzg3IDQxMC44MjYgMjYxLjgxMiA0MTAuODI2IDI3NC4yMzYgNDEwLjgyNkMyNzcuOTIyIDQxMS4xODMgMjgxLjY0MiA0MTAuNzE3IDI4NS4xMjcgNDA5LjQ2MkMyODguNjEyIDQwOC4yMDggMjkxLjc3NyA0MDYuMTk2IDI5NC4zOTQgNDAzLjU3QzI5Ny4wMTIgNDAwLjk0NSAyOTkuMDE3IDM5Ny43NzIgMzAwLjI2NSAzOTQuMjc4QzMwMS41MTQgMzkwLjc4NSAzMDEuOTc1IDM4Ny4wNTggMzAxLjYxNSAzODMuMzY0QzMwMS42MTUgMzUzLjkxOSAzMDEuNjE2IDMyNC40NiAzMDEuNDc0IDI5NS4wMTVDMzAxLjMxMSAyOTMuMzMxIDMwMS42NyAyOTEuNjM3IDMwMi41MDIgMjkwLjE2NUMzMDMuMzM0IDI4OC42OTIgMzA0LjU5OSAyODcuNTEyIDMwNi4xMjUgMjg2Ljc4NkMzMjMuNzkgMjc2LjI5OCAzMzcuNTUxIDI2MC4zMTQgMzQ1LjMxMyAyNDEuMjY2QzM1My4wNzUgMjIyLjIxOSAzNTQuNDEzIDIwMS4xNTEgMzQ5LjEyMyAxODEuMjcyQzM0Mi4zNTYgMTU2Ljg1MyAzMjYuMjg2IDEzNi4wNzUgMzA0LjM3NiAxMjMuNDE0QzI4Mi40NjYgMTEwLjc1NCAyNTYuNDY5IDEwNy4yMjUgMjMxLjk4NyAxMTMuNTg2QzIxNy42NjkgMTE2LjU0NCAyMDQuMjg5IDEyMi45NTkgMTkzLjAwNyAxMzIuMjc0QzE4MS43MjYgMTQxLjU4OCAxNzIuODg0IDE1My41MjIgMTY3LjI0OSAxNjcuMDM4QzE1OS4wMjcgMTg4LjY4NiAxNTguNTQ4IDIxMi41MjEgMTY1Ljg5MyAyMzQuNDg0QzE3My4yMzggMjU2LjQ0NyAxODcuOTU0IDI3NS4xODEgMjA3LjUzMyAyODcuNDk1QzIwOC42NyAyODguMDM4IDIwOS42MTMgMjg4LjkxNyAyMTAuMjM3IDI5MC4wMTNDMjEwLjg2MSAyOTEuMTA5IDIxMS4xMzYgMjkyLjM3IDIxMS4wMjUgMjkzLjYyN0MyMTAuODQxIDMwOS4wMDggMjEwLjkyNiAzMjQuMzMzIDIxMC45MjYgMzM5LjY3MVYzMzkuNjQzWiIgZmlsbD0iIzBEMzM4RiIvPgo8L3N2Zz4K" + }, + "b5397666-4885-aa6b-cebf-e52262a439a2": { + "name": "Chromium Browser" + }, + "771b48fd-d3d4-4f74-9232-fc157ab0507a": { + "name": "Edge on Mac", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOnVybCgjbGluZWFyLWdyYWRpZW50KTt9LmNscy0ye29wYWNpdHk6MC4zNTtmaWxsOnVybCgjcmFkaWFsLWdyYWRpZW50KTt9LmNscy0yLC5jbHMtNHtpc29sYXRpb246aXNvbGF0ZTt9LmNscy0ze2ZpbGw6dXJsKCNsaW5lYXItZ3JhZGllbnQtMik7fS5jbHMtNHtvcGFjaXR5OjAuNDE7ZmlsbDp1cmwoI3JhZGlhbC1ncmFkaWVudC0yKTt9LmNscy01e2ZpbGw6dXJsKCNyYWRpYWwtZ3JhZGllbnQtMyk7fS5jbHMtNntmaWxsOnVybCgjcmFkaWFsLWdyYWRpZW50LTQpO308L3N0eWxlPjxsaW5lYXJHcmFkaWVudCBpZD0ibGluZWFyLWdyYWRpZW50IiB4MT0iNjMuMzMiIHkxPSI4NC4wMyIgeDI9IjI0MS42NyIgeTI9Ijg0LjAzIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIC0xLCAwLCAyNjYpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMGM1OWE0Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMTE0YThiIi8+PC9saW5lYXJHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudCIgY3g9IjE2MS44MyIgY3k9IjY4LjkxIiByPSI5NS4zOCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAtMC45NSwgMCwgMjQ4Ljg0KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMC43MiIgc3RvcC1vcGFjaXR5PSIwIi8+PHN0b3Agb2Zmc2V0PSIwLjk1IiBzdG9wLW9wYWNpdHk9IjAuNTMiLz48c3RvcCBvZmZzZXQ9IjEiLz48L3JhZGlhbEdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0ibGluZWFyLWdyYWRpZW50LTIiIHgxPSIxNTcuMzUiIHkxPSIxNjEuMzkiIHgyPSI0NS45NiIgeTI9IjQwLjA2IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIC0xLCAwLCAyNjYpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMWI5ZGUyIi8+PHN0b3Agb2Zmc2V0PSIwLjE2IiBzdG9wLWNvbG9yPSIjMTU5NWRmIi8+PHN0b3Agb2Zmc2V0PSIwLjY3IiBzdG9wLWNvbG9yPSIjMDY4MGQ3Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDA3OGQ0Ii8+PC9saW5lYXJHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudC0yIiBjeD0iLTM0MC4yOSIgY3k9IjYyLjk5IiByPSIxNDMuMjQiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMC4xNSwgLTAuOTksIC0wLjgsIC0wLjEyLCAxNzYuNjQsIC0xMjUuNCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAuNzYiIHN0b3Atb3BhY2l0eT0iMCIvPjxzdG9wIG9mZnNldD0iMC45NSIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjEiLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0icmFkaWFsLWdyYWRpZW50LTMiIGN4PSIxMTMuMzciIGN5PSI1NzAuMjEiIHI9IjIwMi40MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgtMC4wNCwgMSwgMi4xMywgMC4wOCwgLTExNzkuNTQsIC0xMDYuNjkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMzVjMWYxIi8+PHN0b3Agb2Zmc2V0PSIwLjExIiBzdG9wLWNvbG9yPSIjMzRjMWVkIi8+PHN0b3Agb2Zmc2V0PSIwLjIzIiBzdG9wLWNvbG9yPSIjMmZjMmRmIi8+PHN0b3Agb2Zmc2V0PSIwLjMxIiBzdG9wLWNvbG9yPSIjMmJjM2QyIi8+PHN0b3Agb2Zmc2V0PSIwLjY3IiBzdG9wLWNvbG9yPSIjMzZjNzUyIi8+PC9yYWRpYWxHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudC00IiBjeD0iMzc2LjUyIiBjeT0iNTY3Ljk3IiByPSI5Ny4zNCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgwLjI4LCAwLjk2LCAwLjc4LCAtMC4yMywgLTMwMy43NiwgLTE0OC41KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzY2ZWI2ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzY2ZWI2ZSIgc3RvcC1vcGFjaXR5PSIwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHRpdGxlPkVkZ2VfTG9nb18yNjV4MjY1PC90aXRsZT48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMzUuNjgsMTk1LjQ2YTkzLjczLDkzLjczLDAsMCwxLTEwLjU0LDQuNzEsMTAxLjg3LDEwMS44NywwLDAsMS0zNS45LDYuNDZjLTQ3LjMyLDAtODguNTQtMzIuNTUtODguNTQtNzQuMzJBMzEuNDgsMzEuNDgsMCwwLDEsMTE3LjEzLDEwNWMtNDIuOCwxLjgtNTMuOCw0Ni40LTUzLjgsNzIuNTMsMCw3My44OCw2OC4wOSw4MS4zNyw4Mi43Niw4MS4zNyw3LjkxLDAsMTkuODQtMi4zLDI3LTQuNTZsMS4zMS0uNDRBMTI4LjM0LDEyOC4zNCwwLDAsMCwyNDEsMjAxLjEsNCw0LDAsMCwwLDIzNS42OCwxOTUuNDZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMzUuNjgsMTk1LjQ2YTkzLjczLDkzLjczLDAsMCwxLTEwLjU0LDQuNzEsMTAxLjg3LDEwMS44NywwLDAsMS0zNS45LDYuNDZjLTQ3LjMyLDAtODguNTQtMzIuNTUtODguNTQtNzQuMzJBMzEuNDgsMzEuNDgsMCwwLDEsMTE3LjEzLDEwNWMtNDIuOCwxLjgtNTMuOCw0Ni40LTUzLjgsNzIuNTMsMCw3My44OCw2OC4wOSw4MS4zNyw4Mi43Niw4MS4zNyw3LjkxLDAsMTkuODQtMi4zLDI3LTQuNTZsMS4zMS0uNDRBMTI4LjM0LDEyOC4zNCwwLDAsMCwyNDEsMjAxLjEsNCw0LDAsMCwwLDIzNS42OCwxOTUuNDZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMTAuMzQsMjQ2LjM0QTc5LjIsNzkuMiwwLDAsMSw4Ny42LDIyNSw4MC43Miw4MC43MiwwLDAsMSwxMTcuMTMsMTA1YzMuMTItMS40Nyw4LjQ1LTQuMTMsMTUuNTQtNGEzMi4zNSwzMi4zNSwwLDAsMSwyNS42OSwxMywzMS44OCwzMS44OCwwLDAsMSw2LjM2LDE4LjY2YzAtLjIxLDI0LjQ2LTc5LjYtODAtNzkuNi00My45LDAtODAsNDEuNjYtODAsNzguMjFhMTMwLjE1LDEzMC4xNSwwLDAsMCwxMi4xMSw1NiwxMjgsMTI4LDAsMCwwLDE1Ni4zOCw2Ny4xMSw3NS41NSw3NS41NSwwLDAsMS02Mi43OC04WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQuNjMgLTQuOTIpIi8+PHBhdGggY2xhc3M9ImNscy00IiBkPSJNMTEwLjM0LDI0Ni4zNEE3OS4yLDc5LjIsMCwwLDEsODcuNiwyMjUsODAuNzIsODAuNzIsMCwwLDEsMTE3LjEzLDEwNWMzLjEyLTEuNDcsOC40NS00LjEzLDE1LjU0LTRhMzIuMzUsMzIuMzUsMCwwLDEsMjUuNjksMTMsMzEuODgsMzEuODgsMCwwLDEsNi4zNiwxOC42NmMwLS4yMSwyNC40Ni03OS42LTgwLTc5LjYtNDMuOSwwLTgwLDQxLjY2LTgwLDc4LjIxYTEzMC4xNSwxMzAuMTUsMCwwLDAsMTIuMTEsNTYsMTI4LDEyOCwwLDAsMCwxNTYuMzgsNjcuMTEsNzUuNTUsNzUuNTUsMCwwLDEtNjIuNzgtOFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00LjYzIC00LjkyKSIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTE1Ni45NCwxNTMuNzhjLS44MSwxLjA1LTMuMywyLjUtMy4zLDUuNjYsMCwyLjYxLDEuNyw1LjEyLDQuNzIsNy4yMywxNC4zOCwxMCw0MS40OSw4LjY4LDQxLjU2LDguNjhBNTkuNTYsNTkuNTYsMCwwLDAsMjMwLjE5LDE2N2E2MS4zOCw2MS4zOCwwLDAsMCwzMC40My01Mi44OGMuMjYtMjIuNDEtOC0zNy4zMS0xMS4zNC00My45MUMyMjguMDksMjguNzYsMTgyLjM1LDQuOTIsMTMyLjYxLDQuOTJhMTI4LDEyOCwwLDAsMC0xMjgsMTI2LjJjLjQ4LTM2LjU0LDM2LjgtNjYuMDUsODAtNjYuMDUsMy41LDAsMjMuNDYuMzQsNDIsMTAuMDcsMTYuMzQsOC41OCwyNC45LDE4Ljk0LDMwLjg1LDI5LjIxLDYuMTgsMTAuNjcsNy4yOCwyNC4xNSw3LjI4LDI5LjUyUzE2MiwxNDcuMiwxNTYuOTQsMTUzLjc4WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQuNjMgLTQuOTIpIi8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTU2Ljk0LDE1My43OGMtLjgxLDEuMDUtMy4zLDIuNS0zLjMsNS42NiwwLDIuNjEsMS43LDUuMTIsNC43Miw3LjIzLDE0LjM4LDEwLDQxLjQ5LDguNjgsNDEuNTYsOC42OEE1OS41Niw1OS41NiwwLDAsMCwyMzAuMTksMTY3YTYxLjM4LDYxLjM4LDAsMCwwLDMwLjQzLTUyLjg4Yy4yNi0yMi40MS04LTM3LjMxLTExLjM0LTQzLjkxQzIyOC4wOSwyOC43NiwxODIuMzUsNC45MiwxMzIuNjEsNC45MmExMjgsMTI4LDAsMCwwLTEyOCwxMjYuMmMuNDgtMzYuNTQsMzYuOC02Ni4wNSw4MC02Ni4wNSwzLjUsMCwyMy40Ni4zNCw0MiwxMC4wNywxNi4zNCw4LjU4LDI0LjksMTguOTQsMzAuODUsMjkuMjEsNi4xOCwxMC42Nyw3LjI4LDI0LjE1LDcuMjgsMjkuNTJTMTYyLDE0Ny4yLDE1Ni45NCwxNTMuNzhaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOnVybCgjbGluZWFyLWdyYWRpZW50KTt9LmNscy0ye29wYWNpdHk6MC4zNTtmaWxsOnVybCgjcmFkaWFsLWdyYWRpZW50KTt9LmNscy0yLC5jbHMtNHtpc29sYXRpb246aXNvbGF0ZTt9LmNscy0ze2ZpbGw6dXJsKCNsaW5lYXItZ3JhZGllbnQtMik7fS5jbHMtNHtvcGFjaXR5OjAuNDE7ZmlsbDp1cmwoI3JhZGlhbC1ncmFkaWVudC0yKTt9LmNscy01e2ZpbGw6dXJsKCNyYWRpYWwtZ3JhZGllbnQtMyk7fS5jbHMtNntmaWxsOnVybCgjcmFkaWFsLWdyYWRpZW50LTQpO308L3N0eWxlPjxsaW5lYXJHcmFkaWVudCBpZD0ibGluZWFyLWdyYWRpZW50IiB4MT0iNjMuMzMiIHkxPSI4NC4wMyIgeDI9IjI0MS42NyIgeTI9Ijg0LjAzIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIC0xLCAwLCAyNjYpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMGM1OWE0Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMTE0YThiIi8+PC9saW5lYXJHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudCIgY3g9IjE2MS44MyIgY3k9IjY4LjkxIiByPSI5NS4zOCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAtMC45NSwgMCwgMjQ4Ljg0KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMC43MiIgc3RvcC1vcGFjaXR5PSIwIi8+PHN0b3Agb2Zmc2V0PSIwLjk1IiBzdG9wLW9wYWNpdHk9IjAuNTMiLz48c3RvcCBvZmZzZXQ9IjEiLz48L3JhZGlhbEdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0ibGluZWFyLWdyYWRpZW50LTIiIHgxPSIxNTcuMzUiIHkxPSIxNjEuMzkiIHgyPSI0NS45NiIgeTI9IjQwLjA2IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIC0xLCAwLCAyNjYpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMWI5ZGUyIi8+PHN0b3Agb2Zmc2V0PSIwLjE2IiBzdG9wLWNvbG9yPSIjMTU5NWRmIi8+PHN0b3Agb2Zmc2V0PSIwLjY3IiBzdG9wLWNvbG9yPSIjMDY4MGQ3Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDA3OGQ0Ii8+PC9saW5lYXJHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudC0yIiBjeD0iLTM0MC4yOSIgY3k9IjYyLjk5IiByPSIxNDMuMjQiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMC4xNSwgLTAuOTksIC0wLjgsIC0wLjEyLCAxNzYuNjQsIC0xMjUuNCkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAuNzYiIHN0b3Atb3BhY2l0eT0iMCIvPjxzdG9wIG9mZnNldD0iMC45NSIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjEiLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0icmFkaWFsLWdyYWRpZW50LTMiIGN4PSIxMTMuMzciIGN5PSI1NzAuMjEiIHI9IjIwMi40MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgtMC4wNCwgMSwgMi4xMywgMC4wOCwgLTExNzkuNTQsIC0xMDYuNjkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMzVjMWYxIi8+PHN0b3Agb2Zmc2V0PSIwLjExIiBzdG9wLWNvbG9yPSIjMzRjMWVkIi8+PHN0b3Agb2Zmc2V0PSIwLjIzIiBzdG9wLWNvbG9yPSIjMmZjMmRmIi8+PHN0b3Agb2Zmc2V0PSIwLjMxIiBzdG9wLWNvbG9yPSIjMmJjM2QyIi8+PHN0b3Agb2Zmc2V0PSIwLjY3IiBzdG9wLWNvbG9yPSIjMzZjNzUyIi8+PC9yYWRpYWxHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InJhZGlhbC1ncmFkaWVudC00IiBjeD0iMzc2LjUyIiBjeT0iNTY3Ljk3IiByPSI5Ny4zNCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgwLjI4LCAwLjk2LCAwLjc4LCAtMC4yMywgLTMwMy43NiwgLTE0OC41KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzY2ZWI2ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzY2ZWI2ZSIgc3RvcC1vcGFjaXR5PSIwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHRpdGxlPkVkZ2VfTG9nb18yNjV4MjY1PC90aXRsZT48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMzUuNjgsMTk1LjQ2YTkzLjczLDkzLjczLDAsMCwxLTEwLjU0LDQuNzEsMTAxLjg3LDEwMS44NywwLDAsMS0zNS45LDYuNDZjLTQ3LjMyLDAtODguNTQtMzIuNTUtODguNTQtNzQuMzJBMzEuNDgsMzEuNDgsMCwwLDEsMTE3LjEzLDEwNWMtNDIuOCwxLjgtNTMuOCw0Ni40LTUzLjgsNzIuNTMsMCw3My44OCw2OC4wOSw4MS4zNyw4Mi43Niw4MS4zNyw3LjkxLDAsMTkuODQtMi4zLDI3LTQuNTZsMS4zMS0uNDRBMTI4LjM0LDEyOC4zNCwwLDAsMCwyNDEsMjAxLjEsNCw0LDAsMCwwLDIzNS42OCwxOTUuNDZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMzUuNjgsMTk1LjQ2YTkzLjczLDkzLjczLDAsMCwxLTEwLjU0LDQuNzEsMTAxLjg3LDEwMS44NywwLDAsMS0zNS45LDYuNDZjLTQ3LjMyLDAtODguNTQtMzIuNTUtODguNTQtNzQuMzJBMzEuNDgsMzEuNDgsMCwwLDEsMTE3LjEzLDEwNWMtNDIuOCwxLjgtNTMuOCw0Ni40LTUzLjgsNzIuNTMsMCw3My44OCw2OC4wOSw4MS4zNyw4Mi43Niw4MS4zNyw3LjkxLDAsMTkuODQtMi4zLDI3LTQuNTZsMS4zMS0uNDRBMTI4LjM0LDEyOC4zNCwwLDAsMCwyNDEsMjAxLjEsNCw0LDAsMCwwLDIzNS42OCwxOTUuNDZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMTAuMzQsMjQ2LjM0QTc5LjIsNzkuMiwwLDAsMSw4Ny42LDIyNSw4MC43Miw4MC43MiwwLDAsMSwxMTcuMTMsMTA1YzMuMTItMS40Nyw4LjQ1LTQuMTMsMTUuNTQtNGEzMi4zNSwzMi4zNSwwLDAsMSwyNS42OSwxMywzMS44OCwzMS44OCwwLDAsMSw2LjM2LDE4LjY2YzAtLjIxLDI0LjQ2LTc5LjYtODAtNzkuNi00My45LDAtODAsNDEuNjYtODAsNzguMjFhMTMwLjE1LDEzMC4xNSwwLDAsMCwxMi4xMSw1NiwxMjgsMTI4LDAsMCwwLDE1Ni4zOCw2Ny4xMSw3NS41NSw3NS41NSwwLDAsMS02Mi43OC04WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQuNjMgLTQuOTIpIi8+PHBhdGggY2xhc3M9ImNscy00IiBkPSJNMTEwLjM0LDI0Ni4zNEE3OS4yLDc5LjIsMCwwLDEsODcuNiwyMjUsODAuNzIsODAuNzIsMCwwLDEsMTE3LjEzLDEwNWMzLjEyLTEuNDcsOC40NS00LjEzLDE1LjU0LTRhMzIuMzUsMzIuMzUsMCwwLDEsMjUuNjksMTMsMzEuODgsMzEuODgsMCwwLDEsNi4zNiwxOC42NmMwLS4yMSwyNC40Ni03OS42LTgwLTc5LjYtNDMuOSwwLTgwLDQxLjY2LTgwLDc4LjIxYTEzMC4xNSwxMzAuMTUsMCwwLDAsMTIuMTEsNTYsMTI4LDEyOCwwLDAsMCwxNTYuMzgsNjcuMTEsNzUuNTUsNzUuNTUsMCwwLDEtNjIuNzgtOFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00LjYzIC00LjkyKSIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTE1Ni45NCwxNTMuNzhjLS44MSwxLjA1LTMuMywyLjUtMy4zLDUuNjYsMCwyLjYxLDEuNyw1LjEyLDQuNzIsNy4yMywxNC4zOCwxMCw0MS40OSw4LjY4LDQxLjU2LDguNjhBNTkuNTYsNTkuNTYsMCwwLDAsMjMwLjE5LDE2N2E2MS4zOCw2MS4zOCwwLDAsMCwzMC40My01Mi44OGMuMjYtMjIuNDEtOC0zNy4zMS0xMS4zNC00My45MUMyMjguMDksMjguNzYsMTgyLjM1LDQuOTIsMTMyLjYxLDQuOTJhMTI4LDEyOCwwLDAsMC0xMjgsMTI2LjJjLjQ4LTM2LjU0LDM2LjgtNjYuMDUsODAtNjYuMDUsMy41LDAsMjMuNDYuMzQsNDIsMTAuMDcsMTYuMzQsOC41OCwyNC45LDE4Ljk0LDMwLjg1LDI5LjIxLDYuMTgsMTAuNjcsNy4yOCwyNC4xNSw3LjI4LDI5LjUyUzE2MiwxNDcuMiwxNTYuOTQsMTUzLjc4WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQuNjMgLTQuOTIpIi8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTU2Ljk0LDE1My43OGMtLjgxLDEuMDUtMy4zLDIuNS0zLjMsNS42NiwwLDIuNjEsMS43LDUuMTIsNC43Miw3LjIzLDE0LjM4LDEwLDQxLjQ5LDguNjgsNDEuNTYsOC42OEE1OS41Niw1OS41NiwwLDAsMCwyMzAuMTksMTY3YTYxLjM4LDYxLjM4LDAsMCwwLDMwLjQzLTUyLjg4Yy4yNi0yMi40MS04LTM3LjMxLTExLjM0LTQzLjkxQzIyOC4wOSwyOC43NiwxODIuMzUsNC45MiwxMzIuNjEsNC45MmExMjgsMTI4LDAsMCwwLTEyOCwxMjYuMmMuNDgtMzYuNTQsMzYuOC02Ni4wNSw4MC02Ni4wNSwzLjUsMCwyMy40Ni4zNCw0MiwxMC4wNywxNi4zNCw4LjU4LDI0LjksMTguOTQsMzAuODUsMjkuMjEsNi4xOCwxMC42Nyw3LjI4LDI0LjE1LDcuMjgsMjkuNTJTMTYyLDE0Ny4yLDE1Ni45NCwxNTMuNzhaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNC42MyAtNC45MikiLz48L3N2Zz4=" + }, + "39a5647e-1853-446c-a1f6-a79bae9f5bc7": { + "name": "IDmelon", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2YxNWI1Yzt9LmNscy0ye2ZpbGw6IzkyMWIxZDt9LmNscy0ze2ZpbGw6I2VlMzAyNTt9LmNscy00e2ZpbGw6I2JiMjAyNjt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzQxLjg3LDEwMC4ybC00LjI5LTEuNjRjLTMyLjMxLTExLjgxLTY1LjM2LTEzLjI3LTc2LjkyLTEzLjRsLS44OSwwSDEyMC4xMkEyMy40MywyMy40MywwLDAsMCwxMTEuNiw4N2MtLjQxLjIxLS44MS40Mi0xLjE3LjY0bC0xLjg1LDEuNzYsMTMzLjM1LDY1LjgsMTAzLjM4LTUyLjg5WiIvPjxsaW5lIGNsYXNzPSJjbHMtMiIgeDE9IjI5NC41OCIgeTE9IjEzNy4wNyIgeDI9IjI5Ni45OSIgeTI9IjEzOC4yNyIvPjxsaW5lIGNsYXNzPSJjbHMtMiIgeDE9IjIzOS41MyIgeTE9IjE1Mi4xMSIgeDI9IjI0MS45MyIgeTI9IjE1My4zMSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwNi43NCw5MXEtMi42Miw0LjItMi4zNSwxMS4yNnQuMjYsMTMuMzdWNDIzLjIxcTAsNS43Ni0uMjYsMTQuNDF0MS4zMSwxMi44NGExNC41NSwxNC41NSwwLDAsMCwxLjE0LDIuMTlsMTM2LTI5OS41NkwxMTAuNDMsODcuNjVBMTEuMjQsMTEuMjQsMCwwLDAsMTA2Ljc0LDkxWiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTM2MS44NiwxMTEuNTNjLTIuMzItMS41NS00LjctMy4xLTcuMTMtNC42OGE5My45Miw5My45MiwwLDAsMC0xMi02LjMyYy0uMjctLjExLS41NS0uMjMtLjgzLS4zM2wtOTksNTIuODlMMzg3LjYzLDQwMi4zMUExNjQuMDcsMTY0LjA3LDAsMCwwLDM5NywzODguMTJxMjkuODItNTEuMjEsMjkuODItMTI1YTI4NC44MywyODQuODMsMCwwLDAtNy4wOC02MS4yNSwxNjQuMTYsMTY0LjE2LDAsMCwwLTI2LjUzLTU5Ljc1LDEzNC45LDEzNC45LDAsMCwwLTkuMDUtMTEuMzhBMTUzLjIsMTUzLjIsMCwwLDAsMzYxLjg2LDExMS41M1oiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMDYuNjUsNDUyLjM0YTEwLjA3LDEwLjA3LDAsMCwwLDcuNjksNS4xOWwxLjc0LjJoMTU2YzUwLjI3LDAsODguNjQtMTguNjksMTE1LjUyLTU1LjQyTDI0Mi44OSwxNTMuMDlaIi8+PC9zdmc+", + "icon_light": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2YxNWI1Yzt9LmNscy0ye2ZpbGw6IzkyMWIxZDt9LmNscy0ze2ZpbGw6I2VlMzAyNTt9LmNscy00e2ZpbGw6I2JiMjAyNjt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzQxLjg3LDEwMC4ybC00LjI5LTEuNjRjLTMyLjMxLTExLjgxLTY1LjM2LTEzLjI3LTc2LjkyLTEzLjRsLS44OSwwSDEyMC4xMkEyMy40MywyMy40MywwLDAsMCwxMTEuNiw4N2MtLjQxLjIxLS44MS40Mi0xLjE3LjY0bC0xLjg1LDEuNzYsMTMzLjM1LDY1LjgsMTAzLjM4LTUyLjg5WiIvPjxsaW5lIGNsYXNzPSJjbHMtMiIgeDE9IjI5NC41OCIgeTE9IjEzNy4wNyIgeDI9IjI5Ni45OSIgeTI9IjEzOC4yNyIvPjxsaW5lIGNsYXNzPSJjbHMtMiIgeDE9IjIzOS41MyIgeTE9IjE1Mi4xMSIgeDI9IjI0MS45MyIgeTI9IjE1My4zMSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwNi43NCw5MXEtMi42Miw0LjItMi4zNSwxMS4yNnQuMjYsMTMuMzdWNDIzLjIxcTAsNS43Ni0uMjYsMTQuNDF0MS4zMSwxMi44NGExNC41NSwxNC41NSwwLDAsMCwxLjE0LDIuMTlsMTM2LTI5OS41NkwxMTAuNDMsODcuNjVBMTEuMjQsMTEuMjQsMCwwLDAsMTA2Ljc0LDkxWiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTM2MS44NiwxMTEuNTNjLTIuMzItMS41NS00LjctMy4xLTcuMTMtNC42OGE5My45Miw5My45MiwwLDAsMC0xMi02LjMyYy0uMjctLjExLS41NS0uMjMtLjgzLS4zM2wtOTksNTIuODlMMzg3LjYzLDQwMi4zMUExNjQuMDcsMTY0LjA3LDAsMCwwLDM5NywzODguMTJxMjkuODItNTEuMjEsMjkuODItMTI1YTI4NC44MywyODQuODMsMCwwLDAtNy4wOC02MS4yNSwxNjQuMTYsMTY0LjE2LDAsMCwwLTI2LjUzLTU5Ljc1LDEzNC45LDEzNC45LDAsMCwwLTkuMDUtMTEuMzhBMTUzLjIsMTUzLjIsMCwwLDAsMzYxLjg2LDExMS41M1oiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMDYuNjUsNDUyLjM0YTEwLjA3LDEwLjA3LDAsMCwwLDcuNjksNS4xOWwxLjc0LjJoMTU2YzUwLjI3LDAsODguNjQtMTguNjksMTE1LjUyLTU1LjQyTDI0Mi44OSwxNTMuMDlaIi8+PC9zdmc+" + }, + "d548826e-79b4-db40-a3d8-11116f7e8349": { + "name": "Bitwarden", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF82OF82MSkiPgo8cGF0aCBkPSJNMzAwIDI1My4xMjVDMzAwIDI3OS4wMjMgMjc5LjAyMyAzMDAgMjUzLjEyNSAzMDBINDYuODc1QzIwLjk3NjYgMzAwIDAgMjc5LjAyMyAwIDI1My4xMjVWNDYuODc1QzAgMjAuOTc2NiAyMC45NzY2IDAgNDYuODc1IDBIMjUzLjEyNUMyNzkuMDIzIDAgMzAwIDIwLjk3NjYgMzAwIDQ2Ljg3NVYyNTMuMTI1WiIgZmlsbD0iIzE3NUREQyIvPgo8cGF0aCBkPSJNMjQzLjEwNSAzNy42NzU4QzI0MS4yMDEgMzUuNzcxNSAyMzguOTQ1IDM0LjgzNCAyMzYuMzY3IDM0LjgzNEg2My42MzI4QzYxLjAyNTQgMzQuODM0IDU4Ljc5ODggMzUuNzcxNSA1Ni44OTQ1IDM3LjY3NThDNTQuOTkwMiAzOS41ODAxIDU0LjA1MjcgNDEuODM1OSA1NC4wNTI3IDQ0LjQxNDFWMTU5LjU4QzU0LjA1MjcgMTY4LjE2NCA1NS43MjI3IDE3Ni42ODkgNTkuMDYyNSAxODUuMTU2QzYyLjQwMjMgMTkzLjU5NCA2Ni41NjI1IDIwMS4wOTQgNzEuNTEzNyAyMDcuNjU2Qzc2LjQ2NDggMjE0LjE4OSA4Mi4zNTM1IDIyMC41NzYgODkuMjA5IDIyNi43ODdDOTYuMDY0NSAyMzIuOTk4IDEwMi4zOTMgMjM4LjEyNSAxMDguMTY0IDI0Mi4yMjdDMTEzLjk2NSAyNDYuMzI4IDEyMCAyNTAuMTk1IDEyNi4yOTkgMjUzLjg1N0MxMzIuNTk4IDI1Ny41MiAxMzcuMDggMjU5Ljk4IDEzOS43MTcgMjYxLjI3QzE0Mi4zNTQgMjYyLjU1OSAxNDQuNDkyIDI2My41ODQgMTQ2LjA3NCAyNjQuMjU4QzE0Ny4yNzUgMjY0Ljg0NCAxNDguNTY0IDI2NS4xNjYgMTQ5Ljk3MSAyNjUuMTY2QzE1MS4zNzcgMjY1LjE2NiAxNTIuNjY2IDI2NC44NzMgMTUzLjg2NyAyNjQuMjU4QzE1NS40NzkgMjYzLjU1NSAxNTcuNTg4IDI2Mi41NTkgMTYwLjI1NCAyNjEuMjdDMTYyLjg5MSAyNTkuOTggMTY3LjM3MyAyNTcuNDkgMTczLjY3MiAyNTMuODU3QzE3OS45NzEgMjUwLjE5NSAxODYuMDA2IDI0Ni4zMjggMTkxLjgwNyAyNDIuMjI3QzE5Ny42MDcgMjM4LjEyNSAyMDMuOTM2IDIzMi45NjkgMjEwLjc5MSAyMjYuNzg3QzIxNy42NDYgMjIwLjU3NiAyMjMuNTM1IDIxNC4yMTkgMjI4LjQ4NiAyMDcuNjU2QzIzMy40MzggMjAxLjA5NCAyMzcuNTY4IDE5My42MjMgMjQwLjkzOCAxODUuMTU2QzI0NC4yNzcgMTc2LjcxOSAyNDUuOTQ3IDE2OC4xOTMgMjQ1Ljk0NyAxNTkuNThWNDQuNDQzNEMyNDUuOTc3IDQxLjgzNTkgMjQ1LjAxIDM5LjU4MDEgMjQzLjEwNSAzNy42NzU4Wk0yMjAuODQgMTYwLjY2NEMyMjAuODQgMjAyLjM1NCAxNTAgMjM4LjI3MSAxNTAgMjM4LjI3MVY1OS41MDJIMjIwLjg0QzIyMC44NCA1OS41MDIgMjIwLjg0IDExOC45NzUgMjIwLjg0IDE2MC42NjRaIiBmaWxsPSJ3aGl0ZSIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzY4XzYxIj4KPHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF82OF82MSkiPgo8cGF0aCBkPSJNMzAwIDI1My4xMjVDMzAwIDI3OS4wMjMgMjc5LjAyMyAzMDAgMjUzLjEyNSAzMDBINDYuODc1QzIwLjk3NjYgMzAwIDAgMjc5LjAyMyAwIDI1My4xMjVWNDYuODc1QzAgMjAuOTc2NiAyMC45NzY2IDAgNDYuODc1IDBIMjUzLjEyNUMyNzkuMDIzIDAgMzAwIDIwLjk3NjYgMzAwIDQ2Ljg3NVYyNTMuMTI1WiIgZmlsbD0iIzE3NUREQyIvPgo8cGF0aCBkPSJNMjQzLjEwNSAzNy42NzU4QzI0MS4yMDEgMzUuNzcxNSAyMzguOTQ1IDM0LjgzNCAyMzYuMzY3IDM0LjgzNEg2My42MzI4QzYxLjAyNTQgMzQuODM0IDU4Ljc5ODggMzUuNzcxNSA1Ni44OTQ1IDM3LjY3NThDNTQuOTkwMiAzOS41ODAxIDU0LjA1MjcgNDEuODM1OSA1NC4wNTI3IDQ0LjQxNDFWMTU5LjU4QzU0LjA1MjcgMTY4LjE2NCA1NS43MjI3IDE3Ni42ODkgNTkuMDYyNSAxODUuMTU2QzYyLjQwMjMgMTkzLjU5NCA2Ni41NjI1IDIwMS4wOTQgNzEuNTEzNyAyMDcuNjU2Qzc2LjQ2NDggMjE0LjE4OSA4Mi4zNTM1IDIyMC41NzYgODkuMjA5IDIyNi43ODdDOTYuMDY0NSAyMzIuOTk4IDEwMi4zOTMgMjM4LjEyNSAxMDguMTY0IDI0Mi4yMjdDMTEzLjk2NSAyNDYuMzI4IDEyMCAyNTAuMTk1IDEyNi4yOTkgMjUzLjg1N0MxMzIuNTk4IDI1Ny41MiAxMzcuMDggMjU5Ljk4IDEzOS43MTcgMjYxLjI3QzE0Mi4zNTQgMjYyLjU1OSAxNDQuNDkyIDI2My41ODQgMTQ2LjA3NCAyNjQuMjU4QzE0Ny4yNzUgMjY0Ljg0NCAxNDguNTY0IDI2NS4xNjYgMTQ5Ljk3MSAyNjUuMTY2QzE1MS4zNzcgMjY1LjE2NiAxNTIuNjY2IDI2NC44NzMgMTUzLjg2NyAyNjQuMjU4QzE1NS40NzkgMjYzLjU1NSAxNTcuNTg4IDI2Mi41NTkgMTYwLjI1NCAyNjEuMjdDMTYyLjg5MSAyNTkuOTggMTY3LjM3MyAyNTcuNDkgMTczLjY3MiAyNTMuODU3QzE3OS45NzEgMjUwLjE5NSAxODYuMDA2IDI0Ni4zMjggMTkxLjgwNyAyNDIuMjI3QzE5Ny42MDcgMjM4LjEyNSAyMDMuOTM2IDIzMi45NjkgMjEwLjc5MSAyMjYuNzg3QzIxNy42NDYgMjIwLjU3NiAyMjMuNTM1IDIxNC4yMTkgMjI4LjQ4NiAyMDcuNjU2QzIzMy40MzggMjAxLjA5NCAyMzcuNTY4IDE5My42MjMgMjQwLjkzOCAxODUuMTU2QzI0NC4yNzcgMTc2LjcxOSAyNDUuOTQ3IDE2OC4xOTMgMjQ1Ljk0NyAxNTkuNThWNDQuNDQzNEMyNDUuOTc3IDQxLjgzNTkgMjQ1LjAxIDM5LjU4MDEgMjQzLjEwNSAzNy42NzU4Wk0yMjAuODQgMTYwLjY2NEMyMjAuODQgMjAyLjM1NCAxNTAgMjM4LjI3MSAxNTAgMjM4LjI3MVY1OS41MDJIMjIwLjg0QzIyMC44NCA1OS41MDIgMjIwLjg0IDExOC45NzUgMjIwLjg0IDE2MC42NjRaIiBmaWxsPSJ3aGl0ZSIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzY4XzYxIj4KPHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==" + }, + "fbfc3007-154e-4ecc-8c0b-6e020557d7bd": { + "name": "iCloud Keychain", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBmaWxsPSJub25lIj48cGF0aCBkPSJtMjE3LjM2LDkwLjY5Yy0xNS41OCw5LjU0LTI1LjE3LDI2LjQxLTI1LjM4LDQ0LjY4LjA2LDIwLjY3LDEyLjQzLDM5LjMyLDMxLjQ2LDQ3LjQxLTMuNjcsMTEuODQtOS4xLDIzLjA2LTE2LjExLDMzLjI4LTEwLjAzLDE0LjQ0LTIwLjUyLDI4Ljg3LTM2LjQ3LDI4Ljg3cy0yMC4wNi05LjI3LTM4LjQ1LTkuMjctMjQuMzIsOS41Ny0zOC45LDkuNTctMjQuNzctMTMuMzctMzYuNDctMjkuNzljLTE1LjQ2LTIyLjk5LTIzLjk1LTQ5Ljk2LTI0LjQ3LTc3LjY2LDAtNDUuNTksMjkuNjMtNjkuNzUsNTguODEtNjkuNzUsMTUuNSwwLDI4LjQyLDEwLjE4LDM4LjE1LDEwLjE4czIzLjcxLTEwLjc5LDQxLjM0LTEwLjc5YzE4LjQxLS40NywzNS44NCw4LjI0LDQ2LjUsMjMuMjVabS01NC44Ni00Mi41NWM3Ljc3LTkuMTQsMTIuMTctMjAuNjcsMTIuNDYtMzIuNjcuMDEtMS41OC0uMTQtMy4xNi0uNDYtNC43MS0xMy4zNSwxLjMtMjUuNjksNy42Ny0zNC41LDE3Ljc4LTcuODUsOC43OC0xMi40MSwyMC0xMi45MiwzMS43NiwwLDEuNDMuMTYsMi44Ni40Niw0LjI2LDEuMDUuMiwyLjEyLjMsMy4xOS4zLDEyLjQzLS45OSwyMy45MS03LjA0LDMxLjc2LTE2LjczWiIgZmlsbD0iI0ZGRiIvPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBmaWxsPSJub25lIj48cGF0aCBkPSJtMjE3LjM2LDkwLjY5Yy0xNS41OCw5LjU0LTI1LjE3LDI2LjQxLTI1LjM4LDQ0LjY4LjA2LDIwLjY3LDEyLjQzLDM5LjMyLDMxLjQ2LDQ3LjQxLTMuNjcsMTEuODQtOS4xLDIzLjA2LTE2LjExLDMzLjI4LTEwLjAzLDE0LjQ0LTIwLjUyLDI4Ljg3LTM2LjQ3LDI4Ljg3cy0yMC4wNi05LjI3LTM4LjQ1LTkuMjctMjQuMzIsOS41Ny0zOC45LDkuNTctMjQuNzctMTMuMzctMzYuNDctMjkuNzljLTE1LjQ2LTIyLjk5LTIzLjk1LTQ5Ljk2LTI0LjQ3LTc3LjY2LDAtNDUuNTksMjkuNjMtNjkuNzUsNTguODEtNjkuNzUsMTUuNSwwLDI4LjQyLDEwLjE4LDM4LjE1LDEwLjE4czIzLjcxLTEwLjc5LDQxLjM0LTEwLjc5YzE4LjQxLS40NywzNS44NCw4LjI0LDQ2LjUsMjMuMjVabS01NC44Ni00Mi41NWM3Ljc3LTkuMTQsMTIuMTctMjAuNjcsMTIuNDYtMzIuNjcuMDEtMS41OC0uMTQtMy4xNi0uNDYtNC43MS0xMy4zNSwxLjMtMjUuNjksNy42Ny0zNC41LDE3Ljc4LTcuODUsOC43OC0xMi40MSwyMC0xMi45MiwzMS43NiwwLDEuNDMuMTYsMi44Ni40Niw0LjI2LDEuMDUuMiwyLjEyLjMsMy4xOS4zLDEyLjQzLS45OSwyMy45MS03LjA0LDMxLjc2LTE2LjczWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==" + }, + "53414d53-554e-4700-0000-000000000000": { + "name": "Samsung Pass", + "icon_dark": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgd2lkdGg9IjUycHgiIGhlaWdodD0iNTJweCIgdmlld0JveD0iMCAwIDUyLjAgNTIuMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGRlZnM+PGNsaXBQYXRoIGlkPSJpMCI+PHBhdGggZD0iTTM2MCwwIEwzNjAsODAwIEwwLDgwMCBMMCwwIEwzNjAsMCBaIj48L3BhdGg+PC9jbGlwUGF0aD48Y2xpcFBhdGggaWQ9ImkxIj48cGF0aCBkPSJNMjYsMCBDMzMuOTkxMDI3OCwwIDQxLjEzOTU4MzMsMC45NzUgNDUuOTA4Nzc3OCw1Ljc3Nzc3Nzc4IEM0OS43MTAxOTQ0LDkuNjA1OTE2NjcgNTIsMTUuODY1MDU1NiA1MiwyNiBDNTIsMzYuMTM0OTQ0NCA0OS43MDk4MzMzLDQyLjM5NDQ0NDQgNDUuOTA4MDU1Niw0Ni4yMjI1ODMzIEM0MS4xMzg4NjExLDUxLjAyNDYzODkgMzMuOTkwMzA1Niw1MiAyNiw1MiBDMTguMDA4OTcyMiw1MiAxMC44NjA3Nzc4LDUxLjAyNDYzODkgNi4wOTE1ODMzMyw0Ni4yMjI1ODMzIEMyLjI5MDE2NjY3LDQyLjM5NDQ0NDQgMCwzNi4xMzQ5NDQ0IDAsMjYgQzAsMTUuODY1MDU1NiAyLjI4OTgwNTU2LDkuNjA1NTU1NTYgNi4wOTA4NjExMSw1Ljc3Nzc3Nzc4IEMxMC44NjAwNTU2LDAuOTc1IDE4LjAwODYxMTEsMCAyNiwwIFoiPjwvcGF0aD48L2NsaXBQYXRoPjxsaW5lYXJHcmFkaWVudCBpZD0iaTIiIHgxPSIyNnB4IiB5MT0iNTJweCIgeDI9IjI2cHgiIHkyPSIwLjE5NTkyMTE0OHB4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzI5MjlCMiIgb2Zmc2V0PSIwJSI+PC9zdG9wPjxzdG9wIHN0b3AtY29sb3I9IiMxQTQwQ0MiIG9mZnNldD0iMTAwJSI+PC9zdG9wPjwvbGluZWFyR3JhZGllbnQ+PGNsaXBQYXRoIGlkPSJpMyI+PHBhdGggZD0iTTM3LjE5NDQ0NDQsMCBMMzcuMTk0NDQ0NCw1LjcyMjIyMjIyIEwwLDUuNzIyMjIyMjIgTDAsMCBMMzcuMTk0NDQ0NCwwIFoiPjwvcGF0aD48L2NsaXBQYXRoPjxjbGlwUGF0aCBpZD0iaTQiPjxwYXRoIGQ9Ik0xLjg4MzQyMjEzLDAgQzIuNjIwNzU5ODcsMCAzLjY0MzU2NDAyLDAuMTgxNjEwODcxIDMuNjQzNTY0MDIsMS4zMjExMTgxOSBMMy42NDM1NjQwMiwxLjY4OTExNTYyIEwyLjM0Mjc5MzM5LDEuNjg5MTE1NjIgTDIuMzQyNzkzMzksMS4zNjQ5MDY1OSBDMi4zNDI3OTMzOSwxLjA3OTU3NTczIDIuMTYzMTk2NjQsMC44ODkxNTMzNzEgMS44NTgxNzY4LDAuODg5MTUzMzcxIEMxLjUyOTMxNzg4LDAuODg5MTUzMzcxIDEuNDE2NDgzOTgsMS4wNzUyNzA4OCAxLjM4MDg1OTI3LDEuMjQyMTUxMDkgQzEuMzY2Nzk2ODgsMS4zMDAyNjY1NyAxLjM2MDkwNDA4LDEuNDExNzIxODQgMS4zODYxNDk0MSwxLjUxNzI1NzkzIEMxLjUzNDYwODAyLDIuMTMwNDk3MyAzLjUxMjQ0OTAyLDIuNDU2MTE4ODcgMy43MzI1NTg4MywzLjU1NTUzNzI3IEMzLjc1MzcxOTM3LDMuNjY3MDU5OCAzLjgwMDc5NDg4LDMuOTYxMTM0ODggMy43MzgwNDk4Niw0LjQxMzAwOTYzIEMzLjYxMTgyMzIxLDUuMjg5NjUyMDMgMi44MzgwNTcyLDUuNjEyMTc5NDkgMS44OTU4MTA0Myw1LjYxMjE3OTQ5IEMwLjkxNTcyOTEzNiw1LjYxMjE3OTQ5IDAsNS4yNTk5ODg5MiAwLDQuMDg4ODAwNiBMMCwzLjY4ODI0NzczIEwxLjM5OTQwODIzLDMuNjg4MjQ3NzMgTDEuNDAxMjE2MjUsNC4xOTIzMTg3OSBDMS40MDEyMTYyNSw0LjQ3ODY1ODYgMS41OTYwODA3Myw0LjY2OTI4Mjc1IDEuOTIxODU5MzIsNC42NjkyODI3NSBDMi4yNzA3NDA0LDQuNjY5MjgyNzUgMi4zODgzOTU2OSw0LjQ5MTUwNTg5IDIuNDMxMTg1NTIsNC4zMTU0MTA2MSBDMi40NTYyMjk5Niw0LjIxNjM5OTA1IDIuNDcxNDk3NjksNC4wNTQ2MzA4NSAyLjQyMTAwNzAzLDMuOTI4NjQ2NzEgQzIuMTUxMzQ0MDYsMy4yNTA5NjkxMSAwLjI5NzkyMTY3NywyLjk0MTI4ODk1IDAuMDcyMTE5OTQ3MywxLjg3MDMyMjkyIEMwLjAxNzM0MzYwODUsMS42MDU2NDE4OSAwLjAyMzgzOTA5MTIsMS4zOTkwNzYzNCAwLjA2MTc0MDU2NzcsMS4xNjQyNjAyMSBDMC4yMDAyMjE1ODEsMC4zMDg4NzMwMDcgMC45NTcxMTI3MjcsMCAxLjg4MzQyMjEzLDAgWiBNMTguODQxMTE4NiwwLjAyOTY2MzEwODkgQzE5LjU3MDQ4NzcsMC4wMjk2NjMxMDg5IDIwLjU3Nzg5MDEsMC4yMDY5NjkxMjkgMjAuNTc3ODkwMSwxLjMzNTY0NzA2IEwyMC41Nzc4OTAxLDEuNzAwNzUyMTcgTDE5LjI5MjE4NjQsMS43MDA3NTIxNyBMMTkuMjkyMTg2NCwxLjM4MDQ0NDQxIEMxOS4yOTIxODY0LDEuMDk3NDAwNSAxOS4xMTU2MDMsMC45MDg3OTQyNSAxOC44MTQ0MDAxLDAuOTA4Nzk0MjUgQzE4LjQ5MTIzMzEsMC45MDg3OTQyNSAxOC4zNzkwNjg4LDEuMDkxNjE1ODYgMTguMzQxNzcsMS4yNTkzNzA0OSBDMTguMzI5NzgzNSwxLjMxNjgxMzM0IDE4LjMyMzA4NzEsMS40MjY2NTQyOCAxOC4zNDYyNTY2LDEuNTMwMTcyNDggQzE4LjQ5NDMxMzQsMi4xMzY0MTY0NyAyMC40NTAzOTEyLDIuNDYzMTE0MjUgMjAuNjY2MDE0NCwzLjU0OTIxNDUyIEMyMC42ODk2NTI2LDMuNjU5MDU1NDcgMjAuNzM0MDQ5NiwzLjk1MDcwOTA3IDIwLjY3NTE4ODUsNC4zOTg0MTM1IEMyMC41NTE3NzQzLDUuMjY1MTAwOTMgMTkuNzgyNDk0OSw1LjU4NDgwMzMzIDE4Ljg1MTA5NjIsNS41ODQ4MDMzMyBDMTcuODc4NTgxOCw1LjU4NDgwMzMzIDE2Ljk3NTY0MjgsNS4yMzU0Mzc4MyAxNi45NzU2NDI4LDQuMDc3NTAwMzcgTDE2Ljk3NTY0MjgsMy42Nzc4ODkxOSBMMTguMzU5NTE1NCwzLjY3Nzg4OTE5IEwxOC4zNTk5MTcyLDQuMTgwNjE0OTggQzE4LjM1OTkxNzIsNC40NjMwNTM1MiAxOC41NTUxODM0LDQuNjUwNDQ5MDMgMTguODc5NzU2Nyw0LjY1MDQ0OTAzIEMxOS4yMjU3NTgzLDQuNjUwNDQ5MDMgMTkuMzQyNDc2MSw0LjQ3NTE2MDkxIDE5LjM4MjM4NjUsNC4zMDA4ODE3NCBDMTkuNDA2MzU5NSw0LjIwNTU2OTY2IDE5LjQxOTgxOTIsNC4wNDM4MDE0NiAxOS4zNzI4MTA3LDMuOTE2OTQyOSBDMTkuMTA2NDI4OSwzLjI0NzI2OTYzIDE3LjI3MTE1MzcsMi45NDAwNzgyMSAxNy4wNDc3NjI3LDEuODgxMTUyMyBDMTYuOTkwMTA2OSwxLjYxOTM2MzYgMTYuOTk5MDgwMSwxLjQxNDIxMDU4IDE3LjAzNTMwNzQsMS4xODMwOTM5MyBDMTcuMTcyMzE1MywwLjMzMzgyNzY4NiAxNy45MjI1MSwwLjAyOTY2MzEwODkgMTguODQxMTE4NiwwLjAyOTY2MzEwODkgWiBNMjMuMjM2NDg0NSwwLjE2Njg4MDIxMSBMMjMuMjM2MjI5MSw0LjExMTM3MzY2IEMyMy4yMzcyMDYzLDQuMTU3OTg0NjIgMjMuMjQwODgxOCw0LjIwNDA2NzQ1IDIzLjI0OTY3NjQsNC4yNDExNTE5NCBDMjMuMjc1MTIyNiw0LjM3MTIzOTEzIDIzLjM4Nzc1NTYsNC42MjE1OTMwOCAyMy43NDY5NDkxLDQuNjIxNTkzMDggQzI0LjExMDgzMDEsNC42MjE1OTMwOCAyNC4yMjA1ODM2LDQuMzcxMjM5MTMgMjQuMjQ4MTA1Nyw0LjI0MTE1MTk0IEMyNC4yNTk2OTA1LDQuMTg1NTI1MiAyNC4yNjE3NjYzLDQuMTA5NjUyMjIgMjQuMjU5NjkwNSw0LjA0MjExOTg4IEwyNC4yNTk2OTA1LDAuMTY2ODgwMjExIEwyNS41Nzg2MDgzLDAuMTY2ODgwMjExIEwyNS41Nzg2MDgzLDMuOTIxODUzMTIgQzI1LjU4NDMwMDIsNC4wMTg2NDQ5OSAyNS41NzQ3MjQ0LDQuMjE2Mzk5MDUgMjUuNTY3NDI1Myw0LjI2ODE5MTc4IEMyNS40NzQ3NDc1LDUuMjQ2NjcwNzkgMjQuNzA3NDc3LDUuNTY0MzU1MjkgMjMuNzQ2OTQ5MSw1LjU2NDM1NTI5IEMyMi43ODgyOTYyLDUuNTY0MzU1MjkgMjIuMDIwNTU3LDUuMjQ2NjcwNzkgMjEuOTI5NTUzMiw0LjI2ODE5MTc4IEMyMS45MjM4NjEzLDQuMjE2Mzk5MDUgMjEuOTE2Mjk0NCw0LjAxODY0NDk5IDIxLjkxNzk2ODUsMy45MjE4NTMxMiBMMjEuOTE3OTY4NSwwLjE2Njg4MDIxMSBMMjMuMjM2NDg0NSwwLjE2Njg4MDIxMSBaIE0zNC42Mjk3NjIxLDAuMDI1OTYzNjI4MiBDMzUuNTUzOTk1NiwwLjAyNTk2MzYyODIgMzYuMzYwMDM4MiwwLjMzNjg1NDUzNCAzNi40NTg3NDI3LDEuMzE5NTAzODcgQzM2LjQ2NTU3MywxLjM5MTE5NjkyIDM2LjQ2ODM4MTQsMS40NjUxMTM3OCAzNi40NjkzNjA3LDEuNTI2MTgwMjIgTDM2LjQ2OTAwNCwxLjY1NTc1NDAyIEwzNi40Njg3MjAzLDEuNjY2MTc4ODQgTDM2LjQ2ODcyMDMsMS44MzgwMzY1NCBMMzUuMTU1MzYwNSwxLjgzODAzNjU0IEwzNS4xNTUxNSwxLjUzMzU1NTU2IEMzNS4xNTQ0NDcxLDEuNDk4NzMzNjIgMzUuMTUxNDksMS40MDU2NDEyMyAzNS4xMzk0OTAxLDEuMzQ1MjY1NzEgQzM1LjExNjY1NTUsMS4yMzEzMjE3IDM1LjAxNzA4MDQsMC45NjYwMzUzMDYgMzQuNjE4MTc3NCwwLjk2NjAzNTMwNiBDMzQuMjM4MTU4MiwwLjk2NjAzNTMwNiAzNC4xMjU1OTIxLDEuMjE3NTk5OTkgMzQuMDk5Njc3MiwxLjM0NTI2NTcxIEMzNC4wODE3OTc4LDEuNDE1NDIxMzIgMzQuMDc2MTA1OSwxLjUwODExMDEyIDM0LjA3NjEwNTksMS41OTI3OTQ2IEwzNC4wNzYxMDU5LDMuOTg2ODk2NzIgQzM0LjA3NjEwNTksNC4wNTQ2MzA4NSAzNC4wODAxOTA3LDQuMTI3NjExNTEgMzQuMDg5NzY2NSw0LjE4NjEzMDU3IEMzNC4xMTI1MzQyLDQuMzI3NTE4IDM0LjI0Mzg1MDEsNC41NjgyNTMzIDM0LjYyMDk4OTksNC41NjgyNTMzIEMzNS4wMDA0MDY0LDQuNTY4MjUzMyAzNS4xMzQxMzMsNC4zMjc1MTggMzUuMTU1MzYwNSw0LjE4NjEzMDU3IEMzNS4xNjY5NDUyLDQuMTI3NjExNTEgMzUuMTcwNjI4Miw0LjA1NDYzMDg1IDM1LjE2ODk1NDEsMy45ODY4OTY3MiBMMzUuMTY4OTU0MSwzLjIyODkwNjc2IEwzNC42MzQ0NDk2LDMuMjI4OTA2NzYgTDM0LjYzNDQ0OTYsMi40NjQ5MzAzNiBMMzYuNDc5MTY2NywyLjQ2NDkzMDM2IEwzNi40NzkxNjY3LDMuODY4NTEzMzQgQzM2LjQ3NzA5MDgsMy45NjQ0MzA3OCAzNi40NzU0ODM3LDQuMDM4Njg5NDUgMzYuNDYwMDE1LDQuMjEzOTc3NTcgQzM2LjM3MjgyODIsNS4xNjk1ODcwNyAzNS41NTM5OTU2LDUuNTA4MzI0OTcgMzQuNjI2MDc5MSw1LjUwODMyNDk3IEMzMy43MDM4NTQ1LDUuNTA4MzI0OTcgMzIuODc5MzMsNS4xNjk1ODcwNyAzMi43OTM2MTY0LDQuMjEzOTc3NTcgQzMyLjc3NTkzOCw0LjAzODY4OTQ1IDMyLjc3Mjg1NzYsMy45NjQ0MzA3OCAzMi43NzI4NTc2LDMuODY4NTEzMzQgTDMyLjc3Mjg1NzYsMS42NjYxNzg4NCBDMzIuNzcyODU3NiwxLjU3MDI2MTQgMzIuNzg4NzI4LDEuNDA5MDk4NTcgMzIuNzk5MTA3NCwxLjMxOTUwMzg3IEMzMi45MTQxNTExLDAuMzM5NzQ2ODU1IDMzLjcwMzg1NDUsMC4wMjU5NjM2MjgyIDM0LjYyOTc2MjEsMC4wMjU5NjM2MjgyIFogTTEyLjE0NDc0NDcsMC4xNjY4ODAyMTEgTDEyLjgwMjI2MTYsNC4yNjE1OTk5OCBMMTMuNDYwMTgwNCwwLjE2Njg4MDIxMSBMMTUuNTg1Mjc0NiwwLjE2Njg4MDIxMSBMMTUuNzAxOTI1NSw1LjQwNTIxMDM2IEwxNC4zOTUyNjIsNS40MDUyMTAzNiBMMTQuMzU5ODM4MiwwLjU1NTkzMTA1NCBMMTMuNDYyMjU2Miw1LjQwNTIxMDM2IEwxMi4xMzk4NTYzLDUuNDA1MjEwMzYgTDExLjI0MzA3NzksMC41NTU5MzEwNTQgTDExLjIwNzc4OCw1LjQwNTIxMDM2IEw5LjkwNDQwNTgsNS40MDUyMTAzNiBMMTAuMDE3MjM5NywwLjE2Njg4MDIxMSBMMTIuMTQ0NzQ0NywwLjE2Njg4MDIxMSBaIE03LjkwMTI1MjUsMC4xNjY4ODAyMTEgTDguODYzMjUzNTgsNS40MDUyMTAzNiBMNy40NjQzMTQxLDUuNDA1MjEwMzYgTDYuNzUzODI4ODMsMC41NTU5MzEwNTQgTDYuMDI1ODY2MDIsNS40MDUyMTAzNiBMNC42MTcxNDk4Myw1LjQwNTIxMDM2IEw1LjU4MzE2ODczLDAuMTY2ODgwMjExIEw3LjkwMTI1MjUsMC4xNjY4ODAyMTEgWiBNMjguMzA0ODM2LDUuMzUwNTkyNTcgTDI3LjAyNDYyMzMsNS4zNTA1OTI1NyBMMjcuMDI0NjIzMywwLjE2Njg4MDIxMSBMMjguOTU5ODc1MywwLjE2Njg4MDIxMSBMMzAuMTg3OTkwMyw0LjM4NDM1NTQ3IEwzMC4xMTY4NzQ4LDAuMTY2ODgwMjExIEwzMS40MDU0NTgxLDAuMTY2ODgwMjExIEwzMS40MDU0NTgxLDUuMzUwNTkyNTcgTDI5LjU0OTQyNDEsNS4zNTA1OTI1NyBMMjguMjMsMC45OTkgTDI4LjMwNDgzNiw1LjM1MDU5MjU3IFoiPjwvcGF0aD48L2NsaXBQYXRoPjxjbGlwUGF0aCBpZD0iaTUiPjxwYXRoIGQ9Ik0yNC4zMzUyOTY2LDIuNDcwMDY0MzIgQzI1LjMwOTY1MDIsMi40NzAwNjQzMiAyNi4xMjEzMjMsMi42NTY2MDU2NCAyNi43NjkyNzY4LDMuMDI4OTczNTYgQzI3LjQxNzIzMDUsMy40MDE2OTg4MyAyNy45Mjk1MDE3LDMuOTA4NDMzNjcgMjguMzA2MDkwMiw0LjU1MDI1MDE1IEwyNi4zOTU0NTczLDUuNDgyNTk5MzcgQzI2LjE5NjA4NjksNS4xNDYzMjQ3IDI1LjkxOTE4MzYsNC44ODAwOTIzNiAyNS41NjQ3NDczLDQuNjg0NjE3MDggQzI1LjIxMDMxMTEsNC40ODkxNDE3OSAyNC44MDA0OTQyLDQuMzkxMjI1NDcgMjQuMzM1Mjk2Niw0LjM5MTIyNTQ3IEMyMy44MDM2NDIyLDQuMzkxMjI1NDcgMjMuNDEwNDM5NSw0LjQ5NDg1OTUzIDIzLjE1NTY4ODUsNC43MDIxMjc2NiBDMjIuOTAwNTkxMyw0LjkwOTM5NTc5IDIyLjc3MzU2MTksNS4xNDk1NDA5MyAyMi43NzM1NjE5LDUuNDIyMjA1NzMgQzIyLjc3MzU2MTksNS43Mzg0NjgzMSAyMi45NjE4NTYyLDUuOTY1MDMzODEgMjMuMzM4NDQ0Nyw2LjEwMDgzMDE3IEMyMy43MTQ2ODcsNi4yMzczNDEyNSAyNC4yNjg4Mzk4LDYuMzgyMDcxNTggMjQuOTk5ODY0Niw2LjUzNDY2MzgxIEMyNS4zOTg2MDU0LDYuNjExMTM4NiAyNS43OTk3NjksNi43MTE1NTY0NCAyNi4yMDQzOTQsNi44MzczNDY3NSBDMjYuNjA4NjcyOSw2Ljk2Mjc3OTcgMjYuOTc2OTU0Myw3LjEzMTgxMDQzIDI3LjMwOTIzODMsNy4zNDQ3OTYzMSBDMjcuNjQxNTIyMiw3LjU1NzQyNDgyIDI3LjkxMDExODUsNy44Mjk3MzIyNiAyOC4xMTUwMjY5LDguMTYyNzkwNyBDMjguMzE5OTM1NCw4LjQ5NTQ5MTc4IDI4LjQyMjM4OTYsOC45MTI1Mjk1NSAyOC40MjIzODk2LDkuNDE0MjYxMzcgQzI4LjQyMjM4OTYsOS43NTIzMjI4MyAyOC4zNDQ4NTY3LDEwLjEwNDMyMTMgMjguMTg5NzkwOCwxMC40Njk1NDIgQzI4LjAzNDM3ODgsMTAuODM0NzYyOCAyNy43OTM4MTkxLDExLjE3MzE4MTYgMjcuNDY3MDczMSwxMS40ODM3MjY0IEMyNy4xNDAzMjcyLDExLjc5NDk4NiAyNi43Mjc3NDEzLDEyLjA0ODM1MzQgMjYuMjI5MzE1MywxMi4yNDQ1NDM0IEMyNS43MzA4ODkzLDEyLjQ0MTA5MDggMjUuMTMyNzc4MiwxMi41MzkwMDcxIDI0LjQzNDk4MTgsMTIuNTM5MDA3MSBDMjMuMzYwNTk2OSwxMi41MzkwMDcxIDIyLjQ2ODk2ODIsMTIuMzMyODExIDIxLjc2MDA5NTcsMTEuOTIwMDYxNiBDMjEuMDUxMjIzMywxMS41MDY5NTQ4IDIwLjUwMjk1NDcsMTAuOTEwNTIyOCAyMC4xMTUyOSwxMC4xMzAwNTExIEwyMi4xOTIwNjQ5LDkuMTY1MTgyMjUgQzIyLjQyNDY2MzcsOS42MDQ3MzM2MyAyMi43NDAzMzM1LDkuOTQyNDM3NzQgMjMuMTM5MDc0MywxMC4xNzg2NTE5IEMyMy41Mzc4MTUxLDEwLjQxNDUwODggMjQuMDAzMDEyNiwxMC41MzIwNzk4IDI0LjUzNDY2NywxMC41MzIwNzk4IEMyNS4wODg0NzM2LDEwLjUzMjA3OTggMjUuNTAzODI4NiwxMC40MTc3MjUgMjUuNzgwNzMxOSwxMC4xODkwMTUzIEMyNi4wNTcyODkxLDkuOTU5OTQ4MzIgMjYuMTk2MDg2OSw5LjY4NzY0MDg4IDI2LjE5NjA4NjksOS4zNzEwMjA5NSBDMjYuMTk2MDg2OSw5LjE5NjYyOTgzIDI2LjEzMjM5OTIsOS4wNTUxMTU3MyAyNi4wMDUwMjM2LDguOTQ1NzYzOTIgQzI1Ljg3NzY0ODEsOC44MzcxMjY4MyAyNS43MTE1MDYxLDguNzQxMzU0NjYgMjUuNTA2NTk3Niw4LjY1OTg3Njg1IEMyNS4zMDEzNDMxLDguNTc4MDQxNjcgMjUuMDYwNzgzMyw4LjUxMDE0MzQ5IDI0Ljc4Mzg4LDguNDU1MTEwMjMgQzI0LjUwNjk3NjcsOC40MDA3OTE2OSAyNC4yMTg5OTcyLDguMzQwNzU1NCAyMy45MTk5NDE2LDguMjc1MzU4NzMgQzIzLjQ5ODcwMjUsOC4xODgxNjMxOCAyMy4wODY0NjI2LDguMDg0ODg2NDcgMjIuNjgyMTgzOCw3Ljk2NDgxMzkgQzIyLjI3NzkwNSw3Ljg0NTA5ODY5IDIxLjkxNTE2MTYsNy42Nzg1Njk0NyAyMS41OTM5NTM4LDcuNDY2Mjk4MzEgQzIxLjI3Mjc0NTksNy4yNTMzMTI0NCAyMS4wMTI0NTY4LDYuOTgwNjQ3NjQgMjAuODEzMDg2NCw2LjY0ODMwMzkyIEMyMC42MTM3MTYsNi4zMTU5NjAyIDIwLjUxNDAzMDgsNS44OTg5MjI0MyAyMC41MTQwMzA4LDUuMzk3NTQ3OTcgQzIwLjUxNDAzMDgsNS4wMTU1MzEzNyAyMC42MDU0MDg5LDQuNjQ3ODA5MTIgMjAuNzg4MTY1MSw0LjI5MzY2NjUgQzIwLjk3MDkyMTMsMy45MzkxNjY1MyAyMS4yMjg0NDE0LDMuNjI2MTIwMTggMjEuNTYwNzI1NCwzLjM1MzA5ODAzIEMyMS44OTMwMDkzLDMuMDgwNzkwNTkgMjIuMjk0MTczLDIuODY1NjYwNTYgMjIuNzY1MjU0OCwyLjcwNzM1MDYgQzIzLjIzNTk5MDQsMi41NDkwNDA2MyAyMy43NTkzMzc3LDIuNDcwMDY0MzIgMjQuMzM1Mjk2NiwyLjQ3MDA2NDMyIFogTTMzLjEwNzM1MTUsMi40NzAwNjQzMiBDMzQuMDgxNzA1LDIuNDcwMDY0MzIgMzQuODkzMzc3OSwyLjY1NjYwNTY0IDM1LjU0MTMzMTYsMy4wMjg5NzM1NiBDMzYuMTg5Mjg1NCwzLjQwMTY5ODgzIDM2LjcwMTU1NjUsMy45MDg0MzM2NyAzNy4wNzgxNDUxLDQuNTUwMjUwMTUgTDM1LjE2NzUxMjIsNS40ODI1OTkzNyBDMzQuOTY4MTQxOCw1LjE0NjMyNDcgMzQuNjkxMjM4NCw0Ljg4MDA5MjM2IDM0LjMzNjgwMjIsNC42ODQ2MTcwOCBDMzMuOTgyMzY1OSw0LjQ4OTE0MTc5IDMzLjU3MjU0OSw0LjM5MTIyNTQ3IDMzLjEwNzM1MTUsNC4zOTEyMjU0NyBDMzIuNTc1Njk3MSw0LjM5MTIyNTQ3IDMyLjE4MjQ5NDQsNC40OTQ4NTk1MyAzMS45Mjc3NDMzLDQuNzAyMTI3NjYgQzMxLjY3MjY0NjEsNC45MDkzOTU3OSAzMS41NDU2MTY3LDUuMTQ5NTQwOTMgMzEuNTQ1NjE2Nyw1LjQyMjIwNTczIEMzMS41NDU2MTY3LDUuNzM4NDY4MzEgMzEuNzMzOTExLDUuOTY1MDMzODEgMzIuMTEwNDk5NSw2LjEwMDgzMDE3IEMzMi40ODY3NDE5LDYuMjM3MzQxMjUgMzMuMDQwODk0Nyw2LjM4MjA3MTU4IDMzLjc3MTkxOTQsNi41MzQ2NjM4MSBDMzQuMTcwNjYwMiw2LjYxMTEzODYgMzQuNTcxODIzOSw2LjcxMTU1NjQ0IDM0Ljk3NjQ0ODksNi44MzczNDY3NSBDMzUuMzgwNzI3Nyw2Ljk2Mjc3OTcgMzUuNzQ5MDA5MSw3LjEzMTgxMDQzIDM2LjA4MTI5MzEsNy4zNDQ3OTYzMSBDMzYuNDEzNTc3MSw3LjU1NzQyNDgyIDM2LjY4MjE3MzMsNy44Mjk3MzIyNiAzNi44ODcwODE4LDguMTYyNzkwNyBDMzcuMDkxOTkwMiw4LjQ5NTQ5MTc4IDM3LjE5NDQ0NDQsOC45MTI1Mjk1NSAzNy4xOTQ0NDQ0LDkuNDE0MjYxMzcgQzM3LjE5NDQ0NDQsOS43NTIzMjI4MyAzNy4xMTY5MTE1LDEwLjEwNDMyMTMgMzYuOTYxODQ1NywxMC40Njk1NDIgQzM2LjgwNjQzMzcsMTAuODM0NzYyOCAzNi41NjU4NzM5LDExLjE3MzE4MTYgMzYuMjM5MTI4LDExLjQ4MzcyNjQgQzM1LjkxMjM4MjEsMTEuNzk0OTg2IDM1LjQ5OTc5NjEsMTIuMDQ4MzUzNCAzNS4wMDEzNzAyLDEyLjI0NDU0MzQgQzM0LjUwMjk0NDIsMTIuNDQxMDkwOCAzMy45MDQ4MzMsMTIuNTM5MDA3MSAzMy4yMDcwMzY3LDEyLjUzOTAwNzEgQzMyLjEzMjY1MTgsMTIuNTM5MDA3MSAzMS4yNDEwMjMxLDEyLjMzMjgxMSAzMC41MzIxNTA2LDExLjkyMDA2MTYgQzI5LjgyMzI3ODEsMTEuNTA2OTU0OCAyOS4yNzUwMDk1LDEwLjkxMDUyMjggMjguODg3MzQ0OSwxMC4xMzAwNTExIEwzMC45NjQxMTk4LDkuMTY1MTgyMjUgQzMxLjE5NjcxODYsOS42MDQ3MzM2MyAzMS41MTIzODgzLDkuOTQyNDM3NzQgMzEuOTExMTI5MSwxMC4xNzg2NTE5IEMzMi4zMDk4Njk5LDEwLjQxNDUwODggMzIuNzc1MDY3NSwxMC41MzIwNzk4IDMzLjMwNjcyMTgsMTAuNTMyMDc5OCBDMzMuODYwNTI4NSwxMC41MzIwNzk4IDM0LjI3NTg4MzUsMTAuNDE3NzI1IDM0LjU1Mjc4NjgsMTAuMTg5MDE1MyBDMzQuODI5MzQ0LDkuOTU5OTQ4MzIgMzQuOTY4MTQxOCw5LjY4NzY0MDg4IDM0Ljk2ODE0MTgsOS4zNzEwMjA5NSBDMzQuOTY4MTQxOCw5LjE5NjYyOTgzIDM0LjkwNDQ1NCw5LjA1NTExNTczIDM0Ljc3NzA3ODUsOC45NDU3NjM5MiBDMzQuNjQ5NzAyOSw4LjgzNzEyNjgzIDM0LjQ4MzU2MSw4Ljc0MTM1NDY2IDM0LjI3ODY1MjUsOC42NTk4NzY4NSBDMzQuMDczMzk3OSw4LjU3ODA0MTY3IDMzLjgzMjgzODIsOC41MTAxNDM0OSAzMy41NTU5MzQ4LDguNDU1MTEwMjMgQzMzLjI3OTAzMTUsOC40MDA3OTE2OSAzMi45OTEwNTIxLDguMzQwNzU1NCAzMi42OTE5OTY1LDguMjc1MzU4NzMgQzMyLjI3MDc1NzMsOC4xODgxNjMxOCAzMS44NTg1MTc1LDguMDg0ODg2NDcgMzEuNDU0MjM4Niw3Ljk2NDgxMzkgQzMxLjA0OTk1OTgsNy44NDUwOTg2OSAzMC42ODcyMTY1LDcuNjc4NTY5NDcgMzAuMzY2MDA4Niw3LjQ2NjI5ODMxIEMzMC4wNDQ4MDA4LDcuMjUzMzEyNDQgMjkuNzg0NTExNiw2Ljk4MDY0NzY0IDI5LjU4NTE0MTIsNi42NDgzMDM5MiBDMjkuMzg1NzcwOSw2LjMxNTk2MDIgMjkuMjg2MDg1Nyw1Ljg5ODkyMjQzIDI5LjI4NjA4NTcsNS4zOTc1NDc5NyBDMjkuMjg2MDg1Nyw1LjAxNTUzMTM3IDI5LjM3NzQ2MzgsNC42NDc4MDkxMiAyOS41NjAyMTk5LDQuMjkzNjY2NSBDMjkuNzQyOTc2MSwzLjkzOTE2NjUzIDMwLjAwMDQ5NjIsMy42MjYxMjAxOCAzMC4zMzI3ODAyLDMuMzUzMDk4MDMgQzMwLjY2NTA2NDIsMy4wODA3OTA1OSAzMS4wNjYyMjc5LDIuODY1NjYwNTYgMzEuNTM3MzA5NiwyLjcwNzM1MDYgQzMyLjAwODA0NTMsMi41NDkwNDA2MyAzMi41MzEzOTI2LDIuNDcwMDY0MzIgMzMuMTA3MzUxNSwyLjQ3MDA2NDMyIFogTTEzLjc3MzIwNTcsMi40NzAwMjg1OSBDMTQuNDE1NjIxNCwyLjQ3MDAyODU5IDE1LjAwODE5NDUsMi41OTAxMDExNiAxNS41NTA5MjUsMi44Mjk1MzE1OSBDMTYuMDkzMzA5NCwzLjA2OTY3NjczIDE2LjU0MjIzODksMy4zOTY2NjAwNyAxNi44OTY2NzUxLDMuODEwODM4OTcgTDE2Ljg5NjY3NTEsMi40ODcxODE4MSBMMTkuMTM5NTkyLDIuNDg3MTgxODEgTDE5LjEzOTU5MiwxMi41MjE4MTgxIEwxNi44OTY2NzUxLDEyLjUyMTgxODEgTDE2Ljg5NjY3NTEsMTEuMDk1OTU2MyBDMTYuNTQyMjM4OSwxMS41NDQwODQzIDE2LjA4ODExNzQsMTEuODk2Nzk3NSAxNS41MzQzMTA4LDEyLjE1MzczODUgQzE0Ljk4MDUwNDIsMTIuNDEwNjc5NSAxNC4zODIzOTMsMTIuNTM4OTcxNCAxMy43Mzk5NzczLDEyLjUzODk3MTQgQzEzLjE1Mjk0MjMsMTIuNTM4OTcxNCAxMi41NzQyMTQzLDEyLjQyNjQwMzMgMTIuMDAzNzkzNSwxMi4yMDA1NTI1IEMxMS40MzMzNzI2LDExLjk3NDM0NDQgMTAuOTIxMTAxNSwxMS42NDYyODkgMTAuNDY2OTgwMSwxMS4yMTYzODYzIEMxMC4wMTI4NTg2LDEwLjc4NjQ4MzYgOS42NDcwMDAxMSwxMC4yNjAwOTQgOS4zNzA0NDI5Miw5LjYzNzU3NDkxIEM5LjA5MzUzOTYsOS4wMTQ2OTg0NCA4Ljk1NTA4Nzk0LDguMzA2NDEzMjIgOC45NTUwODc5NCw3LjUxMzA3NjU4IEM4Ljk1NTA4Nzk0LDYuNzA4MzA0NDcgOS4wOTA0MjQ0NCw1Ljk5NTAxNjIyIDkuMzYyMTM1ODIsNS4zNzE3ODI0IEM5LjYzMzUwMTA3LDQuNzQ4OTA1OTMgOS45OTM0NzUzOSw0LjIyMjg3MzcxIDEwLjQ0MjA1ODgsMy43OTI5NzEwMyBDMTAuODkwNjQyMSwzLjM2MjcxMDk4IDExLjQwNTY4MjMsMy4wMzUwMTI5MiAxMS45ODcxNzkzLDIuODA5NTE5NDkgQzEyLjU2ODY3NjMsMi41ODMzMTEzNCAxMy4xNjQwMTg0LDIuNDcwMDI4NTkgMTMuNzczMjA1NywyLjQ3MDAyODU5IFogTTQuMTUzNTQ5NzgsMCBDNC43ODQ4ODkzNSwwIDUuMzY2Mzg2MzIsMC4xMTcyMTM3MDEgNS44OTgwNDA2OSwwLjM1MTk5ODQ2MSBDNi40Mjk2OTUwNiwwLjU4NjQyNTg2MiA2Ljg4OTAwODQ0LDAuOTAzNDAzMTU2IDcuMjc3MDE5MjIsMS4zMDQwMDI0MiBDNy42NjQ2ODM4NiwxLjcwNDI0NDMyIDcuOTY4OTMxMzgsMi4xNzU5NTggOC4xOTA4MDAxNywyLjcxOTE0MzQ0IEM4LjQxMjMyMjgyLDMuMjYxOTcxNTIgOC41MjMwODQxNSwzLjg0MjMyMjI4IDguNTIzMDg0MTUsNC40NjAxOTU3MiBDOC41MjMwODQxNSw1LjA3NzM1NDQ0IDguNDEyMzIyODIsNS42NjA1NjQwOCA4LjE5MDgwMDE3LDYuMjA5NDY3MjYgQzcuOTY4OTMxMzgsNi43NTgzNzA0NCA3LjY2NDY4Mzg2LDcuMjMyOTQyOTkgNy4yNzcwMTkyMiw3LjYzMzU0MjI1IEM2Ljg4OTAwODQ0LDguMDMzNzg0MTYgNi40MjY5MjYwMyw4LjM1MTExODgxIDUuODg5NzMzNTksOC41ODUxODg4NSBDNS4zNTIxOTUwMiw4LjgxOTYxNjI1IDQuNzY4Mjc1MTUsOC45MzY4Mjk5NSA0LjEzNjkzNTU4LDguOTM2ODI5OTUgTDIuMjU5NTMxMDgsOC45MzY4Mjk5NSBMMi4yNTk1MzEwOCwxMi41MjE4NTM5IEwwLDEyLjUyMTg1MzkgTDAsMCBMNC4xNTM1NDk3OCwwIFogTTE0LjEwNTQ4OTcsNC41ODAyMzI1NiBDMTMuNjk1NjcyOCw0LjU4MDIzMjU2IDEzLjMxMDc3NzEsNC42NTU2MzUyNyAxMi45NTA4MDI4LDQuODA1NzI1OTkgQzEyLjU5MDgyODUsNC45NTU4MTY3IDEyLjI3NzkyNzgsNS4xNjAyMjU5NiAxMi4wMTIxMDA2LDUuNDE3NTI0MzMgQzExLjc0NjI3MzQsNS42NzU1Mzc0MSAxMS41Mzg1OTU5LDUuOTgxNzkzOTQgMTEuMzg5MDY4MSw2LjMzNjI5MzkxIEMxMS4yMzk1NDAzLDYuNjkwNzkzODkgMTEuMTY0Nzc2NCw3LjA3MTczODQxIDExLjE2NDc3NjQsNy40ODAxOTk1NyBDMTEuMTY0Nzc2NCw3Ljg4ODMwMzM3IDExLjIzOTU0MDMsOC4yNzI0NjQxMyAxMS4zODkwNjgxLDguNjMxOTY3MTIgQzExLjUzODU5NTksOC45OTE0NzAxMiAxMS43NDYyNzM0LDkuMzAyNzI5NjcgMTIuMDEyMTAwNiw5LjU2NjQ2MDUgQzEyLjI3NzkyNzgsOS44Mjk0NzY2MSAxMi41OTA4Mjg1LDEwLjAzNjAzIDEyLjk1MDgwMjgsMTAuMTg2ODM1NCBDMTMuMzEwNzc3MSwxMC4zMzY5MjYyIDEzLjY5NTY3MjgsMTAuNDExOTcxNSAxNC4xMDU0ODk3LDEwLjQxMTk3MTUgQzE0LjUyNjM4MjcsMTAuNDExOTcxNSAxNC45MTM3MDEyLDEwLjMzNjkyNjIgMTUuMjY4NDgzNiwxMC4xODY4MzU0IEMxNS42MjI5MTk5LDEwLjAzNjAzIDE1LjkyNzE2NzQsOS44MjY2MTc3NCAxNi4xODIyNjQ2LDkuNTU3ODgzODkgQzE2LjQzNzAxNTYsOS4yODk1MDczOSAxNi42MzkxNTUsOC45Nzc4OTA0OCAxNi43ODg2ODI4LDguNjIzNzQ3ODcgQzE2LjkzODIxMDYsOC4yNjk2MDUyNiAxNy4wMTI5NzQ1LDcuODg4MzAzMzcgMTcuMDEyOTc0NSw3LjQ4MDE5OTU3IEMxNy4wMTI5NzQ1LDcuMDgyODE2NTQgMTYuOTM4MjEwNiw2LjcwNjg3NTAzIDE2Ljc4ODY4MjgsNi4zNTIzNzUwNiBDMTYuNjM5MTU1LDUuOTk3ODc1MDkgMTYuNDM3MDE1Niw1LjY4OTExNzA1IDE2LjE4MjI2NDYsNS40MjYxMDA5NCBDMTUuOTI3MTY3NCw1LjE2MjcyNzQ3IDE1LjYyMjkxOTksNC45NTU4MTY3IDE1LjI2ODQ4MzYsNC44MDU3MjU5OSBDMTQuOTEzNzAxMiw0LjY1NTYzNTI3IDE0LjUyNjM4MjcsNC41ODAyMzI1NiAxNC4xMDU0ODk3LDQuNTgwMjMyNTYgWiBNMy45ODc0MDc3OSwyLjE2MTMwNjI4IEwyLjI1OTUzMTA4LDIuMTYxMzA2MjggTDIuMjU5NTMxMDgsNi43NzU1MjM2NyBMMy45ODc0MDc3OSw2Ljc3NTUyMzY3IEM0LjMxOTY5MTc3LDYuNzc1NTIzNjcgNC42MjQyODU0Miw2LjcxNTQ4NzM4IDQuOTAxMTg4NzQsNi41OTU0MTQ4MSBDNS4xNzc3NDU5Myw2LjQ3NTM0MjI0IDUuNDE2MjI4OTIsNi4zMDk1Mjc3NCA1LjYxNTU5OTMsNi4wOTgzMjg2NiBDNS44MTQ5Njk2OSw1Ljg4Njc3MjIyIDUuOTcwMDM1NTUsNS42NDA1NTE5OCA2LjA4MDc5Njg4LDUuMzYwMzgyNjUgQzYuMTkxMjEyMDgsNS4wODA1NzA2NyA2LjI0NjkzODg3LDQuNzgwMDMxODkgNi4yNDY5Mzg4Nyw0LjQ2MDE5NTcyIEM2LjI0NjkzODg3LDQuMTM5NjQ0ODQgNi4xOTEyMTIwOCwzLjgzOTQ2MzQxIDYuMDgwNzk2ODgsMy41NTkyOTQwOCBDNS45NzAwMzU1NSwzLjI3OTEyNDc1IDUuODE0OTY5NjksMy4wMzYxMjA3MyA1LjYxNTU5OTMsMi44MzAyODIwNCBDNS40MTYyMjg5MiwyLjYyNDQ0MzM0IDUuMTc3NzQ1OTMsMi40NjE0ODc3MSA0LjkwMTE4ODc0LDIuMzQxNDE1MTQgQzQuNjI0Mjg1NDIsMi4yMjEzNDI1NyA0LjMxOTY5MTc3LDIuMTYxMzA2MjggMy45ODc0MDc3OSwyLjE2MTMwNjI4IFoiPjwvcGF0aD48L2NsaXBQYXRoPjwvZGVmcz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjMzLjAgLTE2MC4wKSI+PGcgY2xpcC1wYXRoPSJ1cmwoI2kwKSI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjMzLjAgMTYwLjApIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC4wMDAxODA1NTU1NTU1NTIwNzU0OCAwLjApIj48ZyBjbGlwLXBhdGg9InVybCgjaTEpIj48cG9seWdvbiBwb2ludHM9IjAsMCA1MiwwIDUyLDUyIDAsNTIgMCwwIiBzdHJva2U9Im5vbmUiIGZpbGw9InVybCgjaTIpIj48L3BvbHlnb24+PC9nPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3LjU4MzMzMzMzMzMzMzMzMiAxNC44MDU1NTU1NTU1NTU1NSkiPjxnIGNsaXAtcGF0aD0idXJsKCNpMykiPjxnIGNsaXAtcGF0aD0idXJsKCNpNCkiPjxwb2x5Z29uIHBvaW50cz0iMCwwIDM2LjQ3OTE2NjcsMCAzNi40NzkxNjY3LDUuNjEyMTc5NDkgMCw1LjYxMjE3OTQ5IDAsMCIgc3Ryb2tlPSJub25lIiBmaWxsPSIjRkZGRkZGIj48L3BvbHlnb24+PC9nPjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNy41ODMzMzMzMzMzMzMzNzEgMjQuNDMyMDgwMjU1NDc3MzMpIj48ZyBjbGlwLXBhdGg9InVybCgjaTUpIj48cG9seWdvbiBwb2ludHM9IjAsMCAzNy4xOTQ0NDQ0LDAgMzcuMTk0NDQ0NCwxMi41MzkwMDcxIDAsMTIuNTM5MDA3MSAwLDAiIHN0cm9rZT0ibm9uZSIgZmlsbD0iI0ZGRkZGRiI+PC9wb2x5Z29uPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+", + "icon_light": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgd2lkdGg9IjUycHgiIGhlaWdodD0iNTJweCIgdmlld0JveD0iMCAwIDUyLjAgNTIuMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGRlZnM+PGNsaXBQYXRoIGlkPSJpMCI+PHBhdGggZD0iTTM2MCwwIEwzNjAsODAwIEwwLDgwMCBMMCwwIEwzNjAsMCBaIj48L3BhdGg+PC9jbGlwUGF0aD48Y2xpcFBhdGggaWQ9ImkxIj48cGF0aCBkPSJNMjYsMCBDMzMuOTkxMDI3OCwwIDQxLjEzOTU4MzMsMC45NzUgNDUuOTA4Nzc3OCw1Ljc3Nzc3Nzc4IEM0OS43MTAxOTQ0LDkuNjA1OTE2NjcgNTIsMTUuODY1MDU1NiA1MiwyNiBDNTIsMzYuMTM0OTQ0NCA0OS43MDk4MzMzLDQyLjM5NDQ0NDQgNDUuOTA4MDU1Niw0Ni4yMjI1ODMzIEM0MS4xMzg4NjExLDUxLjAyNDYzODkgMzMuOTkwMzA1Niw1MiAyNiw1MiBDMTguMDA4OTcyMiw1MiAxMC44NjA3Nzc4LDUxLjAyNDYzODkgNi4wOTE1ODMzMyw0Ni4yMjI1ODMzIEMyLjI5MDE2NjY3LDQyLjM5NDQ0NDQgMCwzNi4xMzQ5NDQ0IDAsMjYgQzAsMTUuODY1MDU1NiAyLjI4OTgwNTU2LDkuNjA1NTU1NTYgNi4wOTA4NjExMSw1Ljc3Nzc3Nzc4IEMxMC44NjAwNTU2LDAuOTc1IDE4LjAwODYxMTEsMCAyNiwwIFoiPjwvcGF0aD48L2NsaXBQYXRoPjxsaW5lYXJHcmFkaWVudCBpZD0iaTIiIHgxPSIyNnB4IiB5MT0iNTJweCIgeDI9IjI2cHgiIHkyPSIwLjE5NTkyMTE0OHB4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzI5MjlCMiIgb2Zmc2V0PSIwJSI+PC9zdG9wPjxzdG9wIHN0b3AtY29sb3I9IiMxQTQwQ0MiIG9mZnNldD0iMTAwJSI+PC9zdG9wPjwvbGluZWFyR3JhZGllbnQ+PGNsaXBQYXRoIGlkPSJpMyI+PHBhdGggZD0iTTM3LjE5NDQ0NDQsMCBMMzcuMTk0NDQ0NCw1LjcyMjIyMjIyIEwwLDUuNzIyMjIyMjIgTDAsMCBMMzcuMTk0NDQ0NCwwIFoiPjwvcGF0aD48L2NsaXBQYXRoPjxjbGlwUGF0aCBpZD0iaTQiPjxwYXRoIGQ9Ik0xLjg4MzQyMjEzLDAgQzIuNjIwNzU5ODcsMCAzLjY0MzU2NDAyLDAuMTgxNjEwODcxIDMuNjQzNTY0MDIsMS4zMjExMTgxOSBMMy42NDM1NjQwMiwxLjY4OTExNTYyIEwyLjM0Mjc5MzM5LDEuNjg5MTE1NjIgTDIuMzQyNzkzMzksMS4zNjQ5MDY1OSBDMi4zNDI3OTMzOSwxLjA3OTU3NTczIDIuMTYzMTk2NjQsMC44ODkxNTMzNzEgMS44NTgxNzY4LDAuODg5MTUzMzcxIEMxLjUyOTMxNzg4LDAuODg5MTUzMzcxIDEuNDE2NDgzOTgsMS4wNzUyNzA4OCAxLjM4MDg1OTI3LDEuMjQyMTUxMDkgQzEuMzY2Nzk2ODgsMS4zMDAyNjY1NyAxLjM2MDkwNDA4LDEuNDExNzIxODQgMS4zODYxNDk0MSwxLjUxNzI1NzkzIEMxLjUzNDYwODAyLDIuMTMwNDk3MyAzLjUxMjQ0OTAyLDIuNDU2MTE4ODcgMy43MzI1NTg4MywzLjU1NTUzNzI3IEMzLjc1MzcxOTM3LDMuNjY3MDU5OCAzLjgwMDc5NDg4LDMuOTYxMTM0ODggMy43MzgwNDk4Niw0LjQxMzAwOTYzIEMzLjYxMTgyMzIxLDUuMjg5NjUyMDMgMi44MzgwNTcyLDUuNjEyMTc5NDkgMS44OTU4MTA0Myw1LjYxMjE3OTQ5IEMwLjkxNTcyOTEzNiw1LjYxMjE3OTQ5IDAsNS4yNTk5ODg5MiAwLDQuMDg4ODAwNiBMMCwzLjY4ODI0NzczIEwxLjM5OTQwODIzLDMuNjg4MjQ3NzMgTDEuNDAxMjE2MjUsNC4xOTIzMTg3OSBDMS40MDEyMTYyNSw0LjQ3ODY1ODYgMS41OTYwODA3Myw0LjY2OTI4Mjc1IDEuOTIxODU5MzIsNC42NjkyODI3NSBDMi4yNzA3NDA0LDQuNjY5MjgyNzUgMi4zODgzOTU2OSw0LjQ5MTUwNTg5IDIuNDMxMTg1NTIsNC4zMTU0MTA2MSBDMi40NTYyMjk5Niw0LjIxNjM5OTA1IDIuNDcxNDk3NjksNC4wNTQ2MzA4NSAyLjQyMTAwNzAzLDMuOTI4NjQ2NzEgQzIuMTUxMzQ0MDYsMy4yNTA5NjkxMSAwLjI5NzkyMTY3NywyLjk0MTI4ODk1IDAuMDcyMTE5OTQ3MywxLjg3MDMyMjkyIEMwLjAxNzM0MzYwODUsMS42MDU2NDE4OSAwLjAyMzgzOTA5MTIsMS4zOTkwNzYzNCAwLjA2MTc0MDU2NzcsMS4xNjQyNjAyMSBDMC4yMDAyMjE1ODEsMC4zMDg4NzMwMDcgMC45NTcxMTI3MjcsMCAxLjg4MzQyMjEzLDAgWiBNMTguODQxMTE4NiwwLjAyOTY2MzEwODkgQzE5LjU3MDQ4NzcsMC4wMjk2NjMxMDg5IDIwLjU3Nzg5MDEsMC4yMDY5NjkxMjkgMjAuNTc3ODkwMSwxLjMzNTY0NzA2IEwyMC41Nzc4OTAxLDEuNzAwNzUyMTcgTDE5LjI5MjE4NjQsMS43MDA3NTIxNyBMMTkuMjkyMTg2NCwxLjM4MDQ0NDQxIEMxOS4yOTIxODY0LDEuMDk3NDAwNSAxOS4xMTU2MDMsMC45MDg3OTQyNSAxOC44MTQ0MDAxLDAuOTA4Nzk0MjUgQzE4LjQ5MTIzMzEsMC45MDg3OTQyNSAxOC4zNzkwNjg4LDEuMDkxNjE1ODYgMTguMzQxNzcsMS4yNTkzNzA0OSBDMTguMzI5NzgzNSwxLjMxNjgxMzM0IDE4LjMyMzA4NzEsMS40MjY2NTQyOCAxOC4zNDYyNTY2LDEuNTMwMTcyNDggQzE4LjQ5NDMxMzQsMi4xMzY0MTY0NyAyMC40NTAzOTEyLDIuNDYzMTE0MjUgMjAuNjY2MDE0NCwzLjU0OTIxNDUyIEMyMC42ODk2NTI2LDMuNjU5MDU1NDcgMjAuNzM0MDQ5NiwzLjk1MDcwOTA3IDIwLjY3NTE4ODUsNC4zOTg0MTM1IEMyMC41NTE3NzQzLDUuMjY1MTAwOTMgMTkuNzgyNDk0OSw1LjU4NDgwMzMzIDE4Ljg1MTA5NjIsNS41ODQ4MDMzMyBDMTcuODc4NTgxOCw1LjU4NDgwMzMzIDE2Ljk3NTY0MjgsNS4yMzU0Mzc4MyAxNi45NzU2NDI4LDQuMDc3NTAwMzcgTDE2Ljk3NTY0MjgsMy42Nzc4ODkxOSBMMTguMzU5NTE1NCwzLjY3Nzg4OTE5IEwxOC4zNTk5MTcyLDQuMTgwNjE0OTggQzE4LjM1OTkxNzIsNC40NjMwNTM1MiAxOC41NTUxODM0LDQuNjUwNDQ5MDMgMTguODc5NzU2Nyw0LjY1MDQ0OTAzIEMxOS4yMjU3NTgzLDQuNjUwNDQ5MDMgMTkuMzQyNDc2MSw0LjQ3NTE2MDkxIDE5LjM4MjM4NjUsNC4zMDA4ODE3NCBDMTkuNDA2MzU5NSw0LjIwNTU2OTY2IDE5LjQxOTgxOTIsNC4wNDM4MDE0NiAxOS4zNzI4MTA3LDMuOTE2OTQyOSBDMTkuMTA2NDI4OSwzLjI0NzI2OTYzIDE3LjI3MTE1MzcsMi45NDAwNzgyMSAxNy4wNDc3NjI3LDEuODgxMTUyMyBDMTYuOTkwMTA2OSwxLjYxOTM2MzYgMTYuOTk5MDgwMSwxLjQxNDIxMDU4IDE3LjAzNTMwNzQsMS4xODMwOTM5MyBDMTcuMTcyMzE1MywwLjMzMzgyNzY4NiAxNy45MjI1MSwwLjAyOTY2MzEwODkgMTguODQxMTE4NiwwLjAyOTY2MzEwODkgWiBNMjMuMjM2NDg0NSwwLjE2Njg4MDIxMSBMMjMuMjM2MjI5MSw0LjExMTM3MzY2IEMyMy4yMzcyMDYzLDQuMTU3OTg0NjIgMjMuMjQwODgxOCw0LjIwNDA2NzQ1IDIzLjI0OTY3NjQsNC4yNDExNTE5NCBDMjMuMjc1MTIyNiw0LjM3MTIzOTEzIDIzLjM4Nzc1NTYsNC42MjE1OTMwOCAyMy43NDY5NDkxLDQuNjIxNTkzMDggQzI0LjExMDgzMDEsNC42MjE1OTMwOCAyNC4yMjA1ODM2LDQuMzcxMjM5MTMgMjQuMjQ4MTA1Nyw0LjI0MTE1MTk0IEMyNC4yNTk2OTA1LDQuMTg1NTI1MiAyNC4yNjE3NjYzLDQuMTA5NjUyMjIgMjQuMjU5NjkwNSw0LjA0MjExOTg4IEwyNC4yNTk2OTA1LDAuMTY2ODgwMjExIEwyNS41Nzg2MDgzLDAuMTY2ODgwMjExIEwyNS41Nzg2MDgzLDMuOTIxODUzMTIgQzI1LjU4NDMwMDIsNC4wMTg2NDQ5OSAyNS41NzQ3MjQ0LDQuMjE2Mzk5MDUgMjUuNTY3NDI1Myw0LjI2ODE5MTc4IEMyNS40NzQ3NDc1LDUuMjQ2NjcwNzkgMjQuNzA3NDc3LDUuNTY0MzU1MjkgMjMuNzQ2OTQ5MSw1LjU2NDM1NTI5IEMyMi43ODgyOTYyLDUuNTY0MzU1MjkgMjIuMDIwNTU3LDUuMjQ2NjcwNzkgMjEuOTI5NTUzMiw0LjI2ODE5MTc4IEMyMS45MjM4NjEzLDQuMjE2Mzk5MDUgMjEuOTE2Mjk0NCw0LjAxODY0NDk5IDIxLjkxNzk2ODUsMy45MjE4NTMxMiBMMjEuOTE3OTY4NSwwLjE2Njg4MDIxMSBMMjMuMjM2NDg0NSwwLjE2Njg4MDIxMSBaIE0zNC42Mjk3NjIxLDAuMDI1OTYzNjI4MiBDMzUuNTUzOTk1NiwwLjAyNTk2MzYyODIgMzYuMzYwMDM4MiwwLjMzNjg1NDUzNCAzNi40NTg3NDI3LDEuMzE5NTAzODcgQzM2LjQ2NTU3MywxLjM5MTE5NjkyIDM2LjQ2ODM4MTQsMS40NjUxMTM3OCAzNi40NjkzNjA3LDEuNTI2MTgwMjIgTDM2LjQ2OTAwNCwxLjY1NTc1NDAyIEwzNi40Njg3MjAzLDEuNjY2MTc4ODQgTDM2LjQ2ODcyMDMsMS44MzgwMzY1NCBMMzUuMTU1MzYwNSwxLjgzODAzNjU0IEwzNS4xNTUxNSwxLjUzMzU1NTU2IEMzNS4xNTQ0NDcxLDEuNDk4NzMzNjIgMzUuMTUxNDksMS40MDU2NDEyMyAzNS4xMzk0OTAxLDEuMzQ1MjY1NzEgQzM1LjExNjY1NTUsMS4yMzEzMjE3IDM1LjAxNzA4MDQsMC45NjYwMzUzMDYgMzQuNjE4MTc3NCwwLjk2NjAzNTMwNiBDMzQuMjM4MTU4MiwwLjk2NjAzNTMwNiAzNC4xMjU1OTIxLDEuMjE3NTk5OTkgMzQuMDk5Njc3MiwxLjM0NTI2NTcxIEMzNC4wODE3OTc4LDEuNDE1NDIxMzIgMzQuMDc2MTA1OSwxLjUwODExMDEyIDM0LjA3NjEwNTksMS41OTI3OTQ2IEwzNC4wNzYxMDU5LDMuOTg2ODk2NzIgQzM0LjA3NjEwNTksNC4wNTQ2MzA4NSAzNC4wODAxOTA3LDQuMTI3NjExNTEgMzQuMDg5NzY2NSw0LjE4NjEzMDU3IEMzNC4xMTI1MzQyLDQuMzI3NTE4IDM0LjI0Mzg1MDEsNC41NjgyNTMzIDM0LjYyMDk4OTksNC41NjgyNTMzIEMzNS4wMDA0MDY0LDQuNTY4MjUzMyAzNS4xMzQxMzMsNC4zMjc1MTggMzUuMTU1MzYwNSw0LjE4NjEzMDU3IEMzNS4xNjY5NDUyLDQuMTI3NjExNTEgMzUuMTcwNjI4Miw0LjA1NDYzMDg1IDM1LjE2ODk1NDEsMy45ODY4OTY3MiBMMzUuMTY4OTU0MSwzLjIyODkwNjc2IEwzNC42MzQ0NDk2LDMuMjI4OTA2NzYgTDM0LjYzNDQ0OTYsMi40NjQ5MzAzNiBMMzYuNDc5MTY2NywyLjQ2NDkzMDM2IEwzNi40NzkxNjY3LDMuODY4NTEzMzQgQzM2LjQ3NzA5MDgsMy45NjQ0MzA3OCAzNi40NzU0ODM3LDQuMDM4Njg5NDUgMzYuNDYwMDE1LDQuMjEzOTc3NTcgQzM2LjM3MjgyODIsNS4xNjk1ODcwNyAzNS41NTM5OTU2LDUuNTA4MzI0OTcgMzQuNjI2MDc5MSw1LjUwODMyNDk3IEMzMy43MDM4NTQ1LDUuNTA4MzI0OTcgMzIuODc5MzMsNS4xNjk1ODcwNyAzMi43OTM2MTY0LDQuMjEzOTc3NTcgQzMyLjc3NTkzOCw0LjAzODY4OTQ1IDMyLjc3Mjg1NzYsMy45NjQ0MzA3OCAzMi43NzI4NTc2LDMuODY4NTEzMzQgTDMyLjc3Mjg1NzYsMS42NjYxNzg4NCBDMzIuNzcyODU3NiwxLjU3MDI2MTQgMzIuNzg4NzI4LDEuNDA5MDk4NTcgMzIuNzk5MTA3NCwxLjMxOTUwMzg3IEMzMi45MTQxNTExLDAuMzM5NzQ2ODU1IDMzLjcwMzg1NDUsMC4wMjU5NjM2MjgyIDM0LjYyOTc2MjEsMC4wMjU5NjM2MjgyIFogTTEyLjE0NDc0NDcsMC4xNjY4ODAyMTEgTDEyLjgwMjI2MTYsNC4yNjE1OTk5OCBMMTMuNDYwMTgwNCwwLjE2Njg4MDIxMSBMMTUuNTg1Mjc0NiwwLjE2Njg4MDIxMSBMMTUuNzAxOTI1NSw1LjQwNTIxMDM2IEwxNC4zOTUyNjIsNS40MDUyMTAzNiBMMTQuMzU5ODM4MiwwLjU1NTkzMTA1NCBMMTMuNDYyMjU2Miw1LjQwNTIxMDM2IEwxMi4xMzk4NTYzLDUuNDA1MjEwMzYgTDExLjI0MzA3NzksMC41NTU5MzEwNTQgTDExLjIwNzc4OCw1LjQwNTIxMDM2IEw5LjkwNDQwNTgsNS40MDUyMTAzNiBMMTAuMDE3MjM5NywwLjE2Njg4MDIxMSBMMTIuMTQ0NzQ0NywwLjE2Njg4MDIxMSBaIE03LjkwMTI1MjUsMC4xNjY4ODAyMTEgTDguODYzMjUzNTgsNS40MDUyMTAzNiBMNy40NjQzMTQxLDUuNDA1MjEwMzYgTDYuNzUzODI4ODMsMC41NTU5MzEwNTQgTDYuMDI1ODY2MDIsNS40MDUyMTAzNiBMNC42MTcxNDk4Myw1LjQwNTIxMDM2IEw1LjU4MzE2ODczLDAuMTY2ODgwMjExIEw3LjkwMTI1MjUsMC4xNjY4ODAyMTEgWiBNMjguMzA0ODM2LDUuMzUwNTkyNTcgTDI3LjAyNDYyMzMsNS4zNTA1OTI1NyBMMjcuMDI0NjIzMywwLjE2Njg4MDIxMSBMMjguOTU5ODc1MywwLjE2Njg4MDIxMSBMMzAuMTg3OTkwMyw0LjM4NDM1NTQ3IEwzMC4xMTY4NzQ4LDAuMTY2ODgwMjExIEwzMS40MDU0NTgxLDAuMTY2ODgwMjExIEwzMS40MDU0NTgxLDUuMzUwNTkyNTcgTDI5LjU0OTQyNDEsNS4zNTA1OTI1NyBMMjguMjMsMC45OTkgTDI4LjMwNDgzNiw1LjM1MDU5MjU3IFoiPjwvcGF0aD48L2NsaXBQYXRoPjxjbGlwUGF0aCBpZD0iaTUiPjxwYXRoIGQ9Ik0yNC4zMzUyOTY2LDIuNDcwMDY0MzIgQzI1LjMwOTY1MDIsMi40NzAwNjQzMiAyNi4xMjEzMjMsMi42NTY2MDU2NCAyNi43NjkyNzY4LDMuMDI4OTczNTYgQzI3LjQxNzIzMDUsMy40MDE2OTg4MyAyNy45Mjk1MDE3LDMuOTA4NDMzNjcgMjguMzA2MDkwMiw0LjU1MDI1MDE1IEwyNi4zOTU0NTczLDUuNDgyNTk5MzcgQzI2LjE5NjA4NjksNS4xNDYzMjQ3IDI1LjkxOTE4MzYsNC44ODAwOTIzNiAyNS41NjQ3NDczLDQuNjg0NjE3MDggQzI1LjIxMDMxMTEsNC40ODkxNDE3OSAyNC44MDA0OTQyLDQuMzkxMjI1NDcgMjQuMzM1Mjk2Niw0LjM5MTIyNTQ3IEMyMy44MDM2NDIyLDQuMzkxMjI1NDcgMjMuNDEwNDM5NSw0LjQ5NDg1OTUzIDIzLjE1NTY4ODUsNC43MDIxMjc2NiBDMjIuOTAwNTkxMyw0LjkwOTM5NTc5IDIyLjc3MzU2MTksNS4xNDk1NDA5MyAyMi43NzM1NjE5LDUuNDIyMjA1NzMgQzIyLjc3MzU2MTksNS43Mzg0NjgzMSAyMi45NjE4NTYyLDUuOTY1MDMzODEgMjMuMzM4NDQ0Nyw2LjEwMDgzMDE3IEMyMy43MTQ2ODcsNi4yMzczNDEyNSAyNC4yNjg4Mzk4LDYuMzgyMDcxNTggMjQuOTk5ODY0Niw2LjUzNDY2MzgxIEMyNS4zOTg2MDU0LDYuNjExMTM4NiAyNS43OTk3NjksNi43MTE1NTY0NCAyNi4yMDQzOTQsNi44MzczNDY3NSBDMjYuNjA4NjcyOSw2Ljk2Mjc3OTcgMjYuOTc2OTU0Myw3LjEzMTgxMDQzIDI3LjMwOTIzODMsNy4zNDQ3OTYzMSBDMjcuNjQxNTIyMiw3LjU1NzQyNDgyIDI3LjkxMDExODUsNy44Mjk3MzIyNiAyOC4xMTUwMjY5LDguMTYyNzkwNyBDMjguMzE5OTM1NCw4LjQ5NTQ5MTc4IDI4LjQyMjM4OTYsOC45MTI1Mjk1NSAyOC40MjIzODk2LDkuNDE0MjYxMzcgQzI4LjQyMjM4OTYsOS43NTIzMjI4MyAyOC4zNDQ4NTY3LDEwLjEwNDMyMTMgMjguMTg5NzkwOCwxMC40Njk1NDIgQzI4LjAzNDM3ODgsMTAuODM0NzYyOCAyNy43OTM4MTkxLDExLjE3MzE4MTYgMjcuNDY3MDczMSwxMS40ODM3MjY0IEMyNy4xNDAzMjcyLDExLjc5NDk4NiAyNi43Mjc3NDEzLDEyLjA0ODM1MzQgMjYuMjI5MzE1MywxMi4yNDQ1NDM0IEMyNS43MzA4ODkzLDEyLjQ0MTA5MDggMjUuMTMyNzc4MiwxMi41MzkwMDcxIDI0LjQzNDk4MTgsMTIuNTM5MDA3MSBDMjMuMzYwNTk2OSwxMi41MzkwMDcxIDIyLjQ2ODk2ODIsMTIuMzMyODExIDIxLjc2MDA5NTcsMTEuOTIwMDYxNiBDMjEuMDUxMjIzMywxMS41MDY5NTQ4IDIwLjUwMjk1NDcsMTAuOTEwNTIyOCAyMC4xMTUyOSwxMC4xMzAwNTExIEwyMi4xOTIwNjQ5LDkuMTY1MTgyMjUgQzIyLjQyNDY2MzcsOS42MDQ3MzM2MyAyMi43NDAzMzM1LDkuOTQyNDM3NzQgMjMuMTM5MDc0MywxMC4xNzg2NTE5IEMyMy41Mzc4MTUxLDEwLjQxNDUwODggMjQuMDAzMDEyNiwxMC41MzIwNzk4IDI0LjUzNDY2NywxMC41MzIwNzk4IEMyNS4wODg0NzM2LDEwLjUzMjA3OTggMjUuNTAzODI4NiwxMC40MTc3MjUgMjUuNzgwNzMxOSwxMC4xODkwMTUzIEMyNi4wNTcyODkxLDkuOTU5OTQ4MzIgMjYuMTk2MDg2OSw5LjY4NzY0MDg4IDI2LjE5NjA4NjksOS4zNzEwMjA5NSBDMjYuMTk2MDg2OSw5LjE5NjYyOTgzIDI2LjEzMjM5OTIsOS4wNTUxMTU3MyAyNi4wMDUwMjM2LDguOTQ1NzYzOTIgQzI1Ljg3NzY0ODEsOC44MzcxMjY4MyAyNS43MTE1MDYxLDguNzQxMzU0NjYgMjUuNTA2NTk3Niw4LjY1OTg3Njg1IEMyNS4zMDEzNDMxLDguNTc4MDQxNjcgMjUuMDYwNzgzMyw4LjUxMDE0MzQ5IDI0Ljc4Mzg4LDguNDU1MTEwMjMgQzI0LjUwNjk3NjcsOC40MDA3OTE2OSAyNC4yMTg5OTcyLDguMzQwNzU1NCAyMy45MTk5NDE2LDguMjc1MzU4NzMgQzIzLjQ5ODcwMjUsOC4xODgxNjMxOCAyMy4wODY0NjI2LDguMDg0ODg2NDcgMjIuNjgyMTgzOCw3Ljk2NDgxMzkgQzIyLjI3NzkwNSw3Ljg0NTA5ODY5IDIxLjkxNTE2MTYsNy42Nzg1Njk0NyAyMS41OTM5NTM4LDcuNDY2Mjk4MzEgQzIxLjI3Mjc0NTksNy4yNTMzMTI0NCAyMS4wMTI0NTY4LDYuOTgwNjQ3NjQgMjAuODEzMDg2NCw2LjY0ODMwMzkyIEMyMC42MTM3MTYsNi4zMTU5NjAyIDIwLjUxNDAzMDgsNS44OTg5MjI0MyAyMC41MTQwMzA4LDUuMzk3NTQ3OTcgQzIwLjUxNDAzMDgsNS4wMTU1MzEzNyAyMC42MDU0MDg5LDQuNjQ3ODA5MTIgMjAuNzg4MTY1MSw0LjI5MzY2NjUgQzIwLjk3MDkyMTMsMy45MzkxNjY1MyAyMS4yMjg0NDE0LDMuNjI2MTIwMTggMjEuNTYwNzI1NCwzLjM1MzA5ODAzIEMyMS44OTMwMDkzLDMuMDgwNzkwNTkgMjIuMjk0MTczLDIuODY1NjYwNTYgMjIuNzY1MjU0OCwyLjcwNzM1MDYgQzIzLjIzNTk5MDQsMi41NDkwNDA2MyAyMy43NTkzMzc3LDIuNDcwMDY0MzIgMjQuMzM1Mjk2NiwyLjQ3MDA2NDMyIFogTTMzLjEwNzM1MTUsMi40NzAwNjQzMiBDMzQuMDgxNzA1LDIuNDcwMDY0MzIgMzQuODkzMzc3OSwyLjY1NjYwNTY0IDM1LjU0MTMzMTYsMy4wMjg5NzM1NiBDMzYuMTg5Mjg1NCwzLjQwMTY5ODgzIDM2LjcwMTU1NjUsMy45MDg0MzM2NyAzNy4wNzgxNDUxLDQuNTUwMjUwMTUgTDM1LjE2NzUxMjIsNS40ODI1OTkzNyBDMzQuOTY4MTQxOCw1LjE0NjMyNDcgMzQuNjkxMjM4NCw0Ljg4MDA5MjM2IDM0LjMzNjgwMjIsNC42ODQ2MTcwOCBDMzMuOTgyMzY1OSw0LjQ4OTE0MTc5IDMzLjU3MjU0OSw0LjM5MTIyNTQ3IDMzLjEwNzM1MTUsNC4zOTEyMjU0NyBDMzIuNTc1Njk3MSw0LjM5MTIyNTQ3IDMyLjE4MjQ5NDQsNC40OTQ4NTk1MyAzMS45Mjc3NDMzLDQuNzAyMTI3NjYgQzMxLjY3MjY0NjEsNC45MDkzOTU3OSAzMS41NDU2MTY3LDUuMTQ5NTQwOTMgMzEuNTQ1NjE2Nyw1LjQyMjIwNTczIEMzMS41NDU2MTY3LDUuNzM4NDY4MzEgMzEuNzMzOTExLDUuOTY1MDMzODEgMzIuMTEwNDk5NSw2LjEwMDgzMDE3IEMzMi40ODY3NDE5LDYuMjM3MzQxMjUgMzMuMDQwODk0Nyw2LjM4MjA3MTU4IDMzLjc3MTkxOTQsNi41MzQ2NjM4MSBDMzQuMTcwNjYwMiw2LjYxMTEzODYgMzQuNTcxODIzOSw2LjcxMTU1NjQ0IDM0Ljk3NjQ0ODksNi44MzczNDY3NSBDMzUuMzgwNzI3Nyw2Ljk2Mjc3OTcgMzUuNzQ5MDA5MSw3LjEzMTgxMDQzIDM2LjA4MTI5MzEsNy4zNDQ3OTYzMSBDMzYuNDEzNTc3MSw3LjU1NzQyNDgyIDM2LjY4MjE3MzMsNy44Mjk3MzIyNiAzNi44ODcwODE4LDguMTYyNzkwNyBDMzcuMDkxOTkwMiw4LjQ5NTQ5MTc4IDM3LjE5NDQ0NDQsOC45MTI1Mjk1NSAzNy4xOTQ0NDQ0LDkuNDE0MjYxMzcgQzM3LjE5NDQ0NDQsOS43NTIzMjI4MyAzNy4xMTY5MTE1LDEwLjEwNDMyMTMgMzYuOTYxODQ1NywxMC40Njk1NDIgQzM2LjgwNjQzMzcsMTAuODM0NzYyOCAzNi41NjU4NzM5LDExLjE3MzE4MTYgMzYuMjM5MTI4LDExLjQ4MzcyNjQgQzM1LjkxMjM4MjEsMTEuNzk0OTg2IDM1LjQ5OTc5NjEsMTIuMDQ4MzUzNCAzNS4wMDEzNzAyLDEyLjI0NDU0MzQgQzM0LjUwMjk0NDIsMTIuNDQxMDkwOCAzMy45MDQ4MzMsMTIuNTM5MDA3MSAzMy4yMDcwMzY3LDEyLjUzOTAwNzEgQzMyLjEzMjY1MTgsMTIuNTM5MDA3MSAzMS4yNDEwMjMxLDEyLjMzMjgxMSAzMC41MzIxNTA2LDExLjkyMDA2MTYgQzI5LjgyMzI3ODEsMTEuNTA2OTU0OCAyOS4yNzUwMDk1LDEwLjkxMDUyMjggMjguODg3MzQ0OSwxMC4xMzAwNTExIEwzMC45NjQxMTk4LDkuMTY1MTgyMjUgQzMxLjE5NjcxODYsOS42MDQ3MzM2MyAzMS41MTIzODgzLDkuOTQyNDM3NzQgMzEuOTExMTI5MSwxMC4xNzg2NTE5IEMzMi4zMDk4Njk5LDEwLjQxNDUwODggMzIuNzc1MDY3NSwxMC41MzIwNzk4IDMzLjMwNjcyMTgsMTAuNTMyMDc5OCBDMzMuODYwNTI4NSwxMC41MzIwNzk4IDM0LjI3NTg4MzUsMTAuNDE3NzI1IDM0LjU1Mjc4NjgsMTAuMTg5MDE1MyBDMzQuODI5MzQ0LDkuOTU5OTQ4MzIgMzQuOTY4MTQxOCw5LjY4NzY0MDg4IDM0Ljk2ODE0MTgsOS4zNzEwMjA5NSBDMzQuOTY4MTQxOCw5LjE5NjYyOTgzIDM0LjkwNDQ1NCw5LjA1NTExNTczIDM0Ljc3NzA3ODUsOC45NDU3NjM5MiBDMzQuNjQ5NzAyOSw4LjgzNzEyNjgzIDM0LjQ4MzU2MSw4Ljc0MTM1NDY2IDM0LjI3ODY1MjUsOC42NTk4NzY4NSBDMzQuMDczMzk3OSw4LjU3ODA0MTY3IDMzLjgzMjgzODIsOC41MTAxNDM0OSAzMy41NTU5MzQ4LDguNDU1MTEwMjMgQzMzLjI3OTAzMTUsOC40MDA3OTE2OSAzMi45OTEwNTIxLDguMzQwNzU1NCAzMi42OTE5OTY1LDguMjc1MzU4NzMgQzMyLjI3MDc1NzMsOC4xODgxNjMxOCAzMS44NTg1MTc1LDguMDg0ODg2NDcgMzEuNDU0MjM4Niw3Ljk2NDgxMzkgQzMxLjA0OTk1OTgsNy44NDUwOTg2OSAzMC42ODcyMTY1LDcuNjc4NTY5NDcgMzAuMzY2MDA4Niw3LjQ2NjI5ODMxIEMzMC4wNDQ4MDA4LDcuMjUzMzEyNDQgMjkuNzg0NTExNiw2Ljk4MDY0NzY0IDI5LjU4NTE0MTIsNi42NDgzMDM5MiBDMjkuMzg1NzcwOSw2LjMxNTk2MDIgMjkuMjg2MDg1Nyw1Ljg5ODkyMjQzIDI5LjI4NjA4NTcsNS4zOTc1NDc5NyBDMjkuMjg2MDg1Nyw1LjAxNTUzMTM3IDI5LjM3NzQ2MzgsNC42NDc4MDkxMiAyOS41NjAyMTk5LDQuMjkzNjY2NSBDMjkuNzQyOTc2MSwzLjkzOTE2NjUzIDMwLjAwMDQ5NjIsMy42MjYxMjAxOCAzMC4zMzI3ODAyLDMuMzUzMDk4MDMgQzMwLjY2NTA2NDIsMy4wODA3OTA1OSAzMS4wNjYyMjc5LDIuODY1NjYwNTYgMzEuNTM3MzA5NiwyLjcwNzM1MDYgQzMyLjAwODA0NTMsMi41NDkwNDA2MyAzMi41MzEzOTI2LDIuNDcwMDY0MzIgMzMuMTA3MzUxNSwyLjQ3MDA2NDMyIFogTTEzLjc3MzIwNTcsMi40NzAwMjg1OSBDMTQuNDE1NjIxNCwyLjQ3MDAyODU5IDE1LjAwODE5NDUsMi41OTAxMDExNiAxNS41NTA5MjUsMi44Mjk1MzE1OSBDMTYuMDkzMzA5NCwzLjA2OTY3NjczIDE2LjU0MjIzODksMy4zOTY2NjAwNyAxNi44OTY2NzUxLDMuODEwODM4OTcgTDE2Ljg5NjY3NTEsMi40ODcxODE4MSBMMTkuMTM5NTkyLDIuNDg3MTgxODEgTDE5LjEzOTU5MiwxMi41MjE4MTgxIEwxNi44OTY2NzUxLDEyLjUyMTgxODEgTDE2Ljg5NjY3NTEsMTEuMDk1OTU2MyBDMTYuNTQyMjM4OSwxMS41NDQwODQzIDE2LjA4ODExNzQsMTEuODk2Nzk3NSAxNS41MzQzMTA4LDEyLjE1MzczODUgQzE0Ljk4MDUwNDIsMTIuNDEwNjc5NSAxNC4zODIzOTMsMTIuNTM4OTcxNCAxMy43Mzk5NzczLDEyLjUzODk3MTQgQzEzLjE1Mjk0MjMsMTIuNTM4OTcxNCAxMi41NzQyMTQzLDEyLjQyNjQwMzMgMTIuMDAzNzkzNSwxMi4yMDA1NTI1IEMxMS40MzMzNzI2LDExLjk3NDM0NDQgMTAuOTIxMTAxNSwxMS42NDYyODkgMTAuNDY2OTgwMSwxMS4yMTYzODYzIEMxMC4wMTI4NTg2LDEwLjc4NjQ4MzYgOS42NDcwMDAxMSwxMC4yNjAwOTQgOS4zNzA0NDI5Miw5LjYzNzU3NDkxIEM5LjA5MzUzOTYsOS4wMTQ2OTg0NCA4Ljk1NTA4Nzk0LDguMzA2NDEzMjIgOC45NTUwODc5NCw3LjUxMzA3NjU4IEM4Ljk1NTA4Nzk0LDYuNzA4MzA0NDcgOS4wOTA0MjQ0NCw1Ljk5NTAxNjIyIDkuMzYyMTM1ODIsNS4zNzE3ODI0IEM5LjYzMzUwMTA3LDQuNzQ4OTA1OTMgOS45OTM0NzUzOSw0LjIyMjg3MzcxIDEwLjQ0MjA1ODgsMy43OTI5NzEwMyBDMTAuODkwNjQyMSwzLjM2MjcxMDk4IDExLjQwNTY4MjMsMy4wMzUwMTI5MiAxMS45ODcxNzkzLDIuODA5NTE5NDkgQzEyLjU2ODY3NjMsMi41ODMzMTEzNCAxMy4xNjQwMTg0LDIuNDcwMDI4NTkgMTMuNzczMjA1NywyLjQ3MDAyODU5IFogTTQuMTUzNTQ5NzgsMCBDNC43ODQ4ODkzNSwwIDUuMzY2Mzg2MzIsMC4xMTcyMTM3MDEgNS44OTgwNDA2OSwwLjM1MTk5ODQ2MSBDNi40Mjk2OTUwNiwwLjU4NjQyNTg2MiA2Ljg4OTAwODQ0LDAuOTAzNDAzMTU2IDcuMjc3MDE5MjIsMS4zMDQwMDI0MiBDNy42NjQ2ODM4NiwxLjcwNDI0NDMyIDcuOTY4OTMxMzgsMi4xNzU5NTggOC4xOTA4MDAxNywyLjcxOTE0MzQ0IEM4LjQxMjMyMjgyLDMuMjYxOTcxNTIgOC41MjMwODQxNSwzLjg0MjMyMjI4IDguNTIzMDg0MTUsNC40NjAxOTU3MiBDOC41MjMwODQxNSw1LjA3NzM1NDQ0IDguNDEyMzIyODIsNS42NjA1NjQwOCA4LjE5MDgwMDE3LDYuMjA5NDY3MjYgQzcuOTY4OTMxMzgsNi43NTgzNzA0NCA3LjY2NDY4Mzg2LDcuMjMyOTQyOTkgNy4yNzcwMTkyMiw3LjYzMzU0MjI1IEM2Ljg4OTAwODQ0LDguMDMzNzg0MTYgNi40MjY5MjYwMyw4LjM1MTExODgxIDUuODg5NzMzNTksOC41ODUxODg4NSBDNS4zNTIxOTUwMiw4LjgxOTYxNjI1IDQuNzY4Mjc1MTUsOC45MzY4Mjk5NSA0LjEzNjkzNTU4LDguOTM2ODI5OTUgTDIuMjU5NTMxMDgsOC45MzY4Mjk5NSBMMi4yNTk1MzEwOCwxMi41MjE4NTM5IEwwLDEyLjUyMTg1MzkgTDAsMCBMNC4xNTM1NDk3OCwwIFogTTE0LjEwNTQ4OTcsNC41ODAyMzI1NiBDMTMuNjk1NjcyOCw0LjU4MDIzMjU2IDEzLjMxMDc3NzEsNC42NTU2MzUyNyAxMi45NTA4MDI4LDQuODA1NzI1OTkgQzEyLjU5MDgyODUsNC45NTU4MTY3IDEyLjI3NzkyNzgsNS4xNjAyMjU5NiAxMi4wMTIxMDA2LDUuNDE3NTI0MzMgQzExLjc0NjI3MzQsNS42NzU1Mzc0MSAxMS41Mzg1OTU5LDUuOTgxNzkzOTQgMTEuMzg5MDY4MSw2LjMzNjI5MzkxIEMxMS4yMzk1NDAzLDYuNjkwNzkzODkgMTEuMTY0Nzc2NCw3LjA3MTczODQxIDExLjE2NDc3NjQsNy40ODAxOTk1NyBDMTEuMTY0Nzc2NCw3Ljg4ODMwMzM3IDExLjIzOTU0MDMsOC4yNzI0NjQxMyAxMS4zODkwNjgxLDguNjMxOTY3MTIgQzExLjUzODU5NTksOC45OTE0NzAxMiAxMS43NDYyNzM0LDkuMzAyNzI5NjcgMTIuMDEyMTAwNiw5LjU2NjQ2MDUgQzEyLjI3NzkyNzgsOS44Mjk0NzY2MSAxMi41OTA4Mjg1LDEwLjAzNjAzIDEyLjk1MDgwMjgsMTAuMTg2ODM1NCBDMTMuMzEwNzc3MSwxMC4zMzY5MjYyIDEzLjY5NTY3MjgsMTAuNDExOTcxNSAxNC4xMDU0ODk3LDEwLjQxMTk3MTUgQzE0LjUyNjM4MjcsMTAuNDExOTcxNSAxNC45MTM3MDEyLDEwLjMzNjkyNjIgMTUuMjY4NDgzNiwxMC4xODY4MzU0IEMxNS42MjI5MTk5LDEwLjAzNjAzIDE1LjkyNzE2NzQsOS44MjY2MTc3NCAxNi4xODIyNjQ2LDkuNTU3ODgzODkgQzE2LjQzNzAxNTYsOS4yODk1MDczOSAxNi42MzkxNTUsOC45Nzc4OTA0OCAxNi43ODg2ODI4LDguNjIzNzQ3ODcgQzE2LjkzODIxMDYsOC4yNjk2MDUyNiAxNy4wMTI5NzQ1LDcuODg4MzAzMzcgMTcuMDEyOTc0NSw3LjQ4MDE5OTU3IEMxNy4wMTI5NzQ1LDcuMDgyODE2NTQgMTYuOTM4MjEwNiw2LjcwNjg3NTAzIDE2Ljc4ODY4MjgsNi4zNTIzNzUwNiBDMTYuNjM5MTU1LDUuOTk3ODc1MDkgMTYuNDM3MDE1Niw1LjY4OTExNzA1IDE2LjE4MjI2NDYsNS40MjYxMDA5NCBDMTUuOTI3MTY3NCw1LjE2MjcyNzQ3IDE1LjYyMjkxOTksNC45NTU4MTY3IDE1LjI2ODQ4MzYsNC44MDU3MjU5OSBDMTQuOTEzNzAxMiw0LjY1NTYzNTI3IDE0LjUyNjM4MjcsNC41ODAyMzI1NiAxNC4xMDU0ODk3LDQuNTgwMjMyNTYgWiBNMy45ODc0MDc3OSwyLjE2MTMwNjI4IEwyLjI1OTUzMTA4LDIuMTYxMzA2MjggTDIuMjU5NTMxMDgsNi43NzU1MjM2NyBMMy45ODc0MDc3OSw2Ljc3NTUyMzY3IEM0LjMxOTY5MTc3LDYuNzc1NTIzNjcgNC42MjQyODU0Miw2LjcxNTQ4NzM4IDQuOTAxMTg4NzQsNi41OTU0MTQ4MSBDNS4xNzc3NDU5Myw2LjQ3NTM0MjI0IDUuNDE2MjI4OTIsNi4zMDk1Mjc3NCA1LjYxNTU5OTMsNi4wOTgzMjg2NiBDNS44MTQ5Njk2OSw1Ljg4Njc3MjIyIDUuOTcwMDM1NTUsNS42NDA1NTE5OCA2LjA4MDc5Njg4LDUuMzYwMzgyNjUgQzYuMTkxMjEyMDgsNS4wODA1NzA2NyA2LjI0NjkzODg3LDQuNzgwMDMxODkgNi4yNDY5Mzg4Nyw0LjQ2MDE5NTcyIEM2LjI0NjkzODg3LDQuMTM5NjQ0ODQgNi4xOTEyMTIwOCwzLjgzOTQ2MzQxIDYuMDgwNzk2ODgsMy41NTkyOTQwOCBDNS45NzAwMzU1NSwzLjI3OTEyNDc1IDUuODE0OTY5NjksMy4wMzYxMjA3MyA1LjYxNTU5OTMsMi44MzAyODIwNCBDNS40MTYyMjg5MiwyLjYyNDQ0MzM0IDUuMTc3NzQ1OTMsMi40NjE0ODc3MSA0LjkwMTE4ODc0LDIuMzQxNDE1MTQgQzQuNjI0Mjg1NDIsMi4yMjEzNDI1NyA0LjMxOTY5MTc3LDIuMTYxMzA2MjggMy45ODc0MDc3OSwyLjE2MTMwNjI4IFoiPjwvcGF0aD48L2NsaXBQYXRoPjwvZGVmcz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjMzLjAgLTE2MC4wKSI+PGcgY2xpcC1wYXRoPSJ1cmwoI2kwKSI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjMzLjAgMTYwLjApIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC4wMDAxODA1NTU1NTU1NTIwNzU0OCAwLjApIj48ZyBjbGlwLXBhdGg9InVybCgjaTEpIj48cG9seWdvbiBwb2ludHM9IjAsMCA1MiwwIDUyLDUyIDAsNTIgMCwwIiBzdHJva2U9Im5vbmUiIGZpbGw9InVybCgjaTIpIj48L3BvbHlnb24+PC9nPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3LjU4MzMzMzMzMzMzMzMzMiAxNC44MDU1NTU1NTU1NTU1NSkiPjxnIGNsaXAtcGF0aD0idXJsKCNpMykiPjxnIGNsaXAtcGF0aD0idXJsKCNpNCkiPjxwb2x5Z29uIHBvaW50cz0iMCwwIDM2LjQ3OTE2NjcsMCAzNi40NzkxNjY3LDUuNjEyMTc5NDkgMCw1LjYxMjE3OTQ5IDAsMCIgc3Ryb2tlPSJub25lIiBmaWxsPSIjRkZGRkZGIj48L3BvbHlnb24+PC9nPjwvZz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNy41ODMzMzMzMzMzMzMzNzEgMjQuNDMyMDgwMjU1NDc3MzMpIj48ZyBjbGlwLXBhdGg9InVybCgjaTUpIj48cG9seWdvbiBwb2ludHM9IjAsMCAzNy4xOTQ0NDQ0LDAgMzcuMTk0NDQ0NCwxMi41MzkwMDcxIDAsMTIuNTM5MDA3MSAwLDAiIHN0cm9rZT0ibm9uZSIgZmlsbD0iI0ZGRkZGRiI+PC9wb2x5Z29uPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" + }, + "66a0ccb3-bd6a-191f-ee06-e375c50b9846": { + "name": "Thales Bio iOS SDK", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiMyQzJGNzMiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiM1RUJGRDQiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=" + }, + "8836336a-f590-0921-301d-46427531eee6": { + "name": "Thales Bio Android SDK", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiMyQzJGNzMiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiM1RUJGRDQiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=" + }, + "cd69adb5-3c7a-deb9-3177-6800ea6cb72a": { + "name": "Thales PIN Android SDK", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiMyQzJGNzMiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiM1RUJGRDQiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=" + }, + "17290f1e-c212-34d0-1423-365d729f09d9": { + "name": "Thales PIN iOS SDK", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny42IDc3LjYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDc3LjYgNzcuNjsiPjxnPjxwYXRoIGZpbGw9IiMyQzJGNzMiIGQ9Ik03Ny42LDU1LjFjLTQuOSwxLjQtMTEuNCwxLjktMTYuMiwybC0yMi43LTQ1LjhoLTEuM2wtMjIuNiw0NS44Yy00LjgtMC4xLTEwLjUtMC42LTE1LjQtMmwyOC43LTUzLjdoMjAuNSBMNzcuNiw1NS4xeiI+PC9wYXRoPjxwYXRoIGZpbGw9IiM1RUJGRDQiIGQ9Ik00Ny43LDQxLjRjMCw1LjMtNC4zLDkuNS05LjYsOS41Yy01LjMsMC05LjUtNC4zLTkuNS05LjVjMC01LjMsNC4zLTkuNSw5LjUtOS41IEM0My40LDMxLjksNDcuNywzNi4xLDQ3LjcsNDEuNCI+PC9wYXRoPjwvZz48L3N2Zz4=" + }, + "50726f74-6f6e-5061-7373-50726f746f6e": { + "name": "Proton Pass", + "icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIxMDI0IiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMzUzLjI3NCAyMTQuMzkxQzQwOC44MzUgMTU4LjgzMiA0MzYuNjE0IDEzMS4wNTIgNDY4LjY0OCAxMjAuNjQ0QzQ5Ni44MjUgMTExLjQ4OSA1MjcuMTc1IDExMS40ODkgNTU1LjM1MiAxMjAuNjQ0QzU4Ny4zODYgMTMxLjA1MiA2MTUuMTY1IDE1OC44MzIgNjcwLjcyNiAyMTQuMzkxTDgwOS42MDggMzUzLjI3NEM4NjUuMTY5IDQwOC44MzUgODkyLjk0OCA0MzYuNjE0IDkwMy4zNTYgNDY4LjY0OEM5MTIuNTEyIDQ5Ni44MjUgOTEyLjUxMiA1MjcuMTc1IDkwMy4zNTYgNTU1LjM1MkM4OTIuOTQ4IDU4Ny4zODYgODY1LjE2OSA2MTUuMTY1IDgwOS42MDggNjcwLjcyNkw2NzAuNzI2IDgwOS42MDhDNjE1LjE2NSA4NjUuMTY5IDU4Ny4zODYgODkyLjk0OCA1NTUuMzUyIDkwMy4zNTZDNTI3LjE3NSA5MTIuNTEyIDQ5Ni44MjUgOTEyLjUxMiA0NjguNjQ4IDkwMy4zNTZDNDM2LjYxNCA4OTIuOTQ4IDQwOC44MzUgODY1LjE2OSAzNTMuMjc0IDgwOS42MDhMMzI3LjE2MiA3ODAuMzM2QzMxMS4zNjEgNzYyLjYyMSAzMDMuNDYyIDc1My43NjMgMjk3LjgyNyA3NDMuNjg4QzI5Mi44MzMgNzM0Ljc1NCAyODkuMTY2IDcyNS4xMzcgMjg2Ljk0NyA3MTUuMTQ0QzI4NC40NDQgNzAzLjg3OCAyODQuNDQ0IDY5Mi4wMDggMjg0LjQ0NCA2NjguMjcxVjM1NS43MjlDMjg0LjQ0NCAzMzEuOTkyIDI4NC40NDQgMzIwLjEyMiAyODYuOTQ3IDMwOC44NTVDMjg5LjE2NiAyOTguODYzIDI5Mi44MzMgMjg5LjI0NiAyOTcuODI3IDI4MC4zMTFDMzAzLjQ2MiAyNzAuMjM3IDMxMS4zNjEgMjYxLjM4IDMyNy4xNjIgMjQzLjY2NUwzNTMuMjc0IDIxNC4zOTFaIiBmaWxsPSJ1cmwoI3BhaW50MF9yYWRpYWxfMTIxNTVfNDE4NzMpIi8+CjxwYXRoIGQ9Ik0zNTMuMjc0IDIxNC4zOTFDNDA4LjgzNSAxNTguODMyIDQzNi42MTQgMTMxLjA1MiA0NjguNjQ4IDEyMC42NDRDNDk2LjgyNSAxMTEuNDg5IDUyNy4xNzUgMTExLjQ4OSA1NTUuMzUyIDEyMC42NDRDNTg3LjM4NiAxMzEuMDUyIDYxNS4xNjUgMTU4LjgzMiA2NzAuNzI2IDIxNC4zOTFMODA5LjYwOCAzNTMuMjc0Qzg2NS4xNjkgNDA4LjgzNSA4OTIuOTQ4IDQzNi42MTQgOTAzLjM1NiA0NjguNjQ4QzkxMi41MTIgNDk2LjgyNSA5MTIuNTEyIDUyNy4xNzUgOTAzLjM1NiA1NTUuMzUyQzg5Mi45NDggNTg3LjM4NiA4NjUuMTY5IDYxNS4xNjUgODA5LjYwOCA2NzAuNzI2TDY3MC43MjYgODA5LjYwOEM2MTUuMTY1IDg2NS4xNjkgNTg3LjM4NiA4OTIuOTQ4IDU1NS4zNTIgOTAzLjM1NkM1MjcuMTc1IDkxMi41MTIgNDk2LjgyNSA5MTIuNTEyIDQ2OC42NDggOTAzLjM1NkM0MzYuNjE0IDg5Mi45NDggNDA4LjgzNSA4NjUuMTY5IDM1My4yNzQgODA5LjYwOEwzMjcuMTYyIDc4MC4zMzZDMzExLjM2MSA3NjIuNjIxIDMwMy40NjIgNzUzLjc2MyAyOTcuODI3IDc0My42ODhDMjkyLjgzMyA3MzQuNzU0IDI4OS4xNjYgNzI1LjEzNyAyODYuOTQ3IDcxNS4xNDRDMjg0LjQ0NCA3MDMuODc4IDI4NC40NDQgNjkyLjAwOCAyODQuNDQ0IDY2OC4yNzFWMzU1LjcyOUMyODQuNDQ0IDMzMS45OTIgMjg0LjQ0NCAzMjAuMTIyIDI4Ni45NDcgMzA4Ljg1NUMyODkuMTY2IDI5OC44NjMgMjkyLjgzMyAyODkuMjQ2IDI5Ny44MjcgMjgwLjMxMUMzMDMuNDYyIDI3MC4yMzcgMzExLjM2MSAyNjEuMzggMzI3LjE2MiAyNDMuNjY1TDM1My4yNzQgMjE0LjM5MVoiIGZpbGw9InVybCgjcGFpbnQxX2xpbmVhcl8xMjE1NV80MTg3MykiLz4KPHBhdGggZD0iTTM0My4zNTYgMjI0LjMwM0MzNzEuMTM1IDE5Ni41MjQgMzg1LjAyNCAxODIuNjM0IDQwMS4wNDEgMTc3LjQzQzQxNS4xMyAxNzIuODUyIDQzMC4zMDUgMTcyLjg1MiA0NDQuMzkzIDE3Ny40M0M0NjAuNDEgMTgyLjYzNCA0NzQuMyAxOTYuNTI0IDUwMi4wNzkgMjI0LjMwM0w3MTAuNDA2IDQzMi42MjlDNzM4LjE4NSA0NjAuNDA4IDc1Mi4wNzQgNDc0LjMgNzU3LjI3OSA0OTAuMzE0Qzc2MS44NTYgNTA0LjQwMyA3NjEuODU2IDUxOS41ODEgNzU3LjI3OSA1MzMuNjY5Qzc1Mi4wNzQgNTQ5LjY4NiA3MzguMTg1IDU2My41NzYgNzEwLjQwNiA1OTEuMzU0TDUwMi4wNzkgNzk5LjY4MUM0NzQuMyA4MjcuNDYgNDYwLjQxIDg0MS4zNSA0NDQuMzkzIDg0Ni41NTVDNDMwLjMwNSA4NTEuMTMyIDQxNS4xMyA4NTEuMTMyIDQwMS4wNDEgODQ2LjU1NUMzODUuMDI0IDg0MS4zNSAzNzEuMTM1IDgyNy40NiAzNDMuMzU2IDc5OS42ODFMMjE0LjM5MSA2NzAuNzE3QzE1OC44MzIgNjE1LjE1NyAxMzEuMDUyIDU4Ny4zNzggMTIwLjY0NCA1NTUuMzQ2QzExMS40ODkgNTI3LjE2NyAxMTEuNDg5IDQ5Ni44MTYgMTIwLjY0NCA0NjguNjM5QzEzMS4wNTIgNDM2LjYwNSAxNTguODMyIDQwOC44MjYgMjE0LjM5MSAzNTMuMjY2TDM0My4zNTYgMjI0LjMwM1oiIGZpbGw9InVybCgjcGFpbnQyX3JhZGlhbF8xMjE1NV80MTg3MykiLz4KPGRlZnM+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQwX3JhZGlhbF8xMjE1NV80MTg3MyIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgzNTQuMTQ1IDkyNS43NDQpIHJvdGF0ZSgtNTguMTQyKSBzY2FsZSg2NjQuODM1IDEwMzkuNjcpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRDU4MCIvPgo8c3RvcCBvZmZzZXQ9IjAuMDkzNzUiIHN0b3AtY29sb3I9IiNGNkM1OTIiLz4KPHN0b3Agb2Zmc2V0PSIwLjIwNSIgc3RvcC1jb2xvcj0iI0VCQjZBMiIvPgo8c3RvcCBvZmZzZXQ9IjAuMzI0NDY2IiBzdG9wLWNvbG9yPSIjREZBNUFGIi8+CjxzdG9wIG9mZnNldD0iMC40Mjg3NSIgc3RvcC1jb2xvcj0iI0QzOTdCRSIvPgo8c3RvcCBvZmZzZXQ9IjAuNTMzNzUiIHN0b3AtY29sb3I9IiNDNDg2Q0IiLz4KPHN0b3Agb2Zmc2V0PSIwLjY0ODc1IiBzdG9wLWNvbG9yPSIjQjU3OEQ5Ii8+CjxzdG9wIG9mZnNldD0iMC43NzEyNSIgc3RvcC1jb2xvcj0iI0ExNjZFNSIvPgo8c3RvcCBvZmZzZXQ9IjAuODkxMjUiIHN0b3AtY29sb3I9IiM4QjU3RjIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNzA0Q0ZGIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8xMjE1NV80MTg3MyIgeDE9IjMyNi43MTMiIHkxPSItNDQuMzY0OSIgeDI9IjQ4MS41OTgiIHkyPSI5MDEuMDc3IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM2RDRBRkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjM5MjAwOSIgc3RvcC1jb2xvcj0iI0IzOUZGQiIgc3RvcC1vcGFjaXR5PSIwLjk3ODAyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkU4REIiIHN0b3Atb3BhY2l0eT0iMC44Ii8+CjwvbGluZWFyR3JhZGllbnQ+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQyX3JhZGlhbF8xMjE1NV80MTg3MyIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgyOTUuNzQ2IDg0NC43ODYpIHJvdGF0ZSgtNTguMTQyKSBzY2FsZSg1MzQuNzU4IDgzNi4yNTUpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRDU4MCIvPgo8c3RvcCBvZmZzZXQ9IjAuMDkzNzUiIHN0b3AtY29sb3I9IiNGNkM1OTIiLz4KPHN0b3Agb2Zmc2V0PSIwLjIwNSIgc3RvcC1jb2xvcj0iI0VCQjZBMiIvPgo8c3RvcCBvZmZzZXQ9IjAuMzI0NDY2IiBzdG9wLWNvbG9yPSIjREZBNUFGIi8+CjxzdG9wIG9mZnNldD0iMC40Mjg3NSIgc3RvcC1jb2xvcj0iI0QzOTdCRSIvPgo8c3RvcCBvZmZzZXQ9IjAuNTMzNzUiIHN0b3AtY29sb3I9IiNDNDg2Q0IiLz4KPHN0b3Agb2Zmc2V0PSIwLjY0ODc1IiBzdG9wLWNvbG9yPSIjQjU3OEQ5Ii8+CjxzdG9wIG9mZnNldD0iMC43NzEyNSIgc3RvcC1jb2xvcj0iI0ExNjZFNSIvPgo8c3RvcCBvZmZzZXQ9IjAuODkxMjUiIHN0b3AtY29sb3I9IiM4QjU3RjIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNzA0Q0ZGIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==", + "icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIxMDI0IiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMzUzLjI3NCAyMTQuMzkxQzQwOC44MzUgMTU4LjgzMiA0MzYuNjE0IDEzMS4wNTIgNDY4LjY0OCAxMjAuNjQ0QzQ5Ni44MjUgMTExLjQ4OSA1MjcuMTc1IDExMS40ODkgNTU1LjM1MiAxMjAuNjQ0QzU4Ny4zODYgMTMxLjA1MiA2MTUuMTY1IDE1OC44MzIgNjcwLjcyNiAyMTQuMzkxTDgwOS42MDggMzUzLjI3NEM4NjUuMTY5IDQwOC44MzUgODkyLjk0OCA0MzYuNjE0IDkwMy4zNTYgNDY4LjY0OEM5MTIuNTEyIDQ5Ni44MjUgOTEyLjUxMiA1MjcuMTc1IDkwMy4zNTYgNTU1LjM1MkM4OTIuOTQ4IDU4Ny4zODYgODY1LjE2OSA2MTUuMTY1IDgwOS42MDggNjcwLjcyNkw2NzAuNzI2IDgwOS42MDhDNjE1LjE2NSA4NjUuMTY5IDU4Ny4zODYgODkyLjk0OCA1NTUuMzUyIDkwMy4zNTZDNTI3LjE3NSA5MTIuNTEyIDQ5Ni44MjUgOTEyLjUxMiA0NjguNjQ4IDkwMy4zNTZDNDM2LjYxNCA4OTIuOTQ4IDQwOC44MzUgODY1LjE2OSAzNTMuMjc0IDgwOS42MDhMMzI3LjE2MiA3ODAuMzM2QzMxMS4zNjEgNzYyLjYyMSAzMDMuNDYyIDc1My43NjMgMjk3LjgyNyA3NDMuNjg4QzI5Mi44MzMgNzM0Ljc1NCAyODkuMTY2IDcyNS4xMzcgMjg2Ljk0NyA3MTUuMTQ0QzI4NC40NDQgNzAzLjg3OCAyODQuNDQ0IDY5Mi4wMDggMjg0LjQ0NCA2NjguMjcxVjM1NS43MjlDMjg0LjQ0NCAzMzEuOTkyIDI4NC40NDQgMzIwLjEyMiAyODYuOTQ3IDMwOC44NTVDMjg5LjE2NiAyOTguODYzIDI5Mi44MzMgMjg5LjI0NiAyOTcuODI3IDI4MC4zMTFDMzAzLjQ2MiAyNzAuMjM3IDMxMS4zNjEgMjYxLjM4IDMyNy4xNjIgMjQzLjY2NUwzNTMuMjc0IDIxNC4zOTFaIiBmaWxsPSJ1cmwoI3BhaW50MF9yYWRpYWxfMTIxNTVfNDE4NzMpIi8+CjxwYXRoIGQ9Ik0zNTMuMjc0IDIxNC4zOTFDNDA4LjgzNSAxNTguODMyIDQzNi42MTQgMTMxLjA1MiA0NjguNjQ4IDEyMC42NDRDNDk2LjgyNSAxMTEuNDg5IDUyNy4xNzUgMTExLjQ4OSA1NTUuMzUyIDEyMC42NDRDNTg3LjM4NiAxMzEuMDUyIDYxNS4xNjUgMTU4LjgzMiA2NzAuNzI2IDIxNC4zOTFMODA5LjYwOCAzNTMuMjc0Qzg2NS4xNjkgNDA4LjgzNSA4OTIuOTQ4IDQzNi42MTQgOTAzLjM1NiA0NjguNjQ4QzkxMi41MTIgNDk2LjgyNSA5MTIuNTEyIDUyNy4xNzUgOTAzLjM1NiA1NTUuMzUyQzg5Mi45NDggNTg3LjM4NiA4NjUuMTY5IDYxNS4xNjUgODA5LjYwOCA2NzAuNzI2TDY3MC43MjYgODA5LjYwOEM2MTUuMTY1IDg2NS4xNjkgNTg3LjM4NiA4OTIuOTQ4IDU1NS4zNTIgOTAzLjM1NkM1MjcuMTc1IDkxMi41MTIgNDk2LjgyNSA5MTIuNTEyIDQ2OC42NDggOTAzLjM1NkM0MzYuNjE0IDg5Mi45NDggNDA4LjgzNSA4NjUuMTY5IDM1My4yNzQgODA5LjYwOEwzMjcuMTYyIDc4MC4zMzZDMzExLjM2MSA3NjIuNjIxIDMwMy40NjIgNzUzLjc2MyAyOTcuODI3IDc0My42ODhDMjkyLjgzMyA3MzQuNzU0IDI4OS4xNjYgNzI1LjEzNyAyODYuOTQ3IDcxNS4xNDRDMjg0LjQ0NCA3MDMuODc4IDI4NC40NDQgNjkyLjAwOCAyODQuNDQ0IDY2OC4yNzFWMzU1LjcyOUMyODQuNDQ0IDMzMS45OTIgMjg0LjQ0NCAzMjAuMTIyIDI4Ni45NDcgMzA4Ljg1NUMyODkuMTY2IDI5OC44NjMgMjkyLjgzMyAyODkuMjQ2IDI5Ny44MjcgMjgwLjMxMUMzMDMuNDYyIDI3MC4yMzcgMzExLjM2MSAyNjEuMzggMzI3LjE2MiAyNDMuNjY1TDM1My4yNzQgMjE0LjM5MVoiIGZpbGw9InVybCgjcGFpbnQxX2xpbmVhcl8xMjE1NV80MTg3MykiLz4KPHBhdGggZD0iTTM0My4zNTYgMjI0LjMwM0MzNzEuMTM1IDE5Ni41MjQgMzg1LjAyNCAxODIuNjM0IDQwMS4wNDEgMTc3LjQzQzQxNS4xMyAxNzIuODUyIDQzMC4zMDUgMTcyLjg1MiA0NDQuMzkzIDE3Ny40M0M0NjAuNDEgMTgyLjYzNCA0NzQuMyAxOTYuNTI0IDUwMi4wNzkgMjI0LjMwM0w3MTAuNDA2IDQzMi42MjlDNzM4LjE4NSA0NjAuNDA4IDc1Mi4wNzQgNDc0LjMgNzU3LjI3OSA0OTAuMzE0Qzc2MS44NTYgNTA0LjQwMyA3NjEuODU2IDUxOS41ODEgNzU3LjI3OSA1MzMuNjY5Qzc1Mi4wNzQgNTQ5LjY4NiA3MzguMTg1IDU2My41NzYgNzEwLjQwNiA1OTEuMzU0TDUwMi4wNzkgNzk5LjY4MUM0NzQuMyA4MjcuNDYgNDYwLjQxIDg0MS4zNSA0NDQuMzkzIDg0Ni41NTVDNDMwLjMwNSA4NTEuMTMyIDQxNS4xMyA4NTEuMTMyIDQwMS4wNDEgODQ2LjU1NUMzODUuMDI0IDg0MS4zNSAzNzEuMTM1IDgyNy40NiAzNDMuMzU2IDc5OS42ODFMMjE0LjM5MSA2NzAuNzE3QzE1OC44MzIgNjE1LjE1NyAxMzEuMDUyIDU4Ny4zNzggMTIwLjY0NCA1NTUuMzQ2QzExMS40ODkgNTI3LjE2NyAxMTEuNDg5IDQ5Ni44MTYgMTIwLjY0NCA0NjguNjM5QzEzMS4wNTIgNDM2LjYwNSAxNTguODMyIDQwOC44MjYgMjE0LjM5MSAzNTMuMjY2TDM0My4zNTYgMjI0LjMwM1oiIGZpbGw9InVybCgjcGFpbnQyX3JhZGlhbF8xMjE1NV80MTg3MykiLz4KPGRlZnM+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQwX3JhZGlhbF8xMjE1NV80MTg3MyIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgzNTQuMTQ1IDkyNS43NDQpIHJvdGF0ZSgtNTguMTQyKSBzY2FsZSg2NjQuODM1IDEwMzkuNjcpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRDU4MCIvPgo8c3RvcCBvZmZzZXQ9IjAuMDkzNzUiIHN0b3AtY29sb3I9IiNGNkM1OTIiLz4KPHN0b3Agb2Zmc2V0PSIwLjIwNSIgc3RvcC1jb2xvcj0iI0VCQjZBMiIvPgo8c3RvcCBvZmZzZXQ9IjAuMzI0NDY2IiBzdG9wLWNvbG9yPSIjREZBNUFGIi8+CjxzdG9wIG9mZnNldD0iMC40Mjg3NSIgc3RvcC1jb2xvcj0iI0QzOTdCRSIvPgo8c3RvcCBvZmZzZXQ9IjAuNTMzNzUiIHN0b3AtY29sb3I9IiNDNDg2Q0IiLz4KPHN0b3Agb2Zmc2V0PSIwLjY0ODc1IiBzdG9wLWNvbG9yPSIjQjU3OEQ5Ii8+CjxzdG9wIG9mZnNldD0iMC43NzEyNSIgc3RvcC1jb2xvcj0iI0ExNjZFNSIvPgo8c3RvcCBvZmZzZXQ9IjAuODkxMjUiIHN0b3AtY29sb3I9IiM4QjU3RjIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNzA0Q0ZGIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8xMjE1NV80MTg3MyIgeDE9IjMyNi43MTMiIHkxPSItNDQuMzY0OSIgeDI9IjQ4MS41OTgiIHkyPSI5MDEuMDc3IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM2RDRBRkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjM5MjAwOSIgc3RvcC1jb2xvcj0iI0IzOUZGQiIgc3RvcC1vcGFjaXR5PSIwLjk3ODAyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkU4REIiIHN0b3Atb3BhY2l0eT0iMC44Ii8+CjwvbGluZWFyR3JhZGllbnQ+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQyX3JhZGlhbF8xMjE1NV80MTg3MyIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgyOTUuNzQ2IDg0NC43ODYpIHJvdGF0ZSgtNTguMTQyKSBzY2FsZSg1MzQuNzU4IDgzNi4yNTUpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRDU4MCIvPgo8c3RvcCBvZmZzZXQ9IjAuMDkzNzUiIHN0b3AtY29sb3I9IiNGNkM1OTIiLz4KPHN0b3Agb2Zmc2V0PSIwLjIwNSIgc3RvcC1jb2xvcj0iI0VCQjZBMiIvPgo8c3RvcCBvZmZzZXQ9IjAuMzI0NDY2IiBzdG9wLWNvbG9yPSIjREZBNUFGIi8+CjxzdG9wIG9mZnNldD0iMC40Mjg3NSIgc3RvcC1jb2xvcj0iI0QzOTdCRSIvPgo8c3RvcCBvZmZzZXQ9IjAuNTMzNzUiIHN0b3AtY29sb3I9IiNDNDg2Q0IiLz4KPHN0b3Agb2Zmc2V0PSIwLjY0ODc1IiBzdG9wLWNvbG9yPSIjQjU3OEQ5Ii8+CjxzdG9wIG9mZnNldD0iMC43NzEyNSIgc3RvcC1jb2xvcj0iI0ExNjZFNSIvPgo8c3RvcCBvZmZzZXQ9IjAuODkxMjUiIHN0b3AtY29sb3I9IiM4QjU3RjIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNzA0Q0ZGIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==" + }, + "fdb141b2-5d84-443e-8a35-4698c205a502": { + "name": "KeePassXC", + "icon_dark": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJiIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48ZyBpZD0iYyI+PHJlY3Qgd2lkdGg9IjEyOCIgaGVpZ2h0PSIxMjgiIHN0eWxlPSJmaWxsOm5vbmU7IHN0cm9rZS13aWR0aDowcHg7Ii8+PGcgaWQ9ImQiPjxyZWN0IHg9IjU3LjAxMTIiIHk9IjU2LjU3NzEiIHdpZHRoPSIzLjU1OCIgaGVpZ2h0PSIzNS4yMDYxIiBzdHlsZT0iZmlsbDojMGYwZjBkOyBzdHJva2Utd2lkdGg6MHB4OyIvPjxwYXRoIGQ9Im02NCwyOC40ODg1YzQuODI4NywwLDguNzY3OS0zLjk0LDguNzY3OS04Ljc2OTgsMC0uNjM1NS0uMTI3MS0xLjI3MDktLjI1NDItMS45MDY0LTIuNzk1Ni0uNTA4NC01LjU5MTEtLjg4OTctOC41MTM4LS43NjI2LTIuNzk1NiwwLTUuNzE4Mi4yNTQyLTguNTEzOC43NjI2LS4xMjcxLjYzNTUtLjI1NDIsMS4yNzEtLjI1NDIsMS45MDY0LDAsNC44Mjk3LDMuOTM5Miw4Ljc2OTgsOC43Njc5LDguNzY5OFoiIHN0eWxlPSJmaWxsOiMwZjBmMGQ7IHN0cm9rZS13aWR0aDowcHg7Ii8+PHBhdGggZD0ibTg4LjE0MzYsMjMuNjU4N2MuMzgxMiwxLjY1MjMuNTA4MywzLjE3NzUuNTA4Myw0LjgyOTcsMCw5Ljc4NjUtNS44NDUzLDE4LjMwMjEtMTQuMTA0OSwyMi4yNDIxbC0uNjM1NCwxMC40MjIsNy40OTcyLDcuNDk4OC03LjQ5NzIsNy40OTg4LDQuOTU1OCw0Ljk1NjgtNC45NTU4LDQuOTU2OC42MzU0LDkuMjc4MS0xMC41NDY5LDEwLjU0OTEtMTAuNTQ2OS0xMC41NDkxdi00NC42MTEzYy04LjM4NjctMy45NC0xNC4xMDQ5LTEyLjQ1NTYtMTQuMTA0OS0yMi4yNDIxLDAtMS42NTIzLjI1NDEtMy4xNzc1LjUwODMtNC44Mjk3LTE0LjIzMTksOC41MTU1LTIyLjg3MjgsMjMuNzY3My0yMi44NzI4LDQwLjI5LDAsMjYuMDU1LDIxLjA5MzgsNDcuMDI2MSw0Ny4wMTYzLDQ3LjAyNjEsMjYuMDQ5NiwwLDQ3LjAxNjMtMjEuMDk4Miw0Ny4wMTYzLTQ3LjAyNjEtLjEyNzEtMTYuNTIyNy04Ljc2NzktMzEuNzc0NC0yMi44NzI4LTQwLjI5WiIgc3R5bGU9ImZpbGw6IzBmMGYwZDsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBkPSJtNjQsMy4xMDAxQzMwLjQxOTUsMy4xMDAxLDMuMDk5OSwzMC40MTk2LDMuMDk5OSw2NHMyNy4zMTk2LDYwLjksNjAuOTAwMSw2MC45LDYwLjg5OTktMjcuMzE5OCw2MC44OTk5LTYwLjlTOTcuNTgwNiwzLjEwMDEsNjQsMy4xMDAxWm0wLDExNi42NzU5Yy0zMC43NDE1LDAtNTUuNzUxNC0yNS4wMjEyLTU1Ljc1MTQtNTUuNzc1OVMzMy4yNTg2LDguMjI0MSw2NCw4LjIyNDFzNTUuNzUxMiwyNS4wMjA5LDU1Ljc1MTIsNTUuNzc1OS0yNS4wMDk3LDU1Ljc3NTktNTUuNzUxMiw1NS43NzU5WiIgc3R5bGU9ImZpbGw6IzBmMGYwZDsgc3Ryb2tlLXdpZHRoOjBweDsiLz48L2c+PC9nPjwvc3ZnPg==", + "icon_light": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImUiIHgxPSI2My45OTk4IiB5MT0iLTMuMzE0IiB4Mj0iNjMuOTk5OCIgeTI9IjExOC40ODYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM0MTQxNDEiLz48c3RvcCBvZmZzZXQ9Ii4xOTYiIHN0b3AtY29sb3I9IiMzZTNlM2UiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMzYTNhM2EiLz48L2xpbmVhckdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0iZyIgY3g9IjMwMi44MDE0IiBjeT0iLTM3NS41MzAxIiBmeD0iMzAyLjgwMTQiIGZ5PSItMzc1LjUzMDEiIHI9IjIwNy4yMzM5IiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKC00Ni45OTkgMTg1LjUyNzUpIHNjYWxlKC4zNTM5KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjY3MzMiIHN0b3AtY29sb3I9IiNmY2ZjZmMiIHN0b3Atb3BhY2l0eT0iMCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZjZmNmYyIvPjwvcmFkaWFsR3JhZGllbnQ+PHJhZGlhbEdyYWRpZW50IGlkPSJpIiBjeD0iMzExLjE0NzIiIGN5PSItMzQ4LjIzMjUiIGZ4PSIzMTEuMTQ3MiIgZnk9Ii0zNDguMjMyNSIgcj0iMTcyLjM4OTMiIGdyYWRpZW50VHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ2Ljk5OSAxODUuNTI3NSkgc2NhbGUoLjM1MzkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuMTA4OCIgc3RvcC1jb2xvcj0iIzBmMGYwZCIgc3RvcC1vcGFjaXR5PSIwIi8+PHN0b3Agb2Zmc2V0PSIuODg1NiIgc3RvcC1jb2xvcj0iIzQxNDE0MSIgc3RvcC1vcGFjaXR5PSIwIi8+PHN0b3Agb2Zmc2V0PSIuOTMzOSIgc3RvcC1jb2xvcj0iIzFlMWUxZCIgc3RvcC1vcGFjaXR5PSIuNjg0MSIvPjxzdG9wIG9mZnNldD0iLjk4NzQiIHN0b3AtY29sb3I9IiMwZjBmMGQiLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0ibiIgY3g9IjMxNi44OTI3IiBjeT0iLTQ1MS41OTczIiBmeD0iMzE2Ljg5MjciIGZ5PSItNDUxLjU5NzMiIHI9IjMzNC44MzY0IiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKC00Ni45OTkgMTE3LjkyNTYpIHNjYWxlKC4zNTM5IC4yMDI2KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzJlNmIyNiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZhYjUzNiIvPjwvcmFkaWFsR3JhZGllbnQ+PHJhZGlhbEdyYWRpZW50IGlkPSJwIiBjeD0iMzE0LjM4NzUiIGN5PSItNDUzLjM2MyIgZng9IjMxNC4zODc1IiBmeT0iLTQ1My4zNjMiIHI9IjY1LjM5MjUiIGdyYWRpZW50VHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ2Ljk5OSAxODUuNTI3NSkgc2NhbGUoLjM1MzkpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjNmFiNTM2Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMmU2YjI2Ii8+PC9yYWRpYWxHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9InIiIGN4PSIzMjIuMjEyOCIgY3k9Ii0zOTAuMjU0NyIgZng9IjMyMi4yMTI4IiBmeT0iLTM5MC4yNTQ3IiByPSI5Ni41ODUxIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKC00NC4yMTk5IDI1Ni41NzUxKSBzY2FsZSguMzM1NiAuNTU3MikiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiMwMDAiLz48c3RvcCBvZmZzZXQ9Ii43ODQyIiBzdG9wLWNvbG9yPSIjNGY0ZjRmIiBzdG9wLW9wYWNpdHk9IjAiLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0idSIgY3g9IjMxMi45OTQ2IiBjeT0iLTQ3My4wMTc4IiBmeD0iMzEyLjk5NDYiIGZ5PSItNDczLjAxNzgiIHI9IjIyMy41MTAxIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKC00Ni45OTkgMTg1LjUyNzUpIHNjYWxlKC4zNTM5KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2Y1ZjVmNSIvPjxzdG9wIG9mZnNldD0iLjU0ODEiIHN0b3AtY29sb3I9IiNmMmYyZjIiLz48L3JhZGlhbEdyYWRpZW50PjwvZGVmcz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGU7Ij48ZyBpZD0iYiI+PGcgaWQ9ImMiPjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiBzdHlsZT0iZmlsbDpub25lOyBzdHJva2Utd2lkdGg6MHB4OyIvPjxnIGlkPSJkIj48cGF0aCBpZD0iZiIgZD0ibTYzLjk5OTksMTI0LjljLTMzLjU4MDUsMC02MC45MDAxLTI3LjMxOTgtNjAuOTAwMS02MC45UzMwLjQxOTQsMy4xLDYzLjk5OTksMy4xczYwLjg5OTksMjcuMzE5NSw2MC44OTk5LDYwLjktMjcuMzE5Myw2MC45LTYwLjg5OTksNjAuOVptMC0xMTYuNjc1OWMtMzAuNzQxNSwwLTU1Ljc1MTUsMjUuMDIxLTU1Ljc1MTUsNTUuNzc1OXMyNS4wMSw1NS43NzU5LDU1Ljc1MTUsNTUuNzc1OSw1NS43NTEyLTI1LjAyMTIsNTUuNzUxMi01NS43NzU5Uzk0Ljc0MTQsOC4yMjQxLDYzLjk5OTksOC4yMjQxWiIgc3R5bGU9ImZpbGw6dXJsKCNlKTsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0iaCIgZD0ibTYzLjk5OTksMy4xMjM4QzMwLjQzMjUsMy4xMjM4LDMuMTIzNiwzMC40MzI3LDMuMTIzNiw2NHMyNy4zMDg5LDYwLjg3NjIsNjAuODc2Myw2MC44NzYyLDYwLjg3NjEtMjcuMzA5MSw2MC44NzYxLTYwLjg3NjJTOTcuNTY3NCwzLjEyMzgsNjMuOTk5OSwzLjEyMzhaIiBzdHlsZT0iZmlsbDp1cmwoI2cpOyBtaXgtYmxlbmQtbW9kZTpsaWdodGVuOyBvcGFjaXR5Oi4zMjsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0iaiIgZD0ibTYzLjk5OTksMTI0LjljLTMzLjU4MDUsMC02MC45MDAxLTI3LjMxOTgtNjAuOTAwMS02MC45UzMwLjQxOTQsMy4xLDYzLjk5OTksMy4xczYwLjg5OTksMjcuMzE5NSw2MC44OTk5LDYwLjktMjcuMzE5Myw2MC45LTYwLjg5OTksNjAuOVptMC0xMTYuNjc1OWMtMzAuNzQxNSwwLTU1Ljc1MTUsMjUuMDIxLTU1Ljc1MTUsNTUuNzc1OXMyNS4wMSw1NS43NzU5LDU1Ljc1MTUsNTUuNzc1OSw1NS43NTEyLTI1LjAyMTIsNTUuNzUxMi01NS43NzU5Uzk0Ljc0MTQsOC4yMjQxLDYzLjk5OTksOC4yMjQxWiIgc3R5bGU9ImZpbGw6dXJsKCNpKTsgb3BhY2l0eTouNDQ7IHN0cm9rZS13aWR0aDowcHg7Ii8+PHBhdGggaWQ9ImsiIGQ9Im02My45OTk5LDguNTUwNGMtMzAuOTc4MywwLTU2LjE4MDksMjUuMjAyNS01Ni4xODA5LDU2LjE4MDhzMjUuMjAyNSw1Ni4xODA4LDU2LjE4MDksNTYuMTgwOCw1Ni4xODA3LTI1LjIwMjgsNTYuMTgwNy01Ni4xODA4Uzk0Ljk3ODMsOC41NTA0LDYzLjk5OTksOC41NTA0WiIgc3R5bGU9ImZpbGw6cmdiYSgxNSwxNSwxMywuMzUpOyBzdHJva2Utd2lkdGg6MHB4OyIvPjxwYXRoIGlkPSJsIiBkPSJtNjMuOTk5OSwxMjQuOWMtMzMuNTgwNSwwLTYwLjkwMDEtMjcuMzE5OC02MC45MDAxLTYwLjlTMzAuNDE5NCwzLjEsNjMuOTk5OSwzLjFzNjAuODk5OSwyNy4zMTk1LDYwLjg5OTksNjAuOS0yNy4zMTkzLDYwLjktNjAuODk5OSw2MC45Wm0wLTEyMC40OTY2QzMwLjQxOTUsNC40MDM0LDMuMDk5OCwzMS4zNTk2LDMuMDk5OCw2NC40OTMyczI3LjMxOTcsNjAuMDg5OCw2MC45MDAxLDYwLjA4OTgsNjAuODk5OS0yNi45NTY1LDYwLjg5OTktNjAuMDg5OFM5Ny41ODA0LDQuNDAzNCw2NCw0LjQwMzRaIiBzdHlsZT0iZmlsbDojMGYwZjBkOyBvcGFjaXR5Oi4zNTsgc3Ryb2tlLXdpZHRoOjBweDsiLz48L2c+PGcgaWQ9Im0iPjxwYXRoIGlkPSJvIiBkPSJtNjMuOTk5OSw4LjIyNDFjLTMwLjc1NTEsMC01NS43NzYsMjUuMDIwOS01NS43NzYsNTUuNzc1OXMyNS4wMjA5LDU1Ljc3NTksNTUuNzc2LDU1Ljc3NTksNTUuNzc1OC0yNS4wMjExLDU1Ljc3NTgtNTUuNzc1OVM5NC43NTUsOC4yMjQxLDYzLjk5OTksOC4yMjQxWiIgc3R5bGU9ImZpbGw6dXJsKCNuKTsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0icSIgZD0ibTYzLjk5OTgsMTIuODYxM2MtOS4xNjA4LDAtMTYuNjEzNiw3LjQ1MjgtMTYuNjEzNiwxNi42MTM1czcuNDUyOCwxNi42MTM1LDE2LjYxMzYsMTYuNjEzNSwxNi42MTM1LTcuNDUyOCwxNi42MTM1LTE2LjYxMzUtNy40NTI3LTE2LjYxMzUtMTYuNjEzNS0xNi42MTM1WiIgc3R5bGU9ImZpbGw6dXJsKCNwKTsgbWl4LWJsZW5kLW1vZGU6bGlnaHRlbjsgb3BhY2l0eTouNzsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0icyIgZD0ibTM0LjY4NzEsMTYuMzY0NWMtLjAwMjcuMDE5MS0uMDA1NC4wMzc4LS4wMDgxLjA1NjktLjA3MjUuMDEzNi0uMDczNi0uMDAzNy4wMDgxLS4wNTY5Wm00Mi4xMTc3LDM1LjgwMDFsLS43NzE0LDEzLjc4MjIsOS4xMDIzLDkuOTE2NS05LjEwMjMsOS45MTY1LDYuMDE2OCw2LjU1NDktNi4wMTY4LDYuNTU0OS43NzE0LDEzLjY2OTZoLTI1LjYxdi02MC4zOTQ2Yy0xMC4xODIzLTUuMjEwNC0xNy4xMjQ4LTE2LjQ3MTQtMTcuMTI0OC0yOS40MTMyLDAtMi4xNjU5LjMwMzItNC4xNjcxLjYwOS02LjMzLDEuMTA0Ni0uMjA4MiwxOC45NjczLTcuNjk0NywxOC45NjczLTcuNjk0Ny0uMTQ4My44MDkyLDIwLjg1NTEuODA5MiwyMC43MDY4LDAsMCwwLDE3LjI1NzcsNy40MjU3LDE4Ljk4OTEsNy43ODk5LjQzOCwyLjEyNjQuNTg3Myw0LjEwMS41ODczLDYuMjM0OCwwLDEyLjk0MTgtNy4wOTY4LDI0LjIwMjktMTcuMTI0OCwyOS40MTMzWm0xNi41MDc3LTM1LjgwMDFjLjAxMDguMDUxMS4wMTk0LjEwMTEuMDI5OS4xNTIxLjE4OTYuMDM5OS4xOTYtLjAwMzUtLjAyOTktLjE1MjFaIiBzdHlsZT0iZmlsbDp1cmwoI3IpOyBtaXgtYmxlbmQtbW9kZTptdWx0aXBseTsgb3BhY2l0eTouMzsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0idCIgZD0ibTM0LjExNjEsMTAwLjQzMTljLTkuODk3Ny04LjYwODEtMTYuMTY0LTIxLjI5NjktMTYuMTY0LTM1LjQ5NjgsMC0xNi41MjI3LDguNjQwOS0zMS43NzQ0LDIyLjg3MjgtNDAuMjktLjI1NDEsMS42NTIzLS41MDgzLDMuMTc3NC0uNTA4Myw0LjgyOTcsMCw5Ljc4NjUsNS43MTgyLDE4LjMwMiwxNC4xMDQ5LDIyLjI0MjF2NDQuNjExM2wxMC41NDY5LDEwLjU0OTEsMTAuNTQ2OS0xMC41NDkxLS42MzU0LTkuMjc4MSw0Ljk1NTgtNC45NTY4LTQuOTU1OC00Ljk1NjgsNy40OTcyLTcuNDk4OC03LjQ5NzItNy40OTg4LjYzNTQtMTAuNDIyYzguMjU5Ni0zLjk0LDE0LjEwNDktMTIuNDU1NiwxNC4xMDQ5LTIyLjI0MjEsMC0xLjY1MjMtLjEyNzEtMy4xNzc0LS41MDgzLTQuODI5Nyw1LjE2NDMsMy4xMTc4LDkuNTkyMiw3LjE0MTYsMTMuMTQxOSwxMS43OTcyLTguNTg0MS0xMS43ODg5LTIyLjUyOTMtMTkuNDU4Ny0zOC4yNzY2LTE5LjQ1ODctMjYuMDkxMSwwLTQ3LjI0MjEsMjEuMDUtNDcuMjQyMSw0Ny4wMTY1LDAsMTQuNjkzLDYuNzczNiwyNy44MTAxLDE3LjM4MDksMzYuNDMxOFptMjcuNDIxNC03LjY2MjRoLTMuNTU4di0zNS4yMDYxaDMuNTU4djM1LjIwNjFabS01LjA4MjgtNzMuOTcwOGMyLjc5NTYtLjUwODQsNS43MTgyLS43NjI2LDguNTEzOC0uNzYyNiwyLjkyMjYtLjEyNzEsNS43MTgyLjI1NDIsOC41MTM4Ljc2MjYuMTI3MS42MzU1LjI1NDIsMS4yNzEuMjU0MiwxLjkwNjQsMCw0LjgyOTctMy45MzkyLDguNzY5OC04Ljc2NzksOC43Njk4cy04Ljc2NzktMy45NC04Ljc2NzktOC43Njk4YzAtLjYzNTUuMTI3MS0xLjI3MDkuMjU0Mi0xLjkwNjRaIiBzdHlsZT0iZmlsbDojMGYwZjBkOyBtaXgtYmxlbmQtbW9kZTptdWx0aXBseTsgb3BhY2l0eTouMjsgc3Ryb2tlLXdpZHRoOjBweDsiLz48cGF0aCBpZD0idiIgZD0ibTYzLjk5OTksOC4yMjQxYy0zMC43NDE1LDAtNTUuNzUxNCwyNS4wMjA5LTU1Ljc1MTQsNTUuNzc1OXMyNS4wMSw1NS43NzU5LDU1Ljc1MTQsNTUuNzc1OSw1NS43NTEyLTI1LjAyMTIsNTUuNzUxMi01NS43NzU5Uzk0Ljc0MTQsOC4yMjQxLDYzLjk5OTksOC4yMjQxWm0tOC41MTM4LDkuNTg4MmMyLjc5NTYtLjUwODQsNS43MTgyLS43NjI2LDguNTEzOC0uNzYyNiwyLjkyMjYtLjEyNzEsNS43MTgyLjI1NDIsOC41MTM4Ljc2MjYuMTI3MS42MzU1LjI1NDIsMS4yNzEuMjU0MiwxLjkwNjQsMCw0LjgyOTctMy45MzkyLDguNzY5OC04Ljc2NzksOC43Njk4cy04Ljc2NzktMy45NC04Ljc2NzktOC43Njk4YzAtLjYzNTUuMTI3MS0xLjI3MDkuMjU0Mi0xLjkwNjRabTUuMDgyOCwzOC43NjQ4djM1LjIwNjFoLTMuNTU4di0zNS4yMDYxaDMuNTU4Wm0zLjQzMDksNTQuMzk3OGMtMjUuOTIyNSwwLTQ3LjAxNjMtMjAuOTcxMS00Ny4wMTYzLTQ3LjAyNjEsMC0xNi41MjI3LDguNjQwOS0zMS43NzQ0LDIyLjg3MjgtNDAuMjktLjI1NDEsMS42NTIzLS41MDgzLDMuMTc3NC0uNTA4Myw0LjgyOTcsMCw5Ljc4NjUsNS43MTgyLDE4LjMwMiwxNC4xMDQ5LDIyLjI0MjF2NDQuNjExM2wxMC41NDY5LDEwLjU0OTEsMTAuNTQ2OS0xMC41NDkxLS42MzU0LTkuMjc4MSw0Ljk1NTgtNC45NTY4LTQuOTU1OC00Ljk1NjgsNy40OTcyLTcuNDk4OC03LjQ5NzItNy40OTg4LjYzNTQtMTAuNDIyYzguMjU5Ni0zLjk0LDE0LjEwNDktMTIuNDU1NiwxNC4xMDQ5LTIyLjI0MjEsMC0xLjY1MjMtLjEyNzEtMy4xNzc0LS41MDgzLTQuODI5NywxNC4xMDQ5LDguNTE1NiwyMi43NDU3LDIzLjc2NzMsMjIuODcyOCw0MC4yOSwwLDI1LjkyNzktMjAuOTY2OCw0Ny4wMjYxLTQ3LjAxNjMsNDcuMDI2MVoiIHN0eWxlPSJmaWxsOnVybCgjdSk7IHN0cm9rZS13aWR0aDowcHg7Ii8+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" + } +} diff --git a/authentik/stages/authenticator_webauthn/mds/blob.jwt b/authentik/stages/authenticator_webauthn/mds/blob.jwt new file mode 100644 index 0000000000..6e6ab1f1ee --- /dev/null +++ b/authentik/stages/authenticator_webauthn/mds/blob.jwt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIng1YyI6WyJNSUlITURDQ0JoaWdBd0lCQWdJTU11QlUrMkZ3dGl0N1RrUEtNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1HSXhDekFKQmdOVkJBWVRBa0pGTVJrd0Z3WURWUVFLRXhCSGJHOWlZV3hUYVdkdUlHNTJMWE5oTVRnd05nWURWUVFERXk5SGJHOWlZV3hUYVdkdUlFVjRkR1Z1WkdWa0lGWmhiR2xrWVhScGIyNGdRMEVnTFNCVFNFRXlOVFlnTFNCSE16QWVGdzB5TXpBMk1EZ3lNREF3TVRGYUZ3MHlOREEzTURreU1EQXdNVEJhTUlIdE1SMHdHd1lEVlFRUERCUlFjbWwyWVhSbElFOXlaMkZ1YVhwaGRHbHZiakVRTUE0R0ExVUVCUk1ITXpRMU5ESTROREVUTUJFR0N5c0dBUVFCZ2pjOEFnRURFd0pWVXpFYk1Ca0dDeXNHQVFRQmdqYzhBZ0VDRXdwRFlXeHBabTl5Ym1saE1Rc3dDUVlEVlFRR0V3SlZVekVQTUEwR0ExVUVDQk1HVDNKbFoyOXVNUkl3RUFZRFZRUUhFd2xDWldGMlpYSjBiMjR4R1RBWEJnTlZCQWtURURNNE5UVWdVM2NnTVRVelVtUWdSSEl4SERBYUJnTlZCQW9URTBaSlJFOGdRVXhNU1VGT1EwVXNJRWxPUXk0eEhUQWJCZ05WQkFNVEZHMWtjeTVtYVdSdllXeHNhV0Z1WTJVdWIzSm5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTZBc2tvUTBiRnA5M0pRUWRwMWI4bkZDbUI2N2RUTlVwdHdrS3RuSGowWTE4RFdvcEg4Q0tPUk0xTGpBSHlqTVRQb09HWGI1L3J0MXdEZk9LYjBjaHFTRzlsbHJCenAvTjBCdUxMMFpGeVpFQVl0NHRoOFkwT29jM0ZRdFhaOTlUNkhOVytmbVhhTGJZeHhuR25zeEF4alZRbUh3Q1pCbngrV1BLZ2k2QnFhWWNZMDVNOHV6V2tnU3AxbkU0akQrSlE5SE4wSFNGaHpIZTNMVzR2MHRoMkp6MU9RbU1od2lhMFNEL1Y2WVhJcWtYa3FtbUZlbmhDZlNHKy9MaUxnV3htZUl3QXBKNW9lMTBEdm1pSlllYWFGa2diRWMvYjcvNlBNYWE0WC8wYVpaMUo3QzBFSHZuNWxVSGI4aGZCYnpHaHNCS09wUVcxdU9oaUsreUk5b0tRUUlEQVFBQm80SURXRENDQTFRd0RnWURWUjBQQVFIL0JBUURBZ1dnTUlHV0JnZ3JCZ0VGQlFjQkFRU0JpVENCaGpCSEJnZ3JCZ0VGQlFjd0FvWTdhSFIwY0RvdkwzTmxZM1Z5WlM1bmJHOWlZV3h6YVdkdUxtTnZiUzlqWVdObGNuUXZaM05sZUhSbGJtUjJZV3h6YUdFeVp6TnlNeTVqY25Rd093WUlLd1lCQlFVSE1BR0dMMmgwZEhBNkx5OXZZM053TWk1bmJHOWlZV3h6YVdkdUxtTnZiUzluYzJWNGRHVnVaSFpoYkhOb1lUSm5NM0l6TUZVR0ExVWRJQVJPTUV3d1FRWUpLd1lCQkFHZ01nRUJNRFF3TWdZSUt3WUJCUVVIQWdFV0ptaDBkSEJ6T2k4dmQzZDNMbWRzYjJKaGJITnBaMjR1WTI5dEwzSmxjRzl6YVhSdmNua3ZNQWNHQldlQkRBRUJNQWtHQTFVZEV3UUNNQUF3UlFZRFZSMGZCRDR3UERBNm9EaWdOb1kwYUhSMGNEb3ZMMk55YkM1bmJHOWlZV3h6YVdkdUxtTnZiUzluY3k5bmMyVjRkR1Z1WkhaaGJITm9ZVEpuTTNJekxtTnliREFmQmdOVkhSRUVHREFXZ2hSdFpITXVabWxrYjJGc2JHbGhibU5sTG05eVp6QWRCZ05WSFNVRUZqQVVCZ2dyQmdFRkJRY0RBUVlJS3dZQkJRVUhBd0l3SHdZRFZSMGpCQmd3Rm9BVTNiUG5iYWd1Nk1WT2JzOTA1blU4bEJYTzZCMHdIUVlEVlIwT0JCWUVGTWFONFgxYjlBSHVXRFBKSzFBWWRnMk1RR2h4TUlJQmZnWUtLd1lCQkFIV2VRSUVBZ1NDQVc0RWdnRnFBV2dBZGdCSXNPTnIycVpITkEvbGFnTDZuVERySEZJQnkxYmRMSUhadTcrck9kaUVjd0FBQVlpY21HL1lBQUFFQXdCSE1FVUNJUUN1aE5ETitibDkxQkdqOEJMMTMxL2dlL2IrbWY4QTBETjNTWFJCdjZNRWd3SWdUclphZEJaa01abkNweXIwWEFaOTRNdWc0MWhYdjVsWDZhd21LMklTZWE0QWRnRHV6ZEJrMWRzYXpzVmN0NTIwelJPaU1vZEdmTHpzM3NOUlNGbEdjUisxbXdBQUFZaWNtSEZZQUFBRUF3QkhNRVVDSURaS1hxWlFZNmF0U1Y2T3ZlYzlpWGdvcVdTTGdORTNrVkhZa243WFVaRElBaUVBcnZZQ1FOVU5seHRHcC9wcTc2cnRCcWI2ZlJ2NEp1VDFWOXpGc1cyUWRRTUFkZ0RhdHI5clA3VzJJcCtid3J0Y2EraHdrWEZzdTFHRWhUUzlwRDB3U05mN3F3QUFBWWljbUc2WEFBQUVBd0JITUVVQ0lIT3IwTEtWbnVDbzNEZUNWZHRydWFNZC8yQ1JmWVlDVDJSVFNtcFJKWS9QQWlFQTZqeUZ6ODZzSlNZK2lERkxlZkcrV1VWSlQ0Q1ZWVDhWcm1leWJrZWkzMEF3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUJPNjF1TzYzU3o3THRzVjZKclVWdDRrOTRrTE96b0RXSTc0R0piK1dYcWhYRkJMcThtc0FiVXVqTENUTUtvbGltaE9oRWM3UzB3YUVBK2tEc1c4RnhOeFRiZElxK1Bvd0NSNHNOU3Q1bTh4cmJyVFpVR1JaeHpWZG81K1ltTDZ1Q3dNaGk0UHpQQkc3eDJydEszdi9WMk1nVXFkMEJiV1g5NXFwdmFtUmttb2FMRG5vZXN0cmhhcGdaYlN6OUJaeFdxYjFLRmlJeU1yQjYvTlRkYUtqRWNFTUtnTUJQM2ovOFN1a2hvcGVmWHc5WEd1Ym0rWWpNeXAxVXcvWGgrSzdzTXd5amNPMThVb1ZXRzd6Y1BMUlFvZE9OZ1dyS1o1ZldaVy80c1F5em9aU2ZIZ0hQMGpxdTdaRS9JZXViQVJ1ZlhnNTRDNTdrZHo4WU93SGlPdnZUZz0iLCJNSUlFWVRDQ0EwbWdBd0lCQWdJT1NLUUMzU2VTRGFJSU5KM1JtWHN3RFFZSktvWklodmNOQVFFTEJRQXdUREVnTUI0R0ExVUVDeE1YUjJ4dlltRnNVMmxuYmlCU2IyOTBJRU5CSUMwZ1VqTXhFekFSQmdOVkJBb1RDa2RzYjJKaGJGTnBaMjR4RXpBUkJnTlZCQU1UQ2tkc2IySmhiRk5wWjI0d0hoY05NVFl3T1RJeE1EQXdNREF3V2hjTk1qWXdPVEl4TURBd01EQXdXakJpTVFzd0NRWURWUVFHRXdKQ1JURVpNQmNHQTFVRUNoTVFSMnh2WW1Gc1UybG5iaUJ1ZGkxellURTRNRFlHQTFVRUF4TXZSMnh2WW1Gc1UybG5iaUJGZUhSbGJtUmxaQ0JXWVd4cFpHRjBhVzl1SUVOQklDMGdVMGhCTWpVMklDMGdSek13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ3Jhd05uVk5YY0VmdkZvaFBCakJrbjNCQjA0bUdEUGZxTzI0K2xEK1NwdmtZL0FyNUVwQWtjSmpPZlIwaUJGWWhXTjgwSHpwWFl5MnRJQTdtYlhwS3UySnBtWWRVMXhjb1FwUUswdWpFL3dlK3ZFRHlqeWptdGY3NkxMcWJPZnVxM3haYlNxVXFBWStNT3ZBNjdubnBkYXd2a0hnSkJGVlBueHVpNDVYSDRCd1R3YnREdWN4K01vN0VLNG1TMFRpK1AxTnpBUnhGTkNVRk04V3hjMzJ3eFhLZmY2V1U0VGJxVXgvVUptNDg1dHRrRnF1ME94NHdUVVVibjB1dXpLN3lWM1k5ODZFdEd6aEtCcmFNSDM2TWVrU1lsRTQ3M0dxSGV0Umk5cWJORzVwTSsrU2ErV2pSOUUxZTBZd3MxNkNHcXNtVkt3QXFnNHVjNDNlQlRGVWhWQWdNQkFBR2pnZ0VwTUlJQkpUQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQWRCZ05WSFE0RUZnUVUzYlBuYmFndTZNVk9iczkwNW5VOGxCWE82QjB3SHdZRFZSMGpCQmd3Rm9BVWovQkxmNmd1UlNTdVRWRDZZNXFMM3VMZEc3d3dQZ1lJS3dZQkJRVUhBUUVFTWpBd01DNEdDQ3NHQVFVRkJ6QUJoaUpvZEhSd09pOHZiMk56Y0RJdVoyeHZZbUZzYzJsbmJpNWpiMjB2Y205dmRISXpNRFlHQTFVZEh3UXZNQzB3SzZBcG9DZUdKV2gwZEhBNkx5OWpjbXd1WjJ4dlltRnNjMmxuYmk1amIyMHZjbTl2ZEMxeU15NWpjbXd3UndZRFZSMGdCRUF3UGpBOEJnUlZIU0FBTURRd01nWUlLd1lCQlFVSEFnRVdKbWgwZEhCek9pOHZkM2QzTG1kc2IySmhiSE5wWjI0dVkyOXRMM0psY0c5emFYUnZjbmt2TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCVmFKemwwSi9pMHpVVjM4aU1YSVErUS95aHQrSlpaNURXMW90R0w1T1lWMExaNlpFNnhoK1d1dldKSjRockRiaGZvNmtoVUVhRnRSVW51cnF6dXR2VnlXZ1c4bXNub1AwZ3RNWk8xMWN3UFVNVXVVVjhpR3lJT3VJQjBmbG82RytYYlY3NFNadVI1djVSQWdxZ0dYdWNZVVBaV3Z2OUFmek1NUWhSUWtyL01PL1dSMlhTZGlCclhIb0RMMnhrNERtakE0SzZpUEkrMStxTWh5cmtVTS8yWkVkQThsZHF3bDhuUURrS1M3dnE2c1VaNUxQVmRmcHhKWlp1NUpCajR5N0ZORlRWVzFPTWxDVXZ3dDVIOGFGZ0JNTEZpazl4cUs2SkZIcFl4WW1mNHQyc0xMeE4wTGxDdGhKRWFidnAxMFpsT3RmdThoTDVnQ1hjeG53R3h6U2IiXX0.eyJsZWdhbEhlYWRlciI6IlJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgQkxPQiBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLyIsIm5vIjo3MywibmV4dFVwZGF0ZSI6IjIwMjQtMDYtMDEiLCJlbnRyaWVzIjpbeyJhYWd1aWQiOiJmY2IxYmNiNC1mMzcwLTA3OGMtNjk5My1iYzI0ZDBhZTNmYmUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImZjYjFiY2I0LWYzNzAtMDc4Yy02OTkzLWJjMjRkMGFlM2ZiZSIsImRlc2NyaXB0aW9uIjoiTGVkZ2VyIE5hbm8gWCBGSURPMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEwNTAwLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NmsxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MywiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjMsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6WyJhbnkiLCJoYXJkd2FyZSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQmdUQ0NBU2NDRkJsbzBzNVFZRmRYYmZ1c1JkUWVvTFg2UWVubE1Bb0dDQ3FHU000OUJBTUNNRU14Q3pBSkJnTlZCQVlUQWtaU01ROHdEUVlEVlFRS0RBWk1aV1JuWlhJeEl6QWhCZ05WQkFNTUdreGxaR2RsY2lCR1NVUlBJRUYwZEdWemRHRjBhVzl1SUVOQk1CNFhEVEl6TURJeU16RXdNek13T0ZvWERUTXpNREl5TURFd016TXdPRm93UXpFTE1Ba0dBMVVFQmhNQ1JsSXhEekFOQmdOVkJBb01Ca3hsWkdkbGNqRWpNQ0VHQTFVRUF3d2FUR1ZrWjJWeUlFWkpSRThnUVhSMFpYTjBZWFJwYjI0Z1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBVEs3blh5SDRwZ04zVE13Q1dTb01EUmU0RVY4SmwzWHp1aGljWi8yZ3ZoK3p6M1dtVzBPWi9FY1JZRUE4RjI2Y2VldU1jZDIxV1FSUktXcGpXRCtKV2lNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUN3Y3NIdUw4WkZMM0ZOeVUvRE9RbjNibXgwOGxubjBPNVJrdExiT25vUEhRSWdPRWk2SW1BWjE4MXE4UkppTDBoYnc3WnF1dW5pUnE2ZmpXakdvQnUxTW9vPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFTWUFBQUVBQ0FZQUFBQWVNZHZ4QUFBQUFYTlNSMElBcnM0YzZRQUFBSVJsV0VsbVRVMEFLZ0FBQUFnQUJRRVNBQU1BQUFBQkFBRUFBQUVhQUFVQUFBQUJBQUFBU2dFYkFBVUFBQUFCQUFBQVVnRW9BQU1BQUFBQkFBSUFBSWRwQUFRQUFBQUJBQUFBV2dBQUFBQUFBQUVzQUFBQUFRQUFBU3dBQUFBQkFBT2dBUUFEQUFBQUFRQUJBQUNnQWdBRUFBQUFBUUFBQVNhZ0F3QUVBQUFBQVFBQUFRQUFBQUFBZTZTQ2t3QUFBQWx3U0ZsekFBQXVJd0FBTGlNQmVLVS9kZ0FBQVZscFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWxoTlVDQkRiM0psSURZdU1DNHdJajRLSUNBZ1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNEtJQ0FnSUNBZ1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZkR2xtWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTBhV1ptTHpFdU1DOGlQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFBjbWxsYm5SaGRHbHZiajR4UEM5MGFXWm1Pazl5YVdWdWRHRjBhVzl1UGdvZ0lDQWdJQ0E4TDNKa1pqcEVaWE5qY21sd2RHbHZiajRLSUNBZ1BDOXlaR1k2VWtSR1BnbzhMM2c2ZUcxd2JXVjBZVDRLR1Y3aEJ3QUFENjVKUkVGVWVBSHQzTHVPSkdjVkIvQmQ5bUlITmhMaUloT1FPRWFDQ0RraUlDTkc0ZzM4Q2p3SkNRbENCQVNJQk42Q2hBZ0pKRVJpSkF2WkFveXhmRm52aGUvczlKRnFlM3RtdWs5L3A2ZDY1MWZTTjFWZFZlZFV6YTlxL2wyOTlzeWRPM2Z1dkQvR3N6R2ViT2F4Ykt6WDROSG0rdnhxekdONmNESHpkU0Z3ZjdQODh6R1Blem5OM05mcnZhL2oyanpkWEs5UHZ6SVdUQVFJRUZpVmdHQmExZVZ3TWdRSWhJQmdjaDhRSUxBNkFjRzB1a3ZpaEFnUUVFenVBUUlFVmljZ21GWjNTWndRQVFLQ3lUMUFnTURxQkFUVDZpNkpFeUpBUURDNUJ3Z1FXSjJBWUZyZEpYRkNCQWdJSnZjQUFRS3JFeEJNcTdza1RvZ0FBY0hrSHJndEF2RkxvcVl6RVJCTVozS2hGcWQ1ZDdPYzg4VW1pNWNJaEJXdlMzRFd1RHIvUE1ReDUrYWQ2Qmk5dzJ2VE8rZUhkN2c5RldtVWYwN2o5bnpuTi8rZEh2VkdFTVh4OTVpK1BVWmN2SDJmb1BLQ1IvMVB4L2pqR0crT0VYL1Q2YWdUR3ZXbXF3WEMvdDRZL3hranJsMTQ1L1VZaTZZaGtDWnZqZVZ2alBGNHMyN01URTBDY1EvR2c4N0hZM3gvak4rUEVWT3MzemNUY3QvUFpqd3gvV1VjK0wwNEE5UEpCZklIOE9RSFh2a0I4d2IvNXpqUEdLYlRDanc4OW5Bemd1bU56VW5FeWNRVGs2bGZJQUlwbm5Cam1IWUxSRGpGSjRBWXNXenFGNGkvcHZyNUdKa0o1U1BPQ0tZTW81am5jdm1FRkJLWUtDQzhKMkx1MFNvL3NzVkg1Nk9tZmY5TjZhaURLQ1pBNEZZSlpFQ1Z2Mm5CVktaVFNJQkFsNEJnNnBMVmx3Q0Jzb0JnS3RNcEpFQ2dTMEF3ZGNucVM0QkFXVUF3bGVrVUVpRFFKU0NZdW1UMUpVQ2dMQ0NZeW5RS0NSRG9FaEJNWGJMNkVpQlFGaEJNWlRxRkJBaDBDUWltTGxsOUNSQW9Dd2ltTXAxQ0FnUzZCQVJUbDZ5K0JBaVVCUVJUbVU0aEFRSmRBb0twUzFaZkFnVEtBb0twVEtlUUFJRXVBY0hVSmFzdkFRSmxBY0ZVcGxOSWdFQ1hnR0Rxa3RXWEFJR3lnR0FxMHlra1FLQkxRREIxeWVwTGdFQlpRRENWNlJRU0lOQWxJSmk2WlBVbFFLQXNJSmpLZEFvSkVPZ1NFRXhkc3ZvU0lGQVdFRXhsT29VRUNIUUpDS1l1V1gwSkVDZ0xDS1l5blVJQ0JMb0VCRk9Yckw0RUNKUUZCRk9aVGlFQkFsMENncWxMVmw4Q0JNb0NncWxNcDVBQWdTNEJ3ZFFscXk4QkFtVUJ3VlNtVTBpQVFKZUFZT3FTMVpjQWdiS0FZQ3JUS1NSQW9FdEFNSFhKNmt1QVFGbEFNSlhwRkJJZzBDVWdtTHBrOVNWQW9Dd2dtTXAwQ2drUTZCSVFURjJ5K2hJZ1VCWVFUR1U2aFFRSWRBa0lwaTVaZlFrUUtBc0lwaktkUWdJRXVnUUVVNWVzdmdRSWxBVUVVNWxPSVFFQ1hRS0NxVXRXWHdJRXlnS0NxVXlua0FDQkxnSEIxQ1dyTHdFQ1pRSEJWS1pUU0lCQWw4RDkwZmpMVGZOSFkzNXZqR2ViMTNkM0xDL1h4VzRQRi92RWE5UHBCT0phUEJnanI5Y2hSODdybU5mK2tGcjdFcmhPSU83SnZMZnkvc3g3TG1xWHk4dlhzZS96VElvdjM0d3RZM3I5WW5idzEvamhNSjFXSUM5c3ZKbVlDS3hGSU83TG1DSlhqc21GcjBhRFg0OFI0UlEzK2I0ZjdUSUY0K0FmakJGVHJydDQ1V3VYUUliU3Q4WUJmanpHNDhXQmNsdXN5cHRrZVYxeWUxejMvNDd4aHpHZWptRWlNRU1nNzZWL2oyYS8zVFNNK3kvdnhldU9FZnRHQm4xeDNZNzdidC8zd1B2MnM5L2xBdkZ4TzZZZmpSRVhzam8rSExYeFVUd20xKy9Dd2RmakJhYmNTL0hPR1FsMVRMTkl5ZmpoTUoxV0lKK1U0ck44WEw5OXIyRmNyM2pTL1dnTTEyMGdtS1lLNUQyVmI2Q1Y1czhpbVBJZHQ5SWdhdkpFcXZYcWpoT0lHMkRmVUZydXQrL0g5dVBPVHZWdEZjaVBkYVh2UDRPcFZLeG9WUUxMMExucXhISy9uRisxcjIwRXFnSkhQYkI0MTZ5eXF5TkFvRTFBTUxYUmFreUFRRlZBTUZYbDFCRWcwQ1lnbU5wb05TWkFvQ29nbUtweTZnZ1FhQk1RVEcyMEdoTWdVQlVRVEZVNWRRUUl0QWtJcGpaYWpRa1FxQW9JcHFxY09nSUUyZ1FFVXh1dHhnUUlWQVVFVTFWT0hRRUNiUUtDcVkxV1l3SUVxZ0tDcVNxbmpnQ0JOZ0hCMUVhck1RRUNWUUhCVkpWVFI0QkFtNEJnYXFQVm1BQ0Jxb0JncXNxcEkwQ2dUVUF3dGRGcVRJQkFWVUF3VmVYVUVTRFFKaUNZMm1nMUprQ2dLaUNZcW5McUNCQm9FeEJNYmJRYUV5QlFGUkJNVlRsMUJBaTBDUWltTmxxTkNSQ29DZ2ltcXB3NkFnVGFCQVJURzYzR0JBaFVCUVJUVlU0ZEFRSnRBb0twalZaakFnU3FBb0twS3FlT0FJRTJBY0hVUnFzeEFRSlZBY0ZVbFZOSGdFQ2JnR0JxbzlXWUFJR3FnR0NxeXFralFLQk5RREMxMFdwTWdFQlZRREJWNWRRUklOQW1JSmphYURVbVFLQXFJSmlxY3VvSUVHZ1RFRXh0dEJvVElGQVZFRXhWT1hVRUNMUUpDS1kyV28wSkVLZ0tDS2FxbkRvQ0JOb0VCRk1icmNZRUNGUUZCRk5WVGgwQkFtMENncW1OVm1NQ0JLb0NncWtxcDQ0QWdUWUJ3ZFJHcXpFQkFsVUJ3VlNWVTBlQVFKdUFZR3FqMVpnQWdhcUFZS3JLcVNOQW9FMUFNTFhSYWt5QVFGVkFNRlhsMUJFZzBDWWdtTnBvTlNaQW9Db2dtS3B5NmdnUWFCTVFURzIwR2hNZ1VCVVFURlU1ZFFRSXRBa0lwalphalFrUXFBb0lwcXFjT2dJRTJnUUVVeHV0eGdRSVZBVUVVMVZPSFFFQ2JRS0NxWTFXWXdJRXFnS0NxU3FuamdDQk5nSEIxRWFyTVFFQ1ZRSEJWSlZUUjRCQW00QmdhcVBWbUFDQnFvQmdxc3FwSTBDZ1RVQXd0ZEZxVElCQVZVQXdWZVhVRVNEUUppQ1kybWcxSmtDZ0tpQ1lxbkxxQ0JCb0V4Qk1iYlFhRXlCUUZSQk1WVGwxQkFpMENRaW1ObHFOQ1JDb0NnaW1xcHc2QWdUYUJBUlRHNjNHQkFoVUJRUlRWVTRkQVFKdEFvS3BqVlpqQWdTcUFvS3BLcWVPQUlFMkFjSFVScXN4QVFKVkFjRlVsVk5IZ0VDYmdHQnFvOVdZQUlHcWdHQ3F5cWtqUUtCTlFEQzEwV3BNZ0VCVlFEQlY1ZFFSSU5BbUlKamFhRFVtUUtBcUlKaXFjdW9JRUdnVEVFeHR0Qm9USUZBVkVFeFZPWFVFQ0xRSkNLWTJXbzBKRUtnS0NLYXFuRG9DQk5vRTdyZDExdmdjQk9MNlB4bmozaGpQenVHRUR6ekhwMlAvR0tZekV4Qk1aM2JCSnB4dUJsQUUwbWViZnEveUQrL2Q4VDNtOXp5QlQ0dFRDQWltVXlpdjZ4anhneHJUbTJQOFpJd3Z4NGlQOUsvU0QyOThMNitOOGFjeC9qNkdjQm9JSmdLZEF2R3hLNllmamhFL2dQSGtFMDg4c2J6dk9IVC9mZnV1YmIrZkRaT1lIbHpNZkQwWEFVOU01M0tsNXA1blBqVmxRT1hyQ0phWWRyMk9iY3NuajF6T2ZaOFg3dml5N0prOWNyZmNGcStYZlhLLzNMN2NsclU1WCs2VHk0L0h4bmhpK2lKM01qOHZBY0YwWHRkcjl0bkdEL3p5aDM2NUhNZGF2czdsbkc5dmo5ZTdwcXYyWDI1YjF1YjZuQyszYlM4djk4bmwvSy9OK1hxN3h1dVZDd2ltbFYrZzV0TjdWWDl3WDlYdnEvbDJXRS83ZkdkWnp4azVFd0xIQ2VUSHVlTzZxTDVSQWNGMG8vd08zaURnYWFrQjlkUXRCZE9weFIydlc4QVRVN2Z3Q2ZvTHBoTWdPOFJKQlR3eG5aUzc1MkNDcWNkVlZ3SUVqaEFRVEVmZ0tWMmxnSTl5cTd3c2g1MlVZRHJNeTk3ckYvQlJidjNYNk5vempQK1A2ZGdMNlIzcVd1YldIZmkveUJzZVRGNDB1WWxYUitXS0o2YWJ1R1E5eDh3Znhwem5VUzc3UWQzZUwvZVArWExiY2ptMzVickw1dGtydHgvNmVsa1h5OHZYMlN2bnkrMjVYODV6SC9NekU0Z25KaGZ4ekM3YTVuVHpsM2x6bnQvRjlqdlY5dXZMOXN2MU1WL1dMSmN2MjViNzVEeDdWVjh2NjViTDJYYzVYMjdQNVllYkhmenk3bExxdE10SDVVcGN5TitOOGRZWWo4YUlKNmhER2thd3ZUdkdYemUxOFV1aHBsNkJ1R1p4amI0MnhnL0dpTDh1RUZQK1VGNjh1dDFmNHo2TVgrTDk4eGp2alpGbVk5SFVLQkJ2a25FL3ZqM0dMemZIT1NSUFl0L284WG5VZmp4R3JLaU9kNkxKbUxiZnVTL1crdG9oSUlUMlYyVzF2OVd4ZStZVDZ2ZEdvMnFlUEsrTEo1NlB4b2cvR3BaUFRHUHgyaW1LWTRvVGlUOHhZVHF0UVBqSEQ1dzNnNnZkNDhuSlUvelZSak8zWmk3RVUxTSt5ZWU2Zlk0VCswWW1mUkpmWXNRVTgzMy9NWHg1TU85SXovbE8vaVd1Z1RlRms3TTc0QjRDeXpmTnVFLzN6WWpjOS82K1FiVEh1ZGlGQUFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DaHdmMEt2RExkN0UzcHBzYi9BczdIcjAvMTN2NVY3eHIxNTkxWis1emZ6VFVlZVBCN2o2Q3lZRVV5ZmJBd2UzWXpGclQ1cS9OQkZRSmxlRmdnYndmMnlTK2VhSjV2bUh4OTdrQm5COU00NGlZZGp2REZHbkpoM3FJSFFPRVVRUFJqai9USCtOb1p3R2doYlU1cThQZFovWjR3dngzQmZiaUZOZmhuM1plVEovOGI0N296ZWNZTkgwd2lWbUJ2bllmQ2JjYTFpaXBBeXZTaVFiN2kvR0t2ZHorZGpFRSs0Y2IwK3pRdjQ0bVU5N0ZWZStNT3E3RjBSaUhmOWVQZVBKOVF2S2cxdVdVMys4MExNWjl6cnQ0eXYvTzNHZlhyVUUrcU1pNVVua1BQdDd5YUNLN2ZsY3N4aml2VzU3dm1LSFY5MmJjOTF5ejdMMHR3ZTY1YkwrWHE1Ynl4dm45LzI5bmlkeDRybDdmTmVIaU9YdCtmYlBlSjFUTXRqWDZ6WnZTNzN6ZjF6bmpYbUx3dWtVY3lYeTNsdG9pS1dZOHJ0eTIwWFcxNzh1dHcvOTgzNWNzL3RkZms2NTFmdG05dGkzNXppL1BMMXZ1ZWF0WWNjTTJ0eW5yVTV6L1V4MzdWdXViMjhQQ09ZNHVBSnRldEVsdHR5T2VmWDFWNjJQZXR6dm4zYzVmcmw4bVg5c241NzMxeS9xMjY1NzY3bFhKZnpYVDJ1Nm4vZC9zdGF5OWNMWEhZZGx1djNNVi91bjhzNVg1N0Y5cnA4bmZPcjlzMXQyL3RlOXpycnR1ZmJkYkY5MTdydHV1Vit1L2JmdFc1WGo0UFg1WC9xUDdoUUFRRUNCTG9FQkZPWHJMNEVDSlFGQkZPWlRpRUJBbDBDZ3FsTFZsOENCTW9DZ3FsTXA1QUFnUzRCd2RRbHF5OEJBbVVCd1ZTbVUwaUFRSmVBWU9xUzFaY0FnYktBWUNyVDNWaGgyLy9VZG1QZmtRTVQyQktJLy9NNy96UkV6cmQyOFhKbEF2SEwxbkhkNHRjQlRGY0xwRkhjMis3dnE2M1dzRFd1Vi93dHA2ZHhnNysrT2FOWnY1NnlhV2ZXSlBEYXBtLzhJcS9wYW9IOHl3dHBkdlhldHE1RjRQVUlvMzlzenViek1mZlJiaTJYNXZMemlMOFErUFV4UHR6c2trOEZsMWZjdmkxcDhxL3hyY2Q5L2NFWWNhLzdHRHdRVmp6bEU5T24vd2ViYTBWNVU2V0pxZ0FBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiLCJ0eEF1dGhTaW1wbGUiXSwiYWFndWlkIjoiZmNiMWJjYjRmMzcwMDc4YzY5OTNiYzI0ZDBhZTNmYmUiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA5LTE4In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wOS0xOCJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjE0MzRkMmYyNzdmZTQ3OWMzNWRkZjZhYTRkMDhhMDdjYmNlOTlkZDciXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMTQzNGQyZjI3N2ZlNDc5YzM1ZGRmNmFhNGQwOGEwN2NiY2U5OWRkNyJdLCJkZXNjcmlwdGlvbiI6Ik5FT1dBVkUgV2lua2VvIEZJRE8yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDSFRDQ0FjS2dBd0lCQWdJQ2RkVXdDZ1lJS29aSXpqMEVBd0l3ZXpFTE1Ba0dBMVVFQmhNQ1JsSXhFekFSQmdOVkJBb1RDa05sY25SRmRYSnZjR1V4RnpBVkJnTlZCQXNURGpBd01ESWdORE0wTWpBeU1UZ3dNU1F3SWdZRFZRUURFeHREWlhKMFJYVnliM0JsSUVWc2JHbHdkR2xqSUZKdmIzUWdRMEV4R0RBV0JnTlZCR0VURDA1VVVrWlNMVFF6TkRJd01qRTRNREFlRncweE9EQXhNakl5TXpBd01EQmFGdzB5T0RBeE1qSXlNekF3TURCYU1Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUejJqTmFLT0svTUtkVzJmbWUxdHE2R1JFdVB1dUtXOUhnV1lnTVJyanZaVVRPcUxBTkozTWQ1SHF2MUVOMXpNZDRsV3R5ZnpSbGE3cnY1QVJCb09vVG96WXdOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQkVHQTFVZERnUUtCQWhOblRXMGE0RTh1akFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTXJoYjhTbWZOTGVMTmdhQVZtUTZBT01pTE5MVkhYMGtGVU84MENuVDM4RUFpRUF6TkFndjRkSCtIRGhaU2daV0ppYVB1L25mWlRldUd5NE15ZFBNcTV1cnM0PSIsIk1JSUVPRENDQTkyZ0F3SUJBZ0lEQUluQk1Bb0dDQ3FHU000OUJBTUNNSHN4Q3pBSkJnTlZCQVlUQWtaU01STXdFUVlEVlFRS0V3cERaWEowUlhWeWIzQmxNUmN3RlFZRFZRUUxFdzR3TURBeUlEUXpOREl3TWpFNE1ERWtNQ0lHQTFVRUF4TWJRMlZ5ZEVWMWNtOXdaU0JGYkd4cGNIUnBZeUJTYjI5MElFTkJNUmd3RmdZRFZRUmhFdzlPVkZKR1VpMDBNelF5TURJeE9EQXdIaGNOTVRnd01qSXlNak13TURBd1doY05Namd3TVRJeE1qTXdNREF3V2pCME1Rc3dDUVlEVlFRR0V3SkdVakVUTUJFR0ExVUVDaE1LUTJWeWRFVjFjbTl3WlRFWE1CVUdBMVVFQ3hNT01EQXdNaUEwTXpReU1ESXhPREF4SFRBYkJnTlZCQU1URkVObGNuUkZkWEp2Y0dVZ1NXUmxZM2x6SUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTTFZMKzFTVEp2YUVSTzVXQ1IrakdjQXhMdm1QQkRpWlkxTmdGRklocFg2T0FaQXBRWW10NnhTaDc0U3dNK21qZ25zU0VjYzRBMlVmMTM5RmdaNHJwWW80SUNWVENDQWxFd0V3WURWUjBqQkF3d0NvQUlUWjAxdEd1QlBMb3dTZ1lJS3dZQkJRVUhBUUVFUGpBOE1Eb0dDQ3NHQVFVRkJ6QUNoaTVvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMlZqWDNKdmIzUXVZM0owTUZNR0ExVWRJQVJNTUVvd1NBWUpLb0Y2QVdrcEFRRUFNRHN3T1FZSUt3WUJCUVVIQWdFV0xXaDBkSEJ6T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdlkyaGhhVzVsTFdSbExXTnZibVpwWVc1alpUQ0NBV0FHQTFVZEh3U0NBVmN3Z2dGVE1EK2dQYUE3aGpsb2RIUndPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2Y21WbVpYSmxibU5sTDJObGNuUmxkWEp2Y0dWZlpXTmZjbTl2ZEM1amNtd3dnWWFnZ1lPZ2dZQ0dmbXhrWVhBNkx5OXNZM0l4TG1ObGNuUmxkWEp2Y0dVdVpuSXZZMjQ5UTJWeWRFVjFjbTl3WlNVeU1FVnNiR2x3ZEdsakpUSXdVbTl2ZENVeU1FTkJMRzkxUFRBd01ESWxNakEwTXpReU1ESXhPREFzYnoxRFpYSjBSWFZ5YjNCbExHTTlSbEkvWTJWeWRHbG1hV05oZEdWU1pYWnZZMkYwYVc5dVRHbHpkRENCaHFDQmc2Q0JnSVorYkdSaGNEb3ZMMnhqY2pJdVkyVnlkR1YxY205d1pTNW1jaTlqYmoxRFpYSjBSWFZ5YjNCbEpUSXdSV3hzYVhCMGFXTWxNakJTYjI5MEpUSXdRMEVzYjNVOU1EQXdNaVV5TURRek5ESXdNakU0TUN4dlBVTmxjblJGZFhKdmNHVXNZejFHVWo5alpYSjBhV1pwWTJGMFpWSmxkbTlqWVhScGIyNU1hWE4wTUJFR0ExVWREZ1FLQkFoRGFRYmhURnRqY2pBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQW9FZXBITUM1WDlqQkthR3BoY0tqaWRoaU4rWm56N3YzUzNoYzMxL0F1bnNDSVFES3FvZ0syU1pPWFpjdnZIQ0I2VVFTYUEwbkxuNFJVd3kxZ3VEaXZiWmJ3Zz09IiwiTUlJRU9EQ0NBOTJnQXdJQkFnSURBSW5CTUFvR0NDcUdTTTQ5QkFNQ01Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd0hoY05NVGd3TWpJeU1qTXdNREF3V2hjTk1qZ3dNVEl4TWpNd01EQXdXakIwTVFzd0NRWURWUVFHRXdKR1VqRVRNQkVHQTFVRUNoTUtRMlZ5ZEVWMWNtOXdaVEVYTUJVR0ExVUVDeE1PTURBd01pQTBNelF5TURJeE9EQXhIVEFiQmdOVkJBTVRGRU5sY25SRmRYSnZjR1VnU1dSbFkzbHpJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVNMVkwrMVNUSnZhRVJPNVdDUitqR2NBeEx2bVBCRGlaWTFOZ0ZGSWhwWDZPQVpBcFFZbXQ2eFNoNzRTd00rbWpnbnNTRWNjNEEyVWYxMzlGZ1o0cnBZbzRJQ1ZUQ0NBbEV3RXdZRFZSMGpCQXd3Q29BSVRaMDF0R3VCUExvd1NnWUlLd1lCQlFVSEFRRUVQakE4TURvR0NDc0dBUVVGQnpBQ2hpNW9kSFJ3T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdmNtVm1aWEpsYm1ObEwyVmpYM0p2YjNRdVkzSjBNRk1HQTFVZElBUk1NRW93U0FZSktvRjZBV2twQVFFQU1Ec3dPUVlJS3dZQkJRVUhBZ0VXTFdoMGRIQnpPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2WTJoaGFXNWxMV1JsTFdOdmJtWnBZVzVqWlRDQ0FXQUdBMVVkSHdTQ0FWY3dnZ0ZUTUQrZ1BhQTdoamxvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMk5sY25SbGRYSnZjR1ZmWldOZmNtOXZkQzVqY213d2dZYWdnWU9nZ1lDR2ZteGtZWEE2THk5c1kzSXhMbU5sY25SbGRYSnZjR1V1Wm5JdlkyNDlRMlZ5ZEVWMWNtOXdaU1V5TUVWc2JHbHdkR2xqSlRJd1VtOXZkQ1V5TUVOQkxHOTFQVEF3TURJbE1qQTBNelF5TURJeE9EQXNiejFEWlhKMFJYVnliM0JsTEdNOVJsSS9ZMlZ5ZEdsbWFXTmhkR1ZTWlhadlkyRjBhVzl1VEdsemREQ0JocUNCZzZDQmdJWitiR1JoY0RvdkwyeGpjakl1WTJWeWRHVjFjbTl3WlM1bWNpOWpiajFEWlhKMFJYVnliM0JsSlRJd1JXeHNhWEIwYVdNbE1qQlNiMjkwSlRJd1EwRXNiM1U5TURBd01pVXlNRFF6TkRJd01qRTRNQ3h2UFVObGNuUkZkWEp2Y0dVc1l6MUdVajlqWlhKMGFXWnBZMkYwWlZKbGRtOWpZWFJwYjI1TWFYTjBNQkVHQTFVZERnUUtCQWhEYVFiaFRGdGpjakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBb0VlcEhNQzVYOWpCS2FHcGhjS2ppZGhpTitabno3djNTM2hjMzEvQXVuc0NJUURLcW9nSzJTWk9YWmN2dkhDQjZVUVNhQTBuTG40UlV3eTFndURpdmJaYndnPT0iLCJNSUlDSFRDQ0FjS2dBd0lCQWdJQ2RkVXdDZ1lJS29aSXpqMEVBd0l3ZXpFTE1Ba0dBMVVFQmhNQ1JsSXhFekFSQmdOVkJBb1RDa05sY25SRmRYSnZjR1V4RnpBVkJnTlZCQXNURGpBd01ESWdORE0wTWpBeU1UZ3dNU1F3SWdZRFZRUURFeHREWlhKMFJYVnliM0JsSUVWc2JHbHdkR2xqSUZKdmIzUWdRMEV4R0RBV0JnTlZCR0VURDA1VVVrWlNMVFF6TkRJd01qRTRNREFlRncweE9EQXhNakl5TXpBd01EQmFGdzB5T0RBeE1qSXlNekF3TURCYU1Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUejJqTmFLT0svTUtkVzJmbWUxdHE2R1JFdVB1dUtXOUhnV1lnTVJyanZaVVRPcUxBTkozTWQ1SHF2MUVOMXpNZDRsV3R5ZnpSbGE3cnY1QVJCb09vVG96WXdOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQkVHQTFVZERnUUtCQWhOblRXMGE0RTh1akFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTXJoYjhTbWZOTGVMTmdhQVZtUTZBT01pTE5MVkhYMGtGVU84MENuVDM4RUFpRUF6TkFndjRkSCtIRGhaU2daV0ppYVB1L25mWlRldUd5NE15ZFBNcTV1cnM0PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FJQUFBRDhHTzJqQUFBQ3FVbEVRVlJJeDJQOC8vOC9BeTBCRXdPTndhZ0ZwRmx3OGNLRmlySXlSM3Q3UzFPejBLRGdCZlBtLy96NWszaXp2bjM5bHArVGEydGx0V1RSSW9Ub2Z4aFl0WEtsbHBxNnNyd0NBaWtvUklWSHZIMzc5ajl4NE5TcFUwQXRRSTFXNWhad1FhZ1B6cDg3VjExWmlYQXZJeGo5WnpoNTRrUk5aUldSUHZqOTZ4Y0RPTTB6TVRLaUI5Rzh1WFAvL2ZzSE5GUkFTTEMrc1hIbTdObHVidTRRbTNidDNMbHU3VnBpTEdDRW1jdUlhY0daVTZmQjRjV1FYMUFRR3gvbjdPSXlhZW9VYlYwZGlJdmFtbHVlUFh0R1VTVC8rZzMySFNPRGhvWUdSSVNGaGFXcHBZV1ZsUlVvK09Iamg2YjZCb29zZ0h2cXo1OC9jRGw5ZmYzTTdDd0llOCtlM2F0WHJxUWdtZUlva0RLenMvWDE5RUd5L3hrNk96b2ZQM3BFV1ViRHNBWVlSQzN0YlJ3Y0hFRDJoL2Z2NjJwcUNSZU9qQ1RtWkUwdHJaeThYQWo3OEtGRHk1WXVKZDUwVkFzWWNlcEtUVTgzTmpXQnFPbnU3SHh3L3dFK08vN2pzZ0MzMTVtWm1SdWJtOW5aMllGcXZueiswbEJmaHpPZy9xTzdsUW0vQitFQW1Id0xpb29nQ280Y09yeGswV0lpUFVFZ2twRkJVbkt5bVprNWhOM1QxWFgzemgxaVlvS0pjRFRCQTRxRnVibXRsWXViQzhqKyt2VnJUVlUxcUhRaHpRZU1CSHlockt4Y1dGd01VWG42MUtuNWMrZFN2OEpKU0V5MHRyR0dzQ2YwOTkrNmRRc3V4Y0xDQ3JIN1A1SXJTWWdEZUtGUzM5VEV4OHNIWkgvLzlyMnVHaEZRTjY1ZmgyVlBOb3FxVENVbHBlS3lVbWd4ZlBwTVNXRVJNQU11WDdhc3Y3Y1hJcWlscllYd0ZyeGVnL3FPdUdaU2RFek0zdDE3RGgwNkNQVDBwazBiTjIzY0NJOUZZS1pKejhoRTk4SGZmMzhoRERZMmRpTDkwZEhkcGF1cml4YXdyQ3lzcmUzdHVucTZpTFRYME5BQVRvSXNUeDQvdG5kd2lJeU9BdFlFeEZqQXpjM3Q0K3NMSkw5OS9Rb3NFMFZGUmUzczdSdGJtb0dWRlVxY2pUWWRoNzhGQUloQkxsTmQ3anUxQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wOS0yMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDktMjEifSx7ImFhZ3VpZCI6IjRkNDExOTBjLTdiZWItNGE4NC04MDE4LWFkZjI2NWE2MzUyZCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNGQ0MTE5MGMtN2JlYi00YTg0LTgwMTgtYWRmMjY1YTYzNTJkIiwiZGVzY3JpcHRpb24iOiJUaGFsZXMgSURQcmltZSBGSURPIEJpbyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUM2VENDQWRHZ0F3SUJBZ0lKQUpiVHlydTFYL0lQTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVEFlRncweE9EQTJNVEl4TkRRMU5UQmFGdzB5T0RBMk1Ea3hORFExTlRCYU1DTXhJVEFmQmdOVkJBTU1HRWRsYldGc2RHOGdUWFZzZEdsQmNIQWdSa2xFVHlCRFFUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1WaktIV3BiRDdUU2xNeG9jalRsNm5JZjd4MzJQbXNROXpHdUxHR3FBMFVRWm9JcTNYTHpMNkxZVXZKNUE1ZzB1eUZHbGxIRWZHQUtyRWFDUThGVnZQUy9VaDBGeWZ6V2hSQXppVFNpampNSUlWampqVXY5bTl2Rm1jWFNjZ0hpZzdPZHo4ODU4VjBrck5IOTlxR20zd2pnYU9lclRXbXQralhDVWZuMDFJa1RQd3hHMkhsZ0VkNDVqTkxTVjdWb29sK0tlOEUya2k0bEVrVGVIemJvdWxSNUdVYnAzbk1pN0U0N1ZNUWEzYk53bnpXQmJzYUJTU1FoTGszbTVIYUtoaHhhNndKREs0N05pTUNrQ2tkSUh1V1NRTFZBZm04NVVBT050RU9Qd2kwT3VLM3FiZTh5S09GR2YwS2hCNU1NZUF5bTdNVi9NNFcwYTQ5b2dQRDlwTUNBd0VBQWFNZ01CNHdEQVlEVlIwVEJBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUNBb1F3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUpXejV4TE1rNVdOWWJBYjZ5T3hFQ0JvWjJXZUIvcWw0VkozTy8zL3ROc3hPWW56TGVXbzU0MHpRaDlyQW1heHo3ZXVtQmxza01xNHlHUFNOWEI5eWNXR0hna2NDZVN6TjJ3djhDSXpEQnMyb0JaalROazY1TEJaRHNzVE9CdE1XLyt1VEZIUWZidU8zSVNMaEkwRFhmUkVpOU5ETTNqZmsxMXhIY3NmaDJSTVYrUWROZndWYVpackNxK291RytFdmt2N0txcStveXUwVkZNL3R6NjhUR2w2eWxoUEZSMXFoOXd0dHBWakFPT0NFUUNMcVAyZFAyOGx3WUJ5Q3FIUXFWSHdidWp2L0xaalpuS1czTFluZFppeFBQU1JDSnNzRER3SnZoL2Y2blR4ZzlaRSsvSmNZcmU1Q2FJOG56VkhhU09Dak5KN0Z6VUxHNjRKaVdPdlE1MD0iLCJNSUlEZFRDQ0FsMmdBd0lCQWdJSkFJQ1VUdmtndGo1Q01BMEdDU3FHU0liM0RRRUJDd1VBTUZFeEN6QUpCZ05WQkFZVEFrWlNNUXd3Q2dZRFZRUUtEQU5FU1ZNeEN6QUpCZ05WQkFzTUFrTlRNU2N3SlFZRFZRUUREQjVIWlcxaGJIUnZJRTExYkhScFFYQndJRVpKUkU4Z1UzVmlZMkVnUTBFd0hoY05NakF3TnpBM01UUXpOekU0V2hjTk16QXdOekExTVRRek56RTRXakJSTVFzd0NRWURWUVFHRXdKR1VqRU1NQW9HQTFVRUNnd0RSRWxUTVFzd0NRWURWUVFMREFKRFV6RW5NQ1VHQTFVRUF3d2VSMlZ0WVd4MGJ5Qk5kV3gwYVVGd2NDQkdTVVJQSUZOMVltTmhJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF2QUtPZXFDNS9wMEQxaXNDWUtRSmxWVU9yQjZJN0RMb2N1bkUvUm04ZHVHVGJ5eFFodDNDYkZWVHYzTjJMcDJmYmp4bEkrM3NPU0drMzNGVFlrVHF4Y2RKSXJKN1Nza0JjVVNOcmZLT2FRVC82S1FjUDRDbTdWKzY1NVRxK1RXeHl4V1FoRHlndDE1cW9QN011SzZiVDlTd3BDanBmS2hhTVNteVFhTW9VY1JBYkxxZHpCQ2FjMGh6QitaZStncUpsbldWOVVhU0kyckZzVnVINFpFMGNSTytNT3BhTGdNL3MyNDhuR0dIcDIyZXdTUWZiblBhQmJiOGlxeUFQK2N1NTJHTHNVcEtSSmViRStSNitQTVE5SkNkV2VRWlIzRGtmU2lka3YzbWNiNGpxMWlJdGErTXFLaFJud3JmWGg5MTFLV0xuWUFsOUVOQ2hMWDBjNlNqMVFJREFRQUJvMUF3VGpBZEJnTlZIUTRFRmdRVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdId1lEVlIwakJCZ3dGb0FVV0x2aFJCVVBuOHVMSWY2OCtndi9OWkl3R1NJd0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBRkxyRGhhZWdlS0h4WWpIM0VQM3ZVQktobnpNMjA2QVN4Z2VZQ08yRWM5cE9sWUphZXFGRStzVWFtVVYvcHdqRGxxTmFTZ0ZneTdUd2VZa3ZPbU1uNHFTY3NIcXZKM3pHT0FpYWZ3YWgxdlVIZkNsWFI4K2F4TzJpR09VRjBKS3JaOVlZamJBYTUvNEhDbHY3akZQT2RNV1RPUXluZ29pSEFzM2prdVlqcENMRmxCNFZPaTNkMXdqQTFwblRkQktrQWI3dDhuVHZ3Ky9YYkZ2Y1FhNzNWSDdzanZvQnFEM2ZkTWZSY3VWcTRxVVp0WlQ2Y0dhZ1RIRDYxVHRxaDlvTUNaWGNEYlIxUEdabk5icXljc1dQRElLMG5wbUszLzNsZlY4Yytac3J5NmUxNzBtZkpNWnA3TzhtNkNTejYvVkxLK3lESmQ3ODQxd3BtZUtUZjZJblpBPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBUXdBQUFBZ0NBWUFBQURubFVacUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUFBWmRFVllkRk52Wm5SM1lYSmxBSEJoYVc1MExtNWxkQ0EwTGpBdU1qSHhJR21WQUFBSzFFbEVRVlI0WHUxZERYQWNaUm0rTk9BZktvZzZXTzBRY3JlWDNPNzFSNDFvSGRTcXFEQU9nMytjWUVYQm9sWFJURW4yMjB0YUtUYzY0bWdCcXpCaUVVVnBCZHFpd3docVNkSVMydXBZU2d2UnRwVFNja2xqV3pIYWdqcFNSZHI0dkx0dmpydmsyN3ZkdmQxTGpuN1B6RE4zdC9kKzcvdCtmOC8rNzhhSzBORGFhcjJxT2RYWm9xV3lIOVIwYTBGY3Q2N1dkSEdUWm9qVkNjUHFTZWpXMW9RdUhzT3kvZUJUc0RtTS81NFpUOWorTFdHSWc3RGZCL3NCY0RQc2Y0WGZQOFgzYjJ1RzFaSFF6VThtVXVLZHlXVEhtNXFhY2kvakhBS0J5aWYwYkJyK0x3YVhJUFlQa01kcWZMOFhkV3BsczFBQTMxL1FqT3c5OEw4UzliOEJYSVIyK25EYzZEb3psc2swc2xua1FNeGtQR1hPOUVKdFZuWUdGNHNVeVZuZDhVVGFlcDhidys2TGFrQmo1aXpkYk5KUzFyeEVXbnlXeGczNkVtUGRXb1BQRGVqZjdlQVRHTXNIYUR6VHVDNmhiajBOL3BYbUFzcnVnczBXTFA4TnVCSmpaSm1XRWxjbDA5bVBKMUptVzB0TDUrdWlIQnVHa1hzbGpYODduaTRFelZuazlBdmtzUW41N0VTZGhyQjhCTXVQak9XUC8vNE9Ic1IvZTdEOFlkVGxmdFJoRmZnZExHOUh1MXdBZnpyNTVqQU9raVFLaHZWYkdCNkMwLy9pKzJpTmVSeDhGZ252UmZ4ZmFpbnpTazdORTBpSVVQYmY0M3dXbU5UTmQ3QnBLRUE3TFpmRkFZOXpwM3laVFNNRGlRVmkvVStTZzVRWUFJZk9tRzJld3NVakEvcmhXN0w0QmVybWo5aDBVb0IyT0IrVFpUVzRCL2s4T3lHL3lDaU9vVzFJWUg2SDhYUHo5TGJjS3ppbFFHaHBNWnZoWnlIR3dHM2c0MkJrODVaOG85MEc4WDBOaVNzMUl2MlFHazhLZFdzenQ0c25JUDhScVI5bURRWERJZFpTYkJvWjBJbDNTMk9YWlhZcEY0OE1VMTR3bksxYmVXNDFwTDNGRVFDSmxQVld0REcyZnV5VnJOUjN0QlRkU2pCOFlySUZveVZ0bm8yT0N6Qmd4RE5CQjZwWEtNSHd4aUQ5Z0szS2M2UGNrdkJHSlJpK01jbUMwWUQ0ZmRLNFhvaDlXL1lUQ1pSZ2VLTnZ3Y2hrR3RHMmUyVytha3NsR0w0eG1ZSkJheGxwVEkra05SUWRtR1Izb1VNSmhqZjZGUXc2Y0NyelUzdENNTERXdVFzZDNSK0F3M0tuQlE1S3luamhqZHhPbm5EaUNFWnVHanJzWVdsTUp0cGlXVUszQm1UL0ZmRXVkaGc2VVBlNkZnejBiUjZmYTZNbW5ZM2tsRHdoYVlqTFVVNmVzMjd0MGd6em03VmdVdTk2RDZma0h4Q2E2MlVWR0NNcThnMDJqUlFuaW1Cb1J2WWlhVHdtMm50Zlc5dkNrN1cwZFlIcy93SjE2M2s2ZU1adVEwVzlDd2JHOUsxc09xV0F2SVUwWDV0aURadE5iU2pCY0dFRWd0SFdkc3ZKOEUybkF1VXhpYnA1aFdNOTJvRGYyeWI4WDBLeDNyRU5GMG93b2dIbTBoSnB2amFWWVBqQ2lTQVlpYlQxZVdrc0ppYkNrL1BtNVU1aWM4cnhRcGxkTVJQcDdIbHNIaHFVWUVRREpSZ2g0c1V1R0hTUkQrcElWK1RKNHhIMUxHOWRqQ0hUaU1sUjRWaUcyRTdIUmJoQUtGQ0NFUTJVWUlTSUY3dGdvSjJ6MGpoTXRIT2VqbDJ3ZVFGWS9sR1pmU25GZkRZUEJVb3dva0hDTUJkTDg3V3BCTU1YS2dxR0lTNXZUcHRuaDBYVSswNVpuQUpERkF6RDZEZ2QvcDZXeG1IR0RmRkZOaCtIMFFiMHdhT3lNbU9FK09VTkkvY1NMbEExNmwwdzBGNjc0N3E0cFJwR2NkcWE3a3VSNVV0RUg0NWdEbXdLaS9EWmo4LzdJRVMzNHJPemVhYVl6V2xVaDNvUmpKb3pSTUdvT0FFTmEwaTJkVEdHZUVwOFRGSm1QRHZZdkdyVXUyQ0VRYnFoa3NPRkJzeWxpMld4YXNUajZOZDEycHNYdjU3VENRWWxHQzRNU1RCYVc2MDNvbzFkYjZxenFWdGZZbk01NkFwQnc5b3hvVndSTVlsR05LMzkxVnlpS2lqQmlFWXdtbFBkTGJKWXRTVGE3cUhpQSt1K29RVERoU0VKQnRwdmhkVC9HSFd4djl6V3hSaTB0UGlFdEh3SnhiVnNYaFdVWUVRakdIUndHdU9oMGdWNWtUT2VNaS9oaFB4RENZWUxReENNczFxdFZnenU4cmV2cHl5UGp3SHdzcFZoL1N1VldqS2RDd1NHRW95b0JBTzVwODMzb3ArZWs4V3NGZEYrd2E4U1ZvTGh3aEFFQTM3V1RQQmJSSFRjQWV4R3ZKVE5IZlFNTmNmNkJzK1A5ZWJueGZxZVBKV1gya0NaekhnZkV4akNHUUlsR05FSkJzRitFSkV1ZHN2aTFvYmlUNXlLZjlTTllPaldaalR5ZmFIUnVkOUFIb3RZcFdBNE54cUpZMUxmVE5UNUsyd2VpNjBmTWlBVUQ0S2pCZmJtajhiNjhzdGoydzdhRDJxaGZVLzB4eTZacnpIUzJxdWxwVE5sK3d5SXVoY01qQlU2NjFRTm0yY3VQb1BEUllUUkJqcGJSMk1BT1Y5SFp6T1E5OC93L2ZZd2lQSHRmamUwYnYyRmsvQ1BlaEdNT3JzT28vTHQ2N28xWERnVnVpRS9Cd0x4anhLeEtPWEcyTTZkdGkzNnc4T1JkbkdQN1RjZ2tGdWRDOGJVdkE2amxraWtPOCtUdGcySU1YU1l6ZnhEQ1lZTHF4QU1MN2V2bzc3dHRuRi8vMG5Za3RnaEVZbHhITHFhekoydGpFcWJzOWl5U1dYbjJ2NERRQWxHL2FPc1lCaldBVGJ6RHlVWUxnd3NHTGxwS0x0VjZwTkpIVlo0WUhMZi9uZkpCV0lDaDJIZFFFWGk2ZXdsTXI4bGRKNUhZdHY3aFJLTStrYzV3VUQ3N0dVei8xQ0M0Y0tBZ3VIcDlHZEtYTVhtRUl4OHUwUWNYUGpZYSsweW1Vd2oydXR4cWU4aW9vNFgydlkrb1FTai9sRmhsK1NQYk9ZZlNqQmNHRUF3NkhvSzdBNlVuY2lvNThHbXBzdGVlQjFENzlCWDVlSWc0ZjNEcDNPcEdPTE1sL2tmeHgyeHpGcmZqOFZYZ2xIL3FMQkxzb1hOL0VNSmhnc0RDRVlpVmY3MmRXYnBKZHc5Kzg2UmlzTjQ5Zzd1aDNWaEY0UEY2UW1KLzFMcTFnSXU0aG1WQkFNVDl1N3g3MHdKZy9UWWZVNmhMSlJnVkVhRlhaSUgyTXcvbEdDNDBLZGd6SjV0bmdLZkI2UyttUGovMEl3WkhTL25JZzVHUnhzaEJnTlNrU2psWWk1UkFQcnVVbG1jWW1KeS9YbkczSEV4SzZEaUZrWkV4QmpZeUNtVVJTWEJRRHVQb0E1Ym8yYlN5TDZkVS9JRTNpcVVuZ1lObTJnRDE3TjArRzhWcCtRZlNqQmM2Rk13NHJwbFNmMFVFVEZOTmk5RnovRE1XRy8raUVRa0hQYm1OOFMyYlp0NCtiaHpqMG41SjNpQmRGczFsL0FFMUwydUJhTldUT3JpQTV5U0p5RHY3OHI4MUp5ZXJ5NldRQW1HQzMwSVJ0T2MzR2xvcDhOU1AyUFV4Vk5sMS9UcjhxMnh2dng2OFBraXNmZ25mbDhmNng5MGZRVWw0bjVHR3ErWXVqaHk1cXp1MTNDUmlsQ0M0WTExS1JqMFdrZ3RGL3dtUlNVWUx2UWhHRjRtR0FhTFlQUHkyRGcwUGRZejlIN3Nwc3lOOVF4VWZDMGlYZnlGUHRvbmkxbE1HcXhjcENLVVlIaGozUWtHeENLcFcrL21kSUpCQ1lZTFBRb0d2WVFhOXVYZjcxbHA2NkpLbEh0OC9Rc1VSKzBYVFh1QUVneHZyQS9Cb0xmcjJRZkhyL0d6bGVtS0tTTVl1bmtIVFN6RWxMNCtzRmFDZ2ZvK0IrN1dqT3puMkxRc25OY0dpRDFVVHViUG9kbkY1cEdBenBnZ3Z1dFdCdXI2SDd0T3VyaVVpNVFGWFNXS010L0hCTjVFYXlYVXIrdzlNY0VwanZHSzR2Zklid1ZkdzhJcGxBV05CWlM1RHZXaE41WG40ZWRvcWQ4b2lGeXgyd2sraXUvMEl1aWw5S3dUVHNrVDRtbHhEdHJ6Um01WGpQVW8ycFhlNkc0OWdqeHZ3K2ZDaE5HaGNmaHdRQzlqYVRMRUc5eG9HRmVXdmlZK1V1U20yUStjb1hkeTZOWWlOT3d5VlBySEdCaDNKb3p1VUNzZVQ1bVhRZkYvamhnL3hPZlhOZDI4Z2pvMGFIM3BMQWxOTkdkdEw1WWk1NXZRZ2JlajQrNmcvOWdzTXFBT0gzSGFTZndFYlhjRHZtZVRodlVwVGU5Nnk0UXpNNzZRbTlZMFo5RnBkUGNtNnZOcHNBdDlzdHhwTyt2WDRFYkUyMG9UQ2NzR1NvbmwrQi9mNldhL1ZjVjUwYVNQeDd0T0RlRUJ4ZzEweHkrZGtvWGdmQWd4RmlEZTE5QU8zME0vckVRTzl5TG1BNGkvQmIrM2wrYm5rUElITjRQclVMKzErRndCMjJ2aG94MWlmMUc4MVhwYnZBMjVaaksrcjJseFIyNGExZDhSUHpFZnV3b1djc0VXaUpNellqK0kzdytWdEtzaEhnSC9BUFpTbnFqVHpmaTh4aDY3dW5VdVBkckEyOE54WXJIL0F6M3RJNGo1K1RPTEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI0ZDQxMTkwYzdiZWI0YTg0ODAxOGFkZjI2NWE2MzUyZCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwidXYiOmZhbHNlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwibm9NY0dhUGVybWlzc2lvbnNXaXRoQ2xpZW50UGluIjpmYWxzZSwiYmlvRW5yb2xsIjpmYWxzZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3Ijp0cnVlLCJ1dkJpb0Vucm9sbCI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzEsMl0sIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJwcmVmZXJyZWRQbGF0Zm9ybVV2QXR0ZW1wdHMiOjMsInV2TW9kYWxpdHkiOjIsImNlcnRpZmljYXRpb25zIjp7fSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjMyfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTA0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0wNCJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImY0YjY0YTY4YzMzNGU5MDFiOGUyM2M2ZTY2ZTY4NjZjMzE5MzFmNWQiLCJkNWRiNGRkNDhmZTQ2YWZkOGFmOGYxZjdjZmJkZWU2MTY0MGJiYmNjIiwiMzlkMTFjYjFkNmRhOGY2NDZmNTg0ZWVhMTg0MTMzYTAzZDg1YTJjYyIsIjU1NDY0ZDViZWE4NGU3MDczMDc0YjIxZDEyMDQ5MzQzNThjN2RiNGQiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiZjRiNjRhNjhjMzM0ZTkwMWI4ZTIzYzZlNjZlNjg2NmMzMTkzMWY1ZCIsImQ1ZGI0ZGQ0OGZlNDZhZmQ4YWY4ZjFmN2NmYmRlZTYxNjQwYmJiY2MiLCIzOWQxMWNiMWQ2ZGE4ZjY0NmY1ODRlZWExODQxMzNhMDNkODVhMmNjIiwiNTU0NjRkNWJlYTg0ZTcwNzMwNzRiMjFkMTIwNDkzNDM1OGM3ZGI0ZCJdLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gZVBhc3MgRklETy1ORkMgU2VjdXJpdHkgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQmZqQ0NBU1dnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBWE1SVXdFd1lEVlFRRERBeEdWQ0JHU1VSUElEQXlNREF3SUJjTk1UWXdOVEF4TURBd01EQXdXaGdQTWpBMU1EQTFNREV3TURBd01EQmFNQmN4RlRBVEJnTlZCQU1NREVaVUlFWkpSRThnTURJd01EQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOQm1yUnFWT3h6dFRKVk4xOXZ0ZHFjTDd0S1Flb2wybm5NMi95WWd2a3NabnI1MFNLYlZnSUVrekhRVk91ODBMVkVFM2xWaGVPMUhqZ2d4QWxUNm80V2pZREJlTUIwR0ExVWREZ1FXQkJSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QWZCZ05WSFNNRUdEQVdnQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBTUJnTlZIUk1FQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQkJqQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQXdmUHFnSVdJVUIrUUJCYVZHc2RIeTBzNVJNeGxrenBTWC96U3lUWm1VcFFJZ0Iyd0o2blpSTThvWC9uQTQzUmg2U0pvdk0yWHdDQ0gvLytMaXJCQWJCME09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUZBQUFBQVVDQU1BQUFBdEJrcmxBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQkhacFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1Tmkxak1ERTBJRGM1TGpFMU5qYzVOeXdnTWpBeE5DOHdPQzh5TUMwd09UbzFNem93TWlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwa1l6MGlhSFIwY0RvdkwzQjFjbXd1YjNKbkwyUmpMMlZzWlcxbGJuUnpMekV1TVM4aUlIaHRiRzV6T25Cb2IzUnZjMmh2Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOXdhRzkwYjNOb2IzQXZNUzR3THlJZ2VHMXNibk02ZUcxd1RVMDlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl0YlM4aUlIaHRiRzV6T25OMFVtVm1QU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2YzFSNWNHVXZVbVZ6YjNWeVkyVlNaV1lqSWlCNGJYQTZRM0psWVhSdmNsUnZiMnc5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBeU1ERTBJQ2hOWVdOcGJuUnZjMmdwSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE5pMHhNaTB6TUZReE5Eb3pNem93T0Nzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlNHbHpkRzl5ZVQwaU1qQXhOaTB4TWkwek1GUXhOVG96TURveU55c3dPRG93TUNZamVEazc1cGFINUx1MklPYWNxdWFnaCttaW1DMHhJT1czc3VhSmsrVzhnQ1lqZUVFN0lpQjRiWEJOVFRwSmJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qSkZOekZDUmtaRFF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2pKRk56RkNSa1pFUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJajRnUEhodGNFMU5Pa1JsY21sMlpXUkdjbTl0SUhOMFVtVm1PbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWtVM01VSkdSa0ZETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlJSE4wVW1WbU9tUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNa1UzTVVKR1JrSkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUx6NGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NDc3SlhGQUFBQVlGQk1WRVgvLy84RVZxSVhaYXZHMk9vcWNMRzJ6T09rd3QwQlNKdHFsY1hWNHUrYXV0bFdoYnprN1BVQU1ZOUhjcktqdE5icThmZUFsOGFCb3N6ejl2cGRqc0dHcXRGM244dVRzTlNacGM2SnNOVDUrdjB4WUtudThQZmY1L0w0OGZnL2ZyaWN6SmdZQUFBREFFbEVRVlI0MmtSVUNaYkRJQWpGWFpPWTFUYXROYzM5Ynprc1NZYzNyNE1FNGZNQkFhRDZ6bDh5LzlUT2dldDhkNWpmTjc4YndNL2REQ1JwUjUyMXpYZm9qSEowNUlJeWhCQVVTVkFPTmRHekJZdDJmN0tGcmZrSmFBa0hoOUZaaGNEWEhSa1RLbzlNTGloR2FhdkltblYzcXlFWDBFcHJnei80RHdVRDdrQ0hSbmQ4UUZONDNHbzRVVm1ERGd6YTR3MjdvaXpkQTIrY0srdXVVcGpqbzIreHdjLzQyVzUweDVMR1llREJzUjBIVkl4NXg4aUY2MENibGJURUVrRnIyN2JOREJVVlNxMU9LVlBiRTYyYjNFSDhGcUJnNU9PT0V1YzJ0OFpKaXFNT3VHcCtjS2pnN3dWR2Nlb3pxTjRweGdWUFFrakZZZ2JWSktEVWhEQ2pZcmF3UDVxNEVUZ0M5ZklNUkh0aXRwUWNDdkpPRUxjYk1zUWduY2lSa2xqcHlRanZHNDRqcUJVRVRGaUJpMVBFSXlla096c1crVHk1Y0xIb3M1UitkTVMxTHRTU3hmM2dRSGN6UjJDSTRnTU5wVzRJUkExUU1hNnRKNCtDNnVIdUdFOG1OREl5RnFnL09QL01NVXVlUzZJcThTOTBkQWVCSlNFeS9xS2tLK0JOd3o4Y1lZNGpiNUo2dTRpV0NJMkIxWjU2TFc1a0VjNGhrZE1wc3ZVQzU1ODVTWDBRdWJjZ05xeWZnREZFY1R0KzQwLzBTNU54MHdhQ3czT0trY09iQTVJbjBBWXAwMXBqancybjYyNlVEanRId2EyOGlIdVRLcXRydityZVc0MU5aNmlHbHI3dXVMSkNma0Z0Y3RjRzA0c2dtMWVOUytaYURucGFURXJHb3lYNUpLMmlNejh4czBuT3dXR2NQRE40OXFhQ2Q0YnpKb3pEWm0vYUJLK0Vvekx3K1hoTkJpWXdIZjBzaU91MVhQa0cvekt3dnFZS2NmU3dERWNIL29VZTA3ZXMvV1E4ckl5ZzJET1hqOHRqa1pkdURCL2I4aHpEbGxNTU9DUzVCRW5kNTM0Zjh0aTNVWmM0a01zM3hMeWFmTVNzSmhkRzhYUHFqTms1dEFnTzI1ZmVLQ2huVmREai9KMEZNa09zVS94TUJ2MHdGaFllRUdmVkgxM2Z1RFUweURGTGE0ZmM3Um5XSEJmdVRGVjJ0RW1Od2FkYzdhYzNVWTJqZkJsN0hUMzZmZTM0aVFPNW1OQ0ZGQlcwN0tqUGdxaE9MVTAxdlo4UHVlWjJKQ2xGWk44amtVczY5dWthOWVQcDYrRWZMNEFGNStOeXdTYmlySHRjQjhNbC9na3dBRWprSzY0S2pIUGVBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTEtMTkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkZlaXRpYW4gZVBhc3MgRklETy1ORkMgU2VjdXJpdHkgS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAxNTEyMjEwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMC4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMSJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0xMS0wOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRmVpdGlhbiBlUGFzcyBGSURPLU5GQyBTZWN1cml0eSBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDE1MTIyMTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4xIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0xMS0xOSJ9LHsiYWFndWlkIjoiMjc3MmNlOTMtZWI0Yi00MDkwLThiNzMtMzMwZjQ4NDc3ZDczIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyNzcyY2U5My1lYjRiLTQwOTAtOGI3My0zMzBmNDg0NzdkNzMiLCJkZXNjcmlwdGlvbiI6IlNlY3VyaXR5IEtleSBORkMgYnkgWXViaWNvIC0gRW50ZXJwcmlzZSBFZGl0aW9uIFByZXZpZXciLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI5NDcyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AzODRyMV9lY2RzYV9zaGEzODRfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlES2pDQ0FoS2dBd0lCQWdJVWVmK1Z2SGtjVFFuRUQrK3dKTS9JeHpTVUxrMHdEUVlKS29aSWh2Y05BUUVMQlFBd0pqRWtNQ0lHQTFVRUF3d2JXWFZpYVdOdklESXdNak1nUmtsRVR5QlFjbVYyYVdWM0lFTkJNQjRYRFRJek1Ea3lOVEV4TXpJME1Wb1hEVEkwTVRJek1URXhNekkwTVZvd0pqRWtNQ0lHQTFVRUF3d2JXWFZpYVdOdklESXdNak1nUmtsRVR5QlFjbVYyYVdWM0lFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW91Rk1UT0thRTBZdGV4T29pc1N4cCtFYmk1SUE0ZXNFU2N4MTZselFkcVY2L2VaODJLdEplTlhFdU5rQlZaRHBjMzJnU3R1eExCSDhtZ3NvSEJGYWkyRGtqZkJuNXFid1IvYzUrc25sd1p2amdWQTBoekt3OUN3QWVBd1JENWtyV3Q4OC9DVnlDa01jZ0xTR3dacy9yajdGL0xzM0ViZzdNcUxiYlFKOUNvemJiTGRKVVlJSGNQcFNaUHRvTXJaYjRHdm5pNmlWUzlVdkNLZ3BxYzZMR1Jtb1lHRzRaUjNsR0ovWFFaZnUrR2VKVzY3aWltTWoveW9YT3d4dWN4aXZaSEZrNmNRU2d3dXdpb2VObTR3dms4M0xoU3VXY3RmMmtBeVFjWjdrVW5wTmVlK2Q0TWdybUdVNFhNRkxpVGd1dGFCK2U5VjhkNUpUa1VPSGlMenRrUUlEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVTTVTQjViSHJWK2pwSU9NZEpsN3U3YmNuVFk4d0h3WURWUjBqQkJnd0ZvQVVNNVNCNWJIclYranBJT01kSmw3dTdiY25UWTh3REFZRFZSMFRCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFDb3dSM0tUTGZpZEp5UUZOcUVGZlVyZlo5YWE5ZWdwT1F0TlJKZExTdEo2eHUyV2ZMd3ZHNG9qR0psQktObmZhNURJY3lRWWYvOHFKNGVsaUFWZU5YdVltZU1tZ05nWlp5dVk2RzF5V0NEMlYzc0Q2WjR1ajNTYmFET0hqM2dIdnN6Z1FocmhUMWgvcHVIUWtuNitoWUtBcDc3a003SWM2QVovUkZianBtTExrMkQwc0UxbHpULzAyaStCaDdNOHNtYWlEWjkrK0pHenhlU3VuOFcxSGxlWlVtMnFLR21SYTRYUGRyeVQ3eDZLR1VHblU0YTNicFVtVmVZOXJRL3NmTWQ1WlRvbyszdW5GV0R6b1ZWMnZOdTgrK1ZMQzl6bzQwRmFLUUxyOVZBSkRKNHlMRU5SN0tybVY4TDBjQ1hLSkdaV0FXdEc1UkdUbUhJaGQrbkI0MWc9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsImNyZWRCbG9iIiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjI3NzJjZTkzZWI0YjQwOTA4YjczMzMwZjQ4NDc3ZDczIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwibGFyZ2VCbG9icyI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlLCJzZXRNaW5QSU5MZW5ndGgiOnRydWUsIm1ha2VDcmVkVXZOb3RScWQiOnRydWUsImFsd2F5c1V2IjpmYWxzZX0sIm1heE1zZ1NpemUiOjEyODAsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsibmZjIiwidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0zNX1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjQwOTYsIm1pblBJTkxlbmd0aCI6NiwiZmlybXdhcmVWZXJzaW9uIjozMjk0NzIsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsInJlbWFpbmluZ0Rpc2NvdmVyYWJsZUNyZWRlbnRpYWxzIjoxMDB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDQtMDcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTA0LTA3In0seyJhYWd1aWQiOiI1NjI2YmVkNC1lNzU2LTQzMGItYTdmZi1jYTc4YzhiMTI3MzgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjU2MjZiZWQ0LWU3NTYtNDMwYi1hN2ZmLWNhNzhjOGIxMjczOCIsImRlc2NyaXB0aW9uIjoiVkFMTUlETyBQUk8gRklETyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjEyLCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwiYmx1ZXRvb3RoIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDS0RDQ0FjK2dBd0lCQWdJVUFVMzFXK0h6ZTI1OVhwR3RmaHFqczJTQUtEWXdDZ1lJS29aSXpqMEVBd0l3YWpFTE1Ba0dBMVVFQmhNQ1JsSXhFREFPQmdOVkJBb01CMVpCVEUxSlJFOHhMekF0QmdOVkJBc01KbEJ5YjJacFpHOGdRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJpQlNiMjkwTVJnd0ZnWURWUVFEREE5M2QzY3VkbUZzYldsa2J5NWpiMjB3SGhjTk1qTXdOakl5TVRJeE5UQXpXaGNOTWpneE1qRXlNVEl4TlRBeldqQnFNUXN3Q1FZRFZRUUdFd0pHVWpFUU1BNEdBMVVFQ2d3SFZrRk1UVWxFVHpFdk1DMEdBMVVFQ3d3bVVISnZabWxrYnlCQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1SUZKdmIzUXhHREFXQmdOVkJBTU1EM2QzZHk1MllXeHRhV1J2TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJLN1cweC9UMGVKZWE2ZW1DMVJGU2s3eGJyV1JVd0RlQ09CNFVuRE1xaVlET2JJbVI0R2V0MXE1clhaYWlyRDNRdW9XNTFIZ1BmUjlxaHdlMVdFa0gyYWpVekJSTUIwR0ExVWREZ1FXQkJRK0gxR3l5c0JyRWljYXMyT0xXNWhpT1FNU0V6QWZCZ05WSFNNRUdEQVdnQlErSDFHeXlzQnJFaWNhczJPTFc1aGlPUU1TRXpBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUdHSXdQSEpxbFdXcU92RkxvY2YxUGQ2V0tiZHZCSWVuMkl2ZWQ1QTYxQXdBaUJDajJwZS81Y1hxUWJSajF0cXBRZGttaWlpY3B2OENPc29hbnVZZTJteURnPT0iLCJNSUlDSHpDQ0FjU2dBd0lCQWdJVVBUUWFURzZlT3dVVS9NV3ZuK1RKSUhNM2JIb3dDZ1lJS29aSXpqMEVBd0l3YWpFTE1Ba0dBMVVFQmhNQ1JsSXhFREFPQmdOVkJBb01CMVpCVEUxSlJFOHhMekF0QmdOVkJBc01KbEJ5YjJacFpHOGdRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJpQlNiMjkwTVJnd0ZnWURWUVFEREE5M2QzY3VkbUZzYldsa2J5NWpiMjB3SGhjTk1qTXdOakl5TVRJeE5UQXpXaGNOTWpneE1qRXlNVEl4TlRBeldqQmxNUXN3Q1FZRFZRUUdFd0pHVWpFUU1BNEdBMVVFQ2d3SFZrRk1UVWxFVHpFcU1DZ0dBMVVFQ3d3aFVISnZabWxrYnlCQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVJnd0ZnWURWUVFEREE5M2QzY3VkbUZzYldsa2J5NWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFtTm1sb1N3TFREU2NKYTREd1Y3czJ0WDBCOFZXVVlxWitoNmZnWFh6MjRhUE1pcmZHV1YycEJqZXBSemUzRFkvZWlGTXpuYmV1SElaRERYWTJsanN2bzAwd1N6QUpCZ05WSFJNRUFqQUFNQjBHQTFVZERnUVdCQlRlTUFjM2FUZ1l6dVdKK21MYXByeEVGTFhYUERBZkJnTlZIU01FR0RBV2dCUStIMUd5eXNCckVpY2FzMk9MVzVoaU9RTVNFekFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBL2FIY3V6bStFSGp5YkxoMURZbGZCWnF6dzdNeVNKNzVpam9LVFJIU096QUNJUUQ2bm9WbFdVTEQ5eGhhTlMvelVuSlhIYzkwRmpKZ2FhK05aQXc5V1JRY1hnPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTFFBQUFDMENBWUFBQUE5elFZeUFBQUFDWEJJV1hNQUFBN0RBQUFPd3dISGI2aGtBQUFBR1hSRldIUlRiMlowZDJGeVpRQjNkM2N1YVc1cmMyTmhjR1V1YjNKbm0rNDhHZ0FBRVVwSlJFRlVlSnp0bmNsekZGZWV4NytaV1d1bUZoQWd3T3lJVlNDMG1HazMzVjZ3M1Y2UWdabUo2SWk1ZEVSM2ROOTdUblBwNklubzJ4eG1KbWJtMW4vQTNEb21vczFpNHcwODdRV0hzUmFNaE5nc0pDT1FoVmdrVUdZdFdaVTVoMEpqbVZZcFM5SzNLak5mdnM4RmJJVytXYWkrZXZYZTcvMFc1ZHZmSDNRaGtRaUM2dmNMa0VpWVNFTkxoRUlhV2lJVTB0QVNvWkNHbGdpRk5MUkVLS1NoSlVJaERTMFJDbWxvaVZCSVEwdUVRaHBhSWhUUzBCS2hrSWFXQ0lVMHRFUW9wS0VsUWlFTkxSRUthV2lKVUVoRFM0UkNHbG9pRkxGYVBFVFI0bmptbjA1RE5WWlM5QXIzUmpIK1h6K25hRW5tcC9uWGYwUnkyN01VTGNlYXhwMS83WVpieUZQMEZxSW1LN1JidEdGZVBFUFRpNjNlZ3NUR2ZUUTl5UStKclZpUDVOWk9tcDdaZjdvbVpnWnF1T1V3ZTkrbTZobWRSNmw2a3U4eHVvNEJDczhhWnQ4cG1wWVhOVE8wUGZFTjhyZUhhSHI2Z1RlaHhKTTBQY2tURkFWNlJ6ZE5Mbjk3Q1BaMzEybDZYdFQwVUdqMm5xQnBxYWs2cFBlOFNOT1RsRWh1ZlJheGxSdG9lc3ozdkJKcWFtanI2ek53N1J4TnorZzhSdE9TbERDNmVGczV0NUNIZGVsOW1sNGwxTlRRVG5ZR21hR1BhWHFwSGM5QmExeEwwNHM2U2tLSDN2b3lUUzl6K1J5Y3pDT2FYaVhVUEE1dDlwN2tpU2txalBZalBMMklvN2U5QmlXaDAvU283M1dGMU56UTJlRUxLRXlOMC9TTXptT0FvdEQwb2d3emNsUjhkQmZabXhkb2VwVlMrNXRDMTRIVmQ1b21GMXU5R1ltTisybDZVU1hXdEFuSnplMDBQYlBuQk9BNE5MMUs4ZVhxMit3OUFiaThmNnpSSlErSHk4WG9Pc3I3cEhOZG1QMjhSV3N4K0dMb3d0UTRzamQ3YUhwNjIrdFE0aW1hWHVSUVZCakUySE51cEFlRkIyTTB2Y1hnVzNJUzg4Q2dKZzJrOXg2bTZVV04xUGEvZ2RhNGpxYm54MkZ3RnQ4TW5ibDhGazcyTVUyUEdUK05Hc3lmblpNellRMmVwZWt0RnQ4TTdkbzVXSmMrb09teFY1bW9vS2JxcUo5dW1Vc2Z3TFd6TkwzRjRtcytORDBtVGR3SFJnWDIrV09teGxmZFQrT3JvZk5qQTdBbmJ0RDBqRTdpU1QwaU1HUFBoWHVqeUk4TjBQU1dndThWSzh6d1Rtd1ZONVlxT3V3WS9relAyNERyN3d3cS93M2Q5dzdjWW9HbVozUytSZE1TSGFQck9POFR6U25DdXZndVIyc1orRzVveDN5QTdMVlBhWHA2Mit2VWZBUmhVYmw1TUpscm42UDQrQjVOYjZuNGJtaUFlemdzWll3ZHB1bUpTbXJISVdnTnpUUTlzOC9mdytBc2dUQjA1dHBuMU45dVhaWm5lY0k4RERyV05MSlhQNlBwTFlkQUdKcTkvMHB0TzBpdHVoQU5OZDFBcmZZeCswN0JMZG8wdmVVUURFT0RmRUpXRk9nZE1rKzZIUHFCTjZERUVqUTl2eEtSNWlNd2htYkhNR1dlZEhtWXBXdjUyNWRyV2dUclJXQU1EWEFQaDdHVnp5QzVwWU9tSndyeDV1MUliTmhMMC9NekVXaytBbVZvNjlMNzFEd0FXVVQ3MXpCengvMG9ndlVpVUlZdVpXcDlSTlBUOS85TXhxVG5vbXJRbWJIbnkyZHJYZ1RyUmFBTURiQmowbW5vKzE2aDZZV2Q5SzZmUXF0YlJkTUwybllEQ0tDaGN5TzkxR29IMlRMc2U1aGJzRklSN0ZjMFBSYUJNelJjRnlheGlEYTV0UXV4cG8wMHZiQ2k2bzFJN2ZvSlRjK3ZJbGd2Z21kb1BDbWlaZjJ3RkVYbVNRTXdPcnA1c1djZmkyQzlDS1NoaTQvdUlqdjhKVTFQN3p4SzdhWVpSb3dPM3RZcmUvTXIzNHBndlFqc3UweU5TYTlZaitUV0xwcGUyRWlzMzQzNCtsMDB2U0FlQm1jSnJLRXpsOC9Cc2Fab2VsRXVvbVVtYXprNUU1bkw1Mmg2YkFKcmFMZG9VNHRvOWRaWG9DU2pGNU5XdERpTUEyL1E5TmlYWDJ3Q2EyaWdHakhwbjlIMHdrSnE5L08wMlRaQXNMY2JRTUFObmI4ekJIdjhHazB2aXRzT1p1eTVjRzhVK1Z1WGFIclZJTkNHQmdDemo3Y2lKRGQzSU5hMGlhWVhkTFM2SnFSMkhxTHB6ZlJ3NStSVWcrQWIrdUs3dkFsS2lnS2pNem94YWIyakc0cEdtdHdYa0NKWUx3SnZhTWVhUnVicUp6UTlvK3M0b0FiK24wM0JhT2Y5OHJMTDVLcEZLTjVaNWtGRWEyaEdhdHRCbWw1UVNXeG9SWHpkVHBwZTBBK0RzNFRDME5ucjUxR2NucURwUlNGaGlabjNYQ1MzbXFnbW9UQTBYQWNtY2YrV2JuMEZhcXFlcGhjMEZDME9mZjlyTkQycm45c01xSnFFdzlDWTdmclBLYUpWNGttazk3OUswUW9pNmRiRFVQVkdtcDdaL3c1TnE5cUV4dENGKzdlUSs3YWZwaWZ5dG9OYUJEczJHS2dpV0M5Q1kyaUFlekJKYm01SGZNMVdtbDVRME9yWElOWHlIRTB2TElmQldVSmxhR3ZnUTdnNWk2YW5FOE5hUWNIb2ZJc1dsZ3hpRWF3WG9USzBtOC9BR3Z5UXBtZDBIaFV1SnExMzhMcXZaZ2E1WTBOcVFlamVUVzVNZWcxUzIzOUUwL09ieEtZMjZqYXExb1BuR1lUTzBMblJmdGlUSXpROWtRNkh6Tmd6ZS9SZXJRaWRvUUhBSXRhenBWdGZGaUltcmNTVDBQZnowbU90dmxQVTRhaTFJcFNHTm50UEFrNlJvcVhFRXREYmVKY1Fma0g5eFhUZFVNV2U1eEpLUXhkbjdpTnovVHhOVDRSdEJ6UDJIT1FpV0M5Q2FXaUFteWRkT2t4dG8rblZHbmJDVmRoaXozTUpyYUd6Vno2Qll6Nms2ZWtoSGpaa2RCMmpoUitkN0V5Z2kyQzlDSzJoM2FJTjgrSVptcDdSMFIzT21MU2lVQ2QvQmIwSTFvc1F2b1BmWS9ieVNvSktWOFkvcHVuVkNuWlpXWmkzRzBESURXMVBmSVA4blNHYUhqT09XeXVvc2VjQVRJSmRMcUUyTk1CZFVkSjdYNkttWFZhYlVtc0dYaHJzVE0rZmFWcCtFWHBEV3hmZmhXdm5LRnJzeFBocW8rOTdsZGM4eHluQzZnOStFYXdYb1RlMGs1MUJadWhqbWw2WXRoM00rSG5tNnFjb3p0eW42ZmxGNkEwTmNMY2RpUTJ0aUsvZFFkT3JGcVVHbEowMFBXWmMzMCtFTUhSMitBSUtVK00wdlREMGt6YTZqdEZhQkplS1lJTXhDWGE1Q0dGb3VBNHNZdGQvdmVNdFhvT1dhcUFvMEltL2RGWmZlSXBndlJERDBKZ3RvdVZraDJsMVRVanRDRzVNbWozNk9hamQrSmVDTUlZdVRJMGpOOUpMMDJQMlZHYkRmRzM1c1FIWUV6ZG9lbjRqaktFQmNreDZ6NHRROVJVMFBSWktRb2ZlZXBpbUYvYWJ3YWNSeXREVzRFZTBHamhGaTBOdmU1Mml4VVJ2ZTQwMlROUzFjOVNtOGtGQUtFT3ozNkFnOXBPbXhwNHZud3RkRWF3WFFoa2FJTWVrbjlsTGJYaTRYR0tyTmlHNXVaMm1GOFlpV0MrRU16VDdrR01RMndJc0Y2UHpLS0FvRksyd0ZzRjZJWnloQVc0WVN1ODRFb3lZdEtKU0wzek0zcE9oTElMMVFreERFeThLTktNSnFaMjhrY0pMSmRYeUkyaU42emhpcmdzcnBFV3dYZ2hwYUlkOGxjc3NRRjM2YXlCUGduMTRtNllYSklRME5NQk50bUdQUmxzc2Fxb082YjB2MGZSRVBBek9JcXloTTFjL3BjMEVVYlFZZFhqbFl0SGIzb0FTVDFHMFNrV3dIMU8wZ29pd2hpNU5iU0lXMFQ3N3R6U3RSVCtiR0ErM0xyMFg2aUpZTDhRMU5MZ2xSZkcxTzZnRDRDc2x0bm96RWh2MzAvUkV1K3ArR3FFTnpaNThhblRVL3Vhd3JvdjN5V0RmSFVaK2JKQ21GMFNFTmpUQVhaR01qbTRvc1FSTnp4TlZoZDV4aENZbit1b01STURRek1ZcHF0NkkxSzdheGFSVE93NUJxMS9ERVF2SkpOamxJcnloblp3SmEvQXNUYStXMnc1dUVld25RaFRCZWlHOG9RRnludlR1NTZIVnJhTHBsVU5OTnlDOTUwV2FYaFMyRzBCRURKMGI2ZUcxaDFVMTZPMXZjclFXUUQvd0ptMi9YcHg1Z096MXp5bGFRU2NTaG9icndpUVcwZGJpS3B3YWUrNC9MVXdSckJmUk1EU2VYUGM2bk95eStOb1dKSjdaUTlFcXI3K1hwaWRLejQxS2lJeWhpNC91SWp2OEpVMnZtbDMvcVpOZ2IxMkNmZmNtVFMvb1JNYlFBUGRncExjZnFVNU1tcnhIajhwaGNKWklHVG96OURFY2E1cWlwYVlia05yOVBFVnJMc3dvaW12bllBM3dCcFdHZ1VnWm1qM3F0eHJiRG00UmJQZ213UzZYU0JrYUlNZWtkLzRFV3YxcW1sN3BKdktuTkwyb2JUZUFDQm82ZjJjSTluZlhPV0xrL2E3UjBRMUZpMU8wUkMyQzlTSnloZ2E0WVN5ajh6aFJpeGZkRUxVSTFvdG9HcnIvSGJpRlBFVXIzcndOaVEydHk5WkpyTi9ONndFaWNCR3NGNUUwdEdOTkkzUDFFNW9lbytzL3N3RmpkdmlDc0VXd1hrVFMwQUE1Sm4zZ1RTang1SksvWDlIaTFKckZLQjRHWjRtc29iTTN6cU00UFVIUlVsTjFTTzkrWWNuZm45cnpBcTJxbkQxekpteEUxdEJ3SEpqRWhQZmxIT2lZc1dmcjZ6TkNGOEY2RVYxRFk3YnJ2MHZSU3UzOE1iU0c1a1YvWDJsYXdDSEthd0NpdmQwQUltN293djFieUgxN2tTT21xRERhRjEvL3AzZDAwM3JuMlhlSGtiOTltYUlWVmlKdGFJQmNSTnQxZk5IZFFabmRUVVh1aUZRcGtUZTBOZkFCM0p4RjBWcHNENDNFeG4yOG1Zamt4anBoSmZLR2R2TVpXSU84akRTanMvSVZsNXFJZENVYVJiQmVSTjdRQURrbVhXRWZPaVdXb001d01mdmtkZ09RaGdZQTVFYjdZVStPVUxRcTdSU2EzdnNTMUhRRDVabWxJdGp6Rksyd0l3MzlCSXZZOWIrU2JRY3pFU2xLUmJCZVNFTS93ZXc3VFN1aVRiVThCNjF4YmRtdmF3MXJrR3A1anZJc0lGcEZzRjVJUXoraCtIZ1MyUnVrajIyUGVTaEd4MXVBeXZuUlI2MEkxZ3RwNkRsUVk5S2R4OHJHcEhWaTdIbEd4cDUvZ0RUMEhESlgvZ0xIZkVqUmlxM2FoT1NtdHIvNi84bk5CeEJmczVYeUROZk9JVFB3RVVWTEZLU2g1K0FXYlpoZnYwZlRtKy9nUnowTUVrZEJpNEkwOUZPWVBXL1R0Tkp0ci8wZ0pxM0VrMGp2ZjVXbUgvVkVwUG1RaG40S2UrSUc4bmVHS0ZwcTBrQzY5ZkQvLzNlNjlXV29xWHFLZG1GcUhMbVJYb3FXU0VoRHp3UDljRGpQMzVkTEtmVTFla1d3WGtoRHo0TjE4VjI0ZG82aWxkcCtFRnJqT21nTnpVaHRPMGpSaE92QUluWlRGWWtBRExFT0hrNTJCcGtyLzh2SnRWRFVKemVIQ2kzMm5CMitnTUxVT0VWTE5LU2h5MkQybktBbEQ1V3k2amlWTVlBOERDNkVOSFFaWmxmQjJJcjF5OWFLTlcwa3ZLSVNVUytDOVVMdW9jdmhPdFNFSlJhbElsak8vbDVFcEtFWElJanR0R1NaMWNMSUxjY0NGQjdlUVc2a0YwbFdkR0taMkJQZklIK2JFeU9majBlMmlnZTUrZk5QNnVNdVZpWG4vK1YrbUZjd25WOTRiVXhxTG1LS0N6MEd4RlVYaVNvdHBkTFFIcGk5SndOajZHcXZ6bDlNYXZqdjRmazdRTDJ5M3Nhdld1YmY2cngvSjQ3VFk0dWJaaEJYZ2RWSkIrdlNEbmJVRjNGZ1pSRmI2cGIvYVNpM0hCNEVKbC9DS2NJaTVwbjRqZTBBNHhrVmZROWkrTk5vRXYvY3IrTjN2VG8rbjR6QldVWkFTQnJhZzZDTWRjaGMrWXZ3UmJCamxvby9YazNoWHdiU3VKZGRYRHVJV2FTaEt5QUljZDhvSFFhdlRtdjR3MFVkbzZhMjZPK1ZocTRBdjZ0Q2lqTVBrTDN4aFcvUDk0Tkh0b0ovRzB6aGZwbERham5rb2JCQ3pMNlRXUEhHYjMxNXR0VjNLclJGc01jMzVYRmtndzBBeUJVQnE2amdibGJGOVVjYXprL0d5a1pWQUdBNnIrQS9oOUw0UTNzR21sTFp4bHF1MEJYaVoyVzEyWGZLbCtjeWlLdUFFWE5oeEZ3MEpWMXMxQjEwTlJYd0QxdHorUGVESm43Wmtsc3doRGM2bytMY2Q1V3Z1OUxRRlZLY2VZRHN0YzlxL3R6OHJVdXdKOFVzZ3RVVTROWDFObjdYWmlHaGxsK0JUOXhLSUY5aFJFOGFlaEg0MFM0Z0NrV3cyK3NkL0dKNytaazNVM2tGQTFPVnJkTFMwSXNnYy9YVG1vYk9vbFFFKzhKYUc4MnA4c3Z3d01QS0loN1MwSXZCS2NMcTUzWDk5OElhL0RBWWx6bzFRRk9BZzZ1S1piOStaVm9hdWlyTTlQeTVaczhLUXZ5N2x1eG9LSC9vZnBpdkxId25EYjFJQ3ZkR2tSOGJxUDV6bmlSR1JZbkdlUG1Eb1ZWUVVLd2djaWNOdlFScXNYS1dVbGQ1VlM1aElCVXJ2d3E3QUd6SGU1V1dobDRDMXRmdlZYZlNsT3VFT3ZhOFZCNHZNTnhYVTBvcHFGNUlReThCSjJmQ0dqeGJOZjNzTjEraU9QMWQxZlNEeWtMWDNIVnhGNVhzb3FXaGwwZzF0eDFST3d6T2N1VlIrVmh6YzBwZWZWZVYzRWdQQ2cvRzZMcXpMUlNpaGxWUTBITy9mR2h1MzRySzBnNWtjdEpTY1YyTS84ZmYrLzBxaE9GUG93bFloZktiaW4wcnlzZW81eUpYYUludm5MbVR3RWZqOGJKZjMxTG5ZRmREWllhV0s3VEVOMjViS3Y1bk5JR3Y3aTlzdzU5dnlWZDBJQVNrb1NWVjVyYWw0c3Q3SlpzVlhjQXNLSmpJcUxqK1dNUE54NnBuUDZsRGEyeTByNnc4YlZjYVdsSlZ2cGlNNFl2SnBkbHNXNTJEMyt4Y0lEZzlEOUxRa2tDeXU3R0lmOXliWFRCUGVqNmtvU1dCUWxPQW94dnorTHZOZHNWbFYzT1JocFlFQWlQbTR0Q2FBcm8zNUxHNndrdVUrWkNHbGxTZGhPb2lyZ0o2clBSblFuVlJGeTkxVGxxZmR0RlNYMFJMdmJPa0ZmbHBsRzkvZnpCYUtWMFNvWkVYS3hLaGtJYVdDSVUwdEVRb3BLRWxRaUVOTFJFS2FXaUpVRWhEUzRSQ0dsb2lGTkxRRXFHUWhwWUl4ZjhCZlN3WGQ1UFZTVllBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjU2MjZiZWQ0ZTc1NjQzMGJhN2ZmY2E3OGM4YjEyNzM4Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInBpblV2QXV0aFRva2VuIjp0cnVlLCJiaW9FbnJvbGwiOmZhbHNlLCJ1dkJpb0Vucm9sbCI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjIwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJibGUiXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA4LTIzIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJWQUxNSURPIFBSTyBGSURPIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzA4MjMwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wOC0yMyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDItMTQifSx7ImFhZ3VpZCI6Ijk1ZTRkNThjLTA1NmUtNGE2NS04NjZkLWY1YTY5NjU5ZTg4MCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiOTVlNGQ1OGMtMDU2ZS00YTY1LTg2NmQtZjVhNjk2NTllODgwIiwiZGVzY3JpcHRpb24iOiJUcnVVIFdpbmRvd3MgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsic29mdHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsic29mdHdhcmUiXSwiY3J5cHRvU3RyZW5ndGgiOjI1NiwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNTekNDQWZLZ0F3SUJBZ0lVVzNYSzh5eXdiQVdsaWdsaXhJRjYzZHZxWXk4d0NnWUlLb1pJemowRUF3SXdmREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFnTUNFTnZiRzl5WVdSdk1ROHdEUVlEVlFRSERBWkVaVzUyWlhJeEV6QVJCZ05WQkFvTUNsUnlkVlVzSUVsdVl5NHhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhFREFPQmdOVkJBTU1CM1J5ZFhVdVlXa3dJQmNOTWpNeE1UQXpNakF6TmpVeFdoZ1BNakExTXpFd01qWXlNRE0yTlRGYU1Id3hDekFKQmdOVkJBWVRBbFZUTVJFd0R3WURWUVFJREFoRGIyeHZjbUZrYnpFUE1BMEdBMVVFQnd3R1JHVnVkbVZ5TVJNd0VRWURWUVFLREFwVWNuVlZMQ0JKYm1NdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SQXdEZ1lEVlFRRERBZDBjblYxTG1GcE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRU5BdmJ0Y2NNcjdqL1NSV21xSUVaVFJXTkp5ajZtc1lyNWxHZUFnZFNHeUM5TzAzNTZSSWVjdWFWaU9xejBEeGdTMWYvNUtQYlpwMXQweUQyZlZSWDk2TlFNRTR3SFFZRFZSME9CQllFRkE1dEwxMGc4OHQycVhsUGxoSVNJMmRJemxhVk1COEdBMVVkSXdRWU1CYUFGQTV0TDEwZzg4dDJxWGxQbGhJU0kyZEl6bGFWTUF3R0ExVWRFd0VCL3dRQ01BQXdDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdYZnV2anNwKzR2NWlHT3FuZ1VnT2cxaG1iZ0ZQRk1nSWp5V3hDS3F3L2Q4Q0lGaW1MTlhMREl3QStvSWJQMXlPZnFFOHhrNnE3LzRMV09WWWtSQUxvQkMyIiwiTUlJQ2VEQ0NBaDJnQXdJQkFnSVVlaGRWakpKSkV5SzNDQUVTSFUzNVRHWSs3aVl3Q2dZSUtvWkl6ajBFQXdJd2dZOHhDekFKQmdOVkJBWVRBbFZUTVJFd0R3WURWUVFJREFoRGIyeHZjbUZrYnpFUE1BMEdBMVVFQnd3R1JHVnVkbVZ5TVJNd0VRWURWUVFLREFwVWNuVlZMQ0JKYm1NdU1SZ3dGZ1lEVlFRTERBOUZiblJsY25CeWFYTmxJRUYxZEdneEVEQU9CZ05WQkFNTUIzUnlkWFV1WVdreEd6QVpCZ2txaGtpRzl3MEJDUUVXREdsdVptOUFkSEoxZFM1aGFUQWdGdzB5TXpFeE1ESXhNelUzTkRCYUdBOHlNRFV6TVRBeU5URXpOVGMwTUZvd2dZOHhDekFKQmdOVkJBWVRBbFZUTVJFd0R3WURWUVFJREFoRGIyeHZjbUZrYnpFUE1BMEdBMVVFQnd3R1JHVnVkbVZ5TVJNd0VRWURWUVFLREFwVWNuVlZMQ0JKYm1NdU1SZ3dGZ1lEVlFRTERBOUZiblJsY25CeWFYTmxJRUYxZEdneEVEQU9CZ05WQkFNTUIzUnlkWFV1WVdreEd6QVpCZ2txaGtpRzl3MEJDUUVXREdsdVptOUFkSEoxZFM1aGFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJCcnZ0YW5seFhySmtTMlFWL0NIZHp1YnBDbS9xOE8weTZzMEc1RUMzRXlDL2ZBdlU4eUk0NytYdlpxT3ZyaVBLK29jUlNMeENhL3BmTW1YQ3ZoUWFvMmpVekJSTUIwR0ExVWREZ1FXQkJUNlQrUmJ1cE9ZUHc4YjJZeHdNL0NxK1diaGtUQWZCZ05WSFNNRUdEQVdnQlQ2VCtSYnVwT1lQdzhiMll4d00vQ3ErV2Joa1RBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDaHl0MlVXQ2krQlpPcjFOalhwZ0c2c3g4S2xFZGtETFhaWTZ4NnZya09hQUloQUowVWZFUDRWNk0vYXFoWGI4RmJ3WEswbWVBY2E4SVZkREpub1NNcEJHd0kiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFCQUFBQUFRQUNBWUFBQUIvSFN1REFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUYwS1NVUkJWSGdCN04xOWpKN2xmU2Y2QzJ6aUFZOWp4dUFaRDJhaFlDZm5uT2lrb0VRNVN1VklTYzdtbEtwTmxRcm5qelJVY2M1cVNWdXpsVFp3Q2xtcE1RMzBhQk96QmExV0hnbzUydFdNTmpRNjBsaU5EcEZLVHJwdFZwbTIyaW9SSk5MWnM0a2RVbUx3dk5nZWcyY2NEeTltbjk5amhoampsM2w1bnVlK3IvdjZmS1JaMDAxS3NabTVuL3Y2WHIrWHl6N3cwVjkvUFFFQUFBQ05kbmtDQUFBQUdrOEFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFWWW00REtmZWFhSTJsWDZ3c0FvRW5tVGwrZXhtYzNwZjJ0ci9ocm9GcVhmZUNqdi81NkFpcTM1WXBYMmtIQWJlOThNUUVBNU82cEZ6ZW1zV1BYcHNsWHJraEFQUWdBb0dhMnIxdElYN3J1VURzUUFBREl6ZE1ucjBwalI2OU56L3o4cWdUVWl3QUFhaW9xQWFJaVFCQUFBT1FnU3Z4SHBvZlNVeTl0VEVBOW1RRUFOUlVmbnBHYy8yb3JDREFmQUFDb0szMytrQThWQUpBQjh3RUFnRHFLY3YrSHBvYjErVU1tQkFDUWtSM3JUNlRkZzlQYUFnQ0FTaDA0MVpkR1pnYjErVU5tdEFCQVJpYm1ONlNKWnplWUR3QUFWQ0pLL0VlUGJrNzdad2NTa0I4QkFHUm9jVDZBdGdBQW9GZWl6eittKyt2emgzeHBBWURNUlJYQTdzM1RhVWYvaVFRQTBHblI1Ly9vekdBNnNOQ1hnTHdKQUtBaHRBVUFBSjBVZy8zMlRnN3I4NGNHRVFCQXcwUUlzSFBnV09xLy9IUUNBRmd1YS8yZ3VRUUEwRURXQmdJQUsvSFVpeHZUeU15UWd6ODBsQUFBR2l5Q2dEKzkvamx0QVFEQVJVV2Zmd3o0VSs0UHpTWUFnQUtZRHdBQW5FLzArY2ZCUHpZTUFjMW5EU0FVSUQ3VUorYjYwKzBEczJsWEt3Z0FBTXFtengvS3BBSUFDbU0rQUFDVUxTNEZvczgvYnYrQnNnZ0FvRkMzWEhreTNidmxzTFlBQUNpRVBuOUFBQUNGTXg4QUFKb3RTdnhIajI1TysyY0hFbEEyTXdDZ2NERWZJRzRDYnI5Nk51MGNPSllBZ09ZWWJkMzQ2L01IRnFrQUFONWtQZ0FBTkVPVSt6ODBOYXpQSDNnTEZRREFtK0lsWWUva2NIcW05ZEtnTFFBQTh2UG1aN2srZitBOFZBQUFGN1R6NnRsMCs4QXhRUUFBMU56aVdyOFk4Z2R3SVNvQWdBc2FQejZRSnViN3RRVUFRSTB0SHZ6MStRT1hvZ0lBV0pLb0F2akRvY1BwMXF0T0pnQ2dldGI2QWNzbEFBQ1d4ZHBBQUtoVzlQbVBUQSsxcS9RQWxrTUFBS3hJaEFDeE5yRC84dE1KQU9pK3hUNS9hLzJBbFJJQUFDdG1iU0FBOU1aVEwyNU1ZOGV1dGRZUFdCVUJBTEJxRVFUODZmWFBhUXNBZ0E3VDV3OTBrZ0FBNkJqekFRQ2dNNkxFUC9yOG4zcHBZd0xvRkdzQWdZNkpsNVNKdWY1MCs4QnMydFVLQWdDQTVkSG5EM1NUQ2dDZ0s4d0hBSURsaVhML2g2YUc5ZmtEWFNNQUFMcHF4L29UYWZmZ3RMWUFBTGlBQTZmNjBzak1vRDUvb091MEFBQmROVEcvSVUwOHU4RjhBQUE0UjVUNGp4N2RuUGJQRGlTQVhoQUFBRDBSOHdIaVprTmJBQUNrZHA5L1RQZlg1dy8wa2hZQW9PZWlDbUQzNXVtMG8vOUVBb0NTUkovL296T0Q2Y0JDWHdMb05RRUFVQmx0QVFDVUlnYjc3WjBjMXVjUFZFb0FBRlJ1c1MxQUVBQkEwMWpyQjlTSkFBQ29CV3NEQVdpYXAxN2NtRVptaGh6OGdkb1FBQUMxRWtIQWw2NDdsTGF2VzBnQWtLUG84NDhCZjhyOWdib1JBQUMxWkQ0QUFMbUpQdjg0K01mbUc0QTZFZ0FBdFJZaHdLN1dGd0RVbFQ1L0lCY0NBS0QyekFjQW9LNG01dnJiZmY1eCt3OVFkd0lBSUJzeEZ5RG1BMmdMQUtCcSt2eUJIQWtBZ095WUR3QkFWYUxFZi9UbzVyUi9kaUFCNUdadEFzaE1ERmVLRzVkZmJRVUI1Z01BMEN1anJSdC9mZjVBemxRQUFGa3pId0NBYm90eS80ZW1odlg1QTlsVEFRQmtMVjdHOWs0T3AyZGFMMmZhQWdEb3BEYy9ZL1Q1QXcyaEFnQm9GUE1CQUZpdHhiVitNZVFQb0VsVUFBQ05zamdmUUZzQUFDdXhlUERYNXc4MGtRb0FvTEdpQ21EMzV1bTBvLzlFQW9DTHNkWVBLSUVBQUdnOGJRRUFYRWowK1k5TUQ2V0orZjRFMEhRQ0FLQVlFUUxzSERpVytpOC9uUUFvMjJLZnY3VitRRWtFQUVCUnJBMEU0S2tYTjZheFk5ZGE2d2NVUndBQUZDbUNnRCs5L2psdEFRQUYwZWNQbEU0QUFCVE5mQUNBNW9zUy8ranpqMDB4QUNXekJoQW9XcndNVHN6MXA5c0hadE91VmhBQVFIUG84d2Q0S3hVQUFHOHdId0NnT2FMYy82R3BZWDMrQUdjUkFBQ2M0NVlyVDZaN3R4eldGZ0NRb1Rqdzc1MGMxdWNQY0I0Q0FJQUxNQjhBSUI5UjRqOTZkSFBhUHp1UUFEZy9Nd0FBTGlEbUE4UU4wdTFYejZhZEE4Y1NBUFVVZmY0eDNWK2ZQOERGcVFBQVdBTHpBUURxSi9yOEg1MFpUQWNXK2hJQWw2WUNBR0FKM3V3cGJiMXNhZ3NBcUpZK2Y0Q1ZVUUVBc0FJN3I1NU50dzhjRXdRQTlKQzFmZ0Nyb3dJQVlBWEdqdytraWZsK2JRRUFQZkxVaXh2VHlNeVFnei9BS3FnQUFGaWxxQUw0MG5XSDB2WjFDd21Bem9vKy94andwOXdmWVBVRUFBQWRZbTBnUU9kRW4zOGMvR01qQ3dDZElRQUE2TEFJQVhhMXZnQllQbjMrQU4wakFBRG9BbXNEQVpZdnl2MGZtaHB1My80RDBIa0NBSUF1aWlEZ1Q2OS9UbHNBd0VYbzh3Zm9EUUVBUUErWUR3RHdkbEhpUDNwMGM5by9PNUFBNkQ1ckFBRjZJSVpZeGMzV3I3YUNBUE1CQUZLN3p6OXUvZlg1QS9TT0NnQ0FIak1mQUNpWlBuK0E2Z2dBQUNxeVkvMkp0SHR3V2xzQVVJUTQ4TytkSE5ibkQxQWhMUUFBRlptWTM1QW1udDFnUGdEUWFJdHIvYUxjSDRCcUNRQUFLclk0SDBCYkFOQTArdndCNmtVTEFFQ05SQlhBN3MzVGFVZi9pUVNRSzJ2OUFPcEpBQUJRUTlvQ2dCeEZuLy9JOUZDYW1POVBBTlNQQUFDZ3hoYmJBZ1FCUUowdDl2bnZiMzBwOXdlb0x3RUFRTTFaR3dqVTJWTXZia3hqeDY2MTFnOGdBd0lBZ0V4RUVQQ2w2dzZsN2VzV0VrRFY5UGtENUVjQUFKQVo4d0dBS2tXSi8ralJ6V24vN0VBQ0lDOENBSUJNUlFpd3EvVUYwQ3VqclJ0L2ZmNEErUklBQUdUTWZBQ2dGNkxjLzZHcFlYMytBSmtUQUFBMFFNd0ZpUGtBMmdLQVRvb0QvOTdKWVgzK0FLa1pCQUFBRFdJK0FOQUordndCbW1sdEFxQXhubnBwWS91bTd2YXJaOVBPZ1dNSllMbkdaemUxcC92cjh3ZG9IaFVBQUExbFBnQ3dITkhuLytqTVlEcXcwSmNBYUNZVkFBQU45V2J2YnV1bFhsc0FjQ0g2L0FIS29RSUFvQkE3cjU1TnR3OGNFd1FBYlZIaUgrWCsxdm9CbEVNRkFFQWh4bzhQcEluNWZtMEJRSHJxeFkxcFpHYkl3UitnTUNvQUFBb1VWUUIvT0hRNDNYclZ5UVNVSS9yOFk4Q2ZjbitBTWdrQUFBcG1iU0NVSVc3NlI2YUgycHRDQUNpWEFBQ0FkZ2dRYXdQN0x6K2RnT2JRNXcvQTJRUUFBTFJaR3dqTkV1WCtEMDBOdDZmOEEwQVFBQUR3RmhFRS9PbjF6MmtMZ0V3ZE9OV1hSbVlHOWZrRDhEWUNBQURPeTN3QXlFdVUrSThlM1p6Mnp3NGtBRGdmYXdBQk9LOFlGall4MTU5dUg1aE51MXBCQUZCZjBlY2YwLzMxK1FOd01Tb0FBTGdrOHdHZ252VDVBN0FjQWdBQWx1eVdLMCttZTdjYzFoWUFGWXNELzk3SllYMytBQ3lMQUFDQVpUTWZBS3F4dU5Zdnl2MEJZTG5NQUFCZzJXSStRTnc4M243MWJObzVjQ3dCM2FmUEg0RFZVZ0VBd0txWUR3RGRGWDMrY2ZCWDdnL0FhcWtBQUdCVjN1eEZiaDFTdEFWQTU4VFAxc2owVUpxWTcwOEEwQWtxQUFEb3FKMVh6NmJiQjQ0SkFtQ0ZGdnY4OTdlK2xQc0QwRWsrVmFpZEtDTWVjbkNBYkkwZkgwajNITHFoUFNjQVdKNkp1ZjcwdS85NGsxNS95Rmk4eDJxTG82NThzbEE3VWZMNCtJMC9UYnV1T1pLQVBDMjJCZHp4N0xaMFlHRmRBaTR1K3Z6di90a05hYzhMMTdkL2ZvRDhyTC84ZFB2OTlmRWJueld6ZzlwYXMvV21kLzF4Z2hxWmV2V0t0R25OYSttM054MXRwNmZ6cDlla2d3dDlDY2pQWE92bjk4a1hCOUpVNjBDemJkMUM2bDl6T2dHL0VMZjhYejB5bVA3dDlKYjI1eCtRcHgzcjU5SURXdytsSGYxejZhOWZlcWNxT0dyTERBQnFxZi95MTlMWGJqN1krdlhNWVNGS0l2Zk5ETFVQRVVDK1lraWc2aDQ0WS9Ub3RmcjhJWE8zWEhVeTdkcDBwUDFyaUFxZWFJTlR5VU5kcVFDZ2xsNSsvZkwwanN0ZVQ3ZSs4VEM5NFIwdnA1MERzMm5MMmxmU2daZjcybFVCUUg2aUpQSmJyVnVScUFUWXZtNGhRWW1pM0Q4T0NCTnpHMXFmZDVjbElEOVI3dis1YTJmU3Z4eWFmTXZRMjlGam05TS96SzlQVUZjcUFLaTFyOTEwOEcyVHhDTlJqZUZJU3FzZ2J4RUFmT202UTdZRlVJdzNWMmJxRFlhc1JTVmJiTHRackZSZEZEL2pNZnNHNmt3QVFLM2RjdVhKOVBBL2VlNjgvMWw3UC9MTVlQc0dCY2hYelBxSTFnQkJBRTBWSmY2alJ6ZW4vYk1EQ2NoWGxQbmZPM1Q0Z3A5WEVmQzVvS0x1dEFCUWF6RVE2ZFpXQ0hDK0IyMlVFSDkwd3dsdEFaQzVHUEw1dC9NYjJnTURGOXQrb0NuR1p6ZWwrMSs0M3EwL1pDelcrajE0M2ZQdG0vOExEYk45NnNXTmFlell0UW5xVGdVQXRSZUgvMmdGdUpSb0MvakxWdXBxVUNEa0szN2VveHJBL21SeUYzMytqODRNcGdPMjJFQzJvcy8vczIrVSsxOUtsUDRiL0VjT1ZBQlFlM0VyR0QxVzc3bnk1eGY5NzBWWlZxeGVzVFlROGhVLzc5SFdjL0RVdXZRL1hYbksya0N5RXdlQVBhMGIvN2dKUFBiYTJnVGthV2ZyMEI5ci9XNVpRbVZhVlByODlZbDNKc2lCQ2dDeWNPNWF3RXM1OHdLMlZSQUFtVE1mZ0Z4RW4zOGNBcXoxZzd6RmdYLzN0ZE5wZTkrcEpmMzNyZjBqTnlvQXlFS3NCWHlsOVVMMWdmWHpTL3J2eDYzaGIxNTkzSHdBeU56aWZBQnJBNm16NlAzOVY4L2ZrUDdoNUhwci9TQlRaL2Y1YjFyNzZwTC85MFptaHN6NElDc3FBTWpLNHpjK203YXQ0QkFROHdGR2p4ck1Bam1MS29EZG02ZlRqdjRUQ2VvZyt2emo4OFhMUCtRcit2dy9PWERzdkd2OUxzWGFQM0lrQUNBckYxc0xlQ254a0k0WE5ldFpJRy9hQXFoYWxQaVBUQS81UElITXhlZko3c0dwWlIvOEY5MzlzeHNFZ0dSSEFFQjJIcjcrdVNVTlpMbVFBd3ZyMmdPYWJBdUF2QzF1Q3hBRTBDdjYvS0VaNGoxeTE2WWpxM3Fmak5hZnZWUERDWElqQUNBNzhiTC8ySTNQcmppdFhSUVA3dEZqMXdvQ0lHUFdCdElyVWU3L1VPdGwzNkF2eUZlVSs5L1Z1dkh2eEdlR3RYL2t5aEJBc2hOcnd0NXgyZXZwMWxXa3RtRjczMEo3YmVCbGwxMlcvdXVwS3hPUW44VzFnZDk2YVdQN0ptZlQydGNTZE5LQlUzM3BUdzVmMTE3ck4yZWdMR1FwRHY2ZjNuUTAvZEYxejZmM0xIRzYvOFhFWEtuNDdJRWNxUUFnUzh0ZEMzZ3A1Z05BTTVnUFFLZEVpZi9vMGMxcC8reEFBdklWNGZDOVE0Yzc5cmtRNzR5Lys0ODNhUU1pV3lvQXlGS3NCWng5ZFczN0JyOFRZc1ZZL0wyc0RZUzh4ZHJBL2NjM3RmOTZ0VlZDbEN2Ni9POS80WHJEdlNCajI5YWRTbDhjZnFHOTFpL2U4em9sMXY2cEhDVm5LZ0RJMm1vSEFsNkkrUUNRUC9NQldDNTkvcEMvS1BmL2JPdlpIMnY5T3MzYVA1cEFBRURXVnJNVzhGSzBCVUF6YkYrM2tMNTAzU0Z0QVZ4UVBPLzNUZzY3OFlmTTdXd2QraVA0N1ZTTDZMa00vcU1KdEFDUXRhbFhyMmkvMU1jTGZxY3R0Z1hFN2VIQmwvdFVBMENtanIyMnR0MFdFRC9EMjFyUGlrNldncEszNk9IOTgyUFh0TXY5NC9NRXlGTlVnMFpWNkVjM25HZ1BpdTZHcUE1MUtVUVRxQUFnZTUxYUMzZ3AyZ0lnZi9HOHVQM3EyZll0RVdXTFB2K284akxJQy9JMTFIcW0zemQwdUN2dG9HZUw1MFFNL25QN1R4T29BQ0I3blZvTGVDbXhObkRud0d5NkxKMFpOUGJ5NjVjbElDL3h2UGlIayt2YmF3T2pFcUFiMVVQVVcvVDVSN24va3k5ZTdUa09tVnBjNi9mQWRjLzNwTDByS29Xcy9hTXBWQURRQ0xFVzhMRWJmOXF6SGwvekFhQVpyQTBzUnp5M1I2YUgwc1I4ZndMeTFlMCsvM01aL0VmVENBQm9qQjNyVDZRSHRqNmZlaWsrRk80K2RJTzJBTWpjenF0bjJ4T2pCUUhORTZXN1VlNi92L1dsM0IveUZXWCt1ellkNlhxNS83bWlZc2lGRDAwaUFLQlJ1clVXOEZMTUI0RDhXUnZZUEJOei9lMmQzZnAySVYvUjUzL1g1cW4yWU9aZSsyN3JHUkpEUXFGSkJBQTBTamZYQWw1SzlCYnZueDFJbzBldlRVQytJZ2o0dzZIRFhaOHJRdmRFbjMrMGFWbnJCL21LUHY5UERoeHJWMmYxcXR6L1hOYiswVVNHQU5Jb3NjWXBQaVRlYytYUFU2L0ZJTUtvUG9qYncvbFdHQkNEQW9IOFJKZ1hRd0t0RGN4UGxQaC85Y2hnK3JmVFc2ejFnNHp0V0QrWEh0aDZxSDNyMzYyMWZwZGk3UjlOcFFLQXhvbUJnRis3K1dCbGFmR2laMW8zVUYrWkd0WVdBSm1MdG9DZEZkNUFzVFJSZmFYUEgvSldWWi8vdWVMVy81NURON2o5cDVGVUFOQTRMNzkrZVUvV0FsNUtsQkhIMnNBdGExOUpCMTd1YTFjRkFQbUpNdksvT2ZGT2F3TnJLc3I5NDBVOVZuUlo2d2Q1aW5ML3oxMDdrLzdsMEdRdGhySEc3QkF0UkRTVkNnQWE2MnMzSGF6TlJPOUlrUGNmMzVUR1p3Y1NrSzk0cHZ6cDljL1pGbEFEOFZ5TjZkeGUwaUZ2dTY0NVVtbWYvN21zL2FQcFZBRFFXTkdEZjl2R2VrenpqcHZERDZ5Zk54OEFNdGNlOXRrSzg4d0hxTTVpbi8vL2VmZzZmZjZRc1NqemorMU5WZmI1bjAvYy9udFBvOGtFQURSV3ZCamVldVhKV3QzVXhXRWhQdWkwQlVEZTR1VXdCZ1ZHeTVGdEFiMHpQcnVwdlpMTHJUL2tLOWI2UFhqZDgrMmIvN3FGcURINGIreVliVTQwbXhZQUdpME8vOUVLVUZmUkVqRCt4bTBpa0tkNHpzU2d3S2p3b1R1aXovL1JtY0Ywd0swY1pDdjYvRC83UnJsL1hWbjdSd2xVQU5Cb1VhNWIxVnJBcFhqUGxhZmFGUUhhQWlCZjhaeUpBWFN4K1NOS1dyVUZkRTY4aU85cDNmakhqZHl4MTlZbUlFK3hTU1hXK2xVOTNmOWlvc0xvcjArOE0wSFRxUUNnOGVxeUZ2QlN6cnpvYmhVRVFPYWlFaUFxQWd3S1hMbm84NCtYY1d2OUlHOXg0Tjk5N1hUYTNuY3ExWm0xZjVSRUJRQ05GejI2cjdSZUlHTUlYNTNGcmVGdlhuM2NmQURJWElSNGZ6dS93ZHJBRllvZTNILzEvQTNwSDA2dXQ5WVBNblYybi8rbXRhK211clAyajVLb0FLQVlqOS80Ykh0cWR5N0dqbDZiUm84YVJBTTVNeDlnNmFMUFA1NTdYc0loWDlIbi84bUJZN1ZhNjNjcDF2NVJHZ0VBeGJqbHlwUHA0WC95WE1wSmZDakZDL0ZUTDIxTVFMNjBCVnhZbFBpUFRBOTV6a0htNGptM2UzQXFtNFAvb3MvOTR5OXB2NlFvQWdDS0V2dG02enlBNWtJT0xLeHJEOEt5TFFEeXR2UHEyZmJObUNCQW56ODBSYnhYN2RwMEpNdjNxMmc1MmpzMW5LQWtBZ0NLRWkvZGo5MzRiSGJwOUtMNG9CbzlkcTBnQURLbUxlQk11ZjlEclpkdUE3Y2dYOUhudnl2elo1bTFmNVRJRUVDS0V1dTYzbkhaNituV0RGUHFzTDF2b2IwMmNNT2EwL3BrSVZPTGF3Ty85ZExHOW8zWnByV3ZwVkljT05XWC91VHdkZTIxZm5NR25VS1dvcy8vMDV1T3BudTNIRTd2cWZsMC80dUpPVXZ4TEliU3FBQ2dPTG1zQmJ3VTh3R2dHVXFZRHhBbC9xTkhONmY5c3dNSnlGZUVsdmNPSGM3K2VXWHdIeVZUQVVCeFlpM2c3S3RyMnpmcE9Zc1ZZL0Y3Mkw3dVZQci9UbDFwYlNCa0tvWlA3VCsrcWYzWHVWWW5YVXowK2QvL3d2V3FsaUJqY2ZDL3IzWHdqNUwvZVAvSVhhejlNL2lQVXFrQW9GaTVEZ1M4RVBNQklIOU5tZytnengveUYrWCtuMjA5azJKNGFWTkVLOUx2UHZkTENVb2xBS0JZT2E0RnZCUnRBZEFNMjljdHBDOWRkeWpMTXR0NER1MmRISGJqRDVuYjljYkJQL2VXeVhNWi9FZnB0QUJRcktsWHIyaS9YTWVMZGxNc3RnWEU3V0g4L243Mjhyb0U1T2ZZYTJ2YmJRRlIwYk90OVl6S29lUTIrdnovL05nMTZhSEo2OUxQWG5sSEF2SVUxWkZSSlJudkV6RTR1VW1pV3RJbENhVlRBVURSbWpJUThFSzBCVUQrSXFqODFWYW9GN2R4ZFJWOS9sRjlGQ0VBa0tkWTZ4ZDkvazFxanp4YjNQcmZjK2dHdC84VVR3VUFSWXVCZ0RtdkJieVVXQnU0YzJBMlhkYjY2OGxYcnpBb0VESVU2L0tpbkQ3V0JrWWxRSjJxbHFMUFA4cjluM3p4NnRiejlMSUU1R2R4cmQ4RDF6M2Y2RzBrNDhjM1dmc0hTUVVBdEtzQUhydnhwNDMrMEF2bUEwQXo3RmgvSXUwZW5LNzBtZVY1QXMyd2MrQlllL0JvVXlzaEYxbjdCNzhnQUlEVXpJR0FGeElmZ250ZTJHcjlEV1F1Wm4zRWkzc3ZnNEFvOFk5eS8vMnRMK1gra0s4bzg5KzE2VWhqeS8zUEZaVktBa3M0UXdzQXBETURBVzl0aFFCTnJ3SUlVVUw4bTFjZlQxdld2cElPdk55bkxRQXlGU0hlMzg1djZGbGJ3TVJjZjdyL2hldmJKYlRLL1NGUDdUNy9MWWZUbmRmT0ZQSE9FNzdiZW5iOVgwY0dFM0NHQ2dCNFEwbFZBR2VMTXQ3UjFoZVFyM2lSMzcxNU91M29QNUU2TGZyODR6bGhyUi9rSy9yOFB6bHdySkZyL1M3RjJqOTRLeFVBOElhb0FvZ1B4ZmRjK2ZOVWtpai9pMUxpcUFUUUZnQjVpa0dCZjMzaW5SMWRHeGdsL2w5dDNacjkyK2t0N2VjamtLZjRqUCtqNFJjYXVkYnZVcXo5ZzdkVEFRQm5hZnBhd0VzNXNMQXU3WG5oZW1zRElYTXhHMkRuS203Nm9pcEluei9rcmJRKy8zTlord2ZucHdJQXp0TDB0WUNYc21udGErMjFnZVlEUU42aVhQOXZUcnh6MmZNQm90dy9YcGoxK1VPK290ei84ME9UNmE3TjA4WDArWi9QeU15UTFpVTREeFVBY0I1ZnUrbGcwUithSVJMei9jYzNwZkhaZ1FUa0s1NWxmM3I5Y3hkOXBzWFBlMHpKOXJJTStTcTV6LzljMXY3QmhRa0E0RHhLSFFoNFB2WjlRek9jYjIxZ2xQaVBIdDJjOWd2NklHdFI1bi92ME9IaUx5OFc3WG4rK2pReDM1K0F0OU1DQU9kUjBsckFTNGtTNGhnY3BDMEE4aFpEUHFPcUowU2IwL2pzcHZaYVA3ZitrSzl0NjA2bEx3Ni9rSGExd3IxT0RQOXNnaGo4OS9YWmF4SndmaW9BNEFMaThCK3RBTHhWdEFTTXR3NFJCZ1ZDdnFJODJJQS95RmVVKzMrMmRlaVBjbi9leXRvL3VEZ1ZBSEFCYzIvY2RKYzZFUEJDM25QbHFYWkZnTFdCa0M4RC9pQmZzZUhqZ2EySGlwM3Vmekd4d1NTR21BSVhKdjZIaTRpK1dMZGtieGZWRWZkdU9keXVrUEFDQWdEZEY1KzNqOTN3MDdSNzgzVHhRLzdPSjI3OXYyVmVFVnlTQ2dDNGlGZ0wrRW9yQVBqQSt2bkUyMFcvWVF3V014OEFBTHBqcUJXNlAzamQ4KzArLzAxclgwMmNuN1Yvc0RTdU51RVN4bzhQcEdkTytrQzVtTnMydnBpZXVPbmdtU0ZFYmlVQVlOV2l6ejgrVngrLzhWblZkcGNRdC8rMkZjSFNDQUJnQ2FLbmpFdUxGV09QdFY1VW9pb0FBRmlaK0J4OTR1WUQ3YzlWd2ZxbDdYbGhhd0tXUmdBQVN4QWxaUk56OXNrdXhkbnpBWWFzVVFTQUpZdWIvb2V2ZjY3OU9lcmd2elN4OXM5UVlsaTZ0UWxZa3VndGl3OW1IOGhMRTBGQXRBWEVCL1Bvc1d1dERRU0FDNGpBUE1yOVZkQXQzOWd4Vlpxd0hJWUF3aExGV3NCM1hQYTZ0WURMdEwxdklkMjI4YVcwcnZWblp6Z1BBUHhDOVBsL2V0UFI5bzMvZS9wT0paYkgyajlZUGkwQXNBeXhGbkRTVGZheTlWLytXcnVQTWRvQzNHNEFRRW83MXMrMUIvenA4MStaZUI4Yk02TUpsazBBQU1zUVZRQStiRlp1Y1Q1QTlEZWFEd0JBaVJiNy9CL1llcWo5dWNqS2VCK0RsUkVBd0RMRm1obHJBVmNuWG41aVBzQzlRNGNGQVFBVUljcjk3OW84M1Q3OFcrdTNPZ2RPOVZuN0J5c2tBSUFWc0Jhd00yN2IrR0w3UldqbndHd0NnS2FLQVgreDF1LzJnV09KMWJ2L3NMVi9zRklDQUZpQkdHWW5lZTZNS0gvY3ZYbktmQUFBR2lkdSt1UHpUWjkvNThSMklmT1lZT1dzQVlRVkdwa2VURHY2VC9oQTc1REYrUUMzWEhuUzJrQUFzaGJ0YmZjTkhWYnEzMkh0d1gvVy9zR3FxQUNBRllxQmdPT3pteEtkRlcwQk1SOGdxZ0xNQndBZ0o0dDkvdkU1NXZEZmVWRjk2ZllmVmtjQUFLdGdMV0QzeEZ5QW1BK2dMUUNBSE93Y09LYlB2NHVzL1lQT0VBREFLa1FWd043SjRVUjNMTFlGUlAva3RuV25FZ0RVemVKYXY5MnRtMzl0Z2QzajhBK2RZUVlBckZJTUJJeTFnRXI5dWllQ2dNZHYvR2w3OEkvNUFBRFVnVDcvM3ZudVhML2h5OUFoS2dDZ0EvYk5EQ2E2YjNFK1FLeFRBb0FxUko5L2ZBNDlmdU96RHY4OTh1ak1VQUk2UXdBQUhYQndvYzlBd0I2S2RVcldCZ0xRYS9HNUUzMysxdnIxanJWLzBGa0NBT2lRc2FQWHBMblRmcVI2WlhFK3dHT3RHeGpiQWdEb3BzVSsvL2pjY2ZEdkhXdi9vUFBXYkwzcFhYK2NnRlY3K2ZYTDB5dXRBT0FENitjVHZiTnA3V3Z0alFGYjFyNlNEcnpjbCtaUHIwa0EwQWxSN3YvNW9jbjJhcjh0d3VhZUc1a1phczlhQWpySEVFRG9vUEhqQSszMVAxNFNlaS9tQThRTnpiZGUycGhHVFFvR1lCWGk0UC9KMXVkNWZLYTc4YTlHM1A0Yi9BZWRwMTRaT3N4YXdPcEU4R0krQUFDckVXRnlEUGpUNTErdGtXbUQvNkFiVkFCQWgxa0xXTDNGK1FBNytrK2tmVE5EMWdZQ2NFbmIxcDFxbC9yNy9LNWVEUDZibU85UFFPZGQ5b0dQL3ZyckNlaW9PSURHTFRUMUVDOFNvOGV1RlFRQThEWlI3di9aMW0xL2xQdFREM2M4dTgza2YrZ1NRd0NoQytiZUdFUjNxMXVFV3RqZXQ1QjI5TSsxQndUR3lrWUFDRHRiaC80SHRoNXk2MThqTWNkblltNURBcnJEREFEb2t2MnpBOVlDMXNoaVcwQlVaa1JyQUFEbGlnTi9mQjdzM2p5dHo3OUc0dGIvV3diL1FWZXBBSUF1c1Jhd252clhuRTRmM1hEQzJrQ0FBZzIxd3VBSHIzcys3WW9CZjJzYy9Pdkcyai9vUHRlVDBFV3hGakFHQWxJL3NUYndpZGJ0VDd3RURsbmJDTkJvMGVjZnovdDQ3aXYzcnlkci82QTNCQURRWlhiUzExdXNlWHI0K3Vlc0RRUm9xT2p6ZitMbUErM25QZlcxNTRXdENlZytBUUIwV1pTeVRjeFpaVk5uWjg4SFVBMEEwQXh4MHg4QnJ6Ny8rb3R0UFliMFFtK3NUVURYUlU5YnZJaDRBYW0zQ0FLaVBOVGFRSUI4UlpCNzErYXA5dllYOGpCMlRMVWs5SW9LQU9pQjZHc2JuOTJVeU1QWjh3RUF5TU5pbi8vak56N3I4SitSYUpXY0ZMaER6d2dBb0VkaUxhQVB1THhFdjJpMEJaZ1BBRkJ2TzliUHRRLys4ZHhXYlplUGVDOGFNeXNKZWtvQUFEMHlkM3FORDdrTUxjNEhlS3oxWW1rK0FFQzlMUGI1UDdEMVVQdDVUVjY4RjBIdkNRQ2doMks5amJXQWVkcSticUhkRm5EdjBHRkJBRURGb3R6L3JzM1Q3Y08vdFg1NU9uQ3F6OW8vcUlBQUFIck1Xc0M4eFh5QWVPSGNPVENiQU9pOTZQT1B0WDYzRHh4TDVPdit3OWIrUVJVRUFOQmpzUlpRNHAyM0tEUGR2WG5LZkFDQUhvcWIvbmp1NnZQUFgyemJNUmNKcW1FTklGUmdaSG93N2VnLzRRVW1jNHZ6QVc2NThxUzFnUUJkRW0xWDl3MGRWdXJmRU8zQmY5YitRV1ZVQUVBRllpQ2d0WUROc2JnMk1Lb0N6QWNBNkl6RlB2OTR2anI4TjBkVVFicjloK29JQUtBaTFnSTJUOHdGaVBrQTJnSUFWbWZud0RGOS9nMWs3UjlVVHdBQUZZa3FnTDJUdzRsbVdXd0wrSm9iSzRCbGkrZm1ZemY4Tk8xdTNmeHJrMnNlaDMrb25oa0FVS0VZQ0JockFSMFVteWVDZ0tnR2lFRkg1Z01BWEp3Ky8rYUx6ME5Ea0tGNktnQ2dZdnRtQmhQTnRUZ2ZZSmVwMVFCdkUzMys4WHg4L01abkhmNGJ6dUEvcUljMVcyOTYxeDhub0RLenI2MXRId3pmYytYUEU4MFZMN1lmM2ZCU21qKzlKaDFjNkVzQXBZdDVLVisrL21mcEErdm4wenN1ZXozUlhHNy9vVDVVQUVBTmpCMjlKczJkOXVQWWRHZlBCN0F0QUNoVkJLTFJJaFhQUTVWUnpXZnRIOVNMQ2dDb2daZGZ2enk5MGdvQTRoYUU1dXRmYzdxOU1XREwybGZTZ1pmNzJsVUJBRTBYd2VkZGc5UHQxWDViaEtERkdKa1phczg4QXVyQmxTUFV4UGh4YXdGTEUvTUJIci94cCszK1Y0Q21PcnZQMzVyVXNzUjdqZEovcUJjQkFOU0l0WURsNmIvOHRmU1oxb3R4dEFWNE1RYWFKc3I5NCtEL0dZTlFpelF5UFpTQWVyRUdFR3JFV3NCeUxjNEgyTkYvSXUyYkdiSTJFTWhhZkk3dDJuVEU1MW5CWXZEZnhIeC9BdXJsc2c5ODlOZU5YWVVhaVlOZzNBWlR0bmh4R2oxMnJTQUF5RXFVKzMrMmRkdC8rOEN4Uk5udWVIYWIxa2FvSVVNQW9XYm0zaGdJZDZ0Yms2SnQ3MXRJTy9ybnJBMEVzaEY5L245MDNmTnUvVW1qUjY5TkUzTWJFbEEvWmdCQURlMmZIYkFXa0xlc0RUUWZBS2lyT1BESGMwcWZQeUZ1L2ZmUGJrcEFQYWtBZ0JxeUZwQ3p4ZHJBcUFhd05oQ29rMWpyOTJEcnhqOXUvdU01QlNIVy92M1hVMWNtb0o1Y01VSk54VnJBR0FnSWkySnQ0Qk90VzdaNDJSNnlReHVveU9KYXYzZ2VLZmZuYk5iK1FmMEpBS0RHb29jT3poVmx0ZzlmLzV5MkFLRG5kZzRjUzAvY2ZLRDlISUp6M1hQb2hnVFVtd0FBYWl6V0FrN01XYUhEMjUwOUgyRGJ1bE1Kb0p2aXBqK0N4OTJicC9YNWMxNnh2Y2JVZjZpL3RRbW90ZWlsaXhjdkwxeWNUd1FCajkvNFUyc0RnYTZJZHFPN05rKzE1NURBeFl3ZFU3VUlPVkFCQURVWGFmcTRhYnBjd3RuekFRQldhN0hQLy9FYm4zWDQ1NUtpWmRIdFArUkJBQUFaaUxXQVBsaFppdWpMdFRZUVdJMTRmc1RCMzFvL2xpTGVUOGJNTElKc0NBQWdBM09uMTZTUjZjRUVTN0U0SCtDeDFndThiUUhBVWkzMitjZnpZNHRuQjB2azhBOTVNUU1BTWpFeHY2RzlGdERLSlpacSs3cUZkbHVBK1FEQXhVUzUvMTJEVXlxSFdMWURwL3FzL1lQTXFBQ0FqRmdMeUVyRWZJQzQxVE1mQURqYllwOS9yUFZ6K0djbDdqKzhOUUY1V2JQMXBuZjljUUt5TVBYcUZlMSt6UGRjK2ZNRXk5Ry81blM3ZWlSZTh1ZFByMGtIRi9vU1VLNTRIbng1NjgvYUEvN2VjZG5yQ1pZcnFzdmMva04rdEFCQVpzYU9YdE82MFQxdU1CTXJzamdmWUVmL2liUnZaa2hiQUJSbTI3cFQ2YTdOMDlySldKWDI0RDlyL3lCTEFnRElUQXdFakxXQXlybFpqYmoxaXkvekFhQU1VZTcvMmRibnh1MER4eEtzMXZqeFRiWVRRYWJNQUlBTVdRdElweXpPQjlEL0M4MjFzM1hvano1L2gzODZJZDQvNGowRXlKTUFBRElVVlFCN0o0Y1RkTUppVzhEWGJqclliZzBBbWlISy9CKzc0YWRwOStacGJXTjBqTFYva0RjdEFKQ3BaMzUrbGJXQWRGUUVBUTljOTd5MkFNamNVT3RuK2I2aHd6NGY2RGlEL3lCL0tnQWdZL3RtQmhOMFdyUUZQSEhUd2ZhY0NiZUdrSS9GdFg2UDMvaXN3ejlkWWZBZjVNOGFRTWpZN0d0cnJRV2thK0lBOGRFTkwxa2JDQm1JT1I1ZnZ2NW42UVByNTYzMW95dGlBUEZmbjNobkF2S21BZ0F5RjJzQjUwNzdVYVk3enA0UEVHWEZRTDFFVUJlRFBPUG5WTVVPM2RJZS9IZmM0RDlvQWhVQWtMbVhYNzg4dmRJS0FPTFdCN3FsZjgzcHRITmdObTFaKzBvNjhISmZ1eW9BcUU0RWNuY05UcWU3TmsrM2d6cm9wcEdab2Zic0lTQi9oZ0JDQTR5M1V2bmJOaDVQMjlZdEpPaW1tQSt3WThOY2V3WFVxRW5RMEhQUjUvL0pnV1B0bFg1dS9PbUZ1UDAzK0ErYVE5MHdOTVMrNmFFRXZkQi8rV3ZwTTljY2FiY0ZSTjh4MEJzNzFzKzFCL3g5eG9CT2VzamFZV2dXRlFEUUVOWUMwbXVMOHdFaUJQaksxTEMxZ2RBbDhWemZ0ZW1JNXpzOUYydi9sUDVEczF6MmdZLyt1bEd4MEJCeElIdXNkVHZrWm9ncXhJdmk2TEZyQlFIUUlWSHUvOW5XYlgrVSswTVY3bmgyVzdzRkFHZ09Rd0NoUWVaT3IybXZmN3JWTFJFVjJONjNrSGIwejZYTExyc3MvZGRUVnlaZzVYYTFEdjUvZE4zemJ2MnBUTXg1bVpqYmtJQm1NUU1BR2lhR3Mxa0xTRldpQ21YMzVpbnpBV0NGNHNBZlB6LzYvS2xTZSszZjdLWUVOSThLQUdnWWF3R3BnMWdiR05VQTFnYkMwc1JhdndkYk4vNXg4eDgvUDFDbFdQdW5rZ3VheVJCQWFLQllDN2lqLzRUU1VTb1hhd1BqYTN4Mm9QVjl1Y2w4QURpSFBuL3F4dG8vYURaMXd0QlFkclJUSnpzSFp0UEQxeituTFFET3NyTjE2SC9pNWdNTy85VEtQWWR1U0VCekNRQ2dvV0p0andTZk9sbGNHeGo5emFwVEtGbDgvMGNndG52enRENS9haVcydVpqNkQ4Mm1CUUFhYk96b3RlMVdBQytZMUVrRUFYSDRzVGFRMGtTZi8zMURod1ZnMUZJTUVCNDdwbm9RbWs0RkFEUllwUGpqcHZoU1V6RWI0SW1iRHA0WmVpYWtvc0dpenorK3p4Ky84Vm1IZjJvcjNoZmMva1B6Q1FDZzRXSXRvQTkwNml6V25UM1dPaGlaRDBBVHhmZDFIUHl0OWFQTzRqMWh6T3dnS0lJQUFCcHU3dlNhTkRJOW1LRE96cDRQRUdYU2tMdkZQdi80dnQ3aWU1cWFjL2lIY3BnQkFBV1ltTitRbmpsNWxkSlRhaThPU3RFV1lENEF1WXB5LzdzR3AxUzBrSTJuVHhvYURDVlJBUUNGc0JhUW5NUjhnTWR2L0dtN2J4cHlzTmpuSDJ2OUhQN0p5VU5Ud3drb3g1cXRONzNyanhQUWVGT3ZYdEh1UDMzUGxUOVBrSU4zWFBaNnUyb2xEbFB6cDlla2d3dDlDZW9vdmsrL3ZQVm5hVWYvWFB2N0ZuSVIxVlp1LzZFc1dnQ2dJR05IcjJuZHJCNDNpSXFzTE00SGlKV1crMmFHdEFWUUc5dlduVXAzYlo3V1hrV1cyb1AvclAyRDRnZ0FvQ0F4RUREVy9DaXJKa2R4dXhwZjVnTlF0U2ozLzJ6ck9Ycjd3TEVFdVJvL2J1MGZsTWdNQUNoTVRQcjFnVS9PWWo1QVRGZlhaMDBWZHJZTy9kSG43L0JQenVJOUlOWUVBK1VSQUVDQjlrNGErRVBlemw0YkdLMEIwRzFSNWgvZmI3czNUMnVqSW52Vy9rRzV0QUJBZ1o3NStWWFdBdElJRVFROGNOM3oyZ0xvbXFIVzk5aDlRNGM5TDJrTWcvK2diQ29Bb0ZCN3JmMmhRYUl0NEluVzdXek10NGdERzZ6V20ydjlXdDlYRHY4MGljRi9VRFpyQUtGUU1SRFFXa0NhSmc1cU1TalEya0JXSS9yOEg5aDZLSDFnL1h5Q0pvbEJ3SDk5NHAwSktKY0tBQ2hZckFXY08rMHhRTE9jUFI4ZzFyVEJVa1dBRkFNbTlmblRSTzNCZjhjTi9vUFNxUUNBZ3IzOCt1WHBsVllBNEphTEp1cGZjenI5NXRYSDA1YTFyNlFETC9lMXF3TGdmTnA5L3EzUTZNNXJaOW9CRWpUUnlNeFFld1lRVURaWGYxQzQ4ZFp0d01HRmRRbWE2dXo1QUhDMnhUNy94Mjk4dHQwNkFrMFZ0LzhHL3dGQkFBQ2tmZE5EQ1pydU02MkRYclFGM1BiT0Z4UHNXRC9YUHZqSDk0VnlmNXJPK2w5Z2tRQUFlSE10SURUZDRueUF4MW9IUDlzQ3lyVFk1eDlEL3BUN1U0SlkrNmYwSDFna0FBRGFZaTJnZ1lDVVl2dTZoWFpid0wxRGh3VUJoWWh5LzdzMlQ3Y1AvOWI2VVJKci80Q3plZHNIMnFJL01OWURRVWxpUHNDdVRXWURsT0N1d2FsMCs4Q3hCQ1VaUFhwdCsvTWRZSkVBQUhqVC90a0JWUUFBMEFEdHRYK0NmZUFjM3ZTQk44MmRYcE5HREFRRWdPeU50VzcvaGZyQXVUd1ZnTGVJTlVFR0FnSkF2cXo5QXk1RUFBQzhUZlFNQWdCNXV1ZlFEUW5nZkFRQXdOdkV1aUEzQndDUW4xajdaL0FmY0NFQ0FPQzg5QTRDUUY3aWM5dmFQK0Jpdk4wRDUyVXRJQURrSlQ2MzNmNERGeU1BQUM0bzFnSjZrUUNBK292UDZ6RXpmSUJMRUFBQUYzUm1MZUJnQWdEcXplRWZXQW9CQUhCUkUvTWJyQVVFZ0JwNytxVGh2Y0RTQ0FDQVM3SVdFQURxNjZHcDRRU3dGQUlBNEpKaUxhQ0JnQUJRUDliK0Fjc2hBQUNXWk96b05kWUNBa0NOdEFmL1dmc0hMSU8zZVdCSllpQ2dLZ0FBcUkveDQ5YitBY3NqQUFDV0xDWU1lOUVBZ09yRjUzR3M2d1ZZRGdFQXNDeDdKdzBhQW9DcVdmc0hySVFBQUZpV0dBaG9MU0FBVkNjRy8xbjdCNnlFQUFCWXRyM1dEUUZBWlF6K0ExWktBQUFzVy9RZEdnZ0lBTDBYbjcvbThRQXJKUUFBVnNSYVFBRG9yZmJnditNRy93RXI1KzBkV0pGWUN6aDJaSE1DQUhyRE5oNWd0UVFBd0lxTnQyNGhEaTZzU3dCQWQ4WEIzK0EvWUxVRUFNQ3E3SnNlU2dCQWQrMTVZV3NDV0MwQkFMQXExZ0lDUUhmRjJyK0RDMzBKWUxVRUFNQ3F4VnBBQXdFQm9EdXMvUU02eFJzN3NHcldBZ0pBZDR3YS9BZDBrQUFBNklqOXN3T3FBQUNnZytMZ0g1UC9BVHJGMnpyUUViRVdjTVJBUUFEb0dJZC9vTk1FQUVESHhIb2lBd0VCWVBXcy9RTzZRUUFBZE5TbzJ3b0FXTFY3RHQyUUFEcE5BQUIwVkt3RmRHTUJBQ3NYYS84TS9nTzZRUUFBZEZ6MExCb0lDQURMRjUrZjF2NEIzZUlOSGVnNGF3RUJZR1hpODlQdFA5QXRBZ0NnSzJJdG9CY1lBRmc2YS8rQWJoTUFBRjF4WmkzZ1lBSUFsc2JoSCtnMkFRRFFOUlB6RzZ3RkJJQWwrTzVjdnlHNlFOY0pBSUN1c2hZUUFDN3QwWm1oQk5CdEFnQ2dxMkl0b0lHQUFIQmgxdjRCdlNJQUFMcHU3T2cxMWdJQ3dIbTBCLzlaK3dmMGlEZHlvT3RpSUtBcUFBQjR1eGo4NS9ZZjZCVUJBTkFUWG5BQTRLM2ljOUhnUDZDWEJBQkF6K3lkSEU0QXdCa2owd2IvQWIwbEFBQjZKZ1lDV2dzSUFHY0cvMDNNOXllQVhoSUFBRDIxZDBvVkFBQVkvQWRVUVFBQTlGVDBPNDRlOWRJRFFMbEd6Y1VCS2lJQUFIcHUvK3lBdFlBQUZDa08vdDh5K0Erb2lEZHdvT2RpTGVEWWtjMEpBRXBqS3c1UUpRRUFVSW54NHdNR0FnSlFGR3YvZ0tvSkFJREttQVVBUUVuMnZMQTFBVlJKQUFCVXhscEFBRW9SYS84T0x2UWxnQ29KQUlCS3hWcEFBd0VCYURwci80QTY4TllOVkNyNkljZG5OeVVBYUNwci80QzZFQUFBbGJNV0VJQ21pb1AvbUprM1FFMTQ0d1lxRjJzQlI2YUhFZ0EwamNNL1VDY0NBS0FXWWkyU2dZQUFOTW1CVTMzVy9nRzFJZ0FBYXNOYVFBQ2E1UDdEMXY0QjlTSUFBR29qMWdLNktRR2dDV0x0bjhGL1FOMElBSUJhR1prZU5CQVFnS3kxQi85Wit3ZlVrTGRzb0ZaaUlLQzFnQURrTEtyWjNQNERkU1FBQUdvbjFnSjZjUUlnUjliK0FYVW1BQUJxSjZvQTlrNE9Kd0RJamNNL1VHY0NBS0NXWWlDZ3RZQUE1T1M3Yy8yRzJRSzFKZ0FBYW12ZnpHQUNnRnc4T2pPVUFPcE1BQURVMXNHRlBnTUJBY2lDdFg5QURnUUFRSzJOSGIzR1drQUFhczNhUHlBWDNxcUJXb3VCZ0dOSE5pY0FxS3NZL09mMkg4aUJBQUNvdmZIajFnSUNVRS94K1dUd0g1QUxBUUNRQldzQkFhaWprV21ELzRCOENBQ0FMRmdMQ0VEZHhPQy9pZm4rQkpBTEFRQ1FqYjFUcWdBQXFBK0QvNERjQ0FDQWJFU2Y1ZWhSTDFzQVZHL1U0RDhnUXdJQUlDdjdad2VzQlFTZ1VuSHcvNWJCZjBDR3ZFVURXYkVXRUlDcVdmc0g1RW9BQUdRbjFnSWFDQWhBRmF6OUEzSW1BQUN5WkJZQUFGWFk4OExXQkpBckFRQ1FwVmdMT0RGbjlSSUF2Uk5yL3c0dTlDV0FYQWtBZ0d5TnpBd1pDQWhBejFqN0IrVE9tek9RcmVqREhKL2RsQUNnMjZ6OUE1cEFBQUJrTGRZQ2VpRURvSnZpYzJiTTdCbWdBUVFBUU5iYWF3RzlsQUhRUlQ1bmdLWVFBQURaaTNWTTFnSUMwQTBIVHZWWit3YzBoZ0FBYUFSckFRSG9odnNQVy9zSE5JY0FBR2lFV0F2b2hnYUFUb3ExZitiTUFFMGlBQUFhWTJSNjBGcEFBRHFpUGZqUDJqK2dZYndwQTQwUkF3R3RCUVNnRTZLcXpPMC8wRFFDQUtCUnJBVUVZTFdzL1FPYVNnQUFORXBVQWV5ZEhFNEFzRklPLzBCVENRQ0F4b21CZ05ZQ0FyQVMzNTNyTjFRV2FDd0JBTkJJKzJZR0V3QXMxNk16UXdtZ3FRUUFRQ01kWE9nekVCQ0FaYkgyRDJnNkFRRFFXR05IcjdFV0VJQWxzZllQS0lFM1k2Q3hZaURnMkpITkNRQXVKUWIvdWYwSG1rNEFBRFRhK0hGckFRRzR1UGljTVBnUEtJRUFBR2c4YXdFQnVKaVJhWVAvZ0RJSUFJREdzeFlRZ0F1SndYOFQ4LzBKb0FRQ0FLQUllNmRVQVFEd2RnYi9BU1VSQUFCRmlQN08wYU5lOGdENGhWR0QvNERDQ0FDQVl1eWZIYkFXRUlDMk9QaC95K0Evb0REZWhJRmlXQXNJd0NKci80QVNDUUNBb3NSYVFBTUJBY3BtN1I5UUtnRUFVQnl6QUFES3R1ZUZyUW1nUkFJQW9EaXhGbkJpenNvbmdCTEYycitEQzMwSm9FUUNBS0JJSXpOREJnSUNGTWphUDZCazNuNkJJa1gvNS9qc3BnUkFPYXo5QTBvbkFBQ0tGV3NCdlFnQ2xDR2U5Mk5td0FDRkV3QUF4V3F2QmZReUNGQUV6M3NBQVFCUXVGZ0RaUzBnUUxNZE9OVm43UjlBRWdBQVdBc0kwSEQzSDdiMkR5QUlBSURpeFZwQU4wTUF6UlJyLzh4N0FUaERBQURRTWpJOWFDMGdRTU8wQi85Wit3ZndKbSs3QU9uTVFFQnJBUUdhSmFxNzNQNEQvSUlBQU9BTjFnSUNOSWUxZndCdkp3QUFlRU5VQWV5ZEhFNEE1TS9oSCtEdEJBQUFaNG1CZ05ZQ0F1VHR1M1A5aHJzQ25JY0FBT0FjKzJZR0V3RDVlblJtS0FId2RnSUFnSE1jWE9nekVCQWdVOWIrQVZ5WUFBRGdQTWFPWG1NdElFQm1yUDBEdURodnR3RG5FUU1CeDQ1c1RnRGtJd2IvdWYwSHVEQUJBTUFGakIrM0ZoQWdGL0c4TnZnUDRPSUVBQUFYWVMwZ1FCNUdwZzMrQTdnVUFRREFSVmdMQ0ZCL01maHZZcjQvQVhCeEFnQ0FTOWc3cFFvQW9NNE0vZ05ZR2dFQXdDVkVYK25vVVMrWEFIVTBhdkFmd0pJSkFBQ1dZUC9zZ0xXQUFEVVRCLy85czVzU0FFdmpiUlpnQ2F3RkJLaWZXUHNubkFWWU9rOU1nQ1dLdFlBR0FnTFVnN1YvQU1zbkFBQllCck1BQU9yaG5rTTNKQUNXUndBQXNBeXhGbkJpenFvcGdDckYyaitEL3dDV1R3QUFzRXdqTTBONlRnRXFaTzBmd01wNGd3VllwcmgxR2pkMUdxQVMxdjRCckp3QUFHQUZZaTJnRjFDQTNvcm43cGhaTEFBckpnQUFXSUgyV2tBdm9RQTk1YmtMc0RvQ0FJQVZpdlZUMWdJQzlNYUJVMzNXL2dHc2tnQUFZQldzQlFUb2pmc1BiMDBBckk0QUFHQVZZaTJnR3ltQTdyTDJENkF6QkFBQXF6UXlQV2d0SUVDWHRBZi9XZnNIMEJIZVdBRldLUVlDV2dzSTBCM2p4emU1L1Fmb0VBRUFRQWRZQ3dqUWVmRmNqZWNyQUowaEFBRG9nS2dDMkRzNW5BRG9IR3YvQURwTEFBRFFJVEVRMEZwQWdNNkl3WCtHckFKMGxnQUFvSVAyelF3bUFGYlA0RCtBemhNQUFIVFF3WVUrQXdFQlZzbmFQNER1RUFBQWROalkwV3VzQlFSWUlXdi9BTHJIR3lwQWg4VkF3TEVqbXhNQXl4ZUQvOXorQTNTSEFBQ2dDOGFQV3dzSXNGengzRFQ0RDZCN0JBQUFYV0l0SU1EeWpFd1BKUUM2UndBQTBDWFdBZ0lzWFF6K201anZUd0IwandBQW9JdjJUcWtDQUZnS2cvOEF1azhBQU5CRjBjODZldFJMTGNERmpCcjhCOUFUQWdDQUx0cy9PMkF0SU1BRnhNRi8vK3ltQkVEM2VTTUY2REpyQVFFdUxOYitDVWtCZXNQVEZxQUhZaTJnZ1lBQWIyWHRIMEJ2Q1FBQWVzUXNBSUMzdXVmUURRbUEzaEVBQVBSSXJBV2NtTFBpQ2lERTJqK0Qvd0I2U3dBQTBFTWpNME42WFFHU3RYOEFWZkFXQ3RCRGNkczFidG8xVURoci93Q3FJUUFBNkxGWUMrakZGeWhWUFAvR3pFUUJxSVFBQUtESDJtc0J2ZndDaGZMOEE2aU9BQUNnQXJIMnlscEFvRFJQdDU1NzF2NEJWRWNBQUZBUmF3R0IwancwTlp3QXFJNEFBS0Fpc1JiUVRSaFFDbXYvQUtvbkFBQ28wTWowb0xXQVFPTzFCLzlaK3dkUU9XK2RBQldLZ1lEV0FnSk5OMzU4azl0L2dCb1FBQUJVekZwQW9NbmkrUmJQT1FDcUp3QUFxRmhVQWV5ZE5CZ0xhQ1pyL3dEcVF3QUFVQU14RU5CYVFLQnBZdkNmWWFjQTlTRUFBS2lKZlRPRENhQkpEUDREcUJjQkFFQk5IRnpvTXhBUWFJeDRucGx2QWxBdkFnQ0FHaGs3ZW8yMWdFRDIyb1Avamh2OEIxQTMzaklCYWlRR0FvNGQyWndBY2hhRC85eitBOVNQQUFDZ1pzYVBXd3NJNUN1ZVh3Yi9BZFNUQUFDZ2hxd0ZCSExsK1FWUVh3SUFnQnF5RmhESVVhejlpK2NYQVBVa0FBQ29xYjFUYnRHQXZGajdCMUJ2QWdDQW1vbysydEdqWHFhQlBJd2EvQWRRZXdJQWdCcmJQenRnTFNCUWUrMjFmN09iRWdEMTVxMFNvTWFzQlFSeUVHdi9oSlVBOWVkSkRWQnpzUmJRUUVDZ3JxejlBOGlIQUFBZ0EyWUJBSFYxejZFYkVnQjVFQUFBWkNEV2FrM005U2VBT29tMWZ3Yi9BZVJEQUFDUWlaR1pJVDIyUUczRTg4amFQNEM4ZUpNRXlFVGNzbzJic2czVVJEeVAzUDRENUVVQUFKQ1JXQXZvaFJ1b1dqeUh4c3dtQWNpT0FBQWdJKzIxZ0Y2NmdZcDVEZ0hrU1FBQWtKbFl0MlV0SUZDVnAxdlBIMnYvQVBJa0FBRElrTFdBUUZVZW1ocE9BT1JKQUFDUW9WZ0w2QVlPNkRWci93RHlKZ0FBeU5USTlLQzFnRURQdEFmL1dmc0hrRFZ2amdDWmlvR0ExZ0lDdlRKKzNOby9nTndKQUFBeVppMGcwQXZ4bklubkRRQjVFd0FBWkN5cUFQWk9Hc2dGZEplMWZ3RE5JQUFBeUZ3TUJMUVdFT2lXR1B4bjZDaEFNd2dBQUJwZzM4eGdBdWdHZy84QW1rTUFBTkFBQnhmNkRBUUVPaTZlSythTUFEU0hBQUNnSWNhT1htTXRJTkF4N2NGL3h3MytBMmdTYjRvQURSRURBY2VPYkU0QW5SQ0QvOXorQXpTTEFBQ2dRY2FQV3dzSXJGNDhSd3orQTJnZUFRQkF3MWdMQ0t5VzV3aEFNd2tBQUJyR1drQmdOV0x0WHp4SEFHZ2VBUUJBQSsyZEdqWVFFRmdSYS84QW1zdmJJVUFEUmYrdXRZREFjbzBhL0FmUWFBSUFnSWJhUHp1Z0NnQllzdmJhUDhFaFFLTjVNd1JvS0dzQmdlV0l0WDlDUTRCbTg1UUhhTEJZQzJnZ0lIQXAxdjRCbEVFQUFOQncwZE1MY0RIM0hMb2hBZEI4QWdDQWhvdDFYaE56L1FuZ2ZHTHRuOEYvQUdVUUFBQVVZR1JtU0c4djhEYnhYTEQyRDZBYzNnWUJDbUF0SUhBKzhWeHcrdzlRRGdFQVFDRmlMYUFYZldCUlBBL0d6QWdCS0lvQUFLQVFzUlp3Wkhvd0FRU0hmNER5Q0FBQUNqSXh2OEZhUUNBOTNYb09XUHNIVUI0QkFFQmhyQVVFSHBvYVRnQ1VSd0FBVUpoWUMyZ2dJSlRMMmorQWNna0FBQW8wZHZRYWF3R2hRTzNCZjliK0FSVEwyeDlBZ1dJZ29Db0FLTS80Y1d2L0FFb21BQUFvbExXQVVKYjRlWStmZXdES0pRQUFLRlJVQWV5ZE5BZ01TbUh0SHdBQ0FJQ0N4VUJBYXdHaCtXTHduN1YvQUFnQUFBcTNiMll3QWMxbThCOEFRUUFBVUxpREMzMEdBa0tEeGMrM2VSOEFCQUVBQU5ZQ1FrTzFCLzhkTi9nUGdETzg3UUhRSGdnNGRtUnpBcG9sQnYrNS9RZGdrUUFBZ0xieDFpM2h3WVYxQ1dpR09QZ2IvQWZBMlFRQUFMeHAzL1JRQXByQm1rOEF6aVVBQU9CTjFnSkNNOFRhdi9oNUJvQ3pDUUFBZUl1OVU4TUdBa0xtclAwRDRIeTg0UUh3RnRFM2JDMGc1R3ZVNEQ4QUxrQUFBTURiN0o4ZFVBVUFHV3F2L1JQZ0FYQUIzdTRBZUJ0ckFTRlBzZlpQZUFmQWhmaUVBT0M4WWkyZ2dZQ1FEMnYvQUxnVUFRQUFGeFM5eEVBZTdqbDBRd0tBaXhFQUFIQkJzVVpzWXE0L0FmVVdhLzhNL2dQZ1VnUUFBRnpVeU15UW5tS29zZmo1dFBZUGdLWHdSZ2ZBUlZrTENQVVdQNTl1L3dGWUNnRUFBSmNVYXdFZE1LQis0dWR5ekt3T0FKWklBQURBSmNWYXdKSHB3UVRVaThNL0FNc2hBQUJnU1NibU4xZ0xDRFh5ZE92bjBkby9BSlpEQUFEQWtsa0xDUFh4ME5Sd0FvRGxFQUFBc0dTeEZ0QkFRS2lldFg4QXJJUUFBSUJsR1R0NmpiV0FVS0gyNEQ5ci93QllBVzl3QUN4TERBUlVCUURWR1Q5dTdSOEFLeU1BQUdEWnJBV0Vhc1RQWGZ6OEFjQktDQUFBV0xhb0F0ZzdhUUFaOUpxMWZ3Q3NoZ0FBZ0JXSmdZRFdBa0x2eE9BL2EvOEFXQTBCQUFBcnRtOW1NQUc5WWZBZkFLc2xBQUJneFE0dTlCa0lDRDBRUDJmbWJnQ3dXZ0lBQUZiRldrRG9ydmJnditNRy93R3dldDdZQUZpVkdBZzRkbVJ6QXJvakJ2KzUvUWVnRXdRQUFLemFlT3QyOHVEQ3VnUjBWaHo4RGY0RG9GTUVBQUIweEw3cG9RUjBsbldiQUhTU0FBQ0FqckFXRURvcjF2N0Z6eFVBZElvQUFJQ08yVHMxYkNBZ2RJaTFmd0IwbXJjMEFEb20rcFd0QllUVkd6WDRENEF1RUFBQTBGSDdad2RVQWNBcXROZitDZElBNkFKdmFBQjBsTFdBc0RxeDlrK0lCa0EzK0hRQm9PTmlMYUNCZ0xCODF2NEIwRTBDQUFDNklucVlnZVc1NTlBTkNRQzZSUUFBUUZmRStyS0p1ZjRFTEUycy9UUDRENEJ1RWdBQTBEVWpNME42bVdFSjR1ZkUyajhBdXMxYkdRQmRZeTBnTEUzOG5MajlCNkRiQkFBQWRGV3NCWFN3Z1F1TG40OHhNek1BNkFFQkFBQmRGV3NCUjZZSEUzQitEdjhBOUlvQUFJQ3VtNWpmWUMwZ25NZlRyWjhMYS84QTZCVUJBQUE5WVMwZ3ZOMURVOE1KQUhwRkFBQkFUOFJhUUFNQjRSZXMvUU9nMXdRQUFQVE0yTkZyckFXRTlNYmdQMnYvQU9neGIyRUE5RXdNQkZRRkFDbU5IN2YyRDREZUV3QUEwRk14OGR6Qmg1TEY5MytzeHdTQVhoTUFBTkJ6ZXljTlBxTmMxdjRCVUJVQkFBQTlGd01CclFXa1JESDR6OW8vQUtvaUFBQ2dFbnV0UDZOQUJ2OEJVQ1VCQUFDVmlENW9Bd0VwU1h5L20zOEJRSlVFQUFCVXhscEFTdEVlL0hmYzREOEFxdVd0QzRES3hGckFzU09iRXpTZDdSY0ExSUVBQUlCS2piZHVSUTh1ckV2UVZISHdOL2dQZ0RvUUFBQlF1WDNUUXdtYWFzOExXeE1BMUlFQUFJREtXUXRJVThYYXY0TUxmUWtBNmtBQUFFQXR4RnBBQXdGcEdtdi9BS2dUYjFvQTFJSzFnRFROcU1GL0FOU01BQUNBMnRnL082QUtnRWFJZzM5TS9nZUFPdkdXQlVCdHhGckFFUU1CYVFDSGZ3RHFTQUFBUUszRXVqUURBY21adFg4QTFKVUFBSURhR1hWN1NzYnVPWFJEQW9BNkVnQUFVRHV4RnRBTktqbUt0WDhHL3dGUVZ3SUFBR29wZXFnTkJDUW44ZjFxN1I4QWRlYk5Db0Jhc2hhUTNNVDNxOXQvQU9wTUFBQkFiY1ZhUUFjcWNtRHRId0E1RUFBQVVGdG4xZ0lPSnFnN2gzOEFjaUFBQUtEV0p1WTNXQXRJclgxM3J0L1FTZ0N5SUFBQW9QYXNCYVRPSHAwWlNnQ1FBd0VBQUxVWGF3RU5CS1NPclAwRElDY0NBQUN5TUhiMEdtc0JxWlgyNEQ5ci93RElpRGNwQUxJUUF3RlZBVkFuTWZqUDdUOEFPUkVBQUpBTkJ5N3FJcjRQRGY0RElEY0NBQUN5c25keU9FSFZyUDBESUVjQ0FBQ3lFZ01CclFXa1NqSDR6KzAvQURrU0FBQ1FuYjFUcWdDb2pzRi9BT1JLQUFCQWRxTC8ya0JBcWhEZmQrWlFBSkFyQVFBQVdiSVdrRjZMZy8vKzR3TUpBSExselFtQUxNVmF3TEVqbXhQMGlpMFVBT1JPQUFCQXRzWmJ0N0VIRjlZbDZEWnIvd0JvQWdFQUFGbmJOejJVb052MnZMQTFBVUR1QkFBQVpNMWFRTG90MXY0ZFhPaExBSkE3QVFBQTJZdTFnQVlDMGkzVy9nSFFGTjZXQU1pZXRZQjB5NmpCZndBMGlBQUFnRWJZUHp1Z0NvQ09pb04vVFA0SGdLYndwZ1JBSThSYXdCRURBZWtnaDM4QW1rWUFBRUJqeEpvMkF3SHBoQU9uK3F6OUE2QnhCQUFBTk1xb1cxczY0UDdEMXY0QjBEd0NBQUFhSmRZQ3VybGxOV0x0bjhGL0FEU1JBQUNBeG9uZWJRTUJXWW4yNEQ5ci93Qm9LRzlIQURTT3RZQ3NWRlNQdVAwSG9La0VBQUEwVXF3RmRKQmpPYXo5QTZEcEJBQUFOTktadFlDRENaYks0UitBcGhNQUFOQllFL01ickFWa1NiNDcxMjk0SkFDTkp3QUFvTkdzQldRcEhwMFpTZ0RRZEFJQUFCb3QxZ0lhQ01qRldQc0hRQ2tFQUFBMDN0alJhNndGNUx5cy9RT2dKTjZHQUdpOEdBaW9Db0R6aWNGL2J2OEJLSVVBQUlBaU9PaHhydmgrTVBnUGdKSUlBQUFveHQ3SjRRU0xScVlOL2dPZ0xBSUFBSW9SQXdHdEJTVEU0TCtKK2Y0RUFDVVJBQUJRbEwxVHFnQklCdjhCVUNRQkFBQkZpYjV2QXdITE5tb2VCQUNGRWdBQVVCeHJBY3NWQi85dkdmd0hRS0c4L1FCUW5GZ0xPSFprYzZJOHRrRUFVRElCQUFCRkdqOCtrQTR1ckV1VXc5by9BRW9uQUFDZ1dQdXNnU3ZLbmhlMkpnQW8yZG9FQUlXS3RZQmJybmdsMFh6ZmVuRmpPcmpRbHdDZ1pDb0FBQ2lha3ZBeVBOMEtld0NnZEFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUFTTko4QUFBQUFBQW9nQUFBQUFJQUNDQUFBQUFDZ0FBSUFBQUFBS0lBQUFBQUFBQW9nQUFBQUFJQUNDQUFBQUFDZ0FBSUFBQUFBS0lBQUFBQUFBQW9nQUFBQUFJQUNDQUFBQUFDZ0FBSUFBQUFBS0lBQUFBQUFBQW9nQUFBQUFJQUNDQUFBQUFDZ0FBSUFBQUFBS0lBQUFBQUFBQW9nQUFBQUFJQUNyRTBBQUVBdC9kVzcvLzlVaGE5TURxZHZ2YlF4bGVDMmpTK21lNGNPcHlyODB4Lzlqd2w2U1FVQUFBQUFGRUFBQUFBQUFBVVFBQUFBQUVBQkJBQUFBQUJRQUFFQUFBQUFGRUFBQUFBQUFBV3dCcENlK3kvLzZadUovRDN3bFlmVGswLzlWV0o1SG4zNHk0bVVUc3pOcDdtNXVmWmZINTZhYXYvUGs1Tm5mbjJoOWV2aHFlbEVjMzE0eHdmVDNYZDlMbFhoOSs3K1FqbzhXY2IzMTZkMmZpTDlkdXVyQ3AvNDlEOUxBTlNQQUFDZ2g5NS82M3NUUy9PakF6OXBCd0kvYnYzNi9XZCswQW9HcHRPUER2NGtrYi8rL3Y0MHZHVW8wVjBiK3RmN2N3YmdMUVFBQU5UU3U3ZmYzUDQxUXBOUGZmTE1MV1lFQXQ5NytvZnRRT0Q3clY4RkFnQUFTeWNBQUNBYmNhUDVrUTk5c1AwVkRrOU90UU9CYno3MTdmUzlaMzZZQUFDNE1BRUFBTm1LOHVhUC8xcDhmYXdkQm54MTlJbFdJUEFETXdRQUFNNURBQUJBSTBRWXNPZSt6N2YvK3NtLy9IWXJEUGlhSUFBQTRDeldBQUxRT0ZFUjhJMC8vdzlwejcyZlQ4TkRnd2tBQUFFQUFBMG1DQUFBK0FVQkFBQ05GMEhBbnozeTVmVHgyejZXQUFCS0pRQUFvQWlMTXdJZWZmakxxZ0VBZ0NJSkFBQW95dnR2ZlcrN0d1RERPejZZQUFCS0lnQUFvRGhSRGZEUWcxOU1kKzY2SXdFQWxFSUFBRUN4N3R6MTZmVDUzWjlMQUFBbEVBQUFVTFRmL3VRbjJsc0NBQUNhVGdBQVFQRmlTOERlQjc2WUFBQ2FUQUFBQUMwZitkQUhWUUlBQUkwbUFBQ0FOMFFsZ01HQUFFQlRDUUFBNEN3eEdQQlRPMzhyQVFBMGpRQUFBTTRSSWNEdzBHQUNBR2dTQVFBQW5HTkQvL3IwMElPR0FnSUF6U0lBQUlEemVQZjJtOXVWQUFBQVRTRUFBSUFMaUZrQVdnRUFnS1lRQUFEQUJVUXJ3Sjc3N2s0QUFFMGdBQUNBaTNqL3JlOU43N3ZsdlFrQUlIY0NBQUM0aER0MzNaRUFBSEluQUFDQVMxQUZBQUEwZ1FBQUFKYmdJeC82WUFJQXlObmFCRURQUFBtWDMwNmxtWnVmVHlmbTV0THcwRkI3cUY1OHZXdjd0dmF2T2ZtTjIvNjM5TlhSSjFxL2wva0VBSkFqQVFBOTk3LzhyNytSY3ZCZi90TTNVeFcrT3ZxMTlpR0RabnBnN3lPSk05cEJ3TGFiV3pmcnY1TGVmOHYvM0E0RjZpeitlWC9qdG8rbHI0OS9Jd0VBNUVnQUFFQWw0aWI5KzgvOHNQMFZocmNNcFR0M2Zib1ZCcnkzL2RkMTlPRWR2eUlBQUFDeUpRQUFvQllPVDA2bEI3NXlwa0lpYnRvLzF3b0Q2aFlFeEREQXFBVFFCZ0FBNU1nUVFBQnE1NXRQZlR0OTR0UC9yTjBTVXplMkFRQUF1UklBQUZCYk1ROGpnb0NvRHFpTHFBSUFBTWlSQUFDQVdvdkQvKzk4N2cvU2p3NzhKTlhCKzI3NTVRUUFrQ01CQUFDMUZ6MzN2My8zRjJvUkFyeDcrODNaclRBRUFBZ0NBQUN5RUNIQUgrNzVrMW9NNE50UzB5MEZBQUFYSXdBQUlCdG5OZ1U4bktyMlAyeTdLUUVBNUVZQUFFQld2alB4OStsN1QvOHdWU25hQUFBQWNpTUFBQ0E3VmE4SDNMSmxTd0lBeUkwQUFJRHNmUCtaSDFaYUJYRGQwR0FDQU1pTkFBQ0FMSDFuNHU5U1ZXd0JBQUJ5SkFBQUlFc3hDNkFxdzdZQUFBQVpFZ0FBa0tYWUNCQmZBQUFzalFBQWdHejk2TUN6cVNyYUFBQ0EzQWdBQU1qV2lmbTVWSlYrQVFBQWtCa0JBQURaMGdJQUFMQjBBZ0FBQUFBb2dBQUFnR3laeGc4QXNIUUNBQUN5VldVTHdOemNmQUlBeUlrQUFJQnNWVmtCY0VJQUFBQmtSZ0FBUUxZMnJPOVBBQUFzalFBQWdHeGR0MlV3VmNIMkFRQWdSd0lBQUxLMG9YOTlldGYybTFNVkJBQUFRSTRFQUFCazZYMjN2RGRWNWFYNWt3a0FJRGNDQUFDeTlPRWR2NUtxOHVNREJ4TUFRRzRFQUFCa1ozaG9LSDM4MXo2V3F2S2pBejlKQUFDNUVRQUFrSjBxRC8vQkNrQUFJRWNDQUFDeUVyZi9kKzc2ZEtyUzk1LzVZUUlBeUkwQUFJQ3NWSDc0Zi9vSENRQWdSd0lBQUxKeDU2NDdLaS8vLzlGQi9mOEFRSjRFQUFCazRlTzNmYXp5Mi8vd045Lzkrd1FBa0NNQkFBQzFGNGYvUGZkOVBsVXRodi9wL3djQWNyVTJBVUNOUmRsL0hXNyt3L2NjL2dHQWpBa0FBS2lsbVBZZnQvN3Z2L1c5cVM2KytaZi9id0lBeUpVQUFJQmFXVnp6Vi9Xd3YzTWRucHhLMzVuUS93OEE1RXNBQUVEbE5xeGZuejc4b1Y5SnYzSGJ4MnAxNDM4MjVmOEFRTzRFQUFEMDFQRFFZTnJRMzUvZXZmM205TzV0TjZmM3RRNzg4ZGQxOTlYUnJ5VUFnSndKQUFCNjZCdFAvUHRVcXVFdFF5bFhUejcxN1hSNGNqb0JBT1JNQUFEUVF6a2Zna3ZtOWg4QWFJTExFd0J3UVhINGQvc1BBRFNCQUFBQUxpQW0vMzk5L0JzSkFLQUpCQUFBY0FFUDczczhuWmliVHdBQVRTQUFBSUR6aU5MLzcwejhmUUlBYUFvQkFBQ2NJMHIvdnpyNlJBSUFhQklCQUFDY0pRNy92M2YzRnhKQXlmclhuRTVBOHdnQUFPQU4wZThmaDM5VC80RzZtRHRkemV0Ni8rV3ZwVklNclgwbFZXSHU5Sm9FdlNZQUFJQTNPUHdEZFRQM1dqV0h4UDdMVlFCMDI5eHJqbUwwbnU4NkFHaDU0Q3VQcEI4ZitFa0NvS3dLZ0MxWFZGVUI0Q2hHNzYxTkFGQ3dLUHQvWk4vajZjbW52cDBBNnFhcVErSzJ2bE9wRkZ1cWFnRjRUUXNBdlNjQUFLQllpejMvYnY2QnVwcXY2SkM0NVlwWFV5bldyNm1tMm1IK2RSVUE5Sjd2T2dDS0ZOUCtmK2R6LzhMaEg2aTF5VmV2U0ZXSUZvQlM1Z0JzWDdlUXFqRDU4anNTOUpvQUFJRGlmUC9wSDdRTy8zOWc0QjlRZTFXV2lXOWIxL3cyZ0cwVkhmNURWZUVPWmRNQ0FFQlJIdDczZVByNitEY1MxWm1ibTB0VjZlL3ZiLzIvWlFRL0cvclhweXBFZFEyZE0vbHFkYS9yMi9vVzBqTS92eW8xMlphMUw2ZXFUTDNpS0VidnFRQUFvQWcvT3ZDVGRFZnIxdC9odjNwemMvT3BLdGNORGFaU25Bazd5TjE4aGJ2aXQ3K2orUlVBdDF6MTgxU1Z5VmRVQU5CN1lpY0FHaTBHL1gxOS9DL1NWMGVmU0ZEVnJYZ1Zob2VHVWhWT1ZCandOTkdCVTMycEtqczJ6TFd1cVZPamJhK3d6ZUhnUW5YL2JpbVhBQUNBeHZxYmliOVBqK3g3VEs5L3pid3dWZDIvaitFdDFSeUtTMUpsaTBjVHpWZTRLejRHQWQ1eTVjbkd0Z0cwZjM5WG5VeFZPTEN3TGtFVkJBQUFORTRNK1h1OGRlUC8vV2QrbU9Cc0pRVUE3OTUrYzZyQ1MvUFZIS2lhS3NyRTUxb2hRRlVUK2VPQTNOUUFZRWQvZFdIVmxBR0FWRVFBQUVBalJObnhkeWIrTGozNWw5OTI4Sys1S29mRVZWVVczMnZSNmxCVnU4UGs1R1Npc3lJRXFHcFYzVzN2ZkRHTkhiMDJOVkdWQVVDVnJSMlVUUUFBUU5aaXVGOGMvR080bjk3amZNUy9xeW9PcUZYZGl2ZmF1N2RWOS90OFFjdE54MFd2ZUZVQndKWXJYbWxrRzhCUTYvZTFvLzlFcXNwQkxRQlV4QllBQUxJV0pkME8vL21wcWs4OFFvZmhMYzNmQlBDdUNvTU9hd0E3citwKzhWM1hIRWxOYyt1VjFiYXFQSE95bklHazFJc0FBSUNzeFlIdWkvZmVuY2pManc0OG02cnkvbHZlbTVydS9iZjhjcXFLTUs3enFqNHN4aHlBdURGdmtzOVVHR3BFb0ROMzJqR01hdmpPQXlCN0gvblFCOU9uZHY1V0loOG41cXZydlMyaERlRGQyMjlLVmZueHdaOGtPbXZxbGJXVkh4aDNiV3BPRlVETU5kaFNZYUJ4VVA4L0ZSSUFBTkFJZCs3NmRCb2VhbjVwZDFQRTdJYXFmSGpIcjZRbWkwR0hWVzA3aU50L0ZRQ2ROM2Q2VGVXSHh0czJ2dGllQlpDN3FHVDRUTVV0RFUzZHFrQWVEQUVFS0VEMDVIYXpMemNPRzFXdlY0dFdnRDMzM1oxKy8rNHZKT3F2MGswQXJlL1Y5OTN5M3NadWkvandoejZZcXZMakF3Y1QzWEZnb2EreW5mV0w3dG84blQ3MzNDK2xuTVU4Z3kwVnR6TUlBS2lTQUFDZ0FFOCs5ZTMwMWRFblVyZThhOXZONld0Zi9YZXBhdSsvOWIzdFZvQ3ZqLzlGb3Q1K2RMQzZHUUFodmxlYUdnRDg1bTBmUzFYNWtmTC9ycG1ZNjA4N0I0NmxLbTNyTzVWMmI1NUtJek41cnRPTTB2LzRxbEwwLzhkYVI2aUtGZ0FBVmkxNmZyODYrclZVQjFvQjhoQVZBRldXaWpkMVprU1UvMWU1QWVCN1R6Y3pWS21EZ3pVWkhMZHpZTGJ5US9SS1JPbi83c0hxTjFSTXpHMUlVQ1VCQUFBZEVSVUdWZloxTDRwV2dJY2UvR0tpL2lZcmJBT0k3NVAzTlhBYlFBUmdWVklCMEQweEI2QXVxK04yRDA2bmJldE9wVnpFNGYvaDY1OUwvWmVmVGxXTFNnNm9rZ0FBZ0k3NTBsY2VTWFVRVTk2clBnaHhhZDk3NWdlcFNuZnV1aU0xU2R6K2YvelhxaXYvUHpOclpEclJQUlB6OVRnODlsLytXbnI0bi93c2l4Qmc4ZkJmZGQ5L2lOTC9nd3MyQUZBdEFRQUFIVk92Vm9BNzJyTUpxSy8vZHFENk9RQk5xZ0tvT3ZUNmJ4WFBkU2pCeEluKzJ1eVBYd3dCZHF5dmJxWG5wZFRwOEIrVS8xTUhBZ0FBT3FvdXJRRGgzeno0UisxU2IrcXBEa1A0N3Ivdjg0MzRIcW42OWovODUrLytYYUs3NnJBTzhHd1JBanl3OVZCN3NuN2RSRER4K0kzUDF1YndIL1lmSDBoUU5RRUFBQjFYbDFhQVdQZjJ6ei9UckRMdkp1bjJlc3FsaU8rUlQrMzhSTXJkbmxhUVViV3FXenBLTVhyMDJsUTNuMmtGQUhIVFBsU0R3L2I2eTArMzF4VkdNRkdIbnY5RlQ1Kzh5dlIvYWtFQUFFREgxYWtWNExjLytZbEdEbnRyaXUvVm9Bb2cya1Z5L2g2SmYvNW9aNmlTL3YvZWlSM3lkV2tET05zdFY1MU1UOXgwc0YwTlVFVVFFQWYvK0wvOXhNMEgwdTBWcjBzOG4yKzl0REZCSFFnQUFPaUtPclVDTktYTXU0bnFzall1dmtkeVhCOFpjeTdxTVBEeU94UEsvM3RwZkhaVHFxdkZhb0I3aHc3M0pBZzQrK0FmLzdmcmRPdS9LRzcrbnhJQVVCTUNBQUM2NWcvMy9FbWx1OTRYYVFXb3IvOWNrNE5qZkkvRStzaWNncUxvKzQ4NUYzWHdOOS85KzBUdjdKOGRxR1VWd0tMb3U3OXQ0NHZ0aW9BSUEyNTc1NHNkRFFQaTBCOS8vL2g3MS9uZ3YyaXNobTBibEd0dEFvQXVpYkxnYUFXNCs2N1BwYXBGSzBEY1V0Wmg4QnkvRUFGUlZBRlVYY0llWW4za293OS9PZjMrM1Yrb1JYQjFNWEg0LzdOSC9uVTd1S2hhL0p6N3VlcXRHQVlZVlFCMUhMNTNybWdOaUs5d1pnM2V1blJnb2ErOURpOUNqUGovbTdwQWIzeUVCakZvY01zVnI3YStYazdiM3JHUWJtMzl2ZW93YTJDcDNQNVROd0lBQUxycTYrUGZTQi9lOFN1MU9PREZEZTl2ZmZwL3IvM2hyalFSek5UaCt5TkVDUEFmSC85MzZmYysvNFYwZUtxZVBlMVI5aDgzLzNVNC9JYzZ6SEVvVVZRQjdCdzRWdXViNzNORlpVQjg3ZWl2NytyQVRuUDdUOTFvQVFDZzZ4N1krMGd0RHQxUjN2M0ZlKzlPMU1zM24vcDJyVUtaT0ZqLzJTTmZydVZnd0UvdC9LMzB0YS8rdTlvYy9zT2Z0MEkrZW0reENvRDZjdnRQSFFrQUFPaTZ4VmFBT3ZqSWh6N1lQa1JSSDNINHI5c1F1Y1VRSUNiczEwR1UvRWQ3d3QxMzNabnFKQVo5L3JnbXd6NUxWUGRaQUtWeiswOGRlV0lBMEJQUkNsQ1hpZTh4TlQzSGllOU45dVJmZmp2VlVYeXZmT09KZjU4K2Z0dkhVaFUyckYvZkRpSCtZK3ZXdnk1dEVtZjd1dHYvU2tVVndNaDBmYXBCK0lXblh0em85cDlhRWdBQTBETjFhZ1hZYzU5V2dEcUpJWEoxQ1lqT0ZkVUFlKzc3L0p0QlFCekt1MjN4NFA4WGYvNGYyaUZFSGJjVFJHWFBrMC9WTTdncFNSd3luemw1VmFJK292Ui83SmpiZitwSkFBQkF6OVNwRlNCdVU3VUMxRXZkRDVPTFFVQWN5dmZjKy9uMGtSMGY3R2dZRUZVcG45cjVpWGFwLzEvOVAvOTNiUS8raXh6KzYyUHYxTEJXZ0JxSjB2L0pDMncyZ0tyWkFnQkFUOVZwSzBBY3NMN3ozYit0N2JUMzBzUXd3TTlGZTBhTkJ0eWRUeHpLUC81ckgydC9oZWlEYjM4ZFBOTVBIMVV1RVhhZG1EOS90VXNjOURmMDk3YzNEdlMzL2w3djNuWnorK2VoN3IvdnM3bjlyNWYyamZPUnpXbjM0RlNpV2tyL3FUc0JBQUE5RjYwQXNXcXQ2dHZOeFZhQTJQdE9QVHcrK2tTNnYzWExucE00eU1kWFNlTHdmM2hTY0ZZbjQ4Y0gwcmErVSttMmQ3NllxRVlFTVNNelpqSlFiMnFGQU9pNXVyVUNSQ1VBOWZETjlzSFNMV2FkbmZuNWZTSlJQeVBUZzByUEt4SXRHUGNjdWtFckJyWG5PeFNBU3RScks4QWQ2VjNieXJyQnJiTXZmZVdSUkgwNS9OZFhiQVdJUTZnUW9QZjJIcjdPbnp0WkVBQUFVSm02YkFVSS8rYkJQNnIxd0xXUzFIa2pRT21pOUYvdmY3M0ZJWFRQQzF2ZFJQZlE2TkZyMDhSOGY0SWNlRElBVUprNnRRTEVBTFovL3BrN0V2VlFwM0NJTStMZlIxMStYcm00Z3d0OTZlNmZLVWZ2aFRqOHg5Ui95SVduQWdDVnFsTXJ3RzkvOGhQcGZiZFV2NTJBZW9WRG5CSC9QZ3oreTRjUW9Qc2Mvc21SSndJQWxhdlRiVzlNb05jS1VBOTFDb2RLRjJYLzhlK0R2QWdCdXNmaG4xeDVHZ0JRT2EwQVhNaTlleDYwRmFCaXFqSHlGaUhBNy83alRRYlVkZEMrbVNHSGY3SWxBQUNnRnJRQ2NENVJHZkovZlBGUHpBT29TUHk1Lzk3ZFgxRDZuN2s0L01kMmdJTUw2eElyRjVVVVVWR3hmM1lnUWE0RUFBRFVobFlBenVmSEIzK1NIdDczZUtMMzlQMDNSNFFBbi92SG05cWw2eXpmZ1ZObktpbWUrZmxWQ1hJbUFBQ2dOdXJXQ3ZERmUrOU8xTU0zbi9xMk12UWVpejl2ZmYvTkU2WHJleWVIdFFRc3cvanNwdlM3ei8yU1B6TWFRUUFBUUszVXFSWGdJeC82WVByVXp0OUsxTU5YUjU4UUF2UkkvRG5IbnpmTjlOUkxHOXN0QWZFckZ4WUgvaWo1SDVrWlROQVVBZ0FBYXFkT3JRQjM3dnAwR2g3eThsY1hRb0R1Yy9ndlF4eHVveEpBTmNENVJhdUVrbithU0FBQVFPM1VxUlVnNWdEc3VVOHJRSjBJQWJySDRiODhVUVZ3eDdQYjBzajBrQ0NnNWVtVFY3WC9QS0pWd3ZwRW1zaDNOUUMxVktkV2dQZmYrbDZ0QURVVGgxU0RBVHNyL2p3ZC9zczFmbnlnM1JZUU45OGxCZ0Z4OEk5eS8vZ3pFSVRRWkFJQUFHcExLd0FYRXlIUkhYZitRYnRpaEpWcnIvcjcvQmNNL0tOOThJMmI3emdFbDlBYUVEZjhUNzI0OGMyRHYzSi9TaUFBQUtDMjRtRDN3RmNlVG5XZ0ZhQ2VZa1hnNzkzOXI5S1BEdndrc1h6eDUvWTduL3NYNmZ2UDFLUGFobnFJZy85aWE4Q2U1N2MyYmxoZzNQYkhZTDg3ZnJJOTdaMGFkdkNuS0FJQUFHcnRPeE4vbi83bXUzK2Y2a0FyUUQxRlVQUTduL3NEY3dHVzZldmpmNUYrLys0dnRQNzhwaE5jeU1UOGhuWTFRSVFCOFdzY25uTVUvOXpSM3ZEcDF1OGpidnRqdFo4ZWYwcTBOZ0ZBelQyNDkrSFc0ZnMvdEcvaHEzYjNYWGVtN3ozOWcvYk5NL1VTL2V0UFB2Vlg2YzhlL3RkcGVNdFE0dndpTVBuU1Z4NXg2OCt5UkZYQTVDc2IyOVVBL1plZlRyZGNPWjkyYkpoTDI5YWRTdHZYTGFTNmlYL2VPUFQvb0hXN1B6RzN3V0VmM2lBQUFLRDJva2M1V2dFZWV2Q0xxUTcrellOLzFMNXhyc3Q4QW40aERyZWYrUFEvUzUvYStZbjAyNjB2UWNBdnhQZHIzUHBIcjcvdlhWWWpEdE5SR1JCZllURVEyTmEzMFByMVpPcGY4MXBQUTRFNDdCOVlXSmVtWG5sSGV1YmtsZW1abjY5MzRJY0xFQUFBa0lYRlZvQ1BmT2lEcVdweHFQem5uN2tqUFRKaUNuMWR4U0Uzdm1kaWVPUEhiL3RZS3QzM24vNUIrdExlUjVUNzB4WG5CZ0loUW9HaEsxNU9XOWEra3JhODQ1VTB0UGJWdFA3eTE5S1dLMTVwLytmbi9ucWh2Ky9jYTJ2YWZ4MkgvTVgvK1NjdnIydi91bmpvZDlpSHBSTUFBSkNOT3JVQy9QWW5QOUU2WVA2ZE11b2FPek5FOHBGMmEwQ3BRVUFjL0I5di9mNTluOUpyN2NQNlFsODYyUHBLQ2s2Z05zUmxBR1Jqc1JXZ0x1Ni83L08xQ0NPNHVNVWdJRm9Ebm56cTI0MWZHM2ltMVA4YjdkVitzU0hCNFIrQVJTb0FBTWhLbEhYSElhNE90N2xhQWZLeUdBU0UzMmg5Ly96bWJmODB2ZS9XWDA1TkViZjlmOVA2K2ZobTYrZERqejhBNXlNQUFDQTdqK3g3UEwzL2x2ZldZc0NiVm9BOHhTRTV2dUo3Nk1NN1BwZyswdnJLTVF5SVEvLzNXdDk3VC83bHQ5UGhLZjM5QUZ5Y0FBQXVvS29TVWJjMnplYjdxalBpOXhOcnpLSUV2dzd1L093ZDZkNHZQdWpuTjBQeE14bmw4dkVWWWNEN1dzRlNoQUh2M241ekxUY0l4RDl2Vk1IOHR3TS9TZis1RlR6NW5nTmdPUzc3d0VkLy9mVUVBTUJiUkFEdzdtMDNwZmZmK3N2dFg5KzFmVnRQWno3RVlmOUhyWU4rM094L3IzWFRIMVVtRHZ3QXJJWUFBQUJnaVNJQWVOZTJtOXUvUnBYQWh2NytORHcwK0dZd3NGZzFjTEhxZ1RqRXo4M050Zjg2RHZrdlRFNm51Zm41MXE5VDdmOHNEdjJUVTFNTyt3QjBuQUFBQUFBQUNtQU5JQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUFBQUJSQUFBQUFBQUFGRUFBQUFBQkFBUVFBQUFBQVVBQUJBQUQvdlIwN0VBQUFBQUFRNUc4OXlJVVJBQUFEQWdBQUFBQUdCQUFBQUFBTUNBQUFBQUFZRUFBQUFBQXdJQUFBQUFCZ1FBQUFBQURBZ0FBQUFBQ0FBUUVBQUFBQUF3SUFBQUFBQmdRQUFBQUFEQWdBQUFBQUdCQUFBQUFBTUNBQUFBQUFZRUFBQUFBQXdJQUFBQUFBZ0FFQkFBQUFBQU1DQUFBQUFBWUVBQUFBQUF3SUFBQUFBQmdRQUFBQUFEQWdBQUFBQUdCQUFBQUFBTUNBQUFBQUFJQUJBUUFBQUFBREFnQUFBQUFHQkFBQUFBQU1DQUFBQUFBWUVBQUFBQUF3SUFBQUFBQmdJRFBJOHpTRmJibGNBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6Ijk1ZTRkNThjMDU2ZTRhNjU4NjZkZjVhNjk2NTllODgwIiwib3B0aW9ucyI6eyJwbGF0Ijp0cnVlLCJyayI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTAwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJpbnRlcm5hbCJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZmlybXdhcmVWZXJzaW9uIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTAxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMS0wMSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjUxZmZhYjJlMzBhODdjY2ZkYTRjY2ExM2Y1YzBhMjNhNzBiOTA3NzMiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNTFmZmFiMmUzMGE4N2NjZmRhNGNjYTEzZjVjMGEyM2E3MGI5MDc3MyJdLCJkZXNjcmlwdGlvbiI6IkFyY3VsdXMgRklETyAyLjEgS2V5IENhcmQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MTAsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo2LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQzVEQ0NBb3FnQXdJQkFnSUpBSjFtZ1grVEtpSDdNQW9HQ0NxR1NNNDlCQU1DTUlHQU1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLVG1WM0lFcGxjbk5sZVRFUk1BOEdBMVVFQnd3SVUyOXRaWEp6WlhReEZEQVNCZ05WQkFvTUMwTnZiWEJ2VTJWamRYSmxNUkF3RGdZRFZRUUxEQWRCY21OMWJIVnpNU0V3SHdZRFZRUUREQmhEYjIxd2IxTmxZM1Z5WlMxR1NVUlBMVU5CTFZKdmIzUXdJQmNOTWpNd01URXpNVGMxTlRNd1doZ1BNakExTXpBeE1EVXhOelUxTXpCYU1JR0FNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0F3S1RtVjNJRXBsY25ObGVURVJNQThHQTFVRUJ3d0lVMjl0WlhKelpYUXhGREFTQmdOVkJBb01DME52YlhCdlUyVmpkWEpsTVJBd0RnWURWUVFMREFkQmNtTjFiSFZ6TVNFd0h3WURWUVFEREJoRGIyMXdiMU5sWTNWeVpTMUdTVVJQTFVOQkxWSnZiM1F3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVIzTmxzbHBFcFgvQmlaOVJwV0UrcXJtMklSTUxpM2Jrc2RhSFNwQTgrb3pVYUZhdlQ0TDBwUFNMQmhuVFJGMTVDYVRISk1jRVVHdWdyL3hvR1RkTE5wbzRIb01JSGxNQjBHQTFVZERnUVdCQlI0ejc4c1RtYWl3SEJ3MGZ6VjY2VzZmbC85V0RDQnRRWURWUjBqQklHdE1JR3FnQlI0ejc4c1RtYWl3SEJ3MGZ6VjY2VzZmbC85V0tHQmhxU0JnekNCZ0RFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DazVsZHlCS1pYSnpaWGt4RVRBUEJnTlZCQWNNQ0ZOdmJXVnljMlYwTVJRd0VnWURWUVFLREF0RGIyMXdiMU5sWTNWeVpURVFNQTRHQTFVRUN3d0hRWEpqZFd4MWN6RWhNQjhHQTFVRUF3d1lRMjl0Y0c5VFpXTjFjbVV0UmtsRVR5MURRUzFTYjI5MGdna0FuV2FCZjVNcUlmc3dEQVlEVlIwVEJBVXdBd0VCL3pBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlCcGVLRk52ekZ2bit6WThjUWRtRkdydGwwMUp4eWxsYXZscXh1dGMyeHRSZ0loQU8wMWVGc1V2VERka1RlSG05ZUF2d0xQNXZYTklyVTNNT3hqd2FJbHRhT1kiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBWUFBQUJ6ZW5yMEFBQUFBWE5TUjBJQXJzNGM2UUFBQVhKSlJFRlVXRWZGbHR0cXhDQVFobjlEWVZ0VFNzbXA3Lzk2U1RhRlVoZDZFNWN4YTlsa2xlaVkybHp0Z283Zi9ITVVBRFFPL0lRUTBEcmNwRWdGaUgxdzYyc3lnRFhJQlRrTXdBVVNBblVNUUlLVmhLdUx6eTRESVo3L0twYWFoQ3NDaGp1TUsrczhQbFZ2K1BuOGd0QzhlbVlEMEVVSUFkblVVTVBJN2lUQkFMNkRaZHZrQWZBMWtIOERJS0N5cXdCZDVGYWdnT3dxazNUMnk1SUQ1ckZDNEVtV09MMDhyeUtTRDRCa2I1dUhqTThPb0FYeWhlQysvRnpla3h4cUhIbGR5TlBLdlUzbHRXc2ZsZzNxKzkvOThMZU55QTRYcndJNU9xR3ArMXNDV2lCYXZlaTNUY0tZS1JnOERiY3RtTUpBa3BkMWJjclM1RUF1QmF3SzlLQlY0ekpOa1BXNzZZaVlOZFQ1N0Y4VUhKa1NOSXhjbGFDR0NjQzhnSWdacXFmL3R5L0lhaFFuVGQ1bDNiNVBSS3RFMWhDUWMvS2pCdWIwK1B0V3V0MmF0bE13TlFIakFEWnhsZDB5RXk0OWZ4dUtBM0Rva3JxTUpBUHN4aXJnUUVUQkJGaGpIT0VCOEc0NThhSk1jWHI5bmloWEtSR3dBWkQ3bHNjQUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0xMS0xNSIsInVybCI6Imh0dHBzOi8vd3d3LmdldGFyY3VsdXMuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQXJjdWx1cyBGSURPMi9VMkYgQ2FyZCIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMjIxMTE1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMTEtMTUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAyLTIyIn0seyJhYWd1aWQiOiI5YzgzNTM0Ni03OTZiLTRjMjctODg5OC1kNjAzMmY1MTVjYzUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjljODM1MzQ2LTc5NmItNGMyNy04ODk4LWQ2MDMyZjUxNWNjNSIsImRlc2NyaXB0aW9uIjoiQ3J5cHRub3ggRklETzIiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDUVRDQ0FhS2dBd0lCQWdJR0FJRkRVWFFyTUFvR0NDcUdTTTQ5QkFNRE1FOHhDekFKQmdOVkJBWVRBa05JTVE4d0RRWURWUVFJRXdaSFJVNUZWa0V4RkRBU0JnTlZCQW9UQzBOU1dWQlVUazlZSUZOQk1Sa3dGd1lEVlFRREV4QkRVbGxRVkU1UFdDQlNUMDlVSUVOQk1CNFhEVEl3TURZeE5EQXdNREF3TUZvWERUUTVNVEl5T1RJek5UazFPVm93VnpFTE1Ba0dBMVVFQmhNQ1EwZ3hEekFOQmdOVkJBZ1RCa2RGVGtWV1FURVVNQklHQTFVRUNoTUxRMUpaVUZST1QxZ2dVMEV4SVRBZkJnTlZCQU1UR0VOU1dWQlVUazlZSUVsT1ZFVlNUVVZFU1VGVVJTQkRRVEIyTUJBR0J5cUdTTTQ5QWdFR0JTdUJCQUFpQTJJQUJHaGNpa3VSWWdOa2FrMHBPOFhnUFd3RzlSWlhMUWVxUUV2S0hmQ24zN2dhUjVVOXJocDRXOEpUYmZVOXQ4Q0ZnRDBEeE5YRUpFOUtHTm5MQXRMNzA4aENIZW82UzVvZXpuR0RGbjlKODBiTzdiZFNEWUhTNWJ6a0VLUExOdWFtV0tORk1FTXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVZHJFdFV5V2FNdHBWQVE3SkdxUXAzanpOU2hjd0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNREE0R01BRENCaUFKQ0FiV2EveGNLeDdLQ2NvVXNwOFNWWm5XU3hEOG45MVRxQ0pLYWpzN2tKQnoyRHp2Wlp0UHhLc01ZMzhsSC84TVlUQzN3bFJ3ZFpjNXM2MUVobGJkbk9ndUJBa0lCRm1KTHNPUHlNUVdVeG1XbDJ6dUFTN2N0cVUwM1U3NEMzVVVIU0tESDNXU0pIK3kzaS9Yc0NzL0ZNK0RrLzNGak9nUVR4aW9hcUljM2hyd2hQbG1vck5vPSIsIk1JSUNXVENDQWJxZ0F3SUJBZ0lHQUlGRFVYUXBNQW9HQ0NxR1NNNDlCQU1FTUU4eEN6QUpCZ05WQkFZVEFrTklNUTh3RFFZRFZRUUlFd1pIUlU1RlZrRXhGREFTQmdOVkJBb1RDME5TV1ZCVVRrOVlJRk5CTVJrd0Z3WURWUVFERXhCRFVsbFFWRTVQV0NCU1QwOVVJRU5CTUI0WERUSXdNRFl4TkRBd01EQXdNRm9YRFRRNU1USXpNREl6TlRrMU9Wb3dUekVMTUFrR0ExVUVCaE1DUTBneER6QU5CZ05WQkFnVEJrZEZUa1ZXUVRFVU1CSUdBMVVFQ2hNTFExSlpVRlJPVDFnZ1UwRXhHVEFYQmdOVkJBTVRFRU5TV1ZCVVRrOVlJRkpQVDFRZ1EwRXdnWnN3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ01EZ1lZQUJBRUp0bXJNWWM0OG5QU3AwUlJtRXdUMlU1YXEwRDFiM1VSTHBtSlAyNzdJbUVYS0VialZRQThQM1V5VGRaaW5FTFRRNWc2RStsbk4zR2hVV2lmMi9WbVNiUURudTlmK2VieUlaZkJhYm9zS0szU1FWdjRLbXVQOXBiMGY3UDJ2TVBBVUZKTlp2S2VIMURQdGFaa0Z5Yk1LWnNnOENKRXM3QTlLVzNSSS84UURwTjFuSjZNL01EMHdEQVlEVlIwVEJBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVVVuZkxPRERha3UxbzhDU3V3V2ZXeWxqNE92QXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUVBNEdNQURDQmlBSkNBS2Q4RGVOaGJQZXlmaDdVRDNNOWxQcDVhNzdNMUxtQzJNMm83elJpSGxlUHQrWGNyL0kveEdLMTI0Z0V1SGpiT2Z5YW5yZTYzRU1UdVZXOHRzNWtSOTA2QWtJQmdTSWhKb0VOa01WRmJlTVJVRG5EdGJ2K2dLaStodHFPUkd5c2lkNXNnMlZ2Q1g5UWZuVXFCS3RaVlVCZVFWUGszRTVHVUVhbUxrNGpsamR2bERHU1hwVT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRUFBQUFCQUNBTUFBQUNkdDRIc0FBQUJoV2xEUTFCSlEwTWdVSEp2Wm1sc1pRQUFLTStWa1QxSXcxQVVoVTlieFNJVk80aUlPR1NvTGxxUUtpSTRXWVVpVkNtMVFoV1gvTlMyMEtRaGFYRnhGRndMRHFLTGY0dWpreTRPRHE1T2dpS0lrNE83NktJbG5wZUlMZElPUGtqdWw4TzlKKytkQi9qUFM2cHVkNHdEdWxHeDBvbTRsRjFkazdwZUVFSVEzUmpGakt6YTVtd3FsVVRiOVhFUG42aDNVZUdGLzYwZUxXZXJnRThpTDZtbVZTR2I1S25OaWluNGpOeW5GbVNOZkVVZXM3aEI4cXZRRlkrL0JPZGQ5b2NGVzVuMEhEbENEdWViV0dsaXRXRHA1RWx5Uk5NTit2dXpIbXVDdDhneHZWUlZmL1lwVGhqS0dTdkxRdWN6aEFRV3NJZ1VKQ2lvb29nU0tvaXlHbFNTYnMxQmhzVXZHMmwyeDVseGE3OUIxeTlGRjRVdVJhaWNtVWNaT3VlRkQ4U2QvTTNhM3BpSWVVNGhPbmMrTzg3Yk1OQzFDOVJyanZONTdEajFFeUR3QkZ3YmpmbnlFVEQ5VHIzVzBDS0hRTzgyY0hIVDBKUTk0SElIR0hnMFpVdit2UzMrMjh1Tkt5QmVwdzlBaGxrbGI0SDlBMkFrVDYvMU51Y01OdWZXcHFmZjdXbVpIL0FOaGN0MFNPd2g1cEFBQUFMQlVFeFVSZi8vLy92NysvSHg4ZXpzN092cjYrM3Q3ZlQwOVA3Ky90emMzSjJkbldscGFUNCtQaU1qSXhZV0ZoQVFFQThQRHhFUkVSb2FHaXNySzA1T1RueDhmTFcxdGQzZDNZR0JnUUFBQUFnSUNFbEpTYUtpb3ZEdzhOVFUxRmxaV1FvS0NnY0hCeDRlSGtORFExNWVYbTF0YlhCd2NHcHFhanM3T3hjWEZ3VUZCUmtaR2VucDZXdHJhMkppWXF5c3JPTGk0dno4L05uWjJaNmVubEpTVWcwTkRSTVRFNHVMaS9iMjlyUzB0QjBkSFFJQ0FqWTJOcWFtcHZQejgrL3Y3OVBUMDgzTnpkYlcxdVhsNWZMeTh1cnE2cEdSa1NRa0pERXhNY3pNelAzOS9YcDZlaWNuSjY2dXJxZW5wMk5qWXk0dUxnRUJBUU1EQTdpNHVQbjUrWk9Ua3hRVUZBd01ESmFXbGxkWFYzbDVlZlgxOWN2THkxOWZYd3NMQ3hnWUdPVGs1T2JtNWxSVVZIRnhjZnI2K2sxTlRicTZ1aDhmSDRPRGc0aUlpSDkvZjJkblp6OC9QeElTRW9tSmlmZjM5NCtQajVTVWxGaFlXQ2twS2RyYTJqSXlNbzZPanZqNCtMNit2bWhvYURRME5MR3hzWDE5ZmJhMnRvV0ZoUlVWRlpDUWtNckt5aHNiRzl2YjJ6azVPWWFHaGxOVFV6QXdNQ0VoSVNVbEpUbzZPbVZsWmFHaG9lZm41K2pvNkdCZ1lISnljaHdjSE1IQndjZkh4MUJRVUlLQ2dscGFXdC9mM3pVMU5WVlZWUVFFQkZ4Y1hPN3U3dERRMERNek0rSGg0YUNnb0VwS1NydTd1NUtTa3RmWDE4VEV4TWJHeHQ3ZTNrUkVSRlpXVnF1cnF3a0pDWmVYbDNoNGVLaW9xRHc4UExLeXNvMk5qU0FnSUZ0Ylc3Ky92MGhJU0ppWW1NN096blYxZFl5TWpKK2ZuNXFhbWtKQ1FsRlJVYnk4dkdGaFlRWUdCbk56YzgvUHo0U0VoTkhSMGIyOXZabVptYm01dWRMUzBpWW1KaTB0TFE0T0R1RGc0RGMzTjdDd3NNREF3R1ptWmlnb0tFWkdSc25KeVRnNE9KV1ZsVXhNVEtTa3BLT2pveW9xS29lSGgrUGo0Nm1wcWRYVjFVZEhSOGpJeUp1Ym0xMWRYYk96czNSMGRHOXZiMjV1YnJlM3QwVkZSVXRMU3lJaUlxV2xwVUJBUUNyQTNOWUFBQUFKY0VoWmN3QUFMaUlBQUM0aUFhcmkzWklBQUFVaFNVUkJWRmhIN1pmclg1UkZGTWZQSXZCWTRzcGx0ZDhhQVJvb2l4Y1d4TlFIVVdRTmVTVGRaMTFEQWxjbHZMdVNOMWJOQkFXRk5OSE12SkMzc2lRdlhkQVNMNWttcGltVzJVVkx5N1NzelA2S3pyTU0rcUhQc3d2N3B0NzRmVFh6bXpQem5Ea3pPK2NzUGVRL3dCRFVJVGdrVkJLOXdKQTZQdkpvcDdET3hpN2hFWkZScHE1QlFtNHYzUjZMUkN2TTNSK1BGbU50SXowUkU2dE5pdXZSODhuNGhGNHh2Uk10V2pmSjFFY1l0RUZ3M3pnMlQrelhQN2xsODlhVTFBRnByQTE4YXBCUS9DQU5IZ0xJNlVNenVHMGRsanc4YzBTV1RWdG81TlBadk1Tb0hLK1JINVRSN0c3dU13YWlZV1BHMnNOVm51VG9uSjR3emtrVU92NVpJRytDTVBSQlJqNXYvYmtDa2dvbnVuanVmZFJKcHNsRVU0cFVxTThYQzFzOUJrM2x6VStUcUZ1K0ZqYkg5S2lFR1RObnpaN1RSWFBFUGJlRURDOVlvTTRUeGpvVXp3Y1dMQ1REUEk2WXVxaDBvWkRKczNnSmU0K2x3NGxlTkhieWZaelNNaFc1a3lrNm54MU5mOG5ycWVJcGNYclBJbmg1R1pCV2JxVVZJVnBYbjY0V3JLeWdrWlVjcWxLZXJ1U3NXbDFWUGVUbE5XdGZXY2VqTmV0bHFCdVVabE5kT3J3SzgwYUs3ZzFVODJHVnBOb2RXdmk4eEJhOUpsR0JIZGhrRmNaNjlBVmVKOXJNWWRoQ2xMbFZtMmdlTlhWYjk4aGFibG5lV0xjV1dMUmQyT3F4dzR5ZEhwb0FoTzBpYWJjWmNHMGUxM3p4Z3ZxL3lZZkN0M3NJcit5YkdNaHZVVGMzOHRqL1BSYkltOTRXQTR6eXpsTDJJbSt2Nk9wU1o4RzdWdHJuUGViOXRUaHdzUFVyNEhuUFlYbGZ0UFV4UVIxTWhSWjg0S1FVTjh3ZkN2ayt5cGg2dncrTEp4ZUhESFFZK0lpVWp5RWZFWEw3YVZCeGxHcnlVQ25SWUJtci9SMjNQc2UwYng4SFRwRHlDY3dWUWcyQWszQ0hjQWhqa3lsRnhub2hCa0lZRmtuV1E2aVMyQmYxVXlFR2dDMFA4eW5MaFZORVV4RnVFMm9BMUozR1ozUkdSU01wWWRncXhFQTQ2OEFNK2h3NFIwRmxPQ25FUU1pVU1aUE9BOGRwdXhzeFFneUVMeHo4UzF3TUhDRmJHYUtFR0FnY2d3VGFvZklxMGdWRUNqRVErQlNLYUlvTEU0bUs0TW9TYWlCazQ2S2tWTU11YVM5Q3FoQURvUWhOZldnK1lpL1I1RGg4NmUvaDhrRXBNRTc3TFp3amFSdndsVkFEWUxnRHZhaFBHdElseW9sRDlVZ2h0NS9paTBqeVNJZWhYaWI2R29qaTVQaHZyRHRFUTUrWndCaktxVVZ2SjIyL0FwenlDUDArS2QrWXZ4Vk5YV3BjK0s2WThxRit6dyswRzdoYUl3YWFDVzFzNGxlOVFQUjBpWWU2WDN1VjA5alRqUU9CSHRjZWJNUDV3d1V0VFdDVzZPdVM3RVoyTktXcXlON0ZQeTZlb1A1WVB5S1VNNmJ0YkdNWXAyZmo2SEFjV0NHTWRia094RXRTUDhCK2cvUGNiQzJ4T1NJdXBrZE9rclhXK2kwMEQxcnE4WTF6SitTZnFJUkxoT25haHhyMlBTZ3hqS2QrWnNWNnM0MU5uRW1EOFJmS3VNcDUvQmhuWituR3JkdFZpVTBSUzhkZTA4cXp1Z0xxNklhcnNObFduOTBPSko2bGtyN3M4ODVmVzEvbkRyT2FmaU82cGZyZmhHSlNrWGlabEtHSlhLalpTeXRhcXFIUXZmRmNvWmd6eWNEZWNRYjNqZlVPSitVVENtVXRPYzA3cjgwZGNIUnUvZkxmYjY3VTRwQjAwRU1HRTQ4M0NHTmRyQ1l1UTdZbEUxWGNpZEJtdGVDd2o3ZVJ0TGVTajdPbi82d2puZURZbDlYeitkdisyTERHNkpCbHVUYnBabU1oN3libE5ydlZWTjZ5TDU4MFZQRVhWMTduMjhTRTFLVmMwbXBXS3I0Y3cwV0d2S25PSy9zbnROSElTN2orTE0rME5WOW1aL0Q1bzFmNFhxbFZYZHY1MHR4STBKYmc2N0JnVHRUSnUydiswaUxLSjN1dlRlOGZFTHluOG9CM2xrQXR1NzFZNTRud2gzVHBYdnpmMDduV1F0NkZ1OHVtdGYvZlJpc1U2NkFNajlWdmFmT1EveG1pZndEa25VNjVQcXZEWWdBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIlUyRl9WMiJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjljODM1MzQ2Nzk2YjRjMjc4ODk4ZDYwMzJmNTE1Y2M1Iiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjYyOSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTYsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6NDgsInRyYW5zcG9ydHMiOlsibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDEtMDIiLCJ1cmwiOiJ3d3cuY3J5cHRub3guY2giLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMDgwMzAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjciLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMy4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAxLTAyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0wMS0wMiJ9LHsiYWFpZCI6IjRlNGUjNDAwNSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFpZCI6IjRlNGUjNDAwNSIsImRlc2NyaXB0aW9uIjoiVG91Y2ggSUQsIEZhY2UgSUQsIG9yIFBhc3Njb2RlIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjI1NiwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsicnNhX2Vtc2FfcGtjczFfc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsicnNhXzIwNDhfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjYwfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMCwic2VsZkF0dGVzdGVkRkFSIjowLjAsIm1heFRlbXBsYXRlcyI6MCwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJ0ZWUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsidGVlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRWdBQUFCSUNBWUFBQUJWN2JOSEFBQUFBWE5TUjBJQXJzNGM2UUFBQUJ4cFJFOVVBQUFBQWdBQUFBQUFBQUFrQUFBQUtBQUFBQ1FBQUFBa0FBQUZKYnVKMkVrQUFBVHhTVVJCVkhnQjdKWXhiaU5IRUVVRkoxNFlDNWpKQWdzbkhzT09IUEVBQzJoeUIrSU5OS0V6TW5TbXVjQmllUVB5Qm1MZ25MeUJlQVBTSjFqZWdINmY2aHFVeTlQYVhnMEpPK0FBWDkxZFZWMzkvNS9tUURmSDQvSG1pcndIVjNPK2NFR3VCbDBOeXY5OFNqNHQxeHQwdlVIWEczVFJYOEdnNWpjRG41OS9yTDRESDhBTWJCeFd6RnZ3RzNnLzhKaGhHa3MrVkxtYTF4Skg5QVRJaEdNaFpGN3oydk55L0V2aXc5ejlTc2FJck1HKzBKUSs4N1IzOHBYSER0Tlk0bUt1cHBRb29rWmdIb3hacy80RXB1RDJCU2l2T3RXYmFicDlvOUx6Yy94TDRzUGNMV0NJa0Fwc3dXY2dvYmQ5MjRpcnJuWVl4enB5TXZvT0xNQmY0RjgxY1kvV0pVYmthb1p0N21QalloSUEvZ1IzTG56RFdtYk13QXJzZ2QyTXZsSDVEV2hCWndoem1mVTcrTlgzN3B2bnhKZkVMMllReE4rREQwYVl1UVRKbEMzb002STBkbUQvSEZTdTl6dWI5NDBsUnVScUxtSVE1TDgxb2hJQzlQWWxyTlNFMGpyZHJGcG5NWDVqWjhZeEo3NGtmaEdEakNDa1p5Qm56STdjQWt6QkxhaHNuNDBwcm0rT3ZsMVBJR2ZjaXR3UHRpK09KVWJrYWk1aUVHVEhZTnNqNkRNeGllMitKVkhNUzJ2MjZUWk9nY3lOWnVsRjlQYk5pUytKbjkwZ1NPby9ZNUgxQW1UTUF4aDVBN1FHTlppQkZzekJCcXpTV3JFSnFQdyt6WW5kZ3gwNEJ2d1VhMHVNeU5XYzFTQ0l5cHhJK0pGWVphU1pqMEFEWkVTc2ZXbTlwMzRKYXV1bGtiVnVsRjZBN2QzNHZPWTU4U1h4WVpzZEV3aStkU1JGVnFRYlZ5SXhMVGdBRS9QYWNlOTdNNi9Bayt0YiszTkxqTWpWbk5PZ3BTTW9jN3J2Z2VaZzYvTFJtRFU1NGNIaE1jWFU2NWlCak9yTVlQNHAxVzMrVndaQjZ2dEVURUlreUp2VHNJNjNSalVMMFB0ZnRSZW51ZnFCS1hnQ2ZXYk5pWisrYjR3NlR6VzE5Y25kanBMNFdXNFFaR2FKVko4NVVaQ00rY2ZIMm9Sb2xEQ0RqOXVjbk14YWc5aDNTOHlidExROUpVYmthczVsa01pSmNHT2tORTh4RXlMemFzdHJaRDFLZFN2R1BiQmFQeDZJSzY5K25iSE1hN0FEc1hhY2VuZjFPZkVsOGNFR1FYQ2NTRDZhZU5ZaTU0bkhtMVdSWDRZYVg1K2J5eXp0cTVJSkkrYUwwRWMxWnRJdnFpc3hJbGN6YkRPSFEyWUc5RzJ3NnoxbTdnVkdjMVF2RWI3bU5mTlc0dlhRNnlIMDI3UHVibHRPZkVuOEhBYk5qUXlqelBIaW96bDYrOUVNMVN6QUhUaTkrV2ZaSitGVmlpdXZ1cmgzUTh4ZVRCUHlHK3RUWWtTdVpyQkJSa0pFd1RhUTdBUVRseGd2VUlMdlFmZW1tY3ZnR1dnVGF1dXZrWmpxbzFFNjAweGFNUGRudE5xWEUxOFNIN1pacDZjSFl0R2N4dVdXZ2ZpamlWSU44d25ZaHhvdlZQdXJWRHRpcnYwKzcwMWFoOXpiRWlOeU5XY3hDRUxSZ0ZaaTlKQ2JCY0tMNTh6ejM1NjlYbmljejIwdis2YWg3MFk1WWpMUTM3SW1KNzRrUHNnZ2lMd0JLK0NGZEFZUWIwTHVpYlg5SENSa0cvTHFvNXAxZ2hkcVoyaVA5WWo5VHdhUzkvRk5pUkc1bXFFR2ZZU01FZGZvelJtSDNKZk1VWDVzTjhSR1l2ZGdGM3A1a3hZaGQrcEJiSjNpLzZsQkcwY3Vtbk53T2QyRVRqeHpDVHc2K0wwVjhTVlE3em5RZWdTaUVWdG5vc3kxZnFjNDY3SEZjcmVqSkQ3MEJrbUVpRDA0c2lKMk1IS00wUnlKTnpFYXZUbHR5Rmxkby82cURmbDVpbmRtcEx6VnI3VXVNU0pYTTlTZ1B5QlFpYVFlNWczdzVraGdjMG8rNTVlc1RiUkdiMDdNK2JxdWovYUVIclg2RS9QNzl5bFdxelludmlRK3lDQ1JzQWNpODBCY04yZmk4bDVBTktjTmUvV1RlUUM3RUIrckg3RytuMVFWYWs5bnE3YkVpRnpOM3dBQUFQLy9YOUxsUHdBQUJQTkpSRUZVN1ZxN2ppTlZGQndrSkJDc3RCMFFFZXkySUdTRHpwYU1Ec25XTWNsMlNMQ1NIUkJzTnY0QXhEZ2lRbkwvd1hSQVBpM3hBVGI4Z1AwSDIzOHdWTFZQbWRvcno0TngwRzNKVjZvNTk5WTU1L3BVeloxWmFUVVh0N2UzRjAvRkJkYTNML01DV0FPM2hnL2ttZWZDZm1ZNTFxMkFMSExWUGJrc2FuWDNsbjFBa2ZSVWNWZHRmQlBjN0tuNjJQZGtjOWlNWWQ3WlFCSkI4VG1INDhMZWgwN05vZERPN3RnYnQrdmVmd05vdU81ZkhMaDNHMXhxWEk2K2ZFaURXaHVjQXE2QS9tVWNFUEdRT1RTQmdpWUE3eVhtUUJWUkJqSG1BZWNtOFprMFdmeU0zSkFHTlRITUJySGtNRnpZWjBBYk9RM0x3WHZ6RVBtZDdwSjhHYjJxdnkvV1VWdmJIVTF3TStOYWNrTWE5QjdEWEhJSUxaeExJQlh2NWxRSDhwWDE4eVhkWjQ1eWVYeVd6b3daVUNUOXo0WTA2RE1UeG9HYlpEZ092UVQwY21pT0M2SVpFOTNCaURQdm1RS1h3Qld3QWJ4SCswWFVlNzYvSytsNVBaaEJKcWpHVU9tcm9aQXBhN2l3WjQzRU1kS2NZcGU5L3l2cVNtQUZlUCtXWGVEOFhwbm1YRG1ZUVJqdXkyUm9DYUNZWGp4aURxeVR1by9NUVc0Q1VGUnI0R3VzZ0V6MlliOEU5Qm40TjdnM2lEWGkxc0hOakNzR015aUcyZGd3RlA2V1BCZjJITFN6UElYUXZGNDBZZ2xzQVFtOEt5NnNaeG4xcS9pTTNQdUQ0NzI2S3h2YUlBNi9BZHdZRHRqYWtCcjJpZ0s0a0dPZitNZkVOZXI3VjdtNzRiK3Z5VDE5VFhDOWlVTWI5RnlqWXFpN2pPSExtbGhkbllqcURRYVhzd1l4QTk0QVM4RE42NWpUUFlyZytDcFZWNUlQYnNIOW9BYkZNRDloSUg2SE5hVEhKZmk5S094VGMvYXZpbmVsQy9VbFFJTjFaM3VncHJWOHlUek81QXJ1eDJCUWJRTkt5QTI0a2dOeVljOVh3YUdWWjZ6NjVDNWY0ZHhFRGVQRWNnWE9idEsranpYUm8zdG53ZldSK3pFWVZHSklEWGlOZmNuQnRIQ2VBSjNWN00wQmx3R3BjYnFyWVo3M0lQSU84VnZkSFRudm53ZFhNbklOYmhDSHdQQy9BRG4zV2ppWGdBOVBnWHdKRldzUWFjNGFrUEJEc1dZdEYrcHVyTlpmbUg5R0ZiWFBHTGxHWWRCdWxGNUVBUkVMWUd0aUpId0ZybUF0WW1vT2pac0NlVVQxTUpiUlUyRXZma0dPQzF4cmZObVQ5bVUwQm1ISWYyeFFDV0hzeFd0bW5HbmkybXFaNzQyem1wbmxHL0k0NThhMVZyczF2aFN2T0NhRFNodVV4bXdBdm9wTXcySS9BVHBBQnU3TkFjZCtyMld1cjdOKzlYVUhPT1krRjY4NEdvTTRFQWI4RGJnQ0NnMFlQTVczZ0FReXVqbDE1Rnk0MStkeHo3N2Y3aFgzTjdsMGpjb2dIdzZDQzRBL0t1c1FMeUdNS3lCblBTSnJQTmUvSW5CdVVJWXpvYm8yZXVmR3ZTS1hydEVaaElGZkFWc2JYS0lZK1dxbUVvRjlsZFRObVFQblpud0libUsxVFhEcjRCWThIMXFqTTRoRFl1aFUrQWJjSmRDL2pxaVpoVGdhUnl3bEVQdTU1ZXFvcjQxamJ4N25hL1VkaXFNMEtBVDlEQUg4ZmZUR0I4YzVBeHBBeHFUbUZFbXVqSjdPZUpvekIvaWp1amZkUDBmNzBScWtBUlVwSkVTNTBOUWMxbXdCbWRlL0Rwd1h4alhZcys1UFJ0MS9WeHk5UVJEeEF2Z2Q2QUFKVjV4S0dISVV2YmFhVFhDRmNlemppL3BSZlEvRjBSdEVBUkNVQXplQWpPRStsempzYVVKbmVmNHlKNWNCYStOL3hmNEw5VDBtbm9SQkVnSnhyNEh2ZFdiRWVRYklPRVkzcDQwY3VlazNMMTUrNHIyUDJaK1VRUzRJZ3I4Qy9nZ0RaTkFHWjcyY3Y3Qy9CdDRDejczMy8reFAxaUNKaEhqK0dQMEFmQWQ4R3ZoYStXUGpZQVlkODhHbjBudlUvNVdjaXNoajVqd2I5TUNmLzV3Tk9odjA5RDhRNDQvbStRV2RYOUJ4TCtoZlV3VFl5UkNhclo4QUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDUtMTkifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTA1LTE5In0seyJhYWd1aWQiOiIwZDliMmU1Ni01NjZiLWMzOTMtMjk0MC1mODIxYjdmMTVkNmQiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjBkOWIyZTU2LTU2NmItYzM5My0yOTQwLWY4MjFiN2YxNWQ2ZCIsImRlc2NyaXB0aW9uIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIFBybyBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MjU2LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIiwiYmx1ZXRvb3RoIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDU0RDQ0FlMmdBd0lCQWdJSkFNOVJ6WXU0RUlJbE1Bb0dDQ3FHU000OUJBTUNNSDh4Q3pBSkJnTlZCQVlUQWtOT01Td3dLZ1lEVlFRS0RDTkZlR05sYkhObFkzVWdSR0YwWVNCVVpXTm9ibTlzYjJkNUlFTnZMaXdnVEhSa0xqRWVNQndHQTFVRUN3d1ZSWGhqWld4elpXTjFJRVpwWkc4Z1UyVnlkbVZ5TVNJd0lBWURWUVFEREJsRmVHTmxiSE5sWTNVZ1JtbGtieUJTYjI5MElFTkJJREF5TUNBWERURTVNVEF5TXpBNU5UQTBNMW9ZRHpJd05Ua3hNREV6TURrMU1EUXpXakIvTVFzd0NRWURWUVFHRXdKRFRqRXNNQ29HQTFVRUNnd2pSWGhqWld4elpXTjFJRVJoZEdFZ1ZHVmphRzV2Ykc5bmVTQkRieTRzSUV4MFpDNHhIakFjQmdOVkJBc01GVVY0WTJWc2MyVmpkU0JHYVdSdklGTmxjblpsY2pFaU1DQUdBMVVFQXd3WlJYaGpaV3h6WldOMUlFWnBaRzhnVW05dmRDQkRRU0F3TWpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkhscTJqVVFNYWxIai9CUmVRZWZHaXo0RXZZSnlGTFdQejRSZmhKR0txcWwrOG45NmhUMW01Z1hvVHZvTHJqU1U3WDBjQmVvVHNnaHloMjIreXJzNCtTalVEQk9NQjBHQTFVZERnUVdCQlErOFNHVzJCWGJxYjJkY0FPaVdKT1UrR0NzUGpBZkJnTlZIU01FR0RBV2dCUSs4U0dXMkJYYnFiMmRjQU9pV0pPVStHQ3NQakFNQmdOVkhSTUVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRHE4eElXMFpLNXl6M0VBem11eDg4TENUWU8xNTdmVGZ5T2lPekMyQUR5YXdJaEFPMVBXWWxlRmdILzNtdUQ4Y0JBTXIxMWZFS2RGL0FhQzE2ZnR4YWV6TlhIIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUl3QUFBQVlDQVlBQUFBb054VnJBQUFBQ1hCSVdYTUFBQjdDQUFBZXdnRnUwSFUrQUFBRklHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORElnTnprdU1UWXdPVEkwTENBeU1ERTNMekEzTHpFekxUQXhPakEyT2pNNUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdLRmRwYm1SdmQzTXBJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4T0Mwd05TMHlNMVF4TkRvME1EbzFOU3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2UTI5c2IzSk5iMlJsUFNJeklpQndhRzkwYjNOb2IzQTZTVU5EVUhKdlptbHNaVDBpYzFKSFFpQkpSVU0yTVRrMk5pMHlMakVpSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKaFpHOWlaVHBrYjJOcFpEcHdhRzkwYjNOb2IzQTZaV014WlRnM01qRXROek0zWVMwd05UUmxMV0V6WVRrdE5URmtNVE16TkRabFpUSTVJaUI0YlhCTlRUcFBjbWxuYVc1aGJFUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJajRnUEhodGNFMU5Pa2hwYzNSdmNuaytJRHh5WkdZNlUyVnhQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaVkzSmxZWFJsWkNJZ2MzUkZkblE2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRveU1UZzFaakppWmkwNE5XWTVMV05tTkRjdFlXSTROeTA1TVdNellqTm1NR0kzT0dVaUlITjBSWFowT25kb1pXNDlJakl3TVRndE1EVXRNak5VTVRRNk5EQTZOVFVyTURnNk1EQWlJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBb1YybHVaRzkzY3lraUx6NGdQQzl5WkdZNlUyVnhQaUE4TDNodGNFMU5Pa2hwYzNSdmNuaytJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCsvMFZ4UlFBQUdmVkpSRUZVYUFYVndYZmNuM1Y5Ny9IWDUvdjlYdGR2M0RzN0pKQUlBVUxZQlptQ2ltRFZEbGZ0dzIzSHFZdXFQVjBXdGRiV1I2M25WRzJybnJhT3RzaERyUlVmUFIzV1dTM0tWaEFaWVFvRVFrTFduZHp6TjY3cituN2U1MDRpS05XTzg1OCtuMm51aXNTL0ozRzhZWmVaMlpURUltRDg1K1JPTzBaU1VmaUhKUDZGSHlJRVdCakF3ek53Nm9iSTNDeWtDR2FHSk55aExNV3dnbnJvcE5KSUNCTlVjb29pME84Yit4ZkY2UExBcUlNY0dvZDJXK3pZRDlGZzQ5ckFnYjFpMFRKVEhXR0N1bzZVaGVFSmRpOW1WclNOOGNLWXE0MmQrOFNLQ1NPMmdBd2RJQlFRVFB4N1psRFZka2tXYnpUWmNLVEkzZGh2dnJHbHVlTTlkOFVUWDBScitqbW95WUNRT01Tc0JMcEFBakxRUnhwZ3hvK1JBbWxyNG9jSVpoZUdrRjVsQnBMNHJ3aElDWExEZkgrZ0R4ZUZrSGdDQ2VTd2Y3OGhFei9Lak1QRUQ1SWdSWHVSdWYyMHBZQlpRNzJmN1N0R0gzWW1UdnhGTWhjZ0F3bGlBUkxnR1d3R05BZldRcXdtaHNoQmNuNHNHT0ErbDhxQ3h4bVFCVTNEU1pJajhWOFRZRkMwallVRmJlMzFkUDJ5NVpBelR4QVM1TVpBZ1BHanpRQkIxWUR4QTlaWjBLa21jRUhJbWM5M0x2aTNIZkhJa3FaZWpUSWdNRUFPN2w4bnhrOGgzWUxuM1lRMGp1c00xTHlPRU01RTRzZUNnT3ovbFBZY0VJOXhRVHR4eEhnM251a1lJTDVyRWRnT0NDajRmZ1lTc1I1cVJhZWpxMEppdXFwNGdoUU5MdzFWNHNlRkFLOUZNcjVIUUxUalFneWJNY2lOZzdIbjFwV1hmT09oNnNTTDhQa2pNUWRMWUdHYXdkN2ZKWFl2UjBXZkVNQUMxQldFNGxaNkMvOU1tZjZPY3VUcFNJRDRrV1VHMG03RXZlbTJiYzVqaG8xWU94bVBPbk1UcDJhSjdJQ0JpWThKL1Q3UUFrWUFjWkFBUThFb2MwTzJ5TGJSVVVNQ001Q01kaHYyelRsa0kvSmpSR0FSUWhISWpYaU1HY2RLR25lTTBqS0lPeDZwVisvTFp1Y2o3eEFNU1B2bzZ4VjQ5UVhTT016Tnc4Z0VkRm93TXdNalk1RFNYcHJtclJUNkI0eFZpQjlkRWt0dUpOcU90SGMrOEpqK0VEcGQyeFRhakdnQUdlTWdkLzluWUU4STRJSVFRQ3dKZ0lNTFhCQU5tZ3lTa1IySzROejlJRHc2THpZZkxRcmp4NFlaTkRYMGVrNTNMQ0J4U0FwMmpwbGhnaFkxc3paeDAxWE5CWE1FdGhBcVFCVzk1aDAwNlF2RUVhaEp0TXVYVU1RWDBGUlgwMnA5aENMTm93Q2Vyc2Y4UHJCVi9LZkVZY1ovbnpqTStBSHVFQUwvSVRsZ1lNWmhCcTZiRVF2cFNVZEdIbFBWeEJWamRvNnk0UklnRU5zRU82SkJscEVDVkxVVGdoRkxRVFljSXlNS1FaTWhHMVFORktYNDVqMWlZdEpvSlVPVitDRU1HQUVDTUErSS93OENYR0NBTzFqa3Y4MVlJc2dPRW9lSXd5eEFYWW01L2M2cWxZWm5hREpINWN6SmhJQk1tT0FoMy9qbGdYVldRejZSWURBWVhzdEMvUmQwbGtNNUF2STNVSFRmUndCcWZ4NGpvMXVCTDJJUjZnRFpHMElBQk80UUkyRGdEaVlPc1FSeWtJTVpQMGpnR1VMaWNSWUFnUXZNT0VRQ015aGE0Qm5rUElFRUZxQm9RYTdBSFVJRUJEbmZpY2pwcEVseGlJREltczZZblprYmFESllNRHo3M2NnZm1Xa0NSWUxKQ1AwK1dBQUtIbWVBWkVnUUFnVGprTkUycEFnU2h3aklBb3pqZ1o5Qk9rK3d6c0JjN0FPK2d2aWt4S1A4SndTNEdERzRLRVhPRXF6cXRQQUEzekhqQzRLdC9CY0V5NEp4OFdpYk0ySmtLb29hZUFENEN1TGJHQlFseEJFalprR2Y5WFZ0bTRoZ0NJelp2K1hGRHowWU5wNk5MYXhFRG1YbnMweVpFeW9vMHhuSS9vaWNvYWtoUk1CZWczd1RVa24yMVJnbkU4UWhyUTRvZzJjSGJRZjI0cXdpMkhxU0JScUJBRE1lNXc2cGdNNFlESHFRR3pDRGtDQVZNT3lCSEN3QUFnR3hBRGw0Qm9zY1pxQU1DR0lMd2poVVBhRnN3QTZDN21GSm1ubFVIT1FaV2wxV2o0eXlSVUVna0J0bHlUMnRxQU43NTRXNXNXUkNjS3JnRExEamdPVUdDb0dkR0xjQy95cDRoQjlHRU9DWXFYWjRiVzdzUmRGMEZHYUdJQU1wUXNDZVpZRmZNN04zQ1A3YVFId2ZBVG1yUlBaTHJjaXZZR3lXV1ZlQ3RaTWdsNXJLM3BTaVBvYnpoOENBN3lNZ2kxR1pYZXB1cjR6R3BnMnJZbG5YQWplVWhEc1BXZVRQTGZMSDFVRGFmbSttTG95UnR2M0VaTmNtcXl4YU5DQnV2VDZldXdQeE10UnY0K3JSRzl4SU11ZzBNTlFCTE54UGEyUUx1WUZxQU1UbkE4L25vQ0lBeGlFaGd1Y0RMUFkrVGpQNEV1Tmo5K0RXSjRSQU5YTTZkTi9DeUxLeldKd0ZieUJFUUJCTFVJREZtUWR4WFVjcTdzVENnR0gvS1Bweno2QXplaElHTkEya05uamV3ZmJiUHNyWTZ2dG9UejRmYTE2SUJjZ1pXaU9RNjBmWWZ2K0htRmh4QjkzUm44UHp5M0RkanJHZEphbTdNWENRQkVYa0REUEdjZ1VXd1hBR2ZWMWZXMEJ1YXkzeTg3Zzl2OTIyRXcxYklUY3dnU0FGUThKajRINlpYVkZMSHdCbStTNEhBcng0OVRKN1I5a0t4dzhXd1FLUGs2QnNRUUdXemRZWG8vR2pkWk9qTWg4MkRwTWdKanRwOVVUODM5MWtGK2VHb2tqQ0piSU1seEJZcm5Wa3UydHZNdzlIbXZKckJRT1dPRkFFVGxuVkRoOXNXYmlnY2NOTTFCbkVraUFra0xFaEJIdDNHV3dWbWQrOGQ1dnp4ZS9FOU15ejdjeUx6NGZxRVNpVjJWbHMrUHllWW0yUFBrL0ZNc2dIRFBveldJQ3FnbTduQVR5L2dOazlyNkVvbjBkNzlFazBGWWNJQ0FIRUVvRVB2OHFqRDd5VFZjZGR3OFI0UXpXQUxCQmcrV0ZtRnIvS2JITUZVK1h6Q0FteWd3VW8weDcyUGZTWFBIRG4zN0xsS1E5aDFpZEV3R0ZtMXlvNng3eVZzdnRHNmhrd29EUDZOaFptTG1mWnhoWXBYWXpYSUFHQ2FDQzlpMTc5RnpUWFFUcmhRc3BONEl2ZkF1WlprcnBkY1pDZ0UyVm5lelpjSW1LME9ueDFkdGIrTGplNmVOVUsrMkRDanE5ZGhCQzA1QURTaUFYS1ZqU2FSalFpeEdESGdyM1Q0Rm5BcjBwODJ3V2R5RnRiSStHM1RUYmV1QkFRZ0JBTjVQTWpMVDUzeDRPNmV0c0MrODQvd2RaT1lpOXRpTzh5eTdjaTNjaEI0dHhXeXo0UzRjUWlRT2c2dlI1N1RGeVZnanlZWFNSWTFRQU9kR0o4cWFSckpQdG9VM1BRdVNuWUZhUFJObVdEakREWVdkVit2Um5aNEd3ejIyQkFOWlNWbmZpcW80N2xzNVBPVmZQTGJPMktVZHRNWDJBR0JRdzZFOWMwZCsxZHhkcmpOdEZPb0RoQ1ovOTU3SGhnSzBlZkM2RUc1eDRHaTc5T1NoOGdwS2NSL2Rjb3U2ZlFuNGZza0NKUS96M1ViMkJxelU2YVBvd3NPNWJoNEFKY3UvRG1xN1FuQnZTWlovdld0ek4yN0dsMEp6Y3lXQVRaOVZSemI2YmR2b2JONTRxaUJXcWdHb0lpdEVmM3NPZkFteGkzU0xkOUtWVi9GNjN1VnpqNkxJakZPbFJkZ0FVUUVBTU1xM3ZKZGhWcjFrSnVMY01tbjRvcW9MNFpQSU9SR0hDSUdWTkVUaEpnQnRuOXk4TUJyeDhkczdjRmhYZDJvaGcyZm1QTytuU1EzUXkyRDlOa1U5a3BpNDIvb0d5Rmk4cElrQXR2eE1TWW5SK0srQWtMell0RzIzWkJ1d3h2eXoyMTYwYVlRWkZBVVBWNy9xbWlzRDluVkxmMSt2U25lNDRzUU5ZVmplenRwZkhVUm40VHNNNHN2TS9FaVNIQlRGLzloVVg3MDdLdGo0NjAySVhJTjl6VmJKNGFpKy9mY25TNHNCcUl4bFcwWTN6ZHZnVSt1bTNhanpqdEtQNE1iRk10a0duT3M3ODNoUERKRU94UlNSZ2NpWGdieGtzRmxxS3RhS2Y0d3Y1UVY1MTZySjYweWptaDJtOVlFSlRzZm85ZS84aDlCemFld1JIelU0UUNGRnFFOEFhOHVvbWl1SVdtRDU2aExNRGlnN1JISHVTV2E3L0VzUDlSVG5uNnM0Z0dpL1cxeU41SUhPeWtNN0dNaFlVM3M3ajRVc1JxaWxBZ1BrNk92MDY3M3N0UjYyOG5oeHZJMmtoMy9DYm1GMStMdUkzeE5lRGg2VlQ5VnlHT1JQbG1HdjlUSmxidHhJRDU0Vi9TYWo4WGZDZHpleGV4TnRUVldVVGZnQm1ZUVREb0RYZlEwelltV3BBMm5vUDdDZmhnSHlIZmpvbURrampNeFBwQU9BNER6OXdnOFg3VityMlJUbno1WXEwSGRzL2xQeHdwN1RQQm1PTzdna0hsWEh2M3cvNnhpU24vK1ZNMnBiZFhzL1lrajJJNEVLRUtXNTU2VXZIbG1KaW9lbW9yYzBnclFRT1BIaGo2VzJuc2I4cUN4OFVJTVJpNDl0ZFpmMUFVWERCV3BvbUZTcjlsRnM0SkNBdk03WnIxUy92emZIekRlc01NRURSdXQ4NzNtcmNvcC9jRVdCOER6WFJQOTMvcU9pL09Qem45YW12VW5yd3dDNWdlOHRwZkJYeU5KN29iOUR1WW5XallhWjdGWXJaTk1jTksySktDalZkbWRCbkFnQnNmMGhIYjJMTHVkYVFESTFRVnlLQ3o2bVNPbWZvazduK00vRXQ0L1FpdFVlaU9nemNnN1dEWSt6MXlQb21pWEU5amY0aHBCNmIxcEhnNTR5dWZ3WEFBWmhBTlhDK25hbTRsOEI2NjQ5QktCOGdMTU5kN0o1VnVvNHFSRWJ1TXdjSnZZMkVNaTFDTVhvU3FEdGhseEFBZHpkSTBleWs3MzJJNG5PT3V1Mkg5NnROWnRUd3hyQ0FZeEFRTCsyL0NyTS9vYXVoVlQ2WlZkSmh1cnFldEEzUWlPS1FVamU4NnhZd3B3VTdIcjIwbmUwdjJkRzQvNit2dS9pcGdHOTlsZ0ZoaUhOSTR2VWE2SFBkdjdodndpYkZPT0RVQnVSSGpJeHlSSGVvR2drRU1zR3RHMzg3QjMxaDI3R29KRU9EUWJVTzNNdTdkbmxuWkVXWEJWTHNkTzVZNVhoNWVvQ2lLQ0ROeitVUFQrL3pqclpTUXdJQTZ3OXBKWnpEMGF3ZnorZWVTYVN3bWNwWFpOVFZxcDY5WlliOGlCOCtPUjk2ZFV2eGFNRVlsR1dCTFdKS0JBM0o5MjR6VFdPS29YRFNuSzl1WUpBUUVnd1BONk5XN2UydWd6ZG1RUVN3UjRORHViTWI5cjhqRlZxSStBZllab3QrSCtuRDBhU3o1QnNxMzBCdnNndkFObWozZ2ZoUmgrVFNodVJKNUJZaUdBaGdoNkI2S0JBYXNXSDQ2WDcveWMxanJLK3g3QURZKzgrWEUrQWNJd3dSaVNZWjIrVXRJWjFBM014UmhBbWt6bG42ZmJkc2FSSWVpT0pXRERKQkR3NEQyMkxjWTltQjJEa0o2TXJSZ3FuTXpUWDJBYkJ5VWtGalN3dXgwQ1F5ZmptN1BEZU5oMDZEVUYxcDl2WnpHcHVXQVFBWVpNTUFNM0NFQTNUWlFzSFd1MXMvVU1mL1ZVZDF3U2IrR1FRMEdtRUdJUUFwZmYzUi9mdTNLRmR6bEFqTlFnR1lJSjIyQVpwdjQwT2Zod2pNRHp6M2RMdDI1eCtSbzQrcmx0aXdQSVhTNHAxM3lKMVB6UnJzRnFRVjFBd1owUzJNNEJFazdESkZsckJpTnhZdlA1NFZrVml6T2laQnNFZW1uZ0xNRTQ0RDRuaG9vRE03aUlBT0R4V2dVMFRoSkF0d2d3WmZqSlhkc0RTZTJDUGtJVkFNQk1CRFFERGtrZFU3RXV1K2lIcndhZUFtVG96Zmd3R0lGcUlmNEJLVlAweDlDNWpxOHVZNVE4RDNHSWNwUWxOQ2RXTW5ldmN2NDlyYyt5ckxPSWl2WHJtQ3l1SXpLRFJOZ1BLN0pYZUJjek1BZHNQc3h1NDJOUjRINzhaVGhGT29LTUVEZzdHQjBmQ3NSMkx2L0JJNVl0eGtMOEowYnI2TzNQeE1MRGtwa0RwcWswT2tnWXJDanJXTWo5KzNSVGRNTGV2VTRUSzhlZzdJRmJwQU5oQWhCV0FObWNNUnlZNlNBL29MWXZNeTMxemxlMld1NGhDWEdZV1pRTmY3My9ZcEx5NVoybFFGS2pOQUNCZWhWMENtRUFBZGl5WG5kYm5ycDF1bm1qOHBSemw3ZnNuYmR3TTU1djNyZGx2RG95UnNNR2pIWUFUUFQwRXF3Y3NLd0VGRXczQ0NIUUlUVjBleWlXdUFHRVViS0VIN2FBUW5NREFRT0dHQXNDWVlBQTVSOWF5Zlk2UWw3dW1TVTdScm1lSEI3L2FUYkIxUGQ1NUI3RzNETFlMczVyQTAyQVVUVWdBdFNzWkhzTDJiUGdSdG9IQ3h2QUZ0RHNLMFlNSGxjQzA4cnlMMkU2aHFMNHFBUXVyZ21pVVhCc1A4d3ZkWXJxUGJNc243bDFaejZIRmkyNWtKeTNzaGdIa0xnQ1F3UUlDQVZzREI3TGIzZWJsYXRoUkJQWVhiZkNnNnlDRlpBLzVFN0dlNituZEZUWU0yRzB4bHJIME52NWdCWC9lTzlQSHczZEVZNUtDbHcwTEdCY0NvWW9KRk9TK3pjbVQrOVk1ZTJyMTVoZER2RzJuRmpVSUVCQnBoZ1VJdDJhUnk1eXJoOXU1anRpUlBXOFJ5djdIZmRqSUI0VEREREczdjR6bDNEZld1bmpORldvaDJNSmtMdEVJRUE5SVl3VmpLKzZhajRmK2dxbkxaSk4yWEYxd3ptaFJWVURObmFUQU1tNmdYUnpCbXQwcEE3VlEycmxoYzBibVFYTVFuUHJPa05PYzZDaUlZSFdCQ3FCTWtNWTRtRXhZQWxvMTlsOVRtczdXYlQ5ZEEvVnJUdDlCaXRXMVhRc1F5SjY2NVpQSFVIenM5aWd4THhCb3lyZ1FJNEh2UUJ6S1p3UVZtQTVEeTg2eVlxd2ZJV2RPSUZNSElDc2QwRFFUVlloelZYZ0UxQm1BVnp6RWFBSTRFYVl6L1lES2s2RnpwWGNNSFBQa3puS0NDdHA5b2ZlWnlBd0NGeWlBa0NtZXlSMUxxZFhQV1kyUU5tSjVES2hEdFlnUGJZa01YWi80dEZpQ3VBQXo5Qk00UisvMFkybjdPTGRjZEJLamtveVFCak05QTFSQmJVaXl5dW43QzdqbDRMVDFwanpDN0FZQWhtUEVFd2tLQnFJRHNFQzc4STlxYzFqRWVFK0I1MzBXbUZYMTQybXU2cWMvNndBeGx3QVFZSXFneGpIVmE4OHFKd3hVbXJ3bW1QUGx5L2Vxb2REeVN6NVhValltM0ZpcmFXeis0V1FTS1pFVnFnaXNNRVRhT09qR3lvYUhmRmNORkdsQmtMTERFTGcreC9IY3cvVWdRN0tyc2lRZzRxWkhtMjBlNlcyWnh4U0xkcHZKMmQrd3JzOVRsRExBMEdrVVUxZHpRVHU2RGlHSkxOWTN3V3RBME1wUHVCUzhIT0JZRUU4NHQvUXRINk9LdVhRZjlSOFBaVGFZK3NZdmIrQllZek1QS2tmUlRsUG1JOEh4ek1RQWIxNE1zRXU1SlEzSUw3eTRpRDgwaGpzN2hWVE84QjkxdG90MnBTVE1oQUJqU1EvWE1VNVZmQmQ3TTQyRUlJbDdGbTVSeWpKWHppejZDdXR2UGNOMlI2L1VUVGg4WDlINmZWK1J1cUdhQS9UcTUrZ2w0RnFmVU5Mdno1L2FRQ0pBNUtKbG9XN0dRelF4SW1ZK2o2MW9ZanVOYk4yRGNMR0ppQmVKd0JKVEIwUVFyVzNiREMvcUFzd3B1R3RTWE1PY2pFZmhrZG9DUEFYV1BITEV2dm5lOWpjajVpQWVlN2hLaHFlOGJ4YThMN1d1dmlLZmZkblIvKzVqMzYwbk9lVHBoTWlneEFZSlY0YW94V0ZvVEtsVUVHQm5JSTBYN1pqSmNIVkFtYjJEL2pmemJSc3U4b1dkK3p1c2tnaS9ZZys1MmpJZDZKR1dZUWdleUJQWlhPM2RBTkZ3ZlJkVEVtK1R0YXBSOFJ6SjZSM2VoMHdmWTNmR2JmZWJkZGMrekxWbEZySTRPcURXcUR3QUtnQThCYndmOG5LUVZDNjFOVU01OWgxU1MwT3RBZnZaaWk5UUpNc0xodEdja2dObk5RL2pMS2QwQThoNUFYcVB0L0Q5MVBFRk9tR1hZSmNSbGlpVGFqWmdyM2FiSmRoL1JPeEcraFBFV0ljeWk4SDVwM0kxK2ticUEvL0IzV3JvVTdiempBby9mRDFCR3c3YlpQTTZ5T3BDak9vYW4rbGY3c0IybFBRUVI2dTA5Z1pPUmtIREQ3SnRVUXFpR1BTUmFZREdaUEZvY1p3a3lyK3hXL0dRd3JqRUk4cmhXTVpZS1Z3T2RkZk1oZDU4VEMzcmxxTXB4ZnUyZ2FVUVNqY3QwV3NGY1gwaXVhYUpmS1JSYTBJcU5sTjM1ZzZQNnpMbjBPN0NHRG84R2VFWU05blJERzZMblB6dWMzYlp6aW9lWkFYcWJ4c0sxVmhPWERTcGpaQmFYQ1I4ejBCb2M1bHJpelBKcTl2U3p0MGlvVE95MWpVR24yMFdtL3U3M0J0cmZhM0QrWXRaT3pZRFRaYTNwVm1CczI5cnV0a3NyTWtCaFBRYis0dmgxK1R6QmxCbG02eTR5M0oyT0YwQmFMUnIyWVNTVjNQYmpxS1YrYm1WdjNVOFRla1pnRDhkbTQzMDNPRUFPWS9SdVI2Mm0xQ3RBODFYNElVOUJVbXlsYjc4ZktaZVErTEgveVpSVERXNm1iL2VEVGlMZVQycU1NRm9iTTd4NnkraFRJZmpUVy96Z3huWXNERmk2aUdaNkM2ZDlvcFl6eHh6UzZpbVp3QkdPajkxT0gyL0RnWklkVytmc1U2ZTIwT3JEbm9ST3BkU1duUGczV2JOcEh0cmV4c0RCQ3F6WEh5Q1EwRGlIQi9QUkd4aVpYWVBWZWN2TVFNcjVmR2huVitvVjVPeTFFRG5GQTJIR2x3bHVpQWNaaHhpRXU3VFhaZlVMSGhFS1hFM2hhNWF5aWhtaEdBOVJaLytUR2I3am43OGo5RVN4ZUhDd2NEMktZUlRBcmtvWG51UGpKQUgyRHRvS2xnaVV5V1BSTEp6djZoMWdFRnFmWi84aDIvYzBKeDNOcVVaSnlBMlo2aGRBV0kveXJSTGRUOEV6SE5zdWcwektpYVdlS2VnbkdMUU1wRE9hNWNpVFl5YlVMaTJiZE12NUduWFdoWVZlRHVtWjJ0c3hPRzQxSzJhR1czU0RwSlJZMElOaDVZQWdEQndMM3JJcjdGcWs0RFV0Z0JqRyttZXgzSW4wUk04aUNmak5nY0dEQTdDT1FhNUM5aUZpOEQxdFlqOWNnUVdmaUV1cnA5K0xWSDVIQ3ZaZzUrQno5UGl6MGw3R09YNEQ4RmhwYmpzUWhSaUlXNzZZWi9nSXAzb1hVWU0zMXBCTG01MkZRUVh0cVBhM3d2NUMvRkRPWW1ZYlRudjNieFBZT2Vnc2ZZZDJ4TUt3eWcycWVsajJiT2grTDZ5OW90MFJhZlJHNUJ1VnY0SG9ZeFBkTHV3OXczbmhiSFhjd1FJSWlRcEZnV0FsM3NNQVE4WWpnOWliN3JrUVlpWVU5SDdOMUxoRUVqWERROVl0RGYzODBQdE5xQmM5QUkrMEkyWDhwcFhDNXNHTWRJUWx4U0JTTUdsQ1lNV2cwYmRhOHZvVSs3ZG53REowSWV3N29ZMnNhZjlycWtmaHp2VmtubTh6Z3pHRGhUQUVSRVlOUlpkRWZhdXRZbDFlbnhIV0d5QWZjTGR0Znh6RjdWdG0yOC9wOXNTU21aT2U0Y3c0WUJ6bEdQd3QzLzVjUXdwc3d0ZzFySm1JUm5obUNnYUFUS21ZMGRkdm45VHdvT1F2bU9VUmFUUXlYSS84WThGVmNEekIwR002dll6ZzRoYlhIUDVNbVA1TzhXQklUaDVoQk5ROTBmb0d5ZlNHZXZ3aTJDMjlFZC94SXl2WUZEQmVQQmtwQ0FuR1laN0I0Rm1YN004RGxvT3N3N1NhbWtybitNWGo5RkxycGVlREgwVGlZZ1dkb2pYYW82L2NTZURiRDNxMWtiMmlYeCtQMlhGS01pSjhtMkRpeFBBMDE0TnhNdGxtTUowamI5dG5aWnh4bkRPZmtCQlFDdzJHamhjVkswMld5bmdWbHllWXhUSEJjQ3VFQ0M0eldXVm5pM21TNnJ3amNPWmU1dnNxNk9zcjJTZUl4QnBpNGJ1RDV4UUc3TEptOTBNRlNNQ1J3aVNMU202bjFqd3VWM3J1eXhjMHNrVVJyTXREcEdpZE1zWkNDL2FxeXp3cTlNa1VyekkxR0FveGEwRTdhNDVXdTdBLzFKMlBkY0Q4Q0JLcEV1OVNPbk1QTDk4M3o1eE50UFNzUkdHWW9Ba2pnRWdtL1o5OVFIeTRqbDNlRDdSOVVqbUFDT0JXSlE4VGlQbHYrMmZ0MTNCYkU2WVFhQ0RYdWh0a2FpdUxOb05lUXduNUdDcU5ZUHNteUk4YUlSYUx1UTY0YlFpRVFoeGxnRWV4b1RLL2pvSnloMVlHUlNSak1DMUVUQWsra1FFeGJVSDRYaEJrSXM3aEtwcFl2dzJ3RXIxbmltRFdBRVNJTWVtQTJTb3pQUi81OFlvUUV1QUNEWUpjZ0IzT1dPSEFkUWZ4N2FmUHE4TUZxVVovRWFFQUt3Ulo3ZmVZWEt5MGV1ZEt5R3BzYVZrekdTTnRnQk9USXBwdEdNMkFMS1hFQW1IZlJ1S0JnaWZGRUJsbjZsc1Ava091S1lQYVVvZXVvRUd3WXBIdnF4cjllSzl6a01EUytUelNzTURvSkF1ejJyRGNPaC9udktzVm5XTkR4TFFpWXB0MTFpekpmazdUVnpES1BNU0FBQmlIdzRONDV2ZVRoUGY2VFc5YnlsTEpndzZEQ3pOaVpUTmVZK0hxV0hoTEc5RUpOM1lpVTdNQklhYThSZ1NBbEVvdGZxSjkxODEzOTQxZlE3YitTUU1aVkFZWmttTFdSdWhodHlnUWgxQmlMVklzRGpFeElnUE5FRFFnREVwQUlCcmx1eUUyRG1UQ1dpQitnSmdBZGpCSE1FcEtJY1FqMGFPb2haZzRZanpHV3lKQWlVQ0FIVVFNTkIwa1JjRVFiYkJhNGlSL2kvd0gzRDVQTXBkMnQ1UUFBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkQmxvYiIsImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiMGQ5YjJlNTY1NjZiYzM5MzI5NDBmODIxYjdmMTVkNmQiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJsYXJnZUJsb2JzIjp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZSwiYWx3YXlzVXYiOmZhbHNlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjk2LCJ0cmFuc3BvcnRzIjpbInVzYiIsIm5mYyIsImJsZSJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sIm1heFNlcmlhbGl6ZWRMYXJnZUJsb2JBcnJheSI6MjA0OCwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MjU2LCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjo2LCJjZXJ0aWZpY2F0aW9ucyI6eyJGSURPIjoxfSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjUwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTItMTAiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPMiBQcm8gU2VjdXJpdHkgS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEyMTAwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTItMTAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEyLTA4In0seyJhYWd1aWQiOiJjNWVmNTVmZi1hZDlhLTRiOWYtYjU4MC1hZGViYWZlMDI2ZDAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImM1ZWY1NWZmLWFkOWEtNGI5Zi1iNTgwLWFkZWJhZmUwMjZkMCIsImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IFNlcmllcyB3aXRoIExpZ2h0bmluZyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg3MDYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImM1ZWY1NWZmYWQ5YTRiOWZiNTgwYWRlYmFmZTAyNmQwIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIiwibGlnaHRuaW5nIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjMyODcwNn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZdWJpS2V5IDVDaSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMDE3MDAzIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjEuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNS0xMiJ9LHsiYWFndWlkIjoiMjE5NGI0MjgtOTM5Ny00MDQ2LThmMzktMDA3YTE2MDVhNDgyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyMTk0YjQyOC05Mzk3LTQwNDYtOGYzOS0wMDdhMTYwNWE0ODIiLCJkZXNjcmlwdGlvbiI6IklEUHJpbWUgOTMxIEZpZG8iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQzZUQ0NBZEdnQXdJQkFnSUpBSmJUeXJ1MVgvSVBNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1DTXhJVEFmQmdOVkJBTU1HRWRsYldGc2RHOGdUWFZzZEdsQmNIQWdSa2xFVHlCRFFUQWVGdzB4T0RBMk1USXhORFExTlRCYUZ3MHlPREEyTURreE5EUTFOVEJhTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTVZqS0hXcGJEN1RTbE14b2NqVGw2bklmN3gzMlBtc1E5ekd1TEdHcUEwVVFab0lxM1hMekw2TFlVdko1QTVnMHV5RkdsbEhFZkdBS3JFYUNROEZWdlBTL1VoMEZ5ZnpXaFJBemlUU2lqak1JSVZqampVdjltOXZGbWNYU2NnSGlnN09kejg4NThWMGtyTkg5OXFHbTN3amdhT2VyVFdtdCtqWENVZm4wMUlrVFB3eEcySGxnRWQ0NWpOTFNWN1Zvb2wrS2U4RTJraTRsRWtUZUh6Ym91bFI1R1VicDNuTWk3RTQ3Vk1RYTNiTndueldCYnNhQlNTUWhMazNtNUhhS2hoeGE2d0pESzQ3TmlNQ2tDa2RJSHVXU1FMVkFmbTg1VUFPTnRFT1B3aTBPdUszcWJlOHlLT0ZHZjBLaEI1TU1lQXltN01WL000VzBhNDlvZ1BEOXBNQ0F3RUFBYU1nTUI0d0RBWURWUjBUQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FvUXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSld6NXhMTWs1V05ZYkFiNnlPeEVDQm9aMldlQi9xbDRWSjNPLzMvdE5zeE9ZbnpMZVdvNTQwelFoOXJBbWF4ejdldW1CbHNrTXE0eUdQU05YQjl5Y1dHSGdrY0NlU3pOMnd2OENJekRCczJvQlpqVE5rNjVMQlpEc3NUT0J0TVcvK3VURkhRZmJ1TzNJU0xoSTBEWGZSRWk5TkRNM2pmazExeEhjc2ZoMlJNVitRZE5md1ZhWlpyQ3Erb3VHK0V2a3Y3S3FxK295dTBWRk0vdHo2OFRHbDZ5bGhQRlIxcWg5d3R0cFZqQU9PQ0VRQ0xxUDJkUDI4bHdZQnlDcUhRcVZId2J1anYvTFpqWm5LVzNMWW5kWml4UFBTUkNKc3NERHdKdmgvZjZuVHhnOVpFKy9KY1lyZTVDYUk4bnpWSGFTT0NqTko3RnpVTEc2NEppV092UTUwPSIsIk1JSURkVENDQWwyZ0F3SUJBZ0lKQUlDVVR2a2d0ajVDTUEwR0NTcUdTSWIzRFFFQkN3VUFNRkV4Q3pBSkJnTlZCQVlUQWtaU01Rd3dDZ1lEVlFRS0RBTkVTVk14Q3pBSkJnTlZCQXNNQWtOVE1TY3dKUVlEVlFRRERCNUhaVzFoYkhSdklFMTFiSFJwUVhCd0lFWkpSRThnVTNWaVkyRWdRMEV3SGhjTk1qQXdOekEzTVRRek56RTRXaGNOTXpBd056QTFNVFF6TnpFNFdqQlJNUXN3Q1FZRFZRUUdFd0pHVWpFTU1Bb0dBMVVFQ2d3RFJFbFRNUXN3Q1FZRFZRUUxEQUpEVXpFbk1DVUdBMVVFQXd3ZVIyVnRZV3gwYnlCTmRXeDBhVUZ3Y0NCR1NVUlBJRk4xWW1OaElFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXZBS09lcUM1L3AwRDFpc0NZS1FKbFZVT3JCNkk3RExvY3VuRS9SbThkdUdUYnl4UWh0M0NiRlZUdjNOMkxwMmZianhsSSszc09TR2szM0ZUWWtUcXhjZEpJcko3U3NrQmNVU05yZktPYVFULzZLUWNQNENtN1YrNjU1VHErVFd4eXhXUWhEeWd0MTVxb1A3TXVLNmJUOVN3cENqcGZLaGFNU215UWFNb1VjUkFiTHFkekJDYWMwaHpCK1plK2dxSmxuV1Y5VWFTSTJyRnNWdUg0WkUwY1JPK01PcGFMZ00vczI0OG5HR0hwMjJld1NRZmJuUGFCYmI4aXF5QVArY3U1MkdMc1VwS1JKZWJFK1I2K1BNUTlKQ2RXZVFaUjNEa2ZTaWRrdjNtY2I0anExaUl0YStNcUtoUm53cmZYaDkxMUtXTG5ZQWw5RU5DaExYMGM2U2oxUUlEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVV0x2aFJCVVBuOHVMSWY2OCtndi9OWkl3R1NJd0h3WURWUjBqQkJnd0ZvQVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3REFZRFZSMFRCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGTHJEaGFlZ2VLSHhZakgzRVAzdlVCS2huek0yMDZBU3hnZVlDTzJFYzlwT2xZSmFlcUZFK3NVYW1VVi9wd2pEbHFOYVNnRmd5N1R3ZVlrdk9tTW40cVNjc0hxdkozekdPQWlhZndhaDF2VUhmQ2xYUjgrYXhPMmlHT1VGMEpLclo5WVlqYkFhNS80SENsdjdqRlBPZE1XVE9ReW5nb2lIQXMzamt1WWpwQ0xGbEI0Vk9pM2Qxd2pBMXBuVGRCS2tBYjd0OG5UdncrL1hiRnZjUWE3M1ZIN3Nqdm9CcUQzZmRNZlJjdVZxNHFVWnRaVDZjR2FnVEhENjFUdHFoOW9NQ1pYY0RiUjFQR1puTmJxeWNzV1BESUswbnBtSzMvM2xmVjhjK1pzcnk2ZTE3MG1mSk1acDdPOG02Q1N6Ni9WTEsreURKZDc4NDF3cG1lS1RmNkluWkE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFRd0FBQUFnQ0FZQUFBRG5sVVpxQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUVuUUFBQkowQWQ1bUgzZ0FBQUFaZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakF1TWpIeElHbVZBQUFLMUVsRVFWUjRYdTFkRFhBY1pSbStOT0FmS29nNldPMFFjcmVYM083MVI0MW9IZFNxcURBT2czK2NZRVhCb2xYUlRFbjIyMHRhS1RjNjRtZ0JxekJpRVVWcEJkcWl3d2hxU2RJUzJ1cFlTZ3ZSdHBUU2NrbGpXekhhZ2pwU1JkcjR2THR2anJ2azI3dmR2ZDFMam43UHpETjN0L2QrNy90K2Y4Lys3OGFLME5EYWFyMnFPZFhab3FXeUg5UjBhMEZjdDY3V2RIR1Rab2pWQ2NQcVNlalcxb1F1SHNPeS9lQlRzRG1NLzU0WlQ5aitMV0dJZzdEZkIvc0JjRFBzZjRYZlA4WDNiMnVHMVpIUXpVOG1VdUtkeVdUSG01cWFjaS9qSEFLQnlpZjBiQnIrTHdhWElQWVBrTWRxZkw4WGRXcGxzMUFBMzEvUWpPdzk4TDhTOWI4QlhJUjIrbkRjNkRvemxzazBzbG5rUU14a1BHWE85RUp0Vm5ZR0Y0c1V5Vm5kOFVUYWVwOGJ3KzZMYWtCajVpemRiTkpTMXJ4RVdueVd4ZzM2RW1QZFdvUFBEZWpmN2VBVEdNc0hhRHpUdUM2aGJqME4vcFhtQXNydWdzMFdMUDhOdUJKalpKbVdFbGNsMDltUEoxSm1XMHRMNSt1aUhCdUdrWHNsalg4N25pNEV6Vm5rOUF2a3NRbjU3RVNkaHJCOEJNdVBqT1dQLy80T0hzUi9lN0Q4WWRUbGZ0UmhGZmdkTEc5SHUxd0FmenI1NWpBT2tpUUtodlZiR0I2QzAvL2krMmlOZVJ4OEZnbnZSZnhmYWluelNrN05FMGlJVVBiZjQzd1dtTlROZDdCcEtFQTdMWmZGQVk5enAzeVpUU01EaVFWaS9VK1NnNVFZQUlmT21HMmV3c1VqQS9yaFc3TDRCZXJtajloMFVvQjJPQitUWlRXNEIvazhPeUcveUNpT29XMUlZSDZIOFhQejlMYmNLemlsUUdocE1admhaeUhHd0czZzQyQms4NVo4bzkwRzhYME5pU3MxSXYyUUdrOEtkV3N6dDRzbklQOFJxUjltRFFYRElkWlNiQm9aMElsM1MyT1haWFlwRjQ4TVUxNHduSzFiZVc0MXBMM0ZFUUNKbFBWV3RERzJmdXlWck5SM3RCVGRTakI4WXJJRm95VnRubzJPQ3pCZ3hETkJCNnBYS01Id3hpRDlnSzNLYzZQY2t2QkdKUmkrTWNtQzBZRDRmZEs0WG9oOVcvWVRDWlJnZUtOdndjaGtHdEcyZTJXK2Frc2xHTDR4bVlKQmF4bHBUSStrTlJRZG1HUjNvVU1KaGpmNkZRdzZjQ3J6VTN0Q01MRFd1UXNkM1IrQXczS25CUTVLeW5qaGpkeE9ubkRpQ0VadUdqcnNZV2xNSnRwaVdVSzNCbVQvRmZFdWRoZzZVUGU2Rmd6MGJSNmZhNk1tblkza2xEd2hhWWpMVVU2ZXMyN3QwZ3p6bTdWZ1V1OTZENmZrSHhDYTYyVVZHQ01xOGcwMmpSUW5pbUJvUnZZaWFUd20ybnRmVzl2Q2s3VzBkWUhzL3dKMTYzazZlTVp1UTBXOUN3Ykc5SzFzT3FXQXZJVTBYNXRpRFp0TmJTakJjR0VFZ3RIV2Rzdko4RTJuQXVVeGlicDVoV005Mm9EZjJ5YjhYMEt4M3JFTkYwb3dvZ0htMGhKcHZqYVZZUGpDaVNBWWliVDFlV2tzSmliQ2svUG01VTVpYzhyeFFwbGRNUlBwN0hsc0hocVVZRVFESlJnaDRzVXVHSFNSRCtwSVYrVEo0eEgxTEc5ZGpDSFRpTWxSNFZpRzJFN0hSYmhBS0ZDQ0VRMlVZSVNJRjd0Z29KMnowamhNdEhPZWpsMndlUUZZL2xHWmZTbkZmRFlQQlVvd29rSENNQmRMODdXcEJNTVhLZ3FHSVM1dlRwdG5oMFhVKzA1Wm5BSkRGQXpENkRnZC9wNld4bUhHRGZGRk5oK0gwUWIwd2FPeU1tT0UrT1VOSS9jU0xsQTE2bDB3MEY2NzQ3cTRwUnBHY2RxYTdrdVI1VXRFSDQ1Z0Rtd0tpL0RaajgvN0lFUzM0ck96ZWFhWXpXbFVoM29SakpvelJNR29PQUVOYTBpMmRUR0dlRXA4VEZKbVBEdll2R3JVdTJDRVFicWhrc09GQnN5bGkyV3hhc1RqNk5kMTJwc1h2NTdUQ1FZbEdDNE1TVEJhVzYwM29vMWRiNnF6cVZ0ZlluTTU2QXBCdzlveG9Wd1JNWWxHTkszOTFWeWlLaWpCaUVZd21sUGRMYkpZdFNUYTdxSGlBK3Urb1FURGhTRUpCdHB2aGRUL0dIV3h2OXpXeFJpMHRQaUV0SHdKeGJWc1hoV1VZRVFqR0hSd0d1T2gwZ1Y1a1RPZU1pL2hoUHhEQ1lZTFF4Q01zMXF0Vmd6dThyZXZweXlQandId3NwVmgvU3VWV2pLZEN3U0dFb3lvQkFPNXA4MzNvcCtlazhXc0ZkRit3YThTVm9MaHdoQUVBMzdXVFBCYlJIVGNBZXhHdkpUTkhmUU1OY2Y2QnMrUDllYm54ZnFlUEpXWDJrQ1p6SGdmRXhqQ0dRSWxHTkVKQnNGK0VKRXVkc3ZpMW9iaVQ1eUtmOVNOWU9qV1pqVHlmYUhSdWQ5QUhvdFlwV0E0TnhxSlkxTGZUTlQ1SzJ3ZWk2MGZNaUFVRDRLakJmYm1qOGI2OHN0ajJ3N2FEMnFoZlUvMHh5NlpyekhTMnF1bHBUTmwrd3lJdWhjTWpCVTY2MVFObTJjdVBvUERSWVRSQmpwYlIyTUFPVjlIWnpPUTk4L3cvZll3aVBIdGZqZTBidjJGay9DUGVoR01PcnNPby9MdDY3bzFYRGdWdWlFL0J3THhqeEt4S09YRzJNNmR0aTM2dzhPUmRuR1A3VGNna0Z1ZEM4YlV2QTZqbGtpa084K1R0ZzJJTVhTWXpmeERDWVlMcXhBTUw3ZXZvNzd0dG5GLy8wbllrdGdoRVlseEhMcWF6SjJ0akVxYnM5aXlTV1huMnY0RFFBbEcvYU9zWUJqV0FUYnpEeVVZTGd3c0dMbHBLTHRWNnBOSkhWWjRZSExmL25mSkJXSUNoMkhkUUVYaTZld2xNcjhsZEo1SFl0djdoUktNK2tjNXdVRDc3R1V6LzFDQzRjS0FndUhwOUdkS1hNWG1FSXg4dTBRY1hQallhKzB5bVV3ajJ1dHhxZThpb280WDJ2WStvUVNqL2xGaGwrU1BiT1lmU2pCY0dFQXc2SG9LN0E2VW5jaW81OEdtcHN0ZWVCMUQ3OUJYNWVJZzRmM0RwM09wR09MTWwva2Z4eDJ4ekZyZmo4VlhnbEgvcUxCTHNvWE4vRU1KaGdzRENFWWlWZjcyZFdicEpkdzkrODZSaXNONDlnN3VoM1ZoRjRQRjZRbUovMUxxMWdJdTRobVZCQU1UOXU3eDcwd0pnL1RZZlU2aExKUmdWRWFGWFpJSDJNdy9sR0M0MEtkZ3pKNXRuZ0tmQjZTK21Qai8wSXdaSFMvbklnNUdSeHNoQmdOU2tTamxZaTVSQVBydVVsbWNZbUp5L1huRzNIRXhLNkRpRmtaRXhCall5Q21VUlNYQlFEdVBvQTVibzJiU3lMNmRVL0lFM2lxVW5nWU5tMmdEMTdOMCtHOFZwK1FmU2pCYzZGTXc0cnBsU2YwVUVURk5OaTlGei9ETVdHLytpRVFrSFBibU44UzJiWnQ0K2JoemowbjVKM2lCZEZzMWwvQUUxTDJ1QmFOV1RPcmlBNXlTSnlEdjc4cjgxSnllcnk2V1FBbUdDMzBJUnRPYzNHbG9wOE5TUDJQVXhWTmwxL1RyOHEyeHZ2eDY4UGtpc2ZnbmZsOGY2eDkwZlFVbDRuNUdHcStZdWpoeTVxenUxM0NSaWxDQzRZMTFLUmowV2tndEYvd21SU1VZTHZRaEdGNG1HQWFMWVBQeTJEZzBQZFl6OUg3c3BzeU45UXhVZkMwaVhmeUZQdG9uaTFsTUdxeGNwQ0tVWUhoajNRa0d4Q0twVysvbWRJSkJDWVlMUFFvR3ZZUWE5dVhmNzFscDY2SktsSHQ4L1FzVVIrMFhUWHVBRWd4dnJBL0JvTGZyMlFmSHIvR3psZW1LS1NNWXVua0hUU3pFbEw0K3NGYUNnZm8rQis3V2pPem4yTFFzbk5jR2lEMVVUdWJQb2RuRjVwR0F6cGdndnV0V0J1cjZIN3RPdXJpVWk1UUZYU1dLTXQvSEJONUVheVhVcit3OU1jRXBqdkdLNHZmSWJ3VmR3OElwbEFXTkJaUzVEdldoTjVYbjRlZG9xZDhvaUZ5eDJ3aytpdS8wSXVpbDlLd1RUc2tUNG1seER0cnpSbTVYalBVbzJwWGU2RzQ5Z2p4dncrZkNoTkdoY2Zod1FDOWphVExFRzl4b0dGZVd2aVkrVXVTbTJRK2NvWGR5Nk5ZaU5Pd3lWUHJIR0JoM0pvenVVQ3NlVDVtWFFmRi9qaGcveE9mWE5kMjhnam8wYUgzcExBbE5OR2R0TDVZaTU1dlFnYmVqNCs2Zy85Z3NNcUFPSDNIYVNmd0ViWGNEdm1lVGh2VXBUZTk2eTRRek03NlFtOVkwWjlGcGRQY202dk5wc0F0OXN0eHBPK3ZYNEViRTIwb1RDY3NHU29ubCtCL2Y2V2EvVmNWNTBhU1B4N3RPRGVFQnhnMTB4eStka29YZ2ZBZ3hGaURlMTlBTzMwTS9yRVFPOXlMbUE0aS9CYiszbCtibmtQSUhONFByVUwrMStGd0IyMnZob3gxaWYxRzgxWHBidkEyNVpqSytyMmx4UjI0YTFkOFJQekVmdXdvV2NzRVdpSk16WWorSTN3K1Z0S3NoSGdIL0FQWlNucWpUemZpOHhoNjd1blV1UGRyQTI4TnhZckgvQXozdEk0ajUrVE9MQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiMjE5NGI0Mjg5Mzk3NDA0NjhmMzkwMDdhMTYwNWE0ODIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wMS0wNCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDEtMDQifSx7ImFhZ3VpZCI6IjM5YTU2NDdlLTE4NTMtNDQ2Yy1hMWY2LWE3OWJhZTlmNWJjNyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiMzlhNTY0N2UtMTg1My00NDZjLWExZjYtYTc5YmFlOWY1YmM3IiwiZGVzY3JpcHRpb24iOiJJRG1lbG9uIEFuZHJvaWQgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InZvaWNlcHJpbnRfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmYWNlcHJpbnRfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImxvY2F0aW9uX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhdHRlcm5faW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJleWVwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImhhbmRwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCeXpDQ0FYR2dBd0lCQWdJSkFObU1OSzZqVnB1dU1Bb0dDQ3FHU000OUJBTUNNRUV4SkRBaUJnTlZCQW9NRzFaaGJtTnZjM2x6SUVSaGRHRWdVMlZqZFhKcGRIa2dTVzVqTGpFWk1CY0dBMVVFQXd3UVZtRnVZMjl6ZVhNZ1VtOXZkQ0JEUVRBZ0Z3MHlNakV5TVRReE9EUXhNRGxhR0E4eU1EY3lNVEl3TVRFNE5ERXdPVm93UVRFa01DSUdBMVVFQ2d3YlZtRnVZMjl6ZVhNZ1JHRjBZU0JUWldOMWNtbDBlU0JKYm1NdU1Sa3dGd1lEVlFRRERCQldZVzVqYjNONWN5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWFsWWdFb3BuS1NjQW0rZDlmMVhwR0IzemJrWkNEM2haRUt1eFRjbHBCWWxqNHlwTlJnMGdNU2E3Z2VCZ2Q2bmNrNTBZYVZoZHk3NXVJYzJ3YldYOHQ2TlFNRTR3SFFZRFZSME9CQllFRk94eWYwY0RzOFlsK1ZuV1NaMXVZSkFLa0ZlVk1COEdBMVVkSXdRWU1CYUFGT3h5ZjBjRHM4WWwrVm5XU1oxdVlKQUtrRmVWTUF3R0ExVWRFd1FGTUFNQkFmOHdDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTzJYdWlSRFh4eS9Va1doc3VaUVlOVVhlT2owOEFlVFdBREFxWHZjQTMwaEFpQmkyY2RHZDYxUE53SERUWWpYUGVuUGNEOFMwckZURG5jTldmczNFL1dEWEE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FNQUFBQkVwSXJHQUFBQU0xQk1WRVV0bWMzeStmeVd6T1ppczlySzVmSTZuOUI4ditDdzJlemw4dmxIcHROVnJOYlg3UGFqMHVsdnVkMjkzKytKeHVQLy8vODlIUnZwQUFBQUVYUlNUbFAvLy8vLy8vLy8vLy8vLy8vLy8vLy9BQ1d0bVdJQUFBQnNTVVJCVkhnQnhkUEJDb0F3RElQaC95RGlzZS8vdElJUUNabzZSTkdkdHVXRHN0RlNnL1VPZ01pQURRQko2SjRpQ3dTNEJnekJ1RVFIQ29GYSttZE0rcWlqc0RNVmhCZmRvUkZhQUw0bkFlNkFlZ2hPRFlQbnNhTnlMdUFxZzVBSHdPOUFZdTVCbXFFUGhuY0ZtZWN2TTVLS1FITUFBQUFBU1VWT1JLNUNZSUk9IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIzOWE1NjQ3ZTE4NTM0NDZjYTFmNmE3OWJhZTlmNWJjNyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDItMTMiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlZhbmNvc3lzIEFuZHJvaWQgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwMTA5MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDItMTMifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTAyLTEzIn0seyJhYWd1aWQiOiI2NjRkOWY2Ny04NGEyLTQxMmEtOWZmNy1iNGY3ZDhlZTZkMDUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjY2NGQ5ZjY3LTg0YTItNDEyYS05ZmY3LWI0ZjdkOGVlNmQwNSIsImRlc2NyaXB0aW9uIjoiT3BlblNLIGF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciLCJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQkdEQ0J3QUlKQU04QTNlaGRwaUZ1TUFvR0NDcUdTTTQ5QkFNQ01CUXhFakFRQmdOVkJBTU1DVTl3Wlc1VFN5QkRRVEFnRncweU1EQTVNVFF4TWpFeU5EQmFHQTh5TURnd01Ea3hOREV5TVRJME1Gb3dGREVTTUJBR0ExVUVBd3dKVDNCbGJsTkxJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFcy81NFgvSTh5ZG1aZ0ZWRUo0eUtubEE0dUlKcmFtQVFjYzNkbzJ4RHpSR2N4RFR6dHRJYmRrNFhYMnJ6NmFaRVRlWHQ3RTgrN0hNTEk0a2h1SnBVWGpBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBaG5UTFhpdDRHSk5IcWg4aDFESE5iOTBWNU9XNXZSbU9sNmx2RS9jUHo5UUlnYjNkM2h1RTNZaDB5US9IUXVJbzZkSE0rRi80dGVhemhKWkYxNWdZTHdDYz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRUFBQUFCQUNBWUFBQUNxYVhIZUFBQUFBWE5TUjBJQXJzNGM2UUFBQUVSbFdFbG1UVTBBS2dBQUFBZ0FBWWRwQUFRQUFBQUJBQUFBR2dBQUFBQUFBNkFCQUFNQUFBQUJBQUVBQUtBQ0FBUUFBQUFCQUFBQVFLQURBQVFBQUFBQkFBQUFRQUFBQUFCR1VVS3dBQUFJUTBsRVFWUjRBZTFhQ1ZTVVZSVCtrR1ZZQkJRRkJZellGSkZOTGRQUVZrc3o4NVFuc3pSTmJhUE56REkwT2FJSDI3VlVVbk9wekFxWE1KTklzektUVUVRV1JYQm5FeFJpVVlFVUJBVHMzbGZ6SnczTERQL01NT2ZNUEkvTSsrOTcvLy91dmUrKys5Nzk3ak83VGdWR1hMb1lzZXhDZEpNQ1RCWmc1Qm93TFFFak53Q1lMTUJrQVVhdUFkTVNNSElEZ0VWbktxQzgvQUtPWmgyRG82TURBZ01Hd01iYVd1L3M2RlVCVFUxTnlNbk5ROGJSVFBxZmhlSS9TeVNCemMzTjRkZXZMd2FHQkdGZ2NCQmNYSnlsTmwxV3pIUWREVmJYMUNEcjJIRWNKWUV6NmJlNnVrWXRlVnhkZXd0RnNFTDYrdnFnU3hmZHVDdWRLYUNnc0JDYnQyN0RtZXhjOE16TEtiYTJ0Z2dPQ2tEWXN6TmdabVltNTFNcTcrcEdyVFJNY1hFSlRwM09saTA4YzF4RFZwUjhLQlc2Z0M1MHBnQVZWUnNvUVdjS2NIZDN3NGpodDZONzkyNEdLdm8vYkdsMUYrQzFmdTc4ZVdIK1RkZWJjT2VJVUV5Zk9oa0hrMU93SlhZN09jQnFnMU9HMWhSd0lDa1ozOGZGNDhMRlM4MkVkSExxamttUFQ4RGloUkY0YjhuSDRMM2ZrSXJzSmNDTzZjdXZZckQraTQwcXdyT2dseTVWWU5XbjY1R1VmQWpoYjd3R0t5c3JRNUpmZmppOGEvZXYyUGZIL25hRjJyWTlqbWEvSEErUEc5dHVYMzEya0xVRXJseTVncmo0SDlYbU4zYjdEaXg0S3h6MzNuMkgydStjenM1QjlNbzFzTFMwMU1saFNKWUMwZzVub0w3K1dqTmgrTkF5ZHN4b01uVkwvRVRXY2FtaVFtclB6eTlBWldVVjJDK29XL2hZN0tURG5VU1dEeWdvS0ZTUlkvcFRrMGtCbzNEL3lIdnd5b3ZQcTdTWGxwV3IwTm9pL1BaN2d2QXREZzRPYlhYcmNKc3NCZFRWMTZzTTdPN21KdEZhRG1oVUUxSEZ4WC9TcWZHTTlKNnlrcHlTaW04MmJSV1BIamYxVVpLMStpdExBVDFhTU9Xa2c0Y2tCaE1TVloyanU1dXIxTTQ3eU81ZjlpQXk2bDE4c0hRNTl0SnNLMHZpZ1lOWXUzNkRkUHoxOHZKVU5tbjFWNVlQNEJnK2Z1ZnVaZ3o1K25oTHp6WTJObEtkS3dFRCtxT0poTjd4dzA0aDJQRVRKMFY0ck96MFZjd1duRGgxV2dROHFXbUhsV1R4SEJJY0tEMXJzeUpMQVJ5L2UzdDVJaS8vck9ESng5c0xnd1lHUy96ZGVzc2d4R3orRm8yTmpXTC9mMkxpQlB4SUN0dXpkNS9VNS8rVnRQUWoveWZCMzY4ZnVqazZxdEMxUVpDMUJKaUJaNStlQnR0L1ovcXhSeDlweHBPRHZUMkczejRVRmhZV0NIdHVCaTVmdmd4MmFwcVdVYU5HYXZxSzJ2MjFnZ2NVRko0VGg2RnBVeWFwREh6aDRrWFUxdGFLN1cvbDZuV29yYXRUNmRNV3dmTm1EeXhhOEZaYlhXUzFhVVVCN1hHUWtabUY1ZEdyMit1bTBzN2d4OEtJdWZEMHZGbWxUVnNFMlV0QUhVYUNBd01JMXZyUE9hcnpEdmNaTjNhTVRvWG5NZlNpQU1ielhuaitHWFRycHI0akd6d29CT01mZm9oNTFHblJpd0pZZ2g1T1RwajM1dXRxZWZPZ3dBR0UvejJ0ZGZ5dkpVM3F4UWZjT0hBWkhZVS9XYjJXZ0pPaUc4bFNmWGpvTU14NGFncnRIT1lTVFpjVnZTdUFoYW0vZGcyYnQ4VGk5NFJFU1RZYkcydE1mWElTUW9mZEp0SDBVZWtVQlNnRlkrZzg5cnM0dUxuMXhyZ0h4OERldnF1eVNXKy9uYW9BdlVuWnhrQjZjNEp0OE5DcFRTWUZkS3I2RFdEd0RsdEFRME1qamgwL2lmUWpHV0JzVUZmbGZGRVJPRFRPeXpzckRWRlJVWW5zbkZ6cHVaNkFtUk1uVDNVSWN1OVFPTXdCem9jZnJTREJxMkZIR0dCbFZSVmVDbnVHUXVFUWlTbHRWRFpzL0FhSFV0TGc0WEdUU0xqMDgvWEZySmt2SWpYOU1JR3h1N0JxeFZLQkt6QWtuNXVYVDNIRFBJMkg3WkFDTm0yT0ZaY1pvaUxudzVvdU5URGF1Lzd6alZpMjlIMWNyYjJLU3BvaE96czduS1Z0anBubUN4REt3dGdCenlCakNWMjcybEdJZkFXbFpXWG81ZUtDTXprNTZFT1FXcTllTGlnaW1Dd2g4UURtejUyRGZuMTlVRnBhaHJrUkM4bnFUaWcvSlg3ajRuY2lNK3M0SXViTmFUWk9zMDV0UEdpc0FBWTMrRmJIMU1tUEMrSDUyNlB2SDRtZHUzNm1WSGkyU0lURTBDSEh4YmtuZUpuOFJSakE0a1VSNGlqOCtZYXZ4WkxwMmNOSm9NVlJrUkhJemM4WDBGY2Z5aVUyTlYwbndZc28vSjB2aE9GTEV5bXBhWEIzZHhWS1dmZHBOQ3lJVmtMSzRKS1NsaTRzNGRXWHc5QlJ6RkJqSDhENVBWYkNqWUVOQXg4YzhGUlYvU1VZNHo4TDVvZmpuYWdGUXBCOWRPTGptVTg4a0lSSW9rZFJtc3kxZDIvOHNtZXY2Ti9RMElEWFgzdUY2Q3k0bzFqUC9FMUdsWTlrWk9MVjJlR0lYclVHWldRcHlvc1NkWVFyZkVhbTcwaG9jZi8rZnRLNG1sWTBWb0JDOGM4OW50cmEvNEFORm9BVG93cHJoUmlmRVNDRlFnR2VRUjh2VHpMeGNoUVNhTUx4L1NjRWlrUkVMaFltWGthWklqUDZ4NFVGNXNMb0VqczFMZ3l2TFhsL01lYk1ub2xHc3FhMzMxMGlsZyszOFpoMzNURUMxK2xmekwvSU1kTTFMUm92QVlYQ1NwZ2J6OHl3b1VQRWVNcDE2ZXZ0VGV2eFdETWVLaWdSd2liUEN1SFptelh6QlZoWldnbkdyU2piYy9LVUtoek9IMkJJbkJNcmJFbitOTVBlWGw0SWUzbVdCS0p5QXViSlNSUEZ6WkdQbHE5RUNGMmxHWExMNEdaanEvT2dzUUw0b3hNbmpNZXk2RlZZOTVrNW5KMTdDSkNUL1lEeUxnRGY2TmhFZm9BREhONmV3dCtZSllBTlB1c3p6cytNSmxISy9CNUtrWFV4YTlrSS9mMzhzR1hyZDFpNkxCcEJnUUcwN2VVSjYvRDI5a1Q2NFF3cFZPYTJrZmZlSlJLMFBBRktIdFFSbnZ1WUw2S2libWRsUDA1NDhPVWw5c3g4QnVBczBBT2o3eFBObkMzS3BUMmJFV0VPZVI5OFlKVFlIaTFwV1F5NWRUQktTa3B4bHZvTThQY2p3SFNZZ01sNXlmQWRJQzQxTlZmaFJSQVlPN1hRMEtHRUo5YUpKY1JPZGRxVXlYRHV5YzYxQVRhMk5nanc3eS9lWWRTWWNVY3ViamZrSFFTaG5UOWFENFlTL3RpUDdUdmlzZUxqRDlvWjJqQ2FXN1kvR2J6Wmt6UHo4TkJOR2tzR1c2MitxblVMYUhVa0EyM1F1Z1VZcUp5dHNtVlNRS3VxTVpJR2t3VVl5VVMzS3FiSkFscFZqWkUwbUN6QVNDYTZWVEgvQm5veS8wS0Y3dytPQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiVTJGX1YyIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiNjY0ZDlmNjc4NGEyNDEyYTlmZjdiNGY3ZDhlZTZkMDUiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDItMDkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ik9wZW5TSyBhdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTAyMDkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAyLTA5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMi0wOCJ9LHsiYWFndWlkIjoiMzc4OWRhOTEtZjk0My00NmJjLTk1YzMtNTBlYTIwMTJmMDNhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIzNzg5ZGE5MS1mOTQzLTQ2YmMtOTVjMy01MGVhMjAxMmYwM2EiLCJkZXNjcmlwdGlvbiI6Ik5FT1dBVkUgV2lua2VvIEZJRE8yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDSFRDQ0FjS2dBd0lCQWdJQ2RkVXdDZ1lJS29aSXpqMEVBd0l3ZXpFTE1Ba0dBMVVFQmhNQ1JsSXhFekFSQmdOVkJBb1RDa05sY25SRmRYSnZjR1V4RnpBVkJnTlZCQXNURGpBd01ESWdORE0wTWpBeU1UZ3dNU1F3SWdZRFZRUURFeHREWlhKMFJYVnliM0JsSUVWc2JHbHdkR2xqSUZKdmIzUWdRMEV4R0RBV0JnTlZCR0VURDA1VVVrWlNMVFF6TkRJd01qRTRNREFlRncweE9EQXhNakl5TXpBd01EQmFGdzB5T0RBeE1qSXlNekF3TURCYU1Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUejJqTmFLT0svTUtkVzJmbWUxdHE2R1JFdVB1dUtXOUhnV1lnTVJyanZaVVRPcUxBTkozTWQ1SHF2MUVOMXpNZDRsV3R5ZnpSbGE3cnY1QVJCb09vVG96WXdOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQkVHQTFVZERnUUtCQWhOblRXMGE0RTh1akFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTXJoYjhTbWZOTGVMTmdhQVZtUTZBT01pTE5MVkhYMGtGVU84MENuVDM4RUFpRUF6TkFndjRkSCtIRGhaU2daV0ppYVB1L25mWlRldUd5NE15ZFBNcTV1cnM0PSIsIk1JSUVPRENDQTkyZ0F3SUJBZ0lEQUluQk1Bb0dDQ3FHU000OUJBTUNNSHN4Q3pBSkJnTlZCQVlUQWtaU01STXdFUVlEVlFRS0V3cERaWEowUlhWeWIzQmxNUmN3RlFZRFZRUUxFdzR3TURBeUlEUXpOREl3TWpFNE1ERWtNQ0lHQTFVRUF4TWJRMlZ5ZEVWMWNtOXdaU0JGYkd4cGNIUnBZeUJTYjI5MElFTkJNUmd3RmdZRFZRUmhFdzlPVkZKR1VpMDBNelF5TURJeE9EQXdIaGNOTVRnd01qSXlNak13TURBd1doY05Namd3TVRJeE1qTXdNREF3V2pCME1Rc3dDUVlEVlFRR0V3SkdVakVUTUJFR0ExVUVDaE1LUTJWeWRFVjFjbTl3WlRFWE1CVUdBMVVFQ3hNT01EQXdNaUEwTXpReU1ESXhPREF4SFRBYkJnTlZCQU1URkVObGNuUkZkWEp2Y0dVZ1NXUmxZM2x6SUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTTFZMKzFTVEp2YUVSTzVXQ1IrakdjQXhMdm1QQkRpWlkxTmdGRklocFg2T0FaQXBRWW10NnhTaDc0U3dNK21qZ25zU0VjYzRBMlVmMTM5RmdaNHJwWW80SUNWVENDQWxFd0V3WURWUjBqQkF3d0NvQUlUWjAxdEd1QlBMb3dTZ1lJS3dZQkJRVUhBUUVFUGpBOE1Eb0dDQ3NHQVFVRkJ6QUNoaTVvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMlZqWDNKdmIzUXVZM0owTUZNR0ExVWRJQVJNTUVvd1NBWUpLb0Y2QVdrcEFRRUFNRHN3T1FZSUt3WUJCUVVIQWdFV0xXaDBkSEJ6T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdlkyaGhhVzVsTFdSbExXTnZibVpwWVc1alpUQ0NBV0FHQTFVZEh3U0NBVmN3Z2dGVE1EK2dQYUE3aGpsb2RIUndPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2Y21WbVpYSmxibU5sTDJObGNuUmxkWEp2Y0dWZlpXTmZjbTl2ZEM1amNtd3dnWWFnZ1lPZ2dZQ0dmbXhrWVhBNkx5OXNZM0l4TG1ObGNuUmxkWEp2Y0dVdVpuSXZZMjQ5UTJWeWRFVjFjbTl3WlNVeU1FVnNiR2x3ZEdsakpUSXdVbTl2ZENVeU1FTkJMRzkxUFRBd01ESWxNakEwTXpReU1ESXhPREFzYnoxRFpYSjBSWFZ5YjNCbExHTTlSbEkvWTJWeWRHbG1hV05oZEdWU1pYWnZZMkYwYVc5dVRHbHpkRENCaHFDQmc2Q0JnSVorYkdSaGNEb3ZMMnhqY2pJdVkyVnlkR1YxY205d1pTNW1jaTlqYmoxRFpYSjBSWFZ5YjNCbEpUSXdSV3hzYVhCMGFXTWxNakJTYjI5MEpUSXdRMEVzYjNVOU1EQXdNaVV5TURRek5ESXdNakU0TUN4dlBVTmxjblJGZFhKdmNHVXNZejFHVWo5alpYSjBhV1pwWTJGMFpWSmxkbTlqWVhScGIyNU1hWE4wTUJFR0ExVWREZ1FLQkFoRGFRYmhURnRqY2pBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQW9FZXBITUM1WDlqQkthR3BoY0tqaWRoaU4rWm56N3YzUzNoYzMxL0F1bnNDSVFES3FvZ0syU1pPWFpjdnZIQ0I2VVFTYUEwbkxuNFJVd3kxZ3VEaXZiWmJ3Zz09IiwiTUlJRU9EQ0NBOTJnQXdJQkFnSURBSW5CTUFvR0NDcUdTTTQ5QkFNQ01Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd0hoY05NVGd3TWpJeU1qTXdNREF3V2hjTk1qZ3dNVEl4TWpNd01EQXdXakIwTVFzd0NRWURWUVFHRXdKR1VqRVRNQkVHQTFVRUNoTUtRMlZ5ZEVWMWNtOXdaVEVYTUJVR0ExVUVDeE1PTURBd01pQTBNelF5TURJeE9EQXhIVEFiQmdOVkJBTVRGRU5sY25SRmRYSnZjR1VnU1dSbFkzbHpJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVNMVkwrMVNUSnZhRVJPNVdDUitqR2NBeEx2bVBCRGlaWTFOZ0ZGSWhwWDZPQVpBcFFZbXQ2eFNoNzRTd00rbWpnbnNTRWNjNEEyVWYxMzlGZ1o0cnBZbzRJQ1ZUQ0NBbEV3RXdZRFZSMGpCQXd3Q29BSVRaMDF0R3VCUExvd1NnWUlLd1lCQlFVSEFRRUVQakE4TURvR0NDc0dBUVVGQnpBQ2hpNW9kSFJ3T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdmNtVm1aWEpsYm1ObEwyVmpYM0p2YjNRdVkzSjBNRk1HQTFVZElBUk1NRW93U0FZSktvRjZBV2twQVFFQU1Ec3dPUVlJS3dZQkJRVUhBZ0VXTFdoMGRIQnpPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2WTJoaGFXNWxMV1JsTFdOdmJtWnBZVzVqWlRDQ0FXQUdBMVVkSHdTQ0FWY3dnZ0ZUTUQrZ1BhQTdoamxvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMk5sY25SbGRYSnZjR1ZmWldOZmNtOXZkQzVqY213d2dZYWdnWU9nZ1lDR2ZteGtZWEE2THk5c1kzSXhMbU5sY25SbGRYSnZjR1V1Wm5JdlkyNDlRMlZ5ZEVWMWNtOXdaU1V5TUVWc2JHbHdkR2xqSlRJd1VtOXZkQ1V5TUVOQkxHOTFQVEF3TURJbE1qQTBNelF5TURJeE9EQXNiejFEWlhKMFJYVnliM0JsTEdNOVJsSS9ZMlZ5ZEdsbWFXTmhkR1ZTWlhadlkyRjBhVzl1VEdsemREQ0JocUNCZzZDQmdJWitiR1JoY0RvdkwyeGpjakl1WTJWeWRHVjFjbTl3WlM1bWNpOWpiajFEWlhKMFJYVnliM0JsSlRJd1JXeHNhWEIwYVdNbE1qQlNiMjkwSlRJd1EwRXNiM1U5TURBd01pVXlNRFF6TkRJd01qRTRNQ3h2UFVObGNuUkZkWEp2Y0dVc1l6MUdVajlqWlhKMGFXWnBZMkYwWlZKbGRtOWpZWFJwYjI1TWFYTjBNQkVHQTFVZERnUUtCQWhEYVFiaFRGdGpjakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBb0VlcEhNQzVYOWpCS2FHcGhjS2ppZGhpTitabno3djNTM2hjMzEvQXVuc0NJUURLcW9nSzJTWk9YWmN2dkhDQjZVUVNhQTBuTG40UlV3eTFndURpdmJaYndnPT0iLCJNSUlDSFRDQ0FjS2dBd0lCQWdJQ2RkVXdDZ1lJS29aSXpqMEVBd0l3ZXpFTE1Ba0dBMVVFQmhNQ1JsSXhFekFSQmdOVkJBb1RDa05sY25SRmRYSnZjR1V4RnpBVkJnTlZCQXNURGpBd01ESWdORE0wTWpBeU1UZ3dNU1F3SWdZRFZRUURFeHREWlhKMFJYVnliM0JsSUVWc2JHbHdkR2xqSUZKdmIzUWdRMEV4R0RBV0JnTlZCR0VURDA1VVVrWlNMVFF6TkRJd01qRTRNREFlRncweE9EQXhNakl5TXpBd01EQmFGdzB5T0RBeE1qSXlNekF3TURCYU1Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUejJqTmFLT0svTUtkVzJmbWUxdHE2R1JFdVB1dUtXOUhnV1lnTVJyanZaVVRPcUxBTkozTWQ1SHF2MUVOMXpNZDRsV3R5ZnpSbGE3cnY1QVJCb09vVG96WXdOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQkVHQTFVZERnUUtCQWhOblRXMGE0RTh1akFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTXJoYjhTbWZOTGVMTmdhQVZtUTZBT01pTE5MVkhYMGtGVU84MENuVDM4RUFpRUF6TkFndjRkSCtIRGhaU2daV0ppYVB1L25mWlRldUd5NE15ZFBNcTV1cnM0PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FJQUFBRDhHTzJqQUFBQ3FVbEVRVlJJeDJQOC8vOC9BeTBCRXdPTndhZ0ZwRmx3OGNLRmlySXlSM3Q3UzFPejBLRGdCZlBtLy96NWszaXp2bjM5bHArVGEydGx0V1RSSW9Ub2Z4aFl0WEtsbHBxNnNyd0NBaWtvUklWSHZIMzc5ajl4NE5TcFUwQXRRSTFXNWhad1FhZ1B6cDg3VjExWmlYQXZJeGo5WnpoNTRrUk5aUldSUHZqOTZ4Y0RPTTB6TVRLaUI5Rzh1WFAvL2ZzSE5GUkFTTEMrc1hIbTdObHVidTRRbTNidDNMbHU3VnBpTEdDRW1jdUlhY0daVTZmQjRjV1FYMUFRR3gvbjdPSXlhZW9VYlYwZGlJdmFtbHVlUFh0R1VTVC8rZzMySFNPRGhvWUdSSVNGaGFXcHBZV1ZsUlVvK09Iamg2YjZCb29zZ0h2cXo1OC9jRGw5ZmYzTTdDd0llOCtlM2F0WHJxUWdtZUlva0RLenMvWDE5RUd5L3hrNk96b2ZQM3BFV1ViRHNBWVlSQzN0YlJ3Y0hFRDJoL2Z2NjJwcUNSZU9qQ1RtWkUwdHJaeThYQWo3OEtGRHk1WXVKZDUwVkFzWWNlcEtUVTgzTmpXQnFPbnU3SHh3L3dFK08vN2pzZ0MzMTVtWm1SdWJtOW5aMllGcXZueiswbEJmaHpPZy9xTzdsUW0vQitFQW1Id0xpb29nQ280Y09yeGswV0lpUFVFZ2twRkJVbkt5bVprNWhOM1QxWFgzemgxaVlvS0pjRFRCQTRxRnVibXRsWXViQzhqKyt2VnJUVlUxcUhRaHpRZU1CSHlockt4Y1dGd01VWG42MUtuNWMrZFN2OEpKU0V5MHRyR0dzQ2YwOTkrNmRRc3V4Y0xDQ3JIN1A1SXJTWWdEZUtGUzM5VEV4OHNIWkgvLzlyMnVHaEZRTjY1ZmgyVlBOb3FxVENVbHBlS3lVbWd4ZlBwTVNXRVJNQU11WDdhc3Y3Y1hJcWlscllYd0ZyeGVnL3FPdUdaU2RFek0zdDE3RGgwNkNQVDBwazBiTjIzY0NJOUZZS1pKejhoRTk4SGZmMzhoRERZMmRpTDkwZEhkcGF1cml4YXdyQ3lzcmUzdHVucTZpTFRYME5BQVRvSXNUeDQvdG5kd2lJeU9BdFlFeEZqQXpjM3Q0K3NMSkw5OS9Rb3NFMFZGUmUzczdSdGJtb0dWRlVxY2pUWWRoNzhGQUloQkxsTmQ3anUxQUFBQUFFbEZUa1N1UW1DQyIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiMzc4OWRhOTFmOTQzNDZiYzk1YzM1MGVhMjAxMmYwM2EiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJmaXJtd2FyZVZlcnNpb24iOjJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDktMjEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA5LTIxIn0seyJhYWd1aWQiOiJmYTJiOTlkYy05ZTM5LTQyNTctOGY5Mi00YTMwZDIzYzQxMTgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImZhMmI5OWRjLTllMzktNDI1Ny04ZjkyLTRhMzBkMjNjNDExOCIsImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IFNlcmllcyB3aXRoIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjo1MDEwMCwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiZmEyYjk5ZGM5ZTM5NDI1NzhmOTI0YTMwZDIzYzQxMTgiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgU2VyaWVzIDUgd2l0aCBORkMiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE4MDkxODAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4xLjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMiJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDUtMTIifSx7ImFhZ3VpZCI6IjM0MWU0ZGE5LTNjMmUtODEwMy01YTlmLWFhZDg4NzEzNTIwMCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiMzQxZTRkYTktM2MyZS04MTAzLTVhOWYtYWFkODg3MTM1MjAwIiwiZGVzY3JpcHRpb24iOiJMZWRnZXIgTmFubyBTIEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MTA1MDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2azFfZWNkc2Ffc2hhMjU2X3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MywiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MywiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbImFueSIsImhhcmR3YXJlIl0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCZ1RDQ0FTY0NGQmxvMHM1UVlGZFhiZnVzUmRRZW9MWDZRZW5sTUFvR0NDcUdTTTQ5QkFNQ01FTXhDekFKQmdOVkJBWVRBa1pTTVE4d0RRWURWUVFLREFaTVpXUm5aWEl4SXpBaEJnTlZCQU1NR2t4bFpHZGxjaUJHU1VSUElFRjBkR1Z6ZEdGMGFXOXVJRU5CTUI0WERUSXpNREl5TXpFd016TXdPRm9YRFRNek1ESXlNREV3TXpNd09Gb3dRekVMTUFrR0ExVUVCaE1DUmxJeER6QU5CZ05WQkFvTUJreGxaR2RsY2pFak1DRUdBMVVFQXd3YVRHVmtaMlZ5SUVaSlJFOGdRWFIwWlhOMFlYUnBiMjRnUTBFd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUSzduWHlINHBnTjNUTXdDV1NvTURSZTRFVjhKbDNYenVoaWNaLzJndmgrenozV21XME9aL0VjUllFQThGMjZjZWV1TWNkMjFXUVJSS1dwaldEK0pXaU1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQ3djc0h1TDhaRkwzRk55VS9ET1FuM2JteDA4bG5uME81Umt0TGJPbm9QSFFJZ09FaTZJbUFaMTgxcThSSmlMMGhidzdacXV1bmlScTZmaldqR29CdTFNb289Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVNZQUFBRUFDQVlBQUFBZU1kdnhBQUFBQVhOU1IwSUFyczRjNlFBQUFJUmxXRWxtVFUwQUtnQUFBQWdBQlFFU0FBTUFBQUFCQUFFQUFBRWFBQVVBQUFBQkFBQUFTZ0ViQUFVQUFBQUJBQUFBVWdFb0FBTUFBQUFCQUFJQUFJZHBBQVFBQUFBQkFBQUFXZ0FBQUFBQUFBRXNBQUFBQVFBQUFTd0FBQUFCQUFPZ0FRQURBQUFBQVFBQkFBQ2dBZ0FFQUFBQUFRQUFBU2FnQXdBRUFBQUFBUUFBQVFBQUFBQUFlNlNDa3dBQUFBbHdTRmx6QUFBdUl3QUFMaU1CZUtVL2RnQUFBVmxwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJbGhOVUNCRGIzSmxJRFl1TUM0d0lqNEtJQ0FnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0S0lDQWdJQ0FnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJS0lDQWdJQ0FnSUNBZ0lDQWdlRzFzYm5NNmRHbG1aajBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5MGFXWm1MekV1TUM4aVBnb2dJQ0FnSUNBZ0lDQThkR2xtWmpwUGNtbGxiblJoZEdsdmJqNHhQQzkwYVdabU9rOXlhV1Z1ZEdGMGFXOXVQZ29nSUNBZ0lDQThMM0prWmpwRVpYTmpjbWx3ZEdsdmJqNEtJQ0FnUEM5eVpHWTZVa1JHUGdvOEwzZzZlRzF3YldWMFlUNEtHVjdoQndBQUQ2NUpSRUZVZUFIdDNMdU9KR2NWQi9CZDltSUhOaExpSWhPUU9FYUNDRGtpSUNORzRnMzhDandKQ1FsQ0JBU0lCTjZDaEFnSkpFUmlKQXZaQW95eGZGbnZoZS9zOUpGcWUzdG11azkvcDZkNjUxZlNOMVZkVmVkVXphOXEvbDI5OXN5ZE8zZnV2RC9Hc3pHZWJPYXhiS3pYNE5IbSt2eHF6R042Y0RIemRTRndmN1A4OHpHUGV6bk4zTmZydmEvajJqemRYSzlQdnpJV1RBUUlFRmlWZ0dCYTFlVndNZ1FJaElCZ2NoOFFJTEE2QWNHMHVrdmloQWdRRUV6dUFRSUVWaWNnbUZaM1Nad1FBUUtDeVQxQWdNRHFCQVRUNmk2SkV5SkFRREM1QndnUVdKMkFZRnJkSlhGQ0JBZ0lKdmNBQVFLckV4Qk1xN3NrVG9nQUFjSGtIcmd0QXZGTG9xWXpFUkJNWjNLaEZxZDVkN09jODhVbWk1Y0loQld2UzNEV3VEci9QTVF4NSthZDZCaTl3MnZUTytlSGQ3ZzlGV21VZjA3ajluem5OLytkSHZWR0VNWHg5NWkrUFVaY3ZIMmZvUEtDUi8xUHgvampHRytPRVgvVDZhZ1RHdldtcXdYQy90NFkveGtqcmwxNDUvVVlpNlloa0NadmplVnZqUEY0czI3TVRFMENjUS9HZzg3SFkzeC9qTitQRVZPczN6Y1RjdC9QWmp3eC9XVWMrTDA0QTlQSkJmSUg4T1FIWHZrQjh3Yi81empQR0tiVENqdzg5bkF6Z3VtTnpVbkV5Y1FUazZsZklBSXBubkJqbUhZTFJEakZKNEFZc1d6cUY0aS9wdnI1R0prSjVTUE9DS1lNbzVqbmN2bUVGQktZS0NDOEoyTHUwU28vc3NWSDU2T21mZjlONmFpREtDWkE0RllKWkVDVnYybkJWS1pUU0lCQWw0Qmc2cExWbHdDQnNvQmdLdE1wSkVDZ1MwQXdkY25xUzRCQVdVQXdsZWtVRWlEUUpTQ1l1bVQxSlVDZ0xDQ1l5blFLQ1JEb0VoQk1YYkw2RWlCUUZoQk1aVHFGQkFoMENRaW1MbGw5Q1JBb0N3aW1NcDFDQWdTNkJBUlRsNnkrQkFpVUJRUlRtVTRoQVFKZEFvS3BTMVpmQWdUS0FvS3BUS2VRQUlFdUFjSFVKYXN2QVFKbEFjRlVwbE5JZ0VDWGdHRHFrdFdYQUlHeWdHQXEweWtrUUtCTFFEQjF5ZXBMZ0VCWlFEQ1Y2UlFTSU5BbElKaTZaUFVsUUtBc0lKaktkQW9KRU9nU0VFeGRzdm9TSUZBV0VFeGxPb1VFQ0hRSkNLWXVXWDBKRUNnTENLWXluVUlDQkxvRUJGT1hyTDRFQ0pRRkJGT1pUaUVCQWwwQ2dxbExWbDhDQk1vQ2dxbE1wNUFBZ1M0QndkUWxxeThCQW1VQndWU21VMGlBUUplQVlPcVMxWmNBZ2JLQVlDclRLU1JBb0V0QU1IWEo2a3VBUUZsQU1KWHBGQklnMENVZ21McGs5U1ZBb0N3Z21NcDBDZ2tRNkJJUVRGMnkraElnVUJZUVRHVTZoUVFJZEFrSXBpNVpmUWtRS0FzSXBqS2RRZ0lFdWdRRVU1ZXN2Z1FJbEFVRVU1bE9JUUVDWFFLQ3FVdFdYd0lFeWdLQ3FVeW5rQUNCTGdIQjFDV3JMd0VDWlFIQlZLWlRTSUJBbDhEOTBmakxUZk5IWTM1dmpHZWIxM2QzTEMvWHhXNFBGL3ZFYTlQcEJPSmFQQmdqcjljaFI4N3JtTmYra0ZyN0VyaE9JTzdKdkxmeS9zeDdMbXFYeTh2WHNlL3pUSW92MzR3dFkzcjlZbmJ3MS9qaE1KMVdJQzlzdkptWUNLeEZJTzdMbUNKWGpzbUZyMGFEWDQ4UjRSUTMrYjRmN1RJRjQrQWZqQkZUcnJ0NDVXdVhRSWJTdDhZQmZqekc0OFdCY2x1c3lwdGtlVjF5ZTF6My80N3hoekdlam1FaU1FTWc3NlYvajJhLzNUU00reS92eGV1T0VmdEdCbjF4M1k3N2J0LzN3UHYyczkvbEF2RnhPNllmalJFWHNqbytITFh4VVR3bTErL0N3ZGZqQmFiY1MvSE9HUWwxVExOSXlmamhNSjFXSUorVTRyTjhYTDk5cjJGY3IzalMvV2dNMTIwZ21LWUs1RDJWYjZDVjVzOGltUElkdDlJZ2F2SkVxdlhxamhPSUcyRGZVRnJ1dCsvSDl1UE9UdlZ0RmNpUGRhWHZQNE9wVkt4b1ZRTEwwTG5xeEhLL25GKzFyMjBFcWdKSFBiQjQxNnl5cXlOQW9FMUFNTFhSYWt5QVFGVkFNRlhsMUJFZzBDWWdtTnBvTlNaQW9Db2dtS3B5NmdnUWFCTVFURzIwR2hNZ1VCVVFURlU1ZFFRSXRBa0lwalphalFrUXFBb0lwcXFjT2dJRTJnUUVVeHV0eGdRSVZBVUVVMVZPSFFFQ2JRS0NxWTFXWXdJRXFnS0NxU3FuamdDQk5nSEIxRWFyTVFFQ1ZRSEJWSlZUUjRCQW00QmdhcVBWbUFDQnFvQmdxc3FwSTBDZ1RVQXd0ZEZxVElCQVZVQXdWZVhVRVNEUUppQ1kybWcxSmtDZ0tpQ1lxbkxxQ0JCb0V4Qk1iYlFhRXlCUUZSQk1WVGwxQkFpMENRaW1ObHFOQ1JDb0NnaW1xcHc2QWdUYUJBUlRHNjNHQkFoVUJRUlRWVTRkQVFKdEFvS3BqVlpqQWdTcUFvS3BLcWVPQUlFMkFjSFVScXN4QVFKVkFjRlVsVk5IZ0VDYmdHQnFvOVdZQUlHcWdHQ3F5cWtqUUtCTlFEQzEwV3BNZ0VCVlFEQlY1ZFFSSU5BbUlKamFhRFVtUUtBcUlKaXFjdW9JRUdnVEVFeHR0Qm9USUZBVkVFeFZPWFVFQ0xRSkNLWTJXbzBKRUtnS0NLYXFuRG9DQk5vRUJGTWJyY1lFQ0ZRRkJGTlZUaDBCQW0wQ2dxbU5WbU1DQktvQ2dxa3FwNDRBZ1RZQndkUkdxekVCQWxVQndWU1ZVMGVBUUp1QVlHcWoxWmdBZ2FxQVlLcktxU05Bb0UxQU1MWFJha3lBUUZWQU1GWGwxQkVnMENZZ21OcG9OU1pBb0NvZ21LcHk2Z2dRYUJNUVRHMjBHaE1nVUJVUVRGVTVkUVFJdEFrSXBqWmFqUWtRcUFvSXBxcWNPZ0lFMmdRRVV4dXR4Z1FJVkFVRVUxVk9IUUVDYlFLQ3FZMVdZd0lFcWdLQ3FTcW5qZ0NCTmdIQjFFYXJNUUVDVlFIQlZKVlRSNEJBbTRCZ2FxUFZtQUNCcW9CZ3FzcXBJMENnVFVBd3RkRnFUSUJBVlVBd1ZlWFVFU0RRSmlDWTJtZzFKa0NnS2lDWXFuTHFDQkJvRXhCTWJiUWFFeUJRRlJCTVZUbDFCQWkwQ1FpbU5scU5DUkNvQ2dpbXFwdzZBZ1RhQkFSVEc2M0dCQWhVQlFSVFZVNGRBUUp0QW9LcGpWWmpBZ1NxQW9LcEtxZU9BSUUyQWNIVVJxc3hBUUpWQWNGVWxWTkhnRUNiZ0dCcW85V1lBSUdxZ0dDcXlxa2pRS0JOUURDMTBXcE1nRUJWUURCVjVkUVJJTkFtSUpqYWFEVW1RS0FxSUppcWN1b0lFR2dURUV4dHRCb1RJRkFWRUV4Vk9YVUVDTFFKQ0tZMldvMEpFS2dLQ0thcW5Eb0NCTm9FN3JkMTF2Z2NCT0w2UHhuajNoalB6dUdFRHp6SHAyUC9HS1l6RXhCTVozYkJKcHh1QmxBRTBtZWJmcS95RCsvZDhUM205enlCVDR0VENBaW1VeWl2NnhqeGd4clRtMlA4Wkl3dng0aVA5Sy9TRDI5OEw2K044YWN4L2o2R2NCb0lKZ0tkQXZHeEs2WWZqaEUvZ1BIa0UwODhzYnp2T0hUL2ZmdXViYitmRFpPWUhsek1mRDBYQVU5TTUzS2w1cDVuUGpWbFFPWHJDSmFZZHIyT2Jjc25qMXpPZlo4WDd2aXk3Sms5Y3JmY0ZxK1hmWEsvM0w3Y2xyVTVYKzZUeTQvSHhuaGkraUozTWo4dkFjRjBYdGRyOXRuR0QvenloMzY1SE1kYXZzN2xuRzl2ajllN3BxdjJYMjViMXViNm5DKzNiUzh2OThubC9LL04rWHE3eHV1VkN3aW1sVitnNXRON1ZYOXdYOVh2cS9sMldFLzdmR2RaenhrNUV3TEhDZVRIdWVPNnFMNVJBY0Ywby93TzNpRGdhYWtCOWRRdEJkT3B4UjJ2VzhBVFU3ZndDZm9McGhNZ084UkpCVHd4blpTNzUyQ0NxY2RWVndJRWpoQVFURWZnS1YybGdJOXlxN3dzaDUyVVlEck15OTdyRi9CUmJ2M1g2Tm96alArUDZkZ0w2UjNxV3ViV0hmaS95QnNlVEY0MHVZbFhSK1dLSjZhYnVHUTl4OHdmeHB6blVTNzdRZDNlTC9lUCtYTGJjam0zNWJyTDV0a3J0eC82ZWxrWHk4dlgyU3ZueSsyNVg4NXpIL016RTRnbkpoZnh6QzdhNW5UemwzbHpudC9GOWp2Vjl1dkw5c3YxTVYvV0xKY3YyNWI3NUR4N1ZWOHY2NWJMMlhjNVgyN1A1WWViSGZ6eTdsTHF0TXRINVVwY3lOK044ZFlZajhhSUo2aERHa2F3dlR2R1h6ZTE4VXVocGw2QnVHWnhqYjQyeGcvR2lMOHVFRlArVUY2OHV0MWY0ejZNWCtMOTh4anZqWkZtWTlIVUtCQnZrbkUvdmozR0x6ZkhPU1JQWXQvbzhYblVmanhHcktpT2Q2TEptTGJmdVMvVyt0b2hJSVQyVjJXMXY5V3hlK1lUNnZkR28ycWVQSytMSjU2UHhvZy9HcFpQVEdQeDJpbUtZNG9UaVQ4eFlUcXRRUGpIRDV3M2c2dmQ0OG5KVS96VlJqTzNaaTdFVTFNK3llZTZmWTRUKzBZbWZSSmZZc1FVODMzL01YeDVNTzlJei9sTy9pV3VnVGVGazdNNzRCNEN5emZOdUUvM3pZamM5LzYrUWJUSHVkaUZBQUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNod2YwS3ZETGQ3RTNwcHNiL0FzN0hyMC8xM3Y1Vjd4cjE1OTFaKzV6ZnpUVWVlUEI3ajZDeVlFVXlmYkF3ZTNZekZyVDVxL05CRlFKbGVGZ2did2YyeVMrZWFKNXZtSHg5N2tCbkI5TTQ0aVlkanZERkduSmgzcUlIUU9FVVFQUmpqL1RIK05vWndHZ2hiVTVxOFBkWi9aNHd2eDNCZmJpRk5maG4zWmVUSi84YjQ3b3plY1lOSDB3aVZtQnZuWWZDYmNhMWlpcEF5dlNpUWI3aS9HS3ZkeitkakVFKzRjYjArelF2NDRtVTk3RlZlK01PcTdGMFJpSGY5ZVBlUEo5UXZLZzF1V1UzKzgwTE1aOXpydDR5di9PM0dmWHJVRStxTWk1VW5rUFB0N3lhQ0s3Zmxjc3hqaXZXNTd2bUtIVjkyYmM5MXl6N0wwdHdlNjViTCtYcTVieXh2bjkvMjluaWR4NHJsN2ZOZUhpT1h0K2ZiUGVKMVRNdGpYNnpadlM3M3pmMXpualhtTHd1a1VjeVh5M2x0b2lLV1k4cnR5MjBYVzE3OHV0dy85ODM1Y3MvdGRmazY1MWZ0bTl0aTM1emkvUEwxdnVlYXRZY2NNMnR5bnJVNXovVXgzN1Z1dWIyOFBDT1k0dUFKdGV0RWx0dHlPZWZYMVY2MlBldHp2bjNjNWZybDhtWDlzbjU3MzF5L3EyNjU3NjdsWEpmelhUMnU2bi9kL3N0YXk5Y0xYSFlkbHV2M01WL3VuOHM1WDU3RjlycDhuZk9yOXMxdDIvdGU5enJydHVmYmRiRjkxN3J0dXVWK3UvYmZ0VzVYajRQWDVYL3FQN2hRQVFFQ0JMb0VCRk9Yckw0RUNKUUZCRk9aVGlFQkFsMENncWxMVmw4Q0JNb0NncWxNcDVBQWdTNEJ3ZFFscXk4QkFtVUJ3VlNtVTBpQVFKZUFZT3FTMVpjQWdiS0FZQ3JUM1ZoaDIvL1VkbVBma1FNVDJCS0kvL003L3pSRXpyZDI4WEpsQXZITDFuSGQ0dGNCVEZjTHBGSGMyKzd2cTYzV3NEV3VWL3d0cDZkeGc3KytPYU5adjU2eWFXZldKUERhcG0vOElxL3Bhb0g4eXd0cGR2WGV0cTVGNFBVSW8zOXN6dWJ6TWZmUmJpMlg1dkx6aUw4UStQVXhQdHpza2s4RmwxZmN2aTFwOHEveHJjZDkvY0VZY2EvN0dEd1FWanpsRTlPbi93ZWJhMFY1VTZXSnFnQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIzNDFlNGRhOTNjMmU4MTAzNWE5ZmFhZDg4NzEzNTIwMCIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDEtMDQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTAxLTA0In0seyJhYWd1aWQiOiI2OTcwMGY3OS1kMWZiLTQ3MmUtYmQ5Yi1hM2EzYjlhOWVkYTAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjY5NzAwZjc5LWQxZmItNDcyZS1iZDliLWEzYTNiOWE5ZWRhMCIsImRlc2NyaXB0aW9uIjoiUG9uZSBCaW9tZXRyaWNzIE9GRlBBRCBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsicnNhc3NhX3BrY3N2MTVfc2hhMjU2X3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciLCJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQndEQ0NBV2VnQXdJQkFnSVVJRjJBaXd1aFFPVHVieFZ5ZzNYMTM0aVduUW93Q2dZSUtvWkl6ajBFQXdJd05qRVlNQllHQTFVRUF3d1BVRzl1WlNCQ2FXOXRaWFJ5YVdOek1Rc3dDUVlEVlFRR0V3Sk9UekVOTUFzR0ExVUVCd3dFVDNOc2J6QWVGdzB5TXpBek1qVXhOakU0TVRWYUZ3MHpNekF6TWpJeE5qRTRNVFZhTURZeEdEQVdCZ05WQkFNTUQxQnZibVVnUW1sdmJXVjBjbWxqY3pFTE1Ba0dBMVVFQmhNQ1RrOHhEVEFMQmdOVkJBY01CRTl6Ykc4d1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRU0ttT1QzOU82eEFIbkZYeFVYRm90d3VyaG9aQXF5MThXcTdRSjJGRVVoK3lZY3huWk1xNDJMRlhtZFVIMkJQb2s3eFpJRFRxVXlqWndQTEY4OFN3Rm8xTXdVVEFkQmdOVkhRNEVGZ1FVVm5kTG9zalIrcHdLc2QxcmNBWjk0MUpyV04wd0h3WURWUjBqQkJnd0ZvQVVWbmRMb3NqUitwd0tzZDFyY0FaOTQxSnJXTjB3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUJFWVlnNU5uU0I0QXdzMUV5ZWxrbVFqejZOZEY1WlJ4aEFNVnBvb2FydCt3SWdXVjVVZXlOM1hrak51NzlMZCt0MEwyejl4TVhKdDdOUlloRVBtTGdrZnd3PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFhTUFBQUdqQ0FZQUFBQ0JsWHIwQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUhUbWxVV0hSWVRVdzZZMjl0TG1Ga2IySmxMbmh0Y0FBQUFBQUFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NGdQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlRV1J2WW1VZ1dFMVFJRU52Y21VZ09TNHdMV013TURBZ056a3VNVGN4WXpJM1ptRmlMQ0F5TURJeUx6QTRMekUyTFRJeU9qTTFPalF4SUNBZ0lDQWdJQ0FpUGlBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBpQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JTWldZOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlZKbFppTWlJSGh0Ykc1ek9uTjBSWFowUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZGZG1WdWRDTWlJSGh0Ykc1ek9uaHRjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3THlJZ2VHMXNibk02WkdNOUltaDBkSEE2THk5d2RYSnNMbTl5Wnk5a1l5OWxiR1Z0Wlc1MGN5OHhMakV2SWlCNGJXeHVjenB3YUc5MGIzTm9iM0E5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmNHaHZkRzl6YUc5d0x6RXVNQzhpSUhodGNFMU5Pazl5YVdkcGJtRnNSRzlqZFcxbGJuUkpSRDBpZUcxd0xtUnBaRG8zWVdZM01qQXlOUzB5WkRKaExUWmpOR0V0T1dZeVpDMHhNakZpTWpGak9EVXdPRGNpSUhodGNFMU5Pa1J2WTNWdFpXNTBTVVE5SW1Ga2IySmxPbVJ2WTJsa09uQm9iM1J2YzJodmNEbzJNalpoTkRBMVpTMWlZVGxrTFRnMU5EQXRZVGN4WWkxa05HVmpPV00zTVRVeE5ESWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZaakkwTkRJNU1EY3RaRFZpWlMwME1XVmtMV0kxWW1FdFpqbGxPV00zWXpreVlqVXpJaUI0YlhBNlEzSmxZWFJ2Y2xSdmIydzlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFMElDaFhhVzVrYjNkektTSWdlRzF3T2tOeVpXRjBaVVJoZEdVOUlqSXdNakl0TVRBdE1EWlVNVE02TVRnNk5UZ3JNREk2TURBaUlIaHRjRHBOYjJScFpubEVZWFJsUFNJeU1ESXlMVEV5TFRFMFZERXhPak14T2pJeEt6QXhPakF3SWlCNGJYQTZUV1YwWVdSaGRHRkVZWFJsUFNJeU1ESXlMVEV5TFRFMFZERXhPak14T2pJeEt6QXhPakF3SWlCa1l6cG1iM0p0WVhROUltbHRZV2RsTDNCdVp5SWdjR2h2ZEc5emFHOXdPa052Ykc5eVRXOWtaVDBpTXlJK0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnpkRkpsWmpwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qWTJaRGhsWm1OaExUTXpOekl0TmpZME15MWlNamhoTFRVM1kyUXpPR0prTnpCaE1pSWdjM1JTWldZNlpHOWpkVzFsYm5SSlJEMGlZV1J2WW1VNlpHOWphV1E2Y0dodmRHOXphRzl3T2prek1tWmpObUU0TFdZd01qY3RNVEZsTkMxaU9UYzBMV1E1TW1OaVpHVTVabU5sTmlJdlBpQThlRzF3VFUwNlNHbHpkRzl5ZVQ0Z1BISmtaanBUWlhFK0lEeHlaR1k2YkdrZ2MzUkZkblE2WVdOMGFXOXVQU0p6WVhabFpDSWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3lZbVl3TnpZek5DMDFNVGszTFRSbFlqWXRZbVkzWXkxbU9HWm1PVFprWVdKa01tUWlJSE4wUlhaME9uZG9aVzQ5SWpJd01qSXRNVEV0TUROVU1URTZOVGM2TXpNck1ERTZNREFpSUhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5ROUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NBeU5DNHdJQ2hOWVdOcGJuUnZjMmdwSWlCemRFVjJkRHBqYUdGdVoyVmtQU0l2SWk4K0lEeHlaR1k2YkdrZ2MzUkZkblE2WVdOMGFXOXVQU0p6WVhabFpDSWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEcG1NalEwTWprd055MWtOV0psTFRReFpXUXRZalZpWVMxbU9XVTVZemRqT1RKaU5UTWlJSE4wUlhaME9uZG9aVzQ5SWpJd01qSXRNVEl0TVRSVU1URTZNekU2TWpFck1ERTZNREFpSUhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5ROUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NBeU5DNHdJQ2hOWVdOcGJuUnZjMmdwSWlCemRFVjJkRHBqYUdGdVoyVmtQU0l2SWk4K0lEd3ZjbVJtT2xObGNUNGdQQzk0YlhCTlRUcElhWE4wYjNKNVBpQThjR2h2ZEc5emFHOXdPa1J2WTNWdFpXNTBRVzVqWlhOMGIzSnpQaUE4Y21SbU9rSmhaejRnUEhKa1pqcHNhVDU0YlhBdVpHbGtPamM1TURZNE16QTBOek5DT0RFeFJVUkNSVE0xT0VNeU5FTkVSRGt5UXpFMVBDOXlaR1k2YkdrK0lEd3ZjbVJtT2tKaFp6NGdQQzl3YUc5MGIzTm9iM0E2Ukc5amRXMWxiblJCYm1ObGMzUnZjbk0rSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrOGJzRTJnQUFKYzlKUkVGVWVKenQzWG1ZWkdWaDcvRnZkZmZzS3pQRElEc0lTaElVOTJnQVJWRkFweFJjNG5LcG1FMU5ZdFRFdUdhOVJuTzlpVXRRRTYvR05ScFRlTjBpTGpXaUlKcGczQUlvSU9pTmpDeUR3ellETXoxN0wxWDNqN2RMaXBvNnA2dXE2OVJicCtyN2VaNStlcWI3TEcvTmRKOWZ2WHVoVnFzaGFmZ1ZMdDVjcVA5eDduTU5vSGJocGxvYnh4WHF4emRmTnVXV2pjZVBOZjM5RjMrdTMzL3V2cis0VDNPNU5Od0tocEdVallhSE90RDJRei9wdU1acjFUb01rTFRBYUR5bjhmaFduK0grVUtrMW5WZE5PSzVWV1dvTjU3VU1xS2J2SFJKYzlkZHNZQTBQdzBqcWtlYndhWFZJMDJkby9RQnVESitrQjNyek5SdVBhVDYzSGhhTkFUSFdjSHkxNGJ6YTNQZXFIQnBpamZjZUEyWWJ6bXUrWjNYdTgzalR0ZXIzcURZYzMxeHJxcXVmVjIzeHZWOEV0NkUwSEF3anFRdnpCRTl6NkxRS2g4YUg4RGozMXphYWowdTZUbk9BMUIvNmpUV1h4dUNCQndaUTQvZWJYMHR6Y05UUHFWK251VmFVZEozbW9KMXB1RWE5N05XNWo4WmdiQzVML1d1ekpMTnBMK2NNSTZsTmJkUjhHaCswOWMvTkQrVDZjV245TWZVSGYvTXZaM01mVE9NMW04T3BWUzBzN1h2MTBCbm5nV1dxbDZYYTlQZm1RQzF3ZjAycE1aeG1nUWtlR0RiTnRhZDZMYXNlc3ZXL042dVhjYmJoN3kzVkx0elVxamFsQVdZWVNXMW9DcUpXb2RUOGpyL3hhNDNuRkZyOHVUR1lhaTNPcS9MQWtLRGgrRlo5T1BWNzF3T3E4WHF6UERBTW04dlRxc1pVdjhjRUQydzZhMVd1Y1ZxSFVxc2FUejJBR3NPcHNmbXVYbDZhdmw1dGNWNHJoL1N0YVhBWlJsS0tGcldoNXIrUEpYeHVmdGpYdjk3NDhHNE9nZVp6VzlVNjZzYm5QamRlcTlVQWdjYVFxRFo4Ymp4MnZPR2M4YWI3TklaWDQwZGpEYWE1djRtbWV6WFhtdXJuMTJ0Tk0zUG5URFc4cHViQW1XbjZldVAzbTVzM0gvRFpRTXFIaWRnRmtBWlZRbTJvK1d1TnRZd3hEbjF3US9nOWEveGE0ME82TWFpYSsyV2FtOHpxNmcvNnhudlV2MTZ2RVUxd2FDQTAxNkthKzRBYUE0Nkc0OGNhcmxXL3owVERzZlY3TllkUi9UVTExbHdhYXovMW10SDQzSGtUYzM4KzJQRDk1dXMwaGxPMTZXdU54eDR5RWsrRHpacVIxQ1NoYjZoVjgxdFNFTlUvai9QQTBLaC9OTDRKbkdpNlZxdGFUV01ZMUlPbDNoeldxdittc1ZtdThjOXcvOE8vVmNBdGJycC8vZGo2ZGFibmptbDg2RGNIMUN5d2FPNXIwdzNIdFdwbXE5ZDI2bCtyLzMxNjdweURUY2ZYajBrNnJ6R1VtbXRIOWlFTnVMYkRxRkNZcis5MkJKUXJLNEhEZ1EzQWVtQVpzR2J1dXl1eHBqa3Nrc0tvK1hPcmdCcm4wSUNxZjczNXZGWWZOUTY5Wm5QZlRLc211Y2JSZEkxbGJqWHlyYm01cjNtT1VOSzk2dGRvckptMStsNDlGQnRyYW8yRElCcURvc29EYXpqMUFRcjF6NjIrM3VxY3h0Q2k0ZnBwZzBCNlpSYllQZmZuU1dBL3NHUHU0MjVLeGQxSko0NktkbkxHTUdwV3Jpd0NmZ1U0RFhnNGNESndBdkJnN2c4ZVNXclhidUJud0MzQUZ1QjY0RnJnUmtyRmd5bm5EUTNEcUIzbHloSEFtWE1mWndDUHdocU9wT3pOQXRjQi93bDhDN2lTVW5GYjNDSmx3ekJxcFZ3WkEzNE5lQWF3aVJBK2tqUUlyZ2UrTXZkeEphVmkya1RmM0RDTTZzcVZBbkE2OENMZ2VjQ1JjUXNrU2ZPNkIvZzM0RlBBdjFNcTVuWVFobUZVcmp3SStGM2dwY0NKa1VzalNkMjZIZmdJOEJGS3hhMnhDOU9wMFEyamN1VU00RFhBQmR3L2lrbVM4cTRHYkFZdW9sUzhJblpoMmpWYVlSU2E0aTRBM2tEb0U1S2tZWFlOOEE3ZzA0UGVoRGM2WVZTdVBCdDRFL0RJdUFXUnBMNzdNZkFXNEZPVWlnTzVpc0h3aDFHNWNqcHdFZkQ0MkVXUjV0RThHVFBwYytOazAxWkxFTkhpYXdQNHk2a0lmZ2k4amxMeDY3RUwwbXg0dzZoY09RNTRHMkYwbkNUcGZsOGdoTkpOc1F0U04zeGhWSzZNQTY4Ry9vYXdGSThrNlZCVHdGdUJ2NlZVbko3djRLd05WeGlWSzQ4Z0RHMThUTnlDU0ZKdTNBQzhoRkx4ZXpFTE1SeGhGRlpNZUFPaE51UXlQWkxVbVNyd3Q4QmZVeXJPekhkd0Z2SWZSdVhLTWNBbmdDZjMvK2FTTkZTK0I1UW9GYmYwKzhidDVFenpYaWVEbzF4NUdtRjB5SlBqRmtTU2hzTGpnV3NvVnk2SVhaQldCcTltRkNhdnZwSFErVGE0WVNsSitmVlc0RTM5V29nMWY4MTA1Y29TNE9QQUM3Ty9tU1NOdEFyd1FrckZ2Vm5mS0Y5aFZLNnNKNHlQUHlQYkcwbVM1dndBS0ZJcTNwSGxUZklUUm1HZ3doWEFRN0s3aVNTcGhhM0EyVmxPa3MzSEFJWnk1V1RndXhoRWtoVERzY0IzS0ZjZUhyTVFjY01vdlBncmdhT2psa09TUnRzRzRKdVVLOUhXK1l6WFRCZHFSTjhDanVqdGhTVkpYZG9KUElsUzhmcGVYblJ3bStuS2xXT0JiMklRU2RJZ1dRdGNRYm55MEg3ZnVQOWhWSzVzSUF4V3NHbE9rZ1pQZUVhWEszMTlSdmMzak1xVnBZVGgyeWYzOWI2U3BFNGNEVlFvVjFiMTY0YjlDNk93c3NLL0FLZjM3WjZTcEc0OUF2ak0zTlk5bWV0bnplZ3ZnT2YzOFg2U3BJVTVqN0NSYWViNk01cXVYRGtQMkV6c29lU1NwRzY4Z0ZMeE05MmVQQmdyTUlRdHduOElITmJkQlNSSmtlMEZIa3VwK0pOdVRvNC90RHUwTlpZeGlDUXB6MVlBbjV4YnpEb1RXVGViL1Jsd1pzYjNrQ1JsNzVHRXJTY3lrVjB6WGJueVdNS2FjMzBaaVNGSjZvdXpLUlcvMGNrSjhmcU15cFVKNENyQzBFQkowdkM0Q1RpTlVuRi91eWZFN0RONlBRYVJKQTJqazRHLzd2VkZlMTh6S2xjZUROd0laTmJSSlVtS2FoWjROS1hpZGUwY0hLdG05RTRNSWtrYVp1UEF1M3Q1d2Q2R1VibnlGT0E1UGIybUpHa1FQWVZ5cFdmUCs5NDEwNFcxNTY0aERQK1RKQTIvTGNBdlVTck9wQjNVNzJhNkYySVFTZElvT1FsNGFTOHUxSnVhVWJreUJ2d0krT1ZlRkVxU2xCdGJnWk1wRmFlU0R1aG56ZWdGR0VTU05JcU9CWDUzb1JmcFZSaTlzVWZYa1NUbHordm5Xc2k2dHZBd0tsZWVobjFGa2pUS0hndzhkeUVYNkVYTjZMVTl1SVlrS2Q4V2xBVUxHOEJRcnB4SUdOcTNnSjMzSkVsRDRwR1VpdGMyZjdFZkF4aCtGNE5Ja2hSMFBjeTcrNXBSMkRodkszQmt0emVYSkEyVlhjQ1J6U3Q2WjEwek9nZURTSkowdnpYQUJkMmN1SkF3ZXY0Q3pwVWtEYWV1c3FHN1pycHlaUkZ3RjNCWU56ZVZKQTJ0QThEaGxJcDc2bC9Jc3BudUtSaEVrcVJETFFVMmRYcFN0MkhVOFkwa1NTT2piMkgwakM3UGt5UU52NmZQYlN2VXRzN0RLR3dyL3RDT3o1TWtqWW9qZ0VkMWNrSTNOYU96dWpoSGtqUmFPc3FLYnNMbzlDN09rU1NObG82eW9wc3dPck9MY3lSSm82V2pyT2hzbmxHNXNnYlkyVVdoSkVtajUzaEt4ZHV5bUdmMDhPN0tJMGthUWFlMWUyQ25ZZFQyaFNWSkk4OHdraVJGbDFrWW5kemg4WktrMGRWMlpuUWFSaWQyZUx3a2FYUzFuUm50ajZhN2VQTTRZVFhXaVM0TEpVa2FQV3RxRjI2YW5PK2dUbXBHRDhJZ2tpUjE1dGgyRHVva2pEWjJXUkJKMHVocUt6czZDYU1OWFJaRWtqUzYyc3FPVHNKb2ZaY0ZrU1NOcnJheW81TXdXdDVsUVNSSm82dXQ3T2drakZaM1dSQkowdWhxS3p1NjNlbFZrcVNlNlNTTVZtWldDa25Tc0dvck96b0pJK2NZU1pJNjFWWjIyRXduU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS3kxRmJPR0VhU3BDd1Yyam5JTUpJa1pjbWFrU1FwSHd3alNWSjBocEVrS1V1MWRnNHlqQ1JKMFJsR2txUXNPWUJCa2hUZGVEc0hHVWFTcEN4TkZDN2VQTzljSThOSWtwUWxhMGFTcEh3d2pDUkpXYXEyYzVCaEpFbkswbXp0d2szenpqVXlqQ1JKV1pwcDV5RERTSktVSlp2cEpFbjVZQmhKa3JMa2ZrYVNwT2dNSTBsU1BoaEdrcVFzT1lCQmtoU2RZU1JKaXM3TjlTUkowVmt6a2lUbGcyRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0ticUoyQVVZQkt2RzRYSEw0S1FsY1B4aU9HSVJMQzdBc2tMNC9tUVZwbXV3ZFFwdW1ZSWZIWUFiRHNCc1cvc1hTc3E3VmVOdytuTFlYUTNibGg2b3dsUU5abXF3ZDI3cnVQcjM5czg5TDlTWmtRMmpCeTJDNTZ5Qlo2NkdVNWQxWGtYY1U0WHY3SVhQNzRMTEp1SGdBUDd3ZmZ4NGVPaVNPUGZlUFF2bmJ1bnROZi91S0RoclpXK3YyWW5uM2d4M1RQZnVlaTlaRHk5ZDM3dnJRWGdJM2pNRC8zMFFydGtIVit5QkhUTzl2VWN2dk9WSU9HZFY4dmYzVk9FWlc4TERmaEFjdHdnK2RGeG41OHpVUWpCQmVFTUxzSG9zQk5hT1diaDNCbTZkZ21zUHdBLzJ3WFg3Mjl3U2RVaU5YQmlkdWhSZXZSSE9YUVdGQlZ4bjVWajRaVHBuVmZqRitjUzk4SUh0Y085c3o0cTZZRWRNd05HTDR0eDdkd1lOd0JzaXZoNkE4UjVmYi9WNE5xL25oTVh3dU9WUU9pdzgzTDZ4R3o2NEk3eDVHZ1JMeCtBRmEySDVQRDhqWjY2QWIrN3BTNUV5TVZFSU5TcTQvM1BkNm5FNGNURThaams4ZCs1cmQ4L0ExeWFoZkY5b2VSazFJOU5uZFBRaStPQ3g4SldUNEx3RkJsR3psV1B3OGczdzdZZkNxdzRQUDRUU0lCZ0Rucm9LUG5VQ2ZPeTR1R0ZlZC9iSytZTUk0Tmxyc2kvTElOazRBYit4TGp5ai91OEo4R3NyWXBlb3YwWWlqSDVySFZ4K01qeDlkYmIzV1Q0R3I5OFlmcGdldml6YmUwbWRPbnNWZkczdXpWaE1GN1FaTXVldURuMjNvK2owRmVFTnhQdVBoYU1HNEExRVB3eDFHQzBiZzM4OEJ2N21TRmpSeDFkNnloTDQvSW53L0xYOXU2ZlVqbFhqOElIajRNWHI0dHgvNVZnSXhYYVBmVnJrNEl5dHVCcStlbEwyYjZRSHdkQ0cwZm9KK0xjVDIzOFgxbWltRnRwdmI1NEtJK2p1bk82OFkzRnhBZjcrYVBpekkzcmJKQ2d0MUJqaERkcW1DQSs0YzFmRGtnNStJWjQ1QWcvaCthd1pEMTBNdy80c0djb0JET3NuUXB2cktXMk9KTnRmaGN0MnczL3NnYXYzaHhFdXphTjRGaFhDME85ZlhRNVBYaGsrMnVrYmV2bUcwR0g3cGpzNmZobVp1ZkVBdlBuT2JPL1J6MUZRMjJmZ0ZiZG5mNTk3K2pncTdiTTc0VE03T3p0bldRR09Xd3lQWFI1cUh5dFQzbXFPRWQ0czNYQWcvTHozUzZkdkRzOVpIVm8xOWc3NE1MT3I5clUzZUdsZk5ieWVkZU53OHBJUU5PMTYrWVl3S09tMTI0WnpXc25RaGRIU01mam9jZTBGMGJacGVOOTIrTGVkWVVSY211a2EvT1JBK1BpWGU4UElyaGV2ZzVldU8zU2tUTFBmV1JjZW1QOTRUOXN2STFPVHM0TXpzcW9YRHRhRzYvVUFiSjN1L2pWOTdON3d3SHZ4T3Zpanc1TkRhY1VZdlBWSStJMWJ1eTluSjlhT3d4TTc3SlJmVWdoTmRWL1lsVTJaZXVVZGQzZjMvM1hDWW5qS1N0aTBCaDYvZlA3am43c1c3cHFCdjcycjgzc051cUZxcGlzQTd6d0tIalhQNElHcFd2alBmT0pQUTdETUYwU3RiSitCZDkwTlovNDB2SXVkeitzM3d2a2pOanBJOGV5dHdqOXRoM051U2g4bS9LU1ZjRWFmUm0xdFd0MjZOZUcycWZTV2cyRWVWWGZMRlB6enZmRDhtK0hwVzJEejVQem52SHhEQ0xCaE0xUmg5SkwxOHovd3R4d00vK252Mzk2YldkTDN6Y0pyZmc2L3R6VlV3ZE5jZERROEpOSWtWSTJtbjAvRGhiZWtUOWJ0OWNUYkpFbS9tNVZKK1BKa2NyL3NrMVoyMXB5VlZ6Y2VnRC9ZQ2krNkJXNmZaM0wxUlVlSG11WXdHWm93ZXNnUytOTWowby81OWw2NDRHYTQ2V0R2NzMvcEpEenY1dlIyNDhVRitJZGpRditUMUMvM3pjS2ZwOVE4emxxWi9ZUHRpQWw0UWtJTjdLdVRvVC91dXduTlhJc0s4SXdSR3NqdzdiMWg5WW5MZHljZnMzNEMvbnllNTEzZURFVVlGWUIzSHAwK0orRTdlK0YzYmd2OUpWbTU0VUI0RjVyVzdIZnFVbmpsaHV6S0lMWHk5ZDN3Zy8ydHZ6ZFJnQ2RtM095emFYWHJoODIyNmZ2TGxkWXZOR3BOM0x0bTRXVmI0WE03azQ5NTBXSHdzS1Y5SzFMbWhpS01MbGlUM2s5MCszUm9SdHZmaHhFNU54NkFWMjVOUCtZUE5vUzE4YVIrU2h1ZGQxckdEN1ZucjIzOTljcGtXS3NONEN1VHlhTXdUMThSYWdPalpMWUdyOXNHVis5TFB1YU5RMVE3eW4wWVRSVFMvME5tYS9EeXJlR2RScjljc1NmMFNTVlpOZ2F2MjlpLzhrZ1FwaTRrT1daeGR2YzllbEh5bThWTEd6cnNkODdDdnllVWNReDQxZ2cxMWRYTjF1Q1BmNTY4RVBOWksrRzBJVm50SmZkaDlLelY2ZXR0ZlhnSFhKdlFQSkdsaSs0T2syYVRQSGROYUVlWCt1VzJxYkQxUVN2ck0rd3pTcHBiZFBmTW9lLzZ2NWpTVlBlc0VXdXFxN3R0S3YzTjdZc1A2MTlac3BUN01Fb2JDWFRQREZ3VWFXN1B3UnE4T2FYVGVLSVFiMGtXamE0WXE4b25oY2ptRmlQb3ZyWTd1UmJ3Mk9XRHNkQnJEQi9ZSG1xT3JaeS9KbjJDYzE3aytpWDgwdEwwQlVuZnQ3MC8vVVJKcnRpVDNHa004T3RyaDN0NUR3MmVmaTg4ZXRLU01HaW5sVlp6YXZaV3cvNWdyUlFJYTdXTm9yM1ZNQ2V5bFdVZHJQYzN5SElkUm1uclZ1MmVoWXZ2NjE5Wmt2eFRTdlg2cUpTMmRLblhGaFZnWFVMVGNGYXJ5NXlmOER1Nll3YitLNkZqL3NzcEV6K1RCa0tNZ2srbVBNK0dZVUhaWElmUmVTbGg5TmxkY1d0RmRaZnRUbC9UTE8wMVNMMzBtT1hKdi9CWk5kOGxEY20rZEhmeSttcVg3MDZlSHZHd3BXRUpuVkgwOCtua0FPOTBtYVZCbE5zd1dqdWV2djdjbHdka0xhdVpXaGl5bXVSWDIxaVBTdXFGczFQbUV0MmN3VVR3VTVlR1pycFcwbjQvcDJwaElteVNibGJpSHhaSm93M1hUOEF4T2U5UHkyMFlQVHJsSWI1ekZxNkpNSUl1eVdVcE02bFBXemE2RzRpcGYxYU13UXRUUmwxZGxjSHZTMUt0YU5jc2ZDOWw3Z3c0QVRiSjkxUCszZkkreER1M1lmVExLYldpYS9ZTjFoTHJWKzlMYnBOZlZJQVRSN1RaUWYzekp4dmhzSVRoMi91cVlRbWFYaXFRMGtTWE1ybTE3bHQ3azVzT0g3SWtERjRhUlQ5SldmUTI3ODJYdVEyajQxTCs0YTlOK1ErTFlVOFZmcGJTREpMbGhFUHBhYXZTcDBCY3NpdDUvbEczSHJVc2VSaDJwWTJWcWVkcjNrNGFHREhzZHM0bVQrRFArL2JrdVoxMm1kWSsycy9Od3RwMTYxUnkrM20vNTA0OGVqbDg1Nkc5dis2SGQ4QkhkdlQrdXZONTBFUTJyNmN5Q2Y4cjQwMElzelJSZ0Zkc0NMV2lwSGVkTTdYMEVaL2RTdXJYMlQwYmFqM3R1R1FubEJLYUZzOWZBMisvdTZ1aTVkNTlzNjFYTWQrWTI2ZDVrTnZpcjB5Wk1YN25QTXV2eC9EemxETDFleFh2eFlWc0FuQjFwQ1h0eHpONlBldHl1a1QvK29td01zbEwxc1B4ODlTNlA3UWo3S25UUzJOQU1TR01MdHZkL2k3QS83VXZyTkxRNmlGNzNHSjQ1REw0NFFEMURmZEwwbFkxWXpudmU4NXRHQzFKK1lmUGNtWHViaVhOS2dkWW5kdkdVbVhsL05YSmswVmJPVmlGNVdNaGZFNWEwdDVrNmg4ZGdML1BvSGJ4aEJYSjc5TFQ1aEExcXhJR01yd3NvWW54V1d0R000eVM1SDBWaHR5R1VkcS8rd0NOWGZpRnFiUkM1ZndkalhydnBDWEp6YnE5Y1BzMHZPUzJlWDR1dTVTMC9NK2VhdnBpcmExOEtTV016bDhEYjcwemVWTytZWlUwK2pibldaVGY4cWY5QUM0YndGZTFOQ1Z3ZGc5Z1RVN0Q2N3I5WVp2cnROMWZ1elZSU0Y0WjVSdTdPdysvSCs0UEM0VzJjc1JFV0s5dTFHVHhCbUlRRE9CanV6MXAveUZKUTFoalN0dUxwUmZibjB2em1hMkY5UnFmZDNONkgrWkNQSEZGOGhiaDdZeWlheVZ0SmUvbnJPM3VtbmsybnZER05xMHJJQTl5MjB5M1BXV0puVUVjS3AwMitxL2ZBeTcrK3lDODQ2N2VYL2VtU0tNWWQ4ekFuMjdyL1hXemVtRDNXeFhZdkN1c1lIOVRCaXN0TkVvYVJiZXZHaFlPN3NZWEorR1ZoN2YrM3ROWHdWOFdCbXRlWWRiV0pGUWgwcFlkeTRQY2h0SFdsQWRGMmpKQk1Zd0JwNlIwUnQvYTU0ZmV2VFB3MVpSVklmTG1RRzI0WGs4djFBaTdEbDg2Q1ovZDJaOWdYVktBY3hPYTZMNjVwL3U1VEQ4NUFQL3ZZT3ZmNi9VVG9UYjJ6UzZETG04bUNyQWg0YWw5dDJFVVI5cGNvc2NNV0R2eVNVdVNSN3JNMWdaelhwVGlldi8yRUxMdE9sQU5UZGM3WjBQdy9HaC84bUtqV1hucXF1U2Y4NnYzTFd6dHRHL3ZUWDZUK2N3MW94TkdKeXdPZ2RUS1R6T3U5V1l0dDJIMHc1UTFtazVaRWpvMzd4cVFkd3BucFN4UWVjT0J3VmhkWElQbC8yd2Z6Q2tLYWRKMll2MnJCNFdQTEd4YURYKytiWGc3OWh1bGJUbHp3NEN0UE5PcDNBNWd1UDVBK2cvZk9RTzBYRWphTmhGSlM4SkxlYkppTE42ZU9pdkg0TWtwYi9pR3lla0pXMFhzcVdiZkg1aTEzSWJSZEEyK2s3S3N5SXZXOXEwb3FVNVlESTlQYVRhODNMNE9EWUZ6VjZWUFJNL2FLR3dyc2JpUUhQaFg3bWwvWll0Qmxkc3dndlNob3FjdEM4dUZ4UGJpZGNuZjJ6NEQzN1ZtcENFUWUxdUhwNjRLdGJOaGR2YXE1R0h6dy9DbU50Zi9mWmRPcHMvUmVlM0cvcFdsbFkwVDhKc3BZZlQ1WGFNMUpGWERhZTE0ZXI5b1B5d2ZDNEUwekpKV290aGJUVi9oUEM4NkNhT0JXN1JtNTJ4NG9DYzVhMlZ5RzJzL3ZHWmpjdFBGYkEwK0dtR0ZhNm5YbnI0NmVZUlhQOFd1bldYcENTdmdjUW5OL1YvWTFmK1JrMW5vWkRUZEFQeTRIZXJETytBRmE1Ty8vM2RId1RrMzlYOTI4dU9XdzRVcE8ydCthWEo0SmxWcXRLWDExL3oyYlhCRkQ1dVFsbzdCRDA4Sk5hRm1UMWtKcThhSGIzbXRNZUJOQ1NNUmE4VFp0aVVMdWE0WlFaZ1FsOVozZE1KaStPc2orMWNlQ08yNjd6a20rZnRUTlhqSGlPN0ZvdUd5ZmdKK0xhSDFZZGRzNXd1anp1ZEFGYjZlRUc2TEN2Q01JV3lxKy8wTnlTdTRmMzVuL3VjWDFlVzZ6Nmp1ZjkrVlBzeTdkQmk4TUtXVzBrdUxDdkNQeDZSUDhQdndEdGpxUkZjTmdmTlhKejlFTnJleHZYZzMwcHJtMCtZNjVkRmpsc1ByRS9xK0QxVERFay9Eb3BNd0d0aXU5cTFUOE41NS9sUGVkaFE4SitNZjFFVUYrTUN4NlhNZWJqb0k3N0pXcENHUjl2QlBXK0IwSWY1alQzSWZ5WmtyMGhjbHpwTXpWOEFuajAvdWo3dm9udVFWemZOb0tNSUk0TDNiNFpxVWpiYkdnSGNkQTcrWE1DSmxvVFpNd01VbnBFLzhtNjdCSzIvUC8rcTZFb1RkZFpPMmNNaHkyc0pVRFNvSlFUZGVnR2NNMElUM2Jvd0Jyem9jUG5GODZDTnI1UWY3UXd2TE1CbUtaam9JelFGL2ZIc1lZWmRrRFBqTEI4RS9IWnU4MkdBM3psc0ZYemtwZlhJcndCdTNoY1VycFdHUVZpdjY4bVMyMHhiUytvbXpiZ0hKMHFPWHdSY2VISnJta3JhSzJERUR2NzgxLzVOY20rVitBRU9qVzZmZ3BiZk4vNSswYVRWODQrVFFNWmowenFNZHB5NkZqeDBISHpvdXJJV1g1bDEzaDlXVHBXR1JOcFE2cXlhNnVpdjNob2R5SzQ5ZFB2L3Y0eUJaWEFoenBDNCtBUzU1TUR3aVpiTCtnV29Jb241dk85TVBuZnlYRGVDV2RZZjYvajU0MWUxaEVFSGEzSWMxNC9BWFI4RExOOERuZHNJbHUrQ0cvZk52WWJ4K0FzNWVHUVpFL0dxYnE0UC82NzN3N2lIcWFKUk9YQXdQU3hqaHRXMDZyTktkcGRrYVhMbzdERTVxVmlBTU4vL2dBRFZqTFNtRWtObGJEVHRSSHo0Qkp5OEpLOFdjc1NKNXRmTkdrN05ocS9qdkQrbXFMWjJFVVc2YTlDcVRzT2MyK09DeDgyOUJ2bTQ4ekd4KzJYcTRkelpzYzN6VHdmRE9ZMTgxdkdzNWJCeU9Yd3kvc2pUc1M5UkpGZkdqTytETmR3NTRoNXZVb2JSYTBaZDI5ZWZuL2ZNN1c0Y1JoRzBsK2hsR2J6OHFCRTJTeFlVUVB0MzY4UUg0dzl0aHk1QU00MjVsS01NSTROLzN3SE51aHZjZEN3OXVjK2ZYZGVPaDFuTjJENVkybWE3Qlg5MEJGOSszOEd0Smd5WnRvdXNYKzdRMHpWWDd3b1p5RzFzOHhSNjVMTHlCN05kZVljZG50THQwRGZqNHZmRFdPNGQvNE5OUTlSazF1L0VBRkxmQXAzZjI5NzViRHNMemJqYUlOSngrYVdueXUveGJwdUQ2bEZHdHZWUWxMSVdUSk85empxN2VCOC84R2Z6UE80WS9pS0N6TU1ybDZrZDdxL0M2bjhOemI4NSs4Nm1EdGRBM2RONlcwTnduRGFOblJ4eTQwQ3hwaURma2QxdUpLL2JBaGJlRWxwMStCZnNneU5HWWs0VzVhaDlzMmhKR3JmemhodVQ1RWQzWVc0Vi91VGUwVVNlTjhKR0d4VE5UNXZIME80eXUyUjhtZmg3WG9wbnNsQ1h3MENYdzN3UGV6N0szQ3RmdWg2OU93bGQzaHdFZ28yaGt3Z2hDKyt2bHU4UEhTVXZDZklUelZvY2YyazRkcUlaSmZaL2ZHWDZBOWcxZ3ZmR3VHVmpUNGdmN25wd0c1dmFaMW92TDNwSFRYOTdKMmVURmNxc0QyaXh6eXBJdy82VlZ1VytkaXZQZy8vUk8rQjhKQXhuT1dObWJNdDA1RXdZaUxjU3FNU2dVb0ZhRDdiTnd6elQ4YkNvMDZ3L2c0NlB2Q3JWYWV6LzFoWXMzdnhONGJiYkZpZU93OFZCVE9ubEo2SWpjTURIM2d6UDMvVm5Db285M1RJZGZ1T3YydzNVSGhtL1NtU1JsNEQyMUN6ZTllcjZEMnFvWkZTN2VYQUJTbHY3TXQvdG00YkxkNFVPUzFIL3REbUFZNmpDU0pNWFZTUmpsYXA2UkpDay9obWJWYmtsU2ZyVWJSalZDUDc0a1NUMW5HRW1Tb21zcmpHb1hicXBoTTUwa0tTTkR2VGFkSkNrZjJncWp1WGxHdWRqUFNKS1VQdzd0bGlSRlp4aEprcUp6bnBFa0tUcUhka3VTb2pPTUpFblJPYzlJa2hSZEowTzduV2NrU2NwRUo2UHBSbXBYV0VsUy96aTBXNUlVbmNzQlNaS2k2MlEwWFRYTGdraVNSbGNuWVRTZFpVRWtTYU9yazZIZGhwRWtxVk50ZGZGMDBtZGtHRW1TT3RYek1MTFBTSkxVcVo2SGtTUkptWEJvdHlRcE9tdEdrcVRvM005SWtwU2x0c1liT0lCQmtwU2x0aW95aHBFa0tUcWI2U1JKMFRtQVFaSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkRvSm8xcG1wWkFrRGF1MnNxT1RNTnJWWlVFa1NhT3JyZXl3bVU2U0ZGMG5ZYlEzczFKSWtvWlZXOW5SU1JqdDY3SWdrcVRSMVZaMmRCSkdPN29zaUNScGRMV1ZIWWFSSkNsTFBRK2plN29zaUNScGRMV1ZIWjJFMFRhY2F5Uko2c3p0N1J6VWZoaVZpbE9FUUpJa3FSMTdLUlczdDNOZ3AvT01mdFpGWVNSSm82bnR6RENNSkVsWnlTeU1ydS93ZUVuUzZHbzdNem9ObytzNlBGNlNOTHJhemd6RFNKS1VsWXpDcUZTOEM5amFhV2trU1NObkYvRFRkZy91WnRYdS8remlIRW5TYVBrT3BXSzEzWU83Q2FOdmRYR09KR20wZEpRVmhwRWtLUXVaaDlGMXdCMWRuQ2RKR2cyN2dXOTNja0xuWVZRcTFvQkxPejVQa2pRcUxxZFVuTzdraEc2M0hkL2M1WG1TcE9IWGNVWjBHMGFYQWdlNlBGZVNOTHlxd0JjN1BhbTdNQ29WOTJEdFNKSjBxRzlTS3Q3ZDZVbmQxb3dBUHJPQWN5Vkp3Nm1yYkZoSUdIMkpNR0pDa2lTQUtlQ3ozWnpZZlJpVmludUJmKzM2ZkVuU3NQbGN1NXZwTlZ0SXpRamdJd3M4WDVJMFBMck9oSVdGVWFsNE5YRFZncTRoU1JvR1B3V3U2UGJraGRhTUFON1ZnMnRJa3ZMdDNYT0xJblNsRjJIMGFlQzJIbHhIa3BSUE80Qi9Yc2dGRmg1R3BlSU04SjRGWDBlU2xGZnZvMVRjdjVBTDlLSm1CUEIrNE00ZVhVdVNsQis3Z0lzV2VwSGVoRkZJeExmMTVGcVNwRHg1TjZYaXpvVmVwRmMxSTRBUDRKYmtralJLZHRDalFXeTlDNk5RTy9yTG5sMVBralRvM2tLcHVLc1hGK3BselFqZ0U4RDNlM3hOU2RMZytUSHd2bDVkckxkaEZNYVkvM0ZQcnlsSkdrUi9NamVhdWlkNlhUT0NVdkc3d0FmYlBMcnJDVktTcEdnK1RhbjQxVjVlc1BkaEZMd0IyTmJHY1FYQ1JreVNwSHk0Ri9palhsODBtekFLSFZxdjZLQU1CcElrNWNOcktSWHY2dlZGczZvWlFhbDRDZkN4RHNwaElFblNZTHVFVXZGaldWdzR1ekFLWGdWc2FmUFlNZXhEa3FSQnRRMTRhVllYenphTVNzVTl3RzhBMDIyZVVjTkFrcVJCVXdWK20xSnhSMVkzeUxwbVZCOWQ5NW8yajY0MzF4bElralE0M2tTcGVGbVdOOGcrakFCS3hmY1NKc1MyWXh5WXhVQ1NwRUh3UmVDdFdkK2tQMkVVL0Q1d2RadkhUbUFZU1ZKc1B3WitjeUdiNXJXcmYyRVUxcTU3Sm5Ccm0yYzRvRUdTNHJrTDJOU3J0ZWZtMDgrYUVaU0tkd0tiQ1B0ZnRLT1FZV2trU2EyRnlrT3BlRXUvYnRqZk1BSW9GVzhrQk5LQ2RnV1VKR1ZpR25nMnBlSlYvYnhwLzhNSW9GVDhOcUhKYmlySy9TVkpyVlNCWDZkVS9GcS9ieHduakFCS3hTdUE1OVArSEtRNis1RWtxZmVxaE1FS1g0eHg4MEt0MXQ2enZWRElxUHVtWEhrcThDVmdXVFkza0NUTll4cDRQcVhpRjdLNGVEczVFNjltVkZjcWZoMDRGNWpzNG14clNaSzBNUHVCWjJVVlJPMktIMFlBcGVLM2dET0JyUjJlNldnN1NlcmUzY0NUZTcwM1VUY0dJNHdBU3NYcmdTY0FQK2p5Q3RhU0pLbDlQd0dlUUtuNC9kZ0ZnVUVLSTRCU2NSdndKT0RUWFp4ZHJ5VzVGWVVrcGFzQXAxTXEzaHk3SUhYeEJ6QWtLVmRlQTd5ZHNGWmRONmJuemgyc3dKV2tlR3JBbTRHMzlHT0puMS9jdEkyY0dkd3dBaWhYbmdTVWdXTVdjSlVwUWlCTjlLUk1rcFJQZHdPL1JhbDRhYjl2bkkvUmRHbEt4ZjhBSGc1OGFnRlhXVXdJb2xrNm45TWtTY1BneThERFlnUlJ1d2E3WnRTb1hDa0I3d1kyOU9CcU5SeUpKMmx3OWVvWnRRdDRQZkRoZmpiTE5jdC9NMTJ6Y3VWdzRGMUFLWFpSSktuSGV2MG0rUkxnRlhNRHc2SWF2akNxSzFlZVJxZ2xuUnE1SkpJMGFHNENYa09wK0tYWUJhbkxmNTlSa2xMeGN1Q1J3Q3VCelBaa2w2UWMyUVc4QVRoMWtJS29YZm1zR1RVcVY5WUFmd0s4R2xnVHR6Q1MxSGQ3Z2ZjQzc2QlVITWczNThQYlROZEt1YklXZUMzd2g4QzZ1SVdScE14TkFoOEUza2FwdUQxMllkS01WaGpWbFNzcmdOOG0xSlpPaWxzWVNlcTUyNEIvQUQ1RXFkak5BdE45TjVwaFZGZXVqQUZQQTE0R1hBQXNpbHNnU2VyYUxHRUpudzhEbXlrVlp5T1hweU9qSFVhTnlwV053QXVCRndCbjRCd2pTZm53UGVBendDY0hZWWgydHd5alZzcVZvNEJmQjU0T1BCazM5Wk0wT0E0Q1Z3SmZBVDVIcVhocjVQTDBoR0UwbjNKbEtXR1Y4TE1JK3lrOURzTkpVdjhjQks0bUJOQ1Z3RGNvRmZmRkxWTHZHVWFkS2xjV0FROERIZ0djUmxnWDcyVGdXTHBmUFZ5U3FzRHR3QmJnT3VCNjRGcmdla3JGZ3pFTDFnK0dVYStVS3hPRWxjT1BCVFlDNndscjVDMEhWczRkdFFiN29xUlJ0WFB1ODE1Z0g3Q2RNQ0gvSHNJTzFsc3BGVWQyb2VhZWhwRWtTVm5KNTNKQWtxU2hZaGhKa3FJempDUkowUmxHa3FUb0RDTkpVblNHa1NRcE9zTklraFNkWVNSSmlzNHdraVJGOS84QlJ6c0MwaWFneEIwQUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiLCJjcmVkUHJvdGVjdCJdLCJhYWd1aWQiOiI2OTcwMGY3OWQxZmI0NzJlYmQ5YmEzYTNiOWE5ZWRhMCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImNyZWRNZ210Ijp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjpmYWxzZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjoxMDI0LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJ0cmFuc3BvcnRzIjpbImJsZSJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwiZm9yY2VQSU5DaGFuZ2UiOnRydWUsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjoxLCJwcmVmZXJyZWRQbGF0Zm9ybVV2QXR0ZW1wdHMiOjgsInV2TW9kYWxpdHkiOjN9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wNS0wMyIsInVybCI6Imh0dHBzOi8vcG9uZWJpb21ldHJpY3MuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiUG9uZSBCaW9tZXRyaWNzIE9GRlBBRCBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzA1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDUtMDMifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTA3LTEwIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYmY3YmNhYTBkMGM2MTg3YThjNmFiYmRkMTZhMTU2NDBlN2M3YmRlMiIsIjMwMTJiNjYwOTJhMTZkM2Q3Njg3MjQxNjM0YjIwYTNiZGUyNjM0ZTgiLCI3NTMzMDBkNjVkY2M3M2EzOWE3ZGIzMWVmMzA4ZGI5ZmEwYjU2NmFlIiwiOTg1NTJhZWE0NTYzNzBlMjJlMTkwMWUzMTgxNzM1OTE0MmI5Mjg4OCIsImI3NTNhMGU0NjBmYjJkYzdjN2M0ODdlMzVmMjRjZjYzYjA2NTM0N2MiLCJiNmQ0NGE0YjhkNGIwNDA3ODcyOTY5YjFmNmIyMjYzMDIxYmU2MjdlIiwiNmQ0OTFmMjIzYWY3M2NkZjgxNzg0YTZjMDg5MGY4YTFkNTI3YTEyYyJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJiZjdiY2FhMGQwYzYxODdhOGM2YWJiZGQxNmExNTY0MGU3YzdiZGUyIiwiMzAxMmI2NjA5MmExNmQzZDc2ODcyNDE2MzRiMjBhM2JkZTI2MzRlOCIsIjc1MzMwMGQ2NWRjYzczYTM5YTdkYjMxZWYzMDhkYjlmYTBiNTY2YWUiLCI5ODU1MmFlYTQ1NjM3MGUyMmUxOTAxZTMxODE3MzU5MTQyYjkyODg4IiwiYjc1M2EwZTQ2MGZiMmRjN2M3YzQ4N2UzNWYyNGNmNjNiMDY1MzQ3YyIsImI2ZDQ0YTRiOGQ0YjA0MDc4NzI5NjliMWY2YjIyNjMwMjFiZTYyN2UiLCI2ZDQ5MWYyMjNhZjczY2RmODE3ODRhNmMwODkwZjhhMWQ1MjdhMTJjIl0sImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IFNlcmllcyB3aXRoIExpZ2h0bmluZyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgNUNpIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAxOTEwMTcwMDciLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhYWd1aWQiOiI4OWIxOTAyOC0yNTZiLTQwMjUtODg3Mi0yNTUzNThkOTUwZTQiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6Ijg5YjE5MDI4LTI1NmItNDAyNS04ODcyLTI1NTM1OGQ5NTBlNCIsImRlc2NyaXB0aW9uIjoiU2VudHJ5IEVudGVycHJpc2VzIENUQVAyIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoidm9pY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOlsiYW55IiwiaGFyZHdhcmUiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUY5RENDQTl3Q0NRRFNiUGVQdjd6R3FqQU5CZ2txaGtpRzl3MEJBUXNGQURDQnV6RVVNQklHQTFVRUF3d0xVMFZPVkZKWklGSlBUMVF4TFRBckJna3Foa2lHOXcwQkNRRVdIbTFpWlc1dVpYUjBRSE5sYm5SeWVXVnVkR1Z5Y0hKcGMyVnpMbU52YlRFZk1CMEdBMVVFQ2d3V1UyVnVkSEo1SUVWdWRHVnljSEpwYzJWeklFOVNSekVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVMTUFrR0ExVUVCaE1DVlZNeEN6QUpCZ05WQkFnTUFsQkJNUlV3RXdZRFZRUUhEQXhYWlhOMElFTm9aWE4wWlhJd0hoY05Nakl3TXpFMk1UYzFNRE14V2hjTk5Ea3dPREF4TVRjMU1ETXhXakNCdXpFVU1CSUdBMVVFQXd3TFUwVk9WRkpaSUZKUFQxUXhMVEFyQmdrcWhraUc5dzBCQ1FFV0htMWlaVzV1WlhSMFFITmxiblJ5ZVdWdWRHVnljSEpwYzJWekxtTnZiVEVmTUIwR0ExVUVDZ3dXVTJWdWRISjVJRVZ1ZEdWeWNISnBjMlZ6SUU5U1J6RWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRUxNQWtHQTFVRUJoTUNWVk14Q3pBSkJnTlZCQWdNQWxCQk1SVXdFd1lEVlFRSERBeFhaWE4wSUVOb1pYTjBaWEl3Z2dJaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQ0R3QXdnZ0lLQW9JQ0FRQ2xZNXB0dEEyUkI2OG1GSTQ5Ui9ybFNFWE81VU11R05janVoYjF0VllvTzhWTGZuam9YUzNFTStKaFg3eTBXbHpVVDgyL0JkUU5pa21hNWg2cmpUNTZnbjd2Wjd3WXY0ZFhLdll1d2tkVm4rYW5OQmNhRVJZeHlCRUZXV2dxTFo3cVZuWElhWUt2enBLcjVwSVJTRmFRYUszenV6bTBxQzVqVExFaXRzYzVOaU1obWU3ak9VSHJEZkwzVHJPZHRKeldSMGRxakZRa3QyOE5wczgzcXl1dnpiQW9OQmFyWTNhSHpIM2VoZjhkZzdrZkZzSHZtYXZJcFNtNW5qMldKRWkzSys3NnJoamhITEFuVG5udE8rcDg2MWxYVUI5WkQyeEdxc1Ftc2xwS01SSFZMd3ZCVmhJckpTOXRKWUxTOWZkYXQ1aUFJaGtDRlZUTnF0QUpFQWMrUXRacXlsSll2Y3YrVnJEM2xZTUlJNGpuMDNnUFB6ZGs4dDFqUExkdzBINGs3a0FwTGUzWDNNSTFJT3hkbXMyTW1OcnZOYkU4cXhmZ1F5M012SG1UbVZVd2ZnN2k3ZnpPSThyR0hzeGxkbjVaRUZkcmdHK294aTk0cUxMWmNWcDhudnczWUJJbnBVdlBKUThRVlVlVlZwd1FramhZL2U4MVhjaWQyd2doQXBnbTVoQko4VGZZbjhkZ0QwMXZiTjNqWE1UTm5MK3VyTzZRRzNiVEdnR0c3NEJnNzZUZ0puT1RkWUZZWVFiaTl5cWFJRjJQNUdnR1UrMFJaMDFRVTI1am5URUZOUXFuVUYwdFpFMkpIQU5uK3Rya25FN0wxR3lFOXF1cGxNa2FtNGh0bVN1VDFzalE4aEFrYnVnMDhkQmIrZlFmOEZQOGlva0RiK09hK2gzYm9RSURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElDQVFDTnh6SWUxVDRXWGhuMEZsc2JaZ1NlL3VFZDVIdFJQNFdhVnN1RTBlMzBXclVWTnpVYWhUeWo5VFVUSlVDUzdmNG1wTkR3bk5tZHRvTWVZSm4rRzEvbDBLQmlKV0MyMHNjaDBweXFlVmhhZG8yTzhXNFdPYy9pV0dyZEZuZjFqcHV3eVNsbTFINmk0ZCsvZkoyVzBsSzNDYVAwWUYzeFNHVXJTUkpnOWFaSG9ocE43OVNZRnNtajM0eDhXK0NrRm1UWVFvNmE2Uk5TK3FqVENhRFhQSGN3NEVHMFlmamhkVVJNaTZSN2tydnhkdW1iUFJ1QlJzb044NmRYS3BZdXVLRGNTL1NaUXhjYTl3RTNFZ3hSbEN3RmRQcmMyZWd0cjVDYm5UWm1IZ0JwNDl4YTBsaWxjMkVIUVl5bUdMazJTWG12c0tUTHhydS9sZ1Z6OE12eXhqTWR2YVVLVkZha0lqRE4vbFZBV1pUWjNtRTRETSsyb0xCR1VCN2ZxV0lFOUVWNVJDSzdvOEgxOStRaFU4dnNQMTQyWitLQStwRUZIRXVXWjJvVTd4ajVRU0sxUHlvU1gzTnh3MUpCL2xPK0NQSVpyZGRDTENwZ1dmWDRaVDQ2M3h0bloxQ2lHeU1DVU9pM0tPaUdOczJTU0JqU1lJT2RwaXZvT0ZHQTNhVU1vbUhHWmFwcGdvdFJLZWVtS0hmZExyVEJGV0h2UXFCeWVNVzFrTm5FcUQ1M0ZyUzErYS9wbmVjSmhMZW9Xbk9zbzRvb1N0a0xoQWxldVFWK2oyWEJteEpucFoyMXczNDdoVU1keVA5ZjhYY0ZlNmY5eTJWa0h6UkNlaVk3SHRldVE5M1l4Vzg4YzRFaXJYamhGK1dlZDJkbjQxMG01WGRmQk1QZmE2NjhSYXUrcWc9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFQUFBQUJBQ0FZQUFBQ3FhWEhlQUFBQUFYTlNSMElBcnM0YzZRQUFBTVpsV0VsbVRVMEFLZ0FBQUFnQUJnRVNBQU1BQUFBQkFBRUFBQUVhQUFVQUFBQUJBQUFBVmdFYkFBVUFBQUFCQUFBQVhnRW9BQU1BQUFBQkFBSUFBQUV4QUFJQUFBQVZBQUFBWm9kcEFBUUFBQUFCQUFBQWZBQUFBQUFBQUFCSUFBQUFBUUFBQUVnQUFBQUJVR2w0Wld4dFlYUnZjaUJRY204Z01pNHpMallBQUFBRWtBUUFBZ0FBQUJRQUFBQ3lvQUVBQXdBQUFBRUFBUUFBb0FJQUJBQUFBQUVBQUFCQW9BTUFCQUFBQUFFQUFBQkFBQUFBQURJd01qSTZNRE02TVRnZ01UUTZNRFU2TURZQWMwZmp5QUFBQUFsd1NGbHpBQUFMRXdBQUN4TUJBSnFjR0FBQUE3QnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlsaE5VQ0JEYjNKbElEWXVNQzR3SWo0S0lDQWdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRLSUNBZ0lDQWdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlLSUNBZ0lDQWdJQ0FnSUNBZ2VHMXNibk02ZEdsbVpqMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzkwYVdabUx6RXVNQzhpQ2lBZ0lDQWdJQ0FnSUNBZ0lIaHRiRzV6T21WNGFXWTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2WlhocFppOHhMakF2SWdvZ0lDQWdJQ0FnSUNBZ0lDQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpUGdvZ0lDQWdJQ0FnSUNBOGRHbG1aanBaVW1WemIyeDFkR2x2Ymo0M01qQXdNREF2TVRBd01EQThMM1JwWm1ZNldWSmxjMjlzZFhScGIyNCtDaUFnSUNBZ0lDQWdJRHgwYVdabU9saFNaWE52YkhWMGFXOXVQamN5TURBd01DOHhNREF3TUR3dmRHbG1aanBZVW1WemIyeDFkR2x2Ymo0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2VW1WemIyeDFkR2x2YmxWdWFYUStNand2ZEdsbVpqcFNaWE52YkhWMGFXOXVWVzVwZEQ0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2VDNKcFpXNTBZWFJwYjI0K01Ud3ZkR2xtWmpwUGNtbGxiblJoZEdsdmJqNEtJQ0FnSUNBZ0lDQWdQR1Y0YVdZNlVHbDRaV3haUkdsdFpXNXphVzl1UGpZMFBDOWxlR2xtT2xCcGVHVnNXVVJwYldWdWMybHZiajRLSUNBZ0lDQWdJQ0FnUEdWNGFXWTZVR2w0Wld4WVJHbHRaVzV6YVc5dVBqWTBQQzlsZUdsbU9sQnBlR1ZzV0VScGJXVnVjMmx2Ymo0S0lDQWdJQ0FnSUNBZ1BIaHRjRHBOWlhSaFpHRjBZVVJoZEdVK01qQXlNaTB3TXkweE9GUXhORG94TVRvek1TMHdOVG93TUR3dmVHMXdPazFsZEdGa1lYUmhSR0YwWlQ0S0lDQWdJQ0FnSUNBZ1BIaHRjRHBEY21WaGRHVkVZWFJsUGpJd01qSXRNRE10TVRoVU1UUTZNRFU2TURZdE1EVTZNREE4TDNodGNEcERjbVZoZEdWRVlYUmxQZ29nSUNBZ0lDQWdJQ0E4ZUcxd09rTnlaV0YwYjNKVWIyOXNQbEJwZUdWc2JXRjBiM0lnVUhKdklESXVNeTQyUEM5NGJYQTZRM0psWVhSdmNsUnZiMncrQ2lBZ0lDQWdJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQZ29nSUNBOEwzSmtaanBTUkVZK0Nqd3ZlRHA0YlhCdFpYUmhQZ3FLWTdWbEFBQUU3VWxFUVZSNEFlMlZiMGpkVlJqSHozTitWKy9WWFoyVkExUFpER1NSd2dwRHlGZWpQOHlnSU1oRkZHVTUySUtWU0xUVkxHaVhpalpxelNGV1EyS1FOTlo2MFl1TnhkaVlqdjdRUUh0UlU3WVphZFp5b0daY042OTZyNy96OUgydTk5emQzYlM5MXAwZm5Idk83L2wzbnVkem52TzdTcm5IRVhBRUhBRkh3QkZ3QkJ3QlI4QVJjQVFjQVVmQUVYQUVIQUZId0JGd0JCd0JSOEFSY0FRY0FVZEFxVWpQY09nclptOGxzOUNMRmNkS0VVY2ltdnhyL1JmTzlIZEhlZ1pLRnJOYkNUTEtMaUxXVmxtblBYTUc4bHlNUnorby9yb1NUWEFBaHFlTkYzNHE4dUJkczlrK3kvazlEWUEvcmFpSUo3d2pyUGgycmZoNVpoMWo0aU1vem84RzFqUWVYUC9aRmtXcUllL2l0N1d4OGZISlNDUVNYODZGMjl6VFYyQTJvWDgweEoxZWlkbEdwZHpsbFprM2dzMURHNGhwYitIOFJQZmIzemZ2SUZZNW1nUDE0VHRLMm13QU96T0laWTBrM0N4WjJrYjhvQ1BSMnhqWnNxVjhyYzlpZWhzTHV2K05iZTNTbTV2Yi9KckFuYWFWdERyR1NqL25OUXczRWlrT3R2ejJaV2d5VktwMjkvamloS2k0QXJyY0JzQkdWYjd2enhqSXM4YWZrZ1JrMTdMa1NiczU1bXBqVEd0S2QwS0tTY1Y4UW1UeXZwUXY1QlBRbDZWOGI5alhOMllhdXJVWVI2R1AyVHhseG40dDRwTXBzNXVxWUI0TjRlUDM4WWVoWXhXNW00ZjZwSGhyU0pHQk9CRktSLzBvZmdablYyUjFDUHFxSWdyQm9IS1dxRUtHSmxxSGNaLzR3QzRIODA5V2w5S3Z4UWZtRW5TeXYzUkZEUklieFZ3TXlpTEx3V0NKRXlNcTk0bnFSR2FJSHBaM2pMdVJoSFNZeUI1UHljcm5pV29neXpkS2JVZXNPYXlEbU5kaGxtNWJ4VVNic0V3ZXBNamtTUU9BTW5EQ2EvazhIcUt6U2MwaVA2UW9DanZzclFxc1dtdDlWdGE1ekJkQ3pJTXlVTXdnd096RnBwS2tiRjVyZFRMN3pCMkFNaTg2UFBHcGFQUWVrRG9QdnhFeVp1T0NHQlVTalJjUWpZSEczeUpEWVpQeWpqRnViUUpLRlFjVGlWSVpnTG9tS1RlR1kxcS9ocGc5aURrOGI4d1BtTWNBOUg0MnB0SDZ5Z3gvKzdBL0ZpNHJ4TFpML3U5N1Z5NXZKUGFQc3FLcjFndEpIa2EvOWdaQjNzcVFhQVBXYjJMc0ZCbHMra0hpUlZuTGc2T1pXbGd0L0k2T2pzYXFpb28ySWRGZFNQTDlUTjNOMWlqc3NCZFlLQU5yTWZmbnRQNUVRR0g5RU9CWFEzNGVTZXhDRHZzRGdZQUZud3lkN2dBMHZCL1NhQTgydXIyOVhWb25lWHBpaFM5KzRLT096dFpRZEdRRTR1L2lGSG95NlkyZmVlYk5PY3dEMktUWERoejVXMUFKcEJpQ3dJZnZoYTdQNm1GL1NSS3pNV1FHSk03eHZEMDRvUzJaOHB1dEFhelcwNXBrSUVpWDJPY3BOWkhoZDFuV1FET01QVzRvWHVUcERrQ2kvK1Q2UGc2WEtPR0ZudG5YMGZueXZ2YURML0JjL2dnRlo4NFpWbjlvcmVweDh6cURKaTczTjdrWjJxVVBkM1NyQk10NGVIWjYrbVE0SE1hM2p0ZWpJNTZHRGsxeS9ZbEdvNlA1cTFjZjE3NC9VbFZWbFU3TTg3eHVYTkltQVhMZFdrM2c2aldoeGYreU1oUTVpWDJiOFA2N2xlRTBYNEdzQisvbEdMK201RE1DRlhGN3JWM21uRDVsL3FLeXNLMjRLM0RWS3hoR016eFdjUEZjR2M3bEVBcjR4cWRFaTZkeTk4T3hIckpuZHpSdlBZazVNOEhNbU10cW5RWmdzMzd2OU04UEdPMmR3blc2d3ZOVGRhc0crMS9IWWV6RXlSOGEvRVZ0Nyt4OEtXRnRWOEw4SHdDMnFIZTZCN2FoZGZiZzloelkvY2lHZDYzOGxwb2p4L3Z5SXoyYy9rN2NVc1c3WWgwQlI4QVJjQVFjQVVmQUVYQUVIQUZId0JGd0JCd0JSOEFSY0FRY0FVZkFFWEFFSEFGSFlNVVIrQmVwRnRHaUw4TFltZ0FBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiODliMTkwMjgyNTZiNDAyNTg4NzIyNTUzNThkOTUwZTQiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTExLTA4In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMi0xMS0wOCJ9LHsiYWFndWlkIjoiNGU3NjhmMmMtNWZhYi00OGIzLWIzMDAtMjIwZWI0ODc3NTJiIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI0ZTc2OGYyYy01ZmFiLTQ4YjMtYjMwMC0yMjBlYjQ4Nzc1MmIiLCJkZXNjcmlwdGlvbiI6IkhpZGVleiBLZXkgNCBGSURPMiBTREsiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJ1ay1VQSI6IkZJRE8yIEtleSBTREsgLSDQstGW0LQgSGlkZWV6In0sImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1pEQ0NBZ3VnQXdJQkFnSVVJeWxiU0VBRTE1elNFdndGMHI4R3dVZC81b0V3Q2dZSUtvWkl6ajBFQXdJd2dZY3hGekFWQmdOVkJBTU1Ea2hwWkdWbGVpQlNiMjkwSUVOQk1SOHdIUVlKS29aSWh2Y05BUWtCRmhCc1pXZGhiRUJvYVdSbFpYb3VZMjl0TVJvd0dBWURWUVFLREJGSWFXUmxaWG9nUjNKdmRYQWdTVzVqTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFTE1Ba0dBMVVFQmhNQ1ZWTXdIaGNOTWpFd09ERTJNVGN5TXpFNFdoY05ORGt3TVRBeE1UY3lNekU0V2pDQmh6RVhNQlVHQTFVRUF3d09TR2xrWldWNklGSnZiM1FnUTBFeEh6QWRCZ2txaGtpRzl3MEJDUUVXRUd4bFoyRnNRR2hwWkdWbGVpNWpiMjB4R2pBWUJnTlZCQW9NRVVocFpHVmxlaUJIY205MWNDQkpibU11TVNJd0lBWURWUVFMREJsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVFzd0NRWURWUVFHRXdKVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBcWxtQU1BejRoNUl3ZlZad1NiNGpBaTVvdDg1RkUwYnV1Q0tzNG1mdWQyMXFzbzVycHVLSDQzc0txYnJORlFTdHg1UlNDOWJtQnFkUzJseWNsMzVsYWpVekJSTUIwR0ExVWREZ1FXQkJSV0lpUlZXYXlaQm5INUJsVG5RRGlHeVE2T0xUQWZCZ05WSFNNRUdEQVdnQlJXSWlSVldheVpCbkg1QmxUblFEaUd5UTZPTFRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUVaWGg3NlhGaEx4SklUOEZzSW9RSFR3ZkhDRThzVXNLeVByY0x2LzN0b01BaUIrcGpZOWJJNm5LVDZxRnVxZ1JuK2JYQkFkTWVnLzJ2WDh3RzRhQnRvTUFBPT0iLCJNSUlDTWpDQ0FkbWdBd0lCQWdJQkFqQUtCZ2dxaGtqT1BRUURBakNCaHpFWE1CVUdBMVVFQXd3T1NHbGtaV1Y2SUZKdmIzUWdRMEV4SHpBZEJna3Foa2lHOXcwQkNRRVdFR3hsWjJGc1FHaHBaR1ZsZWk1amIyMHhHakFZQmdOVkJBb01FVWhwWkdWbGVpQkhjbTkxY0NCSmJtTXVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUXN3Q1FZRFZRUUdFd0pWVXpBZUZ3MHlNVEE0TVRZeE56STBNRFZhRncwME9UQXhNREV4TnpJME1EVmFNSUdNTVJ3d0dnWURWUVFEREJOSWFXUmxaWG9nUmtsRVR5QlNiMjkwSUVOQk1SOHdIUVlKS29aSWh2Y05BUWtCRmhCc1pXZGhiRUJvYVdSbFpYb3VZMjl0TVJvd0dBWURWUVFLREJGSWFXUmxaWG9nUjNKdmRYQWdTVzVqTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFTE1Ba0dBMVVFQmhNQ1ZWTXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUzBBY1QvaFJGVWJsRmNJcDZiaDRQMlpTcTFhamlVYWdoZWM5dWRTRkdJb1VaNDBZM0lFUGx0azJUeGJ3TS9ScFdtQ0ZyWnNBZGZ5eDIxcnZZZHBMOFJveTh3TFRBTUJnTlZIUk1FQlRBREFRSC9NQjBHQTFVZERnUVdCQlRsWjhEdjNxQUtlS2MxQzJPaU52SHpHcWcxSlRBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBSHB0c3grNkdxdjZuYmErYlQ5Zlc3bjh4c2ZIOFJoSUs4VllGUEtFc0JaQUlnUWhPU0R4a0RrY3k5bmJQVDR4MEVtREQ5VXNMNTAxdGtTc2NmV2EwYUxidz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSUFBQUFDQUNBWUFBQUcwT1ZGZEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFBeVJwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVNeTFqTURFeElEWTJMakUwTlRZMk1Td2dNakF4TWk4d01pOHdOaTB4TkRvMU5qb3lOeUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSU1pXWTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpWSmxaaU1pSUhodGNEcERjbVZoZEc5eVZHOXZiRDBpUVdSdlltVWdVR2h2ZEc5emFHOXdJRU5UTmlBb1RXRmphVzUwYjNOb0tTSWdlRzF3VFUwNlNXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3hNakZET1VJMk9UVkJNREV4TVVVMVFrUkJSRVF3UWtKRk1VWkZSamhHUkNJZ2VHMXdUVTA2Ukc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRveE1qRkRPVUkyUVRWQk1ERXhNVVUxUWtSQlJFUXdRa0pGTVVaRlJqaEdSQ0krSUR4NGJYQk5UVHBFWlhKcGRtVmtSbkp2YlNCemRGSmxaanBwYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pFeU1VTTVRalkzTlVFd01URXhSVFZDUkVGRVJEQkNRa1V4UmtWR09FWkVJaUJ6ZEZKbFpqcGtiMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakV5TVVNNVFqWTROVUV3TVRFeFJUVkNSRUZFUkRCQ1FrVXhSa1ZHT0VaRUlpOCtJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCt2cjVYSWdBQUUvOUpSRUZVZU5waUREbDZnUUVQNEFMaUJDQ2Voa3NCRXc3eC8xQ3NEZFc4RDBrTUJiQmcwUWdDQWtEOEVVbmNDVW8vUmxMRGlHNEFpZ1FPSUl1azlpOFFNNk83QUo5bWRIWC9rY1BnUHdtYVVReGhJdEZtZEhBRlpBQTNFSjhoRUJ2L2NjanJnQXlJQjJKak1sMEFEb05wREJRQUZpSUNpcUFMWUdBZGlaYi9SM1lCSTU2QXd1dEM5THh3Z0FUYlBkSERBT1lLSlNDK2gwZHpBQkM3QVBGZWJJSElpSll2Q0FZc1FBQXhFaWdQd29INEN4QnZKU1VhL3hOd0VTTytBZ1U1U3pPaWFjTHFQU1kwelZZRUVnK0dJU3hrWkdkR3BBd0dUd2ZwWkpRRmNCZjhKN004QU9uNXgwUWd0Y0d3RTdGSkdSZllTMnE5QUFMOUJMTDFUUFJDRlIwVVlVa1B5Q0FOaUU4d1VWQ2dnb0Fsc2hmcVNDMU1rTDBBY2tVak9XbUJDVnR0UTRUdGpMaGlBU1N4QnkwTklHTXQ5REFEQ0NCQzVRRTYrQXpFUEdoaTM2RHRDR1N3SElpamlLMVhHSWhNemYraGxqT2lZVzQwZmljUVI2THBTeWEzZ1lNYzVveEVKcmtLTE9ybjRLcWltZkJZRERPQWlZRXlnTzV3a1BtcXVBcFVFQkNsTUhNUjQ1QmJRTHdkdVVCK0RjVG5nZGlJZ2ZZQXVWWmdoWVdBQ0JCM2s5RzBRTWFUeVhETUw1QURRcUdjWmVRVVJVZ2doNXptRFJNMEh3OFlZRUpyZEZTUkVJL21CRkk3U1lYNVFpamRTb0xqVDVGWVBzQ0FDYllxT1lGQS9GSVRuSWJTNXRocW8xUWFPd0s1a0R1RnJTU2NRMlFMbDFRZ0J6V3ZIejI2V0FnVUZ0SkEvQVNML0Ixb3RqMEc3ZE5LUWh2OG9LaGtKYUk0SnJxVDlCUk5JeWpFL2dDeENwNG16Rm0waElZWEFBUVFxZTBCbEFZVjFLTHZRTHdmaU8vU29wdUlESHlBZURNSjVjdC9ZaFVTQWllZ2htM0dFYS9ZNHZjZlVoT01vaEQ0anlWTnlCRGI5d0dDcTRRNjNMaENvQUdMNVl4NExDZVU0ditUNG9BbFFGeFBaaG1QN3BBTGhCeUI3Z0F6SUk0bVl3UUpGekRFMGVyQzZZQ1RWTFNjQVVmM0YyOG5tOXFXNHhxZ21Jb3ZEZERDY25TenM5QWQ4SjhPbHFNN29oNWJkVXd2d0FmTjZtQUhhQTlBVS9BemNrbDRnSUxVVFduYVlXS0M5Z2tvdFp6Y0Jrd2ZPZjIrNTFTSWdqSllEWXZzQUM0aU5VdmdrZk1pMG93bW1KM0lEcGhIcE9ZbGVPUzJFV2tHTzZ4MlJYWkFPSkdhWTZtWUcrWXpRZHR3bEJTckROREdLVG01WUJvTHRGMzNud3FPSUJic3cxY2JmcUZESWVTSXp3SGNkQ3dONVpBZGdCeWNMVFMwRkRtcUg2T0h3Q2NvWFUybnlnZ2pDdml4TlJobzVQdlB1TklBUm9PQnhpMGp2QzJpRHpUcWxoUFZMMkNFUmtrWmhSWXpBL0ZHZk9VR0M0R2dBcm04RTR2Y0dpRGV4QUFaY0FSMXgwMmhSYms1am9LSGtkeXVHYTdCaWhBb3ByaTBaQ0loNFlCd0R4RnFyVW5wVFFFRUVDWGpBOFFDRFNBdWhQYTRTQ2xwUVpQam9OSFhSYlIwSEJPVnpkdk9nRG1FZkowQk1zV0Y3dmtTcEpqaUJlS1hhUEtnU25vaEEvYVpINlBCRWdBRmFBN3p3S0h1STlTVHlPTXB2V2lOQUFrMCtWbDQ3RDJMWk9jdmVnZUFIcExsL1RqVXZFUHpqQUFaTFoxME5ETlc0RkRIaXVTZUI3UU1nTVZRU3k0UzRXQmhHbVRYU0NUekZYQ29rV2ZBdjNpR3JBQ29neG9ZZzYxRlRXU1NwVFo0aUdTdkg1N2FuMkJBa0RwRUNRTzhkR3E4RXdNMk0rQ2ZYUGdQVGIxeHBLU0FZaHlHd1VKOXNIZ2VsL3V3ZFdUL0U1c0Nkak5BVmlxaEI5Ui9ocUVEY0tXSS80UmE0K3ZSUEcvQlFQNUNzOEdhSW5DT0VBY3lRTmFwZ2NCTXFNYVRETU1EWUZzNmdSRUE2NUFVWnpBTVR3RHkyMndvdXhzNUFKQzc0RXAwY0lnbnRMR0UzSXBjUWFkQVNFVnFpc01EQUhrSWdKYkRBVERQZ3NZd0JkSGt3cEhrOTlBcE1EeEFBV0NKcFFxa05nZ2pzU0IxcGxIQnE0L2VJV05pSUdGdW5RS3drdHdZb3JJNzBNY1RORUVCOEIyTHdzQkJVbWpkb3JKNUx0aGFndnV3S0Z4Rm80WUpxV01MOTZqb0JsTXNZbnVZY0ZnQ2FpRnkwaUFRRHBDZzFvdks5aC9GSXRhTmJkMFdETHlsUVpKMlJPdmp1MEY3YzBvTTVDMUNJNlh3dzdhWTZRcjZ5amxrQUVvQndUVE80N3VodmJuN05MYm5BbzdJUUdrSll1c1lyUmtHcmI5WFdNUXV3N0lqY2dDQXRseFprVEFtTUJRQXFITW5pa1ZjRDFkdjhEZ0Q5dG1Gb1JnSVU1RTZkemhySkd3RElxZHdGRVJES1JEbVltblNiOExtTDBKelU5ZEFyU1Y4QXdxREVPd0NZbGRpMnlHRUJrVzFjQXdvTUExU3p6OUc4M3dkb1FnamRXNE91Y0RVSFdTZUIwV01ESnJIbXdscFlpSFJFbGdnZ1BydWw3RElmNFBtdFEwTWtLMEIxQnc4QlEzUCtVSUxOaTFxTmJtcE1UazZnNEgwZllYVUJLQjFUMlJQajFFakwyZWdOV05yYU9oWlVJdFJHTTAraXVZR1dXamd5RllHN0p0UldLQnRmMmRvUTBRQnFjUEZEQzNBYmtIYklxQ1MvRFk5a2c5QUFQS3VMU1NMSUFvZk5hUkFKQklTSTdzUVdrU1FKVVpKbWQzd0pheGVJb2dzRUl3dWhEMEkwb05HMFVObFJROVpVWUVRQlJLSWtSSGR5Q0x5SVNxUUlnc2lxTWdLb1ljU3BGRHI5Si9oMzZZenU3UDd6Nnk3ZngvOG9MT3pPM08rbmN1Wk0yZk9odUVmSUtPWWZnVzBRRUhoUHhFQldKbWhNQ3N6TG9ReWFtbU1LUE54RHc2ZWwzNy9qaGkyQ1ZnWkEyVGdHMjJIcElIenZJdndxbE5zT1VUYUczckdkK28ra1NaZ01WVVd6L2hzOU1pTDUwRFFYVTZjaG0zd3lJLzVidEx6TzZOR3dIeXFXSTlHWHJHVGl3ckxOMGQ2QzZXdjBIakdPaXJ2WGhRSUdGRVlHMlEwZy90ZXZrQTM1U3NrYmRNTmxVUkUzVmdRc0VkelliU044aHp3K2Z3UE5FRG5hS3hDejZheVVnMHlDK0NVbGUrUlp6ZVk4WGdkcEplRVUrWkhqYlVBdXVTOXN0a0NSajJFdjBodjNMUzdiejg5MTJ1anBBOW96ODhHQVc3TjdBZFZzTWF5VG5HVHlubmtrdWNvclUrTUV1QW0vRlpJSHNRSUMrZ09PODNsT3VvUXJhYkdBTzI0UFdOZy9NZ2d2U09MdWI2REZLbGpxYlNBVVJkVk5TcW1zWEcwZU9MUTRtVzRjU1BnaWlMOUtTVGM1S0tFS2xESHQra05Ra0FKOFA3dzZQMWZDdEhFZmxCSHRCbnlTOEF6SmcxRDVxeUhhQVBydUZaaE5kcXVTOEJGSnEwTE5PTUZSUURYcVV2SU9LTkxnT3dUL0FBU3hzZzRBUWRGYm51OXc0c0EyVm5pM2UvZmNvZ25iakNLMlFZdkF1VGw2SFNJTjdBN04wcHBiU29DamtSSXlURUpQSFoyV3RKY1dRSWEwbEI0Z1oyMGpoQllJeE9RNjdpWUJla0pYRWtLVS9zNW1RQnhPaEZQZll4QStxSllIdHNFQWNJNXVneitIOHprWm9FRklSWGVBWDg3U21PTXZaVWh0Z0N4V3Z4RFFHNklyTGVSd1BKOGpQRTg3b0o5TDVSbGpyODNpYVZrVlVqQ282Tml1YWI5d2RZczVIUU1MeFF0SUl5bVY2MHB2SmNkSWxYSURtRFptVXkvTDdaUThOVUE5NnkyVUk5NTB2OXpNaUVabmwyZ3duQ2hRZTJGclNHMHpHbEl3RVNQOVlBSkJTUUlpa0lnWUVJbW8vaXNNbHhJSGtRRFhGeThEQkd4MFlsOHd3VUg5Y0FZTmx3UHpxYng1MXNJQTVhWmZ4cndQdE9Ic2JsNFVmMUl3QXZtd2d6RGhmY0V1TWYwNlRYT3NOT0hCSEFmc3FnMVhIaTV6L3dIUXhvWEJwQ0EyOHlGT2d1RjZlNUVvODdRWkxqc1F0VUZKSUE3SHp6WkFnSEQ4Ry9RVHhub1BtZkQ5TjdJcE4zeGVpdEl3aGNMbFJHYUo1NFR3ckNPUTRwV2FCTGNlSExLdVJ6bUJzSVd5NVZDOTdkcklRaXZRcWVUQUs2SmJJSDBRTDNiUlVGQWwrSjZmaG9RY01KdG5aRXBOVWtaMTJNdWZJNGlmUmRIQUxlcFdCcHpBcmhRbzBOY0YwQzhWRHprZUl3SldPWmxGUEhhR2tQc2phbndaeFhwdlc0RWRDdHVhbzRoQVp3Mk8xYzFDemd4aFVuYm53WnYveFBYelRrQytoWEt5YUdZdi8wQ056MUFCdWVidnk4bXduUE9YWnU5RkNFTzJVeGFld3dJa0oyN01QemY1U0FFL0lUa2g1RUVOa1pjZU02NXEwUkhGVllCNHdmSW42VjZIVkhoeHpQQ0dnbHJpOUdGblo1alJaYnNCYW5pcTEvaGRRbEExRWpMNDg4UkUzNGh0UUJmd3ZzaEFJRXVOT3NjLytNV2R6V003VW55SW1xaFR4empscStOVmIrVmR3WWh3QzF1dE4raHFVdnM4K01nMU9RMThBVEFKTEpQSU9rL0hPWGhlQ1M4V3k0b1ppNVhCRDA0aVNROGhJVGZ2anppNGs5MlhNYnpnV2g5Zms3YTJIdEhOOEtkcVR4U1ZHWkJ3a3lHei9Eam9vZHhRZ0x0YjZSeWNuUXBKRDdQTWFpUkYvTlZnUG1OMTVQZ1lmRXgzUVdBZWJQWUdoYUYzUGU3cU56NlZCOWthZ0I3VEJYQ3B2ak9vdURpTTZmR2ZKZE5qK0FEMUhleGtwV2dqa0t0Qy9HQkFmSHA0Y09tR2JWNWV2eStOQnZNcGtYV0VwcStwa0p5QnhpNzBsc2lESS9FM2dMenU4TXNmZ25RM3JtR1dsRkZjWHg1NkZKa0pJU2FtTVpOTDVtaWZiQ0lvdWdxOXBLRXlwSXdBODJ1bE4wTU5Bc3EreEpob1dDWjVhT1hWcGJhQTdPWGtkNk1vcUw4RUpSbUQ1TWtQNVFhMkFQTE1zemZQV3QzaHRPWm1UMlBNMmZtM1AySGc5ZHpadmJNM212TjdMM1dYdXUvR3NFZlVHK1F6a01DWlp0K0JxdVBvNjkrVHRCRlU0dFVZaU5LT3IzK29TOTFOSG12K2hDZzhmNU9QenNzWC9xRndURUZ2R2RZTjRoMW5xQlBWRm9SL2N6VUpscW9MY0o1S0VhWHJnazNTMEpLazZ4Unl2bjl0YW94dnQreitEMm9nejBqZ2ZBUFNYbHZxTDh1c3Bmb2QzSEEyaFVIM0p2YWhybFAzaUR6eGE1aXAxTUFCUXVIVHoyRHlMdzRWNUtIbVdFcVRwUUs4UkJUQUh0ais5U0pjSnQrWjM2bmxNV1hDYS9KaXZBdU5YcE1mOTZUbklYak4xb0JtSk5mOWd6UWxoUUc2Qzk5dWsvMUNCVGk2UFVSMmxpckZxazVuNy9Ub0JsdXIxSndlRno3OURRRllEWDhoVlJ5SkpLUzF2S3FuU1hsTkNlRWRhdyszVCtrZU0rOERhNzFLQVJQOTZQeS8valNxTURMZUVESFlxc0UweUVVV2dGd1VyMnVIWVhoWTJTQ3R0aTBtKzRSeHNrcWpDelR2UGFyMHJWNEZHSlp3amJQVm92amlMNXRlaldEQWx5dkhUb2t0VU5QYklDTDkxNjFXSHFwU2JjeVoyc1hGT0lXajFLeS8vNStndlltU2FXUS9WVkZWQURENnZSY3pQTnhUb3pTd2VUdGNYOVdqcEdVc0VQbmU2TVFTUUpMVEdyaG9pSW9nQ2xFRnlmR2VxUGE0UXdZVWJUYm1zamZjcDlIR2VKV0xwcXRZN3M2andxd1RQd0w4UVVCMStkZ3FkU1IrRVdhSHl1a2RxMU5XMHpSc1Y2WUJ3V1lxamR6YzR6ekdBQjg1WHVrNThKVW15VmY0TnNZNXpMMjF6UkNBU0EySmFCNlZZUnpXT0VPMGc0L0t3NWU0UEE2WGNmbXFZam5FZ20zWFdLNjllTW9BRjR6Q09ST3N6eStTMjMwVmlrejZEb0VvME1WSVVxbTRBaTFscWJYV3dGSWVWeHNlZXdHN2NoRjB0eFVMUFhDTW9sZVk0dTN4Nlo2S0FCUEw1c3c1MW9jYStpaXIzUXlUQVVieFk1QzE0QUhqdktkL2RKU2dIYWRvOEtxemIwamRuVFpEdkZnS0lSdHdvRW9YNHFML0t5a0NuQzVoSmNFL0Z5VjQxSW5vMHhnQXVKc1BJU0VZbzZOcXdCanhEOS9GUHdxNVkwZHFnbjg2ZVNTT1Y1VlJlZ01PUTVPME5GUkZZQ2svYUJ5RGN6dmJHTis0K1RRY0N4VlJYZ2c0QmgyR3R0c0ZZQWRydGQ4R2pJRnl6YTRjYzhkN2xiWnJQV1I4eHUyQ29BcFVSMXE5WlpZVnFwemFEZ21xNnkyVm4wL1RHcFFzVlVyQUFzTEwwa0dRUlVEZERIb1VDeVFyWEdLbE9NbkRDQU12VGhJQWFybkVTSmhmbkpqV1ZoUWc2aDZWM1crOXo5ZS8zR0h2aWE4WUZ1V09QcmZtMmhRV09QZ09oMnE5akliS2poT2RxbkNIMjZpdmhKTVc4MlhTdVFSWVhpdlZDdEFMWE9Dc0drQ0lqOHA4Q0JBanZ1NENqd0tpRnRrbC9PakF2ZWRvSnBhOU5DZFJnSE1GRUM2a2w5U2F4SHJTSkRrWWFKdnUySUkzd3plaDFJSjV5NGl0Lzc1UHQrUFZWUC9Qd1VJOHVKZFVMQk84N1NUdnBWbS9IMjdUZzBMQ3pZVzQwTDYxSzBBSkNvRytZejU3YmlDZEJqVFowWWQyNThyNGE3eHZLQ2Z6dmRCVmtKL0ZJQkV5dUVCQnc0TWFTZ3ZXSmZSZmJaTDlLQ05Sb0NkMjZDNmQ4aDhtQ2xaMmpla3NmRTU3eXl2K3l4WmpLYkZYRmRraVRBYWZPUStvS1NXUU5nQ1owTE9PenNxNCt1VmFwak1lVU9ZODY0N01MV2t3Zy9iRmo1VDhzMGYrbk1EcnZsM2pzY0RxdEN3VWlqZCtZa0lIaEtFQXhhTlhwM2pEclBSa1dWME1idWdtM0k4SGpiVElSRmVCMUVBL1AwMnhEYVRjdHhoc29abVpuaTlqaHlQUll2bHcwcVUxMjRVZ0lpZXp5eE9hTXY1V29DM3dHVVpYSWRTR0Iva2VCeW1pQTg3YkJYWUkraXVIOEtyb011eThadHl2dkF4Y1hQdjFxSHQ5ZHIyeHprZmcwN0w0d2cyUFZ6eUROdytpNU1tU1BwVnR1cUJjU3FzaDFOb3krVDFUU3hBdnlkWitrS1k4amVMWi9YUGJ0OWF5NHZjSThYQmJLbms0ZUVYaDVGamQ4aThTTzdlT1pKT1ptL1dzQzA4OUlKYUFlS2xpY01qdU1PeUFRcHhyaE9IUEFFNjN3VVd4NUdrZ3hQcmU2bXkvMkh1ZU16eVlyeGFqM2Rqbmh1MEh2MDhhSG5zQWlQOGFnVUFzRnJaVk0waVRPeHBOKzY1d1dxeFMvSmhpcHZuL2FMNnBOL0V2b0lncEVtejNOZzNISXZGZjkrL2x2L2lueUFGTVBhMGJaV1VSNlIya1JHSGJIQ0RsTE8xYlRDdmxubGNDamg0VFFUYmU1aVRSZVlZRTJFYVh1SDNVQWZORzllcGNHMEFFK2RBSjVQTVFMRHVGc3RqSVpueVpYQUpXempnV3JVcG85aGJsYUNQazAzZFFaQ3ViWDF1K0FZRDl3VnNWbzU0LzU2d3RBellKVHZSeWFpdTVwNnQ4QitTMmdYVUl5c0FnUGJOeHNkTUdEbWV0cE9jckZMSEdXckcyWlFHbW5iME04ZW0wU2dVTWVTVkVXUVFScXNPMXg4WktZT2N6RklES2ZnMlhscG85dUFiZnNhMjRhZ2NRVkNaRVNFY3h2SUZZVE54QmlPYzdCS0RzSHlic2k0cjlPR0xSSklkbHladXFtcGxHSDNyZGpWWEhPSUJIb2F3MkFPY2QwTWxKZ05wRXFKSUFra0lLTDBqNURqTWxjbE9scEZCN0VWWWpZT1p1dWplRmZjaWFWREZVbFdUYmRPZ2pTUzJIKzkwTXJVR01RakxBMzVmcEdPK1BPbUYwaVNMdmxWdmFxblA3OVI4VytKa0c0b25wVXlQSHlUNDI5TzZXRDNvNGp2MUp1ZjRLTWw2SjJOZlFMMXpvODkwa0tyZ0RiS29HMGp1NFVZSnpxVFpvd3ZHYmZyaDc2K2x6RVRXRE1Bdk1seXRJajRqOWQrQklRdm9TOVNrcmh1eUxoeEpqWnhWa3F3Y0NwbS9PNlZjcjIrbkxvQjJxL216UitwUE9ZK3pDNHA3NkZmZ1N5WmFlb2orUFVSTjRMaWc0QldVK3k5bEpaQkdWZzVGR2VERDdlbVJSYnpseUdoK3NSRVhiMlRaT0p4SnZmVnR3SGJ5MnoxSTZORHd0V3JmK3pSSytJMVdBQy9ZUkJvdmxVaGM1c3ZuUlNOWEN3NmNaU3QxTFdUNmQ0VUVSeWYzT0FXb3hsYzZGNVk4ZzNhaGxOMmRlM01zN0wwNnJaM251VytjWmROMXZaSTdORVAxY0xhaGlZbURFR0cwcnJENzExSEFXQ2t3a2NCQkJJSFVqMFVldkY1SGpqVERXOVloTHY0Rk1GYkI3by8vSklVQUFBQUFTVVZPUks1Q1lJSSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiNGU3NjhmMmM1ZmFiNDhiM2IzMDAyMjBlYjQ4Nzc1MmIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJmaXJtd2FyZVZlcnNpb24iOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wNC0wOSIsInVybCI6Ind3dy5oaWRlZXouY29tIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJGSURPMiIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwNDA5MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wNC0wOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjItMDgtMDIifSx7ImFhZ3VpZCI6IjQ3YWIyZmI0LTY2YWMtNDE4NC05YWUxLTg2YmU4MTQwMTJkNSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNDdhYjJmYjQtNjZhYy00MTg0LTlhZTEtODZiZTgxNDAxMmQ1IiwiZGVzY3JpcHRpb24iOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyAtIEVudGVycHJpc2UgRWRpdGlvbiIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzMsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDM4NHIxX2VjZHNhX3NoYTM4NF9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI0N2FiMmZiNDY2YWM0MTg0OWFlMTg2YmU4MTQwMTJkNSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDk2LCJtaW5QSU5MZW5ndGgiOjYsImZpcm13YXJlVmVyc2lvbiI6MzI5NDczLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6MTAwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTA1LTAxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wNS0wMSJ9LHsiYWFndWlkIjoiOTMxMzI3ZGQtYzg5Yi00MDZjLWE4MWUtZWQ3MDU4ZWYzNmM2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI5MzEzMjdkZC1jODliLTQwNmMtYTgxZS1lZDcwNThlZjM2YzYiLCJkZXNjcmlwdGlvbiI6IlN3aXNzYml0IGlTaGllbGQgS2V5IEZJRE8yIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsiZGUtREUiOiJTd2lzc2JpdCBpU2hpZWxkIEtleSBGSURPMiJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ2lUQ0NBZzZnQXdJQkFnSVVPa21VMzVJaWNYb1ZQamZ2d3BHN01ONnRIUFV3Q2dZSUtvWkl6ajBFQXdNd1F6RUxNQWtHQTFVRUJoTUNSRVV4RkRBU0JnTlZCQW9NQzFOM2FYTnpZbWwwSUVGSE1SNHdIQVlEVlFRRERCVlRkMmx6YzJKcGRDQkdTVVJQSUZKdmIzUWdRMEV3SUJjTk1qRXhNREEzTURrek1EUXlXaGdQTWpBMU1URXdNRGN3T1RNd05ESmFNRU14Q3pBSkJnTlZCQVlUQWtSRk1SUXdFZ1lEVlFRS0RBdFRkMmx6YzJKcGRDQkJSekVlTUJ3R0ExVUVBd3dWVTNkcGMzTmlhWFFnUmtsRVR5QlNiMjkwSUVOQk1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdGdPQzdJS3hpcE1KN2JWUFRUODNPZTkweHpIUENlYnh5Q3RnL1dyc1RyUmFTbllpZ21KQ0I4L2pxQk40T1FHMmRaNWpjTnNMNlN3SG9zWURSSmMrTzF6azlpNUdFWldmM0lyOTkyQTZkdU1zcDUxbHE0ZkFnYS9VelROOS9FYnpvNEhBTUlHOU1CMEdBMVVkRGdRV0JCVGZ4emc4R0d6WUFpZEtMNjN1aFNpcmFYSklLREIrQmdOVkhTTUVkekIxZ0JUZnh6ZzhHR3pZQWlkS0w2M3VoU2lyYVhKSUtLRkhwRVV3UXpFTE1Ba0dBMVVFQmhNQ1JFVXhGREFTQmdOVkJBb01DMU4zYVhOelltbDBJRUZITVI0d0hBWURWUVFEREJWVGQybHpjMkpwZENCR1NVUlBJRkp2YjNRZ1EwR0NGRHBKbE4rU0luRjZGVDQzNzhLUnV6RGVyUnoxTUF3R0ExVWRFd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmtBTUdZQ01RRHN2NEs2TmZKdmZ2emQwT3lnd0ovQUJpTHRndEpXaFhUZVVsbHRkcWE0V3NPTTl0dng2MzZ2NUZJdlpSa0sxWG9DTVFDZG9QUSthNGZEQkVpTnVqMFdzMzN1VVFoR3Jwc2VQREdmVlhuNGtFcGJUSUJlT2RWQXgvL1RyTUMvU1ZiK2JzZz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTkVBQUFETUNBSUFBQUJpRU5IOUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc01BQUE3REFjZHZxR1FBQUNadlNVUkJWSGhlN1owSGRCelYxWURYRFRlYXNTazJFRXd4WU1DQUFRT0duMERvRUNkQUNLWWtRQ0NoQkVpQUVFZ2doSVFFSEFpaGR4TEFYYkxhRnExNjc3MnZldTk5cC9lWjFYL2Z6RXBhMWdXRFo2V1Y5dDN6SFIwZGczWm4zL3ZtdnZ0bTU3MnhqT0hBTWJXQm5jTXgxWEVnNTFSVkhYVVROYzF0OW9LS3QrTHpINDNNdXptOGRIMUV3NmxSblN0dGd5c2M3bU5paVdPYzFERk9FalBib2FDdm9jZFgyWWRPaStxNE9MTCsxdkRTeHlOejM0N1BpeTJvcUd2dGNCTUUyT0wxNXR0aXY4NEpndERXMFpGVTVubzNyZndSVzhsMVlhVnJ0cFlmL1hYdG5HMXRsbWkzSlU2eUpJOVpVakdoQlBRNDlIdlU2Tnh0cmNkc3JUMTdlOFgxdTBzZXR4Vi9rRjZlV2w3YjJkVWxpcUxYbmdQR3ZwMWpHTWJWMUJxV1ZmS2NOZmZHOE5JendocU9EdStjdjZmUEVqbHNpU0VzTnNiaTRDeXh2STZBQ1EzMDduYXdxUGZCZ1lqaHd5SUdqZzdyT0hOMzNTMWhKWCsyNVVmbGx0VzN0SE1jNTNWby83RVA1d2lDS0sxdi9peTk5S0dvb3ZVN3lsZnNiSm9UMW9ja2k1ZVI1dkNMamJaWVNmVEdtRkFEK2gyY2krV1FDZUNEblowYjFudmN6c1pMZHBROUdsUDBaV1paWlZNclJWRmVrL1lUL3M1QmhnUGhQa2dxdkN1aWFNM3Ura1hoUFhPaVJpeFdHZ2tPMkpseDRiQnpvUWxwc1ZMSUFUREJVTUpLelkwYVdSTGVzemFzN3Q0OUJaK2xGVlUwdEJ3NDIzM0RPWjduYTV2YlBrc3Z1V3RQNFNrN1hmUEMreTF4ZW02elEwYWw5bnA3VE1nRFZvQjI4UkpJc2lDODc3UWQxZmRGRm55VldkYlkxZ0h6QWE5VmU4V2tjekR2YU92b2hCcnVvYWpDTThQckYwVDJJNWRoSUljWGhaZkdneWxtYjlCUUM5cEJjUzlBOGx1d3AvZWM4TnJIWWdxaWM4czZ1N28xVGZPNjljMllkTTVOa01sbHJ1ZGljaS9jVnJvb3ZCdkpDelVqSkZKc0crYkFnQ0hnaVZPd3hJbEx3am8zYkM5NTBaYWJVVkczdjhKdTBqbFhTL3Q3YWVVM2haVXUzOTVnaVJ6U3B3c3NydHN3QndlSk1oUTRzMmZnMkcxMW04SkxQc21vYUdqcjJPZlZrMG5uN1BubGoxcUx6OWhWTnkrOEQya0xOUno4OUg5cERHWS93TVFDVFNuSStXRzlaKytxL1oyOUpLR29jbkI0Mkt1WFQwdzY5MVpjM3ZWaEpjdkNPOUJmR2pVY1RuS1lnd2ZWZHJwMk5tYjU3cmFiZHhlOW41QlgwOUx1MWNzbkpwMTdOQ0wzekczbGgwWDBvMG9PQ2J2WGkySXdCd2FjQVhQaXhJWGh2V3UvTHYxZGRGNUtkWk5YTDUrWWRPN204TktqdjY3MVZuSXdZL1Y3T1F6bVlIQXc0TnljaUtGanZxcTVMYklzdkxMRHE1ZFBURHEzUHFKKy9zNE8vYy8wYnhwOFh3aURPVWpzK3ZBYTQxNndvLzN5NkliUHF3ZThldm5FcEhPblJuZWlMKzl0RTk4MDdQVnlHTXkzWXRPck9oZ25vMGJQdG5XOTYzSjc5ZktKU2VkVzJnYjE2eU9jZnJrRk80ZjVYaGp5eEhJV3A3ZzZkdWpOT3NhcmwwOU1PcmZDNGJZa2U5QlZGcjlYd1dDK0swNEJYRnJsZEcrcDU3MTYrY1NrYzhmRWt1Z2VLZXdjNXRCeGl1RFNDWEhFNncwSHZDWjhqSk5Dem9HaGZuK1B3WHhYRE9maXFkZSt6VGs5ejJIbk1JZU9OOCtScnpYczQrNFM3QndtQUdEbk1GTU5kZzR6MVdEbkxORWhqMStEQkpyUWRjNW83cWg5RVJsS3dPZWRZdTFtdVhPR1dQdkVWeksvL3hSTnpKa2docGc3ZTRGUFozeE0vM1lMS0xQV09jTWVReWwwUXJzbm1WQXRDclg3QWl1eHlFWXN0Uk5IT29obERuSjVMSFdza3pyZVNhMk1vMWJGVXlmR1V5ZU5jM0xDN09HVUJQTGtCSEpWSEhWTUxMbkVSczZieXB2VFpwVno0MWxxVWpqOUZ6aVA1MXFSV3d0MXQ0NktKVmM0U2ZCcGRRSjFaaks5THBXK0tKMitQSU8rS291K05wdTVJWWU5SlkvZGxNL2VWc0QrcklDOXM1RDllU0Y3bDg3bW9sbkMzVVhzZmNYbzU2WTg5cklNR2hSY2JDZTlqZWJYcElGZzlqaG5wQzVJWXhHUXpORHZNSEFzc3BGd0hwOFVUNTZaVEsxUG82L01vbS9JWlVDbWU0cTVoOHY0SnlyNTUycUV2OVFLcjlZTGJ6UUs3elFMSDdTSUg3ZEtuN1ZKLzJ1WHZ1NlF0blZLMjd1a0hWM1NUcDFkczRYZDNWSmtqeFRXTGNIbmZhS1MyNWpKTEl2Vm5ZTUc5R3ZWUURBYm5ETk8wUEdzTmkrR1dHS0hURWFkbGtpdlQyT3V6VUdKNnBGeTlvVWEvdlVHNGNOV0VXU0s2SkdkQTBycWtKSTdxcFlRYWlXbDFkSmFFNk8xc0ZvN3AzVndXaGVuOWZCYXI2RDE2ZlRQTGdaRnpTMTdoaVJQbVZ2OXVGVzh2WUE3UG82eVJPbUZoMS9iQm9JWjdOeUVhbnFKQnBYWmtYYnk1SGpxZ2xUNjJoeG1jeEgzWkNYL1NwM3dmb3U0clZPMDkwc1pRMHF4VzZtbDFWWVd5VFFpZVNqRnc2dGpzbWRzM3lzdFF5QUdCYytlYnZtWEpkeUo0SnhSN1BvMWNpQ1kyYzdwdVEwUzJ4RU9jblVpRFdNRUZDdC9yQmJlYlJIRHUyVklZMldFMnNScVBXQ1k3S0VWRDZkNlJNMGphMk9xWjh6ai9XUWhIWkRDdzd1a1gyRG52aDF2ZWtPNURRcVJ0Y2tVVkdtUGxNUFFLVzd2bE5LR2xHcEtoWkdSVnNBdHJOYUJvcFBUZG5aSzl4WnpNSUhGemgwUVBiMHR0S0haL3RWWnpPUGxIQXlnem42bGlsUzdlWTJRWWNUMFFDYkQ4YTBCbGVzTzdOeUI4QTZtYmhoTVZ6ako5ZWswVFBpM05BaldYcm1HVXFFK3cwbnR1d1oyN3R2UW5WdGdJMDZNSjYvUFlaNTM4V0hkY2dXaDlnc29zWGtQRk1kM0NlemMvakV5WEJTeHhJYXV0TjFSd0w3UktLUU15WjI4cG1EWkRpR3djL3RIZDI2cGpUdzNoWDZ3bFB1c1ZTeDJxNk9TQnd0M2lJR2QyeGRnbXc1a3VIV3A5TU5sM0xZT3lVV3AzTUZ1dzQzalFJR2QyeGQ2aGx0c0o4NUpvVUM0N1oxU0E2M2k2czJzd001OWsvRU1kNWlWV0pOTTNWL0tiZFdGazdCdzVnVjI3cHZvazRiNVZ1TGtCT3BuaGV3bmJXSXR6bkJtQjNidW0rak9IUnRIM3BqTHZOa2t3S1NCdzhLWkhkaTVjWXhSRmNvNEczbFJPdjBuRjU4MnJNQXMxWHNvT013TDdOdzR1bkFMck1TcGlhaU1pK2lSZTRUOWJMS040OUFDT3plT1Bxb3VqeVZ2eUdYZWJoYXJLRlhHT1M0d2daMGJKNHFZWnlYT1M2WC9VTTBsRDhyREVzNXhnWW9lWHR2ZEpkMFgwczdwbGR6Y2FHSzVrOXlVei82dlhXeGpOUVYvZFIrd0dCUzFpRzRKM2JNWkg3TE9lYjlVSlM1QVNZN1BHSmJaS2Z4NkM5NUo4NkRiT1FGNFd3REdkRm56QXRsMjl0SE1hRnM3cGJ1THVKV2g2eHg4NWlnQ2p1YTJmUGF6TnFtWm1hS3JJNkxxb1dRUERPTDlndGJOby9VUXJhd0cvZEhJYVBXMFdndFFhbzFPTmFWV2taTlV6a3pneUYzNkIwa2NVTFkwQ2pmbnNjYzY5ZlVRZ0YrUEJJSmdjMjV1REhGZUNnVkpMbmt3c05kSFFHZEdHUnNRd1MyMWpGQXpoNVg0QWRuYUsrL3BsbmQzeWRzNjVhODZwQy9hcFUvYnhJOWJ4WTlheEE5YXhQZWJ4ZmVheFhkMTN0R0JLYzVNQkk0Y1BnNThpci9XQ2ZlVmNPdlQ2U01kb2JuV0VGMGljUjl1SjYvUFpxQ2JHeGdOUnJRQUJRelpVQ2xtRFN1N3U2VjNXOFNYYTRXbnE3aEh5cmtIU3ptWXhHMHU1TzRzNUc0cllEY1ZzTGZtTWJma01UZmxNamZtTWpma01OZm5NTmRsSTY3VitkSE1CQzNqelVXZjRvcE01cHdVK3ZnNDhqRGJYdDBST0lMRk9mMmEzTHdZOUUzWEF5V2N2VThlQ1V5U2c0b05Ycm1VVUhkMVNTKzVoTHVMMmF1em1YVnA5QmxKYUhVN2xEWEh4NkYxL0N1Y0ZIemtvNEZZOGlnSENXa0FPTUtPZ0xOaTFyRFVUaTYwb1M4WTUvaDFSMEFKRnVkUU1ZSFdwVjZVVHI5VWk3N3BDc1ExT1JBT0tyYjBZZVhmamVJdmlya042ZlJKOGVRUkRoSUdkRU42eE1UbU1VWk43VXZFckFNK0ZMVDgxQXlwRXdTTGMrakRFOGM1cVIvbnNSKzNTczJzK2NNcUNEY2tldElHbGIvWENUQktRbFpEKzNSQWN4dTJHYjhZdjRjT0U1L2FyenNDU2hBNUYwMmNua2ovcG95TDZaVUhSUE96bkZ2MjVJNm9yOVVMMStVd0sySkoxT0xvUlBkcGVyOUR3Z1NJb0hBTytqc1Npam55b2pUbVpaZVFNNkpRWmwrV2c1RzZobEkvYkpFMjViTW54bEZ6OVhlY3RoTTl4QWtlNXhiWlNKaFN3UnkrbGxKRkdBak5DOVV6Qm9uVDJpcy9YTWF0VHFUbXc5c1pJNHZmWVdDbWh1bDNidHlBWmJIazdRWHNyaTY1bXpmNUxoSkdRUlBWTnh2RUgyWXhpMjNlMmhIbnRta2pTSnliRTAyY0dFODlXTW81K3hYQzdLc2tmWUlXMVNQL3Vvdy9QWkhTYytxVXo5UXd2a3kvYzNxU1cyQWx6MHFtZjEvRlo0K29ncWxydWp5ZXNUcEtmYnRadkQ2SFJVK1FncmVEU3M3dkdEQlRTWkE0dDhST1hweE8vNlZXZ0VIUTFGcHVERXJEM0JIbEQ5WDhlYWswbEl6RzIva2ZBMllxbVg3bklPdEVFMGM1eUt1eW1IODFDaTdLNUpXcmJ0bmo2SmZ2MTIvWFFaczFnM0I0WUoxZWdzUzVGVTd5cGx6bS9SYWhpVEhUT1VpWlhieTJyVlBhbE1lQzFwUFhSL3lPQVRPVlRMTnpxS0pIUDFmcTl5OTkwU2EyYzJiT1dTVnRySTVXUDJnUnI4NWlGcUlaS3hZdUNBZ1M1MDZPSnpjWHNaQ1F1Z1V6bldQVk1TZ1F0elNLbDJiUWFEdDY3Rnd3RUFUT29Tc1hxeE1vS0xuQ3UrVStVNy8xSWhWUHpvanljcTF3WVJxTjNnNWZKUWtHZ3NTNTB4T3BoMHE1cUI1NTBGVG5SbVZQMnBEeXh4ciszQlFLdlIxMkxoaVlmdWNpa0FkbkpGR1BsSFBXUG5uSVZPZUdKVS9pb1B4MEZYZDI4dmpWWUw4RHdFdzlRZUxjbWlUcTBYTE9aclp6OEdweEEvS1RsZHlaMkxuZ0lYaWNlNndjM1I1c3JuTXdVanY3NVNjcXVEWFl1ZUJoMXVjNWNPNUo3RnhRRVNSekNLam5qTHMxeloxRERJdWUrQUg1ZDNoc0RTcUN4TG5UOUhsclpJL0pkd2lQU0o2VVFmUmw2MXFZdDJMbmdvUWdjVzUxQXZYTEVpNnNXKzRWekhTT2tEMVp3OHFMTHY3ODFQSHJjNzd2anBrV2dzUzVrK09welVYY3RrNnBpemZ6ZXdoRzhSUzcxWC9XQ3h2U0dmdzlSTEFRSk02aDcxc0wyQy9heFRaVGQwUVhWVTh0cmI3YkxGNlZ4YUJsdytBY3ZwRnAyZ2tDNTlEUEZVNjBoNnZwOTVXb25yRk9YdHZhTVg1ZmlYSHpIRTUxMDB1UU9IZTBmdi9jR3dHNGZ3NUt1dGcrK1VIOWNaSGU1VjdZdWVsbG1wMEQ5Tnl6MUlidUUvNXJuZm4zQ1V2YVdPR28rcUpMdUNpTldZTHZFdzRHZ3NTNUJWYnk3R1RxbVdvK1owUUJTOHlOVmxiN2I3dDBSd0Y3QXRwTmtyQkU0RlEzclV5L2M5RDkrcnF2SHlTUUQ1ZHhDUU95NlF1cTNiSW5ZMWgreWNYRDdCVXRpUURuY0ZVM2pRU0pjOER5V1BMT1FqYThSK29UVFY3Zkttc2VtRWxFOWtpUGxITm5KZE9MNFUxUnRqTjJ2aG4zejhEM3dEQUJZdnFkQTZDekk0bWxkclJSK2lkdFlpT3JTcWJ1SVF5dkpXcm9vc24vT3REZXVlY21VL0JlaHVoZTV3d216TVB5QlpUZ2NXNitsYncwZy81SGcxQk1LR3dBTm5XbEZVOGxxWDdWSVQxWnlWMmR6WnllU0IzbnBHRHVNdDg0Z0NnOTUza3hVdUNCbWZpZlRXSkMvZS9LeEhsaTROdXd3VW5RT09lR2tnNm1FVTlWOHZFRDhvanA4d2c5MnpHS3A1SFI0Z2JrdDVyRng4cjVXL1BZaTlPWTA1Qjg1SkVPWXFFTlBTTUE3ZjVuZEo1ZjE4NElab1Iyd2VNY05ObXFPT3JuaGV6WEhWS25xYXUvZkFQbUowT1NWa0dxOWo3NXd4YnBMeTdoc1FwdWN4SGF3L1dIMmN5bEdjeUZhY3c1S2RTYVpHcDFJdHA1ODhSNGFtVWNkWHdjQ1Y0ZXE3UENES0I0Qlk3UldhWnp0QU54bEE3YTAxUGYxaFB0aG1sRHUyRXVBV3pFWWh1eHlFWXN0S0puUFM2d0VwQ2g1OFhzNnlTWnlNVEJhV0ZRT0Fmb2pRWE5mV1VtODNxREFJTmc0TFpNaHhmbVZNK2c0R2xpdEJLM21qSW93L1FDeHR6M1c4UXREY0xMdGNKejFmeVRGZHl2eXpnby91NHU5dTR0L0pOODlzZDU3QzE1N00yNWlKdHkwU2JEMzVzYmM1bnJnUnptMmh6dkhyOVhaekUvekdLdXlxU3Z6S1EzWnRLWFo5SlFhVnlhVGwrU1JsK1VScTlQb3k5SW84NVBwYzVOb2RZbVUyY2xVV2NrVWFjbVVqOUlvRmJwKzlHQ3dXRHFJanV5ME92WnhIaU5uZHMzMEM1UmNQcVMwSlMvcmVEQUEwYnh2blZBQTh5RzJuRklSUHZ6MTlGb0EvWGNFVFYxU0hIMnk5RzlVbGkzdEwwTDZhaHZvQzU5MUNwOTJDcDkwQUoyU3UrMWlJZkN1L3IrNWY5cEV0OXFFdi9kS0w3WktQNnJVZHpTS01MNTlzOEc0ZFVHNGUvMXdpdDF3bDlyQmNqRUw3cUVQN21FRjJyNFAxYnp6MWJ4djYrQ1U0Si92SUwvVFRuM0VKd1lwZHpkUmR3ZGFMdHQ5cHBzWmtNNnl0TS9TRVFXTHJhUjNxMExna3ErSUhJdUdsMmxnMUhtcC9sb29Xc25yeW1CR21EM0VTQ2ZxS0g5MUVuWk15cUJoWjUrUWV2aHRTNWVhOWNmRjlIQ2FKQVhvUnhzMEtrL05PcG9oSXRDMUZCYXRVNFZwVlVTU2dXaGxCTktHYUdVRWtxSld5bDJLNFdqU3NHb2tqK3E1STBxMlNOSzVyQ1NQcVRBaVpFMEtFUHQ2MENuaHd5bkI5UWtIN1dDdGVMejFmd0RwZHlOT2N5NlZCcFNJTHE1WVVJN3YyYWZGb0xGT1FDMGkwUmx5b1owK3RVNkFWcDVhbEpkVUlYSGc5RDBuOFl2Y0RJWUQrVUJaUDNFRUFBVnlnTjBoc0JrbkZUUVNUSWdvTk9qU1gvV0JSZ1ozaTFES24yMm1yK3prSVV4K3VSNFZCUk81cnpwVFhoQjVCd0FKVWcwY1VvQzJvZ3V2RnZxTVhWTi82d1BhQ3haODRDSW9HQTNyOVZTV3NhUXNxdExnaFA0M21LWW9kTXdkMEU3eEUvTUxYeGJmaW9KT3VkZ0ptR0htUVQ5ajNvZUJwZkF6U1JDSVhqVjB5ZDRpa2JWSFowU2xJTXdBVnFUaEhhTDl5YTg2ZEl1dUp6VE0vOTg5TjByZFg4SkMyVUsxRldtZmlVUmlrSExIaWhKWWNEOW9FVjhxSlM3TUkzK3hxMkVVMjllY0Rsbk5BRjZ0Q0Y1UlFiOVdyMEFGVFJqOWxmK29SbGdYaTJ0UXNVQzA5NHJNcG5sc1JRYVp3M3pmTHRnQ2dndTV3d2lpVGxSYUlYRVBVWHMxazZwUFFEUEp3bk5nUElZR3RQZXAveTVScmdxYS93aEdWT2Y3WUxST2IwaElOVmRrRW8vVThVbkQ4aW03Mm9kc2dFVDRWN0JrelFnditRUy9pK0xXZWFZanRvdUdKM1RUenRvaTZOanlldHltUDgwaVpXa3l1SFpoRWtCN1RnZ2FISDk4bk0xL0laMCtvaUoyczZ2RndKSE1EcG5vTGZDNmdUcW5tTHVxdzZwa2Rhd2RXWUZUTXM2T2MzYWgzWnlPVGVGV21ERmVjNUFQL2tXVzhselV1akhLamlZdy9hSkhselptUld5TnRiS2FYQXkvN3lRUFNtZW1nL2FUZGtJRzd6TzZTTXNOTVRoZG5KREJ2MThqWkEwcVBTTCtNcUphY0dyYU1INWxnYngybXpHKytTTXFSbGhnOWM1QUp6VHJ4SXZpeVdoNEgyNVRrZ2RVb1lEY0d0ZHlNYXc1RWtZVUg1ZnlhOU5waGZFNk5wTlFhb0xhdWNBUGRYQmZHS0ZrN3cyaDNtMW5zOFlrb2ZNdlhVOWhFUHhqRFd6MnVkdDBvL3oyQlZPZlJ1aEtkQXUySjBEaklaQVR4UW1yODJtLzFiSEp3OHFmWUxIM0dXd0lSdXM2c2tZVnA2dDR0ZWwwZ3R0eGlNMEFyeVQwQXh3RHRDZG14dERIT3RFejl0OHlTWEFWQjltWHBMSmEvNURNZURNYldTMFQ5cWtuK2F6eDhWUnFLa2pzWFBBZUtxRFV4QUcyU3N5R0Rndnc3c2xGNlhTZ1hodWY0aUZXL0xBMFBGTUZiODJoZGEzMThET0dVQmI2T1pCdGp2S1RxNVBveDR1WlQ5ckU0dEcxU0Y4RGVYUUFvYUxPa3A3cjFtOEpwdGRZcXpDTkZyYnJ3dk1Zc1k0WjZCckJ5ZmlZaHR4WmhKMVJ5SHp6M3JCMnF1NEtBM013emNEZk0vd2pJMkludWhlK2Q1aWJtVThOYzhRRGpzM0NiU0ZmbXZuUWl0eFlqeDVSU2J6U0JuL1FZc0Vvd05Nd1FnWnp5MitUNGphV0k3K3hGR1lTU3dPOUU1Q004ODV3RGdMMFJEZ1htb256MHFpYjgxam42MFdQbTBUNC9xVmNrSnQ1N1JoRWQweGl6UGZRUWEwVXkydC9xZEp2QzRuOE5lSFo2UnpnT0VjMGc0U0hscDJlbTRLZldNdTg1c3lEa2JiclIxUzRvQlNTcWd0ckRZZ2VDakZJNmpvV2hTNnJJY3QzRTkwODlyT0x1bStZdlJWR0dyWXdNMGtacXB6RXhqbVJhR2x4VWM1eURNU3FmL0xaRFlYc2s5WDhhODFpSisyU1dIZHNyTmZUaDlDNjZaS0NhV0tWR29wdEh5cmxVUHJDNkdoZXdXdFgvQU1pSjVCMFFQWmNVUkM2d2xnS2dmRE5FRHFVRHEwdnViRkYrYjdBamtZNEZRRXI2STFOVEM2U1JwYVphUHFTMittUHVDREp3MHEwRzVuSjlQb0JpZnMzSDZaU0hoQU5GcmdEdWF0aWlQUFNxWTJaRERYNWJKM0ZIQVBsSEpQVlBEUDEvQ3YxQWxiR29TM204UVBXOFV2MnRIaVBEaXo5L1JJVUQ3Yit1VFlmam1oWDA0YWtGTUcwV0srekdFbFd5ZDNXTWtmVVlHQ1VVU2hHMUgwZlNrbTFCSkNoUnhjUnFoUUJsUVNhaFdwdWlnVmhyWUdHaVZtT0JONmVHMVExTnl5eHFxZUtic1d4Q3BqY0dEL2JCQTJaTkNCL2NwL3hqdm55NFI4ZW52TnM2SzlubGJFVWlmSFV6REpQVCtOdWpTRHZpcUx2ajZIdVRXUHVhMkF2YXVRdmE4WUdmbnJNdTdSY3ZDUysxMGw5MHdWOTF3MS8zdzEvMmNYLzZLTGY4bkZ2K3ppWDZrVi9nYlVJVjZ0bitRZjN4M29WR2pyMXh1RWZ6VUlielFLYnpZS2J6V0o3elNqaGRZZnRZcWZ0MHRmdGt2Yk82V0lIc25XRHhNakdkSXpKT1plWG9Qc0dORDhCMWtXMHYvSGJSS1VkSXZ0MkxtRFpDTG5vZDA2MEFZbzZGK2kwU1U5eUgrTGJjUVJkclFuQ05USVVQOGQ3MFRwOEtRRXRQM0M2a1RxdEVScVRSSUYyWEZ0TW5WT0NuVmVDclV1RmUzVmNFRXFkV0VxdFQ2TnVRaElSMXlzYzhuM0JiSXZjR2tHYzFrR2Mza21zekdUZ2FrMzFBTS96R1orbE1QY2tNdmNuTXY4SkorNUU4NkhFaGJPQkVqUFVOcEg5c2dsYm5WQTFBSTNLOUp2SWRaMmRjdTNGN0RMWUJwaE5HWWd0SnRWenZtaEMrZTE4Q0F4L3NSQWZ4RW9FeWV4SXVZZUdwQjlBUmk4ZklGVFlxR05XR1FubGpxSXd4MVFIaERMblNUMHlxbUoxUGtwOUhYWnpFT2wzTDhhUlNoTW14Z3RjTGRNUS8zcTZKY2ZLR0ZQakF2a1BldXoyVGxnUWlCZnNTSU5qTTJMRHBLSnZ6SVYzK1B4SGg2a1p3TjAyUE5qMEYycnkyT1JmSkFJWWVqZjBTWFYwU29YbUhRSFV4a29aS0hHT0NPSjh0N2FCUGcxNmFFenk1Mzdma3lZT2wxNC9kTVoxeEZxMDNVcDFNTmwzSzR1cVlWUkF6RzNVTFN4Z2xIbGhScjBxQ3B3M1hzQWZvMXo2R0RuZ290OXlnZmFvZDJQaVNWV1lsMEtEYk9jK0g0WmFqdlY3TnNJNGVYS1NSWG1TWmVsTTFEN1l1ZENHOE8vQ0hTbi9qVlp6TDhhQTdYYXZJWlNZVFo5dGI0TUVUc1g4b0IyZTVBRXF4T29CMHE0UGQxU3I2blA0ek9pZ1VZM21OeVlNNzdpR2xLczMyRWNPdGk1bVlSZTJ4MmxQNmRxUzZOUVRacjh6Q0NJRmtiN3RGWDhTUjV6QXZRNGRnNkRKSWhDazFtWVZ6NVp5Y0VjMC9UckpoMmM5bVc3ZEdjQmMyTGc3aG5HenMwa2pLb3VHaTBOMlZ6RTZvLzFOdm41TGQyOHRyMVR1cWVJUFRsdzMvUmo1MllZK25pMzFFN2VsTXQ4MFM2MXNLcHM2dXkxVjlEQ3V1VmZsbkNuSkl3N0I2TDdIY01oZ3AyYllZQUJrV2l6NzZzeW1iZWJ4Q3BTNVUwZFh2c0VMYUpIZnJDVWc1a0tkZzZqZzV4eno0MGhOcVRSLzZnVENrY1YydFFySnYyaUZ0VXJQMVRHbldvNEY0R2R3K2pPellraExraWxYM0lKV2NNS1llbzNFbEFnUnZmS0Q1ZHhweVZpNXpBR3VuUHc4OXdVNnJscVBuVlFIalYxYzc1SjU1TDBaZjNZT2N5RWMydVRxV2VxK0NUMGJEUlR4MVpoZkd3MW5NUDFIR2JDZzdPVHFkOVg4b245OHJEWnprWDJ5TCtDT1FTTXJkZzVETUx3SUlaWW0wSTlYY1VubXAzbllONjZwMXQrQUY4cndVd3k3aHpVYzMrbzVsUE1ydWQ2ZVcxWGwzeGZNZmNEN0J6R2krNGN6RnZQVDZQLzdCSXl6SjYzZG5IYXRrNXBjMUVnVnh4aTUyWVl1bk56WTRpTDArbFg2b1M4VWNYY1hZTGFXZTIvN2RMdGhleEsvSDByeGd0eWpwaHZKVGRtTVc4MGllV2t5ZmVwTnpQYVI2M2lyZm5NY2REanlMbTlEdURRd2M3Tk1IVG5GdG5KYTNPWmoxdkZCa2FWVEwyZnFZN1czbTRTcjh0bGx1UDc1ekFJRUE0ODBEZFlodUZ2WjVmVXcydG1LdWNacXlMVjF4dUVLN09ZeVdlQytSM0RvWU9kbTBub3pzMkpKazVPSUI4cVkrTUhaTkxVWWc3MExYR3JmM0VKRjZjeFN3TzNPeE4yYmlhaFM3RFlSbDZZQ3BOV3Z0Q3RLS1lPckpLK0k5Z3pWZnc1eWZSQ1kvc0k3RnhJbzFkeUlBRlU5NXZ5MkU5YXhXYlc1UDJVYVdVc2NWRDVUUm0vT29HYVB6Nk8reC9Hb1lPZG14a1lCa1NnZlRET1RhR2ZydUpnWURYM1VSbVFNSWRFVDFTdnZMbVlBNjNuR01MQisvb2R5YUdEblF0ZW9MOE5vTzhodyttUEdEM09TZDFSd1A2M1hXeWdOY0hVZ1ZYMWpMVnoycGNkMGkzNTdPU0Q1N0J6b1lWaG15RmNCUHBsbVFNOUQralZlaUZ2Qk4ycWFlNUtDREM0bWxMZmJoYmhMUTZ6Nlc4YUNPR0FvSE51NHN6R0dFUVQ4NktKeFZaaVpUeDFUVFlEVTRlRUFibFBNSDlsSzB5QnMwZVVsMXpDK1duMEhKaEFoSXB6aG0yUnZwdlR6QW9pOXNMM1AwMzhEdmlvQml5d292M0xUb29uTDBxamYxN0VRaWNsRHNqZHZDYWJyeHg2cUt1MVYzNmtYTDliRS9vQ25QUHRHaE1KS3VmbVdnbkk2b3ZzeEJJN09hdXdUYkxVcnVNZ0QzZVFVRFlkNlNDUGlpV1h4WkxMNDhoajQ4Z1Q0cWtUNDlGK2VHdVNxSE5UcUV2UzZSOWxNL2NVc3krNGVLaTBDdHpLSU5xbXhOc3A1a1lMbzMzV0p2MjBnRDB1VHQ5OExoU2NnM3grcElNNEpaRzZJSTIrTEpPK1F1ZnlXY0hHRE1RVm1jeVZPc1lPaHpCUVhtZHNjcGpIYk1wbmJpOWs3eXBpZjFIQy9hcVVlN3lDZjdvSzdmSzVwVUg0cUZVTTc1RXloNVZHVmlNRHR1TWhlRnhHcUgrdkV5N1BZQTUzR0tPTmZ3ZVpSckE0cDIvRmVrb2lXcmI1UkNYM2NoMXY3SVFLclRBTGVGVUhiZXhhanpaMkJaUGVhQlQrM1NTODB5eSszeXArM0NwKzNpWkNHdHZaSlVYMHlMWmVPV0ZBeVJoV2lrWVZGNFdlT3pBa2VUZ1ZhUkc0UUZmbUJwUkh5dmpURStuREFuYzEyQ0Fvbk5QTE9LaGRMa3lqNGZ6ZTFTMUJNVnZzUmhTT0tnVXpuMEszVW9SUWk5M2VEYXpMQ2JXQ1JMdFgxNHp2WHQzTWFxQlhGNi9CL0dCSVJGdTJjNnBIbVpLSGhrTDJoUGY5dWxQYWxNOGVIUnZJSFRZTmdzVTVmWjB3ek5MLzNTUkNrb2M1bEtUdlhRK0lzd3ZqUThFa3dBRDYyd0RTbUtZRGxrMkZhRDVCS3g0NEpWNnRGeTdKb05HeitRTXFIQkJVemtHSkErVkxDeHVBV1JtTy9VY3ZXcnN2UVIwSnhiUXg1dmgza0xrRWxYTS96R0xlYXhIcmFGVTI5UW83amdNRUROL2xwQUlsNXRWWnpOR0J1My9KbDZCeTdxb3NCc3BxS0hITTNZTUR4LzRDV25sRTBxeDlLTW10VHFBV1FGOWc1M0FFTkZnVmtwejZacU53VlJhOWRPSTVKSUJmQjVrTGRpNlVvNU5ES3d1OU8zL3B2WUNkd3hIQUlHVXRZMGg1b1VhNEpKMDVQSEM3cE84TmRpNDBRMURSWFNRd1k3c3hsem5XU2FMSDhCc0RxMS9YQkFMc1hBaUdvbm1hR0cxN2wzUi9DWGRxSWpVdlp2elphSDc5RWlDd2M2RVdpZ2R0R2h6VkkvKzJnajh2bGRZZllhZzc1OWNwZ1FNN0YxS2hqWTMxOEo2NGZ2bTVhbjVEQnN4VjlWdElEUHc2SlhCZzUwSW5KTTNUeVd1T2Zobm1EVmRrMGdGODBzMkJ3YzZGU0lqYVdBdXJSdmRLejFiekd6T1paYkhqOHdic0hIYk85SUFDemkxNUtnaDFXNmYwWkFWM1NUbzkrUjBYdER6ZzF4MkJCanMzdTBQVzBJWGZ0Q0hsUDAzaVBjWHN1bFRxQ0llM3dhZkJOZ1BzM0t3TWFEOUc4Y0Q4dE1TdDd1cVMvK1FTYnNwbFRrbWdGdHFtTDcxTmdKMmJmU0dveUxaaXR4cmVKYjFhTDl4VHpGMmNUaDhYUjg2SHBwNFlVbjNiZjRvSkt1ZXV6bUkrYUVIN1cybFRjbi9zN0FnNFBTVU5mVnRQeUo1ZVFhdW4xWndSWlhlWEJEMzZRQW0zTVpOZUZVK2k5QWFORExiNXRmeTBFRlRPWFpQRmZOZ2lOakVtYjhNeCswTFQ5N09CMFhOVTh2VHdXaU9qbFJCcThxQzh1MXQ2dTFsNHJvYmZYTVJlbWNtY2xrZ2Q2ZER2Tlo5WXhlalg4dE5DVURtM01ZTjVyVjZBMDdSUDBOeXlCeGlXWmpVaVlraG5VR2RBUVBUcDlBcmdrNmVMOThBa29KM1RXbG10aVVWcHpFV3A1U1JhWnBFK0pEdjc1YkJ1NmRNMmNVdWo4RXcxZjI4eGUwMDJ2VGFGUHM0SnBkdjQ5ZDVwSDB6OUNBcm5BUDJ4cE9la1VMOHU0ejVvRmFONjVkaCtoSzF2Tm1QdFJjVDB5dEc5Y2xRUElxSmIydE10UWJyYTFTWHQ2SlMyZGtwZmRVai9iUmMvYXhNL2FoSGZheEZoK3ZsNmcvaEtIZjk4RGY5VUpmZFFHWGRYRVh0ekhudGxGbk5lS2cyemhHV3hwSGZoRnN4TWpmUm1tT2ZYNE5OSXNEZ1hUY3lMSWVBNExzOWs3aXhpSHk3akhpMUhnSUt6R1BpWUJxRE9yMHE1QjB1NSswdllYNWF3a0s3dUxtTHZLbVIvVnNEZVZzRCtKSis5SlkrOU1ZZTlOcHU5S3BPNUxJTlpuMGF2VGFaaDZGeVZRRUhYSE81QUZkdGN2Um05QktGcUV3U0xjekhFbkJoaXNaMDRObzQ4SlpFNkk0azZNeG14Sm1rMkF4L1Q0SFFna1FLSFRrMUVpL2doWGYwZ2dUcEpYOU8vTW82Qzdqbk9TYTdRbC9zZjVTQVB0NU9MYkdoWWdCYno2bVdrTkMvQk41ajZFVHpPR1VBN0FuREtoaFRHcDBaRWZ3TnZydG9uSUphQjM3OERlN1ZxY0JGY3prRjdvYk5XUDEvOTlwSUphZlJNTmlIWkJETkZNaitDTGM5TnRpUG13UGkxMnd3aTZKekR6SHF3YzVpcEJqdUhtV3F3YzVpcDVxQ2RvN0J6R0hNd25JdW5YbXNRdlhyNWhJOXpzYVFsWmN3U3kvdi9QUWJ6WFFIblVpRFBFYThmMkxrVkRyY2wyWU9kdzVnQWpKWkpubFhPMFMzMXZGY3ZuNWgwYnFWMUFPbnA0Q3hXeW1JbC9WOEZnemtZd0J6d0o1WUQ3Vlk3QnQrc3BiMTYrY1NrYzZkRmRWaWlSaTAyQmdGLzV2ZGFHTXpCWUtNc050cGlweTJSSTJ1dG5lL1dqSHIxOG9sSjV5N2FVemQvUnp2Nk0waDE4R2UrTDRUQkhDUmdtNE8xUkxzUDI5RzJNYXIraStwK3IxNCtNZW5jcmVFbHk3NTJ6WWthdHNSSkZqdmovMW9Zek1IZ1lDeHg0cHlJd1JWZjE5d1JXUnBSMWVIVnl5Y21uZnR0Wk83WjI4b1dSdlJiNGlXa0tpN3BNTjhWY0FiTWlSTVhoZmVldDdYMG1aaTh0T3BtcjE0K01lbmNPL0Y1TjRhVkhCUFdnWkljL0NVYVhyRjJtSU1HaEFObmRITlc3Rzc5Y1ZqUlI0bjVycFoycjE0K01lbWNzNkR5dDdhU3MzYlh6US92OVFxTFp4S1lnOGNRTG9aY3NMdm4zTjJ1Wnh3bHlTVlZROE1qWHIxOFl0SzV1dGFPRDlQTGJ3MHJXYkd0emhJeGFJbVgwV1FDcHpyTVFVR2lLN3RRbFlYM0g3K3Q5cmJ3NGkreUtwczd1aVJKOHVybEU1UE9FU1NaVmw3N0oydnVKVHRLbDRSM3c2aU1YZ1ZmcThOOEsyQUllT0lVTEhIQzRXRWRHM2VXL05XZW0xTlZUOVA3dURnSE1lbWNxcW9kblYyUk9hV1B4aFN1RGFzOUxLSVBaVXNubUtkZk9zSG1ZZmJHcU9IMEs4QVdHN1Z3VDgrNnNKcW5iSVgyL1BLZW5sN1BmcGJOVHpvSElRaENRMnY3bDVsbDkwWVVuTGFqZWtGNEg3cHVnaTZkUUdHSWF6dk1Yb0FWNEFZWTRoUVhodmV1MlY3NVlGVEI5dXl5bG80dVVkekhONjFHZk1NNUNKWmxLeHBhUGswcHVpK3ljTzN1dXFYaDNYTWpoMUhtaE5vT1FQSkJ6Z1AvY05vTFNZeGgxSmd1R0VwWXFYbFJ3NGVIZGEwTHEzMHdzdkRMak9LYTVqWklYbDZmOWhYK3prRlFGRlhaMlBwVlp2bWowWVViZHBRZXY3TnhibGd2dW9BQ0ZTSVlEVytEaDlxUUJRMm1EQnBNalFIUXhzemIzYjF5UjhQR25hVlBXZ3UzWjVlN1d0b1podkdhdEovWWgzTVFITWMxdExSSDU1YTlhTS9idEtmMDdMQzY1V0h0aDRYM1d2WU1XcUxkM25lRklSeXFQVXdJSWVnWmh3RUg1a1FNd21DNmZIZmJPYnRyYjlzRGs0WThxT0dhMnpzUG5PR00yTGR6RURBZWQzVjNwMWZXZlp4WjhaU2o1T2F3NHJWYlM1ZC83WnE3dFFYZENnQkhrRHlHN3ZIRWhBN1E0OUR2a2NQenQ3VWN1OVYxM3JheVc4T0tuM2FVZkpaWmtWVlYzOVBUczg4ckkzdkhmcDJEMERTTkpNbjYxdmI0b29yM0V3dWVpczc3YVVUWlpWRU5aMXU3VG5FTXJuSzZUM0FTSitocjBER3pIUXI2R25wOHRXTndyYlZ6WTFUOTdSR2xUOGZrZjVpVW4xUmMyZFRlQ2ZVWTJPTDE1dHZpUU00Wkljdnk0T0JnZFZOclNuVnpXR1g3NTlVRDc3cmNiOVl4VytyNTE0QUc5Q2h3ek95bm5vY2UvM2NkODI3TjZCZlYvWHVxMnROcW1sM05yVU5EUTRxaWVGMDV1UGgyNTNEZ01EZXdjemltTnNiRy9oKzlQNytLZktPK1JnQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjkzMTMyN2RkYzg5YjQwNmNhODFlZWQ3MDU4ZWYzNmM2Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTYsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiIsIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwiZmlybXdhcmVWZXJzaW9uIjo1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDktMTMiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlN3aXNzYml0IGlTaGllbGQgS2V5IEZJRE8yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzA5MTMwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wMS0xNiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU3dpc3NiaXQgaVNoaWVsZCBLZXkgRklETzIiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMDkxMzAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTE2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0xNiJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjAxOTg1NjNjOWVlODgxYmQxOTliNDExYjdiMzhiNjFiYjU2MGE2NDEiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMDE5ODU2M2M5ZWU4ODFiZDE5OWI0MTFiN2IzOGI2MWJiNTYwYTY0MSJdLCJkZXNjcmlwdGlvbiI6IlNlY3VyaXR5IEtleSBORkMgYnkgWXViaWNvIC0gRW50ZXJwcmlzZSBFZGl0aW9uIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyODcwNywicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDItMDIiLCJ1cmwiOiJodHRwczovL3d3dy55dWJpY28uY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU2VjdXJpdHkgS2V5IE5GQyBieSBZdWJpY28gLSBFbnRlcnByaXNlIEVkaXRpb24iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDIzMDIwMjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0wMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDItMDgifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIwNDZhN2UyMzJjMDMxODlkYmMyYjliNmE3NjU3MDJiNTI2NjViZTIxIiwiYzEwYmM0YzZmNjE0YjYzMzcxZDkyOTU5NmVkZWRkZTNlNDU4NDA0ZCIsIjdhOGZlMzdhNDJiYmYyYTViM2U2NTc0ZDZmMDRiZGJjNTVlNTkwNDciLCI3NmU0N2I0N2UzMjgxNGFhYTZhODdjMjgwY2ZjYmQ1Mjc4ODFhNDA0IiwiNmNkOTlkOGIwYWJmYTZhNDM3ODEzOGExNDc1ZjdlNDZkZjIxN2EyNSJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIwNDZhN2UyMzJjMDMxODlkYmMyYjliNmE3NjU3MDJiNTI2NjViZTIxIiwiYzEwYmM0YzZmNjE0YjYzMzcxZDkyOTU5NmVkZWRkZTNlNDU4NDA0ZCIsIjdhOGZlMzdhNDJiYmYyYTViM2U2NTc0ZDZmMDRiZGJjNTVlNTkwNDciLCI3NmU0N2I0N2UzMjgxNGFhYTZhODdjMjgwY2ZjYmQ1Mjc4ODFhNDA0IiwiNmNkOTlkOGIwYWJmYTZhNDM3ODEzOGExNDc1ZjdlNDZkZjIxN2EyNSJdLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gZVBhc3MgRklETyBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwiaXNLZXlSZXN0cmljdGVkIjp0cnVlLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJmakNDQVNXZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQVhNUlV3RXdZRFZRUUREQXhHVkNCR1NVUlBJREF5TURBd0lCY05NVFl3TlRBeE1EQXdNREF3V2hnUE1qQTFNREExTURFd01EQXdNREJhTUJjeEZUQVRCZ05WQkFNTURFWlVJRVpKUkU4Z01ESXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTkJtclJxVk94enRUSlZOMTl2dGRxY0w3dEtRZW9sMm5uTTIveVlndmtzWm5yNTBTS2JWZ0lFa3pIUVZPdTgwTFZFRTNsVmhlTzFIamdneEFsVDZvNFdqWURCZU1CMEdBMVVkRGdRV0JCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFmQmdOVkhTTUVHREFXZ0JSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QU1CZ05WSFJNRUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUJCakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUF3ZlBxZ0lXSVVCK1FCQmFWR3NkSHkwczVSTXhsa3pwU1gvelN5VFptVXBRSWdCMndKNm5aUk04b1gvbkE0M1JoNlNKb3ZNMlh3Q0NILy8rTGlyQkFiQjBNPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMiIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTExLTAxIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJlUGFzcyBGSURPIFNlY3VyaXR5IEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTgwMjI4MDA3IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMTEtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTExLTAxIn0seyJhYWd1aWQiOiI4ZDFiMWZjYi0zYzc2LTQ5YTktOTEyOS01NTE1YjM0NmFhMDIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjhkMWIxZmNiLTNjNzYtNDlhOS05MTI5LTU1MTViMzQ2YWEwMiIsImRlc2NyaXB0aW9uIjoiSURFTUlBIElELU9ORSBDYXJkIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjgyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNVekNDQWZtZ0F3SUJBZ0lKQUwxZi92dTJYV3VSTUFvR0NDcUdTTTQ5QkFNQ01JR0VNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVZtbHlaMmx1YVdFeER6QU5CZ05WQkFjTUJsSmxjM1J2YmpFUE1BMEdBMVVFQ2d3R1NVUkZUVWxCTVNJd0lBWURWUVFMREJsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVJ3d0dnWURWUVFEREJOSlJFVk5TVUVnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEl6TURreE5EQTFNemd3TTFvWUR6SXdOVE13T1RBMk1EVXpPREF6V2pDQmhERUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQWdNQ0ZacGNtZHBibWxoTVE4d0RRWURWUVFIREFaU1pYTjBiMjR4RHpBTkJnTlZCQW9NQmtsRVJVMUpRVEVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUU1VSRlRVbEJJRVpKUkU4Z1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkhiVCtScGtBbzlFY0wrT2VsQ2o4aGlobmZGVUtET3BOc3Nkckh3c2UrcXVGWVYwSEw5andRWE8zNTVta0k0ZGhwM1RzbmJNSjBBSjlqcjZvN0JvQ0VtalVEQk9NQjBHQTFVZERnUVdCQlFuczZhaHhzLy9ncGJhN1hEWkJOc2dERzBsRURBZkJnTlZIU01FR0RBV2dCUW5zNmFoeHMvL2dwYmE3WERaQk5zZ0RHMGxFREFNQmdOVkhSTUVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRRGJWTVFxV3puemIwZUVZV1FhUUluMGRsWURvV1FBYlVJNDZiOWpzQzF1RmdJZ2QreEUwcnVmVy83bmpLYzFxa3NpM1VoTW9qY0ZaQyszY0xUUmhXZ0t4alU9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBdGhKUkVGVWVOcnNsdDlMazFFWXg3L3ZOdGUwdlhPazd5UzdxeVdCWXZuaklrdEdVMHZEQ3drdFY0S1hwdjN3Qi80QkJpSWEvUUMxd2prVlV4TnNVdXV1emQxazZpQkxDeElGemNEWE9UWndZOHIyc3IxcnA0dVhadW9nZ3J5SmZTOGVlTDZjNTN3NDUrRTVISW9RZ29PVUNBZXNHQ0FHaUFFQXlYNkxaZG4xOVhXR1lkUnE5VDhna04xcWEyMFZEbFZaY1pVUVlwdVpLUzB0SFRjYTl5d3o2SHVycTZzL3pzNlNQMmtYd0dJMkF6aktxSFE2M2Z0M2s0U1Fwb1lHQU1XRlJYdktMbW9MQUF3T0RQd2RvTGRIRDJCa2FPaDM4NDNKNUhLNTlwVFYxZHdFOEdwOGZQK09TNHRMNXJmbUg2R1FrTzcwb0x1emMyand1U29wMmRCck9DeW5rNUtPOVBYM1oyWmtNQ2twcXl2ZkdJWUJjTCs5dzJxZEtDb3FDZ1FDQUhpZUYyb2ZQM3hrTXIxVzBJcmF1bHB0UVlIUDd3TkY3ZTJCTmw4RElPMzRDUUFOZCt1N3U3b0FTRUFCcUt1cEpZUlU2YTREb0dYeHFhb1VwWndXQTlhSkNVSkk0UVV0Z0ZQcWt3blNRd0Q2OVByb1Z4UU1CdHZiMmlpS2V0RFJ3Zk44S0JUaU9PN1prNmNBK25vTkxNc0N5TW84emZuOUhNZmxuTWtDc0xTNE9EMDFEVUIzOVJvaHhPbDB5aE1TNGlpUjNXNlBiTHN6QjNGeGNiUkNRUWhSSkNaS0pCS3hXQ3lUeWVSeUdvQlVLdjB5L3htQVRsY3BpNCtYeVdRYWpRYUF6K2VibXB3RVVGNVJEa0NsVWhWcUMzZ1NucCtiaXo0SG5OOFB3Ty8zUjV4QWdNdk56azVta2tXVUNNRHE2bmZCZHpnMkJEQ3RVQUJ3T2wyL2ZJZEFpZzRJQm9PUktJam5lUVZOYjNtM2lpK1hpRUhwK3d6cEdlbHV0L3VsMFFnZ0VBaVVYU203ZGVmMnZaYVd0TFMwaFlXdkgrWSs1Wi9OeThuTmpmNVVTQ1NTU0l3NDRYRFk0ZGhRS3BYRHc4TmlpcXB2YkJ3ZGVWRjFvd29BdTdhV21uck0wS1BmM3Q2K1ZGTGMxTng4UHUvYzZOaVlTQ1NLUHNrZXQyZDVlZG5qOFVRY3I5ZHJYN2U3M1p0Q3lySnJWcXMxSEE0VFFwWlhWcnhlcitDN045MFdpOFZtcyswZkN5cjJxNGdCWW9EL0FQQnpBSTZWTnFHUVBVcW5BQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI4ZDFiMWZjYjNjNzY0OWE5OTEyOTU1MTViMzQ2YWEwMiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImVwIjpmYWxzZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMDI0LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0xMC0xOSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSURFTUlBIElELU9ORSBDYXJkIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzEwMTkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0xMC0xOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTItMDgifSx7ImFhZ3VpZCI6IjQ1NGU1MzQ2LTQ5NDQtNGZmZC02YzkzLThlOTI2NzE5M2U5YSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNDU0ZTUzNDYtNDk0NC00ZmZkLTZjOTMtOGU5MjY3MTkzZTlhIiwiZGVzY3JpcHRpb24iOiJFbnN1cml0eSBUaGluQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjowLCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURDVENDQWZHZ0F3SUJBZ0lKQUxLS2owc0tUWERsTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ0V4SHpBZEJnTlZCQU1NRmtWdWMzVnlhWFI1SUZSb2FXNURJRkp2YjNRZ1EwRXdJQmNOTVRnd056SXpNVE16TnpJeFdoZ1BNakEyT0RBM01UQXhNek0zTWpGYU1DRXhIekFkQmdOVkJBTU1Ga1Z1YzNWeWFYUjVJRlJvYVc1RElGSnZiM1FnUTBFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURFaVpoNHRJY0FVUGZVa0NtWGJOd1dESUZ2V3h4R1BoSnEvL0ZzM3VQQkE0SlFVWGlBSFdVb2YwbU54ZlUzOXlmSzM5LzJ5WGdPSjVRb1pHenBRRUdTdzVTbm95MCs2MW9lSSswSVhrQWFNdmZWdnRtTm9PMk9KTzUrQUR0bER1NnJnSnVWNklwTExSNVNLWE9VMXpPUEhZckFQc1l4djNVTGcyNlc2M3pNVHFwQ05DZzRwendaUnlYamNMclVlQ3pGNFhjZitwL0c0MlpkR3pCZVpjNHoreWNjT014Qng0d3NHY1BnMUhGeXpYbDNKbXR5Zzd6VURFcWJqZUg4TnN5OStrVDMxbVZYb2NpZ0IzaEc3d2N0aUluNkE1bFBHTVBKb0k4NFJaZHJCM2VzOVFsSFpXU252ZEpHZWFMbk81WHE0bUlodWZiWTRzMVVxL3B2R3NBUEFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCU09FbitWRmhJL1pHVVRTVWVoRXlPbHh4RnhMekFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUFzR0ExVWREd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFyYURvOHVtcmVqWE5ZUTZCUkJuNFhzRGVoRGxpajNMQU5NN0o3dGltYU5NZm94YWR3eVMxbnZBOGU3Y083T0F3M2llbFlqTzZvaVNwelVzdTZlSDJsb1owTEswZmtvaWFaWm5IS2IvNDZvNm85OTQ3aTh0dUFPeW9WckdQdzljMjlWb0lRa0UzUWovMFBKWm1VMFl1YmlsUlVOeDZsZEsyNWEwby9xOGxrN0JMMzJOaldkVHpLREpQZ2RLbXJ3bDFtM0syZUdtdjJaSWdBUDRwV1VtZzBERjRYUy9KYW5rRmliUlpoczZLZzBWMDJFOVBjYkd5WElvK2h4VTlRc2pqZ0lQdEZpRjgrVnZRYlBUVmVNMVpjMEN4UG0xWHgyMmtpM0llUHBhRGlnelMwS2Z4azVSbkZ0cVkvWk95VnRhbS9vQVA5dHEvTVRqRVF1MWZscnBwUlE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFIb0FBQUNvQ0FZQUFBQXZyL3JBQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUc3dEpSRUZVZU5yc1hRbVVYRldaL3U5OXIxNVZkVld2NmU3c2hDd1FvaXhCUkF5RElqQ2lETUlvanFPRHg4T01vNk9lTWFnek91TlJPUkpBblVFY1owWkk0SUFPeUw0R1NBeU1IRGlESkNvZ29FQ1RyUk9Ta0syVFRpL1ZWZDIxdlBmdS9QOWJrdTdLZTY5cmViVjF2d3YzVkxycTFhMTc3L2YvMy8zLy8yNXM0NlpOVUlVMGt6SDJPTDQyWWM1QmtDaUZNZThGSVM2dlJwL0lWV3FVZ25rNTVraUE3NFRValpsVjQ0ZDRsUm9rTUdjRFhJOUxtV3I5RUEvNmVucWtBT2dBNkNCTnBTVFhTVDFvL05hbllQL3FWaDhyQWRBQTI5SEYrRGkrSnFZZ3c2akEyREo4ZlFoengzUUgrZ2gyeG1iRE1oZGlLckpteXNvMUJib2VORWl5OHRSTGpObktWSE9GNG5YWU1WTUo1TURxbnRKZzEyRWJlTkJSMDZQdVBPaXc2VkZudWU0N3pzMFNMNlJUaTdYaUN3WEtxZHc2RjB5NVliU2tGTmRyZk9lWEl6Q1RsZHNBN0ROOVFxRDVZTkRmZmdEVUlFT00zQkMxOUN1UU1wWGN0eW1uMFZNeldoWUFIYVRwU04zdTJrd2NUQk1ocytENDlWWWh6SGRqVHBiNHExVG1KNjF5eDgrbzBUS29WekQvTGdDNmVvbGk0emRnZnBmTDUwK1ZBZlFwbUc5MitXdzE1dCtEdVRRcW9PNXE2RHJtRVkvUDFUTEtUbnQ4bG16US9nckc2TUFZQzFJQWRKQUNvS3VaWWhWcWw1ZUJHbTFZOTRxMXRsZzl3MEFYdEpySGl0MEs5Q3hHNnRyMmVNTUNWSGNBcXB3dExtT1l0emdZZEZUdXZucDNSMWs4RGtLU2dDT0diRndrVUU2dnZzMXdTbE82QmxFbEJFMnlESnFtZzRoR2dYL20wd0RaTEhaYmpiWkx1YzllYWZqdTMxdHVsbkR3c1ZPZXhYci82bXRZNE5rTzVYS3NTOGJOdFdLMURLOXlsUGRJQkZnb0JMbkgxZ0xyT3dURHVRem91bjYwWG5MNnpyc010UmhRYzlBUmE0STRBcXlxS2dnRVhIL3hSWUJMTGdGK3dZZk1Ecy9WMWY2NHNRcVZxemVFRzBWNElFWVFEZ01jUEFpNS8vd3ZBMmoxVDY4RFQ0M0IwR0EvcU1qSzdDaDF0N1FZZjBoYURsaFRreUVacU5MWVhHeHZieSt3TzI2SDNMMzNndlRkN3dJL2FRbnFTcXE2a3dOZWM5TFRPU2tLaXZvWWlKMDdRYjFsTllqZUhTQkNDRHhIa210ckJhN25FRlAxcUVaenp3NUc3VFk2ZVhBUTFHdFhnZGkrSGFDemMxclBBdFdjdGdtUFdNeWdhKzFuTjRPKzhtc0FCdzRBeEdPbWtuSmV0SVY1REhDaWg1RVJnQnQvREd6Wk1oQi9leFZBYzNQMXFOd1ByYVlPUUNQRllDc3FqLzcyb2Y2czJ1eUdJSXNISGdUeDZxdWd2L2tHOEJrZEp2dE8wais4WUNraTdSNDRBdkRNTThCKzlDT0ROZ3dCcUhkYXBjNGhvU1NqY3M4ZTRGZC9EZGhkZHdFTURaa2FRTGtSaGdZU1RMU280Zjc3QWY3blRvQzMzakkxdThDNjg2SW9Bd2Q3YUcwRjJMb1YyUFUzbU9OMXBJcDcyOG1HS0thK0pKeVkyY2FOd0ZhdkJyN3lhbU1ZZ2wranNIN3hId0RXUGc2d2JSdEFWNmNyNVRtV1M4eUEvVURHVDlXRWhOcU90aEs3NTE0VDhHTDZvdVRBQXY0UVE3RDVEUmJZMU9CS2F5VWFIMnp0V2xPd3lOb2tZTnd5QWRIV0J1dzNMd0M3OFVaZ04vd0EyRXN2bTBKS245SDN5UjI1L1haZ04vMEUyRTkrQ3BCSW1KM25WYTZ0VlljUEcyV1N0VnNWUVVmTlpmZmREK3plKzh6ZkwyRzRLRzJha3FTWWZuRExOdURYWHcvNk5kZVkya1AwNlBlWVJjRGdFTUZXcndGNCtpbGdxSTNpaWs4QW5IdXVPWHc0UFQ4d0FKeWVSMzhTQmdjQVdscU8xWHQ4YW04M0tmekpKNEhobUFlbm53WTYyUjlwbDRNSVVLQTVHa0FHQzd6ekRzQ3VYU0JXWFl1TTBHWFd4ZSsyazJDaHk4dnVSYnErNXg2VHFrdlZsUTJ6NWhwcTNZL3VWUnRLZENkS2FCWU5Gb3FRTWV3MEJnSlVYWUJnSEVMY2pLQ1ovMXVOUW8wV1M1ZUN1T1o3SnZqT0RaNkhSa3NQdnJZNDFBRlZEYzRGcDZsRkl4Q0FBclJtRGJCMTYwM0xFbjE4UXlNbHlWc1FTZWhzelM4a2tXRkc5WjZNbld4aHB1ZW9yYk5tZ2JnV3daN1pEVEE2NnRUMkdWWVViN1pEYWU5Z1haZUEwN0VmVkE3MUoyb3hROG8reWpiWU5wMENXcHlCaG41eWZrUlRWelY4VElLK2dYNjBPd3R4cjRxaGNaUndUbFNXVEpyK25WK0pOSmxBM3JBQmFiZkZiQ2lWYnpYWU5kdCtKaStpZVFRY0NZWlh1YmFkWWo5SHRJMnVEU09nKy9wTVZ2TnhUS2J4bU4xM24ybE04dktnS2g5bzI2L2JzZ1g0ZGRlYlVsNnVrVUxhU2tiVWJiY0JyRnRYbEhWWjlVU2F0bjgvZ3IzS0dMc05UOFFINjVyZC80QmhmQm5sKzlCMmYyYXZiTEJKczhrYVQ2ZExkMXNJWkRLVWJrV1FuMXhuU25POWh5S3A3V2lZc2Uralp2ZjNId3MwbGVnbkF4cGVCc2owYjUvR2ZYK25LYWxpVzdlWm1rM1dlTEhTYlFkbmtLN2hWNzh5amFoR2lNTFpORzZEZlJCcHZDbGFtc0RZZEUzak0vY1BIdi9ubzhsZ0l0ZUxOTnVtOFVKQkprMWVjeXV3SjlmWHZ5WTdKZEprb3ZGVlNPTjlSZEM0WlhpWkx0UzlaVm5YMVFQYWRyMkl4bGRkWjRKTmhwRWJsZG16TU9SRzNHcU55YzN4eHB6SXNMV1NETFR2Zi8vWW1PM1ZkdnFjaEpyRzVESmRxT29DYlRlQWpBaUtvQkdWall6b0JwWFIrSnVmU1FnVVJZZGJWamNXWFU4V2tTT3d2M2NOaFkwRi9xMDd0ajBjMXRFZkYvQ0xYeHdMaG5EZVFFQ1BkNzNlZUFQWTg4L0xxTFc2TWFHUW56bm5TRmNTZS9pUlk0R05xWkRDRVpQR04vNVdSbEM1Uzl0MTl0eHpFcnZ6bHlhTFZWREFDdzJZb0YvTzU4a016cEk0cDBYejg4RThxWGZ5czhFMExMaTVlUUYwZFYwQXVpNVBYS0JoUkY2UzhQYXVwN0NSU1FKOXlnQk56ZFMxTEFyN2ZHejdoZmlHY2h5Rk01NUZlbDhQeWVRUUNvTlVvR0tPSURhN2RDRjZOS0cvaXNEMDRiL0ZaQUdUeVVLZ0tKYnNZa1hpMzhFdm5NT2doQzBLVkgrS0l3OE11T285VXZlbmdFK3hCYW5NYWp0Tjc5SkVpbk5TMEZpOUFxVGlEbVVpOENUS2lEdUN2QTRWNk44MElWNFNIaHNYWk5leU9GK0IydnZmV04renhndHBTWW1NTFZtR2Faa3EzSGJPMkdWY2tpNURyTmJsZFAxYmlQVFdnc1pvWkFEOERyOUdscVJONDBFT1VuMG54T3d5UlpKZVYwS2h2MmFUYVRUeVBHZWMzWVM4Ly9XZzZ4ck4yRGY0VmduSjBvTXFneTVrOWx0b0ZhaHQ5aHdGR3JtZUtiSzhDa243NjhGaXZNYjI3a0tTZkhOYnZQbFFZblQwWVZyZkxXeXJtejdsWWVYQ2xualRzNGg0UVhaR1dXTjJrRXEyN3dycGQyc0tPWjNNWnQ2ZFZkV2Q5SmVjbFNVSU05YmNHbzNld1lTN3Y4U09hZjVHOUFDZnhMOTNNZk9xZ0dCSmFIVVNMUUZzUXAxY2hsNzVKeEhNVTkxQUYvZ2ZXdWFScUN6ZmtWUFZQMGRhMTJVeTFXVkYrU3ZPMlVMTmhiSkovVlZkZjFrVitwZTVwdjhKclVndFFMZEdyam5GTnpUOWg0THg4eEdYMjJYT0Z6amhKZ3lyV3JvZ3BpZ3JoS3B0NGxHSks0b3NmVnU0Z1l3NXAybDNqMnJhK1ZsMDBCRnpMZWp5bXBONFZ0VzBaNGF6MmJNUmw5OXlsNGdhYVhhSVMvOHFTYnlaUnlTK0NLbjdaQ2ZLSnFkOFROT2U3VXNtdjRnVzNCZ0xXTHArM0NsaVdTRU83MHNrL2xMVnRUN1g5ZVVjemdmR3orRTY0K2M1eFZpdEtGZzZsY3V1Uko3UElMV2JPL1NDUHE0Zm80enc0THcvb1dsZmNzZUZ0UWlKWGNoRGtuU3U3a0RiSkNGcFRWMmZVbk5ia2V3aGxjdEJJcE9CSEZub1FWL1hGT1NzcGtNR014TU1Xc01SMEZWOUEycjFkamV0bGhsZmdFcktGcnM1WktxbVA4R0I2K0dRQXBwT2t4czZKRlFOUnJMQlhXVzFOTWd5bWtDN0NjZGZNcmdRRnhuL0ZEcmNKOXpqSHpTYjVIeHlnREEzVW05cHlsc2hZaXd0RGZxN0pwcE0xblZLVTYyTEtkZ0VWemdqOUMxeEpvSHVBcmJzSG1FUjBDUkp1U2FYbVJVUkJFeXFuZ2lzMXBEc0ZpUkplMmkwOXpTbEtFREtBckNyWjN4SjNnc1RtSmhFU01xdVJBQjI5Y2Jua3QweFB5VXVTSlhUNXJMOTducXJVSkNPOWFlZmZjcnJVZnFDNUgvaWxaREVJTlZmSC9KR3FXaEExM1VJZEFEMk5LRHVBT3o2N0N2ZTZBMElRSzRUb0FPd2F6TW01NmVxcnFyblFrRElQdEN0Z2lrclNRVkhrYWhPQ20xQjhxb1RuUnZDT1dTNWNZSUxoTFhDRnRsa3JIb290T3lXVm54WnZ5R3NPbFl6VlExb0dSdEtqZHZTMlFtU3JwZFVobTUwRnBocmxkMTJvdUxueS9xUEdBQ21qYjFqN2ltV3k4RmdKQUtiTzJkZy9keEZRME9BT3RKcFdEZzBaTFNoaDA3ck14WmhNRmRWNVZqZXN2NStvOTA3MnR0aE9Cd0dpV2IrNkNRdFRZZVRCd1ltclYvREFjMnREV0JQTFZrTVBWMWRSdU9MVFRRems4bG1qQTFrWVVVQnQ1a2E2c2plOXNPd2FIQUl6dXpyZ3pGWk5yUlZqS05McWcvVjRUZno1OE9lMWhiWTJ0RUJpc2ZNajhvWmRJMk93dEpEL1pDV0pYaWx1NXRXZHJqdUNhUTZrREMvZzJXSEVOU2VyazRZakVhTXVXTmhDY0dsdlR2Z0RLeGZ1a3BibFNyK0s1TFZnWTh2UGRubzBPWnN0cVRnUEFITGpaMkNTTFdjZzllVUhBblQyMjF0OE9yc1dYRFIyN3NNa0d4NlZqSDNJS3U4akovMVc2ZnZ0VXh5UGhwOWtnd3BzR25lWE9QQStnaldnNDNiQmVHVy9qQjd0dEZXb3ZwWU5qZUJJVGFnMEZQQnl3OGcyQ0c1NGhORGNxWHBtanJYQmpsSzU0QlhRWHJwZDJoTTdZdkY0UDVUM3cxelJwSncvdTdka0VGdGZHclJJa09McUxNVmE2d1ZreGhGd2hMWXFMV2R1TkFVVVZWWDRTZEIyYkI0c2JHendtYWVoZ1NhNkpHT0JYOENRZDVtZ1Z4VmkxYVlTMjBvSFl6SDRKZW5uV3E4UitCUzNYaU50eDNaUmlBTlp5UmtaMWhnczBZQ21ocEJuYnIybEtXd3ZZcWE3RldmU0pVRnJSaldJeHFuL2puVEdyTXIwVmU4RWhVbnFYd2NRU1pOanRRWTVIcFB0bUg0TklMOTJzeVpFQ245REhHdlUyNjZmZFZvMjMxNHZFWjAzY2hnYzR2R0tTMHZqY2JwY3RSdndjVDdRSmdsQUgrVS9hd3NXUmEySmtjRFRTNkpEUTJ3c1IrWDl4MUdzSXNJcWpEWWdWKzhxYUxVTFZsMHZkYXlyZ082TG9QR01UK3g0QVI0c2IwVm1ueGtSTmtQa01rSFhSdlF0Vy9ESDRWTUg2QmJBVkJiM2o4OERDa2ZJbWk4WEFrMC9lU1RET3U2S1FEWkg5Y1F6UGo0WTNObncwc2Q3ZENrbGIrQmxaY2plVlFoMDArZUVZekpGUUNiK3ZoUkJQdmw5amFJSWRqbGFIVkoxRzFIdk1iVGRRQnlaV2ljNHVPUHpwMURaeGpBT1FPRE1PcGdvRkhmMDlnZUpoemNOdHFWSW1rMGc3Tis4ZUtqd1pBZ1ZkWkFDMk1tR3FmT1gzRmt3THBoZGR3Rm8wS0h3N0VtMkRSem51dUVrVnpLRHc5RUlyQ2xjd2JFQTAydW51dUYvYjUrWmpmMHRyZURGRlltVE5NU0pnbDhiMjlycStzVWNGRkFDNHUyTnl4ZUZMaFFOYUJ4TXNtMnRMVkFOQkk5Ym5LRndJNTdiR2N1Q21nQ2ViczFpUjRzRDZvQmpRTk5lZXJtbEt2VHBJekhWR3RSVmpmTnE3NHlheWFrUWlGajBpSklqU1VrQlNYeWtmODBjeWJzeG5FZ0VoaGdVeE5vNHY5VVNJYWRiYTNHaEgxQTIxTVVhRElFRHNaaThNZnVib2hvd1RGakRXbTFGK05XaFNoUWN1eXRWc3pYV1E2ZFZrRkJwSVZkLzg0WTYrWG1ncnhGYUloOEQ5OGJ6bnN1anBsbWJ6YVgrRnVYWWI0VWMvNkZsM1ExMzc5Z1R1VzlmeWJtcjJFZXpMZVhySDdabi9mOEhNeXJZT0kwb2xPaWRqeUViWHlteVByVC9VdlhnM0dZUHVURzFZZXVHL3EvY2lZMXFJQ3JxeVNRRDJIdXRZNVhPaEh6MzdrODk0UWIwUFRkU2RaN2ZRVHpsMXcrdTlZQjZOTXhYK1h5L0IwT1FNL0MvSVZDR2hzS2hiNFFEb2RQdy9xK09YNEJvbkhzSTAxd09MZUZBUDVubHlJN3k1blVJQzNXcXdUMCtPdGZjd1UrNXdpMlIwcDRmT2JVempHUDU1M3FXSkFGYTl4bGd2VnNiVzE5VEpibDVwR1JFYUNjU0NTTTNOL2ZENWxNeHFrdGhQeW9TN0hEMCs3K0E3dURSQjI3aHhiWUowVWlrWi92MzcvL2IvQnZUYk5zSXhVOW5uZzhEcWp4UmJXaEhJM21BRlU3UkRBMDNRU1NRRVF3UHpWbnpwd3ZUekNxWkJuMjdkc0h1Vnh1TW9ZcXpSaHpvZTdkSHRSbTAxVTdqUkVlZE5ublVROXVHVVBwU21pMnFQT2dEMjFCYW10cnUzbDBkUFJscE8yWENHUzczc1hlSEZVdzBNWlowUk1saUFBNkZieFBvS0wzVjJCMnN5REpTbHdEM3V2bnFVV3BTb0JTSnpTT2VPcDlDTnpzZk9HamZ4UFluWjJkaitCbnkvR1pBVExHNlAxME9nMU4xazRUMzZoYlJlbVpQNUtFYy9ZZmdORmpSMFlLeTFVWXNWNmRNbG1xdlI1RjkxclBKRDB5YWIybUY3WmZxeHpOejlUSVp1RFpiUGFmVUd0WE9sRXh0UnMxZVg1SFJ3ZTVYREw5VFVEVFdGMk1Wdk5DdFpuODZCT0hoNkVGTFQ2OXVHMnZFWS9Qd2o3MzIzdXNvYUliODh3Q2N4ZDJNTDJlWEN1VlZoU2xIelgwVnJTbWYrTUVIb0dMTHRkRmFJbC8wekRwY1h4R3dUQnlvZU4wd1NKQld6emZoYWI5M0dTeTZudDd0Y0wzUFAwSDVnRnJXRGxZWUQ1a3ZWNVpLNk1MUVd3ajRqeHk1TWlucWY1dW1vMVcrQTlRS0Q1SUFCOCtmQmdHQmdZS3ZPbXdDS0RwcDJuVzZvTjczb0VZN1lpczBvMndXcEViMnhveFVSdlI2Q0xRRGc0UEQxL2hwcVg0SEVmWGFoMENQb3NBSnI4YW55K0l3b3N5M1lpeU84ZkdESzNXQTVCOTFXb0NpOEJEK240ZXFmazdidURoK3kxZFhWMFBScVBSRUgzUERyRDQ3a2NUMkJmdDJnM1pDdTc4bTA0Z2p3ZWJyR2dDYlhCdzhNZG9vSzF6RzYvUnYvN2c3Tm16cjIxdWJtWjJFS1VpUU5ObTloVjc5eG5qZHFVYUxhYlp3Z1lyUUdKb05vS3BJdGlmeC9jT3VZM1hLQlRmUWFBL09qWTJOc0ZWOUMxZ1ltOGEvL0N1WFRDcUtQQm1kNWV4ekxST1VqL212U1VHZ2s0RWMrYW9waWtXaXhsR0ZqSmEvOURRME9Yb1Z2MWV5NXNhdHBVQXgvWEhjSnhlaXAvdlFkb1hKUi9NN3FYVkJIYmV0R1U5cEpYWTJFZWhoRk9kVUNOb2luTmxQUmhtWkdEUmVKMUtwVjVFN1YzWjNkMzlzMXplZGxwcmJJNmdjZllRV3V0LzF0TFNvaUlqY0svN3kwcWpHcWpMQTlrUFl1T3BSN0lsNUlGNm9XK3l3TzNBeU42OWU5Y2trOGxIbk53b2E5cnlIRFRNdm8xQ0VjVzJEL3MyUnRkNWloWXlYcm5GTGVxaEFSVFBSdURHeDdNMTFOZ3ZvcWJ2Y0J1dmtlNnZRODIrQ1o5UnB3dlEramdxYmxpZk9oUUtHUlk0dlNJbEExcmdPRndQWGVGbFZPT3pWMkdiNTA0WG9QUEgzWVoxc3lLUkNOanhmV29IMHZmckNQam5pNTIxbWhaQU55cllkcVJNVVpUeGdSSUtwdHlGWU45UkN0alQ0dmJCUmdTYmFKc01NOHFrM1pZVnJpT0Zmd01GNGExaXdhNDEwUFdFUUYwSlBWRTRHV1hqaFpUK2pXQW4rL3Y3UDI1NUNnVzNyYXpHNmVQTzJDeXhBeVV2TFhUSmtwOEJvQUsveTR1cHU4dnp2SmpuYmFDZCtpV2RUbThmR1JuNVhCRmFIU3E1WTJqMnFvbkNiK2swWkswVGlWd0EyNG91d3d3SHQ5czRZak9mVm9taUtHRFEyOXQ3M0JRY2pWMGRIUjBiRnk1Y09FTlZWZUhRV1FuWHcyQW5DYWxpUGE3Qi9FT1g4TUNRd3pEd0tKYlpDY2N2bzJMNC9yREQ4MitBdWFRcS8za0tjb3dVVTJjcUU4ZnJoNURTZjQxOXhDWnBHMVVnVXpMUUZPZStjTjgrNkdsdmc4R3dBaUdQVTVDTERVWlF4U2tTbEwrcWhJQzJmTVZLQkRmR3dIc0piMzRpNmp4U2pJMVY1UE9GMkIxRFZSbVhja2dkNXgzc1E1R3NqQUhsbElOVUF3T0U4RDFsYUFoaXdhYjRxUTAwR1dOMGhzbkY3K3lGSk8yWkR2cXpibFBaT3pXSXZ1ZU1qc0xKYUVEdGljZU5HYTBnVmRFTkl3d0t1RU9rYktEcFJQdHV0TDZYSkJMd2RrdExBTFRQSUdiei9HajZtMk1PMFMwRStFcGJtaS9adHQxWURPSzFPdGVYKzZOSGtMWlhvRkhXMDk0T0I5SDNVd0t3ZlVrYWdyazRuVEZPVERiN210RUVoM0dmaDVUSndCbW9YTlR2ekRyY3p5dis1T3NtdXpPT0hJR0JPWE1DaEh4UUhqckcrZjM3OThPSER4eVlxS24ydncvM0cvdWRhSFBGc1VOcWZEcXNackt4K3IySER0ZmpxcE9Hbyt0UkMrU0xkdStHTVJ4LzA5aTNSek5GeGlqanYxVy9kMm9VSTRrZjI3M0gyTFlUV09DbGdaeW1ZWERmZm5PbExaZDhVeHBmZ2RZdHcreUVaTkxROENBVjMzL243dDBMRis3Wlk5eXRvZnNZSVBKMWpOWXNvRS9Ic2ZySkJRdWdPVERLaWs0cmtMSlY2MnJFSXRNOC9OSkZjUHhHUTlweXVkbjNFdzlTS0luTCs0L0FaclRBZDhkakVOR0RFYnVRSVkvNjdkS2RPNDJUQVVzRStuek1kN3A4OXJUdi9FcStIWjB3dUdSNE9ERE1pb2hGekVBbW5JZERYaGxrUGVyeDJVQkZCbEthMlRydndFR0k1clNTTitQNUxTQjF1anpaU09SS25ZckQzYnhFeFd3YnZTS2xNc3UvdXhnTkM3WElpbE5EaFVWZGZweG5RZVVaMXhQU0htUE05dDkxbzgxWUg5cTBlR2JmSWZSV0tuZDJVTVZLSnUwaDY3czFtNFZVVTVOQjUySVN3U0FtbUpWTXdZcVJFVGdQeDZxbjhiMmRDQXBWTWxLc29KR3ZpWm95SzVXQ2hVUERjSUZ4TjZVTUd4WXRoRU5ZbjhQUnFIR3RjSzBocHp1cFQ4RDJ0bVV5RmIyZnNtSWxrMnRBQjdkL2R0czJlR0RaTWtpRXcwY3YvY3hQU1VXQm1TZ1VaeU45blkwK0pBRWdFUFFQcXhvOEpuSDRJNWIxTXAyOVZlQnYwMHhhTndMOHZ2MEg0T3dEQjR4enJBbGsrdjByMzlvTXUxcGJvYWR6aG5Ia0pYVjBJY2RlRWd0a3JOdHFDajMwMXJneTJMSlo4dS9DdEtOZlo2RW1YL3oycnNhOWhKUlNCanR4eGxnYVByTjVDNEo5aWdHb2xOZGdHc012UldHWW14aUIrWW1Fc2RrK00yNEowV2RSc3orQXI5dnh1WitEZVRpNWNSKzBDLzJTUS9leDNoMHdGN1hrQkxzOHF4T0ZKUVN6VWFqb21JNWxSd1pnZTNzYi9HN09IT002QTdmenJvbnVGK0R6NTlKMHJCS0NweGN0TW4vZm93NGhCUGVUVzdZYUlMK3c0QVE0RUk5UHVBYUIrbVk1Z3Z3WE8zWlVKZVpRVWFDWlpaaTFwOVB3dVRkN1hBOE1iY1hQcWVNU0tBajVYVWRyaHVoUWtnOGdFSFRJaUVCdzVLRS9lQnBXclJuejNCbW44dXhoZ2pJSndpeHJmSnpzV21FQ0xHN05FTTFEb1p6TXlLU0pCcW9IYVhMMzZPaHhZTkwzYWNFRzFVT3ZnczFROFpNRG1hVVJVWTlyQUhLV0JqTzM4ZGJLQm5XVHl6WUoxZHFkT2xuMzJWVGNuSjE4NWF5d3FSaFRyTUNMUXUyelhoUUVOT3ppaW1wVmlpQlcvb2hJYTRXb0gxSjdGRjRmTlVCWUhWNnMvVkZzYkVGNDlVOFZOSnBYQmVnZ2VmZFBGVUxGbFFVNmlIWFhqVUx3QU9UcG9kazhBTG5PVW9YNmpnY2dUdzhhNXdISTA0UEdlYjFXTEVqK2FqYXZ0d29GNmZnWWhCK3AvSUJKb01sVjBlcENOaGlLVW9GbTRCeEd0Q2Z4QllJY3JQYXNEdGhIRjA2NEF5NVlLVUFiTyt0VlZSNVZ0UWxsYTNTSUdiN1I1akJoRUtSS2drMVRwUUxHY3FwanY4dWNoNXRDSWRCZHFKNkFkcjFpUUJWaVNVTE52Y0s1ZGZlRUxpQWlTYUFFUzNscmdUTXFHSWVvSkVDbEJaZGlJbG1qOGkzeE92bUE2N3ErdzNIV2lEU1g4OHVGcWpGOUxBTmFOZ2RjNGhDWFpXaEd5UW5NcnhvaWpvQmxWUlZ5T1N1cm1vd01mS1hIT0M1eDFOb1huVVppTXJHaW9kQVYzVkxveEppbVF4eC9vRDBjTWJSWkQ2enNtaWJDazg0Z0U0b011b3dNSzBrZkNrblN1OXh3UVdYZXp4TzY5b0liRWFOV1J5S3h5RTNwNWxnb0dvL1JWVFdCSnRkSm91R1VwajkxenBvVkpYU3J4eUU5bzFraG51Tk5qRzlUaGI3YlVSTHd5N0lrWFlHRzEwOVJpRUlCeVBYRjRDRmc4U1pKZm9oeHZ0amp1WTFjaU45eXBtbHBWTzJiM1BpZHdHNlY1WDhNUzlMNk1CWW9JREMyNjhEYm9yM3c3NDFLMHFZbzV4OEZyek82RVZ2UXRTSDI3SWtMQ2JxMnFCTFpnbCtmNlJXSklSc0FnZjlmZk9aaEhDaTJNMTNQQmQxZUxRMUczd3FOYm9UbmRPejdLeEhwOHp5cG5keGpUWHN0bTh1OUR4RlY1YVRReVcwYTB0VGNWNXZENFllOVRIVDhSRUhOdnd3b0c3YWNGQ0JRTFFOc25DRldTRUsvV2g4ZUhmMGMzYzhoMDNFWVdqb05laVlEaVpIRW85bE01bWZCV1Y2Tkx4REdUVHVwNUZjeTJXeFBHdDJ3RkYxdnFOTVNWbG9GbWMwS2JXQ0FiaFMvTytpdXh2YTlORTFiTlRpU3ZKMjhKRzdkZnlKUGpHOXFPYUhyWDBENjdrZEw3aHRlMThnR3FmNDBtYkJTVmZXcmlOOGFjNDhEbTJpWVRmREVHVU8zUzN3VHVmMHlIV0JmUU9RTlFOVmd6RUc4aGhwOGRrNVZieEVPOTNtN3hVcDB0SzdYNHhlWEl1QmZ3Uy8yQllEWEo4aUkwK3VJMHlleW1yWUMvLzBITnh0cnNtbktsS3JydCtMclBTZ2k3MEdwK0FocS9FbFlXSWZocndlcEZpbERReXNxWHcvKysrbWNydmVnNzVObVI2K2VjMDcvTDhBQTF5UTIzNTFXWU4wQUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjQ1NGU1MzQ2NDk0NDRmZmQ2YzkzOGU5MjY3MTkzZTlhIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA2LTEwIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJFbnN1cml0eSBUaGluQyBGSURPMiBCaW9tZXRyaWMgU2VjdXJpdHkgS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTA2MDUwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy42IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDYtMTAifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIyZTg2MjkzY2JkMDdkYjI0YzI3MGJlNTU0ZDkxMzU2M2Q2MDZmZDQ3Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjJlODYyOTNjYmQwN2RiMjRjMjcwYmU1NTRkOTEzNTYzZDYwNmZkNDciXSwiZGVzY3JpcHRpb24iOiJBQ1MgRklETyBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEwMDAwLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9LHsibWFqb3IiOjEsIm1pbm9yIjoyfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDUVRDQ0FlZWdBd0lCQWdJVUYvMHdUUFA2RkVxeHBzaWJKaUxGdERqNHFod3dDZ1lJS29aSXpqMEVBd0l3ZFRFTE1Ba0dBMVVFQmhNQ1NFc3hFakFRQmdOVkJBZ01DVWh2Ym1jZ1MyOXVaekVTTUJBR0ExVUVCd3dKU0c5dVp5QkxiMjVuTVNNd0lRWURWUVFLREJwQlpIWmhibU5sWkNCRFlYSmtJRk41YzNSbGJYTWdUSFJrTGpFWk1CY0dBMVVFQXd3UVFVTlRJRVpKUkU4Z1VtOXZkQ0JEUVRBZ0Z3MHlNakExTXpBd09USXpNelZhR0E4eU1EVXlNRFV5TWpBNU1qTXpOVm93ZFRFTE1Ba0dBMVVFQmhNQ1NFc3hFakFRQmdOVkJBZ01DVWh2Ym1jZ1MyOXVaekVTTUJBR0ExVUVCd3dKU0c5dVp5QkxiMjVuTVNNd0lRWURWUVFLREJwQlpIWmhibU5sWkNCRFlYSmtJRk41YzNSbGJYTWdUSFJrTGpFWk1CY0dBMVVFQXd3UVFVTlRJRVpKUkU4Z1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkJ3WWdLVndqQ1Y2K2x2N2ducEZFUnpVMnVORDhnZEVrUENOY3MvdkZEczJzSzQySnV4bmhGbklnTUIyRHlVMElyWElMamYvMlhUMFlTVGQxc1BpVFNhalV6QlJNQjBHQTFVZERnUVdCQlRuUWFycGRTdDRzaWQ3VmpmTklMSUhyYjJQb0RBZkJnTlZIU01FR0RBV2dCVG5RYXJwZFN0NHNpZDdWamZOSUxJSHJiMlBvREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURjb1hKM3J6Tk1BL2Zaa2gwOFBvRnJNeDQzR1lNaFpNZkxQdy8zTWZKcEdBSWdlY3RLd21KWU05SjhTWDh4L2FRVjRpR3ZLV29CZnIxWFBUQU1YT2hWRVlFPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFEQUFBQUF3Q0FZQUFBQlhBdm1IQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzUUFBQTdFQVpVckRoc0FBQWljU1VSQlZHaEQxWmpQaTVWVkdNZjlDOW9iNkRKb0lRaTFpREJ3STVRZ0VVRWx0QkowWVNBR0V1UkNGQk14SWtsQ2F5RklRaWFLQlpVb2xZN1FOSk02M25HYWNhNmo0MHcwMDR6Qk1CTzZMRTduODl6N1BmTzg1ejN2dGRxNStITHVmWCtjOC9rKzV6blBPZmV1K1B1dnY4TGpMRFBRR2g0TzdmSHgwR29OcDg5VnRhMmRuSnlzYVhwNkttbHViajYxMHZ6OFhGaFlXQ2hxY1duUnRMUzRGQjQrZkJnZVBIeGc0ck1Yakw2VkRoNDgyRFhRQlU5R1lqdmViaWMxd1F1NEJBKzRQcy9PempiQ213Rm40cjhvR1JCMEo5b2RKZmgySFg0cWdpSVA3d1U4MEtYb2UzQ0Rmd1I0SG5XSm1lcHBvS04yRFg1NnFwd3l0QURQejNVaTN3c2U2UDhMN2xVeGtDc0hSM25VQmMxbnFRVHU0YjJKRXRTL2tRSlFOeERUaGJRcHdRTkg2K0hWQ3BydnRNeENEaytlTHk1Vm9YdVpLTTJBbmk4YWFNcDNnNDVwWTIwR2o0QlZ2dWZSOTlHV1BFaEp2VkxIOTBNd3Nobm9IWGtCZTNndkQ1N0RNMWd2YU5RTEhGWGhGMjJNWkNDSFJvQjZBVm1DejlORnN0TFlOVkNDeWErVnBPY0VUbjkrakVZRE9UaUw5OStDbDlJRzVYQ0tlSy9JVi9ybzl1dkhLaHBRbVFTeUdIR1g1N00vL0JCbVB2c3MzTnUxSzl6YnZEbmNXYmV1cHJzdnZKQTA4ZUpMWVdiMzd2RDdvVU5oNGNLRjhPZk1UQkc2Qk8vQnBab0JiVkMrWEdweG90bHIxOEwwL3YwR012ckVFMkYweFlvdyt1U1RCanI2OHN0aGRQdjJwRi8ydnhkdWZmeHg1Um9hZis2NU1QYjAwNTEzbzlxclY1djUrNmRPbVNFUExmQ1NBUXBIeFFEUlZWdUplRXlWWDgrZVRkQzBkL2JzQ2ExUFA3VWpTSDkvdjdXcVpENElEREkzVHdwT20raVA2OXJsaHo3L1BBenYzZHN4SHdPQm9lazMzd3ozdi8yMllxQUVUMXN4NE5PR0J4RGd0NTkvUHR4OTQvVXc4Y2t4Z3h3OGNzUWlPZkxzTTVZNjk2LzBkUWFMVWZNcDRNVVlYS2ZONzVIWGpBVURocTYrK3FvRjZ0YXFWV0VtenFDZ2xicTBCSVYza2dHQjB3cmU4am9LNk5ZMzM0U2JtelpaeDdmWHJBbDNQdmdnVEF4ZHQzc01US2VhK2c1VTNZU1hET203M2tWQURyZGFZWGpyVmh1UGxKc2ZHckxyWWhObk1wQkhIMEJldXZYZGQrSFdLNi9ZMUpMbll5ZE9kRSt1TFh1ZVRqMkk1QUVWZFYzejkyaHowYWMwRXROelpQMTZNd0lUMXhnWGtZcVZHWkF3d0lPMjZDSTRFU0RmQndZSERKejd5azhHRkFpdHBPOGVOci92eFhoTitRN1R6WmdKc0l3ZE9KQm1BQlVOTEk2TnBRVTcvdTY3dGtoSkZic1hCMUdOSjIybTMza25sVWhLbzhvaWZkNlBwbFZhS1oxTHNWOEJzMGgvalFIU1BjYk13ZWxmWW15cW1pM3lqejZ5NzJSTHhRQVA4cUtWdUZnUmJwNCtIUVpqMU1seHJpZjRLRUJaQzNUb3hUVUFTL2NJQ0FzZVU3VjdVVW9Sd1ZzYkt5QnNBcmFzaVAyd1J0aXZLZ1o0b2IxbGl6MHcxTmRudWM1MUgzWGdpVENSMThBM05tNE13dzZLNnFUUHJiVnJPL2RpbjNhdFd5clRQUmFxcnNWblZCQzhaQ0NaaU04UHZ2V1dQWnNNQU04bVJVZnRreWN0OGx3VHZEZUJBYWFmdFVGRVdCZDBadWE3Y0dqa3FhZlMvc0MwbXpFSGE4VWdpcG5HQ0NKZGMrQzh0VDBvbXVmZGlnR21sdHhYSjh2Z25kT2tGcUQwMjh4dmR2eG1VWlZTQ21EZ0Y3dDVUNThVQTkybjVqTXU0aDdQYXExNUNaNnFRNkFtdnpobDc4TlpNVUIwV09VMnFJdTRvcDZMUmNtdW1kSWpVekxRUFVxamhRamhuMmU5RWJUZnYvcXFDQzd4SFhoYU1vUjNMMTI2bEJtSUY0a1FEL2wwVWQ3bjhFM2dFdE9NQWZxMldjUkEvTXdCMEs4RmlVVXNlT1RCVS9Tak9CSHcvdm56NTVjTkFFd24xNDhlczVRd3lJYkk4N3hGbm9FeHdUcUl4bTJuZGtDYUFhQnpBY2FSNU9kWXBsa3I2a3NwcEdqN1ZtSmpaYXpLREdDQW1uemo3YmM3RzFVRHZFVGRaMUFxRFA5bWNGRGoyRkV4RU1GazRJKzQ0RWdUaVRNVzF5bUY3TzU2aDd3bTJrQXpBL1RyNFpVK21MOTh1Vy9aQUdsaXBURk9EUytYRFBDY1BrKzg5bHBuMFBqODVKVXJ0aEdsdEhDcFJZVUJ2clF2a0RJWVNIMUZFVlVmOGFtcFpRT2N2UmhqZk1NR1M1OUtGUUtZU3NMZ2JOdVBtZ0YrakhnWUw5S2lhWDNvcE5sMER3TUdua1VlZUJZOHMvcjl1WFAySExOYk1RQVkyeitkVFo4NVV3SDIwWmY0SlphaUhqV3ljcVhCRTVrSk5zSzRpSFVQYUFCSkVXWWx2MGNxQXNXN0hoeFoyc1J4TUNCNG5pTjFhd2JRNUxadDFqR2Jqd2N1aWZWQ0pBQ3pUcnNBV3FoODU1NmtVeXpQOEIwWXFRWWZVMU1uWVV1YmFQeml4WXNHenBpVkdjakJ5RTllcEVhVDMvbDloR21KSXFBS2s2dnBTS0NXZGFCZmJEazRsWXdGQy94UDhhY3MwQVNCZGppMnhSbEFYS05lMjNFaFRqRUx2UEo3MVlrYVg0T09jRUF6UTVMZ1U1WGh6d09uZS92MnBmRXdJSERTaTdMSmJ3Tm1UU1lxQmp5NE4wSmsyWjB0MTJQSDl1T2IzNnNONEJMd3RJTDJFYWYxYWNJWmlCU1oyTG5UOWhOTHFhTkg3WkRJdUJ5amxXNEdIMU1OZU5yR0ZNcEZCRzhlL3JEejY2aTc4REREYjFhT3lCNmVaeTF0M0ZGWUFqcHYwZFV2ejFrQkVEVENXTi9YWDF2SnhBRFFFdkExQTcyTUtGMFlsS204ZnVoOUd5enRvbEZzaEt3Wi9aWW1KZGl3dkRoSkVtbEUxTzJFMm4yZnZraVgvdVBIRFZyZ2dPYVJMeG9vUWF0TmNvdVZ5S2xqSFF1SW11VnJCSlBJYS85ZDR0bXJPM2FFSHc4ZnRsd0htQ3JERGl2QWxPL3hCNHl1U1J6NUg1bENUZkJlV3F3eXBDZ1J2WkxJWlNEUndPQ2dpZWNWREZwSnNGNkE2M015QUtEYUduaFVMM0JhNVRqU1FrVjVybnZaMy9rTzFndTRQRjJRNEFsRVpRWUVua2VlS3RSVTQvTktnL0lxa3g4SkpQMHpWNEh1YmxBRzNnTWVZWUMyWmtEZ2dzK2hVNFhwaXUrb1pNQWJFYlJhRDk2Qlg5NmNlc0VyOHZwY01mQW9lRW13QXZjMVh2S25TSzg2K0hMT0czZ0IzdjZQNmdLcnhRVFhpd2J5RFVxcG9xakxnSWRIQUtyTjFUUGZJelNSTDFXYUVyeGFGbi9OZ0FmM0ttMUtPVHpmYzNDVTU3dWlUaXZRa3BvaVR5dFZESlRBZ2JQSVp3WUVEMkFUdUlDYkJKVGFYTDNndVZjemtJTXJiWkFIeitIejFnczR0UWFxeUVjZysvYzVTeHN0VHI5STFRNE1EQ1pvcjBZREFzOXpIbFdpMzNPeGx2TWVLTFVsK2VpVDU1MjJtanBTTXNDSHgxTUh3ejhjZUh5N0VoUno1UUFBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTEyLTE1IiwidXJsIjoiaHR0cHM6Ly93d3cuYWNzLmNvbS5oay8iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkFDUyBGSURPIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDIyMTIxNDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTEyLTE1In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMC0xMCJ9LHsiYWFndWlkIjoiZTFhOTYxODMtNTAxNi00ZjI0LWI1NWItZTNhZTIzNjE0Y2M2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJlMWE5NjE4My01MDE2LTRmMjQtYjU1Yi1lM2FlMjM2MTRjYzYiLCJkZXNjcmlwdGlvbiI6IkFUS2V5LlBybyBDVEFQMi4wIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEwMDEzLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sImlzRnJlc2hVc2VyVmVyaWZpY2F0aW9uUmVxdWlyZWQiOnRydWUsIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJ6RENDQVhHZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQmlNUXN3Q1FZRFZRUUdFd0pUUlRFU01CQUdBMVVFQ2d3SlFWUkxaWGxEUVRBd01TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1Sc3dHUVlEVlFRREV4SkJkWFJvWlc1MGNtVnVaQ0JEUVNBd01EQXdJQmNOTVRZd01qSTJNRGd4TVRBMldoZ1BNakExTURBeU1qVXdPREV4TURaYU1HSXhDekFKQmdOVkJBWVRBbE5GTVJJd0VBWURWUVFLREFsQlZFdGxlVU5CTURBeElqQWdCZ05WQkFzTUdVRjFkR2hsYm5ScFkyRjBiM0lnUVhSMFpYTjBZWFJwYjI0eEd6QVpCZ05WQkFNVEVrRjFkR2hsYm5SeVpXNWtJRU5CSURBd01EQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBSmNXcWVDeGdhOUtKYkZPMlRaZGpjZ3J0WkFnZmk4VFhLdSt2NWxjUjVjZWI1R0pZeHlvQ2podWVFU0wzZGRtTUlrcEd5aHNFRXRmRlV5QndzeUZWQ2pGakFVTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0NnWUlLb1pJemowRUF3SURTUUF3UmdJaEFMNFRiUDAwc0VOYlRFWEdvYWdNNkhrbDJYSURyeGdLYkh3b3cvOUdpYllUQWlFQXVkSW03RUdxZnlhOFF5Z0tjYmtRZnFyd2VmWW5CdlpLSTB4d24va0tXeDQ9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUpZQUFBQTlDQUlBQUFEQXVBZVlBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFCR3VTVVJCVkhoZTdad0pmQlBWOXNjelMvWTAzUmNvM1hjS0JWd1JCSGtpVDU4THF4dkNFM0F0b0lJQ0JRVFoyZ0l0VWlndFZHaWhLUG9YQVIreXlQTGhBUlpaMUVkVm9Qb1FwS1cwQlZxNlpjOWtsdnhQTXJmUWxpWk5sN1FQUC9sK0xuVG1uRHVUeWZ6dXZlZmNtMGt3czlrc2NIRXZnNk8vTHU1WlVDLzh6NEJuTkw4V1lZU0l0M1k3SEdzSWVINU0vTTRzdE8vQ05rakNzd1BIYW4vNUhSZi9yMGpJNmd6KzQ1L3QvZmthdE8vQ05tZ2d4WGh3SExiTU5HTTIwZDFUYUVhQVd5NER3ekc0RXY3YVhOZ0g5Y0xDUjhaQkw4VEVJalBIeVdMQ2NZTG8ralFIcERQVHRPN2lGVXhJY25xRDM4dlA5dDZXZ1h3dWJOTlVRcEZRUURPRHE4OFNjaG52N21Lb3lsdW5BdTRubFo0dUNSMm5lVVlLaXJKYVBkcnBjamlkQVcyNWNKZ1dKeFZkUFlRMm9odGYrbDdGTlMrODUrbE1DVm1Ea1RPWk9CUEYwVFNIYkM2Y1RxZEpxUC92bGU5azBhZjhIanJwKytCSlpUK21waDQ1WERpWlRwUHdZdUlDQWhlYldWYkFtVm1qb1dTeGExYmVSWFNPaFByaXN0b1R4M0dGRENNSWpNQUpoZHYxVGR0cGpSYTVYVGlUenBIdzhyU0ZCT21CWVJpck4zSVVJeUF3QVUyWExzNUViaGZPcEJNa05KVGRxRDU4aEpCS1lFTHBOLzQ1NWNOOXpSUk5LT1RsRzc1ZzlLNTVudFBwQkFrdlRWOU1rQW9CSm1CWVRWVFdvckRVT2JTeERvWlRqakplUzNaOTFPQjBPaVFoek1NTjE2dXE5eDNDWlZKT2IvQVpNVUtvZFBNWWZMOGlLcDZqYUZJdUwxKy9qYU5NcUxZTDU5QWhDVEdCNE1yTUZJSVF3emJOcUdKeVYvRDJ5RFVMR0dNOWRFVElhRXJUTi9KR0YwNmlReEpTbGJlcWR1NjNkRUdEMFh2SU1HbElJRy8zZWVadnNzZ1ltT0FMWmZLeU5ma2N6ZkIyRjg2Z1F4SmVTVXJEY0VJQWlTaXRqdG1ZaXF4V0lsZk9aUXhxZ1pCZzYyckwxbXkyMmx6cm4wNmgvUkpTMWJWVm4rOGw1RkxPU0hrTUhDU1BpMFFPSzc3am5wS0ZScHBOREM1VGxHVnNaczJjZGR4MTBmbTBYOEtTaFJsbU0ydnBnaWIxN1NqWW1MQzBKTWFnd1VqQ1ZIbXJZdDFueU9xaXMybW5oSFM5Nm1iK0xrSXVNek9NY3NBRHNxaFFxcW9hUXVQdFlycFY2L1g0STlLZ1lBSExFVkpaK2FwYzF6RHFKTm9wWWNtU2RXWVREVGtuUnBMRzRyS1RudjEvQ0I3eVE4alEyK1ZNME9BeklZOHlLcTJBd0hFaGFhaW91TDdwUzNTd2kwNmxQUkl5V3YzTjNPM1doek1zejB5WkljNlJKQ1lTTmk4RUFTa01WSUJhcEZSK2JjVW42SGdYblVyeloyZWdiejFTZWtMazc4dTdXK1RTZTB1dlpYMUNrbTVvSDRIaE1nbklCVnNnS21lZ21xV2dORlBYT3ljek1QRVZ0TjhTaHVMU014RkQ3bjUySmpkdlMwSEJDWWxZcktlb3BZc1dSa1UxU1oyYWtaeVMrdWVmeFVKU0NOZFNyNnAvOElFSDVpYk5ycW1wZlN0eHVxZTd1OUZrSERqdzRYZW1UZDI5WisrT3IzYkk1UW83bWJLSk52VkxTSmcxYTJaeGNmR3NPZk84UGIwNE0wZVFSTzdHSEZURE5ucTk0ZDBaTStGTzRCaGVXMSsvTVNmYjE5ZmVYVzAzSlByck1HYVc1ZXJVUFY1NndkckpHb0MrSmlLcnZ0d3ZFQWxCUUZ3czloMzNwT1dKd2taM2h6UFJoait1b0owMmN1SENoZjNmSHBETDVWcWRidVo3N3lCclN5VE5uYjhwYjdOY0pvY3JVcW5VOGZGeHUzWnNCenRGR2ZmczNSdmc3Ni9UNmlSaUNWait2SHhsNy80RG5oNGVadHNhR2cxR3lnUnRVUkFlSG42aHFFaWoxcEFrV2E5U2pSazkrdWwvUE1uWHNjWFdyWi91M1BtMW05TE5hS0R1RzlEZlNmb0JiWllRbEl2ZHRocnROT1ZHL2c1UzVHNW1XRExRSXk1L0ZiSjJCaUt4V0NxWFFXRUZITVJXWkwyTHVmUG01K2JuKy9qNmduNXdvL3NQU1BqK3UyTzhDN3FDVkdvNUEyYzJ3OW5BSWhUQzZHNngySkVRdzNHUnhLSTNrSmFhTXVYdFJIOFBkNXdrbDZlbHRTb2h0Q1JQSDIrUlVLalJhRk5TbGlDckUyaGJMS1FwMDlYbDYwdFhiTGlhbkZYK3lkM3BTY085WUZtMFlRV3NwYXR5cjZabWw4S3hHVnRzM3JDT01XLyt3bzE1K2Q1ZTN0YitwNHFMaXI2dFg0dm85THFheWx0VmxsSnRwNmpyVlh6OWNjK1BWY2prTE1lS3hhTGZmdis5c0xDUXQ3Zkk5cTkybEpWWENJVkNpcUw2RCtqMzhFTVBJWWNUYUp1RUZSbjVseFlzdnZMaHFvdUw1cEV5UzF0MkJBaVBkRlhOSHdzL3VySmcxYVZaYzI3dE9ZSWNuY2VDaFIvbGJNcjE4YkhxcDFaSGhvZWZLRGlLZkRhWTlmN00ycHFiWlNXWHltMlhxaHVsWDJ6YmlnNkFWNWszUjFXbmdwZFFTR1hKS1N1UnRTWFdaYTlYS09Ud3h1dnFWUjhtelVGVzU5QUdDU0VLbG1ma1NXUUJoRVRxSHY1Z3dLdGprY01Cd2xMZWw3Z0ZFUW8za2NqdnF2V2o0RTdzaS9NWGZKU1ZzOUhYMXdkdXJscXRqb3VPUG4yeUFQbHNJNUZJUEQwOWxlN3Vkb3FIaDRkQ29VQUhDQVRUcDAvRE1ZempPSkZFZXVyTXFlTGlFdVJveXNGRGh5LytjVmtvRXRFMEhSMFI4ZFJUclF5NUhhUU5FcFpuZldhcXJoSUlDY2FvRGt0dFU4c3lFMkp4ME13cHJGYU5TVVRhYytkcURwM29yTlcySlV1VGN6WnU4clBHUDdWYUE4bHF3ZkYvSTErTFlCMXFQVysrOFpwR3E4TnhUQ2dVcDZWL2pLeE5XYnMyU3lhWHdmVkFQSjcxd1F4a2RSb09TOGlaeXo3T0phUUtzNG1SQm9jRnZQd01zanVFUmErZzJhOFRDcVdBNHdpUnZMTWVqbHF5TkdWdDlub2ZIMHYvMDJnMDhiR3hKKzNHUHd0bTY5VzBsNlNrT1NhakVXWmlrQnZ0UDNDZ3RyWUdPUm80ZmVhSHM3LytBdk1maG1FQy9RTmVHZjh5Y2pnTlJ5VXN6L3ZTV0ZHT0NVbmFvQTViMHA2V0pWUXFBNmUrd21vMW1FU3MrcW13OXZnWjVHZ3Z5OVBTSWVUNGVGdmlINlQ3MFZGUlI0NGNSRDdiZ0g0ZGtkRERYVGwyekNpWTgrRTRUalBzdXF3TnlOSEEycldab0I4L0pDUW12b1dzenNRaENTRy9MRnU1MGRJRmFVWWFHTlJqeXZQSTBVYUNrdDdHWVNvTkhWRW80eU5pTzhBSnl6VXZYNW0rS24yMWw3Y1hURW1oLy9XT2l6MTI1SkNkK2NadFlCVGxCOUtxcXFwZno1MHYrdTEzTytYOCthS1NxODBEM3NMNTgzUmFMWFJFU0ZpMi9kK1hFUENRUXlBb0t2cjl1KzlQU3FWU2xtWGRQWlN2VFptTUhNN0VJUW1ydG42dEx5bUI0WjgxYUVJK25JYXNiVWZzNDlWenlnc3N4QktwdVA3NzAvV25MWGw1bXlJVFpCTktON2ZzOVRucHF6TzhmWDFBUHhORnhjZkZIVDY0SHliZHFKSmo1T1p0R1REZ2dVRkRodzBhWXJQY1AzRFFqUGRub3dNYUNJOElmMnpvRUNORjRRU2hVcW56Tm05QkRvRWdNeXNMalB5by91cUVDZkl1K1lLWVE4MjJkSG1PVUNJM000dzRvR2ZQdCsydGtMVkswUHhFSENiTEhJZVQwcEpGYTVIVllXUlNhY3J5dE9RVks3MnQ0NmZBYkdZb1UrN0dISmlCb1JxdDBqQ01LdVFLSDM5L2Z6OC8rR2VyQlBqN1FWYUtEbWpFZ2cvbnFWVXF6Q3lRSzJTYjhwQ0VwZGV1SFRod1NDNlRRY29xa1lpbmRja29DclF1WWVYMi9mckxsd1VpRWF2WEJzMTVneC9IMmdlMEJrbFBmLytKWTFpdEhwZEo2bzZlVUowdGNqd3lXVFREOENQSGpya3BGTkFkZVF0R0VuT1M1dk1WSEtLaDF4dU5ocnE2T2xWOWZYMWRuWjJpMTdYd1FQUEREejJZMExjUFJadUVwTEM4dkdMM045K0FFY1lHbW1VZ1JtcDF1ckdqUi9uNStmR1ZuVTNyeTl3LzluM0srT2MxRE9LTVREcXc3Q1JwWFoxcWtXTllDS24wZ0hncDd1VS84SkxOek5CUVd2Rmo5SEJjSk9TTWxPY1RnL3NkekVjTzI4dmNzNVBtZmZIbDlzWlROSlBKUkp0b3lOMUJ4cHJxNnBSbFM2WlBUVVMrbHJoNTQyWlVYTitBSHY1NnJXN1VxSkVic2pOUG5qcDE3UGgzTUR0RU5WcUNwcG5JaVBDWFhud0I3VGRpejc3OXIwNSszYy9QMTJnMHhzWEU3TnZ6cjlqNEJNdFh6REZNcjlPZFBIRXNJandDVlhVeXJjU1A2L203Nm90T2tRSXZScUNPbVo5c1J6L0FMR0F0MzlObm9EUlpZR3VHTkNUUTc4V25iMzcrTDBJcXUzWG9zT2I4UmJlRVdPUnpESzFXMnljK2Z0alFJWm1aMlVvdkQwOHZyMlVweTBjTUh4NGRIWVZxMk9aMjZIMTA4R0FvYUtmdGpIcnUyZUJlZ1JxZFhpd1dYeTR1SGo5eEVzMHdrTWpBdFQwNTRnazcrakVNdS8ycnJ3SUNBbUJJMFdnMUpwb09DdzNwbDlCUEpISTRGalRGM3FnSTd4YjZaVXhLV2xUNmd0amxLM3JPZkIwNWJDRDA4aFg2K3dnRGZFbGZMMlN5UWNqaUdlTEFRS0cvcjhTdlYxbkduWFRBRWVBZUJRZjEydi9OMXhDUSt0M1h6NkRYd3dBaEVncW52TjVGc2VjMjc3NHpYYVcyckxjUk9GYjQ4OCtnSHd4cERNM01uUEV1cXRFU0pHbjVIWU9SWTU1L2R2U1ljK2ZPVXhRMWFzd0xVYkc5WVVoQU5kb0tuQTQ0TzNEc2QrTFlBcmUrOEQ5MXM0bzNRbGptTnh5aFdWWEhqNFJYdVYxWmYrWHFVVUZRZ1RMaE9CbjEyOFQza2RWc25qVm5ia0N2a01qWStLQ3d5RUdQUGdadm03ZVhscFVGQm9lRlJjWkV4TVo3Ky9WWThORmkzbjQzTjY3ZlVMajd3Qmw2OUFxZE92MDlaTzBZMElGQ3c2UENvbUlqWTN0SHhNVER5UU5Ed2tlTkdZZmNkb21LNjZQMDhyMTA2Ukpzbnp4MVdxcndDSStNTlJnc2l3WnR4VjR2dEtRUER0T3NhcHVTRkFjcncrVkMvRnVYbVNFU29kL0hDZTdWS3pWNWFYMjlDbndlbnA3WjJSdCsrczlaM3RVRkNFbnl0U21UTkNvTmJGdXpZek5vOE1GTXg5YzlNTXBvK1RBeU5qYkdUZUVHZzJwNVJUbnZxS3lxZ3Y5cnFtc3F5cEVGS0R6Nzg3TGsxRzJmZndGNUFESlphVW5DMitHaTYybjFwVEV6aGpXNTVrbXYvblBFOEwvcE5GcG9DUjVlbmhQK09RazViTkd4TmRKbXZQZnVPeEtaR01ZUjJJWTcyN2R2bjZGRGgvQXUrNkJyc0xaZXZWNW5OQmtKZ29RWlRsYjIrbERvMVBIOVB2MXNHL3hOR1BBUVRER2hEblR1RjErWjhOTExMMzc2MlJkZVBnR05XMm9MRWxwK3RxZTdhTzJsNFozRHlJdDJHc2pmc2xrbWs5RTBEYk5EbFVyVFNsRHMyQnBwTTl6ZDNVTkRRbG5XRWdvZ1NNOThkenB5dEFaY0E4akhUMmNYTGxpc3JxMmJOSEdDbTVzYnhOZVE0RjZFVUxoOTU2N25ubnR1MEtDSHdUaG4zb2Q3djltN09qMHRKaXBxUzk0blFyRjQ1T2c3SHhNMWw5QU1OOUZ1MnVsVU1Nc0kyZVk3TEpOSmN6WmtxMVFxdUkvdTdzb2R1M2J0UDJCenNkUnk3OUJtSjNEMDZQRno1eStBRXRDQUlzTWpSbzhhaVJ3T0lKZkxaOCtiSHgwYmYvSFM1ZDI3djE2NUVqME9iMm1PRkpXMVp2Vm4rWG43OXV4bWFQcmJBd2VVM2w0OUEzdUNOemc0Mk1mYlM2WFduRG1ERnBtYlRpcGdrQ0xJSDhNZkU5elYwcnNDR09MZzlkMlUvRE5VYmVMdkk0WlBHUC9TamwyN1FVTEkxeWUvOXNhMWtzc3lhUXZyVzVaK2JOMVl0eTQ3ZFdVNjFMZnV0WXlSTWo0K2JOaldMWGxvL3k1V3BLZDdLSlZtZ2FVTExsMjBFRmtkUTZmVlphL0pDQWtOUWZzTlFFT0U5dzlobGQvVjZRMFVSWU1GSnFDOEJhWXhrQVJURFJHeFNTKzBKQlk0eHBsb2ptRzdvZENzNVFGK2pHaGZOOGxlbHhrWTRBL0pLZzV6RExGNDdMaFdQdVZoT1k2R0dRREwyaW5ncHBzK1JOS1l3c0tmZi96cHJFZ3FnWG85L1FOZW5UZ1JPVnJpME9IREd6YmMrWklYTkZOb1NUcDlDNy9TeExmZzIwa2VOTEllOEw1TXBxdFhyL0lXUGFqTHN2MFQrdk83U0VLWWoxdVVvMHlXMzdKajJPNHJjQmttdUF5T3NWd0dmMjBBd3pDUUxKZ2dpd2V2N1IrSHk5K1NCMDBiV2l2a2lzY0xDckxYMzNsVUVKcTJDUTYybk1NRVo3TllPRFByQUh5cTBpSXIwbFlwbFc1d3A3VjYzZVRKayt3c1BVSWZoU1kxZlhwaVFjRUpaTkdvb1lsVVZsYnl1NDNSNlhRbUZoclhuYStETFZ1OGlNRHd6TXhzMkQ1OStvZVNQeS9QVFpydDRlbk9lOUVDMjRXeGlicWl5ekNSNTYyT0EyL0E1aDF0eldzSHprRDVqQndldFFZTlRhbkxWMzZ6ZDU5VUtvSGhaZk9talFrSmZYajczYXhhdldibnJxOGxVZ204cjVxYTJ1K1BIZlgyc2F3elZGWlZQdjdFUDd5OXZZd0d3OTlIakVoSlhySmx5OWJzbkU4VWJuY1c3ZTRHK3ZTZ1J4NVo4M0U2Mm05RWNYSEpmUThPOVBIMUFZMmh3NXd2UEN0WHlKR3ZKZDZiOFVIUmI3L3QyN3RicjlPKytlYTBHN2NxaFlRUUo3RFJJMGQrOFA2ZGVjalNaY2tIRGgzR0NjTFQzWDNhMU1Sbm4zbWF0Ly95eTYvTFY2eWtHQVlYWU9OZmZySHhtcDlGUWhDeG9kZisxWUQ3QytNcTJ1bFUzbmhyNnJjSER5b1VDclZhL2NacmsxT1RseUZIbDJPVjBOcGQyb2Y5WXp0eTV2OWxidDJxam8xUGdHa29ETkFtaWlyODZVeVhmUzV4TjVZVzJwRzdiUC9ZdjZSK3dLcU1OYVNReERFTThoRVk2N3BSUHdERlFoZU9ZekFhd3lPaVpkWlB2aUQxT0gzaWVIaDRPTy9xRnB3U0ovN2F3SVFTa2trSXNhRGxzS0ZEdWxjL3dOVUwyMHl2MEFpUlNBUVNxdXBWUnc3dDY5OS9BSEowRTY1ZTJEYlNWNjJ1S0MycnE2Mi9YbkdqVDUvNGJ0Y1BjUFhDdG5IdTNIbWFvYUVMTWd3YkZocml2SytjT1k1THduc2UxMEI2anlNUS9EL2V4TGc4Ui80c1FBQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkQmxvYiIsImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiZTFhOTYxODM1MDE2NGYyNGI1NWJlM2FlMjM2MTRjYzYiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2Ijp0cnVlLCJiaW9FbnJvbGwiOnRydWUsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6dHJ1ZSwidXZCaW9FbnJvbGwiOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwiZmlybXdhcmVWZXJzaW9uIjoxMDAxM319LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTEwLTA5IiwidXJsIjoiaHR0cHM6Ly9hdXRoZW50cmVuZC5jb20vYXRrZXktcHJvLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMDA4MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjEuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTEwLTA5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0xMC0wOSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjMyNTI2ZjczZGZjYTEyZGE5YzFkODdkNmUwYWRiNjRlODQzZjczZGEiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMzI1MjZmNzNkZmNhMTJkYTljMWQ4N2Q2ZTBhZGI2NGU4NDNmNzNkYSJdLCJkZXNjcmlwdGlvbiI6IlRydXN0S2V5IEczMjAgVTJGIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MjU2LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ3BUQ0NBa3FnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQnJ6RUxNQWtHQTFVRUJoTUNTMUl4RVRBUEJnTlZCQWdNQ0ZObGIzVnNMVk5wTVJNd0VRWURWUVFIREFwSFlXNW5ibUZ0TFVkMU1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFpWZENUU0JEUVNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SGhjTk1UZ3dOekF5TURVek1UTTVXaGNOTWpNd056QXhNRFV6TVRNNVdqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRSWZxSGlzaTBvTy9leU9xU2FEcnI5aXRHMkl5bUJrSG5TREdRSUlZbVQrdnFBOEFnTzgxbW9tYzJMZDVQR3BFTjZtdUU1NHdQSFFqdmMveUNpaDh1Mm8xVXdVekFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUIwR0ExVWREZ1FXQkJTM0ovZnhpQXYyMmlyZEJzOThTT0RoRjdrVS9qQUxCZ05WSFE4RUJBTUNBUVl3RVFZSllJWklBWWI0UWdFQkJBUURBZ0FITUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEYzQxTEZLNExKQ0JVMlZWS0l6N1o2c3hQaFVFa2g4bkxTTEs2SVhka1A1d0loQUllS1ZPWmNoYVZPNWFGN2ZiZFhvU3JjeXkxWVllVWVQTG9qY0tJOWZYODQiLCJNSUlDZ2pDQ0FpaWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakNCblRFTE1Ba0dBMVVFQmhNQ1MxSXhEakFNQmdOVkJBZ01CVk5sYjNWc01SQXdEZ1lEVlFRSERBZEhZVzVuYm1GdE1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFWk1CY0dBMVVFQ3d3UVEyVnlkR2xtYVdOaGRHVWdWVzVwZERFWk1CY0dBMVVFQXd3UVpWZENUU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdJQmNOTWpNd056RXhNRE0wTmpFMFdoZ1BNakEzTXpBMk1qZ3dNelEyTVRSYU1JR2RNUXN3Q1FZRFZRUUdFd0pMVWpFT01Bd0dBMVVFQ0F3RlUyVnZkV3d4RURBT0JnTlZCQWNNQjBkaGJtZHVZVzB4RnpBVkJnTlZCQW9NRG1WWFFrMGdRMjh1TENCTWRHUXVNUmt3RndZRFZRUUxEQkJEWlhKMGFXWnBZMkYwWlNCVmJtbDBNUmt3RndZRFZRUUREQkJsVjBKTklFTmxjblJwWm1sallYUmxNUjB3R3dZSktvWklodmNOQVFrQkZnNXBibVp2UUdVdGQySnRMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkFoK29lS3lMU2c3OTdJNnBKb091djJLMGJZaktZR1FlZElNWkFnaGlaUDYrb0R3Q0E3eldhaVp6WXQzazhha1EzcWE0VG5qQThkQ085ei9JS0tIeTdhalZUQlRNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3SFFZRFZSME9CQllFRkxjbjkvR0lDL2JhS3QwR3ozeEk0T0VYdVJUK01Bc0dBMVVkRHdRRUF3SUJCakFSQmdsZ2hrZ0JodmhDQVFFRUJBTUNBQWN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQU5WbkpkZS8vdEJMcThNRERpK1NBZDZVZFlJWlNuZzRQTXFteU5ydlpqNjRBaUFYMHhTekFoRmFDQ3AvdWhwVmdubEYrWEJncndBSXNvdFpHVEI2cmtCMzFBPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBR1lBQUFBN0NBWUFBQUNKei85TEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFBeVpwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTVRFeElEYzVMakUxT0RNeU5Td2dNakF4TlM4d09TOHhNQzB3TVRveE1Eb3lNQ0FnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSU1pXWTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpWSmxaaU1pSUhodGNEcERjbVZoZEc5eVZHOXZiRDBpUVdSdlltVWdVR2h2ZEc5emFHOXdJRU5ESURJd01UVWdLRmRwYm1SdmQzTXBJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPalkxTkRZM1JFWkdOVEF3UWpFeFJUWTVSakV6UmpWQlJqaEdRamd6T0RNeUlpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qWTFORFkzUlRBd05UQXdRakV4UlRZNVJqRXpSalZCUmpoR1FqZ3pPRE15SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk5qVTBOamRFUmtRMU1EQkNNVEZGTmpsR01UTkdOVUZHT0VaQ09ETTRNeklpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TmpVME5qZEVSa1UxTURCQ01URkZOamxHTVROR05VRkdPRVpDT0RNNE16SWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejZYcUFTWEFBQVFjMGxFUVZSNDJ1eGNCMWhVeHhZZWxrVjZFUVVSQlNuQ0xrUVRqZTA5RXhFRk5TOEdFOVRQUkkxR0FSc29kb29STkFJV0VEVVdGTEdpYU5RazFzUmd3UXFhS0lqUnA5S0xZaERCS0tFcUxPOGNtTTBiTGhkMkYwdFVkcjd2ZkhQdjdOeTVjODgvWjA2Wm1WVWxyMEd5TkRPM2E2MnZmeGlvK0hIeGsxdEVtWWpLUHd4SUs4ajhnTDRHd3VzL2dNUlpkM09MV3pvd3F2OGdLUCtDN0NlZ1VkZ1BmWDE5VWxsWnFRdlhPaUExeDVVUzgrb0IwWUVzQkdnR3Z0L2MzTHh5ZS9UT0hGMDlQYzEvOSs1alZsMVZKWUh5ZjRIVVhHbkp3QWhlTVNqL2dReDFpTGVxcXFySzNQbnowbjgrRVNzNXNHKy9iV3BLaXBuM3pKbnB0RStSVUZjb1Q1dUR2c3ZVQVFvSGVsOHBNWW9EWWdUWkdxQXhlRy8vam4zSjl1am93clRVVklzRnZuNGtOemVYZ09RUUFLbHNzSk9UMnYyOCsycFFiUzVJelNvWm9DRFFrVUJtUUVsQXZVOStZVld0QkVZK1VNWkJ0aHFvamJxNk9sa1NISHhuMEpEQm5aY0dod2kvMzcrL1h0MXBYbDdrRXhlWGxLRWZmU1NDMjFJZ093RG5MZzhnOVlCbTBtd0FabzF5S21zYUVBdWdXTGlNUmxENmZ2QkI0ZFZyMSs1cmFXdUpCdzkwYWdBS3BzMlJrVVNvSmhTNURCdDJIMjYxZ2RieGdJSkEzK1lCQlZNUS9ONVJLVEg4Z0toU3hSNk16TlhSMFNGck4yeTRKUmFMN0FPK1hraE9uenJWNVBNOWUvVWkwVEc3QzNwMmY5KzRyQlNGaHJpQzFCd0NobHZBOVNhZ0lUSzZjQkNrWnJoU1l1cUQwaFd5UzNUcTBuYjU5Tk84MzVJU0MvUHUzYlVmNU9Ra0V4Uk1WNjljSVljUEhqSU9DMS81MzlxUkkxQmQ1N3pyMWdKcU5IQkJ5UUlhQnZRN1UrWUtJQTVUU2t3ZElCclVTVVJuVVdoa1pGUzFkY2YyZEUwdExiSGZmQitTZVBXcVF1MmhUM1BxN0pscVQvL2dnc0xlWDFhbzZocGFjcXBVVXgwVENOSlJCa0QwaHV2THpQZWdYcktIMzBwYXJNUUFLUDBnU3daYXFLS2lJblR6OE1nK254QmZFWGM2VHZ6eDRDRUtnNExwdzM3OVNQS0RpdlNLSWJOTWVFQzVqbjRPTUgwZWdvSUZrUDhHV1FSVEI2MjBKUzFTWWdBUVBjaENnYWJVM2x0WmxZT2ptUGVvcUtpekwwZ0ptTUlLdDJuU3ZqM3hYUmhRRksvYm95YjVRWGxienMrVlFOOEFoUUVRVlR4R0FmWW5CWnRocEFyTjU2UVdBd3lBOGlrZG9hYXFRaUh4OGZWTkd6TjJqSGw0MkVyMTZKMDdpVVFpVWF3VEtpcGt6Tml4a2g2anZkSzNwRHkxZlZwZHc2MXlEbWdTTURsTmhsK0Q0WjE5ck1vQzZnUFBTZDdxcVF3QU1RRTZBSmVIRUpUM3VuVXIvdTNxbFJ4YmthM05rRUdEMUhkczM2NHdLRmJXVmlSaTUrNzhoLzA5eXlKdVZYSkJlVUlsY29Bc1VPaVVoalk0RzJmckNlVDUxa29NZ0lIMUpnS0ZBeGxvYW1xU3BjdVgzK25uME04bWFNa1NWYkNpRkg0eFN0clVhZE9xakFhTnk5bVRXbVl0cVdsbzlnSk5CMmJmVjZSZGFsYWpCYWRKaS80Q0VpdmF6bXN2TVFCS1o4aE9BMjFGVUJ3SE9ENjhjaTBwWDFJakVROXljbTRXS04yNmR5ZVJlMy9JdVc3M2VmWHVsQWFnNUFPTlFGK2tPY3lFWjdJaFc4d1VZY1I2N1Zzak1UU0lPSWQrcEthQmdVSE4rbzBSZHpwWldOaDk3ZWRQenA4N3AvREx0TFMwaVBlYzJSV1ZQVndManFhWG1QTlVpUUx5QWVZK2ZwNlBBcWxSbzdHekxreXhDN1I3N0kwR0JrREJTTzBXb081NFAzTFVxSHRCSWNGYWUySmlETU5EdzBoWldabkNMK3J2NkVpK25QTjF4cVpzRFlzbmxkWGNkU0RVSDVPQmNXZGYxSWNCT0gwaHU4aDhZeTcxYlVyZk9HQUFFQzNJRmdITlJUWFEzdFQwMmRidDJ6SUZBb0VJVGVEcnlja0t2NkMxb1NHWjc3K2dPS1dqUTFuOHZUSVRIa2N4RE0xZ1lGakZpLzQ0QUdlVDFKeW5LUno5bnpjS0dBQmxJR1NiZ2F6UmZKM3E2Wms1WTZaM3U0ajE2N1UzUm13azFWVlZDamZ1T253NGNabzRPelV5dmNhMnZLcUJ0WllJNUFHTVNuNVpId2ZBR0VCMkI2Z2RNeEI2d0R1dnYvYkFBQ0N0cWJXRlZoZXhzYkVwM2JFcitrRmVYcDZWbjQ4UHljeklWTGpSRGgwNkVMOUYzeFNlVnVzaXVGbFlZY2o1dVJ3b0FFTXFyMkx0Qk1EQktIUU1VL1FyVU4vWDNiZEJZTkMwdEVQek5TQXdNTlYxeEhETDBHWEwxV0oyNzFiY3hCTUl5UGdKRXlUMnd5ZG5iRXVwdEtscWFBTmpGSE1LTUNYelZYNGtnSU5LZnloVE5BMzZzT2wxQjhZTlRXRTlQVDJTbUh5dDJHdWFwOTZKMkZpRkd4S0p4V1J1d0RkNSswck5ESEtlUE5YbS9QeUlXbmpSd0pBYW9reHlBWU42QnEwaEJ6ZDM5NXloTGk2ZFJycTZrcG9hK2ZqWHFsVXI0amw5K2xPdC9xUHpEcVNWV3ZJODloMlFOd0R5VU1sdUJaVS9icmlETEJtVWZxdnpDZkVabXpaRVdNczdsYTFjdmFybWlFYWZxdnNsejlRNFAySG9mU29BOHJPU3pjMzAvTFB1NXVKUzdRcVVFdmNKRTl2UDgvV3BhdHUyclZ3TmJJMktVbkd4MHNyaUZDZFJuMEVKeWdzSXlTeEZSeTgxSlVYcmw1K1Bad1lzWGlSWEE3ZHYzU1pGNXc1WWQ5QlZLMmVLY1NYVFhNbmVGK2RnT21PNENYZXpnQ0dRN3psMW1vazhvUmNNYW00L2VDeHI0UTFWZGxFTHZXNkhsNlhzcmN3NzRjanhJblZiYTlIMEhaR1ptM09HVThlRjFHM28wS2ZmaW4yWkFmVjJjK3JaUW5ZQ3lJQVdlVUdkR0NqSFZWRmNkT01hTTRWQTkwamRja1FVMUwzSDB6Lzhmb3d6YXRBaURKZDBnN29Gbkhwb0ZNMEMwbU9LZytzRk1XRktRM00ycHJLeWtrejM4bEpkRWhKTU5EUTBaREtwdkx5Y1JJYUdXSDVpclp2TEZIOEk1UDRTQjFVMmtCRmxPdnBpL1hqcW9KZmZpVEpjbithRGVlcE5wdld3RG9hTGZxTGxHSkl5cGVVc1dXT1VDU2dRSncxZ2JoY09zOFdRZlVBZFcra3o3YVVoTHFZZXZtczJCWjl0dnlOZmRCa1IvUE5zM0JtamdnY1A3bmpQbWlrWGw4N0V4WkZPZVFsdGRGc0pXQWtKQlIvQ3VCblNJQUtLQXNvR2VnWlVDWlFPdEFiSWtKRklOdlhrdFBFT1NpeFA4ejA0OVZEaXhyTnFFMGIxWXlqWHBOSW9UUnNwc0NKcWFVcVREZ1dXVFFNNURyVTB2Y3VwaDV0THBOdXQySTMwK2cyQUFhbEJVZk9wOWNJbVQ3R1o2TzVlYkNzU3ljWFFaVUZCMnJPNmFLU3dvVEtnVlFxQ2dsSjJFOE0xZEJRTEtZTndsT0lvMll2MWdIa1pwRzZKZ0pmaDJIM20rZ1J6TFlaMzZETDNuMUhKazRac3BCc0dEVGp0UFlaM1BnRktwZkU5Tm1rMEFjelpKb0NaUkhPTUU1NWsyMnRzUFFiWFhpNFdGUldwcmd3TmU3UjArYkxhNVY5WnFhQ2dnSnlLWGkvdTFrNnppQ2tlQzFMakxDY29nMm04RHNGQVM4OFJxQTAxVEtUSmthUEhwTWtVbm05SDI5SGhTRUVvMVM5U2c0ZWRVanlZNngrQjhkbU5BY05jOTJhdUpXeklCOTR0WVBxSURQK0ZEeGlvaHdIZFQrZ3RUcDJWck5ybUJRYWtCajhDbzdMUHRtM1pZbUZpMGo1ejlKZ3hjbzM0M2RHN2lJdEdya1FvcUFma0pnQkhRd1lvbW5SQVNQczBHcGgwRGdpakJuOHdWZTgxQWd6NzRWK1J1Z1V5VEtqMzRqaHQ5S0x2dElLTUhUVGh6RFVYbUpGUWZ3OVFFcDNXQ0czekMrd25wdzl0NkRWS1BodCtzb2ZuMVpnK1NqZk83K0VZR0hxTnJtQUNPQmhEQzBYZnhtM0NoSGJ6L1h6bDhtMncvdkxGZ1VidTcraXgyMlJ3R2xvbzQ5SFJ6SHliZzBvWVBzSU5DRGRYZk1zWi9ZMEJJNmI1VktZc0doaFhRNW5FMVVkdWpHVWFEL1YrYlFLWVhyU1BVbW5EL1FnN2dNNDNNWTBsQUdVdzkwSTZsYW93a3ZxSU1UWmtUbVYvbTIzWU1QZzIyckhIZjhsUXhMY3BQTGZmeWxTbm5tL2pBMUpqMzhSajdDNUwxQzN4VklKR1VTbkNJeHFqZ0htUlREMWNNbUFYdm16aG85RTZrMXBKQ01nV2VuMk5NM0xSSXByWWlMVHdBUk5LbFR5ZTdjbWoxcE0vME8vUWxuVWp3RndBU3FXbU1qdDQrbEpUR2xNTWZGTWxCVnFhdEpvRUJxU21RanI2RmdVRWlKeWNuUEw3T1RqSUJjN2FOV3VFMHl3cVdPV01JcndSd0dsTVdZazQ4emx1NHZzUktJaWFwaUw0Z0FQc0EzQ1B5dm9TVTRRbTZRVG0vaWpVeWFIWGlTeUFsSUdtOUI1QlA4enBUMnZPUGVvZjlGa1dVbGRBbXREcTlLTlRvNUN4QkhGUXhORSszbUFIQmZwY3pIMFVVMS8yVk1ieGJmWlEzMFlRQkw0Tk9xRHkrRGFidzBJc1A3YldaWTlST0hCR0tadWVNZGNwOEVGOWdOQnBEQVE2RDlUWStnazduYUh5ZDJYdTF6UFhpUndyaWwzWlhNUFRQbGRpL21TdWNaTUl1M0pvdzB5UlV0MldSUFdqVkxMWnVpUHA5UldvSXdXTlZmN3E4dTRyUTkvbU1mZzJ4bUI1M1o0eDAxdHUzOFl5TDhGUXA3NXZFMGJQdHpTWUFabnJQakQ2RmdDcE04WkJPNkJ4UUoyYkFLWVBNOUxSYkQvRlNGY21oN2t1ekJ5L2c2Yy92TUJRaXkrRVVkeVlwQ2V0blJzeDBaTTVVN1laUjFxNC9vNjJYTUNBMUR5QXpKZjZOcmJ1a3lZVjI5all5TzNiekt6djJ4anl6T2VFS25oV2F2RGppNEVSR1VEM3FjOFNUUTBKTmwybS9vZDB1cFNtRFZUcGswYWtSdW84Ym9KNnBYSUFrd2o5eUtWQXN2c0cwdWgweXpYbFR6VUNqTlNDS3VVNHFtelNWV1FuSnFLYjhMZHZzMks1WEEraGJ4TUh2czI3UmhxUG1PSnhJRFZPSEgyUlNPMzZUQTd6cktqdXdGVEVzWElJWmVwbHptdnhYVHQ1dWhQUDQ1dXNhNlRyWEdETUtLa3hFb2tPYjNmb3d4ODBndkFoTS9vVG1HZHZVSCtIVGZ2Z3ViK1llMWI1Q3hUYXUyeHBabzVoRGx5M0VWNjhsSkN4YnUxYTYrLzI3SlVkS1FYbmRNZSsvUVhMN2hvYk04dk5PTkxlNWU2T29hWmtWNm9rTmFsU2ZFejlrWnZ3TVU5NWZDQmtvZ1dyQTdqQlFrWTUyek8rVWg3VWU5aUlYOVdSR2QzY2xBL1A1Zk04MDVYRzJrcmg5elJ1bUluOGYzZG83WmlDT3NYTTcyMllLZTZad3B2S0FSejB3djF0UmFMU2ZkOGZVSGQySENBRUtaTDVuSjI5SFptd2FrOWExSTBuN0J3WUJNQUVLb1A4RFZOenpzZmdmSnFKdnMzSjJOaU1nRVh5K3phUHp1MjNCTitHbFJCZm1OTHNsRER3ekRMTmVRaWtCbU5hc2Jna2NEWDVXdjdVU1pOTkxsNjRJUE01WExmWjl1T3hySUNiOWRadDBITjJWRzdTZUg2SlFTc05UY0c5RlJVVlpPYjBHWUxncFNHSytUWld1dmZrOUcyVUV0TU1xVUZuRG5jNUdueC84T0R0eTVjUzdNQmFrK3ZaMWV2V2xlNlV2S2RWOGxTaXdsaFI0dWZaU1FOVFluOGFObW5ISFErb0U2SHRReTBDR0FvT2htczJ0bTNidHZyQ3BZU3lZUjhQMVUxTGszbStpQmdiRzVNVmU0K2xoQ1NWc1dHWVhjQzg4YzBBUkorSlkzSFRXVkszV1QzdFRaT1k1ejBjaTJzbmx3b0xDMVZYaDRjWEJpOWJLcmR2azN4c3I2aXJETjlHRGxBK28xNDNGeFQwQ1hBUmF1Q2JDTXB6QXdPNlJrSmpUbFZSa1pzdHpjek1Na2Q5OFhuVEx4UUl5RVEzTitJeHlhT2kvZDFMZVp5Zkk0RFo2bklBWWdMMEE2azdkV2JLRFRiU2FYSExtMnhRdktoei9oZ0c4QldKeFNWNzkrL1RjQjR3VVBpSXg3ZkJKZW9WWWFHa2Rldlc2VitORzk4eEp6dGJvNlBudWxzYWxsM1o1UUE4a3JHNEVVQ3d2MjQwcEtQUCtSbkRObmcwOEdDTHRjcDRFcDZwejBxNWMwZm4xTW1UNlFzREF1cjlpTnRvWjgrZFN3NGZPL3JYMGNOSGNnWTQ5TytNb0dCWTQ4OHpNZjVVK1V1VFB3QWc0Z0ZGZXVSd0N3OG9PS1hhdnkyZ3ZEQ0pvVkx6RVdUSHBiN05aSGNQazRUNCtOci9obGtXdW9LVWxaYW1lRXgwczM3NDhDR0dSVEJramxJV2dtcyt3UFRhamUwY3BZMzZvUVorcTNma2tQTmFYSVRDWStibmxlWnkwK0JndFBSekoyZm5nb0JGZ2NZSjhRbkVkY1R3UXArNTg1NGVQWEpFcWd0d0Fjd0RBTG5CbWFLUXVld0NGUG8yMTZtRWNQOGtEb0ZGMjN6Snl6aUo5allDWTBKOUczM1FOYW5sWmVYVjN0T24yNVdVMVA2bEMwYUI4ZjltMWdNbzFUeFRGZW9aREk5TG83ZTRISXVHQVBlOEp2NnBnanNBOHJ2U3dXeUdiOE1weGdNM1V3Q1FIQm5XVmpBRmp5OGhVS2k4dm4xYi9zWHZWUU9EQmdXdVJlQnFJcHBtc3dHUVhYTDZKV2dRNEc0VzdtSVlib2JEazJoWnlwRE04NEdEZTZ0dy9ka2ZRRkVvekVJM0I1NWtRalZ6QUpDZHlsalphNUFBbkJpcVcvQWtXZ0ZwZ2VsL0Fnd0FuYllxUThyZ3RNOEFBQUFBU1VWT1JLNUNZSUk9In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTItMjEiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlRydXN0S2V5IFNvbHV0aW9ucyBUMzIwIFUyRiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAyMDA4MTQwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMi0yMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMTItMjEifSx7ImFhZ3VpZCI6IjlkM2RmNmJhLTI4MmYtMTFlZC1hMjYxLTAyNDJhYzEyMDAwMiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiOWQzZGY2YmEtMjgyZi0xMWVkLWEyNjEtMDI0MmFjMTIwMDAyIiwiZGVzY3JpcHRpb24iOiJBcmN1bHVzIEZJRE8yL1UyRiBLZXkgQ2FyZCIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxMDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQytqQ0NBcUNnQXdJQkFnSVVUWEp5MjhscFFWbGhJcDdFVEJpK1U0YmNhRDh3Q2dZSUtvWkl6ajBFQXdJd2dZQXhDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJREFwT1pYY2dTbVZ5YzJWNU1SRXdEd1lEVlFRSERBaFRiMjFsY25ObGRERVVNQklHQTFVRUNnd0xRMjl0Y0c5VFpXTjFjbVV4RURBT0JnTlZCQXNNQjBGeVkzVnNkWE14SVRBZkJnTlZCQU1NR0VOdmJYQnZVMlZqZFhKbExVWkpSRTh0UTBFdFVtOXZkREFnRncweU16QTBNVGd4TlRRMU5UQmFHQTh5TURVek1EUXhNREUxTkRVMU1Gb3dnWUF4Q3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSURBcE9aWGNnU21WeWMyVjVNUkV3RHdZRFZRUUhEQWhUYjIxbGNuTmxkREVVTUJJR0ExVUVDZ3dMUTI5dGNHOVRaV04xY21VeEVEQU9CZ05WQkFzTUIwRnlZM1ZzZFhNeElUQWZCZ05WQkFNTUdFTnZiWEJ2VTJWamRYSmxMVVpKUkU4dFEwRXRVbTl2ZERCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkNnRzdyNlZBL2grQnluVW55RFpNRDBWWmtZVzZSR25waDB3MjVnUURXTW9xQWFpVWFGRzVNQ2xraGFrSUJwTEYrNnhKQmhPMWdzKzdDMWsvanVWdXYyamdmTXdnZkF3SFFZRFZSME9CQllFRkp6MWdGdFRUQk5mZmZES3ZkanBVRXlwNzB6dE1JSEFCZ05WSFNNRWdiZ3dnYldBRkp6MWdGdFRUQk5mZmZES3ZkanBVRXlwNzB6dG9ZR0dwSUdETUlHQU1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLVG1WM0lFcGxjbk5sZVRFUk1BOEdBMVVFQnd3SVUyOXRaWEp6WlhReEZEQVNCZ05WQkFvTUMwTnZiWEJ2VTJWamRYSmxNUkF3RGdZRFZRUUxEQWRCY21OMWJIVnpNU0V3SHdZRFZRUUREQmhEYjIxd2IxTmxZM1Z5WlMxR1NVUlBMVU5CTFZKdmIzU0NGRTF5Y3R2SmFVRlpZU0tleEV3WXZsT0czR2cvTUF3R0ExVWRFd1FGTUFNQkFmOHdDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWdjZ1hHTURQMnJmaDRFVFk5RUpMd3VYbzFTOVVpcXRFbVBocTkvZGlTMG5BQ0lRRG95TFpvc3g4clJBRjF2cFJYY3NWUUREU0hvRXMvUGJtRjNFci9tSjB4Nnc9PSIsIk1JSUM1RENDQW9xZ0F3SUJBZ0lKQUoxbWdYK1RLaUg3TUFvR0NDcUdTTTQ5QkFNQ01JR0FNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0F3S1RtVjNJRXBsY25ObGVURVJNQThHQTFVRUJ3d0lVMjl0WlhKelpYUXhGREFTQmdOVkJBb01DME52YlhCdlUyVmpkWEpsTVJBd0RnWURWUVFMREFkQmNtTjFiSFZ6TVNFd0h3WURWUVFEREJoRGIyMXdiMU5sWTNWeVpTMUdTVVJQTFVOQkxWSnZiM1F3SUJjTk1qTXdNVEV6TVRjMU5UTXdXaGdQTWpBMU16QXhNRFV4TnpVMU16QmFNSUdBTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNBd0tUbVYzSUVwbGNuTmxlVEVSTUE4R0ExVUVCd3dJVTI5dFpYSnpaWFF4RkRBU0JnTlZCQW9NQzBOdmJYQnZVMlZqZFhKbE1SQXdEZ1lEVlFRTERBZEJjbU4xYkhWek1TRXdId1lEVlFRRERCaERiMjF3YjFObFkzVnlaUzFHU1VSUExVTkJMVkp2YjNRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFSM05sc2xwRXBYL0JpWjlScFdFK3FybTJJUk1MaTNia3NkYUhTcEE4K296VWFGYXZUNEwwcFBTTEJoblRSRjE1Q2FUSEpNY0VVR3Vnci94b0dUZExOcG80SG9NSUhsTUIwR0ExVWREZ1FXQkJSNHo3OHNUbWFpd0hCdzBmelY2Nlc2ZmwvOVdEQ0J0UVlEVlIwakJJR3RNSUdxZ0JSNHo3OHNUbWFpd0hCdzBmelY2Nlc2ZmwvOVdLR0JocVNCZ3pDQmdERUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2s1bGR5QktaWEp6WlhreEVUQVBCZ05WQkFjTUNGTnZiV1Z5YzJWME1SUXdFZ1lEVlFRS0RBdERiMjF3YjFObFkzVnlaVEVRTUE0R0ExVUVDd3dIUVhKamRXeDFjekVoTUI4R0ExVUVBd3dZUTI5dGNHOVRaV04xY21VdFJrbEVUeTFEUVMxU2IyOTBnZ2tBbldhQmY1TXFJZnN3REFZRFZSMFRCQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQnBlS0ZOdnpGdm4relk4Y1FkbUZHcnRsMDFKeHlsbGF2bHF4dXRjMnh0UmdJaEFPMDFlRnNVdlREZGtUZUhtOWVBdndMUDV2WE5JclUzTU94andhSWx0YU9ZIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBUG9DQVlBQUFCTm85VGtBQUFBQkdkQlRVRUFBTEdQQy94aEJRQUFBQ0JqU0ZKTkFBQjZKZ0FBZ0lRQUFQb0FBQUNBNkFBQWRUQUFBT3BnQUFBNm1BQUFGM0NjdWxFOEFBQUFoR1ZZU1daTlRRQXFBQUFBQ0FBRkFSSUFBd0FBQUFFQUFRQUFBUm9BQlFBQUFBRUFBQUJLQVJzQUJRQUFBQUVBQUFCU0FTZ0FBd0FBQUFFQUFnQUFoMmtBQkFBQUFBRUFBQUJhQUFBQUFBQUFBRWdBQUFBQkFBQUFTQUFBQUFFQUE2QUJBQU1BQUFBQkFBRUFBS0FDQUFRQUFBQUJBQUFENktBREFBUUFBQUFCQUFBRDZBQUFBQURyRWVLa0FBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFDekdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpV0UxUUlFTnZjbVVnTmk0d0xqQWlQZ29nSUNBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBnb2dJQ0FnSUNBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlnb2dJQ0FnSUNBZ0lDQWdJQ0I0Yld4dWN6cDBhV1ptUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzUnBabVl2TVM0d0x5SUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZaWGhwWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOWxlR2xtTHpFdU1DOGlQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFpVbVZ6YjJ4MWRHbHZiajQzTWp3dmRHbG1aanBaVW1WemIyeDFkR2x2Ymo0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2VW1WemIyeDFkR2x2YmxWdWFYUStNand2ZEdsbVpqcFNaWE52YkhWMGFXOXVWVzVwZEQ0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2V0ZKbGMyOXNkWFJwYjI0K056SThMM1JwWm1ZNldGSmxjMjlzZFhScGIyNCtDaUFnSUNBZ0lDQWdJRHgwYVdabU9rOXlhV1Z1ZEdGMGFXOXVQakU4TDNScFptWTZUM0pwWlc1MFlYUnBiMjQrQ2lBZ0lDQWdJQ0FnSUR4bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNHpNREF3UEM5bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNEtJQ0FnSUNBZ0lDQWdQR1Y0YVdZNlEyOXNiM0pUY0dGalpUNHhQQzlsZUdsbU9rTnZiRzl5VTNCaFkyVStDaUFnSUNBZ0lDQWdJRHhsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0ek1EQXdQQzlsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0S0lDQWdJQ0FnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrQ2lBZ0lEd3ZjbVJtT2xKRVJqNEtQQzk0T25odGNHMWxkR0UrQ2w5RUszOEFBRUFBU1VSQlZIZ0I3TjEvakdWWlFoLzJlKzZyN3BucDM5VmRQVDFkVmQwenV3d0x3OWlFMFB4WTJ5UnVTSVJETExCajVNZ0VRZ3c0L2lHd0hBS0pJNXdmc21YRmltVWxWbUpIU3BSRVRraWtTTEVpNWE5RWltTkdPSkVjZG9kZGtOZHIwQUpEZGp6czdBNHNDN3N6MDEzMTdzazU1NzdxcWY1ZFZlL1gvZkY1VUYydjNydjMzSE0rcDdhcXZuUE9QYWVxUEFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0F3SW9Fd29xdTR6SUVDQkFnUUlCQXZ3WHkzd3oxckFreGZXNzYzUnkxSjBDQUFBRUNCQWdRSUVDQUFBRUMvUlB3SC9UNzEyZHFUSUFBQVFJOUZQQUx0NGVkcHNvRUNCQWdRR0NGQW5uVXZIbit4bzJ2bWpiTlg2cENlQ2I5OGZETDc3ejU1bDllWVIxY2lnQUJBZ1FJakVKZ1l4U3QxRWdDQkFnUUlFRGdwQUlsb08rSDZZZnJ5ZVNIUWdoVjA4UlBwY0lFOUpPS09vOEFBUUlFQ0R4R1FFQi9ESXlYQ1JBZ1FJQUFnUThFNmpqWmlyR3A4czNuSWRTLy9jRTduaEVnUUlBQUFRS0xFamhZN0dWUjVTbUhBQUVDQkFnUUdLQkFVelhYOCtoNVN1ZXBkZEYvNEI5Z0gyc1NBUUlFQ0t4ZlFFQmZmeCtvQVFFQ0JBZ1E2THhBSGNMRk5weDN2cW9xU0lBQUFRSUVlaXNnb1BlMjYxU2NBQUVDQkFpc1RpRE5icjlZeFR6QjNZTUFBUUlFQ0JCWWxvQ0F2aXhaNVJJZ1FJQUFnV0VJbFAzT1E0alhodEVjclNCQWdBQUJBdDBWRU5DNzJ6ZHFSb0FBQVFJRXVpQlFoczNUNFBrTFhhaU1PaEFnUUlBQWdTRUxDT2hEN2wxdEkwQ0FBQUVDOHd2a2dKNXVRUS9ueXdydTg1ZW5CQUlFQ0JBZ1FPQXhBZ0w2WTJDOFRJQUFBUUlFQ0ZSNXlmWnFkM2YzbVJqak9mZWcrNDRnUUlBQUFRTExGUkRRbCt1cmRBSUVDQkFnMEdlQkV0RHZiR3lrRmR5clMzMXVpTG9USUVDQUFJRStDQWpvZmVnbGRTUkFnQUFCQW1zVWFPS2R6U3FXZ0c0Wjl6WDJnMHNUSUVDQXdQQUZCUFRoOTdFV0VpQkFnQUNCa3dxVUVmU3EyVGlYOWtBL25hYTRseFhkVDFxWTh3Z1FJRUNBQUlFbkN3am9UL2J4TGdFQ0JBZ1FHTE5BRzlEcjVueDZFbUlJQXZxWXZ4dTBuUUFCQWdTV0xpQ2dMNTNZQlFnUUlFQ0FRTDhGUW5OdkQzUlQzUHZkbFdwUGdBQUJBaDBYRU5BNzNrR3FSNEFBQVFJRTFpM1FWT0Y2bXVLZWwzUVgwTmZkR2E1UGdBQUJBb01XRU5BSDNiMGFSNEFBQVFJRTVoZEltNkJmbkw4VUpSQWdRSUFBQVFKUEV4RFFueWJrZlFJRUNCQWdNSEtCdERTY2dEN3k3d0hOSjBDQUFJSFZDQWpvcTNGMkZRSUVDQkFnMERlQnZFQmNXUlF1aEh2M29QZXREZXBMZ0FBQkFnUjZKU0NnOTZxN1ZKWUFBUUlFQ0t4VW9BVDBHS3NYMGhacks3MndpeEVnUUlBQWdURUtDT2hqN0hWdEprQ0FBQUVDUnhlWWhCRE81OE5UUkcrM1hUdjZ1WTRrUUlBQUFRSUVqaUVnb0I4RHk2RUVDQkFnUUdCRUFpV003Kzd1bm80eG5oMVJ1eldWQUFFQ0JBaXNUVUJBWHh1OUN4TWdRSUFBZ2U0THZEK1pYRXBickYyYXpYQTNndDc5TGxOREFnUUlFT2l4Z0lEZTQ4NVRkUUlFQ0JBZ3NFU0JFc2FiZUdjejNYK2VWbkdQNXJjdkVWdlJCQWdRSUVBZ0N3am92ZzhJRUNCQWdBQ0J4d3FFWnVOY2V2T1pja0NNUnRBZksrVU5BZ1FJRUNBd3Y0Q0FQcitoRWdnUUlFQ0F3R0FGWWwxZlRJdkU1YjhYckJFMzJGN1dNQUlFQ0JEb2lvQ0EzcFdlVUE4Q0JBZ1FJTkF0Z1RKYUhwcm0ycXhhOWxuclZ2K29EUUVDQkFnTVVFQkFIMkNuYWhJQkFnUUlFRmlVUUF6eFdsb2tMbytmTitrbWRGUGNGd1dySEFJRUNCQWc4QWdCQWYwUktGNGlRSUFBQVFJRVdvRzZxdE1DY2ZsaEFMMTE4QzhCQWdRSUVGaWVnSUMrUEZzbEV5QkFnQUNCM2d1a0VmUkx2VytFQmhBZ1FJQUFnWjRJQ09nOTZTalZKRUNBQUFFQ0t4Wm84dlZDVEZQY3k4UHM5dGJCdndRSUVDQkFZSGtDQXZyeWJKVk1nQUFCQWdUNkxGRG10RGN4dnBEMlFVOUozZjNuZmU1TWRTZEFnQUNCZmdnSTZQM29KN1VrUUlBQUFRS3JGc2dCZlZLSFNkNEgzWU1BQVFJRUNCQllnWUNBdmdKa2x5QkFnQUFCQWowVEtQUFp0N2UzbjBtajUrZG55OE9aNDk2elRsUmRBZ1FJRU9pZmdJRGV2ejVUWXdJRUNCQWdzR3lCRXNidlRpYVhZaFV2bGludWVaSzdCd0VDQkFnUUlMQlVBUUY5cWJ3S0owQ0FBQUVDL1JWb1FzZ3J1TSsyV2V0dk85U2NBQUVDQkFqMFJVQkE3MHRQcVNjQkFnUUlFRmlkUUJrdEQwMXpyZ3JoOU95eVJ0Qlg1KzlLQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0JBNEFrQ2JSaXZtd3ZwU1g1ZXRseDd3dkhlSWtDQUFBRUNCQllnSUtBdkFGRVJCQWdRSUVCZ2lBS2hxV2Q3b0ZlemRlS0cyRXB0SWtDQUFBRUMzUkVRMEx2VEYycENnQUFCQWdRNkpkQ0V0QWQ2U0FQb2FhVzRUbFZNWlFnUUlFQ0F3RUFGQlBTQmRxeG1FU0JBZ0FDQmVRWHFxcDR0RUNlZnoydnBmQUlFQ0JBZ2NCUUJBZjBvU280aFFJQUFBUUxqRWlpSlBNYVlWM0gzSUVDQUFBRUNCRllrSUtDdkNOcGxDQkFnUUlCQVR3VHlvbkFsb0ljUVovZWc1NWM4Q0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFQ0JEb24wQlp0YjJKNlI3MGFIcDcvN3BQalFrUUlFQ2dyd0lDZWw5N1RyMEpFQ0JBZ01CU0JmNzRwQTZUcytVU29XeTF0dFNyS1p3QUFRSUVDQkNvS2dIZGR3RUJBZ1FJRUNCd1dLRE1aNzkyN1dlZmpiRTViL3o4TUkzbkJBZ1FJRUJndVFJQytuSjlsVTZBQUFFQ0JIb3BNRDE5K21JYU43ODRtK0x1SnZSZTlxSktFeUJBZ0VEZkJBVDB2dldZK2hJZ1FJQUFnZVVLbERBK3JhckxhYWs0cTdndjExcnBCQWdRSUVEZ1BnRUIvVDRPWHhBZ1FJQUFBUUpab0o3RXMxVUlwMmNhUnRCOVd4QWdRSUFBZ1JVSUNPZ3JRSFlKQWdRSUVDRFFONEU0RFJkVEtzL0IzRzNvZmVzODlTVkFnQUNCM2dvSTZMM3RPaFVuUUlBQUFRSkxFU2lqNWFGcFhwaVZYclpjVzhxVkZFcUFBQUVDQkFqY0p5Q2czOGZoQ3dJRUNCQWdRQ0FMaEJDdnBYL3krSGtlUVMraG5Rd0JBZ1FJRUNDd1hBRUJmYm0rU2lkQWdBQUJBcjBVaUdGeW9hMjRHZTY5N0VDVkprQ0FBSUZlQ2dqb3ZldzJsU1pBZ0FBQkFzc1dpRlp3WHpheDhna1FJRUNBd0FNQ0F2b0RJTDRrUUlBQUFRSWpGMmp2T1kveDRCNzBrWE5vUGdFQ0JBZ1FXSjJBZ0w0NmExY2lRSUFBQVFKOUVDaHoybU1WcmxYUjdlZDk2REIxSkVDQUFJSGhDQWpvdytsTExTRkFnQUFCQW9zUXlLbDhVdGZWdVZKWXNFRGNJbENWUVlBQUFRSUVqaUlnb0I5RnlURUVDQkFnUUdBY0FtVzE5bXZYcmoyYjFtNC9OMXNlemdydTQraDdyU1JBZ0FDQkRnZ0k2QjNvQkZVZ1FJQUFBUUlkRVNoaGZQL1VxVXRwZXZ0bU84WGRDSHBIK2tZMUNCQWdRR0FFQWdMNkNEcFpFd2tRSUVDQXdCRUZTa0J2UXRoTUs4WE50bGs3NHBrT0kwQ0FBQUVDQk9ZV0VORG5KbFFBQVFJRUNCQVlsa0FkNDlrUXd1bFpxMHh4SDFiM2FnMEJBZ1FJZEZoQVFPOXc1NmdhQVFJRUNCQllzVUFKNDdHdUw4eFNlYnZsMm9vcjRYSUVDQkFnUUdDc0FnTDZXSHRldXdrUUlFQ0F3R01Fd25SNmZmYldiSjI0eHh6b1pRSUVDQkFnUUdDaEFnTDZRamtWUm9BQUFRSUUraThRUXJ4V2hUU0dIc3RHNlAxdmtCWVFJRUNBQUlHZUNBam9QZWtvMVNSQWdBQUJBcXNTaUdGaWdiaFZZYnNPQVFJRUNCQTRKQ0NnSDhMd2xBQUJBZ1FJakZ4Z05xVTliYkhtUVlBQUFRSUVDS3hjUUVCZk9ia0xFaUJBZ0FDQlRncmtkZUhhZ0I3VEZQZnliTFpVWENlcnExSUVDQkFnUUdCNEFnTDY4UHBVaXdnUUlFQ0F3RWtGeXFydHNRclhEckw2U1F0eUhnRUNCQWdRSUhCOEFRSDkrR2JPSUVDQUFBRUNReGFZMUNHY0xRME1sU0gwSWZlMHRoRWdRSUJBNXdRRTlNNTFpUW9SSUVDQUFJRzFDSlF3ZnZYcTFlZlM2dTNuN0srMmxqNXdVUUlFQ0JBWXVZQ0FQdkp2QU0wblFJQUFBUUtIQmFhblRxVUY0dUxsRk5MenkwYlFEK040VG9BQUFRSUVsaXdnb0M4WldQRUVDQkFnUUtBbkFpV014N3ErbEtLNWJkWjYwbW1xU1lBQUFRTERFaERRaDlXZldrT0FBQUVDQk9ZU0NCdnhiQlhDcVZraFJ0RG4wblF5QVFJRUNCQTRub0NBZmp3dlJ4TWdRSUFBZ2FFS3RHRjhXbDlNVC9KenQ2RVB0YWUxaXdBQkFnUTZLeUNnZDdaclZJd0FBUUlFQ0t4ZUlEVE45ZGxWODVaclJ0Qlgzd1d1U0lBQUFRSWpGaERRUjl6NW1rNkFBQUVDQkI0U0NPSDVOTVU5alorM3E4UTk5TDRYQ0JBZ1FJQUFnYVVKQ09oTG8xVXdBUUlFQ0JEb29VQUlGb2pyWWJlcE1nRUNCQWdNUTBCQUgwWS9hZ1VCQWdRSUVGaVFRSk8yV2ZNZ1FJQUFBUUlFMWlHd3NZNkx1aVlCQWdRSUVDRFFPWUY4ejNtYTJoNE83a0h2WEFWVmlBQUJBZ1FJREYzQUNQclFlMWo3Q0JBZ1FJREEwUVRLcXUwaHhxdnRBdTdXaHpzYW02TUlFQ0JBZ01EaUJBVDB4VmtxaVFBQkFnUUk5RmtnQi9SSk5Rbm5TaU9DRmR6NzNKbnFUb0FBQVFMOUZCRFErOWx2YWsyQUFBRUNCQllwVUliTHIxNjkrbHpWVk9kbkc2QWJRbCtrc0xJSUVDQkFnTUFSQkFUMEl5QTVoQUFCQWdRSURGeWdoUEhwcVZPYnNZcVgwaFpydWJrQytzQTdYZk1JRUNCQW9Ic0NBbnIzK2tTTkNCQWdRSURBcWdWS0dJOTFmU25sY3R1c3JWcmY5UWdRSUVDQXdFeEFRUGV0UUlBQUFRSUVDQlNCOUVmQm1UUnVmaXA5a1lmUWphRDd2aUJBZ0FBQkFpc1dFTkJYRE81eUJBZ1FJRUNnZ3dMdENIb0lsMmFwZkhZYmVnZHJxa29FQ0JBZ1FHREFBZ0w2Z0R0WDB3Z1FJRUNBd0hFRVF0TWM3SUV1b0I4SHpyRUVDQkFnUUdCQkFnTDZnaUFWUTRBQUFRSUVlaThRd3ZOVlNHUG9zVjBscnZmdDBRQUNCQWdRSU5BekFRRzlaeDJtdWdRSUVDQkFZR2tDd1FKeFM3TlZNQUVDQkFnUU9JS0FnSDRFSkljUUlFQ0FBSUdCQzh5bXREZWJBMituNWhFZ1FJQUFnVTRMYkhTNmRpcEhnQUFCQWdRSUxGc2dyd3ZYbEl2RWtPNUJ0NEQ3c3NHVlQ0QUFBUUlFSGlkZ0JQMXhNbDRuUUlBQUFRTGpFU2dqNkNIR3ErTnBzcFlTSUVDQUFJSHVDUWpvM2VzVE5TSkFnQUFCQXVzUTJLZ200V3k1Y0xBSCtqbzZ3RFVKRUNCQWdJQ0E3bnVBQUFFQ0JBaU1XNkJzZmI2MXRmVmNtdWgrM3Y1cTQvNW0wSG9DQkFnUVdLK0FnTDVlZjFjblFJQUFBUUtkRU5nL2RlcHlyT0ptMm1JdDE2ZUU5azVVVENVSUVDQkFnTUNJQkFUMEVYVzJwaElnUUlBQWdVY0lsREFlSnBPTGFRLzBDNDk0MzBzRUNCQWdRSURBaWdRRTlCVkJ1d3dCQWdRSUVPaXlRSmpFZlAvNXFWa2RqYUIzdWJQVWpRQUJBZ1FHS3lDZ0Q3WnJOWXdBQVFJRUNCeEpvSVR4eVRSY21xVnl0NkVmaWMxQkJBZ1FJRUJnOFFJQyt1Sk5sVWlBQUFFQ0JIb25NQTFOMmdPOVBQS2U2RWJRWnhnK0VTQkFnQUNCVlFvSTZLdlVkaTBDQkFnUUlOQlJnUkRycStrZTlDb3RFbWNFdmFOOXBGb0VDQkFnTUh3QkFYMzRmYXlGQkFnUUlFRGc2UUlXaUh1NmtTTUlFQ0JBZ01DU0JRVDBKUU1ybmdBQkFnUUlkRnhnTm1MZVhPNTRQVldQQUFFQ0JBZ01YbUJqOEMzVVFBSUVDQkFnUU9CSkFtMUFqekhkZzI1Mis1T2d2RWVBQUFFQ0JKWXRZQVI5MmNMS0owQ0FBQUVDM1JZb3FUeUVzTlZXTTkrSTdrR0FBQUVDQkFpc1EwQkFYNGU2YXhJZ1FJQUFnZTRJNUlBK1NRdkU1WDNRcmQ5ZUVQeERnQUFCQWdUV0l5Q2dyOGZkVlFrUUlFQ0FRQmNFeW1qNTF0YldtVFM3L2NKc2dyc1I5QzcwakRvUUlFQ0F3Q2dGQlBSUmRydEdFeUJBZ0FDQklsREMrUFQwNmMyMHU5cG0ybUl0dnlpZysrWWdRSUFBQVFKckVoRFExd1R2c2dRSUVDQkFvQU1DYlJpdjYwdXBMdWM3VUI5VklFQ0FBQUVDb3hZUTBFZmQvUnBQZ0FBQkFnVFNrUGxHUEpQdVFjODd1K1FoZENQb3Zpa0lFQ0JBZ01DYUJBVDBOY0c3TEFFQ0JBZ1E2SUJBQ2VPVC9iQTVTK1d6MjlBN1VETlZJRUNBQUFFQ0l4UVEwRWZZNlpwTWdBQUJBZ1FPQzB4RGsvWkFUNDlvSS9URExwNFRJRUNBQUlGVkN3am9xeFozUFFJRUNCQWcwREdCRU92bjB4VDNWS3QybGJpT1ZVOTFDQkFnUUlEQWFBUUU5TkYwdFlZU0lFQ0FBSUhIQ0lSZ2diakgwSGlaQUFFQ0JBaXNVa0JBWDZXMmF4RWdRSUFBZ1c0SnpQWlZheTUzcTFwcVE0QUFBUUlFeGlrZ29JK3ozN1dhQUFFQ0JBamtPZTFOWmtoN29GOXZaN2ZQbG9walE0QUFBUUlFQ0t4RlFFQmZDN3VMRWlCQWdBQ0JUZ2kwSStnaGJKWGF5T2VkNkJTVklFQ0FBSUh4Q2dqbzQrMTdMU2RBZ0FBQkFsVjF1OXBJQzhTZG5WR0k2TDRuQ0JBZ1FJREFHZ1VFOURYaXV6UUJBZ1FJRUZpalFBbmptNy93NGJOcGM3VUxOa0JmWTArNE5BRUNCQWdRbUFrSTZMNFZDQkFnUUlEQWlBV2FDMSs1bk81QjM1enRzR1lFZmNUZkM1cE9nQUFCQXVzWEVORFgzd2RxUUlBQUFRSUUxaUZRd3Zneit4c1gwaFQzYyt1b2dHc1NJRUNBQUFFQzl3c0k2UGQ3K0lvQUFRSUVDSXhMWUdNajMzOSthdFpvSStqajZuMnRKVUNBQUlHT0NRam9IZXNRMVNGQWdBQUJBaXNTS0dHODJkL2ZuS1Z5dDZHdkNONWxDQkFnUUlEQTR3UUU5TWZKZUowQUFRSUVDSXhBb0FuaCtxeVplVTkwSStnajZITk5KRUNBQUlIdUNnam8zZTBiTlNOQWdBQUJBa3NYQ0hXOG11NUJyOUlpY1ViUWw2N3RBZ1FJRUNCQTRNa0NBdnFUZmJ4TGdBQUJBZ1NHTFJEcjg4TnVvTllSSUVDQUFJSCtDQWpvL2Vrck5TVkFnQUFCQW9zVUtDUG1JY1lyaXl4VVdRUUlFQ0JBZ01ESkJRVDBrOXM1a3dBQkFnUUk5Rm1nQlBRWTR2WFpIdWg5Ym91NkV5QkFnQUNCUVFnSTZJUG9SbzBnUUlBQUFRTEhGbWp2T1kvVlZudG12aEhkZ3dBQkFnUUlFRmluZ0lDK1RuM1hKa0NBQUFFQzZ4T0kxZTFxSTRSd3BsUkJQRjlmVDdneUFRSUVDQkNZQ1Fqb3ZoVUlFQ0JBZ01ENEJFb2N2L3lMTCtkd2ZtRzJmTHVJUHI3dkF5MG1RSUFBZ1k0SkNPZ2Q2eERWSVVDQUFBRUNLeEFvWWJ5NThPWExhWGUxemRrOTZBTDZDdUJkZ2dBQkFnUUlQRWxBUUgrU2p2Y0lFQ0JBZ01Bd0JVb1lEL3NiRjFMenpnMnppVnBGZ0FBQkFnVDZKeUNnOTYvUDFKZ0FBUUlFQ0N4RTROUmtjcTRLWVNNVmxtZTVHMEZmaUtwQ0NCQWdRSURBeVFVRTlKUGJPWk1BQVFJRUNQUlZvSjNpdnIrL09VdmxzOXZRKzlvYzlTWkFnQUFCQXNNUUVOQ0gwWTlhUVlBQUFRSUVqaTNRaEhDOW5CVExDUHF4ejNjQ0FRSUVDQkFnc0ZnQkFYMnhua29qUUlBQUFRSzlFUWgxdkpxbXVLZjZSaVBvdmVrMUZTVkFnQUNCSVFzSTZFUHVYVzBqUUlBQUFRSlBFbWhDWGlUT2d3QUJBZ1FJRU9pSWdJRGVrWTVRRFFJRUNCQWdzRUtCTW1LZXhzNHZyL0NhTGtXQUFBRUNCQWc4UlVCQWZ3cVF0d2tRSUVDQXdNQUU4cHoySnJjcGhuaTluZDArV3lwdVlBM1ZIQUlFQ0JBZzBEY0JBYjF2UGFhK0JBZ1FJRUJnZm9IMm52TllYU2xGQlZ1c3pVK3FCQUlFQ0JBZ01MK0FnRDYvb1JJSUVDQkFnRUQvQkc3ZE9oVkNPTmUvaXFzeEFRSUVDQkFZcm9DQVB0eSsxVElDQkFnUUlQQW9nVEtmL2VJWHZwREQrWG5MdHorS3lHc0VDQkFnUUdBOUFodnJ1YXlyRWlCQWdBQUJBbXNTT0xqaGZEUEd1RG1ydzhGcmE2cVN5eElnUUlBQUFRSlp3QWk2N3dNQ0JBZ1FJREJDZ2RQMU5HK3hab3I3Q1B0ZWt3a1FJRUNndXdJQ2VuZjdSczBJRUNCQWdNRFNCRUl6T1Z1RmNEQ1R6Z2o2MHFRVlRJQUFBUUlFamk0Z29CL2R5cEVFQ0JBZ1FHQUlBaVdNTjlYKzVWa3FkeHY2RUhwVkd3Z1FJRUJnRUFJQytpQzZVU01JRUNCQWdNQXhCWnI2K3V5TXZDZTZFZlJqOGptY0FBRUNCQWdzUTBCQVg0YXFNZ2tRSUVDQVFNY0ZZb2hiYVlwN1ZhV1Y0anBlVmRValFJQUFBUUtqRVJEUVI5UFZHa3FBQUFFQ0JBNEpoSEQrMEZlZUVpQkFnQUFCQWgwUUVOQTcwQW1xUUlBQUFRSUVWaWhRUnN4RFUyMnQ4Sm91UllBQUFRSUVDQnhCUUVBL0FwSkRDQkFnUUlEQWdBUktRRytxZUQxTmJ4OVFzelNGQUFFQ0JBajBYMEJBNzM4ZmFnRUJBZ1FJRURpT1FGNFVMcTBLRjY2MEorVWIwVDBJRUNCQWdBQ0JMZ2dJNkYzb0JYVWdRSUFBQVFLckVUZ0k0eHNwbHA4cGx6eDRaVFhYZHhVQ0JBZ1FJRURnQ1FJQytoTnd2RVdBQUFFQ0JJWW9jT21sbDg3RktsNllUWEFYMFlmWXlkcEVnQUFCQXIwVUVOQjcyVzBxVFlBQUFRSUVUaVJRd25pTTcyMVdNYVNQZHIyNEU1WGtKQUlFQ0JBZ1FHRGhBZ0w2d2trVlNJQUFBUUlFT2l0UUF2cnBzSEV4YllCK3JyTzFWREVDQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0F3WG9FUU44NVVJVXlTUUI1Q044Vjl2TjhLV2s2QUFBRUNIUk1RMER2V0lhcERnQUFCQWdTV0tGRENlQlAzcnN4U3VYM1dsb2l0YUFJRUNCQWdjRndCQWYyNFlvNG5RSUFBQVFKOUYyanE2NlVKc1NwYnJ2VzlPZXBQZ0FBQkFnU0dJaUNnRDZVbnRZTUFBUUlFQ0J4UklJYTRsYWE0cDZNTm9CK1J6R0VFQ0JBZ1FHQWxBZ0w2U3BoZGhBQUJBZ1FJZEVlZ0R1RjhkMnFqSmdRSUVDQkFnTUNCZ0lCK0lPRXpBUUlFQ0JBWXZrQVpNbzlOdFRYOHBtb2hBUUlFQ0JEb240Q0EzcjgrVTJNQ0JBZ1FJSEFTZ1R5bnZkeHozbFR4ZXJzSCtteXB1Sk9VNWh3Q0JBZ1FJRUJnNFFJQytzSkpGVWlBQUFFQ0JEb3JVTFpWQzFXNFVtcVlublMycGlwR2dBQUJBZ1JHS0NDZ2o3RFROWmtBQVFJRVJpeHc2OVpHV2gvdXpJZ0ZOSjBBQVFJRUNIUldRRUR2Yk5lb0dBRUNCQWdRV0toQUdTMi84UGJiNTJPTUY2M2Z2bEJiaFJFZ1FJQUFnWVVJQ09nTFlWUUlBUUlFQ0JEb3ZFQUo2TStHc0ptMlY5dHM3MEUzeGIzenZhYUNCQWdRSURBcUFRRjlWTjJ0c1FRSUVDQXdkb0ZZMXhlcUtwamlQdlp2Qk8wblFJQUFnVTRLQ09pZDdCYVZJa0NBQUFFQ3l4RUlNWjZwUXRpWWxXNlJ1T1V3SzVVQUFRSUVDSnhJUUVBL0VadVRDQkFnUUlCQTd3UktHSi9HdURWTDVXWEx0ZDYxUW9VSkVDQkFnTUNBQlFUMEFYZXVwaEVnUUlBQWdRY0ZRdE5jbjcxV3RseDc4SDFmRXlCQWdBQUJBdXNURU5EWForL0tCQWdRSUVCZzVRTHBIdlFyYVlwN1dpY3VXc2g5NWZvdVNJQUFBUUlFbml3Z29EL1p4N3NFQ0JBZ1FHQlFBbldJNXdmVklJMGhRSUFBQVFJREVoRFFCOVNabWtLQUFBRUNCSjRnVUViTW02YTYrb1JqdkVXQUFBRUNCQWlzVWVCZ0ZkYzFWc0dsQ1JBZ1FJQUFnUlVJbElBZXFuaTltajFid1RWZGdnQUJBZ1FJRURpR2dCSDBZMkE1bEFBQkFnUUk5Rmlnck5vZXEzQzV0Q0ZVdGxqcmNXZXFPZ0VDQkFnTVUwQkFIMmEvYWhVQkFnUUlFRGdzTUF2anR6ZFNMRDl6K0EzUENSQWdRSUFBZ2U0SUNPamQ2UXMxSVVDQUFBRUNTeFc0ZVBOWHo2ZlYyeS9PMW04M2dyNVViWVVUSUVDQUFJSGpDd2pveHpkekJnRUNCQWdRNkp2QVFSamZUUGVmYjZZOTFuTDlEMTdyVzF2VWx3QUJBZ1FJREZaQVFCOXMxMm9ZQVFJRUNCQzRKMURDK09tNnZtQ0srejBUVHdnUUlFQ0FRT2NFQlBUT2RZa0tFU0JBZ0FDQjVRaUVwamxiaFRCSnBlY2hkQ1BveTJGV0tnRUNCQWdRT0xHQWdINWlPaWNTSUVDQUFJSGVDSlF3UG8zN1c3TlVYdWE0OTZiMktrcUFBQUVDQkVZaUlLQ1BwS00xa3dBQkFnUUloQ1pjTHdxeEtsdXVFU0ZBZ0FBQkFnUzZKU0NnZDZzLzFJWUFBUUlFQ0N4TklOYjFsVFRGUFpWdkFIMXB5QW9tUUlBQUFRSnpDQWpvYytBNWxRQUJBZ1FJOUVtZ0R2RjhuK3FycmdRSUVDQkFZR3dDQXZyWWVseDdDUkFnUUdDTUFtWEl2R21xcXdiUHg5ajkya3lBQUFFQ2ZSSFk2RXRGMVpNQUFRSUVDQkE0a1VDZTAxN3VPUTlWYk85QnQ0RDdpU0NkUklBQUFRSUVsaTFnQkgzWndzb25RSUFBQVFMckZ5amJxc1VRTHBlcUJBbDkvVjJpQmdRSUVDQkE0R0VCQWYxaEU2OFFJRUNBQUlFaENaU2QxVjU5OWRWVHFWRm5odFF3YlNGQWdBQUJBa01URU5DSDFxUGFRNEFBQVFJRUhpSHcvMzN4aXhlcUdDOWF2LzBST0Y0aVFJQUFBUUlkRVJEUU85SVJxa0dBQUFFQ0JKWWtVRWJRbjYzclMybUJ1TTBVMHZObHltdEx1cDVpQ1JBZ1FJQUFnUk1LQ09nbmhITWFBUUlFQ0JEb2swQ2NUQzZrV0c2S2U1ODZUVjBKRUNCQVlIUUNBdnJvdWx5RENSQWdRR0NNQXFGcHpsWWhUR1p0TjRJK3htOENiU1pBZ0FDQnpnc0k2SjN2SWhVa1FJQUFBUUp6Q1pRdzNzUzROVXZsWmN1MXVVcDBNZ0VDQkFnUUlMQVVBUUY5S2F3S0pVQ0FBQUVDSFJOb210a2U2T2xPZFBlZ2Q2eHpWSWNBQVFJRUNMUUNBcnJ2QkFJRUNCQWdNQUtCZWpLNW5LYTRWMm1ST0F1NWo2Qy9OWkVBQVFJRStpa2dvUGV6MzlTYUFBRUNCQWdjU3lDR2VQNVlKemlZQUFFQ0JBZ1FXTG1BZ0w1eWNoY2tRSUFBQVFJckZTZ2o1bW5nL1BtVlh0WEZDQkFnUUlBQWdXTUxiQno3RENjUUlFQ0FBQUVDZlJKb3A3VEhtTzVCZC90NW56cE9YUWtRSUVCZ2ZBSkcwTWZYNTFwTWdBQUJBdU1TYUZkdEQvVm1hWFpJdTZGN0VDQkFnQUFCQXAwVUVOQTcyUzBxUllBQUFRSUVGaUxRaHZGYnQwNmwwczRzcEVTRkVDQkFnQUFCQWtzVE1NVjlhYlFLSmtDQUFBRUMzUkE0LzduUFhVamo1aGRqRzllTm9IZWpXOVNDQUFFQ0JBZzhKR0FFL1NFU0x4QWdRSUFBZ2NFSWxERCtiQWliNmZiei9KRWZBdnBndWxkRENCQWdRR0JvQWdMNjBIcFVld2dRSUVDQXdBY0NiUmlmTk9kVExEZkYvUU1YendnUUlFQ0FRQ2NGQlBST2RvdEtFU0JBZ0FDQkJRckVqYk5WQ1BsM3ZtWGNGOGlxS0FJRUNCQWdzR2dCQVgzUm9zb2pRSUFBQVFMZEVTZ2o2RTNUWEozTmEyOG51WGVuZm1wQ2dBQUJBZ1FJSEJJUTBBOWhlRXFBQUFFQ0JBWXBFSnEwQjNwNnhLcmRjbTJRamRRb0FnUUlFQ0RRZndFQnZmOTlxQVVFQ0JBZ1FPQ0pBckdhWEVsVDNOTXhCdENmQ09WTkFnUUlFQ0N3WmdFQmZjMGQ0UElFQ0JBZ1FHRFpBbldJNTVaOURlVVRJRUNBQUFFQzh3c0k2UE1iS29FQUFRSUVDSFJWb0V4cGp6RSszMVp3ZGlkNlYydXJYZ1FJRUNCQVlPUUNBdnJJdndFMG53QUJBZ1FHSy9EQm5QYW0ycW1pNmUyRDdXa05JMENBQUlIQkNBam9nK2xLRFNGQWdBQUJBZzhKdE51cTFlRmllU2VrM2RBOUNCQWdRSUFBZ2M0S0NPaWQ3Um9WSTBDQUFBRUNjd20wWWZ6bGwwK25VczdPVlpLVENSQWdRSUFBZ1pVSUNPZ3JZWFlSQWdRSUVDQ3dIb0Z6WC83eWhUUzkvZUpzZ3JzUjlQVjBnNnNTSUVDQUFJRWpDUWpvUjJKeUVBRUNCQWdRNkoxQUNlUFBUaWFicWVhWDNJUGV1LzVUWVFJRUNCQVlvWUNBUHNKTzEyUUNCQWdRR0pIQVpISSt0ZmE1RWJWWVV3a1FJRUNBUUc4RkJQVGVkcDJLRXlCQWdBQ0Jwd3VFR005V0lVeG1SNXJpL25ReVJ4QWdRSUFBZ2JVSkNPaHJvM2RoQWdRSUVDQ3dWSUVTeHFjeFhwMmw4ckluK2xLdnFIQUNCQWdRSUVCZ0xnRUJmUzQrSnhNZ1FJQUFnVzRMaEtxNVhtb1lxeHpRamFCM3U3dlVqZ0FCQWdSR0xpQ2dqL3diUVBNSkVDQkFZTmdDYVhiN1pwcmluaG81VzhkOTJNM1ZPZ0lFQ0JBZzBHc0JBYjNYM2FmeUJBZ1FJRURnYVFMeHd0T084RDRCQWdRSUVDRFFEUUVCdlJ2OW9CWUVDQkFnUUdEUkFtWElQRmJ4K1VVWHJEd0NCQWdRSUVCZ09RSUMrbkpjbFVxQUFBRUNCTll0MEM0SzExVFgyejNRM1g2KzdnNXhmUUlFQ0JBZzhEUUJBZjFwUXQ0blFJQUFBUUw5Rkdodk9xL0R4Vkw5WUlHNGZuYWpXaE1nUUlEQW1BUUU5REgxdHJZU0lFQ0F3RmdFMnVIeVYxODluUnA4ZGl5TjFrNENCQWdRSU5CM0FRRzk3ejJvL2dRSUVDQkE0REVDNTcvNHhRdHBldnVsMkk2bG0rUCtHQ2N2RXlCQWdBQ0JyZ2dJNkYzcENmVWdRSUFBQVFLTEV5aGgvTm02M2t4RlhwcHRzU2FnTDg1WFNRUUlFQ0JBWUNrQ0F2cFNXQlZLZ0FBQkFnVFdKcENEZVBuOUhrTzUvL3k1V1UwRTlMVjFpUXNUSUVDQUFJR2pDUWpvUjNOeUZBRUNCQWdRNktMQVFSaWZWTGR2YjZRS1RtYVZuT2JQTWNaSkZVTCtYZDlPY3ArOTZSTUJBZ1FJRUNEUVRZSDh5OXlEQUFFQ0JBZ1E2TDdBUVJnL0dBblBvVHNIOFRaOHYvYmF2UlpzYjIrZitkMFFuZ3NoL29FcUxkNmVEc2pISEp4Mzd6aFBDQkFnUUlBQWdXNEpDT2pkNmcrMUlVQ0FBQUVDQndKdElMK2RndlZySldEbk1GNUd4ZzhPU0o5UFhYcnBoWjJOdmNtSFlsMTliVHJocTFNT2YrVk9WZTJjanZGR1doenV3aXkvbXpGM0NNMVRBZ1FJRUNEUVZRRUJ2YXM5bzE0RUNCQWdNRGFCSEtKektNOGZCNlBqMHhUT0R4NlRhemR2dmppdDlsK05NWHg5RmNNL213TjUzSThmam5VNEYwSStMVDFTS2o4b29IM0J2d1FJRUNCQWdFQmZCQVQwdnZTVWVoSWdRSURBRUFWeUtEKzRSL3krMGZGcjE2NmRiWjZkZkNTRjhXOUptZnRiVTJUL2h2M1lmRldvNmd0dEdHOW50cGNvbjI0MmowM1RudDhHOVp6UkQzOE0wVTZiQ0JBZ1FJREE0QVFFOU1GMXFRWVJJRUNBUUljRmNtZytHQ2x2MHZPRGorcmxsMTkrNWt2dnZmZEtVOWUvUDFUTlB6K040WnZpTkw0VTZuclNadTZZRjMzTGVieXBtaWFmbHlKNGVhY3RMd1MvMHd1S2Z3Z1FJRUNBUUg4Ri9ETHZiOStwT1FFQ0JBajBSeUN2cnA3RCtYNzZ1RGRTdm5YanhuWUszUjlOaTdsOTV4ZnZ2UDhIMGhGZm15SjMrdDFjcHlDZW9uaisvK2swbjNNUXh0dFJjV0c4a1BpSEFBRUNCQWdNVFVCQUgxcVBhZzhCQWdRSWRFSGc4RWg1RHVUM1F2bVZGMTk4cFpwTy80VjB3SGVsZWVrcG5JZkxWZG9KTGJTajR5bVFOeW1RcDJUZWJvOFcwbWUvcTd2UW8rcEFnQUFCQWdSV0lPQ1gvZ3FRWFlJQUFRSUVSaU9RZzNrZUxiOHZsRisrZWZQVnVtbis1VFJDL3QxeHV2L05hZHI2czNreHR6SkNIdU0wVFZsUEs3dVY2ZW9wa09jUjlGeU1Cd0VDQkFnUUlEQTJBUUY5YkQydXZRUUlFQ0N3YUlIRG8rVjVPbnFaa241MWQvZmxHT0wzcEsvL1dCb3AvK2FxRHFkTEtFOHZ0TlBXMDJtaGhQbEpDdWVMcnBQeUNCQWdRSUFBZ1I0S0NPZzk3RFJWSmtDQUFJRk9DT1JVblVmTGN5QXZVOWd2M3J5NXVkRTBmemhVOFU4MFZieWRacW1mYlVmSzB4M2xUWnE2Zm0rVTNMVDFUdlNnU2hBZ1FJQUFnWTRKQ09nZDZ4RFZJVUNBQUlIT0N4eGU4SzJNbGwvZTJmbG91bzM4QjlOVTllOUpnK0U3WllwNnZxZThMUEEyR3lsM0wzbm5PMVlGQ1JBZ1FJREF1Z1VFOUhYM2dPc1RJRUNBUUY4RTh1L012TDFaR1MyL3NMdDcrWFJWZlc5YTNlMEhVeGIvdHJ5bVc1cktua2JLeS92cG52SzBGTHRRM3BlK1ZVOENCQWdRSU5BSkFRRzlFOTJnRWdRSUVDRFFVWUdEYWV3NWxMZWo1WG5CdHpqOW9SVEt2eS9kVjc2ZEYzckxxNzJWMGZLYzB0djd5anZhSE5VaVFJQUFBUUlFdWl3Z29IZTVkOVNOQUFFQ0JOWWxFS3JiNmY3eTEwb29MOEg4eXM3T2Q2UVI4VDhYbXVhN3E3cCs1bDRvVHk4YUxWOVhON2t1QVFJRUNCQVlsb0NBUHF6KzFCb0NCQWdRbUUrZ1RxZm5qLzFaT0ErWGQzZi9XSHJoejhkUS9jRzh4bHRhN0MxTmRJOTc2Wmk4K3JyZm8vTjVPNXNBQVFJRUNCQTRKT0FQaTBNWW5oSWdRSURBYUFVK0NPWXBmbCs3ZHUxc2MrclVuMmhDOWVmU0hQZGJSU1hkWUo3Q2VaTkNlVDcyMUdpbE5Kd0FBUUlFQ0JCWW1vQ0F2alJhQlJNZ1FJQkFEd1R1QytiYjI5dGJkK3I2UjlJTjUvOW11ci84cTBKZWliMnMvSllXaHd2VnhpeWM5NkJacWtpQUFBRUNCQWowVVVCQTcyT3ZxVE1CQWdRSXpDdHdYekRmZXZIRjY3SFovOUU3VmZqaE5JMzllZ3JsYWEzMjZjRys1WG5oTjc4djV4VjNQZ0VDQkFnUUlQQlVBWDl3UEpYSUFRUUlFQ0F3SUlHNnVwM3VNVzhYZjJ0bXdmekg0blQvejRTNnZwSW1zYWQ3ekVzd3QwWGFnRHBkVXdnUUlFQ0FRRjhFQlBTKzlKUjZFaUJBZ01COEFyZlRLSGdPNXE5VlRkbkRQTVovS3dYekgwM0IvSEs3ZjNsajRiZjVoSjFOZ0FBQkFnUUl6Q2tnb004SjZIUUNCQWdRNkx4QS9sMDN6ZUg4cFpkZWV2YkwwNzBmVFJQWWZ5SnRsWGE5U211K3BZWGYybUJ1NGJmT2Q2UUtFaUJBZ0FDQm9Rc0k2RVB2WWUwalFJREFlQVh5ZmVacEVmYXlsM2wxWlhmM0IzNTNmKy9mVHlQbVgxT0NlWnh0bFNhWWovYzdSTXNKRUNCQWdFREhCUElmTHg0RUNCQWdRR0JJQXFHNmRTdHZnNVkyTEsrbVc3dTdmM0RyeHU3UHBzWGZmanA5ZkUzTWk3KzE3K1ZqL0I1TUNCNEVDQkFnUUlCQU53U01vSGVqSDlTQ0FBRUNCQllqa0grdjdWZXZ2NzUzZVh2N1JwaUV2NUttcy8vSlBJeWVwcktuVmRuei93Vy8reFpqclJRQ0JBZ1FJRUJnd1FMK1NGa3dxT0lJRUNCQVlDMENlU1E4ZitUUjhXcHJaK2ZIWXgzK296UmlmakVGODd4cjJqUkZjNy96TW80SEFRSUVDQkFnMEZrQmY2eDB0bXRVakFBQkFnU09LSkIvbDVWcDY1ZDNkbjVmQ05YZlRBdkFmY3VoKzh3M2hQTWpTanFNQUFFQ0JBZ1FXS3VBZ0w1V2ZoY25RSUFBZ1RrRTdvMmFiMjl2bjdsVGgvODRsZlVYMHFoNVZlNHpEeUcvbis4ejl5QkFnQUFCQWdRSTlFSkFRTzlGTjZra0FRSUVDRHdnY0cvVS9Nck43WC94VGhQK2RscWQvU05sT25zVDAzUjI5NWsvNE9WTEFnUUlFQ0JBb0FjQ2VYVEJnd0FCQWdRSTlFWGdZSVgyL2QzZDNlZlMxbW4vZVJYci96T05tdWR3bnZjenp4dXIrWS9QZmVsTjlTUkFnQUFCQWdUdUUvQkh6SDBjdmlCQWdBQ0JEZ3RNVXQybWVZWDJxemUzdisyOUdQL3JOSXY5bFJUTTB5cHdhVXUxWURwN2gvdE8xUWdRSUVDQUFJRWpDQmhCUHdLU1F3Z1FJRUJnelFMdHZ1YlRYSXZMTjNiK2c2YXAvMEhhTCsyVmxNM3pxSG5lUE0xL2NGNXpGN2s4QVFJRUNCQWdNTCtBUDJqbU4xUUNBUUlFQ0N4UElHOWhQcm0zcjNrZC9rNGFOZitPR0p1MHIzbTFuOWFEc3dqYzh1eVZUSUFBQVFJRUNLeFl3QWo2aXNGZGpnQUJBZ1NPTEpDbnRPZkgvdGFON2U4SmRmaUZkSy81ZDVRVjJxc3FHalZ2Y2Z4TGdBQUJBZ1FJREVkQVFCOU9YMm9KQVFJRWhpU1FaM2psS2UzeHlvMmR2MXBWOWYrV25tL0dHUGRtSzdUbmtYVVBBZ1FJRUNCQWdNQ2dCRXh4SDFSM2Fnd0JBZ1FHSVBEcXE2ZXJUMzNxN3NXYk56ZFBOYzMvbEFMNWQrWHQwMUxMbXZSaFN2c0F1bGdUQ0JBZ1FJQUFnVWNMQ09pUGR2RXFBUUlFQ0t4ZW9MM2ZQSVh6U3pzNzM3QVJtLysxcXNPSDhrSnc2WTM4KytwZ3l2dnFhK2FLQkFnUUlFQ0FBSUVWQ0pqaXZnSmtseUJBZ0FDQnB3cmszMGY1WS8veTd1NzNib1R3RDlQekQrVzl6Vk00ejZQbXByUW5CQThDQkFnUUlFQmcyQUlDK3JEN1Yrc0lFQ0RRQjRFOE1wNm5yMCt2N096OFZCMnF2eHVyK0V3SzUvdnBOVlBhKzlDRDZraUFBQUVDQkFnc1JNQVU5NFV3S29RQUFRSUVUaWlRZncvbElGNXQ3ZTcrVjJsSys1K2UzVytlVm1rUGZrZWRFTlZwQkFnUUlFQ0FRRDhGL1BIVHozNVRhd0lFQ1BSZjRIYTZyL3kxRk01ZmV1blpyZjM5Zkw5NVhneHVMelVzLzI0eXc2di9QYXdGQkFnUUlFQ0F3REVGL0FGMFREQ0hFeUJBZ01BQ0JHN2RPcFhEK2M3T3pwVXIrL3YvOTZGdzduN3pCZkFxZ2dBQkFnUUlFT2luZ0lEZXozNVRhd0lFQ1BSWElJZnoxMS9mMjl6ZXZua25WUDlQQ05XdHRGTDczZFFnOTV2M3QxZlZuQUFCQWdRSUVGaUFnQ251QzBCVUJBRUNCQWdjVVNEdmNmNzY2M2UzdHJlL0prN3FuMGxuWFk4eDVwWGFUeCt4QkljUklFQ0FBQUVDQkFZcllBUjlzRjJyWVFRSUVPaVlRQjQ1VDN1Y2IxMi9maXROYWY4SEtaU1hjSjVxYWVTOFkxMmxPZ1FJRUNCQWdNQjZCSXlncjhmZFZRa1FJREF1Z2RtMDlpdTd1OSthdGxEN21iUkMrM05WM2tZdEJPRjhYTjhKV2t1QUFBRUNCQWc4UWNBSStoTnd2RVdBQUFFQ0N4QTRGTTZyR1A5K1ZhVnducWExMjBadEFiYUtJRUNBQUFFQ0JBWWxJS0FQcWpzMWhnQUJBaDBUbUlYelN6czcvMHhWcFhBZXdwbjBPZTk3YnVTOFkxMmxPZ1FJRUNCQWdNRDZCVXh4WDM4ZnFBRUJBZ1NHS1RBTDUyVkJ1RHI4SDZtUlo4ckl1WEErelA3V0tnSUVDQkFnUUdCdUFTUG9jeE1xZ0FBQkFnUWVJYkNSdDFKTDk1enZ4RHI4dmJRZzNBdmxublBoL0JGVVhpSkFnQUFCQWdRSXRBSUN1dThFQWdRSUVGaTBRSjZkdFgveDVzM05OSjM5NzRVUWRodjNuQy9hV0hrRUNCQWdRSURBQUFVRTlBRjJxaVlSSUVCZ2pRS1RkTzF5ai9sR00vM2ZVemovMnRrKzUrNDVYMk9udURRQkFnUUlFQ0RRRHdFQnZSLzlwSllFQ0JEb2cwRCtuVExORmIxeVkvZC9DWFg5clduay9HNzZVampQS0I0RUNCQWdRSUFBZ2FjSUNPaFBBZkkyQVFJRUNCeFpJTjFxbnNMNTd1NS9rVWJPLzBoc21yMzB3dWtqbisxQUFnUUlFQ0JBZ01ESUJRVDBrWDhEYUQ0QkFnUVdJbkM3eXZlZFQ3ZHU3UHhFcU1PUHhlblVWbW9MZ1ZVSUFRSUVDQkFnTUNZQkFYMU12YTJ0QkFnUVdJYkFxNitlcmw2cjlyZHVibjkzVllXL2tVYk9ZOXJ2M08rWFpWZ3Jrd0FCQWdRSUVCaTBnSDNRQjkyOUdrZUFBSUdsQzJ4VW4vclUzU3ZYcjc4U20vQS9wMVhiOHdXYjlKRVhpL01nUUlBQUFRSUVDQkE0aG9BUmptTmdPWlFBQVFJRTdoTW9LN1pmdTNidGJMVXgrYnZwdnZNelZZeDVhcnR3ZmgrVEx3Z1FJRUNBQUFFQ1J4TVEwSS9tNUNnQ0JBZ1FlRmlnREpmdm45cjQ3MU00LzdxeVluc0labVk5N09RVkFnUUlFQ0JBZ01DUkJBVDBJekU1aUFBQkFnVHVFN2gxSzIrZDFxUVYyLys5dEozYTkxcXgvVDRkWHhBZ1FJQUFBUUlFVGlRZ29KK0l6VWtFQ0JBWXNVQU81NisvdnJlMXMvUHRWYWorV2dybkdjTzA5aEYvUzJnNkFRSUVDQkFnc0JnQkFYMHhqa29oUUlEQVdBUW1PWnlmMzltNUVrUDQ2Vm1qcCttejN5ZGorUTdRVGdJRUNCQWdRR0JwQXY2Z1docXRnZ2tRSURBNGdaQmFWSWJMVDlmaHYwMzduZS9FR1BmU2EwYlBCOWZWR2tTQUFBRUNCQWlzUTBCQVg0ZTZheElnUUtDUEFyZHU1UVhnNHBVYk8zOHBMUXIzUitKMHVwOFNlNzRYM1lNQUFRSUVDQkFnUUdBQkFnTDZBaEFWUVlBQWdjRUx6TzQ3djN6anhoK3FxdkJYMDMzbnNRckJ5UG5nTzE0RENSQWdRSUFBZ1ZVS0NPaXIxSFl0QWdRSTlGT2czSGVlVm16ZnFXUHpQODZha0tlNjV5bnZIZ1FJRUNCQWdBQUJBZ3NTRU5BWEJLa1lBZ1FJREZRZ2gvQzhDRng2eFA4aGpacHZWZTQ3YnpuOFM0QUFBUUlFQ0JCWXNJQ0F2bUJReFJFZ1FHQlFBcmVxZk45NXRiVzcrNWZUZnVmZk1Wc1V6bjNuZytwa2pTRkFnQUFCQWdTNklsRCs4T3BLWmRTREFBRUNCRG9rY0NzdEFQZDZWZlk3ajZINkQ2dDgzM25WQnZZTzFWSlZDQkFnUUlBQUFRS0RFVENDUHBpdTFCQUNCQWdzVktETzRYenp3eCsrR092cXY1dVY3TDd6aFJJcmpBQUJBZ1FJRUNCd3Y0Q0FmcitIcndnUUlFQ2dGU2dMd05WMzcveXRFT3FYN0hmdTI0SUFBUUlFQ0JBZ3NId0JBWDM1eHE1QWdBQ0JmZ25rTGRYU3duQlhkbmIrOVZDSEg0alRacHJTdWx1aSt0V0xha3VBQUFFQ0JBajBVRUJBNzJHbnFUSUJBZ1NXS0pDbXRyKytsN2RVUzV1by9XY3gzM1lleW5acXRsUmJJcnFpQ1JBZ1FJQUFBUUpaUUVEM2ZVQ0FBQUVDQndJZmhQQVEvOHUwYXZ1VjlNWmUrdkM3NGtESVp3SUVDQkFnUUlEQUVnWDgwYlZFWEVVVElFQ2dWd0szYnVWcDdFMmEydjZENmI3ejc4bFQyOVBYdGxUclZTZXFMQUVDQkFnUUlOQm5BUUc5ejcybjdnUUlFRmljUUpuYXZuWGp4bmFhMFA2ZnhpWXQyTjVPYlYvY0ZaUkVnQUFCQWdRSUVDRHdSQUVCL1lrODNpUkFnTUJvQk5ycDdUSCtkVlBiUjlQbkdrcUFBQUVDQkFoMFRFQkE3MWlIcUE0QkFnUldMbkNyVEdPZmJ0M1kvcDQwYXY3OWFmUTg3M2R1MWZhVmQ0UUxFaUJBZ0FBQkFtTVhFTkRIL2gyZy9RUUlqRjBnVks5WGU5dmIyMmRpREg4anJkbWVIL25UQnd2R2xaZjhRNEFBQVFJRUNCQWdzR3dCQVgzWndzb25RSUJBdHdVbXVYcDNKdUduMHRUMnI2NWl6S3UybDllNlhXMjFJMENBQUFFQ0JBZ01UMEJBSDE2ZmFoRUJBZ1NPS3BDRCtQN2xtemRmVFFQbS8wNVpHRTQ0UDZxZDR3Z1FJRUNBQUFFQ0N4Y1EwQmRPcWtBQ0JBajBScURNYUsvajlLK2xCZHRQcDlIei9WUnp2eGQ2MDMwcVNvQUFBUUlFQ0F4TndCOWlRK3RSN1NGQWdNRFJCTm85ejIvYytLTnA5UHk3WTB4N25vZGdZYmlqMlRtS0FBRUNCQWdRSUxBVUFRRjlLYXdLSlVDQVFLY0Y4Z0p3YWJUODFxazBhdjVYT2wxVGxTTkFnQUFCQWdRSWpFaEFRQjlSWjJzcUFRSUVpc0N0VzJXa2ZPdm01MzQwMU9IM3BudlA4OVIyQzhQNTlpQkFnQUFCQWdRSXJGbkFkTVkxZDRETEV5QkFZTVVDZGZYNjYzdm50N2UzMHJacWY3R0thY3Z6RVB6SDJoVjNnc3NSSUVDQUFBRUNCQjRsNEkreVI2bDRqUUFCQXNNVktELzNUOWYxVDRRUVhrak56TnVxK1YwdzNQN1dNZ0lFQ0JBZ1FLQkhBdjRvNjFGbnFTb0JBZ1RtRkNqYnFsMjdlZlBEVlJWL3pMWnFjMm82blFBQkFnUUlFQ0N3WUFFQmZjR2dpaU5BZ0VDSEJmTGljTlcwYWY1aXFPdHo2YW5SOHc1M2xxb1JJRUNBQUFFQzR4TVEwTWZYNTFwTWdNQTRCY3JvK1pVWHI3OFNRL1VuWjZQbjFpRVo1L2VDVmhNZ1FJQUFBUUlkRlJEUU85b3hxa1dBQUlGbENJVHBKTjk3ZmpwdHI1WlhiaThqNnN1NGpqSUpFQ0JBZ0FBQkFnU09MMkQwNVBobXppQkFnRURmQlBMbytYUnpkL2ZyWXhYL2phcUpWbTd2V3crcUx3RUNCQWdRSURBS0FTUG9vK2htalNSQVlPUUNaYVE4cGZRZlMvZWViOHhHei8zOEgvazNoZVlUSUVDQUFBRUMzUlB3QjFyMytrU05DQkFnc0VpQmUvZWVwd250UDFqdVBROGh2K1pCZ0FBQkFnUUlFQ0RRTVFFQnZXTWRvam9FQ0JCWXNFQjduM2t6K2RFcWhHZmNlNzVnWGNVUklFQ0FBQUVDQkJZb0lLQXZFRk5SQkFnUTZKaEFHVDIvZFAzNmk2bGVQekFiUGZkenYyT2RwRG9FQ0JBZ1FJQUFnUU1CZjZnZFNQaE1nQUNCNFFtVTBmT05qZnBIMHNydEY5MTdQcndPMWlJQ0JBZ1FJRUJnV0FJQytyRDZVMnNJRUNCd0lKREQrZjdGbXpjM1l3dy9ISzNjZnVEaU13RUNCQWdRSUVDZ3N3SUNlbWU3UnNVSUVDQXdoOER0cWl3RXR4SDN2eS9VWWFlS1RkNzMzTS84T1VpZFNvQUFBUUlFQ0JCWXRvQS8xcFl0ckh3Q0JBaXNYaUJVcjFVbGtJY3EvRWlhMnA3M1BXOFhpMXQ5WFZ5UkFBRUNCQWdRSUVEZ2lBSUMraEdoSEVhQUFJRWVDWlRSODZ1N3UvOVNTdWJmR0dOc1V0Mzl2TzlSQjZvcUFRSUVDQkFnTUU0QmY3Q05zOSsxbWdDQllRdWtJZk9xU3FuOFQ2V1I4eXFOb09lQWJnUjkySDJ1ZFFRSUVDQkFnTUFBQkFUMEFYU2lKaEFnUU9DUVFCNDluMTdaM3Y3YTlQbTdabHVybFJIMVE4ZDRTb0FBQVFJRUNCQWcwRUVCQWIyRG5hSktCQWdRbUVPZ0hTbWZoTzlQaThNOU85dGF6ZWo1SEtCT0pVQ0FBQUVDQkFpc1NrQkFYNVcwNnhBZ1FHRDVBdmxuK3Y3Mjl2YVpLbGIvYXJyMzNPSnd5emQzQlFJRUNCQWdRSURBd2dRRTlJVlJLb2dBQVFKckZ5Zy8wKzlNSnQrWkZtMy95T3plY3ovbjE5NHRLa0NBQUFFQ0JBZ1FPSnFBUDl5TzV1UW9BZ1FJOUVHZ0xBNFhxdWI3TEE3WGgrNVNSd0lFQ0JBZ1FJREEvUUliOTMvcEt3SUVDQkRvcVVEK0Q2N1R6ZTN0bTdFS2Y2aHEwc0x0SVZnY3JxZWRxZG9FQ0JBZ1FJREFPQVdNb0krejM3V2FBSUdoQ2R4dTl6bXZKNVB2VHRQYkwxb2NibWdkckQwRUNCQWdRSURBR0FTTW9JK2hsN1dSQUlHaEM0VHF0V3EvTkRMR1A5NDJObStBN2tHQUFBRUNCQWdRSU5BbkFTUG9mZW90ZFNWQWdNQ2pCY3JQOHMwYk4zNVBGYXJmMTY3ZW5wNTVFQ0JBZ0FBQkFnUUk5RXBBUU85VmQ2a3NBUUlFSGlsUXduZ2Rtank5L2ZSc2VydWY3NCtrOGlJQkFnUUlFQ0JBb0xzQy9vRHJidCtvR1FFQ0JJNHEwRTV2YjhJZlRlSGMzdWRIVlhNY0FRSUVDQkFnUUtCakFnSjZ4enBFZFFnUUlIQk1nYkpTKzlXZG5XK29xbmlyVEcrdjJnWGpqbG1Pd3drUUlFQ0FBQUVDQk5Zc0lLQ3Z1UU5jbmdBQkFuTUtsT250VFFqZkdlcDZZdlgyT1RXZFRvQUFBUUlFQ0JCWW80Q0F2a1o4bHlaQWdNQ2NBam1jbCtudGFXTDdIeTdUMjYwTk55ZXAwd2tRSUVDQUFBRUM2eE1RME5kbjc4b0VDQkNZVjZEOERMKzZ1L3ZWb1lyZk9GdTkzYy8xZVZXZFQ0QUFBUUlFQ0JCWWs0QS81TllFNzdJRUNCQllnRUNaM3A1R3o3ODloUHBjRmF0cEt0UFA5UVhBS29JQUFRSUVDQkFnc0E0QmY4aXRROTAxQ1JBZ3NCaUJsTTNUMG5CVi9NNzhiL29vWHkrbWFLVVFJRUNBQUFFQ0JBaXNXa0JBWDdXNDZ4RWdRR0F4QW5uMGZIcng1czNOdEsvYVIwczBUOFBvaXlsYUtRUUlFQ0JBZ0FBQkF1c1E4TWZjT3RSZGt3QUJBdk1MbE8zVkpqRitTd2pWVGhvOWIxS1JmcWJQNzZvRUFnUUlFQ0JBZ01EYUJQd3h0elo2RnlaQWdNRDhBaUZPYjFjcG9hZlo3VG1nZXhBZ1FJQUFBUUlFQ1BSWVFFRHZjZWVwT2dFQ294VzR0NzF2UkNsb0FBQkFBRWxFUVZSYUNPSGJ5cTNuNmNsb05UU2NBQUVDQkFnUUlEQVFBUUY5SUIycEdRUUlqRXFnL095K2RQMzZpN0VLdjdkc3I1WnVSQitWZ01ZU0lFQ0FBQUVDQkFZb0lLQVBzRk0xaVFDQndRdVVNRjVQSnQrVW5seE1yYzNUMndYMHdYZTdCaElnUUlBQUFRSkRGeERRaDk3RDJrZUF3R0FGNmhCLy82SDd6d1gwd2ZhMGhoRWdRSUFBQVFKakVSRFF4OUxUMmttQXdKQUVwcmt4YVd1MWo3WmJuN3YvZkVpZHF5MEVDQkFnUUlEQWVBVUU5UEgydlpZVElOQlBnZnh6TzE3ZTJkbE5zOXBmS2ZlZkI5dXI5Yk1yMVpvQUFRSUVDQkFnY0wrQWdINi9oNjhJRUNEUWRZSDI1M1pkdjVyR3pUZFRaZDEvM3ZVZVV6OENCQWdRSUVDQXdCRUZCUFFqUWptTUFBRUNYUkpJTjV4Lzg2SDd6N3RVTlhVaFFJQUFBUUlFQ0JBNG9jREdDYzl6R2dFQ0JBaXNYaUF2QkpkSHpQTU42TjlZUGx1OHZXWHdMd0VDQkFnUUlFQmdBQUpHMEFmUWlacEFnTUJvQkVwQXYzYnQydG1VMEwrdXREcEk2S1BwZlEwbFFJQUFBUUlFQmk4Z29BKytpeldRQUlFQkNaU3QxUGFmbTl4SUM4UzlXQmFJcy8vNWdMcFhVd2dRSUVDQUFJR3hDd2pvWS84TzBINENCUG9rVUFKNjNDOEx4RDJiS202QnVENzFucm9TSUVDQUFBRUNCSjRpSUtBL0JjamJCQWdRNkpwQUNQRnJEeTBRVjBKNzErcW9QZ1FJRUNCQWdBQUJBc2NYRU5DUGIrWU1BZ1FJckVzZzVndW5SUDcxYVpHNGRkWEJkUWtRSUVDQUFBRUNCSllrSUtBdkNWYXhCQWdRV0lMQU5KV1o4bm40Y0NrN3BKM1FQUWdRSUVDQUFBRUNCQVlqWUp1MXdYU2xoaEFnMEZHQmd4Q2RQeDg4ejhQZjdYWnBSNjkwL2crcXpaWGQzZTIwT055SFpxZjVqNnhIOTNNa0FRSUVDQkFnUUtEekFnSjY1N3RJQlFrUTZMbkF3VnowZzg4SHpjbGgvY0hYRHQ1NzFPY1M3c05rY2kxTzl6ZG5CeHdFL2tjZDd6VUNCQWdRSUVDQUFJR2VDUWpvUGVzdzFTVkFvQmNDWmJUNytlZWZ2elk5ZGVxL1NlUG01MEtzUGhkRDJFdTF2NUJTOWQ5ODU4MDNYMHZQSitralQxcy95cU1ONDlQcEsybG1lNTFHMGZONStYd1BBZ1FJRUNCQWdBQ0JnUWdJNkFQcFNNMGdRS0I3QXMxeno5WFZkUC9iUTEyZnpZdTY1WVNkbmxmTnRObE5UNzhwZmN6dUtUL0NTUHJ0MjFYMTJtdFZyS3Zka0V0cW1sUmdtOWxUT1I0RUNCQWdRSUFBQVFJREVIRC80Z0E2VVJNSUVPaW13SFF5ZVRkRjZMZGkwNlI4SHUra3ovdk5kSG9uallEZjJ0cmQvZjVaclk4MkN2N2FhKzEwK0tiNlNEZGJxMVlFQ0JBZ1FJQUFBUUx6Q2dqbzh3bzZud0FCQW84Uk9QMlZyK3luVk4zTVJybzMwdWM4YXlsOTVLd2Rmekw5azhQNWZ2cDQybEI0ZnY5Z0t2eUgyaTNXbm5aS09zT0RBQUVDQkFnUUlFQ2dWd0lDZXErNlMyVUpFT2lKUUJudGZ2dnR0OTlMb2Z4M0g0alNrenlTWHRYMU4xemUzZjJoV1h1ZU5vcGVpbmpwcFplZVRWSCtham1uekhQdmlZWnFFaUJBZ0FBQkFnUUlIRWxBUUQ4U2s0TUlFQ0J3SW9HOGxkckJ5UGNIQmVUOXkvTTk2YUg2OGVybGw1OUpieHhsRkwzNm5idDNyNmJ6OGpacnVhd0hjdjhIeFh0R2dBQUJBZ1FJRUNEUVR3RUJ2Wi85cHRZRUNQUkVJSVh3cnp5aXFta1VQZTZublA1MVYrNjgreU96OTU4MGlsN0NlSnhNTHFaVWYrNFI1WG1KQUFFQ0JBZ1FJRUJnQUFJQytnQTZVUk1JRU9pa1FCdXFZOGlqNlBtMjh6THNmYSttYVlwNkhna1BWZjJUMTY1ZE81dGVmK29vZXQwMDExSXBwMHRwUnREdlVYcENnQUFCQWdRSUVCaUtnSUErbEo3VURnSUV1aWJRVGtGdm12Y2VVN0ZKMmlwdFA0MklmMmp2MUtrL05Udm1jYVBvYmRpdjQ0dHBSRDQvY3Vodm41VXYvVU9BQUFFQ0JBZ1FJREFFQVFGOUNMMm9EUVFJZEZjZ3hEd3kvdWhIbXVQZWpxTEhuN3g0OCtabU9pZ2YrOWlmeTNVMTJjdzNydWM5Mng1ZG9GY0pFQ0JBZ0FBQkFnVDZMUERZUHdUNzNDaDFKMENBd0pvRmNvQXVJOXpwbjNmYXA0L00xR1VVUGRUMTdzWjArbWRMblcrVnJkY2VXZjJVeTlzVjNCLzVyaGNKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1c0TGhQRHdLdTZIYXh4Q25iWmRTeGsrL1BuejI5dGIxZXZWWG5yN3daL05iYm9QOGZvRGQ3SWZMc2x6QWdRSUVDQkFnQUNCbmdzOCtFZGd6NXVqK2dRSUVPaU1RQmxCVDhuNm5hZmNMWjUvRHUrRk9sdy9IY0pmbU5YK3daL05KYUNuK2ZEUDU5WG1QQWdRSUVDQUFBRUNCSVlwOE9BZmdjTnNwVllSSUVCZ1RRSWhQbVVFdmExWDJuYXR5YmVYLzltckw3MzBRbnJwd1h2Ulp5UG85Wm4yOEpMOTE5UWlseVZBZ0FBQkFnUUlFRmlXZ0lDK0xGbmxFaUF3Ym9IYnQ5djJoL0NsSTBEa244VjdWVjF2VGZmM2YySjIvTUhQNTV6R2MwQ3YwMDV0N1I3b2FZdTIyVEUrRVNCQWdBQUJBZ1FJREVqZzRBL0FBVFZKVXdnUUlOQWRnYlJRZTdzUCt0T3J0REViUmYvVG05dmJOOVBoOTQyaWIyMXRuVTJqOFJkbUU5d0Y5S2Q3T29JQUFRSUVDQkFnMERzQkFiMTNYYWJDQkFqMFF1QzExMG8xcDAzemJ0b1dMVDEvYXFiT0IreWxRSDloTWdrL1hrNXVGNHNySjlaMWZTYVZjcTR0YS9hdVR3UUlFQ0JBZ0FBQkFvTVNFTkFIMVowYVE0QkE1d1JDOCtSVjNPK3ZjTGtYUGVYNVA3TzFzL09SOU5aK05kdDJiVzlqNDVtcWFtYjNvRDg5N2Q5ZnJLOElFQ0JBZ0FBQkFnVDZJQ0NnOTZHWDFKRUFnZDRLaEZoL3NWUStQTFIxMnFQYWxIOG1weFhkNitkaVhiV2o2TysvV2tiUU4rbzZCZlJ3NmxFbmVZMEFBUUlFQ0JBZ1FHQVlBZ0w2TVBwUkt3Z1E2S2hBMmhydDdqR3JWdTVGcjJMNDRjczNiNzVhZmVwVDVmeDRxcW5UOVBlbnpwTS81clVjVG9BQUFRSUVDQkFnMENFQkFiMURuYUVxQkFnTVNxQ3M1NVpHdzM4bmxudlFqend0dmIwWHZRNm5RNXordXdjaTlWNzlUQ3B3Y3ZDMXp3UUlFQ0JBZ0FBQkFzTVRFTkNIMTZkYVJJQkFod1JTcUg0dlZTZUg5ZU9NZnM5RzBhdC9iZXZHalcvS3pkbWZOSG1CdUlNcDdzY3BLNS91UVlBQUFRSUVDQkFnMEFNQkFiMEhuYVNLQkFqMFZ5Q3RFUGQrRlVMZU1pMC95cWg2Ky9TSi80WVV4dmZUNlB0R0duMy9xZmJJa004OTZ2bFBMTnliQkFnUUlFQ0FBQUVDM1JRUTBMdlpMMnBGZ0VEL0JVcVlucHhxN3FiaDd1T3M1TjYyUElROGloN1R1UHUvY3ZtRkY3NnVpcFBmU1VFL2o1d0w2ZjMvM3RBQ0FnUUlFQ0JBZ01BakJRVDBSN0o0a1FBQkFvc1JtT3hQOXRNbytQRURlcjU4T2k5bjhyQ3g4Vk1wckIvOHZEYTlmVEZkb3hRQ0JBZ1FJRUNBUU9jRU5qcFhJeFVpUUlEQWdBVDI5dmZUdG1sNUJQMEV1VHFFc2k5Nk92TjdKNkgrUkt6aTd5U2FDK2tqajZLZm9NQUJ3V29LQVFJRUNCQWdRR0NBQWdjak1nTnNtaVlSSUVCZy9RSWIrL3QzMDVacGVhRzQvRGp1OVBRY3d2TWE4TS9HMlB4NGVuYndIMVdGODhMcEh3SUVDQkFnUUlEQXNBUUU5R0gxcDlZUUlOQWRnUkxHOTg3dHZaK21xYjg3eDRCM0NlbXBXVHZwNDB4M21xY21CQWdRSUVDQUFBRUNpeFlRMEJjdHFqd0NCQWdjRWpqOWxkUDdhV3I2M1RrbnBCK0U5RU1sZTBxQUFBRUNCQWdRSURBMEFRRjlhRDJxUFFRSWRFV2dqS0MvL2ZiYjc2YlYxNzg4bTVOKzNDbnVoOXRpV3Z0aERjOEpFQ0JBZ0FBQkFnTVVFTkFIMkttYVJJQkFwd1J5S0QvWUI3MVRGVk1aQWdRSUVDQkFnQUNCYmdrSTZOM3FEN1VoUUdCWUFtWFVPKzJVOXBYU3JEVFhmVmpOMHhvQ0JBZ1FJRUNBQUlGRkNnam9pOVJVRmdFQ0JPNFhLQUU5eHREYy83S3ZDQkFnUUlBQUFRSUVDRHdzSUtBL2JPSVZBZ1FJTEZhZ2FXYmJyQmxBWHl5czBnZ1FJRUNBQUFFQ3d4SVEwSWZWbjFwRGdFQVhCVUowRDNvWCswV2RDQkFnUUlBQUFRSWRFeERRTzlZaHFrT0F3S0FFMm52UXErbzM1OWdIZlZBZ0drT0FBQUVDQkFnUUlQQjRBUUg5OFRiZUlVQ0F3R0lFUWpDQ3ZoaEpwUkFnUUlBQUFRSUVCaTBnb0ErNmV6V09BSUUxQzdTTHhGWFZPMVY1dHViYXVEd0JBZ1FJRUNCQWdFQ25CUVQwVG5lUHloRWdNQVNCRU1OMENPM1FCZ0lFQ0JBZ1FJQUFnZVVLQ09qTDlWVTZBUUlFMHUzbjRVc1lDQkFnUUlBQUFRSUVDRHhOUUVCL21wRDNDUkFnTUtkQUNQWkJuNVBRNlFRSUVDQkFnQUNCVVFnSTZLUG9abzBrUUdDZEF0T21lYmVLZVEvMDRFNzBkWGFFYXhNZ1FJQUFBUUlFT2k0Z29IZThnMVNQQUlFQkNJU212UWRkUEI5QVoyb0NBUUlFQ0JBZ1FHQjVBZ0w2OG15VlRJQUFnU0lRWXYzYk00b2MwZk5RdWdjQkFnUUlFQ0JBZ0FDQmh3UUU5SWRJdkVDQUFJSEZDb1FZNzg1aXVUSDB4ZElxalFBQkFnUUlFQ0F3S0FFQmZWRGRxVEVFQ0hSTW9JeVdoN3IrVW13VHVvRGVzUTVTSFFJRUNCQWdRSUJBbHdRRTlDNzFocm9RSURCSWdhYXEzazhOUzU4OENCQWdRSUFBQVFJRUNEeGVRRUIvdkkxM0NCQWdzQkNCalJqZlR3dTQ3ODhLY3cvNlFsUVZRb0FBQVFJRUNCQVlub0NBUHJ3KzFTSUNCRG9tTUQxMTZtNmEyOTZ1NU42eHVxa09BUUlFQ0JBZ1FJQkFkd1FFOU83MGhab1FJREJRZ1hwL2Z6L0dLS0FQdEg4MWl3QUJBZ1FJRUNDd0tBRUJmVkdTeWlGQWdNRERBbVU2Kzk1MHVwZmVFdEFmOXZFS0FRSUVDQkFnUUlEQUlRRUIvUkNHcHdRSUVGaUd3TWJlM3QycUN1K2xqMlVVcjB3Q0JBZ1FJRUNBQUlHQkNBam9BK2xJelNCQW9Mc0NlMmZQdnAraStidXpmRzZSdU81Mmxab1JJRUNBQUFFQ0JOWXFJS0N2bGQvRkNSQVlnOEF6NzcyM2wvWkJUNlBvSGdRSUVDQkFnQUFCQWdRZUx5Q2dQOTdHT3dRSUVKaFhvSXlXdi8zMjIrK2xiZGErWW9MN3ZKek9KMENBQUFFQ0JBZ01XMEJBSDNiL2FoMEJBdDBRYUZJMUR2WkI3MGFOMUlJQUFRSUVDQkFnUUtCekFnSjY1N3BFaFFnUUdLSkFDTlZYaHRndWJTSkFnQUFCQWdRSUVGaWNnSUMrT0VzbEVTQkE0RkVDWldaN2JLcDJjYmgwTS9xakR2SWFBUUlFQ0JBZ1FJQUFBUUhkOXdBQkFnU1dLOURlZWg3anU4dTlqTklKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1g0SWhPZ2U5SDcwbEZvU0lFQ0FBQUVDQk5ZbUlLQ3ZqZDZGQ1JBWWdVQ2V6bDVHME5NLzc3UlB6WEFmUWI5cklnRUNCQWdRSUVEZ1JBSUMrb25ZbkVTQUFJRmpDb1F3UGVZWkRpZEFnQUFCQWdRSUVCaVpnSUErc2c3WFhBSUVWaTdRTGhLWFI5RGJ1OUZYWGdFWEpFQ0FBQUVDQkFnUTZJZUFnTjZQZmxKTEFnUjZMaENpRWZTZWQ2SHFFeUJBZ0FBQkFnU1dMaUNnTDUzWUJRZ1FHTFhBN2R0dDgwUDQwcWdkTko0QUFRSUVDQkFnUU9DcEFnTDZVNGtjUUlBQWdma0ZRZ2pOL0tVb2dRQUJBZ1FJRUNCQVlNZ0NBdnFRZTFmYkNCQll2OEJycjVVNlRKdm0zU3JlVzlSOS9mVlNBd0lFQ0JBZ1FJQUFnYzRKQ09pZDZ4SVZJa0Jna0FLaHNZcjdJRHRXb3dnUUlFQ0FBQUVDaXhNUTBCZG5xU1FDQkFnOFZpREUrb3ZselZENXVmdFlKVzhRSUVDQUFBRUNCTVl0NEEvRmNmZS8xaE1nc0NLQkVPUGVpaTdsTWdRSUVDQkFnQUFCQWowVkVOQjcybkdxVFlCQWJ3VHlqZWRWbUV4K081WjcwTzJHM3B1ZVUxRUNCQWdRSUVDQXdJb0ZCUFFWZzdzY0FRTGpGR2hpdkpOYWJwVzRjWGEvVmhNZ1FJQUFBUUlFamlRZ29CK0p5VUVFQ0JDWVQyQ2pxdDZyUXRpZmxWSkcxZWNyMGRrRUNCQWdRSUFBQVFKREV4RFFoOWFqMmtPQVFOY0VTaGlmbm1ydWhxcXlrbnZYZWtkOUNCQWdRSUFBQVFJZEVoRFFPOVFacWtLQXdIQUZKdnVUL1hRUHVvQSszQzdXTWdJRUNCQWdRSURBM0FJQyt0eUVDaUJBZ01EVEJmYjI5L01xN2dkVDNKOStnaU1JRUNCQWdBQUJBZ1JHSnlDZ2o2N0xOWmdBZ1hVSWJPenYzMDFMeEwwL3U3WjcwTmZSQ2E1SmdBQUJBZ1FJRU9pNGdJRGU4UTVTUFFJRWVpOVF3dmpldWIzM1F3anZwZzNYZXQ4Z0RTQkFnQUFCQWdRSUVGaU9nSUMrSEZlbEVpQkE0RDZCNTk1L2JpOVc4YTU4ZmgrTEx3Z1FJRUNBQUFFQ0JBNEpDT2lITUR3bFFJREFFZ1RLQ1BwYmI3MlZ0MW43OG16ODNCVDNKVUFya2dBQkFnUUlFQ0RRZHdFQnZlODlxUDRFQ1BSRklJZHlpOFQxcGJmVWt3QUJBZ1FJRUNDd0JnRUJmUTNvTGttQXdPZ0V5c0I1Q05WWFNzdlRYUGZSQ1dnd0FRSUVDQkFnUUlEQVV3VUU5S2NTT1lBQUFRSnpDNVNBSG1ObzVpNUpBUVFJRUNCQWdBQUJBb01WRU5BSDI3VWFSb0JBNXdTYVpyYk5tZ0gwenZXTkNoRWdRSUFBQVFJRU9pQWdvSGVnRTFTQkFJSEJDN1JydzRXOEQvcHNtYmpCTjFrRENSQWdRSUFBQVFJRWppc2dvQjlYelBFRUNCQTR2c0JCUVArRWZINThQR2NRSUVDQUFBRUNCTVlpSUtDUHBhZTFrd0NCdFF2RUVEOFdZNXJlSHNJa1ZjWTg5N1gzaUFvUUlFQ0FBQUVDQkxvbElLQjNxei9VaGdDQllRcTBpOE5OdzZlckdIOHJOVEdQcUF2b3creHJyU0pBZ0FBQkFnUUluRmhBUUQ4eG5STUpFQ0J3WklFU3huL3JuLzdUTjlNWi95U2svZGJTUTBBL01wOERDUkFnUUlBQUFRTGpFQkRReDlIUFdrbUF3SG9GY2hqUDA5clRJL3g4bXVLZTRubWU2KzVCZ0FBQkFnUUlFQ0JBNEFNQkFmMERDODhJRUNDd1BJSGJzK1hoNnZqeEZNN1RkZHBoOU9WZFVNa0VDQkFnUUlBQUFRSjlFeERRKzlaajZrdUFRRDhGWG11bnREZE4rUGtVei9kU1hMZFFYRDk3VXEwSkVDQkFnQUFCQWtzVEVOQ1hScXRnQWdRSTNDZFFGb283VzFXZlNTUG92em9iUUc4WGo3dnZNRjhRSUVDQUFBRUNCQWlNVlVCQUgydlBhemNCQXFzV0tQZWh2L25tbSsrbDZlMy9LT1FaNys1RFgzVWZ1QjRCQWdRSUVDQkFvTk1DQW5xbnUwZmxDQkFZbUVCWnZqMjE2V096TzlJSDFqek5JVUNBQUFFQ0JBZ1FtRWRBUUo5SHo3a0VDQkE0bmtDN2NudGFLSzRNbm9mZ1B2VGorVG1hQUFFQ0JBZ1FJREJvQVFGOTBOMnJjUVFJZEV5Z0JQUVE2MCtIR045SmRjc2o2bTFvNzFoRlZZY0FBUUlFQ0JBZ1FHRDFBZ0w2NnMxZGtRQ0I4UXFVTVA3T1p6LzdWb3JtdnhUYW5kWUU5UEYrUDJnNUFRSUVDQkFnUU9BK0FRSDlQZzVmRUNCQVlLa0NPWXpuYWUxcGZianc4YktTdTRYaWxncXVjQUlFQ0JBZ1FJQkFud1EyK2xSWmRTVkFnTUFBQk5xRjR1cjRlanU1dlIxR0gwQzdOSUVBQVFJRUNCQWdRR0JPQVNQb2N3STZuUUFCQXNjVUtGUGFteVo4TWozWlMxUGRMUlIzVEVDSEV5QkFnQUFCQWdTR0tpQ2dEN1ZudFlzQWdhNEtOTGxpWjZ2cU0ybWUrNitXYWU0V2l1dHFYNmtYQVFJRUNCQWdRR0NsQWdMNlNybGRqQUFCQW1WaSsrVE5OOTk4THkzaS9vOUNYc2c5eGhMYTJSQWdRSUFBQVFJRUNJeGJRRUFmZC85clBRRUM2eEZvNzBPdnFvK1ZqZGJXVXdkWEpVQ0FBQUVDQkFnUTZKaUFnTjZ4RGxFZEFnUkdJZEJ1clJiang4c2k3aUc0RDMwVTNhNlJCQWdRSUVDQUFJRW5Dd2pvVC9ieExnRUNCSlloVUFKNnFPdFBoeGpmU1JmSUkrcHRhRi9HMVpSSmdBQUJBZ1FJRUNEUUN3RUJ2UmZkcEpJRUNBeE1vSVR4ZHo3NzJiZFNOUCtsME82MEpxQVBySk0xaHdBQkFnUUlFQ0J3WEFFQi9iaGlqaWRBZ01EOEFqbU01Mm50YVgyNDhIcFp5YjNNZForL1lDVVFJRUNBQUFFQ0JBajBWMEJBNzIvZnFUa0JBdjBXS0F2RnBYOStMcVgwMUpKMkdMM2ZUVko3QWdRSUVDQkFnQUNCZVFRRTlIbjBuRXVBQUlHVEM1UXA3VTFkZnpJOTJVdFQzUzBVZDNKTFp4SWdRSUFBQVFJRUJpRWdvQStpR3pXQ0FJRWVDcFM5enkvVTlhK2tFZlJmbWQySGJqLzBIbmFrS2hNZ1FJQUFBUUlFRmlVZ29DOUtVamtFQ0JBNG5rQzVELzJOTjk1NFAwMXUvOFd5a0x2NzBJOG42R2dDQkFnUUlFQ0F3TUFFQlBTQmRham1FQ0RRSzRGeUgzb1Z3OGZMUm11OXFycktFaUJBZ0FBQkFnUUlMRnBnWTlFRktvOEFBUUlFaml4UTdrTlBBK2V2bDEzUVF6aTRENzBON2tjdXhvRUVDQkFnUUlBQUFRSkRFRENDUG9SZTFBWUNCUG9xVUFKNmZlclVQdzR4Zmo0MUlnZno4bHBmRzZUZUJBZ1FJRUNBQUFFQ0p4Y1EwRTl1NTB3Q0JBak1LMURDK0JmZWVPTnpLWnIvOG15aE9BRjlYbFhuRXlCQWdBQUJBZ1I2S2lDZzk3VGpWSnNBZ1VFSTVEQSt1OVdvVHZlaHB3RjBDOFVOb21NMWdnQUJBZ1FJRUNCd0VnSDNvSjlFelRrRUNCQll0RUNNSHk5RnpvYlJGMTI4OGdnUUlFQ0FBQUVDQkxvdllBUzkrMzJraGdRSURGdWdUR2x2NnZxVDZjbGVhdXJCUW5IRGJyWFdFU0JBZ0FBQkFnUUlQQ1Fnb0Q5RTRnVUNCQWlzVktESlY3dFExNytTcHJmL3ltd0F2YnkyMGxxNEdBRUNCQWdRSUVDQXdOb0ZCUFMxZDRFS0VDQXdjb0U4Z2o1NTQ0MDMzayszb1A5aVdjamRmZWdqLzViUWZBSUVDQkFnUUdDc0FnTDZXSHRldXdrUTZKSkEyZmM4eHZCNjJXaXRTelZURndJRUNCQWdRSUFBZ1pVSkNPZ3JvM1loQWdRSVBGYWczSWVlcHJoL3ZBeWVoK0ErOU1kU2VZTUFBUUlFQ0JBZ01Gd0JBWDI0ZmF0bEJBajBSNkFFOUxDeDhla1E0K2RUdGZPSWVodmErOU1HTlNWQWdBQUJBZ1FJRUpoVFFFQ2ZFOURwQkFnUVdJQkFDZVB2L1Bxdi8wYUs1cjg4V3loT1FGOEFyQ0lJRUNCQWdBQUJBbjBTRU5ENzFGdnFTb0RBVUFWeUdOOW9HMWQvdkVxcnhhWHA3Z0w2VUh0YnV3Z1FJRUNBQUFFQ2p4R1kvVUg0bUhlOVRJQUFBUUtyRllqeFkrMEZjMHIzSUVDQUFBRUNCQWdRR0pPQUVmUXg5YmEyRWlEUVpZRXlZaDRuMDAra0ozZlRWSGNMeFhXNXQ5U05BQUVDQkFnUUlMQUVBUUY5Q2FpS0pFQ0F3QWtFbW56TytmRE1yNlg1N2I4eXV3Kzl2SGFDc3B4Q2dBQUJBZ1FJRUNEUVF3RUJ2WWVkcHNvRUNBeFNJSStnVDk1NDQ0MzNRMVA5UW1taCs5QUgyZEVhUllBQUFRSUVDQkI0bklDQS9qZ1pyeE1nUUdEMUF1MTk1M1gxc2JKUTNPcXY3NG9FQ0JBZ1FJQUFBUUpyRkJEUTE0anYwZ1FJRUhoQW9OeUhYalhWSjhyZ2VRaDVJYy8ydFFjTzlDVUJBZ1FJRUNCQWdNRHdCQVQwNGZXcEZoRWcwRitCRXNicjAzdi9PRFhoYzdObUNPajk3VTgxSjBDQUFBRUNCQWdjUzBCQVB4YVhnd2tRSUxCVWdSTEdQLzlybjM4N3pYWC9wZGxDY1FMNlVza1ZUb0FBQVFJRUNCRG9qb0NBM3AyK1VCTUNCQWprTUo2bnRhZEhmTDNjaDI2aHVKYkR2d1FJRUNCQWdBQ0JFUWdJNkNQb1pFMGtRS0NQQXZGalZVeDVmVGFNM3NjV3FETUJBZ1FJRUNCQWdNRHhCQVQwNDNrNW1nQUJBc3NXS0ZQYVl4M3pWbXQzMHNja2Zaam12bXgxNVJNZ1FJQUFBUUlFT2lBZ29IZWdFMVNCQUFFQ2h3U2EvUHg4ZU9iWFloVi9kVGFBWGw0N2RJeW5CQWdRSUVDQUFBRUNBeFFRMEFmWXFacEVnRUN2QmZKbytlU05OOTU0UDhUd3lkSVM5NkgzdWtOVm5nQUJBZ1FJRUNCd1ZBRUIvYWhTamlOQWdNRHFCTklpN3VrUlpndkZyZTY2cmtTQUFBRUNCQWdRSUxCR0FRRjlqZmd1VFlBQWdjY0l0UGVjeC9CNkdUd1BJYS9zN2o3MHgyQjVtUUFCQWdRSUVDQXdGQUVCZlNnOXFSMEVDQXhKb0lUeCt0VGRUNmRZL3JsWnd3VDBJZld3dGhBZ1FJQUFBUUlFSGlFZ29EOEN4VXNFQ0JCWXMwQUo0NS8vdGMrL25lYTYvOUpzb1RnQmZjMmQ0dklFQ0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFamkrUXczaWUxcDd2US8vNXRCZDZtdUNlTjBYM0lFQ0FBQUVDQkFnUUdMS0FnRDdrM3RVMkFnUUdJQkIvTG9YekZOUnpTdmNnUUlBQUFRSUVDQkFZc29DQVB1VGUxVFlDQlBvc1VQWStqOVBxa3ltZzMwa05tYVFQbytoOTdsRjFKMENBQUFFQ0JBZzhSVUJBZndxUXR3a1FJTEFtZ1JMR2YvUE1tVitMSVh4bU5vQmVRdnVhNnVPeUJBZ1FJRUNBQUFFQ1N4WVEwSmNNckhnQ0JBaWNVQ0FIOUVuMW1jL2NTZVBtditBKzlCTXFPbzBBQVFJRUNCQWcwQ01CQWIxSG5hV3FCQWlNVHFEY2R4N3IrTEdPdHp5bWFmajc1YU9xcHFtdWVhVGZkUHlPZDVycUVTQkFnQUFCQXQwVGFGY0o3bDY5MUlnQUFRSUVaaUczYnNJblVnTE9DOFhsbjlrNStIWm53YmdROWxJd1B4VW1rL2IzU1ZyUTd0NkM4N0hhdjFmZFVPWC9JSnpyM1oyNnA4cDRFQ0JBZ0FBQkFnUzZKR0FFdlV1OW9TNEVDQkM0WDZDTVFrLzI5ajZkWXUxdnpMSnROKzVEVCtFNzN4Y2ZZdlYvcFhwOWF4V2JmenMyOGFkVElQLzU5UFVYYzEzRHBON0l3VDNVNlQ4c2hIQVEwUE4vYTJoSDIwdUFMeVB1UnQzdjczZGZFU0JBZ0FBQkFpTVZNSUkrMG83WGJBSUVlaUZRQXZyYmI3LzkrU3U3dS84azVlSHIzZGtOUFkvbzEzbTAvTGQrODgwM2Z5NXA1by84bUZ6ZTN0NmVUQ1lmYW1MemFoWERLeW5GdjVKQytZMzAzczBVMUo4cmdUMGZPV3RNYWVRSERadCtNQVNmQnR0VHprOUhIdjdJWjNvUUlFQ0FBQUVDQkFZcElLQVBzbHMxaWdDQmdRams3SnAvVHFmUjZqUXlIZXB2cjVvbWxnWGpPdExBbEp5L2txdHk3ZHExcytrL0pMeWZuazUvNjYyM1Bwcys1NCtmVFIvbGtUTDdtYjI2M2s2ajdDbW94NC9FdW40eGhmWVUzcXZyS1pCdnB4eStGVVAxWENwdlV0V3p5VjBIQWI1TjhBZEZQUmpnOCtzNXdPZkg0YzhIejl0My9FdUF3THdDQjdOZ2NqbDUxb3NIQVFJRUNDeEJRRUJmQXFvaUNSQWdzR2lCTkhyK2MrWGU3dGwrYTRzdS83amxwYTNmVXA1T2oxQjlLWDlLNFR3SDlWQzkrdXJwL0hYMXFVOGRUTVhQOFRxKzlkWmI3NmJQbjVsOS9FejZmTytSd3Z2VzNTcGVDWFg5UWpycDVWVHVDeW0wZnppVnRwdWVYMGxyenUya0dmS1hVbDUvTmprY0N2QzVpSkxlMjM4L0dJWFBieHdLOHZuTC9FaWwzVDhpUDN1eHZPa2ZBZ1FlRnNpaFBIL2svNkVKNVEvN2VJVUFBUUlMRnloL1h5MjhWQVVTSUVDQXdLSUU4aC9IemRiMjl0ZWtrZVZQcGh1NG4wMWY1eitXMS8zenUwbi9yYUJPLzlIZ0g2WXA3UC9KZEQ5KzRyZC80emQrL1lGR1QyYjFQQWpyK2UxUTNVNGZyK1duWmJYM3crK1ZGeC80cDA2ajgxdlRqWTFMNmNETGFVWDdseVlodkpDeStKVVU0aitVWmhOY1MwVmVTaVJiU1dVcmZmMU0rbndxQmZuMDhpR2lRK0c5ZmRvRyszUlVmcEx2aTAvRkg3eDI3N3cyenJjVnV2ZGlMcmw5cWZ4NytQbWhsd2Y3ZEpyNlBmZnIvL3ZPWjkvODZHQmJPYzZHNWUvbHd4ODVrQi84ajZMTWtwbWVPdlhONllYZlU5KzU4M2UrOElVdmZIbDIvTDFqeHNtbTFRUUlFRmlzd05qK3NGaXNudElJRUNDd2ZJSDhjenErL1BMTHozenh6dnMvbjc3NHVoU0s4eC9PT1NTdCs1RUcwdHNVbkVMdmI2ZHF2cDcrdlArWjJGUi8vMHdJbjN6enpUZmZlNkNDZWRaVy9tTStoL0w4K2VCM1VQNTgrSG42c3J4L2NHeisra21QK3VMTm14ZlRmN25ZakUxemJocmoxWFR3VGowSm02bUF5K20yZ08ybUN0ZnJFQzZrVWkrbU5INDV2YitaQXZ5cEZQSlB6NXFRYWpDclFyNXF1WHorZk9qWm9aQS9lN2xKaDZXanl3bmwyUGFmV1RrZmpOYm5sdy9hOStEejlwVCsvQ3VnOTZldmpsclR3LzhoN2I3L1lQYjhqUnRmTmEyYWZ5NFY5TzNwMi95ajZYOHJIOG4vVzcvYk5GLzkvN2QzSi9DVlhQV1o5NnZxWHFsWGRiczMyN1NranVPUWtOQXNob1lrTE1adFkyQXltVGV6SklGNUU4Z3lNSGw1bVF6RGZNSm1JRFB2TzJFTlRuZ0pXWmhoR1RMSlFCSW1rMlNTTVBQaXJZME5HQnQ1QVJwc01FMjNkSy9zZGt2cVJYUzN1NlZiWjU3L3FWdlNsYXh1YTdsTExiK3kxYnE2UzlVNTMxUFN2VStkVTZlbXg4Y25kTDgvZ0xqY0RmRThCQkJBQUlFbkYyajl3UERreitZWkNDQ0FBQUs5RUxBUDBBMU5GUGRmTmNIYUw3aEdZMVpoTWl1bktLVmhXeDNiZWt2UmwwS3lHWDFIa2ZSTG1pVHU1bXBsNW90SGp4ejkzaUs0TkJSWXVrM1hzZWdwY3ovYWU5WDgxLzc5UVhEZ2dEMll2bTV4UXJiSGxsNzI3ZXNiZVBUUkxWRzF1cVhpM0FaTkpMOHRpcVBMdFBLZFFTVWMwTUdGN2FGclhLb1Y3dEtRK3dHRmtVMEs0QmJzMVVzZmJGWWQrM1NBWkoxVjFPZjVOTlRiMXVaS01YY2p1Y3YvT0g5ZnMyQjJ4OFVEdmoyeHRROC9lYUU1dEM1UDluUHJjOXR4bTREZURzWGVyV1ArOXlqNW5kS2xFT2VYTFVORDI3V0RQMGV4MndMNVMvWElNL1Y3b044QjdkNTJnRXBmK25jaWlOMXptM05ORU5EbitiaUZBQUlJdEVWZzhSdDdXMWJLU2hCQUFBRUUyaXJnSjRyYnVXZndUZXF3K2xER0FycFYxTUxtL0RCeERZSDI4ZFhDYS9LQi9wUWV2VTgvM2FibkhRalBuUnRwRG8rMTE2Wkxlc0Jod2JEYTlNR0xmRS9meCt4N2V0dWUzbm83S1Y5YXpvdXNiS21IYklLNzJkblpnWFByMTIvU1VZWDFvWHJwZFdSZ1J5Vm9iTmNRZ3EwNkxYNmpSc2h2MVd1M2g3R0czb2R1cXliMFc2K05ibEw5QjNUL1puME5LR3YzNjhUOXF1N1RFUHlXNHJYZXRnSllFRnBpbWJ0MzZjZm42K2lmdVBTVDVsZmIzUDdDQXdCcG9kTHY4MDlQYnRuOUJQVEZLdm40T1QwZ1pnZTE3R3R1MmI1bno5Nm8wWGl4aFhMdE5TL1VzYWRodjMvcWh5U1UyN25uK2tIelR1aEZmZm82b2JrcW4zMThmSHhVdHdub2M1TGNRQUFCQk5vamtINGdhcy9hV0FzQ0NDQ0FRQ2NFZk9RS1hYUnZiTGtyNlQyMyt5NFVwRHBSaG91dDA4cGhVVThmMXBNaTZZTjlyS0hsR2xudTArY1dmYnRHdDYveEgvalhyenVrMFFCZkRDSjNTeFNIWHpwV3EzMUhyMi90eVV2RGhOVXg3U1cvMFBhOWpSNU12MS9vZWVuOXFWbFM1dVRlNUw3OSs5T2VlVnZYM0ZkemdqdWI1RzdGeTlEUTBJYVR6bTFVcitUR0tBclhOWUp3dlpBMkNtYWJmTFpZbU5lcC9CdTA0ZzJoYzV1ZDAvbjBvWHJzWXczQmo4TDFLbGkvQ3JKUjBjaHViMVprc2prSXJFZXpLbE9iQThBbTVhc0kzL3lUZXRpLy9yTHorcDR1Y3pwek45Skg1cjdicnVYWDRHL00zYjN3UnJML2FXREV3cEMzOEVuODFHTUJ2d2VvREJhZWJiSGZMVHZ3NVpmTmwxKythME8xK253WHVwZHFmN3RhUTE2ZUhWU2laSEpIMisyMVUya1VqSjd2OTZsSSs0UitILzJ1dFNEWXArdmpPd0lJSUlCQWV3V1NOL1AycnBPMUlZQUFBZ2kwVjhBK2FNZWFMTzNTMmY2KyszWGJMazFtSDViVEQrRHQzVnA3MTJheHozclgvU2QvZmVhdjZNc1dINEZWRFp2OS9RRTllcXZ1dTZYUjMzL2Y4VU9IL016d0xjVklEeWF2dEhlOVpSVXJ2dG42L3BqZVRyL2J5bHB2cHl1M3V0cVMxRG41bnR5ejFuODFPLzRscDA5dlhIZjJiUCs1S05yUVY2bjB4OVZxUmIzNW0rSkdvMTlERnJacGgxaW5udnp0VWFDejcvVWN4YXlxaFgyRnNMN1F4VHZVQldxOTk1cElUOUUvQ2plcVNEb21FT2k3VTY5bzJLOWh5OWJUYnpXejBRQzJiOWxCQUxPM3lOWnZyMVBOWnJWdVc4OERtaVR1S2ozR2tnMEIyeCt0emV6N3d0OFRuZGF4NjlGSDkycFd4NnZWNGkvVFU1Nm5KejNGOHJmYTBSclh2aWNIeVB3djV0eDZGdGNzL1p0REQvcGlHWDVHQUFFRTJpaGdmOGhaRUVBQUFRU3lMV0IvcTMzNFU4K3pncXlHb3NhYUtNNzNiR1c3NEJjb25jNjkxZ0dHSkF6TW43dWVCSVZSOWM1K0tYTGhMZXBodm1OaWZQeWhSZXRZU2UvNm9wZjI1TWYwZmZaQzM0TmcvLzZrWU1sNTlXbTR0L3RhYnlmUDZjeS9kbm04UGpzQW9OSExRVFN6YWJQYUoreXJWdnRtbzZnL2pHYmlvS0hlL1lhQ3VWMWVyOUc0WEZjVU9EVlJxOTNlbWVLdzFtVUkyUDVrWHhiS2JUK1o2eUhYN1dEbjhQQnVqYlo1Z1o1d2pYN2NyNmZzMVlFVk84Q2kvKzBmKzJYelBldjJldnV5ZFQzWlFrQi9NaUVlUndBQkJOb2dzSncveUczWURLdEFBQUVFRUZpamdQVmt6dTRjSHJ4Unc1ZC9JNFBub2ErbWVoWVNsdTVkdHdmaTJJYVZmMTA5djE5UU1MeFpKei9mYzNKMDlQaWlEZldpZDMxUkVUcnk0MUx2eitsOTZmZldEUzkxWCt2alptM0xoYjRuai9KdmxnV3NqZE13M1hwS1NCQmNjY1g2SFkzR014VzhyOU9UOXF1Wm42ZmZHYnZzb0c2MjlwTHJaMzhxaWcva3RyNlZMQVQwbFdqeFhBUVFRR0NWQXVrSG0xVytuSmNoZ0FBQ0NIUlRRSiszNzA0NnYreVRkeVlXKzlCdWl3V0hsUzVXaCthWjA4M3FxR2Rkd1Z6clZQMUNuWHNkaGo5aFh3b1pid2xqVjk4eE5QaGwzWDlySEVSM0hCOGIrNlplM3hwVXJBejJaU0hVeXBXR1VkM00zYkpVMlplNnIxMFZhOTJmV20rbjYyKzl6MjViV1JiMDJxWlA1SHZiQk16Wjl1ZFc3em56clQ5dzJRLzJ4Ulg5YmtUWHU5bVpGK3Q1VDFNdmVUT1E2eWNicFpKY2tqSDV2V2pmbFI4YUtsQW45MFVWbmdVQkJCQW9yNEQ5MFdkQkFBRUVFTWkrZ0gzSWpuZnUzdjAwblVGOG56NGQyOFJpOWlHNWwzL0hiV1puWFZmTmYxYWZVVm5zb0c4N3k1TmVoc3kybzhtcWRPWjA4N2lFWXZ4NWJlbHI2aHU4dmVMQ1d5dXpzL2M4K3Vpang3VDkxaVU5Q0wzd25OeldaM0FiZ1d3SjJPK1BuY1poUyt2QnAyRFhybDJiZy9Ycm45dHdicjkrNmE3Ujc0T2RTNjZKQnZWdiszckpreTB2OGE5K3kyZTBKWnZGZmFZeDIvaVJFNDgrZWxpM3JheHpCdzEwbXdVQkJCQkFZSTBDOWtiQWdnQUNDQ0NRZlFIN2UrMkNmVUhmanFORDkrb3orVFBVazI0ZmpOTVA4OTJ1Z1Q4NG9FSTlvQTAvUmVja1grcXZmMjZUVGRsRWNPME42bW5ka25QWExaSG8vSHNmMXROd0VyaWptbHI4TGozeFpuV2RmK0Y0clhheDNuVXJlOXJ6bjY2Yjd3ajBRc0IrcnhmM2tzK1ZZOWZRMEEvSG9YdVI5dTNydGF1L1FEdnVsWDYvVHdPNWhXTWJVcE1jdVVyWE0vZjZOdDN3Mi9DVEE5cnZXK3orWi9ENDQ2K2FtSmlZMXZxVHYwdHQyaENyUVFBQkJCRG96QWNvWEJGQUFBRUVPaVBnZTZzMFVkeWZxQy81MVQwOUQxMUJQS3hVTkp0MzhGdm5HbzNmV3hkRjcxZHY5aS9iaC9pV29KNzJZSGRDSXhuQ25vUVRQNFRYT3RrdEx1aXVHWDBkVklyL2duTExMWlh6NSs4NmV2VG9ZNHNLa1I1RXNQVVExaGZoOEdOSEJTelVwZ2ZXRnZTU2I5MnpaMXQxZG5hZkRqL3QxKy9XZFhyZXMvUTdaWmZWOHpuYy8rTVB6R2tWcXorWDNGYTNuTVVmRUV1RHVYNm5SbFNtOTA3V2F2KzkrV0xDK1hJVWVRNENDQ0N3UWdINzQ4cUNBQUlJSUpBUEFRdThzd3JvLzFvQi9mZDZHZEJ0dUtzbWhkYmx2WVAzVEk2TnZjdjR0ZzBQUDZNU3hPL1VmZi9jT3ZUMGdkNkdxR3UyZGg5R092MStrL2F1VzNDeHk0UHB1NzZTbnNiSGRPdHUzWDliRU1hM1R3eHMvM3B3OE9ENWxpYjNBVjgvVzg4NnZlc3RNTnhzaTREdCs3YVAyZmZGQjRTaTdYdjIvRmprR2xmcnNXdTF1NzVRKys1UXk3NXJlNlJHeXVnUmZ3VEtyMGRQN2VpUy9DNkZVVlYvWjdUbCtGdmEybTlQanRVLzFiSlZxNHY5cnJBZ2dBQUNDTFJad1A3QXNpQ0FBQUlJNUVQQTk2RHZHaDYrV3BkUStrTHo4N0Y5U083KzMzS0ZCbjE0cnlpRTN6SlpxNzljWlVqRGJhQURDSnJZemIxVGllTC84Si9pTGFnbmo2ZTlocDNXVHJhbndxV2hScjJBZnB2cTNkZmw2VUlMSExlcnhMZnErMWZVSTFoZlZDQXJweFY5Y1poYTlEUitST0NDQXEwSGZSYWNvMzNaWlpkZEd2ZjFQYytGN25ydG9GZnJZdlRQMUNraTYyeE50c3RhSXZaZmx0THR2MlJmN01idnVFMzNicjhmQ3VhNklsc2NIOUdtYnh5b1ZqOSsrUERoeDVzMXRZT0VWaC9DZVJPRWJ3Z2dnRUM3QmJyeEI3L2RaV1o5Q0NDQVFGa0Y3RU4vUExCNzk4NytLSHBBSDkxMyt3L1U4OE5sdSt2aUFnMXp0eUh0N3E4VmN2K3AzL2pldmYxcDcvU09QYnV2RCtMd0J2VUlYbWVQTmEvZGJqZTdGZFJ0VzdZMEE0OXVXZmhZMkxzK3BReDB0OUxHYlhyc3RnM09mYU5XcTUzMXIwcitzZmRKSzI5NkFNSkNPd3NDaXdYc2Q5UDJGZnRhZUdCSHZ4TzdqaC9mRzBmUjFZRkN1ZllrdXpMQnBaYS85ZnVyL3kyVTI0UncrdDY5WHZMVzhsdDVMWFQzK1FOWkxqN3F3dUREcm4vREgwdzkvUEFwLzBUTmZSR01CRFlSSkFzQ0NDQ0FRSWNGN0kyRUJRRUVFRUFnSHdMcDMyeTNZM2p3SmdYTDYvWGgzajVZZHp2d3ptczF6MFZmSXFUYnViVSt6TzRZSHY0blNpSHZVQjU1dnIxUVBYTTJrVnphd3ppL3J1N2NzcUJ0Z2QxNjE4MXpickk1bGNzZWUwaXVkMmlFd3MxNnpwZW54c2ZIRmhYTHJPMTFDMFBZb2lmeFl5a0UwbjNZOXBzRnZlUTdoNGQzYXg5NmdVYVNYS2ZjZmJVZWY3ckNyLzg5MVg1bU9NMWg1SDRmdFAzSjF0WHRaV0dQdVhNSzQrRWY5TTNNZkdqdWlnajc5aW1ZajFqZGZLRzdYVUMyaHdBQ0NKUlJJUDJ3VjhhNlUyY0VFRUFnandMcGVlZ2YwQkR6dC9ieVBQUVVUK2trT1IrOXRTZDkvcUNCZmJDM0FCUHNIQnI2QmZYTUthaUhlMzJ2WVcrRCtuenhrNE1jMW51NXFIYzlPS0dpanlpTzMrWWE3cmIxUVhELytQajRtZlNGK3U0RHZyNWIvZXlMRUNPRUFpK3R2ZVFXV3YxK2JmWGR2WHYzeHNmRDhGbmF0MStpdmVLbE9yanpQTjNlcm4xS3owcDd5WFdGQTF0NmQzREtiMTcvTEF6bWNhemg2K0VuNGpqKzdlUGo0NlBOSnpHVVBkWGlPd0lJSU5CbEFRSjZsOEhaSEFJSUlMQkdBUi9RdHc4Ty9sd1VoWi90ZVE5NnN6SktLa3VGZEFzMEZscDltZjFUN1RKeGorMytsNXFBK3MwS0tqK29ubmZkN1RweERYVy91UlgrazRUc3BYdlhiVlVQS1h4OVNaZTh1clZSbmIzenhHRi9IZWpXVGRDNzNxcFJqTnUyRDl1WDdSc0xlc2t2dWZ6eUs2cDlmUy9RN25LOUhuNlJIbjlhTWtTOEdjanQrZlA3a3Eyajk1KzViQ2k5djBSaHBGUGY5Y3NYQm44U3pNYnZuM3prRVp1WHdSYjdYYlhmV1E0Mm1RWUxBZ2dnMEFPQjNyOVo5S0RTYkJJQkJCRElzWUFQdmY3NnlJRzdYL1hZcUM4TER6My9lNjVDTkVONi9LZWFPTzQxVFdOZlhsKysvUnFLZjhET3RRMkNYYnQyYlk3WHJYdURTdjF2MU5PNHV6bnMxNEs2aFZ4N1RSWVdKUzBMWmFyWkUzclhuYTRCSGQ2cmliNXVxUVRSN1kzVHArK2ZtcHBLenRkTlNtN3RZWFd4dHJFdkFvOFFNcjVZbTdWK0pUM2V6VUp2Mzc1OVMyWFRwcXNhemwyckhYUy9kbzU5Mm5jSE10cEwza3FkN01jNktxYnlScll6YW8vOHk3QVN2M2ZpeVBpOXpTY1N6RnZGdUkwQUFnajBVS0RuSCtoNldIYzJqUUFDQ09SUndQNXV1MEFUVCswNGVYSkVJMmlma1pWZWRGOHVYUVpPdlloOTZwejdwQ2FPZTIwVE9BM3A5bU1ZdEFSMURRM2VlVDRNMytqQzBDNGRkNGtQNmpxdlhhRW43WTF1cnFMbjM1S1FiVDJpbHNoOEw2U2FRamQ5UjJRWUhOSkRYMVRMM0ZLSm9qc2ZHeHY3N3FJU20wSHFRRmhmaE5Qakg5Tjk3UWs5eDNZZ3JCSEdMdzVkZUozQzdRdlYrRmZxdTM0RG03M2s4NWRBczk5TGExLzducVZGdmZncWxLNjRZSVZTcVcrS2craTNqbytOM2RFc3BMOWZ0eGVNRG1nK3hqY0VFRUFBZ1I0SVpPMk5wQWNFYkJJQkJCREluWUI5cUc3b2NtWi9vZy9lcjg3Q2VlZ0xCT2NuanJ0UVNMZW5oOEcrZlZWTlFPVm5odGFRL1NIbG5qZnIvbDlUd04rUTRhQ2VWalhwbGZUcEo2ejZ6TzZEbTJXMzJNNVRmeUIwd2MzNmZsdGozYnA3ang4NmRESjlZZk83OVZoYTZHLzlXdlFVZnV5QWdIM3VTY08wclg1QkwvbldQWHUyVllMWjV5bVE3MWZMWEtmSGRWNTV0TkZlNFkvTjJQRVpPNEJrZCtnZ1RYTmR0cDZzTFg1NHZYNlhiRC9UNHI2b09yMzNXSzMydWVUbnVZTUpCUE1tQ044UVFBQ0JyQWpZbXhRTEFnZ2dnRUMrQk94RDk2d0MraHNWMEQrY3VZQ3VOS0FRMHdncmxXb1F1MDlNMUdxdmEvS21QY2l0MnBHQ2VpVU42bjdvZnVodTBCcCtTZUdpb3FEdTE2VUEzQXdhclMvTnpHMEwyY25NOEl0NzE1TkFkMFRaL2NzNmQvMFd1WHhob2w3LzlxS1NtNHQ5MlhvSVRJdHcydkJqR3NqdCsrSmU4bkQ3bmoxUGoxemphalhWUy9YNFQ2Z0poeGYxa2l1UXEybjhuWFBCdGczRjZzZ3FrdG5oRmN5dHVKcjQ3ZjVLRkx6djJHajlMNXBiUy9lMUJRY21PbElTVm9vQUFnZ2dzQ29CQXZxcTJIZ1JBZ2dnMEZNQjM0TythOC91RjhkeGVFZXpKQmJ1c3ZRM2ZTVWgzYXF3SURoY01qaDRWVFVLYmxCb2VxVUZEZlZlS25nb1hHVzcxN0xaRkNxcGxWV2xWcWlyV0xDek92Z2xqcytxb1I1UVV4M1FzUDdiWnVKNFpMcGVuMHhmMlB4dUJ5T3NQVnUvRmoyRkh5OGlZTmoyWmZ1VUxRdkM2R1UvZE5tbGpjZXJQNjVIcjFNRHZVU1BQMVB0MDI5UGJQYVNKd2VGMUhCYWk2MGpTNzlYVnN5bEZqdncwRkNSKzJ4ZjAya1hEMnYvZXQvVTJOaW5kTDg5Wm9zL3NKZmM1RjhFRUVBQWdhd0s1T0ZOSjZ0MmxBc0JCQkRvbFlDRmhuano1WmZ2V2xldDNxLzRzRnZKd25wZUxiaG5hVmxwU0xleVd4M3N2Y21IcWt2MzdINVJIRWZ2MUQwL1pROHFRS1U5ekZtcnF4VnZxY1ZDZHJOM1hiZWVPTmxjVGZmZVpjUGg0MHJsenFuUlVadE5PdzFVdWpsMzRNTFdrOWJkN21kWktKQUdjdnR1VHVhVkxKcXZZZGVKRTA5dlZJTDljcjVPamZCOFBlbHl5OTkyREtVWnlyVy82V2VMNUltNWZjL0RZdlcwMzVVK2pUaFJNSS9ycXRLTjY1MzdUeTJYQkxSZ3Z0QWtEeldqakFnZ2dFQkpCZkx5QmxUUzVxSGFDQ0NBd0pJQzZkOXV0Mk40OENabGl1dlZZMmFYVDdJUDRsbGJWaFBTclE1cEFQZWhkUHZ3N3BkSHpnZDE2L0cwSUdJVHlabEQrank3T3crTFBKYnVYVmRRUEs4S2ZGMVBPRkRSY1BqSDQvaWU2Zkh4aVVXVlN0dllRcnlGcy9rZ3V1aUpCZi9SMnQ2KzdHQ1ZHU3c0ZUxGOTkrN2hJSXArWE5jU3UwNXpsMStqRlA2amRzcUVudWNuOWJOL202K3gxOXRYK2p1bG03bFlGZ1J6aldVL0ZvZkJSK0pLMzBkT0hENTh3dGRndi80ZUhDQ1k1NkkxS1NRQ0NDRFFJcEMzTjZTV29uTVRBUVFRS0xXQUJUVTdELzBET2cvOXJSazhENzIxY2VaQytrVm1kMjk5ZnV0dHE2ZUZLZnNLdGc4Ti9hejZDZFdqSGo3SGZtNEc5VFJrMlYxNVdpeGsyZEI5ZmRmL2kzdlhnMkJjOTM5VjU2NXI1dTNnQzhkcnRXLzQ1OC9YME43RExYUW02MG0reno5YXZGdHBJTGZ2QzRhdEIxZGNzWDc3ek14Vk9tYXpYMUg3V2dYeTUrbjI5Z3Ywa3FlQlBJK2ZnZnp2a3Q5WGtoN3oweHFtLzRkUnBmS2hpU05ISHZGTm5nVHp1ZCtaNHUwRzFBZ0JCQkFvdGtBZTM1eUszU0xVRGdFRUVGaWVnQS9vbXYzODU2SW8vR3h6NkhlV2U1UFhFdEpOeE5jM3BkbXhaL0NYRlV2ZnBobTJmNnc1UkRscjExQlBpN3FTNzJuUXRuQmxNOFBiNGw5dkJ5SjBTNzNyNFIxaEdOOFNWZGQ5NWJIdmZlL29vcFdia1MzMmVsdVhmZVY1c2NxbllkcnFzcUNYL0pMTEw3K2kydGYzQWcxSWVKbHEra0k5L2pRYjVqMDNiRDF4c05la0IzRHkvSmxuWVRCM1R2dTcrMFExckh6dzZPam9JZFV4Q09neDl3ejhnd0FDQ09SZElNOXZWbm0zcC93SUlJREFXZ1FzZE1TYTlmeXA2b0xWcEdQQlJuMVppTW55My9XNWtMNk0yZDFWbFNjc1ZqYzdDT0Y3VDY5UXIrbjA3T3kvVkxYZnJHQzJSeUhXd2xrV3I2SCtoSW9zNDQ0a1lDZkQ0Wi9ZdSs3Y1kxckgzUzRNYm8waWQvdkV6cWQ4UFowSnY3bnUxTXJXa3diMlpXeTI1MDlKeTIwRldkQkx2bjM3OWkyVlRadXVhamgzclhiKzYxVDNxL1RrTFMyOTVFbUl0VitCK2NuZGJIMzVYcHdjTkRtaURrWnB4TDQxWmZocEYwWHYxWHdGQjVzVld6REtKTitWcGZRSUlJQUFBdmwvNDZJTkVVQUFnWElLMk45dkMxL1ZuVU9ESXdvcHo4cEJMN3ExbEpWNVZvRzZMNGdiSDV1b2pmK2FmcmE2MkplbGorVXRTVytoRDNEYnJyeHlhM1R1M0J2VTJmeHZkZDd4TGgvVWc2QUlQZXF0Rm1uUU5pTWRwRkJhczk1MS9hLzY2cjdRSnBjN29LOWJ0Qi9jTTFXdjEzUzdkYkVERzZteHJjdStzckJZbWV4Z2szMjNNaTNvSmQ4NU9QZ2pjZVJlckd0NFg2dG52RmhQdThMWE81M2N6WjV2UXlpVVh2VmEreXJLb29NTituMlFpdXBiYVRiVzMraSs5MDdXYW5jM0swa3dMMHByVXc4RUVFQ2dSY0RlRUZrUVFBQUJCUElwWUtHcnNXTm84TDhvOEw0bTQrZWh0d3JQOWFUcm5QVGZWdUI0bXg2MGNMWFM0QmpxR3VyVnRPZjRzc3N1dTNTMnYvOU5TcXkvTG8rQmxxQnVRYVpJNzNlSjA0VjcxeWMxY2VBOWV0SnRDbmUzVHF4YjkvWGc0WWZQdFRTQVdkaStZK3V4d0cvZnU3bWsyN2R0THVnbDN6STB0TDB2aXA4YnhORkw5ZGkxS3RvejFKYWI3SW5OVXhtSzJVdHVGWnhmL0VFS0MrWjJsK3A5aTFyb2ZaUDEraTNOcC9qN2RYdkJ3WXptWTN4REFBRUVFTWk1UUpFK3NPUzhLU2crQWdnZ3NHSUJDNTZ6TzRhSC81VTZVMzgvUndIZEttbzloSTJ3RWxVVjBqK2drUDUyM1pmMmdDNi9KOTNXWk9GN3Z3TG5nU1RzWGZLVXAveEFwUnE5VlpPci9RdjFNNjh2Mk5EM3BNWUwvMDJEZHJOM1hmT1crOTUxdXg1MmJJODlwTUIraDNxaWIzS3o3aXZIeDhkSEY3N2NoM1g3UEpDdXA5MkIzZHJWMW05ZlZzYlc5cTFzR3hyYVd3bmRDOVVQZnIyZThnSVZmYmU2alMyWk5rTzVCZEZDOXBLTFlzSGlSd1BvZ0lUOVhsdU52eEpHOFhzbVJzZi90dm1zMUpGZ3ZvQ05IeEJBQUlGaUNkaWJKUXNDQ0NDQVFENEZyQ2V0c1czMzdoZHBvcmc3bTFXd2NKV1h2KzBXMG1PRjlJcEMrdnNWMG05UTJTMkVXQjFXRXhMdHRmYmxlMlczNzluejlOQTEzcVkxL1pKQ1R4SldkVkJBT2o0QTZYbEZYQks3Qy9hdUI4ZURVRFBEQjhIdE9wMzUxbzFoZUgrdFZqdTdDTUo4YkQwV3BGZlREcmE2dEMzczlRc0M1ZVdYWDc1cnRsTDVDWjFEZnIyQ3VJYXRCOC9TQVlVK2UxR3psOXl1RzY5dEs2WGJmOG4rbkpkOTJxcXgwaVdwcjRLNUhWalI3OEkzTkJIZ2V5Zkd4ai9UWEZGcWFZNnJiWStWbG9ubkk0QUFBZ2owU0tESWIzZzlJbVd6Q0NDQVFOY0U3SU43UExCNzk4NytLTHhmZVdaUXdjWSt4S2REWUx0V2tEVnM2RUloM1ZiWjJ0TzZrazJrZ2NZSDlaMTc5dXh6Y2VNRytmeXN2ZWtwQk5xbHplejhYbk1xK3Z0Z0dyVE4wdXJiMnJ1dUg0UHZLQU4vUVRhM1ZLTG9ycU5Iam56UDdteFpVcU4wUFJjS2lHWnVsdlpsMjVwdnU2YytkZDNPbVRON1l4ZStKSXFENjdXQzV5dUlYbXI1VzQxaDdXR3hVMjJsNzhVN2wxd1VGMXpNeUg1Zisrd0FraVpPL0s0T250dzRNVmIvV1BOK2U2RWRMUEg3c2YzQWdnQUNDQ0JRZklHaWZ6QXBmZ3RTUXdRUUtMTkEramZjN1JnZS9MeUMxc3ZVKzJZelB1ZXRoL2hDSWQzQ29IMnRka25EWlJMVWg0YXVjYUY3bDV5dXR4VXFHS1k5dS9hOE1peUo1M3p2dW1ZR3QxN3FabEFPZ2xQU3ZrOUd0MVRDeW0zQjJiUDNIenQyN1B1TFlOSjl5K3hzLzdOZ2J1dE5MWFZUMTZzZkhCelN0NS9VRTY3VklZRnJoUDJqQ3FIZXVUazNRTkpyYk51Zlg0Kzl0QXlMZWRrKzZZTzVmbWNmRWNLSHduUG4vcWpGMjV6TmRDMzd2MTdPZ2dBQ0NDQ1FOd0Y3WTJSQkFBRUVFTWl2Z0gyUW45MHh0UHQ5WVZSNWU4N09RMjlWdjFCSXQrZk05OGEydm1MNXR5MFlXdER4NjlHbDZmNmgwdUU3bFEzdDJ0azI5TjB1eldidmgyVUo2bGJ0ZEdrTnloYllyUmZiaGxuYnQwUHEzUDZpd3JYMXJ0LzUyTmpZZDlNWExmNitlL2Z1alkvclNnSjZ0UVh5L1hxTjlaSnZtd3YvdnBkY0I0OXNLVmN2ZVN2Vm9tQWVIOWZSa2Q4NzU5eEhwdXYxU2Y5RXJtWGU2c1Z0QkJCQW9KUUNCUFJTTmp1VlJnQ0JBZ240Z0w1OWFPaG5vekQ0YjgxZTRid0d6UXVGZEFzMjdlaEpOQ3NMNlVsUUg5NzlLdWZDRzNScHRtZjdZZFpKVUUrSHh4ZG9GMWxXVlJMamx0NTFCV2xiSks5bWNXNWFOeC9RazI0UDQrQ1crT3paa1hqZHVtM1ZTdVZGNm5GL21WckhEbmI4aUIrcW5UemZOcHBlQXMwK2E2UkQ0TzMrTWk1MjJiOW1qM21zYy83RC82U2ZQNmg1RitvZVk5KytQbDJOd0hyTTEzb3d5cStPZnhCQUFBRUU4aXRBUU05djIxRnlCQkJBd0FRcytNU1hEZy8vVU1QRkQraTJYWkxLd2xaZS83NWZLS1NyU20wTEwvNmdocTFRUzBVOTZyK2lidVMzS1Z6K3NQVWNxL3ZZZXRUTEd0UVRsZVRmcFh2WGs5N3dJekxhcWdCL2lYOXFHc3JkWEMrNUhTVEs2ejdZYXJDVzIzWmtRNU1TaGhYdFc2R04xRkNQK1I4TDVmM0hhcldIbXl0ZWNOQm9MUnZqdFFnZ2dBQUN4UkRJYXk5TE1mU3BCUUlJSU5BbWdkT25UbjEvMDVZdFA2L0FkSmxXYWIxd0ZqRHp1Q2pENkwvWTJlenVMOWt3c0dYOTJWT25ibFpGMmhuMnpNZldaK0dvY2ViVXFmdTJiTmo0U1JlR3gzVHZNOE5LNVJJRkszdmNlajNMM1BPcmx2QUhLc3pDRHB5b1J6eE83Q3lZTzdkZTdaVGVseHdVc210M3o3OUdMeXZwWXBQZWVUMDc3OTdHSWJnL3IraHFBc2ZxOVk5cGY1dVNpdTE3dG5DZWVlTEF2d2dnZ0FBQ1RRRUNPcnNDQWdnZ2tIOEIrMXMrdTJIckZsMURPbnAyRUN0RUpTRXByelc3VUVodjkwR0hKR3p1Qy9wT2YrZjA0MmVtcCs5YXQzM0hKNk5HL0xnUzZUUFU2emxBVVBlN2tBVjBhNU9vSlh5Ym5kMmIzbGZtQXhtZXd2K1RYTWJQaFZGWXRWeXVVd1ArWGdjMmZtV3lWdi8vVGs5UEg5VnpDT2J6V3R4Q0FBRUVFRmhDZ0lDK0JBcDNJWUFBQWprVHNML2w4Y2F0bHd5cXErNGZLbFRtUGFBYmZ6T2t4dzNyU2Q4NHNDVlV6K050dXIvOTcxdVBORWNjN0F1cWozL3J4Qmx0NS9hTjI3Yi9hWkJNOHY0c0JmVU5QcWpiOE8xOEgvZ3cxM1l0U1dodjE5cnl2eDZOSkFnc21OdEVlNUZ1Mys2aStOZW14c2JmZlhaNnVxYnEyWDVyQnpIb01jOS9XMU1EQkJCQW9LTUM3ZitnMDlIaXNuSUVFRUFBZ1NVRS9CRGtEWnMzOStteDF6WkRaSjdQUTArcmFJT0UwK0h1MTI3WVBIQmVZZWNMZXJBVDcxMHVTSUo2R0dnbTdUTVBuRHgxNXRUMDU3ZGNzdTNQZFc3L2VoWGoyUXJxZlFycTZYbkZCTlMwbGNyOTNTYkNpN1Z2VkMyWTY1ZHVST0g4MXpYNTI5dlBucHcrSkJvTDViYS9Fc3pMdlo5UWV3UVFRR0RaQXAzNGtMUHNqZk5FQkJCQUFJRzJDUGlBWGgwWU9GdUp3bDlVcU4yaXRkb1FaQXNIZVYrc0o5MW1FbmZxU2IrK3d5RTlzVG84WjFjNWZmTGs1TmxUMDMrM2Z1dld2NHFjMjZZblBGTmhMSEZOaGpNWHdUanYrMGd2eW04VDZEVjBCWUNxN1E4NmF2TXQ3VFZ2MFZEMmY2VTVFeDVVZ1d5dnRlSHM5bnVZbkE2Z0d5d0lJSUFBQWdnOG1RQUIvY21FZUJ3QkJCREloMEI0Zm5yNnpNYXRXLzZCRXUwUHFSZFB3OXdMRWRCTjM4Sk9kME82VFlvMmY1Q2o4dmlwVTQ5cTZQdGY2alNDejJuQ3I4dDFFT1JwemFITXlhV3hrc01JU1RsOVlmbW5vQUlXdHUxNjdsVk5KcWlETSs2d2RzOTNUYTViLzMrZFBYSmtwRmxuZ25rVGdtOElJSUFBQWlzWElLQ3YzSXhYSUlBQUFsa1U4S0ZnNDVhQnA2dEg3OFYrdHUxaW5TL3QrOUhuZXRLM2Fyajd5WTROZDI5dDN6U28yL3RscE43Um1vYStmMmJqd01BZCtubVB6am0rc2huVTdZQ0lQWmNlOVZhOTR0eTJ0azJDZVJSVk5QdmJZenJaNGQxdS9ZYlhUaDArZkdjd05kVUlkR3BFY0hqdXdFNXhhazVORUVBQUFRUzZLa0JBN3lvM0cwTUFBUVE2Sm1EQk1ONndaZXNsU3JLdlZFeHdCZXBCVDlIbWU5TERMZzEzVDdlYzlLaGJNUXBmZkFBQU44OUpSRUZVU0xQM3pWRG53aC9TMFBjLzNyaDE4MzBhZkgrbGd2cHdFdFQ5UkhJRTlYbTN2TjlLZzdsZHk5emEvcVIyaGQ5ZEY3dlhQRmF2Zi83czFOUzVZTisrdnVDUlI1ekNPVVBaODk3YWxCOEJCQkRJZ0FBQlBRT05RQkVRUUFDQk5nbTRnYTFiejhmT2FhSzRZSjNXYWVHaWFNT3VGL2FrZDNiaXVLV2F4VXh0c1JFTGdYclRIMVN2K3NjM2J0MzZiVDN3TklXNHkzVzNadkgyUWQyZVVqUi9xMU01bHFRTmZUQlhqL2s1OVpoL1ZGY3dmTTFVZmZ5dnBuVTZTYlBIUEZBNHQ5TWNXQkJBQUFFRUVHaUxBQjhjMnNMSVNoQkFBSUhNQ0ZSMkRnM2VvM09rbjZONTFTdzRGUFZBckFWbFhkWktFM1ExNG5kTTF1dnZhOWJWZWpIVEVLMmJIVjhzcU52UVoxdXFPNGNIWDZkTS9oYjVYK2xpWDhRWjNXOXR3TkIzRThyK1ltTlBHanFzWXBkTHMrdVkyMGlVUHc0YTdnT1Q0K00yK1pzdC9uUVNmYWZIM0hQd0R3SUlJSUJBT3dXSytzR3RuVWFzQ3dFRUVNaUxnUDFOYjJ6WXV1VUZPdjM4cWtEZGZRcUtSUTJHdmU1SlQvY0pDMm4rMG13YTRqeXJIdld2RG16WThBbFhxUnpYL1RiaisxYjFwbHRaTGFoYlczQmdYQWlaWEp3T3ROaUYvWFF0Yy8ycjYvdTV6NFlWOTB1VG8rTWYxU2tORXlxekJYTnJQeTZabHNrR3BGQUlJSUJBTVFRSTZNVm9SMnFCQUFJSW1JRDlUWTgxMC9oVGxDNStXajJCUlR3UHZiV2xrN0RielV1d3RXNjk5WFp5L3JHVnAzcjY5T2x6bXZIOVM3cnMzYWVxR2hxdHNHZlhVTjlFVUc4Rnk5UnRYY3ZjUm1PRWRpM3pVRGR2aW9Mb1Z5Zkdhcjl6NXVUMEl5cXAvVjdad1JXQ2VhYWFqY0lnZ0FBQ3hSUWdvQmV6WGFrVkFnaVVVOEFDb3Rzd01LQ2VQdmM2OWZWWnFMQngxa21RTGFhSnIvUGM3TzREVzg3cG5QQTdWTlYwR0hLM2EyMDk2cEVtRHF1ZWYraWg3NStabnI1dHcrYk5uOVlCRXl2blZRcnE2M3hRVDg1dkx1cm9obTZicjNaN2FUQzM0ZXhxQzNkbjZNTFhUOVRxLzE0SFdFYTFVb0w1YW1WNUhRSUlJSURBcWdXSy9LRnQxU2k4RUFFRUVNaXBnQVcrZUdCd2NFZC9HTnlubnR0aGhjRWluNGZlMmt6ejU2Uzd4cTlQam8zL2dSNjBrTjdMWGs5ckQvdnk1Nmp2R2hyNllSWHliZXFoL1JVRjlZcUxkWks2dFUrb0lkWEZQb2lpNm1WcVVURFh1ZVZSWkQzbXVobmZxNU1RUGpBMVd2K0xaaW50czVHMVNUcTNRS1lLVDJFUVFBQUJCSW90UUVBdmR2dFNPd1FRS0pkQStqZmQ3UmdhK2wvS0hxL1FSR1YyWHEwRjFUSXMvbnp3NWpEbE4weU8xZjlJbGJhNjl6cG9wUUU4Q2VxRGcxZTVLTGhCRWZHVlNVQjBzY1k1MkhYVXk5Sk92ZG9YNVN6ck5Kakg4Y05SR0wzdjJOallwMVNnWkM2QkpKajM4cUJPcjJ6WUxnSUlJSUJBUmdUc3lENExBZ2dnZ0VBeEJLd1gyY0tnK21QZFY5VXpxeHQyVjJrV2UwOXJUcndkL3FGbVZIKzlmclpRYk1FM1BYaWhtMTFmTFBCWk9heHRLc2ZxOWZzbnh1cXZxa1R1eFNydDM5dndhanYvV1kvWjgreUxwYjBDRnI3OUpIMWhwVktWK1pnR0w3eHBvTnIzVElYelQrcXhPTmp2OXhIN1piRjJLdFV2amVyTGdnQUNDQ0NRSVlIa2cxeUdDa1JSRUVBQUFRVFdKR0FoTmQ2NFpldFdKZEpYNmJhRmpUSWRqTFVnYmlFM1V2RDlSeHUzRGh6VnpPcDM2MmNMd0JiVWVybFlXOWlYdmZkR3AwOU9IMUhaUHIxKzY5WXZhMmF5SDFCNWY5REN1cDVobC9rcVc3dDFvbDNtVGlHd1V3cDB6YlFKM2ZHK3VIL2RyeHcvY3VUMkV5ZE96QWI3Z3I3Z0VWa2Y3dm0rMFluNnMwNEVFRUFBZ1J3SzlMSkhJWWRjRkJrQkJCREl2SUFQNkpmdDJYUGxiTng0UUtYZHJDOExlMlg3ZTI5aDNFSzZWZi8vVm8vMVIzVWo3YVUyanl3czZVRURmK0JBcHlYOE00MThlS2ZtazN1dUwyQWM2L1FFWHdFT3BxK3N0ZEpnWGxVd0QzU3UvN1F1Wi9EUlNyWDZ1OGNPSDM2MHVhcXM3UXNycXlIUFJnQUJCQkFvckVEWlByQVZ0aUdwR0FJSUlMQklvTEp6YU5DR3VWK2xNZC9XbzF6R2tPZnJ2VVJJOStlQ0wvTHExWS8yUG14dFkyWDF1WHpIbnNGZlVuL3VEUXFYUDJwem1lbDY5aGJVN2NCTG1VWkNxTHFyV0pMWjhaTmc3cHlHdGJ1UFY4UEtqVWRIUncvNXRWbVArWWkzN3ZWb2lsVlVqcGNnZ0FBQ0NKUkJvSXdmMk1yUXJ0UVJBUVRLTGVBRDM0YXRXMzVTdWU0cUJUeE5RT1lEWHRsVS9HZ0NWVm9aL1FuRDNiUFNpMjV0a29aRjM2Tis5dVQwQTJlSDkzeHN3K09QUDZZZTlhZUhVV1c3enB1MklHL25VZHQzRHE0TG9XVlJqN2svTFNEUU9lWVZtNFZBUDMvR1JkRXZUbzNWUG5YNjVNbmplcTdaQmhyT1BuY2d4UC9NUHdnZ2dBQUNDR1JNZ0lDZXNRYWhPQWdnZ0VBYkJPeHZlN3h4NjViZENxWS9yYkJpTTRTWHRmZlZ3cXlGc2l5ZWs3NjRxUzJvVzNtcndiRmpNN3FlKzkwYkxyM3NQd2N6czZkMDM3UFZvejdRRXRTdFBRbnF6VW4xTk1sZXhRN0R5T1J2ZEN6cU5aTzEydStmUFhueW1MZE1uQWptd21CQkFBRUVFTWkrQUFFOSsyMUVDUkZBQUlHVkNsaFFjUnNHdHFqWDBMMVdNYzcrMWx1UGNWa0RYVjU2MHROMlRvTDZ2bjE5Wnc4ZVBLdWdmdWZXalpzKzFZakNHWVZRQytvYkNlbzY2S0orY2d2bU5qeENuZWEzYUtLOTEwM1c2dTgvYytyVXVDQnRuN2QySjVpbmV4WGZFVUFBQVFSeUlWRFdEMnU1YUJ3S2lRQUNDS3hTd0FmU2djSEJIZjFoZUw5aStaQUNuUVdWc2grVTlRWkpSK3VDaWVPeWRFNzY0aWFQTk5ONFJlZE4yL0QyWU52dTNYczBGT0J0Nml2K0Y3cWU5M3BOZ0taREwzYXRlMytadHNXdkxlTFBhVEQzUTlZVnpMOFNSdTQ5RTZQamY5dXNiTHFQVzF1eklJQUFBZ2dna0R1QjlJMHNkd1dud0FnZ2dBQUNGeFVJejA5UG45bTBaY3ZMRmVhZVd2Smg3aW5Vd3A3MExWdnE2bTM5YXFDZTZ1Q1JSOUx6d05Qblp1VzcwM25UVmpZcmUrWHg2ZW5qWjZlblA3ZGg4OEJmNnNETGdPNTdWdk84NjFodGJKZG5zd1B2UlR6NGJnYitRSVJHRUVRNnkvenJZUmkvYWJJMi9xWXpKNmUvM2F5emhYWjZ6SVhBZ2dBQ0NDQ1FYd0VDZW43YmpwSWpnQUFDRnhPd3NCSnYyRHJ3WXpvbjl5VjJyU24xc2xySUsvdGk0ZFZDWENTUG45bThkZk9EWng3ODl0ZWExOFBPYWtpM05yTlRGS3g4OXI1ZFVVaC83T3lwNmIvZWRNbm12M2R4c0ZOMWVicEdCbGo3cGhPbUZhV3RyZDVwTUs4b21CL1NnUFliSnNmcXI5YzE1TCtteDJ5eGZUMzE4WGZ3RHdJSUlJQUFBbmtWS01vYmVGNzlLVGNDQ0NEUVdRRVhqbWdJdFBwVS9RUmFuZDFXZnRadUlWZERwVzMydk9qUGR1MFpmS1VmUW02WDRNcitZZ2NYYkVpK0Qrb1RvNCtNNkx6cm45WFJocGNvbWQ5a0lWMy9WWDF2ZW5JZ0l2czFXcnFFZGpEQ3oxcXZIdk0rdFZWZEI1bmV2RDZPbnpreFd2K1BlbXcyMk4rY21UM3hzSURPZ2dBQ0NDQ0FRTzRGaWpnTUx2ZU5RZ1VRUUFDQk5nallBZGg0NjU0OVYxYmp4Z082dlZsZkZtTDR1eStFNW1KaFY3Ti8yeFR2d2F1T2pkYi93dmVrTjgvM1RwK1U4ZS9wU0RpclM3QnRhT2lub3NDOVMwSDloZmF6Qms1WTc3TzFlZm84dXp2TGkrMmpkZ0NpVDhIY3luOWNvL1kvZk02NTM1K3UxeWQ5d1pOcm1kdHpDT1VlaEg4UVFBQUJCSW9rd0FlMUlyVW1kVUVBQVFTZUtCRHRHQjY4UnlIbnVacFFLd21rVDN4T21lOXBoblJkaHk1MGVRM3AxbjRMenIvZVByejdWWkVMMzZhSjVKNWpsd1VQa3FCdUIyMnlPbkp1Y1RBL284TUs2aW1QYnB3WUc3TloyUU0vVjhESUNNSGNZL0FQQWdnZ2dFQlJCZkp5Ukwyby90UUxBUVFRNktTQS9ZMjM2NkgvcEVZK1AwY2hqZlBRbjZodGdkVkNlcVNFK1BPYkw5bnlyVE1QVG44OUIrZWtMNjZKRFFtM2crNytmR3lkbi80Tm5hUDk4ZlVEVzBiVkQvMWpta2h1bDM4OG1mSGRYcHVkQS9SSm1TcnFNYS9ZalBTNlhOb25OV1QvMVJPMSttYzBpZDkwY3hLL1FCUDUrVkVDVm5nV0JCQkFBQUVFaWlwQVFDOXF5MUl2QkJCQUlCbldIRzhhMkhLNXVvZi9rUVlFTzhXeXJQYWc5cks5V2tKNnFKQStrTmVRYm9iSlJIZDJmdmJob0tGcnFOKzNmY3ZXajU5M3diRXdjTTlRVUw5RUlkakN1VCsvVzk5N0ZkVFR5ZXdDSDh5dElMSDdzemdNWHoxVnEzMWN3WHhLZDluQmhqU1lNNXpkWS9BUEFnZ2dnRURSQlhyMXhseDBWK3FIQUFJSVpFSEFEc0kyZGd3Ti9iaE8xNzFMdCsxdnZnVWQvdllMWVltbE9kdzkxK2VrdDFZcjFFaUFhbm9OOVV1dXVPS1NhSGIyalFycWIxUW8zdUd2b1o0RWRRdkMzZHduekZsbnhpZFhGZEFRL0wvVEtQejNUdFhyWDI0VzNvOEMwRzE2ekpzZ2ZFTUFBUVFRS0k5QU45K1F5Nk5LVFJGQUFJRnNDRmpQc0UwVXQwMFR4ZDJ2U0xSSHZhZEpDTTFHK2JKWWltWkl6LzA1NmEyMlliQmZrOFFkOEpPdkJaZis0S1dYemM3MC80YUMrdXNWMUFlYVFiMWJCMjZjSlhNcm5JTDVBWjFZOEo3SjBmR2JtNFZOUi9VUnpGdGJqOXNJSUlBQUFxVVNJS0NYcXJtcExBSUlsRXdnL1J2dmRnNE5mVTU5cEQvbFlxZFp2WnREaDB1R3NZTHFOa042UzA5Nk10emFKaWpMOHhJcHFFZHBVTDlNTS93M1hPT3Q2cjMrVlZXcVgxK2REdW5wK3U5VEIvcHZUZFpxZjlYRXRBTko5cFYzMzJaMStJWUFBZ2dnZ01EcUJld05rUVVCQkJCQW9KZ0NGb2lTWHNrb3VFYzk2UHJSN21KNUVnRi9hb0JSeFM3OGMzK2RkQXVQKy9ibDRUcnBGNnRhM0F6bjl0NWZQVG82ZW1oaXJQNTZuUXorRmQrcDdUbzZwRHdKNTJFWVY0UHdsNXZoM0p4dE9MdWROMDg0RndJTEFnZ2dnQUFDQkhUMkFRUVFRS0FFQXBvWDdGNk5LYll6Zi9tN3Y3ejJib1owcDVBZS9MbGRYendZR1prSjl1NjFudWE4TDJrZzlwT3c2Uko4M1J0UzdqU2d2bEx4MnhXaUhURWltT2Q5YjZMOENDQ0FBQUp0RmVDRFdsczVXUmtDQ0NDUU9RRS9xM2MxaXI2bWMzNm5WVHI3dTA4Myt2S2FhYTRuWFpjcSt4ODdCd2V2RFE0ZVBGK0FudlMwOW1rd1QwK0ZTTy92eFBmNWJZUzZrRnF5cE44N3NUM1dpUUFDQ0NDQVFDNEZDT2k1YkRZS2pRQUNDQ3hid0FmMG8wZU9ITkVJOSs4MDUrZnk5eTE3RGVWK29xN043WHQ1cTdvNDJlZDlTTGVlOVB3UGQyOXQxVzRFNVc1c283Vk8zRVlBQVFRUVFDQ1hBZ1QwWERZYmhVWUFBUVJXSkdBOXdiR0d1ZHRNN243NjdCVzl1dXhQdGtuMTVrUDZUUVVONldWdlplcVBBQUlJSUlCQUpnUUk2SmxvQmdxQkFBSUlkRlRBRHkvV3lPSjdrcTBrbDducTZCYUx0dkw1a0Y0cGNFOTZKMXR0Zm9oN0o3ZkN1aEZBQUFFRUVNaTVBQUU5NXcxSThSRkFBSUZsQ1BqaHhUWlJuS2JvaWpVMWwvV29NK1I0R1hBTG5qSWYwbTI0T3ozcEMzQ2U5QWYydHljbDRna0lJSUFBQWdna2t3WGhnQUFDQ0NCUWJBRWZqbWFDNEdGVnM1WmNiczFmMnFyWXRlNUU3ZVpET2ozcEsvT2xCMzFsWGp3YkFRUVFRS0NrQXZTZ2w3VGhxVFlDQ0pSS3dBSjZlS3BXbTlJbHRRNzZwS1NMWDVkS29KMlZuUS9wUlprNHJodmhtZjJ0bmZzZzYwSUFBUVFRS0t3QUFiMndUVXZGRUVBQWdUa0JDMGMyckYweDNYMDE2VUVuTDNtUDFmNVRySkRlaloyaEd3Y0JWdHVhdkE0QkJCQkFBSUhNQ0JEUU05TVVGQVFCQkJEb3ZJQTZ6a2NDcHp3V2h2ejlYeXYzd3BET09la1g5K3pHUVlDTGw0QkhFVUFBQVFRUXlJRUFIOUJ5MEVnVUVRRUVFR2lEZ0wvMmVUWHErNXB6N3Z0YW4vMzlKelN0RlhZK3BDZm5wQThON1Evc091bDc5L2F2ZGRWZGZIMDNlcmU3c1kwdWtyRXBCQkJBQUFFRU9pTkFRTytNSzJ0RkFBRUVzaWJnQS9yUkkwY09xL2Y4d1RDNTBwcS9MMnNGelYxNTBwQWVobFdOVVBpZk80WXZmMzV3OE9ENUhJWDBiaHlvNmNZMmNyZnJVR0FFRUVBQUFRUVdDeERRRjR2d013SUlJRkJjQVg5NXRkQUY5L3Z6ME5XVlh0eXFkcmxtUHFTN0dibXVEMXpsMXAzRFQzbGV6a0o2cDhIb1FlKzBNT3RIQUFFRUVDaUVBQUc5RU0xSUpSQkFBSUZsQ2FRaDZaN2syVWszK3JKZXlaT1dJOUFYeFBHc1F2cG01NklEaFBRRlpCd01Xc0RCRHdnZ2dBQUNDQ3d0UUVCZjJvVjdFVUFBZ1NJS0pDRXBETzkxY1J3SG9aL1puV0h1N1d4cERYUFhKSHpXazc2SmtMNEFOajA0dE9CT2ZrQUFBUVFRUUFDQmhRSUU5SVVlL0lRQUFnZ1VXY0FIOU5sSzVXR0Y4MUUvekoySjRqclIzbWxQZWw1Q2VqZkNNejNvbmRqVFdDY0NDQ0NBUU9FRUNPaUZhMUlxaEFBQ0NGeFF3RUpTZU9MdzRSTTZELzJnVDJXYTFleUN6K2FCMVF2a3F5ZTlHL3RBTnc0Q3JMNjllQ1VDQ0NDQUFBSVpFU0NnWjZRaEtBWUNDQ0RRQlFFTFlqWlJuSmJ3bnFRSHZSdlpMTmxpQ2YvTlcwOTZKNXVJSGEyVHVxd2JBUVFRUUtBd0FnVDB3alFsRlVFQUFRUldJQkRGOStwY2FlWDBrUGVCRmJDdCtLbjU2a2xmY2ZWVzhBSjYwRmVBeFZNUlFBQUJCTW9yd0FlejhyWTlOVWNBZ1hJSytFbmhacVA0NjRybnAwUmc3d1AwYm5aMlgxaTZKMzNmdnI3T2JqWlRhMmNmeTFSelVCZ0VFRUFBZ2F3S0VOQ3oyaktVQ3dFRUVPaU1nQS9vSnc0L2VrU3IvM2FZWEdtTm1kdzdZejIvMXFWNjBrZEdab0x5aEhSNjBPZjNCbTRoZ0FBQ0NDQndRUUVDK2dWcGVBQUJCQkFvcklDZGgrNDBVZHg5L2p4MFoyUGRXYm9nc0tBbmZkdlEwTE9DOG9SMDlyRXU3R0JzQWdFRUVFQWcvd0lFOVB5M0lUVkFBQUVFVmlxUTltWitOWGxoMG8yKzBwWHcvRlVJTkh2U05YSmhVeFM0bTNiczN2MmpKUW5wNlQ2M0NqUmVnZ0FDQ0NDQVFIa0VDT2psYVd0cWlnQUNDS1FDU1c5bUdON3I0ampXTmRGOWozcjZJTjg3THRBbjkxbUY5RXZES0x3OUF5RzlHK0daSHZTTzcxWnNBQUVFRUVDZ0NBSUU5Q0swSW5WQUFBRUVWaWJndzlKc3BmS3d3dmxvY3JtMWdQUFFWMmE0dG1lckp6MTJia2IybDRhVjhFQ1BRM28zd25NM0RnS3NyVTE0TlFJSUlJQUFBaGtRSUtCbm9CRW9BZ0lJSU5CbEFRdGs0WW5EaDAvb1BQU0RQams1Wm5MdmNodm8yRWpRcDlQL1o5UVVsMldrSjcyVEJOMDRDTkRKOHJOdUJCQkFBQUVFdWlKQVFPOEtNeHRCQUFFRU1pVmdZY21HdFdzSjcwbDYwTWxQaVVmWC8rM0xVRTk2Snl0UEQzb25kVmszQWdnZ2dFQmhCQWpvaFdsS0tvSUFBZ2lzUWlCeUk0Rk40aDZHdkIrc2dxOGRMeWxKVHpwSGdOcXhzN0FPQkJCQUFJSENDL0NCclBCTlRBVVJRQUNCSlFYOE9lZXpVZU1iU2s2bjlBeDdQeUJFTFVuVmxUdVg3a21mRytuUWxUSjBjaVAwb0hkU2wzVWpnQUFDQ0JSR2dJQmVtS2FrSWdnZ2dNQ0tCSHhBUDNINDBjT0s1UTlxUm5GN01SUEZyWWl3dlU5ZTBKT3VpZU8yRFE4L1ExdG82S3NJNzlVYy9HbnY3c0xhRUVBQUFRUUtLbENFTi8yQ05nM1ZRZ0FCQkRvdTRNOURkNkc3ejUrSHJobkxPcjVGTnZCa0FqWngzRG1kY1hDWnJwUCsrdWFUTy8xZTNZM2U3VzVzNDhsc2VSd0JCQkJBQUlITUMzVDZUVC96QUJRUUFRUVFLTEZBRXBwYytOWEVJT2xHTDdGSE5xcnVYTVdPbElSQnFCbmV1N0owNDhCTU43YlJGU3cyZ2dBQ0NDQ0FRQ2NGQ09pZDFHWGRDQ0NBUUxZRmZHaUtLdkc5TG80YlNvVFdvODR3OTJ5M1dWNUxSdzk2WGx1T2NpT0FBQUlJZEZXQWdONVZiamFHQUFJSVpFckFCL1JHWmYxMzFWdDdKTG5jR2hQRlphV0ZOTlM5U0tHV0h2U3M3RmlVQXdFRUVFQWcwd0lFOUV3M0Q0VkRBQUVFT2lwZ29TazhmdWpRU1JlNGIvbzBxQnNkM1NJclJ3QUJCQkJBQUFFRUVMaWdBQUg5Z2pROGdBQUNDQlJld01LNG55aE9aNS9mbmZTZ2s4OEwzK3BVRUFFRUVFQUFBUVF5SzBCQXoyelRVREFFRUVDZ2V3S2hDMGNDbThSZDA0ZDNiNnRzS1NNQzNSeEtIMnJvUHZ0WVJocWVZaUNBQUFJSVpFK0FOOG5zdFFrbFFnQUJCTG9wNENlRm0yazBEaXFlbjlTRzdYMkJidlJ1dGtEdnR0WDhEQkRXYmZTRXpuanYrQVNCWVJqT0JyT3ozMjlXbWYyc2QyM1BsaEZBQUFFRU1pcEFRTTlvdzFBc0JCQkFvRXNDUHBTZGVPU1JJNHJsRHlsQTJXWTdIdFM2VkRjMnN4eUJLUDdQTm5wQ0xkL2Z3YlkvSDBiKzJNOWZUOVRyMzlaMjdBZjJzK1cwRDg5QkFBRUVFQ2lWQUFHOVZNMU5aUkZBQUlFbEJmeDU2QzUwOS9uejBEVUdlY2xuY1dmUkJCcXFVR1Z5ZFB6bXdNVnZiWjdkWUczZjF1Q3NGVm80WDZkTCtkMVZPVC83MnFJaFVoOEVFRUFBQVFUYUtVQkFiNmNtNjBJQUFRVHlLZUM3elNNN0Q5MHZTVGQ2UHF0Q3FWY29ZQ0U5bXFpTmYxQUIraDBhUWVFUDF1aStkb1gwbVNnTSs3WHVBeHVDOExxalI0K2UxcnB0RysxYXYxYkZnZ0FDQ0NDQVFIRUVxc1dwQ2pWQkFBRUVFRmlsUU5KalhvbEhYQ05zYUt4ekdxQTRpTHRLMEp5OXpOcS9NbG12djIvSDRHQVFSdUY3TllqQ0FyUjlyWG9mc0o3ekpKeTdtN1h1VnpUWFo1ODdadlhGZ2dBQ0NDQ0FBQUpMQ0t6NmpYZUpkWEVYQWdnZ2dFQStCWHhBYjFUV2Z6Y013dEhrY210TUZKZlBwbHhWcWEzOUxZejdrTzVpWnozcDZlZUQxZlowTjN2T0NlZXJhaEZlaEFBQ0NDQlFXb0gwRGJpMEFGUWNBUVFRUU1DSDhmRDRvVU1uWGVBTyt2SHV1b0ZMcVFUYUZ0SzFvdk1LK0gwSyt2U2NsMm9Yb3JJSUlJQUFBdTBRSUtDM1E1RjFJSUFBQXZrV3NIRG16ejFXeCtuZFNRODYrVHpmVGJxcTByY2pwTTlFVWFSenpnbm5xMm9CWG9RQUFnZ2dVSG9CQW5ycGR3RUFFRUFBZ1htQjBMa1JQNG43L0JEbitRZTVWUWFCVllkMHZYQkdzN1Ziei9sZmNjNTVHWFlWNm9nQUFnZ2cwQWtCQW5vblZGa25BZ2dna0Q4QmY2N3hUS054VUVVL3BTOTdmNkFiUFgvdDJJNFNyenlrT3plcm52TytvQkgvMldTdDlzOVVDSDlPdTc0eklWdzdXb1IxSUlBQUFnaVVSb0NBWHBxbXBxSUlJSURBUlFWOFFEL3h5Q05IRk11L3FYT0lMWjZ2ZG9Ld2kyNklCM01oOEdRaDNSNzNYL3BuSnF4VXFrSHNQak5Sci8rZnpkclpLUk4yQ1RjV0JCQkFBQUVFRUZpQkFBRjlCVmc4RlFFRUVDaTRnRDhQUFFqZHZjM3owQzJBc1pSWHdOcmY5NFRiSmRoYVpuZHZIVjBSKzU1ekMrZTEyaTgwcVFqbjVkMW5xRGtDQ0NDQXdCb0ZDT2hyQk9UbENDQ0FRSUVFbWhPNFJ5T0JzMnhtM2Vnc0pSZFlLcVNMeEYrR1RRTXR3b3FDKzZjSjV5WGZTNmcrQWdnZ2dFRGJCS3B0V3hNclFnQUJCQkRJdTREdk1hODBHdmZGVVRnYmhJRzlSMWdQS2dkejg5NnlheXQvR3RKRDYwbmZQamg0SUlpaWdUQjJEWnRRVVBjZGFLNmVudk8xT2ZOcUJCQkFBQUVFL0ljdkdCQkFBQUVFRURBQkg5RGQrZk1QaCt2WEhYWmgrRlQxcFB2NzRDbTlRTG9mUkZQMStwZVgwTENET0p4enZnUU1keUdBQUFJSUlMQVNBWHBGVnFMRmN4RkFBSUZpQzFnSUN5Y21KcVpkcUluaXJLNHVDZTNGcmphMVc0R0FQeWRkejdmUkZkWmpidDl0VjJGQ1FTR3dJSUFBQWdnZ3NGWUJBdnBhQlhrOUFnZ2dVQndCQytnV3VteTV1emxSWFBJVC95SXdMMkE5NVhiNXRQUjcycnMrL3d4dUlZQUFBZ2dnZ01DcUJBam9xMkxqUlFnZ2dFQ3hCVndRZmRWUEZCZjZ5Y0NLWFZscWh3QUNDQ0NBQUFJSVpFU0FnSjZSaHFBWUNDQ0FRRVlFa3FIS2pjWTNkZmI1Q1pYSjNpZm9JYzFJNDFBTUJCQkFBQUVFRUNpMkFBRzkyTzFMN1JCQUFJR1ZDdmlBUGpVK1BxWVhQcVRMYUZrODUvemlsU3J5ZkFRUVFBQUJCQkJBWUJVQ0JQUlZvUEVTQkJCQW9PQUN5WG5vb1J0cG5vZE9EM3JCRzV6cUlZQUFBZ2dnZ0VBMkJBam8yV2dIU29FQUFnaGtTY0JQNEI0RjBZZy9EejFKNlZrcUgyVkJBQUVFRUVBQUFRUUtLVUJBTDJTelVpa0VFRUJnVFFKSmozbWpjWjh1Z3o2cmkyaFpqenJEM05kRXlvc1JRQUFCQkJCQUFJRW5GeUNnUDdrUnowQUFBUVRLSnVBRCtyb29lbEFWZjlpZmg4NUVjV1hiQjZndkFnZ2dnQUFDQ1BSQWdJRGVBM1EyaVFBQ0NHUmN3SHJMcTdWYTdheDZ6LytySCtHdXJ2U01sNW5pSVlBQUFnZ2dnQUFDdVJjZ29PZStDYWtBQWdnZzBCRUJQNlE5YnJqL29teCtTaUc5cXEwUTBqdEN6VW9SUUFBQkJCQkFBSUZFZ0lET25vQUFBZ2dnc0pTQTcwVS9QajQrR3JyZ0w4TEl2MTNNTHZWRTdrTUFBUVFRUUFBQkJCQm9qd0FCdlQyT3JBVUJCQkFvb2tEU1l4NDFQdXJpdUtFSzl1bUxYdlFpdGpSMVFnQUJCQkJBQUlGTUNCRFFNOUVNRkFJQkJCRElwSUQxb2tjVG80K01CRUg0TjM2eU9PY3NxTE1nZ0FBQ0NDQ0FBQUlJZEVDQWdONEJWRmFKQUFJSUZFVEFlc3Y5KzRRdWpQNFIzM1VlaHJ4dkZLUnhxUVlDQ0NDQUFBSUlaRStBRDFyWmF4TktoQUFDQ0dSSndNNDdqeVpxdFFNYTNYNlRldEdqd0s2TnpvSUFBZ2dnZ0FBQ0NDRFFkZ0VDZXR0SldTRUNDQ0JRT0FIL1h1RkM5MEZmc3pDczZEdm5vaGV1bWFrUUFnZ2dnQUFDQ1BSYWdJRGU2eFpnK3dnZ2dFRDJCZXk4ODNCcWRQd21wZkxQcXhjOVZEem5YUFRzdHhzbFJBQUJCQkJBQUlHY0NSRFFjOVpnRkJjQkJCRG9nWUQxbGx1dmVlREMrRWEvL1RBNU45M2Y1aDhFRUVBQUFRUVFRQUNCdGdnUTBOdkN5RW9RUUFDQndndjRjOUd0RjEzbm9IK09jOUVMMzk1VUVBRUVFRUFBQVFSNklFQkE3d0U2bTBRQUFRUnlLdURmTTJJWHZOdFpuM29ZVnZVdjU2TG50REVwTmdJSUlJQUFBZ2hrVDRDQW5yMDJvVVFJSUlCQVZnV3NGNzB5VmE5L1daZGQrMHdZNlMyRTY2Sm50YTBvRndJSUlJQUFBZ2prVUlDQW5zTkdvOGdJSUlCQXJ3WGlLSHEzd3ZrNWV0RjczUkpzSHdFRUVFQUFBUVNLSkVCQUwxSnJVaGNFRUVDZzh3STJlM3QxYW5UMG0rbysvMFBmaXg0RVhCZTk4KzVzQVFFRUVFQUFBUVJLSUVCQUwwRWpVMFVFRUVDZ3pRS3hyYTl5ZnZiOUxvNGYwOG5vZmZyUjM5Zm03YkE2QkJCQUFBRUVFRUNnVkFJRTlGSTFONVZGQUFFRTJpSmdZYng2OU9oUkMrZnZDU09ka2U0Y0FiMHR0S3dFQVFRUVFBQUJCTW9zUUVBdmMrdFRkd1FRUUdEMUFqYlVQWmlzMVQ2aWJINnZocnBYTlorN3YyLzFxK1NWQ0NDQUFBSUlJSUJBdVFVSTZPVnVmMnFQQUFJSXJGYkFMcS9tTDdQbWd1Z2QvbHByWWFDdWRDNjd0bHBRWG9jQUFnZ2dnQUFDQ0JEUTJRY1FRQUFCQkZZcmtGeDJiV3pzL3crZHYreWF2YWN3WWR4cU5Ya2RBZ2dnZ0FBQ0NKUmVnSUJlK2wwQUFBUVFRR0JOQXI3enZCSEhiM2ZPbmRDYW1EQnVUWnk4R0FFRUVFQUFBUVRLTEVCQUwzUHJVM2NFRUVCZzdRSnhzRzlmMy9IeDhkRXdjUC9CWDNhTkNlUFdyc29hRUVBQUFRUVFRS0NVQWdUMFVqWTdsVVlBQVFUYUtEQXk0b2UxVDR6VlA2VExydDJWVEJqbkdPcmVSbUpXaFFBQ0NDQ0FBQUxsRUNDZ2w2T2RxU1VDQ0NEUVNZRjB3amhkYlMzNHR4cnFycXV2aFg0Q3VVNXVsSFVqZ0FBQ0NDQ0FBQUpGRXlDZ0Y2MUZxUThDQ0NEUUd3SHJNYTlPMWV0M2hXRjRveC9xem9SeHZXa0p0b29BQWdnZ2dBQUN1UlVnb09lMjZTZzRBZ2dna0RtQjJFcTAzZ1gvVHFlaGYwdEJ2VThYWFdPb2UrYWFpUUloZ0FBQ0NDQ0FRRllGQ09oWmJSbktoUUFDQ09SUHdBSjZ0VmFyblExQzkwWmYvREN3OXhrLzAzditxa09KRVVBQUFRUVFRQUNCN2dvUTBMdnJ6ZFlRUUFDQm9ndjRvZTZUbytNM3U4RDlvWWE2Mi9zTXZlaEZiM1hxaHdBQ0NDQ0FBQUp0RVNDZ3Q0V1JsU0NBQUFJSXRBajRvZTdyR3U0dG10WDlRWWE2dDhod0V3RUVFRUFBQVFRUXVJZ0FBZjBpT0R5RUFBSUlJTEFxQVQvVWZYeDgvRXpvZ2pmNDhlMWhVTkdhR09xK0trNWVoQUFDQ0NDQUFBSmxFU0NnbDZXbHFTY0NDQ0RRWFFFLzFIMmlYci9OaGNFSE5kUTkxT1laNnQ3ZE5tQnJDQ0NBQUFJSUlKQXpBUUo2emhxTTRpS0FBQUk1RXZCRDNhZEdhKzhJWEh4dk10VGRFZEp6MUlBVUZRRUVFRUFBQVFTNkswQkE3NjQzVzBNQUFRVEtKT0NIdXF2Q3MySGtYdWVjYXdSaFdOWFBESFV2MDE1QVhSRkFBQUVFRUVCZzJRSUU5R1ZUOFVRRUVFQUFnVlVJekFiNzl2VWRPekorWHhnR2I5VlFkOFZ6QlhVV0JCQkFBQUVFRUVBQWdTY0lFTkNmUU1JZENDQ0FBQUp0RlJnWnNXSHQ0Y1JZL1hlRE9QNWNXS2xVMVlVKzA5WnRzRElFRUVBQUFRUVFRS0FBQWdUMEFqUWlWVUFBQVFReUxtQkQydjM3VFZqdGU2MUMrbU5oRVBicFBuclNNOTV3RkE4QkJCQkFBQUVFdWl0QVFPK3VOMXREQUFFRXlpclE4RVBkRHg5K1ZHZWd2MWJEM1cyeGZ6a2YzVlB3RHdJSUlJQUFBZ2dnME96UkFBSUJCQkJBQUlHT0M0eU0yTEQycWk2OTluZk9CZS9YK2VoMmtKaFozVHNPendZUVFBQUJCQkJBSUM4QzlLRG5wYVVvSndJSUlGQU1BVCtzZmJKV3U4SEY3blovNlRYT1J5OUd5MUlMQkJCQUFBRUVFRml6QUFGOXpZU3NBQUVFRUVCZ0JRSTJwTjB1dGFaTG84ZXYwYVhYSmpYU25mUFJWd0RJVXhGQUFBRUVFRUNndUFJRTlPSzJMVFZEQUFFRXNpcmdMNzAyTlQ0K3B1dWoveXJubzJlMW1TZ1hBZ2dnZ0FBQ0NIUmJnSURlYlhHMmh3QUNDQ0FRQkhZK3VxNlBQakU2L3JjdWNPLzI1Nk56ZlhUMkRBUVFRQUFCQkJBb3VRQUJ2ZVE3QU5WSEFBRUVlaWFRWEI4OW1CeXIvMllRTi81WDgvcm81M3RXSGphTUFBSUlJSUFBQWdqMFdJQ0EzdU1HWVBNSUlJQkFpUVhzZlBTSzFmK2NDMSt0YzlMSE5HbGN2MzVrWm5kRFlVRUFBUVFRUUFDQjBna1EwRXZYNUZRWUFRUVF5SlNBdno3NmRMMXVrOFg5Zk9DY2hYT2JSQzdPVkNrcERBSUlJSUFBQWdnZzBBVUJBbm9Ya05rRUFnZ2dnTUJGQkpybm8rdlNhMThKZy9BTk9oOWRVN3pyUHhZRUVFQUFBUVFRUUtCa0FnVDBralU0MVVVQUFRUXlLV0FoWFQzbkU3WGF4M1I5OU44TEsxRkZDZDN1WTBFQUFRUVFRQUFCQkVvalFFQXZUVk5UVVFRUVFDRHpBbjVZdTNyUy80M09SNzh0aWlLN1Bqb2hQZlBOUmdFUlFBQUJCQkJBb0YwQ0JQUjJTYkllQkJCQUFJRzFDbGhBOTVQR3pRVGh6emtYSDlha2NYMGE3TTZrY1d1VjVmVUlJSUFBQWdnZ2tBc0JBbm91bW9sQ0lvQUFBcVVSOEpQR25hclZwcUk0K0tlYU5PNWNFUHBKNHhxbEVhQ2lDQ0NBQUFJSUlGQmFBUUo2YVp1ZWlpT0FBQUlaRldoT0duZXNYci9mQmVFdnFCZmRDbXJ2VjB3Y2w5RW1vMWdJSUlBQUFnZ2cwQjRCQW5wN0hGa0xBZ2dnZ0VBN0JlWm5kdi92bWpUdVhaclpQVlE4cHhlOW5jYXNDd0VFRUVBQUFRUXlKMEJBejF5VFVDQUVFRUFBQVM4d01tTG5ua2VUOWZwN0ZOSS9xWm5kcStwQ1A0OE9BZ2dnZ0FBQ0NDQlFWQUVDZWxGYmxub2hnQUFDK1JlWUc5S3VtZDFmRzhUeDdaclp2Vi9WWW1iMy9MY3ROVUFBQVFRUVFBQ0JKUVFJNkV1Z2NCY0NDQ0NBUUdZRTVtWjJiL1N2KzhlNi9OcTMvY3p1aFBUTU5CQUZRUUFCQkJCQUFJSDJDUkRRMjJmSm1oQkFBQUVFT2lQUUNQWUgxZU9IRHAwTVkvY3p6Z1duQXJ2OFdzQTU2WjNoWnEwSUlJQUFBZ2dnMENzQkFucXY1Tmt1QWdnZ2dNRHlCUTdvV3VqNzl2Vk5qSTgvcERuZGYwYVhYMHQ3MXBrNGJ2bUtQQk1CQkJCQUFBRUVNaTVBUU05NEExRThCQkJBQUlHbVFITm05NGxhN2ZZd2pGN041ZGZZTXhCQUFBRUVFRUNnYUFJRTlLSzFLUFZCQUFFRWlpeGdJVDBJcWhOalk1OVJKL3JibXBkZnM5NzB1UW5saWx4OTZvWUFBZ2dnZ0FBQ3hSWWdvQmU3ZmFrZEFnZ2dVRVFCRzlaZW1heU4vM2JnNHQvVjVkY3ErdGt1eWNhQ0FBSUlJSUFBQWdqa1dvQ0FudXZtby9BSUlJQkFLUVdzdDl4NnpjT0pzZnB2NkJycG4xWlBlaC9YU0MvbHZrQ2xFVUFBQVFRUUtKUUFBYjFRelVsbEVFQUFnZElJV0VqMzcyRzZSdm92NnZKcnQ5bzEwZ25wcFdsL0tvb0FBZ2dnZ0VBaEJRam9oV3hXS29VQUFnaVVRc0FQZGJlYURsVDdmdG81TnhLRlliOSt0UFBVV1JCQUFBRUVFRUFBZ2R3SkVOQnoxMlFVR0FFRUVFQ2dSY0JDZXZYdzRjT1ByMnZFLzBEWFNQK09abmUzYTZRVDBsdVF1SWtBQWdnZ2dBQUMrUkFnb09lam5TZ2xBZ2dnZ01DRkJXeUN1T3I0K1BqRWJLWHlDdldrSHdzc3BEdkh4SEVYTnVNUkJCQkFBQUVFRU1pZ0FBRTlnNDFDa1JCQUFBRUVWaXd3Ryt6YjEzZnl5Skh2UlM1NHVjTDVtU0NNcXJyNEdpRjl4WlM4QUFFRUVFQUFBUVI2SlVCQTc1VTgyMFVBQVFRUWFLK0FYU05kSWYxWXZYNS9ITHVYNjlMb3MwRVlWTFVSR3diUGdnQUNDQ0NBQUFJSVpGNkFnSjc1SnFLQUNDQ0FBQUxMRnJDUXZuZHYvL0h4OFMrNk1QcHB2YzVtZTdmcnBCUFNsNDNJRXhGQUFBRUVFRUNnVndJRTlGN0pzMTBFRUVBQWdjNElIRHg0M25yU3A4YkdQdStpNEZVNkg5MjJZeUhkcnAzT2dnQUNDQ0NBQUFJSVpGYUFnSjdacHFGZ0NDQ0FBQUtyRm1nT2Q1OGFyWDlXbmVpL3FwbmRiVlgybmtkSVh6VXFMMFFBQVFRUVFBQ0JUZ3NRMERzdHpQb1JRQUFCQkhvallDRmRzN3RQanRVL3BjdXZ2YkVaMHEwc2hQVGV0QWhiUlFBQkJCQkFBSUVuRVNDZ1B3a1FEeU9BQUFJSTVGckFYeWQ5c2xiN1NCeTRONGRSbEw3dkVkSnozYXdVSGdFRUVFQUFnV0lLcEI5VWlsazdhb1VBQWdnZ1VIWUJteVRPUW5wbGFxeitPN0dMLzEwenBOdjk5c1dDQUFJSUlJQUFBZ2hrUm9DQW5wbW1vQ0FJSUlBQUFoMFNzQ0J1UGVZVzBuOHJqaHYvWGlFOW5UU09rTjRoZEZhTEFBSUlJSUFBQWlzWElLQ3YzSXhYSUlBQUFnamtUeUFONmRGVWJmdy9LS1QvUHo2a08yZTk2NFQwL0xVbkpVWUFBUVFRUUtDUUFnVDBRallybFVJQUFRUVFXRUxBZ3JoOVZSVFMvOS9BdVJ2RFNxV3FlNngzblpDK0JCaDNJWUFBQWdnZ2dFQjNCUWpvM2ZWbWF3Z2dnQUFDdlJXd0lHNkJQSndZcTcwbENla2E3azVQZW05YmhhMGpnQUFDQ0NDQWdCY2dvTE1qSUlBQUFnaVVUY0JDdWwwWXZSblM0OTlKZXRJZFBlbGwyeE9vTHdJSUlJQUFBaGtUSUtCbnJFRW9EZ0lJSUlCQVZ3UjhMN3EycEpCZWYzTnp1THQ2MGhudTNoVjlOb0lBQWdnZ2dBQUNTd29RMEpkazRVNEVFRUFBZ1JJSXRJVDAybHRjN040ZlZ2enM3dGJEempucEpkZ0JxQ0lDQ0NDQUFBSlpFeUNnWjYxRktBOENDQ0NBUURjRjVrTDZaSzEyUTh0MTB1MSsrMkpCQUFFRUVFQUFBUVM2SmtCQTd4bzFHMElBQVFRUXlLaEFHc1FYWHlmZGlwcytsdEdpVXl3RUVFQUFBUVFRS0pJQUFiMUlyVWxkRUVBQUFRUldLNURPN3U2dmsrNWMvSnVoTHBUZVhCa2hmYldxdkE0QkJCQkFBQUVFVmlTUWZ2aFkwWXQ0TWdJSUlJQUFBZ1VVU004OXIweU8xZDhkTy9lbVVDbGQ5YlF2UW5vQkc1d3FJWUFBQWdnZ2tEVUJBbnJXV29UeUlJQUFBZ2owVWlEdFNhOU0xV29mZGk3NDF3cnBWaDU3djJ6MHNtQnNHd0VFRUVBQUFRU0tMMEJBTDM0YlUwTUVFRUFBZ1pVSnBDRzlxb25qZmw4aC9UVkJFdElyV2cwaGZXV1dQQnNCQkJCQUFBRUVWaUJBUUY4QkZrOUZBQUVFRUNpTmdJVjBDK01XMHYvVWhlN25kZHVHdWR1MTBtZjFuUVVCQkJCQUFBRUVFR2k3QUFHOTdhU3NFQUVFRUVDZ0lBSVcwbWVEdlh2N3AwYnIvODJGMFUvNW44T3dHamhIU0M5SUkxTU5CQkJBQUFFRXNpUkFRTTlTYTFBV0JCQkFBSUhzQ1J3OGVEN1l0Njl2YW16czh5NTIxd1NCT3h0RVVWVUZuY2xlWVNrUkFnZ2dnQUFDQ09SWmdJQ2U1OWFqN0FnZ2dBQUMzUkVZR1pueFBlbmo0MStLWFBCQzU5eWtKby9yMDhZSjZkMXBBYmFDQUFJSUlJQkFLUVFJNktWb1ppcUpBQUlJSUxCbWdXWlArckY2L2Y1cUdQMkUxbmZJUXJyR3daOWY4N3BaQVFJSUlJQUFBZ2dnSUFFQ09yc0JBZ2dnZ0FBQ3l4Vm85cVEvTmpiMjNVci96QXQwTHZyOVVSVDFFOUtYQzhqekVFQUFBUVFRUU9CaUFnVDBpK253R0FJSUlJQUFBb3NGbWozcFI3OTc5TEgrMkwwb2JzUjNXa2pYMHhqdXZ0aUtueEZBQUFFRUVFQmdSUUlFOUJWeDhXUUVFRUFBQVFRa1lEM3Btamh1Zkh6OHpGUzlmbzFyeFA4ampLSys1dXp1TnZzN0N3SUlJSUFBQWdnZ3NHSUJBdnFLeVhnQkFnZ2dnQUFDRXJDUWJ0ZEYxL1hSSit2MWZ4eTc0RCtHbFlyTjdtN1hTN2N2RmdRUVFBQUJCQkJBWUVVQ0JQUVZjZkZrQkJCQUFBRUVGZ2cwOUpPRjlFQ1hZWHU5Yy9HNzFaTnVQNGY2SXFRYkRBc0NDQ0NBQUFJSUxGdUFnTDVzS3A2SUFBSUlJSURBa2dJVzB1MzlOSm9jcS85bUhMczNhWFozQytoUjRJTFpKVi9CblFnZ2dBQUNDQ0NBd0JJQ0JQUWxVTGdMQVFRUVFBQ0JGUXBZYjdtZGUxNlpxdFUrck9IdVA2ZmJqU0FLcTgzejBsZTRPcDZPQUFJSUlJQUFBbVVVSUtDWHNkV3BNd0lJSUlCQUp3UXNvRGRzOGppRjlMK01JM2VOSXZ0SkRYbXZjaG0yVG5DelRnUVFRQUFCQklvblFFQXZYcHRTSXdRUVFBQ0JYZ28wcjVWK2ZIVDhpNkZ6UCs1YzhGMHV3OWJMQm1IYkNDQ0FBQUlJNUVlQWdKNmZ0cUtrQ0NDQUFBSjVFV2hlSzMyaVh2OTJvMXA5bm92akwvbkxzQ1hYU3VjeWJIbHBSOHFKQUFJSUlJQkFsd1VJNkYwR1ozTUlJSUFBQWlVUmFGNHIvY1Rod3ljbWEvV3JBeGQvdGhuU3VReGJTWFlCcW9rQUFnZ2dnTUJLQlFqb0t4WGorUWdnZ0FBQ0NDeFhJTGxXdXI4MitzUlkvWlV1ZGg5b1hvYk4zbjl0OW5jV0JCQkFBQUVFRUVCZ1RvQ0FQa2ZCRFFRUVFBQUJCRG9pWUpkYTg5ZEduNnpWM3E1cnBiOGg4RmRoMDMzT2NSbTJqcEN6VWdRUVFBQUJCUElwUUVEUFo3dFJhZ1FRUUFDQmZBbWt2ZVVWWFN2OWoxd1F2a0xGUDNPeEdkNTFLWFhPVmM5WEcxTmFCQkJBQUFFRTFpeEFRRjh6SVN0QUFBRUVFRUJnV1FMSlpkajI3dTJmR2h2N3ZJc2F6M2ZPZmNkbWVOY0RNNHZYb01lczE1MEZBUVFRUUFBQkJFb2tRRUF2VVdOVFZRUVFRQUNCREFnMFozaWZHbjMwbStHbWMvczB3L3N0Q3VsOXVtYTY5YkxQYVBqN3JCOEJId1hqR1NndFJVQUFBUVFRUUFDQkxncUVYZHdXbTBJQUFRUVFRQUNCVkdEZnZyNGdtVVF1MkRFOCtBZGhFTDdCSHRMUTlpQjI3cDY0Ny9UTGpoODZmdEx1MGhmRDNRMkhCUUVFRUVBQWdZSUxFTkFMM3NCVUR3RUVFRUFnMHdJMmpOMmZuNzU5ZVBnVm1qVHVlcjB4ajFWblpqNXg5T2pSMDNyTVJyclpaZGxZRUVBQUFRUVFRQUFCQkJCQUFBRUVFRUNnd3dJV3dwYzY1V3lwK3pwY0ZGYVBBQUlJSUlBQUFyMFVvQWU5bC9wc0d3RUVFRUFBZ1hrQnUxNTZ1bGl2T3NQYVV3MitJNEFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NMUlg0SDhEN2R1VFMvRDQrdjBBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCIsImNyZWRQcm90ZWN0IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiOWQzZGY2YmEyODJmMTFlZGEyNjEwMjQyYWMxMjAwMDIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJlcCI6ZmFsc2UsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzEsMl0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0xMS0wNyIsInVybCI6Imh0dHBzOi8vd3d3LmdldGFyY3VsdXMuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQXJjdWx1cyBGSURPMi9VMkYgQ2FyZCIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjIxMTA3MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMTEtMDcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAyLTIyIn0seyJhYWd1aWQiOiJmYmVmZGY2OC1mZTg2LTAxMDYtMjEzZS00ZDVmYTI0Y2JlMmUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImZiZWZkZjY4LWZlODYtMDEwNi0yMTNlLTRkNWZhMjRjYmUyZSIsImRlc2NyaXB0aW9uIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIE5GQyBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1NEQ0NBZTJnQXdJQkFnSUpBTTlSell1NEVJSWxNQW9HQ0NxR1NNNDlCQU1DTUg4eEN6QUpCZ05WQkFZVEFrTk9NU3d3S2dZRFZRUUtEQ05GZUdObGJITmxZM1VnUkdGMFlTQlVaV05vYm05c2IyZDVJRU52TGl3Z1RIUmtMakVlTUJ3R0ExVUVDd3dWUlhoalpXeHpaV04xSUVacFpHOGdVMlZ5ZG1WeU1TSXdJQVlEVlFRRERCbEZlR05sYkhObFkzVWdSbWxrYnlCU2IyOTBJRU5CSURBeU1DQVhEVEU1TVRBeU16QTVOVEEwTTFvWUR6SXdOVGt4TURFek1EazFNRFF6V2pCL01Rc3dDUVlEVlFRR0V3SkRUakVzTUNvR0ExVUVDZ3dqUlhoalpXeHpaV04xSUVSaGRHRWdWR1ZqYUc1dmJHOW5lU0JEYnk0c0lFeDBaQzR4SGpBY0JnTlZCQXNNRlVWNFkyVnNjMlZqZFNCR2FXUnZJRk5sY25abGNqRWlNQ0FHQTFVRUF3d1pSWGhqWld4elpXTjFJRVpwWkc4Z1VtOXZkQ0JEUVNBd01qQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIbHEyalVRTWFsSGovQlJlUWVmR2l6NEV2WUp5RkxXUHo0UmZoSkdLcXFsKzhuOTZoVDFtNWdYb1R2b0xyalNVN1gwY0Jlb1RzZ2h5aDIyK3lyczQrU2pVREJPTUIwR0ExVWREZ1FXQkJRKzhTR1cyQlhicWIyZGNBT2lXSk9VK0dDc1BqQWZCZ05WSFNNRUdEQVdnQlErOFNHVzJCWGJxYjJkY0FPaVdKT1UrR0NzUGpBTUJnTlZIUk1FQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUURxOHhJVzBaSzV5ejNFQXptdXg4OExDVFlPMTU3ZlRmeU9pT3pDMkFEeWF3SWhBTzFQV1lsZUZnSC8zbXVEOGNCQU1yMTFmRUtkRi9BYUMxNmZ0eGFlek5YSCJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFJd0FBQUFZQ0FZQUFBQW9OeFZyQUFBQUNYQklXWE1BQUI3Q0FBQWV3Z0Z1MEhVK0FBQUZJR2xVV0hSWVRVdzZZMjl0TG1Ga2IySmxMbmh0Y0FBQUFBQUFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NGdQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlRV1J2WW1VZ1dFMVFJRU52Y21VZ05TNDJMV014TkRJZ056a3VNVFl3T1RJMExDQXlNREUzTHpBM0x6RXpMVEF4T2pBMk9qTTVJQ0FnSUNBZ0lDQWlQaUE4Y21SbU9sSkVSaUI0Yld4dWN6cHlaR1k5SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpFNU9Ua3ZNREl2TWpJdGNtUm1MWE41Ym5SaGVDMXVjeU1pUGlBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGJHNXpPbVJqUFNKb2RIUndPaTh2Y0hWeWJDNXZjbWN2WkdNdlpXeGxiV1Z1ZEhNdk1TNHhMeUlnZUcxc2JuTTZjR2h2ZEc5emFHOXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNCb2IzUnZjMmh2Y0M4eExqQXZJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JGZG5ROUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlVWMlpXNTBJeUlnZUcxd09rTnlaV0YwYjNKVWIyOXNQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdRME1nS0ZkcGJtUnZkM01wSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE9DMHdOUzB5TTFReE5EbzBNRG8xTlNzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRrdE1EVXRNRFZVTURrNk16TTZORGNyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRrdE1EVXRNRFZVTURrNk16TTZORGNyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlEyOXNiM0pOYjJSbFBTSXpJaUJ3YUc5MGIzTm9iM0E2U1VORFVISnZabWxzWlQwaWMxSkhRaUJKUlVNMk1UazJOaTB5TGpFaUlIaHRjRTFOT2tsdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1qRTROV1l5WW1ZdE9EVm1PUzFqWmpRM0xXRmlPRGN0T1RGak0ySXpaakJpTnpobElpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSmhaRzlpWlRwa2IyTnBaRHB3YUc5MGIzTm9iM0E2WldNeFpUZzNNakV0TnpNM1lTMHdOVFJsTFdFellUa3ROVEZrTVRNek5EWmxaVEk1SWlCNGJYQk5UVHBQY21sbmFXNWhiRVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWo0Z1BIaHRjRTFOT2tocGMzUnZjbmsrSUR4eVpHWTZVMlZ4UGlBOGNtUm1PbXhwSUhOMFJYWjBPbUZqZEdsdmJqMGlZM0psWVhSbFpDSWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3lNVGcxWmpKaVppMDROV1k1TFdObU5EY3RZV0k0TnkwNU1XTXpZak5tTUdJM09HVWlJSE4wUlhaME9uZG9aVzQ5SWpJd01UZ3RNRFV0TWpOVU1UUTZOREE2TlRVck1EZzZNREFpSUhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5ROUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QW9WMmx1Wkc5M2N5a2lMejRnUEM5eVpHWTZVMlZ4UGlBOEwzaHRjRTFOT2tocGMzUnZjbmsrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrLzBWeFJRQUFHZlZKUkVGVWFBWFZ3WGZjbjNWOTcvSFg1L3Y5WHRkdjNEczdKSkFJQVVMWUJabUNpbURWRGxmdHcyM0hxWXVxUFYwV3RkYldSNjNuVkcycm5yYU90c2hEclJVZlBSM1dXUzNLVmhBWllRb0VRa0xXbmR6ek42N3IrbjdlNTA0aUtOV084NTgrbjJudWlzUy9KM0c4WVplWjJaVEVJbUQ4NStST08wWlNVZmlISlA2Rkh5SUVXQmpBd3pOdzZvYkkzQ3lrQ0dhR0pOeWhMTVd3Z25yb3BOSklDQk5VY29vaTBPOGIreGZGNlBMQXFJTWNHb2QyVyt6WUQ5Rmc0OXJBZ2IxaTBUSlRIV0dDdW82VWhlRUpkaTltVnJTTjhjS1lxNDJkKzhTS0NTTzJnQXdkSUJRUVRQeDdabERWZGtrV2J6VFpjS1RJM2RodnZyR2x1ZU05ZDhVVFgwUnIram1veVlDUU9NU3NCTHBBQWpMUVJ4cGd4bytSQW1scjRvY0laaGVHa0Y1bEJwTDRyd2hJQ1hMRGZIK2dEeGVGa0hnQ0NlU3dmNzhoRXovS2pNUEVENUlnUlh1UnVmMjBwWUJaUTcyZjdTdEdIM1ltVHZ4Rk1oY2dBd2xpQVJMZ0dXd0dOQWZXUXF3bWhzaEJjbjRzR09BK2w4cUN4eG1RQlUzRFNaSWo4VjhUWUZDMGpZVUZiZTMxZFAyeTVaQXpUeEFTNU1aQWdQR2p6UUJCMVlEeEE5WlowS2ttY0VISW1jOTNMdmkzSGZISWtxWmVqVElnTUVBTzdsOG54azhoM1lMbjNZUTBqdXNNMUx5T0VNNUU0c2VDZ096L2xQWWNFSTl4UVR0eHhIZzNudWtZSUw1ckVkZ09DQ2o0ZmdZU3NSNXFSYWVqcTBKaXVxcDRnaFFOTHcxVjRzZUZBSzlGTXI1SFFMVGpRZ3liTWNpTmc3SG4xcFdYZk9PaDZzU0w4UGtqTVFkTFlHR2F3ZDdmSlhZdlIwV2ZFTUFDMUJXRTRsWjZDLzlNbWY2T2N1VHBTSUQ0a1dVRzBtN0V2ZW0yYmM1amhvMVlPeG1QT25NVHAyYUo3SUNCaVk4Si9UN1FBa1lBY1pBQVE4RW9jME8yeUxiUlVVTUNNNUNNZGh2MnpUbGtJL0pqUkdBUlFoSElqWGlNR2NkS0duZU0waktJT3g2cFYrL0xadWNqN3hBTVNQdm82eFY0OVFYU09Nek53OGdFZEZvd013TWpZNURTWHBybXJSVDZCNHhWaUI5ZEVrdHVKTnFPdEhjKzhKaitFRHBkMnhUYWpHZ0FHZU1nZC85bllFOEk0SUlRUUN3SmdJTUxYQkFObWd5U2tSMks0Tno5SUR3Nkx6WWZMUXJqeDRZWk5EWDBlazUzTENCeFNBcDJqcGxoZ2hZMXN6WngwMVhOQlhNRXRoQXFRQlc5NWgwMDZRdkVFYWhKdE11WFVNUVgwRlJYMDJwOWhDTE5vd0NlcnNmOFByQlYvS2ZFWWNaL256ak0rQUh1RUFML0lUbGdZTVpoQnE2YkVRdnBTVWRHSGxQVnhCVmpkbzZ5NFJJZ0VOc0VPNkpCbHBFQ1ZMVVRnaEZMUVRZY0l5TUtRWk1oRzFRTkZLWDQ1ajFpWXRKb0pVT1YrQ0VNR0FFQ01BK0kvdzhDWEdDQU8xamt2ODFZSXNnT0VvZUl3eXhBWFltNS9jNnFsWVpuYURKSDVjekpoSUJNbU9BaDMvamxnWFZXUXo2UllEQVlYc3RDL1JkMGxrTTVBdkkzVUhUZlJ3QnFmeDRqbzF1QkwySVI2Z0RaRzBJQUJPNFFJMkRnRGlZT3NRUnlrSU1aUDBqZ0dVTGljUllBZ1F2TU9FUUNNeWhhNEJua1BJRUVGcUJvUWE3QUhVSUVCRG5maWNqcHBFbHhpSURJbXM2WW5aa2JhREpZTUR6NzNjZ2ZtV2tDUllMSkNQMCtXQUFLSG1lQVpFZ1FBZ1Rqa05FMnBBZ1Nod2pJQW96amdaOUJPayt3enNCYzdBTytndmlreEtQOEp3UzRHREc0S0VYT0VxenF0UEFBM3pIakM0S3QvQmNFeTRKeDhXaWJNMkprS29vYWVBRDRDdUxiR0JRbHhCRWpaa0dmOVhWdG00aGdDSXpaditYRkR6MFlOcDZOTGF4RURtWG5zMHlaRXlvbzB4bkkvb2ljb2FraFJNQmVnM3dUVWtuMjFSZ25FOFFoclE0b2cyY0hiUWYyNHF3aTJIcVNCUnFCQURNZTV3NnBnTTRZREhxUUd6Q0RrQ0FWTU95QkhDd0FBZ0d4QURsNEJvc2NacUFNQ0dJTHdqaFVQYUZzd0E2QzdtRkptbmxVSE9RWldsMVdqNHl5UlVFZ2tCdGx5VDJ0cUFONzU0VzVzV1JDY0tyZ0RMRGpnT1VHQ29HZEdMY0MveXA0aEI5R0VPQ1lxWFo0Ylc3c1JkRjBGR2FHSUFNcFFzQ2VaWUZmTTdOM0NQN2FRSHdmQVRtclJQWkxyY2l2WUd5V1dWZUN0Wk1nbDVySzNwU2lQb2J6aDhDQTd5TWdpMUdaWGVwdXI0ekdwZzJyWWxuWEFqZVVoRHNQV2VUUExmTEgxVURhZm0rbUxveVJ0djNFWk5jbXF5eGFOQ0J1dlQ2ZXV3UHhNdFJ2NCtyUkc5eElNdWcwTU5RQkxOeFBhMlFMdVlGcUFNVG5BOC9ub0NJQXhpRWhndWNETFBZK1RqUDRFdU5qOStEV0o0UkFOWE02ZE4vQ3lMS3pXSndGYnlCRVFCQkxVSURGbVFkeFhVY3E3c1RDZ0dIL0tQcHp6NkF6ZWhJR05BMmtObmpld2ZiYlBzclk2dnRvVHo0ZmExNklCY2daV2lPUTYwZllmditIbUZoeEI5M1JuOFB6eTNEZGpyR2RKYW03TVhDUUJFWGtERFBHY2dVV3dYQUdmVjFmVzBCdWF5M3k4N2c5djkyMkV3MWJJVGN3Z1NBRlE4Smo0SDZaWFZGTEh3Qm0rUzRIQXJ4NDlUSjdSOWtLeHc4V3dRS1BrNkJzUVFHV3pkWVhvL0dqZFpPak1oODJEcE1nSmp0cDlVVDgzOTFrRitlR29rakNKYklNbHhCWXJuVmt1MnR2TXc5SG12SnJCUU9XT0ZBRVRsblZEaDlzV2JpZ2NjTk0xQm5Fa2lBa2tMRWhCSHQzR1d3Vm1kKzhkNXZ6eGUvRTlNeXo3Y3lMejRmcUVTaVYyVmxzK1B5ZVltMlBQay9GTXNnSERQb3pXSUNxZ203bkFUeS9nTms5cjZFb24wZDc5RWswRlljSUNBSEVFb0VQdjhxakQ3eVRWY2RkdzhSNFF6V0FMQkJnK1dGbUZyL0tiSE1GVStYekNBbXlnd1VvMHg3MlBmU1hQSERuMzdMbEtROWgxaWRFd0dGbTF5bzZ4N3lWc3Z0RzZoa3dvRFA2TmhabUxtZlp4aFlwWFl6WElBR0NhQ0M5aTE3OUZ6VFhRVHJoUXNwTjRJdmZBdVpaa3JwZGNaQ2dFMlZuZXpaY0ltSzBPbngxZHRiK0xqZTZlTlVLKzJEQ2pxOWRoQkMwNUFEU2lBWEtWalNhUmpRaXhHREhncjNUNEZuQXIwcDgyd1dkeUZ0YkkrRzNUVGJldUJBUWdCQU41UE1qTFQ1M3g0TzZldHNDKzg0L3dkWk9ZaTl0aU84eXk3Y2kzY2hCNHR4V3l6NFM0Y1FpUU9nNnZSNTdURnlWZ2p5WVhTUlkxUUFPZEdKOHFhUnJKUHRvVTNQUXVTbllGYVBSTm1XRGpERFlXZFYrdlJuWjRHd3oyMkJBTlpTVm5maXFvNDdsczVQT1ZmUExiTzJLVWR0TVgyQUdCUXc2RTljMGQrMWR4ZHJqTnRGT29EaENaLzk1N0hoZ0swZWZDNkVHNXg0R2k3OU9TaDhncEtjUi9kY291NmZRbjRmc2tDSlEvejNVYjJCcXpVNmFQb3dzTzViaDRBSmN1L0RtcTdRbkJ2U1paL3ZXdHpOMjdHbDBKemN5V0FUWjlWUnpiNmJkdm9iTjU0cWlCV3FnR29JaXRFZjNzT2ZBbXhpM1NMZDlLVlYvRjYzdVZ6ajZMSWpGT2xSZGdBVVFFQU1NcTN2SmRoVnIxa0p1TGNNbW40b3FvTDRaUElPUkdIQ0lHVk5FVGhKZ0J0bjl5OE1Ccng4ZHM3Y0ZoWGQyb2hnMmZtUE8rblNRM1F5MkQ5TmtVOWtwaTQyL29HeUZpOHBJa0F0dnhNU1luUitLK0FrTHpZdEcyM1pCdXd4dnl6MjE2MGFZUVpGQVVQVjcvcW1pc0Q5blZMZjErdlNuZTQ0c1FOWVZqZXp0cGZIVVJuNFRzTTRzdk0vRWlTSEJURi85aFVYNzA3S3RqNDYwMklYSU45elZiSjRhaSsvZmNuUzRzQnFJeGxXMFkzemR2Z1UrdW0zYWp6anRLUDRNYkZNdGtHbk9zNzgzaFBESkVPeFJTUmdjaVhnYnhrc0ZscUt0YUtmNHd2NVFWNTE2cko2MHlqbWgybTlZRUpUc2ZvOWUvOGg5QnphZXdSSHpVNFFDRkZxRThBYTh1b21pdUlXbUQ1NmhMTURpZzdSSEh1U1dhNy9Fc1A5UlRubjZzNGdHaS9XMXlONUlIT3lrTTdHTWhZVTNzN2o0VXNScWlsQWdQazZPdjA2NzNzdFI2MjhuaHh2STJraDMvQ2JtRjErTHVJM3hOZURoNlZUOVZ5R09SUGxtR3Y5VEpsYnR4SUQ1NFYvU2FqOFhmQ2R6ZXhleE50VFZXVVRmZ0JtWVFURG9EWGZRMHpZbVdwQTJub1A3Q2ZoZ0h5SGZqb21Ea2pqTXhQcEFPQTREejl3ZzhYN1YrcjJSVG56NVlxMEhkcy9sUHh3cDdUUEJtT083Z2tIbFhIdjN3LzZ4aVNuLytWTTJwYmRYcy9Za2oySTRFS0VLVzU1NlV2SGxtSmlvZW1vcmMwZ3JRUU9QSGhqNlcybnNiOHFDeDhVSU1SaTQ5dGRaZjFBVVhEQldwb21GU3I5bEZzNEpDQXZNN1pyMVMvdnpmSHpEZXNNTUVEUnV0ODczbXJjb3AvY0VXQjhEelhSUDkzL3FPaS9PUHpuOWFtdlVucnd3QzVnZTh0cGZCWHlOSjdvYjlEdVluV2pZYVo3RllyWk5NY05LMkpLQ2pWZG1kQm5BZ0JzZjBoSGIyTEx1ZGFRREkxUVZ5S0N6Nm1TT21mb2s3bitNL0V0NC9RaXRVZWlPZ3pjZzdXRFkrejF5UG9taVhFOWpmNGhwQjZiMXBIZzU0eXVmd1hBQVpoQU5YQytuYW00bDhCNjY0OUJLQjhnTE1OZDdKNVZ1bzRxUkVidU13Y0p2WTJFTWkxQ01Yb1NxRHRobHhBQWR6ZEkwZXlrNzMySTRuT091dTJIOTZ0Tlp0VHd4ckNBWXhBUUwrMi9Dck0vb2F1aFZUNlpWZEpodXJxZXRBM1FpT0tRVWplODZ4WXdwd1U3SHIyMG5lMHYyZEc0LzYrdnUvaXBnRzk5bGdGaGlITkk0dlVhNkhQZHY3aHZ3aWJGT09EVUJ1UkhqSXh5Ukhlb0dna0VNc0d0RzM4N0IzMWgyN0dvSkVPRFFiVU8zTXU3ZG5sblpFV1hCVkxzZE81WTVYaDVlb0NpS0NETnorVVBUKy96anJaU1F3SUE2dzlwSlp6RDBhd2Z6K2VlU2FTd21jcFhaTlRWcXA2OVpZYjhpQjgrT1I5NmRVdnhhTUVZbEdXQkxXSktCQTNKOTI0elRXT0tvWERTbks5dVlKQVFFZ3dQTjZOVzdlMnVnemRtUVFTd1I0TkR1Yk1iOXI4akZWcUkrQWZZWm90K0grbkQwYVN6NUJzcTMwQnZzZ3ZBTm1qM2dmaFJoK1RTaHVSSjVCWWlHQWhnaDZCNktCQWFzV0g0Nlg3L3ljMWpySyt4N0FEWSs4K1hFK0FjSXd3UmlTWVoyK1V0SVoxQTNNeFJoQW1remxuNmZiZHNhUkllaU9KV0RESkJEdzREMjJMY1k5bUIyRGtKNk1yUmdxbk16VFgyQWJCeVVrRmpTd3V4MENReWZqbTdQRGVOaDA2RFVGMXA5dlp6R3B1V0FRQVlaTU1BTTNDRUEzVFpRc0hXdTFzL1VNZi9WVWQxd1NiK0dRUTBHbUVHSVFBcGZmM1IvZnUzS0ZkemxBak5RZ0dZSUoyMkFacHY0ME9maHdqTUR6ejNkTHQyNXgrUm80K3JsdGl3UElYUzRwMTN5SjFQelJyc0ZxUVYxQXdaMFMyTTRCRWs3REpGbHJCaU54WXZQNTRWa1Zpek9pWkJzRWVtbmdMTUU0NEQ0bmhvb0RNN2lJQU9EeFdnVTBUaEpBdHdnd1pmakpYZHNEU2UyQ1BrSVZBTUJNQkRRRERra2RVN0V1dStpSHJ3YWVBbVRvemZnd0dJRnFJZjRCS1ZQMHg5QzVqcTh1WTVROEQzR0ljcFFsTkNkV01uZXZjdjQ5cmMreXJMT0lpdlhybUN5dUl6S0RSTmdQSzdKWGVCY3pNQWRzUHN4dTQyTlI0SDc4WlRoRk9vS01FRGc3R0IwZkNzUjJMdi9CSTVZdHhrTDhKMGJyNk8zUHhNTERrcGtEcHFrME9rZ1lyQ2pyV01qOSszUlRkTUxldlU0VEs4ZWc3SUZicEFOaEFoQldBTm1jTVJ5WTZTQS9vTFl2TXkzMXpsZTJXdTRoQ1hHWVdaUU5mNzMvWXBMeTVaMmxRRktqTkFDQmVoVjBDbUVBQWRpeVhuZGJucnAxdW5tajhwUnpsN2ZzbmJkd001NXYzcmRsdkRveVJzTUdqSFlBVFBUMEVxd2NzS3dFRkV3M0NDSFFJVFYwZXlpV3VBR0VVYktFSDdhQVFuTURBUU9HR0FzQ1lZQUE1UjlheWZZNlFsN3VtU1U3UnJtZUhCNy9hVGJCMVBkNTVCN0czRExZTHM1ckEwMkFVVFVnQXRTc1pIc0wyYlBnUnRvSEN4dkFGdERzSzBZTUhsY0MwOHJ5TDJFNmhxTDRxQVF1cmdtaVVYQnNQOHd2ZFlycVBiTXNuN2wxWno2SEZpMjVrSnkzc2hnSGtMZ0NRd1FJQ0FWc0RCN0xiM2VibGF0aFJCUFlYYmZDZzZ5Q0ZaQS81RTdHZTYrbmRGVFlNMkcweGxySDBOdjVnQlgvZU85UEh3M2RFWTVLQ2x3MExHQmNDb1lvSkZPUyt6Y21UKzlZNWUycjE1aGREdkcybkZqVUlFQkJwaGdVSXQyYVJ5NXlyaDl1NWp0aVJQVzhSeXY3SGZkaklCNFRERERHM3Y0emwzRGZXdW5qTkZXb2gyTUprTHRFSUVBOUlZd1ZqSys2YWo0ZitncW5MWkpOMlhGMXd6bWhSVlVETm5hVEFNbTZnWFJ6Qm10MHBBN1ZRMnJsaGMwYm1RWE1RblByT2tOT2M2Q2lJWUhXQkNxQk1rTVk0bUV4WUFsbzE5bDlUbXM3V2JUOWRBL1ZyVHQ5Qml0VzFYUXNReUo2NjVaUEhVSHpzOWlneEx4Qm95cmdRSTRIdlFCektad1FWbUE1RHk4NnlZcXdmSVdkT0lGTUhJQ3NkMERRVFZZaHpWWGdFMUJtQVZ6ekVhQUk0RWFZei9ZREtrNkZ6cFhjTUhQUGt6bktDQ3RwOW9mZVp5QXdDRnlpQWtDbWV5UjFMcWRYUFdZMlFObUo1REtoRHRZZ1BiWWtNWFovNHRGaUN1QUF6OUJNNFIrLzBZMm43T0xkY2RCS2prb3lRQmpNOUExUkJiVWl5eXVuN0M3amw0TFQxcGp6QzdBWUFobVBFRXdrS0JxSURzRUM3OEk5cWMxakVlRStCNTMwV21GWDE0Mm11NnFjLzZ3QXhsd0FRWUlxZ3hqSFZhODhxSnd4VW1yd21tUFBseS9lcW9kRHlTejVYVWpZbTNGaXJhV3orNFdRU0taRVZxZ2lzTUVUYU9Pakd5b2FIZkZjTkZHbEJrTExERUxnK3gvSGN3L1VnUTdLcnNpUWc0cVpIbTIwZTZXMlp4eFNMZHB2SjJkK3dyczlUbERMQTBHa1VVMWR6UVR1NkRpR0pMTlkzd1d0QTBNcFB1QlM4SE9CWUVFODR0L1F0SDZPS3VYUWY5UjhQWlRhWStzWXZiK0JZWXpNUEtrZlJUbFBtSThIeHpNUUFiMTRNc0V1NUpRM0lMN3k0aUQ4MGhqczdoVlRPOEI5MXRvdDJwU1RNaEFCalNRL1hNVTVWZkJkN000MkVJSWw3Rm01UnlqSlh6aXo2Q3V0dlBjTjJSNi9VVFRoOFg5SDZmVitSdXFHYUEvVHE1K2dsNEZxZlVOTHZ6NS9hUUNKQTVLSmxvVzdHUXpReEltWStqNjFvWWp1TmJOMkRjTEdKaUJlSndCSlRCMFFRclczYkRDL3FBc3dwdUd0U1hNT2NqRWZoa2RvQ1BBWFdQSExFdnZuZTlqY2o1aUFlZTdoS2hxZThieGE4TDdXdXZpS2ZmZG5SLys1ajM2MG5PZVRwaE1pZ3hBWUpWNGFveFdGb1RLbFVFR0JuSUkwWDdaakpjSFZBbWIyRC9qZnpiUnN1OG9XZCt6dXNrZ2kvWWcrNTJqSWQ2SkdXWVFnZXlCUFpYTzNkQU5Gd2ZSZFRFbStUdGFwUjhSeko2UjNlaDB3ZlkzZkdiZmViZGRjK3pMVmxGckk0T3FEV3FEd0FLZ0E4QmJ3ZjhuS1FWQzYxTlVNNTloMVNTME90QWZ2WmlpOVFKTXNMaHRHY2tnTm5OUS9qTEtkMEE4aDVBWHFQdC9EOTFQRUZPbUdYWUpjUmxpaVRhalpncjNhYkpkaC9ST3hHK2hQRVdJY3lpOEg1cDNJMStrYnFBLy9CM1dyb1U3YnpqQW8vZkQxQkd3N2JaUE02eU9wQ2pPb2FuK2xmN3NCMmxQUVFSNnUwOWdaT1JrSEREN0p0VVFxaUdQU1JhWURHWlBGb2Nad2t5cit4Vy9HUXdyakVJOHJoV01aWUtWd09kZGZNaGQ1OFRDM3JscU1weGZ1MmdhVVFTamN0MFdzRmNYMGl1YWFKZktSUmEwSXFObE4zNWc2UDZ6TG4wTzdDR0RvOEdlRVlNOW5SREc2TG5QenVjM2JaemlvZVpBWHFieHNLMVZoT1hEU3BqWkJhWENSOHowQm9jNWxyaXpQSnE5dlN6dDBpb1RPeTFqVUduMjBXbS91NzNCdHJmYTNEK1l0Wk96WURUWmEzcFZtQnMyOXJ1dGtzck1rQmhQUWIrNHZoMStUekJsQmxtNnk0eTNKMk9GMEJhTFJyMllTU1YzUGJqcUtWK2JtVnYzVThUZWtaZ0Q4ZG00MzAzT0VBT1kvUnVSNjJtMUN0QTgxWDRJVTlCVW15bGI3OGZLWmVRK0xIL3laUlREVzZtYi9lRFRpTGVUMnFNTUZvYk03eDZ5K2hUSWZqVFcvemd4bllzREZpNmlHWjZDNmQ5b3BZenh4elM2aW1ad0JHT2o5MU9IMi9EZ1pJZFcrZnNVNmUyME9yRG5vUk9wZFNXblBnM1diTnBIdHJleHNEQkNxelhIeUNRMERpSEIvUFJHeGlaWFlQVmVjdk1RTXI1ZkdoblYrb1Y1T3kxRURuRkEySEdsd2x1aUFjWmh4aUV1N1RYWmZVTEhoRUtYRTNoYTVheWlobWhHQTlSWi8rVEdiN2puNzhqOUVTeGVIQ3djRDJLWVJUQXJrb1hudVBqSkFIMkR0b0tsZ2lVeVdQUkxKenY2aDFnRUZxZlovOGgyL2MwSngzTnFVWkp5QTJaNmhkQVdJL3lyUkxkVDhFekhOc3VnMHpLaWFXZUtlZ25HTFFNcERPYTVjaVRZeWJVTGkyYmRNdjVHblhXaFlWZUR1bVoydHN4T0c0MUsyYUdXM1NEcEpSWTBJTmg1WUFnREJ3TDNySXI3RnFrNERVdGdCakcrbWV4M0luMFJNOGlDZmpOZ2NHREE3Q09RYTVDOWlGaThEMXRZajljZ1FXZmlFdXJwOStMVkg1SEN2Wmc1K0J6OVBpejBsN0dPWDREOEZocGJqc1FoUmlJVzc2WVovZ0lwM29YVVlNMzFwQkxtNTJGUVFYdHFQYTN3djVDL0ZET1ltWWJUbnYzYnhQWU9lZ3NmWWQyeE1Ld3lnMnFlbGoyYk9oK0w2eTlvdDBSYWZSRzVCdVZ2NEhvWXhQZEx1dzl3M25oYkhYY3dRSUlpUXBGZ1dBbDNzTUFROFlqZzlpYjdya1FZaVlVOUg3TjFMaEVFalhEUTlZdERmMzgwUHROcUJjOUFJKzBJMlg4cHBYQzVzR01kSVFseFNCU01HbENZTVdnMGJkYTh2b1UrN2Rud0RKMElldzdvWTJzYWY5cnFrZmh6dlZrbm04emd6R0RoVEFFUkVZTlJaZEVmYXV0WWwxZW54SFdHeUFmY0xkdGZ4ekY3VnRtMjgvcDlzU1NtWk9lNGN3NFlCemxHUHd0My81Y1F3cHN3dGcxckptSVJuaG1DZ2FBVEttWTBkZHZuOVR3b09Rdm1PVVJhVFF5WEkvOFk4RlZjRHpCMEdNNnZZemc0aGJYSFA1TW1QNU84V0JJVGg1aEJOUTkwZm9HeWZTR2V2d2kyQzI5RWQveEl5dllGREJlUEJrcENBbkdZWjdCNEZtWDdNOERsb09zdzdTYW1rcm4rTVhqOUZMcnBlZURIMFRpWWdXZG9qWGFvNi9jU2VEYkQzcTFrYjJpWHgrUDJYRktNaUo4bTJEaXhQQTAxNE54TXRsbU1KMGpiOXRuWlp4eG5ET2ZrQkJRQ3cyR2poY1ZLMDJXeW5nVmx5ZVl4VEhCY0N1RUNDNHpXV1ZuaTNtUzZyd2pjT1plNXZzcTZPc3IyU2VJeEJwaTRidUQ1eFFHN0xKbTkwTUZTTUNSd2lTTFNtNm4xand1VjNydXl4YzBza1VSck10RHBHaWRNc1pDQy9hcXl6d3E5TWtVcnpJMUdBb3hhMEU3YTQ1V3U3QS8xSjJQZGNEOENCS3BFdTlTT25NUEw5ODN6NXhOdFBTc1JHR1lvQWtqZ0VnbS9aOTlRSHk0amwzZUQ3UjlVam1BQ09CV0pROFRpUGx2KzJmdDEzQmJFNllRYUNEWHVodGthaXVMTm9OZVF3bjVHQ3FOWVBzbXlJOGFJUmFMdVE2NGJRaUVRaHhsZ0VleG9USy9qb0p5aDFZR1JTUmpNQzFFVEFrK2tRRXhiVUg0WGhCa0lzN2hLcHBZdncyd0VyMW5pbURXQUVTSU1lbUEyU296UFIvNThZb1FFdUFDRFlKY2dCM09XT0hBZFFmeDdhZlBxOE1GcVVaL0VhRUFLd1JaN2ZlWVhLeTBldWRLeUdwc2FWa3pHU050Z0JPVElwcHRHTTJBTEtYRUFtSGZSdUtCZ2lmRkVCbG42bHNQL2tPdUtZUGFVb2V1b0VHd1lwSHZxeHI5ZUs5emtNRFMrVHpTc01Eb0pBdXoyckRjT2gvbnZLc1ZuV05EeExRaVlwdDExaXpKZms3VFZ6REtQTVNBQUJpSHc0TjQ1dmVUaFBmNlRXOWJ5bExKZ3c2REN6TmlaVE5lWStIcVdIaExHOUVKTjNZaVU3TUJJYWE4UmdTQWxFb3RmcUo5MTgxMzk0MWZRN2IrU1FNWlZBWVprbUxXUnVoaHR5Z1FoMUJpTFZJc0RqRXhJZ1BORURRZ0RFcEFJQnJsdXlFMkRtVENXaUIrZ0pnQWRqQkhNRXBLSWNRajBhT29oWmc0WWp6R1d5SkFpVUNBSFVRTU5CMGtSY0VRYmJCYTRpUi9pL3dIM0Q1UE1wZDJ0NVFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiJmYmVmZGY2OC1mZTg2LTAxMDYtMjEzZS00ZDVmYTI0Y2JlMmUifX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDctMzAiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6ImVTZWN1IEZJRE8ywq4gTkZDIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEwMjIwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDctMzAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA3LTMwIn0seyJhYWd1aWQiOiI2MmU1NGU5OC1jMjA5LTRkZjMtYjY5Mi1kZTcxYmI2YTg1MjgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjYyZTU0ZTk4LWMyMDktNGRmMy1iNjkyLWRlNzFiYjZhODUyOCIsImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IEZJUFMgU2VyaWVzIHdpdGggTkZDIFByZXZpZXciLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI5NDcyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AzODRyMV9lY2RzYV9zaGEzODRfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6OCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjgsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlES2pDQ0FoS2dBd0lCQWdJVWVmK1Z2SGtjVFFuRUQrK3dKTS9JeHpTVUxrMHdEUVlKS29aSWh2Y05BUUVMQlFBd0pqRWtNQ0lHQTFVRUF3d2JXWFZpYVdOdklESXdNak1nUmtsRVR5QlFjbVYyYVdWM0lFTkJNQjRYRFRJek1Ea3lOVEV4TXpJME1Wb1hEVEkwTVRJek1URXhNekkwTVZvd0pqRWtNQ0lHQTFVRUF3d2JXWFZpYVdOdklESXdNak1nUmtsRVR5QlFjbVYyYVdWM0lFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW91Rk1UT0thRTBZdGV4T29pc1N4cCtFYmk1SUE0ZXNFU2N4MTZselFkcVY2L2VaODJLdEplTlhFdU5rQlZaRHBjMzJnU3R1eExCSDhtZ3NvSEJGYWkyRGtqZkJuNXFid1IvYzUrc25sd1p2amdWQTBoekt3OUN3QWVBd1JENWtyV3Q4OC9DVnlDa01jZ0xTR3dacy9yajdGL0xzM0ViZzdNcUxiYlFKOUNvemJiTGRKVVlJSGNQcFNaUHRvTXJaYjRHdm5pNmlWUzlVdkNLZ3BxYzZMR1Jtb1lHRzRaUjNsR0ovWFFaZnUrR2VKVzY3aWltTWoveW9YT3d4dWN4aXZaSEZrNmNRU2d3dXdpb2VObTR3dms4M0xoU3VXY3RmMmtBeVFjWjdrVW5wTmVlK2Q0TWdybUdVNFhNRkxpVGd1dGFCK2U5VjhkNUpUa1VPSGlMenRrUUlEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVTTVTQjViSHJWK2pwSU9NZEpsN3U3YmNuVFk4d0h3WURWUjBqQkJnd0ZvQVVNNVNCNWJIclYranBJT01kSmw3dTdiY25UWTh3REFZRFZSMFRCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFDb3dSM0tUTGZpZEp5UUZOcUVGZlVyZlo5YWE5ZWdwT1F0TlJKZExTdEo2eHUyV2ZMd3ZHNG9qR0psQktObmZhNURJY3lRWWYvOHFKNGVsaUFWZU5YdVltZU1tZ05nWlp5dVk2RzF5V0NEMlYzc0Q2WjR1ajNTYmFET0hqM2dIdnN6Z1FocmhUMWgvcHVIUWtuNitoWUtBcDc3a003SWM2QVovUkZianBtTExrMkQwc0UxbHpULzAyaStCaDdNOHNtYWlEWjkrK0pHenhlU3VuOFcxSGxlWlVtMnFLR21SYTRYUGRyeVQ3eDZLR1VHblU0YTNicFVtVmVZOXJRL3NmTWQ1WlRvbyszdW5GV0R6b1ZWMnZOdTgrK1ZMQzl6bzQwRmFLUUxyOVZBSkRKNHlMRU5SN0tybVY4TDBjQ1hLSkdaV0FXdEc1UkdUbUhJaGQrbkI0MWc9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsImNyZWRCbG9iIiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjYyZTU0ZTk4YzIwOTRkZjNiNjkyZGU3MWJiNmE4NTI4Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwibGFyZ2VCbG9icyI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlLCJzZXRNaW5QSU5MZW5ndGgiOnRydWUsIm1ha2VDcmVkVXZOb3RScWQiOmZhbHNlLCJhbHdheXNVdiI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyODAsInBpblV2QXV0aFByb3RvY29scyI6WzJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDk2LCJtaW5QSU5MZW5ndGgiOjgsImZpcm13YXJlVmVyc2lvbiI6MzI5NDcyLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJjZXJ0aWZpY2F0aW9ucyI6eyJGSVBTLUNNVlAtMiI6MiwiRklQUy1DTVZQLTItUEhZIjozfSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjEwMH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wNC0wNyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDQtMDcifSx7ImFhZ3VpZCI6ImFiMzJmMGM2LTIyMzktYWZiYi1jNDcwLWQyZWY0ZTI1NGRiNyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiYWIzMmYwYzYtMjIzOS1hZmJiLWM0NzAtZDJlZjRlMjU0ZGI3IiwiZGVzY3JpcHRpb24iOiJUT0tFTjIgRklETzIgU2VjdXJpdHkgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ0xEQ0NBZElDQ1FDdjF2bHFLZVc1ZWpBS0JnZ3Foa2pPUFFRREFqQ0JuREVMTUFrR0ExVUVCaE1DUTBneER6QU5CZ05WQkFnTUJrZGxibVYyWVRFUU1BNEdBMVVFQnd3SFZtVnljMjlwZURFUE1BMEdBMVVFQ2d3R1ZFOUxSVTR5TVNJd0lBWURWUVFMREJsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVJNd0VRWURWUVFEREFwMGIydGxiakl1WTI5dE1TQXdIZ1lKS29aSWh2Y05BUWtCRmhGdlptWnBZMlZBZEc5clpXNHlMbU52YlRBZ0Z3MHhPVEExTVRRd05qVTBNakZhR0E4eU1EY3lNRFV5TURBMk5UUXlNVm93Z1p3eEN6QUpCZ05WQkFZVEFrTklNUTh3RFFZRFZRUUlEQVpIWlc1bGRtRXhFREFPQmdOVkJBY01CMVpsY25OdmFYZ3hEekFOQmdOVkJBb01CbFJQUzBWT01qRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRVRNQkVHQTFVRUF3d0tkRzlyWlc0eUxtTnZiVEVnTUI0R0NTcUdTSWIzRFFFSkFSWVJiMlptYVdObFFIUnZhMlZ1TWk1amIyMHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBVGpiU1pkNjEvN0hhb3h5b3hsM3loNnRqazN0TDZBU0NDdW0vMm5kcTg2RFFMdCtEVTZNVjZmNC8rK3VwQVBiVFpVNmpXbnZJTG92dG5zUmdDV3dVWVJNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJRWlOZk5wQUxaSUg4bjFWeVhwRnlMSXpEZVpFWk9DUmlLaDQ0dW5pYUJaUEFpRUFvZGFuT2xQVUVDakdIRWYrRTRkVEtreUNscExpNEpkRUprVkhRcElYRUpBPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FZQUFBQnplbnIwQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK0xwc2J4dDNJdmVSS2RQVnhYZUY2MHZXZG03T2J3dTJvMjYvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rcWk1cVBObzN1alM2UDhZdVpsbk0xVmlkV0Vsc1N4dzVMaXF1Tm01c3Z0Lzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284L3BQVFQ4ZTduTHVhcnJsY2E3bnVlcjIxZTJiMzZSdWVOODdkOUwxNThSYi8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBZ1kwaFNUUUFBZWlVQUFJQ0RBQUQ1L3dBQWdPa0FBSFV3QUFEcVlBQUFPcGdBQUJkdmtsL0ZSZ0FBQStkSlJFRlVlTnJFbDA5b1hGVVV4bi8zdnZmbWp6T2RtWmNtY1Nha21VeUdxb1FvbEJRWE1WMkovN0R1bExZR0ZIRlJOMEowSVFoU1VBcDIyWTB1dEJaTHNhSllNR2hBVFYxSU54SnIxWkttTnFVWU01a1lrMmttTXpHWm1mZnZ1aGhKdFVMbWpRN05XYjUzM3prZjN6bmZkOTRWMDVsK2dNZUJWNEY3dVQxeENUZ0dqSXZwVFA5RHdGZHNUendzZ2VOc1h4eVhRSFliQVdSMXdBYUN2ajhSQXBUQ1c5L0FMWmZCZFJHQkFGb2lqZ2dHUWFsbUFOZzY0UG11cmV1NHhTSjJZWmxBdXBmb252c1F3U0J1Y1pYcTVTdTQrWG1NN2wySVVBaGMxMDlLVDIrbXVMMzRPekljb3V2WVVjeG5SekNTeWMzMzFhbkxGTjUrbDVWM1RpSVRjWFRUUlBrQUlhWXovU1VnMXVpZ1d5d1M2RTJUL1hvY3JhME5nSTN2dnNlYW5TUFkxMHQ0Y0E4QXhROCtJdmZjWWJRMkV4bUpOR3BKMlQ4RG1vNXlYYXo1QmZTTkNybkRMN0wyNVRtVVcwVnFJU0xEUS9TY1BvRTVjZ0NuVUNBLytqTEJ2dDJ0WTBEb09zN0tDZ2lKbm9oVCsyVVdveXVGQ0Jnb3k2R2F1MHBrWUMrN0o4OGp3eUZtOXU2ak5uTU52WDNubGd4SXZ3d294MEZMSkpBQkE3ZFVKdENiUnVnNmVBcWhhNFN6QTZ4UFhhRDQvbWtBWXZzZncxMWJiWmhYTnFWYXowTUVnOGhvQkx4YnhLTVVHaUhXdjUwRUlOaVhCdHdXQTVBU1pWa28yd1lwLytVUENoc3RHcTFqclZxK1V1ck5HSkN5TEZUTlFqa08wdk1RNFhDZENTbFJHeHNvUEJJSG53U2c4c09QQ0FJdEJBRFl1VGw2VHIwSG1rWis5QldrbEFqRFFGa1dYcVZLNnNnYlJQWTlnTE44ZzlMWk1mVE96aGExUUVyc1hJN0kwQkRtTTA5ampod2djdjhnVHVGR25lNVNtVUFtVGZMMTF3RElQZjhDenZJeVdteEhpeGh3WEpSdGt6eDZCSUMxTHliNDQ1dnpteExURWdtc3VYbFdUcDdDbXAyai9Obm5CUHF5TFhKQ0liRHplU0xEUTJUUGpRT0ttY0ZocWxQVEdMdTY2ek1nQkhnS1oya0o1WGtZcWVUbTBtb1FQcHhRS2J6YU91YWhBd0NVUGhsai9lSWtvY3pkTjZXb0ZFalFPdG9SUXR4ODFnb1ZlSlVLZ1ZRUHNmMlBBckI2OWxNRUJnamc3elVVQ05tY3FuME5vVnNxRSt5L0IvM09UcFJsVS9ucEVucmJ6bWIzL244SG9DcFZndGxNZmVWZStSbG5jUWtaRHJYc2w2Z3hBRnlNN3E2NkQ4d3Y0SzZ0MVhkQWk4SkhKZzh0WWRiYlVTaFFjOHJ3cTN2TEFQd3p0RFlUdmIwRFpWdXRBU0R2Q0FNUWZlUkI3anJ6TVhKSGRHdHRqWTJ6OHVFWmpNNVVLd0FvTU9ySGpHU1N4S0duR3Z2V2NvR2xFMjloa1ByL1JxUnFOWXgwRDNwSHUrKytPcjh0WXVjWDZuL0pQb3hveTBHVWtTaTFxOWVvWExqb0c0QVdqNk9aSnNxeEc0cEFiOVFHNWRobzhSaGFQTmJVZFBzb0RtQkk0UG8yM295dVMrQ2xiUVF3cWdNVHdCTi9YYzhIYmxQaEtlQk5ZT0xQQVFESXNYcWJzcVpLR3dBQUFBQkpSVTVFcmtKZ2dnPT0iLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiYWIzMmYwYzYyMjM5YWZiYmM0NzBkMmVmNGUyNTRkYjciLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTItMDMiLCJ1cmwiOiJodHRwczovL3d3dy50b2tlbjIuY29tIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJUT0tFTjIgRklETzIgU2VjdXJpdHkgS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEyMDMwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTItMTgiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlRPS0VOMiBUMkYyLUFMVSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMjAzMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAzLTAxIn0seyJhYWd1aWQiOiI5NzM0NDZjYS1lMjFjLTlhOWItOTlmNS05Yjk4NWE2N2FmMGYiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6Ijk3MzQ0NmNhLWUyMWMtOWE5Yi05OWY1LTliOTg1YTY3YWYwZiIsImRlc2NyaXB0aW9uIjoiQUNTIEZJRE8gQXV0aGVudGljYXRvciBDYXJkIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEwMDAwLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1FUQ0NBZWVnQXdJQkFnSVVGLzB3VFBQNkZFcXhwc2liSmlMRnREajRxaHd3Q2dZSUtvWkl6ajBFQXdJd2RURUxNQWtHQTFVRUJoTUNTRXN4RWpBUUJnTlZCQWdNQ1VodmJtY2dTMjl1WnpFU01CQUdBMVVFQnd3SlNHOXVaeUJMYjI1bk1TTXdJUVlEVlFRS0RCcEJaSFpoYm1ObFpDQkRZWEprSUZONWMzUmxiWE1nVEhSa0xqRVpNQmNHQTFVRUF3d1FRVU5USUVaSlJFOGdVbTl2ZENCRFFUQWdGdzB5TWpBMU16QXdPVEl6TXpWYUdBOHlNRFV5TURVeU1qQTVNak16TlZvd2RURUxNQWtHQTFVRUJoTUNTRXN4RWpBUUJnTlZCQWdNQ1VodmJtY2dTMjl1WnpFU01CQUdBMVVFQnd3SlNHOXVaeUJMYjI1bk1TTXdJUVlEVlFRS0RCcEJaSFpoYm1ObFpDQkRZWEprSUZONWMzUmxiWE1nVEhSa0xqRVpNQmNHQTFVRUF3d1FRVU5USUVaSlJFOGdVbTl2ZENCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJCd1lnS1Z3akNWNitsdjdnbnBGRVJ6VTJ1TkQ4Z2RFa1BDTmNzL3ZGRHMyc0s0Mkp1eG5oRm5JZ01CMkR5VTBJclhJTGpmLzJYVDBZU1RkMXNQaVRTYWpVekJSTUIwR0ExVWREZ1FXQkJUblFhcnBkU3Q0c2lkN1ZqZk5JTElIcmIyUG9EQWZCZ05WSFNNRUdEQVdnQlRuUWFycGRTdDRzaWQ3VmpmTklMSUhyYjJQb0RBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFEY29YSjNyek5NQS9mWmtoMDhQb0ZyTXg0M0dZTWhaTWZMUHcvM01mSnBHQUlnZWN0S3dtSllNOUo4U1g4eC9hUVY0aUd2S1dvQmZyMVhQVEFNWE9oVkVZRT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBREFBQUFBd0NBWUFBQUJYQXZtSEFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc1FBQUE3RUFaVXJEaHNBQUFpY1NVUkJWR2hEMVpqUGk1VlZHTWY5QzlvYjZESm9JUWkxaURCd0k1UWdFVUVsdEJKMFlTQUdFdVJDRkJNeElrbENheUZJUWlhS0JaVW9sWTdRTkpNNjNuR2FjYTZqNDB3MDA0ekJNQk82TEU3bjg5ejdQZk84NXozdnRkcTUrSEx1ZlgrYzgvays1em5QT2ZldStQdXZ2OExqTERQUUdoNE83Zkh4MEdvTnA4OVZ0YTJkbkp5c2FYcDZLbWx1Ymo2MTB2ejhYRmhZV0NocWNXblJ0TFM0RkI0K2ZCZ2VQSHhnNHJNWGpMNlZEaDQ4MkRYUUJVOUdZanZlYmljMXdRdTRCQSs0UHMvT3pqYkNtd0ZuNHI4b0dSQjBKOW9kSmZoMkhYNHFnaUlQN3dVODBLWG9lM0NEZndSNEhuV0ptZXBwb0tOMkRYNTZxcHd5dEFEUHozVWkzd3NlNlA4TDdsVXhrQ3NIUjNuVUJjMW5xUVR1NGIySkV0Uy9rUUpRTnhEVGhiUXB3UU5INitIVkNwcnZ0TXhDRGsrZUx5NVZvWHVaS00yQW5pOGFhTXAzZzQ1cFkyMEdqNEJWdnVmUjk5R1dQRWhKdlZMSDkwTXdzaG5vSFhrQmUzZ3ZENTdETTFndmFOUUxIRlhoRjIyTVpDQ0hSb0I2QVZtQ3o5TkZzdExZTlZDQ3lhK1ZwT2NFVG45K2pFWURPVGlMOTkrQ2w5SUc1WENLZUsvSVYvcm85dXZIS2hwUW1RU3lHSEdYNTdNLy9CQm1QdnNzM051MUs5emJ2RG5jV2JldXByc3Z2SkEwOGVKTFlXYjM3dkQ3b1VOaDRjS0Y4T2ZNVEJHNkJPL0JwWm9CYlZDK1hHcHhvdGxyMThMMC92MEdNdnJFRTJGMHhZb3crdVNUQmpyNjhzdGhkUHYycEYvMnZ4ZHVmZnh4NVJvYWYrNjVNUGIwMDUxM285cXJWNXY1KzZkT21TRVBMZkNTQVFwSHhRRFJWVnVKZUV5Vlg4K2VUZEMwZC9ic0NhMVBQN1VqU0g5L3Y3V3FaRDRJRERJM1R3cE9tK2lQNjlybGh6Ny9QQXp2M2RzeEh3T0JvZWszM3d6M3YvMjJZcUFFVDFzeDROT0dCeERndDU5L1B0eDk0L1V3OGNreGd4dzhjc1FpT2ZMc001WTY5Ni8wZFFhTFVmTXA0TVVZWEtmTjc1SFhqQVVEaHE2Kytxb0Y2dGFxVldFbXpxQ2dsYnEwQklWM2tnR0Iwd3JlOGpvSzZOWTMzNFNibXpaWng3ZlhyQWwzUHZnZ1RBeGR0M3NNVEtlYStnNVUzWVNYRE9tNzNrVkFEcmRhWVhqclZodVBsSnNmR3JMclloTm5NcEJISDBCZXV2WGRkK0hXSzYvWTFKTG5ZeWRPZEUrdUxYdWVUajJJNUFFVmRWM3o5Mmh6MGFjMEV0TnpaUDE2TXdJVDF4Z1hrWXFWR1pBd3dJTzI2Q0k0RVNEZkJ3WUhESno3eWs4R0ZBaXRwTzhlTnIvdnhYaE4rUTdUelpnSnNJd2RPSkJtQUJVTkxJNk5wUVU3L3U2N3RraEpGYnNYQjFHTkoyMm0zM2tubFVoS284b2lmZDZQcGxWYUtaMUxzVjhCczBoL2pRSFNQY2JNd2VsZllteXFtaTN5ano2eTcyUkx4UUFQOHFLVnVGZ1JicDQrSFFaajFNbHhyaWY0S0VCWkMzVG94VFVBUy9jSUNBc2VVN1Y3VVVvUndWc2JLeUJzQXJhc2lQMndSdGl2S2daNG9iMWxpejB3MU5kbnVjNTFIM1hnaVRDUjE4QTNObTRNd3c2SzZxVFByYlZyTy9kaW4zYXRXeXJUUFJhcXJzVm5WQkM4WkNDWmlNOFB2dldXUFpzTUFNOG1SVWZ0a3ljdDhsd1R2RGVCQWFhZnRVRkVXQmQwWnVhN2NHamtxYWZTL3NDMG16RUhhOFVnaXBuR0NDSmRjK0M4dFQwb211ZmRpZ0dtbHR4WEo4dmduZE9rRnFEMDI4eHZkdnhtVVpWU0NtRGdGN3Q1VDU4VUE5Mm41ak11NGg3UGFxMTVDWjZxUTZBbXZ6aGw3OE5aTVVCMFdPVTJxSXU0b3A2TFJjbXVtZElqVXpMUVBVcWpoUWpobjJlOUViVGZ2L3FxQ0M3eEhYaGFNb1IzTDEyNmxCbUlGNGtRRC9sMFVkN244RTNnRXRPTUFmcTJXY1JBL013QjBLOEZpVVVzZU9UQlUvU2pPQkh3L3ZuejU1Y05BRXduMTQ4ZXM1UXd5SWJJODd4Rm5vRXh3VHFJeG0ybmRrQ2FBYUJ6QWNhUjVPZFlwbGtyNmtzcHBHajdWbUpqWmF6S0RHQ0FtbnpqN2JjN0cxVUR2RVRkWjFBcURQOW1jRkRqMkZFeEVNRms0SSs0NEVnVGlUTVcxeW1GN081Nmg3d20ya0F6QS9UcjRaVSttTDk4dVcvWkFHbGlwVEZPRFMrWERQQ2NQays4OWxwbjBQajg1SlVydGhHbHRIQ3BSWVVCdnJRdmtESVlTSDFGRVZVZjhhbXBaUU9jdlJoamZNTUdTNTlLRlFLWVNzTGdiTnVQbWdGK2pIZ1lMOUtpYVgzb3BObDBEd01HbmtVZWVCWThzL3I5dVhQMkhMTmJNUUFZMnorZFRaODVVd0gyMFpmNEpaYWlIald5Y3FYQkU1a0pOc0s0aUhVUGFBQkpFV1lsdjBjcUFzVzdIaHhaMnNSeE1DQjRuaU4xYXdiUTVMWnQxakdiandjdWlmVkNKQUN6VHJzQVdxaDg1NTZrVXl6UDhCMFlxUVlmVTFNbllVdWJhUHppeFlzR3pwaVZHY2pCeUU5ZXBFYVQzL2w5aEdtSklxQUtrNnZwU0tDV2RhQmZiRGs0bFl3RkMveFA4YWNzMEFTQmRqaTJ4UmxBWEtOZTIzRWhUakVMdlBKNzFZa2FYNE9PY0VBelE1TGdVNVhoendPbmUvdjJwZkV3SUhEU2k3TEpid05tVFNZcUJqeTROMEprMlowdDEyUEg5dU9iMzZzTjRCTHd0SUwyRWFmMWFjSVppQlNaMkxuVDloTkxxYU5IN1pESXVCeWpsVzRHSDFNTmVOckdGTXBGQkc4ZS9yRHo2Nmk3OERERGIxYU95QjZlWnkxdDNGRllBanB2MGRVdnoxa0JFRFRDV04vWFgxdkp4QURRRXZBMUE3Mk1LRjBZbEttOGZ1aDlHeXp0b2xGc2hLd1ovWlltSmRpd3ZEaEpFbWxFMU8yRTJuMmZ2a2lYL3VQSERWcmdnT2FSTHhvb1FhdE5jb3VWeUtsakhRdUltdVZyQkpQSWEvOWQ0dG1yTzNhRUh3OGZ0bHdIbUNyRERpdkFsTy94QjR5dVNSejVINWxDVGZCZVdxd3lwQ2dSdlpMSVpTRFJ3T0NnaWVjVkRGcEpzRjZBNjNNeUFLRGFHbmhVTDNCYTVUalNRa1Y1cm52WjMva08xZ3U0UEYyUTRBbEVaUVlFbmtlZUt0UlU0L05LZy9JcWt4OEpKUDB6VjRIdWJsQUczZ01lWVlDMlprRGdncytoVTRYcGl1K29aTUFiRWJSYUQ5NkJYOTZjZXNFcjh2cGNNZkFvZUVtd0F2YzFYdktuU0s4NitITE9HM2dCM3Y2UDZnS3J4UVRYaXdieURVcXBvcWpMZ0lkSEFLck4xVFBmSXpTUkwxV2FFcnhhRm4vTmdBZjNLbTFLT1R6ZmMzQ1U1N3VpVGl2UWtwb2lUeXRWREpUQWdiUElad1lFRDJBVHVJQ2JCSlRhWEwzZ3VWY3prSU1yYlpBSHorSHoxZ3M0dFFhcXlFY2crL2M1U3hzdFRyOUkxUTRNRENab3IwWURBczl6SGxXaTMzT3hsdk1lS0xVbCtlaVQ1NTIybWpwU01zQ0h4MU1Id3o4Y2VIeTdFaFJ6NVFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZEJsb2IiLCJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6Ijk3MzQ0NmNhZTIxYzlhOWI5OWY1OWI5ODVhNjdhZjBmIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwiZXAiOmZhbHNlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzEsMl0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6NiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMDQsInRyYW5zcG9ydHMiOlsibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjoxMDAwMCwibWF4Q3JlZEJsb2JMZW5ndGgiOjY0LCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6M319LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA3LTIwIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJBQ1MgRklETyBBdXRoZW50aWNhdG9yIENhcmQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMDcyMDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA3LTIwIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMC0wMyJ9LHsiYWFndWlkIjoiNzQ4MjBiMDUtYTZjOS00MGY5LThmYjAtOWY4NmFjYTkzOTk4IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI3NDgyMGIwNS1hNmM5LTQwZjktOGZiMC05Zjg2YWNhOTM5OTgiLCJkZXNjcmlwdGlvbiI6IlNhZmVOZXQgZVRva2VuIEZ1c2lvbiIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDNlRDQ0FkR2dBd0lCQWdJSkFKYlR5cnUxWC9JUE1BMEdDU3FHU0liM0RRRUJDd1VBTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRBZUZ3MHhPREEyTVRJeE5EUTFOVEJhRncweU9EQTJNRGt4TkRRMU5UQmFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNVmpLSFdwYkQ3VFNsTXhvY2pUbDZuSWY3eDMyUG1zUTl6R3VMR0dxQTBVUVpvSXEzWEx6TDZMWVV2SjVBNWcwdXlGR2xsSEVmR0FLckVhQ1E4RlZ2UFMvVWgwRnlmeldoUkF6aVRTaWpqTUlJVmpqalV2OW05dkZtY1hTY2dIaWc3T2R6ODg1OFYwa3JOSDk5cUdtM3dqZ2FPZXJUV210K2pYQ1VmbjAxSWtUUHd4RzJIbGdFZDQ1ak5MU1Y3Vm9vbCtLZThFMmtpNGxFa1RlSHpib3VsUjVHVWJwM25NaTdFNDdWTVFhM2JOd256V0Jic2FCU1NRaExrM201SGFLaGh4YTZ3SkRLNDdOaU1Da0NrZElIdVdTUUxWQWZtODVVQU9OdEVPUHdpME91SzNxYmU4eUtPRkdmMEtoQjVNTWVBeW03TVYvTTRXMGE0OW9nUEQ5cE1DQXdFQUFhTWdNQjR3REFZRFZSMFRCQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKV3o1eExNazVXTlliQWI2eU94RUNCb1oyV2VCL3FsNFZKM08vMy90TnN4T1luekxlV281NDB6UWg5ckFtYXh6N2V1bUJsc2tNcTR5R1BTTlhCOXljV0dIZ2tjQ2VTek4yd3Y4Q0l6REJzMm9CWmpUTms2NUxCWkRzc1RPQnRNVy8rdVRGSFFmYnVPM0lTTGhJMERYZlJFaTlORE0zamZrMTF4SGNzZmgyUk1WK1FkTmZ3VmFaWnJDcStvdUcrRXZrdjdLcXErb3l1MFZGTS90ejY4VEdsNnlsaFBGUjFxaDl3dHRwVmpBT09DRVFDTHFQMmRQMjhsd1lCeUNxSFFxVkh3YnVqdi9MWmpabktXM0xZbmRaaXhQUFNSQ0pzc0REd0p2aC9mNm5UeGc5WkUrL0pjWXJlNUNhSThuelZIYVNPQ2pOSjdGelVMRzY0SmlXT3ZRNTA9IiwiTUlJRGRUQ0NBbDJnQXdJQkFnSUpBSUNVVHZrZ3RqNUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GRXhDekFKQmdOVkJBWVRBa1pTTVF3d0NnWURWUVFLREFORVNWTXhDekFKQmdOVkJBc01Ba05UTVNjd0pRWURWUVFEREI1SFpXMWhiSFJ2SUUxMWJIUnBRWEJ3SUVaSlJFOGdVM1ZpWTJFZ1EwRXdIaGNOTWpBd056QTNNVFF6TnpFNFdoY05NekF3TnpBMU1UUXpOekU0V2pCUk1Rc3dDUVlEVlFRR0V3SkdVakVNTUFvR0ExVUVDZ3dEUkVsVE1Rc3dDUVlEVlFRTERBSkRVekVuTUNVR0ExVUVBd3dlUjJWdFlXeDBieUJOZFd4MGFVRndjQ0JHU1VSUElGTjFZbU5oSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFLT2VxQzUvcDBEMWlzQ1lLUUpsVlVPckI2STdETG9jdW5FL1JtOGR1R1RieXhRaHQzQ2JGVlR2M04yTHAyZmJqeGxJKzNzT1NHazMzRlRZa1RxeGNkSklySjdTc2tCY1VTTnJmS09hUVQvNktRY1A0Q203Vis2NTVUcStUV3h5eFdRaER5Z3QxNXFvUDdNdUs2YlQ5U3dwQ2pwZktoYU1TbXlRYU1vVWNSQWJMcWR6QkNhYzBoekIrWmUrZ3FKbG5XVjlVYVNJMnJGc1Z1SDRaRTBjUk8rTU9wYUxnTS9zMjQ4bkdHSHAyMmV3U1FmYm5QYUJiYjhpcXlBUCtjdTUyR0xzVXBLUkplYkUrUjYrUE1ROUpDZFdlUVpSM0RrZlNpZGt2M21jYjRqcTFpSXRhK01xS2hSbndyZlhoOTExS1dMbllBbDlFTkNoTFgwYzZTajFRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3SHdZRFZSMGpCQmd3Rm9BVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUZMckRoYWVnZUtIeFlqSDNFUDN2VUJLaG56TTIwNkFTeGdlWUNPMkVjOXBPbFlKYWVxRkUrc1VhbVVWL3B3akRscU5hU2dGZ3k3VHdlWWt2T21NbjRxU2NzSHF2SjN6R09BaWFmd2FoMXZVSGZDbFhSOCtheE8yaUdPVUYwSktyWjlZWWpiQWE1LzRIQ2x2N2pGUE9kTVdUT1F5bmdvaUhBczNqa3VZanBDTEZsQjRWT2kzZDF3akExcG5UZEJLa0FiN3Q4blR2dysvWGJGdmNRYTczVkg3c2p2b0JxRDNmZE1mUmN1VnE0cVVadFpUNmNHYWdUSEQ2MVR0cWg5b01DWlhjRGJSMVBHWm5OYnF5Y3NXUERJSzBucG1LMy8zbGZWOGMrWnNyeTZlMTcwbWZKTVpwN084bTZDU3o2L1ZMSyt5REpkNzg0MXdwbWVLVGY2SW5aQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVF3QUFBQWdDQVlBQUFEbmxVWnFBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFBQVpkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNakh4SUdtVkFBQUsxRWxFUVZSNFh1MWREWEFjWlJtK05PQWZLb2c2V08wUWNyZVgzTzcxUjQxb0hkU3FxREFPZzMrY1lFWEJvbFhSVEVuMjIwdGFLVGM2NG1nQnF6QmlFVVZwQmRxaXd3aHFTZElTMnVwWVNndlJ0cFRTY2tsald6SGFnanBTUmRyNHZMdHZqcnZrMjd2ZHZkMUxqbjdQekROM3QvZCs3L3QrZjgvKzc4YUswTkRhYXIycU9kWFpvcVd5SDlSMGEwRmN0NjdXZEhHVFpvalZDY1BxU2VqVzFvUXVIc095L2VCVHNEbU0vNTRaVDlqK0xXR0lnN0RmQi9zQmNEUHNmNFhmUDhYM2IydUcxWkhRelU4bVV1S2R5V1RIbTVxYWNpL2pIQUtCeWlmMGJCcitMd2FYSVBZUGtNZHFmTDhYZFdwbHMxQUEzMS9Rak93OThMOFM5YjhCWElSMituRGM2RG96bHNrMHNsbmtRTXhrUEdYTzlFSnRWbllHRjRzVXlWbmQ4VVRhZXA4YncrNkxha0JqNWl6ZGJOSlMxcnhFV255V3hnMzZFbVBkV29QUERlamY3ZUFUR01zSGFEelR1QzZoYmowTi9wWG1Bc3J1Z3MwV0xQOE51QkpqWkptV0VsY2wwOW1QSjFKbVcwdEw1K3VpSEJ1R2tYc2xqWDg3bmk0RXpWbms5QXZrc1FuNTdFU2RockI4Qk11UGpPV1AvLzRPSHNSL2U3RDhZZFRsZnRSaEZmZ2RMRzlIdTF3QWZ6cjU1akFPa2lRS2h2VmJHQjZDMC8vaSsyaU5lUng4RmdudlJmeGZhaW56U2s3TkUwaUlVUGJmNDN3V21OVE5kN0JwS0VBN0xaZkZBWTl6cDN5WlRTTURpUVZpL1UrU2c1UVlBSWZPbUcyZXdzVWpBL3JoVzdMNEJlcm1qOWgwVW9CMk9CK1RaVFc0Qi9rOE95Ry95Q2lPb1cxSVlINkg4WFB6OUxiY0t6aWxRR2hwTVp2aFp5SEd3RzNnNDJCazg1WjhvOTBHOFgwTmlTczFJdjJRR2s4S2RXc3p0NHNuSVA4UnFSOW1EUVhESWRaU2JCb1owSWwzUzJPWFpYWXBGNDhNVTE0d25LMWJlVzQxcEwzRkVRQ0psUFZXdERHMmZ1eVZyTlIzdEJUZFNqQjhZcklGb3lWdG5vMk9DekJneEROQkI2cFhLTUh3eGlEOWdLM0tjNlBja3ZCR0pSaStNY21DMFlENGZkSzRYb2g5Vy9ZVENaUmdlS052d2Noa0d0RzJlMlcrYWtzbEdMNHhtWUpCYXhscFRJK2tOUlFkbUdSM29VTUpoamY2RlF3NmNDcnpVM3RDTUxEV3VRc2QzUitBdzNLbkJRNUt5bmpoamR4T25uRGlDRVp1R2pyc1lXbE1KdHBpV1VLM0JtVC9GZkV1ZGhnNlVQZTZGZ3owYlI2ZmE2TW1uWTNrbER3aGFZakxVVTZlczI3dDBnenptN1ZnVXU5NkQ2ZmtIeENhNjJVVkdDTXE4ZzAyalJRbmltQm9SdllpYVR3bTJudGZXOXZDazdXMGRZSHMvd0oxNjNrNmVNWnVRMFc5Q3diRzlLMXNPcVdBdklVMFg1dGlEWnROYlNqQmNHRUVndEhXZHN2SjhFMm5BdVV4aWJwNWhXTTkyb0RmMnliOFgwS3gzckVORjBvd29nSG0waEpwdmphVllQakNpU0FZaWJUMWVXa3NKaWJDay9QbTVVNWljOHJ4UXBsZE1SUHA3SGxzSGhxVVlFUURKUmdoNHNVdUdIU1JEK3BJVitUSjR4SDFMRzlkakNIVGlNbFI0VmlHMkU3SFJiaEFLRkNDRVEyVVlJU0lGN3Rnb0oyejBqaE10SE9lamwyd2VRRlkvbEdaZlNuRmZEWVBCVW93b2tIQ01CZEw4N1dwQk1NWEtncUdJUzV2VHB0bmgwWFUrMDVabkFKREZBekQ2RGdkL3A2V3htSEdEZkZGTmgrSDBRYjB3YU95TW1PRStPVU5JL2NTTGxBMTZsMHcwRjY3NDdxNHBScEdjZHFhN2t1UjVVdEVINDVnRG13S2kvRFpqOC83SUVTMzRyT3plYWFZeldsVWgzb1JqSm96Uk1Hb09BRU5hMGkyZFRHR2VFcDhURkptUER2WXZHclV1MkNFUWJxaGtzT0ZCc3lsaTJXeGFzVGo2TmQxMnBzWHY1N1RDUVlsR0M0TVNUQmFXNjAzb28xZGI2cXpxVnRmWW5NNTZBcEJ3OW94b1Z3Uk1ZbEdOSzM5MVZ5aUtpakJpRVl3bWxQZExiSll0U1RhN3FIaUErdStvUVREaFNFSkJ0cHZoZFQvR0hXeHY5eld4UmkwdFBpRXRId0p4YlZzWGhXVVlFUWpHSFJ3R3VPaDBnVjVrVE9lTWkvaGhQeERDWVlMUXhDTXMxcXRWZ3p1OHJldnB5eVBqd0h3c3BWaC9TdVZXaktkQ3dTR0VveW9CQU81cDgzM29wK2VrOFdzRmRGK3dhOFNWb0xod2hBRUEzN1dUUEJiUkhUY0FleEd2SlROSGZRTU5jZjZCcytQOWVibnhmcWVQSldYMmtDWnpIZ2ZFeGpDR1FJbEdORUpCc0YrRUpFdWRzdmkxb2JpVDV5S2Y5U05ZT2pXWmpUeWZhSFJ1ZDlBSG90WXBXQTROeHFKWTFMZlROVDVLMndlaTYwZk1pQVVENEtqQmZibWo4YjY4c3RqMnc3YUQycWhmVS8weHk2WnJ6SFMycXVscFRObCt3eUl1aGNNakJVNjYxUU5tMmN1UG9QRFJZVFJCanBiUjJNQU9WOUhaek9ROTgvdy9mWXdpUEh0ZmplMGJ2MkZrL0NQZWhHTU9yc09vL0x0NjdvMVhEZ1Z1aUUvQndMeGp4S3hLT1hHMk02ZHRpMzZ3OE9SZG5HUDdUY2drRnVkQzhiVXZBNmpsa2lrTzgrVHRnMklNWFNZemZ4RENZWUxxeEFNTDdldm83N3R0bkYvLzBuWWt0Z2hFWWx4SExxYXpKMnRqRXFiczlpeVNXWG4ydjREUUFsRy9hT3NZQmpXQVRiekR5VVlMZ3dzR0xscEtMdFY2cE5KSFZaNFlITGYvbmZKQldJQ2gySGRRRVhpNmV3bE1yOGxkSjVIWXR2N2hSS00ra2M1d1VENzdHVXovMUNDNGNLQWd1SHA5R2RLWE1YbUVJeDh1MFFjWFBqWWErMHltVXdqMnV0eHFlOGlvbzRYMnZZK29RU2ovbEZobCtTUGJPWWZTakJjR0VBdzZIb0s3QTZVbmNpbzU4R21wc3RlZUIxRDc5Qlg1ZUlnNGYzRHAzT3BHT0xNbC9rZnh4Mnh6RnJmajhWWGdsSC9xTEJMc29YTi9FTUpoZ3NEQ0VZaVZmNzJkV2JwSmR3OSs4NlJpc040OWc3dWgzVmhGNFBGNlFtSi8xTHExZ0l1NGhtVkJBTVQ5dTd4NzB3SmcvVFlmVTZoTEpSZ1ZFYUZYWklIMk13L2xHQzQwS2Rneko1dG5nS2ZCNlMrbVBqLzBJd1pIUy9uSWc1R1J4c2hCZ05Ta1NqbFlpNVJBUHJ1VWxtY1ltSnkvWG5HM0hFeEs2RGlGa1pFeEJqWXlDbVVSU1hCUUR1UG9BNWJvMmJTeUw2ZFUvSUUzaXFVbmdZTm0yZ0QxN04wK0c4VnArUWZTakJjNkZNdzRycGxTZjBVRVRGTk5pOUZ6L0RNV0cvK2lFUWtIUGJtTjhTMmJadDQrYmh6ajBuNUozaUJkRnMxbC9BRTFMMnVCYU5XVE9yaUE1eVNKeUR2NzhyODFKeWVyeTZXUUFtR0MzMElSdE9jM0dsb3A4TlNQMlBVeFZObDEvVHI4cTJ4dnZ4NjhQa2lzZmduZmw4ZjZ4OTBmUVVsNG41R0dxK1l1amh5NXF6dTEzQ1JpbENDNFkxMUtSajBXa2d0Ri93bVJTVVlMdlFoR0Y0bUdBYUxZUFB5MkRnMFBkWXo5SDdzcHN5TjlReFVmQzBpWGZ5RlB0b25pMWxNR3F4Y3BDS1VZSGhqM1FrR3hDS3BXKy9tZElKQkNZWUxQUW9HdllRYTl1WGY3MWxwNjZKS2xIdDgvUXNVUiswWFRYdUFFZ3h2ckEvQm9MZnIyUWZIci9HemxlbUtLU01ZdW5rSFRTekVsTDQrc0ZhQ2dmbytCKzdXak96bjJMUXNuTmNHaUQxVVR1YlBvZG5GNXBHQXpwZ2d2dXRXQnVyNkg3dE91cmlVaTVRRlhTV0tNdC9IQk41RWF5WFVyK3c5TWNFcGp2R0s0dmZJYndWZHc4SXBsQVdOQlpTNUR2V2hONVhuNGVkb3FkOG9pRnl4MndrK2l1LzBJdWlsOUt3VFRza1Q0bWx4RHRyelJtNVhqUFVvMnBYZTZHNDlnanh2dytmQ2hOR2hjZmh3UUM5amFUTEVHOXhvR0ZlV3ZpWStVdVNtMlErY29YZHk2TllpTk93eVZQckhHQmgzSm96dVVDc2VUNW1YUWZGL2poZy94T2ZYTmQyOGdqbzBhSDNwTEFsTk5HZHRMNVlpNTV2UWdiZWo0KzZnLzlnc01xQU9IM0hhU2Z3RWJYY0R2bWVUaHZVcFRlOTZ5NFF6TTc2UW05WTBaOUZwZFBjbTZ2TnBzQXQ5c3R4cE8rdlg0RWJFMjBvVENjc0dTb25sK0IvZjZXYS9WY1Y1MGFTUHg3dE9EZUVCeGcxMHh5K2Rrb1hnZkFneEZpRGUxOUFPMzBNL3JFUU85eUxtQTRpL0JiKzNsK2Jua1BJSE40UHJVTCsxK0Z3QjIydmhveDFpZjFHODFYcGJ2QTI1WmpLK3IybHhSMjRhMWQ4UlB6RWZ1d29XY3NFV2lKTXpZaitJM3crVnRLc2hIZ0gvQVBaU25xalR6Zmk4eGg2N3VuVXVQZHJBMjhOeFlySC9BejN0STRqNStUT0xBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI3NDgyMGIwNWE2Yzk0MGY5OGZiMDlmODZhY2E5Mzk5OCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTA0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0wNCJ9LHsiYWFndWlkIjoiMTEwNWU0ZWQtYWYxZC0wMmZmLWZmZmYtZmZmZmZmZmZmZmZmIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIxMTA1ZTRlZC1hZjFkLTAyZmYtZmZmZi1mZmZmZmZmZmZmZmYiLCJkZXNjcmlwdGlvbiI6IkVnb21ldCBGSURPMiBBdXRoZW50aWNhdG9yIGZvciBBbmRyb2lkIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJpc0tleVJlc3RyaWN0ZWQiOnRydWUsImlzRnJlc2hVc2VyVmVyaWZpY2F0aW9uUmVxdWlyZWQiOnRydWUsIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiXSwidGNEaXNwbGF5IjpbImFueSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ216Q0NBa0dnQXdJQkFnSUpBS0JFd1NkME9GWE1NQW9HQ0NxR1NNNDlCQU1DTUlHaE1Rc3dDUVlEVlFRR0V3SkpWREVPTUF3R0ExVUVDQXdGU1ZSQlRGa3hEVEFMQmdOVkJBY01CRkpQVFVVeEZEQVNCZ05WQkFvTUMwMXZkbVZ1WkdFZ1UxQkJNU1l3SkFZRFZRUUREQjFOVDFaRlRrUkJJRVpKUkU4Z1VtOXZkQ0JEWlhKMGFXWnBZMkYwWlRFbk1DVUdDU3FHU0liM0RRRUpBUllZY0dsbGRISnZMbVJwZEhSaFFHMXZkbVZ1WkdFdVkyOXRNUXd3Q2dZRFZRUUxEQU5TSmtRd0hoY05NakF3TVRFMk1EazFOakl5V2hjTk5EQXdNVEV4TURrMU5qSXlXakNCb1RFTE1Ba0dBMVVFQmhNQ1NWUXhEakFNQmdOVkJBZ01CVWxVUVV4Wk1RMHdDd1lEVlFRSERBUlNUMDFGTVJRd0VnWURWUVFLREF0TmIzWmxibVJoSUZOUVFURW1NQ1FHQTFVRUF3d2RUVTlXUlU1RVFTQkdTVVJQSUZKdmIzUWdRMlZ5ZEdsbWFXTmhkR1V4SnpBbEJna3Foa2lHOXcwQkNRRVdHSEJwWlhSeWJ5NWthWFIwWVVCdGIzWmxibVJoTG1OdmJURU1NQW9HQTFVRUN3d0RVaVpFTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFQ1dlcDhXYkF2T0ozbFRCemk4N2YvQ29ZNVgwSFQwM0liMk8xWllqM2ZmTkJqZ1RxV3NPYjZNSVI0dzdLbTVrVlhENThkR3loOTV5d0lERFJMUWdjNEtOZ01GNHdIUVlEVlIwT0JCWUVGT1lOUHhKVW1NOHZxZXFNNHBkMFNmdTNNOU5OTUI4R0ExVWRJd1FZTUJhQUZPWU5QeEpVbU04dnFlcU00cGQwU2Z1M005Tk5NQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdDd1lEVlIwUEJBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUFscWdOZnh6QVBtSUQ0c1F3b09hdDROQ2RMZmdaZlQralNLbVh2WXZEVHVBaUVBKytsU2NBZ0VBRDFNZWMxUWhvZ2U0eWFzcDBGMmZNWWNOeXhvSzlyb0dVWT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTWdBQUFESUNBSUFBQUFpT2puSkFBQUFCR2RCVFVFQUFMR1BDL3hoQlFBQUFDQmpTRkpOQUFCNkpnQUFnSVFBQVBvQUFBQ0E2QUFBZFRBQUFPcGdBQUE2bUFBQUYzQ2N1bEU4QUFBQUJtSkxSMFFBL3dEL0FQK2d2YWVUQUFBQUIzUkpUVVVINGdNQkRTSTNmNU45NEFBQUdlRkpSRUZVZUY3dDNYMXdWTlhkQi9Cenp0MmJmY2x1U0VnSUVwSk5FQ1hRSUFSQ1VMUSsrRmFuaXBTcXJiYVdjYlJUSEtzejlvKyt6ZlNmcDUzcDAzL2FweDFtMm1mR2d2V2xxSFdxZGlyRmw2S1dDaUtRaEpBSVFoQklza2t3NzIrYjNidTc5NTd6ZS83WVpOMkU3TjZYdldlemE4OW5uTTQwbkp2czd2M3V1ZWVlZTE0d0FDQkJzQnZSS3lBSVZvaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeDhJWUlsVmduSVBRNjlBam1QMHRpaFE2QnA4c2FOcEt3TVlheDNnSkFOZVI4c05qb2FPWENBOWZmSERoNTBiTnhZY01NTjBvb1ZJbDRMTHUrRHBiVzNzOEZCeEJqdDZhRzl2ZXJSbzg0ZE81eTMzb29jZWYvVzhscCt0N0VnSEk2ZE9JRlVGV0dNQ0VFWXM2R2h5RXN2UmQ5NkMxUlY3MmlCby93T0ZyMTRrVjY0TU92Q1J3Z29TdVRWVjZPdnZRYVJTT3BEQmI3eU9WaU1xUzB0TURVMXQwV0ZNVVNqa1FNSEluLzVDd1NES1E0VytNcmpZTEhCUWJXdGJmNTJPc1pJVmFQLy9LZXlieDhiRzV1bmdNQlpIZ2RMalRmYlU5MEFZb3dBWWg5OG9QenBUMnhvYVA0eUFqZjVHaXdJaGRRVEo1Q202UlZFYW5OemVPOWUydHVyVjFDd1U3NEdTN3R3Z1Y2NlpMQy9TanQxU3RtemgxNjZwRmRRc0UxK0JvdFN0YWtKUWlHRHdVS0VhT2ZPaFo5K1dqdDdWcStvWUkrOERCWWJHTkRhMjQybUtvNFEydDBkL3VNZjFaTW45WW9LTnNqTFlLbW5UckhoWVhQQlFnaGh6QzVmVnA1OVZ2M29veS9hYzJ0S1lYSVNwcWIweW1WUC9qMzNnS2twdGFrSlVZcUkrVzhGSVd4d01QemNjKzVvdE9EbW01RWs2UjJRMnpTTmRuVnBGeS9Tems3YTNTMnZYKzk2NEFFckh3c0grUmNzcmFPRGRuV1pycTRTQ0lHSkNlWFBmNGFwS2VkWHY1cS9qeFRaMEZEMDdiZGpSNDVBTUlnMERRRmdsd3NpRWV6eDZCMmFEZm4yc1dxYTJ0UUU0WEJHMzB1TUlSU0t2UG9xS0lweiszYnNjdWtka0dNMFRXMXRqZno5Ny9UaVJRU0FNRWFTaEFCWWZ6OGJHNU5Fc0N5Zy9mM2FtVFBXcTZzRWpDRVNpYnp4QmtTanJudnZ4WVdGZWdma0N0YmZIMzNycmRpUkl6QTFGWC91UHYwUEdFTW94QUlCYWZueXRMOGdTL0lzV0Zwckt4c1pzU0ZZYU9heHo5dHZReWprL3ZhM2NWR1IzZ0VMVFZWalRVM1IvZnRwWnlkQzZNbzZHNkpSMnQwdGI5a3l6N0ZabDAvQmdzbEo2ODMyZVdHTU5DMzJ3UWVnS082ZE8wbFptZDRCQzRiMTkwY1BISWg5K0NHRVFtbmVQZzBFSUJMSmhZdDdQZ1ZMTzNlT2RuZmJVMTBsWUl3WVU0OGRRNnJxL3M1M1NFV0YzZ0ZacDFkUmZRNWoydGNId2FBSWxobWFwalkzUXlSaVczV1ZER08xcFFYQ1lmY2pqMGpWMVhxbHM4ZGdSWlVBazVQMDhtV3laSWxlUWU3MFgydU9vSDE5MnVuVE5sZFh5VERXenA0TlAvMjAxdEdoVnpRclZEVjI5R2hvOSs3b3dZTkc3NEl4QmtWaGdZQmV1V3d3OEhKemc5cmF5c2JHT0FZTElZUXh2WGhSMmJ0WFBYVktyeWhmckw5ZmVlRUZaZS9lNlFmdHh0ODFZN1M3RytYQXNPejhDQlliSDFlYm1oQmplZ1V6UmdnTkJKUm5ubEdibXhmbXNZK0ZpaW9aeHJTcmk0VkNldVc0eTQ4MkZqMTdsdlgybXZqaVpvSVFOalFVM3J2WEhRb1YzSHl6NlZPYkFiTXRxbmxnek1iSDJjQUFLUzdXSzhwWEhnUUxZckZZVXhPdlp2dThNSWJ4Y1dYZlBsQVU1eDEzWk9HeEQwU2o2dkhqMFRmZnBGMWRDS1c5OVVzUFkxQVVHZ2c0YW12MWl2TEYvU1BMSE92cm8yZlBacW02U3NBWWdzSElLNjlBSk9LODZ5N3NkT29kWUIzdDY0dnUzNjhlT3dhS1lqMVNDYXBLQXdIRW1BMi9LZ041RUN6MTVFazJQcDd0WUtIcGIzL2s5ZGNoSEhiZGV5OTJ1L1VPTUEyaVVmWFlzZWorL2RNanAyMkpBc1lzRUlCd0dIdTlla1U1eXZWZ3NiRXh0Ymw1d2I1L0dLTllMUHJXV3hBT3V4OThFUHQ4ZWdlWVlITkZsWUF4SFJoZ0l5T1NDRllhMnVuVHRMZlgrdWNldjdQTHBMYkRHS2xxN1AzM1VUVHErdGEzU0dtcDNnSDZ1RlJVQ1JoREtFUjdleGUycHplbmd3V3htTnJjakdJeGl4ODlnRlJaQ1lxUzZYUHIrRXl5STBkQVVkd1BQMHpLeS9VT1NJZFhSWlVzRnFOZFhlaW1tL1RLY1pUVHdXS0JnSGJ1bk1WTUFHQ24wM252dmRqdFZwNS9uZzBNV1B3OVNkVG1aZ2lIM1k4K0tsVlY2WldkQjkrS2FqWWFDSUNpOEdnWEdwVFR3VktibTJGaXdtSWdBTWp5NVk2Nk9sSmNqSjFPNWZubmFYZDNwdWNTWSszTUdXWFBIdGZPblk1VnEvUkt6NUtOaWlvQlkzYjVNa3hPTG1Dd09ML0RETERoWWZYa1NldmQzNFRJbXpiRit3a2RkWFh1WGJzY3RiVTI5TjBUb25WMFJQYnRnL0Z4dmFMVElCcU4vZnZmNGQvOUxuYm9VTlo2NHlBWVhOZzV1dGw0azlab1o4N1F5NWN0bmdZQVVsSWlOelFrZnVDNDlscjNybDJPZGV2U0hHU0MyNDBLQ3ZRS0lZUVE3ZXBTOXU1Vm5uMlc5dlNZZStxWENZd2hFcUVMK2pUYTBtbmpEeUlSdGFuSitzTlVBTWZhdFhNRzZVcFZWWjdISHBNM2JVcDFrRkd5WExCNXMrNmNCVkNVNkx2dmhuYnZqaDArbkxXSzZuTUF0THNiWWpHOWNyemthQnVMZG5kckhSMFd2OThBMk9XU04yMjY4bEVNV2JMRS9kM3Y0c0xDMk9IRGlGSXJ2NTh4YWZseTNacVBkblZGOSsrUE5UV2hhRFRia1lyRG1QWDJRaWlFamRXc3RsdUk5NndMUUcxcGdXRFF5b2xIQ0FFUXY5K3hldlc4LzBoS1N0dzdkenJ2dkJQSnNwVUdITWFPK0NxNnFVRTRyTHo4Y3V6SUVlc2RKWE5ZZUowSXNiRXg5dGxuZXFWNHNlTnQyNDBORDJzWk45dlRUSTdBWHEvcndRZGQ5OXlEWFM1emZ3VUErM3h5UTBQNnhHTlpKbDd2OU1Tc0RBRWdoTERiYlRxZ00wK2o5Y3J4WXZMbFpvWFczazc3KzAxL2xIRUFwS3hNM3JneGZTbnNjcm51dTgvMWpXL2d3a0lUMlFKdzFOYnE5MmpMc2xSVFkvSDFKMk1NTzUwRlgvNnk2NkdIc050dDRuWEdhUnJ0NmtLVTZwWGpJdWZhV0tBbzA4MTJheWNHd0ZGWEp4bVpFeUhMenJ2dXdsNnY4dkxMTUQ1dTZNL0pzdHpZYUdTcUFxbXN4RzQzS0lyRlNnc0FJU1Q1L2M1dDIrUXRXMUFrRW52bkhXcDJhUWFNYVU4UGhNUDJQdUkwS09lQ1JidTZ0RG5yMVJvSGdEMGV1YkhSNktJTWtsU3dkU3QyT3BXWFhtS0RnenJaWWt6eSt4MXIxNllyTTBOYXZoejdmS0FvZWdYbnd4ajJlT1RycjNkdTN4Ni9zUVZDaU45UEF3R2o3eXNPWXpZOHpJYUhKUkVzQktBMk5VRXdhS2ordUJLQVZGMXRyazhjWTNuTEZ1UnlSVjU4a2ZiMHBQdTdHTXNiTnhwOENJMTlQbEpSWWZvNVVyeWl1dnBxNS9idDhxWk5pUnM2TE11UzM2K2EvVXppVDZON2VxUVZLL1NLMmkrM2dzVUdCOVZUcDh5ZGpHU1NKRGMwV0tqNTVRMGJzTnV0UFBkY3l1VkdBUENpUmNrOXJ1bGh0MXVxcXRKYVcvVUtKbUVNZTcwRk45N28zTGFOWEhYVm5IK1UvUDc0bWgvbVBweFliS0hhN3lhL0JKeXBwMDZaL3BZbkFKQ3lNb2Rlc3owVngrclZudTkvMzdGbXpmeHRaQURINnRYRTc1L25uMUtRYW1vTTlzNVBWMVRYWHV0NS9ISDN3dzlmbVNvMGMyMjk4dWM2TUthZG5SQU82NVd6WHc0RkM4Smh0YVhGeUhxMTh3TndyRnNuelhkV0RKS3FxejI3ZHNrTkRmTmt5K21VTjI4MjFka29WVllhdXVWa0RCY1ZPZSsrdS9BSFA1QWJHNUVzejFzS0Z4V1I1Y3YxZjlzY0dMUFBQb09KQ2IxeTlzdWhZTkdMRituRmk1YXJLMXhZYUtMWm5nS3BxSEEvK3FoODQ0M3hNVmpUUDJWTXFxeDAxTldsUFhRdVVsb3FsWmVuaXdJQXd0aXhabzNuaVNmY0R6MlVmdm95ZHJzbHY5OTBzQkNLTjdQMFN0a3ZaNExGbU5yY1BNODJFd1lCU0RVMWptdXUwU3VuajVTVmVSNTVwQ0MrelZQOFJCSWlOelNZblZDRjNXNVNXWmt5Q296aDRtTFhqaDJlcDU2UzYrdU5mQitrNm1wa29LZGpGb3doR2wyUVpsYXVOTjVaZjMrbXpmYkdScnVXdWNKRlJlNmRPM0ZoWWZUdHQxRTBTaFl2MXUxeG5ZY2tTWDcvNStsTUFFQ0VPTmF0YyszWTRmalNsNHpmLzBwK1AvWjR3T3k4RWdBYUNFQTB5bldpMFpWeUpWaHFXeHNiR2pMM2tTVUFrS1ZMNWZwNnZYSW1ZTGZiZGYvOTJPT0ovdTF2MHVyVnhOSnFacExmajkzdVdjdUdNMGJLeWdydXVNTjUyMjE0MGFLMFI4OUZTa3FrcFVzMXMrc01ZRXg3ZTJGcTZqOHhXQkFLWmJUd0ZZQmNYMCtXTHRVclp3NTJPbDNidHBHaUlsSmFhcXJabmtDV0xjT0xGa0Y4d2pzQWNqamsrbnJuMTcvdVdMWEtYRGdRUWdoaGo0ZjQvY2o4VXZVd1BzNHVYemJZQTJlWG5BaVdkdUdDOWZWcUFiRFhLemMwV0F4bGVySmNjTnR0bHNlZDRzSkNxYW9xdmpnQVdiclUrWld2Rk54eWk1VmVnemhDSkw4ZnliSzUxNU9ZRzMzZGRYcEY3WlFEd1dKc2Vwc0phOGtBa0ZhdWxGYXUxQ3VYQVdzdkRDRmNVQ0JWVmFrdExmTEdqYTRkT3pKL2tkUFhWck8zT0pUUzdtNmthVmxZS3lBaGUzOHBGWHI1c3VsdEpwSTVIUEttVGJyak9SZUtvNjdPVTFJaWI5bGl5eXNrUzVlUzRtSnFkcVFheGpRK056cUw2NnhhL0M3YVNHdHR0YkxOUkJ3QXVlb3FlNXZ0OW5Lc1hsMXcrKzIycEFvaFJBb0xwZXBxMDcxWkdMUFIwU3p2cmJmQXdZSmdVRzFwc1Q1bUNFQmV2ejRYVmtaTXlkb1hKaFZaSm42LzZVdHovR2wwZkIyYmJESDVFdTJtblQ5dmZiM2ErSGpPeGthTGgrY25xYWJHeXFBL1ZhVTlQYWFQeXNDQ3RyRXkzR1lDd0hITk5WSk5qVjQ1UTBaSFI4OTFuQU1HeGNYRnBhV2xSVVZGSHB1dVgvYVNLaXB3VVpIcGtWNFkwKzV1VUJTN0xzcTZGakpZdEs5UCsvaGo2L1dOd3lFM050bzEyYmVqbytOWHYvcFZKQktSWmRuajhWUlhWMitvMzNEVFRUZGRmZlhWZW9kbUZmYjVwT1hMV1grL3VjOE40eXh2aUxLUXdWSmJXOW5vcUxrUEtDSCtZRmh2R3BaeGxGSkZVUlJGUVFpTlQ0ejM5ZlVkUDM3OHdKc0h2dm1OYjk1enp6M083SFpicDRGZExzbnZWMXRhOUFyT2x2VU5VU3hkZyt3QWs1TnFTNHU1dnI1a0dEczJiTEIzTHdtTWNmeC9DU2FTSkNHRXVydTcvL0IvZjNqMXRWZVo1ZGZKQWFtcVF1YURIdDhRUmErVWJSWXNXTnE1Y3l3UXNGaGRHWnVHWlFvQVVFb1pZNURVd2lXRUtJcnl5aXV2bkRYL0lHV09XQ3cyTmo0Mk5EVFUwOU1UREFiMWlxY2oxZFFRSXlPOXJoRGZFRVd2bEQwVzZGS29xaGx0TTJGd0dwWVpmci8vL3Z2dVA5ZHg3dXpaczRxaTRKbklFa0tHaG9iZWYvLzlOV3ZXRUV1dmRtQmc0UERodzIzdGJUMkJub25KQ1lmRDhjTWYvdkNHNjIvUU95NGxVbHhNbGk0MTNZckk3b1lvQ3hNczJ0dWIwVFlUaHFkaEdWZGRYZjNrazA5T1RVMGRQSGp3NlQ4K0hRd0djZExMYTJ0dkN3YURpMHlPUjBBSUhmM282RFBQUE5QUjBhRnBXdndYZWp3ZVRiVTZTaFloTkRQb1QvdmtFNzJDYzJWelF4UXJYOEhNcVMwdDFyZVppSytlWUd3YWxpa1lZNS9QOTdXdmZXM3JmMjFOdmlCaWpBY0dCa1pIUjlNY082OVBQLzEwOSs3ZFo4NmNBUUJKa3VJVkhnQ0ErYXZZTElSSTFkV3BCakdubE4wTlVSWWdXR3g4WEQxNU1wTm11L0ZwV0JZNEhJNE5HellVekI0bkU0MUdoMGVHVXgweUx3QjQ5OTEzQTRHQU5ETTZGQUJLaWt2V3JsMjd1SFJ4K21OMUViOGZlenltbTFsWjNCQmxBUzZGOU94WjF0ZG5zYm95T1EzTEdwL1BKOHV5cXFxSnF5RmpMQnFKcGo5cWptQXcySHJxOCtsZkFMQjI3ZG9udnYvRXlwVXJNKzk2bGNyTFNXa3BuWncwOXpIT2JJaGlkcGkxQmRtdXNTQVdpNTA0WVhwK1hJTDVhVmdMWldKaVltQmdJQjVOQUhDNVhBODg4RUI5ZmIzUDU1TU1qSEJQRHhjV1Nta0cxS2N5c3lHS1hqa2JaRHRZTEJEUVB2bkVZcW9RUWdVRnlWT0VjOWxVYUVwTnV1aDR2ZDdhVmZadFErSndTRFUxUnFaZ3pKTEZKV2l5SFN5MXBjWDZlclh4M25ZT3pYWXVadGNtRXBGY3R0N0d4Z2Y5bWE2MEVodWljSmJWWUxHeE1iVzExZlJua1JCZnI3YWtSSzljTGdKazlWMm5RQ29xckF6Y205a1FSYTljcHJJYUxPMzBhZHJYWjdsVGxCUVhXNW1HOVFVVmZ4cHQrbHM2c3lHS1hybE1XVHJIbGtBME9yM05oRFVBMHBvMTFxWmhtZVZ3T0xDMWkzVnE5djlDcDFPeWNCTXpzeUdLWHJsTVpTOVl0S3RMczd3N0hBQjJ1UW9hRzdQVGJDOHFLcEpuZHo4eXhsU3ozVCt6MzZpbWFXRzdMMENTMzI5bHRtQjhReFRPc2hXcytIcTFadnRkRWdCSVphVzBabzFlT1h2RSs3RVMveGRqSEkxRysvcjYwaHh5SmFyUjVCNzJjRGpjMmRXWnByd0Z4TzgzdE83SUZlSWJvdWlWeWtpV2dzVkdSclFNbSsyTmpWbm8xb3NyTGk1ZXRteFpjaXdZWThkUEhKOHdzMnhMLzBCL1pHWW9BY1pZMHpURjduTkpTa3BJUllYcFQzVm1ReFM5Y2huSlVyQzBNMmZvWjU5WmI3YVhsTWdiTnVpVnM0M1g2MTIvYm4zeVR3Z2g3ZTN0TC96NWhhR2hJU1BYUkVWUlB2end3MGdra3VnZzlYcTkvaXJ6VGFLMHBwZWdNUzhMRzZKWU90TW1RU1NpSGo5dS9SSFZmTnRNY0lVeHZ2WFdXeXVXVlNTUDcxTlY5YTkvL2V1UGZ2eWozLy8rOTFPcDE1a05Cb1BIamgzYnZYdjNvVU9IRWsrZEVVSzNiTDNsR2pzV3c1a0Y0K201MGFaa1pVT1ViQVNMZG5acTU4OWJibDJsMm1hQ3E5cmEydTk5NzN0bFpXV0pDeUxHbUZMYTBkSHhyMFAvU3RNTVAvUEptVi8renkvZjJQOUdORHI5YkxHd3NIRDdQZHNmZWVRUkh1T2JKV3RQby9sdmlNSS9XSW4xYXEwR1M2cXVUclhOQkQ4WTQ3dnV1dXZIUC9weFpXWGxuREdsaEpBMGZRZWFPdDJXU2d4MDNycDE2NU5QUHJtRXp5Z29zbVFKV2J6WWRMQm1Oa1RSSzJjZDkyQ3g0V0d0clUydlZHcnhoYThzZERGbmJHaG82RVRUaWJHeHNlUWZ4a09XcGhzZEFJQjlQdUlLQUk0ZVBmcm1XMjlxbHBmQVRBdDdQTlpXK3VPOUlRcjNZR250N1hSZ3dIcXp2YlRVa2NWbWU0S2lLSHYyN25uOTlkZERvVkR5NEJsQ2lOdnRKampsMnlrcks5dlV1R254NHNXSmJJMk5qZTNidCsvamp6OU9kVWhHSEE2cHVqb0huMGJ6YmJqWXM4MUVCdXZWV25iOCtQSDMzbnNQSmZXWUE4REtsU3Z2dnZ2dTJ0cmFOR09VVjYxYTlmUC8vdm5wMDZkLys3dmZkbmQzeHkrZEl5TWpIeDc5c0w2KzN2YitkNVJZZ2lZY050ZlkwRFFhQ0NCS1RZZlNHRXZuMnpCNjRZTDI2YWZtM25CQ1lwdUo3RGJiRVVLcXFuN3d3UWZKZFJVQVZDNnYvT2xQZnZyUXR4OXEyTmdncDc0Umt5VEo0L0ZzM3J6NXpqdnZUSjU4Y2Y3OCtSQ2ZOZzJwcU1BV2V2aG1scURSSzJjUnoyRFpzbDV0clgxam1BeWJuSnc4MTNFdXVYWmhqTjE0MDQzWG1WbTdiSFh0YXJmYm5iZ2dEZzRPSnU0VDdZVzlYb3VEL29hRzJMQzU4ZGJHY1F3V0d4eFVNMW40S3Q1czkzcjF5dGx2ZEd4MFltSWlPVmhPcC9QYWE2OU5jOGlWaW91TEV3UG5NY2FSU0lReXE0dnFwRFg5Tk5yczV6eXpJWXBlT1lzNEJrdHRiMmVEZzZiZmNGeDhkN2dGV3ZocWNuSXkrU1lPQUdSWkx2S1p1elBGWk80Yng4alNSMkhBOU5Ob3M1VVd6dzFSZUFVTFFpSDF4SWtNdDVtd2ZiMWFnOExoTUwxaXlTN1Q3VzZUWnprVFVsV1ZsYVhJTWFaZFhaeWFXYnlDcFYyNFFDOWRzbHhkMmJMTmhHWDhxaFpPOEtKRlpOa3kwelVXeHF5L245T0dLSHlDUmVuMGVyVldneVd0V0dITE5oTzVnMnRZc2NkalpRbkorTk5vUHMwc0xzR2lBd09acmxlN2ViT1Z1ajJIVVVhak1TNTNoWEdTMzI5MHM3RUVuaHVpY0FtVzF0YVcwWHExNWVYeStsbWpWdktSeCtOeEpQWEFUVTFObmU4NG42WjhocXcvalE0RWdFTS9pUDNCZ3FtcDZXMG1ySW12VjF0ZXJsY3UxeFVYRnljR1IyQ01GVVY1L1crdlg3cDBTZE8wVE5kdW1BOVpzb1FzV1dJNldETWJvdWlWTTgzK1lHa2RIYlN6MDNKMXhYR2JDY1BtWGJmRDdGMmh6K2VycTZ0TC9CNUNTR3RyNjg5KzlyUGYvTzl2TGw2Nm1QNVlDeXcvallhSkNkYmZyMWZLTkx2UFgySzlXcE9uWVZvV3Rwa3dvSCtnUHhxTkppZko0WEQ0VEc1VlFnaTUvZmJieTh2TGswY0xkZ2U2MzNubm5jOHVjeGhXRU45c3pPeDlOTVlRRHZPWVcyRnpzR2gvdjNibWpNVlVJWVJrdWVENjY3TzJzdSs4UmtaSGpodytNcWNmeStQeGxKbGZsbkw5dXZXUFBmYllraVZMa3RjS1REK2NLeE1XbTFtSkRWRnNaZmo1TG1Oc2NGQm5hQmdoc1k4K1lpTWpGb01GZ0wxZTdQUFJ6czVaYzhBbGlTeGJabVdla3hteFdHeDRlTGl6cy9NZi8vakh5ZGFUeWMrUEdXTit2OS9DcW1zWTQyMTNiNnVzckR6NHo0T24yazZOalkzRllqR1h5NVg1b2lEekloVVZuMjgyWmh5ZkRWR01CZ3RVTmZMYWEycHJxMDdySnhJeC9ZMUp3QmltcHNKNzlzektKUUQyK1FxZmVzcXU5ZHhUYVd0cisvVnZmajB5TWhJT2grY3NDU2xKMHViR3pZV1d1ajh3eHZYcjY2OWJlOTM0K1BqSXlNakk2QWdBMVBKNXNrNjhYc252TjcxRVZIeERsT0ZoYVVHQ2hRQWdISWJKU1oxZ21YcExWNklVNWl6OEdvK3A1WHRNd3lMUnlNandpQkpSNXFTS1VycG16WnF0VzdlbU90QUlTWkpLUzB0TDdWMHNEZ0NtcGlCNWlnckdaUEhpMUFla2dER0V3N0dqUngwVEUra1dDd0VnSlNYU2loVUc3NnNNQndzaGhQSDBmMXhkK2Z0NS8wV0VFRUlZNFRtUGpRR0FNVlpWVmJWcjE2N2xXWndqWkJERVlzcUxMMnB0YlorZmFZeEJVUXllK0Zrb2piN3pUdXk5OTlKZGJSaHpORFI0SG4vY1lKdkVUTEMrMEFBQll5eHhCMWRRVUZCU1V0S3dzZUcrKys1Ym01c0xKd0ZBTU1oR1J1WW15ZHIzVU5NZy9mdzh4bEFzWnJ5ZEk0STF6ZWYxYmFqZklFbVN5KzFhV3I2MHVxWjZkZTFxdjk5ZllQWTVTVGJaZXcxSi8zdE0vaUVSckdsMWRYVy8rTVV2SkVtU0pDbW53NVFuUkxDbXliS2NaaVM3WUpiNWhwNGdHQ0NDSlhBaGdpVndJWUlsY0NHQ0pYQWhnaVZ3SVlJbGNDR0NKWEFoZ2lWd0lZSWxjQ0dDSlhCaDVsa2hZMW5ZTldvdWdBWDRvL2tDWVBxL0xERDVod3dIUzVLaytEbytGc2FSWlFJQXU5M1k3ZFlyOTU4SFkreng0S0tpTEowUnhyREhZM3prRERZK2VSSlVOUXREaE9lQk1aYmxMSDE4ZWNUSTlCWmI0Y0pDVWw1dThFU1lDSllnR0djb2ZZSmdsZ2lXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFNQeTJtdDZaUVRCTkVma2xWZjB5Z2lDYVE0a1NYcGxCTUUwMGNZU3VCREJFcmdRd1JLNEVNRVN1QkRCRXJnUXdSSzRFTUVTdUJEQkVyZ1F3Uks0RU1FU3VQaC81U1NoVG4yV3hsOEFBQUFsZEVWWWRHUmhkR1U2WTNKbFlYUmxBREl3TVRndE1ETXRNREZVTVRNNk16UTZOVFVyTURBNk1EQmtFQVQzQUFBQUpYUkZXSFJrWVhSbE9tMXZaR2xtZVFBeU1ERTRMVEF6TFRBeFZERXpPak0wT2pVMUt6QXdPakF3RlUyOFN3QUFBQUJKUlU1RXJrSmdnZz09Iiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9LHsiaWQiOiJsb2MiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfSx7ImlkIjoidHhBdXRoU2ltcGxlIiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0IiwidHhBdXRoU2ltcGxlIiwibG9jIl0sImFhZ3VpZCI6IjExMDVlNGVkYWYxZDAyZmZmZmZmZmZmZmZmZmZmZmZmIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNi0wOSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjAwNTEyMDAxIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA2LTA5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNi0wOSJ9LHsiYWFndWlkIjoiMDg5ODcwNTgtY2FkYy00YjgxLWI2ZTEtMzBkZTUwZGNiZTk2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIwODk4NzA1OC1jYWRjLTRiODEtYjZlMS0zMGRlNTBkY2JlOTYiLCJkZXNjcmlwdGlvbiI6IldpbmRvd3MgSGVsbG8gSGFyZHdhcmUgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsicnNhc3NhX3BrY3N2MTVfc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImF0dGNhIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImV5ZXByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwiaXNLZXlSZXN0cmljdGVkIjpmYWxzZSwibWF0Y2hlclByb3RlY3Rpb24iOlsic29mdHdhcmUiXSwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUY5VENDQTkyZ0F3SUJBZ0lRWGJZd1RneS9KNzlKdU1ocFVCNWR5ekFOQmdrcWhraUc5dzBCQVFzRkFEQ0JqREVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENsZGhjMmhwYm1kMGIyNHhFREFPQmdOVkJBY1RCMUpsWkcxdmJtUXhIakFjQmdOVkJBb1RGVTFwWTNKdmMyOW1kQ0JEYjNKd2IzSmhkR2x2YmpFMk1EUUdBMVVFQXhNdFRXbGpjbTl6YjJaMElGUlFUU0JTYjI5MElFTmxjblJwWm1sallYUmxJRUYxZEdodmNtbDBlU0F5TURFME1CNFhEVEUwTVRJeE1ESXhNekV4T1ZvWERUTTVNVEl4TURJeE16a3lPRm93Z1l3eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BYWVhOb2FXNW5kRzl1TVJBd0RnWURWUVFIRXdkU1pXUnRiMjVrTVI0d0hBWURWUVFLRXhWTmFXTnliM052Wm5RZ1EyOXljRzl5WVhScGIyNHhOakEwQmdOVkJBTVRMVTFwWTNKdmMyOW1kQ0JVVUUwZ1VtOXZkQ0JEWlhKMGFXWnBZMkYwWlNCQmRYUm9iM0pwZEhrZ01qQXhORENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFKK24rYm5LdC9KSElSQy9vSS94Z2tnc1lkUHpQMGdwdmR1REEyR2JSdHRoK0w0V1V5b1pLR0J3N3V6NWJqalA4QXFsNFlFeHlqUjNFWlE0THFuWkNoTXBvQ29mYmVEUjRNakNFMVRHd1dnaEdwUzBtTTNHdFdEOVhpTUU0ckUySzBWVzNwZE4wQ0x6a1lidlpiczJ3UVRGZkU2MnlOUWlEanlIRldBWjRCUUg0ZVdhOHdyRE1VeElBbmVVQ3BVNnpDd00rbDZRaDRvaFgwNjNCSHpYbFRTVGMxZkRzaVBhS3VNTWpXaks5dnA1VUhGUGErZE1BV3I2T2xqUVpQRklnM2FaNGNVZnpTOXkrbjc3SHMxTlhQQm42RTREYjY3OXo0RFRoSVh5b0tlWlR2MWFhV09XbC9leHNETEd0Mm1UTVR5eWtWVjh1RDFlUmpZcmlGcG1vUkR3SktBRU1PZmFVUmFyenA3aGthOVRPRWxHeUQyZ09WNEZzY3IyTXhBWUN5d0xtT0x6QTRWRFNZTHVLQWhQU3A3eWF3RVQzMEF2WTFIUmZNd0J4ZXRTcVdQMit5WlJOWUpsSHBvcjVRVHVSRGd6UitaZWorYVd4NnJXTll4NDNrTHRob3plVkozUUNzRDVpRUkvT1psbVduNVdZZjdPOExCLzFBN3Njcll2NDRGRDhjazNaK2h4WHBra2xBc2pKTXNIWmE5bUJxaCtWUjFBaWNYNHVaRzhtMTZ4NjVaVTJ1VXBCYTNybjhDVE5tdzE3WkhPaXVTV0p0UzkrUHJaVkE4bGpnZjRRZ0ExZzZOUE9FaUxHMmZuOEdtK3I1QWsrOXRxdjcyS0RkMkZQQko3WHg0c3RZai9Xak5QdEVVaFc0cmNMSzNrdExmY3k2ZWE3Um9jdzV5NUFnTUJBQUdqVVRCUE1Bc0dBMVVkRHdRRUF3SUJoakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI2akFyT0wwaGlGK0tVMGE1VndWTHNjWFNrVmpBUUJna3JCZ0VFQVlJM0ZRRUVBd0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVc0aW9vMStKOVZXQzBVbnRTQlhjWFJtMWVQVFZhbXRzeFZ5L0dwUDRFbUpkM1ViNTNKek5CZllkZ2ZVTDUxQ3BwUzNaWTZCb2FnQitEcW9BMkdiU0wrN3NGR0hCbDVrYTZGTmVscndzSDZWVnc0eFYvOGtsSWptcU95ZmF0UFlzejBzVWRaZXYrcmVlaUdwS1ZvWHJLNkJEblVVMjcvbWdQdGVtNVlLV3ZIQi9zb29mVXJMS3paVjNXZkdkeDl6QnI4VjB4VzZ2TzNDS2Fxa3FVOXk2RXNRdzM0bjdlSkNiRVZWUThWZEZkOWlWMXBtWHdhQkFmQndrdmlQVEtFUDlDbSt6YkZJT0xyM1YzQ0w5aEpqK2drVFV1WFdsSko2d1ZYRUc1aTRySWJMQVY1OVVyVzRMb25QK3NlcXZXTUpZVUZ4dS9uaUYwUjNmU0dNK05VMTFEdEJWa2hSWnQxdTBrRmhacWpEejFkV3lmVC9ON0hrZTNXc0RxVUZzQmkrOFNFdzkwcld4MmFVa0x2S284M29VNE14NG5hKzJJM2w5RjJhMlZOR2s0SzdsM2EwMGc1MW1pUGlxMERhMGpxdzMwUGFMbHVUTVRHWTUrUm5aVmg1MEpENm5rK0VhM3dSa1U4YWlZRm5wSXhmS0JaNzJ3aG1ZWWEvZWdqOUlLZXFwUjB2dUxlYmJVMGZKQmY4ODBLMWpXRDNaNVNGeUpYbzA1N012ME9QdzVtdHR5dEU1ODVaSXk1SnNhUlhsc09vV0dSWEUza1VUL01LUjFVb0FnUjU0YzhCc2grOURxMndxSUs5bVJuMTV6dkJEZXlIRzYrY3p1ckxvcHppT1VlV29reFpOMXN5ckVkS2xoRm9QWWF2bTZ0K1B6SWNwZHhad0hBK1YzakxKUGZJPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFZ0FBQUJJQ0FZQUFBQlY3Yk5IQUFBQ2tVbEVRVlI0MnV5YWkzR0RNQXlHUXllZ0d6QUNuYUNNa0JIb0Joa2huU0FqMEEyU0RhQVQwRTZRYkVBM2NPWFc2WEVwQnRuSW1Ndjl1dE9sbHhqRi9xS0hMVGRSU20wZ2Rua0FBZ0FDSUFBQ0lBQUNJQUFDSUFnQUFSQUFBUkFBQVJBQUFSQkVBRkNTSklOS2twTHVTVHRTWmJRejc2VzI1emhLa3BGV1BidGF6NlE3NXZQdW9sdXVQbXF4bFpLMnlpNzZzOVJ6bmpscE4ySzdDckZXYVVBSE5TMEhUMEF0dzNZcERTanhiZG9QdWF6aUczdWs1NzljdklkZVdzYlFEN0w3TkFZb1dwS21MeThjaHVlTzVyZUI3S0tLclFuUUpkRFluOUFKWkhjNVFCVDdlbklOWTJoanhycUl0c3ZKV1NkeEZ4S3VZbE9sV0ptRTZ6UFBjc0p1TjdXRmlGN21lNURPQXdzNE95WnlHNlRPc3IvS1F6aURhSm0vbWN5MlYxVjArVDBKZVh4cXFscldDOW1HR3kzTzZ3d0ZhSTBTZFIrRU1nOUFFQUFDSUFCeXFWaVpiKy9wcmdGZE42cWIzMDZqM2xUV3MwQko3NlFqdzBrdE8rM2FkNjBQUWhNcmZNOVl3cUs3bFVQZTRqKy9PUjQwY0RhcUplSit4bzgwSnNXaWgxV1RCQWNiOHlzS3JiK1Rmb3dRS3kzdjU1d2JCa2s0OUZKYlF1c3FyNHNuYWRMOWhFdFhDM25PMUcxSEc2VWZ4SWo1b0RuSmxIUE9WVkFlcldHbXZZUXh3YzcwaGlUaDdCaWR5My8zWkZFNmlzeGY4ZXBOaFVDbDRuNWZ0WXFXS3pNUDNJSXF1YUZucXVYTzBzWjF5bi9SV3E2OVN1SzZHZFBYT1JmU3o0SFBuazFiTlhPMCtVWnplNUhxS0lvZE5Zd25IVlZjT1Vpdk5jU3R4ajRDR0ZZaFdBV2dYZ211RjRKemRNaG42d0RVbTFEcG1GeVZZN0l2UXFlVFJkb2QydjJGOGxObi9nY3BXK3JVc09pOW1BbUZ3bFNvM1B3OUpRM3ArOGJoZ25BTWtQTTYxM0J4T0JRcWMyRkVCNFNtUFFTQUFBaUFBQWlBQUFpQUFBaUFJQUFFUUFBRVFBQUVRUGNvM3dJTUFET1hnRmhPVGdodUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiIwODk4NzA1OGNhZGM0YjgxYjZlMTMwZGU1MGRjYmU5NiIsIm9wdGlvbnMiOnsicGxhdCI6dHJ1ZSwicmsiOnRydWUsInVwIjp0cnVlfSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMDAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MzIsInRyYW5zcG9ydHMiOlsiaW50ZXJuYWwiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjE5MDQyfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMDUiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IldpbmRvd3MgSGVsbG8gSGFyZHdhcmUgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNDE4MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMDUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA4LTA1In0seyJhYWd1aWQiOiJhNGU5ZmM2ZC00Y2JlLTQ3NTgtYjhiYS0zNzU5OGJiNWJiYWEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImE0ZTlmYzZkLTRjYmUtNDc1OC1iOGJhLTM3NTk4YmI1YmJhYSIsImRlc2NyaXB0aW9uIjoiU2VjdXJpdHkgS2V5IE5GQyBieSBZdWJpY28iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA3LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImE0ZTlmYzZkNGNiZTQ3NThiOGJhMzc1OThiYjViYmFhIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjg3MDd9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMy0yOCIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vcHJvZHVjdHMvIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI4MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0wMiIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMjAyMDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAyLTAyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMy0yOSJ9LHsiYWFndWlkIjoiMGFjZjMwMTEtYmM2MC1mMzc1LWZiNTMtNmYwNWY0MzE1NGUwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIwYWNmMzAxMS1iYzYwLWYzNzUtZmI1My02ZjA1ZjQzMTU0ZTAiLCJkZXNjcmlwdGlvbiI6Ik55bWkgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJzakNDQVZtZ0F3SUJBZ0lJUjZsZ3drc2ZqeWd3Q2dZSUtvWkl6ajBFQXdJd0xURXJNQ2tHQTFVRUF3d2lUbmx0YVNCR1NVUlBJRUYwZEdWemRHRjBhVzl1SUZKdmIzUWdRMEVnUjI5c1pEQWVGdzB5TURBMk1qWXhOakl6TlRKYUZ3MHpOVEEyTWpNeE5qSXpOVEphTUMweEt6QXBCZ05WQkFNTUlrNTViV2tnUmtsRVR5QkJkSFJsYzNSaGRHbHZiaUJTYjI5MElFTkJJRWR2YkdRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRWlZ5ellMc3Zidm1nNGJtUk55WmpyVlh6enpVZlVlWWlXWVppUjN2QUNhdlg0ai9WeDNqWS93dm1kU2M1YmFDbVZRaCtyTjBRKysrTEd3VWoxa0ZpY28yTXdZVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjhHQTFVZEl3UVlNQmFBRkhtcThLQzU3OGpWNDNDSnhUeHhCS1libzFpTU1CMEdBMVVkRGdRV0JCUjVxdkNndWUvSTFlTndpY1U4Y1FTbUc2TllqREFPQmdOVkhROEJBZjhFQkFNQ0FZWXdDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdLaDFIY2dMN294cGRXbm5jazl1Q1dGNkM2YjJ0c2JHUGpTSHUzMUc0OFdNQ0lIdUVzdFNIR2tNbEZUSDM2N3B0bWZDNndpeG1hQ2R3VDhDVi9panJPVE1JIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVBQUFBQkFDQU1BQUFDZHQ0SHNBQUFBQTNOQ1NWUUlDQWpiNFUvZ0FBQUFDWEJJV1hNQUFBTEZBQUFDeFFHSjFuL3ZBQUFBR1hSRldIUlRiMlowZDJGeVpRQjNkM2N1YVc1cmMyTmhjR1V1YjNKbm0rNDhHZ0FBQWpSUVRGUkZLYjdHS3I3R0s3L0dMTC9ITGIvSExzREhMOERJTU1ESU1jRElNY0hJTXNISU5NSEpOY0xKTnNMSk5zTEtOOExLT01QS09jUEtPc1BLTzhQTE84VExQTVRMUHNUTVA4WE1RTVhNUWNYTVFzYk5ROGJOUk1iTlJjYk5Sc2ZPUjhmT1NNZk9TY2pPUzhqUFRNblBUY25RVDhuUVVNclFVTXJSVWNyUlVzclJVOHZSVk12UlZjdlNWY3pTV2MzVFdzM1RXODNUWE03VVhjN1VYczdVWDg3VVlNL1ZZYy9WWXMvVlpORFdaZERXWnRIV1o5SFhhTkhYYWRIWGF0TFhhOUxZYk5MWWJkUFljTlRaY2RUWmN0VFpkZFhhZDliYmV0YmJlOWZjZk5mY2ZkZmNmOWpkZ05uZGdkbmRndG5laGRyZmh0cmZoOXZmaU52Zml0emdpOXpnak56Z2pkemhqdDNoajkzaGtkN2lrdDdpazk3aWxON2lsTi9qbGQvamw5L2ptT0RrbWVEa211RGttK0hrbk9IbG5lSGxvT0xtb2VMbW91UG1vK1BtcGVUbnB1VG5xZVhvcSticHJPYnByZWJwcnVicHIrZnFzT2Zxc2VmcXN1anFzK2pydGVucnR1bnN0K25zdU9uc3VlcnN1dXJ0dk92dHZldnR3T3p1d2V6dXhlM3d4dTd3eU83d3llL3h5dS94eSsveHpPL3h6ZkR5ei9EeTBQSHkwZkh6MHZIejAvSHowL0x6MVBMMDFmTDAxdlAwMS9QMDJQUDAyUFAxMmZUMTJ2VDEyL1QxM1BUMjNmWDIzL1gzNFBiMzRmYjM0dmIzNC9mNDVQZjQ1dmY0NS9qNTZQajU2Zmo1NnZuNTYvbjY3UG42N2ZuNjdmcjY3dnI3Ny9yNzhQcjc4ZnY3OHZ2Nzh2djg4L3Y4OVB6ODlmejg5dno5OS96OTkvMzkrUDM5K2YzOSt2MysrLzcrL1A3Ky9mNy8vdi8vLy8vL1dwbzRyQUFBQkNsSlJFRlVHQm1sd1kxL2xBTUF3UEhmZGx1YTJtV2tGblZIU2hFcXhJaGlVaXB2a1RvMFJHSlVXRjR5VWQ2Wjkycnp0cUpTbUJxMnBtZjMrK2M4eisxV2Q4L3VydHVuN3hmUEUxWnc2bUIzVjFmM3dWTldnS1VON00yMHpLd2xwM1ptUzJidmdLVmhDVU9keStxSm1iQ3NjOGdTY0l5K3RpWkcxRXhOWGJzZ05iV0dFVTF0ZnprR3hndytNWWxJYXMzcjN3NllNL0R0NjJ0U1JDWnRHalFHaTcwM2k5QzBSN3VOT2ZEb05FS3BQUmJEUWtNUEVacjE0aWxMT04xeEphR1ZBeGJDQWdmbkE1TmZEQ3dqMkRvSnVPYVFCZkNzQTlPQXBVZXM0UEJ0d1BRRG5vVm5kQ1Voc1NWclJkbG5FNUQ4M0ROdzFQY1hRY01leituOVNkQzQzMUdZZDdnWmtwOVpoYytTTU9PSWVUZ2lXQVFUUDdFcW4xOElpd05INElpTlVQdXVWZHBkQ3hsSFlNNVhDY2hZdFExUTIyVU9Sb0lGc0Npd2FzRkN1RzdZQ0VhMlFkMzNqa05QSFd3M2dxSFRNMkdENDdJZVpnV0dNUFFhVEQ3aHVKeE1Rb2NoREYwTEdZc2R2WFgycTFhU2dRV0dVSHVnN3BqRjdnTTZyT0JZSGZTb3FJL0JuY2JNQlJxUFdzR2RzRkZGblFPN2pFa1RXbUVGYjhGY0ZUMWVRK0tFTVdraTcxbmVpUVExeHhUZEJkY2JsNGE1a0JxMHZPdmhiVVVmaDNYR3BXRnZJMlFzYngwOHJtZ3JiRE11RGQzdFVOL2pxS0dqdlhrbnpka0c5eWc2SHo0eUxnM2R3WFd3S0d0TzcvSjZSdFcvYStSRG1LL29EUGpKdURSMCszVUN0aHY1WVFvRjFoajVFV1lvbW9UZmpFdEJqejRFRngwM2REdlFOQ1h2Nm4xR2prSlMwVHI0MjVqQkJqaWkvYzJ3VXYwblFjMWVZLzZCaEtJTjBHZGsrSjF0ZVMvZENzMVp0Uk5xUHRDZllacHhmVEJSMGFud2k1SE5GSHJCeUIxdzVaQTlrREx1RUZ5cWFCcjJHWG1FczJvZXpobzUxQUNiN0lHVWNkOUJXdEVsMEdua3hNYTFlZmMvdGQrODUyRENqejJRTXE0VGJsSDBBZGhzV2NFOHVLa2JVc1k5QXc4cTJnNnRsdGRWQ3hzZ1pWd3J0Q3Y2QlRRTlc5NGFxSU9VTWRsTDRFdEZnMGJZWjNsOVV3bWxqUGtPa29HaUxvZU1GZXdrbERZbUEzZXBxRy9BWmNPV2wxMEszR1N4N0V4NFMwVWRtQXg3cktCdk5yeGhzVDB3ZVZERjBGcFlaQ1gvdnZtcE1RdGhyU0VNOVNiZ0E4ZmxmVWowR3NMSXZURG50T01RWEEwcmpXQ2s5d0o0M25IWUFoTVBHc0djTnBqd2pWWGJQeEdlTmdkelRzMkdLL3F0MHNrMFhEVmtEbzdvYm9BbFExYmx2eGE0WUo4ak1HOEhzQ0t3Q3NFSzRGWHpjTlFHWVBtZzV6UjBENUJ4Rkk3S3JnSnUvc056K1AxR1lGWFdVWGhHY0QvUS9Ja1ZmZHdNckFvOEF3czhBU1FlK2R1eSt0Y2xnQ2N0Z0lVNkc0SG1WMDViMG44N3BnUEpkeXlFUlhwdklIUjVlNTlqL05sK0dhR0Z2UmJCWXNQYm13alYzOTN4cXdWK2ZlMnVla0lYdjVLMUdNYjFQVG1Gbk5TeTlTL3YzTDE3NTh2cmw2WEltYkxwTCtOd3JQNnQ4eWhoM3RaK3g4S1M5cmN0cnFkQS9ZMXRCeXdKeXhubzZzaXNibTFwYVYyZDZlZ2FzQnc4VDNpZS9nZXZqNEgyRkRQMDJBQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjBhY2YzMDExYmM2MGYzNzVmYjUzNmYwNWY0MzE1NGUwIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsInVwIjpmYWxzZSwidXYiOnRydWUsImNyZWRNZ210Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjh9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMy0yMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiTnltaSBGSURPMiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTAyMTgwMDciLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDMtMjIifSx7ImFhZ3VpZCI6ImQ5MWM1Mjg4LTBlZjAtNDliNy1iOGFlLTIxY2EwYWE2YjNmMyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZDkxYzUyODgtMGVmMC00OWI3LWI4YWUtMjFjYTBhYTZiM2YzIiwiZGVzY3JpcHRpb24iOiJLRVktSUQgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJ2akNDQVdPZ0F3SUJBZ0lSQUxHcG1XWUlaeFdybzRmTFBVRXMvZ0l3Q2dZSUtvWkl6ajBFQXdJd1BURUxNQWtHQTFVRUJoTUNSMEl4RnpBVkJnTlZCQW9NRGtSdmRDQlBjbWxuYVc0Z1RIUmtNUlV3RXdZRFZRUUREQXhHU1VSUElGSnZiM1FnUTBFd0lCY05NVGt4TURFM01EQXdNREF3V2hnUE1qQTBPVEV3TVRZeU16VTVOVGxhTUQweEN6QUpCZ05WQkFZVEFrZENNUmN3RlFZRFZRUUtEQTVFYjNRZ1QzSnBaMmx1SUV4MFpERVZNQk1HQTFVRUF3d01Sa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVHRpeEpFZXN5SWk5bTl1TUxnYW1CMlRHZTQvWnc2M1hYeVhSRFE0Q0k5dWV4TGxrY1dBK1IrU1A5Si81b25IS21PS0h4c0VTbEdqNDdhdGhMY05lSDZOQ01FQXdIUVlEVlIwT0JCWUVGTHNKdjBiWTlydVBDMFY3T2Z3UGtPSXcwNVpPTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUURuWVJnbUdBK0ZTeEtGTlVPeVA4THYxZmFBcmlJNlp3b3FlR0dvdWJ2NEt3SWhBTk1xNlVUaDBDekpENlRVeEZOZnkvOGhnY0NhT3U1c3dGTmIrM3h0SnZYSyJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFEb0FBQUFTQ0FZQUFBQUtSTTF6QUFBRUdXbERRMUJyUTBkRGIyeHZjbE53WVdObFIyVnVaWEpwWTFKSFFnQUFPSTJOVlYxb0hGVVVQcnR6WnlNa3psTnNOSVYwcUQ4TkpRMlRWalNodExwLzNkMDJicFpKTnRvaTZHVDI3czZZeWM0NE03djlvVTlGVUh3eDZwc1V4TCszZ0NBbzlRL2JQclF2bFFvbDJ0UWdLRDYwK0lOUTZJdW02NWs3TTVscHVySGVaZTU4ODUzdm5udnV1V2Z2QmVpNXFsaVdrUlFCRnBxdUxSY3k0bk9IajRnOUs1Q0VoNkFYQnFGWFVSMHJYYWxNQWpaUEMzZTFXOTlEd250ZjJkWGQvcCt0dDBZZEZTQnhIMkt6NXFnTGlJOEI4S2RWeTNZQmV2cVJIei9xV2g3Mll1aTNNVURFTDNxNDRXUFh3M00rZm8xcFp1UXM0dE9JQlZWVGFvaVhFSS9NeGZoR0RQc3hzTlpmb0UxcTY2cm81YUppbTNYZG9MRnc3MkgrbjIzQmFJWHpiY09uejVtZlBvVHZZVno3S3pVbDUrRlJ4RXVxa3A5Ry9BamlhMjE5dGh6ZzI1YWJrUkUvQnBEYzNwcXZwaEh2UkZ5czJ3ZXF2cCtrcmJXS0lYN25oRGJ6TE9JdGlNODM1OHBUd2RpcnFwUEZuTUYyeExjMVd2THlPd1RBaWJwYm12SEhjdnR0VTU3eTUrWHFOWnJMZTNsRS9QcThlVWoyZlhLZk9lM3BmT2p6aEpZdEIveWxsNVNERmNTRGlIK2hSa0gyNStMK3NkeEtFQU1aYWhybFNYOHVrcU1PV3kvalhXMm02TTlMREJjMzFCOUxGdXY2Z1ZLZy8wU3ppM0tBcjFrR3ExR01qVS9hTGJucTYvbFJ4YzRYZko5OGhUYXJnWCsrRGJNSkJTaVlNSWU5Q2sxWUF4RmtLRUFHM3hiWWFLbUREZ1l5RkswVUdZcGZvV1lYRytmQVBQSTZ0Sm5Od2I3Q2xQN0l5RitEK2JqT3RDcGtoejZDRnJJYS9JNnNGdE5sOGF1RlhHTVRQMzRzTndJL0poa2dFdG1EejE0eVNmYVJjVElCSW5tS1BFMzJreHl5RTJUdit0aEtiRVZlUERmVy9ieU1NMUttbTBYZE9iUzdvR0QvTXlwTVhGUFhyQ3dPdG9Zanl5bjdCVjI5L01aZnNWenBMRGRSdHVJWm5icFh6dmxmK2V2OE12WXIvR3FrNEgva1YvRzNjc2Rhekx1eVRNUHNiRmh6ZDFVYWJRYmpGdkRSbWNXSnhSM3pjZkhrVnc5R2ZwYkptZWV2OUYwOFdXOHVEa2FzbHdYNmF2bFdHVTZOUkt6MGcvU0h0Q3k5SjMwby9jYTl6WDNLZmMxOXpuM0JYUUtSTzh1ZDQ3N2hMbkFmYzEvRzltcnpHbHJmZXhaNUdMZG42WlpyckVvaEkyd1ZIaFp5d2piaFVXRXk4aWNNQ0dOQ1VkaUJscTNyK3hhZkw1NDlIUTVqSCthbisxeStMbFlCaWZ1eEF2Uk4vbFZWVk9sd2xDa2RWbTlOT0w1QkU0d2tRMlNNbERaVTk3aFg4NkVpbFUvbFVta1FVenRURTZteDFFRVBoN09tZHFCdEF2djhIZFdwYnJKUzZ0SmozbjBDV2RNNmJ1c056UlYzUzlLVFlocXZOaXFXbXVyb2lLZ1loc2hNam1oVGg5cHRXaHNGNzk3MGovU2JNcnNQRTFzdVI1ejdETUMrUC9Icyt5N2lqclFBbGh5QWdjY2piaGpQeWdmZUJUanpoTnF5MjhFZGtVaDhDK0RVOSt6MnYvb3llSDc5MU9uY3hIT3M1eTJBdFRjN25iL2Y3M1RXUGtEL3F3Qm5qWDhCb0o5OFZRTmNDKzhBQUFBNFpWaEpaazFOQUNvQUFBQUlBQUdIYVFBRUFBQUFBUUFBQUJvQUFBQUFBQUtnQWdBRUFBQUFBUUFBQURxZ0F3QUVBQUFBQVFBQUFCSUFBQUFBY2RMdEN3QUFBemhKUkVGVVdBbnRWMmxJVkZFVVBtL0djUm9iUjhuNjBZOFVsU0RiU01rV1dzU1NJQXpNTVNsSkVBMkxiREUzYkJFS2FzaVNqUG1qaUxSUVpoaU41bzlNSWF2SklLSEJDVXVaakJTcGZ0Z2toWlBrTWpQMkZ1OTU3OXE4eVVRaHNRdVArMzNuZlBlY2QrNjU5ekhEakxFRDVzQlF6SUVhK1JMblRLRSswbzVXdEQrQTRvY0czcVRWTFlJM1J4clFIWG94R25IVXNxMWdTcndDVWhzNng0RS91OTR4WUJjWU13WTlKeTBvQ1N1T0JuSmh0TG9nTms4aitxUkFHci9uMUN2ZWxWeVhEeGFiR1dXTVFna01JOUQzQlM5QlFRZ3FCRUIxMUEwdWNMdWM0ODhvU3BOcWM5RU80T2FMNUp5aWxxd1I1M1oyazlEdmRFR2J2WXVQVjkvOUhGeE9VU2RYNU1UNC9HSXU1NWhiak11K3EydDBHSndqd2hOcWlJTFkyK2xFU3MxVW9aUm5uRmo2YkdEcGZJb3VhNjY0bTJpVUFSbmJENk1uL1g0ZWo0OVhaNk10YThjSnhOTUZ1bnRmUTFLZGtFc2FrenE2VWdmQlNaVXBCSUorVXlvRXFyWElwYUMzeUNxbFBENjc4U0JjYnk3bjhmZitUMkMxdjBPTjJpOEFDdGVsSVo4S2tPWXNNQnZoWHN0TlBveWw0d2xBSWgzUmEwZTVJMHVHV3FPRnE3Ry83eFR4eTgxRkNlZlF0YnRpSCtLMlk0OFFUd2NvaWNrR2hWTHNXNitqandvcmVpZ3p3TkNRZ3pxeWIzUFlYZkl5UWk1RW9sZXBVa04zWVN2UE0xY2x3S1hHRWhnZEhrUi9XTWdhMEtvMFVHMXJnZzc3QjdSeklEaGdNUnhhUGFFZGxFS2UrTTBQaEI4RFgzbEJSdjFwYUU2OWhtTFpRcmtMVG9hUHJ3WjhGU3BDLzNxMjVac2gzTEFXMTVtU2pUdzJkVFpSbThrWlE1YXNtSEtobU1BRGtEMjZXdDFDVUtxRTRwd2pQMEhhTVE5eGdMdHo1TkZvL0NtSkQ2T2srSUo1T29wUEY1SCt5Rk96cDBvNlpEdktpUzdyaXlHdlJyeVhaMXJLd0xBbFM3b2VjVmZ1TThTVEJTWjlLWUIrc21ydk9xTzFCZ1lkL1NocTJGdUdtQU5lQzkyemRCc29Va29oNTY3d1Vhb3lWMExLOHAyd01paVVDc0tSelRmMlU3WVg2WGNvUGhPRXkvbk44UVh2SmNtUkdYZVVRSnhsank1UjZNTmpJU1p5RjZFUVgrNjVCUjgvZDRMMHdRVXpDTGg4NU9ORDBnU3pkN3hvd3dGQ2NmNWpvWnp5VnZ4NTltZVdLSTB3eG1HQWZ3R28xQnFJQ0Y4UHJUbVBvU1d0eXVNck1mLy9wbm5jbDlsckZNL2o3SzFoVW0vK0MxMHlLbjEwNlkxREFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiZDkxYzUyODgwZWYwNDliN2I4YWUyMWNhMGFhNmIzZjMiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjk2LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA3LTE1IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJLRVktSUQgRklETzLCriBTZWN1cml0eSBLZXkgd2l0aCBVMkYiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMDMxOTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA3LTE1In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNy0xNSJ9LHsiYWFndWlkIjoiNGM1MGZmMTAtMTA1Ny00ZmM2LWI4ZWQtNDNhNTI5NTMwYzNjIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI0YzUwZmYxMC0xMDU3LTRmYzYtYjhlZC00M2E1Mjk1MzBjM2MiLCJkZXNjcmlwdGlvbiI6IkltcHJvdmVJRCBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjQ1LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNiVENDQWhPZ0F3SUJBZ0lKQUtNOUZxazArWDkvTUFvR0NDcUdTTTQ5QkFNQ01JR1JNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVZtbHlaMmx1YVdFeEVEQU9CZ05WQkFjTUIwRnphR0oxY200eEdEQVdCZ05WQkFvTUQwbHRjSEp2ZG1WSlJDd2dTVzVqTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFZk1CMEdBMVVFQXd3V1NXMXdjbTkyWlVsRUlFWkpSRThnVW05dmRDQkRRVEFnRncweU1qRXlNREV3T1RJNU5UaGFHQTh5TURVeU1URXlNekE1TWprMU9Gb3dnWkV4Q3pBSkJnTlZCQVlUQWxWVE1SRXdEd1lEVlFRSURBaFdhWEpuYVc1cFlURVFNQTRHQTFVRUJ3d0hRWE5vWW5WeWJqRVlNQllHQTFVRUNnd1BTVzF3Y205MlpVbEVMQ0JKYm1NdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SOHdIUVlEVlFRRERCWkpiWEJ5YjNabFNVUWdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZlgwc0Z5a2l2Q0c5NVBpNWpXV2cwTXNhMHhvWHFHNVIrNlhvaGtQU09XcW1jSlcrQ2tDNERXT0FBRHpERFladWh4MHMxQi9VazJCb1ZpOW1SSXFhZ3FOUU1FNHdIUVlEVlIwT0JCWUVGTUpwS2gzWGNmUk5pWFZXZjZQbnVkWmkyTXMzTUI4R0ExVWRJd1FZTUJhQUZNSnBLaDNYY2ZSTmlYVldmNlBudWRaaTJNczNNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURTQUF3UlFJZ005MFlWMFRUMzlWN0JEeG5mRktKYmpVL0h2RW5Kc2tjRmdXVjkvdEtyZmtDSVFEZkNDVGZDendZUldKcFhydU44d1JmNERZMUVhNjRnampJOWo1bGxoSVB0dz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBdGhKUkVGVWVOcnNsdDlMazFFWXg3L3ZOdGUwdlhPazd5UzdxeVdCWXZuaklrdEdVMHZEQ3drdFY0S1hwdjN3Qi80QkJpSWEvUUMxd2prVlV4TnNVdXV1emQxazZpQkxDeElGemNEWE9UWndZOHIyc3IxcnA0dVhadW9nZ3J5SmZTOGVlTDZjNTN3NDUrRTVISW9RZ29PVUNBZXNHQ0FHaUFFQXlYNkxaZG4xOVhXR1lkUnE5VDhna04xcWEyMFZEbFZaY1pVUVlwdVpLUzB0SFRjYTl5d3o2SHVycTZzL3pzNlNQMmtYd0dJMkF6aktxSFE2M2Z0M2s0U1Fwb1lHQU1XRlJYdktMbW9MQUF3T0RQd2RvTGRIRDJCa2FPaDM4NDNKNUhLNTlwVFYxZHdFOEdwOGZQK09TNHRMNXJmbUg2R1FrTzcwb0x1emMyand1U29wMmRCck9DeW5rNUtPOVBYM1oyWmtNQ2twcXl2ZkdJWUJjTCs5dzJxZEtDb3FDZ1FDQUhpZUYyb2ZQM3hrTXIxVzBJcmF1bHB0UVlIUDd3TkY3ZTJCTmw4RElPMzRDUUFOZCt1N3U3b0FTRUFCcUt1cEpZUlU2YTREb0dYeHFhb1VwWndXQTlhSkNVSkk0UVV0Z0ZQcWt3blNRd0Q2OVByb1Z4UU1CdHZiMmlpS2V0RFJ3Zk44S0JUaU9PN1prNmNBK25vTkxNc0N5TW84emZuOUhNZmxuTWtDc0xTNE9EMDFEVUIzOVJvaHhPbDB5aE1TNGlpUjNXNlBiTHN6QjNGeGNiUkNRUWhSSkNaS0pCS3hXQ3lUeWVSeUdvQlVLdjB5L3htQVRsY3BpNCtYeVdRYWpRYUF6K2VibXB3RVVGNVJEa0NsVWhWcUMzZ1NucCtiaXo0SG5OOFB3Ty8zUjV4QWdNdk56azVta2tXVUNNRHE2bmZCZHpnMkJEQ3RVQUJ3T2wyL2ZJZEFpZzRJQm9PUktJam5lUVZOYjNtM2lpK1hpRUhwK3d6cEdlbHV0L3VsMFFnZ0VBaVVYU203ZGVmMnZaYVd0TFMwaFlXdkgrWSs1Wi9OeThuTmpmNVVTQ1NTU0l3NDRYRFk0ZGhRS3BYRHc4TmlpcXB2YkJ3ZGVWRjFvd29BdTdhV21uck0wS1BmM3Q2K1ZGTGMxTng4UHUvYzZOaVlTQ1NLUHNrZXQyZDVlZG5qOFVRY3I5ZHJYN2U3M1p0Q3lySnJWcXMxSEE0VFFwWlhWcnhlcitDN045MFdpOFZtcyswZkN5cjJxNGdCWW9EL0FQQnpBSTZWTnFHUVBVcW5BQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI0YzUwZmYxMDEwNTc0ZmM2YjhlZDQzYTUyOTUzMGMzYyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImVwIjpmYWxzZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMDI0LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMS0xNyIsInVybCI6Imh0dHBzOi8vd3d3LmltcHJvdmVpZC5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJJbXByb3ZlSUQgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMTE3MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDEtMTcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTA1LTE4In0seyJhYWd1aWQiOiJlZTA0MWJjZS0yNWU1LTRjZGItOGY4Ni04OTdmZDY0MTg0NjQiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImVlMDQxYmNlLTI1ZTUtNGNkYi04Zjg2LTg5N2ZkNjQxODQ2NCIsImRlc2NyaXB0aW9uIjoiRmVpdGlhbiBlUGFzcyBGSURPMi1ORkMgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCMkRDQ0FYNmdBd0lCQWdJUUdCVXJRYmREcm0yMEZabkRzWDJDQlRBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERURTRNRFF3TVRBd01EQXdNRm9ZRHpJd05EZ3dNek14TWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXNGWUVFaGlKdXFxbk1nUWpTaWl2QmpWN0RHQ1RmNFhCQkgvQjd1dlpzS3hYU2hGMEw4dURJU1dVdmNFeGl4UnM2Z0Izb2xkU3Jqb3g2TDhUOTROT3pxTkNNRUF3SFFZRFZSME9CQllFRkV1OWh5WVJyUnlKendSWXZuRFNDSXhyRmlPM01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSURIU2IybWJOREFVTlh2cFBVMG9XS2VOeWUwZlEybDlEMDFBUjIrc0xaZGhBaUVBbzN3ejY4NElGTVZzQ0NSbXVKcXhINkZRUkVTTnFlenVvMUUrS2tHeFd1TT0iLCJNSUlCZmpDQ0FTV2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakFYTVJVd0V3WURWUVFEREF4R1ZDQkdTVVJQSURBeU1EQXdJQmNOTVRZd05UQXhNREF3TURBd1doZ1BNakExTURBMU1ERXdNREF3TURCYU1CY3hGVEFUQmdOVkJBTU1ERVpVSUVaSlJFOGdNREl3TURCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk5CbXJScVZPeHp0VEpWTjE5dnRkcWNMN3RLUWVvbDJubk0yL3lZZ3Zrc1pucjUwU0tiVmdJRWt6SFFWT3U4MExWRUUzbFZoZU8xSGpnZ3hBbFQ2bzRXallEQmVNQjBHQTFVZERnUVdCQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBZkJnTlZIU01FR0RBV2dCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFNQmdOVkhSTUVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCQmpBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBd2ZQcWdJV0lVQitRQkJhVkdzZEh5MHM1Uk14bGt6cFNYL3pTeVRabVVwUUlnQjJ3SjZuWlJNOG9YL25BNDNSaDZTSm92TTJYd0NDSC8vK0xpckJBYkIwTT0iLCJNSUlCMkRDQ0FYNmdBd0lCQWdJUUZaOTd3czJKR1BFb2E1TkkrcDh6MWpBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERURTRNRFF3TVRBd01EQXdNRm9ZRHpJd05EZ3dNek14TWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRW5mQUtianZNWDFFeTFiNmsrV1FRZE5WTXQ5SmdHV3lKM1B2TTRCU0s1WHFUZm8rKzBvQWovNHRud3lJTDBIRkJSOVN0K2t0anFTWERmamlYQXVyczg2TkNNRUF3SFFZRFZSME9CQllFRk5HaG1FMkJmOE81YS9ZSFo3MVFFdjZRUmZGVU1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFDM3NUMWxCakdlRit4S1RwelYxS1lVMmNrYWhUZDRtTEp5ellPaGFIdjRpZ0lnRDJKWWtmeUg1UTRCcG84cnJvTzBJdDdvWWpGMmtneS9lU1ozVTlHbGFxdz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRkFBQUFBVUNBTUFBQUF0QmtybEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFCSFpwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTURFMElEYzVMakUxTmpjNU55d2dNakF4TkM4d09DOHlNQzB3T1RvMU16b3dNaUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenBrWXowaWFIUjBjRG92TDNCMWNtd3ViM0puTDJSakwyVnNaVzFsYm5Sekx6RXVNUzhpSUhodGJHNXpPbkJvYjNSdmMyaHZjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5d2FHOTBiM05vYjNBdk1TNHdMeUlnZUcxc2JuTTZlRzF3VFUwOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXRiUzhpSUhodGJHNXpPbk4wVW1WbVBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWU1pXWWpJaUI0YlhBNlEzSmxZWFJ2Y2xSdmIydzlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFMElDaE5ZV05wYm5SdmMyZ3BJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4TmkweE1pMHpNRlF4TkRvek16b3dPQ3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2U0dsemRHOXllVDBpTWpBeE5pMHhNaTB6TUZReE5Ub3pNRG95Tnlzd09Eb3dNQ1lqZURrNzVwYUg1THUySU9hY3F1YWdoK21pbUMweElPVzNzdWFKaytXOGdDWWplRUU3SWlCNGJYQk5UVHBKYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pKRk56RkNSa1pEUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakpGTnpGQ1JrWkVRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lqNGdQSGh0Y0UxTk9rUmxjbWwyWldSR2NtOXRJSE4wVW1WbU9tbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNa1UzTVVKR1JrRkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUlITjBVbVZtT21SdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1rVTNNVUpHUmtKRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpTHo0Z1BDOXlaR1k2UkdWelkzSnBjSFJwYjI0K0lEd3ZjbVJtT2xKRVJqNGdQQzk0T25odGNHMWxkR0UrSUR3L2VIQmhZMnRsZENCbGJtUTlJbklpUHo0NzdKWEZBQUFBWUZCTVZFWC8vLzhFVnFJWFphdkcyT29xY0xHMnpPT2t3dDBCU0p0cWxjWFY0dSthdXRsV2hiems3UFVBTVk5SGNyS2p0TmJxOGZlQWw4YUJvc3p6OXZwZGpzR0dxdEYzbjh1VHNOU1pwYzZKc05UNSt2MHhZS251OFBmZjUvTDQ4ZmcvZnJpY3pKZ1lBQUFEQUVsRVFWUjQya1JVQ1piRElBakZYWk9ZMVRhdE5jMzliemtzU1ljM3I0TUU0Zk1CQWFENnpsOHkvOVRPZ2V0OGQ1amZONzhid00vZERDUnBSNTIxelhmb2pISjA1SUl5aEJBVVNWQU9OZEd6Qll0MmY3S0ZyZmtKYUFrSGg5RlpoY0RYSFJrVEtvOU1MaWhHYWF2SW1uVjNxeUVYMEVwcmd6LzREd1VEN2tDSFJuZDhRRk40M0dvNFVWbUREZ3phNHcyN29pemRBMitjSyt1dVVwampvMit4d2MvNDJXNTB4NUxHWWVEQnNSMEhWSXg1eDhpRjYwQ2JsYlRFRWtGcjI3Yk5EQlVWU3ExT0tWUGJFNjJiM0VIOEZxQmc1T09PRXVjMnQ4WkppcU1PdUdwK2NLamc3d1ZHY2VvenFONHB4Z1ZQUWtqRllnYlZKS0RVaERDallyYXdQNXE0RVRnQzlmSU1SSHRpdHBRY0N2Sk9FTGNiTXNRZ25jaVJrbGpweVFqdkc0NGpxQlVFVEZpQmkxUEVJeWVrT3pzVytUeTVjTEhvczVSK2RNUzFMdFNTeGYzZ1FIY3pSMkNJNGdNTnBXNElSQTFRTWE2dEo0K0M2dUh1R0U4bU5ESXlGcWcvT1AvTU1VdWVTNklxOFM5MGRBZUJKU0V5L3FLa0srQk53ejhjWVk0amI1SjZ1NGlXQ0kyQjFaNTZMVzVrRWM0aGtkTXBzdlVDNTU4NVNYMFF1YmNnTnF5ZmdERkVjVHQrNDAvMFM1Tngwd2FDdzNPS2tjT2JBNUluMEFZcDAxcGpqdzJuNjI2VURqdEh3YTI4aUh1VEtxdHJ2K3JlVzQxTlo2aUdscjd1dUxKQ2ZrRnRjdGNHMDRzZ20xZU5TK1phRG5wYVRFckdveVg1SksyaU16OHhzMG5Pd1dHY1BETjQ5cWFDZDRiekpvekRabS9hQksrRW96THcrWGhOQmlZd0hmMHNpT3UxWFBrRy96S3d2cVlLY2ZTd0RFY0gvb1VlMDdlcy9XUThySXlnMkRPWGo4dGprWmR1REIvYjhoekRsbE1NT0NTNUJFbmQ1MzRmOHRpM1VaYzRrTXMzeEx5YWZNU3NKaGRHOFhQcWpOazV0QWdPMjVmZUtDaG5WZERqL0owRk1rT3NVL3hNQnYwd0ZoWWVFR2ZWSDEzZnVEVTB5REZMYTRmYzdSbldIQmZ1VEZWMnRFbU53YWRjN2FjM1VZMmpmQmw3SFQzNmZlMzRpUU81bU5DRkZCVzA3S2pQZ3FoT0xVMDF2WjhQdWVaMkpDbEZaTjhqa1VzNjl1a2E5ZVBwNitFZkw0QUY1K055d1NiaXJIdGNCOE1sL2drd0FFamtLNjRLakhQZUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiZWUwNDFiY2UyNWU1NGNkYjhmODY4OTdmZDY0MTg0NjQiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjYsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsibmZjIiwidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMTAtMjYiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkZlaXRpYW4gZVBhc3MgRklETzItTkZDIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE4MDkyOTAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjQiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTEwLTI2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0xMC0yNiJ9LHsiYWFpZCI6IjAwNjYjMDAwMiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFpZCI6IjAwNjYjMDAwMiIsImRlc2NyaXB0aW9uIjoiQ0FQWSBVQUYiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X2RlciJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInRlZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJ0ZWUiXSwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbImFueSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0Y0Rpc3BsYXlQTkdDaGFyYWN0ZXJpc3RpY3MiOlt7IndpZHRoIjozMiwiaGVpZ2h0IjozMiwiYml0RGVwdGgiOjEsImNvbG9yVHlwZSI6MywiY29tcHJlc3Npb24iOjAsImZpbHRlciI6MCwiaW50ZXJsYWNlIjowLCJwbHRlIjpbeyJyIjoyNTUsImciOjI1NSwiYiI6MjU1fV19XSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBSUFBQUQ4R08yakFBQUtuMmxEUTFCcFkyTUFBRWpIbFpZSFVKUFpGc2Z2OTZVM1drTG9FSG9UcEJOQWVnMWRPdGdJU1lCUVFrZ0lLalpVRmxkZ0xhaUlnTEtnaXhRRjF3TElXaEFMdGtYQUF0WU5zaWlvNjJMQmhzcCt3Q1B1dnBrM2IvWmt6bmQvYytiY2M4Kzl1WGZtRHdCNWtDMFVac0FLQUdRS2NrUVIvbDZNdVBnRUJ1NHhnQUFCK1JrQUZUWkhMUFFNRHc4R2lNMk4vN1IzZDVCc3hHNWFUTmNDLzg0VXVUd3hCd0FvSE9Fa3JwaVRpZkJ4eERzNVFsRU9BQ2pFZ2Y3eUhPRTBseU5NRXlFTklueG9tbE5tdVhPYWsyYjUxa3hPVklRM3dxTUE0TWxzdGlnRkFOSmJKTTdJNWFRZ2RjZzBoSzBFWEw0QVlSK0UzVGlwYkM3Q0JRalB5OHpNbXVZakNKc2svYTFPeWo5cUpzbHFzdGtwTXA3ZHk0emhmZmhpWVFaNzViODhqdjl2bVJtU3VUWDBFU2VuaWdJaXBzZnBjMHZQQ3BLeElDazBiSTc1M0puOEdVNlZCRVRQTVVmc25UREhYTFpQa0d4dVJtandIQ2Z6L1ZpeU9qbXNxRGtXWlVYSTZ2UEV2cEZ6ekJaOVcwdVNIdTBwVzVmSGt0WE1TNDJLbmVOY2Zrem9ISXZUSTRPKzVYakw0aUpKaEt6blpKR2ZiSStaNHIvdGk4K1M1ZWVrUmdYSTlzaisxaHRQSENmcmdjdno4WlhGQmRHeUhHR09sNnkrTUNOY2xzL0w4SmZGeGJtUnNyazV5R1g3TmpkY2RqNXA3TUR3T1FhUndBYllBV3RnQldKemVDdW03elR3emhLdUZQRlRVbk1ZbnNpcjRURllBbzdsUElhTmxUVVRnT2szT1BzWHZ4bWNlVnNRSGY4dGxvMnM3ZlFiY2hjUGY0c2xDZ0ZvM1FVQXZmcGJ6RkFYQVBrU0FOcWxISWtvZHphR252NWdBQkhJQXhwUUE5cklIVElCRmtoM0RzQUZlQUJmRUFqQ1FCU0lCMHNCQjZTQ1RDQUN5OEZxc0I0VWdtS3dEZXdDRmFBYTdBZjE0REE0Q3RyQUtYQU9YQUxYUUMrNERlNERLUmdCejhFNGVBY21JUWpDUVJTSUNxbEJPcEFoWkE3WlFFeklEZktGZ3FFSUtCNUtoRklnQVNTQlZrTWJvV0tvRktxQWFxQUc2R2ZvSkhRT3VnTDFRWGVoSVdnTWVnMTlnbEV3R2FiQldyQVJQQjltd3A1d0VCd0ZMNEZUNEd3NER5NkF0OERsY0MxOENHNkZ6OEhYNE51d0ZINE9UNkFBaW9TaW8zUlJGaWdteWhzVmhrcEFKYU5FcUxXb0lsUVpxaGJWak9wQWRhTnVvcVNvRjZpUGFDeWFpbWFnTGRBdTZBQjBOSnFEemthdlJaZWdLOUQxNkZiMEJmUk45QkI2SFAwVlE4Rm9Zc3d4emhnV0pnNlRnbG1PS2NTVVllb3dKekFYTWJjeEk1aDNXQ3lXampYR09tSURzUEhZTk93cWJBbDJMN1lGMjRudHd3NWpKM0E0bkJyT0hPZUtDOE94Y1RtNFF0d2UzQ0hjV1Z3L2JnVDNBVS9DNitCdDhINzRCTHdBdndGZmhtL0VuOEgzNDUvaUp3a0tCRU9DTXlHTXdDV3NKR3dsSENCMEVHNFFSZ2lUUkVXaU1kR1ZHRVZNSTY0bmxoT2JpUmVKRDRodlNDU1NIc21KdEpERUorV1R5a2xIU0pkSlE2U1BaQ1d5R2RtYnZKZ3NJVzhoSHlSM2t1K1MzMUFvRkNPS0J5V0Jra1BaUW1tZ25LYzhvbnlRbzhwWnlySGt1SExyNUNybFd1WDY1VjdLRStRTjVUM2xsOHJueVpmSkg1Ty9JZjlDZ2FCZ3BPQ3R3RlpZcTFDcGNGSmhRR0ZDa2Fwb3JSaW1tS2xZb3Rpb2VFVnhWQW1uWktUa3E4UlZLbERhcjNSZWFaaUtvdXBUdmFrYzZrYnFBZXBGNmdnTlN6T21zV2hwdEdMYVlWb1BiVnhaU2RsT09VWjVoWEtsOG1sbEtSMUZONkt6NkJuMHJmU2o5RHYwVHlwYUtwNHFQSlhOS3MwcS9TcnZWVFZVUFZSNXFrV3FMYXEzVlQrcE1kUjgxZExWdHF1MXFUMVVSNnVicVM5VVg2NitULzJpK2dzTm1vYUxCa2VqU09Pb3hqMU5XTk5NTTBKemxlWit6ZXVhRTFyYVd2NWFRcTA5V3VlMVhtalR0VDIwMDdSM2FwL1JIdE9oNnJqcDhIVjI2cHpWZWNaUVpuZ3lNaGpsakF1TWNWMU4zUUJkaVc2TmJvL3VwSjZ4WHJUZUJyMFd2WWY2UkgybWZyTCtUdjB1L1hFREhZTVFnOVVHVFFiM0RBbUdUTU5VdzkyRzNZYnZqWXlOWW8wMkdiVVpqUnFyR3JPTTg0eWJqQitZVUV6Y1RiSk5hazF1bVdKTm1hYnBwbnROZTgxZ00zdXpWTE5Lc3h2bXNMbURPZDk4cjNuZlBNdzhwM21DZWJYekJpeklGcDRXdVJaTkZrT1dkTXRneXcyV2JaWXY1eHZNVDVpL2ZYNzMvSzlXOWxZWlZnZXM3bHNyV1FkYWI3RHVzSDV0WTJiRHNhbTB1V1ZMc2ZXelhXZmJidnZLenR5T1o3ZlBidENlYWg5aXY4bSt5LzZMZzZPRHlLSFpZY3pSd0RIUnNjcHhnRWxqaGpOTG1KZWRNRTVlVHV1Y1RqbDlkSFp3em5FKzZ2eW5pNFZMdWt1ankrZ0M0d1c4QlFjV0RMdnF1YkpkYTF5bGJneTNSTGNmM2FUdXV1NXM5MXIzeHg3NkhseVBPbytubnFhZWFaNkhQRjk2V1htSnZFNTR2ZmQyOWw3ajNlbUQ4dkgzS2ZMcDhWWHlqZmF0OEgza3ArZVg0dGZrTis1djc3L0t2ek1BRXhBVXNEMWdnS1hGNHJBYVdPT0Jqb0ZyQWk4RWtZTWlneXFDSGdlYkJZdUNPMExna01DUUhTRVBRZzFEQmFGdFlTQ01GYllqN0dHNGNYaDIrQzhMc1F2REYxWXVmQkpoSGJFNm9qdVNHcmtzc2pIeVhaUlgxTmFvKzlFbTBaTG9yaGo1bU1VeERUSHZZMzFpUzJPbGNmUGoxc1JkaTFlUDU4ZTNKK0FTWWhMcUVpWVcrUzdhdFdoa3NmM2l3c1YzbGhndldiSGt5bEwxcFJsTFR5K1RYOFplZGl3Umt4aWIySmo0bVIzR3JtVlBKTEdTcXBMR09kNmMzWnpuWEEvdVR1NFl6NVZYeW51YTdKcGNtanlhNHBxeUkyVXMxVDIxTFBVRjM1dGZ3WCtWRnBCV25mWStQU3o5WVBwVVJteEdTeVkrTXpIenBFQkprQzY0a0tXZHRTS3JUMmd1TEJSS3M1MnpkMldQaTRKRWRXSkl2RVRjbmtORHhNNTFpWW5rTzhsUXJsdHVaZTZINVRITGo2MVFYQ0ZZY1gybDJjck5LNS9tK2VYOXRBcTlpck9xYTdYdTZ2V3JoOVo0cnFsWkM2MU5XdHUxVG45ZHdicVJmUC84K3ZYRTllbnJmOTFndGFGMHc5dU5zUnM3Q3JRSzhndUd2L1AvcnFsUXJsQlVPTERKWlZQMTkranYrZC8zYkxiZHZHZnoxeUp1MGRWaXErS3k0czhsbkpLclAxai9VUDdEMUpia0xUMWJIYmJ1MjRiZEp0aDJaN3Y3OXZwU3hkSzgwdUVkSVR0YWR6SjJGdTE4dTJ2WnJpdGxkbVhWdTRtN0pidWw1Y0hsN1hzTTltemI4N2tpdGVKMnBWZGxTNVZtMWVhcTkzdTVlL3YzZWV4cnJ0YXFMcTcrOUNQL3g4RWEvNXJXV3FQYXN2M1kvYm43bnh5SU9kRDlFL09uaGpyMXV1SzZMd2NGQjZYMUVmVVhHaHdiR2hvMUc3YzJ3VTJTcHJGRGl3LzFIdlk1M041czBWelRRbThwUGdLT1NJNDgrem54NXp0SGc0NTJIV01lYXo1dWVMenFCUFZFVVN2VXVySjF2QzIxVGRvZTM5NTNNdkJrVjRkTHg0bGZMSDg1ZUVyM1ZPVnA1ZE5ienhEUEZKeVpPcHQzZHFKVDJQbmlYTXE1NGE1bFhmZlB4NTIvZFdIaGhaNkxRUmN2WC9LN2RMN2JzL3ZzWmRmTHA2NDRYemw1bFhtMTdackR0ZGJyOXRkUC9Hci82NGtlaDU3V0c0NDMybnVkZWp2NkZ2U2Q2WGZ2UDNmVDUrYWxXNnhiMTI2SDN1NjdFMzFuY0dEeGdIU1FPemg2TitQdXEzdTU5eWJ2NXovQVBDaDZxUEN3N0pIbW85cmZUSDlya1RwSVR3LzVERjEvSFBuNC9qQm4rUG52NHQ4L2p4UThvVHdwZTZyenRHSFVadlRVbU45WTc3TkZ6MGFlQzU5UHZpajhRL0dQcXBjbUw0Ly82ZkhuOWZHNDhaRlhvbGRUcjB2ZXFMMDUrTmJ1YmRkRStNU2pkNW52SnQ4WGZWRDdVUCtSK2JIN1UreW5wNVBMUCtNK2wzOHgvZEx4TmVqcmc2bk1xU2toVzhTZWtRSW94T0hrWkFCZUh3U0FFZzhBdFJjQTRxSlpqVHhqMEt5dW55SHd2M2hXUjgrWUF3RDdFUzBlbFE5QU1ESldJbTZFc0x3SEFPR0lSM2tBMk5aVzV2OHhjYkt0eld3dFVoc2lUY3FtcHQ0ZzJoQm5Dc0NYZ2FtcHliYXBxUzkxU0xQM0FPaDhONnZOcDAzNVBBQ3FNMTJjUGFDUi85OGErUytZendkMWpHaURkUUFBQUNCalNGSk5BQUI2SmdBQWdJUUFBUG9BQUFDQTZBQUFkVEFBQU9wZ0FBQTZtQUFBRjNDY3VsRThBQUFBQm1KTFIwUUEvd0QvQVArZ3ZhZVRBQUFBQ1hCSVdYTUFBQXNTQUFBTEVnSFMzWDc4QUFBQUIzUkpUVVVINGdjTkJDME0rWWVxL0FBQUFIZDBSVmgwVW1GM0lIQnliMlpwYkdVZ2RIbHdaU0E0WW1sdEFBbzRZbWx0Q2lBZ0lDQWdJRFF3Q2pNNE5ESTBPVFJrTURRd05EQXdNREF3TURBd01EQXdNRE00TkRJME9UUmtNRFF5TlRBd01EQXdNREF3TURBeE1HUTBNV1E0WTJRNU9HWXdNR0l5TURSbE9UZ3dNRGs1T0FwbFkyWTROREkzWlFxbVU4T09BQUFNUm5wVVdIUlNZWGNnY0hKdlptbHNaU0IwZVhCbElHbGpZd0FBV01PdG1XdVc1S2dSaGY5ckZWNENCQkFReStFVjUzai9HL0NIbE5WVjNabGplM3lzR2xvcENVRVFqM3N2bXV1ZmMxNy80RWpTMmhYT01WZlRXRU1OT29QRSs1WXUzVFZYS1pKckZnbWxGU3RkUXFpYmY4THBaRStUekdXOU5HcXFxWVljU3lnaHovQTYvcnorZDRjejYvVWEvVDVXa3ZYTHNyOTVYSCt2ZTR5YXRkU2s2Ymtzci9zcWwrWnpXOWZ6WU9UblBBTUxEbFhxYzUxZTV5Q3BWandYdnU1YmUwMlFMOXg1dS9GNTBPZlhBNjAvNzMrdGxQdS85Vi81NTBDWnlEeW1wdjNNME1Ja0NMR0sxdnQ2K0pkRm9TcjIxNWRGTTc3dXAzRHBadFdtKzNtUXZ4NXN1cE1TK25xaGZRMDBDZEJTLzdvL1hwWkt1L1N2TEtwL2JhbCtzUFM2SDlUM0I3OUY1L3RvR2Z0UDNpbERWdnVmdy85L3k2UC9ZaUJjT0d2NWN5bnlkVDIxVmNtdHlOZjEvUzk1cDBNOWp5TFgyNE90a25mMnQvdjJpdFNmOXh0UmFhVzhEMFFKNS9SS3VKLzNzOGFjOC9ndzhXVGkrVDZRcXZHV3ZWdFVjN2FTLzd4UDBqcHA0dThERWZSY1NucTdUNTUvV2hwK0hhWGsrRDVRMDVMdEZ3NTl2OUMxa2FMMTdUNHJLSnIzMjBBazRTanAzUmRub0p6eWZsOWFMVVUrT1ZzSnMzNEk4Nm8vVStQbkNvd1ZmTEFvbnlYazloNU5vdmJKZC9pMHRFOVI0eEZoTHU4djZDNGZCam9nbCtWRFFwNXkvQUg2UHdlYWhPaHR5UlN3NHRQeVlXa1AxSDJhR1Y1NXl5UHRMTG1YOERaUUNNZjh4RUNKM3lrZTlPTWVtSWczV3YxVkpqbXBNN2lSa0FZTXRRdjJnOE1lQ2pyQnlxQ2xKdGt5aGVFU1E2WGI4YjhJOHNmaGFaMW5ONTNkdkJZMXRFOGRhM3ljbm13OVJaejYrdFJQTWVOZTJpQTU3NVdwK2FlT0JPVWhVVyszQzBiYmg2NEt5YWhmZlI0ZmZRUEVHZkJVdmgrS29WRzhjVCs0SkN4RDFzdC9ESkRHOCtLeE9uY0dPdGh6b2xGNHFmRFNBVGR0QitwWTNGRU4xRmZGa29aVmpRSGFlT2tIQmpBbU5kN3ZpWUU2TDNWZUdydzBlR25NUTFnSEZCKytPU1M4ZUdueCs1VGE1dmNldDlISUI5ckEzVlIveEZPUjNqRW1tdEU4UkNrME9yQ01FN1dZZGppT2p5UnFKTFFSNjRrUWpYZmh4RmhKeUlqWnNURUlKa2VqRStiR3poeWR6b1B6NEl5RmNYSmVuQmZuelhsemR2cDdoNzFZbW9RanJqSnRCUkdsT2I1dDZLZElHNFNNWjRWbnpDNlZlNVVYWVY0aGRJS0lFRUlzbmFLVndjdk1LUGhEOElXY0lPRUQ4WEluZFFxRHJGU0NGV2tySkNZQjFXa2VEclluNVZtbGFGUGRJVFZ1R0RjWVBYV3VCOWV6b2paNFlSL0tuaUc1RVcybERGS2dHbWlMT2huaFFFNCt3QWJTaEl6Sm1RRXpDWmZ4VVNhU0dVdnp6Q0V6V01ZbkowdXliekp0aFlLQUtnU2pwRTdtV0NnRk1WcFlPelZKTVNtcFJPdTBRYUdESm9XbEZzSmRDUFA5eHhKVjZxM0NGRXVVNktuMm9IVmM1Qjd5ekZiUTdyZDBWQ0tqT3dWWUpweGFycVJFWmZhYUZramlDQ1FTQmhTb1RGeU5aNGl6T3FDanVsQlB6RnE5SVZzR0NleWhrVDh0bjFMdUpQTU9yWEdOdGExelBiam1uYlpyYUNTamtic20rTWhZcHpIVG9XUkRxRmpqZCtjM0RyZkpieVl4WHVneGhzNnlPcFoxVXFLenBFN1pkRktnZDhDLzQ0dStadWgrQXMwZjZud2tDNlBFQXd1VU9sVkQ1ekZPOVhERzhZTUl6a2dHU2tmbHBUQUxlWVFHUWRydE1Ic044NVFabVRzWmRKMC9FdlRvemNVU0YzNVo5RnRrL0pvOFgvekdIWnQwMklKRm0vQ2hJOE91SHJZTjZsSER4Z2Q3YityU2dsTjNUcFk3eU9Ca3RlTXJIeWs0eS9aOXFoc3ZpVjRrQ01Dc09LQmlzMUZjZ3dlcm5qY2poWHovRjdNRG95dkdObVBzZUd0YWpMdXh1Qm9wcXlpd1NCVE5rZHFKMGxPVVNkdkE5SUZxb1RFSk9oSUFvSFZ5ZWhhQW9GQ1pVQWVGaHo1QmVmZVkyN2pna2dVNmJDWUZIYUpFU0NxV29oSE9BQzFHTEdORlZuV3E3Y2haRkxORjFSbTFlZFFoR01vOTcxZXNZRVBOTWNKenNUYUx0ZTlJYnNYcU5UWndoRUtQS0pUWVdvK3RlMnlMMzk0ZnhNa2xtbzVvRnE5b2c5eGRLMUpoc1V1UEhkZjBXb0dqSFVtTjJISG9pRG1PTk9KZ21ZTUJCNWFNMWVNQklGSWdUaWc3empyaXhEOXp6amh4OEFLMUZsVzg2c0V3aTRRNkxnYmJDUEtOZFJ1ZmJNdHhrMUI3VzNTaTRXbGYwWlVMSHZqdzZMdkxqYVg0bnNJVDBweXNBelRBT2tJRi9qWFdERGwxbkRtMzhKS0lWRG42U0tUeHU3dklXcEJPRjRCTEFDdEpsaVZOa2VRSExGMXlYdXhLcCtRK0pLOU9kbEZoOUMxS3MzcEptYWdHaDhJWkdYcVhJNmgxMEhZandMUnNVaXRWeGdCMVRkaHRTVXN1alJScUhUdFdGc0RrRW1OVVBDOW1TMEFUcWdjRFV4R2tublFid0xFRElpSWpLYWhzTXVoSFJzaUJ0cG1NL1JJNm9jc2xjMVZBYzhyQ0w2dXFMR1plbTd3a2E5RFBnbUZBZUJWS1JsZ2dVTjdGTFlxekVuZUFLeUZmZEY2NGhmSmRnMElnbFRQaHcwVnhjSFpKeHpiUmxNUUd1SjhUSFZNQ20xUDFsRVpMaVpCbGJFWHlYQ25iVG5tMVJQS25Ba0NYaGlpY2tvcXZkTFlCaU5Pa2ZTZmRCbGxrQkJwOFlUTlYxR21MT1RYSXBqVXNhck9CUHVVT2tqR1REVmJ1d0IzRDlKb1RLNFZZUExIZ05KUzA3RDJOM1Fob1RTaXFORm5SM09sS2l3aFRMb2xFVFVCTTJuSTJvalFZQ1NRaFBqRTV6NTNNOEMwd0kxSk84NEhJZ3oxNGxpVFVmbEVYa3pUZDJBTlZZYnVNZ2tjeGhYTEhmcWFEdXFERGpMek1yV2NLbkFvRE9OZzRGREM1ck0zV1c2NmowRUVDVktWRGJYaXBWcFFuTHpjWXErV1JxZVBjZ0VlS0JWbUlTenNDbmI0OTFkeVpDRHNnOW5ubGU4UEF5QU96S2NCTVZQTWNQWk5TbVc1NUdiRlliS1VRQVZ0M0poVWVya1R2NDhyczYvQjh2ZUNoV0VCMm9CNnNnQXVCZzBKbEZwS2dTS1d1QVhWZ3JSQkdpTFVYSEZhT1JNL05DVEk3STJIYmg2d3BoTHFBd2tXaFZ1M3NkQnh4aVBTdmxCSXNYaG9wMkNvaWRJNWlnSXdoT0cwY3hxdWw4MWJ2TkdlZ2dkdUcwZGdoekVRRHhlYlNzdGoyck5yS21sWkFwc0pPc2V5eENwQVBnOGNDQVNDMXNLR1FXYjFmR01NT1B2T29nNk1ZSnJoVWJDb3lDZGVTVEZZMVFTMzVCUDFzTHJlUlBjeGsxUGcrWHpnV1d6YTVsQ3BYZUYycmtjUjBvcklWZXRhMkp4dW9wR1lkMVV5bTVNYktIWWxRZFREeDZKemRzYlBxN0g2aFhSdjRqWFlZYUg0NFpiTUIzNU5zd09PT1VuQWdIVFVHMFNOYk5xRWgzNk9WaWtRZ3ZsUnp4dzdFS0tsRDBReDJHVEUvWDRZbVlRSnRVTzRWNTV4MVZRWFkxVnRsQTB1YUpmZ0ZudEJkRzMxTmVyVm1WN1VOYkdXdFJMYWl2eW9BWHdlRkJMRFcyV2lIVk5pdFVFTDE2TmNOQW02ZUF3NEltRng5RjFSWnZaQVM3V2lLQmttMU9CY2dFa0E2QU5nemtGQWJWUXA5cmthcXQ3d3A5a3dvKzBBZEhlY0tmbUhUbE1iVnFubGp5TWJlRkRUWXpRQnRNNHoxM2FqTDFtZHZVSDNEaFczNGJGTUJETzR0a0d2eHluSnZXL1VpT0x0NWdqY040WXgyUTY0aE42QVcxR2ZzemFBUFFMc2JWSDZLeGNBU0VBZEoxU2c2NnFRVXR6THR1dXVRK0JvU3l2Q200UWhqczJ0dFlCaEpoYm96ODBrU05HT1haUU9zSDkwTkZyUkpsK25WbHVZTGtoV0QrR3ozVGJvc0Zqck1IWTJueU5zRnJiTGxoMkxoQzVwcEI2QXBmQnBNbVNrcXFwd0NiRmN2bmNuUUtuaWdrelNrMmU1WTFSdEUwbWJ1QUN3OURERXplNGYwWVpRK0tMT3hEVWFmZmFJRVY4NVhYNUQ1aGpzMnRIOFNHSXZPWndoa2JFRjE5WUVNR1hIQlZ4bkdueUI5d3ZkOXMwTEsxS2prbUVacC9VS2ZZWGkxQWJDUmRXMWdEYlZOZlMrMk05Q3E4VElvUGZvb2pMVDVjZElzam1uakNKNnhrTFlzNEFMSHdUU0grYUZTOTRKb1pwZXpVUlJhVVE1Z2ZIRklEMFlBU05KaUw0RHNCMjVueVlPVmtRMlpYZlZNMTZRMkVDUWtTRnF6alRuaER5WXpCRXFiT0dPQ0ZuTU1uWXcwV2NpRXNDWjRCbkhvQkJUUXJYWDZhTmM2ZStnd2tHMXBzaGhrYVBMRmJta0I5d3Urd1krR0hRQlIzcXNzdkZYSzBnV0tNeDV1V0UxaHhjMUFwZ2hpNGs2NFZ2ZUI3MUcvN0VKbTY4Z3ZWTEFwREQ0WGltYzU2c0E3T3h2b01neHVaN1k3RTMxVDBrWEFCbGFtRFhodGFHUm5uNVFoT0IvV1B0OWV3WXROQWtDSnlJQXgwVmlrL2lLZVlHcmZnQ2JnTW54Y0cyamRDTis5YkNJVDJpYXcyNkUrbndqcHduNWlGNC9vaGVpT2xzRWwwUnhJOGd5QlFEdGVrT0Z3MitXcXkvVUVEYVhaNk5USU9xUU9OVkFkWlBHT2toKzFPdUdrVUJvT05GL1V5TTdEOTVwZ0pHWHJmckh4T3ArYjQ0OFBEMS9maUVRNTdnOFFZTmQ5WjVYN2F5RGMvdlJnZVYrZnBmLzh4QnJEai84SDhPTmUrRS8zcno4Zi9QWjkrOXZJMjdMKyt0SmVYbC9POG55dUVURFBRS0t2VDJxdnI5RGw5YkdrUE4vSjBhY3BmVGovZGdEK0xESWwrYzJ5TVI2ZlFLdkhrWjVlM3grcjNENkM3dXQ5bjM3M2VYVjlsb1k0T3FjWlRneC9mSXIvR2hrS3ZzL3QyMC9EMmVTTTltMVIrSXZqK2hjVDlUb1JBclAzbFFBQUFDVjBSVmgwVW1GM0lIQnliMlpwYkdVZ2RIbHdaU0JwY0hSakFBcHBjSFJqQ2lBZ0lDQWdJQ0F3Q3NEVy9HWUFBQWVjU1VSQlZFakhyVlpiYkp4WEVaNDUvL2t2ZThtdWQrMWRyMk03ZHV6R3VUU2hpZEtFcGlGcEJDVVJFb1FLYUZVRVJSVkNvaytnVmp4Q0gzamlBZkhDRXc4b1NDQkJLd2pRb3BhV0ZBcE5RK3ZnSnMzRmNaeUxMN0c5YSsvTnYzZi8rMy9POEhEV2JtZ3JWQzduNlQ5ejVqOXpadWFiK1FhSlNCSXdoRmpLdWJxZk1yUlMxZ1FBSWtDRS8zMXhTY1FRYnl3N1AzbDlzZVpFR3VKOWcrbHZQdFJ2NnRyL3hRWm5pRTBuK3NGTGM3WW5pRWhqK0tmSlppenBtZU5ERzBxU0FPRmZqQkVBQWhBQjNDVlh3dmZwTUFCNDRXSzExbzd5S2Y3NWZUMkhSalBaaFBiMjdiWHJGUWNSaENRQVlBaUlRQVMwL2pPdXgxREpONFIzTDdWbGZpUXV6TGMxeENjT2xiNzI0T2Fuanc4OU1KcHArZUtkdVJZQWFBeUphTGJtbFZjRFJFQUFBaEJTaHJGRUJOdUx5bmFnUEJDU0lpSGx1alVpaW9TTXBlVHpEYjlzQjFzTDFwR3hybGdTWjNoc2UvNmxTL1ZiVlJjQWF1M3dSNi9NejlWOXhuRC9VUHFwWXdPV3J2M3N6YVZyWmVmeGc2VlRaOHROSnpxNXIrZnhnMzFURmVlSGY1dzlNcGI3K2lmNkFlRGxLN1hueDVlZk9qYkFLM2JvQm1La2tBQkFCZ1FBMjB2SkgzOWx1NkV4QUhodWZQbnlnck1wb2NXQ1hyM2EzSkszdnJDL3QrbUtoVWI0MHplVzVodEJOc0dmUDcreWR6QXpsTGRhdnJ5NjZDalVUSlhkcGl0Nk15YXozVmdROUtSMWxSWUEwRFUyV2tnTzVpMHZGT016YTdrVS85N25ocjl4dEMraHN4c3JIZ0JZblBtUjVJdzljM3h3ckRjUkMvanpWQ050OGVHZVJMVVZyWGt4QUN3Mmc0R2MyWjh6V1JCTElMQjBkbmQrVkc1alNkdDZrNDhkS083c1N4OFp5eGtjZzVnVWJJS1lIajFRL05UTzdpY2VMQmtjWjJzK0FJd1dFZzBuYWpoUkxHVFpEZ2Z6bHNFWlI4U050MjhzalNFQWJMTDRkeis3ZFhrdE9ETlpINTlaQ3lMU1ZENEprZ2JiMXBzRWdJRmNvamRqTkowWUFNWktpZE1Uc21LSGFZdXZ1dkU5eFFRQThLVEJBTUVKeFB0d1JrU0krUExsNnFtelpkc1QyUVEzZEpUVU9USTRLcWROemxLbTVnU2hrRFJTU09xY0xUYURwTUdFcE5GaUFnQllQcVhyREN0MnFBb0tBQllhL3JkL2VmMFhiNVhkVVB6cTdSV0RzeWNQbDU0OU9XeHk5aDRLMTcyV1JFSVMxMUFROVdXTjdoU2ZiL2czVjd5VXFRM21MUUJnL1Rrem0rVFh5azdMajdtR0FIQnBvWFZocnEwenRySVdyTFRDVCsvS2YvbmpmU09GWkJRVEFnSUFRL1JDMlFwaUFIQkQyWERpVFJiWEVDMWRHK3EyNXVyK2xjWDJRTTdzU1JzQXdBWnkxbEMzVlcxRnA4NHVCYkdZcWJvdlg2NTNwL25lTFdrL2twSWdrK0FBTUZWMjJvSFFHS2pDamdTOVB0VUVnTGR1cmRaYVlWL1dVR25iVmtwVzdQQjZ4VlVKa0VRY0FCN2EzblZwb1QwKzA1cGNtbzRFMlo0WTdyRjI5S1dubDkyVXFaMjdhWnM2L3VIZE90ZFEzU0lrSkEzMnlwWEc5TEpiWFlzWXc5MERLUlc2MFVJQ0FDTFJTUUFSY0FCNGVGZjN4TnphdVp0clFjd2trYzd3eWNOOUFMQzF4eG90V0pObFoyS3VkZUxlbkJBMFhYRVVUQk02MjkyZit1dTB6Um1PRnExUDdzZ3JBMFBkQ1V0bllTeTM5aVNVSmxjOTZ6c25obDhzVmE4dU9nbURmV1pQOTg2K3RKQ2thK3pwNDF0Ky9ZK1ZZc1o0OVA3aTVKSlRiWVZFeEJDQ21MNTZxRyswbUt5MW95L3VMMWk2cGtpbE4ydmtVbnpORXdONUN3QVFrS3QycURGOFpGL3hrWDN2OVdlTklSRnM3cksrOWZBV0pkd3pzR25qVkJJWm5IM3AvdDUxVEhjZ2Jtak1EV1YvenN4WW5KUUh5aEVDSUVtSXFJRE9FRHR5QXRXa0VaR0loQVJkUTBSZ2lBcXlzU1J0WFhscDFmL2RoV3ExRlI3YjNnVUFVcExHa0czMGJzYlVuOER1WWhaMUYwTkVBSWFvVUJURzVJV2lVL09JaUtDTXZYdW4vZHQzYWhyaXh3YlNHMFRFLzBNR1JBQVl6QnQ3QmxLNnh1NStCd0RrVS9wSXdYeGdKS3VDMlFrREVhazRzSC9Mdi9RQndvSVBEQVpFSklnNFkrb0lFQkFBcGFUL2d0a1ZadUFqREI4TUVXcXQ4Ry9URFJWSG9nN0gwbnFMVmR0cUsrd29BQkFCUTZpM3cxbzc3QUJobmE2RFNLNjZFUkUxbkxBZHhLQkkvL3lzWGJHRE01TjFGVTMxSWx5UGlkcDZZVHd4YTd1aDJCZ3Z4bWRzVi9WZ0JFWFhBSEN0N1B4bVlqbVc5TVowODlwU0d3QzRHNHEyTHg0NzBMZnFoaGZtMTZiS3pzbTloZE1UeTRXTXNhMllUQnE4YlBzM1Y3d2RwZVRGTzYzWnVuZGlkK0gyaXJ0M1MyYXhHZlRuek5mTzFnK09aQ3QyYU9uczhEMDVMeElwVTdPOTJPUk1KWlVsRFcxTHQvWDlGMjR0cllibDFhQTNhengzdnJKL09OdWJNZWNiZ1JmSm1acmYzMlcyQTdHdG1PcEptMWNXV2w0a0FXRFg1dFNkUm5CMExGK3h3K1cxY0hkL0dnRGFnVWlidkdLSHVzWlUwRmpMajhkS3FXZFBqdjc5MW1yZGlTek9Vb2EydWN1OGQzUEswcG1sTTVPem9aNkVxVE9ONFdneGVYUEZMV1VNQU9BYUk0TFJZcEl6TEtTTmJFTDNJakZiOWVZYmZxMGRhaHFxNUhHRHM5K2ZyMnd0SkVwWjA5SlJFdlhuekw5TU5VeU9zWVRiVlRkdGFuNGtpS0RoaEFONTB3dGxKcUVEZ0pDMHlkSmV2TGhpNmt4akRBQm1hOTZCa2N4OWc1bWZuMXNzWlUyTHN3NTQ3OVM5MHhNVlB4S0xUZSsxYXpVaWV2TkdzOW9LWm12dStablZlanRvK1pIdFJRc05iOW4yWDcxU2pXSkpSUFYyRUVUaXpHU3QyZ3FhVGtoRVRTZHNlUkVSemRmZFpkdFh3ZytwZ3crdEtiVnVWOTJGcG45MExLK0duNDlVK3FxU0paRnFuNnFrSlhYWWtZQVFPaU1qSW9TeDFGWDNXUzh4S1FseFE2V0RiMXIvUW9CL0FxWklHWEwzelRoRUFBQUFiR1ZZU1daTlRRQXFBQUFBQ0FBRUFSb0FCUUFBQUFFQUFBQStBUnNBQlFBQUFBRUFBQUJHQVNnQUF3QUFBQUVBQWdBQWgya0FCQUFBQUFFQUFBQk9BQUFBQUFBQUFFZ0FBQUFCQUFBQVNBQUFBQUVBQXFBQ0FBUUFBQUFCQUFBRVRhQURBQVFBQUFBQkFBQUNvd0FBQUFBT3lQNWZBQUFBSlhSRldIUmtZWFJsT21OeVpXRjBaUUF5TURFNExUQTNMVEV6VkRBME9qUTFPakV5S3pBd09qQXc2aFpPMGdBQUFDVjBSVmgwWkdGMFpUcHRiMlJwWm5rQU1qQXhPQzB3TnkweE0xUXdORG8wTlRveE1pc3dNRG93TUp0TDltNEFBQUFZZEVWWWRHVjRhV1k2UlhocFprbHRZV2RsVEdWdVozUm9BRFkzTlNBSkFNd0FBQUFZZEVWWWRHVjRhV1k2UlhocFprbHRZV2RsVjJsa2RHZ0FNVEV3TVFZbk5xOEFBQUFTZEVWWWRHVjRhV1k2UlhocFprOW1abk5sZEFBM09NblVleWNBQUFBb2RFVllkR2xqWXpwamIzQjVjbWxuYUhRQVEyOXdlWEpwWjJoMElFRndjR3hsSUVsdVl5NHNJREl3TVRndlRBVkJBQUFBRjNSRldIUnBZMk02WkdWelkzSnBjSFJwYjI0QVJHbHpjR3hoZVJjYmxiZ0FBQUFBU1VWT1JLNUNZSUk9In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA4LTE3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0wOC0xNyJ9LHsiYWFndWlkIjoiZWZiOTZiMTAtYTllZS00YjZjLWE0YTktZDMyMTI1Y2NkNGE0IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJlZmI5NmIxMC1hOWVlLTRiNmMtYTRhOS1kMzIxMjVjY2Q0YTQiLCJkZXNjcmlwdGlvbiI6IlNhZmVuZXQgZVRva2VuIEZJRE8iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoyNTYsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDNlRDQ0FkR2dBd0lCQWdJSkFKYlR5cnUxWC9JUE1BMEdDU3FHU0liM0RRRUJDd1VBTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRBZUZ3MHhPREEyTVRJeE5EUTFOVEJhRncweU9EQTJNRGt4TkRRMU5UQmFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNVmpLSFdwYkQ3VFNsTXhvY2pUbDZuSWY3eDMyUG1zUTl6R3VMR0dxQTBVUVpvSXEzWEx6TDZMWVV2SjVBNWcwdXlGR2xsSEVmR0FLckVhQ1E4RlZ2UFMvVWgwRnlmeldoUkF6aVRTaWpqTUlJVmpqalV2OW05dkZtY1hTY2dIaWc3T2R6ODg1OFYwa3JOSDk5cUdtM3dqZ2FPZXJUV210K2pYQ1VmbjAxSWtUUHd4RzJIbGdFZDQ1ak5MU1Y3Vm9vbCtLZThFMmtpNGxFa1RlSHpib3VsUjVHVWJwM25NaTdFNDdWTVFhM2JOd256V0Jic2FCU1NRaExrM201SGFLaGh4YTZ3SkRLNDdOaU1Da0NrZElIdVdTUUxWQWZtODVVQU9OdEVPUHdpME91SzNxYmU4eUtPRkdmMEtoQjVNTWVBeW03TVYvTTRXMGE0OW9nUEQ5cE1DQXdFQUFhTWdNQjR3REFZRFZSMFRCQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKV3o1eExNazVXTlliQWI2eU94RUNCb1oyV2VCL3FsNFZKM08vMy90TnN4T1luekxlV281NDB6UWg5ckFtYXh6N2V1bUJsc2tNcTR5R1BTTlhCOXljV0dIZ2tjQ2VTek4yd3Y4Q0l6REJzMm9CWmpUTms2NUxCWkRzc1RPQnRNVy8rdVRGSFFmYnVPM0lTTGhJMERYZlJFaTlORE0zamZrMTF4SGNzZmgyUk1WK1FkTmZ3VmFaWnJDcStvdUcrRXZrdjdLcXErb3l1MFZGTS90ejY4VEdsNnlsaFBGUjFxaDl3dHRwVmpBT09DRVFDTHFQMmRQMjhsd1lCeUNxSFFxVkh3YnVqdi9MWmpabktXM0xZbmRaaXhQUFNSQ0pzc0REd0p2aC9mNm5UeGc5WkUrL0pjWXJlNUNhSThuelZIYVNPQ2pOSjdGelVMRzY0SmlXT3ZRNTA9IiwiTUlJRGRUQ0NBbDJnQXdJQkFnSUpBSUNVVHZrZ3RqNUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GRXhDekFKQmdOVkJBWVRBa1pTTVF3d0NnWURWUVFLREFORVNWTXhDekFKQmdOVkJBc01Ba05UTVNjd0pRWURWUVFEREI1SFpXMWhiSFJ2SUUxMWJIUnBRWEJ3SUVaSlJFOGdVM1ZpWTJFZ1EwRXdIaGNOTWpBd056QTNNVFF6TnpFNFdoY05NekF3TnpBMU1UUXpOekU0V2pCUk1Rc3dDUVlEVlFRR0V3SkdVakVNTUFvR0ExVUVDZ3dEUkVsVE1Rc3dDUVlEVlFRTERBSkRVekVuTUNVR0ExVUVBd3dlUjJWdFlXeDBieUJOZFd4MGFVRndjQ0JHU1VSUElGTjFZbU5oSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFLT2VxQzUvcDBEMWlzQ1lLUUpsVlVPckI2STdETG9jdW5FL1JtOGR1R1RieXhRaHQzQ2JGVlR2M04yTHAyZmJqeGxJKzNzT1NHazMzRlRZa1RxeGNkSklySjdTc2tCY1VTTnJmS09hUVQvNktRY1A0Q203Vis2NTVUcStUV3h5eFdRaER5Z3QxNXFvUDdNdUs2YlQ5U3dwQ2pwZktoYU1TbXlRYU1vVWNSQWJMcWR6QkNhYzBoekIrWmUrZ3FKbG5XVjlVYVNJMnJGc1Z1SDRaRTBjUk8rTU9wYUxnTS9zMjQ4bkdHSHAyMmV3U1FmYm5QYUJiYjhpcXlBUCtjdTUyR0xzVXBLUkplYkUrUjYrUE1ROUpDZFdlUVpSM0RrZlNpZGt2M21jYjRqcTFpSXRhK01xS2hSbndyZlhoOTExS1dMbllBbDlFTkNoTFgwYzZTajFRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3SHdZRFZSMGpCQmd3Rm9BVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUZMckRoYWVnZUtIeFlqSDNFUDN2VUJLaG56TTIwNkFTeGdlWUNPMkVjOXBPbFlKYWVxRkUrc1VhbVVWL3B3akRscU5hU2dGZ3k3VHdlWWt2T21NbjRxU2NzSHF2SjN6R09BaWFmd2FoMXZVSGZDbFhSOCtheE8yaUdPVUYwSktyWjlZWWpiQWE1LzRIQ2x2N2pGUE9kTVdUT1F5bmdvaUhBczNqa3VZanBDTEZsQjRWT2kzZDF3akExcG5UZEJLa0FiN3Q4blR2dysvWGJGdmNRYTczVkg3c2p2b0JxRDNmZE1mUmN1VnE0cVVadFpUNmNHYWdUSEQ2MVR0cWg5b01DWlhjRGJSMVBHWm5OYnF5Y3NXUERJSzBucG1LMy8zbGZWOGMrWnNyeTZlMTcwbWZKTVpwN084bTZDU3o2L1ZMSyt5REpkNzg0MXdwbWVLVGY2SW5aQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVF3QUFBQWdDQVlBQUFEbmxVWnFBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFBQVpkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNakh4SUdtVkFBQUsxRWxFUVZSNFh1MWREWEFjWlJtK05PQWZLb2c2V08wUWNyZVgzTzcxUjQxb0hkU3FxREFPZzMrY1lFWEJvbFhSVEVuMjIwdGFLVGM2NG1nQnF6QmlFVVZwQmRxaXd3aHFTZElTMnVwWVNndlJ0cFRTY2tsald6SGFnanBTUmRyNHZMdHZqcnZrMjd2ZHZkMUxqbjdQekROM3QvZCs3L3QrZjgvKzc4YUswTkRhYXIycU9kWFpvcVd5SDlSMGEwRmN0NjdXZEhHVFpvalZDY1BxU2VqVzFvUXVIc095L2VCVHNEbU0vNTRaVDlqK0xXR0lnN0RmQi9zQmNEUHNmNFhmUDhYM2IydUcxWkhRelU4bVV1S2R5V1RIbTVxYWNpL2pIQUtCeWlmMGJCcitMd2FYSVBZUGtNZHFmTDhYZFdwbHMxQUEzMS9Rak93OThMOFM5YjhCWElSMituRGM2RG96bHNrMHNsbmtRTXhrUEdYTzlFSnRWbllHRjRzVXlWbmQ4VVRhZXA4YncrNkxha0JqNWl6ZGJOSlMxcnhFV255V3hnMzZFbVBkV29QUERlamY3ZUFUR01zSGFEelR1QzZoYmowTi9wWG1Bc3J1Z3MwV0xQOE51QkpqWkptV0VsY2wwOW1QSjFKbVcwdEw1K3VpSEJ1R2tYc2xqWDg3bmk0RXpWbms5QXZrc1FuNTdFU2RockI4Qk11UGpPV1AvLzRPSHNSL2U3RDhZZFRsZnRSaEZmZ2RMRzlIdTF3QWZ6cjU1akFPa2lRS2h2VmJHQjZDMC8vaSsyaU5lUng4RmdudlJmeGZhaW56U2s3TkUwaUlVUGJmNDN3V21OVE5kN0JwS0VBN0xaZkZBWTl6cDN5WlRTTURpUVZpL1UrU2c1UVlBSWZPbUcyZXdzVWpBL3JoVzdMNEJlcm1qOWgwVW9CMk9CK1RaVFc0Qi9rOE95Ry95Q2lPb1cxSVlINkg4WFB6OUxiY0t6aWxRR2hwTVp2aFp5SEd3RzNnNDJCazg1WjhvOTBHOFgwTmlTczFJdjJRR2s4S2RXc3p0NHNuSVA4UnFSOW1EUVhESWRaU2JCb1owSWwzUzJPWFpYWXBGNDhNVTE0d25LMWJlVzQxcEwzRkVRQ0psUFZXdERHMmZ1eVZyTlIzdEJUZFNqQjhZcklGb3lWdG5vMk9DekJneEROQkI2cFhLTUh3eGlEOWdLM0tjNlBja3ZCR0pSaStNY21DMFlENGZkSzRYb2g5Vy9ZVENaUmdlS052d2Noa0d0RzJlMlcrYWtzbEdMNHhtWUpCYXhscFRJK2tOUlFkbUdSM29VTUpoamY2RlF3NmNDcnpVM3RDTUxEV3VRc2QzUitBdzNLbkJRNUt5bmpoamR4T25uRGlDRVp1R2pyc1lXbE1KdHBpV1VLM0JtVC9GZkV1ZGhnNlVQZTZGZ3owYlI2ZmE2TW1uWTNrbER3aGFZakxVVTZlczI3dDBnenptN1ZnVXU5NkQ2ZmtIeENhNjJVVkdDTXE4ZzAyalJRbmltQm9SdllpYVR3bTJudGZXOXZDazdXMGRZSHMvd0oxNjNrNmVNWnVRMFc5Q3diRzlLMXNPcVdBdklVMFg1dGlEWnROYlNqQmNHRUVndEhXZHN2SjhFMm5BdVV4aWJwNWhXTTkyb0RmMnliOFgwS3gzckVORjBvd29nSG0waEpwdmphVllQakNpU0FZaWJUMWVXa3NKaWJDay9QbTVVNWljOHJ4UXBsZE1SUHA3SGxzSGhxVVlFUURKUmdoNHNVdUdIU1JEK3BJVitUSjR4SDFMRzlkakNIVGlNbFI0VmlHMkU3SFJiaEFLRkNDRVEyVVlJU0lGN3Rnb0oyejBqaE10SE9lamwyd2VRRlkvbEdaZlNuRmZEWVBCVW93b2tIQ01CZEw4N1dwQk1NWEtncUdJUzV2VHB0bmgwWFUrMDVabkFKREZBekQ2RGdkL3A2V3htSEdEZkZGTmgrSDBRYjB3YU95TW1PRStPVU5JL2NTTGxBMTZsMHcwRjY3NDdxNHBScEdjZHFhN2t1UjVVdEVINDVnRG13S2kvRFpqOC83SUVTMzRyT3plYWFZeldsVWgzb1JqSm96Uk1Hb09BRU5hMGkyZFRHR2VFcDhURkptUER2WXZHclV1MkNFUWJxaGtzT0ZCc3lsaTJXeGFzVGo2TmQxMnBzWHY1N1RDUVlsR0M0TVNUQmFXNjAzb28xZGI2cXpxVnRmWW5NNTZBcEJ3OW94b1Z3Uk1ZbEdOSzM5MVZ5aUtpakJpRVl3bWxQZExiSll0U1RhN3FIaUErdStvUVREaFNFSkJ0cHZoZFQvR0hXeHY5eld4UmkwdFBpRXRId0p4YlZzWGhXVVlFUWpHSFJ3R3VPaDBnVjVrVE9lTWkvaGhQeERDWVlMUXhDTXMxcXRWZ3p1OHJldnB5eVBqd0h3c3BWaC9TdVZXaktkQ3dTR0VveW9CQU81cDgzM29wK2VrOFdzRmRGK3dhOFNWb0xod2hBRUEzN1dUUEJiUkhUY0FleEd2SlROSGZRTU5jZjZCcytQOWVibnhmcWVQSldYMmtDWnpIZ2ZFeGpDR1FJbEdORUpCc0YrRUpFdWRzdmkxb2JpVDV5S2Y5U05ZT2pXWmpUeWZhSFJ1ZDlBSG90WXBXQTROeHFKWTFMZlROVDVLMndlaTYwZk1pQVVENEtqQmZibWo4YjY4c3RqMnc3YUQycWhmVS8weHk2WnJ6SFMycXVscFRObCt3eUl1aGNNakJVNjYxUU5tMmN1UG9QRFJZVFJCanBiUjJNQU9WOUhaek9ROTgvdy9mWXdpUEh0ZmplMGJ2MkZrL0NQZWhHTU9yc09vL0x0NjdvMVhEZ1Z1aUUvQndMeGp4S3hLT1hHMk02ZHRpMzZ3OE9SZG5HUDdUY2drRnVkQzhiVXZBNmpsa2lrTzgrVHRnMklNWFNZemZ4RENZWUxxeEFNTDdldm83N3R0bkYvLzBuWWt0Z2hFWWx4SExxYXpKMnRqRXFiczlpeVNXWG4ydjREUUFsRy9hT3NZQmpXQVRiekR5VVlMZ3dzR0xscEtMdFY2cE5KSFZaNFlITGYvbmZKQldJQ2gySGRRRVhpNmV3bE1yOGxkSjVIWXR2N2hSS00ra2M1d1VENzdHVXovMUNDNGNLQWd1SHA5R2RLWE1YbUVJeDh1MFFjWFBqWWErMHltVXdqMnV0eHFlOGlvbzRYMnZZK29RU2ovbEZobCtTUGJPWWZTakJjR0VBdzZIb0s3QTZVbmNpbzU4R21wc3RlZUIxRDc5Qlg1ZUlnNGYzRHAzT3BHT0xNbC9rZnh4Mnh6RnJmajhWWGdsSC9xTEJMc29YTi9FTUpoZ3NEQ0VZaVZmNzJkV2JwSmR3OSs4NlJpc040OWc3dWgzVmhGNFBGNlFtSi8xTHExZ0l1NGhtVkJBTVQ5dTd4NzB3SmcvVFlmVTZoTEpSZ1ZFYUZYWklIMk13L2xHQzQwS2Rneko1dG5nS2ZCNlMrbVBqLzBJd1pIUy9uSWc1R1J4c2hCZ05Ta1NqbFlpNVJBUHJ1VWxtY1ltSnkvWG5HM0hFeEs2RGlGa1pFeEJqWXlDbVVSU1hCUUR1UG9BNWJvMmJTeUw2ZFUvSUUzaXFVbmdZTm0yZ0QxN04wK0c4VnArUWZTakJjNkZNdzRycGxTZjBVRVRGTk5pOUZ6L0RNV0cvK2lFUWtIUGJtTjhTMmJadDQrYmh6ajBuNUozaUJkRnMxbC9BRTFMMnVCYU5XVE9yaUE1eVNKeUR2NzhyODFKeWVyeTZXUUFtR0MzMElSdE9jM0dsb3A4TlNQMlBVeFZObDEvVHI4cTJ4dnZ4NjhQa2lzZmduZmw4ZjZ4OTBmUVVsNG41R0dxK1l1amh5NXF6dTEzQ1JpbENDNFkxMUtSajBXa2d0Ri93bVJTVVlMdlFoR0Y0bUdBYUxZUFB5MkRnMFBkWXo5SDdzcHN5TjlReFVmQzBpWGZ5RlB0b25pMWxNR3F4Y3BDS1VZSGhqM1FrR3hDS3BXKy9tZElKQkNZWUxQUW9HdllRYTl1WGY3MWxwNjZKS2xIdDgvUXNVUiswWFRYdUFFZ3h2ckEvQm9MZnIyUWZIci9HemxlbUtLU01ZdW5rSFRTekVsTDQrc0ZhQ2dmbytCKzdXak96bjJMUXNuTmNHaUQxVVR1YlBvZG5GNXBHQXpwZ2d2dXRXQnVyNkg3dE91cmlVaTVRRlhTV0tNdC9IQk41RWF5WFVyK3c5TWNFcGp2R0s0dmZJYndWZHc4SXBsQVdOQlpTNUR2V2hONVhuNGVkb3FkOG9pRnl4MndrK2l1LzBJdWlsOUt3VFRza1Q0bWx4RHRyelJtNVhqUFVvMnBYZTZHNDlnanh2dytmQ2hOR2hjZmh3UUM5amFUTEVHOXhvR0ZlV3ZpWStVdVNtMlErY29YZHk2TllpTk93eVZQckhHQmgzSm96dVVDc2VUNW1YUWZGL2poZy94T2ZYTmQyOGdqbzBhSDNwTEFsTk5HZHRMNVlpNTV2UWdiZWo0KzZnLzlnc01xQU9IM0hhU2Z3RWJYY0R2bWVUaHZVcFRlOTZ5NFF6TTc2UW05WTBaOUZwZFBjbTZ2TnBzQXQ5c3R4cE8rdlg0RWJFMjBvVENjc0dTb25sK0IvZjZXYS9WY1Y1MGFTUHg3dE9EZUVCeGcxMHh5K2Rrb1hnZkFneEZpRGUxOUFPMzBNL3JFUU85eUxtQTRpL0JiKzNsK2Jua1BJSE40UHJVTCsxK0Z3QjIydmhveDFpZjFHODFYcGJ2QTI1WmpLK3IybHhSMjRhMWQ4UlB6RWZ1d29XY3NFV2lKTXpZaitJM3crVnRLc2hIZ0gvQVBaU25xalR6Zmk4eGg2N3VuVXVQZHJBMjhOeFlySC9BejN0STRqNStUT0xBQUFBQUVsRlRrU3VRbUNDIiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiZWZiOTZiMTAtYTllZS00YjZjLWE0YTktZDMyMTI1Y2NkNGE0In19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTE3IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTYWZlTmV0IGVUb2tlbiBGSURPIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDAyMDcwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTE3In0seyJhYWd1aWQiOiI0YjNmODk0NC1kNGYyLTRkMjEtYmIxOS03NjRhOTg2ZWMxNjAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjRiM2Y4OTQ0LWQ0ZjItNGQyMS1iYjE5LTc2NGE5ODZlYzE2MCIsImRlc2NyaXB0aW9uIjoiS2V5WGVudGljIEZJRE8yIFNlY3AyNTZSMSBGSURPMiBDVEFQMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCYURDQ0FRK2dBd0lCQWdJVUpVcjVUQkwrUi9yRmZ6VGZHcTh0RGRhd0F3a3dDZ1lJS29aSXpqMEVBd0l3SVRFZk1CMEdBMVVFQXd3V1MyVjVXR1Z1ZEdsaklFWkpSRThnVW05dmRDQkRRVEFnRncweU1EQTNNamd3T1RRME5USmFHQTh5TURjd01EY3hOakE1TkRRMU1sb3dJVEVmTUIwR0ExVUVBd3dXUzJWNVdHVnVkR2xqSUVaSlJFOGdVbTl2ZENCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJNS0kya0cram1BN0hhV29wUGRudmhCd1JjYnFnK21KUlNhT2hTcWRCZkkwMHNjSXgzOXllaHM0TkNJRWR6bE9nQ0V0d0hHaFRGeklGQVhhaGdTaFVwZWpJekFoTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0N3WURWUjBQQkFRREFnSUVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJSE05VzlvbkNIQ0l5aWx3QlZrVitSVTFEc1RKTmliZnhhNlYvSEpGUGVRVUFpQjY5cU8vdzlieGVicStaZDZCdGtTWGpUM0hLZk5lWFlQN1A5Yi93TXpwalE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFNZ0FBQURJQ0FZQUFBQ3RXSzZlQUFBSlZFbEVRVlI0MnUyZFRXOFdWUlNBKzQvOFMvd1FkbllscktRcjZhcUpDNDBzTU1GRURRc1dKRFlhVWpRZzBWQ0pSQXNTQlFvcVJkcXhaK0tRNmZqT3pMMHo5OXg3enJ6UGsweWtXTnAzMm5uZWMrNDU5Mk5qQXdBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBS0k1ZnZIVFlmdmlKd0lyT2JwMXUzcjU0Y2ZWNGRibDZ1bjV6YmZYaSsyZDZxOXJYMVN2Nzk2cnZJdHc4dWhHZFh4L3B6cisvdjNxK050M1YxOEpKTG43K3kvVnRmMjlhdnU3RzlYRmJ6NnJ6dC84cE5yYSs3TCsrUHJQZDZxRGwwL1BMZTM1a2Z0cTM2OWNtMTlkOVgvUGYxKy9VVDNidkhCR2lyN3IrY1ZMYmtTcGpoNi9jL0xyNTlYeER4LzB5NUJZa0Z1UEg1eDVRSVl1K1R6NWZPOWlYUG54NjZEN2xVdGsyWC8ybTQ5N2ZuTndjRTRlK0JBeHVwZEVHcXYzVlVzeEZDR1VCSkVJRWZxZ2RCOGFqMktJM0JJaHB0eXpSQlR6NlZSbzFPaTdKQlV6bFQ0OStHaTZGRE1Fa2RSaDZvUFNUa1U4cFNDU1BzNjVYN2trOHBpTkhIUGxzQ0pKUGJDV01VVUtNU1lLTWpWeWVKVWtKcVVhdTBRMGN6ZllIWVRQdldRTVUwU08xR0pNRUNUbHcrSkJrdFQzSzVlcE1ZbWtWaW5sYUs2c1l3eXBSR21JRVNtSS9HSlRQeXlXSmRHUXc5d1liT3FnM0VJVWthcFVkRVZLVVJDdEI2YTVMRlc0dE8vVnhCdUNqRDAwNUdqS3Y2cFI0NCs5NnZqT2UvcHlSQWd5ZDJEdVJSSnRPY3lNUlY3ZDNLMjBCTkZNcytxeWJRNHhJZ1RSU3Erc1NaSkREak5wbHFSQm1vTDhzNS8rRjVtc2RPdFlrRktTNUpLamFab2lTR3lWS3NkNFk2SWcwdWpLS1VodVNlUWRQZmY5SVlnSE9ZeEdrSnlTcE9ycnhGenlQUkhFZ3h6R0JkR1dwSVFjakVGaXhod1ByNWFWNC9RS2ZhMmxCTkdTcEpRY1p1Wm1XUmRFdlFFWWNFbFJ3T0lnVm5zdVUwazV6UFJCTEF0U3o2a3FMRWZzTkJOWjgxSHlvVW9sU1drNVRJdy96QXVTcXdrNEZEMGV4ZWZCSmFvOUtTVXBMWWVwdVZoV0JTblM2K2pLY1RyMm1mcHp6ZEZSMTVERWdoeW1wcnhiRk1SQ2FpWFRXT2I4WEV0V3RLWStiQ1g2T0daVEs5T0NGRTZ0NXNyUmtHTFJWRzVKU2hZWnpNbGhVWkRTVmF0VWNpREpBdVN3S0VqSjZCRWpSOHgyUUVqaVZBNXJncFNNSGlGeTlDM2xyUXNLSTdKWWtTVG1ZY3doaVdrNXJBbFNLbnFFeUJIU3pSOHJDU09Ka3cwYUxBcHk4bVRYZEZxVnFqVHNVWklVdTVXNGxNT1NJTFAyck1veDVrallQL0VvaWN6eldqczVyQWhTcnl2UEtjZHBLaWZmVTdONGdDUUxrTU9LSUZtWHp3YkswYTFTMVJKSFJybVFUcnlGem5VdVNkekpZVVdRYk9sVnFCenR0U2VkZnhPN0xnVkpITXRoUmhDcmNpU1NSRDUvblNWeEs0Y0ZRZXF0ZXl6TDBmTTFwS1RiWEVIQ0JEUVZMVWdpR3lXRXJzTUlrY1MxSENZRTBWNHRHQ2hIVUpQeU5CVWNMRFFNaVJMWWRiY2dTY3d1amtQRkJ2Tzd0WHNRUkhXdGVVUzFhbFNRRlY5TGVqZmR2K3RMMFdKK0p4NGxhVGNVNWZYTHdyR05KVkJjRUNPbDNNRkdaVGU5NnE1VkVTbGFFZUxNLysrT1h3TG5jSG1UWkxFc1VwQ0FRWEZ3dXRkNndPczBhcUFmMG00ODFsOXJhSER2Wk9DKzlwS1VGRVJsWVZSQTVPZys2UDk3c0ZjOHhHTnlqSFhuUTZwalNJSWc2b0tFckNGZjFYZHAvN3Rha2dseXJKSmtkUEErRWttc3JFeGNXMGxLQ3FJeHZYM09ZSHhWVXk5V2ptN1ZLbVFTNXRpY01BdFJwSkVFUVR3TGNuOW5QSHFNVk0zYWtreVdvN1dYVmxDVUhIbmRGdGFLTDZhdnNjNkN5Snl1RkYzNzNtclZSRmxEeGsxYTg1OFdmZklUZ3BRVlpNNTVoMDBrQ3AycDdDV0NJTWlhcDFoSkJPbEVoTkhwTkNPdlcyUEJFaWtXZy9UcDM3TVpZRStaSjlaVHVoMzZXaktRSDNyTk1qK0tRVHBsM254bDNxR0JkNmZzR2pWWGJFVmpzRDNvWHluSndQd3V5cndJb3JLRFlteWpzSzh4R0NWSnQrUGVTdVY2SlFsb0ZGcUlIalFLbHpiVlpFbzNmY1ZEUFBydTM0b0NvOU5SSmt4L29ZdU9JQnVXMXAydkVtRlVrb2lPZTh3NUk4aUJJTE5McWFrbDZVdjV1aDMydDR1bHVsTkt4cHFLQVZVMkszTEVidWdtMWExbVhRalQzVk11bU5MZXNDSFJtcEN4ZC8rUWRmVWhFY1NiSEVNTHBoWlJFbWJKYlZ3SldLSkpIVDJlN05iL1BUUDJHSkprZ2V2U1E3WXVZc250T216YUVGbmFqWlZESHJRbHlzR21EYWtFeVhYRXM0d1JBbGJ6SlpVa1FBNXZHOGhOZWMxcysrTmw0N2pRbmR4blNxTDFvSG1VZzQzanZHMDlxaWdKY3JEMXFNN20xYm5Tck5oakQyS252QWVrY09zcUI1dFh6em4rSUVjMVMvRnNrRkJCUEo0MkpldFJVcjltOHdmbldCT2tqaUxlRDlCeHNxTjdyQnhyZTdxVU5VR3NIOEZXUjdtZU11NVNJd2RIc0hHSXAvb2huakpsSFRrNHhITVp4MENQTEY2S3hjcDZjcXR5Y0F4MHBDQ2g4NXBVSlhtWVp1VWNjaXhBRXBPQ0tDMmt5aW1KekdiMUpvZUYxMnhPRW91Q1RPby9HSlBFMjVqRDBvUkpVMzBTcTRKWVNMVkN0eExxSWx2amxIN0laQ2VVcVQ5M0M1S1lXVTlpV2hBRHFWYk00VGROT2JmMHd5WGppTG5QUldsSlpDMCtnb1NrV2dGNzI2cGZnU3NCaGZaQk1sN2xzQ0tKaWVXKzFnV0pudXFoZElXKzFwSzdrS1NVdzRJa0pvNXc4eUNJQ1VrQzA2d2x5VkU2S3ByWTV0U0xJUFdZcE1DTTN4aEJTbTN5cGlsSFNVa1F4RlA1MTZnZ09lUW9KUW1DZUVxM0RBcVNVNDRTa3BnUTVOWE5YVlZCdEY1MzlqbGJoc1lnMG9Rc0lVZHVTVXdJOHViZzRKeVdISWRibDFWdnNPNlQ1SnI5R3lpSWRoWEx5bTZIT1NReFVjVVNubCs4cENLSXBHODVYci9xN295UmdtaWU1V0Z0SzFCdFNjemM2OUd0MjhubGVMWjVJYXY5ZFVOUk01cEVkTlBYYVo5Y0xVbk1uV1FsNlpESDZKRnRBQjhoU09vb1luMFRhWTBqNHN6ZHI0eEY1RjAvaFJ3dnRuZUsybDl2STVRNjdZb1FKR1VIMnNzTzZ5blhrWmdaZTJoSW9qMHdMeFpSSWdWSklZbTM0d2RTU0dKK1N5Q1JaR3E2OWVlVlQ4M2VYRDFHbWRPSm55Q0lNSFhxdTV0dGNUcklOUFdwYTJITVJvNitCbUpvTkpHVVNxTWhxQ3BMYkFvMlVaRG1uVFcwL0N1ZlY3TEhVV0x3N25wejY5ZDM3OVdSUVNSb3lzRVNZZVJqa1VnaWp1ZGZwRHo0OVhFR2tvb05TVE5Ea0FaSmwyUUFMMUdsU2I5RUNQbFkvbjR4aDg1MDNoeEVBTG5ISnJMSW4rWHZYRVVNV0RIUS8yOXJueFJ5QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQWdHLytCUUI5ZDhINTlDWklBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI0YjNmODk0NGQ0ZjI0ZDIxYmIxOTc2NGE5ODZlYzE2MCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTEwLTE1IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJLWDkwNiBTbWFydCBUb2tlbiBGSURPwq4iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMTAxNTAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTAtMTUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTEwIn0seyJhYWd1aWQiOiI0YzBjZjk1ZC0yZjQwLTQzYjUtYmE0Mi00YzgzYTExYzA0YmEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjRjMGNmOTVkLTJmNDAtNDNiNS1iYTQyLTRjODNhMTFjMDRiYSIsImRlc2NyaXB0aW9uIjoiRmVpdGlhbiBCaW9QYXNzIEZJRE8yIFBybyBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCMlRDQ0FYNmdBd0lCQWdJUUZRTktXKzd6YmcvN2QrbFR5cklXd0RBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERUSXlNRFl3T0RBd01EQXdNRm9ZRHpJd05USXdOakEzTWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXNGWUVFaGlKdXFxbk1nUWpTaWl2QmpWN0RHQ1RmNFhCQkgvQjd1dlpzS3hYU2hGMEw4dURJU1dVdmNFeGl4UnM2Z0Izb2xkU3Jqb3g2TDhUOTROT3pxTkNNRUF3SFFZRFZSME9CQllFRkV1OWh5WVJyUnlKendSWXZuRFNDSXhyRmlPM01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDQjBORlFTTjB6NGxXei95YzM2ZXdyVEN6dHRLL3FGdmxhUE9LaCtUMW82d0loQVAwb0tLQStjaWNzRHkzWTNuK1ZsUDhlQjNQQnpNa2h2Vy85SVNYQ3crVkIiLCJNSUlCMlRDQ0FYNmdBd0lCQWdJUUZRTktXKzd6YmcvN2QrbFR5cklXd0RBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERUSXlNRFl3T0RBd01EQXdNRm9ZRHpJd05USXdOakEzTWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXNGWUVFaGlKdXFxbk1nUWpTaWl2QmpWN0RHQ1RmNFhCQkgvQjd1dlpzS3hYU2hGMEw4dURJU1dVdmNFeGl4UnM2Z0Izb2xkU3Jqb3g2TDhUOTROT3pxTkNNRUF3SFFZRFZSME9CQllFRkV1OWh5WVJyUnlKendSWXZuRFNDSXhyRmlPM01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDQjBORlFTTjB6NGxXei95YzM2ZXdyVEN6dHRLL3FGdmxhUE9LaCtUMW82d0loQVAwb0tLQStjaWNzRHkzWTNuK1ZsUDhlQjNQQnpNa2h2Vy85SVNYQ3crVkJNSUlCMkRDQ0FYNmdBd0lCQWdJUUJUbWszWndpbEZYanNaeXdIRG5NZ0RBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERUSXlNRFl3T0RBd01EQXdNRm9ZRHpJd05USXdOakEzTWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRW5mQUtianZNWDFFeTFiNmsrV1FRZE5WTXQ5SmdHV3lKM1B2TTRCU0s1WHFUZm8rKzBvQWovNHRud3lJTDBIRkJSOVN0K2t0anFTWERmamlYQXVyczg2TkNNRUF3SFFZRFZSME9CQllFRk5HaG1FMkJmOE81YS9ZSFo3MVFFdjZRUmZGVU1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUJ5Uno0T0FsUlo5SHo5S1Y3ZzJRTnRDMEM4SnhIL3hMSlk4RlpFbXRKM3NBaUVBc3JlVDArZU5rTmNVakk5aDVPUENvSDZObXNPa2d2RUFCSlpyRjA3QURrWT0iLCJNSUlCMkRDQ0FYNmdBd0lCQWdJUUJUbWszWndpbEZYanNaeXdIRG5NZ0RBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERUSXlNRFl3T0RBd01EQXdNRm9ZRHpJd05USXdOakEzTWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRW5mQUtianZNWDFFeTFiNmsrV1FRZE5WTXQ5SmdHV3lKM1B2TTRCU0s1WHFUZm8rKzBvQWovNHRud3lJTDBIRkJSOVN0K2t0anFTWERmamlYQXVyczg2TkNNRUF3SFFZRFZSME9CQllFRk5HaG1FMkJmOE81YS9ZSFo3MVFFdjZRUmZGVU1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUJ5Uno0T0FsUlo5SHo5S1Y3ZzJRTnRDMEM4SnhIL3hMSlk4RlpFbXRKM3NBaUVBc3JlVDArZU5rTmNVakk5aDVPUENvSDZObXNPa2d2RUFCSlpyRjA3QURrWT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRkFBQUFBVUNBTUFBQUF0QmtybEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFCSFpwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTURFMElEYzVMakUxTmpjNU55d2dNakF4TkM4d09DOHlNQzB3T1RvMU16b3dNaUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenBrWXowaWFIUjBjRG92TDNCMWNtd3ViM0puTDJSakwyVnNaVzFsYm5Sekx6RXVNUzhpSUhodGJHNXpPbkJvYjNSdmMyaHZjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5d2FHOTBiM05vYjNBdk1TNHdMeUlnZUcxc2JuTTZlRzF3VFUwOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXRiUzhpSUhodGJHNXpPbk4wVW1WbVBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWU1pXWWpJaUI0YlhBNlEzSmxZWFJ2Y2xSdmIydzlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFMElDaE5ZV05wYm5SdmMyZ3BJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4TmkweE1pMHpNRlF4TkRvek16b3dPQ3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2U0dsemRHOXllVDBpTWpBeE5pMHhNaTB6TUZReE5Ub3pNRG95Tnlzd09Eb3dNQ1lqZURrNzVwYUg1THUySU9hY3F1YWdoK21pbUMweElPVzNzdWFKaytXOGdDWWplRUU3SWlCNGJYQk5UVHBKYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pKRk56RkNSa1pEUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakpGTnpGQ1JrWkVRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lqNGdQSGh0Y0UxTk9rUmxjbWwyWldSR2NtOXRJSE4wVW1WbU9tbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNa1UzTVVKR1JrRkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUlITjBVbVZtT21SdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1rVTNNVUpHUmtKRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpTHo0Z1BDOXlaR1k2UkdWelkzSnBjSFJwYjI0K0lEd3ZjbVJtT2xKRVJqNGdQQzk0T25odGNHMWxkR0UrSUR3L2VIQmhZMnRsZENCbGJtUTlJbklpUHo0NzdKWEZBQUFBWUZCTVZFWC8vLzhFVnFJWFphdkcyT29xY0xHMnpPT2t3dDBCU0p0cWxjWFY0dSthdXRsV2hiems3UFVBTVk5SGNyS2p0TmJxOGZlQWw4YUJvc3p6OXZwZGpzR0dxdEYzbjh1VHNOU1pwYzZKc05UNSt2MHhZS251OFBmZjUvTDQ4ZmcvZnJpY3pKZ1lBQUFEQUVsRVFWUjQya1JVQ1piRElBakZYWk9ZMVRhdE5jMzliemtzU1ljM3I0TUU0Zk1CQWFENnpsOHkvOVRPZ2V0OGQ1amZONzhid00vZERDUnBSNTIxelhmb2pISjA1SUl5aEJBVVNWQU9OZEd6Qll0MmY3S0ZyZmtKYUFrSGg5RlpoY0RYSFJrVEtvOU1MaWhHYWF2SW1uVjNxeUVYMEVwcmd6LzREd1VEN2tDSFJuZDhRRk40M0dvNFVWbUREZ3phNHcyN29pemRBMitjSyt1dVVwampvMit4d2MvNDJXNTB4NUxHWWVEQnNSMEhWSXg1eDhpRjYwQ2JsYlRFRWtGcjI3Yk5EQlVWU3ExT0tWUGJFNjJiM0VIOEZxQmc1T09PRXVjMnQ4WkppcU1PdUdwK2NLamc3d1ZHY2VvenFONHB4Z1ZQUWtqRllnYlZKS0RVaERDallyYXdQNXE0RVRnQzlmSU1SSHRpdHBRY0N2Sk9FTGNiTXNRZ25jaVJrbGpweVFqdkc0NGpxQlVFVEZpQmkxUEVJeWVrT3pzVytUeTVjTEhvczVSK2RNUzFMdFNTeGYzZ1FIY3pSMkNJNGdNTnBXNElSQTFRTWE2dEo0K0M2dUh1R0U4bU5ESXlGcWcvT1AvTU1VdWVTNklxOFM5MGRBZUJKU0V5L3FLa0srQk53ejhjWVk0amI1SjZ1NGlXQ0kyQjFaNTZMVzVrRWM0aGtkTXBzdlVDNTU4NVNYMFF1YmNnTnF5ZmdERkVjVHQrNDAvMFM1Tngwd2FDdzNPS2tjT2JBNUluMEFZcDAxcGpqdzJuNjI2VURqdEh3YTI4aUh1VEtxdHJ2K3JlVzQxTlo2aUdscjd1dUxKQ2ZrRnRjdGNHMDRzZ20xZU5TK1phRG5wYVRFckdveVg1SksyaU16OHhzMG5Pd1dHY1BETjQ5cWFDZDRiekpvekRabS9hQksrRW96THcrWGhOQmlZd0hmMHNpT3UxWFBrRy96S3d2cVlLY2ZTd0RFY0gvb1VlMDdlcy9XUThySXlnMkRPWGo4dGprWmR1REIvYjhoekRsbE1NT0NTNUJFbmQ1MzRmOHRpM1VaYzRrTXMzeEx5YWZNU3NKaGRHOFhQcWpOazV0QWdPMjVmZUtDaG5WZERqL0owRk1rT3NVL3hNQnYwd0ZoWWVFR2ZWSDEzZnVEVTB5REZMYTRmYzdSbldIQmZ1VEZWMnRFbU53YWRjN2FjM1VZMmpmQmw3SFQzNmZlMzRpUU81bU5DRkZCVzA3S2pQZ3FoT0xVMDF2WjhQdWVaMkpDbEZaTjhqa1VzNjl1a2E5ZVBwNitFZkw0QUY1K055d1NiaXJIdGNCOE1sL2drd0FFamtLNjRLakhQZUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZEJsb2IiLCJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjRjMGNmOTVkMmY0MDQzYjViYTQyNGM4M2ExMWMwNGJhIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInBpblV2QXV0aFRva2VuIjp0cnVlLCJub01jR2FQZXJtaXNzaW9uc1dpdGhDbGllbnRQaW4iOmZhbHNlLCJsYXJnZUJsb2JzIjp0cnVlLCJiaW9FbnJvbGwiOmZhbHNlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOmZhbHNlLCJ1dkJpb0Vucm9sbCI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJ1dkFjZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZSwiYWx3YXlzVXYiOmZhbHNlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMSwyXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV0sIm1heFNlcmlhbGl6ZWRMYXJnZUJsb2JBcnJheSI6MTAyNCwibWluUElOTGVuZ3RoIjo0LCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoyLCJwcmVmZXJyZWRQbGF0Zm9ybVV2QXR0ZW1wdHMiOjUsInV2TW9kYWxpdHkiOjIsInJlbWFpbmluZ0Rpc2NvdmVyYWJsZUNyZWRlbnRpYWxzIjoxMjh9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMTEtMTMifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTExLTEzIn0seyJhYWd1aWQiOiI1MzQzNTAyZC01MzQzLTUzNDMtNjE3Mi02NDQ2NDk0NDRmMzIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjUzNDM1MDJkLTUzNDMtNTM0My02MTcyLTY0NDY0OTQ0NGYzMiIsImRlc2NyaXB0aW9uIjoiRVNTIFNtYXJ0IENhcmQgSW5jLiBBdXRoZW50aWNhdG9yIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsiZnItQ0EiOiJTU0UgQ2FydGUgw6AgUHVjZSBJbmMuIEF1dGhlbnRpZmljYXRldXIifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MjU2LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlTTURDQ0VCaWdBd0lCQWdJV0FLb0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBREFOQmdrcWhraUc5dzBCQVFzRkFEQ0NBalV4RXpBUkJnc3JCZ0VFQVlJM1BBSUJBd3dDUTBFeEdEQVdCZ3NyQmdFRUFZSTNQQUlCQWd3SFVYWERxV0psWXpFYk1Ca0dDeXNHQVFRQmdqYzhBZ0VCREFwVVpYSnlaV0p2Ym01bE1URXdMd1lEVlFRUERDaFR3NmxqZFhKcGRNT3BJRWx1Wm05eWJXRjBhWEYxWlNBdklFTjVZbVZ5SUZObFkzVnlhWFI1TVRzd09RWURWUVFGRERKT1JWRWdNVEUzTXpRNE9EWTBOU0F2SUVOT0lERXdOalEzTnpNdE1DQXZJRUpPSURjMk56TTBPVFk0TVZKRE1EQXdNVEVxTUNnR0NTcUdTSWIzRFFFSkFSWWJhVzVtYjJOaFFITnRZWEowWTJGeVpITmxZM1Z5YVhSNUxtTmhNUm93R0FZRFZRUVhEQkVyTVNBb05EVXdLU0E1TmpRdE5EVXhNVEVhTUJnR0ExVUVGQXdSS3pFZ0tEUTFNQ2tnT1RZMExUYzNOell4RURBT0JnTlZCQkVNQjBvMlZ5QXdRVEl4Q3pBSkJnTlZCQVlUQWtOQk1SQXdEZ1lEVlFRSURBZFJkY09wWW1Wak1STXdFUVlEVlFRSERBcFVaWEp5WldKdmJtNWxNUm93R0FZRFZRUUpEQkV4TVRjNUlHUmxJR3duWlhod2NtVnpjekV5TURBR0ExVUVDd3dwUVhWMGIzSnBkTU9wSUdSbElGQnZiR2wwYVhGMVpTQXZJRkJ2YkdsamVTQkJkWFJvYjNKcGRIa3hOVEF6QmdOVkJBb01MRk5UUlNCRFlYSjBaU0REb0NCUWRXTmxJRWx1WXk0Z0x5QkZVMU1nVTIxaGNuUWdRMkZ5WkNCSmJtTXVNVVl3UkFZRFZRUURERDFUUTFBZ1FYVjBiM0pwZE1PcElHUmxJRkJ2YkdsMGFYRjFaU0F2SUZORFV5QkRaWEowYVdacFkyRjBaU0JRYjJ4cFkza2dRWFYwYUc5eWFYUjVNQjRYRFRFNE1EVXpNREUxTXpFMU4xb1hEVE00TURVek1ERTFNekUxTjFvd2dnSW1NUk13RVFZTEt3WUJCQUdDTnp3Q0FRTU1Ba05CTVJnd0ZnWUxLd1lCQkFHQ056d0NBUUlNQjFGMXc2bGlaV014R3pBWkJnc3JCZ0VFQVlJM1BBSUJBUXdLVkdWeWNtVmliMjV1WlRFeE1DOEdBMVVFRHd3b1U4T3BZM1Z5YVhURHFTQkpibVp2Y20xaGRHbHhkV1VnTHlCRGVXSmxjaUJUWldOMWNtbDBlVEU3TURrR0ExVUVCUXd5VGtWUklERXhOek0wT0RnMk5EVWdMeUJEVGlBeE1EWTBOemN6TFRBZ0x5QkNUaUEzTmpjek5EazJPREZTUXpBd01ERXhLakFvQmdrcWhraUc5dzBCQ1FFV0cybHVabTlqWVVCemJXRnlkR05oY21SelpXTjFjbWwwZVM1allURWFNQmdHQTFVRUZ3d1JLekVnS0RRMU1Da2dPVFkwTFRRMU1URXhHakFZQmdOVkJCUU1FU3N4SUNnME5UQXBJRGsyTkMwM056YzJNUkF3RGdZRFZRUVJEQWRLTmxjZ01FRXlNUXN3Q1FZRFZRUUdFd0pEUVRFUU1BNEdBMVVFQ0F3SFVYWERxV0psWXpFVE1CRUdBMVVFQnd3S1ZHVnljbVZpYjI1dVpURWFNQmdHQTFVRUNRd1JNVEUzT1NCa1pTQnNKMlY0Y0hKbGMzTXhNVEF2QmdOVkJBc01LRlpoYkdsa1lYUnBiMjRndzRsMFpXNWtkU0F2SUVWNGRHVnVaR1ZrSUZaaGJHbGtZWFJwYjI0eE5UQXpCZ05WQkFvTUxGTlRSU0JEWVhKMFpTRERvQ0JRZFdObElFbHVZeTRnTHlCRlUxTWdVMjFoY25RZ1EyRnlaQ0JKYm1NdU1UZ3dOZ1lEVlFRRERDOVRRMUFnVm1Gc2FXUmhkR2x2YmlCRmRHVnVaSFVnTHlCVFExTWdSWGgwWlc1a1pXUWdWbUZzYVdSaGRHbHZiakNDQWlBd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJTkFEQ0NBZ2dDZ2dJQkFMU0NZdkh4YTZod2FDaXNTcHF6UzllWWRjWjhoeldyeitMN1VWV21wdjJGTjdpeTI4RTV3VmZxckQ5eTJZL2w5TGtRd29TSmUyeDJvQ0lVcDZrM1BLaEg0T1p4aEIyWDU2OGx1SXhQZzY4VUt2QWVZc3pmaEZXbTJFRlNlaDMxdjhzcW85V2VCemIwUmVzem04NlJqSkxGY0NDa2FhVlVWOHBERkMwKzFkR0NsS2JRWHIvZGpBNFZ2SXRYTnp2T1VuTWk1VTFsVUhsNEUvRmlacGNlOHA3bzdEYk54NHdpRW84bGtPNDVKRkxiZklvN1J0K2w4YTA0SVYrc01Ja2JlWU1QVzhxdExMUmhpWDU2c21wVHdrZkpUbGlkVDlER1pvWG5ZQ25RTDJXd3NXQnNzZGlpYnlKSlFYL2ZUSWJHNzY0VmpqZks3ZW84QUpJc2dHSm9LS2YxcCtKL2RFeVpYUUxmS2tWajZiRStnR2c2UUE3a1pSeklGbkcrTlI1SnNZcXFKMlNQMjl5UlMvRVBxcVBjYWtGY095aDZ3dC9wckVHa2NHS2RCN1RYMTZWOWphRFlkdlpyLzVIUW1iUlZ0YVk4WWJIQUFrRXV3NUFFOHhWbHIvdnZkeHpCOHNKNDFjYVBrTDBKcTJYWEk0OXZ5RWV3NjFoV1ZTWmdXUGl5VGtZN1h6NDM3MmVuTzErUjZPZnBJTjh5bXRVek4wUDlsZlYyMG1SaElWUUU1OWQ2dWJnU2ZPTEw3eUFTa3k2Q3UvZGlRUWFBdWx1alFHWTh2b0RQeXJPa0ttays3Mm95K1lyaXE3aUtVc3RacmdwLy8yMmg4SW9hOEdhWE40TDUrN09oY0wrU3hjY1BsbStpSVRZQmtuME1UR1U4R1B6ZVR2VE1hSlRUaldXakFnRWxvNElKUVRDQ0NUMHdIUVlEVlIwT0JCWUVGTXBaUFhWR05ReWpQV3pNV1R0ZnZ6YlBJRzV4TUI4R0ExVWRJd1FZTUJhQUZOcHlQbWlETkFkcUFaSFNwYTgrSEUyaTRmNU9NQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdDd1lEVlIwUEJBUURBZ0hHTUlJQ21BWURWUjBsQklJQ2p6Q0NBb3NHQ0NzR0FRVUZCd01CQmdnckJnRUZCUWNEQWdZSUt3WUJCUVVIQXdRR0Npc0dBUVFCZ2pjS0F3UUdDaXNHQVFRQmdqZERBUUVHQ2lzR0FRUUJnamREQVFJR0NTc0dBUVFCZ2pkUUFRWUlLd1lCQlFVSEF3TUdDaXNHQVFRQmdqYzlBUUVHQ2lzR0FRUUJnamNLQXcwR0Npc0dBUVFCZ2pjVUFnRUdDQ3NHQVFVRkJ3TUhCZ2dyQmdFRkJRY0RCZ1lJS3dZQkJRVUlBZ0lHQnlzR0FRVUNBd1VHQnlzR0FRVUNBd1FHQ1NzR0FRUUJnamNWRXdZS0t3WUJCQUdDTndvRERBWUlLd1lCQlFVSEF3a0dCMkI4aHZkb0FnUUdCMkI4aHZkb0FnVUdCMkI4aHZkb0FnY0dCMkI4aHZkb0FnZ0dCMkI4aHZkb0Fna0dCMkI4aHZkb0Fnb0dCMkI4aHZkb0Fnc0dCMkI4aHZkb0Fnd0dCMkI4aHZkb0FnMEdCMkI4aHZkb0FnNEdCMkI4aHZkb0FnOEdCMkI4aHZkb0FoQUdCMkI4aHZkb0FoRUdCMkI4aHZkb0FoSUdCMkI4aHZkb0FoTUdCMkI4aHZkb0FoUUdCMkI4aHZkb0FoVUdCMkI4aHZkb0FoWUdCMkI4aHZkb0FoY0dCMkI4aHZkb0FoZ0dCMkI4aHZkb0Foa0dCMkI4aHZkb0Fob0dCMkI4aHZkb0JRRUdDR0I4aHZkb0JRRUJCZ2hnZkliM2FBVUJBZ1lJWUh5RzkyZ0ZBUU1HQ0dCOGh2ZG9CUUVFQmdoZ2ZJYjNhQVVCQlFZSVlIeUc5MmdGQVFZR0NHQjhodmRvQlFFSEJnaGdmSWIzYUFVQkNBWUlZSHlHOTJnRkFRa0dDR0I4aHZkb0JRRUtCZ2hnZkliM2FBVUJDd1lJWUh5RzkyZ0ZBUXdHQ0dCOGh2ZG9CUUVOQmdoZ2ZJYjNhQVVCRGdZSVlIeUc5MmdGQVE4R0NHQjhodmRvQlFFUUJnaGdmSWIzYUFVQkVRWUlZSHlHOTJnRkFSSUdDR0I4aHZkb0JRRVRCZ2hnZkliM2FBVUJGQVlJWUh5RzkyZ0ZBUlVHQ0dCOGh2ZG9CUUVXQmdoZ2ZJYjNhQVVCRndZSVlIeUc5MmdGQVJnd09nWURWUjBmQkRNd01UQXZvQzJnSzRZcGFIUjBjRG92TDJOaExuTnRZWEowWTJGeVpITmxZM1Z5YVhSNUxtTmhMM0J2YkhOamN5NWpjbXd3ZFFZSUt3WUJCUVVIQVFFRWFUQm5NQ3dHQ0NzR0FRVUZCekFCaGlCb2RIUndPaTh2YjJOemNDNXpiV0Z5ZEdOaGNtUnpaV04xY21sMGVTNWpZVEEzQmdnckJnRUZCUWN3QW9ZcmFIUjBjRG92TDJOaExuTnRZWEowWTJGeVpITmxZM1Z5YVhSNUxtTmhMMUJ2YkZOamMwTmhMbU55ZERBcUJnTlZIUkVFSXpBaGhoOW9kSFJ3T2k4dlpYWXVjMjFoY25SallYSmtjMlZqZFhKcGRIa3VZMkV2TUlJRllBWURWUjBnQklJRlZ6Q0NCVk13UWdZSFlIeUc5MmdCQXpBM01EVUdDQ3NHQVFVRkJ3SUJGaWxvZEhSd2N6b3ZMMk5oTG5OdFlYSjBZMkZ5WkhObFkzVnlhWFI1TG1OaEwyTndjeTl6WTNObGRqQUtCZ2hnZkliM2FBRURBVEFMQmdsZ2ZJYjNhQUVEQVFFd0N3WUpZSHlHOTJnQkF3RUNNQXNHQ1dCOGh2ZG9BUU1CQXpBTEJnbGdmSWIzYUFFREFRUXdDd1lKWUh5RzkyZ0JBd0VGTUFzR0NXQjhodmRvQVFNQkJqQUxCZ2xnZkliM2FBRURBUWN3Q3dZSllIeUc5MmdCQXdFSU1Bc0dDV0I4aHZkb0FRTUJDVEFMQmdsZ2ZJYjNhQUVEQVFvd0N3WUpZSHlHOTJnQkF3RUxNQXNHQ1dCOGh2ZG9BUU1CRERBTEJnbGdmSWIzYUFFREFRMHdDd1lKWUh5RzkyZ0JBd0VPTUFzR0NXQjhodmRvQVFNQkR6QUxCZ2xnZkliM2FBRURBUkF3Q3dZSllIeUc5MmdCQXdFUk1Bc0dDV0I4aHZkb0FRTUJFakFLQmdoZ2ZJYjNhQUVEQWpBTEJnbGdmSWIzYUFFREFnRXdDd1lKWUh5RzkyZ0JBd0lDTUFzR0NXQjhodmRvQVFNQ0F6QUxCZ2xnZkliM2FBRURBZ1F3Q3dZSllIeUc5MmdCQXdJRk1Bc0dDV0I4aHZkb0FRTUNCakFMQmdsZ2ZJYjNhQUVEQWdjd0N3WUpZSHlHOTJnQkF3SUlNQXNHQ1dCOGh2ZG9BUU1DQ1RBTEJnbGdmSWIzYUFFREFnb3dDd1lKWUh5RzkyZ0JBd0lMTUFzR0NXQjhodmRvQVFNQ0REQUxCZ2xnZkliM2FBRURBZzB3Q1FZSFlIeUc5MmdCQlRBS0JnaGdmSWIzYUFFRkFUQUtCZ2hnZkliM2FBRUZBakFLQmdoZ2ZJYjNhQUVGQXpBS0JnaGdmSWIzYUFFRkJEQUtCZ2hnZkliM2FBRUZCVEFLQmdoZ2ZJYjNhQUVGQmpBS0JnaGdmSWIzYUFFRkJ6QUtCZ2hnZkliM2FBRUZDREFLQmdoZ2ZJYjNhQUVGQ1RBS0JnaGdmSWIzYUFFRkNqQUtCZ2hnZkliM2FBRUZDekFLQmdoZ2ZJYjNhQUVGRERBS0JnaGdmSWIzYUFFRkRUQUtCZ2hnZkliM2FBRUZEakFLQmdoZ2ZJYjNhQUVGRHpBS0JnaGdmSWIzYUFFRkVEQUtCZ2hnZkliM2FBRUZFVEFLQmdoZ2ZJYjNhQUVGRWpBS0JnaGdmSWIzYUFFRkV6QUtCZ2hnZkliM2FBRUZGREFLQmdoZ2ZJYjNhQUVGRlRBS0JnaGdmSWIzYUFFRkZqQUtCZ2hnZkliM2FBRUZGekFLQmdoZ2ZJYjNhQUVGR0RBS0JnaGdmSWIzYUFFRkdUQUtCZ2hnZkliM2FBRUZHakFLQmdoZ2ZJYjNhQUVGR3pBS0JnaGdmSWIzYUFFRkhEQUtCZ2hnZkliM2FBRUZIVEFLQmdoZ2ZJYjNhQUVGSGpBSkJnZGdmSWIzYUFFQ01Bb0dDR0I4aHZkb0FRSUJNQW9HQ0dCOGh2ZG9BUUlDTUFvR0NHQjhodmRvQVFJRE1Bb0dDR0I4aHZkb0FRSUVNQW9HQ0dCOGh2ZG9BUUlGTUFvR0NHQjhodmRvQVFJR01Bb0dDR0I4aHZkb0FRSUhNQW9HQ0dCOGh2ZG9BUUlJTUFvR0NHQjhodmRvQVFJSk1Bb0dDR0I4aHZkb0FRSUtNQW9HQ0dCOGh2ZG9BUUlMTUFvR0NHQjhodmRvQVFJTU1Bb0dDR0I4aHZkb0FRSU5NQW9HQ0dCOGh2ZG9BUUlPTUFvR0NHQjhodmRvQVFJUE1Bb0dDR0I4aHZkb0FRSVFNQW9HQ0dCOGh2ZG9BUUlSTUFvR0NHQjhodmRvQVFJU01Bb0dDR0I4aHZkb0FRSVRNQW9HQ0dCOGh2ZG9BUUlVTUFvR0NHQjhodmRvQVFJVk1Bb0dDR0I4aHZkb0FRSVdNQW9HQ0dCOGh2ZG9BUUlYTUFvR0NHQjhodmRvQVFJWU1Bb0dDR0I4aHZkb0FRSVpNQW9HQ0dCOGh2ZG9BUUlhTUFvR0NHQjhodmRvQVFJYk1Bb0dDR0I4aHZkb0FRSWNNQW9HQ0dCOGh2ZG9BUUlkTUFvR0NHQjhodmRvQVFJZU1Bb0dDR0I4aHZkb0FRSWZNQW9HQ0dCOGh2ZG9BUUlnTUFvR0NHQjhodmRvQVFJaE1Bb0dDR0I4aHZkb0FRSWlNQW9HQ0dCOGh2ZG9BUUlqTUFjR0JXZUJEQUVCTUFjR0JXZUJEQUVDTUFnR0JtZUJEQUVDQVRBSUJnWm5nUXdCQWdJd0NBWUdaNEVNQVFJRE1BY0dCV2VCREFFRE1BY0dCV2VCREFFZk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQ0I2SDg2SXlWN2tUR2RaaC9udWk4d3dHY0RYVFVUckFzdWNPM3IwQ2tudTRyMXB6YUtOS215NjNFdjNQdmcwdlBFd2ZtTkFBUVZkU2JnR3ROMEwrRlpaS0JLQWREVmEwSXZLaVIvOTltdHZySXNqUlhtWXVHZ1JUaW1TZWFzM2huR2k4N2tHTmkzeFlRVStselpUSFlrRzE2QXU0dFZhMmZjNTVLcVhPMlFCNko1VVZPQjVrMzdqcGZMVnRIMDVYSXJZNmlrNlM4TjZTbzBSb05kUmZpSG52RklJV3ZvR2t4UE9NcUpQc3ZkbHArLytzUXZlY2U4KzdQS0MrV0FDQjIvYlBaR0wzQnRRSmxoUGI1Z210NUh5SjZoNGExeWEyK2JWZnZIak02UjZraFlodklhTmZtY2tQeTd2S0M5SjZsTUVxZEQ3OVdkZGZ2OWpSYmtyY0k1bHZ6UERCWFdXVTF3WWgyQnlmeTVBTXV0WDgvaXNIZHRiSkNiVjBRak9yWVdnWTBwYWtqOTBkUlQ1QXUzdStvQXJtMWZld2lBbnU3TzlIV2h4WmRqTDVwWmVuOStyRXc4OGM2cUNDZDZialIzK1Zwc2F1K0RsWXhjZXJFTzI2ZVpvUFNRTi9KZk02czZBWGtMT0dMdkxxanpmYy85bzE2d1ZiUUxWb2F3MzdsV3FrK3lueXdRa3E4TmR5T0NldDd4Ymw5S0xzOHg2ejMwdWxydTl6SkdTK215R01yS0R0Zm1DdG96L2l3TmRKdWFzTkdUaStsOHdWcDg4bm1GOEdZQThMVXd0bU9La2E1VnFLOFlaS3pvMXZvRityRDhHTVFhdE5JTjh2eDhKMGNmTlRVbWh2Q0QrdXhlVm1jS3ZIcHEzQ09wdFU2cFU3dWJsZURueUxmRDl3PT0iLCJNSUlWcmpDQ0U1YWdBd0lCQWdJV0FNb0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBVEFOQmdrcWhraUc5dzBCQVFzRkFEQ0NBakF4T3pBNUJnTlZCQVVNTWs1RlVTQXhNVGN6TkRnNE5qUTFJQzhnUTA0Z01UQTJORGMzTXkwd0lDOGdRazRnTnpZM016UTVOamd4VWtNd01EQXhNUk13RVFZTEt3WUJCQUdDTnp3Q0FRTU1Ba05CTVJnd0ZnWUxLd1lCQkFHQ056d0NBUUlNQjFGMXc2bGlaV014R3pBWkJnc3JCZ0VFQVlJM1BBSUJBUXdLVkdWeWNtVmliMjV1WlRFeE1DOEdBMVVFRHd3b1U4T3BZM1Z5YVhURHFTQkpibVp2Y20xaGRHbHhkV1VnTHlCRGVXSmxjaUJUWldOMWNtbDBlVEVxTUNnR0NTcUdTSWIzRFFFSkFSWWJhVzVtYjJOaFFITnRZWEowWTJGeVpITmxZM1Z5YVhSNUxtTmhNUm93R0FZRFZRUVhEQkVyTVNBb05EVXdLU0E1TmpRdE5EVXhNVEVhTUJnR0ExVUVGQXdSS3pFZ0tEUTFNQ2tnT1RZMExUYzNOell4RURBT0JnTlZCQkVNQjBvMlZ5QXdRVEl4Q3pBSkJnTlZCQVlUQWtOQk1SQXdEZ1lEVlFRSURBZFJkY09wWW1Wak1STXdFUVlEVlFRSERBcFVaWEp5WldKdmJtNWxNUm93R0FZRFZRUUpEQkV4TVRjNUlHUmxJR3duWlhod2NtVnpjekVyTUNrR0ExVUVDd3dpUVhWMGFHOXlhWFREcVNCU1lXTnBibVVnTHlCU2IyOTBJRUYxZEdodmNtbDBlVEUxTURNR0ExVUVDZ3dzVTFORklFTmhjblJsSU1PZ0lGQjFZMlVnU1c1akxpQXZJRVZUVXlCVGJXRnlkQ0JEWVhKa0lFbHVZeTR4U0RCR0JnTlZCQU1NUDFObFkzVnlhWFREcVNCRFlYSjBaU0REb0NCUWRXTmxJQ2hUUTFBcElFRkRJQzhnVTIxaGNuUWdRMkZ5WkNCVFpXTjFjbWwwZVNBb1UwTlRLU0JEUVRBZUZ3MHhPREExTXpBeE5URTVNRFJhRncwME9EQTFNamd4TlRFNU1EUmFNSUlDTlRFVE1CRUdDeXNHQVFRQmdqYzhBZ0VEREFKRFFURVlNQllHQ3lzR0FRUUJnamM4QWdFQ0RBZFJkY09wWW1Wak1Sc3dHUVlMS3dZQkJBR0NOendDQVFFTUNsUmxjbkpsWW05dWJtVXhNVEF2QmdOVkJBOE1LRlBEcVdOMWNtbDB3NmtnU1c1bWIzSnRZWFJwY1hWbElDOGdRM2xpWlhJZ1UyVmpkWEpwZEhreE96QTVCZ05WQkFVTU1rNUZVU0F4TVRjek5EZzROalExSUM4Z1EwNGdNVEEyTkRjM015MHdJQzhnUWs0Z056WTNNelE1TmpneFVrTXdNREF4TVNvd0tBWUpLb1pJaHZjTkFRa0JGaHRwYm1adlkyRkFjMjFoY25SallYSmtjMlZqZFhKcGRIa3VZMkV4R2pBWUJnTlZCQmNNRVNzeElDZzBOVEFwSURrMk5DMDBOVEV4TVJvd0dBWURWUVFVREJFck1TQW9ORFV3S1NBNU5qUXROemMzTmpFUU1BNEdBMVVFRVF3SFNqWlhJREJCTWpFTE1Ba0dBMVVFQmhNQ1EwRXhFREFPQmdOVkJBZ01CMUYxdzZsaVpXTXhFekFSQmdOVkJBY01DbFJsY25KbFltOXVibVV4R2pBWUJnTlZCQWtNRVRFeE56a2daR1VnYkNkbGVIQnlaWE56TVRJd01BWURWUVFMRENsQmRYUnZjbWwwdzZrZ1pHVWdVRzlzYVhScGNYVmxJQzhnVUc5c2FXTjVJRUYxZEdodmNtbDBlVEUxTURNR0ExVUVDZ3dzVTFORklFTmhjblJsSU1PZ0lGQjFZMlVnU1c1akxpQXZJRVZUVXlCVGJXRnlkQ0JEWVhKa0lFbHVZeTR4UmpCRUJnTlZCQU1NUFZORFVDQkJkWFJ2Y21sMHc2a2daR1VnVUc5c2FYUnBjWFZsSUM4Z1UwTlRJRU5sY25ScFptbGpZWFJsSUZCdmJHbGplU0JCZFhSb2IzSnBkSGt3Z2dJZ01BMEdDU3FHU0liM0RRRUJBUVVBQTRJQ0RRQXdnZ0lJQW9JQ0FRRGEyQXlwVXNEbTZ6dmdLc29PcnJ1NFdlQW5PWFNod0kxVDBUaVFac3ZKOTB1d1Y1TURXY2FNZjBEWnlsMk9LaU4rTG16UElDYlh3NFRDckpwaEpYbmR5UEYwOUUzSDFRQzJwR043MUJOcHhvRGVCcWtYMVlJVzRQSGhZOXFoalJLZ3BsYkpUS2NIZlFBMUNqVlR6WDVyYUFtbkxBSjhpdW83SFY3WmJwbEZnN1YzY1dPSmJjM3A1RkZpeGVTSTV4QUNMc0pRSUFpdE5QMzBGaHB4NGJ4eENZOW8xWlFPL0hVMzN6N1piQ3UxUXcwaWFYWUlyMFZXR3U1ZUN6c2d6bDU2YndEdVBQN05mMThtSkVhVjAzOWVXdTQ5U2pkWDZoWWtRRlQrd1FCWVV4T1BVbzhoN3h4WEdaYndNblRNVXlRd1c2dXliVUI4R3d0ak1JVm9EVDlZNjg4U0gzZmQ3cURvWXV1VGh3OURjSEZqaFpIaG5tRjB6UmpRby9GWmFzMDdta1E5WElkUmpXdFdQZHFTRldzZGo4K2JTcWQ2bG9IWmxzVlBweHlDUldMZWdhV0RpNitLU3J4Z3VRWGd4M2lwODViVGR5Q0lDT2JXYTg4QzhDcUdxc1VCVG5qbXlHOTFGRmVGaDRlRGcyQ0pYem5WZHNIU2ZlS1VWR0Y5SEZXbjN4NVFvRDIrTmVWRmdIcWpPbVBJeXhCSkw1VnQ4QVZRMHZvZDkyM1B4YXltT2xVVWtyQmhsSlhFL1YzVHdES2U2Tjg4eWpHVWZ0RmM3Z0R2aHU4aUprQVVENWlkVFR0Y1Z4cjFFMFRnZGJQYXFqM09Mc2g2V0hmWjZ1ZDJLYjF2cWhzUVY2WDZReGZsZHVXNjN5Z0ZuYmh0d0RkTGxRc0tERHJXQjQyUHh3SUJKYU9DRExVd2dneXhNQjBHQTFVZERnUVdCQlRhY2o1b2d6UUhhZ0dSMHFXdlBoeE5vdUgrVGpBZkJnTlZIU01FR0RBV2dCUWtZR29IY3lSVmRUczIrblJaazFYSnNnQW1PakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQmhqQTVCZ05WSFI4RU1qQXdNQzZnTEtBcWhpaG9kSFJ3T2k4dlkyRXVjMjFoY25SallYSmtjMlZqZFhKcGRIa3VZMkV2WTJGelkzTXVZM0pzTUhJR0NDc0dBUVVGQndFQkJHWXdaREFzQmdnckJnRUZCUWN3QVlZZ2FIUjBjRG92TDI5amMzQXVjMjFoY25SallYSmtjMlZqZFhKcGRIa3VZMkV3TkFZSUt3WUJCUVVITUFLR0tHaDBkSEE2THk5allTNXpiV0Z5ZEdOaGNtUnpaV04xY21sMGVTNWpZUzlqWVhOamN5NWpjblF3S2dZRFZSMFJCQ013SVlZZmFIUjBjRG92TDJOaExuTnRZWEowWTJGeVpITmxZM1Z5YVhSNUxtTmhMekNDQzNFR0ExVWRJQVNDQzJnd2dndGtNRHNHQm1COGh2ZG9BVEF4TUM4R0NDc0dBUVVGQndJQkZpTm9kSFJ3Y3pvdkwyTmhMbk50WVhKMFkyRnlaSE5sWTNWeWFYUjVMbU5oTDJOd2N6QUlCZ1pnZkliM2FBSXdDQVlHWUh5RzkyZ0RNQWdHQm1COGh2ZG9CREFJQmdaZ2ZJYjNhQVV3Q0FZR1lIeUc5MmdHTUFnR0JtQjhodmRvQnpBSUJnWmdmSWIzYUFnd0NBWUdZSHlHOTJnSk1BZ0dCbUI4aHZkb0NqQUlCZ1pnZkliM2FBc3dDQVlHWUh5RzkyZ01NQWdHQm1COGh2ZG9EVEFJQmdaZ2ZJYjNhQTR3Q0FZR1lIeUc5MmdQTUFnR0JtQjhodmRvRURBSkJnZGdmSWIzYUFFSk1Ba0dCMkI4aHZkb0FRb3dDUVlIWUh5RzkyZ0JDekFKQmdkZ2ZJYjNhQUVNTUFrR0IyQjhodmRvQVEwd0NRWUhZSHlHOTJnQkRqQUpCZ2RnZkliM2FBRVBNQWtHQjJCOGh2ZG9BUkF3Q1FZSFlIeUc5MmdCRVRBSkJnZGdmSWIzYUFFU01Ba0dCMkI4aHZkb0FRRXdDZ1lJWUh5RzkyZ0JBUUV3Q2dZSVlIeUc5MmdCQVFJd0NnWUlZSHlHOTJnQkFRTXdDZ1lJWUh5RzkyZ0JBUVF3Q2dZSVlIeUc5MmdCQVFVd0NnWUlZSHlHOTJnQkFRWXdDZ1lJWUh5RzkyZ0JBUWN3Q2dZSVlIeUc5MmdCQVFnd0NnWUlZSHlHOTJnQkFRa3dDZ1lJWUh5RzkyZ0JBUW93Q2dZSVlIeUc5MmdCQVFzd0NnWUlZSHlHOTJnQkFRd3dDZ1lJWUh5RzkyZ0JBUTB3Q2dZSVlIeUc5MmdCQVE0d0NnWUlZSHlHOTJnQkFROHdDZ1lJWUh5RzkyZ0JBUkF3Q2dZSVlIeUc5MmdCQVJFd0NnWUlZSHlHOTJnQkFSSXdDZ1lJWUh5RzkyZ0JBUk13Q2dZSVlIeUc5MmdCQVJRd0NnWUlZSHlHOTJnQkFSVXdDZ1lJWUh5RzkyZ0JBUll3Q1FZSFlIeUc5MmdCQlRBS0JnaGdmSWIzYUFFRkFUQUtCZ2hnZkliM2FBRUZBakFLQmdoZ2ZJYjNhQUVGQXpBS0JnaGdmSWIzYUFFRkJEQUtCZ2hnZkliM2FBRUZCVEFLQmdoZ2ZJYjNhQUVGQmpBS0JnaGdmSWIzYUFFRkJ6QUtCZ2hnZkliM2FBRUZDREFLQmdoZ2ZJYjNhQUVGQ1RBS0JnaGdmSWIzYUFFRkNqQUtCZ2hnZkliM2FBRUZDekFLQmdoZ2ZJYjNhQUVGRERBS0JnaGdmSWIzYUFFRkRUQUtCZ2hnZkliM2FBRUZEakFLQmdoZ2ZJYjNhQUVGRHpBS0JnaGdmSWIzYUFFRkVEQUtCZ2hnZkliM2FBRUZFVEFLQmdoZ2ZJYjNhQUVGRWpBS0JnaGdmSWIzYUFFRkV6QUtCZ2hnZkliM2FBRUZGREFLQmdoZ2ZJYjNhQUVGRlRBS0JnaGdmSWIzYUFFRkZqQUtCZ2hnZkliM2FBRUZGekFLQmdoZ2ZJYjNhQUVGR0RBS0JnaGdmSWIzYUFFRkdUQUtCZ2hnZkliM2FBRUZHakFLQmdoZ2ZJYjNhQUVGR3pBS0JnaGdmSWIzYUFFRkhEQUtCZ2hnZkliM2FBRUZIVEFLQmdoZ2ZJYjNhQUVGSGpBSkJnZGdmSWIzYUFFQ01Bb0dDR0I4aHZkb0FRSUJNQW9HQ0dCOGh2ZG9BUUlDTUFvR0NHQjhodmRvQVFJRE1Bb0dDR0I4aHZkb0FRSUVNQW9HQ0dCOGh2ZG9BUUlGTUFvR0NHQjhodmRvQVFJR01Bb0dDR0I4aHZkb0FRSUhNQW9HQ0dCOGh2ZG9BUUlJTUFvR0NHQjhodmRvQVFJSk1Bb0dDR0I4aHZkb0FRSUtNQW9HQ0dCOGh2ZG9BUUlMTUFvR0NHQjhodmRvQVFJTU1Bb0dDR0I4aHZkb0FRSU5NQW9HQ0dCOGh2ZG9BUUlPTUFvR0NHQjhodmRvQVFJUE1Bb0dDR0I4aHZkb0FRSVFNQW9HQ0dCOGh2ZG9BUUlSTUFvR0NHQjhodmRvQVFJU01Bb0dDR0I4aHZkb0FRSVRNQW9HQ0dCOGh2ZG9BUUlVTUFvR0NHQjhodmRvQVFJVk1Bb0dDR0I4aHZkb0FRSVdNQW9HQ0dCOGh2ZG9BUUlYTUFvR0NHQjhodmRvQVFJWU1Bb0dDR0I4aHZkb0FRSVpNQW9HQ0dCOGh2ZG9BUUlhTUFvR0NHQjhodmRvQVFJYk1Bb0dDR0I4aHZkb0FRSWNNQW9HQ0dCOGh2ZG9BUUlkTUFvR0NHQjhodmRvQVFJZU1Bb0dDR0I4aHZkb0FRSWZNQW9HQ0dCOGh2ZG9BUUlnTUFvR0NHQjhodmRvQVFJaE1Bb0dDR0I4aHZkb0FRSWlNQW9HQ0dCOGh2ZG9BUUlqTUFrR0IyQjhodmRvQVFNd0NnWUlZSHlHOTJnQkF3RXdDd1lKWUh5RzkyZ0JBd0VCTUFzR0NXQjhodmRvQVFNQkFqQUxCZ2xnZkliM2FBRURBUU13Q3dZSllIeUc5MmdCQXdFRU1Bc0dDV0I4aHZkb0FRTUJCVEFMQmdsZ2ZJYjNhQUVEQVFZd0N3WUpZSHlHOTJnQkF3RUhNQXNHQ1dCOGh2ZG9BUU1CQ0RBTEJnbGdmSWIzYUFFREFRa3dDd1lKWUh5RzkyZ0JBd0VLTUFzR0NXQjhodmRvQVFNQkN6QUxCZ2xnZkliM2FBRURBUXd3Q3dZSllIeUc5MmdCQXdFTk1Bc0dDV0I4aHZkb0FRTUJEakFMQmdsZ2ZJYjNhQUVEQVE4d0N3WUpZSHlHOTJnQkF3RVFNQXNHQ1dCOGh2ZG9BUU1CRVRBTEJnbGdmSWIzYUFFREFSSXdDZ1lJWUh5RzkyZ0JBd0l3Q3dZSllIeUc5MmdCQXdJQk1Bc0dDV0I4aHZkb0FRTUNBakFMQmdsZ2ZJYjNhQUVEQWdNd0N3WUpZSHlHOTJnQkF3SUVNQXNHQ1dCOGh2ZG9BUU1DQlRBTEJnbGdmSWIzYUFFREFnWXdDd1lKWUh5RzkyZ0JBd0lITUFzR0NXQjhodmRvQVFNQ0NEQUxCZ2xnZkliM2FBRURBZ2t3Q3dZSllIeUc5MmdCQXdJS01Bc0dDV0I4aHZkb0FRTUNDekFMQmdsZ2ZJYjNhQUVEQWd3d0N3WUpZSHlHOTJnQkF3SU5NQWtHQjJCOGh2ZG9BUVF3Q2dZSVlIeUc5MmdCQkFFd0N3WUpZSHlHOTJnQkJBRUJNQXNHQ1dCOGh2ZG9BUVFCQWpBTEJnbGdmSWIzYUFFRUFRTXdDd1lKWUh5RzkyZ0JCQUVFTUFzR0NXQjhodmRvQVFRQkJUQUxCZ2xnZkliM2FBRUVBUVl3Q3dZSllIeUc5MmdCQkFFSE1Bc0dDV0I4aHZkb0FRUUJDREFMQmdsZ2ZJYjNhQUVFQVFrd0N3WUpZSHlHOTJnQkJBRUtNQXNHQ1dCOGh2ZG9BUVFCQ3pBTEJnbGdmSWIzYUFFRUFRd3dDd1lKWUh5RzkyZ0JCQUVOTUFzR0NXQjhodmRvQVFRQkRqQUxCZ2xnZkliM2FBRUVBUTh3Q3dZSllIeUc5MmdCQkFFUU1Bc0dDV0I4aHZkb0FRUUJFVEFMQmdsZ2ZJYjNhQUVFQVJJd0N3WUpZSHlHOTJnQkJBRVRNQW9HQ0dCOGh2ZG9BUVFDTUFzR0NXQjhodmRvQVFRQ0FUQUxCZ2xnZkliM2FBRUVBZ0l3Q3dZSllIeUc5MmdCQkFJRE1Bc0dDV0I4aHZkb0FRUUNCREFMQmdsZ2ZJYjNhQUVFQWdVd0N3WUpZSHlHOTJnQkJBSUdNQXNHQ1dCOGh2ZG9BUVFDQnpBTEJnbGdmSWIzYUFFRUFnZ3dDd1lKWUh5RzkyZ0JCQUlKTUFzR0NXQjhodmRvQVFRQ0NqQUxCZ2xnZkliM2FBRUVBZ3N3Q3dZSllIeUc5MmdCQkFJTU1Bc0dDV0I4aHZkb0FRUUNEVEFMQmdsZ2ZJYjNhQUVFQWc0d0NnWUlZSHlHOTJnQkJBTXdDd1lKWUh5RzkyZ0JCQU1CTUFzR0NXQjhodmRvQVFRREFqQUxCZ2xnZkliM2FBRUVBd013Q3dZSllIeUc5MmdCQkFNRU1Bc0dDV0I4aHZkb0FRUURCVEFMQmdsZ2ZJYjNhQUVFQXdZd0N3WUpZSHlHOTJnQkJBTUhNQXNHQ1dCOGh2ZG9BUVFEQ0RBTEJnbGdmSWIzYUFFRUF3a3dDd1lKWUh5RzkyZ0JCQU1LTUFzR0NXQjhodmRvQVFRREN6QUxCZ2xnZkliM2FBRUVBd3d3Q3dZSllIeUc5MmdCQkFNTk1Ba0dCMkI4aHZkb0FRWXdDZ1lJWUh5RzkyZ0JCZ0V3Q2dZSVlIeUc5MmdCQmdJd0NnWUlZSHlHOTJnQkJnTXdDZ1lJWUh5RzkyZ0JCZ1F3Q2dZSVlIeUc5MmdCQmdVd0NnWUlZSHlHOTJnQkJnWXdDZ1lJWUh5RzkyZ0JCZ2N3Q1FZSFlIeUc5MmdCQnpBS0JnaGdmSWIzYUFFSEFUQUtCZ2hnZkliM2FBRUhBakFLQmdoZ2ZJYjNhQUVIQXpBS0JnaGdmSWIzYUFFSEJEQUtCZ2hnZkliM2FBRUhCVEFLQmdoZ2ZJYjNhQUVIQmpBS0JnaGdmSWIzYUFFSEJ6QUtCZ2hnZkliM2FBRUhDREFLQmdoZ2ZJYjNhQUVIQ1RBS0JnaGdmSWIzYUFFSENqQUpCZ2RnZkliM2FBRUlNQW9HQ0dCOGh2ZG9BUWdCTUFvR0NHQjhodmRvQVFnQ01Bb0dDR0I4aHZkb0FRZ0RNQW9HQ0dCOGh2ZG9BUWdFTUFvR0NHQjhodmRvQVFnRk1Bb0dDR0I4aHZkb0FRZ0dNQW9HQ0dCOGh2ZG9BUWdITUFvR0NHQjhodmRvQVFnSU1Bb0dDR0I4aHZkb0FRZ0pNQW9HQ0dCOGh2ZG9BUWdLTUFvR0NHQjhodmRvQVFnTE1BY0dCV2VCREFFQk1BY0dCV2VCREFFQ01BZ0dCbWVCREFFQ0FUQUlCZ1puZ1F3QkFnSXdDQVlHWjRFTUFRSURNQWNHQldlQkRBRURNQWNHQldlQkRBRWZNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUNBUUJZLzdBUE5IMWEySmZwbHcxZ2pJRVEvTGM0WEk1cERzMDJQT3pwVmtDVjZuWkpaZDVYWEZib2VDemFkcFpwU1BXL1JlZUxyUkc4a2ZHVVpIV0tjOFVDVWsrWGNWOVd2SzU0RWZEOXl4dGFVWWhlRCt0YmJQTUcrdit4bzF5UEhPUVBUOFUvUTFleEphZDYxUnpPcFlHQmIrdnl5bDQ5RjJncUU2SzZPVXM1aXRQWFlidmJiYlZEMjRwYnRHRm5VZWdyaUtoUWZhQ21oTGN6Y3pPME1yVXVJQjNaZnB6dUhZcXQvT1lteXRZY2lzUVh2TzZ1cUhFTW1rT1RKQ1dUazV0L0RBeHF5dzlHcDdUa1dXZ2g2RzRwdlNjVGtrMVlTZHQxcE83NXRaTnhZNWtpbldtQzh4VEIya01vRmpjWDBTd2lFdDR2TWNIUzI1S3U4emduL0ZJSXRGaEJTK2tIL2FMdVh3Yit2KzJUM3NmWTJFZVJBc3gxUHlmeHNGQjNFR0hhRnN5TjhUdy9tZFY1MElsemw1V1FRMnMrVHhPNU04UXo2R1llcEgwVHNkbjhucnF1Y2hCcjNLOFg1TnRjL3VGY0dySW0vVHRlbWszdU44cmVHVWU3R2c0Y2ZoNzRpaExJcmt3SlpHTTh5UnY1Wnd1aWhQMnQ3dkdYUXpWTEdpMUFBczhERlRTSVJ0UWVrcXYxbG5EZWVXMjN3ZmtVNit2SFZDZ2hSSzVxdXlYUGh3b0hqeWxCWkJBTlp4QW0yZVpIVTZNeGF6QTNOQlJtaXo0aTFCdTl4VEdVeVlZbnNVQlhFYlc5Mi9IWXRGeGQ3dWlwaVBYajlBS21WNENuSU5Wd0VxTGprczFWZHhmKzdMNEQrRk1XT01OTUFpNFdtazNtSFROWm1WMk5BZz09IiwiTUlJSmd6Q0NCMnVnQXdJQkFnSVdBTW9BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURBTkJna3Foa2lHOXcwQkFRc0ZBRENDQWpBeE96QTVCZ05WQkFVTU1rNUZVU0F4TVRjek5EZzROalExSUM4Z1EwNGdNVEEyTkRjM015MHdJQzhnUWs0Z056WTNNelE1TmpneFVrTXdNREF4TVJNd0VRWUxLd1lCQkFHQ056d0NBUU1NQWtOQk1SZ3dGZ1lMS3dZQkJBR0NOendDQVFJTUIxRjF3NmxpWldNeEd6QVpCZ3NyQmdFRUFZSTNQQUlCQVF3S1ZHVnljbVZpYjI1dVpURXhNQzhHQTFVRUR3d29VOE9wWTNWeWFYVERxU0JKYm1admNtMWhkR2x4ZFdVZ0x5QkRlV0psY2lCVFpXTjFjbWwwZVRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYVc1bWIyTmhRSE50WVhKMFkyRnlaSE5sWTNWeWFYUjVMbU5oTVJvd0dBWURWUVFYREJFck1TQW9ORFV3S1NBNU5qUXRORFV4TVRFYU1CZ0dBMVVFRkF3Ukt6RWdLRFExTUNrZ09UWTBMVGMzTnpZeEVEQU9CZ05WQkJFTUIwbzJWeUF3UVRJeEN6QUpCZ05WQkFZVEFrTkJNUkF3RGdZRFZRUUlEQWRSZGNPcFltVmpNUk13RVFZRFZRUUhEQXBVWlhKeVpXSnZibTVsTVJvd0dBWURWUVFKREJFeE1UYzVJR1JsSUd3blpYaHdjbVZ6Y3pFck1Da0dBMVVFQ3d3aVFYVjBhRzl5YVhURHFTQlNZV05wYm1VZ0x5QlNiMjkwSUVGMWRHaHZjbWwwZVRFMU1ETUdBMVVFQ2d3c1UxTkZJRU5oY25SbElNT2dJRkIxWTJVZ1NXNWpMaUF2SUVWVFV5QlRiV0Z5ZENCRFlYSmtJRWx1WXk0eFNEQkdCZ05WQkFNTVAxTmxZM1Z5YVhURHFTQkRZWEowWlNERG9DQlFkV05sSUNoVFExQXBJRUZESUM4Z1UyMWhjblFnUTJGeVpDQlRaV04xY21sMGVTQW9VME5US1NCRFFUQWVGdzB4T0RBMU16QXhOVEUxTXpCYUZ3MDBPREExTXpBeE5URTFNekJhTUlJQ01ERTdNRGtHQTFVRUJRd3lUa1ZSSURFeE56TTBPRGcyTkRVZ0x5QkRUaUF4TURZME56Y3pMVEFnTHlCQ1RpQTNOamN6TkRrMk9ERlNRekF3TURFeEV6QVJCZ3NyQmdFRUFZSTNQQUlCQXd3Q1EwRXhHREFXQmdzckJnRUVBWUkzUEFJQkFnd0hVWFhEcVdKbFl6RWJNQmtHQ3lzR0FRUUJnamM4QWdFQkRBcFVaWEp5WldKdmJtNWxNVEV3THdZRFZRUVBEQ2hUdzZsamRYSnBkTU9wSUVsdVptOXliV0YwYVhGMVpTQXZJRU41WW1WeUlGTmxZM1Z5YVhSNU1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0cGJtWnZZMkZBYzIxaGNuUmpZWEprYzJWamRYSnBkSGt1WTJFeEdqQVlCZ05WQkJjTUVTc3hJQ2cwTlRBcElEazJOQzAwTlRFeE1Sb3dHQVlEVlFRVURCRXJNU0FvTkRVd0tTQTVOalF0TnpjM05qRVFNQTRHQTFVRUVRd0hTalpYSURCQk1qRUxNQWtHQTFVRUJoTUNRMEV4RURBT0JnTlZCQWdNQjFGMXc2bGlaV014RXpBUkJnTlZCQWNNQ2xSbGNuSmxZbTl1Ym1VeEdqQVlCZ05WQkFrTUVURXhOemtnWkdVZ2JDZGxlSEJ5WlhOek1Tc3dLUVlEVlFRTERDSkJkWFJvYjNKcGRNT3BJRkpoWTJsdVpTQXZJRkp2YjNRZ1FYVjBhRzl5YVhSNU1UVXdNd1lEVlFRS0RDeFRVMFVnUTJGeWRHVWd3NkFnVUhWalpTQkpibU11SUM4Z1JWTlRJRk50WVhKMElFTmhjbVFnU1c1akxqRklNRVlHQTFVRUF3dy9VMlZqZFhKcGRNT3BJRU5oY25SbElNT2dJRkIxWTJVZ0tGTkRVQ2tnUVVNZ0x5QlRiV0Z5ZENCRFlYSmtJRk5sWTNWeWFYUjVJQ2hUUTFNcElFTkJNSUlDSURBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWcwQU1JSUNDQUtDQWdFQXVqYUNURWkwa0daMW1zODVlZVVodWdScFJ0eWswQ0F6YnhyWE9EYVVTTU43UWhHRWNOVlI4YlB5Y2FKdVBTRXdZWXJ4REJSS0lIenl0dUQrRS9wSEpVa24zM3V5ZGJZSElhdVJ2WUpXbVBhUVZUS2RucnY4OEpLMFNkU0ZZRlpvTGhkdms3V00vM0xzU3NBaDZZaVpTc1gvZnpPcmdNanlQVWF3ZDFKa01yUmhBVDJENGRMOEFVU2Zwdm9xSzRpT2VGYnE4emN6VnlJYWtXaElRcXdxUC8rUDZpYi9zeGlhcG9oc0R1aUNkcFE3QjdNVHl6T0gza0twb0dabTlUcjZEV1l0dTh6QU5wbzh6UTJaTHUwNDVsTkJRZlVTejVTRXdhRHlZV1FSU2hEVXJsaHpieGVBbGI1NjA5Q3A4RjhRNk11Sk5DLzQyalFvQ2owQkFLUVB6MXJxZFZUZmNKc1lWemF0enlvdHByTWFHTUZ6UEZlbFJiSitDSzhEU0xUTVdUK0JIR1dEOEJwVDdGZVBpNmlIVmJucXcwOEY5MFhQRTNXcmhxdGxuOGwzaVhINjVDb280djlFVnk0RityaU5GS3VrekVURHFlWDB3ak11SExRS1dLYW0xR3pvWmZQVUJnc3IzN2Q3bmx6bWp0RWNZRVkzNDcyWklpTU94V1Q5b0hQdUdXSExGaGVHWHcxKzVxd04wU3VrVzAvOVh1WUcwZlBmWW50c01zOHhsTC9Tc0VmQkRXaW1EYzRFcjhVcnYwNDdhWnk3a0NBbHdzbVloeFhBdXIrVHBvMzR3czk3VWRrOTllM0lrNU4wYnh6TWdyS0RSTVk0eElKSmhITkY1VldQZ1F3emtDYnF1RFhEN0l5UTV4cmxGQXBTSU9sZmdRVE9lUG5rMW9jQ0FTV2pnWkF3Z1kwd0hRWURWUjBPQkJZRUZDUmdhZ2R6SkZWMU96YjZkRm1UVmNteUFDWTZNQjhHQTFVZEl3UVlNQmFBRkNSZ2FnZHpKRlYxT3piNmRGbVRWY215QUNZNk1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0dHTUNvR0ExVWRFUVFqTUNHR0gyaDBkSEE2THk5allTNXpiV0Z5ZEdOaGNtUnpaV04xY21sMGVTNWpZUzh3RFFZSktvWklodmNOQVFFTEJRQURnZ0lCQUtOM0c5OXI1ZUprVVdLRDFKYzlheXpaRnBJeENzaE5iVkdJZk5lMFppd0NCOUt0UmlPK0VqRXVuSmxVT2ZqblhNWk9EMThrdTRwNlU1ZTBKQ1NWSHhQSDc2cDEzc1dGYnhjWWl3dXRjYU93c09LSElsZjI4MWFuSXR3WmJHT2VTWjlveVRiclNLQlNQWDlKamhzcTBieVB0UTVUUlZ3bjJoQ1JlZUkyUkJicy81S0RSSEtNSjNDc3dJWllXcnlCelp6R3ZHUGxkUXRNVWUyTlBpVFh2Mnk4NkNZZXd3aGlNUVJPM2kva1pzamZlV0lrcUpZVHpqQTlGREhERXJTeWNlOGUvMXNYZ0RhYnFwRW82enJ4ZDVIZ1FHQjhGSW1WYTdLdExJSXFsUUU5QVg0V3hBeU51ZHl2aCtPbDMzNU1hNFFQNmtjalgxdUY4d2krUTcrTjl3QW9XNEI2UE9pUDZ0V2JaRVA5ME1KRTU5SkpnUGNaMTd6M2U3MExYc0pPcVpBUUhqT1ZlUzk3RHJkeXFhMG03YVcxQ08rcExBTWROL1RobE1iS0NFampPSWwrUkJPQWZ1WTh4NER6RlBoMWM5UU05bXJqbzdLc1NqWUJiSzVqVVhuWG9RVVFJUHdTUUVyK21UVGNBeEtHcGdXUHVGUWNqM2cwbUxqeEtqVXRqcm1DVC9TMzZoWkRsUS93RityM2FTK2hLazduUjlzVmpSWUJHMW43OVJnQWVIcEE0NWlWYXI0YXlGSmFFUDhPKytWUmlBVU4rWTdtcXJBK2p6OTdrNmJHaWxyRTJGbFcvMlBZVGVnZ3QvMFdUbVltSnVFTkFtR3lqQU41RXlyUFIrSUxlcVhsTHBMYTd0WWJZMkRGTXRkNVVtOU55STFpbUZFTm92VjUrbGJEIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQWxnQUFBS0tDQVlBQUFEaGtDWDRBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBQUlHTklVazBBQUhvbEFBQ0Fnd0FBK2Y4QUFJRHBBQUIxTUFBQTZtQUFBRHFZQUFBWGI1SmZ4VVlBQVFXTlNVUkJWSGphN0wxMWZGM0plZi8vUG5qNVNycGl0Q1NEekF6THpOblFOdHlBa3pUUXRQRTNiUW9wTisydm1LWkozS1JOQ3FtYVFwZzN1MW5tdGVVMWsweVNaVEZMbCtIUTd3L1pYbnN0Smd2bS9YcnB0V3ZwbkhQbnpzeVorY3d6enp5UDVEZ09Bb0ZBSUJBSUJJTHBReFpWSUJBSUJBS0JRQ0FFbGtBZ0VBZ0VBb0VRV0FLQlFDQVFDQVJDWUFrRUFvRkFJQkFJaE1BU0NBUUNnVUFnbUN1b29nb1dOcElraVVvUUxBaDI3Tno5QVBBRjRGMTF0YnZxUlkwSUZnTGlKUC9DUlZpd0JBTEJmQkJYSHdkK0Rxd0ZYdDJ4Yy9kZG9sWUVBc0ZjUmhMcWVZRTNzTEJnQ2VhM3NGSVlzbHI5MWh2K1pBS2ZycXZkOVhWUlM0TDVqSmlEaGNBU0NJRWxFTXkydUFvQzN3WWVHdVd5cndLZnFhdmRaWWthRXdpQkpSQUNTeUFFbGtBd3VyaXFBaDRGVm8vajhxY1k4c3NhRkRVbkVBSkxNRmNRUGxnQ2dXQ3VpYXU3Z2YzakZGY0E5d0w3ZHV6Y3ZWYlVua0FnbUNzSUM5WkNiMkJod1JMTUgyRWxBYjhOL1Awa0YzOXg0TU4xdGJ1K0wycFRNRjhRYzdBUVdBSWhzQVNDbVJSWGZ1QS9nSGROdytQK0FmaUR1dHBkcHFoWmdSQllBaUd3QkVKZ0NSYXJ1Rm9EZkI5WU5ZMlBmUWw0VDEzdHJuWlJ3d0loc0FUWEErR0RKUkFJcnFlNCtsV2dicHJGRmNDdHdLR0wvbHdDZ1VBdzZ3Z0wxa0p2WUdIQkVzeE5ZZVVHdmd4OFlvWS95Z1krRC95VkNPVWdtSXVJT1ZnSUxJRVFXQUxCZEltclZjQjNnWFd6K0xIUEE3OHF0Z3dGUW1BSlpndXhSU2dRQ0daVFhIMlVvUkFNNjJiNW8rOEFqdTdZdWZ0aDBRb0NnV0EyRUJhc2hkN0F3b0lsbUJ2Q0tnaDhBM2pQSENqT1Y0RGZyNnZkbFJZdEk3amVpRGxZQ0N5QkVGZ0N3V1RGMWEzQWZ3Tkw1bEN4amdIdnI2dmRkVlMwa0VBSUxJRVFXQUloc0FUelNWaHB3RjhBdjhmY2RFZklBSDhJZkttdWRwY3RXa3dnQkpaQUNDeUJFRmlDdVM2dVZnSC9DMnlhQjhWOUR0aFpWN3VyV2JTY1FBZ3NnUkJZQWlHd0JITlJXTW5BTHVCdkFQYzhLbm9ZK0V4ZDdhNWEwWW9DSWJBRVFtQUpoTUFTekNWeHRSejRKbkRMUFA0YWp3RWZyNnZkMVNaYVZDQUVsa0FJTElFUVdJTHJLYXd1V2EzK0d2QXNnSzhrckZrQ0liQUVRbUFKaE1BU1hGZHhOV3RXSzhjMnljUUgwUDE1czlXdmhUVkxJQVNXUUFnc2dSQllnbGtWVmlyd0dZWk9DYzY0MWNvMk14aVJDM2kxRENuTGd4cGNnaVFycy9GVnc4RG5nRy9VMWU0U2c2VkFDQ3pCdUJHUjNBVUN3VVRGMVZaZ0gvQ0YyUkJYWmpwT2VxQ0p0MnhvNUl2dmVaWE41VzFrQmh1eHpWbUpFNW9GL0F2dzhvNmR1OWVJMWhjSUJPTkZXTEFXZWdNTEM1Wmcrb1NWSC9oTGh2eXRabVZ4WmlZSE1PSTlmT3JPNDJ5cDdMbjgrMThjV2NLUERsYWpCVXBSWGI3WnFnSUQrRHVHRWtlblJJOFFUQWRpRGhZQ1N5QUVsbUJ4aTZzM01XVEpLWitsYVFjcjFvbHNEZks3RHh5aU1pOTZ6UldIbXZQNDJqTnJVYjE1cU43YzJheU9zOEFuNjJwM1BTdDZoa0FJTElFUVdFSmdDUVNURVZaTGdDOEJiNSsxQ2NlMnNLSXQ1SGtIK1owSERwSHR6WXg0YlV1L255ODh2b21NRkVUeGw4NTJmLzgvNEhmcWFuZDFpSjRpRUFKTElBU1dFRmdDd1hpRWxadWhGRGVmWXhaREwxaEdDalBTd3BiS0xqNTZhejJhTW5ZR20xaEtZL2ZUNjdrd2tJTVNxRUJXdE5tc3FoaERqdjVmcnF2ZFpZaWVJeEFDU3lBRWxoQllBc0ZJNHVwaDRDdEE5V3grcnBrTVk4UzZlTStPczl5N3BuVkM5OXFPeFBmMkxlV3BreFZvZ1pMWjlNdTZ4Q2xnVjEzdHJxZEVEeElJZ1NVUUFrc0lMSUhnU21HMUZOZ05QRFRMTXd4bXZCM0ZqUENaKzQ2d3ZEQTg2VWU5ZGo2ZmYzMStEWW9uQjlWWGNEMnE4WWZBWit0cWQxMFFQVW9nQkpZUVdLSVdoTUFTTEc1aGxRMzhNZkJwUUovTno3WXRBeXZTVEVWb2dFL2ZmWXlnSnpQbFozWkZQSHpwaVkwTXBvTW9nZkxaaXBkMUpTbmdpOERmMWRYdWlvb2VKaEFDU3dnc2dSQllnc1VsckRUZzE0RS9BMEt6L2ZsbUtvSVI3ZVRCOVJkNFpNdDVaR242eGlMRGtxbDllU1YxNTR0US9hV29MdS8xcU9MdWkzWDc3M1cxdTB6UjR3UkNZQW1CSlJBQ1M3RHd4ZFhiR1lycHRIejJKeFFiTzk0QlJwVGZ1UHNZYTB2N1oreXo5cHdyNUQ5ZVdvWHF5VUgxNVFQWDVYMm9CMzZ2cm5iWG82TG5DWVRBRWdKTElBU1dZR0VLcTIzQVB6SUx1UU9Id3pMVFdORVdxbklIK0kyN2prOTRTN0FuNmlFL2tKelFQZDBSRDE5NWVqMjlpU0NLdjN5MlR4bGV5Yk1NaFhVNEpIcWlRQWdzSWJBRVFtQUpGb2F3V2cxOEhuakg5U3FEa2VqSGlQZnl5SlpHM3JUaHdvUnNTUTd3dlgzTGVmeG9PUisrOVJTMzE3UlBUTmpaRXQvZHQ0eG5UcGFoQm9yUTNNSHJOcDhDM3dQK3RLNTIxeG5STXdWaURoWUNTeUFFbG1CK0NxdGx3SjhDNytjNjdZL1psb2tkYjhXcnhOaDF6OUZobzdLUEtzd3NtWDk1YmkxSDJ3cFF2QVVZc1U3dVg5UE11N2FmbS9BWE90R1d3ejgvdHc1YjlpUDdTcTZIQS94bHpRZjhEL0Q1dXRwZDUwVlBGUUpMSUFTV1FBZ3N3ZndRVmhYQUh3RWZCYTZiaWpCVFVZeFlKemN2YStmOU41NUZWNjBKM1I5TzZQejlMemZUSGM5R0Q1WWh5UXEyWlpBSnQ3Q3FxSmRQMzMxMHdzK01wMVcrK2RKcWpyYm1vVncvQi9qTCtoSDRKdkNYZGJXNzJrVFBGUUpMSUFTV1FBZ3N3ZHdVVnNYQTd6TjBPbEMvWHVWd2JHdklrZDJNOGNrN2o3T2h2Ry9DejJqdTgvTjNqMjhtSStmZzhoZkNGWDNac1cweWtUWkM3a0YrLzZFRGhIenBDVDkvejdsQ3Z2bnlLaFJYRU1WWGlDVEoxN1BwVXNBM2dMK3VxOTNWTFhxeUVGZ0NJYkFFUW1BSjVvYXdxZ0IrRi9nMXdIMDl5MkttWXBqeER0YVc5dkxSVytzSnVDZWVRV2JmK1FLKzhmd2FGRTgrdWk5bnhPdlMwVzRVczUvZnZ1OElLNG9HSi93NS9YRTNYMzl1RFUxOTJjaitVbFRkYzcyYk1nbjhHL0RGdXRwZHphSm5DNEVsRUFKTElBU1c0UG9JcTFVTVdheCtGVkN2NjBSeDBXcGxHekUrZW1zOTI2c25ib2l4blNGbjlLZE9sS01IeDVmeXhraEdobExzYkQvTGZXdGJKbDV1NE9VenhYenIxUnBVVnhENStsdXpZR2pyOEg4WUNsWjZXdlIwSWJBRVFtQUpoTUFTekk2dzJnTDhJZkIycnBQeitwVk1oOVVxbXRMNHlsTWJ1TkFmUXNzcW0xQTRCY3RJWVVSYTJWVFJ6Y2R1T3psaHZ5eUFnYmlMZjN0eE5lZTZjeTVhczd4em9ha2RodEx2L0xVSTd5QUVsa0FJTElFUVdJS1pFMVozQXA4RDdwc1RrNE5sWWlmYXdVenc0VnNtWjdVQ09OY2Q1RXRQYmlRalphRUhpaVpsUVhKc2kweWtqU3c5d21jZk9FUnhWbUpTWlhucFRESC8vV29OaXN1SDdDMituaWNOMzhnVHdOL1cxZTU2WHJ3SlFtQUpoTUFTQ0lFbG1McW8wb0YzQWI4TmJKb3I1VEtTQTVpeEhtNWMxc243YmppTFY1OWNOcGhmSHF2Z2U2OHRRL1VWb0h1enBseXVkS3dQTzlYSHI5MTJraHVYZGszcUdaR2t6cmRlcmVGUWN6NnF2d0ROblRXWHVzUUI0RXZBOStwcWR4bmlEUkVDU3lBRWxrQUlMTUhFaEZVZThESGdONEdTdVZJdTIweGp4OXZ4YVhFK2Z2c0phaWJoWEE0UVQydjg4M05yT2QyWml4WXNSZEdtenpmZlRDY3dvdTFzcis3a3d6ZlhvNnYycEo1enJEWEV2Nys0bXJUalEvYVdJS3Y2WE9vaTdjQlhnWCt0cTkzVko5NFlJYkFFUW1BSmhNQVNqQzZzdGdHL0Fid0hjTTJkaWNER1N2U1FTWVI1ZU1NRjNyS3hDVldabkhBNTI1WEZsNS9hZ0NFRjBRTEZNK0pVN3RnbVJxUWR2eGJsdCs0N1RIa29OcW5uWkV5Rkh4Mm80c2tUNWVqZUhGUnYzbFVoSStZQWFlQTd3RmZyYW5mdEYyK1FFRmdDSWJBRVFtQUpYaGRWWG9hMkFYOGQyRDdYeW1lbW9sanhUcXJ6Qi9ud0xhY29tcVIvaysxSS9QUlFGVDg3WElrMlRWdUNZd3FrZUQ5bW9wZjMzWENXdTFlM1R2cEVRT3VBai85NGFUV3RBd0ZrYnpHYTJ6OFh1MUlkOEhXR3RnOFQ0czBTQWtzZ0JKWkFDS3pGS3F6V003UU4rQUVnYTY2Vjc5SjJvQzRsK2VETnA5aGEyVFBwWi9WRVBleCtlajJkMFN5MFFPbXNicmNOblRKc1kybitBSis2NnhoWkUwd3lmWGt5Qk9vYUN2bnZWMnV3Wk05YzNEYThSQmo0YjRhMkQ0K0pOMDBJTElFUVdBSWhzQmFEcU1wbWFQdnZJOEMyT1RubzJ6WldvcHRNTXNLYjFsL2d6UnViSnUzSEJFTW44MnBmV1luaXprSDNYWjh0TnNleE1hTGRZSVQ1NUozSDJieWtkOUxQU2hrS1B6MVV4UlBIeTlHOVdTamUvTGtRTzJzazlnSC9DWHlucm5iWG9IZ0RoY0FTQ0lFbEVBSnJJWWtxQmJnZitCRHdWdWFRYjlVYlJudU01Q0Jtb3BkVnhmMTg4T2JURkFTU2szNWNMS1h4alJmV2NySWpoQllvbVJPeHBZeFVEQ1BXd2JiS2JuYmVmQXJQSkU4L0FuUU1ldm12VjFkeXJpc2J4WmVQNXNsaURvUWxHNGswOEJPZ0ZuaXFybmFYSmQ1TUliQUVRbUFKaE1DYWo2SktCbTVteUZyMVRpQi9McGZYU01Wd2twM2srdUo4OE1iVHJDb1ptTkx6RGpUbDg2OHZyTUZSQTJqK0lpUjU3bGg0SE52RWlIYWdFZVBYN3pqTzJyTCtLVDN2ZUd1SWIrMVpTVGpwUWZJV2p5c0MvWFdtQi9nK1E4N3hyOVRWN3JMRkd5c0Vsa0FJTElFUVdITmRXRzBGM3N1UTAzclpYQyt2WmFSd0VoMm9wSGp2ampQY3RLd0xTWnI4dUJCTGFYeno1ZFVjYWNsRDh4ZWh6azFuOENGUmVUSE56bzdxTGo1NDAra3BXYk1jUitMRk04VjhkOTh5Yk5tRDVDbEcwVnp6b2N1MlhCUmIzeGFuRUlYQUVnaUJKUkFDYTY2SnFpM0FJd3hacTZyblE1bHR5OEJPZEdLbUU3eGxVeE1QckcyZWtwOFZERm10L3UyRk5kaHFBTTFmT0plaW9JODh3VmttUm16NnJGbHBVK0d4b3hVOGVxUVN6ZTFGOWhST0tPM1BkYVlSK0QvZ0ozVzF1dzZJTjFzSUxJRVFXQUloc0daYlVNbkFqUmRGMVNOQTVYd3B1MjJaT01rdTBzazRkNjVzNDYyYm1naE84bFRkSlFZU0x2Nzl4ZFdjNmdqTmVhdlZTRnl5Wm0xZTBzdUhicDVjUHNVckdVem8vUGhnTlMrZUxzYnQ5U041Q3BBVmRUNVZTUlB3STRaeUllNFYyNGhDWUFtRXdCSUlnVFZUb2tvRGJnTitCWGdiVUR5dkJuTGJ4RTcwa0VwRXVXVkZKMi9iZEo1Y2YycUtrNFBFTS9XbGZMdHVPYkllUlBjWHpDbGZxNG5Ya1lVUjY4SXhvbnpneHRQY1d0TXhaWmYxdnBpYkgreGZ5dDZHQWx5K0lJb25EMGxXNTF2VmRERGtJUDlENEVXUm9rY0lMSUVRV0tLQmhjQ2FxcWdLQVE4Q2J3WWVZQTdHcWhxUGFMQ1N2YVRqWWJaWDkvRElsZ1lLZzhrcFA3ZHR3TWUvUExlT3ptZ0F6VitNb25zV1RMdWI2UVJtcklQeVVJUlAzSDU4MG9GVnI2UXI0dUY3KzVaeDhFSWVMbDgyaWlkM1hteWhEa01ZK0NYd2MrQ3h1dHBkQTJLa0VBSkxJQVNXRUZpQzhZaXFGUmNGMVp1Qlc0QjVPUXZhbG9tZDZpV1RpTEMrdko5M2JqMUhhVTU4eXM5TkdRby9PckNVcDA2V29YcEN1SHlodVpZNlp0b212a3lzRnlzMXdBUHJXbmpicHNZcCs2aGRFcWJmcVZ2T2lmYWNvUmhhN2x3a1JaMnYxV1FCTDE4VVd6K3ZxOTExUm93Z1FtQUpoTUFTQWt0d1NWRDVnTHVCKzRDSGdLcjUvSDFzTTRPVDZpR1ZpTE85cW9lM2JEby9MY0lLWUU5RElkOTZkU1VXWGxSLzBWeU5ZajY5Q3NKTVk4VTYwYVVFTzIrcG4xSTAremNLclI4ZnJPWkFVOTVGSDYzOCtlUU1QeExuZ2NlQUo0Qm42MnAzeGNVSUl3U1dFRmdDSWJBV2o2Q1NnTFVNQmY1OGtDRXIxYnhYQ3BhUmhsUTM2VlNTVzFkMDhPWU5UZVFGVXRQeTdOWUJILy8yd2hyYUJvTW92c0s1bW9kdlJqRlNVY3hZRjFYNVlUNTZ5MG1LczZjbjFWOTMxTVBQRDFmeXl0a2lYRzR2dVBQblMzaUhzY2d3Wk4xNi9LTGdPbDVYdTB0TU9FSmdDWUVsRUFKcmdZbXFTb2FzVkpkK0NoYktkelBUQ2FSME4wWW16YjFyV3JsL2JUUFozc3kwUER1ZVZ2bkIvbVU4ZjZvRXpSdEM4NFVXZFo5eUhKdE1yQTh6TmNnOXExdDUrK1pHdkZPSW5YVWxnd21keDQ5VjhQU0pjblMzQzBmUFIzVjVGMUwxZFFQUFhQcXBxOTNWSkVZbUliQ0V3QklJZ1RYL0JGVXBjQ3R3NTBWQnRYU2hUZlJtS2dLcFhqVFo0SUcxRjdocmRkdTBUZmFtTGZQVThUSitkSEFwa3VwRjlSY3VoTzJyYWNNMk01anhMakFUdkdOYkEzZXZha1dScDJjc1RXUlVuajVaeGhQSEtqQWREZHg1cU83Z1hNNTFPRmthTG9xdDV4ZzZtZGd1QkpaQUNDeUJFRmh6VDFCVk1yVFZkOGZGbjZVTDhYdmFsb0dkNnNkSWhpbkxpZlBRK2lhMlZ2Wk0yK1R1QVB2UEYvQ3RWMWVTc3R5b3ZxSUZkVHB3dWpFekNheFlGejQ5eVFkdnFwOVNBdWszWXRrUys1dnllZXhvSmEwRFBqUlBGckk3dEpDRmJnUHcvTVdmbCtwcWQxMFFBa3NnQkpaQUNLelpGVk51WUROd0UzRER4ZjhXTCtSMk5ETUpwSFF2cVdTSzdkVTlQTGp1QXBWNTBlbWQzYnFEL09mTHErbU0rRkM4aFdpZWdIaUJ4b21SakdER3V5bkxpYkh6NXBOVTVVOXYyelQxQm5qODJCTDJOZWJqOXJoeFhIbHpJbkgyRE5NQnZBcnN2ZmpmZzNXMXUxSUw3VXVLT1ZnSUxJRVFXTmRUVUZVd0ZEWDkwczhtWU1IdlZ6bTJoWmtLUTdvUFZUYTVaM1VMZDY5cW0zTFU5VGZTM09mbk8vdFdjS29qRzhXYmg4dWJ2U0RETHN6R1JHbkVCekFTZmF3dUhlUjlPMDVQMituTlMwU1NPcy9VbC9MMHlYSk1Xd1ZYTHFvN2E3N0cwNXF3amdVT0FYc3UvZFRWN21vV0Frc2dCSlpBQ0t6eGlha3locXhURzRFdHdEWVd1SFhxRGNQdGtOTjZwbzlVTXMycWtnSHVYZFBDaHZJK1pHbDYzOVdPc0pmdjFLM2dXR3NJeFpPRDdzMVpMQlAxakF0akk5R1BrUmhrWTBVZjc5bHhabG9DdTE2SjdVZ2NhY25scVJQbDFMZG5EMW0xOU55TFR2R0xTaHgzQVB1QWc4QmhocXhjclVKZ0NZVEFFaXhhZ2JWajUyNkZJVCtwUzJKcU0wT1dxYnpGMkU2V21jWkpEMkttSWdSY0dlNWMxY3F0eXp2SThhV24vYk42bzI2Kys5cHlEalRsbzdpejBIMjVRbGpOaU5BeU1lSkQvbkxicXJ0NTk3WnpVMDVOTkJ6OWNSY3ZueTNtdWZveW9tbDl5Q0hlbFkyaXVoWnIxZmRlRkZ5SHJ2aHBxS3ZkWlFtQkpSQUNTN0JnQk5aRklWVU5yTG40cy9yaWYxY0Nyc1hjTnJhWndVcEhJRE9JYlZ2c3FPN2k5cHAybGhlR1orVHp1aUllZm5Ld21yckdRbFIzRU5XYk85K1NEOC9QZHJaTXpFUXZSakxLVGN1NmVPdW1SZ3FtMmFKMWliTmRXYnh3dW9TNnhrSmtXUUU5RzhVVlhCUUJZY2NnRFp3Q1RnQW5MLzczQk5CNHZZV1htSU9Gd0JJSWdUVWVNWFVqUTA3bjFReFpwNVlEUzFnRS9sSVRtV3l0ZEFUWkdDQ1RzZGhjMmN0Tnl6cFlWOWFQS3Rzejhwbk5mWDUrZUdBWlIxdENhSjRncWpja1FpNWNsN1kzTUJOOUdNa29HeXY2ZUdSTEErV2gySXg4bG1uTEhHc044Y3JaWWc1ZHlFUFhGV3d0WjBoc0NWRjlKUWJRQkp3RkdoazZ5VmhYVjd0cmp4QllBaUd3QkhOSllIMEhlTGVvOVdFbTFsUVV4UndnbmJaWVc5N1BMY3M2MkZqUk95MjU3VWF6WnZ4Zy8zTE9kQVpSUGRub3Zod2tXVXl1MXh2SE5qRVNBeGlKUVdxS3c3eGo2MW1XRlVSbTdQTXlwc3poNWp4ZVBsZk04WllRTHBlQ3BlYWd1Z05DYUEvUGQrdHFkNzFIQ0N6QlZCR2pyV0E2U1lvcXVDaXF6RFJXT29wa0RHSVlOdXZLKzdtaHVwT05GYjI0dFpuYmtYQWNpY010dWZ6azRGSmFCM3dvN2x5OGVWbkN4Mm91TFhwa0ZkMmZqK1lOMFJBZTVLOGZ6YUk4Rk9kdG14dllXTjZITk0ySEdYVFZabnQxTjl1cnUwbG1WSTYwNUxLbm9ZampyU0UwVGNiUnNsRmNBV1RWSlJwSGpHTUNJYkFFYzVUd1l2N3laaVlKUmdRbkU4RzJiRFl0NldWSGRSZnJ5dnBtMUZJRmtNeW92SEM2aEY4Y3JTUnA2TWp1WE55NUN6TDY5d0lTV2dvdWZ5Nk9MNGVPUkppdlBSdkFxNmQ1YUYwVHQ5ZDA0Sm1tcVB4WDR0Rk5ibGpheFExTHU4aVlNc2RhYzZsckxPVFFoVHhrUlViU2c2QUZVWFUzaSt3MG9oakhCRUpnQ1FSekJjZTJNVE54RkhPUWRDcUZWemZZV3RuTmxpVTlyQ29abUxibzZxUFJFZmJ5K0xFbHZIS21DRVYzSWJ2emNBZDlvbkhtazlDU1pIUmZEdmh5eUtUai9PaXdqKys5dG94YlZuVHkwTG9MRkdVbFp1UnpkZFZtUzJVUFd5cDdzR3lKK3ZZY0RseklaMzlUQVltSWhzdnR4bEt6VVhVZmtpeUV1a0FnQkpiZ2VyTGdjNnBZUmhvckUwTzF3aVJTRnFVNUNYWXM2MlRUa3Q0WmMxaCtJN1lqY2JRbGwxOGNyZVJjVnhETkU4Q1ZreU8yZUJiQ2dPenlnY3VIYXFiWjJ4emtwZFBGTEN1TThLYjFUYXlmZ1Zob2wxQmtoN1ZsL2F3dDYrZERONSttcGQvUG9RdDUxSjB2b3EzWGk5ZXRZQ3BaS0xvZlJWdncvY3d0ZXFKQUNDekJYR1BCamJ5T2JXRm1Fc2htQkNPZFFKWnNOcFQxc2FHaWgvVmwvZE1lVlgwMHVpSWVucTB2NDRYVEpWaU9CcTRRM3J5ZzhLOWFnTWlxQ3oxUWhPYkxweWtXNFd2UFphTklCbmVzYk9mT2xhM1RIcmowalpTSFlwU0hZcnhsVXhPUnBNN1IxaEJIbXZNNTBwcUw0Y2hvTGkrMkdrVFZ2UXV4L3dtQkpSQUNTekRueUozM2dzcHhzRElKSERPR2JFWkpwaHpLYytOc1dkck4rdkkrcXZLaTArNkVQQm9aVTJIZitYeWVPRjVKYTc4WHplMUg4V1hqRWdtWUZ3V1NyT0M2dUgxb1paSThlemFMSjQ2VlV4WktjUC9hSnJaWDlhQ3JNeHZHS2VqSmNNdnlUbTVaM29ualNKenZEWEMwSlpmOUZ3cG83ZkhoY1V2WWFnQko5YVBvbm9YZzk1Y3JlcDVBQ0N6QlhHUGVSV0YzSEFmTFNPSVljUlFyU2lKcGtSZElzM0ZKRDJ0SysxbFZQRENqcC82R0w1UEVtYzRzWGpoVFNsMURBWXFtZ1I3Q214OFFUdXVMR0VYM29PZ2V0SUJOVnpMS3QvWUcrYytYRFhaVWQzUDdpalpXRklWblhQeExra04xZm9UcS9BaHYyM3llWkVibFZHYzJKOXBDSEc3T3A3ZmJoZGVqWUNrQkpNMkhvbm5tWXo1VUliQUUwL08raUJnY0M3eUJaemNPVmhORGdVWG5ycUN5TFN3amhXTmVFbFEyT2Y0TTYwcjdXRjB5SktpeXZKbnJVclp6M1VGZVBWZk1xK2VLTUcwVlNjOUM4d1NGYjVWZ1JHd3pqWkdNNEdUQ3FMTEpUY3M2dVdsWng0ekcxUnFOY0VLbnZpT0hrKzBoanJYbDBoL1Q4WHBrYkNXQXBQcFFOUGQ4MkZKc3FxdmRWVFdiaXp5QkVGZ0NJYkJHRTFjNlEvRmo1cFNKeFRMU1dFWUt4WTVpRzBsU0dTak9UcktxdUovVkpRUFVGQTNPcWgvVk5TTjViNEE5RFVXOGVxNllSRVpGZG1XaHVnSW9ZZ3RRTU5HK25rbGlwaVBZNlFoZTNlU21aUjNjdUxTVHlyem9kU3RUT0tsenBqT2JrKzA1MUhlRTZCajA0TlpCMWp4WWNnQkZjNk5vT25Nc0pJUU5lT3BxZDgzS3dDRG00SVdMMkNJVVRCZExyN2U0Y2l4ektHbXlrVUJ4WWlSVEppN1ZZa1ZCaEpYRi9Td3ZDRk9WSDUxeG41WFJCMU9KaHU0Z2V4cUtxRHRmU0NLdG9yb0N5SzRnbnFCWDlDTEJwTG0waFVpZ0VDT2Q0TGx6T1R4MW9oeXZ5MlJIVlJjM0x1MWthVUZrVm4wSXN6d1p0bFYxczYycUd4anlLVHpmRStCc2R4YW5Pa0tjNnc0U054UThiZ1ZMRGlCcFhtVFZkYjNUK2NnTXBmczZKWHFWUUFnc3dWeGd3Nnd1TVMwRHkwaURsVUMxNDZUVEpwYnRVSlNkWW1WRlB5c0tCMWxhR0tFZ2NQMkRNcHUyekttT2JPb2FDM250Zk1IRjdiOGdpdHVQVjRncXdVd003QzR2dUx6b0ZHRm1FcnpZRk9LRk0yV29zc20ycW01MlZIZXhzbmh3eHZKZmpvU3VXdFFVRDFKVFBNakRHeTRBMEIzMTBOQVY1RXhYTnFjNlEzVDJ1VkZrQ1pkTHhaUjhvSHBRVk5kc0o2eGVKd1NXUUFnc3dWeGh5MHc4MUxGTUxDdURiV1JRbkFTU25TU1Z0cEVsbTdLY0JNdkxCbGlTRjZVeUwwcHhWbUpXZ251T2gxaEtHMHBKMGxoTWZWczJzcUlNUmNqMkIzQnI0aFM0WUJZSGVkMkxxbnVCUWl3anhkNldYUFkybG1KYkZxdEtCN214dW9NTjVYMzQzY1oxS1Y5QklFbEJJTW1OeTdvQXNHeUpqckNYcHQ0QUYzb0RuTzNLb1hYQWkrM0l1SFFaRkRlV2ROSFNwZW96WmUzYUNueGY5QjZCRUZpQ3VjRDJTWXNvMjhZMjA5aVdnV05uVUowazJCblNhUnZiY2NnUHBLbklqMUlSaWxLYUU2YzhGQ00vbUp4VFhoc08wTkxuNTNCTEhuV05SYlQxZTNHNU5SdzFDMWVPYjdaWDN3TEJzQXo1UExtQmZHd3p3NW1CT0dmM0ZwQit3YUFzbEdCN2RTY2J5M3NwejQxZHQvZExrUjNLY3VLVTVjUzVaWG5uNWZlckorS2hwZDlQMjRDUDV2NEFGL29DOVBhNWtDUUpseTRqS1RxbTVFR1NkV1JGUTFaZFU0bEFmNFBvTFlLcElwemNGM29EejRLVCs0NmR1NzNBSUtCTjV2NU1Jb3lUNkdScFlZVFM3QmlGd1FRRndTVEYyUW55QTZrWmkxNDlWV0lwamVOdElmWmZLT1JZU3dqVGxsRjBINUlXUUhWNVJRQlF3YnpCc1MzTWRBTEhpR0psNHFqeVVJTHlMVXU2V0ZmYWY5MnNXMk5oT3hMZEVRK2RZUS9kRVE5ZEVTOXRnMzRhdW9KSTNpSjBiOVprSDUwQmN1cHFkeVZtdk83RkhMeGdFUllzd1hSdzIyVEYxU1VSdUt3b3d1ODllSEJPZjhtTXFYQ21LNHVqTGJrY2JpbWdLK3pDN1ZLeDFTelVnQmVQMlBvVHpOZUZtS3lnZVFMZ0NRQmdHU21PZE9WenJLMklWTnFrTUpobVkwVVA2OHQ3V1ZFWXZxNEhSYTVFbGh5S3NoTFg1R3Y4dThjMzB4Z3Ruc3FqZGVCVzRBblJPd1JDWUFtdUoyK2U0dWhPUEQzM3VxSmh5WnpyenVKVWV6YUhXZ3BvN3ZPaGF6S09Ha0RSdlBnTHZDTHdwMkJCOHZwV1lnalZ0b2xrRWp6WFdNRHpaNkprREp1SzNEZ2J5bnBZWFRyQXNvSXdtbUxQcWZJbjBpcE0vZDE4c3hCWWdpbE5iY0k4dWNBYmVJYTNDSGZzM0MwRHJjQ2tsNHRtS2thaGRwYlB2MjNmOVIyVU15b04zVUZPZCtad3BEV2ZsajR2bWlxQjZrZldmS2k2QjBrUmF4TEI0c2F4VE14TUV0dUlneG5ETUIzS1F3bldsZld5c21pQXBRVmhmQzd6dXBieHozNnluUzVqT2FyYlA1WEhkQUJsZGJXN1psUTlpamw0NFNKbUM4RlV1WDBxNHVxNlRSS09SUHVnbDdOZFdkUjM1SEs2TTV1QnVJWkxsM0ZVUDdMbXhadnJ1ZDd4ZUFTQ3ViZG9VOVNydGhNMXk2VGJTUExVMlNLZXJvK1J6dGprK0F4V0ZBNnlxcVNQNVlWaFNyTVRzeHAvYTVvb1pzajk0WG5SNmdJaHNBVFhnNDlNV2V6ZzRGSm5kb3RoSU82aXFTOUFZM2VRRSsxNU5QZjVjSkJRTlJlMjRrZlIzZmg5YnJIbEp4Qk1FRmxSa1pVQXVBTkFJWnBqa3pKU0hPcEtjYVE5aG1ta3dYR295SXV6dXJpUHBRVmhLdk5paEh5cEdTdVRydG80bVdrUmRCOFJBa3N3NmNXSU1FOHU4QWFld1MzQ0hUdDNoeGphSHB4U1hwZE1Jc3lhMEVuKzM3MUhwMXdtQitnS2U3blE1NmV4Sit0eURKMk1LZVBTRld6Rmg2eDZVRFMzQ0owZ0VNd1N0cG5CTWxMWVpoTFppcFBPV09pS1RXbE9naFdGQTFUbFIxaVNGNlVvbUp3V1M5ZFhubHJQaWY3VlV6bEZlSWtrVUZwWHUydGdwdXBHek1FTEYySEJFa3lGVDB4VlhBRTR0a25JUDdIVnJHVkw5TVhjdEE3NGFCdndjYjQzbTVaK1AzMnhvYnhtbXE1aHl6NWsxWVVhZEtPckduTXMzNWxBc0dpUVZmM2lnaVlJZ0lhRGJXWm9UNmRwYlV3am40dGpaQXdjeHlFdmtLRThGS01xYjVEU2kvR3djdjJwQ1FVUkR2bFNPTDNUNGdmbUFUNE8vSjFvUmNHRURSeENQUy93QnA0aEM5YkY1TTduZ1pJcHIyN2piVHkwNnRqbDFCbkRjYmc1ai8xTkJiUU4rdW1OdW9ra1ZSUVpORjNCa2J5Z3VHWTZzck5BSUpoaGJNdkFOalBZWmdhc05KS1R3TWhZV0RZRVBTYjVnUlFsMlRHMlZuYXpzYUozeE9jOGVtUUpqOVd2US9hVlRrZXgyb0RxbVVyK0xPYmdoWXVZaVFTVDVTUFRJYTRBSkR0OVRSeWJON0szb1loOXpaVm9uaUN5UjhQdjEwUWdUNEZnZ1NFckdyS2lnY3QzK1hjYUZ3T2hXZ1p0S1lPbTh4RXNXeDVWWUJVR0UyQ2xwNnRZcFJmSHU2K0xGaEpNcUQrTEtoQk1sQjA3ZDN1QVA1eXU1NlV6MXBnQ3k2T2JLTG9ielJOQTBkeENYQWtFRTBDekI4bHhUbEVnblVDMysrZGQrU1ZaUWRFdXZ2KzZHN2MyK3ZaZlVWYVNqREd0d1ZEL2NNZk8zU0tTc0dCQ0NBdVdZREo4QmlpZmpnY05KWE4yS0I1RFlIbDFRNWpTQllLSnZsKzJRYmJUd0wycnpuSDdpbllreWVFL1hsckxvYjR0b014UHZlQTREajU5OU4yNmt1dzRsdVZnVytaMHVReVVBNzhGL0kzb1ZZTHhJaXhZZ2dteFkrZnVZcWJSZW1VWktVcHpFbU02c0E2NWtnbUJKUkNNRjVmVndjckFRZjdnZ1ZlNW82YnQ4dW04WDcyaG5peXBlUjZyUmdkNUROZFNSWFlveVVsaUdkTWFDdUlQZHV6Y1hTUjZsa0FJTE1GTThTWEFQMjFQczJLc0src2Q4N0o0V2hNeHFnU0NjYjFUR2JMdGVqNndlUStmdnV2d05ZbWEzWnBGY1dBQXg3SG41ZGVUWkpsb2V1d1FLK3RLZTVITTJIUitkQUQ0c3VoZ0FpR3dCTlBPanAyNzN3UzhlMW9mYWtSWlV6cDJpSm1VcVY0eVl3a0VnaEZ3V1Iyc3pqcklIejM0S2hzcmVrYTg3dTVWVGVoVzMvejhrcEpFeWh6YkIzTnRXVDlNcjhBQ2VQZU9uYnNmRWoxTklBU1dZRHJGVlFqNDErbDhwbTBaR0liRHlxTEJNYThkVExpUVplRXlLQkM4RWNkeGNESmhQS2w2Zm5YVFhqNTE1eEU4K3VoTzRDdUx3Z1NVM25uNWZTVkpJWndZMjMrc3BtZ1F3N0NIUWo1TUwvKzJZK2Z1SE5IekJFSmdDYWFMZjJHYXdqSmN3a3BIMlZEUmg2cU12VlhSSDNlSms0TUN3V1ZSWmVPeXVzaWxudFdCZlh4bzg3UDQ5VFNQSGwzS0srZUtzV3hwREpIaVVKWGJqMk9iOCs2N3k0cEtmOXcxNW5XYVlyT2hvZzhyTSsxV3JCSkV5QWJCT0JBbUFjR1k3Tmk1KzVQQXU2WjlKWnJwNStabEhlTzZ0aittbzJWcG9qRUVpeDdOSHFSUVA4OGptMCt6b2pCOCtmZHJTL3Y1eXRPYitmNlJyVHgrTWthV0swN1FuVUpUYkdJWkhjTlUwVldUZDJ3K1JYRjJnanRyTG5DOHA1cjBQTXZWTGlzYWZlSHhwYm02ZVZrSEo5cnp3UnVhN21LOGE4Zk8zYy9WMWU0U1Frc3djbDhWVlNBWVExeHRZd1ljT3kwakJZNDVhckRBUzhSU0dobFRSbGFGd0JJc1RpUXJqbU9sa2F3a0s3THErZHlEKzY0U1Z3QmUzZVJ6RDc3R0krc080Tk9TREtRQ05BeVVjYnlubXVaSUdWMkpBczRQbHZLTmx6WURVSmtYeFNjUHpMdTZrTldoOFNDV0duczgyRmpSaStTWTAzMmE4QkpmdmpnK0NnVERJaXhZZ3RIRVZSSHdZOEExN1E5UDkzTG55clp4NVJkcjdBbmlkaW1JWElLQ3hZWmptV1J4bnVyY1RrNzNMVVdYNHZ6YXJjZEhGbUtTdzIwcjJybHRSVHVXTFJGSjZTUXpLcExrMEI5elUvdnFhdEx5NjY5elZXNC9mYjBtMHJ6eWI1Und1eFNhZWdORGp1eWpvTWdPZDZ4czQ0VkdQMmhsMDEwUUYvQ2pIVHQzYjZ1cjNkVXBlcXZnbXNXQXFBTEJDT0xLQ3p6S1VKcUlhWjgwMHNrRTk2NXBHZGYxRGQxQkhNVXJHa1d3ZUlTVlkrTzFtbG1idlovUDNmOHlPMjgraFVvU1diTFJsUEdGVjFCa2h4eHZHcGRxOGFPREsvaldhOXRJNkN2UmxDRy9xLzY0bTdMc01DNTcvam03TzRxWGM5MVo0N3IydnJVdHBCSUpiR3RHL00zS2dFY3ZqcGNDd1ZVSUM1WmdPSEdsQTk4RHRzekU4KzFVTDl1cnV3bjV4cGNyN0ZCTEFaTHFFdzBqV0JUb1ZnOTVlaHNmdU9FRTVhSFhIYlRkYW9hME5mRnQ4bjk3YVMxZGlXSnMyWTFscFlsWktuLzBrOXV3SFlXazVTV3RoSmh2eDBjazFjZkI1Z0xldHZuOG1OZUdmR2wyTE8zbVNFY0EvRFBpYjdZRitONk9uYnNmbWFtRTBBSWhzQVFMUTF3cHdQOENiNW9SY1dXWnBCTVIzcjY1Y1Z6WHB3eUZsajRmM2p5eFFCUXNiQ1FyUm81MGdUZHZQTU8yeXU1ci91N1cwaVF0TjhtTU9tWVloaXZaZGZkaEJoUDFSRk1haVl4S01xUGlkeGtFM0JsU3Bzb1BEOWJRYWE0Q1daODNkYVc2UExUMCtrZ1pDbTV0N0p5RGI5L2NTTjMzQy9CNDhxY3JkYzRiZVJQd1B6dDI3bjV2WGUwdVMvUm1nUkJZZ2plS0t3bW9CZDR4VTUvaEpEdTVlWGtuaGNIa3VLNC8ycEtMcHFzaVJJTmd3ZUxZR2JLY0MyeGZjb0dITjV4SGxZZmZBdlRyYWJxU1BycWpIcGJrUnNmOWZLOXU0aDFGa0gzbTdnUDg5Uzg5UkZneGY4U29yS0xwS2tkYmN0bGUzVDNtOVlYQkpEY3Y3K1JBcXhjQ1pUTlZySGNDcVIwN2QzK29ybmFYeU9zbEVENVlnc3ZpU3Jrb3J0NC9VNTloR1NtTVZKeDNiRzBZOXowdm5TM0YwYkpGQXdrV0pKYVpodGdGQ253REZBVGk5TVZHUGs5U25oTWxZYmpvREUrdk5kZnZOaWpQN3A5M3FYTWNMWnVYem83ZlJmU2RXeHN3MHZHWk9sRjRpUThBdFJmSFU4RWlSMWl3Qk96WXVkdkZrTS9WVzJad09NU0p0L0hPYlExa2VjYm5waEJMYVJ4dnpjR1RHeENOSkZpUUtLb0xnc3M1bTdRNWV5eUpUeDVBSjQ3ZmxTTGZGMk50YVEvTENzTGsrbE5VNWc2aW5JTVQ3Zm5zcU82YTFuTGNXTjFHL1lFSXRqcC9Gak9hTzhEeDFoeGlLZTJhZkl2RGtlWE44TTV0RGZ6b2tJcVNYYzBNbmtyK0lKQzFZK2Z1ZDlmVjdrcUxYaTRFbG1EeGlxdHM0Q2ZBN1RQNU9XYWlqNUEzeGoyclc4ZDl6NHRuU3RCY3JwbnltUkFJNWd5U0pJUHFJNEdQQkRCb1FNdUF6Y0dlQkQ1bEVGMktvMHRwTkRsSmQ4dy83Wisvc25nQXI5UlBqUGtqc0dSRlJYTzVlUEZNQ1ErdHZ6Q3VlKzVaM2NvTHAwdnBqL2VpK3ZKbnNuaHZCWDY1WStmdXQ5ZlY3aG9VUFh4eElyWUlGN2U0V2c3c25XbHhaUmtwTXZGK1BuWFhzWEhGdlFLd0hZbkhqaTVCZHVlS2hoSXNXdEVsYVg0U2NobURVZzNkck1mVWlvaWt2V1RNNlIyNjNacEZRRS9NdnduTW5jdGpSNWRnTytPelJpbXl3NmZ1T2tZbU1URFRXNFVBZHdCN0w0NnpBaUd3Qkl0SVhOMEQxQUUxTS9rNWptMWpSbHQ1NzQ2emxPWEV4MzFmWFdNQmFjdUY2aExoR1FUekhRZkxTR0diR1J6YlFqYzc4RnB0MS96b1pnZk9HTEdhYkROSjNNN25lTnYwTHp3Q3J1UzhxMW5WNVNOdHVhaHJMQmozUFdVNWNkNjc0eXhtdEJYSG5uRy9zeHFnYnNmTzNYZUw5MkR4SWZaZUZwK3drb0UvQnY1c05nUzJGV3RqYlVrUDk2NFovOWFnWlV0OGI5OEtaRysrYUREQlBOWlZEaTY3Z3p4WE56ZXVhQ1dhMG5tMWNRbVdJL09SR3c2UzUzL2RnbkttSzRjZkgxMkxwSTQ4Sk90V053R3BuWDU3S1MrZksyZnprcDdYaFpjaklVbk9sTHlLS2tKaFRrVXl5S28rcjZwWjl1YnozWDByMkY3VlBXNEwrYjFyV2puZWxzdnBIaDAxV0RIVFJjd0JudHl4Yy9mbmdmK3ZybmFYTFY2T3hZR3dZQzB1Y1ZVS1BBRjhmbGJFVmFJSGp4em1FM2VjbU5COUw1d3VJV2E0MGR6Q3VWMHdUMWV1OWlDRjhqRisvYVlYK0lNSDY3aWpwbzAzYnpqUC83dHJINUxrOElPREt3bjUwK1FGVWhpMnpNK1ByU1NwVlkvNFBJL1Z4dTJWUi9tamgxOGpxTFRURmNzbVpRd2RWSHZzYUNXLzlaM2JhUitZbXJXM0ttOFEyWmwvUHRtYU8wRGNjUFA4cVlrbG5majFPNC9qa1NOWWlaN1ptbXMvRHp4eGNSd1dDSUVsV0VEaTZuM0FVZUNlMmZnOE14WEJTdlh6ZXc4ZUdsY2d3RXZFMHhyZjNiY2N4VnNrR2swdy8zQWN2R1lUZHkxNWpUOSswMTZXRlVTdStuTlJWb0szcmE5bklCM2l1Nit0WURDaDg3WG50eEJSUm5iVDhab1hlT3VhZzd4MVl3TzZhck0wdDVkQnM1QVh6Z3pGY3lvSXhrbExPWFJGUFZNcWVzaVh4aVhINTJXMUs5NGl2dnZhc25FbGdMNkVXN1A0dlFjUFlTWDdNVk9SMlNycVBjRFJIVHQzdjFlOExFSmdDZWEvc0tyYXNYUDN6eGlLemg2YUZYR1ZTV0pFTy9ucy9ZY3B6cDZZNCt4L3ZWcURvL3BSWFNKeXUyQ2VhU3ZiSnNzK3pTZHYyY05iTmpZaVNjTnZWOTI0dEpNQ2J5OEgyNnI0d2hQYkdhQUdTWktHRldzKzh4d2YzUFlhdHl4dnYvenJoOWMzNEZjRzJkTllodU5JbE9YRWNTdHBMdlJtVDZuODJkNDBDdk16MDR2cThvTHE1NzllWFRtaCs0cXpFM3oyZ2NNWTBVN016S3c1K1llQS85dXhjL2ZQZHV6Y1hTWGVIQ0d3QlBPWDU0QTN6OWFIV1VZS005TEN4Kzg0UVUzUjRJVHVQZEVXNGtCVEFacGZXSzhFODAxY1dlUTQ5WHoyM3IxVTU0OXREZm5RamNlUkpSaVFhb2JOVXVBNE5rcWlnUnVXbkNmYmw3cThIUWhRRUV3U2N2Y3hhSlh5eXJraUNvSkp2RnFLOXZEVXdqZm9xbzBpbWZPMkRUUi9FUWVhOGpuZU9yRjFaRTNSSUIrLzR3Um1wSFUyVGhaZXlac3ZqcytDQllwd2NsLzQvQmZ3cDdNbHJveHdNeCs1dFo0ZDQwaGZjU1h4dE1vL1A3Y1cxVmNvMHVJSTVwZTRjbXh5bk5QODd2Mzd4aDFFdHlncndaS3NEbzRQRmdNT2J3eDZLVWtTaG5zSlR6Y1Y4VXB6REpVa21wekJyV2J3YUJtU2FRbkxoaWRPTHVPRzZpNjhXcHA0eGpXbDcrRlNMUnhuL21aNGtXUUZ6Vi9Jdnp5L2xyOS81eDU4TG1QYzkrNm83c2F5WmI3NUVwQlZnYUs1WjNOOEZpeFFoQVZyNGZPdndJeWZXckV5U1RJWHhkVk55em9uTmtFQi8vemNlakprb1htQ29zVUU4NHFBMmNDbjc5by9ibkYxaVhkdFBZM0hia09LbmliTFBvdHNEc0psZ1NNaEt4cVM1aWVsRkJGVHFoaVFhdWl3MXRHWTJrS1B0QjVMRGpCZ2xmUERnOHZ3dVZJa0RYM1J0NFhtQ1pJaHlGZWZXY2RFcGVKTnl6cjUwTTJueUlTYk1UT3pFckxDdmpnK0M0VEFFc3hINm1wM3RRR1B6K1JubUtrWW1YQUxIN3Z0NUlURkZjQmpSNVp3dWl1RUhoUmJnNEw1aHlsNStQbVJwV1RNaVZsZTh3SXBTb045NVBodC91eE56N056ODdQVStQZVRiWjlHTmZ1dUVGdkRrKzJjSXlCM2NMQnRDUzRsUXppaGp6dmc1bkJrVEFYYm1mL1dZejFZek5tZUVEOC9OSEgzcGx0WGRQQ3gyMDVpaEZzd1U3R1pMdXJqRjhkbmdSQllnbm5NTjJmcXdWYWlIelBXeG0vZGY0UWJsazQ4UDlyUmxseCtjR0FwV3FCc0tGMklRRERQU0tsbEhPN2Z3bC8rNGtaT2RlUk02TjRIMWpRU043MmNiTTlsODVJZVBuM1hRZjdpTFMrd28vZ3c1Z2orUUk1dGtXUFg4enYzMVhIbjhnYlNUamFuT25KSW16TDlzY2x2RTBaVEdyYWt6ZnYya0NRWkxWREdqdzlXY2JoNTRnRlpiMWpheFcvZGR3UXoxb2FaNkorWDQ3SkFDQ3pCN1BGem9IdGFuK2c0bUxGMk5MT1RQMzNMZnRhV1Rud2d1dEFYNEN0UHI4Y1ZMRUhSWEtLVkJQTjRKSFV6SUsvbVArcHVwUGFWMVJqVytJYldWU1VEK05RRVQ5WlhBdEFaOXZMbHB6WnpvSE1sNmpCK1FJNXRrQytkNVBjZnFDUGtTM0h2bW1ieXRCWWNieG15cXRNVm1YeW9ob0c0QzhQMkxJam1VRFFYcm1BeC8vVDBlcHA2Sng1UGIyMVpQMy82bHYxb1ppZG10RzFNYStJazZMNDRMZ3VFd0JMTVorcHFkeG5BZjAvWDgyekx3QWlmcDlqWHlmLzNTQjBWdVJNM3BYZEZQUHp0THphamVBdEVPaHpCQWtFaXFaUnpvR2NyZi9Ib1RaenR5aHJISFZDZVBVaGZNcHV2UGJlQkx6MTNLdzNKemFTVVVuaEQ2QWJKVGxPc25PVDNIdGhId0cxY3Z2L0ROeC9EUXgrbW1rL2I0T1NEODdZUCtzbXdjTUtqcUc0L2lxK0F2MzFzODZTRVowVnVqTDk2cEk1aWZ4ZEcrRHkyWlV4bjhmNzc0cmdzRUFKTHNBQ1lsdE1xWmlwQ3V2ODhkOVdjNTQ4ZjNrL1FNL0c0T2QxUkQ1Ly82WFpNTFEvZG15MWFSckNnY0JRUEEvSnEvbTNQVGVPeVp0Mnl2SldVRmVCa2VDdHhwUkpKdnZaNnh6SXh3aGVveWgva1JGdUlsbjcvNVlUUHBUbHgxaFMwb01nbWJRT1RQeVJ5dWp0MzNxWEpHUXZkbTQybDVmSDVuMjZmbE1nS2VqTDg4Y1A3dWF2bVBPbis4eGlwOEp3YWp3VnpmTWsxbjQvbENzYlJ3RmVzZ25mczNIMGNXRE9wU2NPMnNHTHRxRTZVVDk1NVlsSmJnZ0E5VVE5LytmT3RwS1I4ZEwvSU5TaFk0TytmbFNSWGFlQWRtK3RaVTlvL2JLNUF3NUw1czBmdklDd3RIZE1QMGJaTUpEdU5XNDZpa2NDbERJVnRVQ1dENXY0Z2xYa1JmdnZlL1pNcTYxOC9maVB0NXZvRjJRNlpXQStxMmN1ZnZmVTFDb09UT3lGNHZDM0UxNTliZ3lINVVmMGxTUEtrb3h3ZHI2dmR0ZTd5MkNybTRBV0xzR0F0THI0OUNXbUZrUndrM2QvSWxySW12dkN1UFpNV1Z5MzlmdjdreDl0SlNnVkNYQWtXQlk3aW9kZFp3Mys4ZGdkLytmTWI2WTFkNjFlbEtUWitQWVdhYU1SanRlQTRJMGRWa1JVVlNmT1JWb3FJS2RYMHNaSldZejFObVMyWW5xcEpoMm93YlpsWXhyTmcyMEgzNTJPbytmekpqM2RNeWljTFlHMXBQMTk0MXg2MmxsMGcxWDhlSXprSVRFb2NmVWU4R1VKZ0NSWWVFMzZ4SGRzbUhlbmh3N2VjNUdPM244U2pUeTdTODhuMkhENy8wMjNZZWhFdWY1NW9DY0hpUVpJd2xIeTZuTFY4OWRuTnc0WlNDTGlTQkwwVy8rLzJGNmgwSGNabHRVL0lzVnEzZWdsYVowZ2Jrd3V6VU4rZVE4eGEyTytseTU4SHJrTCs4bWRiT2RxU082bG5lSFNUajkxK2tvL2NjcEowcEFmSG5sU0lRU0d3aE1BU0xEVHFhbmMxQUFjbk5EZklDaDZmaCthK3lUdlBQbm04bkgvNDVTWVVmd202TDFzMGhHQ1I2aXlaUWF1WTB4M1h2Z05Gd1RnWlN5UGtTL083OTcvR0oyOThrV0xsS0xvMTl1RmZ0OVhHTFJWSCtQeGJYOFcyclhHZllMeVNGODlXWUtsWkM3NE5kRjgyYXFDWUx6MjFnVjhjV1RMcDV6VDNCZkQ0UEpQSk9uSHc0amdzRUFKTHNBRDU4Y1NYZm5tOGNMb0UwNTVZZDBtYkNsOTdkaDNmM2I4Q1YzWUZtdHN2YWwrd3FNa1FvR0dZcE15bDJSSFN0cHZ1aTQ3WXl3dkRmUGptWTdqdG5sR2Y1eldiZU51YWd6eXkrUnd1MVVLU0pIcWpFMHZ6WXRveUhaRXMzSFl2THF0endiZUI1Zzdnemk3blI0ZVc4ZVduTmx5VjUzRzg5Zlg4NlJKd1Rjcmk5MlB4Rml3ZVJDN0N4Y2VQZ0wrY3lBMks1c2FRVkE1ZHlHVmJWYzg0VjNoK3Z2elVScUpHRUhkT2ljZ3ZLQkF3dE92blVxeHJmdTkzR1dSc25lTnRJZlkxRlZQZm1VL016Q0VoRnc3ckdPODREZ0hySEIvYWNZaFZKUU92djZ2SzBFR1M0dXpFdU11MHI3R1FnVXdlNnd2TzBCMEwwR1V2L0l3S2l1YkduVlBGaVU0WHYvLzlBSis1OXdoVitkRngzWHZvUWk2U3JFNDJYK0dQeEZ1d2VCQVdyRVZHWGUydWs4RHBDZC9vQ3ZGc2ZmbVlsMW0yeEEvMkwrWFBmN3FkR0NXNHNzdUZ1QklJTHExb3BSVEZXZGZHamROVUcxMlJlTFpoSFMrMDNrS1BzNWFrVW9xa0RMOEdkcHV0L01yR1l5d3R1RHBzZ0tiWTlNUW1Gc3ZxNlZOVkJOVSszbjlEUFJsTFd6UnRJY2tLcnV4eWtuSUpmL0d6Ylh4MzN6TE1jV3l2UGxOZmpxTlB5b2ZyOU1YeFY3QlkzbmRSQll1U253Qy9QNkdPNHM3aVZFYzIvWEVYSVY5NitOR2pJNXQvZTNFTjRiUWZkMDdKZ291cEl4Qk1GYmVVSU5kL2JRb2NqMmFpeUJacHBaVHhaQk5NSzhWOC84aDJmbmpFUUpGTU5NVkNsVTBHRXk0aXFmRm5SV2pzQ2RJZERmRFEydE5vaW9WaDY3REkxa082THdmVjVlUHBVeXAxallWOC9QWVRyQ3dlSFBiYS9yaUwweDFaZVBNbUZXL3NKK0lOV0Z3SUM5Ymk1QmVUV2UyNVBTNWVQVHZ5OXNGUEQxY3hrQTdoeWxraXhKVkFNTnhDUlVvT0s3Q1Nob3BwZzJyMmpuUGtWa2tvWmNTVUtzTHljbnFkbFhSYWEwbW9WZU95d2x5ZThROHZKOHNkNS80MUYraUx1N0VZMnZaeWJCT1gxWVhmYXNCdk5hS1lBd3Q3SWxSMVhEbVZoRE1oZm41NDVDVFJyNXd0d3UxeFQ5WXEvd3Z4Qml5eTkxMVV3YUxrVldBUXlKN0lUYllXNG9VenBUeTg4Y0t3ZjMvVCtndWNmaklrYWxjZ0dBRmR5YUNyMXg3dE4wd1p5NExsMldkcGk4ZEpLQk0vNFdZbmUwRExJdWhPait2NmFFcmpXSE1Xdi92Z1lSVFpvUy9tSnBHR2tQc1VWYmw5M0ZsemdZcmNHQTRTQjg0WDhPT2pxNGdweTY5SjRiT2dzQkk4dktGcHhEKy9lS1lVV3d0TnhzZzNlSEhjRlN3aWhBVnJFVkpYdThzQ2ZqblIrelNYajc2WW03YUI0WE1Icmk3dHgrZktZS2Jpb3BJRmdtSHdxTU9ubGtvWkNvcGs4ZkNHSmo2MGJSOEI4OHlvQVVldmVhN2RqbUwwSWprcENvT3Z2MytqUGNHcm03eDVZeE9yUzRZQ0IydXl6VHMySE9UUDN2d1NIN25sT0ZYNVVSVFpRWlZ0ZGl6dDVPTzNITUJqdFN6WXRqRlRjUUx1ekZXSEJxNmtiV0JvL05NbWx6djFseGZIWFlFUVdJSkZ3T01UdmtPU2NIazg3R2tvSFA3UHdGMHJXN0hUQTZKMkJZTGhSSTJXR243eUhneWlLeG15dkJuV2xQYnoyL2ZzSlkrVFlJK2Q2OU5sZFhKNzVRbVdGOFh3SzRPWGs2K2ZhTS9obFRQRkk5Nm55QTZQYkdtOC9PK2E0a0h1WE5tS0tnOHZ5NnJ6SXhUN3VpY2svT1lUZG5xQWUxWTNqL2ozUFEyRnVEemV5VnJ3SGhlOVh3Z3N3ZUxoTVNhUjU4SFJjbmoxM01pRDl1MDE3V1JTS1J6YkZEVXNFRnc1Z1ZzR0ZhSElzSC9yalBoUUpJdXNpOG5Uc3p4cDNyZjlCSzdVV1d4alpJdXdadlZ5VS9rSkh0N1FpR0VwdU9VWUlkK1FpSHY1VEFsSFdzWWZxK25RaFR3YWUwWVBLUHltOVEzb1Z2K0NheHZITnNta1U5eTZvbVBFYTE0OVY0S2paVS9xOFJmSFc4RWlRL2hnTFZMcWFuZjE3dGk1K3hDd2VVSWRSdmN5R0hIUk1lZ2ROdFpPamkvTml1SXc1Nk1SWEQ3aGp5VVFYRUt4NHl3ckdONjZHMDI3TVV5Skx6MjlqWVRoSW0yNnlPQWpxUVdRbE9GUEJVckdJRzY3bmVyOFFWNDRYVUpQUE1DSy9LN0xmMjhkOEpIdHpZeTdmUDF4Ti8rN2R6azNMZXZta1MzREJ4dGZVUmpHcC9ReHlNSktxNU5KUmxoZE1uaFo0TDZSamtFdmd3a2RiNTUzTW84L1ZGZTdxMWU4QVlzUFljRmEzRHd6NFRza0NiZkh6V3ROQlNOZWN2ZXFGcVNNMkNZVUNLN0VJMGNvelI3ZUdoWEx1RW03cW1qT2JLVFhXVVZVcVNhdEZDSnIzaEZQck5sS2dFRzVobjk5N1FHK2UrSWVIRW5uelJzYUw0c3JWYmJKOWFYR1hiNlFMOFhkcTl0UUZadS9mV3d6S1ZNZDV2VjNDT3JKQmRjMlVtYjA3Y0hYbWdwd2U5eVQzUjU4UnZSK0liQUVRbUNOQzB2TlpzOG8yNFNiS25veFRRdmJUSXNhRmdndW9rc3Bjb2FKSWRjYmRaTzJmUk5PSEN6SkNvcm1RdEY5SUd0VVpIV1NIeGdTUDkrdVcwSEluK2FtWlIzamZsNnVQMFU0NmVJdEc4L3pybTNuK050SE45SGNkMjE2cThKZ0ZNZGVPUDdhdHBuR3RpeldsNDI4OWZucXVXSXNOV2RXeDFtQkVGaUMrYzFMZ0RIUm0xU1hqNDVCRHdPSjRiY3VkTlZtWTBVZlJqSXFhbGdndUloWEgzN0JjYW9qUk5MVThacU5rMzUyTmcxODRJYWhJT0VkWVMrcWJCTk91RmhSRkI3M013b0NLYUxKb2ZoMTFma1JmdnYrSTlTK3N2SWF2NnpWeGIxZ0xSd3JscEdLc3JteUYxVVpYdUFPSkZ4MERucFFYWlBhSGpRdWpyTUNJYkFFaTRtNjJsMEpZTTlFNzVNa0dhOUg1VmpMeUQ1V3Q2NW9CeU1zS2xrZ3VJamZOZngyM2Y3bVl2eEtoQWRXbjBHM3VpZjhYSmZaemlNYlR4Szg2RC8wSHkrdUl1UkxzYU42WW9tYjNicDVWZUxqdi9uRlppcnpvdnozcXlzSkoxNFBIRnlaRjhXbkRDNmNoc2tNY3N1eTloSC9mTFFsRjY5WFJaSW1OVjN1dVRqT0NvVEFFaXhDSm1XK050VnM5amNWanZqM2RhWDkySmJZSmhRSUFHd3pRMVh1dGFMRXNpWDZFZ0ZDM2loM3IycWhNdEEwcnRBTWwwV1IzYzB0UytyWldqa2t6SDUwc0pyeVVKem12Z0Qzcm1tZGNEa05lMmhLU0dSVXF2T2oxQlFPWXRrU2YvL0xUWmV2eVE4azBZa3ZrSFpKZzJPenBuVGs3Y0VEVFFXWVN2YXNqcThDSWJBRUM0UG5KM09UcXZzNDJaNkRhUS9maFZURlptM1pBSVlJT2lvUW9CTmxSZUcxazNoOVJ3NlJUSUJ0UzRZc0tMOTI2ekd5bllieGlTdXJneDJseDNuNzVuTUFIR3NOMGRnZHBLWGZ6Ni9mZFh4UzVieVVaaWVSVWRGVml4MUx1L2lOdTQ5aFdoSzFyNnk4ZkoxUFh4Z0xKeU1WWTExWlA0bzhmTVFhMDVZNTJaNkRxdnNtK3hIUGk5NHZCSlpnOGZJYWsvRERrbFVkV1pFNDA1azE0alUzTGV0QU1nWkZEWStuUHEwb2tobkd0Z3hSR1FzUXR4U2hQQlM3NXZkUDFWZmhWbE9VWk1mSW1ESmUzZVQ5TzQ2TkhqSGRjZkNhamJ4bDlRSGV1ZlVzQUkwOUFYNTZhQ2lIM2dOcm04bnpweVpWVHRNYU9pV1g1MC9SSHgvS1MxZ1lUSEx2bWxZT1hjaWpJenpraHhUeXhoZEV3RkhKQ0hQektOdURaenF6a0JWcHNybFZqWXZqcTJDUkl1SmdMWExxYW5jbGQremNmUkRZTWRGN0ZjM1A4YllRcTBkSUxiR2h2SmVNWWFGYUpySWl1dHF3YzZWdGtXV2Y0ZUYxWi9DN0RNNzFoR2p1RHhKT2VVbWFIdUpPTHJiaW42ei9oMkN1Q0N3MWlWZS9Pdmh1SXFQU0hjOGhUZ0hmMkhNN0tpazBPWU5MTlVnbkUxaXVOSXAyOVVFU3lVNlNJelh3c2R1UFhCWnN4MXBEL094UUZicHFzN2FzajYxVjNaTXVwNmJZUkZNYUFiZEJJcVBRRzNXVEYwaHg1OG8yWGpsYnpIKyt0SW8vZlBnQU5VVjlIT2xQSTZtZWVkc210bVZpR0Nicnl2cEd2T1o0V3doRjgwLzJJdzdXMWU1S2l0NHZCSlpnY2ZQU1pBU1dyUVk0M0p6UHU3WU52NlhoMWl5cThtTzBKZVBvM2l4Unk4TVFrczd4T3cvc3ZSemdjSDM1NjROOVBLMXh1ak9MZzgzRmRFVUR4REplRWs0T3BwSXRCTmM4dzZkZHU2VjJyaXVMcUpVUG1wOFVWMHppRnVEbm1vVENick9ORmJrWCtQRE5KOUF1bm5oNzdPZ1NqcldHVUdTSExVdDZ1SHQxNjVUS3VUUS96UG1lSU92TCsvalVuY2ZaL2ZSNlBuRFQ2YUUwT2RrSlVvYk11ZTRzbHVhSDhVcURwSmkvQXN0TXgxbGFFQnMyK2ZZbERqZm5ZNnVCeVNSM3ZqU3VDb1RBRWl4eUpwWGxYZFU5dFBWNFNXVFVhMWJubDloUjFjR1BqK1lCUW1BTlI5Q1ZIREY2dE05bHNIbEpMNXVYOUY0V1hILzU2QTNZOWdDS0FuRW5GMHNPakJpSVVqQTNjR3lMb3F4clE1YkVNeHFXbzQwNWVUdFdpbXpPODk3dHgxbDcwUm5iQnI3NjlIb2NCekttd2xzMk5yR2hZdXJCd3JkV2RmUGltVkxXbC9lUjQwdnp1dzhlNHQ5ZVhFMDhyU0hqRVBJbitlSCtwZnpPQTRmUXBSaXBlZHd1a2hsaFIvWEljY0lTR1pXMkFTLysvRW1MeUZkRjd4Y0NTeUI0ZVZJRGxLemdkY3ZVdCtld3BiSm4yR3MyVlBUeDNYMHB0SUF6MlNqSUMvc0ZWTVlmc1BHN3I2MGdJd1Y1LzVaOXJDM3Q1MVJuRnErZEw2RjVJSWU0blVOU0toQmlhd0xZbG9Gc3AzSEpjVlJTSk93Z2pwWXo3WjhqV1VsV0ZWMHJmbnk2Z1NJWk1JSVZ5SEVjZkZZek5mbXQvT3FPZXR6YVVGOXA2Z3RRKy9KSzh2eEoraEllZnZPdVkrVDZwMGZxVk9UR2FPb05ZTmtTaXV6ZzFVMyszejFIZ2FGME1mR014bzhPVkNQSkRqNHRUV1MreGh0MUhES3BGQnNxUnQ0ZXJHL1B3ZXVXcC9KT3ZTemVNaUd3Qkl1Y3V0cGRQVHQyN2o0RHJKandPS1VHT040V0dsRmdGV2NsQ0xnTk1wbmtaQVAxTGV3WFVCNStoakp0bVhCQ3Z6eHhIbXZONVVUM0VpcUNIV3hlTWxUWDY4djZMMGVmYnVvTjhIUjlKVTM5dVlTZFVoekZMeXIzeW41cW0rak9JRzdDK1BRa0FUMUphVTZVNnZ3QlF0NDB0YSt1SVM2VnpzaG5lK1ZCbHVSZTYrQmVsSlhBSzBkSUVMeTJYMWo5NU9zdGZPaldZNVRsdkg0Uzk1c3ZyNlNwSjRpcTJBUTlCcjk1OS9GcEwrK3RLOXI0djcwcitNQk5wNjkrbHkvbUhsMVZQTUR4bGx3Q3JpUWRDUWVZZndzbk01TWt5MnRRRUJqWlJlcDRXd2hibWZUMjRKbTYybDA5NHMwVEFrc2dBS2liak1CQzlYT3NOUTg0UGVJbEd5cjYyTnVTTHdUV2NOWU55UmxXWEgzbDZVMjRWWXZmdU9zdzhiVEtkL2F2d1NVbitNak53MCtvbFhsUmZ1M1dZMlJNaGFmcnk2azdYOGFnWFlhbExONnRXY2RNRUpDNkNPcFJ5dk1HMlZIVlFXVmU1QnFmbS8vWnU0b0J1d3BtNkNDR0ppWElHMllpTHdnbWNjc1Jyb3BDYWFVSmNwNTdWelp3eDhyV3k5TGxUR2NXLy83aWF0S21URWwya28vY2VwTDh3TXhzME4xZTA4RzNYczNpbXkrdDR2MDNucjZtdnRhVTl2UEM2UktXRmZSejZwd3gyUk4yMXhVckV4OXpTL1ZZYXg3UzVCM2M2OFRvSmhBQ1MzQ0ovY0FISm5xVG9ydnA2WFlSVDJ2NFhNT0hHRmhmMWt2ZCtTaVFMMnA1RERLbXdoZWYzRUpiWmlWWlVpdHBVK0hmWGxwUDNNcm1IZXYzWDQ3V1BSSzZhdkhRdWlZZVdIdUJaK3JMZWY1TUZXR3BHbVI5VWRTZmJhVUowazYyTzh5MlplM3NxT3JFN3g0NTlNV2g1bndPZHk3RlVvSXpWaWFmbmhyUnhuUG5pdk04VWE4aFNSSStQVVYxUVM5djI5UncyYWZSdG1XKy92eHFEamZuVXBFYjV6MDd6cktzWU9ZekpIendwbFBzTzEvQVgvOWlDemRVZDNIWHFqWjBkY2phV2g2SzBUSG80OVlWN2JqT1JUREltMzhMR3l2SytyS1JCVlk4cmRFVGRlRXZjRTlsUEJVSWdTVVFBSk9NMXlKSk1sNjN4Tm11SUJ0SDhHZFlYVEpBT21PaDJaYndFUnFGbEtId3BhZTIwSlV1UTA2MUVIR1hzUHZwOVhRa1Mxa2V1c0F0eTl2SC9TeFpjcmgzZFRNM0wydm5XM3NHT0R0UVNWb3BYcGdWNXppb1ZqOVpTaGNiS2pxNGUyVXpXZDVyaGVqZWhrTDJOQlpobWhLLysrQ1FaZkQ3QjFlVFVrcG50SGhlYldSUmZPZktWbTZ2YVVPV2hnOTBPWkRROGVrR1gzalhubUcvMDB5eXZhcWI3VlhkUEZOZnl0OC92b244UUlyNzExNmdNaStLTEVGNUtJNUxtbjhDeTdFdDBtbUxWU09FbHdFNDJ4WEU2NWFtY2xwWHhMOFNDSUVsdU14aGhnNklUMWdCT1lxUE0xM1pJd29zbjh1Z01DdEZPSk5FY3d2Zm9PRklaRlMrK09SV0JqSjViQzJ1cHlJM3dvK09aOUVjTHFRMDJNWEhiajAydWNsZE4vbms3VWZaZjc2TEh4eGVRMVJadW1CQ1BEaU9qY2Z1SkZmdjVvR05EV3dzNzd0bXk3VW42dVovOTlUUUZmSFFHM1ZSRmtyd3lUdE9BUEIvZGFzSVM5VXo2a0ZrV3lZbDJkRXh4ZkJJNVBwVGZPaVcwOWUxbnU5ZTFjYmRxOXJvaWJyNS9tdkxHRXk2R0l6cnVGUUxyNVlpTnMvaWpacVpKTVhacVJGUFBnT2M2Y3JHVVNZZHZkMjZPSjRLaE1BU0NDNEhIRDBKckp2d1JLZjZPZEdXQzl0R1R2R3hvYnlYNXhzTFFBaXNxd2Q3U3lhYTB2akhwN1lSTS93OHZQb0lkNjFzdVNpT0RCSVpqWnVYdFkrWXltTzhiSzNxb2p3M3d0ZWV5OUR2MUlBOGoxOTl4OEZ0ZDFEbzZlUlhOZy9GYUhvamtaVE92ejYvbXNHRWptWEw1UHBUZk9MMkUxVG1ENG1kd1lST1EzOFJrakt6VzZlU25SNDJCK0ZreVpneVo3dXlSODJkTjFQa0IxSjg2cTdqMk1CUEQxWXltTkR4NjBtNjUxbXNCdHVJczNIWjZQN254OXR5Y2RSSmoxVW5SWUJSZ1JCWWdqZXlmeklDUzlFOE5QZjVNRzBaVlI1K09idTJ0SThYenNTQVFsSExWNURNcVB6alU5dElHUnFmdUxtT1pZV3YrOWRjU3VBN1hSUUdrL3p1L1hWODZXbWJMbk1WMGppY3VtVXJTWmJjaEs3WVpDd1Z3OWF3MFRId2tMWTlJS2xJaWpwclZqSGQ2aVpQYitmZDIrcFpPb3l3QXZqRjBVcjJOZVlqU3c3WjNnd2Z1KzNrTmR0clB6aXdnaWdWTTM3K1RaZFQ1SGlubnJjdlpTZzhmcXlTWit0TGVQZjJjOWUxejhyQTJ6YzNBVkNlRStaY3E0R3NhUFBtblpQTUdHdEtSZzdQWU5veUxYMCtQTG1Uam44bC9LOEVRbUFKcnVFQThPRUpEN2lLaXFaS05QVUVyaElJVjdLOE1FdzZZNlBaTnBJc29wQmZvbVVnUUdFd3dlY2VtQjBmbTREYjRMUDN2c2JmL1ZLaTE2ckJReCtLWkdJNEx0SmtYelZSU25hYUpaNFQ3THJuME9YSTRhWWxNNWpVR1V6b0RDWmNkRVg4ZElUOVJOTXUwcVpHUE9NaVk3dElPd0V5VXRhMHBVaVNyQmdoK1FKdjNYVDZjcGlLNFNiR0wvNXl3OUQxd0R1Mk5iQm1HRCtiUkVhbHNhOWdYQUp6eWpnT2lqejVQYlJFUnVXbmg1YXlyNmtZdzNUNGYvY2NabmxoZU03MDMxWEZmYnpVRXNjbWUxNjhiNDV0a2M3WUxDdUlqSGhOVTA4QVRaV20wbmNQaUpGTklBU1c0STFNMmpGVDFWMDBqaUt3dkxwSnJqOUR3a2lpdW55aXBpOE85aVZaTVg3dmdmMlhUMmpOQmo2WHdXL2RzNTh2UEtuaU9EYS9kYzkrb2ltTnV2TWxuT2dzWnBCcUpGa2xLRFh6NjNjZXVTeXVBRlRGSnMrZnVpS1pjTSt3b3FDNXo4L2hsa0thQjdJSnAzekU3VHhNSlh2Q3dXWWQyeUxnTkxHMTdBSnYzM3h1eEszU1dFcmppMDl1Sk0rZkpKclUrYU9IRDZDTmtBTGw4V09WaEozeVdZbmVsTUZMeTBDQXF2em8rTDh6ME5DVnhTOVBWTkU4R0NKdHFLd3Q3dUFETjU2OEhHeDByckFrTjRwSEhpUStUd1NXWmFUSUQ2YnhqT0ovMWRnVFFOVmRVL21ZZldKMEV3aUJKWGdqeHkrTzd4T2VlMHpKVDBOM05qQnlMclJWSmYzc2F5MFVBdXNpV1p6bjAzY2RtbFZ4ZFlrY1g1cWROeDNoeTA5djRWaGJIbmV2YW1GcFFZUklzcEd2UEpPaXkxcU5KRG00eGxrMnk1WndIQWxWc2ZIcUppdUxCMWxaUERqVU55eVo0MjBobmp1OWhLNTRpQ2psU09QWVV0S3Rib285clh6NDVtTlhDTHByNll1NSthZG4xcEhuVDZJcERwOTcwOEVScjdVZGljTnRKVWlxZTFicVdWSzlQSCttaWkxTHV2RzVScDdVb3ltTjA1MDU3R3Nxb1NzYXBEK1ZqVXRKVVJyczR6MWI2eThIK1p4ckhHbkpRN0pTUS91RzgwRmdaWktzS2gvZGY2MmhPeHRUOGpOSjd6d0hPQ0ZHTjRFUVdJS3JxS3ZkbGRpeGMzY0RzR3lpOThxYW0zTTlvd2UxWEZQU3ovN21HTXpEdURrelFZRnZjTmFQM2wvSmlzSkI3cXBwNXNjSHE3bHJWUXNTRVBSaytNdzkrL25iWCtwRW5SSWVPMXJGbXpjMmppaXFucWt2WjE5VEdkR01EOHUyOGJzeStMUTArZjQ0Rzh1N1dGWVF4dTgyMkZqUnk4YUtYc0lKblI4ZldzN3BubUlpVXVXd1lUc2N5eVNMQnQ2eS9oUTNWSGVPK2gxaUtZM2RUNituTENlR1M3UDU0RTJuUnIxK2YxTUJVYXRvVmtlK2Jtc1ZmL3VFVHE0M1FtRXdqa3MxQ1NmY3hESTZTVU1qWWJoSUdCNmlHUzgrUFVWUWkzQmp4UmtlV0h1ZWtDODlaL3R2TktYeC9RTTFaQXdaSlh0K3ZIT3lIV04xeWVnQzYyeDNGckkyYVFIZVVGZTdLeUZHTjRFUVdJTGhPREVaZ2FWb2Jub0hYS1FNWmNSdGpPV0ZZZEpwQTQzNW1WNWpPckV0azlMc3lIVXZ4eU5ienJIdmZBR25PbkpZVlR6a3J4UndHOXl6OGh3L3JpL214YVpWaEZNNmI5L1VjRG1RYk1aVWVQRk1DUytjcldUUUxzRWpSY2p6OUZHZUUrYTFqbFgwT29VMDlWb2M2STdoay92eHFRbEMzaGhiS2pwWlU5ckh6cHRQMEI4L3gzKytNa2hiWWdrWjVYWEJyVnM5bEhrdjhMSGJqaElZSlVBb1FNcFUrY0l2TjdLMElFemFWTVlVVndEUDFGZGlxck9zQm1TRkFWWXdrSVN6Y1FzckU4T3J4TkRsREtxVXdhZW55Zk5HV1ZQU3piclNQdklDOCtOWVhzQnQ4UFpOWi9uZWdiWHo1SzF6U0tjTmFvcEc5bUZMR1FwOXNTa0ZHQlhXSzRFUVdJSVJPUXE4ZGFJM1NaS01XNGNMdlFGcUxtNE52Wkg4UUJLWGFtTVpHUlROdGFncldaSmxlcUxYZjZ0VWxodytjY2N4bmoxWmZsbGdBZHkyb3AzajdhZnBpV2V4cjJVWmg5dkt5UFlNVGZ4SlV5ZGloQWlvL2F3TDFmUFdUV2NwRENZNTF4MWtmOGZxaTk5UHdaR3ppSkZGekliT3FFUDlrVGkrWTcyNDVSaWZ1dU1nbjcxdlB6OC8wc2R6NTFhVFZvc0pPbzNjditvMGQ5UzBqYXZzLy9ENEJqWlY5SEsyTzV2ZmZlRFFtTmUzRC9yb3orU0NjcjNFdlVPV2M1YjcxcDlqZWNFZytZSGtOV2xvNWh0MzFMUng4RUlSRFlteTJUazBNQVVzSTROYnN3ajVSaGF3RjNvRHVIV21jaXIycUpoQ0JFSmdDYVo5QmFab2JzNzNCa2NVV0FBVnVURXV4Rk5DWUVreWJaRWNZaWx0MUZRdXM4SFMvQWo2dWd0WHQ2WHM4T203RG1FN0VvM2RRVjQ4VjA1VFg0Z0J1eEtGSkRlVUh1V1J6UTFYT1F1L2NyYU1sSlE3ckcxU2tpVFEvTVFzRmNWcXhPOHlHWWk3MkgraEJBTXZwZG94ZnYzMncrU01jMHZzcTgrc1kzMVpId2ViOC9uVHQ0N3ZiTWJQanl3bElaVmNOOXVwWnZidzNtM0hXRmZXdjZENjhzZHVPOHJmL05KUGhKVnpYR0NscU1xTmozck4rZDRnaWpZbC96eGh3Uks4dm9BVlZTQjRBOGNuZTZNcCtUblhQYm9mVmszUkFJNHBZdkFCREZMTmw1L2VRaUp6L2RjNTVhSFk4QU9FNUxDc01NeEhiajdPbjd6cFpkYUZEcUU1VVpyNmNuajVYQW5SMU92TzZnMTlvUkZUSVRtMlJjQTZ4eDFsci9MSGI5cERPS256aFNkM0VEVUMzRkoraE04OXVHOVljZldsSnpmdzFJbFNiUHYxb2VxeG8wdkk4bVE0MHBySC83dm42TGdHc1VSRzVjSkEzblZOMVJSUSsxaTd3TVFWWE53cTNIQUtsOVU1cDh2cG1FbFdGbzllLytlNnN6Q2xLUVZEUG81QWNCRmh3Uks4a1RPQUFVdzRjcUNzdVdqcUd6MXA3dEtDTUhLOThBRzFMUk92M1U2N1hjTmZQYVp6NzZvR2JsMCs5WWp0TTRtbTJIejh0bVBzYWVqaDBXTTEvTGorSnA0NTA0OWZqeVBoRUhOS2huR3RjOUNzUHZMMVZqNTUrK0hMVHRzSG1nckltUER4VytwWVdUeHlUcmp1aUljVDVISzRwUURibGxoZDBzZnB6aHh5ZkdudVhkTXlib3ZYTDQ5WEVxSHMrazN1amtPQlA3cGdQUSszVlhYeGFrTXpaMko1YzNhclVMWVRWT1dOSGtPc3FTK0lQSG5ydW5GeC9CUUlodnFjcUFMQmxkVFY3aktBVTVPNVYxRmQ5RVpjV1BiSTAwaDFYb1JVMmdMSFdkd3ZucDNnL3BwamJNdzloQ09wL09qNERmejV6Mi9qLytwcUdFem9jN3JzTnk3dDVJOGZlb1ZieWc2alNobDYwcVcwRzJ2SXlEbXZDMGd6Zzl0cUkxODZ6dnMzdmNRZlBGUjMxWW00VzFlMDgvKzk3WlZSeFJYQVg3MWpMN3BxRTNSbitQQ3Q5ZWlxelp2V1h5Q1MxTG1odW10YzVjMllNZ2RiU2tIeFhMLzJ0aUxzcUdwYjBIMzZJN2NjSjR1R3VWazR4eUdWdHFqS0d6a2VtV1ZMOUVaY0tPcWtCZGFwaStPblFBQUlDNVpnZU9xWlJNb2NTVlpRRmVnTWV5bk5HZDdYSWN1YndhdGJXR1o2cXI0Tzh4cXZFbUZEUlIvM3Jta2xubFo1N0ZnVlI5dEwyTk82bnFNZFM4aHhoOWxZM3NubWltN3lBM052UzlXam03eHZ4eWxNK3d3bjIzSTQwRnpFUU1LRDdjam9pa2xWM2lBN3Fqb29DSTVjOXZFRXpaU0JUOTExbktNdHVmekxzMnQ1M3cxbmFCdndzMk9jNGdyZ3NXTlZoSjN5NjFwZkFibVhkV1Y5QzdwUEI5d0dENncrdzQ5UDVtSW9jeXNVaTJXbThibXNVY09pZElhOXFBcFQyVWF1RjFPSFFBZ3N3VmhNMnN5dHV4UmErdjBqQ2l5QWl0dzQ1Mk9MVzJDcEpDOEh6L1M1VE42NTlTeHZ0eHQ0NFZRcEw1eXJvQ1c1bk9Zekszbm1iQzl1T1k3ZmxTVFBGMmRkYVErVmVaRTVJN3BVMldaOWVSL3J5MmRXUEt3djcyTmw4UUM3bjE1UE9Lbno4SWFtY2QwWFQydnN1MUNCSTN1dmF6MEY5ZGljaThJK0U5eTJvcDI2ODgwMHBYS3VxNy9iTlFMTFNGT2RHeHYxbXBaK1A3cHJTbVVXMjRNQ0liQUVZekxwYkxLMjVLVnRZUFR3QTB2ekIyZ01weGQxQmJ0VkExbHlyaEVyMjZzN2VlN01FaHpGZ3lUSm1LazBocTdTbFN5aUtlWm5mNWVOWDQyZ1MzSDhlcHFBSzhteS9BR3E4d2NweTRtUG1nSmt2cU9yTnIvendHRmVQRk04Ym9INXJUMnJpRmg1Qk8wVFpPUnNrbkxKckNXbXZvUmpacWdwN1YyUWJXTGFNaklnWDVGdjhjTTNIK01mbnM0aXh0STVVMDdIVExPc1lIRFVhOW9HZk5pU2R5cCtNK2NRQ0lUQUVzeVl3Skk5bk84ZC9TUmhSVzRNK2N6aWRuUjNxOWU2YWlReUt2L3c1RFlHcEpXWFJVRElsK1J6RCt5aGZjQkxjMytBczkyNTlNYTh0SWV6R0hDVzRrMTJjYm9yajJUS3dxdWJiQ3p2NGNPM25pS2UxamphbWt2QW5XRlY4Y0NjZHA2ZnVKV2tZMXpYSFduSjQxeC9CWVd1VnY3b1RYdHA2ZmZ6dmYwcjZVd1drWmFMSjV3WGNiTDRwRTV1WHI0dy9hLys1aGViaWFWVS91NmRleS8vTHMrZlltTkpDNiswRitFb2N5TXRsdXdrUmp3cGU0bnp2Vm5ZOHBUODlJVEFFZ2lCSlJpVFNadTZGVlducFgvMFk4NmxPWEZNdzVqNE1jVUZoSzVjTGJBeXBzSVhuOXhLcjcxcTZDU2VFUUV0U05Kd29VZ09GYmt4S25KajNMSzhnLy9kdTVLMlpEV09BNnZ5ei9QK0cwNWRsYy93VEdjMi83bG5FMkduRkUxSzQ2ZWQxY1U5dkhmN3Vhc3NEUXVaZ1lTTDd4NVlneW9sK2RpdFI1QWxoeVc1VVg3My90YzQxeDNrQndkVzBwTXVJaTBYemJqUUNtaGhDZ0lMTHpUSkQvWXZSVmNzTnBSZm01SGdWN2FjNVVSSEFRT3NuaE5sTlEyRHNweXh0d2dWMTVRT21JZ3RRc0hWd2w1VWdlQ04xTlh1NmdFbWxjZEZWbDBNeERVTWErU3VWWklkeDdTR1lpTXRXcTZZMDAxYjVvdFBicUhMWEFXeVRJNXpHcjg4NU5OazRLRW45cnF2MnN0blN6alV1UnhUeVVKV1ZQb1QzcXZFMVVEQ1JlMmVqVVRWRmNpcUZ5KzkzTHY2QXNzTHd2ekZ6N2R3b0NsL3dWZHR4bFQ0cDJjM2s3UUN2SGx0UFVWWlYxdExseFZFK05RZGg5bFljQnB6OEN5V01ZT3BhYXdrbThvN0Zsd2ROL1VFdU5BWFFGVWNIdGw2YmE1S1RiRjUyOGJUNkZiM2RTK3JZMXRZRnRmMGc2djdqTXhBWEVPZS9BbkN5TVZ4VXlDNGpMQmdDVWJpSExCNXdycEJsdEhWb2ZoRkl6bTZLN0pEcmo5RHdreWo2dDdGV2JzWGQreHNSK0lyVDIyaUxiTUtaSTFzK3pTZnVmczF2dlRzVFFBa3JDeGErL3dVQkpJMDlRYjQrZkUxcE5TU3k0K0pwVDFYQ2JXdlBidUpzTHdNQ2JCdGsyMUxXcmlqcGhVQXI4dmd2L1p1cHI2ampmZnVPTFdndGcydkZGZGZmSElyZmFrQ2JxdzR4UzNMMjRHaEUySW4ya09jYUM5Z0lPa2pZZnFJT3lHVWJOK00rbVFGcFZidVh0bXlvT3JZdG1WcVgxM0pyOTEya3YvWlU0TmJIZDd2Yjh1U2JwNDgwVTZibVQ5cjI3SERhbHd6VFNpUUdiVy9kMGM5Nk9yUStEV0Y4VklnRUFKTE1DNGFKeU93QUhSZHBtc1VnUVZRRm9wenFqOERpMVJnWlN3VkIvamFzeHU0a0Z3RmlodS9lWlpmdjJNL2VZRVVMdFVBZThpbjdXeFBpS1dGWWY3dDVVM0VsYXFoU2M1SUl5a2FTY2REUEszaGRSbjh5M1ByNlRKWElDbktSYkdyMEI5L1hZRDVYUWFPNG1WZjkyWWFIOHZtNDdjZUdYVlZQOThZaUx2NHArYzIwNS9PWTJ2cEdkNnovVFJIV25MNTl4ZFhJMnMrVEswQVNYVURFbHc4TERhVDA3NWptMVRsOUN5NGd3ZGZlWG9kRDIrNFFHTlAxdVdUc0NQeDdtMzEvUE1yK2FTVTB1c25DSTNNbVA1WDNSRVB1ajRsb2QyQVFQQUd4QmFoWUNRbTcwOGd1K2dLank2Y3F2TUdjYXpVb3EzY3BLSHo3eSt1NDF4MEZiYml3MmMyOE5HYkRsQjJVWlJxOHRDMm42eW90UFFIK2Fkbk56TW9yUUFKUEZZTGN1SThraVNSZExJNTN4dmd1L3RxYUl5dHdMa2ltS1lreVF3bWgvNXRPeExmM3JlS3BGU0FMZnZwTkZleCs1bU5mS2R1K1lLb3ozM25DL203SjI5a01CWGs3bVhIK2NDTlF5R0pOcFQzOGRlL3NwZGJxaHZJVlpwUXpVRXVtdzlubUlEVHdpT2J6eTY0dm52enNnNStjV1FKRXVCekdmenpzeU9Iekt2T2oxRGs3Y1J4cnAvdm4yT2xxTTRmSFBXYXJyQVg1Q25sUnoyTFFDQUVsbUNjVE5ya2JVb2VPc1lRV0NYWmNSUm44UXFzU0NhTEUvMnJzSlFnWlBwUm5BUm51M000MXgwa2JTcm9WNXd5YkJrSTBtV3NRTUlreHo3SngyNTRsZXJDQkVnU3B1VG5PM1VyMk45ZWczRkZKUFZMeERNdWJFZmkzMTlhUzZleDlISnNvZ0J0ZlBydXd6VDNCL2p1dmhYenRoNHRXK0xMVDIzbVczV2JjQ2tHdjNuYlh0Njg0ZnpWUXNkdDhNNnRaL256TjcvRSt6YytUNGx5RkxmVk5xT1R2bU9aVkljNnlmVXZ2RDYrdmJxYlAzdnJhMXpvODlNMjRHTkpib1MvZW5RckdYUDQ2ZVM5MityeDJhM1hyYnlLazZJa2UvUWt6eDFoTDZZa1RoQUtwaGV4UlNnWWllYkozaWdwT3EwRGdWR3ZLY3hLWXBybTR1MkFxb2VRMG9Fc3RaSFdOREpPa01kT0YvSGtHUk9Qa2lTZHNlSGllRzk2cXZBNFhTelB2c0NIYmpxQlc3TklIeDZxT1ZsUkdUQ0trYlNDUzFNN2RqcUM3Qm9LbFpFeTNmekRFMXRwU3kvRGtsL1BFNW5CUnpLanN2UG1lcjcwekE0S1RpVzVjeDc2Q3JVTitHZ2Y5UEFyRzQ5emUwM2JOYkhGcmxwTlNnNWJxN3JaV3RYTmhiNEFQejYwbk01WUhsSEtwejEvWG9BTHZHdnJxUVhkaGQ5LzR4bmFCbno4KzR1cldWVXl3Ri8vWWd1ZnZ2dllOYUt5TkNkT2liK0xzL0d5cWZnNFRSclROQ2tJamk1MFd3Y0NTTXFVVGhBMkl4QUlnU1VZSjVOZWNzcUtUbmRrOU5WZ1lUQkJ4bkJ3T2Zhc0IzNmNDK1NwRi9pRGgvWmQvbmMwcGRFKzRLT3BMNHV6M1NFR2tsNFM1bmxpZGdqYkFwbEJpckppeE5MYWtNQXlYZzl5SWJrTEdFcXEzRXVPMmtGQ1Vva3hKTEJpVGhHUlZNVTFBaUxsQkRuVGxjTURheThneXpLL3JGL0o2cEplQ29Qeks1eEFlU2pPMzcvemxRbmZ0eVEzeW1mdU9VaC8zTVVQRHk3blhGOEpNYWxpV3FLUE8xYUdtdndPc2tkSnk3SlFLTTJKOHlkdmZZMnZQcjJlZ2tDU3J6NnpqZy9jZElycS9LdHovcjFqeTJtKzhud1JTWGwyVXhZNWprM0djQ2dNanU1cjJCM3hJSHVuSkxCYUVRaUV3QkxNOUlwTVZqUWlTUlhUa2xHVjRiZGgzSnFGUjdleExXTXF5VlhuTFc3dDZub0p1QTFxaWdlcEtSN2tmaTRBUTRGSHozUm04MXBUTVczaGJKNXZXTWtyNTFjUTBLUEVEUTlEZ2NSZUYxWnYyWHlXZFdWOS9NblA3M3g5Z2xHOXd6cHlLNnFMVTUyNWVIV0RwSk5EV2dsUisycVkzMzlnMzd5cVIwbWFtajlWeUpmbVk3Y2VweTkyanYvZXU1cVdXQmxwcFhoS3o4eWlpWGR0WFR3aGtXUmcxejFIZWZSSUpZbU15di90WGNIYnR6U3lwdVQxUk41bE9YSHlQTDIwWk1wbTlVU2hiUmw0ZEh2VU5FV21KUk5KcWdTQ1U0ck1KeXhZZ21IZkRZSGdHdXBxZHlXQi9rbE5lcktNcGtMWEdGYXN2RUFheDF5Y3llZmp4dGlpMHF1YmJLem81V08zSGVQUDMvd1N2MzNuaTZ3dnZvQmxTMWl5RjlzeWNTSU4zRnQ5Z0Q5OWVBOGJLM3BwNmZlVGRnTGpLa043T0l0SFQ2NG5vK1FoU1RKZHlXTE9kUWNYWlh2aytsTjg1cDZEN056NkN0bjJTYkFuWjMyU3JCamJselRqY3kyK2Z2M3doaWEyVjNXaHlBNC9QckNVTTUxWFozUjRZRTBqbWoyN0NhOXQweUF2TUhwYXJxN0l4UkFOazdlazkxOGNMd1VDSWJBRTQyYlNabStYTHRFWEd6MlpjMGwySE50YXBBSXI0OGF5SjdhU0x3L0ZlUDhOOWZ6NW0xL21FemM4eHdyL1lYeGVoZWNhVnZHRko3YlIxQnZnVEZjT1NUdG5sQlc5ZWRtNU82WlVrMUNXWFA1Yldpbmc1MGVXTCtvT3Y2NnNqejk4Y0E5THZVZlE3SUVKMzU4dE5mUHdHNXpzRnhPMzFYUnc1OHBXTk1YaTIzWEw2WW0rUGdhc0wrc2pLTTl1NEZIYk1zWjBjTytMdWRHMEtVMkZZbnRRSUFTV1lQWUdEa25XNkkrUGJxVXB5NG5nV0lzejZYTUcvNWhKc1VlanBtaVF6OXh6Z0QrNDd3Vlc1TFhTbThqaXF5L2V4cU5IcXBHMUszeEpIQWVNS0FHN2tSTDFLSEs4NGZKS1hYNkRYNVlreWZURXMwYU53cjhZOE9vbW43bjNJTnVLanVDMk9zZDluMmIxOHZEYXM2aUxKQjNSU055d3RKc3RsVDM0WENaZmZXWTk5dVgrNWJDbXVBdkhuRVhmTkN0TldjN29TU242NDY1cjNnVWhzQVJDWUFsbW1ra2ZLN01sZlV5QlZSaE1MdHBRRFVrbmk4YWVyQ2svSitlaUQ5RWYzUDhpeTBLdHVMMXVITWRCTmJvSlVVK04velUrdVBFWi91VEI1M2hrNHlsY3Z0RS9NKzdrWHJPMXN4aVJnUGZ0T00ydGxjZlJ4N0d0NVRnMmVYb2JPNVoyaWxFRHVHZDFLL21CRkVGUG1uOTVkdTBWdjcrQVgycWZ0WElvcENqS1NvNHBzQ3ltNUFmYUlscGNJQVNXWU5ZR0RoTTN2YkV4ZkxEOEtXemJYSlFWS3lsdVRuWG1UZHZ6c3IwWlBubkhFWGJkL2hMRnlqSEFRY0hrWFZ0UHNiMjZDNjl1OHJNankwbkxoYU0reDVDQ25Pck1GVDMvSW0vWjJFQytkZ0hIR3IyZit1eFdQbmpEOFFYMy9XTXBqYjBOaFpqMnhLZUtEOTE4aXJTaDBqbm81Vnoza0dnUCtkSms2ZUZaSzc5dG1lVDZSbC9FOWNZOFdKSVFXQUloc0FTenl4UkNOYWgwUjBZUE5ocnlwOGtZenFLc1dFbVM2RXVNZjR2d3VWT2xuR3dQalhsZFdVNmNQM3JUWHU1ZmZwaUU2ZVVmbjdtSjUwK1gwanJnb3llVk4rWUpMbGxSYVE4dlRrZjNnYmlMNDIwaGZuUndHVjkrZWpOLy9maE4vTW5QN21UQUtBQkdGbGlPbldGcFR0dVk2VmptSTdwcTg0dWoxZnplOTIvbG1mcnlDZnNOL3ZaOVJ6QXNtZi9kODNvdzIzV2xYZGl6NUJxUU1SeEMvdEUvcXp2aUZWdUVnaGxCaEdrUWpNYWtiZm15ck5JWEg5M0pQY3VUeHJHSHN0MVBSL3loZVdjZHlIaEptd291MVJyeldzTlMrUHBMMjdodGFTTy9zdlhzcURuMEpPREJkVTFzV2RMRjExL2N5TTlQYk1RNkdNUHdsZzUvbitOZ1d3YXlPdVM3bFRZWDM3RFFIM2Z4OTQ5dklaTDI0YmlMVVhUUDY1VXBqWjZ6TU10cDRsZDMxQy9JZXRGVml6OSs4ejYrOHZSbWZueHNBeStjWGNKOXF4cTRlVm5udUVKa3VIV1RSN1kwOHZYblY5TTI0S00wSjg1TlN6dDQ2WHdYQ1NwbXRPeU9iZUhZUStQTWFQVEYzY2phbFBwOE93TEJjUE9ncUFMQktFemFvVVJTVkNLSjBlUEtLTEtEMTJVdDJtM0NoSlBEdWE3eFdZdk9kZWRndWN0NXFYVUxYL2psTnVMcHNXUDJGQVNUL09GRGRkVGtOU081Y3k1SDBYWnNDOWtNNDdmT1V5Z2ZKMlFmUlhjR3J4Sm9vMDVjampSaFM4WmNKK1JMODdmdmVKVS9lZE1yM0ZqeUdybk9TWFNyZTh4ME9ySVY0YWFxSnZ6dWhYc2ExcVZhL083OSszbjcyaVBZanN4M0QyL2o4NC9leEw3emhlUEs2cmk5dXB1bEJWRitjbWdvVVhtdVA0VmZqYzU0dVczYnhPdXlVT1RSU3hsSmFGT041QzhjN3dURElpeFlndEhvbmJSeWwxVU1TeUtSVWZIcUl3dW9MSy9Cb0dYQ0lndzJhc3BaSEdvcFlrM3A2K0VBT3NKZW5qaGVSVjlpYUh0VmtXeFNwa3BmcGhoSlZyREk0a0pxUFgvelN6ZWZ1UFhRbU50U3Fteno4ZHVPOGRpeEtNODNyQ0xtRktHbHp2R1JtK3RaWGpTSVZ6ZjV1MTl1cHorVC8zcmJTZllZWWkvSTJlNXNIbHAzWWNHMVNYRjJnZy9lV0k4RG5Pdks0aGZIbHRJVnl5VWlsU0hKYjR6MDdaQWpOL1BndXFZRjMxY2x5ZUh1MVMzY1Z0UEdvMGVxZWEyNW5QL2V2NFBIai9meTFnMW4yRmd4K2xEeHFUdVA4eDh2cmJ6ODd6eC9qSzZJZ3pTRFFVY2R5eVRiTzdyd1RXU0d4aW1QUEtXcHNCZUJRQWdzd1FTWmZGUkFTY0tsRGZtMWpDYXdjdjBwK3NPTDFORmRWbWdaZVAzRTNvOE9MbWZQaGFVazVMSnJ0MHl2bUlja1JXWFFXY1ZYWDNEenBqVW51VzFGMjVpZjlkQzZKZ29DQ2I1M2FDT1dKNCt1cUk4TkZiMDA5L25wVFJhQU92UUJqbTJSNnhzOXJVanJRSUMwcVMzc3RnR1dGNGI1VE9GQklrbWRIeDlheHFtZVlpSk81V1ZyaDh2czRoM2JUbzFwSVZsSWFJck4yemVmNC82MVRmend3SEpPZEpieXpYMDNVWENzaDBjMm5XSjF5ZkN4dzNKOGFYN25nU09YLzcycHJKTVR4eEtnK21hc3JMWmxrcHMxdW9QN1FOeUZTMk9xMGVYN0VBaUdNelNJS2hDTVJGM3RyZ3dRbWJSNlZ5VUdFMk9GYW9pUGVVSnJJVE9RRHZIU21XSysrZklhWG1wZVQxSmRNajUvTkVraXJsYnpzNU5iK04rOUs4ZTFWYk8xc3BzUGJkK1BiRWQ1K3N4S3puVG04TU5ETlNTdVNBMmoyRkhXbDQwZURMS3BiM0dGY1FoNk1uem9wcE44N3I2WFdKdjlHaDZyRFhCUTdVR1dGb1FYWmIvMTZpWWZ1TEdlejkzL0l1c0tHNGxtZkh6amxadjVxMS9jTUs1c0FFc0x3L2lrZ1JrdG8yT1pGQVpIRHpJNm1IQ2hxbE1TVjVHTDQ2UkFJQVNXWU1MMFRMcHp5UXF4TVh5Rjh2MUpKQ2U5YUNzM29aVHovUk4zY0tCM0c0WXk4YkFOS2FXWTE3bzJzUHZwVGVNS0VMcW10SjhQYlQrRUxObjg1NTROZE1ieXIwb1I0cGQ2V0YweWVvYWsxZ0UvZnRmaW0xT3lQQmwrL1k2amZIVEhLK1RZOWNUa0pYenh5VzBrTW90M0l5RGJtK0ZqdHg3bkQrOS9rUzFsRGNRemJyNzg3STM4N2VQYmFlb2RPV1ZUUVNDSkxzVm50R3lTa3liZlAzb01yRmhhUTU3YUFadHVCQUloc0FTVFpQTCtCWkpDTktXTk1VQ25rVEVXZFFYYmFoQkptYndQbWlsbmN6YStucjk3ZlB1NEp2dTFaWDI4YTlNUkREekVwTEtyVnZ3Vk9YM282dWcrV1AxeE55NTE4Vm9kVnhZUDhFY1B2VXExN3dTOVJqbi8rTlJXVW9heXFQdHdsamZEQjIrczU4L2YvQ0p2V25PYWNNckRsNTY5aVM4OHNZM1dFVElXZVBXWkZla3lCdG5lMFJkdjBaUUcwcFRhVG13UENvVEFFc3orQUdKSkd0SGs2QUxMN3piQXRrUXRUL2xOZHROaHJ1SHZmcm1Ed1lRKzV1V2JsM1R6OE9xamVPMkwvbHVPUTlCcDVMM2J4ZzQza01vb0JOMkxlMWZFclZuODFyMEhXUjJxcHpkVHlwZWUzaktwWUp3TERWMjFlWEJkRTMveGxwZW9DblhUbkZ6QjdoZHU1MHRQYmFFamZIVmNQSzgyczVacng3WUlqSEc2TTVyVXNLUXArUk1LZ1NVUUFrc3dhU1p0QXJjY0Y1SFU2Sk45d0cxZzJiYW81V2xBVWxSNm5WVjg4YWtkZEVVOFkxNS9SMDBiSDcxaEx4WGFJY3IxSTN6eTF2MWtlVWNYVG4weE41SWs0WE1aaTc2K1pjbmg0N2NmWTNuMk9UcVRTL2pHOCt0Rko3eUlwdGo4NXAxSHlKRmJTQ2psbkV0czVrdlAzY2J1WnpiUmZiRnY1bmhUT0RQNDd0dVdQV2I0akVoS3gzS21kSUpaYkJFS1JrU2NJaFNNeGFSOXNDUlpZU0F4ZXJEUm9DZURhVHE0UkQxUGo4aVNGZnFkbFh6NWFZblAzUE1haGNIUmZWQldGZyt3c25qZnVKL2ZOdUJEa21WeS9XbFIyUXlkTnZ6RTdjZjQyOGM5bkJ1c1ltOURKemNzd255RTNWRVBCWUdyKzVxcTJJUzhjZnFUSU1reUNaWndPbGJHRjU4dG9ESzdrNEFyaFdPYnc0Uy9tQjVNeXlIb0dYM0JNSkJ3VHpYSWNZOTRDd1FqTHNKRUZRakdZTkltY0VsV2lDUkhIeno5TGdQTEJoeEgxUFIwVGZxU1RFU3Q0U3ZQYkJ1WEpXc2luT3JLeGFYWlkwYkhYbFNyVk5ubVUzY2N3aTJIZWVsYythS3NnL3IySEg1MGNObTFkYU5ZMTR3SmNhV1M0K0d0SE9tb0dET1E2MlJ4SEFmTEhocGZSaU9TMUtjcXNNUVdvV0Rrc1VGVWdXQU1KdTNrUGg2QnBhczJxdUpnMjlaVTg0RUozaUN5d3NwS3Z2b2MvT2FkWTF1eXhzdUZ2bXl5UEpsRkZmc0poZ0pTMXI2OGt1NTRFTC9MUkpZY1pObEdsUzA4bW9sYnMvRElNV0pwZlZIMnQ2SmdndThkV0VPT044V2RLMXZITVRhb0pPVnFadXBvZ0dOYnFJb3o1b0dOU0ZKSFVxZFVDaEZrVkRBaXdvSWxHSXRKWjdDVlpZVjRlbXpSNU5GdEhOc1VOVDN0SWt1aVgxckpWNStiUGt0V05PM0JweTgrNjVWWE4vbm9iZldFdkVuYUV1VTBwalp6TnJhUjB3TXJPZHk5bWtNZDFhUnRMNHBra2pZWDM0bkNnbUFTdjAvbDhmcTFIRzdKdSs3bGNXd1RqejYyZFN5ZVZxY2FwaUVtUmhyQlNBaVRnV0RHQmhCSlZraGt4aDY4ZkM2VGlIQjBuem1SUlExZmVRWis1NzQ2UXI3Smk2TzJBUi9SakkrVmhWMkxzaTVkcXNXdXV3L3gyTEVCWGpoWFExeFpnc3ZwWTFQcEJlNWUxVXBoTURtdUJNZ0xrUnhmR3BVMFlYVTUzOWx2a3VYZVIxVis1THFWeDdGdGZLNnhGMjNKaklKUENDekJEQ0VzV0lJeEYzbFRtTjJ4SFRESENJRHBkeGs0SWxURERJb3NtYkJTdzVlZTNrWi9mUExIQ2ZZMkZwTzIzV3dvNjFyVTlmblF1aVkrY2NzZXN1MTZra29GaHp1WGNiUTFmOUdLcTB1NDFTR0g4cGhTemIrK3ZIbmEvZjhtSnJER0R0RmdXaksydzFUVDVNVEZDQ01RQWtzd1dRYW5NckVEWTI2WitOMFpIRWNJckprV1dmMnM0b3RQYmlPY25KeWYwS211ZkxKZFlaWVZSaFo5ZlZiblIvaURCL2RTNlQ1Q2hpQlBuTjNJOS9hdldOUjE0cjIwZFN4SlJKVGwvTk96VzBta3I4OG1pZU5ZWTJZYnVEUXVYWm5KWURiSFI0RVFXQUxCbEZab21qSmtoaDhOajJiaWlGT0VNeSt5WkpsQmVTVmZlbXJibUJIMjMwaHZ6RTBrazAxQWorTlNoUmdHOExrTWZ1ZUIvZHhTZGdEWk1kalR1bzcvMmJOcTBkYUhSelhnWWxaTVNaSVpsR3BvR0VkZXdwa1JXQTRlYmZRdHdtUkdRWnU2dTV5d1lBbUV3QkpjbndGRVZpQnBxR09zZkUxd2hBL1c3SWdzaFY1bkZWOTRZdHU0RGlCYzR1bVRTNGlZMmF3cjZSS1ZlR1Y5QXUvY2VwWVBiZCtMeCtualFOZEtmanhNdUlMRlFGNGdnVzFaVjczOFNyRHkraFRHc2ZIb1l3Z3NRMFVXQWtzZ0JKYmdPaklsSjA1Rmd2UVllZHFDN3ZTTVJuUVdYS3Q2KzV4Vi9PTlQ0MHRVN0RnU0p6c0x5Tkw2dUhWRm02aS9ZVmhiMnMvdjNmOHFlVm83ZXk1VXM3ZXhhTkhWUVZFd2RzMXBZRm5Scmt0WkhOc202Qjc5UUVmYVVGQ2tLWCtVY0hJWENJRWxtQngxdGJ1bTVIQWp5ZEtZUGxndXpVSkdiRHZOSnBLaTBtV3Q0aCtlR0R0UjhhRUxlWVN0UW5KY2cyUjVNcUx5UmlEYm0rRnpEKzVqVFdFclB6dXluS2RPVkdEWlF6TjRKS2x6dkMzRVR3OHY1WnN2citXZm54dnkyVHJabm9QdFNBdmkrL3RkR2FRNTRrc3BZK0hTUmk5TDJsU1E1S25WL1ZUSFI4SENSb1JwRUl4M2xlYWYxRUFueTJOTzRDN1ZRa0xFd1pyOVdVaWoyMXJGbDU1eStPeDkrOUZIOEsxNm9yNGFHWnY3VmpjdW1xcEpaRlRPZEdaenZEMmZ6a2lBcEtHVE1qVk1XMEZYREh4Nml1cmNBZDYxN2N4Vjl5bXl3enUybk9FclQyM2tGL1hyZVA3Y01pVEp3WFJjeEswZ2h1MTYvZFJhbjhPcnpWR0NhaC92MjNhY2xjVUQ4N3JPUExxRktodk1CVnUwaERtbXIyREtVSkRsS2RrWWhQVktJQVNXWU1yRUp5dXdrR1NTWTJ4RHVUUUxDYkZGZUYxUWROcU5WZnpEa3c2L2M5K0JhMFJXWTArUXZuUUJXV28zR3lzV2R0RHFsbjQvTDUwdG83RTNSTXp3RTdPeUFmQXBVWFE1aVY5UDQxSU5OTVhnZEVjMmJ2WHFNQUNkWVM4L1BieU1DNFA1aE8xU0pNWEV3c0FqSjhseHhWamhhU1Uva0NETGs4S25HOFRUR2o4NVZFM015Y0k5akVOMklxTmlXaklaVThhMGgvNExrTEZrREd0bzBaSTJaQ3g3NlBjNXZqUkxjcVBYTGNxK0t0dHo1ckNLaEQybUJTdVpVV0ZxSndpRi81VkFDQ3pCdEFpc3lacEpTSnVqRDJJZXpRSVJwdUc2NGNndTJqT3IrTW96RHI5MTd3RlUrWFd4KzhPRE5TVHNFTGNzT2NsODJzaHFIZkFoUzFDU1BYclhqYVkwbmp5eGhPUHRSVVN0SEJLV2x5eTFqNkFlb3lhcm5jMFZIVlNFWXVSY0VhRDFzV09WTkE2V2M5dnlFd0NjYk0vaDBXUEw2VTNta3JTQ0JOVnVsdmxQY3VQU1Z0YVU5STBZaitueDQwdkFVd0JtZ3YvYXV3a0hDZE9Xc1IwSjI1RnhrSEVjQnhrYkhBc0pzR3h3a0pCa1NCc2F5Q3FHNDhiQ2hVZExVK2hxNVE4ZTJuZGQ2dHkwWlNSSllrNUlMTWNhR2xkR1lXaGNFZ0pMSUFTVzRQb1NuZlE0aHpLbUQ1WmJNMmNzNmF0Z25DaHVXbElyK1lkZlNuejY3b1A0WENaMWpZVjBKVXR3eXpIV2xNd1A2OVdSbGp4K2NuZ0ZVU3NQMnpLNFo4VXBIbHAzL3Bycld2cjkvUGpRQ2pxaUljSldIbGxLTC9udUxtNm9hbU5iVmRmUXlkWmhDQ2QxWG02b3hpUEg2SXU3K2Z5ak54TTI4cEN4eUhIMTh2Q3lvOXkwdEFOVkdiMC9OM1JuOGR5NWxXU1VmTkNoeDNad3JDUit1UmV2RXNPbnB5a0tSbGxSMEVldVAwWEluOGF0V3BkUHhtVk1tWXlwRUV0cjlFYmRIR3ZMNDVXR0N0THE5Y3VGYUpneXRqTTMwZ1E1amoyc1ZmQktVb2FLZ3pLVmhVTlVEQndDSWJBRTF3MWJVc1k4UmVqU0xCRUhheTYwbGV5bHhWakwzenpoSmRzZHB6dVJSMG9wd2pFVG5PM09ZWGxoZU02V3ZiRW53SGRlVzAxZk1vUmJUVlBzYmFjcm5zUEI1cEtyQkZaVGI0RHZIVmhGVHpJZnczYVJyWFh6UU9VKzdsbmRQS0tvdXBKdjdWbERtQ3JjOVBHelV6ZmhsUWVwQ0xUeUs1dFBVeDRhbjB0T05LWHhuNjl1SUM2Vm8xdTkrS1ErOG53Uk5sZDBzcmEwYjF6cGpIVFZSbGR0L0c2RGtDL0ZqdzdWb0hxQzNGVlRQNlAxYkZveVQ1OHM0NEYxemRmOHJUZm13VUpqTGtnc3gzYkczQ0xNbURLMnBJaVRYZ0loc0FUWGxlUk1QbHhYYklTK21odElzc1lnTlF5bTRkSk1LYWxlWG1sWXd0MnJXdVpja05HdWlJZi8zYnVhN2xnUWo1Ym1iZXVPc0tPNkUxMjErZHhQN2lGakQ0VUo2QWg3K2IrNjFYVEVDN0ZSeVhWMThhYTE1OWhRMFR0dUM4Yko5aEFYSW1VZ3l5aDJtdVZaRjNqM3RsTVVCc2YvZXRpT3hEODhzWm1VcWJBNmR6OTMxbHhnWmZFZzhpVFQ3RGpBUHorM2tTNXJHWDZ6RWNjWjJzSk1aRFRpYVIzRGtrbGRZVUZXWkFldlp1TFJEVXF5WXVRSEV1VDZVK1Q2VStPcUIxV3grZW5oYXZ4dWsxdVd0MS8xdDdiQjRIVUx5ekJjdmVqS2pGdkZFMkxFRUFpQkpaZ3FhVkVGaTVzd1Mvanh3VTdlcy8zMG5DaFBOS1h4N2JwVm5PL0xJZUJPOGRHYkR3NXJZVE50bVg5OWNUM24rb3N4SEIrNWVqdVBiRHJONnBLSm5kaXpiSWx2NzF1TjdVaFV1Zzd6dnUwbktjMlp1QXZPbWM0c0hscDNuaTFMZXNmY1Jod1AvN3RuRlUySjVZQk9XRjdLdDQ5WDQ5ZzJzbVNoeXdhS1pLSEtKamhEdmxzV0tvYXRZZGdxamlPaHlRWStOWVltSmZIckNaYmtESExqMG5ZcTgwYmUvVnFTbitMbngxZFRsUmUrcWc2Nm9qNGtXVmxNcjRXSVdTSVFBa3R3L2JBZGRjeEk3cGVYbklLNWkrTGhhSHNwYjBvMWpwbEVkNkwwUnQwY2JDNWdYV2t2eGRtakd3Vk1TK1puUjZyWmY2RUVWYmI0d0ExSFJ4VkxVYnVRWTcyRjVDaXR2SDNkRVc1YzJqbXBNdjdpYUNVcEF6NSt5MHRUQ3Fld3NuaHcydXJ0aGRPbDdHa3NKdHZmamQvVmpFZkxrT3RMVXB3VkpjK2Z4Ty9Pb0N0RHAra1V5Y0cwaDBLbUpBMlZTRktqZlRCSVY4UkhKTzBpWWJnWlNHWFQybHJPL3ZZVkJMVUJWaGQxOGRDNjgvaGNWMitkNW5nU3RLVFg4dlVYVS96aGczc3YrNFZGVWw3bXlrbUk4YmdjSkRJcXRpT21RSUVRV0lMcnk2Um5CUWRwek8wL2oyNWgyVUpoelhYQ1ZQSHRmVDE4L0xaajAvYk1wMDlXOE5TWkd1S0duNmRPaGZuOSsxOGx6NThhOXRvOURVVThkbnc1aGlWeis0b21IbGpUakRUSzFwcGxnVmZ1WlhQNUJYNWx5N21yVGtkT0JNdVdLTTJPOGZmdmZIbk9uS1IwSElrY2I0clB2M1hrK2hxYjdtc0VSMk5Qa1AxTnhaeG9EL0hjK2MzMHhieDg4bzRqVjR2RW9qNk85R2NZa0pmenRlZFNmUGIrL1hSSFBLUnNQOHdSQTVadE15NmZPbWRxTFRvb1JnV0JFRmlDT1kwa3pGZnpvNTBVbFliK0Vyb2o1eWdJVHMwdHp3SCtkKzhxRG5kVTRwRmpyQzVwWVYvSFJoNDlzcFNkTjUrNDZ0ckduZ0RmM3JlR2dYUTJSYjVlUG5iYjBYRkZsQTlvWVQ1eHgvRUorVWdOaHlJN2JLbnNtVnR0SVRtc0wrK2IxbWQ2ZFpPVlJZUHNhU2pGVW5NSVN2M2tCYTYxS0ZibmgvRktnNlRrWWxwVFMvbitheEZzUnlKR29YQVlGd2lFd0JJSUJKTWhKcFh6UDNXcitlMTdEMHo2R2FZdDg4L1ByYWN0SEdKVHlYbmV2ZTBNZzBtZEV6M1ZkRVlEbDYvTG1ETGYyck9hVTczbEtJN0IvU3RQY3UvcTVuRi96cCsrNVRYUllCT2dNK3psR3k5dUpHS0dLUEcxODZFYlQ1QWZ1RmFjbG1USDBhVTRLY0NVczNtdGRUbXlIVVhXTlZHSkFvRVFXSUxaVzJuTFJGTmp4T2FSRUtjSTUwdDd5Z29kc1dJYWU0SlU1MDg4RFZzaW8vS1ZwemNSVDd2NGpkdjNVWkU3Rk5vZ3o1OUNsNUxFTW00QXVxTWUvdm01VGZSYUZlUXFMWHp5dGtOaittY0pKczlMWjB2NXhmR1ZSSlZxWFBJZ1NjUEZ0L2FzSmNlYnBDcHZrTEtjS0VWWkNRSnVZK2drb3BvaWNuSEhOYW1XWVJ2cE9XVzljcHpYTXhLTlJDU2xJMG5DNWlZUUFrc3dmNmZrTWYwY3ZMcUpKZUtNemh1U1NnbmZlVzBWZi9oUTNZVHVDeWQxdnZ6MEpyeTZ3UjgvdkFmM0crSVVlZlVVNFV3Mno1OHU1WmNuYTBpUnpjcXNVM3o4dHFQb3F1Z2dNOFg1bmdCN3poV1I1VW5ndFU2Uk5qWGlobytJR2FJcDVxYXVYY090cHZFb2NWUXBqVWZOMEJQUnJrcWVKV3V1T2ZXZExKdkx6dmVqcnV5UVJBY1FDSUVsRUFqbWltYVc2TW1Vc3IrcGdLMlYzZU82cFN2aTRXdlBibUJsMFFEdnUySDRVQTlaN2lTZHFTVThlbklERWc1M1Z4L216UnNhUlgzUE1GWDVVWDd2d2F1M2ZET21Rbi9jeFVEY1JYdllSME5QaU1Ha2gzREtTMSttQU1NVEV2NVdBb0VRV0lKcFlFb3BJY1QyMzhMRFVQTDUyWkVWYktyb0dUTzVjSE8vbjI4OHY0N2JhOXE0YjgzSVBsVEw4Z2M0M3Evamt4UDg2dmFqckMzdEZ4VjluZEJWaTZLc0JFVlpDVmFWREhEM3FsWmdLRkJxVTIrQVZ4dEtPZDhYSW1vRWlWT0lwTGptM1hlY2huRXBJbnFLUUFnc3dWU1pmUGh1U1NLZUVjNnZDNUZCcDV3blRpemhvWFZOSTE1VDM1N0RmKzlkemNQcnozUFRzdlpSbjdjMGY1RGdxUVkrZSsrQktZUWVFTXdrc3VSUW5SKzU3SC9YRjNQejRwbFNUbllXRURXQ1JDbEZrdWZIK3g3UGFFanlsTFlJeGI2MVFBZ3N3ZlZEa3NiMmM3aVUwc0p4Yk9GME9vK3dsU0N2TkZaeVowM3JzUDR1KzVzSytPSEJHdTVmM1RpbXVBS296SXZ5bDIvYml6Nk9kRHltSlE5dFlTVmM5RVk5dEljRDlFUzlKRTJOYUVMaHMvY2ZtUGFBcUlKcnlmV25lUHZtQnQ1T0Ezc2JDdm51TVI4RytkZTFUSTQ5Tko2TW5kWkorR0FKaE1BU0xQUk9lQ2xsaUNQR3UvbkdvRlBKOXc5MDhjRWJyMDR5L095cGNwNnNYOGFPeWhidVdOazJvWDZReUtnTXhGMzB4MTEwUjMxMGhQMzBKenlrRFkyMHBaS3hOREtXaG9XTHRPMG1iV3JJa29OSFRaT3hWZkwxVGlHdVpwRyttSnYvMjdlS2xrZ1JHVGwzenJ6Q1kyMWRDd1JDWUFrRWdqbUxwTGc0MlZWR2YvdzhJZC9RdHQ1UERpL2xsZlBMV1JacTUrMmJ6NzF1V1FBaUNmMnk1YWt6N0tjOUhDQ1cxa21iR21sTEkyMXFtTTdRLzZjTUhTUUp0MnJnVWcwa3gwUlRESFRad3F1bGNLdjkrRjBaaXJKaUZHZEYrZG5ocFF6WXBkUVVkb3VHbVFXaUtZM3Y3YS9oYkc4eFVXa0prcUtJOVpGQUlBU1dRQ0NZdG9sV1dzTC83TzFsMTkySCtQNys1ZXh0WFUwcUhzYklrdm5IcDdhUk1qVXlsa3JhMUxEUVNaa2FhVk5GVnd6Y1NnYVhtc0dsR0xnVWc0QXJpVnMxQ1BsU0ZBVmpoSHhKc2p3WmdwN001UmhNdy9HOS9Tc1lORXNvOWJYd3JtMW5SS1BNSUdsVDRkRWpsVHhiWDRIbExrSFJQSXN0eWJOQUlBU1dZTnFZa2pPbmlIRzFzSkZraFpab01WOTl4cVlodW95TWxJUGp6K05rMkVZamhrY080MWJTNUhoaStQUTB4Vmx4eW5QQzVBZVM1QWRTK0Z6R09QcVF4TEhXWEo0L1U0RXEyL3ptWFljdi8yMXZZeEY3bTFlUXBmYnc2YnNPSVV0aWEyZ21VU1NIRzVkMnNxSndnTTV3QSszaEFJTkpOeWxESTJucXBFMGRVL0tRdEFJNGl2YzZpQzludHNZbFMvUUdnUkJZZ3FreTZlUElraVNUekl6ZHpUVEZ3WEVzSkJGZFoxNlNsTXM0MmUvQnI2VUp5bWNKdWhNc0NRMnl0cVNISmJteGNRUjl2QmJEa2puUkZ1S1ZoakthK3JLSnB6VnkvU2xxQ250eEhBbEpjbWdiOFBHVEkydlFwUVNmdXVQZ3VCTDhqalFsaHhNNjBaUk9OS1dSeUtpRWsyNHlsb3lNdzMxcm04WDIxNlZKUTdFcHlZNVRraDFuWGRtMW9UUk1XNlkzNnFZejdPRkVld0Z0Z3dFaUdSOHhLNFFoaDVEa21YM0hIY2RHVThZV1djbU1PdFZETlZIUkd3UkNZQW11dDQxakhFSk0xTkw4dzBFMkkvamxIckpkVWRaVmRiR3h2R2RLS1czNjR5NzJOeFZ5dUxXSXJvaWZsS0VROGlWWlg5ckZIVFV0bElkaWw2OU5aRlMrL3NJbVRFZGo1L2JYS01vYTMrZEdranIxSFRtYzdNaWpKK1lqWmJwSW1ScUc3Y0owaGh6b1RVZEhrbFVVMHR4U2NVU0lxNGxNS3JKOU9ZYld4b3FoaE5TV0xYR3VLNHRuVHkraE5Sd2k0cFRpS0w2WkczR2s4ZlJlMGFvQ0liQUUxNS9KcjlSa21VUm03QzBDVGJGeEhMR1hPQyt3VWdTa2RrTHVRVzViMDh5bWl0NXhoVllZZnBLRGh1NGdMNTh0cDNrd204R2tIOE9TeWZORjJWaldjWTJvdXZLK2YzbCtBeEV6eEFNMVIxbGIxamZxNTdRTitIanFaQ1V0ZzlrTXBud2tERGMrTFlWUFQrUFJNZ1JkQ2J5NmdjK1Z3YXVibk83SW9pMVpSYTdXd2J1MkNwK3VxYUxJRGpYRmc5UVVENUl4WlI0L1hzVytwaklHcVpyMklLV09iYU9OSTdWU01xT0FJaXhZQWlHd0JOZDVTcDNDV25LOE9neGJ1TTdNN1VuU0hDUkxhV2RqUlFmM3JyNHc2VkFJamlOeHFqT0xGODRzb1MyY1RTU1RoU3haWkx2Q2JDcHRIbEZVWGNtUERpem5RcmlVdFlYbmVYQ0VRS2VXTGZIS3VSS2VPMTFKZDlTTFczZkk5Y1haVk5yQ3hySXVxZ3NpdzI0cFpreVpBODIzNEZZU2ZQQ0c0K0s0L3pTanF6YVZ1V0gybkY4Q2lqNGpuekgrK0tGVHNtSUpIeXlCRUZpQ0tST2Z0THlTSkZMRytDeFlhV0hCbXB1RGhEVkF0dExHZmVzYTJWSGRPV25CMFJQMThOaXhLczcxNWhFMlFxaVlCUFZCdHBTZTVjNXhpS3BMSEc4TDhWTGpVb3A5blh6MGx1UFhDampnaFZObC9PREFVaXhiWmxsUmxQdlhOTEN4dk9lYUJOUEQ4WU1EeXhrd2k5aFNlSUxxZ3JEb0FOUE1vMGVxZUtGeEpVbTFZbVkyNlJ3YlRSbDdMRWtaS3BJNnBSTEVSV3NLaE1BU1RKWEpSMjJVSkN4N2JETzhydHFrUk5MQ09ZVmtKY2lXbXJoblZTTzNyV2hIbXVUcHZIUGRRWDUwcUliZVpDNUowMHUyM3NmNmdnYnVXMzJlaXR6WWhKNDFFSGZ4MzN2WEU5Qmo3THI3NERWaXJ6UHM1WitmVzBjaW8vR205VTNjVWRNMklRZjducWlISSswVjVDZ2R2UCtHVTZJVFREUC91MmNGZXk1VVlidUxrUjFuUnB3dkhjY2VSeFQzSVF2bkZEOWZSTE1WQ0lFbG1ES1Q5bHFXSkptTU9mWWc1dFlzd29hd1lFMXV3VzVpV3hZU0pycVVRcFV5S05KUVlFNUZzcEFsQjBXMlVXUUxDUWRKQWxXeUw3YVBnM0x4LytNWm5haVpUZHpKSnlDMXNhSDRBdS9hZXZiMVNQc1RwTG5QejdmM3JhWXpXWUFFNUxsN2VmZkdBMnhhMGp1cFVBcW1MZlBWNXpaaDJqS2Z1ZU1nUHRlMXd1bDBaellmdWVVa2xYbVRjNC81MXA0MVpHd1g3OTl4Y05KK1pZS1JlZmVPYzJ5dDdPWkVSejdOL1VIYUVxVWtwZUpwRmxnT0xtM3NQcHN4SmZTcG5TSk1pQllWQ0lFbG1DcXh5ZDQ0SkxER0hzUzh1Z0VaSWJER0ZsTVdicWNIbnh6RzcwcmkxVExrK1JQa0J4TGsrcEw0WFFZK2w0SFBaZUp6R1JQZXptc2I4UEhDbVRMdVhObENjZGJrNW85a1J1Vy85cXptYkY4cEFFdUM3VHl5NmN5RXJWVnY1TjlmWEV0UExNREhiems0WXRsdXIybWY5UE9QdHVUU0hDbGllYWlWZGNNNHpadjJVUDdEVkVZaG50RXdUQmxWc1ZFa0I3L2JJTnViSGxiMENhNlljR1Q3c3JNN3dOZGZNRGcyV0RDOXNiSWNlMmc4R1ZOZ3liaW1KckJpb2tVRlFtQUpycXZBQWtnWnlxaitMeDdkdkp5a1ZURHNySUhIYXFNODBNNmIxNStqTWo4NkkvNHJwVGx4M3JmajlLVHZQOTRXNGp2NzF4SXhjaWoyZHZMK0cwNk0yN2RxTkI0N1dzbXg5a0xlc3Y3TW1DY0dKNE5sUy96ZzBDcDhhcFFQM25pU3hwNGdaN3R5T05zVElwWnlEd1hRdEhSc1NSOEs0MkNyRjYwbElFc09MdFZBSVlNdXAvQnFhYkk4U1RhWGQ3Q3VySDljZ1ZRWEszZXNhS1orYncyV0hKcEdmV1dQdVMxOHlTOVVFZ0pMSUFTVzREb3o2VUNqU0JLU0JPa3hCSlpYTTBXWWhoR0VsV29Oa0tPMDhhczNubUJaNGR4MXV2N2hnZVc4Y240WkxpWEZyNnpieiswMWJkUHkzTU10ZVR4MmZCbmJLOXU0ZisyRkdTbjd6NDlVMHhQUHdhZUcrZHNuYnlGcEIwbWFMdnhhQWwySzQ5UFMrRjFKUE9ycm9Sd3ViU0VtTWhxUnBFN0MwRWtaR3RHTWgrNWtQc2U2bCtNNTJNODdOeC9ueHFWZG9pc1BROGlYeGkwbmlET05Bc3V4OFdxakM2eTBvUXk1WDAzTkJ5c2lXbEFnQkpaZ3Frd3Azb3VxUU5KUXlTSXo0alhaM3BRUVdGZE9FbVlDdjl4TnlEWEFYV3ViMkZyVlBXZkRJdHFPeE5kZldNK3AzaVVVZWJyNDlUc09rK05MVDh1ekwvVDUrZVlyNjZuS0hlQUROOWJQU1BsVGhzS2U4K1ZJcm13VXhjQ3R4aWoxTnJHbXVJY1ZSWU1VWnlVbTVPQnZPeEl2blNubVp5YzM0VmRTYks4U3lhZEhRbGN0SktiM3ZYY2NpMnh2YXRScmtvYUtPdlZkU1JFSFN5QUVsbURLVE1rVXJpb1FTNC9lMVh3dUE5bFp2RnNwam1PaldRUDQ1RDV5UERFMkwrdGt5NUl1c3J5Wk9WMXUyNUg0eXRPYmFJZ3NSelo3Y0drV1B6KzZsS3E4QVVxejR4UUdFNVAyUytxS2VOajl6RlpDM2lTZnZ2dndqT1VZZEdzV04xYzM0OUVhMlZMWlRjaVhtdkl6bno5VENZN0VlN2JWaXpoYW93MHNhUTE3bXFjaDJUSHhqN0V0RzB0UGk4QVNXNFFDSWJBRVUyWktwbkJGa1ltbnRWR3Y4YnNNNU1WNDZ0bHg4Tml0bFBpN3VHOVZJeXVMQjRlZGtCMkdUc2k5ZXE2TTdwaWZsS2xqMmtNemhLYVk2TEpKbmovRyt0SnV0bFYxejByQ1l3ZjR5dE1iT1R0UWlhMjRRQ3ZqYkJUT2hDMWV2bUNna2tDeTArQ1l1RlNMcFFWaGZ1UE9JK042ZG4vY3hUOCt0UjFWc2Zuc2ZmdG4vRVRmV3pZMlR0dXpIaisyaE41TUNUVTU1MWhWL0hxdXZsaEtZeURoSXB6UVNac0tTVVBGcFZwNGRZT0EyNkE0T3pHdStFMExhbUJKNnFSc0w5T1pnbFRHR05QdkxaN1dVSlFwZjZnSWtpWVFBa3N3WmZxbmNyTWtqVU5ndVExd0Z0bXhlTWNoYUovbW96Y2ZZbW4reUJyMnBiTWxQSHFrbW94U1FFWU92WDdpNnRLZW9UMzAwenBnYzdRbnpPbk9ZM3p3cHZvWkwzNGlyWEhiOGxadW8zVmMxM3ZIYWNucWk3bjV4NmUzWXpreXYzTnYzYVFqeGw4dndmQnlZelZ1K2lnSXhQbW5aemNUVGJ0SlpGd1lqZ3ZUY1pFMFhaaTJqQ1FOaFJUUVpBdVhhdUNTNDNqVUZDRlBuSnVXdHJLaHZIZkJXNzh1OUFVeDhVNXZpbmZIR2hwUHhoQllVM1J3QnhnUVU0TkFDQ3pCbEtpcjNaWGVzWE4zQXZCT2FyeVRWT0pqYkJFRzNBYTJ2YmdFbHRkdTQyTzNIS1JxaEpoTjhiVEcxNTdiU0c4aUI5dUtrMVp6a0VjNXppNUpNcnFjcGlSN2RuWXVmQzZETFpVOTB6dmg5Z2I0eGt1YlNWczZIN3Q1LzdnVE9NOFZ2clZuTldGbkNUSnhuamxmakU5TDRKSmplTlVVT1ZvTW41NGh4NWNrNkU2anF6YU9Bd01KRDcweEQ1RzBtMmpLUTJPNG5EUDdxd2dlN21ObFlUZHYzM1Iyd1laL09OY1RRbGExYVgybWJWdGppdko0V3NXUjFLbjROU2JxYW5lbEVRaUV3QkpNQS8yVEZWaTJwQkpOYVdNS0xOTjAwQmRSaGZxMThJamlxaS9tNWt0UGJ5TmwrN2kzcGg2L251Ri9qaTBEWmVSWFZyWENiQ2c4d3oyclcrWmxmUnhxenVjNys5ZGpJL1BCSFlkWldUeS9EQVJuT3JPcGI4OGhQNnVCb0R2QnFxSStWaGIxVVJHS2pUdFlxd08wOXZ0NXBuNEp4OXNMZUtWOUsvc2E4L244MitySThTNjgrVHljOHNJMEg5OHdUV2RNZ1JWTmFkaG9VN0djOVNNUUNJRWxtRWFCVlRhWkd5M0hSVGpoR3ZXYWJHOGEwMklvc0pBa0xZb0svZi9aZSsvd05xL3o3di96WUhFUFNDSkZpcHJVbGl4Yk5pVkx0bHpiU2FnTVp6VnA2SFJrMkcwajVkZkVUUHQyU0gzYnZsMXBLN1ZwbTlocFVpbUxHYzBRa3pqTmNoelIyNVpGV1pTc3ZhbkpKWkVFRjBCaVByOC9BTmdRaEkwSHdBUHcvbHdYTHRrUzhJeHp6bjJmNzduUE9mZng1MU15WURMYzNQbE9USm41ajQ3MXVIM0YvUFpkaDFpMzhEcW4rNnF4S0E2OEZFZFJzVTdtbDU3TDJFNjdUUFBLK1RrOGVYUU5Sanc4dXJHTFZYUHlyLyt5bUx6ODR3ZjJNU09OSFpRSy9seGtIcCtDMTFSRk5kZjQ2SVBIQzFKY3VUeEdKbHlsb0dHT1VWUVZqNWU0dTFoSEhFVjRzYVRUQVlyQUVrUmdDWnFSY25aSHhXQmt5RjRTOHp2RlppOUdnNHJQNThWZzFMQlplbDBVTTRSUmNhT3FScnlZOEdIRXE1cncrQ3lvaWdGRk1malhOU2tHRkVWQjlmbFFWVy9nejFzakQ4SHZHd3pHdE1UZ21LK2VIeDlhd3NQcnp0NFV3Zml2NTlZeU9sWEtiWFU5MUZmWlVZSHFVbjhTeThsSWZZclBTNjNoREo5KzYrdmtvelE5TzFETmo0L2NScEZ4aWsvZTM4WDhHZm01T1N2VjQzbENtWFNaZU9MWk83bnFXSVRWMU11bkgreWl0bkt5SUIzSzJmNHFwckJxZWsyZnorOUg0cDFGT0d3dlNUZDcvQkNDSUFKTDBJaVVGOXNZakNac2NTSllBT1hGWGp3K1Q4eHBzS1FhdDIrVVZkWVR2UHYyYmlxSzNiZzhCaWJkSnR4ZWczOFhsOHZJaE5QQzJGUVI0MU5GREU0VTB6MjZDSU43a0UxTCtxZ3FjVkpWNGtUaDVvWEdOa2NKdzQ0U2h1M0YyRjBXSEM0TGs1NWlwdFJLcHJCaU1NWmZVNktxS2o1akJhOWRXMDZKMmNONzcvRHZZclBaaXdDRjhtS1ZvNE5yT1A5Q0k4V0dNY3BNay9pOG5sdDNXNmtxMWVwWld0K1duMmZuMlowbXZ2SEtIUlFabkh6bXJRZVlYYUJpSWhFR0o0cDU0dGttaHR3TldOeTl2UFAyODB3NHpaUzczSlJhQ204TlZ1ZWxPYmlWU2swSEJhclBRM2x4ZkR1d09ZclNIY2pkUUJCRVlBa2FrWEsyUk1WZ2pMc0dDL3pyc0lhOUh0Qm96V3NaQTN6aS91TUpKNG4wK0F6ODlVOW5VV09kNG9OM25VL3FYaDZ2Z1N2RDVSeTZNcHV6MTJjeTdxcGtYSzBINDgxVGVoYnZEV1phK3FncHR6TStaV0Y0c29KZm4xN09pS09Jajl4emlobGxUcmE5NndEalUyWmVQdGZBb2F2MWpMcXFzTGtXZ3NuOFptZmttd0pETVdYZWJqN3hHNGZ6ZGdycHF5L2R6cFRIelA5cDNqK3R4WldxS3V4KzRUYkdQRE53dWJ3NHFlZWJYWE1vdGZoM0Y1YWFITXlwSEdYenFrc3NtRmtZK1MydmpWUnJld1lob0hvOUNlMDZIWjh5b3hTbmRXL0pIaXVJd0JJMG95OTFnV1ZpWWlwK1U1dFZNY21nVGJ1UnVxS1FWQVp1azhGSGtkRU5hdkpqYXBQUlIyUE5HSTAxWThBNXhpWXRQSGRtSG9ldTFEUG1xOE50bkluRjNVdnprcU04ZFB2bG00VFpzNmZuOHJQWEZ6RXhaV0xyZzhjeEtQNUZ1dTlhYzRsM3JibkVzTDJZNTgvTTVVUmZMV051SzNicU1EaUhNQ2xUL05iNlk1cE1UZVdDQTkyek9UOVl5OXRYbnRIa3ZNSjhSbEZVL3UrN0QzSmxxSnpSU1F0VGJoUDlZK1ZjdFZVeTdDakY3aTdqOFBXNW5CcGFpTlU4eUh2V25HUHQvTUc4ZmQ5aGV6RjJUNFcyNjY4QW44OURUVlY4b1Q0eFphSzROSzN1cnc5QkVJRWxhRVRLSXphRDBZakhxMkIzbW1NbUFLeXZzbk55VUR1QjVmWVZNVHBwb2Fva3NXem9EcGNKdDllSUZwbUhLa3RjdkgvdEJkNjM5Z0t2WFp6Tkw0OHRZVWl0NThDbEJuNWpXZThibzJ5VDBjZmJWMS9oYlN1djh2enBCZ2JIaTI5WmN6T2p6QjlSK3lEbjZSc3Q1ZG5UOHpsL2ZSYTlJMFVjdUZoSDA0THJlWmN2YVdMS3pFK09ycUM2WkpLSDFsd1M2d293ZitaRVJKTnp1RXgwZHM5bS84VjVERTNOcE8zZ2ZkU2Q2T1dSZTQvblhTb0xnUDBYNnBoUWE3WE5md1g0dkI3cXF1d3h2Mk4zbXZGNEZRekd0TlNkSEM0cGlNQVNOS00zamZFNVJXWVltaWlLS2JCbWxVOWlWTFdiNnBwU0srZ2RLWXNwc0hwc1pSeTZVc3ZwL2xtTVRKVXo2cHZQMHJMWHRJdE1BSGN2R21EZHd1djg2dmdDbmpuVHlELzlZaVBiM25YZ3BtazlvMEhsYmF2aUoreXNyM0x3ZXh0T0EzQnBzSUpuVDg5bjMvazZmbU5aZmcyb3YvTFNHa2E5OWR3Lzc3QWNKWk1BcFJZUGIxblJ3MXRXOUhCNXFJSWZkaTJuWjZLTy8zaDJFM2ZPdWNMRDY4L21WVGtlN2FuRFlDclcvTHBHMVVsTlJld0kxdEJFRVVYbW9IV21qRVN3QkJGWWdtYWt0ZWJBYkRZd2JDOE9HNkhmek16eUtWQzFPM3ZQVFJrWEI2dFlHU0dmMHNCWUNidGVYTXVZWnhZVG5pcEtUSk1VSzJNc0tqdEJTOU5aelF2UG9LZzh0T1lTR3h2NytQemV1L2pibjJ6Z1gzNXJYMW9KSkJmT0d1ZjM3enVSZHcxSnhSK3RWTld6L05hNmMySlpTYkpnNWpoLyt2YURuTzZyNXZ1dnJXTGYxZFdjdVQ2VFA5aDBOQyttV3NlbnpJdzRLeldmSHZRM0xsZmNzeVNIN2NXWXpXbkh6bVFObGlBQ1M5Q01hK244V0RHWUdacUl2Wk93cG1JS3I5dWoxUnAzREVZTGw0ZXFJLzdiMTErK0hadDdObGJ6ZGU1YmNKTFZjd2FaTjJPQ1luTm1kK0xOS0hQeWQrL2Z6N2RmWGNtL1B0WEUzN3p2dFZ2eVlCVTZDdkRiZDU4UmkwcVRGZlVqL00xN1h1V0hYVXQ1N1dvamo3K3dpWFZ6TC9LaHBuTzZqbWE5Zks2QmNiVStJeWxGdkc0UE5SV3hCZGJRUkJHS0lXMHZjMDFhb0JDM0Q1SWlFQktoczYyMUgwZzV2T1JSaWhpeXg1NFNxSzJjeE9VaFl1NnAxSHB5aFRGbjVIdE91RXBvckx6SS8zdlBQbjd6emdzc25UMmFjWEgxaHRFcEtoKy85eVJ2V1hHTjcreGJLbzFMU0JtalFlWEQ2OCt5WmROK2loUUhMMTlaeTJkL2NRK1hoeXAwKzh5SHJ0YWpaR0I2VUZWOXVEekV6UnMyTkZHTVJ5bEs1MWF1Z0Q4VUJCRllnbWFrUEdwVGxTTDZSc3BpZnFmSTVLVzB5SWZQcTkzaHZwT3V5SWZ2RkpzOVhMZFg0L0htemdRZVhOSERiOTUxVVZxVmtEYkxaby93Zng5NmxSVXp6akx1cnVieEZ6YXgrOFUxakUzcTYvQ3BZWHN4bzY2cWpGemI1M1ZUV3VTTG0yUzBiN1FNTlQyQkpkRXJRUVNXb0RsWFVtNW9Sak85Y1FRV3dNeHlKejZQZGdKcnlsdk1sUHZXeFI0TlZTT011R3M0MDErVjB3S3RMblZKcXhJMG9kVGk0Vk52ZVozSEhuaUp1ckloVGc0MDhObW5mb1BkTDY1SnlQYXl3ZDZUODdGVG54bUI1WEV6c3p6K0pwbmVrYktFa2dGbndnOEtJckFFSVJvcG55SnNNSm9adHNjZk5kWlgyVkUxakdDNUthTi85TTB6cXUxT0UwOGVXc0tsWVNzR2RRcUx5U2UxS2hRVUMyYU84K2Z2ZUkwL2IzNkorZFZEbkwwK201MTc3K2R6VDkrVjArZFNnWk45czFHTW1ZbXFxVjQzYzZydGNiODNiQy9DWUVyckdhNUtLeE1TUVJhNUM4bHdPUjJCNVhJYm1KZ3lVeDRqMC9LQ21hTWM2Wi9TN0lFbmZaVmNIcXJFb0tqODlNZ1Nlc1ptWXZkVVVHa2U0cUdWeDFnNmUxUnFWU2hJR3F4MlB2M1cxeG1kdFBEVDF4ZXphRlp1Mi9xWnZtckd2TE15MXV1bzNpbm16NGo5amhOVGZqOVVaRWpySVM1TDZ4SkVZQWxhY3lIbFh5b0tSUmE0UGw0U1UyQTFXTzBZZk5vZG1hSVlMVHg1ZUNrV2l4bWp3VXROMlNndFM0OXl4L3hCeWI4a1RBdXFTbHg4OUo1VE9YK09YNTFZak1zNEsyTUhraHQ4a3pSWVkwZXdCc1pLS0M0aXJVUGEwL0tEZ2dnc1FjaUVZekdiVGZTT2xBYU9rNGt1c0Z4dXIyYXBHaFNEZ2FMaUl0NjE0amozTGUzRFpKUXBRVUhJTmc2WGlZR0phaFJqNWxhbHVOeGU1c1lSV0gwalpaaE1hWGQ3SXJDRXhFUy9GSUdRTGNmaVZVcm90Y1ZlYkZ0VE1RV3EvOGdMTFZCVkh3dXIrM2h3UlkrSUswSElFYytjbXNjNERSbTd2cy9yQVJWbXhjbUIxVHRTaWxjcEVZRWxpTUFTOUVWblcyc3ZrUExCWno1RENaZUdLbU0zU0VWbFpvVVRuMGViSTNOVW40L2Fpa21wUEVISUVTclFkYVVCakNVWnU0ZlA0MlJtaFJORG5NUGRMdzFWNFRPazlSeU9nQjhVQkJGWWd1WjBwL3BEbzhsQ2p5MytkdkZGczhid2FpU3dERVlUWndlc3FLb2lOU2NJT2VCa3p3eEdQYlVadllmWDQ2UngxbGpjNy9YWXlqQ210NE5Rb2xkQ3dzZ2FMQ0ZaVGdPM3BTUjJUQlpHYkJiY1hnUG1HTk4xUzJwSE9OS25YZFJwd0wyRS8vZXpFb3BNSG95S2l0bm93V3owVUdweFUxODFRVVAxT0RQTHBxaXRuTXhhTm5kQm1DNzg4dmhpM01aWkdiMkg0cDFrU2EwdDVuZmNYZ01qRGpQbFpXa0pMRG5qU1JDQkpXUnVRSnF5RXpRWUtUTER0ZUV5RnRXTVIvM2VncG5qNE5GT1lIa01GVXk2aWxBVUJiZlhpRSt4NEZVdE9IM0ZkUFdiVUF4UWFyUmp4a0dSMFVtSjJVVmwwU1RMWmcreHBIYUV1VFBzMCs2OFFFSFFnc0h4WW01TXpnUmpoaVBJbmtrV3pJeDkwUFcxNFRJc1pyOGZTb01UVXF1Q0NDd2hVNlMxMzl0c05uTjVxQ0ttd0pvL2N3S25TOFdzK2xBVWJXYXhaNVNNODM4ZmVoVlZWUmlmTWpNK1pXYkVVVVRQU0RuWGJKV01USmJnOUppd3U0cXdUVlhUNDVqUDBTRXpaV2NuS0ZMR0tMZE1NcnQ4bktZRi9heWFZOE5pa2tpWElNVGpmNDhzWVlLR2pLNUZVVlVmVHBmS3ZEZ0M2L0pRQldaejJ2dVRUMHV0Q2lLd2hFeHhNcDBmZXd4bGNRK2lMYlY0cUM1ejQzUTdNVm0wV1JockNIaDRSVkdwTEhGUldlS2l3V3BuZGNQd0xkKzEyWXU0Wml2ajdQV1pYQm1xWk14WnlxaXprbDdIQWw2L3NZcHk0ekFWbGdtVzFReHgzOUllNnFvYzBpb0VJWXdwdDVFTGd6VVlqSm50WnJ4dUo5Vmxia290bnJnQ3kyTW9KODA4OGllbFpnVVJXRUttT0FQNFNIV0RoTEdFODllcjQzNXRjZTBZeHdhbk5CTllUay9pMHdMV01pZldNaWRyNXI0cHZzYW56Snp0citidzFUb0d4aXNZYzFieTdLV0ZkRjViUnJscGxNV3pCbWxlZVVYRWxpQUVlUHJFQWthWlI2YTNsM2pkVXl5WkhYK0IrL25yMVNqRzRuUnU1VVBXWUFraXNJUk0wZG5XNnR6d3lPUG5nV1VwNlN0ekViM0RwZmhVSmVhVzZsVnpoamcrWUFlczJnZ3NieEVlbnlIbHRWUVZ4VzZhRnQ2Z2FlR05Od1RYNFNzMWRGMnBaOGhSd1dzOXF6alMxMGlsZVlSMUMzcDV5NHFyc21CZW1MWjRmUXF2WFo2TGtzSFVERUVVcjUyVjlVT3hsWkdxMEdzcnBXaEdVVHEzT3QvWjF1cVUyaFZFWUFtWjVQVlVCWmJCYUFaRm9YZWtOR2JXNWNhYU1YeHU3UmE2VDFESC8reGZ3Vy9mZllZaURkWlBWUlM3dVg5WkwvY3Y2OFduS3B6b21jR3paeFp3ZmFLYXA4N2N4VXZkalRSVUR2UCt0ZWZpWnBjV2hFTGpsZk56R1BQTnlVb2lJSjk3TXVicEVPQlBNSXFpK1AxUGVuNVBFRVJnQ1JrWFdBK24rdU9pSWpNWHJsZkZGQjRMWm83ajlhcjR2TzUwbmFMZkNSdktPWGo5TGs3L2ZBNFdveE9Ud1l2WjRBdWtpMUF4QnRKR21CUWZLQ29XbzQ4aWs1Y2lzNGZ5SWhkVnhVN0tpMTJVRjdtcExIRmhMWFc5c2REZG9LaXNtVHZFbXJsRHVEd0d1aTdYOHVMWitWd2VxZU0vbjV0RFRja2c3MTV6Z1RWem80K3luUjRqWDM5cEpiYkpNcGJWRHZQV2xWZVpVVFlsTFUzSU8xVGcyVE1MOFptcU1pK3V2RzY4WHRXLzh6Z0c1d2VxS0NwSzI0K0l3QkpFWUFsWkVWZ3A0ekdVYy81NkZROHNqNTRRMldoUVdURExRWjl6RWtPSk5pY1RGdnR1VUdSeEF3YThxZ0d2RjZiQ2dsbmo3a3E4SGkvVnhlUDRWQU51bnhHZmFzU3JHdkg0VEtpcWdrSHhVbVR5WUZMY0ZKbmNsSmhkV0VzY05NNGFZVkhOS0hjdkd1Q2V4ZjFjSHl2aHAwZVdjSEZvRmwvcjNNaU0xNGQ1MyszbldEdC84RmJSYWZMeXNYdlA4S1huNytDRlM3ZHo0Tm9TNmtxdjg5dDNuMlpPdFVUQWhEeHlEbGRtTWVhZERjYk0zOHZybW1UQkxFZmNnOXN2M0tqU1lvRzdDQ3hCQkphZ2I0RmxNSlZ3cGkvKzJxbzFEVGZvT1ZNSEpaV2FQSFNaeGNIZnZlZWxxUDgrTkZITXptZmVpc3M4Z3pzYXp2S0J1ODRETU9reU1UNWxac0pweHU0MDhiMkRheGd6cmtDeGQxTlQ3c0kyV1U2L281YUQvYVVVRzZjb01VNVFicG1pdXNUTzdYTnU4STdWRnpsNmJSYjdMODdubXdjMzhQTmp3L3pPM1NkWUhEYXRVVmJrNXMvZWNaQW5ENDJ3Ly9JU0xremV5ZWVmcitIMnVzdjh6dDJuNDNZaWdxQUhmbjVzS2E0TUp4WU40bk03dUgzeGpiamZPOU5ueFdCS2V6MllDQ3hCQkphUVdUcmJXdnMyUFBMNEFEQTdsZDhiemNVTTNDaG15bTJNdVJCODFSd2JUNStZME95NVhkNGlQRjVEMUVPZnovUlhZL2ZPUURHWDhkcVZlYng5OVNYS2lqeVVXUHlmV2lheE84MTRDZXhFS3E1bDdkeFhlYzhkRjdrK1ZzTFY0WExPRE15a2Y2eWNHM1lydmU3Yk9ENDhTYmxobUdMakJCVkZrNHdOKzdCNUxIejV4WHVZVjNXRGo5MXpBbXZabSt0bUZlQ0RkNTNuOW9ZYnRMMTZPelpsS1FmNlo5SDlpMm9lZSt1aG03NmIxRWpmcCtCd21hZ29ka3NERmpMR3lWNHJJKzdhekNjV0RkcUxaNEtWOWJFenVFKzZUQXlNRlZOZWs5WU93b0hPdHRZK3FXRWhxV0NDRklHUXFzNUsyU2thakpRVUtaenRyNDc1dmNXMVk3ZzhLajZ2UjVNSG52UlZjbWt3ZWc2dW96MnpJVERLSFdNaFAzaHQrUzNmdVRaY3hwVHFqNmlweG5JNkw4L0g1VEZRVitWZy9hTHJmR1RqS2Y3czdhOWhOcmhBVVZBTUpzeStFVkJWQnFicWNSVTM0clBNd3FjcW5CMWZ6Yi91M2NUUGppeTY1YXpFSmJOSCtjdDN2VXBqeVJHTWlvc0IzMnIrN2RjYnVUcFVudEs3ajA1YTJQbkx1K1JNUmlHalBIbDRPVTdEN0t6Y3krZjE0UEtvTEs2TnZjRDkzRUFWSlVWS3VobmNPNlYyQlJGWWd1NEZGZ0NtTXM3RUVWZ1drNWNGTSsxNFhkcmtsbklxMVJ5K0d0MzVEOW5MM3N3Y2I3UndkbkFPZ3hNM2ozcTdCNnR4ODZiSUdWVVg4T1RoSlRkOVo5aGVqSXZTZ0pvMFVWM200dS9mOXlLdHYvRXM5elVjWUthbEQ2UEpoR0lxWmR5NGxHY3VidUN6djlqSXdOak5VeGhsUlI3K3o5dTdlSERCUWNwODF4ZzFMdU8vWDFxWDBJSFo0Y3dvYzJKemxQRFU4UVhTY29XTWNHNmdpbUhYYkZDeUkrSzlMZ2NMWnRyam5xcHdwcjhhVEdYcDNrNEVsaUFDUzhnYXI2WHpZOVZVenJGcjhkZHBOQzBjUUhWck0wMW9NSm81ZTMxbXhIL3plQTNZM1RjTG5IRmxBZi9UdWZJV2dXVXdoU3k2TnhaenJMZUI4YWszLys3S2NCbVRQdjhPS3NWZ29IOXlEa2V2ekdMQnpIRitiOE5wL3ZxaGZWU1lSLzJkaE51SngxaEZ2KzgyL3VPWlRYU2NuSGZUL1JUZy9XdTcyYnJwVmF5KzA0eXdrQys5ME1UWVpQTExkVGN0N2VQcEU0dHd1R1JsZ0tBOVB6cTBIS2R4ZHRidXA3b25hRm80RVBkN3g2N05RaldWcDN1NzE2U0dCUkZZUXJZNGdIOUhka3FZekNWY0hTN0Y1WW5kQk5jMERPRjFhYmVMYnN4VmRVdFVDdURTWU1VYm91Z05jV013Y20yOG5pc2gwM0xqenVLQTdIbVRVV1VCZXc2K09aMTRkbUFtWHFYMGpmOTNHdXY0MGVzcjhQcjh2NXR5RzNFRXhGeUo5eHAxeXV0WTFYTk1Nb3RmbnIyYko1NjU4NVp5V1Z3Ym1ESXNQY2FFYnhaZmZtRnQwdE45NzE1ekVVVXg4cE93aUpzZ3BNdnB2bXF1VDlWbkxYb0Y0SFhadVgxdTdBU2pMbytCSzhPbG1NeHBMWEJYQS81T0VFUmdDWm1uczYxMWxEU09qVkNNSml4bWhiTUQxVEcvdDNEV0JFYkZoOWV0VFFMbENScDQ2dGlpVzBlNVBUVTR1VFZ2ajhQUXdQOTBybjdqLysydVc4V1pZckJ3YnJDZW9ZQnd1MmFydk9YOHRWSGZmSDUrdEJHQXk0TVZUS3IrZXpuTkM1aFZNY25mdi9jRlByem1CVXFWRzV3ZVc4Mi9QTFhoamVzRktTdnk4S2R2NzJMemtzTmNIcXlnNDlTOHBONjlxdFRGM09wUmp2WFdKM1Ywa0NERTQwZUhWdURLWXZUSzYzWmlWSHdzaUhQQTg5bUJhb3JNQ2twNjV5R2VDZmc3UVJDQkpXU05GOVA1c1dLdTROalZHYkcvbzZqY050ZUd4NmxORkVzeG1qZzlNSnNwOTgwQ28zdlFpc0ZraVhCL0E0T3VlbzVlbmNuNGxCbVhML0pSRytQS0FyNTNZRVZVRWVZMVZ0QjVhUUhqVTJaTzlzM0NyVlM4OFR6ZHRqbjBqWmF5YVVrZmYvbk9mY3d3WE9XNjd6WSt0M2RqeElPeDMzUDdSZjc4SGEreC8wTHRHMUd4UkhsdzJXWEdYSlU4ZjJhdXRGNUJFMTYvTW90QlYzYWpWeDZublRYemhsR1UyRUgwWTFkbm9KZ3JjdXJuQkJGWWdwQUtMNlgxYTNNRnIxK3RqZnUxRFkxOUdEemFEU0JIbWM5UFgxOTg4OTlOUlo5Q2NCcHIrZkhoNVZ3ZExyOWxHdkVOSVdZd2NtV3NqcXZENVRqY1JWSHV1NGp2N0YvRnhhSHFtN0xUMnczeitNNStmNVNzck1oRGJjVVlpc0hBdUhFWlgzcnhiazcyM2lwQ0Y5V004YWZ2ZUozSkpOZFQzVDV2aU9yaWNib3V6NUhXSzZTTkN2enZrV1c0VFRYWjdiZzhvOXk5cUQrKytMdGFDK2tMckpla3BnVVJXRUplQ1N5anBZU0IwZUtiRm9oSFlzM2NZWnhPRDZwUG84T1RqU1VjN3BuL3hsb3NtNk1JcHhwcmw1SENpRzh1MzNwMU5SNUQ5TVd5ZG1VZW4rOW9Za3FKdkhoZk1acTRPREtISVh2cHpYK3ZHTGp1Yk9EUVpYOG41UXV1clZJVTdLWWx0SFd1NC9pMVd4Zm5sMW84bENlWjE4cGk4bEpoY1REbUtyOGxpaWNJeWJML1FoMGozam1FcjB2TXFLanplWEU2UGF5Wk94enplK05UWnZwSGl6RmEwazR3S2dKTEVJRWxaSmZPdHRiTHdPVlVmNjhvQmtwTGpCeTlPalBtOTBvdEhoYlcyRFdiSmdRWVV4YnkxWmR1UjFVVnp2YjVFNHpHd21PME1tRlpIZk5jUk1WZ3dGbXlBcmVoT3VwM0hJWjVqTGh2SGUyN2pMWDg1UFhsZUgwS1kySFJOSWRwRWQ5KzdjNllPYnlTb2I1cURMdTNpZ3ZYSzZVUkN5bmo4Um40NWZHbHVJMHpzM3RmcDUyRk5YWktMYkh6NHgyOU9wT3lFdU9icVZkUzQzTEF6d21DQ0N3aDY3eWNsck0wVnROMU9mNDA0YVlsUGVBYTBleWhGWU9SZm1jajdRZVhjclJuTnFxcE5EdWxwU2dveFpFalhDUHFQTDYxYndVVG5sdUZqOTNZeUZkZlhxdEppb1ZsdFVPNHZVWXVEMWRKNnhWUzVoZEhGektpenMvK2pWMGpiRnJhRS9kckJ5L1Y0akZXNTlTL0NTS3dCQ0VkOXFielkxTlJPVWV2em9pN1dIdmRvaHM0cDV6YVRSTUNIbU1WblQzTE9UTlFuZTRvVnhOOHhrcU85RFl3b2RaSEZHWWp5aExhOXExTyt6NzExUTVLVEU1dWpKZEo2eFZTd3VFeTBYbHBBYXF4UEt2M1ZYMWVuRk5PMWkyTWZmNmcxNmR3N05vTVRFVnBQOTllcVcxQkJKYVFLenJTYW9BbUN3YURJZTZ4T2RaU0ozTm5PalNkSmdSd0d1ZmdNQzdTVFdHNml4YWhSSnVHTkZpNE5ES0h2cEgwb20ybFJSNk1paHM1T2xwSWxlOGZXTUVvQzdOK1g0L1R6dHlaRHF5bHNkTzJuTzJ2eG1Bd1JOd1puRTMvSm9qQUVvU1U2V3hyN1FGT3BkVUlMUlZ2TFBDT3hmMUxlMUJkMnFlak1aaUxkVk9laWlHMlNkcVZCbjUyTkwxRW9hVm1EejZ2bTFLelJ4cXdrRFI5STZXY0dXeEFNVnF5Zm0vVk5jcjlDVXdQSHJwY2c4R1M5cHJGVXdIL0pnZ2lzSVNja1Y0WTNWTEpxeGZxNGtaVU5qUU80SEpPYVRwTm1HOG9CaU85bzlWcFhjUGxOZUQyS05SVTJLWGxDa256clZkdlk4S1EvYlZYcXMrTHl6bkZoc2JZeCtPb3dLc1g2c0NTOWhwRG1SNFVSR0FKK1Myd1RKWlNwanltdUx2YXFrcGRMSzRkeHowMVh2Z2xxa2FYbTVPK2tyUVd1enRjSm55cXdzeXlTV201UWxMc3YxQkgvOVM4bkt4WmRFK05zN2gybktwU1Y4enZYYmhleVpUSGhDbjk5QXdpc0FRUldFTE9lUmFZU3VjQzV1SXl1aTdGMzAzNHRwVlh3V1diRm9XcVRsd0Vyek9DOWpMamNLWXVzRzZNbDREcVkzYVZRMXF1a0RCVGJpTS9PN1ljdDJsV2JoN0FaZlBiZnh5Nkx0WmlMazU3QThjVThJelV1aUFDUzhncG5XMnRqb0RJU2wxTW1LdlpkNzQrN2pUaFhRdHU0SEc3OFhsY2hWMm9pa0pWc1l1VlZZY3A4ZmJlL0U5NHNaaDhLVi82ZFA4c2lzMWVhaXFtcFBFS0NmTS9uU3NaSVRjYlFud2VGeDYzbTdzV3hONDlxQUw3THRTam1xdlRIalIydHJWS2lGY1FnU1hvZ3ArbDgyT1RwUVM3eTh5RmdkanJKb3JOWHRZdnVvRjdzdkRQWG5Vd2s3ZXV1TUxIMXUyajJuY1NOUkROTWhzbXFTeEpYV0JlR2E3Q1d1YkVvTWcrUWlFeHVxOVhjV1p3SG9xeEtDZjNkMCtPc243UkRZck5zZGRmWGhpb3d1NHlZN0trbmRmdVoxTHJnZ2dzUVMvOElyMmZLNWlLSzNqNVhGM2NiemF2dW9yUE9SSnpuVkloNERiTzRJV3o4MWd6ZDRpL2ZtZ2ZhNnlIS1BMMk1iTmtJdVZyT2oxR1JwM2xsSm9sZWlVa2hzZHJvRzMvR2h5R2VibDVBRlhGNXh4aDg2cjQwNE12bjZ2RFZLekppUWUva0pvWFJHQUp1cUN6cmZVcThIcGFFc3RTemFzWDZ1SW1IVjA2ZTVUS0VoZHVaMkh0Z2xQVm02ZjlGTVZBNzFnMUt2N0kzVnpyT0lyUFJmUEtpeW5mNDBEM2JFYmNNNWxuSFpOR0t5VEVkL2F2d09aYkJJcVNrL3U3blhZcVMxd3NtUjA3YXUzMUtleTdVSTlpcVU3M2xvY0Qva3dRMHNJa1JTQm95SStCdGFuKzJHZ3V4cWVZT0hwdEpuZk9INHo1M1hlc3ZzS1BqNVJEY1hsQkZKelA0MkNXY280cHRScUhjZjRibmRtRWR3YVhibFJnTnZsNDZjSVNxaXlqckprN2xQSjlYamkzQUtOQllVWGRZT0lkbk5mQXFNT0N3MlZpeW0zQ3F5cTRQQVlzSmg4R1ZFcUxQRlFXdTZnb2NXczY3ZGgxcVlhMTh3Y3hHbVFxTTFlYzZyTnk0c1lpVkdOcHpwNUJkUTd4amp1dXhQM2UwV3N6VVJRanh2VHoyajBwTlMrSXdCTDBSanZ3RDJsZHdXTGx1Vk56NHdxcys1ZjNzdWUxeFpnOExpMnlOZWNjeFZERS9CbDIzckg2T045NFpRMUQzb1Y0alpVNGxWbDBuRjdBTlZzVlBveDhaT1B4bE85eHVxOGFtN3VHVXNNbzgyZmVQTTNvVXhYNlJrcTVjTDJhQ3plc0REbEttSFFYNGZTYThmak0rRERqeFlKSE5hRmlRRkVVVkZYRmdJcEpjV0pVWENpcW0yS1RpMUt6azRxaUtkWTBYR2RaM1FpMUZhbXRGZTRiTGVQYWtRcmVmMmUzV0ZZT21KZ3k4eitkYTVnMHpzM2h3TU9GeCtYay91VzljYi83M0ttNVlMRnE1Y2NFUVFTV29CODYyMXBQYjNqazhlUEFiU2szeUpJcWpsMnpNanBwb1NyR1F1NVNpNGQ3RmwvblFFOFZSUld6QzBCZ0dibGlzekxYZXB5L2ZzOStmbjVrZ0gyWEZqR3VMT0o0ejJ3TVJaWGNOLzg0aTJhbGxnTk1CWDU0YUNWT1F4MWxuQUhnNEtVYURsK3Q0OFpFT1haWENWTnFPWk5xTllxeDZNMDhSd3Bnak5FQkFxSDU0Q2RVd0FVNFZZNE5UMUorWXBoaXd6aDFGV1Bjcy9nYWErWU9ZeklrdGdQeW5zWDliUC9oUnQ2eTRscGFpL3FGRklTTnF2QmZ6NjFsUkZtYTArZHdUOXE0WjhrQXBaYllwdzZNT2l3Y3UyYWxkRmJheVVXUGQ3YTFucFlXSUlqQUV2VElqOU1SV0lyQlJIRkpFUytmcmVmZGQxeU8rZDJIYnIvRXZ2T3pzWlRYNk9LdzVvVEZqcXFpd0MxcldzWjlzemd6VU1XS3VoSGV0N2FiZTVmMDh0bWZlL0NZNTdLNDhpUWZiRHFYOGoyZlBUV1BRZmRjTUNwTXVFcjQ1NmZmaXQwM0E5VlU1aSs3UVBGcFZvcUtnc0ZjaW9OU0hNRFF1SS9UWGN1b1BIeWQrZFpoM3JtNis1WW9Xamd6eTZlWU8yT0tiKzVieFdOdmUxMHNLNHQ4NTlVVjlMcVdnc0dVUXp2eDRaa2M0NkUxbCtOKzkrVno5UlNYRktHay83dy9rdG9YdEVJV3VRdGE4NE8wSGF0bEZoMG41OFhOaWRWZ3RiT29aaHkzSTc5U05wUzV6bENqSE1mb3ZYbWh1Y3N3azJkT0xYemovMy82K21Jb3FxR2g1QngvOUpZanBMckVlTmhlUk1lWnBYaU1NL3ozc1N6QWJsd0E1b3FzQ1ZORk1lQXpXUmt4TE9lSTdXNGVmK2xCL3VXcERaem9tUkh6ZHg5YWQ1YmpQVE01RStjd2NFRTduajZ4Z0NQWGwrTTFWT1QwT2R5T1VSYlZqTk5namIyWlJRVy92N0Jva2dEMUI5SUNCQkZZZ2k3cGJHczlDUnhPNXhxbW9sSW1uQlpPOXNSZlQvSEJ1eTdnbXhyS3E1UU5ScE9KUDkzOEdzMkw5bFBoUGZmRzJZcUtZcUIvdkJxdlQrR0hYVXM1TnJpTWFtTXZuMmsrbFBDMFdqaGVuOEtYbnIrVE1hVlJOKyt2R0l4TUdSdm9jZC9CMTE1N2dNLytZaU1YYmtRK0ptbjFuR0htemJUenJWZHZpN3U3VkVpZlE1ZHI2VGk3R3FjeHg5UHVxb3B2YW9nUE5sMkkrOVdUUFZZbW5CWk1SV2t2eEQvYzJkWjZTbHFCSUFKTDBEUGZTYk1MeGxCczVhbGpDK0orODdhNXcxaExwL0xxZk1JeHRZSG56OHpsdlhkY1pOdmJYMlpKNlNHS1BQMEFqSHRuOGVYbmJ1UFZxeXNwVXdiNTQrYURjZGVmeE9Kckw5L0dkZmNTRklOUmZ3V2hLTGlNdGZSN2IrZkxMOS9QNDgvY3lhamoxZzBMSDlsd2dqRm5LZi9UdVVJc0s0T2NHNmppQjRmdVlOSTBMK2ZQNHA0YXgxbzZ4VzBOdzNHLys5U3hCUmlLclVEYUF2dzcwZ29FRVZpQzN2a2UvdlhQS1dNcXNYS2l4OHJnZVB3dDF4KzQ2d0sreVVIZHZMenE4Nko2b3AvenA1aEtPSGhsRGdEVnBTNytaUE1oUHJidUZheStrM2dvNXF4dE1XWjFuRTg5MkVWMWFlcUx1OXNQTHVYMDhESjh4ako5dHhaRlljclV3Tm1KSm5iKytsNWVPVjkvMHo4dm5EWE82dnArWHJ1eWtJTWg1MVZlSFM1bjBpWExTTFhnbXEyTXIrMXJ3bTdTUjZUVE56bklCKzZLSDcwYUhDL21SSThWVTBuYXV3ZDlBYjhsQ0NLd0JQM1MyZGJhUjVvSHBTb0dJOFdscFhTY2pMOUZmRVBqQUNWbS9VU3hGTVdBZWVxU2YvclBHem42Tk9hWnhibVFZNEh1bURmSWgrNDZSWkZ2a0dLam5UKzg5eEQxYVJ6Ry9LdmpDOWgvYlJVdTQ2ejhhVGdHSTJQRzVmencrRDE4dnVOT3B0eHZSdDArZnM5SktpeDI5blRkeHZYeEVteU9JaDd2dUoyU05LSjdncCtCc1JLKzlNSTZKb3hMZFBFODdxbHhTc3hUYkdnY2lQdmR2U2ZuVWx4YXFrV0U5cG1BM3hJRUVWaUM3dmxHMmxjb21zVXpwK2JlMU5GR3dtaFErZEM2OC9nY04vVHg1b3BDVFpXWHYzekh5Nnl1T2tpSjkrb3RhOFNjeGxxZU9yNzRqZisvT2x6T2R3L2VqdEdvOE9HN2pzVE5XaDJMcDQ0dHBPUDhHcHpHdXJ4c09HNWpEZWNuMXZMUFQ5MUQ3NGcvK2xaaThmQ3hqY2Z3cUdiKzY3bTd1REpVams5VjhQakVoYVhEc0wySUx6NjNqbEhEc3B4bGFnL0g1N2pCaDlhZGo1dGdkc3B0NU5sVGM2Rm9sajc4bFNDSXdCS3l4SThCV3pvWE1KcUxNWmt0UEg5NlR0enZibHJTVDRuSmlXZHFRaGN2UCs0cXcyVDA4VWR2T2NML3QrbGxaaHVPWWZZT2gyZ3dBMzNqVmh3dUU0TVR4WHo1eFNZOFNnWE5TMC9RdE9CNld1THFtUXUzTVdWc3lPL1dZN1F3eENvZWYyNGpoeTc3cHdWWDFOdDR5OUt6MkZ3ejJYdHlJUmpNZk83cEpsd2VvMWhiQ294Tld2aDh4M3FHbFJXNlNYUGltWnFneE9SazA1TCt1Tjk5L25RREpyTkZpOHp0d3dGL0pRZ2lzQVQ5MDluVzZnUytuZTUxMUtKYWZuNWtVZHdkWk1Fb2x0ZHhYUmZ2UDZIV3ZDRU1HbXZHK092M3ZNcjdWcnhLbGU4MHF0ZC8wUEtZMnNCUFgxL0U0OCtzdzBFTjYrYWM1dTJycjZSOHovYURTM21tKzQ3OEYxZHZpRkNGQ2RNU3ZuKzRpV2RPK1JkZXYvZU9pMnlZZTVZcm83UHhHcXU0TVZITzMvOTBQUk5UWmpHNlpBWUFVMlkrdC9kdWhsaWhxeHh5WHNkMVByVHVYTnpvbGRlbjhQTWpDMUdMYXJXNDdYY0Mva29RUkdBSmVjTlgwNzJBcWFnTXQycW1zenYrdHZGTlMvc29zMHpobnRUQlFjYW1DbDQ2LytadUxBVjR5NHByL00xREwzTjM3V3VVZVMrQnNZaDkzUXV4ZWVleHJPb2N2M1AzbWRSRXFLcncxWmR1NDlWcnR6TmxxQ3U0UnVRd3p1ZXBNMnQ1OHJCL1N2WDNOcDVtOC9MVGxCakdtVnM5eHR0WFgrVWZmcmFlWVh1UldGeUM0dXJmOTY1blNGMmhxOTJsN3NreHlpeVRiRm9hUDNyVjJUMGJ0MnJHVkZTbUN6OGxDQ0t3aEt6UzJkWjZETmlmOW9XS2F2bHhWeU9xR2orSzlYc2J6K0IxM05CRlhpeWJjd1o5SXpmbjVpazJlL240dlNmNTR3ZGZ3dVE0aDY5NEx2Tkt6L1BKQjQrbWRBK1B6OEFYbnJtVFk4TnI4bXRCZTVKTUdlZnc4dVhiK09rUi95NjM5OTdSemQrKyt3VzJQbkNFQjViMzhMc2J6L0pQUDE5M1Mza0x0NHFyLzl5N25rSGZLbjJsN2xCVnZJNGIvTjdHczNHalY2cXE4T091UnRBbWVyVS80S2NFUVFTV2tIZDhNZDBMbUVzcUdIT1cwTmtkMzZHdVczU2RXZVYyWEpPNXorNXVWK2J5M1FNckkvN2JMNDh2UWkycXA4WjRtczgwSDhLZ0pDOElwOXhHL3UzcGRWeXdyOFpycUN6NGh1UTAxdkhpeGR0NDZ0akNOOFJxTUVmWTJubURmT3F0eC9qYzAzZHlmcUJLckM2S3VQcmNyKy9tdW04VjZDd3Ztc3N4eXF4eU8rc1d4Wi9pNyt5dVpjeFpncmxFazB6elQwakxFRVJnQ2ZsS081RG13aWdGcGJpV0h4NWNIRGVLcFFBZjMzUWFqLzNHR3huU2M0VmlNTkRuYU9EUTVacWIvdjZaVS9NNGNXTUpsY28xL3JpNWl5SlQ4cytwcWdxZjc3aUxYdGNxVk1QMGlkcE1HZXQ1NXNJYW5qdDlhekxNeHBveC91SmRoOWo5NG1wZXZ6cExMQytFWVhzUi8vYjBCZ2JWbGJvVFY2clBpOGR4ZzQ5dk9oMDNWYWlxS3Z6dzRHS1U0bG8wU0N4NkhmaWh0QTVCQkphUWwzUzJ0YnFBLzA3M09zRW9WdGZsK0Izbnlub2JLK2ZZY05tSGRDRUlmbmg0RmJiQStxRHpBMVU4ZlhvVlJZenhxYmQwVVZXU1dpTFJ6dTdaRERnWG9CcW0zN3FqS2VNY2ZubnFOZzVjdkhWZDN1ektTZjdtdmEveFpGY2pyNXg3TTJHcDE2ZndEeis5bTRzM0txZGRlUTNiaS9qQ00rdjlDOXAxbU5IZlpSOWk1UndiSyt2amJ6bytlR21XbHRHci93NzRKMEVRZ1NYa0xidUJORE5DK3FOWTMrOWNtdENaZEIvZmRCclA1Q2crVCs3OTU2aXlsQzg4MjBUZlNDbGYzN2NXZ0VmdWVUMnRSS0lITDlmak5zNll0ZzFxMGpTZjl0ZlhjdXphekZ2K3JhTFl6Vis5cDR2T2k3WDg2dmg4QUo0L001ZEJieVAvL2ZKR2ZuMWl3YlFwcDRHeEVqNzM2dzBNc2xLWDRzcm5jZUdaSE9Yam0wN0gvYTdYcC9DREEwdTFpbDY1Z1YzaW1nVVJXRUplMDluVzJnTjhQOTNybUVzcUdYZVc4TXE1K0R2bGFpc21hVjU5RGZkRWY4N2ZYekVZdWVGZHliLytlaU4ydFpZSGw1eGhlVjFhS2NKd2U0MWFkREo1THJJVzhwM1g3dVI0QkpGbE1YbjVrODFIR1hWWStPSEJScDQ1dlJDUFVzcVlPb2Rmbkw2VC8zcHVMUzVQWWJ1L3E4UGxmUDZaRFl3YTlaV0s0YVoyUE5GUDgrcHIxRlpNeHYzdUsrZnFHSGVXWUM3UkpBcjVnODYyMWw3eHpvSUlMS0VRK0RkTnhFcEpIWHRlVzRMYkc3L3BmbWpkQmN3NGRIR0VqbUkwNFM1WnlneHpEKzlhYzBrRDBhWktpd0xzcHNWODg4Q2RuT3E5OVN3NlJWSDU4TjNubVQ5amdxVTF3N3h6NFF1MHJIeUcyU1Y5bkJwZXpqLy9jaVBYeDBvS3Nsek85RmZ6eGVmdlp0eTRERVhScHhCM1Q0MWp4c0dIMXNVL2M5RGxNYkRudFNVb0pacWxJZmxYc1I1QkJKWlFFSFMydFI0RmZwWHVkVXpGNVhnb3B1TkUvRE1LaTB4ZUhyM3ZKSjZKQVZUVmwvTXlVSDFlbHRUYXBubmNTWHNtell2NVJtY1Q1d2FxSS83NzNZM1hlZlMrRTd4djdRWGV1dklxZi9HTzEyaXNQTWV3Yno3LytjdzlFZGR5QVhFM1ZPaVZ3MWRxK1BxcjY3Q2JsK3JtK0p0Ynk5YUhaMktBUis4N21kQW1qMmRPenNWRE1hYmljaTF1L3l0SnpTQ0l3QklLamM5cGNSR2xwSjRmSDJwa1BJSHMzZXNYM2FDeFpoVFh4R0RPWDE1UkRGd1pxa1NMMkpQTFk1TFdGSUxEdEppdjdGdkg4Wjc0NjlKTVJoOS8zSHlZTzJjZHc2bFVzZWZJM1h6NzFaWDR3Z1RWTTZmbThxKy9Xcy9nUkhIZWxNTUxaeHI0YmxjVGR0TmlYVCtuYTJLUXhwcFIxaStLZjM3bytKU1pIeDlxUkNtcDE1VWZFZ1FSV0lKdTZHeHJmUWJvVFBjNlJrc0pKa3NwN2E4bDFvbHNlZUFFdnFrUnZPNnBYQ3NzK2wyTCtQZW4xNlhkYVR2Y0ZtbFFFVVRXdHcvY0ZYRk4xaTJPVDFGNTlMNFR2SHY1UVl6cUZLLzFyMlhuVStzWm0zeXpYQTllbnNPbHFUWDhlOGQ5N0hsdEdSNnZ2dDNsajdxVzh0TlRkekZwMHZjaWZxOTdDdC9VQ0ZzZU9KSFE5OXRmVzR6UlVvclJvc2wwYm1mQUR3bUNDQ3loNFBnN1RiUkthUjB2bjZ2bjZuRDhLWU9haWtsYTFsL0FQZDZiOHd6dlhtTVZGNmZXOHJtTysvbmNyOWR4K0VwTlFyc2lReGwxV0pqMGxFbExpb0RkdEpodnZkYkU0Y3VKWmZsKzI4cXJ0RDY0ajVtbXkvUk9MV1RuMC9kd3RyOGF1OVBNbUt1U0t2VWlSY1pKWHJxNGxMLzkyU1pldjZLLy9GcSt3RkZKcjF5OUhhZHhqcjRyU0ZWeGovZlNzdjRDTlFrc2JMODZYTTdMNStveGxOYnB5djhJUWtMOWxLcktZdG1Dcm1BZHJzSFk4TWpqaDRHMTZWN0g0N2hPUStsVi91YTlCeFB3NndwLzgrUUdyanNic0pUcnBKTlVWWXplRVNvTTEybW9zckY1MVVXVzFNWS9SL0dGTXcyMG4zZ1F6T1hTd0tOUTZybkViNjQ1eHIxTEV0c281dlVwL1BMWVF2WmRYSWg5eWtSOWhZMnJVMHRaTi9zWWo5NTNuT1BYWnZLTFkwdTRjTDJNNVhXai9Oazd1blR4bmk2UGtTOCt0NWJMam1WNWtjM2ZOVEZJYlZFUC8vaUJUcFFFVGkvNHg1K3RvOGN4RDFPcEpzZmlIT3BzYTIzU24rYVVQcmhRa1lVY1FpNzRlK0RKZEM5aUxLbmh5dkFvKzg3WGNlK1MvamhDVStWVGJ6M0tYLzI0QkdOUk9VYXpEdGJWS0FwZWs1VVJyTmhHZlp4N1pSRVZ4aUVXenJUeHdMSXJMS29aaTdnZy90WHVCaEZYY1hDWUZ2S1Q0MFljTGhQTnE2N0ViMHNHbGZmZWNaSE5xNjd3OHlPTlBIK21nV0xMZGQ2MXBoc0ZXRE4zaURWemgrZ2JMZVZDbE1YMDJXYlVZZUVMenpSeDNiY01EUHBmSitaMVQrR1pIT1pUN3pxYWtMamFkNzZPSzhPVldLdzFXajNDUDRwbENDS3doRUxuZjRIRHdKM3A2Uk1GWTlrY3Z2MnFoN1h6Qjk4NGx5NGE5ZFVPSGw1L2dSOGVNbUt3THRKVmJpREZZTUJsbU0wUXN4a2M5SEw4eGhMS0RNUE1MSnRnL2NKZWx0U09NanhSeEMrUEwyYlFOVmNtOXhNUldjWjVQSDNXaU1ObDVuMXJMeVQwbTJLemx3K3RPOGR2clR2SDFhSHlXNUxCMWxjNTBrb1FxeFZYaHN2WjllSmRqQ2pMZEpsQU5CeFY5ZUVlNytIaDlSZW9yNDVmZmc2WGlXL3ZXNDZ4Ykk1V1VmakRBYjhqQ05uejZ4S2VMUEFLMXVrMjdRMlBQUDUyNEdrdHJ1VVp1OHc5Q3kveThVMW40anQ2NEI5L3VwNnJFdzBVVmN6V2Z3V3FLbmduS0ZIR2NLa2xlSXpWdWswYXFWZUt2TmU1cSs0VXY3ZnhkRUc4ejhGTHRldzVkRHNPVTZOdTB6Q0U0eHdmWUY1NUQzL3p2dGNTU2xQeXpWZVc4K3FsUmt5Vjg3VjZoSGQwdHJYK1dwOG1MbjF3b1NLZVdzZ0pBV2YzdkNhTnVHd09MNXlady9tQnF2aUNFL2owMjQ2Q2F3U1AwNTRQQ2hsTUZVd2FHL0NhWm9pNFNxVnpOOWJ5V3YvdC9QZnp0OStTaWlHZlVJSDJnMHY1L3VIMU9NeUw4MFpjZWFZbXdEWENwOTkyTkNGeGRYNmdpaGZPek1GUXBsbGFodWYxS3E0RUVWaUNrQ20yYTlLSWpXWXM1VFY4K2ZuYkV0cEtQNlBNeWRZSFQrQWE2OFhuOVVndFRBTThSaXVuUm0vajh4MTM0Zkhsbjl1YmNodjUvTjY3Mk5kekoxT211WG56M0Q2dkI5ZDRIMXNmUE1HTU1tZjhldklhK1BMenQyRXByOEZnTk92S3p3aUNDQ3doYitoc2ErMUVnOFh1QUtZU0szWjNHVThlV3BUUTk5Y3R2TUY5eS9wd2ovY0VZZ05Db2VNMVZIREp2cHAvKzlVNkpsMzVzL3gwWUt5RWYvcmxSczdiYjhkdHNPWlJpYXU0eDN1NGIxa2Y2eGJlU09nWFR4NWFoTjFkaHFsRXMvZDhNdUJuQkVFRWxqRHQrQXY4Sjl1bjM1akxHbmpxMkh3dURWWWs5UDJQM1hNR2EvRVl6dkZCcVlWcGdzOVlRbzk3TmYvMjlQcUVUZ0xJTmZ1NzYvajNqbnNaVmxhaEdJdnlxcXlkNDRQTUtCN2pZL2VjU2VqN2x3WXJlT3JZZkF4bERWbzlnanZnWHdSQkJKWXcvZWhzYXowUGZFR1R4bXl5WUNtYnhSZWZXWlBRWWRBbW80OC9lK2RoY05sd1QwMUlaVXdicjJmaHVtODEvL3IwQmdiSDlabmV3T016OFBXWFYvUERvK3R4bUpmazNkbzc5OVFFdUd6ODZUc1BZekxHUHdmVTdUWHd4RE8zWXltYmhjR2syU2tGWHdqNEYwRVFnU1ZNV3o0TDNORGlRcWJTR1V5NHkvbEI1NUtFdmw5Yk1jbW4zbm9VOTNnZlBvOUxhbUxhZUQ0anc4cEsvdk9aRFFtZEJwQk5ib3lYOEUrLzJNanJnM2N5cGZmTTdCSHdlVnk0eC92NDlOdU9VcHRBdG5hQTczY3U4VThObHM3UXJCZ0Rma1VRUkdBSjA1Zk90dFpSNEc4MWE5VGxjM251ZEFNbmVoSmJ4N0YyL2hEdlduTVoxOWcxVk5VbkZUSk5VQlFEbzRibGZQR0Z1em5kcDQrMVRjK2Ruc2UvN2QzRWRkOXFmTWI4T3c1SlZYMjR4cTd4cmpXWHVXUGVVRUsvT2RGajVmblREUmpLTlYyOC96Y0J2eUlJSXJDRWFjOHVRSlB6Und4R002YUtPdjdyMlRVM0hkNGJpdyt0djhDeTJpRmNZejFTRTlOTFpXRTNMZVViKzlmejJzWGM1VVVibnpMekgzdWIrT25wdTNHWUY2TVk4dE0xdTBaN1dENTdrQSt0VHl5eDY5aWtoZjk2ZGcybWlqb3RkdzEyQVYrUnhpMkl3QklFb0xPdDFRZDhFbzIyOUptTEsvR1pLdm5TYzdjbGRFRUZhRzArUXJWbEZOZkVEYW1RYVliZHRJZzlSNXJZZTNKKzF1Lzkyc1haN1BqVnZWeHczSUhiT0N0dnk5QTFjWVBxb2hFZVN6RGZsUXArK3pSVllpN1c3QnhGRmZoa3dKOElnZ2dzUVFpSXJJUEFmMnQxUFdOWlBkMkRWcDQ2bWxpbldXejJzdTJoTGhUWE1DNkh6QzVNTnlhTjgvalYyYlcwSDF5YWxmc04yNHY0ejcxMzhmMGpHeGsxcmtBeG1QTzI3RnlPVVJUWE1Oc2VPa1N4Mlp2UWI1NDZPcC91UWF1V0NVVUIvanZnUndSQkJKWWdoUEZYYUxUZ1hWRU1HTXZuOGNPRGl6bVhRSlozZ0ZubFUvejV1dzdoc1Eva1I2WjNRVk9jeG5yMjlkekpFOCt1VFNocGJTcDRmUW8vTzdLSXozVnM0b0xqTHB6R3Vyd3VNNC9UanNjK3dKKy82eEN6eXFjUytzMjVnU3ArZUhBeHh2SjVXdTZRdkI3d0g0S2dDK1Fzd2tLdllDWC9qZ2JaOE1qakR3TS8wS3dEbUJ6RjRPemxYMzVyUDFXbGllMFVQSGlwaGk4OXU0YWk2dmtZelVYU2tLYWIzWGducVRXZDQ1TVB2RTVOZ2p2aEV1SHc1UnIrOStneWJMNzVlQTJWZVY5T1hyY1Q1OGdWL3VpdHh4Sk9KanJxc1BDWFA5cUlyMmdPcHBJcUxSL240YzYyMXZaOEswUHBnMFZnQ1NLd3NpMnlmZ0s4WHpPUk5kRkxmV2svZi8zZWd4Z05pYlg1WHgyYlQvdkJwUlJaRjJpNUFGZkltNDdQUjRYM0F1OWJjNHA3bC9TbGRhMnpBMVg4Nk5BS2hsejFUQmxtRjBUNStMeHVuTGJMUEx6K0xPKzQ3V3BpZ3N5bjhObWZyYVBQVVllcFhOTVVGUC9iMmRiNm0vblp6cVFQTGxSTVVnU0NUdmtqNEVGQWt5R3VxYXllM3RFcHZydC9LUis5OTJ4Q3Yzbm5taXVNVGhheDk2UkNrWFVCaWtITVpYb05UZ3hNbUpieTQyTWxxQnhtMDVMZXBLOXh2R2NtUHorMmhNR3BXcVlNOVdCUUNxSnNWSzhIMThnVjNyNzZTc0xpQ3VDNys1ZlNPMWFOdVVyVGRWZWp3UDhuTFZiUW5ROFI5VnpvblVUK092UU5qenorS1BCMTdVYmNIbHdqRi9uSXh0TTh1Q0x4enZJckw2em13S1U1V0tvWDV1MzJlU0U5U3IxWHVIL1JhZDU5K3lVVUpiYlB0RG1LZVA3TVhJNzIxRFBxcWNWbG1BV0tVakJsb2ZwOHVFWXVjZmZDWGo3eHdJbUVmL2Y4NlRsOFovOEtMTldMTUJnMUhhejhmbWRiNnpmeXRqeWxEeGFCSllqQXlwSEkraG53SHEydTUzVlA0Unk1d3JaM0hXWjUvVWhpd2t4VitNTGUyem5aWDRlbGVuN2VIVnNpYUlQSk8wS2xvWWUxYy90WjAzQ0RxbElYWnFNUGg5TkU3MGc1UjN0cTZCK3JaTnhkeVpoYWg4RlllR3YzVk5XSGErUUtxK3I2K2N6bW94aVV4UHFQTTMzVjdIenF6c0NhUmsyUEovcDVaMXZyZS9PN1RLVVBGb0VsaU1ES2pjQ2FEUndITkVzUTVKa2FRM1gwOHRrUEhraDRBYlBIWitEZmY3V1djNE8xRkZYUEU1RTFqZkY1WEJReGhna25Cb01QdDJyQjZTc0hVMGxCdHd0VjllRWN1Y3JTbXV2ODZUdGV4MlJJTE5YVWpmRVMvdnJIZDZPVXpzRlVyT25DL2tIZ3RzNjIxZ0VSV0lJSUxFRUVWbW9pNndQQWo3Vzhwc2MrUUJrMytJY1BIS0NzeUoyRXlMcVRDME8xbUt2bUZVVFpDa0tpSXNBOWVwWEZNNi83RDNCT1VGeE5USm41ZnorNUd3YzFtTW8wWDl6L3djNjIxaWNMb1d5RndrU0c0WUx1Q1RqUnIydDVUVlBaYk95K2F2N3RWMnR4SjVqdnlHVHc4YWZ2UE15ODZrSGNvMWZsM0VKaG1vZ3JIKzdScTh5dnZwR1V1SEo3RFh6dTZiVTRmTldaRUZkZkx3UnhKWWpBRWdROTBBcWMxbFJrbFRmUVB6NkRMejE3RzZxYVdEVEtaUER4bCsvdVl2SE02emhIUkdRSmhTK3VuQ1AreU5YMmR4OUtXRnlwcXNLWG5yMk4vdkVabU1vYnRINnMwd0YvSUFnaXNBUWhYVHJiV3UzQWh3R25aaGRWRkl3Vjh6blpWOHMzOXkxUFhKZ0ZJbG5MYWdad2pWeEI5WG1sZ29UQ0UxYytMNjZSS3l5ckdVZ3FjZ1h3elgzTE9kbFhpN0ZpdnRZN0tKMzRFNHJLTVF1Q0NDeEIwRkJrSFFYK1JNdHJLZ1lEeHNvRnZISytnUjhmYkV4T1pMM2pkZGJNNmNjMWNobWYxeU1WSkJRTS9wUW1sMWt6cDU4L2UrZnJTWW1ySHgxczVKWHpEUmdyRjJRaXJjbWZkTGExSHBNYUV2SUJXZVJlNkJWY2dBdXhOenp5K0I2Z1Jkc094WTNMZG9tVzllZVNTcHlvcWdyZmVIa0YreTQwWUttZUx4bmZoUUlRVjI1Y0kxZTRkM0VQajk1M09tN2VyMUNlUGo2UDl0ZVdZckV1eklRdDdPbHNhLzF3b1pXMzlNR0ZpNlNtRnZLUjN3ZFdBNnUwdXFEQmFNWmNOWjg5Qi96UnFiZXQ2a2xRd0tyOC9tK2NvcUxZeGErT3ExaXE1c25aaFVMZTRuVTdjWTVlNVYyM1hhSmwvWVdrZnZ2TXlRYjJIRmlhcVlIR1NlQVBwSWFFZkVJaVdJVmV3UVdhU21EREk0OHZCdzRDNWRwMk1GTzRScS93Qjc5eGludVg5Q2YxMjE4Zm44ZjNEeXpGVXRtQXFhaFVHcCtRVjNpY0RseGpQZnoyM2VkNGV4SlJYSUI5NSt2NDJrc3JzVlJwbmtnVVlCeFkzOW5XZXFZUXkxMzZZQkZZZ2dnc1BZcXNEd0kvMG40VTc4LzIvb2YzSnkreVhydFl3MzgvZHh1bThqck1KWlhTQUlXOHdEMDVobWVpbjArKzVUanJGOTFJV2x4OTljV1ZtY2pTSHVTM090dGFmMXlvWlM5OWNPRWlpOXlGdkNYZ2REK3I5WFdONW1Jc1ZYUDU2b3NyMlhlK0xxbmZybDkwZzIwUEhjYm42TU5sSDVKS0VuU1B5ejZFejlISHRvY09weXl1TEZWek15V3UvckdReFpVZ0Frc1E5TXovUStNczd3QW1TeWxGVmZQNCtrc3JlZjcwbktSK3U2eHVoSC80elFNVWVRZHdqdldCakZBRlBhS3FPTWY2S1BJTzhBKy9lWUJsZFNOSi9mejUwM1A0K2tzckthcWFoOG1Ta1NueEh3Ri9LeFVsNUNzeVJWam9GVHdOam5QWjhNampaY0RMd0ZxdHIrMTFUK0VhdWNMdmJqeWI4TUwzSU9OVFpuWSsxY1RBUkRXV3lya29CcU0wU0VFZjJzcm54VFYyamJweUczL3hya05VRkx1VCt2MHpKeHY0N3Y1bFdESTNMZmc2Y045MHlIY2xmYkFJTEVFRWx0NUYxbnlnRTZqVCt0cGU5eFR1c2F1OGYyMDM3MTE3S2FuZnVyMEcvdXZaTlJ6dnFjRlNOUStEeVNLTlVzZ3BQbzhMMStoVjFqVGM0Rk52UFliSm1OeHBCRDk3ZlNILyszb2o1c3A1bVJKWC9jQ0d6cmJXSzlOQzdFb2ZMQUpMRUlHVkJ5THJMdUJGb0N3VG5aSjc5RElQTHIvSzc5NXpqbVJLVlFWK2VtZ1IvL3Y2SWl5VmN6QVZsVW5ERkhLQ1oyb0MxM2dmNzcvekl1Kzc4MkxTN2ZpN3J5N2wrVFB6TUZjdHlOUmd3UTdjMzluV2VtaTYxSW4wd1NLd0JCRlkrU0t5M2dYOG5BeXNML1I1UFhqR0x0RTB2NTlQUEhBU2c1S2M3YngrWlNaZmZPWjJEQ1V6c1pUTmxNWXBaQlhueEJEcTFCQ1BOUi9sam5uSmJjRHdxUXBmZVdFVlhWZnFNRlV1eEdETVNBcEZIL0NlenJiV3A2WlR2VWdmTEFKTEVJR1ZUeUpyQzdBckk4N1E1OFV6ZHBuRnN3YjU0ODFIc1ppU080ZXdiNlNVZjMzcUxpYTgxVmdxNjFFVTJXY2laTG9EOStFZTY2WE1PTXBmUEhTSStpcEhVcjkzZVl4OGZ1L3RYQmljaGFseVFTYlhFbTdwYkd2OXl2U3JIK21EUldBSklyRHlTMlQ5TGZCM21lcXd2T05YbVZWaVk5dER5UzhRZHJoTWZHSHZIWFFQenNCY05VK08xeEV5aHMvcnhqMTZsY1padzN4bTh4RktMY21kbVRrK1pXYm5MKzlpY05LS3NXSmVKZ2NFZjlmWjF2cjMwMU1BU3g4c0Frc1FnWlYvSXV0eDRMRU1lVVU4OWw1S0dPRXYzOTFGYmVWa2NoMmZxdkQ5enFWMG5KcUxwVUl5dnd2YTQzSGFjWTMxc25uMVZYNzc3dk5KblNrSWNIMnNoSC81UlJPVFZHTXFtd09aOHlXUGQ3YTFmbWE2MXBQMHdZV0x6RThJaGN4bmdPOWtTTGxpS205Z1NxbmhiNTY4bTNNRFZja1pucUx5dXh2UHN2V0I0N2pIcitHY2tLU2tnbmE0SmdieGpQZnd5YmNjNTNjMm5FdGFYSjBicU9Kdm5yeWJLVU1OcHZLR1RJcXI3d0IvTERVbUZDSVN3U3IwQ3A3R0VTeUFEWTg4YnNhZnNQQzlHWXNVVEk3aXRnL3dpZnRQc25IeFFOSy83eDh0NVhPL3VwTlJWeVdXeWdiSmx5V2tqT3J6NGg3cm9kSXl4cCs5OHpCMVNhNjNBdGgvWVRaZmVYRVY1dkxabUlxck12bTRQd00rMk5uVzZwbldkU1o5c0Fnc1FRUldIb3NzUzBCa3ZTZGpJc3MxaVh2c0t1OWJlNUgzM1htSlpFdmQ1VEh5bFJkWGNlaHlMWmJLQm95V0VtbThRbEo0WFpPNHhucFl0M0NBUC9pTmsxaE15ZVczVW9IL1BiU0lueDFaaExseUxxYk10c0dmQVIvcWJHdDFUWHRSTEgyd0NDeEJCRmFlaTZ4Uy9Pa2IzcEtwZS9nOExqeGpWMWpUY0oydEQ1NUl1b01EZU83MEhMNjliem1tMGhvc1pWYXBPQ0V4Z1c2MzRYSGM0T09ienZEQTh0N2tmKzh4c092NTFSenJyY1ZVTVQvVENYR2Z3NStPd1NFMUp3SkxCSllnQWt0RVZtTE8wdWZGTzM2Vm1hVWovTms3WDhkYTZrejZHbGVHeXZuYzAzY3k1YXZFWERFSHhTQkxKWVZvN2MySGE3eVhVb04vU25EZWpJbWtyMkd6Ri9GdnY3cVQ0Y2txLzA3QnpFNVJpN2dTZ1NVQ1N4Q0JKU0lyWlplSlo2SWZnMmVFUDMzSDZ5eXVIVXY2Q2c2WGlTODl0NGJUZlRNeFZ6Wms2a2dTSVkveHVpWnhqL2V3YXM0UWYvU1dZeFNidlVsZjQ4TDFTdjc5NmJYNFRGWk01Yk9CalBvTEVWY2lzRVJnQ1NLd3BvSEkrZ0VaWEpNRjRKNGN3VE54blkrbE9HMEQ4TXlwdWZ6UHEwc3hsYzdDVWpaREtrOEEvRm5adlpORGZQU2VzN3hsWlU5SzEzamh6QnkrOWNweXpPVzFtRXFxTS8zSVB3YytMT0pLQkpZSUxFRUVWdUdMTEF2d1F6SzR1eERlUENoNjA1SmVQbnJ2V1V5RzVOZGw5ZGpLK005ZnIyWFVWWUc1b2lGVHg1UUllWURQNjhFOTNrTjEwVGgvOHZiWG1WTnRUL29hSHArQmI3NnluRmN2MUdmeXdPWlFaRUc3Q0N3UldJSUlyR2tvc3RxQTM4bW9BL1Y1OEk1ZnBhNThoTSs4L1VoSzY3TGNYZ1BmZkdVRis4N1h5WUhSMHhUMzFBVHU4VDUrWTFrZkg3M25EQ1pqOG1MZFppL2lQMzk5QjlmdDFZSDFWaGtYNjk4REhoRnhKUUpMQkpZZ0FtdjZpU3dGZUJ6NGRJYTlLRjU3UDZwN2xNZmVkcFRWRGJhVUxuUHdVZzI3bmw4TmxtcUt5bXN6bVFCUzBGRUg3SjRZQU5jb2YvVFc0NnlkUDVqU2RVNzB6T0NKWjlhQXVRcFRXVjAyMnM0WGdkYk90bGJwWkVSZ2ljQVNSR0JOWTZIMWQ4RGZadm8rbnFreDNPUDl2Ry90SmQ1MzE4V1VsaFFQMjR2NHd0NDc2QjJ0d2xUUmdORmNKQlZZb0hqZFR0empQY3kzanZCWTg5R1VvcCtxcXZDVFF3djUrWkdGbUN2cU1SVlhaT1BSLzc2enJmWHZwQVpGWUluQUVrUmdDV3g0NVBGUEExOGd3MGRJK1R3dXZPTlhXVFJybUUrLzlSamxTUjRXRGY2ekRIOStaQUUvT2RRWVdBQXZPYk1Lck52RlpSL0c0eGppdDlaMTg5Q2FLMGtmZHdQK3c1cS8rTXdhTGczTndGZ3hMOVA1clFCOHdHYzYyMXEvS0hVb0Frc0VsbFN1Q0N3aFZHVDlGdjd6MFRLNjhsZFZmWGduZWpIN3h2amp0eDlKS1pVRCtITm1mYUhqRHNaY0ZaZ3I1bUF3bXFVUzh4eWYxNDE3cklmcTRuRStzL2tJYzYzMmxLNXpmcUNLLzl4N0IxNWpCY2F5T1NoS3h2T3BUUUVmNld4ci9aSFVvZ2dzUVFTV0NDd2hrc2k2RC8vT3ArcE0zOHM5T1lKNzRqcS9mZmM1M243YnRkU3U0VFh3dmM2bFBIKzZBWFA1Yk13bGxWS0plWXJMTVlySGZwM21WZGQ0K083ektlMDZWWUZmSDUvSER3NHN3WktkRkF3QU51QjluVzJ0TDBzdGlzQVNSR0NKd0JKaWlheFZ3RlBBL0V6ZnkrdWV3anQralZYMU4vakVBeWNwSzBydDdOdFR2VmErK093YTNGUmdycWlYUTZQenFaUDFlWEdOOTFLc1RQRFkyNDZ5ckc0a3BldlluV1oyUGIrSzAvMnpNRmJNeTliNnZDdkF1enJiV2s5S1RZckFFa1JnaWNBU0VoRlpkZmdqV2VzeTM4SDY4TnA3TUt2anREWWZaZW5zMFpTdTQzQ1orTnBMcTNqOVNnM204anBNeGVWU2tUckhQVFdCZTZLUDlRdXY4K2g5cDFMS3lBNXdwcithSnpyVzRERlVZQ3hyeU5ZUlN3ZUE5M2UydGZaTFRZckFFa1JnaWNBU2toRlpwZmpYWkgwZ0cvZnpUSTdnbXJqdTMyVjQ1eVVNU21yMjJkbGR5OWRlV2dXbUNzemxzeVdhcGNlTzFlZkZQZEdQMFR2TzFnZVBzM2IrVUVyWDhha0tUM1l0NGhkSEYyQXBuNDJwcENwYnIvQWo0R09TblYwRWxpQUNTd1NXa0tySU1nRC9BdnhGTnU3bjg3andUbHlsb1dxRVQ3L3RHRFBLbkNsZFozekt6RmRlV00ySjNwa1N6ZElaL3FoVlAzY3R1TUh2MzNlU1VrdHEwOEtERThWOHNlTjIrc1lyTVpablpaZGdrSDhGdGt1T0t4RllnZ2dzRVZpQ0ZrTHJFV0Eza1BtdGVxcUt4OTZQNmhwbDY0TW51R3ZCWU1xWGVqT2FWUm1JWmhta01uUFZtUWFpVmdiUEJGc2VQSjVXdlI3b3J1V3JMNjdDVUZ5RnFYUjJ0cExPdW9DdG5XMnRiVktiSXJBRUVWZ2lzQVF0UmRhOXdKTkFiVGJ1NTNIYWNZLzNjdC9TWGo1eXoxbk1LUnlQQW1IUnJJcDZPV29uQndTalZtdm5EZkw3OTUxTUtmOFpnTXRqNUZ2N2xySC9RajJtaXF3ZW16UUFmTEN6clhXZjFLWUlMRUVFbGxTd0NLeE1pS3o1d1A4Q2E3TnhQNS9YZzIvaUd1WG1jUjVyUHNhQ21lTXBYNnN6RVBWUXpKV1l5MnRsYlZZMk90Q1FxTlVuSGpoQjA4SWJLVityKzBZbFgzeG1EUTV2T2NieXVkazRTekRJWWVBM085dGFyMGlOaXNBU1JHQUpJckF5S2JMS2dLOEREMmZybmg3SEVDNzdFQis0cTV0MzMzRWw1UVh3WTVNV3Z2YlNLbzczek1SVVhvZFoxbVpsRFBma0dPNkpBWm9XM3VEajk1NU9PV3JsOVNuODlQQkNmblprSVpieUdrd2xXYzNjL3ozZ0QyVXh1d2dzUVFTV0lBSXJXeUpMQWY0Yy93TDRyQ3hzOG5xYytDYXVVVmN4eHFmZWRvemFpc21VcjlWMXFZYXZ2cmdLajZFY1Mza2RpdEVrbGFvUlBxOGI5M2cvUllZSlB2bkFjVzZiTzV6eXRmcEdTL212Wjlad3cxNkpzWHh1TmhleSs0Qy82R3hyL1hlcFVSRllnZ2dzUVFSV0xvUldNL0FEWUVhV1BESWV4M1U4azZOODlONHpQTEM4TitWTE9Wd212cjF2T1ozZHN6R1YxV0lwclpJS1RST1hmUVNQNHdZUExPL2x3M2VmU3ptdmxRbzhlN0tCNys1ZmhybXNHbE5wRFpBMWV4NEdIdTVzYTMxR2FsUUVsaUFDU3hDQmxVdVJ0UkIvWHFDN3NuVlByMnNTejhRMWxzOGVac3NESjZrc2NhVjhyVk85VnI3OC9HMU1lc3N4VjlUTG1ZWXA0UE80Y0kvM1VtR3g4MGR2UGNxU0ZNK1hCTEE1aXZqdjUxWnpjZENLc1dJdVJuTnhObC9sSU5EUzJkWjZTV3BWQkpZZ0Frc1FnYVVIa1ZVRWZBSFltajNuN01ObjcwTjFqL09KKzArbXRZRGE1VEh5L1FOTGVPNTBBK2JTV1ZqS3FzbGl4Q1NmZTBoYzlpSGNrelllV25PWkQ5eDFFVk9LdXowQk9ydG44N1VYVjJJb3FzUllOanNiaHpTSDhtWGdUenJiV3AxU3NTS3dCQkZZZ2dnc3ZRbXRqd0M3Z05KczNkTXpOWUZub28rMTg2L3p5S1l6S1MrbUJyZzBXTUdYbjF2RHNLTU1VOFdjYkVkUDhncVB5NEZub28vNnluRSsrZUJ4R3F6MmxLODFQbVhtYXkrdDRrVFBUSXpsYzdLZFNzTU9mS0t6cmZWN1Vxc2lzQVFSV0lJSUxEMkxyTlhBRDRFVldYUFVQaTllZXkrS3g4NGZwaG5OOHFrS3Z6bzJueDhkYk1SUVhJV2x2Q2Jia1JSOWQ0bytMKzZKNjZqdWNYNW53MW5lc3JJbnJWamZnZTVhdnZiU1NneVdDZ3lsOWRsT0Juc1MrRkJuVytzcHFWa1JXSUlJTEVFRVZqNklySExnSzhCdlovTyt3V2pXWFF1dTg4aDlwMU0raGdWZ2FLS1kzUytzNXZ6MWFrbnBFTUE5T1liYlBzRHRjNGQ0OUw1VFZLV3g5czBmdFZySmlaNVp1WWhhZ2YrY3pVOTJ0clhheFdKRllBa2lzQVFSV1BrbXRENEYvQWVRdGYzMXdXaVcwZXRQYnBucVFjSkJEbHlzNWVzdnJjUm5LTWRVWG9kaEdxWjA4SGxjZUNiNktUTFkrY1Q5SjdoOVhwcGxHb3hhbWNzeGxOVm5PK21yRS9oTVoxdnJMckZRRVZpQ0NDeEJCRlkraTZ6MXdCNWdZVGJ2NjVtYXdEM1J4L3BGQTN6czNqTnBSYk1jTGhQZjcxektTK2ZxTVpYT29taWFMSUpYVlJWM1lCSDcyMWRmNWJlYXVyR1l2Q2xmTHhpMU90NHpDMU5aZlM0TzRlN0d2MHZ3a0ZpbUNDeEJCSllnQXFzUVJGWVYvc09pSDg3bWZiVmNtd1Z3OFVZRnUxNjRqU0Y3T2FieWVveVdrb0t0TTQvVGptZWluN25XTVQ1eC80bTBGckVEN0R0Znh6ZGZXWjZycUJYQWQ0SC9yN090ZFV3c1VnU1dJQUpMRUlGVmFFTHJENERIeWVJdVF3aXN6YkwzY2R1Y1FSNjk3elJWcGFtdkhWSlZoWTZUYy9uQmdTVVlMQlVGZDY2aHordkJNOUdQNHJYenNVMm51WGRKZjFxeHVxR0pZcjd5NGlvdTNLakdXSmFUdFZaMjRJODYyMXEvSlJZb0Frc1FnU1dJd0Nwa2tiVUMveGx2YTdQcXpIMWV2STUrZk00SlBucnZHZTViMXBlV2NCaWR0UEROVjFieStwV1poWkVKWGxWeE9rYndPQWJadEtTZjM5MTROcTFwVmI4UWJlQUhCNVpnS3FuRVdEbzdGN3N4dTREZjdteHJQUytXSndKTEVJRWxpTUNhRGlLckNOZ0pmQ2JiOS9ZNEhmanN2U3ljT2NLV0IwNHdxMklxcmV1ZDdMWHkxUmRYTSs0cTlVOGI1bUh1TEkvTGdYZWlqMW5sZHJiY2Y1eEZOZU5wWGE5dnBKUmR6OTlHNzFnRnhyS0dYRTJsZmc3NHE4NjJWcGRZbkFnc1FRU1dJQUpydWdtdGR3TnR3S3pzT25ZZlhzZDEzSk5qUEx6K1BHOWZmUTFGU2QwZmVIMEtUeDJiejVPSEdqRVdWV0l1cThtTGFVUC9kT0FBZUNiNG5RM25lSEJGYjlybDhQTWpDL2pwNFVXWVN3Tm5DR2JmRGdlQWozVzJ0ZjVhTEV3RWxpQUNTeENCTloxRjFoemdXOERic24xdnIzc0szMFFQTmVYamJIbmdCUE5uVHFSMVBadTlpTFpYVm5MczJneDlUeHVxS2k2N0RiZGppSHVYRFBDN0c4OVNWdVJPNjVMbkJxclkvY0pxeGwxbEtLVU5HTTFGdVhpenB3UGk2cnBZbGdnc1FRU1dJQUpMUk5Zamp4dUFQd0grQ2NodXo2eXFlQ2FIY05tSDJiejZXdHFwQ0NCczJyQ3NUbGU3RFlPN0EyZFhUTERsd1JNc21KbmVkS0REWmVKN25VdlpkNjRPYzNrTnBoSnJMbDVyRXRnR2ZMR3pyVlVjdXdnc1FRU1dJQUpMQ0JOYWE0QnZBM2RrKzk0K2p3dWZveGVMNHVBUGYrTmsyc2swdlQ2RnZTZm04Y09EaXpGWXlqR1YxZVkwU2FuUDQ4Smo3OGZnYy9DUmU4NndhV2wvMnBtOE9ydHJhWHRsQmFxeERFUHBuRnk5WHhmd2tjNjIxdE5pUVNLd0JCRllnZ2dzSWJySUtnTCtBZmd6SU92Ynp0eFRvM2ducm5QSHZCdDhiTk9adEk2REFYOXl6ZTkxTHVQVjg3TXhsODdFVW1iTjZyb2sxZWZEWlIvRU16bks1dHV1OHNHN3VpazJweGVoRzV3bzV1c3ZyZVRjZFN1RzB2cGNIU1BrQmY0WitNZk90bGEzV0k0SUxFRUVsaUFDUzBoTWFOMFBmSk1zWjREM2l4SXZQa2MvWHVjRXY3UHhMQTh1NzB0cjhUZkE1YUVLdnZyaUt2cEdLekNXemM2S0tIRTVSdkU2cnJPOGJvUkhOcDJpdG5JeVBVWGpVM2o2K0R4K2RIQXg1cEpLakdXMXVUb0krenorcUZXbldJb0lMRUVFbGlBQ1MwaGVaRlVDbndjZXpjWDlQUzUvU29mWkZlTjg0djZUYVMrQ1Y0SDlGMmJ6N1gwcjhGQ0txWHcyQnBQMlM4Njhya2s4OW40cUxBNSsvNzZUM0RaM09PMXJudTJ2NWlzdnJtTE1XWXFockNHWDZTaitHL2d6T2FSWkJKWWdBa3NRZ1NXa0w3UStnUCtvblZsWnYzbklJdmkzcnVqaFErc3ZwRDNGNXZJWStjbmhSZnpxMkR4TXhWV1l5Mlpwa3RiQjUvWGdzUS9nYzluNTBMb0xiRjU5RmFNaFBUODNQbVhtdS91WGNxQjdOcWF5R3N5bDFsdzFnMzdnRHpyYlduOHBGaUVDU3hDQkpZakFFclFUV1hYNG94ZnZ6OFg5ZlY0M1Buc3ZScCtEajI4NnpkMk42V2NDdURGZXdyZjJyZUJFanhWVGFZMC9yVU1LN1ZaVmZianR3N2duYmR5N2VJRGYzbkNXaXVMMGxpV3Bxc0lMWityNTd2NWxHQzFsR01ycVVBdzVXNlQvWGFDMXM2MTFTQ3hCQkpZZ0Frc1FnU1ZrUm1qOUh2N3pER2ZrNHY3dXFRbDg5ajRXMTQ3dysvZWx2NjRKNEV4Zk5WOS9aUlZEOWxKTXBiTXhKYkUreTcvTzZnYUxabzN4OFUybm1EZGpJdTNudVRKVXpsZGVYTVhBZUFXR3NqbVlMS1c1cXU0QjRKT2RiYTAva1pZdkFrc1FnU1dJd0JJeUw3SnlHczN5WjRLL2djc3h5a08zWCtaOWF5OWhNZm5TdktiQ0srZG44OTM5eS9GUWdyR3NMbWF5VG8vVGdkZlJUNFZsa2tjMm5VbzdyUVNBM1dtaS9lQVNYanhUajZWc0JxYVNtYm5JeEI3ays4Q25KV29sQWtzUWdTV0l3Qkt5TDdSK0QzZ0N5TW5DSUovSGhjL2VnMFdaNUpIN1RuSFhnc0cwcitueUdQblprWVg4OHNoOGpFVVYvbU4zUXZKTCtmTlpEWURYd1lmWG4rZkJGVDFwcjdOU2daZk8xUFBkem1WZ0tzVlFXby9CYU01VnRRNENmOVRaMXRvdUxWd0VsaUFDU3hDQkplUk9aRFhnWHdEL1VLNmV3VE01anNmUno5SmFHNC9lZDFxVGFVT2JvNGp2ZHk3bFFIY3Q1bElycHVKS1BJNWhQTTR4TnErK3htL2VlWkVTaXlmdCsvalRSNnowVHdlVzFtTXFLc3RsZGY0d0lLNXVTTXNXZ1NXSXdCSkVZQW42RUZxUDRFL3BrSk1EQUcrZE5yeWM5cEU3QUZlSHkvbld2aFYwMzZqZ3JnV0QvTTZHYzh3b20wcjd1bmFubVQydkxlYWxzN3FZRHBTb2xRZ3NRUVNXSUFKTDBMSEltZ044aVJ5dHpZSTNwdzFOVFBLUmU4NnlZZkVBV3JSRXIwOUpleW93ZUozblQ4L2hCd2VXWXJTVW9wVFc1L1FJSCtCL2dEL3ViR3NkbEJZc0Frc1FnU1dJd0JMMExiUmE4Sy9ObXAyclozQlBUYUE2K21pb0h1ZlIrMDZsbmFSVUMwNzJXdm5HeXlzWmM1YWlsTTdCbE50RHFLL2kzeUVvZWExRVlBa2lzQVFSV0VJZWlheVp3TDhESDg5aEQvSkdrdEpOUy9wNStPN3phZWVuU29VYjR5Vjg1OVZsSE8rWmlhbHNGdWFTYWlCbjlxRUNYd2Irc3JPdGRVeGFxZ2dzUVFTV0lBSkx5RStoOVE3OGkrRG41K29aZkY0UHFxTWZUeUREZXZPcWE1cE05OFhENlRIeTA4TUxlZXJZZkN3bGxSaExhelRKR0o4R1o0QlBkTGExdmlRdFU1QStXQVNXSUFKTHlIK1JWUTc4TS9CcGNoaTY4Ym9tOFRsNnFiQTRlR1RUYVUzT0NJelljUUg3ejgvbU82OHV4MnNvd1ZBNkI0UEprc3NxOEFEL0N2eGpaMXZybExSSVFRU1dDQ3hCQkpaUVdFSnJFL0FWWUdVdW44TTlPWUxYZm9PVjljTjhkTk1aYWlzbU5idjJwY0VLdnY3U1N2ckh5djFwRjVMSUNwOGhEdUtQV3IwdUxWQVFnU1VDU3hDQkpSU3V5TElBMjRDL0FvcHkxcm40ZkhnbnIrTnkrUE5hdmYvT2k1U21rZGZLWmkvaUI2OHQ0VUIzTFpheW1aaEtadVF5N1FMQUJQRFh3QmM3MjFxOTB2SUVFVmdpc0FRUldNTDBFRnJMOEMrMmZtc3VuOFBuY2FFNit2QjVKbmw0L1hrZVhOR2IxUG9zcDhmSUwxNWZ3TStQTHFDb3BBeEQ2ZXhjSHNvYzVIK0J4enJiV3E5S1N4TkVZSW5BRWtSZ0NkTlBaQ240ZHhsK0RwaVp5MmZ4dUJ5b2pqNHFMQTQrZXU4WjdvaHp0cUNxS3J4MHRvN3ZIMWlLYWlpQjBucU1wcUpjRjJrUDBOcloxdnBqYVYyQ0NDd1JXSUlJTEVHRVZnMytsQTRmemZXenVDZEg4VHF1MHpocmxJL2VlNFo1TTI3Tm4zV3kxOG8zWDFtQmJiSlVEOGZiZ0g5ZC9SZUJ2NWJVQzRJSUxFRUVsZ2dzUVFnWFdzMzRwdzJYNUxiajhlRjFET0p5akhEUDRnRSt0UDRDMWxJbjEyeGxmSGYvTXM3Mld6R1d6c0pjV2swT04wVUdPUUpzNld4clBTQXRTQkNCSllqQUVvRWxDTkZFVmpHd1BmREo2Wnlieit0Qm5lekhOZWxneFJ3YnAzcXRXRXFyTVpiTVFqRVljbDFVNDhEL3c3K0kzU010UnhDQkpZakFFb0VsQ0lrSXJhWEFmd0diYy8wc1hvOFQxVDJKd1ZLZTYzTURnN1RqUHord1YxcUtJQUpMRUlFbEFrc1FVaEZhSHdZK0Q5UkphWEFlK0ZSblcrdXZwU2dFRVZoQ05BeFNCSUlneEtPenJmVUh3SExnY2NBM1RZdkJDZndkc0ViRWxTQUk4WkFJVnFGWHNFU3dCSTNaOE1qamR3SmZBalpPbzlkK0d2aDBaMXZyZVdrQmdwWklIeXdDU3hDQkpRaWhJa3NCSGdWMkFEVUYvS3FYZ1AvVDJkYjZwTlM2SUFKTEVJRWxpTUFTc2lXMHJNQm5nVTlTV0VzT25QZ1BadjZYenJiV1NhbHBRUVNXSUFKTEVJRWw1RUpvRmRLMDRTL3haMksvSURVcmlNQVNSR0FKSXJDRVhJdXNmSjgydklnLzdjSlBwVFlGRVZpQ0NDeEJCSmFnTjZGVkRmd3Q4R25BbEFlUGJBZitHZmlQenJiV0thbEJRUVNXSUFKTEVJRWw2RmxvcmNTZk8rdnRPbjdNL3dHMmRiYTE5a2lOQ1NLd0JCRllnZ2dzSVorRTF2dUEvd0FXNitpeER1SmZaL1dxMUpBZ0FrdklCSkpvVkJDRWpCSlkwN1FhK0V0Z0lzZVBjeDM0ZldDRGlDdEJFREtKUkxBS3ZZSWxnaVhvaUEyUFBENEgveUw0ajJiNTFtNzgwNVdmN1d4ckhaT2FFUFNDOU1FaXNBUVJXSUtncGREYWlQL1luZlZadU4wdjhDY0xQU3NsTDRqQUVrUmdDU0t3aEVJWFdRYmc0OEMvQUxNemNJc3p3SjkwdHJVK0phVXRpTUFTUkdBSklyQ0U2U2EwS29EdHdQOEJpalc0NUJEdzk4Q1hPOXRhUFZMQ2dnZ3NRUVNXSUFKTG1NNUNhejcrYU5idnBuZ0pOLzVweDg5MnRyV09TSWtLSXJBRUVWaUNDQ3hCZUZObzNZMC9yY09tSkg3MkkrQXZPdHRhdTZVRUJSRllnZ2dzUVFTV0lFUVdXUXJ3SVdBbnNDakdWMS9EdjREOVpTazFRUVNXSUFKTEVJRWxDSWtKclNMZ01lQ3ZnYXFRZjdvTS9GL2dlNTF0cmVMRUJCRllnZ2dzUVFTV0lLUWd0R1lBZndYOEh2QnZ3QmM3MjFxZFVqS0NDQ3hCQkpZZ0NJSWdDTUkwUVk3S0VRUkJFQVJCRUlFbENJSWdDSUlnQWtzUUJFRVFCRUVFbGlBSWdpQUlnaUFDU3hBRVFSQUVRUVNXSUFpQ0lBaUNDQ3hCRUFSQkVBUkJCSllnQ0lJZ0NJSUlMRUVRQkVFUUJCRllnaUFJZ2lBSVFqZ21LUUlobCtUaFdZbFd3Q1kxSndqa3ZlM0tVWEZDSnBFSWxpQWs3cHozQUx1a0tBUkJiRmNRUkdBSlF2bzBBUWVCbHNCbm14U0pJSWp0Q2tJc0ZBbVJDamx0Z1BxZkl0d0c3QWo3T3h1d0R1aVdHaFNFL0xWZDZmK0VUQ0lSTEVHSVRIQmFZVWVVZjJ1UkloSUVzVjFCaUlZc2NoZUVXMmtLT09qR0NQL1dEV3dIMnFXWUJFRnNWeENpSVJFc1FiaVpiZmpYYklRN2FGdkFPUzhXQnkwSVlydUNFQStKWUFtQ0h5ditYVWFScGc5MkJ4eTBwR2NRQkxGZFFSQ0JKUWdKMGh4dzBPRWozNDZBYys2U0loSUVzVjFCRUlFbENNbVBnRU1kdEt6VkVBU3hYVUZJQzBuVElPUzJBZW9uVGNPZXdHaDRaK0FqQ0VKK2tMTHRTdjhuaU1BU1JHQmxaeVFNc2xaREVQS05sRzFYK2o5QkJKWWdBa3NRQkVGanBQOFRNb21rYVJBRVFSQUVRZEFZV2VRdVpCVkZVYXo0a3dFR1A5YkFweW53bFM3ZURQVUgvN3NMLzY0ZzRXWWE4YTg5YVF3cHk2WUkzK3NJK2RNVytGT08rUkVFUWNna3FxcktSejRaLytEUFViTUhVRlA4RE9QZmpwMkk2RkJ6OE1uV0liSk4rSThBdVpEbTgwWkt5QmlzcDJ5VlJYT2E5OWtTNDlvN0FtMG0zWGZaRy9oc0M5eXZVZVA2M0piQjhtN09rUzJrMmpaeVpydmlvK1dUaVk5RXNJUk1SNnlpNWFsSkZtdWdnOXVhZ01BcVJMWUV4RSt6aGtLdGhWdDNYUlZLK1FVamV1blNIUFluZ2VoZk8vNGtsaElKMURZaUt3Z0Znd2dzSVpQaWFrZWNFV3R3eXFvcnBGTU1UbmZGNmppblUvTEFZTVNxT1krZU9WdjFreXR4MHhobzE5dnc1MXlTdEI2Q0lJakFFckltcm5ZUmVRcW5BOWl0cW1wNzRIdlJPckF0VWNSWnZLaEVGN0E1Ukp3RTJSSGxXUkpkMnhXNnZpbGJZbWRibE9jT2ZkZjJ3SitoYTlkQ243ZUo1S2EyZ3RjTExidG92OThlOXYrMmdPaEpWR0FGNjZveFFyM3VpQ0NtZG9mZHF5dk9lM1RFdWVZYjdaSElXL3lEZ3I4NVJ2bnR3QjhKZkRoRndkY2U0VDJhb2p4cmQwRE1kU2NvTkp0aWxMc3RnVEpNdE43RGJiY3hocDFZcDRudENvS3N3WkpQUnRaYlJWdFhzaTNDZDJPeEk4STFVbldRV3E2YnNuTHIrcDY5R3BxbE5YQzlhR3ZSZHBEOGRNcU9OTjQvMnJOazFEVmxvSHpUWFM4V2F3M2hRYlNaa296MXJNbVd3YlkwMjN5NjlkNmlVVDFtM0hiRmI4c25FeDlKMHlCb0hibHFqRExpM0txcWFySlRLUjFKak1xelNieVJ2eGJpcWpsS2Vhd0xSQkNTalphMFJ4RU5RdUp0OGVIQUoxcTBhMitldkVlMjBPTnhOWm0wWFVHNENSRllndFpFR2xtMnE2cTZPNFZyNmRrUlpxS2pDb3FyU0NKeU8vN3BrMVRYSFVtbm9wMW8yQnhEWkczVCtmTm51eDEwVHhQYkZRUVJXRUxtQ0VTdnRrUVJCNm1PTnZWNmRFMG1ubXRQRkhHMUZXMFdVb3ZJMGs2a2JJMHh3TERxNURrYmRWRC8zZFBFZGdWQkJKYVFVVm9pZFVhcXFxYmpaQ010QU5aakpDRGRMZWJSZGdwdTUrYkYzZEt4NklOSWkramh6WFFpZWhSWXVSQTdlb3dXYVcyN2dpQUNTOGc0elZFNklpMGR0RjZpQTFvNjZXYWlUSzJpYlFvQW1SclJsdDFKMklFZTIydzJzT213YkVSZ0NWbEIwalFJbVJ3eFo4SkI2NjNEc2dZaUE2aytwNVhJR2VxN2laOVVOZDJ5YkpJbW14SEJxdGR5N1o0bTk4eVc3UXFDQ0N3aHJ3VldCMit1NGVyU21UTmNwOEUxWXVVYTB2cGR1eU9JT3lFOXdkb1ZRVkRwcFZ5N1EwUmdNN21kSXV3SXNXSGQyRzRDcVdJRVFRU1dVTENpSzVoY3NSQ3hFbmxxc0lQTWJISHZDdnR2R2Jsckk3TDB5bGFkUEljaXpVUVFnU1VJNlhmZzRhTjV5YlVVblMxRWpuWmtTbERhcExQTG1oMElnakROa1VYdVFxWTdsc2JBZ2M5Q1pJRVZxUXhsTVhyK0VFa2d5d0hRZ2lCSUJFdkl5c2g5bDZJbzYxUlZMWVFwcWRDejFvTHZuTXA3dFJCNStyUmRtbEZlaWF0SUM5cEZJQmUyN1FwQ1FrZ0VTOUNNUUxiMjdpaU83YUNpS0lXd2E2MEZmN2IxNENkVkJ4MHRxcmRiV2xKZXRRVkVKRTg3MnhVRUVWaENUdGdaWS9SNFVGR1VIWXFpNVBQdU5hMUVZc1Nrck9MMDg0cHRVUVN5MUdGaDI2NGdpTUFTc2s4Z2lyVTdUcWQwUVZHVWJYa3F0TFI0NXFZbzE1R3BwZndTVitGVHZEWlNQeFpLeUEvYkZRUVJXRUpPUmRaV1lrK1RXUEVmRFhNQmY1TE5mTXFrck1XelJodEp5K0xvL0tBbDBIN0QyWXBFcndyZGRnVWhZV1NSdTVBcGtmV3dvaWk3aUgwdVcvRGN0aTM0bzE2N3llNFc5K1lVdnErRmsyNFVnWlczYkNGeTV2MTRnd3FoTUd4WEVFUmdDYm9RV1ZzVlJla0lkRWp4d3ZOQm9kV0JmeDFYTnFiTG1zbE5ucTVvRVN6Sm42VHZEbjFiaFBZU25CYVV6UW5acnc5Si95TG9HcGtpRkRJdHN0cUJ4VWwwUU0zNGQvZ2tJc29LRFpsZTBnK05JYUxxWUtCTk5rY1F4SnRGWEFtQ0lBSkx5SlhJc2dYV1pTVWp0TGJnWDZQVlVxQ2piMEVmN0FEVUNKOExBVkcxZzFzampzR0R1TmVSM2FpakNIQkJFSUVsQ0JHRlZuZVNRc3NLN0NIeWdtSXQySTcvNkpoRVA1dWxGcWM5eVVaa3RVU21rTVYyQlJGWWdwQ3cwTnFad01oOEc1RVhGbWViRG1RaCtuUW5tS3hTdHZ6bkYySzdnZ2dzWVhvSnJjQklkSEhnejFoQ2F3dVJFenRtRzNIU2hjVjIvTkdOOE05V29pY05iUmFSbFplSTdRb2lzSVJwaHcxL0pHc2RzWGNQUmtydW1LL3ZHd25KTkoxOWdvZHJoMzkyQjBUV1lpS25YMmpDUDMwdENJSWdBa3ZJaXhIbVpxSm53N2FTK3lpV0ZndU51Mks4bjVCY21XV2p2aCtPSXZ5YjBVZFVWY2llN1FxQ0NDd2hyOWtaUTJUbGVsZGhjRXBwTWY3RnMxbzZlb2xnNmJkemZEaktNeFJLVkhVNm9JWHRDb0lJTEtFZ1JGYWtOUlBXSEF1UmJ0SmZNQ3NSck5qb1VXZ0dwN0VqMWRrT3FiSzhRQXZiRlFRUldFSkJzRHVQT3VCa0hYMGs5Sm9mSzl1QzBCcEY0T2hWOUxjZ3VjMEVRUkNCSmVRUkhWbnUySFA5WGszb2M3b3AyMU9halVtSTBteXpOY3JmeTFvc1FSQkVZQW5hb3loS3M2SW9MWXFpYkZNVVJTdVJVS2lKRlcxRVB4ZzRuekxYTjJieHVucHBDeDFFWC9BdVVTeEJFRVJnQ1pxS3ErQlpiY0dzNjlPdG93bm1SZHFCUDE5WElzSWpXaFJyRy9xTDBIVmxXV0NGdDU5dTlMVURiR2VNdWhQeWIyQzRWMUdVSFlxaWJORndjQ2dJSXJBRVRRanYvREl0RVBRVzJRcXV3UWxtbkU5RVlMWkhFUTNXZ0VqTEI0R1ZpV2hicEUwTTdUb3JENGxpRlE2cDJLNGdpTUFTY29aV1RzcWFSd0lyMmVlTHRpc05JaDh3bkdzQkhlbWRHalB3bkZ2eW9MNUJvbGlGSkxEMDN0WUVFVmpDTktZclFzZWJLYUhXaGI2bWk3YUVDVUZiRWs1NmQ0eDMyWVcrcGdyYmt4QkVXZ3FzYnZRWHdZTFlVYXdXY1FsNXdTMjJxNnFxQ0N4QkJKYWdLMndaRWxoYmt1am9jMFZ6R2lOZ0c5RjNwVFdoci9QdVlnbXNaZzNydXpHQ0NOVXJzU0tRZ3Y1SngzWUZRUVNXa0JzVVJVbTMwNDJVVzhpbXN3N1h5cTNSaW80VWhNdnVQQkJaM1RHZVU0dG9XMk1FWWFLMytpWkNYWGRFZVpjdDRnVjBqUmEyS3dnaXNJU01ZNHZTeWFSS1U2RFRqaFF4ME5QMFlLU3BvRlJHd2R0ai9LNEp1S0J4aHgwVU0zdFRlTTVvZFoyT0VJd21KUFZXMzBScGs1SFlnV1RtMXpOYTJhNGdpTUFTTWtxa0pKRE5pcUtrMHNHMFJPbHNPMkowWnJrYUFXL1R5RW5iOEorUkZpdGorcTRRb1pWS3VUWUZudmRnNERyYjhFY0lyVWsrWjd3cHphWVU2enRja0xmcnJMNmowVUhrNlZOcmxFR0NVRmkyS3doUk1Va1JDQmtjSVRZcGlySWJhRmRWdFR1T3cyc2grcEVqWGZnUDIwM1VlVGFGZFBxeENPYWNzcVZ3YmEwWDRBZEYxaDZpcjJscURIVGFPd0lkZTFmZzB4MG1jb1BDS2JqTEw1YVFhaWE1ZFczdEFaRzFLNHJJT2hqNFRudmdHYU5GdkpyajFQZldOTnRmRTRtZFc5a1M5cDFnenExazZuSjdsSWhJVUR4MlJDakQ3cEN5YUl6dzdOSHFLbEpPc0dRMlZzUXFxL0MvYTR4aE4xMGF0LytjMjY2cXFucVBsZ3I1aHFxcThwRlBXcCtBSTFiamZJWURuYzJ1Z0hQY0ZoQVRCK1A4YmsrU1VaYm1CSjRsVXgrdEloYmJBdVdWNmVjZEp2V3B4eTBKM3VOQ29ONkRuM2pmMTJyTjJkNDB5eWJaTllTN1VyejJOZzNxY1crT3l5clZNdE9WN1lvdmw0L1dINGxnQ1ZxSTlHNUZVUklaUVNiamdHMkJ5TUR1UENvS3JhWVlkZ2FpSE52SXpHTHBZSFFwbmJMZEhYamZlSm43RzBsc1BWNHdMOWpPUERXRFlCUXJGK3V1dWhIMFlydUM4QVpwQzZ5Tmp6NGhwU2dFT3hndE1sbDNCVHJ2YUpuT3A0dVQ3c1kvVGJZOUlMTENwN0tTdlZaSHlNZW00ZnR1RHRSNThCbFRlYmJkeE00SmxnclpUdFFhRklpNVNORWdBa3VEdGl4OW1aQXMrNy94V014L1Z3SlRQQ0t3Qk0zb2JHdHQ1dWExRkZadVhROFR1bDRqMk9ubm82aktKc0VvWUdOSXVZWkdpSUpyc1lKcmNycEQvc3oyOHpXSDFYK2s1K3ZRUytSZ3d5T1B0K0NmanJZQld6dmJXbFBOdDliTXJXdmlCSjJ5NFpISHBSQUVFVmlDSUFnWkZJWVh1SGw2TDdpWVh3Uy9JQWdwQ1N4SjB5QUl3blJuRzdldW5Xb0ppQzQ1OWtZUWhKUVFnU1VJd25RbW1COHNFbGI4MDRiSjdtUVZCRUVRZ1NVSXdyUVhXUEdRYUpZZ0NDS3dCRUVRa21BM3NKajRLU3NrbWlVSWdnZ3NRUkNFSkFpbXhFaEVhRWswU3hBRUVWaUNJQWdaRUZvU3pSSUVRUVNXSUFoQ2hvU1dSTE1FUVJDQkpRaUNrQUdoRlJyTmFwUWlFd1JCQkpZZ0NJSjJRa3VpV0lJZ2lNQVNCRUhRV0dodFI0N0hFUVJCQkpZZ0NJSm1RcXNMLzBIUGdpQUliMkNTSWhBRVFVaExhQW1DSU55Q1JMQUVRUkFFUVJCRVlBbUNJQWlDSUlqQUVnUkJFQVJCbUZib2RRMVdVK0JqQlpvRGYyY2w4c0dzWFlBdDhPbkN2eTRpK0tjZTJSTjRqOUNjT2R1UlJiS0NuMFprTjVyWXJTQklmeXdDUzhOT3BTVlFlYzBwVkg2UTBGdzBOcUFkNkFqOHFRZTJFVGxmVG1PT2pHWkh5UDgzYTNUZGpnakcxaFgyOTVsaUY3QWx6MjB5WHFlOUIzM25YRklLMEUvcXlXNjFmcTl3dTAvSER3UnRuU3gyc0kzNHMrbHJUUWV3T1VXL2VsRGpaOWxOZGpkVDZLay96bXQvbDB1QlpRMTBoaTFSbExCVzE5K2lrNUdtTmVEUTRqWEtiSkdLOFNSNjNXak9PdFRBYkJrU2pmbU9MWS9mc1JCSHFYcXpXeTNSMnZkYXcyeStKYXh0dEFjK1hYbGc4eDA2ZXA3dUxMVnpQZmJIZWUzdmNyRUdxekVRYVJqR0gwRnAwa05CWklFdFJEOFl0aWxIOVpBTGh4NnMrMTBaZUlaQ0VGamRjWnhVWTU0K2U3NmlON3ZOVjN0cERBalZnNEhQRmcydm00dUJUamFmcHp2RDlhTFgvamp2L1YwMkJaWTFVSUVYeVA0MGppM0hGZEhJemROeGtXak93VFBsdXVPNkVDZ1hxd2JYYTZZdzZNNWpBV21qc05DajNXcEZMcCs3S2RDcEg5U2dUV2ZxUGZRVXdlckt3RFh6b1QvT2UzK1hyU25DTFVsMnBNRTFPN1pBaDJPTFV2RE52TG40THRzTk5CbTJKZGlZT3JMNFRCMFI3dGZJbXdzYWsvbGR1T0UySmVINGd1dEFOcWZaUVRjbFlSU0p0Z2RyQW1XUlRHZWRpS2lOTnlyYUh1WHZZNFgyYlNRV2tvLzNqTTA2dDdQcFlMZGFzajFLblRiSHFlUDJHR1ZoVGNMMm00QzlnZWZZcmFFZkM5YWROWVk5N0k3amI3bzFmcDZnUDRrV0VRMWRzOVlkOXZkYVI3RHlxVC9PYTMrWGFZRVZQR2srRVlQYkhXSzh0Z1FhTVNHRjJCSXdxQ1lkanF5YkV4d2hXTFA4WER0akdOK3VHRTRubVlXZkxRbStmM0JoNkxvMDZxb3BoaEZzVDdFVGpOV21raTJMOE92dVNNR3B4M1BlVFRGK3QxTkRtOTZXb1BqSVovUnF0MW9Qc0haR2VKL2hHTDlibDBUNU5STjdpalY0djEwaGZZQ1dmc3dhNHplWldwTzdNNEgyc2lWS2ZUd3MvWEZoK2J0TVRoRTI0dzgvTnNlSkptd0hadURmSmJHYjFEclk5aGlkWFQ1RXI1S0p3SkFGSTlScVZOZk9tMmUyeFJNNGpZSFJiS29kVmxPVTlyVTVqUWlEbG1XUmlCTk81NXBOR28wWTQyR0xNYW9zcEFoV3Z0bXRWalJwMU9ZN0F1MWtjZURQZUg1OUY5cE85elZteVI2MGVxNU1QMU9oOWNkNTRlOHlKYkMySk5CWjdnd1kzMDYwaVREWjBsVExtV3JVelVsOFZ5OGo5M2dqbFdRSlJudTJKMkEwcVl3VW9pMkdUSGUzWWxNR3lvSU1PUWF0T3NaTTJHQytrWTkybXcyQjFaVmltOWlKUC9JVjcvZDd5TTU2eks0Y3Q2MXNQMU1oOXNkNTRlOHlJYkIyRUgyS0tkaVFOaWM0cXNsMXA1VXV1elJzTkxrZVlXblJjSGNtSUxLMmtmd0MvRXc1cmFZc2k0bFVyMm1ONHp5elpRT0ZFc0hLUjd2VmlreTFvK0FncXl2T3ZYZG84QTZOY1d3c1Z3T0JUUHJXNmRRZjU0Mi8wMXBnN1lvVGdRZ21iOHZtb3RCY0dkT1dDQVlWWEZ3NVhRVldVR1RGcS85dEdqMXpld2FOT0JNT01kVnJObVhvdXZsZ1oySzMycExKeUlBTi96b2pXNUxscnhlUm1HOENxMUQ3NDd6eGR3YU5LelBXb3REZHBMOVRMSnVkVnJvR3ZpMkt1R2hQMFRGa2cyeUYxdU5sSlc3UjRMa3pPVDFJaHB5U0xRUFBtaTNuV1FqUnEzeTEyMndKTEMzcXVKdjRDNURUemR6ZHJBTjdTS1pzTS9GTWhkd2Y1NDIvMDBwZ2JVdWdNcmZtcUZIblltUWRheFRja1liQXllVUlxMHRqSTR2WFliV2thWENabkI3TWxKalEyMko4dlE5a3hHNjFGNWpaYUV2eEZrK25LN0RpVFJIbXNueXpZVHVGM2gvbmpiL1RRbUFGYzJya3VqS2JkREt5ampVS3RzVjVwbHhQTldTejRTYXlxekJSWnhycHVkdnp6SWd6RlcwVGdWWDRkcHRwSDZwMVpNQVd4ejdUTGM5R25iYlRwaXc4MDNUb2ovUEczNlVsc0RZKytrU1RUaW96Vm9lWTdSRkxwQVIzNFdIeDdoanZrTXNNNi9FU0RHcEp2T3MxcG1Gc1dod3VtOGtJVnFQRzE4eEZ0RTFQa1lIcGJyZlpFRmpaSG1DbEdoVnNUdk8rK1J3RW1DNzljZDc0dTVRVGpXNTg5SWxnMGpKcmpCZmRtbU9Ia2Uzb1ZXT01VWEQ0YzdYRXVFYXVSbG5aekIyamxjQnF6SkFUYmM1Z1o5T280VFVieVUzSXZFTkhIZGQwdDl0czJML1c3OWF0a2YzbjBvY2xLemlzR1h5dTZkSWY1NVcvU3llVGU2ekRlb083UlhKTkxxSlhrU3A4ZHhLTklKZEhiK2cxdEI3UHNYUnc4N0VIN1Jrc0J5M0xJdlJZakM2ZFAyczRteWtjOHQxdUMzR0FaVTNESCtqUmg4WEthcTVGUHpWZCt1Tzg4bmNwQ2F5Tmp6N1JRdXlGaUZ0MTBpRm5jOFFTN1dpTm5VazJnbHl0NTJqT1VjTk45MzdiTTNEdnhneTNxdzVBeWJEalRuaVVOYzNKZDd2TmxnL29rbmZJaUoxcThVelRxVC9PSzMrWHRNQUtUQTNHbXVkdDF5Q0NrS282RGg1STJaVURnOW9XcGNKM0o5blFjdVdvRzdQY2NPT05VUFU0MnRTakVlZGoxRkZQNUx2ZFpxc2QyUXJrUFhKRnBxWUhwMXQvbkZmK0xwVUlWcXhFY0RaeU44OGJ6RWlicTFGVGM0S2o0TkRuYlVxeUFlWENBV1NxNGVvaFdWd2hHTEVJck9sdHQ0WGFqcm96OEI1NmpHQ2xXN2JUclQvT0szK1gxQzdDalk4KzBSaEhMV3QxamxHK3NTUEtLTGdqUldQUFJWNmQ1aXczM0hnQ3F6Mkg5WmxQUmx3STB6cGl0N2tuMjFIYmVQWnYwOWdXY20yN21SQlkwN0Uveml0L2wyeWFobTF4R3UvdWFlaWt0MFF4bnAxcEdIc3VwaHV5UGZLTHRXWmd0eGh4Mm5VbUFtdDYyRzAyMmxJbU91bE1uSlNRN1dVT2lSSnJCMkU2enpYZCt1Tzg4M2NKVHhFR29sZnhzc05PeCtoVnBFYmVub0RoeER2ME5Oc09JSnNDcXptT2cyM1hzUkhyS1lLVmpVTnRnOXUvd3p1Rm5XSzNPYmZiYkFtZXJpeTMzWHcrMFNDWnNrMDNlalhkK3VPODgzZkpyTUhhRnVmbHBtUDBhbHVVU2s5a1o1dWVSc0pOV1dpNGliYWxlRk0wdVRaaVBRbXNiSFNLa2RZcGRZamQ2c0p1ODFsZ3RXUkFZR1Y3bVVPNlpkdVZaaHVlYnYxeDN2bTdoS1lJQXpzSFcrSkVIS1piOUNyYTBScTdFelRtN2hRZFJiNDcxNVk0NzdkOUdoaHhOc1JnVndiTG8wdnNWaGQybTY5dHZqbE8yMjNYc1QyazJ1YTBmS2JwMmgvbm5iOUxkQTFXQzdIRHI5TjE3VldrTWtrbWxOaWhrOUd3TlFPanlXZ0dzaXVPdU9xYUJrYWNqV2ZWeXNHMjZDd2FJSGFiLzIxK1c1eStSSFlRU245Y0VQNHVVWUcxSmM2SWJyb3RwbzIyZXlOWjU5Q2RZbVBLNWdoV3E0WWI3eWlIZHZTeHJpZmJpMzNUalFSa3NrTnBqRkFlZXBzbW5jNTJtNDAycjNWZE44VnB0enN6WUF1MkhOdXUxZ0pydXZiSGVlZnY0Z3Fzd09KMnZTNUl6aFhib2hoeHN0TmIrU0N3dEhDd1ZtQXZzZGNpYkowbVJweU5UbEdyWjIzUmVSbE1kN3ZOaHYxcldkK1JGaENIaTZ0Q2kxNXBmUWJoZE8yUDg5TGZtVks4YVNqVDdUaU9KcUlmclpIc0tDbGVUcDJkT1hZQVd0UnZNL0VQSWQyTVBxSkQrYlFOV01zZE5VMFI2cWVKNkZuT3hXNXpiN2ZaYWt0YVJyQjJFRHNwWmpybFp0V3AzV3E5d0gyNjlzZDU2ZTlNYVRTUTZTcXdka1NwNEZUbXZidDBNQkxPVlBTcU1kQmc0MjBsM3FxanVvMVhGclk4ZVZZcm9HYm92dDFpdDdxdzIyeTBKUzJuZzNmRjhRVVBwMmxmMDJVSDRYVHRqL1BTMzVuU2JMalRUVnpGT2xvakZlY1FWTjdXS0k3YW1vVk9YZXZwZ2VBdXdTMXgzbnM3K2x1TVdTaEg1R1NTRHJGYlhkaXRsbVdqcGYxSDZ2ejJ4dkV6V3pWb1YvbDJCbUYzQnVxcmtQdmp2UFIzTWRkZ2JYejBpU2F5dDhNc1gwZkI2V2JNemZVQnN0WTRIVWs4Y2RhTVAxSzFCeGdPL0JrdmFyVVlmZTUwS1pSRG5qTkZQaDM2VytoMm00MTJsSzdBMmdaY2lGTWVXZzIwOUpyRlhjc0kxblR1ai9QUzM1bFNiQnlKZHNDRlJLeWpOZElwaDY0WW81S21MQmhOVTV4MzNxTFJmWGFUM2lMV1hCdHhQdTBnektUREVidlZoOTFtWTREVm5hSU50UkQ3RU9JZ1d6VVNWODA2YnJOYTdpQ2N6djF4WHZvN1V4ckdsNjhPTjUzUm1OYWo0SGhHMFpoREI2QUZYZmgzdGVUTHNRMU5lZExXNDdXTGRKSzFXb2wrbEZHSDJLMXU3RFliSFZkajROODdZdGlMTmZCbjhMdU5DWmJkVnJUYjhaYVBPd2k3VTd6ZWRPeVA4OWJmbWRJd3Z1a2tzS0lkcmFIRmJxRmNUalZZeWV6NWFidkpuNlIzK2JSNE5ONTBpQmJ0OGdLUmM4S0kzZWJlYnJQVmxyWVJPeWxvS25RRXhKV1dmVWUrN1NETXhGRkEwMVZnNmRyZkdkTDU4ZjV2UERZZEJGYTBvelU2TkJJUHVYVFVtYjcrTHVBZytYRUliajVsY005R3BLMDdEOHBodXRwdE5xTURhTmllSHNhZmtrWHJmbU02blVFNEhRVlczdm83azA2TVQ4OW9jYlJHTEdMdFNBbzJycTRjTk54NEk0TmcxdHZtT05kcHdyK0xTQys1cmxKcDY5M3lySGtuc0FyWmJyTWhUTFJpZDhDWHRFOUQyN1hHYUR0NkZzUGltMFZnWmExaW80MkNPelN1eU9ZY09PcDRPMUlTZmNkNHlVU2I4RWV6SHM3VFVkSjBQT1Jac3hQbHhXN3pzdU5LcDB5NlFzcmFWaUQyb0tWUDZkSlJmZVc3d05LMXZ6TWh4R0piaGtmQm9aWFpuSUlJMG91bzZNQ2ZldUZnREdNSTVzZnF5RU1qMWxzRUt4ZFRJbDFpdDdxeDIyeDFYTEhFa1Mya1RRUVRrbmJvekJaeTNXYWJDc0NXeE4rSndNcVk4NG1Xb21Cdmxodlh6aHcwM0dRYm1BMS9oT3Bnbkk1UHJ3S3JVSFlRZG1mb0hqYXhXOTNZYlRiYS9OWThFUUo2VGEzU0dFVms1MnN1T2ZGM0lyQTBaVmNlT01GTU9xWlVHbGdYL2pVWFcySjBPbnFNWWpVbDhGNzU0SEMwTE5md3JjL3RZcmU2c050c1BXTytSRm4wbW5pelNZZlBWR2dDUy9mK0xwN0E2bzcxZ2hzZmZhS1J3dHk1RU8xb2pWdzVrRXdjdlpHcGVlMmR4RTVPMmtKK1pVWFBKekdvNVk2YW5XSzN1clJiclo4dm44VlZQTnZWbzUxMnAybVhqWEhLb3RENjQ3ejJkNFlFYnB5UGpUdGR0dVZSSTlQYjZEVmVFc2N0Nkc5OWl1d2dGTHZORjd2VnUvMkxQYnc1a0l4RU9wR1I2ZGdmNTdXL2l4ZkJzazNEQ3QwU1pSVGNIYVZDYlJvNXBGaEhTMlRpNkkxTXJsM29JSDRVUzA4SlNKdnl5SWp6S1YrWDJLMnNPY3dsdGh6YWFHTVNiVkdyOTVsdUFrdjMvaTZld09xS29jUUx0VUtqallJemtTQXZGR3VNZXpmbFdjTnRKM1k0ZTBzZUNTeTlHYkdlejEwVHU4MjgzV3I1M0lVZzFKdDErRXlaaUY1TjEvNDRyLzFkdWxPRVRRVldtZEdPMXRpZGhjck05dGxtc1JxdUZxUHU5amp0UmsvT0lGL0MwTm5ZVVNOMnEyKzd6Y2FnWXJwUE5ldFZZRTIzL2pqdi9WMDhnUlZ2Sk5OTWZ1UjdTWGNrbW8wRnY5azhlaU1iZ2lLZU0ybkpneEdTTFk4RTFuVGRuVFNkN0ZZRWx2NXBpbEsyM2FRZkdaeE8vWEZCK0x1WUFpdHcxbUE4WTJzcGtNcU10dmc2RzZQZ1JCcE1jNVlhcmxidjJoWG5XaTE1WU1UVDhRekNlRGF5TnlCb21zUnVzMjYzV3JaNXF3ajFqTFZIb3JUSGRKbE8vWEZCK0x0RURudHVud1lWMmdqc3lPRW9PSkZHMDVpbGhxdWxnODJIYWNKOFdvdVM2Nm5NYlFIQnNBTi9RdGtMWXJkWnRkdENhVWZaRXJqWkhnUllNeXl3cGt0L1hERCt6cEJtQXc2TzBKcnp2Q0szeFRDS2JEcWNyaXc1Nm14bFA4NEhaOUNjcGJMSWRMMWxXZ3hHMmkzWEpYYWJWYnN0bE1pQUhnWlBtV0JIalBhb2xTK1pEdjF4d2ZpN3VBSnIvemNlNjBqQTZMYmxjU1UyeFJoMVpEdlpZcmJXYzJSclpOQVY1NTFhcHJrUmF5a0dNOTB4Ymt2QjJZdmQ2bk1kVmlHbCt1aE8wVjR5VWFiWmFJK0YzaDhYbEw4ekpQaTluUWtVeEpZOHJjUWRPaGtGWjlOWlpIb0hZU2g2bnliTWw4NG1senRxb3VWNmFoZTcxVlVucjdjQlZxN0xQcHYrWlZlTXZsUHJNaTNrL3JpZy9GMUNBbXYvTng1THhHbnRJUCsyaWNZS3ArYmlxSkN1TkJ1ZEhwMnJucWNKNDQyUTlEUkZtTXNkTmR1aTFLdE43RFpyZHB1TmRxKzNYYk5hK0pkc0NJMXRVY3JVbHFIMldLajljY0g1TzBNUzM5MGU1OSt0QVJXZlQ5dEVkK2xvRkp5SXdHbktjTVB0enRBN2RlWFlBUmJDU0Q1WDYyYjBHTDJham5hYmpUYWZqeWNCeFBNdjJ6SXNjSnVJSGszZG1zRkJTQ0gyeHdYbjd4SVdXUHUvOFZnNzhYZENOT0ZmYVo4UHlqbldFUmU1UE9pMkk4TWo0V3p0SUV5MGNUYVN1MmtVYXc1SFNma2lCcmRGR1ptM2k5MW0xVzZ6MFhIbDYxRkw4ZnFsUFJrc3k3MHhmRjRtYmFUUSt1T0M5SGVHSkwrL1BRRWp0UEptN29oc09Jc2RKTDk5MG9xKzFuQWs2dVNhOHJUaHRxZlFxTE9CN0NETTRtaE9JMEU4WGUwMkcrMUliMjArR1lFVmJ5M1dyZ3pZeHNFb2c3UXUvTkdyVEZNby9YSEIrcnVrQk5iK2J6eG1BeDVPd0JDRGp2Q2d4dEVKSy80MU83dUE0Y0QxZ3lGZ2E1SUZhZFhoS0RpZWsydlN5QWl5TGJDNjR6VFNYRzB0enFjcHdtenZxSW1WSVQxWDBiM3BiTGRhZG9MWjdyaXl3ZllFMnM1ZTBwOHlzK0tQaU8ySzBRNHlPVFVZZnE5QzZJOEwxdDhsRzhFS1puZmZuR0FEQ29aUUw1QmFOdFRHUUFVR0c4ZHdvSEZIY3JSTlNWeFRML2x6a25WeVdqVGNYRG5ZZUkxMEI5bGRMMkFsZjQ1aWlEZkZaTlA0WGkwQnUyMU1RU3huc2d5bXM5MW1veTNsczhCS1pNcXNPYVF2c3FiWS9pNFFmV09PTGRBM1pyTWM4NzAvTG1oL3A2aXFtdElQTno3NlJERDAySlJDZytpTzBZRTFCU29yV2FXOU9leWFrYkxxTmdjS3NUR0dnN0hGZURZYjZXZmtiWXhob01HenBPS0pvRWpIME95TVVJYmhJcUtKMkx2MnRrZDU1K0NPdW5RZHgzQWN4eFlzWDVzRzVSNnRuSzBoNVJOdlBWcThkOTZaQVVOUHBVMEU3U2xSa1JIcGVrMEpkam83RTRnV3BDdDhwNnZkYWxtR2tjN0VpelZLRHgxVWRNWHB4THJRNzVFNkJ4UHNrNExyYXJwRDZzWVd3UjZhU0N6Q0hwd1d6SlZJMVh0L1hKRCtidjgzSHN1TXdBb1JXZHZRUjJLemRXR051d1h0RnpkcTBibGs0cm02QXUrZnFKQkpoZDJrdjY1Z1I0cHRKZno5RW1FTDJxKzd1TVYrTkx6V05xS3ZMOUlUaXpNY0xack9kcHN2YldrN3VaK1MxVnBvcEVNNzJac1dqUGZ1ZXUyUEM5TGZ4Uk5ZaG5UdUhGaVR0VDJnVm5NUm9nODI3QmtSS2pNVE8zZTBNS0JNUEZkMzJQV3RHYjVIT2lJdFcvZk85TTR0clVmdytiRFRweU1MZGo1ZDdUYWYycEtlcHhKdGdjNDlHd0t3Ry84YXFJZlJ4d1lCUGZmSDA5TGZHVFI4a01XQnd1M09jSVBlSFdqUVN1RFBhT2M4TmV2VXNXVDZ1VElsTExvMHJMOXMzRHZmT3BsOGNEalpXSHMxWGUxV0JKYTJCSVZHSnFZeXV3UFhYMGR1ODhIbFUzODhMZjJkU2VNSDJoMzR0QVFjVWd2cFJWT0M2eXE2UXY3TTVZaFRDMlBOUkhTcEt3c05WeXRIdFpQa2s0dnFVV0JwNmJpczZQTlE0SEJiekVabk1sM3RObC9ha3Q1T09JaFg3eDBoZlZFNi9WR3cvWGZvVkZUcHZUK2VsdjR1clRWWUFCc2ZmU0tSa1Y5d3dXWG9BdVB3bCtrSytiT2J5QXRDQlVFUUJDRlZnb3ZXUXpkTmhQWkozU0g5VGxlWXFDZ0VwRC9Xa0l3dWNoY0VRUkFFUVJCdXhTQkZJQWlDSUFpQ0lBSkxFQVJCRUFSQkJKWWdDSUlnQ0lJSUxFRVFCRUVRQkVFRWxpQUlnaUFJZ2dnc1FSQUVRUkFFRVZpQ0lBaUNJQWlDQ0N4QkVBUkJFQVFSV0lJZ0NJSWdDQ0t3QkVFUUJFRVFCQkZZZ2lBSWdpQUlJckFFUVJBRVFSQkVZQW1DSUFpQ0lJakFFZ1JCRUFSQkVFUmdDWUlnQ0lJZ2lNQVNCRUVRQkVFUWdTVUlnaUFJZ2lDSXdCSUVRUkFFUVJDQkpRaUNJQWlDSUFKTEVBUkJFQVJCRUlFbENJSWdDSUlnQWtzUUJFRVFCQ0d2TVNYejVZMlBQckVOMkJIakt6WmdScGJmWVEvUWt1SnZPNEROMGd6ZVFJLzEyeEtvNDBUb0JuWURPd3V3WGxxQXByQzYyQmw0WDVzMFhXbHp3clMxcllOaHp4OUtGN0JPcWprejdQL0dZekgvM1pEa3hYYnUvOFpqU2tDWUJOa05LSUhQakJ5ODQ4T0JlMjhQK2J2MmtHY0svNndMZVg1eGlqZXpNMUJHZXFyZjlnajEyeDFXcDFzRGY5Y1lFSWg3QzZpalZ3UC92UzdrZlI4T3ZPK09nSE1WcE0wSjA5ZTJnczhmcVY4VWNaVkRVcDBpYkF6NTd3NmR2RXRUbUdvbmhxSi9PQ0FjT3FRSjVHWDl0b2Y5MjI1dWprUTJBMXNLWUdTOUovQmVPeU1JZ00yQmppRFJzanNZNkZBdWhOV3ZJRzB1MG52dkNiU1piUVZZcjFyYWxoNTl0cDc4ZHFHMW13dkFMcUpIREcvQ2xPd2ROajc2aEZXbkhYQmptUE9MaFMwd0FoVnVSYS8xMnh4SFFIY0huR05MaE00eEgwZlhPK0lNQW14eEJoS2hUcUVwMEpGMEJQNS9MN0JZbXJxMHVRanNDUGlBblFtMnIrbHNXM29kREhRaHl3YTA3aFAzQm13OUtiOXBTdUZtelRxc3lNYVFCaWFOUzl0T1JROWwyUlJvNVBGRVh4ZXByOGZUV3llWHFMaU4xeEdFajlDM2MvUFVseUJ0THJ4OUZESmEycFplQlpaRXI3VEZSb3BUcmVrS3JIWWRqVXFrY1drdnNOcDErRXl4Uko4MUxMcVFyeDE3WThqQUlSWVBTM09WTmllSWJSRS8yaXJrZ0ZUV1lHa3Rab0pURmxxcDkvWTQ5OXFSNFBYMkpqRXliUXBjOXdMK2RTN2hueDF4M2ozOCs1RjJSamFHZmVkQ2xHczJScmplbG1sU3Z5MWgzMnVNVWgrN29qaW9TTi9kbG1UNVdnUDFIZnJ2ZThNNjRrVGZkUXVKclpkSzlEMmpQWHUwZHc5dGE5SFc0bHlJODl0bzVSak9yZ1N1c1RkS1c5NlY0RFBzeVVLYjI1YkFPN1FrV0tjN2dPRUlkUkhKbit4TnNBeENmZEsyTk10dFM0UzJIcTNOSk5OTzBtbVBXdHRXUHZqdHBqZ1JyRVRLUHRxNm9tVHFMZDEzM1paa0d6NFl3L2NsNHRmQ1A4TUJQejJjNFBmakxnbElTbUJ0ZlBTSjBMQzViZjgzSGt0WEtRY0Z6KzQwcjlNY0VzcnJpdU1NNDRrR2E4QlFyQWxFY0lKQ0xPaUFRbmVqeklqeFhpMkJ4dGVFZnkxWTZBNldEdDdjSnI0bGJIU3M4T2FVVDJNVUp4UDhYanR2N2dyY25ZU2hXaE1zeTJ6VnJ6VkIwUmZxTUhjR3lpRllGc0hvdzJiZTNBRVdUa2ZnMzRMdnZEdXN2Q09WNy9hdzhtMEpHSDFYV0oxYWsramNiV0dPS05paHh1b01ncy9VRWRMUlIzclBhTThlZlBkZ0JDYjRiNHREaE9xT0tPMXRNVzlPSzltNGRjZHVjQzFQdkIyN1c2TThRN0FPYkFFNzN4V2hMTGR5ODRMenpXRjJHRngvdGpNTGJXNG5ONi9UMkJ4bTI4MkI1NC9sblBjRS9Fb3dMVXBvT1FUdC9tQ1lQd24vN3VJWTVSR3NqNTB4dnFmRUtMZWcvOW9Tb2M2M0JxN2ZtRVk3U2FjOWFtMWIrZUMzNDBWYkYwZXA1OFVoOTloQzVFME55ZFJiT3UvYUhuaVBkV0gzaU9RUFFuL2JIZVY3dXdQdnREWHNkN3ZEL0gzd3M1MDMwM0xNaVBHOWh3UDNiVStrZjB3Mmd0V3NZWFNqT1dRa1prM2pPcUdpd0JwSGNUWW04Tng3QXQrTDkweWhUaTdZQ0cxaHhydzE4UGZ0WWIvYkU2akFoN2w1V2lHNGc2VXI1THVSbkVSM2lGSEVvcU1BNnJjNTdOMjdZa1FRZzgrOVBjeVJXZ08vVGVTZEdoTU1zMXZEdm1NTmRQNFBoOVYzZStDVDZQUlJSNFR2Qm5ldnhPdVlteEtzdTBpREIydUVkKzhPYTZOTmNjb3MvSnBkZ2JwSWRQMUNZNVR5M3g2d3NlNlFqcTRseWpOMGg3Mi9MZkQ3elVrTUdOSnRjMDBodncwVnZWdWozQ08wRG9JNWpkWVJlZjNjd3lIMzJCWnk3WWZEL0U5empQSllGL0xkNWdqUEducS84SExiRVdpSEhWR2VNYmk3MGhaQklDVFRUdEpwajVtd0xUMzc3VVNpclpIcXVUdkM0R1JiQkgrZHJIMm44cTYyQ0cydE1jYTlRLzJzTmVTWnU4SytzenRLT1lSZmIyZVlEVGRIcVl2Mk1EdlVWR0FsbWdvaGtSSGlqcEJyYU5VQmg2dmNjSVVhcitGdUMzdkdlSkdaZHVJbktnM2RqUk1NcWNjYlRlOE9hV0JORWVvZzZFd2JZNHppR3RNMFZMM1ViMU9VRVdqd3VrR2hHOXo1dERuQ3FEUFI5MmtPRVdPSnJEL3JDSXRtUkx2UFRoTGZ0V3FMSVFhQ0ViSWRNWjQ5VVlIVm5ZQUREaS8zcmhnaiszVGJUQ0xQc0RPR1FHblJhR0NnUlp0cmlsSWV0amoydFRja09oSnR6VmQ3Z2dJalViSGRsRVRkQmFORzhkcXpqY2hKT3BPMXhWVGJvOWEycFhlL25jakFPRlk5ZDRROHV6WEM0Q1ZaKzlicVhVTUhDZDF4SW92V0NJT0pXQU80UkwrWGxrOUxXR0FGMGpPMFJHaE1xUkFjQ2FRNkVvbm1ERHVTaURoRXFzeVdFQlZyamZKY3djaE1OOG1sZXJDR0dHKzhuVHBkTWE0Qk4wKzViSW5TUUpMZC9hZlgrZzBQZjRmUG1XOEppWEJzai9IN2ppVGFVcnpkazQwUkRMNHBwUE5ObCs3QXFIQjdGTWNTYVMxaFU0TE9xREZLKzJxTzB2YUM2enRzVWRwRU1zSXUwZkx2aU5HQjJhS0k5bVNFUXFiYlhEU3hGeXJDT3lLSWw2YUFnT3BJMFQ4a1VwK3Aya2RMb04xMWs5aE93KzFwdHBOVTI2UFd0cVYzdjUzb3NvNTQ5ZHdlSmJpUWJMMXArYTdKRGhJNkVteFQ4WHhrTEhHZkdZRVY3blQyZitPeFZMZnZCNDAwdEFOdTFNQVp4bHN6MUJTanNFS25kN3JER2tHa1VSd2tmNHpDbHNCOU9oSndlbzFSUnIwdEliOE5Sc1lpalJDYTB4d0ZwWk9lUWN2NkRSZTV3Zm42ME05aTNweUxqMlY4aVVTa1dwSXcxSzRJamp2WVBvWjVNNTlRT2dUWHlLeUw4UHhiVXV3b283V05TS0h6NExSSU4yOU8rNUNFc051UlpOMG5JNFp0Q1hZQ0xTUzN5U1BkTmhkdFdtTkhTQlJrY3hUL2tPakFwakZLZEMzOEdlSkZZbU9OMUZ2Qy9NcTJOQWRleWJhVFZOdWoxcmFWVDM2N0k0RjZiay9Bbm14cDFKdVc3NXFNVDB0a01KRm9YeEJyc0piTVJwbWtCSllXZVRhQ1VhS3RZUlhabUliUkpxcXVZNjNCMkJQaU1HMHhucXM1eVE0N2t0RW1zdzRvdkZFM2NldmFsS0Rqc2NiNFhyN1dieUpyWWVMOTNwckFpQ1g0akUxSkdHcWs5U29kSVozMHRvRFEwaUtpRlR4OVlHZVVVV1l5enFNeHduZENIWERvanJ3dHZKbGNMOTdJT05KdW5oWVNYM3VXYVBnK1VyUWd0TzJHNzNyYWsyUjcxcUxOUlhxV0p0NWMwMlNMTXZqU2FwMWdTNElEcGRCbjNSdWgzTm9UOUh2UmRuOWRTTEdkcE5NZXRiYXRmUExiOFd3MGxoK01sdk10V2Z2VzZsMmJVeGdrSkJLRlRVYXdSZHFGbUpTb1R6bUNsV0kwSWhnbENsZksxaFE3NFpZMG55azg0a0ljWVJDNmVEV1puRGVOWWNhWDZIdnRqdkQzSFdHR3NEdWtiRVB2bDI0RVN3LzFHK284ZHFmeCsyU21CeFBwNUJxajFPUG13SWg0ZDlnb0x4R1J0U2VCMGRIdU9CR2NSSjg5bGdNTzNYMW9KZjYwU0xEY3duZnJyRXRSMk1UcUJLS3RrV3NPS1ovd2FGTlhrcmFxVlpzTFBzdnVzS2hKdk9oT0lyNGhXQWE3MHh6NU44VW90OUFGNGZIOFhqREtGNzdiYkhHSzdTU2Q5cWlsYmVXYjMrNUl3dytHRGk2NzA3QnZyZDQxMGNGdU10TitpZmpJMERwZlRPUWRzdG9Lck1ENnEzUWpITUhkZWFHanVsMXhITDhXalN2ZTczY0VSaW5odXcxakNheGtFd29tTTFVVWJZMUJjNVRLRGE0bENFNkZOS2I0ZkhxdjMxUkUzNVlrZnB2b29zWjRJNit1Z0NIT0NLa0hhNEx2bXN3VVJIc0s3VExhUGNJZGNIZ2tMcDdUaXRSbWtoMk5Keks2REJWU3RnU2NjV09hRWFpdU5OcHNWOWlmelVSZmkyaE5vWngyYTlnNWRjVVpRQ1FxTXFKRkVwSnRKNm0yUjYxdFMrOStPOUgxVjRrc1VtK0pNQWhJdHQ2MGZOZGtCd2xhYmVhSUpkaWFrdTBiRGFrNG5SVFdYd1hYTFVWYXl4QnA1SmlzS0VnbGxOOFlFbkVKZjY3ZFVaNHAzU212Ukl4MlYwaWp0Q1ZRdVRadURzTzJhTkNwNksxK1V4RjlvZXRRZGlkUkJ2RU1mMXVZdU5sQzVNU2xvYVA5N2dTTVB4Rm4zaEp5N1owcENLd3R4RjUvRmJvZFBuVExlV09Tbzk2Z0FFZ21BaFRQQVZvRHo5OGRwUk9JTkpXUXlrWVVMZHBjNkcvYlEreHBWNXErWVV1SWZXL1hjS1Rla1dDNU5TWm9ReDFwdHBOVTIyTW1iQ3RmL0haSENvT2cwSGNQUG1kN0d2V201YnVtTzBqSWhHRGJtcXdJTmlUcC9CSjFPc0ZrZXFGT0lWTGVpTzQwUkV1Nkk4M2dUcmYyS004Vk5LckdDUGRKWkNTMUxhenliV0dHSE8yWmdnZno3bzdnWEtPOVp6RFhVakFCWHpycEdmUll2OTBwaUw3bUpOdUdOUUVoMkJKQnpEZkY2YXk3aWI4dXFqa3M0aGF0Y3czKys4TkVYMkFkNi9mZFVhSVZrVHJhblNIdnNTdE5wNVZJWGNYckJIYng1amI3YUl0d2JSbzhoeFp0TG5UMGF3c2JzRVh5RzEwaGRkRWN3MGFEdTVjZnp2QklQZHJ6eGZKN2pYRWlXSW0yazNUYW85YTJwWGUvblVnZkdHOTNjYkJPSTIyK1NOYSt0WHBYTFFZSm1SWnNHWXRnMldKOEo1Z2ZKbmp5ZE5BcHhNcnJFcG84TU5tUWJLcnNpVEZTQ1k4RWJBbFQ3UjBoVVp0ZEVaNDVlSXhDK0RiNm5TSGx0RGVzTTl3UytMdG0za3hPR2kwYUU0MnRJUjFvZHhxR3FwZjZiVW5nbVJKcEg5MVJITUVPYnM2RzNSN3l1ejFoOVJPTWRyWkVHTmszaHpubzRMTUhNM0Uvbk1Uek4wYTRkMVBnM3JzQ2RSdHA3VU5YbkdmZkUzak83VW5VZldpbTRtQ2JqVmJHa2ZJZDdZandMUEhxS3RJYW4yQlpXZ1B2M3AxZzVMRXh4RWEzWkxuTjJTTFl2aTNFYjJ5TEVBM29EdkZONGZuNGdtMjFLMG9acEROUzcwcWczRUlIb2p1aXRORTlFZDRsbFhhU1Rudk1oRzNwMVc5YmsvRGIwUVJEc0srS3RyTTFtWHJUOGwzMXNQNnFLMEpaN1NESlhZU0txcW9SLzJIam8wKzBKSHV4c0ViWkZOWUFkb2QxVHBHbVZvSnA2bU0xcXVFNDkzNlkyTmxzd3cxemNWamxYSWpRS1d3UEUyUEJjNDVhb3J4N05QSFdRdVFzMU1FdHdKRTZ3T0V3WWJLVjZGTXZ3ZDFJaVJ3Sm9zZjZUZVNaSG80VEVVcTBRN1ZGNkt5QzBiam1DUFhUSHFYY2R3UitFNzVGZXpmSkxjaHQ1T1kxQ3VFZGNCZXhwOXlpdGNsb3p4NXRhalBVMlVhemw0TUppdVd0Q1R6enJnVGFXbGVFT3Q4Ykk5cERqSGFaelRZWDZqZkM4eXQxYy9NVWVyUzJGS3NNRWltUHpXR2RTcUwyRWFuY2dsSDU1aWdDY1djYzN4V3JuWkJHZSt6T3NHM2xrOThPdHRWNDlkd2Q0aGU2MDZpMzNScSthN1N6Z3JjbjJMYldoUW1qYUVJOFhGQUcxdzRuM1dmcy84WmpxUW1zUk5uNDZCTk1jN2FSK0JsbmdpQUlnaUFVQVBFRWxrR0tLQzJDeVFQM1NsRUlnaUFJZ2lBQ1N4dUNpUU90VWhTQ0lBaUNJSWpBU3A5ZzdxeGRKTGNWWEJBRVFSQ0VBaWZ0TlZpQ0lBaUNJQWpDelVnRVN4QUVRUkFFUVFTV0lBaUNJQWlDQ0N4QkVBUkJFQVFSV0lJZ0NJSWdDSUlJTEVFUUJFRVFCQkZZZ2lBSWdpQUlJckFFUVJBRVFSQUVFVmlDSUFpQ0lBZ2lzQVJCRUFSQkVFUmdDWUlnQ0lJZ0NPSDgvd01BSWs4TmdBdlBaZ0VBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8xIiwiRklET18yXzAiLCJVMkZfVjIiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCIsImNyZWRQcm90ZWN0Il0sImFhZ3VpZCI6IjUzNDM1MDJkNTM0MzUzNDM2MTcyNjQ0NjQ5NDQ0ZjMyIiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWV9LCJtYXhNc2dTaXplIjoyMDAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjIwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjM1MCwidHJhbnNwb3J0cyI6WyJuZmMiXSwibWluUElOTGVuZ3RoIjo2LCJmaXJtd2FyZVZlcnNpb24iOjJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDctMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIyLTA3LTAxIn0seyJhYWlkIjoiNGU0ZSM0MDEwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiNGU0ZSM0MDEwIiwiZGVzY3JpcHRpb24iOiJBbmRyb2lkIEZpbmdlcnByaW50IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjI1NiwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMCwic2VsZkF0dGVzdGVkRkFSIjowLjAsIm1heFRlbXBsYXRlcyI6MCwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MzB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwidGVlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInRlZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVnQUFBQklDQVlBQUFCVjdiTkhBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQXlScFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1TXkxak1ERXhJRFkyTGpFME5UWTJNU3dnTWpBeE1pOHdNaTh3TmkweE5EbzFOam95TnlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUlNaV1k5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVkpsWmlNaUlIaHRjRHBEY21WaGRHOXlWRzl2YkQwaVFXUnZZbVVnVUdodmRHOXphRzl3SUVOVE5pQW9UV0ZqYVc1MGIzTm9LU0lnZUcxd1RVMDZTVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRHBCUmtJek1USTJSa0U0TVVJeE1VVTFPVUl4TVVaRk5qaENSakkzTWpJeU5DSWdlRzF3VFUwNlJHOWpkVzFsYm5SSlJEMGllRzF3TG1ScFpEcEJSa0l6TVRJM01FRTRNVUl4TVVVMU9VSXhNVVpGTmpoQ1JqSTNNakl5TkNJK0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnpkRkpsWmpwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09rRkdRak14TWpaRVFUZ3hRakV4UlRVNVFqRXhSa1UyT0VKR01qY3lNakkwSWlCemRGSmxaanBrYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2tGR1FqTXhNalpGUVRneFFqRXhSVFU1UWpFeFJrVTJPRUpHTWpjeU1qSTBJaTgrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrcEQvekJnQUFEQkJKUkVGVWVOcnNYQVZ3Rk1zVzdVQ0NFNElGQ3c0QkNnbnVCQ244UTNBS2QzZDNMeWdjQ3Fkd1QrSHVyb1VHSjBCd0tkemQwcjlQRjNlcXAzZjJrZmQ0MmQzdzlsUjFZTHQ3Wm1mdTNMNXliczk2TURPU2k5WkJ0UCtKbG9uOXQzQkR0SzJpelJUdHNkV0UycUs5RW8zL3g5dXJuN0l3SWNndEdKc0dtVEFQMFJLTDlsUzBhTXdORmVHaStVWVhmd2FMRnVpV2h3MmdQRC93NTVwby9tNTVXT0k2QlBSUnROaHVXVmppa3lmVXlGbmZualp0V2xheVpFbVdMVnMyNXUvdnorTEVpY000NSt6YnQyL3N4bzBiTERRMGxCMDllbFQrNnlSSTJieHh0SWVvVzdjdTM3bHpKLy94NHdlUENJNGRPOFpidG16cERFLzJ4cUVDcWx5NU1yOTQ4U0wvcDNqOCtERnYwYUtGUXdYazhWTkEzcEdwcDU2ZW5tek5taldzV3JWcTh2UHIxNi9aK2ZQbjJmSGp4OW5WcTFkbGUvRGdBWHYzN2gxNzgrWU44L2IyWnZIaXhXTXBVNlprT1hMa1lGbXpabVhGaWhWanhZc1hsOGRqZmxCUUVBc0xDNHZzSmZZMjBqV29kT25TL05XclYxSURaczZjeWNWTldzNkxIVHMyOS9QejQwSVlQRjI2ZEZ3SXlISmUrZkxsK2I1OSsvanQyN2Q1bzBhTnVJZUhSOVJjWXRHaVJlTVZLbFRndTNidDRyMTY5VEtOcFU2ZG1yZHAwNGF2V3JXS256dDNqZ3ZOc1Z4U3dsaHpvUzE4NjlhdHZFK2ZQang3OXV6R09SSWxTc1I3OU9qQnMyVEpFcGxDaWp3QnhZMGJseGNwVXNUNG5DQkJBbm1UWjg2YzRiOERhTTZZTVdONGloUXAvZ3dqalNjOWVmSmsvdm56NTEvZS9QdjM3N213UWZ6bHk1Y1I4bkFiTm16Z0JRc1dqTHBHdWwrL2ZteklrQ0ZNMkJlYk1jUTJodzRkWWhjdVhHQWhJU0ZNZUNnbUJNVEN3OE5saXg4L1BrdWNPREVMQ0FpUWNWSmdZQ0FUR21uNVBjSEJ3V3pnd0lGTWFGZlVNTkxpaHJqd1VEWlBISm94YWRJa1hxaFFvWDkwM2t5Wk1rbDdaaFVxZlB6NGtUZHMyTkQxTlVnRWdXelpzbVhNeTh2TDZJTmJIemR1SEpzOWV6WVRIczNvVDVJa0NSTkxSRWJVR1RKa1lMNit2ckpmR0hpcFRYZnUzSkh1WHhoeWR2bnlaZFAzTkczYWxIWHYzbDFxbUFxRUJmcGNsOUdnSmsyYTJEelpwVXVYbWd5cVdEYThhOWV1ZlAvKy9melRwMDhSTnM0aTllQ3paczJTYmw3OXp0NjllNXZzRzV5QVN4cHB1RzRkNGlrYjQ5R2pSK2ZDSG5HaFRmeDNnZENnZGV2V3hya1JOeDA4ZU5BWVIzamhjZ0phdm55NUtTWElseStmTVZhNGNHRXUxTjd5WnA4OGVjSlBuRGpCeGJMa0V5ZE81Q05IanVSang0N2xDeFlzNEx0MzcrWTNiOTYwS3lpY1UwVG54dmZnT09ENjlldXVKYUJreVpJWkZ3MDNMV3lLTVFZdDB2SDI3VnMrWmNvVVhyWnNXYnNSczlweTVzekp1M1hyeG9YWHN4VFV3b1VMamJsWXZrRHQyclZkUjBEQ3hSb1htenQzYnFNZmthNE9wQnYyZ3J4VXFWTEp1S1pNbVRJOFQ1NDhQR25TcERaek1JNzRSNGNJRitUeG1JT2xMSEk5SGlOR0ROY1FrUEEyOGlKVlNnSlBYTVdYTDE5NGpSbzFUTWNoOTJyZnZyMU1PZTdmdnkvbnFJRHhGVjZNcjEyN2xuZnMySkVMcjJjY0MrMURHcUxpK2ZQblBIUG16SEljR29RMHhPa0N5cFVybDd3NDJBdDczZ3cyQ1Vtb0dzL0F4dndkTHdaZ1BvNkRVYVp6WVhucHNSWWNCc1pjUW9PZzdyQTd5TWJ4R2N0RE44THFEZlh2MzE4bW9mWUFMYUJtRHppK2I5Kytwbk9xZVBqd0lZOFZLNWJ6YlZETW1ER2w1MEhrak04aTJPTmZ2MzQxTFJIMFVYYS9jZU5HbTV2RjBwb3hZd2F2VktrU2p4TW5qdW44eU5LUjhJNGZQMTRtcVRxMmI5OXVhRW1YTGwxTVk0aXpuQzRnVllYeHhQU2JLRnEwcURHK1o4OGVHODNxMUttVEZCek5TWk1tRFcvUW9JRzBOMkFPOVpRRU5nN2FvZUxhdFdzOFljS0VjaHhadmdxUkM3cE9ISFQ0OEdIVHhlRkc3ZG1KTFZ1MnlJaWF4bXZXckdtWnUxR0d2M0xsU3NQZ0l1QmN2SGl4YVE1aUpWcmk0SjlVL0thaC9uY0V0R2JOR3RORndjM2Fzdy93V09xeE1Mb1JCWmFhbW1Mb3hENHhreW9CaDNqTGFRTHk4ZkdSZHNCZTBGYW5UaDNUMk5HalIwM0xVMDBQQ0VlT0hPSHo1czJUUW9kOTBnRk5wZUN5WjgrZXBqR1JFTXYrcWxXcm11eVUwd1Frc25QVEJlN1lzY01ZSzFHaWhJMHhWbzJ3eml4Q01HcVFTYTFreVpMOHlwVXJwcmxoWVdHR2w5S3ZBV0VIK2lucVBudjJyUE1FdEhmdlh1UEM0S0dvSDhTOHlnakNteUgyb1hGNEdCWHo1ODgzeFZXSXRsZXZYczJIRFJ2R3ZieThaUCswYWROTXg4Qm0wVEhJdlFpaG9hRkdyQVVnT1ZZZGdVTUZoUGdIUUlKSmZZaUR3c1BEVFRjVEdCaG9qSzlidDg0MEJnMmdNZDBMRVZDOXNMSm4wNmRQbC8wNWN1UXc5ZGVxVlV2Mm56eDVVbjVXSFlMREJJUVlhTUtFQ2J4Y3VYSkdYN05teld4dXJtTEZpc2I0bkRselRHTno1ODQxeHBETi94V2FOMjh1NTBFb0tvb1ZLMlpqN0pHZW9BOWhBa0RwaDBNRnBLc3RxRlFkMWF0WHQ2c2Q2cEtFY1ZWeCt2UnB1Ynp1M3IxcjZrY0NpL2xJUkFuMzd0MlRmZDdlM3FhNXlOWFFIeElTSXUyWTA5eDhnUUlGNUEzcHNVdXBVcVdNT1lNR0RiSjB5V2oxNjljM2pjR3pxUlVSMVpNaC9hQWtWd1hPb1dzaGpENzZHamR1Yk5KaWh3cEl0d2xFZVdiTW1OR1lNM1RvVUJ0YUFzc1RZM256NWpXTmdZelh2d1BweHRPblQ0MDUwRlQwVDUwNjFaUjdxWWFaQUxvRXg2ZFBuOTQ1QW9LN1ZZR0xWc2ZWbXdCdTNickY0OGVQTDhjQ0FnSk05Q3ZLMHhqRGNzRE9ENFFNcUtmQjZNTUpxQWt1YUE5NE45VlRZaDdPcXpLWENDYWRtbXFBNGdEQXkyRG5ocm8wOUFBU09SUHhPVENzMzc5L040M0RFMkhNQ3MrZVBUTUpDSjRRY3hFZUVMWnQyeWI3a0g4UlFPVTZWVUR3WW9oNjFkbzRvdGhIang3WjJCeEtiREd1aHdHVXQ4SFFScFRVUjlBSkJwRUFnZU1jV0ZZRWFKZ1ZLK21VWkJXRzB5cXZRcUpKYzhBZTZxQ1loUnFFQk1LdGJkdTJNZ3pRbzJqQzRNR0Q1WHg0TWIyYVFRd25BQ1B0VkFIQklFT1RyTmhCZFZlSEhnWWd1aVpYL0t0V3BVb1ZtVExvbXhnd2hnUlc1YnZSdDJqUklxTnY5T2pSemhNUTFOZHFrd0dTVWxRaVNMUDBhZ1M4RHBGc3hCOUQrK0FCWWNnUjV5Qk8wbmxvblRiUmN6NkVHK2hEVUdsRnV6aGNRUEFrNEpzSkNPeXc3NGZHc1V4UU05ZVRVbXlOd1RpV0Y0ejNYd0hHbVZJS05DeFpOVEVHeVVZQXpZRStsSjBJYWduS0tVc002b3hnRHZhRitoRGk2d1FhQUlOT2MwQ3pXdUhGaXhjbTJsYjFncWkvNFZoL2YzL1RQaVRhd1FiUUhHSXRuYzRvcW9rZ2FsYWJOMisydVRsNEprbzRyUkpXM0h5SERoM2swd2FONGV2cnk0T0NnbVJkWHdXOEk4VlJhbFB0RXlYR3dQcjE2MTJEY29VTndkS3hBdWhSZXFwNmlScEFqdmFyUFk0bzVSQ1FvZXR6c053SXRBVUdkZ3ljdDBzSTZOU3BVemFDT1hEZ2dMdzVsWDFFTUtlaVhidDJ4amlNS2JocUJIZlFNTFhtamlXbDd1Q0E4VmEvSHpRdWdXeGc1ODZkVFJ5VVV3VUVRYWlFdk82KzY5V3JaMU9OUUEyZE9HU1ZlRk1CMGt6ZGZLN1cvOVdLQ2hsdWdQWlJSNlRtN3pBQmdmb1lNR0NBa1M1UUE5MmhsM3VBVnExYUdUZGhiOWNIQVV1U3pnZnF3aXJBUkdtYW9HNkxjY2xObktBL2tGeGFSY0F3cHJUcEVoR3pYbHRIV0lBeURaYUhDaFFWZFVJT2NaTVZoUXR0ZFZrQllZTzNGVUJYWUtjSHpRUERwKzc3UVc1R1pKZ1ZsVUxjVHNxVUtZMDhEcHVvYUs3Nk1INkRISXQ4QWNHRHFJQW5nV0NvcUVkejlMUUUwVER0b3FjdExHaVU5Q0l1OHZUMGxIMFU4eURpcG1CVk5lQy93ZjA0Wm9taCtvQ2NLSC8rL0taK1ZEcDBDZ1FicWJEN1RPV09JQURFUWVoVDV5ZFBubHoyZ2ZxZ2FxcE8yQ05KL1kwS2h1TTNrdU5wWXA4UVhMNVZBWkRTQU4zbTBHNFFOWWZEVG4zMDBSNGkyQzk4Um9CcFZTQndhUUVodzljNUlaV3ZWcmV1NkZ2MHFHd05EL2Zod3dkRDAzU0tsa2d6RWlJWWhTanpLZ0lJTkpXR29Hb29PQnhhS2xhbFk2UVdOQWFhZ29BeXRGNDhSRnhFS1FVME5FcStxekZpeEFoNTAycnRqR2lTRlN0VzJDWFdFRGxiN2RCUWpUdlpMU1NrVWZKdEgzdTdZZUhWMU53S1dMSmtpVEVIeVNnS2Z3UktPSWNQSDI3YUlZSXNmdE9tVGFZOEw4b0tDRzRlOUtrVjFNb0RkcjlldW5USnBnNm04anVrVVFnMC82VjB3dmtDd3FZbkpKOXFnUkV1SEtVZk5RSlg4elY0Sy9KeXFrYWhmUDNIdnRSTFhrc3RTWVAvZ1ZmVCtXcmF4a0xDZ2ZBUVhmL1JiejFiZWJ0Um8wYlpGQmVKcnc0T0RwYVZXQWhWMytEcHlMZWUzNGtXejFsdjd1UE5abUZ3bVorZkgvUHg4V0VpKzVkdlArUC9JaVNRYnpnN0VlL2RQMDN4aTUrbXdFL2kzSGZMd1M3dVEwQnIzWEt3aTdYdUgxaXlEL2tEU3hES0M5RnF1T1ZoZ3hvL1pXUEEvU052RmoveTVxRkp6ZjB6Z2RyUEJQNWZnQUVBYk1qMzB3M3ZzeGNBQUFBQVNVVk9SSzVDWUlJPSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiZmlkby51YWYuYW5kcm9pZC5rZXlfYXR0ZXN0YXRpb24iLCJkYXRhIjoie1wiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzXCI6W1wiTUlJQ2l6Q0NBaktnQXdJQkFnSUpBS0lGbnRFT1ExdFhNQW9HQ0NxR1NNNDlCQU1DTUlHWU1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnd3TlRXOTFiblJoYVc0Z1ZtbGxkekVWTUJNR0ExVUVDZ3dNUjI5dloyeGxMQ0JKYm1NdU1SQXdEZ1lEVlFRTERBZEJibVJ5YjJsa01UTXdNUVlEVlFRRERDcEJibVJ5YjJsa0lFdGxlWE4wYjNKbElGTnZablIzWVhKbElFRjBkR1Z6ZEdGMGFXOXVJRkp2YjNRd0hoY05NVFl3TVRFeE1EQTBNelV3V2hjTk16WXdNVEEyTURBME16VXdXakNCbURFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01Da05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNNRFUxdmRXNTBZV2x1SUZacFpYY3hGVEFUQmdOVkJBb01ERWR2YjJkc1pTd2dTVzVqTGpFUU1BNEdBMVVFQ3d3SFFXNWtjbTlwWkRFek1ERUdBMVVFQXd3cVFXNWtjbTlwWkNCTFpYbHpkRzl5WlNCVGIyWjBkMkZ5WlNCQmRIUmxjM1JoZEdsdmJpQlNiMjkwTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFN2wxZXgrSEEyMjBEcG43bXRodnNUV3BkYW1ndUQvOS9TUTU5ZHg5RUltMjlzYS82RnN2SHJjVjMwbGFjcXJld0xWUUJYVDVES3lxTzEwN3NTSFZCcEtOak1HRXdIUVlEVlIwT0JCWUVGTWl0NlhkTVJjT2p6dzBXRU9SNVF6b2hXakRQTUI4R0ExVWRJd1FZTUJhQUZNaXQ2WGRNUmNPanp3MFdFT1I1UXpvaFdqRFBNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdLRU1Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lEVWhvKytMTkVZZW5OVmc4eDFZaVNCcTNLTmxRZllObnM2S0dZeG1TR0I3QWlCTkMvTlIyVEI4ZlZ2YU5UUWRxRWNiWTZXRlpUeXRUeVNuNTAydlFYM3h2dz09XCIsXCJNSUlGWURDQ0EwaWdBd0lCQWdJSkFPajZHV01VMHZvWU1BMEdDU3FHU0liM0RRRUJDd1VBTUJzeEdUQVhCZ05WQkFVVEVHWTVNakF3T1dVNE5UTmlObUl3TkRVd0hoY05NVFl3TlRJMk1UWXlPRFV5V2hjTk1qWXdOVEkwTVRZeU9EVXlXakFiTVJrd0Z3WURWUVFGRXhCbU9USXdNRGxsT0RVellqWmlNRFExTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFyN2JIZ2l1eHB3SHNLN1F1aTh4VUZtT3I3NWd2TXNkL2RURURESmRTU3h0ZjZBbjd4eXFwUlI5MFBMMmFieE0xZEVxbFhuZjJ0cXcxTmU0WHdsNWpsUmZkbkpMbU4wcFR5LzRsajQvN3R2MFNrM2lpS2t5cG5FVXRSNldmTWdIMFFaZktITTErZGkreTlURlJ0djZ5Ly8wcmIrVCtXOGE5bnNOTC9nZ2puYXI4NjQ2MXFPMHJPczJjWGpwM2tPRzFGRUo1TVZtRm1CR3RucktwYTczWHBYeVRxUnhCL00wbjFuL1c5bkdxQzRGU1lhMDRUNk41UklaR0JOMnoyTVQ1SUtHYkZsYkM4VXJXMER4VzdBWUltUVFjSHRHbC9tMDBRTFZXdXRIUW9WSlluRlBsWFRjSFl2QVNMdStSaGhzYkRteE1nSkowbWNEcHZzQzRQanZCK1R4eXdFbGdTNzB2RTBYbUxEK09KdHZzQnNsSFp2UEJLQ09kVDBNUyt0Z1NPSWZnYSt6MVoxZzcrRFZhZ2Y3cXV2bWFnOGpmUGlveUt2eG5LL0Vnc1RVVmkyZ2h6cTh3bTI3dWQvbUlNN0FZMnFFT1JSOEdvM1RWQjRIeldRZ3BacnQzaTVNSWxDYVk1MDRMelNSaWlnSEN6QVBsSHdzK1cwckI1TitlcjUvMnBKS25mQlNEaUNpRkFWdENMT1o3Z0xpTW0wamhPMkI2dFVYSEkvK01SUGp5MDJpNTlsSU5NUlJldjU2R0t0Y2Q5cU8vMGtVSldkWlRkQTJYb1M4Mml4UHZadFhRcFVwdUwxMmFiKzlFYURLOFo0UkhKWVlmQ1QzUTV2TkFYYWlXUSs4UFRXbTJRZ0JSL2Jrd1NXYytOcFVGZ05QTjlQdlFpOFdFZzVVbUFHTUNBd0VBQWFPQnBqQ0JvekFkQmdOVkhRNEVGZ1FVTm1IaEFIeUlCUWxSaTBSc1IvOGFUTW5xVHhJd0h3WURWUjBqQkJnd0ZvQVVObUhoQUh5SUJRbFJpMFJzUi84YVRNbnFUeEl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FZWXdRQVlEVlIwZkJEa3dOekExb0RPZ01ZWXZhSFIwY0hNNkx5OWhibVJ5YjJsa0xtZHZiMmRzWldGd2FYTXVZMjl0TDJGMGRHVnpkR0YwYVc5dUwyTnliQzh3RFFZSktvWklodmNOQVFFTEJRQURnZ0lCQUNESXc0MUwzS2xYRzBhTWlTLy9jcXJHK0VTaEhVR284SE5zdzMwVzFrSnRqbjZVQndSTTZqbm1pd2ZCUGI4VkE5MWNoYjJ2c3NBdFgyemJUdnFCSjkrTEJQR0Nkdy9FNTNSYmY4NnFoeEthaUFIT2pwdkF5NVkzbTAwbXFDMHcvWnd2anUxdHdiNHZoTGFKNU5rVUpZc1VTN3JtSktISEJuRVRMaThHRnFpRXNxVFdwRy82aWJZQ3Y3cllEQkpEY1I5VzYyQlc5amZJb0JRY3hVQ1VKb3VNUEgyNWxMTmNEYzFzc3F2QzJ2N2lVZ0k5TGVvTTFzTm92cVBtUVVpRzlySGxpMXZYeHpDeWFNVGp3ZnRrSkxrZjY3MjRERmh1S3VnMmpJVFYwUWtYdmFKV0Y0blVhSE9UTkE0dUpVOVdEdlpMSTFqODNBKy94bkFKVXVjSXYvekdKMUFNSDJib0hxRjhDWTE2THBzWWdCdDZ0S3h4V0gwMFhjeURDZFcyS2xCQ2VxYlFQY3NGbVd5V3VneGRjZWtoWXNBV3lvU2Y4MThOVXNaZEJXQmFSL091a1hyTkxma1E3OUl5Wm9oWmJ2YWJPL1grTVZUM3JyaUFvS2M4b0UyVXdzNkRGKzYwUFY3L1dJUGpOdlh5U2Rxc3BJbVNONzhtZmx4RHF3THFSQllrQTNJNzVxcHBMR0c5cnA3VUNkUmp4TWw4WkRCbGQrN3l2SFZndDFjVnpKeDl4bnlHQ0MyM1VhaWNNRFNYWXJCNEk0V0hYUEdqeGhadUN1UEJMVGRPTFU4WVJ2TVlkRXZZZWJXSE1wdndHQ0Y2YkF4M0pCcEllT1Exd0RCNXkwVVNpY1YzWWdZR21pK05aZmhBNFVSU2g3N1lkNnV1Sk9KRU5SYU5WVHprXCJdfSIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA1LTE5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0wNS0xOSJ9LHsiYWFndWlkIjoiMDk1OTFmYzYtOTgxMS00OGY3LThmNTctYjlmMjNkZjY0MTNmIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIwOTU5MWZjNi05ODExLTQ4ZjctOGY1Ny1iOWYyM2RmNjQxM2YiLCJkZXNjcmlwdGlvbiI6IlBvbmUgQmlvbWV0cmljcyBPRkZQQUQgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyIsImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJuZmMiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJ3VENDQVdlZ0F3SUJBZ0lVTTl6WDB5S1FqOHhnVmx6Mmt0QTBnbFNQcXFRd0NnWUlLb1pJemowRUF3SXdOakVZTUJZR0ExVUVBd3dQVUc5dVpTQkNhVzl0WlhSeWFXTnpNUXN3Q1FZRFZRUUdFd0pPVHpFTk1Bc0dBMVVFQnd3RVQzTnNiekFlRncweU1qRXhNVGN4TlRFNE1EVmFGdzB6TWpFeE1UUXhOVEU0TURWYU1EWXhHREFXQmdOVkJBTU1EMUJ2Ym1VZ1FtbHZiV1YwY21samN6RUxNQWtHQTFVRUJoTUNUazh4RFRBTEJnTlZCQWNNQkU5emJHOHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUlJPVEwwZWpOZVg5V3dqRVlQaGptTnVZejkzNkJtYUQwS0VWWDBLamxocktUNTVDak96c2ZUMEhSaTd0MnVDTUdKSnBvNUdoSXdzQzFjZ2wrblBXaUJvMU13VVRBZEJnTlZIUTRFRmdRVXVMQU9uZU9vcm5kRG0rcy9UWGh1YXBtV3dJSXdId1lEVlIwakJCZ3dGb0FVdUxBT25lT29ybmREbStzL1RYaHVhcG1Xd0lJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlCT0wzUGtvbnhSM1lpNXExUUtCWlBQc1owQklUMVhXUVpxSTZoNW1wNUtkQUloQVBYRHFFeGdyUjE1L3ErNWl0Vjg2YWlVa1p2VFU4cCtnUVQ2R2x2UUQwVW8iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBYU1BQUFHakNBWUFBQUNCbFhyMEFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFIVG1sVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEQ5NGNHRmphMlYwSUdKbFoybHVQU0x2dTc4aUlHbGtQU0pYTlUwd1RYQkRaV2hwU0hweVpWTjZUbFJqZW10ak9XUWlQejRnUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpUVdSdlltVWdXRTFRSUVOdmNtVWdPUzR3TFdNd01EQWdOemt1TVRjeFl6STNabUZpTENBeU1ESXlMekE0THpFMkxUSXlPak0xT2pReElDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSU1pXWTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpWSmxaaU1pSUhodGJHNXpPbk4wUlhaMFBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWRmRtVnVkQ01pSUhodGJHNXpPbmh0Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0x5SWdlRzFzYm5NNlpHTTlJbWgwZEhBNkx5OXdkWEpzTG05eVp5OWtZeTlsYkdWdFpXNTBjeTh4TGpFdklpQjRiV3h1Y3pwd2FHOTBiM05vYjNBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZjR2h2ZEc5emFHOXdMekV1TUM4aUlIaHRjRTFOT2s5eWFXZHBibUZzUkc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRvM1lXWTNNakF5TlMweVpESmhMVFpqTkdFdE9XWXlaQzB4TWpGaU1qRmpPRFV3T0RjaUlIaHRjRTFOT2tSdlkzVnRaVzUwU1VROUltRmtiMkpsT21SdlkybGtPbkJvYjNSdmMyaHZjRG8yTWpaaE5EQTFaUzFpWVRsa0xUZzFOREF0WVRjeFlpMWtOR1ZqT1dNM01UVXhORElpSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2WmpJME5ESTVNRGN0WkRWaVpTMDBNV1ZrTFdJMVltRXRaamxsT1dNM1l6a3lZalV6SWlCNGJYQTZRM0psWVhSdmNsUnZiMnc5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBeU1ERTBJQ2hYYVc1a2IzZHpLU0lnZUcxd09rTnlaV0YwWlVSaGRHVTlJakl3TWpJdE1UQXRNRFpVTVRNNk1UZzZOVGdyTURJNk1EQWlJSGh0Y0RwTmIyUnBabmxFWVhSbFBTSXlNREl5TFRFeUxURTBWREV4T2pNeE9qSXhLekF4T2pBd0lpQjRiWEE2VFdWMFlXUmhkR0ZFWVhSbFBTSXlNREl5TFRFeUxURTBWREV4T2pNeE9qSXhLekF4T2pBd0lpQmtZenBtYjNKdFlYUTlJbWx0WVdkbEwzQnVaeUlnY0dodmRHOXphRzl3T2tOdmJHOXlUVzlrWlQwaU15SStJRHg0YlhCTlRUcEVaWEpwZG1Wa1JuSnZiU0J6ZEZKbFpqcHBibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPalkyWkRobFptTmhMVE16TnpJdE5qWTBNeTFpTWpoaExUVTNZMlF6T0dKa056QmhNaUlnYzNSU1pXWTZaRzlqZFcxbGJuUkpSRDBpWVdSdlltVTZaRzlqYVdRNmNHaHZkRzl6YUc5d09qa3pNbVpqTm1FNExXWXdNamN0TVRGbE5DMWlPVGMwTFdRNU1tTmlaR1U1Wm1ObE5pSXZQaUE4ZUcxd1RVMDZTR2x6ZEc5eWVUNGdQSEprWmpwVFpYRStJRHh5WkdZNmJHa2djM1JGZG5RNllXTjBhVzl1UFNKellYWmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG95WW1Zd056WXpOQzAxTVRrM0xUUmxZall0WW1ZM1l5MW1PR1ptT1Raa1lXSmtNbVFpSUhOMFJYWjBPbmRvWlc0OUlqSXdNakl0TVRFdE1ETlVNVEU2TlRjNk16TXJNREU2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQXlOQzR3SUNoTllXTnBiblJ2YzJncElpQnpkRVYyZERwamFHRnVaMlZrUFNJdklpOCtJRHh5WkdZNmJHa2djM1JGZG5RNllXTjBhVzl1UFNKellYWmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRHBtTWpRME1qa3dOeTFrTldKbExUUXhaV1F0WWpWaVlTMW1PV1U1WXpkak9USmlOVE1pSUhOMFJYWjBPbmRvWlc0OUlqSXdNakl0TVRJdE1UUlVNVEU2TXpFNk1qRXJNREU2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQXlOQzR3SUNoTllXTnBiblJ2YzJncElpQnpkRVYyZERwamFHRnVaMlZrUFNJdklpOCtJRHd2Y21SbU9sTmxjVDRnUEM5NGJYQk5UVHBJYVhOMGIzSjVQaUE4Y0dodmRHOXphRzl3T2tSdlkzVnRaVzUwUVc1alpYTjBiM0p6UGlBOGNtUm1Pa0poWno0Z1BISmtaanBzYVQ1NGJYQXVaR2xrT2pjNU1EWTRNekEwTnpOQ09ERXhSVVJDUlRNMU9FTXlORU5FUkRreVF6RTFQQzl5WkdZNmJHaytJRHd2Y21SbU9rSmhaejRnUEM5d2FHOTBiM05vYjNBNlJHOWpkVzFsYm5SQmJtTmxjM1J2Y25NK0lEd3ZjbVJtT2tSbGMyTnlhWEIwYVc5dVBpQThMM0prWmpwU1JFWStJRHd2ZURwNGJYQnRaWFJoUGlBOFAzaHdZV05yWlhRZ1pXNWtQU0p5SWo4Kzhic0UyZ0FBSmM5SlJFRlVlSnp0M1htWVpHVmg3L0Z2ZGZmc0t6UERJRHNJU2hJVTkyZ0FSVkZBcHhSYzRuS3BtRTFOWXRURXVHYTlSbk85aVV0UUU2L0dOUnBUZU4waUxqV2lJSnBnM0FJb0lPaU5qQ3lEd3pZRE16MTdMMVgzajdkTGlwbzZwNnVxNjlSYnArcjdlWjUrZXFiN0xHL05kSjlmdlh1aFZxc2hhZmdWTHQ1Y3FQOXg3bk1Ob0hiaHBsb2J4eFhxeHpkZk51V1dqY2VQTmYzOUYzK3UzMy91dnIrNFQzTzVOTndLaHBHVWpZYUhPdEQyUXovcHVNWnIxVG9Na0xUQWFEeW44ZmhXbitIK1VLazFuVmROT0s1VldXb041N1VNcUtidkhSSmM5ZGRzWUEwUHcwanFrZWJ3YVhWSTAyZG8vUUJ1REora0IzcnpOUnVQYVQ2M0hoYU5BVEhXY0h5MTRiemEzUGVxSEJwaWpmY2VBMlliem11K1ozWHU4M2pUdGVyM3FEWWMzMXhycXF1ZlYyM3h2VjhFdDZFMEhBd2pxUXZ6QkU5ejZMUUtoOGFIOERqMzF6YWFqMHU2VG5PQTFCLzZqVFdYeHVDQkJ3WlE0L2ViWDB0emNOVFBxVitudVZhVWRKM21vSjFwdUVhOTdOVzVqOFpnYkM1TC9XdXpKTE5wTCtjTUk2bE5iZFI4R2grMDljL05EK1Q2Y1duOU1mVUhmL012WjNNZlRPTTFtOE9wVlMwczdYdjEwQm5uZ1dXcWw2WGE5UGZtUUMxd2YwMnBNWnhtZ1FrZUdEYk50YWQ2TGFzZXN2Vy9ONnVYY2JiaDd5M1ZMdHpVcWphbEFXWVlTVzFvQ3FKV29kVDhqci94YTQzbkZGcjh1VEdZYWkzT3EvTEFrS0RoK0ZaOU9QVjcxd09xOFhxelBEQU1tOHZUcXNaVXY4Y0VEMnc2YTFXdWNWcUhVcXNhVHoyQUdzT3BzZm11WGw2YXZsNXRjVjRyaC9TdGFYQVpSbEtLRnJXaDVyK1BKWHh1ZnRqWHY5NzQ4RzRPZ2Vaelc5VTY2c2JuUGpkZXE5VUFnY2FRcURaOGJqeDJ2T0djOGFiN05JWlg0MGRqRGFhNXY0bW1lelhYbXVybjEydE5NM1BuVERXOHB1YkFtV242ZXVQM201czNIL0RaUU1xSGlkZ0ZrQVpWUW0ybytXdU50WXd4RG4xd1EvZzlhL3hhNDBPNk1haWErMldhbTh6cTZnLzZ4bnZVdjE2dkVVMXdhQ0EwMTZLYSs0QWFBNDZHNDhjYXJsVy96MFREc2ZWN05ZZFIvVFUxMWx3YWF6LzFtdEg0M0hrVGMzOCsyUEQ5NXVzMGhsTzE2V3VOeHg0eUVrK0R6WnFSMUNTaGI2aFY4MXRTRU5VL2ovUEEwS2gvTkw0Sm5HaTZWcXRhVFdNWTFJT2wzaHpXcXYrbXNWbXU4Yzl3LzhPL1ZjQXRicnAvL2RqNmRhYm5qbWw4NkRjSDFDeXdhTzVyMHczSHRXcG1xOWQyNmwrci8zMTY3cHlEVGNmWGowazZyekdVbW10SDlpRU51TGJEcUZDWXIrOTJCSlFySzRIRGdRM0FlbUFac0didXV5dXhwamtza3NLbytYT3JnQnJuMElDcWY3MzV2RllmTlE2OVpuUGZUS3NtdWNiUmRJMWxialh5cmJtNXIzbU9VTks5NnRkb3JKbTErbDQ5RkJ0cmFvMkRJQnFEb3NvRGF6ajFBUXIxejYyKzN1cWN4dENpNGZwcGcwQjZaUmJZUGZmblNXQS9zR1B1NDI1S3hkMUpKNDZLZG5MR01HcFdyaXdDZmdVNERYZzRjREp3QXZCZzdnOGVTV3JYYnVCbndDM0FGdUI2NEZyZ1JrckZneW5uRFEzRHFCM2x5aEhBbVhNZlp3Q1B3aHFPcE96TkF0Y0Ivd2w4QzdpU1VuRmIzQ0psd3pCcXBWd1pBMzROZUFhd2lSQStralFJcmdlK012ZHhKYVZpMmtUZjNEQ002c3FWQW5BNjhDTGdlY0NSY1Fza1NmTzZCL2czNEZQQXYxTXE1bllRaG1GVXJqd0krRjNncGNDSmtVc2pTZDI2SGZnSThCRkt4YTJ4QzlPcDBRMmpjdVVNNERYQUJkdy9pa21TOHE0R2JBWXVvbFM4SW5aaDJqVmFZUlNhNGk0QTNrRG9FNUtrWVhZTjhBN2cwNFBlaERjNllWU3VQQnQ0RS9ESXVBV1JwTDc3TWZBVzRGT1VpZ081aXNId2gxRzVjanB3RWZENDJFV1I1dEU4R1RQcGMrTmswMVpMRU5IaWF3UDR5NmtJZmdpOGpsTHg2N0VMMG14NHc2aGNPUTU0RzJGMG5DVHBmbDhnaE5KTnNRdFNOM3hoVks2TUE2OEcvb2F3Rkk4azZWQlR3RnVCdjZWVW5KN3Y0S3dOVnhpVks0OGdERzE4VE55Q1NGSnUzQUM4aEZMeGV6RUxNUnhoRkZaTWVBT2hOdVF5UFpMVW1Tcnd0OEJmVXlyT3pIZHdGdklmUnVYS01jQW5nQ2YzLythU05GUytCNVFvRmJmMCs4YnQ1RXp6WGllRG8xeDVHbUYweUpQakZrU1Noc0xqZ1dzb1Z5NklYWkJXQnE5bUZDYXZ2cEhRK1RhNFlTbEorZlZXNEUzOVdvZzFmODEwNWNvUzRPUEFDN08vbVNTTnRBcndRa3JGdlZuZktGOWhWSzZzSjR5UFB5UGJHMG1TNXZ3QUtGSXEzcEhsVGZJVFJtR2d3aFhBUTdLN2lTU3BoYTNBMlZsT2tzM0hBSVp5NVdUZ3V4aEVraFREc2NCM0tGY2VIck1RY2NNb3ZQZ3JnYU9qbGtPU1J0c0c0SnVVSzlIVytZelhUQmRxUk44Q2p1anRoU1ZKWGRvSlBJbFM4ZnBlWG5Sd20rbktsV09CYjJJUVNkSWdXUXRjUWJueTBIN2Z1UDloVks1c0lBeFdzR2xPa2daUGVFYVhLMzE5UnZjM2pNcVZwWVRoMnlmMzliNlNwRTRjRFZRb1YxYjE2NGI5QzZPd3NzSy9BS2YzN1o2U3BHNDlBdmpNM05ZOW1ldG56ZWd2Z09mMzhYNlNwSVU1ajdDUmFlYjZNNXF1WERrUDJFenNvZVNTcEc2OGdGTHhNOTJlUEJnck1JUXR3bjhJSE5iZEJTUkprZTBGSGt1cCtKTnVUbzQvdER1ME5aWXhpQ1FwejFZQW41eGJ6RG9UV1RlYi9SbHdac2Iza0NSbDc1R0VyU2N5a1YwelhibnlXTUthYzMwWmlTRko2b3V6S1JXLzBja0o4ZnFNeXBVSjRDckMwRUJKMHZDNENUaU5VbkYvdXlmRTdETjZQUWFSSkEyams0Ry83dlZGZTE4ektsY2VETndJWk5iUkpVbUthaFo0TktYaWRlMGNIS3RtOUU0TUlra2FadVBBdTN0NXdkNkdVYm55Rk9BNVBiMm1KR2tRUFlWeXBXZlArOTQxMDRXMTU2NGhEUCtUSkEyL0xjQXZVU3JPcEIzVTcyYTZGMklRU2RJb09RbDRhUzh1MUp1YVVia3lCdndJK09WZUZFcVNsQnRiZ1pNcEZhZVNEdWhuemVnRkdFU1NOSXFPQlg1M29SZnBWUmk5c1VmWGtTVGx6K3ZuV3NpNnR2QXdLbGVlaG4xRmtqVEtIZ3c4ZHlFWDZFWE42TFU5dUlZa0tkOFdsQVVMRzhCUXJweElHTnEzZ0ozM0pFbEQ0cEdVaXRjMmY3RWZBeGgrRjROSWtoUjBQY3k3KzVwUjJEaHZLM0JrdHplWEpBMlZYY0NSelN0NloxMHpPZ2VEU0pKMHZ6WEFCZDJjdUpBd2V2NEN6cFVrRGFldXNxRzdacnB5WlJGd0YzQllOemVWSkEydEE4RGhsSXA3NmwvSXNwbnVLUmhFa3FSRExRVTJkWHBTdDJIVThZMGtTU09qYjJIMGpDN1BreVFOdjZmUGJTdlV0czdES0d3ci90Q096NU1rallvamdFZDFja0kzTmFPenVqaEhralJhT3NxS2JzTG85QzdPa1NTTmxvNnlvcHN3T3JPTGN5UkpvNldqck9oc25sRzVzZ2JZMlVXaEpFbWo1M2hLeGR1eW1HZjA4TzdLSTBrYVFhZTFlMkNuWWRUMmhTVkpJODh3a2lSRmwxa1luZHpoOFpLazBkVjJablFhUmlkMmVMd2thWFMxblJudGo2YTdlUE00WVRYV2lTNExKVWthUFd0cUYyNmFuTytnVG1wR0Q4SWdraVIxNXRoMkR1b2tqRFoyV1JCSjB1aHFLenM2Q2FNTlhSWkVralM2MnNxT1RzSm9mWmNGa1NTTnJyYXlvNU13V3Q1bFFTUkpvNnV0N09na2pGWjNXUkJKMHVocUt6dTYzZWxWa3FTZTZTU01WbVpXQ2tuU3NHb3JPem9KSStjWVNaSTYxVloyMkV3blNZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWkt5MUZiT0dFYVNwQ3dWMmpuSU1KSWtaY21ha1NRcEh3d2pTVkowaHBFa0tVdTFkZzR5akNSSjBSbEdrcVFzT1lCQmtoVGRlRHNIR1VhU3BDeE5GQzdlUE85Y0k4TklrcFFsYTBhU3BId3dqQ1JKV2FxMmM1QmhKRW5LMG16dHdrM3p6alV5akNSSldacHA1eUREU0pLVUpadnBKRW41WUJoSmtyTGtma2FTcE9nTUkwbFNQaGhHa3FRc09ZQkJraFNkWVNSSmlzN045U1JKMFZremtpVGxnMkVrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLYnFKMkFVWUJLdkc0WEhMNEtRbGNQeGlPR0lSTEM3QXNrTDQvbVFWcG11d2RRcHVtWUlmSFlBYkRzQnNXL3NYU3NxN1ZlTncrbkxZWFEzYmxoNm93bFFOWm1xd2QyN3J1UHIzOXM4OUw5U1prUTJqQnkyQzU2eUJaNjZHVTVkMVhrWGNVNFh2N0lYUDc0TExKdUhnQVA3d2ZmeDRlT2lTT1BmZVBRdm5idW50TmYvdUtEaHJaVyt2MllubjNneDNUUGZ1ZWk5WkR5OWQzN3ZyUVhnSTNqTUQvMzBRcnRrSFYreUJIVE85dlVjdnZPVklPR2RWOHZmM1ZPRVpXOExEZmhBY3R3ZytkRnhuNTh6VVFqQkJlRU1Mc0hvc0JOYU9XYmgzQm02ZGdtc1B3QS8yd1hYNzI5d1NkVWlOWEJpZHVoUmV2UkhPWFFXRkJWeG41Vmo0WlRwblZmakYrY1M5OElIdGNPOXN6NHE2WUVkTXdOR0w0dHg3ZHdZTndCc2l2aDZBOFI1ZmIvVjROcS9uaE1Yd3VPVlFPaXc4M0w2eEd6NjRJN3g1R2dSTHgrQUZhMkg1UEQ4alo2NkFiKzdwUzVFeU1WRUlOU3E0LzNQZDZuRTRjVEU4WmprOGQrNXJkOC9BMXlhaGZGOW9lUmsxSTlObmRQUWkrT0N4OEpXVDRMd0ZCbEd6bFdQdzhnM3c3WWZDcXc0UFA0VFNJQmdEbnJvS1BuVUNmT3k0dUdGZWQvYksrWU1JNE5scnNpL0xJTms0QWIreExqeWovdThKOEdzcllwZW92MFlpakg1ckhWeCtNang5ZGJiM1dUNEdyOThZZnBnZXZpemJlMG1kT25zVmZHM3V6VmhNRjdRWk11ZXVEbjIzbytqMEZlRU54UHVQaGFNRzRBMUVQd3gxR0MwYmczODhCdjdtU0ZqUngxZDZ5aEw0L0ludy9MWDl1NmZVamxYajhJSGo0TVhyNHR4LzVWZ0l4WGFQZlZyazRJeXR1QnErZWxMMmI2UUh3ZENHMGZvSitMY1QyMzhYMW1pbUZ0cHZiNTRLSStqdW5PNjhZM0Z4QWY3K2FQaXpJM3JiSkNndDFCamhEZHFtQ0ErNGMxZkRrZzUrSVo0NUFnL2grYXdaRDEwTXcvNHNHY29CRE9zblFwdnJLVzJPSk50ZmhjdDJ3My9zZ2F2M2h4RXV6YU40RmhYQzBPOWZYUTVQWGhrKzJ1a2Jldm1HMEdIN3BqczZmaG1adWZFQXZQbk9iTy9SejFGUTIyZmdGYmRuZjU5NytqZ3E3Yk03NFRNN096dG5XUUdPV3d5UFhSNXFIeXRUM21xT0VkNHMzWEFnL0x6M1M2ZHZEczlaSFZvMTlnNzRNTE9yOXJVM2VHbGZOYnllZGVOdzhwSVFOTzE2K1lZd0tPbTEyNFp6V3NuUWhkSFNNZmpvY2UwRjBiWnBlTjkyK0xlZFlVUmNtdWthL09SQStQaVhlOFBJcmhldmc1ZXVPM1NrVExQZldSY2VtUDk0VDlzdkkxT1RzNE16c3FvWER0YUc2L1VBYkozdS9qVjk3Tjd3d0h2eE92aWp3NU5EYWNVWXZQVkkrSTFidXk5bko5YU93eE03N0pSZlVnaE5kVi9ZbFUyWmV1VWRkM2YzLzNYQ1luaktTdGkwQmg2L2ZQN2puN3NXN3BxQnY3MnI4M3NOdXFGcXBpc0E3endLSGpYUDRJR3BXdmpQZk9KUFE3RE1GMFN0YkorQmQ5ME5aLzQwdkl1ZHorczN3dmtqTmpwSThleXR3ajl0aDNOdVNoOG0vS1NWY0VhZlJtMXRXdDI2TmVHMnFmU1dnMkVlVlhmTEZQenp2ZkQ4bStIcFcyRHo1UHpudkh4RENMQmhNMVJoOUpMMTh6L3d0eHdNLytudjM5NmJXZEwzemNKcmZnNi90elZVd2ROY2REUThKTklrVkkybW4wL0RoYmVrVDlidDljVGJKRW0vbTVWSitQSmtjci9zazFaMjFweVZWemNlZ0QvWUNpKzZCVzZmWjNMMVJVZUhtdVl3R1pvd2VzZ1MrTk1qMG8vNTlsNjQ0R2E0NldEdjczL3BKRHp2NXZSMjQ4VUYrSWRqUXYrVDFDLzN6Y0tmcDlROHpscVovWVB0aUFsNFFrSU43S3VUb1QvdXV3bk5YSXNLOEl3Ukdzanc3YjFoOVluTGR5Y2ZzMzRDL255ZTUxM2VERVVZRllCM0hwMCtKK0U3ZStGM2JndjlKVm01NFVCNEY1clc3SGZxVW5qbGh1ektJTFh5OWQzd2cvMnR2emRSZ0NkbTNPeXphWFhyaDgyMjZmdkxsZFl2TkdwTjNMdG00V1ZiNFhNN2s0OTUwV0h3c0tWOUsxTG1oaUtNTGxpVDNrOTArM1JvUnR2Zmh4RTVOeDZBVjI1TlArWVBOb1MxOGFSK1NodWRkMXJHRDdWbnIyMzk5Y3BrV0tzTjRDdVR5YU13VDE4UmFnT2paTFlHcjlzR1YrOUxQdWFOUTFRN3luMFlUUlRTLzBObWEvRHlyZUdkUnI5Y3NTZjBTU1ZaTmdhdjI5aS84a2dRcGk0a09XWnhkdmM5ZWxIeW04VkxHenJzZDg3Q3Z5ZVVjUXg0MWdnMTFkWE4xdUNQZjU2OEVQTlpLK0cwSVZudEpmZGg5S3pWNmV0dGZYZ0hYSnZRUEpHbGkrNE9rMmFUUEhkTmFFZVgrdVcycWJEMVFTdnJNK3d6U3BwYmRQZk1vZS82djVqU1ZQZXNFV3VxcTd0dEt2M043WXNQNjE5WnNwVDdNRW9iQ1hUUERGd1VhVzdQd1JxOE9hWFRlS0lRYjBrV2phNFlxOG9uaGNqbUZpUG92clk3dVJidzJPV0RzZEJyREIvWUhtcU9yWnkvSm4yQ2MxN2sraVg4MHRMMEJVbmZ0NzAvL1VSSnJ0aVQzR2tNOE90cmgzdDVEdzJlZmk4OGV0S1NNR2lubFZaemF2Wld3LzVnclJRSWE3V05vcjNWTUNleWxXVWRyUGMzeUhJZFJtbnJWdTJlaFl2djYxOVprdnhUU3ZYNnFKUzJkS25YRmhWZ1hVTFRjRmFyeTV5ZjhEdTZZd2IrSzZGai9zc3BFeitUQmtLTWdrK21QTStHWVVIWlhJZlJlU2xoOU5sZGNXdEZkWmZ0VGwvVExPMDFTTDMwbU9YSnYvQlpOZDhsRGNtK2RIZnkrbXFYNzA2ZUh2R3dwV0VKblZIMDgrbmtBTzkwbWFWQmxOc3dXanVldnY3Y2x3ZGtMYXVaV2hpeW11UlgyMWlQU3VxRnMxUG1FdDJjd1VUd1U1ZUdacnBXMG40L3AycGhJbXlTYmxiaUh4WkpvdzNYVDhBeE9lOVB5MjBZUFRybEliNXpGcTZKTUlJdXlXVXBNNmxQV3phNkc0aXBmMWFNd1F0VFJsMWRsY0h2UzFLdGFOY3NmQzlsN2d3NEFUYko5MVArM2ZJK3hEdTNZZlRMS2JXaWEvWU4xaExyVis5TGJwTmZWSUFUUjdUWlFmM3pKeHZoc0lUaDIvdXFZUW1hWGlxUTBrU1hNcm0xN2x0N2s1c09IN0lrREY0YVJUOUpXZlEyNzgyWHVRMmo0MUwrNGE5TitRK0xZVThWZnBiU0RKTGxoRVBwYWF2U3AwQmNzaXQ1L2xHM0hyVXNlUmgycFkyVnFlZHIzazRhR0RIc2RzNG1UK0RQKy9ia3VaMTJtZFkrMnMvTnd0cDE2MVJ5KzNtLzUwNDhlamw4NTZHOXYrNkhkOEJIZHZUK3V2TjUwRVEycjZjeUNmOHI0MDBJc3pSUmdGZHNDTFdpcEhlZE03WDBFWi9kU3VyWDJUMGJhajN0dUdRbmxCS2FGczlmQTIrL3U2dWk1ZDU5czYxWE1kK1kyNmQ1a052aXIweVpNWDduUE11dngvRHpsREwxZXhYdnhZVnNBbkIxcENYdHh6TjZQZXR5dWtULytvbXdNc2xMMXNQeDg5UzZQN1FqN0tuVFMyTkFNU0dNTHR2ZC9pN0EvN1V2ck5MUTZpRjczR0o0NURMNDRRRDFEZmRMMGxZMVl6bnZlODV0R0MxSitZZlBjbVh1YmlYTktnZFluZHZHVW1YbC9OWEprMFZiT1ZpRjVXTWhmRTVhMHQ1azZoOGRnTC9Qb0hieGhCWEo3OUxUNWhBMXF4SUdNcndzb1lueFdXdEdNNHlTNUgwVmh0eUdVZHEvK3dDTlhmaUZxYlJDNWZ3ZGpYcnZwQ1hKemJxOWNQczB2T1MyZVg0dXU1UzAvTStlYXZwaXJhMThLU1dNemw4RGI3MHplVk8rWVpVMCtqYm5XWlRmOHFmOUFDNGJ3RmUxTkNWd2RnOWdUVTdENjdyOVladnJ0TjFmdXpWUlNGNFo1UnU3T3crL0grNFBDNFcyY3NSRVdLOXUxR1R4Qm1JUURPQmp1ejFwL3lGSlExaGpTdHVMcFJmYm4wdnptYTJGOVJxZmQzTjZIK1pDUEhGRjhoYmg3WXlpYXlWdEplL25yTzN1bW5rMm52REdOcTBySUE5eTIweTNQV1dKblVFY0twMDIrcS9mQXk3Kyt5Qzg0NjdlWC9lbVNLTVlkOHpBbjI3ci9YV3plbUQzV3hYWXZDdXNZSDlUQmlzdE5Fb2FSYmV2R2hZTzdzWVhKK0dWaDdmKzN0Tlh3VjhXQm10ZVlkYldKRlFoMHBZZHk0UGNodEhXbEFkRjJqSkJNWXdCcDZSMFJ0L2E1NGZldlRQdzFaUlZJZkxtUUcyNFhrOHYxQWk3RGw4NkNaL2QyWjlnWFZLQWN4T2E2TDY1cC91NVREODVBUC92WU92ZjYvVVRvVGIyelM2RExtOG1DckFoNGFsOXQyRVVSOXBjb3NjTVdEdnlTVXVTUjdyTTFnWnpYcFRpZXYvMkVMTHRPbEFOVGRjN1owUHcvR2gvOG1LaldYbnFxdVNmODZ2M0xXenR0Ry92VFg2VCtjdzFveE5HSnl3T2dkVEtUek91OVdZdHQySDB3NVExbWs1WkVqbzM3eHFRZHdwbnBTeFFlY09Cd1ZoZFhJUGwvMndmekNrS2FkSjJZdjJyQjRXUExHeGFEWCsrYlhnNzlodWxiVGx6dzRDdFBOT3AzQTVndVA1QStnL2ZPUU8wWEVqYU5oRkpTOEpMZWJKaUxONmVPaXZINE1rcGIvaUd5ZWtKVzBYc3FXYmZINWkxM0liUmRBMitrN0tzeUl2VzlxMG9xVTVZREk5UGFUYTgzTDRPRFlGelY2VlBSTS9hS0d3cnNiaVFIUGhYN21sL1pZdEJsZHN3Z3ZTaG9xY3RDOHVGeFBiaWRjbmYyejREMzdWbXBDRVFlMXVIcDY0S3RiTmhkdmFxNUdIencvQ21OdGYvZlpkT3BzL1JlZTNHL3BXbGxZMFQ4SnNwWWZUNVhhTTFKRlhEYWUxNGVyOW9QeXdmQzRFMHpKSldvdGhiVFYvaFBDODZDYU9CVzdSbTUyeDRvQ2M1YTJWeUcycy92R1pqY3RQRmJBMCtHbUdGYTZuWG5yNDZlWVJYUDhXdW5XWHBDU3ZnY1FuTi9WL1kxZitSazFub1pEVGRBUHk0SGVyRE8rQUZhNU8vLzNkSHdUazM5WDkyOHVPV3c0VXBPMnQrYVhKNEpsVnF0S1gxMS96MmJYQkZENXVRbG83QkQwOEpOYUZtVDFrSnE4YUhiM210TWVCTkNTTVJhOFRadGlVTHVhNFpRWmdRbDlaM2RNSmkrT3NqKzFjZUNPMjY3emttK2Z0VE5YakhpTzdGb3VHeWZnSitMYUgxWWRkczV3dWp6dWRBRmI2ZUVHNkxDdkNNSVd5cSsvME55U3U0ZjM1bi91Y1gxZVc2ejZqdWY5K1ZQc3k3ZEJpOE1LV1cwa3VMQ3ZDUHg2UlA4UHZ3RHRqcVJGY05nZk5YSno5RU5yZXh2WGczMHBybTArWTY1ZEZqbHNQckUvcStEMVRERWsvRG9wTXdHdGl1OXExVDhONTUvbFBlZGhROEorTWYxRVVGK01DeDZYTWViam9JNzdKV3BDR1I5dkJQVytCMElmNWpUM0lmeVprcjBoY2x6cE16VjhBbmowL3VqN3ZvbnVRVnpmTm9LTUlJNEwzYjRacVVqYmJHZ0hjZEE3K1hNQ0psb1RaTXdNVW5wRS84bTY3QksyL1AvK3E2RW9UZGRaTzJjTWh5MnNKVURTb0pRVGRlZ0djTTBJVDNib3dCcnpvY1BuRjg2Q05yNVFmN1F3dkxNQm1LWmpvSXpRRi9mSHNZWVpka0RQakxCOEUvSFp1ODJHQTN6bHNGWHprcGZYSXJ3QnUzaGNVcnBXR1FWaXY2OG1TMjB4YlMrb216YmdISjBxT1h3UmNlSEpybWtyYUsyREVEdjc4MS81TmNtK1YrQUVPalc2ZmdwYmZOLzUrMGFUVjg0K1RRTVpqMHpxTWRweTZGangwSEh6b3VySVdYNWwxM2g5V1RwV0dSTnBRNnF5YTZ1aXYzaG9keUs0OWRQdi92NHlCWlhBaHpwQzQrQVM1NU1Ed2laYkwrZ1dvSW9uNXZPOU1QbmZ5WERlQ1dkWWY2L2o1NDFlMWhFRUhhM0ljMTQvQVhSOERMTjhEbmRzSWx1K0NHL2ZOdllieCtBczVlR1FaRS9HcWJxNFAvNjczdzdpSHFhSlJPWEF3UFN4amh0VzA2ck5LZHBka2FYTG83REU1cVZpQU1OLy9nQURWakxTbUVrTmxiRFR0Ukh6NEJKeThKSzhXY3NTSjV0Zk5HazdOaHEvanZEK21xTFoyRVVXNmE5Q3FUc09jMitPQ3g4MjlCdm00OHpHeCsyWHE0ZHpac2MzelR3ZkRPWTE4MXZHczViQnlPWHd5L3NqVHNTOVJKRmZHak8rRE5kdzU0aDV2VW9iUmEwWmQyOWVmbi9mTTdXNGNSaEcwbCtobEdiejhxQkUyU3hZVVFQdDM2OFFINHc5dGh5NUFNNDI1bEtNTUk0Ti8zd0hOdWh2Y2RDdzl1YytmWGRlT2gxbk4yRDVZMm1hN0JYOTBCRjkrMzhHdEpneVp0b3VzWCs3UTB6Vlg3d29aeUcxczh4UjY1TEx5QjdOZGVZY2RudEx0MERmajR2ZkRXTzRkLzROTlE5UmsxdS9FQUZMZkFwM2YyOTc1YkRzTHpiamFJTkp4K2FXbnl1L3hicHVENmxGR3R2VlFsTElXVEpPOXpqcTdlQjgvOEdmelBPNFkvaUtDek1Ncmw2a2Q3cS9DNm44TnpiODUrODZtRHRkQTNkTjZXME53bkRhTm5SeHk0MEN4cGlEZmtkMXVKSy9iQWhiZUVscDErQmZzZ3lOR1lrNFc1YWg5czJoSkdyZnpoaHVUNUVkM1lXNFYvdVRlMFVTZU44SkdHeFROVDV2SDBPNHl1MlI4bWZoN1hvcG5zbENYdzBDWHczd1BlejdLM0N0ZnVoNjlPd2xkM2h3RWdvMmhrd2doQysrdmx1OFBIU1V2Q2ZJVHpWb2NmMms0ZHFJWkpmWi9mR1g2QTlnMWd2Zkd1R1ZqVDRnZjducHdHNXZhWjFvdkwzcEhUWDk3SjJlVEZjcXNEMml4enlwSXcvNlZWdVcrZGl2UGcvL1JPK0I4SkF4bk9XTm1iTXQwNUV3WWlMY1NxTVNnVW9GYUQ3Yk53enpUOGJDbzA2dy9nNDZQdkNyVmFlei8xaFlzM3Z4TjRiYmJGaWVPdzhWQlRPbmxKNklqY01ESDNnelAzL1ZuQ29vOTNUSWRmdU92MnczVUhobS9TbVNSbDREMjFDemU5ZXI2RDJxb1pGUzdlWEFCU2x2N010L3RtNGJMZDRVT1MxSC90RG1BWTZqQ1NKTVhWU1JqbGFwNlJKQ2svaG1iVmJrbFNmclViUmpWQ1A3NGtTVDFuR0VtU29tc3JqR29YYnFwaE01MGtLU05EdlRhZEpDa2YyZ3FqdVhsR3VkalBTSktVUHc3dGxpUkZaeGhKa3FKem5wRWtLVHFIZGt1U29qT01KRW5ST2M5SWtoUmRKME83bldja1NjcEVKNlBwUm1wWFdFbFMvemkwVzVJVW5jc0JTWktpNjJRMFhUWExna2lTUmxjbllUU2RaVUVrU2FPcms2SGRocEVrcVZOdGRmRjAwbWRrR0VtU090WHpNTExQU0pMVXFaNkhrU1JKbVhCb3R5UXBPbXRHa3FUbzNNOUlrcFNsdHNZYk9JQkJrcFNsdGlveWhwRWtLVHFiNlNSSjBUbUFRWklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZBd2pTVkowaHBFa0tUckRTSklVbldFa1NZck9NSklrUldjWVNaS2lNNHdrU2RFWlJwS2s2QXdqU1ZKMGhwRWtLVHJEU0pJVW5XRWtTWXJPTUpJa1JXY1lTWktpTTR3a1NkRVpScEtrNkF3alNWSjBocEVrS1RyRFNKSVVuV0VrU1lyT01KSWtSV2NZU1pLaU00d2tTZEVaUnBLazZEb0pvMXBtcFpBa0RhdTJzcU9UTU5yVlpVRWtTYU9ycmV5d21VNlNGRjBuWWJRM3MxSklrb1pWVzluUlNSanQ2N0lna3FUUjFWWjJkQkpHTzdvc2lDUnBkTFdWSFlhUkpDbExQUStqZTdvc2lDUnBkTFdWSFoyRTBUYWNheVJKNnN6dDdSelVmaGlWaWxPRVFKSWtxUjE3S1JXM3QzTmdwL09NZnRaRllTUkpvNm50ekRDTUpFbFp5U3lNcnUvd2VFblM2R283TXpvTm8rczZQRjZTTkxyYXpnekRTSktVbFl6Q3FGUzhDOWphYVdra1NTTm5GL0RUZGcvdVp0WHUvK3ppSEVuU2FQa09wV0sxM1lPN0NhTnZkWEdPSkdtMGRKUVZocEVrS1F1Wmg5RjF3QjFkbkNkSkdnMjdnVzkzY2tMbllWUXExb0JMT3o1UGtqUXFMcWRVbk83a2hHNjNIZC9jNVhtU3BPSFhjVVowRzBhWEFnZTZQRmVTTkx5cXdCYzdQYW03TUNvVjkyRHRTSkowcUc5U0t0N2Q2VW5kMW93QVByT0FjeVZKdzZtcmJGaElHSDJKTUdKQ2tpU0FLZUN6M1p6WWZSaVZpbnVCZiszNmZFblNzUGxjdTV2cE5WdEl6UWpnSXdzOFg1STBQTHJPaElXRlVhbDROWERWZ3E0aFNSb0dQd1d1NlBia2hkYU1BTjdWZzJ0SWt2THQzWE9MSW5TbEYySDBhZUMySGx4SGtwUlBPNEIvWHNnRkZoNUdwZUlNOEo0RlgwZVNsRmZ2bzFUY3Y1QUw5S0ptQlBCKzRNNGVYVXVTbEIrN2dJc1dlcEhlaEZGSXhMZjE1RnFTcER4NU42WGl6b1ZlcEZjMUk0QVA0SmJra2pSS2R0Q2pRV3k5QzZOUU8vckxubDFQa2pUbzNrS3B1S3NYRitwbHpRamdFOEQzZTN4TlNkTGcrVEh3dmw1ZHJMZGhGTWFZLzNGUHJ5bEpHa1IvTWplYXVpZDZYVE9DVXZHN3dBZmJQTHJyQ1ZLU3BHZytUYW40MVY1ZXNQZGhGTHdCMk5iR2NRWENSa3lTcEh5NEYvaWpYbDgwbXpBS0hWcXY2S0FNQnBJazVjTnJLUlh2NnZWRnM2b1pRYWw0Q2ZDeERzcGhJRW5TWUx1RVV2RmpXVnc0dXpBS1hnVnNhZlBZTWV4RGtxUkJ0UTE0YVZZWHp6YU1Tc1U5d0c4QTAyMmVVY05Ba3FSQlV3VittMUp4UjFZM3lMcG1WQjlkOTVvMmo2NDMxeGxJa2pRNDNrU3BlRm1XTjhnK2pBQkt4ZmNTSnNTMll4eVl4VUNTcEVId1JlQ3RXZCtrUDJFVS9ENXdkWnZIVG1BWVNWSnNQd1orY3lHYjVyV3JmMkVVMXE1N0puQnJtMmM0b0VHUzRya0wyTlNydGVmbTA4K2FFWlNLZHdLYkNQdGZ0S09RWVdra1NhMkZ5a09wZUV1L2J0amZNQUlvRlc4a0JOS0NkZ1dVSkdWaUduZzJwZUpWL2J4cC84TUlvRlQ4TnFISmJpcksvU1ZKclZTQlg2ZFUvRnEvYnh3bmpBQkt4U3VBNTlQK0hLUTYrNUVrcWZlcWhNRUtYNHh4ODBLdDF0Nnp2VkRJcVB1bVhIa3E4Q1ZnV1RZM2tDVE5ZeHA0UHFYaUY3SzRlRHM1RTY5bVZGY3FmaDA0RjVqczRteHJTWkswTVB1QloyVVZSTzJLSDBZQXBlSzNnRE9CclIyZTZXZzdTZXJlM2NDVGU3MDNVVGNHSTR3QVNzWHJnU2NBUCtqeUN0YVNKS2w5UHdHZVFLbjQvZGdGZ1VFS0k0QlNjUnZ3Sk9EVFhaeGRyeVc1RllVa3Bhc0FwMU1xM2h5N0lIWHhCekFrS1ZkZUE3eWRzRlpkTjZibnpoMnN3SldrZUdyQW00RzM5R09KbjEvY3RJMmNHZHd3QWloWG5nU1VnV01XY0pVcFFpQk45S1JNa3BSUGR3Ty9SYWw0YWI5dm5JL1JkR2xLeGY4QUhnNThhZ0ZYV1V3SW9sazZuOU1rU2NQZ3k4RERZZ1JSdXdhN1p0U29YQ2tCN3dZMjlPQnFOUnlKSjJsdzllb1p0UXQ0UGZEaGZqYkxOY3QvTTEyemN1Vnc0RjFBS1haUkpLbkhldjBtK1JMZ0ZYTUR3NklhdmpDcUsxZWVScWdsblJxNUpKSTBhRzRDWGtPcCtLWFlCYW5MZjU5UmtsTHhjdUNSd0N1QnpQWmtsNlFjMlFXOEFUaDFrSUtvWGZtc0dUVXFWOVlBZndLOEdsZ1R0ekNTMUhkN2dmY0M3NkJVSE1nMzU4UGJUTmRLdWJJV2VDM3doOEM2dUlXUnBNeE5BaDhFM2thcHVEMTJZZEtNVmhqVmxTc3JnTjhtMUpaT2lsc1lTZXE1MjRCL0FENUVxZGpOQXROOU41cGhWRmV1akFGUEExNEdYQUFzaWxzZ1NlcmFMR0VKbnc4RG15a1ZaeU9YcHlPakhVYU55cFdOd0F1QkZ3Qm40QndqU2Zud1BlQXp3Q2NIWVloMnR3eWpWc3FWbzRCZkI1NE9QQmszOVpNME9BNENWd0pmQVQ1SHFYaHI1UEwwaEdFMG4zSmxLV0dWOExNSSt5azlEc05KVXY4Y0JLNG1CTkNWd0Rjb0ZmZkZMVkx2R1VhZEtsY1dBUThESGdHY1JsZ1g3MlRnV0xwZlBWeVNxc0R0d0JiZ091QjY0RnJnZWtyRmd6RUwxZytHVWErVUt4T0VsY09QQlRZQzZ3bHI1QzBIVnM0ZHRRYjdvcVJSdFhQdTgxNWdIN0NkTUNIL0hzSU8xbHNwRlVkMm9lYWVocEVrU1ZuSjUzSkFrcVNoWWhoSmtxSXpqQ1JKMFJsR2txVG9EQ05KVW5TR2tTUXBPc05Ja2hTZFlTUkppczR3a2lSRjkvOEJSenNDMGlhZ3hCMEFBQUFBU1VWT1JLNUNZSUk9IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIwOTU5MWZjNjk4MTE0OGY3OGY1N2I5ZjIzZGY2NDEzZiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJ0cmFuc3BvcnRzIjpbImJsZSIsIm5mYyJdLCJmaXJtd2FyZVZlcnNpb24iOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMTEtMTAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIyLTExLTEwIn0seyJhYWd1aWQiOiI3ZTNmM2QzMC0zNTU3LTQ0NDItYmRhZS0xMzkzMTIxNzhiMzkiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjdlM2YzZDMwLTM1NTctNDQ0Mi1iZGFlLTEzOTMxMjE3OGIzOSIsImRlc2NyaXB0aW9uIjoiUlNBIERTMTAwIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoyNTYsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNMRENDQWMrZ0F3SUJBZ0lFWlAvZ056QU1CZ2dxaGtqT1BRUURBZ1VBTUhjeEN6QUpCZ05WQkFZVEFsVlRNUXN3Q1FZRFZRUUlFd0pOUVRFUU1BNEdBMVVFQnhNSFFtVmtabTl5WkRFWk1CY0dBMVVFQ2hNUVVsTkJJRk5sWTNWeWFYUjVJRXhNUXpFVE1CRUdBMVVFQ3hNS1QzQmxjbUYwYVc5dWN6RVpNQmNHQTFVRUF4TVFVbE5CSUVaSlJFOGdRMEVnVW05dmREQWdGdzB5TWpBMU1URXdNREUzTVRkYUdBOHlNRFV5TURVeE1EQXdNVGN4TjFvd2R6RUxNQWtHQTFVRUJoTUNWVk14Q3pBSkJnTlZCQWdUQWsxQk1SQXdEZ1lEVlFRSEV3ZENaV1JtYjNKa01Sa3dGd1lEVlFRS0V4QlNVMEVnVTJWamRYSnBkSGtnVEV4RE1STXdFUVlEVlFRTEV3cFBjR1Z5WVhScGIyNXpNUmt3RndZRFZRUURFeEJTVTBFZ1JrbEVUeUJEUVNCU2IyOTBNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVMZjJoNjhHelNFV0VvcDIyUkx2S0Mxd05BdFVJdG12NFRmMk94SXBCMVhRZTlKUDJuUlBDbWt6emZRVVluT2s5SjlQZ3ZqRWk2NGJ1VUtQcnFkMDNNYU5GTUVNd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0hRWURWUjBPQkJZRUZMaFJvNHVFMm1uSi9WdEdmQitPTjByQVF6UVpNQXdHQ0NxR1NNNDlCQU1DQlFBRFNRQXdSZ0loQUw3MTlLMGxTNmpkb2xsaUk4aDRseUk4dGdGRmp2NE5QZzFkZElGK2JIbVNBaUVBMHRpMWFQMFNjcHJtQm9MYUdQeGR1VGhmN013bWlRYlRtMjdOZ2FoUnZLZz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSHNBQUFBdkNBWUFBQUREMkxXZUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFDeE1BQUFzVEFRQ2FuQmdBQUFBVGRFVllkRk52Wm5SM1lYSmxBRWRKVFZBZ01pNDRMamd4Z2N0aUFBQWNIMGxFUVZSNFhzVmNpWHRXeGJuM2orbXR5cG9RRXJJWlpSRkJGS3U0VkcydFZXbjE2bE9mZWl0WWJkVmJiYXRkckxidXl1SkdyVW9yZGFHVjdCdUJFUFlJQ0dRaGdaQ3dFN0oveVh2ZjMrK2RtWE8rc09TTGliM3ZrL2xtenB5WmQ5NTlsbk5PTHBJaEVTUmtBWkl1dmg0TURTVWo0WlgrRExyQi9QV29JTjdQbHhXSTA1V1NBRzFBaDcrdEVLNEhZNVVBZHhscWg5MysycUI0Z01yUU9VbzlicCtUbG9IQWgvMkNGMDI4OExtRFlaZXB3a1hET3cyNUlZY3I2MnVEb2lFbVpZaDVFdG9CbDE4SUJyU0xLVEhlUDVSZEdwUkVWSGNlYVhpV2dsQmRSY1NyNHgzSkc4VVl3ZU1qdUlMeDQ1TUM2eDNOVUx5WGxZTFA0L3dadWJIK0tVS1NzcTA4Q2dRY09JN0J3RmQ1ZkY2NDNwdWlIaW1NaGNhdW1lL0hYSCtpNnhnZVZtSkVTd1RYRUJtTCtIRUNCZjJXNDRhMlo2NmdPY3hzN0JERHFVQ2EzRmdKMXNSb0R4Q3JTeUxCUzlJb081ZnNMd1FXeGgxeTl0WGtrYVNLTExSRDVoUnE0SW5UZk1oWUkzNk1oM2J4cHVjQjE0dkE1dWltNDBWZFRXaTROanE4TUJXWXg1Uk9RTm5UaFNZeFdoeU5nZitVSXMrRkFmampDZzdnQ0dBV0wzTklPQWhvaWVnTW9CWEVtYUp1NHVBODJ4TURzSUg2VGh5WHJ2MTdwYnRoMzRpcHAzRS9jN1R2YW1xVTB3MzdOVFZLb3FOREJvSGFLeUVBeXVkZzVMeWc3V05HbE1DMUtpWXc3TEtCOW5acCsreHoyZnZDODdKenljOWt5MzMzU08yaUc2VG1waHRrNHgyM3kvYWYzaS8xVC81U21sY3VsOFBsWmRKOStDRDdlb015eFdBMFh4T24rV3VDSWpRNmJVNTJwQnJOUGtIRG10dW9KcHZvSG5wRmRMQ0tGakY2Mmk1Q0gyOUZTSjdkcG5lV1MxSGF4VktTbTNuQlZNdzhJMHJaMDZRMEowUEtjcWN6TDgvT2xNcjVzMlQza29mbDRLZHJaV0N3SCtNNm9rY0czeTVTaUFHdmNkSGRJeTBmcjZaQ1MyZWtrNGJTdk9sU25LTjBhQTRhakxaTUxXZEtXYjdTakh1Z1VXbXRYakJYOXZ6bVYzSjgwMFpGRnZHZk1vRWpnaWx5WUdCQVpicVM0MVhmdkVEVDFiSmgwWFd5Y2RHMVVuM05mR24rYUpVT2EyUDdvV0hVS0I4cC9VTDJ2ZmlTTkM1L1V3MUhPWGVHUDlySUUrWnNHRi9jc3BwV3JwU3l0TWtVeW9WU3VVdDJIVE9BdkN3cHlwbnVoSjhsSmRPblNzbTBTNlc4SUYrYVhuNUoranJhT05ySVlCWWN3aG9JMWIrQi9pN3ArT0lMcVZwd2hSUk5tMHpGbGVWbUJSbzRKbEp1T3Vrcm13RmFqRFlxWGE4cmNyS28rT0tNS1ZJNDdSS3BtRHRIbWxhOEpnT25UbExJWGpaakJsVlF6Nkdqc243aGxWS2FtU1psV1dxVWtJZlNYSktUSnNXWlUyWER6WXVrOS9CaGJXeWNXdEF5M2x0V3ZDbjF2MWdpZTUvL25SeXJYczg2M2g0bGdSY1pRa01hSVZCbHIzcGJpcWRlVEEvMWlaNHlMRUZZd2F2UGtTRFFvbHhsa0o2dXdzNVdKdE1teU1ZYkZrbDc4Yjh3MkFVQjVFUVIzT2pzN1R3cGU1NTlSa296SnFnM0s3NHdYam85RjRZWDZySkJPNVNlM0FhS0w4bWJJYVY2WFpLVGJia0t2K3JLT1hKaTYyYU9GZm5ZMktIMWcvZWxaT0xGVXB5bk5LaUNJWThTbFEyTlUya3NuUHB0T2Z6NXY2MnhHOVpQSzRjK2VsOWEzbm1IU3U5cFA4VDcvdDVvUUpWOWJqanc5a29wVHA5QTRVQklDTWNRRU1OZ1hub1FLQlFlQ1RLcTgvWHdLdVJrVG9WWm5xTjlnVE16UTZwbTVVckxYMWVSOElqeXlQZ0lyQWRqL2JhT1VwUEh2RnVVcGxFQzBVUnhWV1NESGxXeVUxeFJ0dFpuVEpKQ3BSK3BhTW9sS3N4THlBKzhHSjdrNlNKUGFnendlT1I3Ly9nc3h4czFPQVVFaVBFejBOZXZYajJYaG01R1pWRUZNcXhRV2tGSDBZd3A2Z0RYUzJLdzEzVlZZL084OS9kSTU0NHZwYSt0amFIZHhySjdvNEVSbFEwbE13em02VHlYcnhZNWZiS3NtM3lwRkUrR0FMOGRCQmxQVUFRRk8vVlNlbkVoaEsvS3FLQjNtNEtLRWI0MEtwVGx6NUNPd21JM3FrS2czK1k2NHpmYUhyV3RlcGZLUW9pMmFPR0VwZEVEaHJRdS9kdFNlZldWc3VzSlhZaXRXQ2tIUC90RWpoWitJWWMrK1ZpYTMxb2h1NTU1V2piZWZZZlNNSU8wQXhlVURCN0xaMS9HRUc0MHBManhjbzBzYzk3Ry9pZ2JNMjFyMXVoVU0xSEhtY0hwcGp4UERTczdMY2lpUEF1T3BEeE1ueUJIMXExakh4ZzNrQ0drbTRKdFVVYXFNSWpMUmdNakt0c3Job1NwWW5ZLytZU2NXRjhqSGVYbGNxeXNYSTZVRjUrVmpsYVVTRWRaa2JTdVcwdFBxVkxodzBqOHZBbWNESzBPYjlYTWZCbm9QdTE0QUdOR1F4QWVmNVRSL2w2cG1GT2docWVHb2taSW11RFJMcStjVnlEdG4vOVRoanA3WkZDOWFTaWh1R0Fvc0JMTkV3bGR3ZmYzeVVEUEdSazRjMXhPcnErVkw1OTZRaW9LY3FRNGJaSWNlTzl0Rzk5RG9PUDhBTnhvUmtwOWV4WWpQbW9XemlmUGxDV21EMVVzalV1TkUrc2FpNElxRXpXRW11c1hXQ2ZTNFdoeEdkQWhPYWtFL0tuQ3lNcUdJSlVZRUFKbE42MVl4dnVEYW5sSmduRkE1aUhjWWRDcTRScWVBNmE0ZUZLR0dkckpmS1o4OWV5dkErMld4ejNMQkhmd0g2dWw5REpNSTZaY1JweDhsTE9rOHFxWjB0VngyTkZrWGhEd2Nadm1GbmdPRjVYUHUzbzUyS2Y4dnMweVdyQWZXVHVidjNNQjIrUEhEUmpuLy9EYVR5aERUaFZxM09DNzVES05RbXFzVUhSRkxuWUdtTGMxVjk2UUh5b3VqbWdEcmdoZE5FYjRTUjFTbUxQVkF2M0t0U0JUR3AyeVV4VUVBQUxHR3ZORVhTMFZ6cWxCUXhrV0tKZ2VTdkp5cEhiQlBCbnM2WEVkRExjSnpTbEkvK29mZTlRTVQrbXBoRWRBU0JDZVJvMGpHcTdKdkNhMHB4eHMwck42RDc3czJ1RVBXNWhJUVg0N1l6U01ESWFEZVAxMGcycitERXJ0M2JmUkdHSGdtTFlneDBJWXFQSlJQa09uTVZVdXAwZzFDTXpsYUxQNWp1OVpkeUoycTNPWHJCQVo4bWdnSmMrR1FJdGR1RG53MWpJVkRGcFFTa2x3TG84bWtFQVVCdVhnM3orVTBuU2Q5LzFxRk1wVy9KVnpaa3JIaHZLQWc1bEQ1OUZ1V255bkdZZTI5M1FoWVJFMjJPY1hObENjZVRGQks0bUtQeTRCYUFnbVROODI4aUlWcGg5MEJQQjdZUzkranUyNkh0RnBybW9tb2xsRUs2ZWRyQXpaZXQ4OVVubnRWYVpzVGJnSEwwY3FtNVVuSGNVNmR6dGFBSEY2UWptcVNnbEdYcUNwVUgxQ0tOcS84ZzAzaGhLQmdrOHhDRUpqdlJHTEhEYWFPTjBwWmJPeFVOSDVXa002UWpqbXJzcVpPZEt5NmoyMjg3N2w4VmhJRzVRTnR5MmlsMkFxb1BGeFNsQnYwSVVnaGUzSG83SmRmd2YwWXJUU090YTZ0bEVMQUs2ak9oOFlMZ2huTlhMOWgvcGs1Mk1QVTdsY256aUZZZ3JDNHZiNGxrM1M5TmVWVWpobEVuYzNaVE0wU3VWTjVTSVdhZWZERHlxbWlBL2daSXJ4TkZwSUxZeXJvam52NUdYenFCRmdaRndZUEdIMjY1VGUzU04xOS95UWh3czJsOW1LdXJ3Z1YvWXZmODF4NUZhZ0xnRU5sTEQ1L3NWVXRqYytlamVpZzI2ek9zcEtJbUhvSHd3RzF3SDhCUnM1K2pXbmFqUXNlb095Wm01Y2xrY0ExOGlNaVFYQ3NTMWJwT2E2T1ZReXBpM1FDdU1zeXBvbWRYZDlUL3BWRG9PblQwcnBuRngzd0tON2ZuZzlqRmREK1liNWMrWDR4bzJHamo5ZUhnWTJUSFNkQ3FTMlFITUoyeVN2N0NUQUFnaDVHRnNMV29FNkpJclNxT05LdU83TzIzVmZPY21ZMHdURmxSU29JUzB6M0xZMGM4Z2NIc0RlNTMrdmN6VkN2ODUzMmljSVVYRlVYVDFidDAybmd4RjZwZHRGbEhrRGhDcWoyelpXZE44cDJqY1lFYXk5TmRleUx2Z2FYbnhCQ25WYlo4b3piNFZYRjA2K1dOby9XYU9OMVp3VC9kTDQyaHM4dkNyTnRvTWRXN1JteUxyTUNkTHczQjlWR09BSStFMm1FVTJPeGxIQW1KVnQ0K3ZBS3FSZzNSNFE0a2lSSTFTaDkrUnhLU3N3Ny9SNEVjb1p4di8rZ2ZWQmM5Y2V3S0wrSEsrclVhUElzWlZyckMvQ2VsRjJ1bFRQdjFLT1ZsWktRZzNLOTRIcGVMK05ZSmpnTkkvYSt6dzFZWVkyS0xpTHp1Wm1xZjN1VFR6Y3dRb2NZUnpURmxMVnJkZEp6MEY3QUlQNXZiTnBqMVJlZWJrVXo4RGhrUEtrdkdEeFdhVHpPczdPdS9idk4wcjBMeGl5KzJFK0NoaTdaME8vUVpkK3RsVVlkTUpTNVEwb21TZ2p3WHRoeVZBUzUxd3FUQldsVzZjelgrNUVEKzBLcEFiZWtEeHMvdkZkVXB3NTBUeEIreklxWU9GRGhVL1ZsWG02YlB2SnZkTCtyMC9sek40RzZldHhEMTVnakI2UE0wSmNNYUhlUnlmV085cjVrd0t3RDNMMVZxWDk4RDgvMXJuWTFqczhIZ1Y5V0ZobXBVbmpTMzhPWWtJZkdPYmUzLzVheXFZclQ1Q3hlamIzM2xwZWx6WlJEcnovcnRKbjdRMU0yTWwxcWNFNGhISC9PazJ5Z1B5Y2E1Y2dNQ0dIUHYrbmJyMXlxV2gvZ3NTd3BhRzU5dlpiMkRZd29RcnhSU3ZvQW05d1FMcGFXcVRtMm5rYUluSHNhSHRVNE1DUmFSSDJyQm8yOFpDaE9ITXlQV1BYNDQ5SzY4b1ZjclJtby9TZlBPWFFtVEVaV290SThUSWlRUmg3UkhEQzF4SThOZEhiSXh0dXZVbktzalNFVTI1S245dGFWUzJZS3ljM2I3RzI2T2Q0UEZwUlp0NnRTZ1pQUHBSRFJodXV1eVk4bU9GWXBNN0E2bEtIOFptekZXeTc0d21Jem5XUnVnNjB5dTVmUHlHVnVzY0c4NWkvd0F4RE1GYlhXVlBrOENmL1FJY1lJeVpFbHRVQ0FtTmFPTDV0aDZ6L3p0VlNOSDFLYkN0bVo4MldiUDhOYndkdTFGVXZtQzJidm4rejFDOTlXTnJYZkN6OVIzQUFZL2lDeHlQRE5ZWm1GZWkvTUFRNjBVOWxjS3lraEhMRERvT0hQekErVlNBVXVYM3BROXBJT1VSYkp4dWtvZDUrUmlNZVhEa2VqQ2VORElxcjdkT1BiUWduWXhzTE5hT0RjVkUyamlGUGI5N0t2ZUhSMGpJTm9aOUk2MS9mbGEvKzhEdXB1LzAyN2h1cjhuV2VqcTFLV1ZaRmxVOVBrNjMvdlZpeE9LRXBXQmFQQ2l3US9MbGFUMnVUYkwvM1hpbk9RSVF3b3luU0hNS2xrSFE3ZzZQSnBGRHFRbjNWRlhsU09uZTI3SGpvQVRteHlhMTRDZVkxUVJIdWNPZEM0R2xFK0VhL2piZmR6UG1YZkdKeFJvVlBrOG81ZVl4c2ZyQ2dPSTRqMHJwbXRVYTlmTktJT2Q0V2RtbkVWVFZ2Ym1pTDdvSGVVRWdOeGtIWklEWWhoejlid3djTDJGb1VaMC9tbzhkQ3RXNElHUThBR0tMeXphT2hITzZYMVpMeE1MLzd0SWJYUUxoT2FGckdKZVo2WXk4U3V2Y2toa3h0Z1NQVXFtdm1rRFo3R3FlNDg3TzVuZUZKblNhRVJUNktkU0VTWlFnVEM2TENyTWxTcXdycTFLMVNJaEVMNmFSaFpHVURjSFNNOWgyMTFYd0dBQm80Qm1UbW90aW1HeGRwRTFzL0dEZytYSjRZNkpHYVc2NVgyblBaajhsSEJkMWF0c0ZRWEZ1bXJ3SGpGc1l4SCs1NCtIN3VuN0hnOHA3cnd4SFB3NVZ3S2wvbk14d05Rc2pkRFEwT2c0ZVlnQ2tNeTVuUkc3ekhHNkNNQng2dEg2Mld1c1YzU2ZYQ2E2WG9jdlZrWFF6aHNhRVhPcmRxNEVGcFlPNm5FalU2UEhyRTA3cGRUendtQ1o2dkc4VEhPVDlFM3JibFIzY0hIc09aTi9qWHhXVGpxaFVPWVRMOTFKOEx5YzN2ck5MMjVpQStDb0pXNURVM0xIUlRuTzhmazFPS01EN0tkdFJqb1ZFeGQ1WVNpQmNLWEdqTnRUQmJOUU00VkxCcXBRanJ1NTkrV3JyYVdxM2ptQUNSSUFxL1hYdDJTL043NzhxdUozOHV0WGZjSWhVYVBndlRKM0hSeGdVYytGQkY4eTJhZkNqR0xmVFVpd296THRXRjRxMXllays5b2FaQTQ4cUpDeGhhY2tYTlQyeXRNMDlVbk9YWldEOWtrbmNZZGVXOEt5VFJiZDVQZkpxSGRZaXJBd3owZEV2bFZiTzVNQXZLZGs0RHBiZXRYZXNVYnQzWWRSUXdMbUdjWVV3Qmc5Zi82bkV5N1FWcklRM1BybldmcVhQbHJoZWVsUk5WMVh3RU9SNUFyNGh4aldzRWY0VEZudVpXUG80OStMZjNwWDdKUTFKNWVhNnNtemFKKzE4TDV4YlNzY2pEUXdrWUkvYnJPT0hxYm0wTmFKM2pLWmhTVEZIZW82ME9DejlFTC9CTEpibFVPdTBTMmZ2S2kyeHJPeFFITVpxNWFFT205dzhzWHlick10VTRzVFdGekVHbk9ncm04VzBhdWF5ZDI3dDV6YWNJWTFjMmlRWVR0Z0x2T3RRaTFicU5xTXJKNVJ6S2NLbWVnK05BRUgxNi96NTBjQkJqL211Q0RZOWZDQjllRTVPQWJRbDRCOXNYME5iMDNnbytEaTJhSHAzZzRibTZoVXVVcDBoaDlpVFovNWMvY3h0bEtqVWdibmNaYW5XTW52b3ZwZnE2cTBJSTk0cUNJV0dCbFRoek9oZ01zbVN2eHJYaHhlVmdWNmRVWEg0WmFlTFVwem5mcGRPOFl0NU1PUko3UU9LNnB3empObWViaFp2eVlKMFIwN1lpeGlvVDVTMC91cFB0eVB4b3FSMEJBanJpeGw0NTJaTWdWQWg2WUtCUEdsNS9oY2JIK1ZIcDg2OUxZVnVJaHhMbE0vT2t0N1hGZGZaZytJS1lYYmIzK1Q4eVhQdjlOUERSeUtkTmxEMi8vNjAxNHZqV3dYWGp0ZGtqb3FNV2NLRi9vSzFJcHhRc01qazFZS3JSeFMzbzNmWDRJOWFPTURwbkdSZGxlMThLRnF1dy9ydlhtMVVxb1p4M1FEQ0VtWi9EVjRUUXpyY2RLd1JEVTRRZWI0VGJWTVBraGEwWlF1cXhkWVgwSWlvR3hvbm55YnBWd3BZTkM3Wlc3UDFWc0w0ZmtIZ2VtYXZ4OURRMnlzWWYzRXBGa0VkNk4zaFZudFdydTV1YnRMWFNCanl1SHlEZzlPQXVzZnJvT1hwWUtndDBlK2p3d0FEOUN4OVZDK2ZKcWJvNlp4Zi9EOG9HZUNIZ3AxOFhUR2UyYjdYM3VGV0FvYi9PTzNoNFgzUHJEZEo3L0doZ2NFd3dERWNRSXJKWUVUL3g2R1B6NUtBMHZ2b2lweHNJbFFjOGpFaTZSOWVGNUZlL2ZZb3JmZlp4dUFoYWhnbGg3c1RXcjBoWC91Z1BvN2IreXEvMjMvN0xSMlNncTRmdjlDVDE5elFvZ0NaL2l5WDg5ZmJMdnVkK3g5ZWJiYUdtZE9YWm9oZXZUZTk3NlFWSjlNZU9wbE9FY1ZPMlA4UUxBbFhUKytwUGY1Q2lxWGJteThXTGhpUXVpQXF5cFBHVlY3WHQ2QWtlRGtsenRKTWFNbjljYXluV3p1UkpvNEIzbk5xeVdkWi9aNTdTYUI1a29WUG4yc3pKc3ZXbjk3dHplazJ1SDRGZXFxbzVlVUkyMzN1UHZWK0hneERGNFUvQm9IQ2NwdGxnTGdIaVpVQ3NEQXE5c1o3Y1hDZVZzNjZnczVnUnFVRnFLQWQrSEx0MnR4N1FWc1picWpBT0N6UmxXdW1qS0NFOUNNRUp0bHUzVmpXM1hPZSsxRER2b1ZCd0tyUndycHpldllmdHhneE9ZRUZ1b2FEQWNxUjBRcmcvS0oyTkRWSjcwMDFVRGcxUkZjNkYxZlIwMmZvVEtOdWo4SkhMRzVkT0F4dHFwU3pEUGtMd0hvMjV2eVJyRXQ5RTZlMW9aMHYwb3hOb3djcVdnSU01NWFaMVZEVHFkQTd2NlpINng1ZnlBUW1tRnRBRkhVRHgyRW9lME8ybGQ3QlVZZHc4KzN6UXR2b2poamxzdmJqUFZvVmpMc0l4NTY1bm50SzlaUy9ibVFEOFlhZ3B4cGNwQlA3RkZBYUJhQTNiV0VPZldTRmN1S0lUcUJOdkFCamNoaHNYa0NZOEsyZW8xRzFqU2Zwa3FYOTBhZmhjQ1JER0J3ckZWL2ZnWWluTmhJR29BV3QvTHZSMGp3MmxONjd3aHlnamdMWmhzK0c1eWdLblpuaGRpOUZDbzZJdEpOV29zREtmZTRWN0ZTdFpKdWpyKzFzZXdUZXU3SUZqeDJUcmcvY3hIQ0ZNaHBDRXBONXpjdHNtMXhKZzFrOElWSnVscytUcUJudlA4R2lURld5RCt1Z3hLc0J5OUl0U21NOFZLQmI5YTEzOWdhNjhjU2FOTjBYQXB6dGpUNThvalcvamZUdjBjU2FpUDc3ZnFYMTdwR1RxRkhvY0RBVEtRQm1mOXRUZXVKQW5nNmw0SHZCNzNNYW5KaHRDaG5UTFZudlA5L2w4Ry9Mak9LQlJ4NEozdDM2d0NqM0RPQUVYOFNqWVJZQnZYTmtZK0VoSnNWVE11WXdld3pDcFJQUGhSTllVMmZTRDI5d0JpNTJKZXdLUk9SRTdjUE83S25qYmtwL0s1c1Uva0pPYk5rbUM1K3FSTXF4WGRNZ1R6MWt3V2ZLbnU2bUZ6OGR4dE1wOUxmbTBzM1I4Nk5DNWN6dGFLaGgrdzJPQ3JIL2tmNlIwR3BSdEwyS1kwak9rS0Q5TGR2N3ZZOW80OVJCcmVCVllNUHg0QmdNTVRlKyt3NGRJd0kweE9FMUE2VG9WcnI5Mm5yYUFYSnh5QTNnbWsrRS9vbXlNdS9NWGVBMFkyeEpkdGZLMHluRGlxeExNUDBaYkZNWnA1WEdhbmZBT3JsM0xyMHN4cDJMMXZQMW5EOG5CVDFmTHFUMjcrSDZiV2JkalhqdHpFZWlRMEV2MUQ1L2pIS3NwbDIzMy8wZ1ZwaUhSbmZiQkdCRjlzQkxmK3VNZjJ0Y2hBTkRoUEJ6UTJkcW80MCtnb3FrRURiUDRMQXFLcUppVkw2ZGhKQnpUMFpFQ3NEbCtOSVdJZ1BLWkxxbjZ6bnd1enJESTllc0RiZzh6cCtvMCthRzFqZkZzWmVjQU1mam1sZTBZNkR2WUt1VlhYVTZQcm5SN1dSQU52SGkwZCtZQVZwY0dKbGdVTExrcjZXMXZ0YTlMVkNFSVpWQVMzaG5IZSswYmJyNWV0dnpzUVdsNC9qbHArZkFET1ZKVkthZDJiSk91dlYvUkVMRHFidi8zV21sNi9WWFo5dEFEL0VTb1NOY041cEgyU0JMS0s4TExmd1U1MHZiRjJpQXVtaUNMVnJQcjUwc3BkSDhrN1B0amo0MXZ3dG1VWFVhbmJQWWptTEd6djFZMnZQcXl2YUNabTJOUk1iYVF4Sk15dFBSOVF6KzNSb25ETjY1c3MxRUx3ZmlJcnlSVFY1ZEtaSkhpZ3JLNUQxZGhiWC9neHlRWWp6VzlVSWVUdStPUnBVb0hyRnNYUTNuYW40OU0zWlNnZ3NiUkpIRGljNkxLK1RQNUVpSStxRnQvN2RYY3JwVE5MYkErT2lZZWhLQ2ZQN2l3MTNsdGEvUFZiNTZXeEVCZlRBTVJQZDNORFZJMWIxWWtFN2Q0UWhrUFc0N1Y0anR2MTNoVTRNYndBemxBTWRIYnhlY0trSnMvWU1GNEtGY1V6SkMyVDZNUEpPTHJoQmdhd244c2pQdkZ3NmFiYitUREJqc3N3RmVNYnRFeEoxYzZQdlVQOStNZW9mMjE3NG42blZKMXpVeFZ6bFFweEdtU0M1M2VxM2dzNjNENWlJRTZUQjBvKzN0SS9ISVNDMGF1dm8wV2ZyNnI3WGNzZVZESE00UERyd25NMHpQSXN3TThMK2NDRStOd2ZJc0lOYmZnbWJXMXN5NXhQczREMWlHTTZTNnQzbmZYOHQ0WG56TkhVUU0xWGh5dktnZHM4L0FOV3poYjhFZ0NNb1AvZ0xJQlJqWEc3dHkxazFzeGVKYmZSdEREdGE1dThUM1NmL3g0YUV2bVZkRmU2UGhrdGY3Sng2Ukt0eDNsK1hqTDFEd3FuaXhhT0FXN09sdllvQndKQ1VMRFV5OS9INjlNN2ZuVGJ6Z3FCdVA0UmdSenhLWWVIUi9QNE9ITmZNODdHSnJpU3Bza2JmemUzSzA3Zk44UndJZnFVSFpnNFJoZ0NreDBubUVJcDNPb3dYTnRnY2dFK3ErZUplM2xSV3p0Y1owTFZObHVNQ2E4L1FIQXY5bFFaVStkYUorWElseG93cnZkVFcrOXlSWVJJU09CS2N3emd2TGVQenpEaFJtT0F3c3pKdlBRSHc4Tk1JYzJMSC9Kck53SUllRGFIOVJnNE42V0E3TDdsYi9JbHJ2dlZHK2Z6WlZwdWVMQld5ZUlHdDRJb0hndkVIcXZLZ21HeHBjbk1OZHJmYzMxODJYNzBpVzZCZHlpcENweU1qYWNML1B5QSsrdGxFSzhFSkV4aGUrL0ZXWk1KQS9GYWQvU3FlSWE5UzViR1lOSDV1ZzZEbUFrRGNuK3Z6d3YvNTd3TFg3dWhFK0FrU2kzeWY4bE94Lzl1ZlRwbGpUQU9RWS82LytnR1F6cW9xYWVyN0VlL1BCdm1qNWd3cDcwek81NklqS0dSb1preXpYb1B0RXVUVzh1NDlPeDVtV3ZTK3V5MS9UNkRXbld4ZFBoenorVG9XN2RSMnMvUC8rZ0g4ZUw0MUhsRDNTZWtoTWJhblEvL0pic2Z1cEp2c3RXYzlOQ2J2UHdBa0NoQ2dHQ3dJdjU2M1FyaFVlRjFkZGNKYlYzM1NFN2Z2VzRIRnoxbHE2Y2R5bytXMU1Bc1pXZ0tLUGJWS2ExaVVFNVdscWlOTDdNLzIzU3ZQeFZPZkRtNjN3MUdndW9JeldWVkVpU1hHTEZzWUZSMGQzZUl2dGZlVW5sOW9iUzhEckgzN2Z5VldsODgyVnBYZk94YlVNVnpqNU9NVEJsNncrSWpCS0VIRmVTRFpac3E5SDlrWUFMUTdaVkRGNFltaVZ0aXl3endJVlA1eGduaERqOXNWdHFGcnFJT2RQZUpsMzdHbFdCWDhyeExYVjhtZkRFaG1wTFdvYjNkdTdaTGYySDJqUXNka2VPckJCWFVsVG5DZ3F4WWhnekFsLzJ0SG96SFRzQTNRRE9EVENFWGtRUjBuUVU2S0tRNHpTZERkR2N6Y1lHWHBpc2NkVTBBaXNTL0tDcFFrU2NKdlVTRTY0akhIVk9zamF5bFZERVZWQ0UxNDY3QkhpNkFqMnhlMzQ4Z3F1UGJxUGVqVCtNdDJpckJXTTBPdEFXSE9BaFdLQWRtYnZuaGMySFpBNnYzUnM3REludURFQ0xINU1sajF3ajRJQ24zem1QSm44M0R2eW5kKzcrTUFEQlVJSy9IMk1nTkhaMUZ3SzJOVndCaURQZTErNUhEUGo3cm8zRDRlOEczYnNhQ2ovV0pvUXg3ZTdiQWtJN1YyZkZpQTZXazROYXlBSFJPQmpCeHZJSjNTS2pBYzQ0TjJNQVA0QWFFOFpBbVhpSEkwZTlHOTl1NmZoeDVoVzRRSXNhQUl4UVFLanpCZVpvci9kakFya1FjRHVnRFcwVU41WW53bWZEaUxKR0prQ2pKUnJNM2RJK3BwVmdGUDRHSUpSeEQyM2ozbTkxQUZMaityZ3NWb2phQVl4R0c0OWwrNHZhT3hMOHRhOGVLOFREZFp4WHcyL1h3L25pTmZzbFE1aXpYVytGcUJPQXpMa3l3SzZUMjR3SVNiZzlQaENrV1J4NURGaXRQK2RzTXF3aWZobG1JNWVmWlVoeGlOOUNXVk9nanBuUmFKRUM1VWlBSGkxbG9ZMnRoU25Hb2ZEWkdFRXBpdkdRaEJNWHd3ZFJXc0FENlVxNkovSi9VVmJXT2hOS2dBd0FBQUFBU1VWT1JLNUNZSUk9IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI3ZTNmM2QzMDM1NTc0NDQyYmRhZTEzOTMxMjE3OGIzOSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0xMC0wNyIsInVybCI6Imh0dHBzOi8vd3d3LnJzYS5jb20iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkRTMTAwIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMjEwMDcwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0xMC0wNyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjItMTAtMDcifSx7ImFhZ3VpZCI6IjczYmIwY2Q0LWU1MDItNDliOC05YzZmLWI1OTQ0NWJmNzIwYiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNzNiYjBjZDQtZTUwMi00OWI4LTljNmYtYjU5NDQ1YmY3MjBiIiwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IDUgRklQUyBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA2LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI3M2JiMGNkNGU1MDI0OWI4OWM2ZmI1OTQ0NWJmNzIwYiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtaW5QSU5MZW5ndGgiOjYsImZpcm13YXJlVmVyc2lvbiI6MzI4NzA2LCJjZXJ0aWZpY2F0aW9ucyI6eyJGSVBTLUNNVlAtMiI6MiwiRklQUy1DTVZQLTItUEhZIjozfX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMiIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAzLTI4IiwidXJsIjoiaHR0cHM6Ly93d3cueXViaWNvLmNvbS9wcm9kdWN0cy8iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgNSBGSVBTIFNlcmllcyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI4MDA0IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMi0xOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWUsgNSBGSVBTIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTAxMTgwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDItMTgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAzLTI5In0seyJhYWd1aWQiOiIxNDlhMjAyMS04ZWY2LTQxMzMtOTZiOC04MWY4ZDViN2YxZjUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjE0OWEyMDIxLThlZjYtNDEzMy05NmI4LTgxZjhkNWI3ZjFmNSIsImRlc2NyaXB0aW9uIjoiU2VjdXJpdHkgS2V5IGJ5IFl1YmljbyB3aXRoIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjo1MDIwMCwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIxNDlhMjAyMThlZjY0MTMzOTZiODgxZjhkNWI3ZjFmNSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJuZmMiLCJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlNlY3VyaXR5IEtleSBORkMgYnkgWXViaWNvIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEwMTcwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiJGSURPMjAwMjAxIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNS0xMiJ9LHsiYWFpZCI6IjAwNTIjMDAwMiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFpZCI6IjAwNTIjMDAwMiIsImRlc2NyaXB0aW9uIjoiaS1TcHJpbnQgQW5kcm9pZCBGaW5nZXJQcmludCBVQUYgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGNEaXNwbGF5UE5HQ2hhcmFjdGVyaXN0aWNzIjpbeyJ3aWR0aCI6MzIwLCJoZWlnaHQiOjQ4MCwiYml0RGVwdGgiOjE2LCJjb2xvclR5cGUiOjIsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MH1dLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFLNEFBQUE5Q0FZQUFBQTAvbElEQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUtUV2xEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOM1dKUDNGajdmOTJVUFZrTFk4TEdYYklFQUlpT3NDTWdRV2FJUWtnQmhoQkFTUU1XRmlBcFdGQlVSbkVoVnhJTFZDa2lkaU9LZ0tMaG5RWXFJV290VlhEanVIOXludFgxNjcrM3QrOWY3dk9lYzUvek9lYzhQZ0JFU0pwSG1vbW9BT1ZLRlBEcllINDlQU01USnZZQUNGVWpnQkNBUTVzdkNad1hGQUFEd0EzbDRmblN3UC93QnIyOEFBZ0J3MVM0a0VzZmgvNE82VUNaWEFDQ1JBT0FpRXVjTEFaQlNBTWd1Vk1nVUFNZ1lBTEJUczJRS0FKUUFBR3g1ZkVJaUFLb05BT3owU1Q0RkFOaXBrOXdYQU5paUhLa0lBSTBCQUprb1J5UUNRTHNBWUZXQlVpd0N3TUlBb0t4QUlpNEV3SzRCZ0ZtMk1rY0NnTDBGQUhhT1dKQVBRR0FBZ0psQ0xNd0FJRGdDQUVNZUU4MERJRXdEb0REU3YrQ3BYM0NGdUVnQkFNRExsYzJYUzlJekZMaVYwQnAzOHZEZzRpSGl3bXl4UW1FWEtSQm1DZVFpbkplYkl4Tkk1d05Nemd3QUFCcjUwY0grT0QrUTUrYms0ZVptNTJ6djlNV2kvbXZ3YnlJK0lmSGYvcnlNQWdRQUVFN1A3OXBmNWVYV0EzREhBYkIxdjJ1cFd3RGFWZ0JvMy9sZE05c0pvRm9LMEhyNWkzazQvRUFlbnFGUXlEd2RIQW9MQyswbFlxRzlNT09MUHY4ejRXL2dpMzcyL0VBZS90dDY4QUJ4bWtDWnJjQ2pnLzF4WVc1MnJsS081OHNFUWpGdTkrY2ovc2VGZi8yT0tkSGlOTEZjTEJXSzhWaUp1RkFpVGNkNXVWS1JSQ0hKbGVJUzZYOHk4UitXL1FtVGR3MEFySVpQd0U2MkI3WExiTUIrN2dFQ2l3NVkwbllBUUg3ekxZd2FDNUVBRUdjME1ubjNBQUNUdi9tUFFDc0JBTTJYcE9NQUFMem9HRnlvbEJkTXhnZ0FBRVNnZ1Nxd1FRY013UlNzd0E2Y3dSMjh3QmNDWVFaRVFBd2t3RHdRUWdia2dCd0tvUmlXUVJsVXdEcllCTFd3QXhxZ0VacmhFTFRCTVRnTjUrQVNYSUhyY0JjR1lCaWV3aGk4aGdrRVFjZ0lFMkVoT29nUllvN1lJczRJRjVtT0JDSmhTRFNTZ0tRZzZZZ1VVU0xGeUhLa0FxbENhcEZkU0NQeUxYSVVPWTFjUVBxUTI4Z2dNb3I4aXJ4SE1aU0JzbEVEMUFKMVFMbW9IeHFLeHFCejBYUTBEMTJBbHFKcjBScTBIajJBdHFLbjBVdm9kWFFBZllxT1k0RFJNUTVtak5saFhJeUhSV0NKV0JvbXh4Wmo1VmcxVm84MVl4MVlOM1lWRzhDZVllOElKQUtMZ0JQc0NGNkVFTUpzZ3BDUVIxaE1XRU9vSmV3anRCSzZDRmNKZzRReHdpY2lrNmhQdENWNkV2bkVlR0k2c1pCWVJxd203aUVlSVo0bFhpY09FMStUU0NRT3laTGtUZ29oSlpBeVNRdEphMGpiU0Mya1U2USswaEJwbkV3bTY1QnR5ZDdrQ0xLQXJDQ1hrYmVRRDVCUGt2dkp3K1MzRkRyRmlPSk1DYUlrVXFTVUVrbzFaVC9sQktXZk1rS1pvS3BSemFtZTFBaXFpRHFmV2tsdG9IWlFMMU9IcVJNMGRab2x6WnNXUTh1a0xhUFYwSnBwWjJuM2FDL3BkTG9KM1lNZVJaZlFsOUpyNkFmcDUrbUQ5SGNNRFlZTmc4ZElZaWdaYXhsN0dhY1l0eGt2bVV5bUJkT1htY2hVTU5jeUc1bG5tQStZYjFWWUt2WXFmQldSeWhLVk9wVldsWDZWNTZwVVZYTlZQOVY1cWd0VXExVVBxMTVXZmFaR1ZiTlE0NmtKMUJhcjFha2RWYnVwTnE3T1VuZFNqMURQVVYranZsLzlndnBqRGJLR2hVYWdoa2lqVkdPM3hobU5JUmJHTW1YeFdFTFdjbFlENnl4cm1FMWlXN0w1N0V4MkJmc2JkaTk3VEZORGM2cG1yR2FSWnAzbWNjMEJEc2F4NFBBNTJaeEt6aUhPRGM1N0xRTXRQeTJ4MW1xdFpxMStyVGZhZXRxKzJtTHRjdTBXN2V2YTczVnduVUNkTEozMU9tMDY5M1VKdWphNlVicUZ1dHQxeitvKzAyUHJlZWtKOWNyMUR1bmQwVWYxYmZTajlSZnE3OWJ2MFI4M01EUUlOcEFaYkRFNFkvRE1rR1BvYTVocHVOSHdoT0dvRWN0b3VwSEVhS1BSU2FNbnVDYnVoMmZqTlhnWFBtYXNieHhpckRUZVpkeHJQR0ZpYVRMYnBNU2t4ZVMrS2MyVWE1cG11dEcwMDNUTXpNZ3MzS3pZck1uc2pqblZuR3VlWWI3WnZOdjhqWVdsUlp6RlNvczJpOGVXMnBaOHl3V1dUWmIzckpoV1BsWjVWdlZXMTZ4SjFsenJMT3R0MWxkc1VCdFhtd3liT3B2THRxaXRtNjNFZHB0dDN4VGlGSThwMGluMVUyN2FNZXo4N0Fyc211d0c3VG4yWWZZbDltMzJ6eDNNSEJJZDFqdDBPM3h5ZEhYTWRteHd2T3VrNFRURHFjU3B3K2xYWnh0bm9YT2Q4elVYcGt1UXl4S1hkcGNYVTIybmlxZHVuM3JMbGVVYTdyclN0ZFAxbzV1N205eXQyVzNVM2N3OXhYMnIrMDB1bXh2SlhjTTk3MEgwOFBkWTRuSE00NTJubTZmQzg1RG5MMTUyWGxsZSs3MGVUN09jSnA3V01HM0kyOFJiNEwzTGUyQTZQajFsK3M3cEF6N0dQZ0tmZXArSHZxYStJdDg5dmlOKzFuNlpmZ2Y4bnZzNytzdjlqL2kvNFhueUZ2Rk9CV0FCd1FIbEFiMkJHb0d6QTJzREh3U1pCS1VITlFXTkJic0dMd3crRlVJTUNRMVpIM0tUYjhBWDhodjVZelBjWnl5YTBSWEtDSjBWV2h2Nk1Nd21UQjdXRVk2R3p3amZFSDV2cHZsTTZjeTJDSWpnUjJ5SXVCOXBHWmtYK1gwVUtTb3lxaTdxVWJSVGRIRjA5eXpXck9SWisyZTlqdkdQcVl5NU85dHF0bkoyWjZ4cWJGSnNZK3lidUlDNHFyaUJlSWY0UmZHWEVuUVRKQW50aWVURTJNUTlpZU56QXVkc21qT2M1SnBVbG5SanJ1WGNvcmtYNXVuT3k1NTNQRmsxV1pCOE9JV1lFcGV5UCtXRElFSlFMeGhQNWFkdVRSMFQ4b1NiaFU5RnZxS05vbEd4dDdoS1BKTG1uVmFWOWpqZE8zMUQrbWlHVDBaMXhqTUpUMUlyZVpFWmtya2o4MDFXUk5iZXJNL1pjZGt0T1pTY2xKeWpVZzFwbHJRcjF6QzNLTGRQWmlzcmt3M2tlZVp0eWh1VGg4cjM1Q1A1Yy9QYkZXeUZUTkdqdEZLdVVBNFdUQytvSzNoYkdGdDR1RWk5U0ZyVU05OW0vdXI1SXd1Q0ZueTlrTEJRdUxDejJMaDRXZkhnSXI5RnV4WWppMU1YZHk0eFhWSzZaSGhwOE5KOXkyakxzcGI5VU9KWVVsWHlhbm5jOG81U2c5S2xwVU1yZ2xjMGxhbVV5Y3R1cnZSYXVXTVZZWlZrVmU5cWw5VmJWbjhxRjVWZnJIQ3NxSzc0c0VhNDV1SlhUbC9WZlBWNWJkcmEza3EzeXUzclNPdWs2MjZzOTFtL3IwcTlha0hWMElid0RhMGI4WTNsRzE5dFN0NTBvWHBxOVk3TnRNM0t6UU0xWVRYdFc4eTJyTnZ5b1RhajlucWRmMTNMVnYydHE3ZSsyU2JhMXIvZGQzdnpEb01kRlR2ZTc1VHN2TFVyZUZkcnZVVjk5VzdTN29MZGp4cGlHN3EvNW43ZHVFZDNUOFdlajN1bGV3ZjJSZS9yYW5SdmJOeXZ2Nyt5Q1cxU05vMGVTRHB3NVp1QWI5cWI3WnAzdFhCYUtnN0NRZVhCSjkrbWZIdmpVT2loenNQY3c4M2ZtWCszOVFqclNIa3IwanEvZGF3dG8yMmdQYUc5NytpTW81MGRYaDFIdnJmL2Z1OHg0Mk4xeHpXUFY1NmduU2c5OGZua2dwUGpwMlNubnAxT1B6M1VtZHg1OTB6OG1XdGRVVjI5WjBQUG5qOFhkTzVNdDEvM3lmUGU1NDlkOEx4dzlDTDNZdHNsdDB1dFBhNDlSMzV3L2VGSXIxdHY2MlgzeSsxWFBLNTA5RTNyTzlIdjAzLzZhc0RWYzlmNDF5NWRuM205Nzhic0c3ZHVKdDBjdUNXNjlmaDI5dTBYZHdydVROeGRlbzk0ci95KzJ2M3FCL29QNm4rMC9yRmx3RzNnK0dEQVlNL0RXUS92RGdtSG52NlUvOU9INGRKSHpFZlZJMFlqalkrZEh4OGJEUnE5OG1UT2srR25zcWNUejhwK1Z2OTU2M09yNTkvOTR2dEx6MWo4MlBBTCtZdlB2NjU1cWZOeTc2dXByenJISThjZnZNNTVQZkdtL0szTzIzM3Z1Tys2MzhlOUg1a28vRUQrVVBQUittUEhwOUJQOXo3bmZQNzhML2VFOC9zbDBwOHpBQUFBQkdkQlRVRUFBTEdPZlB0Umt3QUFBQ0JqU0ZKTkFBQjZKUUFBZ0lNQUFQbi9BQUNBNlFBQWRUQUFBT3BnQUFBNm1BQUFGMitTWDhWR0FBQWFoa2xFUVZSNDJ1eWRlWmhsVlhYMmYydWZPOVN0cWk2cWVtNm1abWo0bW9iRStCR1JNU0pEQ0pNUUNZb2dDa0hGS1lJR0lRb21PQVFrd1NpUnFJZ0NSaU1FR1VRa1lBUVJaQW9OQ0IvSTVORGRBcUdibnJ1NnF1dmVlODVlM3g5NzNhNVRwODZ0dWxWVVF6clBYYzl6bis0K3d6NTdlUGRhNzFwcjc5MmlxclNsTFZ1YnVIWVh0S1VOM0xhMHBRM2N0clNsRGR5MnRJSGJscmEwZ2R1V3RyU0IyNVkyY052U2xqWncyOUtXTm5EYjBoYWdNTlpORVprSDlBSkorakt3RWxnemllL3RidTlycWl3SFBKLzZ4dlpBVitxWlZ5TUNiQUorUDg1ejA0RDlnSDJBUmNCTW9OUHVEUUhyZ2Q4Qmp3TVBBNzhlNzhOZFVjVGx1KzVCYjZGQXNoV24xUVdLVHZVZENrY2c3QUNVZ2RoK20wVDVHbkJiM3J1SzRPWFZmZitFcHgrZk9IQ0JuWUdmQXNYTTljZUJQN0ZCYlZVK0NGeG1ZRXAvLzJyZ0E2bHJYd2VPbU1LK1h3d2MwT1RlVE9CczROM0EvQmJMMndUY0Mxd08vUGgvdVdMclU3Z3hFWGtybVlGcmlCZnViZ2JjMTVNcVBBRDhzd0UzL1hzVDhQRUpmR2M3NFBOQUtWUE9md09mem1qMFVzNzNYczJ2MUtST2J3YnVCODZmQUdnQktqYXhiZ1crQi9Ua1BlUlIvaGNzWHpvUGVPdXdCaDM5bXlMTE9MVlV3ZVN6d09IQTNwbnJud1p1TkRNL25uelJ0RnRXUGd5c0dEWG1VeXZsbkd1N0dmQm1qZkZlYkJPcTFFVFpBSndDekFiZWxyVStYUzZpSkxJMWd6Y0Nqc201L2p6d2xQVlBYd3MwN0hVRDdoQndwbW1uTkFpNmdTOEJ4NDd6L2hGbWlyUHlUZUJITGRiekNXRDFKSnhKQVo3SnVYNUpFOUQrQXJnT2VNeDR2RGUrdmNqQStZNGMyblE0OERmQWhTTm1ScVdMNllVQ2c5NXZyY0N0QUROeUtPSkJ3TWIvMGM1WlNoNDFVLytGelBWamdCT0JIelI1cjlQQW5aWGYybUMzS2g4RjdwdWlOdThDSEpWei9SK0JjNXU4OHhSd1BmQnQ0UHZBM0p6Ni9ZdUJIWUJGblYxaktPcXRSdU5tRy9ETC93bWduUWh3QWY3QkJuei9uQUcvRTFpYjg4NDV3SjQ1Vk9CRFRaNXZKc1VwYlBNZjVkQ0hKY0FGTGJ4N3Q5R2JtektPd2d5UXc0QnJQVXBKSEh0MmRoT1BqaWJNQS9ZQWRqUXpXd1NxRnFINVBmQnNEblZxVldaYTJUc0IwNjJOaVFGdERiQU0rTTBFb2tGSkxuV2ZuTXdIOXJLSVVZK1ZzOGI2L1ZmcENiOGxnRnUzeU1CRHFWQlJvMUovbStPczdkRkVnMTF1a1lxSm12eXBrams1MTE0Q2FpMitmNnRSaVYwQkZZR0NJc0R1SU5SUUR1cnBZMkZuRjRQSjVyRS9EbmkvUlRkNnh5aDd0VG5FVndFL2JMRSsrd0puQVljWTN4NUxsaHZsK3pad2U4NzlzODJDZXB0VTAzTXM3TDBweWliQVY1cFkzQWg0SjNBR0ljelkzYVJPSzRHZkczVzhjMHNBRitCSkErbWxtZXNmTVJPNk9IWHRuNHdmcHVXWkZqWGJscFE4Z0RZMDFkSVczbytCUHdNcUNGNEV2T0ppZENNbzgwcGxUcG85aDNyZ3RoWGdDdURVRnVzMnczeUdZNEViRE96cnhuaitIT0NpQ1Zpa3VjQUo5cnZTckVlY3VyOHd4NkptSjMxMjR0K1U4OXdpUWxqelQxcW8weXliTENjQzM3Vkp1SGFxZ1l2TnNLUFRZUkxydUM4REIxdEh2TXNHTjJ0NlBnajBUK0tiOVNrRTduTk5BSE9iVGFxN2dBM2psSkZyMmdvaW5MUDlmTFlyZFREZ0V5VHcrMU9iYUw2WHJFKzJJY1RMczJHN3Z6RGdIOWZFYko5c05DMHJHNHgyREpwbTdERnEwcEY1N3YyRXBNb1hYNlZseTc2emp6bmRlWlp0bVZHaEFyQkRqb044S3JEQU5QdWFxUVp1WWh6MVlVYkdNQThBM211YTk1S2M5NzVrWm1ZeXNwM3hvOG1rcUpkbnRPeWp4aVVYNW1pSm00QVh6QWw1MmtJL1M2Mk1sN1BhTDFJUUJDK0tRemhwMWx3V2RYWXprQ1JJS1AvOU9RTjNucG5FMWFsdzNTN0FhY0FuTW1OeU5QRDJIRlBjRGZ4OTV0cEdtM2czV2wwYllPOHdrSndNZkNyRDd6OElmQlVZc0g4dk5oNGUyMFE2TFBQOE1xTkprcUlEejJRMCt2VTVvTDNWRk5zaktjVTEyK2pOZWVaM05HUS9vdzBuTWthTVdNYmE1U3N5NWdUOHNIblMyWUY1MkQ2YURhUHNUOGc2alNlMzUyanJRZE82azlFSWgxcUhwZVZZNEpZSmxGYzEwQzZ6Z1hvQXVLY0F6K0dFV0lKRGR1bE91N056dVVJMTBJVFRqYXVtNVUrQm42cUFLS2dsdndWQUZVVE96Wm4wUDg0Sk9SNFAzSnk1ZHBxcWZvZkdlRHFYcHc2L2FFQkpPMXQ3a0IrTEwxbDcweEdVS3htWjVjektGVG4zTHhHTElQbU1tcmE2OVdoSTVHVGJlQnp3bzhtbWZNZVNyNXRLUHpManFNM1A0WlFmYkJHMGpCRldtOHJJeWEybWdTNXJ3YUZwYU1VR3Y5dkhMTXVRSXY4SmNnbm9Belh2dVdYdFNqNHhkd2MwREZHZktMaEdla2xBa1FIdkJIV0NXbktpcGdrT29jc1ZTYXExSzhLa2xXbmh0ampqZXhLZ3JUYm9NaXRvUGswME9JWnJWZlhHUWtlSjdoblRVVlZXckY2Sjk1NmlPQW80bkZmRSs0Y3k3WElqL0pDR29ncmc3OHlaMklXOFo2MkpPOG1vZUwzOERPRnZhZ0t4NkloMUMwS1l2QVdWRFVYUDZhQlBtR1Z0eUZrYUpxMmZhdUNxT1dXUDVIaWZhYmtZK0svWDBSbmIzRjNPT2FJb29sNnZRMGcwM0crVzR3UkNObTBpMHBHZ2I4UExrY0NuRUw1MDk3clZITlhUeTg3bERtcXFxeU5sc3dLTUhhaTRxMUg1bW5xNVQwV1dLYXhLMU9ORjZOMXVIdkhnMFBxTnE5Y2Nvb0N2eDZoUHhDemZDTFBvVmI4TitpMFJVVmNLZmxtcHE1T2VtZE9KaWtYaUpNYXZlb1hFZTV5QUUzbzh1cWVvbmoxMlJ4a0l0WlZPMWVING1JS2dSNEdrRll6MytNL1V4RGlMQnFCbUFWUUxEdExxb25LNUlCZW43dTZQeUc1TmZKSnhWNGVOalZ6VkpWMWRYZWQwZDNkZmxhVWNJa0ljeHc4UERnNWVsUGR1VjFjWHpyVk1XWjlYMVEyVHBBcWJuY0Zpc1VpNVhLYS92NS8xNjlkVHI5ZGZNTjczT2VDUG9pamF0N2UzZDY4b2loWUIyNXFaTERVdjJvRktVYVA0VWhWNXlYdTk3cUZpa2IxbnptRWdTUjRVa1Jnb0pCTFlvRlBkM1NsZnNaZGZBVjdvUkpjSThxeUxvdWNyMDdmNVZiR3Y1emZlK3cyMWFwWDY0SkRHL1FOb0hJOW91ampubzJtZEZEc3JsQ3BsSW9tS3pybnRKVW5tZXUrM0JlYjE5dlhOVmEvelJkalJJVHRwY05DMnBPeWJkYWdWUGFZU0lndmpEWFFzc0tlTUdGN3RLSmNyZTA4S3VBc1dMQmkzdHFWUzZlcGlzWGlVZWNGcFdTOGlaM3J2YTVPZEdLa0pjcWFJL0h6U0tsZUVlcjNPME5BUTNudDZlM3ZwN3U2bVZxdFJyVllaR2hyYU5EQXc4Q0R3NEx4NTh5Z1dpempucHFucVBPLzlEc0JlcXZySHdFRWlNait0ZHdJZDhGUWorYXozL3BabllkUHlubW5zV081NHZxcGNndXI1Q25RSUlBbXAxUXV6SmRDVXZWR29xNmVleENEeW9ncUxvNDdTRFhTVWJ5eE9tMWFWZUtTMTFNaEJ5ZUhRd3oyOFcvSDdrZmp0UVN0aFBnblRac3pZakhYVkxSQU5IeTA3Wk9tVkJLVXdJUk0rY3R4Wk1LbW9RcWxVYWdWVVZLdlZLM0tBZXgvd2VCNDRKM0hza3dBVUNvVkpnVGFPWTRhR2hsSTJ6Qk5GRVpWS2hjN09UbFNWRFJzMnNHSERCcElrd1RtSHF2YXJhci8zL25sVnZjdnEzS09xSjZucUpVQnZvNmRMWHFrVzJIMEkvNFphNGgrNmN2bnZPWC83QlNUQ0JUNU9YcFRFbnlYS3dpVHlMYXhQMWUwdGd2TG5vR2VMNm1rVzRVaDNZSmZHL2h2SlprNnBPUkFZQWZZMUZnMUltTm9sb3lPTTZGUVhxT2ljU1FFM1BkZ1RqT1hSSlBiNHFuaHF2VjZuWEM0aklpMkJYMFJJa29TaG9TRlVGUkhwc0JEVk5MVUNWTlVCdC9mMDlEelczZDJOaUNBaURmQnVCbm9qUmhySDhUZmpPTjRBWE90c2JkOWdBUXBEQ3VKM1RWUWZLZ3hWcWZXdmg0NE9uSXUrZ2ZmWG9INGZVZllWMVRkYStHcyswQWRTR2dQTGJ3SitnT3ArNmRpeUtGK1ZSTitkTTlETGdDY1JmZ01zRWVRbFlJbVA1RVdVVjF5aXAyOUI0R2FkNzBFVnZnc01qVSthYzNzZ0F2M1pwSUJyVHN4a2dUdWxocWtCMXY3K2Z1STRudEI3bFVxbHdhZEZWZitXMFVzc1p3Q1BpUWpyMXExRFZhbFVLa1JSdEZrRE8rZnczbE92MTFIVm53SnJuZExYaUpWUkY2UVFsVHVkY095MDZVamlxVzNjaUxnSWNXNEk5ZmRLVkxoWG5FUENQT2dWWlI3NFhSVGRVMVgzUjNnTG8xUENpNEFqRkxWWXJ1d2xJZWFibGxVTzkxRkIva01kL1RyQ2RaZmdHTlZqVkxWM0MxS0ZaYU5DcmVpRjRxTGxJVGlpelFZSXZFZHpWdEdwVERJQk1SR0FiUEhRZ0FpMVdtMGlrMmxZRld6YVJMbGNCdGlrcXI4QzNwSjU1Q2pnVTBtU1ZHdTFHdDU3QmdZR05tdmNoZ1oyempVMGZpOGhxeFU2TVFHZlJOUmpYYkh2Tmowc0tKVTdhdWliRVNtb2V0VWtFV0FJN3grTW9vSVhWMEJFMWttSURUL2owZHNVajZyZlJUM1htYVpOeTU2cEpNUitPVXJoSDlSRi94NkZjaTArcktnQndpZHh3K0xzMVp6eWVWQkZYRFRaSVhxSWtWbkNDdkJPamVQTHhFVzRLTDljbnlSb0VvTnFDWkZDQ3VFRjArTHgxZ3pjZ1NSSjhONjM3TkNONEN4SlFyVmFiV2pkdTNLQSszK0F5NUlrK1JDZ0RacVFwU09xU3ExV0k0cWljNEVPSFZZdFJPb0g2eXBQN0JoRkZJU09tdmMzQnlxUWltZXIzNzFlajVlaGlvakRSV0djMVBZVGFFakIzcEFEM0xRNjZzdHA0bElmSjhUVVFNSDdFSVh3U1JMYytTaENJcmVUaUJ5ZlMrbTg0bTJzWFZHSFk3UVRrOXNJS3dqVFhQY2NWYjFCcTdXWHlPbFBFUUVScEJEOW9ZaDhEOVdLQVZjSUdjdTMwMlNKd05ZQzNCTlZkVThtbC9LdEF6Y2xTZEp2WFBWZmdVOFNOa2ltNVV6Q1pzNHZXM3czbXl1dkFHOVUxYlBqT0Q0eGNFb0JBYWRLMWZIRFRkNi91Q21wbzRtdTgwbnlsSVJGMStsTTFJWHEvUm5xdmZlcURaSUJJamhBb3FoTFJJN09JVjFQdzJaZXZ6SUhWb2VxNmc5OGJKcTFZWUpGUWdaTmRRSGVmMTgxTjk3ZWxUYlRQazVhai9iSWlNalFNbFd1RWRXUHBCN1pIdUZXUWhieGlTYkY3RTNpcjFVWmpxT0hKS0pjd2hqcldyWVc0UDYxeUt1aXpQZWxPbUVaOEdsVi9Xck9jMitWc0RGd3Vhb3VaWGdYUkorcTdpQWlPNmUxaGplelhFcDBoUy9JQlRXZlVFMWlTQkxVKzYrcjZrR1o4azhEZGtYa0dna0R1UTZJRUprSjdLUGV2MWRINXUwQi9sdEVmcGFLSFR5b3FuRm03TTRBWGtEa3V4TDI4WUZJRDdDN3FoNlA2dnZVajlyTjBKQnZFZGJFUGdwY2tzcUV0UWplRWVQeWQ2cDZLQ1BYZ2J3UmVKQ1FyYnlIc0FESUFUdXE2a0dvdmsxSEx3QzZDdWUrTmRaM3R4cU8rMnBvUnNQVU5qSm5xbnA1SE1mVENmdnA4bVF1bzNjNWpMYXhJbmlScFlWRTM2VlJZVWxKSFBPTFplcHhqS3EvemdieGpBd2xQWWhoVFR4ZzNuTkhQbGcwQVQ2R1NGcjdQNHZxTlNEdnk0empGd2pybjFlWTJ1b0I1b3lFb1c0QTZRcmZIT0g4TFdLU2kvWEZqV2piYWxUZnJxbzNCZkJLMmxxOXczN2pSWEwvVFVRK3BPTnNlU3FNeHcxYmxMeHlKcnUrb0hPS2dkdlZvQmh4SEc4T3B3R2ZTNUprTVdHWDd3R1RLTGZmNDc2dnpuME8wM0pGRVdaSFJSTDFxS3FxOGdGOGZRbm9KN0MwdUl3Uis4eUE5em1JUG9senQ0WU1naUsrTVI3NmNRMlJrRC9QbE5sRGFzVmVwcnovQVBjcDhQOEVIQ3FqdnlzNVVhRnBPWFFwZzdVSWlVWmcvaG4xL21EUitJc2E0c3lGc1VKTXFUcXVBTGxFWFBITHJjU2p4Z1N1YjMyajMzT212Um92T01MU3djbklGWVF0TWxPMXk3REc4QkpDNGppbVdOemMwYmVyNnUycWVpQmhDZUcrcXJvYllZMXNKYVdaWXNLeXdWVWk4cFRWN3piRS9YWjAyRjh6VHBYK3ZmUHg5MFQxQklYRE5FUUlwbWZLcndNYlhkQ1dqd3Y4Mkl2Y29zNXRISzJBQWRnbzZOdWQ5NmNvdk1mb1JWOUthMWFCRFM3UW9nY1F1VWxGN2xFQjUrTVBvSHF4d29IR3Urc3VUTHk3WkhSYzlqTUdYclV4Zld5MGRvdkJSYWhFYVJpdVFQM3BUdjFYUlBWRWhVTTA3QmpaaHVGbGtsVmduUXMwNVhZVnVWWWxlcWxsVFQ5V0lIKzhUTlVFMWhwczlzcEhlSlN2ZzBSUlJLbFVJbzVqa2lRWkVUMnd2M2VyNmt6VFhJMnQ2VVBBV2hGNVJVUnFtK3N1QlRSeWRBRkp1WUIzd2o5dXR3c0xLNTMwSndteFYvQTFuSThSVmJ4Q0lxN1RpNXR0ZzFnMGJiUXB4SVdUVnlMVldNVDRzeXVCaXhDZ0Vqa2txVEdVZUpzY2l2TWVyMUIzaFJsR2JUcHR3ZzhLckN6NmVKV1lPZmNpZUlsd1BnYXYxRjAwVFpFS3NLbmc0MzdIeElJSmtRZ2RGbjBaS2xZb1JpVVVwWjRrSkVsTVVldEVJY1RCa05kR0hXY3p2T3BzQUZoZThQSGFxTkZlaVpDb2pFdlJqK01mZVdEcXFVSWpkZHJDWWh5ODl5TTBlT09kUm56MHRaSVd3bW9ibWNoTzF0VHl2cUdOZzF5KzVOZThaZnBNRHVpYnlheGltVTFhejVyc1FRdjFVQlFoRW1ISWUwck9VVlFsdGo1M0loU2N3MFVSaVNvM3IzaVpNcDZEKzZiVEZVVU1KdkZJYm1sV0pSS2g3QndDMVB6d015WG5jQzZpNnVOR2Zmcnp2UFlPNTNBSVErcnhUWlJhU1J3YmZjenRxMWZ6Y3EzR2s0T0R6Ty9zNHNqWmM5bTUwb1VUNGZlYmhoaEtZaW9pN0ZMcHBCOVpYUkJaSGVybG16cUFsU2dpSWF6ZG1MVEdiVVVyaXNnSThHWUJtdFcwemJUZ1pNRGJtQkI1NVRlU0J0bDZxZXBtcmRzQWNRUElqZXhjcy9vMm5obld1QkVla0tST2txbkh6RktabzJmTjVjanBmWFE3U0h4Q0FVY3NEaFZISk1LTDFTRnVXL1VLdjl5d2daMHJuZnpaOUQ3MjdPeWtNNHBZbHlRc3JjYmdDdHkzZGlXM3ZySWNnSjBxRmQ0NVp5NXY2ZTNESnpIVm9NMDJhOEJWOVJyM3JGM0R5OVVxend6MGJ3YmZEaDBWOXVxZXhuRXpaMUJTR0xLNks2QnhXQWZWVllpNFk4MXFCaFBQbjA3dlk1dW9RR3poTlJHaDVqMlJDT3ZpbUF1WEx1RzV3Y0ZSZmJSdFJ3Y0ZoSmVyUTlRMUxMQS9jZlpzanBrMWx4ZXFRMVM5WjJGWDkrYkRVZ28rRHFmK2lGQ0tpdnhrN1RydVdiT0tsYlVRS254aDArQ1dBVzZhTm93MTZLMjhud1ZkSGlnYndNbWJJR09WbTMwMmI3M0RDRkRtVUpzc3VGdHA3OEt1THM2ZnZ4TVZFWjRhR01DNUNJL2pzZjcxM0xsbVZYb25NQUI3ZEhZeHIxeml5WUVCVnRhYWJ6dyt0Rzg2cDgyZHk1eGltYXFMV0YydmMrZWFWZHl4YWlXcjZzM2ZlMU5QRHpNTFJSWjBkVE90VUtUaUhBczd5a3d2RlBqaHFwVjg5YVVYQVpqZjBjR2l6aTUyNjZ4UTg4cUwxU3BIenBqT3RDamk4MHVYOHV0TkU5c1hNTE5ZWWsxY3g2dUdDVFJyRGdVUmZCS3pzS3VUeURtdWVmbGw3bGk5cWpXbGx4MkVWZ2VFc05HdFdXeXdnN0NlOWJYZ0FFWEMyb1BaaEIwS3MrMVhtT29QWllIZHFrd3ZGcGxYS2plN3ZSdGhHOUYrRXkxM3UzS1o4M2FjenlsenQyVm1jZFJLdm4wSlh2M2hqSDNVRkR0MWRIRHNqSm5qZDdRSVhkR0VVc0pmSSt3S0gxTjZDd1cyTFpjbmhNOVhBOXd6akNObHR6T1hDWHZNZnJRbHdKTWpCMW9nZjYzOTFsbldheUk3R2c1aWRKcjF0WkpGNXEwZk1rWGxiVVBZOHJMSmtpM3JDSm5DMTBOdUlHekdiTWdmTXpyZFBpNGRuR3JnUnBZSldaS0pSMzdCUE51RnIxSG5IR1pVN1VUQ2ZyQTMyNThkRXlqamQ2MW9ocTFFenJQKzJOOFV4MXhhMjFmM1dzZ3ZDSWVSdks3QWhiQWRaRk5xVnUxdG5mYWhoZ05LMk9INUFHSGYyV2N6Q1lac05rVUlXN1QvYjhQS0FoOGo3UHE5bTVDZWJBYmNab1B6VHNMcXIwOVlIZjR6bFhEWWgzQzR5VHJDK29STENTbEtDT3NXdm1QVzQ5Wk1rbUtlMWV0b0c0eExUZE9kUlRodjRqckNGdmN2TVhJTC96SEFTWVNkQVk4YlBaaEpPUG15SjJYSjdpZWtTVTlJdlh0RVNDTHd1UFhEdGszYWU2V0ZtcG90N0o1dnoveVNzS1A2ME16OUl3Z0xaaDZ6OW1QVzZLek1jeWMzRWlDRWhlOGZJK3pVdlordzJBYkR3WnZzbTVjU3pwTDRmL2IzQXdubmIyU3phU2ZabUcxUjRFTEl2NnNONG1LR2oxZHloSE1LVmdMdklSekorU0xoVElFR0lidUxrY2Z1UkJhWS9xc1UvMVBDSXVvdkVIWVVaMG5tb2ZiTWNZUkEvTjZFWUhkRGJyTXlyN09PdnQ2QU90TjQ0SldFRThjZkJiNWg1bXd1NFN5RlcreWRLMjJDTHN4TTBOV21xUThtSEdTaDF0NnpiVkJXV0I4MDZ2d3RlK1lCNEgwMjRQdll0VmxXamhvSVRrM1JoNk10Q2ZJNXdrNlR4UWFzUEdKNGxKV3gyTXBMeXd3THhmM1UydlVWUzM0MGpwQTl4ZDc5WndQaFgxcmR6ODBKbmQzUDhHbWIrNlhhZmo3RGg4VzhZa21NK1paWWV0a1NVOTh3NEY1czVYYWtNblByMDlSbVN3SVg0Tit0WTFmYVlHQ2Ryb3c4aHVjTmR1MTQrL2N0akR3aks3TEdOdmJtNzJMUFh6VEd0dzlPZ1h1ZC9YbEQ2djdOQnFCU3lxbE1DRXZtMHBtLzlPbVJGeHNGU3NzVERKOGMwMmhIbWp2dWF0YytrN3AyckYxckFQNWZiQUtrMTBIc3gvQ0pOaDlKZ1RodGhYNUpPQ1FqeldQcmpEeE5LQzJuQTZ1c3JPK2t0UG01akQ2RjUxNERGYVlScjhvcDcrT21kTkx5RStEYUZIZlZsTUpweUc4eUZPem5oR01OTmdkZDdMM0dCRHZjWXVoenhnUHVWRGxQNXhuSHZEalZ3SU5NYTkyWEdmemZXWWYva1B6TlVwb1pOTXhFTmszd3BiVFM3K3o5YXNaWmZJamgwMnpXMmF6ZUpoMDF5Mml2UHpDZzMyejNsTEFaOEE4eTlmcEpUbDN2U0YxN3RCSGxNazFUSnFRNGwyZmEzTkEydHhpbGVacHdLczAzR1Q2SkpySDdqWGNLaEJNUTc4N3BrNnZOUWZzWXcyZTF2UmY0UTN2M0psTVNhcFRJbThMWmxuQTRSMHYwTTZOd2xQekRETFBQcFJjMlBHdDlkSktCK2hUem04WTlzWEtxZ0x2ZWdMRWlVMkVoZi9HR3BnQ1RaRUpiSFpuR2FvdVpyQmROWTVEenZVMDVBUE5qZERDbW1hNVA5ZEcvcHNwdnRHRmd2QWlhL1ZsTnRiZFpXOG9XQlRnQStEc3pwenVrTlBpVFJxMGEzNzdLSmtFeldXbnZ6aktUZjRacDZYWFdyZ2FBdm12dDZtalNEelFKYTNZeWNzMXlLLzJSVi80MURLK1BQZ1Q0NjFZQU4xWEFqWExLdTh1Y3NmMVNXdmNOaEFQZUdwcHFyV21OZExpa2g5R0gzTFVTRDA1YUFGQ3IvZkN3OGQ4ZjBHVHJTRTY5Tk1VeEY2Y2NSeklBazNIcXVOeWNtcktaL0FzSVJ5VE5uSUEyekxZdHR2bzFqc2U2TFllemxvei9ucHFqeGRlWW85eEpTRmx2WTA3c2J5YzRUb1djOXQ5a2JUekhsTjlQWGt2Z2luVjBPZ3IrZ00ybW04MXJyaEVPYXJzNVZibnJ6WEc3Z0hEWTNJZnRla2VxSTRTUjYwZWJEZmlQVEpzMU5OSXBwc0c2YzBEZG02bnIwOGFybHhxZHVZS3dHN2pCYTJPakloZVo1bXVjMXAwZHFMcnh2RUhqbUplWlJsdVcwbExUY3NiQW1WVTQwT0tjdnpYUS85eWV1ZEQ2N0NiamxYUE5FZjBvbzNmWHZzdkF1ZGlVd3NsVzc4VGVQZHNpRXhkWlBZOHhaK3kvck80M0V4WVYzVWs0ZXZVS1UwSnFmNy9OK3JhVW9sZU5OcmljbUhJNkxQbWtSUXp1TTcvaVFjTEt0SHNNQTE5bi9KTXl4eWEvRTNUT0tqWmo5c29CMVZsV3Nmdk1BY291V1A1TEEva2RGdlo2VHlvazFXdjhlYzQ0SWJuenpPUCtmT28zS3hWeU95NWpIYzdLMUhWWGN6QWZadmcvN05qUkJ2UWg2K0FyVW1YT3NXK205Mzh0c0FFLzFjcDZ4RGgvSmVQeG41eXAvN2JtTkpXTlE5OXV2Tzh5UnU3NFBkQWlJNCtZUnZ4a0UrMjlEK0hFeHNlTjU1NmFlVzZ1VGNZSHJXMVhNL0xNcm9Oc2dqeENPSG16RWI1OHE0VVNmMkdUK21pR0Q2cHJ0Q0g3UHhDZHljZ0UxVHlMNHo1aW5Mc2hiN09KY2RCckZjZHR5MGpncWpsaWJabVluR3RSbkdLcndDMjArMnpLcEdFbXU5cGQwYks4d1N6c1gxbGN1L1d6QjlvYWQ4cWsyL2hiWDdzcldwYkRqTTZjUGxGOFNodWdiZG1helZ0YjJ0SUdibHZhMGdadVc5clNCbTViMnNCdFMxdGVSL24vQXdDTzQxTEJDanowOHdBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wOC0wMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRklETyBMMSBDbGllbnQvQXV0aGVudGljYXRvciBDb21ibyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVUFGMTAwMDIwMTgwMjIxMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDgtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTA4LTAxIn0seyJhYWd1aWQiOiIxNzVjZDI5OC04M2QyLTRhMjYtYjYzNy0zMTNjMDdhNjQzNGUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjE3NWNkMjk4LTgzZDItNGEyNi1iNjM3LTMxM2MwN2E2NDM0ZSIsImRlc2NyaXB0aW9uIjoiQ2h1bmdod2EgVGVsZWNvbSBGSURPMiBTbWFydCBDYXJkIEF1dGhlbnRpY2F0b3IiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJ6aC1DTiI6IuS4reiPr-mbu-S_oeaZuuaFp-WNoUZJRE8y6Lqr5Lu96amX6K2J5ZmoIn0sImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNOekNDQWI2Z0F3SUJBZ0lVWHh3RWtVSDQraEIxbFU4RkpOcEJnek81Mldvd0NnWUlLb1pJemowRUF3TXdVakVMTUFrR0ExVUVCaE1DVkZjeEdUQVhCZ05WQkFvTUVFTm9kVzVuYUhkaElGUmxiR1ZqYjIweEtEQW1CZ05WQkFNTUgwTklWQ0JHU1VSUE1pQkJkWFJvWlc1MGFXTmhkRzl5SUZKUFQxUWdRMEV3SUJjTk1qTXdOREUxTVRBMU1ETTBXaGdQTWpBMU1EQTRNekV4TURVd016UmFNRkl4Q3pBSkJnTlZCQVlUQWxSWE1Sa3dGd1lEVlFRS0RCQkRhSFZ1WjJoM1lTQlVaV3hsWTI5dE1TZ3dKZ1lEVlFRRERCOURTRlFnUmtsRVR6SWdRWFYwYUdWdWRHbGpZWFJ2Y2lCU1QwOVVJRU5CTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUVjdU9uY2t6VXBIczMwQmZBcUVqbmFUaDdRSWJic2g2SU85bWlvWFQyNlRxNThPVCtVclFtak1aV092VGI1S01lSDdBdU1uUDB2dHVSaTdOd3liakZwTFoweitOVlFXTGxpK3k2TXJRK0xBWHNrTHVibGR5akxtbHJyRWIzYm5WNG8xTXdVVEFkQmdOVkhRNEVGZ1FVaTFoRmd2cnc5eWkrZHZFMlRpQVZuaGMwSlVvd0h3WURWUjBqQkJnd0ZvQVVpMWhGZ3Zydzl5aStkdkUyVGlBVm5oYzBKVW93RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQXdObkFEQmtBakFXQm9wYUw0anhvWWJ2QzV6Y2pKTy9KRXQ3MlZpUWFvbTFwS3ptUG1LaWZsZnRpOUlJbjNyejFqaXRQM3p5bkM0Q01IWk50MXdNSnROYkZSNVJJWmZ2RXRFN200bys4Z2RqclpqSVlxK09qQVliNUZHNU1NV1BKZi9lWUZHVElvV1RGZz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUlRQUFBQ0dDQUlBQUFDVDdyWDdBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNNQUFBN0RBY2R2cUdRQUFBemJTVVJCVkhoZTdaMzVVeFJYSHNBRFlhUHhJSnBzRWxPbE1WZVpzemFwelZHcDJ0cXRaSk0xaWFsY3U4bUFpSWhHV0VFbGVNU05obzA1dkNVYVNUeWlFZHc1WUJpWUFkUUJZYmdQR1JoT004ekFESWpJRGNQbFg3RGZMRnVXOWJYcDZlNTViL3FKWGZYNVFTMzdYWjk1Vi9jNzduQ1BYVk5nQkVVR1F5Z3lHSUpkR2E3UmE0N2g4WWEra2FvclEzbU8zcFRLOXE5TnpaRW5xdDdZWlhsNmM4NkNLRU53Uk5yTU1GMVFxQ1lvNUgrRWFtYUU2ZVpHcEQwWVpYaHFVL1pmdnl1QS83elQxSFM2d3AzYjBsUFZPUVJCUVlBUUxJcUlIWmlUMFRZNlVkdnR5V3pvT3BocmowbTJ2ck92OEtuNDdPQlZhWUVxOVIyZlNBRWVCRU5QeG1lL3ZiZHdYYkwxZ05tZVVYK2w1dXB3MjhnRWlscDJHSkxSM0QrcXFlNVljL0xpeXp2TUQ4Y2FaNjlNbFN4Z0tnSlU2dG5ocVl0aWpDOXZOME85T1ZQVjN0US9ncEloSS9MTGdLcFEwVEc0U1d0N0tEb2o0S2Jpb3dwRTk4RGE5QTFuYWtyZEE1QU1sREQvSTVzTTEraEVlY2ZnVDRYT2p3K1gzYk1xRFJXVG40RjI3S1B2UzVJc3p0SjJPYTNJSnNQVzdZSE1yenR0RFQ5YXdRalJwNnQvS0hCQWQ0S1M2amRra3dIOXAzMW9qRUZhNWV2WUdlckFGUlFaREtISVlBaUtNbUJZNHZTTUMyYUM2akJHWkdLbWhHb2lhY213OVhoMm1wclducm9vaEtoZnFyL09hb2FSTGdxRUlEcnJaUlNwTlA2ZDJVUnZ1RVZlaG12MFdtNUx6N0w5UlVHaEdqU2M1K1RPRU0zUzNSWmR6ZVdXb1hFVUZFRyswTmVqZUtVQnFYMTdiK0c1UzkwMDNuR1JsNUhaMExYa3Mrd0FZVzh5WUxwMzZJSURCcFFvRU9LUWtnRkExaDdmbUpWdTYwUlIrQTVKR1E3UCtDL2w3dnZXcEtQVWN3SS9zVmNUY28wTlhTZ1FTaENVTWNuODFmcmpKYTB0d3lSck16RVp2dzZPUVNjeEt6d1ZKWnFUR1dIYU5TZXJpbHo5S0JCNkVKY0IzTDFDbDVEUjJEd3dpdUtTREJrWk1CWUNFL2V0MGQrMVhPdVYrWkg2L1dZN3lFT0JVT1ZMUXdOS0JoSHVYYVBmWVdpQUpnRkZKdzB5TXFBM2c4SzlKQXl5VlZzZ3p1RnhsQXhTUU1aSmRlYmtPM0FGeVNneUdFS1J3UkNLRElhUUtLT3NmZUJVdWZ0a21Vc0liZ2ErYUJhNytsR3FLQUhGVXVvZVFMRUxSSW9NVzQvbnZRUEY5MFRxWWY3TXo3eElmZlRwYXZTNExPdzBOcUcwMFNKU3YyeGZrVlhTK3l2Uk1tQktzVFcxRHViUGFBWjBNd0dmcUovWm5KUHY3RVVoeUFLTlNkOVVRT0hFYTJ4TzhaTVAwVEowMWc2Qkx6eUNJOUtTQ3Azb2Nibndwd3dBSnJabnF0cFJHcndpVGtiTjFlSEhOcGhReEp4QXRmZ3dzZGdoeC95T0V6L0xBQmJIR3FzNnhYMFVFQ0dqZFdUaTQ4TmxLTXFwbUIydWM3RzBaTS8vTW9BUEVrdGFQU0lLUVlRTUdFRkZISzk4WjEraEVDUlVVcXI4WE9aQ0tmUUQ0Y2NxUkwwTUZkMW5LTkJEa2NFUWlneUdVR1F3aENLRElieklhQnVaU01oc2VDTE85TWo2VEs4OHV0NTRzc3lGUXZDZDJHUXJpdWlXNC9HTnh1M3A5VjYzNTNpUkFjUFpWM2FZMGZCNUt1NWRuVTdqWTJySWtYSVUwYTNJSDc4NFgreHRtT3RGUnBMRk9YdWxvRFVHZ09wSUdZMEZkOU5EeHF4dzNhRjhCOG9hZ2s4R2xPemZENVdpUUtjaUtGUjdyTGdOaFVDRTZTRURXTGEvaUwrbDRwTlIxajRZTEhoUDBjSjFtWmwwRmtGTkd4bHpWcVlXdGZHMVZId3k5cCszUDc3UkpJeXNGVDlWMVBWUzJhem9meG1CS3MzOWF3MDM1WkVBMzJRMW9kemRDSitNbXF2RHhlNEJJWlM0QjJxdWVpaHRzZmEvakFDVitwVXZ6YWJHTHBSTjMrSC82T1NsQTJjQnVacXBkL2NWTmZVVFd5MG9CRVVHSCsvc0xZUktqOUpERDBVR0gwRWhtbzhPbFZSM0RhRWtVVUtSNFFYb3pEZitwNVpTZDRqZ2tBRVJsM2NNcHRaYzFnbkcwdHFIQWlHSXZES0FvRkROQWJNZFpka1h5dG9IT08xeXlIQU1qMjg0VXdNVDcxbmhRdGw0cGdZRlFoRFpaUUIzTGRlaUxFc0dDalltMmNxNVRZdERSa1B2eUZ0N0NsRnErSUVaQ1FxRUlDeklJTXZyM3hiVTlYRE15VGhrVkhVT0xma3NHejNQUThBbmFxMjFBd1ZDa09rbjQ3RU5XWldYT1JhT2NNakliZW1aR3lIaVpKVkFsZnI4cFc0VUNFR21uNHc1SzFQUC84cFJZaHd5VGxlNFlRaUJudWNCWlBDL2N2R1I2U2NEU3V4RUtjZExWZTZhOFpXeFVUZzdUVTJOZlJTUDBHSk54cUtZeklSTVhBaGlPY2ZWbG5ESVlBM1daUHgrVGJxaDdvcnJwblQ2amlKRE5JRWhtdENrY29LYlhLK2p5SkRDL1orbXM3NHBueEpzZHVBd2NVUHA5QjBPR2JYZEhyRlFmZFhNcGd6b09VcmNBNmdjUklHeUNYREllR0hidWVlMjVJZ2k0bGdsQ29RZ2JNb0Fub3pQUnVVZ0hDaGtsRTJBUTRiQTAzQnU1Tm5OWjFFZ0JHRldoaThFaFdoUU5nRU9HWGVLbWZGTnNpakdTSytsbXBZeVlONkhzZ2x3eUJBMS9aNWtmcVRlMUhnVmhVT0syMW9HMUNEMHBGZG1oT2xnSG83Q0ljVnQzVXc5dStYc2t2aHNVVHkxS1dlN29RR0ZRNG80ZFMyS1RnTDNyeldnNGlCQ2dFcTlJRG9EeFNXRVp6Ym5vR3dDSERMS093YkxPZ1pFQVkvVTlYQ00xWWdBSWFQb0pCQ2JZa1hsU0FUNGdXL1cya3JiY1hSZTRUeVFrVVBHdElUZUJrdlF6Tlo1VSt4RFQ4YlMzUlpTSTBsRmhxL0FzTDY2aTh6aHFvb01YNW14WEZ0QWFIRU1oNHhTOThEUm9sWnBaTlNSZjVkSkJLcWI4ajlQcTBmbDRCWE9iNk1jTWs2VnUyRktndUlUQ016K0d2djh1ajVWSUZSbGlBV0tsM012QzRjTXM3MW5qdURkU2dnWWQ5T2IvZmtDVXpKbWg2Y0svZXhhMlRuMFJGd1dlbDQ0cnliazBwdHpTSVlwR1krc04xVUlYS3BUM3p2eXQ5MFc5THh3UVBzK3M5MC9pMU9GdzVTTTE3N0o1L3k5Y3Nob0dSNWZsMnlGUWNLTnArbUs0dlZ2ODIyTVZRNnFNZ0pWR2xRQ1BFREJScDJxNWp6K25VTUcvS2hMM1AwcGxlNWtxYWd2ZHZqNVFHZXZVSlh4OGc0ektnRWVvR0NMWGYxQ0Z6NVBTNmpLZVA5Z0NZcE9Hb29NQW9RZkpmUFZXWkZCZ0RoMUxZcE9Hb29NQXV6S3VZU2lrd2FmREZ1M3A3eGowSGRZNk15cHl0aDcvbGVVNWFuZ1hLRnpIVDRaQjNOYm50dHkxbmRXSGEveXcwVSsvRkNWOGVnR0U4cnlWUERYSVQ0Wk1BSVRmb29MRHpBTWowbTJ5bmhOSjBCVmhrQm1yZEFWT1BuZTcvTEphQnVkZVA5Z01RcFJHak5YNkhhZnZVVDFranQrV0pDeGRJOUYra0V1d09GOHg2eHdIUXBVR3ZOWDZ4UHpXbHd5K1pCZEJ2d2NEK2JhK1RjU2VKRUJVL0VYdHdzOS9Nc3JjeVBTZGhnYXZCNUlSZ1BaWlR6LytibENiOStndk1pQWd0dWFXdmRnbE9HK1QvVkVXTGd1RXpveC85Y1BTaklDVmVyZ1Zha29qemZ6UUZSNnZNYm10ZGYwSW1QYVFFbkdZeHRNV1UzRWxsSXFNbnppVDEvbE5aRGJ6NmpJa0U2QVN2M3B5WXNFbTF4RmhuU0NRalNjWDA4bG84aVF6aE54V1dSdmFoWWhvN3hqTVBwMDlUOE9sOTZLL0dIcldWU1V2Z085TjRvRnNmYlVSYTluMmQ2SUNCbE96L2lIMzVlZ0JDbndzR3gva2FpN2RjUTFVMVdkUTR0ampTaEtCVTRXL2pOVDdCMXhvdnVNbEVyM3ZFZzlpbGdCRVJ5UmRwTHJkQkIrUk11QXhpcE9YU3ZrYXJqYmxrQ1ZKamFsUnNMbFg2SmxBTlZkdzIvdHNjeU5TSjJ6MGg4RWhXcFJidVhsZDZGYWxNSWJnV0o1YzFjQnRPZW8wSVFnUlFaUTBOcDNwTUJ4T044ZnZDVDRtZ0wvQUdNa2xNSWJnV0tSZkUra1JCbis1QU9XaG5BdmJUL2ZQRURycTZVaVF3UXp3M1JrcDl3SVJZWlF3TVFtcmEyRjVwMmNpZ3lodkpxUVc4YTFSWlVneEdRNFBSTXdtS01CcWUvd3ZoQVVvczJ6OXppR3gxRGFBTWc0S2dySmtKSGg4SXduWkRRdWlETE1oYkVkYVdBb2lZckcvd1NvMUNoVmt6eTQxckF0clk1VTIwV3NaalQxai80cnZYNUdHRnR6QXFyY3RWeTdOZFhXUU80S0Y1SjlobjFvN0VkTHEvQ2JnVzVwWUg1M0tLK0Y3R0pKOGgyNDFucDVjYXdSNmpWSy9iUUJzcll3SnBQR3RjN2taYmhHcjVrYXU5NzRybUJhdnI4S1ZHbGUreVkvbys0S2pRVjU1R1ZNY3ZISzBMYTArbzkvS1BVZC83KzBENDVJZTN0dklVckdKRnUwZFpXUzNqc0pnWllNb0hWa0FvWVp2dk9lZjRlMk1JcE56R3V4RCtGa1RFSjF4VEJGR2FUdzI2UVB4dEJQYjhveDFGMUJDZkFiaW96L015Tk1GNUpVbnRmU1MrTmNiWUVvTW40RHBxdEhDaHdFbDZOSlF6WVpNQnFCZWJzUTNrK2syR2ZBTEhYcEhvdWx0ZTk2ZERMdVc1Qk5SbVBmeU0rbHJzMWFXMHlLTlNhWmp5WHhJcTY1RWN2aTljWlZKeXAvaXlqRnVrbHJPMTdTUm5CR0xSYjVhc2JJUkdGYlgyS2UvYTA5aGJQQ0NleVA4b1c3VitqZTNGVnd3R3lIS2lMakRpdVord3pvTGNGS2diTXY0bGpGdmF2VEEyNHFKcXBBZFBNaTllRkhLeTQ0ZWlFWk1uYmRrekRVZ2RmMWVJNFd0WVltbGIrdzdkeEQwUmt6VitpSXYxT0JBR2VHNlJaRVp6eS83WnpxU05tUGhVNGI3L1pUUDhPUWpFbWdsYWpzSE5SVWQzeVgwN3o2NTZxL2ZIM2g0VmdqTkNPU3hjQ0Q4UGlpR09PZmQxNklQRkgxYlhhenVycWo0dktnak0zUlZEQW40enF1MFFuNzBKaXQ1N2U5NkRuTlYrRlgvSm1tOXNQdlMxN2FibjQ0eGdqTkMvekdnMEkxZ1NvTnREWUEvQUgrQ3Y4NEx6SU5pdjdGTDh3ZkpKYkVxV3VUTE03czVtNElCSUtDQU9YYVZDZ0VkbVhjaGlneUdFS1J3UkNLRElaUVpEQ0VJb01oRkJrTW9jaGdDRVVHUXlneUdFS1J3UXhqMS80TEZOUk00TDd3aGc0QUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiLCJjcmVkUHJvdGVjdCIsImNyZWRCbG9iIiwibGFyZ2VCbG9iS2V5IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjE3NWNkMjk4ODNkMjRhMjZiNjM3MzEzYzA3YTY0MzRlIiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZSwibGFyZ2VCbG9icyI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMDI0LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjE2LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjQ4LCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoxMDI0LCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjoxLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDctMTkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkNodW5naHdhIFRlbGVjb20gRklETzIgU21hcnQgQ2FyZCBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzA3MTkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wNy0xOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTAtMDMifSx7ImFhZ3VpZCI6IjNiMWFkYjk5LTBkZmUtNDZmZC05MGI4LTdmNzYxNGE0ZGUyYSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiM2IxYWRiOTktMGRmZS00NmZkLTkwYjgtN2Y3NjE0YTRkZTJhIiwiZGVzY3JpcHRpb24iOiJHb1RydXN0IElkZW0gS2V5IEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJxVENDQVUrZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQTdNU0F3SGdZRFZRUUREQmRIYjFSeWRYTjBJRVpKUkU4eUlGSnZiM1FnUTBFZ01URVhNQlVHQTFVRUNnd09SMjlVY25WemRFbEVJRWx1WXk0d0lCY05NakV3TXpBeU1EWXhPRFE0V2hnUE1qQTFNVEF5TWpNd05qRTRORGhhTURzeElEQWVCZ05WQkFNTUYwZHZWSEoxYzNRZ1JrbEVUeklnVW05dmRDQkRRU0F4TVJjd0ZRWURWUVFLREE1SGIxUnlkWE4wU1VRZ1NXNWpMakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSXprTWR0Tlp0MFpPek8rdTFmMkVLWlJTbmZodnl3YmhvbkJGOU5TUHEyV0c3bnVSaS95dlo4bERqd3A1ZGFyUTZPZFpnK0hxYlNTZVhKWHc3VXBjbFNqUWpCQU1BOEdBMVVkRXdRSU1BWUJBZjhDQVFBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUIwR0ExVWREZ1FXQkJSald4VG8xRXEzM1pyeGZMRFdzc2RkYkQvdlpUQUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQitFMDlHem1jWWxNOTVxVC9hZm5QVTlxNlhKbXhPU0tXQVJPNStrZ1VuV2dJaEFJYTluNXA0MHRjR2ZtZUY2L1d2WW9qQU51eWtRcWhWazhXbmZnMTVTNjlyIiwiTUlJQnpUQ0NBWE9nQXdJQkFnSUpBTFMzU2liR0RYVFBNQW9HQ0NxR1NNNDlCQU1DTURzeElEQWVCZ05WQkFNTUYwZHZWSEoxYzNRZ1JrbEVUeklnVW05dmRDQkRRU0F4TVJjd0ZRWURWUVFLREE1SGIxUnlkWE4wU1VRZ1NXNWpMakFlRncweE9URXlNRFF3TmpVNU5EQmFGdzAwT1RFeE1qWXdOalU1TkRCYU1Ec3hJREFlQmdOVkJBTU1GMGR2VkhKMWMzUWdSa2xFVHpJZ1VtOXZkQ0JEUVNBeE1SY3dGUVlEVlFRS0RBNUhiMVJ5ZFhOMFNVUWdTVzVqTGpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkE1bWpZc2pvd0FJMGpucGkvL0NKM0tuemhHYlRVbXN0TldxTjc4aW9HMUNUSzlnUGdQbDlVaUZPSk8vditGZkZLK1B4djEwYzYwNGR2bElEQWJLdytpallEQmVNQXdHQTFVZEV3RUIvd1FDTUFBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUIwR0ExVWREZ1FXQkJTZ1d0WTBuRWNtUG1HREx1Q3djZUtlSlBTY296QWZCZ05WSFNNRUdEQVdnQlNnV3RZMG5FY21QbUdETHVDd2NlS2VKUFNjb3pBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlBeG9WczZxajdEWDJ4aXhDampjRFVkeEJUSm1TVExiMGYxclJHd3JBQnpUUUloQVB0MFAzMnF6QWVlcEY0Ly90Z3p4cU5vS2tXRGNhUFBTWHJnK3h6cmxWSHciLCJNSUlCenpDQ0FYYWdBd0lCQWdJQ0FTQXdDZ1lJS29aSXpqMEVBd0l3T3pFZ01CNEdBMVVFQXd3WFIyOVVjblZ6ZENCR1NVUlBNaUJTYjI5MElFTkJJREV4RnpBVkJnTlZCQW9NRGtkdlZISjFjM1JKUkNCSmJtTXVNQ0lZRHpJd01Ua3hNakEwTURZMU9UUXdXaGdQTWpBMU1UQTBNRGN3TXpBMU1EQmFNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXhNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBNW1qWXNqb3dBSTBqbnBpLy9DSjNLbnpoR2JUVW1zdE5XcU43OGlvRzFDVEs5Z1BnUGw5VWlGT0pPL3YrRmZGSytQeHYxMGM2MDRkdmxJREFiS3craWpaakJrTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUIwR0ExVWREZ1FXQkJTZ1d0WTBuRWNtUG1HREx1Q3djZUtlSlBTY296QWZCZ05WSFNNRUdEQVdnQlNnV3RZMG5FY21QbUdETHVDd2NlS2VKUFNjb3pBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBa3JMTTVWM0RuRDBYY1ZVRlcrTk1GY0JaQ08xRnh5WXo0VmtQSDNBN0tHUUlnSGF5VGZVODhvSUVpTU5heDEzdGdaYW9oaE1BWEVNanFUeUl0YmNUVDhRYz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBakNBWUFBQUQxN2doYUFBQUFCR2RCVFVFQUFMR09mUHRSa3dBQUFDQmpTRkpOQUFDSER3QUFqQThBQVAxU0FBQ0JRQUFBZlhrQUFPbUxBQUE4NVFBQUdjeHpQSVYzQUFBS0wybERRMUJKUTBNZ1VISnZabWxzWlFBQVNNZWRsbmRVVk5jV2g4KzlkM3FoelREU0dYcVRMakNBOUM0Z0hRUlJHR1lHR01vQXd3eE5iSWlvUUVRUkVRRkZrS0NBQWFPaFNLeUlZaUVvcUdBUFNCQlFZakNLcUtoa1J0WktmSGw1NytYbDk4ZTkzOXBuNzNQMzJYdWZ0UzRBSkU4ZkxpOEZsZ0lnbVNmZ0IzbzQwMWVGUjlDeC9RQUdlSUFCcGdBd1dlbXB2a0h1d1VBa0x6Y1hlcnJJQ2Z5TDNnd0JTUHkrWmVqcFQ2ZUQvMC9TckZTK0FBRElYOFRtYkU0NlM4VDVJazdLRktTSzdUTWlwc1lraWhsR2laa3ZTbERFY21LT1crU2xuMzBXMlZITTdHUWVXOFRpbkZQWnlXd3g5NGg0ZTRhUUkyTEVSOFFGR1Z4T3BvaHZpMWd6U1pqTUZmRmJjV3d5aDVrT0FJb2t0Z3M0ckhnUm00aVl4QThPZEJIeGNnQndwTGd2T09ZTEZuQ3lCT0pEdWFTa1p2TzVjZkVDdWk1TGoyNXFiYzJnZTNJeWt6Z0NnYUUvazVYSTVMUHBMaW5KcVV4ZU5nQ0xaLzRzR1hGdDZhSWlXNXBhVzFvYW1obVpmbEdvLzdyNE55WHU3U0s5Q3ZqY000alc5NGZ0ci94UzZnQmd6SXBxcytzUFc4eCtBRHEyQWlCMy93K2I1aUVBSkVWOWE3L3h4WGxvNG5tSkZ3aFNiWXlOTXpNempiZ2NscEc0b0wvcmZ6cjhEWDN4UFNQeGRyK1hoKzdLaVdVS2t3UjBjZDFZS1VrcFFqNDlQWlhKNHRBTi96ekUvemp3ci9OWUdzaUo1ZkE1UEZGRXFHakt1THc0VWJ0NWJLNkFtOEtqYzNuL3FZbi9NT3hQV3B4cmtTajFud0ExeWdoSTNhQUM1T2MrZ0tJUUFSSjVVTnoxMy92bWd3OEY0cHNYcGpxeE9QZWZCZjM3cm5DSitKSE9qZnNjNXhJWVRHY0orUm1MYStKckNkQ0FBQ1FCRmNnREZhQUJkSUVoTUFOV3dCWTRBamV3QXZpQllCQU8xZ0lXaUFmSmdBOHlRUzdZREFwQUVkZ0Y5b0pLVUFQcVFTTm9BU2RBQnpnTkxvREw0RHE0Q2U2QUIyQUVqSVBuWUFhOEFmTVFCR0VoTWtTQjVDRlZTQXN5Z013Z0JtUVB1VUUrVUNBVURrVkRjUkFQRWtLNTBCYW9DQ3FGS3FGYXFCSDZGam9GWFlDdVFnUFFQV2dVbW9KK2hkN0RDRXlDcWJBeXJBMGJ3d3pZQ2ZhR2crRTFjQnljQnVmQStmQk91QUt1ZzQvQjdmQUYrRHA4Qng2Qm44T3pDRUNJQ0ExUlF3d1JCdUtDK0NFUlNDekNSellnaFVnNVVvZTBJRjFJTDNJTEdVR21rWGNvRElxQ29xTU1VYllvVDFRSWlvVktRMjFBRmFNcVVVZFI3YWdlMUMzVUtHb0c5UWxOUml1aERkQTJhQy8wS25RY09oTmRnQzVITjZEYjBKZlFkOURqNkRjWURJYUcwY0ZZWVR3eDRaZ0V6RHBNTWVZQXBoVnpIak9BR2NQTVlyRlllYXdCMWc3cmgyVmlCZGdDN0g3c01ldzU3Q0IySFBzV1I4U3A0c3h3N3JnSUhBK1hoeXZITmVITzRnWnhFN2g1dkJSZUMyK0Q5OE96OGRuNEVudzl2Z3QvQXorT255ZElFM1FJZG9SZ1FnSmhNNkdDMEVLNFJIaEllRVVrRXRXSjFzUUFJcGU0aVZoQlBFNjhRaHdsdmlQSmtQUkpMcVJJa3BDMGszU0VkSjUwai9TS1RDWnJreDNKRVdRQmVTZTVrWHlSL0pqOFZvSWlZU1RoSmNHVzJDaFJKZEV1TVNqeFFoSXZxU1hwSkxsV01rZXlYUEtrNUEzSmFTbThsTGFVaXhSVGFvTlVsZFFwcVdHcFdXbUt0S20wbjNTeWRMRjBrL1JWNlVrWnJJeTJqSnNNV3laZjVyRE1SWmt4Q2tMUm9MaFFXSlF0bEhyS0pjbzRGVVBWb1hwUkU2aEYxRytvL2RRWldSblpaYktoc2xteVZiSm5aRWRvQ0UyYjVrVkxvcFhRVHRDR2FPK1hLQzl4V3NKWnNtTkp5NUxCSlhOeWluS09jaHk1UXJsV3VUdHk3K1hwOG03eWlmSzc1VHZrSHltZ0ZQUVZBaFF5RlE0cVhGS1lWcVFxMmlxeUZBc1ZUeWplVjRLVjlKVUNsZFlwSFZicVU1cFZWbEgyVUU1VjNxOThVWGxhaGFiaXFKS2dVcVp5Vm1WS2xhSnFyOHBWTFZNOXAvcU1Ma3Qzb2lmUksrZzk5QmsxSlRWUE5hRmFyVnEvMnJ5NmpucUllcDU2cS9vakRZSUdReU5XbzB5alcyTkdVMVhUVnpOWHMxbnp2aFplaTZFVnI3VlBxMWRyVGx0SE8weDdtM2FIOXFTT25JNlhUbzVPczg1RFhiS3VnMjZhYnAzdWJUMk1Ia012VWUrQTNrMTlXTjlDUDE2L1N2K0dBV3hnYWNBMU9HQXdzQlM5MUhvcGIybmQwbUZEa3FHVFlZWmhzK0dvRWMzSXh5alBxTVBvaGJHbWNZVHhidU5lNDA4bUZpWkpKdlVtRDB4bFRGZVk1cGwybWY1cXBtL0dNcXN5dTIxT05uYzMzMmplYWY1eW1jRXl6cktEeSs1YVVDeDhMYlpaZEZ0OHRMU3k1RnUyV0U1WmFWcEZXMVZiRFRPb0RIOUdNZU9LTmRyYTJYcWo5V25yZHphV05nS2JFemEvMkJyYUp0bzIyVTR1MTFuT1dWNi9mTXhPM1k1cFYyczNZayszajdZL1pEL2lvT2JBZEtoemVPS280Y2gyYkhDY2NOSnpTbkE2NXZUQzJjU1o3OXptUE9kaTQ3TGU1YndyNHVyaFd1amE3eWJqRnVKVzZmYllYZDA5enIzWmZjYkR3bU9keDNsUHRLZTM1MjdQWVM5bEw1WlhvOWZNQ3FzVjYxZjBlSk84Zzd3cnZaLzQ2UHZ3ZmJwOFlkOFZ2bnQ4SDY3VVdzbGIyZUVIL0x6ODl2Zzk4dGZ4VC9QL1BnQVQ0QjlRRmZBMDBEUXdON0EzaUJJVUZkUVU5Q2JZT2JnaytFR0lib2d3cER0VU1qUXl0REYwTHN3MXJEUnNaSlh4cXZXcnJvY3JoSFBET3lPd0VhRVJEUkd6cTkxVzcxMDlIbWtSV1JBNXRFWm5UZGFhcTJzVjFpYXRQUk1sR2NXTU9obU5qZzZMYm9yK3dQUmoxakZuWTd4aXFtTm1XQzZzZmF6bmJFZDJHWHVLWThjcDVVekUyc1dXeGs3RzJjWHRpWnVLZDRndmo1L211bkFydVM4VFBCTnFFdVlTL1JLUEpDNGtoU1cxSnVPU281TlA4V1I0aWJ5ZUZKV1VySlNCVklQVWd0U1JOSnUwdldremZHOStRenFVdmlhOVUwQVYvVXoxQ1hXRlc0V2pHZllaVlJsdk0wTXpUMlpKWi9HeStyTDFzM2RrVCtTNDUzeTlEcldPdGE0N1Z5MTNjKzdvZXFmMXRSdWdEVEVidWpkcWJNemZPTDdKWTlQUnpZVE5pWnQveURQSks4MTd2U1ZzUzFlK2N2Nm0vTEd0SGx1YkN5UUsrQVhEMjJ5MzFXeEhiZWR1Nzk5aHZtUC9qaytGN01KclJTWkY1VVVmaWxuRjE3NHkvYXJpcTRXZHNUdjdTeXhMRHU3QzdPTHRHdHJ0c1B0b3FYUnBUdW5ZSHQ4OTdXWDBzc0t5MTN1ajlsNHRYMVplczQrd1Q3aHZwTUtub25PLzV2NWQrejlVeGxmZXFYS3VhcTFXcXQ1UlBYZUFmV0R3b09QQmxocmxtcUthOTRlNGgrN1dldFMyMTJuWGxSL0dITTQ0L0xRK3RMNzNhOGJYalEwS0RVVU5INC93am93Y0RUemEwMmpWMk5pazFGVFNERGNMbTZlT1JSNjcrWTNyTjUwdGhpMjFyYlRXb3VQZ3VQRDRzMitqdngwNjRYMmkreVRqWk10M1d0OVZ0MUhhQ3R1aDl1ejJtWTc0anBITzhNNkJVeXRPZFhmWmRyVjliL1Q5a2ROcXA2dk95SjRwT1VzNG0zOTI0VnpPdWRuenFlZW5MOFJkR091TzZuNXdjZFhGMnowQlBmMlh2QzlkdWV4KytXS3ZVKys1SzNaWFRsKzF1WHJxR3VOYXgzWEw2KzE5Rm4xdFAxajgwTlp2MmQ5K3crcEc1MDNybTEwRHl3Zk9Eam9NWHJqbGV1dnliYS9iMSsrc3ZETXdGREowZHpoeWVPUXUrKzdrdmFSN0wrOW4zSjkvc09raCttSGhJNmxINVkrVkh0ZjlxUGRqNjRqbHlKbFIxOUcrSjBGUEhveXh4cDcvbFA3VGgvSDhwK1NuNVJPcUU0MlRacE9ucDl5bmJqNWIvV3o4ZWVyeitlbUNuNlYvcm42aCsrSzdYeHgvNlp0Wk5UUCtrdjl5NGRmaVYvS3ZqcnhlOXJwNzFuLzI4WnZrTi9OemhXL2wzeDU5eDNqWCt6N3MvY1I4NWdmc2g0cVBlaCs3UG5sL2VyaVF2TER3Ry9lRTgvczNCQ2tlQUFBQUNYQklXWE1BQUE3RUFBQU94QUdWS3c0YkFBQUFJWFJGV0hSRGNtVmhkR2x2YmlCVWFXMWxBREl3TVRnNk1EVTZNamdnTVRZNk5ESTZNVFQ5aHdyZkFBQUlIVWxFUVZSWVI1MVhDMUJVNXhYK2RsbGdRZDRQVVJBZmlTaGFORzFpN0JodG0wNUtVa25UV0IrTlFhMFlHMk9EbGpvT0drMWlPNTFxTkdRY2s5b2tSSnMwNEl3NnB1TjBURXhUYU9zWVM3U1NwaHBmMUtBVkJSWmhXUjRySUx0N2I3L3ozN3ZzUWhhQy9TNy9zdnozdk0vNXovbXg2QVNHQ1oyUC9GZ3M4cGY2NklOZmpNVjRPV3hZemQvRGcrWlhZRUhsSjUvanZnV2I4T2pxSFdoc2NhbjlPMVV1R0Y0RWhNUVUzdHJoUnQ3cWwzR3FzaHBJaUFGOFBxRHJOcFlWNU9IMUYxY2dKam9xS0ZMQ0krSUhOMng0RVRDVi8zemJINUE4Y1JGT1ZWOENSaWNEVVpGQU5KZlZpdklERmFqNjl4ZUtUaWtrajZiUkZIMXc1WUpCSXREZjZqOVZuc2E4WjNiUVd5OFFTNit0NWp0M3Q0ckExczBGMkx6cWNXT1A2TDFhcDR5S0dEZkczQ0VHQzRRWUVBeU5qeCsxMTV2MEtZK3UxNUdXcHlNblg4YzBXVXQxWkQraEkrbGhmV0hSVHQzcjlablVCaHBYYmRUUElWdy9qeEc2WTgwV2M1ZHlmUUc1d1JpMEJ2S0xkMk4vMlFmTWN5eGdaNWdGa3UrV2RveWNPQVpWKzMrTnV6UFRqSDNDdGZzZE9OWVcwMUVmd3BEQUhZMVBCLysySVdOZktlS1h6RGNJQjhDaU1WSEIxZnYySDQ5aFpXRUpNTUlPeEl6Z0R1M1RXUDRkWFRURWh2SlhpckQwc1RrR01kRlRmUVoxMzE0QVgzY2pGYk11K0NsUWhhaGk3dVhUZ3Nqa2lSaHo3QkRzT2RucURWZ2ZGcWF5THdKZlhHL0M3Q1cvd3MzTHpGOUtvbEdlOHFhblZ5bGZ1M1loWG51K1FFZ1Z2TTJ0YUpqM0ZEcXJqdExIVk83WTFMNUV3SWQycXJaUVJMejZOUFk5M0c5R2JPNGlaQjR0SjNtWU1xL1BBTXU0SDlIRENLNXdRN0dQWGplMVlzYUQ5NkxpblJlWWlXZ2hVM0NzZmc3TzB0Zm9hd3lGUkN0QnVncTVDMkhXUkdSV0hZYnU5VEV5ODZGcjdhUkw0bnN4aVdKcG5DMHBBMW5PYzBxV01xKyt5Y1d6M0FORW1zcDdic01XYnNYSEgrM0M2ZmUyOVNsdmUvY1FMbGppNENwOWkvNm1rRm1VaTg5dXJqYU0zTG9kazN4MWlQcm1mWWllUFJQWnZoc1l1YjJFS1dnbXQ0ZVVPbmxpNFdtdGcrWm1TZ2tWQVllekRhTnpsZ0pwU1R4RFhxU1BUa0w5WDNjckFrSDN5Yzl3NDRjcjRHbXVVZUVXTVlZMzNhclFFbjljZ1BTRGJ4akVSQWVGaDltc0xDUFdrWW5hakJud05UU1JMNHdHdFdOeVZ5T3NVWFl6UVNKT01xR1d4djdDVkppNE5tc2Vyc3lhQmEzNUpwVkwxUXVMRjcxb2dIM2ExekNwcnJhZjhwSzNqeUIrYWo1aTZORHJiRTUrMk1hbTAxaXZpb0pSbkxMTUZDaW9QV1BUTEFzRjkwa3BzbEg4SmtkUnd1MVVRaWI4cFFJVHp2NE40Wm5waXU1RTlVVkU1T1JqdzVhOVFCeFRGaEdPd2swQncrUUlHOUw3STJDQTZBeFM3RWNZN0dTVUVwSWk2MGJxOWgzSTF1c3hJdmM3NnYzMW15NU1tN2NCMzNxa0NCNWhUNDRqRTQ4aWo1aE5EUGtLQkF3WUJNb3V0WGdxNkZYS3htZlZ2cUI5Y1NIRzNyTU01eTVlQXpLWW5yQlFQZ2J3WmZjR1NjRkF5QUZTajhVZ2IzMTFEeTVhWXVBK2VBalc5QlRqOUlpQmJwNmtMczRIdnlacFlFRVlPZ1hzVEFNWkJNSWszaXVaMWtoY3Vlc0JOUDVpSFZPVHlIbkR3U1JHZDdOWk9Wd29MbHlBalQ5YlFDTjR4Q2dxTXR4b1RuNUk3UmhGR0VEQUFFNHZ0UVpBVExMS1kySG42dmJBdzBrblBVQjJkYTBYV2tNTDd2MTZGdHBxMzhQTDYvUFppR2lRTVBHWFBWd2lFNENTd3ljWVFSRWdWNGdpTkRvY1AzazhqVzRtdlY1VHA4RWRsNERLRDNiaTAwTmJFVzgySzFjbnZUZkhkYkEwK1M2UzVBbEcvd2lFcUFHYm1teUdhamtOR2pwVjEwdjc3VzVNYWorSGg3NlJwZWphZVRlWXRmZ0Z2UEg3STd5a1JDbWVZSWprcjQ1QWlCcVFycVdoaCtKNjJFd2JrTEJ5SmFicUhVaGFFeGhNVC85eUR4TEdQWTZULzZwaEQrQUVGVzJzcWM1YlJyc1ZEQjBCQ1gxUURkZzRxZnpJZHJHM1Q3OEhFVk9tWUhKekUwYnQ1YWcyOGRiQlNsZ216TWZlc2crQmRFNUV1VGRJRkNVTm5DY2x4Y3RNU201VHRoSEYvbEZXR2xYcW1XUDFoVTNrOGpVSC9uemlqTHhDV0VJaXhwOWgxN3Z3ZDloU09DdUkwNTlmUWNvRHEvRE11bDI4TXpEY2ZxOXY4elRjYU1hU1JkK0ZmdlV3aXBibktYcUJ0MUVHRWd0M1FHcVVBWkdSOUZqR3I0QUZwRE1WY3hjK2h5ay9LRWFkdzJuc0UyMjhGOHhjL0NKbVBsUUlaMXVIZVcrZ0NDOTVHMXVSTTNrODZpL3R4NzRkYTB3TzhyeFp6Z2thRDIvZE5kb1lyaUtnTTdIUWVMc2krbTVFdVN0K3c0citCNUJxQ3BWS0ZvK2EyL0RUWitjamxTMzJwYTN2QW9sQlZ6U3BtWFkzNTNzY2p2NXVBM0xuVERmMmlhNFRwMUQveUZKNHVocFl5TWxVYWt4UUwwZTNMVDRGazlwNHN5Wk1BOVJYbEIwNWdlVWJPSWFsb3lXYVRVWndpOTFOR2xXTWpGZHpUL0pNYk51OEhKdWVEdHlJdmMxTzNKaTdETGMrcmVDQlRTTzFUWEdJMXg3Y1JPeU03eUh6NDhPdzBBblpWd1lJWS9DOXNMaGtIMTU1cVl5RGhVY3dpcU5admVPU091bjFzT3M1OGNSVGorSEF6aUtEd1VUalQ5YkJWVjVLeFhHa3RsT3A4UG1vdWhVUjlqUmtWQjdnUmVWK2cxanFUZVRLaFNRVXZKcFBuLzNrRmw3SjV4clg4S2xQcXU5WjMxK25PMXJhVENvRHpsZjM4Q3B1NTFVOFVhOUJKdGRZL1JMWEJmNTlIckc2czdUTXBKUnJmLzlyL0pjTWtJandwdy9WNTJ2MTFEbXJkUXYvTDNqLytHZm1yb0hPaXVQNmYyS3pxQ1JhS2F6QmVLNXgra1drY1M5S2J5aFliMUlLUks2eGdqSG8vd1ZEd2NPclZiM2srZXh4aGp1RmdaYWhJMklrejAySXVUOFhZOTdmQjl0SUtUNlZ2RUZoZEo0aElTSUNOamF0ZlI0MUdhUFFmZllzMVk3dVU2NHh6OVlJTys2cStnVGovL21ob1Z4OEM3Q0doa1RnVG5ENzhuLzFxOU1mWnM0akdlcFVoanFldVU3U25idjJtaFIzaGpzeVFHTmgralBvL3VpWVhwZVhyenVLdGdUOU54bjYvNytoOEgvVlFDaUlrS0Z5SFJyQS93QzRlK08rWjFjbjRRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIzYjFhZGI5OTBkZmU0NmZkOTBiODdmNzYxNGE0ZGUyYSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMy0wNSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiR29UcnVzdCBJZGVtIEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwMzA1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0xMi0wNCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiR29UcnVzdCBJZGVtIEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMTIyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTItMDQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTAzLTA1In0seyJhYWlkIjoiNGU0ZSM0MDExIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiNGU0ZSM0MDExIiwiZGVzY3JpcHRpb24iOiJTYW1zdW5nIFBhc3MiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MjU2LCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjAsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjMwfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInRlZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVnQUFBQklDQVlBQUFCVjdiTkhBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQXlScFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1TXkxak1ERXhJRFkyTGpFME5UWTJNU3dnTWpBeE1pOHdNaTh3TmkweE5EbzFOam95TnlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUlNaV1k5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVkpsWmlNaUlIaHRjRHBEY21WaGRHOXlWRzl2YkQwaVFXUnZZbVVnVUdodmRHOXphRzl3SUVOVE5pQW9UV0ZqYVc1MGIzTm9LU0lnZUcxd1RVMDZTVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRHBCUmtJek1USTJSa0U0TVVJeE1VVTFPVUl4TVVaRk5qaENSakkzTWpJeU5DSWdlRzF3VFUwNlJHOWpkVzFsYm5SSlJEMGllRzF3TG1ScFpEcEJSa0l6TVRJM01FRTRNVUl4TVVVMU9VSXhNVVpGTmpoQ1JqSTNNakl5TkNJK0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnpkRkpsWmpwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09rRkdRak14TWpaRVFUZ3hRakV4UlRVNVFqRXhSa1UyT0VKR01qY3lNakkwSWlCemRGSmxaanBrYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2tGR1FqTXhNalpGUVRneFFqRXhSVFU1UWpFeFJrVTJPRUpHTWpjeU1qSTBJaTgrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrcEQvekJnQUFEQkJKUkVGVWVOcnNYQVZ3Rk1zVzdVQ0NFNElGQ3c0QkNnbnVCQ244UTNBS2QzZDNMeWdjQ3Fkd1QrSHVyb1VHSjBCd0tkemQwcjlQRjNlcXAzZjJrZmQ0MmQzdzlsUjFZTHQ3Wm1mdTNMNXliczk2TURPU2k5WkJ0UCtKbG9uOXQzQkR0SzJpelJUdHNkV0UycUs5RW8zL3g5dXJuN0l3SWNndEdKc0dtVEFQMFJLTDlsUzBhTXdORmVHaStVWVhmd2FMRnVpV2h3MmdQRC93NTVwby9tNTVXT0k2QlBSUnROaHVXVmppa3lmVXlGbmZualp0V2xheVpFbVdMVnMyNXUvdnorTEVpY000NSt6YnQyL3N4bzBiTERRMGxCMDllbFQrNnlSSTJieHh0SWVvVzdjdTM3bHpKLy94NHdlUENJNGRPOFpidG16cERFLzJ4cUVDcWx5NU1yOTQ4U0wvcDNqOCtERnYwYUtGUXdYazhWTkEzcEdwcDU2ZW5tek5taldzV3JWcTh2UHIxNi9aK2ZQbjJmSGp4OW5WcTFkbGUvRGdBWHYzN2gxNzgrWU44L2IyWnZIaXhXTXBVNlprT1hMa1lGbXpabVhGaWhWanhZc1hsOGRqZmxCUUVBc0xDNHZzSmZZMjBqV29kT25TL05XclYxSURaczZjeWNWTldzNkxIVHMyOS9QejQwSVlQRjI2ZEZ3SXlISmUrZkxsK2I1OSsvanQyN2Q1bzBhTnVJZUhSOVJjWXRHaVJlTVZLbFRndTNidDRyMTY5VEtOcFU2ZG1yZHAwNGF2V3JXS256dDNqZ3ZOc1Z4U3dsaHpvUzE4NjlhdHZFK2ZQang3OXV6R09SSWxTc1I3OU9qQnMyVEpFcGxDaWp3QnhZMGJseGNwVXNUNG5DQkJBbm1UWjg2YzRiOERhTTZZTVdONGloUXAvZ3dqalNjOWVmSmsvdm56NTEvZS9QdjM3N213UWZ6bHk1Y1I4bkFiTm16Z0JRc1dqTHBHdWwrL2ZteklrQ0ZNMkJlYk1jUTJodzRkWWhjdVhHQWhJU0ZNZUNnbUJNVEN3OE5saXg4L1BrdWNPREVMQ0FpUWNWSmdZQ0FUR21uNVBjSEJ3V3pnd0lGTWFGZlVNTkxpaHJqd1VEWlBISm94YWRJa1hxaFFvWDkwM2t5Wk1rbDdaaFVxZlB6NGtUZHMyTkQxTlVnRWdXelpzbVhNeTh2TDZJTmJIemR1SEpzOWV6WVRIczNvVDVJa0NSTkxSRWJVR1RKa1lMNit2ckpmR0hpcFRYZnUzSkh1WHhoeWR2bnlaZFAzTkczYWxIWHYzbDFxbUFxRUJmcGNsOUdnSmsyYTJEelpwVXVYbWd5cVdEYThhOWV1ZlAvKy9melRwMDhSTnM0aTllQ3paczJTYmw3OXp0NjllNXZzRzV5QVN4cHB1RzRkNGlrYjQ5R2pSK2ZDSG5HaFRmeDNnZENnZGV2V3hya1JOeDA4ZU5BWVIzamhjZ0phdm55NUtTWElseStmTVZhNGNHRXUxTjd5WnA4OGVjSlBuRGpCeGJMa0V5ZE81Q05IanVSang0N2xDeFlzNEx0MzcrWTNiOTYwS3lpY1UwVG54dmZnT09ENjlldXVKYUJreVpJWkZ3MDNMV3lLTVFZdDB2SDI3VnMrWmNvVVhyWnNXYnNSczlweTVzekp1M1hyeG9YWHN4VFV3b1VMamJsWXZrRHQyclZkUjBEQ3hSb1htenQzYnFNZmthNE9wQnYyZ3J4VXFWTEp1S1pNbVRJOFQ1NDhQR25TcERaek1JNzRSNGNJRitUeG1JT2xMSEk5SGlOR0ROY1FrUEEyOGlKVlNnSlBYTVdYTDE5NGpSbzFUTWNoOTJyZnZyMU1PZTdmdnkvbnFJRHhGVjZNcjEyN2xuZnMySkVMcjJjY0MrMURHcUxpK2ZQblBIUG16SEljR29RMHhPa0N5cFVybDd3NDJBdDczZ3cyQ1Vtb0dzL0F4dndkTHdaZ1BvNkRVYVp6WVhucHNSWWNCc1pjUW9PZzdyQTd5TWJ4R2N0RE44THFEZlh2MzE4bW9mWUFMYUJtRHppK2I5Kytwbk9xZVBqd0lZOFZLNWJ6YlZETW1ER2w1MEhrak04aTJPTmZ2MzQxTFJIMFVYYS9jZU5HbTV2RjBwb3hZd2F2VktrU2p4TW5qdW44eU5LUjhJNGZQMTRtcVRxMmI5OXVhRW1YTGwxTVk0aXpuQzRnVllYeHhQU2JLRnEwcURHK1o4OGVHODNxMUttVEZCek5TWk1tRFcvUW9JRzBOMkFPOVpRRU5nN2FvZUxhdFdzOFljS0VjaHhadmdxUkM3cE9ISFQ0OEdIVHhlRkc3ZG1KTFZ1MnlJaWF4bXZXckdtWnUxR0d2M0xsU3NQZ0l1QmN2SGl4YVE1aUpWcmk0SjlVL0thaC9uY0V0R2JOR3RORndjM2Fzdy93V09xeE1Mb1JCWmFhbW1Mb3hENHhreW9CaDNqTGFRTHk4ZkdSZHNCZTBGYW5UaDNUMk5HalIwM0xVMDBQQ0VlT0hPSHo1czJUUW9kOTBnRk5wZUN5WjgrZXBqR1JFTXYrcWxXcm11eVUwd1Frc25QVEJlN1lzY01ZSzFHaWhJMHhWbzJ3eml4Q01HcVFTYTFreVpMOHlwVXJwcmxoWVdHR2w5S3ZBV0VIK2lucVBudjJyUE1FdEhmdlh1UEM0S0dvSDhTOHlnakNteUgyb1hGNEdCWHo1ODgzeFZXSXRsZXZYczJIRFJ2R3ZieThaUCswYWROTXg4Qm0wVEhJdlFpaG9hRkdyQVVnT1ZZZGdVTUZoUGdIUUlKSmZZaUR3c1BEVFRjVEdCaG9qSzlidDg0MEJnMmdNZDBMRVZDOXNMSm4wNmRQbC8wNWN1UXc5ZGVxVlV2Mm56eDVVbjVXSFlMREJJUVlhTUtFQ2J4Y3VYSkdYN05teld4dXJtTEZpc2I0bkRselRHTno1ODQxeHBETi94V2FOMjh1NTBFb0tvb1ZLMlpqN0pHZW9BOWhBa0RwaDBNRnBLc3RxRlFkMWF0WHQ2c2Q2cEtFY1ZWeCt2UnB1Ynp1M3IxcjZrY0NpL2xJUkFuMzd0MlRmZDdlM3FhNXlOWFFIeElTSXUyWTA5eDhnUUlGNUEzcHNVdXBVcVdNT1lNR0RiSjB5V2oxNjljM2pjR3pxUlVSMVpNaC9hQWtWd1hPb1dzaGpENzZHamR1Yk5KaWh3cEl0d2xFZVdiTW1OR1lNM1RvVUJ0YUFzc1RZM256NWpXTmdZelh2d1BweHRPblQ0MDUwRlQwVDUwNjFaUjdxWWFaQUxvRXg2ZFBuOTQ1QW9LN1ZZR0xWc2ZWbXdCdTNickY0OGVQTDhjQ0FnSk05Q3ZLMHhqRGNzRE9ENFFNcUtmQjZNTUpxQWt1YUE5NE45VlRZaDdPcXpLWENDYWRtbXFBNGdEQXkyRG5ocm8wOUFBU09SUHhPVENzMzc5L040M0RFMkhNQ3MrZVBUTUpDSjRRY3hFZUVMWnQyeWI3a0g4UlFPVTZWVUR3WW9oNjFkbzRvdGhIang3WjJCeEtiREd1aHdHVXQ4SFFScFRVUjlBSkJwRUFnZU1jV0ZZRWFKZ1ZLK21VWkJXRzB5cXZRcUpKYzhBZTZxQ1loUnFFQk1LdGJkdTJNZ3pRbzJqQzRNR0Q1WHg0TWIyYVFRd25BQ1B0VkFIQklFT1RyTmhCZFZlSEhnWWd1aVpYL0t0V3BVb1ZtVExvbXhnd2hnUlc1YnZSdDJqUklxTnY5T2pSemhNUTFOZHFrd0dTVWxRaVNMUDBhZ1M4RHBGc3hCOUQrK0FCWWNnUjV5Qk8wbmxvblRiUmN6NkVHK2hEVUdsRnV6aGNRUEFrNEpzSkNPeXc3NGZHc1V4UU05ZVRVbXlOd1RpV0Y0ejNYd0hHbVZJS05DeFpOVEVHeVVZQXpZRStsSjBJYWduS0tVc002b3hnRHZhRitoRGk2d1FhQUlOT2MwQ3pXdUhGaXhjbTJsYjFncWkvNFZoL2YzL1RQaVRhd1FiUUhHSXRuYzRvcW9rZ2FsYWJOMisydVRsNEprbzRyUkpXM0h5SERoM2swd2FONGV2cnk0T0NnbVJkWHdXOEk4VlJhbFB0RXlYR3dQcjE2MTJEY29VTndkS3hBdWhSZXFwNmlScEFqdmFyUFk0bzVSQ1FvZXR6c053SXRBVUdkZ3ljdDBzSTZOU3BVemFDT1hEZ2dMdzVsWDFFTUtlaVhidDJ4amlNS2JocUJIZlFNTFhtamlXbDd1Q0E4VmEvSHpRdWdXeGc1ODZkVFJ5VVV3VUVRYWlFdk82KzY5V3JaMU9OUUEyZE9HU1ZlRk1CMGt6ZGZLN1cvOVdLQ2hsdWdQWlJSNlRtN3pBQmdmb1lNR0NBa1M1UUE5MmhsM3VBVnExYUdUZGhiOWNIQVV1U3pnZnF3aXJBUkdtYW9HNkxjY2xObktBL2tGeGFSY0F3cHJUcEVoR3pYbHRIV0lBeURaYUhDaFFWZFVJT2NaTVZoUXR0ZFZrQllZTzNGVUJYWUtjSHpRUERwKzc3UVc1R1pKZ1ZsVUxjVHNxVUtZMDhEcHVvYUs3Nk1INkRISXQ4QWNHRHFJQW5nV0NvcUVkejlMUUUwVER0b3FjdExHaVU5Q0l1OHZUMGxIMFU4eURpcG1CVk5lQy93ZjA0Wm9taCtvQ2NLSC8rL0taK1ZEcDBDZ1FicWJEN1RPV09JQURFUWVoVDV5ZFBubHoyZ2ZxZ2FxcE8yQ05KL1kwS2h1TTNrdU5wWXA4UVhMNVZBWkRTQU4zbTBHNFFOWWZEVG4zMDBSNGkyQzk4Um9CcFZTQndhUUVodzljNUlaV3ZWcmV1NkZ2MHFHd05EL2Zod3dkRDAzU0tsa2d6RWlJWWhTanpLZ0lJTkpXR29Hb29PQnhhS2xhbFk2UVdOQWFhZ29BeXRGNDhSRnhFS1FVME5FcStxekZpeEFoNTAycnRqR2lTRlN0VzJDWFdFRGxiN2RCUWpUdlpMU1NrVWZKdEgzdTdZZUhWMU53S1dMSmtpVEVIeVNnS2Z3UktPSWNQSDI3YUlZSXNmdE9tVGFZOEw4b0tDRzRlOUtrVjFNb0RkcjlldW5USnBnNm04anVrVVFnMC82VjB3dmtDd3FZbkpKOXFnUkV1SEtVZk5RSlg4elY0Sy9KeXFrYWhmUDNIdnRSTFhrc3RTWVAvZ1ZmVCtXcmF4a0xDZ2ZBUVhmL1JiejFiZWJ0Um8wYlpGQmVKcnc0T0RwYVZXQWhWMytEcHlMZWUzNGtXejFsdjd1UE5abUZ3bVorZkgvUHg4V0VpKzVkdlArUC9JaVNRYnpnN0VlL2RQMDN4aTUrbXdFL2kzSGZMd1M3dVEwQnIzWEt3aTdYdUgxaXlEL2tEU3hES0M5RnF1T1ZoZ3hvL1pXUEEvU052RmoveTVxRkp6ZjB6Z2RyUEJQNWZnQUVBYk1qMzB3M3ZzeGNBQUFBQVNVVk9SSzVDWUlJPSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiZmlkby51YWYuYW5kcm9pZC5rZXlfYXR0ZXN0YXRpb24iLCJkYXRhIjoie1wiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzXCI6W1wiTUlJQ2l6Q0NBaktnQXdJQkFnSUpBS0lGbnRFT1ExdFhNQW9HQ0NxR1NNNDlCQU1DTUlHWU1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnd3TlRXOTFiblJoYVc0Z1ZtbGxkekVWTUJNR0ExVUVDZ3dNUjI5dloyeGxMQ0JKYm1NdU1SQXdEZ1lEVlFRTERBZEJibVJ5YjJsa01UTXdNUVlEVlFRRERDcEJibVJ5YjJsa0lFdGxlWE4wYjNKbElGTnZablIzWVhKbElFRjBkR1Z6ZEdGMGFXOXVJRkp2YjNRd0hoY05NVFl3TVRFeE1EQTBNelV3V2hjTk16WXdNVEEyTURBME16VXdXakNCbURFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01Da05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNNRFUxdmRXNTBZV2x1SUZacFpYY3hGVEFUQmdOVkJBb01ERWR2YjJkc1pTd2dTVzVqTGpFUU1BNEdBMVVFQ3d3SFFXNWtjbTlwWkRFek1ERUdBMVVFQXd3cVFXNWtjbTlwWkNCTFpYbHpkRzl5WlNCVGIyWjBkMkZ5WlNCQmRIUmxjM1JoZEdsdmJpQlNiMjkwTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFN2wxZXgrSEEyMjBEcG43bXRodnNUV3BkYW1ndUQvOS9TUTU5ZHg5RUltMjlzYS82RnN2SHJjVjMwbGFjcXJld0xWUUJYVDVES3lxTzEwN3NTSFZCcEtOak1HRXdIUVlEVlIwT0JCWUVGTWl0NlhkTVJjT2p6dzBXRU9SNVF6b2hXakRQTUI4R0ExVWRJd1FZTUJhQUZNaXQ2WGRNUmNPanp3MFdFT1I1UXpvaFdqRFBNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdLRU1Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lEVWhvKytMTkVZZW5OVmc4eDFZaVNCcTNLTmxRZllObnM2S0dZeG1TR0I3QWlCTkMvTlIyVEI4ZlZ2YU5UUWRxRWNiWTZXRlpUeXRUeVNuNTAydlFYM3h2dz09XCJdfSIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA1LTE5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0wNS0xOSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjNjMjJiNTk3ZjMwZTg2ODllZDI0NjBmOWRmZTk5Yjc1MTAzMjkyZjYiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiM2MyMmI1OTdmMzBlODY4OWVkMjQ2MGY5ZGZlOTliNzUxMDMyOTJmNiJdLCJkZXNjcmlwdGlvbiI6IlJlZHN5cyBVMkYgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURBakNDQXFpZ0F3SUJBZ0lKQU1FVnNwZUVzR2lLTUFvR0NDcUdTTTQ5QkFNQ01JSGJNUXN3Q1FZRFZRUUdFd0pGVXpFY01Cb0dBMVVFQ0F3VFEyOXRkVzVwWkdGa0lHUmxJRTFoWkhKcFpERVBNQTBHQTFVRUJ3d0dUV0ZrY21sa01TMHdLd1lEVlFRS0RDUlNaV1J6ZVhNZ1UyVnlkbWxqYVc5eklHUmxJRkJ5YjJObGMyRnRhV1Z1ZEc4Z1Uwd3hJekFoQmdOVkJBc01HbE52YkhWamFXOXVaWE1nUTJocGNDQjVJRlJoY21wbGRHRnpNUTh3RFFZRFZRUUREQVpTWldSemVYTXhPREEyQmdrcWhraUc5dzBCQ1FFV0tYVnpkV2RsYmk1VGIyeDFZMmx2Ym1WelEwaEpVSGxrWlVWdGFYTnBiMjVBY21Wa2MzbHpMbVZ6TUI0WERURTRNVEF4TVRBNE1EWTFNMW9YRFRJek1UQXhNREE0TURZMU0xb3dnZHN4Q3pBSkJnTlZCQVlUQWtWVE1Sd3dHZ1lEVlFRSURCTkRiMjExYm1sa1lXUWdaR1VnVFdGa2NtbGtNUTh3RFFZRFZRUUhEQVpOWVdSeWFXUXhMVEFyQmdOVkJBb01KRkpsWkhONWN5QlRaWEoyYVdOcGIzTWdaR1VnVUhKdlkyVnpZVzFwWlc1MGJ5QlRUREVqTUNFR0ExVUVDd3dhVTI5c2RXTnBiMjVsY3lCRGFHbHdJSGtnVkdGeWFtVjBZWE14RHpBTkJnTlZCQU1NQmxKbFpITjVjekU0TURZR0NTcUdTSWIzRFFFSkFSWXBkWE4xWjJWdUxsTnZiSFZqYVc5dVpYTkRTRWxRZVdSbFJXMXBjMmx2YmtCeVpXUnplWE11WlhNd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRZ0d1bVNkNWJkOXB3THMzMlhXU05iSEZDUWRHZ2tDQkx1U0hKbmVYUWNFS0NCV1JDMnlNME1hL2pleXZXUzhaVGhFaE5vVHVvRzBIS0RHd0MvcGZDRW8xTXdVVEFkQmdOVkhRNEVGZ1FVUENLMWwvTU9ob250SkdENTMrbWJkUkF5a3ZZd0h3WURWUjBqQkJnd0ZvQVVQQ0sxbC9NT2hvbnRKR0Q1MyttYmRSQXlrdll3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUJaZUQ5ajZvVUtNWjBrVzBtRENuSHFLcGxaYldlVFN4R3p2U1JmOUpzZjh3SWhBTWY4ZDEweWx6SVl1bGZpdTBPbnQ1c0lXNS9SRW1lMFZ3UHg5T2JoTEFUeiJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFNZ0FBQURJQ0FZQUFBQ3RXSzZlQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzUUFBQTdFQVpVckRoc0FBQ2J1U1VSQlZIaGU3WjBKZ0IxVm1iYmZ1dnZ0N25TNk8zc0NKQUlTQWhGUkJCVUVsTVZBWUNLUmdZQ0pFY0t3aW96b0RPcUFxR3dqbTdJb2htWDRkWVJCUUJIWlFRaUt3SThDaW9JUUlDeUpDZGw3WCs1YU5lOTc2dDdPN2FSVGhKQTB2LzdmazV4YmRhdE9uVHBWOWIzbmZOK3BxdHRlUUdBWXhxREVLbFBETUFiQkJHSVlFWmhBRENNQ0U0aGhSR0FDTVl3SVRDQ0dFWUVKeERBaU1JRVlSZ1FtRU1PSXdBUmlHQkdZUUF3akFoT0lZVVJnQWpHTUNFd2doaEdCQ2NRd0lqQ0JHRVlFSmhERGlNQUVZaGdSbUVBTUl3SVRpR0ZFWUFJeGpBaE1JSVlSZ1FuRU1DSXdnUmhHQkNZUXc0akFCR0lZRVpoQURDTUNFNGhoUkdBQ01Zd0lUQ0NHRVlFSnhEQWlNSUVZUmdRbUVNT0l3QVJpR0JHWVFBd2pBaE9JWVVSZ0FqR01DRXdnaGhHQkNjUXdJakNCR0VZRUpoRERpTUFFWWhnUm1FQU1Jd0lUaUdGRVlBSXhqQWhNSUlZUmdRbkVNQ0l3Z1JoR0JDWVF3NGpBQkdJWUVaaEFEQ01DRTRoaFJHQUNNWXdJVENDR0VZRUp4REFpTUlFWVJnUW1FTU9Jd0FSaUdCR1lRQXdqQWhPSVlVUmdBakdNQ0V3Z2hoR0JDY1F3SWpDQkdFWUVKaEREaU1BRVloZ1JtRUFNSXdJVGlHRkVZQUl4akFoTUlJWVJnUW5FTUNJd2dSaEdCRjVBS3ZOYkZCVmFab3E3YjREUFZDN2xFTFN2UXRDNURGNTNCM3lmUytOeHhESjFpTmVQUWJsNURCTFo0ZjJxMWZhYVYxSjVIcE5oRENWYlRDQlZBNjVPYzR1ZmdmL1hSNUI0WlFHOHhjOGhXTE1Lc1R5Tm5ZcUpKWmlQVmw4MWVOWEFseHFLVEZ4WGJHNkF0ODJ1Q0hiY0Q1aHlFQkpUUDYzRkRna3R4cytBbnlZWVkydXp4UVNTNjEwSi8vRmJVSHJxVmlSZWVBckpIQTJmVnAzS2NtV21rdUl4Q29QS0NId2FkNldmOEtRTUVsQTVUbUVCZ25JNVhFekJsQXZxZVppMjNSSEJmaWNnZnVBcGlHZWErZ1ZqR0Z1VExTS1FzaCtndU9wVnBGc21VQkgxYnBrS0RYcGJVWGpqV1hqUDNRYjg0VVlrK256RTY3Z2lsb1lYcHdJa2hrbzM0TlhVd3MyNmFuRzluMVFsS1JhcWhUMVF1UnZvbTd3YkVwODVENmtQZjBZNUVXUDM0N05ycXJwemhyR2wyR294U0pXSzErVGlpZkpMQzRDYjV5RFp2aHhCUTR3RzdWRWd0UkZHdjlNVmZySnFFZzVsQXMvbk9sVlZQbGFlZ3FCUWl1a1VpbC80TDlUdE15ZnNqOWd6cWJ4SzMyUVk3NXF0THBEMWtYMzNMTGdFbWR1K0JtOWtQY1ZEWDh4ajI5OWZqYXBJcWxBZWJwVVg5akxzcmJUTUthNVFRcm1UUFVwRE0ySmZmaENaSGZaMDZ5dzZNYllVbXl3UTE0ckxNTjlsK3h3RzJVRDMwdWVSdkd3M3BKb1M4RHoxTWRWcU1JZFhNWEJYTmMxenp4SUdseXMyY1NHNkJLSmx6QjRVaWlpdnBGQSsvbGxrenZpRjJ5TEIzZ1N1ZHpLTXplZHRCQkxLb3B6clJySFFpMHpqYUdkOFd3THR0TEJvQWVMekQwU3NKU3NKY0NGTDl5UWgwaThTZlZSRXdxcDZNbnhONlhLNXFsTW9YdGxuSEVTSHJTT1BmSkdDdTJ3SmhUZU9lVW9JWWdsenVZek41bTFzeDBPK1p4WGFmblFxc2x0UUhDRStranNlZ1B4ZTg5Zzc5TUZMME9pWmdpU3JsS1RMbGVEZWxKSkt6SjcwNGFVb0NNMm51SXpKWXdveXpNdkV1Qit4RVVta21xbVlVOGVqNy9tSFVhWTRuS0FNWXpNWnZBZmhraEp0c05UWGp2TE1ac1IvMllGTXRyR3lja3VoM1hySWxRdUlmeWVONVBBNjFTWmNxdDdEOVNaTS9XaWRlaERYZ1JBWlBtZDhDc3IxSkJYM3EwZ2hsY29vTFNraGYvcHRxUC9vVVZ3dmQwdi9yUzh4M2hrRExZYUc1dlFpK3l3WDRjMWw4THZIWkNTM3VEaEVhUHpwZUFxNUhmYWluUmZneDdtTVBVakFhY0FlUTcyR3BtRmkzVktzRjZkUVQ1SmlQdlUwbFI3SHJVdFRRSFZNOVFra2RrZ2hQZjlvOVAzeFFXcEhJbks3TTR4M3hBQ0JCR3F4K2IvQStmeXBvNURRemIxZFA3MVYyMTNGMnVrSis3Q3pLTGs3N0JJRlVoS0hSTUxxY0ZrMTZTNjgzQ29sVUNpZThqbXh5UDFTUVVyTVNLRWd5eXc3cGhDLy9oQ1VWeThPUldJWTc1QUJWcU0ybldhSDNPV0hvYjdZQVk4R0Z3d2Y2WXg0YTZGOWxySXQ3cUV0RjMrb1JuRitTQXdKOVJMVkpNRXdWV0lUTDBraEpKT2NNamhQU1JUTW8xNGx3L1g2bmszQ3o4YVFuQmhIOFpKSmJqK1VFNDl2YXg2TjhZOUdSU0NoN3kveXovMGFEVS9lQjI4WVBYYmFtYmQ4MFZidFFXUzRzZDdGRkFNTlBTWVIwTWdwRHVjMmNjY0JSUUlubElwQXVONTNTWUppdnFyYmxXWkpFb2VXWjlTcnNHeCs5N0lwMURVRGZUZlAwdTU0bkNyY01EWU5aL3ZxTllLZzZOclcwcFV6RUl5aG9URklsbC92TDNwb3E3ZTU1YmNlQ2x0K041SVZRNHdDQU9NUXpYdVZhWXhUbHlnU3JmZGNraURrY25GZWVST0pTbTlDRVdRb09FMFYremRsa1g3NU51UmJYOXlxWWpmKzhRanRoWUc1N3lYUi9kQzFxQy9rM0kxdHJaRTdrMTYrRXJrVnI3aHNXeExkN0ZPdjFkZTZFSm1lSlJRSEF4NjVUZ3JRSlFyVndRM3pNaGR0dnQvVmluTTdDU25PdUlQekVsV1l1STFpRmhlYmhLSnhJa25SRGFOUUVoTlkxdDBuT0RmTE1EWVZOOHdyUTFVdmtUOXhPT3FUblRRMnVUYzBZYmJLS0FYb2E1cUV1bSsvRm03Z1B0ODlFb2hLeTk4NkZhbjhhM1RuZEVkZEF1QWV1S282VlU1NlhxeVBGQk9LU3E2WS9vWHJ0WUN6ZWc1TFM0TXlFK2ZkczF0Y3BhblBCb0RMaXl0NzRaMjhBcW42TVpVTkRTTWExNFBRaEZCOC9VOUl0VkVjTlFaS3A4WDU4ZG0yMTlGejY2bGIyTlh5VVBqdEY1SHUvU3ZpS2ZVZXJBbzFFT2hHaDJyRjVLbFhVQytpb0QwbTl5djhyZ0VwbjNtcmNZZ2VxM2ZEdlpwUzNFalNOMlN2RVNodzEvSjBnbTVaR3VsUmJBaWV1d1FsWnFOaytHa1kwZEI2UXZ6Zi9CZGlUWnFydURqOEp4UFNORmFmUXZiSitjai80b3RPSktGUXFzMzNPME5sYXZ1ZTM1K081S3ZYd0tzZnhwM1FYTmtyK0JTQ1lna1hWM0RpVXVXNzcrSU56bE1nY3YxY2JLSk9SWUt1SkNlbTZ2WWEzVkp5UTcvY3E0Wis2K29SVy83ZlhLQk9aZlBxYi96L1JmK2Q5TndaazVBc0xXWWdMQ09rb2VxdXRscGorZnY4VjVhQjl1WlJHTGNqWXFjOGhYVGRDRmVBREY1ditOVm9iUUFhVnZWcVJvN3l1VFh3N3QwUHFlNlhFR1NIdTVZOEZwZExwNzF3UDR3dFlwNUVHcFlubWJxNzU0TVgvN1pvMnhBV3dFTXQ5YlFpT0tJRGlWUWp5emFNYUp6WnlZYUtxeGU3R0FDS1Blak8rRXdLaUgzUGQvTnhXbHFzTVkxczF5TEV6aHVKdnRzL2k5N1dNSGpYQStZYm8weHhxUHkranBlUmUrUm94RzhlaFVUeFZRUjF3N2t2dGZUYUozT29DTHBJMG9VbmQ0cjdWWklWYjY0NGhKNVlDUlBMVXRseXd6cWZEVmNheHR2Z2xkbURsTHJiRWY5Q016Q2U3aFNOU01GNVREMElYUlJudk01cW1WdmYxZWFuMk1vWEN3am96QmNiR3hEc09CM3hDWHNESTZZQUdiWE1iUGNMakdmYUZ3SnJua0N3OUg0azg1M3dza2thYUphOUJITTRJYkNua0x4Y0R5SVpoY3Vkb3JRL1RiY2tMTlBQdGFMNHdSdVIzUDc0Q0ZrYi95OVE4dG04eHVJb0ZyclpiaXR5ckpvR0cvR3VwVWlNMnMyWnlkYkVLMUVnaFJWTGtENTlJbUxqYURJMFZKK3VWVXdHNndUQmxwZFQxNHJMcCtkM3QxNDlpNlpCanV0Szd0VU05NHloOG5HcVFTZGZUOWpHSlFvRzRhNHNyZURCS1U2UTY2VHZLUzBYY3RNcTIyOUZ2RnduZW5hOUZQVTduVmxaWWxTWlBtTW1yN3NheDNWbWw4dm5jZEFuUDRHenp2cGFaY25XUjQybWJFT3hhdTdwRzVEKytZbGh2RWxpUlM3cm9tZHkrcDFvbUJxK2NyMDFjVEZJejdKRnlIN2wvYUZBZEUvRWpRVEo0aWtBeGlDaElNcVZxV0lUeGlnVWtJeFp3WEk0QXNYODdCRmN3SzMxTEVLeFI1Q1FtNlR2NFdITGpkTHBWeDVkREovbHVxZDNoNGlnMElYY3p0OUYzZVN2VnBZTTVPbG5uc1hQYnJrRjlRME5sU1hScU83TlRjMW9ibW5HcEVrVE1YWFhYVEZpUkJpZi9iMXh4RDhmZ3dTdmNlMzF5Rk1nKys2N0gvNzl6QzlWbG14OS9ESWJVWG90dlk5ZmdPejkzMFM4S1FPdldFWTVWMFMrYmp2RXpub05TYjNLd0x4YnVUME5CWkp2WDRYa2lXTVFqRS9TcE5rYjZDUlJHTHIzRUdQUTdDY1Ryc2R3bzFzYVJXTGxRNEhJOENrQWZsZTg0dkc3cHZMVG5DQTRsWEMwWExjajNBQkFyYkIwaUp5WGRJWUN0VXBCdmczRnFmT1IyUEdrUVUvdVF3OHZ3SVhmdlJndHpTMmJYQytmM1dmZyt5aVZTeWpRb0pvYWgrSElJMmZpYzhjY1U4bng5OEhNbzQ1MUFsSERWU1dYeTFFZysrTGZ2andVQWduUGQ1SFhxZlRBbVVnOWVRVml3N0x1T2dScmMralpZemF5Ujkza1J2TTFDdW1pVytlVGJ6MWM2Y21tMGNoelRyOE80bEE5MXpVaS9iZ2duc3ZkVTc5dUFUT3ExOUFKMVRLdHI4eTYxWndQWFNibTB4Q3M2MkVvSW5mVEwxeStxVWE0SmRDZTJCNEE5ZHNPZG5pT0dPdVdTcVdZa2tqWEpMY3N5V2x0Y3ZsU3lHWlNxS3ZMb0hIWU1Jd1lPWkxpVCtLbS83a1YwLy9wQ0t4ZXM3WlM4dEFkNTk4cnNnV05lUmJ2T0FhcFAxeUJlRDE3aVhJT0pZb2pQNGU5T3NVUlUrRExVeG12MnR0V3h1MUJINldXRnFveWpBT2NDTUs1Q3F3VWwrbmRwSEFGUDFRL1ZaSXhoYytrY052WDR4OWE0Vnd1OWhvVUR2c1NsT1Z5Y1gyWitVQ1hLK1pHeWxpSzIvdFF3am9xMW12K2tHcTVDU2lYYXM2allnOVI3T3RGYnhkam1PNXVkSFYwb0dQdFduUzJ0ZEVOMFcrM2hDWHFNODVqSDBheFpPdnJjZlN4czkxeTQrMHAwbHA2NzV5RDVKcy9oejk2UEFyWlVlak5qb2QvOW1Ka3B4N2o3RFR1NlltTE1QOVEwRytpOFNrSHVSZEJwR0luVG9VT0F5cFM4MFVpNFZmZHUzQ1oxQ3E3alpUQzFZS3pkSzA4ZGh3ME1LMnE5alJjNHdYdlJhS1lVdzFJWk1acUhNVFZjVk5RamRlMHR1S0gxL3dBOTl6OUs5eDcxeTl4LzcxMzRmNzc3OGFWVjF5T0QrLytBYlMzdFlhWmEwakU0OGpXMWVISFA5SE5TWlZpUkpGZzcxQjN4RTFJZnFXRTVDbkxrRGpqTFdUL2RTblN3N1lMZS83S1FNNVEwaStRWU44dkFGMmM2anF5TXZLZUJsN1M5UXhLTVlsVXBGbmxkTnN4YWVqV3FVRkxPWFZCT1pkUkhHcUpWYjRlSjNrdkV2dytsTWJQY05WVXYvQk8wQVVxRmRSVHJDUEdMbjd5VGp2aDNIUE94cWNQUHRqNTYrdVRUcWZ4ekxOL3JIejd4MGRuVlZZeG1DbHJuYlB6alJCajcxQjF2b1dNVTJhbDVCclpkZVlhZmZVcUs4Tko3V2VJNXF0MTFIenRPa2ROSlYyUXJvenVFWkxaSGpMTlhLOFhrZlRMaHhxQzllSnNkY3QwaS9TNFIzVVVpMEY4bk1HOHZ1dUlKQW9Ld1FYMUN1S2xENzBteXdOeVFieUdlQlc4OC92UXUxWHJLUFcwSVRqZ0dTUmI5dENCczVJNjlRTjVlTUZ2Y2ZGbGx6Rkk1NG1vWWZYcTFmZy8xODNIeEVrVEswc0dzbkxWYXJwVGN6QjI3TUFISVV1bEVvYlZzeGU1OFliS2tvM3oxbHZMS2FabnNPalZSVmkxYWhYeUJiYWtQTmNqUnJSZzRuYmJZYmNQZmhDNzdES2xrbnZUV2J1MkZiOTcvSGQ0YmRGckxIY2xDc1V5WTZZNmJMUE5lT3kxNTE3WVk0OFB1M3p2TkVpWHpSUTZGeUwrNWszd1ZqMkljdnZmRUMrc0JFM0RXVjJacDdjVWEwS3lmanpLVGJ1anZQMnh5RTQ4SEVXNnEvNnZEa1ZjcjNMVElIUVZnckp1RE5NRjdtcUhkK1JkU0NUVHZFYXlQKzFwSUs0Wit0bngzRThIMTNON2xhR0JrbUkzY3U4N0ZOa0R6bkJDVXpXMGVhbHJHZnpIYm9EM3d2MElscjZJUkdlWCs1MW8yYjNhelZJNmhuTHplSGpiVGtYNUE0ZWhidHJwL1VJTkh6V3BIRXp1NW45RC9TT1hJMmpVS0JiWDhtUTU0NmV4dTlFckNVUDNTZWhqeDVLVllWOEYzekkwQ2lBY3V0VjIvTkRvbDM2NW5iUHVMVUJPaDNJNGQzMzhvSWlDTnhxcDZYb0JqQWZzVkZ4WldjUG1DdVNOTnhaajNzbW5ZUFNvVVpVbElmbDhBYnZ2TmhYZlB2ZWN5cElOV2ZDYngzRHR0ZGRoRlFQNk9vb3BIbWRMeXZPdVU2bUxVOWIxS1pmZGtHdWNCbkg4M0RtWU5ldW9jT01JbHZ4dEtjNi84Q0s4VEdFTWE2QnJ5WExkZlE2V3FWR2dFbzJxcjY4UDlaa1VmdlkvTitPNEUwK0d6LzFFQ1VUMVVWdGU3RnFJNFBGRGtleDRrOWRiYm9JTWhnMnJlM3BhRjUwNUEwcUl5Uyt4cWN6blVOeDJEaEtIL05TVjAvM29hV2g4OWtmaHZUSmVDNDBFeWxqUkMvVHMrMjNVN2ZjdGZtRzg2czdDUUhyWHZJcjRkM1pDTW55TXo0VUQra01CaGRWYytZTzFTRGEwdUV1YnovWEEvOTcreUQ3L0xGQXYrMk4xcW5hb0czZGxDWkRUSWpkMmF1ZnhObzVFK29iVi9YdXRURlV6aW1EMnBlanJadDdLSStKaEgrUWNvOHFVdUk5YXRLMFdjdXBLNDFSZlZRa21wei9PNms3NVlHN1BrQ1R1VzNlWHloLzVZYVg2cXB1YjJUeDRUT3R6eGRWWG9ybkpQZTA1Z0RVTTVEWGt1ekZPT3VWVVhIVHhwUlJCZ05HalI2R0JnWDA2blhKL0dpTFAzcWRFZFNScGdHcnhKVm9GL3ovK3lVOHdiOTYvVkVvWW5EdCtlUWRtenowZWExdmJNVzdNR0paYmh3eUZvTkc1ZUNxRkJGTW1rOGFJbG1iT3B6R1g1YVdTQ29DalQ0ekVVVmoxTUdMM1RVR3FzQVplUFkweFhzK2tGcDhaOUZPWCtYYW1Ebmg1L1Q1c0h3VkEyNkp0eE9QSi9sWTcrNmxya0hPTmNKb05NSzAza1lXWHFrTXdqSTN3NzNrK3VDcTJFWGZEZitoc0pKdTRjVEtGZ01mRGczSmwrdnYvTTJJVWh5aDByb0IzY2dPeWJ6MkwyRWcyREZrZW0yNTA2OUxubUpuaEJMcTVseTdXVFQvdXFjRXhpVFc5N3M5dmlIQ2VXOFZweFhVOCtQSnhseUxleXR5U3BKb3VHWHhKSTg3TXlsa3QwV2tLbnpYbnJNdFRRYlB1RGlHM2xSSHh2eHVKVXplb2JkNFRlQUx5UmVSYVBvVHM2R2s4a1RYMWZRZG9NeG1ubzhhSWxpejVHMDc3NHVsNC9iVTNrYVJycXRLcmUyaHRhOE8wZ3cvRUIzYmR0YkprSGNvejdmQWoyR3UwT2lPTjYzRWJMaXNVQ3VqcDZzS25QcmsvNXM3NUhLWWZPbzI5U1F5NVhqYXRSUGVQR3B0YnNLYWpFM09QbStlV3JjL2RkOTFOd2M3SCtQSGpXQ2Rab1ZBejU2RzN0dzlyMlJ2bTJYT29UTTJYU2pKSHovVjJnd21rdWtTL2J1bWlzTWNPUmpCY3piZCtLYU1DZStoaXZBNjUzV240MHg1Rjd0Q25rRC9vSHVUM3VCejVDWWVod0YzNCthNVFJRXkwSG5oNzAxdnBvNjlUUTBEN3lmVDBJUC9HWTV5dkxLeWdSa1R1VmVxUHQ5TnprVDJHdlJuN1EwaUxxV052ZE9XSzhpVjc2YWtuZWpweWxzS0NkRk02UjlQdW5ma2Z5Si85QUhvdmZCTDVjKzVGM3dsWEliZlAwZlF3VWlpMXJYYmlyQks2V0JVMG93UG8vZklrTkJRV3c4dXdFbnFZVURjQ3VXZTlwZWRhWXozWnErQkRiKy9wYlQ3TkoraFNNYStlcTlLODZoVG80cWdGVjZ5aUlkNzFqM2hybzMzVGR5emtXNUU0Z3U1Sm5DMHpGMHV6RzJOakxsYUpyc2R3ZDNkZHZaTG5qR3B0YXh0S3hRTGRsM3A2R1JRSGwwdUFSUzVyYlczRllkT240OSsvT3ZnakxjZWRjQkk2T2p2ZGZSVGh4RUVYYXNMWTBmamhENjUyeTJyNTVqZlB4WjlmWEloc0p1UHk2a3l1WGJNR1gvbnlHUlRSSVM2UDZLRnhIVEw5Y0l6YlpzTjdQWElUUC8rNVkvR0Z6ODhPcnhQcG8waXUvdEcxZU9qaGh5blVEWjhBcUhXeFhHalI5aWQ0ajN3WUNUM05YVzBjOVR0a1BSMG96UW4wVXdEOTU3ZXl0bjlhYkZ1RVZQT08vZlhTdFNoZTJZQjBzc2oybURiQzgxZjJ5OVJhQWNYbWZaQTkvbmZNeEsxZGdYcklpZlY1L0JyVTNmdEZka0VadW01NkNrUENvL3U4MDlGSXpidlZ4UTVGOWxyQlNYVklOTE5NN1p3TnZQWldZc1BmOTUvUG9YNjdEL0o3ZUE2Rnl0VzhVaTlqbExwdGR1bGZOOEJXTkF3cTlhUXVYNFR1dGR5UXZpT2QwdENqWUFvNDczb0M5OVplcUYyM3Nsb2FDZlVXTGxEbEs1dUdTUVk3aEVtVWM2M3dQbnEzRTRlSUVrY1VHckx0N081R1IzY1BPanU3bmU4dXQ2V0pRb3JyQlMySnBsakVxcFVyc2NPa1NiaHUvalViRmNjZm5uNEdieTVaMGk4T29UdnhQbDJxd2NRaHpqLy9QSFF4dUJUVjB6MmMrNzcxOWw5VXZvVmNmZlhWYUI0NXF2YVNPTll3VUQvN0cxL0g4Y2ZON1JlSDBERDBXYXpuN05uSDhyam9Ia1dnYzFlbWplZ2hDTmRRMWpSNGlYUUMvaE96OUFKcVAxcXJwTzJVMGpYaUVNcnFUN3NlNktielg3TWlRQmF4eFk4alJ6ZE5UNUs3eHpEY2NzNCs5ZzMzS3ZVNkdLUFJvMHZNdm1IZ0NCZ051UklVa0xCU0FUdTkrUFhIOGRxeFhIN1hXaVZ0cC9wcHZyNUdIR0tndmRBVm9sZUh0SUxFN3oyUHdsc3N1RWozU0gvUWhzMkhWNklrM0M4WXNvaWd4UCthc2dqM25mNGQ5K3JzVXVOaW5EcnRjTysxT3h3S3REL3QyKzlwUTNHWGM1RGM1bkFLWHhWN2QrZytqbG81M1FpVVN5UjNSUHRTS3JDbDNXMlhLWGowa1lkdzZhVVhZNmYzdjk5dE14aDMzdm1yQWZHS2FxYnRqenJ5cys2NzNLemFWTlRmUmlFalI0MTBzVWtWaWZiTk54a2sxL0RZLzMwYTZScmhpUktGTjJuaWRqandVL3RYbG16SThYUG11R09LZXBGTXhxSVJ3S0xPclFMdzJuT2FiRURkc2pzUi82bUgzSDBmUXVHUDMwSit6ZTlkcjZPY3F2WDZKZXM5b3RUT3g2SjMrQVJtb2oxVjlpMUhOWjFoL2tjdllnNTZMWlhHTHIvMHo4aTJkdExrOUJZYzBmblBsMURZKy9PTUhZYTV6c2FSektJd2RoUkZvcjJ2STBsUHAyN0ZjMGdkMTRUQ21lUFIrOU5UMGZlWGg1M2JxTFIrL2NSQWdUaENjMDVQbUFydk80K2d1SXltVmZEZE1Kd3VqdnhRZHh4cVBad1Z1aStWLy94dzFzbGlXWG10VVRlczQzT0dwRjVuSzZkQVNmdnFiVU51eDlPUTJlVjhmbWVyeCtYdkJobU9UME9WRzlUWjFZMjJ0dlorWTlYK1V1azBubnYrZWN6NHpFd3NmUGxsdDN4anZQTEtLNGhyNUtlR1REYUxYOXg1Snc0KzVEQk0vOHhuQjZSRFo4ekVRWWNlemgweEVxd1pZUks2SHRYN0wzTDdPanM3QnVSUjNWVG5BeUxFVVdYY21MRzh6aEZOQ2ZldjFyYTA5eDFBUndmejVXa0dNbjkzMGRrVTEvUC9jS1E2WDBiaXhmT1J2UE5qS1A4NGp2SmpzMUhNcjNibE9oSDA3eUI4bFM1KzZDMG85dW9Kck9vS1Rpbnk0T2tybllIcVpyUE90UGZRMXhCVDZPTytLUmRqRDNhcTZWay9jTi9kKzBORVo5Yjc2bU1vNk41dG5zZmpMcjJ6UUJjR3lQWEtkaTVINXNINVNGOXdNRENUYnZoRkI2Q3crTS9LNk15NnlpQUNDZXN2ZFNkM1BRRCt4VStqc0pKR1RxWEdTZ3g0TlNUR0prUS9pcUFLdW1DZUplckFxeTJBcjJHK2lqMDZjWEJlYTlaM2diWnNDc3ZYRC9UNkVzZk8vNEhNN2o5MGRYUkRoWlg2YkM1cjZPL2ZjTjE4L09xTzIvSEEzYi9FbGQrL3pBVzFhdDFWdE9LUFZDWkxRNi9EU1NlZGdudnV2aWZjY0JBS2hienJmYXBVdDAreTJaVExwdDVsc0NRa3ltcHk1NXpMQ3BVYm1NdVdMV1V2TUZCNEtydk05ZVBIREJ4K0hnejFqczVuM3hoY3IzMW14ODlFY1RvOWpQUjRvTHVEaXFGcjVvZDFVSTFpWG9aQmRDTmlEUlJMS292NEc3Y2ljZDFvOVA3aEhHZnN6aWdJbXpRM2pXKzNMN3hSZTlDbTlKdWVRbmtTU0pmeTZGbDRselBTRXRmRlhueVExcSsvNmVmT0dHT1ZFa29mTzRibnJkRUpyWG9qc2N6ZUxURm1aOFRtdDZKMzI3M2dyMlhkS0VDMklOdzFiVmpIb2NlZjlLczNqUWtrZUdyclgzZ1U4Wk4yUitkNS8xVDE2TFNMU29tRG9wRW5ka3ZiZndTRmExY2czNjBJbjRYVHlaUzc1WnhOVG9OeUl1eFZLSW80VTFBSm5OU3p4SmpuWFRiY200NE9uT0wxZWNGS2UvNGNtYWtYdW9QYjJGRGhPMFdIMGNsV3M4cVV5VHZocmp0dW8vRVZYQUJmUFV5NVlRcVFMLzcrVlhoa3dhT1ZwUU54aGxGamlHNlc5ZGZmTkZFY1V0N0VWR0x5bldzU3RweHVKS3pTU0EwZ1FiZG52YWNBQnFPN3I1YysvOXRjTUYxYzdpUGRPQldKYWErZ2VOZ2lOa1pmUXo0OUdtWGRpTzJqQ3dRR0JaVXo0djdpVjd3QjhlRU55RDUxSWZJTGY5Sy9yb3F1VUhubUxTaDM4aHJxMXppY2dKaXl0S25mbnV2eWxCWmNoclQrdWwrbGw5QjZqU2duai81UjVmczY5QWN2TkpxVnFHOUczVGZvNWwyM0dyMUhYb0Q4dU1rb3NsY0pPbWk0dmJxUlhZVTE0QWFKY1I0YW43a0hmVmZNZFQrL3E0aDh3Q2pXaHVqcFNnVXhYdWluZlg4NlVzL2RqL2hZTGxHZ3BCOUNrS3VRWWp1ZDVoN2lMRkREYis2SDNMU2hsRXBCYVRSTEVvL1kwK2FpMDZYekdiQS9MZGFOUTN6L0Z4SExOT25BWEV2eFRubW5Od3J6Tkx6cGg4OUF5OGlScmdYV0lXcXZtcTVZdGd6WGM1dkpPdzJNUitiOXk0bm82T3JocVF0YmUrWE4wMDJhTWYwUW5IREM0RU8zbThvblBuVVFKb3hueTk1UDRPS1lLVk4yeGtYbmZhZXliRU4wRTNMYVlUTXdac3pBSndFRzNDalV5ZFpvcFBNUVpENDZ4N0tPRU9meHIxaUE0T1Zya0hqekYrNmVnbnNBbHZsajZ2WFk0dWRUWTVDZDg0YkwzdzhiR0tvYlBiY2ZnTHJGdjJVand4aEQ1N0xvb2RUUkEvOUNlZ1VYTmpGMDV4NGtFSGRYTzRldUtjY2dQZWNXMmpaN0J1ZFloWVRYUUw1RDJLZUVOaHhXWCt0S2Ivd1I1VWQvaE9RRERPelpnN2dZVzZHQzdrblFTOHF0WnY0SFEzZFMyMGNnSHpHODZIcFBKSFhtZlNpZTlSdmsxSkN1MW0xSHJtR0J1aFBwTVU3eE5PeW5Ma003a3d1bVZyM3lmVU9YYUVzazdydlVoVkt1RmFWZC9oT1k5aFlTNlNaM1VKc2pqczFCajhKZmZlWDNzSHo1OHNxU0VPMTlMQTMxbE5PK2lENjJ6TFhzczg4KzdrMjlLc3FyWjdadSsvbkFFYW5OWWNMNENlNnUrenJvdWlYVGVQTEpwMWpIdHlyTE51U2NzODkyN2wwVXZwZERvWlJEbVNkWVBVT2M0bkRudXBMVWFpZkhIc0JHNnVmby9maVBxYnAxUGE2YVlmZkhqSExWeC85cm9EaEVhc2F2VU9oaHk2NXJ5MytLS1Jodm8vam9lZkQwR2lHWEM1L1RQbjdOSEgydDI2ZDd6cW1HVXFrUE9kYW9hdHhoNmFHeGF6N3h2ZzhqUGU5NjVLOTZGZVZXOXNBYVNhckI3YWFzWjR2ZlZpQWhrb2dVcW1LeXUrNlA5UHdTK21aY2d0NDFMSHcxQTdVYy9YQUt4RDFLVHRVN1YwZnpPcE1TaHhTdloyM0M0M3ZYS0VnTGlwMG85clNqT0dFV2dzL21rWnI4ZGZmajdrUG0wdFd3eTVRcCtOZlRUa1hyNmxWMDZYUnBLMUNrSTBlTXhOR3pqcTBzQ0RuaCtPUFEzVTUzcFBaOE1PK3c0VTJZTWZOSVBQdk1NNVdGZy9QNjY2L2ovQXN1d2hOUFBWVlpzbzZqWnM1Z29CNE9CMWRSV3pGNjlHak1uWGNTN3JudkFTNVp0K1BGaXhmanRETytqSmNXdmJIQjZOZjYrSXd0dkJWUG9QUkxCclV2WFlCQ3gwdXUxM0NYZXIxcGZDbkZIbmZtNjVBTnhmdzgvS1lOYjVwVzBVaFVjYy9qR2UvV1BQVEp1Qzc3Ky9NNENZZlNIWXpoc05jc0pGTjZsa3RsRDhUUDlhRTR5MFB2N2Fjajk4WXp6dnRSdmFvOWlQSzdaYis5RVI0RldIM2YzY0VNWmYwbFp0WmQ3ZjNidUZnYlJ6dlRUZ3VQWFl2WUExOUhxdEFPcjRVN3Ewc2p5TElLdXEydjg1MWlqS0puc2VScUtZRGNuQnVHeXE3TmdsNktMMGNOY2gvYm53eHY2bVZJeE1LTEVMN0JQTEFsMkJ3Mjkxa3NjYzQ1MzhTZm4zOEIyWVpocnNydVl2RDBhaFNwdWJrSk45NXduY3NuSG4vaUNYejluSE14ZnR4NFh2ZndmQ2kvN29kMGRuVzVrYWhKMjIySHNYUjVrblJidTNwNnNITFZHaXg3YXprRDlESjdwUnl1dVBSaWZPUWo0WU9HdFJ4NTFESHUrdFRlWnhHNjFMcVJLTGRRajVrb2hsRnZvK2UwdEU0dTMvcWpaT3ZmS01US0p4RC8zU2ZjejdrR09ibytyTHFmM3BZN0c4dGo1citlWlVEWE1zU1N2QzVlSFkrSlI4VmppaFVERk9rdWxUNzNKMlJIN2U3S1hoOWRRYVhnT3g1U3d5aEdmV0ZQSlRjdHBzRWh0ZlFNd0F2eVhyN2JSVytoWWRBV3ZwRHZSdXhFWG9OaE5MYytDcGJsbEp2cmtkQndNc3NyZDdVanRteUZpdzRVNTNoRmxoSXdubVA1d2QvSzZEM3JPZ3liZHFLcit5YjFJSU9oRFdXYW1mMU9SdXFpTmhUT2ZCNzV5U2VpcDVjblpCVTd1TzRlbmwzV0xrLy9zTWdhVm9ZR3BJME5YYVgxa3dJb1hvNkEyNWZaVGVkYkdXUXl4bWc1Q0lXUDNnWHZpQnhTdTEySkpNV2hVc09TMzcwNDNpMFhYSEErR21oc01qd25EcVp3ZEN1REZhdlg0Tnh2bmVmeWlVL1F6YnI0d3ZPeFl0VXE5TkVJcSsyVWd2eW00Y09kMGE2aUtQLzBsNy9nRDgvK0NRdGZmaFVkSFIwWTNqak1pVmZQVlBXLzRMWWV0LzdzWmhwK0tJYmE5azlDVlAxYUtOYTZiTmE5QWFuUnNhN3VidmRFYjExOXZSc2RpeUtNN1hoY3lVYUtaQVRpZEdtVGpIeVRQUzhnMGZsWHhQMDJ4QlVEeHVwNS9NenIwN3Vnd2VaWmw5SVJkeU5EY1d6c1hrdWNzcGFreS90OUMrV0NlcEdxZVlaWDJLRkJrVDAvUjUrVTR0aElPZjBqY1JuYXgvQTRrb3d6TW9WZUpGYThndmhiQzVIdW9qZ2FLZVlNNHc4M2lFTmIwOS9nWDFaR3o1Y3VjdUlRVHZBOGdZUHZaVlBSUmFJcVZZZ3pDS1o4Njk4UXZIWTd2R1cvUnF6dEtTUks3YXdzVi9EbzlYT2dYa3lqTGVHRkNGdFBicVZoUzRtRGRkVWlQOG1MTlh3UGVDUDNSWG5zWWNpMGZMem1OREVmUDNVQVc1b0hIbndJNTUxM0FacEd0TENPWWZtcWo0ejExcHYrR3p2c3NMMWJ0akgwcU1TblAzMG9VbW4yMHpValFqS1d0dGExT1BhWVdUampTNmRYbHZJNGVmb3Z2ZXo3ZU9TUkJlNE9kWkt4aUhwYXZWNmdyY0l6cXRQRG9KUG5xUHJlZXowTlhMSFB4SWtiNzlFdXYrSXEzSHZ2ZlVnenIxNFJEbnVIc0V5VkZkNkl6R1BlM05tWVBYc09Eam4wY0xkZnhRcFY4blIzZEEvbG5HOThYZDR5Y3UyL1IrelJqemxENXVWaVNTeVQxMUpPdUVZeTllZnZYQnl2eTh0cldjendQTzQ0RDdHOUxxRUx6SDNMM053MUg0endxbW9FcVhUNU1OU1ZhYlZzQkhXT1lteGtTN1NiOHFvK3hDN3VSQ0xKSGlMTXZnRzlGRmZwOUN3eWJKZjExRlAvVS9NeVZkVloyOUhINHFWQ3dKMzV0TTNpUHJPUm1uc1Zrc1BDaHgycnhiNTdnYXlISGtkWjk4NjVxMU00N1Z6TURtRVI0bjFMZVBRVVRMSGRuWEM1Umw1OEpJWERMalgxUHZpTkUraW03VVFSaGU2QktscHRSNGFDRlN0WDRxV1hYbUlMVFRldXNrejA5ZVh4OFkvdDZaNjJmVHVXTGwyR1JhKy93UzU4WUsrbVk5R2JoOU9tVGVzZndhcmx1ZWYrakw4OC96eVdyMXlGOXZaMjUvNW9td1NOdTdHeEVTTmFXckQ5OXUvRGgzYjdBSm81dnlsSUNMK20rRjU4OFNXc1dic0dSYnBYS20vVXlKSFliZW91T1BEQUF5czVnY2QrOTdoN01GSzlYaFhWUVkvd1Q5bDVNaSt1WEtyd21FcjUxZkE2WGdTNi84cnIya29EN2xadStERzZWWmtSaU5WL0FNR0lEN25lcEw4ZjBBbGRWL1JHa2MzMFhqOFZEYTBMMmEyayt3VVNVTkI5azJlajd0aWJ3b3did1hsbVRJVWlYZklsejlLZGVoRisxeXJXazk2SVl1RUViYXQrRkx6Uk82RDh2cjJRYWg3djZqaFkxYmE0UUF6ajNkTDN3bTNJM0RFTGdYNUxXYjJkRTBnSnBkWWl5aGYxSUoxU0ZEMDBER1hqYkJnT3VkZnFKYXFwMmtKclh1NVYvSjVaOEJyU2pDWFVGeEMxNGJraWN2dDlDUW05TXhJdUhSSk1JTWFRRXpBdzlvTThlbi96VlhyYXI5TGQ3b1YrRXJiMDBpMG9mVDlGRjFCQmcxeTVpbm42T2ZRazY1Q2RjWlcraEs3YUVHRXVsakhreUdVcU1jN3hML0xjbzFVYXpsVThHcWNlM0tQNGZ1WGRHbzByKzNuazlBakt1UjFJcFlmK0YvbXRCekhlQTBJejF5dXV1cGNScjYrblVES0laZXBRcmp4c3FZY0tTM25kRVU4aFRuRWtuRGpraEEwdEpoQmp5QWtqRU5KTGtXajBxOUREYVE1bGpUcnBFWnllSElxYytudi9CeEpmNjBPYzR0Qjc3ZStGdVpxTFpRdzVnVjlDS1paQThPWjlLSzMrS3hKOVN4SEx0YVBzMWNHdjJ4YXhpWHNqdHMwbncvYzZ3azNlTTB3Z3hwQVRXcHp1eUc5by9scWw1TzZHdjlmcUlDWVF3NGpBWWhERGlNQUVZaGdSbUVBTUl3SVRpR0ZFWUFJeGpBaE1JSVlSZ1FuRU1DSXdnUmhHQkNZUXc0akFCR0lZRVpoQURDTUNFNGhoUkdBQ01Zd0lUQ0NHRVlFSnhEQWlNSUVZUmdRbUVNT0l3QVJpR0JHWVFBd2pBaE9JWVVSZ0FqR01DRXdnaGhHQkNjUXdJakNCR0VZRUpoRERpTUFFWWhnUm1FQU1Jd0lUaUdGRVlBSXhqQWhNSUlZUmdRbkVNQ0l3Z1JoR0JDWVF3NGpBQkdJWUVaaEFEQ01DRTRoaFJHQUNNWXdJVENDR0VZRUp4REFpTUlFWVJnUW1FTU9Jd0FSaUdCR1lRQXdqQWhPSVlVUmdBakdNQ0V3Z2hoR0JDY1F3SWpDQkdFWUVKaEREaU1BRVloZ1JtRUFNSXdJVGlHRkVZQUl4akFoTUlJWVJnUW5FTUNJd2dSaEdCQ1lRdzRqQUJHSVlFWmhBRENNQ0U0aGhSR0FDTVl3SVRDQ0dFWUVKeERBaU1JRVlSZ1FtRU1PSXdBUmlHQkdZUUF3akFoT0lZVVJnQWpHTUNFd2doaEdCQ2NRd0lqQ0JHTVpHQWY0WDdwQllZdkhldWJJQUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMTAtMTEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTEwLTExIn0seyJhYWd1aWQiOiI5OThmMzU4Yi0yZGQyLTRjYmUtYTQzYS1lODEwNzQzOGRmYjMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6Ijk5OGYzNThiLTJkZDItNGNiZS1hNDNhLWU4MTA3NDM4ZGZiMyIsImRlc2NyaXB0aW9uIjoiT25seUtleSBTZWNwMjU2UjEgRklETzIgQ1RBUDIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQzJUQ0NBb0NnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpCN01Rc3dDUVlEVlFRR0V3SlZVekVYTUJVR0ExVUVDQXdPVG05eWRHZ2dRMkZ5YjJ4cGJtRXhGREFTQmdOVkJBb01DME55ZVhCMGIxUnlkWE4wTVJBd0RnWURWUVFMREFkU2IyOTBJRU5CTVE4d0RRWURWUVFEREFaamNuQXVkRzh4R2pBWUJna3Foa2lHOXcwQkNRRVdDMmx1Wm05QVkzSndMblJ2TUNBWERUSXlNREl5TVRJd01URXpNVm9ZRHpJd056SXdNakE1TWpBeE1UTXhXakNCalRFTE1Ba0dBMVVFQmhNQ1ZWTXhGekFWQmdOVkJBZ01EazV2Y25Sb0lFTmhjbTlzYVc1aE1SUXdFZ1lEVlFRS0RBdERjbmx3ZEc5VWNuVnpkREVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVQTUEwR0ExVUVBd3dHWTNKd0xuUnZNUm93R0FZSktvWklodmNOQVFrQkZndHBibVp2UUdOeWNDNTBiekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCUERIQmdhN2Q2dU5nYVVqRTE1UWh4dmd5ZVR0VWgzdVRHSkNYaDFNLzVwNS9OL2MzRUZqb2cwR29PTjBmTVpwSVpqNk9ENzBXQzFJWE9wVlE0ZmJmdGFqZ2Q4d2dkd3dIUVlEVlIwT0JCWUVGTUZ0MndQQTNwZFhRUGFXMlVnWHZlRWx5N1NrTUlHaUJnTlZIU01FZ1pvd2daZWhmNlI5TUhzeEN6QUpCZ05WQkFZVEFsVlRNUmN3RlFZRFZRUUlEQTVPYjNKMGFDQkRZWEp2YkdsdVlURVVNQklHQTFVRUNnd0xRM0o1Y0hSdlZISjFjM1F4RURBT0JnTlZCQXNNQjFKdmIzUWdRMEV4RHpBTkJnTlZCQU1NQm1OeWNDNTBiekVhTUJnR0NTcUdTSWIzRFFFSkFSWUxhVzVtYjBCamNuQXVkRytDRkZONk83eG5JS2I3NDgzcHFpcWd1QVQ2VnBRTU1Ba0dBMVVkRXdRQ01BQXdDd1lEVlIwUEJBUURBZ1R3TUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUZ3OG5tTEU2eWJNRWFmT2NoZ21YcGNINE5Jc2R3V2xEdWZyZWRMK0IrQ2lBaUJIV3N5Nzd3MDllQy9zRWpvVmNHa213UmNaa1R0bXJZb056Z3VpallNVnRRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBREFBQUFBd0NBSUFBQURZWUc3UUFBQUtMMmxEUTFCSlEwTWdjSEp2Wm1sc1pRQUFTTWVkbG5kVVZOY1doOCs5ZDNxaHpURFNHWHFUTGpDQTlDNGdIUVJSR0dZR0dNb0F3d3hOYklpb1FFUVJFUUZGa0tDQUFhT2hTS3lJWWlFb3FHQVBTQkJRWWpDS3FLaGtSdFpLZkhsNTcrWGw5OGU5MzlwbjczUDMyWHVmdFM0QUpFOGZMaThGbGdJZ21TZmdCM280MDFlRlI5Q3gvUUFHZUlBQnBnQXdXZW1wdmtIdXdVQWtMemNYZXJySUNmeUwzZ3dCU1B5K1planBUNmVELzAvU3JGUytBQURJWDhUbWJFNDZTOFQ1SWs3S0ZLU0s3VE1pcHNZa2lobEdpWmt2U2xERWNtS09XK1NsbjMwVzJWSE03R1FlVzhUaW5GUFp5V3d4OTRoNGU0YVFJMkxFUjhRRkdWeE9wb2h2aTFnelNaak1GZkZiY1d3eWg1a09BSW9rdGdzNHJIZ1JtNGlZeEE4T2RCSHhjZ0J3cExndk9PWUxGbkN5Qk9KRHVhU2tadk81Y2ZFQ3VpNUxqMjVxYmMyZ2UzSXlremdDZ2FFL2s1WEk1TFBwTGluSnFVeGVOZ0NMWi80c0dYRnQ2YUlpVzVwYVcxb2FtaG1aZmxHby83cjROeVh1N1NLOUN2amNNNGpXOTRmdHIveFM2Z0JneklwcXMrc1BXOHgrQURxMkFpQjMvdytiNWlFQUpFVjlhNy94eFhsbzRubUpGd2hTYll5Tk16TXpqYmdjbHBHNG9ML3JmenI4RFgzeFBTUHhkcitYaCs3S2lXVUtrd1IwY2QxWUtVa3BRajQ5UFpYSjR0QU4venpFL3pqd3IvTllHc2lKNWZBNVBGRkVxR2pLdUx3NFVidDViSzZBbThLamMzbi9xWW4vTU94UFdweHJrU2oxbndBMXlnaEkzYUFDNU9jK2dLSVFBUko1VU56MTMvdm1ndzhGNHBzWHBqcXhPUGVmQmYzN3JuQ0orSkhPamZzYzV4SVlUR2NKK1JtTGErSnJDZENBQUNRQkZjZ0RGYUFCZElFaE1BTld3Qlk0QWpld0F2aUJZQkFPMWdJV2lBZkpnQTh5UVM3WURBcEFFZGdGOW9KS1VBUHFRU05vQVNkQUJ6Z05Mb0RMNERxNENlNkFCMkFFaklQbllBYThBZk1RQkdFaE1rU0I1Q0ZWU0FzeWdNd2dCbVFQdVVFK1VDQVVEa1ZEY1JBUEVrSzUwQmFvQ0NxRktxRmFxQkg2RmpvRlhZQ3VRZ1BRUFdnVW1vSitoZDdEQ0V5Q3FiQXlyQTBid3d6WUNmYUdnK0UxY0J5Y0J1ZkErZkJPdUFLdWc0L0I3ZkFGK0RwOEJ4NkJuOE96Q0VDSUNBMVJRd3dSQnVLQytDRVJTQ3pDUnpZZ2hVZzVVb2UwSUYxSUwzSUxHVUdta1hjb0RJcUNvcU1NVWJZb1QxUUlpb1ZLUTIxQUZhTXFVVWRSN2FnZTFDM1VLR29HOVFsTlJpdWhEZEEyYUMvMEtuUWNPaE5kZ0M1SE42RGIwSmZRZDlEajZEY1lESWFHMGNGWVlUd3g0WmdFekRwTU1lWUFwaFZ6SGpPQUdjUE1ZckZZZWF3QjFnN3JoMlZpQmRnQzdIN3NNZXc1N0NCMkhQc1dSOFNwNHN4dzdyZ0lIQStYaHl2SE5lSE80Z1p4RTdoNXZCUmVDMitEOThPejhkbjRFbnc5dmd0L0F6K09ueWRJRTNRSWRvUmdRZ0poTTZHQzBFSzRSSGhJZUVVa0V0V0oxc1FBSXBlNGlWaEJQRTY4UWh3bHZpUEprUFJKTHFSSWtwQzBrM1NFZEo1MGovU0tUQ1pya3gzSkVXUUJlU2U1a1h5Ui9KajhWb0lpWVNUaEpjR1cyQ2hSSmRFdU1TanhRaEl2cVNYcEpMbFdNa2V5WFBLazVBM0phU204bExhVWl4UlRhb05VbGRRcHFXR3BXV21LdEttMG4zU3lkTEYway9SVjZVa1pySXkyakpzTVd5WmY1ckRNUlpreENrTFJvTGhRV0pRdGxIcktKY280RlVQVm9YcFJFNmhGMUcrby9kUVpXUm5aWmJLaHNsbXlWYkpuWkVkb0NFMmI1a1ZMb3BYUVR0Q0dhTytYS0M5eFdzSlpzbU5KeTVMQkpYTnlpbktPY2h5NVFybFd1VHR5NytYcDhtN3lpZks3NVR2a0h5bWdGUFFWQWhReUZRNHFYRktZVnFRcTJpcXlGQXNWVHlqZVY0S1Y5SlVDbGRZcEhWYnFVNXBWVmxIMlVFNVYzcTk4VVhsYWhhYmlxSktnVXFaeVZtVktsYUpxcjhwVkxWTTlwL3FNTGt0M29pZlJLK2c5OUJrMUpUVlBOYUZhclZxLzJyeTZqbnFJZXA1NnEvb2pEWUlHUXlOV28weWpXMk5HVTFYVFZ6TlhzMW56dmhaZWk2RVZyN1ZQcTFkclRsdEhPMHg3bTNhSDlxU09uSTZYVG81T3M4NURYYkt1ZzI2YWJwM3ViVDJNSGtNdlVlK0EzazE5V045Q1AxNi9TditHQVd4Z2FjQTFPR0F3c0JTOTFIb3BiMm5kMG1GRGtxR1RZWVpocytHb0VjM0l4eWpQcU1Qb2hiR21jWVR4YnVOZTQwOG1GaVpKSnZVbUQweGxURmVZNXBsMm1mNXFwbS9HTXFzeXUyMU9ObmMzMzJqZWFmNXltY0V5enJLRHkrNWFVQ3g4TGJaWmRGdDh0TFN5NUZ1MldFNVphVnBGVzFWYkRUT29ESDlHTWVPS05kcmEyWHFqOVducmR6YVdOZ0tiRXphLzJCcmFKdG8yMlU0dTExbk9XVjYvZk14TzNZNXBWMnMzWWsrM2o3WS9aRC9pb09iQWRLaHplT0tvNGNoMmJIQ2NjTkp6U25BNjV2VEMyY1NaNzl6bVBPZGk0N0xlNWJ3cjR1cmhXdWphN3liakZ1Slc2ZmJZWGQwOXpyM1pmY2JEd21PZHgzbFB0S2UzNTI3UFlTOWxMNVpYbzlmTUNxc1Y2MWYwZUpPOGc3d3J2Wi80NlB2d2ZicDhZZDhWdm50OEg2N1VXc2xiMmVFSC9Mejg5dmc5OHRmeFQvUC9QZ0FUNEI5UUZmQTAwRFF3TjdBM2lCSVVGZFFVOUNiWU9iZ2srRUdJYm9nd3BEdFVNalF5dERGMExzdzFyRFJzWkpYeHF2V3Jyb2NyaEhQRE95T3dFYUVSRFJHenE5MVc3MTA5SG1rUldSQTV0RVpuVGRhYXEyc1YxaWF0UFJNbEdjV01PaG1Oamc2TGJvcit3UFJqMWpGblk3eGlxbU5tV0M2c2Zhem5iRWQyR1h1S1k4Y3A1VXpFMnNXV3hrN0cyY1h0aVp1S2Q0Z3ZqNS9tdW5BcnVTOFRQQk5xRXVZUy9SS1BKQzRraFNXMUp1T1NvNU5QOFdSNGlieWVGSldVckpTQlZJUFVndFNSTkp1MHZXa3pmRzkrUXpxVXZpYTlVMEFWL1V6MUNYV0ZXNFdqR2ZZWlZSbHZNME16VDJaSlovR3krckwxczNka1QrUzQ1M3k5RHJXT3RhNDdWeTEzYys3b2VxZjF0UnVnRFRFYnVqZHFiTXpmT0w3Slk5UFJ6WVROaVp0L3lEUEpLODE3dlNWc1MxZStjdjZtL0xHdEhsdWJDeVFLK0FYRDIyeTMxV3hIYmVkdTc5OWh2bVAvamsrRjdNSnJSU1pGNVVVZmlsbkYxNzR5L2FyaXE0V2RzVHY3U3l4TER1N0M3T0x0R3RydHNQdG9xWFJwVHVuWUh0ODk3V1gwc3NLeTEzdWo5bDR0WDFaZXM0K3dUN2h2cE1Lbm9uTy81djVkK3o5VXhsZmVxWEt1YXExV3F0NVJQWGVBZldEd29PUEJsaHJsbXFLYTk0ZTRoKzdXZXRTMjEyblhsUi9HSE00NC9MUSt0TDczYThiWGpRMEtEVVVOSDQvd2pvd2NEVHphMDJqVjJOaWsxRlRTRERjTG02ZU9SUjY3K1kzck41MHRoaTIxcmJUV291UGd1UEQ0czIranZ4MDY0WDJpK3lUalpNdDNXdDlWdDFIYUN0dWg5dXoybVk3NGpwSE84TTZCVXl0T2RYZlpkclY5Yi9UOWtkTnFwNnZPeUo0cE9VczRtMzkyNFZ6T3VkbnpxZWVuTDhSZEdPdU82bjV3Y2RYRjJ6MEJQZjJYdkM5ZHVleCsrV0t2VSsrNUszWlhUbCsxdVhycUd1TmF4M1hMNisxOUZuMXRQMWo4ME5adjJkOSt3K3BHNTAzcm0xMER5d2ZPRGpvTVhyamxldXZ5YmEvYjErK3N2RE13RkRKMGR6aHllT1F1Kys3a3ZhUjdMKzluM0o5L3NPa2grbUhoSTZsSDVZK1ZIdGY5cVBkajY0amx5SmxSMTlHK0owRlBIb3l4eHA3L2xQN1RoL0g4cCtTbjVST3FFNDJUWnBPbnA5eW5iajViL1d6OGVlcnorZW1DbjZWL3JuNmgrK0s3WHh4LzZadFpOVFAra3Y5eTRkZmlWL0t2anJ4ZTlycDcxbi8yOFp2a04vTnpoVy9sM3g1OXgzalgrejdzL2NSODVnZnNoNHFQZWgrN1BubC9lcmlRdkxEd0cvZUU4L3ZNTzd4c0FBQUFDWEJJV1hNQUFCWWxBQUFXSlFGSlVpVHdBQUFHaUVsRVFWUll3KzJZYTJ3VVZSU0F6engydTd0dGQwc0R0UzJZU3JGMGE2VWFNV0lUbzJBdEFXSUJLU3BGTkNTS1JtbXd2akNrVVJPTXFCVTFQZ0NyQkRRK0NJS2dnaStNNzlyYUFrRm9HNUJnb1ErZ25iYk1kcmU3c3pQM2NmeHhsM0ZiQ2xUakQzL3MrVFZuOXN5OTM1em4zWkVRRWY1UElzUC9UQkpBQ2FBRVVBSW9BWlFBK29laXhpdUluREdPaUtxcVNwSjA0U2NaWTV4eldaWmxXWW0zcFpRQ2dLSW9GMTBCQUJDUk1SWnZMTm5UWHF3dXJvUEI0UEhqeDNWZEh4Z1lNRTNUc2l6R0dBQWtKU1c1M1c2Zno1ZVJrZUgzKzRVOVkweVdaYkVpSW82R3c2YmhuQ3VLQW9oZ1A0V0k0Z2RFM1BMaCsxY1hUUm05ZTFOU3ZJc1czM1h3VURNaWNvNlVFa1FzWHpDL3RIUm1lK2RKU2doZVRBNzlmbURjMkxHN3Z2eWFVU29ZSkVSa2pDcUtXdm5nL2V2ZWVrZnNsSjZlN3ZGNHZGNnYyKzEydVZ5S290aGVwSlNHUWlGZDF3TUJQUkl4eFAybWZmdXZ1Zm9xenBqRDZWUVZpWEZvT1h3a0wzZWkwK2s4OXpVNFo3S3NXRkhqcWFlZnJubHBMUUJNekx1aTdXZ3JwVlJWMVppSGZ2M3BPMkc5Y2xWMWEydHJkMDlQYjIrdnJ1dkJZSEJ3Y0RCOFZnWUhCME9oVUNBUTBEU3RvNk5qejlkZnBhZDVBZUQ2RzI1R3hFZ2tnb2dlbHhNQVdvNzhZWnJtdVM2eExBc1JHeHZxYzNJdUZUdmVmTXZNRSszdHdqMklDT0pxNmQwVkFIQm54ZDJJYUpwUnhwaElOMG9wcGRRT2E3eEtDREV0YTE5VFl5ekhFWTFJK0FKQVlpUFROQjkvN0ZHUjlUNnY3K1ZYWGhkTDJXWXhEeFVXNUN1cTQvVjFHNFRhMXRiVzBORFExZFVsMU1OSGp0VFYxV2xhYnl6d0J3ODJOVFYxOS9SUVF2cjdlaWZsVEFDQWhzYjluSkVSZ1RqbndqRmY3TjVWNE04WEwzQnIyZHlqeDlvUTBUU3RlTzRZVU83RXk5d3UxeWM3UHhWcVZWVlZjbkpLVFUyTlVHOHZMd2VBUGQvc0VaNmJNWDE2VmxiMngxdTNJcUpoaEV0TGJnU0FMZHQyQytOaFFKekhXc2s5U3haN1BCNUI4OEZIV3htam9oU0dpUW9BNFFHZFdFUldIRzYzTjlZTUFCd09sZk5ZUjFCVVZWWVVyYmRmMUxra1NiSXNEWVlOQUpCbDFlTkpCWURUcHpyT1Y0d045WFVWRllzNnUwNEJ3UFFadDN5eVk1czNKUVZBQW9BUldnUWk5cHp1eU15OHhPdE4rNlcrVVdBR2cwRk4wd1lHZ2tJZENBUzZ1N3ZENGJCUWRWM1hOQzBjam5ET0tTRjNsTThIZ09wbjFnenpFS1cwdjcvdmthb1ZZcU54R1psdnY3TXhQcDlHRkJVQXFFbUJjNUJBa1dLTk96VTFOVFUxMVliMitueGVuODlXMDlMUzdDNGdTU0FyQ2dCd2JnMnRiUjZOUmlzZmVuREwxbTBBVURaL1FXM3QrcXlNUzJJUk9IL3psQUVBUWJScjZWOE5IMG1XWkFDQW9YL3ZaRWwySlNWZFgxeWM1SFFDd0s1UGQremMvcGxoR0tNYXJnNm5LaXNTSURMT3hDaDRkL1BteXNySyt2cmZoTkhidGJYTGxpMXJibTRXNEsrc1hidHk1Y3E5ZS9mS3NveUloRm9BSUN2cVVFNWduSzk0K0pFZmZ2eCt4dlNiQUdENThnZEtaODdhdC84QUFCQkNMalJROUw2ZThkbFpLY25lYjcvN1dmU3V1V1ZsQUxCaFE2MklhMmxKQ1FEczJMRlRWRm5SbENtU0pHL2F0QWtSTGRPY1YxWUdBRFd2dm5GdWxZbGNpUnJHYTYrK0xIcVB5K1Y2Y2xXMWFFZ2pacElNQUQ2ZjE2azZLQ2VSeUlBSWNFbEp5WklsU3pJell5R2ZOWHYyd29VTFBaNWtVV1h6NXMxZnVuUnBWdFo0QU9DY1JpSUJBSmd3L3RJUndpbEpBS0E2SEN1cUhqM1JkdXpLd2lzSUlTOCsvMXp1NWY2angvNGNPWk1FMTZUY3l4d081OFpON3czajVad1BlNDk0MVRTamZYMTlFM01tQUVCZHcxN082UGs2dGQzZlgzeGhqVU5WQWNEaFRGcFYvWlJGU1B5dmY0K08yK2JPQVlCRmkrOFJ6clFzeTdJc01sVG9XU0dFV0pabG1xWkZTR1A5TC9hTFJTNDRPbXpwN0dpZmR0MjFBQ0JKY3U2a3l3OGNha1pFY3BZcDVxRXZQdHN1MW4zaXlWVXRMYTA5UFpxbWFmMzkvYnF1NjdvZUNBU0N3V0FvRkJLVDljeVpNNXFtZFhaMmZMbjdjN0g5bkxubGlHZ1l4bWlBaE5ueno2MU84OFpheWVwbjF3UUNnYitCeEd5YlZ6YkhqdVBZc2VPeXM3UHo4dkw4Zm45QlFVRmhZZUhVcVZPTGk0dW5UWnRXVkZTVW41K2ZtWm1aZkhZT2VEd3BKenE2Q0NHV1pkckh2ZWJEaDg4SFpNZW90ZVhRN0ZremhYMzFNNnVIZUloemJwbm0rblZ2K3ZNbmo3NEYrZExHUExTOHNyMnpNMzZiKys2N3QySlJSZGVwMC9HWmNhNklWS0dVdnJkNVk5YjRIUHZ4a1krdzNkM2RKMCtlakVhampESERNRVFPY2M0bFNYSTZuV1BHakVsUFQ1ODhlYkk0dUlsRHNWMGsvNmpCMnB2YWkwanhYOUJFVFFHQXFxb1hYY3MrNU1mUnhPNERnSDNLSGcwVDU5emVVVXA4MGtzQUpZQVNRQW1nQkZBQzZMK1Z2d0NxR2ZIeWtBcG1vd0FBQUFCSlJVNUVya0pnZ2c9PSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiY3JlZFByb3RlY3QiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfSx7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI5OThmMzU4YjJkZDI0Y2JlYTQzYWU4MTA3NDM4ZGZiMyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEyLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjI1NiwidHJhbnNwb3J0cyI6WyJ1c2IiXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTAzLTMwIiwidXJsIjoiaHR0cHM6Ly9jcnAudG8iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ik9ubHlLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIyMDMzMDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wMy0zMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDEtMTEifSx7ImFhZ3VpZCI6IjYxMjUwNTkxLWIyYmMtNDQ1Ni1iNzE5LTBiMTdiZTkwYmIzMCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNjEyNTA1OTEtYjJiYy00NDU2LWI3MTktMGIxN2JlOTBiYjMwIiwiZGVzY3JpcHRpb24iOiJlV0JNIGVGUEEgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjI1NiwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNwVENDQWtxZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd0hoY05NVGd3TnpBeU1EVXpNVE01V2hjTk1qTXdOekF4TURVek1UTTVXakNCcnpFTE1Ba0dBMVVFQmhNQ1MxSXhFVEFQQmdOVkJBZ01DRk5sYjNWc0xWTnBNUk13RVFZRFZRUUhEQXBIWVc1bmJtRnRMVWQxTVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUWlZkQ1RTQkRRU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUUlmcUhpc2kwb08vZXlPcVNhRHJyOWl0RzJJeW1Ca0huU0RHUUlJWW1UK3ZxQThBZ084MW1vbWMyTGQ1UEdwRU42bXVFNTR3UEhRanZjL3lDaWg4dTJvMVV3VXpBU0JnTlZIUk1CQWY4RUNEQUdBUUgvQWdFQU1CMEdBMVVkRGdRV0JCUzNKL2Z4aUF2MjJpcmRCczk4U09EaEY3a1UvakFMQmdOVkhROEVCQU1DQVFZd0VRWUpZSVpJQVliNFFnRUJCQVFEQWdBSE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRGM0MUxGSzRMSkNCVTJWVktJejdaNnN4UGhVRWtoOG5MU0xLNklYZGtQNXdJaEFJZUtWT1pjaGFWTzVhRjdmYmRYb1NyY3l5MVlZZVVlUExvamNLSTlmWDg0IiwiTUlJQ2dqQ0NBaWlnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQm5URUxNQWtHQTFVRUJoTUNTMUl4RGpBTUJnTlZCQWdNQlZObGIzVnNNUkF3RGdZRFZRUUhEQWRIWVc1bmJtRnRNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRVpNQmNHQTFVRUN3d1FRMlZ5ZEdsbWFXTmhkR1VnVlc1cGRERVpNQmNHQTFVRUF3d1FaVmRDVFNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SUJjTk1qTXdOekV4TURNME5qRTBXaGdQTWpBM016QTJNamd3TXpRMk1UUmFNSUdkTVFzd0NRWURWUVFHRXdKTFVqRU9NQXdHQTFVRUNBd0ZVMlZ2ZFd3eEVEQU9CZ05WQkFjTUIwZGhibWR1WVcweEZ6QVZCZ05WQkFvTURtVlhRazBnUTI4dUxDQk1kR1F1TVJrd0Z3WURWUVFMREJCRFpYSjBhV1pwWTJGMFpTQlZibWwwTVJrd0Z3WURWUVFEREJCbFYwSk5JRU5sY25ScFptbGpZWFJsTVIwd0d3WUpLb1pJaHZjTkFRa0JGZzVwYm1adlFHVXRkMkp0TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBaCtvZUt5TFNnNzk3STZwSm9PdXYySzBiWWpLWUdRZWRJTVpBZ2hpWlA2K29Ed0NBN3pXYWlaell0M2s4YWtRM3FhNFRuakE4ZENPOXovSUtLSHk3YWpWVEJUTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZMY245L0dJQy9iYUt0MEd6M3hJNE9FWHVSVCtNQXNHQTFVZER3UUVBd0lCQmpBUkJnbGdoa2dCaHZoQ0FRRUVCQU1DQUFjd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFOVm5KZGUvL3RCTHE4TUREaStTQWQ2VWRZSVpTbmc0UE1xbXlOcnZaajY0QWlBWDB4U3pBaEZhQ0NwL3VocFZnbmxGK1hCZ3J3QUlzb3RaR1RCNnJrQjMxQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBRXhDQVlBQUFEdkRZZ3FBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFGaWNTVVJCVkhoZTdkMEhlQlhGMnNEeE43M1FDVFZBNkZJRkZLa0NVdXlBRXVtS1lrRlViSUNDSWlLQ1VnUUU3TDBnZGxRc0tDcFNySWdnU0MraEpuUkNKNEgwYjJmdmVELzBraENTbmMyZWsvL3Z1WG1ZZDQ2WGtKTno5c3k3TS9OT1FKWkZBQUFBQUFCQWdRclVmd0lBQUFBQWdBSkVnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUVCQWxrVzNQU3N6TlZYU0R5VEtxYTFiNWRTYWRaSzZlNCtrSHo5bTk0bjMvL21BY1FFaG9SSmN1cFFFUjBWSldKVktFdDZndm9SWHJ5WkJwVXBKUUNEMzRRQUFBQUJmNE5rRVBTc2pRMDV0M2lLSFB2cEVqdit3UU5MMzdaT3MxRFQ5S0lDekNZeU1sTkFhMWFURU5aMmxaSmZPRWxxaHZQV09EOUNQQWdBQUFQQWF6eVhvS2pFL012YzdTWHh6aHB4YXNWTDNBc2lQZ05BUUtkcXh2WlM5WTRBVWFkSlk5d0lBQUFEd0VrOGw2TWQvKzEzMmpIdEtVdGF0MXowQW5GYTg2OVZTWWRnUUNhdFNSZmNBQUFBQThBSlBKT2daSjA3SW5vbFQ1UEFISDR0a1p1cGVBS1lFaElkTGhWRWpKS3BYZHdrSUR0YTlBQUFBQUFwU2dTZm9wN1pzbFIwREIwbnExdTI2QjRBckFnS2syQldYU3BYSkV5U29hRkhkQ1FBQUFLQ2dGR2lDZnVMUDVSSS9ZSkJrSERtaWV3QzRMYnhSUTZuMjVpc1NFaFdsZXdBQUFBQVVoQUpMMEU4c1hTWTdicmxETXBPU2RBK0FnaEphcTRiVS9PaGRDUzVkV3ZjQUFBQUFjRnVCSEpDc2xyWEgzM2t2eVRuZ0VhbWJ0OHIyZ1lNa2cvY2tBQUFBVUdCY1Q5RFRqeDZUN2JmZElSbUhEdXNlQUY1dzhzKy9aT2NqajBrV2hSb0JBQUNBQXVIcUVuZDF4bm44QXcvSnNTL202SjV6RnhnWklVR2xTa2xJamVvU1ZLSzQ3Z1VLT2V0dG5MNXZ2NlR0aUplTUkwY2xLeTFOUDNEdUtrNFlLMlg2OU5JUkFBQUFBTGU0bXFBZlhiaklMZ3AzemtlcEJRWksrUGtOSktwL1B5bld1cVVFbHlrakFVRkIra0VBZjh0TVRaWFVYYnZrNkxmejVORE05eVY5ejE3OVNPNEZsaXdoNS8zd0RVWGpBQUFBQUplNWxxQm5KQ1ZMM0ZYWFNGckNUdDJUTzZFMXEwdkZVU09rZU5zMmRxSU9JSGN5VDU2VWd4OThMUHVmZVY0eWp4M1h2YmxUb2x0WGlaazZ5YnBDQk9nZUFBQUFBS2E1bHZFZW1mUDF1U1huVm1KUW9tZXMxSjR6VzRwZjBvN2tIRGhIZ1JFUlV2YlcvbExMZWcrcG85VE94YkZ2djVkVDhRazZBZ0FBQU9BR1Y3SmV0ZXgyLy9NdjZTZ1hyR1E4YXRCQWlYbHF2QVNHaCt0T0FIa1JWcVd5ZllSYTVNVXRkYy9aWloxS2tmM1B2cUFqQUFBQUFHNXdKVUUvc1hpSnBPL2FvNk96Q0FpUTBqZjNrK2loOTdPOEZuQ0l1dEZWN2RVWHoya20vY1NDUlpKKzVLaU9BQUFBQUpqbXloNTBWYm45NkdkZjZDaG5Lb0dvK2ZIN0VoZ1dxbnZ5eWZyeHN0TFRKZjNFQ2NrNGZseXlVdk5lM1Jwd2l6cXRJTGhZTVh1WnVsMFEwYUdiVmFlMjc1RE5WMTRqV1NrcHVpZG5sWjZaSXFXdjZhSWpBQUFBQUNZWlQ5QlZjcnl1ZVJ2SlBIeEU5K1FnT0ZpcXozcFBpalpwckR2eUxubmRlamsyZjZFay9icFlVclpzbFl6RWcvb1J3SGNFeDFTUmlOcTFwR2lIZGxLc1kzc0pxMWhSUDVKMysxNTZWZlpQbXFxam5CVzlyS05VZi9WRkhRRUFBQUF3eVhpQ25yeG1yV3pwMmwxSE9TdmE4UktwL3ZyTGVaNHR6RHlWSWtlKy9VNFNYM3RUVXRadDBMMkFud2dNbEtLZDJrdVpXL3RMc1JiTjgvdytTVDk2VkRaMXZGSXlEaDNXUGRrTEtsNWM2djd4c3dTR2hla2VBQUFBQUtZWTM0T2UvTmRLM1RxNzBuMTY1UzNweU1xUzQ0dC9sN2pPM1dUWGtPRWs1L0JQbVpseVl0NEMyWDdETGJKdDRDQkp5V09WOWVBU0phVEV0VjExbEROMVZGdnF6bDA2QWdBQUFHQ1M4UVQ5NVByY0pjc0JrUkZTN0pLMk9zbzlWU0YrOThUSnN1T21BWks2ZFp2dUJmeVlTdFIvV0NpYnUxNG5oK2Q4WThmbnFrU1hxM1FyWjFscGFaTEMrd29BQUFCd2hka0VQU3RMMHJadTEwSE93aHZVbDhEUWN5c01wNHErYmIvakhqbjQ2cHYyWG5lZ01NazhkbHgyRGg0bWU2WStZNy9YemtWRXpSb1NXTFNvam5LV3NpZVhKekFBQUFBQXlCZWpDYnJhM3A2Um5LeWpuS216bXMrRlNzNjMzVHBRa2hiOXBIdUFRaWdqUXhKZmVNVmVSWEl1U1hwQVJJUUVsNDNTVWM3U2Q1T2dBd0FBQUc0d080T2VtU21adVR6T0thaENlZDA2TzdYc05uN1lDRG01YklYdUFRbzN0WXJrd0ZzemRIUjI2dWkyZ05EY0ZYN0wyTGRmdHdBQUFBQ1laSHdQdWduN1gzdFRUbnozZzQ0QUtQc21UWk9rRlgvcENBQUFBSUN2TVhyTW10b1h2cWxMcktSdWpOTTkyWXNhTkZDaWh3M1ZVZlpPYm9xVExWMnVzMmZSY3kwdzBONXZHMXdtU2dLalN1bE93S09zZDJUR3psMlNjZUtFWko1STBwMjVFMXFyaHRUKzhsTUpqSWpRUFdlV2xaRWhjWjFqSldYakp0MlR2WkxkdWtxVmFaTjFCQUFBQU1BVTMwclFyWC9xdHR2dWtCTUxjN252M0Q0M3VvT1VIWEN6aE5lcks4SEZpdWtIQUkvTHpKUzB3NGZseE85L3lJSG5YN0lTYWVzOWxKdTNha0NBbEI4eFRNcmRmcXZ1T0RNU2RBQUFBTUI3ZkdxSmU5S3ExYmxPemtOaXFrajFqMlpLOVZkZmtLTE5tNUdjdzdjRUJrcElWSlNVNm55VjFKNHpXeW8rT1ZvQ3dzUDFnem13a3ZqRWwxK1RqS1J6bTNrSEFBQUFVUEI4SjBHM0VvOERyNzZoZzV5Rm45OUFhczcrU0lwZTFGVDNBTDVMRlhRcmMzMGYrNFpUVU1rU3VqZDdHWWNPeXhGMVBqb0FBQUFBbitJekNYcjZrYU9TOU10dk9zcGVjTVh5VXUzMWx5V2tkR25kQS9pSElvM09sOHJQVGJWZTVFRzZKM3RIUHZ0Q3R3QUFBQUQ0Q3A5SjBKTldycExNWThkMWxJM0FRS2s0ZHJTRWxDdXJPd0QvVXJ6TnhWTHFoajQ2eWw3eW55c2s0L2dKSFFFQUFBRHdCYjZUb1AvMnUyNWxMN3hlSFNuUjRSSWRBZjZwN0lCYkpTQTRXRWZaeU1pUXBKVXJkUUFBQUFEQUYvaE1ncDY4YnAxdVphOUVsNnZ0L2JxQVB3dXJYRWtpV2pYWFVmWk9yVjZyV3dBQUFBQjhnVThrNkZrWm1aSzJhYk9Pc2xmc3NrNjZCZmkzWW0zYjZGYjJVdmZ2MXkwQUFBQUF2c0JIRXZSME8way9tN0FLRlhRTDhHK2gxYXZwVnZZeVQzRFVHZ0FBQU9CTGZHYUplNjRFNkQ4QmY4ZHJIUUFBQVBBNy9wV2dBd0FBQUFEZ28walFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUENNaXk2TGJqc3RMVFpWT1hXRW5kR0tkN3NoYzFhS0JFRHh1cW8zL0tURTJWRGEzYVM4YWhRN3JuekJxc1hTNkJrWkU2TWljMVBrRk9yZCtnSS9pejBKZ1lDYTlYUjBmZWNXVCtBa2tZTUVoSFoxYWlSNnpFVEo2Z28zL0t5c2lRdU02eGtySnhrKzdKWHNsdVhhWEt0TWs2QWdBQUFHQUtDWG9lSEp6NXZ1eCtiS3lPNE0raSt2ZVQ2TWNmMVpGM2tLQURBQUFBL29jbDdnQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCd1JrV1hUYmNWbnA2YktwUzZ5a2JvelRQZG1MR2pSUW9vY04xZEUvWmFhbXlvWlc3U1hqMENIZGMyWU4xaTZYd01oSUhabHpjdlVhT2Y3anp6cnl2dVEvVjhqeFJUL3B5Rm5sQjk4ckV1Uy85M2tpR3AwdnhkcTEwWkYzSEptL1FCSUdETkxSbVpYb0VTc3hreWZvNkoreU1qSWtybk9zcEd6Y3BIdXlWN0piVjZreWJiS09BQUFBQUpoQ2dsNElKTDQ1US9ZOGNlWkVMYjhheHEyUmdPQmdIY0V0L3B5Z1o2V2xTVmFtc2N0UzRSTWdFaGdTWXYxcE5RQUEvME9OTThXRmo1MkE0Q0FKQ0FyU1VjRno5Zk9XenlJZzEwalFDd0VTZFAvanp3bjZ0cUhENU5TS2xUcENmZ1dWS0M2MVBuNWZBa05EZFE4QTRIUngzZnRJK2xuR21FNG9QL3dCS1gzVkZUb3FXQmxKU2JMbHhsc2s0L0FSM1dOV1pJdG1FalArQ1FrSVpIY3RjRFlrNklVQUNici84ZWNFUGE3ZnpYSnk4UklkSWI5Q2ExU1h1dk8rMFJFQTROL1d0V3duNlFjTzZNaWM2RW5qcFV6M1dCMFZvTXhNMlQ1MG1Cejd5cDNQaHVBSzVhWDI3SThscEZ3NTNRTWdKOXpHQWdBL0ZsYXJwbTRCQUNDUytORXMxNUx6Z0xBd3FUSjFFc2s1Y0E1STBBSEFqNFdXTDY5YkFJRENMbm5kZXRrejdpa2RtVmR1eUwxU3JFVnpIUUhJRFJKMEFQQmpZWTBhNmhZQW9ERExPSDVjNGdjL0tGa25UK29lczRwZGNabVV1KzBXSFFISUxSSjBBUEJqNFRWcjZCWUFvTkRLeXBMZGs1NlcxQzFiZFlkWklaV2lwY3I0c1JTRkEvS0FkdzBBK0t1Z0lBbXJVRUVIQUlEQzZ2QTMzOHJoRHo3V2tWbUJrUkVTODhJekVseXlwTzRCY0M1STBBSEFUd1dWS2lXQnhZcnFDQUJRR0tYRXg4dXVrYVB0V1hUamdvS2t3cWhIcE1qNWJLOEM4b29FSFFEOFZGRFJJaElZRnFZakFEQXJNek5UVHA0OEtZY09IWkt0MjdiSjBxVkxKVFUxVlQrS2dwQjVLa1YyREg1UU1vOGYxejFtcWFOWnkvVHNyaU1BZVVHQ0RnQitLcVJ5SlFrSUN0SVJBT1NOU3J6VDB0SWtPVGxaRWhNVFpmUG16Yko0OFdKNTcvMzNaZHo0OFRKNHlCQzVOalpXYXRldEsrZlZxeWQxcks5NkRScEk2N1p0NWJoTGlTSE9RTzA3ZjJxeW5GcTVXbmVZRmQ2b29WUWVPMW9rSUVEM0FNZ0xFblFBOEZPaFZXTjBDd0J5cGhMd0F3Y095TnExYTJYMjdObnk0a3N2eVdPalIwdS9tMjZTaTl1MWs2Yk5tdGxKZDZXWUdLblhzS0cwNjlCQmJyNzFWbmw4N0ZoNXdmcHZ2NWs3VitMajQyWHYzcjF5NU9oUk82bEh3VHE2NkNjNS9QNUhPaklyc0doUmlaaytSUUxEdzNVUGdMd2lRUWNBUHhWS2dUZ0FPVGgyN0poY2V2bmxVcmQrZllrc1ZreWlxMVNSSmsyYlNxKytmZVgrSVVOa3dsTlB5VWNmZnl6TGxpMlQ5UnMyeU80OWUwaThmVVRxN2oyeWMvZ0l5VXBQMXowR0JRUkk5Sk9QUzNqVnFyb0RRSDZRb0FPQW53cS9vSkZ1QWNEL1V2dkRGLy8rdTJ6WjZzN1JXM0JIcHZWN2pYL29FY2s0ZEZqM0dHUWw1MUVEYnBiU1hUdnJEZ0Q1UllJT0FINHF2RW9WM1FJQUZCYjdYMzFka24vN1hVZG1SVjdVVkNvT0hhd2pBRTRnUVFjQVB4UVFFU0VoWmNycUNBQlFHQnhmc2xUMlAvZVNqc3dLcmxoQnFqNDNWUUpEUTNVUEFDZVFvQU9BSHdvdVgwNENRb0oxQkFEd2QrbEhqa2pDc0llc2h2bDk1d0doSVZKNThnUUpLY3VOWU1CcEpPZ0E0SWRDU3BhVWdFQXU4UUJRR0toaWNQSERINUgwWFh0MGoxbGw3cnBEaXJkcXFTTUFUbUwwQmdCK0tLUkdOYzZpQllCQzRzRGI3OGlKK1F0MVpGYlI5dTJrNHIyRGRBVEFhU1RvQUR3bHBGeFpDYTFTMmJXdmtJb1YzVWxrcmU4UlVpbjZqUDhHRTE4UjlldnJid3dBOEdkSksxZkp2cW5QNk1pc0VPdnpKV2JLUkc0QUF3WUZaRmwwMjNGcXVjMm1MckdTdWpGTzkyUXZhdEJBaVI0MlZFZi9wSTZMMk5DcXZXUWNPcVI3enF6QjJ1VVNHQm1wSS93dDhjMFpzdWVKQ1RweVZzTzROUklRekQ1WHR4Mlp2MEFTQnVSODk3cEVqMWlKbVh6bTMzdFdSb2JFZFk2VmxJMmJkRS8yU25icktsV21UZGFSL3prVkh5OXhsM1UyZmxac1lKRWlVbWZCZHhKU0prcjNBRURCU2t4TWxLbzFhdGpIclpteWQ5Y3VpWXJ5OW5WdlhjdDJrbjdnZ0k3TWlaNDBYc3AwajlXUk05S1BIWk80YmowbGJVZTg3akVuTUNKQ3FuL3dqaFE1djZIdUFXQUNNK2dBQUFDQUQ5cjF4SGhYa25NSkRKVHlqejVFY2c2NGdBUWRBQUFBOERFSFA1MHRSei83UWtkbWxlamFXY3IwNnFrakFDYVJvQU1BQUFBKzVHVGNadGt6WnB5T3pBcXJjNTVVR1RlR2swRUFsL0JPZzA5UjlRaTI5cnRaMWwzUXd2aFgzTFU5Sk9ORWt2N09BQUFBQlMvanhBbUp2LzhCeVV3eVAwWUpMRlpNWXA2Zlp1OC9CK0FPRW5UNGpxd3MyVGY5ZVVuNjlYZkpPSExVNkZkbThrbXBPSHFrQkJVdG9yODVBS0N3eU16TWxQVDA5RE4rWldSa1dCOUh4dXJyQWpuS3NsNmJ1eWRNeWxXUjEzd0xDcFRvTWFNa29rWU4zVkY0cWZkOFR0Y0Y5UmpnRktxNEZ3TCtVc1g5Mk0rL3lJNWI3eFRyU3FoN3pDbDcvOTFTWWZDOU92SWVxcmc3aHlydXZpOGxKVVhXcmwwcmY2MWNLZnYzNzVjRGlZbjZFWkd3MEZBcFdiS2tsQzFiVm1yWHJpMzE2dGIxZkVWcHVDY3BLVW0yYnQwcXExYXZsajE3OXNpMjdkdGw0OGFOY3VyVUtUbDU4dVFaQjkwUkVSRVNFaElpcFVxVmtnYjE2MHVsU3BXa2F0V3FkcnR5NWNvUzdFTW5tMURGL1Q5OHFZcjdrZSsrbC9oN2hxaTdTTHJIbk5MOSswbmxVWThVdWlQVjB0TFNKTjRhR3l4ZnNVSVNFaElrTGk1T05sbGY2cnFRbkp5cy82di9wOTd6WVdGaFVyeDRjV25Zb0lGOUhhaFdyWm8wYnRUSXZqNzQwalVCM2tDQ1hnajRRNEtldW51UGJMWmVTeG1IaitnZWN5SmJ0NVFhTTkvMDlGNHJFblRua0tEN3BxTkhqOHJjYjcrVkR6NzhVSDc4NlNjNzBjcXRPdWVkSjQ4LzlwajA2TkZEOTZBd1VNbjJ0bTNiWlBIdnY4dWlIMytVdi83NlMxYXVXcVVmZFVaNGVMZzBiOVpNTHJqZ0FtblZzcVcwYk5IQ0hxQjdGUW42Zi9oS2dwNlNzRlBpcnVrdW1jZU82UjV6SWk1c0lqVm52aTJCNFdHNngzK3AxNys2d2Z2TEw3L0kvQVVMNVBjbFMrU1lRODl4cEpXWHRHM1RSdHBmY29tMHNLNEh6UzY2eUw1T0FEa2hRUzhFZkQxQnoweEprYTNYOTVlVHkvL1NQZVlFbFMwanRiK2VMU0ZseStvZWJ5SkJkdzRKZXU3OGJpVTE2OWF2MTVFekxySUdLbzNPUDE5SHVYUEFHa1MvL09xck11WHBwODg0azVGYnN6NzZTTHBkZTYyT3p0MnNUejZSNDhlUDY4aDVWMTV4aFVSSFIrdklHWjk5OXBrY09YcFVSODY3eEJxQTF2VFlVbGkxSEgzVHBrM3kyZXpaOHNtbm44cjZEUnZzUHJjRUJRWFpONFI2OWV3cFYxMTVwVFJvME1DZWFUTnAxYXBWc3V6UFAzV1VzeE1uVHNoREkwYllTM1JOZVhyeVpDbGF0S2lPOHE1OCtmTFMrZXFyZGVRc1gwalFzOUxTWkhPL20rWGtzdVc2eDV6Z2NtV2wxdXhaRWxxaHZPN3hQK28xcjI3UWZXaDlGcno3M250eThPQkI0MXRYQWdJQ3BGaXhZdEtqZTNmcGQvMzEwcng1YytQWGd6TlJOeXMvLytJTE9YTEU3S1JYNmRLbDgvVTVtMWZxNTN0bjVzd3pyb0J5aXJySjBydFhML3NhYndJSmVpSGcwd202OWZMYzg4enprdmpzQzFaYjl4a1NZRjBrcTc3OW1oUnIyVnozZUJjSnVuTkkwSFBuL2lGRDVNV1hYdEtSTSs2NzV4NTVlc29VSGVWTURhWm16Wm9sUXg5OFVCS3RnVlIrcU9XR2YvN3hoOVN2WDEvM25CdjFzZG1vU1JQWnNIR2o3bkhldDk5OEk1MDZkdFNSTTVvMmEyWXY1VGJsbmJmZmxyNTkrdWlvWUtrVkZkOS8vNzFNc2w1ZmFoQ3VscXdXTkRXUVUwdGZCOXg2cS8wOHhjVEUyQU4ycDAyZE5zMU91djJOU21vK3NCSXBFenlmb0Z2WG5GMFRKc3ZCTjk3U0hlYW9NVjNWMTErUzRtM2I2Qjcvb203c2ZqOXZuancxYVpLcytPc3ZWMi9ZblU2OTk2dFhxeWFENzcvZlR2UlVNdXVtMndjT2xMZmZlVWRIWnFpYkVic1RFbHhmTWFDMkxkVS8vM3lqdjlzTzdkdkxkM1BuR3JtR0t4U0pnNmNkKzIyeEhIemhGZVBKdWZVT2t6S0RCdnBFY2c3NGk0U2RPM1VyWjRjUEg1YnJiN2hCYnI3dHRud241NHFhelZPSkV2eVBXcXI2M3Z2djJ6Y2pldlh0YTg4a2V5RTVWOVJnY2NlT0hUSnE5R2o3QnMrMXNiR3lkTm15QWtzUWZFM3JWcTEwcS9CUk5YZ096akNiVFAydHpGMjMrMlZ5cm03eWZ2bmxsOUtrYVZQcDJidTNmVzBveVBlZXV0RzdkZHMydVcvd1lLblhzS0U4UFhWcXZsYUZuYXRldlhycGxqbHFsWm1xRCtPMkpVdVdHUC9kOXJGZVE2YVNjNFVFSFo2VmRpQlJkajN3c1BHWlRTV3lXVk1wZjlkQUhRRnd3eHJyZy90c2k3alVudUcyN2R2TDdDKytjR3k1V3BreVpldzcrL0FmNm5YMDg4OC9TNXQyN2VUbVcyK1ZMVnUzNmtlOEtmbmtTYnVHZ3ZyM1huSFZWZllXRXVTc1JpR3RKSjY2Yjc4a0RIL0V5akROSjVORjJsNHNGZTY5VzBmK1EyM1B1cnBMRitsdUphWHFNOFZyRGgwNkpBOC84b2g5WS9HTEw3ODg2K2VpRXk2eHJqMnEwS1ZwYzcvN1RyZmNNMy9oUXQweVE2MEl1QzQyZjhVZXo0WUVIWjZrOWxvbFBQaVFwRnNmVEthcHZWWXh6MCtYZ0pBUTNRUEFEY2VPSHJVclpXZEhWYzd0ZU9tbGRsVnRKMTE0d1FWRzczekRYV29mOWRBSEhwRExycnpTWHJMcVM5Uk5KMVhrVU4yRTZ0NnpwMnpjNU1MUldUNUk3ZE5WVmZJTEc3WEZNK0hoUnlUandQK2ZUR0ZLY01VS0VqTjVvZ1FZMmxOYkVOU0ttc2xQUHkwdFdyV1NoWXNXNlY3djJyeGxpejI3MysrbW0reDZLeWFGaG9aS2Q4Tkpwcko0OFdMZGNvZTZwcW9pb0NhcG14dnFkQmlUU05EaFBWbFpzdStsVnlYcHAxOTFoemtxS2E4MGFaeUVsQzJqZXdDNDVkang0L2J5OVRQWnZYdTNYRzRsWER0MzdkSTl6aW1NQTMxL3BXYkQybmZzS00rLytLTFBMeFgvOHF1djVLTG16V1hzRTAvWU54M3cvMEtDZzZWQ2hRbzZLanoydi9HMk8yT2hpQWlwK3Z4MHZ4b0xxV01UdTE1empUd3ljcVI5UEpxdlVMUG5IOCthWmMrbS83RjBxZTQxNDdycnJqTitzMW90Y1RkNVNzUy9xYU15MVZZaWsyN3MxMCszekNGQmgrY2MvMzJKSkQ3L3NvN01paHB3aXhTL3BKMk9BTGhKelo2cnMyYi9UUlg0NnRXbmo1SGtYRkhWeHVIN2xscURWN1ZFM09tajBncVNTaVNlR0RkT1dsNThzYXhZc1VMM29tN2R1b1h1YUtyamZ5eVZBOU9mMDVGQmdZRlNZZmhRS2RLa3NlN3dmU3RYcnJTdkRRdDhZTlk4TzN2MjdyVnZVczk4OTExalM5NVZYUWQxREp4SnUzYnZOcDR3bjI3ZXZIbTZaVVpFUklSOXlvcHBKT2p3bExUOSt5WGgvZ2Z0SmU2bVJUUy9TQ29NdlU5SEFBcUN1dHQ5T3JVOGJjZ0REOGlTUC83UVBjNEtDdzB0dEh0Wi9ZazZyL2lLcTYrVy9TNVUzaTRJYWx0SDMzNzlYSjE1OHJLYU5XdnFWdUdRZnV5NDdCeitpQ3MxZUlwZmVabVU2WGU5am55ZldsTGR2bE1uaVU5STBEMitTOTJzSG5qbm5USnQrblFqU1hxUklrV2syelhYNk1pY2IxM2FoNjZlbzNrLy9LQWpNOVRwS2lWS2xOQ1JPU1RvOEF6MVFhUUtvYml4MXlvb3FyVEVUSjFrL0F4M0FEbjc3Vi83MDlUeE4yckd3SlN5WmN0S0tjTjd4MkRXK3ZYcjdSVVdKcytoOTRMSlR6MWw3eE9GU0xPTEx0SXQvNmVPUVUwWU9VclNFbkozeWtWK2hOYXVLVlVtanBPQVFQOUlCMzc4OFVlNXFrc1h2OW9pb3FyUGp4ZzVVcDU1OWxuZDR5eFZqZHkweFM0VndUeVZraUovR0xxNS83Y0J0OTJtVzJhUm9NTXo5ci8rcGlUOStJdU96TEgzblU4ZUw2R1ZvblVQZ0lKeStoTDNvMGVQMmtmT3FBR0pLZVhMbDdjTFRzRTNxV3JIc1QxNnlJRkU4emR5QzlLZEF3ZEtWeXZSd0g4MGJkcFV0L3hmNHJ2dnkvRnZ6TTg0QmhhSmxKanBVeVNvU0JIZDQ5dlVxcXR1M2J2YnM4NytScTBzRy9iUVEvTGVlKy9wSHVlMGJObFNpaGN2cmlNejFMRm5LVmJ5Yk5ybXVEalp1MitmanB5bnpxcHYxN2F0anN3aVFZY25uUGhqcWV5ZlBGMUhacFVlY0xPVTZOQmVSd0FLa3BvTi9kc2JiNzVwL0FpY3BoZGVTQVYzSDZXV0w2cUNUMXUyYk5FOS9ra1ZNWnd3ZnJ5T29QYWVWNnRhVlVmK0xYbk5XdGs3ZWFxT0RBb01rSXBqUmtsazNicTZ3N2R0Mzc1ZHV2Zm80ZmZGRmUrOCsyN0h0MytwYXVSWFgzV1Zqc3pZdDMrLzdMZStUUHRtN2x6ZE1rTXRiM2ZyaUZZU2RCUzQ5RU9ISkdISWNIV0xVUGVZRTltaW1WUWN3cjV6d0N2VUhtSzFWRGt4TVZIR2pCMnJlODFSeGFiZ214WXRXaVJ2elppaEkvK2s5b1MrL2VhYlVyUm9VZDJEa2lWS1NGUlVsSTc4Vi9xeFk3Smo4SU9TZGRKd3hmR0FBQ25kNzNxSjZuYXQ3dkJ0YXNhOGQ5KytkaExvNzFRUnlSdjY5Yk5YRWpuSmRGVnlOWHYrNysxc1RsT3JERXp1ZFZjMzl1KzQvWFlkbVVlQ2pnSmxuM2MrYklTazc5NmplOHdKS2xWS3FreWZ6SG5uZ0llbzVlejc5dTJUOTk1L1g1SnpPQlBkS2VyOFV2Z2U5VG9aTlhxMFBRanpWMm9BT09LaGg2UkpreWE2QjByNUNoWHN5c2wrTFN0TGRqMDVRZEsyL2JOb3Bnbmg5ZXRKOUVNUDJvbTZQeGo3NUpPeTNNVVRENEtDZ3V4aW8ycGxoL3BTVzZaQ3JIR2xXeXV6ZHNUSHk1MkRCamw2TFd6ZXJKbVVLV1AyaUwxdnYvMVd0OHc0ZXV5WXJEdHRSWjdUb2l0V2xHYlc4K1FXRW5RVXFQMXZ6WkFUQzM3VWtVSFdoVE42L0JnSkxZVG5xQUplcHFwVXI5K3dRVjU2MmZ6Umltb2dWYTFhTlIzQmw2aXE3YVlxKzN1Rk92Sm82SkFoT3NMZkdqZHFwRnYrNjlDWGMrVG9aMS9veUp5Z01sRlM5YVhuSk5CUGpxejcrZWVmWmVxMGFUb3lSeFZydk9MeXkrV0Y1NTZUWDMvNlNiWnQyU0o3ZCsyeXYvYnMzQ2tiMXE2VmIrYk1zVyt3MWE5WFQvKy96UG5LK2w1T3poYXJxdVFkREI4LytyTjFEYy9JeU5DUjg5VEpGMDZ2TERoZCsvYnRqUjlKZHpvU2RCU1lFMzhza3dOVG50R1JRVlp5WHZxMi9sTHl5c3QxQndBdmVmT3R0MlRMMXEwNk1xZHExYXF1ZnNEQ0dXcnYrYlBQUDY4ajg2cFVxU0kzMzNTVFBEMTVzc3l6QnNFYjE2MlRyWEZ4c20vM2J0bTBmcjJzVzcxYTVuLy92VHozekRNeWNzUUl1YVpyVjZsWHQ2NEU1K05Va0tqU3BlV2RHVFBzbVRqOFUrM2F0WFhMUDUzYXZrTjJqeDVyejZLYkZCQVNMSlVuUENGaGZsSWdWKzAzSHpCd29JN01VTFBpdlhyMnROL3pjNzc4VWdiZWZydGRzRkNkQnFLMm82Z3Z0U2M1SmlaR0x1M1VTY2FPR1NQTGx5MlQyWjkrS3VjM2JLai9GdWVwRlVYM0R4N3MySjU3OVhQZWNMM1pvL1pVWWMrOWUvZnF5SG5mV2Rka2s5eGMzcTZRb0tOQXBDVWVsSVQ3SDNEbnZQTUxtMGpGQjVtVkFMeHF6dGRmNjVaWmxhS2o4NVZFb1dBY1BIaFFmdnI1WngyWlU3MTZkWGx2NWt3N0lYL3QxVmZsdm52dmxmYVhYR0tmbTYrU2RsWEJWLzAzS21GczE2NmQzSG5ISGZMNDZOSHk2YXhac3VMUFAyVlhmTHg4L09HSDlrQzNTdVhLK20vTm5TbVRKa21NOVQzd3YveDVXMHBHY3JMRVcyT2h6T1BtaTV0RjNYYUxsT2pZUVVlK2I5S1VLYkxWWUZIUjRsYmlQWFBHREhuM25YZnNtN3U1cFpiQWQrbmNXUmIvK3F1ZDBKdXlmY2NPZWY2RkYzU1VmNWRZMXpwVk1NNlVaT3UxL3FkMW5UUkIzY1Q5NGd0eksxRFU3LzhpbDQ5NkpFR0g2N0l5TTJYWDZMR1N2dGZjVVFoL1U4dTVZcDZkS29FY3F3UVVlbTUvd01JWnExZXZ0by9nTStuaTFxM2xqOFdMN2RteXZNeGlxMEc1U3VCanUzV3ppN3l0VzdOR2ZscTRVSHIyNkhIV0k0eHU2TnRYYnJqaEJoM2xuN3B4c05NYXZPZm1hOVdLRmNiUFdsLzExMTluL042NS9WTDdZLzJSR2d2dGZtcUtuRnF6VnZlWVU2Uk5hNms0OUg0ZCtUNjFEOXZKNVBUZjFFcXJEOTkvWDNyMzZtWFBMdWVGMmxMMTdQVHBjdis5OStiNTd6aWJxZGJmNzlTMVVhMEd1TFJqUngyWk1YL0JBdDF5bHFvUWIvSjBqOHN2dmRUMTFVMGs2SEJkNHRzelhUbmpVNEtESkhyQ0V4SWFYVkYzQUNqTWF0ZXFwVnZ3SmFabnoxVmkvY0Y3N3prNmU2U0tSN1ZxMVVyZWYvZGRlM25zeFBIajdSVWMveDZvcTVuMnA1OSsydEVCdkVvdTFIbi91ZmxTUzNWTksyZDlqek45Nzl4K3Fac2YvdWpvRHd2azhBY2Y2OGljNEhMbEpHYnlSQW53bytkeGl2V2VVYWQvbURKNjFDaTU3TExMZEpSMzZyVTdmdHc0WTZ0QURoOCtMSysrOXBxTzhrZGRnOVFOU3BOKytmVlgzWExXWHl0WEdpMHlhN3JLL1ptUW9NTlZTU3RYeWI0cDVndDZLS1g2OXBhU25meG5PUmVBL0ZHenBQQTlKaXZ6S3BkYkEvR0tGYzNkeUZWSjVnTkRoOXF6Nm1yZnV0cXZxcWhLMEcrKy9ycTkveHlGUzhxdVhiSnp4Q2dSZzBXemxJQ3dNSWw1ZnFxRWxETi9JOFl0TzNmdWxMY05IcmZZb25semUzdUxVOVFLbFJlZmYxNGlEWjFFOEpwMURWRjcwcDJnYmtvVU1WaW5aYzNhdGZaTkJhY3RNRFF6cjZpdFI4MnQxNFRiU05EaG12UkRoeVhoM3FIbXovaTBoRGVvSjlHUFBxeHVDZW9lQUlXWldtNFljdzc3Q09FZGE5ZXQweTB6cXJ0VTJWL05iTjh4Y0tDOXJIelV5SkV5ZVBCZ2U5OG5DcGRNZmJ4czVwRWp1c2Vjd0tKRkpNelBUcTZZK2U2Nzlubmdwb3daUGRyeFdpV3Fic1d0dDl5aUkyZHQyNzVkRmk1Y3FLUDhLVnEwcUhUcDBrVkh6bE5IdzZscTdrNVMrODlORm9qcjJyVnJnYXppSVVHSEs3TFMweVhob1Vja0xXR243akZIZlNCVmVYNmFCQnJlVndlZ1lLZ2pZYTYrOGtvWi8rU1Q5cEUzQ2RZQTVlamh3M0xNK2pwNjZKQnMzN0pGZnJNR0FXci8zMTEzM0dHZks5M200b3Z0R1V2NG5zVEVSTjB5STgyRllxV25VM3M5SHhzMVNwNFlNOGJZM2xSNDEvNlhYNVBrSlV0MVpGYkd3VU95OC9FbjdmM3UvdURreVpQeW5NRzk1NjFhdHBTT2h2WmgzM1AzM2NiMk1iL2w0SW9DVlRmRHBDVkxsdWlXTS9iczJTTWJOMjNTa2JPQ0FnUGwrcjU5ZGVRdUVuUzRJdkhEaitYRS9FVTZNaWNnT0VncVRaNGc0WngxRFBpZHFLZ29lZnl4eCt3cTIxOTgvcmtNZS9CQmUrbFpoUW9WN09XREVkYVhtcVdzVkttU05Mdm9Jcm5yemp2bDJXZWVzWXQvZlRGN05za1F6aWh1ODJaN0ZzWnR2QjRMcCtBeVVicmxqdU56djVORG4zK3BJOS8ydy96NWN1REFBUjA1NzVhYmJ6YjJ2cXhtalVzYm5YKytqcHlsNm5Ra0pTWHBLSC9hdFcxcmY1YWFvdjZ0VGw1dmY3Y1NmcWVXK1A5YjVjcVZwZW1GRitySVhTVG9NQzU1elZyWk4yNlNXb2VpZTh3cHFmYWRYNUgvd2g0QXZFTU5sOVN4TlN1V0xaT1JqenhpSityblFnMjQxQkozK0NiVGlleUNoUXRsbThIam1vRFRSZlhzTHBITm11cklCZGJZYTgrVEV5VE5ZR0xybGxtelp1bVc4OVFLcTY0R2wzZXJaZExYeGNicXlGbjc5dTJUcFV1ZFdaVlJxbFFwdTJxNUtXb2ZlbXBxcW83eWI5RWljNU4vM2J0M0w3QWlsU1RvTUNyanhBbEpHRHBjc2d6dUYvcGJXUDI2RXYzSWNEV2EwejBBZkozNmNMei8vdnRsMWtjZkdTM2tCZTh5ZmN5V3FnWjlkZGV1a3BDUW9Ic0Fjd0tDZzZYU0U0OUxnSXZITm1VZVBTWTdSNDF4WmFMRWxKU1VGSm56elRjNmNsNHo2enBUcGt3WkhabHhtY0hFOStOUFB0R3QvT3ZWcTVkdU9lK0VsUmNzWDc1Y1IvbW5ickNhb0c3WTlML3BKaDI1andRZHhtUmxaTWpPa2FNbE5jN2MyWVIvQ3l4V1ZHSmVtQzZCNGVHNkI0QS9HSFRublRKcDRrVEhpL2JBZDFSem9iaWZPa08zV2N1VzhzR0hIem82dXdPY1NVVHRXbEwydnJ0MTVJN2o4K2JMUVI5ZTZ2N3JiNzhaUFZxdGsrRXp3Slc2ZGV2cWx2TlU4VFZWaE0wSjZsZzRWU3ZERkxWVndRbTdkdTgydHYrOFpxMWFjbDd0MmpweUh3azZ6TWpLa3NUM1A1UmpYNW03Mi9sZmdRRlNjZXhqN0RzSC9Fem5xNjZTeVpNbUdWL2lERzlyMUtpUmJwbDE4T0JCNlgvTExkSzBlWE9aOWNrbmN2VG9VZjBJNEx4eXQvYVhzTHAxZE9TT3ZlTW1TdXFldlRyeUxWOS8vYlZ1T1U5OXhuUm8zMTVINW9TSGg4djVEUnZxeUZtN3JXVDEwS0ZET3NvZmRUUmtHNFBIa3FyejBKM1loejUzN2x6ZGNsNzMyTmdDblJnZ1FZY1J5ZXMzeUw2SlU5elpkOTZ6dTVTK3RxdU9BUGlEMHFWTHl5c3Z2MXhnKzcvZ0hlcGNZcmR1MHFoQjQ0WU5HK1Q2ZnYya2JvTUdjdS85OTh1eVpjdnM1YldBazlTS3Y4cVR4a3VBaTZkTFpCdytJZ21QakxKWE9Qb1NWUVRzeDU5KzBwSHoxUEZpNmlnMDA5UjFyR0tGQ2pweTFyRmp4K3lDbDA3cDM3Ky9iamx2MDZaTmpxeFVNcmE4UFN4TWJyNzVaaDBWREJKME9DN2orSEZKdUdld1pDV2YxRDNtaE5hcUlaVkdqMlRmT2VCSDFDRG15YkZqN2J2NFFJMGExblUrT2xwSDdsSEh1NzM4eWl2U3FrMGJhZFNraVR3d2JKaGRpTW50WTluZ3Y0clVyeWVsKy9mVGtUdVNmdmxORHMzK1FrZStRUzF0WDc5K3ZZNmNwMDcvS0ZteXBJN01LbUh3KzZ4WnMwYTM4cS85SlpkSThlTEZkZVNzbmJ0MnlmYnQyM1dVTitxbTZkSmx5M1RrckFiMTZ4ZklaODdwU05EaHJLd3MyZlg0azVLNmJZZnVNRWZ0TzYvNjh2TVNhUEE0Q0FEdVUvdjBidXpuN3FBVjNxVUd6N0hkdXVtb1lHemR0azJlZmU0NWFkMjJyZFNvVlV2NjNYU1RmRHhybGwwOUdjZ3pOYU02K0Y0SnFScWpPMXlRbVdsWGRVL1pibjZjNWhTVnpLVWF2REdtOWhxSHVyU1NvVnpac3JybHZOOFdMOWF0L0ZPbnBiUnMwVUpIenB2NzdiZTZsVGZ4Q1FuNVR2S3owKzNhYXd0ODlSNEpPaHgxY05hbmNuUzJDMFZJckRkT3hkRWpKYnhtRGQwQndCK28yZk9IaHcrMzkrb0JmN3ZuN3JzOWMxVGVYaXNwLytqamorV0dHMitVS3RXcVNZdFdyV1RNMkxHeTZNY2ZqUmF4Z24reWw3cFBlTUxWbFlDWngwOUl3cU9qZldhcHV5cUFabExWR1BkdWtKUXJWMDYzbkxkbnp4N2R5ci9Bd0VDNXllQ044dnh1V2ZqaGh4OTB5MW1oSVNGR2wvZm5GZ2s2SEhOeTR5YlpNL3BKVi9hZGw0aTlSa3BmVjdBektnQ2NWN2xTSmZ2dU5YQzY2dFdyUzQvdTNYWGtIV3JQK3ZJVksrVEo4ZVBsOGl1dmxFcldRTDlYbno3eXNaWEFxOEd5RTRXUTRQK0t0V2d1cGE3dnJTTjNKQzllSWdkbXZxY2piMU9uTEpoVXFuUnAzZkp0Y1hGeHV1V01LNjY0d3RqS2dwVXJWK2E1dG9lNnJuNWo2TWk5cGsyYkdxc1RjQzVJME9HSWpLUWtpYi83Zm5mT082OTdubFIrWWpUN3pnRS8xS2QzYjN0Sk0zQTZ0Ykppek9qUlVxeFlNZDNqUFdyUWVQTGtTWm45K2VkeXcwMDNTZjJHRGVXS3E2NlN6ejc3akpsMW5GV0Z3ZmRLa09GenVQOXQvOVJuNUpRUExIVlhOOEZNZW52R0RLbGVxNVlyWDA5UG02YS9xL01PSGpva3B4d2NoNWNvVVVMYXRtbWpJMmVwbFVqcW1MUzhVTmZUUHcyOUpxNjk1aHI3ODZhZ2thQWozN0l5TS8rejczekxOdDFqVGtCRWhGUjU1bW5PT3dmOGtGcGFOdUMyMjNRRS9GUFZxbFhsaVRGalBERjR5bzBUU1VteWNORWk2WDM5OVZLdlFRTzd5TnlPSFR1WVZjY1poWlF1TFpXZWZGeXRMZFk5NW1VbUpjdk9oMGRLVm5xNjd2RWVWWlRSeWFYYlo2SVN2cDA3ZDdyeXBhcXRtNkxPUVZjM0NaMmlyclU5ZS9UUWtiUFU3MVVWM2N5THpaczN5NEVEQjNUa0hQWHozbUJkcjcyQUJCMzVkdmlMcitUb3A1L3J5Q0RyalZQeHNSRVNjWjc1b3pBQXVLOSsvZnAyRWdaazU0NkJBK1hxcTY3U2tlL1l0MysvWFdTdVZwMDYwdmVHRzJURlgzL3BSNEQvVjZKamV5bldxWU9PM0pHODlFODU4UDZIT3ZJZXRRejZGTWNjNWs1V2x1T25USmljVWY1cXpoemRPamZ6RE8wL3Y3aDFhNm5nZ2VYdENnazY4a1h0Tzk4OVlwUjlVVEN0ZUxldUV0VzdwNDRBK0p0T25UcHg3amx5RkJ3Y0xEUGVla3N1YU5KRTkvaWVUei83ekM0c3B4SjFkUjR3OExjQTYvcFhlZXhvQ1NybHpwRmZmOXMvYWFxYzNPVHMvbVducVBPeTg3cFh1YkRKeU14MGZJYStUSmt5Y3ZsbGwrbklXVXYrK0VNeThsQ284THZ2djljdFovWHQwMGUzQ2g0Sk92SWwvdDRoa3BXU3FpTnpRdXZVdGo2MEhyTm4wUUg0cCtzOTlPRUk3MUw3SXIvKzZpdHAwcml4N3ZFOWFwbjdKNTkrS2syYk43Y3J3Q2NuSit0SFVOaUZsQ3NyRlI1OVdFZnV5RHg1VWhJZWZGZ3lyV1RZYTFUQ2VmVG9VUjJoSVBUcDFVdTNuTFZ2NzE1NzJmKzVPSGp3b1B5NWZMbU9uQk1SRWVHcEFyVWs2TWlYTkpmT080OTVkcW9FRlMycWV3RDRtMHJSMFZLdlhqMGRBVGtyVzdhc3pQdnVPN244MGt0MWoyOVNCWjFVQmZpTDI3YTE5MVVDU3RRMTEwalJEdTEwNUk1VGE5ZkovbGRmMTVGM3FKdFoxRzBvV0IwN2RwU1FrQkFkT2Vla2RmMDcxKzArYTlhdWRYU2YvZC9hWEh5eDBTUHd6aFVKT2p5di9NTVBzdThjOEhOTm1qUXhNZ0NBL3lwWnNxUjg5dW1uTXVUKysrMHplMzJaR25TMnZlUVNtZnZ0dDdvSGhWcGdnRVNQR2lrQkxwLzlmK0RGVnlYWlN0UzlKTjFIem1yM1o5SFIwWEp4cTFZNmN0YlhYMyt0VzdtemFORWlJemRzYmpSNDVudGVrS0REODlKVTlVN3VuZ0orclJyRjRaQUhZVllDTSttcHAyVFdSeDlKbGNxVmRhOXZTang0VUhyMDZpWHZ2ZisrN2tGaEZsNDFSc29QRytMcTFyNnNsQlRaT2ZJeHlYSzQwRmgrc1AzREcvcjI3YXRiempyWDVlcno1OC9YTGVlb2JWT205dG5uRlFrNlBPL2dxMi9Lc1o5LzBSRUFBUDkwVGRldXN1cXZ2K3paZERYWThsV3FJTmFBZ1FObDFpZWY2QjRVWm1WdTZDdmhEZHpkK25OcTlWclorOEpMT2lwNHhkamVtR3RxSlZGa1pLU09uTldoZlh2N2hxalQxT3FoL2Z2MzZ5aG5pWW1Kc3ZUUFAzWGtISFhXZTFSVWxJNjhnUVFkK1JMWm9wbHVtWk9WbWlZN0h4d2hxYnZObm9NSkFQQmRSYTJCdkpwTi84c2F3UFh1MWN2WVFOVzA5UFIwdWYyT08yVDVpaFc2QjRWVllHaW9WSmswUVFMQzNWM3Fudmo2MjVLMGFyV09DcGFwSTc3OGtYcW0xRWtYSnFnalVCczJhS0FqNTZqbDZyOHRYcXlqbkMzKy9YZjcrdWkwL2pmZHBGdmVRWUtPZktreTlTa0pLbVArcmxQR2dVU0pIL3lBSnl1TUFnQzhvM0xseWpKenhneFp1WHk1M0h2UFBSSlZ1clIreEhja0pTVkovNXR2Wm5rdjdCbzhaVzYvVFVmdXlGSlYzWWMvWWxkM0wyaXFOZ24xU1hJbndPQU11cHFkdjdsL2Z4MDU2N2ZmZnRPdG5QMzAwMCs2NVp6eTVjckpwWjA2NmNnN1NOQ1JMeUhXQzd2S00xTWtJTVRNSGJ2VG5WeTZYUFk5KzRLT0FBQTRNelhyVnExYU5aazZaWXBzMnJCQjNucmpEV25Wc3FWUHpjWnQyTGhSSmt5Y3FDTVVXdFpydHZ5ZHQwdG9yWnE2d3gycGNadGw3NHN2NjZqZ3FJU3pTSkVpT2tKT1ZCSWRHaHFxSStkMXZ2cHFDVFB3OTZ1Wjhkd1VmdnMxbDRuOHVWRFYyOVhxSzY4aFFVZStGV3ZkU3FLc0R3ODNKTDc4dWh6NzFmazNLQURBUHhVdlhsejYzWENEL0xSb2tXeGN0MDRtakJ0bkQ4cE1ERFNkOXRJcnI4aStmZnQwaE1JcU1EeGNLazk0VWlRb1NQZTRRNDI1VGhnNGMvcGNxSDNQNFM1WHMvZFY1Y3FXTlpxZ3EycnVqUnMzMXBGelZxMWFaUjg1bVJONy8vbXlaVHB5VHUvZXZYWExXd0t5REI0dW1KV2VMcHU2eEVycXhqamRrNzJvUVFNbGV0aFFIZjJUV3RhOG9WVjd5VGgwU1BlY1dZTzF5eVhRUi9lY21aVDQ1Z3paODhRRUhUbXJZZHdhQ1FnT3RuL1gyMjY5UTVKKy9sVS9ZazV3dWJKUzY2dlBKTVQ2czdBNk1uK0JKQXdZcEtNeks5RWpWbUltbi9uM25wV1JJWEdkWXlWbDR5YmRrNzJTM2JwS2xXbVRkZVIvVHNYSFM5eGxuZTNYc0VtQlJZcEluUVhmU1lnTFcwSk11SC9JRUhueEpYT0ZnKzYrNnk2WlBtMmFqcnhOZld3MmF0TEVudUUwNWR0dnZwRk9IVHZxeUJsTm16V1RWYXZON1N0OTUrMjNwVytmUGpyeU52VTdQSGJzbUh3emQ2NHN0QkozdGNSeXk5YXRSdlkzNXRld0J4NlE4ZVBHNmNoWmF0QmJ0VVlOdXppZEtYdDM3ZkpjQWFaL1c5ZXluYVFmT0tBamM2SW5qWmN5M1dOMWRPNTJUWGhLRHI3K3RvN2NFVkkxUnM2Yk0xdUNDbWg4cmQ2VGRSczBrQjA3ZHVnZTU2blZOdTNhdHRXUjd6cXZkbTE1YVBod0habngwc3N2eTMyREIrdklPUXQvK0VIYXRHbWpvLy8xeWFlZlN0OGJidENSTTlTNTUxczJiWkx3OEhEZDR4MGs2SVdBR3dtNmtuYndvTVJkM1UweTlwdi9rSXRzM1ZKcXZQMmFCQlRTZlVrazZNNGhRYzhkRXZUL1I0SitacjZVb1ArYlNnTFVUTFZLMk5XWG1xbFJsWVVORHBGeVRjMWFxWmwvRTROSUV2VC84SlVFUGVQNGNkbDQ5YldTN25MUjNOTDkra3JseDBmWnkrMEx3aVVkT3VTNmtGaGVYSFhsbGZMbDU1L3JDRGxSMThWcU5XdEttc05IOFkxNDZDRVpPMmFNanY3WGdOdHZseGt6WitySUdYMTY5N2JybFhnUlM5emhtQkRyQTdqeWxJbXVMTUZLWHJ4RTlyN3dzaG9wNng0QUFQSkdWVDZ1VkttUzNENWdnTXorOUZQWnNIYXQvUHpqajNMWEhYZEkxWmdZWTVXUmMyUHYzcjJ5Y3RVcUhhRXdDeXBXVENvOWFTVXhnZTRPM3c5L09FdU8vMWx3UzkyYlhYU1JicG14ZXMwYXljakkwQkZ5VXJac1dXblpvb1dPbkpQVFBuUjFBM0h4a2lVNmNrNlA3dDExeTN0STBPR280bTB2bGpKM3ViQWYzWG9USDN6eFZUbit4MUxkQVFDQU0xVFJvQmJObTh1enp6d2o2NjFrL2FlRkMyWFFYWGNWU0VYNHpNeE0rZnJycjNXRXdrNk5zMHBjMDFsSDdsQXJ6SFlPZjBReWtncm1WSUhhdFd2cmxoa25UcHl3dDd6ZzdGU2h6V3U2ZHRXUmM5U0t0SlNVRkIzOTA1NDllMlRMbGkwNmNrYjU4dVh0bFJOZVJZSU94NVcvWjVCRU5EZDd0MVBKU2t1VG5mYzlJR2t1TEtrSEFCUk82b2luWnMyYXlUUFRwc25Xelp2bHBSZGVrTnExYXVsSDNiSGtqejkwQzRXZE9rb3IrdUZoRWhUbDdzMml0QjN4c252aTVBSlp1ZGpDd0l6dDZWUnl2aW51N050eDhSL1hYbnV0NHlkaXFKVkMyN2R2MTlFL3FUb2hUcTl3Nk5LNXM5R0NldmxGZ2c3SEJZYUZTc3d6VXlTb2JCbmRZMDY2bFp3bkRIdFlzdEpabWdRQU1Fc2QrVFRndHR0azVZb1Y4dVRZc1JJUkVhRWZNVXZ0aVdjSkx2NFdVcmFzUkk4ZTZmcFM5eU1mZnlMSGZqTzNGenc3MWF0Vk0zclVtbHFsOHNNUFArZ0laNk4rSDgyYk5kT1JjK1prczFMSTZSVkU2amk2M2oxNzZzaWJTTkJoUkdpRkNsTDU2WW4vTFNCblV0SlB2OHErNTEvVUVRQUFacWxaZFZVdCtmTlBQNVVpTGhTblZVWHNmSFVKcmhjcjQvdURrbGRlSWNVdWRiYVE1Tm5ZUzkySGpaRDB3NGQxanp2VWxwUDY5ZXJweUF5VkhIcWhLS1N2TUZFUTlFeUZBSk9Ta2h6ZmYxN1J5bEZhdDI2dEkyOGlRWWN4eGR0Y0xLWHZ1RTFIWmlXcS9laS9zd1FRQU9DZURoMDZ5UEJodzNSa2pwcmhVL3RrbmFhSzN6bTlWUFhmMk50clJrQlFrRlI2L0ZFSkxGRmM5N2dqZmQ5KzJUVitrcXRMM1lPc24vWFNUcDEwWk1aZksxZkt0bTNiZElTenVlTHl5eDB2bnJsOHhZci9PUTlkSFgrcEtzYzdxVnUzYnZiNStsNUdnZzV6ckEvOWl2ZmZJeEV0blY4RzgyLzJmdlFISG5MOXJpNEFtS0FTTWllcG1TR25qOFhCZndvbTNYYmJiY2FYdXF2ZjM3OEhyazVRZzFUVENickpJOXdLdTlEeTVhWDhnME4wNUo2am4zOHBSeGY5cUNOM1hISEZGYnBsaGxycDhaWkhqOXp5b2hvMWFrakRCZzEwNUF4MTFPV3UzYnQxOUIrTEZ5OTJkR1dEdXRuVHorSHoxRTBnUVlkUjZwenlLcE1uU2xDcGtyckhISFV1YU1KREk0MmZadzBBcGgwL2ZseTNuUEhKcDUvSytnMGJkQVFubFM1Vnl0NlQ2WXRNSitmS1pvZXJMK09meXZUcUtSRk5MOUNSU3pJelpkZGpZeVg5NkZIZFlaNDZWVUVkOFdYU2pIZmVzWmRVNCt6VVB1NGIrL1hUa1RQVVRaTGZmdnROUi84eFo4NGMzWEpHMWFwVnBkSDU1K3ZJdTBqUVlWeFk1VXBTYWVwVDluSXMwMDdNV3lENzMzaGJSd0RnbTV4YzBoY2ZIeS8zRFI2c0kvOXk4T0JCT1hDZ1lFL3lVQU5WdFNmZE5EWHo0N1R3OEhBSk5KeWtxMldyTUNjZ09FZ3FqMzlDQWlMQ2RZODcxS1RJemtkSDI4bTZHOVJ5Nmw2R0MzdXA0N3pHUHZHRWpncWUweXVwbkthT0tYTzZFdnJjYjcvVnJmL2NxUDdsWHdsN2ZsMTd6VFdlcnQ3K054SjB1S0xFSmUyazFLMDM2Y2lzQTFPbXkvSEZ6aGFVQUFBM3JYQW9xVkg3Zi92ZGVLTWtKaWJxSHYraGt2T3UxMTRyelZxMHNDc3dGK1JnMXZSdVhKV2NGeTl1WnE5eDQ4YU5kY3NNTlNORzhTMnpJbXJWbEhMM0RySzNGcnJwMkxmZnk1SDVDM1JrbnFxOGJYclZ4NnV2dlNacjE2M1RVY0ZRMjVIZWZmZGR1ZW5tbXoxZFpMRmF0V3BTdlhwMUhUbERGWXI3KzJkZXRXcVZveXNhMU0zVVcvcjMxNUcza2FEREhkWUZ0ZUtRK3lTOFNTUGRZYzUvcW93K0xPbUhqK2dlQUhDT0dpQ1dLbFZLUjJhb1k3WHltOVNrcEtUSUxiZmU2bmdGWEM5UU15dlh4c2JhejVQYXM5akZTdFQ3MzNLTDdQN1gva1UzcUwzaHBtK0FoQVFIUzRrU0pYVGtyTXFWS3VtV0djdisvTk0rNHhobWxlMS9vNFRWcTZNamwyUm15YTZSb3lYTnBWVXN6WnMzTjE3Ti9ZU1ZFS3FibWtkZFhMNy9OM1hOWDdseXBWeDYrZVZ5eTRBQjh2R3NXZkxzYzg5NTlnYVhXam5VNy9ycmRlUU1kZU4xMTY1ZGRsc2w2MDcrN09mVnJpMjFyUzlmUUlJTzF3UkdSRWpNYzFNbDBOQXN3T25TZCszNXovbm9IbDhlQk1BM21TNEt0bnJOR2xtN2RxMk96dDNKa3lmbFppczUvOUxoL1h0ZW9LcVo5KzdiVjViODhmOG5kNmd6d2ovODZDTnBmT0dGOHRTa1NVWXFubWZucDU5L05uNWpvRW1USnNhVzBWY3luS0NyMzhYalk4YmtlYUROTVcyNUV4Z2VMbFVtUEduWC9uRlR4c0ZEc3ZPeHNTcTcxRDNtcUpVa1ExellyclBHdXZiMjZ0UEg4Vm9nT1ZGSjZXMjMzeTR0TDc3NHY4ZU5xZmZNcU5HalpmNzgrWGJzUmRmRnhqcTYvVWJkOEZRMzlSU256NmJ2MHFXTDQ1WG5UU0ZCaDZ2Q0tsZVdTbE1tNk1pc0UvTVh5WUYzM3RNUkFEakgxR3ptNmNaUG5KaW5wRVlOOUdLN2Q3Y0x3L2tiTldEdWU4TU5NaStiZ2R1UkkwZmswY2Nla3pyMTY4dTA2ZE9OejJ5ci9lK0RoNWl2b24zaGhSZnFsdk5hdDJxbFcrYk1mTzg5ZWVPTk44N3A5YnhwMHlZWlBIU290R3Zmbmtyd3VSVFpvTDVFM2VMT2RzTFRIWjgzWHc1OThaV096RklKWWFYb2FCMlpzMkRoUW1uVHJwMnNXNzllOTVpeGRkczJHVFo4dU5ScjBFQm12dnZ1Lzl5UVVxOTl0VHBvKy9idHVzZGIxQkwzZW5YcjZzZ1ozOCtiWjIvUCt2SG5uM1dQTTI2em5rZGZRWUlPMTVXOHJKTkUzVGxBUjJidG56UlZrbGF0MWhFQU9NUHA0MlhPUkNYWUw3MzhjcTZUR2pYejhONzc3OHRGelp2TC9BWHU3UXQxaTFxeVAyRGdRUG4ydSs5MFQvWlVrYjNoRHo4c05Xdlh0Z3ZrTFYyNjFQRmo1clpaQStiT1hidmFBMnlUMUw1Sms4V3hhdFdxWlg4UGs5UnpmODk5OTltSnh1clZxOCtZY0t2WDcwWXJLWC9ublhma3lxdXZsa1lYWENBdnZQaWl2WTFCSlM3SWhZQUFxWEQvUFJKYXZhcnVjSWwxamRvejdpbEpkV0VyUTdGaXhlVFJrU04xWkpaS3psdTJibTJ2eWpuczRERythb1dUbWhWWEs0SHFOMndvMDU5OVZrN21jSXppL2dNSDVOcnJybk4xWlZCdXFaVTl2WHYxMHBFelZOMEtkYzEyc3E3SUJkYjFSQjBONXl0STBGRWdLZ3krVDhJYW1OMUhwR1JaRjhHRSt4N2dmSFFBamxMRmNVeFRpZm5RQng2UUlVT0gyck1uYWhuM3Y2aytkWGFzS2lqVXRGa3p1ZVcyMnlUeDRFSDlxUDlReVp2NjJUNmJQVnYzNUU2eTlSbWdibkswYmQ5ZTZqWm9JSTg5L3Jnc3N4SStOVHVUbDlVSmFzQ29LajFQZk9vcGFYTGhoYkxpcjcvMEkrWlVybHhaenJjRzhhYW9HYkNTSmMwZmhacGhQWGNmZlBpaE5HL1ZTaXJGeE5oSnVOcUcwY2RLVWxwZGZMRlVybHBWTHJDZTA5c0dEclJ2TUozK2VsZS9ON1UzRldlbmxycFhHamRXclFmWFBlN0lPSFJJZG80Y0xWa1o1cmNXWG4vOTlVYmZFNmRUeWJSYWxWTzNmbjE1Y1Bod1diNTgrVGtueXVxMXJGYnpxTzB3YWxWSW5YcjE1S291WGV6cjJabXU2MmV5YnQwNnVlT3V1enhaMlYwbDZFN2U1TnV3Y2FOODl2bm5lYnBHWjBkVmJ6ZDlJOUpKQWRZUDc5eFAveStxV05lbUxyR1N1akZPOTJRdmF0QkFpUjQyVkVmL2xKbWFLaHRhdGJmZi9EbHBzSGE1QkVaRzZnaC9TM3h6aHV4NXdzeXk4b1p4YXlRZ2ovczVUbTNiTGx1NlhpZVpTY202eDV5aVYxNG0xWjZmN3NwUmIyNVFWVk1UQmd6UzBabVY2QkVyTVpQUC9IdlBzajRRNGpySFNzckdUYm9uZXlXN2RaVXEweWJyeVArY2lvK1h1TXM2R3o4L1A3QklFYW16NERzSktST2xlM3pML1VPR3lJc3Z2YVFqNTkxdERUeW1UNXVtSSsvN2ErVkthZDZ5cGFNRGlKeW80N0JxV0ltVU9ndjQ3MlJLTGVmK2Zja1MyYmxybDZ0N0piUHp6dHR2Uzk4K2ZYVGtIRFZ6cmhJNXA1YnNxeUovWmFLaTdKc3NIVHQwa1BQUFA5OHVQRlc2ZEdtN1VycmFUNm0rMU1CWmZhbVpNMVdJN3BkZmZwSHZ2djllL3N6REFEMC9IbjNrRVJsdEpRZ21YZHV0bTN4ejJ2RkdYalQ0dnZ0azhxUkpPbkxXdXBidEpOMkZRbWZSazhaTG1lNnhPakxJdWk0bFBEWkdEci8va2U1d2lmWGVxdlRVT0lseTRXZjgyWG8vcW1KcUJaR3dsaTlmM2k0NDFySkZDNmxRc2FKOWJWYlhqckRRVUVtM3JobHFtYnE2cWFxS0k4YkZ4Y212aXhmTGdmMzc1ZWl4WS9wdnlMdW5Ka3lRb1M1c3F6a1g2bmZRdWswYis5cm9sTCt2d1U1UTEveTFxMWI1VElFNGhSbDBGSmp3NnRVazJycVFpd3QzdEU1OE8wOE96SmlwSXdESUh6VTRpN0NTWnJlb0dXUzEzUEt0R1ROazJqUFAyRitxdlg3REJrOGs1NmFvZ2E3YTQrM2tmbnAxVStWQVlxSzlkUHFweVpPbDMwMDN5WVhObWttMW1qV2xkTm15VXJWR0RYdlphWXlWd0t1NDVubm4yZnVnSDNuMFVmbnhwNTljVGM3VlRZTjc3N2xIUitiME1YQmp4V2t2dmZLS2JMS1NIZVNDV3VvKytGNEpLbGRXZDdqRWVtL3RuVGhaVXZmdDB4M21YTnk2ZFlFZG1hVldMYWtiQkpPZmZsb2VlUEJCdStaSHA4c3VremFYWENMdE8zYTBieHlvN1RocTVuM0d6Sm15ZWZObVI1SnpaZlRqajl2NzQ3MUV6VXgzNjlaTlI4NXdLamxYTG1qU3hLZVNjNFVFSFFXcTFGVlhTS20renU1ZHljNyt5ZE1sZVczQm5tMEp3RDlFUmtaS2h3NGRkQVFUVkhKKy8rREI4dnFiYitvZWQ2aVZDZkVKQ1k0TnFQTmowSjEzMmttNmFaZDI2aVRGaXhYVGtUZXBsUlFQUGZ5d2E2dFdmRjFJVkpSVUdqUEtsVW1RMDJVY09pd0p3eDh4dnlyTitybWVuakxGOFFKbFhuZktlaC9jMUwrLzdOaXhRL2Q0dzVXWFgyN1BWSHZSRFE0ZkJlY0dFblFVTE9zQ0d6MXFoSVNmYjc3Z1V0YXBVNUp3NzFESk9PNjlJaHNBZkUvUEhqMTBDMDVUU3lZZkhEWk1YbjM5ZGQxVCtEU29YMThlZnVnaEhabFZwa3dadWV5eXkzVGtYVjkvODQwcyt2RkhIZUZzU2x6YVNZcGQza2xIN2tuNmRiRWNuR1grRklraVJZckl6Qmt6N01KeGhjbSsvZnZ0V1hzdnJaNXExS2lSSjR1d2hZYUdTdGV1WFhYa08walFVZUFDdzhJazVvVm5KTEJZVWQxalR1cTI3Wkx3MEVoN0R6WUE1SWVhZFZRRFJEaExMVzE4Y3R3NGVmSGxsM1ZQNGFNR2xhOWFQMytZOWZub0JqWHo5Y2pERHp0Nm5yRUphdlo4K0VNUGNleGFMZ1VFQmtybHNhTWxLTXI4S294L3NINVBlOFpQa2xNNzRuV0hPWTBiTjVZM1gzL2RmczhVSnF2WHJKRkI5OXpqNkZMdy9GQXJHa3pVSU1tdnBoZGVLTldxdW55cWdRTkkwT0VKWVZVcVMvU1RqOXN6NnFZZC8yNmVIUHp3WXgwQlFONm9Ra0d4RHUrN015MHFLa291YWRkT1I5NmpFckJKa3lmTHVBa1RDdTFTWnBVa1B6TnRtalJ2M2x6M3VFTVZ5K3ZhcFl1T3ZFc1ZhSHhuSmpWbGNrc3RkYS93MElQMnZuUTNaU1VueTg3aEl5VExoU0p1cWtMMytDZWY5T3dTYTFNKy9PZ2ptZkwwMHpvcWVGMDdkN1lUZFMvcGYrT05Qdm02SUVHSFo1VHEybGxLOXJwT1J3WlpIeFo3eDArUzVIWHJkUWNBNU0yd0J4N3dtWmtiOWU5ODdlV1g3VXJ3WHFVR1VsMnNRVjZ0bWpWMVQrR2lCcmNQRHg4dXQ5MTZxKzV4ajNydXh6Nyt1R3V6OXZueHhMaHhkcTBBNUU1VTdMVlNwTzNGT25KUDhyTGxjdUN0R1RveVI3MTJWVEhGeHcyZmR1QkZVNmRQOTh3UmhPb21YNlhvYUIwVnZLSkZpOHBWVjEybEk5OUNnZzd2c0M2dzBTTkhTRmdkODVVV3M1SlBTdnhkOTBtR0gxYy9CbUJldlhyMTdEdjB2a0FOWHRWZXZKaVlHTjNqVFdxUTkvdml4ZmJadW9WcFJpdzRPRmhHUFBTUVBEWnFWSUg5M09yMXJJNTE4L3J6dm52M2Joay9jYUtPY0ZhQmdWSnA5RWdKaUlqUUhlN1ovK3lMa2hKdmZxbTd1cmsxNHVHSDVaV1hYcExJQXZnNUM0SmF2cjF3L254N1paUVhoSVNFeUkzOSt1bW80RjNVdEtsVXJGaFJSNzZGQkIyZUVsUzBpTVM4K0t3RUZqZGY4Q010UGtGMmpoeHQ3NVVDZ0x4UWljeVRUendoVlNwWDFqM2VvLzZOSTBlTWtBY2ZlTUNPNjV4M252Mm5seFVyV3RRdS92VEJ1KzlLeFFvVmRLLy9VdWZjUHp0OXVuM2VlVUV2RVgxZzZGRHAwTDY5anJ6clJTc1IyN2h4bzQ1d051SFZxa241WVVQc3lSQTNaWjQ0SWZGRGgwdW1DM1VEMUxYdTFsdHVrZG1mZlNabHk3cDh4SnlMU3BRb0lVK09IU3MvTFZvazlldlYwNzNlY0Yxc3JHZHFXVnpmdDYvbmJ6Wm1od1FkbmhOZW83cFVmTUpLbkYwWXBCeWJNMWNTUC9oSVJ3Qnc3dFF4V0srLytxb25sN3FyV1ZrMUkzcjZyR3k1Y3VYc1A3MU8vWHU3ZCs4dWZ5NWRLamYxNitjVFM2L3pvbXJWcXZMTm5EbHkrNEFCbmhoTXFsbXc5MmJPbEVibm42OTd2TWsrZG0zRWlFSmJxeUF2eXZUcExlRU42K3ZJUFNmL1dpVUgzbnBIUitaMTdOQkJmdi8xVi91c2RGOU4wTTVFSmI2WFhYcXAvUG5ISC9MUThPR2UvTXhScTNDOE1HdXRLdnVyMmdTK2lnUWRubFNxeTlWU3NxY0wrOUd0RC9aOTQ1NlNrM0diZFFjQW5MdU9IVHZLMUNsVENuejI4M1JxbWVjTHp6NHJqNDRjK1k5L1Y2bFNwWHhxMEtwbXdsNS83VFg1K2NjZnBYV3JWcDU2anZOREpjSzM5Tzh2UzM3N1RkcTJhYU43dlVFZHUvYkY3Tm1lVDlMVnNXdno1czNURWM0bU1DeFVxancxWGdMY3Z0bGxqYlVPUFArU3EyTXR0WlhudTdselpkd1RUOWg3a1gyWnVsNDNhTkJBdnZqc001bno1WmYyVFQydlVqY05lbmJ2cnFPQ282NnA2clBPVjVHZ3c1UFUwU0RxZlBTd3V1YVhZbWFxL2VpRDdwZU1wR1RkQXdEbmJ1RHR0OXVWaEwyUVFLb2w5M08rK2twdXZmWFcvL24zcUprRlZZSGVsNmdCNmdWTm1zaUNIMzZRTDYzRVVTWHF2a3p0amZ6ZVNoNWVlZmxseit3Zi9iZksxbXRJSlRocU50S0wxR3RDblVoUXljUGJTN3dvNHJ6YVVtYWcrMFVJTTVPVEpXSFl3NUtabHFaN3pGT3Jib1k5K0tEOHNYaXhkTHZtR3ArY1RhOWJwNDY4L2NZYjlvMjhLNjY0d2lkdVVIcmh1RFZmcjJGQ2dnN1BDaXBTUktwTW15eUJMcHd6bkxwNWkreDZiSXhkNFIwQThrSU5CdFQrM2JkZWY5M2VRMTBRMUwraDMvWFgyOHZDczV1VlZUTWNCZlh2eXkrMXhGTU5VaGN0V0NBTDVzMlRYajE3K3N4WjlPcDNveEx6OTk5OVYzNzkrV2RwWS8xK3ZENkFWRFBwYXNaT0ZhOEw5OUFXQTFVYzY0UDMzcFB2di8xV0d0UjNmOG0yVDdOZWMrWHZ1bFBDckVUZGJhZFdyNVY5ejcyb0kvZlVybDFiWm4zOHNmeTRjS0ZjY2ZubG5qL3ZYMUhMOHo5OC8zMVo4ZWVmY3IxMVRmZWxMVDVxbVh2MTZ0VjE1TDdpeFl2N3hKR1JPU0ZCaDZkRjFLMGpGY2VPc2w2cDVsK3FSei8vU2c3Ty9rSkhBSkEzYWpDMWRNa1NWODhiVjN2TjI3VnRLejh2V2lSdnZ2Rkdqa3Y3MU5KcU5ZdnV5MVJpMjliNmVkVmU2YTF4Y2ZMVXhJbHk0UVVYMk0rRDE2aUNUajJ1dTA1K1hMREFUc3g3OXVqaFU4djAxZXRsN0pneHNtVHhZdW5Vc1dPQlBjZXFrSjc2L3A5OThvbjlQSGEzbmxOLzJlN2dOclhVdmRLNE1lckNvWHZjay9qcUc1Szh2bUNPdVczVnNxVjg5Y1VYc2x6WHRTampzZFVyYXUrMk9tTHhMeXNwVjZ1RjFHdmNpOWUwczFIdjFkaHUzWFRrUG5XZDhQblB1Q3lEMVRXeTB0TmxVNWRZU2QwWXAzdXlGelZvb0VRUEc2cWpmMUtWSHplMGFpOFpodzdwbmpOcnNIYTVCRVpHNmdoL1MzeHpodXg1WW9LT25OVXdibzBFR0w1NFpHVm1Tc0tJUitYb3g1L3BIbk1DcklGSXphOCtrWWc2ZFhTUE54Mlp2MEFTQmd6UzBabVY2QkVyTVpQUC9IdlB5c2lRdU02eGtySnhrKzdKWHNsdVhlMlZEUDRxN2NBQjJUVnVvdldjbUYwOVlRK0lIbnRVZ2wwNG9jQ0VHZSs4SS9Pc0FZTXBsM2JxSkRmMzc2OGovNUJodmMrK21qTkh4b3dkSytzM2JMQmpweFd4UHZOVW92ckl3dzlMOCtiTmN6MHpwQ3BnLzJZbFhFNGFkT2VkMHJwMWF4MjVUejIvTytMajVRdHJBUDY1OWJWMjNUbzVldlNvZnRROTZ1WkJ5WklscGRsRkY5bUplVGRyb09yTGV5RlBsMmw5SHE5WXNjSSs0bXpCd29WeTRzUUovWWdaYXRhd1JvMGE5cDdXL2pmZFpDKzdONUdVSjR3Y0xlbkhqdW5JbktqciswanhWaTEwVlBEMnYvbTJKSzFZcVNQM2hKOVhXeXJlYzVjOW0xK1ExUFZoN3R5NU1tUG1UUGx6K1hJNWZQaXdmc1FkNm5xdGlveDJ1T1FTT3pGdjJiS2xSUHBKSHFNKzg4YU5INitqLzNVeU9WbSt0cDU3RTUrTDZzYXRXbDNseTBqUUN3RmZUOUNWRE91RGMvTjF2U1YxeXpiZFkwNVk3VnBTNjh0UEpEQThYUGQ0RHdrNjREdlMwdExrajZWTDVaVlhYcEc1MzM0cng2MmtKcStEa2tCclFLdG1ORlV5cmdZZ25hKysyazVhdkw1VTJtMXFhSFB3NEVGWnZYcTFmUHZkZC9iZ2U4a2ZmMGk2TlM1UlgwNVNNMXhxb0swUzhoYlc3K1ZxNjNlaWlxdXBKTjJmcWJQSXY3RUcyTE0rK2NSK2JrK2VQR2tuOFBtaFh0dHF4VUZySzFGUlMxVGJ0V3RuRjhUeWhTWEo4RzFIamh5eHJ4T3E4T0RpeFl0bDlabzE5clhDeVFSU1hTdlVsaHgxcmJqOHNzdWtmZnYyOWg3emlFSnlidnZwUHBzOVczcjM3YXNqNTZqbmQxZDh2TTlzZmNvT0NYb2g0QThKdXBLOGJyMXM3WG1EWkNXYkwrWldzbmNQcVRMaGlRSy91NXNkRW5UQU41MDZkVXJXV0FNL2xiRC8vdnZ2RXArUUlJbFdJaGx2RFNoVWduTTZ0ZiszZkxseWRoRXhWZlN0V2JObTByQmhRMm5jcUpIZkozOG1wRnBqaVowN2Q4cWF0V3Z0UHpmRnhjbldyVnZ0Z2JtYVNVdEtTckpuNE05RS9RNmlTcGUybjNlMXY3R2FsVFRXcTF0WHFzVEUyTCtUeXBVcUZjcEI5dC9VYzdmV2VsNVhybG9sNjlldnQyZlAxR3lrZWw2M2JOa2kveDVvVm9xT3RtY08xWmM2NS82Q0N5NlFtalZyU2lQcnRSMVRwUW9KT1FxY1doMnliZHMyZXlXT3VsNm9tMURIamgyenY5UTFZL2VlUFpKOGh2R29TZ3lqSzFhMGJ6U3A2NFc2Z2FwdTJLbXE4dWRiMTRvcTF1dGIzWWdxek5SblhZdldyZTFyaGRQNjNYQ0R2UFhHR3pyeVhTVG9oWUMvSk9pS09yTjh6eU9qZFdSV3BXY21TK2xydXVySVcwalFBZjl4dG85aFpzZk55KzFRaU4vRnVjbnBlZVc1aEsvS3pmV0MxM2YyWG52OWRSbDB6ejA2Y282NnNmZkRkOS9aQlRoOUhRbDZJWEJrOWhkeTRPWFhkZVNzV2w5L2JpWG9MdDdwdGw2dXU2YzlLeW1ienY2YXlxL0FZc1drOHBoUkV1VEIxeFFKT2dBQUFIekp2bjM3cFBFRkY4akJzK1IwZWFHMkMveTFmTGxmck1BaFFRZDhFQWs2QUFBQWZJVktPVys1OVZaNTc0TVBkSTl6MUlxRjExNTV4UzRtNlE4NG53SUFBQUFBWU16N1ZtSnVJamxYeXBVcko5ZkZ4dXJJOTVHZ0F3QUFBQUNNK1BYWFg0M3NPLy9iblFNSCt2elo1NmNqUVFjQUFBQUFPRzdWNnRYU3EwK2ZNMWE5ZDBMRmloWGx2bnZ2MVpGL0lFRUhBQUFBQURocS9vSUZjdmtWVjhqK0F3ZDBqL09HUC9pZ2ZmeWxQeUZCQndBQUFBQTRJaTB0VFo1LzRRVzVOamJXU01YMnY5V3RXMWNHM242N2p2d0hDVG9BQUFBQUlGOVVwZmIxNjlmTDFWMjZ5SkFISHBDVWxCVDlpUE5VNWZZcGt5WkphR2lvN3ZFZkpPZ0FBQUFBZ0R6YnNHR0QzRGxva0Z6WXJKa3MrdkZIM1d0T3J4NDk1SXJMTDllUmZ5RkJCd0FBQUFDY2swT0hEc25zenorWHpsMjZTS01MTHBBMzMzcEwwdFBUOWFQbVJGZXNLTTlNbjY0ai8wT0NEZ0FBQUFESVVWSlNrcXhidDA3ZWV2dHRpYjN1T3FsZXE1WmRvZjM3SDM2d2w3ZTdJVHc4WEQ1NDd6Mkppb3JTUGY2SEJCMEFBQUFBSUptWm1YTHExQ2w3ZG56RHhvM3kxWnc1TXVxeHgrVHlLNitVV25YcTJFdllCOTU1cDh6NTVodGpSNmRsSnpBd1VCNTc5RkZwM2JxMTd2RlBKT2dBQUFBQVVNaWRPSEZDV3JkcEk0MmFOSkVhdFd2TCtZMGJ5M1U5ZXNqRVNaTms0YUpGa3BpWUtCa1pHZnEvZGwrZlhyMWs2SkFoT3ZKZkpPZ0FBQUFBVU1nVktWSkVkdTdhSmR1MmI3ZVhzM3RKMnpadDVPV1hYcEtnb0NEZDQ3OUkwQUVBQUFDZ2tGTkhsN1Z1MVVwSDN0SDB3Z3ZsMDFtekpDSWlRdmY0TnhKMEFBQUFBSURVT2U4ODNmS0dpMXUzbHJuZmZDT2xTcFhTUGY2UEJCMEFBQUFBSU0yYU5kT3RncVZtODYvcDBrVytuak5IU3BVc3FYc0xCeEowQUFBQUFJQlVxVnhadHdxT1NzNkgzSCsvZlBqQkIxSWtNbEwzRmg0azZBQUFBQUFBaVltSmtXTEZpdW5JZlNWS2xKQjNaOHlRcHlaT2xKQ1FFTjFidUpDZ0F3QUFBQUNrZVBIaUVoNFdwaVAzQkFZRXlHV1hYaXJMbHk2VlhyMTY2ZDdDaVFRZEFBQUFBR0RQV3J1OUR6MjZZa1Y1NmNVWDVhc3Z2ckJuOEFzN0VuUUFBQUFBZ0sxQmd3YTZaVlprUklUY1BXaVFyRnl4UW02OTVaWkNjY1o1YnBDZ0F3QUFBQUJzRnpacG9sdG1oSWVIeXgwREI4ckt2LzZTNlZPblNzbENWcVg5YkVqUUFRQUFBQUMyT25YcTZKYXpxc2JFeU5qSEg1Zk5HemZLODg4K0s5V3FWdFdQNEhRazZBQUFBQUFBVzNSMHRCUXRVa1JIK1ZQSitydjZYWCs5ZkQ5M3JteGN2MTVHUFB5d2xDOWZYaitLTXlGQkJ3QUFBQURZaWhZdEt1WHltRVNyLzIrZDg4NlRPKys0UXhiTm55OGIxcTJUdDk1OFV6cDA2TUFlODF3aVFRY0FBQUFBMk1MQ3dpU21TaFVkblZsQVFJQmQ1RTN0SDI5L3lTVnkzNzMzeXR5dnY1WU5hOWZhUmQrZWUrWVp1ZmppaSszOTVqZzNKT2dBQUFBQWdQOXEyYUtGL1dlNXNtV2xjZVBHMHJGREI3a3VOdFplb2o1enhneVpQMitlckxlUzhWM3g4VEx2dSsvazZjbVQ1ZEpPbmV6bDY4eVU1dzhKT2dBQUFBRGd2MFk5K3Fpa25Ub2x1eElTWk5tU0pmTGQzTG55MFFjZjJFWGUrdlR1TFczYnRMSDNxb2VHaHVyL0I1eENnZzRBQUFBQStDOFM3NEpEZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIdUFqQ1hxQS9iK3p5VHgxU3JjQS81YVpmRkszY2hERS9UY0FBQURBbC9qRUNENHdORVNDaWhYVFVmYVNWcTNSTGNDL25WeTJYTGV5RnhKVlJyY0FBQUFBK0FLZm1XSUx2NkN4Ym1YdjZOZHpkUXZ3WDFscGFYTHNoL2s2eWw1bzVXamRBZ0FBQU9BTGZDWkJqenkvb1c1bDc4UzhCWkorNkpDT0FQOTA3SmRmSlgzUFBoMWxMN0pGTTkwQ0FBQUE0QXQ4SmtFdmVuRXI2MStiODBiMGpLTkhaZmRUVDR0a1p1b2V3TDlrSkNmTDN2R1RSTEt5ZE0rWkJaVXZKK0hWcXVrSUFBQUFnQy93bVFROXJGcFZDYTFlWFVmWk8vcnA1NUw0eVdjNkF2eEhWbnE2N0JvNVdsSTNiOVU5MlN2ZXFZTUVCUHJNMnhzQUFBQ0F4V2RHOElHaG9WS3FWM2NkNVNBalEvYU9mRndPdlBPdVpGbHR3QjlrSkNWSi9JTVB5OUV2NXVpZUhGaUplYW5lUFhRQUFBQUF3RmY0MUJSYlZOL2VFbFNxcEk2eXAyWWE5ejQrVHJiZmZwZWMycnFOSmUvd1dlcTFmT3luWDJUenRUM2xtRXJPejdLMFhZbHNjWkVVeVVYTkJnQUFBQURlRXBCbDBXM0hxZVJpVTVkWVNkMFlwM3V5RnpWb29FUVBHNnFqN08xLzVYWFpOM0dLanM0dUlEaFlJcG8xbGFMdDIwbEVyUm9TVkxhc2ZnVHdxS3hNU1l2ZkpTYzNicFRqMy84Z0taczI2d2ZPTGlBMFJHcDgrb0ZFTnN3NVFWZXJTK0k2eDByS3hrMjZKM3NsdTNXVkt0TW02d2dBQUFDQUtUNlhvR2VtcHNubTJKNlNzbTZEN2dId3QxSTNYUytWeHp5bW8reVJvQU1BQUFEZTQzTlZwQUpEUTZUSzFFa1NXS1NJN2dHZ2hOV3ZLOUVqaHVzSUFBQUFnSzh4bTZBSEJGai95L2xvdFA5S1Q5ZU5zNHVvYzU1VW1qNUpBa0pDZEE5UXVBVlhLQy9WWG45SkFzUERkYzlacUhVenVWdzhvN2FKQUFBQUFERFBlSUllR0ptN21lN2NIQjExdXBLZE9rckY4V1BzUGJkQVlSWVVWVnFxdmYyYWhGYXNxSHZPTGlzdFZUS09IOWRSem9LclY5VXRBQUFBQUNZWlRkRFZPY3pCdWFpNnJwemFzVU8zY3NsSy9xTjZYQ2RWWG5sQkFvc1gwNTFBNFJKYXA3YlUrT1I5ZTFYSnVVZy9kRmpTOXgvUVVjNUNLbFRRTFFBQUFBQW1HZCtESG5aK2ZkM0tXZHFXYlpLeWM2ZU9jcTlFKzNaUzY4dFBKS0o1VTkwRCtEKzE3THhrMzE1UzY3T1BKTHhhTmQyYmU4Y1gveTZTa2FHakhBUUVTRmlWeWpvQUFBQUFZSkx4QkQzaXZOelA3QjMrK0RQZE9qZGhWYXRLemZmZmtlaEo0eVNrYWhYZEMvaWhvQ0NKYUhhaFZQLzRYYWt5Ym93RVJVYnFCM0pQVlhBLy9QRW5Pc3BaWUVTNGhGVS85eHNBQUFBQUFNNmQwV1BXbExURWc3S2hSVnVSekV6ZGs3MlF5cFhrdk8vbldFbEJoTzQ1ZDVrcEtYTHN4NS9sNER2dnlxblZheVh6V083MjJRS2VwYmFLUkpXV3lOWXRwY3lBbXlXeVhqMEpzQkwxdkVwYXRWcTJkZTlySDRONE5xRTFxa3VkSDc2eFo5SUJBQUFBbUdVOFFWYzJYZHREVWxhdDBWSE95ZzY1VnlyY2Q3ZU84aWY5eUJFNXVYR1RKQzlmSVNtYk5rdjZzV09TbFpxbUh3VzhLeWd5UW9LS0Y1ZndDeHBMa1NhTkpheGFOYnN2djFSU3ZxWHZUWEp5MlhMZGs3UFN0L1dYU28rTzBCRUFBQUFBazF4SjBQZTkvSnJzZitwcEhlVXNNREpTcW4veW5qMUxDTUJaQjk1NVQvWSsvbVR1amxnTENwU2FYMzRxa2ZWNUx3SUFBQUJ1TUw0SFhTblorYXBjTDhuTlRFNlcrRHZ2eTFQQk9BRFpPN3J3UjlrM2JtS3V6ejhQcTFWVElzNnJyU01BQUFBQXBybVNvS3NxMEVXdnZrSkhaNWNXbnlCYis5d29KemR2MFQwQThzeEt5STk4KzcwazNIWHZPVzN4aUxybEpydGFQQUFBQUFCM3VKS2dLK1h1dlAyY0J2dnB1L2JJMXRqZWN1anpMM05WekFyQS84bzRjVUoyVFpna0NmY01rYXlVVk4xN2RpSFZxa3FwMkd0MUJBQUFBTUFOcmlYb2tmWHFTdkhZcmpyS25VeVZYQXg5U0xiY2NMT2NXTHFNUkIzSXBjeFRwK1RncDdNbDdvcXVjdWkxdDNKMzV2bmZBZ0trM0gyREpEQTBWSGNBQUFBQWNJTXJSZUwrbG5ZZ1VlSTZkNU1NNjg5elppVU5vVFZyU05GMkYwdVJDNXJZN2FBU0pmU0RRQ0dYbFNucCt3L0lxVTF4a3JSa3FaejRkYkZrV0hGZUZMSGVZOVhmZWswQ0FsMjdmd2NBQUFEQTRtcUNyaHo1WVlHOUYxYlN6MkZHTHp1Y3pRejhQd2ZleW9FbGlrdXRPYk1sckhJbDNRTUFBQURBTGE0bjZDcUoyRFBwYVVsOCtYWGRBY0FMQXNKQ0plYlZGNlY0dXphNkJ3QUFBSUNiM0YvREdoQWdGUjRjSWlXdW93QVY0QmxCZ1ZKaDlFaVNjd0FBQUtBQUZjZ21VM1VtZXVWeFk2VG9wUjEwRDRBQ0V4Z281UjRZTEdYNjlOSWRBQUFBQUFxQyswdmNUNU9WbWlvN0h4c3JSejc2UlBjQWNKTmExbDV4ekNpSjZ0MVQ5d0FBQUFBb0tBV2FvTnVzYjUvNDNnZXliOElVeVV4TzFwMEFUQXVKcVN5VnAweVVvczB1MGowQUFBQUFDbExCSitqYXFlM2JaZWVESStUazhoVlcwcTQ3QVRndUlEUlVTbHpiUmFJZmUwU0NpaGJWdlFBQUFBQUttbWNTZENVclBWMk9mUCtEN0pzOFRkSjJ4TnV6NndDY0VSQVNMQkZOR3R0TDJpUHIxckU2T0tZUUFBQUE4QkpQSmVoL3kweEprZU8vTHBiRU45NldrMzhzc3hOM0FIbGdKZUdCUlNLbDJHV2RwTXl0TjBsay9mcDJVVGdBQUFBQTN1UEpCUDEwcWZ2M3kvRkZQMG5TYjcvTHlZMmJKRzNMTnNsS1M5T1BBdmkzQUNzaEQ2dFZVeUlibnk5RjI3YVJvcTFhU0ZDUkl2cFJBQUFBQUY3bCtRVDlINngvcXBwTlR6dDhSREpPSEpmMGc0Y2tLek5UUHdnVVhvSGhZUkpVdklRRWx5d3B3U1dLU3dDejVBQUFBSURQOGEwRUhRQUFBQUFBUDhVMEd3QUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQUZUdVQvQUVpNFBoc1dEcENoQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI2MTI1MDU5MWIyYmM0NDU2YjcxOTBiMTdiZTkwYmIzMCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo2LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjE5MiwidHJhbnNwb3J0cyI6WyJ1c2IiXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMiIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA0LTA0IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJlV0JNIGVGUEEgRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTgwOTI2MDIwIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDQtMDQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTA0LTA0In0seyJhYWd1aWQiOiJmOGEwMTFmMy04YzBhLTRkMTUtODAwNi0xNzExMWY5ZWRjN2QiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImY4YTAxMWYzLThjMGEtNGQxNS04MDA2LTE3MTExZjllZGM3ZCIsImRlc2NyaXB0aW9uIjoiU2VjdXJpdHkgS2V5IGJ5IFl1YmljbyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjo1MDEwMCwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImY4YTAxMWYzOGMwYTRkMTU4MDA2MTcxMTFmOWVkYzdkIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU2VjdXJpdHkgS2V5IGJ5IFl1YmljbyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTgwOTI2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhYWd1aWQiOiI4OTc2NjMxYi1kNGEwLTQyN2YtNTc3My0wZWM3MWM5ZTAyNzkiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6Ijg5NzY2MzFiLWQ0YTAtNDI3Zi01NzczLTBlYzcxYzllMDI3OSIsImRlc2NyaXB0aW9uIjoiU29sbyBUYXAgU2VjcDI1NlIxIEZJRE8yIENUQVAyIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjlEQ0NBWm9DQ1FERVIyT1NqL1MrakRBS0JnZ3Foa2pPUFFRREFqQ0JnREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFnTUNFMWhjbmxzWVc1a01SSXdFQVlEVlFRS0RBbFRiMnh2SUV0bGVYTXhFREFPQmdOVkJBc01CMUp2YjNRZ1EwRXhGVEFUQmdOVkJBTU1ESE52Ykc5clpYbHpMbU52YlRFaE1COEdDU3FHU0liM0RRRUpBUllTYUdWc2JHOUFjMjlzYjJ0bGVYTXVZMjl0TUNBWERURTRNVEV4TVRFeU5URTBNbG9ZRHpJd05qZ3hNREk1TVRJMU1UUXlXakNCZ0RFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRTFoY25sc1lXNWtNUkl3RUFZRFZRUUtEQWxUYjJ4dklFdGxlWE14RURBT0JnTlZCQXNNQjFKdmIzUWdRMEV4RlRBVEJnTlZCQU1NREhOdmJHOXJaWGx6TG1OdmJURWhNQjhHQ1NxR1NJYjNEUUVKQVJZU2FHVnNiRzlBYzI5c2IydGxlWE11WTI5dE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVdIQU4wQ0NKVlpkTXMwb2t0WjVtOTN1eG1CMWl5cThFTFJMdHFWRkxTT2lIUUVhYjU2cVJUQi9RenJwR0FZKytZMm13K3ZSdVFNTmhCaVUwS3p3akJqQUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpRUF6OVNsckFYSWxFdTg3dnJhNTRySUNQcys0YjBxaHAzUGR6Y1RnN3J2blAwQ0lHanh6bHRlUVF4K2pRR2Q3cndTWnVFNVJXVVBWeWdZaFVzdFFPOXpOVU9zIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUxRQUFBQzBDQU1BQUFBS0UvWUFBQUFBQkdkQlRVRUFBTEdQQy94aEJRQUFBQ0JqU0ZKTkFBQjZKZ0FBZ0lRQUFQb0FBQUNBNkFBQWRUQUFBT3BnQUFBNm1BQUFGM0NjdWxFOEFBQUMrbEJNVkVYLy8vL3c4UERYMTllK3ZiMmxwS1NrbzZPL3ZyN2EyZG4xOVBYNit2cTd1cnA2ZUhoZlhGeEdRa01zS1Nvakh5QXpMekJOU2t0b1pXYUtpSWpTMGRMWTE5aURnWUg4Ky96WjJObDRkbmN4TFM2WGxaVzZ1Ym40K1BqbzUrZDRkWFlsSVNJNU5UYXVySzMrL3Y2NHQ3Y3NLQ2xaVmxmdjcrK2pvYUhrNU9RNU5qZnI2K3ZnMytCbFltSldVMVNvcHFmSHhzWW1JeU05T1RwU1QxQS9QRDA0TkRWOGVYclcxZFg4L1B6ZTN0NkhoWVV0S2lxOHVyc3ZLeXpqNCtQdjd1NWZYRjFuWkdYUjBORW5JeVRoNE9EMDlQUXJKeWhhVjFqbTV1WitmSDFFUUVIRnhNVEt5Y3EzdGJhaW9LR05pNHkydExYdTdlN0d4Y1d4c0xDZW5KeVJqNUNtcGFYUXo4K1JqNDgvT3p6RXc4U1dsSlJWVWxNbUlpTlRVRkdVa3BQOS9mM0l4OGVJaG9aSFJFVmtZV0trb3FLZW5aM1UwOU5oWGwvVDB0SktSMGQ3ZVhra0lDR0NnSUJzYW1wcmFXblYxTlFxSmlkcmFHbmw1ZVcwczdOWFZGVHM3T3hGUVVMMjl2WStPanQyYzNRb0pDVmNXVnFhbUpuTXk4dk56TXlibVpvNk56am41dWMzTXpUcDZlbFlWVlg3Ky90bVpHUmlYMkRPemMxU1RrK1ZrNU9QalkzcTZ1bzBNVEZ0YTJ1QmYzOU1TVXFHaElWZVcxdkx5c3V3cjYrcXFLaTN0clkxTVRMeTh2TGo0dUpiV0ZuS3ljbENQejhwSlNhcXFhbElSVWJjM055c3E2dXlzYkd6c3JKMWNuUGYzdDh6TURFdUtpdVpsNWlobjZDY21wcjI5ZlhKeU1oUFRFMkxpSW4zOS9kZFdsczhPRGx6Y1hGeWNIQ0FmbjVVVVZLWGxwWkxSMGgwY25KWVZWYTV1TGhEUUVDUWpvNmZuWjVKUmtaeGJtOWpZR0V3TEMxTVNFbGxZMlB6OC9OQlBqOVJUazdiMnRyRHdzSlFUVTJwcDZod2JXNU9TMHlMaVlwZ1hWN1B6czc1K2ZscVoyZ3lMaTg3T0RqQ3djR2RtNXVKaDRlcnFxcEFQVDZucGFiUTBOQ0VnWUorZTN6eDhmR3RyS3pBdjc5eWIzQ0ZnNFNTa0pGdWEyeTFzN1M5dTd5d3JxL0R3c09NaW91RWdvUGMyOXVZbHBlOXZMMTllbnZ0N2UzZDNkMDJNak92cmE3cDZPaWducDlwWm1kM2RIWEJ3TURpNGVGR1EwUi9mWDZPakl4dmJHM1cxdGFjMTJWNEFBQUFBV0pMUjBRQWlBVWRTQUFBQUFkMFNVMUZCK0lKR2hjNkhJMHQ4bUFBQUEyVFNVUkJWSGphN1Z4NWZCUkZGaTdDSFVrYVJBeTN3VUM0eEpBQVM3akNFUWdva1ZQa1RCaXlpa0NHeTRVVkNVSE9vSWFRY0NjWWdzZ3B5eEZBRVRjQ0lnUnc1VWdNdUFyb3hndFdGUEJZVjExM2Y3L04xT3VlZXRWZDNUTTFFU1ovOVBkUHB0NVIvYVc3dXZwVjFhc2l4SVlOR3paczJMQmh3NFlOR3paczJMQmh3NFlOR3pac1NLTlNRT1VxVmF0VnIrRnZIbDZpWnVBOXRZS0NGUlcxNjl4Yjl6NWZxNnAzUDBQSUhhUmN2MEZEeFlDZ1JyN2Q4Y2FvamlaM2pITFRCMElWSVpvOUdGWlJTVGR2b1pnaXZHWEZKTjBxVkxGQVVPdUtTTHFLWW8wMmJTc2U2WWRhZUNDdHRLdHdwTU1lOXNSWlVTSXFHdW4yT29LUlVSMDZSdXBrblNRNzJ6dE8rZ0hNTHZnUG5hUExaQ0ZkdW5ialdIZXZXS1NiOUVBWGlJcHh5M3Yyd3FSN1Z5elNmVkQ5c1gyUm9sOGRwSW1UKzhUY2FkS0JxUDcrbktZZXZ0VURLaFRwcXFqK1IzalZvMGcxME9qWk12NnhRWU1IRHhvU1AxU1M5SUJod3grdk8rS0p3SkUrL3oralVQMmplVlZFYjRZeE9yZUFzZU1TTkxmUXhQR2R2U1h0bUpEMFI5Ym9ubnhLN2dscW1JZ2J3V05lT2owOVNkK1QxNXJzRmVudVUvUWRiSEpUSDBnM3gxVTRwM3J6eE5wT2N5b0dPS2VqajcwSjZSbUpSajlsWmxKTmFkSjkrQ29hUGhQeEp3OGVuYU1VSWFKWUd4R1RubVVTTDh6K3N5enBHc2FhbnAxYWJZNjVRK05neFFUQmpTMUpEemJ6VTU2ckw4dDZycWlhbEhtcDljVG04Mk5OcjYya1BHOUJlb0c1bjdKUU5vNmNiMVpUbXdlR1ZESllMMXBzY1cybDJSSlQwZ01UckJ5WHBrbXlYbVplVjhJTEwvSzJqcGV3dWx1djlPWGhNN0ZrZHBnSjZZd1YyS3hUNXVOWks3bVJ4eXBKMHBWTVhpekE2alhZZGkzU1JLNmpzVi9OVk55WHJEY2gvUWlTWk1PZHlKbU9aTEViSkZuZnQwS3h3c3U1YnN1UWpVeWNGNmhKTjZFbi80cERTSG9EZWhNV2JsYjlvaHNnczdtU3BFbnJsWmFzbGZHYTRhdEl1SVg1NHcvVVZpSHBiZWdCYldlTzl6Snh3a095ck9lTTJHSEpPdGtCZGloY2pZcEc3bWpLcExlSWROcE9WczVFMTMwUjJiMG1TN3JzdXJ0R1c3SCtDelhhbmNja2piRDNLaWJmbVNZZ3ZRZVZ1WGRrTDVPdmxpZGQxbDZIV3pTU3ZPb3VrKzdvYVhKZnNiN0lkSStBOUQ1V25NSmRkQjI2Ukw0dnJBbUppWmhlMjRUMWZwYytpWlVQOEo3bzhhY0xTTTlteFlPYzN3eGtPTjgzMG1WdzlFbC9lYWFBdE5NVlE3N095b204V3hEVHZDRWdqVHFkZlp6ZlVHUzQzbWZTTGpScHYveVFJWTU3czB4Uml4V2Y0VjMyTTgwMEFXbjBJQWJ4am5GTTgxUzVTTHZRT2oySUorMGFpaDFteGFtOCtWdE04MWNqNlh4VUxPQWQzMmFhSStVbVhZYWpYR2owTnQ4SWtuamJlL2lHb3lPZGc0clZlTWRqWmczSFY4ekhqYnRGbVNDY0ZkL2hUWTh6VFc4amFZSzZTdDFrMWJ0TU05RmJYdEYxVGpEczBXdFA0bHRkU0VnbTN3Z1FVTU5KRnBCRzBRM2ZDUG9od3kzRVd5eEVYbGw2NVNha2RKWU5pckpZOFJSdmlUNm95d1drVDdOaUE4N3ZEREljNWpYcHBjaXJvMTQ1SENrN0VTNzA0RDhGTFpGaGdZQjBNaXN1NWE1UWdPN0tVT0l0MEd1dktPL3BsS2hmVnY1V1ZtNkxPc0pOMkRDVnlXTUxCYVJSMmRrRk82SjNZYS9Ybk1uN21IVEQ2cHd1Qm44ZXp4TCtNWjlEaGc0VXQ0UVRBZWwrcUNQS1FvNTkwVjA0N3ozcEhPN3pGNFdqbWM2ZHNJb09XaHNoQVJyVFlJNFRSYVRKQlZidVVjZ2M3MGQyUmQ2VHhqMkNDM1ZlM1ZEc0VzOHArQ0FQeTJ2VHlZbWNFaWE1ZUVhcm9nZzlrZXpkUXRKNElEbzdSM09zZ2taYzh5UTRrMXpGZ0JXSG4zMVhMMU1mNmxnazJqRVNaSmZ3bk1LSFJFZ2FOMTVscFJvaGpzY1hrQXVYa2hVdnNGaGRsNnVCbTB4azR0OHJONy8vSEI2Z1hzdzNJVDBERDhaM1RtclUvcU81SCtNTFBDbkZtZlN6SE5lcWNFL3l4Y2RhbWFVVUVSUFM1RVBMK2kvS1RqS05MRkU4QVgwUnFsclpYU2FtcE1sWkM3KzhLNUtjQ2FuZnhnUG5xM2dkSU1uY3poMUZpVWpQNlcvK2dMWktjeTdya005WlVZNXN4RnRIbUxTUVdCWUxDZWZ5MGo0eHVVRDJHcStaWWpnaXNrMDVqd3ZRVytjZUVOa2RZTk1qWmxPOVQrd1VPWGFRWDhaVzhla1I4V2o4M0Q4RVMwVEZ1enJwN1JZZkxVWUdacFBxUFpNTWM3UlRHbnVpWm9XdytPVG5kQldlV21VMkI1dC8rU1M2Zk55VFZYWno2cEZvNFlPZldzeDRjeW5xL0xJUE52WWxNNE5IeTRFTDdzbWM5UENVT3YxN2J4dFYydFBTdHZoUzZxclA5dS8vN1BQVVVya0ZuMHBEeG1abGhrK2F1Ky9vU0VlNUdkdXdZY09HRFJzMmJOaXdZY05HaGNYbGNCZStNTkZ1b2Rydy9yNnZUTjRSMUtWRHpDL0Z5cTNxS0hTWHYxbEtrUDVLNWR6SzN5UWxTSytIUEdwblZYOXpsQ0Jkb0hKK3d0OFVKVWdId3B5ZDgzMS9NNVFnZlEwNGgyN3lvVTUva2E2Y0FweGY5VGMvQ2RLbHNFd1UrcUMvNlVtUXZnU2NFNjc3bTUwRTZYL0M2bUxDY0grVGt5QTlFUEpkRW54WlZmQVg2ZmJBT2ZJcmYxT1RJTDBIcHNzalRYUHR3OVlrVFI4M3VzM2Vkc2xyMFpJeGNUUnhRWnllVzB4MXJEeGcyTHF2ejQ0N25qWHhXdlg4MzROMExpekF4alkzc2MrNGdYSkU4azZ5SFE3ZlVFbVVRK0N6aUM2UXVsUHk0bEVHbHhKOHZoS1JobzcwR3RqL0ZHdXlGQko5Rk85QWN1RjFkNTRHNUk2TUVYaDlpMFBGQ2VHNkdocU8zVTBrd1pOK0hqaW5tR3pXeXRpckdMQkRpN1VoVC9rZGdSdmRKUkwzS2YxZFdiQmpNMHAyd1pZalhRU0xaaWszeGJZeHA3Um1jZnBXMG9WbWFtR25ta1ZSVEpPQzRuSU1icE9wR2VRK2RsRnpCZkxlcnJXdDNXRXRzM1plTkpFQ0pqMFNubjFlTmJIcEJtak5vZWM3dyt0Mit6b2tUZlNZQWZyUGFja1lGRUphUjd6clp5R2t5WTIrck80VHViSU04bFMrOXBsMEg3Z0xlYVZpeStoRFZMMFFaWlUxblVkRmgyRy80bmUwMEVIdkYvSzlTeHhFZi85QVRXYWpQbVlQRGN5Yzd4RVpNTktUMVllVk1rTnNPWUpxZTNFcmRRNXdoMVJsQXN2ZjMrajhiaUlUZXROTGZzVHFmMUYxSnBHQm0vVFQ3bXlFUjRWdjh4azZKdmorVTkxdHBDOVp0d3hhMkVyZGRkbVJaQnE5RTlESjBMMnhQL0g2RGk1WmJZY3ZwRHVqcEo1dElzTi9VOVVQZXZGN1ZBeUwvalhwRXJ0dWN5dWtTY0ZMNDZBZmdSRjhEVi9RR3FTeUoxVFNBVnlDdlNCU1drSUQ3SENqb3AxTHZoRitRMTRGMy9kRVVCbnNEUXloL2QxWnZnSklzaDlQSkFDa3o4RU9qTHl4TUM3YzJkZGdkOFRzZmx5aUNzaEJlSWoyQlI5d2VwcnhmVXBkQTZmZDVQZjhnbmpJVmhla1psYnFvaHVjOTdPV1duWGFFRVBRYlRrbERtTUZiWEZEcG9uVXNUaVo4UmNuYXo2RVFBYzBWYkpidGlMdDZ1c2MwSWtaM3FaQ09nVWkzQ0M4R0xXYklkVDVLTkxTRmh1Wm9aYlVIVnpIcTVOeWdaR0diOG9TeUZmUmQ1elhxUFJ4VVExMEkwazNlQVpwOUQ4NGdiUWJ1ZjRpUTh2Mk81WitSWGEvbG9oMFNtVVFWSU52MUdJK0hvRGt4MHR0QmJoRlZlcTkyMGNMTTl4K3o5TnlxYnVNRGw2WU9XNVZ3ZTN5a2RZNEUzSURCQmU0MStXcTRnRXFMMmpDV1c0LytoL2hlUFZ6M3UzWDVPdldlU1ZXcEZHTVZGUE53MXFBelQ3elJGb2JtOUhHc2tQYmdscGNZdWlZdHpUVGViYjRwQXVSQkpCT3VZWkUyOVdZR3A5WmM4RVRhUzFPZ2syNzJyQm52YXVRc0lpN1l0cXNwVHBmNTdJQUlnVWd6WC82SWF4UlR2VmpvcE9lU0d0N3IwTG9qVHl1bHVobVIyTk9aa0JTSXA4b0YzeU55RUE0NzNFUXFucWRTZWl1MXRDWURGTzQ0NVhCOU9iQ0h0Q2hsRnFnNkxyNUU4YjNRcWRFSkx4SUpDQWtYVVBkQThRbW1HQlBtVGVISExXbW4rcHY2ZTlCcnAvTlRBL2FDTG1TV2t2TCsrNG9NK1lTVDR0TmhxbThidTdOZy9CVjhPcDBraGRjbGhBKzA5UjI2d0QvbDZRUy9RM3lsYlNXaFh0TzZ3YlcwT0luM3RRSVowSzRvcFR0OUMzenRCTjFNNlFteW1Ram01QU9ld0ZZMzFETE5la01UcUkzTlViVFVkbFZvcVoxMS9Mb3NKbTIvQjNsSjAxdVEzZnFMRlhMTkNaSkVkMjFXUlBMZ0llVk5DQnM0eUNFbm53d2hDbis0MzRHUEdDTVgweThodWxLd0VBWTYyZXJzUTRrVGs4ejJ2MUlvMW04WGpDQUJsY1RZUG9tR3gxMVFOOUw1VGRERlpEdks1RW9hNzdtY2g0YXlHcjRuTStCOThXWU52d2IvYXIxd3lJNkxraUdRV1ZYSkI5RHF6aGhxQUlDQjRrNHhKeDBDQVMvZEN1aTIvQzBQcU4xTngxcnY4WEo2RkMyZHRxdnJqLzRFNTNmVFh4TDZSY3lWaUpYMW1KSkxnYW1GQ0pobTBVR0RNaDBIVmdhN0hDZXdBa2ROTU9hVG9ieDR6UFlvM1JJZHo3RUFEcmxlY3g3enBhTG4wUFVmaDhtUjlXczZLdjRXK0g0a3NwKzFkMGxHdm5UbHIyV2s2djdYWTV6bjV0aTJLaVUvanVSMWpaSC9oZEs2dTZTWSs3YkdyYitCSldzMks3emE2b2xTWmZvMHBUVk15N21YV0wvNVpxWHFXaW1wM05GdkNhZHJ4NHdBK3R5eGRwWkR4OTMzVExoZno5WHFmc0tGT09LREk2OVZVdmR0bGJTVTl1Z3NuSDhWL0Y5bHhSdGZWTTdKU3hWZ3JNMWFWSVBWbCtDdjZPbEVPRytqMUJCUUZTcTZneXA3bjFOdG5vc2t4cnJXcFBXOXJXc2hKN2ZNU0xPY0xrMnN3UnU2c2E1UTBiTmR0SEJOVW9EdWZHNUI5TGtKLzQ1dDU3R1gyM0hnbnloMjFTcS9VajAvN1RTSDJ5U2tDbDdST1pOZWlhbWVZaFY2UVkxdU9xZXk5aWM3ajdBcThXeEk0VW1icys2OUQzRVo5K2tGU3o3bUIwVVYvS0c3Tmtldm1GUjdxeWpvemJsTmpYL0hFQlFlTXU4aXVpWTlwdCs2N3FyZTBBT3FUQ0FydTFwZjlPUXdvKzAwM25KM3pUa0FFZlVCSmEvb3J1SVhCclZIeTcvYnFHN2dkdTA2d3E3Q1ZGc0JWNm14aWhTTmw1NDZ5ZDEzUzdJNFc4NjNwSm1pSlBmemVsMzBrNXZ6OTd6T3hqcEZLOFB2dkE3ZmttRU9EcjBZRXo1Szd0N0tMd3lwdm5BTHZuK3BtSERoZzBiTm16WXNHSERoZzBiZHcvL0IyWkhJSjZEbTZUOEFBQUFKWFJGV0hSa1lYUmxPbU55WldGMFpRQXlNREU0TFRBNUxUSTJWREl6T2pVNE9qSTRLekF5T2pBd2Z6UFlkUUFBQUNWMFJWaDBaR0YwWlRwdGIyUnBabmtBTWpBeE9DMHdPUzB5TmxReU16bzFPRG95T0Nzd01qb3dNQTV1WU1rQUFBQlhlbFJZZEZKaGR5QndjbTltYVd4bElIUjVjR1VnYVhCMFl3QUFlSnpqOGd3SWNWWW9LTXBQeTh4SjVWSUFBeU1MTG1NTEV5TVRTNU1VQXhNZ1JJQTB3MlFESTdOVUlNdlkxTWpFek1RY3hBZkxnRWlnU2k0QTZoY1JkUEpDTlpVQUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6Ijg5NzY2MzFiZDRhMDQyN2Y1NzczMGVjNzFjOWUwMjc5Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNC0wMyIsInVybCI6Imh0dHBzOi8vc29sb2tleXMuY29tIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTb2xvIFRhcCBGSURPMiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEyMDYwMDMiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNC0wMyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDQtMDMifSx7ImFhZ3VpZCI6IjUxNmQzOTY5LTVhNTctNTY1MS01OTU4LTRlN2E0OTQzNDE2NyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNTE2ZDM5NjktNWE1Ny01NjUxLTU5NTgtNGU3YTQ5NDM0MTY3IiwiZGVzY3JpcHRpb24iOiJTbWFydERpc3BsYXllciBCb2JlZVBhc3MgRklETzIgQXV0aGVudGljYXRvciIsImFsdGVybmF0aXZlRGVzY3JpcHRpb25zIjp7InpoLVRXIjoiU21hcnREaXNwbGF5ZXIgQm9iZWVQYXNzIEZJRE8yIOi6q-S7vempl-itieWZqCJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnZqQ0NBV09nQXdJQkFnSVVQV0pYZjJWN0ZBdGM4NzVkRTRqUGFiaTVZQlF3Q2dZSUtvWkl6ajBFQXdJd1JURUxNQWtHQTFVRUJoTUNWRmN4SWpBZ0JnTlZCQW9NR1ZOdFlYSjBSR2x6Y0d4aGVXVnlJRlJsWTJodWIyeHZaM2t4RWpBUUJnTlZCQU1NQ1VKdlltVmxVR0Z6Y3pBZ0Z3MHlNakF5TVRRd09ETTNNelphR0E4eU1EVXlNREl3TnpBNE16Y3pObG93UlRFTE1Ba0dBMVVFQmhNQ1ZGY3hJakFnQmdOVkJBb01HVk50WVhKMFJHbHpjR3hoZVdWeUlGUmxZMmh1YjJ4dloza3hFakFRQmdOVkJBTU1DVUp2WW1WbFVHRnpjekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCS0hWcWJCQkRVMFZYSlVXVkh5N1M2b3Z5d1pUeDhsYWJCem1CNTRnRmc2OElyeVA1cGhDTVVQSUl2SG1ZRjVWK2xhb0RVdzI0N3FJNjNjZmVHald1eDZqTHpBdE1Bd0dBMVVkRXdRRk1BTUJBZjh3SFFZRFZSME9CQllFRk1LRFJtWWptVmJ1c1BYSG1GbllnbEZRNXZXcE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ3NRREp2QjVGY2E0cnlQT1ZaK01CQUlaem93K09WN1Qvd0JKOTkwNkhaWkFJaEFNVmJTd2Qyak5vSGwzU1J5aHJjZlFKcURvNTB2dEtGK0poZzA1dkhtT3AyIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVNnQUFBRW9DQUlBQUFCa1pmdE9BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRmlVQUFCWWxBVWxTSlBBQUFEYWNTVVJCVkhoZTdaMEZsQlhIdHZkNTY5M3ZTdTU3MzdyMzVzWkRjTXZnN2hKQ0lFZ0k3aks0RE80MkJFaHdkeDhJQkVtUVlNR0R1OXRnQ1E0Sjdnek85enVuYW5yNmRQYzVETndWS2wvVy9xMmFXZWQwVjFkWFYrOS83VjFkM1gwU1BCTUU0WlVqd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNRUVwNEJ3L3NIekp3WUtXeVpYSm55NW8vVjA2VjhtVFBWcUhNNTkyN2RsbThjT0dUSjA5MFZoZE5HalpvMDZKNTI1WXQ3S2xKdy9ycjFxelZPZUxIeUdGRFcwUTBjWlJUcDJhTnA4K2U2aHpQbzJEZVBOVFpxcjlLYVpJbGZmVHdrYzRSbk1FREJyU0lhT3JZdXlPMWJCWXhmT2lRQmZQbW5UdDdWbS9tWXZHQ0JVMGJOWFJzK0tLcFJkTW1BL3YyMVNVK2oxNWZkS2RpYk5XMFlZUHY1ODNUUzMvZlRQOTZhclBHamFnei82ZE5uYXFYL2tIeEZ0NytmZnZ5Wk0vNllmSmtXVE9rdDZ0T0pldzRlNmFNR2NNK1RKYncvY3JseWgwL2RreHZGc3ZqeDQvRFVxYklrU2xqenN5WjdDbmpoMmxhTjIrdU04V0R2WHQybzVBY2dZV3c2N0FVeWVNcHZLaUpFek44bU1aUmYxS0dOS21YTGYxQlp3cE8wY0tGc3FaUFo5KzdaNktWTW9WOW1DWjVNZzV3eHZScGVtTWJyWm8xWTVWanF4ZE42ZE9rN3RhNWt5NHhKREgzWTRvVXlFK3QyQ3AxMGlTYk5tN1VLMzdmMUErdm5TbHRHSFhtN0hSbzIxWXYvWVBpSWJ5dW5Ub21UNVRRclRmUGxETkw1aFNKUHFoZXBiTGUyTSsrZlhzeHhIdzVjemd5Szgrak04V0RzcVZLVXI2OUJGS3VyRm1xVmlpdmM0VGsydFdyOUE1NWMyUjNsRURLbGpGRGw0NGRkTDRnM0w1OXUwQ2UzRzV2R1NLeHIvUnBVbVhMbE5IaC9TcVVLVTIxSFpsZk5HR1VreWFNMXlXRzVPeVpNMWI3MHgwYzJMOWZyNGdGMzFJL1BIejYxMS9yNzc4UHlwZitUTFZTeHJBMC83OTQ2WmZHS2J5dUhUdmdyTnlhQ1pIUVJxWHk1ZlQyZnVaOE81c08zcEZOSlR6WXNXTkhkYjZRMFBUcFU2ZHkxNFJ6VTdGc0daMHBKUGlITE9uVE9UWlhpVzZseUVjRlF6dk42OWV1NWMvdDA1SmoyK2NtQ2srVkpQSEc5ZXRVT2ZmdTNTdFNxRUNlK0hWa0lSSUJ5S2xUcDFTWm9UbDM1c3lIS1pLekNiM0dKeDhWdW5mM3JsN2hwMzNiTnJoQkFnY3EyYjFMRjczVU5BOGUzS2RuVWEyZExsWEtGY3VXNlJWL1VBS0VGelZwWXVwa1NhMHpiU1dhZ3dBZ2M5b3dGYjA0eEpBMVE3cStYMzZsaS9EVHBFRjl6cXM5ajVVb1pOTDRlSFhiak0wOHZTN0NLMU9xcE00VW5PaERoOUttQ3RXRFlIWVhmLzFWNS9aaS9icTFhVk9tY0d3VnowVE5TYXFjV3pkdmZwUS8zd3Q1VG5maUZPVEtsdVhpeFl1cXpOQk1takFPSTJZcjZ2QnBrY0lQN3QvWEsveTlRT0VDK1ZYRDhwOUdab2xlWjVUSFR4N1JIYWdqelowOTI1WExsL1dLUHlnQnd2dmc3YmZjbG9yVHlKd3ViYTNxVldkTW05YXplMlM5MnJXU3Z2OGVmVkwyakJsVVpzN3gxMUZSdWdnL3BZdC9HaXl5WXNEV3VGNDluUzg0VXlkUDlneFdTWWgvUU4vZU9sOXdxbGVxeUw0YzI5b1RVZWlzR1ROMGJpOFlCTHJIaHh4MWlzU0pWRXFaSkRHalRRNWYyYkVqMFc0dG1qYWhuRDI3ZHI3eitqOEp5SzBOcmVRT3BFa1U2TWhHU3Byd1BRNzhicUR2Q3Nhb0VjT3pwRXRMVVpSZnJWSkZ2ZFRQa3lkUGluNzhrZG92NTZody9ueDZoV2tXTDF6QTBJNWFJYnc4T2JMZHZIRkRyL2lERWllOFFmMzdxN05sVDFoZXgzWWV3OXc5ZTNhM2J0RThXY0wzR1N5bFRaVnkzOTQ5ZW9VZnp4RFJTb25mZTFmbkN3NGxxS2pEbmJDLzNyMTY2SHhCUURQcFF0YUJoRTl1MmF5cDNzQ0xQcjE2WmcyTVZGRmR4N1p0OUdvL1owNmZtaG9WVlRCUGJ2b21lMDRTZTZkN3VuNzltczdxUmUwYTFSM2FRM1hmenA2cFY3OHM0VFZxcUU2SHM5TzVRM3U5TkphVks1WW4veUFoZ1d1Uzk5NWR2WEtsWHZxZk1Ydld6TGYvK1E5ZkIvRStIVVE2dmZSRldMdG10UklldlZqaGZIbjEwajh1Y2NJcm1EZTNvK2QyOTVkdVdqV1ArTWRyZjlOZi9EQU93WHBDR0QyUzJMbDl1ODd0UmMvSWJtNDd0aExDNnhIWlRXY05RckhDSHdWenVWYmlZRDhwVkZCdjRBVUJjNDdNQVFFenh6VjltdmNGaVhhdFdoSkYyek9UNkxabXo1eWxjN2lJdVI5VDlLTkNqamIvTUVXeTgrZk82eHd2UzYxcTFaU2VhY1l4bzBicXBUWWVQSHg0OE1DQmVQclArREI4NkJEVmErZk9tdVhUSWgvcnBTOUNwM2J0c21WTVR3bDBHWFZyMXRCTC83akVDWTllMEtFV0ZMSnY3MTY5T2pqcjFnWk16UkcvQmJ1eW9oTEs2ZDQxNkpqKzRzVmZjUlFoZElzMS83Qm9rYzd0eGNSeFkzR1lqcTA4VTZxa1NkaWQzc3hGOFkrTE9GVEJjYzM1N2x1OTJvVmJSVGpWUnZYcjZ0VXU3dHk1WGFSQWZ2dllqNk1td0Q1Mzdwek84VkxjaTdscjFZUXp1RzNMRnIzaXQ2UnRxNWFFQSt3Ukh4dlBPUThIN1Z1MVV0Y0ZRcHZISHdZdHZMMTdkb2U1TGlURVUzZ091bmJxU09zN2lySW5iS0pVMFU5MGJoZXRtemZQbHNIWDh3Vkw2ZE9rMnJCT1h6RDBKRnZHak80ckdlelVMV2FmUXhqcDRSQVVIeGNvNENnblRiS2t0Mi9kMXF0ZDlPblZ5MUZ6TEttNWY1am55ZDdkdTRuMzdQbXBKTzdpd1lPNGF5RXZBY0V0M2w0RjZtbVNKenZvbWt2NExhaFl0a3d1djQ4bE9QK3E1eGQ2Nll0UXRsUkpGYVJrREV1ejRJOCtsd0J4SGk5MXNxUU8wNHhQcU9tbTFLZkZuaHZtcFVqMHdXT3Z1MTUyNzlvWmxpSjVDSGRIUW5ocmYveFJiK0NpVTd1MjdwRXE5YWxRNXZNQ3VYTTVTaWFxYVJBZXJyY001T3FWSy9seTViQ1BNNVU3dWhGODBOK21SUXZIdGR6UXd0dTBZYVBETTJPN2xRTW5adUxQaVJNL0h6MTZoUCtyVjYxTTd4OHNlYzRseEo5TGx5NGVPUno5MC9IaitudEl5cFVxcVh3c1IzVGt5R0cxOE5EQmc5R0hEcW5Qb1huOCtMR3FNUDlmZEM3aDBNRUR4NDRlalk2TzE0NytFNGpNRDBkSGsvVDMvNHc0NFNWNjUyMjN4UlBYZFdqVFd1ZUlINkd2cktpVU1lekQyVE05TGlHVUxsSGNjYkhCbmRLbVNybDc1MDY5UVNEWHJsM0RpVG11eXZBMWJhb1VyUFgxeW9FOUFtZWF4RmxYbTl0aEZPcTRyTXJvaFY0NXhOUWZBMHRsZkZaQ2VJMGIxTmVyWFl3WU50UXhsS1VqcUYvYnV5UHdCTXNtcml1WU4wK3loTy9UWVJHemtLdzQzK2MvUHc2WVM0QUQrL2VQSFRWeThzUUpFOGFOblRON3RsNXE0OEtGODQzcTEwdVRQQ251M1ZkZ2l1UkozMyt2ZE1uaVM0S0g5M1JTS1JNbnNuWmFxVnhaYkNCRjRrU3FQdFN0WkxHaTM4OFA1Y1FlUG5pWU1rbGlOdWRrNWM2ZWpRTDFDaSt1WDc4K2F2andhaFVySkg3M0hmYXI5a0pLblRRSlZTMWF1QkJ4cjhvNVpPQkFqblF5eHpwNjlDOFhMcWlGYnE1ZXZUSjZ4QWlWYy9USUVaY0RaekllUFhyWW9XMGJ1Z01HSm1wSDdPV3pUNHN4U05ZNVhPemNzV1BzNkZHcXdDRURCNmlGTjY3ZmFGQW52SGIxYXFUV0xackhDWTh2amc1YkpVU0NTWjA4Y1VMbkM4bnBVeWN6dXE2czBKcU9KZGt6WldqVHNvWGVKcFo1YytiRVI3UzByOTdBUmFQNjlkMVJMdlVmTm5nUWE0Y1BHZXkrWmtPd2QvaXdSeCsyYmN0V0ltMTdUdHhScFhKQkorNmpKazVRZnNhZU1xY05HemRtdE03aG9rUGIxbzdhVWoxVW9WZUhaTTNxVlVUQ0JDa0V0OEdtNW4wQlMrVktlb05ZUmd3YmdvbG5TaHRHLzFYaWt5SjZhU3hZS3RhTUdUak9BaDBXK2ZQbnlyRmkyVktkMWNicFU2ZkNVdnJtNjFWQ2V4NmJwMHhSTUUvdW16ZHY2bTBDMmJSeG8ycHRUQ1ZIbHN6QjducmR0M2RQbVpJbENKZG9xR0FkTkpVdmxEZTN5czhlc1NnT050a0g3eStZLzcxYTZLWmxSQVJtUUxZTWFWS25TNU5LTC9XRHdqOTQreTFPazcwMzUrZ3dodVNKUHVnUkdhbnpCVEoyMUNoNkJBcEVyaVdLK2hxWkdPMjlOLzVOM1hMNjcvN2pRNXp3VnExWVFTZm5hZmMwSFAyVzU3eUNneG5UcHptdXJGQmpBcDc4T1hQWVMxWkJoZDRtbHZ5NWN6azhobWRDZUUrZmVqaWV3OUdIT0htTytyTWo2K3IydGkxYk1vU2xjV1RnRkk0WjdXSHJQYi9vN3A1TDZOU3VuVjRkU1A4K2ZUeTdqSlJKRWgwNWNrUm5jbEc1WEZtSDlYQ3FvaVpOMUt1REUxNmpHbzFndFJYNzlkM2VrQzR0bS9OZnRTMEpjM0hmRnRlZ1RoMDEwNUExUS9wK3ZRTnVlMWkrZEdueUR4S3FiVW1VUTdIMkdJSGFFc1lUZ3VvTllsbTZaSWwxMGpuZFZFTjVCc1RHWjZzK2JJNkJIZkVLMVZhdlhtWE5KUlFwVUVBdkRRVHpvM3BxSktrU21UbEc5MUYzYXE5UFU0dW1UWlF2NGR5MWFlRjlrL0QxYTlmd1lPU2hHVG1LNzJiSFhZVnUzYXpaaHluMElKemp5cEkrSGZ2aXY5b1grVmxMMktKejIyalNzS0hlYjZZTVNqV29UcFZqcFRqaFFlWHk1ZDBESkN1eFM4NzNycDA3ZEc0dkJ2YnJTemI3VnB6bUxoM2JVMHVIWFhJT0dKUG96ZnczelhCVWpqd2NvV01KaVM3QWMzejRjWUg4amtpU1JOT3NXN05HNTBEYk9iWG1yZVFiNXRYMWlPNjZkT3JnY0VjMFpiZE9uYzZmTzhlSWdwSFB0cTFib2laT2JOYWtNV3JueEx2clNja1Z5bjZ1aTNNUmJDN2h3dlBtRWo0dldkeWF0L0JaZWRpSDlOYmhOYXFQSHp0MnlxUkpYMGRGbFN6NmlUcEdhdVgybjFVcVZGQnFaKzFRZnlCZ1lRM09PUmE4TjM2RDBLaEt4Zks0Qy9iQ3ZpaTJZTzVjMTY1ZDFSdjRpYmwzajhGem51eStBMUY1cGtWRm5UcDE4dml4bzhlT0haMDJkUXJOYUxVa3N1RTBQWHJrZkM0RTYxUjVxQUErVFMrTmhiRkFxV0xGTEcxVFBXd01FUkpJRXdST216S0ZveTVoTzJyaVJyWGhyQm5mVUhNVyt2UmMwRnZQa1YyNjBBZVJoODNKcHBmNjdtdVBzRUllVG4yVzlMN0duQm8xZWZpUUlYaUlISDVkVVJQODNwblR6dnY0NnRTcXFScVplaTVhdUFERHBtWElURWRtUlNnQndnTU9SdFhETTdFOWpyNURtMVk2dDR1YVZTbzVlbkc4N2E4WGZuR1ByeHozamhISlVMZzlBdzNCMktCUTNqeDJtNllRZC9nRXk1WXNZVGhxejZreU82SXB3bXZWMzF1Sm5kTFhQbnp3UU9lSXBhaHJ3RWJpQktpK25NUlpvVUZaNHFpMlNpeE1sU1F4S3RYRnViaHo1elltcUd4RkpTcFBnU0UyZ2M5TEZMZjZOUTZFUTU3c3VtMzYweUlmcTVwVHcrM2JBdVlTN2o5NFFJT290VFM0M2ZsY09IOUJqZE9vQmdiZ2VNWmkxamZmRUxIVFVBVnk1YlFMNzlhdFc3bXlaczZaUlRjcDR2bWlhMWU5emtiZG1qV3NEcDF5dnVqbW5JYjF6VWI0VFpsZDkrenVqTjhxbGkyTDNhdk5xWHpxWkVrR3VCNlBLbDJ5aERvdXVveEZDeGFxaFF6REdONnprTk5CM1R5Zll1T2dXS3NhMzNKM0c5YXZ0MGF0Vktsc3FWSnF1UVdkcHJKbmltM1hXZzhwTFpUUzFPYWNMejZUR1lkUkw3eDIzNisrSWdER05wekNnNklmRmFiMkRpTzJKM29SakVibkRpUXNWY3A4Z1liSU9PVCsvZnNqWWlkWXJZUStLOGMrWkJEUnVLRmI3WXpPOSs3Wm5UZDdOdXNZU0J4QXhYSmwxVloycUk5Ykp4enFtVE9uZFE0L0N4Zk1WeUdOUFdHQ216ZHQwamxpY2FqaWhSS0hSc3R1MnJoQmwrWEZucUJ6Q2M0dXdLSmxzd2lzVm1XbVh5OWJxdVREUncvMXVsZ1lSSDJVUDYrcU9lVWZPaGh3QWVEQytmTVowK29yUnF6ZHMzT1hYdkhzMmFJRkN6Sjg2R3NaWHd1WDhYYlVBL3IxcGZVdVg3Nmt2L3VmdWtUZVZrUDU1eEo2Nm5XQldMYzBrSmtQOSsvSDZCVityTGtFVE5ZUmJQZUk3R29ObnVsck1JWnIxenh1QmtxZXlCY2txMTdEZmhjK05xQ1dJd0QzSmRaQi9mdXA4SUZpQ1l6MTBtZlBDTWVVMVZFck5LYVgycmgwNlJLbldKV01SUFhTV0hDRHJMSVNWU29lZUZQQnVYUG5QSVFIZ3dmMlQvTCt1MjVUdGhKQ2QydnZ4TTgvRVEvWUZVdnRhVXBXYmRtMHlYR1JrRVJzemFyTGx5KzdCMGdZMXJEQlF4aE80SnJ0cTJpSXNxVS84Kzh0anZGang3Z3ZiSEMwN1ZzN1BUTTFkUGlvUEhpR2pCbDY5TytuYy9oeHp5WEVKNUdmc1FUbmpGTjE1blNBNE4xczJ2aGljd2tiTjZ6SDZGVlRZTjlWSzFUUUt3STVjZUlFRlNBUDlsMGdUNjVyVndQQ3dnc1hMaWkxczdaSWdmeDRYYjNDSmp5Zi9qOHVySmU2T0hmMnpQWHIxOVhuL2Z2MnZmdnYxK2tPcWxZb3I3U1hMblhLWVBjay9melRUNnBpL215cDVzK2JxMWNRU1Q2eXpTV2tUclZxVmR4ZGJLZE9uVklETUJLbm5zUDNITjRUMlliNW44YmdGR0F3Zk5Vcm5qMmpibXBZU09zdFhyaEFMNDJGbmFyOVltK0QrdmRYQ3hmTW02Zk1pZDFSbjYxQjdrQW85MWtwVlNWS3RsOW0zN3RuajNLekt0RlpGUC9FWTliYVczaHc3dHhaRGlPRTYrUDBseXNkNElLWExsbE1sMnpQVDk5ZnRhSTJFZUlpaHlsVDQzMTc5akRFVW1HR2xjaEdPN0lKTGVWUUZJTHYxcW1qS2xEeDhPRUR1MmRYaWE5MFlIZnVla3gyNHhBNE85bnk1TXFZTDNmcUFuay95WjZ0VWFxd3FKejV6eGI1L0ZqaXRMc1RKTGpXdXZQdVkwZmQzVVRvUktFRXhvUkpPN2VIR2dOYmpCanFOWmRRSitoY1FvbWlSVlFNejhrT0ZtN0FtdFdyVll0aFR4L2x6K2U0MVhoSzFDUnJ6RVB2d0RoVHIzajI3UHo1OHd3aVZFMHlwd3ZyMU01NWg2ZWJzcCtWWWxqSUIrSkEyb3JFMlE4MjA0TmVpaFFxb0xweStzUXZlOFJOc3R2bkVoZ0ZuVHdaZC8yY1FhWWFHckFLYXdrV2gyL1lzRTcxWWh4MTN1elo5VkkvV0FzMnd5cjZSR3VhUVRIbnUyL1ZWaFN1N0UxQnY1UGI3MzVwNmtwZTRaV2lmbmh0ZFVab1VzWitldW16WndqVjZsSXBtVGJSS3dJSktqekYxS2lveE8rK1k3K1VaRTkwbi9aZXBIL2ZQdFlJUkNWT0NSYW0xdGFzVXBsbXRhK2xtVW9WSzhySmNKZzR3OExaczN5emZMNDcxZ092a1hMTytuelpTeFdvWUhqdDJDbUpveDArZElqT0VVaVg0Y1B5cGt2N1pmSTBpOTVJOU10ZjNpQ2QvZXViUC8vcFh3Y1QvSFYvZ2dTazY1MTc3andjVFZmbktKTXpweDRVb09mT0dKYkdIUTVRdHk0ZEF6cUZFSFJvOHdKekNjdVhMbFhQMTlGUTlETHVSLzR0cGs2WlRBWnlZaE8xcWxYUlMyTVpOM3FVVWp0cksxVndldGVLWmNvb0t5ZlJnTVVLRjc1N0wramtPNEUwUmZIaDN0Mjd5cFV4S01pZjIrbGo3VVIyNmF3T0dYTXFYN3EwWGhvNGw4QXFTMTFYcjE1UmdTS0pYajdFZzh2V1JCRW5oWmhXTC9Vejg1dnBxcStoY0FZN2VxbWZuRmt6YTNlWE5tendBTzN1SGo5NWJBOFUwWjQ2Nlk1RWVLbFVSNkw4YjJ4MzhJNFpOVkpWaHBORlp4RTEwZnN5OVhPRUIzZnYzaTFWckZqV0RFN2pKbEd0NHAvRUJhL1ZrVmFnUklrODU4NzVUcTJkUDNlT1EwVWtqdHloT3RyTzZ0R1h1eDdNY1hTV3AwK2Q0dGdjSlZBbTJYUU9Hekc3OS8zU3ZNTzVmeVcrOEtmWFQvL3R6WjllZSt2dzM5K08vc3UvRHliNHk0RUVmenBUc3VLdFJYcVNxa2RrcE9ONFVaMTFtMzlNVE15QytmTUw1TW50Y05Ra3VycVdFYUdlZUxEd25FdVlHalZKcnc2a2FZTUdhbDgwdUNQS2NFRGdwM0x5djBsOTU5eDlnenExbGJRUUFCMldYaG9MSTJwNlVneFUxWWZxNFFmbXpkV256OEd3d1lQMjdQRTlrakxuMjFucWVtT2ViRm1MaEx6cHZGUDdka3A0bk9LaWhlSUdUcXRYMmVZU2JOY2VKNDdUVHhWU0pVNm8zUk02Nk5mN0t6S1FrL0t0dVFURndZTUhyQ2cwYThZTVZweU1aN2FXTThoWEMySFhyaDMwK3l5UGYzSUl6N3Bsa3NNcGxEZVBYdXJpK2NKVGxDajZpU3JPa1loUHJJUGhTQndhQ0V1Wndycm42TlRKVTFUUmtjR2RVaVZOc24zN05yVkpyeSs2cXdhMUVuMEozWnRhQ3hYTGZHNTEwbGJDZXRhdmk3dHZPMmIzM2wrYXR6djAzLy9jbitDL0RpYjRuK2kvdlhuNGY5NGhSZi81ZFpZYytYZmk2MlBqNGdRRjRiNURlSFNXN2htYlloOFhkb2lIeEpnYlM5STVnbkEvSnVZVDExd0NwLy9nd1lNNmg0MWJ0MjU5bEU5Zkw4RzNEeDAwVUsvd2dyaGROUWdOTldIc1dMMDBsaXJseTZrS3MzYWsxd1RVZ3Zsek9XV1c5dmlBcDZXUDBLdTltUDcxVkNVUHdqT01SQy8xd202UkgrV0xldzR3MkZ4Q3c3cDZ5cEhsbjVjb3JwZDZ3YkNmUE9Ua3VNYU0xSE1KRnBuUyt1WkNNRHpxdVgzclZyV3dmT25QVkZQZ1MzSEZhaUgwN3gwWHRWR213OUY1cG5kZS85ZDQyMjBTNGRYMW95SHNidmJNb0E5OHhsZDRVQ2hmWG9ldGtEQ1gzYnQ4RjhldVhybml1TEpDSWxSUTJ5b0s1c2tWK2cwSU5IU3RxbkVCVXJ2V3JSeHF4NlZzM3F5dlFLNWZ0ODR4cENUUldDV0xmNm95WEJzNzZlaTdxWWdlN1hvakhmclR2MWpJaU83ZU9sM1VvSUVEUDhvWDF6blJjenVPbEVOejMvcHc3dXhaQmxTV21hckVoa1VLZVU4WldkeTVmZnZqZ3M2cnB2UTRwMDdHWFJXd1lQUkZBS2IyUW1jYzRyYjF1M2Z1V0RYUDhHSHFaVDhFdk0zSk41Y1FPOVBnYThaTjNtOUEycmh1UGNaazcxQndublNwd1c1ZGFoV0JqL1dkb3h5Wk1qWnQxRkF2OWFKYVpUM1ZSR2RxbjdzUG5Fdm9ycGVpamMrMW5MSmxTTit0YzZnWW5xR21QcTQwcVpjczBuTUpGb3pUMUZpSmZsODlzYjE5MjliVXlYeFB1Mk04Tk9tRjgzRnpwME1IRFZMQ1k5ZnhlZEdCRzB2bkdPZmM0TSt5dklEd3RtM2RRdURuTUhTRXAweGh3L3IxRGhuUUJYNFdxd0dGTlZrWkxER2V2SG9sYnBCQWRPY1dudVhOQ2hmSXAwNk1sZkpTUWxqcVg2NWZ1OVloY3A5UGIzK04vdk8vTGIyUm92OFBYaTdCVCtselBicXFMMGt2V3ZCOUd2L3RRc2svU0JnVCt4S0VZaDg3Si9FNHpMMyt5TXJCb0g1OVZYL3Z5QnppNlNIWXMzdVh1cnBvSlhaWHN1Z25ENzNlT0hqbzBBRTF3Q1Boam43KytXZTl3b1ZqTGlFNjhCNlJDK2ZQV1hmenNaYkFVcTl3Y2Z2MmJmb09lNUJQTzZNWnZUcVFabzBhcWFjV2NSMTlBMitGc2ZQNDhXUE1VZFVOdnpURTVyY0Q1eEowc1AzMDZST1dxUHdFb210L2pMc0x3bzAxbDRCRWo3dmU2Tk8vVHgvcVJnYkdDKzM5Tng2M2JxN3Zqc1M2bWpWdXJMSXBMT0dSb1ZYelpucnBpNkNHaUZTR2dldkpFMEZQbGs5NEJEUHFTMmpPbmptZDNrdDRlM2I3TEhMYzZOSFdIUlVxY1ZUdFd3ZmNZTDExNjVZUTBTYm53N3FrcTdCQ0l5c2h2RlVyVjdDS3FOcGVGSkxMaEQvT2xmT2J0RmwrVHZEWFE3aTR2NzhkSUxtL3ZYa2d3WDhkUzVydWJxeVhPN0IvUDZaQWg2ZWNDWGEyWkludlB1RExseTQ2Smc5SktaTWs5bnd1QWQrRjBUaDhGeXBpRE9ONTRWdXhhZU42RHNTK0NZVjhYdUpUenp0eUhNSmpXS3RYdURnUmU4bWUrdmptRWdKdk1UbC83cnhTTzJ2OWN3blBlV3FoZDY5ZTlrYzBPYm1kMmpzdmRUNTUrdGp5TnZqWUVFOFZIRDkyVE8yZEFna2ZkdTdRMTM0ZlBYcWtxc1IvTFBYSDJDaWRhTnk2eW9yd1ZxM3duWFJQQ0JPczBSckNPM1BHMlQ0L0xGbXNPaEV5NU15Y2lTWFc1QjVuMzNIejlLQisvUzNodFE1eWwxa0lyTGtFQ2tjYXYvenlpMTdoSWdGajF0Zis5TjlSRXlmb0JjSHg5SGkwNWs4LytXVGRyRWxqZFIrTmxlakFwc1IyWUlvblQ1K2dGb2ROcThSQ211L3g0d0RMbzVrY05tM2RJWTBkV0t1eTVNMmRJM2V1c1FsVFhQenpHeWYrK3ViaFFNbVJDRFVQSnZqZkc3UGo1bzVhUmtSZ28zYTNSamVocmpjY1BueUl6L2JESkR3dVZ2aWp4NjRiblJRRCt2WnpPejI4S0c1TjUzQXhmUEFnZWhsN2ZtTHNSdlc4SDVrOWQrNGM3YUFhRFpQOWZuN2NVVGhZczNwVndGekNyWUNlNHZ0NTg1VDkrZm9GMzF6Qzg1LzZJeHhORy92S09jb3NsRGVQWTM3Lzd0MDdWRXpWalU1aDQvcjFlb1VMNjU0aHlpSC92YnQzMVBJSEQrNnJtV2dXY3BoV3NQM280VVBMVklpa3ZwOGI5S2czckZ1WFBvMy9vcWgvVWs0dnRYSCsvRGxPQnhrNGtJSjVjaE41cXZQT1dXN1pMRUpuaW1YZW5POHlodm12RmZtdFN5K05OOVpjQXZ0S21jUTVzVzRuQVNNQkRveVVJVTJxZ2I1NTVLRDl0SHVNUjd0d3B0VmFGT2pRSk4ySis4Wk9nazlIZktnU21lMzNweXF3ZUhYOFZsTENZNFNndkd2dTNEbFRGc3piTlVYWThkZmVPczBvemlXNTZMKzhRY3g1dHJ6elZRSVJqUnJRN3ZhU2ZUN25NMTlNdjJYTFppcGpYMFhNWExKWTBTZGVUdy9CblR1M2FRZEhQWEhVSVdiRCszMzFwU1BrNXF0am1zUUNuMUE4ZG14RzE5WWsrSE5HVXlaUFVsMEFlM2ZQSmZodVhJeGRXOFUxbHhDTStYUG4wbk9yU3VKNEhTUERHOWV2YzBaWWhkRVh5Sk9icjNwRklEdTJiV1VFcXdyQms5U3FYazJ2d1BsdldPODVsd0FWeW55dVRJVk4xR3VqUEJrL1pvenF4VGdGMmYwT3pRMGRsdEl3SnFwYWtnOG9CRitpYzhTeWRldG0raHFWQVZIY3VhMDdpSGd5WnFTZVMvRDFib0VUR3c0U0RCN1FYeGtCTmNQSkVsMlVMdjVwMU1TSlAvMTBQQ2JHTjhGNjllclZhVk9uMEZrNm9qNFN0dHZPUHlsNXhldktTc3JFaVo2NHdpM0xPT3lKV241YzBHTlNXUFZoOXB5NHFVdVhMdnJjSFJGN3Z0d2xzbWJiOVgvZk8vK1hONCs2SkVmeWpmSCsvdmI5YUkvbkE5YXZYK2RRRjRsNGtxaDc3R2pkZGxaaWJCRDZ5WXpHRFR3ZVI4SWlnODBtbDhla0FodVQzbjNhMTFQMGFoZU42dGFsRG1Uem1VdWExTWVQZVQrYzJyTjdwRHFWV0twYm4zVnExVlEraDZwMkRIeFA4N2pSbytxSDE5WmZYRmdQdWFJUTY0S3pZdVdLRlphUExaZzNENEczWG1FajVuNU1sdGluQjJMckh6Y1B1V3JGY3MrNUJMQ3VhbUtaRENNOUI4REhqeDhueEZXaTRyaTZCdDVjWVdGTnhGc0pZNll6MWFzRG9ZYXFRQnF6YytEa2hCc2kvNjFiTnVzdnZ0ZlM2aXUzN0s1ZWVDMjkxSXNFN2R1MmNjeHIwODFnMmVnZUswK1JPQkd1REttb3FqalNCMisvZGQ4ZnNXeFk3N3pBU0VON1RtSXdzcUkwaDBRSk5uYnRjTnJveVJNbnNtUkliNy96azNOVHAyWU5qaTF6cG95TTZQb21UVTFzZWZ3MUQ4bEZ2L1lXanU1Q2s2Q1A4Rjc4OVdMTzJQY2pXQW5yWDd4dzRaaVJJOXp1cUlmcnpsMDdwMCtmVXRleTdGdHhhaDN2K2JXd3hrVld3cXNjOHBwTFVOQm9XSU5xTkRiazFOTFQ2WFUyNnNaS2k0NWp3ampuWEFKTnA3cE8xbHIzN3l2b1ZnakdDdVRPNVhuSjFCcnhFa3phalF3V0xWcEloOHNxYkViZHhlSUF3K0RrV2dmTHFXL1JOR0Nlczk5WFh3Vzdpb2dydzZqVWh1UnhqekQzN05xSmNWcGRjOWIwNmI3czRmMzZPVUlNdFJlVmZQcFBuV3JuRHUrNzIxbzFqMURpSVJ0T2ZsdnNESVNiY1dQRy9QUHZyNjFjc1Z4Lzk3MW1xcXBxWlBvYVJ5TTdTTUI0MUtyUUN5V09lZFNJNGFvVTN5MFJnWDZNM1FlTFp6SUVEdk93bFZyVjRtSVBpM05uejJabHJCVm96WnpDOUZrekY4eVJmYzIvUHNEUnVXTkwwcUUvL1hOL2dnUzNmd3oxWGhZb0Z6djVZeVVjQlU2amJLbFNEbFZnVzR0Y3QvazVpR2pZVUowdGUvSS9SZVhzVUc3ZHZGblk5WDdiWUhNSkZqU1JWVDdWUStlTW54M1hiMHFYS0o0N20rK0k4Q0dPdVlTWSsvZXNCK1FKWHVoZjlBby85V3JYNGl5d2xncFhMRlBHL3NyM21sVXFLMmZMS1NQUVBSdjRpR3J6cG8xcE5OYnkzM0ZEMW9aMWF5TWFOZVM0ckROSU9lNW5jNzdvMGxVZEY3MWJyeS9pNWhJVWRQM0tWTkFBQmthQmF2bnQyN2NRTUNHVjNaQTQ2cVZMdkg4UFkrdm16U3FnVlFuai9NeXJtMUFROVNSNjUyMlZrLzBTQjgwSWZMWGNvMGNQeDQ4ZHd5cjJTRHAyTk80NmF1SFlxOHFjb01rVFFsMDNTVkRzWTkrekNQWURpRS9pRExWdEZmY0llZE9HRFJ4WFZud3p6a0Z1Mm1vUjBWU2RMWlVTdi92T2RhLzd6UytjdjVBdFUwYUg4TkxseXhPZUx0UFByNzFGY3VoTkpjTExvNGw4dDJVL2wyRkRoamc2Q3l5dmFzVUtHS2lqTlhCSG5uTUpkazZmT2UyK2JzUUpkby8wRGtjZklpZW56Y3JHZmdsN0hqMTBQbXBnSitaZUROMi9GUyt4STd3SDhRZ2FyaGRlRzI5V3UzcTFmSDVEWVMxOW91TjUweXRYTHJNWFZUMTY4ZjAyYWQyN2V5OS9iazZZRG4zNVFCQ090VkU0ZG0vdE1XdUdkTzdYV0tBRWxRRnJZL1JPdklxR1B5M3ljYktFNzZkUGs4bzZ5OVNLMmhiTXJSOE10L041aWVLcSt5T0Q0MUljVEpzNmxXT3hDcUZBREU5RllYejJGNnRkSXA4enAwL3I3dVlVOTJKaTJOREtTZGRqWFZiMVpPamdRZGFWWk45ZXdqNWtDTmF3WGgwT2tJZ2F3V2RPNTd1Mng2cFVTUlByYmZ4WTEwdnhxS0hmdCsrYlRwZzhjUUtCSmMydERrYnR6ek54NXJKbFRQLyttMjg0cHVTcGhLTUxSOHhyVnEvV3F3Tlp2WEtGTlNERTlBY1AwQytsY0xCaiszYUNJcXMrV0ZYS0FubEhKRXA1NmM5dmVJN29TRGk2c3hWQ0JkWjJEa2RIRTV3NGp0ZXlUbnVpMjQ3UGk0MmJOMjNpNmZRY0lVMzB3WU5xK0c0bExPL3pFaVZDL09hWjRzYU5HM1FLOUFMMkd1YkpscFdSZ2k5bHlheU9oUk5STUU5dVJ1WjZNei9uenB4UlYvYUlHNUdaNHdYcDM4NmNpYXJ0cmUxSXFBdGgzUGVQK1MyZVBJNmJTeUN4WDFVVGE0bEtWQXdqRHZZQWVQSFk1d1B4U0o0R1U3OU9lRmlLNUk2VFFqMXA2dFRKa216Y3NFRnB6MmVacnQrS3NZTnRxMEw4dTh1bGx3YW5aVFBmZFc5cnYreFJIWjFsNTVSRGhocTJwME90aHlUSUhIb3VBZUltMEFsVld6VnJocE9sTzBFMk5EU0pBSUNkSVE4KzAzem91Rk83ZGsrZUJwZ0lYU1pTWkplTUFhejA5ci8rRWV5Vk5UZXVYMC9xZnprUEJTWlArSDZ3K2E3Wk0yY21mT3ROcThBMEtWUE9TL0RheVFUL2RTREJmM3VtdlFrU1hCa3lTbThjUDNETHRKMjFDOCtFdldJVGQyTXZmNGRnODhhTlNkOS96OUVPOUk2TytLcFhqeThTdi9ldVBVK0tSQi9VckZwVnIzNGUzMHo3T2l4bGN2YkNvTVZuQ242OVlSL0tMQmc0K0Z4TnhneU91WVNaMzB4WGpjbnhzcUg3OHVPamg0OTZkWS9rWUltZDJKeGlmV1ZteVl5OWNwb1lycnQvdHVIdW5iaTVCSHZLblRXTHJ5WVpNK0JZL05mcWloL1l2MDl2RXdqZDJldi8reisrUmtpUkhGOFJiRTZmd1I0Vnd5YnBHaWdXcFRGdVZMTXZhOWV1OGRtZS96U2x0VDFoNEdEbjl1M3EyaXh0UmFjL0wvYis0ZEQ0bXRwdjh6U0NhbWU2U1BvZ245bjRoOFNNWUhWV1A3dDM3WHozMzYrcmMvcldQLytobHdiQjQ4NlZTNWN1SXNJSlk4ZE9qWnJjSTdJYndkSzBLVlBHamg1MU5NanJRKzdkdXhkOTZCQ1JyajBkREh3RTA4R1J3NGVQSGVWZjlLMmJRZWZ1T1N2UjBicFkvazRkUHZKMHovNzcrdzdFZUtZOSt4OGNEM3FYUURCK09uNzg2TkVqVnAwOUUwZDlJbjR2ZW9Mang5Z2lvRUEyWjVuOTZ1NmxTNWM0Y0h1ZUkwY09uMzdlODNzT01PVkIvZnZWckZxRmhGUEZYeldvRTE2eldwWElMcDJuVFoxeXduVjNDNkVtSGw3VjU3VHJWUVYyNXMrWlEyZGZvMHBsSXFBcUZTczByRnRueldydlcwK3R1UVFTZmlDMS8xSmNrdmZmWTZnWlhxTjZoelp0ZmxpeU9QVExxbW1XUXdjUCtodmhDRFZ6WHdPM3MyRCt2REdqUnJaczFqUnE0c1R6NS9Xc3crM2J0NVh0c1RsSkxYUlQ5ck5TNmpLeXo5M2x6S0dYeG8rbFAvelFwRUg5dXJWcUpuenJqVXBseXhEU0R4azAwUE1GS0RFeE1kR0gxT0VjRFhHcFRQRUN0NHdKZ2gzN1hNTHY1OGRQM05EcDBDUEV1YnU1Yy9RS280andoSmRrMGNLNHVZVFNnVGZsL3E1bzFsaGZlc1hkaFhoTzV4VWp3aE5la21aTkdpbURadnhUcmVJTHYzSDgxWEQ1OGlWMXBaR1VLVzJZL2Vac3M0andoSmVrUTlzMlNuaFowcWNiMkMvZ3BUVy9INW8xMXIxRDNoelowNmNPZUZtdFdVUjR3c3Z3K05HakVrVS9VVE1CR1lPOGtOODR2Lzd5aTkzZDJSK2hObzRJVDNnWkhqNTRVTFJ3SVRXcGxUWmxpcTJiQTI0bCs1MkFIMVozaXZuY1hlemQvTDhUUkhqQ3kzRGx5aFhyY1o0ODJiS2V0ejNFL1R2aDRhTkh4SlpxbWpGejJyQ1J3NGZwRmI4UFJIakN5N0JycDM0cEVFNHZYNDdzN2g5VU1FNi9QcjB6Mjk3MjlYdnJHa1I0d3N2dy9meTUxbHlDKzljT2pQUGd3VVBMM1dYTGtMNVZzNWQ1aWNOdmlnaFBlQm5hTkcrZU5PRjdZU2xUcUNkYzlkTGZEYjE3OVV6MHp0dFV6M2RiNGdjSlEvemd0aWxFZU1MTGNPYk1hZjk5ZjBjUEg0NzJmTGpFTEVjT1IvdHUxbE0zb3dYL3BUU0RpUEFFd1FBaVBFRXdnQWp2VlhQa3lKRktGU28wajRody96NmpnN2x6NXZUcDAyZmdnQUg5Ky9jZk1YeDRzQnZlTDErK3ZIRGh3dDVmZmxtM1RwMWFOV3RXckZCaHllTEZlbDBnTTJiTWlJeU1QT2Y2NlkvWnMyWkZkdXYyb2s5SWVITHE1RWtxWEs5dTNSclZxemVMaUZpNDREbFA3aHZoNnRXck5NV0FmdjBhTm1oQWkxVW9YMzdwVW8rZm1INVJidDI2OVVYMzd2M2lkeE9QQ085Vk0yN2N1S1pObW9UWHJ1MzUzaFE3dmIvNnFuR2pSclZyMXNRNE1HWCtqd3Q4Sy92RGh3OEhEUnhZczBZTkpGZW5kbTFTN1ZxMXlwVXRHMHhDL2ZyMnJWcWx5azgvL2NUbmJsMjdmdldWZnY5c3I1NDk2OVdyRi9yQnpmaUEvcXRYcTBaVk9UcHFRbXJSL0lWZlRmbWJjdi8rL1MrKytJSW1wWkoxd3NOSnRHclZ5cFhkVHh1K0JLZE9uNjVldFNyOWp2NGVFaEhlS3dYdmhKWndCZlMxMjdZRnZMSExBYUxxM0trVEZoeHovLzdkdTNjWExWem9FMkd0V3RiYkRXNWN2OTRJR2phc1g3ZnVoQWtUamg4L0h0cUZQbmp3b0VPSERtM2J0aVViMWNBeDFxOVg3L2FkTzArZlB1M2N1WE9yVnEzNHJMTytGSmN1WGNLYW16UnV2SGlSNzczQWNPclVxZS9uejFlZmZ3OWN1bmlSOXFTRzZHMzgrUEVIRGh5STU2dWM0OG5xVmFzby81dHZ2dEhmUXlMQ2U2Vk1uellONnh3OGFGREQrdlZuaHJ5L2tiNjVRL3YyRGVyWHg2RFZrdW5UcCtQWmlELzVqQ3lSSERiVXJsMDc2MGRqUW5QcjVzMklpQWkweDdaOEpkejY1VmZmUmZacjE2Nmh3QjVmeFAwRzA4dXhZZjE2RGcxL29yKy9Xa2FOR3ZWWnFWSS8vdmlqL3U3aXp1M2JxQ0tpYVZPUzUwdkIvM09XTFZ0R3o3Z2krRXV2N1lqd1hoMHhNVEdFWHZpY2t5ZE9ZT3ZEaCt0M3RIbHk0c1FKemlKT3ozcDU4NDlyMWlDODRjTjh0ejRSeitBQUNWa2ZCM25OcnBzcmx5OFRWaEcrNnUreG9GdVdNempSMzczQWR6MTNCS2lFMTlYck45QWRPT0k2WE83Tm16ZjFsMER1M0xsejVzd1pCcVdPdDVzcFdLcy9QWHYyWmE5ZVRSczNEdkhlbXU2UmtUUlg4MmJONHROaUhDODdQWFAyckdlbjVvNUx5Yy9Bb1VlUEhyUkFpQiszc0NQQ2UzV3NYTGtTRS85Mjltdyt0Mm5kdWlQT0ozaHdlUDc4ZVhwb2F4Z0duVHAwUUhoYnRteTVlZXNXbnBEUCsvZDV2OHZFazAyYk5sSGdKUC92SkM1ZHVyVDBaNTlOR0QrZXo2dFdyVUxoaTJMalF5eTRRdm55dUZQMTFvYWpSNC9TUnpCeVkvUlNyMDRkQWxxVnpRMmVtWnlFME5PK0RuZ1pIakNxL0x4MGFVYVZSNDRjb2RvMXFsV2pIZFExbmlGRGhsUW9WNDd5dXdjcWY5ZXVYY1RSYXI5VW02SHBjdjhQTSt6YXZadWFUNW8wYWVMNDhaVXFWdVJ3R1BkU1lSUkZwMWE1VWlYS1Z5WFl1WDd0R3VNNjZxYkd0eUZZdUdCQjNmQndhcWdHcTFVcVYxWXZDNlBES2wrdTNPYk5tMXUwYUZHNVlzV2xzVzlQSk1obnB6V3JWeWMvZFNDUW9hZFFxMElqd250MW9EVE00cTYvbjZZRHhreUR2Zk1jRm43L2ZZTjY5UWIwNzg4NGhQTWQyYTJiaWkxeEVNdVdMbVhibmtGKzVqOFlhOWV1UldBTC9HL1VYTEprQ2RZOGI5NDhQdi93d3crK0FHbTU3NjJzSTBlTVlQeURtL1Z0NFBlNlpHTmZzMmZOUXBsVUFEY2I0alVxTTJmTXdGakpQMnBrd0UvYmJ0KytuWjZDWXJIajhlUEdJVFlPcEV2bnpqUUlYb2pEUVpQc2FOMDYvZTZnbFN0VzFLaGVuU1VFa092WHJ5Y3lwMWJiL1VQaXVYUG5zcTI2T29VYVI0OGVqVVNuUkVXeGtQSlhyVnk1MTZzelFrNm9ya083NTd3V21tQ0VZam5HV2JObXJWMnpSaDJ2V3RXL1h6OUc1blNYdEZXbENoVlcrcHVyZmJ0Mm5GRHl6Smd4WS8yNmRYendsTDBuSXJ4WHhQNERCK2ptUjhTK1hmanJxVlA1R3VLVk9ITysrdzVqNGx6UzVaUFRkNEliTmxRUkYvSkFrOU9tVFZNNTQ4bWdnUU94cXVoRGgvZzhkTWdReWp6amp4NkhEUjJLTVYyOWNtWGh3b1hoZ2RjaHYvUlBVV3lKZmVSbitmTGxOV3ZVV0xNbTFDOW1vUVJsaTIzYnhQM2k3SXh2dm1FSjN1RHc0Y05xQ1Y0RjhiUnNvVi9OaWpLcG0vTEd1M2Z0d3VFZ1lDdTQ3ZFd6SjVuVndBeHQweXlvNk1BQjM5dTBidnRmR284ZjR4QW11MTdMYVVHdDZBNm9odjd1eGVoUm85Z3BEbDkvZi9hTUtyRkVmYWIrdEF6ZGg0cFUrVDkwOEdEVzBtV29ERUFkRUtmKzhqeEVlSytJUG4zNllEMWZmZm5sWUQ5RVZsaVBGZUM1NmQyN055ZDd4UERoaElJRU52YkxCZ1A2OWVPVXMxeC9kMkVOalFDdEtya3lMRVJzNnZjbENad3d4SFArb0toUDc5NllGR0ttVEd6YUdzQmN1M2FOL0sxYnRXTER2bjM2OU92WEx6SXlFbEhObk9YOGJSa0hpM0dudFdwUlZOKytmZFdTcU1tVE1VcjFBNmJBcUJXYmJ0VXk3czNUaE45a0lJcm1NM1dqSnVwM25oWDR4b2ltVFpXbnBkMncvbSsvRGZqNVFmb2c5aGppeWdyUkFXVUdlOTB0TUpiRHg5SW02c29URUdOVHBiR3g4emMwQlNWY2k0MVFHTkg1SmlwdHI2TS9jZklrK1lmNlIrRHhRWVQzS21EQWhvOXExS0NCYnpCUXRhb2F0NkJEdkkzTzRRSUxJNzVpZksrLzIwQXFlSThRSG0vOCtQRUVkZGdCaVFHSkNpazdkT2pRdm0xYmpKN2V1bFBIam0xYnQ3Ny80TUdUSjArNmRPbUNXZE1Ma095L1phbmlRelE1WU1BQWVnMUFlNmdpaE9BdENHVXhVMEkxNVZTN2R1M0t3VjZPZllzdXpvcER3NCtwci9EMTExOWoyWHYzN2lXUVpyQkVSS2RYNEZ1ZVBLSFJDQUxWVndhOVNQcDY0R1ZKSWxKMkYyTDhPWERnUUk0bGhNZmJ2WHMzWndUSHFMLzdmc053bzg4Sis3M29rYU5IK1V3N3FGVXdaODRjRHVHNzcrTGV6MGtrVEd1SGRxcDJSSGl2Z3RGanh0QWxiOXl3UVgvM3h5cU14WDNYVjd6ZTNCNFRFOU9oZlh0TzVJWEFuMDFVNEFEcG0wT004WWhqOFRaNEtoS1d1bW5UcHZ2MzcwZEVSTEE3bEhiN3poMGlJc3JuTTI2RXp6MTY5RkNXWkxmNDFhdFhVd0hDUy8zOUJSaytiQmpHZXRBZkVIYnMyTEY1UklUMWN1dGR1M2Y3YkhSRzNNdkl1M1hyaHB4UTV0TW5UMWpWMGZiN0pPY3ZYS0FjRmRIUmFFU2g5aUJXd2VpTzZDREVKRGg2b0JlZzM5SGZYU2lYdTlQbUVyK2ZQNThsRy95LytFZFBRUjJHMm5ySkJRc1dzSGJqSnYwanA3QmswU0tXckY2NVVuOS9IaUs4MzV4TEZ5L2lUT2p5NzhYKzFMTkNSVkJxbE9MQTV5SHIxeWVEcHl4OVU5VjE2dUQwdnBrK1hTK0taY0w0OGNwV0hGeXl6U1VRSnZGWlhTOUZETFZxMU9qbEg5aE1uVElGODdLdXJCQ3NrcTFyNTdnZjVsYzRmcHRTY2V2V0xjZjhGY0xERUJFZWFzRmxkZTdTUmEvd1Z4S1JyN1RaS0R1bGZRamtIajk2eERBU2I2eFhQSHUyYmRzMmFrVlh3bWZhaWpLNzJvcUNwMCtmRXZYWnV3dzNLcEpFMjR5YzlhSll4bzBidDJYVHB2bno1dUV6N1I2dmIrL2VMRkdEOFBsejUvcGtabXRZZkIxcjFkU09nczhjVkloZnFIY2d3dnZONGFSeVNsVFFZbWZJNE1GWTlrbXZId2xTY3dtUlhic0dtNWlhUG0wYXd5M0VTZnl6WmZQbUF3Y1BFbm5TcVZldVZNbHp3azBIVHY2ckY1czNiK2J6QlA5djJUQ3N3cVJteFU3bE13U2xxcGIyMnJkclI1ZXhPamEyUEhUb0VGN2FjbHgyR0ZWV0tGZnVpOGpJRmN1WC8vckxMMWdoZGZQMU5YZnZVaDkycDdTdEdEdG1ERHZkSDJ1amRDNG9FMitzdnFJNnR2M09QNHBidjM0OUZlQzQxT1Y3QWtJMlZDSzBlT29mZ0tuck5BUUlhaERyaG5FbVlRS2w0YmgyN05peGQ4K2V5Wk1tc1NOMHptZ1diOGtITXFqZjdoc3paZ3c1OGFMcU5ycUpFeWJRTEZ2OVExQUZJUWxOemVhcllydVBnWU1HMVEwUFYzTWs4VUdFOTl1Q2Y4RCtzSXhmL2JlSjJKazdiMTZsaWhXWGVjVnlkS2lNQXdjRS9pSzhBN1NucmdlZ1FDeTdUdTNhbU02WHZYcDVYdTVmdm13Wis1cnZ2NEZyNWZMbGZHYnZmTVp1K0d5L1ZvSDJLTGFkLzhvN2VzYlFzVGsxbjhhNDBlRnRMTGJ2MktGdWdLUXliSUpENXBCVm1McGh3d1oyWVhmT3Zxdnc0ZUZXZzV3NGVSSWp4cjJycjN2MjdLbGFwUXBGVmF0YWxacWdLUDRqRlZZdFhyeVluQTQvajhkalgzZ3oxRnV1Yk5uMXNYTVNia2FPR0VGT1ZVbGZpNFdIMDJLREJnNVV2L0U0ZXRRb2xyQ2NYVkFhd3VOQTFJYmRJeU9wakNPVTNibGpCL1VrdjVyMGE5eXdJYVhwZGZGQWhQZmJRbHkzZE9sUzY0cThIUlN5Yk5teTdkczlmaDd4eElrVFJHNjdZaThEQmdOVElOdjQ4ZU9qb3FMd2FaNitTTUhRSHhtb3U4L1lJNStWR2UzWXZwMDZPTFM2ZHUzYVpVdVhLbGQ4NDhZTmZBVWVnSkJzVGZETGhnb0drM1FIWkNhTXRHNHJ3WWV3dXlPMnAxRnh1VCt1WHYwZ05vckdUVkdIWTdhZmlTWEt4YTBSK3RKNmUzYnZwbmRRTjFVZVBIaVFuQ3hVMlN3dVg3bzBmdHk0TWFOSFQ0bUtzdTZ3OCtUczJiTS8vdmpqaUJFanBrK2Zqa1J4WEhxRm40MGJOdzRiTmt4NVZ4cld1b3hFaStISjNUMGEvbkRSb2tVb2R0ellzWVNwTTIyajF1Y2l3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hNRUE0andCTUVBSWp4Qk1JQUlUeEFNSU1JVEJBT0k4QVRCQUNJOFFUQ0FDRThRRENEQ0V3UURpUEFFd1FBaVBFRXdnQWhQRUF3Z3doTUVBNGp3Qk1FQUlqeEJNSUFJVHhBTUlNSVRCQU9JOEFUQkFDSThRVENBQ0U4UURDRENFd1FEaVBBRXdRQWlQRUV3Z0FoUEVBd2d3aE1FQTRqd0JNRUFJanhCTUlBSVR4QU1JTUlUQkFPSThBVEJBQ0k4UVRDQUNFOFFEQ0RDRXdRRGlQQUV3UUFpUEVFd2dBaFBFQXdnd2hPRVY4NnpaLzhQTXAwaEQvVWQvL0FBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI1MTZkMzk2OTVhNTc1NjUxNTk1ODRlN2E0OTQzNDE2NyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOmZhbHNlLCJiaW9FbnJvbGwiOnRydWUsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3IjpmYWxzZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiIsIm5mYyIsImJsZSJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZmlybXdhcmVWZXJzaW9uIjoyLCJwcmVmZXJyZWRQbGF0Zm9ybVV2QXR0ZW1wdHMiOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wNi0wMiIsInVybCI6Imh0dHBzOi8vd3d3LnNtYXJ0ZGlzcGxheWVyLmNvbS9maWRvIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTbWFydERpc3BsYXllciBCb2JlZVBhc3MgRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwNjAyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDYtMDIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTEwIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNTczNDAyYWU5MDFlMjdjMTE0MzhlYjhhNDRlNzQ2ZWM3MzcyZGVlMyJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI1NzM0MDJhZTkwMWUyN2MxMTQzOGViOGE0NGU3NDZlYzczNzJkZWUzIl0sImRlc2NyaXB0aW9uIjoiU09MSUQgd2ViS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlIYkRDQ0JWU2dBd0lCQWdJSVlPTjZiL2FvR1k4d0RRWUpLb1pJaHZjTkFRRUxCUUF3Z1k4eEN6QUpCZ05WQkFZVEFscEJNVEl3TUFZRFZRUUtEQ2xNUVZjZ1ZISjFjM1JsWkNCVWFHbHlaQ0JRWVhKMGVTQlRaWEoyYVdObGN5QlFWRmtnVEhSa0xqRXBNQ2NHQTFVRUN3d2dURUZYZEhKMWMzUWdWSEoxYzNRZ1UyVnlkbWxqWlhNZ1VISnZkbWxrWlhJeElUQWZCZ05WQkFNTUdFeEJWM1J5ZFhOMElGQnlhWFpoZEdVZ1VtOXZkQ0JEUVRBZUZ3MHhPREV3TVRreE1qRTVNRFZhRncweU9ERXdNVFl4TWpFNU1EVmFNSUdSTVFzd0NRWURWUVFHRXdKYVFURXlNREFHQTFVRUNnd3BURUZYSUZSeWRYTjBaV1FnVkdocGNtUWdVR0Z5ZEhrZ1UyVnlkbWxqWlhNZ1VGUlpJRXgwWkM0eEtUQW5CZ05WQkFzTUlFeEJWM1J5ZFhOMElGUnlkWE4wSUZObGNuWnBZMlZ6SUZCeWIzWnBaR1Z5TVNNd0lRWURWUVFEREJwTVFWZDBjblZ6ZENCUWNtbDJZWFJsSUVGMWRHZ2dRMEV3TVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBTVhJZDI3SVZEdFBydVdVcG5PWnlyeDlWUEN4WFFxTzdzZVBtUGtLeUNEbStmaFBaSXBXcGkyNDUrOVZSc2h1MUtudFkzV1hOaTAvd2ExeFZZbGhrejNUV3V3RjBhSktoeWNUWEZQZzFwRjBkR3gyd2NoYXdISDR0UDM4U2wrMi84ZDNuenNIZ0NaSE8zMURZRkhtUTJvVVhnUzZLU1VMQUJXMFRKN1NnaHBnSlloc1NjeEkxYkpXSDAycW9WUEo1eUpvREE3N1BvcmM0cHhPTGx0UmFBK3c3NitZa0V6RW9lNyswbEdoOUZacFRNQUJUemlXMVpQL1R5SUR3OEQ4eVBOK25jMFFHakJrNFFFcUtVYlN0YUkvMGE3VSt0TEpRSUh6b25lSEwxZ0oyWGo5aGszM3VmNjRBZnliWXJsdFNyT0dDcWJsdGltR1BDY3BZcjFwYlZrWExsOUpvVFNtblUzbVN5UGVpTXVWcDFURms3Um8vUERzY2FnRWIrdWU3c2F1RTVoZklYMkZDb1hQcldJU1JCZ0NVS1BOQTZoUnhYRHRHQmpKMVhva0JzRWViZERId29rN2wrY3JJMm5jeUVNSTFNQTQ0NVBXRFJrdDRwVDRRNUFlcmZzYzUvdzhIRnZjTnJWMFhUMkNuY011OXBGS1VFWUV0YzJWUjdwbzNUWkdNNmExSmJDT2tNRy82MzQwLzZzMlNCQmtzTVFvVVZJOTZSU2kxYWRtYS9BaGVuQkZaV1lTWkhpamR1RWFQSjFsNXhQWUxtRk5ydmFyUExHN3l3SjFYN0VGU1JLV0FzbmJUSVZWM3ZFaGFqM2lIL2FtTDdEVVhtT2xLM1lCRXNQQzN4MUxEMFkrTlBzOTYzVVlEOUJMTUhKakdNUTMwRHBkZ01CZzhtZGJBZ01CQUFHamdnSEdNSUlCd2pBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUI4R0ExVWRJd1FZTUJhQUZJRG9VSG5tM2RhajkyUmhWdjFIck9LdkNkRnVNRFlHQ0NzR0FRVUZCd0VCQkNvd0tEQW1CZ2dyQmdFRkJRY3dBWVlhYUhSMGNEb3ZMMjlqYzNBdWJHRjNkSEoxYzNRdVkyOHVlbUV3U0FZRFZSMGdCRUV3UHpBOUJncGdoa2dCaHZwc0NnSUJNQzh3TFFZSUt3WUJCUVVIQWdFV0lXaDBkSEJ6T2k4dmJHRjNkSEoxYzNRdVkyOHVlbUV2Y21Wd2IzTnBkRzl5ZVRDQjNBWURWUjBmQklIVU1JSFJNSUhPb0RTZ01vWXdhSFIwY0RvdkwyTnliQzVzWVhkMGNuVnpkQzVqYnk1NllTOU1WRjlRY21sMllYUmxYMUp2YjNSZlEwRXVZM0pzb29HVnBJR1NNSUdQTVNFd0h3WURWUVFEREJoTVFWZDBjblZ6ZENCUWNtbDJZWFJsSUZKdmIzUWdRMEV4TWpBd0JnTlZCQW9NS1V4QlZ5QlVjblZ6ZEdWa0lGUm9hWEprSUZCaGNuUjVJRk5sY25acFkyVnpJRkJVV1NCTWRHUXVNU2t3SndZRFZRUUxEQ0JNUVZkMGNuVnpkQ0JVY25WemRDQlRaWEoyYVdObGN5QlFjbTkyYVdSbGNqRUxNQWtHQTFVRUJoTUNXa0V3SFFZRFZSME9CQllFRk1RbDZnT2djNFYzNFlzcHBWc1Rzb2ZUSHd6V01BNEdBMVVkRHdFQi93UUVBd0lCaGpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQXVDZ0J3R0xObitEcWFiV1RZL2RQeDhmcVRKOERlOXRnNHl2eU1vVFR3OE9ZRTBPaUdxQm9ES0U0d09hY1lKd2Irc3A4b2FiYjRWVTU1RlhqcDNtTUZ1NnNuc21LdzhPSnpaeldNbHBCOC95a0FhOXhCS0JwZDlBSlFRZkt1Q0RyblJnQ0pHejVqY01oMTN6b2o0Y3M5eGp5QWVURjgxUVhtczVyQ3lHQm5iS2I5OURXY2Z0Rys0blVMZFZBNDNaSDFZTWhaOExHeHRVZjFlNlhlYTF0Qy9Hb04wbFNOZVVSR3VNS2x0MCs5MUFoRG14b2F3SGlWYm9aL0V1RzFPS0QzczRKejhNTlNZQVBjRnNzZzI4WEpCOTl2TFpzVnpzekJsOEYyZk1LZ1ZPaUw3L0NReEYvUW51bzFwcVkzamw1eU95UGc3ZzZwcElGK0VxR3BQc0RNWEJjOE5wOERCYlJKL0hkYlJHQzZPWHlWcXB5WXlJM01iMFBXTXd3NUhjNWozNkpZaHNhSW1rdmIrbjUvU2dJL3lheDhvT0xFVi9vZytwV2Y5eGVOakt4N080LzRJYVVCNDhUaFNnOTJPZVFIQm5yTERWVHhDaHlTRUw5Qm1hVW1HUDdCTDduWW1UazErb1JHZ1RkTU0xb2xvZ2hTamM5S3pwMldBWkFvVHNESWdVVWR3eE9sSXFrYzBtSUFSdEl4Q0dTM3FnWnhOU3JienBLWjJwc3UzZkJ4U0RsT29GM3hoeDNScGE1eWpmclVFbzRDZ3NDc1VDdHg4NWt3UThzYnZndExMTlVlbW1DcmxNb1BXSDlhL1N4QkF6TjRpWkZLUzJrRDdzRnF4bFhrMTcyK1NIRkF3UjF1SVJ0YkEzNDBFZ0tXLzBPRjlXS29MMGtRekRLTW9VPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFaQUFBQUdRQ0FNQUFBQzNZY2IrQUFBQWIxQk1WRVVBWmYvdDd2OFVjZjhpZWY5QWl2L0ExUDhKYXY4QUFHWHY3LzhBR280eWd2L04yLy9uNnY4QUJHelk0djlabWY4QVlmcG9vZjhBRVlDbHhmK1h2UCtBci84QUNuVGc1djhBWFBJQVZ1Z0FOTFVBVHQyNTBQOXpxUDlPa3Y4QVBzT010djhBSzZjQUlwb0FSdEN2eXY4ODFML01BQUFSTTBsRVFWUjQydXlkNjNicXlBNkVaU0JtQXdFQ2tBdUVXMGplL3huUFdYUGRRMlBjclZaSjduYnI3NndWNytFRHUxeWxsbWhjcWxORjVTTW9RRW9WSUFWSXFRS2tBQ2xWZ0JRZ3BRcVFBcVJVQVZLcUFDbEFTaFVnQlVpcEFxUUFLVldBRkNDbENwQlNCVWdCVXFvQUtVQktGU0FGU0trQ3BBQXBWWUNVS2tBS2tGSUZTQUZTcWdBcFFFb1ZJQVZJcVFLa1ZBRlNnSlFxUUFxUVVva0N1WDUvVURyMXNqdXZzd2J5OWtuSjFYbWVMNUMzSFNWWTMvTnNnWHhTa3JYUEZjaVZFcTExbmtEbXUxU0JmT2NKWkUvSjFpUkhJRzh2NlFMWnpUTUU4azBKMTFkK1FDWXA4NkNYdCt5QWZDWU5oTTY1QWZtaXhHdWRGNUQ1UitwQVB2TUNzcWZrNjVvVGtQVkwra0ErNWhrQmNTVHY4bGRRVmRQYlAvRDZDMXp1SmZmNUFIRWtiNzBJL0hoK292OUNjUDNZU0Y4VklMdjQ3L2ZwOWsrYzBFRGNTNTV6QWVKSTN1Rno4S2N6cTIvL3lBRU54TDNrSkE4Z2I0N2szVEErbnVQdEg1bFdhQ0pIQyttckFPUjgrLzgxNGp4am53ZTNmMmFMQnZJOE5MQzA4RURXam9COFluMDgyOXMvTTNoSEU5a2FTRjg4RU1mRVdrbnAwR09PMGhjT3hNbHRCMXpCZW5Dazd3eE41TW1SdnV2VWdiaTU3WVg5OFN6MXBlOVNQYzFGQTlrTFNONi9hK0hvMEI4MGtJVzY5QVVEY1hQYmlNK3dlblhvd3FXdmM4bGQya0RPb25jWlY0ZGUwRURVcFM4V3lFVDJPVnh0OUtXdmM4bVB0NFNCZkVvcjFaR1FobzY1NURsZElGZnBMM1ExRTNyTGpMcmtPbFVnYm00YjczYXNKSHlZeUV0K3BncGtMKzhIVnU4RENhY3k4cExYTklHNGt2ZUEwS0VSTHphZWRkRnNaQVFDaWMxdEc3NndRKzAwdDNJdnVVOFJ5QVNVdW1hZTV1S0E3RkRmNUJIa2w5ZVZOQmNHeE1sdEIxTDNlamRhUlV0ZnpUUVhCV1QrZ1ZORHE1elRYQlNRTS9CRGU5ZFBjL1drTHdqSUd2cEdmWUhkRHUzVFhCQ1FiNmpubEhPYWl3RnlCVXRUZ3pUM29KVG1Rb0RNZCtpWHR5NDBNbjZuQTJTUHRqZXFoWDRqbzFLYWl3QWltdHY2NmxBRDZidExCY2had1NKM285Vk1HaGtCUU5ZcVQ5eE9OREsrSlFIa1V5ZG0xWmUrS21tdVBKQ3IwbGYzS2M5R1JuRWdrcTJLajZzTGpZeWYzUWV5VjVNL0ZvMk1BN2owbFFhaUlYa2IwMXk4cGZVS1QzT2xnWHdyM2tkY0hRcC9ydU9scnpDUWllcVQxdWtxSkhpYXUwR251Y0pBZHJyZjJaRitseFphK3NvQytkSzlxOS9wS2pRNG03dnVMaEJFcTJKZ21qdUUvMFRBall5aVFQYmFqbC8xWHFzZlVBQ251WkpBMWkvcU41QmZqdXFwOVJzWlJkTmNTU0RmK2cxVHJzN0NYeFNiNWdvQ21ZQnpXNi9YQWlJeVNIUGZ1Z2dFbjl0NnZEZ1RFVTJUVG5NSkozbnhiZW11bTZWeVFBR2E1b29CY1UwcytPZmltcTlhUHhGZ0k2TVlrTFArUy9PaGFScmZRZi9aOWRVMUlOaFdSVSsxbzlmd2dHdGtsQUtpbE5zKy9GQVVHeDV3MGxjSXlGVy81Y0I5WTlhOE9pek5KWkRraFRzWXJxZWsrL3RFamFXUkFiTFhIMEl5cXg4QndUYzhvS1F2WVNRdlBOMTJjd2x0alFjYVMwTVF5WXZ2LzlpMERhS0d2d1dCcEs4RWtJbitEZU91aWFYc0UyREcwaEJDOGg3MTd4ZHV2ZXJmTmMvZEFQS2xMem9YZFRzUXZOY01TWFBqZ2VqbnRvMG1sbll3Z2toelNWN3k0bzJMZzkrQ0NiaWxoVWh6bzRFWTVMYk5KcGIyTndPUTVrWURNY2h0dDc0N1dQQ1dsdnhZR2hLWHZBdjlHNFdkcFNVL2xpWVdpRUZ1dS9KZlU0UzN0TVRIMHBDdzVNVy9qODFxZnlENE4xVHhzVFFrTEhueHVlMG9aSk1YM3RLU1RuUGpnQmprdGhzS3FvMytFKzFxQjhRZ3QyMDNzYlJ2b2NKcExvbEtYdnhEOUpVQ0s3WDllakZBNUZhRGlKcFkyakpjZGl4TkJCQ0wzSFpKd2JYVS8wZDkyd0RaNjkrdkQ4U290TWJTOElFWTVMYStKcGF5cFZWSnBya2tKM254dWUyV1dKWFVXQm9Tazd6NHQySi9FMHZaMHFvRTAxdzJFSVBjZGtYTVNtbkpDSWxKWHJpek9xdTVRQXpHMHJEVFhDWVFpOXgyUk94S2FNa0lDVWxlZkRxM29ZaEtaOGtJQ1VsZWd5TVozYkswcE1iUzhJQjg2MHZlVjRvcXZLVWxKSDFaUUF4YUZSZDFISkJrbG95d2dPejBKZStTSWd0dmFjbElYdzRRNVJFemJCTXJ5YkUwbElUazVabFkyanBRUlBveWdKejEvMWUzSkZCcExCa0pCK0syS2o3cC81OTIwdElTYVdTa2VNbUxmMXl1U0tSVytuZldQUjdJVlY5UXptb1pJSFVLWTJsQ2dWaU1tQm1SVU9FdHJmaXhOQlFyZVEyT2puWFkwb3BQY3dPQkdJeVlpVE94dEw4OTBVdEdLRkx5R2h3LzdyU2xGWjNtaGdFeGFGVmMxSkpBOEFva3RwRXhESWpCaUprbGlSWmVvMGRLWDRxU3ZQaDNyUU1KRjl6U2lreHpLVXJ5d2xzVkpVd3NiWjhucnBFeEJJakJpSmt0aWRkVy82azN3UUF4YUZXVU1iRzBiN05SYVc0QUVJUGNka1dBZ2d1UktPbnJEOFFndDUzVkNDRDRmM2ZNa2hIaVMxNkROWFgzUCtEcGFiazZIbGZMMDlRUFlLZVhqQkRieEJwMHdNU3FSOGVmLzd6cUxYNk9vM1lxY0VzcklzMzFCV0tRMjdhWldQVnBjL2M3OGJ3NTFkYVdGai9OSmE3a3hldjV4eWJXOFBKQUxiMWZocmFXRmovTjlRUmlNR0xtb1lrMTNMWjhINnJOMU5UU1lxZTV4SlM4QmlmM2ZudDhYVHgrbnRWMllHZHBWZXcwbDVpU1YvOXM2MitmcHVlcjNXSnBhR2x4R3huOWdPam50czBtMWlCQUkyMEdkcFlXY3l3TnNTU3Z3WHlFZno3Sm9OZTZ4ZFRNMG1LT3BTR1c1RFdZSVBMMzdTcndxL0M4TkxPMGVHTnBmSUFZNUxaTkp0WXErRTVUSGMwc0xaYjA5UUJpa05zMm1WaWNSMWYxYW1WcHNkSmNZcGhZQm9kYW95NjhNckswV05LM0hZakJpSmtHRTJ2SlZFYlYwc2JTWW8ybGFRVmlrTnMybUZoVHRyUjduaHBaV293MGw0Sk5MSVB6azMvK01DUHUrWXVCamFYRlNIUGJnQmprdG9EdGhOWEd5TklLSDB0RG9aSVhuOXN1RWU3VDBzVFNZcVM1MUxuYzlyNkpGYXNrR3Q0MDRaWlc4RmdhNmxwdTIyQmlSU3VKaTVHbEZacm1VdGRhRmUrYldQRWRZTlhReU5JS2JHU2tqdVcyRGJlV0xZbzAraHRXaFM0Wm9ZN2x0aXZRRDZUeEo3TFMvNHBkdVVBTVJzdzBtRmdpNzZJWEkwc3JySkdSdXBYYjNqZXhhcEg3eW50dFpHa0ZMUm1oVHVXMkRTYVcwTHZQeWNqU0NrcHpxVXU1YlZNbjFnYUtHKzhGaFVoZjZsS3JZbE55SVhUaFo4R1VKZkxKdUE0SFlwRGJOblZpaWQzbHAxWmRXZ0hTbHpvMFlxWXAvaFp6QjQ1V0J3OERwQzkxWjhSTVl5ZVdtTC84WTlhbDVkL0lTSjJSdk0yZFdHSjNsSVZabDVaL21rdWRrYnlOblZpMTNEVnFzeTR0NzdFMDVQa0RNZWdYLytmckszZVJxZDNCdzVQblQrUStrSGtIVGxRZ0lyR1QzY0ZEUjBMdVFvQ3MxU1h2ZytPRWdrK3ZwZUhCdzF1Sjl4SUZCUDdQSGFtY21sMFpIangwbnBFaFFONjAvN21QamhNZWNkOVN4WnVBMDFnYWRNdHlmU3pzUC9maGNVSWxJT0RINU5IVHo2Sk9IRUI0VlRyb3Z6STdlT2h0WjFFWHJON0hNN0ZVSHVyb1Z5M3Y0enZVaFREazhVd3NGZGtMTmlQOEl4SHFRRnpZTWhOTDQ4VVFiR2tGOU1HVC9VSG90cGxZY3RaSlZSdk4wZ280SkUzMkxTZXRNN0h3NWlMWTBncHBQQ0h6cHF6Mm1WaDQreDFzYVlXMFpwSDV1Sm4ybVZqd2dBcHNhUVdOb2lIcnhsNlBtVmpvQ0JkdGFRVzE5NUoxNjd2SFRDeDBrd1BZSXdvYlowYkdRLzI4QnJ2TCtEYVY0clVlMmtKZjdONWUvUEVwdjhIdTJFWTVzRWNVT0JLVGJLZGsrUTEyaDdhU2dqMmkwR09HWkhvRTEzZXdPN0RaR20xcGhSN0VKZFBoNHI2RDNZSEhFY0NXVnZEZzhiWkRuOUF4RHY2RDNXRUhkdENXMWloMG1FTWJFSGZRaVp6MERSanNEanZTQnJhMHRxRm5QdHNIQndCSEFZVU1kcjhvUFVGa1BTTEdqT3RXSUxnbFIwR0QzV09QUlMrQ0xpYjFvR1FzUUdvZlBnTkxjOE1HdTBNR0I0QXRMYzZlaEhZZ3FFVjVvWVBkbzM2WWdadmVoRHdpemhJOWozbFpvRldTb2RzSkFjTm53SllXWnpxVDE0aS9XMHVybGxEcTRkc0p4Y2N6Z1MwdDN1aGVIeUNJc3lLYzdZVFNBOHpBbGxaQWJoczZKaFp3bW9xMW5YQ2xvUjZrSHBUTThlOWVRT1RUWE9aMlF0YW5kR1JkS3ZwQnlWeVE0RGZaK2xiNjFyRnBMbmM3SVdOTUxIZHRVdVNEa3J0Q3hITVkvMDQyemVWdkp3d2VwSHhpWHlyTzB1SXUyZkVFSXB2bXhtd25EQm8xWGkxaXJoVHpvT1RPNHZkZTZDTGF5QmkxbmJBV0djWVB0clRDNXB0d2dFaE9Cb3JkVHJqMGZONHVJdmZvUmxoYS9GV0cza3ZCQk5QYzZPMkU4UXRkd0pZV2YrT1JQeEE1NlN1eG5YQjRhVjE1Tkl5L0N2ZEJXZkYzZ2dYc01SUkxjMlgyRFVjdEJRTmJXcUZ6Rm5sQXBCb1pYMG1vK0d2ejBKWld4RjdKRUNBeTB2ZFpjcDFxUFhVWFMwNGxMOEN5dElKbjlUS0J5RXk1UHBGMEJhOWVCWnMxVWJ1Smc0QklORExPS0sxaVdGcmg4OTY1UUNRMkpRd1RBeEwrQWh5MzN6NE1TSHdqNDVhU3E5QVhZTWJPRURhUTZHMDdWWjBla0hyNlZ3MXZhbkJURGY5dkwyc2drTmhHeGlYMXIvWmpKSkM0alcyTEh2THdYVXJNQkJMWHlEanRJWkRyR0Fza1pucnNUdzk1Zkk3QlFHSWFHUWM5QkRLQkErR1BwWG50SVkvekdBK0VPNWJtdWU0Zmo1YzNCU0RjTlBmWXd4L0lmcXdCaERlV1p0YkRIMGlvNUdVQzRhVzVweDcrUUs1akhTQ2NOTGRJWGlBUXhsaWE1MkVQZ2F6VmdJU251VVh5WW9FRXByblZva2hlTEpEUU5OZDVvZytmdWxtSHk3KzEvYU0yLy83SDJYOXI4ZjViTGFKeTIzZ2dZV251SVRyMTZXSlZNcTJLTWtEdXBMbFZRRy8xNmxkbUZabmJDZ0FKU1hOZkkzUEdCQ295dHhVQUV0REk2QjZCdmVURzQwbEc4a1lCOFU5emw1d1grN1NLZGQ1V0dvaHZtdnVVNVJQOWNTL054OXdBaUdlYTZ6N1JsN254ZUphU3ZKRkEvTWJTWEpqeFNVSjFGREd4NG9GNHBibnUwWlhYekhCVWNwSTNGb2pQV0pvVlA0SlBwVTVpa2pjV2lNZFlHdmVKL3BNYmo0T1FpU1VCcERYTnJVWmhubGVLZHl4QnlSc1BwRzBzelRiTUZVNnhMb0tTTng1SXkxaWEvSi9vTWVkdElVQWVwN2s5ZUtLdkpDV3ZBSkNIMHRkdE5Obmt4b003WWdZSDVORlltbEZNWTNZYU5aTEpiU1dCTktlNW0veWY2RCt5a2xjRVNPT1NFZGZoT2ViR281STBzY1NBTkkybE9RYjNDaVZYWXJtdEtKQ0dSc1llUE5IRkphOFFrUHZTOTVUL0UxMWM4Z29CdVp2bS9uakdWd21YWUc0ckRPUk9JNlA3Uk0rdTBRUWdlY1dBT0dsdXZmSnVnVWhXWVVXTm1BRURjUzB0Q3UrUDczTnVLdzdFbGI2NU41cFVjU05tMEVCYzZadjdFMTAydDVVSDRxYTVtVC9SbDZLNXJUd1FWL3JtM1RyS1dnMmlDc1MxdEhKdUhaWE9iUkZBMWoxNm9vdTJLcUtBUEpDKzJiV09Ra3dzY1NDdXBaVnI2NmhzcXlJTWlKdm01dG82T2tOSlhtRWc0L3ZTTjd0R0U5ZklQbys3Q1dSeWowZCtqU2FBM0JZRTVLNzB6YTUxbEw4YVJCK0kyOGlZWCt1b2VLc2lFc2dkU3l1N1JoT2s1SlVISXI5ZnJ4KzVMUXpJbmJFMG1RVlQ4cTJLV0NCU1MwWjZsdHNDZ1V6eWJsY0U1YlpBSURKTFJ2cVcyeUtCU0N3WjZXeWhjbHNra0tDeE5DVzNWUUFTdjJTa2Y3a3RGSWpjZnIydTFSTXN0OFVDaVYweTBzUGNGZ3hrbldjWDBCWnJZZ0dCeEMwWjZiSGtoUUh4RzB0VGNsczFJREZMUnZvc2VYRkE1cnZzZ3R5VGd1VEZBV0V2R2Vsc0hhQzVMUjRJZDhsSXZ5VXZFZ2h2eVVoZmMxc0ZJTHdsSTMzTmJUV0F2T1dVNXE1MEpDOFVDR1BKU0g5eld4VWdHYVc1OE54V0IwZzJhZTVHUy9LQ2dUU09wU2ttbGhHUVROSmN4SWdaR3lCNVNGOTN1Y05rbkNxUUxOTGNwWjdraFFQSkljM0ZqSml4QXBKQm1qdlNNckYwZ0t4VGw3NWJlS3VpTHBEVTAxeGR5YXNCSkhIcGU4UzNLaW9EU1RyTnJiUnlXMDBnU2FlNVdybXRKaENQSlNNSjViYnJESUM0bGxZcTBsY3Z0OVVGa21valk3VlZ5MjExZ2JRc0dTbTVyVG9ROTJ4dUVvMk1SMTBUU3hGSW1tbnVURi95cWdFWnB5aDlUNHE1clRvUU44MGRkYjQwYzF0MUlBOG5NaVpTKzNGT1FGb25MWGUrZHZPc2dMUk9XdTU4WGNkNUFXbWN5SmhJZlk0ekEvSjQwbkwzYTUwZEVEZk5UYW5PNC95QVRCTG04ZkdXSVJDUEpTT2RyYTl4amtEU2xiNjdjWlpBL3RmZUhhTUFDTVFBRUN4RENrR3VFTG5XLy85UkxBWEI5aEptdnpCTjBpUjFSOTlzQ3ZMelpHVFpybWdLOG5WR3RrRDdhQXNTV1hFOW5ORVhKSTVaanVUY09vTThKbG1yRWMxQkJBU0lnQUFSRUNBQ0FrUkFCQVNJZ0FBUkVDQUNBa1JBQkFTSWdBQVJFQ0FDQWtSQUJBU0lnQUFSRUNBQ0FrUkFCQVNJZ0FBUkVDQUNBa1JBOU80R1Y2Tkk4TGpMeHRjQUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNC0xMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU09MSUQgd2ViS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAxOTAzMTkwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA0LTExIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wNC0xMSJ9LHsiYWFpZCI6IjAwNDIjMDAwMiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFpZCI6IjAwNDIjMDAwMiIsImRlc2NyaXB0aW9uIjoiU1NlblN0b25lIEZJRE8gVUFGIEF1dGhlbnRpY2F0b3IgZm9yIGlPUyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZrMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJpbWFnZS9wbmciLCJ0Y0Rpc3BsYXlQTkdDaGFyYWN0ZXJpc3RpY3MiOlt7IndpZHRoIjoyMDAsImhlaWdodCI6NDAwLCJiaXREZXB0aCI6MSwiY29sb3JUeXBlIjozLCJjb21wcmVzc2lvbiI6MCwiZmlsdGVyIjowLCJpbnRlcmxhY2UiOjAsInBsdGUiOlt7InIiOjIxNiwiZyI6MjE2LCJiIjoyMTZ9LHsiciI6MjAwLCJnIjowLCJiIjowfV19LHsid2lkdGgiOjMwMCwiaGVpZ2h0Ijo1MDAsImJpdERlcHRoIjo4LCJjb2xvclR5cGUiOjYsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MH1dLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFOEFBQUF2Q0FZQUFBQ2l3SmZjQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzTUFBQTdEQWNkdnFHUUFBQWFoU1VSQlZHaEQ3WnI1YnhSbEdNZjlLelRCOEFNL1lFaEUyVzdwUVpjV0tLQmNsU3BIQVRsRUxBUkU3a05FQ0NBM0ZrV0swQ0tLU0NGSXNLQmNnVkNEV0dORVNkQVlpZHdnZ2dKQmlSaU1oRmMvNHd5ODg4NHp1OU5kbG5HVGZaSlAybjNuTysrODg5MzNmdmVCQngrUHFDekprVFV2QmJMbXBVRFd2QlRJbXBjQ1NadlhMQ2RYOVIwNVNrMTliYjVhdGY1OTlmRysvZXJBNTQxcTQ3YVAxTExWYTlTSXlWTlVpOElpOGQ1a0dUc2kzME5GdjdhaTluN1FaUE13YmR5czJlclUyWE1xVWR5OCtaY2FObUdpbUU4eVhOM1JVZDNhMThuRjBmVWxvdlorMENUeldwZDJWaitlT20xYkV5eTZEeDRpNXBVTUdXdmVvNTA2cTIyN2R0dVdCSXVmZnI2b1dwVjBGUE5MaG93MTc1MU5tMjFMdlBIM3JWdFdqZno2NkxmcWw4dFg3RlJsOVlGU1hzbVNzZWI5Y2VPR2JZazdNTlVjR1BnOFpzYk1lOXJmUVVhYVYvSk1YOXNxZHpEQ1N2cDBrWkhtVFpnOXg3YkxIY01uVGhiMTZlSittVmZRcTh5YVVaUU5HNjRpWForMC9rcTZ1T1pGTzBRdGF0ZFdLZlhuUlE5OUJqOTFSNU9JRm5rNTRqTjBta1VpcWxPM1hEVytNbCs5OG1LQjZ0VzdyV3BaY1BjKzB6ZzR0THJZbFVjODZFNmVHRGpJTXViVnBjdXNlYXJmZ0lZR1JrNmJyaFpWci9KY0h6b29MNzU1MGplZExFeG9wV2NBcGkyWlVxaHU3Skx2clZzUVU4MXprek9QZWVtTVJZdlZ1UXNYN1BiaURRWTVKdlpvbmZ0SysxVlk4SDl1dHg1MzBoMG9iK2ptUllxajZvdWFZdkVlblcvV2xZanA4Y3diTW02ODJ0UHdxVzFSNHRqLzJTSDEzSVJKWWw0bW9adlhwaVNxRHI3ZFh0UUh4YS9QSzMvK0JXc0sxZFRnSHU2Vjh0UUozYndGa3dwRnJVT1E1MHMxcjNsZXZtOHpaY3ExNytCQmF3N0s4bEVLNXF6a1llYXJrOUE4cDdQM0d6REsrbmQzRFFvdys2VUM4U1ZOODJpdXYzOGltN050YVh0VjFDVnE2Umd3NHBrc21iZGkzYnUyRGU3WWZhQkJ4Y3FmdnFQclVqRlFOVFEyMmxmZFVWVlQ2OHJUSktGNURuU21VamdkcWc0bVNTOXBtc2ZESlIzRzZUb0gwaVc5YVY3TFdMSFlYS2xsVER0MExUQXRrWUlhYW1wMVFqVnYrK3V5R1V4VmRKMEROVlhTbStiMXFSeHBsODRkZGZYMUxwMU8vZDY5dHNvZDB2czVoR3JlOXh1OG8rZnBMUjFjR2hOVEQ2WjU3QzlLTVdYZWZKZE9aOTRiYjlvcWQxUk9uUzdxSVRUekhpbU1xaXZiTzNnMERkVnlrM1dRQmhCenRLMzVZS05kT25jOE8zYWNTNmZEWkZnS2FYTHNFSnA1cmRybGlCcXA4OWNKY3MvbTdUdnMwcmtqR2ZONGIwa1BvWm4zVUp1SU9ybloyMnlQMWZtdlV4K081Z1NxZWJWMW0relN1WU5WaHE3VFdiRGlMVnZsanBsTGxvcDZDTFhQKzJxdHZHTElMLzF2aW1JU2RNQmd6U29GWnl1NlRxZCtqenhnc1BhVjlCQ3FlZS9OallrNnY2bEs5Y3dpVWMvU1R0ZjFIRHBNM2I1OTJ5N2gzVGh4NW96SzY5SExwWVd1QXdhcVM1Y3YyNnE3Y2ViOGVmVllhUmVQM2lGVTh6ajFrblN3WlhITW1uQ2pZME9nYWxvN1VRZlNDTTNxUVFyMkgvWEZQN3NzWHg0NVlsOTFCeWVDZXA0bW9ab0grMWZHM3hENHRUN3g4a3d5ajhud2I5ZXYyNlYwQjZkKzdINHpLdnVkQUg1MzdGanF5ek9IZEpuSEV1em1YcS9XanhPYnZOTWJ2N25oeXdzWDJhVnNXdEM4KzQ4YUxlYXBFN3A1d0taaTBBMkFRUlY1bnZSNEUrdUpjK2I2MWtBcHFJbnhCZ21kLzRWNVFQL210MThIREM3c1JIZnRtZXU1bG1oVjBybi9BTFgyMzJicWQ0QkZuRHg3VmkxY1dTMnVmZjBJYkI0N3FleHhtVWo5UXV0WWp1cGQzdFlENmFiV0JCTXJoK2FwTmJPS3JORjErdWdDYTRyaVhHZndNUFB0VmlhdmhVM1lNT0FBbnVVYi9SMDdMMHlPU2VPYWRFODhBcHNYRkdmZjMweW5obEpnTTUxQ1U2dk45RXpnbnB2SEJGVXlpVnJhZVBpd0o1M0RGNVpUWm5vbUVOZzg1a05VZDJvSmkyV3ByNE9tbWtmTjR4NHpIZmlWRmM4RHY4Tnp1aE5xT2lkaWxHdkE2REd1ZVp3Tzc4QUFRbjZjaUVrNitydzVWY3ZqdnFORFlQT29JVXdhS1NocnhBdVhMbGtINGFZdUdmTVlEYzEwV0Y1VGEzMWhQSk9mY1VoclUvSmxJTmk2YzZlbFJZZEJwbzYrK1lmang2MWxHTmZSbTRNRDVySjFqM0ZvR0huakRTQk5hcllVZ01MeU1zektwYjd0WHBvSGZQczhoM1dwMUx6TmZOazU0WHhDMXdER1VtWXpYWWVmaDZ6L2NLdFZtNEVCeGE5VlFHRHpZcjNMclVNUmpIRUtrazd6YUZLWVFBMmhHUVUxeis4NU5GV3BYRHJrejN2eDEwR3F4UTZCemVOYm9CazVuOGs0bmViUmgrazFoV2Z4VEYwRDFFeVdVczVuditkZ1FxS2F4enVDZEUwaXNIbDAyTlE4YWgwbVhyMTJMYTNtMGY5d2lrOSt3TE5UTVkvODZNUG84eWkzMU9meG1UNlBXb3FHOStEWnVrWW5hNTZtU1p0NVdXU3k1cVZBMXJ3VXlKcVhBbG56a2lhaS9nSFNEN1JrVHlpaG9nQUFBQUJKUlU1RXJrSmdnZz09In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDktMTMifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTA5LTEzIn0seyJhYWlkIjoiMDAyMiMxMTAwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiMDAyMiMxMTAwIiwiZGVzY3JpcHRpb24iOiJNb3ZlbmRhIEVnb21ldCBGSURPIFVBRiBpT1MgVG91Y2ggSUQvRmFjZSBJRCBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidWFmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9kZXIiXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmYWNlcHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoiaW1hZ2UvcG5nIiwidGNEaXNwbGF5UE5HQ2hhcmFjdGVyaXN0aWNzIjpbeyJ3aWR0aCI6NTQwLCJoZWlnaHQiOjg0MCwiYml0RGVwdGgiOjgsImNvbG9yVHlwZSI6MiwiY29tcHJlc3Npb24iOjAsImZpbHRlciI6MCwiaW50ZXJsYWNlIjowfSx7IndpZHRoIjo4MTAsImhlaWdodCI6MTI2MCwiYml0RGVwdGgiOjgsImNvbG9yVHlwZSI6MiwiY29tcHJlc3Npb24iOjAsImZpbHRlciI6MCwiaW50ZXJsYWNlIjowfV0sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQU1nQUFBRElDQUlBQUFBaU9qbkpBQUFBQkdkQlRVRUFBTEdQQy94aEJRQUFBQ0JqU0ZKTkFBQjZKZ0FBZ0lRQUFQb0FBQUNBNkFBQWRUQUFBT3BnQUFBNm1BQUFGM0NjdWxFOEFBQUFCbUpMUjBRQS93RC9BUCtndmFlVEFBQUFCM1JKVFVVSDRnTUJEU0kzZjVOOTRBQUFHZUZKUkVGVWVGN3QzWDF3Vk5YZEIvQnp6dDJiZmNsdVNFZ0lFcEpORUNYUUlBUkNVTFErK0ZhbmlwU3FyYmFXY2JSVEhLc3o5bysremZTZnA1M3AwMy9hcHgxbTJtZkdndldscUhXcWRpckZsNktXQ2lLUWhKQUlRaEJJc2trdzcyK2IzYnU3OTU3emUvN1laTjJFN042WHZXZXphODlubk00MG5KdnM3djN1dWVlZWUxNHdBQ0JCc0J2Ukt5QUlWb2hnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVng4SVlJbFZnbklQUTY5QWptUDB0aWhRNkJwOHNhTnBLd01ZYXgzZ0pBTmVSOHNOam9hT1hDQTlmZkhEaDUwYk54WWNNTU4wb29WSWw0TEx1K0RwYlczczhGQnhCanQ2YUc5dmVyUm84NGRPNXkzM29vY2VmL1c4bHArdDdFZ0hJNmRPSUZVRldHTUNFRVlzNkdoeUVzdlJkOTZDMVJWNzJpQm8vd09GcjE0a1Y2NE1PdkNSd2dvU3VUVlY2T3Z2UWFSU09wREJiN3lPVmlNcVMwdE1EVTF0MFdGTVVTamtRTUhJbi81Q3dTREtRNFcrTXJqWUxIQlFiV3RiZjUyT3NaSVZhUC8vS2V5Yng4Ykc1dW5nTUJaSGdkTGpUZmJVOTBBWW93QVloOThvUHpwVDJ4b2FQNHlBamY1R2l3SWhkUVRKNUNtNlJWRWFuTnplTzllMnR1clYxQ3dVNzRHUzd0d2dWNjZaTEMvU2p0MVN0bXpoMTY2cEZkUXNFMStCb3RTdGFrSlFpR0R3VUtFYU9mT2haOStXanQ3VnErb1lJKzhEQlliR05EYTI0Mm1LbzRRMnQwZC91TWYxWk1uOVlvS05zakxZS21uVHJIaFlYUEJRZ2hoekM1ZlZwNTlWdjNvb3kvYWMydEtZWElTcHFiMHltVlAvajMzZ0trcHRha0pVWXFJK1c4RklXeHdNUHpjYys1b3RPRG1tNUVrNlIyUTJ6U05kblZwRnkvU3prN2EzUzJ2WCs5NjRBRXJId3NIK1Jjc3JhT0RkbldacnE0U0NJR0pDZVhQZjRhcEtlZFh2NXEvanhUWjBGRDA3YmRqUjQ1QU1JZzBEUUZnbHdzaUVleng2QjJhRGZuMnNXcWEydFFFNFhCRzMwdU1JUlNLdlBvcUtJcHorM2JzY3VrZGtHTTBUVzF0amZ6OTcvVGlSUVNBTUVhU2hBQllmejhiRzVORXNDeWcvZjNhbVRQV3E2c0VqQ0VTaWJ6eEJrU2pybnZ2eFlXRmVnZmtDdGJmSDMzcnJkaVJJekExRlgvdVB2MFBHRU1veEFJQmFmbnl0TDhnUy9Jc1dGcHJLeHNac1NGWWFPYXh6OXR2UXlqay92YTNjVkdSM2dFTFRWVmpUVTNSL2Z0cFp5ZEM2TW82RzZKUjJ0MHRiOWt5ejdGWmwwL0Jnc2xKNjgzMmVXR01OQzMyd1FlZ0tPNmRPMGxabWQ0QkM0YjE5MGNQSEloOStDR0VRbW5lUGcwRUlCTEpoWXQ3UGdWTE8zZU9kbmZiVTEwbFlJd1lVNDhkUTZycS9zNTNTRVdGM2dGWnAxZFJmUTVqMnRjSHdhQUlsaG1hcGpZM1F5UmlXM1dWREdPMXBRWENZZmNqajBqVjFYcWxzOGRnUlpVQWs1UDA4bVd5WklsZVFlNzBYMnVPb0gxOTJ1blRObGRYeVREV3pwNE5QLzIwMXRHaFZ6UXJWRFYyOUdobzkrN293WU5HNzRJeEJrVmhnWUJldVd3dzhISnpnOXJheXNiR09BWUxJWVF4dlhoUjJidFhQWFZLcnloZnJMOWZlZUVGWmUvZTZRZnR4dDgxWTdTN0crWEFzT3o4Q0JZYkgxZWJtaEJqZWdVelJnZ05CSlJubmxHYm14Zm1zWStGaWlvWnhyU3JpNFZDZXVXNHk0ODJGajE3bHZYMm12amlab0lRTmpRVTNydlhIUW9WM0h5ejZWT2JBYk10cW5sZ3pNYkgyY0FBS1M3V0s4cFhIZ1FMWXJGWVV4T3ZadnU4TUlieGNXWGZQbEFVNXgxM1pPR3hEMFNqNnZIajBUZmZwRjFkQ0tXOTlVc1BZMUFVR2dnNGFtdjFpdkxGL1NQTEhPdnJvMmZQWnFtNlNzQVlnc0hJSzY5QUpPSzg2eTdzZE9vZFlCM3Q2NHZ1MzY4ZU93YUtZajFTQ2FwS0F3SEVtQTIvS2dONUVDejE1RWsyUHA3dFlLSHBiMy9rOWRjaEhIYmRleTkydS9VT01BMmlVZlhZc2VqKy9kTWpwMjJKQXNZc0VJQndHSHU5ZWtVNXl2VmdzYkV4dGJsNXdiNS9HS05ZTFByV1d4QU91eDk4RVB0OGVnZVlZSE5GbFlBeEhSaGdJeU9TQ0ZZYTJ1blR0TGZYK3VjZXY3UExwTGJER0tscTdQMzNVVFRxK3RhM1NHbXAzZ0g2dUZSVUNSaERLRVI3ZXhlMnB6ZW5nd1d4bU5yY2pHSXhpeDg5Z0ZSWkNZcVM2WFByK0V5eUkwZEFVZHdQUDB6S3kvVU9TSWRYUlpVc0ZxTmRYZWltbS9US2NaVFR3V0tCZ0hidW5NVk1BR0NuMDNudnZkanRWcDUvbmcwTVdQdzlTZFRtWmdpSDNZOCtLbFZWNlpXZEI5K0thallhQ0lDaThHZ1hHcFRUd1ZLYm0yRml3bUlnQU1qeTVZNjZPbEpjakoxTzVmbm5hWGQzcHVjU1krM01HV1hQSHRmT25ZNVZxL1JLejVLTmlpb0JZM2I1TWt4T0xtQ3dPTC9ERExEaFlmWGtTZXZkMzRUSW16YkYrd2tkZFhYdVhic2N0YlUyOU4wVG9uVjBSUGJ0Zy9GeHZhTFRJQnFOL2Z2ZjRkLzlMbmJvVU5aNjR5QVlYTmc1dXRsNGs5Wm9aODdReTVjdG5nWUFVbElpTnpRa2Z1QzQ5bHIzcmwyT2RldlNIR1NDMjQwS0N2UUtJWVFRN2VwUzl1NVZubjJXOXZTWWUrcVhDWXdoRXFFTCtqVGEwbW5qRHlJUnRhbkorc05VQU1mYXRYTUc2VXBWVlo3SEhwTTNiVXAxa0ZHeVhMQjVzKzZjQlZDVTZMdnZobmJ2amgwK25MV0s2bk1BdExzYllqRzljcnprYUJ1TGRuZHJIUjBXdjk4QTJPV1NOMjI2OGxFTVdiTEUvZDN2NHNMQzJPSERpRklydjU4eGFmbHkzWnFQZG5WRjkrK1BOVFdoYURUYmtZckRtUFgyUWlpRWpkV3N0bHVJOTZ3TFFHMXBnV0RReW9sSENBRVF2OSt4ZXZXOC8waEtTdHc3ZHpydnZCUEpzcFVHSE1hTytDcTZxVUU0ckx6OGN1eklFZXNkSlhOWWVKMElzYkV4OXRsbmVxVjRzZU50MjQwTkQyc1pOOXZUVEk3QVhxL3J3UWRkOTl5RFhTNXpmd1VBKzN4eVEwUDZ4R05aSmw3djlNU3NEQUVnaExEYmJUcWdNMCtqOWNyeFl2TGxab1hXM2s3NyswMS9sSEVBcEt4TTNyZ3hmU25zY3JudXU4LzFqVy9nd2tJVDJRSncxTmJxOTJqTHNsUlRZL0gxSjJNTU81MEZYLzZ5NjZHSHNOdHQ0blhHYVJydDZrS1U2cFhqSXVmYVdLQW8wODEyYXljR3dGRlhKeG1aRXlITHpydnV3bDZ2OHZMTE1ENXU2TS9Kc3R6WWFHU3FBcW1zeEc0M0tJckZTZ3NBSVNUNS9jNXQyK1F0VzFBa0Vudm5IV3AyYVFhTWFVOFBoTVAyUHVJMEtPZUNSYnU2dERucjFSb0hnRDBldWJIUjZLSU1rbFN3ZFN0Mk9wV1hYbUtEZ3pyWllrenkreDFyMTZZck0wTmF2aHo3ZktBb2VnWG53eGoyZU9UcnIzZHUzeDYvc1FWQ2lOOVBBd0dqN3lzT1l6WTh6SWFISlJFc0JLQTJOVUV3YUtqK3VCS0FWRjF0cms4Y1kzbkxGdVJ5UlY1OGtmYjBwUHU3R01zYk54cDhDSTE5UGxKUllmbzVVcnlpdXZwcTUvYnQ4cVpOaVJzNkxNdVMzNithL1V6aVQ2TjdlcVFWSy9TSzJpKzNnc1VHQjlWVHA4eWRqR1NTSkRjMFdLajU1UTBic051dFBQZGN5dVZHQVBDaVJjazlydWxodDF1cXF0SmFXL1VLSm1FTWU3MEZOOTdvM0xhTlhIWFZuSCtVL1A3NG1oL21QcHhZYktIYTd5YS9CSnlwcDA2Wi9wWW5BSkN5TW9kZXN6MFZ4K3JWbnU5LzM3Rm16Znh0WkFESDZ0WEU3NS9ubjFLUWFtb005czVQVjFUWFh1dDUvSEgzd3c5Zm1TbzBjMjI5OHVjNk1LYWRuUkFPNjVXelh3NEZDOEpodGFYRnlIcTE4d053ckZzbnpYZFdESktxcXoyN2Rza05EZk5reSttVU4yODIxZGtvVlZZYXV1VmtEQmNWT2UrK3UvQUhQNUFiRzVFc3oxc0tGeFdSNWN2MWY5c2NHTFBQUG9PSkNiMXk5c3VoWU5HTEYrbkZpNWFySzF4WWFLTFpuZ0twcUhBLytxaDg0NDN4TVZqVFAyVk1xcXgwMU5XbFBYUXVVbG9xbFplbml3SUF3dGl4Wm8zbmlTZmNEejJVZnZveWRyc2x2OTkwc0JDS043UDBTdGt2WjRMRm1OcmNQTTgyRXdZQlNEVTFqbXV1MFN1bmo1U1ZlUjU1cENDK3pWUDhSQklpTnpTWW5WQ0YzVzVTV1preUNvemg0bUxYamgyZXA1NlM2K3VOZkIrazZtcGtvS2RqRm93aEdsMlFabGF1Tk41WmYzK216ZmJHUnJ1V3VjSkZSZTZkTzNGaFlmVHR0MUUwU2hZdjF1MXhuWWNrU1g3LzUrbE1BRUNFT05hdGMrM1k0ZmpTbDR6Zi8wcCtQL1o0d095OEVnQWFDRUEweW5XaTBaVnlKVmhxV3hzYkdqTDNrU1VBa0tWTDVmcDZ2WEltWUxmYmRmLzkyT09KL3UxdjB1clZ4TkpxWnBMZmo5M3VXY3VHTTBiS3lncnV1TU41MjIxNDBhSzBSODlGU2txa3BVczFzK3NNWUV4N2UyRnE2ajh4V0JBS1piVHdGWUJjWDArV0x0VXJadzUyT2wzYnRwR2lJbEphYXFyWm5rQ1dMY09MRmtGOHdqc0FjamprK25ybjE3L3VXTFhLWERnUVFnaGhqNGY0L2NqOFV2VXdQczR1WHpiWUEyZVhuQWlXZHVHQzlmVnFBYkRYS3pjMFdBeGxlckpjY050dGxzZWQ0c0pDcWFvcXZqZ0FXYnJVK1pXdkZOeHlpNVZlZ3poQ0pMOGZ5Yks1MTVPWUczM2RkWHBGN1pRRHdXSnNlcHNKYThrQWtGYXVsRmF1MUN1WEFXc3ZEQ0ZjVUNCVlZha3RMZkxHamE0ZE96Si9rZFBYVnJPM09KVFM3bTZrYVZsWUt5QWhlMzhwRlhyNXN1bHRKcEk1SFBLbVRicmpPUmVLbzY3T1UxSWliOWxpeXlza1M1ZVM0bUpxZHFRYXhqUStOenFMNjZ4YS9DN2FTR3R0dGJMTlJCd0F1ZW9xZTV2dDluS3NYbDF3KysyMnBBb2hSQW9McGVwcTA3MVpHTFBSMFN6dnJiZkF3WUpnVUcxcHNUNW1DRUJldno0WFZrWk15ZG9YSmhWWkpuNi82VXR6L0dsMGZCMmJiREg1RXUybW5UOXZmYjNhK0hqT3hrYUxoK2NucWFiR3lxQS9WYVU5UGFhUHlzQ0N0ckV5M0dZQ3dISE5OVkpOalY0NVEwWkhSODkxbkFNR3hjWEZwYVdsUlVWRkhwdXVYL2FTS2lwd1VaSHBrVjRZMCs1dVVCUzdMc3E2RmpKWXRLOVArL2hqNi9XTnd5RTNOdG8xMmJlam8rTlh2L3BWSkJLUlpkbmo4VlJYVjIrbzMzRFRUVGRkZmZYVmVvZG1GZmI1cE9YTFdYKy91YzhONHl4dmlMS1F3VkpiVzlub3FMa1BLQ0grWUZodkdwWnhsRkpGVVJSRlFRaU5UNHozOWZVZFAzNzh3SnNIdnZtTmI5NXp6ejNPN0haYnA0RmRMc252VjF0YTlBck9sdlVOVVN4ZGcrd0FrNU5xUzR1NXZyNWtHRHMyYkxCM0x3bU1jZngvQ1NhU0pDR0V1cnU3Ly9CL2YzajF0VmVaNWRmSkFhbXFRdWFESHQ4UVJhK1ViUllzV05xNWN5d1FzRmhkR1p1R1pRb0FVRW9aWTVEVXdpV0VLSXJ5eWl1dm5EWC9JR1dPV0N3Mk5qNDJORFRVMDlNVERBYjFpcWNqMWRRUUl5TzlyaERmRUVXdmxEMFc2RktvcWhsdE0yRndHcFlaZnIvLy92dnVQOWR4N3V6WnM0cWk0Sm5JRWtLR2hvYmVmLy85Tld2V0VFdXZkbUJnNFBEaHcyM3RiVDJCbm9uSkNZZkQ4Y01mL3ZDRzYyL1FPeTRsVWx4TWxpNDEzWXJJN29Zb0N4TXMydHViMFRZVGhxZGhHVmRkWGYza2swOU9UVTBkUEhqdzZUOCtIUXdHY2RMTGEydHZDd2FEaTB5T1IwQUlIZjNvNkRQUFBOUFIwYUZwV3Z3WGVqd2VUYlU2U2hZaE5EUG9UL3ZrRTcyQ2MyVnpReFFyWDhITXFTMHQxcmVaaUsrZVlHd2FsaWtZWTUvUDk3V3ZmVzNyZjIxTnZpQmlqQWNHQmtaSFI5TWNPNjlQUC8xMDkrN2RaODZjQVFCSmt1SVZIZ0NBK2F2WUxJUkkxZFdwQmpHbmxOME5VUllnV0d4OFhEMTVNcE5tdS9GcFdCWTRISTROR3pZVXpCNG5FNDFHaDBlR1V4MHlMd0I0OTkxM0E0R0FORE02RkFCS2lrdldybDI3dUhSeCttTjFFYjhmZXp5bW0xbFozQkJsQVM2RjlPeFoxdGRuc2JveU9RM0xHcC9QSjh1eXFxcUpxeUZqTEJxSnBqOXFqbUF3MkhycTgrbGZBTEIyN2RvbnZ2L0V5cFVyTSs5NmxjckxTV2twblp3MDl6SE9iSWhpZHBpMUJkbXVzU0FXaTUwNFlYcCtYSUw1YVZnTFpXSmlZbUJnSUI1TkFIQzVYQTg4OEVCOWZiM1A1NU1NakhCUER4Y1dTbWtHMUtjeXN5R0tYamtiWkR0WUxCRFFQdm5FWXFvUVFnVUZ5Vk9FYzlsVWFFcE51dWg0dmQ3YVZmWnRRK0p3U0RVMVJxWmd6SkxGSldpeUhTeTFwY1g2ZXJYeDNuWU96WFl1WnRjbUVwRmN0dDdHeGdmOW1hNjBFaHVpY0piVllMR3hNYlcxMWZSbmtSQmZyN2FrUks5Y0xnSms5VjJuUUNvcXJBemNtOWtRUmE5Y3BySWFMTzMwYWRyWFo3bFRsQlFYVzVtRzlRVVZmeHB0K2xzNnN5R0tYcmxNV1RySGxrQTBPcjNOaERVQTBwbzExcVpobWVWd09MQzFpM1ZxOXY5Q3AxT3ljQk16c3lHS1hybE1aUzlZdEt0THM3dzdIQUIydVFvYUc3UFRiQzhxS3BKbmR6OHl4bFN6M1QrejM2aW1hV0c3TDBDUzMyOWx0bUI4UXhUT3NoV3MrSHExWnZ0ZEVnQklaYVcwWm8xZU9YdkUrN0VTL3hkakhJMUcrL3I2MGh4eUphclI1QjcyY0RqYzJkV1pwcndGeE84M3RPN0lGZUlib3VpVnlraVdnc1ZHUnJRTW0rMk5qVm5vMW9zckxpNWV0bXhaY2l3WVk4ZFBISjh3czJ4TC8wQi9aR1lvQWNaWTB6VEY3bk5KU2twSVJZWHBUM1ZtUXhTOWNobkpVckMwTTJmb1o1OVpiN2FYbE1nYk51aVZzNDNYNjEyL2JuM3lUd2doN2UzdEwvejVoYUdoSVNQWFJFVlJQdnp3dzBna2t1Z2c5WHE5L2lyelRhSzBwcGVnTVM4TEc2SllPdE1tUVNTaUhqOXUvUkhWZk50TWNJVXh2dlhXV3l1V1ZTU1A3MU5WOWE5Ly9ldVBmdnlqMy8vKzkxT3AxNWtOQm9QSGpoM2J2WHYzb1VPSEVrK2RFVUszYkwzbEdqc1d3NWtGNCttNTBhWmtaVU9VYkFTTGRuWnE1ODliYmwybDJtYUNxOXJhMnU5OTczdGxaV1dKQ3lMR21GTGEwZEh4cjBQL1N0TU1QL1BKbVYvK3p5L2YyUDlHTkRyOWJMR3dzSEQ3UGRzZmVlUVJIdU9iSld0UG8vbHZpTUkvV0luMWFxMEdTNnF1VHJYTkJEOFk0N3Z1dXV2SFAvcHhaV1hsbkRHbGhKQTBmUWVhT3QyV1NneDAzcnAxNjVOUFBybUV6eWdvc21RSldiellkTEJtTmtUUksyY2Q5MkN4NFdHdHJVMnZWR3J4aGE4c2RERm5iR2hvNkVUVGliR3hzZVFmeGtPV3Boc2RBSUI5UHVJS0FJNGVQZnJtVzI5cWxwZkFUQXQ3UE5aVyt1TzlJUXIzWUdudDdYUmd3SHF6dmJUVWtjVm1lNEtpS0h2Mjdubjk5ZGREb1ZEeTRCbENpTnZ0SmpqbDJ5a3JLOXZVdUdueDRzV0piSTJOamUzYnQrL2pqejlPZFVoR0hBNnB1am9IbjBiemJiallzODFFQnV2VlduYjgrUEgzM25zUEpmV1lBOERLbFN2dnZ2dnUydHJhTkdPVVY2MWE5ZlAvL3ZucDA2ZC8rN3ZmZG5kM3h5K2RJeU1qSHg3OXNMNiszdmIrZDVSWWdpWWNOdGZZMERRYUNDQktUWWZTR0V2bjJ6QjY0WUwyNmFmbTNuQkNZcHVKN0RiYkVVS3Fxbjd3d1FmSmRSVUFWQzZ2L09sUGZ2clF0eDlxMk5nZ3A3NFJreVRKNC9GczNyejV6anZ2VEo1OGNmNzgrUkNmTmcycHFNQVdldmhtbHFEUksyY1J6MkRac2w1dHJYMWptQXlibkp3ODEzRXV1WFpoak4xNDA0M1htVm03YkhYdGFyZmJuYmdnRGc0T0p1NFQ3WVc5WG91RC9vYUcyTEM1OGRiR2NRd1dHeHhVTTFuNEt0NXM5M3IxeXRsdmRHeDBZbUlpT1ZoT3AvUGFhNjlOYzhpVmlvdUxFd1BuTWNhUlNJUXlxNHZxcERYOU5OcnM1enl6SVlwZU9ZczRCa3R0YjJlRGc2YmZjRng4ZDdnRld2aHFjbkl5K1NZT0FHUlpMdktadXpQRlpPNGJ4OGpTUjJIQTlOTm9zNVVXencxUmVBVUxRaUgxeElrTXQ1bXdmYjFhZzhMaE1MMWl5UzdUN1c2VFp6a1RVbFdWbGFYSU1hWmRYWnlhV2J5Q3BWMjRRQzlkc2x4ZDJiTE5oR1g4cWhaTzhLSkZaTmt5MHpVV3hxeS9uOU9HS0h5Q1JlbjBlclZXZ3lXdFdHSExOaE81ZzJ0WXNjZGpaUW5KK05Ob1BzMHNMc0dpQXdPWnJsZTdlYk9WdWoySFVVYWpNUzUzaFhHUzMyOTBzN0VFbmh1aWNBbVcxdGFXMFhxMTVlWHkrbG1qVnZLUngrTnhKUFhBVFUxTm5lODRuNlo4aHF3L2pRNEVnRU0vaVAzQmdxbXA2VzBtckltdlYxdGVybGN1MXhVWEZ5Y0dSMkNNRlVWNS9XK3ZYN3AwU2RPMFROZHVtQTlac29Rc1dXSTZXRE1ib3VpVk04MytZR2tkSGJTejAzSjF4WEdiQ2NQbVhiZkQ3RjJoeitlcnE2dEwvQjVDU0d0cjY4OSs5clBmL085dkxsNjZtUDVZQ3l3L2pZYUpDZGJmcjFmS05MdlBYMks5V3BPbllWb1d0cGt3b0grZ1B4cU5KaWZKNFhENFRHNVZRZ2k1L2ZiYnk4dkxrMGNMZGdlNjMzbm5uYzh1Y3hoV0VOOXN6T3g5Tk1ZUUR2T1lXMkZ6c0doL3YzYm1qTVZVSVlSa3VlRDY2N08yc3UrOFJrWkhqaHcrTXFjZnkrUHhsSmxmbG5MOXV2V1BQZmJZa2lWTGt0Y0tURCtjS3hNV20xbUpEVkZzWmZqNUxtTnNjRkJuYUJnaHNZOCtZaU1qRm9NRmdMMWU3UFBSenM1WmM4QWxpU3hiWm1XZWt4bXhXR3g0ZUxpenMvTWYvL2pIeWRhVHljK1BHV04rdjkvQ3Ftc1k0MjEzYjZ1c3JEejR6NE9uMms2TmpZM0ZZakdYeTVYNW9pRHpJaFVWbjI4MlpoeWZEVkdNQmd0VU5mTGFhMnBycTA3ckp4SXgvWTFKd0JpbXBzSjc5c3pLSlFEMitRcWZlc3F1OWR4VGFXdHIrL1Z2ZmoweU1oSU9oK2NzQ1NsSjB1Ykd6WVdXdWo4d3h2WHI2NjliZTkzNCtQakl5TWpJNkFnQTFQSjVzazY4WHNudk43MUVWSHhEbE9GaGFVR0NoUUFnSEliSlNaMWdtWHBMVjZJVTVpejhHbytwNVh0TXd5TFJ5TWp3aUJKUjVxU0tVcnBtelpxdFc3ZW1PdEFJU1pKS1MwdEw3VjBzRGdDbXBpQjVpZ3JHWlBIaTFBZWtnREdFdzdHalJ4MFRFK2tXQ3dFZ0pTWFNpaFVHNzZzTUJ3c2hoUEgwZjF4ZCtmdDUvMFdFRUVJWTRUbVBqUUdBTVZaVlZiVnIxNjdsV1p3alpCREVZc3FMTDJwdGJaK2ZhWXhCVVF5ZStGa29qYjd6VHV5OTk5SmRiUmh6TkRSNEhuL2NZSnZFVExDKzBBQUJZeXh4QjFkUVVGQlNVdEt3c2VHKysrNWJtNXNMSndGQU1NaEdSdVlteWRyM1VOTWcvZnc4eGxBc1pyeWRJNEkxemVmMWJhamZJRW1TeSsxYVdyNjB1cVo2ZGUxcXY5OWZZUFk1U1RiWmV3MUovM3RNL2lFUnJHbDFkWFcvK01VdkpFbVNKQ21udzVRblJMQ215YktjWmlTN1lKYjVocDRnR0NDQ0pYQWhnaVZ3SVlJbGNDR0NKWEFoZ2lWd0lZSWxjQ0dDSlhBaGdpVndJWUlsY0NHQ0pYQmg1bGtoWTFuWU5Xb3VnQVg0by9rQ1lQcS9MREQ1aHd3SFM1S2srRG8rRnNhUlpRSUF1OTNZN2RZcjk1OEhZK3p4NEtLaUxKMFJ4ckRIWTN6a0REWStlUkpVTlF0RGhPZUJNWmJsTEgxOGVjVEk5QlpiNGNKQ1VsNXU4RVNZQ0pZZ0dHY29mWUpnbGdpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhTUHkybXQ2WlFUQk5FZmtsVmYweWdpQ2FRNGtTWHBsQk1FMDBjWVN1QkRCRXJnUXdSSzRFTUVTdUJEQkVyZ1F3Uks0RU1FU3VCREJFcmdRd1JLNEVNRVN1UGgvNVNTaFRuMld4bDhBQUFBbGRFVllkR1JoZEdVNlkzSmxZWFJsQURJd01UZ3RNRE10TURGVU1UTTZNelE2TlRVck1EQTZNREJrRUFUM0FBQUFKWFJGV0hSa1lYUmxPbTF2WkdsbWVRQXlNREU0TFRBekxUQXhWREV6T2pNME9qVTFLekF3T2pBd0ZVMjhTd0FBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTEwLTMwIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJDbGllbnQvQXV0aGVudGljYXRvciBDb21ibyBDZXJ0aWZpY2F0aW9uIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVQUYxMDAwMjAxOTA1MDYwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy42IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMTAtMzAifSx7ImFhZ3VpZCI6ImEwMjE2N2I5LWFlNzEtNGFjNy05YTA3LTA2NDMyZWJiNmYxYyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiYTAyMTY3YjktYWU3MS00YWM3LTlhMDctMDY0MzJlYmI2ZjFjIiwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IDUgU2VyaWVzIHdpdGggTGlnaHRuaW5nIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyOTQ3MywicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9LHsibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsInNlY3AzODRyMV9lY2RzYV9zaGEzODRfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsImNyZWRCbG9iIiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6ImEwMjE2N2I5YWU3MTRhYzc5YTA3MDY0MzJlYmI2ZjFjIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwibGFyZ2VCbG9icyI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlLCJzZXRNaW5QSU5MZW5ndGgiOnRydWUsIm1ha2VDcmVkVXZOb3RScWQiOnRydWUsImFsd2F5c1V2IjpmYWxzZX0sIm1heE1zZ1NpemUiOjEyODAsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0zNX1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjQwOTYsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjk0NzMsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsInJlbWFpbmluZ0Rpc2NvdmVyYWJsZUNyZWRlbnRpYWxzIjoxMDB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDUtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTA1LTAxIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMzQyOTM4ZTBlZTY1ZDUxZWUwNTYxMWMyODIwMmM2NzRkZmQ1YzlkZSIsImQ1M2VkZDIzYWRiNmI1YjRhZGQxMDJmYjRhZDFiNDAzN2ZmNGE3YWUiLCJhMTgzMzUzMmU4MWJjY2M3OTI0NWZhNmY1Mjk2YzQ4MTVkZmY1OTljIiwiZjVmNmVlZjcyOWEwMjY0NzUyMDUzYzIyZTg5ZmMzMDI4ZjE1MzZjMSJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIzNDI5MzhlMGVlNjVkNTFlZTA1NjExYzI4MjAyYzY3NGRmZDVjOWRlIiwiZDUzZWRkMjNhZGI2YjViNGFkZDEwMmZiNGFkMWI0MDM3ZmY0YTdhZSIsImExODMzNTMyZTgxYmNjYzc5MjQ1ZmE2ZjUyOTZjNDgxNWRmZjU5OWMiLCJmNWY2ZWVmNzI5YTAyNjQ3NTIwNTNjMjJlODlmYzMwMjhmMTUzNmMxIl0sImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IEZJUFMgU2VyaWVzIHdpdGggTGlnaHRuaW5nIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyODcwNywicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0wOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDItMDgifSx7ImFhZ3VpZCI6IjJjMGRmODMyLTkyZGUtNGJlMS04NDEyLTg4YThmMDc0ZGY0YSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiMmMwZGY4MzItOTJkZS00YmUxLTg0MTItODhhOGYwNzRkZjRhIiwiZGVzY3JpcHRpb24iOiJGZWl0aWFuIEZJRE8gU21hcnQgQ2FyZCIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUIyRENDQVg2Z0F3SUJBZ0lRR0JVclFiZERybTIwRlpuRHNYMkNCVEFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFc0ZZRUVoaUp1cXFuTWdRalNpaXZCalY3REdDVGY0WEJCSC9CN3V2WnNLeFhTaEYwTDh1RElTV1V2Y0V4aXhSczZnQjNvbGRTcmpveDZMOFQ5NE5PenFOQ01FQXdIUVlEVlIwT0JCWUVGRXU5aHlZUnJSeUp6d1JZdm5EU0NJeHJGaU8zTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJREhTYjJtYk5EQVVOWHZwUFUwb1dLZU55ZTBmUTJsOUQwMUFSMitzTFpkaEFpRUFvM3d6Njg0SUZNVnNDQ1JtdUpxeEg2RlFSRVNOcWV6dW8xRStLa0d4V3VNPSIsIk1JSUJmakNDQVNXZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQVhNUlV3RXdZRFZRUUREQXhHVkNCR1NVUlBJREF5TURBd0lCY05NVFl3TlRBeE1EQXdNREF3V2hnUE1qQTFNREExTURFd01EQXdNREJhTUJjeEZUQVRCZ05WQkFNTURFWlVJRVpKUkU4Z01ESXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTkJtclJxVk94enRUSlZOMTl2dGRxY0w3dEtRZW9sMm5uTTIveVlndmtzWm5yNTBTS2JWZ0lFa3pIUVZPdTgwTFZFRTNsVmhlTzFIamdneEFsVDZvNFdqWURCZU1CMEdBMVVkRGdRV0JCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFmQmdOVkhTTUVHREFXZ0JSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QU1CZ05WSFJNRUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUJCakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUF3ZlBxZ0lXSVVCK1FCQmFWR3NkSHkwczVSTXhsa3pwU1gvelN5VFptVXBRSWdCMndKNm5aUk04b1gvbkE0M1JoNlNKb3ZNMlh3Q0NILy8rTGlyQkFiQjBNPSIsIk1JSUIyRENDQVg2Z0F3SUJBZ0lRRlo5N3dzMkpHUEVvYTVOSStwOHoxakFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFbmZBS2Jqdk1YMUV5MWI2aytXUVFkTlZNdDlKZ0dXeUozUHZNNEJTSzVYcVRmbysrMG9Bai80dG53eUlMMEhGQlI5U3Qra3RqcVNYRGZqaVhBdXJzODZOQ01FQXdIUVlEVlIwT0JCWUVGTkdobUUyQmY4TzVhL1lIWjcxUUV2NlFSZkZVTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUMzc1QxbEJqR2VGK3hLVHB6VjFLWVUyY2thaFRkNG1MSnl6WU9oYUh2NGlnSWdEMkpZa2Z5SDVRNEJwbzhycm9PMEl0N29ZakYya2d5L2VTWjNVOUdsYXF3PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIyYzBkZjgzMjkyZGU0YmUxODQxMjg4YThmMDc0ZGY0YSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6NiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJuZmMiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMjQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA0LTI0In0seyJhYWlkIjoiMDA2RiMwMDAyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiMDA2RiMwMDAyIiwiZGVzY3JpcHRpb24iOiJIYW5rbyBVQUYgQ2xpZW50L0F1dGhlbnRpY2F0b3IgQ29tYm8gZm9yIGlPUyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfZGVyIl0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9kZXIiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBd3dBQUFFc0NBWUFBQUJ1VERSa0FBQUFCbUpMUjBRQUFBQUFBQUQ1UTd0L0FBQUFDWEJJV1hNQUFBN0RBQUFPd3dISGI2aGtBQUFBQjNSSlRVVUg0QVVVRUJnVVNld1J6Z0FBSUFCSlJFRlVlTnJ0M1grTUhHZWQ1L0hQVTlWZC9TTkdqQU5SREF2Wk5wdnh4RGczTi9IR1M5QTRDb28ybUZzaE9ab2pXaTJDTEFpRDd5Q2NRTVQ1ZytUMjdpQ0pkQW1ySUJHUXdnL3RFU0lqbE1OeXBJZ2o1R1FSSlJiY0JobWZOODdFbnBBWndBdEdRR2JRSlRQOXM1Nzd3ejFKSEhzOE0xMVBWVC9WL1g1SlZyU0x1NnI3KzFTMzYxUFBMMk90RlFBQUFBQ2NUMEFKQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFCQVlBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUlEQUFBQUFBQURMQ3BRQWM4YVVHMlc5SldqcjhzQ29ab3plRW9ZYS8vTkYrd0hmMy9zdkl2UHhJTlM3T2xiSGJVZlB0STMrR0xmMG0yM1ducVpsQVFBQUNBem93WEZqTmhVcnVqeHNhMnNRYUN5b3FGYVdwT0s1ZjgvM0cyOGJhRU5nTkJJWVRTclFaTlM5cW45Wk5XckZPbXc3ZWthQlRoV2JtcTFaVzZmMUFRQUFDQXk0VUVBSTlhNE5GWTJzcGZVTFpWWHkvTG1Md1prUUlVbXFTQytVekxHMmRNeElKMFliZHBvckF3QUFnTUF3bE9hTUtiY2liWlowVmNGbys0YUthclMyRklZYUQ2Vng2VXdQUkx1dHh6b0ZUUytXOU16RXZGM2d5Z0VBQUNBd0RIUklXQ3JxblpIMGw0V0tka1dVWlBXTHY2QmRCV2xYcVhHbTk2RVQ2eWZOdHY2RitROEFBQUFFaG9FTUNWVkswck13MUhnWWFqd3FTck5sTTljS2RKQ2VCd0FBQUFKRExwMm9tTTFCckhjWHlycSthcnJ6RWVCTUVLaFdrajZ6M1BQUXNIcTAwdEt6VEpvR0FBQUVCbmhyenBoeXM2S3JpN0Z1TEFlcUthUW1XUWhEalZlbDhUalV3a3pKSEdvMmRZZ2hTd0FBZ01BQWJ5ejNKa1FWVFpVa3R0cnJrOEJvSkFvMUZWVTB0ZHpyc0xWcGoxQVpBQUJBWUVCZlRFZG1lekhRZGVWQWsvUW0rR1c1MTJHMlloYmFiWDJ2Mk5hVERGY0NBQUFFQm1RV0ZNcUJQbGd0ZEpkQ2hiY0NvNUdvcUwwcWF1OU15Ung0dWFvZk1Fa2FBQUFRR09EY25ESGxWa0hYRmtMdElpamtVeFJxS21wb2l1QUFBQUFJREhEcVpOWHNMSmIxa1lqVmpnZ09BQUFBQkFZc1d4NTZWQXBVazZFZWd4d2NpazBkWUk0REFBQWdNR0JOVGxUTTVzanFVd3c5R3A3Z0VKZDEvVXpSTURrYUFBQVFHTEN5b3h2TnlJWWxmYlFjYUpJZWhlR3lQRGs2RHJWck9qTDdXWTRWQUFBUUdQQ0s1UW5ORzR2YXl4NEtReDRjQXRXcWdUNy9mTmtjYmpUMFhUYUFBd0FBQklZaE4xTXlXd3NsZlN3S0dINkVWeFVEVFJZcm1qeFpNZzlGVGYyUVlVb0FBTUJuUFBOT3dkR05adVFYa2ZsNEZPcUxBV0VCS3lpRitwQXQ2LzZaa3RsS05RQUFnSy9vWVhEc1pOWHNmS1BWUjRJQ3k2UmlEWW5kYUNRSzljVmZST2F4c0tYdjBOc0FBQUFJREFOcWVWSnppVW5ONk9XTFdOQ3VPTlM3WmtybUgwY2JkcHFLQUFBQVh6QWt5WUhweUd4L1kxMWZLZ2FhcEJybytjdjRhbS9EeCtlTUtWTVJBQURnQTNvWUVwZ3pwdHdwNnNQVmduWlJEVGo3VWhhMEt3NDBkcUppdmpxMlpHZXBDQUFBNkNkNkdIcDAzSmhOdHFRN0M0UUZwUEhGREZRckc5MDdVelEzVUEwQUFFQmd5Sm1UVmJOelEwWDNzd0lTMGhZVnRmZjVzdmtzUTVRQUFBQ0JJUWZtakNuL0lqSWZMMG1mb1JySVNqSFFwQzNyL3VQR2JLSWFBQUNBd09DcDQ4WnNpaVBkeGhBazlPV0xhalN5b2FMN1QxYk5UcW9CQUFBSURKNlpLWm10MWJMdURFT05VdzMwVTBuNnpFekpmSkJLQUFBQUFvTW5UbGJOemlqVUZ3UERSbXp3UXhScTZvV1MrUWZtTlFBQUFBS0RCNWl2TUh5YUxUMHdYOUtlaHZUbE9OYWNqKzh4RERWdVM3cVRlUTBBQUlEQUFQVEJ4THhkMkxKb245cGN0N2ZXcmZhMVloMzI3c3NicUZZdEV4b0FBQUNCQWVpcnNTVTdlM25kM2pkZjBwNW1Sd2U4K2dKM0owTlBSMlk3TFFVQUFOTEFUczk5MEd6cEFkZkhqSXJhUzJYVE5URnZGeVR0UDI3TW9WSkpmMWNNTk9uTGU2c1c5UG5weU55OXRXbVAwRklBQUlEQWtIT2pMZnU0NjJQK3Ntb0lEQm5aWnUxcFNmZWRxSmlEa2RXbmZObkFqOUFBQUFEU3dKQWtvRWRqUzNaMmM5M2UycEMrSEZzdCtCSWFXSFlWQUFBUUdBQ1BiRm0wVC8ycHJGdmJiVDNtdy91SlFrMFJHZ0FBQUlFQjhNakV2RjM0aTZiOVJyT2ovK3hEYndPaEFRQUFFQmdBRDQwMjdMU3A2eFlmZWhzSURRQUFnTUFBZUtobWJmMHZtdlliaTIzZDNlL2VoaWpVMUV6UjNFQ3JBQUFBQWdQZ21hMU5lK1JQWmQzYTZlaFlYME5EVVh2WnB3RUFBQkFZQUE5TnpOdUZkelRzRnhvZFBkVFA5OUZkY3BYUUFBQUFDQXlBajdZMDdNRitEMUdxRnZUNUV4V3ptZFlBQUFBRUJzQkRXNXYyeUdKZGQvUnppRklrM1g3Y21FMjBCZ0FBSURBQUh0cG03ZW1ncVh0YXNRNzM1UXR2TkZJdDY4NDVZOHEwQmdBQUlEQUFIcXBaVzcrOGJ1OXJkblNnWDZFaGpuUWJvUUVBQUJBWUFJK05OdXoreGJidTdzZTV3MURqbmFJK1RDc0FBQUFDQStDeHJVMTdwRis3UXhjSzJzVWVEUUFBZ01BQWVHNjBZYWNYNjdxakg2RWhLbXJ2VE1sc3BSVUFBQUNCQWZEWU5tdFA5eXMwRkFKOWpwV1RBQUFBZ1FISVFXam94ODdRZ2RGSUpkSW5tQVFOQUFBSURJRG5KdWJ0UXREVVBWbUhoakRVZUN2U0ZDMEFBQUFHTmpETUdWTSt1dEdNMEtUSXU1cTE5WDZFaGlqVUZQTVpBQURBd0FhR1RsRWZydFMxa1NZRm9hRjNoVUNmSTNnREFJQ0JDd3pUa2RsZUtHZ1h6UWxDUThJZkJLT1JEVXY2S05VSEFBQURFeGlPYmpRajVWQ2ZwQ2t4cUtGaHFhbXZaN2w2VWpIUUpQc3pBQUNBZ1FrTUc1YjAwY0NJSVJRWVdQMVljalVxYWk5THJRSUFnTndIaHBOVnM3TVlhSkptQktIQnZVcWtUMUI1QUFDUTI4QndkS01aS1ZwOWhDYkVNSVdHZWtkZnkrcDhZYWh4aGlZQkFJRGNCb1kzdkt5YkdJcUVZYk8xYVk4MHBDOW5kYjVDUVgvTHFra0FBQkFZY21lbVpMYXlLaEtHMVpaRisxU3pvd09aL0VDd2FoSUFBQVNHdkwzaE9XUEtCYU9QMFhRWVpxTU51eityNVZhTGdTYlowQTBBQUFKRGJyUUt1allJVktQcE1QUmYzcWJ1eVdvU2RDSFE1K2FNS1ZOMUFBQUlERjQ3dXRHTVJFWHRwZG1BTTNzMExOWjFSeVkvRkVZanJZS3VwZW9BQUJBWXZNWllhdUJzMjZ3OW5kVWs2S2lvdlV5QUJnQ0F3T0N0RXhXem1UMFhnSE50V2JSUHRkdDZMSXR6dmVGbDNVVEZBUUFnTUhncHN2b1V6UVdjWDlqU2Q3S1l6MUFvYU5lSml0bE14UUVBSURCNFpUb3kyNW5vREt5c1ptMjlLZDJWU1RpeHVwR0tBd0JBWVBCS09kQUhhU3Jnd3NhVzdHeWpvNGZTUGcvTHJBSUFRR0R3eXNtcTJVbnZBdkl1cXh2c3FLa2Z4ckhtMGo0UGU2RUFBRUJnOE1LY01lV2kxVWRvSnVTZE1YcmZUTWw4TU8yOURHclcxcHRHWDAzOWh5TlFiVG95MjJsWkFBQUlESDNWS3VqYXdJaGxIREVRb2xCVGNhVGIwZzROV1ExTllxZ2dBQUFFaHI0cmhOcEZFMkdRaEtIR3N3Z05XUXhOb3BjQkFBQUNRMSt4TWhJSURiMnJXVnR2VzMwcjdjOVNNbm8vTFFvQUdFYkdtSXVOTVpQR21KdU5NZmNZWXc0YVkrd3FmNzdSL2J0VHhwZ0pZMHlGd0pBQXd4MHc2S0doWGRKL1RQTWNvdzA3M1lwMU9PM1B3YjRNenY4QnVtY04vK0NzOW1kTFhzL3Y2UTJCVGVuUExWeS94aHBqRHFiMFhyWU00blhzdzNmVVFXMlgvOXljMDkrRXFlNTErMGRKVDBuNnRxUjlrbmF2NFJCN3VuLzMrNUorTG1uUkdQUDVidkR3Tmp4NEdSam9YY0F3NkM1UG1tb3dialQwM2RUREQvc3lZTEM5T2NWalgwWjVKVW03alRGdm93eTVjbzJqNHh6S1dWQzRwUnNTdnIvR2NMQldkM1dEeHhQZE1PSmRjQ2g0ZWlOMUhkOUZyUFdHdUZPVzA2ZFRTeHMwbjlYN2owSk56UlRONzBkYjl2RTBqci9OMnRNekpYTWdDaldWWnZBNWJzeDN0MWw3bWlzU0E2aVc0ckhmUTNsZmNhT2sreWxEYnJqNE4rVVJhKzJwbklTRnFXNUlTTnVPN25rZU1jYmNacTA5U1dCWXdZbUsyVndPTk1sM0VXdTlJYzc3WjRpSzJqdFRNcWRHRzNZNmxSdjZwZzdFWlYyZjVvcGpVYVRySmUzbmlzUUEycER5elFIT3VKbkFrQS9kM2lBWFQ5Y1A1T0N6WGl6cHYrdk1NS0lzN2RhWm5yZC9iNjMxb2s3ZURVa0tZcjJicnlPR1RTSFE1NDRic3ltTlk5ZXNyYmZiK2w2cW9TZlVWTm9yUHdGOWNrMmFCeCtrK1I1Snc1TXhab0l5NU1MMWpvN2o5WENrYmpENllSL0N3bXQ5MzVlNVRsNEZoamxqeW1rT25RQjhGUmlOVkNKOUlxMmI3bUpiVDhaV0MybCtobVpGVjlPU0dFQWJVejcrSlpUNEZUc3BRUzRNL0hDa2JsZzRJRDk2QWIvaXcrUndyd0lETnh3WVptR284V2FrOTZWeDdDeDZHWW94azU4eGtOSit1bmdwSlg3RnpaVEFiOE13SEtrNzRkaVhzTERzMi8zdWdmTXFNSEREZ1dGWEN2V2h0SllwVGJ1WElRaFVZNGxWRE5qTjBjVVpuT1lLS3YyS0hjWVk1akQ2YlJpR0kvMDMrVG0vNk9zWi9TYjVIUmhPVk14bWxsSUZwTWpxVTJrTVRhcFpXMi9GZWpUVkh4VG1JR0d3dkRtRGN4Q3l6OFlxaVg0YjZPRkl4cGozNnN3ZUNWNEdha24vWWVnREF6Y2FRUGU3RUtqV0t1amFOSTY5V05XUFV3MDdUSDdHWUtsbGNJNDlsUGtzZCtWbDU5dGhNK2pEa2JyWDNaMDUrSDcwWmFFRUx3TERuREhsUXVDc213dkl2YWlvdlVjM0d1ZkxvRTdNMjRWbUo5MGY2NldpM2trTFlrQnN5T0lrL1J4bTRLbnRsTUJMZ3o0YzZXUEt4MUxIZlhuSTRFVmdXQ3JxbldtdUVRL2swUnRlMWsxcEhEY085Sk0wM3pjYkwyS0FYSlBSZWQ1TXFjL0NiNGlmWFBSOGV6a2NxZHU3OEpXY3RNTytmanhrOENJd1JOSmY4ajBFemxZb2FGY2FrNGpIbHV4c3A2TmpLUWFHeVRSNlI0QSsySmpSZVdxVStpeDMwZXZpM1EzMXhYTHpaTnZYMVpIK1hjNmE1UDFERnhqbWpDa1hDdHJGMXhFNFYyalRXVG1zWWRPZC9GeHQ2RXBhRHdNZ3E2Ny9UWlQ2SEN5elBwanQ0ZXR3SkpkTCtqNGlhWmVrc2RmOHVVclNweDJlSS9NOXkvb2VHQmp2REt5c0dHZ3lqVjZHU2t2UHB2bStDeDNtSkNIZk1uN0NUY0ErMTAyVVlPRGF3OWZoU0s0bWMwdlMzMXRyYjdUVy9zaGFlL0kxZjQ1YWErL3Zob2VuSFp4bmQvZDlEMDlnWURnU3NPck45MSs3UG1iTjJucWFrNS9EVU9NTVMwTE9aVG12WUF2bFBzY2VoaVY1Rlo0SGVUalNYems2enFldHRROWU2QzlZYTA5SytvUm43OXYvd01Cd0pHQU5nYUdnWFNuZGZQODh6ZmRkZWxudm9QV1FZN1VNejdXYmNwOFh3NUlHcXgxOEhZN2tZdjdDSTVLK3RaYS9hSzA5S3VsZUIrZThKc3NpOVRVd3RDSTJyQUhXb3Jxbzk3Zys1bWpEVHFlNTh6TzloOGk1RFZtZXJGOXJxM3Z1azVUQUN3TTdIS25MUmUvSmc5YmFwWFVHaktReTNXQ3UzME9TcnVKN0NLeXVHS1N6SWtJN1R1K0pENzJIeUxsck1qNWZsWktmSS9OeDJqZ255QTcwY0NTSFFmM0g2L3o3Unh5OS84eStIMzBOREFYRDVpekFtcjZvUmlNekpiTTFoVU9uT2l3cHBmY01aR0ZqeHVkakNOLzVzWUJDZnczNmNLU2FnMk04WXExOWNUMHY2UFpHZk5QQnVUT2JhOVczd0hEY21FMUJ3TnJUd0RvNDc1RXJOaldiNWh1MloxYUVBUElvNjkxVTMwckp6MnVLRXZUVm9BOUhjckdrOFQvMytEb1gvLzVtOXFDaGI0R2hXTkhsZkErQnRZdEM5Lzl3MXF5dHQySWRUdTE3YnJTVGxrUGU5R2wxbnN1by9Ia3hMS2wvMzRPS0JudDFKTW5Oa3NiUFpmeTYxOHJzUVVQZkFrUFlGa01WZ0hWS1k0aVA3ZWlaMUg1Z0F0VllYaFU1bEtTYnY5ZkpqUHNvKzRvWWx0UWZyb2FOSC9MNE03b1lldmk3SGwvM2tvTnpaL2Fnb2RDdkZncEN2WXZ2b3QvS1J2ZitzbXFHN25NM1czcGd0R1VmOS9UdFhTVnAydVVCNDRLZVQvTU5kNWRYUGNJM0NqbFNTL0RhQjlYak1xbkdtTW82VjFvWkZyZDA2NHBzWGVmZ0dENFBSNUxjOUtEOHZzZlh6ZVhwWXVoTEQ4TnhZellGUmp4MUJOYWI4Rk5ZS0dCc3ljNm0vSjZ2b09XUU0wbVdWUDFkZ3RlK25kS2YxdzVqekFSbHlFNTNPTkpkRGc1MWdHcW1Lck9leWI0RUJ1WXZBRDErWVZNYTRwUG1QSVpRZk4rUk96MHZxV3F0VGZKZHFsSDZGVEVmS2x2RE1CekpsVDhNeGYxSFAwN0svQVdnZDJuc29Kem1QSVl3MVBpY01XVmFEam5TNjdqbXA3di83WFVld3daS3Y2S2JLVUdtQm40NGtxczlHTmE3cENxQllUMG5EVmhxRWVoVktrTjhBcVg2bzk0bzZ5MjBISEtrMTNITlArNys5MlNQcjcrRzBxK0lZVW5aM1VnekhBbjlEd3h6eHBUWmZ3SG9YUnBEZkY2dTZyZXAvdEMwR1phRTNOd3NKVmxTZGFINzMxLzErUHFOdE1BRi9RMGx5QVREa2REL3dNQ1RSaUJoWUFnMTd2cVlFL04ySWRVZkdzTkRBdVJHa2lWVmw5ZFYvMDJQcjk5RCtTL29ydTdUYjZSckdGWkhndStCZ1NlTlFITEhqZG5rK3BocFRueG1HQ0p5SkVtNFhWNVgvWVZlRDhBbVphdmFUZ25TdzNBaytCTVllTklJSkJaRjdvY3VtTmpKSmpJckJZWWFFNStSRTBrbUhzOTEvN3VZNEJoVm11Q0NycU1FdVFoa0RFY2lNQ1MrY2VCSkk1QlVMT2RQSVdPYjdpWXlERWRFVHJpWWVQenJCSys5a2lhNElJWWxwZXNxQjhkZ09CS0J3VWxncUZGMklQRTM5eExYaDdSRnBickRyREg2TXhvT09kQno3NTIxOW1UM3YwbStTMitsQ1ZaMUxTVklqWXZsYXhtT1JHQklKbzF4MThBd01rYVhPZzhNVnYrYTZwdnVKSnBNQ21URjFjVGplM3Q4M1dVMHdhcHVvZ1JwL0x0aUppVHRjSENvbjFKTkFrTWlhWXk3QnBDVEh4dWp6VlFCbnQ4d0pWbFM5ZlVCb2RlVng5NURTNndlNmhLMkZjN1B4VzdhVHkvM3RJSEEwTHNVeGwwRHc2Z1lhTkwxTVV2MWRQZGlDTVdRSkhqUFpTL1ljejIrYmdmTnNDWlhVd0xuWEF4SGVwQXlFaGhjbk8wU1NnNzRxV1p0UGRXdlAvT1hrSU92UVlMWHZuNFlScytyamhsanR0QVVxMkpZa2tNT2h5TTlSVFVKREE0dVNQZmpyZ0hreDlHTlpvUXF3R01iSEI1ckxzRnJlYmkydWozc1dlR1VxK0ZJUnlrbGdTRXhoaVFBN3VSeEVZRktuWGxNOEZxU0pWV2ZlZDMvL1ljRXgrTGgydHBjVHdtY1lUZ1MvQWtNREVrQTNDbVVsYnUxeU9NT2dRRmVjM1o5V210ZlRQRHlLMmlLTlpsYTVYOWZwRVNyWXpnU3ZBc01BSVk4NUZpOWlTckFZejB2cWJyQ3lqQ1A5SGc0VmhSYm05MFhHcGJFNW1GcnhuQWsrQk1ZVGxRTVA0QUFBQytsdEV4bnI4dEw3cUZGMW94aFNja3hIQW4rQkFZQU1LR3VwQXJ3VkpJbFZWZmFwTzBaendMTUlMcUZFaVFLeW04VHc1R3dCb1hNa2ttc3NrSUtucFkvWDdRZm9Bb0EwTE5hQ3NkOEtjRnIzeXpweFNGcmc5c2wzYlhPMSt3d3hrd3dIS1puTG5wb0dJNUVZSEFvMXRzSURBQ1FpUlBHR0txd1BrbVdWUDNwQ3YvL0Z4SUdtR0hiTWJmWE9RYzdKWEhEMnBzcEI4ZGdPTklRWUVnU2dNeUVSdHVvQWp4MVRRckhUTEpLejZZaGJJTmprcDd1NFhVM2MvbXVYM2M0MG00SGgySTRFb0VCQUJ6KzRCaXhjUnQ4bFdSSjFmUE9WVmhoNWFTMUdzYjVQb3ZxN1duMWp1N1NvT2Z6VFM3dEZURWNDUVFHQUFEV3diZVZpYllNYVR2MCtyUjZwYVZCNTdtMFY4UndKUGdYR0ZnZEJRRGdJd2NyRXYzNkF2L2J2VDBlYy9jd3RrWDNhWFV2dzVLK1lveXBjRFd2V1UwTVI0S1BnUUVBQUU4bFdWSlYxdHFsQy96UEN3bUN6TEQyTXR6ZjQrdTJjeW12MlUwT2pzRndKQUlEQUFCRG81Ymd0YXVOa1g4dXdiR3JROW9laDNwODNYVmN5bXZtWWdnZXc1RUlEQUNRampsanlsUUJua215cE9wcVkrUi9sK0RZN3hpeWRxaEtrclgybEtSSGVuajlYUXhMeWhURGtRZ01BSkNPUmxsdm9Rcnd6QlVKWHJ2YWJzNi9UM0RzdHc1Wk83dzJJQjNvOFJpdkg1YTB3T1dkQ29ZakVSZ0FBQmdxU1piN1hXMDM1ejhrT1BabFE5d21qL2I0dW8rODd2OStqc3M3RlF4SElqQUFBREJVOWlWNDdRVjNjN2JXdnRpbjk1VnIzYnIxc29mQ0hnZXJYbUYxUDZjRUJBWUFTRTI3cmlXcUFGODRHUE8rbHQyY3Y5bkg5NWRuRC9mNHVxdTVzbE4zRlNVZ01BQkFhclpaZTVvcXdDTnZUL2o2WDYvaDc4ejM4ZjNsMmM5NmZOMU5YTmFwWTk4TEFnTUFBRVBqa2lRdlhtVVBobVhQSkRoRmJWZ2JwanNzNmZZZVhzcXdwR3l3N3dXQkFRQ1FZMlBXV3RQTEgvVytNM0ZlWFpyZ3RXc2RhdlJTZ25Oc0dQSnIrWWtlWC9kK2ZnWlN4NzRYQkFiM1RKem9CeE1BZ0RRa1dWSjFyVU9Oa3ZRd1hEUGtiWEdreDJOTk9hZzlMdXd1ZW5JSURNN0ZWbk9VR3dEZ21TUkxxbVp4TTdweG1OdWlPK1NybDJGSnU0MHhiK1B5WHRFM0hSMkhDZVlFQmdBQUJsNlNwVXZYMUhOdXJUMlo0Qng3YUNMOW9NZlhYVS9wVnZTLzFOdHUycS9IQkhNQ0F3QzQxZW5vR0ZXQUx4eXM4dks3ZGZ6ZHB4Tzh6NkYrVXQ3ZFViaVgrazF4bFYvUUFRZkhZSUk1Z1FFQTNJcU4vaDlWZ0VlU0xsbjYrM1g4M1I4bk9FK1ZwdXBwWitIZEdxNDVJT3QxeU5GeG1HQStCQXFaM1NnVTlEemxUczlNMGR4QUZkeGRxMk5MZHBaS0FBUHZrb1N2LzhNNi91NnZFcHpuU2trbmg3eXRmdFRqNitobFdJRzE5cFF4NXBGdXNFcGlxc2RBQndMREFOMDh4cG9MQXYvWHdZNksya3RydWRGczZRRkpCSVpVL29GYTF4QU9JRzJYSnJ1ZTdZdnIrT3UvU1hDcXQvTGJZVS8yZUhPN204djhnZzQ0cU5GdVk4emJyTFduS09mZ3lteElVcnV1cFR3V3FDUDlLNWNKNENxQnIyc0lCNUMySkV1cXJuZkNhSkt3Zk5tUXRNZHFLMElkNEpKMXp0V3dwQnNwSllIQmlXM1ducWJjQUFDUEpGbFNkYjFEaEpLRTVmY01TWHVzdGlMVUlTNVp0N3E5QWk2V1dMMlphaElZQU1BSjVqTEJNMG1XVkYzdm5JUmZKempYRHBycWxadmJSNmlFY3c4N09NWU9ZOHdFcFNRd09OR0tkWmlTQXdENnpjR1NxdXVhazlEZGdDekorOTFDcTBtU3ZrWUpuUHVabytQc3BKUUVobHlJTzBPMUl5YVFPNlc2ZmtzVjRJbWtTNnIyTWljaHlkQ1BTMmd5cHplM2VEWE12aWczdzVLKzRpQ0lnOEFneFRiZGxXY0tWbTl5L2tYcTZCa3VFOENObXJWMXFnQlBKTDBCNzJWT3dueUM4MTFLa3ptOXVjWFpIblowbk8yVWtzQ1FYTGl1TmFzQkRCQ0dKTUl6U1cvQWUvbjM3S2NKem5jRlRlYjg1aGF2ZXRMUmNhNmpsQVFHQjA4RzBsMmkxQWE2eVBreGkvbGNEaGJ3alluMUVsV0FSeExkZ0s5ekR3WVhOdE5rem05dThlcjF2Q1RwZGdlSHVzc1ljekVWSlRBa3NsUk8xQjI3K29jeDduOVEwdzQ1d0xDSXJlYW9BanlTWkVuVlhsZnFTVExFZFE5TjV2em1GbWQ3d3RGeHJxYVVCSVpFSnVidEFpVUhodmJYaGwxQTRaTWtTNnFlN1BGMWkwbmVNRTl1VTdtNXhhdU9PRHJPVFpTU3dKQlltdU9ZaTRFbVhSOXpiTW5PY3BrQXlUV2I2Zll3QXV1NDhVNjZrc3MrWTR4ZDd4OGwyNHRCa3Q1TTY1MTFjL3MwWlhESFljL05Ic0l0Z2NIQkJkblRVblJyTm1kTTJmVXg0NWloRkVCUzdQWU9qN3c5cCsrN1J0T2RkWFA3SUpWd3psWFB6ZnNwSllFaDJaYzhYUGZ1bU92U0tPc3Ryby9aRWZNWWdFVGZvWTZPVVFWNEpLOTdHbXlpNmM3eUZDVndIc1FPeTAzUHpSVFZKREFrdkJqVHZmazJSbi9tL0QyekZ3T1FOSFEvVHhYZ2tienVhWEFsVFhmV3plMVJNU3dwRFM1NmJuWWJZOTVHS1FrTVBVdDlUa0FuaFRHZVROWUVFbWxiUFVjVjRKRzg3bW13aGFaTDVlWVdaM1BWYzNNanBTUXdKTHVuVDNGNFFocExxNzVjMVcrNVZJRGV4UzM5aGlyQUl5TTVmZCs3YWJwekhLUUViam5zdWJtWmFoSVlFbWtydmNDUXhrcEpFL04yZ1luUFFPK1k4QXpQN012ckcyZVl4emszdDZmVSs3NFlXSm1MbnBzZHhwZ0pqei9qSDJobXp3TkR4Nlk3OGZsRXhUanZaV2hiWitzVEEwTWx6YVdVZ1I1dXVDczUvd2dzclhxdUE1VEF1Ujg1T3M1T2o4T21rOTNhalRGRE1WU3dMNEdoY1pGZVNQY2ZCUGNUbnhtRERmVDRvOHlpQWZETDIzUCsvdDlCRTU3alVVcmcvR2I2cE56MDNIeGxBRUs2enpMclhTdjA0OU5Oek51RjJiS1pDNEowMXBRTzI5b3F4OHV0TlM3U0M5V0d2MWZNc0Q3RlRXTUlHdHlLQzZ5UUJLOWNrdlAzLzFhYThKeWIyeGVOTWQrVXRJZHFPSFZBYnViTmJKZm9hVTdKeWF4T1ZPalhKMnhiSFlsUzJvUW1DUFV1U2Q5d0hYSmVLSmxqWWFoeEg2K1l5K3Yydm1IOHB2eXlhZ2dNbm1PM2RIam0wcHkvLzh0b3d2TjZtTURnM0NGSHg3bk80OEJ3ci9vM3B5bFh5eVFIL1RweG1rTjhBcU9SVk9ZeGhNNitQTUJRWVA0Q1BIUkZ6dC8vUHByd3ZINUdDZHh5T0tIOExtUE14UU5jcW43ZStHYzI1TGR2Z2FIUzByTnBIdC9FK3JldWo3bFlZaXcyc0I1eHdLWks4TTVJM2o4QVk4TFBlM1A3b3M0OExZWmJyaWFVWCszcDUrdm5mWjJMNFlVdkRYeGdxRmxiVDNNL2hxSnhQek4vWXQ0dXBQbWVnVUhUV21MK0Fyd3pDRS9vMzA0em5oZkxxN3JuYWtMNVRaNStQaGMzM0wzMldyb1lYdmhDVm9VSyt0bEtuVmcvU2UyREJhb2QzV2ljUDBscVdGWmpBTllpampYSC9ndndpWXNuODlaYWsvU1BwTEdFYitNU1d2TzhXUDdjc1c3UHpUY2RIR3FQcDN1SXVPaGgrS3NlWC9jZUIrZk9iQytKdmdhR1psdi9rdWJ4cXczMzQ4b3FMVDBiV3kzd013SmNHSHVYd0VOSm44eTdlb0tkOUIvNVMybks4OTdjTGttNm5VbzQ5N0NqNDF6djRXZjd0WU5qN0Y3dnc0aHVlTnJoNEpvL05SU0JZWnUxcDlQY1Fia1k2MGJYeDZ4WlcyL0hUSDRHMXVEbmxBQ2VTZnBrM3NrU2hnNDJqTHFHcGx6UkR5aUJjNjRtbEU5NUdqSmRQQWpZdnM2Ly8wNEg1OHgwems3UTc4Wks4eWxrRUtoMjNKaE5yby83Y3BVZkpPQkNZcXVGMFlhZHBoTHdUTkluOHk1N2w1UGNwR3lrS1ZlOEFUd3FzZGlDNDVxNkdwYTAyOU5ka2YrM2k4KzJ6ci8vU1Fmbi9PbFFCUWFsL0JTeUdMbC9Fak14YnhlYUhiYWlCMVo4RUVBdkhQeVVkRWxWbDh1QkorbXRZTCtCQzN1UUVqam5hbGpTZXozOGJDN3VRL2NaWXliVzhoZU5NZStWbXczeE1sM2hxZStCWWJSaHA5T2NFMUFNOVA0MGprc3ZBOUMvQndGQWo1SXVoT0Z5Q2NORS85aDdPb0hVRjA5UkF1ZWVkSFNjbXozOGJLNUd1bng5dGRCZ2pKbVU5SmlEY3oxdHJUMlpaWkY4NkdGSTlXbGtZRFF5SFpudHJvOUxMd053Zmd4SGdzZVNMcWs2NS9DOUpBMGZWWnJ6L0xyRGtsaGkxVzFOWFUwbzM3SFdKL0Y1L0d5U2ZtNk11Y2NZTTJtTTJmS2FQNVBHbUhzY2h0bk1lOUc4Q0F6TlpyckRGNHFCcmt2anVQUXlBTmsrQUFCNjVXaXpzMFdIYnlucCt1bFgwcW9YeEFNOTk1NXdkSnkvOGZDenVieWYyOWNOQmlkZTgrY3B1ZDBESnZOZU5DOENRK3FySlFXYVRHUHk4OFM4WFdpMjlBQy9JY0NyNGlDOS9WV0FCQkp2ZHVaNENjT2s0V01EVFhwQlBMaHd6OVhRbmJ0ODI2MDhaNzFTajNUZjcvQUZCa2xxZDV5TTZWcFJGS1d6L20reHJTZlRERHRBcnNKQ3JMbXhKVHRMSmVBaHJ6WTdjekQrbUI2RzFjTWR3NUxjMXRUbFBoZmJQZnlJWDh0SlU5emJqNU42RXhoZTNwRHVNbWhScUtrMGRuNnVXVnR2R24yVm54SWcvZUFQSkpCMFNkVjdQZnM4NzZGSkIrWUdNRTljRFV2YTdlRm5leklISWZNUmErM2hvUTRNRS9OMm9SVXIxU0pjdEpqT3VMbXhKVHZiNk9naGZrY3c3TklPL2tBQ1YzajRucEtFa0IwMDZhcCtSZ25jNnQ2c3V2aWQzMmVNdWRpeno3WWs2Yjk2M2dSOWUzQVIrRlNGVnV3c3VaNVhXcjFyY0hPMUFBQUxwVWxFUVZRTWtoUTE5VU9HSm1HWXRkdDZiR0xlTGxBSmVDcnBiLzlQZmZ0QW5tNkM1ZE1Ob0tzTngzQTJWeXYwWE8zaE5YTlU3b1pkT1E4TC9lcGQ4QzR3YkczYUkybmZkS2ZWeTFDenRyN1kwSmY0SGNHd2lnMXJuOE5yK3p4OFQwbER5Q1UwNjZvZXBnVE91ZnF0djhuVHozZWYvQnVhOUxTay85TFBOeEQ0MWtxcFQzNU9zWmRobTdXbkc5S1grUzNCMElXRldIUHN2UUJmT1ZxUkpZMWRWWlB1eFhBcHJidXFKeW1CVzkybjhDNkdKZTN4Y1FQQzd0Q2tXeHg5UmxkaFlhcjd2Z2dNeTRydDlML2NhZlV5U05LV1Jmc1VHN3BoMkxRQ0hhUUs4TmpiUFgxZmN3bGZmd1ZOdTZhYnY5dXBoSE91aGlWZDcrbDFjMHJTbEFlaFlUa3NuT3AzVFFxK05WTE4ydnBNeVJ5SVFrMmxkWTRvMU5TSml2bEpXc3Mvampicy9oZEs1dkl3MUhoV2Rac3BtaHRjSC9QbERYcWFNZWxZVFd5MUVOV1pYQWl2dVJpNjgrc1UzbGZTdlJoR2FObzFlWUlTT1BjalI4ZVpVaDkyTFY1cmFEREdUT25NVUtBOXd4d1d2QXdNMHBrZGxLTkdlb0ZCa2tLckczVm1uRm9xZ3FidTZVUzZMYXZRRUJXMTEvbU5ZRjNQU3lJdzRJSmFzUjdkWW0yZFNzQmppWWZ1cERFY29IdERrdVFRK3lUZFJ2T3U2Z2dsY0g3dG5qVEdQS0xreTZQdU5zWnNjYkF2U1pxaDRUL3B6TkMyYjJkNDZ0c2wzZGZ2WVVobjNkZjYyRUJaTExGYUREUTVIWm5VTmc2cFdWc1Btcm9udHR4d1k3QXRWdlZqcWdEUEpSMjZrK1pLTzRrbVYvcTJOS1duTjMxTGtqNU5KWnh6TmZ6NnZiNWZQOWJhQjNWbWFHUGF5NXJlSzJuTVdudTNUMkhCMjhBZ1NSMlQvcGpvY3FoUHpobFRUak0wTE5aMUI2RUJnNnJaMFFHR3JTRUhrZzdkbVUveHZTVjlzdnBtbW5kTldNWE52VU9Pam5OelRvTG5LV3Z0YlpMZUpPbnY1VzRscGFlN2dYYk1XbnVicjcwdHhscnJiZU04WHphZkxRYWFUUE1jalk0ZTJ0S3dxWWFUNDhac3FwWjFaMkRPL0tQMTU0djJBNjdQOGN1cStaK3VqMW0zMnBmV1BBK2ZQM2V6cFFkR1cvWngzNi9sTk5wbnZmV2NMMmtQZ1FFQU1JeTZxenk5VTlJV1NaZnB6QTdzcTIycWVLL09EUGQrVHRJLyt6SkhZVFVGbjk5Y3graGdVZWtHaGxLb0Q1Mm9tUCtiNW8zeE5tdFBIemZtam1wSnR3YUJhbnpGTUFqb1hRQUFETFB1emY0cHVac0U3cTNBNXpjM3RtUm4wNTdMSUVuRldCOU8reHpickQxdEdycWowOUV4dm1JWUJDOVg5UU9xQUFEQTRBdDhmNE5aekdVSVE0Mm5zU3pwNjlXc3JiK2pZYi9BWlllOG8zY0JBQUFDZ3pleTZtV0lpdHA3b21JMmMwa0FxNk4zQVFBQUFvTlhzdWhsa0tUSTZsTnBycG9FRElKR1J3L1J1d0FBQUlIQksyTkxkcmJaY2JiZTc4ckZDRlJyUmVsdUdBZmtXV3kxRURYMVF5b0JBQUNCd1R0WkRZR0lRazJsdWFFYmtHZnR0cjVYWTFkbkFBQUlERDZhbUxjTHpaWWV5T0pjNVZDZlBHN01KaTRQNEZWeHJEblgrMU1BQUFBQ2cxUEZ0cDZNWTgybFhoU2prVXFrVHpDZkFYaFYwK2lyVkFFQUFBS0QxMnJXMXR0VzM4cmlYR0dvOFU0eC9mMFpnRHhveFRycys2N2ZBQUNBd0NCSkdtM1k2U3lXV1pXa1FrRzdzdGlmQWZCWmJMWHdVa1gvUkNVQUFDQXc1RWFXTnk5UlVYdVpCSTFoMW03cmV5eWpDZ0FBZ1NGWHNwd0FMVEVKR3NPcjA5RXhKam9EQUVCZ3lLWFJsbjI4MDlHeFRJcGtORkl0NjA1Q0E0Yk5VbE5mcHdvQUFCQVl1SmxaWTJoZzVTUU1rMlpMRDJ5ejlqU1ZBQUNBd0pCYjI2dzluZVhRcEREVWVCenBOa0lEQmgxRGtRQUF3RUFFQmluYm9VbUVCZ3dMaGlJQkFJQ0JDUXpMTnpleFZXYXJ1TEJIQXdZWlE1RUFBTURBQlladDFwNXVHZjJQTE05WktHalhUTWw4a0VzSWc2UVY2ekJEa1FBQXdNQUZCa25hc21pZmFyZjFXSmJuakVKTkVSb3dTQzZ2Mi91b0FnQUFHTWpBSUVsaFM5K0pZODBSR2dBQUFBQUN3emxxMXRZWEcvcFMxdWVOUWsyOVVETC93RVJvQUFBQUVCZzh0ODNhMDR0dDNaMzFlVms5Q1FBQUFBU0duTmphdEVlYUhSMGdOQUFBQUFBRWh2TWFiZGo5V2U3UDhOclFZTXU2LzdneG03aThBQUFBUUdEdytjTTFkVStXK3pPOGNsNmprV3BaZDg2VXpGWXVNUUFBQUJBWVBGV3p0cjVZMXgzOUNnMVJxQzlPUjJZN2x4a0FBQUFJREo3YVp1M3BkcXgvN05mNXF3VjlubVZYQVFBQVFHRHcyR2pEVHZkajVhUmxMTHNLQUFBQUFvUG50amJ0a1VaSEQvWHIvTXVUb1U5VXpHWXVPd0FBQUJBWVBMU2xZUS8yWTduVlY0cHRORkkydW5lbWFHN2cwZ01BQUFDQndVT2pEYnUvbjZGQmtxS2k5ajVmTnA4OXV0R01jQWtDQUFDQXdPQmhhR2kzOVZnLzMwTXgwT1FiNi9vU1M2OENBQUNBd09DaHNLWHY5R05qdDdPSzMxMTY5UmVSK1RnVG9nRUFBRUJnOEVqTjJuclExRDM5RGcyU1ZDaG9seTNyZm5vYkFBQUFRR0FnTkp5L0lWN1QyOERjQmdBQUFCQVlQQXNOL1o0SXZheFEwSzQzMXZVbFZsSUNBQUFBZ2NHajBPREQ2a212TklyUlNGVFUzdG15WVZJMEFBQUErcXBBQ1Y0MTJyRDdaMHBHVWFncEw0SkRvRm9rZmZINXNqbmNNVG80dG1SbmFhVU12aFNoZGoxZk5sZTZQR1pvdEkzS0FnQUFBc09naElhaStYMVUxRjVmM2xNeDBHUlJtaVE0WkJmVUFxbEdKUUFBQUFnTTV3OE5MZnY0ZEdUK1dDM284ejY5citYZzhFTEpIR3RZUFZwcDZkbWF0WFZhREFBQUFBU0dqRzF0MmlNbkttWmZKTjBlR0htMWFsRVlhcndxamNlaEZtWks1bERiNnJrcUxUbDAyblV0VVFVQUFKQTJKajFmd05pU25WMnM2dzRmbGwwOWIrT2RXWXAxeXJlZUVLUnZzYTI3dDFsN21rb0FBQUFDUTU5dHMvWjAwTlE5clZpSHFRYjZMYlphZUdsSnQyeHQyaU5VQXdBQUVCZzhVYk8yZm5uZDN0Zm82Q0dxZ1g3cGRIVHNUMlhkU3M4Q0FBRElFaVBmMTJGTHd4NmNLWmtUaFVDZjgyMWVBd1piczZNRG93MjduMG9BQUlDczBjT3dUcU1OTy8ybnNtNzFkVjREQmt0c3RiRFkxdDJFQlFBQVFHRElrWWw1dS9DT2h2MENRNVNRcGs1SHh4YnJ1b1A1Q2dBQW9KOFlrcFFBUTVTUWxrWkhEMjFwMklOVUFnQUE5QnM5REFtTk51eTBxZXVXZGx1UFVRMGtGY2VhcTF2dEl5d0FBQUJmME1QZ1FIZTM1Vy9NbE14VDlEYWdWNDJPSG9xYSt1RVl1M2NEQUFDUDBNUGdFTDBONk1WcmV4VnFoQVVBQU9BWmVoZ2NvN2NCNjBHdkFnQUFJREFNcWRHR25aNHo1cFpHcFBlVlFuMklpdUMxT2gwZFcycnE2MnpDQmdBQUNBeERyTnZiY1BDNE1UOHRsZlIzeFVDVFZHVzR4VllMOVk2K3hsS3BBQUNBd0lCWGRKOGkzemNkbVNmS2dUNFlCS3BSbGVHelBQeG9LOE9QQUFBQWdRSG4wMzJxZkdTbWFHNG9GUFMzekc4WURzMk9EcnhjMVE4bTV1MEMxUUFBQUFRR3JHcTBaUitmTStiSlprSFhFaHdHVnl2VzRZN1J3YkdHbmFVYUFBQ0F3SUIxNmM1dk9CTWNJazFGb2Fhb3l2ckZWZ3UrQmE1WGdrS2RvQUFBQUFnTWNCTWM5aC9kYUg1dzBVdmFRWS9EK25Tc2pnZkdqOG5rQkFVQUFFQmdRR3E2NDlzWnFwUkR6WTRPeElGK1FsQUFBQUFFQnFSdWVhaVNwTWVuSTdPZFZaWDhGRnN0dEdJOXVsalZqNW5NREFBQUNBem9pK1ZWbFU1VXpPWkNSMzlkS0dnWFZlbHpVSWcxVjQrMXY5TFNzMXRZSGhVQUFCQVk0SU94SlRzcjZSdEhONXFITDNwSk93cWhkdEhya0dGSXNGcG94enJFc0NNQUFFQmdnTmVXNXpsSWV2eEV4V3dPWXIyN0VPaDY1anFrb3hYcmNDdldFNVdXbmgybE53RUFBQkFZa0NmZFhvZFpTZnRuU21hcnBLc0lEOGwxT2pyV0RuVm9zYVJubUpzQUFBQkFZQmdJb3cwN0xXbWE4TkNiVnF6RGNhQ25DUWtBQUFBRWhxRUtEOGVOMlJRVjlHL0NRTzhPUTQxVG5UUGlXSE50cXlPU2ZsNXNhdlp5aGhzQkFBQVFHSWJSTm10UFN6cXRNL3M3bEZ1Uk5sdHByQ0NORDFPQWlLMFc0bzcrVDZlZzZkYVNudS9XQlFBQUFBUUdMT3Z1NzdEYyszQnd6cGh5bzZ5M0JHMWRia0pkR1JwdGUvMFFwbEpkdjgzaloyM0ZPaHhielhhc2Z0VzRTQzh3ekFnQUFLQjN4bHBMRlNCSmVtMklVS0JMUmh0MnYrL3YrV1RWN0RRdFZSVG9WTE9wZVhvUEFBQUFDQXdBQUFBQU1oSlFBZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQUFnTUFBQUFBREFzdjhQbGRyNk5IUjMrN1lBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMC0yMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMTAtMjEifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI3ODY1NDQ3NzJlY2M5ZDNlODUwNDkyMjJhZTMzMjI2MzQ1YjU5YzY5Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjc4NjU0NDc3MmVjYzlkM2U4NTA0OTIyMmFlMzMyMjYzNDViNTljNjkiXSwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IEJpbyBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4OTY1LCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjJ9LHsibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTA4LTExIiwidXJsIjoid3d3Lnl1Ymljby5jb20iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgQmlvIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTA4MTEwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS40In0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTA4LTExIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0wOC0xOCJ9LHsiYWFndWlkIjoiOTcwYzhkOWMtMTlkMi00NmFmLWFhMzItM2Y0NDhkYjQ5ZTM1IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI5NzBjOGQ5Yy0xOWQyLTQ2YWYtYWEzMi0zZjQ0OGRiNDllMzUiLCJkZXNjcmlwdGlvbiI6Ildpbk1hZ2ljIEZJRE8gRWF6eSAtIFRQTSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsicnNhc3NhX3BrY3N2MTVfc2hhMjU2X3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3IiwicnNhc3NhX3BrY3N2MTVfc2hhMV9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTEyLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRXJUQ0NBNVdnQXdJQkFnSVFSVGZjZ282eHdJRkdmbXR6azFCU25UQU5CZ2txaGtpRzl3MEJBUXNGQURCRU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRmJHOWpZV3d4R0RBV0Jnb0praWFKay9Jc1pBRVpGZ2gzYVc1dFlXZHBZekVSTUE4R0ExVUVBeE1JVjJsdWJXRm5hV013SGhjTk1EZ3hNVEkwTVRnek5EUTVXaGNOTWpnd056RXpNVGN6TWpNM1dqQkVNUlV3RXdZS0NaSW1pWlB5TEdRQkdSWUZiRzlqWVd3eEdEQVdCZ29Ka2lhSmsvSXNaQUVaRmdoM2FXNXRZV2RwWXpFUk1BOEdBMVVFQXhNSVYybHViV0ZuYVdNd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURRQ2ttUS9LOERuMzlxU0NXNXRLTHZ2RExIM0NsU2NnUXJEZzcrdVk0NGpIbElZMS9MbDZ2MnJwajdubG1WTWxJem9nZDN5WGpDRkJ2R3I0emlHUTJRYzhVcGthVTk2RVp4RXRId1pTdHc2WVEwamRuZ2tTTFB2T3A4VDhZaUpwY3ZzVnRRdGlRME9zVFR1aU8yRWk0THVMaDdLUis4eDRiQVJ2emtCV3N0TkJUcVZTQVpRWWVzcW5sOEg1U2Z3YjNJb3U4TFNpQXN1T1h5eHQybXM5MTFZcnhXdmgvS25PZWwzT2QzaCtLNWRRWVA1MytmUFV6Z3o1NlRUajhSNFk2elJ1emRrYm5SNnhXWGRySzQxNGlYOUQ2eDVxOFcyWEpKcFRNSzdFblNYRzBxN1hGN3A2OGpES0FueEFGOGtmaDN1aW5jMnVsbVZPWmJUUnp4RjhCM0FnTUJBQUdqZ2dHWk1JSUJsVEFUQmdrckJnRUVBWUkzRkFJRUJoNEVBRU1BUVRBTEJnTlZIUThFQkFNQ0FZWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVqTXNUYlkwd1hRQlIyOWJXSEl2YkZmVUFGZlV3Z2dFR0JnTlZIUjhFZ2Y0d2dmc3dnZmlnZ2ZXZ2dmS0dnYlZzWkdGd09pOHZMME5PUFZkcGJtMWhaMmxqS0RJcExFTk9QWEJvYjJWdWFYZ3NRMDQ5UTBSUUxFTk9QVkIxWW14cFl5VXlNRXRsZVNVeU1GTmxjblpwWTJWekxFTk9QVk5sY25acFkyVnpMRU5PUFVOdmJtWnBaM1Z5WVhScGIyNHNSRU05ZDJsdWJXRm5hV01zUkVNOWJHOWpZV3cvWTJWeWRHbG1hV05oZEdWU1pYWnZZMkYwYVc5dVRHbHpkRDlpWVhObFAyOWlhbVZqZEVOc1lYTnpQV05TVEVScGMzUnlhV0oxZEdsdmJsQnZhVzUwaGpob2RIUndPaTh2Y0dodlpXNXBlQzUzYVc1dFlXZHBZeTVzYjJOaGJDOURaWEowUlc1eWIyeHNMMWRwYm0xaFoybGpLRElwTG1OeWJEQVNCZ2tyQmdFRUFZSTNGUUVFQlFJREFnQURNQ01HQ1NzR0FRUUJnamNWQWdRV0JCVGZRUTVXcldNUlc3OHZrV2gybmlEVDNWOTdyREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBaUxwTHRuYUUwQWJJaVNtbWo0RUxSVFJNR3VlZHhkNlpUWTJ5VWkxUU5zd2FJMk9GbmgvTkRXTFdPZ0YzNkhPdkRFTFhCWVpNNitBc1BpVkhVNzJzdmxZajdZNUh6WnZvVWtNM2R2YnhyNlUyQko4OUpFRVRSSVdxVWxZT3E0N0JlODRPUjJYdm1uaVV1SnJGT3pzQVljdHJaWDJURlgzQWJWUHM0TFNUTmMwZGEwdXEwQ3FvT1NPSUNmenoxWDd1ZjdUdzlPMEtjS2VyRmd6ZVVjbUd0S3Y1b0s3Ulk5V2tEeGRpMjJSeTBHRWI2MHRuYXY3cWs5amE0NVdCak4xMHh1TnBOc2xDYWxSbk5ZT0dWdFkxbTRveTJnKzF4ZDFiMHZ4ZzB4SnNXNGsyb3ZUZFpRUzVIQ2ttZTA1TTVMeTBTRlNWRy9SSHhNczZJeDQzQ2N0Q0lRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTFFBQUFDMENBTUFBQUFLRS9ZQUFBQUIxRkJNVkVVQUFBRC8vLzhSQmZjU0NmTVNDdklUQy9FVEMvQVRETzhURGU0VkV1a1dFK2dYRk9nWEZlWUFBTThBQU00WUYrVWFIT0FBQjg4QUJNNEJCODhCQ004Q0NjOEVDYzhJRDlBYUh0MGJIOXdiSU53YklOc2JJZG9jSWR3Y0l0b2NJOWtxTU5jQkM5QURDOUFFRGRBRkVkRU5GOU1ORjlJUEdOTVBHTklQR2RJUkd0TVJHOU1USGRNVUh0TVZIOVFWSHRNV0g5TVdJTk1YSU5RWUlkUVpJdFFhSTlRYUpOUWJKZFViSk5RY0pOY2NKZFVkSmRjZEp0VWVKdGNkSnRRZUo5VWVLTlVlSjlRZUtOTWVLZE1mS05VZktkUWZLZE1mS3RJZ0tkWWdLdFlnS2RVaEt0WWhLOVVpSzlZaUxOWWpMZGNqTE5Za0xOWWtMZFluTU5jbkw5WXBNdGNxTTlnc05OZ3VOdGd4T2RreE90bEZUTnhOVk41UlY5NVRXZDlWVzk5ZFkrRmthdUppYU41NGZlYUZpdU9FaWVLRml1S0dpdU9HaStPc3NPZ25QcjhyU0xVdFRxODdjSTA5ZFlsRWhuZEprMnBLbFdsTW0ySk5uV0JObldGVnNVNVZza3RXczB4V3NreFh0VXBXdEVwV3MwcFd0RXRXczB0WXQwaFd0VWhYdFVoWHRrbFh0VWxZdVVaWXVFVll1RVphdlVKWnUwUmF2ajlhdlVGYndENWJ2ejlleURoZXh6bGR4amxkeFRsZnlUVmV5RFpleHpkZXh6aGV4amhmeWpOajFTcGoweXRpMGl4aTBpMWwxeWhrMWlrVnFpRWlBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBRittbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORFVnTnprdU1UWXpORGs1TENBeU1ERTRMekE0THpFekxURTJPalF3T2pJeUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdNakF4T1NBb1YybHVaRzkzY3lraUlIaHRjRHBEY21WaGRHVkVZWFJsUFNJeU1ESXdMVEEzTFRJeFZERTRPakUwT2pBMEt6QXpPakF3SWlCNGJYQTZUVzlrYVdaNVJHRjBaVDBpTWpBeU1DMHdPQzB6TVZReE5qb3hPRG94TkNzd016b3dNQ0lnZUcxd09rMWxkR0ZrWVhSaFJHRjBaVDBpTWpBeU1DMHdPQzB6TVZReE5qb3hPRG94TkNzd016b3dNQ0lnWkdNNlptOXliV0YwUFNKcGJXRm5aUzl3Ym1jaUlIQm9iM1J2YzJodmNEcERiMnh2Y2sxdlpHVTlJaklpSUhCb2IzUnZjMmh2Y0RwSlEwTlFjbTltYVd4bFBTSnpVa2RDSUVsRlF6WXhPVFkyTFRJdU1TSWdlRzF3VFUwNlNXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3dZakV3TmpFMll5MHhPV0UwTFdVME5EWXRPVEJsWlMwM056QXpNMkZrTUdRellXVWlJSGh0Y0UxTk9rUnZZM1Z0Wlc1MFNVUTlJbUZrYjJKbE9tUnZZMmxrT25Cb2IzUnZjMmh2Y0RvNU4yTTROR0UyTnkwM1pESmxMVEJsTkRjdFlqQXpOUzFsTjJVNE5XSXhaRGswWlRZaUlIaHRjRTFOT2s5eWFXZHBibUZzUkc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRveU1tVXhOR1JrWkMwNVpqQXpMVGhrTkdJdFlUYzJOaTAxTW1FNE1qaGpNRGRoTmpjaVBpQThlRzF3VFUwNlNHbHpkRzl5ZVQ0Z1BISmtaanBUWlhFK0lEeHlaR1k2YkdrZ2MzUkZkblE2WVdOMGFXOXVQU0pqY21WaGRHVmtJaUJ6ZEVWMmREcHBibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakl5WlRFMFpHUmtMVGxtTURNdE9HUTBZaTFoTnpZMkxUVXlZVGd5T0dNd04yRTJOeUlnYzNSRmRuUTZkMmhsYmowaU1qQXlNQzB3TnkweU1WUXhPRG94TkRvd05Dc3dNem93TUNJZ2MzUkZkblE2YzI5bWRIZGhjbVZCWjJWdWREMGlRV1J2WW1VZ1VHaHZkRzl6YUc5d0lFTkRJREl3TVRrZ0tGZHBibVJ2ZDNNcElpOCtJRHh5WkdZNmJHa2djM1JGZG5RNllXTjBhVzl1UFNKellYWmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG93WWpFd05qRTJZeTB4T1dFMExXVTBORFl0T1RCbFpTMDNOekF6TTJGa01HUXpZV1VpSUhOMFJYWjBPbmRvWlc0OUlqSXdNakF0TURndE16RlVNVFk2TVRnNk1UUXJNRE02TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFNUlDaFhhVzVrYjNkektTSWdjM1JGZG5RNlkyaGhibWRsWkQwaUx5SXZQaUE4TDNKa1pqcFRaWEUrSUR3dmVHMXdUVTA2U0dsemRHOXllVDRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejVYQmVhbEFBQU8xa2xFUVZSNDJ1MWQ1NThrVlJXZFowNllBNkppRHBnRG1GaXRMVnl6bUhQT1lsWlFFV1E5QVhNV3pQNnpmcml2OHF2dXFwN3Vuc0hmOUtlZDdkNlpzN2Z1dStIY2M5K2NwQWZnNitRQzlBWG9DOUFYb0M5QVg0QytBSDBCK2dMMEJlai9GOUEwdVAwelBrZWdEVXVpTm9BaWJNRzBjUTVBU3hJczBCUUZxUGdaaXBZZ1E1SjV0cUJoeXpZbFNvSWd5eE1qdzdKSlU3WW9VajVEMEpSdDA1WmxVYUk5OW02RGtDWERsRUFKcHZZQSsyUkh5QklzMmJJQVdMUmdxZWNqdGtSWnNnM0pGR0VBT0QzcW5VQ1REakRNV0V6WmxIb3VRb2xDL0w4b0VXbzh4ZElaZ0xacFc1WUV3SllrSW50QzloREpJRzNURWt5THRpSElQTFd0ZHdDdENHS2tRWnRLeVNaaFc0WWordG1TYkVLMllLUkVDYVJFaXlDUERScXlURkRxaFY0aUlyWWxLaUpkdUVZdk9sdUFiQm8rbmExUGRzQXNHclpIQ1VXd0xVR1NMTW5rSkFxS3BreEwxakZCbTVDTVFhRG9Ib0VsQUxRaDBHSWh2RU9rVDJmcTlhQWRqc0dpdDlNbW1BTmhFWml0TUxhUEIxcVIzSVM1ZHdGWnRHeDZKc2JEeHR5N0J3RnR5VVlYYWhIcHNQZWxhV253TEJ4UnZlOWd0RTVSK0oyc05iVGt6aU1EY0E4MWdKeDAzUHlWYlVKVWUzQVJ1Ujg0SG1nVFJQNzVkQVlwRSsyVGlLcXUvWDlGV1dxcjlRaEhSdFd4UUVmYWF3RWhRcDg3NDdjSU15YUt6U2ZRNEJRUnFmSTRvRFVJSFpMc3U1eFNZR0puYXFxeFBHd2J6V2ZjTkRLRVRtSHFsYUNqdUdQckt3Mk1EcEhEcGJQaFpkdXRjNnQxcXdndnh3RnRXV2lPR05VOVlkdU9naUpIazJ4R2QrY3ZvZjJ6WkFySGNnOUcxYWJ1aTM2bWEwOG4xWmlYWmxkOGdMMW5wRk9rbDVYdVFVRmdCOGlkNDNUK0liRjU5Rkl2RDdudEl4MHR6WkhjSTZKQSs1RFZTeUFvZ2JDSFNXWS9UTUxhNkVFYk9TM1FiR0pFb2wzTUZwYlE5akltZEJhZ2MvZlVSUTlPL2pqcGY5dlVxSDFSSDJ2ZFF5UWE0MEVDblBPa3k4SEFSandQbWRvWFhiTTJqY3RpRytsa1VnSTQzL2ZKMFIweXV0c3pBUTJJWGZ3d2JkRGFWRW5BRmdFVDNCc3Z0a1B0NFY1Wm1RdWhUV0ZCakdMVzJCc0p1YnFlZGpTSXZWUTRLaVBDVHpqbzBFNVZIcDBlTkIzSnc1c2EzNVQyeDVEdXFVY01aZ1liNmhNTE9tK2dBZHFjSTF6SWZrWTVINkFURFpyV0hHc2JCTVA1c25SS1FSNWxmcnBFakZnV3podG9CSVVVVXdBVlVFczZaKzRSWVM4NlFkbWExa25nWVEyOUd6L2RrWXVLVG5lU045UDVBNTJDMXlJY0dkSk9SMzN0T25QSnBWSmdMbG43UElKT2Fvb094U1RnbUtoUE1VZDBMcU1sT2laWUs1S3FqSWozbEJUelBFbUVrR2NGSUNuQWtqWHVlRTQxc1kwd0FqbUdGMHN6aW13S2h2SllENUpwSU0vTEZBK1JGbU1FeVRIVGZjb3hjNHpoRUtsR1hBWTc1akNVUWVTaEhnVmFpQXlRZ3hLaWYrQTArNTUyb0IraDJzSFBhRm1ocEFpV3NHa0NoZzBMbWZVTDE3RU5rU1NNU2JJNnZRckJrYy9SUEcwdThTb0ZzKzZZUHVkWm1ZeUlwV0JNb1dKOEUvK2wvWUx1cUZSRjg3VTFzMUNnbUllaEZCdzBQVTBDTmdYWmtBWEc5QlFqSmNCK1JDcHFwdnZCUFhyYlFRanlOVHQyTU5vaURFZTFaUmlJUHQ3T3dXWC9vRk9pTFNGMEJ0b3lUMkYyMjF3b3VrdFFjYVRESTJLc0YyTjM0eUNnVTJKRUxFclE0cEJkekxWaXJ6QmdVTmsrRE9nWXVBQWhsTkR1bmlhanAzZ2gxSEJDQndFZHZITWNvSjJiN3liRERocWhVYmJkczFvczV6cnZYa0UxMVV5UFZ6TkhMZWUrSlc2eTgrQjhSNy9PeDFLZFM0TWF6YXYzcjh0ekNMS3dXNThZdlZybjBxSExzUThNT2srVHVKdXRoVkh3a01seE5EcUVBaklTTUhjU3RPV0VxRjc5U3dvSHQzUndaOU16djh3NzhvSG9OY25UbWRKaHRLYUlpY0Y2MXBFMmlJNEpqTEpnSFBVUEpKQ04wRmRTcVd4anIwSm9OR1IramdTYWpoSitaYlFPN1JiNlNUeGtpRWNCbll4d0QzQlY2SWhPZ3IzR0tGTFZjVURuUWRnNlV6T2tJYjFqR0RvUnB5T0JUaEgxMWhSOFVXYjBNZ3ZvYUJXUEJ6cXJOYkhjb2MxaDYyUGwxOUZBSnplSmNUbm82TVA3M1FKS2gvbUFvTnZHWkRFYkViSlU5WStGVmVpRERybklrQW1vWlVPamNDYjNKOUcwVkt6TUR3bGEwVll2aW5xV0hKck9OTWlHUmRYUVFWZEdRbEsvcFBXeW96VHN0OTBtNEdKV1BTem9hSFMzaXgxaFc0RFltNTVuTHJKVUNSelkwbmtYWUtzL2gzZjByV3BCRUZ3U0FSeDJveWdrN1Z1R2lpSkFFY1BvU0Rsb3lIUjAwTUVDYXlQdkVLSkpERFhWSVZmdHBGcEhCQjNKWVFOUFJtZitiMFRuT2haK1pvTDhnUmZPZ3VLYjh3K0xiSWl2NFhGdE41WFNHWURPQ3hndXZTT0J6S3l2TU1qMkVhRm45VU9IdGpTQ1VKZ21Fb1VJUTBJOEN3N3NIQk9OT2E1N0hXaDQwa2VFb2w2RGozU1NsTmhtR0pVOE9aTkFERjNPbUtwRFM5S25mWUFXNkZFd0lJWS9sR0ZHZG1sdE12ZW5oQmdOTWJoK1R2WTRaQm16cGZoYTJTWkhEOXNhZDkwS2JyM0xkWk1kc3hnQ1dYbDlaRFNuYWQ3YzBQU3NGTWhxekp3d0x6OTF6NVlnTytVc1krbzI3bnJqa2RIVGFVZXpKYk5KZUxoU1RNaVJCV0lUanVpdkRjVitWdXVmTWtmR0RFMWNxTUU1NlhkaUZyTnhCM2FscFVrTU5LV0s5YUplZGFHSUJSNDk3RkgwQU11YVNVcDVXTFFwaTY1MUQ2Qy9MY1pta1hMNE1Ib01ZdDR3V2RwV3hvaE0zTndPcjlXYTB2MXZxTnp5cTk5dHNKOTl3MjJYZFZ3RTJVemEweDVCYzFEVXg5YkxZSEdXMGZWclE1Q2NoV3lUQUtodEhmeGEvWFJmVDJ3d3o5OEh5Y3c5WGl0MnVCWlFlakUrelFxamJROW1aVWFFMkpJcERPbkU0TXlJc1EycWpoYVF0ODRFWXVmWklzdWlxTk1tRnlpcnFtekNBalhvTGZJNm1udnNuS1hOODNJNE5CNnlBUzFaNWwvcDA4Z0VmK3l5a01MdzBPUUZ1WTdZaWxTaERmNFd5VWhzOXRRV3dGaS9NcUlzRVlpUjRkQmZMWUE5VGlqSW1qRzNUZ2hnam0xNUc5Zk56bURhTzJoWmlEWWpnR01rMUFtaFNtK0xMK2J4US9PeFljcWRuME5lNTRhWHh2UFZHMFcyRmNvUlRDd1RDODA5S1NGcFlNSmNORVJqSTIzSjVCSVhxKzlYTHpMa09vY0lnY2FvR1NIVTV6bWlhUjJuaXJ6VkRCZ01QUTFnckJBQ0YwRlhWVlZWTTAyZHBOaXlsekV5WWJqbFlCdEh3Tmc3WWtxQUdPb3lMOE92MDF1ZkZBRlhkVlZWVlYxSzQ2QUlvZEQ1SWZpVzNsOGpkaTgwNmRGdE1UcXhYTzJ0YStKT3BwRHJxbnROQ3FiczBnWE5kOUJFWVA4WUZndGp0azNBZWh1WFFGZlQxN2lGemsrMVJJa3JpdnQrYUJNNUpiWnk2TURPRXRXVHpaQkhxSnZxdlJUQnFheWJHclNDMUQ3WExxYWdxOHRiVVFmcnpYTFdZWWovK2wxVmtCc0hCRDEwNWpKcTJLVTl3aGhvajI2QUNXSGdRWVN6SjF1Y1k0ZzZ5bWRNeTBxUWd5NnJtUVBvSU1zakxlaXBuZXNwYW9zZXJ6TVJ6Q0xYZ1NjRTMwSWVRclIrc3QzT1ZWVlhYVnJBY01abUFhRjlHZWIwTEduVVFVVHNaZEQxK0t0ZXR1aWZ0U3lwWk55eDVDRkxaT3gzWTJzQ2VvdWhHOVNoTUdLUDVyY2hrZkp3SVRGdW5nRG93NEdlQnp2MDZ1Q0xFQnJYM0I3Wm1EU3Z1Um84MUFyWFNURjd6MFVRcWIzN0pkL2lrdVU3d3k0UWxFRWZiQm1xYk9ueFh6VmVIWnBLUmRFc1JXTm5qRXJVWEwxNVgxZUpsVUdYVDEzQjFJRTB5OGxGeUJUSHE3T3hBek96U0w1djBQVTRsVXhCUjBlWEx4TVRzN1o4WEMySHlKODgyQkxKeE5MVlhBV1ZlVnhueVQ2eTZsalQ5TWlJMFlkYmZEbnBZYXUzZ282dGhhWk9Ma3hUNDBZeHkvVFAwbEZBVCt2bi9oczNwNVR1ak5aWnNRcGVJbk9VRStIVjM2YXpCbDFYVlhVcHBmU2Jxd1k0cDB2S0RSL2xuL3pxbittSW9OT3NwYStrbFA1OHJ6MnI3NEVRTjE3ZGRjL2YvNVRPRG5UcVI4SmJudjdJMis4cmhJdTJscEprUVhmLy9OOC8vdGFESG4zNWxvMTF3Y0pYWGVJRlRqS3dlZ3ZvcXJwY1BmdmEyLzh3czF2UnJzclpWMy83M3g4OC9oSFZMVE00THkrRk9tdklEdlNvQmkzR2ordXYrOUg5MEpUeVJ2UzBobWxmdmU5ZjMzdjQ0OTQ1QjZSbzVNdWJIOElXME5WbTBNKzY0MzVwUEpFSzVqOHZoOTM5aTMvYysrMEhYL3VPYXZkWFBRRmVCbDFQVW5pQnVxbXE2NTl4eDkrR001ZFF0TVpWY3JidXV1ZVAvLzcrOVE5OXk5dExKcXNuWDlURE4rcnAwNmozWU9ucmZuUy8ya1l3cncwNkp0eUNmT2Z2L25QbmR4N3ltSGR1ZDloTGx6WWZ5dUVKMkRGNmhCRnVmdFFQL3hJSjJuRnRZdHl3bVRsYjZ0ZS8vTzR6SC9hbXQyMlBGdTkvMFF0dm5mOVFQZGVocmc1NThSWitEek1YMFhEUWtYRVZJZWxmM3JjOXdsWlZYVmZWaTc5Yyt1YnRUNnczT25RRHV0NmNYT3IycmI5ZVJiNWloRjB4blc5K1hGUTd4M2Q2N0RjYkFxQ2UvT0MzYm8wZHkydVBDSVkvVlN5OGRsRVoyVU1XNXJJTStxdHBycmg4OVpYdEVXOWFtbTd5am1RRFdWNFpkd2RIV2IyOENJMXZkYzNYWnVyMTlLVW5qMlBLSXRBYlMxT2JVTDVnbFJhWFRtUEhvTDh4L2ZhWFVrb3BmZVNsQzVQTEN0RE10d2dRNHRMNVdjazllcUNiaVAzZUcxTks2Ymx2TEtUTEJhQ3IyV01ZUzBseCsvV09iVWw4djJ2Q3A5dnNYZGRWOWFGWHBKUysrTVFyaFNDNHFCdWZiUkViUmZQdVJXVjJqOEpCZk9XSFUwcGZlRXExMkQzU09MNlhXWVdRWVc0WVVEb3pETHVBdnVGakthWFB2R0JSYlRwTGk5VWxCaEtoTzlnMHNOdjhKT1pEM2tzK25sTDYzUE9LSUphQUx0VTZiYXZ0MmZGOEhnQnBGMHZYMWFVM3A1USsvNlJTdmJvYjFkditPODJOWERKbkJtNDVveG4wMTZjLzg0T3ZTU2w5NVFsWGx2djByS2xIejJlaVNSbEFEcW5sUmk0c3U4Y1VkQjF4K3Ztdlh3TTZiV2pjdW40bUxoWXJnVzdvNkMwN2lQWGx1WU1ZUCtPelQxdlFiUlZuTHBkbi8xa3U5cWRITU5TdTNqcUFtem1JWGZmeDFDdVRSNzU1SkxkMVRwVEtWelRMVUROM1dRVDZtdHVtQnpGLzROM2JtNjJaNFdjOTErdm1mWVBScE5acTdqVFlxdlBLbHI2dFdFTVdUUGV1VjkyMGJjeGNQSWtqaEJoTk16UGF1RzVoYS9VMEYvTG1DcDQzZkdLWDJmZzRGSE9rakdwdXZZaU9jWmMwZnVXbUc0WS81YTBmZVBuTGJxM3E5N3oyaHZkVmkxUUlhWE11Q2pVUUJ2d2Q0bUlqYXNrOVZ4bDAvNHZYZlhyeXFlZDg2c2FxZXZOSFA3bE1oVEEwZHlGUkIvUFZuN3psKzl3b0h1OGlwdFdYc2ZhdnNVaktkNGlRWUVybkZiU0hDNGFNdXM0Njd1VmlxeThZN2t1U1loZmhJSktPZllKRy95cmsrRjA0dHBuT00yaENSSHRSZlo0VjRzZ1h6NjIzZEx0ajVlYUMwK01iZXYxRjhGRlBPMFJ1b1dGTDV4eDBaSkdRWDhVdnplSHhNYS9XbWtKZzNMRVFpbTg2blgvUUlRRE1GQk9sczhDOFZsNHZoM1FpLzNxY1ExK3J1YmVNaUh5RHNFNTFHZGN4M1lPUTNkd09kVmFZMThmcElCN2xzNE84eS9aRjNJdVh6dksxK3BjYmJHQnJ6aW5vYy9KNlFJTCtIMTl0aGRPd09nNkNBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiYWFndWlkIjoiOTcwYzhkOWMxOWQyNDZhZmFhMzIzZjQ0OGRiNDllMzUiLCJvcHRpb25zIjp7InBsYXQiOnRydWUsInJrIjp0cnVlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJ0cmFuc3BvcnRzIjpbImludGVybmFsIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTI1N30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTY1NTM1fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDEtMjYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTAxLTI2In0seyJhYWd1aWQiOiJjNTcwMzExNi05NzJiLTQ4NTEtYTNlNy1hZTEyNTk4NDMzOTkiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImM1NzAzMTE2LTk3MmItNDg1MS1hM2U3LWFlMTI1OTg0MzM5OSIsImRlc2NyaXB0aW9uIjoiTkVPV0FWRSBCYWRnZW8gRklETzIiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUVPRENDQTkyZ0F3SUJBZ0lEQUluQk1Bb0dDQ3FHU000OUJBTUNNSHN4Q3pBSkJnTlZCQVlUQWtaU01STXdFUVlEVlFRS0V3cERaWEowUlhWeWIzQmxNUmN3RlFZRFZRUUxFdzR3TURBeUlEUXpOREl3TWpFNE1ERWtNQ0lHQTFVRUF4TWJRMlZ5ZEVWMWNtOXdaU0JGYkd4cGNIUnBZeUJTYjI5MElFTkJNUmd3RmdZRFZRUmhFdzlPVkZKR1VpMDBNelF5TURJeE9EQXdIaGNOTVRnd01qSXlNak13TURBd1doY05Namd3TVRJeE1qTXdNREF3V2pCME1Rc3dDUVlEVlFRR0V3SkdVakVUTUJFR0ExVUVDaE1LUTJWeWRFVjFjbTl3WlRFWE1CVUdBMVVFQ3hNT01EQXdNaUEwTXpReU1ESXhPREF4SFRBYkJnTlZCQU1URkVObGNuUkZkWEp2Y0dVZ1NXUmxZM2x6SUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTTFZMKzFTVEp2YUVSTzVXQ1IrakdjQXhMdm1QQkRpWlkxTmdGRklocFg2T0FaQXBRWW10NnhTaDc0U3dNK21qZ25zU0VjYzRBMlVmMTM5RmdaNHJwWW80SUNWVENDQWxFd0V3WURWUjBqQkF3d0NvQUlUWjAxdEd1QlBMb3dTZ1lJS3dZQkJRVUhBUUVFUGpBOE1Eb0dDQ3NHQVFVRkJ6QUNoaTVvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMlZqWDNKdmIzUXVZM0owTUZNR0ExVWRJQVJNTUVvd1NBWUpLb0Y2QVdrcEFRRUFNRHN3T1FZSUt3WUJCUVVIQWdFV0xXaDBkSEJ6T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdlkyaGhhVzVsTFdSbExXTnZibVpwWVc1alpUQ0NBV0FHQTFVZEh3U0NBVmN3Z2dGVE1EK2dQYUE3aGpsb2RIUndPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2Y21WbVpYSmxibU5sTDJObGNuUmxkWEp2Y0dWZlpXTmZjbTl2ZEM1amNtd3dnWWFnZ1lPZ2dZQ0dmbXhrWVhBNkx5OXNZM0l4TG1ObGNuUmxkWEp2Y0dVdVpuSXZZMjQ5UTJWeWRFVjFjbTl3WlNVeU1FVnNiR2x3ZEdsakpUSXdVbTl2ZENVeU1FTkJMRzkxUFRBd01ESWxNakEwTXpReU1ESXhPREFzYnoxRFpYSjBSWFZ5YjNCbExHTTlSbEkvWTJWeWRHbG1hV05oZEdWU1pYWnZZMkYwYVc5dVRHbHpkRENCaHFDQmc2Q0JnSVorYkdSaGNEb3ZMMnhqY2pJdVkyVnlkR1YxY205d1pTNW1jaTlqYmoxRFpYSjBSWFZ5YjNCbEpUSXdSV3hzYVhCMGFXTWxNakJTYjI5MEpUSXdRMEVzYjNVOU1EQXdNaVV5TURRek5ESXdNakU0TUN4dlBVTmxjblJGZFhKdmNHVXNZejFHVWo5alpYSjBhV1pwWTJGMFpWSmxkbTlqWVhScGIyNU1hWE4wTUJFR0ExVWREZ1FLQkFoRGFRYmhURnRqY2pBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQW9FZXBITUM1WDlqQkthR3BoY0tqaWRoaU4rWm56N3YzUzNoYzMxL0F1bnNDSVFES3FvZ0syU1pPWFpjdnZIQ0I2VVFTYUEwbkxuNFJVd3kxZ3VEaXZiWmJ3Zz09IiwiTUlJQ0hUQ0NBY0tnQXdJQkFnSUNkZFV3Q2dZSUtvWkl6ajBFQXdJd2V6RUxNQWtHQTFVRUJoTUNSbEl4RXpBUkJnTlZCQW9UQ2tObGNuUkZkWEp2Y0dVeEZ6QVZCZ05WQkFzVERqQXdNRElnTkRNME1qQXlNVGd3TVNRd0lnWURWUVFERXh0RFpYSjBSWFZ5YjNCbElFVnNiR2x3ZEdsaklGSnZiM1FnUTBFeEdEQVdCZ05WQkdFVEQwNVVVa1pTTFRRek5ESXdNakU0TURBZUZ3MHhPREF4TWpJeU16QXdNREJhRncweU9EQXhNakl5TXpBd01EQmFNSHN4Q3pBSkJnTlZCQVlUQWtaU01STXdFUVlEVlFRS0V3cERaWEowUlhWeWIzQmxNUmN3RlFZRFZRUUxFdzR3TURBeUlEUXpOREl3TWpFNE1ERWtNQ0lHQTFVRUF4TWJRMlZ5ZEVWMWNtOXdaU0JGYkd4cGNIUnBZeUJTYjI5MElFTkJNUmd3RmdZRFZRUmhFdzlPVkZKR1VpMDBNelF5TURJeE9EQXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBVHoyak5hS09LL01LZFcyZm1lMXRxNkdSRXVQdXVLVzlIZ1dZZ01Scmp2WlVUT3FMQU5KM01kNUhxdjFFTjF6TWQ0bFd0eWZ6UmxhN3J2NUFSQm9Pb1Rvell3TkRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUJFR0ExVWREZ1FLQkFoTm5UVzBhNEU4dWpBT0JnTlZIUThCQWY4RUJBTUNBUVl3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQU1yaGI4U21mTkxlTE5nYUFWbVE2QU9NaUxOTFZIWDBrRlVPODBDblQzOEVBaUVBek5BZ3Y0ZEgrSERoWlNnWldKaWFQdS9uZlpUZXVHeTRNeWRQTXE1dXJzND0iLCJNSUlFT0RDQ0E5MmdBd0lCQWdJREFJbkJNQW9HQ0NxR1NNNDlCQU1DTUhzeEN6QUpCZ05WQkFZVEFrWlNNUk13RVFZRFZRUUtFd3BEWlhKMFJYVnliM0JsTVJjd0ZRWURWUVFMRXc0d01EQXlJRFF6TkRJd01qRTRNREVrTUNJR0ExVUVBeE1iUTJWeWRFVjFjbTl3WlNCRmJHeHBjSFJwWXlCU2IyOTBJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3SGhjTk1UZ3dNakl5TWpNd01EQXdXaGNOTWpnd01USXhNak13TURBd1dqQjBNUXN3Q1FZRFZRUUdFd0pHVWpFVE1CRUdBMVVFQ2hNS1EyVnlkRVYxY205d1pURVhNQlVHQTFVRUN4TU9NREF3TWlBME16UXlNREl4T0RBeEhUQWJCZ05WQkFNVEZFTmxjblJGZFhKdmNHVWdTV1JsWTNseklFTkJNUmd3RmdZRFZRUmhFdzlPVkZKR1VpMDBNelF5TURJeE9EQXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU0xWTCsxU1RKdmFFUk81V0NSK2pHY0F4THZtUEJEaVpZMU5nRkZJaHBYNk9BWkFwUVltdDZ4U2g3NFN3TSttamduc1NFY2M0QTJVZjEzOUZnWjRycFlvNElDVlRDQ0FsRXdFd1lEVlIwakJBd3dDb0FJVFowMXRHdUJQTG93U2dZSUt3WUJCUVVIQVFFRVBqQThNRG9HQ0NzR0FRVUZCekFDaGk1b2RIUndPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2Y21WbVpYSmxibU5sTDJWalgzSnZiM1F1WTNKME1GTUdBMVVkSUFSTU1Fb3dTQVlKS29GNkFXa3BBUUVBTURzd09RWUlLd1lCQlFVSEFnRVdMV2gwZEhCek9pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZZMmhoYVc1bExXUmxMV052Ym1acFlXNWpaVENDQVdBR0ExVWRId1NDQVZjd2dnRlRNRCtnUGFBN2hqbG9kSFJ3T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdmNtVm1aWEpsYm1ObEwyTmxjblJsZFhKdmNHVmZaV05mY205dmRDNWpjbXd3Z1lhZ2dZT2dnWUNHZm14a1lYQTZMeTlzWTNJeExtTmxjblJsZFhKdmNHVXVabkl2WTI0OVEyVnlkRVYxY205d1pTVXlNRVZzYkdsd2RHbGpKVEl3VW05dmRDVXlNRU5CTEc5MVBUQXdNRElsTWpBME16UXlNREl4T0RBc2J6MURaWEowUlhWeWIzQmxMR005UmxJL1kyVnlkR2xtYVdOaGRHVlNaWFp2WTJGMGFXOXVUR2x6ZERDQmhxQ0JnNkNCZ0laK2JHUmhjRG92TDJ4amNqSXVZMlZ5ZEdWMWNtOXdaUzVtY2k5amJqMURaWEowUlhWeWIzQmxKVEl3Uld4c2FYQjBhV01sTWpCU2IyOTBKVEl3UTBFc2IzVTlNREF3TWlVeU1EUXpOREl3TWpFNE1DeHZQVU5sY25SRmRYSnZjR1VzWXoxR1VqOWpaWEowYVdacFkyRjBaVkpsZG05allYUnBiMjVNYVhOME1CRUdBMVVkRGdRS0JBaERhUWJoVEZ0amNqQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQUtCZ2dxaGtqT1BRUURBZ05KQURCR0FpRUFvRWVwSE1DNVg5akJLYUdwaGNLamlkaGlOK1puejd2M1MzaGMzMS9BdW5zQ0lRREtxb2dLMlNaT1haY3Z2SENCNlVRU2FBMG5MbjRSVXd5MWd1RGl2Ylpid2c9PSIsIk1JSUNIVENDQWNLZ0F3SUJBZ0lDZGRVd0NnWUlLb1pJemowRUF3SXdlekVMTUFrR0ExVUVCaE1DUmxJeEV6QVJCZ05WQkFvVENrTmxjblJGZFhKdmNHVXhGekFWQmdOVkJBc1REakF3TURJZ05ETTBNakF5TVRnd01TUXdJZ1lEVlFRREV4dERaWEowUlhWeWIzQmxJRVZzYkdsd2RHbGpJRkp2YjNRZ1EwRXhHREFXQmdOVkJHRVREMDVVVWtaU0xUUXpOREl3TWpFNE1EQWVGdzB4T0RBeE1qSXlNekF3TURCYUZ3MHlPREF4TWpJeU16QXdNREJhTUhzeEN6QUpCZ05WQkFZVEFrWlNNUk13RVFZRFZRUUtFd3BEWlhKMFJYVnliM0JsTVJjd0ZRWURWUVFMRXc0d01EQXlJRFF6TkRJd01qRTRNREVrTUNJR0ExVUVBeE1iUTJWeWRFVjFjbTl3WlNCRmJHeHBjSFJwWXlCU2IyOTBJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVR6MmpOYUtPSy9NS2RXMmZtZTF0cTZHUkV1UHV1S1c5SGdXWWdNUnJqdlpVVE9xTEFOSjNNZDVIcXYxRU4xek1kNGxXdHlmelJsYTdydjVBUkJvT29Ub3pZd05EQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CRUdBMVVkRGdRS0JBaE5uVFcwYTRFOHVqQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0NnWUlLb1pJemowRUF3SURTUUF3UmdJaEFNcmhiOFNtZk5MZUxOZ2FBVm1RNkFPTWlMTkxWSFgwa0ZVTzgwQ25UMzhFQWlFQXpOQWd2NGRIK0hEaFpTZ1pXSmlhUHUvbmZaVGV1R3k0TXlkUE1xNXVyczQ9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFDcVVsRVFWUkl4MlA4Ly84L0F5MEJFd09Od2FnRnBGbHc4Y0tGaXJJeVIzdDdTMU96MEtEZ0JmUG0vL3o1azNpenZuMzlscCtUYTJ0bHRXVFJJb1RvZnhoWXRYS2xscHE2c3J3Q0Fpa29SSVZIdkgzNzlqOXg0TlNwVTBBdFFJMVc1aFp3UWFnUHpwODdWMTFaaVhBdkl4ajlaemg1NGtSTlpSV1JQdmo5NnhjRE9NMHpNVEtpQjlHOHVYUC8vZnNITkZSQVNMQytzWEhtN05sdWJ1NFFtM2J0M0xsdTdWcGlMR0NFbWN1SWFjR1pVNmZCNGNXUVgxQVFHeC9uN09JeWFlb1ViVjBkaUl2YW1sdWVQWHRHVVNULytnMzJIU09EaG9ZR1JJU0ZoYVdwcFlXVmxSVW8rT0hqaDZiNkJvb3NnSHZxejU4L2NEbDlmZjNNN0N3SWU4K2UzYXRYcnFRZ21lSW9rREt6cy9YMTlFR3kveGs2T3pvZlAzcEVXVWJEc0FZWVJDM3RiUndjSEVEMmgvZnY2MnBxQ1JlT2pDVG1aRTB0clp5OFhBajc4S0ZEeTVZdUpkNTBWQXNZY2VwS1RVODNOaldCcU9udTdIeHcvd0UrTy83anNnQzMxNW1abVJ1Ym05bloyWUZxdm56KzBsQmZoek9nL3FPN2xRbS9CK0VBbUh3TGlvb2dDbzRjT3J4azBXSWlQVUVna3BGQlVuS3ltWms1aE4zVDFYWDN6aDFpWW9LSmNEVEJBNHFGdWJtdGxZdWJDOGorK3ZWclRWVTFxSFFoelFlTUJIeWhyS3hjV0Z3TVVYbjYxS241YytkU3Y4SkpTRXkwdHJHR3NDZjA5OSs2ZFFzdXhjTENDckg3UDVJclNZZ0RlS0ZTMzlURXg4c0haSC8vOXIydUdoRlFONjVmaDJWUE5vcXFUQ1VscGVLeVVtZ3hmUHBNU1dFUk1BTXVYN2FzdjdjWElxaWxyWVh3RnJ4ZWcvcU91R1pTZEV6TTN0MTdEaDA2Q1BUMHBrMGJOMjNjQ0k5RllLWkp6OGhFOThIZmYzOGhERFkyZGlMOTBkSGRwYXVyaXhhd3JDeXNyZTN0dW5xNmlMVFgwTkFBVG9Jc1R4NC90bmR3aUl5T0F0WUV4RmpBemMzdDQrc0xKTDk5L1Fvc0UwVkZSZTNzN1J0Ym1vR1ZGVXFjalRZZGg3OEZBSWhCTGxOZDdqdTFBQUFBQUVsRlRrU3VRbUNDIiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJjNTcwMzExNjk3MmI0ODUxYTNlN2FlMTI1OTg0MzM5OSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjpmYWxzZX0sIm1heE1zZ1NpemUiOjY0MCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sInRyYW5zcG9ydHMiOlsibmZjIiwidXNiIl0sImZpcm13YXJlVmVyc2lvbiI6Mn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wOS0yMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDktMjEifSx7ImFhZ3VpZCI6ImM4MGRiZDlhLTUzM2YtNGExNy1iOTQxLTFhMmYxYzdjZWRmZiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiYzgwZGJkOWEtNTMzZi00YTE3LWI5NDEtMWEyZjFjN2NlZGZmIiwiZGVzY3JpcHRpb24iOiJISUQgQ3Jlc2NlbmRvIEMzMDAwIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMwLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUMrekNDQXFHZ0F3SUJBZ0lVZEhrWnFvajYyMzlFLzhGUWIrSUpTdUhDYUZVd0NnWUlLb1pJemowRUF3SXdhekVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFvTUNraEpSQ0JIYkc5aVlXd3hJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhJekFoQmdOVkJBTU1Ha1pKUkU4Z1FYUjBaWE4wWVhScGIyNGdVbTl2ZENCRFFTQXlNQjRYRFRJeU1URXdOREl4TURrek5Gb1hEVFEzTVRFd05ESXhNRGt6TkZvd1pqRUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQW9NQ2toSlJDQkhiRzlpWVd3eElqQWdCZ05WQkFzTUdVRjFkR2hsYm5ScFkyRjBiM0lnUVhSMFpYTjBZWFJwYjI0eEhqQWNCZ05WQkFNTUZVWkpSRThnUVhSMFpYTjBZWFJwYjI0Z1EwRWdOREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSmxVL3R4K0FRa0RlcnN3M3BKMlRDcnNyaW9WV2cvcDNJMTg1ODgzUlBSbzN5dWRkOThqVm5OdHA3RGlHRjdzSnpBaloyaTJYYjN2UFVZSCt1OTBmTG1qZ2dFbU1JSUJJakFPQmdOVkhROEJBZjhFQkFNQ0FZWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFmQmdOVkhTTUVHREFXZ0JTNzZEcGw5M3ZCMmg1RkRMdnlNTXZVQnlqM2l6QWRCZ05WSFE0RUZnUVVETCt6cGZyTHVkM3FwalZUK285YzVDMERYNVV3UkFZRFZSMGZCRDB3T3pBNW9EZWdOWVl6YUhSMGNEb3ZMMk55YkM1b2VXUnlZVzUwYVdRdVkyOXRMMFpKUkU5QmRIUmxjM1JoZEdsdmJsSnZiM1JEUVRJdVkzSnNNSFlHQ0NzR0FRVUZCd0VCQkdvd2FEQS9CZ2dyQmdFRkJRY3dBb1l6YUhSMGNEb3ZMMk55YkM1b2VXUnlZVzUwYVdRdVkyOXRMMFpKUkU5QmRIUmxjM1JoZEdsdmJsSnZiM1JEUVRJdWNEZGpNQ1VHQ0NzR0FRVUZCekFCaGhsb2RIUndPaTh2YjJOemNDNW9lV1J5WVc1MGFXUXVZMjl0TUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUJ1Vzlack5yaE5JeFFzZHlFZ05DeG5KbHlyWUdCdTYxSzJ4QSt6QW9weU9BaUVBcHdTM1hSZVBRQVZWR25URGFFMmw5ZnpPSHYwUDJEUFRBODUzOTJWRGJqcz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBVk1BQUFDc0NBWUFBQURHK0U4TUFBQUFJR05JVWswQUFIb2xBQUNBZ3dBQStmOEFBSURwQUFCMU1BQUE2bUFBQURxWUFBQVhiNUpmeFVZQUFBQUpjRWhaY3dBQUQyQUFBQTlnQVhwNFJZMEFBQXlnU1VSQlZIaGU3WjEvYkpUbEhjQnZqaGpOY0M0TytkWGVYVnRVVE16aVA3b1lYWlk1MUlrS2QxZk5uRkhqNW9oQm1BN2oyTVJzWm9sbXhoaE5Kb3J0MjRLZ3NpRnNpbTdUQWRNWVJGUUVGVGNWeHcvcndBRUZSQ2hRK3V1ZVBjLzFxUVAzVE5zKzMzdmV1K3ZuazN6UzQyZ2ZudmU5dDU4Kzc3M1hJd0VBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFVRXBrRzYvWFBwbklSUjhnSWg1dDQxcjljWWF0QmZ3UDlRM242eDIwVFp0UDFEY3BSTVRQTmRlVTE0dXVWdDJNcTIxRkJreHRNam1yTHBWcTBSODMxMVpYMzJydkxtTUtQMjMwanFtUDNEc05FZkh6ekVXN0V4Zk9HV21MOG9Xa2s4a2YxcVhTUFhYVnFhWEpVYVBPcUttcU9yTXVtZnByYlRMVm5VcWxMcmVmVmtaTW1QMTEvWk9sdzdsekVCRUhvam1yelVaVGJWMytMM1ZqeDA0d0lSMDlldlRKNDFLcEtkb2JqQ05Iamh3MWR1elk1TGgwamRLcjFMUHRwNWNCSnFTc1JoRlIwdDZnenJTVmNYR01EcW1xU1NZeit2WXdFODZhcXRTMXRkWHA2ODN0dWpGalVqVmprNVAxS3JXOTk5UExnVnpVNWR3WmlJZyttcUJlT3FmT2x1WW8wdW4wY1RxbVhmYVB3OHdLMWQ1TzZGUDh0MnJUNlZ2MHpTK2JzUGJlVytya29vK2NPd0VSVWNKY2RNRFc1aWlxcTZ1UEg1ZXE2VnQxRmxhbU9xSTc2MUkxMjA5SjEvUkY5a3ZsRWRQNmhtODdOeDRSVWRKc3d6MjJPcDlpWXFwWG81MzJqMlpsbWovcHBKTytxajkycDhlTU9kM2VmMHg1eERUWHRNKzU0WWlJa3VhaURsdWRJK2s5aFU4bmp0TzNDekUxZDQ0WU1XS012bjNRM0I0K2V2akorbmJmS3JXRTRYV2tpQmpLeTV2UHN1WDVsTHBVYW1adE1yM2YzSzZ0VHI1VHVGTlRsMHcrV3BOSzNhei9ycU8yT2ozTjNsMmlUSTZtT2pjWUViRVk1cHFldGZVNWlycnExRE8xeWRTQmNWV3BHK3hkaWJxcTVBeXpPdFgzTDdSM2xURDEwWExuQmlNaUZzTmNVK0hVM1VWeVZQSU1IZFdWcDlYV3FWTnJhdlA2OXZLcUVWV24ycjh1Y2Vxai9jNE5Sa1FzaHJtb2pGNHZPaENJS1NLRzFIMFJxZ0lncG9nWVVtS0tpQ2dnTVVWRUZKQ1lJaUlLU0V3UkVRVWtwb2lJQWhKVFJFUUJpU2tpb29ERUZCRlJRR0tLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRRUzk3V0NVdWVFQWxMcHdkVnZOdjVpTDNuQWJyOXg1MC8xdkY5aUt0YXo0RE1hN0h3RHorcnZuMHg2eCsvT0tZZHpFMDIzR1JQbjdNTVhTcDNpZVRHOTNiWEdrU1V6bHZudnV5aW92anJwem5uTk9nMUFmL3VzMjc3TWhoMmZuSm9kNXZRTmU4K3FQK0pvNkxhZEVxOTV6NjRkZXVYV0JIcVF3NnUzdFVXM3VuMnJ4am4xcTlZYWRhc25xenVxbjVaWFh5TlF0VTR1S0hWQ0pUZ1lFbHBuS2FiNmE0cUpTWWZyVG5RTm5HOUlhSFgzTFBxUitlcUNNelZOaXovN0JhOGRaV2RlVjl6NnZFQkwyS3JaU3dFbE01aWFrL3hIUm8wZG5WbzU1ZDk2RWFmK01pdjZkSlNrRmlLaWN4OVllWURsM2VidG1qenB1MTFPL3hqMU5pS2ljeDlZZVl3aHRiZHFsVHB1cVZxcmtvNTloWEpTc3hsWk9ZK2tOTXd6UHJzVFhxenNWdnFMdVd2S0V5ZHk5VHVYdVdxMTh1ZkwxdzM3MUwxNnNWNjdjVkxpYUZwQ2VmVjQrKytFK1Z1R0MyYzMrVnBNUlVUbUxxRHpFTlQyTENiL1Vxc0ZFbE1nMy9uWk81S0ZTNFR6dEpQeDZYemxGVlV4YXFLWE5XcW8vYkR0dXZMRDY3MjlyVk4zNjZ4SVRxcVAxVmtoSlRPWW1wUDhRMFBJWFhoanJtNUZSSDdaakpEZXFPMzYrMVgxMTh1bnQ2MUMyUHJOYkg1Ukd4TDBXSnFaekUxQjlpR3A0QnhiUlBIYlpKZHkrekk0UmgvZ3Z2RjFiSXp2bVVnc1JVVG1McUR6RU56NkJpYXN3MHFoL3IwLzZRUFBucUIzN0hSekVscG5JU1UzK0lhWGdHSFZOak5sSi8vM0NQSFNrTVQ3L1dVcHBCSmFaeUVsTi9pR2w0dkdLcUhmK1R4WGFrY1B6eEZiMUNMYlhuVUltcG5NVFVIMklhSHQrWW1xaTl0MjJ2SFMwY1AxdndxbnMrY1VsTTVTU20vaERUOEhqSE5CZXA4MjUvMm80V2pudytyOFpQWCt5ZVV4d1NVem1KcVQvRU5EemVNZFYrNWFwSDdHaGgyWGV3UTJUK0loSlRPWW1wUDhRMFBDSXhtbVJPOVQreEk0YmxtVFV0aGRXeGMxNGhKYVp5RWxOL2lHbDRSR0thamRRdDgxNnhJNFpuK0ZXQ3gvOWdKYVp5RWxOL2lHbDRwRTZUejV5eHhJNFludmMvMnR2NzY2K09lUVdUbU1wSlRQMGhwdUdSaXVubzZ4KzNJOGJEaU9zZWRjNHJtTVJVVG1McUR6RU5qMVJNaDEzUmJFZU1CM1BNeHZyY0tUR1ZrNWo2UTB6REl4VlRjeEdxcTd2YmpocWVydTRldVcwWmpNUlVUbUxxRHpFTmoxaUE5SEd6ZGxPckhUVWVicDBmNHd2NWlhbWN4TlFmWWhvZXNaaG1HdFhDbFJ2dHFQR3diYmMrZnVKNmgzNWlLaWN4OVllWWhrY3NwanBpdHoyMnhvNGFEKzBkWFNveE1hYTM2U09tY2hKVGY0aHBlQ1JqR3VkclRmdUk3YW8rTVpVenpwaCs1MWQvVXVmT2VsckViLzc4S2JVaGhqZXVNQkRUOElqRk5LYmYwZjhzdHoyK3hqMi9Za3RNNVl3enBwVUNNUTJQV0V5MTU5eTIxSTRhSDZ2ZTNlNmNXOUVscG5JU1UzK0lhWGdxTGFaYjQ3b0lSVXpsSktiK0VOUHdWRnBNdCs4OTJQdS9xanJtVjFTSnFaekUxQjlpR3A1S2krbXVmZTBxbG5maEo2WnlFbE4vaUdsNEtpMm1oZmM0dmN6akdCcXN4RlJPWXVvUE1RMVB4WjNtZjh4cHZpekV0Q3docHVHcHRKanUySHVJbUlwQ1RNc1NZaHFlU292cEJ6djNtN0E1NTFkVWlhbWNjY2JVdk1IRTYwS3UyYmhUSFdqdnNpT0hoWmlHcDlKaXVtVDFadWZjaWk0eGxUUE9tQjVyZmhLYko5MGx2UGdoOWZyR2VONzloNWlHUnl5bUpmSWJVUFgzTEhmUHI5Z1NVem5qakNtL20yOGxwZ05HTEtZbDhydjVzWnppRzRtcG5NVFVIMklhSHNtWVRvLzV1c0grUTUyOVoxZXUrUlZiWWlvbk1mV0htSVpITEthWlJyWG9wVTEyMUhoWTM3S2JsYWs0eEhUd0V0TkJRVXdiMVlyMTIreW84WEQyektYdXVZV1FtTXBKVFAwaHB1RVJpK25rQnRYNnlTRTdhbmphMnZVcC9pVXh2VEcwa1pqS1NVejlJYWJoa1h6T05FNmVXTFhKUGE5UUVsTTVpYWsveERROFVqRTk4WnI1ZHNUdzlQVGs0M25idlNNbHBuSVNVMytJYVhpa1lucnE5Q2ZzaU9INXk3cC9tWmc1NXhWTVlpb25NZldIbUlaSEpLWTZaSmZjK1p3ZE1TeUhPN3YxTVJQamM2VjlFbE01aWFrL3hEUThJakhOTktvbHE3ZllFY015clhHVmUwNmhKYVp5RWxOL2lHbDRSR0lhMDhXblRkdjN4ZmNpL2M5S1RPVWtwdjRRMC9CSXhIVDh0RVYydEhDMGQralRlMzJzdXVZVGk4UlVUbUxxRHpFTmozZE05U24rM09jMzJOSENZSzdlbnpYelNmZDg0cEtZeWtsTS9TR200ZkdONmZBZnpMTWpoV1BHdkplZGM0bFZZaW9uTWZXSG1JYkhLNmFURzlUY3Y0VmRsZDYrY0kwSmwzcytjVXBNNVNTbS9oRFQ4QXc2cHRsSW5YL0huKzBvWWJpcGVWVTgveVZKZnlTbWNoSlRmNGhwZUFZVjAweURPdmYyWit3SXhhZTdKNjkrTlB2RjBseVI5a2xNNVNTbS9oRFQ4UFE3cGlaaytyVGVIR3YzUHJYZWZuWHhPZGplcWNaTlhlU2VVeWxKVE9Va3B2NFEwL0Frdm5WLzc3c3RmZGFKRDZsaFZ6U3JFNitlcjA2L2FiSEszTDFjL1NId0MvT1h2Ym0xTUEvWFBpczVpYW1jeE5RZllncUdnNGM3MVZYM1AxOVlDYnYyVjBsS1RPVWtwdjRRMDZGTlIxZTNlbmpadXlyeDNRZWMrNm1rSmFaeUVsTi9pT25RcEwyelN6V3QyTkI3U2wvS0Y1aytUMklxSnpIMWg1Z09IZkw1dkhxN1pZK2FNbWVsU2x5Z1Y2TGxHdEUraWFtY3hOUWZZbHJaZk54MldLMTZiNGU2MGJ6VFU3WlJKU1o1UE5hbEpqR1ZjOUp2bHFubGIyNHRYSUVNNmNwMy9xMk8vZjVjNTV3R1phWlJQZmpzUDV6L1ZySDkzY3FOK2h2TTQ2TER4RG5xcFhlM084Y3VwaXZlMnFZdXVlczU5NXo2NFFsWHoxZTc5N2VybHRhMml2RE5MYnZWMmsydGhYM3o2eWZXcW9sM1BxZE9NRC93TDlhbjhmcUh0V3NmbEwzRUZMRUVOS2U0NXVWSVpsVmU3cHJ0TUZmaHkrbEt2SVRFRkJGUlFHS0tpQ2dnTVVWRUZKQ1lJaUlLU0V3UkVRVWtwb2lJQWhKVFJFUUJpU2tpb29ERUZCRlJRR0tLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCS3phbXVhalZ1Y0dJaU1YeG9LMVBoWkZ0YUhKc0xDSmljY3hGdTJ4OUtvd3Jtc2M3TnhnUnNSaG1vbC9ZK2xRZzVqa00xMFlqSWtxYWkvSzJPaFZLcnVrRjU0WWpJa3FhaTNiWTZsUXd1YWpidWZHSWlCTG10T2ZjZDd3dFRnV1RpNlk3ZHdBaW9vUzVhSm10elJDZ1Buck51Uk1RRVgzTVJxMjJNa09JYk9ORzU4NUFSQnlNdWFZS2ZTbFVmOGhGaS9RT3lPdVZxbnZuSUNKK2tlYktmWDNUV2x1VklVdzJPazJ2VWx1SktpSU8yRnkwTjVGdHVzN1dCQXFZcU5aSDYvVEhmVHFzblluNlpyMnpFQkdQMEt4Q3MxR2Jic1NXUktaaGdxMEhBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFQnBrVWo4QjRBb20rTWJUKzNKQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJjODBkYmQ5YTUzM2Y0YTE3Yjk0MTFhMmYxYzdjZWRmZiIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjUsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6ODB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMS0yMCIsInVybCI6Imh0dHBzOi8vd3d3LmhpZGdsb2JhbC5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJISUQgQ3Jlc2NlbmRvIEMzMDAwIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzAxMjAwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMS0yMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDEtMjQifSx7ImFhZ3VpZCI6IjViMGU0NmJhLWRiMDItNDRhYy1iOTc5LWNhOWI4NGY1ZTMzNSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNWIwZTQ2YmEtZGIwMi00NGFjLWI5NzktY2E5Yjg0ZjVlMzM1IiwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IDUgRklQUyBTZXJpZXMgd2l0aCBMaWdodG5pbmcgUHJldmlldyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMzg0cjFfZWNkc2Ffc2hhMzg0X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjgsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6OCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURLakNDQWhLZ0F3SUJBZ0lVZWYrVnZIa2NUUW5FRCsrd0pNL0l4elNVTGswd0RRWUpLb1pJaHZjTkFRRUxCUUF3SmpFa01DSUdBMVVFQXd3YldYVmlhV052SURJd01qTWdSa2xFVHlCUWNtVjJhV1YzSUVOQk1CNFhEVEl6TURreU5URXhNekkwTVZvWERUSTBNVEl6TVRFeE16STBNVm93SmpFa01DSUdBMVVFQXd3YldYVmlhV052SURJd01qTWdSa2xFVHlCUWNtVjJhV1YzSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBb3VGTVRPS2FFMFl0ZXhPb2lzU3hwK0ViaTVJQTRlc0VTY3gxNmx6UWRxVjYvZVo4Mkt0SmVOWEV1TmtCVlpEcGMzMmdTdHV4TEJIOG1nc29IQkZhaTJEa2pmQm41cWJ3Ui9jNStzbmx3WnZqZ1ZBMGh6S3c5Q3dBZUF3UkQ1a3JXdDg4L0NWeUNrTWNnTFNHd1pzL3JqN0YvTHMzRWJnN01xTGJiUUo5Q296YmJMZEpVWUlIY1BwU1pQdG9NclpiNEd2bmk2aVZTOVV2Q0tncHFjNkxHUm1vWUdHNFpSM2xHSi9YUVpmdStHZUpXNjdpaW1Nai95b1hPd3h1Y3hpdlpIRms2Y1FTZ3d1d2lvZU5tNHd2azgzTGhTdVdjdGYya0F5UWNaN2tVbnBOZWUrZDRNZ3JtR1U0WE1GTGlUZ3V0YUIrZTlWOGQ1SlRrVU9IaUx6dGtRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVNNVNCNWJIclYranBJT01kSmw3dTdiY25UWTh3SHdZRFZSMGpCQmd3Rm9BVU01U0I1YkhyVitqcElPTWRKbDd1N2JjblRZOHdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUNvd1IzS1RMZmlkSnlRRk5xRUZmVXJmWjlhYTllZ3BPUXROUkpkTFN0SjZ4dTJXZkx3dkc0b2pHSmxCS05uZmE1REljeVFZZi84cUo0ZWxpQVZlTlh1WW1lTW1nTmdaWnl1WTZHMXlXQ0QyVjNzRDZaNHVqM1NiYURPSGozZ0h2c3pnUWhyaFQxaC9wdUhRa242K2hZS0FwNzdrTTdJYzZBWi9SRmJqcG1MTGsyRDBzRTFselQvMDJpK0JoN004c21haURaOSsrSkd6eGVTdW44VzFIbGVaVW0ycUtHbVJhNFhQZHJ5VDd4NktHVUduVTRhM2JwVW1WZVk5clEvc2ZNZDVaVG9vKzN1bkZXRHpvVlYydk51OCsrVkxDOXpvNDBGYUtRTHI5VkFKREo0eUxFTlI3S3JtVjhMMGNDWEtKR1pXQVd0RzVSR1RtSEloZCtuQjQxZz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiNWIwZTQ2YmFkYjAyNDRhY2I5NzljYTliODRmNWUzMzUiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJsYXJnZUJsb2JzIjp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6ZmFsc2UsImFsd2F5c1V2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTI4MCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMl0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0zNX1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjQwOTYsIm1pblBJTkxlbmd0aCI6OCwiZmlybXdhcmVWZXJzaW9uIjozMjk0NzIsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsImNlcnRpZmljYXRpb25zIjp7IkZJUFMtQ01WUC0yIjoyLCJGSVBTLUNNVlAtMi1QSFkiOjN9LCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6MTAwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTA0LTA3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wNC0wNyJ9LHsiYWFndWlkIjoiODIwZDg5ZWQtZDY1YS00MDllLTg1Y2ItZjczZjA1NzhmODJhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI4MjBkODllZC1kNjVhLTQwOWUtODVjYi1mNzNmMDU3OGY4MmEiLCJkZXNjcmlwdGlvbiI6IklEbWVsb24gaU9TIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InZvaWNlcHJpbnRfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJsb2NhdGlvbl9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImV5ZXByaW50X2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiaGFuZHByaW50X2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGF0dGVybl9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnl6Q0NBWEdnQXdJQkFnSUpBTm1NTks2alZwdXVNQW9HQ0NxR1NNNDlCQU1DTUVFeEpEQWlCZ05WQkFvTUcxWmhibU52YzNseklFUmhkR0VnVTJWamRYSnBkSGtnU1c1akxqRVpNQmNHQTFVRUF3d1FWbUZ1WTI5emVYTWdVbTl2ZENCRFFUQWdGdzB5TWpFeU1UUXhPRFF4TURsYUdBOHlNRGN5TVRJd01URTROREV3T1Zvd1FURWtNQ0lHQTFVRUNnd2JWbUZ1WTI5emVYTWdSR0YwWVNCVFpXTjFjbWwwZVNCSmJtTXVNUmt3RndZRFZRUUREQkJXWVc1amIzTjVjeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVhbFlnRW9wbktTY0FtK2Q5ZjFYcEdCM3pia1pDRDNoWkVLdXhUY2xwQllsajR5cE5SZzBnTVNhN2dlQmdkNm5jazUwWWFWaGR5NzV1SWMyd2JXWDh0Nk5RTUU0d0hRWURWUjBPQkJZRUZPeHlmMGNEczhZbCtWbldTWjF1WUpBS2tGZVZNQjhHQTFVZEl3UVlNQmFBRk94eWYwY0RzOFlsK1ZuV1NaMXVZSkFLa0ZlVk1Bd0dBMVVkRXdRRk1BTUJBZjh3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQU8yWHVpUkRYeHkvVWtXaHN1WlFZTlVYZU9qMDhBZVRXQURBcVh2Y0EzMGhBaUJpMmNkR2Q2MVBOd0hEVFlqWFBlblBjRDhTMHJGVERuY05XZnMzRS9XRFhBPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBTUFBQUJFcElyR0FBQUFNMUJNVkVVdG1jM3krZnlXek9aaXM5cks1Zkk2bjlCOHYrQ3cyZXpsOHZsSHB0TlZyTmJYN1BhajB1bHZ1ZDI5MysrSnh1UC8vLzg5SFJ2cEFBQUFFWFJTVGxQLy8vLy8vLy8vLy8vLy8vLy8vLy8vQUNXdG1XSUFBQUJzU1VSQlZIZ0J4ZFBCQ29Bd0RJUGgveURpc2UvL3RJSVFDWm82Uk5HZHR1V0RzdEZTZy9VT2dNaUFEUUJKNko0aUN3UzRCZ3pCdUVRSENvRmErbWRNK3FpanNETVZoQmZkb1JGYUFMNG5BZTZBZWdoT0RZUG5zYU55THVBcWc1QUh3TzlBWXU1Qm1xRVBobmNGbWVjdk01S0tRSE1BQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiODIwZDg5ZWRkNjVhNDA5ZTg1Y2JmNzNmMDU3OGY4MmEiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTAyLTA4IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJWYW5jb3N5cyBpT1MgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwMTA5MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDItMDgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTAyLTA4In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYzU1Zjc0YzcwYzY4ZThkY2U1YjdmZGI0Y2RkYTc3MmFkOTI5NGM2NyIsImZkMzY1NzNkMjRiZTNmN2YzMmFkNTA0MDI3MWFiNjEwMzVhMWZjYWQiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYzU1Zjc0YzcwYzY4ZThkY2U1YjdmZGI0Y2RkYTc3MmFkOTI5NGM2NyIsImZkMzY1NzNkMjRiZTNmN2YzMmFkNTA0MDI3MWFiNjEwMzVhMWZjYWQiXSwiZGVzY3JpcHRpb24iOiJHb1RydXN0IElkZW0gQ2FyZCBVMkYgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJ6akNDQVhPZ0F3SUJBZ0lKQU1oVi92UVl1NEtBTUFvR0NDcUdTTTQ5QkFNQ01Ec3hJREFlQmdOVkJBTU1GMGR2VkhKMWMzUWdSa2xFVHpJZ1VtOXZkQ0JEUVNBeU1SY3dGUVlEVlFRS0RBNUhiMVJ5ZFhOMFNVUWdTVzVqTGpBZUZ3MHhPVEV5TURRd056QXpNREZhRncwME9URXhNall3TnpBek1ERmFNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXlNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJKSGdLOWZOcU5FV0lZVHNaL2dOaTE3enBFcks3RkMxWW8rRnpxUlZNWUdVSmdBSjl2ZzMxaVRDSjFWWXhiQUtNUWJsTEdrVm4vZGZQNzNnZVRLZWQ5T2pZREJlTUF3R0ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01CMEdBMVVkRGdRV0JCUmdMWFdkV2VyMWtTR3BwZ1BsaVppMUhzWVBoREFmQmdOVkhTTUVHREFXZ0JSZ0xYV2RXZXIxa1NHcHBnUGxpWmkxSHNZUGhEQUtCZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF1anJLV1p3K1MwVGZHMWJKSmNzcW1HdTVXTGJCMkVnb3JEMmhBMnE2Qm9JQ0lRQ2l5eG52QW42TWkrRGRSbnczU1FHUVpvTEtGS3dIcjRYR05JTzVwQUhBSEE9PSIsIk1JSUJxRENDQVUrZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQTdNU0F3SGdZRFZRUUREQmRIYjFSeWRYTjBJRVpKUkU4eUlGSnZiM1FnUTBFZ01qRVhNQlVHQTFVRUNnd09SMjlVY25WemRFbEVJRWx1WXk0d0lCY05NakV3TXpBeU1EWXlNekUzV2hnUE1qQTFNVEF5TWpNd05qSXpNVGRhTURzeElEQWVCZ05WQkFNTUYwZHZWSEoxYzNRZ1JrbEVUeklnVW05dmRDQkRRU0F5TVJjd0ZRWURWUVFLREE1SGIxUnlkWE4wU1VRZ1NXNWpMakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQTc2WnlHM2UrRFpvVy9Ldk0zNlhKQUo2Qkw5a1hNTmpFdjRxR0lENWxBOFo4dVJlTTFZZk1pbzVuRUhMVTJTWkxRM3FYUlJ2eEdONEkrSDUrNmZWdzJqUWpCQU1BOEdBMVVkRXdRSU1BWUJBZjhDQVFBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUIwR0ExVWREZ1FXQkJScytVa21NNXhVazYvejVRTnRXQjI2aTR3NzdEQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQkErSVg1Ri84N1cvZW1aa2lKVEhxcmlMRlpPYTc5N3pzRS8wS1A3QVU1UWdJZ0I2NHhGcVBTQkM0S2kxVXJyTlg5VjJ0aGIrNDVSYnRTVm1pNjZXVitnbEU9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWpDQVlBQUFEMTdnaGFBQUFBQkdkQlRVRUFBTEdPZlB0Umt3QUFBQ0JqU0ZKTkFBQ0hEd0FBakE4QUFQMVNBQUNCUUFBQWZYa0FBT21MQUFBODVRQUFHY3h6UElWM0FBQUtMMmxEUTFCSlEwTWdVSEp2Wm1sc1pRQUFTTWVkbG5kVVZOY1doOCs5ZDNxaHpURFNHWHFUTGpDQTlDNGdIUVJSR0dZR0dNb0F3d3hOYklpb1FFUVJFUUZGa0tDQUFhT2hTS3lJWWlFb3FHQVBTQkJRWWpDS3FLaGtSdFpLZkhsNTcrWGw5OGU5MzlwbjczUDMyWHVmdFM0QUpFOGZMaThGbGdJZ21TZmdCM280MDFlRlI5Q3gvUUFHZUlBQnBnQXdXZW1wdmtIdXdVQWtMemNYZXJySUNmeUwzZ3dCU1B5K1planBUNmVELzAvU3JGUytBQURJWDhUbWJFNDZTOFQ1SWs3S0ZLU0s3VE1pcHNZa2lobEdpWmt2U2xERWNtS09XK1NsbjMwVzJWSE03R1FlVzhUaW5GUFp5V3d4OTRoNGU0YVFJMkxFUjhRRkdWeE9wb2h2aTFnelNaak1GZkZiY1d3eWg1a09BSW9rdGdzNHJIZ1JtNGlZeEE4T2RCSHhjZ0J3cExndk9PWUxGbkN5Qk9KRHVhU2tadk81Y2ZFQ3VpNUxqMjVxYmMyZ2UzSXlremdDZ2FFL2s1WEk1TFBwTGluSnFVeGVOZ0NMWi80c0dYRnQ2YUlpVzVwYVcxb2FtaG1aZmxHby83cjROeVh1N1NLOUN2amNNNGpXOTRmdHIveFM2Z0JneklwcXMrc1BXOHgrQURxMkFpQjMvdytiNWlFQUpFVjlhNy94eFhsbzRubUpGd2hTYll5Tk16TXpqYmdjbHBHNG9ML3JmenI4RFgzeFBTUHhkcitYaCs3S2lXVUtrd1IwY2QxWUtVa3BRajQ5UFpYSjR0QU4venpFL3pqd3IvTllHc2lKNWZBNVBGRkVxR2pLdUx3NFVidDViSzZBbThLamMzbi9xWW4vTU94UFdweHJrU2oxbndBMXlnaEkzYUFDNU9jK2dLSVFBUko1VU56MTMvdm1ndzhGNHBzWHBqcXhPUGVmQmYzN3JuQ0orSkhPamZzYzV4SVlUR2NKK1JtTGErSnJDZENBQUNRQkZjZ0RGYUFCZElFaE1BTld3Qlk0QWpld0F2aUJZQkFPMWdJV2lBZkpnQTh5UVM3WURBcEFFZGdGOW9KS1VBUHFRU05vQVNkQUJ6Z05Mb0RMNERxNENlNkFCMkFFaklQbllBYThBZk1RQkdFaE1rU0I1Q0ZWU0FzeWdNd2dCbVFQdVVFK1VDQVVEa1ZEY1JBUEVrSzUwQmFvQ0NxRktxRmFxQkg2RmpvRlhZQ3VRZ1BRUFdnVW1vSitoZDdEQ0V5Q3FiQXlyQTBid3d6WUNmYUdnK0UxY0J5Y0J1ZkErZkJPdUFLdWc0L0I3ZkFGK0RwOEJ4NkJuOE96Q0VDSUNBMVJRd3dSQnVLQytDRVJTQ3pDUnpZZ2hVZzVVb2UwSUYxSUwzSUxHVUdta1hjb0RJcUNvcU1NVWJZb1QxUUlpb1ZLUTIxQUZhTXFVVWRSN2FnZTFDM1VLR29HOVFsTlJpdWhEZEEyYUMvMEtuUWNPaE5kZ0M1SE42RGIwSmZRZDlEajZEY1lESWFHMGNGWVlUd3g0WmdFekRwTU1lWUFwaFZ6SGpPQUdjUE1ZckZZZWF3QjFnN3JoMlZpQmRnQzdIN3NNZXc1N0NCMkhQc1dSOFNwNHN4dzdyZ0lIQStYaHl2SE5lSE80Z1p4RTdoNXZCUmVDMitEOThPejhkbjRFbnc5dmd0L0F6K09ueWRJRTNRSWRvUmdRZ0poTTZHQzBFSzRSSGhJZUVVa0V0V0oxc1FBSXBlNGlWaEJQRTY4UWh3bHZpUEprUFJKTHFSSWtwQzBrM1NFZEo1MGovU0tUQ1pya3gzSkVXUUJlU2U1a1h5Ui9KajhWb0lpWVNUaEpjR1cyQ2hSSmRFdU1TanhRaEl2cVNYcEpMbFdNa2V5WFBLazVBM0phU204bExhVWl4UlRhb05VbGRRcHFXR3BXV21LdEttMG4zU3lkTEYway9SVjZVa1pySXkyakpzTVd5WmY1ckRNUlpreENrTFJvTGhRV0pRdGxIcktKY280RlVQVm9YcFJFNmhGMUcrby9kUVpXUm5aWmJLaHNsbXlWYkpuWkVkb0NFMmI1a1ZMb3BYUVR0Q0dhTytYS0M5eFdzSlpzbU5KeTVMQkpYTnlpbktPY2h5NVFybFd1VHR5NytYcDhtN3lpZks3NVR2a0h5bWdGUFFWQWhReUZRNHFYRktZVnFRcTJpcXlGQXNWVHlqZVY0S1Y5SlVDbGRZcEhWYnFVNXBWVmxIMlVFNVYzcTk4VVhsYWhhYmlxSktnVXFaeVZtVktsYUpxcjhwVkxWTTlwL3FNTGt0M29pZlJLK2c5OUJrMUpUVlBOYUZhclZxLzJyeTZqbnFJZXA1NnEvb2pEWUlHUXlOV28weWpXMk5HVTFYVFZ6TlhzMW56dmhaZWk2RVZyN1ZQcTFkclRsdEhPMHg3bTNhSDlxU09uSTZYVG81T3M4NURYYkt1ZzI2YWJwM3ViVDJNSGtNdlVlK0EzazE5V045Q1AxNi9TditHQVd4Z2FjQTFPR0F3c0JTOTFIb3BiMm5kMG1GRGtxR1RZWVpocytHb0VjM0l4eWpQcU1Qb2hiR21jWVR4YnVOZTQwOG1GaVpKSnZVbUQweGxURmVZNXBsMm1mNXFwbS9HTXFzeXUyMU9ObmMzMzJqZWFmNXltY0V5enJLRHkrNWFVQ3g4TGJaWmRGdDh0TFN5NUZ1MldFNVphVnBGVzFWYkRUT29ESDlHTWVPS05kcmEyWHFqOVducmR6YVdOZ0tiRXphLzJCcmFKdG8yMlU0dTExbk9XVjYvZk14TzNZNXBWMnMzWWsrM2o3WS9aRC9pb09iQWRLaHplT0tvNGNoMmJIQ2NjTkp6U25BNjV2VEMyY1NaNzl6bVBPZGk0N0xlNWJ3cjR1cmhXdWphN3liakZ1Slc2ZmJZWGQwOXpyM1pmY2JEd21PZHgzbFB0S2UzNTI3UFlTOWxMNVpYbzlmTUNxc1Y2MWYwZUpPOGc3d3J2Wi80NlB2d2ZicDhZZDhWdm50OEg2N1VXc2xiMmVFSC9Mejg5dmc5OHRmeFQvUC9QZ0FUNEI5UUZmQTAwRFF3TjdBM2lCSVVGZFFVOUNiWU9iZ2srRUdJYm9nd3BEdFVNalF5dERGMExzdzFyRFJzWkpYeHF2V3Jyb2NyaEhQRE95T3dFYUVSRFJHenE5MVc3MTA5SG1rUldSQTV0RVpuVGRhYXEyc1YxaWF0UFJNbEdjV01PaG1Oamc2TGJvcit3UFJqMWpGblk3eGlxbU5tV0M2c2Zhem5iRWQyR1h1S1k4Y3A1VXpFMnNXV3hrN0cyY1h0aVp1S2Q0Z3ZqNS9tdW5BcnVTOFRQQk5xRXVZUy9SS1BKQzRraFNXMUp1T1NvNU5QOFdSNGlieWVGSldVckpTQlZJUFVndFNSTkp1MHZXa3pmRzkrUXpxVXZpYTlVMEFWL1V6MUNYV0ZXNFdqR2ZZWlZSbHZNME16VDJaSlovR3krckwxczNka1QrUzQ1M3k5RHJXT3RhNDdWeTEzYys3b2VxZjF0UnVnRFRFYnVqZHFiTXpmT0w3Slk5UFJ6WVROaVp0L3lEUEpLODE3dlNWc1MxZStjdjZtL0xHdEhsdWJDeVFLK0FYRDIyeTMxV3hIYmVkdTc5OWh2bVAvamsrRjdNSnJSU1pGNVVVZmlsbkYxNzR5L2FyaXE0V2RzVHY3U3l4TER1N0M3T0x0R3RydHNQdG9xWFJwVHVuWUh0ODk3V1gwc3NLeTEzdWo5bDR0WDFaZXM0K3dUN2h2cE1Lbm9uTy81djVkK3o5VXhsZmVxWEt1YXExV3F0NVJQWGVBZldEd29PUEJsaHJsbXFLYTk0ZTRoKzdXZXRTMjEyblhsUi9HSE00NC9MUSt0TDczYThiWGpRMEtEVVVOSDQvd2pvd2NEVHphMDJqVjJOaWsxRlRTRERjTG02ZU9SUjY3K1kzck41MHRoaTIxcmJUV291UGd1UEQ0czIranZ4MDY0WDJpK3lUalpNdDNXdDlWdDFIYUN0dWg5dXoybVk3NGpwSE84TTZCVXl0T2RYZlpkclY5Yi9UOWtkTnFwNnZPeUo0cE9VczRtMzkyNFZ6T3VkbnpxZWVuTDhSZEdPdU82bjV3Y2RYRjJ6MEJQZjJYdkM5ZHVleCsrV0t2VSsrNUszWlhUbCsxdVhycUd1TmF4M1hMNisxOUZuMXRQMWo4ME5adjJkOSt3K3BHNTAzcm0xMER5d2ZPRGpvTVhyamxldXZ5YmEvYjErK3N2RE13RkRKMGR6aHllT1F1Kys3a3ZhUjdMKzluM0o5L3NPa2grbUhoSTZsSDVZK1ZIdGY5cVBkajY0amx5SmxSMTlHK0owRlBIb3l4eHA3L2xQN1RoL0g4cCtTbjVST3FFNDJUWnBPbnA5eW5iajViL1d6OGVlcnorZW1DbjZWL3JuNmgrK0s3WHh4LzZadFpOVFAra3Y5eTRkZmlWL0t2anJ4ZTlycDcxbi8yOFp2a04vTnpoVy9sM3g1OXgzalgrejdzL2NSODVnZnNoNHFQZWgrN1BubC9lcmlRdkxEd0cvZUU4L3MzQkNrZUFBQUFDWEJJV1hNQUFBN0VBQUFPeEFHVkt3NGJBQUFBSVhSRldIUkRjbVZoZEdsdmJpQlVhVzFsQURJd01UZzZNRFU2TWpnZ01UWTZOREk2TVRUOWh3cmZBQUFJSFVsRVFWUllSNTFYQzFCVTV4WCtkbGxnUWQ0UFVSQWZpU2hhTkcxaTdCaHRtMDVLVWtuVFdCK05RYTBZRzJPRGxqb09HazFpTzUxcU5HUWNrOW9rUkpzMDRJdzZwdU4wVEV4VGFPc1lTN1NTcGhwZjFLQVZCUlpoV1I0cklMdDdiNy96Mzd2c1FoYUMvUzcvc3Z6M3ZNLzV6L214NkFTR0NaMlAvRmdzOHBmNjZJTmZqTVY0T1d4WXpkL0RnK1pYWUVIbEo1L2p2Z1diOE9qcUhXaHNjYW45TzFVdUdGNEVoTVFVM3RyaFJ0N3FsM0dxc2hwSWlBRjhQcURyTnBZVjVPSDFGMWNnSmpvcUtGTENJK0lITjJ4NEVUQ1YvM3piSDVBOGNSRk9WVjhDUmljRFVaRkFOSmZWaXZJREZhajY5eGVLVGlra2o2YlJGSDF3NVlKQkl0RGY2ajlWbnNhOFozYlFXeThRUzYrdDVqdDN0NHJBMXMwRjJMenFjV09QNkwxYXA0eUtHRGZHM0NFR0M0UVlFQXlOangrMTE1djBLWSt1MTVHV3B5TW5YOGMwV1V0MVpEK2hJK2xoZldIUlR0M3I5Wm5VQmhwWGJkVFBJVncvanhHNlk4MFdjNWR5ZlFHNXdSaTBCdktMZDJOLzJRZk1jeXhnWjVnRmt1K1dkb3ljT0FaViszK051elBUakgzQ3Rmc2RPTllXMDFFZndwREFIWTFQQi8rMklXTmZLZUtYekRjSUI4Q2lNVkhCMWZ2Mkg0OWhaV0VKTU1JT3hJemdEdTNUV1A0ZFhUVEVodkpYaXJEMHNUa0dNZEZUZlFaMTMxNEFYM2NqRmJNdStDbFFoYWhpN3VYVGdzamtpUmh6N0JEc09kbnFEVmdmRnFheUx3SmZYRy9DN0NXL3dzM0x6RjlLb2xHZThxYW5WeWxmdTNZaFhudStRRWdWdk0ydGFKajNGRHFyanRMSFZPN1kxTDVFd0lkMnFyWlFSTHo2TlBZOTNHOUdiTzRpWkI0dEozbVlNcS9QQU11NEg5SERDSzV3UTdHUFhqZTFZc2FEOTZMaW5SZVlpV2doVTNDc2ZnN08wdGZvYXd5RlJDdEJ1Z3E1QzJIV1JHUldIWWJ1OVRFeTg2RnI3YVJMNG5zeGlXSnBuQzBwQTFuT2MwcVdNcSsreWNXejNBTkVtc3A3YnNNV2JzWEhIKzNDNmZlMjlTbHZlL2NRTGxqaTRDcDlpLzZta0ZtVWk4OXVyamFNM0xvZGszeDFpUHJtZllpZVBSUFp2aHNZdWIyRUtXZ210NGVVT25saTRXbXRnK1ptU2drVkFZZXpEYU56bGdKcFNUeERYcVNQVGtMOVgzY3JBa0gzeWM5dzQ0Y3I0R211VWVFV01ZWTMzYXJRRW45Y2dQU0RieGpFUkFlRmg5bXNMQ1BXa1luYWpCbndOVFNSTDR3R3RXTnlWeU9zVVhZelFTSk9NcUdXeHY3Q1ZKaTRObXNlcnN5YUJhMzVKcFZMMVF1TEY3MW9nSDNhMXpDcHJyYWY4cEszanlCK2FqNWk2TkRyYkU1KzJNYW0wMWl2aW9KUm5MTE1GQ2lvUFdQVExBc0Y5MGtwc2xIOEprZFJ3dTFVUWliOHBRSVR6djRONFpucGl1NUU5VVZFNU9Sanc1YTlRQnhURmhHT3drMEJ3K1FJRzlMN0kyQ0E2QXhTN0VjWTdHU1VFcElpNjBicTloM0kxdXN4SXZjNzZ2MzFteTVNbTdjQjMzcWtDQjVoVDQ0akU0OGlqNWhORFBrS0JBd1lCTW91dFhncTZGWEt4bWZWdnFCOWNTSEczck1NNXk1ZUF6S1luckJRUGdid1pmY0dTY0ZBeUFGU2o4VWdiMzExRHk1YVl1QStlQWpXOUJUajlJaUJicDZrTHM0SHZ5WnBZRUVZT2dYc1RBTVpCTUlrM2l1WjFraGN1ZXNCTlA1aUhWT1R5SG5Ed1NSR2Q3TlpPVndvTGx5QWpUOWJRQ040eENncU10eG9UbjVJN1JoRkdFREFBRTR2dFFaQVRMTEtZMkhuNnZiQXcwa25QVUIyZGEwWFdrTUw3djE2RnRwcTM4UEw2L1BaaUdpUU1QR1hQVndpRTRDU3d5Y1lRUkVnVjRnaU5Eb2NQM2s4alc0bXZWNVRwOEVkbDRES0QzYmkwME5iRVc4MksxY252VGZIZGJBMCtTNlM1QWxHL3dpRXFBR2JtbXlHYWprTkdqcFYxMHY3N1c1TWFqK0hoNzZScGVqYWVUZVl0ZmdGdlBIN0k3eWtSQ21lWUlqa3I0NUFpQnFRcnFXaGgrSjYyRXdia0xCeUphYnFIVWhhRXhoTVQvOXlEeExHUFk2VC82cGhEK0FFRlcyc3FjNWJScnNWREIwQkNYMVFEZGc0cWZ6SWRyRzNUNzhIRVZPbVlISnpFMGJ0NWFnMjhkYkJTbGdtek1mZXNnK0JkRTVFdVRkSUZDVU5uQ2NseGN0TVNtNVR0aEhGL2xGV0dsWHFtV1AxaFUzazhqVUgvbnppakx4Q1dFSWl4cDloMTd2d2Q5aFNPQ3VJMDU5ZlFjb0RxL0RNdWwyOE16RGNmcTl2OHpUY2FNYVNSZCtGZnZVd2lwYm5LWHFCdDFFR0VndDNRR3FVQVpHUjlGakdyNEFGcERNVmN4YytoeWsvS0VhZHcybnNFMjI4Rjh4Yy9DSm1QbFFJWjF1SGVXK2dDQzk1RzF1Uk0zazg2aS90eDc0ZGEwd084cnhaemdrYUQyL2ROZG9ZcmlLZ003SFFlTHNpK201RXVTdCt3NHIrQjVCcUNwVktGbythMi9EVForY2psUzMycGEzdkFvbEJWelNwbVhZMzUzc2NqdjV1QTNMblREZjJpYTRUcDFEL3lGSjR1aHBZeU1sVWFreFFMMGUzTFQ0Rms5cDRzeVpNQTlSWGxCMDVnZVViT0lhbG95V2FUVVp3aTkxTkdsV01qRmR6VC9KTWJOdThISnVlRHR5SXZjMU8zSmk3RExjK3JlQ0JUU08xVFhHSTF4N2NST3lNN3lIejQ4T3cwQW5aVndZSVkvQzlzTGhrSDE1NXFZeURoVWN3aXFOWnZlT1NPdW4xc09zNThjUlRqK0hBemlLRHdVVGpUOWJCVlY1S3hYR2t0bE9wOFBtb3VoVVI5alJrVkI3Z1JlVitnMWpxVGVUS2hTUVV2SnBQbi8za0ZsN0o1eHJYOEtsUHF1OVozMStuTzFyYVRDb0R6bGYzOENwdTUxVThVYTlCSnRkWS9STFhCZjU5SHJHNnM3VE1wSlJyZi85ci9KY01rSWp3cHcvVjUydjExRG1yZFF2L0wzai8rR2Ztcm9IT2l1UDZmMkt6cUNSYUthekJlSzV4K2tXa2NTOUtieWhZYjFJS1JLNnhnakhvL3dWRHdjT3JWYjNrK2V4eGhqdUZnWmFoSTJJa3owMkl1VDhYWTk3ZkI5dElLVDZWdkVGaGRKNGhJU0lDTmphdGZSNDFHYVBRZmZZczFZN3VVNjR4ejlZSU8rNnErZ1RqLy9taG9WeDhDN0NHaGtUZ1RuRDc4bi8xcTlNZlpzNGpHZXBVaGpxZXVVN1NuYnYybWhSM2hqc3lRR05oK2pQby91aVlYcGVYcnp1S3RnVDlOeG42LzcraDhIL1ZRQ2lJa0tGeUhSckEvd0M0ZStPK1oxY240UUFBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA5LTAyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJHb1RydXN0IElkZW0gQ2FyZCBVMkYxMTAwMjAxNzA0MDMwMDEiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDE3MDQwMzAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yLjUiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMy4wIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wOS0wMiJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjA5NmJmYzhiZGJhYWE3NDBiOWVkOGY3NGIwNTRiNWU4YTgxODQxZDIiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMDk2YmZjOGJkYmFhYTc0MGI5ZWQ4Zjc0YjA1NGI1ZThhODE4NDFkMiJdLCJkZXNjcmlwdGlvbiI6IlRydXN0S2V5IFQxMjAgVTJGIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoyNTYsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDcFRDQ0FrcWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakNCcnpFTE1Ba0dBMVVFQmhNQ1MxSXhFVEFQQmdOVkJBZ01DRk5sYjNWc0xWTnBNUk13RVFZRFZRUUhEQXBIWVc1bmJtRnRMVWQxTVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUWlZkQ1RTQkRRU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdIaGNOTVRnd056QXlNRFV6TVRNNVdoY05Nak13TnpBeE1EVXpNVE01V2pDQnJ6RUxNQWtHQTFVRUJoTUNTMUl4RVRBUEJnTlZCQWdNQ0ZObGIzVnNMVk5wTVJNd0VRWURWUVFIREFwSFlXNW5ibUZ0TFVkMU1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFpWZENUU0JEUVNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFJZnFIaXNpMG9PL2V5T3FTYURycjlpdEcySXltQmtIblNER1FJSVltVCt2cUE4QWdPODFtb21jMkxkNVBHcEVONm11RTU0d1BIUWp2Yy95Q2loOHUybzFVd1V6QVNCZ05WSFJNQkFmOEVDREFHQVFIL0FnRUFNQjBHQTFVZERnUVdCQlMzSi9meGlBdjIyaXJkQnM5OFNPRGhGN2tVL2pBTEJnTlZIUThFQkFNQ0FRWXdFUVlKWUlaSUFZYjRRZ0VCQkFRREFnQUhNQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUURjNDFMRks0TEpDQlUyVlZLSXo3WjZzeFBoVUVraDhuTFNMSzZJWGRrUDV3SWhBSWVLVk9aY2hhVk81YUY3ZmJkWG9TcmN5eTFZWWVVZVBMb2pjS0k5Zlg4NCIsIk1JSUNnakNDQWlpZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQ0JuVEVMTUFrR0ExVUVCaE1DUzFJeERqQU1CZ05WQkFnTUJWTmxiM1ZzTVJBd0RnWURWUVFIREFkSFlXNW5ibUZ0TVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVaTUJjR0ExVUVDd3dRUTJWeWRHbG1hV05oZEdVZ1ZXNXBkREVaTUJjR0ExVUVBd3dRWlZkQ1RTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd0lCY05Nak13TnpFeE1ETTBOakUwV2hnUE1qQTNNekEyTWpnd016UTJNVFJhTUlHZE1Rc3dDUVlEVlFRR0V3SkxVakVPTUF3R0ExVUVDQXdGVTJWdmRXd3hFREFPQmdOVkJBY01CMGRoYm1kdVlXMHhGekFWQmdOVkJBb01EbVZYUWswZ1EyOHVMQ0JNZEdRdU1Sa3dGd1lEVlFRTERCQkRaWEowYVdacFkyRjBaU0JWYm1sME1Sa3dGd1lEVlFRRERCQmxWMEpOSUVObGNuUnBabWxqWVhSbE1SMHdHd1lKS29aSWh2Y05BUWtCRmc1cGJtWnZRR1V0ZDJKdExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQWgrb2VLeUxTZzc5N0k2cEpvT3V2MkswYllqS1lHUWVkSU1aQWdoaVpQNitvRHdDQTd6V2FpWnpZdDNrOGFrUTNxYTRUbmpBOGRDTzl6L0lLS0h5N2FqVlRCVE1CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdIUVlEVlIwT0JCWUVGTGNuOS9HSUMvYmFLdDBHejN4STRPRVh1UlQrTUFzR0ExVWREd1FFQXdJQkJqQVJCZ2xnaGtnQmh2aENBUUVFQkFNQ0FBY3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTlZuSmRlLy90QkxxOE1ERGkrU0FkNlVkWUlaU25nNFBNcW15TnJ2Wmo2NEFpQVgweFN6QWhGYUNDcC91aHBWZ25sRitYQmdyd0FJc290WkdUQjZya0IzMUE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUErZ0FBQUV4Q0FZQUFBRHZEWWdxQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUVuUUFBQkowQWQ1bUgzZ0FBRmljU1VSQlZIaGU3ZDBIZUJYRjJzRHhONzNRQ1RWQTZGSUZGS2tDVXV5QUV1bUtZa0ZVYklDQ0lpS0NVZ1FFN0wwZ2RsUXNLQ3BTcklnZ1NDK2hKblJDSjRIMGIyZnZlRC8wa2hDU25jMmVrLy92dVhtWWQ0NlhrSk56OXN5N00vTk9RSlpGQUFBQUFBQkFnUXJVZndJQUFBQUFnQUpFZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVFQkFsa1czUFNzek5WWFNEeVRLcWExYjVkU2FkWks2ZTQra0h6OW05NG4zLy9tQWNRRWhvUkpjdXBRRVIwVkpXSlZLRXQ2Z3ZvUlhyeVpCcFVwSlFDRDM0UUFBQUFCZjROa0VQU3NqUTA1dDNpS0hQdnBFanYrd1FOTDM3Wk9zMURUOUtJQ3pDWXlNbE5BYTFhVEVOWjJsWkpmT0VscWh2UFdPRDlDUEFnQUFBUEFhenlYb0tqRS9NdmM3U1h4emhweGFzVkwzQXNpUGdOQVFLZHF4dlpTOVk0QVVhZEpZOXdJQUFBRHdFazhsNk1kLysxMzJqSHRLVXRhdDF6MEFuRmE4NjlWU1lkZ1FDYXRTUmZjQUFBQUE4QUpQSk9nWkowN0lub2xUNVBBSEg0dGtadXBlQUtZRWhJZExoVkVqSktwWGR3a0lEdGE5QUFBQUFBcFNnU2ZvcDdac2xSMERCMG5xMXUyNkI0QXJBZ0trMkJXWFNwWEpFeVNvYUZIZENRQUFBS0NnRkdpQ2Z1TFA1UkkvWUpCa0hEbWlld0M0TGJ4UlE2bjI1aXNTRWhXbGV3QUFBQUFVaEFKTDBFOHNYU1k3YnJsRE1wT1NkQStBZ2hKYXE0YlUvT2hkQ1M1ZFd2Y0FBQUFBY0Z1QkhKQ3NsclhIMzNrdnlUbmdFYW1idDhyMmdZTWtnL2NrQUFBQVVHQmNUOURUang2VDdiZmRJUm1IRHVzZUFGNXc4cysvWk9jamowa1doUm9CQUFDQUF1SHFFbmQxeG5uOEF3L0pzUy9tNko1ekZ4Z1pJVUdsU2tsSWplb1NWS0s0N2dVS09ldHRuTDV2djZUdGlKZU1JMGNsS3kxTlAzRHVLazRZSzJYNjlOSVJBQUFBQUxlNG1xQWZYYmpJTGdwM3prZXBCUVpLK1BrTkpLcC9QeW5XdXFVRWx5a2pBVUZCK2tFQWY4dE1UWlhVWGJ2azZMZno1TkRNOXlWOXoxNzlTTzRGbGl3aDUvM3dEVVhqQUFBQUFKZTVscUJuSkNWTDNGWFhTRnJDVHQyVE82RTFxMHZGVVNPa2VOczJkcUlPSUhjeVQ1NlVneDk4TFB1ZmVWNHlqeDNYdmJsVG9sdFhpWms2eWJwQ0JPZ2VBQUFBQUthNWx2RWVtZlAxdVNYblZtSlFvbWVzMUo0elc0cGYwbzdrSERoSGdSRVJVdmJXL2xMTGVnK3BvOVRPeGJGdnY1ZFQ4UWs2QWdBQUFPQUdWN0pldGV4Mi8vTXY2U2dYckdROGF0QkFpWGxxdkFTR2grdE9BSGtSVnFXeWZZUmE1TVV0ZGMvWlpaMUtrZjNQdnFBakFBQUFBRzV3SlVFL3NYaUpwTy9hbzZPekNBaVEwamYzaytpaDk3TzhGbkNJdXRGVjdkVVh6MmttL2NTQ1JaSis1S2lPQUFBQUFKam15aDUwVmJuOTZHZGY2Q2huS29HbytmSDdFaGdXcW52eXlmcnhzdExUSmYzRUNjazRmbHl5VXZOZTNScHdpenF0SUxoWU1YdVp1bDBRMGFHYlZhZTI3NUROVjE0aldTa3B1aWRubFo2WklxV3Y2YUlqQUFBQUFDWVpUOUJWY3J5dWVSdkpQSHhFOStRZ09GaXF6M3BQaWpacHJEdnlMbm5kZWprMmY2RWsvYnBZVXJac2xZekVnL29Sd0hjRXgxU1JpTnExcEdpSGRsS3NZM3NKcTFoUlA1SjMrMTU2VmZaUG1xcWpuQlc5cktOVWYvVkZIUUVBQUFBd3lYaUNucnhtcld6cDJsMUhPU3ZhOFJLcC92ckxlWjR0ekR5VklrZSsvVTRTWDN0VFV0WnQwTDJBbndnTWxLS2Qya3VaVy90THNSYk44L3crU1Q5NlZEWjF2Rkl5RGgzV1Bka0xLbDVjNnY3eHN3U0doZWtlQUFBQUFLWVkzNE9lL05kSzNUcTcwbjE2NVMzcHlNcVM0NHQvbDdqTzNXVFhrT0VrNS9CUG1abHlZdDRDMlg3RExiSnQ0Q0JKeVdPVjllQVNKYVRFdFYxMWxETjFWRnZxemwwNkFnQUFBR0NTOFFUOTVQcmNKY3NCa1JGUzdKSzJPc285VlNGKzk4VEpzdU9tQVpLNmRadnVCZnlZU3RSL1dDaWJ1MTRuaCtkOFk4Zm5xa1NYcTNRcloxbHBhWkxDK3dvQUFBQndoZGtFUFN0TDByWnUxMEhPd2h2VWw4RFFjeXNNcDRxK2JiL2pIam40NnB2MlhuZWdNTWs4ZGx4MkRoNG1lNlkrWTcvWHprVkV6Um9TV0xTb2puS1dzaWVYSnpBQUFBQUF5QmVqQ2JyYTNwNlJuS3lqbkttem1zK0ZTczYzM1RwUWtoYjlwSHVBUWlnalF4SmZlTVZlUlhJdVNYcEFSSVFFbDQzU1VjN1NkNU9nQXdBQUFHNHdPNE9lbVNtWnVUek9LYWhDZWQwNk83WHNObjdZQ0RtNWJJWHVBUW8zdFlya3dGc3pkSFIyNnVpMmdORGNGWDdMMkxkZnR3QUFBQUNZWkh3UHVnbjdYM3RUVG56M2c0NEFLUHNtVFpPa0ZYL3BDQUFBQUlDdk1Yck1tdG9YdnFsTHJLUnVqTk05MllzYU5GQ2lodzNWVWZaT2JvcVRMVjJ1czJmUmN5MHcwTjV2RzF3bVNnS2pTdWxPd0tPc2QyVEd6bDJTY2VLRVpKNUkwcDI1RTFxcmh0VCs4bE1KaklqUVBXZVdsWkVoY1oxakpXWGpKdDJUdlpMZHVrcVZhWk4xQkFBQUFNQVUzMHJRclgvcXR0dnVrQk1MYzdudjNENDN1b09VSFhDemhOZXJLOEhGaXVrSEFJL0x6SlMwdzRmbHhPOS95SUhuWDdJU2FlczlsSnUzYWtDQWxCOHhUTXJkZnF2dU9ETVNkQUFBQU1CN2ZHcUplOUtxMWJsT3prTmlxa2oxajJaSzlWZGZrS0xObTVHY3c3Y0VCa3BJVkpTVTZueVYxSjR6V3lvK09Wb0N3c1AxZ3ptd2t2akVsMStUaktSem0za0hBQUFBVVBCOEowRzNFbzhEcjc2aGc1eUZuOTlBYXM3K1NJcGUxRlQzQUw1TEZYUXJjMzBmKzRaVFVNa1N1amQ3R1ljT3l4RjFQam9BQUFBQW4rSXpDWHI2a2FPUzlNdHZPc3BlY01YeVV1MzFseVdrZEduZEEvaUhJbzNPbDhyUFRiVmU1RUc2SjN0SFB2dEN0d0FBQUFENENwOUowSk5XcnBMTVk4ZDFsSTNBUUtrNGRyU0VsQ3VyT3dEL1Vyek54VkxxaGo0NnlsN3lueXNrNC9nSkhRRUFBQUR3QmI2VG9QLzJ1MjVsTDd4ZUhTblI0UklkQWY2cDdJQmJKU0E0V0VmWnlNaVFwSlVyZFFBQUFBREFGL2hNZ3A2OGJwMXVaYTlFbDZ2dC9icUFQd3VyWEVraVdqWFhVZlpPclY2cld3QUFBQUI4Z1U4azZGa1ptWksyYWJPT3NsZnNzazY2QmZpM1ltM2I2RmIyVXZmdjF5MEFBQUFBdnNCSEV2UjBPMGsvbTdBS0ZYUUw4RytoMWF2cFZ2WXlUM0RVR2dBQUFPQkxmR2FKZTY0RTZEOEJmOGRySFFBQUFQQTcvcFdnQXdBQUFBRGdvMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBDTWl5NkxianN0TFRaVk9YV0VuZEdLZDdzaGMxYUtCRUR4dXFvMy9LVEUyVkRhM2FTOGFoUTdybnpCcXNYUzZCa1pFNk1pYzFQa0ZPcmQrZ0kvaXowSmdZQ2E5WFIwZmVjV1QrQWtrWU1FaEhaMWFpUjZ6RVRKNmdvMy9LeXNpUXVNNnhrckp4ays3SlhzbHVYYVhLdE1rNkFnQUFBR0FLQ1hvZUhKejV2dXgrYkt5TzRNK2krdmVUNk1jZjFaRjNrS0FEQUFBQS9vY2w3Z0FBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQndSa1dYVGJjVm5wNmJLcFM2eWtib3pUUGRtTEdqUlFvb2NOMWRFL1phYW15b1pXN1NYajBDSGRjMllOMWk2WHdNaElIWmx6Y3ZVYU9mN2p6enJ5dnVRL1Y4anhSVC9weUZubEI5OHJFdVMvOTNraUdwMHZ4ZHExMFpGM0hKbS9RQklHRE5MUm1aWG9FU3N4a3lmbzZKK3lNaklrcm5Pc3BHemNwSHV5VjdKYlY2a3liYktPQUFBQUFKaENnbDRJSkw0NVEvWThjZVpFTGI4YXhxMlJnT0JnSGNFdC9weWdaNldsU1ZhbXNjdFM0Uk1nRWhnU1l2MXBOUUFBLzBPTk04V0ZqNTJBNENBSkNBclNVY0Z6OWZPV3p5SWcxMGpRQ3dFU2RQL2p6d242dHFIRDVOU0tsVHBDZmdXVktDNjFQbjVmQWtORGRROEE0SFJ4M2Z0SStsbkdtRTRvUC93QktYM1ZGVG9xV0JsSlNiTGx4bHNrNC9BUjNXTldaSXRtRWpQK0NRa0laSGN0Y0RZazZJVUFDYnIvOGVjRVBhN2Z6WEp5OFJJZEliOUNhMVNYdXZPKzBSRUE0Ti9XdFd3bjZRY082TWljNkVuanBVejNXQjBWb014TTJUNTBtQno3eXAzUGh1QUs1YVgyN0k4bHBGdzUzUU1nSjl6R0FnQS9GbGFycG00QkFDQ1MrTkVzMTVMemdMQXdxVEoxRXNrNWNBNUkwQUhBajRXV0w2OWJBSURDTG5uZGV0a3o3aWtkbVZkdXlMMVNyRVZ6SFFISURSSjBBUEJqWVkwYTZoWUFvRERMT0g1YzRnYy9LRmtuVCtvZXM0cGRjWm1VdSswV0hRSElMUkowQVBCajRUVnI2QllBb05ES3lwTGRrNTZXMUMxYmRZZFpJWldpcGNyNHNSU0ZBL0tBZHcwQStLdWdJQW1yVUVFSEFJREM2dkEzMzhyaER6N1drVm1Ca1JFUzg4SXpFbHl5cE80QmNDNUkwQUhBVHdXVktpV0J4WXJxQ0FCUUdLWEV4OHV1a2FQdFdYVGpnb0trd3FoSHBNajViSzhDOG9vRUhRRDhWRkRSSWhJWUZxWWpBREFyTXpOVFRwNDhLWWNPSFpLdDI3YkowcVZMSlRVMVZUK0tncEI1S2tWMkRINVFNbzhmMXoxbXFhTlp5L1RzcmlNQWVVR0NEZ0IrS3FSeUpRa0lDdElSQU9TTlNyelQwdElrT1RsWkVoTVRaZlBtemJKNDhXSjU3LzMzWmR6NDhUSjR5QkM1TmpaV2F0ZXRLK2ZWcXlkMXJLOTZEUnBJNjdadDViaExpU0hPUU8wN2YycXluRnE1V25lWUZkNm9vVlFlTzFva0lFRDNBTWdMRW5RQThGT2hWV04wQ3dCeXBoTHdBd2NPeU5xMWEyWDI3Tm55NGtzdnlXT2pSMHUvbTI2U2k5dTFrNmJObXRsSmQ2V1lHS25Yc0tHMDY5QkJicjcxVm5sODdGaDV3ZnB2djVrN1YrTGo0Mlh2M3IxeTVPaFJPNmxId1RxNjZDYzUvUDVIT2pJcnNHaFJpWmsrUlFMRHczVVBnTHdpUVFjQVB4VktnVGdBT1RoMjdKaGNldm5sVXJkK2ZZa3NWa3lpcTFTUkprMmJTcSsrZmVYK0lVTmt3bE5QeVVjZmZ5ekxsaTJUOVJzMnlPNDllMGk4ZlVUcTdqMnljL2dJeVVwUDF6MEdCUVJJOUpPUFMzalZxcm9EUUg2UW9BT0Fud3Evb0pGdUFjRC9VdnZERi8vK3Uyelo2czdSVzNCSHB2VjdqWC9vRWNrNGRGajNHR1FsNTFFRGJwYlNYVHZyRGdENVJZSU9BSDRxdkVvVjNRSUFGQmI3WDMxZGtuLzdYVWRtUlY3VVZDb09IYXdqQUU0Z1FRY0FQeFFRRVNFaFpjcnFDQUJRR0J4ZnNsVDJQL2VTanN3S3JsaEJxajQzVlFKRFEzVVBBQ2VRb0FPQUh3b3VYMDRDUW9KMUJBRHdkK2xIamtqQ3NJZXNodmw5NXdHaElWSjU4Z1FKS2N1TllNQnBKT2dBNElkQ1NwYVVnRUF1OFFCUUdLaGljUEhESDVIMFhYdDBqMWxsN3JwRGlyZHFxU01BVG1MMEJnQitLS1JHTmM2aUJZQkM0c0RiNzhpSitRdDFaRmJSOXUyazRyMkRkQVRBYVNUb0FEd2xwRnhaQ2ExUzJiV3ZrSW9WM1Vsa3JlOFJVaW42alA4R0UxOFI5ZXZyYnd3QThHZEpLMWZKdnFuUDZNaXNFT3Z6SldiS1JHNEFBd1lGWkZsMDIzRnF1YzJtTHJHU3VqRk85MlF2YXRCQWlSNDJWRWYvcEk2TDJOQ3F2V1FjT3FSN3pxekIydVVTR0JtcEkvd3Q4YzBac3VlSkNUcHlWc080TlJJUXpENVh0eDJadjBBU0J1Ujg5N3BFajFpSm1Yem0zM3RXUm9iRWRZNlZsSTJiZEUvMlNuYnJLbFdtVGRhUi96a1ZIeTl4bDNVMmZsWnNZSkVpVW1mQmR4SlNKa3IzQUVEQlNreE1sS28xYXRqSHJabXlkOWN1aVlyeTluVnZYY3Qya243Z2dJN01pWjQwWHNwMGo5V1JNOUtQSFpPNGJqMGxiVWU4N2pFbk1DSkNxbi93amhRNXY2SHVBV0FDTStnQUFBQ0FEOXIxeEhoWGtuTUpESlR5ano1RWNnNjRnQVFkQUFBQThERUhQNTB0UnovN1FrZG1sZWphV2NyMDZxa2pBQ2FSb0FNQUFBQSs1R1RjWnRrelpweU96QXFyYzU1VUdUZUdrMEVBbC9CT2cwOVI5UWkyOXJ0WjFsM1F3dmhYM0xVOUpPTkVrdjdPQUFBQUJTL2p4QW1Kdi84QnlVd3lQMFlKTEZaTVlwNmZadTgvQitBT0VuVDRqcXdzMlRmOWVVbjY5WGZKT0hMVTZGZG04a21wT0hxa0JCVXRvcjg1QUtDd3lNek1sUFQwOUROK1pXUmtXQjlIeHVyckFqbktzbDZidXlkTXlsV1IxM3dMQ3BUb01hTWtva1lOM1ZGNHFmZDhUdGNGOVJqZ0ZLcTRGd0wrVXNYOTJNKy95STViN3hUclNxaDd6Q2w3LzkxU1lmQzlPdkllcXJnN2h5cnV2aThsSlVYV3JsMHJmNjFjS2Z2Mzc1Y0RpWW42RVpHdzBGQXBXYktrbEMxYlZtclhyaTMxNnRiMWZFVnB1Q2NwS1VtMmJ0MHFxMWF2bGoxNzlzaTI3ZHRsNDhhTmN1clVLVGw1OHVRWkI5MFJFUkVTRWhJaXBVcVZrZ2IxNjB1bFNwV2thdFdxZHJ0eTVjb1M3RU1ubTFERi9UOThxWXI3a2UrK2wvaDdocWk3U0xySG5OTDkrMG5sVVk4VXVpUFYwdExTSk40YUd5eGZzVUlTRWhJa0xpNU9ObGxmNnJxUW5KeXMvNnYvcDk3ellXRmhVcng0Y1duWW9JRjlIYWhXclpvMGJ0VEl2ajc0MGpVQjNrQ0NYZ2o0UTRLZXVudVBiTFplU3htSGorZ2VjeUpidDVRYU05LzA5RjRyRW5UbmtLRDdwcU5IajhyY2I3K1ZEejc4VUg3ODZTYzcwY3F0T3VlZEo0OC85cGowNk5GRDk2QXdVTW4ydG0zYlpQSHZ2OHVpSDMrVXYvNzZTMWF1V3FVZmRVWjRlTGcwYjlaTUxyamdBbW5Wc3FXMGJOSENIcUI3RlFuNmYvaEtncDZTc0ZQaXJ1a3VtY2VPNlI1eklpNXNJalZudmkyQjRXRzZ4MytwMTcrNndmdkxMNy9JL0FVTDVQY2xTK1NZUTg5eHBKV1h0RzNUUnRwZmNvbTBzSzRIelM2NnlMNU9BRGtoUVM4RWZEMUJ6MHhKa2EzWDk1ZVR5Ly9TUGVZRWxTMGp0YitlTFNGbHkrb2VieUpCZHc0SmV1NzhiaVUxNjlhdjE1RXpMcklHS28zT1AxOUh1WFBBR2tTLy9PcXJNdVhwcDg4NGs1RmJzejc2U0xwZGU2Mk96dDJzVHo2UjQ4ZVA2OGg1VjE1eGhVUkhSK3ZJR1o5OTlwa2NPWHBVUjg2N3hCcUExdlRZVWxpMUhIM1RwazN5MmV6WjhzbW5uOHI2RFJ2c1ByY0VCUVhaTjRSNjlld3BWMTE1cFRSbzBNQ2VhVE5wMWFwVnN1elBQM1dVc3hNblRzaERJMGJZUzNSTmVYcnlaQ2xhdEtpTzhxNTgrZkxTK2VxcmRlUXNYMGpRczlMU1pITy9tK1hrc3VXNng1emdjbVdsMXV4WkVscWh2Tzd4UCtvMXIyN1FmV2g5RnJ6NzNudHk4T0JCNDF0WEFnSUNwRml4WXRLamUzZnBkLzMxMHJ4NWMrUFhnek5STnlzLy8rSUxPWExFN0tSWDZkS2w4L1U1bTFmcTUzdG41c3d6cm9CeWlyckowcnRYTC9zYWJ3SUplaUhnMHdtNjlmTGM4OHp6a3Zqc0MxWmI5eGtTWUYwa3E3NzltaFJyMlZ6M2VCY0p1bk5JMEhQbi9pRkQ1TVdYWHRLUk0rNjc1eDU1ZXNvVUhlVk1EYVptelpvbFF4OThVQkt0Z1ZSK3FPV0dmLzd4aDlTdlgxLzNuQnYxc2Rtb1NSUFpzSEdqN25IZXQ5OThJNTA2ZHRTUk01bzJhMll2NVRibG5iZmZscjU5K3Vpb1lLa1ZGZDkvLzcxTXNsNWZhaEN1bHF3V05EV1FVMHRmQjl4NnEvMDh4Y1RFMkFOMnAwMmROczFPdXYyTlNtbytzQklwRXp5Zm9GdlhuRjBUSnN2Qk45N1NIZWFvTVYzVjExK1M0bTNiNkI3L29tN3Nmajl2bmp3MWFaS3MrT3N2VjIvWW5VNjk5NnRYcXlhRDc3L2ZUdlJVTXV1bTJ3Y09sTGZmZVVkSFpxaWJFYnNURWx4Zk1hQzJMZFUvLzN5anY5c083ZHZMZDNQbkdybUdLeFNKZzZjZCsyMnhISHpoRmVQSnVmVU9rektEQnZwRWNnNzRpNFNkTzNVclo0Y1BINWJyYjdoQmJyN3R0bnduNTRxYXpWT0pFdnlQV3FyNjN2dnYyemNqZXZYdGE4OGtleUU1VjlSZ2NjZU9IVEpxOUdqN0JzKzFzYkd5ZE5teUFrc1FmRTNyVnExMHEvQlJOWGdPempDYlRQMnR6RjIzKzJWeXJtN3lmdm5sbDlLa2FWUHAyYnUzZlcwb3lQZWV1dEc3ZGRzMnVXL3dZS25Yc0tFOFBYVnF2bGFGbmF0ZXZYcnBsamxxbFptcUQrTzJKVXVXR1AvZDlyRmVRNmFTYzRVRUhaNlZkaUJSZGozd3NQR1pUU1d5V1ZNcGY5ZEFIUUZ3d3hycmcvdHNpN2pVbnVHMjdkdkw3QysrY0d5NVdwa3laZXc3Ky9BZjZuWDA4ODgvUzV0MjdlVG1XMitWTFZ1MzZrZThLZm5rU2J1R2d2cjNYbkhWVmZZV0V1U3NSaUd0Sko2NmI3OGtESC9FeWpETko1TkYybDRzRmU2OVcwZitRMjNQdXJwTEYrbHVKYVhxTThWckRoMDZKQTgvOG9oOVkvR0xMNzg4NitlaUV5NnhyajJxMEtWcGM3LzdUcmZjTTMvaFF0MHlRNjBJdUM0MmY4VWV6NFlFSFo2azlsb2xQUGlRcEZzZlRLYXB2Vll4ejArWGdKQVEzUVBBRGNlT0hyVXJaV2RIVmM3dGVPbWxkbFZ0SjExNHdRVkc3M3pEWFdvZjlkQUhIcERMcnJ6U1hyTHFTOVJOSjFYa1VOMkU2dDZ6cDJ6YzVNTFJXVDVJN2ROVlZmSUxHN1hGTStIaFJ5VGp3UCtmVEdGS2NNVUtFak41b2dRWTJsTmJFTlNLbXNsUFB5MHRXcldTaFlzVzZWN3YycnhsaXoyNzMrK21tK3g2S3lhRmhvWktkOE5KcHJKNDhXTGRjb2U2cHFvaW9DYXBteHZxZEJpVFNORGhQVmxac3UrbFZ5WHBwMTkxaHprcUthODBhWnlFbEMyamV3QzQ1ZGp4NC9ieTlUUFp2WHUzWEc0bFhEdDM3ZEk5emltTUEzMS9wV2JEMm5mc0tNKy8rS0xQTHhYLzhxdXY1S0xteldYc0UwL1lOeDN3LzBLQ2c2VkNoUW82S2p6MnYvRzJPMk9oaUFpcCt2eDB2eG9McVdNVHUxNXpqVHd5Y3FSOVBKcXZVTFBuSDgrYVpjK20vN0YwcWU0MTQ3cnJyak4rczFvdGNUZDVTc1MvcWFNeTFWWWlrMjdzMTArM3pDRkJoK2NjLzMySkpENy9zbzdNaWhwd2l4Uy9wSjJPQUxoSnpaNnJzMmIvVFJYNDZ0V25qNUhrWEZIVnh1SDdsbHFEVjdWRTNPbWowZ3FTU2lTZUdEZE9XbDU4c2F4WXNVTDNvbTdkdW9YdWFLcmpmeXlWQTlPZjA1RkJnWUZTWWZoUUtkS2tzZTd3ZlN0WHJyU3ZEUXQ4WU5ZOE8zdjI3clZ2VXM5ODkxMWpTOTVWWFFkMURKeEp1M2J2TnA0d24yN2V2SG02WlVaRVJJUjl5b3BwSk9qd2xMVDkreVhoL2dmdEplNm1SVFMvU0NvTXZVOUhBQXFDdXR0OU9yVThiY2dERDhpU1AvN1FQYzRLQ3cwdHRIdFovWWs2ci9pS3E2K1cvUzVVM2k0SWFsdEgzMzc5WEoxNThyS2FOV3ZxVnVHUWZ1eTQ3QnoraUNzMWVJcGZlWm1VNlhlOWpueWZXbExkdmxNbmlVOUkwRDIrUzkyc0huam5uVEp0K25RalNYcVJJa1drMnpYWDZNaWNiMTNhaDY2ZW8zay8vS0FqTTlUcEtpVktsTkNST1NUbzhBejFRYVFLb2JpeDF5b29xclRFVEoxay9BeDNBRG43N1YvNzA5VHhOMnJHd0pTeVpjdEtLY043eDJEVyt2WHI3UlVXSnMraDk0TEpUejFsN3hPRlNMT0xMdEl0LzZlT1FVMFlPVXJTRW5KM3lrVitoTmF1S1ZVbWpwT0FRUDlJQjM3ODhVZTVxa3NYdjlvaW9xclBqeGc1VXA1NTlsbmQ0eXhWamR5MHhTNFZ3VHlWa2lKL0dMcTUvN2NCdDkybVcyYVJvTU16OXIvK3BpVDkrSXVPekxIM25VOGVMNkdWb25VUGdJSnkraEwzbzBlUDJrZk9xQUdKS2VYTGw3Y0xUc0UzcVdySHNUMTZ5SUZFOHpkeUM5S2RBd2RLVnl2UndIODBiZHBVdC94ZjRydnZ5L0Z2ek04NEJoYUpsSmpwVXlTb1NCSGQ0OXZVcXF0dTNidmJzODcrUnEwc0cvYlFRL0xlZSsvcEh1ZTBiTmxTaWhjdnJpTXoxTEZuS1ZieWJOcm11RGpadTIrZmpweW56cXB2MTdhdGpzd2lRWWNublBoanFleWZQRjFIWnBVZWNMT1U2TkJlUndBS2twb04vZHNiYjc1cC9BaWNwaGRlU0FWM0g2V1dMNnFDVDF1MmJORTkva2tWTVp3d2ZyeU9vUGFlVjZ0YVZVZitMWG5OV3RrN2VhcU9EQW9Na0lwalJrbGszYnE2dzdkdDM3NWR1dmZvNGZmRkZlKzgrMjdIdDMrcGF1UlhYM1dWanN6WXQzKy83TGUrVFB0bTdsemRNa010YjNmcmlGWVNkQlM0OUVPSEpHSEljSFdMVVBlWUU5bWltVlFjd3I1endDdlVIbUsxVkRreE1WSEdqQjJyZTgxUnhhYmdteFl0V2lSdnpaaWhJLytrOW9TKy9lYWJVclJvVWQyRGtpVktTRlJVbEk3OFYvcXhZN0pqOElPU2RkSnd4ZkdBQUNuZDczcUo2bmF0N3ZCdGFzYThkOSsrZGhMbzcxUVJ5UnY2OWJOWEVqbkpkRlZ5Tlh2KzcrMXNUbE9yREV6dWRWYzM5dSs0L1hZZG1VZUNqZ0psbjNjK2JJU2s3OTZqZTh3SktsVktxa3lmekhubmdJZW81ZXo3OXUyVDk5NS9YNUp6T0JQZEtlcjhVdmdlOVRvWk5YcTBQUWp6VjJvQU9PS2hoNlJKa3lhNkIwcjVDaFhzeXNsK0xTdExkajA1UWRLMi9iTm9wZ25oOWV0SjlFTVAyb202UHhqNzVKT3kzTVVURDRLQ2d1eGlvMnBsaC9wU1c2WkNySEdsV3l1emRzVEh5NTJEQmpsNkxXemVySm1VS1dQMmlMMXZ2LzFXdDh3NGV1eVlyRHR0Ulo3VG9pdFdsR2JXOCtRV0VuUVVxUDF2elpBVEMzN1VrVUhXaFRONi9CZ0pMWVRucUFKZXBxcFVyOSt3UVY1NjJmelJpbW9nVmExYU5SM0JsNmlxN2FZcSszdUZPdkpvNkpBaE9zTGZHamRxcEZ2KzY5Q1hjK1RvWjEvb3lKeWdNbEZTOWFYbkpOQlBqcXo3K2VlZlplcTBhVG95UnhWcnZPTHl5K1dGNTU2VFgzLzZTYlp0MlNKN2QrMnl2L2JzM0NrYjFxNlZiK2JNc1crdzFhOVhULysvelBuSytsNU96aGFycXVRZERCOC8rck4xRGMvSXlOQ1I4OVRKRjA2dkxEaGQrL2J0alI5SmR6b1NkQlNZRTM4c2t3TlRudEdSUVZaeVh2cTIvbEx5eXN0MUJ3QXZlZk90dDJUTDFxMDZNcWRxMWFxdWZzRENHV3J2K2JQUFA2OGo4NnBVcVNJMzMzU1RQRDE1c3N5ekJzRWIxNjJUclhGeHNtLzNidG0wZnIyc1c3MWE1bi8vdlR6M3pETXljc1FJdWFaclY2bFh0NjRFNStOVWtLalNwZVdkR1RQc21UajhVKzNhdFhYTFA1M2F2a04yang1cno2S2JGQkFTTEpVblBDRmhmbElnViswM0h6QndvSTdNVUxQaXZYcjJ0Ti96Yzc3OFVnYmVmcnRkc0ZDZEJxSzJvNmd2dFNjNUppWkdMdTNVU2NhT0dTUExseTJUMlo5K0t1YzNiS2ovRnVlcEZVWDNEeDdzMko1NzlYUGVjTDNaby9aVVljKzllL2ZxeUhuZldkZGtrOXhjM3E2UW9LTkFwQ1VlbElUN0gzRG52UE1MbTBqRkI1bVZBTHhxenRkZjY1WlpsYUtqODVWRW9XQWNQSGhRZnZyNVp4MlpVNzE2ZFhsdjVrdzdJWC90MVZmbHZudnZsZmFYWEdLZm02K1NkbFhCVi8wM0ttRnMxNjZkM0huSEhmTDQ2Tkh5NmF4WnN1TFBQMlZYZkx4OC9PR0g5a0MzU3VYSyttL05uU21USmttTTlUM3d2L3g1VzBwR2NyTEVXMk9oek9QbWk1dEYzWGFMbE9qWVFVZStiOUtVS2JMVllGSFI0bGJpUFhQR0RIbjNuWGZzbTd1NXBaYkFkK25jV1JiLytxdWQwSnV5ZmNjT2VmNkZGM1NVZjVkWTF6cFZNTTZVWk91MS9xZDFuVFJCM2NUOTRndHpLMURVNy84aWw0OTZKRUdINjdJeU0yWFg2TEdTdnRmY1VRaC9VOHU1WXA2ZEtvRWNxd1FVZW01L3dNSVpxMWV2dG8vZ00rbmkxcTNsajhXTDdkbXl2TXhpcTBHNVN1Qmp1M1d6aTd5dFc3TkdmbHE0VUhyMjZISFdJNHh1Nk50WGJyamhCaDNsbjdweHNOTWF2T2ZtYTlXS0ZjYlBXbC8xMTE5bi9ONjUvVkw3WS8yUkdndnRmbXFLbkZxelZ2ZVlVNlJOYTZrNDlINGQrVDYxRDl2SjVQVGYxRXFyRDk5L1gzcjM2bVhQTHVlRjJsTDE3UFRwY3YrOTkrYjU3emlicWRiZjc5UzFVYTBHdUxSalJ4MlpNWC9CQXQxeWxxb1FiL0owajhzdnZkVDExVTBrNkhCZDR0c3pYVG5qVTRLREpIckNFeElhWFZGM0FDak1hdGVxcFZ2d0phWm56MVZpL2NGNzd6azZlNlNLUjdWcTFVcmVmL2RkZTNuc3hQSGo3UlVjL3g2b3E1bjJwNTkrMnRFQnZFb3UxSG4vdWZsU1MzVk5LMmQ5anpOOTc5eCtxWnNmL3Vqb0R3dms4QWNmNjhpYzRITGxKR2J5UkFud28rZHhpdldlVWFkL21ESjYxQ2k1N0xMTGRKUjM2clU3ZnR3NFk2dEFEaDgrTEsrKzlwcU84a2RkZzlRTlNwTisrZlZYM1hMV1h5dFhHaTB5YTdySy9abVFvTU5WU1N0WHliNHA1Z3Q2S0tYNjlwYVNuZnhuT1JlQS9GR3pwUEE5Sml2ektwZGJBL0dLRmMzZHlGVko1Z05EaDlxejZtcmZ1dHF2cXFoSzBHKysvcnE5L3h5RlM4cXVYYkp6eENnUmcwV3psSUN3TUlsNWZxcUVsRE4vSThZdE8zZnVsTGNOSHJmWW9ubHplM3VMVTlRS2xSZWZmMTRpRFoxRThKcDFEVkY3MHAyZ2Jrb1VNVmluWmMzYXRmWk5CYWN0TURRenI2aXRSODJ0MTRUYlNORGhtdlJEaHlYaDNxSG16L2kwaERlb0o5R1BQcXh1Q2VvZUFJV1pXbTRZY3c3N0NPRWRhOWV0MHkwenFydFUyVi9OYk44eGNLQzlySHpVeUpFeWVQQmdlOThuQ3BkTWZieHM1cEVqdXNlY3dLSkZKTXpQVHE2WStlNjc5bm5ncG93WlBkcnhXaVdxYnNXdHQ5eWlJMmR0Mjc1ZEZpNWNxS1A4S1ZxMHFIVHAwa1ZIemxOSHc2bHE3azVTKzg5TkZvanIyclZyZ2F6aUlVR0hLN0xTMHlYaG9VY2tMV0duN2pGSGZTQlZlWDZhQkJyZVZ3ZWdZS2dqWWE2Kzhrb1ovK1NUOXBFM0NkWUE1ZWpodzNMTStqcDY2SkJzMzdKRmZyTUdBV3IvMzExMzNHR2ZLOTNtNG92dEdVdjRuc1RFUk4weUk4MkZZcVduVTNzOUh4czFTcDRZTThiWTNsUjQxLzZYWDVQa0pVdDFaRmJHd1VPeTgvRW43ZjN1L3VEa3laUHluTUc5NTYxYXRwU09odlpoMzNQMzNjYjJNYi9sNElvQ1ZUZkRwQ1ZMbHVpV00vYnMyU01iTjIzU2tiT0NBZ1BsK3I1OWRlUXVFblM0SXZIRGorWEUvRVU2TWljZ09FZ3FUWjRnNFp4MURQaWRxS2dvZWZ5eHgrd3EyMTk4L3JrTWUvQkJlK2xaaFFvVjdPV0RFZGFYbXFXc1ZLbVNOTHZvSXJucnpqdmwyV2Vlc1l0L2ZURjdOc2tRemlodTgyWjdGc1p0dkI0THArQXlVYnJsanVOenY1TkRuMytwSTkvMncvejVjdURBQVIwNTc1YWJiemIydnF4bWpVc2JuWCsranB5bDZuUWtKU1hwS0gvYXRXMXJmNWFhb3Y2dFRsNXZmN2NTZnFlVytQOWI1Y3FWcGVtRkYrcklYU1RvTUM1NXpWclpOMjZTV29laWU4d3BxZmFkWDVIL3doNEF2RU1ObDlTeE5TdVdMWk9Sanp4aUorcm5RZzI0MUJKMytDYlRpZXlDaFF0bG04SGptb0RUUmZYc0xwSE5tdXJJQmRiWWE4K1RFeVROWUdMcmxsbXpadW1XODlRS3E2NEdsM2VyWmRMWHhjYnF5Rm43OXUyVHBVdWRXWlZScWxRcHUycTVLV29mZW1wcXFvN3liOUVpYzVOLzNidDNMN0FpbFNUb01Dcmp4QWxKR0RwY3NnenVGL3BiV1AyNkV2M0ljRFdhMHowQWZKMzZjTHovL3Z0bDFrY2ZHUzNrQmU4eWZjeVdxZ1o5ZGRldWtwQ1FvSHNBY3dLQ2c2WFNFNDlMZ0l2SE5tVWVQU1k3UjQxeFphTEVsSlNVRkpuenpUYzZjbDR6NnpwVHBrd1pIWmx4bWNIRTkrTlBQdEd0L092VnE1ZHVPZStFbFJjc1g3NWNSL21uYnJDYW9HN1k5TC9wSmgyNWp3UWR4bVJsWk1qT2thTWxOYzdjMllSL0N5eFdWR0plbUM2QjRlRzZCNEEvR0hUbm5USnA0a1RIaS9iQWQxUnpvYmlmT2tPM1djdVc4c0dISHpvNnV3T2NTVVR0V2xMMnZydDE1STdqOCtiTFFSOWU2djdyYjc4WlBWcXRrK0V6d0pXNmRldnFsdk5VOFRWVmhNMEo2bGc0VlN2REZMVlZ3UW03ZHU4MnR2KzhacTFhY2w3dDJqcHlId2s2ek1qS2tzVDNQNVJqWDVtNzIvbGZnUUZTY2V4ajdEc0gvRXpucTY2U3laTW1HVi9pREc5cjFLaVJicGwxOE9CQjZYL0xMZEswZVhPWjlja25jdlRvVWYwSTRMeHl0L2FYc0xwMWRPU092ZU1tU3VxZXZUcnlMVjkvL2JWdU9VOTl4blJvMzE1SDVvU0hoOHY1RFJ2cXlGbTdyV1QxMEtGRE9zb2ZkVFJrRzRQSGtxcnowSjNZaHo1MzdsemRjbDczMk5nQ25SZ2dRWWNSeWVzM3lMNkpVOXpaZDk2enU1Uyt0cXVPQVBpRDBxVkx5eXN2djF4Zys3L2dIZXBjWXJkdTBxaEI0NFlORytUNmZ2Mmtib01HY3UvOTk4dXlaY3ZzNWJXQWs5U0t2OHFUeGt1QWk2ZExaQncrSWdtUGpMSlhPUG9TVlFUc3g1OSswcEh6MVBGaTZpZzAwOVIxckdLRkNqcHkxckZqeCt5Q2wwN3AzNysvYmpsdjA2Wk5qcXhVTXJhOFBTeE1icjc1WmgwVkRCSjBPQzdqK0hGSnVHZXdaQ1dmMUQzbWhOYXFJWlZHajJUZk9lQkgxQ0RteWJGajdidjRRSTBhMW5VK09scEg3bEhIdTczOHlpdlNxazBiYWRTa2lUd3diSmhkaU1udFk5bmd2NHJVcnllbCsvZlRrVHVTZnZsTkRzMytRa2UrUVMxdFg3OSt2WTZjcDA3L0tGbXlwSTdNS21Idys2eFpzMGEzOHEvOUpaZEk4ZUxGZGVTc25idDJ5ZmJ0MjNXVU4rcW02ZEpseTNUa3JBYjE2eGZJWjg3cFNORGhyS3dzMmZYNGs1SzZiWWZ1TUVmdE82LzY4dk1TYVBBNENBRHVVL3YwYnV6bjdxQVYzcVVHejdIZHV1bW9ZR3pkdGsyZWZlNDVhZDIycmRTb1ZVdjYzWFNUZkR4cmxsMDlHY2d6TmFNNitGNEpxUnFqTzF5UW1XbFhkVS9aYm42YzVoU1Z6S1VhdkRHbTlocUh1clNTb1Z6WnNycmx2TjhXTDlhdC9GT25wYlJzMFVKSHpwdjc3YmU2bFRmeENRbjVUdkt6MCszYWF3dDg5UjRKT2h4MWNOYW5jblMyQzBWSXJEZE94ZEVqSmJ4bURkMEJ3QitvMmZPSGh3KzM5K29CZjd2bjdyczljMVRlWGlzcC8rampqK1dHRzIrVUt0V3FTWXRXcldUTTJMR3k2TWNmalJheGduK3lsN3BQZU1MVmxZQ1p4MDlJd3FPamZXYXB1eXFBWmxMVkdQZHVrSlFyVjA2M25MZG56eDdkeXIvQXdFQzV5ZUNOOHZ4dVdmamhoeDkweTFtaElTRkdsL2ZuRmdrNkhITnk0eWJaTS9wSlYvYWRsNGk5UmtwZlY3QXpLZ0NjVjdsU0pmdnVOWEM2NnRXclM0L3UzWFhrSFdyUCt2SVZLK1RKOGVQbDhpdXZsRXJXUUw5WG56N3lzWlhBcThHeUU0V1E0UCtLdFdndXBhN3ZyU04zSkM5ZUlnZG12cWNqYjFPbkxKaFVxblJwM2ZKdGNYRnh1dVdNSzY2NHd0aktncFVyVithNXRvZTZybjVqNk1pOXBrMmJHcXNUY0M1STBPR0lqS1FraWIvN2ZuZk9PNjk3bmxSK1lqVDd6Z0UvMUtkM2IzdEpNM0E2dGJKaXpPalJVcXhZTWQzalBXclFlUExrU1puOStlZHl3MDAzU2YyR0RlV0txNjZTeno3N2pKbDFuRldGd2ZkS2tPRnp1UDl0LzlSbjVKUVBMSFZYTjhGTWVudkdES2xlcTVZclgwOVBtNmEvcS9NT0hqb2tweHdjaDVjb1VVTGF0bW1qSTJlcGxVanFtTFM4VU5mVFB3MjlKcTY5NWhyNzg2YWdrYUFqMzdJeU0vK3o3M3pMTnQxalRrQkVoRlI1NW1uT093ZjhrRnBhTnVDMjIzUUUvRlBWcWxYbGlURmpQREY0eW8wVFNVbXljTkVpNlgzOTlWS3ZRUU83eU55T0hUdVlWY2NaaFpRdUxaV2VmRnl0TGRZOTVtVW1KY3ZPaDBkS1ZucTY3dkVlVlpUUnlhWGJaNklTdnAwN2Q3cnlwYXF0bTZMT1FWYzNDWjJpcnJVOWUvVFFrYlBVNzFVVjNjeUx6WnMzeTRFREIzVGtIUFh6M21CZHI3MkFCQjM1ZHZpTHIrVG9wNS9yeUNEcmpWUHhzUkVTY1o3NW96QUF1SzkrL2ZwMkVnWms1NDZCQStYcXE2N1NrZS9ZdDMrL1hXU3VWcDA2MHZlR0cyVEZYMy9wUjREL1Y2SmpleW5XcVlPTzNKRzg5RTg1OFA2SE92SWV0UXo2Rk1jYzVrNVdsdU9uVEppY1VmNXF6aHpkT2pmekRPMC92N2gxYTZuZ2dlWHRDZ2s2OGtYdE85ODlZcFI5VVRDdGVMZXVFdFc3cDQ0QStKdE9uVHB4N2pseUZCd2NMRFBlZWtzdWFOSkU5L2llVHovN3pDNHNweEoxZFI0dzhMY0E2L3BYZWV4b0NTcmx6cEZmZjlzL2FhcWMzT1RzL21XbnFQT3k4N3BYdWJESnlNeDBmSWErVEpreWN2bGxsK25JV1V2KytFTXk4bENvOEx2dnY5Y3RaL1h0MDBlM0NoNEpPdklsL3Q0aGtwV1NxaU56UXV2VXRqNjBIck5uMFFINHArczk5T0VJNzFMN0lyLys2aXRwMHJpeDd2RTlhcG43SjU5K0trMmJON2Nyd0NjbkordEhVTmlGbENzckZSNTlXRWZ1eUR4NVVoSWVmRmd5cldUWWExVENlZlRvVVIyaElQVHAxVXUzbkxWdjcxNTcyZis1T0hqd29QeTVmTG1PbkJNUkVlR3BBclVrNk1pWE5KZk9PNDk1ZHFvRUZTMnFld0Q0bTByUjBWS3ZYajBkQVRrclc3YXN6UHZ1TzduODBrdDFqMjlTQloxVUJmaUwyN2ExOTFVQ1N0UTExMGpSRHUxMDVJNVRhOWZKL2xkZjE1RjNxSnRaMUcwb1dCMDdkcFNRa0JBZE9lZWtkZjA3MSswK2E5YXVkWFNmL2QvYVhIeXgwU1B3emhVSk9qeXYvTU1Qc3U4YzhITk5talF4TWdDQS95cFpzcVI4OXVtbk11VCsrKzB6ZTMyWkduUzJ2ZVFTbWZ2dHQ3b0hoVnBnZ0VTUEdpa0JMcC85ZitERlZ5WFpTdFM5Sk4xSHptcjNaOUhSMFhKeHExWTZjdGJYWDMrdFc3bXphTkVpSXpkc2JqUjQ1bnRla0tERDg5SlU5VTd1bmdKK3JSckY0WkFIWVZZQ00rbXBwMlRXUng5SmxjcVZkYTl2U2p4NFVIcjA2aVh2dmYrKzdrRmhGbDQxUnNvUEcrTHExcjZzbEJUWk9mSXh5WEs0MEZoK3NQM0RHL3IyN2F0Ynpqclg1ZXJ6NTgvWExlZW9iVk9tOXRubkZRazZQTy9ncTIvS3NaOS8wUkVBQVA5MFRkZXVzdXF2dit6WmREWFk4bFdxSU5hQWdRTmwxaWVmNkI0VVptVnU2Q3ZoRGR6ZCtuTnE5VnJaKzhKTE9pcDR4ZGplbUd0cUpWRmtaS1NPbk5XaGZYdjdocWpUMU9xaC9mdjM2eWhuaVltSnN2VFBQM1hrSEhYV2UxUlVsSTY4Z1FRZCtSTFpvcGx1bVpPVm1pWTdIeHdocWJ2Tm5vTUpBUEJkUmEyQnZKcE4vOHNhd1BYdTFjdllRTlcwOVBSMHVmMk9PMlQ1aWhXNkI0VlZZR2lvVkprMFFRTEMzVjNxbnZqNjI1SzBhcldPQ3BhcEk3NzhrWHFtMUVrWEpxZ2pVQnMyYUtBajU2amw2cjh0WHF5am5DMysvWGY3K3VpMC9qZmRwRnZlUVlLT2ZLa3k5U2tKS21QK3JsUEdnVVNKSC95QUp5dU1BZ0M4bzNMbHlqSnp4Z3hadVh5NTNIdlBQUkpWdXJSK3hIY2tKU1ZKLzV0dlpua3Y3Qm84Wlc2L1RVZnV5RkpWM1ljL1lsZDNMMmlxTmduMVNYSW53T0FNdXBxZHY3bC9meDA1NjdmZmZ0T3RuUDMwMDArNjVaenk1Y3JKcFowNjZjZzdTTkNSTHlIV0M3dktNMU1rSU1UTUhidlRuVnk2WFBZOSs0S09BQUE0TXpYclZxMWFOWms2WllwczJyQkIzbnJqRFduVnNxVlB6Y1p0MkxoUkpreWNxQ01VV3RacnR2eWR0MHRvclpxNnd4MnBjWnRsNzRzdjY2amdxSVN6U0pFaU9rSk9WQklkR2hxcUkrZDF2dnBxQ1RQdzk2dVo4ZHdVZnZzMWw0bjh1VkRWMjlYcUs2OGhRVWUrRld2ZFNxS3NEdzgzSkw3OHVoejcxZmszS0FEQVB4VXZYbHo2M1hDRC9MUm9rV3hjdDA0bWpCdG5EOHBNRERTZDl0SXJyOGkrZmZ0MGhNSXFNRHhjS2s5NFVpUW9TUGU0UTQyNVRoZzRjL3BjcUgzUDRTNVhzL2RWNWNxV05acWdxMnJ1alJzMzFwRnpWcTFhWlI4NW1STjcvL215WlRweVR1L2V2WFhMV3dLeURCNHVtSldlTHB1NnhFcnF4ampkazcyb1FRTWxldGhRSGYyVFd0YThvVlY3eVRoMFNQZWNXWU8xeXlYUVIvZWNtWlQ0NWd6Wjg4UUVIVG1yWWR3YUNRZ090bi9YMjI2OVE1SisvbFUvWWs1d3ViSlM2NnZQSk1UNnM3QTZNbitCSkF3WXBLTXpLOUVqVm1JbW4vbjNucFdSSVhHZFl5Vmw0eWJkazcyUzNicEtsV21UZGVSL1RzWEhTOXhsbmUzWHNFbUJSWXBJblFYZlNZZ0xXMEpNdUgvSUVIbnhKWE9GZys2KzZ5NlpQbTJhanJ4TmZXdzJhdExFbnVFMDVkdHZ2cEZPSFR2cXlCbE5teldUVmF2TjdTdDk1KzIzcFcrZlBqcnlOdlU3UEhic21Id3pkNjRzdEJKM3RjUnl5OWF0UnZZMzV0ZXdCeDZROGVQRzZjaFphdEJidFVZTnV6aWRLWHQzN2ZKY0FhWi9XOWV5bmFRZk9LQWpjNklualpjeTNXTjFkTzUyVFhoS0RyNyt0bzdjRVZJMVJzNmJNMXVDQ21oOHJkNlRkUnMwa0IwN2R1Z2U1Nm5WTnUzYXR0V1I3enF2ZG0xNWFQaHdIWm54MHNzdnkzMkRCK3ZJT1F0LytFSGF0R21qby8vMXlhZWZTdDhiYnRDUk05UzU1MXMyYlpMdzhIRGQ0eDBrNklXQUd3bTZrbmJ3b01SZDNVMHk5cHYva0l0czNWSnF2UDJhQkJUU2ZVa2s2TTRoUWM4ZEV2VC9SNEorWnI2VW9QK2JTZ0xVVExWSzJOV1htcWxSbFlVTkRwRnlUYzFhcVpsL0U0TklFdlQvOEpVRVBlUDRjZGw0OWJXUzduTFIzTkw5K2tybHgwZlp5KzBMd2lVZE91UzZrRmhlWEhYbGxmTGw1NS9yQ0RsUjE4VnFOV3RLbXNOSDhZMTQ2Q0VaTzJhTWp2N1hnTnR2bHhrelorcklHWDE2OTdicmxYZ1JTOXpobUJEckE3anlsSW11TE1GS1hyeEU5cjd3c2hvcDZ4NEFBUEpHVlQ2dVZLbVMzRDVnZ016KzlGUFpzSGF0L1B6amozTFhIWGRJMVpnWVk1V1JjMlB2M3IyeWN0VXFIYUV3Q3lwV1RDbzlhU1V4Z2U0TzN3OS9PRXVPLzFsd1M5MmJYWFNSYnBteGVzMGF5Y2pJMEJGeVVyWnNXV25ab29XT25KUFRQblIxQTNIeGtpVTZjazZQN3QxMXkzdEkwT0dvNG0wdmxqSjN1YkFmM1hvVEgzenhWVG4reDFMZEFRQ0FNMVRSb0JiTm04dXp6endqNjYxay9hZUZDMlhRWFhjVlNFWDR6TXhNK2ZycnIzV0V3azZOczBwYzAxbEg3bEFyekhZT2YwUXlrZ3JtVklIYXRXdnJsaGtuVHB5d3Q3emc3RlNoeld1NmR0V1JjOVNLdEpTVUZCMzkwNTQ5ZTJUTGxpMDZja2I1OHVYdGxSTmVSWUlPeDVXL1o1QkVORGQ3dDFQSlNrdVRuZmM5SUdrdUxLa0hBQlJPNm9pblpzMmF5VFBUcHNuV3padmxwUmRla05xMWF1bEgzYkhrano5MEM0V2RPa29yK3VGaEVoVGw3czJpdEIzeHNudmk1QUpadWRqQ3dJenQ2VlJ5dmludTdOdHg4Ui9YWG51dDR5ZGlxSlZDMjdkdjE5RS9xVG9oVHE5dzZOSzVzOUdDZXZsRmdnN0hCWWFGU3N3elV5U29iQm5kWTA2Nmxad25ESHRZc3RKWm1nUUFNRXNkK1RUZ3R0dGs1WW9WOHVUWXNSSVJFYUVmTVV2dGlXY0pMdjRXVXJhc1JJOGU2ZnBTOXlNZmZ5TEhmak8zRnp3NzFhdFZNM3JVbWxxbDhzTVBQK2dJWjZOK0g4MmJOZE9SYytaa3MxTEk2UlZFNmppNjNqMTc2c2liU05CaFJHaUZDbEw1NlluL0xTQm5VdEpQdjhxKzUxL1VFUUFBWnFsWmRWVXQrZk5QUDVVaUxoU25WVVhzZkhVSnJoY3I0L3VEa2xkZUljVXVkYmFRNU5uWVM5MkhqWkQwdzRkMWp6dlVscFA2OWVycHlBeVZISHFoS0tTdk1GRVE5RXlGQUpPU2toemZmMTdSeWxGYXQyNnRJMjhpUVljeHhkdGNMS1h2dUUxSFppV3EvZWkvc3dRUUFPQ2VEaDA2eVBCaHczUmtqcHJoVS90a25hYUszem05VlBYZjJOdHJSa0JRa0ZSNi9GRUpMRkZjOTdnamZkOSsyVFYra3F0TDNZT3NuL1hTVHAxMFpNWmZLMWZLdG0zYmRJU3p1ZUx5eXgwdm5ybDh4WXIvT1E5ZEhYK3BLc2M3cVZ1M2J2YjUrbDVHZ2c1enJBLzlpdmZmSXhFdG5WOEc4Mi8yZnZRSEhuTDlyaTRBbUtBU01pZXBtU0duajhYQmZ3b20zWGJiYmNhWHVxdmYzNzhIcms1UWcxVFRDYnJKSTl3S3U5RHk1YVg4ZzBOMDVKNmpuMzhwUnhmOXFDTjNYSEhGRmJwbGhscnA4WlpIajl6eW9obzFha2pEQmcxMDVBeDExT1d1M2J0MTlCK0xGeTkyZEdXRHV0blR6K0h6MUUwZ1FZZFI2cHp5S3BNblNsQ3BrcnJISEhVdWFNSkRJNDJmWncwQXBoMC9mbHkzblBISnA1L0srZzBiZEFRbmxTNVZ5dDZUNll0TUorZktab2VyTCtPZnl2VHFLUkZOTDlDUlN6SXpaZGRqWXlYOTZGSGRZWjQ2VlVFZDhXWFNqSGZlc1pkVTQrelVQdTRiKy9YVGtUUFVUWkxmZnZ0TlIvOHhaODRjM1hKRzFhcFZwZEg1NSt2SXUwalFZVnhZNVVwU2FlcFQ5bklzMDA3TVd5RDczM2hiUndEZ201eGMwaGNmSHkvM0RSNnNJLzl5OE9CQk9YQ2dZRS95VUFOVnRTZmRORFh6NDdUdzhIQUpOSnlrcTJXck1DY2dPRWdxajM5Q0FpTENkWTg3MUtUSXprZEgyOG02RzlSeTZsNkdDM3VwNDd6R1B2R0VqZ3FlMHl1cG5LYU9LWE82RXZyY2I3L1ZyZi9jcVA3bFh3bDdmbDE3elRXZXJ0NytOeEowdUtMRUplMmsxSzAzNmNpc0ExT215L0hGemhhVUFBQTNyWEFvcVZIN2YvdmRlS01rSmlicUh2K2hrdk91MTE0cnpWcTBzQ3N3RitSZzF2UnVYSldjRnk5dVpxOXg0OGFOZGNzTU5TTkc4UzJ6SW1yVmxITDNEckszRnJycDJMZmZ5NUg1QzNSa25xcThiWHJWeDZ1dnZTWnIxNjNUVWNGUTI1SGVmZmRkdWVubW16MWRaTEZhdFdwU3ZYcDFIVGxERllyNysyZGV0V3FWb3lzYTFNM1VXL3IzMTVHM2thRERIZFlGdGVLUSt5UzhTU1BkWWM1L3FvdytMT21IaitnZUFIQ09HaUNXS2xWS1IyYW9ZN1h5bTlTa3BLVElMYmZlNm5nRlhDOVFNeXZYeHNiYXo1UGFzOWpGU3RUNzMzS0w3UDdYL2tVM3FMM2hwbStBaEFRSFM0a1NKWFRrck1xVkt1bVdHY3YrL05NKzR4aG1sZTEvbzRUVnE2TWpsMlJteWE2Um95WE5wVlVzelpzM04xN04vWVNWRUtxYm1rZGRYTDcvTjNYTlg3bHlwVng2K2VWeXk0QUI4dkdzV2ZMc2M4OTU5Z2FYV2puVTcvcnJkZVFNZGVOMTE2NWRkbHNsNjA3KzdPZlZyaTIxclM5ZlFJSU8xd1JHUkVqTWMxTWwwTkFzd09uU2QrMzV6L25vSGw4ZUJNQTNtUzRLdG5yTkdsbTdkcTJPenQzSmt5ZmxaaXM1LzlMaC9YdGVvS3FaOSs3YlY1Yjg4ZjhuZDZnendqLzg2Q05wZk9HRjh0U2tTVVlxbm1mbnA1OS9ObjVqb0VtVEpzYVcwVmN5bktDcjM4WGpZOGJrZWFETk1XMjVFeGdlTGxVbVBHblgvbkZUeHNGRHN2T3hzU3E3MUQzbXFKVWtRMXpZcnJQR3V2YjI2dFBIOFZvZ09WRko2VzIzM3k0dEw3NzR2OGVOcWZmTXFOR2paZjc4K1hic1JkZkZ4anE2L1ViZDhGUTM5UlNuejZidjBxV0w0NVhuVFNGQmg2dkNLbGVXU2xNbTZNaXNFL01YeVlGMzN0TVJBRGpIMUd6bTZjWlBuSmlucEVZTjlHSzdkN2NMdy9rYk5XRHVlOE1OTWkrYmdkdVJJMGZrMGNjZWt6cjE2OHUwNmRPTnoyeXIvZStEaDVpdm9uM2hoUmZxbHZOYXQycWxXK2JNZk84OWVlT05OODdwOWJ4cDB5WVpQSFNvdEd2Zm5rcnd1UlRab0w1RTNlTE9kc0xUSFo4M1h3NTk4WldPekZJSllhWG9hQjJaczJEaFFtblRycDJzVzc5ZTk1aXhkZHMyR1RaOHVOUnIwRUJtdnZ2dS85eVFVcTk5dFRwbysvYnR1c2RiMUJMM2VuWHI2c2daMzgrYloyL1ArdkhubjNXUE0yNnpua2RmUVlJTzE1VzhySk5FM1RsQVIyYnRuelJWa2xhdDFoRUFPTVBwNDJYT1JDWFlMNzM4Y3E2VEdqWHo4Tjc3Nzh0RnpadkwvQVh1N1F0MWkxcXlQMkRnUVBuMnUrOTBUL1pVa2IzaER6OHNOV3ZYdGd2a0xWMjYxUEZqNXJaWkErYk9YYnZhQTJ5VDFMNUprOFd4YXRXcVpYOFBrOVJ6Zjg5OTk5bUp4dXJWcTgrWWNLdlg3MFlyS1gvbm5YZmt5cXV2bGtZWFhDQXZ2UGlpdlkxQkpTN0loWUFBcVhEL1BSSmF2YXJ1Y0lsMWpkb3o3aWxKZFdFclE3Rml4ZVRSa1NOMVpKWkt6bHUyYm0ydnlqbnM0REcrYW9XVG1oVlhLNEhxTjJ3bzA1OTlWazdtY0l6aS9nTUg1TnJycm5OMVpWQnVxWlU5dlh2MTBwRXpWTjBLZGMxMnNxN0lCZGIxUkIwTjV5dEkwRkVnS2d5K1Q4SWFtTjFIcEdSWkY4R0UreDdnZkhRQWpsTEZjVXhUaWZuUUJ4NlFJVU9IMnJNbmFobjN2NmsrZFhhc0tpalV0Rmt6dWVXMjJ5VHg0RUg5cVA5UXladjYyVDZiUFZ2MzVFNnk5Um1nYm5LMGJkOWU2alpvSUk4OS9yZ3NzeEkrTlR1VGw5VUphc0NvS2oxUGZPb3BhWExoaGJMaXI3LzBJK1pVcmx4WnpyY0c4YWFvR2JDU0pjMGZoWnBoUFhjZmZQaWhORy9WU2lyRnhOaEp1TnFHMGNkS1VscGRmTEZVcmxwVkxyQ2UwOXNHRHJSdk1KMytlbGUvTjdVM0ZXZW5scnBYR2pkV3JRZlhQZTdJT0hSSWRvNGNMVmtaNXJjV1huLzk5VWJmRTZkVHliUmFsVk8zZm4xNWNQaHdXYjU4K1Rrbnl1cTFyRmJ6cU8wd2FsVkluWHIxNUtvdVhlenIyWm11NjJleWJ0MDZ1ZU91dXp4WjJWMGw2RTdlNU51d2NhTjg5dm5uZWJwR1owZFZiemQ5STlKSkFkWVA3OXhQL3krcVdOZW1MckdTdWpGTzkyUXZhdEJBaVI0MlZFZi9sSm1hS2h0YXRiZmYvRGxwc0hhNUJFWkc2Z2gvUzN4emh1eDV3c3l5OG9aeGF5UWdqL3M1VG0zYkxsdTZYaWVaU2NtNng1eWlWMTRtMVo2ZjdzcFJiMjVRVlZNVEJnelMwWm1WNkJFck1aUFAvSHZQc2o0UTRqckhTc3JHVGJvbmV5VzdkWlVxMHlicnlQK2NpbytYdU1zNkd6OC9QN0JJRWFtejREc0pLUk9sZTN6TC9VT0d5SXN2dmFRajU5MXREVHltVDV1bUkrLzdhK1ZLYWQ2eXBhTURpSnlvNDdCcVdJbVVPZ3Y0NzJSS0xlZitmY2tTMmJscmw2dDdKYlB6enR0dlM5OCtmWFRrSERWenJoSTVwNWJzcXlKL1phS2k3SnNzSFR0MGtQUFBQOTh1UEZXNmRHbTdVcnJhVDZtKzFNQlpmYW1aTTFXSTdwZGZmcEh2dnY5ZS9zekRBRDAvSG4za0VSbHRKUWdtWGR1dG0zeHoydkZHWGpUNHZ2dGs4cVJKT25MV3VwYnRKTjJGUW1mUms4WkxtZTZ4T2pMSXVpNGxQRFpHRHIvL2tlNXdpZlhlcXZUVU9JbHk0V2Y4MlhvL3FtSnFCWkd3bGk5ZjNpNDQxckpGQzZsUXNhSjliVmJYanJEUVVFbTNyaGxxbWJxNnFhcUtJOGJGeGNtdml4ZkxnZjM3NWVpeFkvcHZ5THVuSmt5UW9TNXNxemtYNm5mUXVrMGIrOXJvbEwrdndVNVExL3kxcTFiNVRJRTRoUmwwRkpqdzZ0VWsycnFRaXd0M3RFNThPMDhPekppcEl3RElIelU0aTdDU1pyZW9HV1MxM1BLdEdUTmsyalBQMkYrcXZYN0RCazhrNTZhb2dhN2E0KzNrZm5wMVUrVkFZcUs5ZFBxcHlaT2wzMDAzeVlYTm1rbTFtaldsZE5teVVyVkdEWHZaYVl5VndLdTQ1bm5uMmZ1Z0gzbjBVZm54cDU5Y1RjN1ZUWU43NzdsSFIrYjBNWEJqeFdrdnZmS0tiTEtTSGVTQ1d1bysrRjRKS2xkV2Q3akVlbS90blRoWlV2ZnQweDNtWE55NmRZRWRtYVZXTGFrYkJKT2ZmbG9lZVBCQnUrWkhwOHN1a3phWFhDTHRPM2EwYnh5bzdUaHE1bjNHekpteWVmTm1SNUp6WmZUamo5djc0NzFFelV4MzY5Wk5SODV3S2psWExtalN4S2VTYzRVRUhRV3ExRlZYU0ttK3p1NWR5YzcreWRNbGVXM0JubTBKd0Q5RVJrWktodzRkZEFRVFZISisvK0RCOHZxYmIrb2VkNmlWQ2ZFSkNZNE5xUE5qMEoxMzJrbTZhWmQyNmlURml4WFRrVGVwbFJRUFBmeXdhNnRXZkYxSVZKUlVHalBLbFVtUTAyVWNPaXdKd3g4eHZ5ck4rcm1lbmpMRjhRSmxYbmZLZWgvYzFMKy83Tml4US9kNHc1V1hYMjdQVkh2UkRRNGZCZWNHRW5RVUxPc0NHejFxaElTZmI3N2dVdGFwVTVKdzcxREpPTzY5SWhzQWZFL1BIajEwQzA1VFN5WWZIRFpNWG4zOWRkMVQrRFNvWDE4ZWZ1Z2hIWmxWcGt3WnVleXl5M1RrWFY5Lzg0MHMrdkZISGVGc1NsemFTWXBkM2tsSDdrbjZkYkVjbkdYK0ZJa2lSWXJJekJrejdNSnhoY20rL2Z2dFdYc3ZyWjVxMUtpUko0dXdoWWFHU3RldVhYWGtPMGpRVWVBQ3c4SWs1b1ZuSkxCWVVkMWpUdXEyN1pMdzBFaDdEellBNUllYWRWUURSRGhMTFcxOGN0dzRlZkhsbDNWUDRhTUdsYTlhUDMrWTlmbm9Calh6OWNqRER6dDZuckVKYXZaOCtFTVBjZXhhTGdVRUJrcmxzYU1sS01yOEtveC9zSDVQZThaUGtsTTc0bldIT1kwYk41WTNYMy9kZnM4VUpxdlhySkZCOTl6ajZGTHcvRkFyR2t6VUlNbXZwaGRlS05XcXVueXFnUU5JME9FSllWVXFTL1NUajlzejZxWWQvMjZlSFB6d1l4MEJRTjZvUWtHeER1KzdNeTBxS2tvdWFkZE9SOTZqRXJCSmt5Zkx1QWtUQ3UxU1pwVWtQek50bWpSdjNsejN1RU1WeSt2YXBZdU92RXNWYUh4bkpqVmxja3N0ZGEvdzBJUDJ2blEzWlNVbnk4N2hJeVRMaFNKdXFrTDMrQ2VmOU93U2ExTSsvT2dqbWZMMDB6b3FlRjA3ZDdZVGRTL3BmK09OUHZtNklFR0haNVRxMmxsSzlycE9Sd1paSHhaN3gwK1M1SFhyZFFjQTVNMndCeDd3bVprYjllOTg3ZVdYN1Vyd1hxVUdVbDJzUVY2dG1qVjFUK0dpQnJjUER4OHV0OTE2cSs1eGozcnV4ejcrdUd1ejl2bnh4TGh4ZHEwQTVFNVU3TFZTcE8zRk9uSlA4ckxsY3VDdEdUb3lSNzEyVlRIRnh3MmZkdUJGVTZkUDk4d1JoT29tWDZYb2FCMFZ2S0pGaThwVlYxMmxJOTlDZ2c3dnNDNncwU05IU0ZnZDg1VVdzNUpQU3Z4ZDkwbUdIMWMvQm1CZXZYcjE3RHYwdmtBTlh0VmV2SmlZR04zalRXcVE5L3ZpeGZiWnVvVnBSaXc0T0ZoR1BQU1FQRFpxVklIOTNPcjFySTUxOC9yenZudjNiaGsvY2FLT2NGYUJnVkpwOUVnSmlJalFIZTdaLyt5TGtoSnZmcW03dXJrMTR1R0g1WldYWHBMSUF2ZzVDNEphdnIxdy9ueDdaWlFYaElTRXlJMzkrdW1vNEYzVXRLbFVyRmhSUjc2RkJCMmVFbFMwaU1TOCtLd0VGamRmOENNdFBrRjJqaHh0NzVVQ2dMeFFpY3lUVHp3aFZTcFgxajNlby82TkkwZU1rQWNmZU1DTzY1eDNudjJubHhVcld0UXUvdlRCdSs5S3hRb1ZkSy8vVXVmY1B6dDl1bjNlZVVFdkVYMWc2RkRwMEw2OWpyenJSU3NSMjdoeG80NXdOdUhWcWtuNVlVUHN5UkEzWlo0NElmRkRoMHVtQzNVRDFMWHUxbHR1a2RtZmZTWmx5N3A4eEp5TFNwUW9JVStPSFNzL0xWb2s5ZXZWMDczZWNGMXNyR2RxV1Z6ZnQ2L25ielptaHdRZG5oTmVvN3BVZk1KS25GMFlwQnliTTFjU1AvaElSd0J3N3RReFdLKy8rcW9ubDdxcldWazFJM3I2ckd5NWN1WHNQNzFPL1h1N2QrOHVmeTVkS2pmMTYrY1RTNi96b21yVnF2TE5uRGx5KzRBQm5oaE1xbG13OTJiT2xFYm5uNjk3dk1rK2RtM0VpRUpicXlBdnl2VHBMZUVONit2SVBTZi9XaVVIM25wSFIrWjE3TkJCZnYvMVYvdXNkRjlOME01RUpiNlhYWHFwL1BuSEgvTFE4T0dlL014UnEzQzhNR3V0S3Z1cjJnUytpZ1FkbmxTcXk5VlNzcWNMKzlHdEQvWjk0NTZTazNHYmRRY0FuTHVPSFR2SzFDbFRDbnoyODNScW1lY0x6ejRyajQ0YytZOS9WNmxTcFh4cTBLcG13bDUvN1RYNStjY2ZwWFdyVnA1Nmp2TkRKY0szOU84dlMzNzdUZHEyYWFON3ZVRWR1L2JGN05tZVQ5TFZzV3Z6NXMzVEVjNG1NQ3hVcWp3MVhnTGN2dGxsamJVT1BQK1NxMk10dFpYbnU3bHpaZHdUVDloN2tYMlp1bDQzYU5CQXZ2anNNNW56NVpmMlRUMnZVamNOZW5idnJxT0NvNjZwNnJQT1Y1R2d3NVBVMFNEcWZQU3d1dWFYWW1hcS9laUQ3cGVNcEdUZEF3RG5idUR0dDl1VmhMMlFRS29sOTNPKytrcHV2ZlhXLy9uM3FKa0ZWWUhlbDZnQjZnVk5tc2lDSDM2UUw2M0VVU1hxdmt6dGpmemVTaDVlZWZsbHord2YvYmZLMW10SUpUaHFOdEtMMUd0Q25VaFF5Y1BiUzd3bzRyemFVbWFnKzBVSU01T1RKV0hZdzVLWmxxWjd6Rk9yYm9ZOStLRDhzWGl4ZEx2bUdwK2NUYTlicDQ2OC9jWWI5bzI4SzY2NHdpZHVVSHJodURWZnIyRkNnZzdQQ2lwU1JLcE1teXlCTHB3em5McDVpK3g2Ykl4ZDRSMEE4a0lOQnRUKzNiZGVmOTNlUTEwUTFMK2gzL1hYMjh2Q3M1dVZWVE1jQmZYdnl5KzF4Rk1OVWhjdFdDQUw1czJUWGoxNytzeFo5T3Azb3hMejk5OTlWMzc5K1dkcFkvMSt2RDZBVkRQcGFzWk9GYThMOTlBV0ExVWM2NFAzM3BQdnYvMVdHdFIzZjhtMlQ3TmVjK1h2dWxQQ3JFVGRiYWRXcjVWOXo3Mm9JL2ZVcmwxYlpuMzhzZnk0Y0tGY2Nmbmxuai92WDFITDh6OTgvMzFaOGVlZmNyMTFUZmVsTFQ1cW1YdjE2dFYxNUw3aXhZdjd4SkdST1NGQmg2ZEYxSzBqRmNlT3NsNnA1bCtxUnovL1NnN08va0pIQUpBM2FqQzFkTWtTVjg4YlYzdk4yN1Z0S3o4dldpUnZ2dkZHamt2NzFOSnFOWXZ1eTFSaTI5YjZlZFZlNmExeGNmTFV4SWx5NFFVWDJNK0QxNmlDVGoydXUwNStYTERBVHN4Nzl1amhVOHYwMWV0bDdKZ3hzbVR4WXVuVXNXT0JQY2Vxa0o3Ni9wOTk4b245UEhhM25sTi8yZTdnTnJYVXZkSzRNZXJDb1h2Y2svanFHNUs4dm1DT3VXM1ZzcVY4OWNVWHNselh0U2pqc2RVcmF1KzJPbUx4THlzcFY2dUYxR3ZjaTllMHMxSHYxZGh1M1hUa1BuV2Q4UG5QdUN5RDFUV3kwdE5sVTVkWVNkMFlwM3V5RnpWb29FUVBHNnFqZjFLVkh6ZTBhaThaaHc3cG5qTnJzSGE1QkVaRzZnaC9TM3h6aHV4NVlvS09uTlV3Ym8wRUdMNTRaR1ZtU3NLSVIrWG94NS9wSG5NQ3JJRkl6YTgra1lnNmRYU1BOeDJadjBBU0JnelMwWm1WNkJFck1aUFAvSHZQeXNpUXVNNnhrckp4ays3SlhzbHVYZTJWRFA0cTdjQUIyVFZ1b3ZXY21GMDlZUStJSG50VWdsMDRvY0NFR2UrOEkvT3NBWU1wbDNicUpEZjM3NjhqLzVCaHZjKyttak5IeG93ZEsrczNiTEJqcHhXeFB2TlVvdnJJd3c5TDgrYk5jejB6cENwZy8yWWxYRTRhZE9lZDBycDFheDI1VHoyL08rTGo1UXRyQVA2NTliVjIzVG81ZXZTb2Z0UTk2dVpCeVpJbHBkbEZGOW1KZVRkcm9PckxleUZQbDJsOUhxOVlzY0krNG16QndvVnk0c1FKL1lnWmF0YXdSbzBhOXA3Vy9qZmRaQys3TjVHVUo0d2NMZW5IanVuSW5LanIrMGp4VmkxMFZQRDJ2L20ySksxWXFTUDNoSjlYV3lyZWM1YzltMStRMVBWaDd0eTVNbVBtVFBseitYSTVmUGl3ZnNRZDZucXRpb3gydU9RU096RnYyYktsUlBwSkhxTSs4OGFOSDYrai8zVXlPVm0rdHA1N0U1K0w2c2F0V2wzbHkwalFDd0ZmVDlDVkRPdURjL04xdlNWMXl6YmRZMDVZN1ZwUzY4dFBKREE4WFBkNER3azY0RHZTMHRMa2o2Vkw1WlZYWHBHNTMzNHJ4NjJrSnErRGtrQnJRS3RtTkZVeXJnWWduYSsrMms1YXZMNVUybTFxYUhQdzRFRlp2WHExZlB2ZGQvYmdlOGtmZjBpNk5TNVJYMDVTTTF4cW9LMFM4aGJXNytWcTYzZWlpcXVwSk4yZnFiUEl2N0VHMkxNKytjUitiaytlUEdrbjhQbWhYdHRxeFVGcksxRlJTMVRidFd0bkY4VHloU1hKOEcxSGpoeXhyeE9xOE9EaXhZdGw5Wm8xOXJYQ3lRUlNYU3ZVbGh4MXJiajhzc3VrZmZ2MjloN3ppRUp5YnZ2cFBwczlXM3IzN2FzajU2am5kMWQ4dk05c2Zjb09DWG9oNEE4SnVwSzhicjFzN1htRFpDV2JMK1pXc25jUHFUTGhpUUsvdTVzZEVuVEFONTA2ZFVyV1dBTS9sYkQvL3Z2dkVwK1FJSWxXSWhsdkRTaFVnbk02dGYrM2ZMbHlkaEV4VmZTdFdiTm0wckJoUTJuY3FKSGZKMzhtcEZwamlaMDdkOHFhdFd2dFB6ZkZ4Y25XclZ2dGdibWFTVXRLU3JKbjRNOUUvUTZpU3BlMm4zZTF2N0dhbFRUV3ExdFhxc1RFMkwrVHlwVXFGY3BCOXQvVWM3ZldlbDVYcmxvbDY5ZXZ0MmZQMUd5a2VsNjNiTmtpL3g1b1ZvcU90bWNPMVpjNjUvNkNDeTZRbWpWclNpUHJ0UjFUcFFvSk9RcWNXaDJ5YmRzMmV5V091bDZvbTFESGpoMnp2OVExWS9lZVBaSjhodkdvU2d5aksxYTBielNwNjRXNmdhcHUyS21xOHVkYjE0b3ExdXRiM1lncXpOUm5YWXZXcmUxcmhkUDYzWENEdlBYR0d6cnlYU1RvaFlDL0pPaUtPck44enlPamRXUldwV2NtUytscnV1cklXMGpRQWY5eHRvOWhac2ZOeSsxUWlOL0Z1Y25wZWVXNWhLL0t6ZldDMTNmMlhudjlkUmwwenowNmNvNjZzZmZEZDkvWkJUaDlIUWw2SVhCazloZHk0T1hYZGVTc1dsOS9iaVhvTHQ3cHRsNnV1NmM5S3ltYnp2NmF5cS9BWXNXazhwaFJFdVRCMXhRSk9nQUFBSHpKdm4zN3BQRUZGOGpCcytSMGVhRzJDL3kxZkxsZnJNQWhRUWQ4RUFrNkFBQUFmSVZLT1crNTlWWjU3NE1QZEk5ejFJcUYxMTU1eFM0bTZRODRud0lBQUFBQVlNejdWbUp1SWpsWHlwVXJKOWZGeHVySTk1R2dBd0FBQUFDTStQWFhYNDNzTy8vYm5RTUgrdnpaNTZjalFRY0FBQUFBT0c3VjZ0WFNxMCtmTTFhOWQwTEZpaFhsdm52djFaRi9JRUVIQUFBQUFEaHEvb0lGY3ZrVlY4aitBd2Qwai9PR1AvaWdmZnlsUHlGQkJ3QUFBQUE0SWkwdFRaNS80UVc1TmpiV1NNWDJ2OVd0VzFjRzNuNjdqdndIQ1RvQUFBQUFJRjlVcGZiMTY5ZkwxVjI2eUpBSEhwQ1VsQlQ5aVBOVTVmWXBreVpKYUdpbzd2RWZKT2dBQUFBQWdEemJzR0dEM0Rsb2tGellySmtzK3ZGSDNXdE9yeDQ5NUlyTEw5ZVJmeUZCQndBQUFBQ2NrME9IRHNuc3p6K1h6bDI2U0tNTExwQTMzM3BMMHRQVDlhUG1SRmVzS005TW42NGovME9DRGdBQUFBRElVVkpTa3F4YnQwN2VldnR0aWIzdU9xbGVxNVpkb2YzN0gzNndsN2U3SVR3OFhENTQ3ejJKaW9yU1BmNkhCQjBBQUFBQUlKbVptWExxMUNsN2RuekR4bzN5MVp3NU11cXh4K1R5SzYrVVduWHEyRXZZQjk1NXA4ejU1aHRqUjZkbEp6QXdVQjU3OUZGcDNicTE3dkZQSk9nQUFBQUFVTWlkT0hGQ1dyZHBJNDJhTkpFYXRXdkwrWTBieTNVOWVzakVTWk5rNGFKRmtwaVlLQmtaR2ZxL2RsK2ZYcjFrNkpBaE92SmZKT2dBQUFBQVVNZ1ZLVkpFZHU3YUpkdTJiN2VYczN0SjJ6WnQ1T1dYWHBLZ29DRGQ0NzlJMEFFQUFBQ2drRk5IbDdWdTFVcEgzdEgwd2d2bDAxbXpKQ0lpUXZmNE54SjBBQUFBQUlEVU9lODgzZktHaTF1M2xybmZmQ09sU3BYU1BmNlBCQjBBQUFBQUlNMmFOZE90Z3FWbTg2L3Awa1crbmpOSFNwVXNxWHNMQnhKMEFBQUFBSUJVcVZ4WnR3cU9TczZIM0grL2ZQakJCMUlrTWxMM0ZoNGs2QUFBQUFBQWlZbUprV0xGaXVuSWZTVktsSkIzWjh5UXB5Wk9sSkNRRU4xYnVKQ2dBd0FBQUFDa2VQSGlFaDRXcGlQM0JBWUV5R1dYWGlyTGx5NlZYcjE2NmQ3Q2lRUWRBQUFBQUdEUFdydTlEejI2WWtWNTZjVVg1YXN2dnJCbjhBczdFblFBQUFBQWdLMUJnd2E2WlZaa1JJVGNQV2lRckZ5eFFtNjk1WlpDY2NaNWJwQ2dBd0FBQUFCc0Z6WnBvbHRtaEllSHl4MERCOHJLdi82UzZWT25Tc2xDVnFYOWJFalFBUUFBQUFDMk9uWHE2SmF6cXNiRXlOakhINWZOR3pmSzg4OCtLOVdxVnRXUDRIUWs2QUFBQUFBQVczUjB0QlF0VWtSSCtWUEorcnY2WFgrOWZEOTNybXhjdjE1R1BQeXdsQzlmWGorS015RkJCd0FBQUFEWWloWXRLdVh5bUVTci8yK2Q4ODZUTysrNFF4Yk5ueThiMXEyVHQ5NThVenAwNk1BZTgxd2lRUWNBQUFBQTJNTEN3aVNtU2hVZG5WbEFRSUJkNUUzdEgyOS95U1Z5MzczM3l0eXZ2NVlOYTlmYVJkK2VlK1ladWZqaWkrMzk1amczSk9nQUFBQUFnUDlxMmFLRi9XZTVzbVdsY2VQRzByRkRCN2t1TnRaZW9qNXp4Z3laUDIrZXJMZVM4VjN4OFRMdnUrL2s2Y21UNWRKT25lemw2OHlVNXc4Sk9nQUFBQURndjBZOStxaWtuVG9sdXhJU1pObVNKZkxkM0xueTBRY2YyRVhlK3ZUdUxXM2J0TEgzcW9lR2h1ci9CNXhDZ2c0QUFBQUErQzhTNzRKRGdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSHVBakNYcUEvYit6eVR4MVNyY0EvNWFaZkZLM2NoREUvVGNBQUFEQWwvakVDRDR3TkVTQ2loWFRVZmFTVnEzUkxjQy9uVnkyWExleUZ4SlZScmNBQUFBQStBS2ZtV0lMdjZDeGJtWHY2TmR6ZFF2d1gxbHBhWExzaC9rNnlsNW81V2pkQWdBQUFPQUxmQ1pCanp5L29XNWw3OFM4QlpKKzZKQ09BUDkwN0pkZkpYM1BQaDFsTDdKRk05MENBQUFBNEF0OEprRXZlbkVyNjErYjgwYjBqS05IWmZkVFQ0dGtadW9ld0w5a0pDZkwzdkdUUkxLeWRNK1pCWlV2SitIVnF1a0lBQUFBZ0Mvd21RUTlyRnBWQ2ExZVhVZlpPL3JwNTVMNHlXYzZBdnhIVm5xNjdCbzVXbEkzYjlVOTJTdmVxWU1FQlByTTJ4c0FBQUNBeFdkRzhJR2hvVktxVjNjZDVTQWpRL2FPZkZ3T3ZQT3VaRmx0d0I5a0pDVkovSU1QeTlFdjV1aWVIRmlKZWFuZVBYUUFBQUFBd0ZmNDFCUmJWTi9lRWxTcXBJNnlwMllhOXo0K1RyYmZmcGVjMnJxTkplL3dXZXExZk95blgyVHp0VDNsbUVyT3o3SzBYWWxzY1pFVXlVWE5CZ0FBQUFEZUVwQmwwVzNIcWVSaVU1ZFlTZDBZcDN1eUZ6Vm9vRVFQRzZxajdPMS81WFhaTjNHS2pzNHVJRGhZSXBvMWxhTHQyMGxFclJvU1ZMYXNmZ1R3cUt4TVNZdmZKU2MzYnBUajMvOGdLWnMyNndmT0xpQTBSR3A4K29GRU5zdzVRVmVyUytJNngwckt4azI2SjNzbHUzV1ZLdE1tNndnQUFBQ0FLVDZYb0dlbXBzbm0ySjZTc202RDdnSHd0MUkzWFMrVnh6eW1vK3lSb0FNQUFBRGU0M05WcEFKRFE2VEsxRWtTV0tTSTdnR2doTld2SzlFamh1c0lBQUFBZ0s4eG02QUhCRmoveS9sb3RQOUtUOWVOczR1b2M1NVVtajVKQWtKQ2RBOVF1QVZYS0MvVlhuOUpBc1BEZGM5WnFIVXp1Vnc4bzdhSkFBQUFBRERQZUlJZUdKbTdtZTdjSEIxMXVwS2RPa3JGOFdQc1BiZEFZUllVVlZxcXZmMmFoRmFzcUh2T0xpc3RWVEtPSDlkUnpvS3JWOVV0QUFBQUFDWVpUZERWT2N6QnVhaTZycHphc1VPM2NzbEsvcU42WENkVlhubEJBb3NYMDUxQTRSSmFwN2JVK09SOWUxWEp1VWcvZEZqUzl4L1FVYzVDS2xUUUxRQUFBQUFtR2QrREhuWitmZDNLV2RxV2JaS3ljNmVPY3E5RSszWlM2OHRQSktKNVU5MEQrRCsxN0x4azMxNVM2N09QSkx4YU5kMmJlOGNYL3k2U2thR2pIQVFFU0ZpVnlqb0FBQUFBWUpMeEJEM2l2TnpQN0IzKytEUGRPamRoVmF0S3pmZmZrZWhKNHlTa2FoWGRDL2lob0NDSmFIYWhWUC80WGFreWJvd0VSVWJxQjNKUFZYQS8vUEVuT3NwWllFUzRoRlUvOXhzQUFBQUFBTTZkMFdQV2xMVEVnN0toUlZ1UnpFemRrNzJReXBYa3ZPL25XRWxCaE80NWQ1a3BLWExzeDUvbDREdnZ5cW5WYXlYeldPNzIyUUtlcGJhS1JKV1d5Tll0cGN5QW15V3lYajBKc0JMMXZFcGF0VnEyZGU5ckg0TjROcUUxcWt1ZEg3NnhaOUlCQUFBQW1HVThRVmMyWGR0RFVsYXQwVkhPeWc2NVZ5cmNkN2VPOGlmOXlCRTV1WEdUSkM5ZklTbWJOa3Y2c1dPU2xacW1Id1c4S3lneVFvS0tGNWZ3Q3hwTGtTYU5KYXhhTmJzdnYxUlN2cVh2VFhKeTJYTGRrN1BTdC9XWFNvK08wQkVBQUFBQWsxeEowUGU5L0pyc2YrcHBIZVVzTURKU3FuL3luajFMQ01CWkI5NTVUL1krL21UdWpsZ0xDcFNhWDM0cWtmVjVMd0lBQUFCdU1MNEhYU25aK2FwY0w4bk5URTZXK0R2dnkxUEJPQURaTzdyd1I5azNibUt1eno4UHExVlRJczZyclNNQUFBQUFwcm1Tb0tzcTBFV3Z2a0pIWjVjV255QmIrOXdvSnpkdjBUMEE4c3hLeUk5OCs3MGszSFh2T1czeGlMcmxKcnRhUEFBQUFBQjN1SktnSytYdXZQMmNCdnZwdS9iSTF0amVjdWp6TDNOVnpBckEvOG80Y1VKMlRaZ2tDZmNNa2F5VVZOMTdkaUhWcWtxcDJHdDFCQUFBQU1BTnJpWG9rZlhxU3ZIWXJqcktuVXlWWEF4OVNMYmNjTE9jV0xxTVJCM0lwY3hUcCtUZ3A3TWw3b3F1Y3VpMXQzSjM1dm5mQWdLazNIMkRKREEwVkhjQUFBQUFjSU1yUmVMK2xuWWdVZUk2ZDVNTTY4OXpaaVVOb1RWclNORjJGMHVSQzVyWTdhQVNKZlNEUUNHWGxTbnArdy9JcVUxeGtyUmtxWno0ZGJGa1dIRmVGTEhlWTlYZmVrMENBbDI3ZndjQUFBREE0bXFDcmh6NVlZRzlGMWJTejJGR0x6dWN6UXo4UHdmZXlvRWxpa3V0T2JNbHJISWwzUU1BQUFEQUxhNG42Q3FKMkRQcGFVbDgrWFhkQWNBTEFzSkNKZWJWRjZWNHV6YTZCd0FBQUlDYjNGL0RHaEFnRlI0Y0lpV3Vvd0FWNEJsQmdWSmg5RWlTY3dBQUFLQUFGY2dtVTNVbWV1VnhZNlRvcFIxMEQ0QUNFeGdvNVI0WUxHWDY5TklkQUFBQUFBcUMrMHZjVDVPVm1pbzdIeHNyUno3NlJQY0FjSk5hMWw1eHpDaUo2dDFUOXdBQUFBQW9LQVdhb051c2I1LzQzZ2V5YjhJVXlVeE8xcDBBVEF1SnFTeVZwMHlVb3MwdTBqMEFBQUFBQ2xMQkoramFxZTNiWmVlREkrVGs4aFZXMHE0N0FUZ3VJRFJVU2x6YlJhSWZlMFNDaWhiVnZRQUFBQUFLbW1jU2RDVXJQVjJPZlArRDdKczhUZEoyeE51ejZ3Q2NFUkFTTEJGTkd0dEwyaVByMXJFNk9LWVFBQUFBOEJKUEplaC95MHhKa2VPL0xwYkVOOTZXazM4c3N4TjNBSGxnSmVHQlJTS2wyR1dkcE15dE4wbGsvZnAyVVRnQUFBQUEzdVBKQlAxMHFmdjN5L0ZGUDBuU2I3L0x5WTJiSkczTE5zbEtTOU9QQXZpM0FDc2hENnRWVXlJYm55OUYyN2FSb3ExYVNGQ1JJdnBSQUFBQUFGN2wrUVQ5SDZ4L3FwcE5UenQ4UkRKT0hKZjBnNGNrS3pOVFB3Z1VYb0hoWVJKVXZJUUVseXdwd1NXS1N3Q3o1QUFBQUlEUDhhMEVIUUFBQUFBQVA4VTBHd0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFGVHVUL0FFaTRQaHNXRHBDaEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMi0yMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiVHJ1c3RLZXkgU29sdXRpb25zIFQxMjAgVTJGIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDIwMDgxNDAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjciLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTEyLTIxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0xMi0yMSJ9LHsiYWFndWlkIjoiMzEyNGUzMDEtZjE0ZS00ZTM4LTg3NmQtZmJlZWIwOTBlN2JmIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIzMTI0ZTMwMS1mMTRlLTRlMzgtODc2ZC1mYmVlYjA5MGU3YmYiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMgd2l0aCBMaWdodG5pbmcgUHJldmlldyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDM4NHIxX2VjZHNhX3NoYTM4NF9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURLakNDQWhLZ0F3SUJBZ0lVZWYrVnZIa2NUUW5FRCsrd0pNL0l4elNVTGswd0RRWUpLb1pJaHZjTkFRRUxCUUF3SmpFa01DSUdBMVVFQXd3YldYVmlhV052SURJd01qTWdSa2xFVHlCUWNtVjJhV1YzSUVOQk1CNFhEVEl6TURreU5URXhNekkwTVZvWERUSTBNVEl6TVRFeE16STBNVm93SmpFa01DSUdBMVVFQXd3YldYVmlhV052SURJd01qTWdSa2xFVHlCUWNtVjJhV1YzSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBb3VGTVRPS2FFMFl0ZXhPb2lzU3hwK0ViaTVJQTRlc0VTY3gxNmx6UWRxVjYvZVo4Mkt0SmVOWEV1TmtCVlpEcGMzMmdTdHV4TEJIOG1nc29IQkZhaTJEa2pmQm41cWJ3Ui9jNStzbmx3WnZqZ1ZBMGh6S3c5Q3dBZUF3UkQ1a3JXdDg4L0NWeUNrTWNnTFNHd1pzL3JqN0YvTHMzRWJnN01xTGJiUUo5Q296YmJMZEpVWUlIY1BwU1pQdG9NclpiNEd2bmk2aVZTOVV2Q0tncHFjNkxHUm1vWUdHNFpSM2xHSi9YUVpmdStHZUpXNjdpaW1Nai95b1hPd3h1Y3hpdlpIRms2Y1FTZ3d1d2lvZU5tNHd2azgzTGhTdVdjdGYya0F5UWNaN2tVbnBOZWUrZDRNZ3JtR1U0WE1GTGlUZ3V0YUIrZTlWOGQ1SlRrVU9IaUx6dGtRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVNNVNCNWJIclYranBJT01kSmw3dTdiY25UWTh3SHdZRFZSMGpCQmd3Rm9BVU01U0I1YkhyVitqcElPTWRKbDd1N2JjblRZOHdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUNvd1IzS1RMZmlkSnlRRk5xRUZmVXJmWjlhYTllZ3BPUXROUkpkTFN0SjZ4dTJXZkx3dkc0b2pHSmxCS05uZmE1REljeVFZZi84cUo0ZWxpQVZlTlh1WW1lTW1nTmdaWnl1WTZHMXlXQ0QyVjNzRDZaNHVqM1NiYURPSGozZ0h2c3pnUWhyaFQxaC9wdUhRa242K2hZS0FwNzdrTTdJYzZBWi9SRmJqcG1MTGsyRDBzRTFselQvMDJpK0JoN004c21haURaOSsrSkd6eGVTdW44VzFIbGVaVW0ycUtHbVJhNFhQZHJ5VDd4NktHVUduVTRhM2JwVW1WZVk5clEvc2ZNZDVaVG9vKzN1bkZXRHpvVlYydk51OCsrVkxDOXpvNDBGYUtRTHI5VkFKREo0eUxFTlI3S3JtVjhMMGNDWEtKR1pXQVd0RzVSR1RtSEloZCtuQjQxZz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiMzEyNGUzMDFmMTRlNGUzODg3NmRmYmVlYjA5MGU3YmYiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJsYXJnZUJsb2JzIjp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZSwiYWx3YXlzVXYiOmZhbHNlfSwibWF4TXNnU2l6ZSI6MTI4MCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH0seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTM1fV0sIm1heFNlcmlhbGl6ZWRMYXJnZUJsb2JBcnJheSI6NDA5NiwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjMyOTQ3MiwibWF4Q3JlZEJsb2JMZW5ndGgiOjMyLCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6MSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjEwMH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wNC0wNyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDQtMDcifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI0NDU2MWE5NWQ5YTI2NjRkMzJhMjY3ZGJmZTg2Y2UwYmIxOWU1OTI2IiwiNDJkYjI0YzI2NDRiZDBjMzA5NDhhMzNjY2MyNjYzNWQ5MWRiZTQwZiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI0NDU2MWE5NWQ5YTI2NjRkMzJhMjY3ZGJmZTg2Y2UwYmIxOWU1OTI2IiwiNDJkYjI0YzI2NDRiZDBjMzA5NDhhMzNjY2MyNjYzNWQ5MWRiZTQwZiJdLCJkZXNjcmlwdGlvbiI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPIFNlY3VyaXR5IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNrakNDQWptZ0F3SUJBZ0lKQUxsaUt2cUdId094TUFvR0NDcUdTTTQ5QkFNQ01JR2xNUXN3Q1FZRFZRUUdFd0pEVGpFU01CQUdBMVVFQ0F3SlIzVmhibWRrYjI1bk1SRXdEd1lEVlFRSERBaFRhR1Z1ZW1obGJqRXpNREVHQTFVRUNnd3FVMmhsYm5wb1pXNGdSWGhqWld4elpXTjFJRVJoZEdFZ1ZHVmphRzV2Ykc5bmVTQkRieTRnVEhSa01SNHdIQVlEVlFRTERCVkZlR05sYkhObFkzVWdSbWxrYnlCVFpYSjJaWEl4R2pBWUJnTlZCQU1NRVVWNFkyVnNjMlZqZFNCR2FXUnZJRU5CTUI0WERURTNNRE13TWpBNU1UVXhNRm9YRFRJM01ESXlPREE1TVRVeE1Gb3dnYVV4Q3pBSkJnTlZCQVlUQWtOT01SSXdFQVlEVlFRSURBbEhkV0Z1WjJSdmJtY3hFVEFQQmdOVkJBY01DRk5vWlc1NmFHVnVNVE13TVFZRFZRUUtEQ3BUYUdWdWVtaGxiaUJGZUdObGJITmxZM1VnUkdGMFlTQlVaV05vYm05c2IyZDVJRU52TGlCTWRHUXhIakFjQmdOVkJBc01GVVY0WTJWc2MyVmpkU0JHYVdSdklGTmxjblpsY2pFYU1CZ0dBMVVFQXd3UlJYaGpaV3h6WldOMUlFWnBaRzhnUTBFd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUbW45MUVJWVZmNURUMHA5aXBjM01vYmZ3S2FyblA5ZE04Y3JNU1pOUFh5WXYwSDczOHVLakJubmxDcnEzM0lURHdDT0RTbFVhRHc1MEluam51NXlQQ28xQXdUakFkQmdOVkhRNEVGZ1FVcklrdkQ2ekxpRHVjZGhObkFxbG1ySW5ObjVzd0h3WURWUjBqQkJnd0ZvQVVySWt2RDZ6TGlEdWNkaE5uQXFsbXJJbk5uNXN3REFZRFZSMFRCQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQURkWkJTeTU5RjNkemMrRXZVOUpDdjNlSEp3K0FpdkJYVThINDZlNmVwOUFJZ1V0OS9BZy92VEFqSWtLdElKcy96YkhhZkRjSm1ybnlVL1pQMTE1T2JlbjA9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUl3QUFBQVlDQVlBQUFBb054VnJBQUFBQ1hCSVdYTUFBQjdDQUFBZXdnRnUwSFUrQUFBRklHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORElnTnprdU1UWXdPVEkwTENBeU1ERTNMekEzTHpFekxUQXhPakEyT2pNNUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdLRmRwYm1SdmQzTXBJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4T0Mwd05TMHlNMVF4TkRvME1EbzFOU3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2UTI5c2IzSk5iMlJsUFNJeklpQndhRzkwYjNOb2IzQTZTVU5EVUhKdlptbHNaVDBpYzFKSFFpQkpSVU0yTVRrMk5pMHlMakVpSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKaFpHOWlaVHBrYjJOcFpEcHdhRzkwYjNOb2IzQTZaV014WlRnM01qRXROek0zWVMwd05UUmxMV0V6WVRrdE5URmtNVE16TkRabFpUSTVJaUI0YlhCTlRUcFBjbWxuYVc1aGJFUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJajRnUEhodGNFMU5Pa2hwYzNSdmNuaytJRHh5WkdZNlUyVnhQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaVkzSmxZWFJsWkNJZ2MzUkZkblE2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRveU1UZzFaakppWmkwNE5XWTVMV05tTkRjdFlXSTROeTA1TVdNellqTm1NR0kzT0dVaUlITjBSWFowT25kb1pXNDlJakl3TVRndE1EVXRNak5VTVRRNk5EQTZOVFVyTURnNk1EQWlJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBb1YybHVaRzkzY3lraUx6NGdQQzl5WkdZNlUyVnhQaUE4TDNodGNFMU5Pa2hwYzNSdmNuaytJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCsvMFZ4UlFBQUdmVkpSRUZVYUFYVndYZmNuM1Y5Ny9IWDUvdjlYdGR2M0RzN0pKQUlBVUxZQlptQ2ltRFZEbGZ0dzIzSHFZdXFQVjBXdGRiV1I2M25WRzJybnJhT3RzaERyUlVmUFIzV1dTM0tWaEFaWVFvRVFrTFduZHp6TjY3cituN2U1MDRpS05XTzg1OCtuMm51aXNTL0ozRzhZWmVaMlpURUltRDg1K1JPTzBaU1VmaUhKUDZGSHlJRVdCakF3ek53Nm9iSTNDeWtDR2FHSk55aExNV3dnbnJvcE5KSUNCTlVjb29pME84Yit4ZkY2UExBcUlNY0dvZDJXK3pZRDlGZzQ5ckFnYjFpMFRKVEhXR0N1bzZVaGVFSmRpOW1WclNOOGNLWXE0MmQrOFNLQ1NPMmdBd2RJQlFRVFB4N1psRFZka2tXYnpUWmNLVEkzZGh2dnJHbHVlTTlkOFVUWDBScitqbW95WUNRT01Tc0JMcEFBakxRUnhwZ3hvK1JBbWxyNG9jSVpoZUdrRjVsQnBMNHJ3aElDWExEZkgrZ0R4ZUZrSGdDQ2VTd2Y3OGhFei9Lak1QRUQ1SWdSWHVSdWYyMHBZQlpRNzJmN1N0R0gzWW1UdnhGTWhjZ0F3bGlBUkxnR1d3R05BZldRcXdtaHNoQmNuNHNHT0ErbDhxQ3h4bVFCVTNEU1pJajhWOFRZRkMwallVRmJlMzFkUDJ5NVpBelR4QVM1TVpBZ1BHanpRQkIxWUR4QTlaWjBLa21jRUhJbWM5M0x2aTNIZkhJa3FaZWpUSWdNRUFPN2w4bnhrOGgzWUxuM1lRMGp1c00xTHlPRU01RTRzZUNnT3ovbFBZY0VJOXhRVHR4eEhnM251a1lJTDVyRWRnT0NDajRmZ1lTc1I1cVJhZWpxMEppdXFwNGdoUU5MdzFWNHNlRkFLOUZNcjVIUUxUalFneWJNY2lOZzdIbjFwV1hmT09oNnNTTDhQa2pNUWRMWUdHYXdkN2ZKWFl2UjBXZkVNQUMxQldFNGxaNkMvOU1tZjZPY3VUcFNJRDRrV1VHMG03RXZlbTJiYzVqaG8xWU94bVBPbk1UcDJhSjdJQ0JpWThKL1Q3UUFrWUFjWkFBUThFb2MwTzJ5TGJSVVVNQ001Q01kaHYyelRsa0kvSmpSR0FSUWhISWpYaU1HY2RLR25lTTBqS0lPeDZwVisvTFp1Y2o3eEFNU1B2bzZ4VjQ5UVhTT016Tnc4Z0VkRm93TXdNalk1RFNYcHJtclJUNkI0eFZpQjlkRWt0dUpOcU90SGMrOEpqK0VEcGQyeFRhakdnQUdlTWdkLzluWUU4STRJSVFRQ3dKZ0lNTFhCQU5tZ3lTa1IySzROejlJRHc2THpZZkxRcmp4NFlaTkRYMGVrNTNMQ0J4U0FwMmpwbGhnaFkxc3paeDAxWE5CWE1FdGhBcVFCVzk1aDAwNlF2RUVhaEp0TXVYVU1RWDBGUlgwMnA5aENMTm93Q2Vyc2Y4UHJCVi9LZkVZY1ovbnpqTStBSHVFQUwvSVRsZ1lNWmhCcTZiRVF2cFNVZEdIbFBWeEJWamRvNnk0UklnRU5zRU82SkJscEVDVkxVVGdoRkxRVFljSXlNS1FaTWhHMVFORktYNDVqMWlZdEpvSlVPVitDRU1HQUVDTUErSS93OENYR0NBTzFqa3Y4MVlJc2dPRW9lSXd5eEFYWW01L2M2cWxZWm5hREpINWN6SmhJQk1tT0FoMy9qbGdYVldRejZSWURBWVhzdEMvUmQwbGtNNUF2STNVSFRmUndCcWZ4NGpvMXVCTDJJUjZnRFpHMElBQk80UUkyRGdEaVlPc1FSeWtJTVpQMGpnR1VMaWNSWUFnUXZNT0VRQ015aGE0Qm5rUElFRUZxQm9RYTdBSFVJRUJEbmZpY2pwcEVseGlJREltczZZblprYmFESllNRHo3M2NnZm1Xa0NSWUxKQ1AwK1dBQUtIbWVBWkVnUUFnVGprTkUycEFnU2h3aklBb3pqZ1o5Qk9rK3d6c0JjN0FPK2d2aWt4S1A4SndTNEdERzRLRVhPRXF6cXRQQUEzekhqQzRLdC9CY0V5NEp4OFdpYk0ySmtLb29hZUFENEN1TGJHQlFseEJFalprR2Y5WFZ0bTRoZ0NJelp2K1hGRHowWU5wNk5MYXhFRG1YbnMweVpFeW9vMHhuSS9vaWNvYWtoUk1CZWczd1RVa24yMVJnbkU4UWhyUTRvZzJjSGJRZjI0cXdpMkhxU0JScUJBRE1lNXc2cGdNNFlESHFRR3pDRGtDQVZNT3lCSEN3QUFnR3hBRGw0Qm9zY1pxQU1DR0lMd2poVVBhRnN3QTZDN21GSm1ubFVIT1FaV2wxV2o0eXlSVUVna0J0bHlUMnRxQU43NTRXNXNXUkNjS3JnRExEamdPVUdDb0dkR0xjQy95cDRoQjlHRU9DWXFYWjRiVzdzUmRGMEZHYUdJQU1wUXNDZVpZRmZNN04zQ1A3YVFId2ZBVG1yUlBaTHJjaXZZR3lXV1ZlQ3RaTWdsNXJLM3BTaVBvYnpoOENBN3lNZ2kxR1pYZXB1cjR6R3BnMnJZbG5YQWplVWhEc1BXZVRQTGZMSDFVRGFmbSttTG95UnR2M0VaTmNtcXl4YU5DQnV2VDZldXdQeE10UnY0K3JSRzl4SU11ZzBNTlFCTE54UGEyUUx1WUZxQU1UbkE4L25vQ0lBeGlFaGd1Y0RMUFkrVGpQNEV1Tmo5K0RXSjRSQU5YTTZkTi9DeUxLeldKd0ZieUJFUUJCTFVJREZtUWR4WFVjcTdzVENnR0gvS1Bweno2QXplaElHTkEya05uamV3ZmJiUHNyWTZ2dG9UejRmYTE2SUJjZ1pXaU9RNjBmWWZ2K0htRmh4QjkzUm44UHp5M0RkanJHZEphbTdNWENRQkVYa0REUEdjZ1VXd1hBR2ZWMWZXMEJ1YXkzeTg3Zzl2OTIyRXcxYklUY3dnU0FGUThKajRINlpYVkZMSHdCbStTNEhBcng0OVRKN1I5a0t4dzhXd1FLUGs2QnNRUUdXemRZWG8vR2pkWk9qTWg4MkRwTWdKanRwOVVUODM5MWtGK2VHb2tqQ0piSU1seEJZcm5Wa3UydHZNdzlIbXZKckJRT1dPRkFFVGxuVkRoOXNXYmlnY2NOTTFCbkVraUFra0xFaEJIdDNHV3dWbWQrOGQ1dnp4ZS9FOU15ejdjeUx6NGZxRVNpVjJWbHMrUHllWW0yUFBrL0ZNc2dIRFBveldJQ3FnbTduQVR5L2dOazlyNkVvbjBkNzlFazBGWWNJQ0FIRUVvRVB2OHFqRDd5VFZjZGR3OFI0UXpXQUxCQmcrV0ZtRnIvS2JITUZVK1h6Q0FteWd3VW8weDcyUGZTWFBIRG4zN0xsS1E5aDFpZEV3R0ZtMXlvNng3eVZzdnRHNmhrd29EUDZOaFptTG1mWnhoWXBYWXpYSUFHQ2FDQzlpMTc5RnpUWFFUcmhRc3BONEl2ZkF1WlprcnBkY1pDZ0UyVm5lelpjSW1LME9ueDFkdGIrTGplNmVOVUsrMkRDanE5ZGhCQzA1QURTaUFYS1ZqU2FSalFpeEdESGdyM1Q0Rm5BcjBwODJ3V2R5RnRiSStHM1RUYmV1QkFRZ0JBTjVQTWpMVDUzeDRPNmV0c0MrODQvd2RaT1lpOXRpTzh5eTdjaTNjaEI0dHhXeXo0UzRjUWlRT2c2dlI1N1RGeVZnanlZWFNSWTFRQU9kR0o4cWFSckpQdG9VM1BRdVNuWUZhUFJObVdEakREWVdkVit2Um5aNEd3ejIyQkFOWlNWbmZpcW80N2xzNVBPVmZQTGJPMktVZHRNWDJBR0JRdzZFOWMwZCsxZHhkcmpOdEZPb0RoQ1ovOTU3SGhnSzBlZkM2RUc1eDRHaTc5T1NoOGdwS2NSL2Rjb3U2ZlFuNGZza0NKUS96M1ViMkJxelU2YVBvd3NPNWJoNEFKY3UvRG1xN1FuQnZTWlovdld0ek4yN0dsMEp6Y3lXQVRaOVZSemI2YmR2b2JONTRxaUJXcWdHb0lpdEVmM3NPZkFteGkzU0xkOUtWVi9GNjN1VnpqNkxJakZPbFJkZ0FVUUVBTU1xM3ZKZGhWcjFrSnVMY01tbjRvcW9MNFpQSU9SR0hDSUdWTkVUaEpnQnRuOXk4TUJyeDhkczdjRmhYZDJvaGcyZm1QTytuU1EzUXkyRDlOa1U5a3BpNDIvb0d5Rmk4cElrQXR2eE1TWW5SK0srQWtMell0RzIzWkJ1d3h2eXoyMTYwYVlRWkZBVVBWNy9xbWlzRDluVkxmMSt2U25lNDRzUU5ZVmplenRwZkhVUm40VHNNNHN2TS9FaVNIQlRGLzloVVg3MDdLdGo0NjAySVhJTjl6VmJKNGFpKy9mY25TNHNCcUl4bFcwWTN6ZHZnVSt1bTNhanpqdEtQNE1iRk10a0duT3M3ODNoUERKRU94UlNSZ2NpWGdieGtzRmxxS3RhS2Y0d3Y1UVY1MTZySjYweWptaDJtOVlFSlRzZm85ZS84aDlCemFld1JIelU0UUNGRnFFOEFhOHVvbWl1SVdtRDU2aExNRGlnN1JISHVTV2E3L0VzUDlSVG5uNnM0Z0dpL1cxeU41SUhPeWtNN0dNaFlVM3M3ajRVc1JxaWxBZ1BrNk92MDY3M3N0UjYyOG5oeHZJMmtoMy9DYm1GMStMdUkzeE5lRGg2VlQ5VnlHT1JQbG1HdjlUSmxidHhJRDU0Vi9TYWo4WGZDZHpleGV4TnRUVldVVGZnQm1ZUVREb0RYZlEwelltV3BBMm5vUDdDZmhnSHlIZmpvbURrampNeFBwQU9BNER6OXdnOFg3VityMlJUbno1WXEwSGRzL2xQeHdwN1RQQm1PTzdna0hsWEh2M3cvNnhpU24vK1ZNMnBiZFhzL1lrajJJNEVLRUtXNTU2VXZIbG1KaW9lbW9yYzBnclFRT1BIaGo2VzJuc2I4cUN4OFVJTVJpNDl0ZFpmMUFVWERCV3BvbUZTcjlsRnM0SkNBdk03WnIxUy92emZIekRlc01NRURSdXQ4NzNtcmNvcC9jRVdCOER6WFJQOTMvcU9pL09Qem45YW12VW5yd3dDNWdlOHRwZkJYeU5KN29iOUR1WW5XallhWjdGWXJaTk1jTksySktDalZkbWRCbkFnQnNmMGhIYjJMTHVkYVFESTFRVnlLQ3o2bVNPbWZvazduK00vRXQ0L1FpdFVlaU9nemNnN1dEWSt6MXlQb21pWEU5amY0aHBCNmIxcEhnNTR5dWZ3WEFBWmhBTlhDK25hbTRsOEI2NjQ5QktCOGdMTU5kN0o1VnVvNHFSRWJ1TXdjSnZZMkVNaTFDTVhvU3FEdGhseEFBZHpkSTBleWs3MzJJNG5PT3V1Mkg5NnROWnRUd3hyQ0FZeEFRTCsyL0NyTS9vYXVoVlQ2WlZkSmh1cnFldEEzUWlPS1FVamU4NnhZd3B3VTdIcjIwbmUwdjJkRzQvNit2dS9pcGdHOTlsZ0ZoaUhOSTR2VWE2SFBkdjdodndpYkZPT0RVQnVSSGpJeHlSSGVvR2drRU1zR3RHMzg3QjMxaDI3R29KRU9EUWJVTzNNdTdkbmxuWkVXWEJWTHNkTzVZNVhoNWVvQ2lLQ0ROeitVUFQrL3pqclpTUXdJQTZ3OXBKWnpEMGF3ZnorZWVTYVN3bWNwWFpOVFZxcDY5WlliOGlCOCtPUjk2ZFV2eGFNRVlsR1dCTFdKS0JBM0o5MjR6VFdPS29YRFNuSzl1WUpBUUVnd1BONk5XN2UydWd6ZG1RUVN3UjRORHViTWI5cjhqRlZxSStBZllab3QrSCtuRDBhU3o1QnNxMzBCdnNndkFObWozZ2ZoUmgrVFNodVJKNUJZaUdBaGdoNkI2S0JBYXNXSDQ2WDcveWMxanJLK3g3QURZKzgrWEUrQWNJd3dSaVNZWjIrVXRJWjFBM014UmhBbWt6bG42ZmJkc2FSSWVpT0pXRERKQkR3NEQyMkxjWTltQjJEa0o2TXJSZ3FuTXpUWDJBYkJ5VWtGalN3dXgwQ1F5ZmptN1BEZU5oMDZEVUYxcDl2WnpHcHVXQVFBWVpNTUFNM0NFQTNUWlFzSFd1MXMvVU1mL1ZVZDF3U2IrR1FRMEdtRUdJUUFwZmYzUi9mdTNLRmR6bEFqTlFnR1lJSjIyQVpwdjQwT2Zod2pNRHp6M2RMdDI1eCtSbzQrcmx0aXdQSVhTNHAxM3lKMVB6UnJzRnFRVjFBd1owUzJNNEJFazdESkZsckJpTnhZdlA1NFZrVml6T2laQnNFZW1uZ0xNRTQ0RDRuaG9vRE03aUlBT0R4V2dVMFRoSkF0d2d3WmZqSlhkc0RTZTJDUGtJVkFNQk1CRFFERGtrZFU3RXV1K2lIcndhZUFtVG96Zmd3R0lGcUlmNEJLVlAweDlDNWpxOHVZNVE4RDNHSWNwUWxOQ2RXTW5ldmN2NDlyYyt5ckxPSWl2WHJtQ3l1SXpLRFJOZ1BLN0pYZUJjek1BZHNQc3h1NDJOUjRINzhaVGhGT29LTUVEZzdHQjBmQ3NSMkx2L0JJNVl0eGtMOEowYnI2TzNQeE1MRGtwa0RwcWswT2tnWXJDanJXTWo5KzNSVGRNTGV2VTRUSzhlZzdJRmJwQU5oQWhCV0FObWNNUnlZNlNBL29MWXZNeTMxemxlMld1NGhDWEdZV1pRTmY3My9ZcEx5NVoybFFGS2pOQUNCZWhWMENtRUFBZGl5WG5kYm5ycDF1bm1qOHBSemw3ZnNuYmR3TTU1djNyZGx2RG95UnNNR2pIWUFUUFQwRXF3Y3NLd0VGRXczQ0NIUUlUVjBleWlXdUFHRVViS0VIN2FBUW5NREFRT0dHQXNDWVlBQTVSOWF5Zlk2UWw3dW1TVTdScm1lSEI3L2FUYkIxUGQ1NUI3RzNETFlMczVyQTAyQVVUVWdBdFNzWkhzTDJiUGdSdG9IQ3h2QUZ0RHNLMFlNSGxjQzA4cnlMMkU2aHFMNHFBUXVyZ21pVVhCc1A4d3ZkWXJxUGJNc243bDFaejZIRmkyNWtKeTNzaGdIa0xnQ1F3UUlDQVZzREI3TGIzZWJsYXRoUkJQWVhiZkNnNnlDRlpBLzVFN0dlNituZEZUWU0yRzB4bHJIME52NWdCWC9lTzlQSHczZEVZNUtDbHcwTEdCY0NvWW9KRk9TK3pjbVQrOVk1ZTJyMTVoZER2RzJuRmpVSUVCQnBoZ1VJdDJhUnk1eXJoOXU1anRpUlBXOFJ5djdIZmRqSUI0VEREREczdjR6bDNEZld1bmpORldvaDJNSmtMdEVJRUE5SVl3VmpLKzZhajRmK2dxbkxaSk4yWEYxd3ptaFJWVURObmFUQU1tNmdYUnpCbXQwcEE3VlEycmxoYzBibVFYTVFuUHJPa05PYzZDaUlZSFdCQ3FCTWtNWTRtRXhZQWxvMTlsOVRtczdXYlQ5ZEEvVnJUdDlCaXRXMVhRc1F5SjY2NVpQSFVIenM5aWd4THhCb3lyZ1FJNEh2UUJ6S1p3UVZtQTVEeTg2eVlxd2ZJV2RPSUZNSElDc2QwRFFUVlloelZYZ0UxQm1BVnp6RWFBSTRFYVl6L1lES2s2RnpwWGNNSFBQa3puS0NDdHA5b2ZlWnlBd0NGeWlBa0NtZXlSMUxxZFhQV1kyUU5tSjVES2hEdFlnUGJZa01YWi80dEZpQ3VBQXo5Qk00UisvMFkybjdPTGRjZEJLamtveVFCak05QTFSQmJVaXl5dW43QzdqbDRMVDFwanpDN0FZQWhtUEVFd2tLQnFJRHNFQzc4STlxYzFqRWVFK0I1MzBXbUZYMTQybXU2cWMvNndBeGx3QVFZSXFneGpIVmE4OHFKd3hVbXJ3bW1QUGx5L2Vxb2REeVN6NVhValltM0ZpcmFXeis0V1FTS1pFVnFnaXNNRVRhT09qR3lvYUhmRmNORkdsQmtMTERFTGcreC9IY3cvVWdRN0tyc2lRZzRxWkhtMjBlNlcyWnh4U0xkcHZKMmQrd3JzOVRsRExBMEdrVVUxZHpRVHU2RGlHSkxOWTN3V3RBME1wUHVCUzhIT0JZRUU4NHQvUXRINk9LdVhRZjlSOFBaVGFZK3NZdmIrQllZek1QS2tmUlRsUG1JOEh4ek1RQWIxNE1zRXU1SlEzSUw3eTRpRDgwaGpzN2hWVE84QjkxdG90MnBTVE1oQUJqU1EvWE1VNVZmQmQ3TTQyRUlJbDdGbTVSeWpKWHppejZDdXR2UGNOMlI2L1VUVGg4WDlINmZWK1J1cUdhQS9UcTUrZ2w0RnFmVU5Mdno1L2FRQ0pBNUtKbG9XN0dRelF4SW1ZK2o2MW9ZanVOYk4yRGNMR0ppQmVKd0JKVEIwUVFyVzNiREMvcUFzd3B1R3RTWE1PY2pFZmhrZG9DUEFYV1BITEV2dm5lOWpjajVpQWVlN2hLaHFlOGJ4YThMN1d1dmlLZmZkblIvKzVqMzYwbk9lVHBoTWlneEFZSlY0YW94V0ZvVEtsVUVHQm5JSTBYN1pqSmNIVkFtYjJEL2pmemJSc3U4b1dkK3p1c2tnaS9ZZys1MmpJZDZKR1dZUWdleUJQWlhPM2RBTkZ3ZlJkVEVtK1R0YXBSOFJ6SjZSM2VoMHdmWTNmR2JmZWJkZGMrekxWbEZySTRPcURXcUR3QUtnQThCYndmOG5LUVZDNjFOVU01OWgxU1MwT3RBZnZaaWk5UUpNc0xodEdja2dObk5RL2pMS2QwQThoNUFYcVB0L0Q5MVBFRk9tR1hZSmNSbGlpVGFqWmdyM2FiSmRoL1JPeEcraFBFV0ljeWk4SDVwM0kxK2ticUEvL0IzV3JvVTdiempBby9mRDFCR3c3YlpQTTZ5T3BDak9vYW4rbGY3c0IybFBRUVI2dTA5Z1pPUmtIREQ3SnRVUXFpR1BTUmFZREdaUEZvY1p3a3lyK3hXL0dRd3JqRUk4cmhXTVpZS1Z3T2RkZk1oZDU4VEMzcmxxTXB4ZnUyZ2FVUVNqY3QwV3NGY1gwaXVhYUpmS1JSYTBJcU5sTjM1ZzZQNnpMbjBPN0NHRG84R2VFWU05blJERzZMblB6dWMzYlp6aW9lWkFYcWJ4c0sxVmhPWERTcGpaQmFYQ1I4ejBCb2M1bHJpelBKcTl2U3p0MGlvVE95MWpVR24yMFdtL3U3M0J0cmZhM0QrWXRaT3pZRFRaYTNwVm1CczI5cnV0a3NyTWtCaFBRYis0dmgxK1R6QmxCbG02eTR5M0oyT0YwQmFMUnIyWVNTVjNQYmpxS1YrYm1WdjNVOFRla1pnRDhkbTQzMDNPRUFPWS9SdVI2Mm0xQ3RBODFYNElVOUJVbXlsYjc4ZktaZVErTEgveVpSVERXNm1iL2VEVGlMZVQycU1NRm9iTTd4NnkraFRJZmpUVy96Z3huWXNERmk2aUdaNkM2ZDlvcFl6eHh6UzZpbVp3QkdPajkxT0gyL0RnWklkVytmc1U2ZTIwT3JEbm9ST3BkU1duUGczV2JOcEh0cmV4c0RCQ3F6WEh5Q1EwRGlIQi9QUkd4aVpYWVBWZWN2TVFNcjVmR2huVitvVjVPeTFFRG5GQTJIR2x3bHVpQWNaaHhpRXU3VFhaZlVMSGhFS1hFM2hhNWF5aWhtaEdBOVJaLytUR2I3am43OGo5RVN4ZUhDd2NEMktZUlRBcmtvWG51UGpKQUgyRHRvS2xnaVV5V1BSTEp6djZoMWdFRnFmWi84aDIvYzBKeDNOcVVaSnlBMlo2aGRBV0kveXJSTGRUOEV6SE5zdWcwektpYVdlS2VnbkdMUU1wRE9hNWNpVFl5YlVMaTJiZE12NUduWFdoWVZlRHVtWjJ0c3hPRzQxSzJhR1czU0RwSlJZMElOaDVZQWdEQndMM3JJcjdGcWs0RFV0Z0JqRyttZXgzSW4wUk04aUNmak5nY0dEQTdDT1FhNUM5aUZpOEQxdFlqOWNnUVdmaUV1cnA5K0xWSDVIQ3ZaZzUrQno5UGl6MGw3R09YNEQ4RmhwYmpzUWhSaUlXNzZZWi9nSXAzb1hVWU0zMXBCTG01MkZRUVh0cVBhM3d2NUMvRkRPWW1ZYlRudjNieFBZT2Vnc2ZZZDJ4TUt3eWcycWVsajJiT2grTDZ5OW90MFJhZlJHNUJ1VnY0SG9ZeFBkTHV3OXczbmhiSFhjd1FJSWlRcEZnV0FsM3NNQVE4WWpnOWliN3JrUVlpWVU5SDdOMUxoRUVqWERROVl0RGYzODBQdE5xQmM5QUkrMEkyWDhwcFhDNXNHTWRJUWx4U0JTTUdsQ1lNV2cwYmRhOHZvVSs3ZG53REowSWV3N29ZMnNhZjlycWtmaHp2VmtubTh6Z3pHRGhUQUVSRVlOUlpkRWZhdXRZbDFlbnhIV0d5QWZjTGR0Znh6RjdWdG0yOC9wOXNTU21aT2U0Y3c0WUJ6bEdQd3QzLzVjUXdwc3d0ZzFySm1JUm5obUNnYUFUS21ZMGRkdm45VHdvT1F2bU9VUmFUUXlYSS84WThGVmNEekIwR002dll6ZzRoYlhIUDVNbVA1TzhXQklUaDVoQk5ROTBmb0d5ZlNHZXZ3aTJDMjlFZC94SXl2WUZEQmVQQmtwQ0FuR1laN0I0Rm1YN004RGxvT3N3N1NhbWtybitNWGo5RkxycGVlREgwVGlZZ1dkb2pYYW82L2NTZURiRDNxMWtiMmlYeCtQMlhGS01pSjhtMkRpeFBBMDE0TnhNdGxtTUowamI5dG5aWnh4bkRPZmtCQlFDdzJHamhjVkswMld5bmdWbHllWXhUSEJjQ3VFQ0M0eldXVm5pM21TNnJ3amNPWmU1dnNxNk9zcjJTZUl4QnBpNGJ1RDV4UUc3TEptOTBNRlNNQ1J3aVNMU202bjFqd3VWM3J1eXhjMHNrVVJyTXREcEdpZE1zWkNDL2FxeXp3cTlNa1VyekkxR0FveGEwRTdhNDVXdTdBLzFKMlBkY0Q4Q0JLcEV1OVNPbk1QTDk4M3o1eE50UFNzUkdHWW9Ba2pnRWdtL1o5OVFIeTRqbDNlRDdSOVVqbUFDT0JXSlE4VGlQbHYrMmZ0MTNCYkU2WVFhQ0RYdWh0a2FpdUxOb05lUXduNUdDcU5ZUHNteUk4YUlSYUx1UTY0YlFpRVFoeGxnRWV4b1RLL2pvSnloMVlHUlNSak1DMUVUQWsra1FFeGJVSDRYaEJrSXM3aEtwcFl2dzJ3RXIxbmltRFdBRVNJTWVtQTJTb3pQUi81OFlvUUV1QUNEWUpjZ0IzT1dPSEFkUWZ4N2FmUHE4TUZxVVovRWFFQUt3Ulo3ZmVZWEt5MGV1ZEt5R3BzYVZrekdTTnRnQk9USXBwdEdNMkFMS1hFQW1IZlJ1S0JnaWZGRUJsbjZsc1Ava091S1lQYVVvZXVvRUd3WXBIdnF4cjllSzl6a01EUytUelNzTURvSkF1ejJyRGNPaC9udktzVm5XTkR4TFFpWXB0MTFpekpmazdUVnpES1BNU0FBQmlIdzRONDV2ZVRoUGY2VFc5YnlsTEpndzZEQ3pOaVpUTmVZK0hxV0hoTEc5RUpOM1lpVTdNQklhYThSZ1NBbEVvdGZxSjkxODEzOTQxZlE3YitTUU1aVkFZWmttTFdSdWhodHlnUWgxQmlMVklzRGpFeElnUE5FRFFnREVwQUlCcmx1eUUyRG1UQ1dpQitnSmdBZGpCSE1FcEtJY1FqMGFPb2haZzRZanpHV3lKQWlVQ0FIVVFNTkIwa1JjRVFiYkJhNGlSL2kvd0gzRDVQTXBkMnQ1UUFBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA5LTA0IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJFeGNlbHNlY3UgZVNlY3UgRklETyBTZWN1cml0eSBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDE2MDYwNzAwNSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4xIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wOS0wNCJ9LHsiYWFndWlkIjoiYjZlZGUyOWMtMzc3Mi00MTJjLThhNzgtNTM5YzFmNGM2MmQyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJiNmVkZTI5Yy0zNzcyLTQxMmMtOGE3OC01MzljMWY0YzYyZDIiLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gQmlvUGFzcyBGSURPMiBQbHVzIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjJEQ0NBWDZnQXdJQkFnSVFHQlVyUWJkRHJtMjBGWm5Ec1gyQ0JUQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVzRllFRWhpSnVxcW5NZ1FqU2lpdkJqVjdER0NUZjRYQkJIL0I3dXZac0t4WFNoRjBMOHVESVNXVXZjRXhpeFJzNmdCM29sZFNyam94Nkw4VDk0Tk96cU5DTUVBd0hRWURWUjBPQkJZRUZFdTloeVlSclJ5Snp3Ull2bkRTQ0l4ckZpTzNNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lESFNiMm1iTkRBVU5YdnBQVTBvV0tlTnllMGZRMmw5RDAxQVIyK3NMWmRoQWlFQW8zd3o2ODRJRk1Wc0NDUm11SnF4SDZGUVJFU05xZXp1bzFFK0trR3hXdU09IiwiTUlJQjJEQ0NBWDZnQXdJQkFnSVFGWjk3d3MySkdQRW9hNU5JK3A4ejFqQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVuZkFLYmp2TVgxRXkxYjZrK1dRUWROVk10OUpnR1d5SjNQdk00QlNLNVhxVGZvKyswb0FqLzR0bnd5SUwwSEZCUjlTdCtrdGpxU1hEZmppWEF1cnM4Nk5DTUVBd0hRWURWUjBPQkJZRUZOR2htRTJCZjhPNWEvWUhaNzFRRXY2UVJmRlVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQzNzVDFsQmpHZUYreEtUcHpWMUtZVTJja2FoVGQ0bUxKeXpZT2hhSHY0aWdJZ0QySllrZnlINVE0QnBvOHJyb08wSXQ3b1lqRjJrZ3kvZVNaM1U5R2xhcXc9IiwiTUlJQmZqQ0NBU1dnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBWE1SVXdFd1lEVlFRRERBeEdWQ0JHU1VSUElEQXlNREF3SUJjTk1UWXdOVEF4TURBd01EQXdXaGdQTWpBMU1EQTFNREV3TURBd01EQmFNQmN4RlRBVEJnTlZCQU1NREVaVUlFWkpSRThnTURJd01EQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOQm1yUnFWT3h6dFRKVk4xOXZ0ZHFjTDd0S1Flb2wybm5NMi95WWd2a3NabnI1MFNLYlZnSUVrekhRVk91ODBMVkVFM2xWaGVPMUhqZ2d4QWxUNm80V2pZREJlTUIwR0ExVWREZ1FXQkJSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QWZCZ05WSFNNRUdEQVdnQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBTUJnTlZIUk1FQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQkJqQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQXdmUHFnSVdJVUIrUUJCYVZHc2RIeTBzNVJNeGxrenBTWC96U3lUWm1VcFFJZ0Iyd0o2blpSTThvWC9uQTQzUmg2U0pvdk0yWHdDQ0gvLytMaXJCQWJCME09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUZBQUFBQVVDQU1BQUFBdEJrcmxBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQkhacFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1Tmkxak1ERTBJRGM1TGpFMU5qYzVOeXdnTWpBeE5DOHdPQzh5TUMwd09UbzFNem93TWlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwa1l6MGlhSFIwY0RvdkwzQjFjbXd1YjNKbkwyUmpMMlZzWlcxbGJuUnpMekV1TVM4aUlIaHRiRzV6T25Cb2IzUnZjMmh2Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOXdhRzkwYjNOb2IzQXZNUzR3THlJZ2VHMXNibk02ZUcxd1RVMDlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl0YlM4aUlIaHRiRzV6T25OMFVtVm1QU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2YzFSNWNHVXZVbVZ6YjNWeVkyVlNaV1lqSWlCNGJYQTZRM0psWVhSdmNsUnZiMnc5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBeU1ERTBJQ2hOWVdOcGJuUnZjMmdwSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE5pMHhNaTB6TUZReE5Eb3pNem93T0Nzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlNHbHpkRzl5ZVQwaU1qQXhOaTB4TWkwek1GUXhOVG96TURveU55c3dPRG93TUNZamVEazc1cGFINUx1MklPYWNxdWFnaCttaW1DMHhJT1czc3VhSmsrVzhnQ1lqZUVFN0lpQjRiWEJOVFRwSmJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qSkZOekZDUmtaRFF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2pKRk56RkNSa1pFUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJajRnUEhodGNFMU5Pa1JsY21sMlpXUkdjbTl0SUhOMFVtVm1PbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWtVM01VSkdSa0ZETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlJSE4wVW1WbU9tUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNa1UzTVVKR1JrSkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUx6NGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NDc3SlhGQUFBQVlGQk1WRVgvLy84RVZxSVhaYXZHMk9vcWNMRzJ6T09rd3QwQlNKdHFsY1hWNHUrYXV0bFdoYnprN1BVQU1ZOUhjcktqdE5icThmZUFsOGFCb3N6ejl2cGRqc0dHcXRGM244dVRzTlNacGM2SnNOVDUrdjB4WUtudThQZmY1L0w0OGZnL2ZyaWN6SmdZQUFBREFFbEVRVlI0MmtSVUNaYkRJQWpGWFpPWTFUYXROYzM5Ynprc1NZYzNyNE1FNGZNQkFhRDZ6bDh5LzlUT2dldDhkNWpmTjc4YndNL2REQ1JwUjUyMXpYZm9qSEowNUlJeWhCQVVTVkFPTmRHekJZdDJmN0tGcmZrSmFBa0hoOUZaaGNEWEhSa1RLbzlNTGloR2FhdkltblYzcXlFWDBFcHJnei80RHdVRDdrQ0hSbmQ4UUZONDNHbzRVVm1ERGd6YTR3MjdvaXpkQTIrY0srdXVVcGpqbzIreHdjLzQyVzUweDVMR1llREJzUjBIVkl4NXg4aUY2MENibGJURUVrRnIyN2JOREJVVlNxMU9LVlBiRTYyYjNFSDhGcUJnNU9PT0V1YzJ0OFpKaXFNT3VHcCtjS2pnN3dWR2Nlb3pxTjRweGdWUFFrakZZZ2JWSktEVWhEQ2pZcmF3UDVxNEVUZ0M5ZklNUkh0aXRwUWNDdkpPRUxjYk1zUWduY2lSa2xqcHlRanZHNDRqcUJVRVRGaUJpMVBFSXlla096c1crVHk1Y0xIb3M1UitkTVMxTHRTU3hmM2dRSGN6UjJDSTRnTU5wVzRJUkExUU1hNnRKNCtDNnVIdUdFOG1OREl5RnFnL09QL01NVXVlUzZJcThTOTBkQWVCSlNFeS9xS2tLK0JOd3o4Y1lZNGpiNUo2dTRpV0NJMkIxWjU2TFc1a0VjNGhrZE1wc3ZVQzU1ODVTWDBRdWJjZ05xeWZnREZFY1R0KzQwLzBTNU54MHdhQ3czT0trY09iQTVJbjBBWXAwMXBqancybjYyNlVEanRId2EyOGlIdVRLcXRydityZVc0MU5aNmlHbHI3dXVMSkNma0Z0Y3RjRzA0c2dtMWVOUytaYURucGFURXJHb3lYNUpLMmlNejh4czBuT3dXR2NQRE40OXFhQ2Q0YnpKb3pEWm0vYUJLK0Vvekx3K1hoTkJpWXdIZjBzaU91MVhQa0cvekt3dnFZS2NmU3dERWNIL29VZTA3ZXMvV1E4ckl5ZzJET1hqOHRqa1pkdURCL2I4aHpEbGxNTU9DUzVCRW5kNTM0Zjh0aTNVWmM0a01zM3hMeWFmTVNzSmhkRzhYUHFqTms1dEFnTzI1ZmVLQ2huVmREai9KMEZNa09zVS94TUJ2MHdGaFllRUdmVkgxM2Z1RFUweURGTGE0ZmM3Um5XSEJmdVRGVjJ0RW1Od2FkYzdhYzNVWTJqZkJsN0hUMzZmZTM0aVFPNW1OQ0ZGQlcwN0tqUGdxaE9MVTAxdlo4UHVlWjJKQ2xGWk44amtVczY5dWthOWVQcDYrRWZMNEFGNStOeXdTYmlySHRjQjhNbC9na3dBRWprSzY0S2pIUGVBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImI2ZWRlMjljMzc3MjQxMmM4YTc4NTM5YzFmNGM2MmQyIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwiZmlybXdhcmVWZXJzaW9uIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDktMjkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkZlaXRpYW4gQmlvUGFzcyBGSURPMiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxODA5MjkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4yIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA5LTI5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0wNy0zMSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImZmZjk0MGQzNTc5YmM0NDA0MDU1NzQ3YjM2NzBkNDNhMWU5N2QwNTQiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiZmZmOTQwZDM1NzliYzQ0MDQwNTU3NDdiMzY3MGQ0M2ExZTk3ZDA1NCJdLCJkZXNjcmlwdGlvbiI6IkJsdWluayBLZXkgVTJGIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDelRDQ0FuT2dBd0lCQWdJSkFNK2ExMlZ6bkN0R01Ba0dCeXFHU000OUJBRXdlekVMTUFrR0ExVUVCaE1DUTBFeEVEQU9CZ05WQkFnVEIwOXVkR0Z5YVc4eER6QU5CZ05WQkFjVEJrOTBkR0YzWVRFVE1CRUdBMVVFQ2hNS1FteDFhVzVySUV4MFpERVRNQkVHQTFVRUF4TUtRbXgxYVc1cklFdGxlVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR2hoYldsa1FHSnNkV2x1YXk1allUQWVGdzB4TnpBMU1URXhORFEzTlRkYUZ3MHlNREExTVRBeE5EUTNOVGRhTUhzeEN6QUpCZ05WQkFZVEFrTkJNUkF3RGdZRFZRUUlFd2RQYm5SaGNtbHZNUTh3RFFZRFZRUUhFd1pQZEhSaGQyRXhFekFSQmdOVkJBb1RDa0pzZFdsdWF5Qk1kR1F4RXpBUkJnTlZCQU1UQ2tKc2RXbHVheUJMWlhreEh6QWRCZ2txaGtpRzl3MEJDUUVXRUd4b1lXMXBaRUJpYkhWcGJtc3VZMkV3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVRtQkFJQ1NMYm5SQWZtYWdiN0dMc0RKUWtIUFM0czI2RDhyTndpZ3RHOWhVYy9uQzZkeDFNejI3ZmFobnhrbXU3cTVURHdzWnI3Wlo2UGdBc1dVWnZZbzRIZ01JSGRNQjBHQTFVZERnUVdCQlQvK1VEVFY1dkVRRUJWZEhzMmNOUTZIcGZRVkRDQnJRWURWUjBqQklHbE1JR2lnQlQvK1VEVFY1dkVRRUJWZEhzMmNOUTZIcGZRVktGL3BIMHdlekVMTUFrR0ExVUVCaE1DUTBFeEVEQU9CZ05WQkFnVEIwOXVkR0Z5YVc4eER6QU5CZ05WQkFjVEJrOTBkR0YzWVRFVE1CRUdBMVVFQ2hNS1FteDFhVzVySUV4MFpERVRNQkVHQTFVRUF4TUtRbXgxYVc1cklFdGxlVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR2hoYldsa1FHSnNkV2x1YXk1allZSUpBTSthMTJWem5DdEdNQXdHQTFVZEV3UUZNQU1CQWY4d0NRWUhLb1pJemowRUFRTkpBREJHQWlFQTVnZjQxelFKQ2hjRFpmRXBqMHhTcGJndlhVeUxwaDJTdFJFekVLZDNSeGtDSVFDNmlTbWpLQ0srT3ZwQWR3bjFVa29MTjQzbnZZN0R0QVRWRGM0UGtXMDR2dz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUhnQUFBQjRDQVlBQUFBNVpEYlNBQUFBQm1KTFIwUUEvd0QvQVArZ3ZhZVRBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBUUZrbEVRVlI0MnUyZGVYUVVWYnJBZjdYMG1rNDZJUW5MZ0d5eUNnU01LRkVFbnd2d2RNWlJSRUY5S2lMRGUvcGNSa2JrZ2FLamdxaU1Db3JqT0lJZ3VEOUFSTnhHa0cxRVZqa0lBV1NSVlFJa2dheWQzcXJyemg5SnhqV2Q2cEIwMGtWOW5NUGhrSHNxZGU3dmZ1djk3aTFKQ0NHd3hMUWlXMU5nQWJiRUFteUpCZGdTQzdBbEZtQkxMTUNXV0lBdHdKWllnR01Vbno5b3piYVpBZC85NUN6OHdaQTE0MllGdkg3N1hxYk5YV0xOdUZrQjIyMHFqLzMxSGVaL3VNcWFkVE1DRmtLUWtwekVINmZONGRzRFI2MlpOeHRnWFlDdUN6Uk41NXI3bmlhaTY5YnNteXROcXR4MlZoU1pnM2tGREwzL0dheXRhRE9aYUYyQVZQbHZ0OVBPOG5YYmVPR3RqeTBDcGdHTStJa3UyKzAyeGo3OUdpczI1bG9VekJKay9WeFNVanpjTW5FR0JVVmxGb25FQi96TC81TWtpZEp5ditXUHphckJBS3Fxc0RGM0g3Yys5Q0lXWTVQNDRKOUxrc3ZCd3VYcldMaDh2VVVrWWRNa1BicDJPMngyYnBrd25YWGY3TEdvbUUyREsvMHh1SndPYmh6L0hBVkZwUmFaUkFPc1k4ekJGaGFWczJQZllZdE13cGxvZ3dHVUpFbm9WclJsbmlqNjExYUNybHVBRTFDRFJYV2xzblp6Ym1sd0F2cGdBUmhCTEZYVnJTMHhwNGtXbGdZbnFJazJHbVVKMElXMVY1eUFHaHlyT2JmRXRGRzBzTG85RWhTd29SaExzdEtreFBUQnhqMjF0WFdZaUJxTWNXZ1JTNE1URUxCdVBJcTJORGdoTmRpZ1NNSktrOHdkUlZ0cFVuMktHamZ0amFXUzFZQnAwdkhDWWhSRlJsVVVISFlWaDgyR29zZ1c0Tk1sYkJTWkJBM2FtOVY3K0Roc3Nvek5wdUoyMnNsTTg5TCtONWxrZCsvQXhkbm5rTjI5Z3dXNFFWTWYwWkFhTEFnRXdnUWxnUlNBNGpJNGZMeVE5ZHYzTU8vRGxhQUxtbWVtTWlpbk56ZGRPWURzY3pyUUtpUE5BbXpJL3phUjdVSlJHYVpUWFhWUlpCbkZMdU8wMndEd0I4TXNYckdCeFNzMjRuRTV1YUJYSng0WStYditvMjhQSzhpS3JzSEd4emRtSlV1V0pHeXFpazFWQ0drYVgyemN6cVVqSjNIeHlJZFp1L1ZiZ3FHd0JmalhOTmhvb2FNcFZiS0VFTmhWRlc5cU1sdDNIMkx3blpNWk9PcFJ0dXphYndIKzZVVEZvTUZTMDl3UFZoVVp1Nkt3ODdzam5IZkRPQ2JNZUpOU245OENISE1lTEdpeW13MkN5dU92WHErSEY5LytoTDRqSG1SajdsNExjS3htTnhFNk91dzJsUk5GSlZ3OGNoSUxscTAvd3pVNEJoOU1BeGM2NmxNa0pGd09CN2RNbU03ZFQ4NDZjd0hyMVdxY0FGRjB6SkFsY0x1Y3ZMcG9HZmRQbTl2a3JFLzhORmcwRFEwV1FpQkVaWU85SkVuMTlzd2tsNU9YMy91TW04WlBiMUtRNHhaRng1SUlSeHB3Z2pxMWJVbWJGczN3ZWx6WVZKbUlyaFBTTkxSSWhOUDlyVWt1SngrczJNamt2eTlvT3RGL2ZJSXNnUzVBTmxETGtocFVneVhXdlRHVlNFUW5GQTdqOHdjcExDN2pxMjkyczJqWmVsWi92UU9oQzVLVFhIWFdaSmZUemhOL1gwQ1N5OG00a2I4L013QlhiU2MxQ1JOZFhaSk1jamxJUy9IUXBrVTZmYnEyNTMrSEQrRjRZVEV2dnYwSjczMzJKY2NLaTdHcFNwM011RGZKeldOL2U0L0wrL1hpM0c2TnUzblJOTk9rUmdxeVdtYWtNdlcrbTlueTNyUE1mdnd1VkVYQkh3d1JLMkpkQ0NSSll1ajl6eENPNkdjQVlCRlRFTjNvbDZSNWs5M2NmT1VBRHYzakZZWmVkZ0VoVFl1NWZLcklNa2Z6aXhqMXlNd3pKSXJXRXk4UDlyaWR2RHZ0VDh4LzhqNzhnVkRNbHNYamRySms1U2ErM3JuZjVCcGNGV2dadFhWTkxROGVka1VPbTkrZGhzZnRpTW02aUtyMDhKNnBzOHdPT0RZYlhkOG0rbVJKR1R2MkhXSFRqbjFzMzN1WS9GTWxNVDhqcTBzN3ZucnpLWncyVzB6dnB5b0s2Ny9adzV3UFZwZzNpdFoxNDlwYkh4cGNWT3BqNis0RHZQWFJHcjdZbEV0ZS9pbENnUkRvT3NnU3F0MU9pM1F2QTg4N2g1dXZHa0JPcjg1a3BLWFUrdHoyclRKWk0yOHlBMjZiaEJZRFpHOUtFcysrdm9RYi83TS9icWZEaEhsd1ZmVW9Iajc0cWRudjgrcWlaUlNjS2tVZ2tHVVpwOE9PeTJIL3lialNjajlMVm01a3ljcE5wSHJjREI5eUVkUEhqNnIxK2QwN3RPR3ZrOFp3NDUrZXhadWFiUGk5RGg4dlpQT083eGg0M2psbWpLSmowOGk2bU9nZDN4MmgxN0N4UFBUQ1d4U1YrbEJWQlp1cW9zaS9YbDZSNVI4Nk55cUNJV2ErOHlsdEIvOFBYMjNkWGV2dkdqR2tQL2ZkOWp0Q1lTMm1UT0w1TjVhYTB3ZkhWSnVWWWpmUjg1ZXVJdWVXaVJ3OFdvQTNKYWxPQzlEamRsSlU1bVBJWFUvdy9QemFRVHg2NXdneTAxSU1leDZicXJCMDFXYU81cDh5cHdZMzFIYmh4MnUyTVByUEwyTlRsZFB1YjFaa0dVVldlT0NwMlR6OTJ1S29ZOU85SGlhTUhrcHhtUyttZVpnYjUyQXJmaWE2QVh6dzZxOTNNSFRzTTdpZGpucE5yYnpOdkV4K2RTRWZydG9jZGR4ZHc0ZlE0K3l6aUJpc1ZubVMzSHl5WmpOaExXSXl3UG9QYmFxR2ZMQUJrMTVjNW1Qa3d5L2hkanJxYmR2dnArbU56TTNqbjZld09QcFZ4NC9jT2R6d2dsUmtpZjE1QlJRV2w1b0xjRXcrV0JnTHNtYSs4Mm1kOGxuRG9ZQWtvUU8zVDVvWjFUcGMwdmNja2owdVE0dE1DSUhQSCtUNzQ2ZE1wc0ZWZnd6cG1RUjZKUHFDS1BVRm1EcHJJVFpWYWREM2R0aHQvSFBMTG5ZZnlxdHhUSXRtcWZUcDBzNncyWTFFZERiRnNWRXZUaWI2MzhwcFVPT2phL0J6ODVZUUNtc05ZcHAvcm5GaExjS2N4U3VpYURwY05iQXZ2Z3EvUWNzQUczTDNtVE1QTm9vajJnbi9RQ2pNaDZzMjRrbHl4NmNTcENpODgvSHFxR01HNVdRWm4zQkpKbmZmRWJQNVlMM2VLbGtuaTB2Snl5OUNibUR0L1hGQjVHaitLYlorZTZER01kMDZ0aUhkNnpGVTBKRWtpV1A1SjgybXdURXVpQ2lBQzB0OCtBT2h1Qjl2V2I5OWI3U3dnYk5hWlJoSzFTUUpTc3JMOFFVME13RVdNUUt1ZWZ5eC9GTng3MXBVVlpYOTMrZEhIZE82ZWJxeDk1SWtncUV3cFJVVlppdDB4SExMVHMwYTdLdnd4MVFWcXg4ekxWUHFpdzRreGVNMkZFWldIM0FQeHVsVHUvSHh3YnBBU1BXajhZcWlRTno3QVFTcW90VHFXMk12L3BnRXNNMm14akFCVXRRenVNMVNrNUZsS2E1NHcxcUVsdW1wVWNmNC9BRkRlWUtvOHNOMmg4MDhnRk9TM0NpU1pFanhKQW55VHhiWCtQUGZaS1NoS2dwU0hCa0xMVUt2em1kRkhYT2lzTmpZSWhaZ1V4UlM0cFRteFFXdzErTWt4Wk5rS05pU0pabURSMC9Vck1GZVQ1Vy9pdzloQWRnY2R2cG5kNDg2N2xEZUNVT3BtMENRN0hHVDdMS2JCN0FzUVhxYTF4aGdXU0x2WkNuSENvdHFCTnk3YTN0Q29maWtHWkZJaEl2NmRDSERXM1AzeHZjblRuTDhWSmtoMXlGMFFXWjYvQzUyaWRzQjhPNGRXaHZlMHRQRFlWWnYybG5qeisrOFlUQVZjVW96aEM2NCs2YmZSaDJ6Y2xNdVFqTzI0SFFoNk5hK3Rma0FuOS96Yk1QNXNOUHRaT25xVFRYKy9Lb0IyZlRyM1JVdDByRDdxaElTNlduSkRNcnBGWFhjeDJzMjQzUWJPODhraE03NVBjNDJIK0IrV1YwTmx4Y2RkanZydnRsTmNWbk5XanBqd21pa09xUW5zVWh4V1RualIxMUxhbkxOYlVCRnBUNDJiTnVMdzI0c0twWmttWDVaWGN3SHVIUGJsamdjTm1QUnJ4RGtGNVdTRytVTGFEbTlPblBENElzb0tXOFlVeDBLUjdqdWloenV1ZkhLcU9PMjd6MUVRWEdab1VLT0pJSExidWZzczFxWUQzQkdhZ3F0MGxNTkY3U0VnR2ZtUk8rTG12UEUzZVJrZFk2cHU5R0lhSkVJclZ1a01mZUplMnBON1o2YS9iN2h3b3N1b0hWbUtwa0dlckFURG5DU3k4SEF2ajJvQ0FTTkZVZFVoWTlXYldMMTVoMVJ4MzMwMGtOMDc5Z0duejlZTDdseFdOTm9udVpsN2J5cHBIaGNVWk94THpaczU3TXZ0NkFhYkR6dyt3TmNjbjdQWC9Sb213SXd3QjNYWGtvNGFQeW11R1NQbTNIUHpZK3FvYzFTUEh6OTdqU3VHbkF1d2FCVzUrWTdJUVRCVUpqZVhkcXo3ZjNwTkcrV1Vvc0oxeGcvL1EyU1BjWUxGdUdReGgzWFhoN1BLWTh2NEw0OU9wSGRvNlBoTGtSWmx0bjUzUkhlL3VTZnRZNWRQT1AvbUQvMVBwd09sZEp5ZjFVVWJFektLZ0xvdXM3TWlYOWd4V3VQNDNIVmZyemtqWS9Xc0d2L1VXVFoyQlJxRVozemUzZW1UN2YyY1FVc2lUaHZyTDc3MlZydWVQUmw3RGJGc0dZRmdpRnlGNzlBNTdZdGEvZHp1bURLcXd0NCs5UEtVL3BhV0t1cS8wcVZPem44c0psaFV4VXkwbEs0K3BMeitQT2RJMGd6MkRTLysyQWVQYSs3UDZhT3puQllZKzZVZXhrKytFSnpBejVaWEVidkd4N0E1dzhhem90MVhhZGxSaHBiM3ZzTFNTNm5JVi9yOHdmSXl5L2k2MTNmc1dYbmZnNGNMY0RuRCtCeTJtbmJLcE0rWGR0eGZzL090RzdlREs5Qk15dEU1WE96UjR6amVHR0o0VTBQU1pMd3VCeDhzL0I1bW5rOTVnWU1NR0hHR3p3N2J5a2V0OU80L3dwSDZKZlZpVS8vTmdtSHpVWmpTREFVWnNoZFU5aVV1eSttanM0eW41K0pvNGN5NWQ2YjQvN09qUUpZSUdoMTZXZ3FBdUdZdHY1Q0lZMnNMbTFaUFhleTRjSkNmY0lkT0dvUzIvY2N3VzQzZmloVDEzVThiaWQ1WDh4dWxFWFpLQjhya0pDWU9YRk16S1ZHdTExbDI5N0RuRGZpUVk0Y0w0emIreDQrVmtEMjhISGs3b3NOYm5WdzlkSkRZMmdzYWJTdlVWeDcyUVZrZFdrWE8yU2J5c0ZqQldTUGVKQlhGbnplNE8vNXlvTFB5YjV4UEllT244U214Z2hYaTNCdXQvWmNmVW5mUmdQY0tDYTZXdlllT2tiVzlXT3gyMngxcWltWGxKUXgrT0pzcGo4NGl1NGRXOWZyMVlRNzkzL1AyTCs4enJJdnQrRDFKdGZwR1dGTlk5dkM2WFF5RVAyYkVqREFvdVViK0s4SjAzRTVIWFZxaGRVaUVSUlpvWCtmTGp3ODVucjZuOXZ0dE43bnl5MjdtRHA3RVd1MzdpR2lSMnJ0eGFvcGFnNEVncncxYlN6WFhkYXZNYWUzOFFFTEliaDE0Z3Y4LzdKMWRiNi9RcElrUW1HTkNwK2ZubDNiTWVxYXl4aDBZVzlhcEh0SlRuTGhkTmgvVWZRUVFDQVlvcXpjei9GVHhTeGZ2NDI1SDZ3a2QvY0IzRWx1N0RhMXpyM1hGWUVRSTRaY3lQeXBmMFNDTXhzd1ZHNkNYMzN2VkZadTNJSGRkbnJYaGtSMG5VaEVSMVVWUEM0bm1Xa3B0TWp3MHJ5WmwyU1hxNnB5NVNmL1ZBa25UcFpRVUZSS3VUK0Fwa1ZRRkJsRlByMndKQmpXdUx4ZlQ1YStPTEhCejA0bERHQUIrUDFCTHJydElmWWNPbmJha0grczJib3UwSFVkTFJMNWQ1MWFsaVZVUlVHV1pXUlpxcmRURXFHd1J0ZjJyVmc3ZnlvdXA0UEd4OXRFQVA5ZzJvSmNjc2VqN05oM3BONGd4eTFQRG10a2RXckx5am1QeC8ycXBDYVpKdjJhdUJ3T3ZueDlDbjI2ZFNBWVRKenZFd1dEWWJLN2RXRDE2NU54T1J4TjZ0MmFGR0JKcWp4MHZYTDJZNHdaZGdXbHZvcTRuU0tzMCtSSkVxVytDc1pjZndVclpqK0cwMjZqcWIxdWt6TFJQNWRuWDEvQzVGY1gxVGxkYVVpcFRzOG0vZmN3SHJ6OW1pYTdDSnMwWUlCdkR4emw5a2RlWXNQVzNYamp2Qk5UYzRHbG5BdDZkMkhlbEh2cDFxRjFVNTYrcGcrNFdxYk4vWUFaYjM1TVVaa1BleDF2WWovZGZEMmtSVWhMVHVMK1czL0wrTnV2VFlqNElHRUFBeFFXbFRMci9lVThPV3NSRllFUUtYWDh0a0tzVXViejQzTGFlWGpNTVA1dzNSVnhiWm83b3dEL2VNS2Zudk1CQy82eGxtT0ZSVVIwVVpYWDFvOVc2N3FvOHJFU0xUUFN1SDVRRGhOSER5UEY0MHEwcVVwTXdOVlNXdTVuNytFODN2eG9EWXVXcitkSVhnRW9NbTZuNDBjZjFCRDgyblhWMG8vK3FyNU5weUlRaEloTzYxYVpYRDhvaDF0K041RE9iVnNaN3Zpd0FEZXdiTm0xbjgrLzJzcjY3ZnM0ZURTZmt5VmwrQU1oTkYxSDEvVWZidnVScEtwN0tTc1hRMnF5bTQ1dFdwQ1QxWVVoL2ZzMCtwZFNMTUFHeEI4TTRmTUg4UWVDaE1JYS9tQUlyYXFiVTFWbFhIWUhkcHVDeStrZ3llV0lhNit5QmRpUytpdkdXRk5nQWJiRUFteUpCZGdTQzdBbEZtQkxMTUNXV0lBdHdKYVlSZjRGME1NbDY1M0lZS3dBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTAxLTA3IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJCbHVpbmsgTHRkLCBJbmplY3RvciwgVTJGIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAxNTA4MTEwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wMS0wNyJ9LHsiYWFndWlkIjoiODUyMDM0MjEtNDhmOS00MzU1LTliYzgtOGE1Mzg0NmU1MDgzIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI4NTIwMzQyMS00OGY5LTQzNTUtOWJjOC04YTUzODQ2ZTUwODMiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBGSVBTIFNlcmllcyB3aXRoIExpZ2h0bmluZyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg3MDYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6Ijg1MjAzNDIxNDhmOTQzNTU5YmM4OGE1Mzg0NmU1MDgzIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiIsImxpZ2h0bmluZyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sIm1pblBJTkxlbmd0aCI6NiwiZmlybXdhcmVWZXJzaW9uIjozMjg3MDYsImNlcnRpZmljYXRpb25zIjp7IkZJUFMtQ01WUC0yIjoyLCJGSVBTLUNNVlAtMi1QSFkiOjN9fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wyIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDMtMjgiLCJ1cmwiOiJodHRwczovL3d3dy55dWJpY28uY29tL3Byb2R1Y3RzLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSA1IEZJUFMgU2VyaWVzIHdpdGggTGlnaHRuaW5nIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzAzMjgwMDUiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAyLTE4IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZSyA1Q2kgRklQUyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwMTE4MDA1IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAyLTE4In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMy0yOSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImQwMDJmNGMwYTg4YTdjMjdkNTIwMWM2YTUxYTBlMDU0NmI2ZDhmNzUiLCI2N2VmMGY0YzM2YjUxNzgwYTNmYWNjMGE5MjMyNDU5M2FiMTk2Njg1IiwiYjk1MjA2MjI4ZWFkNDkyYjllMTQ1MDRhYmVmY2IyMDU0NmIwZTUzYiIsIjliZThjODZmM2I3ZGE5ZjUwMjZhNTY2MDdiMmI5M2YwZmZkMDU4YWUiLCI3Mjk1NDk5NTMxYzBmYjA1OWQ2Yzg4ZDFiMjk2NjU1NDc3NTdjNmM2IiwiZWE1NDQyYzljYzU2ZjY0NTZkYjUzNDRiMzY5Njg5YzY0N2E3YTFlMSIsIjA3ZTQ0YTdjMmU3ZTBiNjA1NGMwMjkyZmJhNjkxZWViZmRiNDgxYmQiLCI3NWQ5MjY2YTc5NTk5ZTljYWM2MDRhYzJiZTNmMDNhMGYwNDQ0ZDc0Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImQwMDJmNGMwYTg4YTdjMjdkNTIwMWM2YTUxYTBlMDU0NmI2ZDhmNzUiLCI2N2VmMGY0YzM2YjUxNzgwYTNmYWNjMGE5MjMyNDU5M2FiMTk2Njg1IiwiYjk1MjA2MjI4ZWFkNDkyYjllMTQ1MDRhYmVmY2IyMDU0NmIwZTUzYiIsIjliZThjODZmM2I3ZGE5ZjUwMjZhNTY2MDdiMmI5M2YwZmZkMDU4YWUiLCI3Mjk1NDk5NTMxYzBmYjA1OWQ2Yzg4ZDFiMjk2NjU1NDc3NTdjNmM2IiwiZWE1NDQyYzljYzU2ZjY0NTZkYjUzNDRiMzY5Njg5YzY0N2E3YTFlMSIsIjA3ZTQ0YTdjMmU3ZTBiNjA1NGMwMjkyZmJhNjkxZWViZmRiNDgxYmQiLCI3NWQ5MjY2YTc5NTk5ZTljYWM2MDRhYzJiZTNmMDNhMGYwNDQ0ZDc0Il0sImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IFNlcmllcyB3aXRoIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSA1IE5GQyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTEwMDIwMTkxMDE3MDA2IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjEuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNS0xMiJ9LHsiYWFndWlkIjoiZDgyMWE3ZDQtZTk3Yy00Y2I2LWJkODItNDIzNzczMWZkNGJlIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJkODIxYTdkNC1lOTdjLTRjYjYtYmQ4Mi00MjM3NzMxZmQ0YmUiLCJkZXNjcmlwdGlvbiI6Ikh5cGVyIEZJRE8gQmlvIFNlY3VyaXR5IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnh6Q0NBV3lnQXdJQkFnSUNFQXN3Q2dZSUtvWkl6ajBFQXdJd09qRUxNQWtHQTFVRUJoTUNRMEV4RWpBUUJnTlZCQW9NQ1VoWlVFVlNVMFZEVlRFWE1CVUdBMVVFQXd3T1NGbFFSVkpHU1VSUElEQXlNREF3SUJjTk1UZ3dNVEF4TURBd01EQXdXaGdQTWpBME56RXlNekV5TXpVNU5UbGFNRG94Q3pBSkJnTlZCQVlUQWtOQk1SSXdFQVlEVlFRS0RBbElXVkJGVWxORlExVXhGekFWQmdOVkJBTU1Ea2haVUVWU1JrbEVUeUF3TWpBd01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXJLVUkxRzBTN2E2SU9MbG1IaXBMbEJ1eFRZanNFRVNRdnpRaDNkQjdkdnh4V1dtN2tXTDkxcnE2UzdheVpHMGdaUFIrellxZEZ6d0FZRGNHNCthWDY2TmdNRjR3SFFZRFZSME9CQllFRkxaWWNmTU13a1FBR2J0M3J5elpGUEZ5cG1zSU1COEdBMVVkSXdRWU1CYUFGTFpZY2ZNTXdrUUFHYnQzcnl6WkZQRnlwbXNJTUF3R0ExVWRFd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ0cyL3BwTUd0N3BrY1JpZTVZSW9oUzN1RFBJcm1pUmNUanFEY2xLVldnMGdJaEFOY1BORFpIRTIvelordUI1VGhHOU9adXMreFNiNGtua3JiQXlYS1gyem0vIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUkwQUFBQVdDQVlBQUFEOS94OGxBQUFBQkhOQ1NWUUlDQWdJZkFoa2lBQUFCM0ZKUkVGVWFJSHRtazF5MjlnUngzOE5JdExTekFuTW5NRE1Oa21WNmFxcHluSjRBOU1uTUNTU1ZhRzBNTHdRc1JCbHdTY1FkWUtSVmxtbFJHNW1HK29FUTUwZzFDNVVTSFFXai9oKy9OQkV0bWNtK3E4SXZFYS9ma0Qzdi92MVk0Vk5PQXhhL1BtN0tqLytZMW9hOC93cWYvbnIzL25UZDNmVzhXZjhadUd1SFduM213Z1h3QnZyZUdVdkJCcEFnOFBnSFo5Nnd5OWk0VE8rTGRyOUppS3ZWbGRqQnIyUll4WHNudFNCaXcyS2hvaThUYTRkTGpnTVdrOW82ak4rQ2VqMFBVUm13QmlKcm9tbzBRa2FaYWZwbnRTSjVBYVI2Z1pGYjB2M254M25Od2lwTXVpTlVCMmlFbEtKSnFEMWZIcnkvQ29xRjJzZHhqakYrZG81ak9Pd01WVmw2VTZpYTA2UEo3bnhUdEFBWHErdXhpeVk0cEk2NldMK21kQ2Y1WjdwbnRSUjUvdFVoa3QrRjFXSjVCVWl0WklOcWxPV01pYnNwYlZZcCsrQnZGaHJkNnczN0UxTllGVmVJMnA1VHpKaDhlOXh5Y1o0YlNxdmNzK0pqdmlQM0NXMlBNYU9HRjVRbzZLdlMyc1ZIWEY2Tk1ienE3ajc3ODNhWmNiWjN6N241THlnbHJ6amlMdmsrMFdZT1VTcXFOWVlIRS9vQk0yODA3aDdWeUQxekoxckJyMVJzdUJTeXRJRFZGb0lyNUpiRGhlMCt6UE9qcTZzQ3hZOFlxZFFSNEJKUWFJQmZGajkvZ2p6RVBZUEFQTWlLM3QvQVBLTUZvbUhKSTUxRC9QUDZONFFrZGZZSUdLcXVWd3RKdXVESVliTEdKaWlFaUpxMTQxQ1pXL0dZWENRNk82ZTFJbWNINEFhb2dWeEFWZkhxM1Uvemc2QWRoQWl2QWV4bUNMUUNlS2ExRGZxRlNEdk5DNjFaTnpSTVdEc0Z1cXJKUTFCakhPaHN6UTl0ZnREeUx4azVaYkZ2SlVzV3ZXSGdra2ZHUnlGTE9jTmxOdkMyTVdxTHZyZllTSTJUSzVGM2hyalYvQ0NXaTVkUm5qV0tMZkI0U0tuNjZrZ1VrWDBITTgzakJMSkZjTFR6OU1KZk9Nd1h3aExRdHBCQ1BJVHlFKzR0Rmc4REEzVEhBYXRUS1FhaDFuT0c0VCtETSt2bG1vYzFVdk9qb3huR3BrR2xmMVJ3amdpVlpRTDRJOVBZdnlnNTlQdXR4QjVDVUFGRC9ETWIvV1RLRk85NDlOUk9UV3FYaUlTVTI0Tko4T1lEZzNpeUVvZk9BQXBNaUFzNXVWN1dkMVpsaFNwNHU3WGdWRmk5enJkb211Y2ZJc2RTak1oR05VN0lDNWM4N0xHanNmRHBFQ3ZlTnMxa2FybkdYcTdaMGt6aVZaM2Z3aGtjL2MxWjBjcEE1MGVUNnlPZzlUcEJENkRudit6REM1Q3hWKzFBQUI5aStmN3NGL05PYnVJdlJBWG1TWnBGcURUYnlXczZ0Z1lRQ1k1K1UzSTZ4N1JEcHE1ZEYzRVFxNXk5Y2htNVp2dHlNNGowbG9yMndsMm0yNUh1RlRVejdGSWhKZGZsRmJUU09hVzVTcGx4VVZ6ekNhaFA2Tjcwa0tkZjZhUDZudmlYR21EOHBKdVAxOGJSTHkwcFdjKzlZYkp4elpSN0tGYVM1MWR4d3lPZHZ2UTN4SVZibWozZlpZUDF6dW5VUnU2SjNXeTVkR3VUdjRFY0JGcFpxN3YxKzU4aWluTDNic3BGTTF3ZWp5aDB4OG5VU3hTeFF0cWF5TkxhS0VGZHJBNVREcm9BemZHSG4yZjMrWEpiczRaVWN2VmJ2RU9JWStiVW5TcXpqZzcrdjFHM1NvTnNMQ01TV0dHRVlVYXlCQjNIOXJCRU9GeXd3Y3YyMkdDbzRFNjloM3VWNEJEdkNzQlVQNjFSczZTc3NTZUo3VkE5enRUOFE0d0wvY2FvRlJqYmFieEZpb2pWRWFaK2dQZ25taHUzK1dWZEt4cFEyUjFaMWxWOVM2eGFmbmdvWHBwZmRZNHh0T2s4SzhFRnpUREROUTRERnA1dHBFWkVqVUlqMWRidlA0UStONmlLKzR4Wkl1KzhjYlpWZStRUXFRcnRYemhXTUFDRDdjdy8zSUR5NnlkbTF1Y3FHVk5FWVlaQ3M2K3JsaTE0aHBIVTV2TUhDMjh3TWZWSm9wWFdPTUh2R0JZQ2pDYkhWSFJycThQRnlWRVNPbGE5Snp1eVNScHVpM202WXMxUFlGc04vZysrV1g2T0lVZXc1YVBLVElzRmNvbTZqN1lIOEF3Vjd1ZjByM3llU3ViWlhjNHUrUitZOWV1TmNJYlZLdUlaRnNTWWFscEdkdHUyZ2ZoNm4xZEVUTzk2WlhrMTdISkRyTXJTcTgzbFFGYlpiVytwUzdJd1ZrMTRhNHpocG90ZHR4bmlSM0diTXZ6UFFHSlRFUEsxc2RSUG4reDRpd2JmY0oyQm9oM09GL0tudUk3UkxjMzZBYTlFWnB4a3VpUmZSenpYZEtncld3S3RJS3NtMm1PbWw1U3B0MWkyZUlYWVBvMGkzbUx5dDRrb1V5UktoRTNkRS9lY0hvODRUQm81WG9iQUJIditIUThzWjVWS2JlYzlVcjcrMThQOUp4T1VIWkdpUTZzREFMbUhicjdVK0JGcnQxZ2pqaktUcVRVY2cyL1NtVFJ1OFVPMWF0TWdkMWFIZEZNckxJd0lpMHJQdEFPM2lKTVVhMUR0bDdUcllGbG5NWnNsNXVyWXM3UVpldzQ3YjVuSWlkRFh4RnArejF5aGdqWm92U081VU5qMjhTL2JLd3I4amZzV0VKL1JxZnZKOGNBcXUveGdpRktsZVNJSUR0RlZxOWVNckE1NHhZN2x1TGowaVQ3ellwenhiSVMrYWpUU0dXcEFUVWtZNGh5dS9iNEo0UDA3T24wZUVMM3BJRTZlY2NwZGt0VkwzTmQxM3dqNng1SG01eHQ2RCtvVEpMekYxdFJGekZkblgrc0wvcDJrZGsyVC9tQnpVVTdwSjNick81c04zZHdGTkx1MXhGcUNDWU5MQmppOGhFMFBsdXFBeTlXRzVBWkVWZjVMdllqN0FoN1U3eWdUZ1VQMFhxcUcrTUF3cFRGS2dXZUhrK01yUG9nOWZ4MzB6SElpT1U4TEU1bG5iNTB4OUJwNmpoWm1PT0RmRitsRTJSYlRHKytacFBwR2Q4RzVmL1RuQjVQVmdYdWZYNUF4eVdIeVNMaTNiUEQvSC9BL3MrOW91TW90eXdlbWxaWkkzRHcvSGZQWnhoMFQrcDArcVBraU4rR1R2OVh2RXQ2eHMvQmZ3R2hobW5ZY2F5ZGdRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImQ4MjFhN2Q0ZTk3YzRjYjZiZDgyNDIzNzczMWZkNGJlIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjk2LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAyLTA5IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJIeXBlciBGSURPwq4gQmlvIFNlY3VyaXR5IEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwMjA4MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTAyLTA5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0wMi0wOSJ9LHsiYWFndWlkIjoiOTg3NjYzMWItZDRhMC00MjdmLTU3NzMtMGVjNzFjOWUwMjc5IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI5ODc2NjMxYi1kNGEwLTQyN2YtNTc3My0wZWM3MWM5ZTAyNzkiLCJkZXNjcmlwdGlvbiI6IlNvbXUgU2VjcDI1NlIxIEZJRE8yIENUQVAyIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUI5RENDQVpvQ0NRREVSMk9Tai9TK2pEQUtCZ2dxaGtqT1BRUURBakNCZ0RFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRTFoY25sc1lXNWtNUkl3RUFZRFZRUUtEQWxUYjJ4dklFdGxlWE14RURBT0JnTlZCQXNNQjFKdmIzUWdRMEV4RlRBVEJnTlZCQU1NREhOdmJHOXJaWGx6TG1OdmJURWhNQjhHQ1NxR1NJYjNEUUVKQVJZU2FHVnNiRzlBYzI5c2IydGxlWE11WTI5dE1DQVhEVEU0TVRFeE1URXlOVEUwTWxvWUR6SXdOamd4TURJNU1USTFNVFF5V2pDQmdERUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQWdNQ0UxaGNubHNZVzVrTVJJd0VBWURWUVFLREFsVGIyeHZJRXRsZVhNeEVEQU9CZ05WQkFzTUIxSnZiM1FnUTBFeEZUQVRCZ05WQkFNTURITnZiRzlyWlhsekxtTnZiVEVoTUI4R0NTcUdTSWIzRFFFSkFSWVNhR1ZzYkc5QWMyOXNiMnRsZVhNdVkyOXRNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVXSEFOMENDSlZaZE1zMG9rdFo1bTkzdXhtQjFpeXE4RUxSTHRxVkZMU09pSFFFYWI1NnFSVEIvUXpycEdBWSsrWTJtdyt2UnVRTU5oQmlVMEt6d2pCakFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBejlTbHJBWElsRXU4N3ZyYTU0cklDUHMrNGIwcWhwM1BkemNUZzdydm5QMENJR2p4emx0ZVFReCtqUUdkN3J3U1p1RTVSV1VQVnlnWWhVc3RRTzl6TlVPcyJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFMUUFBQUMwQ0FNQUFBQUtFL1lBQUFBQUJHZEJUVUVBQUxHUEMveGhCUUFBQUNCalNGSk5BQUI2SmdBQWdJUUFBUG9BQUFDQTZBQUFkVEFBQU9wZ0FBQTZtQUFBRjNDY3VsRThBQUFDK2xCTVZFWC8vLy93OFBEWDE5ZSt2YjJscEtTa282Ty92cjdhMmRuMTlQWDYrdnE3dXJwNmVIaGZYRnhHUWtNc0tTb2pIeUF6THpCTlNrdG9aV2FLaUlqUzBkTFkxOWlEZ1lIOCsveloyTmw0ZG5jeExTNlhsWlc2dWJuNCtQam81K2Q0ZFhZbElTSTVOVGF1ckszKy92NjR0N2NzS0NsWlZsZnY3Kytqb2FIazVPUTVOamZyNit2ZzMrQmxZbUpXVTFTb3BxZkh4c1ltSXlNOU9UcFNUMUEvUEQwNE5EVjhlWHJXMWRYOC9QemUzdDZIaFlVdEtpcTh1cnN2S3l6ajQrUHY3dTVmWEYxblpHWFIwTkVuSXlUaDRPRDA5UFFySnloYVYxam01dVorZkgxRVFFSEZ4TVRLeWNxM3RiYWlvS0dOaTR5MnRMWHU3ZTdHeGNXeHNMQ2VuSnlSajVDbXBhWFF6OCtSajQ4L096ekV3OFNXbEpSVlVsTW1JaU5UVUZHVWtwUDkvZjNJeDhlSWhvWkhSRVZrWVdLa29xS2VuWjNVMDlOaFhsL1QwdEpLUjBkN2VYa2tJQ0dDZ0lCc2FtcHJhV25WMU5RcUppZHJhR25sNWVXMHM3TlhWRlRzN094RlFVTDI5dlkrT2p0MmMzUW9KQ1ZjV1ZxYW1Kbk15OHZOek15Ym1abzZOempuNXVjM016VHA2ZWxZVlZYNysvdG1aR1JpWDJET3pjMVNUaytWazVPUGpZM3E2dW8wTVRGdGEydUJmMzlNU1VxR2hJVmVXMXZMeXN1d3I2K3FxS2kzdHJZMU1UTHk4dkxqNHVKYldGbkt5Y2xDUHo4cEpTYXFxYWxJUlViYzNOeXNxNnV5c2JHenNySjFjblBmM3Q4ek1ERXVLaXVabDVpaG42Q2NtcHIyOWZYSnlNaFBURTJMaUluMzkvZGRXbHM4T0RsemNYRnljSENBZm41VVVWS1hscFpMUjBoMGNuSllWVmE1dUxoRFFFQ1FqbzZmblo1SlJrWnhibTlqWUdFd0xDMU1TRWxsWTJQejgvTkJQajlSVGs3YjJ0ckR3c0pRVFUycHA2aHdiVzVPUzB5TGlZcGdYVjdQenM3NStmbHFaMmd5TGk4N09EakN3Y0dkbTV1Smg0ZXJxcXBBUFQ2bnBhYlEwTkNFZ1lKK2Uzeng4Zkd0ckt6QXY3OXliM0NGZzRTU2tKRnVhMnkxczdTOXU3eXdycS9Ed3NPTWlvdUVnb1BjMjl1WWxwZTl2TDE5ZW52dDdlM2QzZDAyTWpPdnJhN3A2T2lnbnA5cFptZDNkSFhCd01EaTRlRkdRMFIvZlg2T2pJeHZiRzNXMXRhYzEyVjRBQUFBQVdKTFIwUUFpQVVkU0FBQUFBZDBTVTFGQitJSkdoYzZISTB0OG1BQUFBMlRTVVJCVkhqYTdWeDVmQlJGRmk3Q0hVa2FSQXkzd1VDNHhKQUFTN2pDRVFnb2tWUGtUQml5aWtDR3k0VVZDVUhPb0lhUWNDY1lnc2dweXhGQUVUY0NJZ1J3NVVnTXVBcm94Z3RXRlBCWVYxMTNmNy9OMU91ZWV0VmQzVE0xRVNaLzlQZFBwdDVSL2FXN3V2cFYxYXNpeElZTkd6WnMyTEJodzRZTkd6WnMyTEJodzRZTkd6WnNTS05TUU9VcVZhdFZyK0Z2SGw2aVp1QTl0WUtDRlJXMTY5eGI5ejVmcTZwM1AwUElIYVJjdjBGRHhZQ2dScjdkOGNhb2ppWjNqSExUQjBJVklabzlHRlpSU1Rkdm9aZ2l2R1hGSk4wcVZMRkFVT3VLU0xxS1lvMDJiU3NlNllkYWVDQ3R0S3R3cE1NZTlzUlpVU0lxR3VuMk9vS1JVUjA2UnVwa25TUTcyenRPK2dITUx2Z1BuYVBMWkNGZHVuYmpXSGV2V0tTYjlFQVhpSXB4eTN2MndxUjdWeXpTZlZEOXNYMlJvbDhkcEltVCs4VGNhZEtCcVA3K25LWWV2dFVES2hUcHFxaitSM2pWbzBnMTBPalpNdjZ4UVlNSER4b1NQMVNTOUlCaHd4K3ZPK0tKd0pFKy96K2pVUDJqZVZWRWI0WXhPcmVBc2VNU05MZlF4UEdkdlNYdG1KRDBSOWJvbm54SzdnbHFtSWdid1dOZU9qMDlTZCtUMTVyc0ZlbnVVL1FkYkhKVEgwZzN4MVU0cDNyenhOcE9jeW9HT0tlamo3MEo2Um1KUmo5bFpsSk5hZEo5K0NvYVBoUHhKdzhlbmFNVUlhSllHeEdUbm1VU0w4eitzeXpwR3NhYW5wMWFiWTY1UStOZ3hRVEJqUzFKRHpielU1NnJMOHQ2cnFpYWxIbXA5Y1RtODJOTnI2MmtQRzlCZW9HNW43SlFObzZjYjFaVG13ZUdWREpZTDFwc2NXMmwyUkpUMGdNVHJCeVhwa215WG1aZVY4SUxML0syanBld3VsdXY5T1hoTTdGa2RwZ0o2WXdWMkt4VDV1TlpLN21SeHlwSjBwVk1YaXpBNmpYWWRpM1NSSzZqc1YvTlZOeVhyRGNoL1FpU1pNT2R5Sm1PWkxFYkpGbmZ0MEt4d3N1NWJzdVFqVXljRjZoSk42RW4vNHBEU0hvRGVoTVdibGI5b2hzZ3M3bVNwRW5ybFphc2xmR2E0YXRJdUlYNTR3L1VWaUhwYmVnQmJXZU85ekp4d2tPeXJPZU0yR0hKT3RrQmRpaGNqWXBHN21qS3BMZUlkTnBPVnM1RTEzMFIyYjBtUzdyc3VydEdXN0grQ3pYYW5jY2tqYkQzS2liZm1TWWd2UWVWdVhka0w1T3ZsaWRkMWw2SFd6U1N2T291ays3b2FYSmZzYjdJZEkrQTlENVduTUpkZEIyNlJMNHZyQW1KaVpoZTI0VDFmcGMraVpVUDhKN284YWNMU005bXhZT2Mzd3hrT044MzBtVnc5RWwvZWFhQXROTVZRNzdPeW9tOFd4RFR2Q0VnalRxZGZaemZVR1M0M21mU0xqUnB2L3lRSVk1N3MweFJpeFdmNFYzMk04MDBBV24wSUFieGpuRk04MVM1U0x2UU9qMklKKzBhaWgxbXhhbTgrVnRNODFjajZYeFVMT0FkMzJhYUkrVW1YWWFqWEdqME50OElrbmpiZS9pR295T2RnNHJWZU1kalpnM0hWOHpIamJ0Rm1TQ2NGZC9oVFk4elRXOGphWUs2U3QxazFidE1NOUZiWHRGMVRqRHMwV3RQNGx0ZFNFZ20zd2dRVU1OSkZwQkcwUTNmQ1BvaHd5M0VXeXhFWGxsNjVTYWtkSllOaXJKWThSUnZpVDZveXdXa1Q3TmlBODd2RERJYzVqWHBwY2lybzE0NUhDazdFUzcwNEQ4RkxaRmhnWUIwTWlzdTVhNVFnTzdLVU9JdDBHdXZLTy9wbEtoZlZ2NVdWbTZMT3NKTjJEQ1Z5V01MQmFSUjJka0ZPNkozWWEvWG5NbjdtSFRENnB3dUJuOGV6eEwrTVo5RGhnNFV0NFFUQWVsK3FDUEtRbzU5MFYwNDd6M3BITzd6RjRXam1jNmRzSW9PV2hzaEFSclRZSTRUUmFUSkJWYnVVY2djNzBkMlJkNlR4ajJDQzNWZTNWRHNFczhwK0NBUHkydlR5WW1jRWlhNWVFYXJvZ2c5a2V6ZFF0SjRJRG83UjNPc2drWmM4eVE0azF6RmdCV0huMzFYTDFNZjZsZ2syakVTWkpmd25NS0hSRWdhTjE1bHBSb2hqc2NYa0F1WGtoVXZzRmhkbDZ1Qm0weGs0dDhyTjcvL0hCNmdYc3czSVQwREQ4WjNUbXJVL3FPNUgrTUxQQ25GbWZTekhOZXFjRS95eGNkYW1hVVVFUlBTNUVQTCtpL0tUaktOTEZFOEFYMFJxbHJaWFNhbXBNbFpDNys4SzVLY0NhbmZ4Z1BucTNnZElNbmN6aDFGaVVqUDZXLytnTFpLY3k3cmtNOVpVWTVzeEZ0SG1MU1FXQllMQ2VmeTBqNHh1VUQyR3ErWllqZ2lzazA1and2UVcrY2VFTmtkWU5NalpsTzlUK3dVT1hhUVg4Wlc4ZWtSOFdqODNEOEVTMFRGdXpycDdSWWZMVVlHWnBQcVBaTU1jN1JUR251aVpvV3crT1RuZEJXZVdtVTJCNXQvK1NTNmZOeVRWWFp6NnBGbzRZT2ZXc3g0Y3lucS9MSVBOdllsTTROSHk0RUw3c21jOVBDVU92MTdieHRWMnRQU3R2aFM2cXJQOXUvLzdQUFVVcmtGbjBwRHhtWmxoaythdSsvb1NFZTVHZHV3WWNPR0RSczJiTml3WWNOR2hjWGxjQmUrTU5GdW9kcncvcjZ2VE40UjFLVkR6Qy9GeXEzcUtIU1h2MWxLa1A1SzVkekszeVFsU0srSFBHcG5WWDl6bENCZG9ISit3dDhVSlVnSHdweWQ4MzEvTTVRZ2ZRMDRoMjd5b1U1L2thNmNBcHhmOVRjL0NkS2xzRXdVK3FDLzZVbVF2Z1NjRTY3N201MEU2WC9DNm1MQ2NIK1RreUE5RVBKZEVueFpWZkFYNmZiQU9mSXJmMU9USUwwSHBzc2pUWFB0dzlZa1RSODN1czNlZHNscjBaSXhjVFJ4UVp5ZVcweDFyRHhnMkxxdno0NDdualh4V3ZYODM0TjBMaXpBeGpZM3NjKzRnWEpFOGs2eUhRN2ZVRW1VUStDemlDNlF1bFB5NGxFR2x4Sjh2aEtSaG83MEd0ai9GR3V5RkJKOUZPOUFjdUYxZDU0RzVJNk1FWGg5aTBQRkNlRzZHaHFPM1Uwa3daTitIamlubUd6V3l0aXJHTEJEaTdVaFQva2RnUnZkSlJMM0tmMWRXYkJqTTBwMndaWWpYUVNMWmlrM3hiWXhwN1JtY2ZwVzBvVm1hbUdubWtWUlRKT0M0bklNYnBPcEdlUStkbEZ6QmZMZXJyV3QzV0V0czNaZU5KRUNKajBTbm4xZU5iSHBCbWpOb2VjN3crdDIrem9rVGZTWUFmclBhY2tZRkVKYVI3enJaeUdreVkyK3JPNFR1YklNOGxTKzlwbDBIN2dMZWFWaXkraERWTDBRWlpVMW5VZEZoMkcvNG5lMDBFSHZGL0s5U3h4RWYvOUFUV2FqUG1ZUERjeWM3eEVaTU5LVDFZZVZNa05zT1lKcWUzRXJkUTV3aDFSbEFzdmYzK2o4YmlJVGV0Tkxmc1RxZjFGMUpwR0JtL1RUN215RVI0VnY4eGs2SnZqK1U5MXRwQzladHd4YTJFcmRkZG1SWkJxOUU5REowTDJ4UC9INkRpNVpiWWN2cER1anBKNXRJc04vVTlVUGV2RjdWQXlML2pYcEVydHVjeXVrU2NGTDQ2QWZnUkY4RFYvUUdxU3lKMVRTQVZ5Q3ZTQlNXa0lEN0hDam9wMUx2aEYrUTE0RjMvZEVVQm5zRFF5aC9kMVp2Z0pJc2g5UEpBQ2t6OEVPakx5eE1DN2MyZGRnZDhUc2ZseWlDc2hCZUlqMkJSOXdlcHJ4ZlVwZEE2ZmQ1UGY4Z25qSVZoZWtabGJxb2h1Yzk3T1dXblhhRUVQUWJUa2xEbU1GYlhGRHBvblVzVGlaOFJjbmF6NkVRQWMwVmJKYnRpTHQ2dXNjMElrWjNxWkNPZ1VpM0NDOEdMV2JJZFQ1S05MU0ZodVpvWmJVSFZ6SHE1TnlnWkdHYjhvU3lGZlJkNXpYcVBSeFVRMTBJMGszZUFacDlEODRnYlFidWY0aVE4djJPNVorUlhhL2xvaDBTbVVRVklOdjFHSStIb0RreDB0dEJiaEZWZXE5MjBjTE05eCt6OU55cWJ1TURsNllPVzVWd2UzeWtkWTRFM0lEQkJlNDErV3E0Z0VxTDJqQ1dXNC8raC9oZVBWejN1M1g1T3ZXZVNWV3BGR01WRlBOdzFxQXpUN3pSRm9ibTlIR3NrUGJnbHBjWXVpWXR6VFRlYmI0cEF1UkJKQk91WVpFMjlXWUdwOVpjOEVUYVMxT2drMjcyckJudmF1UXNJaTdZdHFzcFRwZjU3SUFJZ1VnelgvNklheFJUdlZqb3BPZVNHdDdyMExvalR5dWx1aG1SMk5PWmtCU0lwOG9GM3lOeUVBNDczRVFxbnFkU2VpdTF0Q1lERk80NDVYQjlPYkNIdENobEZxZzZMcjVFOGIzUXFkRUpMeElKQ0FrWFVQZEE4UW1tR0JQbVRlSEhMV21uK3B2NmU5QnJwL05UQS9hQ0xtU1drdkwrKzRvTStZU1Q0dE5ocW04YnU3TmcvQlY4T3Awa2hkY2xoQSswOVIyNndEL2w2UVMvUTN5bGJTV2hYdE82d2JXME9JbjN0UUlaMEs0b3BUdDlDM3p0Qk4xTTZRbXltUWptNUFPZXdGWTMxRExOZWtNVHFJM05VYlRVZGxWb3FaMTEvTG9zSm0yL0IzbEowMXVRM2ZxTEZYTE5DWkpFZDIxV1JQTGdJZVZOQ0JzNHlDRW5ud3doQ24rNDM0R1BHQ01YMHk4aHVsS3dFQVk2MmVyc1E0a1RrOHoydjFJbzFtOFhqQ0FCbGNUWVBvbUd4MTFRTjlMNVRkREZaRHZLNUVvYTc3bWNoNGF5R3I0bk0rQjk4V1lOdndiL2FyMXd5STZMa2lHUVdWWEpCOURxemhocUFJQ0I0azR4SngwQ0FTL2RDdWkyL0MwUHFOMU54MXJ2OFhKNkZDMmR0cXZyai80RTUzZlRYeEw2UmN5VmlKWDFtSkpMZ2FtRkNKaG0wVUdETWgwSFZnYTdIQ2V3QWtkTk1PYVRvYng0elBZbzNSSWR6N0VBRHJsZWN4N3pwYUxuMFBVZmg4bVI5V3M2S3Y0VytINGtzcCsxZDBsR3ZuVGxyMldrNnY3WFk1em41dGkyS2lVL2p1UjFqWkgvaGRLNnU2U1krN2JHcmIrQkpXczJLN3phNm9sU1pmbzBwVFZNeTdtWFdMLzVacVhxV2ltcDNORnZDYWRyeDR3QSt0eXhkcFpEeDkzM1RMaGZ6OVhxZnNLRk9PS0RJNjlWVXZkdGxiU1U5dWdzbkg4Vi9GOWx4UnRmVk03SlN4VmdyTTFhVklQVmwrQ3Y2T2xFT0crajFCQlFGU3E2Z3lwN24xTnRub3NreHJyV3BQVzlyV3NoSjdmTVNMT2NMazJzd1J1NnNhNVEwYk5kdEhCTlVvRHVmRzVCOUxrSi80NXQ1N0dYMjNIZ255aDIxU3EvVWowLzdUU0gyeVNrQ2w3Uk9aTmVpYW1lWWhWNlFZMXVPcWV5OWljN2o3QXE4V3hJNFVtYnMrNjlEM0VaOStrRlN6N21CMFVWL0tHN05rZXZtRlI3cXlqb3pibE5qWC9IRUJRZU11OGl1aVk5cHQrNjdxcmUwQU9xVENBcnUxcGY5T1F3byswMDNuSjN6VGtBRWZVQkphL29ydUlYQnJWSHk3L2JxRzdnZHUwNndxN0NWRnNCVjZteGloU05sNTQ2eWQxM1M3STRXODYzcEptaUpQZnplbDMwazV2ejk3ek94anBGSzhQdnZBN2ZrbUVPRHIwWUV6NUs3dDdLTHd5cHZuQUx2bitwbUhEaGcwYk5tellzR0hEaGcwYmR3Ly9CMlpISUo2RG02VDhBQUFBSlhSRldIUmtZWFJsT21OeVpXRjBaUUF5TURFNExUQTVMVEkyVkRJek9qVTRPakk0S3pBeU9qQXdmelBZZFFBQUFDVjBSVmgwWkdGMFpUcHRiMlJwWm5rQU1qQXhPQzB3T1MweU5sUXlNem8xT0RveU9Dc3dNam93TUE1dVlNa0FBQUJYZWxSWWRGSmhkeUJ3Y205bWFXeGxJSFI1Y0dVZ2FYQjBZd0FBZUp6ajhnd0ljVllvS01wUHk4eEo1VklBQXlNTExtTUxFeU1UUzVNVUF4TWdSSUEwdzJRREk3TlVJTXZZMU1qRXpNUWN4QWZMZ0VpZ1NpNEE2aGNSZFBKQ05aVUFBQUFBU1VWT1JLNUNZSUk9IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI5ODc2NjMxYmQ0YTA0MjdmNTc3MzBlYzcxYzllMDI3OSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMDMiLCJ1cmwiOiJodHRwczovL3NvbG9rZXlzLmNvbSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU29tdSBGSURPMiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTEyMDYwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNC0wMyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDQtMDMifSx7ImFhZ3VpZCI6ImY1NmY1OGIzLWQ3MTEtNGFmYy1iYTdkLTZhYzA1Zjg4Y2IxOSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZjU2ZjU4YjMtZDcxMS00YWZjLWJhN2QtNmFjMDVmODhjYjE5IiwiZGVzY3JpcHRpb24iOiJXaW5NYWdpYyBGSURPIEVhenkgLSBQaG9uZSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRXJUQ0NBNVdnQXdJQkFnSVFSVGZjZ282eHdJRkdmbXR6azFCU25UQU5CZ2txaGtpRzl3MEJBUXNGQURCRU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRmJHOWpZV3d4R0RBV0Jnb0praWFKay9Jc1pBRVpGZ2gzYVc1dFlXZHBZekVSTUE4R0ExVUVBeE1JVjJsdWJXRm5hV013SGhjTk1EZ3hNVEkwTVRnek5EUTVXaGNOTWpnd056RXpNVGN6TWpNM1dqQkVNUlV3RXdZS0NaSW1pWlB5TEdRQkdSWUZiRzlqWVd3eEdEQVdCZ29Ka2lhSmsvSXNaQUVaRmdoM2FXNXRZV2RwWXpFUk1BOEdBMVVFQXhNSVYybHViV0ZuYVdNd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURRQ2ttUS9LOERuMzlxU0NXNXRLTHZ2RExIM0NsU2NnUXJEZzcrdVk0NGpIbElZMS9MbDZ2MnJwajdubG1WTWxJem9nZDN5WGpDRkJ2R3I0emlHUTJRYzhVcGthVTk2RVp4RXRId1pTdHc2WVEwamRuZ2tTTFB2T3A4VDhZaUpwY3ZzVnRRdGlRME9zVFR1aU8yRWk0THVMaDdLUis4eDRiQVJ2emtCV3N0TkJUcVZTQVpRWWVzcW5sOEg1U2Z3YjNJb3U4TFNpQXN1T1h5eHQybXM5MTFZcnhXdmgvS25PZWwzT2QzaCtLNWRRWVA1MytmUFV6Z3o1NlRUajhSNFk2elJ1emRrYm5SNnhXWGRySzQxNGlYOUQ2eDVxOFcyWEpKcFRNSzdFblNYRzBxN1hGN3A2OGpES0FueEFGOGtmaDN1aW5jMnVsbVZPWmJUUnp4RjhCM0FnTUJBQUdqZ2dHWk1JSUJsVEFUQmdrckJnRUVBWUkzRkFJRUJoNEVBRU1BUVRBTEJnTlZIUThFQkFNQ0FZWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVqTXNUYlkwd1hRQlIyOWJXSEl2YkZmVUFGZlV3Z2dFR0JnTlZIUjhFZ2Y0d2dmc3dnZmlnZ2ZXZ2dmS0dnYlZzWkdGd09pOHZMME5PUFZkcGJtMWhaMmxqS0RJcExFTk9QWEJvYjJWdWFYZ3NRMDQ5UTBSUUxFTk9QVkIxWW14cFl5VXlNRXRsZVNVeU1GTmxjblpwWTJWekxFTk9QVk5sY25acFkyVnpMRU5PUFVOdmJtWnBaM1Z5WVhScGIyNHNSRU05ZDJsdWJXRm5hV01zUkVNOWJHOWpZV3cvWTJWeWRHbG1hV05oZEdWU1pYWnZZMkYwYVc5dVRHbHpkRDlpWVhObFAyOWlhbVZqZEVOc1lYTnpQV05TVEVScGMzUnlhV0oxZEdsdmJsQnZhVzUwaGpob2RIUndPaTh2Y0dodlpXNXBlQzUzYVc1dFlXZHBZeTVzYjJOaGJDOURaWEowUlc1eWIyeHNMMWRwYm0xaFoybGpLRElwTG1OeWJEQVNCZ2tyQmdFRUFZSTNGUUVFQlFJREFnQURNQ01HQ1NzR0FRUUJnamNWQWdRV0JCVGZRUTVXcldNUlc3OHZrV2gybmlEVDNWOTdyREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBaUxwTHRuYUUwQWJJaVNtbWo0RUxSVFJNR3VlZHhkNlpUWTJ5VWkxUU5zd2FJMk9GbmgvTkRXTFdPZ0YzNkhPdkRFTFhCWVpNNitBc1BpVkhVNzJzdmxZajdZNUh6WnZvVWtNM2R2YnhyNlUyQko4OUpFRVRSSVdxVWxZT3E0N0JlODRPUjJYdm1uaVV1SnJGT3pzQVljdHJaWDJURlgzQWJWUHM0TFNUTmMwZGEwdXEwQ3FvT1NPSUNmenoxWDd1ZjdUdzlPMEtjS2VyRmd6ZVVjbUd0S3Y1b0s3Ulk5V2tEeGRpMjJSeTBHRWI2MHRuYXY3cWs5amE0NVdCak4xMHh1TnBOc2xDYWxSbk5ZT0dWdFkxbTRveTJnKzF4ZDFiMHZ4ZzB4SnNXNGsyb3ZUZFpRUzVIQ2ttZTA1TTVMeTBTRlNWRy9SSHhNczZJeDQzQ2N0Q0lRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTFFBQUFDMENBTUFBQUFLRS9ZQUFBQUIxRkJNVkVVQUFBRC8vLzhSQmZjU0NmTVNDdklUQy9FVEMvQVRETzhURGU0VkV1a1dFK2dYRk9nWEZlWUFBTThBQU00WUYrVWFIT0FBQjg4QUJNNEJCODhCQ004Q0NjOEVDYzhJRDlBYUh0MGJIOXdiSU53YklOc2JJZG9jSWR3Y0l0b2NJOWtxTU5jQkM5QURDOUFFRGRBRkVkRU5GOU1ORjlJUEdOTVBHTklQR2RJUkd0TVJHOU1USGRNVUh0TVZIOVFWSHRNV0g5TVdJTk1YSU5RWUlkUVpJdFFhSTlRYUpOUWJKZFViSk5RY0pOY2NKZFVkSmRjZEp0VWVKdGNkSnRRZUo5VWVLTlVlSjlRZUtOTWVLZE1mS05VZktkUWZLZE1mS3RJZ0tkWWdLdFlnS2RVaEt0WWhLOVVpSzlZaUxOWWpMZGNqTE5Za0xOWWtMZFluTU5jbkw5WXBNdGNxTTlnc05OZ3VOdGd4T2RreE90bEZUTnhOVk41UlY5NVRXZDlWVzk5ZFkrRmthdUppYU41NGZlYUZpdU9FaWVLRml1S0dpdU9HaStPc3NPZ25QcjhyU0xVdFRxODdjSTA5ZFlsRWhuZEprMnBLbFdsTW0ySk5uV0JObldGVnNVNVZza3RXczB4V3NreFh0VXBXdEVwV3MwcFd0RXRXczB0WXQwaFd0VWhYdFVoWHRrbFh0VWxZdVVaWXVFVll1RVphdlVKWnUwUmF2ajlhdlVGYndENWJ2ejlleURoZXh6bGR4amxkeFRsZnlUVmV5RFpleHpkZXh6aGV4amhmeWpOajFTcGoweXRpMGl4aTBpMWwxeWhrMWlrVnFpRWlBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBRittbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORFVnTnprdU1UWXpORGs1TENBeU1ERTRMekE0THpFekxURTJPalF3T2pJeUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdNakF4T1NBb1YybHVaRzkzY3lraUlIaHRjRHBEY21WaGRHVkVZWFJsUFNJeU1ESXdMVEEzTFRJeFZERTRPakUwT2pBMEt6QXpPakF3SWlCNGJYQTZUVzlrYVdaNVJHRjBaVDBpTWpBeU1DMHdPQzB6TVZReE5qb3hPRG94TkNzd016b3dNQ0lnZUcxd09rMWxkR0ZrWVhSaFJHRjBaVDBpTWpBeU1DMHdPQzB6TVZReE5qb3hPRG94TkNzd016b3dNQ0lnWkdNNlptOXliV0YwUFNKcGJXRm5aUzl3Ym1jaUlIQm9iM1J2YzJodmNEcERiMnh2Y2sxdlpHVTlJaklpSUhCb2IzUnZjMmh2Y0RwSlEwTlFjbTltYVd4bFBTSnpVa2RDSUVsRlF6WXhPVFkyTFRJdU1TSWdlRzF3VFUwNlNXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3dZakV3TmpFMll5MHhPV0UwTFdVME5EWXRPVEJsWlMwM056QXpNMkZrTUdRellXVWlJSGh0Y0UxTk9rUnZZM1Z0Wlc1MFNVUTlJbUZrYjJKbE9tUnZZMmxrT25Cb2IzUnZjMmh2Y0RvNU4yTTROR0UyTnkwM1pESmxMVEJsTkRjdFlqQXpOUzFsTjJVNE5XSXhaRGswWlRZaUlIaHRjRTFOT2s5eWFXZHBibUZzUkc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRveU1tVXhOR1JrWkMwNVpqQXpMVGhrTkdJdFlUYzJOaTAxTW1FNE1qaGpNRGRoTmpjaVBpQThlRzF3VFUwNlNHbHpkRzl5ZVQ0Z1BISmtaanBUWlhFK0lEeHlaR1k2YkdrZ2MzUkZkblE2WVdOMGFXOXVQU0pqY21WaGRHVmtJaUJ6ZEVWMmREcHBibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakl5WlRFMFpHUmtMVGxtTURNdE9HUTBZaTFoTnpZMkxUVXlZVGd5T0dNd04yRTJOeUlnYzNSRmRuUTZkMmhsYmowaU1qQXlNQzB3TnkweU1WUXhPRG94TkRvd05Dc3dNem93TUNJZ2MzUkZkblE2YzI5bWRIZGhjbVZCWjJWdWREMGlRV1J2WW1VZ1VHaHZkRzl6YUc5d0lFTkRJREl3TVRrZ0tGZHBibVJ2ZDNNcElpOCtJRHh5WkdZNmJHa2djM1JGZG5RNllXTjBhVzl1UFNKellYWmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG93WWpFd05qRTJZeTB4T1dFMExXVTBORFl0T1RCbFpTMDNOekF6TTJGa01HUXpZV1VpSUhOMFJYWjBPbmRvWlc0OUlqSXdNakF0TURndE16RlVNVFk2TVRnNk1UUXJNRE02TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFNUlDaFhhVzVrYjNkektTSWdjM1JGZG5RNlkyaGhibWRsWkQwaUx5SXZQaUE4TDNKa1pqcFRaWEUrSUR3dmVHMXdUVTA2U0dsemRHOXllVDRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejVYQmVhbEFBQU8xa2xFUVZSNDJ1MWQ1NThrVlJXZFowNllBNkppRHBnRG1GaXRMVnl6bUhQT1lsWlFFV1E5QVhNV3pQNnpmcml2OHF2dXFwN3Vuc0hmOUtlZDdkNlpzN2Z1dStIY2M5K2NwQWZnNitRQzlBWG9DOUFYb0M5QVg0QytBSDBCK2dMMEJlai9GOUEwdVAwelBrZWdEVXVpTm9BaWJNRzBjUTVBU3hJczBCUUZxUGdaaXBZZ1E1SjV0cUJoeXpZbFNvSWd5eE1qdzdKSlU3WW9VajVEMEpSdDA1WmxVYUk5OW02RGtDWERsRUFKcHZZQSsyUkh5QklzMmJJQVdMUmdxZWNqdGtSWnNnM0pGR0VBT0QzcW5VQ1REakRNV0V6WmxIb3VRb2xDL0w4b0VXbzh4ZElaZ0xacFc1WUV3SllrSW50QzloREpJRzNURWt5THRpSElQTFd0ZHdDdENHS2tRWnRLeVNaaFc0WWordG1TYkVLMllLUkVDYVJFaXlDUERScXlURkRxaFY0aUlyWWxLaUpkdUVZdk9sdUFiQm8rbmExUGRzQXNHclpIQ1VXd0xVR1NMTW5rSkFxS3BreEwxakZCbTVDTVFhRG9Ib0VsQUxRaDBHSWh2RU9rVDJmcTlhQWRqc0dpdDlNbW1BTmhFWml0TUxhUEIxcVIzSVM1ZHdGWnRHeDZKc2JEeHR5N0J3RnR5VVlYYWhIcHNQZWxhV253TEJ4UnZlOWd0RTVSK0oyc05iVGt6aU1EY0E4MWdKeDAzUHlWYlVKVWUzQVJ1Ujg0SG1nVFJQNzVkQVlwRSsyVGlLcXUvWDlGV1dxcjlRaEhSdFd4UUVmYWF3RWhRcDg3NDdjSU15YUt6U2ZRNEJRUnFmSTRvRFVJSFpMc3U1eFNZR0puYXFxeFBHd2J6V2ZjTkRLRVRtSHFsYUNqdUdQckt3Mk1EcEhEcGJQaFpkdXRjNnQxcXdndnh3RnRXV2lPR05VOVlkdU9naUpIazJ4R2QrY3ZvZjJ6WkFySGNnOUcxYWJ1aTM2bWEwOG4xWmlYWmxkOGdMMW5wRk9rbDVYdVFVRmdCOGlkNDNUK0liRjU5Rkl2RDdudEl4MHR6WkhjSTZKQSs1RFZTeUFvZ2JDSFNXWS9UTUxhNkVFYk9TM1FiR0pFb2wzTUZwYlE5akltZEJhZ2MvZlVSUTlPL2pqcGY5dlVxSDFSSDJ2ZFF5UWE0MEVDblBPa3k4SEFSandQbWRvWFhiTTJqY3RpRytsa1VnSTQzL2ZKMFIweXV0c3pBUTJJWGZ3d2JkRGFWRW5BRmdFVDNCc3Z0a1B0NFY1Wm1RdWhUV0ZCakdMVzJCc0p1YnFlZGpTSXZWUTRLaVBDVHpqbzBFNVZIcDBlTkIzSnc1c2EzNVQyeDVEdXFVY01aZ1liNmhNTE9tK2dBZHFjSTF6SWZrWTVINkFURFpyV0hHc2JCTVA1c25SS1FSNWxmcnBFakZnV3podG9CSVVVVXdBVlVFczZaKzRSWVM4NlFkbWExa25nWVEyOUd6L2RrWXVLVG5lU045UDVBNTJDMXlJY0dkSk9SMzN0T25QSnBWSmdMbG43UElKT2Fvb094U1RnbUtoUE1VZDBMcU1sT2laWUs1S3FqSWozbEJUelBFbUVrR2NGSUNuQWtqWHVlRTQxc1kwd0FqbUdGMHN6aW13S2h2SllENUpwSU0vTEZBK1JGbU1FeVRIVGZjb3hjNHpoRUtsR1hBWTc1akNVUWVTaEhnVmFpQXlRZ3hLaWYrQTArNTUyb0IraDJzSFBhRm1ocEFpV3NHa0NoZzBMbWZVTDE3RU5rU1NNU2JJNnZRckJrYy9SUEcwdThTb0ZzKzZZUHVkWm1ZeUlwV0JNb1dKOEUvK2wvWUx1cUZSRjg3VTFzMUNnbUllaEZCdzBQVTBDTmdYWmtBWEc5QlFqSmNCK1JDcHFwdnZCUFhyYlFRanlOVHQyTU5vaURFZTFaUmlJUHQ3T3dXWC9vRk9pTFNGMEJ0b3lUMkYyMjF3b3VrdFFjYVRESTJLc0YyTjM0eUNnVTJKRUxFclE0cEJkekxWaXJ6QmdVTmsrRE9nWXVBQWhsTkR1bmlhanAzZ2gxSEJDQndFZHZITWNvSjJiN3liRERocWhVYmJkczFvczV6cnZYa0UxMVV5UFZ6TkhMZWUrSlc2eTgrQjhSNy9PeDFLZFM0TWF6YXYzcjh0ekNMS3dXNThZdlZybjBxSExzUThNT2srVHVKdXRoVkh3a01seE5EcUVBaklTTUhjU3RPV0VxRjc5U3dvSHQzUndaOU16djh3NzhvSG9OY25UbWRKaHRLYUlpY0Y2MXBFMmlJNEpqTEpnSFBVUEpKQ04wRmRTcVd4anIwSm9OR1IramdTYWpoSitaYlFPN1JiNlNUeGtpRWNCbll4d0QzQlY2SWhPZ3IzR0tGTFZjVURuUWRnNlV6T2tJYjFqR0RvUnB5T0JUaEgxMWhSOFVXYjBNZ3ZvYUJXUEJ6cXJOYkhjb2MxaDYyUGwxOUZBSnplSmNUbm82TVA3M1FKS2gvbUFvTnZHWkRFYkViSlU5WStGVmVpRERybklrQW1vWlVPamNDYjNKOUcwVkt6TUR3bGEwVll2aW5xV0hKck9OTWlHUmRYUVFWZEdRbEsvcFBXeW96VHN0OTBtNEdKV1BTem9hSFMzaXgxaFc0RFltNTVuTHJKVUNSelkwbmtYWUtzL2gzZjByV3BCRUZ3U0FSeDJveWdrN1Z1R2lpSkFFY1BvU0Rsb3lIUjAwTUVDYXlQdkVLSkpERFhWSVZmdHBGcEhCQjNKWVFOUFJtZitiMFRuT2haK1pvTDhnUmZPZ3VLYjh3K0xiSWl2NFhGdE41WFNHWURPQ3hndXZTT0J6S3l2TU1qMkVhRm45VU9IdGpTQ1VKZ21Fb1VJUTBJOEN3N3NIQk9OT2E1N0hXaDQwa2VFb2w2RGozU1NsTmhtR0pVOE9aTkFERjNPbUtwRFM5S25mWUFXNkZFd0lJWS9sR0ZHZG1sdE12ZW5oQmdOTWJoK1R2WTRaQm16cGZoYTJTWkhEOXNhZDkwS2JyM0xkWk1kc3hnQ1dYbDlaRFNuYWQ3YzBQU3NGTWhxekp3d0x6OTF6NVlnTytVc1krbzI3bnJqa2RIVGFVZXpKYk5KZUxoU1RNaVJCV0lUanVpdkRjVitWdXVmTWtmR0RFMWNxTUU1NlhkaUZyTnhCM2FscFVrTU5LV0s5YUplZGFHSUJSNDk3RkgwQU11YVNVcDVXTFFwaTY1MUQ2Qy9MY1pta1hMNE1Ib01ZdDR3V2RwV3hvaE0zTndPcjlXYTB2MXZxTnp5cTk5dHNKOTl3MjJYZFZ3RTJVemEweDVCYzFEVXg5YkxZSEdXMGZWclE1Q2NoV3lUQUtodEhmeGEvWFJmVDJ3d3o5OEh5Y3c5WGl0MnVCWlFlakUrelFxamJROW1aVWFFMkpJcERPbkU0TXlJc1EycWpoYVF0ODRFWXVmWklzdWlxTk1tRnlpcnFtekNBalhvTGZJNm1udnNuS1hOODNJNE5CNnlBUzFaNWwvcDA4Z0VmK3l5a01MdzBPUUZ1WTdZaWxTaERmNFd5VWhzOXRRV3dGaS9NcUlzRVlpUjRkQmZMWUE5VGlqSW1qRzNUZ2hnam0xNUc5Zk56bURhTzJoWmlEWWpnR01rMUFtaFNtK0xMK2J4US9PeFljcWRuME5lNTRhWHh2UFZHMFcyRmNvUlRDd1RDODA5S1NGcFlNSmNORVJqSTIzSjVCSVhxKzlYTHpMa09vY0lnY2FvR1NIVTV6bWlhUjJuaXJ6VkRCZ01QUTFnckJBQ0YwRlhWVlZWTTAyZHBOaXlsekV5WWJqbFlCdEh3Tmc3WWtxQUdPb3lMOE92MDF1ZkZBRlhkVlZWVlYxSzQ2QUlvZEQ1SWZpVzNsOGpkaTgwNmRGdE1UcXhYTzJ0YStKT3BwRHJxbnROQ3FiczBnWE5kOUJFWVA4WUZndGp0azNBZWh1WFFGZlQxN2lGemsrMVJJa3JpdnQrYUJNNUpiWnk2TURPRXRXVHpaQkhxSnZxdlJUQnFheWJHclNDMUQ3WExxYWdxOHRiVVFmcnpYTFdZWWovK2wxVmtCc0hCRDEwNWpKcTJLVTl3aGhvajI2QUNXSGdRWVN6SjF1Y1k0ZzZ5bWRNeTBxUWd5NnJtUVBvSU1zakxlaXBuZXNwYW9zZXJ6TVJ6Q0xYZ1NjRTMwSWVRclIrc3QzT1ZWVlhYVnJBY01abUFhRjlHZWIwTEduVVFVVHNaZEQxK0t0ZXR1aWZ0U3lwWk55eDVDRkxaT3gzWTJzQ2VvdWhHOVNoTUdLUDVyY2hrZkp3SVRGdW5nRG93NEdlQnp2MDZ1Q0xFQnJYM0I3Wm1EU3Z1Um84MUFyWFNURjd6MFVRcWIzN0pkL2lrdVU3d3k0UWxFRWZiQm1xYk9ueFh6VmVIWnBLUmRFc1JXTm5qRXJVWEwxNVgxZUpsVUdYVDEzQjFJRTB5OGxGeUJUSHE3T3hBek96U0w1djBQVTRsVXhCUjBlWEx4TVRzN1o4WEMySHlKODgyQkxKeE5MVlhBV1ZlVnhueVQ2eTZsalQ5TWlJMFlkYmZEbnBZYXUzZ282dGhhWk9Ma3hUNDBZeHkvVFAwbEZBVCt2bi9oczNwNVR1ak5aWnNRcGVJbk9VRStIVjM2YXpCbDFYVlhVcHBmU2Jxd1k0cDB2S0RSL2xuL3pxbittSW9OT3NwYStrbFA1OHJ6MnI3NEVRTjE3ZGRjL2YvNVRPRG5UcVI4SmJudjdJMis4cmhJdTJscEprUVhmLy9OOC8vdGFESG4zNWxvMTF3Y0pYWGVJRlRqS3dlZ3ZvcXJwY1BmdmEyLzh3czF2UnJzclpWMy83M3g4OC9oSFZMVE00THkrRk9tdklEdlNvQmkzR2ordXYrOUg5MEpUeVJ2UzBobWxmdmU5ZjMzdjQ0OTQ1QjZSbzVNdWJIOElXME5WbTBNKzY0MzVwUEpFSzVqOHZoOTM5aTMvYysrMEhYL3VPYXZkWFBRRmVCbDFQVW5pQnVxbXE2NTl4eDkrR001ZFF0TVpWY3JidXV1ZVAvLzcrOVE5OXk5dExKcXNuWDlURE4rcnAwNmozWU9ucmZuUy8ya1l3cncwNkp0eUNmT2Z2L25QbmR4N3ltSGR1ZDloTGx6WWZ5dUVKMkRGNmhCRnVmdFFQL3hJSjJuRnRZdHl3bVRsYjZ0ZS8vTzR6SC9hbXQyMlBGdTkvMFF0dm5mOVFQZGVocmc1NThSWitEek1YMFhEUWtYRVZJZWxmM3JjOXdsWlZYVmZWaTc5Yyt1YnRUNnczT25RRHV0NmNYT3IycmI5ZVJiNWloRjB4blc5K1hGUTd4M2Q2N0RjYkFxQ2UvT0MzYm8wZHkydVBDSVkvVlN5OGRsRVoyVU1XNXJJTStxdHBycmg4OVpYdEVXOWFtbTd5am1RRFdWNFpkd2RIV2IyOENJMXZkYzNYWnVyMTlLVW5qMlBLSXRBYlMxT2JVTDVnbFJhWFRtUEhvTDh4L2ZhWFVrb3BmZVNsQzVQTEN0RE10d2dRNHRMNVdjazllcUNiaVAzZUcxTks2Ymx2TEtUTEJhQ3IyV01ZUzBseCsvV09iVWw4djJ2Q3A5dnNYZGRWOWFGWHBKUysrTVFyaFNDNHFCdWZiUkViUmZQdVJXVjJqOEpCZk9XSFUwcGZlRXExMkQzU09MNlhXWVdRWVc0WVVEb3pETHVBdnVGakthWFB2R0JSYlRwTGk5VWxCaEtoTzlnMHNOdjhKT1pEM2tzK25sTDYzUE9LSUphQUx0VTZiYXZ0MmZGOEhnQnBGMHZYMWFVM3A1USsvNlJTdmJvYjFkditPODJOWERKbkJtNDVveG4wMTZjLzg0T3ZTU2w5NVFsWGx2djByS2xIejJlaVNSbEFEcW5sUmk0c3U4Y1VkQjF4K3Ztdlh3TTZiV2pjdW40bUxoWXJnVzdvNkMwN2lQWGx1WU1ZUCtPelQxdlFiUlZuTHBkbi8xa3U5cWRITU5TdTNqcUFtem1JWGZmeDFDdVRSNzU1SkxkMVRwVEtWelRMVUROM1dRVDZtdHVtQnpGLzROM2JtNjJaNFdjOTErdm1mWVBScE5acTdqVFlxdlBLbHI2dFdFTVdUUGV1VjkyMGJjeGNQSWtqaEJoTk16UGF1RzVoYS9VMEYvTG1DcDQzZkdLWDJmZzRGSE9rakdwdXZZaU9jWmMwZnVXbUc0WS81YTBmZVBuTGJxM3E5N3oyaHZkVmkxUUlhWE11Q2pVUUJ2d2Q0bUlqYXNrOVZ4bDAvNHZYZlhyeXFlZDg2c2FxZXZOSFA3bE1oVEEwZHlGUkIvUFZuN3psKzl3b0h1OGlwdFdYc2ZhdnNVaktkNGlRWUVybkZiU0hDNGFNdXM0Njd1VmlxeThZN2t1U1loZmhJSktPZllKRy95cmsrRjA0dHBuT00yaENSSHRSZlo0VjRzZ1h6NjIzZEx0ajVlYUMwK01iZXYxRjhGRlBPMFJ1b1dGTDV4eDBaSkdRWDhVdnplSHhNYS9XbWtKZzNMRVFpbTg2blgvUUlRRE1GQk9sczhDOFZsNHZoM1FpLzNxY1ExK3J1YmVNaUh5RHNFNTFHZGN4M1lPUTNkd09kVmFZMThmcElCN2xzNE84eS9aRjNJdVh6dksxK3BjYmJHQnJ6aW5vYy9KNlFJTCtIMTl0aGRPd09nNkNBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiYWFndWlkIjoiZjU2ZjU4YjNkNzExNGFmY2JhN2Q2YWMwNWY4OGNiMTkiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwidHJhbnNwb3J0cyI6WyJpbnRlcm5hbCJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wMS0yNiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDEtMjYifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIzYzYwOTIzNzRjMGQwODYyYmFkZTE4NzhiODY0N2Y3MjAwNTE5YzIzIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjNjNjA5MjM3NGMwZDA4NjJiYWRlMTg3OGI4NjQ3ZjcyMDA1MTljMjMiXSwiZGVzY3JpcHRpb24iOiJBcmN1bHVzIEZJRE8yL1UyRiBLZXkgQ2FyZCBbUDcxXSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxMDAsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjJ9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo2LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDK2pDQ0FxQ2dBd0lCQWdJVVRYSnkyOGxwUVZsaElwN0VUQmkrVTRiY2FEOHdDZ1lJS29aSXpqMEVBd0l3Z1lBeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBPWlhjZ1NtVnljMlY1TVJFd0R3WURWUVFIREFoVGIyMWxjbk5sZERFVU1CSUdBMVVFQ2d3TFEyOXRjRzlUWldOMWNtVXhFREFPQmdOVkJBc01CMEZ5WTNWc2RYTXhJVEFmQmdOVkJBTU1HRU52YlhCdlUyVmpkWEpsTFVaSlJFOHRRMEV0VW05dmREQWdGdzB5TXpBME1UZ3hOVFExTlRCYUdBOHlNRFV6TURReE1ERTFORFUxTUZvd2dZQXhDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJREFwT1pYY2dTbVZ5YzJWNU1SRXdEd1lEVlFRSERBaFRiMjFsY25ObGRERVVNQklHQTFVRUNnd0xRMjl0Y0c5VFpXTjFjbVV4RURBT0JnTlZCQXNNQjBGeVkzVnNkWE14SVRBZkJnTlZCQU1NR0VOdmJYQnZVMlZqZFhKbExVWkpSRTh0UTBFdFVtOXZkREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQ2dHN3I2VkEvaCtCeW5VbnlEWk1EMFZaa1lXNlJHbnBoMHcyNWdRRFdNb3FBYWlVYUZHNU1DbGtoYWtJQnBMRis2eEpCaE8xZ3MrN0Mxay9qdVZ1djJqZ2ZNd2dmQXdIUVlEVlIwT0JCWUVGSnoxZ0Z0VFRCTmZmZkRLdmRqcFVFeXA3MHp0TUlIQUJnTlZIU01FZ2Jnd2diV0FGSnoxZ0Z0VFRCTmZmZkRLdmRqcFVFeXA3MHp0b1lHR3BJR0RNSUdBTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNBd0tUbVYzSUVwbGNuTmxlVEVSTUE4R0ExVUVCd3dJVTI5dFpYSnpaWFF4RkRBU0JnTlZCQW9NQzBOdmJYQnZVMlZqZFhKbE1SQXdEZ1lEVlFRTERBZEJjbU4xYkhWek1TRXdId1lEVlFRRERCaERiMjF3YjFObFkzVnlaUzFHU1VSUExVTkJMVkp2YjNTQ0ZFMXljdHZKYVVGWllTS2V4RXdZdmxPRzNHZy9NQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURTQUF3UlFJZ2NnWEdNRFAycmZoNEVUWTlFSkx3dVhvMVM5VWlxdEVtUGhxOS9kaVMwbkFDSVFEb3lMWm9zeDhyUkFGMXZwUlhjc1ZRRERTSG9Fcy9QYm1GM0VyL21KMHg2dz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBUG9DQVlBQUFCTm85VGtBQUFBQkdkQlRVRUFBTEdQQy94aEJRQUFBQ0JqU0ZKTkFBQjZKZ0FBZ0lRQUFQb0FBQUNBNkFBQWRUQUFBT3BnQUFBNm1BQUFGM0NjdWxFOEFBQUFoR1ZZU1daTlRRQXFBQUFBQ0FBRkFSSUFBd0FBQUFFQUFRQUFBUm9BQlFBQUFBRUFBQUJLQVJzQUJRQUFBQUVBQUFCU0FTZ0FBd0FBQUFFQUFnQUFoMmtBQkFBQUFBRUFBQUJhQUFBQUFBQUFBRWdBQUFBQkFBQUFTQUFBQUFFQUE2QUJBQU1BQUFBQkFBRUFBS0FDQUFRQUFBQUJBQUFENktBREFBUUFBQUFCQUFBRDZBQUFBQURyRWVLa0FBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFDekdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpV0UxUUlFTnZjbVVnTmk0d0xqQWlQZ29nSUNBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBnb2dJQ0FnSUNBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlnb2dJQ0FnSUNBZ0lDQWdJQ0I0Yld4dWN6cDBhV1ptUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzUnBabVl2TVM0d0x5SUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZaWGhwWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOWxlR2xtTHpFdU1DOGlQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFpVbVZ6YjJ4MWRHbHZiajQzTWp3dmRHbG1aanBaVW1WemIyeDFkR2x2Ymo0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2VW1WemIyeDFkR2x2YmxWdWFYUStNand2ZEdsbVpqcFNaWE52YkhWMGFXOXVWVzVwZEQ0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2V0ZKbGMyOXNkWFJwYjI0K056SThMM1JwWm1ZNldGSmxjMjlzZFhScGIyNCtDaUFnSUNBZ0lDQWdJRHgwYVdabU9rOXlhV1Z1ZEdGMGFXOXVQakU4TDNScFptWTZUM0pwWlc1MFlYUnBiMjQrQ2lBZ0lDQWdJQ0FnSUR4bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNHpNREF3UEM5bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNEtJQ0FnSUNBZ0lDQWdQR1Y0YVdZNlEyOXNiM0pUY0dGalpUNHhQQzlsZUdsbU9rTnZiRzl5VTNCaFkyVStDaUFnSUNBZ0lDQWdJRHhsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0ek1EQXdQQzlsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0S0lDQWdJQ0FnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrQ2lBZ0lEd3ZjbVJtT2xKRVJqNEtQQzk0T25odGNHMWxkR0UrQ2w5RUszOEFBRUFBU1VSQlZIZ0I3TjEvakdWWlFoLzJlKzZyN3BucDM5VmRQVDFkVmQwenV3d0x3OWlFMFB4WTJ5UnVTSVJETExCajVNZ0VRZ3c0L2lHd0hBS0pJNXdmc21YRmltVWxWbUpIU3BSRVRraWtTTEVpNWE5RWltTkdPSkVjZG9kZGtOZHIwQUpEZGp6czdBNHNDN3N6MDEzMTdzazU1NzdxcWY1ZFZlL1gvZkY1VUYydjNydjMzSE0rcDdhcXZuUE9QYWVxUEFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0F3SW9Fd29xdTR6SUVDQkFnUUlCQXZ3WHkzd3oxckFreGZXNzYzUnkxSjBDQUFBRUNCQWdRSUVDQUFBRUMvUlB3SC9UNzEyZHFUSUFBQVFJOUZQQUx0NGVkcHNvRUNCQWdRR0NGQW5uVXZIbit4bzJ2bWpiTlg2cENlQ2I5OGZETDc3ejU1bDllWVIxY2lnQUJBZ1FJakVKZ1l4U3QxRWdDQkFnUUlFRGdwQUlsb08rSDZZZnJ5ZVNIUWdoVjA4UlBwY0lFOUpPS09vOEFBUUlFQ0R4R1FFQi9ESXlYQ1JBZ1FJQUFnUThFNmpqWmlyR3A4czNuSWRTLy9jRTduaEVnUUlBQUFRS0xFamhZN0dWUjVTbUhBQUVDQkFnUUdLQkFVelhYOCtoNVN1ZXBkZEYvNEI5Z0gyc1NBUUlFQ0t4ZlFFQmZmeCtvQVFFQ0JBZ1E2THhBSGNMRk5weDN2cW9xU0lBQUFRSUVlaXNnb1BlMjYxU2NBQUVDQkFpc1RpRE5icjlZeFR6QjNZTUFBUUlFQ0JCWWxvQ0F2aXhaNVJJZ1FJQUFnV0VJbFAzT1E0alhodEVjclNCQWdBQUJBdDBWRU5DNzJ6ZHFSb0FBQVFJRXVpQlFoczNUNFBrTFhhaU1PaEFnUUlBQWdTRUxDT2hEN2wxdEkwQ0FBQUVDOHd2a2dKNXVRUS9ueXdydTg1ZW5CQUlFQ0JBZ1FPQXhBZ0w2WTJDOFRJQUFBUUlFQ0ZSNXlmWnFkM2YzbVJqak9mZWcrNDRnUUlBQUFRTExGUkRRbCt1cmRBSUVDQkFnMEdlQkV0RHZiR3lrRmR5clMzMXVpTG9USUVDQUFJRStDQWpvZmVnbGRTUkFnQUFCQW1zVWFPS2R6U3FXZ0c0Wjl6WDJnMHNUSUVDQXdQQUZCUFRoOTdFV0VpQkFnQUNCa3dxVUVmU3EyVGlYOWtBL25hYTRseFhkVDFxWTh3Z1FJRUNBQUlFbkN3am9UL2J4TGdFQ0JBZ1FHTE5BRzlEcjVueDZFbUlJQXZxWXZ4dTBuUUFCQWdTV0xpQ2dMNTNZQlFnUUlFQ0FRTDhGUW5OdkQzUlQzUHZkbFdwUGdBQUJBaDBYRU5BNzNrR3FSNEFBQVFJRTFpM1FWT0Y2bXVLZWwzUVgwTmZkR2E1UGdBQUJBb01XRU5BSDNiMGFSNEFBQVFJRTVoZEltNkJmbkw4VUpSQWdRSUFBQVFKUEV4RFFueWJrZlFJRUNCQWdNSEtCdERTY2dEN3k3d0hOSjBDQUFJSFZDQWpvcTNGMkZRSUVDQkFnMERlQnZFQmNXUlF1aEh2M29QZXREZXBMZ0FBQkFnUjZKU0NnOTZxN1ZKWUFBUUlFQ0t4VW9BVDBHS3NYMGhacks3MndpeEVnUUlBQWdURUtDT2hqN0hWdEprQ0FBQUVDUnhlWWhCRE81OE5UUkcrM1hUdjZ1WTRrUUlBQUFRSUVqaUVnb0I4RHk2RUVDQkFnUUdCRUFpV003Kzd1bm80eG5oMVJ1eldWQUFFQ0JBaXNUVUJBWHh1OUN4TWdRSUFBZ2U0THZEK1pYRXBickYyYXpYQTNndDc5TGxOREFnUUlFT2l4Z0lEZTQ4NVRkUUlFQ0JBZ3NFU0JFc2FiZUdjejNYK2VWbkdQNXJjdkVWdlJCQWdRSUVBZ0N3am92ZzhJRUNCQWdBQ0J4d3FFWnVOY2V2T1pja0NNUnRBZksrVU5BZ1FJRUNBd3Y0Q0FQcitoRWdnUUlFQ0F3R0FGWWwxZlRJdkU1YjhYckJFMzJGN1dNQUlFQ0JEb2lvQ0EzcFdlVUE4Q0JBZ1FJTkF0Z1RKYUhwcm0ycXhhOWxuclZ2K29EUUVDQkFnTVVFQkFIMkNuYWhJQkFnUUlFRmlVUUF6eFdsb2tMbytmTitrbWRGUGNGd1dySEFJRUNCQWc4QWdCQWYwUktGNGlRSUFBQVFJRVdvRzZxdE1DY2ZsaEFMMTE4QzhCQWdRSUVGaWVnSUMrUEZzbEV5QkFnQUNCM2d1a0VmUkx2VytFQmhBZ1FJQUFnWjRJQ09nOTZTalZKRUNBQUFFQ0t4Wm84dlZDVEZQY3k4UHM5dGJCdndRSUVDQkFZSGtDQXZyeWJKVk1nQUFCQWdUNkxGRG10RGN4dnBEMlFVOUozZjNuZmU1TWRTZEFnQUNCZmdnSTZQM29KN1VrUUlBQUFRS3JGc2dCZlZLSFNkNEgzWU1BQVFJRUNCQllnWUNBdmdKa2x5QkFnQUFCQWowVEtQUFp0N2UzbjBtajUrZG55OE9aNDk2elRsUmRBZ1FJRU9pZmdJRGV2ejVUWXdJRUNCQWdzR3lCRXNidlRpYVhZaFV2bGludWVaSzdCd0VDQkFnUUlMQlVBUUY5cWJ3S0owQ0FBQUVDL1JWb1FzZ3J1TSsyV2V0dk85U2NBQUVDQkFqMFJVQkE3MHRQcVNjQkFnUUlFRmlkUUJrdEQwMXpyZ3JoOU95eVJ0Qlg1KzlLQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0JBNEFrQ2JSaXZtd3ZwU1g1ZXRseDd3dkhlSWtDQUFBRUNCQllnSUtBdkFGRVJCQWdRSUVCZ2lBS2hxV2Q3b0ZlemRlS0cyRXB0SWtDQUFBRUMzUkVRMEx2VEYycENnQUFCQWdRNkpkQ0V0QWQ2U0FQb2FhVzRUbFZNWlFnUUlFQ0F3RUFGQlBTQmRxeG1FU0JBZ0FDQmVRWHFxcDR0RUNlZnoydnBmQUlFQ0JBZ2NCUUJBZjBvU280aFFJQUFBUUxqRWlpSlBNYVlWM0gzSUVDQUFBRUNCRllrSUtDdkNOcGxDQkFnUUlCQVR3VHlvbkFsb0ljUVovZWc1NWM4Q0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFQ0JEb24wQlp0YjJKNlI3MGFIcDcvN3BQalFrUUlFQ2dyd0lDZWw5N1RyMEpFQ0JBZ01CU0JmNzRwQTZUcytVU29XeTF0dFNyS1p3QUFRSUVDQkNvS2dIZGR3RUJBZ1FJRUNCd1dLRE1aNzkyN1dlZmpiRTViL3o4TUkzbkJBZ1FJRUJndVFJQytuSjlsVTZBQUFFQ0JIb3BNRDE5K21JYU43ODRtK0x1SnZSZTlxSktFeUJBZ0VEZkJBVDB2dldZK2hJZ1FJQUFnZVVLbERBK3JhckxhYWs0cTdndjExcnBCQWdRSUVEZ1BnRUIvVDRPWHhBZ1FJQUFBUUpab0o3RXMxVUlwMmNhUnRCOVd4QWdRSUFBZ1JVSUNPZ3JRSFlKQWdRSUVDRFFONEU0RFJkVEtzL0IzRzNvZmVzODlTVkFnQUNCM2dvSTZMM3RPaFVuUUlBQUFRSkxFU2lqNWFGcFhwaVZYclpjVzhxVkZFcUFBQUVDQkFqY0p5Q2czOGZoQ3dJRUNCQWdRQ0FMaEJDdnBYL3krSGtlUVMraG5Rd0JBZ1FJRUNDd1hBRUJmYm0rU2lkQWdBQUJBcjBVaUdGeW9hMjRHZTY5N0VDVkprQ0FBSUZlQ2dqb3ZldzJsU1pBZ0FBQkFzc1dpRlp3WHpheDhna1FJRUNBd0FNQ0F2b0RJTDRrUUlBQUFRSWpGMmp2T1kveDRCNzBrWE5vUGdFQ0JBZ1FXSjJBZ0w0NmExY2lRSUFBQVFKOUVDaHoybU1WcmxYUjdlZDk2REIxSkVDQUFJSGhDQWpvdytsTExTRkFnQUFCQW9zUXlLbDhVdGZWdVZKWXNFRGNJbENWUVlBQUFRSUVqaUlnb0I5RnlURUVDQkFnUUdBY0FtVzE5bXZYcmoyYjFtNC9OMXNlemdydTQraDdyU1JBZ0FDQkRnZ0k2QjNvQkZVZ1FJQUFBUUlkRVNoaGZQL1VxVXRwZXZ0bU84WGRDSHBIK2tZMUNCQWdRR0FFQWdMNkNEcFpFd2tRSUVDQXdCRUZTa0J2UXRoTUs4WE50bGs3NHBrT0kwQ0FBQUVDQk9ZV0VORG5KbFFBQVFJRUNCQVlsa0FkNDlrUXd1bFpxMHh4SDFiM2FnMEJBZ1FJZEZoQVFPOXc1NmdhQVFJRUNCQllzVUFKNDdHdUw4eFNlYnZsMm9vcjRYSUVDQkFnUUdDc0FnTDZXSHRldXdrUUlFQ0F3R01Fd25SNmZmYldiSjI0eHh6b1pRSUVDQkFnUUdDaEFnTDZRamtWUm9BQUFRSUUraThRUXJ4V2hUU0dIc3RHNlAxdmtCWVFJRUNBQUlHZUNBam9QZWtvMVNSQWdBQUJBcXNTaUdGaWdiaFZZYnNPQVFJRUNCQTRKQ0NnSDhMd2xBQUJBZ1FJakZ4Z05xVTliYkhtUVlBQUFRSUVDS3hjUUVCZk9ia0xFaUJBZ0FDQlRncmtkZUhhZ0I3VEZQZnliTFpVWENlcnExSUVDQkFnUUdCNEFnTDY4UHBVaXdnUUlFQ0F3RWtGeXFydHNRclhEckw2U1F0eUhnRUNCQWdRSUhCOEFRSDkrR2JPSUVDQUFBRUNReGFZMUNHY0xRME1sU0gwSWZlMHRoRWdRSUJBNXdRRTlNNTFpUW9SSUVDQUFJRzFDSlF3ZnZYcTFlZlM2dTNuN0srMmxqNXdVUUlFQ0JBWXVZQ0FQdkp2QU0wblFJQUFBUUtIQmFhblRxVUY0dUxsRk5MenkwYlFEK040VG9BQUFRSUVsaXdnb0M4WldQRUVDQkFnUUtBbkFpV014N3ErbEtLNWJkWjYwbW1xU1lBQUFRTERFaERRaDlXZldrT0FBQUVDQk9ZU0NCdnhiQlhDcVZraFJ0RG4wblF5QVFJRUNCQTRub0NBZmp3dlJ4TWdRSUFBZ2FFS3RHRjhXbDlNVC9KenQ2RVB0YWUxaXdBQkFnUTZLeUNnZDdaclZJd0FBUUlFQ0t4ZUlEVE45ZGxWODVaclJ0Qlgzd1d1U0lBQUFRSWpGaERRUjl6NW1rNkFBQUVDQkI0U0NPSDVOTVU5alorM3E4UTk5TDRYQ0JBZ1FJQUFnYVVKQ09oTG8xVXdBUUlFQ0JEb29VQUlGb2pyWWJlcE1nRUNCQWdNUTBCQUgwWS9hZ1VCQWdRSUVGaVFRSk8yV2ZNZ1FJQUFBUUlFMWlHd3NZNkx1aVlCQWdRSUVDRFFPWUY4ejNtYTJoNE83a0h2WEFWVmlBQUJBZ1FJREYzQUNQclFlMWo3Q0JBZ1FJREEwUVRLcXUwaHhxdnRBdTdXaHpzYW02TUlFQ0JBZ01EaUJBVDB4VmtxaVFBQkFnUUk5RmtnQi9SSk5Rbm5TaU9DRmR6NzNKbnFUb0FBQVFMOUZCRFErOWx2YWsyQUFBRUNCQllwVUliTHIxNjkrbHpWVk9kbkc2QWJRbCtrc0xJSUVDQkFnTUFSQkFUMEl5QTVoQUFCQWdRSURGeWdoUEhwcVZPYnNZcVgwaFpydWJrQytzQTdYZk1JRUNCQW9Ic0NBbnIzK2tTTkNCQWdRSURBcWdWS0dJOTFmU25sY3R1c3JWcmY5UWdRSUVDQXdFeEFRUGV0UUlBQUFRSUVDQlNCOUVmQm1UUnVmaXA5a1lmUWphRDd2aUJBZ0FBQkFpc1dFTkJYRE81eUJBZ1FJRUNnZ3dMdENIb0lsMmFwZkhZYmVnZHJxa29FQ0JBZ1FHREFBZ0w2Z0R0WDB3Z1FJRUNBd0hFRVF0TWM3SUV1b0I4SHpyRUVDQkFnUUdCQkFnTDZnaUFWUTRBQUFRSUVlaThRd3ZOVlNHUG9zVjBscnZmdDBRQUNCQWdRSU5BekFRRzlaeDJtdWdRSUVDQkFZR2tDd1FKeFM3TlZNQUVDQkFnUU9JS0FnSDRFSkljUUlFQ0FBSUdCQzh5bXREZWJBMituNWhFZ1FJQUFnVTRMYkhTNmRpcEhnQUFCQWdRSUxGc2dyd3ZYbEl2RWtPNUJ0NEQ3c3NHVlQ0QUFBUUlFSGlkZ0JQMXhNbDRuUUlBQUFRTGpFU2dqNkNIR3ErTnBzcFlTSUVDQUFJSHVDUWpvM2VzVE5TSkFnQUFCQXVzUTJLZ200V3k1Y0xBSCtqbzZ3RFVKRUNCQWdJQ0E3bnVBQUFFQ0JBaU1XNkJzZmI2MXRmVmNtdWgrM3Y1cTQvNW0wSG9DQkFnUVdLK0FnTDVlZjFjblFJQUFBUUtkRU5nL2RlcHlyT0ptMm1JdDE2ZUU5azVVVENVSUVDQkFnTUNJQkFUMEVYVzJwaElnUUlBQWdVY0lsREFlSnBPTGFRLzBDNDk0MzBzRUNCQWdRSURBaWdRRTlCVkJ1d3dCQWdRSUVPaXlRSmpFZlAvNXFWa2RqYUIzdWJQVWpRQUJBZ1FHS3lDZ0Q3WnJOWXdBQVFJRUNCeEpvSVR4eVRSY21xVnl0NkVmaWMxQkJBZ1FJRUJnOFFJQyt1Sk5sVWlBQUFFQ0JIb25NQTFOMmdPOVBQS2U2RWJRWnhnK0VTQkFnQUNCVlFvSTZLdlVkaTBDQkFnUUlOQlJnUkRycStrZTlDb3RFbWNFdmFOOXBGb0VDQkFnTUh3QkFYMzRmYXlGQkFnUUlFRGc2UUlXaUh1NmtTTUlFQ0JBZ01DU0JRVDBKUU1ybmdBQkFnUUlkRnhnTm1MZVhPNTRQVldQQUFFQ0JBZ01YbUJqOEMzVVFBSUVDQkFnUU9CSkFtMUFqekhkZzI1Mis1T2d2RWVBQUFFQ0JKWXRZQVI5MmNMS0owQ0FBQUVDM1JZb3FUeUVzTlZXTTkrSTdrR0FBQUVDQkFpc1EwQkFYNGU2YXhJZ1FJQUFnZTRJNUlBK1NRdkU1WDNRcmQ5ZUVQeERnQUFCQWdUV0l5Q2dyOGZkVlFrUUlFQ0FRQmNFeW1qNTF0YldtVFM3L2NKc2dyc1I5QzcwakRvUUlFQ0F3Q2dGQlBSUmRydEdFeUJBZ0FDQklsREMrUFQwNmMyMHU5cG0ybUl0dnlpZysrWWdRSUFBQVFKckVoRFExd1R2c2dRSUVDQkFvQU1DYlJpdjYwdXBMdWM3VUI5VklFQ0FBQUVDb3hZUTBFZmQvUnBQZ0FBQkFnVFNrUGxHUEpQdVFjODd1K1FoZENQb3Zpa0lFQ0JBZ01DYUJBVDBOY0c3TEFFQ0JBZ1E2SUJBQ2VPVC9iQTVTK1d6MjlBN1VETlZJRUNBQUFFQ0l4UVEwRWZZNlpwTWdBQUJBZ1FPQzB4RGsvWkFUNDlvSS9URExwNFRJRUNBQUlGVkN3am9xeFozUFFJRUNCQWcwREdCRU92bjB4VDNWS3QybGJpT1ZVOTFDQkFnUUlEQWFBUUU5TkYwdFlZU0lFQ0FBSUhIQ0lSZ2diakgwSGlaQUFFQ0JBaXNVa0JBWDZXMmF4RWdRSUFBZ1c0SnpQWlZheTUzcTFwcVE0QUFBUUlFeGlrZ29JK3ozN1dhQUFFQ0JBamtPZTFOWmtoN29GOXZaN2ZQbG9walE0QUFBUUlFQ0t4RlFFQmZDN3VMRWlCQWdBQ0JUZ2kwSStnaGJKWGF5T2VkNkJTVklFQ0FBSUh4Q2dqbzQrMTdMU2RBZ0FBQkFsVjF1OXBJQzhTZG5WR0k2TDRuQ0JBZ1FJREFHZ1VFOURYaXV6UUJBZ1FJRUZpalFBbmptNy93NGJOcGM3VUxOa0JmWTArNE5BRUNCQWdRbUFrSTZMNFZDQkFnUUlEQWlBV2FDMSs1bk81QjM1enRzR1lFZmNUZkM1cE9nQUFCQXVzWEVORFgzd2RxUUlBQUFRSUUxaUZRd3Zneit4c1gwaFQzYyt1b2dHc1NJRUNBQUFFQzl3c0k2UGQ3K0lvQUFRSUVDSXhMWUdNajMzOSthdFpvSStqajZuMnRKVUNBQUlHT0NRam9IZXNRMVNGQWdBQUJBaXNTS0dHODJkL2ZuS1Z5dDZHdkNONWxDQkFnUUlEQTR3UUU5TWZKZUowQUFRSUVDSXhBb0FuaCtxeVplVTkwSStnajZITk5KRUNBQUlIdUNnam8zZTBiTlNOQWdBQUJBa3NYQ0hXOG11NUJyOUlpY1ViUWw2N3RBZ1FJRUNCQTRNa0NBdnFUZmJ4TGdBQUJBZ1NHTFJEcjg4TnVvTllSSUVDQUFJSCtDQWpvL2Vrck5TVkFnQUFCQW9zVUtDUG1JY1lyaXl4VVdRUUlFQ0JBZ01ESkJRVDBrOXM1a3dBQkFnUUk5Rm1nQlBRWTR2WFpIdWg5Ym91NkV5QkFnQUNCUVFnSTZJUG9SbzBnUUlBQUFRTEhGbWp2T1kvVlZudG12aEhkZ3dBQkFnUUlFRmluZ0lDK1RuM1hKa0NBQUFFQzZ4T0kxZTFxSTRSd3BsUkJQRjlmVDdneUFRSUVDQkNZQ1Fqb3ZoVUlFQ0JBZ01ENEJFb2N2L3lMTCtkd2ZtRzJmTHVJUHI3dkF5MG1RSUFBZ1k0SkNPZ2Q2eERWSVVDQUFBRUNLeEFvWWJ5NThPWExhWGUxemRrOTZBTDZDdUJkZ2dBQkFnUUlQRWxBUUgrU2p2Y0lFQ0JBZ01Bd0JVb1lEL3NiRjFMenpnMnppVnBGZ0FBQkFnVDZKeUNnOTYvUDFKZ0FBUUlFQ0N4RTROUmtjcTRLWVNNVmxtZTVHMEZmaUtwQ0NCQWdRSURBeVFVRTlKUGJPWk1BQVFJRUNQUlZvSjNpdnIrL09VdmxzOXZRKzlvYzlTWkFnQUFCQXNNUUVOQ0gwWTlhUVlBQUFRSUVqaTNRaEhDOW5CVExDUHF4ejNjQ0FRSUVDQkFnc0ZnQkFYMnhua29qUUlBQUFRSzlFUWgxdkpxbXVLZjZSaVBvdmVrMUZTVkFnQUNCSVFzSTZFUHVYVzBqUUlBQUFRSlBFbWhDWGlUT2d3QUJBZ1FJRU9pSWdJRGVrWTVRRFFJRUNCQWdzRUtCTW1LZXhzNHZyL0NhTGtXQUFBRUNCQWc4UlVCQWZ3cVF0d2tRSUVDQXdNQUU4cHoySnJjcGhuaTluZDArV3lwdVlBM1ZIQUlFQ0JBZzBEY0JBYjF2UGFhK0JBZ1FJRUJnZm9IMm52TllYU2xGQlZ1c3pVK3FCQUlFQ0JBZ01MK0FnRDYvb1JJSUVDQkFnRUQvQkc3ZE9oVkNPTmUvaXFzeEFRSUVDQkFZcm9DQVB0eSsxVElDQkFnUUlQQW9nVEtmL2VJWHZwREQrWG5MdHorS3lHc0VDQkFnUUdBOUFodnJ1YXlyRWlCQWdBQUJBbXNTT0xqaGZEUEd1RG1ydzhGcmE2cVN5eElnUUlBQUFRSlp3QWk2N3dNQ0JBZ1FJREJDZ2RQMU5HK3hab3I3Q1B0ZWt3a1FJRUNndXdJQ2VuZjdSczBJRUNCQWdNRFNCRUl6T1Z1RmNEQ1R6Z2o2MHFRVlRJQUFBUUlFamk0Z29CL2R5cEVFQ0JBZ1FHQUlBaVdNTjlYKzVWa3FkeHY2RUhwVkd3Z1FJRUJnRUFJQytpQzZVU01JRUNCQWdNQXhCWnI2K3V5TXZDZTZFZlJqOGptY0FBRUNCQWdzUTBCQVg0YXFNZ2tRSUVDQVFNY0ZZb2hiYVlwN1ZhV1Y0anBlVmRValFJQUFBUUtqRVJEUVI5UFZHa3FBQUFFQ0JBNEpoSEQrMEZlZUVpQkFnQUFCQWgwUUVOQTcwQW1xUUlBQUFRSUVWaWhRUnN4RFUyMnQ4Sm91UllBQUFRSUVDQnhCUUVBL0FwSkRDQkFnUUlEQWdBUktRRytxZUQxTmJ4OVFzelNGQUFFQ0JBajBYMEJBNzM4ZmFnRUJBZ1FJRURpT1FGNFVMcTBLRjY2MEorVWIwVDBJRUNCQWdBQ0JMZ2dJNkYzb0JYVWdRSUFBQVFLckVUZ0k0eHNwbHA4cGx6eDRaVFhYZHhVQ0JBZ1FJRURnQ1FJQytoTnd2RVdBQUFFQ0JJWW9jT21sbDg3RktsNllUWEFYMFlmWXlkcEVnQUFCQXIwVUVOQjcyVzBxVFlBQUFRSUVUaVJRd25pTTcyMVdNYVNQZHIyNEU1WGtKQUlFQ0JBZ1FHRGhBZ0w2d2trVlNJQUFBUUlFT2l0UUF2cnBzSEV4YllCK3JyTzFWREVDQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0F3WG9FUU44NVVJVXlTUUI1Q044Vjl2TjhLV2s2QUFBRUNIUk1RMER2V0lhcERnQUFCQWdTV0tGRENlQlAzcnN4U3VYM1dsb2l0YUFJRUNCQWdjRndCQWYyNFlvNG5RSUFBQVFKOUYyanE2NlVKc1NwYnJ2VzlPZXBQZ0FBQkFnU0dJaUNnRDZVbnRZTUFBUUlFQ0J4UklJYTRsYWE0cDZNTm9CK1J6R0VFQ0JBZ1FHQWxBZ0w2U3BoZGhBQUJBZ1FJZEVlZ0R1RjhkMnFqSmdRSUVDQkFnTUNCZ0lCK0lPRXpBUUlFQ0JBWXZrQVpNbzlOdFRYOHBtb2hBUUlFQ0JEb240Q0EzcjgrVTJNQ0JBZ1FJSEFTZ1R5bnZkeHozbFR4ZXJzSCtteXB1Sk9VNWh3Q0JBZ1FJRUJnNFFJQytzSkpGVWlBQUFFQ0JEb3JVTFpWQzFXNFVtcVlublMycGlwR2dBQUJBZ1JHS0NDZ2o3RFROWmtBQVFJRVJpeHc2OVpHV2gvdXpJZ0ZOSjBBQVFJRUNIUldRRUR2Yk5lb0dBRUNCQWdRV0toQUdTMi84UGJiNTJPTUY2M2Z2bEJiaFJFZ1FJQUFnWVVJQ09nTFlWUUlBUUlFQ0JEb3ZFQUo2TStHc0ptMlY5dHM3MEUzeGIzenZhYUNCQWdRSURBcUFRRjlWTjJ0c1FRSUVDQXdkb0ZZMXhlcUtwamlQdlp2Qk8wblFJQUFnVTRLQ09pZDdCYVZJa0NBQUFFQ3l4RUlNWjZwUXRpWWxXNlJ1T1V3SzVVQUFRSUVDSnhJUUVBL0VadVRDQkFnUUlCQTd3UktHSi9HdURWTDVXWEx0ZDYxUW9VSkVDQkFnTUNBQlFUMEFYZXVwaEVnUUlBQWdRY0ZRdE5jbjcxV3RseDc4SDFmRXlCQWdBQUJBdXNURU5EWForL0tCQWdRSUVCZzVRTHBIdlFyYVlwN1dpY3VXc2g5NWZvdVNJQUFBUUlFbml3Z29EL1p4N3NFQ0JBZ1FHQlFBbldJNXdmVklJMGhRSUFBQVFJREVoRFFCOVNabWtLQUFBRUNCSjRnVUViTW02YTYrb1JqdkVXQUFBRUNCQWlzVWVCZ0ZkYzFWc0dsQ1JBZ1FJQUFnUlVJbElBZXFuaTltajFid1RWZGdnQUJBZ1FJRURpR2dCSDBZMkE1bEFBQkFnUUk5Rmlnck5vZXEzQzV0Q0ZVdGxqcmNXZXFPZ0VDQkFnTVUwQkFIMmEvYWhVQkFnUUlFRGdzTUF2anR6ZFNMRDl6K0EzUENSQWdRSUFBZ2U0SUNPamQ2UXMxSVVDQUFBRUNTeFc0ZVBOWHo2ZlYyeS9PMW04M2dyNVViWVVUSUVDQUFJSGpDd2pveHpkekJnRUNCQWdRNkp2QVFSamZUUGVmYjZZOTFuTDlEMTdyVzF2VWx3QUJBZ1FJREZaQVFCOXMxMm9ZQVFJRUNCQzRKMURDK09tNnZtQ0srejBUVHdnUUlFQ0FRT2NFQlBUT2RZa0tFU0JBZ0FDQjVRaUVwamxiaFRCSnBlY2hkQ1BveTJGV0tnRUNCQWdRT0xHQWdINWlPaWNTSUVDQUFJSGVDSlF3UG8zN1c3TlVYdWE0OTZiMktrcUFBQUVDQkVZaUlLQ1BwS00xa3dBQkFnUUloQ1pjTHdxeEtsdXVFU0ZBZ0FBQkFnUzZKU0NnZDZzLzFJWUFBUUlFQ0N4TklOYjFsVFRGUFpWdkFIMXB5QW9tUUlBQUFRSnpDQWpvYytBNWxRQUJBZ1FJOUVtZ0R2RjhuK3FycmdRSUVDQkFZR3dDQXZyWWVseDdDUkFnUUdDTUFtWEl2R21xcXdiUHg5ajkya3lBQUFFQ2ZSSFk2RXRGMVpNQUFRSUVDQkE0a1VDZTAxN3VPUTlWYk85QnQ0RDdpU0NkUklBQUFRSUVsaTFnQkgzWndzb25RSUFBQVFMckZ5amJxc1VRTHBlcUJBbDkvVjJpQmdRSUVDQkE0R0VCQWYxaEU2OFFJRUNBQUlFaENaU2QxVjU5OWRWVHFWRm5odFF3YlNGQWdBQUJBa01URU5DSDFxUGFRNEFBQVFJRUhpSHcvMzN4aXhlcUdDOWF2LzBST0Y0aVFJQUFBUUlkRVJEUU85SVJxa0dBQUFFQ0JKWWtVRWJRbjYzclMybUJ1TTBVMHZObHltdEx1cDVpQ1JBZ1FJQUFnUk1LQ09nbmhITWFBUUlFQ0JEb2swQ2NUQzZrV0c2S2U1ODZUVjBKRUNCQVlIUUNBdnJvdWx5RENSQWdRR0NNQXFGcHpsWWhUR1p0TjRJK3htOENiU1pBZ0FDQnpnc0k2SjN2SWhVa1FJQUFBUUp6Q1pRdzNzUzROVXZsWmN1MXVVcDBNZ0VDQkFnUUlMQVVBUUY5S2F3S0pVQ0FBQUVDSFJOb210a2U2T2xPZFBlZ2Q2eHpWSWNBQVFJRUNMUUNBcnJ2QkFJRUNCQWdNQUtCZWpLNW5LYTRWMm1ST0F1NWo2Qy9OWkVBQVFJRStpa2dvUGV6MzlTYUFBRUNCQWdjU3lDR2VQNVlKemlZQUFFQ0JBZ1FXTG1BZ0w1eWNoY2tRSUFBQVFJckZTZ2o1bW5nL1BtVlh0WEZDQkFnUUlBQWdXTUxiQno3RENjUUlFQ0FBQUVDZlJKb3A3VEhtTzVCZC90NW56cE9YUWtRSUVCZ2ZBSkcwTWZYNTFwTWdBQUJBdU1TYUZkdEQvVm1hWFpJdTZGN0VDQkFnQUFCQXAwVUVOQTcyUzBxUllBQUFRSUVGaUxRaHZGYnQwNmwwczRzcEVTRkVDQkFnQUFCQWtzVE1NVjlhYlFLSmtDQUFBRUMzUkE0LzduUFhVamo1aGRqRzllTm9IZWpXOVNDQUFFQ0JBZzhKR0FFL1NFU0x4QWdRSUFBZ2NFSWxERCtiQWliNmZiei9KRWZBdnBndWxkRENCQWdRR0JvQWdMNjBIcFVld2dRSUVDQXdBY0NiUmlmTk9kVExEZkYvUU1YendnUUlFQ0FRQ2NGQlBST2RvdEtFU0JBZ0FDQkJRckVqYk5WQ1BsM3ZtWGNGOGlxS0FJRUNCQWdzR2dCQVgzUm9zb2pRSUFBQVFMZEVTZ2o2RTNUWEozTmEyOG51WGVuZm1wQ2dBQUJBZ1FJSEJJUTBBOWhlRXFBQUFFQ0JBWXBFSnEwQjNwNnhLcmRjbTJRamRRb0FnUUlFQ0RRZndFQnZmOTlxQVVFQ0JBZ1FPQ0pBckdhWEVsVDNOTXhCdENmQ09WTkFnUUlFQ0N3WmdFQmZjMGQ0UElFQ0JBZ1FHRFpBbldJNTVaOURlVVRJRUNBQUFFQzh3c0k2UE1iS29FQUFRSUVDSFJWb0V4cGp6RSszMVp3ZGlkNlYydXJYZ1FJRUNCQVlPUUNBdnJJdndFMG53QUJBZ1FHSy9EQm5QYW0ycW1pNmUyRDdXa05JMENBQUlIQkNBam9nK2xLRFNGQWdBQUJBZzhKdE51cTFlRmllU2VrM2RBOUNCQWdRSUFBZ2M0S0NPaWQ3Um9WSTBDQUFBRUNjd20wWWZ6bGwwK25VczdPVlpLVENSQWdRSUFBZ1pVSUNPZ3JZWFlSQWdRSUVDQ3dIb0Z6WC83eWhUUzkvZUpzZ3JzUjlQVjBnNnNTSUVDQUFJRWpDUWpvUjJKeUVBRUNCQWdRNkoxQUNlUFBUaWFicWVhWDNJUGV1LzVUWVFJRUNCQVlvWUNBUHNKTzEyUUNCQWdRR0pIQVpISSt0ZmE1RWJWWVV3a1FJRUNBUUc4RkJQVGVkcDJLRXlCQWdBQ0Jwd3VFR005V0lVeG1SNXJpL25ReVJ4QWdRSUFBZ2JVSkNPaHJvM2RoQWdRSUVDQ3dWSUVTeHFjeFhwMmw4ckluK2xLdnFIQUNCQWdRSUVCZ0xnRUJmUzQrSnhNZ1FJQUFnVzRMaEtxNVhtb1lxeHpRamFCM3U3dlVqZ0FCQWdSR0xpQ2dqL3diUVBNSkVDQkFZTmdDYVhiN1pwcmluaG81VzhkOTJNM1ZPZ0lFQ0JBZzBHc0JBYjNYM2FmeUJBZ1FJRURnYVFMeHd0T084RDRCQWdRSUVDRFFEUUVCdlJ2OW9CWUVDQkFnUUdEUkFtWElQRmJ4K1VVWHJEd0NCQWdRSUVCZ09RSUMrbkpjbFVxQUFBRUNCTll0MEM0SzExVFgyejNRM1g2KzdnNXhmUUlFQ0JBZzhEUUJBZjFwUXQ0blFJQUFBUUw5Rkdodk9xL0R4Vkw5WUlHNGZuYWpXaE1nUUlEQW1BUUU5REgxdHJZU0lFQ0F3RmdFMnVIeVYxODluUnA4ZGl5TjFrNENCQWdRSU5CM0FRRzk3ejJvL2dRSUVDQkE0REVDNTcvNHhRdHBldnVsMkk2bG0rUCtHQ2N2RXlCQWdBQ0JyZ2dJNkYzcENmVWdRSUFBQVFLTEV5aGgvTm02M2t4RlhwcHRzU2FnTDg1WFNRUUlFQ0JBWUNrQ0F2cFNXQlZLZ0FBQkFnVFdKcENEZVBuOUhrTzUvL3k1V1UwRTlMVjFpUXNUSUVDQUFJR2pDUWpvUjNOeUZBRUNCQWdRNktMQVFSaWZWTGR2YjZRS1RtYVZuT2JQTWNaSkZVTCtYZDlPY3ArOTZSTUJBZ1FJRUNEUVRZSDh5OXlEQUFFQ0JBZ1E2TDdBUVJnL0dBblBvVHNIOFRaOHYvYmF2UlpzYjIrZitkMFFuZ3NoL29FcUxkNmVEc2pISEp4Mzd6aFBDQkFnUUlBQWdXNEpDT2pkNmcrMUlVQ0FBQUVDQndKdElMK2RndlZySldEbk1GNUd4ZzhPU0o5UFhYcnBoWjJOdmNtSFlsMTliVHJocTFNT2YrVk9WZTJjanZGR1doenV3aXkvbXpGM0NNMVRBZ1FJRUNEUVZRRUJ2YXM5bzE0RUNCQWdNRGFCSEtKektNOGZCNlBqMHhUT0R4NlRhemR2dmppdDlsK05NWHg5RmNNL213TjUzSThmam5VNEYwSStMVDFTS2o4b29IM0J2d1FJRUNCQWdFQmZCQVQwdnZTVWVoSWdRSURBRUFWeUtEKzRSL3krMGZGcjE2NmRiWjZkZkNTRjhXOUptZnRiVTJUL2h2M1lmRldvNmd0dEdHOW50cGNvbjI0MmowM1RudDhHOVp6UkQzOE0wVTZiQ0JBZ1FJREE0QVFFOU1GMXFRWVJJRUNBUUljRmNtZytHQ2x2MHZPRGorcmxsMTkrNWt2dnZmZEtVOWUvUDFUTlB6K040WnZpTkw0VTZuclNadTZZRjMzTGVieXBtaWFmbHlKNGVhY3RMd1MvMHd1S2Z3Z1FJRUNBUUg4Ri9ETHZiOStwT1FFQ0JBajBSeUN2cnA3RCtYNzZ1RGRTdm5YanhuWUszUjlOaTdsOTV4ZnZ2UDhIMGhGZm15SjMrdDFjcHlDZW9uaisvK2swbjNNUXh0dFJjV0c4a1BpSEFBRUNCQWdNVFVCQUgxcVBhZzhCQWdRSWRFSGc4RWg1RHVUM1F2bVZGMTk4cFpwTy80VjB3SGVsZWVrcG5JZkxWZG9KTGJTajR5bVFOeW1RcDJUZWJvOFcwbWUvcTd2UW8rcEFnQUFCQWdSV0lPQ1gvZ3FRWFlJQUFRSUVSaU9RZzNrZUxiOHZsRisrZWZQVnVtbis1VFJDL3QxeHV2L05hZHI2czNreHR6SkNIdU0wVFZsUEs3dVY2ZW9wa09jUjlGeU1Cd0VDQkFnUUlEQTJBUUY5YkQydXZRUUlFQ0N3YUlIRG8rVjVPbnFaa241MWQvZmxHT0wzcEsvL1dCb3AvK2FxRHFkTEtFOHZ0TlBXMDJtaGhQbEpDdWVMcnBQeUNCQWdRSUFBZ1I0S0NPZzk3RFJWSmtDQUFJRk9DT1JVblVmTGN5QXZVOWd2M3J5NXVkRTBmemhVOFU4MFZieWRacW1mYlVmSzB4M2xUWnE2Zm0rVTNMVDFUdlNnU2hBZ1FJQUFnWTRKQ09nZDZ4RFZJVUNBQUlIT0N4eGU4SzJNbGwvZTJmbG91bzM4QjlOVTllOUpnK0U3WllwNnZxZThMUEEyR3lsM0wzbm5PMVlGQ1JBZ1FJREF1Z1VFOUhYM2dPc1RJRUNBUUY4RTh1L012TDFaR1MyL3NMdDcrWFJWZlc5YTNlMEhVeGIvdHJ5bVc1cktua2JLeS92cG52SzBGTHRRM3BlK1ZVOENCQWdRSU5BSkFRRzlFOTJnRWdRSUVDRFFVWUdEYWV3NWxMZWo1WG5CdHpqOW9SVEt2eS9kVjc2ZEYzckxxNzJWMGZLYzB0djd5anZhSE5VaVFJQUFBUUlFdWl3Z29IZTVkOVNOQUFFQ0JOWWxFS3JiNmY3eTEwb29MOEg4eXM3T2Q2UVI4VDhYbXVhN3E3cCs1bDRvVHk4YUxWOVhON2t1QVFJRUNCQVlsb0NBUHF6KzFCb0NCQWdRbUUrZ1RxZm5qLzFaT0ErWGQzZi9XSHJoejhkUS9jRzh4bHRhN0MxTmRJOTc2Wmk4K3JyZm8vTjVPNXNBQVFJRUNCQTRKT0FQaTBNWW5oSWdRSURBYUFVK0NPWXBmbCs3ZHUxc2MrclVuMmhDOWVmU0hQZGJSU1hkWUo3Q2VaTkNlVDcyMUdpbE5Kd0FBUUlFQ0JCWW1vQ0F2alJhQlJNZ1FJQkFEd1R1QytiYjI5dGJkK3I2UjlJTjUvOW11ci84cTBKZWliMnMvSllXaHd2VnhpeWM5NkJacWtpQUFBRUNCQWowVVVCQTcyT3ZxVE1CQWdRSXpDdHdYekRmZXZIRjY3SFovOUU3VmZqaE5JMzllZ3JsYWEzMjZjRys1WG5oTjc4djV4VjNQZ0VDQkFnUUlQQlVBWDl3UEpYSUFRUUlFQ0F3SUlHNnVwM3VNVzhYZjJ0bXdmekg0blQvejRTNnZwSW1zYWQ3ekVzd3QwWGFnRHBkVXdnUUlFQ0FRRjhFQlBTKzlKUjZFaUJBZ01COEFyZlRLSGdPNXE5VlRkbkRQTVovS3dYekgwM0IvSEs3ZjNsajRiZjVoSjFOZ0FBQkFnUUl6Q2tnb004SjZIUUNCQWdRNkx4QS9sMDN6ZUg4cFpkZWV2YkwwNzBmVFJQWWZ5SnRsWGE5U211K3BZWGYybUJ1NGJmT2Q2UUtFaUJBZ0FDQm9Rc0k2RVB2WWUwalFJREFlQVh5ZmVacEVmYXlsM2wxWlhmM0IzNTNmKy9mVHlQbVgxT0NlWnh0bFNhWWovYzdSTXNKRUNCQWdFREhCUElmTHg0RUNCQWdRR0JJQXFHNmRTdHZnNVkyTEsrbVc3dTdmM0RyeHU3UHBzWGZmanA5ZkUzTWk3KzE3K1ZqL0I1TUNCNEVDQkFnUUlCQU53U01vSGVqSDlTQ0FBRUNCQllqa0grdjdWZXZ2NzUzZVh2N1JwaUV2NUttcy8vSlBJeWVwcktuVmRuei93Vy8reFpqclJRQ0JBZ1FJRUJnd1FMK1NGa3dxT0lJRUNCQVlDMENlU1E4ZitUUjhXcHJaK2ZIWXgzK296UmlmakVGODd4cjJqUkZjNy96TW80SEFRSUVDQkFnMEZrQmY2eDB0bXRVakFBQkFnU09LSkIvbDVWcDY1ZDNkbjVmQ05YZlRBdkFmY3VoKzh3M2hQTWpTanFNQUFFQ0JBZ1FXS3VBZ0w1V2ZoY25RSUFBZ1RrRTdvMmFiMjl2bjdsVGgvODRsZlVYMHFoNVZlNHpEeUcvbis4ejl5QkFnQUFCQWdRSTlFSkFRTzlGTjZra0FRSUVDRHdnY0cvVS9Nck43WC94VGhQK2RscWQvU05sT25zVDAzUjI5NWsvNE9WTEFnUUlFQ0JBb0FjQ2VYVEJnd0FCQWdRSTlFWGdZSVgyL2QzZDNlZlMxbW4vZVJYci96T05tdWR3bnZjenp4dXIrWS9QZmVsTjlTUkFnQUFCQWdUdUUvQkh6SDBjdmlCQWdBQ0JEZ3RNVXQybWVZWDJxemUzdisyOUdQL3JOSXY5bFJUTTB5cHdhVXUxWURwN2gvdE8xUWdRSUVDQUFJRWpDQmhCUHdLU1F3Z1FJRUJnelFMdHZ1YlRYSXZMTjNiK2c2YXAvMEhhTCsyVmxNM3pxSG5lUE0xL2NGNXpGN2s4QVFJRUNCQWdNTCtBUDJqbU4xUUNBUUlFQ0N4UElHOWhQcm0zcjNrZC9rNGFOZitPR0p1MHIzbTFuOWFEc3dqYzh1eVZUSUFBQVFJRUNLeFl3QWo2aXNGZGpnQUJBZ1NPTEpDbnRPZkgvdGFON2U4SmRmaUZkSy81ZDVRVjJxc3FHalZ2Y2Z4TGdBQUJBZ1FJREVkQVFCOU9YMm9KQVFJRWhpU1FaM2psS2UzeHlvMmR2MXBWOWYrV25tL0dHUGRtSzdUbmtYVVBBZ1FJRUNCQWdNQ2dCRXh4SDFSM2Fnd0JBZ1FHSVBEcXE2ZXJUMzNxN3NXYk56ZFBOYzMvbEFMNWQrWHQwMUxMbXZSaFN2c0F1bGdUQ0JBZ1FJQUFnVWNMQ09pUGR2RXFBUUlFQ0t4ZW9MM2ZQSVh6U3pzNzM3QVJtLysxcXNPSDhrSnc2WTM4KytwZ3l2dnFhK2FLQkFnUUlFQ0FBSUVWQ0pqaXZnSmtseUJBZ0FDQnB3cmszMGY1WS8veTd1NzNib1R3RDlQekQrVzl6Vk00ejZQbXByUW5CQThDQkFnUUlFQmcyQUlDK3JEN1Yrc0lFQ0RRQjRFOE1wNm5yMCt2N096OFZCMnF2eHVyK0V3SzUvdnBOVlBhKzlDRDZraUFBQUVDQkFnc1JNQVU5NFV3S29RQUFRSUVUaWlRZncvbElGNXQ3ZTcrVjJsSys1K2UzVytlVm1rUGZrZWRFTlZwQkFnUUlFQ0FRRDhGL1BIVHozNVRhd0lFQ1BSZjRIYTZyL3kxRk01ZmV1blpyZjM5Zkw5NVhneHVMelVzLzI0eXc2di9QYXdGQkFnUUlFQ0F3REVGL0FGMFREQ0hFeUJBZ01BQ0JHN2RPcFhEK2M3T3pwVXIrL3YvOTZGdzduN3pCZkFxZ2dBQkFnUUlFT2luZ0lEZXozNVRhd0lFQ1BSWElJZnoxMS9mMjl6ZXZua25WUDlQQ05XdHRGTDczZFFnOTV2M3QxZlZuQUFCQWdRSUVGaUFnQ251QzBCVUJBRUNCQWdjVVNEdmNmNzY2M2UzdHJlL0prN3FuMGxuWFk4eDVwWGFUeCt4QkljUklFQ0FBQUVDQkFZcllBUjlzRjJyWVFRSUVPaVlRQjQ1VDN1Y2IxMi9maXROYWY4SEtaU1hjSjVxYWVTOFkxMmxPZ1FJRUNCQWdNQjZCSXlncjhmZFZRa1FJREF1Z2RtMDlpdTd1OSthdGxEN21iUkMrM05WM2tZdEJPRjhYTjhKV2t1QUFBRUNCQWc4UWNBSStoTnd2RVdBQUFFQ0N4QTRGTTZyR1A5K1ZhVnducWExMjBadEFiYUtJRUNBQUFFQ0JBWWxJS0FQcWpzMWhnQUJBaDBUbUlYelN6czcvMHhWcFhBZXdwbjBPZTk3YnVTOFkxMmxPZ1FJRUNCQWdNRDZCVXh4WDM4ZnFBRUJBZ1NHS1RBTDUyVkJ1RHI4SDZtUlo4ckl1WEErelA3V0tnSUVDQkFnUUdCdUFTUG9jeE1xZ0FBQkFnUWVJYkNSdDFKTDk1enZ4RHI4dmJRZzNBdmxublBoL0JGVVhpSkFnQUFCQWdRSXRBSUN1dThFQWdRSUVGaTBRSjZkdFgveDVzM05OSjM5NzRVUWRodjNuQy9hV0hrRUNCQWdRSURBQUFVRTlBRjJxaVlSSUVCZ2pRS1RkTzF5ai9sR00vM2ZVemovMnRrKzUrNDVYMk9udURRQkFnUUlFQ0RRRHdFQnZSLzlwSllFQ0JEb2cwRCtuVExORmIxeVkvZC9DWFg5clduay9HNzZVampQS0I0RUNCQWdRSUFBZ2FjSUNPaFBBZkkyQVFJRUNCeFpJTjFxbnNMNTd1NS9rVWJPLzBoc21yMzB3dWtqbisxQUFnUUlFQ0JBZ01ESUJRVDBrWDhEYUQ0QkFnUVdJbkM3eXZlZFQ3ZHU3UHhFcU1PUHhlblVWbW9MZ1ZVSUFRSUVDQkFnTUNZQkFYMU12YTJ0QkFnUVdJYkFxNitlcmw2cjlyZHVibjkzVllXL2tVYk9ZOXJ2M08rWFpWZ3Jrd0FCQWdRSUVCaTBnSDNRQjkyOUdrZUFBSUdsQzJ4VW4vclUzU3ZYcjc4U20vQS9wMVhiOHdXYjlKRVhpL01nUUlBQUFRSUVDQkE0aG9BUmptTmdPWlFBQVFJRTdoTW9LN1pmdTNidGJMVXgrYnZwdnZNelZZeDVhcnR3ZmgrVEx3Z1FJRUNBQUFFQ1J4TVEwSS9tNUNnQ0JBZ1FlRmlnREpmdm45cjQ3MU00LzdxeVluc0labVk5N09RVkFnUUlFQ0JBZ01DUkJBVDBJekU1aUFBQkFnVHVFN2gxSzIrZDFxUVYyLys5dEozYTkxcXgvVDRkWHhBZ1FJQUFBUUlFVGlRZ29KK0l6VWtFQ0JBWXNVQU81NisvdnJlMXMvUHRWYWorV2dybkdjTzA5aEYvUzJnNkFRSUVDQkFnc0JnQkFYMHhqa29oUUlEQVdBUW1PWnlmMzltNUVrUDQ2Vm1qcCttejN5ZGorUTdRVGdJRUNCQWdRR0JwQXY2Z1docXRnZ2tRSURBNGdaQmFWSWJMVDlmaHYwMzduZS9FR1BmU2EwYlBCOWZWR2tTQUFBRUNCQWlzUTBCQVg0ZTZheElnUUtDUEFyZHU1UVhnNHBVYk8zOHBMUXIzUitKMHVwOFNlNzRYM1lNQUFRSUVDQkFnUUdBQkFnTDZBaEFWUVlBQWdjRUx6TzQ3djN6anhoK3FxdkJYMDMzbnNRckJ5UG5nTzE0RENSQWdRSUFBZ1ZVS0NPaXIxSFl0QWdRSTlGT2czSGVlVm16ZnFXUHpQODZha0tlNjV5bnZIZ1FJRUNCQWdBQUJBZ3NTRU5BWEJLa1lBZ1FJREZRZ2gvQzhDRng2eFA4aGpacHZWZTQ3YnpuOFM0QUFBUUlFQ0JCWXNJQ0F2bUJReFJFZ1FHQlFBcmVxZk45NXRiVzcrNWZUZnVmZk1Wc1V6bjNuZytwa2pTRkFnQUFCQWdTNklsRCs4T3BLWmRTREFBRUNCRG9rY0NzdEFQZDZWZlk3ajZINkQ2dDgzM25WQnZZTzFWSlZDQkFnUUlBQUFRS0RFVENDUHBpdTFCQUNCQWdzVktETzRYenp3eCsrR092cXY1dVY3TDd6aFJJcmpBQUJBZ1FJRUNCd3Y0Q0FmcitIcndnUUlFQ2dGU2dMd05WMzcveXRFT3FYN0hmdTI0SUFBUUlFQ0JBZ3NId0JBWDM1eHE1QWdBQ0JmZ25rTGRYU3duQlhkbmIrOVZDSEg0alRacHJTdWx1aSt0V0xha3VBQUFFQ0JBajBVRUJBNzJHbnFUSUJBZ1NXS0pDbXRyKytsN2RVUzV1by9XY3gzM1lleW5acXRsUmJJcnFpQ1JBZ1FJQUFBUUpaUUVEM2ZVQ0FBQUVDQndJZmhQQVEvOHUwYXZ1VjlNWmUrdkM3NGtESVp3SUVDQkFnUUlEQUVnWDgwYlZFWEVVVElFQ2dWd0szYnVWcDdFMmEydjZENmI3ejc4bFQyOVBYdGxUclZTZXFMQUVDQkFnUUlOQm5BUUc5ejcybjdnUUlFRmljUUpuYXZuWGp4bmFhMFA2ZnhpWXQyTjVPYlYvY0ZaUkVnQUFCQWdRSUVDRHdSQUVCL1lrODNpUkFnTUJvQk5ycDdUSCtkVlBiUjlQbkdrcUFBQUVDQkFoMFRFQkE3MWlIcUE0QkFnUldMbkNyVEdPZmJ0M1kvcDQwYXY3OWFmUTg3M2R1MWZhVmQ0UUxFaUJBZ0FBQkFtTVhFTkRIL2gyZy9RUUlqRjBnVks5WGU5dmIyMmRpREg4anJkbWVIL25UQnd2R2xaZjhRNEFBQVFJRUNCQWdzR3dCQVgzWndzb25RSUJBdHdVbXVYcDNKdUduMHRUMnI2NWl6S3UybDllNlhXMjFJMENBQUFFQ0JBZ01UMEJBSDE2ZmFoRUJBZ1NPS3BDRCtQN2xtemRmVFFQbS8wNVpHRTQ0UDZxZDR3Z1FJRUNBQUFFQ0N4Y1EwQmRPcWtBQ0JBajBScURNYUsvajlLK2xCZHRQcDlIei9WUnp2eGQ2MDMwcVNvQUFBUUlFQ0F4TndCOWlRK3RSN1NGQWdNRFJCTm85ejIvYytLTnA5UHk3WTB4N25vZGdZYmlqMlRtS0FBRUNCQWdRSUxBVUFRRjlLYXdLSlVDQVFLY0Y4Z0p3YWJUODFxazBhdjVYT2wxVGxTTkFnQUFCQWdRSWpFaEFRQjlSWjJzcUFRSUVpc0N0VzJXa2ZPdm01MzQwMU9IM3BudlA4OVIyQzhQNTlpQkFnQUFCQWdRSXJGbkFkTVkxZDRETEV5QkFZTVVDZGZYNjYzdm50N2UzMHJacWY3R0thY3Z6RVB6SDJoVjNnc3NSSUVDQUFBRUNCQjRsNEkreVI2bDRqUUFCQXNNVktELzNUOWYxVDRRUVhrak56TnVxK1YwdzNQN1dNZ0lFQ0JBZ1FLQkhBdjRvNjFGbnFTb0JBZ1RtRkNqYnFsMjdlZlBEVlJWL3pMWnFjMm82blFBQkFnUUlFQ0N3WUFFQmZjR2dpaU5BZ0VDSEJmTGljTlcwYWY1aXFPdHo2YW5SOHc1M2xxb1JJRUNBQUFFQzR4TVEwTWZYNTFwTWdNQTRCY3JvK1pVWHI3OFNRL1VuWjZQbjFpRVo1L2VDVmhNZ1FJQUFBUUlkRlJEUU85b3hxa1dBQUlGbENJVHBKTjk3ZmpwdHI1WlhiaThqNnN1NGpqSUpFQ0JBZ0FBQkFnU09MMkQwNVBobXppQkFnRURmQlBMbytYUnpkL2ZyWXhYL2phcUpWbTd2V3crcUx3RUNCQWdRSURBS0FTUG9vK2htalNSQVlPUUNaYVE4cGZRZlMvZWViOHhHei8zOEgvazNoZVlUSUVDQUFBRUMzUlB3QjFyMytrU05DQkFnc0VpQmUvZWVwd250UDFqdVBROGh2K1pCZ0FBQkFnUUlFQ0RRTVFFQnZXTWRvam9FQ0JCWXNFQjduM2t6K2RFcWhHZmNlNzVnWGNVUklFQ0FBQUVDQkJZb0lLQXZFRk5SQkFnUTZKaEFHVDIvZFAzNmk2bGVQekFiUGZkenYyT2RwRG9FQ0JBZ1FJQUFnUU1CZjZnZFNQaE1nQUNCNFFtVTBmT05qZnBIMHNydEY5MTdQcndPMWlJQ0JBZ1FJRUJnV0FJQytyRDZVMnNJRUNCd0lKREQrZjdGbXpjM1l3dy9ISzNjZnVEaU13RUNCQWdRSUVDZ3N3SUNlbWU3UnNVSUVDQXdoOER0cWl3RXR4SDN2eS9VWWFlS1RkNzMzTS84T1VpZFNvQUFBUUlFQ0JCWXRvQS8xcFl0ckh3Q0JBaXNYaUJVcjFVbGtJY3EvRWlhMnA3M1BXOFhpMXQ5WFZ5UkFBRUNCQWdRSUVEZ2lBSUMraEdoSEVhQUFJRWVDWlRSODZ1N3UvOVNTdWJmR0dOc1V0Mzl2TzlSQjZvcUFRSUVDQkFnTUU0QmY3Q05zOSsxbWdDQllRdWtJZk9xU3FuOFQ2V1I4eXFOb09lQWJnUjkySDJ1ZFFRSUVDQkFnTUFBQkFUMEFYU2lKaEFnUU9DUVFCNDluMTdaM3Y3YTlQbTdabHVybFJIMVE4ZDRTb0FBQVFJRUNCQWcwRUVCQWIyRG5hSktCQWdRbUVPZ0hTbWZoTzlQaThNOU85dGF6ZWo1SEtCT0pVQ0FBQUVDQkFpc1NrQkFYNVcwNnhBZ1FHRDVBdmxuK3Y3Mjl2YVpLbGIvYXJyMzNPSnd5emQzQlFJRUNCQWdRSURBd2dRRTlJVlJLb2dBQVFKckZ5Zy8wKzlNSnQrWkZtMy95T3plY3ovbjE5NHRLa0NBQUFFQ0JBZ1FPSnFBUDl5TzV1UW9BZ1FJOUVHZ0xBNFhxdWI3TEE3WGgrNVNSd0lFQ0JBZ1FJREEvUUliOTMvcEt3SUVDQkRvcVVEK0Q2N1R6ZTN0bTdFS2Y2aHEwc0x0SVZnY3JxZWRxZG9FQ0JBZ1FJREFPQVdNb0krejM3V2FBSUdoQ2R4dTl6bXZKNVB2VHRQYkwxb2NibWdkckQwRUNCQWdRSURBR0FTTW9JK2hsN1dSQUlHaEM0VHF0V3EvTkRMR1A5NDJObStBN2tHQUFBRUNCQWdRSU5BbkFTUG9mZW90ZFNWQWdNQ2pCY3JQOHMwYk4zNVBGYXJmMTY3ZW5wNTVFQ0JBZ0FBQkFnUUk5RXBBUU85VmQ2a3NBUUlFSGlsUXduZ2Rtank5L2ZSc2VydWY3NCtrOGlJQkFnUUlFQ0JBb0xzQy9vRHJidCtvR1FFQ0JJNHEwRTV2YjhJZlRlSGMzdWRIVlhNY0FRSUVDQkFnUUtCakFnSjZ4enBFZFFnUUlIQk1nYkpTKzlXZG5XK29xbmlyVEcrdjJnWGpqbG1Pd3drUUlFQ0FBQUVDQk5Zc0lLQ3Z1UU5jbmdBQkFuTUtsT250VFFqZkdlcDZZdlgyT1RXZFRvQUFBUUlFQ0JCWW80Q0F2a1o4bHlaQWdNQ2NBam1jbCtudGFXTDdIeTdUMjYwTk55ZXAwd2tRSUVDQUFBRUM2eE1RME5kbjc4b0VDQkNZVjZEOERMKzZ1L3ZWb1lyZk9GdTkzYy8xZVZXZFQ0QUFBUUlFQ0JCWWs0QS81TllFNzdJRUNCQllnRUNaM3A1R3o3ODloUHBjRmF0cEt0UFA5UVhBS29JQUFRSUVDQkFnc0E0QmY4aXRROTAxQ1JBZ3NCaUJsTTNUMG5CVi9NNzhiL29vWHkrbWFLVVFJRUNBQUFFQ0JBaXNXa0JBWDdXNDZ4RWdRR0F4QW5uMGZIcng1czNOdEsvYVIwczBUOFBvaXlsYUtRUUlFQ0JBZ0FBQkF1c1E4TWZjT3RSZGt3QUJBdk1MbE8zVkpqRitTd2pWVGhvOWIxS1JmcWJQNzZvRUFnUUlFQ0JBZ01EYUJQd3h0elo2RnlaQWdNRDhBaUZPYjFjcG9hZlo3VG1nZXhBZ1FJQUFBUUlFQ1BSWVFFRHZjZWVwT2dFQ294VzR0NzF2UkNsb0FBQkFBRWxFUVZSYUNPSGJ5cTNuNmNsb05UU2NBQUVDQkFnUUlEQVFBUUY5SUIycEdRUUlqRXFnL095K2RQMzZpN0VLdjdkc3I1WnVSQitWZ01ZU0lFQ0FBQUVDQkFZb0lLQVBzRk0xaVFDQndRdVVNRjVQSnQrVW5seE1yYzNUMndYMHdYZTdCaElnUUlBQUFRSkRGeERRaDk3RDJrZUF3R0FGNmhCLy82SDd6d1gwd2ZhMGhoRWdRSUFBQVFKakVSRFF4OUxUMmttQXdKQUVwcmt4YVd1MWo3WmJuN3YvZkVpZHF5MEVDQkFnUUlEQWVBVUU5UEgydlpZVElOQlBnZnh6TzE3ZTJkbE5zOXBmS2ZlZkI5dXI5Yk1yMVpvQUFRSUVDQkFnY0wrQWdINi9oNjhJRUNEUWRZSDI1M1pkdjVyR3pUZFRaZDEvM3ZVZVV6OENCQWdRSUVDQXdCRUZCUFFqUWptTUFBRUNYUkpJTjV4Lzg2SDd6N3RVTlhVaFFJQUFBUUlFQ0JBNG9jREdDYzl6R2dFQ0JBaXNYaUF2QkpkSHpQTU42TjlZUGx1OHZXWHdMd0VDQkFnUUlFQmdBQUpHMEFmUWlacEFnTUJvQkVwQXYzYnQydG1VMEwrdXREcEk2S1BwZlEwbFFJQUFBUUlFQmk4Z29BKytpeldRQUlFQkNaU3QxUGFmbTl4SUM4UzlXQmFJcy8vNWdMcFhVd2dRSUVDQUFJR3hDd2pvWS84TzBINENCUG9rVUFKNjNDOEx4RDJiS202QnVENzFucm9TSUVDQUFBRUNCSjRpSUtBL0JjamJCQWdRNkpwQUNQRnJEeTBRVjBKNzErcW9QZ1FJRUNCQWdBQUJBc2NYRU5DUGIrWU1BZ1FJckVzZzVndW5SUDcxYVpHNGRkWEJkUWtRSUVDQUFBRUNCSllrSUtBdkNWYXhCQWdRV0lMQU5KV1o4bm40Y0NrN3BKM1FQUWdRSUVDQUFBRUNCQVlqWUp1MXdYU2xoaEFnMEZHQmd4Q2RQeDg4ejhQZjdYWnBSNjkwL2crcXpaWGQzZTIwT055SFpxZjVqNnhIOTNNa0FRSUVDQkFnUUtEekFnSjY1N3RJQlFrUTZMbkF3VnowZzg4SHpjbGgvY0hYRHQ1NzFPY1M3c05rY2kxTzl6ZG5CeHdFL2tjZDd6VUNCQWdRSUVDQUFJR2VDUWpvUGVzdzFTVkFvQmNDWmJUNytlZWZ2elk5ZGVxL1NlUG01MEtzUGhkRDJFdTF2NUJTOWQ5ODU4MDNYMHZQSitralQxcy95cU1ONDlQcEsybG1lNTFHMGZONStYd1BBZ1FJRUNCQWdBQ0JnUWdJNkFQcFNNMGdRS0I3QXMxeno5WFZkUC9iUTEyZnpZdTY1WVNkbmxmTnRObE5UNzhwZmN6dUtUL0NTUHJ0MjFYMTJtdFZyS3Zka0V0cW1sUmdtOWxUT1I0RUNCQWdRSUFBQVFJREVIRC80Z0E2VVJNSUVPaW13SFF5ZVRkRjZMZGkwNlI4SHUra3ovdk5kSG9uallEZjJ0cmQvZjVaclk4MkN2N2FhKzEwK0tiNlNEZGJxMVlFQ0JBZ1FJQUFBUUx6Q2dqbzh3bzZud0FCQW84Uk9QMlZyK3luVk4zTVJybzMwdWM4YXlsOTVLd2Rmekw5azhQNWZ2cDQybEI0ZnY5Z0t2eUgyaTNXbm5aS09zT0RBQUVDQkFnUUlFQ2dWd0lDZXErNlMyVUpFT2lKUUJudGZ2dnR0OTlMb2Z4M0g0alNrenlTWHRYMU4xemUzZjJoV1h1ZU5vcGVpbmpwcFplZVRWSCtham1uekhQdmlZWnFFaUJBZ0FBQkFnUUlIRWxBUUQ4U2s0TUlFQ0J3SW9HOGxkckJ5UGNIQmVUOXkvTTk2YUg2OGVybGw1OUpieHhsRkwzNm5idDNyNmJ6OGpacnVhd0hjdjhIeFh0R2dBQUJBZ1FJRUNEUVR3RUJ2Wi85cHRZRUNQUkVJSVh3cnp5aXFta1VQZTZublA1MVYrNjgreU96OTU4MGlsN0NlSnhNTHFaVWYrNFI1WG1KQUFFQ0JBZ1FJRUJnQUFJQytnQTZVUk1JRU9pa1FCdXFZOGlqNlBtMjh6THNmYSttYVlwNkhna1BWZjJUMTY1ZE81dGVmK29vZXQwMDExSXBwMHRwUnREdlVYcENnQUFCQWdRSUVCaUtnSUErbEo3VURnSUV1aWJRVGtGdm12Y2VVN0ZKMmlwdFA0MklmMmp2MUtrL05Udm1jYVBvYmRpdjQ0dHBSRDQvY3Vodm41VXYvVU9BQUFFQ0JBZ1FJREFFQVFGOUNMMm9EUVFJZEZjZ3hEd3kvdWhIbXVQZWpxTEhuN3g0OCtabU9pZ2YrOWlmeTNVMTJjdzNydWM5Mng1ZG9GY0pFQ0JBZ0FBQkFnVDZMUERZUHdUNzNDaDFKMENBd0pvRmNvQXVJOXpwbjNmYXA0L00xR1VVUGRUMTdzWjArbWRMblcrVnJkY2VXZjJVeTlzVjNCLzVyaGNKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1c0TGhQRHdLdTZIYXh4Q25iWmRTeGsrL1BuejI5dGIxZXZWWG5yN3daL05iYm9QOGZvRGQ3SWZMc2x6QWdRSUVDQkFnQUNCbmdzOCtFZGd6NXVqK2dRSUVPaU1RQmxCVDhuNm5hZmNMWjUvRHUrRk9sdy9IY0pmbU5YK3daL05KYUNuK2ZEUDU5WG1QQWdRSUVDQUFBRUNCSVlwOE9BZmdjTnNwVllSSUVCZ1RRSWhQbVVFdmExWDJuYXR5YmVYLzltckw3MzBRbnJwd1h2Ulp5UG85Wm4yOEpMOTE5UWlseVZBZ0FBQkFnUUlFRmlXZ0lDK0xGbmxFaUF3Ym9IYnQ5djJoL0NsSTBEa244VjdWVjF2VGZmM2YySjIvTUhQNTV6R2MwQ3YwMDV0N1I3b2FZdTIyVEUrRVNCQWdBQUJBZ1FJREVqZzRBL0FBVFZKVXdnUUlOQWRnYlJRZTdzUCt0T3J0REViUmYvVG05dmJOOVBoOTQyaWIyMXRuVTJqOFJkbUU5d0Y5S2Q3T29JQUFRSUVDQkFnMERzQkFiMTNYYWJDQkFqMFF1QzExMG8xcDAzemJ0b1dMVDEvYXFiT0IreWxRSDloTWdrL1hrNXVGNHNySjlaMWZTYVZjcTR0YS9hdVR3UUlFQ0JBZ0FBQkFvTVNFTkFIMVowYVE0QkE1d1JDOCtSVjNPK3ZjTGtYUGVYNVA3TzFzL09SOU5aK05kdDJiVzlqNDVtcWFtYjNvRDg5N2Q5ZnJLOElFQ0JBZ0FBQkFnVDZJQ0NnOTZHWDFKRUFnZDRLaEZoL3NWUStQTFIxMnFQYWxIOG1weFhkNitkaVhiV2o2TysvV2tiUU4rbzZCZlJ3NmxFbmVZMEFBUUlFQ0JBZ1FHQVlBZ0w2TVBwUkt3Z1E2S2hBMmhydDdqR3JWdTVGcjJMNDRjczNiNzVhZmVwVDVmeDRxcW5UOVBlbnpwTS81clVjVG9BQUFRSUVDQkFnMENFQkFiMURuYUVxQkFnTVNxQ3M1NVpHdzM4bmxudlFqend0dmIwWHZRNm5RNXordXdjaTlWNzlUQ3B3Y3ZDMXp3UUlFQ0JBZ0FBQkFzTVRFTkNIMTZkYVJJQkFod1JTcUg0dlZTZUg5ZU9NZnM5RzBhdC9iZXZHalcvS3pkbWZOSG1CdUlNcDdzY3BLNS91UVlBQUFRSUVDQkFnMEFNQkFiMEhuYVNLQkFqMFZ5Q3RFUGQrRlVMZU1pMC95cWg2Ky9TSi80WVV4dmZUNlB0R0duMy9xZmJJa004OTZ2bFBMTnliQkFnUUlFQ0FBQUVDM1JRUTBMdlpMMnBGZ0VEL0JVcVlucHhxN3FiaDd1T3M1TjYyUElROGloN1R1UHUvY3ZtRkY3NnVpcFBmU1VFL2o1d0w2ZjMvM3RBQ0FnUUlFQ0JBZ01BakJRVDBSN0o0a1FBQkFvc1JtT3hQOXRNbytQRURlcjU4T2k5bjhyQ3g4Vk1wckIvOHZEYTlmVEZkb3hRQ0JBZ1FJRUNBUU9jRU5qcFhJeFVpUUlEQWdBVDI5dmZUdG1sNUJQMEV1VHFFc2k5Nk92TjdKNkgrUkt6aTd5U2FDK2tqajZLZm9NQUJ3V29LQVFJRUNCQWdRR0NBQWdjak1nTnNtaVlSSUVCZy9RSWIrL3QzMDVacGVhRzQvRGp1OVBRY3d2TWE4TS9HMlB4NGVuYndIMVdGODhMcEh3SUVDQkFnUUlEQXNBUUU5R0gxcDlZUUlOQWRnUkxHOTg3dHZaK21xYjg3eDRCM0NlbXBXVHZwNDB4M21xY21CQWdRSUVDQUFBRUNpeFlRMEJjdHFqd0NCQWdjRWpqOWxkUDdhV3I2M1RrbnBCK0U5RU1sZTBxQUFBRUNCQWdRSURBMEFRRjlhRDJxUFFRSWRFV2dqS0MvL2ZiYjc2YlYxNzg4bTVOKzNDbnVoOXRpV3Z0aERjOEpFQ0JBZ0FBQkFnTVVFTkFIMkttYVJJQkFwd1J5S0QvWUI3MVRGVk1aQWdRSUVDQkFnQUNCYmdrSTZOM3FEN1VoUUdCWUFtWFVPKzJVOXBYU3JEVFhmVmpOMHhvQ0JBZ1FJRUNBQUlGRkNnam9pOVJVRmdFQ0JPNFhLQUU5eHREYy83S3ZDQkFnUUlBQUFRSUVDRHdzSUtBL2JPSVZBZ1FJTEZhZ2FXYmJyQmxBWHl5czBnZ1FJRUNBQUFFQ3d4SVEwSWZWbjFwRGdFQVhCVUowRDNvWCswV2RDQkFnUUlBQUFRSWRFeERRTzlZaHFrT0F3S0FFMm52UXErbzM1OWdIZlZBZ0drT0FBQUVDQkFnUUlQQjRBUUg5OFRiZUlVQ0F3R0lFUWpDQ3ZoaEpwUkFnUUlBQUFRSUVCaTBnb0ErNmV6V09BSUUxQzdTTHhGWFZPMVY1dHViYXVEd0JBZ1FJRUNCQWdFQ25CUVQwVG5lUHloRWdNQVNCRU1OMENPM1FCZ0lFQ0JBZ1FJQUFnZVVLQ09qTDlWVTZBUUlFMHUzbjRVc1lDQkFnUUlBQUFRSUVDRHhOUUVCL21wRDNDUkFnTUtkQUNQWkJuNVBRNlFRSUVDQkFnQUNCVVFnSTZLUG9abzBrUUdDZEF0T21lYmVLZVEvMDRFNzBkWGFFYXhNZ1FJQUFBUUlFT2k0Z29IZThnMVNQQUlFQkNJU212UWRkUEI5QVoyb0NBUUlFQ0JBZ1FHQjVBZ0w2OG15VlRJQUFnU0lRWXYzYk00b2MwZk5RdWdjQkFnUUlFQ0JBZ0FDQmh3UUU5SWRJdkVDQUFJSEZDb1FZNzg1aXVUSDB4ZElxalFBQkFnUUlFQ0F3S0FFQmZWRGRxVEVFQ0hSTW9JeVdoN3IrVW13VHVvRGVzUTVTSFFJRUNCQWdRSUJBbHdRRTlDNzFocm9RSURCSWdhYXEzazhOUzU4OENCQWdRSUFBQVFJRUNEeGVRRUIvdkkxM0NCQWdzQkNCalJqZlR3dTQ3ODhLY3cvNlFsUVZRb0FBQVFJRUNCQVlub0NBUHJ3KzFTSUNCRG9tTUQxMTZtNmEyOTZ1NU42eHVxa09BUUlFQ0JBZ1FJQkFkd1FFOU83MGhab1FJREJRZ1hwL2Z6L0dLS0FQdEg4MWl3QUJBZ1FJRUNDd0tBRUJmVkdTeWlGQWdNRERBbVU2Kzk1MHVwZmVFdEFmOXZFS0FRSUVDQkFnUUlEQUlRRUIvUkNHcHdRSUVGaUd3TWJlM3QycUN1K2xqMlVVcjB3Q0JBZ1FJRUNBQUlHQkNBam9BK2xJelNCQW9Mc0NlMmZQdnAraStidXpmRzZSdU81Mmxab1JJRUNBQUFFQ0JOWXFJS0N2bGQvRkNSQVlnOEF6NzcyM2wvWkJUNlBvSGdRSUVDQkFnQUFCQWdRZUx5Q2dQOTdHT3dRSUVKaFhvSXlXdi8zMjIrK2xiZGErWW9MN3ZKek9KMENBQUFFQ0JBZ01XMEJBSDNiL2FoMEJBdDBRYUZJMUR2WkI3MGFOMUlJQUFRSUVDQkFnUUtCekFnSjY1N3BFaFFnUUdLSkFDTlZYaHRndWJTSkFnQUFCQWdRSUVGaWNnSUMrT0VzbEVTQkE0RkVDWldaN2JLcDJjYmgwTS9xakR2SWFBUUlFQ0JBZ1FJQUFBUUhkOXdBQkFnU1dLOURlZWg3anU4dTlqTklKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1g0SWhPZ2U5SDcwbEZvU0lFQ0FBQUVDQk5ZbUlLQ3ZqZDZGQ1JBWWdVQ2V6bDVHME5NLzc3UlB6WEFmUWI5cklnRUNCQWdRSUVEZ1JBSUMrb25ZbkVTQUFJRmpDb1F3UGVZWkRpZEFnQUFCQWdRSUVCaVpnSUErc2c3WFhBSUVWaTdRTGhLWFI5RGJ1OUZYWGdFWEpFQ0FBQUVDQkFnUTZJZUFnTjZQZmxKTEFnUjZMaENpRWZTZWQ2SHFFeUJBZ0FBQkFnU1dMaUNnTDUzWUJRZ1FHTFhBN2R0dDgwUDQwcWdkTko0QUFRSUVDQkFnUU9DcEFnTDZVNGtjUUlBQWdma0ZRZ2pOL0tVb2dRQUJBZ1FJRUNCQVlNZ0NBdnFRZTFmYkNCQll2OEJycjVVNlRKdm0zU3JlVzlSOS9mVlNBd0lFQ0JBZ1FJQUFnYzRKQ09pZDZ4SVZJa0Jna0FLaHNZcjdJRHRXb3dnUUlFQ0FBQUVDaXhNUTBCZG5xU1FDQkFnOFZpREUrb3ZselZENXVmdFlKVzhRSUVDQUFBRUNCTVl0NEEvRmNmZS8xaE1nc0NLQkVPUGVpaTdsTWdRSUVDQkFnQUFCQWowVkVOQjcybkdxVFlCQWJ3VHlqZWRWbUV4K081WjcwTzJHM3B1ZVUxRUNCQWdRSUVDQXdJb0ZCUFFWZzdzY0FRTGpGR2hpdkpOYWJwVzRjWGEvVmhNZ1FJQUFBUUlFamlRZ29CK0p5VUVFQ0JDWVQyQ2pxdDZyUXRpZmxWSkcxZWNyMGRrRUNCQWdRSUFBQVFKREV4RFFoOWFqMmtPQVFOY0VTaGlmbm1ydWhxcXlrbnZYZWtkOUNCQWdRSUFBQVFJZEVoRFFPOVFacWtLQXdIQUZKdnVUL1hRUHVvQSszQzdXTWdJRUNCQWdRSURBM0FJQyt0eUVDaUJBZ01EVEJmYjI5L01xN2dkVDNKOStnaU1JRUNCQWdBQUJBZ1JHSnlDZ2o2N0xOWmdBZ1hVSWJPenYzMDFMeEwwL3U3WjcwTmZSQ2E1SmdBQUJBZ1FJRU9pNGdJRGU4UTVTUFFJRWVpOVF3dmpldWIzM1F3anZwZzNYZXQ4Z0RTQkFnQUFCQWdRSUVGaU9nSUMrSEZlbEVpQkE0RDZCNTk1L2JpOVc4YTU4ZmgrTEx3Z1FJRUNBQUFFQ0JBNEpDT2lITUR3bFFJREFFZ1RLQ1BwYmI3MlZ0MW43OG16ODNCVDNKVUFya2dBQkFnUUlFQ0RRZHdFQnZlODlxUDRFQ1BSRklJZHlpOFQxcGJmVWt3QUJBZ1FJRUNDd0JnRUJmUTNvTGttQXdPZ0V5c0I1Q05WWFNzdlRYUGZSQ1dnd0FRSUVDQkFnUUlEQVV3VUU5S2NTT1lBQUFRSnpDNVNBSG1ObzVpNUpBUVFJRUNCQWdBQUJBb01WRU5BSDI3VWFSb0JBNXdTYVpyYk5tZ0gwenZXTkNoRWdRSUFBQVFJRU9pQWdvSGVnRTFTQkFJSEJDN1JydzRXOEQvcHNtYmpCTjFrRENSQWdRSUFBQVFJRWppc2dvQjlYelBFRUNCQTR2c0JCUVArRWZINThQR2NRSUVDQUFBRUNCTVlpSUtDUHBhZTFrd0NCdFF2RUVEOFdZNXJlSHNJa1ZjWTg5N1gzaUFvUUlFQ0FBQUVDQkxvbElLQjNxei9VaGdDQllRcTBpOE5OdzZlckdIOHJOVEdQcUF2b3creHJyU0pBZ0FBQkFnUUluRmhBUUQ4eG5STUpFQ0J3WklFU3huL3JuLzdUTjlNWi95U2svZGJTUTBBL01wOERDUkFnUUlBQUFRTGpFQkRReDlIUFdrbUF3SG9GY2hqUDA5clRJL3g4bXVLZTRubWU2KzVCZ0FBQkFnUUlFQ0JBNEFNQkFmMERDODhJRUNDd1BJSGJzK1hoNnZqeEZNN1RkZHBoOU9WZFVNa0VDQkFnUUlBQUFRSjlFeERRKzlaajZrdUFRRDhGWG11bnREZE4rUGtVei9kU1hMZFFYRDk3VXEwSkVDQkFnQUFCQWtzVEVOQ1hScXRnQWdRSTNDZFFGb283VzFXZlNTUG92em9iUUc4WGo3dnZNRjhRSUVDQUFBRUNCQWlNVlVCQUgydlBhemNCQXFzV0tQZWh2L25tbSsrbDZlMy9LT1FaNys1RFgzVWZ1QjRCQWdRSUVDQkFvTk1DQW5xbnUwZmxDQkFZbUVCWnZqMjE2V096TzlJSDFqek5JVUNBQUFFQ0JBZ1FtRWRBUUo5SHo3a0VDQkE0bmtDN2NudGFLSzRNbm9mZ1B2VGorVG1hQUFFQ0JBZ1FJREJvQVFGOTBOMnJjUVFJZEV5Z0JQUVE2MCtIR045SmRjc2o2bTFvNzFoRlZZY0FBUUlFQ0JBZ1FHRDFBZ0w2NnMxZGtRQ0I4UXFVTVA3T1p6LzdWb3JtdnhUYW5kWUU5UEYrUDJnNUFRSUVDQkFnUU9BK0FRSDlQZzVmRUNCQVlLa0NPWXpuYWUxcGZianc4YktTdTRYaWxncXVjQUlFQ0JBZ1FJQkFud1EyK2xSWmRTVkFnTUFBQk5xRjR1cjRlanU1dlIxR0gwQzdOSUVBQVFJRUNCQWdRR0JPQVNQb2N3STZuUUFCQXNjVUtGUGFteVo4TWozWlMxUGRMUlIzVEVDSEV5QkFnQUFCQWdTR0tpQ2dEN1ZudFlzQWdhNEtOTGxpWjZ2cU0ybWUrNitXYWU0V2l1dHFYNmtYQVFJRUNCQWdRR0NsQWdMNlNybGRqQUFCQW1WaSsrVE5OOTk4THkzaS9vOUNYc2c5eGhMYTJSQWdRSUFBQVFJRUNJeGJRRUFmZC85clBRRUM2eEZvNzBPdnFvK1ZqZGJXVXdkWEpVQ0FBQUVDQkFnUTZKaUFnTjZ4RGxFZEFnUkdJZEJ1clJiang4c2k3aUc0RDMwVTNhNlJCQWdRSUVDQUFJRW5Dd2pvVC9ieExnRUNCSlloVUFKNnFPdFBoeGpmU1JmSUkrcHRhRi9HMVpSSmdBQUJBZ1FJRUNEUUN3RUJ2UmZkcEpJRUNBeE1vSVR4ZHo3NzJiZFNOUCtsME82MEpxQVBySk0xaHdBQkFnUUlFQ0J3WEFFQi9iaGlqaWRBZ01EOEFqbU01Mm50YVgyNDhIcFp5YjNNZForL1lDVVFJRUNBQUFFQ0JBajBWMEJBNzIvZnFUa0JBdjBXS0F2RnBYOStMcVgwMUpKMkdMM2ZUVko3QWdRSUVDQkFnQUNCZVFRRTlIbjBuRXVBQUlHVEM1UXA3VTFkZnpJOTJVdFQzUzBVZDNKTFp4SWdRSUFBQVFJRUJpRWdvQStpR3pXQ0FJRWVDcFM5enkvVTlhK2tFZlJmbWQySGJqLzBIbmFrS2hNZ1FJQUFBUUlFRmlVZ29DOUtVamtFQ0JBNG5rQzVELzJOTjk1NFAwMXUvOFd5a0x2NzBJOG42R2dDQkFnUUlFQ0F3TUFFQlBTQmRham1FQ0RRSzRGeUgzb1Z3OGZMUm11OXFycktFaUJBZ0FBQkFnUUlMRnBnWTlFRktvOEFBUUlFaml4UTdrTlBBK2V2bDEzUVF6aTRENzBON2tjdXhvRUVDQkFnUUlBQUFRSkRFRENDUG9SZTFBWUNCUG9xVUFKNmZlclVQdzR4Zmo0MUlnZno4bHBmRzZUZUJBZ1FJRUNBQUFFQ0p4Y1EwRTl1NTB3Q0JBak1LMURDK0JmZWVPTnpLWnIvOG15aE9BRjlYbFhuRXlCQWdBQUJBZ1I2S2lDZzk3VGpWSnNBZ1VFSTVEQSt1OVdvVHZlaHB3RjBDOFVOb21NMWdnQUJBZ1FJRUNCd0VnSDNvSjlFelRrRUNCQll0RUNNSHk5RnpvYlJGMTI4OGdnUUlFQ0FBQUVDQkxvdllBUzkrMzJraGdRSURGdWdUR2x2NnZxVDZjbGVhdXJCUW5IRGJyWFdFU0JBZ0FBQkFnUUlQQ1Fnb0Q5RTRnVUNCQWlzVktESlY3dFExNytTcHJmL3ltd0F2YnkyMGxxNEdBRUNCQWdRSUVDQXdOb0ZCUFMxZDRFS0VDQXdjb0U4Z2o1NTQ0MDMzayszb1A5aVdjamRmZWdqLzViUWZBSUVDQkFnUUdDc0FnTDZXSHRldXdrUTZKSkEyZmM4eHZCNjJXaXRTelZURndJRUNCQWdRSUFBZ1pVSkNPZ3JvM1loQWdRSVBGYWczSWVlcHJoL3ZBeWVoK0ErOU1kU2VZTUFBUUlFQ0JBZ01Gd0JBWDI0ZmF0bEJBajBSNkFFOUxDeDhla1E0K2RUdGZPSWVodmErOU1HTlNWQWdBQUJBZ1FJRUpoVFFFQ2ZFOURwQkFnUVdJQkFDZVB2L1Bxdi8wYUs1cjg4V3loT1FGOEFyQ0lJRUNCQWdBQUJBbjBTRU5ENzFGdnFTb0RBVUFWeUdOOW9HMWQvdkVxcnhhWHA3Z0w2VUh0YnV3Z1FJRUNBQUFFQ2p4R1kvVUg0bUhlOVRJQUFBUUtyRllqeFkrMEZjMHIzSUVDQUFBRUNCQWdRR0pPQUVmUXg5YmEyRWlEUVpZRXlZaDRuMDAra0ozZlRWSGNMeFhXNXQ5U05BQUVDQkFnUUlMQUVBUUY5Q2FpS0pFQ0F3QWtFbW56TytmRE1yNlg1N2I4eXV3Kzl2SGFDc3B4Q2dBQUJBZ1FJRUNEUVF3RUJ2WWVkcHNvRUNBeFNJSStnVDk1NDQ0MzNRMVA5UW1taCs5QUgyZEVhUllBQUFRSUVDQkI0bklDQS9qZ1pyeE1nUUdEMUF1MTk1M1gxc2JKUTNPcXY3NG9FQ0JBZ1FJQUFBUUpyRkJEUTE0anYwZ1FJRUhoQW9OeUhYalhWSjhyZ2VRaDVJYy8ydFFjTzlDVUJBZ1FJRUNCQWdNRHdCQVQwNGZXcEZoRWcwRitCRXNicjAzdi9PRFhoYzdObUNPajk3VTgxSjBDQUFBRUNCQWdjUzBCQVB4YVhnd2tRSUxCVWdSTEdQLzlybjM4N3pYWC9wZGxDY1FMNlVza1ZUb0FBQVFJRUNCRG9qb0NBM3AyK1VCTUNCQWprTUo2bnRhZEhmTDNjaDI2aHVKYkR2d1FJRUNCQWdBQ0JFUWdJNkNQb1pFMGtRS0NQQXZGalZVeDVmVGFNM3NjV3FETUJBZ1FJRUNCQWdNRHhCQVQwNDNrNW1nQUJBc3NXS0ZQYVl4M3pWbXQzMHNja2Zaam12bXgxNVJNZ1FJQUFBUUlFT2lBZ29IZWdFMVNCQUFFQ2h3U2EvUHg4ZU9iWFloVi9kVGFBWGw0N2RJeW5CQWdRSUVDQUFBRUNBeFFRMEFmWXFacEVnRUN2QmZKbytlU05OOTU0UDhUd3lkSVM5NkgzdWtOVm5nQUJBZ1FJRUNCd1ZBRUIvYWhTamlOQWdNRHFCTklpN3VrUlpndkZyZTY2cmtTQUFBRUNCQWdRSUxCR0FRRjlqZmd1VFlBQWdjY0l0UGVjeC9CNkdUd1BJYS9zN2o3MHgyQjVtUUFCQWdRSUVDQXdGQUVCZlNnOXFSMEVDQXhKb0lUeCt0VGRUNmRZL3JsWnd3VDBJZld3dGhBZ1FJQUFBUUlFSGlFZ29EOEN4VXNFQ0JCWXMwQUo0NS8vdGMrL25lYTYvOUpzb1RnQmZjMmQ0dklFQ0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFamkrUXczaWUxcDd2US8vNXRCZDZtdUNlTjBYM0lFQ0FBQUVDQkFnUUdMS0FnRDdrM3RVMkFnUUdJQkIvTG9YekZOUnpTdmNnUUlBQUFRSUVDQkFZc29DQVB1VGUxVFlDQlBvc1VQWStqOVBxa3ltZzMwa05tYVFQbytoOTdsRjFKMENBQUFFQ0JBZzhSVUJBZndxUXR3a1FJTEFtZ1JMR2YvUE1tVitMSVh4bU5vQmVRdnVhNnVPeUJBZ1FJRUNBQUFFQ1N4WVEwSmNNckhnQ0JBaWNVQ0FIOUVuMW1jL2NTZVBtditBKzlCTXFPbzBBQVFJRUNCQWcwQ01CQWIxSG5hV3FCQWlNVHFEY2R4N3IrTEdPdHp5bWFmajc1YU9xcHFtdWVhVGZkUHlPZDVycUVTQkFnQUFCQXQwVGFGY0o3bDY5MUlnQUFRSUVaaUczYnNJblVnTE9DOFhsbjlrNStIWm53YmdROWxJd1B4VW1rL2IzU1ZyUTd0NkM4N0hhdjFmZFVPWC9JSnpyM1oyNnA4cDRFQ0JBZ0FBQkFnUzZKR0FFdlV1OW9TNEVDQkM0WDZDTVFrLzI5ajZkWXUxdnpMSnROKzVEVCtFNzN4Y2ZZdlYvcFhwOWF4V2JmenMyOGFkVElQLzU5UFVYYzEzRHBON0l3VDNVNlQ4c2hIQVEwUE4vYTJoSDIwdUFMeVB1UnQzdjczZGZFU0JBZ0FBQkFpTVZNSUkrMG83WGJBSUVlaUZRQXZyYmI3LzkrU3U3dS84azVlSHIzZGtOUFkvbzEzbTAvTGQrODgwM2Z5NXA1by84bUZ6ZTN0NmVUQ1lmYW1MemFoWERLeW5GdjVKQytZMzAzczBVMUo4cmdUMGZPV3RNYWVRSERadCtNQVNmQnR0VHprOUhIdjdJWjNvUUlFQ0FBQUVDQkFZcElLQVBzbHMxaWdDQmdRams3SnAvVHFmUjZqUXlIZXB2cjVvbWxnWGpPdExBbEp5L2txdHk3ZHExcytrL0pMeWZuazUvNjYyM1Bwcys1NCtmVFIvbGtUTDdtYjI2M2s2ajdDbW94NC9FdW40eGhmWVUzcXZyS1pCdnB4eStGVVAxWENwdlV0V3p5VjBIQWI1TjhBZEZQUmpnOCtzNXdPZkg0YzhIejl0My9FdUF3THdDQjdOZ2NqbDUxb3NIQVFJRUNDeEJRRUJmQXFvaUNSQWdzR2lCTkhyK2MrWGU3dGwrYTRzdS83amxwYTNmVXA1T2oxQjlLWDlLNFR3SDlWQzkrdXJwL0hYMXFVOGRUTVhQOFRxKzlkWmI3NmJQbjVsOS9FejZmTytSd3Z2VzNTcGVDWFg5UWpycDVWVHVDeW0wZnppVnRwdWVYMGxyenUya0dmS1hVbDUvTmprY0N2QzVpSkxlMjM4L0dJWFBieHdLOHZuTC9FaWwzVDhpUDN1eHZPa2ZBZ1FlRnNpaFBIL2svNkVKNVEvN2VJVUFBUUlMRnloL1h5MjhWQVVTSUVDQXdLSUU4aC9IemRiMjl0ZWtrZVZQcGh1NG4wMWY1eitXMS8zenUwbi9yYUJPLzlIZ0g2WXA3UC9KZEQ5KzRyZC80emQrL1lGR1QyYjFQQWpyK2UxUTNVNGZyK1duWmJYM3crK1ZGeC80cDA2ajgxdlRqWTFMNmNETGFVWDdseVlodkpDeStKVVU0aitVWmhOY1MwVmVTaVJiU1dVcmZmMU0rbndxQmZuMDhpR2lRK0c5ZmRvRyszUlVmcEx2aTAvRkg3eDI3N3cyenJjVnV2ZGlMcmw5cWZ4NytQbWhsd2Y3ZEpyNlBmZnIvL3ZPWjkvODZHQmJPYzZHNWUvbHd4ODVrQi84ajZMTWtwbWVPdlhONllYZlU5KzU4M2UrOElVdmZIbDIvTDFqeHNtbTFRUUlFRmlzd05qK3NGaXNudElJRUNDd2ZJSDhjenErL1BMTHozenh6dnMvbjc3NHVoU0s4eC9PT1NTdCs1RUcwdHNVbkVMdmI2ZHF2cDcrdlArWjJGUi8vMHdJbjN6enpUZmZlNkNDZWRaVy9tTStoL0w4K2VCM1VQNTgrSG42c3J4L2NHeisra21QK3VMTm14ZlRmN25ZakUxemJocmoxWFR3VGowSm02bUF5K20yZ08ybUN0ZnJFQzZrVWkrbU5INDV2YitaQXZ5cEZQSlB6NXFRYWpDclFyNXF1WHorZk9qWm9aQS9lN2xKaDZXanl3bmwyUGFmV1RrZmpOYm5sdy9hOStEejlwVCsvQ3VnOTZldmpsclR3LzhoN2I3L1lQYjhqUnRmTmEyYWZ5NFY5TzNwMi95ajZYOHJIOG4vVzcvYk5GLzkvN2QzSi9DVlhQV1o5NnZxWHFsWGRiczMyN1NranVPUWtOQXNob1lrTE1adFkyQXltVGV6SklGNUU4Z3lNSGw1bVF6RGZNSm1JRFB2TzJFTlRuZ0pXWmhoR1RMSlFCSW1rMlNTTVBQaXJZME5HQnQ1QVJwc01FMjNkSy9zZGt2cVJYUzN1NlZiWjU3L3FWdlNsYXh1YTdsTExiK3kxYnE2UzlVNTMxUFN2VStkVTZlbXg4Y25kTDgvZ0xqY0RmRThCQkJBQUlFbkYyajl3UERreitZWkNDQ0FBQUs5RUxBUDBBMU5GUGRmTmNIYUw3aEdZMVpoTWl1bktLVmhXeDNiZWt2UmwwS3lHWDFIa2ZSTG1pVHU1bXBsNW90SGp4ejkzaUs0TkJSWXVrM1hzZWdwY3ovYWU5WDgxLzc5UVhEZ2dEMll2bTV4UXJiSGxsNzI3ZXNiZVBUUkxWRzF1cVhpM0FaTkpMOHRpcVBMdFBLZFFTVWMwTUdGN2FGclhLb1Y3dEtRK3dHRmtVMEs0QmJzMVVzZmJGWWQrM1NBWkoxVjFPZjVOTlRiMXVaS01YY2p1Y3YvT0g5ZnMyQjJ4OFVEdmoyeHRROC9lYUU1dEM1UDluUHJjOXR4bTREZURzWGVyV1ArOXlqNW5kS2xFT2VYTFVORDI3V0RQMGV4MndMNVMvWElNL1Y3b044QjdkNTJnRXBmK25jaWlOMXptM05ORU5EbitiaUZBQUlJdEVWZzhSdDdXMWJLU2hCQUFBRUUyaXJnSjRyYnVXZndUZXF3K2xER0FycFYxTUxtL0RCeERZSDI4ZFhDYS9LQi9wUWV2VTgvM2FibkhRalBuUnRwRG8rMTE2Wkxlc0Jod2JEYTlNR0xmRS9meCt4N2V0dWUzbm83S1Y5YXpvdXNiS21IYklLNzJkblpnWFByMTIvU1VZWDFvWHJwZFdSZ1J5Vm9iTmNRZ3EwNkxYNmpSc2h2MVd1M2g3R0czb2R1cXliMFc2K05ibEw5QjNUL1puME5LR3YzNjhUOXF1N1RFUHlXNHJYZXRnSllFRnBpbWJ0MzZjZm42K2lmdVBTVDVsZmIzUDdDQXdCcG9kTHY4MDlQYnRuOUJQVEZLdm40T1QwZ1pnZTE3R3R1MmI1bno5Nm8wWGl4aFhMdE5TL1VzYWRodjMvcWh5U1UyN25uK2tIelR1aEZmZm82b2JrcW4zMThmSHhVdHdub2M1TGNRQUFCQk5vamtINGdhcy9hV0FzQ0NDQ0FRQ2NFZk9RS1hYUnZiTGtyNlQyMyt5NFVwRHBSaG91dDA4cGhVVThmMXBNaTZZTjlyS0hsR2xudTArY1dmYnRHdDYveEgvalhyenVrMFFCZkRDSjNTeFNIWHpwV3EzMUhyMi90eVV2RGhOVXg3U1cvMFBhOWpSNU12MS9vZWVuOXFWbFM1dVRlNUw3OSs5T2VlVnZYM0ZkemdqdWI1RzdGeTlEUTBJYVR6bTFVcitUR0tBclhOWUp3dlpBMkNtYWJmTFpZbU5lcC9CdTA0ZzJoYzV1ZDAvbjBvWHJzWXczQmo4TDFLbGkvQ3JKUjBjaHViMVprc2prSXJFZXpLbE9iQThBbTVhc0kzL3lUZXRpLy9yTHorcDR1Y3pwek45Skg1cjdicnVYWDRHL00zYjN3UnJML2FXREV3cEMzOEVuODFHTUJ2d2VvREJhZWJiSGZMVHZ3NVpmTmwxKythME8xK253WHVwZHFmN3RhUTE2ZUhWU2laSEpIMisyMVUya1VqSjd2OTZsSSs0UitILzJ1dFNEWXArdmpPd0lJSUlCQWV3V1NOL1AycnBPMUlZQUFBZ2kwVjhBK2FNZWFMTzNTMmY2KyszWGJMazFtSDViVEQrRHQzVnA3MTJheHozclgvU2QvZmVhdjZNc1dINEZWRFp2OS9RRTllcXZ1dTZYUjMzL2Y4VU9IL016d0xjVklEeWF2dEhlOVpSVXJ2dG42L3BqZVRyL2J5bHB2cHl1M3V0cVMxRG41bnR5ejFuODFPLzRscDA5dlhIZjJiUCs1S05yUVY2bjB4OVZxUmIzNW0rSkdvMTlERnJacGgxaW5udnp0VWFDejcvVWN4YXlxaFgyRnNMN1F4VHZVQldxOTk1cElUOUUvQ2plcVNEb21FT2k3VTY5bzJLOWh5OWJUYnpXejBRQzJiOWxCQUxPM3lOWnZyMVBOWnJWdVc4OERtaVR1S2ozR2tnMEIyeCt0emV6N3d0OFRuZGF4NjlGSDkycFd4NnZWNGkvVFU1Nm5KejNGOHJmYTBSclh2aWNIeVB3djV0eDZGdGNzL1p0REQvcGlHWDVHQUFFRTJpaGdmOGhaRUVBQUFRU3lMV0IvcTMzNFU4K3pncXlHb3NhYUtNNzNiR1c3NEJjb25jNjkxZ0dHSkF6TW43dWVCSVZSOWM1K0tYTGhMZXBodm1OaWZQeWhSZXRZU2UvNm9wZjI1TWYwZmZaQzM0TmcvLzZrWU1sNTlXbTR0L3RhYnlmUDZjeS9kbm04UGpzQW9OSExRVFN6YWJQYUoreXJWdnRtbzZnL2pHYmlvS0hlL1lhQ3VWMWVyOUc0WEZjVU9EVlJxOTNlbWVLdzFtVUkyUDVrWHhiS2JUK1o2eUhYN1dEbjhQQnVqYlo1Z1o1d2pYN2NyNmZzMVlFVk84Q2kvKzBmKzJYelBldjJldnV5ZFQzWlFrQi9NaUVlUndBQkJOb2dzSncveUczWURLdEFBQUVFRUZpamdQVmt6dTRjSHJ4Unc1ZC9JNFBub2ErbWVoWVNsdTVkdHdmaTJJYVZmMTA5djE5UU1MeFpKei9mYzNKMDlQaWlEZldpZDMxUkVUcnk0MUx2eitsOTZmZldEUzkxWCt2alptM0xoYjRuai9KdmxnV3NqZE13M1hwS1NCQmNjY1g2SFkzR014VzhyOU9UOXF1Wm42ZmZHYnZzb0c2MjlwTHJaMzhxaWcva3RyNlZMQVQwbFdqeFhBUVFRR0NWQXVrSG0xVytuSmNoZ0FBQ0NIUlRRSiszNzA0NnYreVRkeVlXKzlCdWl3V0hsUzVXaCthWjA4M3FxR2Rkd1Z6clZQMUNuWHNkaGo5aFh3b1pid2xqVjk4eE5QaGwzWDlySEVSM0hCOGIrNlplM3hwVXJBejJaU0hVeXBXR1VkM00zYkpVMlplNnIxMFZhOTJmV20rbjYyKzl6MjViV1JiMDJxWlA1SHZiQk16Wjl1ZFc3em56clQ5dzJRLzJ4Ulg5YmtUWHU5bVpGK3Q1VDFNdmVUT1E2eWNicFpKY2tqSDV2V2pmbFI4YUtsQW45MFVWbmdVQkJCQW9yNEQ5MFdkQkFBRUVFTWkrZ0gzSWpuZnUzdjAwblVGOG56NGQyOFJpOWlHNWwzL0hiV1puWFZmTmYxYWZVVm5zb0c4N3k1TmVoc3kybzhtcWRPWjA4N2lFWXZ4NWJlbHI2aHU4dmVMQ1d5dXpzL2M4K3Vpang3VDkxaVU5Q0wzd25OeldaM0FiZ1d3SjJPK1BuY1poUyt2QnAyRFhybDJiZy9Ycm45dHdicjkrNmE3Ujc0T2RTNjZKQnZWdiszckpreTB2OGE5K3kyZTBKWnZGZmFZeDIvaVJFNDgrZWxpM3JheHpCdzEwbXdVQkJCQkFZSTBDOWtiQWdnQUNDQ0NRZlFIN2UrMkNmVUhmanFORDkrb3orVFBVazI0ZmpOTVA4OTJ1Z1Q4NG9FSTlvQTAvUmVja1grcXZmMjZUVGRsRWNPME42bW5ka25QWExaSG8vSHNmMXROd0VyaWptbHI4TGozeFpuV2RmK0Y0clhheDNuVXJlOXJ6bjY2Yjd3ajBRc0IrcnhmM2tzK1ZZOWZRMEEvSG9YdVI5dTNydGF1L1FEdnVsWDYvVHdPNWhXTWJVcE1jdVVyWE0vZjZOdDN3Mi9DVEE5cnZXK3orWi9ENDQ2K2FtSmlZMXZxVHYwdHQyaENyUVFBQkJCRG96QWNvWEJGQUFBRUVPaVBnZTZzMFVkeWZxQy81MVQwOUQxMUJQS3hVTkp0MzhGdm5HbzNmV3hkRjcxZHY5aS9iaC9pV29KNzJZSGRDSXhuQ25vUVRQNFRYT3RrdEx1aXVHWDBkVklyL2duTExMWlh6NSs4NmV2VG9ZNHNLa1I1RXNQVVExaGZoOEdOSEJTelVwZ2ZXRnZTU2I5MnpaMXQxZG5hZkRqL3QxKy9XZFhyZXMvUTdaWmZWOHpuYy8rTVB6R2tWcXorWDNGYTNuTVVmRUV1RHVYNm5SbFNtOTA3V2F2KzkrV0xDK1hJVWVRNENDQ0N3UWdINzQ4cUNBQUlJSUpBUEFRdThzd3JvLzFvQi9mZDZHZEJ0dUtzbWhkYmx2WVAzVEk2TnZjdjR0ZzBQUDZNU3hPL1VmZi9jT3ZUMGdkNkdxR3UyZGg5R092MStrL2F1VzNDeHk0UHB1NzZTbnNiSGRPdHUzWDliRU1hM1R3eHMvM3B3OE9ENWxpYjNBVjgvVzg4NnZlc3RNTnhzaTREdCs3YVAyZmZGQjRTaTdYdjIvRmprR2xmcnNXdTF1NzVRKys1UXk3NXJlNlJHeXVnUmZ3VEtyMGRQN2VpUy9DNkZVVlYvWjdUbCtGdmEybTlQanRVLzFiSlZxNHY5cnJBZ2dBQUNDTFJad1A3QXNpQ0FBQUlJNUVQQTk2RHZHaDYrV3BkUStrTHo4N0Y5U083KzMzS0ZCbjE0cnlpRTN6SlpxNzljWlVqRGJhQURDSnJZemIxVGllTC84Si9pTGFnbmo2ZTlocDNXVHJhbndxV2hScjJBZnB2cTNkZmw2VUlMSExlcnhMZnErMWZVSTFoZlZDQXJweFY5Y1poYTlEUitST0NDQXEwSGZSYWNvMzNaWlpkZEd2ZjFQYytGN25ydG9GZnJZdlRQMUNraTYyeE50c3RhSXZaZmx0THR2MlJmN01idnVFMzNicjhmQ3VhNklsc2NIOUdtYnh5b1ZqOSsrUERoeDVzMXRZT0VWaC9DZVJPRWJ3Z2dnRUM3QmJyeEI3L2RaV1o5Q0NDQVFGa0Y3RU4vUExCNzk4NytLSHBBSDkxMyt3L1U4OE5sdSt2aUFnMXp0eUh0N3E4VmN2K3AzL2pldmYxcDcvU09QYnV2RCtMd0J2VUlYbWVQTmEvZGJqZTdGZFJ0VzdZMEE0OXVXZmhZMkxzK3BReDB0OUxHYlhyc3RnM09mYU5XcTUzMXIwcitzZmRKSzI5NkFNSkNPd3NDaXdYc2Q5UDJGZnRhZUdCSHZ4TzdqaC9mRzBmUjFZRkN1ZllrdXpMQnBaYS85ZnVyL3kyVTI0UncrdDY5WHZMVzhsdDVMWFQzK1FOWkxqN3F3dUREcm4vREgwdzkvUEFwLzBUTmZSR01CRFlSSkFzQ0NDQ0FRSWNGN0kyRUJRRUVFRUFnSHdMcDMyeTNZM2p3SmdYTDYvWGgzajVZZHp2d3ptczF6MFZmSXFUYnViVSt6TzRZSHY0blNpSHZVQjU1dnIxUVBYTTJrVnphd3ppL3J1N2NzcUJ0Z2QxNjE4MXpickk1bGNzZWUwaXVkMmlFd3MxNnpwZW54c2ZIRmhYTHJPMTFDMFBZb2lmeFl5a0UwbjNZOXBzRnZlUTdoNGQzYXg5NmdVYVNYS2ZjZmJVZWY3ckNyLzg5MVg1bU9NMWg1SDRmdFAzSjF0WHRaV0dQdVhNSzQrRWY5TTNNZkdqdWlnajc5aW1ZajFqZGZLRzdYVUMyaHdBQ0NKUlJJUDJ3VjhhNlUyY0VFRUFnandMcGVlZ2YwQkR6dC9ieVBQUVVUK2trT1IrOXRTZDkvcUNCZmJDM0FCUHNIQnI2QmZYTUthaUhlMzJ2WVcrRCtuenhrNE1jMW51NXFIYzlPS0dpanlpTzMrWWE3cmIxUVhELytQajRtZlNGK3U0RHZyNWIvZXlMRUNPRUFpK3R2ZVFXV3YxK2JmWGR2WHYzeHNmRDhGbmF0MStpdmVLbE9yanpQTjNlcm4xS3owcDd5WFdGQTF0NmQzREtiMTcvTEF6bWNhemg2K0VuNGpqKzdlUGo0NlBOSnpHVVBkWGlPd0lJSU5CbEFRSjZsOEhaSEFJSUlMQkdBUi9RdHc4Ty9sd1VoWi90ZVE5NnN6SktLa3VGZEFzMEZscDltZjFUN1RKeGorMytsNXFBK3MwS0tqK29ubmZkN1RweERYVy91UlgrazRUc3BYdlhiVlVQS1h4OVNaZTh1clZSbmIzenhHRi9IZWpXVGRDNzNxcFJqTnUyRDl1WDdSc0xlc2t2dWZ6eUs2cDlmUy9RN25LOUhuNlJIbjlhTWtTOEdjanQrZlA3a3Eyajk1KzViQ2k5djBSaHBGUGY5Y3NYQm44U3pNYnZuM3prRVp1WHdSYjdYYlhmV1E0Mm1RWUxBZ2dnMEFPQjNyOVo5S0RTYkJJQkJCRElzWUFQdmY3NnlJRzdYL1hZcUM4TER6My9lNjVDTkVONi9LZWFPTzQxVFdOZlhsKysvUnFLZjhET3RRMkNYYnQyYlk3WHJYdURTdjF2MU5PNHV6bnMxNEs2aFZ4N1RSWVdKUzBMWmFyWkUzclhuYTRCSGQ2cmliNXVxUVRSN1kzVHArK2ZtcHBLenRkTlNtN3RZWFd4dHJFdkFvOFFNcjVZbTdWK0pUM2V6VUp2Mzc1OVMyWFRwcXNhemwyckhYUy9kbzU5Mm5jSE10cEwza3FkN01jNktxYnlScll6YW8vOHk3QVN2M2ZpeVBpOXpTY1N6RnZGdUkwQUFnajBVS0RuSCtoNldIYzJqUUFDQ09SUndQNXV1MEFUVCswNGVYSkVJMmlma1pWZWRGOHVYUVpPdlloOTZwejdwQ2FPZTIwVE9BM3A5bU1ZdEFSMURRM2VlVDRNMytqQzBDNGRkNGtQNmpxdlhhRW43WTF1cnFMbjM1S1FiVDJpbHNoOEw2U2FRamQ5UjJRWUhOSkRYMVRMM0ZLSm9qc2ZHeHY3N3FJU20wSHFRRmhmaE5Qakg5Tjk3UWs5eDNZZ3JCSEdMdzVkZUozQzdRdlYrRmZxdTM0RG03M2s4NWRBczk5TGExLzducVZGdmZncWxLNjRZSVZTcVcrS2craTNqbytOM2RFc3BMOWZ0eGVNRG1nK3hqY0VFRUFBZ1I0SVpPMk5wQWNFYkJJQkJCREluWUI5cUc3b2NtWi9vZy9lcjg3Q2VlZ0xCT2NuanJ0UVNMZW5oOEcrZlZWTlFPVm5odGFRL1NIbG5qZnIvbDlUd04rUTRhQ2VWalhwbGZUcEo2ejZ6TzZEbTJXMzJNNVRmeUIwd2MzNmZsdGozYnA3ang4NmRESjlZZk83OVZoYTZHLzlXdlFVZnV5QWdIM3VTY08wclg1QkwvbldQWHUyVllMWjV5bVE3MWZMWEtmSGRWNTV0TkZlNFkvTjJQRVpPNEJrZCtnZ1RYTmR0cDZzTFg1NHZYNlhiRC9UNHI2b09yMzNXSzMydWVUbnVZTUpCUE1tQ044UVFBQ0JyQWpZbXhRTEFnZ2dnRUMrQk94RDk2d0MraHNWMEQrY3VZQ3VOS0FRMHdncmxXb1F1MDlNMUdxdmEvS21QY2l0MnBHQ2VpVU42bjdvZnVodTBCcCtTZUdpb3FEdTE2VUEzQXdhclMvTnpHMEwyY25NOEl0NzE1TkFkMFRaL2NzNmQvMFd1WHhob2w3LzlxS1NtNHQ5MlhvSVRJdHcydkJqR3NqdCsrSmU4bkQ3bmoxUGoxemphalhWUy9YNFQ2Z0poeGYxa2l1UXEybjhuWFBCdGczRjZzZ3FrdG5oRmN5dHVKcjQ3ZjVLRkx6djJHajlMNXBiUy9lMUJRY21PbElTVm9vQUFnZ2dzQ29CQXZxcTJIZ1JBZ2dnMEZNQjM0TythOC91RjhkeGVFZXpKQmJ1c3ZRM2ZTVWgzYXF3SURoY01qaDRWVFVLYmxCb2VxVUZEZlZlS25nb1hHVzcxN0xaRkNxcGxWV2xWcWlyV0xDek92Z2xqcytxb1I1UVV4M1FzUDdiWnVKNFpMcGVuMHhmMlB4dUJ5T3NQVnUvRmoyRkh5OGlZTmoyWmZ1VUxRdkM2R1UvZE5tbGpjZXJQNjVIcjFNRHZVU1BQMVB0MDI5UGJQYVNKd2VGMUhCYWk2MGpTNzlYVnN5bEZqdncwRkNSKzJ4ZjAya1hEMnYvZXQvVTJOaW5kTDg5Wm9zL3NKZmM1RjhFRUVBQWdhd0s1T0ZOSjZ0MmxBc0JCQkRvbFlDRmhuano1WmZ2V2xldDNxLzRzRnZKd25wZUxiaG5hVmxwU0xleVd4M3N2Y21IcWt2MzdINVJIRWZ2MUQwL1pROHFRS1U5ekZtcnF4VnZxY1ZDZHJOM1hiZWVPTmxjVGZmZVpjUGg0MHJsenFuUlVadE5PdzFVdWpsMzRNTFdrOWJkN21kWktKQUdjdnR1VHVhVkxKcXZZZGVKRTA5dlZJTDljcjVPamZCOFBlbHl5OTkyREtVWnlyVy82V2VMNUltNWZjL0RZdlcwMzVVK2pUaFJNSS9ycXRLTjY1MzdUeTJYQkxSZ3Z0QWtEeldqakFnZ2dFQkpCZkx5QmxUUzVxSGFDQ0NBd0pJQzZkOXV0Mk40OENabGl1dlZZMmFYVDdJUDRsbGJWaFBTclE1cEFQZWhkUHZ3N3BkSHpnZDE2L0cwSUdJVHlabEQrank3T3crTFBKYnVYVmRRUEs4S2ZGMVBPRkRSY1BqSDQvaWU2Zkh4aVVXVlN0dllRcnlGcy9rZ3V1aUpCZi9SMnQ2KzdHQ1ZHU3c0ZUxGOTkrN2hJSXArWE5jU3UwNXpsMStqRlA2amRzcUVudWNuOWJOL202K3gxOXRYK2p1bG03bFlGZ1J6aldVL0ZvZkJSK0pLMzBkT0hENTh3dGRndi80ZUhDQ1k1NkkxS1NRQ0NDRFFJcEMzTjZTV29uTVRBUVFRS0xXQUJUVTdELzBET2cvOXJSazhENzIxY2VaQytrVm1kMjk5ZnV0dHE2ZUZLZnNLdGc4Ti9hejZDZFdqSGo3SGZtNEc5VFJrMlYxNVdpeGsyZEI5ZmRmL2kzdlhnMkJjOTM5VjU2NXI1dTNnQzhkcnRXLzQ1OC9YME43RExYUW02MG0reno5YXZGdHBJTGZ2QzRhdEIxZGNzWDc3ek14Vk9tYXpYMUg3V2dYeTUrbjI5Z3Ywa3FlQlBJK2ZnZnp2a3Q5WGtoN3oweHFtLzRkUnBmS2hpU05ISHZGTm5nVHp1ZCtaNHUwRzFBZ0JCQkFvdGtBZTM1eUszU0xVRGdFRUVGaWVnQS9vbXYzODU2SW8vR3h6NkhlV2U1UFhFdEpOeE5jM3BkbXhaL0NYRlV2ZnBobTJmNnc1UkRscjExQlBpN3FTNzJuUXRuQmxNOFBiNGw5dkJ5SjBTNzNyNFIxaEdOOFNWZGQ5NWJIdmZlL29vcFdia1MzMmVsdVhmZVY1c2NxbllkcnFzcUNYL0pMTEw3K2kydGYzQWcxSWVKbHEra0k5L2pRYjVqMDNiRDF4c05la0IzRHkvSmxuWVRCM1R2dTcrMFExckh6dzZPam9JZFV4Q09neDl3ejhnd0FDQ09SZElNOXZWbm0zcC93SUlJREFXZ1FzZE1TYTlmeXA2b0xWcEdQQlJuMVppTW55My9XNWtMNk0yZDFWbFNjc1ZqYzdDT0Y3VDY5UXIrbjA3T3kvVkxYZnJHQzJSeUhXd2xrV3I2SCtoSW9zNDQ0a1lDZkQ0Wi9ZdSs3Y1kxckgzUzRNYm8waWQvdkV6cWQ4UFowSnY3bnUxTXJXa3diMlpXeTI1MDlKeTIwRldkQkx2bjM3OWkyVlRadXVhamgzclhiKzYxVDNxL1RrTFMyOTVFbUl0VitCK2NuZGJIMzVYcHdjTkRtaURrWnB4TDQxWmZocEYwWHYxWHdGQjVzVld6REtKTitWcGZRSUlJQUFBdmwvNDZJTkVVQUFnWElLMk45dkMxL1ZuVU9ESXdvcHo4cEJMN3ExbEpWNVZvRzZMNGdiSDV1b2pmK2FmcmE2MkplbGorVXRTVytoRDNEYnJyeHlhM1R1M0J2VTJmeHZkZDd4TGgvVWc2QUlQZXF0Rm1uUU5pTWRwRkJhczk1MS9hLzY2cjdRSnBjN29LOWJ0Qi9jTTFXdjEzUzdkYkVERzZteHJjdStzckJZbWV4Z2szMjNNaTNvSmQ4NU9QZ2pjZVJlckd0NFg2dG52RmhQdThMWE81M2N6WjV2UXlpVVh2VmEreXJLb29NTituMlFpdXBiYVRiVzMraSs5MDdXYW5jM0swa3dMMHByVXc4RUVFQ2dSY0RlRUZrUVFBQUJCUElwWUtHcnNXTm84TDhvOEw0bTQrZWh0d3JQOWFUcm5QVGZWdUI0bXg2MGNMWFM0QmpxR3VyVnRPZjRzc3N1dTNTMnYvOU5TcXkvTG8rQmxxQnVRYVpJNzNlSjA0VjcxeWMxY2VBOWV0SnRDbmUzVHF4YjkvWGc0WWZQdFRTQVdkaStZK3V4d0cvZnU3bWsyN2R0THVnbDN6STB0TDB2aXA4YnhORkw5ZGkxS3RvejFKYWI3SW5OVXhtSzJVdHVGWnhmL0VFS0MrWjJsK3A5aTFyb2ZaUDEraTNOcC9qN2RYdkJ3WXptWTN4REFBRUVFTWk1UUpFK3NPUzhLU2crQWdnZ3NHSUJDNTZ6TzRhSC81VTZVMzgvUndIZEttbzloSTJ3RWxVVjBqK2drUDUyM1pmMmdDNi9KOTNXWk9GN3Z3TG5nU1RzWGZLVXAveEFwUnE5VlpPci9RdjFNNjh2Mk5EM3BNWUwvMDJEZHJOM1hmT1crOTUxdXg1MmJJODlwTUIraDNxaWIzS3o3aXZIeDhkSEY3N2NoM1g3UEpDdXA5MkIzZHJWMW05ZlZzYlc5cTFzR3hyYVd3bmRDOVVQZnIyZThnSVZmYmU2alMyWk5rTzVCZEZDOXBLTFlzSGlSd1BvZ0lUOVhsdU52eEpHOFhzbVJzZi90dm1zMUpGZ3ZvQ05IeEJBQUlGaUNkaWJKUXNDQ0NDQVFENEZyQ2V0c1czMzdoZHBvcmc3bTFXd2NKV1h2KzBXMG1PRjlJcEMrdnNWMG05UTJTMkVXQjFXRXhMdHRmYmxlMlczNzluejlOQTEzcVkxL1pKQ1R4SldkVkJBT2o0QTZYbEZYQks3Qy9hdUI4ZURVRFBEQjhIdE9wMzUxbzFoZUgrdFZqdTdDTUo4YkQwV3BGZlREcmE2dEMzczlRc0M1ZVdYWDc1cnRsTDVDWjFEZnIyQ3VJYXRCOC9TQVlVK2UxR3psOXl1RzY5dEs2WGJmOG4rbkpkOTJxcXgwaVdwcjRLNUhWalI3OEkzTkJIZ2V5Zkd4ai9UWEZGcWFZNnJiWStWbG9ubkk0QUFBZ2owU0tESWIzZzlJbVd6Q0NDQVFOY0U3SU43UExCNzk4NytLTHhmZVdaUXdjWSt4S2REWUx0V2tEVnM2RUloM1ZiWjJ0TzZrazJrZ2NZSDlaMTc5dXh6Y2VNRytmeXN2ZWtwQk5xbHplejhYbk1xK3Z0Z0dyVE4wdXJiMnJ1dUg0UHZLQU4vUVRhM1ZLTG9ycU5Iam56UDdteFpVcU4wUFJjS2lHWnVsdlpsMjVwdnU2YytkZDNPbVRON1l4ZStKSXFENjdXQzV5dUlYbXI1VzQxaDdXR3hVMjJsNzhVN2wxd1VGMXpNeUg1Zisrd0FraVpPL0s0T250dzRNVmIvV1BOK2U2RWRMUEg3c2YzQWdnQUNDQ0JRZklHaWZ6QXBmZ3RTUXdRUUtMTkEramZjN1JnZS9MeUMxc3ZVKzJZelB1ZXRoL2hDSWQzQ29IMnRka25EWlJMVWg0YXVjYUY3bDV5dXR4VXFHS1k5dS9hOE1peUo1M3p2dW1ZR3QxN3FabEFPZ2xQU3ZrOUd0MVRDeW0zQjJiUDNIenQyN1B1TFlOSjl5K3hzLzdOZ2J1dE5MWFZUMTZzZkhCelN0NS9VRTY3VklZRnJoUDJqQ3FIZXVUazNRTkpyYk51Zlg0Kzl0QXlMZWRrKzZZTzVmbWNmRWNLSHduUG4vcWpGMjV6TmRDMzd2MTdPZ2dBQ0NDQ1FOd0Y3WTJSQkFBRUVFTWl2Z0gyUW45MHh0UHQ5WVZSNWU4N09RMjlWdjFCSXQrZk05OGEydm1MNXR5MFlXdER4NjlHbDZmNmgwdUU3bFEzdDJ0azI5TjB1eldidmgyVUo2bGJ0ZEdrTnloYllyUmZiaGxuYnQwUHEzUDZpd3JYMXJ0LzUyTmpZZDlNWExmNitlL2Z1alkvclNnSjZ0UVh5L1hxTjlaSnZtd3YvdnBkY0I0OXNLVmN2ZVN2Vm9tQWVIOWZSa2Q4NzU5eEhwdXYxU2Y5RXJtWGU2c1Z0QkJCQW9KUUNCUFJTTmp1VlJnQ0JBZ240Z0w1OWFPaG5vekQ0YjgxZTRid0d6UXVGZEFzMjdlaEpOQ3NMNlVsUUg5NzlLdWZDRzNScHRtZjdZZFpKVUUrSHh4ZG9GMWxXVlJMamx0NTFCV2xiSks5bWNXNWFOeC9RazI0UDQrQ1crT3paa1hqZHVtM1ZTdVZGNm5GL21WckhEbmI4aUIrcW5UemZOcHBlQXMwK2E2UkQ0TzMrTWk1MjJiOW1qM21zYy83RC82U2ZQNmg1RitvZVk5KytQbDJOd0hyTTEzb3d5cStPZnhCQUFBRUU4aXRBUU05djIxRnlCQkJBd0FRcytNU1hEZy8vVU1QRkQraTJYWkxLd2xaZS83NWZLS1NyU20wTEwvNmdocTFRUzBVOTZyK2lidVMzS1Z6K3NQVWNxL3ZZZXRUTEd0UVRsZVRmcFh2WGs5N3dJekxhcWdCL2lYOXFHc3JkWEMrNUhTVEs2ejdZYXJDVzIzWmtRNU1TaGhYdFc2R04xRkNQK1I4TDVmM0hhcldIbXl0ZWNOQm9MUnZqdFFnZ2dBQUN4UkRJYXk5TE1mU3BCUUlJSU5BbWdkT25UbjEvMDVZdFA2L0FkSmxXYWIxd0ZqRHp1Q2pENkwvWTJlenVMOWt3c0dYOTJWT25ibFpGMmhuMnpNZldaK0dvY2ViVXFmdTJiTmo0U1JlR3gzVHZNOE5LNVJJRkszdmNlajNMM1BPcmx2QUhLc3pDRHB5b1J6eE83Q3lZTzdkZTdaVGVseHdVc210M3o3OUdMeXZwWXBQZWVUMDc3OTdHSWJnL3IraHFBc2ZxOVk5cGY1dVNpdTE3dG5DZWVlTEF2d2dnZ0FBQ1RRRUNPcnNDQWdnZ2tIOEIrMXMrdTJIckZsMURPbnAyRUN0RUpTRXByelc3VUVodjkwR0hKR3p1Qy9wT2YrZjA0MmVtcCs5YXQzM0hKNk5HL0xnUzZUUFU2emxBVVBlN2tBVjBhNU9vSlh5Ym5kMmIzbGZtQXhtZXd2K1RYTWJQaFZGWXRWeXVVd1ArWGdjMmZtV3lWdi8vVGs5UEg5VnpDT2J6V3R4Q0FBRUVFRmhDZ0lDK0JBcDNJWUFBQWprVHNML2w4Y2F0bHd5cXErNGZLbFRtUGFBYmZ6T2t4dzNyU2Q4NHNDVlV6K050dXIvOTcxdVBORWNjN0F1cWozL3J4Qmx0NS9hTjI3Yi9hWkJNOHY0c0JmVU5QcWpiOE8xOEgvZ3cxM1l0U1dodjE5cnl2eDZOSkFnc21OdEVlNUZ1Mys2aStOZW14c2JmZlhaNnVxYnEyWDVyQnpIb01jOS9XMU1EQkJCQW9LTUM3ZitnMDlIaXNuSUVFRUFBZ1NVRS9CRGtEWnMzOStteDF6WkRaSjdQUTArcmFJT0UwK0h1MTI3WVBIQmVZZWNMZXJBVDcxMHVTSUo2R0dnbTdUTVBuRHgxNXRUMDU3ZGNzdTNQZFc3L2VoWGoyUXJxZlFycTZYbkZCTlMwbGNyOTNTYkNpN1Z2VkMyWTY1ZHVST0g4MXpYNTI5dlBucHcrSkJvTDViYS9Fc3pMdlo5UWV3UVFRR0RaQXAzNGtMUHNqZk5FQkJCQUFJRzJDUGlBWGgwWU9GdUp3bDlVcU4yaXRkb1FaQXNIZVYrc0o5MW1FbmZxU2IrK3d5RTlzVG84WjFjNWZmTGs1TmxUMDMrM2Z1dld2NHFjMjZZblBGTmhMSEZOaGpNWHdUanYrMGd2eW04VDZEVjBCWUNxN1E4NmF2TXQ3VFZ2MFZEMmY2VTVFeDVVZ1d5dnRlSHM5bnVZbkE2Z0d5d0lJSUFBQWdnOG1RQUIvY21FZUJ3QkJCREloMEI0Zm5yNnpNYXRXLzZCRXUwUHFSZFB3OXdMRWRCTjM4Sk9kME82VFlvMmY1Q2o4dmlwVTQ5cTZQdGY2alNDejJuQ3I4dDFFT1JwemFITXlhV3hrc01JU1RsOVlmbW5vQUlXdHUxNjdsVk5KcWlETSs2d2RzOTNUYTViLzMrZFBYSmtwRmxuZ25rVGdtOElJSUFBQWlzWElLQ3YzSXhYSUlBQUFsa1U4S0ZnNDVhQnA2dEg3OFYrdHUxaW5TL3QrOUhuZXRLM2Fyajd5WTROZDI5dDN6U28yL3RscE43Um1vYStmMmJqd01BZCtubVB6am0rc2huVTdZQ0lQWmNlOVZhOTR0eTJ0azJDZVJSVk5QdmJZenJaNGQxdS9ZYlhUaDArZkdjd05kVUlkR3BFY0hqdXdFNXhhazVORUVBQUFRUzZLa0JBN3lvM0cwTUFBUVE2Sm1EQk1ONndaZXNsU3JLdlZFeHdCZXBCVDlIbWU5TERMZzEzVDdlYzlLaGJNUXBmZkFBQU44OUpSRUZVU0xQM3pWRG53aC9TMFBjLzNyaDE4MzBhZkgrbGd2cHdFdFQ5UkhJRTlYbTN2TjlLZzdsZHk5emEvcVIyaGQ5ZEY3dlhQRmF2Zi83czFOUzVZTisrdnVDUlI1ekNPVVBaODk3YWxCOEJCQkRJZ0FBQlBRT05RQkVRUUFDQk5nbTRnYTFiejhmT2FhSzRZSjNXYWVHaWFNT3VGL2FrZDNiaXVLV2F4VXh0c1JFTGdYclRIMVN2K3NjM2J0MzZiVDN3TklXNHkzVzNadkgyUWQyZVVqUi9xMU01bHFRTmZUQlhqL2s1OVpoL1ZGY3dmTTFVZmZ5dnBuVTZTYlBIUEZBNHQ5TWNXQkJBQUFFRUVHaUxBQjhjMnNMSVNoQkFBSUhNQ0ZSMkRnM2VvM09rbjZONTFTdzRGUFZBckFWbFhkWktFM1ExNG5kTTF1dnZhOWJWZWpIVEVLMmJIVjhzcU52UVoxdXFPNGNIWDZkTS9oYjVYK2xpWDhRWjNXOXR3TkIzRThyK1ltTlBHanFzWXBkTHMrdVkyMGlVUHc0YTdnT1Q0K00yK1pzdC9uUVNmYWZIM0hQd0R3SUlJSUJBT3dXSytzR3RuVWFzQ3dFRUVNaUxnUDFOYjJ6WXV1VUZPdjM4cWtEZGZRcUtSUTJHdmU1SlQvY0pDMm4rMG13YTRqeXJIdld2RG16WThBbFhxUnpYL1RiaisxYjFwbHRaTGFoYlczQmdYQWlaWEp3T3ROaUYvWFF0Yy8ycjYvdTV6NFlWOTB1VG8rTWYxU2tORXlxekJYTnJQeTZabHNrR3BGQUlJSUJBTVFRSTZNVm9SMnFCQUFJSW1JRDlUWTgxMC9oVGxDNStXajJCUlR3UHZiV2xrN0RielV1d3RXNjk5WFp5L3JHVnAzcjY5T2x6bXZIOVM3cnMzYWVxR2hxdHNHZlhVTjlFVUc4Rnk5UnRYY3ZjUm1PRWRpM3pVRGR2aW9Mb1Z5Zkdhcjl6NXVUMEl5cXAvVjdad1JXQ2VhYWFqY0lnZ0FBQ3hSUWdvQmV6WGFrVkFnaVVVOEFDb3Rzd01LQ2VQdmM2OWZWWnFMQngxa21RTGFhSnIvUGM3TzREVzg3cG5QQTdWTlYwR0hLM2EyMDk2cEVtRHF1ZWYraWg3NStabnI1dHcrYk5uOVlCRXl2blZRcnE2M3hRVDg1dkx1cm9obTZicjNaN2FUQzM0ZXhxQzNkbjZNTFhUOVRxLzE0SFdFYTFVb0w1YW1WNUhRSUlJSURBcWdXSy9LRnQxU2k4RUFFRUVNaXBnQVcrZUdCd2NFZC9HTnlubnR0aGhjRWluNGZlMmt6ejU2Uzd4cTlQam8zL2dSNjBrTjdMWGs5ckQvdnk1Nmp2R2hyNllSWHliZXFoL1JVRjlZcUxkWks2dFUrb0lkWEZQb2lpNm1WcVVURFh1ZVZSWkQzbXVobmZxNU1RUGpBMVd2K0xaaW50czVHMVNUcTNRS1lLVDJFUVFBQUJCSW90UUVBdmR2dFNPd1FRS0pkQStqZmQ3UmdhK2wvS0hxL1FSR1YyWHEwRjFUSXMvbnp3NWpEbE4weU8xZjlJbGJhNjl6cG9wUUU4Q2VxRGcxZTVLTGhCRWZHVlNVQjBzY1k1MkhYVXk5Sk92ZG9YNVN6ck5Kakg4Y05SR0wzdjJOallwMVNnWkM2QkpKajM4cUJPcjJ6WUxnSUlJSUJBUmdUc3lENExBZ2dnZ0VBeEJLd1gyY0tnK21QZFY5VXpxeHQyVjJrV2UwOXJUcndkL3FGbVZIKzlmclpRYk1FM1BYaWhtMTFmTFBCWk9heHRLc2ZxOWZzbnh1cXZxa1R1eFNydDM5dndhanYvV1kvWjgreUxwYjBDRnI3OUpIMWhwVktWK1pnR0w3eHBvTnIzVElYelQrcXhPTmp2OXhIN1piRjJLdFV2amVyTGdnQUNDQ0NRSVlIa2cxeUdDa1JSRUVBQUFRVFdKR0FoTmQ2NFpldFdKZEpYNmJhRmpUSWRqTFVnYmlFM1V2RDlSeHUzRGh6VnpPcDM2MmNMd0JiVWVybFlXOWlYdmZkR3AwOU9IMUhaUHIxKzY5WXZhMmF5SDFCNWY5REN1cDVobC9rcVc3dDFvbDNtVGlHd1V3cDB6YlFKM2ZHK3VIL2RyeHcvY3VUMkV5ZE96QWI3Z3I3Z0VWa2Y3dm0rMFluNnMwNEVFRUFBZ1J3SzlMSkhJWWRjRkJrQkJCREl2SUFQNkpmdDJYUGxiTng0UUtYZHJDOExlMlg3ZTI5aDNFSzZWZi8vVm8vMVIzVWo3YVUyanl3czZVRURmK0JBcHlYOE00MThlS2ZtazN1dUwyQWM2L1FFWHdFT3BxK3N0ZEpnWGxVd0QzU3UvN1F1Wi9EUlNyWDZ1OGNPSDM2MHVhcXM3UXNycXlIUFJnQUJCQkFvckVEWlByQVZ0aUdwR0FJSUlMQklvTEp6YU5DR3VWK2xNZC9XbzF6R2tPZnJ2VVJJOStlQ0wvTHExWS8yUG14dFkyWDF1WHpIbnNGZlVuL3VEUXFYUDJwem1lbDY5aGJVN2NCTG1VWkNxTHFyV0pMWjhaTmc3cHlHdGJ1UFY4UEtqVWRIUncvNXRWbVArWWkzN3ZWb2lsVlVqcGNnZ0FBQ0NKUkJvSXdmMk1yUXJ0UVJBUVRLTGVBRDM0YXRXMzVTdWU0cUJUeE5RT1lEWHRsVS9HZ0NWVm9aL1FuRDNiUFNpMjV0a29aRjM2Tis5dVQwQTJlSDkzeHN3K09QUDZZZTlhZUhVV1c3enB1MklHL25VZHQzRHE0TG9XVlJqN2svTFNEUU9lWVZtNFZBUDMvR1JkRXZUbzNWUG5YNjVNbmplcTdaQmhyT1BuY2d4UC9NUHdnZ2dBQUNDR1JNZ0lDZXNRYWhPQWdnZ0VBYkJPeHZlN3h4NjViZENxWS9yYkJpTTRTWHRmZlZ3cXlGc2l5ZWs3NjRxUzJvVzNtcndiRmpNN3FlKzkwYkxyM3NQd2N6czZkMDM3UFZvejdRRXRTdFBRbnF6VW4xTk1sZXhRN0R5T1J2ZEN6cU5aTzEydStmUFhueW1MZE1uQWptd21CQkFBRUVFTWkrQUFFOSsyMUVDUkZBQUlHVkNsaFFjUnNHdHFqWDBMMVdNYzcrMWx1UGNWa0RYVjU2MHROMlRvTDZ2bjE5Wnc4ZVBLdWdmdWZXalpzKzFZakNHWVZRQytvYkNlbzY2S0orY2d2bU5qeENuZWEzYUtLOTEwM1c2dTgvYytyVXVDQnRuN2QySjVpbmV4WGZFVUFBQVFSeUlWRFdEMnU1YUJ3S2lRQUNDS3hTd0FmU2djSEJIZjFoZUw5aStaQUNuUVdWc2grVTlRWkpSK3VDaWVPeWRFNzY0aWFQTk5ONFJlZE4yL0QyWU52dTNYczBGT0J0Nml2K0Y3cWU5M3BOZ0taREwzYXRlMytadHNXdkxlTFBhVEQzUTlZVnpMOFNSdTQ5RTZQamY5dXNiTHFQVzF1eklJQUFBZ2dna0R1QjlJMHNkd1dud0FnZ2dBQUNGeFVJejA5UG45bTBaY3ZMRmVhZVd2Smg3aW5Vd3A3MExWdnE2bTM5YXFDZTZ1Q1JSOUx6d05Qblp1VzcwM25UVmpZcmUrWHg2ZW5qWjZlblA3ZGg4OEJmNnNETGdPNTdWdk84NjFodGJKZG5zd1B2UlR6NGJnYitRSVJHRUVRNnkvenJZUmkvYWJJMi9xWXpKNmUvM2F5emhYWjZ6SVhBZ2dBQ0NDQ1FYd0VDZW43YmpwSWpnQUFDRnhPd3NCSnYyRHJ3WXpvbjl5VjJyU24xc2xySUsvdGk0ZFZDWENTUG45bThkZk9EWng3ODl0ZWExOFBPYWtpM05yTlRGS3g4OXI1ZFVVaC83T3lwNmIvZWRNbm12M2R4c0ZOMWVicEdCbGo3cGhPbUZhV3RyZDVwTUs4b21CL1NnUFliSnNmcXI5YzE1TCtteDJ5eGZUMzE4WGZ3RHdJSUlJQUFBbmtWS01vYmVGNzlLVGNDQ0NEUVdRRVhqbWdJdFBwVS9RUmFuZDFXZnRadUlWZERwVzMydk9qUGR1MFpmS1VmUW02WDRNcitZZ2NYYkVpK0Qrb1RvNCtNNkx6cm45WFJocGNvbWQ5a0lWMy9WWDF2ZW5JZ0l2czFXcnFFZGpEQ3oxcXZIdk0rdFZWZEI1bmV2RDZPbnpreFd2K1BlbXcyMk4rY21UM3hzSURPZ2dBQ0NDQ0FRTzRGaWpnTUx2ZU5RZ1VRUUFDQk5nallBZGg0NjU0OVYxYmp4Z082dlZsZkZtTDR1eStFNW1KaFY3Ti8yeFR2d2F1T2pkYi93dmVrTjgvM1RwK1U4ZS9wU0RpclM3QnRhT2lub3NDOVMwSDloZmF6Qms1WTc3TzFlZm84dXp2TGkrMmpkZ0NpVDhIY3luOWNvL1kvZk02NTM1K3UxeWQ5d1pOcm1kdHpDT1VlaEg4UVFBQUJCSW9rd0FlMUlyVW1kVUVBQVFTZUtCRHRHQjY4UnlIbnVacFFLd21rVDN4T21lOXBoblJkaHk1MGVRM3AxbjRMenIvZVByejdWWkVMMzZhSjVKNWpsd1VQa3FCdUIyMnlPbkp1Y1RBL284TUs2aW1QYnB3WUc3TloyUU0vVjhESUNNSGNZL0FQQWdnZ2dFQlJCZkp5Ukwyby90UUxBUVFRNktTQS9ZMjM2NkgvcEVZK1AwY2hqZlBRbjZodGdkVkNlcVNFK1BPYkw5bnlyVE1QVG44OUIrZWtMNjZKRFFtM2crNytmR3lkbi80Tm5hUDk4ZlVEVzBiVkQvMWpta2h1bDM4OG1mSGRYcHVkQS9SSm1TcnFNYS9ZalBTNlhOb25OV1QvMVJPMSttYzBpZDkwY3hLL1FCUDUrVkVDVm5nV0JCQkFBQUVFaWlwQVFDOXF5MUl2QkJCQUlCbldIRzhhMkhLNXVvZi9rUVlFTzhXeXJQYWc5cks5V2tKNnFKQStrTmVRYm9iSlJIZDJmdmJob0tGcnFOKzNmY3ZXajU5M3diRXdjTTlRVUw5RUlkakN1VCsvVzk5N0ZkVFR5ZXdDSDh5dElMSDdzemdNWHoxVnEzMWN3WHhLZDluQmhqU1lNNXpkWS9BUEFnZ2dnRURSQlhyMXhseDBWK3FIQUFJSVpFSEFEc0kyZGd3Ti9iaE8xNzFMdCsxdnZnVWQvdllMWVltbE9kdzkxK2VrdDFZcjFFaUFhbm9OOVV1dXVPS1NhSGIyalFycWIxUW8zdUd2b1o0RWRRdkMzZHduekZsbnhpZFhGZEFRL0wvVEtQejNUdFhyWDI0VzNvOEMwRzE2ekpzZ2ZFTUFBUVFRS0k5QU45K1F5Nk5LVFJGQUFJRnNDRmpQc0UwVXQwMFR4ZDJ2U0xSSHZhZEpDTTFHK2JKWWltWkl6LzA1NmEyMlliQmZrOFFkOEpPdkJaZis0S1dYemM3MC80YUMrdXNWMUFlYVFiMWJCMjZjSlhNcm5JTDVBWjFZOEo3SjBmR2JtNFZOUi9VUnpGdGJqOXNJSUlBQUFxVVNJS0NYcXJtcExBSUlsRXdnL1J2dmRnNE5mVTU5cEQvbFlxZFp2WnREaDB1R3NZTHFOa042UzA5Nk10emFKaWpMOHhJcHFFZHBVTDlNTS93M1hPT3Q2cjMrVlZXcVgxK2REdW5wK3U5VEIvcHZUZFpxZjlYRXRBTko5cFYzMzJaMStJWUFBZ2dnZ01EcUJld05rUVVCQkJCQW9KZ0NGb2lTWHNrb3VFYzk2UHJSN21KNUVnRi9hb0JSeFM3OGMzK2RkQXVQKy9ibDRUcnBGNnRhM0F6bjl0NWZQVG82ZW1oaXJQNTZuUXorRmQrcDdUbzZwRHdKNTJFWVY0UHdsNXZoM0p4dE9MdWROMDg0RndJTEFnZ2dnQUFDQkhUMkFRUVFRS0FFQXBvWDdGNk5LYll6Zi9tN3Y3ejJib1owcDVBZS9MbGRYendZR1prSjl1NjFudWE4TDJrZzlwT3c2Uko4M1J0UzdqU2d2bEx4MnhXaUhURWltT2Q5YjZMOENDQ0FBQUp0RmVDRFdsczVXUmtDQ0NDUU9RRS9xM2MxaXI2bWMzNm5WVHI3dTA4Myt2S2FhYTRuWFpjcSt4ODdCd2V2RFE0ZVBGK0FudlMwOW1rd1QwK0ZTTy92eFBmNWJZUzZrRnF5cE44N3NUM1dpUUFDQ0NDQVFDNEZDT2k1YkRZS2pRQUNDQ3hid0FmMG8wZU9ITkVJOSs4MDUrZnk5eTE3RGVWK29xN043WHQ1cTdvNDJlZDlTTGVlOVB3UGQyOXQxVzRFNVc1c283Vk8zRVlBQVFRUVFDQ1hBZ1QwWERZYmhVWUFBUVJXSkdBOXdiR0d1ZHRNN243NjdCVzl1dXhQdGtuMTVrUDZUUVVONldWdlplcVBBQUlJSUlCQUpnUUk2SmxvQmdxQkFBSUlkRlRBRHkvV3lPSjdrcTBrbDducTZCYUx0dkw1a0Y0cGNFOTZKMXR0Zm9oN0o3ZkN1aEZBQUFFRUVNaTVBQUU5NXcxSThSRkFBSUZsQ1BqaHhUWlJuS2JvaWpVMWwvV29NK1I0R1hBTG5qSWYwbTI0T3ozcEMzQ2U5QWYydHljbDRna0lJSUFBQWdna2t3WGhnQUFDQ0NCUWJBRWZqbWFDNEdGVnM1WmNiczFmMnFyWXRlNUU3ZVpET2ozcEsvT2xCMzFsWGp3YkFRUVFRS0NrQXZTZ2w3VGhxVFlDQ0pSS3dBSjZlS3BXbTlJbHRRNzZwS1NMWDVkS29KMlZuUS9wUlprNHJodmhtZjJ0bmZzZzYwSUFBUVFRS0t3QUFiMndUVXZGRUVBQWdUa0JDMGMyckYweDNYMDE2VUVuTDNtUDFmNVRySkRlaloyaEd3Y0JWdHVhdkE0QkJCQkFBSUhNQ0JEUU05TVVGQVFCQkJEb3ZJQTZ6a2NDcHp3V2h2ejlYeXYzd3BET09la1g5K3pHUVlDTGw0QkhFVUFBQVFRUXlJRUFIOUJ5MEVnVUVRRUVFR2lEZ0wvMmVUWHErNXB6N3Z0YW4vMzlKelN0RlhZK3BDZm5wQThON1Evc091bDc5L2F2ZGRWZGZIMDNlcmU3c1kwdWtyRXBCQkJBQUFFRU9pTkFRTytNSzJ0RkFBRUVzaWJnQS9yUkkwY09xL2Y4d1RDNTBwcS9MMnNGelYxNTBwQWVobFdOVVBpZk80WXZmMzV3OE9ENUhJWDBiaHlvNmNZMmNyZnJVR0FFRUVBQUFRUVdDeERRRjR2d013SUlJRkJjQVg5NXRkQUY5L3Z6ME5XVlh0eXFkcmxtUHFTN0dibXVEMXpsMXAzRFQzbGV6a0o2cDhIb1FlKzBNT3RIQUFFRUVDaUVBQUc5RU0xSUpSQkFBSUZsQ2FRaDZaN2syVWszK3JKZXlaT1dJOUFYeFBHc1F2cG01NklEaFBRRlpCd01Xc0RCRHdnZ2dBQUNDQ3d0UUVCZjJvVjdFVUFBZ1NJS0pDRXBETzkxY1J3SG9aL1puV0h1N1d4cERYUFhKSHpXazc2SmtMNEFOajA0dE9CT2ZrQUFBUVFRUUFDQmhRSUU5SVVlL0lRQUFnZ1VXY0FIOU5sSzVXR0Y4MUUvekoySjRqclIzbWxQZWw1Q2VqZkNNejNvbmRqVFdDY0NDQ0NBUU9FRUNPaUZhMUlxaEFBQ0NGeFF3RUpTZU9MdzRSTTZELzJnVDJXYTFleUN6K2FCMVF2a3F5ZTlHL3RBTnc0Q3JMNjllQ1VDQ0NDQUFBSVpFU0NnWjZRaEtBWUNDQ0RRQlFFTFlqWlJuSmJ3bnFRSHZSdlpMTmxpQ2YvTlcwOTZKNXVJSGEyVHVxd2JBUVFRUUtBd0FnVDB3alFsRlVFQUFRUldJQkRGOStwY2FlWDBrUGVCRmJDdCtLbjU2a2xmY2ZWVzhBSjYwRmVBeFZNUlFBQUJCTW9yd0FlejhyWTlOVWNBZ1hJSytFbmhacVA0NjRybnAwUmc3d1AwYm5aMlgxaTZKMzNmdnI3T2JqWlRhMmNmeTFSelVCZ0VFRUFBZ2F3S0VOQ3oyaktVQ3dFRUVPaU1nQS9vSnc0L2VrU3IvM2FZWEdtTm1kdzdZejIvMXFWNjBrZEdab0x5aEhSNjBPZjNCbTRoZ0FBQ0NDQndRUUVDK2dWcGVBQUJCQkFvcklDZGgrNDBVZHg5L2p4MFoyUGRXYm9nc0tBbmZkdlEwTE9DOG9SMDlyRXU3R0JzQWdFRUVFQWcvd0lFOVB5M0lUVkFBQUVFVmlxUTltWitOWGxoMG8yKzBwWHcvRlVJTkh2U05YSmhVeFM0bTNiczN2MmpKUW5wNlQ2M0NqUmVnZ0FDQ0NDQVFIa0VDT2psYVd0cWlnQUNDS1FDU1c5bUdON3I0ampXTmRGOWozcjZJTjg3THRBbjkxbUY5RXZES0x3OUF5RzlHK0daSHZTTzcxWnNBQUVFRUVDZ0NBSUU5Q0swSW5WQUFBRUVWaWJndzlKc3BmS3d3dmxvY3JtMWdQUFFWMmE0dG1lckp6MTJia2IybDRhVjhFQ1BRM28zd25NM0RnS3NyVTE0TlFJSUlJQUFBaGtRSUtCbm9CRW9BZ0lJSU5CbEFRdGs0WW5EaDAvb1BQU0RQams1Wm5MdmNodm8yRWpRcDlQL1o5UVVsMldrSjcyVEJOMDRDTkRKOHJOdUJCQkFBQUVFdWlKQVFPOEtNeHRCQUFFRU1pVmdZY21HdFdzSjcwbDYwTWxQaVVmWC8rM0xVRTk2Snl0UEQzb25kVmszQWdnZ2dFQmhCQWpvaFdsS0tvSUFBZ2lzUWlCeUk0Rk40aDZHdkIrc2dxOGRMeWxKVHpwSGdOcXhzN0FPQkJCQUFJSENDL0NCclBCTlRBVVJRQUNCSlFYOE9lZXpVZU1iU2s2bjlBeDdQeUJFTFVuVmxUdVg3a21mRytuUWxUSjBjaVAwb0hkU2wzVWpnQUFDQ0JSR2dJQmVtS2FrSWdnZ2dNQ0tCSHhBUDNINDBjT0s1UTlxUm5GN01SUEZyWWl3dlU5ZTBKT3VpZU8yRFE4L1ExdG82S3NJNzlVYy9HbnY3c0xhRUVBQUFRUUtLbENFTi8yQ05nM1ZRZ0FCQkRvdTRNOURkNkc3ejUrSHJobkxPcjVGTnZCa0FqWngzRG1kY1hDWnJwUCsrdWFUTy8xZTNZM2U3VzVzNDhsc2VSd0JCQkJBQUlITUMzVDZUVC96QUJRUUFRUVFLTEZBRXBwYytOWEVJT2xHTDdGSE5xcnVYTVdPbElSQnFCbmV1N0owNDhCTU43YlJGU3cyZ2dBQ0NDQ0FRQ2NGQ09pZDFHWGRDQ0NBUUxZRmZHaUtLdkc5TG80YlNvVFdvODR3OTJ5M1dWNUxSdzk2WGx1T2NpT0FBQUlJZEZXQWdONVZiamFHQUFJSVpFckFCL1JHWmYxMzFWdDdKTG5jR2hQRlphV0ZOTlM5U0tHV0h2U3M3RmlVQXdFRUVFQWcwd0lFOUV3M0Q0VkRBQUVFT2lwZ29TazhmdWpRU1JlNGIvbzBxQnNkM1NJclJ3QUJCQkJBQUFFRUVMaWdBQUg5Z2pROGdBQUNDQlJld01LNG55aE9aNS9mbmZTZ2s4OEwzK3BVRUFFRUVFQUFBUVF5SzBCQXoyelRVREFFRUVDZ2V3S2hDMGNDbThSZDA0ZDNiNnRzS1NNQzNSeEtIMnJvUHZ0WVJocWVZaUNBQUFJSVpFK0FOOG5zdFFrbFFnQUJCTG9wNENlRm0yazBEaXFlbjlTRzdYMkJidlJ1dGtEdnR0WDhEQkRXYmZTRXpuanYrQVNCWVJqT0JyT3ozMjlXbWYyc2QyM1BsaEZBQUFFRU1pcEFRTTlvdzFBc0JCQkFvRXNDUHBTZGVPU1JJNHJsRHlsQTJXWTdIdFM2VkRjMnN4eUJLUDdQTm5wQ0xkL2Z3YlkvSDBiKzJNOWZUOVRyMzlaMjdBZjJzK1cwRDg5QkFBRUVFQ2lWQUFHOVZNMU5aUkZBQUlFbEJmeDU2QzUwOS9uejBEVUdlY2xuY1dmUkJCcXFVR1Z5ZFB6bXdNVnZiWjdkWUczZjF1Q3NGVm80WDZkTCtkMVZPVC83MnFJaFVoOEVFRUFBQVFUYUtVQkFiNmNtNjBJQUFRVHlLZUM3elNNN0Q5MHZTVGQ2UHF0Q3FWY29ZQ0U5bXFpTmYxQUIraDBhUWVFUDF1aStkb1gwbVNnTSs3WHVBeHVDOExxalI0K2UxcnB0RysxYXYxYkZnZ0FDQ0NDQVFIRUVxc1dwQ2pWQkFBRUVFRmlsUU5KalhvbEhYQ05zYUt4ekdxQTRpTHRLMEp5OXpOcS9NbG12djIvSDRHQVFSdUY3TllqQ0FyUjlyWG9mc0o3ekpKeTdtN1h1VnpUWFo1ODdadlhGZ2dBQ0NDQ0FBQUpMQ0t6NmpYZUpkWEVYQWdnZ2dFQStCWHhBYjFUV2Z6Y013dEhrY210TUZKZlBwbHhWcWEzOUxZejdrTzVpWnozcDZlZUQxZlowTjN2T0NlZXJhaEZlaEFBQ0NDQlFXb0gwRGJpMEFGUWNBUVFRUU1DSDhmRDRvVU1uWGVBTyt2SHV1b0ZMcVFUYUZ0SzFvdk1LK0gwSyt2U2NsMm9Yb3JJSUlJQUFBdTBRSUtDM1E1RjFJSUFBQXZrV3NIRG16ejFXeCtuZFNRODYrVHpmVGJxcTByY2pwTTlFVWFSenpnbm5xMm9CWG9RQUFnZ2dVSG9CQW5ycGR3RUFFRUFBZ1htQjBMa1JQNG43L0JEbitRZTVWUWFCVllkMHZYQkdzN1Ziei9sZmNjNTVHWFlWNm9nQUFnZ2cwQWtCQW5vblZGa25BZ2dna0Q4QmY2N3hUS054VUVVL3BTOTdmNkFiUFgvdDJJNFNyenlrT3plcm52TytvQkgvMldTdDlzOVVDSDlPdTc0eklWdzdXb1IxSUlBQUFnaVVSb0NBWHBxbXBxSUlJSURBUlFWOFFEL3h5Q05IRk11L3FYT0lMWjZ2ZG9Ld2kyNklCM01oOEdRaDNSNzNYL3BuSnF4VXFrSHNQak5Sci8rZnpkclpLUk4yQ1RjV0JCQkFBQUVFRUZpQkFBRjlCVmc4RlFFRUVDaTRnRDhQUFFqZHZjM3owQzJBc1pSWHdOcmY5NFRiSmRoYVpuZHZIVjBSKzU1ekMrZTEyaTgwcVFqbjVkMW5xRGtDQ0NDQXdCb0ZDT2hyQk9UbENDQ0FRSUVFbWhPNFJ5T0JzMnhtM2Vnc0pSZFlLcVNMeEYrR1RRTXR3b3FDKzZjSjV5WGZTNmcrQWdnZ2dFRGJCS3B0V3hNclFnQUJCQkRJdTREdk1hODBHdmZGVVRnYmhJRzlSMWdQS2dkejg5NnlheXQvR3RKRDYwbmZQamg0SUlpaWdUQjJEWnRRVVBjZGFLNmVudk8xT2ZOcUJCQkFBQUVFL0ljdkdCQkFBQUVFRURBQkg5RGQrZk1QaCt2WEhYWmgrRlQxcFB2NzRDbTlRTG9mUkZQMStwZVgwTENET0p4enZnUU1keUdBQUFJSUlMQVNBWHBGVnFMRmN4RkFBSUZpQzFnSUN5Y21KcVpkcUluaXJLNHVDZTNGcmphMVc0R0FQeWRkejdmUkZkWmpidDl0VjJGQ1FTR3dJSUFBQWdnZ3NGWUJBdnBhQlhrOUFnZ2dVQndCQytnV3VteTV1emxSWFBJVC95SXdMMkE5NVhiNXRQUjcycnMrL3d4dUlZQUFBZ2dnZ01DcUJBam9xMkxqUlFnZ2dFQ3hCVndRZmRWUEZCZjZ5Y0NLWFZscWh3QUNDQ0NBQUFJSVpFU0FnSjZSaHFBWUNDQ0FRRVlFa3FIS2pjWTNkZmI1Q1pYSjNpZm9JYzFJNDFBTUJCQkFBQUVFRUNpMkFBRzkyTzFMN1JCQUFJR1ZDdmlBUGpVK1BxWVhQcVRMYUZrODUvemlsU3J5ZkFRUVFBQUJCQkJBWUJVQ0JQUlZvUEVTQkJCQW9PQUN5WG5vb1J0cG5vZE9EM3JCRzV6cUlZQUFBZ2dnZ0VBMkJBam8yV2dIU29FQUFnaGtTY0JQNEI0RjBZZy9EejFKNlZrcUgyVkJBQUVFRUVBQUFRUUtLVUJBTDJTelVpa0VFRUJnVFFKSmozbWpjWjh1Z3o2cmkyaFpqenJEM05kRXlvc1JRQUFCQkJCQUFJRW5GeUNnUDdrUnowQUFBUVRLSnVBRCtyb29lbEFWZjlpZmg4NUVjV1hiQjZndkFnZ2dnQUFDQ1BSQWdJRGVBM1EyaVFBQ0NHUmN3SHJMcTdWYTdheDZ6LytySCtHdXJ2U01sNW5pSVlBQUFnZ2dnQUFDdVJjZ29PZStDYWtBQWdnZzBCRUJQNlE5YnJqL29teCtTaUc5cXEwUTBqdEN6VW9SUUFBQkJCQkFBSUZFZ0lET25vQUFBZ2dnc0pTQTcwVS9QajQrR3JyZ0w4TEl2MTNNTHZWRTdrTUFBUVFRUUFBQkJCQm9qd0FCdlQyT3JBVUJCQkFvb2tEU1l4NDFQdXJpdUtFSzl1bUxYdlFpdGpSMVFnQUJCQkJBQUlGTUNCRFFNOUVNRkFJQkJCRElwSUQxb2tjVG80K01CRUg0TjM2eU9PY3NxTE1nZ0FBQ0NDQ0FBQUlJZEVDQWdONEJWRmFKQUFJSUZFVEFlc3Y5KzRRdWpQNFIzM1VlaHJ4dkZLUnhxUVlDQ0NDQUFBSUlaRStBRDFyWmF4TktoQUFDQ0dSSndNNDdqeVpxdFFNYTNYNlRldEdqd0s2TnpvSUFBZ2dnZ0FBQ0NDRFFkZ0VDZXR0SldTRUNDQ0JRT0FIL1h1RkM5MEZmc3pDczZEdm5vaGV1bWFrUUFnZ2dnQUFDQ1BSYWdJRGU2eFpnK3dnZ2dFRDJCZXk4ODNCcWRQd21wZkxQcXhjOVZEem5YUFRzdHhzbFJBQUJCQkJBQUlHY0NSRFFjOVpnRkJjQkJCRG9nWUQxbGx1dmVlREMrRWEvL1RBNU45M2Y1aDhFRUVBQUFRUVFRQUNCdGdnUTBOdkN5RW9RUUFDQndndjRjOUd0RjEzbm9IK09jOUVMMzk1VUVBRUVFRUFBQVFSNklFQkE3d0U2bTBRQUFRUnlLdURmTTJJWHZOdFpuM29ZVnZVdjU2TG50REVwTmdJSUlJQUFBZ2hrVDRDQW5yMDJvVVFJSUlCQVZnV3NGNzB5VmE5L1daZGQrMHdZNlMyRTY2Sm50YTBvRndJSUlJQUFBZ2prVUlDQW5zTkdvOGdJSUlCQXJ3WGlLSHEzd3ZrNWV0RjczUkpzSHdFRUVFQUFBUVNLSkVCQUwxSnJVaGNFRUVDZzh3STJlM3QxYW5UMG0rbysvMFBmaXg0RVhCZTk4KzVzQVFFRUVFQUFBUVJLSUVCQUwwRWpVMFVFRUVDZ3pRS3hyYTl5ZnZiOUxvNGYwOG5vZmZyUjM5Zm03YkE2QkJCQUFBRUVFRUNnVkFJRTlGSTFONVZGQUFFRTJpSmdZYng2OU9oUkMrZnZDU09ka2U0Y0FiMHR0S3dFQVFRUVFBQUJCTW9zUUVBdmMrdFRkd1FRUUdEMUFqYlVQWmlzMVQ2aWJINnZocnBYTlorN3YyLzFxK1NWQ0NDQUFBSUlJSUJBdVFVSTZPVnVmMnFQQUFJSXJGYkFMcS9tTDdQbWd1Z2QvbHByWWFDdWRDNjd0bHBRWG9jQUFnZ2dnQUFDQ0JEUTJRY1FRQUFCQkZZcmtGeDJiV3pzL3crZHYreWF2YWN3WWR4cU5Ya2RBZ2dnZ0FBQ0NKUmVnSUJlK2wwQUFBUVFRR0JOQXI3enZCSEhiM2ZPbmRDYW1EQnVUWnk4R0FFRUVFQUFBUVRLTEVCQUwzUHJVM2NFRUVCZzdRSnhzRzlmMy9IeDhkRXdjUC9CWDNhTkNlUFdyc29hRUVBQUFRUVFRS0NVQWdUMFVqWTdsVVlBQVFUYUtEQXk0b2UxVDR6VlA2VExydDJWVEJqbkdPcmVSbUpXaFFBQ0NDQ0FBQUxsRUNDZ2w2T2RxU1VDQ0NEUVNZRjB3amhkYlMzNHR4cnFycXV2aFg0Q3VVNXVsSFVqZ0FBQ0NDQ0FBQUpGRXlDZ0Y2MUZxUThDQ0NEUUd3SHJNYTlPMWV0M2hXRjRveC9xem9SeHZXa0p0b29BQWdnZ2dBQUN1UlVnb09lMjZTZzRBZ2dna0RtQjJFcTAzZ1gvVHFlaGYwdEJ2VThYWFdPb2UrYWFpUUloZ0FBQ0NDQ0FRRllGQ09oWmJSbktoUUFDQ09SUHdBSjZ0VmFyblExQzkwWmYvREN3OXhrLzAzditxa09KRVVBQUFRUVFRQUNCN2dvUTBMdnJ6ZFlRUUFDQm9ndjRvZTZUbytNM3U4RDlvWWE2Mi9zTXZlaEZiM1hxaHdBQ0NDQ0FBQUp0RVNDZ3Q0V1JsU0NBQUFJSXRBajRvZTdyR3U0dG10WDlRWWE2dDhod0V3RUVFRUFBQVFRUXVJZ0FBZjBpT0R5RUFBSUlJTEFxQVQvVWZYeDgvRXpvZ2pmNDhlMWhVTkdhR09xK0trNWVoQUFDQ0NDQUFBSmxFU0NnbDZXbHFTY0NDQ0RRWFFFLzFIMmlYci9OaGNFSE5kUTkxT1laNnQ3ZE5tQnJDQ0NBQUFJSUlKQXpBUUo2emhxTTRpS0FBQUk1RXZCRDNhZEdhKzhJWEh4dk10VGRFZEp6MUlBVUZRRUVFRUFBQVFTNkswQkE3NjQzVzBNQUFRVEtKT0NIdXF2Q3MySGtYdWVjYXdSaFdOWFBESFV2MDE1QVhSRkFBQUVFRUVCZzJRSUU5R1ZUOFVRRUVFQUFnVlVJekFiNzl2VWRPekorWHhnR2I5VlFkOFZ6QlhVV0JCQkFBQUVFRUVBQWdTY0lFTkNmUU1JZENDQ0FBQUp0RlJnWnNXSHQ0Y1JZL1hlRE9QNWNXS2xVMVlVKzA5WnRzRElFRUVBQUFRUVFRS0FBQWdUMEFqUWlWVUFBQVFReUxtQkQydjM3VFZqdGU2MUMrbU5oRVBicFBuclNNOTV3RkE4QkJCQkFBQUVFdWl0QVFPK3VOMXREQUFFRXlpclE4RVBkRHg5K1ZHZWd2MWJEM1cyeGZ6a2YzVlB3RHdJSUlJQUFBZ2dnME96UkFBSUJCQkJBQUlHT0M0eU0yTEQycWk2OTluZk9CZS9YK2VoMmtKaFozVHNPendZUVFBQUJCQkJBSUM4QzlLRG5wYVVvSndJSUlGQU1BVCtzZmJKV3U4SEY3blovNlRYT1J5OUd5MUlMQkJCQUFBRUVFRml6QUFGOXpZU3NBQUVFRUVCZ0JRSTJwTjB1dGFaTG84ZXYwYVhYSmpYU25mUFJWd0RJVXhGQUFBRUVFRUNndUFJRTlPSzJMVFZEQUFFRXNpcmdMNzAyTlQ0K3B1dWoveXJubzJlMW1TZ1hBZ2dnZ0FBQ0NIUmJnSURlYlhHMmh3QUNDQ0FRQkhZK3VxNlBQakU2L3JjdWNPLzI1Nk56ZlhUMkRBUVFRQUFCQkJBb3VRQUJ2ZVE3QU5WSEFBRUVlaWFRWEI4OW1CeXIvMllRTi81WDgvcm81M3RXSGphTUFBSUlJSUFBQWdqMFdJQ0EzdU1HWVBNSUlJQkFpUVhzZlBTSzFmK2NDMSt0YzlMSE5HbGN2MzVrWm5kRFlVRUFBUVFRUUFDQjBna1EwRXZYNUZRWUFRUVF5SlNBdno3NmRMMXVrOFg5Zk9DY2hYT2JSQzdPVkNrcERBSUlJSUFBQWdnZzBBVUJBbm9Ya05rRUFnZ2dnTUJGQkpybm8rdlNhMThKZy9BTk9oOWRVN3pyUHhZRUVFQUFBUVFRUUtCa0FnVDBralU0MVVVQUFRUXlLV0FoWFQzbkU3WGF4M1I5OU44TEsxRkZDZDN1WTBFQUFRUVFRQUFCQkVvalFFQXZUVk5UVVFRUVFDRHpBbjVZdTNyUy80M09SNzh0aWlLN1Bqb2hQZlBOUmdFUlFBQUJCQkJBb0YwQ0JQUjJTYkllQkJCQUFJRzFDbGhBOTVQR3pRVGh6emtYSDlha2NYMGE3TTZrY1d1VjVmVUlJSUFBQWdnZ2tBc0JBbm91bW9sQ0lvQUFBcVVSOEpQR25hclZwcUk0K0tlYU5PNWNFUHBKNHhxbEVhQ2lDQ0NBQUFJSUlGQmFBUUo2YVp1ZWlpT0FBQUlaRldoT0duZXNYci9mQmVFdnFCZmRDbXJ2VjB3Y2w5RW1vMWdJSUlBQUFnZ2cwQjRCQW5wN0hGa0xBZ2dnZ0VBN0JlWm5kdi92bWpUdVhaclpQVlE4cHhlOW5jYXNDd0VFRUVBQUFRUXlKMEJBejF5VFVDQUVFRUFBQVM4d01tTG5ua2VUOWZwN0ZOSS9xWm5kcStwQ1A0OE9BZ2dnZ0FBQ0NDQlFWQUVDZWxGYmxub2hnQUFDK1JlWUc5S3VtZDFmRzhUeDdaclp2Vi9WWW1iMy9MY3ROVUFBQVFRUVFBQ0JKUVFJNkV1Z2NCY0NDQ0NBUUdZRTVtWjJiL1N2KzhlNi9OcTMvY3p1aFBUTU5CQUZRUUFCQkJCQUFJSDJDUkRRMjJmSm1oQkFBQUVFT2lQUUNQWUgxZU9IRHAwTVkvY3p6Z1duQXJ2OFdzQTU2WjNoWnEwSUlJQUFBZ2dnMENzQkFucXY1Tmt1QWdnZ2dNRHlCUTdvV3VqNzl2Vk5qSTgvcERuZGYwYVhYMHQ3MXBrNGJ2bUtQQk1CQkJCQUFBRUVNaTVBUU05NEExRThCQkJBQUlHbVFITm05NGxhN2ZZd2pGN041ZGZZTXhCQUFBRUVFRUNnYUFJRTlLSzFLUFZCQUFFRWlpeGdJVDBJcWhOalk1OVJKL3JibXBkZnM5NzB1UW5saWx4OTZvWUFBZ2dnZ0FBQ3hSWWdvQmU3ZmFrZEFnZ2dVRVFCRzlaZW1heU4vM2JnNHQvVjVkY3ErdGt1eWNhQ0FBSUlJSUFBQWdqa1dvQ0FudXZtby9BSUlJQkFLUVdzdDl4NnpjT0pzZnB2NkJycG4xWlBlaC9YU0MvbHZrQ2xFVUFBQVFRUUtKUUFBYjFRelVsbEVFQUFnZElJV0VqMzcyRzZSdm92NnZKcnQ5bzEwZ25wcFdsL0tvb0FBZ2dnZ0VBaEJRam9oV3hXS29VQUFnaVVRc0FQZGJlYURsVDdmdG81TnhLRlliOSt0UFBVV1JCQUFBRUVFRUFBZ2R3SkVOQnoxMlFVR0FFRUVFQ2dSY0JDZXZYdzRjT1ByMnZFLzBEWFNQK09abmUzYTZRVDBsdVF1SWtBQWdnZ2dBQUMrUkFnb09lam5TZ2xBZ2dnZ01DRkJXeUN1T3I0K1BqRWJLWHlDdldrSHdzc3BEdkh4SEVYTnVNUkJCQkFBQUVFRU1pZ0FBRTlnNDFDa1JCQUFBRUVWaXd3Ryt6YjEzZnl5Skh2UlM1NHVjTDVtU0NNcXJyNEdpRjl4WlM4QUFFRUVFQUFBUVI2SlVCQTc1VTgyMFVBQVFRUWFLK0FYU05kSWYxWXZYNS9ITHVYNjlMb3MwRVlWTFVSR3diUGdnQUNDQ0NBQUFJSVpGNkFnSjc1SnFLQUNDQ0FBQUxMRnJDUXZuZHYvL0h4OFMrNk1QcHB2YzVtZTdmcnBCUFNsNDNJRXhGQUFBRUVFRUNnVndJRTlGN0pzMTBFRUVBQWdjNElIRHg0M25yU3A4YkdQdStpNEZVNkg5MjJZeUhkcnAzT2dnQUNDQ0NBQUFJSVpGYUFnSjdacHFGZ0NDQ0FBQUtyRm1nT2Q1OGFyWDlXbmVpL3FwbmRiVlgybmtkSVh6VXFMMFFBQVFRUVFBQ0JUZ3NRMERzdHpQb1JRQUFCQkhvallDRmRzN3RQanRVL3BjdXZ2YkVaMHEwc2hQVGV0QWhiUlFBQkJCQkFBSUVuRVNDZ1B3a1FEeU9BQUFJSTVGckFYeWQ5c2xiN1NCeTRONGRSbEw3dkVkSnozYXdVSGdFRUVFQUFnV0lLcEI5VWlsazdhb1VBQWdnZ1VIWUJteVRPUW5wbGFxeitPN0dMLzEwenBOdjk5c1dDQUFJSUlJQUFBZ2hrUm9DQW5wbW1vQ0FJSUlBQUFoMFNzQ0J1UGVZVzBuOHJqaHYvWGlFOW5UU09rTjRoZEZhTEFBSUlJSUFBQWlzWElLQ3YzSXhYSUlBQUFnamtUeUFONmRGVWJmdy9LS1QvUHo2a08yZTk2NFQwL0xVbkpVWUFBUVFRUUtDUUFnVDBRallybFVJQUFRUVFXRUxBZ3JoOVZSVFMvOS9BdVJ2RFNxV3FlNngzblpDK0JCaDNJWUFBQWdnZ2dFQjNCUWpvM2ZWbWF3Z2dnQUFDdlJXd0lHNkJQSndZcTcwbENla2E3azVQZW05YmhhMGpnQUFDQ0NDQWdCY2dvTE1qSUlBQUFnaVVUY0JDdWwwWXZSblM0OTlKZXRJZFBlbGwyeE9vTHdJSUlJQUFBaGtUSUtCbnJFRW9EZ0lJSUlCQVZ3UjhMN3EycEpCZWYzTnp1THQ2MGhudTNoVjlOb0lBQWdnZ2dBQUNTd29RMEpkazRVNEVFRUFBZ1JJSXRJVDAybHRjN040ZlZ2enM3dGJEempucEpkZ0JxQ0lDQ0NDQUFBSlpFeUNnWjYxRktBOENDQ0NBUURjRjVrTDZaSzEyUTh0MTB1MSsrMkpCQUFFRUVFQUFBUVM2SmtCQTd4bzFHMElBQVFRUXlLaEFHc1FYWHlmZGlwcytsdEdpVXl3RUVFQUFBUVFRS0pJQUFiMUlyVWxkRUVBQUFRUldLNURPN3U2dmsrNWMvSnVoTHBUZVhCa2hmYldxdkE0QkJCQkFBQUVFVmlTUWZ2aFkwWXQ0TWdJSUlJQUFBZ1VVU004OXIweU8xZDhkTy9lbVVDbGQ5YlF2UW5vQkc1d3FJWUFBQWdnZ2tEVUJBbnJXV29UeUlJQUFBZ2owVWlEdFNhOU0xV29mZGk3NDF3cnBWaDU3djJ6MHNtQnNHd0VFRUVBQUFRU0tMMEJBTDM0YlUwTUVFRUFBZ1pVSnBDRzlxb25qZmw4aC9UVkJFdElyV2cwaGZXV1dQQnNCQkJCQUFBRUVWaUJBUUY4QkZrOUZBQUVFRUNpTmdJVjBDK01XMHYvVWhlN25kZHVHdWR1MTBtZjFuUVVCQkJCQUFBRUVFR2k3QUFHOTdhU3NFQUVFRUVDZ0lBSVcwbWVEdlh2N3AwYnIvODJGMFUvNW44T3dHamhIU0M5SUkxTU5CQkJBQUFFRXNpUkFRTTlTYTFBV0JCQkFBSUhzQ1J3OGVEN1l0Njl2YW16czh5NTIxd1NCT3h0RVVWVUZuY2xlWVNrUkFnZ2dnQUFDQ09SWmdJQ2U1OWFqN0FnZ2dBQUMzUkVZR1pueFBlbmo0MStLWFBCQzU5eWtKby9yMDhZSjZkMXBBYmFDQUFJSUlJQkFLUVFJNktWb1ppcUpBQUlJSUxCbWdXWlArckY2L2Y1cUdQMkUxbmZJUXJyR3daOWY4N3BaQVFJSUlJQUFBZ2dnSUFFQ09yc0JBZ2dnZ0FBQ3l4Vm85cVEvTmpiMjNVci96QXQwTHZyOVVSVDFFOUtYQzhqekVFQUFBUVFRUU9CaUFnVDBpK253R0FJSUlJQUFBb3NGbWozcFI3OTc5TEgrMkwwb2JzUjNXa2pYMHhqdXZ0aUtueEZBQUFFRUVFQmdSUUlFOUJWeDhXUUVFRUFBQVFRa1lEM3Btamh1Zkh6OHpGUzlmbzFyeFA4ampLSys1dXp1TnZzN0N3SUlJSUFBQWdnZ3NHSUJBdnFLeVhnQkFnZ2dnQUFDRXJDUWJ0ZEYxL1hSSit2MWZ4eTc0RCtHbFlyTjdtN1hTN2N2RmdRUVFBQUJCQkJBWUVVQ0JQUVZjZkZrQkJCQUFBRUVGZ2cwOUpPRjlFQ1hZWHU5Yy9HNzFaTnVQNGY2SXFRYkRBc0NDQ0NBQUFJSUxGdUFnTDVzS3A2SUFBSUlJSURBa2dJVzB1MzlOSm9jcS85bUhMczNhWFozQytoUjRJTFpKVi9CblFnZ2dBQUNDQ0NBd0JJQ0JQUWxVTGdMQVFRUVFBQ0JGUXBZYjdtZGUxNlpxdFUrck9IdVA2ZmJqU0FLcTgzejBsZTRPcDZPQUFJSUlJQUFBbVVVSUtDWHNkV3BNd0lJSUlCQUp3UXNvRGRzOGppRjlMK01JM2VOSXZ0SkRYbXZjaG0yVG5DelRnUVFRQUFCQklvblFFQXZYcHRTSXdRUVFBQ0JYZ28wcjVWK2ZIVDhpNkZ6UCs1YzhGMHV3OWJMQm1IYkNDQ0FBQUlJNUVlQWdKNmZ0cUtrQ0NDQUFBSjVFV2hlSzMyaVh2OTJvMXA5bm92akwvbkxzQ1hYU3VjeWJIbHBSOHFKQUFJSUlJQkFsd1VJNkYwR1ozTUlJSUFBQWlVUmFGNHIvY1Rod3ljbWEvV3JBeGQvdGhuU3VReGJTWFlCcW9rQUFnZ2dnTUJLQlFqb0t4WGorUWdnZ0FBQ0NDeFhJTGxXdXI4MitzUlkvWlV1ZGg5b1hvYk4zbjl0OW5jV0JCQkFBQUVFRUVCZ1RvQ0FQa2ZCRFFRUVFBQUJCRG9pWUpkYTg5ZEduNnpWM3E1cnBiOGg4RmRoMDMzT2NSbTJqcEN6VWdRUVFBQUJCUElwUUVEUFo3dFJhZ1FRUUFDQmZBbWt2ZVVWWFN2OWoxd1F2a0xGUDNPeEdkNTFLWFhPVmM5WEcxTmFCQkJBQUFFRTFpeEFRRjh6SVN0QUFBRUVFRUJnV1FMSlpkajI3dTJmR2h2N3ZJc2F6M2ZPZmNkbWVOY0RNNHZYb01lczE1MEZBUVFRUUFBQkJFb2tRRUF2VVdOVFZRUVFRQUNCREFnMFozaWZHbjMwbStHbWMvczB3L3N0Q3VsOXVtYTY5YkxQYVBqN3JCOEJId1hqR1NndFJVQUFBUVFRUUFDQkxncUVYZHdXbTBJQUFRUVFRQUNCVkdEZnZyNGdtVVF1MkRFOCtBZGhFTDdCSHRMUTlpQjI3cDY0Ny9UTGpoODZmdEx1MGhmRDNRMkhCUUVFRUVBQWdZSUxFTkFMM3NCVUR3RUVFRUFnMHdJMmpOMmZuNzU5ZVBnVm1qVHVlcjB4ajFWblpqNXg5T2pSMDNyTVJyclpaZGxZRUVBQUFRUVFRQUFCQkJCQUFBRUVFRUNnd3dJV3dwYzY1V3lwK3pwY0ZGYVBBQUlJSUlBQUFyMFVvQWU5bC9wc0d3RUVFRUFBZ1hrQnUxNTZ1bGl2T3NQYVV3MitJNEFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NMUlg0SDhEN2R1VFMvRDQrdjBBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA4LTE2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJBcmN1bHVzIEZJRE8yL1UyRiBLZXkgQ2FyZCBbUDcxXSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMDAwMDIwMjMwODE2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDgtMTYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTA5LTEyIn0seyJhYWd1aWQiOiJmNGM2M2VmZi1kMjZjLTQyNDgtODAxYy0zNzM2YzdlYWE5M2EiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImY0YzYzZWZmLWQyNmMtNDI0OC04MDFjLTM3MzZjN2VhYTkzYSIsImRlc2NyaXB0aW9uIjoiRklETyBLZXlQYXNzIFMzIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1VUQ0NBZmVnQXdJQkFnSUpBTnI1QUpaekFrcUFNQW9HQ0NxR1NNNDlCQU1DTUlHRU1Rc3dDUVlEVlFRR0V3SldUakVMTUFrR0ExVUVDQXdDVGxNeER6QU5CZ05WQkFjTUJraGhJRTV2YVRFUU1BNEdBMVVFQ2d3SFRVdEhjbTkxY0RFUE1BMEdBMVVFQ3d3R1VtOXZkRU5CTVJJd0VBWURWUVFEREFsdGF5NWpiMjB1ZG00eElEQWVCZ2txaGtpRzl3MEJDUUVXRVhOMWNIQnZjblJBYldzdVkyOXRMblp1TUI0WERUSXdNRFV5TURBNE1ESXhNMW9YRFRNd01EVXhPREE0TURJeE0xb3dnWVF4Q3pBSkJnTlZCQVlUQWxaT01Rc3dDUVlEVlFRSURBSk9VekVQTUEwR0ExVUVCd3dHU0dFZ1RtOXBNUkF3RGdZRFZRUUtEQWROUzBkeWIzVndNUTh3RFFZRFZRUUxEQVpTYjI5MFEwRXhFakFRQmdOVkJBTU1DVzFyTG1OdmJTNTJiakVnTUI0R0NTcUdTSWIzRFFFSkFSWVJjM1Z3Y0c5eWRFQnRheTVqYjIwdWRtNHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUnhTbE81MWphYWNyVVFuejBPS214SjYwdytiQlFJUG55bUViMm4xZW1nQUFpaGZweWFlSkhUMHJVb0RCT3hNeUZ4NWdlMlNlbmNsN3FFM2xwR1FwZ09vMUF3VGpBZEJnTlZIUTRFRmdRVVdwRllRTkwveVZwaDJkaXJuN2M4VFlKSTZnQXdId1lEVlIwakJCZ3dGb0FVV3BGWVFOTC95VnBoMmRpcm43YzhUWUpJNmdBd0RBWURWUjBUQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUFoUzBkeDR0TzIrYk8vaW5IdncyM29RQjNLdkxJajhuWmNtcnBsU0YrTHFRSWhBT2xWT1ZYZm1CMGhSSTZxVFI2Wk80T01lcTIwSGtXUTFiYkxOTDAyZXlNbyJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFoWUFBQURmQkFNQUFBQllFWWUxQUFBQUcxQk1WRVVBVEpoQWViS0Fwc3kvMHVYZXUxem16SVh2M2E3Mzd0Yi8vLy9MWm42U0FBQVB5RWxFUVZSNDJ1MmRUWktqT2hMSEFXKzhWRlJ0V0ZMMGhpWDJiRGhBZGI4TDlHSU84R0ptRGpBeDhaWklldDNOc2NjSUJQcElTU2tNMWVDeUYxM1JHQXZwUnlyL3FRK1NKTkUrcHk3OCtmV3VmNzZCWjlIRS9LaGw4K0oySUd1NlhYM01DaU9xOXdQRm9yWlk1QW9LSW82a3phNVpJQXpqTzRvRnNWZ29YOTZzb2l6ZmNHYjQrMWlrMFdZQnMrQVdpa3p0UDhJaW1HWXIrMk1ScnQyZktCYXRWZkJadFpscVpKTHRta1VhNlRrZExJckU3WW5ZMURmcXBOa3ppNUJoL0JmSHdzZjRSb0NYdDA5MW8zTGVOWXNzMGl4QUZsNUZKVm52S2dRZWt1MmFoZDlzZitCWWVCWDFaZ3hNNkVoMU8yL2ZMRTR4Z3VwZzRWTlVsdlNkb3ovcGZMT2ZadGNzZk5VRHpBSml3WHc5citjZ1dCUm53V1hYTEU0eG5oTmswZnE2U0R1eTRQM0J2Yk5JWWp3bnlNS25xRjJiU2NOcGhPL1lONHM4eGl3QUZ0d2J0VXdzWHJzRHNIREdXKzg0RnY0eDZzQ2lMSVN0N0o2Rnl6QitJRm5ZaWxwMXRyOFFnSGJ2TDF5RzhSM0p3anRHdlZuTndLSk8rOTYwZXhhd3JQNTh4N0ZnL2xoV3hoZkQzMmIzTEU1b3p3bXdhUDE5cnRkU0VWL2NydEx1UE81MEdjYXZkeVFMRWlpTm5BWVd0MDVTWkFkZ2NVS2JoY1dDaDl5UEdLZjJuYVhrT3grbk9nM2pPNUlGOVUzakRDZmtFNVhxQ0N4eW5LQUNMUHlLT25TaVpyU2d0RHNDaXhSckZoYUxjRXhmRDhMQ3ljN25PMTJHOGZNZHlZSWhmQTlKMHFxN2tuMlpoWWRGaXZPY0Zvc1dFY1V5L0dyTUxsam92ZnpYTzVZRndlanpNTWRYZFVkaG9abjIzMWdXSEJuUWwyWFpkWWRob2QzUDcxZ1dRVVhkN3lmQkdjYVBkeXlMSXFpb2gyU2hHTWFmYUJaSi9LcmtJVmprQ0JVeFdMQzRhZlhqc0VqaiswZ2R2MEI3REJaS083QytrOFF0UFIySUJjb3d2bmtWTmVzZWhJVmlHRGdXQjFiVUlJdFRaQXgrWUVVTnNwaDcreThVaXdNcmFwZ0Z3akMrK2JySTZZRll6SWJ4RThIaXlJcUtZSEdPbWVNaitLWFovYk1nQzJUMTIyTW9xc1hpeTRKNDY1dG5HdWQ4WUJaVjdUR000RnBSY2VDZ0UyREJQWVl4eXVyWFAxMHNEcTJvTmd2QS9abXkrazhYaTJNcktzQ0NodUt0cjUyTHhiRVZGV0RoTll6ZWUvN2haSEZzUllWWStBeWpsOVcvWEN6WXNSVVZZc0VUcjJIODBibFl0QWZ2SWdDTHppZXJmNy8veDhuaTRJb0tzdkRLNnRmT3hZSWZYRkZCRmw3RDZKd3NqcTZvTUFzYVdHaUdXZFJIbnNaeHNnREVNUXV6T0xxaU9saFEvM29peU9Md2l1cGc0WTIzSEN3T3I2Z3VGclhYTUVBVzVPaUs2bUxoamJkQUZzZFhWQmNMdjZ4Q0xPaXhwM0Y4TEh6eEZzamkrSXJxWk5INUpqNGhGc25oRmRYTndoZHZBU3pZNFlOT0R3dkFNTTRlRnZYeEZkWERncm9kQU1EaUFSVFZ3NExIK0l0SFVGUVBDOHZzZlRyeUVPN0N3NEpIeEJlUGJoZUdZZmpqenVLaC9ZWHBQZjNqa2ZhaGRjUVFoOEE0OVFGRzdINFcxUEVGRkhlU0I0NDdEY05JUS9OYWp6d2VNYnhuY0w3enZwbGYxcWVNS1J2L0NYcmRydjB2dml4dnVNaFNvNWZwWmNIeDgrRDNxQ3FUOW1ja1l1T1NrTWpTcGswQ1hPVlZ5akJVaUJxVHdxYyt3K0kzN0JxOHgrQzgxbkpWZlhOZG40Mkh4aXh0TXd1dVhFem4xd0t0S0d4WGZsVXUrWXBrd2NGbXJUdmZXVGdyd1BSdEVCTUxyamxxTFpFZGpzVUZWcnpnMDVOQTExOTFIdnppcnNISWdwcmpaRU96VkJnb0ZxWnZlOFd4b05EUk5kZEhMSitydEd4a1FRd1d0UWM2aGdWM1NWNUlDQW5nQmJIclpvaE80cDFrSGxpOEdmTW53Q3pUYXhRTDU1UmRpQVVGMnJUaWVtcnRlLzZSZ1hOSnhMY2hGOEdDT25jM2gxaHdRQnpYVzJmbjNnYzFRQmExZDZjMmdnVng3bTRPQm91MWZYdlgyMzlSZXgrTWhWaHcvMDd0TUF2cTN2WWVaTUh0RnFIMzVaeVhtTVY4bHlFV3JmOG5ZUllrY2FiUkNnOGkvdEVoV2NUdmdKNGFsdDNDUXZabTNtV1ZSV2syNWFXQ2ZoSmtNVmV5ajA1TG92cjVKUU9xMWZieEVWMEhyb1lBTVZ0b3FWRlJadndreUtJMVNpeVUyN1ltaTFoVjVhWWtVdDJlbU8xNGFwZldaRWdXeEl4aWl2a1NhN0tJVmRYVzZrbTFaay9NUm1vRkZOTkZHeFFMYnQ4a01oMVprMFhzZnZEQ1ZodWlWb05acFRDZ1dLSzJMc1NDMm82TVRiZHRWUmFScWdyWURsVUZpRmx5MUFKZGo2ckZoRmpVUUxWcXlYZFZGbkdxeWlCYzZuMnpNNFlVa0xVUjVXQ0lCUUVLb1BJcXE3S0lVOVVXempjMU93eTdSempTTXMzRUFpdzQ2TkxKZUhCVkZuR3FXb2NheHVEQm10bnh1RkwxQUF1NEFGbVJkVmxFcVNvQnI2alVnNWxGVU5naEYyWlk2bVRSZ3NiS3hxUHJzb2hTVmRod2xJWXhzMDR0WEtSeU9NQ2locDNZaUhoZEZqR3F5bUdIMGxvc1RFNTU1N2l2WVJZRjNNamg4Tm9zSWxTVndUZFphWmlEUlFWVFRSRXNDRnlsOFZjcnM0aFFWUXAvelUwV1dhaFhxY2NETEJ3RjBFMVlSS2hxNjdqZ0FoWkZGSXZNWWFMNXlpd2lOaXU1V0pDcFlWWXZjc0dkKzQ2ZkJmT3lPSy9OQXErcXJZTlVZYkE0UTY3a0hoWm5SeWRiblFWZVZldWd3YU5adFB0a2dWZlZZbThzVHF1elFHZUpXY3JpZkMrTHlzRWlXNTBGZXBPOGkwWDdPQ3pRcXJxVVJYWWNGbWhWL1F3c3NLcGFSN1BnNjJqcUI3TEE3Z0Z1bzFsMFc3SGdHMmtxV2xWZHNWYUlSZEo1UXRWbExOaG1MSkNxNm9yQkY3RHdqODJTSUF1NkdRdWtxbEtITC9Hd1dEWm1EN05vdHhtYjRWWFZNWDhSWm5HR3FTcXR6U05aRkp1TTJTTlUxYVVLSGhhT09iNTZQZ3lFWTh5Y0tITU5qWnN0V0NCVjFkSDdQU3djYzcvRWJPM0pNV2ZFZkgxczlUbStHRlYxekY1NldERGZ4c3ZLY0IzNm5jazlMT2dtOCtCUnFscjdaclZoZ3dmSnRxcUJ1WlpvS3crTFlpeDFFeFk0VmFXd0wvR3hLS0IrcGEwTEV0UFl1TFg0Vk1GZEpOK0dCVTVWT2R4L2ZDeUNhOHYyaW10ckxVcFdzSHRydG1HQjNOSkhiTVBndVpkRmNNK0JiSHBqZkoxcExMUnQwenpaWkowOVVsVnJLL3JnNU94bDBkbSsrS0l2M0RLalRNMXFKQXROeVl0dDlsOUVxaW96UXpGT2tnQ0wyaXlPT1RhNDU3cUY1am9MQmNZbDJXWmZUcXlxRW1OL0ZrbENMS2FDeCtkQnJoYnJRbTNKOUVSQlk3Q1luaHQ1VXpZRWJNTUNtZlpnTnAvK1BkUnZROHU5TE9iZWw1VTNFb1ZkL0xSeTk5SjBaUUp0aHF1RzJyMTg2Zmk4cC9HMEhRdmM0MmZBWHRjUUMrcmY2K3JZUDVzRExPenFiY1FDT1ZhdG8xazQ5dTAyL2hPYUVJdTAyNDRGVWxWNVBBdnFOd3Z3QkgxVGRlVjZLZjFHTExBendIVTBDK2krYS9HQzU5Sk9GbW0zSlF2azQyZWNSTE5nU2FCbzZyUWFKNHRtVXhiWUdXQVd6Y0sycFZOZ09OU0VXTHgybTdKQUp4TzZSTE13MjVvR3ZGRGVtU3dJUE8yMkdRdWNxcG93c2c3QlFvZVJObjVqZSswc0ZuclB4RDZUdVp3RlB2bllWYTgzZ29YNmVHOFc2SG12bmMxQ296a1hrSlRhcDhHdytOKy90TSsvd1pONGFYNmNENS9MeDVDemFycnA2VndFZUh2a1k5L3BGMytSK21zR2xUSDc5Tnk0VXNCT1VqTW9qUzR3VHlTTm9LcTQ3N1g1QzI3ZG4vMmxxVUN5V1BKaGZqL3daTEZuRnFnbkdKOHNQaHNMaG4wVS9oT3dvUGc0NStGWjFPaDBFWS9QZ3VDeUFud0dGalRaVGxLUHhxTGVVRVlPeG9JbEc3ck9nN0VneVlhdWMrOHNTbWhpSXZ1Y0xMUlJkNEhNSWZLWUxMaVM1K05LMExsbEhwS0ZuSUFxeTlCVTFlT3pvSjRWdjgvR292WGxsUHBrTE9xUE5JdWRzeWcrMGl4MnpzSy9aUDdaV2VUZEoyVmg3emw0N1Q0ckN5MWI3ZVlvZGo4Mll3cU50TnFZdkg5dGNBZmpWRjRXY2pQWmIzWmUzZlB6WlBGazhXVHhaUEZrOFdUeFpQRms4V1R4WlBGazhXVHhaUEZrOFdUeFpQSGdMSzVsR2RpUDdmbXc4cTczdE9temRER2IramRoY2JscmMwRHJmUEFEVjJYMTdiOGtXVzhuenlJV05GbUR4ZEpsSWJYaGRmSzdXWkNWV0l6TGhSem9McXpDc09ESkloYlhaalVXUEZtSnhiZ2NRZ0FESVFtR1JidUlCWE04QjVnczZ5SlpyRm1mZFJaeVhjUXkraGwzSmRaMi9DeUtSYXRMclRESXdtcEVzdXkrTm5lekdCeHdmaDhMc21oVmZrMFdkZlNtUTVCRmYxZXo0YStqandSWkxIdjMrZEJIMW1GUlJPK29nbG53VVVvNDBObDVnMk94eUdPeGJrVVc2U29zZWdQTC9UZHdHeFpkdDJZZmFmUXdzaHBDVVRXd25NN2d0K01PRnRTd2NXWkVveXFMT1ZMVldHUm1PUHdsRlBOV3E3Sm90U2F3UWRLS09WNjR6QTkrM3Y2UUtidmIyV1RCNVh2Rmh2cTlhUm1QS3ZYbENrTjhtZG0rVTNPNyttTjdmWEZuTnIya0pldUxvK05UNHZKa2tXMU5uckJRVTJjcEcycVowdmtwZTZxbEdpR0ptMFhmbHJseGwwVExNYWl4SU5wckN5dkZRcFZJdnJZemJaa3N5Tm9zdUxwcmhGcWJyWWdTVldwWi8yd1d0Y0tDcTJVWUxHcjFPNFVGVlljMVdnRXlKYUhCSWxtYnhWQzFWd1cvdXR1S3F2OEpzR2pIOTgxVjZ0RGlaTE5JOUJRL2xUWWFrREMwQW1UeXhzMVpjR1dYbWFnTEVXd3VvaHFGT05JL0x6Nm03NnFFajFORytCcUxTamJ1OW9PWG9aT3JMUHJ4dU1CYkRiVTNXTkI1d011SCszTVpESU9LVkV0bFpiTElwdXZmMUZENDR6dFpLQThMTW5HNzZkQWpTSDhwR1RUSXRHNjVXMVA3MzBrVzhxVzFSRkpRNHM1NnRFS2lvRlBkcFlBaFJ3WkVYTEtZVTdscUxCcUZoZWFLRjdNWS9Wd2pyOFdUS1pSajBublZvM0UzSGhac2Jod2REVTE0ZW9NRkdmOE8zK25hTVFsTVBSeW5VejY1Qm1CeDZ0Wm5NY0E0aVd2TmplMHZTR1ZWcVpMdHpjVkM2U1AxbklFek0xbE0yZ0N3R0hRc2x4SGdxUEJNU2NHbnNqaHZ3V0tBVWNucXppelU0S0hxSmhrTXNwaENuOEppd2FlZkY4TXQxMkoyQVNNZGdiSFpnVmNRaTJvVEZnTEdDV0tSS3JIeTJBb1BpMjVpY1pKeWtCb3MyTlQ2WW5CSSt2aEZ3TWpGTlRpWms2czBIOGhDQ0FiRUlzT3pLRlFXWjNWMkk0S0ZJTkMvd2U4OG9aZ3ZZYkRvTm1MUlgvbE9GbVFNeUNybEZKQkY1Mk14U01pdEFLSys3TzlEV1FqUGZSY0xkVHhDbHR2RklPYkRTM1p1MzlPMC9IZ1dGR2FCOXhmdGNQemVQakpvaUxDTGRDemd3MWt3bUVXQ1prSGtBRTdWRVp0Rk4wMXorRm1jYWhGMDllcnMwaEdReFhrcnU1aHZZcEFGVGVTUHExRStuQ3hPSVJaWno0TTEwZ2xOOFFVZk9SWWhGc1Y5TEhyaHNsaU1JV2pIcXlBTG9nN0NXOWxFZ0VVeC9yMzYvRVU5cDQ0L2pjTWtoV1BpWkVIa1dHNTlIZWxiS0N3MXlLS1F5eHF5M2FKdVY1MUZNLzZnVjBxZXVYWGtOSTFIYW5HeFFockdFTCtMNkYxblVjL3ZFVzJHZUc0SmkzRmhtU2lzRlJiRC9NbzFVVmtVWXNDcGpGTzUrUG1VTjNNZXAxNFNuVVUvdmhYUlpKOUZ6Mkl4VkVSTVlNbHg2bFVmcC9iVnljUnRxd3dXdDM5ZituRnFMVWZYK2JLNTMzbmR6R1l4VFdzcExHcHova0xMN2FEUFh5Z3NwbGRSak5OREZndHRFcWxXbHlhNXJDQ2QwMFRxTEdUV2tlbUU1ajRXRGNCaWV0Kzh3b0xDTEY3VnlWd09zSkR2L2FJaEZxazZyNVhQSSttem1sNWRaekc5LzBTbTl1dnVZakdYcjdKZ05vdmhlaWFMVEova3Y5Z3NxRDdmZVhLeXFGenpuZW9ySEhRV3crbXpJZWQzc1hqcFFCWkRvMTVWVFIzNEdDeSttQXNlb3R5WGRoNmJqVVZOZzlIR3hhSnl6b1BMbzFWbnNlQXlaQzlHRzkxa2p4SmJ1T3ZtMmp1N0ZseVY0Nmk5Ti9ENnlEVzBnZWh0dURINzI2L1ZicGZ6SWJBK3Q4YzhqVThXYTZ5UlBoZ0x1dTBqN1FkaGNSMFh6TGJNZEhBVUZrVWZFMitaTHVkQUxNZ0haSDA0Q292dDg2SWNqa1h6Wk5HSGxyMnphSDdMbGNXV292OER3aWZFektwNHJVZ0FBQUFBU1VWT1JLNUNZSUk9IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiLCJVMkZfVjIiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJmNGM2M2VmZmQyNmM0MjQ4ODAxYzM3MzZjN2VhYTkzYSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDMtMTAiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMDcxNzAwMSJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMy0xMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDMtMTAifSx7ImFhZ3VpZCI6ImQzODRkYjIyLTRkNTAtZWJkZS0yZWFjLTU3NjVjZjFlMmE0NCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZDM4NGRiMjItNGQ1MC1lYmRlLTJlYWMtNTc2NWNmMWUyYTQ0IiwiZGVzY3JpcHRpb24iOiJFeGNlbHNlY3UgZVNlY3UgRklETzIgRmluZ2VycHJpbnQgU2VjdXJpdHkgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjAsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1NEQ0NBZTJnQXdJQkFnSUpBTTlSell1NEVJSWxNQW9HQ0NxR1NNNDlCQU1DTUg4eEN6QUpCZ05WQkFZVEFrTk9NU3d3S2dZRFZRUUtEQ05GZUdObGJITmxZM1VnUkdGMFlTQlVaV05vYm05c2IyZDVJRU52TGl3Z1RIUmtMakVlTUJ3R0ExVUVDd3dWUlhoalpXeHpaV04xSUVacFpHOGdVMlZ5ZG1WeU1TSXdJQVlEVlFRRERCbEZlR05sYkhObFkzVWdSbWxrYnlCU2IyOTBJRU5CSURBeU1DQVhEVEU1TVRBeU16QTVOVEEwTTFvWUR6SXdOVGt4TURFek1EazFNRFF6V2pCL01Rc3dDUVlEVlFRR0V3SkRUakVzTUNvR0ExVUVDZ3dqUlhoalpXeHpaV04xSUVSaGRHRWdWR1ZqYUc1dmJHOW5lU0JEYnk0c0lFeDBaQzR4SGpBY0JnTlZCQXNNRlVWNFkyVnNjMlZqZFNCR2FXUnZJRk5sY25abGNqRWlNQ0FHQTFVRUF3d1pSWGhqWld4elpXTjFJRVpwWkc4Z1VtOXZkQ0JEUVNBd01qQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIbHEyalVRTWFsSGovQlJlUWVmR2l6NEV2WUp5RkxXUHo0UmZoSkdLcXFsKzhuOTZoVDFtNWdYb1R2b0xyalNVN1gwY0Jlb1RzZ2h5aDIyK3lyczQrU2pVREJPTUIwR0ExVWREZ1FXQkJRKzhTR1cyQlhicWIyZGNBT2lXSk9VK0dDc1BqQWZCZ05WSFNNRUdEQVdnQlErOFNHVzJCWGJxYjJkY0FPaVdKT1UrR0NzUGpBTUJnTlZIUk1FQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUURxOHhJVzBaSzV5ejNFQXptdXg4OExDVFlPMTU3ZlRmeU9pT3pDMkFEeWF3SWhBTzFQV1lsZUZnSC8zbXVEOGNCQU1yMTFmRUtkRi9BYUMxNmZ0eGFlek5YSCJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFJd0FBQUFZQ0FZQUFBQW9OeFZyQUFBQUNYQklXWE1BQUI3Q0FBQWV3Z0Z1MEhVK0FBQUZJR2xVV0hSWVRVdzZZMjl0TG1Ga2IySmxMbmh0Y0FBQUFBQUFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NGdQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlRV1J2WW1VZ1dFMVFJRU52Y21VZ05TNDJMV014TkRJZ056a3VNVFl3T1RJMExDQXlNREUzTHpBM0x6RXpMVEF4T2pBMk9qTTVJQ0FnSUNBZ0lDQWlQaUE4Y21SbU9sSkVSaUI0Yld4dWN6cHlaR1k5SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpFNU9Ua3ZNREl2TWpJdGNtUm1MWE41Ym5SaGVDMXVjeU1pUGlBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGJHNXpPbVJqUFNKb2RIUndPaTh2Y0hWeWJDNXZjbWN2WkdNdlpXeGxiV1Z1ZEhNdk1TNHhMeUlnZUcxc2JuTTZjR2h2ZEc5emFHOXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNCb2IzUnZjMmh2Y0M4eExqQXZJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JGZG5ROUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlVWMlpXNTBJeUlnZUcxd09rTnlaV0YwYjNKVWIyOXNQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdRME1nS0ZkcGJtUnZkM01wSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE9DMHdOUzB5TTFReE5EbzBNRG8xTlNzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRrdE1EVXRNRFZVTURrNk16TTZORGNyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRrdE1EVXRNRFZVTURrNk16TTZORGNyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlEyOXNiM0pOYjJSbFBTSXpJaUJ3YUc5MGIzTm9iM0E2U1VORFVISnZabWxzWlQwaWMxSkhRaUJKUlVNMk1UazJOaTB5TGpFaUlIaHRjRTFOT2tsdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1qRTROV1l5WW1ZdE9EVm1PUzFqWmpRM0xXRmlPRGN0T1RGak0ySXpaakJpTnpobElpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSmhaRzlpWlRwa2IyTnBaRHB3YUc5MGIzTm9iM0E2WldNeFpUZzNNakV0TnpNM1lTMHdOVFJsTFdFellUa3ROVEZrTVRNek5EWmxaVEk1SWlCNGJYQk5UVHBQY21sbmFXNWhiRVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWo0Z1BIaHRjRTFOT2tocGMzUnZjbmsrSUR4eVpHWTZVMlZ4UGlBOGNtUm1PbXhwSUhOMFJYWjBPbUZqZEdsdmJqMGlZM0psWVhSbFpDSWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3lNVGcxWmpKaVppMDROV1k1TFdObU5EY3RZV0k0TnkwNU1XTXpZak5tTUdJM09HVWlJSE4wUlhaME9uZG9aVzQ5SWpJd01UZ3RNRFV0TWpOVU1UUTZOREE2TlRVck1EZzZNREFpSUhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5ROUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QW9WMmx1Wkc5M2N5a2lMejRnUEM5eVpHWTZVMlZ4UGlBOEwzaHRjRTFOT2tocGMzUnZjbmsrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrLzBWeFJRQUFHZlZKUkVGVWFBWFZ3WGZjbjNWOTcvSFg1L3Y5WHRkdjNEczdKSkFJQVVMWUJabUNpbURWRGxmdHcyM0hxWXVxUFYwV3RkYldSNjNuVkcycm5yYU90c2hEclJVZlBSM1dXUzNLVmhBWllRb0VRa0xXbmR6ek42N3IrbjdlNTA0aUtOV084NTgrbjJudWlzUy9KM0c4WVplWjJaVEVJbUQ4NStST08wWlNVZmlISlA2Rkh5SUVXQmpBd3pOdzZvYkkzQ3lrQ0dhR0pOeWhMTVd3Z25yb3BOSklDQk5VY29vaTBPOGIreGZGNlBMQXFJTWNHb2QyVyt6WUQ5Rmc0OXJBZ2IxaTBUSlRIV0dDdW82VWhlRUpkaTltVnJTTjhjS1lxNDJkKzhTS0NTTzJnQXdkSUJRUVRQeDdabERWZGtrV2J6VFpjS1RJM2RodnZyR2x1ZU05ZDhVVFgwUnIram1veVlDUU9NU3NCTHBBQWpMUVJ4cGd4bytSQW1scjRvY0laaGVHa0Y1bEJwTDRyd2hJQ1hMRGZIK2dEeGVGa0hnQ0NlU3dmNzhoRXovS2pNUEVENUlnUlh1UnVmMjBwWUJaUTcyZjdTdEdIM1ltVHZ4Rk1oY2dBd2xpQVJMZ0dXd0dOQWZXUXF3bWhzaEJjbjRzR09BK2w4cUN4eG1RQlUzRFNaSWo4VjhUWUZDMGpZVUZiZTMxZFAyeTVaQXpUeEFTNU1aQWdQR2p6UUJCMVlEeEE5WlowS2ttY0VISW1jOTNMdmkzSGZISWtxWmVqVElnTUVBTzdsOG54azhoM1lMbjNZUTBqdXNNMUx5T0VNNUU0c2VDZ096L2xQWWNFSTl4UVR0eHhIZzNudWtZSUw1ckVkZ09DQ2o0ZmdZU3NSNXFSYWVqcTBKaXVxcDRnaFFOTHcxVjRzZUZBSzlGTXI1SFFMVGpRZ3liTWNpTmc3SG4xcFdYZk9PaDZzU0w4UGtqTVFkTFlHR2F3ZDdmSlhZdlIwV2ZFTUFDMUJXRTRsWjZDLzlNbWY2T2N1VHBTSUQ0a1dVRzBtN0V2ZW0yYmM1amhvMVlPeG1QT25NVHAyYUo3SUNCaVk4Si9UN1FBa1lBY1pBQVE4RW9jME8yeUxiUlVVTUNNNUNNZGh2MnpUbGtJL0pqUkdBUlFoSElqWGlNR2NkS0duZU0waktJT3g2cFYrL0xadWNqN3hBTVNQdm82eFY0OVFYU09Nek53OGdFZEZvd013TWpZNURTWHBybXJSVDZCNHhWaUI5ZEVrdHVKTnFPdEhjKzhKaitFRHBkMnhUYWpHZ0FHZU1nZC85bllFOEk0SUlRUUN3SmdJTUxYQkFObWd5U2tSMks0Tno5SUR3Nkx6WWZMUXJqeDRZWk5EWDBlazUzTENCeFNBcDJqcGxoZ2hZMXN6WngwMVhOQlhNRXRoQXFRQlc5NWgwMDZRdkVFYWhKdE11WFVNUVgwRlJYMDJwOWhDTE5vd0NlcnNmOFByQlYvS2ZFWWNaL256ak0rQUh1RUFML0lUbGdZTVpoQnE2YkVRdnBTVWRHSGxQVnhCVmpkbzZ5NFJJZ0VOc0VPNkpCbHBFQ1ZMVVRnaEZMUVRZY0l5TUtRWk1oRzFRTkZLWDQ1ajFpWXRKb0pVT1YrQ0VNR0FFQ01BK0kvdzhDWEdDQU8xamt2ODFZSXNnT0VvZUl3eXhBWFltNS9jNnFsWVpuYURKSDVjekpoSUJNbU9BaDMvamxnWFZXUXo2UllEQVlYc3RDL1JkMGxrTTVBdkkzVUhUZlJ3QnFmeDRqbzF1QkwySVI2Z0RaRzBJQUJPNFFJMkRnRGlZT3NRUnlrSU1aUDBqZ0dVTGljUllBZ1F2TU9FUUNNeWhhNEJua1BJRUVGcUJvUWE3QUhVSUVCRG5maWNqcHBFbHhpSURJbXM2WW5aa2JhREpZTUR6NzNjZ2ZtV2tDUllMSkNQMCtXQUFLSG1lQVpFZ1FBZ1Rqa05FMnBBZ1Nod2pJQW96amdaOUJPayt3enNCYzdBTytndmlreEtQOEp3UzRHREc0S0VYT0VxenF0UEFBM3pIakM0S3QvQmNFeTRKeDhXaWJNMkprS29vYWVBRDRDdUxiR0JRbHhCRWpaa0dmOVhWdG00aGdDSXpaditYRkR6MFlOcDZOTGF4RURtWG5zMHlaRXlvbzB4bkkvb2ljb2FraFJNQmVnM3dUVWtuMjFSZ25FOFFoclE0b2cyY0hiUWYyNHF3aTJIcVNCUnFCQURNZTV3NnBnTTRZREhxUUd6Q0RrQ0FWTU95QkhDd0FBZ0d4QURsNEJvc2NacUFNQ0dJTHdqaFVQYUZzd0E2QzdtRkptbmxVSE9RWldsMVdqNHl5UlVFZ2tCdGx5VDJ0cUFONzU0VzVzV1JDY0tyZ0RMRGpnT1VHQ29HZEdMY0MveXA0aEI5R0VPQ1lxWFo0Ylc3c1JkRjBGR2FHSUFNcFFzQ2VaWUZmTTdOM0NQN2FRSHdmQVRtclJQWkxyY2l2WUd5V1dWZUN0Wk1nbDVySzNwU2lQb2J6aDhDQTd5TWdpMUdaWGVwdXI0ekdwZzJyWWxuWEFqZVVoRHNQV2VUUExmTEgxVURhZm0rbUxveVJ0djNFWk5jbXF5eGFOQ0J1dlQ2ZXV3UHhNdFJ2NCtyUkc5eElNdWcwTU5RQkxOeFBhMlFMdVlGcUFNVG5BOC9ub0NJQXhpRWhndWNETFBZK1RqUDRFdU5qOStEV0o0UkFOWE02ZE4vQ3lMS3pXSndGYnlCRVFCQkxVSURGbVFkeFhVY3E3c1RDZ0dIL0tQcHp6NkF6ZWhJR05BMmtObmpld2ZiYlBzclk2dnRvVHo0ZmExNklCY2daV2lPUTYwZllmditIbUZoeEI5M1JuOFB6eTNEZGpyR2RKYW03TVhDUUJFWGtERFBHY2dVV3dYQUdmVjFmVzBCdWF5M3k4N2c5djkyMkV3MWJJVGN3Z1NBRlE4Smo0SDZaWFZGTEh3Qm0rUzRIQXJ4NDlUSjdSOWtLeHc4V3dRS1BrNkJzUVFHV3pkWVhvL0dqZFpPak1oODJEcE1nSmp0cDlVVDgzOTFrRitlR29rakNKYklNbHhCWXJuVmt1MnR2TXc5SG12SnJCUU9XT0ZBRVRsblZEaDlzV2JpZ2NjTk0xQm5Fa2lBa2tMRWhCSHQzR1d3Vm1kKzhkNXZ6eGUvRTlNeXo3Y3lMejRmcUVTaVYyVmxzK1B5ZVltMlBQay9GTXNnSERQb3pXSUNxZ203bkFUeS9nTms5cjZFb24wZDc5RWswRlljSUNBSEVFb0VQdjhxakQ3eVRWY2RkdzhSNFF6V0FMQkJnK1dGbUZyL0tiSE1GVStYekNBbXlnd1VvMHg3MlBmU1hQSERuMzdMbEtROWgxaWRFd0dGbTF5bzZ4N3lWc3Z0RzZoa3dvRFA2TmhabUxtZlp4aFlwWFl6WElBR0NhQ0M5aTE3OUZ6VFhRVHJoUXNwTjRJdmZBdVpaa3JwZGNaQ2dFMlZuZXpaY0ltSzBPbngxZHRiK0xqZTZlTlVLKzJEQ2pxOWRoQkMwNUFEU2lBWEtWalNhUmpRaXhHREhncjNUNEZuQXIwcDgyd1dkeUZ0YkkrRzNUVGJldUJBUWdCQU41UE1qTFQ1M3g0TzZldHNDKzg0L3dkWk9ZaTl0aU84eXk3Y2kzY2hCNHR4V3l6NFM0Y1FpUU9nNnZSNTdURnlWZ2p5WVhTUlkxUUFPZEdKOHFhUnJKUHRvVTNQUXVTbllGYVBSTm1XRGpERFlXZFYrdlJuWjRHd3oyMkJBTlpTVm5maXFvNDdsczVQT1ZmUExiTzJLVWR0TVgyQUdCUXc2RTljMGQrMWR4ZHJqTnRGT29EaENaLzk1N0hoZ0swZWZDNkVHNXg0R2k3OU9TaDhncEtjUi9kY291NmZRbjRmc2tDSlEvejNVYjJCcXpVNmFQb3dzTzViaDRBSmN1L0RtcTdRbkJ2U1paL3ZXdHpOMjdHbDBKemN5V0FUWjlWUnpiNmJkdm9iTjU0cWlCV3FnR29JaXRFZjNzT2ZBbXhpM1NMZDlLVlYvRjYzdVZ6ajZMSWpGT2xSZGdBVVFFQU1NcTN2SmRoVnIxa0p1TGNNbW40b3FvTDRaUElPUkdIQ0lHVk5FVGhKZ0J0bjl5OE1Ccng4ZHM3Y0ZoWGQyb2hnMmZtUE8rblNRM1F5MkQ5TmtVOWtwaTQyL29HeUZpOHBJa0F0dnhNU1luUitLK0FrTHpZdEcyM1pCdXd4dnl6MjE2MGFZUVpGQVVQVjcvcW1pc0Q5blZMZjErdlNuZTQ0c1FOWVZqZXp0cGZIVVJuNFRzTTRzdk0vRWlTSEJURi85aFVYNzA3S3RqNDYwMklYSU45elZiSjRhaSsvZmNuUzRzQnFJeGxXMFkzemR2Z1UrdW0zYWp6anRLUDRNYkZNdGtHbk9zNzgzaFBESkVPeFJTUmdjaVhnYnhrc0ZscUt0YUtmNHd2NVFWNTE2cko2MHlqbWgybTlZRUpUc2ZvOWUvOGg5QnphZXdSSHpVNFFDRkZxRThBYTh1b21pdUlXbUQ1NmhMTURpZzdSSEh1U1dhNy9Fc1A5UlRubjZzNGdHaS9XMXlONUlIT3lrTTdHTWhZVTNzN2o0VXNScWlsQWdQazZPdjA2NzNzdFI2MjhuaHh2STJraDMvQ2JtRjErTHVJM3hOZURoNlZUOVZ5R09SUGxtR3Y5VEpsYnR4SUQ1NFYvU2FqOFhmQ2R6ZXhleE50VFZXVVRmZ0JtWVFURG9EWGZRMHpZbVdwQTJub1A3Q2ZoZ0h5SGZqb21Ea2pqTXhQcEFPQTREejl3ZzhYN1YrcjJSVG56NVlxMEhkcy9sUHh3cDdUUEJtT083Z2tIbFhIdjN3LzZ4aVNuLytWTTJwYmRYcy9Za2oySTRFS0VLVzU1NlV2SGxtSmlvZW1vcmMwZ3JRUU9QSGhqNlcybnNiOHFDeDhVSU1SaTQ5dGRaZjFBVVhEQldwb21GU3I5bEZzNEpDQXZNN1pyMVMvdnpmSHpEZXNNTUVEUnV0ODczbXJjb3AvY0VXQjhEelhSUDkzL3FPaS9PUHpuOWFtdlVucnd3QzVnZTh0cGZCWHlOSjdvYjlEdVluV2pZYVo3RllyWk5NY05LMkpLQ2pWZG1kQm5BZ0JzZjBoSGIyTEx1ZGFRREkxUVZ5S0N6Nm1TT21mb2s3bitNL0V0NC9RaXRVZWlPZ3pjZzdXRFkrejF5UG9taVhFOWpmNGhwQjZiMXBIZzU0eXVmd1hBQVpoQU5YQytuYW00bDhCNjY0OUJLQjhnTE1OZDdKNVZ1bzRxUkVidU13Y0p2WTJFTWkxQ01Yb1NxRHRobHhBQWR6ZEkwZXlrNzMySTRuT091dTJIOTZ0Tlp0VHd4ckNBWXhBUUwrMi9Dck0vb2F1aFZUNlpWZEpodXJxZXRBM1FpT0tRVWplODZ4WXdwd1U3SHIyMG5lMHYyZEc0LzYrdnUvaXBnRzk5bGdGaGlITkk0dlVhNkhQZHY3aHZ3aWJGT09EVUJ1UkhqSXh5Ukhlb0dna0VNc0d0RzM4N0IzMWgyN0dvSkVPRFFiVU8zTXU3ZG5sblpFV1hCVkxzZE81WTVYaDVlb0NpS0NETnorVVBUKy96anJaU1F3SUE2dzlwSlp6RDBhd2Z6K2VlU2FTd21jcFhaTlRWcXA2OVpZYjhpQjgrT1I5NmRVdnhhTUVZbEdXQkxXSktCQTNKOTI0elRXT0tvWERTbks5dVlKQVFFZ3dQTjZOVzdlMnVnemRtUVFTd1I0TkR1Yk1iOXI4akZWcUkrQWZZWm90K0grbkQwYVN6NUJzcTMwQnZzZ3ZBTm1qM2dmaFJoK1RTaHVSSjVCWWlHQWhnaDZCNktCQWFzV0g0Nlg3L3ljMWpySyt4N0FEWSs4K1hFK0FjSXd3UmlTWVoyK1V0SVoxQTNNeFJoQW1remxuNmZiZHNhUkllaU9KV0RESkJEdzREMjJMY1k5bUIyRGtKNk1yUmdxbk16VFgyQWJCeVVrRmpTd3V4MENReWZqbTdQRGVOaDA2RFVGMXA5dlp6R3B1V0FRQVlaTU1BTTNDRUEzVFpRc0hXdTFzL1VNZi9WVWQxd1NiK0dRUTBHbUVHSVFBcGZmM1IvZnUzS0ZkemxBak5RZ0dZSUoyMkFacHY0ME9maHdqTUR6ejNkTHQyNXgrUm80K3JsdGl3UElYUzRwMTN5SjFQelJyc0ZxUVYxQXdaMFMyTTRCRWs3REpGbHJCaU54WXZQNTRWa1Zpek9pWkJzRWVtbmdMTUU0NEQ0bmhvb0RNN2lJQU9EeFdnVTBUaEpBdHdnd1pmakpYZHNEU2UyQ1BrSVZBTUJNQkRRRERra2RVN0V1dStpSHJ3YWVBbVRvemZnd0dJRnFJZjRCS1ZQMHg5QzVqcTh1WTVROEQzR0ljcFFsTkNkV01uZXZjdjQ5cmMreXJMT0lpdlhybUN5dUl6S0RSTmdQSzdKWGVCY3pNQWRzUHN4dTQyTlI0SDc4WlRoRk9vS01FRGc3R0IwZkNzUjJMdi9CSTVZdHhrTDhKMGJyNk8zUHhNTERrcGtEcHFrME9rZ1lyQ2pyV01qOSszUlRkTUxldlU0VEs4ZWc3SUZicEFOaEFoQldBTm1jTVJ5WTZTQS9vTFl2TXkzMXpsZTJXdTRoQ1hHWVdaUU5mNzMvWXBMeTVaMmxRRktqTkFDQmVoVjBDbUVBQWRpeVhuZGJucnAxdW5tajhwUnpsN2ZzbmJkd001NXYzcmRsdkRveVJzTUdqSFlBVFBUMEVxd2NzS3dFRkV3M0NDSFFJVFYwZXlpV3VBR0VVYktFSDdhQVFuTURBUU9HR0FzQ1lZQUE1UjlheWZZNlFsN3VtU1U3UnJtZUhCNy9hVGJCMVBkNTVCN0czRExZTHM1ckEwMkFVVFVnQXRTc1pIc0wyYlBnUnRvSEN4dkFGdERzSzBZTUhsY0MwOHJ5TDJFNmhxTDRxQVF1cmdtaVVYQnNQOHd2ZFlycVBiTXNuN2wxWno2SEZpMjVrSnkzc2hnSGtMZ0NRd1FJQ0FWc0RCN0xiM2VibGF0aFJCUFlYYmZDZzZ5Q0ZaQS81RTdHZTYrbmRGVFlNMkcweGxySDBOdjVnQlgvZU85UEh3M2RFWTVLQ2x3MExHQmNDb1lvSkZPUyt6Y21UKzlZNWUycjE1aGREdkcybkZqVUlFQkJwaGdVSXQyYVJ5NXlyaDl1NWp0aVJQVzhSeXY3SGZkaklCNFRERERHM3Y0emwzRGZXdW5qTkZXb2gyTUprTHRFSUVBOUlZd1ZqSys2YWo0ZitncW5MWkpOMlhGMXd6bWhSVlVETm5hVEFNbTZnWFJ6Qm10MHBBN1ZRMnJsaGMwYm1RWE1RblByT2tOT2M2Q2lJWUhXQkNxQk1rTVk0bUV4WUFsbzE5bDlUbXM3V2JUOWRBL1ZyVHQ5Qml0VzFYUXNReUo2NjVaUEhVSHpzOWlneEx4Qm95cmdRSTRIdlFCektad1FWbUE1RHk4NnlZcXdmSVdkT0lGTUhJQ3NkMERRVFZZaHpWWGdFMUJtQVZ6ekVhQUk0RWFZei9ZREtrNkZ6cFhjTUhQUGt6bktDQ3RwOW9mZVp5QXdDRnlpQWtDbWV5UjFMcWRYUFdZMlFObUo1REtoRHRZZ1BiWWtNWFovNHRGaUN1QUF6OUJNNFIrLzBZMm43T0xkY2RCS2prb3lRQmpNOUExUkJiVWl5eXVuN0M3amw0TFQxcGp6QzdBWUFobVBFRXdrS0JxSURzRUM3OEk5cWMxakVlRStCNTMwV21GWDE0Mm11NnFjLzZ3QXhsd0FRWUlxZ3hqSFZhODhxSnd4VW1yd21tUFBseS9lcW9kRHlTejVYVWpZbTNGaXJhV3orNFdRU0taRVZxZ2lzTUVUYU9Pakd5b2FIZkZjTkZHbEJrTExERUxnK3gvSGN3L1VnUTdLcnNpUWc0cVpIbTIwZTZXMlp4eFNMZHB2SjJkK3dyczlUbERMQTBHa1VVMWR6UVR1NkRpR0pMTlkzd1d0QTBNcFB1QlM4SE9CWUVFODR0L1F0SDZPS3VYUWY5UjhQWlRhWStzWXZiK0JZWXpNUEtrZlJUbFBtSThIeHpNUUFiMTRNc0V1NUpRM0lMN3k0aUQ4MGhqczdoVlRPOEI5MXRvdDJwU1RNaEFCalNRL1hNVTVWZkJkN000MkVJSWw3Rm01UnlqSlh6aXo2Q3V0dlBjTjJSNi9VVFRoOFg5SDZmVitSdXFHYUEvVHE1K2dsNEZxZlVOTHZ6NS9hUUNKQTVLSmxvVzdHUXpReEltWStqNjFvWWp1TmJOMkRjTEdKaUJlSndCSlRCMFFRclczYkRDL3FBc3dwdUd0U1hNT2NqRWZoa2RvQ1BBWFdQSExFdnZuZTlqY2o1aUFlZTdoS2hxZThieGE4TDdXdXZpS2ZmZG5SLys1ajM2MG5PZVRwaE1pZ3hBWUpWNGFveFdGb1RLbFVFR0JuSUkwWDdaakpjSFZBbWIyRC9qZnpiUnN1OG9XZCt6dXNrZ2kvWWcrNTJqSWQ2SkdXWVFnZXlCUFpYTzNkQU5Gd2ZSZFRFbStUdGFwUjhSeko2UjNlaDB3ZlkzZkdiZmViZGRjK3pMVmxGckk0T3FEV3FEd0FLZ0E4QmJ3ZjhuS1FWQzYxTlVNNTloMVNTME90QWZ2WmlpOVFKTXNMaHRHY2tnTm5OUS9qTEtkMEE4aDVBWHFQdC9EOTFQRUZPbUdYWUpjUmxpaVRhalpncjNhYkpkaC9ST3hHK2hQRVdJY3lpOEg1cDNJMStrYnFBLy9CM1dyb1U3YnpqQW8vZkQxQkd3N2JaUE02eU9wQ2pPb2FuK2xmN3NCMmxQUVFSNnUwOWdaT1JrSEREN0p0VVFxaUdQU1JhWURHWlBGb2Nad2t5cit4Vy9HUXdyakVJOHJoV01aWUtWd09kZGZNaGQ1OFRDM3JscU1weGZ1MmdhVVFTamN0MFdzRmNYMGl1YWFKZktSUmEwSXFObE4zNWc2UDZ6TG4wTzdDR0RvOEdlRVlNOW5SREc2TG5QenVjM2JaemlvZVpBWHFieHNLMVZoT1hEU3BqWkJhWENSOHowQm9jNWxyaXpQSnE5dlN6dDBpb1RPeTFqVUduMjBXbS91NzNCdHJmYTNEK1l0Wk96WURUWmEzcFZtQnMyOXJ1dGtzck1rQmhQUWIrNHZoMStUekJsQmxtNnk0eTNKMk9GMEJhTFJyMllTU1YzUGJqcUtWK2JtVnYzVThUZWtaZ0Q4ZG00MzAzT0VBT1kvUnVSNjJtMUN0QTgxWDRJVTlCVW15bGI3OGZLWmVRK0xIL3laUlREVzZtYi9lRFRpTGVUMnFNTUZvYk03eDZ5K2hUSWZqVFcvemd4bllzREZpNmlHWjZDNmQ5b3BZenh4elM2aW1ad0JHT2o5MU9IMi9EZ1pJZFcrZnNVNmUyME9yRG5vUk9wZFNXblBnM1diTnBIdHJleHNEQkNxelhIeUNRMERpSEIvUFJHeGlaWFlQVmVjdk1RTXI1ZkdoblYrb1Y1T3kxRURuRkEySEdsd2x1aUFjWmh4aUV1N1RYWmZVTEhoRUtYRTNoYTVheWlobWhHQTlSWi8rVEdiN2puNzhqOUVTeGVIQ3djRDJLWVJUQXJrb1hudVBqSkFIMkR0b0tsZ2lVeVdQUkxKenY2aDFnRUZxZlovOGgyL2MwSngzTnFVWkp5QTJaNmhkQVdJL3lyUkxkVDhFekhOc3VnMHpLaWFXZUtlZ25HTFFNcERPYTVjaVRZeWJVTGkyYmRNdjVHblhXaFlWZUR1bVoydHN4T0c0MUsyYUdXM1NEcEpSWTBJTmg1WUFnREJ3TDNySXI3RnFrNERVdGdCakcrbWV4M0luMFJNOGlDZmpOZ2NHREE3Q09RYTVDOWlGaThEMXRZajljZ1FXZmlFdXJwOStMVkg1SEN2Wmc1K0J6OVBpejBsN0dPWDREOEZocGJqc1FoUmlJVzc2WVovZ0lwM29YVVlNMzFwQkxtNTJGUVFYdHFQYTN3djVDL0ZET1ltWWJUbnYzYnhQWU9lZ3NmWWQyeE1Ld3lnMnFlbGoyYk9oK0w2eTlvdDBSYWZSRzVCdVZ2NEhvWXhQZEx1dzl3M25oYkhYY3dRSUlpUXBGZ1dBbDNzTUFROFlqZzlpYjdya1FZaVlVOUg3TjFMaEVFalhEUTlZdERmMzgwUHROcUJjOUFJKzBJMlg4cHBYQzVzR01kSVFseFNCU01HbENZTVdnMGJkYTh2b1UrN2Rud0RKMElldzdvWTJzYWY5cnFrZmh6dlZrbm04emd6R0RoVEFFUkVZTlJaZEVmYXV0WWwxZW54SFdHeUFmY0xkdGZ4ekY3VnRtMjgvcDlzU1NtWk9lNGN3NFlCemxHUHd0My81Y1F3cHN3dGcxckptSVJuaG1DZ2FBVEttWTBkZHZuOVR3b09Rdm1PVVJhVFF5WEkvOFk4RlZjRHpCMEdNNnZZemc0aGJYSFA1TW1QNU84V0JJVGg1aEJOUTkwZm9HeWZTR2V2d2kyQzI5RWQveEl5dllGREJlUEJrcENBbkdZWjdCNEZtWDdNOERsb09zdzdTYW1rcm4rTVhqOUZMcnBlZURIMFRpWWdXZG9qWGFvNi9jU2VEYkQzcTFrYjJpWHgrUDJYRktNaUo4bTJEaXhQQTAxNE54TXRsbU1KMGpiOXRuWlp4eG5ET2ZrQkJRQ3cyR2poY1ZLMDJXeW5nVmx5ZVl4VEhCY0N1RUNDNHpXV1ZuaTNtUzZyd2pjT1plNXZzcTZPc3IyU2VJeEJwaTRidUQ1eFFHN0xKbTkwTUZTTUNSd2lTTFNtNm4xand1VjNydXl4YzBza1VSck10RHBHaWRNc1pDQy9hcXl6d3E5TWtVcnpJMUdBb3hhMEU3YTQ1V3U3QS8xSjJQZGNEOENCS3BFdTlTT25NUEw5ODN6NXhOdFBTc1JHR1lvQWtqZ0VnbS9aOTlRSHk0amwzZUQ3UjlVam1BQ09CV0pROFRpUGx2KzJmdDEzQmJFNllRYUNEWHVodGthaXVMTm9OZVF3bjVHQ3FOWVBzbXlJOGFJUmFMdVE2NGJRaUVRaHhsZ0VleG9USy9qb0p5aDFZR1JTUmpNQzFFVEFrK2tRRXhiVUg0WGhCa0lzN2hLcHBZdncyd0VyMW5pbURXQUVTSU1lbUEyU296UFIvNThZb1FFdUFDRFlKY2dCM09XT0hBZFFmeDdhZlBxOE1GcVVaL0VhRUFLd1JaN2ZlWVhLeTBldWRLeUdwc2FWa3pHU050Z0JPVElwcHRHTTJBTEtYRUFtSGZSdUtCZ2lmRkVCbG42bHNQL2tPdUtZUGFVb2V1b0VHd1lwSHZxeHI5ZUs5emtNRFMrVHpTc01Eb0pBdXoyckRjT2gvbnZLc1ZuV05EeExRaVlwdDExaXpKZms3VFZ6REtQTVNBQUJpSHc0TjQ1dmVUaFBmNlRXOWJ5bExKZ3c2REN6TmlaVE5lWStIcVdIaExHOUVKTjNZaVU3TUJJYWE4UmdTQWxFb3RmcUo5MTgxMzk0MWZRN2IrU1FNWlZBWVprbUxXUnVoaHR5Z1FoMUJpTFZJc0RqRXhJZ1BORURRZ0RFcEFJQnJsdXlFMkRtVENXaUIrZ0pnQWRqQkhNRXBLSWNRajBhT29oWmc0WWp6R1d5SkFpVUNBSFVRTU5CMGtSY0VRYmJCYTRpUi9pL3dIM0Q1UE1wZDJ0NVFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiJkMzg0ZGIyMi00ZDUwLWViZGUtMmVhYy01NzY1Y2YxZTJhNDQifX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDktMDQiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPMiBGaW5nZXJwcmludCBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDcwODAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wOS0wNCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDktMDQifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI4NWY0NGY5ZmYwZjNiZTZjMzczYzIxMWUzNDZlMmU2YmM0ZWIyZDVjIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjg1ZjQ0ZjlmZjBmM2JlNmMzNzNjMjExZTM0NmUyZTZiYzRlYjJkNWMiXSwiZGVzY3JpcHRpb24iOiJBQ1MgRklETyBBdXRoZW50aWNhdG9yIENhcmQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MTAwMDAsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH0seyJtYWpvciI6MSwibWlub3IiOjJ9LHsibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNRVENDQWVlZ0F3SUJBZ0lVRi8wd1RQUDZGRXF4cHNpYkppTEZ0RGo0cWh3d0NnWUlLb1pJemowRUF3SXdkVEVMTUFrR0ExVUVCaE1DU0VzeEVqQVFCZ05WQkFnTUNVaHZibWNnUzI5dVp6RVNNQkFHQTFVRUJ3d0pTRzl1WnlCTGIyNW5NU013SVFZRFZRUUtEQnBCWkhaaGJtTmxaQ0JEWVhKa0lGTjVjM1JsYlhNZ1RIUmtMakVaTUJjR0ExVUVBd3dRUVVOVElFWkpSRThnVW05dmRDQkRRVEFnRncweU1qQTFNekF3T1RJek16VmFHQTh5TURVeU1EVXlNakE1TWpNek5Wb3dkVEVMTUFrR0ExVUVCaE1DU0VzeEVqQVFCZ05WQkFnTUNVaHZibWNnUzI5dVp6RVNNQkFHQTFVRUJ3d0pTRzl1WnlCTGIyNW5NU013SVFZRFZRUUtEQnBCWkhaaGJtTmxaQ0JEWVhKa0lGTjVjM1JsYlhNZ1RIUmtMakVaTUJjR0ExVUVBd3dRUVVOVElFWkpSRThnVW05dmRDQkRRVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQndZZ0tWd2pDVjYrbHY3Z25wRkVSelUydU5EOGdkRWtQQ05jcy92RkRzMnNLNDJKdXhuaEZuSWdNQjJEeVUwSXJYSUxqZi8yWFQwWVNUZDFzUGlUU2FqVXpCUk1CMEdBMVVkRGdRV0JCVG5RYXJwZFN0NHNpZDdWamZOSUxJSHJiMlBvREFmQmdOVkhTTUVHREFXZ0JUblFhcnBkU3Q0c2lkN1ZqZk5JTElIcmIyUG9EQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRRGNvWEozcnpOTUEvZlpraDA4UG9Gck14NDNHWU1oWk1mTFB3LzNNZkpwR0FJZ2VjdEt3bUpZTTlKOFNYOHgvYVFWNGlHdktXb0JmcjFYUFRBTVhPaFZFWUU9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQURBQUFBQXdDQVlBQUFCWEF2bUhBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNRQUFBN0VBWlVyRGhzQUFBaWNTVVJCVkdoRDFaalBpNVZWR01mOUM5b2I2REpvSVFpMWlEQndJNVFnRVVFbHRCSjBZU0FHRXVSQ0ZCTXhJa2xDYXlGSVFpYUtCWlVvbFk3UU5KTTYzbkdhY2E2ajQwdzAwNHpCTUJPNkxFN244OXo3UGZPODV6M3Z0ZHE1K0hMdWZYK2M4L2srNXpuUE9mZXUrUHV2djhMakxEUFFHaDRPN2ZIeDBHb05wODlWdGEyZG5KeXNhWHA2S21sdWJqNjEwdno4WEZoWVdDaHFjV25SdExTNEZCNCtmQmdlUEh4ZzRyTVhqTDZWRGg0ODJEWFFCVTlHWWp2ZWJpYzF3UXU0QkErNFBzL096amJDbXdGbjRyOG9HUkIwSjlvZEpmaDJIWDRxZ2lJUDd3VTgwS1hvZTNDRGZ3UjRIbldKbWVwcG9LTjJEWDU2cXB3eXRBRFB6M1VpM3dzZTZQOEw3bFV4a0NzSFIzblVCYzFucVFUdTRiMkpFdFMva1FKUU54RFRoYlFwd1FOSDYrSFZDcHJ2dE14Q0RrK2VMeTVWb1h1WktNMkFuaThhYU1wM2c0NXBZMjBHajRCVnZ1ZlI5OUdXUEVoSnZWTEg5ME13c2hub0hYa0JlM2d2RDU3RE0xZ3ZhTlFMSEZYaEYyMk1aQ0NIUm9CNkFWbUN6OU5Gc3RMWU5WQ0N5YStWcE9jRVRuOStqRVlET1RpTDk5K0NsOUlHNVhDS2VLL0lWL3JvOXV2SEtocFFtUVN5R0hHWDU3TS8vQkJtUHZzczNOdTFLOXpidkRuY1diZXVwcnN2dkpBMDhlSkxZV2IzN3ZEN29VTmg0Y0tGOE9mTVRCRzZCTy9CcFpvQmJWQytYR3B4b3RscjE4TDAvdjBHTXZyRUUyRjB4WW93K3VTVEJqcjY4c3RoZFB2MnBGLzJ2eGR1ZmZ4eDVSb2FmKzY1TVBiMDA1MTNvOXFyVjV2NSs2ZE9tU0VQTGZDU0FRcEh4UURSVlZ1SmVFeVZYOCtlVGRDMGQvYnNDYTFQUDdValNIOS92N1dxWkQ0SURESTNUd3BPbStpUDY5cmxoejcvUEF6djNkc3hId09Cb2VrMzN3ejN2LzIyWXFBRVQxc3g0Tk9HQnhEZ3Q1OS9QdHg5NC9Vdzhja3hneHc4Y3NRaU9mTHNNNVk2OTYvMGRRYUxVZk1wNE1VWVhLZk43NUhYakFVRGhxNisrcW9GNnRhcVZXRW16cUNnbGJxMEJJVjNrZ0dCMHdyZThqb0s2TlkzMzRTYm16Wlp4N2ZYckFsM1B2Z2dUQXhkdDNzTVRLZWErZzVVM1lTWERPbTcza1ZBRHJkYVlYanJWaHVQbEpzZkdyTHJZaE5uTXBCSEgwQmV1dlhkZCtIV0s2L1kxSkxuWXlkT2RFK3VMWHVlVGoySTVBRVZkVjN6OTJoejBhYzBFdE56WlAxNk13SVQxeGdYa1lxVkdaQXd3SU8yNkNJNEVTRGZCd1lIREp6N3lrOEdGQWl0cE84ZU5yL3Z4WGhOK1E3VHpaZ0pzSXdkT0pCbUFCVU5MSTZOcFFVNy91Njd0a2hKRmJzWEIxR05KMjJtMzNrbmxVaEtvOG9pZmQ2UHBsVmFLWjFMc1Y4QnMwaC9qUUhTUGNiTXdlbGZZbXlxbWkzeWp6Nnk3MlJMeFFBUDhxS1Z1RmdSYnA0K0hRWmoxTWx4cmlmNEtFQlpDM1RveFRVQVMvY0lDQXNlVTdWN1VVb1J3VnNiS3lCc0FyYXNpUDJ3UnRpdktnWjRvYjFsaXowdzFOZG51YzUxSDNYZ2lUQ1IxOEEzTm00TXd3Nks2cVRQcmJWck8vZGluM2F0V3lyVFBSYXFyc1ZuVkJDOFpDQ1ppTThQdnZXV1Bac01BTThtUlVmdGt5Y3Q4bHdUdkRlQkFhYWZ0VUZFV0JkMFp1YTdjR2prcWFmUy9zQzBtekVIYThVZ2lwbkdDQ0pkYytDOHRUMG9tdWZkaWdHbWx0eFhKOHZnbmRPa0ZxRDAyOHh2ZHZ4bVVaVlNDbURnRjd0NVQ1OFVBOTJuNWpNdTRoN1BhcTE1Q1o2cVE2QW12emhsNzhOWk1VQjBXT1UycUl1NG9wNkxSY211bWRJalV6TFFQVXFqaFFqaG4yZTlFYlRmdi9xcUNDN3hIWGhhTW9SM0wxMjZsQm1JRjRrUUQvbDBVZDduOEUzZ0V0T01BZnEyV2NSQS9Nd0IwSzhGaVVVc2VPVEJVL1NqT0JIdy92bno1NWNOQUV3bjE0OGVzNVF3eUliSTg3eEZub0V4d1RxSXhtMm5ka0NhQWFCekFjYVI1T2RZcGxrcjZrc3BwR2o3Vm1KalphektER0NBbW56ajdiYzdHMVVEdkVUZFoxQXFEUDltY0ZEajJGRXhFTUZrNEkrNDRFZ1RpVE1XMXltRjdPNTZoN3dtMmtBekEvVHI0WlUrbUw5OHVXL1pBR2xpcFRGT0RTK1hEUENjUGsrODlscG4wUGo4NUpVcnRoR2x0SENwUllVQnZyUXZrRElZU0gxRkVWVWY4YW1wWlFPY3ZSaGpmTU1HUzU5S0ZRS1lTc0xnYk51UG1nRitqSGdZTDlLaWFYM29wTmwwRHdNR25rVWVlQlk4cy9yOXVYUDJITE5iTVFBWTJ6K2RUWjg1VXdIMjBaZjRKWmFpSGpXeWNxWEJFNWtKTnNLNGlIVVBhQUJKRVdZbHYwY3FBc1c3SGh4WjJzUnhNQ0I0bmlOMWF3YlE1TFp0MWpHYmp3Y3VpZlZDSkFDelRyc0FXcWg4NTU2a1V5elA4QjBZcVFZZlUxTW5ZVXViYVB6aXhZc0d6cGlWR2NqQnlFOWVwRWFUMy9sOWhHbUpJcUFLazZ2cFNLQ1dkYUJmYkRrNGxZd0ZDL3hQOGFjczBBU0JkamkyeFJsQVhLTmUyM0VoVGpFTHZQSjcxWWthWDRPT2NFQXpRNUxnVTVYaHp3T25lL3YycGZFd0lIRFNpN0xKYndObVRTWXFCank0TjBKazJaMHQxMlBIOXVPYjM2c040Qkx3dElMMkVhZjFhY0laaUJTWjJMblQ5aE5McWFOSDdaREl1QnlqbFc0R0gxTU5lTnJHRk1wRkJHOGUvckR6NjZpNzhERERiMWFPeUI2ZVp5MXQzRkZZQWpwdjBkVXZ6MWtCRURUQ1dOL1hYMXZKeEFEUUV2QTFBNzJNS0YwWWxLbThmdWg5R3l6dG9sRnNoS3daL1pZbUpkaXd2RGhKRW1sRTFPMkUybjJmdmtpWC91UEhEVnJnZ09hUkx4b29RYXROY291VnlLbGpIUXVJbXVWckJKUElhLzlkNHRtck8zYUVIdzhmdGx3SG1DckREaXZBbE8veEI0eXVTUno1SDVsQ1RmQmVXcXd5cENnUnZaTElaU0RSd09DZ2llY1ZERnBKc0Y2QTYzTXlBS0RhR25oVUwzQmE1VGpTUWtWNXJudlozL2tPMWd1NFBGMlE0QWxFWlFZRW5rZWVLdFJVNC9OS2cvSXFreDhKSlAwelY0SHVibEFHM2dNZVlZQzJaa0RnZ3MraFU0WHBpdStvWk1BYkViUmFEOTZCWDk2Y2VzRXI4dnBjTWZBb2VFbXdBdmMxWHZLblNLODYrSExPRzNnQjN2NlA2Z0tyeFFUWGl3YnlEVXFwb3FqTGdJZEhBS3JOMVRQZkl6U1JMMVdhRXJ4YUZuL05nQWYzS20xS09UemZjM0NVNTd1aVRpdlFrcG9pVHl0VkRKVEFnYlBJWndZRUQyQVR1SUNiQkpUYVhMM2d1VmN6a0lNcmJaQUh6K0h6MWdzNHRRYXF5RWNnKy9jNVN4c3RUcjlJMVE0TURDWm9yMFlEQXM5ekhsV2kzM094bHZNZUtMVWwrZWlUNTUyMm1qcFNNc0NIeDFNSHd6OGNlSHk3RWhSejVRQUFBQUJKUlU1RXJrSmdnZz09In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDctMjAiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkFDUyBGSURPIEF1dGhlbnRpY2F0b3IgQ2FyZCIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMjMwNzIwMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDctMjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTAzIn0seyJhYWd1aWQiOiJiOTNmZDk2MS1mMmU2LTQ2MmYtYjEyMi04MjAwMjI0N2RlNzgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImI5M2ZkOTYxLWYyZTYtNDYyZi1iMTIyLTgyMDAyMjQ3ZGU3OCIsImRlc2NyaXB0aW9uIjoiQW5kcm9pZCBBdXRoZW50aWNhdG9yIHdpdGggU2FmZXR5TmV0IEF0dGVzdGF0aW9uIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmFjZXByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhdHRlcm5faW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwidGVlIl0sImlzS2V5UmVzdHJpY3RlZCI6ZmFsc2UsIm1hdGNoZXJQcm90ZWN0aW9uIjpbInRlZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRG9UQ0NBb21nQXdJQkFnSUxCQUFBQUFBQkQ0V3FMVWd3RFFZSktvWklodmNOQVFFRkJRQXdPekVZTUJZR0ExVUVDaE1QUTNsaVpYSjBjblZ6ZEN3Z1NXNWpNUjh3SFFZRFZRUURFeFpEZVdKbGNuUnlkWE4wSUVkc2IySmhiQ0JTYjI5ME1CNFhEVEEyTVRJeE5UQTRNREF3TUZvWERUSXhNVEl4TlRBNE1EQXdNRm93T3pFWU1CWUdBMVVFQ2hNUFEzbGlaWEowY25WemRDd2dTVzVqTVI4d0hRWURWUVFERXhaRGVXSmxjblJ5ZFhOMElFZHNiMkpoYkNCU2IyOTBNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQStNaTh2UlJRWmhQLzhOTjU3Q1B5dHhySGpvWHhFbk9tR2FvUTI1eWlaWFJhZHo1UmZWYjIzQ08yMU8xZldMRTNUZFZKRG03MWFvZlcwb3pTSjhiaS96YWZtR1dnRTA3R0ttU2IxWkFTenhRRzlEdmoxQ2krNkE3NHEwNUlsRzJPbFRFUVhPMmlMYjNWT20yeUhMdGd3RVpMQWZWSnJuNUdpdEIwamFFTUFzN3UvT2VQdUd0bTgzOUVBTDltSlJRcjNSQXdIUWVXUDAzMmE3aVB0M3NNcFRqcjNrZmIxVjA1L0lpbjg5Y3FkUEhvV3FJN24xQzZwb3hGTmNKUVpaWGNZNEx2M2I5M1RaeGl5V056RnRBcEQwbXBTUEN6cXJkc3hhY3dPVUJkcnNUaVhTWlQ4TTRjSXdoaHFKUVp1Z1JpUU93Zk9IQjNFZ1p4cHpBWVhTVW5wUUlEQVFBQm80R2xNSUdpTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlMyQ0hzTmVzeXNJRXlHVmpKZXo2dHVoUzF3VnpBL0JnTlZIUjhFT0RBMk1EU2dNcUF3aGk1b2RIUndPaTh2ZDNkM01pNXdkV0pzYVdNdGRISjFjM1F1WTI5dEwyTnliQzlqZEM5amRISnZiM1F1WTNKc01COEdBMVVkSXdRWU1CYUFGTFlJZXcxNnpLd2dUSVpXTWw3UHEyNkZMWEJYTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFCVzd3b2pvRlJPbFpmSitJbmFSY0hVb3dBbDlCOFRxN2VqaFZocHdqQ3QyQldLTGVQSnpZRmErSE1qV3FkOEJmUDlJanNPMFFiRTJ6Wk1jd1NPNWJBaTVNWHpMcVhaSStPNFRrb2dwMjRDSko4aVlHZDdpeDF5Q2NVeFhPbDVuNEJIUGEyaEN3Y1VQVWYvQTJrYURBdEU1Mk1scDMreXliaDJoTzBqOW4wSHEwViswOSt6dittS3RzMm9vbWNyVXRXM1pmQTVUR09na1htVFVnOVUzWU83bjlHUHAxTnp3OHYvTU94OEJMallSQitUWDNFSklyZHVQdW9jQTA2ZEdpQmgrNEUzN0Y3OENrV3IxK2NYVmRDZzZtQ2JwdmJqakZzcHdnWmdGSjB0bDB5cGt4V2RZY1FCWDBqV1dMMVdNUkpPRWNnaDRMTVJrV1hidEthSU9NNVYiLCJNSUlFRHpDQ0F2ZWdBd0lCQWdJQkFEQU5CZ2txaGtpRzl3MEJBUVVGQURCb01Rc3dDUVlEVlFRR0V3SlZVekVsTUNNR0ExVUVDaE1jVTNSaGNtWnBaV3hrSUZSbFkyaHViMnh2WjJsbGN5d2dTVzVqTGpFeU1EQUdBMVVFQ3hNcFUzUmhjbVpwWld4a0lFTnNZWE56SURJZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt3SGhjTk1EUXdOakk1TVRjek9URTJXaGNOTXpRd05qSTVNVGN6T1RFMldqQm9NUXN3Q1FZRFZRUUdFd0pWVXpFbE1DTUdBMVVFQ2hNY1UzUmhjbVpwWld4a0lGUmxZMmh1YjJ4dloybGxjeXdnU1c1akxqRXlNREFHQTFVRUN4TXBVM1JoY21acFpXeGtJRU5zWVhOeklESWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd2dnRWdNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEUUF3Z2dFSUFvSUJBUUMzTXNqKzZYR21CSVd0REJGazM4NU43OGdER0ljL29hdjdQS2FmOE1PaDJ0VFliaXRUa1Bza3BENkU4SjdvWCt6bEowVDFLS1kvZTk3Z0t2RElyMU12bnNvRkFaTWVqMlljT2FkTitscTJjd1FsWnV0M2YrZFp4a3FaSlJSVTZ5Ykg4MzhaMVRCd2o2K3dSaXIvcmVzcDdkZWZxZ1NIbzlUNWlhVTBYOXREa1lJMjJXWThzYmk1Z3YyY09qNFF5RHZ2Qm1WbWVwc1pHRDMvY1ZFOE1DNWZ2ajEzYzdKZEJtekRJMWFhSzRVbWtoeW5BclBrUHcydkNIbUN1RFk5NnB6VE5iTzhhY3Ixekozby9XU05GNEF6Ymw1S1habkpIb2UwblJyQTFXNFROU05lMzV0ZlBlL1c5M2JDNmo2N2VBMGNRbWRyQk5qNDF0cHZpL0pFb0FHckFnRURvNEhGTUlIQ01CMEdBMVVkRGdRV0JCUy9YN2ZSenQwZmh2UmJWYXpjMXhEQ0RxbUk1ekNCa2dZRFZSMGpCSUdLTUlHSGdCUy9YN2ZSenQwZmh2UmJWYXpjMXhEQ0RxbUk1NkZzcEdvd2FERUxNQWtHQTFVRUJoTUNWVk14SlRBakJnTlZCQW9USEZOMFlYSm1hV1ZzWkNCVVpXTm9ibTlzYjJkcFpYTXNJRWx1WXk0eE1qQXdCZ05WQkFzVEtWTjBZWEptYVdWc1pDQkRiR0Z6Y3lBeUlFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1Z2dFQU1Bd0dBMVVkRXdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUFXZFA0aWQwY2thVmFHc2FmUHpXZHFiQVljYVQxZXBvWGtKS3R2M0w3SWV6TWRlYXRpRGg2R1g3MGsxUG5jR1FWaGl2NDVZdUFwblAreXozU0ZtSDhsVStuTE1QVXhBMklHdmQ1NkRlcnVpeC9VMEY0N1pFVUQwL0N3cVRSVi9wMkpkTGlYVEFBc2dHaDFvK1JlNDlMMkw3U2haM1UwV2l4ZUR5TEpseHkxNnBhcThVNFp0M1Zla3l2Z2dRUXRvOFBUN2RMNVdYWHA1OWZrZGhlTXRsYjcxY1pCRHpJMGZtZ0FLaHlucFZTSllBQ1BxNHhKREtWdEhDTjJNUVdwbEJxamxJYXBCdEpVaGxibDkwVFNyRTlhdHZOemlQVG5OdlQ1MWNLRVlXUVBKSXJTUG5OVmVLdGVsdHRRS2JmaTNRQkZHbWg5NURtSy9ENWZzNEM4ZkY1UT0iLCJNSUlDanpDQ0FoV2dBd0lCQWdJUVhJdVp4VnFVeGRKeFZ0N05pWURNSmpBS0JnZ3Foa2pPUFFRREF6Q0JpREVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrNWxkeUJLWlhKelpYa3hGREFTQmdOVkJBY1RDMHBsY25ObGVTQkRhWFI1TVI0d0hBWURWUVFLRXhWVWFHVWdWVk5GVWxSU1ZWTlVJRTVsZEhkdmNtc3hMakFzQmdOVkJBTVRKVlZUUlZKVWNuVnpkQ0JGUTBNZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt3SGhjTk1UQXdNakF4TURBd01EQXdXaGNOTXpnd01URTRNak0xT1RVNVdqQ0JpREVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrNWxkeUJLWlhKelpYa3hGREFTQmdOVkJBY1RDMHBsY25ObGVTQkRhWFI1TVI0d0hBWURWUVFLRXhWVWFHVWdWVk5GVWxSU1ZWTlVJRTVsZEhkdmNtc3hMakFzQmdOVkJBTVRKVlZUUlZKVWNuVnpkQ0JGUTBNZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBUWFyRlJhcWZsb0krZDYxU1J2VThaYTJFdXJ4dFcyMGVaemNhN2RuTllNWWYzYm9Ja0R1QVVVN0ZmTzdsMC80aUd6enZmVWlubmdvNE4rTFpmUVljVHhtZHdsa1dPcmZ6Q2p0SERpeDZFem5QTy9MbHhUc1YremZUSi9palRqZVhtalFqQkFNQjBHQTFVZERnUVdCQlE2NFFtRzFNOFp3cFoyZEVsMjNPQTF4bU5qbWpBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQXdOb0FEQmxBakEyWjZFV0NOemtsd0JCSFU2KzRXTUJ6enVxUWhGa29KMlVPUUlSZVZ4N0hmcGt1ZTRXUXJPL2lzSUp4T3prc1UwQ01RRHBLbUZIakZKS1MwNFljUGJXUk5adTlZTzZiVmk5Sk5sV1NPcnZ4S0pHZ1locU9rYlJxWnROeVdIYTBWMVhhaGc9IiwiTUlJRFh6Q0NBa2VnQXdJQkFnSUxCQUFBQUFBQklWaFRDS0l3RFFZSktvWklodmNOQVFFTEJRQXdUREVnTUI0R0ExVUVDeE1YUjJ4dlltRnNVMmxuYmlCU2IyOTBJRU5CSUMwZ1VqTXhFekFSQmdOVkJBb1RDa2RzYjJKaGJGTnBaMjR4RXpBUkJnTlZCQU1UQ2tkc2IySmhiRk5wWjI0d0hoY05NRGt3TXpFNE1UQXdNREF3V2hjTk1qa3dNekU0TVRBd01EQXdXakJNTVNBd0hnWURWUVFMRXhkSGJHOWlZV3hUYVdkdUlGSnZiM1FnUTBFZ0xTQlNNekVUTUJFR0ExVUVDaE1LUjJ4dlltRnNVMmxuYmpFVE1CRUdBMVVFQXhNS1IyeHZZbUZzVTJsbmJqQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU13bGRwQjVCbmdpRnZYQWc3YUV5aWllL1FWMkVjV3RpSEw4UmdKRHg3S0tuUVJmSk1zdVMrRmdna2JoVXFzTWdVZHdiTjFrMGV2MUxLTVBnajBNSzY2WDE3WVVoaEI1dXpzVGdIZU1DT0ZKMG1waUx4OWUrcFpvMzRrbmxUaWZCdGMreWNzbVdRMXozckRJNlNZT2d4WEc3MXVMMGdSZ3lrbW1LUFpwTy9iTHlDaVI1WjJLWVZjM3JIUVUzSFRnT3U1eUx5NmMrOUM3di9VOUFPRUdNK2lDSzY1VHBqb1djNHpkUVE0Z09zQzBwNkhwc2srUUxqSmc2VmZMdVFTU2FHamxPQ1pnZGJLZmQvK1JGTyt1SUVuOHJVQVZTTkVDTVdFWlhyaVg3NjEzdDJTYWVyOWZ3UlB2bTJMN0RXemdWR2tXcVFQYWJ1bURrM0YyeG1tRmdoY0NBd0VBQWFOQ01FQXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJL3dTMytvTGtVa3JrMVErbU9haTk3aTNSdThNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJMUU52QVVLcit5QXp2OTVaVVJVbTdsZ0FKUWF5ekU0YUdLQWN6eW12bWRMbTZBQzJ1cEFyVDlmSHhENHEvYzJkS2c4ZEVlM2pncjI1c2J3TXBqak01UmNPTzVMbFhiS3I4RXBic1U4WXQ1Q1JzdVpSais5eFRhR2RXUG9PNHp6VWh3OGxvL3M3YXdsT3F6SkNLNmZCZFJveVYzWHBZS0JvdkhkN05BRGRCaisxRWJkZFRLSmQrODJjRUhoWFhpcGEwMDk1TUo2Uk1HM056ZHZRWG1jSWZlZzdqTFFpdENod3MvenlyVlE0UGtYNDI2OE5YU2I3aExpMThZSXZEUVZFVEk1M085ekpybEFHb21lY3NNeDg2T3lYU2hrRE9PeXlHZU1saEx4UzY3dHRWYjkrRTdnVUpUYjBvMkhMTzAySlFaUjdya3BlRE1kbXp0Y3BIV0Q5ZiIsIk1JSUQzVENDQXNXZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBRENCanpFTE1Ba0dBMVVFQmhNQ1ZWTXhFREFPQmdOVkJBZ1RCMEZ5YVhwdmJtRXhFekFSQmdOVkJBY1RDbE5qYjNSMGMyUmhiR1V4SlRBakJnTlZCQW9USEZOMFlYSm1hV1ZzWkNCVVpXTm9ibTlzYjJkcFpYTXNJRWx1WXk0eE1qQXdCZ05WQkFNVEtWTjBZWEptYVdWc1pDQlNiMjkwSUVObGNuUnBabWxqWVhSbElFRjFkR2h2Y21sMGVTQXRJRWN5TUI0WERUQTVNRGt3TVRBd01EQXdNRm9YRFRNM01USXpNVEl6TlRrMU9Wb3dnWTh4Q3pBSkJnTlZCQVlUQWxWVE1SQXdEZ1lEVlFRSUV3ZEJjbWw2YjI1aE1STXdFUVlEVlFRSEV3cFRZMjkwZEhOa1lXeGxNU1V3SXdZRFZRUUtFeHhUZEdGeVptbGxiR1FnVkdWamFHNXZiRzluYVdWekxDQkpibU11TVRJd01BWURWUVFERXlsVGRHRnlabWxsYkdRZ1VtOXZkQ0JEWlhKMGFXWnBZMkYwWlNCQmRYUm9iM0pwZEhrZ0xTQkhNakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMM3R3UVA4OW8vOEFyRnZXNTlJMloxNTRxSzNBMkZXR01OSHR0ZktQVFV1aVVQM29XbWIzb29hL1JNZ25MUkpkeklwVnYyNTdJemRJdnB5M0NkaGwrNzJXb1RzYmhtNWlTemNoRnZWZFB0clg4V0pwUkJTaVVaVjlMaDFIT1ovNUZTdVMvaFZjbGNDR2ZnWGNWbnJIaWdIZE1XZFNMNXN0UFNrc1BOa04zbVN3T3hHWG4vaGJWTk1ZcS9OSHd0anV6cWQrL3g1QUpoaGRNOG1na0JqODdKeWFoa05tY3JVRG5YTU4vdUxpY0ZaOFdKL1g3TmZaVEQ0cDdkTmRsb2VkbDQwd09pV1ZwbUtzL0IvcE0yOTNESXhmSkhQNEY4UitHdXFTVnpSbVpUUm91TmpXd2wydFZaaTRVdDBIWmJVSnRRSUJGblFtQTRPNXQ3OHcrd2ZrUEVDQXdFQUFhTkNNRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FRWXdIUVlEVlIwT0JCWUVGSHdNTWgrbjJUQi94SDFvbzJLb29jNnJCMXNuTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBUldmb2xUd052bEprN21oK0NoVG5VZGdXVVh1RW9rMjFpWFFuQ29LalVzSFU0OFRScW5lU2Zpb1ltVWVZczBjWXRicFVnU3BJQjdMaUtaM3N4NG1jdWpKVURKaTVEblVveDlnNjFETHUzNGpkL0lyb0FvdzU3VXZ0cnV6dkUwM2xSVHMyUTlHY0hHY2c4Um5vTkFYM0ZXT2R0NW9Vd0Y1b2t4QkRnQlBmZzhuL1VxZ3IvUWgwMzdaVGxaRmtTSUhjNDB6SStPSUYxbG5QNmFJK3h5ODRmeGV6Nm5IN1Bmckh4QnkyMi9ML0twTC9RbHdWS3ZPb1lLQUtRdlZSNENTRngwOUY5SGRrV3NLbGhQZEFLQUNMOHgzdkxDV1JGQ3p0QWdmZDlmREwxbU1wWWpuMHE3cEJaYzJUNU5uUmVKYUgxWmdVdWZ6a1ZxU3I3VUl1T2hXbjAiLCJNSUlGV2pDQ0EwS2dBd0lCQWdJUWJrZXB4VXRIREEzc005Q0p1UnowNFRBTkJna3Foa2lHOXcwQkFRd0ZBREJITVFzd0NRWURWUVFHRXdKVlV6RWlNQ0FHQTFVRUNoTVpSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6SUV4TVF6RVVNQklHQTFVRUF4TUxSMVJUSUZKdmIzUWdVakV3SGhjTk1UWXdOakl5TURBd01EQXdXaGNOTXpZd05qSXlNREF3TURBd1dqQkhNUXN3Q1FZRFZRUUdFd0pWVXpFaU1DQUdBMVVFQ2hNWlIyOXZaMnhsSUZSeWRYTjBJRk5sY25acFkyVnpJRXhNUXpFVU1CSUdBMVVFQXhNTFIxUlRJRkp2YjNRZ1VqRXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFDMkVRS0xIdU9oZDVzNzNMK1VQcmVWcDBBOG9mMkMrWDB5Qm9KeDl2YU1mL3ZvMjd4cUxwZVhvNHhMK1N2MnNmbk9oQjJ4K2NXWDN1KzU4cVBwdkJLSlhxZXFVcXY0SXlmTHBMR2NZOXZYbVg3d0NsN3JhS2IweGxwSERVMFFNK05Pc1JPanlCaHNTK3o4Q1pEZm5XUXBKU01Ib2JUU1BTNWc0TS9TQ1llN3pVandUY0xDZW9pS3U3clBXUm5XcjQrd0I3Q2VNZkdDd2NEZkxxWnRiQmtPdGRoK0pocEZBejJ3ZWFTVUtLMFBmeWJscUFqK2x1ZzhhSlJUN29NNmlDc1ZsZ215NEhxTUxuWFduT3VuVm1TUGxrOW9yajJYd29TUHdMeEF3QXRjdmZhSHN6VnNyQmhRZjRUZ1RNMlMweURwTTd4U21hOHl0U216SlNxMFNQbHk0Y3BrOSthQ0VJM29uY0tLaVBvNFpvcjhZL2tCK1hqOWUxeDMrbmFIK3V6ZnNRNTVsVmUwdlNidjFnSFI2eFlLdTQ0THRjWEZpbFdyMDZ6cWtVc3B6Qm1rTWlWT0t2RmxSTkFDenFyT1NiVHFuM3lEc0VCNzUwT3JwMnlqajMySmdmcE1wZi9WanNQT1MrQzEyTE9PUmM5MndPMUFLLzFURDdDbjFUc05zWXFpQTk0eHJjeDM2bTk3UHRiZmtTSVM1cjc2MkRMOEVHTVVVWExlWGRZV2s3MHBhRFB2T21ic0I0b20zeFBYVjJWNEo5NWVTUlFBb2dCL21xZ2h0cW14bGJDbHVRMFdFZHJIYkVnOFFPQitEVnJOVmp6Umx3VzV5MHZ0T1V1Y3hEL1NWUk51SkxEV2NmcjB3YnJNN1J2MS9vRkIyQUNZUFRySXJucVlOeGdGbFFJREFRQUJvMEl3UURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVNUs4ckpuRWFLMGduaFM5U1ppenY4SWtUY1Q0d0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQkFEaVdDdTQ5dEpZZVgrK2RuQXN6bnl2Z3l2M1NqZ29mUVhTbGZLcUUxT1h5SHVZM1VqS2NDOUZoSGI4b3diWkVLVFYxZDVpeWZObTlkS3lLYU9PcE1Ra3BBV0J6NDBkOFU2aVFTaWZ2UzllZmsrZUNOczZhYUF5QzU4L1VFQlp2WHc2WlhQWWZjWDN2NzNzdmZ1bzIxcGR3Q3hYdTExeFdhak9sNDBrNERMaDkrNDJGcExGWlh2UnE0ZDJoOW1SRXJ1WlJneUZteGhFKzg4NUg3cHdvSHlYYS82eG1sZDAxRDF6dklDeGkvWkc2cWN6OFdweVRnWU1wbDBwOFduSzBPZEMzZDh0NS9XazZramZ0YmpobFJuN3BZTDE1aUpkZk9CTDA3cTliZ3NpRzFlR1piWXdFOG5hNlNmWnU2VzBlWDZEdko0SjJRUGltMDFoY0R5eEMya0xHZTRnMHg4SFlSWnZCUHNWaEhkbGpVRW4yTklWcTRCakZia2VyUVVJcG0vWmdEZEl4MDJPWUk1TmFBSUZJdE8vTmlzM0p6NW51Mlo2cU51Rm9TM0ZKRkRZb09qMGR6cHFQSmVhQWNXRXJ0WHZNK1NVV2dlRXhYNkdqZmhha25CWnFseGk5ZG5LbEM1NGROdVl2b1MrK2NKRVBxT2JhK01TU1FHd2xmbnV6Q2R5eUY2MkFSUEJvcFkrVWRmOTBXdWlvQW53TUNlS3BTd3VnaFF0aXVlK2hNWkw3Ny9aUkJJbHM2S2wwb2JzWHM3WDlTUTk4UE95REdDQkRUdFdUdXJRMHNSOFdOaDhNNW1RNUZremM0UDRkeUtsaVBVRHF5c1UwQXJTdWlZZ3pOZHdzRTNQWUovSFFjdTUxT3lMZW1HaG1XL0hHWTBkVkhMcWxDRkYxcGtnbCIsIk1JSUR4VENDQXEyZ0F3SUJBZ0lRQXF4Y0ptb0xRSnVQQzNueXJrWWxkekFOQmdrcWhraUc5dzBCQVFVRkFEQnNNUXN3Q1FZRFZRUUdFd0pWVXpFVk1CTUdBMVVFQ2hNTVJHbG5hVU5sY25RZ1NXNWpNUmt3RndZRFZRUUxFeEIzZDNjdVpHbG5hV05sY25RdVkyOXRNU3N3S1FZRFZRUURFeUpFYVdkcFEyVnlkQ0JJYVdkb0lFRnpjM1Z5WVc1alpTQkZWaUJTYjI5MElFTkJNQjRYRFRBMk1URXhNREF3TURBd01Gb1hEVE14TVRFeE1EQXdNREF3TUZvd2JERUxNQWtHQTFVRUJoTUNWVk14RlRBVEJnTlZCQW9UREVScFoybERaWEowSUVsdVl6RVpNQmNHQTFVRUN4TVFkM2QzTG1ScFoybGpaWEowTG1OdmJURXJNQ2tHQTFVRUF4TWlSR2xuYVVObGNuUWdTR2xuYUNCQmMzTjFjbUZ1WTJVZ1JWWWdVbTl2ZENCRFFUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1iTTVYUG0rOVM3NVMwdE1xYmY1WUUveWMwbFNiWnhLc1BWbERSbm9nb2NzRjlwcGtDeHhMZXlqOUNZcEtsQldUclQzSlRXUE50ME9LUkt6RTBsZ3ZkS3BWTVNPTzd6U1cxeGtYNWp0cXVtWDhPa2hQaFBZbEcrK01YczJ6aVM0d2JsQ0pFTXhDaEJWZnZMV29rVmZuSG9OYjlOY2drOXZqbzRVRnQzTVJ1TnM4Y2tSWnFuckcwQUZGb0V0N29UNjFFS21FRkJJazVsWVllQlFWQ21lVnlKM2hsS1Y5VXU1bDBjVXl4K21NMGFCaGFrYUhQUU5BUVRYS0Z4MDFwOFZkdGVaT0UzaHpCV0JPVVJ0Q21BRXZGNU9ZaWlBaEY4SjJhM2lMZDQ4c29LcURpckNtVEN2MlpkbFlUQm9TVWVoMTBhVUFzZ0VzeEJ1MjRMVVRpNFM4c0NBd0VBQWFOak1HRXdEZ1lEVlIwUEFRSC9CQVFEQWdHR01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZMRSt3MmtEK0w5SEFkU1lKaG9JQXU5alpDdkRNQjhHQTFVZEl3UVlNQmFBRkxFK3cya0QrTDlIQWRTWUpob0lBdTlqWkN2RE1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQWNHZ2FYM05lY256eUlaZ1lJVnlIYklVZjRLbWVxdnhneWRrQVFWOEdLODNyWkVXV09OZnFlL0VXMW50bE1NVXU0a2VoRExJNnplTTdiNDFONWNkYmxJWlFCMmxXSG1pUms5b3Btek42Y044Mm9OTEZwbXlQSW5uZ2lLM0JENDFWSE1XRVo3MWpGaFM5T01QYWdNUllqeU9maVpSWXp5NzhhRzZBOStNcGVpekdMWUFpSkxRd0dYRkszeFBrS21ORVZYNThTdm53Mll6aTlSS1IvNUNZckNzU1hhUTNwak9MQUVGZTR5SFlTa1ZYeVNHbll2Q29DV3c5RTFDQXgyL1M2Y0NaZGtHQ2V2RXNYQ1MrMHl4NURhTWtISjhIU1hQZnFJYmxvRXB3OG5MK2UvSUJjbTJQTjdFZXFKU2Rub0RmekFJSjlWTmVwK09rdUU2TjM2QjlLIiwiTUlJRHR6Q0NBcCtnQXdJQkFnSVFET2ZnNVJmWVJ2NlA1V0Q4Ry9Bd09UQU5CZ2txaGtpRzl3MEJBUVVGQURCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1EwRXdIaGNOTURZeE1URXdNREF3TURBd1doY05NekV4TVRFd01EQXdNREF3V2pCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDdERoWE81RU9BWExHSDg3ZGcrWEVTcGE3Y0pwU0lxdlRPOVNBNUtGaGdEUGlBMnFrVmxUSmhQTFd4S0lTS2l0eWZDZ3lERjNxUGtLeUs1M2xUWERHRUt2WVBtREkyZHN6ZTNUeW9vdTlxK3lIeVVtSGZueURYSCtLeDJmNFlaTklTVzEvNVdCZzF2RWZOb1RiNWEzL1VzRGcrd1J2RGpEUFoyQzhZL2lnUHM2ZUQxc051Uk1CaE5aWVcvbG1jaTNadDEvR2lTdzByL3d0eTJwNWcwSTZRTmNaNFZZY2dvYy9sYlFySVNYd3htRE5zSXVtSDBESmFvcm9UZ2hIdE9SZWRtVHB5b2ViNnBOblZGekYxcm9WOUlxNC9BVWFHOWloNXlMSGE1RmNYeEg0Y0RyQzBrcVpXczcyeWwrMnFwL0MzeGFnL2xSYlEvNkdXNndoZkdIZFBBZ01CQUFHall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQmhqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUkY2Nkt2OUpMTGdqRXRVWXVucHlHZDgyM0lEekFmQmdOVkhTTUVHREFXZ0JSRjY2S3Y5SkxMZ2pFdFVZdW5weUdkODIzSUR6QU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFvZzY4MytMdDhPTnljM3BrbEwvM2NtYllNdVJDZFdLdWgrdnkxZG5lVnJPZnpNNFVLTGtObDJCY0VreFk1Tk05ZzBsRldKYzFhUnFvUitwV3hubXJFdGhuZ1lUZmZ3azhsT2E0Sml3Z3ZUMnpLSW4zWC84aTRwZUVIK2xsNzRmZzM4Rm5TYk5kNjdJSkt1c203WGkrZlQ4cjg3Y21OVzFmaVFHMlNWdWZBUVdicXowbHdjeTJmOEx4YjRiRyttUm82NEV0bE90Q3QvcU1IdDFpOGI1UVo3ZHN2ZlB4SDJzTU5nY1dmemQ4cVZ0dGV2RVNSbUNEMXljRXZrdk9sNzdEWnlwb0VkK0E1d3d6WnI4VERSUnU4MzhmWXhBZStvMGJKVzFzajZXM1lRR3gwcU1tb1JCeG5hM2l3L25EbVZHM0t3Y0l6aTdtVUxLbitncEZMNkx3OGc9PSIsIk1JSUNDakNDQVpHZ0F3SUJBZ0lRYmtlcHlJdVV0dWk3T3lyWW9yTEJtVEFLQmdncWhrak9QUVFEQXpCSE1Rc3dDUVlEVlFRR0V3SlZVekVpTUNBR0ExVUVDaE1aUjI5dloyeGxJRlJ5ZFhOMElGTmxjblpwWTJWeklFeE1RekVVTUJJR0ExVUVBeE1MUjFSVElGSnZiM1FnVWpRd0hoY05NVFl3TmpJeU1EQXdNREF3V2hjTk16WXdOakl5TURBd01EQXdXakJITVFzd0NRWURWUVFHRXdKVlV6RWlNQ0FHQTFVRUNoTVpSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6SUV4TVF6RVVNQklHQTFVRUF4TUxSMVJUSUZKdmIzUWdValF3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVHpkSE9uYUl0Z3JrTzROY1dCTUh0TFNaMzd3V0hPNXQ1R3ZXdlZZUmcxcmtEZGMvZUprVEJhNnp6dWhYeWlRSFk3cWNhNFI5Z3E1NUtSYW5QcHNYSTVueW1mb3BqVFgxNVlobVVQb1lSbEJ0SGNpOG5IYzhpTWFpL2x4S3ZSSFlxalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCU0FUTmJyZFA5Sk5xUFYyUHkxUHNWcThKUWRqREFLQmdncWhrak9QUVFEQXdObkFEQmtBakJxVUZKMENNUnczSjVRZENIb2pYb2h3MCtXYmhYUklqVmhMZm9JTis0WmJhM2Jzc3g5QnpUMVlCa3N0VFRaYnlBQ01BTnhzYnFqWUF1Rzdab0lhcFZvbitLejRaTmtmRjZUcHQ5NUxZMkY0NVRQSTExeHpQS3dUZGIrbWNpVXFYV2k0dz09IiwiTUlJRmtEQ0NBM2lnQXdJQkFnSVFCWnNiVjU2T0lUTGlPUWU5cDNkMVhEQU5CZ2txaGtpRzl3MEJBUXdGQURCaU1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TRXdId1lEVlFRREV4aEVhV2RwUTJWeWRDQlVjblZ6ZEdWa0lGSnZiM1FnUnpRd0hoY05NVE13T0RBeE1USXdNREF3V2hjTk16Z3dNVEUxTVRJd01EQXdXakJpTVFzd0NRWURWUVFHRXdKVlV6RVZNQk1HQTFVRUNoTU1SR2xuYVVObGNuUWdTVzVqTVJrd0Z3WURWUVFMRXhCM2QzY3VaR2xuYVdObGNuUXVZMjl0TVNFd0h3WURWUVFERXhoRWFXZHBRMlZ5ZENCVWNuVnpkR1ZrSUZKdmIzUWdSelF3Z2dJaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQ0R3QXdnZ0lLQW9JQ0FRQy81cEJ6YU42NzVGMUtQREFpTUdrejdNS25KUzdKSVQzeWl0aFp3dUVwcHoxWXEzYWF6YTU3RzRRTnhEQWY4eHVrT0JiclZzYVhiUjJyc25ueXloSFM1Ri9XQlR4U0QxSWZ4cDRWcFg2K242bFhGbGxWY3E5b2szRENzcnAxbVdwek1wVFJFRVFRTHQrQzh3ZUU1blE3YlhIaUxRd2I3aURWeVNBZFl5a3R6dXhlVHNpVCtDRmhtelRyQmNaZTdGc2F2T3ZKejgyc05FQmZzWHBtN25mSVNLaG1WMWVmVkZpT0RDdTNUNmN3MlZidXludGQ0NjNKVDE3bE5lY3h5OXFUWHR5T2o0RGF0cEdZUUpCNXczakh0ckhFdFdvWU9BTVFqZGpVTjZRdUJYMkk5WUkrRUpGd3ExV0NRVExYMndSekttNlJBWHdoVE5TOHJoc0RkVjE0WnRrNk1VU2FNMEMvQ05kYVNhVEM1cW1nWjkya0o3eWhUem0xRVZnWDl5UmNSbzlrOThGcGlIYVlkajFaWFVKMmg0bVhhWHBJOE9DaUVodG1tblRLM2tzZTV3NWpydWJVNzVLU09wNDkzQURrUlNXSnRwcEVHU3Qrd0pTMDBtRnQ2elBaeGQ5TEJBRE1mUnlWdzQvM0liS3lFYmU3Zi9MVmpIQXNRV0Nxc1dNWVJKVWFkbUorOW9DdysraGtwalBSaVFmaHZiZm1RNlFZdUtaM0FlRVBsQXdoSGJKVUtTV0piT1VPVWxGSGRMNG1yTFpCZGQ1NnJGK05QOG04MDBFUkVsdmxFRkRyTWNYS2NoWWlDZDk4VEhVL1krd2hYOFFnVVd0dnNhdUdpMC9DMWtWZm5TRDhvUjdGd0kraXNYNEtKcG4xNUdrdm1CMHQ5ZG1wc2gzbEd3SURBUUFCbzBJd1FEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCaGpBZEJnTlZIUTRFRmdRVTdOZmpndEp4WFdSTTN5NW5QK2U2bUs0Y0QwOHdEUVlKS29aSWh2Y05BUUVNQlFBRGdnSUJBTHRoMlgycGJMNFh4SkVidzZHaUFJM2paR2dQVnM5M3JuRDUvWnBLbWJuSmVGd01ERi9rNWhRcFZnczJTVjFFWStDdG5KWVlaaHNqRFQxNTZXMXIxbFQ0MGp6QlEwQ3VIVkQxVXZ5UU83dVltV2xyeDhHbnFHaWtKOXlkK1NldU1JVzU5bWROT2o2UFdUa2lVMFRyeUYwRHl1MVFlbjFpSVFxQXlITm0wYUFGWUYvb3BiU25yNmozYlRXY2ZGcUsxcUk0bWZONGkvUk4waUFMM2dUdWpKdEhnWElOd0JReTd6QlpMcTdnY2ZKVzVHcVhiNUpRYlphTmFIcWFzallVZWdieUpMa0pFVkRYQ0xHNGlYcUVJMkZDS2VXanphSWdRZGZSbkdUWjZpYWhpeFRYVEJteVVFRnhQVDlOY0NPR0RFcmNnZExNTXBTRURRZ0pseHhQd081cklIUXcwdUE1TkJDRklSVUJDT2hWTXQ1eFNka29GMUJONXI1TjBYV3MwTXI3UWJoRHBhclR3d1ZFVHl3Mm0rTDY0a1c0STFOc0JtOW5WWDlHdFV3L2JpaGFlU2JTcEtoaWw5SWU0dTFLaTd3Yi9VZEtEZDluWm42eVcwSFFPK1QwTy9RRVkrbnZ3bFFBVWFDS0tzbk9lTXpWNm9jRUdMUE9yMG1Jci9PU21iYXo1bUVQMG9VQTUxQWE1QnVWblJtaHVaeXhtN0VBSHUvUUQwOUNiTWtLdk81RCtqcHhwY2hOSnFVMS9ZbGR2SVZpSFRMU29DdFU3WnBYd2R2NkVNOFp0NHRLRzQ4QnRpZVZVK2kyaVcxYnZHalVJK2lMVWFKVytmQ21nS0RXSHJPOER3OVRkU21xNmhOMzVONk1nU0d0QnhCSEVhMkhQUWZSZGJ6UDgyWisiLCJNSUlGV2pDQ0EwS2dBd0lCQWdJUWJrZXB4bHF6NXlERk1Kby9hRkx5YnpBTkJna3Foa2lHOXcwQkFRd0ZBREJITVFzd0NRWURWUVFHRXdKVlV6RWlNQ0FHQTFVRUNoTVpSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6SUV4TVF6RVVNQklHQTFVRUF4TUxSMVJUSUZKdmIzUWdVakl3SGhjTk1UWXdOakl5TURBd01EQXdXaGNOTXpZd05qSXlNREF3TURBd1dqQkhNUXN3Q1FZRFZRUUdFd0pWVXpFaU1DQUdBMVVFQ2hNWlIyOXZaMnhsSUZSeWRYTjBJRk5sY25acFkyVnpJRXhNUXpFVU1CSUdBMVVFQXhNTFIxUlRJRkp2YjNRZ1VqSXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFETzN2Mm0rK3pzRkRROEJ3WmFiRm4zR1RYZDk4R2RWYXJUelR1a2szTHZDdnB0bmZid2hZQmJvVWhTbnpuRnQrNG9yTy9MZG1nVXVkK3RBV3laSDhRaUhaLytjbmZnTEZ1djVBUy9UM0tnR2pTWTZEbG83SlVsZTNhaDVtbTVoUm05aVl6K3JlMDI2bk84LzRQaXkzM0IwczVLczQwRm5vdEprOS9CVzlCdVh2QXVNQzZDL1BxOHRCY0tTT1dJbThXYmE5Nnd5clFEOE5yMGtMaGxaUGRjVEszb2ZtWmVtZGU0d2o3STBCT2RyZTdrUlh1SlZmZUtIMkpTaEJLendrQ1g0NG9mUjVHbWRGclMrTEZqS0JDNHN3bTRWbmRBb2lhWWVjYiszeVh1UHVXZ2Y5UmhEMUZMUEQrTTJ1RndkTmpDYUtINXdRenBvZUovdTFVOGRnYnVhazdNa29nd1RacTlUd3RJbW9TMW1LUFYrM1BCVjJIZEtGWjFFNjZIanVjTVVRa1FkWWhNdkkzNWV6elVJa2dmS3R6cmE3dEVzY3N6Y1RKR3I2MUs4WXpvZERxczV4b2ljNERTTVBjbFFzY2lPenNTclpZdXhzTjJCNm9ndHpWSlYrbVNTZWgyRm5JeFp5dVdmb3FqeDVSV0lyOXFTMzRCSWJJak10L2tta1J0V1Z0ZDlRQ2dISnZHZUplTmtQK2J5S3EwcnhGUk9WN1orMmV0MVZzUm5US2FHNzNWdWx1bHljc2xhVk5WSjF6Z3lqYkxpR0g3SHJmUXkrNFcrOU9tVE42U3BkVGkzL1VHVk40dW5VdTBrekNxZ2M3ZEd0eFJjdzFQY09ubHRoWWhHWG15NW9rTGRXVEsxYXU4Q2NFWW9mL1VWS0dGUFAwVUpBT3loOU9rdHdJREFRQUJvMEl3UURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVdS8vS2ppT2ZUNW5LMitKb3BxVVZKeGNlMlE0d0RRWUpLb1pJaHZjTkFRRU1CUUFEZ2dJQkFMWnA4S1ozL3A3dUM0R3Q0Y0NweC9rMUhVQ0NxK1lFdE4vTDl4MFBnL0IrRTAyTmpPN2pNeUxET2Z4QTMyNUJTMEpUdmhhSThkSTRYc1JvbVJ5WVVwT001Mmp0RzJwemVnVkFUWDlsTzlaWThjNkRSMkRqLzVlcG5HQjNHRlcxZmdpVHo5RDJQR2NERldFSitZRjU5ZXhUcEovSmp3R0xjOFIzZHR5RG92VU1TUnFvZHQ2U20yVDRzeXpGSjlNSHdBaUFwSmlTNHdHV0Fxb0M3bzg3eGRGdENqTXdjM2k1VDFRV3Z3c0hvYVJjNXN2SlhJU1BEK0FWZHl4K0puN2F4RXZicHhaM0I3RE5kZWh5UXRhVmhKMkdnL0xra00wSlI5U0xBM0RhV3NZRFF2VHRONkx3RzFCVVN3N1loTjRaS0ptQlI2NEpHejlJMGNOdjRyQmdGL1h1SXdLbDJnQmJiWkNyN3FMcEd6dnB4MFFuUlk1cm4vV2toTHgzK1d1WHJENVJSYUlScHN5RjdncG84ajVRT0hva1loNFhJRGR0YWsyM0NadkovS1JZOWJiN25FNFl1NVVDNTZHdG13ZnVObXNrMGptR3daT0RVTktCUnFoZllsY3N1MnhraUFodTd4TlVYOTB0eEdkajA4K0pONytkSVBUN2VvT2JvQjZCQUZEQzVBd2lXVklRN1VOV2h3RDRGRktuSFl1VGpLSk5SbjhueG5HYkpON2syb2FMRFg1cklNSEFudUZsMkdxanB1aUZpem9IQ0J5NjlZOVZtaGgxZnVYc2dXYlJJWE9oTlVRTGdEMWJuRjV2S2hlVzBZTWppR1p0NW9iaWNESXZVaUxueU9kL3hDeGdYUy9EcjU1RkJjT0VBcmY5TEFoU1Q0TGRvL0RVaGdrQyIsIk1JSUNpVENDQWcrZ0F3SUJBZ0lRSDBldnFtSUFjRkJVVEFHZW0yT1pLakFLQmdncWhrak9QUVFEQXpDQmhURUxNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdURWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFQnhNSFUyRnNabTl5WkRFYU1CZ0dBMVVFQ2hNUlEwOU5UMFJQSUVOQklFeHBiV2wwWldReEt6QXBCZ05WQkFNVElrTlBUVTlFVHlCRlEwTWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd0hoY05NRGd3TXpBMk1EQXdNREF3V2hjTk16Z3dNVEU0TWpNMU9UVTVXakNCaFRFTE1Ba0dBMVVFQmhNQ1IwSXhHekFaQmdOVkJBZ1RFa2R5WldGMFpYSWdUV0Z1WTJobGMzUmxjakVRTUE0R0ExVUVCeE1IVTJGc1ptOXlaREVhTUJnR0ExVUVDaE1SUTA5TlQwUlBJRU5CSUV4cGJXbDBaV1F4S3pBcEJnTlZCQU1USWtOUFRVOUVUeUJGUTBNZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBUURSM3N2ZGNtQ0ZZWDdkZVNSRnRTcllwbjFQbElMQnM1QkFIK1g0UW9rUEIwQkJPNDkwbzBKbHd6Z2RlVDYrM2VLS3ZVRFlFczJpeFlqRnEwSmNmUks5Q2hRdFA2SUhHNC9iQzh2Q1ZsYnBWc0xNNW5pd3oySitXb3M3N0xUQnVtalFqQkFNQjBHQTFVZERnUVdCQlIxY2FjWlNCbThuWjNxUVVmZmxNUklkNW5UZVRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQXdOb0FEQmxBakVBN3dOYmVxeTNlQXB5dDRqZi83VkdGQWtLK3FEbWZRakdHb2U5R0toenZTYktZQXlkenBtZnoxd1BNT0crRkRIcUFqQVU5Sk04U2FjemVwQkdSN05qZlJPYlRyZHZHRGVBVS83ZElPQTFtamJSeHdHNTV0emQ4LzhkTERvV1Y5bVNPZFk9IiwiTUlJRFREQ0NBalNnQXdJQkFnSUlkM2NHSnlhcHNYd3dEUVlKS29aSWh2Y05BUUVMQlFBd1JERUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQW9NQzBGbVptbHliVlJ5ZFhOME1SOHdIUVlEVlFRRERCWkJabVpwY20xVWNuVnpkQ0JEYjIxdFpYSmphV0ZzTUI0WERURXdNREV5T1RFME1EWXdObG9YRFRNd01USXpNVEUwTURZd05sb3dSREVMTUFrR0ExVUVCaE1DVlZNeEZEQVNCZ05WQkFvTUMwRm1abWx5YlZSeWRYTjBNUjh3SFFZRFZRUUREQlpCWm1acGNtMVVjblZ6ZENCRGIyMXRaWEpqYVdGc01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBOWh0UFp3Y3JvUlgxQmlMTEh3R3k0M05GQmtSSkxMdEpKUlRXenNPM3F5eFB4a0V5bEZmNkVxZGJEdUtQSHg2R0dhZXF0UzI1WHcyS3dxK0ZOWGt5TGJzY1lqZnlzVnRLUGNyTmNWL3BRcjZVNk1qZStTSklaTWJscThZcmJhMEY4UHJWQzgrYTVmQlFwSXM3UjZValczcDYrRE0vdU8rWmwrTWd3ZFlvaWMrVSs3bEY3ZU5BRnhIVWRQQUxNZUlySm1xYlRGZXVyQ0ErdWtWNkJmTzltMmtWcm4xT0lHUEVOWFk2QndMSk4vM0hSKzdvOFhZZGN4WHlsNlMxeUhwNTJVS3FLMzljL3M0bVQ2Tm1nVFd2UkxwVUhod3dNbVdkNWp5VFhsQk9ldU02MUc3TUd2djUwamV1SkNxclZ3TWlLQTFKZFgrM0tOcDF2NDdqM0E1NU1RSURBUUFCbzBJd1FEQWRCZ05WSFE0RUZnUVVuWlBHVTR0ZXlxOC9ueDRQNVptVnZDVDJsSTh3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FRWXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRmlzOUFRT3pjQU4vd3I5MUxvV1h5bTllMmlaV0VuU3RCMDNUWDhuZlVZR1hVUEdoaTQrYzdJbWZVK1RxYmJFS3BxcklaY1VzZDZNMDZ1SkZkaHJKTlR4RnE3WXBGelVmMUdPN1JnQnNaTmp2Yno0WVlDYW5ySE9RbkRpcVgwR0pYMG5vZjV2N0xNZUpOcmpTMVVhQURzMXREdloxMTB3L1lFVGlmTENCaXZ0WjhTT3lVT3lYR3NWaVFLOFl2eE84clV6cXJKdjB3cWlVT1AyTytndVJNTGJaamlwTTFaSThXMGJNNDBOakQ5Z041M1R5bTErTkg0Tm4zSjJpeHVmY3YxU05VRkZBcFl2SExLYWMwa2hzVWxIUlVlMDcybzBFY2xObXN4WnQ5WUNubHBPWmJXVXJodmZLYkFXOGI4QW5nYzZGMlMxQkxVaklaa0tsVHVYZk84PSIsIk1JSUVBRENDQXVpZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREJqTVFzd0NRWURWUVFHRXdKVlV6RWhNQjhHQTFVRUNoTVlWR2hsSUVkdklFUmhaR1I1SUVkeWIzVndMQ0JKYm1NdU1URXdMd1lEVlFRTEV5aEhieUJFWVdSa2VTQkRiR0Z6Y3lBeUlFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1TUI0WERUQTBNRFl5T1RFM01EWXlNRm9YRFRNME1EWXlPVEUzTURZeU1Gb3dZekVMTUFrR0ExVUVCaE1DVlZNeElUQWZCZ05WQkFvVEdGUm9aU0JIYnlCRVlXUmtlU0JIY205MWNDd2dTVzVqTGpFeE1DOEdBMVVFQ3hNb1IyOGdSR0ZrWkhrZ1EyeGhjM01nTWlCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVENDQVNBd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFTkFEQ0NBUWdDZ2dFQkFONmQxK3BYR0VtaFcrdlhYMGlHNnI3ZC8rVHZaeHowWldpelYzR2dYbmU3N1p0SjZYQ0FQVllZWXdodjJ2TE0wRDkvQWxRaVZCRFlzb0hVd0hVOVMzL0hkOE0rZUtzYUE3VWdheTlxSzdIRmlIN0V1eDZ3d2RoRkoyK3FOMWozaHliWDJDMzJxUmUzSDNJMlRxWVhQMldZa3RzcWJsMmkvb2pnQzk1LzVZMFY0ZXZMT3RYaUVxSVRMZGlPcjE4U1BhQUlCUWkyWEtWbE9BUkZtUjZqWUdCMHhVR2xjbUliWXNVZmIxOGFRcjRDVVdXb3JpTVlhdng0QTZsTmY0REQrcXRhL0tGQXBNb1pGdjZ5eU85ZWN3M3VkNzJhOW5tWXZMRUhaNklWRGQyZ1dNWkVld28rWWloZnVrRUhVMWpQRVg0NGRNWDQvN1Zwa0krRWRPcVhHNjhDQVFPamdjQXdnYjB3SFFZRFZSME9CQllFRk5MRXNOS1IxRXdSY2JOaHl6MmgvdDJvYXRUak1JR05CZ05WSFNNRWdZVXdnWUtBRk5MRXNOS1IxRXdSY2JOaHl6MmgvdDJvYXRUam9XZWtaVEJqTVFzd0NRWURWUVFHRXdKVlV6RWhNQjhHQTFVRUNoTVlWR2hsSUVkdklFUmhaR1I1SUVkeWIzVndMQ0JKYm1NdU1URXdMd1lEVlFRTEV5aEhieUJFWVdSa2VTQkRiR0Z6Y3lBeUlFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1Z2dFQU1Bd0dBMVVkRXdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQURKTDg3TEtQcEg4RXNhaEI0eU9kNkF6QmhSY2tCNFk5d2ltUFFvWitZZUFFVzVwNUpZWE1QODBrV055T083TUhBR2pIWlFvcERIMmVzUlUxL2JsTVZnRG9zek9ZdHVVUlhPMXYwWEpKTFhWZ2dLdEkzbHBqYmkyVGM3UFRNb3pJK2djaUtxZGkwRnVGc2tnNVltZXpUdmFjUGQrbVNZZ0ZGUWxxMjV6aGVhYklaMEtiSUlPcVBqQ0RQb1FIbXlXNzRjTnhBOWhpNjN1Z3l1VitJNlNoSEk1NnlEcWcrMkR6WmR1Q0x6clRpYTJjeXZrMC9aTS9pWng0bUVSZEVyL1Z4cUhEM1ZJTHM5UmFSZWdBaEpobGRYUlFMSVFUTzdFckJCRHBxV2VDdFdWWXBvTno0aUN4VElNNUN1ZlJlWU5ueWljc2JrcVdsZXROdyt2SFgvYnZaOD0iLCJNSUlFUGpDQ0F5YWdBd0lCQWdJRVNsT01LREFOQmdrcWhraUc5dzBCQVFzRkFEQ0J2akVMTUFrR0ExVUVCaE1DVlZNeEZqQVVCZ05WQkFvVERVVnVkSEoxYzNRc0lFbHVZeTR4S0RBbUJnTlZCQXNUSDFObFpTQjNkM2N1Wlc1MGNuVnpkQzV1WlhRdmJHVm5ZV3d0ZEdWeWJYTXhPVEEzQmdOVkJBc1RNQ2hqS1NBeU1EQTVJRVZ1ZEhKMWMzUXNJRWx1WXk0Z0xTQm1iM0lnWVhWMGFHOXlhWHBsWkNCMWMyVWdiMjVzZVRFeU1EQUdBMVVFQXhNcFJXNTBjblZ6ZENCU2IyOTBJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNUlDMGdSekl3SGhjTk1Ea3dOekEzTVRjeU5UVTBXaGNOTXpBeE1qQTNNVGMxTlRVMFdqQ0J2akVMTUFrR0ExVUVCaE1DVlZNeEZqQVVCZ05WQkFvVERVVnVkSEoxYzNRc0lFbHVZeTR4S0RBbUJnTlZCQXNUSDFObFpTQjNkM2N1Wlc1MGNuVnpkQzV1WlhRdmJHVm5ZV3d0ZEdWeWJYTXhPVEEzQmdOVkJBc1RNQ2hqS1NBeU1EQTVJRVZ1ZEhKMWMzUXNJRWx1WXk0Z0xTQm1iM0lnWVhWMGFHOXlhWHBsWkNCMWMyVWdiMjVzZVRFeU1EQUdBMVVFQXhNcFJXNTBjblZ6ZENCU2IyOTBJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNUlDMGdSekl3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQzZoTFp5MjU0TWErS1o2VEFCcDNicU1yaVZRUnJKMm1GT1dITFAvdmFDZWI5ellRWUtwU2ZZczEvVFJVNGNjdFpPTXZKeWlnLzNneG5RYW9DQUFFVWVzTWZubXI4U1Z5Y2NvMmd2Q29lOWFtc09YbVh6SEhmVjFJV05jQ0cwc3pMbmk2TFZoamtDc2JqU1I4N2t5VW5FTzZmZSsxUjlWNzd3Nkc3Q2ViSTZDMVhpVUpnV01oTmNMM2hXd2NLVXMvSmE1Q2VhbnlUWHh1elFteVdDNDh6Q3hFWEZqSmQ2Qm1zcUVaK3BDbTVJTzIvYjFCRVpRdmVQQjcvMVUxK2NQdlFYTE9acHJFNHlUR0ozNnJmbzViczB2Qm1McnB4UjU3ZCt0Vk94TXlMbGJjOXdQQnI2NHB0bnRvUDBqYVd2WWt4TjRGaXNaRFFTQS9pMmpaUmpKS1J4QWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlJxY2laNjBCN3ZmZWM3YVZIVWJJMmZrQkptcXpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWVaOGRsc2EyZVQ4aWpZZlRod01FWUdwcm1pNVppWE1SckVQUjlSUC9qVGtyd1BLOVQzQ01xUy9xRjhRTFZKN1VHNWFZTXp5b3JXS2lBSGFyV1dsdUJoMSt4TGxFalppdkV0Umgyd29aUmtmejYvZGp3VUFGUUtYU3QvUzFtamEvcVloMmlBUlZCQ3VjaDM4YU56eCtMYVVhMk5TSlhzcTlyRDFzMkcydjFmTjJEODA3aURnaW5XeVRtc1E5djRJYlpUK21EMTJxL09XeUZjcTFyY2E4UGRDRTZPb0djckJOT1RKNHZ6NFJuQXVrblpvaDgvQ2JDekI0MjhIY2gwUCt2R09heXNYQ0hNbkhqZjg3RWxnSTVyWTk3SG9zVHZ1RGxzNE1QR21IVkhPa2M4S1QvMUVRckJWVUFkajhCYkdKb1g5MGc1cEoxOXhPZTRwSWI0dEY5Zz09IiwiTUlJRlJqQ0NBeTZnQXdJQkFnSUliWXdVUnJHbUN1NHdEUVlKS29aSWh2Y05BUUVNQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQW9NQzBGbVptbHliVlJ5ZFhOME1Sd3dHZ1lEVlFRRERCTkJabVpwY20xVWNuVnpkQ0JRY21WdGFYVnRNQjRYRFRFd01ERXlPVEUwTVRBek5sb1hEVFF3TVRJek1URTBNVEF6Tmxvd1FURUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQW9NQzBGbVptbHliVlJ5ZFhOME1Sd3dHZ1lEVlFRRERCTkJabVpwY20xVWNuVnpkQ0JRY21WdGFYVnRNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQXhCTGZxVi8rUWQzZDlaK0s0L2FzNFR4NG1yelk4SDk2b0RNcTNJMGdXNjR0YitlVDJUWndhbWpQamxHamhWdG5CS0FRSkc5ZEtJTEJsMWZZU0NrVHR1RytrVTNmaFF4VEdKb2VKS0pQai9DaWhRdkw5Q2wvMHFSWTdpWk55YXFvZTVyWitqamVSRmNWNWZpTXlObEk0ZzBXSngwZXlJT0ZKYmU2cWxWQnpBTWlTeTJSall2bWlhOW14K24vSytrOHJOclNzOFBoYUp5SitIb0FWdDcwVlpWcys3cGszV0tMM3d0M011dGl6Q2FhbTd1cVlvTk10QVo2TU1ncHYrMEdUWmU1SE1ReEs5VmZ2Rk1TRjV5WlZ5bG1kMkVoTVFjdUpVbWRHUEx1OHl0eGpMVzZPUWRKZC96dkxwS1FCWTB0TDNkNzcwTy9OYnVhMlBsenB5enkwRmZ1S0U0bVg0K1FhQWt2dVBqY0J1a3VtajVScDlFaXhBcW5PRWhzcy9uL2ZhdUdWK082MW9WNGQ3cEQ2a2gvOXRpK0kyMGV2OUUyYkZoYzhlNmtHVlFhOVFQU2R1YmhqTDA4czlOSVMrTEkrSCtTcUhaR25FSmxQcVFld1FjRFdrWXR1SmZ6dDlXeVZTSHZ1dHhNQUpmN0ZKVW5NNy9vUTBkRzBnaVpGbUE3bW43UzV1MDQ2dXdCSGp4SVZra0p4MHczQUo2SURzQno0VzltNlhKSE1ENFE1UXNEeVpwQ0FHekZsSDVoeElyZmY0SWFDMW5FV1RKM3M3eGdhVlk1L2JRR2V5eldaRGJadlVqdGhCOStwU0tQS3JoQzlJSzMxRk9RZUU0dEd2MkJiMFRYT3dGMGxrTGdBT0l1YStyRjduS3N1Ny8rNnFxbytOejJzbm1LdG1jQ0F3RUFBYU5DTUVBd0hRWURWUjBPQkJZRUZKM0FaNllNSXRrbTlVV3JwbVZTRVNmWVJheGpNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01BMEdDU3FHU0liM0RRRUJEQVVBQTRJQ0FRQ3pWMDBRWWs0NjVLenF1Qnl2TWlQSXMwbGFVWngyS0kxNXFsZEdGOVgxVXZhM1JPZ0lSTDhZaE5JTGdNM0ZFdjBBVlFWaGgwSGN0U1NlUE1UWXlQdHduaTk0bG9NZ050NThEMmtUaUtWMU5wZ0lwc2Jmck03aldOYTNQdDY2OCtzMFFOaWlnZlY0UHkvVnBmelpvdFJlQkE0WHJmNUI4T1d5Y3ZwRWdqTkM2QzFZOTFhTVlqKzZRckNjREZ4K0xtVW1YRk5QQUxKNGZxRU5tUzJOdUIyT29zU3cvV0RRTUtTT3lBUmlxY1R0TmQ1NmwrME9PRjZTTDVOd3BhbWNiNmQ5RXgxK3hnaElzVjVuNjFFSUplbm1KV3RTS1pHYzBqbHpDRmZlbVFhMFc1MFFCdUhDQUtpNEhFb0NDaFRRd1VISys0dzFJWDJDT1BLcFZKRVpOWk9VYldvNnhiTFF1NG1HaytpYnlRODZwM3E0b2ZCNFJ2cjhOeS9saW9UejMvNEUyYUZvb0M4azRnbVZCdFdWeXVFa2x1dDg5cE1GdSsxejZTM1JkVG5YNXlUYjJFNWZRNCtlMEJRNXYxVndTSmxYTWJTYzdrcVlBNVl3SDJBRzdoc2ovb0ZnSXhwSFlvV2x6QmswZ0crenJCcmpuL0I3U0szVkFkbG50cWx5aytvdFpyV3l1T1E5UExMdlRJenE2d2UvcXpXYVZZYThHS2ExcUY2MGcyeHJhVURUbjl6eHcybHJ1ZUZ0Q2ZUeHFsQjJDbnA5ZWhlaFZaWkNtVEVKM1dBUmpRVXdmdWFPUnRHZEZOckhGK1FGbG96RUpMVWJ6eFFIc2tENG81NUJocndFMEd1V3lDcUFOUDIvN3dhajNWakZoVDArai82ZUtlQzJ1QWxvR1J3WVF3PT0iLCJNSUlEVkRDQ0FqeWdBd0lCQWdJREFqUldNQTBHQ1NxR1NJYjNEUUVCQlFVQU1FSXhDekFKQmdOVkJBWVRBbFZUTVJZd0ZBWURWUVFLRXcxSFpXOVVjblZ6ZENCSmJtTXVNUnN3R1FZRFZRUURFeEpIWlc5VWNuVnpkQ0JIYkc5aVlXd2dRMEV3SGhjTk1ESXdOVEl4TURRd01EQXdXaGNOTWpJd05USXhNRFF3TURBd1dqQkNNUXN3Q1FZRFZRUUdFd0pWVXpFV01CUUdBMVVFQ2hNTlIyVnZWSEoxYzNRZ1NXNWpMakViTUJrR0ExVUVBeE1TUjJWdlZISjFjM1FnUjJ4dlltRnNJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEyc3dZWXpEOTlCY2pHbForVzk4OGJEamtjYmQ0a2RTOG9kaE0rS2hEdGdQcFRTRUhDSWphV0M5bU9TbTlCWGlMblRqb0JiZHFmbkdrNXNSZ3ByRHZnT1NKS0ErZUpkYnRnL090cHBISG1NbENHRFVVbmEyWVJwSXVUOHJ4aDBQQkZwVlhMVkR2aVMyQWVsZXQ4dTVmYTlJQWpia1UrQlFWTmRuQVJxTjdjc2lSdjhsVks4M1FsejZjSm1UTTM4NkRHWEhLVHViVTFYdXBHYzFWM3NqczBsNDRVK1ZjVDR3dC9sQWpOdnhtNXN1T3BEa1pBTGVWQWptUkN3NytPQzdSSFFXYTlrMCtidzhISGE4c0hvOWdPZUw2TmxNVE9kUmVKaXZiUGFnVXZUTHJHQU1vVWdSeDVhc3pQZUU0dXdjMmhHS2NlZW9XTVBSZndDdm9jV3ZrK1FJREFRQUJvMU13VVRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUQWVwaG9qWW43cXdWa0RCRjlxbjFsdU1yTVRqQWZCZ05WSFNNRUdEQVdnQlRBZXBob2pZbjdxd1ZrREJGOXFuMWx1TXJNVGpBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQU5lTXBhdVV2WFZTT0tWQ1VuNWthRk9TUGVDcGlsS0luWjU3UXp4cGVSK25Cc3FUUDNVRWFCVTZiUys1S2IxVlNzeVNoTndyclpIWXFMaXp6L1R0MWtMLzZjZGpIUFRmU3RRV1ZZcm1tM29rOU5uczRkMGlYcktZZ2p5Nm15UXpDc3BsRkFNZk9FVkVpSXVDbDZyWVZTQWxrNmw1UGRQY0ZQc2VLVWd6YkZiUzliWnZseHJGVWFLbmphWkMybXFVUHVMay9JSDJ1U3JXNG5PUWR0cXZtbEtYQng0T3QyL1VuaHc0RWJOWC8zYUJkN1lkU3R5c1ZBcTQ1cG1wMDZkckU1N3hOTkI2cFhFMHpYNUlKTDRobVhYZVh4eDEyRTZuVjVmRVdDUkUxMWF6YkpIRndMSmhXQzlrWHROSGpVU3RlZGVqVjBOeFBOTzNDQldhQW9jdm1Ndz09IiwiTUlJRGxqQ0NBbjZnQXdJQkFnSVFDNU1jT3RZNVorcG5JNy9EcjVyMFN6QU5CZ2txaGtpRzl3MEJBUXNGQURCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1J6SXdIaGNOTVRNd09EQXhNVEl3TURBd1doY05Nemd3TVRFMU1USXdNREF3V2pCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1J6SXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEWjV5Z3ZVajgyY2ttSWt6VHorR29lTVZTQW42MVVRYlZIMzVhbzFLK0FMYmtLejNYOWlhVjlKUHJqSWd3cnZKVVhDek8vR1UxQkJwQUF2UXhORVA0SHRlY2NiaUpWTVdXWHZkTVgwaDVpODl2cWJGQ01QNFFNbHMrM3l3UGd5bTJoRkV3YmlkM3RBTEJTZksrUmJMRTRFOUhwRWdqQUFMQWNLeEhhZDNBMm02N09lWWZjZ25EbUNYUndWV212bzJpZnY5MjJlYlB5blhBcFZmU3IvNVZoODhsQWJ4M1J2cE83MDRncXU1Mi9jbHBXY1RzLzFQUFJDdjRvNzZQdTJabXZBOU9QWUxmeWtxR3h2WW1KSHpETnc2WXVZak91RmdKM1JGcm5nUW84cDBRdWViZy9CTHhjb0lmaEc2OVJqczNzTFByNC9tM3dPbnlxaStSbmxUR05BZ01CQUFHalFqQkFNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdHR01CMEdBMVVkRGdRV0JCVE93MHE1bVZYeXVOdGd2NmwrdlZhMWx6YW4xakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBeXFWVmpPUElRVzVwSjZkMUVlODhoalp2MHAzR2VEZ2RhWmFpa21rdU9HeWJmUVRVaWFXeE1UZUt5U0hNcTJ6Tml4eWExcjlJMGpKbXdZckE4eTg2NzhEajFKR0cwVkRqQTl0emQyOUtPVlB0M2liSHRYMnZLMExSZFdMalNpc0N4MUJMNEduaWxtd09SR1lRUkkrdEJldjRlYXltRytnM05KMVR5V0dxb2xLdlNuQVdoc0k2eUxFVGNEYll6KzcwQ2pUVlcwejlCNXlpdXRrQmNsenpUY0hkRHJFY0RjUmp2cTMwRlB1SjdLSkJEa3pNeUZkQTBHNERxczBNam9tWm1XendQREN2T045dnZLTytLU0FucTNUL0V5SjQzcGRTVlI2RHRWUWdBKzZ1d0U5VzNqZk13MytxQkNlNzAzZTRZdHNYZkp3b0loTnpiTThtOVlvcDV3PT0iLCJNSUlEZFRDQ0FsMmdBd0lCQWdJTEJBQUFBQUFCRlV0YXc1UXdEUVlKS29aSWh2Y05BUUVGQlFBd1Z6RUxNQWtHQTFVRUJoTUNRa1V4R1RBWEJnTlZCQW9URUVkc2IySmhiRk5wWjI0Z2JuWXRjMkV4RURBT0JnTlZCQXNUQjFKdmIzUWdRMEV4R3pBWkJnTlZCQU1URWtkc2IySmhiRk5wWjI0Z1VtOXZkQ0JEUVRBZUZ3MDVPREE1TURFeE1qQXdNREJhRncweU9EQXhNamd4TWpBd01EQmFNRmN4Q3pBSkJnTlZCQVlUQWtKRk1Sa3dGd1lEVlFRS0V4QkhiRzlpWVd4VGFXZHVJRzUyTFhOaE1SQXdEZ1lEVlFRTEV3ZFNiMjkwSUVOQk1Sc3dHUVlEVlFRREV4SkhiRzlpWVd4VGFXZHVJRkp2YjNRZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEYUR1YVpqYzZqNDArS2Z2dnhpNE1sYStwSUgvRXFzTG1WRVFTOThHUFI0bWRtenh6ZHp4dElLKzZOaVk2YXJ5bUFaYXZweHkwU3k2c2NUSEFIb1QwS01NMFZqVS80M2RTTVVCVWM3MUR1eEM3My9PbFM4cEY5NEczVk5UQ09Ya056OGtIcDFXcmpzb2s2VmprNGJ3WThpR2xiS2szRnAxUzRiSW5NbS9rOHl1WDlpZlVTUEpKNGx0YmNkRzZUUkdIUmpjZEdzblVPaHVnWml0VnRiTlY0RnBXaTZjZ0tPT3Z5SkJOUGMxU1RFNFU2Rzd3ZU5MV0xCWXk1ZDR1eDJ4OGdrYXNKVTI2UXpuczNkTGx3UjVFaVVXTVdlYTZ4cmtFbUNNZ1pLOUZHcWtqV1pDclhnelQvTENyQmJCbERTZ2VGNTlOODlpRm83K3J5VXA5L2s1RFBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUmdlMllhUlEyWHlvbFFMMzBFelRTby8vejlTekFOQmdrcWhraUc5dzBCQVFVRkFBT0NBUUVBMW5QbmZFOTIwSTIvN0xxaXZqVEZLREsxZlB4c25Dd3J2UW1lVTc5clhxb1JTTGJsQ0tPenlqMWhUZE5HQ2JNK3c2RGpZMVViOHJydnJUbmhRN2s0bytZdmlpWTc3NkJRVnZuR0N2MDR6Y1FMY0ZHVWw1Z0UzOE5mbE5VVnlSUkJuTVJkZFdRVkRmOVZNT3lHai84Tjd5eTVZMGIycXZ6ZnZHbjlMaEpJWkpyZ2xmQ203eW1QQWJFVnRRd2RwZjVwTEdra2VCNnpweHh4WXU3S3lKZXNGMTJLd3ZoSGhtNHF4Rll4bGRCbmlZVXIrV3ltWFVhZERLcUM1SmxSM1hDMzIxWTlZZVJxNFZ6Vzl2NDkza0hNQjY1alVyOVRVL1FyNmNmOXR2ZUNYNFhTUVJqYmdiTUVITVVmcElCdkZTREozZ3lJQ2gzV1psWGkvRWpKS1NacDRBPT0iLCJNSUlGM2pDQ0E4YWdBd0lCQWdJUUFmMXRNUHlqeWxHb0c3eGtEalVETFRBTkJna3Foa2lHOXcwQkFRd0ZBRENCaURFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDazVsZHlCS1pYSnpaWGt4RkRBU0JnTlZCQWNUQzBwbGNuTmxlU0JEYVhSNU1SNHdIQVlEVlFRS0V4VlVhR1VnVlZORlVsUlNWVk5VSUU1bGRIZHZjbXN4TGpBc0JnTlZCQU1USlZWVFJWSlVjblZ6ZENCU1UwRWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd0hoY05NVEF3TWpBeE1EQXdNREF3V2hjTk16Z3dNVEU0TWpNMU9UVTVXakNCaURFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDazVsZHlCS1pYSnpaWGt4RkRBU0JnTlZCQWNUQzBwbGNuTmxlU0JEYVhSNU1SNHdIQVlEVlFRS0V4VlVhR1VnVlZORlVsUlNWVk5VSUU1bGRIZHZjbXN4TGpBc0JnTlZCQU1USlZWVFJWSlVjblZ6ZENCU1UwRWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUNBRW1VWE5nN0Qyd2l6MEt4WERYYnR6U2ZUVEsxUWcySGlxaUJOQ1Mxa0Nkek9pWi9NUGFuczlzL0IzUEhUc2RaN055Z1JLMGZhT2NhOE9obTBYNmE5ZloyalkwSzJkdktwT3l1UitPSnYwT3dXSUpBSlB1TG9kTWtZdEpIVVltVGJmNk1HOFlnWWFwQWlQTHorRS9DSEZIdjI1QitPMU9SUnhoRm5SZ2hSeTRZVVZEKzhNLzUrYkp6L0ZwMFl2VkdPTmFhblpzaHlaOXNoWnJIVW0zZ0R3RkE2Nk16dzNMeWVUUDZ2QlpZMUgxZGF0Ly9PK1QyM0xMYjJWTjNJNXhJNlRhNU1pcmRjbXJTM0lEM0tmeUkwcm40N2FHWUJST2NCVGtaVG16Tmc5NVMrVXplUWMwUHpNc05UNzl1cS9uUk9hY2RyakdDVDNzVEhETi9oTXE3TWt6dFJlSlZuaSs0OVZ2NE0wR2tQR3cvekpTWnJNMjMzYmtmNmMwUGxmZzZsWnJFcGZES0VZMVdKeEEzQmsxUXdHUk9zMDMwM3ArdGRPbXcxWE50QjF4TGFxVWtMMzlpQWlnbVRZbzYxWnM4bGlNMkV1TEUvcERrUDJRS2U2eEpNbFh6emF3V3BYaGFEekxobjR1Z1RuY3hiZ3ROTXMrMWIvOTdsYzZ3ak95MEF2elZWZEFsSjJFbFlHbitTTnVaUmtnN3pKbjBjVFJlOHlleERKdEMvUVY5QXFVUkU5Sm5uVjRlZVVCOVhWS2crL1hSakw3RlFaUW5tV0VJdVF4cE10UEFsUjFuNkJCNlQxQ1pHU2xDQnN0NitlTGY4WnhYaHlWZUVIZzlqMXVsaXV0WmZWUzdxWE1Zb0NBUWxPYmdPSzZueVRKY2NCejhOVXZYdDd5K0NEd0lEQVFBQm8wSXdRREFkQmdOVkhRNEVGZ1FVVTNtL1dxb3JTczlVZ09IWW04Q2Q4cklEWnNzd0RnWURWUjBQQVFIL0JBUURBZ0VHTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTUJRQURnZ0lCQUZ6VWZBM1A5d0Y5UVpsbERIUEZVcC9MK00rWkJuOGIya01WbjU0Q1ZWZVdGUEZTUENlSGxDanRIem9CTjZKMi9GTlF3SVNieG10T3Vvd2hUNktPVldLUjgya1YyTHlJNDhTcUMvM3ZxT2xMVlNvR0lHMVZlQ2taN2w4d1hFc2tFVlgvSkpwdVhpb3I3Z3RObjMvM0FUaVVGSlZEQnduN1lLbnVIS3NTaktDYVhxZVlhbGx0aXo4SSs4alJSYThZRldTUUVnOXpLQzdGNGlSTy9GanM4UFJGL2lLejZ5K08wdGxGWVFYQmwyK29kbktQaTR3MnI3OE5CYzV4amVhbWJ4OXNwbkZpeGRqUWczSU04V2NSaVF5Y0UweHlOTis4MVhIZnFuSGQ0YmxzakR3U1hXWGF2VmNTdGtOci8rWGVUV1lSVWMrWnJ1d1h0dWh4a1l6ZVNmN2ROWEdpRlNlVUhNOWg0eWE3YjZObkpTRmQ1dDBkQ3k1b0d6dUNyK3lEWjRYVW1GRjBzYm1aZ0luL2YzZ1pYSGxLWUM2U1FLNU1OeW9zeWNkaXlBNWQ5elpieXVBbEpRRzAzUm9IbkhjQVA5RGMxZXc5MVBxN1A4eUYxbTkvcVMzZnVRTDM5WmVhdFRYYXcyZXdoMHFwS0o0amp2OWNKMnZoc0UvekIrNEFMdFJaaDh0U1FaWHE5RWZYN21SQlZYeU5XUUtWM1dLZHdybnVXaWgwaEtXYnQ1REhEQWZmOVlrMmRETFdLTUd3c0F2Z25FekRITmI4NDJtMVIwYUJMNktDcTlOalJIREVqZjh0TTdxdGozdTFjSWl1UGhuUFFDalkvTWlRdTEyWkl2VlM1bGpGSDRneFErNklIZGZHamp4RGFoMm5HTjU5UFJieFl2bktrS2o5IiwiTUlJRHJ6Q0NBcGVnQXdJQkFnSVFDRHZnVnBCQ1JyR2hkV3JKV1pISFNqQU5CZ2txaGtpRzl3MEJBUVVGQURCaE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TQXdIZ1lEVlFRREV4ZEVhV2RwUTJWeWRDQkhiRzlpWVd3Z1VtOXZkQ0JEUVRBZUZ3MHdOakV4TVRBd01EQXdNREJhRncwek1URXhNVEF3TURBd01EQmFNR0V4Q3pBSkJnTlZCQVlUQWxWVE1SVXdFd1lEVlFRS0V3eEVhV2RwUTJWeWRDQkpibU14R1RBWEJnTlZCQXNURUhkM2R5NWthV2RwWTJWeWRDNWpiMjB4SURBZUJnTlZCQU1URjBScFoybERaWEowSUVkc2IySmhiQ0JTYjI5MElFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTRqdmhFWExlcUtUVG8xZXFVS0tQQzNlUXlhS2w3aExPbGxzQkNTRE1BWk9uVGpDM1UvZER4R2tBVjUzaWpTTGRod1pBQUlFSnpzNGJnNy9melR0eFJ1TFdac2NGczNZbkZvOTduaDZWZmU2M1NLTUkydGF2ZWd3NUJtVi9TbDBmdkJmNHE3N3VLTmQwZjNwNG1WbUZhRzVjSXpKTHYwN0E2RnB0NDNDL2R4Qy8vQUgyaGRtb1JCQllNcWwxR05YUm9yNUg0aWRxOUpveitFa0lZSXZVWDdRNmhMK2hxa3BNZlQ3UFQxOXNkbDZnU3plUm50d2k1bTNPRkJxT2Fzdit6Yk1VWkJmSFd5bWVNci95N3ZyVEMwTFVxN2RCTXRvTTFPLzRnZFc3alZnL3RSdm9TU2lpY05veEJOMzNzaGJ5VEFwT0I2anRTajFldFgramtNT3ZKd0lEQVFBQm8yTXdZVEFPQmdOVkhROEJBZjhFQkFNQ0FZWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVBOTVRTlZiUlRMdG04S1BpR3h2RGw3STkwVlV3SHdZRFZSMGpCQmd3Rm9BVUE5NVFOVmJSVEx0bThLUGlHeHZEbDdJOTBWVXdEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBTXVjTjZwSUV4SUsrdDFFbkU5U3NQVGZyZ1QxZVhrSW95UVkvRXNyaE1BdHVkWEgvdlRCSDFqTHVHMmNlblRubUNtckViWGpjS0NoelV5SW1aT01rWERpcXc4Y3ZwT3AvMlBWNUFkZzA2Ty9uVnNKOGRXTzQxUDBqbVA2UDZmYnRHYmZZbWJXMFc1QmpmSXR0ZXAzU3ArZFdPSXJXY0JBSSswdEtJSkZQbmxVa2lhWTRJQklxRGZ2OE5aNVlCYmVyT2dPelc2c1JCYzRMMG5hNFVVK0tyazJVODg2VUFiM0x1akVWMGxzWVNFWTFRU3RlRHdzT29CcnArdXZGUlRwMkluQnVUaHM0cEZzaXY5a3VYY2xWekRBR3lTajRkenAzMGQ4dGJRa0NBVXc3QzI5Qzc5RnYxQzVxZlBybUFFU3JjaUl4cGcwWDQwS1BNYnAxWldWYmQ0PSIsIk1JSUMrVENDQW9DZ0F3SUJBZ0lOQUthTGVTa0FBQUFBVU5DUitUQUtCZ2dxaGtqT1BRUURBekNCdnpFTE1Ba0dBMVVFQmhNQ1ZWTXhGakFVQmdOVkJBb1REVVZ1ZEhKMWMzUXNJRWx1WXk0eEtEQW1CZ05WQkFzVEgxTmxaU0IzZDNjdVpXNTBjblZ6ZEM1dVpYUXZiR1ZuWVd3dGRHVnliWE14T1RBM0JnTlZCQXNUTUNoaktTQXlNREV5SUVWdWRISjFjM1FzSUVsdVl5NGdMU0JtYjNJZ1lYVjBhRzl5YVhwbFpDQjFjMlVnYjI1c2VURXpNREVHQTFVRUF4TXFSVzUwY25WemRDQlNiMjkwSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVJQzBnUlVNeE1CNFhEVEV5TVRJeE9ERTFNalV6TmxvWERUTTNNVEl4T0RFMU5UVXpObG93Z2I4eEN6QUpCZ05WQkFZVEFsVlRNUll3RkFZRFZRUUtFdzFGYm5SeWRYTjBMQ0JKYm1NdU1TZ3dKZ1lEVlFRTEV4OVRaV1VnZDNkM0xtVnVkSEoxYzNRdWJtVjBMMnhsWjJGc0xYUmxjbTF6TVRrd053WURWUVFMRXpBb1l5a2dNakF4TWlCRmJuUnlkWE4wTENCSmJtTXVJQzBnWm05eUlHRjFkR2h2Y21sNlpXUWdkWE5sSUc5dWJIa3hNekF4QmdOVkJBTVRLa1Z1ZEhKMWMzUWdVbTl2ZENCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlU0F0SUVWRE1UQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQklRVHlkQzZiVUY3NG16UTYxVmZaZ0lhSlBSYmlXbEg0N2pDZmZIeUFzV2ZvUFpiMVlzR0dZWlBVeEJ0QnlRbm9hRDQxVWNaWVV4OXlwTW42blFNNzIrV0NmNWo3SEJkTnExbmQ2N0puWHhWUkRxaVkxRWY5ZU5pMUtsSEJ6N01JS05DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkxkajV4cmRqZWtJcGxXRHBPQnFVRUZsRVVKSk1Bb0dDQ3FHU000OUJBTURBMmNBTUdRQ01HRjUyT1ZDUjk4Y3JsT1pGN1p2SEgzaHZ4R1UwUU9JZGVTTmlhU0tkMGJlYldIdkF2WDd0ZC9NL2s3Ly9xbm1wd0l3VzVuWGhUY0d0WHNJL2VzbmkwcVUrZUg2cDQ0bUNPaDhrbWh0Yzlodkpxd2hBcmladHlaQld5VmdydEJJR3U0RyIsIk1JSUYyRENDQThDZ0F3SUJBZ0lRVEtyNXl0dGpiK0FmOTA3WVd3T0duVEFOQmdrcWhraUc5dzBCQVF3RkFEQ0JoVEVMTUFrR0ExVUVCaE1DUjBJeEd6QVpCZ05WQkFnVEVrZHlaV0YwWlhJZ1RXRnVZMmhsYzNSbGNqRVFNQTRHQTFVRUJ4TUhVMkZzWm05eVpERWFNQmdHQTFVRUNoTVJRMDlOVDBSUElFTkJJRXhwYldsMFpXUXhLekFwQmdOVkJBTVRJa05QVFU5RVR5QlNVMEVnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3dIaGNOTVRBd01URTVNREF3TURBd1doY05Nemd3TVRFNE1qTTFPVFU1V2pDQmhURUxNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdURWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFQnhNSFUyRnNabTl5WkRFYU1CZ0dBMVVFQ2hNUlEwOU5UMFJQSUVOQklFeHBiV2wwWldReEt6QXBCZ05WQkFNVElrTlBUVTlFVHlCU1UwRWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhrd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUNSNkZTUzBncFdzYXdOSk4zRnowUm5kSmtyTjZOOUkzQUFjYnhUMzhUNktoS1BTMzhRVnIyZmNISzNZWC9KU3c4WHB6M2pzQVJoN3Y4Umw4ZjBoajRLK2o1YytaUG1OSHJaRkd2bm5MT0ZvSUo2ZHE5eGtOZnMvUTM2bkd6NjM3Q0M5QlIrK2I3RXBpOVBmNWwvdGZ4blEzSzlEQURXaWV0ckxOUHRqNWdjRkt0KzVlTnUvTmlvNUpJazJrTnJZcmhWL2VyQnZHeTJpL01Palpya20yeHBtZmg0U0RCRjFhM2hEVHhGWVB3eWxsRW52R2ZEeWk2MmErcEd4OGNnb0xFZlpkNUlDTHFrVHFueWcwWTNoT3ZveklGSVEyZE9jaXFiWEwxTUd5aUtYQ0o3dEt1WTJlN2dVWVBEQ1VaT2JUNlorcFVYMm53elYwRThqVkh0QzdaY3J5eGpHdDlYeUQrODZWM0VtNjlGbWVLaldpUzB1cWxXUGM5dnF2OUpXTDd3cVAvMHVLM3BOL3U2dVBRTE92bm9RMEllaWRpRXl4UHgyYnZoaVdDNGpDaFdyQlFkbkFybmNldlBEdDA5cVphaFNMMDg5NisxRFNKTXdCR0I3Rlk3OXRPaTRsdTNzZ1FpVXBXQWsybm9qa3hsOFpFRExYQjBBdXFMWnhVcGFWSUN1OWZmVUdwVlJyK2dveWhoZjNEUXc2S3FMQ0dxUjg0b25BWkZkcitDR0NlMDFhNjB5MURtYS9STWhuRXc2YWJmRm9iZzJQOUEzZnZRUW9oL296TTZMbHdlUVJHQlk4NFljV3NyN0thS3R6RmNPbXBINE1ONVdkWWdHcS95YXBpcWNyeFhTdEpMbmJzUS9MQk1RZVh0SFQxZUtKMmN6TCt6VWRxblIrV0VVd0lEQVFBQm8wSXdRREFkQmdOVkhRNEVGZ1FVdTY5K0FqMzZwdkU4aEk2dDdqaVk3Tmt5TXRRd0RnWURWUjBQQVFIL0JBUURBZ0VHTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTUJRQURnZ0lCQUFyeDFVYUV0NjVSdTJ5eVRVRVVBSk5Nbk12bHdGVFBvQ1dPQXZuOXNLSU45U0NZUEJNdHJGYWlzTlorRVpMcExycWVMcHB5c2IwWlJHeGhOYUthdEJZU2FWcU00ZGMrcEJyb0x3UDBybUVkRUJzcXBJdDZ4ZjRGcHVIQTFzaitucTZQSzdvOW1malljd2xZUm02bW5QVFhKOU9WMmplRGNoelRjK0NpUjVrRE9GM1ZTWGtBS1J6SDdKc2dIQWNrYVZkNHNqbjhPb1NndFp4OGpiOHVrMkludHpuYUZ4aXV2VHdKYVArRW16elYxZ3NENDFlZUZQZlI2MC9JdlljanQ3WkpRM21GWExycmtndWh4dWhvcUV3V3NScVpDdWhUTEpLN29Ra1lkUXhscUh2TEk3Y2F3aWlGd3h2LzBDdGk3NlI3Q1pHWVo0d1VBYzFvQm1waklYVURnSWlLYm9IR2hmS3BwQzNuOUtVa0VFZUR5czMwalhsWXNRYWI1eG9xMlowQjE1Ujk3UU5LeXZEYjZLa0JQdlZXbWNrZWprazl1K1VKdWVCUFNaSTlGb0pBek14Wnh1WTY3Ukl1YVR4c2xiSDlxaDE3ZjRhK0hnNHlSdnY3RTQ5MWYweUxTMFpqL2dBMFFIREJ3N21oM2FadzRnU3pRYnpwZ0pIcVpKeDY0U0lEcVp4dWJ3NWxUMnlIaDE3emJxRDVkYVdiUU9oVHNpZWRTcm5BZHlHTi80ZnkzcnlNN3hmZnQwa0wwZkp1TUFzYURrNTI3Ukg4OWVsV3NuMi94MjBLazR5bDBNQzJIYjQ2VHBTaTEyNXNDOEtLZlBvZzg4VGs1YzBOcU11UmtyRjhoZXkxRkdsbURvTG56YzdJTGFaUmZ5SEJOVk9GQmtwZG42MjdHMTkwIiwiTUlJQi9qQ0NBWVdnQXdJQkFnSUlkSmNsaXNjL2VsUXdDZ1lJS29aSXpqMEVBd013UlRFTE1Ba0dBMVVFQmhNQ1ZWTXhGREFTQmdOVkJBb01DMEZtWm1seWJWUnlkWE4wTVNBd0hnWURWUVFEREJkQlptWnBjbTFVY25WemRDQlFjbVZ0YVhWdElFVkRRekFlRncweE1EQXhNamt4TkRJd01qUmFGdzAwTURFeU16RXhOREl3TWpSYU1FVXhDekFKQmdOVkJBWVRBbFZUTVJRd0VnWURWUVFLREF0QlptWnBjbTFVY25WemRERWdNQjRHQTFVRUF3d1hRV1ptYVhKdFZISjFjM1FnVUhKbGJXbDFiU0JGUTBNd2RqQVFCZ2NxaGtqT1BRSUJCZ1VyZ1FRQUlnTmlBQVFOTUY0YkZaMEQwS0Y1TmJjNlBKSjZ5aFVjeldMem5DWmNCejNsVlBxajFzd1M2dlFVWCtpT0dhc3ZMa2ptckJoRGVLelFOOE85c3MwczVrZmlHdVpqdUQwdUwzakVUOXYwRDZSb1RGVnlhNVVkVGhoQ2xYak1OenlSNHB0bEt5bWpRakJBTUIwR0ExVWREZ1FXQkJTYXJ5bDZ3QkUxTlNaUk1BRERhdjVBMWE3V1BEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCQmpBS0JnZ3Foa2pPUFFRREF3Tm5BREJrQWpBWENmT0hpRkJhcjhqQVFyOUhYL1ZzYW9iZ3hDZDA1RGhUMXdWL0d6VGp4aSt6eWdrOE41M1g1N2hHOGYyaDRuRUNNRUpaaDBQVVVkKzYwd2t5V3M2SWZsYzluRjlDYS9VSExiWHdncFA1V1crdVpQcFk1WXNlNDJPK3RZSE5id0tNZVE9PSIsIk1JSUVNakNDQXhxZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREI3TVFzd0NRWURWUVFHRXdKSFFqRWJNQmtHQTFVRUNBd1NSM0psWVhSbGNpQk5ZVzVqYUdWemRHVnlNUkF3RGdZRFZRUUhEQWRUWVd4bWIzSmtNUm93R0FZRFZRUUtEQkZEYjIxdlpHOGdRMEVnVEdsdGFYUmxaREVoTUI4R0ExVUVBd3dZUVVGQklFTmxjblJwWm1sallYUmxJRk5sY25acFkyVnpNQjRYRFRBME1ERXdNVEF3TURBd01Gb1hEVEk0TVRJek1USXpOVGsxT1Zvd2V6RUxNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdNRWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFQnd3SFUyRnNabTl5WkRFYU1CZ0dBMVVFQ2d3UlEyOXRiMlJ2SUVOQklFeHBiV2wwWldReElUQWZCZ05WQkFNTUdFRkJRU0JEWlhKMGFXWnBZMkYwWlNCVFpYSjJhV05sY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDVBbmZSdTRlcDJoeHhOUlVTT3ZrYklnd2Fkd1NyK0dCK081QUw2ODZ0ZFVJb1dNUXVhQnRERmNDTE5TUzFVWTh5MmJtaEdDMVBxeTB3a3dMeHlUdXJ4RmE3MFZKb1NDc042c2pOZzR0cUpWZk1pV1BQZTNNL3ZnNGFpakpSUG4yanltSkJHaENmSGRyL2p6RFVzaTE0SFpHV0N3RWl3cUpINVlaOTJJRkNva2NkbXRldDRZZ05XOElvYUUrb3hveDZnbWYwNDl2WW5NbGh2Qi9WcnVQc1VLNiszcXN6V1kxOXpqTm9GbWFnNHFNc1hlRFpSck9tZTlIZzZqYzhQMlVMaW1BeXJMNThPQWQ3dm41bEo4UzNmckhSTkc1aTFSOFhsS2RINWtCakhZcHkrZzhjbWV6NktKY2ZBM1ozbU5XZ1FJSjJQMk43U3c0U2NEVjdvTDhrQ0F3RUFBYU9Cd0RDQnZUQWRCZ05WSFE0RUZnUVVvQkVLSXo2VzhRZnM0cThwNzRLbGY5QXdwTFF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdld1lEVlIwZkJIUXdjakE0b0RhZ05JWXlhSFIwY0RvdkwyTnliQzVqYjIxdlpHOWpZUzVqYjIwdlFVRkJRMlZ5ZEdsbWFXTmhkR1ZUWlhKMmFXTmxjeTVqY213d05xQTBvREtHTUdoMGRIQTZMeTlqY213dVkyOXRiMlJ2TG01bGRDOUJRVUZEWlhKMGFXWnBZMkYwWlZObGNuWnBZMlZ6TG1OeWJEQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFDRmI4QXZDYjZQK2srdFo3eGtTQXprL0V4ZllBV015bXRyd1VTV2dFZHVqbTdsM3NBZzlnMW8xUUdFOG1UZ0hqNXJDbDdyKzhkRlJCdi8zOEVyakhUMXIwaVdBRmYyQzNCVXJ6OXZIQ3Y4UzVkSWEyTFgxcnpOTHpSdDB2eHVCcXc4TTBBeXg5bHQxYXdnNm5DcG5CQll1ckRDL3pYRHJQYkRkVkNZZmVVMEJzV08vOHRxdGxiZ1QyRzl3ODRGb1Z4cDdaOFZsSU1DRmxBMnpzNlNGejdKc0RvZUEzcmFBVkdJLzZ1Z0xPcHl5cEVCTXMxT1VJSnFzaWwyRDRrRjUwMUtLYVU3M3lxV2pnb203QzEyeXhvdytldit0bzUxYnlydkxqS3pnNkNZRzFhNFhYdmkzdFB4cTNzbVBpOVdJc2d0UnFBRUZROFRtRG41WHBOcGFZYmc9PSIsIk1JSUNSakNDQWMyZ0F3SUJBZ0lRQzZGYStoM2ZvTFZKUksvTkpLQnM3REFLQmdncWhrak9QUVFEQXpCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1J6TXdIaGNOTVRNd09EQXhNVEl3TURBd1doY05Nemd3TVRFMU1USXdNREF3V2pCbE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TUXdJZ1lEVlFRREV4dEVhV2RwUTJWeWRDQkJjM04xY21Wa0lFbEVJRkp2YjNRZ1J6TXdkakFRQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRWjU3eXNSR1h0emJnL1dQdU5zVmVwUkMwRkZmTHZDLzhRZEorMVlsSmZabjRmNWR3YlJYa0x6TVpUQ3AyTlhRTFpxVm5lQWxyMmxTb09qVGhLaWtuR3ZNWURPQWRmVmRwK0NXN2lmMTdRUlNBUFdYWVExcUFrOEMzZU52SnNLVG1qUWpCQU1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0dHTUIwR0ExVWREZ1FXQkJUTDBMMnA0WmdGVWFGTk42S0RlYzZOSFNya2hEQUtCZ2dxaGtqT1BRUURBd05uQURCa0FqQWxwSUZGQW1zU1MzVjBUOGdqNDNEeWRYTGVmSW53ejVGeVlaNWVFSkpaVnJtRHh4RG5PT2xZSmpaOTFlUTBoamtDTUh3MlUvQXc1V0pqT3BuaXRxTTdtelQ2SHRvUWtuRmVrUk9uM2FSdWtzd3kxdlVoWnNjdjZwWmphbVZGa3BVQnRBPT0iLCJNSUlFS2pDQ0F4S2dBd0lCQWdJRU9HUGUrREFOQmdrcWhraUc5dzBCQVFVRkFEQ0J0REVVTUJJR0ExVUVDaE1MUlc1MGNuVnpkQzV1WlhReFFEQStCZ05WQkFzVU4zZDNkeTVsYm5SeWRYTjBMbTVsZEM5RFVGTmZNakEwT0NCcGJtTnZjbkF1SUdKNUlISmxaaTRnS0d4cGJXbDBjeUJzYVdGaUxpa3hKVEFqQmdOVkJBc1RIQ2hqS1NBeE9UazVJRVZ1ZEhKMWMzUXVibVYwSUV4cGJXbDBaV1F4TXpBeEJnTlZCQU1US2tWdWRISjFjM1F1Ym1WMElFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1SUNneU1EUTRLVEFlRncwNU9URXlNalF4TnpVd05URmFGdzB5T1RBM01qUXhOREUxTVRKYU1JRzBNUlF3RWdZRFZRUUtFd3RGYm5SeWRYTjBMbTVsZERGQU1ENEdBMVVFQ3hRM2QzZDNMbVZ1ZEhKMWMzUXVibVYwTDBOUVUxOHlNRFE0SUdsdVkyOXljQzRnWW5rZ2NtVm1MaUFvYkdsdGFYUnpJR3hwWVdJdUtURWxNQ01HQTFVRUN4TWNLR01wSURFNU9Ua2dSVzUwY25WemRDNXVaWFFnVEdsdGFYUmxaREV6TURFR0ExVUVBeE1xUlc1MGNuVnpkQzV1WlhRZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGtnS0RJd05EZ3BNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXJVMUxxUktHc3VxaklBY1ZGbVFxSzB2UnZ3dEtUWTd0Z0hhbFo3ZDRRTUJ6UXNob3dOdFRLOTFldUhhWU5aT0xHcDE4RXpvT0gxdTNIcy9sSkJRZXNZR3BqWDI0ekd0TEEvRUNETnlycFVBa0FIOTBsS0dkQ0NtemlBdjFoM2VkVmMza3czN1hhbVNyaFJTR2xWdVhNbEJ2UGNpNlpnemovTDI0U2NGMmlVa1ovY0Nvdlltalp5L0duN3h4R1dDNExla3N5WkIyWm51VTRxOTQxbVZUWFR6V25MTFBLUVA1TDZSUXN0Ukl6Z1V5VllyOXNtUk1EdVNZQjNYYmY5KzVDRlZnaFRBcCtYdElwR21HNHpVL0hvWmRlbm9WdmU4QWpoVWlWQmNBa0NhVHZBNUphSkcvK0VmVG5aVkN3UTVOMzI4bXo4TVlJV0ptUTNEVzFjQUg0UUlEQVFBQm8wSXdRREFPQmdOVkhROEJBZjhFQkFNQ0FRWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVWZVNCMFJHQXZ0aUp1UWlqTWZtaEpBa1d1WEF3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUR1YmoxYWJNT2RUbVh4NmVhZE5sOWNabFpEN0JoL0tNM3hHWTQrV1ppVDZRQnNoSjhybWNuUHlULzR4bWYzSURFeG9VOGFBZ2hPWStyYXQybDA5OGM1dTloVVJsSUlNN2orVnJ4R3JEOWN2M2g4RGoxY3NIc203bWhwRWxlc1lUNllmelgxWEVDK2JCQWxhaExWdTJCMDY0ZGFlMFd4NVhua2NGTVhqMEV5VE8yVTg3ZDg5dnFibGxSckR0Um5EdlY1YnUvOGo3MmdaeXhLVEoxd0RMVzh3MEI2MkdxemVXdmZScXFnbnB2NTVnY1I1bVROWHVoS3dxZUJDYkpQS1Z0NytiWVFMQ0l0K2plclhtQ0hHOCtjOGVTOWVuTkZNRlkzaDdDSTN6SnBEQzVmY2dKQ05zMmViYjBnSUZWYlB2L0VyZkY2YWR1bFprTVY4Z3pVUlpWRT0iLCJNSUlDSGpDQ0FhU2dBd0lCQWdJUllGbEo0Q1l1dTFYNUNuZUtjZmxLMkd3d0NnWUlLb1pJemowRUF3TXdVREVrTUNJR0ExVUVDeE1iUjJ4dlltRnNVMmxuYmlCRlEwTWdVbTl2ZENCRFFTQXRJRkkxTVJNd0VRWURWUVFLRXdwSGJHOWlZV3hUYVdkdU1STXdFUVlEVlFRREV3cEhiRzlpWVd4VGFXZHVNQjRYRFRFeU1URXhNekF3TURBd01Gb1hEVE00TURFeE9UQXpNVFF3TjFvd1VERWtNQ0lHQTFVRUN4TWJSMnh2WW1Gc1UybG5iaUJGUTBNZ1VtOXZkQ0JEUVNBdElGSTFNUk13RVFZRFZRUUtFd3BIYkc5aVlXeFRhV2R1TVJNd0VRWURWUVFERXdwSGJHOWlZV3hUYVdkdU1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFUjBVT2x2dDlYYi9wT2RFaCtKOEx0dFY3SHBJNlNGa2M4R0l4TGNCNktQNGFwMXl6dHN5WDUwWFVXUHJSZDIxRG9zQ0haVFFLSDNyZDZ6d3pvY1dkVGFSdlFaVTRmOGtlaE92Um5rbVNoNVNIRERxRlNtYWZuVm1UVFpkaEJvWktvMEl3UURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVUGVZcFNKdnFCOG9oUkVvbTNtN2Uwb1BRbjFrd0NnWUlLb1pJemowRUF3TURhQUF3WlFJeEFPVnBFc2x1MjhZeHVnbEI0WmY0Ky8yYTRuMFN5ZTE4Wk5QTEJTV0xWdG1nNTE1ZFRndURuRnQyS2FBSkppRnFZZ0l3Y2RLMWoxenFPK0Y0Q1lXb2RaSTd5Rno5U084TmRDS29DT0p1eFVuT3h3eThwMkZwOGZjNzRTckwrU3Z6WnBBMyIsIk1JSUZnekNDQTJ1Z0F3SUJBZ0lPUmVhN0E0TXp3NFZsU09iL1JWRXdEUVlKS29aSWh2Y05BUUVNQlFBd1RERWdNQjRHQTFVRUN4TVhSMnh2WW1Gc1UybG5iaUJTYjI5MElFTkJJQzBnVWpZeEV6QVJCZ05WQkFvVENrZHNiMkpoYkZOcFoyNHhFekFSQmdOVkJBTVRDa2RzYjJKaGJGTnBaMjR3SGhjTk1UUXhNakV3TURBd01EQXdXaGNOTXpReE1qRXdNREF3TURBd1dqQk1NU0F3SGdZRFZRUUxFeGRIYkc5aVlXeFRhV2R1SUZKdmIzUWdRMEVnTFNCU05qRVRNQkVHQTFVRUNoTUtSMnh2WW1Gc1UybG5iakVUTUJFR0ExVUVBeE1LUjJ4dlltRnNVMmxuYmpDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSlVINkhQS1p2bnNGTXA3UFBjTkNQRzBSUXNzZ3JSSXh1dGJQSzZEdUVHU014U2tiMy9wS3N6R3NJaHJ4YmFKMGNheS94VE9VUlFoN0VyZEcxckcxb2Z1VFRvVkJ1MWtaZ3VTZ01wRTNuT1VUdk9uaVg5UGVHTUl5QkpRYlVKbUwwMjVlU2hOVWhxS0dvQzNHWUVPZnNTS3ZHUk1JUnhEYU5jOVBJckZzbWJWa0pxM01RYkZ2dUp0TWdhbUh2bTU2NnFqdUwrK2dtTlEwUEFZaWQva0QzbjE2cUlmS3RKd0xudm52Sk83YlZQaVNIeU1FQWM0LzJheWQyRis0T3FNUEtxMHBQYnpsVW9TQjIzOWpMS0p6OUNnWVhmSVdIU3cxQ002OTEwNnlxTGJuUW5lWFVRdGtQR0J6VmVTK242OFVBUmpOTjlya3hpK2F6YXlPZVNzSkRhMzhPKzJIQk5YazdiZXN2amloYmR6b3JnMXFrWHk0SjAyb1c5VWl2RnlWbTR1aU1WUlFrUVZsTzZqeFRpV20wNU9XZ3RIOHdZMlNYY3d2SEUzNWFic0lRaDEvT1poRmo5MzFkbVJsNFFLYk5RQ1RYVEFGTzM5T2Z1RDhsNFVvUVN3QytuKzdvL2hiZ3V5Q0xOaFpnbHFzUVk2WlpaWndQQTEvY25hS0kwYUVZZHdnUXFvbW5VZG5qcUdCUUNlMjREV0pmbmNCWjRuV1V4Mk9WdnErYVdoMklNUDBmL2ZNQkg1aGM4elNQWEtiV1FVTEhwWVQ5TkxDRW5GbFdRYVl3NTVQZld6ak1wWXJaeENSWGx1RG9jWlhGU3haYmEvakp2Y0Ura05iN2d1M0dkdXlZc1J0WVFVaWdBWmNJTjVrWmVSMUJvbnZ6Y2VNZ2ZZRkdNOEtFeXZBZ01CQUFHall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCU3ViQVdqa3hQaW91ZmkxeHpXeC9CL3lHZFRvREFmQmdOVkhTTUVHREFXZ0JTdWJBV2preFBpb3VmaTF4eld4L0IveUdkVG9EQU5CZ2txaGtpRzl3MEJBUXdGQUFPQ0FnRUFneVh0Nk5IOWxWTE5uc0FFb0pGcDVselFoTjdjcmFKUDZFZDQxbVdZcVZ1b1BJZDhBb3JSYnJjV2MrWmZ3RlNZMVhTK3djM2lFWkd0SXhnOTNlRnlSSmEwbFY3QWU0NlplQlpERTFaWHM2S3pPN1YzM0VCeXJLUHJtelUrc1FnaG9lZkVRemQ1TXI2MTU1d3NUTHhES1ptT01OT3NJZURqSGZyWUJ6TjJWQUFpS3JsTklDNXdhTnJsVS95RFhOT2Q4djlFREVSbTh0TGp2VVlBR20wQ3VpVmRqYUV4VWQxVVJoeE4yNW1XN3hvY0JGeW1GZTk0NEhuK1hkcytxa3hWL1pvVnFXL2hwdnZmY0REcHcrNUNSdTNDa3dXSituMWplei9RY1lGOEFPaVlyZzU0Tk1NbCs2OEtueUJyM1RzVGp4S000a0VhU0hwem9IZHB4N1pjZjRMSUh2NVlHeWdycUd5dFhtM0FCZEo3dCt1QS9pVTMvZ0tiYUt4Q1hjUHU5Y3pjOEZCMTBqWnBuT1o3Qk45dUJtbTIzZ29KU0ZtSDYzc1VZSHBrcW1sRDc1SEhUT3dZM1d6dlV5Mk1tZUZlOG5JK3oxVEl2V2ZzcEE5TVJmL1R1VEFqQjB5UEVMK0dsdG1aV3JTWlZ4eWt6THNWaVZPNkxBVVA1TVNlR2JFWU5OVk1uYnJ0OXgrdkpKVUVlS2dEdSs2QjVkcGZmSXRLb1pCMEphZXpQa3ZJTEZhOXg4anZPT0pja3ZCNTk1eUV1blF0WVFFZ2ZuN1I4azhIV1YrTExVTlM2MFlNbE9IMVprZDVkOVZVV3grdEpEZkxSVnBPb0VSSXlOaXdtY1VWaEFuMjFrbEp3R1c0NWhweGJxQ284WUxvUlQ1czFnTFhDbWVEQlZySnBCQT0iLCJNSUlFa1RDQ0EzbWdBd0lCQWdJRVJXdFFWREFOQmdrcWhraUc5dzBCQVFVRkFEQ0JzREVMTUFrR0ExVUVCaE1DVlZNeEZqQVVCZ05WQkFvVERVVnVkSEoxYzNRc0lFbHVZeTR4T1RBM0JnTlZCQXNUTUhkM2R5NWxiblJ5ZFhOMExtNWxkQzlEVUZNZ2FYTWdhVzVqYjNKd2IzSmhkR1ZrSUdKNUlISmxabVZ5Wlc1alpURWZNQjBHQTFVRUN4TVdLR01wSURJd01EWWdSVzUwY25WemRDd2dTVzVqTGpFdE1Dc0dBMVVFQXhNa1JXNTBjblZ6ZENCU2IyOTBJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEEyTVRFeU56SXdNak0wTWxvWERUSTJNVEV5TnpJd05UTTBNbG93Z2JBeEN6QUpCZ05WQkFZVEFsVlRNUll3RkFZRFZRUUtFdzFGYm5SeWRYTjBMQ0JKYm1NdU1Ua3dOd1lEVlFRTEV6QjNkM2N1Wlc1MGNuVnpkQzV1WlhRdlExQlRJR2x6SUdsdVkyOXljRzl5WVhSbFpDQmllU0J5WldabGNtVnVZMlV4SHpBZEJnTlZCQXNURmloaktTQXlNREEySUVWdWRISjFjM1FzSUVsdVl5NHhMVEFyQmdOVkJBTVRKRVZ1ZEhKMWMzUWdVbTl2ZENCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMYVZ0a05DK3NadEttOUkzNVJNT1ZjRjdzTjVFVUZvTnUzcy9wb0JqNkU0S1B6M0VFWm1MazBlR3JFYVRzYlJ3SldJc01uL01Zc3pBOXUzZzNzK0lJUmU3YkpXS0tmNDRMbEFjVGZGeTBjT2x5cG93Q0tWWWhYYlI5bjEwQ3YvZ2t2SnJUN2VUTnVRZ0ZBL0NZcUVBT3d3Q2owWXpmdjlLbG1hSTVVWExFV2VIMjVEZVcwTVhKaitTS2ZGSTBkY1h2MXU1eDYwOW1oRjBZYURXNktLamJIaktZRCtKWEdJcmI2OGo2eFNsa3VxVVkza0V6RVo2RTVObjl1c3MyclZ2RGxVY2NwNmVuK1EzWDBkZ05tQnUxa213aEgrNXBQaTk0RGtaZnMwTnc0cGdIQk5yemlHTHA1L1Y2K2VGNjdySE1zb0lWKzJITmpub2dRaStkUGEyTXNDQXdFQUFhT0JzRENCclRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFyQmdOVkhSQUVKREFpZ0E4eU1EQTJNVEV5TnpJd01qTTBNbHFCRHpJd01qWXhNVEkzTWpBMU16UXlXakFmQmdOVkhTTUVHREFXZ0JSb2tPUm5wS1pUZ01lR1pxVHg5MHREKzRTOWJUQWRCZ05WSFE0RUZnUVVhSkRrWjZTbVU0REhobWFrOGZkTFEvdUV2VzB3SFFZSktvWklodlo5QjBFQUJCQXdEaHNJVmpjdU1UbzBMakFEQWdTUU1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ1QxREN3MXdNZ0t0RDVZK2lSREFVZ3FWOFp5bnR5VHRTeDI5Q1crMVJhR1N3TUNQZXl2SVdvblg5dE8xS3pLdHZuMUlTTVkvWVB5eVlCa1ZCczlGOFU0cE4wd0JPZU1EcFE0N1JneFJ6d0lrU05jVWVzeUJySjZadWFBR0FULzNCK1h4Rk5TUnV6RlZKN3lWVGF2NTJWcjJ1YTJKN3A4ZVJEamVJUlJEcS9yNzJEUW5OU2k2cTdweW5QOVdRY0NrM1J2S3FzbnlyUS8zOS8ybjNxc2Uwd0pjR0UyalRTVzNpRFZ1eWNOc01tNGhIMlowa2RrcXVNKyt2L2V1NkZTcWRRZ1BDblhFcVVMbDhGbVR4U1FlRE50R1BQQVVPNm5JUGNqMkE3ODFxMHRIdXUyZ3VRT0hYdmdSMW0wdmRYY0RhenYvd29yM0VsaFZzVC9oNS9XclE4IiwiTUlJQjRUQ0NBWWVnQXdJQkFnSVJLamlrSEpZS0JONUNzaWlsQytnMG1BSXdDZ1lJS29aSXpqMEVBd0l3VURFa01DSUdBMVVFQ3hNYlIyeHZZbUZzVTJsbmJpQkZRME1nVW05dmRDQkRRU0F0SUZJME1STXdFUVlEVlFRS0V3cEhiRzlpWVd4VGFXZHVNUk13RVFZRFZRUURFd3BIYkc5aVlXeFRhV2R1TUI0WERURXlNVEV4TXpBd01EQXdNRm9YRFRNNE1ERXhPVEF6TVRRd04xb3dVREVrTUNJR0ExVUVDeE1iUjJ4dlltRnNVMmxuYmlCRlEwTWdVbTl2ZENCRFFTQXRJRkkwTVJNd0VRWURWUVFLRXdwSGJHOWlZV3hUYVdkdU1STXdFUVlEVlFRREV3cEhiRzlpWVd4VGFXZHVNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUV1TVo1MDQ5c0pRNmZMamtaSEFPa3JwcmxPUWNKRnNwanNibUcrSXBYd1ZmT1F2cHpvZmRsUXY4ZXdRQ3libk1PLzhjaDVSaWtxdGx4UDZqVXVjNk1IYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkZTd2U2MUZ1T0pBZi9zS2J2dStNOGs4bzRUVk1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRRGNrcUdnRTZiUEE3RG14Q0dYa1BvVVZ5MEQ3TzQ4MDI3S3FHeDJ2S0xldXdJZ0o2aUZKeldiVnNhajhrZlN0MjRiQWdBWHFtZW1GWkhlK3BUc2V3djRuNFE9IiwiTUlJRHhUQ0NBcTJnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVFzRkFEQ0JnekVMTUFrR0ExVUVCaE1DVlZNeEVEQU9CZ05WQkFnVEIwRnlhWHB2Ym1FeEV6QVJCZ05WQkFjVENsTmpiM1IwYzJSaGJHVXhHakFZQmdOVkJBb1RFVWR2UkdGa1pIa3VZMjl0TENCSmJtTXVNVEV3THdZRFZRUURFeWhIYnlCRVlXUmtlU0JTYjI5MElFTmxjblJwWm1sallYUmxJRUYxZEdodmNtbDBlU0F0SUVjeU1CNFhEVEE1TURrd01UQXdNREF3TUZvWERUTTNNVEl6TVRJek5UazFPVm93Z1lNeEN6QUpCZ05WQkFZVEFsVlRNUkF3RGdZRFZRUUlFd2RCY21sNmIyNWhNUk13RVFZRFZRUUhFd3BUWTI5MGRITmtZV3hsTVJvd0dBWURWUVFLRXhGSGIwUmhaR1I1TG1OdmJTd2dTVzVqTGpFeE1DOEdBMVVFQXhNb1IyOGdSR0ZrWkhrZ1VtOXZkQ0JEWlhKMGFXWnBZMkYwWlNCQmRYUm9iM0pwZEhrZ0xTQkhNakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMOXhZZ2p4K2xrMDl4dkpHS1AzZ0VsWTZTS0RFNmJGSUVNQk80VHg1b1ZKbnlmcTlvUWJUcUMwMjNDWXh6SUJzUVUrQjA3dTlQcFBMMWt3SXVlckdWWnI0b0FIL1BNV2RZQTVVWHZsK1RXMmRFNnBqWUlUNUxZL3FRT0QrcUsraWhWcWY5NEx3N1laRkFYSzZzT29CSlE3Um53eURmTUFaaUxJaldsdE5vd1JHTGZUc2h4Z3REajZBb3pPMDkxR0I5NEtQdXRkZk1oOCs3QXJVNlNTWW1sUkpRVmhHa1NCakN5cFE1WWozNnc2Z1pvT0tjVWNxZWxkSHJhZW5qQUtPYzd4aUlEN1MxM01NdXlGWWtNbE5BSldKd0dSdER0d0tqOXVzZWljaUFGOW45VDUyMU50WUoyL0xPZFlxN2hmUnZ6T3hCc0RQQW5yU1RGY2FVYXo0RWNDQXdFQUFhTkNNRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FRWXdIUVlEVlIwT0JCWUVGRHFhaFFjUVp5aTI3L2E5QlVGdUlNR1UyZy9lTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFDWjIxMTUxZm1YV1djRFlmRitPd1l4ZFMyaElJNVBaWWUwOTZhY3ZOanBMOURiV3U3UGRJeHp0RGhDMmdWNytBSjF1UDJsc2RldTl0ZmVFOHRURUg2S1J0R1grcmN1S3hHcmtMQW5nUG5vbjFycE41K3I1TjlzczRVWG5UM1pKRTk1a1RYV1h3VHJnSU9ybWdJdHRSRDAySkRIQkhOQTdYSWxvS21mN0o2cmFCS1pWOGFQRWpvSnBMMUUvUVlWTjhHYjVES2o3VGpvMkdUekxINFUvQUxxbjgzL0IyZ1gyeUtRT0MxNmpkRlU4V25qWHpQS2VqMTdDdVBLZjE4NTVlSjF1c1YyR0RQT0xQQXZUSzMzc2VmT1Q2akVtMHBVQnNWL2ZkVUlEK0ljL240WHVLeGU5dFFXc2tNSkRFMzJwMnUwbVlSbHlucUk0dUpFdmx6MzZoejEiLCJNSUlEZHpDQ0FsK2dBd0lCQWdJRUFnQUF1VEFOQmdrcWhraUc5dzBCQVFVRkFEQmFNUXN3Q1FZRFZRUUdFd0pKUlRFU01CQUdBMVVFQ2hNSlFtRnNkR2x0YjNKbE1STXdFUVlEVlFRTEV3cERlV0psY2xSeWRYTjBNU0l3SUFZRFZRUURFeGxDWVd4MGFXMXZjbVVnUTNsaVpYSlVjblZ6ZENCU2IyOTBNQjRYRFRBd01EVXhNakU0TkRZd01Gb1hEVEkxTURVeE1qSXpOVGt3TUZvd1dqRUxNQWtHQTFVRUJoTUNTVVV4RWpBUUJnTlZCQW9UQ1VKaGJIUnBiVzl5WlRFVE1CRUdBMVVFQ3hNS1EzbGlaWEpVY25WemRERWlNQ0FHQTFVRUF4TVpRbUZzZEdsdGIzSmxJRU41WW1WeVZISjFjM1FnVW05dmREQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtNRXV5S3JtRDFYNkNaeW1yVjUxQ25pNGVpVmdMR3c0MXVPS3ltYVpOK2hYZTJ3Q1FWdDJ5Z3V6bUtpWXY2MGlOb1M2empySVozQVFTc0JVbnVJZDlNY2o4ZTZ1WWkxYWdubmMrZ1JRS2ZSek1waWpTM2xqd3VtVU5Lb1VNTW82dldySlllS21wWWNxV2U0UHd6VjkvbFNFeS9DRzlWd2NQQ1B3QkxLQnN1YTRkbktNM3AzMXZqc3VmRm9SRUpJRTlMQXdxU3VYbUQrdHFZRi9MVGRCMWtDMUZrWW1HUDFwV1Bna0F4OVhiSUdldk9GNnV2VUE2NWVoRDVmL3hYdGFiejVPVFp5ZGM5M1VrM3p5WkFzdVQzbHlTTlRQeDhrbUNGY0I1a3B2Y1k2N09kdWhqcHJsM1JqTTcxb0dESHdlSTEydi95ZWpsMHFocWROa053bkdqa0NBd0VBQWFORk1FTXdIUVlEVlIwT0JCWUVGT1dkV1RDQ1Ixak1yUG9JVkRhR2V6cTFCRTN3TUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFNd0RnWURWUjBQQVFIL0JBUURBZ0VHTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDRkRGMk81RzlSYUVJRm9OMjdUeWNsaEFPOTkyVDlMZGN3NDZRUUYrdmFLU20yZVQ5Mjloa1RJN2dRQ3ZsWXBOUmhjTDBFWVdvU2loZlZDcjNGdkRCODF1a01KWTJHUUUvc3pLTitPTVkzRVUvdDNXZ3hqa3pTc3dGMDdyNTFYZ2RJR245dy94WmNoTUI1aGJnRi9YKytaUkdqRDhBQ3RQaFNOemtFMWFreGVoaS9vQ3IwRXBuM28wV0M0enhlOVoyZXRjaWVmQzdJcEo1T0NCUkxiZjF3YldzYVk3MWs1aCszenZEeW55NjdHN2Z5VUloemtzTGk0eGFObWpJQ3E0NFkzZWtRRWU1K05hdVFyejR3bEhyUU16Mm5aUS8xL0k2ZVlzOUhSQ3dCWGJzZHRUTFNSOUk0THREK2dkd3lhaDYxN2p6Vi9PZUJIUm5ESkVMcVl6bXAiLCJNSUlEdWpDQ0FxS2dBd0lCQWdJTEJBQUFBQUFCRDRZbTVnMHdEUVlKS29aSWh2Y05BUUVGQlFBd1RERWdNQjRHQTFVRUN4TVhSMnh2WW1Gc1UybG5iaUJTYjI5MElFTkJJQzBnVWpJeEV6QVJCZ05WQkFvVENrZHNiMkpoYkZOcFoyNHhFekFSQmdOVkJBTVRDa2RzYjJKaGJGTnBaMjR3SGhjTk1EWXhNakUxTURnd01EQXdXaGNOTWpFeE1qRTFNRGd3TURBd1dqQk1NU0F3SGdZRFZRUUxFeGRIYkc5aVlXeFRhV2R1SUZKdmIzUWdRMEVnTFNCU01qRVRNQkVHQTFVRUNoTUtSMnh2WW1Gc1UybG5iakVUTUJFR0ExVUVBeE1LUjJ4dlltRnNVMmxuYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS2JQSkE2K0xtOG9tVVZDeEtzK0lWU2JDOU4vaEhENkVyUEx2NGRmeG4rRzA3SXdYTmI5cmZGNzNPWDRZSllKa2hEMTBGUGUrM3QrYzRpc1VvaDdTcWJLU2FaZXFLZU1XaEc4ZW9McnZvenBzNnlXSlFlWFNwa3FCeSswSG5lL2lnKzFBbndibHJqRnVUb3N2TllTdWV0WmZlTFFCb1pmWGtscXRUbGVpRFRzdkhnTUNKaUViS2pOUzdTZ2ZReDVUZkM0TGNzaHl0VnNXMzNob0NtRW9mblRsRW5MSkdLUklMemRDOVhaelBucUp3b3JjNUhHblJ1c3lNdm80S0QwTDVDTFRmdXdOaHYyR1hxRjRHM3lZUk9JWEovZ2t3cFJsNHBhenErcjFmZXFDYXBndmR6Wlg5OXlxV0FUWGdBQnlVcjZQNlRxQndNaEFvNkN5Z1BDbTQ4Q0F3RUFBYU9CbkRDQm1UQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVW0rSUhWMmNjSHNCcUJ0NVp0Sm90Mzl3WmhpNHdOZ1lEVlIwZkJDOHdMVEFyb0NtZ0o0WWxhSFIwY0RvdkwyTnliQzVuYkc5aVlXeHphV2R1TG01bGRDOXliMjkwTFhJeUxtTnliREFmQmdOVkhTTUVHREFXZ0JTYjRnZFhaeHdld0dvRzNsbTBtaTNmM0JtR0xqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFtWUZUaHh4b2w0YVI3T0JLdUVRTHE0R3NKMC9Xd2JnY1EzaXpESnI4Nml3OGJtRWJUVXNwOVo4RkhTYkJ1T21EQUdKRnRxa0lrN21wTTBzWW1zTDRoNGhPMjkxeE5CckJWTnBHUCtEVEtxdHRWQ0wxT21MTklHKzZLWW5YM1pIdTAxeWlQcUZiUWZYZjVXUkRMZW5WT2F2U290KzNpOURBZ0JrY1JjQXRqT2o0TGFSMFZrbkZCYlZQRmQ1dVJIZzVoNmgrdS9ONUdKRzc5Rytkd2ZDTU5ZeGRBZnZEYmJudlJHMTVSakYrQ3Y2cGdzSC83NnR1SU1SUXlWK2RUWnNYakF6bEFjbWdRV3B6VS9xbFVMUnVKUS83VEJqMC9WTFpqbW14NkJFUDNvalkreDFKOTZyZWxjOGdlTUpnRXRzbFFJeHEvSDVDT0VCa0V2ZWVnZUdUTGc9PSIsIk1JSUNERENDQVpHZ0F3SUJBZ0lRYmtlcHgyeXBjeVJBaVE4RFZkMk5IVEFLQmdncWhrak9QUVFEQXpCSE1Rc3dDUVlEVlFRR0V3SlZVekVpTUNBR0ExVUVDaE1aUjI5dloyeGxJRlJ5ZFhOMElGTmxjblpwWTJWeklFeE1RekVVTUJJR0ExVUVBeE1MUjFSVElGSnZiM1FnVWpNd0hoY05NVFl3TmpJeU1EQXdNREF3V2hjTk16WXdOakl5TURBd01EQXdXakJITVFzd0NRWURWUVFHRXdKVlV6RWlNQ0FHQTFVRUNoTVpSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6SUV4TVF6RVVNQklHQTFVRUF4TUxSMVJUSUZKdmIzUWdVak13ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBUWZUek9ITXltS29ZVGV5OGNoV0VHSjZsYWRLMHVGeGgxTUo3eC9KbEZ5YitLZjFxUEt6RVVVUm91dDczNkdqT3l4ZmkvL3FYR2RHSVJGQkVGVmJpdnFKbis3a0FIalN4bTY1RlNXUlFteDFXeVJSSzJFRTQ2YWpBMkFEREwyNENlalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVEI4U2E2b0MydWhZSFAwL0VxRXIyNENtZjl2REFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBZ0Z1a2ZDUEFsYVVzM0w2SmJ5TzVvOTFsQUZKZWthekluWEowZ2xNTGZhbEF2V2hneGVHNFZEdkJOaGNsMk1HOUFqRUFualdTZElVbFVmVWs3R1JTSkZDbEg5dm95OGwyN095Q2J2V0ZHRlBvdU9PYUthcVcwNE1qeWFSN1liUE1BdWhkIiwiTUlJRGpqQ0NBbmFnQXdJQkFnSVFBenJ4NXFjUnFhQzdLR1N4SFFuNjVUQU5CZ2txaGtpRzl3MEJBUXNGQURCaE1Rc3dDUVlEVlFRR0V3SlZVekVWTUJNR0ExVUVDaE1NUkdsbmFVTmxjblFnU1c1ak1Sa3dGd1lEVlFRTEV4QjNkM2N1WkdsbmFXTmxjblF1WTI5dE1TQXdIZ1lEVlFRREV4ZEVhV2RwUTJWeWRDQkhiRzlpWVd3Z1VtOXZkQ0JITWpBZUZ3MHhNekE0TURFeE1qQXdNREJhRncwek9EQXhNVFV4TWpBd01EQmFNR0V4Q3pBSkJnTlZCQVlUQWxWVE1SVXdFd1lEVlFRS0V3eEVhV2RwUTJWeWRDQkpibU14R1RBWEJnTlZCQXNURUhkM2R5NWthV2RwWTJWeWRDNWpiMjB4SURBZUJnTlZCQU1URjBScFoybERaWEowSUVkc2IySmhiQ0JTYjI5MElFY3lNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6Zk5OTng3YThteWFKQ3RTblgvUnJvaENnaU45UmxVeWZ1STIvT3U4anFKa1R4NjVxc0dHbXZQckMzb1hna2tSTHBpbW43V282aCs0RlIxSUFXc1VMZWNZeHBzTU56YUh4bXgxeDdlL2RmZ3k1U0RONjdzSDBOTzNYc3MwcjB1cFMva3FiaXRPdFNacExZbDZadHJBR0NTWVA5UElVa1k5MmVRcTJFR25JL3l1dW0wNlpJeWE3WHpWK2hkRzgyTUhhdVZCSlZKOHpVdGx1TkpiZDEzNC90SlM3U3NWUWVwajVXenRDTzdURzFGOFBhcHNwVXd0UDFNVll3blNsY1VmSUtkelhPUzB4WktCZ3lNVU5HUEhnbStGNkhtSWNyOWcrVVF2SU9sQ3NSbktQWnpGQlE5Um5iRGh4U0pJVFJOcnc5RkRLWkpvYnE3bk1XeE00TXBoUUlEQVFBQm8wSXdRREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQmhqQWRCZ05WSFE0RUZnUVVUaUpVSUJpVjV1TnU1Zy82K3JrUzdRWVhqemt3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUdCbktKUnZEa2hqNnpIZDZtY1kxWWw5UE1XTFNuL3B2dHNyRjkrd1gzTjNLaklUT1lGblFvUWo4a1ZuTmV5SXYvaVBzR0VNTktTdUlFeUV4dHY0TmVGMjJkK21RcnZIUkFpR2Z6WjBKRnJhYkEwVVdUVzk4a25kdGgvSnN3MUhLajJaTDd0Y3U3WFVJT0daWDFOR0ZkdG9tL0R6TU5VK01lS05oSjdqaXRyYWxqNDFFNlZmOFBsd1VIQkhRUkZYR1U3QWo2NEd4SlVURnk4YkpaOTE4ckdPbWFGdkU3RkJjZjZJS3NoUEVDQlYxL01VUmVYZ1JQVHFoNVV5a3c3K1UwYjZMSjMvaXlLNVM5a0pSYVRlcExpYVdOMGJmVktmamxsRGlJR2tuaWJWYjYzZERjWTNmZTBEa2h2bGQxOTI3anlOeEYxV1c2TFpabTZ6TlRmbE1yWT0iLCJNSUlEVERDQ0FqU2dBd0lCQWdJSWZFOEVPUnpVbVMwd0RRWUpLb1pJaHZjTkFRRUZCUUF3UkRFTE1Ba0dBMVVFQmhNQ1ZWTXhGREFTQmdOVkJBb01DMEZtWm1seWJWUnlkWE4wTVI4d0hRWURWUVFEREJaQlptWnBjbTFVY25WemRDQk9aWFIzYjNKcmFXNW5NQjRYRFRFd01ERXlPVEUwTURneU5Gb1hEVE13TVRJek1URTBNRGd5TkZvd1JERUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQW9NQzBGbVptbHliVlJ5ZFhOME1SOHdIUVlEVlFRRERCWkJabVpwY20xVWNuVnpkQ0JPWlhSM2IzSnJhVzVuTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF0SVRNTXhjdWE1UnNhMkZTb091anozbVVUT1dVZ0puTFZXUkVaWTluWk9JRzQxdzNTZll2bTRTRUhpM3lZSjB3VHN5RWhlSXN6eDZlL2phck0zYzFSTmcxbGhvOU51aDZEdGpWUjZGcWFZdlovTHM2cm5sYTFmVFdjYnVha0NOcm1yZUlkSWNNSGwrNW5pMzZxMU1yM0x0MlBwTk1DQWlNSHFJakhOUnFyU0s2bVFFdWJXWEx2aVJtVlNSTFFFU3hHOWZod29YQTNoQS9QZTI0L1BIeEkxUGN2MldYYjluNVFIR05mYjJWMU02K29GNG5JOTc5cHRBbURnQXA2enhHOEQxZ3Z6OVEwdHdtUVZHZUZEZENCS053VjZnYmgrMHQrbnZ1akFyanFXYUpHY3RCK2QxRU5tSFA0bmRHeUgzMjlKS0JOdjNiTlBGeWZ2TU1GcjIwRlFJREFRQUJvMEl3UURBZEJnTlZIUTRFRmdRVUJ4L1M1NXphd202aVFMU3dlbEFRVUhURXlMMHdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQVFZd0RRWUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFJbFhzaFo2cU1MOTF0bWJtelRDbkxReUZFMm5wTi9zdnFlKytFUGJrVGZPdERJdVVGVWFOVTUyUTNFZzc1TjNUaFZ3TG9mRHdSMXQzTXUxSjlRc1Z0RlNVenBFMG5QSXhCc0ZaVnBpa3B6dVFZMHgyK2MwNmxraDFRRjYxMlM0WkRuTnllMnY3VXNEU0tlZ21RR0EzR1dqTnE1bFdVaFBna3ZJWmZGWEhlVlpMZ28vYk5qUjllVUp0R3hVQUFyZ0ZVMkhkVzIzV0paYTNXM1NBS0QwbTBpK3d6ZWt1amJnZkllRmx4b1ZvdDR1b2x1OXJ4ajVrRkROY0ZuNEoyZEh5OGVnQnpwOTBTeGRiQms2WnJWOS9aRnZnckcrQ0pQYkZFZnhvamZIUlo0OHgzZXZaS2lUMy9acGc0Smc4a2xDTk8xYUFGU0ZIQlkya2d4YytxYXR2OXM9IiwiTUlJRUhUQ0NBd1dnQXdJQkFnSVFUb0V0aW9KbDRBc0M3ajQxQWtibFBUQU5CZ2txaGtpRzl3MEJBUVVGQURDQmdURUxNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdURWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFQnhNSFUyRnNabTl5WkRFYU1CZ0dBMVVFQ2hNUlEwOU5UMFJQSUVOQklFeHBiV2wwWldReEp6QWxCZ05WQkFNVEhrTlBUVTlFVHlCRFpYSjBhV1pwWTJGMGFXOXVJRUYxZEdodmNtbDBlVEFlRncwd05qRXlNREV3TURBd01EQmFGdzB5T1RFeU16RXlNelU1TlRsYU1JR0JNUXN3Q1FZRFZRUUdFd0pIUWpFYk1Ca0dBMVVFQ0JNU1IzSmxZWFJsY2lCTllXNWphR1Z6ZEdWeU1SQXdEZ1lEVlFRSEV3ZFRZV3htYjNKa01Sb3dHQVlEVlFRS0V4RkRUMDFQUkU4Z1EwRWdUR2x0YVhSbFpERW5NQ1VHQTFVRUF4TWVRMDlOVDBSUElFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEwRUNMaTNMamtSdjNVY0ViVkFTWTA2bS93ZWFLWFR1SCs3dUl6ZzNqTHo4R2x2Q2lLVkNacnRzN29WZXdkRkZ4emUxQ2tVMUIvcW5JMkdxR2QwUzdXV2FYVUY2MDFDeHdSTS9hTjVWQ2FUd3d4SEd6VXZBaFRhSFl1amw4SEo2akpKM3lneGFZcWhaOFE1c1ZXN2V1TkpIKzFHSW1HRWFhUCt2QitmR1FWK3VzZWcyTDIzSXdhbWJWNEVhamNOeG8yZjhFU0lsMzNyWHArMmR0UWVtOE9iMHkyV0lDOGJHb1BXNDNuT0l2NHRPaUpvdkd1RlZEaU9FalBxWFNKRGxxUjZzQTFLR3pxU1grRFQrbkhiclRVY0VMcE5xc09POVZVQ1FGWlVhVE5FOHRqYTNHMUNFWjBvN0tCV0Z4QjNOSDVZb1pFcjBFVGM1T25LVklyTHNtOXdJREFRQUJvNEdPTUlHTE1CMEdBMVVkRGdRV0JCUUxXT1dMeGt3Vk42UkFxVENwSWI1SE5scFcvekFPQmdOVkhROEJBZjhFQkFNQ0FRWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QkpCZ05WSFI4RVFqQkFNRDZnUEtBNmhqaG9kSFJ3T2k4dlkzSnNMbU52Ylc5a2IyTmhMbU52YlM5RFQwMVBSRTlEWlhKMGFXWnBZMkYwYVc5dVFYVjBhRzl5YVhSNUxtTnliREFOQmdrcWhraUc5dzBCQVFVRkFBT0NBUUVBUHBpZW0vWWI2ZGM1dDNpdUhYSVlTZE9INUVPQzZ6L0pxdldvdGU5VmZDRlNaZm5WRGVGczlENk1rM09STGdMRVRnZHhiOENQT0dFSXFCNkJDc0F2SUM5Qmk1SGNTRVc4OGNiZXVuWnJNOGdBTFRGR1RPM25uYytJbFA4endGYm9KSVltdU5nNE9OOHFhOTBTek1jL1J4ZE1vc0lHbGduVzIvNC9QRVpCMzFqaVZnODhPOEVja3pYWk9GS3M3c2pzTGpCT2xEVzBKQjlMZUduYThnSTR6SlZTay9Cd0pWbWNJR2ZFN3ZtTFYySDBrblo5UDRTTlZiZm81YXpWOGZVWlZxWmErNUFjcjVQcjVSelVaNWRkQkE2K0M0T21GNE81TUJLZ3hUTVZCYmtOKzhjRmR1UFlTbzM4TkJlanhpRW92akJGTVI3SGVMNVlZVGlzTytJQlpRPT0iLCJNSUlDUHpDQ0FjV2dBd0lCQWdJUUJWVld2UEplcERVMXc2UVAxYXRGY2pBS0JnZ3Foa2pPUFFRREF6QmhNUXN3Q1FZRFZRUUdFd0pWVXpFVk1CTUdBMVVFQ2hNTVJHbG5hVU5sY25RZ1NXNWpNUmt3RndZRFZRUUxFeEIzZDNjdVpHbG5hV05sY25RdVkyOXRNU0F3SGdZRFZRUURFeGRFYVdkcFEyVnlkQ0JIYkc5aVlXd2dVbTl2ZENCSE16QWVGdzB4TXpBNE1ERXhNakF3TURCYUZ3MHpPREF4TVRVeE1qQXdNREJhTUdFeEN6QUpCZ05WQkFZVEFsVlRNUlV3RXdZRFZRUUtFd3hFYVdkcFEyVnlkQ0JKYm1NeEdUQVhCZ05WQkFzVEVIZDNkeTVrYVdkcFkyVnlkQzVqYjIweElEQWVCZ05WQkFNVEYwUnBaMmxEWlhKMElFZHNiMkpoYkNCU2IyOTBJRWN6TUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUUzYWZadTRxNEMvc0xmeUhTOEw2K2MvTXpYUnE4Tk9yZXhwdTgwSlgyOE16UUM3cGhXMUZHZnA0dG4rNk9Zd3dYN0FkdzljK0VMa0NEbk9nL1FXMDdyZE9rRkZrMmVKMERRKzRRRTJ4eTNxNklwNkZydFVQT1o5d2ovd01jbytJK28wSXdRREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQmhqQWRCZ05WSFE0RUZnUVVzOXRJcFBtaHhkaXVOa0hNRVdOcFlpbThTOFl3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QUsyODhtdy9Fa3JSTFRuRENnbVhjL1NJTm95SUo3dm1pSTFRaGFkaitaNHkzbWFURC9ITXNRbVAzV3lyK210L29BSXdPV1pid21TTnVKNVEzS2pWU2FMdHg5elJTWDhYQWJqSWhvOU9qSWdycUpxcGlzWFJBTDM0Vk9LYTVWdDhzeWNYIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQVlBQUFBZjgvOWhBQUFCN2tsRVFWUjRBYVdQUDJzVVFSaUhuNW1kdmV4ZC9wbEVjdmxEQ2kxRS9FTWFiVVdJOWphS1dQb1YvQTdCUWhBYkc3dDhDQ1VJS1FRTHV3aENVQnNMQlNVbUdrTHVkbTluNW5XSHpNQWVnbzNQOE95OXM4dnZmZCtqemN0UHoyWWErWmRidTQ4bUcwbWE4RWg4L2JGM3lXR0d3UHZWODFkNys5LzJscHkzTXJ0eTdqc3dQUHo4WWIyMGxRSjJpYWluMnc5b2swMmFMVVJXc3R4dWlIZ2tubnJFSzNHRVJnOXBvWjdzM0NVeGwvZHZWZnJudG1SYWc5QnVJQ0pnclhmSG5SdkFXeUphRHhYQitlekNXcVgzdDZlNmkvcmkvRTFBa2RCb0xpL2Nackw1cHFlSGIyeXZ1OVJJVUtmaVdIOTVJVm1tVjZldWNLMS9qOEpNSXdSbzZqTmNYNzdQMnZRNlpFWjdPWHJlU0ZBOTNybkQzTXg2cjdZZlR4UUtHa040V1A4ZVc3K2J6NFozZUhFRTlGRlpBSlh1bGlYVnlVRWZpZjlaSElOVytCUTVmU2MrM29Uanp0VFpSa3g0TEVodGZoMWF2Qk1TSWtCckErSnZPQW9obTFBRmdKR1JwYk9vWFMvWDFLWGdIWkU0WDFTc3hwdDE4aVlJbUdKaVJGV1dLQ1hrQmRpUjRMMFFVRUthbUlLeGhvUVptNmZBZE1EVmpUN2NRd0JFWWgzRFNzbDRBK3RyUVR3SmJVQ3NUNVArQ29kVFp0WURtTkpZY3JFRFFTQ2hJTXNWem9WUTJrTEZNQ0NRRlc0QW9EYmZiUkRJN2ZJaTVhQUw0MWp0Vk5pUWlQVWptVUJPZ0FNQ202ODMvc3MvVGFWWHR4NHFLTW9BQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImFhZ3VpZCI6ImI5M2ZkOTYxZjJlNjQ2MmZiMTIyODIwMDIyNDdkZTc4Iiwib3B0aW9ucyI6eyJwbGF0Ijp0cnVlLCJyayI6dHJ1ZSwidXYiOnRydWV9LCJ0cmFuc3BvcnRzIjpbImludGVybmFsIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMjAiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkFuZHJvaWQgU2FmZXR5TmV0IEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDIyNTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA4LTA1IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJBbmRyb2lkIFNhZmV0eU5ldCBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTAyMjUwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy42IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjEuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMTItMTcifSx7ImFhZ3VpZCI6IjJmYzA1NzlmLTgxMTMtNDdlYS1iMTE2LWJiNWE4ZGI5MjAyYSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiMmZjMDU3OWYtODExMy00N2VhLWIxMTYtYmI1YThkYjkyMDJhIiwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IDUgU2VyaWVzIHdpdGggTkZDIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyODcwNiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIyZmMwNTc5ZjgxMTM0N2VhYjExNmJiNWE4ZGI5MjAyYSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJuZmMiLCJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MzI4NzA2fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgNSBORkMgU2VyaWVzIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTA4MjYwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhYWd1aWQiOiIzMWMzZjdmZi1iZjE1LTQzMjctODNlYy05MzM2YWJjYmNkMzQiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjMxYzNmN2ZmLWJmMTUtNDMyNy04M2VjLTkzMzZhYmNiY2QzNCIsImRlc2NyaXB0aW9uIjoiV2luTWFnaWMgRklETyBFYXp5IC0gU29mdHdhcmUiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInJzYXNzYV9wa2NzdjE1X3NoYTFfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJyc2Fzc2FfcGtjc3YxNV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImNyeXB0b1N0cmVuZ3RoIjoxMTIsImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlFclRDQ0E1V2dBd0lCQWdJUVJUZmNnbzZ4d0lGR2ZtdHprMUJTblRBTkJna3Foa2lHOXcwQkFRc0ZBREJFTVJVd0V3WUtDWkltaVpQeUxHUUJHUllGYkc5allXd3hHREFXQmdvSmtpYUprL0lzWkFFWkZnaDNhVzV0WVdkcFl6RVJNQThHQTFVRUF4TUlWMmx1YldGbmFXTXdIaGNOTURneE1USTBNVGd6TkRRNVdoY05Namd3TnpFek1UY3pNak0zV2pCRU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRmJHOWpZV3d4R0RBV0Jnb0praWFKay9Jc1pBRVpGZ2gzYVc1dFlXZHBZekVSTUE4R0ExVUVBeE1JVjJsdWJXRm5hV013Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRFFDa21RL0s4RG4zOXFTQ1c1dEtMdnZETEgzQ2xTY2dRckRnNyt1WTQ0akhsSVkxL0xsNnYycnBqN25sbVZNbEl6b2dkM3lYakNGQnZHcjR6aUdRMlFjOFVwa2FVOTZFWnhFdEh3WlN0dzZZUTBqZG5na1NMUHZPcDhUOFlpSnBjdnNWdFF0aVEwT3NUVHVpTzJFaTRMdUxoN0tSKzh4NGJBUnZ6a0JXc3ROQlRxVlNBWlFZZXNxbmw4SDVTZndiM0lvdThMU2lBc3VPWHl4dDJtczkxMVlyeFd2aC9Lbk9lbDNPZDNoK0s1ZFFZUDUzK2ZQVXpnejU2VFRqOFI0WTZ6UnV6ZGtiblI2eFdYZHJLNDE0aVg5RDZ4NXE4VzJYSkpwVE1LN0VuU1hHMHE3WEY3cDY4akRLQW54QUY4a2ZoM3VpbmMydWxtVk9aYlRSenhGOEIzQWdNQkFBR2pnZ0daTUlJQmxUQVRCZ2tyQmdFRUFZSTNGQUlFQmg0RUFFTUFRVEFMQmdOVkhROEVCQU1DQVlZd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWpNc1RiWTB3WFFCUjI5YldISXZiRmZVQUZmVXdnZ0VHQmdOVkhSOEVnZjR3Z2Zzd2dmaWdnZldnZ2ZLR2diVnNaR0Z3T2k4dkwwTk9QVmRwYm0xaFoybGpLRElwTEVOT1BYQm9iMlZ1YVhnc1EwNDlRMFJRTEVOT1BWQjFZbXhwWXlVeU1FdGxlU1V5TUZObGNuWnBZMlZ6TEVOT1BWTmxjblpwWTJWekxFTk9QVU52Ym1acFozVnlZWFJwYjI0c1JFTTlkMmx1YldGbmFXTXNSRU05Ykc5allXdy9ZMlZ5ZEdsbWFXTmhkR1ZTWlhadlkyRjBhVzl1VEdsemREOWlZWE5sUDI5aWFtVmpkRU5zWVhOelBXTlNURVJwYzNSeWFXSjFkR2x2YmxCdmFXNTBoamhvZEhSd09pOHZjR2h2Wlc1cGVDNTNhVzV0WVdkcFl5NXNiMk5oYkM5RFpYSjBSVzV5YjJ4c0wxZHBibTFoWjJsaktESXBMbU55YkRBU0Jna3JCZ0VFQVlJM0ZRRUVCUUlEQWdBRE1DTUdDU3NHQVFRQmdqY1ZBZ1FXQkJUZlFRNVdyV01SVzc4dmtXaDJuaURUM1Y5N3JEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFpTHBMdG5hRTBBYklpU21tajRFTFJUUk1HdWVkeGQ2WlRZMnlVaTFRTnN3YUkyT0ZuaC9ORFdMV09nRjM2SE92REVMWEJZWk02K0FzUGlWSFU3MnN2bFlqN1k1SHpadm9Va00zZHZieHI2VTJCSjg5SkVFVFJJV3FVbFlPcTQ3QmU4NE9SMlh2bW5pVXVKckZPenNBWWN0clpYMlRGWDNBYlZQczRMU1ROYzBkYTB1cTBDcW9PU09JQ2Z6ejFYN3VmN1R3OU8wS2NLZXJGZ3plVWNtR3RLdjVvSzdSWTlXa0R4ZGkyMlJ5MEdFYjYwdG5hdjdxazlqYTQ1V0JqTjEweHVOcE5zbENhbFJuTllPR1Z0WTFtNG95MmcrMXhkMWIwdnhnMHhKc1c0azJvdlRkWlFTNUhDa21lMDVNNUx5MFNGU1ZHL1JIeE1zNkl4NDNDY3RDSVE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFMUUFBQUMwQ0FNQUFBQUtFL1lBQUFBQjFGQk1WRVVBQUFELy8vOFJCZmNTQ2ZNU0N2SVRDL0VUQy9BVERPOFREZTRWRXVrV0UrZ1hGT2dYRmVZQUFNOEFBTTRZRitVYUhPQUFCODhBQk00QkI4OEJDTThDQ2M4RUNjOElEOUFhSHQwYkg5d2JJTndiSU5zYklkb2NJZHdjSXRvY0k5a3FNTmNCQzlBREM5QUVEZEFGRWRFTkY5TU5GOUlQR05NUEdOSVBHZElSR3RNUkc5TVRIZE1VSHRNVkg5UVZIdE1XSDlNV0lOTVhJTlFZSWRRWkl0UWFJOVFhSk5RYkpkVWJKTlFjSk5jY0pkVWRKZGNkSnRVZUp0Y2RKdFFlSjlVZUtOVWVKOVFlS05NZUtkTWZLTlVmS2RRZktkTWZLdElnS2RZZ0t0WWdLZFVoS3RZaEs5VWlLOVlpTE5ZakxkY2pMTllrTE5Za0xkWW5NTmNuTDlZcE10Y3FNOWdzTk5ndU50Z3hPZGt4T3RsRlROeE5WTjVSVjk1VFdkOVZXOTlkWStGa2F1SmlhTjU0ZmVhRml1T0VpZUtGaXVLR2l1T0dpK09zc09nblByOHJTTFV0VHE4N2NJMDlkWWxFaG5kSmsycEtsV2xNbTJKTm5XQk5uV0ZWc1U1VnNrdFdzMHhXc2t4WHRVcFd0RXBXczBwV3RFdFdzMHRZdDBoV3RVaFh0VWhYdGtsWHRVbFl1VVpZdUVWWXVFWmF2VUpadTBSYXZqOWF2VUZid0Q1YnZ6OWV5RGhleHpsZHhqbGR4VGxmeVRWZXlEWmV4emRleHpoZXhqaGZ5ak5qMVNwajB5dGkwaXhpMGkxbDF5aGsxaWtWcWlFaUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFGK21sVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEQ5NGNHRmphMlYwSUdKbFoybHVQU0x2dTc4aUlHbGtQU0pYTlUwd1RYQkRaV2hwU0hweVpWTjZUbFJqZW10ak9XUWlQejRnUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpUVdSdlltVWdXRTFRSUVOdmNtVWdOUzQyTFdNeE5EVWdOemt1TVRZek5EazVMQ0F5TURFNEx6QTRMekV6TFRFMk9qUXdPakl5SUNBZ0lDQWdJQ0FpUGlBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBpQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJaUI0Yld4dWN6cDRiWEE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM4aUlIaHRiRzV6T21SalBTSm9kSFJ3T2k4dmNIVnliQzV2Y21jdlpHTXZaV3hsYldWdWRITXZNUzR4THlJZ2VHMXNibk02Y0dodmRHOXphRzl3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzQm9iM1J2YzJodmNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSRmRuUTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpVVjJaVzUwSXlJZ2VHMXdPa055WldGMGIzSlViMjlzUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnUTBNZ01qQXhPU0FvVjJsdVpHOTNjeWtpSUhodGNEcERjbVZoZEdWRVlYUmxQU0l5TURJd0xUQTNMVEl4VkRFNE9qRTBPakEwS3pBek9qQXdJaUI0YlhBNlRXOWthV1o1UkdGMFpUMGlNakF5TUMwd09DMHpNVlF4TmpveE9Eb3hOQ3N3TXpvd01DSWdlRzF3T2sxbGRHRmtZWFJoUkdGMFpUMGlNakF5TUMwd09DMHpNVlF4TmpveE9Eb3hOQ3N3TXpvd01DSWdaR002Wm05eWJXRjBQU0pwYldGblpTOXdibWNpSUhCb2IzUnZjMmh2Y0RwRGIyeHZjazF2WkdVOUlqSWlJSEJvYjNSdmMyaHZjRHBKUTBOUWNtOW1hV3hsUFNKelVrZENJRWxGUXpZeE9UWTJMVEl1TVNJZ2VHMXdUVTA2U1c1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRvd1lqRXdOakUyWXkweE9XRTBMV1UwTkRZdE9UQmxaUzAzTnpBek0yRmtNR1F6WVdVaUlIaHRjRTFOT2tSdlkzVnRaVzUwU1VROUltRmtiMkpsT21SdlkybGtPbkJvYjNSdmMyaHZjRG81TjJNNE5HRTJOeTAzWkRKbExUQmxORGN0WWpBek5TMWxOMlU0TldJeFpEazBaVFlpSUhodGNFMU5Pazl5YVdkcGJtRnNSRzlqZFcxbGJuUkpSRDBpZUcxd0xtUnBaRG95TW1VeE5HUmtaQzA1WmpBekxUaGtOR0l0WVRjMk5pMDFNbUU0TWpoak1EZGhOamNpUGlBOGVHMXdUVTA2U0dsemRHOXllVDRnUEhKa1pqcFRaWEUrSUR4eVpHWTZiR2tnYzNSRmRuUTZZV04wYVc5dVBTSmpjbVZoZEdWa0lpQnpkRVYyZERwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qSXlaVEUwWkdSa0xUbG1NRE10T0dRMFlpMWhOelkyTFRVeVlUZ3lPR013TjJFMk55SWdjM1JGZG5RNmQyaGxiajBpTWpBeU1DMHdOeTB5TVZReE9Eb3hORG93TkNzd016b3dNQ0lnYzNSRmRuUTZjMjltZEhkaGNtVkJaMlZ1ZEQwaVFXUnZZbVVnVUdodmRHOXphRzl3SUVORElESXdNVGtnS0ZkcGJtUnZkM01wSWk4K0lEeHlaR1k2YkdrZ2MzUkZkblE2WVdOMGFXOXVQU0p6WVhabFpDSWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3dZakV3TmpFMll5MHhPV0UwTFdVME5EWXRPVEJsWlMwM056QXpNMkZrTUdRellXVWlJSE4wUlhaME9uZG9aVzQ5SWpJd01qQXRNRGd0TXpGVU1UWTZNVGc2TVRRck1ETTZNREFpSUhOMFJYWjBPbk52Wm5SM1lYSmxRV2RsYm5ROUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREU1SUNoWGFXNWtiM2R6S1NJZ2MzUkZkblE2WTJoaGJtZGxaRDBpTHlJdlBpQThMM0prWmpwVFpYRStJRHd2ZUcxd1RVMDZTR2x6ZEc5eWVUNGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NVhCZWFsQUFBTzFrbEVRVlI0MnUxZDU1OGtWUldkWjA2WUE2SmlEcGdEbUZpdExWeXptSFBPWWxaUUVXUTlBWE1XelA2emZyaXY4cXZ1cXA3dW5zSGY5S2VkN2Q2WnM3ZnV1K0hjYzkrY3BBZmc2K1FDOUFYb0M5QVhvQzlBWDRDK0FIMEIrZ0wwQmVqL0Y5QTB1UDB6UGtlZ0RVdWlOb0FpYk1HMGNRNUFTeElzMEJRRnFQZ1ppcFlnUTVKNXRxQmh5ellsU29JZ3l4TWp3N0pKVTdZb1VqNUQwSlJ0MDVabFVhSTk5bTZEa0NYRGxFQUpwdllBKzJSSHlCSXMyYklBV0xSZ3FlY2p0a1Jac2czSkZHRUFPRDNxblVDVERqRE1XRXpabEhvdVFvbEMvTDhvRVdvOHhkSVpnTFpwVzVZRXdKWWtJbnRDOWhESklHM1RFa3lMdGlISVBMV3Rkd0N0Q0dLa1FadEt5U1poVzRZait0bVNiRUsyWUtSRUNhUkVpeUNQRFJxeVRGRHFoVjRpSXJZbEtpSmR1RVl2T2x1QWJCbytuYTFQZHNBc0dyWkhDVVd3TFVHU0xNbmtKQXFLcGt4TDFqRkJtNUNNUWFEb0hvRWxBTFFoMEdJaHZFT2tUMmZxOWFBZGpzR2l0OU1tbUFOaEVaaXRNTGFQQjFxUjNJUzVkd0ZadEd4NkpzYkR4dHk3QndGdHlVWVhhaEhwc1BlbGFXbndMQnhSdmU5Z3RFNVIrSjJzTmJUa3ppTURjQTgxZ0p4MDNQeVZiVUpVZTNBUnVSODRIbWdUUlA3NWRBWXBFKzJUaUtxdS9YOUZXV3FyOVFoSFJ0V3hRRWZhYXdFaFFwODc0N2NJTXlhS3pTZlE0QlFScWZJNG9EVUlIWkxzdTV4U1lHSm5hcXF4UEd3YnpXZmNOREtFVG1IcWxhQ2p1R1ByS3cyTURwSERwYlBoWmR1dGM2dDFxd2d2eHdGdFdXaU9HTlU5WWR1T2dpSkhrMnhHZCtjdm9mMnpaQXJIY2c5RzFhYnVpMzZtYTA4bjFaaVhabGQ4Z0wxbnBGT2tsNVh1UVVGZ0I4aWQ0M1QrSWJGNTlGSXZEN250SXgwdHpaSGNJNkpBKzVEVlN5QW9nYkNIU1dZL1RNTGE2RUViT1MzUWJHSkVvbDNNRnBiUTlqSW1kQmFnYy9mVVJROU8vampwZjl2VXFIMVJIMnZkUXlRYTQwRUNuUE9reThIQVJqd1BtZG9YWGJNMmpjdGlHK2xrVWdJNDMvZkowUjB5dXRzekFRMklYZnd3YmREYVZFbkFGZ0VUM0JzdnRrUHQ0VjVabVF1aFRXRkJqR0xXMkJzSnVicWVkalNJdlZRNEtpUENUempvMEU1VkhwMGVOQjNKdzVzYTM1VDJ4NUR1cVVjTVpnWWI2aE1MT20rZ0FkcWNJMXpJZmtZNUg2QVREWnJXSEdzYkJNUDVzblJLUVI1bGZycEVqRmdXemh0b0JJVVVVd0FWVUVzNlorNFJZUzg2UWRtYTFrbmdZUTI5R3ovZGtZdUtUbmVTTjlQNUE1MkMxeUljR2RKT1IzM3RPblBKcFZKZ0xsbjdQSUpPYW9vT3hTVGdtS2hQTVVkMExxTWxPaVpZSzVLcWpJajNsQlR6UEVtRWtHY0ZJQ25Ba2pYdWVFNDFzWTB3QWptR0Ywc3ppbXdLaHZKWUQ1SnBJTS9MRkErUkZtTUV5VEhUZmNveGM0emhFS2xHWEFZNzVqQ1VRZVNoSGdWYWlBeVFneEtpZitBMCs1NTJvQitoMnNIUGFGbWhwQWlXc0drQ2hnMExtZlVMMTdFTmtTU01TYkk2dlFyQmtjL1JQRzB1OFNvRnMrNllQdWRabVl5SXBXQk1vV0o4RS8rbC9ZTHVxRlJGODdVMXMxQ2dtSWVoRkJ3MFBVMENOZ1haa0FYRzlCUWpKY0IrUkNwcXB2dkJQWHJiUVFqeU5UdDJNTm9pREVlMVpSaUlQdDdPd1dYL29GT2lMU0YwQnRveVQyRjIyMXdvdWt0UWNhVERJMktzRjJOMzR5Q2dVMkpFTEVyUTRwQmR6TFZpcnpCZ1VOaytET2dZdUFBaGxORHVuaWFqcDNnaDFIQkNCd0VkdkhNY29KMmI3eWJERGhxaFViYmRzMW9zNXpydlhrRTExVXlQVnpOSExlZStKVzZ5OCtCOFI3L094MUtkUzRNYXphdjNyOHR6Q0xLd1c1OFl2VnJuMHFITHNROE1PaytUdUp1dGhWSHdrTWx4TkRxRUFqSVNNSGNTdE9XRXFGNzlTd29IdDNSd1o5TXp2OHc3OG9Ib05jblRtZEpodEthSWljRjYxcEUyaUk0SmpMSmdIUFVQSkpDTjBGZFNxV3hqcjBKb05HUitqZ1NhamhKK1piUU83UmI2U1R4a2lFY0JuWXh3RDNCVjZJaE9ncjNHS0ZMVmNVRG5RZGc2VXpPa0liMWpHRG9ScHlPQlRoSDExaFI4VVdiME1ndm9hQldQQnpxck5iSGNvYzFoNjJQbDE5RkFKemVKY1RubzZNUDczUUpLaC9tQW9OdkdaREViRWJKVTlZK0ZWZWlERHJuSWtBbW9aVU9qY0NiM0o5RzBWS3pNRHdsYTBWWXZpbnFXSEpyT05NaUdSZFhRUVZkR1FsSy9wUFd5b3pUc3Q5MG00R0pXUFN6b2FIUzNpeDFoVzREWW01NW5MckpVQ1J6WTBua1hZS3MvaDNmMHJXcEJFRndTQVJ4Mm95Z2s3VnVHaWlKQUVjUG9TRGxveUhSMDBNRUNheVB2RUtKSkREWFZJVmZ0cEZwSEJCM0pZUU5QUm1mK2IwVG5PaForWm9MOGdSZk9ndUtiOHcrTGJJaXY0WEZ0TjVYU0dZRE9DeGd1dlNPQnpLeXZNTWoyRWFGbjlVT0h0alNDVUpnbUVvVUlRMEk4Q3c3c0hCT05PYTU3SFdoNDBrZUVvbDZEajNTU2xOaG1HSlU4T1pOQURGM09tS3BEUzlLbmZZQVc2RkV3SUlZL2xHRkdkbWx0TXZlbmhCZ05NYmgrVHZZNFpCbXpwZmhhMlNaSEQ5c2FkOTBLYnIzTGRaTWRzeGdDV1hsOVpEU25hZDdjMFBTc0ZNaHF6Snd3THo5MXo1WWdPK1VzWStvMjducmprZEhUYVVlekpiTkplTGhTVE1pUkJXSVRqdWl2RGNWK1Z1dWZNa2ZHREUxY3FNRTU2WGRpRnJOeEIzYWxwVWtNTktXSzlhSmVkYUdJQlI0OTdGSDBBTXVhU1VwNVdMUXBpNjUxRDZDL0xjWm1rWEw0TUhvTVl0NHdXZHBXeG9oTTNOd09yOVdhMHYxdnFOenlxOTl0c0o5OXcyMlhkVndFMlV6YTB4NUJjMURVeDliTFlIR1cwZlZyUTVDY2hXeVRBS2h0SGZ4YS9YUmZUMnd3ejk4SHljdzlYaXQydUJaUWVqRSt6UXFqYlE5bVpVYUUySklwRE9uRTRNeUlzUTJxamhhUXQ4NEVZdWZaSXN1aXFOTW1GeWlycW16Q0FqWG9MZkk2bW52c25LWE44M0k0TkI2eUFTMVo1bC9wMDhnRWYreXlrTUx3ME9RRnVZN1lpbFNoRGY0V3lVaHM5dFFXd0ZpL01xSXNFWWlSNGRCZkxZQTlUaWpJbWpHM1RnaGdqbTE1RzlmTnptRGFPMmhaaURZamdHTWsxQW1oU20rTEwrYnhRL094WWNxZG4wTmU1NGFYeHZQVkcwVzJGY29SVEN3VEM4MDlLU0ZwWU1KY05FUmpJMjNKNUJJWHErOVhMekxrT29jSWdjYW9HU0hVNXptaWFSMm5pcnpWREJnTVBRMWdyQkFDRjBGWFZWVlZNMDJkcE5peWx6RXlZYmpsWUJ0SHdOZzdZa3FBR09veUw4T3YwMXVmRkFGWGRWVlZWVjFLNDZBSW9kRDVJZmlXM2w4amRpODA2ZEZ0TVRxeFhPMnRhK0pPcHBEcnFudE5DcWJzMGdYTmQ5QkVZUDhZRmd0anRrM0FlaHVYUUZmVDE3aUZ6aysxUklrcml2dCthQk01SmJaeTZNRE9FdFdUelpCSHFKdnF2UlRCcWF5YkdyU0MxRDdYTHFhZ3E4dGJVUWZyelhMV1lZai8rbDFWa0JzSEJEMTA1akpxMktVOXdoaG9qMjZBQ1dIZ1FZU3pKMXVjWTRnNnltZE15MHFRZ3k2cm1RUG9JTXNqTGVpcG5lc3Bhb3NlcnpNUnpDTFhnU2NFMzBJZVFyUitzdDNPVlZWWFhWckFjTVptQWFGOUdlYjBMR25VUVVUc1pkRDErS3RldHVpZnRTeXBaTnl4NUNGTFpPeDNZMnNDZW91aEc5U2hNR0tQNXJjaGtmSndJVEZ1bmdEb3c0R2VCenYwNnVDTEVCclgzQjdabURTdnVSbzgxQXJYU1RGN3owVVFxYjM3SmQvaWt1VTd3eTRRbEVFZmJCbXFiT254WHpWZUhacEtSZEVzUldObmpFclVYTDE1WDFlSmxVR1hUMTNCMUlFMHk4bEZ5QlRIcTdPeEF6T3pTTDV2MFBVNGxVeEJSMGVYTHhNVHM3WjhYQzJIeUo4ODJCTEp4TkxWWEFXVmVWeG55VDZ5NmxqVDlNaUkwWWRiZkRucFlhdTNnbzZ0aGFaT0xreFQ0MFl4eS9UUDBsRkFUK3ZuL2hzM3A1VHVqTlpac1FwZUluT1VFK0hWMzZhekJsMVhWWFVwcGZTYnF3WTRwMHZLRFIvbG4venFuK21Jb05Pc3BhK2tsUDU4cnoycjc0RVFOMTdkZGMvZi81VE9EblRxUjhKYm52N0kyKzhyaEl1MmxwSmtRWGYvL044Ly90YURIbjM1bG8xMXdjSlhYZUlGVGpLd2Vndm9xcnBjUGZ2YTIvOHdzMXZScnNyWlYzLzczeDg4L2hIVkxUTTRMeStGT212SUR2U29CaTNHait1dis5SDkwSlR5UnZTMGhtbGZ2ZTlmMzN2NDQ5NDVCNlJvNU11Ykg4SVcwTlZtME0rNjQzNXBQSkVLNWo4dmg5MzlpMy9jKyswSFgvdU9hdmRYUFFGZUJsMVBVbmlCdXFtcTY1OXh4OStHTTVkUXRNWlZjcmJ1dXVlUC8vNys5UTk5eTl0TEpxc25YOVRETitycDA2ajNZT25yZm5TLzJrWXdydzA2SnR5Q2ZPZnYvblBuZHg3eW1IZHVkOWhMbHpZZnl1RUoyREY2aEJGdWZ0UVAveElKMm5GdFl0eXdtVGxiNnRlLy9PNHpIL2FtdDIyUEZ1OS8wUXR2bmY5UVBkZWhyZzU1OFJaK0R6TVgwWERRa1hFVkllbGYzcmM5d2xaVlhWZlZpNzljK3VidFQ2dzNPblFEdXQ2Y1hPcjJyYjllUmI1aWhGMHhuVzkrWEZRN3gzZDY3RGNiQXFDZS9PQzNibzBkeTJ1UENJWS9WU3k4ZGxFWjJVTVc1cklNK3F0cHJyaDg5Wlh0RVc5YW1tN3lqbVFEV1Y0WmR3ZEhXYjI4Q0kxdmRjM1hadXIxOUtVbmoyUEtJdEFiUzFPYlVMNWdsUmFYVG1QSG9MOHgvZmFYVWtvcGZlU2xDNVBMQ3RETXR3Z1E0dEw1V2NrOWVxQ2JpUDNlRzFOSzZibHZMS1RMQmFDcjJXTVlTMGx4Ky9XT2JVbDh2MnZDcDl2c1hkZFY5YUZYcEpTKytNUXJoU0M0cUJ1ZmJSRWJSZlB1UldWMmo4SkJmT1dIVTBwZmVFcTEyRDNTT0w2WFdZV1FZVzRZVURvekRMdUF2dUZqS2FYUHZHQlJiVHBMaTlVbEJoS2hPOWcwc052OEpPWkQza3MrbmxMNjNQT0tJSmFBTHRVNmJhdnQyZkY4SGdCcEYwdlgxYVUzcDVRKy82UlN2Ym9iMWR2K084Mk5YREpuQm00NW94bjAxNmMvODRPdlNTbDk1UWxYbHZ2MHJLbEh6MmVpU1JsQURxbmxSaTRzdThjVWRCMXgrdm12WHdNNmJXamN1bjRtTGhZcmdXN282QzA3aVBYbHVZTVlQK096VDF2UWJSVm5McGRuLzFrdTlxZEhNTlN1M2pxQW16bUlYZmZ4MUN1VFI3NTVKTGQxVHBUS1Z6VExVRE4zV1FUNm10dW1CekYvNE4zYm02Mlo0V2M5MSt2bWZZUFJwTlpxN2pUWXF2UEtscjZ0V0VNV1RQZXVWOTIwYmN4Y1BJa2poQmhOTXpQYXVHNWhhL1UwRi9MbUNwNDNmR0tYMmZnNEZIT2tqR3B1dllpT2NaYzBmdVdtRzRZLzVhMGZlUG5MYnEzcTk3ejJodmRWaTFRSWFYTXVDalVRQnZ3ZDRtSWphc2s5VnhsMC80dlhmWHJ5cWVkODZzYXFldk5IUDdsTWhUQTBkeUZSQi9QVm43emwrOXdvSHU4aXB0V1hzZmF2c1VqS2Q0aVFZRXJuRmJTSEM0YU11czQ2N3VWaXF5OFk3a3VTWWhmaElKS09mWUpHL3lyaytGMDR0cG5PTTJoQ1JIdFJmWjRWNHNnWHo2MjNkTHRqNWVhQzArTWJldjFGOEZGUE8wUnVvV0ZMNXh4MFpKR1FYOFV2emVIeE1hL1dta0pnM0xFUWltODZuWC9RSVFETUZCT2xzOEM4Vmw0dmgzUWkvM3FjUTErcnViZU1pSHlEc0U1MUdkY3gzWU9RM2R3T2RWYVkxOGZwSUI3bHM0Tzh5L1pGM0l1WHp2SzErcGNiYkdCcnppbm9jL0o2UUlMK0gxOXRoZE93T2c2Q0FBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJhYWd1aWQiOiIzMWMzZjdmZmJmMTU0MzI3ODNlYzkzMzZhYmNiY2QzNCIsIm9wdGlvbnMiOnsicGxhdCI6dHJ1ZSwicmsiOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sInRyYW5zcG9ydHMiOlsiaW50ZXJuYWwiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMjU3fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotNjU1MzV9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wMS0yNiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDEtMjYifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJlMDc3OTI2NTA0Y2Q3NWViNDA1YTQ1YmUxNjBmNzgzMDQ0ZTNmNWEyIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImUwNzc5MjY1MDRjZDc1ZWI0MDVhNDViZTE2MGY3ODMwNDRlM2Y1YTIiXSwiZGVzY3JpcHRpb24iOiJBVEtleS5IZWxsbyBUeXBlQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjowLCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQlNUQ0I3NkFEQWdFQ0FoRHlGTVhxT2YvbkVZZURnRzV2Ym1sak1Bb0dDQ3FHU000OUJBTUNNQ2d4SmpBa0JnTlZCQU1USFVWbmFYTlVaV01nUm1sdVoyVnljSEpwYm5RZ1ZUSkdJRlpFSUVOQk1CNFhEVEU0TURFeU16QXdNREF3TUZvWERUSXpNREV5TXpBMU5UazFPVm93SlRFak1DRUdBMVVFQXhNYVJXZHBjMVJsWXlCR2FXNW5aWEp3Y21sdWRDQlZNa1lnVmtRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTajYvRTlDNGNURnNFSHZPSkdFVnZrRGdIUndKV1FyNHVDdFZjYktzRlVLbTlsdUw2YVJSNTJGUkdUSWR6YmpVTWsxaWVEeVJIdTdLS1dSTkYxNE0rTk1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ1Foam9scVp2ZUFEYjB3N3ZkczgrMXBGeTNXQlVpSnNETHZrV0Q2dVAvcVFJaEFLS0h1NExhaVpEcXRSVHE5L2FGSzRMNG9TcGFRVkc3aHp2WmNWUDJZV3lKIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQU1nQUFBQnFDQVlBQUFENWpCNTdBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNJQUFBN0NBUlVvU29BQUFCelpTVVJCVkhoZTdaMEhZRlJGR3NmLzZiMEhRa2lqU0pFaWdocEFsTjZiSUJBNnlpa0luQVVWRGp6dVBFKzlwbGhvS2lycUlVVkFGRkM2aUNqRkErbElrNmFVUUlCQUV0S3ptL3UrZWU5bGE1TGR6U2JabGZucHNKdlp0N1B6NXMxL3Z2bm16Y3p6S0NZZ2tVaXM0cW0rU2lRU0swaUJTQ1JsSUFVaWtaU0JGSWhFVWdaU0lOV0lIQjF4ZlVvZHhjbzVmeDZwcTlaQ241OFBEdzhQTlZiaURMaklQYnk4a1BqSUtQaEdocXV4RWxla1ZJRmMrMkVuOWo4MkFZVVptZUppU3B4SHNVNFBMejgvUExCMUxZTHExMWRqSmE1STZWMHNOaHBzT1dSd2Z2QlVYeVV1VHhrK2lISVJQVHc4NGVFcGcxT0RzVmdrTG8zZFRqcjN5R1N3UDBqY2s5SjlrTzI3c1AveGlTakt5SUtIdCtLRGlFUDVnaGNWb1ZpdkYzR1NjaUFyNGVucnE3NVZMRWF4VGtkeDVJTjgreldDNnRVVGNSTFh4RDZCa0NpOEFnTVIycVF4Zk1MRHBVaHNnVXIzMnJidlJlTWlCZUorMkNVUWZXRWhBdXNrb2NXc21RaTd0eVdLOHd0RXZNUUtKZTZGQnpZMXZBc2dVV2lqZ1ZJZzdvUDlBcWxYRnkzbnowWlk4MllpVGxJK0c1SWFvYml3U0FyRURiSC9UanJMU1hhdGJJS0xTclEvVnBzZ2lUc2dwNXBJSkdVZ0JTS1JsSUg5UGtoZDhrSGVleHRoTGNqeE5LSW9OeGRaUHgrRHZxQ0EzTkxiNndaWU1mM240ZTJOaVB2dUtSbXBZa1RCVXZGdVRHb3Noc2FsRCtKK09FMGcyV2ZPWXUrajQ1RjNKUTJlbm1TWWJoZU5VT25weVNmempZeEV4MTFiMVVnRktSRDN4MmtDdVhYcURQNDNhQVR5VWxOdnY4bU5WT0Y5bzZQUjVlaGVrM1pCQ3NUOWNaNFBRalhEdzh1VGdqYzhxU0o0VXBmamRnaGM2Ymw3SlY3Vm9wRDhmcEJPdWtSU0JsSWdFa2tadUxWQTJIMHFLMGdrRmNWdEJTSUVvTmREbjVkUElRODZOZkI3UGM4Um84K2tTQ1FWeFQwRndoWkNwNE5QUkRnYS9ua3FHcjR3RlkybVQwR2pGNmFJOTNkTS9pTjhvaUxGTVh5c1JPSW9iaWtRcnZMNm9pTEVwd3hCZytlZVFvUG5uMGFES2MvUUs0ZW4wV2pHbjFENzRZZkU2ajFwUlNRVndmMEVRaFdlNzhjRUpTVWlhZHdqYXFRbGlXTkd3Q2M4VkxVaWFxUkVZaWR1SnhDMkNKN2VYb2diT2hnQnRXUFZXRXVDNjlkRFRJOXVRaURVSVZOakpSTDdjQytCc085QlhhdUF1RGpVZnFpdkdsazZkU2M4cnZnaTlCMkp4QkhjUnlBc0RuN1JGNk5HbDQ0SWJuaUhFbDhHUVEwYklPN2hBZUIxNFhKNXNNUVIzTXFDY0hmSmx5eEMvSWloYW93WlpqMHBudm9STjJRZy9HcEVLNzZJUkdJbmJpTVFVZmZKQ3NTblBJeXc1azFGbkRGcG03Y2dkZDE2OVM4RDRTMWJJT3IrTnNLQ3lCRXRpYjI0ajBESWorRDdIdkhEaHFneEJuVDUrVGc5NngyY1g3aUVMSVZsVnlwK1JBcTgvUHlWYnBZVWljUU8zRUlnM1BMckM0c1EyNzh2UXBvMFZtTU5YUDFtSzY1djM0WDAvLzJFRzN0K1VtTU5STFc3SDdVSDloTWlrL0tRMklQckM0U2RjL0lmL0dwR2kwcHVEdDhUT2I5a0dUeDhmYURMeWNHNWp6Nmw3NWhhRVo2R3o4UENQc0ZCMGhlUjJJWExDNFJiZk80YXhYVHJqUEJXTFpWSUk2NTk5ejNTZC94WXNqNGpkZFZxWE4rMVcvM1VRR1RiWk5UbzJobjZna0xwaTBoc3hyVUZ3aFZaWDB6K2d5OWlCejRFVDNvMWhpY21YbGp4SlhTNXVYUW1kQ3JxeHRBWGxxeFFqekRBMDA1aUIvU0RUMWlJY1BhbEx5S3hCWmNXQ0ZkaFhYNGVZbnAyUjQxTzdaVklJektQSGtmYXVvMWlSVjhKWHQ1STIvUU4wbmRiK2lMUkhkb2h1bU43Nm1aSlgwUmlHNjRyRVBZOXFLWDNEZ3BDMHVQVzUxeWRmZTlENlBMeXhZMUF0aHg4MzRNdEJULzBKM1hsYWd0L3d6c29HTFY2OTZTekprR3hGWkZJeXNGbEJTSmFlS3JndGZyMFJHaXpKaUxPbUt2Zi9ZQzB6ZC9DazV6ekVyUXRkOGdwdjdEOGMrU2NPYWY4YlVUYzRBR0lhdHRhT1BmU0Y1R1VoMnNLaENzdUJYNXNRSzMrZmVBZEdLUitvTUNXNGZMcXI2RExVWHdQNDcyb2hDV2h1S0xNTFB6NjMwVnFyQ2xza2NRT0krcnZTQ1NsNFpJQzRTckxJb2hvazR5WTdsMlZTQ051N0QrSXkrczJDVXRSR3A1K2Z1VEFmNEdiQnc2cU1RYWkyclZGemE2ZHhMMFZLUTlKV2Jpc0JlRzc0NG1QamhMM01NeTV2R1l0OHRQU2hLVmd1S3RrSEFUc2k5ek13S1ZWWDFsWUNaK3dVTVQwNms3Zko4dGo5cGxFWW96TENVUlVjbXJaMlhMVTZOeEJqVFdRdm5zUExpNWRMcnBJNHM1NEdZRWQ4VXZMdjBUVzBSUHF0dzNFRHV5UDBPWk55VkxKT1ZxUzBuRTlDNkluZ2RCL0NhT0d3anNnUUkwMGtQdnJlWVMwYUk2YUxLQXVIY3NNTmJ0MVFYRGpCc2k5ZUZIOXRnSHZ3RUQ2amVIUTU1RWZJd1VpS1FYbmJUMTYrZ3gyRHhtRnZOUXI4T1J1a1pIamJDdkNldWlLRUptY2pQdVdMeFRQRWplRnMrcFl1dUpiWm5rcXVIRVRlNGFOSmovbE1EeDlmRXljZlZzUnhVZVd5amNxQ2wwT205N0JGd1ZMbjh1dFI5MFgxN0lnWE5tS1BWQ3JmMjhyNG1Ec3I4Q01xUGhXS3I4dnp3NGVQbFNJVXZ5MlJHS0d5d2hFV0E5cWlVT2JOa2I4a0lGcWJPWER1NStFTm05R3YwMi9MMFVpTWNOMUxBaFZUdXJ2SVQ1bEVMeERROVhJeXNjbk5BU3hmWG9wZDlhbFFDUm11SVJBTk9zUjNLZ2g2anp4bUJwYmRTU09IWW1nK25VcEgzSkVTMktLU3pqcElndmt1RVoxYkkrRWtVUEYrL0phYys0U2VRYjZvMGI3QjhTejI0M2hDWTdYdCsxQTBhMWJKZmRLU29YeXliOTAvdU5GdUw1N2p6amVIbWRkNUYwNjZiOWJYRWNnRlBqeGJiem9TYWxaS2lJWnk3UTRMMEYxRXRGMjB4b0UxNm1qeGlya3BWN0dqcDRQSWV2b2NURmR4UkwrUGZVdFEzbGxrWWw1WGZSZUNrU2lVZTFkTEtXQ1VSZUxueU5PclRmUHVQVU9waEJDSVN3RXZoRVJZaTI2YjJTRVJmQU9DeFVQNnpISHc5T0wvQmo2cnBYdmNGbys5TXBwaTkvZzN3b0tvcElnUzhLV2l5cDdLVzJHNURha1dnV2l0YjdlNGFGbzl0YS9jZGVzMTlGODFtc2kzRFY3cHRpSTJpc3dRQWpJYWREditWRnIzM0Q2RlBxTk4wcCtyOFdzbWJqemxSZmhGMXVMaENKRklsR29kZ3ZDYzY1NDVDcHg1REN4WTBuQzhCUVI0b2NPUm1CY2JSVGV5cmJXdzZvUXZBSXhNQ0dPZm1PUTRmZUdEVWJkY1dNUjA2MExIVUhpa0FLUkVOVW1FRzZodVYvT0kxZjFucHlneGhyZ1ozMmNlbnNldmRFTHY4QnBVRGVPNzZDZisrQVRGR1dUK015b08zRThmS2pyeFlNQVVpU1M2ck1nYXVXTDZkNFpmdEZSNHIweEY1YXRSUGF2NThVQWdUTU5DRHZndkxsRHhzRWp1TDd6UnpYV1FHQlNQS0k3ZFNTZnFOREVqNWZjbmxUUEtCYjlwTDVJQi8vWUdDU3ZXSVRnTytxckh5Z1VabVZoVjg4QklrM3hCRmtyYVhGZUFxaWIxUHFMcGRSZFNsQmpGZkt2WE1XUGc0Y2orK1FwcTZOWWZNbzhZaGFSZkEvYXJsbXBUSHMzSXZ2TU9ld2FrSUtDdEd1S1FNczRGMUY4bFRTS2RaTXMzWTk3ZGlNck00c01uOUtXOFRQWlEwTkMwYUhEZy9EMzl4ZHh0bEJBNTd2bDIrK1FrMk5xTlRuN1Jib2kzTldzR1pvMHVWT05CVTZjL0FXWFV5L0J5MHRaNzAvMlhsalZwazJhSU1xb1Fjdkl6TVQySDdZamh5eStad1Vzdlk1NkN2ejd6Wm9hVm84ZVBYb01SNDRlaFpmWlVMMU9yOE45OTl5THVuVk5SeS90SlRjM2o4cmtXK1JSM3JWcnpOZE1SOWVuYmV0a0pDWW1WbzlBUkFWbDM0UDYvUzNtdktuR0draGR1eEVISnp3bEtwSldxY3lwaUVDNFZ2Q05TVS8vQUhMT1gwT3RmcjNWRDFUb3M4TlRYc0NGSmNzQTc3SW5NVmFtUUk0ZU80YnhFeWJpN05sZjRVMzVZQW9MQzlDd1lVTXNXN29JTVRWcmlqaGJXUExaTWt5Yi9tZFZhTnI1RkNPZnJrT1RPNXRnM3B4WnVQUE9SbW84TU9PdkwrS3paU3NReUlNa0JKOG1pK3k5ZVhQUXVYTW5FY2VjSkNFTkd6a2FhV2xwSldLeUh5VWZrNTk1R3RQL05FV05BelpzM0l3bkprNFNaYXhjQXc3RlZBYUZHRFJ3SU9iTTVycFQrclVwajIrMmZJdkh4MDhRalk2SGh5SkNIVjJuZ0tCQWJObTRUZ2pFVkpwVkFWZE9xaUQ4YkkrNms4YXJrUWFLc25Odzd2MEYwTkhGWUgraFV1RENwclIxMUpxZW5iOUFXQk1UNkxPRVVjUGdFOG1QVHFqT2plYUs0ZVh0UzhHYkJPS2xCbm92aEdaN3hWaTRlREZlZnVVZlFoemkrMnBhbkFhM3d2UGZuV3NpRGlZdnJ3QzNidDFDTmwwUEpXVFQzOWtvb0Fwa0ROY3JieEtHYVI3dERjcjN6UzFGeng3ZDBMTFYzZlRPUXh5akhldExqZDZPblR1eGQ5OEI1VUFIeU1uSnhjSkZpNFcxOFBIeEVXbDdjZm8rM3VqZnA0OFFCMVBsQXVGV2xSK2Z4dXMxUXUrMDNFWTBmZGVQeU5oL1VOemZjTHh0S0I5dWtialZ5RHp5TTI1WTJTS0lONmtMYmRGY2lMa1VJMXNGS0RjdHVldkNsWnVEa20vYmIyWWVQSGdJTTJlK0pWcG9yZ2hhR3R4cSt2bjdZZXFVNTlDZ2dlV2pKRHlwMitsRjE4QTBXSnRsWUpsSGU0UDJmV3ZuTkhiTUdCUVZGWXIzNGpnNm52Tnk0K1pOYlA1bWk0aDNCTGJPZS9mdUU0TFQ4c0M5aXZEd2NIVHZ6aU9aQ2xVdkVCS0hQM1VONm96L2d4cGpRRS85MEZOdnpCRkR2NVJyTGhIMWswcUNMcmd1T3hmbkZpd2tJVmcrWktmK1V4UEY4bHl4SVhhMWljUnh1QTgvN2M4emtKNmVMaXFWcUFSMEhpd09QcHNYWjd5QWh3Y01VQTZ1RU5RcjRKNkJnMEZKUWZ2SGxQWVBQb2kyYmRxUVNBelhSeFBTaWhXZmk2NmRJN3crODAxa2thL0w1YUxCWGJlMnJWdWpTK2ZPYWt3VkMwUVVCbFcyR3AzYkk2U3hxVWxuMG5mdXdzMTkrOFVvVXlWTG93UVBNcW5YZCt6RWpaOHN6WFZrbTJSaDZWalVWcTZkUzFOWVVJaVhYbjRWSjA3OEFqOC9QMU54ME91b0VjTXhhdVFJOVdqSDRmVFlPckdqNjJqSTVWZHltQXRWUzJGTWVIZ1llblR2VnBKdkRud3VYTEV2WGtyRjFxM2IxQ050NS9TcDB6aHc0SURvMW1ubHdxR0llZ3REVXdZTHE2SlJkUUxoVEZBRy9HSnFJbjU0aWhwcGdPOTduSm56cmlJTWJpSFVWcUl5RVMwUldhcUNHeGs0L2ZZY05kWUFUMzFKZW5RMHZFUGNhOU5ycm5UUFBqOFYyN2Z2b05OVHVpVmFKZUErZDkvZXZURmoralQxNklvUkdocUMzcjE3WWRDZ2gvSHd3QUVPaFVFVUJnOStHRTJ0N0gvRzE2aGZ2ejZvWGJ1MnlMOHhmbjYrV1BEeEo4ak16RkpqeW9mVCtIVEpVdVNScUkxOUhyWlFkOTkxRnpwMk5OMEhvY29Fd3FmR2xTd2l1WlhGQ0JpVHZtczNidTQvUkI2Zm95TWhqc0V5OUNJcmNuWGJkbVQrZkV5Sk5DSXkrVjVFdFcwam5IWHpDK1NxdlB2ZSs5aXk5VHY0Qi9pWHRKQk1FWFVoMk4rWU1XTTZBdFRScVlvU1d5c1dyNzd5ZDh5WjlSYmVmdXNOaHdPUG92VWo1OWdhc2JWcW9YT25Ea0xjeG5CTGYvYmNPWHl6NVJzMXBueDRSSERidHU5Rm82SEI1Y09PLytqUkk5VVlBMVZuUWNoRThtelp1cE9lZ0hlUTZmUjBGczc1eForaEtDTkRXQTdSc2xjVnFoV2hKZ1JuNXM2M3RCVGtwNGdOSktpbDVIT2cwbFEvY0UxV3JWNkQyWFBuSVRjM1IxUUNyU3k1aGF4WHZ6N216bjRidFdKaVJKeXpFQTU2QlFPMzVtVmQ5eEhEaHlFb01MQ2txOFhIY21DL1ljblM1YUtiWnd0cjE2OFRvaXB4ekNrdEhyNXUyZkp1ZE94Z3VZdE9sUWlFTTZITEx5RGZveE1pN20ybHhocklQbk1XVnpac0puL0FhQnZScW9aYW8ydmZiMGZHb2NOcWhJR0kxdmNodkVWek1mcm15dkw0WWNkMi9QTmYveEh2dVhYVktnRGZoQXNKRHFadTFaL1F1SkdsNytjT05HcllVSFIvakoxMWhuMlJJMGVPNE5EaEkycE0yU3hlOHBrUXBGWTJES2ZabFJ6ek9DdVBGYTk4Z1hBbVNQVTh2Nm1PbFUyb2VSWGZpWC84Unp6S2dISXRNbDdWOEcreXYxRnc5YXJWUnlmNFJrWlMzaDlWTEkxYXFLN0diNy85aG1uVFp1RHlsU3NXSTFZOHZQdnM1TW5vMnRVd2ZPbHVjQmRvN0tOanhIMEtQaThPNHJwUnVFRTlqOVZrT2JraEtJdEY1SHVjdjNCQlhHdXRubkg1MUtoWkF3TUg5aGQvbTFQcEF1SHFKTzU3VUIrU04yb3o1OGFlZlVqZjhUK3hWV2gxdzlOYUxxNWNoWHdTaWpreHZYc0lmMFJQbGxCcmVWd0ZucEx5MTcvOUhSY3VYaElWU1lNdlB2ZmJ4NDk3REkrTUdhWEd1aSt0V3JZVVUyS01mUkd1NkFIKy9zS3ZPSEhTY29OQWpjeXNXMWl6NWl2NHFKWlZvNkNnRVAzNzlVV042QnBxakNtVkt4Q3VTQlM4eVBlSUh6bFVMSDR5aHU4OVhGejJ1Wmg3UmJrMnlYaFZJMzZiV2hiMmcwNis5cFlhYTBxZGNXT1ZoL2lvNStVYUZHUDZqTDhJcDl4WDNlbWV6MFVUUjk4K3ZUSGx1Y2xrVmFxa04xMnBzR1VjbHBJaUtybmVxUHlGczA0VzlLdXZ2bFpqTE5tMmJSc09Iam9rMHREZ3JoVjNxMGFTZjFNYWxWcHFmQXJzOUlhUzZxMDlBQ2ZyeENsYy9tcTkwblZ4SmhYUW1RZFpzclQxbTVCNXhISkVLK0tlbG1KRGJWNzlXTjN5NEg0MDg5NzdDN0IyM1hyNHFaYUR4Y0VXTHA4c1hkczJyVEZ0eXZNaS92ZENwODRka0pTVUJEM1ZLMk5MN2t2ZHlPVXJWdUxxMVd0cWpDa3J2L2hTV0FzdUg2Mk1lRGk4ZTQrdXFGL1BkTEtzTVpWdlFZajZUMCswT3Vudy9LS2x5Rk0zb1JZdHVOMnc3MkNaTG05NDdVaDZXdUVWWEVzWHp6bzB4NTlhbTBUZVZFSnJqWTB1VU5YaUFSK3lGanhpTld2MkhPRmphSG5uQ3k5R3JPclZ3WnN6WDBkaWtqS25xTExJemMwVkxmT2VuMzRTVXpjY0NUL3QzU3UrZjhIS0ZySG14TlNNUWMrZVBlaWR3Y2xtZUZUcThwWEwrSHJkV2pYR0FNOU0zdkx0Vm5FTW8zMlB1Nk5EQmcwdXNieldxRHlCVUNaNGJrdEkwenZoSFJsTzF1SVhjWitCQTc5UDI3d1ZhUnMydzR2Nmo0NVVadm9TK1BFRldjZFBVRGlKektPVU5vV3NZeWZFbzltSzh3dkZNWGJEbFl5K2RtbjExN2kyYlR2bGxkSTJ5cmQvWEJ4OG95THB3T29SQjVlVmw3Y25qbEIrWG43MVZYRVgybmc0bDd0VzBWSFJlT25GdjZLMmxWRVpaM1B4MGlVOE0vbDVQREwyY1l4OWZKeGo0Ykh4R0RWbUxGWjgvb1dhYXRtTUhqVUNRVUVCNGx5NXNtdm43a21ONWFiTlc1QjIxWFQ2eWVMRlM4V3hmSngyTEhjLzc3Ky9MWm9hVGZHM1J1VUpoRE5ERjQ0M216NHc3a25zSGpRQ3U0ZU9Wc0xnRVRqNDVETmtQYTRLeDlnUjJDSVZwcWZqME5QUGkvUjJwMUM2SElhTXhJRUpUeU1uTmRXaHRFVWhVdHA1Rnk5ai80U25LTjhqRGZrZU5Cejd4MDFDRVRsOGRLVHloU3FHKzlCWHFkeW1UNStPR3pjeXhNeGU3YUpyNUJma2kzbHRWUUZYUEdXbTd5MHgyOWV4Y0V2TWl5bzBuMVZkQ2p6TnYyK2ZQbVFwVFoxMXRxU0hEaDBXTXdnMGpoejVHV3UrV3FNT1hpaFdod1BQM2gyYU1zVEVKN0ZHcFhheFdDQzgvanYvMm5Ya1g3K09ndXZwSXZEZlJWbkt3aDN6aTJzci9EMjJVSVhwR1pTMmtxNUltMEpoK2syK2NoVkttenI1NUxCbm11YWJBL1Z4MmE4U0tUdVlma1hndk4zTXlNQ2wxTXRXTHk1YkU2NXdmM3Y1WlJMUURUVzI4dUQ4Y012TmVhbG8wTHBBdGpDTUtqY3YzR0pMb0hXWitQdVptWm40ZWkzNXRTb3JWcTdFalpzWkluM3RjbkVYbEJkK2RXeHY2UmViVTZrQ1lWZ2syalBNalFPMzBvNVdZQTMrUGkvbXNraWI0cHlTTmw4MHM3UkYrcHgyQmROM0ZKRXZOV2hvclNJSGp1Y0srOXR2NS9IeUsvOUVOaittcnRJeC9MNGpRVWxCKzhjMm1qWnRJbGI5NlkxMnZPRnpaeXV5OWJ0dE9IUG1yR2dndmw2M1FZeHlHY1BPK1pqUm94RVJFYTdHbEU2bEMwVGlmTXdGd2kwaWQzVVlybkQ4RVZlVURaczJZdG15NVNLK3N1RGY0NjRPNThIUndOTkZlSjRZTDZXMUZlNHk4ZjJMZ0FBL2NlNmEwTmlLNkhSRmVIdjJIS3hkdjU2Nm8ya2xaY1hIc01YaEtUZTloS05mUHBVZ0VGWFJuT0hiSVloekxmbW55dUNMelJXRDV5QjE3OVlWQ1FueG9ySXhpaFh4Rk5iam5YZm40K3haeTZmOU9vdEEvd0MwYW5VMzJsQnIzanI1UG9kQ0d3bzhKSjFndG5TNlBIZ2FmRUo4UWtuandQQzU4L0xrNzdaOWo3bnozaE5kS3kxZUU5R3dsTUVrTE52Vzh6dDNUZnJnVWNpN2ZGbDBUVzRycUZYeXBmNXdsOE43MUFnRlJUY1ZXNU0rNmFuSk9IZjJyTEFJR256SmxNdm1nYjU5ZTJIbWYvNk45UnMyNHJtcDA4VDlBUmFIVmlHNGRlN1VzUVBlblBrYUlpTjU5TTAycGs1N0FZdVhMRVVRN3pwSmNGb3N4ZzgvbUk4ZUpFZ05ycHpzcFBPTk82MmxkZ1RlRU1MZjMwK3NYYkdIQlI5OWpGZis4VzhTZ3JJNmtkSEtoNE54V2JEMTRJYmtnL252aXJsZHR1QTBDOEtyN25nakJwNVR4V3M3YnJjZ3BxQ29aVkhaOE1YbWZuVHZudDN4S2puakxCN3ViblRyMHRuRWFlV0t3UnNwY0d2Nnp2ejNSWnl6NFFvWUVoS0NzTkJRaE5Lcm95RXNMTlJ1Y1RBOFJaNm44SE5EWUh6ZUhEUnhhTENGdmI5dEc1dkZ3VGpOZ2hSY3Y0NExpNWVoNEZhMlNhWnVDNmdJdlFJQ2NNZXpUNm9SQ3FKZzZUTm5XaEMrWEJ6dWFkVVNIMzM0QVlLRERjK1FQM2Z1SENZOStReCtQbnBVSE0vWGdZOWwwUVNIQk9POXVYUFFydDM5NnRGbFk2c0ZjUVg0WnVsYnMrYVVPaEttVkhIS2YwRWh2dCs2QlhYckpDa2YySURUQkNLeHBESUV3aTFsZkZ3Y0ZuNnlBUFdzZkpjbjdUMyt4Q1JxTFF2Vm9VMURWNnQ1OCtiNDVLTVBFQjFsdVZHZk9lNGtrTE5VUGtPR2pjSzFhMWROdXFJYW5IZGU4OUdGTE96SEg5cG5TZVVvbHB2QkZ6c2dJQkFob1dGcWpDa2RPclFYZDVxNUpUVnUrM2lvOC9DUkkyS2QrdStOdXRSb1AvaEFXL0tIRE1QR0d2dzMrMG5jalh0c3JPVnlpL0tRQW5GTExDdUNNWS85NFZIY2ZYY0xzaHJLMUh5MkloeDQxZDY2ZGV2eDlicDE2cEcvSC9yMDdvWHdpREFoQnZPeTRXSG9saTFib2xVcnk4VjY1ZUdnUUc0ekg2TWlWSU0vRmxlN05sNzh5d3ZrbjRTUS8yR1lyOFJXaFN2UTY2Ky9pV1BIajZ0SC96NTRzTjBEYU5PNmRjbFF0d2FmTzA4clNSa3lDSUZXbnJ0ZkhuWUxoSzkzdFM2TmRTTllHdFhWbExTNHF3WCtPR2tDWFMvRFZqOHNFckYyNHRkZnhiNVFya25wbHJFc2VCTzgyckd4SnRhRDMvTUFCY2YzN05GZGpiVVB1NXgwZGk1OUlpSlFxMTh2Qk1UVkZqdDlTRXFIeGNHRmUrck4yV0xlR0UrN1lTcmlwTE96MmJCQkF5eGV0QkExYTBTTHVOTGdUYStuLytWRnJGcTFpdndXUSt2Smw1eGJXdDRIZCtLRUo5UllVMngxMHErbnArUExMMWNqT3lmYjZnaVNyWEIrV2ljbmkyRllSemg5K2d5ZW1QaEhuRHA5V2pRQzNCZ29EUVB3N0ROUDRha25KNmxIMm9kOUFsRVA1UVZEOUsvNFgxSUdwQkF1TXk4L1AvSEtGNDJwS29Fd3g0K2ZSTXFJRVNTV1crSm1HdWVCODhLYnBFV0VoMkgrTy9PUW5IeWZlclFCV3dWeTR1UkpEQjh4R2xmUzBrVEZkQVR5cUpDZmw0OW5KL1BtMVZQVldQdVlQLzhEdlBhR1loVzFBUW9ldVV0TVRNQm5pejlGWEZ5YytNeGU3Sks4ZG9GNU4wTHVabm40eWxCbW9ETGkzZVdOeFZIVk5HN2NFTk9uVGhYOWNHNVJHYzRMVDVOUFQ3K0JWLy81TDJUd2Rrc093cFdScDNhd2dCME82dmU5ckN4K3N3V2V2Yng2N1ZvU1JKRkpPZk9vMXJBaFF4d1dCK09BRDJLWVRTcUQ3Y0ZoMkZDVHdMUWdvdXkwM095Z2N1QzFGOGJwY0l1Lzc4QUJMUGpvRS9HM28xZzdYMGVESSt6WTlTTitPZm1MYUFTME5MakxGaGtaZ1Q1OXpSNXRZU2VPZHhvbFZZRGlZSnNIM2lwSnErUzJ3RUo0Y3RKRU5HdldSRlFjUXpyRjR0RUZzK2UrUTM2SzVSSmpkNENuM1BDTVplNythVDRRbnhldjJlL2NzU1BxSk5sKzE5d2FwUXFFKzhuNjNEd1U1ZWFnS0VjR1p3WmRUcTZZdjhXT2UxbjQrdmloVmt4TkpNVEhJVDZ1dGhyaUVFTng1cy9TS0kvWTJGamhyUEtHQjd6UHJaWmVRbnc4WW12RllPbnlGY0xoMXVDMTV2ejBLTzUrYVlIM3dPVit2VEU4U25UclZwYkpjWFlIL2gwS1hObnRaZSsrL2RpK2M2ZG9CRFRyd1hrS0RRdEQzMzdXdHpLMWgxS2RkRjdiZlhyZWZPaElJTnJvaThRNThNeFZEK3AzTjNscGhuZ01YV2tVVUdYTXpNZ1VyYjUyOGZseThZTmVvaUlqSFJvMVN1TVZrV3c5NkwzV29XRW5tWmZvUmtWRmxrd1kvRzdiRHpoMi9KandEeGcrWHE4clFzL3UzWkJVeC9Eb00xNlV0SGI5QnVTUThEM1ZwelRaQzZmTlQzYmlhZlBKOTFrT0dKVEZtRWZIVWw2M2k0MFh1SXk0ZkFySW1uU2pmSDd3N2p5cno5RzNoMUlGd284cDBCWFl0dCtweERGNHN6eDNiSHk0eWpqcUx6aVQ0eWRPSUdYb1NHU1JCZE5HMExqcnlNOWhYTEg4TXp4d3YyMFRNOHVpZElGSUpDNE1DK0Z2TDcyQ1JVdVdtRXpLNUdIdzFtMlNzV0xwRXZYSWlpSDdUaEszSlBWeUtuYnMya2xDTWJUdi9KNjNJZTNUczVjYVUzR2tRQ1J1eWVkZmZDbWVzT3ZEOStSVTY4R1RNNXMyYjQ1ZXZSeWJWbUlOS1JDSjIxRklEdjJ5WlorTG00dU01aFB4NkZXbjlnK0szUmVkaFJTSXhPMzQ3OEpQY2VuU0paTlJQQlpIamVob0RCOW0rWGkvaWlBRkluRXJlRnJKeG8yYnhYdHRKRTEwcjhnNUgvQlFmMFNUU0p5SkZJakVyZGkwK1J2czNiY1BPcjFlM0IvaXdIZlI0eE1UTUx5TXh4ZzRpaHptbGJnVi9JRFM3VHQyd0pObkpxdTNPdlBKZWp6UXJoMmVHUGNIK1BvNjkwRk1VaUFTU1JuSUxwWkVVaXJBL3dGQXpyZ1dXbmQwakFBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wMi0yNiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQXV0aGVuVHJlbmQgVGVjaG5vbG9neSBJbmMuIEFUS2V5LkhlbGxvIFR5cGVDIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAxODAyMjgwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDItMjYifSx7ImFhaWQiOiI0ZTRlIzQwMGIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhaWQiOiI0ZTRlIzQwMGIiLCJkZXNjcmlwdGlvbiI6IlRvdWNoIElEIG9yIEZhY2UgSUQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MjU2LCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9LHsibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjowLCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmYWNlcHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbImFueSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFZ0FBQUJJQ0FZQUFBQlY3Yk5IQUFBQUFYTlNSMElBcnM0YzZRQUFBQnhwUkU5VUFBQUFBZ0FBQUFBQUFBQWtBQUFBS0FBQUFDUUFBQUFrQUFBRkpidUoyRWtBQUFUeFNVUkJWSGdCN0pZeGJpTkhFRVVGSjE0WUM1akpBZ3NuSHNPT0hQRUFDMmh5QitJTk5LRXpNblNtdWNCaWVRUHlCbUxnbkx5QmVBUFNKMWplZ0g2ZjZocVV5OVBhWGcwSk8rQUFYOTFkVlYzOS81L21RRGZINC9IbWlyd0hWM08rY0VHdUJsME55djk4U2o0dDF4dDB2VUhYRzNUUlg4R2c1amNEbjU5L3JMNERIOEFNYkJ4V3pGdndHM2cvOEpoaEdrcytWTG1hMXhKSDlBVEloR01oWkY3ejJ2TnkvRXZpdzl6OVNzYUlyTUcrMEpRKzg3UjM4cFhIRHROWTRtS3VwcFFvb2taZ0hveFpzLzRFcHVEMkJTaXZPdFdiYWJwOW85THpjL3hMNHNQY0xXQ0lrQXBzd1djZ29iZDkyNGlycm5ZWXh6cHlNdm9PTE1CZjRGODFjWS9XSlVia2FvWnQ3bVBqWWhJQS9nUjNMbnpEV21iTXdBcnNnZDJNdmxINURXaEJad2h6bWZVNytOWDM3cHZueEpmRUwyWVF4TitERDBhWXVRVEpsQzNvTTZJMGRtRC9IRlN1OXp1Yjk0MGxSdVJxTG1JUTVMODFvaElDOVBZbHJOU0UwanJkckZwbk1YNWpaOFl4Sjc0a2ZoR0RqQ0NrWnlCbnpJN2NBa3pCTGFoc240MHBybStPdmwxUElHZmNpdHdQdGkrT0pVYmthaTVpRUdUSFlOc2o2RE14aWUyK0pWSE1TMnYyNlRaT2djeU5adWxGOVBiTmlTK0puOTBnU09vL1k1SDFBbVRNQXhoNUE3UUdOWmlCRnN6QkJxelNXckVKcVB3K3pZbmRneDA0QnZ3VWEwdU15TldjMVNDSXlweEkrSkZZWmFTWmowQURaRVNzZldtOXAzNEphdXVsa2JWdWxGNkE3ZDM0dk9ZNThTWHhZWnNkRXdpK2RTUkZWcVFiVnlJeExUZ0FFL1BhY2U5N002L0FrK3RiKzNOTGpNalZuTk9ncFNNb2M3cnZnZVpnNi9MUm1EVTU0Y0hoTWNYVTY1aUJqT3JNWVA0cDFXMytWd1pCNnZ0RVRFSWt5SnZUc0k2M1JqVUwwUHRmdFJlbnVmcUJLWGdDZldiTmlaKytiNHc2VHpXMTljbmRqcEw0V1c0UVpHYUpWSjg1VVpDTStjZkgyb1JvbERDRGo5dWNuTXhhZzloM1M4eWJ0TFE5SlVia2FzNWxrTWlKY0dPa05FOHhFeUx6YXN0clpEMUtkU3ZHUGJCYVB4NklLNjkrbmJITWE3QURzWGFjZW5mMU9mRWw4Y0VHUVhDY1NENmFlTllpNTRuSG0xV1JYNFlhWDUrYnl5enRxNUlKSSthTDBFYzFadEl2cWlzeElsY3piRE9IUTJZRzlHMnc2ejFtN2dWR2MxUXZFYjdtTmZOVzR2WFE2eUgwMjdQdWJsdE9mRW44SEFiTmpReWp6UEhpb3psNis5RU0xU3pBSFRpOStXZlpKK0ZWaWl1dnVyaDNROHhlVEJQeUcrdFRZa1N1WnJCQlJrSkV3VGFRN0FRVGx4Z3ZVSUx2UWZlbW1jdmdHV2dUYXV1dmtaanFvMUU2MDB4YU1QZG50TnFYRTE4U0g3WlpwNmNIWXRHY3h1V1dnZmlqaVZJTjh3blloeG92VlB1clZEdGlydjArNzAxYWg5emJFaU55TldjeENFTFJnRlppOUpDYkJjS0w1OHp6MzU2OVhuaWN6MjB2KzZhaDcwWTVZakxRMzdJbUo3NGtQc2dnaUx3QksrQ0ZkQVlRYjBMdWliWDlIQ1JrRy9McW81cDFnaGRxWjJpUDlZajlUd2FTOS9GTmlSRzVtcUVHZllTTUVkZm96Um1IM0pmTVVYNXNOOFJHWXZkZ0YzcDVreFloZCtwQmJKM2kvNmxCRzBjdW1uTndPZDJFVGp4ekNUdzYrTDBWOFNWUTd6blFlZ1NpRVZ0bm9zeTFmcWM0NjdIRmNyZWpKRDcwQmttRWlEMDRzaUoyTUhLTTBSeUpOekVhdlRsdHlGbGRvLzZxRGZsNWluZG1wTHpWcjdVdU1TSlhNOVNnUHlCUWlhUWU1ZzN3NWtoZ2Mwbys1NWVzVGJSR2IwN00rYnF1ai9hRUhyWDZFL1A3OXlsV3F6WW52aVEreUNDUnNBY2k4MEJjTjJmaThsNUFOS2NOZS9XVGVRQzdFQitySDdHK24xUVZhazlucTdiRWlGek4zd0FBQVAvL1g5TGxQd0FBQlBOSlJFRlU3VnE3amlOVkZCd2tKQkNzdEIwUUVleTJJR1NEenBhTURzbldNY2wyU0xDU0hSQnNOdjRBeERnaVFuTC93WFJBUGkzeEFUYjhnUDBIMjM4d1ZMVlBtZG9yejROeDBHM0pWNm81OTlZNTUvcFV6WjFaYVRVWHQ3ZTNGMC9GQmRhM0wvTUNXQU8zaGcva21lZkNmbVk1MXEyQUxITFZQYmtzYW5YM2xuMUFrZlJVY1ZkdGZCUGM3S242MlBka2M5aU1ZZDdaUUJKQjhUbUg0OExlaDA3Tm9kRE83dGdidCt2ZWZ3Tm91TzVmSExoM0cxeHFYSTYrZkVpRFdodWNBcTZBL21VY0VQR1FPVFNCZ2lZQTd5WG1RQlZSQmpIbUFlY204WmswV2Z5TTNKQUdOVEhNQnJIa01GellaMEFiT1EzTHdYdnpFUG1kN3BKOEdiMnF2eS9XVVZ2YkhVMXdNK05hY2tNYTlCN0RYSElJTFp4TElCWHY1bFFIOHBYMTh5WGRaNDV5ZVh5V3pvd1pVQ1Q5ejRZMDZETVR4b0diWkRnT3ZRVDBjbWlPQzZJWkU5M0JpRFB2bVFLWHdCV3dBYnhIKzBYVWU3Ni9LK2w1UFpoQkpxakdVT21yb1pBcGE3aXdaNDNFTWRLY1lwZTkveXZxU21BRmVQK1dYZUQ4WHBubVhEbVlRUmp1eTJSb0NhQ1lYanhpRHF5VHVvL01RVzRDVUZScjRHdXNnRXoyWWI4RTlCbjRON2czaURYaTFzSE5qQ3NHTXlpRzJkZ3dGUDZXUEJmMkhMU3pQSVhRdkY0MFlnbHNBUW04S3k2c1p4bjFxL2lNM1B1RDQ3MjZLeHZhSUE2L0Fkd1lEdGpha0JyMmlnSzRrR09mK01mRU5lcjdWN203NGIrdnlUMTlUWEM5aVVNYjlGeWpZcWk3ak9ITG1saGRuWWpxRFFhWHN3WXhBOTRBUzhETjY1alRQWXJnK0NwVlY1SVBic0g5b0FiRk1EOWhJSDZITmFUSEpmaTlLT3hUYy9hdmluZWxDL1VsUUlOMVozdWdwclY4eVR6TzVBcnV4MkJRYlFOS3lBMjRrZ055WWM5WHdhR1ZaNno2NUM1ZjRkeEVEZVBFY2dYT2J0SytqelhSbzN0bndmV1IrekVZVkdKSURYaU5mY25CdEhDZUFKM1Y3TTBCbHdHcGNicXJZWjczSVBJTzhWdmRIVG52bndkWE1uSU5iaENId1BDL0FEbjNXamlYZ0E5UGdYd0pGV3NRYWM0YWtQQkRzV1l0RitwdXJOWmZtSDlHRmJYUEdMbEdZZEJ1bEY1RUFSRUxZR3RpSkh3RnJtQXRZbW9PalpzQ2VVVDFNSmJSVTJFdmZrR09DMXhyZk5tVDltVTBCbUhJZjJ4UUNXSHN4V3RtbkduaTJtcVo3NDJ6bXBubEcvSTQ1OGExVnJzMXZoU3ZPQ2FEU2h1VXhtd0F2b3BNdzJJL0FUcEFCdTdOQWNkK3IyV3VyN04rOVhVSE9PWStGNjg0R29NNEVBYjhEYmdDQ2cwWVBNVzNnQVF5dWpsMTVGeTQxK2R4ejc3ZjdoWDNON2wwamNvZ0h3NkNDNEEvS3VzUUx5R01LeUJuUFNKclBOZS9JbkJ1VUlZem9ibzJldWZHdlNLWHJ0RVpoSUZmQVZzYlhLSVkrV3FtRW9GOWxkVE5tUVBuWm53SWJtSzFUWERyNEJZOEgxcWpNNGhEWXVoVStBYmNKZEMvanFpWmhUZ2FSeXdsRVB1NTVlcW9yNDFqYng3bmEvVWRpcU0wS0FUOURBSDhmZlRHQjhjNUF4cEF4cVRtRkVtdWpKN09lSm96Qi9panVqZmRQMGY3MFJxa0FSVXBKRVM1ME5RYzFtd0JtZGUvRHB3WHhqWFlzKzVQUnQxL1Z4eTlRUkR4QXZnZDZBQUpWNXhLR0hJVXZiYWFUWENGY2V6amkvcFJmUS9GMFJ0RUFSQ1VBemVBak9FK2x6anNhVUpuZWY0eUo1Y0JhK04veGY0TDlUMG1ub1JCRWdKeHI0SHZkV2JFZVFiSU9FWTNwNDBjdWVrM0wxNSs0cjJQMlorVVFTNElncjhDL2dnRFpOQUdaNzJjdjdDL0J0NEN6NzMzLyt4UDFpQ0poSGorR1AwQWZBZDhHdmhhK1dQallBWWQ4OEduMG52VS81V2Npc2hqNWp3YjlNQ2YvNXdOT2h2MDlEOFE0NC9tK1FXZFg5QnhMK2hmVXdUWXlSQ2FyWjhBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wNS0xOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTgtMDUtMTkifSx7ImFhZ3VpZCI6IjlkZGQxODE3LWFmNWEtNDY3Mi1hMmI5LTNlM2RkOTUwMDBhOSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiOWRkZDE4MTctYWY1YS00NjcyLWEyYjktM2UzZGQ5NTAwMGE5IiwiZGVzY3JpcHRpb24iOiJXaW5kb3dzIEhlbGxvIFZCUyBIYXJkd2FyZSBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJyc2Fzc2FfcGtjc3YxNV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYXR0Y2EiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmFjZXByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImV5ZXByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInRlZSJdLCJpc0tleVJlc3RyaWN0ZWQiOmZhbHNlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJ0ZWUiXSwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUY5VENDQTkyZ0F3SUJBZ0lRWGJZd1RneS9KNzlKdU1ocFVCNWR5ekFOQmdrcWhraUc5dzBCQVFzRkFEQ0JqREVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENsZGhjMmhwYm1kMGIyNHhFREFPQmdOVkJBY1RCMUpsWkcxdmJtUXhIakFjQmdOVkJBb1RGVTFwWTNKdmMyOW1kQ0JEYjNKd2IzSmhkR2x2YmpFMk1EUUdBMVVFQXhNdFRXbGpjbTl6YjJaMElGUlFUU0JTYjI5MElFTmxjblJwWm1sallYUmxJRUYxZEdodmNtbDBlU0F5TURFME1CNFhEVEUwTVRJeE1ESXhNekV4T1ZvWERUTTVNVEl4TURJeE16a3lPRm93Z1l3eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BYWVhOb2FXNW5kRzl1TVJBd0RnWURWUVFIRXdkU1pXUnRiMjVrTVI0d0hBWURWUVFLRXhWTmFXTnliM052Wm5RZ1EyOXljRzl5WVhScGIyNHhOakEwQmdOVkJBTVRMVTFwWTNKdmMyOW1kQ0JVVUUwZ1VtOXZkQ0JEWlhKMGFXWnBZMkYwWlNCQmRYUm9iM0pwZEhrZ01qQXhORENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFKK24rYm5LdC9KSElSQy9vSS94Z2tnc1lkUHpQMGdwdmR1REEyR2JSdHRoK0w0V1V5b1pLR0J3N3V6NWJqalA4QXFsNFlFeHlqUjNFWlE0THFuWkNoTXBvQ29mYmVEUjRNakNFMVRHd1dnaEdwUzBtTTNHdFdEOVhpTUU0ckUySzBWVzNwZE4wQ0x6a1lidlpiczJ3UVRGZkU2MnlOUWlEanlIRldBWjRCUUg0ZVdhOHdyRE1VeElBbmVVQ3BVNnpDd00rbDZRaDRvaFgwNjNCSHpYbFRTVGMxZkRzaVBhS3VNTWpXaks5dnA1VUhGUGErZE1BV3I2T2xqUVpQRklnM2FaNGNVZnpTOXkrbjc3SHMxTlhQQm42RTREYjY3OXo0RFRoSVh5b0tlWlR2MWFhV09XbC9leHNETEd0Mm1UTVR5eWtWVjh1RDFlUmpZcmlGcG1vUkR3SktBRU1PZmFVUmFyenA3aGthOVRPRWxHeUQyZ09WNEZzY3IyTXhBWUN5d0xtT0x6QTRWRFNZTHVLQWhQU3A3eWF3RVQzMEF2WTFIUmZNd0J4ZXRTcVdQMit5WlJOWUpsSHBvcjVRVHVSRGd6UitaZWorYVd4NnJXTll4NDNrTHRob3plVkozUUNzRDVpRUkvT1psbVduNVdZZjdPOExCLzFBN3Njcll2NDRGRDhjazNaK2h4WHBra2xBc2pKTXNIWmE5bUJxaCtWUjFBaWNYNHVaRzhtMTZ4NjVaVTJ1VXBCYTNybjhDVE5tdzE3WkhPaXVTV0p0UzkrUHJaVkE4bGpnZjRRZ0ExZzZOUE9FaUxHMmZuOEdtK3I1QWsrOXRxdjcyS0RkMkZQQko3WHg0c3RZai9Xak5QdEVVaFc0cmNMSzNrdExmY3k2ZWE3Um9jdzV5NUFnTUJBQUdqVVRCUE1Bc0dBMVVkRHdRRUF3SUJoakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI2akFyT0wwaGlGK0tVMGE1VndWTHNjWFNrVmpBUUJna3JCZ0VFQVlJM0ZRRUVBd0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVc0aW9vMStKOVZXQzBVbnRTQlhjWFJtMWVQVFZhbXRzeFZ5L0dwUDRFbUpkM1ViNTNKek5CZllkZ2ZVTDUxQ3BwUzNaWTZCb2FnQitEcW9BMkdiU0wrN3NGR0hCbDVrYTZGTmVscndzSDZWVnc0eFYvOGtsSWptcU95ZmF0UFlzejBzVWRaZXYrcmVlaUdwS1ZvWHJLNkJEblVVMjcvbWdQdGVtNVlLV3ZIQi9zb29mVXJMS3paVjNXZkdkeDl6QnI4VjB4VzZ2TzNDS2Fxa3FVOXk2RXNRdzM0bjdlSkNiRVZWUThWZEZkOWlWMXBtWHdhQkFmQndrdmlQVEtFUDlDbSt6YkZJT0xyM1YzQ0w5aEpqK2drVFV1WFdsSko2d1ZYRUc1aTRySWJMQVY1OVVyVzRMb25QK3NlcXZXTUpZVUZ4dS9uaUYwUjNmU0dNK05VMTFEdEJWa2hSWnQxdTBrRmhacWpEejFkV3lmVC9ON0hrZTNXc0RxVUZzQmkrOFNFdzkwcld4MmFVa0x2S284M29VNE14NG5hKzJJM2w5RjJhMlZOR2s0SzdsM2EwMGc1MW1pUGlxMERhMGpxdzMwUGFMbHVUTVRHWTUrUm5aVmg1MEpENm5rK0VhM3dSa1U4YWlZRm5wSXhmS0JaNzJ3aG1ZWWEvZWdqOUlLZXFwUjB2dUxlYmJVMGZKQmY4ODBLMWpXRDNaNVNGeUpYbzA1N012ME9QdzVtdHR5dEU1ODVaSXk1SnNhUlhsc09vV0dSWEUza1VUL01LUjFVb0FnUjU0YzhCc2grOURxMndxSUs5bVJuMTV6dkJEZXlIRzYrY3p1ckxvcHppT1VlV29reFpOMXN5ckVkS2xoRm9QWWF2bTZ0K1B6SWNwZHhad0hBK1YzakxKUGZJPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFZ0FBQUJJQ0FZQUFBQlY3Yk5IQUFBQ2tVbEVRVlI0MnV5YWkzR0RNQXlHUXllZ0d6QUNuYUNNa0JIb0Joa2huU0FqMEEyU0RhQVQwRTZRYkVBM2NPWFc2WEVwQnRuSW1Ndjl1dE9sbHhqRi9xS0hMVGRSU20wZ2Rua0FBZ0FDSUFBQ0lBQUNJQUFDSUFnQUFSQUFBUkFBQVJBQUFSQkVBRkNTSklOS2twTHVTVHRTWmJRejc2VzI1emhLa3BGV1BidGF6NlE3NXZQdW9sdXVQbXF4bFpLMnlpNzZzOVJ6bmpscE4ySzdDckZXYVVBSE5TMEhUMEF0dzNZcERTanhiZG9QdWF6aUczdWs1NzljdklkZVdzYlFEN0w3TkFZb1dwS21MeThjaHVlTzVyZUI3S0tLclFuUUpkRFluOUFKWkhjNVFCVDdlbklOWTJoanhycUl0c3ZKV1NkeEZ4S3VZbE9sV0ptRTZ6UFBjc0p1TjdXRmlGN21lNURPQXdzNE95WnlHNlRPc3IvS1F6aURhSm0vbWN5MlYxVjArVDBKZVh4cXFscldDOW1HR3kzTzZ3d0ZhSTBTZFIrRU1nOUFFQUFDSUFCeXFWaVpiKy9wcmdGZE42cWIzMDZqM2xUV3MwQko3NlFqdzBrdE8rM2FkNjBQUWhNcmZNOVl3cUs3bFVQZTRqKy9PUjQwY0RhcUplSit4bzgwSnNXaWgxV1RCQWNiOHlzS3JiK1Rmb3dRS3kzdjU1d2JCa2s0OUZKYlF1c3FyNHNuYWRMOWhFdFhDM25PMUcxSEc2VWZ4SWo1b0RuSmxIUE9WVkFlcldHbXZZUXh3YzcwaGlUaDdCaWR5My8zWkZFNmlzeGY4ZXBOaFVDbDRuNWZ0WXFXS3pNUDNJSXF1YUZucXVYTzBzWjF5bi9SV3E2OVN1SzZHZFBYT1JmU3o0SFBuazFiTlhPMCtVWnplNUhxS0lvZE5Zd25IVlZjT1Vpdk5jU3R4ajRDR0ZZaFdBV2dYZ211RjRKemRNaG42d0RVbTFEcG1GeVZZN0l2UXFlVFJkb2QydjJGOGxObi9nY3BXK3JVc09pOW1BbUZ3bFNvM1B3OUpRM3ArOGJoZ25BTWtQTTYxM0J4T0JRcWMyRkVCNFNtUFFTQUFBaUFBQWlBQUFpQUFBaUFJQUFFUUFBRVFBQUVRUGNvM3dJTUFET1hnRmhPVGdodUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiI5ZGRkMTgxN2FmNWE0NjcyYTJiOTNlM2RkOTUwMDBhOSIsIm9wdGlvbnMiOnsicGxhdCI6dHJ1ZSwicmsiOnRydWUsInVwIjp0cnVlfSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMDAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MzIsInRyYW5zcG9ydHMiOlsiaW50ZXJuYWwiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjE5MDQyfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMDUiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IldpbmRvd3MgSGVsbG8gVkJTIEhhcmR3YXJlIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDQxODAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA4LTA1In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wOC0wNSJ9LHsiYWFndWlkIjoiZDg1MjJkOWYtNTc1Yi00ODY2LTg4YTktYmE5OWZhMDJmMzViIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJkODUyMmQ5Zi01NzViLTQ4NjYtODhhOS1iYTk5ZmEwMmYzNWIiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgQmlvIFNlcmllcyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg5NjUsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjUsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjo1LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsImNyZWRCbG9iIiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6ImQ4NTIyZDlmNTc1YjQ4NjY4OGE5YmE5OWZhMDJmMzViIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInBpblV2QXV0aFRva2VuIjp0cnVlLCJsYXJnZUJsb2JzIjp0cnVlLCJiaW9FbnJvbGwiOmZhbHNlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOmZhbHNlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6ZmFsc2UsImFsd2F5c1V2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjEwMjQsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjg5NjUsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsInByZWZlcnJlZFBsYXRmb3JtVXZBdHRlbXB0cyI6MywidXZNb2RhbGl0eSI6MiwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjI1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDYiLCJ1cmwiOiJ3d3cueXViaWNvLmNvbSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSBCaW8iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIxMDgwNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjQifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA4LTEwIn0seyJhYWd1aWQiOiI1MGE0NWIwYy04MGU3LWY5NDQtYmYyOS1mNTUyYmZhMmUwNDgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjUwYTQ1YjBjLTgwZTctZjk0NC1iZjI5LWY1NTJiZmEyZTA0OCIsImRlc2NyaXB0aW9uIjoiQUNTIEZJRE8gQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxMDAwMCwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9LHsibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNRVENDQWVlZ0F3SUJBZ0lVRi8wd1RQUDZGRXF4cHNpYkppTEZ0RGo0cWh3d0NnWUlLb1pJemowRUF3SXdkVEVMTUFrR0ExVUVCaE1DU0VzeEVqQVFCZ05WQkFnTUNVaHZibWNnUzI5dVp6RVNNQkFHQTFVRUJ3d0pTRzl1WnlCTGIyNW5NU013SVFZRFZRUUtEQnBCWkhaaGJtTmxaQ0JEWVhKa0lGTjVjM1JsYlhNZ1RIUmtMakVaTUJjR0ExVUVBd3dRUVVOVElFWkpSRThnVW05dmRDQkRRVEFnRncweU1qQTFNekF3T1RJek16VmFHQTh5TURVeU1EVXlNakE1TWpNek5Wb3dkVEVMTUFrR0ExVUVCaE1DU0VzeEVqQVFCZ05WQkFnTUNVaHZibWNnUzI5dVp6RVNNQkFHQTFVRUJ3d0pTRzl1WnlCTGIyNW5NU013SVFZRFZRUUtEQnBCWkhaaGJtTmxaQ0JEWVhKa0lGTjVjM1JsYlhNZ1RIUmtMakVaTUJjR0ExVUVBd3dRUVVOVElFWkpSRThnVW05dmRDQkRRVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQndZZ0tWd2pDVjYrbHY3Z25wRkVSelUydU5EOGdkRWtQQ05jcy92RkRzMnNLNDJKdXhuaEZuSWdNQjJEeVUwSXJYSUxqZi8yWFQwWVNUZDFzUGlUU2FqVXpCUk1CMEdBMVVkRGdRV0JCVG5RYXJwZFN0NHNpZDdWamZOSUxJSHJiMlBvREFmQmdOVkhTTUVHREFXZ0JUblFhcnBkU3Q0c2lkN1ZqZk5JTElIcmIyUG9EQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRRGNvWEozcnpOTUEvZlpraDA4UG9Gck14NDNHWU1oWk1mTFB3LzNNZkpwR0FJZ2VjdEt3bUpZTTlKOFNYOHgvYVFWNGlHdktXb0JmcjFYUFRBTVhPaFZFWUU9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQURBQUFBQXdDQVlBQUFCWEF2bUhBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRHNRQUFBN0VBWlVyRGhzQUFBaWNTVVJCVkdoRDFaalBpNVZWR01mOUM5b2I2REpvSVFpMWlEQndJNVFnRVVFbHRCSjBZU0FHRXVSQ0ZCTXhJa2xDYXlGSVFpYUtCWlVvbFk3UU5KTTYzbkdhY2E2ajQwdzAwNHpCTUJPNkxFN244OXo3UGZPODV6M3Z0ZHE1K0hMdWZYK2M4L2srNXpuUE9mZXUrUHV2djhMakxEUFFHaDRPN2ZIeDBHb05wODlWdGEyZG5KeXNhWHA2S21sdWJqNjEwdno4WEZoWVdDaHFjV25SdExTNEZCNCtmQmdlUEh4ZzRyTVhqTDZWRGg0ODJEWFFCVTlHWWp2ZWJpYzF3UXU0QkErNFBzL096amJDbXdGbjRyOG9HUkIwSjlvZEpmaDJIWDRxZ2lJUDd3VTgwS1hvZTNDRGZ3UjRIbldKbWVwcG9LTjJEWDU2cXB3eXRBRFB6M1VpM3dzZTZQOEw3bFV4a0NzSFIzblVCYzFucVFUdTRiMkpFdFMva1FKUU54RFRoYlFwd1FOSDYrSFZDcHJ2dE14Q0RrK2VMeTVWb1h1WktNMkFuaThhYU1wM2c0NXBZMjBHajRCVnZ1ZlI5OUdXUEVoSnZWTEg5ME13c2hub0hYa0JlM2d2RDU3RE0xZ3ZhTlFMSEZYaEYyMk1aQ0NIUm9CNkFWbUN6OU5Gc3RMWU5WQ0N5YStWcE9jRVRuOStqRVlET1RpTDk5K0NsOUlHNVhDS2VLL0lWL3JvOXV2SEtocFFtUVN5R0hHWDU3TS8vQkJtUHZzczNOdTFLOXpidkRuY1diZXVwcnN2dkpBMDhlSkxZV2IzN3ZEN29VTmg0Y0tGOE9mTVRCRzZCTy9CcFpvQmJWQytYR3B4b3RscjE4TDAvdjBHTXZyRUUyRjB4WW93K3VTVEJqcjY4c3RoZFB2MnBGLzJ2eGR1ZmZ4eDVSb2FmKzY1TVBiMDA1MTNvOXFyVjV2NSs2ZE9tU0VQTGZDU0FRcEh4UURSVlZ1SmVFeVZYOCtlVGRDMGQvYnNDYTFQUDdValNIOS92N1dxWkQ0SURESTNUd3BPbStpUDY5cmxoejcvUEF6djNkc3hId09Cb2VrMzN3ejN2LzIyWXFBRVQxc3g0Tk9HQnhEZ3Q1OS9QdHg5NC9Vdzhja3hneHc4Y3NRaU9mTHNNNVk2OTYvMGRRYUxVZk1wNE1VWVhLZk43NUhYakFVRGhxNisrcW9GNnRhcVZXRW16cUNnbGJxMEJJVjNrZ0dCMHdyZThqb0s2TlkzMzRTYm16Wlp4N2ZYckFsM1B2Z2dUQXhkdDNzTVRLZWErZzVVM1lTWERPbTcza1ZBRHJkYVlYanJWaHVQbEpzZkdyTHJZaE5uTXBCSEgwQmV1dlhkZCtIV0s2L1kxSkxuWXlkT2RFK3VMWHVlVGoySTVBRVZkVjN6OTJoejBhYzBFdE56WlAxNk13SVQxeGdYa1lxVkdaQXd3SU8yNkNJNEVTRGZCd1lIREp6N3lrOEdGQWl0cE84ZU5yL3Z4WGhOK1E3VHpaZ0pzSXdkT0pCbUFCVU5MSTZOcFFVNy91Njd0a2hKRmJzWEIxR05KMjJtMzNrbmxVaEtvOG9pZmQ2UHBsVmFLWjFMc1Y4QnMwaC9qUUhTUGNiTXdlbGZZbXlxbWkzeWp6Nnk3MlJMeFFBUDhxS1Z1RmdSYnA0K0hRWmoxTWx4cmlmNEtFQlpDM1RveFRVQVMvY0lDQXNlVTdWN1VVb1J3VnNiS3lCc0FyYXNpUDJ3UnRpdktnWjRvYjFsaXowdzFOZG51YzUxSDNYZ2lUQ1IxOEEzTm00TXd3Nks2cVRQcmJWck8vZGluM2F0V3lyVFBSYXFyc1ZuVkJDOFpDQ1ppTThQdnZXV1Bac01BTThtUlVmdGt5Y3Q4bHdUdkRlQkFhYWZ0VUZFV0JkMFp1YTdjR2prcWFmUy9zQzBtekVIYThVZ2lwbkdDQ0pkYytDOHRUMG9tdWZkaWdHbWx0eFhKOHZnbmRPa0ZxRDAyOHh2ZHZ4bVVaVlNDbURnRjd0NVQ1OFVBOTJuNWpNdTRoN1BhcTE1Q1o2cVE2QW12emhsNzhOWk1VQjBXT1UycUl1NG9wNkxSY211bWRJalV6TFFQVXFqaFFqaG4yZTlFYlRmdi9xcUNDN3hIWGhhTW9SM0wxMjZsQm1JRjRrUUQvbDBVZDduOEUzZ0V0T01BZnEyV2NSQS9Nd0IwSzhGaVVVc2VPVEJVL1NqT0JIdy92bno1NWNOQUV3bjE0OGVzNVF3eUliSTg3eEZub0V4d1RxSXhtMm5ka0NhQWFCekFjYVI1T2RZcGxrcjZrc3BwR2o3Vm1KalphektER0NBbW56ajdiYzdHMVVEdkVUZFoxQXFEUDltY0ZEajJGRXhFTUZrNEkrNDRFZ1RpVE1XMXltRjdPNTZoN3dtMmtBekEvVHI0WlUrbUw5OHVXL1pBR2xpcFRGT0RTK1hEUENjUGsrODlscG4wUGo4NUpVcnRoR2x0SENwUllVQnZyUXZrRElZU0gxRkVWVWY4YW1wWlFPY3ZSaGpmTU1HUzU5S0ZRS1lTc0xnYk51UG1nRitqSGdZTDlLaWFYM29wTmwwRHdNR25rVWVlQlk4cy9yOXVYUDJITE5iTVFBWTJ6K2RUWjg1VXdIMjBaZjRKWmFpSGpXeWNxWEJFNWtKTnNLNGlIVVBhQUJKRVdZbHYwY3FBc1c3SGh4WjJzUnhNQ0I0bmlOMWF3YlE1TFp0MWpHYmp3Y3VpZlZDSkFDelRyc0FXcWg4NTU2a1V5elA4QjBZcVFZZlUxTW5ZVXViYVB6aXhZc0d6cGlWR2NqQnlFOWVwRWFUMy9sOWhHbUpJcUFLazZ2cFNLQ1dkYUJmYkRrNGxZd0ZDL3hQOGFjczBBU0JkamkyeFJsQVhLTmUyM0VoVGpFTHZQSjcxWWthWDRPT2NFQXpRNUxnVTVYaHp3T25lL3YycGZFd0lIRFNpN0xKYndObVRTWXFCank0TjBKazJaMHQxMlBIOXVPYjM2c040Qkx3dElMMkVhZjFhY0laaUJTWjJMblQ5aE5McWFOSDdaREl1QnlqbFc0R0gxTU5lTnJHRk1wRkJHOGUvckR6NjZpNzhERERiMWFPeUI2ZVp5MXQzRkZZQWpwdjBkVXZ6MWtCRURUQ1dOL1hYMXZKeEFEUUV2QTFBNzJNS0YwWWxLbThmdWg5R3l6dG9sRnNoS3daL1pZbUpkaXd2RGhKRW1sRTFPMkUybjJmdmtpWC91UEhEVnJnZ09hUkx4b29RYXROY291VnlLbGpIUXVJbXVWckJKUElhLzlkNHRtck8zYUVIdzhmdGx3SG1DckREaXZBbE8veEI0eXVTUno1SDVsQ1RmQmVXcXd5cENnUnZaTElaU0RSd09DZ2llY1ZERnBKc0Y2QTYzTXlBS0RhR25oVUwzQmE1VGpTUWtWNXJudlozL2tPMWd1NFBGMlE0QWxFWlFZRW5rZWVLdFJVNC9OS2cvSXFreDhKSlAwelY0SHVibEFHM2dNZVlZQzJaa0RnZ3MraFU0WHBpdStvWk1BYkViUmFEOTZCWDk2Y2VzRXI4dnBjTWZBb2VFbXdBdmMxWHZLblNLODYrSExPRzNnQjN2NlA2Z0tyeFFUWGl3YnlEVXFwb3FqTGdJZEhBS3JOMVRQZkl6U1JMMVdhRXJ4YUZuL05nQWYzS20xS09UemZjM0NVNTd1aVRpdlFrcG9pVHl0VkRKVEFnYlBJWndZRUQyQVR1SUNiQkpUYVhMM2d1VmN6a0lNcmJaQUh6K0h6MWdzNHRRYXF5RWNnKy9jNVN4c3RUcjlJMVE0TURDWm9yMFlEQXM5ekhsV2kzM094bHZNZUtMVWwrZWlUNTUyMm1qcFNNc0NIeDFNSHd6OGNlSHk3RWhSejVRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMSIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRCbG9iIiwiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI1MGE0NWIwYzgwZTdmOTQ0YmYyOWY1NTJiZmEyZTA0OCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsIm5vTWNHYVBlcm1pc3Npb25zV2l0aENsaWVudFBpbiI6ZmFsc2UsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMSwyXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMDQsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MTAwMDAsIm1heENyZWRCbG9iTGVuZ3RoIjoxMjgsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoyMH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTExLTE3IiwidXJsIjoiaHR0cHM6Ly93d3cuYWNzLmNvbS5oay8iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkFDUyBGSURPIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIyMTExNzAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTExLTE3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMS0xOCJ9LHsiYWFndWlkIjoiZjdjNTU4YTAtZjQ2NS0xMWU4LWI1NjgtMDgwMDIwMGM5YTY2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJmN2M1NThhMC1mNDY1LTExZTgtYjU2OC0wODAwMjAwYzlhNjYiLCJkZXNjcmlwdGlvbiI6IktPTkFJIFNlY3AyNTZSMSBGSURPMiBDb25mb3JtYW5jZSBUZXN0aW5nIENUQVAyIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMCwic2VsZkF0dGVzdGVkRkFSIjowLjAsIm1heFRlbXBsYXRlcyI6MSwibWF4UmV0cmllcyI6MSwiYmxvY2tTbG93ZG93biI6MzB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNKRENDQWNtZ0F3SUJBZ0lCQVRBTUJnZ3Foa2pPUFFRREFnVUFNSEV4Q3pBSkJnTlZCQVlUQWt0U01RMHdDd1lEVlFRS0V3UkxiMjVoTVNJd0lBWURWUVFMRXhsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVM4d0xRWURWUVFERXlaR1NVUlBNaTR3SUVGMWRHaGxiblJwWTJGMGIzSWdVbTl2ZENCRFpYSjBhV1pwWTJGMFpUQWVGdzB3TVRBeE1ERXdNREF3TURCYUZ3MHpNREV5TXpFeU16VTVOVGxhTUhFeEN6QUpCZ05WQkFZVEFrdFNNUTB3Q3dZRFZRUUtFd1JMYjI1aE1TSXdJQVlEVlFRTEV4bEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1TOHdMUVlEVlFRREV5WkdTVVJQTWk0d0lFRjFkR2hsYm5ScFkyRjBiM0lnVW05dmRDQkRaWEowYVdacFkyRjBaVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSnU1RUM0amE2bUx2dFBXMnVEdXZ4VWQxSHZEenB1TmhUWEV6Ukh0QjRvZjNCMXdkdmFjcXZLK2REc2p3cCs4UkJodTB0eld4KzFVNE9KYUxQYzI4VitqVURCT01Bd0dBMVVkRXdRRk1BTUJBZjh3SFFZRFZSME9CQllFRk43aUxZMURBT2RvY1dsU3A5am1yL2ZsSFAxeU1COEdBMVVkSXdRWU1CYUFGTjdpTFkxREFPZG9jV2xTcDlqbXIvZmxIUDF5TUF3R0NDcUdTTTQ5QkFNQ0JRQURSd0F3UkFJZ0YvdERxeHRYY0tIQkFxL05CWkQyTkxQekU2MFU1c2tkakVZZmZwR3JOMllDSUcreElyOTVpcDc0L21iaUZrUm56aS9pcGsrUXV1WUMvYUZRZTlwQ0FqbmMiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBU01BQUFBd0NBWUFBQUJhRlJ5c0FBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUVHMlNVUkJWSGhlN1gwSGVKeG5sYTdhcUJlWFZFTFl3QTExTHl4a2wyWGhoa0FvQ1FUQ0xydFBsdWZDaGN2ZUpkd0FTOWdzc1BBc2daREVYYlo2Y1M5SlhPTVNKMjZKNDdqM0psdTJ1alRTU0pyUmpFWmxlbEU1OTMzUFA3ODhWbXlORitjK2ErZlJlZlRwTC9QLzMzZStjdDd2blBPVlAwa21hWkp1WWhxT2hhWldtN3kyNjAzWnVIVzdyTjN5cXV6Y2UwQjZCbjFqdjRlSFIyUjRkRVJHY1M0eUVoY202VWFoU1RDYXBKdWFDRFFuejlUS3NoZldTRkY1dGN5dnFKYTVwUlV5cTZoVWloY3RrWE1YNjJRbzloeUJpR0ZraEhkR1lzZEp1bEZvRW93bTZhWW1oMnRBRnE5NFVaNmROVS9CcUxDOFNvcXFGc244cW9VeXU3UmNscTVjSmE3K0FRV2pvWkhoeThCb2FDakNLQ2JwQnFGSk1KcWttNW9PbnpnakM4cXFwTENrUWlxWHJUUzBvcEl5bVZOV0lmTXFxbVRPL0FWUzE5UXNVYUJRT0JvQkJDa2NhUmdlam1vY2szUmowQ1FZVGRKTlRXczN2aUt6aThzVWhOUkVLNjlVcmVqNW9oS1pDekFxS2l1WDQ2ZlBYR2FtWGRLS0puMUdOeEpOZ3RFazNkUzBhZnN1S1ZtNFJJR0ladG1DNmtWU3RteUZ6Q2d1bGZrNG4xZFVMSWVPSFg4YkdFVWlJVDFPMG8xRGsyQTBTVGMxblRoL1VjR0lwdGxNQUJBMW9ubVYxWVptVkwxUU5hUDY1aFkxMHppYVJqT05QcVBSVWNMVEpCamRTRFFKUnBOMFV4T05yV1ZyMTZ0L2lLTm5zNkFkVVNPYVdWNGhzeW9xNVlVMWF3MGd3blBSWVlBUWppWVFUWTZtM1ZpVTVKS295TkNnU0dnQTlkTW5RUmxFQmFPUzBHa01YOE5ndzlCSW1IMk5CbjJKdFQyQ2Y4YUFoVVNqckhpRFJ2Z3pmNDlST0J6VlJoTEdQMzJOVWVBa0VnSlBPSTVFb25vL2lLQ3hvR2NiUnFRQlJCN0NNY1M3dzNocEFQeGZ2Q0NlMWF1bGE4Wk1HWmcxVHdabXpKZmVad3ZGKzhkbkpQQ0hQNHIzOTgrTHQ3eGFodmJ2aytHZURqUk1EL0labG5aRUcyRDh3NGhyQ0tyN1NGUWJ1Si9weGZrM1I4RjRmRERKanpna2dySVRqOEZMZUFSMy9PQVE4YkFNd3VCK2VGVDVEK0ExR2dkNEEzbnk0SmtCUFpjaGxLRzFWU0pIRG92bjlWMFNPWGxTWkxBUDhlTGRjQmpsRUFSUHpEdUlaUlJoNzg1MFdPNVJDUXo3a1ljUjhlS25JSDVUdnZGd0dDbndsekRTNG5OUlpBeXg0b2NBK0FEUHczeURFVjQ5akZKZ1IyTGx6SURveVlkM05LcnBoWkdURU5MUk9tS3hhT0V4djBQaTBwSkZIWU8vSVR6cFJRaXdYR2dpc1lyZkFTeGdGQU9CZ0d4NDVSVXByYTZXK1dWbE1xZW9TSW9ySzJYZDVzMW9mMUVaR3JvOElkWjFBTzlNMG8xRlNhNTdQaWsyeSszU25YYWJuTXVZTG1jLzhra0pQanRicExrQkRabE5iR0lpQ0FYUnVJZGpMWXVWcndpQ0VBNUd0T0VPK2tOeXRyWk9Ocjd5bWhTWFY4bU1PWVV5ZDBHSmxORE9uMThzSlpWVXB5dmx4YlhyeE9zTEdNSk9RTU9maHpFZzZtRlBDTnlNYXNNZkhnWDRkTFdJRkM4Vi84TmZsZ3QzM1NhMW1jblNtWlVrQTVsSjRrNU5rcTZrSkhHbUpVa25qcmJzSkduS1RaSjZYRGZqdWowM1Izbys5VkVKZlBkckltdGVnNFE2a0Y1UWhrTitCUXVmSHhDQk5BRXZsOUdWd0dnRVV0WC96QnlwKzd0dnk4bXZmRTNPZitQYk1ycHFFVEx0a2w0K1lHUkRQRkhrQzhJb29VRVozcnhSdkk4L0tZSDd2eVh0bVhuU25aNGw5cFJVY1NhRFYvRFhScDd6ODZRaE8xZDYvK0poNlgzaVNYRy9zbG9DWFJkUXdPQnFDS0NBUHdXeUdBWERDczFHWWlFRE9CVEs5YUV3ZnNPSkQ1azZWaWUxS1hkSWUwNkJPSkp6eElaMEp3cDJTNVowSktWTGEwcTZYRWl4eVBuOEFtbit5TDNpZk9qeklvOS9EM1ZRS1dLdFIzcDlFUG9ZSUxNcEJQRlBPelB5Z2pZQlVJdWdETmlaS0pGUGh1c2tmOWhvWTV6VTJON1ZMU2ZPbkpXYUN4ZkY3dXBWTmxoWDJ0R0FDT0FteGRmaEpOMFlsTlJYa0lMR2xpVGRDSU1Jb2FSTWFVa3FrTnB2L1MwRXZpYjIyTldKWUVRZ2lxL2NJUXBMakd3dXQyeDc4eTBwaFFvOWo4T3RzVkJZWG1rY0s2dGtObXo5ZWVWbHN1dXR0N1JoTVNZRk5jU3RXbEFJdlZpVWNVYkYzMzVST243MFUybVljcmNjdTNXS3RFTmcyOVBTcENjdFZYckF2eE9CWUVRZzZzS3hDZGNVY0dkU3N2UW5wZUdZcHNMZWlHRE5USmRqR1puUzhlSDdSRmF1UW5LQVg2OFB3bVBJc0dxSWNXUUNVWHlnNVBWLzlwdlNpL2o2VXBMRWptUGJ0S2xpZitKbitDbWdHbFlVUituckVsZmhiRGw4NzBlbExXODYrQU1BNFZrUEF0OVY4RXhQRWdmQXRCdTh1OUxTOFh1eUhBU0kyc0NuRTREUVhIQ1gyUDdsWHlSY2UxckxpWEZEZVRRS2pLd3lxUFppbEQveG5BK09RcnNhVldUQXcwZjJTRFBTZGlDOUtJSUxQRThVT3NDTERVZDNSb3E0OFR6Zk04bzVUVHdXQUZOcXZqU21USlhhajM5S3VrcG1pamdCVE9nMnlKOFQvTkJFVXZ4aGdSSU1jYzdmR0VhRytQLzZpZFdnVlJFanRyLzRhNU11MVpsQjhlQTBTZi8xbEZTTDNyZ2hCMXJETkFnUmprT1orU3E0cHpPbmlUejltOWhqRTlHbENtVTF4elI1UFhwOUlWbjE4a2FaVTFZdXp4Yk9WK0NaWDFVTis3NVM1c0ttbjFsY0luTXF5bkN2VWw0L2VFRDZnajZWSno5NmVZSWNEUk5lai9ML3NGdmNwVVhTL2Q1UGlBM0NmQ0hmb3NKc2g1RFlrSWRPQ0V5M0JZSUQ0V25CZVRPQXFEa0RXdEFVQ0xVbFZmcndiRC95NVFUNGRHVm5hcTlQQUdad1pXWkpEYlNFTXc4OExITDJwRVJEL1VoMVJQd0I2a21YVXp3UU1VU2hTL20vL0tqNEVFOHYwZzJRRDV4ZnlKd3VzbVFGdEN1UGpMeTZSYnJ2L1F5RU9WMzZrcE9sRGhwY004cTdBVHkyUVd0ckFBalZndTg2SEpzQlJ0WjBhSG1wNUM4Vm5ZTUJVTlRxMm5IZWo4N0M4WUcvRW5kSktiaWgrUVhSWjVuemhJVUZrNDlha0lvNS9rR0hWRE5QWUZiQllKR09OMTZUeGx2ZUp5MU1HL0UxcGFWTUdOcFFobzNVMk1CREY4NVp2bDNwcWRLV21peXR5RXNieXI4Wjk2alp0U04vWnovMDU5SzlGTnBTRkZBSmZtaksrV20va1RjRDRmVVFHSTNJS1BtNlRob1pRa3RCMElKQWlJYVJVT3g4S0RLc2RSUVBPanhub0xaa2RIaVRkS05RRXRYd2RnaXBOU2REemtDUUxxS0J1cE1zMG1YSmxOYTc3NGc5TmdHeEFjUXFsUUFVaVE2cklEajdQYkoyNHhhWkF3MW9aa21aenZrb3JGcW9Ea1lHWHZPM09XV2xzbVBmWGhsRXcyUjdqYUpYRCtHY1lFVGZRb0R0YU5nbkF6Ly9oYlNDTjJvUTdSQU1ha0NlbEV4eFFhZ28vRmJlQi8vdEZnZ0k3blVnZEFLY0tIQ3RFUDVXYUlCdEJDdGNzM2UzSjZlTE5TdEhnaWtwY2g3WFBYZytpSHlmbm5LYmhOYXVoQlQzR2dKOUJZb0hJM1QzMHZ6Z2d3b2lEVXdmY1EzazVJb2pMVWNpOTM5SklxV3o1UGhkZHdNTWsyVVV2M1ZCc0MvbUdRRFVqN1RKZXkvdURTWkQwNEMyNFlWQUR5Wm5pQXZuanFRVTVEUEZNRFVSZHg4NmkxNEF3amxjWDd6emRvazg5ZzlJbnI0bkEzVG9lNk9vMHpOREh4TVZJUTJvR0dwNWZ1Ym85Qm5rTjExY1dSblNtcDJzSURKUk1MV2hidkRJdkJHRU92a3VBS2sxdzZLQTZnQnZiZ1JxZUt5WGxwUnA0dmpaejhGS0ozZ1prWDRFZ3BKUndkU2J5Q1g0ZXljY3lLaUMydlAxY3VqZ01kbTM5NUNjT2xralhaMDk0aG1FTnNycUFSRjQ0djFHUnIxTjBvMUdTYzI1NmRLQmh1YTB3RnlEUUxWQlNMb3B6R2hjclRBUkVsTE10Nk9xTVM0cER6MTlnN0p4MjA2Wk1iOVlKNkJ4SWhxSFhoazQ2c0c1SUlXVjFUcExkcy9CZytLQkdjYjNRa1AwY3BpakhMRXc0aEh2ZDM4Q1FjZ1FPL2p6Z0NjMitBNkVucFJjRllCQm1ESGRsblJwU2N1QTZWVWd0cXlwNk1YejhZNUZoWndDVHlCaklGaDE1a0tZY2kxU0EzQ3lwbHJVVjBPdGtML1RiT3EzM0NYQlpTc2dNQURGTWRCNU8rbjlxRS9xUHZkNUFKNUYvTm5UWWNMQWJJSDJWWWQ0bk8rNUJVQUNEYTRnVjJyQmUwYytnQXBnUWkwdEFnM0hud1RRU2s2RlJwVXU3dVJNUEpzQ1VBV1lRaU9obGxTSHZEWWczODdzUEswZmdnSHJwUnZnU3FBbFFEbm56WUYwZTlXL1piaGtvd0R3ZmdPTW9JSUV3U0xMbHM1amhTMnZUZHlmL2JUVUk2NEI4c2c0SmdqZEFFVTdlSE9rWjB0N012Z0RiN2EwWkpqeWhqOHVDSjRkNmVBWFBEbFFqaVBRUXFtWkhybnJGaG40M25kRVhFNHRSeWRxVnVFQW1oSHhrZHJSTytIQjlrTVRXcmgwaFN3b3JaQ0toVXYwT0x1d1NGNWN1MEZjNkJCTnVwSWpleEtVYml4S29tQUxHcHdmUndxNEM0MThBR1pDTnhwVVBjNFRFdXMzVnFmVWpLZ1JFWWllTFZ5Z1E2eXppeXBrZnZraURZVmxBS2FTS3BsUldDcmxpMWZLMWwxdmpRMjNrb2FpYUtMMGQ3Q1JSbzJSTGZuUkQrWEluZE5nQ3REblkyaEJ6dHcwOWZrMDV1UklFNFQyWW5hcW5MMmxRRHJ1K3dzWmVQZ2hjWDdoQzlMNytmdkY5NFVIeFBQQTU2VDd6KzZCTnBVakhSQ2FGZ0l1QUlFOVBrMnJqaFNMdEdhbVNTZE1EVGVFMzRNZW43NnpsbW52azVFOUwybXZTclgrcWczWEh4RDdWNytoWmlLRnV3ZmcwNXlkRGhBQmYrQ3RQY2Vpd09SR1dmWWlEVHJRTzhDM05XczZBR0dLTkFMNGFZSTFRSmd2Z0xjVzhOQ0owTVg0Y0UzTmlGcGZIUVM5QVh5MzRSNUJTZjFOQUllNjZYZUtiSHBaQVVmOXhXR0t1VjgxSVU0eTdzWVY5U1JrSWxaUDBFczJyNVhhK3o0aTNvemJ4RXBBbmlDMEF6UzdvVUcyWmFUSkJhVEp6c3BPTUFRL1hwaVlkWHlHb0FVd3I4VjFEVHN6WEErQ2IxOVNqdmlmbTQ5ZXhpMTlnQjhGSVA1RDlScXdjRGs0L0NsRXpabHIwVGdEbSt2U0dEanZpTE95S3dCU1BUMDlzU2VSMmpqdGFOSm5kR05Sa2cyTmlZTFlCRUd0bjRZZUhNTEp4dTlKblFJQnk0dzlOZ0doUGpscVJxS1BpS2FaYWtRQUlwcGk4MHVycFloZ0ZEdWFZZGVlZzJOTmtiM1dDRWRjQ0VRMCthZ1pSY0xTVkhOV2JCREFGdkJIOEhHbFpxR1I1Nmh3WDV5U0tZT2YvRy9TdmVFbEVXc3pHanlFREdnNE5EeXFJeXNxZUlpTFE5azZURDhNS1RoMVN0dy8vNVhVdk9mREFJSjhjYVZQVnpPT21naWQ0QVE2QjdTYUkxTlM1ZFMwZEpGcGQyZ0RKaUJkVlR0QzZIem9VYkhHd0VOSHd5Q1EvZFF1Y2Q1QXJSTm1UVitxRVg5TG1rVTZQdkZSOFQ3K1BmRS8vMHNaK2NOTUNUejlQTTVuNi9RRDMwK2ZBcEErSk0xWnQ4QWtoVmFGL0RjaTFDUHVyc3hNQ0hpZUJCQ2NDRTFwdVVKTnJ2bC9may9FQXkyQXpQVDVVSDVCQ1F3YjJxYUVVWjRSR0VsUm1Fb0Q2Q3g0RDNuaTBMNi92bEg4KzQ5TUhBNGRrSkVqQnlXOGRaTjRpdWRMOUxlL0ZkK2ozNWFHVysrR1dacXZBd1hVa3RxUjV5NmMyNUh2Ym5SbXJURG4yak96WkcvQnZiQ2pUcUlPZkJMaEZBR3FiMmd1UnQxZlB4Z1Eyemp6MnRTNGVWNjBjUEhZdmYzNzkwc29aUGorekZHMVNib3hLYW1UUG9BSlFxSjVSQnpOWVJXN1BRSGRSNFltR1gxRE04ckt4d0pueExLQnpKaGZKUE9LU21YL2dVTUdnQ0Vhem5oaGxPTG52Sm1vK0JHWnpsY1o2SmIrZTlGelF4QnQwTnk2OHFCTm9OR1BJTkQwYWZ6VjAyaUpFTHdFMUJQcmtSa2w1Y0JQcG50c0VueDZ0aHhOdWd0bVhySU0wRXdEbU5DWlhJdjRPN0x5TlMyT0dza1R2OEg3YmlPLzRJMUtHNmNYU0FUQ1JTMWpOQ0lERHo2aXdraWZGRWU5YU1vUTRPMHB5ZEk0emZCejFlZmNLK2VlK3FVTWRiUXpBdlhzNnV3Y0xVZU9kUmx6cDNUb216MTR1MFBPTEYwbnA5NzNFV2hjVTFXVE82Y0Nud1lBb3A4UDhTT05EdDVMU1JQWnNSWVJSWVd1ZDhQUkZsVVRMUkVSWTNYVWphL2dTTkNsbzV0MTRTT2pxSDhacHBlSFRNZk9xY0c2QjZSanh4NXB2bTJLOHRiQndROGNxVDAxWjJVclFBMm1wQUJNTTZYL20xOUhqQzVWZEhXK0laM3BBRXpOKzNVU28xaFFoamFIZHFjanRRQWd1Z0FLS3hiSm5QSnFXZkVpdE52WWM4eW1VU1NtSzRDWm5waE1iY284eG5kS1Y3bzN2dE15MHpFVzVUSTlJNWpMVWN6bnRkeGp2dGQ0TXJVM3BoV2YzcnRScTBzSVJnU2hSUE9JckRhSGJIcDFoNnJLbkpKUGpZaE82c0pGaXhXSTZLaW0yVllFa05wNzhJajQvR3pjUmh5Y0hLZ3hBNXRDS3BJc2JNalRxaFhTQUhEZzBMTExraXVOQUlzdUNEdDlSSzc3UGlkeTloeWVOWGlhaUNoYXNBV05MaFQxWi9TUlNMK3pWV1RkV3FtNWZScUVDVDA1VEE4ZE1Vck5rUG9zYUdESjZXcHUyRDcyMXdBR0xyUmtZOUFJRGNDQVpCa0FEUjBqQmtZdENHOERJL0RyZU4rSFJFb1hpOWlSNWlnWVladERYUFNsYUFGcU9iQUlSaVJFRFE2bXE0UVFuSU9xVlhSLzhTR1laUm5pemN6UUFZYVdYSmhPdWRDMmNFNHRoTnFkNnhkUGdLZFFiRklqT3c5andtZ2lndDZIdW8xQUthVXBSNVVGZ1R3TXhRS3lTRVVUWjBaZ2xobndtTGlSa2JZV3FYdjBNWUJQbGpSRCsydk96eEVYeW9BbWNGY0IyaERLdHVVVEg1ZWhnVVlqazN3WFlLVDF3cnhmSnpIS2ljQ29FbTJReVVTQXVDd1BvMHpNVERCY0c1bEFRQkFZYjdielBCSmhnVnhPWVRXWjQ5TzZVa2hNNDlPS1A3NmI2SnJBYUtKNVJOU0lDRVN6Q290bDVvSVMxWUNvTG5PaG9xNmF4aldCaUEzbExRQlJJRGFyZW93UU42Y0RzbFVGVlVwQlE4UFMvclhIVkV1aGh1S3daS2dQaHFOSk5IczhjMmFnSVVkMUJDa2hvZUVMWjNRVC85QTJ3aEhPWFdJSTR0SWp2VE9la3E3a1hLbURlZEdUbGl5ZXRHeXBzU1RESEV4VnMrTU10TEJvZVJFZ3g2OEtoL0xPN01kQUpCRVljWnFFNDUvL1NhVFhodlI4NGh1QmZvYTg4blZPNHpRTGcrdW02RDJMQUFCR1lLSXFJRUVBeUtjMG5aWDZEMzlNUjdVR0MzTGtGSGh0QlFnTkpDUHUxQlJwQm1oZWVQK0hrY2NCZFdRemNzNit2cWEyem1mQUEvbmhQTVVRemlsV09EV0FCM1hDRGlPRTRFZndnQi92TURWUzFoVUN5K1I4TFRTaTZSTEl2bE1jeWNZOExuWWE5STlSdTZ6Skx4RDNyZzFHcEpvZUlaQ21PYzZ2a3hqbFJHQzBvTFJNZ2VoUEJhTXJhU3NreWdQRGVBMkY5eTZmM1gwcExlNFVRQTNwMGlKZDQ5MzRPSmplZUxlQWFXYVNUTkNMLy8zZFFra2NrWmtvbUFWR1l2Wk5kd3lQNmlPaWFVYU5DRUMwb0hLaDBSQVFPSEkybzZoRVRiTUZ1TjV6NExCNEFzWmtPSFBCb2hZb0l1TFNBaVlUVkw4UkhtaHBFRnYyKzlWWlN4N29lK21BMFBVREpDNmtaOHZvMmNQcUIrcS94TnBWaVlJVVpvK3ZUQ1BnZENneUNwRWFoUmFCRzU0bXNYLzY4OUtjbkNKT2dKRUxhWEYrRGRQbGFCSkhqQnozZndYQzdZUkF4Z1EwMXVIUjdKZ1lqS0N4cEUwVjM1WTFLc2dEQ0w1aHhJSjNLYzR4R05heXZPVFBNRXhpaW1zRTVlS0VFSEVtZkhoVnRUU2tacW1UbkpNUjZadHF5YlJBMkZPa0JhYXNOU2xicEt2VllBMlIwdVJUU1UxRVJGam1nOG5qVkJuaU1WWldHZ2ZzWmdvTVQ0MHdxblZvbUpkKzVLdGI3RC84am9JUWgvblBvaHc0U3RpZm1xMmczZ0F6c3ZzNW1OVlJhaFdJQUFKSHpjak04ZlhRdFlBUjAyRmcxalRBVnJ5MFdIWmk0dk9jcm1LK0d3b2JuV2w4WUhrSFF3QWE1RzM4L1lpT0VMTUlPV1dGTGc4V3J3R00zT3lORkE5RzVqbGxRd1BPK1J6ZjU3azU0R1BLMEx1SkVvTVI4bXYyRGl6czhmT0k2Q09pYVVZTmlOczRjTHRQSGdsTVBOSkhSTk9NR2hIZkM0U0NXcmhHZ2FJcDRZK3JwN2dHaWhOeWg0SSs2VnUrV0xXQURnaVpnK1lUem52U0tIalFqREp2Ull2bzQvSXNvNFVsSUFvMm13Q0JSQjluNnpXRkRIR01BaFpHeXN2RmxsWUFMY05JeTUyV0prMVRNN1IzRHdBRW0xS255WEJIRGVLaGRvQVhXUnhzTTlwdUpnYWordFNwSW80V25XZERaVWVkOVBoVHJRNG1HNTN0WTAwcWRrSSsxV1RqZzJDOGczZDhOckYrNWpPSUh6d2hES1NtU2wxNm1tb2lyU2duRHpTNDRkM2JOVnU2a1JnajRrVUNDb0V6K3E3b0pRcU4rQ1FDcldkMGxCb2JNa20wNVlJMitvZ2k2RWdpT3AvODhnQ1RMdXl6QWl4THhBdEE3RU1aMEovRkNhYm5MT2tBejFSeHBsckUvby8vaU1RQ3hveHNhTllqeUx0T1A3aE9ZaFluQXFQaThnb3RUd1ltclVBQUVMcldWZnY2RHY3eEdBODRVZVRCRE9hOWVERGlzK1k1ZzlubUdVd3dJckRFMC9qMWNxb2g0Y2hBdVRIUCtaNEpUdThtU21pbW1UVnh0WGxFZEZiVEhEUG5EaWtRbFZYSm5BV2xVbHl4VUozVjlCSHB1eWhBbzFJWWx4SDR4elZiOUZ2d1BJb0czL21ELzYwYUFHZjhVc2p0NlAwNTZZNGFrclhnenhBUjlBcktna3BjQWlMd2dHbW16OU1vNjk4TWlFTVZZRWViMU9iY1pveW1aYWZvc1BuNWFSWmoxamJTcFQ5RXRtNVJQdFdVUkt2alRGL0dPVEVZY2JiMUZPU3JUNU1URHpMSUZoc2VOaVlCNGh4V294WXhpWXVLNldkZ0dZVUF6aXFza0gvRDlCb1ExNDkvSlBhQ1BPV3ZGM1ZEL3hZRG5lOTBJcnVLNStta1VhTk1qZndtSkRMR0IyTmxRaGxsemdpRVhrYUVQNDBNUVMxSC9NNDJRRkJob0FYQkNZeXVZMitKTC9VZTVZTWFaVzltaXB6blNDMnVQWnhOL3NsUDR3VjFpV3NFQkx5SVZ1TDFFZG1lQ0l5NGhRajVaV0EyakZiTVRKbGhZanAyNnF6WTdNNnhPQmdHZkVFNWNPUzRuRDUzUVlMUTluaVA5Y2oxbDF0ZTJ5SHJONzBpTzk3WUl4Y2FtdkU3ZGR4TDc1NnFPYWZCdEJKTUloQWRPM1pNZkQ1MkJ1U1JaV1Fzc0c3djZnUWZKeEZmL1dWeG1TM3czVUtKd1lpMUhjc3o1V2o4UENLT2x0RlpUUjhSVFROcVJBU2lCU1dWc20zbm0yUEQvaVJUN1NRSUJZZTRzTlBvVmRDUDRCd0pvWVNIY1c3NzJIMDZOTjROTTQzTEZsd0FJeHVPRFZuSjB2L0JUOHR3bEN2YThWYmtHcnhHcHFDeDlwQTRCWnpCQkVLdUpLREVOOXovZVowbDdTaElrem9JMDBVQWl4dGd3cUhxcGd3QXlyL05SQndlUEVrQmdwWVg1cW81MHNSZ1pFL1B4ek11QXpmQmcwNzlnNjFIRnhZRm44blRqMFZBTW50Z0paNHdnUDllUDhCMzFDOGppeXZsVkVxS0RHUWI4Nnk2b0MyMnBXZkZURFlBNTlPL0EyZUkzMkRSQUxFRXhHY0c2ZUJYZENGdmdBdUFCbjhaR1hVcjM5UkNXWHp4Z1huWC9JOTY4TXdBbUd5V3czbTNxOW5ZQm0yVzg2YzRrNXoxeDQ2bGZlcWR5Q0RMRDhRSVJ1bUZVbWk2TGlJUDEycW1tVjJnQVVKbW1Kam1vTVBkdG11M3ptNW5ISjVBV041NGE3OHNXZkdDSEQ1K1N1OTUwY1ozN241THFwY3NsMFhMVnNyaTVhdGs2Y29YZGZIM3ZrT0g4YnV4aUpsaDlmb042bFRmZi9pSVhwdGt0OXRsMGFKRjB0WFZkWm1QaUlDeitkV3RpRytGdkxoMkRkTFhlZlFhZEtyRXU0aXVRVE5DKzV4Z0hoSEJpS05tZWw1VW9wb1JOU0lDRWF0ZC8ra0pEa1I2T3NNUktZR0ltM1Zvc1k5UXhHa0tBR0JHZlRBN3BvdU53czFHbkpVR01FcVdqc3hrT1ptWEpNUDNmeDJQQVlTQzNPd2tzYmdScmxSb1dHL3E5ekNjc2RRN09KOXBCQXg0Y1dkMDV1OGxuR0k0eW11bVFnc0RJTmt0eVRyQ1ZnUHRKdkRBOThIZklJUUptZ3Q0cEQ2Z1R1SUVZT1JOeWtEYTNjb0h1VlV3QzBMckFBQVl3bXlBa2RuQVZFdGk0Qm9yUG9BYkxQMitTSy9JdnAxeU1UTlB0WStMMERvNGU3NHhMVjFjME43T1RZZEovY3dmdEZ4WmxPSWRObllOU0VUMmN6SzRickZZbjN4QzJqNy9KYmtJUUdsT3lnUVE1d0JZMHNTT0RvQXowM1grRUk0TXZiRnpUbG5nb3R1R2xGeTBwRHZrYkpZeEFrbHp1dE9TSXEzSk9kS2FsNno4TnJJY0FGcmNiTVhJYUFnbHAvcmhkUkdMNkU4Rm8ydlpBNXN6dXFucE1CMXFQM1E1Y0xlSlY5QWhtL0cyZHpta3JHcVJiTmk4VllHSjk3aFR4VXZyWHBhNUM0cDBCd0g5VkJMdWI5aThSV2JPblNjVkN4ZnBmZE5IUkRDYU4yK2VPSjNPc1pFN0VqWGR5a1VMOFR6elVpSXQ3VllKUk5qeURLM3AzVVFKd1VqRm5ZaUJybnpwQzV2bCtlcmxNcmRzaVpwaXo1ZVd5ckxTSlZKY0JPMm9yRXhtTGtSaldGSXBieDdkRDFNREVrR2ZVQ0pDWFlSMFdObW9XRGw5V0J6UUpqalJrZVlJZlNTMnpBeGRqR25OVEpYK3Yva0tlSUp0elhaazJqZlhRMndMYUNpK3ZkdWtPVDFiN0RRSElXdzJBQ0FCa1dYUWtaMHA4cWxQb2ZwcHBzSE14RHRjLzZXcEo1aG54SGxTZkY0emgyZjF3S2FOZXlNMFRhK0JkQmdjaVlYMzdKV09qSFRwZ2NDM3BhVWFpNFBKTDgyaDFEUVpmRzRtNGpUbWhXa0NLbmRRK3puRVRCUkFOQzRjNkl3ZjJydFc1TXVQU0JNSENYS042UUU2ZHlrbFZXZFVOeU0vamZsSjZvK2FLSFRnK2JNQVJUZUF5d1ZOaURzajlFTTd1b0Q4OTJzWklIN3daa1U2ekx4YUlDZ1Fka1R2UU8wbEJLUHhacHFSSmlEcEduMUdaYVhWOHRMYWpZcnZweHNiWlhaNXVXemZ2VnQvR3lVNmdWNS9mYmRVVlMwVWo4ZkgvbTZNdkY2LzdxdTBlZHMyNVRPTXpMKzhkYXRVTFYwcVJSVVZzdnJsbC9VNW11ZGRYWGFwQk44Mlc1ZkdNYXlUN1VScTZ1cGtYa21KQWxkWkZVQnc2MnVhQi9xcTNvbnl1NUVvSVJqUkdPSHM2QTFWSzZSNlZvbHFQYityS0pHNVN4ZWloNEI1Tm5PdVZGUXZoWXE1U2tvTEsrWE1vZE5heDlTQURNMGhBZUZaZFczamowOFBIOTByM1dtNU9vdlpsWnltdld4N09zd1JDQnhYczN2K3g4T1h3T2dkcUEwVkRvQ1JmOTkyQlNPT0JsMEdScmh1NVVqZW5YZEIwRGtkQUF6amoxTVVSOVhHbkZnem1oaU0yTVFUMDdXQUVRWCtTbUNFdmxmajhFZVFNbHQ1ZDYvWWZ2VWIyWXY4dEdRVnlFQ3FSVFVjVzBhcTlLUm5pQWZhSVpkeWNBREJtY3lwQ2FrVEJyN2JsSk9xenY1MlM2cFl3VTlQaGtYT2NhMGZ6TFdyZ1ZGRStieCsrbFBBNkQvandDNHFycEF0cis2VUV4Y3VTdW15WllpN1NoeDlPcHRMRTJkOEd6ZHRrUlVyWDdnVVA0SnBjaE40dHU3Y0tWNTBDTUhoWWRuNDZxc0tTQ2ZQblZPZ09uUDJuRDVuYmJjaHJWTHA2blpjRnMrbTExNlRGYXRYeTREUEwxdGUyeWJMVnIxd21YUDgzVVNKelRUa2VIL05TZFY0Rmk1Y0xNL05tU1BQdmJoWW5sbGFMZk1YbE1wL3JGc2k4MkhQYmx1L1U2Sk9WREQrZk9HWUNubU5taEhnVG8vVUV5S0gzcFN1MUJ3VlloT01LSGhXQ0RwWDQwZSs4SWo0M2tFd1Vwb0FqS2lkY2ZGcXM0Vm1CdUZWR2RaejllYmU0R0RFR2RtRDBTRnhVTFh0YXBmV1AzOVFiRGwzQTNDeWRVREFTMU9NZWMxSlYyMUdsOTF3aXhVQVNpUHF2eFgzSmdwT0FFNFhnRVozVTBCZW0zQ1BQaUpxV213L056MFlsVmJKa3BVdlNmbVNaYnI5VFhIMUltbnQ3TlJsUjR5TS9kSExHemZMcHMydmFOeThiNlpEUUtKWjl0ck9YV09PN0RVYlhwYVh0N3dpSWJTZDVTKzhLSlhRcURoZG9OdmVBM2txbGs1b1NPYTdnV0JZQVd2ZkVjTy94TDI4U3dHR0RZM04rb3oyaGU4aVNqeTBEeE9OVHNlTEFaYzA5WGFJeSswUWEwZWJxcFZ1bTBzY0VhY000aUVPU3BxQm9LSjFmUzJsRmFWbzRqbjhFVjlNTUtKbTVJQ1FFQnk0em9uTEh0b2hlSkVIdmc1K2ZFWWkxOUNZcm9rbUFDTVh0L213Y09FcmdabGdoSXlwb3d0QXdqeE9DRVlBc3Y5aU1LSjV4anFKOXRkSjNmMFBBTnh6aFN2eHVjaldEbjd0NmVrNjRzV042RGlWZ21ZYkYrNXk1YjByTTF0bnZVOFV2SGlYV2hGOVNIMEVwbXhqQWJMdWtKQUdvRU04VndhajJES2c2NlQvNzJDRU9EaWhkeUUwbi9OTkxiTDhwWmRrOGZJVnhvNmsrSjJ4RUhEb21DWXZuRnhwcGtjLzBmcE5tM1VIVS9QZVMrdldLeUR4dkxYREp2TkxTdFhKYmJNNzFML1ZadXZVM3doVy9Cb3V3YWk1UXlkMzZBamNvbVhMNWJWdE80eTBFN04vVTFGQ01GSzU2eHNRMzRHM3hQdjZacEdEMjBTMmJ4VFp1VTFHOXV3UmVSWDI4MW1ZWnRFK1BCdWJ5TVphUWJnbVVVc0FSbXpNVFJDVUxwaG9GQnJ2Zlo5SEgyOE03UnRDOXc3UU9ERGlGaG1kRU5aM0JSaWhxTHhlbHd6ODI1UEdqT2k4TEoyeDNRbGVlYzMxYnJwVEE4NTFqVmx1dWx6TTVpNEduR0Nab2V2ZUpncFdtTlRkZUs3dHppa0tTRnpmeHlrUjNDenUvSlNNbXg2TXVPQzJkTkZTT1YvZnBIRWNPWEZTbnAwNVM4N1dYakFHSUJFMnZySlZ6U2N6blVHL3NVaVpnWTdxZFJzM0taOE1tMTk5VGE5TlRXbm43amZWRjNUZ3lGRXBxYWdVYTJmWDJMc0VyYm5GeFdyV01RMmFhWHkyQXZtajF2Uk9sTitOUkluTnRHQy9SR2VVU1dmMkI5RUQ1dW8ycnU3Y1BBVU1iam5hbG5hckhFNlpJa2YvNm5Pb2xYV0FiN3NNaFFlTWdtTHBKeUswQnhPTTZPQUxIWGdEUXBhdFF0eWJZdEVlbTg1cjlzSTAyZXdmK0FSZ0FMcWF5dWUxSkhBTkJEQUs3TjhoTFJrNWw0RlJKM2k0MmMwMFRlSDBVV2lXK2VMQjh5ZW4wN2RqYURMY01zVUYvbGl1MXBRc3NYM2lVK0w0NXg5STc3Ty9rc2lNMzR2OCt0ZmlmV2JHaE1FNjR4a1pmUFkveEQ3dktUa1BUYWdlYWVoUVB0TGdpTnJWd2VqbU1OTTRiZVVGbUdFQjdocUo2MGdZMnM2R2pWSzlaS242amhqTFd3Y09xbFp6c2RFQUxBWnFSZFJ5WnMyZXEzNGhtbDEwT2xPcjRmdW1BN3JIM2FmYUR1UGpCTTFPUjQvdTY4MUp3dFNhWGxpM1RqOHNRSk9PNEVSUW1qdHZ2dFRWTjc0ajVYY2pVVUl3Y3JIQ09xM1MrT1d2U2dPWFM2Z0pnOFpNWVV1enFQQUdJYXowUFp6THpoUEh2ejhKVGFvVDlXd0lYRUxDTTZhQTAvS0tIdDR6cGhtNVUyRkNJQjJ1d3lJb2NWdlh1aWwzNHpuRFRPTXcvVHRDY1dERUhSL2p3WWdDZnpNN3NQbnRqdjZmUEtuTFhGaHY5Zm5nTTRsemxRcDBHZ08xb1JQUUNIdC84UXVSNW5wa2pFWTUxOGYxSXdwT1lhQzRYejNvRGdhakhsUmNvelJPZmE5MEpLWHEzbGdjbGFRSmQ3T0QwZXpLS2xtOVphc082dyt4dVNFQ09wdG5GaGJLN2tQR05qZ2REb2M2cXBlc1dpWG42dXRsTUJpVTA3VzFzbkQ1Y25ueHBUWFMxeitvSmhYVHBtK0pQaWFURjc1UFovYUM4bklOdHA0ZUNZMk15TkhUcC9XNjArbFV1VER6UUsxcjhaSmw2alJYdjlXN2lCS1BwcUVFV0FoaXV5Qm5IdmhMTkNwajQvc3VOT2hPcU9jVUJBcHRMOVJ6T2pGcmtyUEU4NU5mQTVDOCtobWdoSVJLQ25QcEFSSmh4Y2pKZzJLMzVFa3I0dVVFT2dvMTkxbm0vQlZPaER4dG1XS0FFVjdoOFBBN1FoT0JFY3Bnd3FIOUd4eU14Tjh2YlhmOXVmckJlbEJIM0RpdU5YZXFuSUhXeWUwOWJFblFjQi85cGtoL2w4NUxha0ZTYW9XU1VRVDI2Qk1GN3JHdno0b2JXdk1kTUszVGRTVHVmQTVONjNjSEdLM2QrcHFSUmJ3YzhCbDE5dEtHRGJLZ3VrcUJpRHhjYkc2V2lzV0xaZmFDQlZLK2FKRU94NWN0WENnOXpsNU4wM1JzcjEyM1FUWUQzSGhPZ09LN3RBaFdybG1qNEdQdDd0WjdqR1B4eXBYYTNmS2FaaDFOUXZLeGZjY3VxVjY0V0hyZHVtSE11NFlTZ3BFdThCejI2UW9tYWJOS3gvLzRCNERFRkRWZjJpQndQUWcrYUE0Y1BiSG1HMSs4NkVlREREeitJNVJpdTlpWkN1dWNzM3g1d2xtK28wT0FFME13dFdwSHVNZ0N3SUlMcnY3cXpydEQvUm5jWUorak05d0F2anM3SHoxdHVqUmszeUp5ZUFzMEkvUTJyQ255eGNXbi9PYVoraUVZRTlkMUdZN2JSTVJQSVlXUWNPaXQ3WEptNnEwNndzU3ZacHlhem1IdFBOMm4rZ1Q0Y0QvMEVOTEVrMlJhSjRFR2pRbDhBQmdUakc3RWVVYUJqanBvS2JmcGpwaHRlZW1vbXl4cHpBY0lFVGp4N25rY0k2Vno4S0JYZWROMWFPRkJ2Rzc0TkV6UzJmTnhZWXc0WXFwVjU1UFdwS25xd0s1QitYR25oVjZVeGRYQTZHYVpaOVRaMlNsdXQxc25KOGF2NE9lNnNXNEF4K0RnNE5qRXhTQTBvbnBvUmx6V1liVmFkZkppL0NKWVhqTXVsOHQxZVJtQ1BCNlA3a3JKSTRseDg5cWsrTDJNdUdUSVpyUHBURzM5d2dxaVVpMDlsa0h6M1BqNkNvRC9zbDBDak1BZEJIZzB0am01Uk15WFNjb2plNXhZdkVQY3ZJeVhzZmpqMDB3WUVBK2ZONFBHeTN0eDVaRFlaMFNtMFhpNEpTeVhhb2lyVFM1ODVnRUpwQllvOE5SQ0VEcWdMZkhiWDFUNzdianV0cVRLZ1hTTEFVaGhRRUlZcWo4WEZDSkJDdkJRQUhHaWZCU1FXRFlRSUoyUGpOczBoVnJ2L1pqaFRJV3dzSEZ6TWw1bmNxcnVrOU5oS1pEKzUzK0g1L1h6aVpvWkNwOHVMVUVjVVFDVGJzRkJ2WnJsbllDMDZDRlF3d2ZmZ0dZelRmd1p5ZHF6dHlMZERtaCs1TU9XbHlHanYzb0tqTWUyVGxXbUFXQTh4LzhiV1RQcVAzVkEzTW5UZFA1UEkzaGlSMUdYWTFFSE5pZVVXaEhrMEhiVVJaUzFxd0FlNVAvaElRa0dMZ21mbG5Nc1hFWjhCRW14ZTNHazNhNkRESjBGYWVwYjdMZGszdFNha1puWGVBRWw4WnEvbWVERTgvajlqRXpnaUFldjhhQVVmNHduTTYzNHVFMktQeDliTWhMTDFEQTZlVlBRRlRRZzZMd1haZWNTYXcrWE5wUXp3Q2djWm8wYlpLWnI4alNXWjhSdGdnZmp1MVNJQ0RHQTRmRnQ5MkxYSmw5anY0OEw5Snd4Y0QxbVlqRHloSlZCcW9rc2JoZG5ydGd2S2lCUlErS1FPL2NZMG8zdExlazZwTXVadVFRa052eStIejJKMWcwN0dFMmNLeHhZTkl4SEFZbTlLdkxNWGYrVUpaWURCTGIxc2NlZ25SajdDVkU3WWdPbnc1WDdSUGR4VXQ3RDM4S0RIbU5YUTBhSVRQRlZ4cXNWeG5Ma0pEOXVVSmFJV09kaHZMbi9EYVNUS3o2WWFOemJpQ1lodDkzVnlYOXBPU0pybHN0b05HSm9XNG91ZUpFRmVvT0QwU0EwdnI3a0FnVWVCUWdBN01VczhBZGVtVGRQY3I0TTdsNnZtN0w1MEdjd2Y3cGJRS3lIWm5tT0Q1Y1IreG9jdkg2N09OUHYxSkUwRytLM1pscFVXNzVad0doOHZnZ2VwbUR5dDNqTktCNVl6UGZpTlF4VGtBbFE1bmw4MmNXL1R4b1RmSkNaMXBWb2ZIeWtNWUNJQjRTNFlPNHdhWUlTUWVoUzNpL1g5a2p4K2REOE05NXhjYjhOWE1hQjBaWGVlVnZBNzR4SFQvR2ZJZUhRdnFIUEdKVVpWUWRCREpDZ0lkRmtZK1BqQndlcHZkRGhUSCtTcm1XQ2dGQnpha2pLa2M0bi9oa1J1Q1ZBcVlUY003dHE0ckFnOGFmTENNRVY4NGpTRmVmQ0NwaGtXZXJqWUh6MDQ3UWo4QXNVRktyMktYZUxIRDlzN0dwb2xEVUtQZlorTExQY0JkSlkxSnFBa0w2ZlMxZTJiNFhtVmFDZzE1aHJqQWgxQTJDNUxxNDk5Ullacmptc2ozTTFsZEVRa0poR1B4RVlBYVQvcTMxR1IvZWpidEoxcjJ3Q1VHOHl0SmIwRkdPN1dwWWx5am13cWxxZlZ6NVp4VndaaTRiSWRFMGhNc1BiQ085b3B6RFNLMWJMZEUySGU1VDNUQzlRcmV2cVlIVGpETzB6WDFjQ0NBcS95OTA3dGcvUitHMUE5Q3Urc1dJZWZ6U0R1ZFVIMzQzZkJzUzhSekxMbGNKUFBreGV4blp3aUtWdkJzWm92aDhQWkNieG5obW4rWTY1RDVJWnpMeVF2RjZ2cm8wam1XbkhnNTRaQ0Z3TVYwclRUSS9FT1BpTStSeVA1cnZ4NWN4emZnV1ljNnI0WkVJd3NyUEMrRDdWRHJ4QlFESk9vZUsxV2NYNzJiL1M3M2h4WmIwdkRXWU5BSWthRWswMitwQWFDRXJwVTJYd2h6K0YzUG9Va0tnaEdXd2lZcHhUNFJ3Tng3YWZaUnExWi9EK2RBaWVNV2ZGQWNIbVJMeGVOR2cyYnFZWCtLZWY0MkdQZnZDUnlxYUtOY3VEQUJFZEZjOW93RndyUHlHRmtCa3ZEWlAvZUZyYUxUbXExZkV6MlFTOWJnQVJQNmJvdU8vTDBBQ002UXJVSEJUMFNMcXAwZzBPUm0xTmNqWXQyNWhIQkhEdlFwNnNYTFlCL2pwd1hwdWNJdUVmL3dTRk1LRHIxbm9Id0JQWUk0L0J3T0JsamZGSzVFTVAxMC8rdW1xbE1UTkh2NnJiWWtuUmJZSWR5UHZORGtiRnBTVnk4UEFoOFFlTkFRc0tOWU1KQ0F6aHlPV0N6dmJSWWV2UzgvRWdZQWJlSnlERWExK204TWFYZGZ3N1pwb213REdRelByaCsyWSt6RGppMy9FRi9OSnU2OURyTUxSOHZZOTNkdTdjS1N0WHJyeHNQeVg2djBobVBEeU9MeVB5ZnFYNy94bmlkQVp1cWVJTGhST2JhVnlYUm9XZCs3WVFoVmhjTk5ub1ExS25kdU5SdWZqTmg2VEprcVdBUkEySkpodDlTRlRUMi9qNUg1Z0dmVW5UREVDQ2hxVHdNWVQ0b21nVXNHTlZKTDBSUkk5N3pEc0s0dXhmZmxIcUlXZzBKZmlKb1l0bzFCd3k1aWR4V3VqWG1mNStpVzVlaWNlNVJ3NTVNVUJOa1JJUmNuR29BVk1Ua3hZMWVHcjl5Ny9XajFoMjVLV294dUJPc2VnaTBETTRIM3grMWxoak5wb0xpS0NubFhDRGo2WjUvWEwrbzUvUWNpUVlVVnZwUXIxeU1TemZhYzFPbGZyODIwVGUyQ0pPbENVZCt1U3hkeGcyRzZUS2JJemppZmVOMzVDSHNFY2N2MzFLRjlkeUJMSWxNME8xWTViajFjSEk2TzJ2bDk0Sk1DS056eWNGak1KMjVNUnhzWGJhZExzT3ZzRlY5R1o4UEtkcmt1YzhjbnNSbnJkMmRFbmxvcVhpN0J2VTZ6Q0FoKzhUbGhpQ0FBSUcvbWFTQ1VvbW1UNG92bXZFYjZRZkh3K3ZDVFltT01hRGxBSmQ3QjF6WThPT2JydVVWeTlVYllUWDFFaVk3NWFXRmpsKy9EanVJQzh4UURUSkJETUducHNnWmw3SEg4M0FaeGg0bnp5TS85M2MxNHpId3VJeU9YNjZSdmxKN0RQeWNYeHJSQUVKQnlVdE9FVEVVVFlDd0ZETmNRVWsxWkJnc3RHSFJLYzJSOWs0RDRscU93R0pHcEthYk1FZWNJekdqdmhZVEZvTjZudEF3VE1OaFA2cUNySG13WXhBWFB5dVdWZVNNYVdBbzBKY0MwWE42OElIN3hFNWZCQUM1MFltd3pJd2lsNkxrYWwyaEVpTWZXRW5waUh3c1g2Tk9BcHVrVG9Ja2h0eDAwZmxCNmpVWmNHa2VlOFVDVjA4cm8xTnpXdmtXMHNVNThibkEyNXNNR0w5ZUo3OHBlYUoyNEIwSkhOclhmREY5eEFYQndsMHE1YXZRZnM3OWpycVprQ0d3aHc5TmFLNEVyRUJVMWkxNFE0NFJiYnRrdVpwNzlYUk9mcmJHdEFaRGFUbDNGUmdkQ1ZpUHMxM1RlSDN3ZFF5N3psNlhkTGpIdEMyWWQ1amFHbnZoTkF2bHNiV2RyM214MG5OMy9pK2UzQUFRT1hXOC9HaldYNC8yaVBJMUhMTTkzb0grdlZJUzZEZjYwRzZ4aGVQNHdXZEF0NlB1UHZ3ck1mbjFYdDh4cHdTd0VtWW5NSE5OVzY4WmpESkJFT09EcHBFVGFrWGZBNTRCc2Mwdy9pME5IN1VKZE96OXpqUTcva3VlNFpiN3ZLNVFmTHJjb3E3dis4eVRaSHZGbGRVeTk1RFIzVTc1OFJneERsQUFDUnFTRFRadEhnOEtNQWg3bjRjRlFlVUQ5VklvQ0hSWktOWlJYOEVSOWs0N004R1NVQ2loa1NUalQ0a2RXcUhBenJzVDJlcGdqR2k1TmRCUWpqWEJ1dXlTdjg5MDhRS2s2bk9raXlCcEFKeHBtWHA5L1BwaTNKQVE2Si9ZdTg5OTBtd2JERUFxVjhGaUtDcHhjbzQrSFdMQk9TdE9TcW5QL1JKNVp0RDh6Um5PSmt6bUpRbUozUFRSUDd1UWJEV0p3SGtVL2xDWVdvYlJyRU1rT2tiSEl6ME8ybnJOME5UemRCcEMvd3VIRGVSSXhpMVo4R3NCcDhEaUllVEZldmU4eEh4LzdGUXBJZGZnWTNWNnhWSWhSU1Z4Z2JjT24rdTdMampRNmlMVlAyTTFBV1VRWGZCVkpRRE9nK2tjVE9ERWFtd3VFaE9udVhYWWFoaGhPWFZIZHQxazdPVkw3Mm91MWFVVmk2VUY5YXMxeS9iOHBrMUd6YnBsMjI1S1JzQnFiU3lRZzRkTzZwYVZMZXpSelpzM3FUN0VqSGU2aVdMVlN2aHlCakxzNjJ0VFpZdVhTbzdkdXlRNWN1WFMybHBxY2JaMU5ZcXkxYXQxRTNXR04vTXVYTTA3Wm9MdFdONW92L3E2UEZqVWxsZEpUTm16WlNTc2xMWi9NcVdNYTJJaTNNNVMzek8vQVU2MjN2R25MbTZ0SVYwNk5BaFdiMTY5Umd3RWdTUEhqMnE2Yzh0bkNmbFNQTzE3ZHNVNkpnV2ZWOU1hOU9XemZMU210VXl2MmlCekprM1Y5UHJzbmZyTXdRYVB2L2k2cGRrQWZMNjNJem5aZG1LNVhLdTl2d1lJUEdab3ZJcU9YcnFMRnU0SlBHNzlYVVFiS3JZM0RLQ0RiWXVHMm84ekJVS1ppSktOQStwbHBQZklDejhaRGJUNnNGNVIycSsyTC8vT0VyUWJiUUhMOTRsTndyaGFLaThHRWF2c1hXdmVOT01vWFlIR2pUQnFCMm1JTFV1UjU2eGVUNC9ZVjJmUFZVdWZ2SXpFdnpEYkpHRFI4QVVZY2tIanZ6SU1OVmRPZ1VoWFB5Z0laR0J5UEw2WHVuKzliTmlMOGlXcHZ3TUFHK3FoQUVrZllpL0VlQm5uWkl0enZ4Y0ZUZzJsUEZxL0NYeXlJVkhIbEdobzUrSjROdVNEdUZEdmtNNHI4dk1SVjZRcnJuTEcwMWRxRys2dnU1cVVjWVJIZkY4alVYU2MyeTNSRkp1MVh3N2tWNFR6Q0ZxaTl5Z3Z5Y3BXNkl6bnNPRFBzUnR6TE1hd0xtVjd6cmNZbnYwYitVWUJ3UUtPS0ptOE5xUU5SV2Fwa1hhTWl6U2s1NkorazVYL2h2ejhzWDJ0UWNrK093dnhMbWtXRUxiMTR1Y2VGTWlCM2RLWlAwTE12cUhaeVR3bFc5Sno2MzNTbHRtSnRKT2xtQktyb0pPWTNhS25BY0FONk91K1FGS21tM2NwWk5nT0Rya0JVZkdWTldoa1FIa2laVitmY1N5TVlHSUcvc1JpR2FYNExweWtjeXZYZ0l3TWdTYXdUUVpTS3JWWFFOeG9lcmV3NGMxSFc0QndyMkpPTEZ4L1pZdDBtNjNxNytqc0xoRWw0UXd4aTRBK2ZIVFovUWVmK05xL1A0Qmo2YTY2b1dYRkFqcW1wcWxyYXRMNDJEOHpnRm9WL2pkN25iTGZPNExWbGdvYit6Yko0ZE9uTkIwRzYxV25WQlpVbFVsSjJwcWRJTGxpK3ZYNjhSS3hrdWhibXUzNmhZa1hPTkdQczVlcUpjeWdPSGg0eWRVckxnZlVtMTlnL0pWYytHaW1tcm1HcnFEUjQvcGZaN1RCZE1FT2VZNk9hNmI2M2E2NU1TWnM3bzc1ZGJ0Ty9RWkJ0NGowSzljOWFMdU5IQzI1cnlVbEpiTGpwMnZLMDhNbk54WnZYU0Z0TUJzNWFaenIrN1lLY1VsWlFxY3BqTi9EcTRQbkRpbCtVL2lDbXRxQmR4VG1SdGt1Ym12TXI5Nm1wd2lmV25YOEVYWkJQT1FRa2xaQUpOMHFjOU1VY0R6QWp3bzhIVjMzU2JXeDc4bDBhQlB6VUN5eGt4eStRa1pVM3RyT0NUK0wzMUphdStZTG5ZTDk4OHhQaExZQkMyTC9pZ0NFN1dqUHZUQUhBWGovdFd0NmFuU2dtZjVMWG11OW1jUHpla0FmUURBenZRQ0NIQ09ORUs3b0daQS9teGNjb0pqSXdUMURNQXpCTk9TY2UzSm15SlNNVjhiTFh1S3E0SlJ3Q2R0bi9zcXpOTTBzY09zN01sTUYwZHlqazc4SXlDMVpyRU1nMk9xTW91SXBKOGcwaHNUMHpCM2xTUmcrMGZFY1dTbk5LWmtpdzNwY0hDaEUzbHJTMG1SZGtzV1RLMDg2Zi85TTNnQno3TUZVODVqZmdtdGx3UGI1TUwwMnhUSWhyT3pkTjBZVis5eldRL042Qm9BQnJWT2RoWnNEMjZVYlg4eXdSK2RRSEkreXBEYVRnRTZxeXhwdGFBK2tiY2FoQURxazUvbHZnQU5sdVhwUWJteUUrdlBTcGV6N0lCd1RyQnlReU1Hc3F2R3hmeUVBRWJ2eEF4Nlp0VUFvaXJqQXhBNE1zd3NxWkRuRnBUSy9CS0FhY3hNWWcxU2NDZXN6M0hFVGRBT256eXBzNlJacEdzM2JaTEtKVXNVUUxTWUVRMFh5VzdhK3FxbXdWWDc5TTNRSE9LcWZMb2RtSkxUNVphcXhVdmt6UGxhZlk3djl2VDNLNkEwUUNQaU5XZHpGMEliMlhQd29BSWY3ekVRcE9ZVUZjbU9OOThjdTNlaHFVbDU2K3cySE9VWDYrczBidkxEaWJuQm9WRjVZZTBHWGN2RzlIamYzQ1dBT3dTWUkxZ0VId0lMd1lqeDhoNUJoMXVWY0kwYzd6RlB2TGR3NmJLeDkzYnYzYWZ2bUxzWGNPSHVTNnZYNnVadmRPaHo3VjFqVTRzMHdGU2xDY1ozbVA2OG9tSnB0YmJwT3h3bDVKZURqcHpoeHk0NG1zWTVJV3d3VVB0NVpPRGV4ZjFvWkd5c0NTbkJQQ1MzSlVkblUxc0JTTncwalo4OHZvQkdTai9GRUFRcTlDUjY4OTUyR0VKb21xaHR0aEd1aUdMUFRoK1MrRHVrNlcrK2JFd1hRT08zVDBFRGg5RHdZNFpPeXkyNlRFUzN2NEFRZEFKRXlYODNnSlJhM2lCNmZYNFhucjA5TllpK1pKZ08wQUpvanRIM3hLK2d1cElCdkJESUhtcUdBRG11YUc5RnZJRW5mNDhDOUd1anZWckQxZnNqZm1sOStPOTEzZGRGOEVHLzJZQmxpdmp5YnBjR3hNV1BDZmlrbDkra0JRQWhneWgxbWxFY3didXFIWFFaZ1ljb0hrUmxSeThlbGhvQUhiK0J6L1RzMEl6b1MrdE16NVBtNUduaWV1NTVQSThFQ0Y2c2ZXZ0NMTUxlSU9wa0dKcklra1Z5S21VS0FDUkhKM1A2OHl5NmZvd0FSUTJtQS9sdlI1azBJMzZPWHJJRHFRZnduVU1abnNHOVdqelRsb1V5eERrQmh4MUJGOHFkUnc0Mk5PUWJJNnJVcmp0enMzVUxFWUp4SDNoMkpnR1VSNmtSb3N3VWtIVzU4M1VUMnh5RmtvQTBGejB6djdIUHZkZ1ppcXE1K0xSc3pJSE1XalRCaUdRZUp5S2FOa2RQR250ZE0zQ3JFUE1ydFdaWSsvSkdYWWx2WGxQWVp4Zk9WNjJDYVhJenREWnJod292dHgraG9DdlBBQ0tlSHpwMlhNR0NXaFhCd3R4R2hJSDdaL00raGZoQ1E2UGU0eUpjYWpZY2llcm90R2thRE50ZmYwTTFHRzZCVzdWa3VSU1dsT3NXSm55SDhYTVJMclVaOG1VQ0Q4T3hVNmMxWGZPYWVlUldKK1kxQTAwNmJxR3JBSXRyYW45MGhoTjB6S1V1WEhlMzVaVlh4L2hwYld1WGxhdlhxWWIyM0t5NUNzYlVESzBkN1dOYTZ0eWlValhUNko1SnNqLzJKVG1YazZtelpmdnlBUlJvU0J4cDZVU0Q0NmIwaWNod3NSa01YMmtlVWdkNnpUWnFJV2pJRkNMMndwM1pNTE95WU1yZ25NUG5nMC85VlB5aEpnZ3NXaW5rMVEvWm8rOW4xQmRCajRRZXd0RWk5WTgraWdaTmJZME9VZ2hBRmt3cnZNL1BDamxoWXVtV0h3UlVDK0xOVGtjdm4ycjRxQ0JNTGRCNjZOTlJIMHRjNE9laGFiSnc2Z0MzdWVXK1BMMHB0MHZQczgraHN2eTZOL1dWeUFRb0JtNmM0djNkcytBbFRiemdxK2NXYUFTTUU2QkhUU0VJbmprVGh5NTJuZGxNeHpwS1RYZXJORXowaVFrTmp3T3VISnNZYmpnbHR2eTdWZmlEeU5zRjVJSGFJc3U0QWFEdm5QTXMrQTVxYnh5T0dKcW11a1pRcHRSY293Q2t3T1oxY2pCN0dyU2ZWTzBrR21CbXFha0dMWktMV3dsU0JCcCs3NHlERGwzSVZ5Y0F1eXMxQytZMkFDWTFVMXBUMGxGZUZ1MVlQTWd6dFovbXpBTHgvZUM3NHY3eDk5RnhaQ1BmNEE5bFg0OTY1eWVnbUZZQXNOelBURE5ENk1DMEtLNlRxRUdzV3J0V3pSdHFSNldMbGtEMUx6ZkFhQ0ZNbXdyRFoyU0NrV21ta2E3RlZDTVltU1lZV3pjMUlHNERZbW9JNXA1RlhGSFAzeGtvOUJSY2dvZ3BxSzdlUGdVQ21qN2N2K2pOQXdkME1TMkYzQlJ3UjY5YkFZdnZNVjRUTUFodUJDMXpGSXlCMmhkTktZZXpSNGZzZCt5Q0NRUndvc25GcjVrMFdXMnlhczE2QlVwemp5WHVFTUIzK0M3QnlZeUw3OFNERWZOSUh4UFB5UWZmSjJDU0J3SVo3MU9ib3YvSi9LWWNIdEhkQ0JqWS92aEZJSnB3YTE3ZUxMVU56ZExuOGN1ZS9RZTBERXdBcFlPN3BIS2hIRG9PTXcwM2ttVGpjam43bnZjYmpRV0M0MEx2MkQwVkFJSWpWM2dub2tUemtMcS85bVd4Wm1SckR4eWs5Z0doWjAvTTRlWGFLZm5heTlvekliai8rbU1JdHgwUWdDcWd4c0JJS0VRNEtFVTgwdmFyZjVlVzVGdjE0NEEwdzZKbzVHZGpvRWtUc0JYQ3lWNjVHL25vNVhRQzlNaDJtQlZkeVprNlRFL1Rqcjg3OFJ3M3NhY2dFNHc0SjZZWjJvTHRBNStGWWI4ZXdvSStPeGdncEw2TjRvR0lRZkhrOEVucHZPMkRxcTBNNVdaSVBYamlWekg4QUlsQmFwY3duWXlHNVdVTklGL2NqQjV2am1WdUFrSTVVSU5RWGlKNC82ZS9sQ2Jrand0ZXZZamZDMDJtQTJCYm41NHNmYk4vaDRlZ1Y3THNxSDJnWHFpRnNlS1pGSGtOQjl3eWRIQ2JuUHJDcDZVbEowUExoMlowVHdyTXpBd0FPanNQbEtXVlpSa0RPNEswK3FrUXFHRnlIWndWcGhvL0JzQ3liNXA2bDNRODgwZWtDKzFyOCtzd1R6K2d6M1pCby9JaERnS2NGZVVSRkNkQUdMbWg2a3N6L0pvMHc0bkpFSXpUVWxwZExjL09ucTFxUHpXa1l2VEdoZVZWQUFXWTJySG5WR2owLzdXVHVkY1EzeWNBVVVqandZaENUVk1vWG5nSkd0UWFXdHFOT1QwTVhMbFBnTnIxNWg1OWp2WGhHaHhVamFyWjJxNEN6NzJNcUFFUkxQZzduMlBnN3dRcC9tNkNDQUVxM3VSNWVkTkczZS9JZktlenAxZktGeTY1N0I3NUlSaVJQek1lSGsrZXJWSFE1VFhUM2JicmRRVW5tbW5tUFc0Z3g3SXc0eUtBRVZpWU5nTkJpVUJrN25qSkJjSXpaODJSYzNXTlkza2hDSE83bEhodGp0OVZQSExpdFA0T0ZjTXU5dC84WGhwdi9TaE1wd3hvSzhtNnhTdk5LRGE4UkpSd0hsSW9LTjZmUFExTjZ6MXFhakZ1RlNRRUozcFE1eFREUWQyYmRLZjRmek1UYi9PVGpvakxiMVMybnpraDJQbkFlaVFpM29PN3hmYlZiNG9yTFY5T280RlRzOUk1TkRoWGdBSFkyWERzc0JnOU4vMUUzRFNONjdGYXAyYnFPak91eXVjUU4zMWpoM096cERudE52RTgvbStvNFRaa0FJbFJrSEgwUnlnMWwyZzhFREZRN21tcVJWQXhYYmQvQ0dBSFFPZWFMUEJFY0tySm5LYmdRMkJWbFlEelIxQTI5SjdnOWNRRUJLRzF4ZXpyS0Z6VFJUbjhqWWZrUkZhMmFvWUVDUzd6YUFEZzlqLzNERm9PQUNzRzRvTW91RUZjOEhQZWVpT21qSG5wVGJlZGs2RS9QQzNOdDl3cFZtZzFEb0FtUVljbWJUUEtrclBkR3dwd3hIa3I2b3l6dHptcm5xT0UxSEFKL2cyWmFkTC94T01pNTQ4alg0aVorVUZXbTMvOEM2bUJ1ZFlHcllqN2FiTXRkZDJhSitFb1Ixb0k5SGlPREdtWlhCK3hqWENVYTgvK2ZRcElOSDFtenkrV29xcUZNcXVvQktCUUJZRXo5SGV5cCtZQnpMTnJkV0FYemkrUzAyZHE5RjMyL212V3J0Y2VuOWRzS2dRZkNxcHBEakZRMkNuME5IY09IVDRxNTJzdjZyTnZ2TFZYelJScVIvUUwwZi9FN1VEY2ZjWW9sYTJ6VzFmamo5OEhteE1veTZIMTJSMU92YWJncTZaVlhLckQ1ZlM5N0h4OWx3SVdRYUsrdVUyLzR2TXNUQ1A2ZWFpcHNmb0pZTlNlcUMxUjI2TWpuZnhTNnlFWXFkemltczlUQ3lMLy9LUlNQTjk4bmtCTTA1V0FHOC9udXZVdlh3Wkd6QnY5VnZRYnZibnZvRzQwOS96c09mTEdtN3YxR1pyTTg2SEZybDYvVWI4eGwwVExUVHk5RXQyeFhicWYvRmRwK1BvM3BPNHJEMHZISS84Z3ZtLy9FSzhrb0FUemtQUnpPZHgyNFV5dDlNK1pKUTNmZkZUYzl6OGsvVjk4UkZvZS9vYTBQdmhWY1g3OU1SbjQ0dmVsNWJzQUJKOGZNa1BYcHJHaHZ3cDdDR0lJVkdKQnFUZ0ZYSWp2bU1qUGZ5dUJXKzhXSndTVFMwWW9TQzRJQzdVZkRuZXpoeWZ3YWMrTyt4ekdwbk9hd3RFNmRaclkvL3ZIUldZdUVuSGFFUzF5RURWY3F2WWh3OU52Skg2SjRrSElKTXFWa3hrSElNa1JtRkUvZTBwOVNOMFBmbE5OeS9hZlB5R08ySU13VEhDQ1hBREFSNUhMWUt5OEppSk9vV2YwVVpTQlA4Q0pvWGpmYlpmUXNxWFM5dGova3ZhdlBpcHRqLzY5T0wvMUF4bllzRWtDc2ZWK0JCM09RT2RubUhUUkgvSkNrNDFhbHBaakNNZ1V3bE9oZHRUOWV1bCsvRWZTOXZGUFMydkJYZEFnODFDV3VkQWFwOENVblFMQXkwZklnV21iSjIxMzNpTmRmL2N0a1JYbFFKMlRScm1GZEZlalMyMGdCQkRmdjF2NnZ2ZTQxSC85TzNMNk85K1I0TC84QklDS3ZGQXF3UWZyV05jaVhpZFIwMkZ0Y0JKaGJYMmRqa0p4eEd2RGxsZGxEUVRqNEZGai8yZ0dQa2ZUZ0hTdFlNUzloNXBiMnBSdHZuL3MrRW5adC8rZ25qTXdGZ0lBQmRZMGh3aFFPOTdZclJ1aUxWK3hTdW9ibXZSWm1rbDAvTkp2UkxOeXd5dXZTSHRINTFoY0hKWGlQa1U4YWpFaEVBQUpUaHlaNHNnY255TVlFY0Eydkx4Si9TKzh4eEdxVjdadFYyMkZFeTVmMjdWYlI5U1lWdnltYndRVSttNWVXTE5XVHA4N3IvYzQ2c2QzNDAxRGpyelJOMGJBWVJ3MHNmZzdmeU1ZY2E2U21xWnhlMzd2ZVd1ZkhEaDRXTS9KTnplQVc3THlSZlVaTFg5aHRmcW1xQWxTaXpNbmFoNDllUWJndUJueEg0Sm1oTGJLZ2ZBK0ZTdW8yWDdBQjB3aXJxUTNaaEFtb0FUemtQcVJQVjE0cVNVR1lROGJYeElkSFlWWTBPeGd1aEVPTVliUlgrTTlUbFQwZXZCR0NObzhmZ3NFVkFENWxSSisvb2piYnVpWFJ5Qlo1Smd0Mm05dEV2Zk9yV0tiL1p3NC91K1BwT09yWDVPQkJ4NlM4UDJQeU1DRFh4TDdnMStRTG1nVGc0Ly9IeEdveXJKbm53eTVuV3I2Y01TZGdrdHRqT2x4bnlJQ05ISElEN1pOaWdlaWVEQWlFM3gvSUJUUkl6VVJIZEVLY0FJWVloOXNrZWJZY3pSQjlkT1BLQ3Z1aG5rdFZncjNidUpucDdYOEVIVS9HR09ETUFDR09TRFlvQ3p0Ym4yR1N6b1VjVUpzemVRRFhJRVhBanR2cTUrRzhvaEk2TG9oZ0dqOWtNRlI5TkRCRHVsclBpeDlSM1pLZE85T0dkMTdUQWJmM0NmOUoyR3E5SGJvY3pUOXlBTS9nTWs0R0ZoZVh2MFdHaU5IZlBqVC9ERzdMQm0zUTdwd09lcUZ3T0k5K282RzN3R25FWG5STldJNFp3aHd4QTcxdzYraHNQV2FNNWdKVml4Q2FoRW1YWXNEVzR1ZE8wNHdTN2pndFhtUFI4Wk40VFFGMVRSdEdIalBmSTRqVEx4bkFoWjU0eVpxL0kxVFRzd2xKZWJYbHhuTTlKaTJHYytWZ2puYjJZelhQSEpFamVjTThUNGkvUTJ5YlY0em1IeHpYcExKSXdQZmk3K09OMDgxTGZCR0hzaHJmRjU1SkZEeEdZNm1tUi9CMURoUUIvemRlTWJNaDhqL0E4eVBJcE9TNXk0ZUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiJmN2M1NThhMC1mNDY1LTExZTgtYjU2OC0wODAwMjAwYzlhNjYifX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMjkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IktPTkEgRklETzIgQklPUEFTUyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNDAyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMjkifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA0LTI5In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiZGQ2NmEwOWE0NmExYjdhZDU0Y2EzMzVlZmRhZGEyZmNhYmY4NGJjYiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJkZDY2YTA5YTQ2YTFiN2FkNTRjYTMzNWVmZGFkYTJmY2FiZjg0YmNiIl0sImRlc2NyaXB0aW9uIjoiU0hBTE8gQVVUSCIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCbURDQ0FUNmdBd0lCQWdJVUJJZ2ZYcGQ1d2tNcXhoS1d0aFhqNXJwNHd6OHdDZ1lJS29aSXpqMEVBd0l3S1RFbk1DVUdBMVVFQXd3ZVFWaEZURXdnVlRKR0lFTkJJRk5sY21saGJDQXhOREl5TkRVME1UYzFNQjRYRFRJd01ESXdNekEwTlRnd05sb1hEVFEzTURZeU1UQTBOVGd3Tmxvd0tURW5NQ1VHQTFVRUF3d2VRVmhGVEV3Z1ZUSkdJRU5CSUZObGNtbGhiQ0F4TkRJeU5EVTBNVGMxTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZXNjTUpKOERPRW0zNmR1U3pleW0rRUhNZTczRk9vTUpTaHYxam1QcjRQM0tvbWRVQXkrMTNyL2VueXdMNkQwYTQxSDZmb1JTVnUwQkk4V25zeHhEY2FORU1FSXdEQVlEVlIwVEJBVXdBd0VCL3pBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVUyUmU0SXUySS8rS1h1d0g2RU1KazNxck0vV0F3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQVBSQ3FyRHNJQU1vRjliU1JOSjlqaWVTekVEU1VNUWsvLzRrVEdMYjNHZUZBaUJkZzU1TVF1NHJTN1RQcURVWWhsS1JQeDh1eHp4QUJjMFFGNGVDOCtFckRRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBUUFBQUFFQUNBWUFBQUJjY3FobUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFXb21sRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYXJaaFhVQlhkc3NkN1ppZlliSExPYk1JbTU1eHprcHlEQ0d4eXp0a0FvcUtDa2lRSnFJQUJFUVVFUVFRRFlNQUFDQ0tDSWtvUUFVVkZFVUZBdVEvZkZjODVWZWZoVnQxK21WLzlxMWYzNnVsWk5hc2FnR3VOR2hNVGdUSUJSRVlseERtYUd3bTVlM2dLRVdZQUFRNGdnZ2hncVA3eE1ZYjI5dFlBQUgrZS8yNC9YZ0FDQURBc1M0MkppWUQvbXpFSEJNYjdBeUQyQU9BWEVPOGZDWUJjQTBBMi9XUGlFZ0F3VFFBZ2twd1Frd0NBZVE0QWJISHVIcDRBbUhrQVlBditoemNCZ00zUDNjTVRBTXNFQUd4eHpvN0dBRmhSQUJvU2xSb1hERUJTQUFDaEpQL2dCQUNTUFFDZUpTb2dOQXFBSlFBQXIrY2ZRZzBBNERvSEFES1JrZEVCQUZ5REFDRGg5eTl4Z3Y4dHB0OTJUQ28xZUp2L3FRVUFBR2hNUXVOaklxaXA4UDl0a1JHSmYzSlFBSUFVRW1maENBQ2lBTWhZZUxUVk5rZjUyZHI5NGRBQWdEOGNrbWpoOG9mOTQ0MDkvM0FBMWNScWUyMkVyZlVmRGdvMXM5eU9rMkRwL0ljRDQwMmQvbkJjdE9OMnJxQTRZOE0vVEkzN216Y3gzR1ZiRHdtMDNJNmZGdUxzOW9lVFFsMXQvM0I4dUpQVlh4L2piVDB1MFhGNy80RlI1a1ovODVwdDF4NFoveS8xaGxwdXIwMEljYmJZcnAzNmQvK0JVWVovWThhN2IrOHRJTkRFOUsrUHk3Wi9USUxSZHE2WUNQdHQvOEFJODIwOVBzbHBlMjFDblBOZi93VDc3WGNZUnQxaC80ZkJHa3pCQklUQUdFSWhDZ0loRXFnZ0JDWVFDdkVRQXhGQWhkU0V3SlFFQUFEajZKalV1TkRna0FRaHc1aVlpRUFoeXloL09Sa2hKUVZGVFFCM0QwK2hmejZQWlVkQUFBRGhlUHBYaTAwQTBOSUVRRS85MWFqU0FCMHlBR3lYLzJxaWFnQjBGUUNkTS82SmNVbi9hRmdBQUJ3UWdSSFlnQnNFUUFRa1FCYVVRQTIwd1FCTVlRZllnVE40Z0RmNFF3aEVRaHdrd3g3WUQxbVFBL2xRRE9Wd0JzN0NSYmdDelhBZGJrSTNQSUFuTUFnak1BNlRNQXNmWVFsK3dBYUNJQVNFSG1GRnVCRkJSQXlSUnBRUURVUVBNVVdzRVVmRUEvRkZncEVvSkJIWmd4eEFjcEJDcEJ5cFJ1cVFxOGdOcEJ0NWhBd2hMNUVwWkFINWhxeWpHSlNFc3FIOEtBV1ZSelZRUTlRS2RVWjNvY0ZvTEpxR0hrUnowVEswQnIyTXRxSGQ2Qk4wQkoxRVA2SXJHTURRWVRnd1pJd3NSZ05qakxIRGVHS0NNSEdZZlpoc1RBbW1CdE9BNmNEMFlvWXhrNWhGekU4c0hzdUtGY0xLWXJXeEZsZ1hyRDgyRnJzUGV3eGJqcjJJYmNQZXd3NWpwN0JMMk44NGVod2ZUaHFuaGJQRXVlT0NjY200TEZ3SjdnS3VGWGNmTjRLYnhmM0E0L0VjZUhHOE90NEM3NEVQdysvR0g4T2Z3amZpdS9CRCtCbjhDb0ZBNENaSUUzUUpkZ1FxSVlHUVJUaEp1RXk0UTNoR21DV3MwZERSQ05JbzBaalJlTkpFMFdUU2xOQmNvcmxOODR4bWptYURsb2xXakZhTDFvNDJnRGFWTm8vMkhHMEg3VlBhV2RvTklqTlJuS2hMZENhR0VmY1R5NGdOeFB2RTE4UmxPam82WVRwTk9nZTZVTG9NdWpLNkpycUhkRk4wUDBrc0pDbVNNY21MbEVqS0pkV1N1a2d2U2N2MDlQUVVlZ042VC9vRStsejZPdnE3OUcvbzF4aFlHZVFZTEJrQ0dOSVpLaGphR0o0eGZHYWtaUlJqTkdUMFpreGpMR0ZzWVh6S3VNaEV5MFJoTW1haU11MWpxbUM2d1RUS3RNTE15cXpJYk1jY3lYeU0rUkx6SStaNUZnSUxoY1dVSllEbElNdFpscnNzTTZ3WVZoRldZMVovMWdPczUxanZzODZ5NGRuRTJTelp3dGh5Mks2d0RiQXRzYk93cTdDN3NxZXdWN0RmWXAva3dIQlFPQ3c1SWpqeU9KbzVYbkNzYy9KekduSUdjaDdsYk9COHhybkt4Y3Rsd0JYSWxjM1Z5RFhDdGM0dHhHM0tIYzVkd0gyZGU0SUh5eVBGNDhDVHpIT2E1ejdQSWk4YnJ6YXZQMjgyYnpQdkt6NlVUNHJQa1c4MzMxbStQcjRWZmdGK2MvNFkvcFA4ZC9rWEJUZ0VEQVRDQklvRWJnc3NDTElLNmdtR0NoWUozaEg4SU1RdVpDZ1VJVlFtZEU5b2ljeEh0aUFua3F2SkErUU5ZWEZoRitGTTRVYmhDUkdpaUlaSWtFaVJTSS9Ja3FpZ3FJM29IdEY2MFZkaXRHSWFZaUZpcFdLOVlxc1VjWW9iNVREbE9tVmVuRXZjVWp4TnZGNzh0UVM5aEw1RXJFU054SE5KdktTR1pMamtLY2xCS1ZSS1ZTcEVxa0xxcVRRcXJTWWRLbjFLZWtnR0o2TXBFeVZUSXpNcVM1STFsRTJTclplZGt1T1FzNWJMbExzdTkxbGVWTjVUdmtDK1YvNjNncXBDaE1JNWhYRkZGc1VkaXBtS0hZcmZsS1NVL0pVcWxKNHIweXViS2FjcnR5dC9WWkZXQ1ZRNXJUS215cXBxbzNwWXRVZjFsNXE2V3B4YWc5cUN1cWk2cjNxbCtxZ0dtNGE5eGpHTmg1bzRUU1BOZE0yYm1qKzExTFFTdEpxMXZtakxhb2RyWDlLZTF4SFhDZFE1cHpPaks2eEwxYTNXbmRRVDB2UFZxOUtiMUNmclUvVnI5S2NOUkF3Q0RDNFl6QmxLR29ZWlhqYjhiS1JnRkdmVWFyUnFyR1c4MTdqTEJHTmlicEp0TW1ES1l1cGlXbTc2eGt6WUxOaXMzbXpKWE5WOHQzbVhCYzdDeXFMQVl0U1MzOUxmc3M1eWFZZjZqcjA3N2xtUnJKeXN5cTJtcmFXczQ2dzdiRkNiSFRZbmJGN2JpdGxHMlY2M0F6dEx1eE4yRS9iaTlySDJuUTU0QjN1SENvZjNqb3FPZXh4N25WaWRmSnd1T2Yxd05uTE9jeDUza1hCSmRPbHhaWFQxY3ExelhYVXpjU3QwbTNTWGQ5L3Ivc1NEeHlQVW85MlQ0T25xZWNGelphZnB6dUtkczE2cVhsbGVMM2FKNzByWjljaWJ4enZDKzVZUG93L1ZwOFVYNSt2bWU4bDNrMnBIcmFHdStGbjZWZm90K1J2N2wvcC9EREFJS0FwWUNOUU5MQXljQzlJTktneWFEOVlOUGhHOEVLSWZVaEt5R0dvY1doNzZOY3dpN0V6WWFyaGRlRzM0Vm9SYlJHTWtUYVJ2NUkwb2xxandxSHZSQXRFcDBVTXgwakZaTVpPeFdySEZzVXR4Vm5FWDRwSDRYZkh0Q1d3Sk1RbDlpUktKaHhLbmt2U1NLcExXa2wyVFcxS1lVNkpTK2xLbFVvK216cVdacFozZmpkM3R2N3RuRDNuUC9qMVRldzMzVnU5RDl2bnQ2MGtYU1QrWVBwdGhubkZ4UDNGLytQNytUSVhNd3N6dkI5d09kQnprUDVoeGNPYVErYUg2TElhc3VLelJ3OXFIenh6QkhnazlNbkJVK2VqSm83K3pBN0lmNXlqa2xPUnNIdk0vOXZpNDR2R3k0MXU1UWJrRGVXcDVwL1B4K1ZINUx3cjBDeTRXTWhlbUZjNmNzRG5SVmlSVWxGMzB2ZGluK0ZHSlNzbVpVbUpwWXVsa21YVlorMG5Say9rbk44dER5a2NxakNvYUsva3FqMWF1bmdvNDlleTB3ZW1HTS94bmNzNnNWNFZXalZXYlY3ZlZVR3BLenVMUEpwMTlmODcxWE85NWpmTjFGM2d1NUZ6NFZSdFZPM25SOGVLOU92VzZ1a3Q4bC9McTBmckUrb1hMWHBjSHI1aGNhVytRYmFodTVHak1hWUtteEtZUFYzMnZ2bWkyYXU1cDBXaHB1Q1oycmJLVnRUVzdEV2xMYlZ1NkhuSjlzdDJqZmVqR2poczlIZG9kcloxeW5iVTN5VGNyYnJIZnlydE52SDN3OXRhZHREc3JYVEZkaTkzQjNUTTlQajNqZDkzdlByL25jRy9ndnRYOWh3L01IdHp0TmV5OTgxRDM0YzFIV285dVBOWjRmUDJKMnBPMlB0VysxbjdWL3RZQnRZRzJwK3BQMndjMUJ6dUdkSVp1UDlOLzFqMXNNdnpndWVYekp5TzJJME12WEY2TWpYcU5UbzRGak0yL2pIajU5VlhTcTQzeGpOZTQxOWtUVEJNbGIvamUxTHlWZk5zNHFUWjVhOHBrcW0vYWFYcDh4bi9tNDd2NGQ1dXpCOS9UdnkrWkU1eXJtMWVhdjdsZ3RqRDRZZWVIMlk4eEh6Y1dzejR4ZjZyOExQSDUyaGVETDMxTDdrdXpYK08rYm4wN3RzeTlYUHRkNVh2UGl2M0tteCtSUHpaV3M5ZTQxeTcrMVBqWnUrNjJQcmVSdkVuWUxQc2wrYXZqdDlYdjExdVJXMXN4MURncUFBQmdBQUFOQ2dMNFZndEE3d0hBT2doQTNQblAvZnAvRFlNQW9BRGdpc2doSDlGVEdHK3NKSTZBKzRwZklJelN2S1dkSXE2U2NQUVVCaXZHQktZcTVsRldPalk5OWpTT1JzNDViaWtlS204cDMxTUJuS0NxVUNBNVY3aFo1Sm5vWndvcXppREJLRWtuaFVyOWxQNGtNeVU3TEhkWHZsWGhuR0srMGw3bE1CVlhWUU0xS1hWVzlVMk5XYzArcld2YWxUb0hkTVAwSFBYMURHUU1CWTA0akpsTWFFMnhwci9NVnMyWExPWXRKM2VNV1ExWTM3ZTVhZHRpZDhYK2trT2Q0eVduSzg2TkxsZGRXOXhhM0s5NVhQTnMyZG5zZFhWWG8zZWpUN052TzdYYnI4Ly9aY0Q3d085Qld5RjBvUnhod3VIU0VhcVIrbEdXMFM0eGdiSEpjY2ZqTHlUY1NSeEwrcHBDbXlxVXByN2Jkby8vM3BSOTJlbWxHVlg3cXpQUEhDZzdtSGNvSzJ2MzRkZ2pRVWM5czIxekRJK3BIcGZJNWN0anlhY3JvQzJrTzhGVXhGVk1McEV1VlNuVFBXbGFibFBoVXJuemxQL3A4RE1KVlJuVitUWFZaMXZQUFQ3LzlzTDNpelIxZkpmazY0MHV1MXdKYmtocFBOSlVjcldtdWI2bDVWcEg2NTIyKzljZnRmZmZHT29ZNlJ5N09YN3I3ZTEzZHo1MnJmUmc3ckxmazdpdjg4QysxLzloOHFQc3g1VlBHdnU2KzRjR0pwOStHbHdaV24rMk9ienhmRzFrNWNYWDBVOWo4eTluWHIwWkgzdjliS0wvemNPMzl5Y2ZURDJlZmpZejhXNWhkbVVPbVNjdGNIMFErU2kzcVBuSitMUGxGNnNsazY5SzN6aS9mVnZ1L1g1eUpmeUh6aXJENnR1MXhwOFo2dzRiNUkydm05Mi9Dbjc3Ymlsc2JmMWIvK1Z3UXJobC9BTGhBODAwN1ZjNklrbU0zcFFoaERHUHFZZDVtVldXellmOUpNZHpMbnB1RzU1RHZGMThQd1NrQlgyRWpwR3ZDYjhRK1M3R1NPRVRwMGlRSmJtazZLVFdwS2RsQm1RNzVNN0tIMU5JVXZSVnNsUldVT0ZVK2FYNlR1MnhlcU5Ha1dhYWxyZTJrUTVGbDBiM285NlFmcnZCV2NNQ28wempaSk1JVXo4elYzTXJDejFMeFIwaVZ1eldCT3MxbXcrMnIrMkc3Qjg2OURqZWR1cDBibmRwZFcxeXEzZS80Rkh0V2I2enlPdjRyc1BlbVQ3cHZ1blVUTDlzL3hNQmxZRzFRVTNCN1NGZG9RL0Rub2FQUkx5T2ZCZTFHTDBXaTQvampKZEpNRXAwVDRwS1BwQlNtbm81N2M3dVozdmU3VjFKUnpPSSt4a3lTUWZ3QjM0Zi9INW9JV3ZpOE5DUiswZmJzK3R6VGgvTFA1NlptNXdYbVI5Y0VGd1lkaUt1S0szNFFFbE82WW15aXBNMTVYVVZUWld0cDI2ZTdqbnpwT3BGOWJ1YWxYUDQ4MXdYcEdwMUx0clcrVnlLcWMrNG5IK2xxcUd4OFZiVDQ2c2p6VzliNXE4dHRhNjFiYlhqYjlCM3NIWHkzQlM2UmJrdGMwZTVTN2Q3UjQvSDNZaDc2ZmRQUEtqdDdYalkvMmp5OGJjK2JEL0hBT1dwNnFEUmtQVXpwMkczNTU0alhpKzhSMzNHZkYvNnZxS09VMTlUSjZodnFHLzlKME9tWXFiM3pHUy9LNSt0Zjk4NTF6Yy9zZkRwdytZaTZSUFBaOG9YdVNYNXIrTGZPTDl0TFU5OTcxNnArckZ2MVd0TjZ5Zlh6eC9yd3h0Tm04ZC9oZjAyMnhMNWovNy85L00vd0VwazAyR1A1MmprL01JdHhlUFBXOEgzWElCZVVFY29uRndxZkZ0a1d2UTNoVm1jTENFbEtTa2xMazJXNFpGbGtxT1ZCL2xsaFRuRk1hV0h5bTBxRjFTTDFRNm94MnJzMHJUU1V0Y1cwV0hRV2RPZDBSdlU3ekpvTWJ4b1ZHVmNZVkpzbW10MjJEekRJc1V5Wmtld2xiZTFzNDJsclo2ZG1yMjhnNlFqeFVuVVdkaUY3Q3JveHVmTzdjSGh5YktUNUVYWWhlejY1ZjNUWjlWM2picmhqd2JRQkRJR2NRVHpoWkJES1dGUzRmSVJTcEdxVVpyUitqSG1zUTV4UHZFeENSbUpCVW5WeVZkVHVsS2ZwazNzL3JobmJSK2FUc3dnN2FmTlJESy9IM2gzOFBtaG5xekd3NmVPWkI5TnpLYm0yQnpUT0M2U3k1ajdLKzlUL25UQjY4S3hFNk5GWThVdlM4Wkt4OHBHVDc0b2YxNHhYRGwwNnVucC9qTURWVVBWTDJvbXpyNC90M1IrdlJaN2tiNk8vWkpBUGVXeTNCV1ZCcTFHL1NianF5Yk5waTBtMTR4YURkcDByMnUxcTk5UTdwRHZsTDVKdVNWOFcrQU9ieGR2dDBDUDZGM1plK3IzalI3WTlMbzk5SHNVOFRqcFNYcmZrZjZDZ2JLbnB3ZXJoMnFlVlExWFBpOGRLWGlSTTNwd2JPL0w1RmZSNHlHdmZTYzgzamk5dFo5MG1IS2I5cHVKZlpjNVcveis0bHpuZlAvQzVJZHZpOWhQYko5RnZ5Z3Q2WDQxK1dhMmJQYmRlRVgvaC9hcTJwcmlUK2wxeW9iUUp2Y3YxdC8wVy9pdExZQi81aXdBQUhnMWdIT0RBQzZIQWF3TEFFNXJBMUNJQUNRR0FIdDZBR2ROUUkzeUFGVldCbFRoN1BiL0F3RXMwQUlUY0FFWnBFRWRqTUVCZkNBYTBpRWZhcUFWSHNFRUxDTkVoSXhvSWM1SU5KS04xQ0lQa0ZrVWowcWcxbWdzV29aMm80c1lib3dGSmczVGlKbkhpbUw5c2Vldzh6ZzVYREt1QjgrSTk4VzNFR2dJdm9ST0dpNmFGSnBYdFBxMHRVUm00ajdpSnpvZnVpR1NDZWs2dlJUOWFRWjJodU9NTkl5SG1IQk1oNWxKekNkWStGbnFXTlZaZTluYzJPYllVem5vT0tvNDFUa0h1U0s0aWR6MVBMWTgzM2tyK2N6NWx2bXJCR3dFMWdWcmhWeklPSEtiY0pnSVdlU1ZhTEdZSTRXVk1pSmVMdUVyS1M3NVNhcEZPbFZHWHhZdisxU3VRajVFUVVPUlR2R3RVcHR5dmtxRXFyV2FrcnFBQnFzbWd4YVROcWNPV1ZkZVQxL2Z5U0RNOEtCUnRYRzN5WXdad1Z6S3dzb3lkTWNocXlyclRwc3gyMVY3YmdkZHgwQ25QT2RPbDQ5dWZPNTJIcG1lMTNiTzd1THdOdk5KOXEyblR2cHpCemdGRmdRTmhiQ0d1b2RWaFM5R2FrZmxScy9GbXNiVkp0QW5KaWU5UzNGTzdkMnR1NmR0bjFKNjAzN0Z6T2FEeW9ldUhwWTljaUZiSUtmc09HdHVRVDV6UWRFSm5xS2FFdG5TenBNMjVUT1Y2YWRGemd4V0h6cHJlQjV6NGRIRndrcytseFVhTUkydnJsNXJLV2lOdmU1d1E2R1Q3dWIwN2RhdXJCNzNleklQME43eFIyMVBpdnVUbm5vT0dRMHJqRWlNS3IxMEdTK2IySmhNbXQ2Y1BUelArZUh5SjdNdjc3NGRYcEZmZmIyZSs4dGthK3RmK3M4SlpKQUdOVEFHZS9DR1NOZ0x1VkFGTGZBQXhtRUpJU0FDaURwaWo0UWpXY2hacEJ1WlJCRlVCRFZEdzlGQ3RCTjlqMkhGR0dFU01aY3c3N0JrTEJWN0hydUlVOEdsNC9yeC9QaG8vRDBDSHlHSk1FeWpSRk5FODVQV2wvWXhVWjE0Z1k2YjdqZ0pRMG9qZmFVUHBaOWkyTWt3eXVqS09NcTBrMm1hT1p4NWxlVVFLd2RySFpzZTJ6QjdLUHNXUnltbkltYy9Wd1EzQTNjemp6c3Z5dHZBNThWUHozOUhJRTVRVEhCTUtKdXNTLzRtZkZHRUtzb3ZPaTVXUWZFV0Z4WC9LTkVxbVNGbExjMHBQU1BUSUpzcVp5YlBKaityMEs2WXF4U29iS0RDcDdLaE9xRjJWNzFSbzFxelhLdEN1MGFuUWZlVzNxRCtlNE10STE1akxSTXYwLzFtZGVaREZqOTNDRmpwVy92WTdMVTlaWGZiZnRxUjFrbkoyZHZsdU90dHQyVVBTVSsvblJWZXc5NUVIMFBmRk9wVnY0OEJFb0hCUVhYQm4wSlZ3dmFGUDQ3a2pncVA3b3Jsamt1S0gwM1VTVHFYd3BpNk4rM3pIdXJlc1hTSGpQNU02d1A5aCt5em5oMXhQRHFVWTN2c2NhNUZYbStCWmVGQWtVdnhtOUx3c3ZYeVk1WGtVNTFuUEtwKzE5U2Y4NzdBV2Z1OHJyamU4d3E1WWJIcFJuUDJOZTgybFhiNkczT2RkMjRWM1Fuc1Zya0w5L29mVkQ2TWZHelF4OW0vOUxSdnFINDRkeVJwTlBobDhIamFSTzNiajlPRzcycm1pQXVKSDJjL2V5NDlXN1piR1Z4elhYLzdLL0xmK3YvZnovOGJXRWFJaURDaWhUZ2pVVWcyVW92Y1IyWlJIQ3FPV3FFeGFDbDZCLzJBNGNDWVlwSXg5WmhwTEQvV0UxdU9mWTBqNDRKeFRiaE4vQTU4QmY0THdaUndpckJHNDBMVFNzdEp1NGQyaG1oRDdLQ1RvQ3NqMFpEU1NJdjBQdlRQR2F3WkhqQWFNWFl6R1RFOVlMWm1IbUdoc254aDNjZkd3RmJGcnNUK2dNT0w0enRuSHBjTVZ4OTNGQThyVHlkdklCOExYeGQvaklDUXdLRGdmaUVsb2Zma0NtRW5FUWFSSjZJNVlqWVVac3BMOFJxSlNFbE5LWnpVa1BRcG1WQlpkVG1DM0V2NUJvVkRpdDVLV3NyY3l1c3FiMVI3MVZyVjZ6VXVhalpvZFdyMzZVenBydXR6R0tnYXVodnRNNjQxR1RiRG1DdGIrRnZtNytpd21yYWh0VlcwODdRLzdIRGRjY0Zad01YTnRkQnQwSVBKMDJsbmlkZVlONC9QVHQ5SzZodC9rWUN3d0d2QlNJaDlhRTNZYW9SZFpIMDBNU1l5ZGlUZUtLRTVTVHk1S3BVdnJXSVAzOTZhZEttTTFrempBODhQaFdSdEhzblBKdWMwSGRmTmZaVHZXdkQrUkVveHFlUmNtZDdKOFlyZHB3Uk8zNnVLcmhFOCsrSjhjYTFubmRpbGxjc1BHODQwcFRhN1hWTnY0MjFIYnl4Mmp0N3F2bFBiblhYWDU3NWlML0p3OEhGVlg5eUErYURnME0vaEZ5TnRvK1V2OTQ5SFRmaTk5WmtLbmttZFBUSFhzakMyQ0orbGx6eS9IZnZlODJQanAvcEcwcThiVzFzQThVSEtTZ0FBZ0pDTUFIQnZ0cmFXS1FDRVFvQmZCVnRiR3pWYlc3L09BbUJlQTNSRi9ETzdCd0RBTXdFVVV0QzhJZkZITnprei9uT0cvais4dDI3RURkTEFTZ0FBQUNCalNGSk5BQUJ0bUFBQWM0NEFBUGgvQUFDQzZnQUFjS0lBQU90YUFBQXc1QUFBRDdjRHJINTJBQUJaamtsRVFWUjQydXhkZDNoVVpkNDk5OTdwdlU4YUpJUXV4WVlLV0JERnRvSzZpQ0ppNzcydHJMcnUybnV2NjlycjZuNG9ZbDlGZDFHa0dZb1VJYjFPa3BsTTcrMjI3NC9KblUwZ0NRRVNpcnpuZWZMc3FqTzVkeWIzbkY5NWY0VVNSUkVFQkFRSEptanlGUkFRRUFFZ0lDQWdBa0JBUUVBRWdJQ0FnQWdBQVFFQkVRQUNBZ0lpQUFRRUJFUUFDQWdJaUFBUUVCQVFBU0FnSUNBQ1FFQkFRQVNBZ0lDQUNBQUJBUUVSQUFJQ0FpSUFCQVFFUkFBSUNBaUlBQkFRRUJBQklDQWdJQUpBUUVCQUJJQ0FnSUFJQUFFQkFSRUFBZ0lDSWdBRUJBUkVBQWdJQ0lnQUVCQVFFQUVnSUNBZ0FrQkFRRUFFZ0lDQWdBZ0FBUUVCRVFBQ0FnSWlBQVFFQkVRQUNBZ0lpQUFRRUJBUUFTQWdJQ0FDUUVCQVFBU0FnSUFBQUNEcjd3c2ZlT0NCdlg2ekZFVkJvVkNBNTNrb0ZBclUxZFhCYURSQ3A5UEJZREFna1VoZzA2Wk5HRFpzR0lxTGl4R05SaUVJQWxwYlcrRjBPcUZVS3NGeEhFd21FNnFxcW1BMm0rRjBPcEhOWmlHS0lqd2VEd0tCQUVhTUdBR2F6bW1qUXFIQWhnMGI0SFE2TVhUb1VIQWNCNVpsc1hYclZoaU5Sb3djT1JMQllCQTZuUTV1dHh2eGVCeWpSbzBDeDNGUXE5Vm9hR2hBTnB2RmhBa1RFQXFGd0xJczlIbzlXbHRia1V3bXU3MTIwNlpOU0NhVG1EUnBFbGlXQlFCNFBCNWtzMW1VbEpTQTR6aG90VnBFbzFHNDNXNlVscFpDRkVYSVpETFFOSTNXMWxid1BJK1NraEprczFtWXpXYTB0TFNndWJrWlk4ZU9oVmFyaFVLaGdOL3ZSMlZsSmNhTUdRT3oyWXhNSmdPYXB0SFIwUUdMeFFLV1pXRTBHZ0VBTlRVMUtDa3BnY0ZnUUR3ZUIwM1RZQmdHRFEwTk1Kdk5VS3ZWTUpsTWlNVmkrTzIzM3pCOCtIQTRuVTdFWWpHd0xJdjI5bllVRlJWQkpwTkJFQVFZalVaVVZWWEJhclhDWnJPQlpWbXdMSXQwT2cydjE0dWlvcUw4TlJpR3dhKy8vb3JpNHVMODU4OWtNcWl1cm9aS3BjS1lNV01RaThXZzFXcmhjcm1nVkNwUlhGeU1aRElKalVhRHRyWTIxTlhWb2FTa0JLV2xwUUFBbFVxRnhzYkd1Nzc5OWx1YndXQUluM0xLS1d4VFU1TnI2ZEtsM3BreloyWVBQL3p3MkJ0dnZORkVVUlI3MzMzM1pTb3FLckpQUC8wMGJyamhCcHgvL3ZtNDY2Njc0SEs1OE5oamp5RVdpK0gyMjIvSG1XZWVpVXN2dlJTUFB2b29LaXNyY2UrOTk2S3FxZ3ByMXF6QmZmZmRCNy9mRDFFVTl4aFBqai8rK0lFWEFBS0MvUkdpS0lLbWFkanRkalExTlIyNlpNbVNmNnhmdi81SVNiVGVmdnR0MERRTm85R0k1Y3VYWThXS0ZjaGtNbW0xV3MwKy8venpxV2cwMm1hejJTSWJObXhJeCtQeFVIdDdld3ZETU9tS2lvcDRMQmJyWUJqR20wNm4weDZQSjVwTUp0c1ZDa1ZLbzlHa0dZYkphalFhV0sxVytIdytpS0lJaXFMMlh3K0FnR0IvSkw5U3FZUk9wOFBtelp2LytzVVhYendZalViaGREcEIwelFFUVlCV3F3VkZVUkFFQVN6TGd1ZDVxRlFxVlNxVlVxMWJ0MDZ2VnFzZFJxTVJtelp0d3ZMbHkyR3oyYUJTcWZDUGYvd0RvaWpDYkRaajFhcFZXTFZxRlRLWkRLZlJhTkl2dlBCQ3d1LzMrMlF5V2NPcVZhdk9HVDU4ZURZYWpZSmwyWDFPQklnQUVQd3VpYzh3REl4R0k5eHVkL21xVmFzZXJLK3ZQNTloR0RnY0RnaUNrTGZJWFFrcGw4c2hsOHR6eEpESllMUFpBQUFjeDBHdjEwT3YxK2QvdjE2dkIwVlJFRVVScVZRS0xNdENyVmJMa3Nta2J2MzY5VHFsVXVsTUpwUGpIM3Zzc2RXUFB2cm8wUWFESVNXRmRTUUpTRUF3U0JBRUFScU5CanFkRHRYVjFmZXNXYk9tdnI2Ky9ueTFXZzJ0Vmd0QkVQcVZhOW9oY1dnNi96cTVYQTZOUmdPS29zQXdES3hXSzNRNkhaeE9KMXBhV2c1ZHNHQkJoZGZyVlJRWEYvZnIra1FBQ0FoMndlb0RnTlZxQlVWUnBrV0xGbjMvd3c4LzNBOEFCb01CTXBtc1g0bTRnWGJSSFE0SDZ1dnJ4My93d1FlZngySXhLQlFLSWdBRUJBTnQ5UlVLQmF4V0sxd3UxOXozMzMrL2R0MjZkVE9zVml1VVNtVy9NL0FEVFg0cHpCZ3laQWkrK2VhYlV6LzU1Sk5MUm80Y21UOFJJVGtBQW9MZEpKZ29pckJhclFpSHcyVkxsaXg1cUsydGJYNHltWVROWnN2Lzk3MUIvcTczS0pQSllMVmE4ZW1ubjc1dE1CaXlNMmZPL0RDVlN1V1BWWWtBRUJEc2d0VlhLcFZRcVZTb3JhMmQrOE1QUDd6aGNybDBKcE1KWnJONXB5enNZR2ZtcGZxSFVDaUV4eDU3N0o5cXRUcDV3Z2tuZkpaS3BmWm9mUUFSQUlMZkRma05CZ1BrY3JubHUrKytlMm50MnJYemFKcEdRVUVCQkVIWXA4Z3ZnZWQ1bUV3bU1BeURCeDU0WUxIVmFpMDU0WVFUMm1wcWF2Ym9mWkFjQU1GK0grdmJiRFlFQW9GSkgzNzRZZldLRlN2bWFUUWFHSTNHblk2cjl6VHBCRUdBWHErSFRDYkQ0c1dMdi9aNFBOQm9OSHYxT3lVQ1FMRGZ4UHNXaXdVQUxMVzF0YTh2WDc1OFRWTlRrODNwZEVJdWwrL3o1TzhxQXNYRnhWaTVjdVhCTjkxMDAzODVqcU9MaW9yMldsS1FDQURCUGs5OHFZQ250YlgxOUk4KytxaG0wNlpOVnlnVUNoaU54bDJLb2ZkbU5aNTBiYWZUaWFxcXF1blBQUFBNTjI2M0d3YURnUWdBQWNHMlVLbFUwR2cwV0xObXpiMGZmUERCVno2ZnoybzJtL3Q5cnIrdmlocE4weWdwS2NGMzMzMTN5bnZ2dmZlS3dXQUF3ekI3L0RNUkFTRFlKd2tpazhra0MzL3dmLzd6bjlXTEZ5KytqNklvV0N5VzNTTEp2bUQ5dTRyQWtDRkQ4TjEzMzEyemNPSENVNHVMaTZGV3EvZG9PRUJPQVFqMktVaEhabXExR3F0WHIzNXkxYXBWdDdNc0M1MU9CNFpoZG9zY2U0djh2VjFYRkVXbzFXcHdISWUzMzM3NzMwYWo4ZVFwVTZaOEw1Zkx3Zk04OFFBSURpeXJUMUVVN0hZNzR2SDRrUjkvL1BIYUpVdVczRTVSRlBSNlBXaWEzdWN0di9RWnBLWWltVXdHbVV3R2htRjZ2YjUwcE1uelBCNTg4TUZ2cTZxcXhwZVdsdTR4TDRCNEFBVDdCUG5WYWpXTVJpTTJidHg0Nzg4Ly8zeGZOQnFGMld6ZWJlTHZTY3N2RGF1SlJDS2dhVG8vcUVVU0JZcWllbXdKNW5rZUZvc0ZITWZSTDc3NDRqS2RUbGN5YXRTb3BNL25neUFJZzNyL1JBQUk5aXJ4cGU2NWpvNk9neW9xS2hiVTF0WmVvbFFxWWJQWjhtMjcrekw1cGM4Z2s4bVFTQ1FRREFZUkNvVzZUV3FTWGpOczJEQ29WQ3FrMCtudDdrc1FCRGlkVHRUVzFwcGZmdm5scFE4ODhNQlJjcmtjMld5V2hBQUV2ODlZWHlyZ3FhaW91UC9qanovZVVsOWZmNG5CWUlCR294a1FGM2hQV0g2bFVnbUtvdERSMFFHWHk0VmtNZ21sVXBrZk9DSU5HWW5GWXFpdXJnYlA4NzAyS1BFOGo2RkRoMkx6NXMxSFB2end3eC9vOVhyWTdmWkJ6UWNRQVNEWUsrVHZiTnUxZi9iWlovLzUrdXV2NzBtbjB6Q1pUQVBpOHU4SjhrdnpLWlBKSkZ3dUZ3S0JBR1F5R2VSeWVkN3Q3enJiVUtWUzVlY1pTaDVEVDUrVG9palliRGFzWGJ0Mi9wdHZ2dmxvTkJxRldxMG1Ba0R3K3lDK1dxMkczVzVIWFYzZG5QZmZmNzk2M2JwMUo5anQ5Z0d6K25zQ2Nya2NDb1VDNFhBWUxwY0w2WFE2N3dsSUpPNU5nT0x4T0dwcWFxQlNxWHJzQkJSRkVYSzVIRmFyRmErOTl0cWRYMzc1NVpXbHBhVURKb3drQjBDd1YySjlVUlJodDl1UlNDUksxNjlmLy9odnYvMDJsNmJwblc3YjNadldYMHJzSlJJSmhNTmh4R0t4dklXWDdsLzZYMm5PNExhaUlJb2lnc0VnbXB1YlVWcGFpa1FpMGVQM3BWQW9VRkpTZ284Ly92ZzFrOG5VY01vcHAvd25rVWdnazhrTTZPY2pBa0F3NkZaZnBWTEJiRGFqcnE3dXd2Lzg1ejkvNytqbzBKbk41a0dwZkJzTThrdFdtYVpwK0h3K0JBS0JQRW03a3I0citiY3QrdWtxQUFEUTF0YVc5NFlTaWNSMjl5M05IZlQ3L1hqNTVaZVhqQnc1Y3N6bzBhTnJQUjdQZ0g1R0VnSVFES3JsN3h5ZWFmL1BmLzd6OGNLRkM5OExCb002dTkwK0tDN3RZSkNmb2lnb2xVcndQSSsydGpiNC9YNHdETk50dEZkUEhzeTI5eUxsQkxxaXJxNE9rVWdFR28ybTE2U2cxV3FGSUFqMGZmZmQ5MU5sWmFWNjZOQ2hBK294RVFFZ0dCU3JyMVFxWWJmYkVZdkZEdjcwMDArM0xsKytmSTVXcTRYSlpCcVVXSDh3eG5sSlNiMUlKSUtXbGhaRW8xRW9GSXB1Uk82TmlEM2RUMC8vcnJxNkdxbFVDaXFWcXNmZkpRZ0M3SFk3MnRyYUN0OTY2NjJWUHA4dlA0Q1VDQURCUG1uMU85dDJIY3VXTFh0djJiSmxHM3crbjgxdXR3L2FMTHpCc1B3TXd5Q1R5YUN0clEzdDdlMzU0N3Urckg3WCs1R3EvN3IrTUF6VG81WGZzbVZMbjhlRGdpQmd5SkFocUtpb09PUnZmL3ZiY3FWU0NiMWVQeURmSlJFQWdnRWxZcWUxbXZYaGh4L1dMRnUyN0VLR1lhRFg2L2VyemozSlhaZmlmWVZDMFdPaXJ6ZmhFQVFCeVdRUzZYUWE2WFFhbVV3RzZYUWFITWYxK0I2TzQxQlhWNWRQS1BhR2dvSUNiTm15NWVoWFgzMzFQbEVVb2RWcWQvdDdKUUpBc05zV242SW9hRFFhNlBWNnJGbXo1cUgzMzMvL0M1L1BaM1E0SElQZXRqdFlTVDlCRUdDejJhRFJhUEtGT1AyeCtwbE1CdElXSU9uMzhEd1BqdU42RlFBQWlFUWkrUnFCbmo2VGxJaTBXQ3o0NktPUDd2MzU1NTh2TGlnb3lJdEcxeDhpQUFSN2pQeHl1UndHZ3dHaFVHank1czJibHk5YnR1eHVqdU4ydTIxM2I1Ry9xMnV1MVdyaGNEanlCTzdMNm91aWlFUWlnWGc4bmkvOTNWa3l4dU54c0N6YlkzMkFkS3lvVXFrd1pNZ1F2UERDQys5VVZGU00xbWcwaU1malNDUVMrUjhpQUFTRERtbStuZGxzeHRLbFM1LysxNy8rdGFxam8rTm9rOGtFcFZJNTZFVTllNkxTTDVQSndHQXc5RHBzVkFvVjB1azBZckVZTXBrTUdJYkpuM0QwbFBudjdmNkxpNHR4OE1FSGc2YnA3VXAvSmZMTDVYSm90VnFrMDJrME5UWGhqVGZlZUltaUtFU2owVzQvT3dOU0IwQ3cwMWFmcG1tWVRDYUV3K0hKUzVjdWZYWHIxcTBUZFRvZGREcmRIb24xOTJSZlA4dXkwbEVjUEI0UEZBcEYzdDJYckw2MFhuMWJzdmUxRVZqNm5tUXlHVXBMUytGd09KREpaTUR6Zkk4MUFkSmFzOXJhV25nOEhnREFqei8rT0tPNnVycTRzTEN3TFJ3T2t4d0F3ZUJiZloxT0I0dkZncGFXbHRzLy92ampWZFhWMVJOdE5odlVhdlh2anZ3UytWaVdoYzFtazFwMlFkTTBPSTdyWnZYN3VxL2V2QUNyMVlvSkV5YkE0WEFnbVV4dVIzN3BLRkt2MXlNYWpXTHo1czN3ZUR4UUtwVlFLcFhJWnJQNCtlZWZyNWVXbVBaVmdrd0VnR0MzU0NBTjVvekg0NGQrK2VXWDcxUlVWRHlwVUNpa0k3L2ZKZm1sYS9JOEQ1N25VVlJVQkxWYWpVZ2tnbGdzQm83amRoam5TNGxBQUZDcjFiR0Nnb0tRUnFOQmFXa3BSbzRjQ1laaGVpMEgxdWwwb0drYWpZMk4yTEpsQzFLcEZOUnFkYmZRNHR0dnY1M3I4WGpBY1Z6KzFJR0VBQVFEYXZXMVdpMk1SaU4rL1BISFIxZXVYSGxuT0J5RzFXcmRvME1zOXpUNXUxNlBvcWk4NVM4cEtVRW9GSUlnQ0gyZWNFanZBUUM5WGw4NWJkcTAyWFBuenEycXJxNStkOUdpUlJkcE5CcWswK250Qm41SXYxZWowU0FVQ3FHeHNSR3BWS3JIbzBpR1lkRFMwbEx1OVhxUG5qWnQyb3IyOXZhZC9weEVBQWo2Uk9lNEt0dG5uMzMycitYTGw1K28xK3ZoY0RnR3ZJRm5YMEp2Vlh6WmJCWnF0UnBqeG96QjFxMWJ3WEZjcnlJZ2tYL1dyRmwvUCt1c3M2NjMyKzM0NUpOUDNscXpaczE4aG1IeS8zMWI4cXZWNnJ6VmIyOXZCMDNUK2ZCcTIrc29GQXFrVWltOC8vNzdDMHdtMDRyYTJsclFOSTBqanp5U0NBREJyb1BuZWFoVUt1aDBPbXpkdW5YMmtpVkxYZytGUXBiQnF1SGZIZXN2L2JlQnVxY2RYU3VWU3NGZ01HRGt5SkdvcWFucEpnSmRyYjVXcStYdXZQUE9ZOGVPSGJ1NnJhM3QwRVdMRm4yeWR1M2FjcWtpc3V2OVNyRytUcWRES3BWQ1EwTUR3dUZ3ZnJCSWI1OU5DaTErK09HSE02ZFBuKzV3T3AxZWNncEFzRnV4UHBCYldwRk9wOHUrLy83N0Y3WnUzVG9ybTgzQ2JEYnZ0Umk4dDM5UDB6UllsczA5eUoya0d1ekJvUlJGSVpsTXdtS3hvTHk4SEEwTkRkdldDTVJPT2VXVVJ5KzY2S0pIMVdvMVhuLzk5YmVxcTZzdmxYSUkyOTZqWlBVRlFVQnpjek84WG0vZTAranQ4MnpiZGNqelBCS0p4SjNISDMvOGJVMU5UVVFBQ0hZdDFsZXBWSEE0SEtpc3JMenN4eDkvZkxtdHJVMWxzOWwyZVFQUFlNZjlpVVFDeVdRU21VdzZsNmN3bVVIdG9qZXdzK0tXVHFkaHQ5dVJ6V1lSalVhUnpXWlJYRnljUGUyMDAyNE1oVUx2dWx5dWNmLys5NzlYMXRUVUdNeG1NeFFLeFhaV242SW9HQXdHSkJJSjFOYldJcEZJUUM2WDkzcWlzdTM3TTVrTWpFWWpXSmJGNTU5L2ZzN0VpUk52NjZ0Z2lRZ0FRWThQbGRUQUU0dkZ0Tjk4ODgwNzY5ZXZuMFBUTktTZGRZTTltWFpuQ2Nrd0ROS1pEQUorUDJpYWh0RmtRandlaHlLWmhFNm53ODZTWUZjK215aUtTS2ZUS0N3c1JHRmhJVmlXaGRGb2xEVTBORHpVMk5qNFVrVkZoVTRVeFh3UjBiYmtWU3FWa012bGNMdmRhR2xwQWMvei9iTDZYZk1MaFlXRmtNdmxhR2xwd2FaTm0wcUN3V0JwZVhsNU14RUFnbjViZmJWYURZUEJBTGZiZmVnUFAvendlV05qNHhDSHc5RnQ0ZWErUkg0Sm9VQUFCWVZGT1BiNDZTZ1pVZ2FGUW82dnYxaU1WbGN6dEZyZG9KSy9LNlNwdlRSTkl4Z00waDZQcDBTcFZPWkxnYnRXRDBwRlZGcXROaC9yUzdNRWUyc0gzbFk0T0k2RFJxT0J5V1NDS0lwb2EydkxEeUJ0YW1xYU5uSGl4UGVJQUJEMGkveWRaL2lGUzVZc2VYN1RwazNuY0J5WGoxUDNaZktuVWlrWWpFWmNjZTBOR0RkK0lqTHBOTGI4dGhHaFlBQXltWHlQa1gvYjc1T21hYWhVcXJ5WDBsT0lKWmZMMGQ3ZWpyYTJOckFzbTMvOXR1VHYrczlkOXduWTdYWUFRREFZUkRLWnpBOFl6V2F6Mkx4NTg4ekpreWQvQUVBZ0FrRFFxK3RLMHpTc1ZpdGFXbHJtVkZSVXZOUFkyS2cxbVV6YmxmTHV6VDE2ZllGaEdDaVZTcXo4K1NmVVZsY2lGbzNpMTNWcmtFNm5vTlBwOTduaG9sSlJUenFkUmwxZEhVS2hFR1F5V2I5aWZRRElaRExRNlhRd204MUlwOVB3K1h3QWNzTkp1NzUrNDhhTngvend3dzhUempqampJMUVBQWg2ZktpTVJpT3kyU3hhVzF2dnJxNnVmb2puZVRpZHp1MWl6MzBwNDcvZFE5dVo4Vit6ZW1WblBDeENwOWREcHpOQUVQZ0J2ZGJ1ZnVkU1VzL3Y5Nk91cmc0Y3gvWEw2Z081NDFocElwQldxNFhmNzBjc0ZvTk1KdXZ4L2owZVQyRXNGanNLQUJFQWd1N3VwMXd1aDlsc1JsdGIyL0hMbGkxN3FLcXE2bWlOUnJOZGRucGZKMzlYb2hpTXhtMCs1NzVCL3E0ekVqS1pUSTlGUFR1SzlWbVdoVmFyaFU2bkEwVlJjTGxjNERndWIvVjc4b3BZbHNYcTFhdkhreHdBUVRmeTYzUTZtRXdtL1B6eno4OHVXN2JzRm83allES1p1azJwM1Z2WVY4T00zUlZidFZxZHovQnpITmRyVWMrMlhoZkhjUkJGRWRJd2xVZ2tnbmc4RG9aaGVpVy9WQXNBQU5GbzFFd0VnQ0FmNjNkMjdoMnhhTkdpZDZ1cnE4ZnFkTHI4aUs3ZU50UDhuc2svbU5mczJyWmJYMThQajhmVExkYmYxc3B2aTB3bWt4K21tczFtNFhhNzgyRkViNTlGV2orbVVxbHcrdW1uM3pkdDJyVFhpQUFROHVldC9xWk5tLzYwY3VYS3B5aUtrdFp4N2RRa1cyTDFkODdxaDBJaE5EVTFkZHNSMkIrckx3Z0N6R1l6akVZand1RndQbEhZVnlXa2RBUlpXRmk0OGJ6enpydDZ6Smd4djVCQ29BUGMzV2NZQm5hN0hhMnRyVk4vL1BISG03ZHUzWHF1UnFQSm56TWZ5T1FmclBtQk9wME8yV3dXalkyTmNMdmRvQ2hxcDZ5K1NxV0NYcThIVGRQd2VEeElwVko5V24xSk1EUWFEWTQ1NXBnbm5FN25IVHFkRG0xdGJkRHBkRVFBRGxTcnIxYXJ3VEFNVnE5ZS9lU3laY3R1ajBRaXNGZ3MzWXA2Q1BrSDd2dG1HS2FiMVUrbFV2MjIrdEtjUWF2Vm1tLzlqY1Zpb0dtNng4U3M5RDVwMk9pRUNSUFd6cDgvLzFxRlFySDI1NTkvUmpRYTNhVitEU0lBdndQaVM2Vzh5V1RTOU4xMzMzM1MxTlIwb2xhcmhkUHA3SEdXM2UvWkhkOFRuMUdxb0dRWUJzM056ZmxxdlA1YS9XdzJDN2xjanBLU0VvaWlpSTZPRG1ReW1lM085YmY5TzB1TlQrZWNjODRESjU5ODhyMHN5NksydHJiSE1XSkVBQTRBU0pOclRTWVRxcXFxWnYvNDQ0OS9iMjl2ZDFvc2xueDU2TDVpa2ZlVzBBemtkYVcyWGFtVXQ3YTJGcUZRYUtlc1BzL3orZnhNS3BXQ3orZmJvZFdYWW4yajBSaWROR25TdGNjY2M4eUg0WEFZTE12dTlPUmhJZ0MvRTZ0UFVSUUtDZ3JnOVhyTGZ2enh4MWMzYnR4NHN1UUpiTnQ4OG51endIdmp1bExNemZNOG1wcWE0UFA1ZWkzbDdhbXVJcHZONWpQOFBNL0Q1L04xaS9WNyszdGxzMWtvRkFyTW16ZnZRYWZUK1hKemMzT0gyKzJHMFdnY2tNOUhCR0EvSkw5U3FZVEJZRUJ0YmUwVlgzNzU1WXVCUUVCbHNWaWdVQ2o2WFFaTE12NzkvNzVwbW9aZXIwY3ltZXl6YmJjMzExMGFMMjZ4V0JDTlJoRU1CbmRvOWFWRW44UGg4RjF5eVNWenBrNmR1bXpObWpVSUJBSW9MeThmc005SEJHQS9pL1ZOdWRaWDNiZmZmdnRhWTJQalBKcW1lNTFiVCtMKzNiZjZLcFVLTXBrc1g5UWp4Zi85aWZVNWpzdDdha3FsRW02M2U0ZXh2bVQxQWVESUk0OWNlUGJaWjE4ams4bENEUTBOU0tWU3UrM3lFd0hZRHlFOWRFcWxFaTZYNjZpbFM1ZCtXRnRiVzI0eW1YYVk0U2R4LzY1YmZaMU9oMlF5bVcvYmxjdmxQUTcyNk9uOVV0dXV3V0NBS0lwb2JXMkZJQWo5aXZVZERrZjY4TU1QdjNIMDZORnZDSUtBUUNBQWg4TXhLTjhWRVlEOWdQeWR2ZCtsUzVZc2VYSFRwazJ6T0k2RDNXN2ZLYXRQeUw5ellzc3dETnh1TjFwYlczdHM0T21MeERSTjV4dXNRcUVRVXFrVVpESlpyd05FdTVML2hCTk8rUEQ4ODg5ZjBORFEwRjVWVlFXRHdkRHJYZ0VpQUw5emwxOG1rOEhwZEtLbXBtYldraVZMRnJhMnRxcE1KbE8rM0hSZkplVCtiUG03cnQ0S2g4UGJ4ZnA5SlZlbHRsMnIxWXBrTWdtLzM3L0RVbDdwWEwrZ29DQTRiOTY4YTBlUEhyMFFBTHhlTDJpYUh2VHZrZ2pBUGtoOEFEQ1pUQkFFQVpzM2I3NW42ZEtsOTFNVWxUL1gzOWtNUDRuNWQveWRLeFFLS0pWS0JBS0JYdHQyZDVTd3MxcXQwT2wwQ0FRQ2ZiYnRiaHZyVzYzV1g4ODk5OXpURGovODhJN0t5a3BJMDVmM0JJZ0E3R1B1dnJRQ3VyR3g4WlJseTViZFgxZFhkNVFVLys5cmd5NzJkN0dSamxQVmFqWFM2VFRhMjl2aGRydnpGWDQ3c3ZxaUtDS2J6VUt2MStkZkw0VU0vY253MiszMjRKdzVjLzRobDh2dkRnYUQ4SHE5dTdUZWl3akE3OFR5NjNRNnNDeUxIMy84OGJtbFM1ZmV6TElzekdiemJzM2lKOWEvZDdGVktCUlFxOVZvYjI5SGMzTXplSjdmcnFpbkg4ZDBVQ2dVQ0lWQzNkcDJkeFRyVDUwNjlkTzVjK2RlTVd6WXNOQlhYMzJGWkRLNVYvNVdSQUQyRVN0a3RWcFJWMWQzMklvVks5NzArWHlINlBWNkdJM0czU3JxMlJmbitlMEwxNVJpZlo3blVWZFgxMlBiN281aWZZVkNrWjhHM05iVzFtZXNMd2tPei9OZ0dBYXpaczI2NTZTVFRub3dtODNtQjMzc0taZWZDTUErUm42OVhnK0ZRb0YxNjliZC9PMjMzejZYeldiemJidTc0L0lUOHZkdTlWVXFWWjl0dTMxWmZWRVVZVGFiOHh0N2Q2WnR0N2k0ZU12a3laTXZualJwMHJwZ01BZ0FrRGI3N2kwUUFkaEx4QWNBczltTVlEQTRmZm55NWJkczNyejVESVpoZHR2cUh5aHUvNjZHV05sc0Z2WDE5ZWpvNk5pdWJYZEhWbCt0VnVlSHFYaTkzbjYzN1NxVlNzeWZQLzlScDlQNWw1cWFHbmc4SHBqTlpzaGtlNTkrUkFEMk1LUnpacnZkanA5Ly92bko1dWJtMndPQlFML2FkbjlQYnZpZXVxWjBuS3BTcVJBTUJ0SGMzTHhkMjI1Zk14SzZ0dTFxdFZvRWc4Rit0ZTFLNUQva2tFTlduM0hHR2RjY2R0aGhHNWN2WDQ1UUtJU2hRNGZ1TTg4akVZQTliUFd0Vml0RVVUU3RYcjM2bit2V3JmdUR3V0RvVjlzdUlmK3VrVitsVXVXMzdicmQ3dTNhZHZ1eStsTGJibkZ4TVNpS2d0dnR6amZuOUxYQlIycmJQZVdVVXg0Ni8venovK2J6K2REUTBJQnNOanZncGJ4RUFQWURTRzI3RE1PZ3FxcHE3dkxseTE5MnU5MVdoOE94MjdIKzNzUytTbjdwT0ZXbFVpR1pUT2FMZXZwcjlTWHJMYzFQVEtmVDhIZXVJZXRQS1c5cGFXbWtyS3pzdHBFalI3NFZpOFVRRG9mekN6MzJOUkFCR0dTckx4MFZwVktwOGs4Ly9mVGRxcXFxWXdEQVlySHM5alpiWXZsN0pyL1V0dHZZMkFpZnp3ZU80L0pXZjBmRFVhUzJYYXZWQ3BabDRmZjcrOTNBSTVmTGNlNjU1OTQ5WThhTXY2OVpzeWJjMXRhRzRjT0g3OU01R1NJQWd4anJxMVFxRkJVVllkT21UUmQ4ODgwM2I3bGNMcm5OWmh1UVdKK1FmM3V4N2FsdFZ6cnI3NC9ZcHRQcG5XN2JsYXkrM1c3M1hYTEpKWE1tVHB5NExKRkl3T3YxN25QdVBoR0FQUnpyQTFELzhzc3ZiMVZVVkp3bms4bFFWRlNVMy9heXZ4SnhYLzNPbFVwbHQ3WmRudWZ6cGJ3NytyNmx0bDJuMHdtbFVnbVB4NE4wT3QzdnR0MnhZOGYrMzR3Wk02NHVLU21KTkRVMTVSdDQ5b2ZRamdqQUFNZjZhclVhRm9zRkRRME54Ly8wMDA5dlZsZFhsOXRzTmpBTWsxL2VzRCtUZjEreS90SmdUaW5XcjI5b1FMQnoyNjVHbzhuL1Rmb1NEcFpsb2RQcG9OUHBJQWdDMnRyYWRxWnROM0xlZWVmOW1lZjUxNkxSS0FLQkFKUks1WDcxekJJQkdFQXJaREtaNFBWNlMvLzk3MysvOXNzdnY1d01vTWY5OElUOHUzOU42VGlWcG1tMHQ3ZWp0YlUxWi9XVlN0QU1BNnF6azA0UUJJaUNBSFQ1UFYzYmRnc0xDd0hrdHUybTArbCt0KzJlZU9LSjc1NTExbG0zV3EzVzBLSkZpeUNYeS9kYU5SOFJnTDFNZkpxbVliZmJFUWdFVHZyKysrOC9UeVFTYXFQUk9LQ3hQaUYvOSs5Y3A5TWhsVXFoc2JFUmtVZ2tmOWJQZEpLWHBtbXdMQXVPNDdZamRDYVRnVmFyaGRWcVJTYVRnZGZyQllCK2xmSXFGSXJ3SlpkY2NzWFVxVk1YaGNOaHRMZTM3OWZoR0JHQTNZejF6ZWJjS3JhVksxZmV1Mnpac3Z0NG5vZk5aaHV3REQ4aC8vYXh2bEtwN0xadFZ6cmVvMmdhTE1kQ3FWQ2lxTGdFUG04SGdvRUE1RElaMEtYMzNtS3hkQ3ZxMlZIYnJuU3VQMjdjdU1vampqaGlSbUZoWWJ1MHRrdktNK3l2SUFLd2krUm5HQVlHZ3dFdWwrdVBTNVlzK1d0dGJlMWhHbzBHZXIxK3Z6M1gzMWZKMzNYYmJqS1poTXZsUWtkSEIyaWF6aFg2TUF3RVFRQkZVVENiTERDYnpCQWhndWR5OC9LRnpyWmRnOEVBdFZvTmp1UFExdFltV2ZSZTNYMXBqSGRoWWFIbmhCTk9lSEhhdEdtUGJOcTBDZTN0N1NndkwvOWRKR0dKQU93a0JFR0FYcStIeldiRG1qVnJucW12cjc4MWxVb05TQVBQL3VLQzc4bHJkbTNnY2J2ZGFHcHVodEJKWElaaFFETk0zZ3R3T0p4UXFWUzVJN3lBSDRJZzVwT3ZUcWNUQ29VQ3dXQVE4WGdjTXBtc1gyMjdreWRQL3Z6Q0N5KzhRS1ZTeGYxK1A4TGhNUFI2L2UvbWVTWUNzQk5XbjZJbzJPMTJ1Rnl1U2IvODhzdWJEUTBORTdWYWJYNCszMkRONGo5UWovdTZ0dTNtdCsweURPUktaZTZNdmJOcVQ2L1h3MlozUUJRRWVEczZFRS9FYzhJaFZ5Q2J6Y0pzTm9LbTZSME81dXdhNjFNVWhXT09PZWF2Zi9qREh4N21lUjR1bHdzS2hXSy9UUFFSQVJoQXExOVJVWEhyMTE5Ly9ZelV0aXY5OTk4YjlxYjFsM3JybFVvbFFxRVFtcHVia1V3bTh3U1VYSDRadzhCcXM4RmtOQ0VlVHlBUThDT2J6WUNpcUx4QXlHUU1vdEVZV0pZRlRkTmdHS1pYOGt1eC92ang0N2NlZXVpaGw4cGtzb3BBSUFBQXZ6dmlFd0hvcHdXaWFSb1dpd1ZlcjNmR3BrMmI3bHkvZnYySkRNUGtaL1lkS0FtNFBVbCtyVmFMYkRhTGhvWUdkSFIwQUFDVVhheStJUERRNlhJVmV6VE53T2YxSWhhUGdlYzUwRFR6di92dnpOVklpeno2K2p0TDVjSm5uMzMyUFNlZmZQS0RGUlVWcUttcDJhV0ZtMFFBZmlkV1g1cnIzdGJXOXNqR2pSdnZTcWZUTUpsTWtNbGtoUHlESUxiU0xMNUFJSURtNXVaOE5SN0RNR0JrTXZBQ0Q0YWlZYmM3WVRRYWtZakhjK2YzbVRRb21nTERkSCtjc3h3THJWcVRId0N5YldsdTExaC93b1FKSytiT25YdDFhV25wbG1nMENyL2Z2MC8wNnhNQjJFdXh2c1ZpUVNhVHNYLzExVmR2cmwyN2RwWldxNFZPcHh1UTR6MmFwcEZNSnBGT3BTQ1RIdkRPSDVxaFFZRTZZTWpmZFRBblJWSGQybmFsNHowcDBhZlJhT0J3T0NGalpBaUZnZ2lId3VCNERnekRkTDkzQ2hCNEFWdzJDN1hWQm9WU2lYQTRuTDlXMTFnZkFBNDk5TkFuWnMrZWZZZlZha1ZUVXhQMGV2MStVY2RQQkdBUXJMNUtwWUplcjBkOWZmMkZTNWN1ZmFHMXRkVWtsZkx1THZHbGg2K3R0UlZXbXcyalJvOUJOQnBGSnBOR09wVkNOSkZBT3BYS0o2RlVLaFdzbmRmK1BlWVpwSVNjVXFsRUlwR0F5K1ZDS0JUS1Y5WFJuU1NVbHFOWXJUWmtzMW40L1g0a2t3bWdjOWpIdHVDeU9WR3dPNXlReVdRSStQMzU3NytyMVI4eVpJajdqRFBPdUp1aXFMZmRiamRrTXRrQlEzd2lBRDFZSWJQWmpGZ3NWdkxGRjE5OFhsTlRjeGdBT0ozTy9HdDJCd3pESUI2UG82MjFGZE9PbjQ3YkZ2d1pCVVdGQ1BqOXlLVFRTS1ZTQ0lkRENBUUNDQVlDQ0FRQ2NEVzNZT1BHRFpDcUNnZHo0KytldHY1U2lDV0tJaG9hR3VEMys3dE41YVVaQmh6UFFhZlZ3V3pPTFQ2TmhNTUloY01RQkQ1ZitOUFY2b3VDQ0RiTFFxL1h3MkEwSXBWS29zUGp5U1VNWlRMd1BBK1daYUZXcXpGbnpwdzdqamppaUJlVVNtVjY2ZEtsTUJnTW9DaHFuOXFxVEFSZ0QxcDlqVWFEeHNiR2kzLysrZWVYRW9tRVRxL1hEeGpwR0lhQnorZERKcFBCemJmZWhxdXZ2ejV2bVJ3T0p4aUdnVXlXR3ljdGt6clFPZ3RiSHJyL2Z2enovZmN3YkFBM3d1NU44bS9idGx0Zlg1OC9sNWM2K2tUa092VE1ablBlNm5zN09wQkl4Q0YyZnAvYjNqL0hjZ0FBdTkwT2xWcU5ZQ0NBZUR3QmhTTG5UYVJTU1FDQVZxdjF6cDA3ZDk2TUdUUCsyOXpjakhBNHZNZG44Uk1CMkllc3ZzMW1RendlMTMzMTFWZHZiZGl3NFJ5YXB2UGx2UU5DZnBrTTNvNE95R1V5UFA3aVM1aDV4aGxvZGJrUWpVYkJNQXd5bVV5djd6VWFqYmozZ1FmUjNOeUUvLzduQjR3ZGU5Q0FkaFR1RGZKTEpQZDRQUG0yWGFWQ0FZcW1RY3NZOEx3QW1Wd0doOE1KclZhSGFEU0NTRGlFYk9jeEhyMU5yQzhLSXJLWkROUnFEYXcyS3ppT2g4ZnQ3dlFtRkdEWmJON2xuejU5K3VMQ3dzTEx0VnB0cUxXMU5YODBlQ0JEZHFDU1g2RlFRSy9YbzdtNWVlYTMzMzc3ZkZWVlZibkZZc2tYaVF3VU1mdytIOGFNSFlNbm5ub0d4U1VscUttdWhpQUkvWW8xZzhFZzFHb043cjduSGpRMU5xS3R0UlVsUTRhQTQ3ajlpdnhkMjNZVGlRUWFHaG9RREFaekRUeWQzWHNpY21UV0d3eXdtQzJnS0JwK3Z4ZXhhQlJDNS91NzN6ekFzUndvVURDWkxkQm9OSWpINGdpSHcvbFlQcFZLUUJCRUZCUVV0TStlUGZ2dVNaTW12Yk5reVJJRWc4RjlhakFuRVlBOTdQSWJqVVpvdGRxaWI3Lzk5clhtNXViVFdaWkZRVUZCUHNNL2tNVEl4ZjRKY0x5QWJEWUxqbVhCOVBONGlXRVl0TGE2VUZaV2pqZmZmUStYWERBZmJhMnRLQ29wQWIrYklyQ255QytGV0RLWkRPM3Q3ZmthZktWU21UdW5sOHZ6THJqVmFvTldxME04SGtVd0ZBS2J6WUNpNkI3RmtzM2tZbm16eFFLTzQrRDMrY0N5TEJRS09YaWVSeXFWQmdDY2Nzb3BiNXg0NG9tM3FOWHFSR3RySzFLcEZJeEdJMkYrSitnRGlmaFMvM2RyYSt2MDc3Ly92cXF5c3ZKMHVWd3VyZDhlRkdLWUxSYlUxOVhoMmlzdlJ6S1pndDNoNkRHajMvWDRzYmlrQk5MSkEwM1RhRzV1UXZudzRYam1oUmZBTUF3Q1B0OStrYTJXaW5wWWxrVlZWUlZhV2xyeXB4c0FPcTErTGtGWFVGQUlqVVlEbjg4TG45Y0hOcHNGdzhpNnUraFU3dStZemVRYWUyeDJPK0t4ZUxkRVh6cWRSbWU5UnV6MDAwK2ZmZXFwcDE0SklPSHhlUFpLc3BNSXdEN3lJRnF0VmhpTlJsUlVWRHo4emp2di9OZmo4ZWdkRGtlM1JOK3VQaHlTQll0R28vbEJFeEo0amtOSlNRbHFhMnJ3NU9PUHdtWjNRRzh3ZEl2bHVjNGRnSVZGUmRqeTIyLzQ5T09Qc1hiTkdsaHROaFFVRkFDaWlJYjZlaHcxZVFvZWZPUlJSQ0lSeE9QeFhZNWZCNXNFVWltdlhxOUhKQkxCbGkxYjhsTjV1eDZuVWhTRlRDWUROcHRGc25PT1hqUWFnUWl4VjZ0UGdZS3pvQUE2dlI0ZG5nNUVJbUVvRkFvSWdvQmtNZ0dlNXpGdTNMaE5Eejc0NEdIbDVlV0wyOXJha0U2bkQvaFkvNEFNQWFUWTAyUXlvYTZ1N3NLdFc3ZmVYbFZWTlZHdFZzTnNObmV6eEx0S0NwcW1jMWxxYndlR2p4aUpjQ2lFZERvTnBVcVZtMFRUZVI5RFMwdXg2T09GMEdxMHVPUHV1eUVLUXA3RVpvc0ZIbzhIYjd6NkQ2eFl2aHpSU0FSYW5SWVREejRFTjl4ME13NGFQeDR0emMxb2JHakFXYlBQUmtOREE1NTk2a2tNRzFZT21WeTJVOG5Ld1NSLzE3WmQ2VnpmNS9QbDIzYTN2VS9wWGhLSkJOTHBOQlFLWlkreHZzQUw0RGtlQm9NUkdxMEcyV3dXQWI4Zll1ZjQ3MHdtRFM0bnRLNFpNMlk4TlduU3BCYzBHZzA4SGcvS3lzb0l5dzlFRDBBVVJSZ01CaGdNQmxSV1ZqNnhlUEhpOTZxcXFpWmFMTG1FMFVDUVh5YVRJUlFNb3RYbHd0enp6c2NuaXovRDNIbm5vNldsR1h6bm9NbXVGckd3c0FpdnZQd2lubnY2YWRnN3ZRK0tvbUF3R1BIT20yL2lnL2ZmaDF3dVIxRnhNVFFhTFg3NDdqdGNkOVdWYUc1cVFrbEpDWExMSkZ0dzg2MjM0b0tMTDBaalU4TStRMzdKQmRmcGRQRDcvZGk2ZFN1OFhpL2tjbm1meDZrUzRYbWVCNmp0NzVITGNvQUlPSndPYUhVNmhJSkJCSHkrM09zb0NzbGtBaHpINGVDREQvNzZycnZ1R24zc3NjZStFSWxFZWl6OUpUZ0FCRUE2WjdiWmJBaUZRbE0rL2ZUVERldlhyMStnMCtueTNYdGRIOGJkSVVVNEhFWnhTUW1lZStsbC9PMisrd0FBMTF4M1BlYWNPeGYxZFhYZGZyOVU5VlkrZkFSZWZ1RjVMRjYwQ01OSGpBQkZVWWhFdy9CMmVPQjBPdkpESmVWeU9jYU9HNGVPamc0OC9zakRVS3BVTUpsTVNNVGo4QWNDK050OTkrUEVrMDVHUTMxOXY5emJ3WGI3cGNVbjlmWDFxSyt2ejhmNk95eXU2WEpmWFY4bmlybWlIbzFHZzhLaUlnaUNpQTUzZXk3UnAxUWltODBnblU1Qm9WQmc2dFNwZDArWk1tVm1OcHROdVZ3dThEeFBYUDREVVFDa0VVMEdnd0ViTjI2ODliMzMzbHRaV1ZsNXNNbGs2ck1IZkZjUkNZZHgwTGp4dVB5U2l4RU9SOURVMUlSNFBJWUhIbm9FeDU5d0FwcWFHcnRWcTRtaUNJMUdBNHZWaXVlZWZncVZXN2VpdEt3TURNMkFGd1JrTXBsdUR5N0hjU2dmUGh6TGZ2d1Jqejc0QUFvS0M2RTNHQkR3KzVITlpQREVVMC9qNEVNT2hhdWxwVTlyTjFqa2w2eStWcXRGTkJyRmxpMWIwTkhSQVlWQ3NjTWlLbWtERHdXQVllaHVBc0J4SEhpT2g4bHNodGxpUVRnY2hzL3J6UTM3cENna0VuRndISWNKRXlacyt0dmYvaloxNHNTSmorVEtnNU9FK0FlaUFFaXh2dGxzQnN1eXgzM3p6VGNyRnk1YytJd2dDUG4xeTcxTmZ0a1pzQ3lMY0NnRXJyT0FwS2k0R0Y5LzlTV3V2dVlhNlBWNm1DMFcrSHcrOER5UGwvL3hLZzQ1OURBMDF0Zm42OVdsaVVGT3B4UGhjQmhYWG5JSnFpb3JNWExFY0J3Ly9RUmtNMWxrTXBsdTkwVlJGSXFLaS9IMlcyL2hnWHZ2Z2MxdWg4RmdnTnZ0aGxhcnhmTXZ2d3lIMDRuMnRyWWVSV0N3eUM4TjVnU0ErdnA2VkZaV0lwMU85OC9xSXplWVU2RlF3RzYzUTZISWVUM1pUQWJaVEJaYWpSWUZoWVZnYUJvZXR4dUplQnh5dVJ3c3l5S1ZTc0pvTkdMdTNMbTNYM1hWVlFkYnJkWlZIUjBkQTM1OFN3UmdQNEZVVTY3WDY3Rmh3NFpIS3lvcWZtcG9hSmlpVkNxaDFXcDdiYUxwejhOQzB6VGk4VGhjTFMzNXZ2UkREenNNTnJzRDZYUTZuMkI4NjQwMzhQeHp6OERoeUxud0hSMGVhRFFhM1AvUXd6QWFUZkI0M04zSXlYRWNpb3FLME5ycXdvM1hYWU90bFZYNDA1OFg0SkxMTDBkelUyTit2cDFFTktWU2lhS2lJdnpqNVpmeDZ0OXpoRmNvRkdodGJjV1FJVVB3OE9OUFFCUkZCSVBCUVk5N3BSQkxwOU1oRkFybFkzMnBxV2RIVmw4UUJMQXNDNHZGQXJ2ZGptZzBDcTNlQUl2RkNwbE1Cb3ZWQ3JQRmduZ3Nsa3YwZFY0dm1VeUFaYk1vTGk1ZWZ1T05OeDQwWThhTXAvMStQd0tCQUluMUQwUUI2RnJLeXpCTTRhSkZpNzc2OHNzdjc2UnBHaWFUcWMvdXZmNlFYeFJGcEZJcFRKZzRFYmY5K2MvNDA0SS80Mi8zM1k4cnI3ME9vVkF3djgxWG9WQmdXSGs1WG5yMldYeXljQ0ZHalI2ZDMwWTdidng0UFBuc3MwaW4wZ2dHdXorb1BNK2pmUGh3Tk5UVjQ4KzMzUXAzdXdmM1BmZ1FUcDkxQnVwcWE3ZkxINmhVS2d3dExjVnpUeitONWN0K3hzaFJvd0FBRFkyTk9PYllZL0hFTTg5Q29WQWdsVXdPaXZXWGlxVFVhaldVU2lXYW1wcFFYVjJOVENiVGI2c3ZIWkVXRkJUa1oveEZvMUVJUEllQ3dpSU1LeDhPR2NQQTNkNk9XQ3dHdVNKWHlpdlY4YytjT2ZQbFAvemhEOGNxRklwS2FZRUhjZmtQUUFIb2F2V3JxNnN2Ky9EREQyc3FLaXBPTjV2Ti9iSkMvWDNnZVo3SHVQSGo0WFE0OGRPUFM2RldxN0JxeFhJME56WGxOODlJcERCM3h2VWJmbDJQb2FWbEFJREdoZ2JNT1Bsa1BQVFk0NGpING9oRUl0MXJCSGdlWmNPR1ljWHk1ZmhzOGFmUWFEUjQ2TEhIY2V4eDA5RFcxdHJ0WGdWQmdGYXJoVWFyeFNNUFBZRHFxcXBjV1RETElwdko0dXh6enNGaGh4K09VQ2cwNE9TWHR1MUt4M3ZWMWRWd3U5MzVzVjA3K3I1NW5nZkhjZm05ZStsMEdtMXRiZm1WWER6UEk4dG1FUTZGNFBWNk8wOU5aUGxZdjZ5c3JQN0dHMis4Y1BiczJUZUVRaUZFbzFGQy9BTlJBS1FIelc2M0k1MU9GNjFhdFdyTk45OTg4NmJQNTlNNUhJNzg2dWVCU0lZeERBT2RUb2VQUHZnQTExeDFKWVlNSFFwQkVQSHVXMitoWk1pUWJxR0ZGTmRISXhGY2R0RkZxSzJwUWRtd1lXQlpGbzBORFpnM2Z6NGVlUGdSaEVPaDdXSjhhVTVkTkJKR01CaUVRaTdIODMvL080WU1HUXFYcTN0eVR4QUVGQlFXd3RYU2pFc3Z2QUN1bGhZY08yVXlObXo0RmJQUG1JVU52LzRLZStmSzhZRVdXNFpoME5qWTJLMm9wei9mdDdRMXQ3aTRPRC90SnhnTTVpZjkwRFFObnVQaDlYZ1FDVWM2cHkzeFNDUVNBSUFMTHJqZ3RqdnV1R1BFdUhIalBpQU5QSHRSQUtScXQ3MzV3ekFNTEJZTDZ1dnJMM24vL2Zlckd4c2JKMW10MW43TjR0OVpVa2lycE5VYURVYU1HSUZweDAvSFB6OTRIOWxzRmdxRklrOWVsbVdSU09RcTBBcUxpaER3KzNITERkZkI1L09odUtRRW1Vd0dUWTJObUhmQmhUanI3TE5SVzFPZGovR3B6bVVWbVV3R1Ztc3VXZWwydTJIUUcvREFJNDlDcVZEQjcrOWU5c3R6SElZTUdRcVAyNDJIN3JzWGI3enpEaGJjZWdzcVZxK0dVcWtZc0RGV1VvaGxNQmlReVdSUVdWbVpqL1g3c3d4REZFV2swMmxvdFZvNEhBN0VZakc0M1c1d0hOZHRQbCt1R2pEZDJTUEJJSmxNSUpQSndHYXpoVTgrK2VTVGpqcnFxR2Rqc1JoOG5XZi9KTkUzc09qMzB5SXA4dDRDUlZHUXlXVFVraVZMRnYveXl5OW5Bb0RGWWhuVWNkeEFydGhIcVZMaDhVY2VSaUtSUUhGSkNYaWVCOE13OEhvN29OUHFNSDdDQk5UWDFVRVFCSlFORzRhNjJscmNmc3ZOZU9QdGQyR3oyUkVJK09IdDhPRFBkLzBGNFZBSVgzM3hSVDZFU01Uak9IZmVQQnczL1hqNE8ydjhXMXFhTVdYcVZEenkrT080OGJwclFkTTU0WlBLaDNtZXg3RHljbFJWVldMQkxiZkFacmVqZlBqd0Fmc3VwT05VYWU5ZVMwdExQZyt4bzVGb2t0Vm5HQVpPcHpQZitwdkpaSG9kekVsUmRPY3hhSzZCNThRVFQvejRwSk5PdW03anhvMStsOHNGazhsMFFBN3IyS2NFWU1LRThhQ1FhK0JRS0pTRFBxR21wNHk4M1c3SHQ5OStlNFRQNThQNDhlT1JUQ2I3WlJGMjEycndISWRNSmdPbFVwbHI1WlhKME56VWlGR2pSdVBtUC8wSmxWdTJZdDNhdFZBcWxkRHI5U2dmUGh3cmZsNkd4eDU1R0E4ODhnZ3ltVFFDZ1FEc0RnY2VlZUpKSEg3RUVhaXRyb1lJWU5UbzBUaDd6amtRT3BPTzBueTdodnA2bkRaekZoNktSUERZd3c4aEVZOUQzVGxCUnpwSjBPc04wT24wK1RoNmR6OW4xOEdjc1ZnTXJhMnQrZmJhL3RSUmlGMDI4R2kxV25BY0I0L0hrMisvN3VuOXVWTHEzRXlFd3NMQ2xyUFBQdnZPd3c4Ly9LUDI5bllFZzBHVWxwWVNsdTRMQXFBM21pSHdBaWhLUkNnWVFDSWVCMEJCb1ZUMldPYzlHREFhamVLaGh4NTY3OXExYTErUHgrTlFxOVhieGRRRFRYNEpVb1dlS0lyd2ViMllkdngwM1BHWHUvSEJlKy9pOVZmL2djTENRcFNYRDRmYjNRNlpUSVpoNWNQeDN0dHZ3V0sxNExiYkY2Q3hvUUYrbnc5YXJSYVhYSFk1ZUk0SElPWUdobmk5U0NXVGVWZGZPaTV6dFRUamlxdXZRU0FRd0F2UFBvUFNIdXJhcGMrM3U1OVQycmJMTUF6YTJ0cmdjcm55UjVCZDh5KzlmY2NzeTRLaUtCUVVGSFNiZ0NTVHlmck1GVWpET2c0Ly9QRFhaODZjZVpQVDZVeTN0YlhseFpCZ0h4R0FZY05IUVlBSWhxYmg5M25SMHR3TXJVYURjQ2lBVnBjTE1oa0RwVklKaXFJaERqRDVKTlRYMTJQOCtQR0xLWXA2dmJxNkdvY2Nja2grMXR0Z2tyK2JOOEJ6VUNnVXVPSG1tL0hLU3kvaS9mZmV3NFFKRS9EMGM4OWoxY3FWZU9XbEYyR3oyL09KcnhlZWVRYUZCWVdZZDhFRnFLMnRSVHFkUnF2TDFlMmNYMG82OWtTcXhvWUczSFRiYmZodDh5YXNYTEVDRG9kandEK25WTlNUVHFkUlhWMk5hRFRhNTVyc2JTRnQyeldiemNoa01wQUtjM3AzK2YrM2Q4OXV0MmZPUFBQTXkyUXkyWWVaVEFaK3Z6ODM3NC9FK3Z1V0FHU3pHWWdBMG9JQWg3TUFTbzBlYXBVS1BKdEJPQndDRGFDK3JoYnBWQUlNUlVNVUJmQjhMdGxGMHpTVUE3QkZWUlJGakI0OU9qQnAwcVFWYTlhc09icTF0UlhsNWVWSUpCTGRpbWNHaS96NWg1ZmpzSFhMRnBRTkc0WkxMcjBNbDF4Mk9aYi92QXp2dlBVbXpCWnozb0pyT3ZzUDdydm5iM0FXRkdEYTlPbW9xNjN0MTRSaG51ZGhkemhndHp2d3hXZUwwZFRZQ0oxV082RGtseXk4WEM1SE1CaEVmWDE5ZnM5ZWY2MitLSXF3Mld6NURIOGlrZGpodHQwdXMvalhYM2ZkZGVlekxGdTlkT2xTYUxWYVF2eDlWUUR5TVJ0RklaTk9JeEdQSVp0S3dtZ3lvV1RvVUFpOGlFU1doMW9oaDltb1J6S2RRcnFUbU5sTUduNmZGN3dnUU1iSW9ObkZQN1MwMnZtRUUwNzRjTTJhTlVkTHJhWkRoZ3hCT3AzZUkyRUl3OGdnVnlqdzF1dXY0N1RUWjJMOHhBbDQ3cG1uOE4yMy8wWnBhUmtVaXR5NWVEd1dnMUtwaE5XV0cycDUrNjIzNEwwUFA4TElVYVBRMk5EUWE3WmVxbndiTVdJa2FtcXE4Y1FqRCtPYnI3NkNUQ2FEMVdick5nNXNWOGtpWmZpMVdpMWlzUmlhbXByZzkvdnpZN3Y2YS9VTkJnTjBPaDB5bVF6YTI5dkJjVnlmMjNZNWpvTWdDQ2d1TG00NTdiVFRIamo0NElQZlZLdlZhR2hvSU1UZlh3U2cyeCtWcHNGeExCSnhEcUlnZ2dJZ1Z5cWgwZW5CS0ZVd21heElaeklRQlI0Q2FBaUNnRXc2aGVibXB0eVJUbWNHbU41MnNVTWZDSVZDS0M0dS9sQXVsNy9Nc2l3Nk9qckFNQXlLaTR1UjdLeUNHK3llZDRQQmdIZzhqamRlL1VmTzBtczFHRDE2VEg3WkJFM1RLQjAyRE82Mk5tU3pXUlFVRnFLcHNSRzMzM0l6M3ZuZ254Zy9ZUUs4SFIyNVlSZ3NDNDdqOHV1cGREb2Rpa3VHNFBQRm4rTFJoeDZFcTZVRlpjT0c1ZGRhN3k3NXBlcEZ0Vm9OdDl1TnhzYkdmSkt1UCtmNkVvbnRkanRVS2xWKzJ5N0RNSDJTWDdMNlk4YU0rWDcyN05sbmpCdzVNdTF5dWNCeEhJbjE5MWNCNklrY0FzK0RaYk5nc3l4NGlrSXFsWVJXcThXWWNlTWdDQlFnOG5BVUZDRVdpNE9DZ0E1M0c3S2RrM0ZwbW9JZ2lLQm9HckxPUVpFOVljU0lFZUVKRXlhc1hMOSsvVlFBYUc5dmgwS2hnTTFtUXlxVkd2UXZqZU00cUZRcUZCUVdkb3RwcFhQcTZxcEtQUHo0a3dpSFFuanU2YWN3WXVSSWxKYVZvYWFtQmd0dXV4V1hYWEVsVkNvVlRHWXo5SG85VEdZelZDb1Z0Rm90RXZFRVhuenVXVHozOUZQUWFEUVllOUJCK1hoNUlOeCtLVHRmVzFzTHI5ZmJMZGJ2VHdPUFVxbUUxV29GeTdMNVJLRkUvSjRHZmtqM3JsQW9NRy9ldkFmR2pSdDNyNVJrSktXOHZ6TUI2TTFxQ0R5UGVDeUdiRFpISEllekFEeDgwT3UwS0NzdlJ5SWVoeWdLU0NlVG9Ha0tiRGFMZERvTmlKMFBDRVhuSituU05JMWh3NFpoNXN5WkgwZ0NBQUJOVFUwd0dBeFFxVlJJcDlON3pLV1Vyc013REJMeE9Ed2VENDQ5N25pVURTdEQwZEZIWS9teVpXaG9xSWZSYUVSNWVUazJiZHlJNjY2K0NsYUxCVWF6R1NhVENTYXpHUVVGQlNnYlZvNDF2NnpHbDU5L0JtZEJJWFE2M1lDTUFlKzZnU2NZRE9iMzd1Mk0xUWR5ZFJkUzJCQUtoZkt4L282cy9zU0pFeXRtejU1OS9iQmh3OVp1M2JvVnlXUXl2MUtkNEhjdUFOcytGS0lvSUpWS0lwTk9RU2xub05PcG9kWm9JWUpDbWhXaDBXb0FnUWNUaitYeURaazBCSTZGWEs1QU1obEhLcFdDd1BNNDZxaWozbk00SE05NXZWNkY5UHVycXFvd1pzd1lLSlhLSFI0UERpVDVnVnhCajk1Z3dPMTMzUVc3elk0M1huOHRkM2F2MXVRckIzbWV6eGN2c1N5TERvOEhycFlXc05sc3JnZWU1NkhSYWxBMnJCd1VUZmRJL3AzNVRGS3NyOVBwa00xbVVWZFhsNitvNjA5UmoyVDFWU29WTEJZTFdKYUZ4K1BKbC9mdUtNT3ZWcXZGVTA4OTlaWVpNMmE4SUlvaW1wdWJ5YkNPQTFrQWVyUk9QQStPWXlHS2dNQnp5R1l6MEdnME1GbXNVQ3FVNlBENVFWTkFnZE1PVDNzYjRpNFhrdWswMkV3bXdiR1oxUmFyN2JqYjc3b1hiNzc2SXVwcmExQlRVNE9ERGpvSUNvVUMyV3gyVUU4RHVpSWVqK080NmRPaFZxbng1OXR1UlNnVWdxNXp1OUMybGx4YWZDbGwyN3N3Tmo4aFIrekJPdTRzK2FXa25tVDFwUjc4L2xoOWljUm1zeGs2blE2UlNBU1JTQVFNdy9SSmZzbnFqeG8xYXUya1NaUG1qeDgvdmlZU2llU3JKd21JQVBRclpPQjVIcFNZMi9vaWt6RklwVkt3T3B4d0ZwVWdIazhnSG8zZ3h0dnVjS3YxRmh3L2ZRWVltUXgzM0hJdDB1azA2dXJxTUdyVXFFRmJxdGtURWUxT0oxYXZYSW12UHY4Y0JxTVJRNFlPelpOZVJHNTZrTkI1Wk5hcld6OEFCVTBTc2RWcWRlZEk4V2E0M2U2ZHR2clNzQTVSRk9GMnU4R3liTCtzUGdETW5UdjM3OGNjYzh6MUZSVVY4SHE5c0ZxdEpNdS9qMktmOThXNkZzeHdMQXNLSW1LeHVNUGpEejg2NGRBalp6dnNkdnl5YWpuR2paK0lxNjY3QlFBUWpVYlIwdEtTWHprOTJPVFBXMjhBTnJzZGFyVTY3K29LZ29DNm1ocU1IVGNPZnpoOUp1THhlUDYxdTMzTkhtSjlxVzAzSG8ranFxb0ticmU3MzhNNnBMYmQzQ1plSzlMcE5OeHVkejZIMEpmVjUza2V3NGNQMzNMZGRkZWROMmZPbk9zRGdRQmlzUmdoUHZFQWRoOVNwbGttWTlEUTJIeHRZM1ByaytsTVJxdnNIQ010azhuZ2FtbkcyZWZOaDB3dXg5K2ZmeEplcnhkS3BSS0ZoWVg1NDhIQnZrY3B0aFU3MTFZSGd3RUUvQUhjOFplN2NlSkpKK0hwSng2SDMrZURScU9CczZDZ1h5dStkc2J5UzlPT0d4b2E0UFA1QUtEZlJUM1piRGFmNGVkNUhvRkFvRnNEejQ1S2VVODg4Y1JiWnMyYTlieE1Kb1BMNWRwdVB3SUJFWUJkSnBaR293Rk5VY3pHelZXdk43VzBYcXBTS3FCUnF5R0svMHQwQ1lLQXhzWjZuSFhPWExTM3RlQ3pULzRQTHBjTENvVUNGb3VsMzQxREEwRkdkTHI4eFNWRDhQQmpUOEJSa0p2WjkrTi8vNHZKVTZkaTVNaFIrT3JMTHdhazhrMFNIcTFXaTBRaWdmcjZlaVFTQ1NnVWluNVBQcEtLZXFUNmhuQTRESnFtK3hYckR4a3lKSERxcWFkZXBsQW92cEJHa2ttcnRnbUlBT3pXZ3kyWHlXRFFheEVJaFkrdHJLNTdNeGlLak5ScE5hQnBhanN2bXFKekpick5UWTI0L3RZNzBOelVpRi9YVnFDK3ZoNEtoUUphclJhcFZHcTN0di9zRERMWkxFYU5IbzF3S0lRTDVwMkh5Vk9tNFBOdi9nMi96NGZQRnk4R3g3SzdmYzF0MjNhbHMvWCtWUE4xYmRzdEtDaUFYQzZIMSt2dHMyMVh1aWJiZWU4elpzejQ4T3l6ejc0eEZvc0ZmL25sRjVoTXBnR2JSMEJ3Z0FxQTlOenFkRnF3TEtkcWFYVS8zdWJ1dUFrQTlEcHRaeEpyRzJKUS8zdW9NK2swZk40TzNIVDdYYmpuamx2aGFtNUNiVzB0RGpyb29GMCtIdHdWMFhBNEhGaiswMC80NklNUGNPS01HVGpwbEZPeGVkTkd2UC9PdTZqY211c2o2T3VNdjY5cmJ0dTI2M0s1RUlsRWRycHQxMmcwUXFQUmdHVlorSHkrUHR0MnUxcDlpOFhTZE82NTU5NCtaY3FVUmNGZ0VHNjNtN2o3SkFrNFVMRytERHF0Qmo1LzhLUmYxbTdZNG1wejM1UnorZnRYbzA1M2RpdnE5UVk4K3N6TE1GdXM0RGdPZFhWMW9DaHFwK2NZN0tySHdIRWMxQm9OYkhZYnlvY1BSenFkd3A5dnV5MjM3WGMzeUM5WmVLVlNpZGJXVm16WnNnV1JTR1M3dlh1OS9WNldaZk1qekxSYUxRS0JRTDQyb0xmM2R5WC9zY2NlKys1Sko1MDBxcXlzYkpISDR5RnR1OFFER0RqeXE1UktRQVM5dGJydXVjWW0xNDBVUlVHbjFXeHpkTld6OWUvMm9XUXl1TnRiVVRLa0ZBODk4Unh1dS81S0pKTkoxTlhWWWVUSWtmbWEvVDBScHpvY1R2enczWGRJSkJJWVZsNmV6N2J2cXVEb2REcWtVaWswTmpidVV0dXVYcStIMFdoRU9wMkcxK3NGZ0Q1amZhbjIzMlF5Wlc2NjZhWUxUU2JUeHovODhBTkNvUkFzRmd1SjlZa0hzUHZFbDhrWUdQUTZzQ3hiK091bUxXdHI2NXR1VkNvVlVHOW45WGRNZmdrTUkwT2JxeG5EUjR6Q24vNXlUeTR4RjRtZ3BhVWxIemNQbHZYZjFoUFE2ZlZ3RmhUa1ArL09Yazl5elRVYURVS2hFTFpzMllKb05BcVZTdFV2cTg5eEhEaU9nOVZxaGNsa1FqQVl6Qy90N00xNlMyR0NJQWlZTUdIQzZudnV1V2ZDdUhIalBtNXJhOHNQL3lBZ0FyRGI1TmRvMUJCRnlDdXI2eC9mV2wxWGswaW1EdFhydEQxVXErMWszTjRwQW8zMXRUajYyT054OGVWWEF3QzhYbSsrUm1Dd3liKzdlUWJwODBzSnpKcWFHbFJYVi9jNzBTZFpmWjFPbDFzekRxQ3RyYTNQVTRKdDZnRmE1czJiTi8vcXE2K2VvdEZvYWx0Ylc4bGdUaElDREJ6MGVpMGlrZGdoNnpiODlrazRFaDJ1VnF1Zzd1OTRzWDQrZ3lLQTlsWVg1bDl5SlVLaEVMNzRkQ0U4SGc5ME9oM01abk9QeDRQN3dnTXVUZFJScVZUd2VEeTczTFpyczltZ1ZDb1JDb1dRU0NUeXBidzdpdlZQT2VXVW40ODY2cWhURTRsRU1ocU5ncUtvSFlvbUFmRUErZ1dsUWc2TldvVm1WL3MxcTlmOHVpNGVUd3czNkhXNUZ1QWVIMnhxcDhoUGJadjR5bWJoYW1uQzlUZmZqaU9uSEEwQWFHaG9RREtaaEZxdEhyQnR3UU5oL2FWNzBXZzBvQ2dLdGJXMWFHaG95TmYxNzJnNnJuU3VMNWZMVVZSVUJJcWkwTmJXaG1ReW1SZVBucTR2dWZ4cXRScHo1ODc5MjdYWFhudWNRcUZJdHJlM2s3WmRJZ0FEWTlGb21vWldvMFlxblJuVzNOcStxSzZoK1JXZTUrbGNHQ0R1bnFudjQ5VVVUU09kU3NIcjllQ3VleDdFcURFSFFSQUUxTlRVNUN2Zzl0Wnl5VzIzLzBpbHZGS3M3L1A1T3FzZ1pmMHE1WldtSnRsc05pUVNDWGk5M255MVpGL1ZmQnpINGVDREQxNXg5OTEzSHpKdDJyU0hQQjVQdnZtSGdBakFicE5mclZKQnJWYWl0cjdwMWwvV2Jhd0xoU096dFJwMU4zZFVXc1JodGxoN3QzUzd5RkdhcGhFSmg4RnpQUDc2d0tNd21reGdXUmFWbFpWZ1dYYjd6cnc5U0g3cGxLUHJ0bDFKbkhabTI2NWNMb2UwSWNuajhTQVVDa0V1bC9jWjYwdWZmY3FVS1RlZWYvNzV4OWp0OW8zU0hnQmk5WWtBREV5c3I5TWltVW9QLzNYamx1KzNWdGM5SXdvaXJlNHlKRlI2dUozT0FqVFcxK0h6UlF0elJTM0tiZklCTytINjl3U0dZZUR4dE1OZ05PSCtSNTRHa0Z2NTNkemMzS3Q3dkNmSXp6QU1OQm9OZ3NGZ042dmZuNXFGcnR0MmJUWWJvdEVvZkQ1ZjNwdm83ZHBTaG4veTVNbXJicjc1NW9tbHBhVXZCWU5CWXZXSkFBeWMxVmNxRkREb2RHaHNicjF3MVpwZks3Mit3QXlkVmdPNS9IL3VxQ2dLTUJpTXNGaXRXTDdzUjZ4ZnR3WU13MkR6eGcxUXFkU1F5ZnBYdU5OZng0QmhaR2h0YWNiSU1XTng1ejBQQWNoMUR6WTFOZVc3Qi9mRWNOR3UyM1pWS2hWYVdscFFVMU1EbG1YelZuOUhrQnB1Q2dzTG9WUXE0ZkY0RUl2RitvejFCVUhJSi9yT1BQUE14Mis5OWRhcFJxTnhzN1NVazJUNER5eklCdVBCcHVsY0FVODhuaWhwY2JYZjJORHMrck5DTG9kV3ErbENmTEZ6NVpVVnRUVlZxTno2RzlLcE5FNCs1UThvSHpFYVAvMzNlNno1WlFVT1BleElDQUlQRVFOSFNvWmgwTnpZZ09relRrWWtITUlyTHp3Tmo4Y0RtVXlHb3FLaVBUSmhXQzZYUXlhVElScU53dVB4SUJ3TzU0L20rcFBoRjBVUkpwTUphclVhcVZRS1VpTk9mMHA1eThySzFweDY2cW1QalJzMzd0T09qZzZFUWlGaTlZa0FESnpWVjZsVXFLbHJ2S20rb2ZueFRDYXIwbXJVMngxZHlXUXk2UFFHL1BqZkgxQzE5VGNjTmZVWUhITDRKS1NTS1RRM05XRENJWWRoL1pyVnFLdXR3dGp4RXhBT2hYcDEwWGZWWmpYVTFXSHUvRXZoOTNueDhVZnZRenJuTGl3c0hOVGhvbXExdXJON3NYRzd0dDBkaFEzU2NsS3BiZGZ2OTNjYjBkVVQrYVVHSHBsTWhoTlBQUEdPOHZMeUowYU9IQW0zMncycjFVcGlmU0lBQS9SZ3ExUVFSRkcrY1hQVmEvV05UWmNvRllxODFlLzZZRXF0cHQ5Ky9RWDhQaS9tWDN3NWRIbzlndjRBZ0Z5aFNTcVp3TVJERHNQUy8zd0h0VWFEOHVFakVRd0d0bnRZZDVYOEZKVVRwSWE2YXN5NzhESlVWMjdCcGczcjRYSzVZREFZb05Gb2RxdDdzQ2NTU3JGK1BCNUhRMFBEYnJYdHhtS3huUnJSVlZSVTVMbnh4aHV2QnZERnlwVXI4MU42aU10UGNnQzcvV0RMNVRKb3RSb2swK2xqTi81V3RibWhxZVVTclViVGF4Skw3RnlFV1ZvMkRMUFBPUStNakVIQUw2MS96cjJHNHppQXBqRDU2T05RVTdVVlRZMzEwR2kwQTU2SVN5YVRTS2RTdU8rUnB6R2t0QXhBTGd2UDgveUE3VHpzR3V1M3RiVmh5NVl0U0NRUy9ZcjFwUVllQUNnc0xJVEpaSUxQNTBNa0VvRmNMdS9WZWt1eFBrVlJPT1dVVTk3NTA1LytOTHFzck95THRyWTJFdXNUN0w0QVNMVFE2N1RnV0Y3elcyWE5LL1dOTGN0WWxoMnQxYWgzMk01S1VSU0dqeGdGUVJDUVNpWkIwOXZ2eGtzbUVqQVlqQmc3YmlJODduWndYUGNhOUYxL2hLbHUrWUJnMEE5ZTRQSHdVeTlnK01oUlNLZlRxS3FxeXEvSjJsVVJrR29mOUhvOWtza2txcXFxME5MU0FwcW0reVV1WGEyKzFacnJhbXpyWERiUzE0Z3VsbVZ6RTRZMUd0ZWNPWFBPdXZEQ0N5OU5wOVBSam80T3NuZVBZUGREQUZFRVpBd0RyVVlObno5dyttK1Z0YTlFWS9FaE9vMEdERVAzbXpDcFZCK2JmQ2lBcG1oRUlpRTRDd3Boczl1UlNxWHlBeWNHZ3Z4NUVaREo0SEczWTJqcE1OeDkvMk80N1B6WlNDYVRxSzZ1eGtFSEhkVG5BdExlSU5Yck13eUQxdFpXdExhMjd0UzJYV2xZaDlQcEJFVlJDQWFEK1cyN3ZSWDFkSFg1NTg2ZCs3WldxNzJSNS9tRTMrOUhPcDJHWHE4blR6ekI3bmtBb2dpb1ZBcklaVEpzcmFsL2VlMnZ2MzJWU3FlSEdQUzZ6a2s5NG9DUThuLzVBZ2JwZEFvY3h3M090Qm5xZjBuSlZsY1RyRFk3RnZ6MS9rNkJ5clhkOXZkWXJpdDBPaDA0amtObFpTVmNMaGRrTWhsVS9WeVFLbTNiTFN3c0JNZHg4SGc4WUZtMnozeUI1UEpicmRiSTdiZmZQdnZjYzgrOVRCVEZSRGdjSmk0L3dRQjRBQ0lnbDh1Z1VNZ1JpOGRMcXVzYVB2RUhRa2RwTmJtZDhoaklZek9xWjNkNElGMy8zc1NtdmMyRmswNmJDVTk3Rzk1LzZ6VUVnMEYwZEhUQTZYUWlrVWpzMEdWWEtwV1F5V1FJaFVKb2JHenNWbVhZbjJFZEZFWEJhclZDbzlGc3QyMjN0L2RMT1lLSkV5ZXVPdmZjYytjV0ZoYTZtcHVia1VxbFNJYWZZR0FFUUt2VElzdXk2dDhxYXg3M2RQaXU0amhlYWREcjhobitBU1BsYmxiNzdkUTdleEdhcHZvNm5IL3g1V0FZQnUrOC9rcStFOC9wZFBZNFlianJ0dDFvTkFxMzI1MGZyTm5mV0QrYnpjSmdNRUNyMWU3MHR0MFJJMFo0RGp2c3NPdUdEeCsrV0tWU29iVzFGVWFqa1ZoOWdvRVRnT2FXbG5udEhjSG5ZNG1rbmVkNHFGVC9TNDRObGtVZVZGQjlXK0kyVndzdXVlSWF0TGUyWXNtL3YwUlRVeFBrY2psTUpsTzM0MEZwWnI3VXR0dlUxSlJ2MisxdlVRL1A4N0RiN1ZBb0ZQbTIzYjdtKzNXTjlTZFBudnpUelRmZmZHWmxaV1drcGFVbFgwSk1RRENnT1lBTkZTdkZUeGQrWUdkb0tsK0VzcWRJT2RpdS83WmdhQnBzTm9OV1Z3dXV2TzRtMkIxT0FFQmRYUjFTcVJSVUtsVis0NUJPcHdORlVhaXJxME5qWTJPM3R0MGRXWDFwQTA5SlNjbDJiYnU5aVlma0xXZzBHbHg0NFlWM1hubmxsY2R6SEJjaHd6b0lCbFVBcGt5Wi9DK3dxUmRmZXZaSjZJMUdhTFU2Q0lMd3U3TCszYTFzcm51UXBtazg4dFFMTUpzdEVFVVJqWTJOdVpCSXE0VmFyZDZ1Z2FjL0k3cWt0bDJ6MlF5THhZSkVJb0dPam80KzIzWWx6NFRqT0l3ZE8vYm52LzcxcitPUFBmYll4ejBlRDZMUktDbmxKUmhjQVJnNWNqUXV1UENpbDJvcmY4T3JMejJYVzI2cFVBNGNBM2ZSK2tzdXVORm9BbnEwbXJ1ZVkyQVlCcDcyTnRqc0Ryenc2anNZTlhvc0Vva0VhbXRyd2JJc21wcWE4disvdnljRlBiWHRCb1BCSGJidGRtYjRjZHh4eC8zcHVPT09PODV1dDI5cGFXbnB0cEdJZ0dEUUJDQVFER0w4dVBFMUo4NDRxZXE3cno3RHQxOS9BWnZkdmxkZGYxRVFZTFBiRVkvSHNYelpqNURMNU50WXdnSFl1c1BRU0tkVEtDb3B3ZGp4RXdIa2hvdHUzTGd4Yi9YN000dGZhdHUxV3EydzIrMklScVB3Ky8wQTBLKzIzY01PTzJ6RkF3ODhNRzd5NU1uUHVOMXUwclpMc0djRklCUUt3V1F5b2J4czZNSmpUemdGQllXRnFGaTFBbWFMZFZCZGY2b1hNaWxWS3RnZFRxeGI4d3UrV1B3SjJscGIwTmJhQXFQSlBDQkNJd2dDMUdvMWlvcUhvdFhWZ252L2Nqc3F0MjZHcW5NdW5pQUlVQ3FWL1dvZmxrcHlwYlpkdDl1ZGI5dnR6ZXB6SE5lMWJmZUpHMis4OFJpbFVybTFyYTJOeFBvRWUxNEFlSjZIUHhEQWxDbVQzMVNyRkRqaXFLT1JaYlA0ZFYwRmREcjlydE41SjU1ajZjalI3bkFpblVyaDY2OCtRMjFOTmFhZE1BTVhYWFlWZkY0UE5xeGJBNFBCMk92Mm9CM2RtVVJtaDlNSmlxYng3Njgrdyt1dnZJQ1dwa1k0SElYUTZ3M2RSS0kzSW5hZHJtczJtMkcxV3BGS3BkRFcxZ2FlNTNlWTRSZEZFVU9HREZrMWUvYnNQODZZTWVNT3FXV1lXSDJDdlNJQUZFVWhGQXBoeGtrbnQxUnRXci9zZ2IvZGlkbm56RVBBNzBOTjlWWm9kZnFkcndMY0NZc3NkZFBaN0E2c1cvTUxGbjcwUGt4R00rYk52eGpsNWNNUjhQdHcrQkdUNGZkN1VibjFOeGlOUm9pZG1mcitRaEFFS0pSS09Kd0ZxS3JjaW4rODlDdysvM1FoWkl3TWRyc1RQTWZsY2cxZFJMRzM3MHFLOVFzS0NxQlFLQkFJQlBLeGZtK0pRaW5ERHdEWFhIUE5YK2JNbVRQVmFEUisxdEhSQVpabFNheFBzUGNFb0NzdXZPamlmLzIyY1IwKy90Y0h1T0RpSzlEUzFBU2Z0d002dmFIL3d6MTNNdTdQWmNqbCtQS3pSVmkxNG1lY2N0cE1URDEyR2dJQlA2TFJhTDRvWnVveHg2T3h2ZzVOVGZYUUcwMjUrK25IdFhMYmI4d3dtY3o0NXN2UDhOcmZuNGVuclEyRmhjVlFLZFdkcGJZWm1Nd1dhRHRuOTBuWi9HMUpMRFh3T0J3T3hPTnhlRHdlOER5L3d3MDhITWVocEtTazdlNjc3NTUxMGtrblBlcjFlaUdONUNZdVA4RmVGd0NLb3VEeGVIRGE2YWQvREFEUFAva0kxcTVaalhQbVhZZ3RtellnRVk5QnJkYnNPQk8vaTBpbmtyQllyWmgvMGFVb0xTdUh6OXVSdjYrYzFjMkNwaGxNUGZaNHVKcWJFQXI0SVZjcSttWDFpMHVHSUpHSTQ3MjNYOFBYWDN3S3ZWWVBpOVdXQ3p2d3Y2R2xNcmtjT3IyaFd5R1FkSDJPNDNMaGc4TUJrOG1Fam82T0hiYnRTbFpmRkVWTW56NzlyYnZ1dW10a1dWblpWeTB0TFh0c2ZSa0JFWUIrSXhxTm9zRHA5TjkyMjIwM0FjQmR0OTJBcXNyZmNNU1VvN0ZtOVVwd1BBdVZTdDEzT0xBTFdYK2U1OEhJWkRqaXlDbWdhUnJoY0hENzRTQVVoVVFpRG9QUmlLR2w1V2hwYWVyelVvSWd3R3ExUWlaajhOWG5pL0QzNTUvQytvcGY0SFFXUXRtbDJDZFAxczVyYURUYWJwdDBSVkZFT3AyR3dXQ0F4V0lCeTdKb2JXM05GL3IwSnFiU3VmNndZY1BhWnMyYWRjWXh4eHh6T2NkeEtkSzJTN0JQaHdBZWp3Y0xGaXg0OFE5LytNUExITWRod1UzWG9MaGtDQTQ3NGlqODlOOGZJSW9DWkRMNUxsbC9xZy92UXhSRnhHSTVkNStpNkI3ZlNkTTBvcEVJQ2dvTE1YemtLR1F5NlI2dExrM1RLQ29xUmlRY3hqdXYvd09MUC80L0pCTkpPSndGUFdiMnBYL0taREt3V0d5Z2FSazRqZ05OMHhBRUFZV0ZoZm5Db0dBd0NJcWkrdFcyTzJ2V3JOZi8vT2Mvanl3cksvdXl2YjJkTlBBUTdOc0NJTG02TFMwdGVPQ0JCMjQ0N3JqanZnV0F2eTY0R2VNbUhvenk0U094YWNONmFMUWE5R2ZKejZCOEtKcEdKcHNCVGRQYkRSb1JCQUU2dlI0MnV3Ty9yRnlPRjU1K0hIVTFOUmhhV2dhTlRyZWQxZTlLZmlCWGUwRExaTERhN2ZuWitRVUZCZUI1SGg2UEJ4ekg5Vm5VdzdJc3N0a3NIQTVIZk1HQ0JXZk1uajM3cWtRaWtaS1dkUktyVDdEUGV3QUFFSS9IWWJQWjhQVFRUNTgyZE9qUWRaczMvb3BINzdzYnA1eCtCblI2UGFxM2JvWFJaSVl3Z0hQOWQvYWRYY2tzQ0FKa01oa0tDb3VRU2FmeDBYdHY0WU4zM2tBMms0SGQ0Y2haNmg2c3ZyaU5zTVRpY1NSVFNmQkM3Z1FnbTgzQzUvUHRjTnV1OUZvQUtDc3JXM2JwcFpkT0dEdDI3SmZOemMxSXA5UEU2aFBzWHdMQU1Bd2FHeHNobDh2eDRZY2ZIcVhYNjBQZmYvczE3cnZyVHpobTJva0loWUtvcnR3Q2s4bmNvMVVkVlBKVDJ3dUJ5V1NHd1dqQ3NxWC93Y3ZQUG9uVkszNkd4V3FEM21qc01kWVh0N0hjUUc2enNOVnFqUzI0N2RiVHp6ajlEMDlKdnp1ZFR2ZHA5VG1PQTh1eUtDb3Fjdi8xcjM4OWU4NmNPZFBTNlhTVDIrMG1WcDlnL3hRQUNkRm9GQVVGQmZ3VFR6eHhQRTNUK09HN2I3RHduKzlpNWxsejBGQlhBM2Q3S3d4R0l3UlIyRE9maU9vZTZ3T0EzZWxFTEJiRnU2Ky9nbzgvZkErSmVCek9nc0xjZVh3WDhtOUxmTW5xSnhJSmVEd2RPT2lnZzlaZWZORUZFOHFIbFgxejZhV1hMaWdzTFB5cXE4ajB0R1ZZeXZCUG5UcjFwenZ2dkhQc21ERmpQbzFHbzRqRllzVHFFK3pmQWlCVnU3VzB0T0RjYzgvZGRNODk5OHdGZ0hmZWVBWDF0Ymx4Mnh2WHIwVXc0SWRXcCt2MVpHQXdPZ3BGTVJmckZ4V1hvS0cyRnE4OC96UTJyRjhMaDdNQWVvT2htOVh2aWZqU0ZwMk9EaS9VYWpWbW5uN2FJeWNjUCswSWpVYlQvT3VHRGFCcEd2Lzg1ejlubVV5bStMYmhCb0I4S2E5ZXI4ZGxsMTMycDZ1dXV1cDRRUkFpcElHSDRIZmxBVkFVQlpxbVVWVlZoVC8rOFk4TGI3MzExdHp4NEo5dVFJZkhqWk5PblltdFd6YUJZemtvZG1QQ2JuLzFRSnJPWTdVNWtJakg4Zm1paFhqekh5OGhIb3Voc0toNHV3eC9UM2REMHpUaThUaUN3UkRHalJ1NzZZYnJyNXQrNGduVDcvYjVBNGpGNGxBcWxSQUVBZVBHSFlTNzc3NzdWSTFHSTBnQ0lDWDZSRkZFYVducGp4ZGZmUEZCMDZkUGY4YnRkaU1lajVOU1hvSjlDZ00yWlRPZFRrT2hVT0RCQng5ODBlUHhVQjk5OU5IejExdzJEMjk5dUFnVERqNE1LNWI5RnllY2RCb0VuZ2ZQYzNuclBaRFdYeEFFYUxSYVdDeFdyRnErREY4dS9nVGhZQkFtaXhrcTFmWldINzFZL1VBZ0FKUEpoTE5uejc3cjhNTU9mWXhoYUxTMHVDQ0tJbmllUjJHQkUzS1pITC85OWhzdXZQRENGV3ExZXNvTk45endpNVRrTXhnTTR2bm5uLzhucFZMNUxNL3pJTFA0Q1g2M0hvQUVobUdRU0NTd2VmTm0zSEhISFM5TW5UcjFKemFieFMzWFhJYXk4dUVZUG5JMFZxOWNCcVZLbFQvREh5anlTOVY2Tm9jRGNya2NpLzd2UTN6MDN0dklwTk53RmhaQ29WRG15Uy8yUWY1c05ndWYzNCtpb3FKMUYxNHcvOUJqanozNnNYQWtna2drMm8yOE9ROUNCRVhSYUdob3dORkhIMTJ4WU1HQzJRcUZBdVBHamF2NHkxLytNbWJLbENuUEJvTkJKQklKNHU0VC9QNDlBQW5KWkJLRmhZVzQ2NjY3VHBnL2YzNVZ3TzhiK2V6akQrSHhaLytPZDk5OEJSdlhyOFdrbzZZZ0hBb05pRVdVckw3WmFrRk5WU1crL1BSajFGVlh3V1ozUUtIc1RuejBZZlg5Zmo4RVVjUlpaOHhhUEhMa3lObUN3TVBUNGMzVjhHOHpqancvQzdGenM1Qk1Kc00xMTF5ek9KbE1UclBaYk10VUtoVmNMaGV4K2dRSGpnZlExUk5vYUdqQWlCRWpoSVVMRng1dHM5azIvWGZKdi9Iby9YZmpyRG56SUFnaTZtdXFZVEthK25VODJKdjE3NXJoRnlIaXE4V0w4TWJMdWJiZHd1SVN5QlVLQ0lMUXE4V1hZdjEwT28xd09Jd0pFeWI4Y3NWbGw4Ny80MWxueldheldVU2pVZEQ5SUMvRE1FaW4wMmh2YjRmSlpGcVdUQ2JKaUM2Q0E5Y0RrQ3lqeitkRGFXbXA3NzMzM2p2eXZQUE9pMys2OEVPWlNxM0dKVmRjaTM5OThEYlVHZzBLQ29vUWpVWjIya1dXR25nc1Zpc3F0MnpHbDRzL1JrdGpZKzVjdnpQRDM1OVVZeVFTQlNEaTlEK2M5dFFKSjB4ZmtNMWs0UFA1ZHJvd1Iwb3NTdE9DaWRVbk9HQTlBSWtRUE0ram82TURSeHh4Uk9hbW0yNDZCd0ErZlBkTkxQM2hPNXcyOHl4VXJGNkJXRFFDblY2L0UzMzdPYUtaVEdhWXpWWjgrOVhuZVAzbDUrSDFlRkJVTWlUdjhvczd1RGVPNCtIeisySFE2eUt6WnA0Kzk3aGpqMTNnOS9zUkNBVHpyeUVnSUFLd215SUFBRnUzYnNWbGwxMzIyVFhYWEhNL0FEeDYvOTNJWmpNNDQ0L25ZT1h5bnhDUHhhQlVxM2M4VTQvUFdmMkN3bUpFSW1HOC8vYXIrT2FMeGREcWRMQlliVHQwOXlYTEhBeUZFSW1FY2RvcEozOCtmLzc1WTAxRzQwSi9NQWlPNXdqeENZZ0FERFI0bmtjMEdzVk5OOTEwMzZXWFhub25BTngyL1pWZ0dCbU9QbTQ2dG16YXVNTWFla0VRWUxVN29KQXI4UG1uLzRkWFhud2E2OWY4QXJ2RENaVktEYjVmVnArRDN4L0FzTkxTdHF1dXVIeittV2VjY1paQ0lYZUh3bUZRQUNnUThoTVFBUmo0QzlCMGZzZmRrMDgrK2ZqSko1LzhRb2ZIalZ1dnV4eWpSby9Gc09IRFViRnFCWFJkWnUxSkVNVmN0MTFoVVFuQzRSRGVmZk1mK09hTFQ4Rm1zckE3Q3dDSzZ0NXMxTXYxWTdFWUlwRW9KazgrNm9PcnI3cHl6TGp4NHo3MCtYeElKSkxraUk2QUNNQmdRNm9SYUdob3dQMzMzMy96a0NGRDJqczhidHh5M2VVWU4rRVFhTFJhL0xieDE4NWhubUwrUjI4d3dXSzE0NWRWeS9IU000K2p1bklMaGd3dGcxcXIzZUVKZ3BTSGFHOTNRNnZSNE9TVFRyejB5Q01tWGNqeFhMeWp3MHRpZlFLQ1BTVUFPV3N1SWg2UG82U2tCSTgvL3ZoeE9wMHVzbm5qcjNqbGhhZHg1dXh6RVF6NFVWTmRDYTFXQzBZbWc4UHBSRElSeDcvZWZ4di9mUHNOWkRKcE9KeUZFRHJGWVVkV1B4cUxJUmFMNDlCRERsNTcwMDAzSER0NjFPaDNQQjRQMGhuU2VrdEFJRUcycHk0a0plRnFhMnN4YWRLaytvOCsrdWlRYzg0NVo5T1huMzJpTHl3dXh2a1hYWTUvdnZzR3JGWWJobzhhamUrKy9nSkx2LzhPa1hBWUZyc2RETVBrZS9CM1pQWDlnUUNLaTRyaVo4eWFlZUh3OHZMUGxFb2xhbXZxY3ZjQUNvQkkvdklFQkh2U0EraEswa0FnZ09IRGh6ZmRlZWVkUjlJMEpiejI4dlA0NGJ1dmNmYTU4L0hydWdxOCt1S3pXTHp3WDBobk1yQTZuYUJwdWw5V1A1RklJQkFJWXZpd1lldlBPblBXb1dOR2ovb3NsL1dQRUt0UFFMQ3ZDRUE2blVaSFJ3ZHV1dW1tcWp2dXVQTlNBSGpvbnJzUWlZU2cwK3Z4eGVLUFVWaGMwcThhQWFtVTErUEpMZGU4WVA3NWo1MTU1cXpET1phcjYrandrbkpjQW9KOVNRQzZoZ05OVFUyWU9YUG1lNmVlZXVyZkFlRDZLeS9DaUZGamNkVFU0eEJQeFB0bDlWT3BGS0xSS0NaT25MRG02cXV1T09iRUU2YmZGWThuRUNkTk9BUUUrNllBU0FnR2d6QWFqWGpsbFZldVArcklJMS94ZTcxNDc4MVhVVDU4QkZLcFpKOXJ0eWlLUWtkSEJ6aU93emx6enI3ajZxdXVPTkppc2E2UWxuQVE4aE1RN0JpeXZYcHhtUXgrZjI2eno1dHZ2WFhkVlZkZE5YTGx5cFV6Nm1xck1XUm9LV1J5T2RqT0h2dXVWaitUeWFDanc0dWpqanBpNjJHSEhqcHZXRm5acGtna2luZzhEcVBCUVA2cUJBVDdnd2NBL0c4emprcWx3cjMzM251U1dxMk9SY0loaEVPNVBYcGRXMjlGVVVSSFJ3ZWkwU2hPUG5uR3A5ZGNmZFU0cTlXNnFhMjluV3pSSVNEWUh3VkFJbTFMU3d2R2pCbUQ1NTkvL2dRQWlWWlhDM2lPQThNdytXV2IwV2dVaHg5MjJFOVhYWG5GSDJmLzhheXpFNGtFZ3NFZ2FiMGxJTmhmQmFDcmE5L2MzSXhwMDZhdGZlMjExNllCUUhWVnJqQW9HQXdpRm90aCt2SFRuci9rNG91T0h6RmkrR2NkWGgrWnAwOUE4SHNSQUNBM1NUY1FDT0NNTTg1WWQ5MjExNTRURHZwUlcxdUhzckxTMkp5eloxOXcwTml4dC9qOC90enFMWkJTWGdLQzNZVnNYN29abXFhUnpXWlJWVldGVzI2OTVSTzVVdlhVNXQrMlRyanV1bXN1Y3JzOTNwYVdGbWgxT2tKOEFvTGZvd0FBdWFTZ0lBalFhTFE0YU96WXhSelBielFZRE42NnVucnkxeUlnR0dCUWd6cW5uNENBZ09RQUNBZ0lpQUFRRUJBUUFTQWdJQ0FDUUVCQVFBU0FnSUNBQ0FBQkFRRVJBQUlDQWlJQUJBUUVSQUFJQ0FpSUFCQVFFQkFCSUNBZ0lBSkFRRUJBQklDQWdJQUlBQUVCQVJFQUFnSUNJZ0FFQkFSRUFBZ0lDSWdBRUJBUUVBRWdJQ0FnQWtCQVFFQUVnSUNBZ0FnQUFRRUJFUUFDQWlJQUJBUUVSQUFJQ0FpSUFCQVFFQkFCSUNBZ0lBSkFRRUJBQklDQWdJQUlBQUVCQVJFQUFnSUNJZ0FFQkFSRUFBZ0lDSWdBRUJBUUVBRWdJQ0FnQWtCQVFFQUVnSUNBZ0FnQUFRRUJFUUFDQWdJaUFBUUVCRVFBQ0FnSWlBQVFFQkRzTmZ6L0FESzhiSzFzMHl5WEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMS0xNyIsInVybCI6Imh0dHBzOi8vd3d3LmF4ZWxsLmNvLmpwL2VuLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU0hBTE8gQVVUSCIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMjMwMTE3MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDEtMTcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAxLTI3In0seyJhYWd1aWQiOiIzZjU5NjcyZi0yMGFhLTRhZmUtYjZmNC03ZTVlOTE2YjZkOTgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjNmNTk2NzJmLTIwYWEtNGFmZS1iNmY0LTdlNWU5MTZiNmQ5OCIsImRlc2NyaXB0aW9uIjoiQXJjdWx1cyBGSURPIDIuMSBLZXkgQ2FyZCBbUDcxXSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxMDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDK2pDQ0FxQ2dBd0lCQWdJVVRYSnkyOGxwUVZsaElwN0VUQmkrVTRiY2FEOHdDZ1lJS29aSXpqMEVBd0l3Z1lBeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBPWlhjZ1NtVnljMlY1TVJFd0R3WURWUVFIREFoVGIyMWxjbk5sZERFVU1CSUdBMVVFQ2d3TFEyOXRjRzlUWldOMWNtVXhFREFPQmdOVkJBc01CMEZ5WTNWc2RYTXhJVEFmQmdOVkJBTU1HRU52YlhCdlUyVmpkWEpsTFVaSlJFOHRRMEV0VW05dmREQWdGdzB5TXpBME1UZ3hOVFExTlRCYUdBOHlNRFV6TURReE1ERTFORFUxTUZvd2dZQXhDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJREFwT1pYY2dTbVZ5YzJWNU1SRXdEd1lEVlFRSERBaFRiMjFsY25ObGRERVVNQklHQTFVRUNnd0xRMjl0Y0c5VFpXTjFjbVV4RURBT0JnTlZCQXNNQjBGeVkzVnNkWE14SVRBZkJnTlZCQU1NR0VOdmJYQnZVMlZqZFhKbExVWkpSRTh0UTBFdFVtOXZkREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQ2dHN3I2VkEvaCtCeW5VbnlEWk1EMFZaa1lXNlJHbnBoMHcyNWdRRFdNb3FBYWlVYUZHNU1DbGtoYWtJQnBMRis2eEpCaE8xZ3MrN0Mxay9qdVZ1djJqZ2ZNd2dmQXdIUVlEVlIwT0JCWUVGSnoxZ0Z0VFRCTmZmZkRLdmRqcFVFeXA3MHp0TUlIQUJnTlZIU01FZ2Jnd2diV0FGSnoxZ0Z0VFRCTmZmZkRLdmRqcFVFeXA3MHp0b1lHR3BJR0RNSUdBTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNBd0tUbVYzSUVwbGNuTmxlVEVSTUE4R0ExVUVCd3dJVTI5dFpYSnpaWFF4RkRBU0JnTlZCQW9NQzBOdmJYQnZVMlZqZFhKbE1SQXdEZ1lEVlFRTERBZEJjbU4xYkhWek1TRXdId1lEVlFRRERCaERiMjF3YjFObFkzVnlaUzFHU1VSUExVTkJMVkp2YjNTQ0ZFMXljdHZKYVVGWllTS2V4RXdZdmxPRzNHZy9NQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURTQUF3UlFJZ2NnWEdNRFAycmZoNEVUWTlFSkx3dVhvMVM5VWlxdEVtUGhxOS9kaVMwbkFDSVFEb3lMWm9zeDhyUkFGMXZwUlhjc1ZRRERTSG9Fcy9QYm1GM0VyL21KMHg2dz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBUG9DQVlBQUFCTm85VGtBQUFBQkdkQlRVRUFBTEdQQy94aEJRQUFBQ0JqU0ZKTkFBQjZKZ0FBZ0lRQUFQb0FBQUNBNkFBQWRUQUFBT3BnQUFBNm1BQUFGM0NjdWxFOEFBQUFoR1ZZU1daTlRRQXFBQUFBQ0FBRkFSSUFBd0FBQUFFQUFRQUFBUm9BQlFBQUFBRUFBQUJLQVJzQUJRQUFBQUVBQUFCU0FTZ0FBd0FBQUFFQUFnQUFoMmtBQkFBQUFBRUFBQUJhQUFBQUFBQUFBRWdBQUFBQkFBQUFTQUFBQUFFQUE2QUJBQU1BQUFBQkFBRUFBS0FDQUFRQUFBQUJBQUFENktBREFBUUFBQUFCQUFBRDZBQUFBQURyRWVLa0FBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFDekdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpV0UxUUlFTnZjbVVnTmk0d0xqQWlQZ29nSUNBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBnb2dJQ0FnSUNBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlnb2dJQ0FnSUNBZ0lDQWdJQ0I0Yld4dWN6cDBhV1ptUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzUnBabVl2TVM0d0x5SUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZaWGhwWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOWxlR2xtTHpFdU1DOGlQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFpVbVZ6YjJ4MWRHbHZiajQzTWp3dmRHbG1aanBaVW1WemIyeDFkR2x2Ymo0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2VW1WemIyeDFkR2x2YmxWdWFYUStNand2ZEdsbVpqcFNaWE52YkhWMGFXOXVWVzVwZEQ0S0lDQWdJQ0FnSUNBZ1BIUnBabVk2V0ZKbGMyOXNkWFJwYjI0K056SThMM1JwWm1ZNldGSmxjMjlzZFhScGIyNCtDaUFnSUNBZ0lDQWdJRHgwYVdabU9rOXlhV1Z1ZEdGMGFXOXVQakU4TDNScFptWTZUM0pwWlc1MFlYUnBiMjQrQ2lBZ0lDQWdJQ0FnSUR4bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNHpNREF3UEM5bGVHbG1PbEJwZUdWc1dFUnBiV1Z1YzJsdmJqNEtJQ0FnSUNBZ0lDQWdQR1Y0YVdZNlEyOXNiM0pUY0dGalpUNHhQQzlsZUdsbU9rTnZiRzl5VTNCaFkyVStDaUFnSUNBZ0lDQWdJRHhsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0ek1EQXdQQzlsZUdsbU9sQnBlR1ZzV1VScGJXVnVjMmx2Ymo0S0lDQWdJQ0FnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrQ2lBZ0lEd3ZjbVJtT2xKRVJqNEtQQzk0T25odGNHMWxkR0UrQ2w5RUszOEFBRUFBU1VSQlZIZ0I3TjEvakdWWlFoLzJlKzZyN3BucDM5VmRQVDFkVmQwenV3d0x3OWlFMFB4WTJ5UnVTSVJETExCajVNZ0VRZ3c0L2lHd0hBS0pJNXdmc21YRmltVWxWbUpIU3BSRVRraWtTTEVpNWE5RWltTkdPSkVjZG9kZGtOZHIwQUpEZGp6czdBNHNDN3N6MDEzMTdzazU1NzdxcWY1ZFZlL1gvZkY1VUYydjNydjMzSE0rcDdhcXZuUE9QYWVxUEFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0FBQUVDQkFnUUlFQ0F3SW9Fd29xdTR6SUVDQkFnUUlCQXZ3WHkzd3oxckFreGZXNzYzUnkxSjBDQUFBRUNCQWdRSUVDQUFBRUMvUlB3SC9UNzEyZHFUSUFBQVFJOUZQQUx0NGVkcHNvRUNCQWdRR0NGQW5uVXZIbit4bzJ2bWpiTlg2cENlQ2I5OGZETDc3ejU1bDllWVIxY2lnQUJBZ1FJakVKZ1l4U3QxRWdDQkFnUUlFRGdwQUlsb08rSDZZZnJ5ZVNIUWdoVjA4UlBwY0lFOUpPS09vOEFBUUlFQ0R4R1FFQi9ESXlYQ1JBZ1FJQUFnUThFNmpqWmlyR3A4czNuSWRTLy9jRTduaEVnUUlBQUFRS0xFamhZN0dWUjVTbUhBQUVDQkFnUUdLQkFVelhYOCtoNVN1ZXBkZEYvNEI5Z0gyc1NBUUlFQ0t4ZlFFQmZmeCtvQVFFQ0JBZ1E2THhBSGNMRk5weDN2cW9xU0lBQUFRSUVlaXNnb1BlMjYxU2NBQUVDQkFpc1RpRE5icjlZeFR6QjNZTUFBUUlFQ0JCWWxvQ0F2aXhaNVJJZ1FJQUFnV0VJbFAzT1E0alhodEVjclNCQWdBQUJBdDBWRU5DNzJ6ZHFSb0FBQVFJRXVpQlFoczNUNFBrTFhhaU1PaEFnUUlBQWdTRUxDT2hEN2wxdEkwQ0FBQUVDOHd2a2dKNXVRUS9ueXdydTg1ZW5CQUlFQ0JBZ1FPQXhBZ0w2WTJDOFRJQUFBUUlFQ0ZSNXlmWnFkM2YzbVJqak9mZWcrNDRnUUlBQUFRTExGUkRRbCt1cmRBSUVDQkFnMEdlQkV0RHZiR3lrRmR5clMzMXVpTG9USUVDQUFJRStDQWpvZmVnbGRTUkFnQUFCQW1zVWFPS2R6U3FXZ0c0Wjl6WDJnMHNUSUVDQXdQQUZCUFRoOTdFV0VpQkFnQUNCa3dxVUVmU3EyVGlYOWtBL25hYTRseFhkVDFxWTh3Z1FJRUNBQUlFbkN3am9UL2J4TGdFQ0JBZ1FHTE5BRzlEcjVueDZFbUlJQXZxWXZ4dTBuUUFCQWdTV0xpQ2dMNTNZQlFnUUlFQ0FRTDhGUW5OdkQzUlQzUHZkbFdwUGdBQUJBaDBYRU5BNzNrR3FSNEFBQVFJRTFpM1FWT0Y2bXVLZWwzUVgwTmZkR2E1UGdBQUJBb01XRU5BSDNiMGFSNEFBQVFJRTVoZEltNkJmbkw4VUpSQWdRSUFBQVFKUEV4RFFueWJrZlFJRUNCQWdNSEtCdERTY2dEN3k3d0hOSjBDQUFJSFZDQWpvcTNGMkZRSUVDQkFnMERlQnZFQmNXUlF1aEh2M29QZXREZXBMZ0FBQkFnUjZKU0NnOTZxN1ZKWUFBUUlFQ0t4VW9BVDBHS3NYMGhacks3MndpeEVnUUlBQWdURUtDT2hqN0hWdEprQ0FBQUVDUnhlWWhCRE81OE5UUkcrM1hUdjZ1WTRrUUlBQUFRSUVqaUVnb0I4RHk2RUVDQkFnUUdCRUFpV003Kzd1bm80eG5oMVJ1eldWQUFFQ0JBaXNUVUJBWHh1OUN4TWdRSUFBZ2U0THZEK1pYRXBickYyYXpYQTNndDc5TGxOREFnUUlFT2l4Z0lEZTQ4NVRkUUlFQ0JBZ3NFU0JFc2FiZUdjejNYK2VWbkdQNXJjdkVWdlJCQWdRSUVBZ0N3am92ZzhJRUNCQWdBQ0J4d3FFWnVOY2V2T1pja0NNUnRBZksrVU5BZ1FJRUNBd3Y0Q0FQcitoRWdnUUlFQ0F3R0FGWWwxZlRJdkU1YjhYckJFMzJGN1dNQUlFQ0JEb2lvQ0EzcFdlVUE4Q0JBZ1FJTkF0Z1RKYUhwcm0ycXhhOWxuclZ2K29EUUVDQkFnTVVFQkFIMkNuYWhJQkFnUUlFRmlVUUF6eFdsb2tMbytmTitrbWRGUGNGd1dySEFJRUNCQWc4QWdCQWYwUktGNGlRSUFBQVFJRVdvRzZxdE1DY2ZsaEFMMTE4QzhCQWdRSUVGaWVnSUMrUEZzbEV5QkFnQUNCM2d1a0VmUkx2VytFQmhBZ1FJQUFnWjRJQ09nOTZTalZKRUNBQUFFQ0t4Wm84dlZDVEZQY3k4UHM5dGJCdndRSUVDQkFZSGtDQXZyeWJKVk1nQUFCQWdUNkxGRG10RGN4dnBEMlFVOUozZjNuZmU1TWRTZEFnQUNCZmdnSTZQM29KN1VrUUlBQUFRS3JGc2dCZlZLSFNkNEgzWU1BQVFJRUNCQllnWUNBdmdKa2x5QkFnQUFCQWowVEtQUFp0N2UzbjBtajUrZG55OE9aNDk2elRsUmRBZ1FJRU9pZmdJRGV2ejVUWXdJRUNCQWdzR3lCRXNidlRpYVhZaFV2bGludWVaSzdCd0VDQkFnUUlMQlVBUUY5cWJ3S0owQ0FBQUVDL1JWb1FzZ3J1TSsyV2V0dk85U2NBQUVDQkFqMFJVQkE3MHRQcVNjQkFnUUlFRmlkUUJrdEQwMXpyZ3JoOU95eVJ0Qlg1KzlLQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0JBNEFrQ2JSaXZtd3ZwU1g1ZXRseDd3dkhlSWtDQUFBRUNCQllnSUtBdkFGRVJCQWdRSUVCZ2lBS2hxV2Q3b0ZlemRlS0cyRXB0SWtDQUFBRUMzUkVRMEx2VEYycENnQUFCQWdRNkpkQ0V0QWQ2U0FQb2FhVzRUbFZNWlFnUUlFQ0F3RUFGQlBTQmRxeG1FU0JBZ0FDQmVRWHFxcDR0RUNlZnoydnBmQUlFQ0JBZ2NCUUJBZjBvU280aFFJQUFBUUxqRWlpSlBNYVlWM0gzSUVDQUFBRUNCRllrSUtDdkNOcGxDQkFnUUlCQVR3VHlvbkFsb0ljUVovZWc1NWM4Q0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFQ0JEb24wQlp0YjJKNlI3MGFIcDcvN3BQalFrUUlFQ2dyd0lDZWw5N1RyMEpFQ0JBZ01CU0JmNzRwQTZUcytVU29XeTF0dFNyS1p3QUFRSUVDQkNvS2dIZGR3RUJBZ1FJRUNCd1dLRE1aNzkyN1dlZmpiRTViL3o4TUkzbkJBZ1FJRUJndVFJQytuSjlsVTZBQUFFQ0JIb3BNRDE5K21JYU43ODRtK0x1SnZSZTlxSktFeUJBZ0VEZkJBVDB2dldZK2hJZ1FJQUFnZVVLbERBK3JhckxhYWs0cTdndjExcnBCQWdRSUVEZ1BnRUIvVDRPWHhBZ1FJQUFBUUpab0o3RXMxVUlwMmNhUnRCOVd4QWdRSUFBZ1JVSUNPZ3JRSFlKQWdRSUVDRFFONEU0RFJkVEtzL0IzRzNvZmVzODlTVkFnQUNCM2dvSTZMM3RPaFVuUUlBQUFRSkxFU2lqNWFGcFhwaVZYclpjVzhxVkZFcUFBQUVDQkFqY0p5Q2czOGZoQ3dJRUNCQWdRQ0FMaEJDdnBYL3krSGtlUVMraG5Rd0JBZ1FJRUNDd1hBRUJmYm0rU2lkQWdBQUJBcjBVaUdGeW9hMjRHZTY5N0VDVkprQ0FBSUZlQ2dqb3ZldzJsU1pBZ0FBQkFzc1dpRlp3WHpheDhna1FJRUNBd0FNQ0F2b0RJTDRrUUlBQUFRSWpGMmp2T1kveDRCNzBrWE5vUGdFQ0JBZ1FXSjJBZ0w0NmExY2lRSUFBQVFKOUVDaHoybU1WcmxYUjdlZDk2REIxSkVDQUFJSGhDQWpvdytsTExTRkFnQUFCQW9zUXlLbDhVdGZWdVZKWXNFRGNJbENWUVlBQUFRSUVqaUlnb0I5RnlURUVDQkFnUUdBY0FtVzE5bXZYcmoyYjFtNC9OMXNlemdydTQraDdyU1JBZ0FDQkRnZ0k2QjNvQkZVZ1FJQUFBUUlkRVNoaGZQL1VxVXRwZXZ0bU84WGRDSHBIK2tZMUNCQWdRR0FFQWdMNkNEcFpFd2tRSUVDQXdCRUZTa0J2UXRoTUs4WE50bGs3NHBrT0kwQ0FBQUVDQk9ZV0VORG5KbFFBQVFJRUNCQVlsa0FkNDlrUXd1bFpxMHh4SDFiM2FnMEJBZ1FJZEZoQVFPOXc1NmdhQVFJRUNCQllzVUFKNDdHdUw4eFNlYnZsMm9vcjRYSUVDQkFnUUdDc0FnTDZXSHRldXdrUUlFQ0F3R01Fd25SNmZmYldiSjI0eHh6b1pRSUVDQkFnUUdDaEFnTDZRamtWUm9BQUFRSUUraThRUXJ4V2hUU0dIc3RHNlAxdmtCWVFJRUNBQUlHZUNBam9QZWtvMVNSQWdBQUJBcXNTaUdGaWdiaFZZYnNPQVFJRUNCQTRKQ0NnSDhMd2xBQUJBZ1FJakZ4Z05xVTliYkhtUVlBQUFRSUVDS3hjUUVCZk9ia0xFaUJBZ0FDQlRncmtkZUhhZ0I3VEZQZnliTFpVWENlcnExSUVDQkFnUUdCNEFnTDY4UHBVaXdnUUlFQ0F3RWtGeXFydHNRclhEckw2U1F0eUhnRUNCQWdRSUhCOEFRSDkrR2JPSUVDQUFBRUNReGFZMUNHY0xRME1sU0gwSWZlMHRoRWdRSUJBNXdRRTlNNTFpUW9SSUVDQUFJRzFDSlF3ZnZYcTFlZlM2dTNuN0srMmxqNXdVUUlFQ0JBWXVZQ0FQdkp2QU0wblFJQUFBUUtIQmFhblRxVUY0dUxsRk5MenkwYlFEK040VG9BQUFRSUVsaXdnb0M4WldQRUVDQkFnUUtBbkFpV014N3ErbEtLNWJkWjYwbW1xU1lBQUFRTERFaERRaDlXZldrT0FBQUVDQk9ZU0NCdnhiQlhDcVZraFJ0RG4wblF5QVFJRUNCQTRub0NBZmp3dlJ4TWdRSUFBZ2FFS3RHRjhXbDlNVC9KenQ2RVB0YWUxaXdBQkFnUTZLeUNnZDdaclZJd0FBUUlFQ0t4ZUlEVE45ZGxWODVaclJ0Qlgzd1d1U0lBQUFRSWpGaERRUjl6NW1rNkFBQUVDQkI0U0NPSDVOTVU5alorM3E4UTk5TDRYQ0JBZ1FJQUFnYVVKQ09oTG8xVXdBUUlFQ0JEb29VQUlGb2pyWWJlcE1nRUNCQWdNUTBCQUgwWS9hZ1VCQWdRSUVGaVFRSk8yV2ZNZ1FJQUFBUUlFMWlHd3NZNkx1aVlCQWdRSUVDRFFPWUY4ejNtYTJoNE83a0h2WEFWVmlBQUJBZ1FJREYzQUNQclFlMWo3Q0JBZ1FJREEwUVRLcXUwaHhxdnRBdTdXaHpzYW02TUlFQ0JBZ01EaUJBVDB4VmtxaVFBQkFnUUk5RmtnQi9SSk5Rbm5TaU9DRmR6NzNKbnFUb0FBQVFMOUZCRFErOWx2YWsyQUFBRUNCQllwVUliTHIxNjkrbHpWVk9kbkc2QWJRbCtrc0xJSUVDQkFnTUFSQkFUMEl5QTVoQUFCQWdRSURGeWdoUEhwcVZPYnNZcVgwaFpydWJrQytzQTdYZk1JRUNCQW9Ic0NBbnIzK2tTTkNCQWdRSURBcWdWS0dJOTFmU25sY3R1c3JWcmY5UWdRSUVDQXdFeEFRUGV0UUlBQUFRSUVDQlNCOUVmQm1UUnVmaXA5a1lmUWphRDd2aUJBZ0FBQkFpc1dFTkJYRE81eUJBZ1FJRUNnZ3dMdENIb0lsMmFwZkhZYmVnZHJxa29FQ0JBZ1FHREFBZ0w2Z0R0WDB3Z1FJRUNBd0hFRVF0TWM3SUV1b0I4SHpyRUVDQkFnUUdCQkFnTDZnaUFWUTRBQUFRSUVlaThRd3ZOVlNHUG9zVjBscnZmdDBRQUNCQWdRSU5BekFRRzlaeDJtdWdRSUVDQkFZR2tDd1FKeFM3TlZNQUVDQkFnUU9JS0FnSDRFSkljUUlFQ0FBSUdCQzh5bXREZWJBMituNWhFZ1FJQUFnVTRMYkhTNmRpcEhnQUFCQWdRSUxGc2dyd3ZYbEl2RWtPNUJ0NEQ3c3NHVlQ0QUFBUUlFSGlkZ0JQMXhNbDRuUUlBQUFRTGpFU2dqNkNIR3ErTnBzcFlTSUVDQUFJSHVDUWpvM2VzVE5TSkFnQUFCQXVzUTJLZ200V3k1Y0xBSCtqbzZ3RFVKRUNCQWdJQ0E3bnVBQUFFQ0JBaU1XNkJzZmI2MXRmVmNtdWgrM3Y1cTQvNW0wSG9DQkFnUVdLK0FnTDVlZjFjblFJQUFBUUtkRU5nL2RlcHlyT0ptMm1JdDE2ZUU5azVVVENVSUVDQkFnTUNJQkFUMEVYVzJwaElnUUlBQWdVY0lsREFlSnBPTGFRLzBDNDk0MzBzRUNCQWdRSURBaWdRRTlCVkJ1d3dCQWdRSUVPaXlRSmpFZlAvNXFWa2RqYUIzdWJQVWpRQUJBZ1FHS3lDZ0Q3WnJOWXdBQVFJRUNCeEpvSVR4eVRSY21xVnl0NkVmaWMxQkJBZ1FJRUJnOFFJQyt1Sk5sVWlBQUFFQ0JIb25NQTFOMmdPOVBQS2U2RWJRWnhnK0VTQkFnQUNCVlFvSTZLdlVkaTBDQkFnUUlOQlJnUkRycStrZTlDb3RFbWNFdmFOOXBGb0VDQkFnTUh3QkFYMzRmYXlGQkFnUUlFRGc2UUlXaUh1NmtTTUlFQ0JBZ01DU0JRVDBKUU1ybmdBQkFnUUlkRnhnTm1MZVhPNTRQVldQQUFFQ0JBZ01YbUJqOEMzVVFBSUVDQkFnUU9CSkFtMUFqekhkZzI1Mis1T2d2RWVBQUFFQ0JKWXRZQVI5MmNMS0owQ0FBQUVDM1JZb3FUeUVzTlZXTTkrSTdrR0FBQUVDQkFpc1EwQkFYNGU2YXhJZ1FJQUFnZTRJNUlBK1NRdkU1WDNRcmQ5ZUVQeERnQUFCQWdUV0l5Q2dyOGZkVlFrUUlFQ0FRQmNFeW1qNTF0YldtVFM3L2NKc2dyc1I5QzcwakRvUUlFQ0F3Q2dGQlBSUmRydEdFeUJBZ0FDQklsREMrUFQwNmMyMHU5cG0ybUl0dnlpZysrWWdRSUFBQVFKckVoRFExd1R2c2dRSUVDQkFvQU1DYlJpdjYwdXBMdWM3VUI5VklFQ0FBQUVDb3hZUTBFZmQvUnBQZ0FBQkFnVFNrUGxHUEpQdVFjODd1K1FoZENQb3Zpa0lFQ0JBZ01DYUJBVDBOY0c3TEFFQ0JBZ1E2SUJBQ2VPVC9iQTVTK1d6MjlBN1VETlZJRUNBQUFFQ0l4UVEwRWZZNlpwTWdBQUJBZ1FPQzB4RGsvWkFUNDlvSS9URExwNFRJRUNBQUlGVkN3am9xeFozUFFJRUNCQWcwREdCRU92bjB4VDNWS3QybGJpT1ZVOTFDQkFnUUlEQWFBUUU5TkYwdFlZU0lFQ0FBSUhIQ0lSZ2diakgwSGlaQUFFQ0JBaXNVa0JBWDZXMmF4RWdRSUFBZ1c0SnpQWlZheTUzcTFwcVE0QUFBUUlFeGlrZ29JK3ozN1dhQUFFQ0JBamtPZTFOWmtoN29GOXZaN2ZQbG9walE0QUFBUUlFQ0t4RlFFQmZDN3VMRWlCQWdBQ0JUZ2kwSStnaGJKWGF5T2VkNkJTVklFQ0FBSUh4Q2dqbzQrMTdMU2RBZ0FBQkFsVjF1OXBJQzhTZG5WR0k2TDRuQ0JBZ1FJREFHZ1VFOURYaXV6UUJBZ1FJRUZpalFBbmptNy93NGJOcGM3VUxOa0JmWTArNE5BRUNCQWdRbUFrSTZMNFZDQkFnUUlEQWlBV2FDMSs1bk81QjM1enRzR1lFZmNUZkM1cE9nQUFCQXVzWEVORFgzd2RxUUlBQUFRSUUxaUZRd3Zneit4c1gwaFQzYyt1b2dHc1NJRUNBQUFFQzl3c0k2UGQ3K0lvQUFRSUVDSXhMWUdNajMzOSthdFpvSStqajZuMnRKVUNBQUlHT0NRam9IZXNRMVNGQWdBQUJBaXNTS0dHODJkL2ZuS1Z5dDZHdkNONWxDQkFnUUlEQTR3UUU5TWZKZUowQUFRSUVDSXhBb0FuaCtxeVplVTkwSStnajZITk5KRUNBQUlIdUNnam8zZTBiTlNOQWdBQUJBa3NYQ0hXOG11NUJyOUlpY1ViUWw2N3RBZ1FJRUNCQTRNa0NBdnFUZmJ4TGdBQUJBZ1NHTFJEcjg4TnVvTllSSUVDQUFJSCtDQWpvL2Vrck5TVkFnQUFCQW9zVUtDUG1JY1lyaXl4VVdRUUlFQ0JBZ01ESkJRVDBrOXM1a3dBQkFnUUk5Rm1nQlBRWTR2WFpIdWg5Ym91NkV5QkFnQUNCUVFnSTZJUG9SbzBnUUlBQUFRTEhGbWp2T1kvVlZudG12aEhkZ3dBQkFnUUlFRmluZ0lDK1RuM1hKa0NBQUFFQzZ4T0kxZTFxSTRSd3BsUkJQRjlmVDdneUFRSUVDQkNZQ1Fqb3ZoVUlFQ0JBZ01ENEJFb2N2L3lMTCtkd2ZtRzJmTHVJUHI3dkF5MG1RSUFBZ1k0SkNPZ2Q2eERWSVVDQUFBRUNLeEFvWWJ5NThPWExhWGUxemRrOTZBTDZDdUJkZ2dBQkFnUUlQRWxBUUgrU2p2Y0lFQ0JBZ01Bd0JVb1lEL3NiRjFMenpnMnppVnBGZ0FBQkFnVDZKeUNnOTYvUDFKZ0FBUUlFQ0N4RTROUmtjcTRLWVNNVmxtZTVHMEZmaUtwQ0NCQWdRSURBeVFVRTlKUGJPWk1BQVFJRUNQUlZvSjNpdnIrL09VdmxzOXZRKzlvYzlTWkFnQUFCQXNNUUVOQ0gwWTlhUVlBQUFRSUVqaTNRaEhDOW5CVExDUHF4ejNjQ0FRSUVDQkFnc0ZnQkFYMnhua29qUUlBQUFRSzlFUWgxdkpxbXVLZjZSaVBvdmVrMUZTVkFnQUNCSVFzSTZFUHVYVzBqUUlBQUFRSlBFbWhDWGlUT2d3QUJBZ1FJRU9pSWdJRGVrWTVRRFFJRUNCQWdzRUtCTW1LZXhzNHZyL0NhTGtXQUFBRUNCQWc4UlVCQWZ3cVF0d2tRSUVDQXdNQUU4cHoySnJjcGhuaTluZDArV3lwdVlBM1ZIQUlFQ0JBZzBEY0JBYjF2UGFhK0JBZ1FJRUJnZm9IMm52TllYU2xGQlZ1c3pVK3FCQUlFQ0JBZ01MK0FnRDYvb1JJSUVDQkFnRUQvQkc3ZE9oVkNPTmUvaXFzeEFRSUVDQkFZcm9DQVB0eSsxVElDQkFnUUlQQW9nVEtmL2VJWHZwREQrWG5MdHorS3lHc0VDQkFnUUdBOUFodnJ1YXlyRWlCQWdBQUJBbXNTT0xqaGZEUEd1RG1ydzhGcmE2cVN5eElnUUlBQUFRSlp3QWk2N3dNQ0JBZ1FJREJDZ2RQMU5HK3hab3I3Q1B0ZWt3a1FJRUNndXdJQ2VuZjdSczBJRUNCQWdNRFNCRUl6T1Z1RmNEQ1R6Z2o2MHFRVlRJQUFBUUlFamk0Z29CL2R5cEVFQ0JBZ1FHQUlBaVdNTjlYKzVWa3FkeHY2RUhwVkd3Z1FJRUJnRUFJQytpQzZVU01JRUNCQWdNQXhCWnI2K3V5TXZDZTZFZlJqOGptY0FBRUNCQWdzUTBCQVg0YXFNZ2tRSUVDQVFNY0ZZb2hiYVlwN1ZhV1Y0anBlVmRValFJQUFBUUtqRVJEUVI5UFZHa3FBQUFFQ0JBNEpoSEQrMEZlZUVpQkFnQUFCQWgwUUVOQTcwQW1xUUlBQUFRSUVWaWhRUnN4RFUyMnQ4Sm91UllBQUFRSUVDQnhCUUVBL0FwSkRDQkFnUUlEQWdBUktRRytxZUQxTmJ4OVFzelNGQUFFQ0JBajBYMEJBNzM4ZmFnRUJBZ1FJRURpT1FGNFVMcTBLRjY2MEorVWIwVDBJRUNCQWdBQ0JMZ2dJNkYzb0JYVWdRSUFBQVFLckVUZ0k0eHNwbHA4cGx6eDRaVFhYZHhVQ0JBZ1FJRURnQ1FJQytoTnd2RVdBQUFFQ0JJWW9jT21sbDg3RktsNllUWEFYMFlmWXlkcEVnQUFCQXIwVUVOQjcyVzBxVFlBQUFRSUVUaVJRd25pTTcyMVdNYVNQZHIyNEU1WGtKQUlFQ0JBZ1FHRGhBZ0w2d2trVlNJQUFBUUlFT2l0UUF2cnBzSEV4YllCK3JyTzFWREVDQkFnUUlEQlNBUUY5cEIydjJRUUlFQ0F3WG9FUU44NVVJVXlTUUI1Q044Vjl2TjhLV2s2QUFBRUNIUk1RMER2V0lhcERnQUFCQWdTV0tGRENlQlAzcnN4U3VYM1dsb2l0YUFJRUNCQWdjRndCQWYyNFlvNG5RSUFBQVFKOUYyanE2NlVKc1NwYnJ2VzlPZXBQZ0FBQkFnU0dJaUNnRDZVbnRZTUFBUUlFQ0J4UklJYTRsYWE0cDZNTm9CK1J6R0VFQ0JBZ1FHQWxBZ0w2U3BoZGhBQUJBZ1FJZEVlZ0R1RjhkMnFqSmdRSUVDQkFnTUNCZ0lCK0lPRXpBUUlFQ0JBWXZrQVpNbzlOdFRYOHBtb2hBUUlFQ0JEb240Q0EzcjgrVTJNQ0JBZ1FJSEFTZ1R5bnZkeHozbFR4ZXJzSCtteXB1Sk9VNWh3Q0JBZ1FJRUJnNFFJQytzSkpGVWlBQUFFQ0JEb3JVTFpWQzFXNFVtcVlublMycGlwR2dBQUJBZ1JHS0NDZ2o3RFROWmtBQVFJRVJpeHc2OVpHV2gvdXpJZ0ZOSjBBQVFJRUNIUldRRUR2Yk5lb0dBRUNCQWdRV0toQUdTMi84UGJiNTJPTUY2M2Z2bEJiaFJFZ1FJQUFnWVVJQ09nTFlWUUlBUUlFQ0JEb3ZFQUo2TStHc0ptMlY5dHM3MEUzeGIzenZhYUNCQWdRSURBcUFRRjlWTjJ0c1FRSUVDQXdkb0ZZMXhlcUtwamlQdlp2Qk8wblFJQUFnVTRLQ09pZDdCYVZJa0NBQUFFQ3l4RUlNWjZwUXRpWWxXNlJ1T1V3SzVVQUFRSUVDSnhJUUVBL0VadVRDQkFnUUlCQTd3UktHSi9HdURWTDVXWEx0ZDYxUW9VSkVDQkFnTUNBQlFUMEFYZXVwaEVnUUlBQWdRY0ZRdE5jbjcxV3RseDc4SDFmRXlCQWdBQUJBdXNURU5EWForL0tCQWdRSUVCZzVRTHBIdlFyYVlwN1dpY3VXc2g5NWZvdVNJQUFBUUlFbml3Z29EL1p4N3NFQ0JBZ1FHQlFBbldJNXdmVklJMGhRSUFBQVFJREVoRFFCOVNabWtLQUFBRUNCSjRnVUViTW02YTYrb1JqdkVXQUFBRUNCQWlzVWVCZ0ZkYzFWc0dsQ1JBZ1FJQUFnUlVJbElBZXFuaTltajFid1RWZGdnQUJBZ1FJRURpR2dCSDBZMkE1bEFBQkFnUUk5Rmlnck5vZXEzQzV0Q0ZVdGxqcmNXZXFPZ0VDQkFnTVUwQkFIMmEvYWhVQkFnUUlFRGdzTUF2anR6ZFNMRDl6K0EzUENSQWdRSUFBZ2U0SUNPamQ2UXMxSVVDQUFBRUNTeFc0ZVBOWHo2ZlYyeS9PMW04M2dyNVViWVVUSUVDQUFJSGpDd2pveHpkekJnRUNCQWdRNkp2QVFSamZUUGVmYjZZOTFuTDlEMTdyVzF2VWx3QUJBZ1FJREZaQVFCOXMxMm9ZQVFJRUNCQzRKMURDK09tNnZtQ0srejBUVHdnUUlFQ0FRT2NFQlBUT2RZa0tFU0JBZ0FDQjVRaUVwamxiaFRCSnBlY2hkQ1BveTJGV0tnRUNCQWdRT0xHQWdINWlPaWNTSUVDQUFJSGVDSlF3UG8zN1c3TlVYdWE0OTZiMktrcUFBQUVDQkVZaUlLQ1BwS00xa3dBQkFnUUloQ1pjTHdxeEtsdXVFU0ZBZ0FBQkFnUzZKU0NnZDZzLzFJWUFBUUlFQ0N4TklOYjFsVFRGUFpWdkFIMXB5QW9tUUlBQUFRSnpDQWpvYytBNWxRQUJBZ1FJOUVtZ0R2RjhuK3FycmdRSUVDQkFZR3dDQXZyWWVseDdDUkFnUUdDTUFtWEl2R21xcXdiUHg5ajkya3lBQUFFQ2ZSSFk2RXRGMVpNQUFRSUVDQkE0a1VDZTAxN3VPUTlWYk85QnQ0RDdpU0NkUklBQUFRSUVsaTFnQkgzWndzb25RSUFBQVFMckZ5amJxc1VRTHBlcUJBbDkvVjJpQmdRSUVDQkE0R0VCQWYxaEU2OFFJRUNBQUlFaENaU2QxVjU5OWRWVHFWRm5odFF3YlNGQWdBQUJBa01URU5DSDFxUGFRNEFBQVFJRUhpSHcvMzN4aXhlcUdDOWF2LzBST0Y0aVFJQUFBUUlkRVJEUU85SVJxa0dBQUFFQ0JKWWtVRWJRbjYzclMybUJ1TTBVMHZObHltdEx1cDVpQ1JBZ1FJQUFnUk1LQ09nbmhITWFBUUlFQ0JEb2swQ2NUQzZrV0c2S2U1ODZUVjBKRUNCQVlIUUNBdnJvdWx5RENSQWdRR0NNQXFGcHpsWWhUR1p0TjRJK3htOENiU1pBZ0FDQnpnc0k2SjN2SWhVa1FJQUFBUUp6Q1pRdzNzUzROVXZsWmN1MXVVcDBNZ0VDQkFnUUlMQVVBUUY5S2F3S0pVQ0FBQUVDSFJOb210a2U2T2xPZFBlZ2Q2eHpWSWNBQVFJRUNMUUNBcnJ2QkFJRUNCQWdNQUtCZWpLNW5LYTRWMm1ST0F1NWo2Qy9OWkVBQVFJRStpa2dvUGV6MzlTYUFBRUNCQWdjU3lDR2VQNVlKemlZQUFFQ0JBZ1FXTG1BZ0w1eWNoY2tRSUFBQVFJckZTZ2o1bW5nL1BtVlh0WEZDQkFnUUlBQWdXTUxiQno3RENjUUlFQ0FBQUVDZlJKb3A3VEhtTzVCZC90NW56cE9YUWtRSUVCZ2ZBSkcwTWZYNTFwTWdBQUJBdU1TYUZkdEQvVm1hWFpJdTZGN0VDQkFnQUFCQXAwVUVOQTcyUzBxUllBQUFRSUVGaUxRaHZGYnQwNmwwczRzcEVTRkVDQkFnQUFCQWtzVE1NVjlhYlFLSmtDQUFBRUMzUkE0LzduUFhVamo1aGRqRzllTm9IZWpXOVNDQUFFQ0JBZzhKR0FFL1NFU0x4QWdRSUFBZ2NFSWxERCtiQWliNmZiei9KRWZBdnBndWxkRENCQWdRR0JvQWdMNjBIcFVld2dRSUVDQXdBY0NiUmlmTk9kVExEZkYvUU1YendnUUlFQ0FRQ2NGQlBST2RvdEtFU0JBZ0FDQkJRckVqYk5WQ1BsM3ZtWGNGOGlxS0FJRUNCQWdzR2dCQVgzUm9zb2pRSUFBQVFMZEVTZ2o2RTNUWEozTmEyOG51WGVuZm1wQ2dBQUJBZ1FJSEJJUTBBOWhlRXFBQUFFQ0JBWXBFSnEwQjNwNnhLcmRjbTJRamRRb0FnUUlFQ0RRZndFQnZmOTlxQVVFQ0JBZ1FPQ0pBckdhWEVsVDNOTXhCdENmQ09WTkFnUUlFQ0N3WmdFQmZjMGQ0UElFQ0JBZ1FHRFpBbldJNTVaOURlVVRJRUNBQUFFQzh3c0k2UE1iS29FQUFRSUVDSFJWb0V4cGp6RSszMVp3ZGlkNlYydXJYZ1FJRUNCQVlPUUNBdnJJdndFMG53QUJBZ1FHSy9EQm5QYW0ycW1pNmUyRDdXa05JMENBQUlIQkNBam9nK2xLRFNGQWdBQUJBZzhKdE51cTFlRmllU2VrM2RBOUNCQWdRSUFBZ2M0S0NPaWQ3Um9WSTBDQUFBRUNjd20wWWZ6bGwwK25VczdPVlpLVENSQWdRSUFBZ1pVSUNPZ3JZWFlSQWdRSUVDQ3dIb0Z6WC83eWhUUzkvZUpzZ3JzUjlQVjBnNnNTSUVDQUFJRWpDUWpvUjJKeUVBRUNCQWdRNkoxQUNlUFBUaWFicWVhWDNJUGV1LzVUWVFJRUNCQVlvWUNBUHNKTzEyUUNCQWdRR0pIQVpISSt0ZmE1RWJWWVV3a1FJRUNBUUc4RkJQVGVkcDJLRXlCQWdBQ0Jwd3VFR005V0lVeG1SNXJpL25ReVJ4QWdRSUFBZ2JVSkNPaHJvM2RoQWdRSUVDQ3dWSUVTeHFjeFhwMmw4ckluK2xLdnFIQUNCQWdRSUVCZ0xnRUJmUzQrSnhNZ1FJQUFnVzRMaEtxNVhtb1lxeHpRamFCM3U3dlVqZ0FCQWdSR0xpQ2dqL3diUVBNSkVDQkFZTmdDYVhiN1pwcmluaG81VzhkOTJNM1ZPZ0lFQ0JBZzBHc0JBYjNYM2FmeUJBZ1FJRURnYVFMeHd0T084RDRCQWdRSUVDRFFEUUVCdlJ2OW9CWUVDQkFnUUdEUkFtWElQRmJ4K1VVWHJEd0NCQWdRSUVCZ09RSUMrbkpjbFVxQUFBRUNCTll0MEM0SzExVFgyejNRM1g2KzdnNXhmUUlFQ0JBZzhEUUJBZjFwUXQ0blFJQUFBUUw5Rkdodk9xL0R4Vkw5WUlHNGZuYWpXaE1nUUlEQW1BUUU5REgxdHJZU0lFQ0F3RmdFMnVIeVYxODluUnA4ZGl5TjFrNENCQWdRSU5CM0FRRzk3ejJvL2dRSUVDQkE0REVDNTcvNHhRdHBldnVsMkk2bG0rUCtHQ2N2RXlCQWdBQ0JyZ2dJNkYzcENmVWdRSUFBQVFLTEV5aGgvTm02M2t4RlhwcHRzU2FnTDg1WFNRUUlFQ0JBWUNrQ0F2cFNXQlZLZ0FBQkFnVFdKcENEZVBuOUhrTzUvL3k1V1UwRTlMVjFpUXNUSUVDQUFJR2pDUWpvUjNOeUZBRUNCQWdRNktMQVFSaWZWTGR2YjZRS1RtYVZuT2JQTWNaSkZVTCtYZDlPY3ArOTZSTUJBZ1FJRUNEUVRZSDh5OXlEQUFFQ0JBZ1E2TDdBUVJnL0dBblBvVHNIOFRaOHYvYmF2UlpzYjIrZitkMFFuZ3NoL29FcUxkNmVEc2pISEp4Mzd6aFBDQkFnUUlBQWdXNEpDT2pkNmcrMUlVQ0FBQUVDQndKdElMK2RndlZySldEbk1GNUd4ZzhPU0o5UFhYcnBoWjJOdmNtSFlsMTliVHJocTFNT2YrVk9WZTJjanZGR1doenV3aXkvbXpGM0NNMVRBZ1FJRUNEUVZRRUJ2YXM5bzE0RUNCQWdNRGFCSEtKektNOGZCNlBqMHhUT0R4NlRhemR2dmppdDlsK05NWHg5RmNNL213TjUzSThmam5VNEYwSStMVDFTS2o4b29IM0J2d1FJRUNCQWdFQmZCQVQwdnZTVWVoSWdRSURBRUFWeUtEKzRSL3krMGZGcjE2NmRiWjZkZkNTRjhXOUptZnRiVTJUL2h2M1lmRldvNmd0dEdHOW50cGNvbjI0MmowM1RudDhHOVp6UkQzOE0wVTZiQ0JBZ1FJREE0QVFFOU1GMXFRWVJJRUNBUUljRmNtZytHQ2x2MHZPRGorcmxsMTkrNWt2dnZmZEtVOWUvUDFUTlB6K040WnZpTkw0VTZuclNadTZZRjMzTGVieXBtaWFmbHlKNGVhY3RMd1MvMHd1S2Z3Z1FJRUNBUUg4Ri9ETHZiOStwT1FFQ0JBajBSeUN2cnA3RCtYNzZ1RGRTdm5YanhuWUszUjlOaTdsOTV4ZnZ2UDhIMGhGZm15SjMrdDFjcHlDZW9uaisvK2swbjNNUXh0dFJjV0c4a1BpSEFBRUNCQWdNVFVCQUgxcVBhZzhCQWdRSWRFSGc4RWg1RHVUM1F2bVZGMTk4cFpwTy80VjB3SGVsZWVrcG5JZkxWZG9KTGJTajR5bVFOeW1RcDJUZWJvOFcwbWUvcTd2UW8rcEFnQUFCQWdSV0lPQ1gvZ3FRWFlJQUFRSUVSaU9RZzNrZUxiOHZsRisrZWZQVnVtbis1VFJDL3QxeHV2L05hZHI2czNreHR6SkNIdU0wVFZsUEs3dVY2ZW9wa09jUjlGeU1Cd0VDQkFnUUlEQTJBUUY5YkQydXZRUUlFQ0N3YUlIRG8rVjVPbnFaa241MWQvZmxHT0wzcEsvL1dCb3AvK2FxRHFkTEtFOHZ0TlBXMDJtaGhQbEpDdWVMcnBQeUNCQWdRSUFBZ1I0S0NPZzk3RFJWSmtDQUFJRk9DT1JVblVmTGN5QXZVOWd2M3J5NXVkRTBmemhVOFU4MFZieWRacW1mYlVmSzB4M2xUWnE2Zm0rVTNMVDFUdlNnU2hBZ1FJQUFnWTRKQ09nZDZ4RFZJVUNBQUlIT0N4eGU4SzJNbGwvZTJmbG91bzM4QjlOVTllOUpnK0U3WllwNnZxZThMUEEyR3lsM0wzbm5PMVlGQ1JBZ1FJREF1Z1VFOUhYM2dPc1RJRUNBUUY4RTh1L012TDFaR1MyL3NMdDcrWFJWZlc5YTNlMEhVeGIvdHJ5bVc1cktua2JLeS92cG52SzBGTHRRM3BlK1ZVOENCQWdRSU5BSkFRRzlFOTJnRWdRSUVDRFFVWUdEYWV3NWxMZWo1WG5CdHpqOW9SVEt2eS9kVjc2ZEYzckxxNzJWMGZLYzB0djd5anZhSE5VaVFJQUFBUUlFdWl3Z29IZTVkOVNOQUFFQ0JOWWxFS3JiNmY3eTEwb29MOEg4eXM3T2Q2UVI4VDhYbXVhN3E3cCs1bDRvVHk4YUxWOVhON2t1QVFJRUNCQVlsb0NBUHF6KzFCb0NCQWdRbUUrZ1RxZm5qLzFaT0ErWGQzZi9XSHJoejhkUS9jRzh4bHRhN0MxTmRJOTc2Wmk4K3JyZm8vTjVPNXNBQVFJRUNCQTRKT0FQaTBNWW5oSWdRSURBYUFVK0NPWXBmbCs3ZHUxc2MrclVuMmhDOWVmU0hQZGJSU1hkWUo3Q2VaTkNlVDcyMUdpbE5Kd0FBUUlFQ0JCWW1vQ0F2alJhQlJNZ1FJQkFEd1R1QytiYjI5dGJkK3I2UjlJTjUvOW11ci84cTBKZWliMnMvSllXaHd2VnhpeWM5NkJacWtpQUFBRUNCQWowVVVCQTcyT3ZxVE1CQWdRSXpDdHdYekRmZXZIRjY3SFovOUU3VmZqaE5JMzllZ3JsYWEzMjZjRys1WG5oTjc4djV4VjNQZ0VDQkFnUUlQQlVBWDl3UEpYSUFRUUlFQ0F3SUlHNnVwM3VNVzhYZjJ0bXdmekg0blQvejRTNnZwSW1zYWQ3ekVzd3QwWGFnRHBkVXdnUUlFQ0FRRjhFQlBTKzlKUjZFaUJBZ01COEFyZlRLSGdPNXE5VlRkbkRQTVovS3dYekgwM0IvSEs3ZjNsajRiZjVoSjFOZ0FBQkFnUUl6Q2tnb004SjZIUUNCQWdRNkx4QS9sMDN6ZUg4cFpkZWV2YkwwNzBmVFJQWWZ5SnRsWGE5U211K3BZWGYybUJ1NGJmT2Q2UUtFaUJBZ0FDQm9Rc0k2RVB2WWUwalFJREFlQVh5ZmVacEVmYXlsM2wxWlhmM0IzNTNmKy9mVHlQbVgxT0NlWnh0bFNhWWovYzdSTXNKRUNCQWdFREhCUElmTHg0RUNCQWdRR0JJQXFHNmRTdHZnNVkyTEsrbVc3dTdmM0RyeHU3UHBzWGZmanA5ZkUzTWk3KzE3K1ZqL0I1TUNCNEVDQkFnUUlCQU53U01vSGVqSDlTQ0FBRUNCQllqa0grdjdWZXZ2NzUzZVh2N1JwaUV2NUttcy8vSlBJeWVwcktuVmRuei93Vy8reFpqclJRQ0JBZ1FJRUJnd1FMK1NGa3dxT0lJRUNCQVlDMENlU1E4ZitUUjhXcHJaK2ZIWXgzK296UmlmakVGODd4cjJqUkZjNy96TW80SEFRSUVDQkFnMEZrQmY2eDB0bXRVakFBQkFnU09LSkIvbDVWcDY1ZDNkbjVmQ05YZlRBdkFmY3VoKzh3M2hQTWpTanFNQUFFQ0JBZ1FXS3VBZ0w1V2ZoY25RSUFBZ1RrRTdvMmFiMjl2bjdsVGgvODRsZlVYMHFoNVZlNHpEeUcvbis4ejl5QkFnQUFCQWdRSTlFSkFRTzlGTjZra0FRSUVDRHdnY0cvVS9Nck43WC94VGhQK2RscWQvU05sT25zVDAzUjI5NWsvNE9WTEFnUUlFQ0JBb0FjQ2VYVEJnd0FCQWdRSTlFWGdZSVgyL2QzZDNlZlMxbW4vZVJYci96T05tdWR3bnZjenp4dXIrWS9QZmVsTjlTUkFnQUFCQWdUdUUvQkh6SDBjdmlCQWdBQ0JEZ3RNVXQybWVZWDJxemUzdisyOUdQL3JOSXY5bFJUTTB5cHdhVXUxWURwN2gvdE8xUWdRSUVDQUFJRWpDQmhCUHdLU1F3Z1FJRUJnelFMdHZ1YlRYSXZMTjNiK2c2YXAvMEhhTCsyVmxNM3pxSG5lUE0xL2NGNXpGN2s4QVFJRUNCQWdNTCtBUDJqbU4xUUNBUUlFQ0N4UElHOWhQcm0zcjNrZC9rNGFOZitPR0p1MHIzbTFuOWFEc3dqYzh1eVZUSUFBQVFJRUNLeFl3QWo2aXNGZGpnQUJBZ1NPTEpDbnRPZkgvdGFON2U4SmRmaUZkSy81ZDVRVjJxc3FHalZ2Y2Z4TGdBQUJBZ1FJREVkQVFCOU9YMm9KQVFJRWhpU1FaM2psS2UzeHlvMmR2MXBWOWYrV25tL0dHUGRtSzdUbmtYVVBBZ1FJRUNCQWdNQ2dCRXh4SDFSM2Fnd0JBZ1FHSVBEcXE2ZXJUMzNxN3NXYk56ZFBOYzMvbEFMNWQrWHQwMUxMbXZSaFN2c0F1bGdUQ0JBZ1FJQUFnVWNMQ09pUGR2RXFBUUlFQ0t4ZW9MM2ZQSVh6U3pzNzM3QVJtLysxcXNPSDhrSnc2WTM4KytwZ3l2dnFhK2FLQkFnUUlFQ0FBSUVWQ0pqaXZnSmtseUJBZ0FDQnB3cmszMGY1WS8veTd1NzNib1R3RDlQekQrVzl6Vk00ejZQbXByUW5CQThDQkFnUUlFQmcyQUlDK3JEN1Yrc0lFQ0RRQjRFOE1wNm5yMCt2N096OFZCMnF2eHVyK0V3SzUvdnBOVlBhKzlDRDZraUFBQUVDQkFnc1JNQVU5NFV3S29RQUFRSUVUaWlRZncvbElGNXQ3ZTcrVjJsSys1K2UzVytlVm1rUGZrZWRFTlZwQkFnUUlFQ0FRRDhGL1BIVHozNVRhd0lFQ1BSZjRIYTZyL3kxRk01ZmV1blpyZjM5Zkw5NVhneHVMelVzLzI0eXc2di9QYXdGQkFnUUlFQ0F3REVGL0FGMFREQ0hFeUJBZ01BQ0JHN2RPcFhEK2M3T3pwVXIrL3YvOTZGdzduN3pCZkFxZ2dBQkFnUUlFT2luZ0lEZXozNVRhd0lFQ1BSWElJZnoxMS9mMjl6ZXZua25WUDlQQ05XdHRGTDczZFFnOTV2M3QxZlZuQUFCQWdRSUVGaUFnQ251QzBCVUJBRUNCQWdjVVNEdmNmNzY2M2UzdHJlL0prN3FuMGxuWFk4eDVwWGFUeCt4QkljUklFQ0FBQUVDQkFZcllBUjlzRjJyWVFRSUVPaVlRQjQ1VDN1Y2IxMi9maXROYWY4SEtaU1hjSjVxYWVTOFkxMmxPZ1FJRUNCQWdNQjZCSXlncjhmZFZRa1FJREF1Z2RtMDlpdTd1OSthdGxEN21iUkMrM05WM2tZdEJPRjhYTjhKV2t1QUFBRUNCQWc4UWNBSStoTnd2RVdBQUFFQ0N4QTRGTTZyR1A5K1ZhVnducWExMjBadEFiYUtJRUNBQUFFQ0JBWWxJS0FQcWpzMWhnQUJBaDBUbUlYelN6czcvMHhWcFhBZXdwbjBPZTk3YnVTOFkxMmxPZ1FJRUNCQWdNRDZCVXh4WDM4ZnFBRUJBZ1NHS1RBTDUyVkJ1RHI4SDZtUlo4ckl1WEErelA3V0tnSUVDQkFnUUdCdUFTUG9jeE1xZ0FBQkFnUWVJYkNSdDFKTDk1enZ4RHI4dmJRZzNBdmxublBoL0JGVVhpSkFnQUFCQWdRSXRBSUN1dThFQWdRSUVGaTBRSjZkdFgveDVzM05OSjM5NzRVUWRodjNuQy9hV0hrRUNCQWdRSURBQUFVRTlBRjJxaVlSSUVCZ2pRS1RkTzF5ai9sR00vM2ZVemovMnRrKzUrNDVYMk9udURRQkFnUUlFQ0RRRHdFQnZSLzlwSllFQ0JEb2cwRCtuVExORmIxeVkvZC9DWFg5clduay9HNzZVampQS0I0RUNCQWdRSUFBZ2FjSUNPaFBBZkkyQVFJRUNCeFpJTjFxbnNMNTd1NS9rVWJPLzBoc21yMzB3dWtqbisxQUFnUUlFQ0JBZ01ESUJRVDBrWDhEYUQ0QkFnUVdJbkM3eXZlZFQ3ZHU3UHhFcU1PUHhlblVWbW9MZ1ZVSUFRSUVDQkFnTUNZQkFYMU12YTJ0QkFnUVdJYkFxNitlcmw2cjlyZHVibjkzVllXL2tVYk9ZOXJ2M08rWFpWZ3Jrd0FCQWdRSUVCaTBnSDNRQjkyOUdrZUFBSUdsQzJ4VW4vclUzU3ZYcjc4U20vQS9wMVhiOHdXYjlKRVhpL01nUUlBQUFRSUVDQkE0aG9BUmptTmdPWlFBQVFJRTdoTW9LN1pmdTNidGJMVXgrYnZwdnZNelZZeDVhcnR3ZmgrVEx3Z1FJRUNBQUFFQ1J4TVEwSS9tNUNnQ0JBZ1FlRmlnREpmdm45cjQ3MU00LzdxeVluc0labVk5N09RVkFnUUlFQ0JBZ01DUkJBVDBJekU1aUFBQkFnVHVFN2gxSzIrZDFxUVYyLys5dEozYTkxcXgvVDRkWHhBZ1FJQUFBUUlFVGlRZ29KK0l6VWtFQ0JBWXNVQU81NisvdnJlMXMvUHRWYWorV2dybkdjTzA5aEYvUzJnNkFRSUVDQkFnc0JnQkFYMHhqa29oUUlEQVdBUW1PWnlmMzltNUVrUDQ2Vm1qcCttejN5ZGorUTdRVGdJRUNCQWdRR0JwQXY2Z1docXRnZ2tRSURBNGdaQmFWSWJMVDlmaHYwMzduZS9FR1BmU2EwYlBCOWZWR2tTQUFBRUNCQWlzUTBCQVg0ZTZheElnUUtDUEFyZHU1UVhnNHBVYk8zOHBMUXIzUitKMHVwOFNlNzRYM1lNQUFRSUVDQkFnUUdBQkFnTDZBaEFWUVlBQWdjRUx6TzQ3djN6anhoK3FxdkJYMDMzbnNRckJ5UG5nTzE0RENSQWdRSUFBZ1ZVS0NPaXIxSFl0QWdRSTlGT2czSGVlVm16ZnFXUHpQODZha0tlNjV5bnZIZ1FJRUNCQWdBQUJBZ3NTRU5BWEJLa1lBZ1FJREZRZ2gvQzhDRng2eFA4aGpacHZWZTQ3YnpuOFM0QUFBUUlFQ0JCWXNJQ0F2bUJReFJFZ1FHQlFBcmVxZk45NXRiVzcrNWZUZnVmZk1Wc1V6bjNuZytwa2pTRkFnQUFCQWdTNklsRCs4T3BLWmRTREFBRUNCRG9rY0NzdEFQZDZWZlk3ajZINkQ2dDgzM25WQnZZTzFWSlZDQkFnUUlBQUFRS0RFVENDUHBpdTFCQUNCQWdzVktETzRYenp3eCsrR092cXY1dVY3TDd6aFJJcmpBQUJBZ1FJRUNCd3Y0Q0FmcitIcndnUUlFQ2dGU2dMd05WMzcveXRFT3FYN0hmdTI0SUFBUUlFQ0JBZ3NId0JBWDM1eHE1QWdBQ0JmZ25rTGRYU3duQlhkbmIrOVZDSEg0alRacHJTdWx1aSt0V0xha3VBQUFFQ0JBajBVRUJBNzJHbnFUSUJBZ1NXS0pDbXRyKytsN2RVUzV1by9XY3gzM1lleW5acXRsUmJJcnFpQ1JBZ1FJQUFBUUpaUUVEM2ZVQ0FBQUVDQndJZmhQQVEvOHUwYXZ1VjlNWmUrdkM3NGtESVp3SUVDQkFnUUlEQUVnWDgwYlZFWEVVVElFQ2dWd0szYnVWcDdFMmEydjZENmI3ejc4bFQyOVBYdGxUclZTZXFMQUVDQkFnUUlOQm5BUUc5ejcybjdnUUlFRmljUUpuYXZuWGp4bmFhMFA2ZnhpWXQyTjVPYlYvY0ZaUkVnQUFCQWdRSUVDRHdSQUVCL1lrODNpUkFnTUJvQk5ycDdUSCtkVlBiUjlQbkdrcUFBQUVDQkFoMFRFQkE3MWlIcUE0QkFnUldMbkNyVEdPZmJ0M1kvcDQwYXY3OWFmUTg3M2R1MWZhVmQ0UUxFaUJBZ0FBQkFtTVhFTkRIL2gyZy9RUUlqRjBnVks5WGU5dmIyMmRpREg4anJkbWVIL25UQnd2R2xaZjhRNEFBQVFJRUNCQWdzR3dCQVgzWndzb25RSUJBdHdVbXVYcDNKdUduMHRUMnI2NWl6S3UybDllNlhXMjFJMENBQUFFQ0JBZ01UMEJBSDE2ZmFoRUJBZ1NPS3BDRCtQN2xtemRmVFFQbS8wNVpHRTQ0UDZxZDR3Z1FJRUNBQUFFQ0N4Y1EwQmRPcWtBQ0JBajBScURNYUsvajlLK2xCZHRQcDlIei9WUnp2eGQ2MDMwcVNvQUFBUUlFQ0F4TndCOWlRK3RSN1NGQWdNRFJCTm85ejIvYytLTnA5UHk3WTB4N25vZGdZYmlqMlRtS0FBRUNCQWdRSUxBVUFRRjlLYXdLSlVDQVFLY0Y4Z0p3YWJUODFxazBhdjVYT2wxVGxTTkFnQUFCQWdRSWpFaEFRQjlSWjJzcUFRSUVpc0N0VzJXa2ZPdm01MzQwMU9IM3BudlA4OVIyQzhQNTlpQkFnQUFCQWdRSXJGbkFkTVkxZDRETEV5QkFZTVVDZGZYNjYzdm50N2UzMHJacWY3R0thY3Z6RVB6SDJoVjNnc3NSSUVDQUFBRUNCQjRsNEkreVI2bDRqUUFCQXNNVktELzNUOWYxVDRRUVhrak56TnVxK1YwdzNQN1dNZ0lFQ0JBZ1FLQkhBdjRvNjFGbnFTb0JBZ1RtRkNqYnFsMjdlZlBEVlJWL3pMWnFjMm82blFBQkFnUUlFQ0N3WUFFQmZjR2dpaU5BZ0VDSEJmTGljTlcwYWY1aXFPdHo2YW5SOHc1M2xxb1JJRUNBQUFFQzR4TVEwTWZYNTFwTWdNQTRCY3JvK1pVWHI3OFNRL1VuWjZQbjFpRVo1L2VDVmhNZ1FJQUFBUUlkRlJEUU85b3hxa1dBQUlGbENJVHBKTjk3ZmpwdHI1WlhiaThqNnN1NGpqSUpFQ0JBZ0FBQkFnU09MMkQwNVBobXppQkFnRURmQlBMbytYUnpkL2ZyWXhYL2phcUpWbTd2V3crcUx3RUNCQWdRSURBS0FTUG9vK2htalNSQVlPUUNaYVE4cGZRZlMvZWViOHhHei8zOEgvazNoZVlUSUVDQUFBRUMzUlB3QjFyMytrU05DQkFnc0VpQmUvZWVwd250UDFqdVBROGh2K1pCZ0FBQkFnUUlFQ0RRTVFFQnZXTWRvam9FQ0JCWXNFQjduM2t6K2RFcWhHZmNlNzVnWGNVUklFQ0FBQUVDQkJZb0lLQXZFRk5SQkFnUTZKaEFHVDIvZFAzNmk2bGVQekFiUGZkenYyT2RwRG9FQ0JBZ1FJQUFnUU1CZjZnZFNQaE1nQUNCNFFtVTBmT05qZnBIMHNydEY5MTdQcndPMWlJQ0JBZ1FJRUJnV0FJQytyRDZVMnNJRUNCd0lKREQrZjdGbXpjM1l3dy9ISzNjZnVEaU13RUNCQWdRSUVDZ3N3SUNlbWU3UnNVSUVDQXdoOER0cWl3RXR4SDN2eS9VWWFlS1RkNzMzTS84T1VpZFNvQUFBUUlFQ0JCWXRvQS8xcFl0ckh3Q0JBaXNYaUJVcjFVbGtJY3EvRWlhMnA3M1BXOFhpMXQ5WFZ5UkFBRUNCQWdRSUVEZ2lBSUMraEdoSEVhQUFJRWVDWlRSODZ1N3UvOVNTdWJmR0dOc1V0Mzl2TzlSQjZvcUFRSUVDQkFnTUU0QmY3Q05zOSsxbWdDQllRdWtJZk9xU3FuOFQ2V1I4eXFOb09lQWJnUjkySDJ1ZFFRSUVDQkFnTUFBQkFUMEFYU2lKaEFnUU9DUVFCNDluMTdaM3Y3YTlQbTdabHVybFJIMVE4ZDRTb0FBQVFJRUNCQWcwRUVCQWIyRG5hSktCQWdRbUVPZ0hTbWZoTzlQaThNOU85dGF6ZWo1SEtCT0pVQ0FBQUVDQkFpc1NrQkFYNVcwNnhBZ1FHRDVBdmxuK3Y3Mjl2YVpLbGIvYXJyMzNPSnd5emQzQlFJRUNCQWdRSURBd2dRRTlJVlJLb2dBQVFKckZ5Zy8wKzlNSnQrWkZtMy95T3plY3ovbjE5NHRLa0NBQUFFQ0JBZ1FPSnFBUDl5TzV1UW9BZ1FJOUVHZ0xBNFhxdWI3TEE3WGgrNVNSd0lFQ0JBZ1FJREEvUUliOTMvcEt3SUVDQkRvcVVEK0Q2N1R6ZTN0bTdFS2Y2aHEwc0x0SVZnY3JxZWRxZG9FQ0JBZ1FJREFPQVdNb0krejM3V2FBSUdoQ2R4dTl6bXZKNVB2VHRQYkwxb2NibWdkckQwRUNCQWdRSURBR0FTTW9JK2hsN1dSQUlHaEM0VHF0V3EvTkRMR1A5NDJObStBN2tHQUFBRUNCQWdRSU5BbkFTUG9mZW90ZFNWQWdNQ2pCY3JQOHMwYk4zNVBGYXJmMTY3ZW5wNTVFQ0JBZ0FBQkFnUUk5RXBBUU85VmQ2a3NBUUlFSGlsUXduZ2Rtank5L2ZSc2VydWY3NCtrOGlJQkFnUUlFQ0JBb0xzQy9vRHJidCtvR1FFQ0JJNHEwRTV2YjhJZlRlSGMzdWRIVlhNY0FRSUVDQkFnUUtCakFnSjZ4enBFZFFnUUlIQk1nYkpTKzlXZG5XK29xbmlyVEcrdjJnWGpqbG1Pd3drUUlFQ0FBQUVDQk5Zc0lLQ3Z1UU5jbmdBQkFuTUtsT250VFFqZkdlcDZZdlgyT1RXZFRvQUFBUUlFQ0JCWW80Q0F2a1o4bHlaQWdNQ2NBam1jbCtudGFXTDdIeTdUMjYwTk55ZXAwd2tRSUVDQUFBRUM2eE1RME5kbjc4b0VDQkNZVjZEOERMKzZ1L3ZWb1lyZk9GdTkzYy8xZVZXZFQ0QUFBUUlFQ0JCWWs0QS81TllFNzdJRUNCQllnRUNaM3A1R3o3ODloUHBjRmF0cEt0UFA5UVhBS29JQUFRSUVDQkFnc0E0QmY4aXRROTAxQ1JBZ3NCaUJsTTNUMG5CVi9NNzhiL29vWHkrbWFLVVFJRUNBQUFFQ0JBaXNXa0JBWDdXNDZ4RWdRR0F4QW5uMGZIcng1czNOdEsvYVIwczBUOFBvaXlsYUtRUUlFQ0JBZ0FBQkF1c1E4TWZjT3RSZGt3QUJBdk1MbE8zVkpqRitTd2pWVGhvOWIxS1JmcWJQNzZvRUFnUUlFQ0JBZ01EYUJQd3h0elo2RnlaQWdNRDhBaUZPYjFjcG9hZlo3VG1nZXhBZ1FJQUFBUUlFQ1BSWVFFRHZjZWVwT2dFQ294VzR0NzF2UkNsb0FBQkFBRWxFUVZSYUNPSGJ5cTNuNmNsb05UU2NBQUVDQkFnUUlEQVFBUUY5SUIycEdRUUlqRXFnL095K2RQMzZpN0VLdjdkc3I1WnVSQitWZ01ZU0lFQ0FBQUVDQkFZb0lLQVBzRk0xaVFDQndRdVVNRjVQSnQrVW5seE1yYzNUMndYMHdYZTdCaElnUUlBQUFRSkRGeERRaDk3RDJrZUF3R0FGNmhCLy82SDd6d1gwd2ZhMGhoRWdRSUFBQVFKakVSRFF4OUxUMmttQXdKQUVwcmt4YVd1MWo3WmJuN3YvZkVpZHF5MEVDQkFnUUlEQWVBVUU5UEgydlpZVElOQlBnZnh6TzE3ZTJkbE5zOXBmS2ZlZkI5dXI5Yk1yMVpvQUFRSUVDQkFnY0wrQWdINi9oNjhJRUNEUWRZSDI1M1pkdjVyR3pUZFRaZDEvM3ZVZVV6OENCQWdRSUVDQXdCRUZCUFFqUWptTUFBRUNYUkpJTjV4Lzg2SDd6N3RVTlhVaFFJQUFBUUlFQ0JBNG9jREdDYzl6R2dFQ0JBaXNYaUF2QkpkSHpQTU42TjlZUGx1OHZXWHdMd0VDQkFnUUlFQmdBQUpHMEFmUWlacEFnTUJvQkVwQXYzYnQydG1VMEwrdXREcEk2S1BwZlEwbFFJQUFBUUlFQmk4Z29BKytpeldRQUlFQkNaU3QxUGFmbTl4SUM4UzlXQmFJcy8vNWdMcFhVd2dRSUVDQUFJR3hDd2pvWS84TzBINENCUG9rVUFKNjNDOEx4RDJiS202QnVENzFucm9TSUVDQUFBRUNCSjRpSUtBL0JjamJCQWdRNkpwQUNQRnJEeTBRVjBKNzErcW9QZ1FJRUNCQWdBQUJBc2NYRU5DUGIrWU1BZ1FJckVzZzVndW5SUDcxYVpHNGRkWEJkUWtRSUVDQUFBRUNCSllrSUtBdkNWYXhCQWdRV0lMQU5KV1o4bm40Y0NrN3BKM1FQUWdRSUVDQUFBRUNCQVlqWUp1MXdYU2xoaEFnMEZHQmd4Q2RQeDg4ejhQZjdYWnBSNjkwL2crcXpaWGQzZTIwT055SFpxZjVqNnhIOTNNa0FRSUVDQkFnUUtEekFnSjY1N3RJQlFrUTZMbkF3VnowZzg4SHpjbGgvY0hYRHQ1NzFPY1M3c05rY2kxTzl6ZG5CeHdFL2tjZDd6VUNCQWdRSUVDQUFJR2VDUWpvUGVzdzFTVkFvQmNDWmJUNytlZWZ2elk5ZGVxL1NlUG01MEtzUGhkRDJFdTF2NUJTOWQ5ODU4MDNYMHZQSitralQxcy95cU1ONDlQcEsybG1lNTFHMGZONStYd1BBZ1FJRUNCQWdBQ0JnUWdJNkFQcFNNMGdRS0I3QXMxeno5WFZkUC9iUTEyZnpZdTY1WVNkbmxmTnRObE5UNzhwZmN6dUtUL0NTUHJ0MjFYMTJtdFZyS3Zka0V0cW1sUmdtOWxUT1I0RUNCQWdRSUFBQVFJREVIRC80Z0E2VVJNSUVPaW13SFF5ZVRkRjZMZGkwNlI4SHUra3ovdk5kSG9uallEZjJ0cmQvZjVaclk4MkN2N2FhKzEwK0tiNlNEZGJxMVlFQ0JBZ1FJQUFBUUx6Q2dqbzh3bzZud0FCQW84Uk9QMlZyK3luVk4zTVJybzMwdWM4YXlsOTVLd2Rmekw5azhQNWZ2cDQybEI0ZnY5Z0t2eUgyaTNXbm5aS09zT0RBQUVDQkFnUUlFQ2dWd0lDZXErNlMyVUpFT2lKUUJudGZ2dnR0OTlMb2Z4M0g0alNrenlTWHRYMU4xemUzZjJoV1h1ZU5vcGVpbmpwcFplZVRWSCtham1uekhQdmlZWnFFaUJBZ0FBQkFnUUlIRWxBUUQ4U2s0TUlFQ0J3SW9HOGxkckJ5UGNIQmVUOXkvTTk2YUg2OGVybGw1OUpieHhsRkwzNm5idDNyNmJ6OGpacnVhd0hjdjhIeFh0R2dBQUJBZ1FJRUNEUVR3RUJ2Wi85cHRZRUNQUkVJSVh3cnp5aXFta1VQZTZublA1MVYrNjgreU96OTU4MGlsN0NlSnhNTHFaVWYrNFI1WG1KQUFFQ0JBZ1FJRUJnQUFJQytnQTZVUk1JRU9pa1FCdXFZOGlqNlBtMjh6THNmYSttYVlwNkhna1BWZjJUMTY1ZE81dGVmK29vZXQwMDExSXBwMHRwUnREdlVYcENnQUFCQWdRSUVCaUtnSUErbEo3VURnSUV1aWJRVGtGdm12Y2VVN0ZKMmlwdFA0MklmMmp2MUtrL05Udm1jYVBvYmRpdjQ0dHBSRDQvY3Vodm41VXYvVU9BQUFFQ0JBZ1FJREFFQVFGOUNMMm9EUVFJZEZjZ3hEd3kvdWhIbXVQZWpxTEhuN3g0OCtabU9pZ2YrOWlmeTNVMTJjdzNydWM5Mng1ZG9GY0pFQ0JBZ0FBQkFnVDZMUERZUHdUNzNDaDFKMENBd0pvRmNvQXVJOXpwbjNmYXA0L00xR1VVUGRUMTdzWjArbWRMblcrVnJkY2VXZjJVeTlzVjNCLzVyaGNKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1c0TGhQRHdLdTZIYXh4Q25iWmRTeGsrL1BuejI5dGIxZXZWWG5yN3daL05iYm9QOGZvRGQ3SWZMc2x6QWdRSUVDQkFnQUNCbmdzOCtFZGd6NXVqK2dRSUVPaU1RQmxCVDhuNm5hZmNMWjUvRHUrRk9sdy9IY0pmbU5YK3daL05KYUNuK2ZEUDU5WG1QQWdRSUVDQUFBRUNCSVlwOE9BZmdjTnNwVllSSUVCZ1RRSWhQbVVFdmExWDJuYXR5YmVYLzltckw3MzBRbnJwd1h2Ulp5UG85Wm4yOEpMOTE5UWlseVZBZ0FBQkFnUUlFRmlXZ0lDK0xGbmxFaUF3Ym9IYnQ5djJoL0NsSTBEa244VjdWVjF2VGZmM2YySjIvTUhQNTV6R2MwQ3YwMDV0N1I3b2FZdTIyVEUrRVNCQWdBQUJBZ1FJREVqZzRBL0FBVFZKVXdnUUlOQWRnYlJRZTdzUCt0T3J0REViUmYvVG05dmJOOVBoOTQyaWIyMXRuVTJqOFJkbUU5d0Y5S2Q3T29JQUFRSUVDQkFnMERzQkFiMTNYYWJDQkFqMFF1QzExMG8xcDAzemJ0b1dMVDEvYXFiT0IreWxRSDloTWdrL1hrNXVGNHNySjlaMWZTYVZjcTR0YS9hdVR3UUlFQ0JBZ0FBQkFvTVNFTkFIMVowYVE0QkE1d1JDOCtSVjNPK3ZjTGtYUGVYNVA3TzFzL09SOU5aK05kdDJiVzlqNDVtcWFtYjNvRDg5N2Q5ZnJLOElFQ0JBZ0FBQkFnVDZJQ0NnOTZHWDFKRUFnZDRLaEZoL3NWUStQTFIxMnFQYWxIOG1weFhkNitkaVhiV2o2TysvV2tiUU4rbzZCZlJ3NmxFbmVZMEFBUUlFQ0JBZ1FHQVlBZ0w2TVBwUkt3Z1E2S2hBMmhydDdqR3JWdTVGcjJMNDRjczNiNzVhZmVwVDVmeDRxcW5UOVBlbnpwTS81clVjVG9BQUFRSUVDQkFnMENFQkFiMURuYUVxQkFnTVNxQ3M1NVpHdzM4bmxudlFqend0dmIwWHZRNm5RNXordXdjaTlWNzlUQ3B3Y3ZDMXp3UUlFQ0JBZ0FBQkFzTVRFTkNIMTZkYVJJQkFod1JTcUg0dlZTZUg5ZU9NZnM5RzBhdC9iZXZHalcvS3pkbWZOSG1CdUlNcDdzY3BLNS91UVlBQUFRSUVDQkFnMEFNQkFiMEhuYVNLQkFqMFZ5Q3RFUGQrRlVMZU1pMC95cWg2Ky9TSi80WVV4dmZUNlB0R0duMy9xZmJJa004OTZ2bFBMTnliQkFnUUlFQ0FBQUVDM1JRUTBMdlpMMnBGZ0VEL0JVcVlucHhxN3FiaDd1T3M1TjYyUElROGloN1R1UHUvY3ZtRkY3NnVpcFBmU1VFL2o1d0w2ZjMvM3RBQ0FnUUlFQ0JBZ01BakJRVDBSN0o0a1FBQkFvc1JtT3hQOXRNbytQRURlcjU4T2k5bjhyQ3g4Vk1wckIvOHZEYTlmVEZkb3hRQ0JBZ1FJRUNBUU9jRU5qcFhJeFVpUUlEQWdBVDI5dmZUdG1sNUJQMEV1VHFFc2k5Nk92TjdKNkgrUkt6aTd5U2FDK2tqajZLZm9NQUJ3V29LQVFJRUNCQWdRR0NBQWdjak1nTnNtaVlSSUVCZy9RSWIrL3QzMDVacGVhRzQvRGp1OVBRY3d2TWE4TS9HMlB4NGVuYndIMVdGODhMcEh3SUVDQkFnUUlEQXNBUUU5R0gxcDlZUUlOQWRnUkxHOTg3dHZaK21xYjg3eDRCM0NlbXBXVHZwNDB4M21xY21CQWdRSUVDQUFBRUNpeFlRMEJjdHFqd0NCQWdjRWpqOWxkUDdhV3I2M1RrbnBCK0U5RU1sZTBxQUFBRUNCQWdRSURBMEFRRjlhRDJxUFFRSWRFV2dqS0MvL2ZiYjc2YlYxNzg4bTVOKzNDbnVoOXRpV3Z0aERjOEpFQ0JBZ0FBQkFnTVVFTkFIMkttYVJJQkFwd1J5S0QvWUI3MVRGVk1aQWdRSUVDQkFnQUNCYmdrSTZOM3FEN1VoUUdCWUFtWFVPKzJVOXBYU3JEVFhmVmpOMHhvQ0JBZ1FJRUNBQUlGRkNnam9pOVJVRmdFQ0JPNFhLQUU5eHREYy83S3ZDQkFnUUlBQUFRSUVDRHdzSUtBL2JPSVZBZ1FJTEZhZ2FXYmJyQmxBWHl5czBnZ1FJRUNBQUFFQ3d4SVEwSWZWbjFwRGdFQVhCVUowRDNvWCswV2RDQkFnUUlBQUFRSWRFeERRTzlZaHFrT0F3S0FFMm52UXErbzM1OWdIZlZBZ0drT0FBQUVDQkFnUUlQQjRBUUg5OFRiZUlVQ0F3R0lFUWpDQ3ZoaEpwUkFnUUlBQUFRSUVCaTBnb0ErNmV6V09BSUUxQzdTTHhGWFZPMVY1dHViYXVEd0JBZ1FJRUNCQWdFQ25CUVQwVG5lUHloRWdNQVNCRU1OMENPM1FCZ0lFQ0JBZ1FJQUFnZVVLQ09qTDlWVTZBUUlFMHUzbjRVc1lDQkFnUUlBQUFRSUVDRHhOUUVCL21wRDNDUkFnTUtkQUNQWkJuNVBRNlFRSUVDQkFnQUNCVVFnSTZLUG9abzBrUUdDZEF0T21lYmVLZVEvMDRFNzBkWGFFYXhNZ1FJQUFBUUlFT2k0Z29IZThnMVNQQUlFQkNJU212UWRkUEI5QVoyb0NBUUlFQ0JBZ1FHQjVBZ0w2OG15VlRJQUFnU0lRWXYzYk00b2MwZk5RdWdjQkFnUUlFQ0JBZ0FDQmh3UUU5SWRJdkVDQUFJSEZDb1FZNzg1aXVUSDB4ZElxalFBQkFnUUlFQ0F3S0FFQmZWRGRxVEVFQ0hSTW9JeVdoN3IrVW13VHVvRGVzUTVTSFFJRUNCQWdRSUJBbHdRRTlDNzFocm9RSURCSWdhYXEzazhOUzU4OENCQWdRSUFBQVFJRUNEeGVRRUIvdkkxM0NCQWdzQkNCalJqZlR3dTQ3ODhLY3cvNlFsUVZRb0FBQVFJRUNCQVlub0NBUHJ3KzFTSUNCRG9tTUQxMTZtNmEyOTZ1NU42eHVxa09BUUlFQ0JBZ1FJQkFkd1FFOU83MGhab1FJREJRZ1hwL2Z6L0dLS0FQdEg4MWl3QUJBZ1FJRUNDd0tBRUJmVkdTeWlGQWdNRERBbVU2Kzk1MHVwZmVFdEFmOXZFS0FRSUVDQkFnUUlEQUlRRUIvUkNHcHdRSUVGaUd3TWJlM3QycUN1K2xqMlVVcjB3Q0JBZ1FJRUNBQUlHQkNBam9BK2xJelNCQW9Mc0NlMmZQdnAraStidXpmRzZSdU81Mmxab1JJRUNBQUFFQ0JOWXFJS0N2bGQvRkNSQVlnOEF6NzcyM2wvWkJUNlBvSGdRSUVDQkFnQUFCQWdRZUx5Q2dQOTdHT3dRSUVKaFhvSXlXdi8zMjIrK2xiZGErWW9MN3ZKek9KMENBQUFFQ0JBZ01XMEJBSDNiL2FoMEJBdDBRYUZJMUR2WkI3MGFOMUlJQUFRSUVDQkFnUUtCekFnSjY1N3BFaFFnUUdLSkFDTlZYaHRndWJTSkFnQUFCQWdRSUVGaWNnSUMrT0VzbEVTQkE0RkVDWldaN2JLcDJjYmgwTS9xakR2SWFBUUlFQ0JBZ1FJQUFBUUhkOXdBQkFnU1dLOURlZWg3anU4dTlqTklKRUNCQWdBQUJBZ1Q2TGlDZzk3MEgxWjhBZ1g0SWhPZ2U5SDcwbEZvU0lFQ0FBQUVDQk5ZbUlLQ3ZqZDZGQ1JBWWdVQ2V6bDVHME5NLzc3UlB6WEFmUWI5cklnRUNCQWdRSUVEZ1JBSUMrb25ZbkVTQUFJRmpDb1F3UGVZWkRpZEFnQUFCQWdRSUVCaVpnSUErc2c3WFhBSUVWaTdRTGhLWFI5RGJ1OUZYWGdFWEpFQ0FBQUVDQkFnUTZJZUFnTjZQZmxKTEFnUjZMaENpRWZTZWQ2SHFFeUJBZ0FBQkFnU1dMaUNnTDUzWUJRZ1FHTFhBN2R0dDgwUDQwcWdkTko0QUFRSUVDQkFnUU9DcEFnTDZVNGtjUUlBQWdma0ZRZ2pOL0tVb2dRQUJBZ1FJRUNCQVlNZ0NBdnFRZTFmYkNCQll2OEJycjVVNlRKdm0zU3JlVzlSOS9mVlNBd0lFQ0JBZ1FJQUFnYzRKQ09pZDZ4SVZJa0Jna0FLaHNZcjdJRHRXb3dnUUlFQ0FBQUVDaXhNUTBCZG5xU1FDQkFnOFZpREUrb3ZselZENXVmdFlKVzhRSUVDQUFBRUNCTVl0NEEvRmNmZS8xaE1nc0NLQkVPUGVpaTdsTWdRSUVDQkFnQUFCQWowVkVOQjcybkdxVFlCQWJ3VHlqZWRWbUV4K081WjcwTzJHM3B1ZVUxRUNCQWdRSUVDQXdJb0ZCUFFWZzdzY0FRTGpGR2hpdkpOYWJwVzRjWGEvVmhNZ1FJQUFBUUlFamlRZ29CK0p5VUVFQ0JDWVQyQ2pxdDZyUXRpZmxWSkcxZWNyMGRrRUNCQWdRSUFBQVFKREV4RFFoOWFqMmtPQVFOY0VTaGlmbm1ydWhxcXlrbnZYZWtkOUNCQWdRSUFBQVFJZEVoRFFPOVFacWtLQXdIQUZKdnVUL1hRUHVvQSszQzdXTWdJRUNCQWdRSURBM0FJQyt0eUVDaUJBZ01EVEJmYjI5L01xN2dkVDNKOStnaU1JRUNCQWdBQUJBZ1JHSnlDZ2o2N0xOWmdBZ1hVSWJPenYzMDFMeEwwL3U3WjcwTmZSQ2E1SmdBQUJBZ1FJRU9pNGdJRGU4UTVTUFFJRWVpOVF3dmpldWIzM1F3anZwZzNYZXQ4Z0RTQkFnQUFCQWdRSUVGaU9nSUMrSEZlbEVpQkE0RDZCNTk1L2JpOVc4YTU4ZmgrTEx3Z1FJRUNBQUFFQ0JBNEpDT2lITUR3bFFJREFFZ1RLQ1BwYmI3MlZ0MW43OG16ODNCVDNKVUFya2dBQkFnUUlFQ0RRZHdFQnZlODlxUDRFQ1BSRklJZHlpOFQxcGJmVWt3QUJBZ1FJRUNDd0JnRUJmUTNvTGttQXdPZ0V5c0I1Q05WWFNzdlRYUGZSQ1dnd0FRSUVDQkFnUUlEQVV3VUU5S2NTT1lBQUFRSnpDNVNBSG1ObzVpNUpBUVFJRUNCQWdBQUJBb01WRU5BSDI3VWFSb0JBNXdTYVpyYk5tZ0gwenZXTkNoRWdRSUFBQVFJRU9pQWdvSGVnRTFTQkFJSEJDN1JydzRXOEQvcHNtYmpCTjFrRENSQWdRSUFBQVFJRWppc2dvQjlYelBFRUNCQTR2c0JCUVArRWZINThQR2NRSUVDQUFBRUNCTVlpSUtDUHBhZTFrd0NCdFF2RUVEOFdZNXJlSHNJa1ZjWTg5N1gzaUFvUUlFQ0FBQUVDQkxvbElLQjNxei9VaGdDQllRcTBpOE5OdzZlckdIOHJOVEdQcUF2b3creHJyU0pBZ0FBQkFnUUluRmhBUUQ4eG5STUpFQ0J3WklFU3huL3JuLzdUTjlNWi95U2svZGJTUTBBL01wOERDUkFnUUlBQUFRTGpFQkRReDlIUFdrbUF3SG9GY2hqUDA5clRJL3g4bXVLZTRubWU2KzVCZ0FBQkFnUUlFQ0JBNEFNQkFmMERDODhJRUNDd1BJSGJzK1hoNnZqeEZNN1RkZHBoOU9WZFVNa0VDQkFnUUlBQUFRSjlFeERRKzlaajZrdUFRRDhGWG11bnREZE4rUGtVei9kU1hMZFFYRDk3VXEwSkVDQkFnQUFCQWtzVEVOQ1hScXRnQWdRSTNDZFFGb283VzFXZlNTUG92em9iUUc4WGo3dnZNRjhRSUVDQUFBRUNCQWlNVlVCQUgydlBhemNCQXFzV0tQZWh2L25tbSsrbDZlMy9LT1FaNys1RFgzVWZ1QjRCQWdRSUVDQkFvTk1DQW5xbnUwZmxDQkFZbUVCWnZqMjE2V096TzlJSDFqek5JVUNBQUFFQ0JBZ1FtRWRBUUo5SHo3a0VDQkE0bmtDN2NudGFLSzRNbm9mZ1B2VGorVG1hQUFFQ0JBZ1FJREJvQVFGOTBOMnJjUVFJZEV5Z0JQUVE2MCtIR045SmRjc2o2bTFvNzFoRlZZY0FBUUlFQ0JBZ1FHRDFBZ0w2NnMxZGtRQ0I4UXFVTVA3T1p6LzdWb3JtdnhUYW5kWUU5UEYrUDJnNUFRSUVDQkFnUU9BK0FRSDlQZzVmRUNCQVlLa0NPWXpuYWUxcGZianc4YktTdTRYaWxncXVjQUlFQ0JBZ1FJQkFud1EyK2xSWmRTVkFnTUFBQk5xRjR1cjRlanU1dlIxR0gwQzdOSUVBQVFJRUNCQWdRR0JPQVNQb2N3STZuUUFCQXNjVUtGUGFteVo4TWozWlMxUGRMUlIzVEVDSEV5QkFnQUFCQWdTR0tpQ2dEN1ZudFlzQWdhNEtOTGxpWjZ2cU0ybWUrNitXYWU0V2l1dHFYNmtYQVFJRUNCQWdRR0NsQWdMNlNybGRqQUFCQW1WaSsrVE5OOTk4THkzaS9vOUNYc2c5eGhMYTJSQWdRSUFBQVFJRUNJeGJRRUFmZC85clBRRUM2eEZvNzBPdnFvK1ZqZGJXVXdkWEpVQ0FBQUVDQkFnUTZKaUFnTjZ4RGxFZEFnUkdJZEJ1clJiang4c2k3aUc0RDMwVTNhNlJCQWdRSUVDQUFJRW5Dd2pvVC9ieExnRUNCSlloVUFKNnFPdFBoeGpmU1JmSUkrcHRhRi9HMVpSSmdBQUJBZ1FJRUNEUUN3RUJ2UmZkcEpJRUNBeE1vSVR4ZHo3NzJiZFNOUCtsME82MEpxQVBySk0xaHdBQkFnUUlFQ0J3WEFFQi9iaGlqaWRBZ01EOEFqbU01Mm50YVgyNDhIcFp5YjNNZForL1lDVVFJRUNBQUFFQ0JBajBWMEJBNzIvZnFUa0JBdjBXS0F2RnBYOStMcVgwMUpKMkdMM2ZUVko3QWdRSUVDQkFnQUNCZVFRRTlIbjBuRXVBQUlHVEM1UXA3VTFkZnpJOTJVdFQzUzBVZDNKTFp4SWdRSUFBQVFJRUJpRWdvQStpR3pXQ0FJRWVDcFM5enkvVTlhK2tFZlJmbWQySGJqLzBIbmFrS2hNZ1FJQUFBUUlFRmlVZ29DOUtVamtFQ0JBNG5rQzVELzJOTjk1NFAwMXUvOFd5a0x2NzBJOG42R2dDQkFnUUlFQ0F3TUFFQlBTQmRham1FQ0RRSzRGeUgzb1Z3OGZMUm11OXFycktFaUJBZ0FBQkFnUUlMRnBnWTlFRktvOEFBUUlFaml4UTdrTlBBK2V2bDEzUVF6aTRENzBON2tjdXhvRUVDQkFnUUlBQUFRSkRFRENDUG9SZTFBWUNCUG9xVUFKNmZlclVQdzR4Zmo0MUlnZno4bHBmRzZUZUJBZ1FJRUNBQUFFQ0p4Y1EwRTl1NTB3Q0JBak1LMURDK0JmZWVPTnpLWnIvOG15aE9BRjlYbFhuRXlCQWdBQUJBZ1I2S2lDZzk3VGpWSnNBZ1VFSTVEQSt1OVdvVHZlaHB3RjBDOFVOb21NMWdnQUJBZ1FJRUNCd0VnSDNvSjlFelRrRUNCQll0RUNNSHk5RnpvYlJGMTI4OGdnUUlFQ0FBQUVDQkxvdllBUzkrMzJraGdRSURGdWdUR2x2NnZxVDZjbGVhdXJCUW5IRGJyWFdFU0JBZ0FBQkFnUUlQQ1Fnb0Q5RTRnVUNCQWlzVktESlY3dFExNytTcHJmL3ltd0F2YnkyMGxxNEdBRUNCQWdRSUVDQXdOb0ZCUFMxZDRFS0VDQXdjb0U4Z2o1NTQ0MDMzayszb1A5aVdjamRmZWdqLzViUWZBSUVDQkFnUUdDc0FnTDZXSHRldXdrUTZKSkEyZmM4eHZCNjJXaXRTelZURndJRUNCQWdRSUFBZ1pVSkNPZ3JvM1loQWdRSVBGYWczSWVlcHJoL3ZBeWVoK0ErOU1kU2VZTUFBUUlFQ0JBZ01Gd0JBWDI0ZmF0bEJBajBSNkFFOUxDeDhla1E0K2RUdGZPSWVodmErOU1HTlNWQWdBQUJBZ1FJRUpoVFFFQ2ZFOURwQkFnUVdJQkFDZVB2L1Bxdi8wYUs1cjg4V3loT1FGOEFyQ0lJRUNCQWdBQUJBbjBTRU5ENzFGdnFTb0RBVUFWeUdOOW9HMWQvdkVxcnhhWHA3Z0w2VUh0YnV3Z1FJRUNBQUFFQ2p4R1kvVUg0bUhlOVRJQUFBUUtyRllqeFkrMEZjMHIzSUVDQUFBRUNCQWdRR0pPQUVmUXg5YmEyRWlEUVpZRXlZaDRuMDAra0ozZlRWSGNMeFhXNXQ5U05BQUVDQkFnUUlMQUVBUUY5Q2FpS0pFQ0F3QWtFbW56TytmRE1yNlg1N2I4eXV3Kzl2SGFDc3B4Q2dBQUJBZ1FJRUNEUVF3RUJ2WWVkcHNvRUNBeFNJSStnVDk1NDQ0MzNRMVA5UW1taCs5QUgyZEVhUllBQUFRSUVDQkI0bklDQS9qZ1pyeE1nUUdEMUF1MTk1M1gxc2JKUTNPcXY3NG9FQ0JBZ1FJQUFBUUpyRkJEUTE0anYwZ1FJRUhoQW9OeUhYalhWSjhyZ2VRaDVJYy8ydFFjTzlDVUJBZ1FJRUNCQWdNRHdCQVQwNGZXcEZoRWcwRitCRXNicjAzdi9PRFhoYzdObUNPajk3VTgxSjBDQUFBRUNCQWdjUzBCQVB4YVhnd2tRSUxCVWdSTEdQLzlybjM4N3pYWC9wZGxDY1FMNlVza1ZUb0FBQVFJRUNCRG9qb0NBM3AyK1VCTUNCQWprTUo2bnRhZEhmTDNjaDI2aHVKYkR2d1FJRUNCQWdBQ0JFUWdJNkNQb1pFMGtRS0NQQXZGalZVeDVmVGFNM3NjV3FETUJBZ1FJRUNCQWdNRHhCQVQwNDNrNW1nQUJBc3NXS0ZQYVl4M3pWbXQzMHNja2Zaam12bXgxNVJNZ1FJQUFBUUlFT2lBZ29IZWdFMVNCQUFFQ2h3U2EvUHg4ZU9iWFloVi9kVGFBWGw0N2RJeW5CQWdRSUVDQUFBRUNBeFFRMEFmWXFacEVnRUN2QmZKbytlU05OOTU0UDhUd3lkSVM5NkgzdWtOVm5nQUJBZ1FJRUNCd1ZBRUIvYWhTamlOQWdNRHFCTklpN3VrUlpndkZyZTY2cmtTQUFBRUNCQWdRSUxCR0FRRjlqZmd1VFlBQWdjY0l0UGVjeC9CNkdUd1BJYS9zN2o3MHgyQjVtUUFCQWdRSUVDQXdGQUVCZlNnOXFSMEVDQXhKb0lUeCt0VGRUNmRZL3JsWnd3VDBJZld3dGhBZ1FJQUFBUUlFSGlFZ29EOEN4VXNFQ0JCWXMwQUo0NS8vdGMrL25lYTYvOUpzb1RnQmZjMmQ0dklFQ0JBZ1FJQUFnV1VMQ09qTEZsWStBUUlFamkrUXczaWUxcDd2US8vNXRCZDZtdUNlTjBYM0lFQ0FBQUVDQkFnUUdMS0FnRDdrM3RVMkFnUUdJQkIvTG9YekZOUnpTdmNnUUlBQUFRSUVDQkFZc29DQVB1VGUxVFlDQlBvc1VQWStqOVBxa3ltZzMwa05tYVFQbytoOTdsRjFKMENBQUFFQ0JBZzhSVUJBZndxUXR3a1FJTEFtZ1JMR2YvUE1tVitMSVh4bU5vQmVRdnVhNnVPeUJBZ1FJRUNBQUFFQ1N4WVEwSmNNckhnQ0JBaWNVQ0FIOUVuMW1jL2NTZVBtditBKzlCTXFPbzBBQVFJRUNCQWcwQ01CQWIxSG5hV3FCQWlNVHFEY2R4N3IrTEdPdHp5bWFmajc1YU9xcHFtdWVhVGZkUHlPZDVycUVTQkFnQUFCQXQwVGFGY0o3bDY5MUlnQUFRSUVaaUczYnNJblVnTE9DOFhsbjlrNStIWm53YmdROWxJd1B4VW1rL2IzU1ZyUTd0NkM4N0hhdjFmZFVPWC9JSnpyM1oyNnA4cDRFQ0JBZ0FBQkFnUzZKR0FFdlV1OW9TNEVDQkM0WDZDTVFrLzI5ajZkWXUxdnpMSnROKzVEVCtFNzN4Y2ZZdlYvcFhwOWF4V2JmenMyOGFkVElQLzU5UFVYYzEzRHBON0l3VDNVNlQ4c2hIQVEwUE4vYTJoSDIwdUFMeVB1UnQzdjczZGZFU0JBZ0FBQkFpTVZNSUkrMG83WGJBSUVlaUZRQXZyYmI3LzkrU3U3dS84azVlSHIzZGtOUFkvbzEzbTAvTGQrODgwM2Z5NXA1by84bUZ6ZTN0NmVUQ1lmYW1MemFoWERLeW5GdjVKQytZMzAzczBVMUo4cmdUMGZPV3RNYWVRSERadCtNQVNmQnR0VHprOUhIdjdJWjNvUUlFQ0FBQUVDQkFZcElLQVBzbHMxaWdDQmdRams3SnAvVHFmUjZqUXlIZXB2cjVvbWxnWGpPdExBbEp5L2txdHk3ZHExcytrL0pMeWZuazUvNjYyM1Bwcys1NCtmVFIvbGtUTDdtYjI2M2s2ajdDbW94NC9FdW40eGhmWVUzcXZyS1pCdnB4eStGVVAxWENwdlV0V3p5VjBIQWI1TjhBZEZQUmpnOCtzNXdPZkg0YzhIejl0My9FdUF3THdDQjdOZ2NqbDUxb3NIQVFJRUNDeEJRRUJmQXFvaUNSQWdzR2lCTkhyK2MrWGU3dGwrYTRzdS83amxwYTNmVXA1T2oxQjlLWDlLNFR3SDlWQzkrdXJwL0hYMXFVOGRUTVhQOFRxKzlkWmI3NmJQbjVsOS9FejZmTytSd3Z2VzNTcGVDWFg5UWpycDVWVHVDeW0wZnppVnRwdWVYMGxyenUya0dmS1hVbDUvTmprY0N2QzVpSkxlMjM4L0dJWFBieHdLOHZuTC9FaWwzVDhpUDN1eHZPa2ZBZ1FlRnNpaFBIL2svNkVKNVEvN2VJVUFBUUlMRnloL1h5MjhWQVVTSUVDQXdLSUU4aC9IemRiMjl0ZWtrZVZQcGh1NG4wMWY1eitXMS8zenUwbi9yYUJPLzlIZ0g2WXA3UC9KZEQ5KzRyZC80emQrL1lGR1QyYjFQQWpyK2UxUTNVNGZyK1duWmJYM3crK1ZGeC80cDA2ajgxdlRqWTFMNmNETGFVWDdseVlodkpDeStKVVU0aitVWmhOY1MwVmVTaVJiU1dVcmZmMU0rbndxQmZuMDhpR2lRK0c5ZmRvRyszUlVmcEx2aTAvRkg3eDI3N3cyenJjVnV2ZGlMcmw5cWZ4NytQbWhsd2Y3ZEpyNlBmZnIvL3ZPWjkvODZHQmJPYzZHNWUvbHd4ODVrQi84ajZMTWtwbWVPdlhONllYZlU5KzU4M2UrOElVdmZIbDIvTDFqeHNtbTFRUUlFRmlzd05qK3NGaXNudElJRUNDd2ZJSDhjenErL1BMTHozenh6dnMvbjc3NHVoU0s4eC9PT1NTdCs1RUcwdHNVbkVMdmI2ZHF2cDcrdlArWjJGUi8vMHdJbjN6enpUZmZlNkNDZWRaVy9tTStoL0w4K2VCM1VQNTgrSG42c3J4L2NHeisra21QK3VMTm14ZlRmN25ZakUxemJocmoxWFR3VGowSm02bUF5K20yZ08ybUN0ZnJFQzZrVWkrbU5INDV2YitaQXZ5cEZQSlB6NXFRYWpDclFyNXF1WHorZk9qWm9aQS9lN2xKaDZXanl3bmwyUGFmV1RrZmpOYm5sdy9hOStEejlwVCsvQ3VnOTZldmpsclR3LzhoN2I3L1lQYjhqUnRmTmEyYWZ5NFY5TzNwMi95ajZYOHJIOG4vVzcvYk5GLzkvN2QzSi9DVlhQV1o5NnZxWHFsWGRiczMyN1NranVPUWtOQXNob1lrTE1adFkyQXltVGV6SklGNUU4Z3lNSGw1bVF6RGZNSm1JRFB2TzJFTlRuZ0pXWmhoR1RMSlFCSW1rMlNTTVBQaXJZME5HQnQ1QVJwc01FMjNkSy9zZGt2cVJYUzN1NlZiWjU3L3FWdlNsYXh1YTdsTExiK3kxYnE2UzlVNTMxUFN2VStkVTZlbXg4Y25kTDgvZ0xqY0RmRThCQkJBQUlFbkYyajl3UERreitZWkNDQ0FBQUs5RUxBUDBBMU5GUGRmTmNIYUw3aEdZMVpoTWl1bktLVmhXeDNiZWt2UmwwS3lHWDFIa2ZSTG1pVHU1bXBsNW90SGp4ejkzaUs0TkJSWXVrM1hzZWdwY3ovYWU5WDgxLzc5UVhEZ2dEMll2bTV4UXJiSGxsNzI3ZXNiZVBUUkxWRzF1cVhpM0FaTkpMOHRpcVBMdFBLZFFTVWMwTUdGN2FGclhLb1Y3dEtRK3dHRmtVMEs0QmJzMVVzZmJGWWQrM1NBWkoxVjFPZjVOTlRiMXVaS01YY2p1Y3YvT0g5ZnMyQjJ4OFVEdmoyeHRROC9lYUU1dEM1UDluUHJjOXR4bTREZURzWGVyV1ArOXlqNW5kS2xFT2VYTFVORDI3V0RQMGV4MndMNVMvWElNL1Y3b044QjdkNTJnRXBmK25jaWlOMXptM05ORU5EbitiaUZBQUlJdEVWZzhSdDdXMWJLU2hCQUFBRUUyaXJnSjRyYnVXZndUZXF3K2xER0FycFYxTUxtL0RCeERZSDI4ZFhDYS9LQi9wUWV2VTgvM2FibkhRalBuUnRwRG8rMTE2Wkxlc0Jod2JEYTlNR0xmRS9meCt4N2V0dWUzbm83S1Y5YXpvdXNiS21IYklLNzJkblpnWFByMTIvU1VZWDFvWHJwZFdSZ1J5Vm9iTmNRZ3EwNkxYNmpSc2h2MVd1M2g3R0czb2R1cXliMFc2K05ibEw5QjNUL1puME5LR3YzNjhUOXF1N1RFUHlXNHJYZXRnSllFRnBpbWJ0MzZjZm42K2lmdVBTVDVsZmIzUDdDQXdCcG9kTHY4MDlQYnRuOUJQVEZLdm40T1QwZ1pnZTE3R3R1MmI1bno5Nm8wWGl4aFhMdE5TL1VzYWRodjMvcWh5U1UyN25uK2tIelR1aEZmZm82b2JrcW4zMThmSHhVdHdub2M1TGNRQUFCQk5vamtINGdhcy9hV0FzQ0NDQ0FRQ2NFZk9RS1hYUnZiTGtyNlQyMyt5NFVwRHBSaG91dDA4cGhVVThmMXBNaTZZTjlyS0hsR2xudTArY1dmYnRHdDYveEgvalhyenVrMFFCZkRDSjNTeFNIWHpwV3EzMUhyMi90eVV2RGhOVXg3U1cvMFBhOWpSNU12MS9vZWVuOXFWbFM1dVRlNUw3OSs5T2VlVnZYM0ZkemdqdWI1RzdGeTlEUTBJYVR6bTFVcitUR0tBclhOWUp3dlpBMkNtYWJmTFpZbU5lcC9CdTA0ZzJoYzV1ZDAvbjBvWHJzWXczQmo4TDFLbGkvQ3JKUjBjaHViMVprc2prSXJFZXpLbE9iQThBbTVhc0kzL3lUZXRpLy9yTHorcDR1Y3pwek45Skg1cjdicnVYWDRHL00zYjN3UnJML2FXREV3cEMzOEVuODFHTUJ2d2VvREJhZWJiSGZMVHZ3NVpmTmwxKythME8xK253WHVwZHFmN3RhUTE2ZUhWU2laSEpIMisyMVUya1VqSjd2OTZsSSs0UitILzJ1dFNEWXArdmpPd0lJSUlCQWV3V1NOL1AycnBPMUlZQUFBZ2kwVjhBK2FNZWFMTzNTMmY2KyszWGJMazFtSDViVEQrRHQzVnA3MTJheHozclgvU2QvZmVhdjZNc1dINEZWRFp2OS9RRTllcXZ1dTZYUjMzL2Y4VU9IL016d0xjVklEeWF2dEhlOVpSVXJ2dG42L3BqZVRyL2J5bHB2cHl1M3V0cVMxRG41bnR5ejFuODFPLzRscDA5dlhIZjJiUCs1S05yUVY2bjB4OVZxUmIzNW0rSkdvMTlERnJacGgxaW5udnp0VWFDejcvVWN4YXlxaFgyRnNMN1F4VHZVQldxOTk1cElUOUUvQ2plcVNEb21FT2k3VTY5bzJLOWh5OWJUYnpXejBRQzJiOWxCQUxPM3lOWnZyMVBOWnJWdVc4OERtaVR1S2ozR2tnMEIyeCt0emV6N3d0OFRuZGF4NjlGSDkycFd4NnZWNGkvVFU1Nm5KejNGOHJmYTBSclh2aWNIeVB3djV0eDZGdGNzL1p0REQvcGlHWDVHQUFFRTJpaGdmOGhaRUVBQUFRU3lMV0IvcTMzNFU4K3pncXlHb3NhYUtNNzNiR1c3NEJjb25jNjkxZ0dHSkF6TW43dWVCSVZSOWM1K0tYTGhMZXBodm1OaWZQeWhSZXRZU2UvNm9wZjI1TWYwZmZaQzM0TmcvLzZrWU1sNTlXbTR0L3RhYnlmUDZjeS9kbm04UGpzQW9OSExRVFN6YWJQYUoreXJWdnRtbzZnL2pHYmlvS0hlL1lhQ3VWMWVyOUc0WEZjVU9EVlJxOTNlbWVLdzFtVUkyUDVrWHhiS2JUK1o2eUhYN1dEbjhQQnVqYlo1Z1o1d2pYN2NyNmZzMVlFVk84Q2kvKzBmKzJYelBldjJldnV5ZFQzWlFrQi9NaUVlUndBQkJOb2dzSncveUczWURLdEFBQUVFRUZpamdQVmt6dTRjSHJ4Unc1ZC9JNFBub2ErbWVoWVNsdTVkdHdmaTJJYVZmMTA5djE5UU1MeFpKei9mYzNKMDlQaWlEZldpZDMxUkVUcnk0MUx2eitsOTZmZldEUzkxWCt2alptM0xoYjRuai9KdmxnV3NqZE13M1hwS1NCQmNjY1g2SFkzR014VzhyOU9UOXF1Wm42ZmZHYnZzb0c2MjlwTHJaMzhxaWcva3RyNlZMQVQwbFdqeFhBUVFRR0NWQXVrSG0xVytuSmNoZ0FBQ0NIUlRRSiszNzA0NnYreVRkeVlXKzlCdWl3V0hsUzVXaCthWjA4M3FxR2Rkd1Z6clZQMUNuWHNkaGo5aFh3b1pid2xqVjk4eE5QaGwzWDlySEVSM0hCOGIrNlplM3hwVXJBejJaU0hVeXBXR1VkM00zYkpVMlplNnIxMFZhOTJmV20rbjYyKzl6MjViV1JiMDJxWlA1SHZiQk16Wjl1ZFc3em56clQ5dzJRLzJ4Ulg5YmtUWHU5bVpGK3Q1VDFNdmVUT1E2eWNicFpKY2tqSDV2V2pmbFI4YUtsQW45MFVWbmdVQkJCQW9yNEQ5MFdkQkFBRUVFTWkrZ0gzSWpuZnUzdjAwblVGOG56NGQyOFJpOWlHNWwzL0hiV1puWFZmTmYxYWZVVm5zb0c4N3k1TmVoc3kybzhtcWRPWjA4N2lFWXZ4NWJlbHI2aHU4dmVMQ1d5dXpzL2M4K3Vpang3VDkxaVU5Q0wzd25OeldaM0FiZ1d3SjJPK1BuY1poUyt2QnAyRFhybDJiZy9Ycm45dHdicjkrNmE3Ujc0T2RTNjZKQnZWdiszckpreTB2OGE5K3kyZTBKWnZGZmFZeDIvaVJFNDgrZWxpM3JheHpCdzEwbXdVQkJCQkFZSTBDOWtiQWdnQUNDQ0NRZlFIN2UrMkNmVUhmanFORDkrb3orVFBVazI0ZmpOTVA4OTJ1Z1Q4NG9FSTlvQTAvUmVja1grcXZmMjZUVGRsRWNPME42bW5ka25QWExaSG8vSHNmMXROd0VyaWptbHI4TGozeFpuV2RmK0Y0clhheDNuVXJlOXJ6bjY2Yjd3ajBRc0IrcnhmM2tzK1ZZOWZRMEEvSG9YdVI5dTNydGF1L1FEdnVsWDYvVHdPNWhXTWJVcE1jdVVyWE0vZjZOdDN3Mi9DVEE5cnZXK3orWi9ENDQ2K2FtSmlZMXZxVHYwdHQyaENyUVFBQkJCRG96QWNvWEJGQUFBRUVPaVBnZTZzMFVkeWZxQy81MVQwOUQxMUJQS3hVTkp0MzhGdm5HbzNmV3hkRjcxZHY5aS9iaC9pV29KNzJZSGRDSXhuQ25vUVRQNFRYT3RrdEx1aXVHWDBkVklyL2duTExMWlh6NSs4NmV2VG9ZNHNLa1I1RXNQVVExaGZoOEdOSEJTelVwZ2ZXRnZTU2I5MnpaMXQxZG5hZkRqL3QxKy9XZFhyZXMvUTdaWmZWOHpuYy8rTVB6R2tWcXorWDNGYTNuTVVmRUV1RHVYNm5SbFNtOTA3V2F2KzkrV0xDK1hJVWVRNENDQ0N3UWdINzQ4cUNBQUlJSUpBUEFRdThzd3JvLzFvQi9mZDZHZEJ0dUtzbWhkYmx2WVAzVEk2TnZjdjR0ZzBQUDZNU3hPL1VmZi9jT3ZUMGdkNkdxR3UyZGg5R092MStrL2F1VzNDeHk0UHB1NzZTbnNiSGRPdHUzWDliRU1hM1R3eHMvM3B3OE9ENWxpYjNBVjgvVzg4NnZlc3RNTnhzaTREdCs3YVAyZmZGQjRTaTdYdjIvRmprR2xmcnNXdTF1NzVRKys1UXk3NXJlNlJHeXVnUmZ3VEtyMGRQN2VpUy9DNkZVVlYvWjdUbCtGdmEybTlQanRVLzFiSlZxNHY5cnJBZ2dBQUNDTFJad1A3QXNpQ0FBQUlJNUVQQTk2RHZHaDYrV3BkUStrTHo4N0Y5U083KzMzS0ZCbjE0cnlpRTN6SlpxNzljWlVqRGJhQURDSnJZemIxVGllTC84Si9pTGFnbmo2ZTlocDNXVHJhbndxV2hScjJBZnB2cTNkZmw2VUlMSExlcnhMZnErMWZVSTFoZlZDQXJweFY5Y1poYTlEUitST0NDQXEwSGZSYWNvMzNaWlpkZEd2ZjFQYytGN25ydG9GZnJZdlRQMUNraTYyeE50c3RhSXZaZmx0THR2MlJmN01idnVFMzNicjhmQ3VhNklsc2NIOUdtYnh5b1ZqOSsrUERoeDVzMXRZT0VWaC9DZVJPRWJ3Z2dnRUM3QmJyeEI3L2RaV1o5Q0NDQVFGa0Y3RU4vUExCNzk4NytLSHBBSDkxMyt3L1U4OE5sdSt2aUFnMXp0eUh0N3E4VmN2K3AzL2pldmYxcDcvU09QYnV2RCtMd0J2VUlYbWVQTmEvZGJqZTdGZFJ0VzdZMEE0OXVXZmhZMkxzK3BReDB0OUxHYlhyc3RnM09mYU5XcTUzMXIwcitzZmRKSzI5NkFNSkNPd3NDaXdYc2Q5UDJGZnRhZUdCSHZ4TzdqaC9mRzBmUjFZRkN1ZllrdXpMQnBaYS85ZnVyL3kyVTI0UncrdDY5WHZMVzhsdDVMWFQzK1FOWkxqN3F3dUREcm4vREgwdzkvUEFwLzBUTmZSR01CRFlSSkFzQ0NDQ0FRSWNGN0kyRUJRRUVFRUFnSHdMcDMyeTNZM2p3SmdYTDYvWGgzajVZZHp2d3ptczF6MFZmSXFUYnViVSt6TzRZSHY0blNpSHZVQjU1dnIxUVBYTTJrVnphd3ppL3J1N2NzcUJ0Z2QxNjE4MXpickk1bGNzZWUwaXVkMmlFd3MxNnpwZW54c2ZIRmhYTHJPMTFDMFBZb2lmeFl5a0UwbjNZOXBzRnZlUTdoNGQzYXg5NmdVYVNYS2ZjZmJVZWY3ckNyLzg5MVg1bU9NMWg1SDRmdFAzSjF0WHRaV0dQdVhNSzQrRWY5TTNNZkdqdWlnajc5aW1ZajFqZGZLRzdYVUMyaHdBQ0NKUlJJUDJ3VjhhNlUyY0VFRUFnandMcGVlZ2YwQkR6dC9ieVBQUVVUK2trT1IrOXRTZDkvcUNCZmJDM0FCUHNIQnI2QmZYTUthaUhlMzJ2WVcrRCtuenhrNE1jMW51NXFIYzlPS0dpanlpTzMrWWE3cmIxUVhELytQajRtZlNGK3U0RHZyNWIvZXlMRUNPRUFpK3R2ZVFXV3YxK2JmWGR2WHYzeHNmRDhGbmF0MStpdmVLbE9yanpQTjNlcm4xS3owcDd5WFdGQTF0NmQzREtiMTcvTEF6bWNhemg2K0VuNGpqKzdlUGo0NlBOSnpHVVBkWGlPd0lJSU5CbEFRSjZsOEhaSEFJSUlMQkdBUi9RdHc4Ty9sd1VoWi90ZVE5NnN6SktLa3VGZEFzMEZscDltZjFUN1RKeGorMytsNXFBK3MwS0tqK29ubmZkN1RweERYVy91UlgrazRUc3BYdlhiVlVQS1h4OVNaZTh1clZSbmIzenhHRi9IZWpXVGRDNzNxcFJqTnUyRDl1WDdSc0xlc2t2dWZ6eUs2cDlmUy9RN25LOUhuNlJIbjlhTWtTOEdjanQrZlA3a3Eyajk1KzViQ2k5djBSaHBGUGY5Y3NYQm44U3pNYnZuM3prRVp1WHdSYjdYYlhmV1E0Mm1RWUxBZ2dnMEFPQjNyOVo5S0RTYkJJQkJCRElzWUFQdmY3NnlJRzdYL1hZcUM4TER6My9lNjVDTkVONi9LZWFPTzQxVFdOZlhsKysvUnFLZjhET3RRMkNYYnQyYlk3WHJYdURTdjF2MU5PNHV6bnMxNEs2aFZ4N1RSWVdKUzBMWmFyWkUzclhuYTRCSGQ2cmliNXVxUVRSN1kzVHArK2ZtcHBLenRkTlNtN3RZWFd4dHJFdkFvOFFNcjVZbTdWK0pUM2V6VUp2Mzc1OVMyWFRwcXNhemwyckhYUy9kbzU5Mm5jSE10cEwza3FkN01jNktxYnlScll6YW8vOHk3QVN2M2ZpeVBpOXpTY1N6RnZGdUkwQUFnajBVS0RuSCtoNldIYzJqUUFDQ09SUndQNXV1MEFUVCswNGVYSkVJMmlma1pWZWRGOHVYUVpPdlloOTZwejdwQ2FPZTIwVE9BM3A5bU1ZdEFSMURRM2VlVDRNMytqQzBDNGRkNGtQNmpxdlhhRW43WTF1cnFMbjM1S1FiVDJpbHNoOEw2U2FRamQ5UjJRWUhOSkRYMVRMM0ZLSm9qc2ZHeHY3N3FJU20wSHFRRmhmaE5Qakg5Tjk3UWs5eDNZZ3JCSEdMdzVkZUozQzdRdlYrRmZxdTM0RG03M2s4NWRBczk5TGExLzducVZGdmZncWxLNjRZSVZTcVcrS2craTNqbytOM2RFc3BMOWZ0eGVNRG1nK3hqY0VFRUFBZ1I0SVpPMk5wQWNFYkJJQkJCREluWUI5cUc3b2NtWi9vZy9lcjg3Q2VlZ0xCT2NuanJ0UVNMZW5oOEcrZlZWTlFPVm5odGFRL1NIbG5qZnIvbDlUd04rUTRhQ2VWalhwbGZUcEo2ejZ6TzZEbTJXMzJNNVRmeUIwd2MzNmZsdGozYnA3ang4NmRESjlZZk83OVZoYTZHLzlXdlFVZnV5QWdIM3VTY08wclg1QkwvbldQWHUyVllMWjV5bVE3MWZMWEtmSGRWNTV0TkZlNFkvTjJQRVpPNEJrZCtnZ1RYTmR0cDZzTFg1NHZYNlhiRC9UNHI2b09yMzNXSzMydWVUbnVZTUpCUE1tQ044UVFBQ0JyQWpZbXhRTEFnZ2dnRUMrQk94RDk2d0MraHNWMEQrY3VZQ3VOS0FRMHdncmxXb1F1MDlNMUdxdmEvS21QY2l0MnBHQ2VpVU42bjdvZnVodTBCcCtTZUdpb3FEdTE2VUEzQXdhclMvTnpHMEwyY25NOEl0NzE1TkFkMFRaL2NzNmQvMFd1WHhob2w3LzlxS1NtNHQ5MlhvSVRJdHcydkJqR3NqdCsrSmU4bkQ3bmoxUGoxemphalhWUy9YNFQ2Z0poeGYxa2l1UXEybjhuWFBCdGczRjZzZ3FrdG5oRmN5dHVKcjQ3ZjVLRkx6djJHajlMNXBiUy9lMUJRY21PbElTVm9vQUFnZ2dzQ29CQXZxcTJIZ1JBZ2dnMEZNQjM0TythOC91RjhkeGVFZXpKQmJ1c3ZRM2ZTVWgzYXF3SURoY01qaDRWVFVLYmxCb2VxVUZEZlZlS25nb1hHVzcxN0xaRkNxcGxWV2xWcWlyV0xDek92Z2xqcytxb1I1UVV4M1FzUDdiWnVKNFpMcGVuMHhmMlB4dUJ5T3NQVnUvRmoyRkh5OGlZTmoyWmZ1VUxRdkM2R1UvZE5tbGpjZXJQNjVIcjFNRHZVU1BQMVB0MDI5UGJQYVNKd2VGMUhCYWk2MGpTNzlYVnN5bEZqdncwRkNSKzJ4ZjAya1hEMnYvZXQvVTJOaW5kTDg5Wm9zL3NKZmM1RjhFRUVBQWdhd0s1T0ZOSjZ0MmxBc0JCQkRvbFlDRmhuano1WmZ2V2xldDNxLzRzRnZKd25wZUxiaG5hVmxwU0xleVd4M3N2Y21IcWt2MzdINVJIRWZ2MUQwL1pROHFRS1U5ekZtcnF4VnZxY1ZDZHJOM1hiZWVPTmxjVGZmZVpjUGg0MHJsenFuUlVadE5PdzFVdWpsMzRNTFdrOWJkN21kWktKQUdjdnR1VHVhVkxKcXZZZGVKRTA5dlZJTDljcjVPamZCOFBlbHl5OTkyREtVWnlyVy82V2VMNUltNWZjL0RZdlcwMzVVK2pUaFJNSS9ycXRLTjY1MzdUeTJYQkxSZ3Z0QWtEeldqakFnZ2dFQkpCZkx5QmxUUzVxSGFDQ0NBd0pJQzZkOXV0Mk40OENabGl1dlZZMmFYVDdJUDRsbGJWaFBTclE1cEFQZWhkUHZ3N3BkSHpnZDE2L0cwSUdJVHlabEQrank3T3crTFBKYnVYVmRRUEs4S2ZGMVBPRkRSY1BqSDQvaWU2Zkh4aVVXVlN0dllRcnlGcy9rZ3V1aUpCZi9SMnQ2KzdHQ1ZHU3c0ZUxGOTkrN2hJSXArWE5jU3UwNXpsMStqRlA2amRzcUVudWNuOWJOL202K3gxOXRYK2p1bG03bFlGZ1J6aldVL0ZvZkJSK0pLMzBkT0hENTh3dGRndi80ZUhDQ1k1NkkxS1NRQ0NDRFFJcEMzTjZTV29uTVRBUVFRS0xXQUJUVTdELzBET2cvOXJSazhENzIxY2VaQytrVm1kMjk5ZnV0dHE2ZUZLZnNLdGc4Ti9hejZDZFdqSGo3SGZtNEc5VFJrMlYxNVdpeGsyZEI5ZmRmL2kzdlhnMkJjOTM5VjU2NXI1dTNnQzhkcnRXLzQ1OC9YME43RExYUW02MG0reno5YXZGdHBJTGZ2QzRhdEIxZGNzWDc3ek14Vk9tYXpYMUg3V2dYeTUrbjI5Z3Ywa3FlQlBJK2ZnZnp2a3Q5WGtoN3oweHFtLzRkUnBmS2hpU05ISHZGTm5nVHp1ZCtaNHUwRzFBZ0JCQkFvdGtBZTM1eUszU0xVRGdFRUVGaWVnQS9vbXYzODU2SW8vR3h6NkhlV2U1UFhFdEpOeE5jM3BkbXhaL0NYRlV2ZnBobTJmNnc1UkRscjExQlBpN3FTNzJuUXRuQmxNOFBiNGw5dkJ5SjBTNzNyNFIxaEdOOFNWZGQ5NWJIdmZlL29vcFdia1MzMmVsdVhmZVY1c2NxbllkcnFzcUNYL0pMTEw3K2kydGYzQWcxSWVKbHEra0k5L2pRYjVqMDNiRDF4c05la0IzRHkvSmxuWVRCM1R2dTcrMFExckh6dzZPam9JZFV4Q09neDl3ejhnd0FDQ09SZElNOXZWbm0zcC93SUlJREFXZ1FzZE1TYTlmeXA2b0xWcEdQQlJuMVppTW55My9XNWtMNk0yZDFWbFNjc1ZqYzdDT0Y3VDY5UXIrbjA3T3kvVkxYZnJHQzJSeUhXd2xrV3I2SCtoSW9zNDQ0a1lDZkQ0Wi9ZdSs3Y1kxckgzUzRNYm8waWQvdkV6cWQ4UFowSnY3bnUxTXJXa3diMlpXeTI1MDlKeTIwRldkQkx2bjM3OWkyVlRadXVhamgzclhiKzYxVDNxL1RrTFMyOTVFbUl0VitCK2NuZGJIMzVYcHdjTkRtaURrWnB4TDQxWmZocEYwWHYxWHdGQjVzVld6REtKTitWcGZRSUlJQUFBdmwvNDZJTkVVQUFnWElLMk45dkMxL1ZuVU9ESXdvcHo4cEJMN3ExbEpWNVZvRzZMNGdiSDV1b2pmK2FmcmE2MkplbGorVXRTVytoRDNEYnJyeHlhM1R1M0J2VTJmeHZkZDd4TGgvVWc2QUlQZXF0Rm1uUU5pTWRwRkJhczk1MS9hLzY2cjdRSnBjN29LOWJ0Qi9jTTFXdjEzUzdkYkVERzZteHJjdStzckJZbWV4Z2szMjNNaTNvSmQ4NU9QZ2pjZVJlckd0NFg2dG52RmhQdThMWE81M2N6WjV2UXlpVVh2VmEreXJLb29NTituMlFpdXBiYVRiVzMraSs5MDdXYW5jM0swa3dMMHByVXc4RUVFQ2dSY0RlRUZrUVFBQUJCUElwWUtHcnNXTm84TDhvOEw0bTQrZWh0d3JQOWFUcm5QVGZWdUI0bXg2MGNMWFM0QmpxR3VyVnRPZjRzc3N1dTNTMnYvOU5TcXkvTG8rQmxxQnVRYVpJNzNlSjA0VjcxeWMxY2VBOWV0SnRDbmUzVHF4YjkvWGc0WWZQdFRTQVdkaStZK3V4d0cvZnU3bWsyN2R0THVnbDN6STB0TDB2aXA4YnhORkw5ZGkxS3RvejFKYWI3SW5OVXhtSzJVdHVGWnhmL0VFS0MrWjJsK3A5aTFyb2ZaUDEraTNOcC9qN2RYdkJ3WXptWTN4REFBRUVFTWk1UUpFK3NPUzhLU2crQWdnZ3NHSUJDNTZ6TzRhSC81VTZVMzgvUndIZEttbzloSTJ3RWxVVjBqK2drUDUyM1pmMmdDNi9KOTNXWk9GN3Z3TG5nU1RzWGZLVXAveEFwUnE5VlpPci9RdjFNNjh2Mk5EM3BNWUwvMDJEZHJOM1hmT1crOTUxdXg1MmJJODlwTUIraDNxaWIzS3o3aXZIeDhkSEY3N2NoM1g3UEpDdXA5MkIzZHJWMW05ZlZzYlc5cTFzR3hyYVd3bmRDOVVQZnIyZThnSVZmYmU2alMyWk5rTzVCZEZDOXBLTFlzSGlSd1BvZ0lUOVhsdU52eEpHOFhzbVJzZi90dm1zMUpGZ3ZvQ05IeEJBQUlGaUNkaWJKUXNDQ0NDQVFENEZyQ2V0c1czMzdoZHBvcmc3bTFXd2NKV1h2KzBXMG1PRjlJcEMrdnNWMG05UTJTMkVXQjFXRXhMdHRmYmxlMlczNzluejlOQTEzcVkxL1pKQ1R4SldkVkJBT2o0QTZYbEZYQks3Qy9hdUI4ZURVRFBEQjhIdE9wMzUxbzFoZUgrdFZqdTdDTUo4YkQwV3BGZlREcmE2dEMzczlRc0M1ZVdYWDc1cnRsTDVDWjFEZnIyQ3VJYXRCOC9TQVlVK2UxR3psOXl1RzY5dEs2WGJmOG4rbkpkOTJxcXgwaVdwcjRLNUhWalI3OEkzTkJIZ2V5Zkd4ai9UWEZGcWFZNnJiWStWbG9ubkk0QUFBZ2owU0tESWIzZzlJbVd6Q0NDQVFOY0U3SU43UExCNzk4NytLTHhmZVdaUXdjWSt4S2REWUx0V2tEVnM2RUloM1ZiWjJ0TzZrazJrZ2NZSDlaMTc5dXh6Y2VNRytmeXN2ZWtwQk5xbHplejhYbk1xK3Z0Z0dyVE4wdXJiMnJ1dUg0UHZLQU4vUVRhM1ZLTG9ycU5Iam56UDdteFpVcU4wUFJjS2lHWnVsdlpsMjVwdnU2YytkZDNPbVRON1l4ZStKSXFENjdXQzV5dUlYbXI1VzQxaDdXR3hVMjJsNzhVN2wxd1VGMXpNeUg1Zisrd0FraVpPL0s0T250dzRNVmIvV1BOK2U2RWRMUEg3c2YzQWdnQUNDQ0JRZklHaWZ6QXBmZ3RTUXdRUUtMTkEramZjN1JnZS9MeUMxc3ZVKzJZelB1ZXRoL2hDSWQzQ29IMnRka25EWlJMVWg0YXVjYUY3bDV5dXR4VXFHS1k5dS9hOE1peUo1M3p2dW1ZR3QxN3FabEFPZ2xQU3ZrOUd0MVRDeW0zQjJiUDNIenQyN1B1TFlOSjl5K3hzLzdOZ2J1dE5MWFZUMTZzZkhCelN0NS9VRTY3VklZRnJoUDJqQ3FIZXVUazNRTkpyYk51Zlg0Kzl0QXlMZWRrKzZZTzVmbWNmRWNLSHduUG4vcWpGMjV6TmRDMzd2MTdPZ2dBQ0NDQ1FOd0Y3WTJSQkFBRUVFTWl2Z0gyUW45MHh0UHQ5WVZSNWU4N09RMjlWdjFCSXQrZk05OGEydm1MNXR5MFlXdER4NjlHbDZmNmgwdUU3bFEzdDJ0azI5TjB1eldidmgyVUo2bGJ0ZEdrTnloYllyUmZiaGxuYnQwUHEzUDZpd3JYMXJ0LzUyTmpZZDlNWExmNitlL2Z1alkvclNnSjZ0UVh5L1hxTjlaSnZtd3YvdnBkY0I0OXNLVmN2ZVN2Vm9tQWVIOWZSa2Q4NzU5eEhwdXYxU2Y5RXJtWGU2c1Z0QkJCQW9KUUNCUFJTTmp1VlJnQ0JBZ240Z0w1OWFPaG5vekQ0YjgxZTRid0d6UXVGZEFzMjdlaEpOQ3NMNlVsUUg5NzlLdWZDRzNScHRtZjdZZFpKVUUrSHh4ZG9GMWxXVlJMamx0NTFCV2xiSks5bWNXNWFOeC9RazI0UDQrQ1crT3paa1hqZHVtM1ZTdVZGNm5GL21WckhEbmI4aUIrcW5UemZOcHBlQXMwK2E2UkQ0TzMrTWk1MjJiOW1qM21zYy83RC82U2ZQNmg1RitvZVk5KytQbDJOd0hyTTEzb3d5cStPZnhCQUFBRUU4aXRBUU05djIxRnlCQkJBd0FRcytNU1hEZy8vVU1QRkQraTJYWkxLd2xaZS83NWZLS1NyU20wTEwvNmdocTFRUzBVOTZyK2lidVMzS1Z6K3NQVWNxL3ZZZXRUTEd0UVRsZVRmcFh2WGs5N3dJekxhcWdCL2lYOXFHc3JkWEMrNUhTVEs2ejdZYXJDVzIzWmtRNU1TaGhYdFc2R04xRkNQK1I4TDVmM0hhcldIbXl0ZWNOQm9MUnZqdFFnZ2dBQUN4UkRJYXk5TE1mU3BCUUlJSU5BbWdkT25UbjEvMDVZdFA2L0FkSmxXYWIxd0ZqRHp1Q2pENkwvWTJlenVMOWt3c0dYOTJWT25ibFpGMmhuMnpNZldaK0dvY2ViVXFmdTJiTmo0U1JlR3gzVHZNOE5LNVJJRkszdmNlajNMM1BPcmx2QUhLc3pDRHB5b1J6eE83Q3lZTzdkZTdaVGVseHdVc210M3o3OUdMeXZwWXBQZWVUMDc3OTdHSWJnL3IraHFBc2ZxOVk5cGY1dVNpdTE3dG5DZWVlTEF2d2dnZ0FBQ1RRRUNPcnNDQWdnZ2tIOEIrMXMrdTJIckZsMURPbnAyRUN0RUpTRXByelc3VUVodjkwR0hKR3p1Qy9wT2YrZjA0MmVtcCs5YXQzM0hKNk5HL0xnUzZUUFU2emxBVVBlN2tBVjBhNU9vSlh5Ym5kMmIzbGZtQXhtZXd2K1RYTWJQaFZGWXRWeXVVd1ArWGdjMmZtV3lWdi8vVGs5UEg5VnpDT2J6V3R4Q0FBRUVFRmhDZ0lDK0JBcDNJWUFBQWprVHNML2w4Y2F0bHd5cXErNGZLbFRtUGFBYmZ6T2t4dzNyU2Q4NHNDVlV6K050dXIvOTcxdVBORWNjN0F1cWozL3J4Qmx0NS9hTjI3Yi9hWkJNOHY0c0JmVU5QcWpiOE8xOEgvZ3cxM1l0U1dodjE5cnl2eDZOSkFnc21OdEVlNUZ1Mys2aStOZW14c2JmZlhaNnVxYnEyWDVyQnpIb01jOS9XMU1EQkJCQW9LTUM3ZitnMDlIaXNuSUVFRUFBZ1NVRS9CRGtEWnMzOStteDF6WkRaSjdQUTArcmFJT0UwK0h1MTI3WVBIQmVZZWNMZXJBVDcxMHVTSUo2R0dnbTdUTVBuRHgxNXRUMDU3ZGNzdTNQZFc3L2VoWGoyUXJxZlFycTZYbkZCTlMwbGNyOTNTYkNpN1Z2VkMyWTY1ZHVST0g4MXpYNTI5dlBucHcrSkJvTDViYS9Fc3pMdlo5UWV3UVFRR0RaQXAzNGtMUHNqZk5FQkJCQUFJRzJDUGlBWGgwWU9GdUp3bDlVcU4yaXRkb1FaQXNIZVYrc0o5MW1FbmZxU2IrK3d5RTlzVG84WjFjNWZmTGs1TmxUMDMrM2Z1dld2NHFjMjZZblBGTmhMSEZOaGpNWHdUanYrMGd2eW04VDZEVjBCWUNxN1E4NmF2TXQ3VFZ2MFZEMmY2VTVFeDVVZ1d5dnRlSHM5bnVZbkE2Z0d5d0lJSUFBQWdnOG1RQUIvY21FZUJ3QkJCREloMEI0Zm5yNnpNYXRXLzZCRXUwUHFSZFB3OXdMRWRCTjM4Sk9kME82VFlvMmY1Q2o4dmlwVTQ5cTZQdGY2alNDejJuQ3I4dDFFT1JwemFITXlhV3hrc01JU1RsOVlmbW5vQUlXdHUxNjdsVk5KcWlETSs2d2RzOTNUYTViLzMrZFBYSmtwRmxuZ25rVGdtOElJSUFBQWlzWElLQ3YzSXhYSUlBQUFsa1U4S0ZnNDVhQnA2dEg3OFYrdHUxaW5TL3QrOUhuZXRLM2Fyajd5WTROZDI5dDN6U28yL3RscE43Um1vYStmMmJqd01BZCtubVB6am0rc2huVTdZQ0lQWmNlOVZhOTR0eTJ0azJDZVJSVk5QdmJZenJaNGQxdS9ZYlhUaDArZkdjd05kVUlkR3BFY0hqdXdFNXhhazVORUVBQUFRUzZLa0JBN3lvM0cwTUFBUVE2Sm1EQk1ONndaZXNsU3JLdlZFeHdCZXBCVDlIbWU5TERMZzEzVDdlYzlLaGJNUXBmZkFBQU44OUpSRUZVU0xQM3pWRG53aC9TMFBjLzNyaDE4MzBhZkgrbGd2cHdFdFQ5UkhJRTlYbTN2TjlLZzdsZHk5emEvcVIyaGQ5ZEY3dlhQRmF2Zi83czFOUzVZTisrdnVDUlI1ekNPVVBaODk3YWxCOEJCQkRJZ0FBQlBRT05RQkVRUUFDQk5nbTRnYTFiejhmT2FhSzRZSjNXYWVHaWFNT3VGL2FrZDNiaXVLV2F4VXh0c1JFTGdYclRIMVN2K3NjM2J0MzZiVDN3TklXNHkzVzNadkgyUWQyZVVqUi9xMU01bHFRTmZUQlhqL2s1OVpoL1ZGY3dmTTFVZmZ5dnBuVTZTYlBIUEZBNHQ5TWNXQkJBQUFFRUVHaUxBQjhjMnNMSVNoQkFBSUhNQ0ZSMkRnM2VvM09rbjZONTFTdzRGUFZBckFWbFhkWktFM1ExNG5kTTF1dnZhOWJWZWpIVEVLMmJIVjhzcU52UVoxdXFPNGNIWDZkTS9oYjVYK2xpWDhRWjNXOXR3TkIzRThyK1ltTlBHanFzWXBkTHMrdVkyMGlVUHc0YTdnT1Q0K00yK1pzdC9uUVNmYWZIM0hQd0R3SUlJSUJBT3dXSytzR3RuVWFzQ3dFRUVNaUxnUDFOYjJ6WXV1VUZPdjM4cWtEZGZRcUtSUTJHdmU1SlQvY0pDMm4rMG13YTRqeXJIdld2RG16WThBbFhxUnpYL1RiaisxYjFwbHRaTGFoYlczQmdYQWlaWEp3T3ROaUYvWFF0Yy8ycjYvdTV6NFlWOTB1VG8rTWYxU2tORXlxekJYTnJQeTZabHNrR3BGQUlJSUJBTVFRSTZNVm9SMnFCQUFJSW1JRDlUWTgxMC9oVGxDNStXajJCUlR3UHZiV2xrN0RielV1d3RXNjk5WFp5L3JHVnAzcjY5T2x6bXZIOVM3cnMzYWVxR2hxdHNHZlhVTjlFVUc4Rnk5UnRYY3ZjUm1PRWRpM3pVRGR2aW9Mb1Z5Zkdhcjl6NXVUMEl5cXAvVjdad1JXQ2VhYWFqY0lnZ0FBQ3hSUWdvQmV6WGFrVkFnaVVVOEFDb3Rzd01LQ2VQdmM2OWZWWnFMQngxa21RTGFhSnIvUGM3TzREVzg3cG5QQTdWTlYwR0hLM2EyMDk2cEVtRHF1ZWYraWg3NStabnI1dHcrYk5uOVlCRXl2blZRcnE2M3hRVDg1dkx1cm9obTZicjNaN2FUQzM0ZXhxQzNkbjZNTFhUOVRxLzE0SFdFYTFVb0w1YW1WNUhRSUlJSURBcWdXSy9LRnQxU2k4RUFFRUVNaXBnQVcrZUdCd2NFZC9HTnlubnR0aGhjRWluNGZlMmt6ejU2Uzd4cTlQam8zL2dSNjBrTjdMWGs5ckQvdnk1Nmp2R2hyNllSWHliZXFoL1JVRjlZcUxkWks2dFUrb0lkWEZQb2lpNm1WcVVURFh1ZVZSWkQzbXVobmZxNU1RUGpBMVd2K0xaaW50czVHMVNUcTNRS1lLVDJFUVFBQUJCSW90UUVBdmR2dFNPd1FRS0pkQStqZmQ3UmdhK2wvS0hxL1FSR1YyWHEwRjFUSXMvbnp3NWpEbE4weU8xZjlJbGJhNjl6cG9wUUU4Q2VxRGcxZTVLTGhCRWZHVlNVQjBzY1k1MkhYVXk5Sk92ZG9YNVN6ck5Kakg4Y05SR0wzdjJOallwMVNnWkM2QkpKajM4cUJPcjJ6WUxnSUlJSUJBUmdUc3lENExBZ2dnZ0VBeEJLd1gyY0tnK21QZFY5VXpxeHQyVjJrV2UwOXJUcndkL3FGbVZIKzlmclpRYk1FM1BYaWhtMTFmTFBCWk9heHRLc2ZxOWZzbnh1cXZxa1R1eFNydDM5dndhanYvV1kvWjgreUxwYjBDRnI3OUpIMWhwVktWK1pnR0w3eHBvTnIzVElYelQrcXhPTmp2OXhIN1piRjJLdFV2amVyTGdnQUNDQ0NRSVlIa2cxeUdDa1JSRUVBQUFRVFdKR0FoTmQ2NFpldFdKZEpYNmJhRmpUSWRqTFVnYmlFM1V2RDlSeHUzRGh6VnpPcDM2MmNMd0JiVWVybFlXOWlYdmZkR3AwOU9IMUhaUHIxKzY5WXZhMmF5SDFCNWY5REN1cDVobC9rcVc3dDFvbDNtVGlHd1V3cDB6YlFKM2ZHK3VIL2RyeHcvY3VUMkV5ZE96QWI3Z3I3Z0VWa2Y3dm0rMFluNnMwNEVFRUFBZ1J3SzlMSkhJWWRjRkJrQkJCREl2SUFQNkpmdDJYUGxiTng0UUtYZHJDOExlMlg3ZTI5aDNFSzZWZi8vVm8vMVIzVWo3YVUyanl3czZVRURmK0JBcHlYOE00MThlS2ZtazN1dUwyQWM2L1FFWHdFT3BxK3N0ZEpnWGxVd0QzU3UvN1F1Wi9EUlNyWDZ1OGNPSDM2MHVhcXM3UXNycXlIUFJnQUJCQkFvckVEWlByQVZ0aUdwR0FJSUlMQklvTEp6YU5DR3VWK2xNZC9XbzF6R2tPZnJ2VVJJOStlQ0wvTHExWS8yUG14dFkyWDF1WHpIbnNGZlVuL3VEUXFYUDJwem1lbDY5aGJVN2NCTG1VWkNxTHFyV0pMWjhaTmc3cHlHdGJ1UFY4UEtqVWRIUncvNXRWbVArWWkzN3ZWb2lsVlVqcGNnZ0FBQ0NKUkJvSXdmMk1yUXJ0UVJBUVRLTGVBRDM0YXRXMzVTdWU0cUJUeE5RT1lEWHRsVS9HZ0NWVm9aL1FuRDNiUFNpMjV0a29aRjM2Tis5dVQwQTJlSDkzeHN3K09QUDZZZTlhZUhVV1c3enB1MklHL25VZHQzRHE0TG9XVlJqN2svTFNEUU9lWVZtNFZBUDMvR1JkRXZUbzNWUG5YNjVNbmplcTdaQmhyT1BuY2d4UC9NUHdnZ2dBQUNDR1JNZ0lDZXNRYWhPQWdnZ0VBYkJPeHZlN3h4NjViZENxWS9yYkJpTTRTWHRmZlZ3cXlGc2l5ZWs3NjRxUzJvVzNtcndiRmpNN3FlKzkwYkxyM3NQd2N6czZkMDM3UFZvejdRRXRTdFBRbnF6VW4xTk1sZXhRN0R5T1J2ZEN6cU5aTzEydStmUFhueW1MZE1uQWptd21CQkFBRUVFTWkrQUFFOSsyMUVDUkZBQUlHVkNsaFFjUnNHdHFqWDBMMVdNYzcrMWx1UGNWa0RYVjU2MHROMlRvTDZ2bjE5Wnc4ZVBLdWdmdWZXalpzKzFZakNHWVZRQytvYkNlbzY2S0orY2d2bU5qeENuZWEzYUtLOTEwM1c2dTgvYytyVXVDQnRuN2QySjVpbmV4WGZFVUFBQVFSeUlWRFdEMnU1YUJ3S2lRQUNDS3hTd0FmU2djSEJIZjFoZUw5aStaQUNuUVdWc2grVTlRWkpSK3VDaWVPeWRFNzY0aWFQTk5ONFJlZE4yL0QyWU52dTNYczBGT0J0Nml2K0Y3cWU5M3BOZ0taREwzYXRlMytadHNXdkxlTFBhVEQzUTlZVnpMOFNSdTQ5RTZQamY5dXNiTHFQVzF1eklJQUFBZ2dna0R1QjlJMHNkd1dud0FnZ2dBQUNGeFVJejA5UG45bTBaY3ZMRmVhZVd2Smg3aW5Vd3A3MExWdnE2bTM5YXFDZTZ1Q1JSOUx6d05Qblp1VzcwM25UVmpZcmUrWHg2ZW5qWjZlblA3ZGg4OEJmNnNETGdPNTdWdk84NjFodGJKZG5zd1B2UlR6NGJnYitRSVJHRUVRNnkvenJZUmkvYWJJMi9xWXpKNmUvM2F5emhYWjZ6SVhBZ2dBQ0NDQ1FYd0VDZW43YmpwSWpnQUFDRnhPd3NCSnYyRHJ3WXpvbjl5VjJyU24xc2xySUsvdGk0ZFZDWENTUG45bThkZk9EWng3ODl0ZWExOFBPYWtpM05yTlRGS3g4OXI1ZFVVaC83T3lwNmIvZWRNbm12M2R4c0ZOMWVicEdCbGo3cGhPbUZhV3RyZDVwTUs4b21CL1NnUFliSnNmcXI5YzE1TCtteDJ5eGZUMzE4WGZ3RHdJSUlJQUFBbmtWS01vYmVGNzlLVGNDQ0NEUVdRRVhqbWdJdFBwVS9RUmFuZDFXZnRadUlWZERwVzMydk9qUGR1MFpmS1VmUW02WDRNcitZZ2NYYkVpK0Qrb1RvNCtNNkx6cm45WFJocGNvbWQ5a0lWMy9WWDF2ZW5JZ0l2czFXcnFFZGpEQ3oxcXZIdk0rdFZWZEI1bmV2RDZPbnpreFd2K1BlbXcyMk4rY21UM3hzSURPZ2dBQ0NDQ0FRTzRGaWpnTUx2ZU5RZ1VRUUFDQk5nallBZGg0NjU0OVYxYmp4Z082dlZsZkZtTDR1eStFNW1KaFY3Ti8yeFR2d2F1T2pkYi93dmVrTjgvM1RwK1U4ZS9wU0RpclM3QnRhT2lub3NDOVMwSDloZmF6Qms1WTc3TzFlZm84dXp2TGkrMmpkZ0NpVDhIY3luOWNvL1kvZk02NTM1K3UxeWQ5d1pOcm1kdHpDT1VlaEg4UVFBQUJCSW9rd0FlMUlyVW1kVUVBQVFTZUtCRHRHQjY4UnlIbnVacFFLd21rVDN4T21lOXBoblJkaHk1MGVRM3AxbjRMenIvZVByejdWWkVMMzZhSjVKNWpsd1VQa3FCdUIyMnlPbkp1Y1RBL284TUs2aW1QYnB3WUc3TloyUU0vVjhESUNNSGNZL0FQQWdnZ2dFQlJCZkp5Ukwyby90UUxBUVFRNktTQS9ZMjM2NkgvcEVZK1AwY2hqZlBRbjZodGdkVkNlcVNFK1BPYkw5bnlyVE1QVG44OUIrZWtMNjZKRFFtM2crNytmR3lkbi80Tm5hUDk4ZlVEVzBiVkQvMWpta2h1bDM4OG1mSGRYcHVkQS9SSm1TcnFNYS9ZalBTNlhOb25OV1QvMVJPMSttYzBpZDkwY3hLL1FCUDUrVkVDVm5nV0JCQkFBQUVFaWlwQVFDOXF5MUl2QkJCQUlCbldIRzhhMkhLNXVvZi9rUVlFTzhXeXJQYWc5cks5V2tKNnFKQStrTmVRYm9iSlJIZDJmdmJob0tGcnFOKzNmY3ZXajU5M3diRXdjTTlRVUw5RUlkakN1VCsvVzk5N0ZkVFR5ZXdDSDh5dElMSDdzemdNWHoxVnEzMWN3WHhLZDluQmhqU1lNNXpkWS9BUEFnZ2dnRURSQlhyMXhseDBWK3FIQUFJSVpFSEFEc0kyZGd3Ti9iaE8xNzFMdCsxdnZnVWQvdllMWVltbE9kdzkxK2VrdDFZcjFFaUFhbm9OOVV1dXVPS1NhSGIyalFycWIxUW8zdUd2b1o0RWRRdkMzZHduekZsbnhpZFhGZEFRL0wvVEtQejNUdFhyWDI0VzNvOEMwRzE2ekpzZ2ZFTUFBUVFRS0k5QU45K1F5Nk5LVFJGQUFJRnNDRmpQc0UwVXQwMFR4ZDJ2U0xSSHZhZEpDTTFHK2JKWWltWkl6LzA1NmEyMlliQmZrOFFkOEpPdkJaZis0S1dYemM3MC80YUMrdXNWMUFlYVFiMWJCMjZjSlhNcm5JTDVBWjFZOEo3SjBmR2JtNFZOUi9VUnpGdGJqOXNJSUlBQUFxVVNJS0NYcXJtcExBSUlsRXdnL1J2dmRnNE5mVTU5cEQvbFlxZFp2WnREaDB1R3NZTHFOa042UzA5Nk10emFKaWpMOHhJcHFFZHBVTDlNTS93M1hPT3Q2cjMrVlZXcVgxK2REdW5wK3U5VEIvcHZUZFpxZjlYRXRBTko5cFYzMzJaMStJWUFBZ2dnZ01EcUJld05rUVVCQkJCQW9KZ0NGb2lTWHNrb3VFYzk2UHJSN21KNUVnRi9hb0JSeFM3OGMzK2RkQXVQKy9ibDRUcnBGNnRhM0F6bjl0NWZQVG82ZW1oaXJQNTZuUXorRmQrcDdUbzZwRHdKNTJFWVY0UHdsNXZoM0p4dE9MdWROMDg0RndJTEFnZ2dnQUFDQkhUMkFRUVFRS0FFQXBvWDdGNk5LYll6Zi9tN3Y3ejJib1owcDVBZS9MbGRYendZR1prSjl1NjFudWE4TDJrZzlwT3c2Uko4M1J0UzdqU2d2bEx4MnhXaUhURWltT2Q5YjZMOENDQ0FBQUp0RmVDRFdsczVXUmtDQ0NDUU9RRS9xM2MxaXI2bWMzNm5WVHI3dTA4Myt2S2FhYTRuWFpjcSt4ODdCd2V2RFE0ZVBGK0FudlMwOW1rd1QwK0ZTTy92eFBmNWJZUzZrRnF5cE44N3NUM1dpUUFDQ0NDQVFDNEZDT2k1YkRZS2pRQUNDQ3hid0FmMG8wZU9ITkVJOSs4MDUrZnk5eTE3RGVWK29xN043WHQ1cTdvNDJlZDlTTGVlOVB3UGQyOXQxVzRFNVc1c283Vk8zRVlBQVFRUVFDQ1hBZ1QwWERZYmhVWUFBUVJXSkdBOXdiR0d1ZHRNN243NjdCVzl1dXhQdGtuMTVrUDZUUVVONldWdlplcVBBQUlJSUlCQUpnUUk2SmxvQmdxQkFBSUlkRlRBRHkvV3lPSjdrcTBrbDducTZCYUx0dkw1a0Y0cGNFOTZKMXR0Zm9oN0o3ZkN1aEZBQUFFRUVNaTVBQUU5NXcxSThSRkFBSUZsQ1BqaHhUWlJuS2JvaWpVMWwvV29NK1I0R1hBTG5qSWYwbTI0T3ozcEMzQ2U5QWYydHljbDRna0lJSUFBQWdna2t3WGhnQUFDQ0NCUWJBRWZqbWFDNEdGVnM1WmNiczFmMnFyWXRlNUU3ZVpET2ozcEsvT2xCMzFsWGp3YkFRUVFRS0NrQXZTZ2w3VGhxVFlDQ0pSS3dBSjZlS3BXbTlJbHRRNzZwS1NMWDVkS29KMlZuUS9wUlprNHJodmhtZjJ0bmZzZzYwSUFBUVFRS0t3QUFiMndUVXZGRUVBQWdUa0JDMGMyckYweDNYMDE2VUVuTDNtUDFmNVRySkRlaloyaEd3Y0JWdHVhdkE0QkJCQkFBSUhNQ0JEUU05TVVGQVFCQkJEb3ZJQTZ6a2NDcHp3V2h2ejlYeXYzd3BET09la1g5K3pHUVlDTGw0QkhFVUFBQVFRUXlJRUFIOUJ5MEVnVUVRRUVFR2lEZ0wvMmVUWHErNXB6N3Z0YW4vMzlKelN0RlhZK3BDZm5wQThON1Evc091bDc5L2F2ZGRWZGZIMDNlcmU3c1kwdWtyRXBCQkJBQUFFRU9pTkFRTytNSzJ0RkFBRUVzaWJnQS9yUkkwY09xL2Y4d1RDNTBwcS9MMnNGelYxNTBwQWVobFdOVVBpZk80WXZmMzV3OE9ENUhJWDBiaHlvNmNZMmNyZnJVR0FFRUVBQUFRUVdDeERRRjR2d013SUlJRkJjQVg5NXRkQUY5L3Z6ME5XVlh0eXFkcmxtUHFTN0dibXVEMXpsMXAzRFQzbGV6a0o2cDhIb1FlKzBNT3RIQUFFRUVDaUVBQUc5RU0xSUpSQkFBSUZsQ2FRaDZaN2syVWszK3JKZXlaT1dJOUFYeFBHc1F2cG01NklEaFBRRlpCd01Xc0RCRHdnZ2dBQUNDQ3d0UUVCZjJvVjdFVUFBZ1NJS0pDRXBETzkxY1J3SG9aL1puV0h1N1d4cERYUFhKSHpXazc2SmtMNEFOajA0dE9CT2ZrQUFBUVFRUUFDQmhRSUU5SVVlL0lRQUFnZ1VXY0FIOU5sSzVXR0Y4MUUvekoySjRqclIzbWxQZWw1Q2VqZkNNejNvbmRqVFdDY0NDQ0NBUU9FRUNPaUZhMUlxaEFBQ0NGeFF3RUpTZU9MdzRSTTZELzJnVDJXYTFleUN6K2FCMVF2a3F5ZTlHL3RBTnc0Q3JMNjllQ1VDQ0NDQUFBSVpFU0NnWjZRaEtBWUNDQ0RRQlFFTFlqWlJuSmJ3bnFRSHZSdlpMTmxpQ2YvTlcwOTZKNXVJSGEyVHVxd2JBUVFRUUtBd0FnVDB3alFsRlVFQUFRUldJQkRGOStwY2FlWDBrUGVCRmJDdCtLbjU2a2xmY2ZWVzhBSjYwRmVBeFZNUlFBQUJCTW9yd0FlejhyWTlOVWNBZ1hJSytFbmhacVA0NjRybnAwUmc3d1AwYm5aMlgxaTZKMzNmdnI3T2JqWlRhMmNmeTFSelVCZ0VFRUFBZ2F3S0VOQ3oyaktVQ3dFRUVPaU1nQS9vSnc0L2VrU3IvM2FZWEdtTm1kdzdZejIvMXFWNjBrZEdab0x5aEhSNjBPZjNCbTRoZ0FBQ0NDQndRUUVDK2dWcGVBQUJCQkFvcklDZGgrNDBVZHg5L2p4MFoyUGRXYm9nc0tBbmZkdlEwTE9DOG9SMDlyRXU3R0JzQWdFRUVFQWcvd0lFOVB5M0lUVkFBQUVFVmlxUTltWitOWGxoMG8yKzBwWHcvRlVJTkh2U05YSmhVeFM0bTNiczN2MmpKUW5wNlQ2M0NqUmVnZ0FDQ0NDQVFIa0VDT2psYVd0cWlnQUNDS1FDU1c5bUdON3I0ampXTmRGOWozcjZJTjg3THRBbjkxbUY5RXZES0x3OUF5RzlHK0daSHZTTzcxWnNBQUVFRUVDZ0NBSUU5Q0swSW5WQUFBRUVWaWJndzlKc3BmS3d3dmxvY3JtMWdQUFFWMmE0dG1lckp6MTJia2IybDRhVjhFQ1BRM28zd25NM0RnS3NyVTE0TlFJSUlJQUFBaGtRSUtCbm9CRW9BZ0lJSU5CbEFRdGs0WW5EaDAvb1BQU0RQams1Wm5MdmNodm8yRWpRcDlQL1o5UVVsMldrSjcyVEJOMDRDTkRKOHJOdUJCQkFBQUVFdWlKQVFPOEtNeHRCQUFFRU1pVmdZY21HdFdzSjcwbDYwTWxQaVVmWC8rM0xVRTk2Snl0UEQzb25kVmszQWdnZ2dFQmhCQWpvaFdsS0tvSUFBZ2lzUWlCeUk0Rk40aDZHdkIrc2dxOGRMeWxKVHpwSGdOcXhzN0FPQkJCQUFJSENDL0NCclBCTlRBVVJRQUNCSlFYOE9lZXpVZU1iU2s2bjlBeDdQeUJFTFVuVmxUdVg3a21mRytuUWxUSjBjaVAwb0hkU2wzVWpnQUFDQ0JSR2dJQmVtS2FrSWdnZ2dNQ0tCSHhBUDNINDBjT0s1UTlxUm5GN01SUEZyWWl3dlU5ZTBKT3VpZU8yRFE4L1ExdG82S3NJNzlVYy9HbnY3c0xhRUVBQUFRUUtLbENFTi8yQ05nM1ZRZ0FCQkRvdTRNOURkNkc3ejUrSHJobkxPcjVGTnZCa0FqWngzRG1kY1hDWnJwUCsrdWFUTy8xZTNZM2U3VzVzNDhsc2VSd0JCQkJBQUlITUMzVDZUVC96QUJRUUFRUVFLTEZBRXBwYytOWEVJT2xHTDdGSE5xcnVYTVdPbElSQnFCbmV1N0owNDhCTU43YlJGU3cyZ2dBQ0NDQ0FRQ2NGQ09pZDFHWGRDQ0NBUUxZRmZHaUtLdkc5TG80YlNvVFdvODR3OTJ5M1dWNUxSdzk2WGx1T2NpT0FBQUlJZEZXQWdONVZiamFHQUFJSVpFckFCL1JHWmYxMzFWdDdKTG5jR2hQRlphV0ZOTlM5U0tHV0h2U3M3RmlVQXdFRUVFQWcwd0lFOUV3M0Q0VkRBQUVFT2lwZ29TazhmdWpRU1JlNGIvbzBxQnNkM1NJclJ3QUJCQkJBQUFFRUVMaWdBQUg5Z2pROGdBQUNDQlJld01LNG55aE9aNS9mbmZTZ2s4OEwzK3BVRUFFRUVFQUFBUVF5SzBCQXoyelRVREFFRUVDZ2V3S2hDMGNDbThSZDA0ZDNiNnRzS1NNQzNSeEtIMnJvUHZ0WVJocWVZaUNBQUFJSVpFK0FOOG5zdFFrbFFnQUJCTG9wNENlRm0yazBEaXFlbjlTRzdYMkJidlJ1dGtEdnR0WDhEQkRXYmZTRXpuanYrQVNCWVJqT0JyT3ozMjlXbWYyc2QyM1BsaEZBQUFFRU1pcEFRTTlvdzFBc0JCQkFvRXNDUHBTZGVPU1JJNHJsRHlsQTJXWTdIdFM2VkRjMnN4eUJLUDdQTm5wQ0xkL2Z3YlkvSDBiKzJNOWZUOVRyMzlaMjdBZjJzK1cwRDg5QkFBRUVFQ2lWQUFHOVZNMU5aUkZBQUlFbEJmeDU2QzUwOS9uejBEVUdlY2xuY1dmUkJCcXFVR1Z5ZFB6bXdNVnZiWjdkWUczZjF1Q3NGVm80WDZkTCtkMVZPVC83MnFJaFVoOEVFRUFBQVFUYUtVQkFiNmNtNjBJQUFRVHlLZUM3elNNN0Q5MHZTVGQ2UHF0Q3FWY29ZQ0U5bXFpTmYxQUIraDBhUWVFUDF1aStkb1gwbVNnTSs3WHVBeHVDOExxalI0K2UxcnB0RysxYXYxYkZnZ0FDQ0NDQVFIRUVxc1dwQ2pWQkFBRUVFRmlsUU5KalhvbEhYQ05zYUt4ekdxQTRpTHRLMEp5OXpOcS9NbG12djIvSDRHQVFSdUY3TllqQ0FyUjlyWG9mc0o3ekpKeTdtN1h1VnpUWFo1ODdadlhGZ2dBQ0NDQ0FBQUpMQ0t6NmpYZUpkWEVYQWdnZ2dFQStCWHhBYjFUV2Z6Y013dEhrY210TUZKZlBwbHhWcWEzOUxZejdrTzVpWnozcDZlZUQxZlowTjN2T0NlZXJhaEZlaEFBQ0NDQlFXb0gwRGJpMEFGUWNBUVFRUU1DSDhmRDRvVU1uWGVBTyt2SHV1b0ZMcVFUYUZ0SzFvdk1LK0gwSyt2U2NsMm9Yb3JJSUlJQUFBdTBRSUtDM1E1RjFJSUFBQXZrV3NIRG16ejFXeCtuZFNRODYrVHpmVGJxcTByY2pwTTlFVWFSenpnbm5xMm9CWG9RQUFnZ2dVSG9CQW5ycGR3RUFFRUFBZ1htQjBMa1JQNG43L0JEbitRZTVWUWFCVllkMHZYQkdzN1Ziei9sZmNjNTVHWFlWNm9nQUFnZ2cwQWtCQW5vblZGa25BZ2dna0Q4QmY2N3hUS054VUVVL3BTOTdmNkFiUFgvdDJJNFNyenlrT3plcm52TytvQkgvMldTdDlzOVVDSDlPdTc0eklWdzdXb1IxSUlBQUFnaVVSb0NBWHBxbXBxSUlJSURBUlFWOFFEL3h5Q05IRk11L3FYT0lMWjZ2ZG9Ld2kyNklCM01oOEdRaDNSNzNYL3BuSnF4VXFrSHNQak5Sci8rZnpkclpLUk4yQ1RjV0JCQkFBQUVFRUZpQkFBRjlCVmc4RlFFRUVDaTRnRDhQUFFqZHZjM3owQzJBc1pSWHdOcmY5NFRiSmRoYVpuZHZIVjBSKzU1ekMrZTEyaTgwcVFqbjVkMW5xRGtDQ0NDQXdCb0ZDT2hyQk9UbENDQ0FRSUVFbWhPNFJ5T0JzMnhtM2Vnc0pSZFlLcVNMeEYrR1RRTXR3b3FDKzZjSjV5WGZTNmcrQWdnZ2dFRGJCS3B0V3hNclFnQUJCQkRJdTREdk1hODBHdmZGVVRnYmhJRzlSMWdQS2dkejg5NnlheXQvR3RKRDYwbmZQamg0SUlpaWdUQjJEWnRRVVBjZGFLNmVudk8xT2ZOcUJCQkFBQUVFL0ljdkdCQkFBQUVFRURBQkg5RGQrZk1QaCt2WEhYWmgrRlQxcFB2NzRDbTlRTG9mUkZQMStwZVgwTENET0p4enZnUU1keUdBQUFJSUlMQVNBWHBGVnFMRmN4RkFBSUZpQzFnSUN5Y21KcVpkcUluaXJLNHVDZTNGcmphMVc0R0FQeWRkejdmUkZkWmpidDl0VjJGQ1FTR3dJSUFBQWdnZ3NGWUJBdnBhQlhrOUFnZ2dVQndCQytnV3VteTV1emxSWFBJVC95SXdMMkE5NVhiNXRQUjcycnMrL3d4dUlZQUFBZ2dnZ01DcUJBam9xMkxqUlFnZ2dFQ3hCVndRZmRWUEZCZjZ5Y0NLWFZscWh3QUNDQ0NBQUFJSVpFU0FnSjZSaHFBWUNDQ0FRRVlFa3FIS2pjWTNkZmI1Q1pYSjNpZm9JYzFJNDFBTUJCQkFBQUVFRUNpMkFBRzkyTzFMN1JCQUFJR1ZDdmlBUGpVK1BxWVhQcVRMYUZrODUvemlsU3J5ZkFRUVFBQUJCQkJBWUJVQ0JQUlZvUEVTQkJCQW9PQUN5WG5vb1J0cG5vZE9EM3JCRzV6cUlZQUFBZ2dnZ0VBMkJBam8yV2dIU29FQUFnaGtTY0JQNEI0RjBZZy9EejFKNlZrcUgyVkJBQUVFRUVBQUFRUUtLVUJBTDJTelVpa0VFRUJnVFFKSmozbWpjWjh1Z3o2cmkyaFpqenJEM05kRXlvc1JRQUFCQkJCQUFJRW5GeUNnUDdrUnowQUFBUVRLSnVBRCtyb29lbEFWZjlpZmg4NUVjV1hiQjZndkFnZ2dnQUFDQ1BSQWdJRGVBM1EyaVFBQ0NHUmN3SHJMcTdWYTdheDZ6LytySCtHdXJ2U01sNW5pSVlBQUFnZ2dnQUFDdVJjZ29PZStDYWtBQWdnZzBCRUJQNlE5YnJqL29teCtTaUc5cXEwUTBqdEN6VW9SUUFBQkJCQkFBSUZFZ0lET25vQUFBZ2dnc0pTQTcwVS9QajQrR3JyZ0w4TEl2MTNNTHZWRTdrTUFBUVFRUUFBQkJCQm9qd0FCdlQyT3JBVUJCQkFvb2tEU1l4NDFQdXJpdUtFSzl1bUxYdlFpdGpSMVFnQUJCQkJBQUlGTUNCRFFNOUVNRkFJQkJCRElwSUQxb2tjVG80K01CRUg0TjM2eU9PY3NxTE1nZ0FBQ0NDQ0FBQUlJZEVDQWdONEJWRmFKQUFJSUZFVEFlc3Y5KzRRdWpQNFIzM1VlaHJ4dkZLUnhxUVlDQ0NDQUFBSUlaRStBRDFyWmF4TktoQUFDQ0dSSndNNDdqeVpxdFFNYTNYNlRldEdqd0s2TnpvSUFBZ2dnZ0FBQ0NDRFFkZ0VDZXR0SldTRUNDQ0JRT0FIL1h1RkM5MEZmc3pDczZEdm5vaGV1bWFrUUFnZ2dnQUFDQ1BSYWdJRGU2eFpnK3dnZ2dFRDJCZXk4ODNCcWRQd21wZkxQcXhjOVZEem5YUFRzdHhzbFJBQUJCQkJBQUlHY0NSRFFjOVpnRkJjQkJCRG9nWUQxbGx1dmVlREMrRWEvL1RBNU45M2Y1aDhFRUVBQUFRUVFRQUNCdGdnUTBOdkN5RW9RUUFDQndndjRjOUd0RjEzbm9IK09jOUVMMzk1VUVBRUVFRUFBQVFSNklFQkE3d0U2bTBRQUFRUnlLdURmTTJJWHZOdFpuM29ZVnZVdjU2TG50REVwTmdJSUlJQUFBZ2hrVDRDQW5yMDJvVVFJSUlCQVZnV3NGNzB5VmE5L1daZGQrMHdZNlMyRTY2Sm50YTBvRndJSUlJQUFBZ2prVUlDQW5zTkdvOGdJSUlCQXJ3WGlLSHEzd3ZrNWV0RjczUkpzSHdFRUVFQUFBUVNLSkVCQUwxSnJVaGNFRUVDZzh3STJlM3QxYW5UMG0rbysvMFBmaXg0RVhCZTk4KzVzQVFFRUVFQUFBUVJLSUVCQUwwRWpVMFVFRUVDZ3pRS3hyYTl5ZnZiOUxvNGYwOG5vZmZyUjM5Zm03YkE2QkJCQUFBRUVFRUNnVkFJRTlGSTFONVZGQUFFRTJpSmdZYng2OU9oUkMrZnZDU09ka2U0Y0FiMHR0S3dFQVFRUVFBQUJCTW9zUUVBdmMrdFRkd1FRUUdEMUFqYlVQWmlzMVQ2aWJINnZocnBYTlorN3YyLzFxK1NWQ0NDQUFBSUlJSUJBdVFVSTZPVnVmMnFQQUFJSXJGYkFMcS9tTDdQbWd1Z2QvbHByWWFDdWRDNjd0bHBRWG9jQUFnZ2dnQUFDQ0JEUTJRY1FRQUFCQkZZcmtGeDJiV3pzL3crZHYreWF2YWN3WWR4cU5Ya2RBZ2dnZ0FBQ0NKUmVnSUJlK2wwQUFBUVFRR0JOQXI3enZCSEhiM2ZPbmRDYW1EQnVUWnk4R0FFRUVFQUFBUVRLTEVCQUwzUHJVM2NFRUVCZzdRSnhzRzlmMy9IeDhkRXdjUC9CWDNhTkNlUFdyc29hRUVBQUFRUVFRS0NVQWdUMFVqWTdsVVlBQVFUYUtEQXk0b2UxVDR6VlA2VExydDJWVEJqbkdPcmVSbUpXaFFBQ0NDQ0FBQUxsRUNDZ2w2T2RxU1VDQ0NEUVNZRjB3amhkYlMzNHR4cnFycXV2aFg0Q3VVNXVsSFVqZ0FBQ0NDQ0FBQUpGRXlDZ0Y2MUZxUThDQ0NEUUd3SHJNYTlPMWV0M2hXRjRveC9xem9SeHZXa0p0b29BQWdnZ2dBQUN1UlVnb09lMjZTZzRBZ2dna0RtQjJFcTAzZ1gvVHFlaGYwdEJ2VThYWFdPb2UrYWFpUUloZ0FBQ0NDQ0FRRllGQ09oWmJSbktoUUFDQ09SUHdBSjZ0VmFyblExQzkwWmYvREN3OXhrLzAzditxa09KRVVBQUFRUVFRQUNCN2dvUTBMdnJ6ZFlRUUFDQm9ndjRvZTZUbytNM3U4RDlvWWE2Mi9zTXZlaEZiM1hxaHdBQ0NDQ0FBQUp0RVNDZ3Q0V1JsU0NBQUFJSXRBajRvZTdyR3U0dG10WDlRWWE2dDhod0V3RUVFRUFBQVFRUXVJZ0FBZjBpT0R5RUFBSUlJTEFxQVQvVWZYeDgvRXpvZ2pmNDhlMWhVTkdhR09xK0trNWVoQUFDQ0NDQUFBSmxFU0NnbDZXbHFTY0NDQ0RRWFFFLzFIMmlYci9OaGNFSE5kUTkxT1laNnQ3ZE5tQnJDQ0NBQUFJSUlKQXpBUUo2emhxTTRpS0FBQUk1RXZCRDNhZEdhKzhJWEh4dk10VGRFZEp6MUlBVUZRRUVFRUFBQVFTNkswQkE3NjQzVzBNQUFRVEtKT0NIdXF2Q3MySGtYdWVjYXdSaFdOWFBESFV2MDE1QVhSRkFBQUVFRUVCZzJRSUU5R1ZUOFVRRUVFQUFnVlVJekFiNzl2VWRPekorWHhnR2I5VlFkOFZ6QlhVV0JCQkFBQUVFRUVBQWdTY0lFTkNmUU1JZENDQ0FBQUp0RlJnWnNXSHQ0Y1JZL1hlRE9QNWNXS2xVMVlVKzA5WnRzRElFRUVBQUFRUVFRS0FBQWdUMEFqUWlWVUFBQVFReUxtQkQydjM3VFZqdGU2MUMrbU5oRVBicFBuclNNOTV3RkE4QkJCQkFBQUVFdWl0QVFPK3VOMXREQUFFRXlpclE4RVBkRHg5K1ZHZWd2MWJEM1cyeGZ6a2YzVlB3RHdJSUlJQUFBZ2dnME96UkFBSUJCQkJBQUlHT0M0eU0yTEQycWk2OTluZk9CZS9YK2VoMmtKaFozVHNPendZUVFBQUJCQkJBSUM4QzlLRG5wYVVvSndJSUlGQU1BVCtzZmJKV3U4SEY3blovNlRYT1J5OUd5MUlMQkJCQUFBRUVFRml6QUFGOXpZU3NBQUVFRUVCZ0JRSTJwTjB1dGFaTG84ZXYwYVhYSmpYU25mUFJWd0RJVXhGQUFBRUVFRUNndUFJRTlPSzJMVFZEQUFFRXNpcmdMNzAyTlQ0K3B1dWoveXJubzJlMW1TZ1hBZ2dnZ0FBQ0NIUmJnSURlYlhHMmh3QUNDQ0FRQkhZK3VxNlBQakU2L3JjdWNPLzI1Nk56ZlhUMkRBUVFRQUFCQkJBb3VRQUJ2ZVE3QU5WSEFBRUVlaWFRWEI4OW1CeXIvMllRTi81WDgvcm81M3RXSGphTUFBSUlJSUFBQWdqMFdJQ0EzdU1HWVBNSUlJQkFpUVhzZlBTSzFmK2NDMSt0YzlMSE5HbGN2MzVrWm5kRFlVRUFBUVFRUUFDQjBna1EwRXZYNUZRWUFRUVF5SlNBdno3NmRMMXVrOFg5Zk9DY2hYT2JSQzdPVkNrcERBSUlJSUFBQWdnZzBBVUJBbm9Ya05rRUFnZ2dnTUJGQkpybm8rdlNhMThKZy9BTk9oOWRVN3pyUHhZRUVFQUFBUVFRUUtCa0FnVDBralU0MVVVQUFRUXlLV0FoWFQzbkU3WGF4M1I5OU44TEsxRkZDZDN1WTBFQUFRUVFRQUFCQkVvalFFQXZUVk5UVVFRUVFDRHpBbjVZdTNyUy80M09SNzh0aWlLN1Bqb2hQZlBOUmdFUlFBQUJCQkJBb0YwQ0JQUjJTYkllQkJCQUFJRzFDbGhBOTVQR3pRVGh6emtYSDlha2NYMGE3TTZrY1d1VjVmVUlJSUFBQWdnZ2tBc0JBbm91bW9sQ0lvQUFBcVVSOEpQR25hclZwcUk0K0tlYU5PNWNFUHBKNHhxbEVhQ2lDQ0NBQUFJSUlGQmFBUUo2YVp1ZWlpT0FBQUlaRldoT0duZXNYci9mQmVFdnFCZmRDbXJ2VjB3Y2w5RW1vMWdJSUlBQUFnZ2cwQjRCQW5wN0hGa0xBZ2dnZ0VBN0JlWm5kdi92bWpUdVhaclpQVlE4cHhlOW5jYXNDd0VFRUVBQUFRUXlKMEJBejF5VFVDQUVFRUFBQVM4d01tTG5ua2VUOWZwN0ZOSS9xWm5kcStwQ1A0OE9BZ2dnZ0FBQ0NDQlFWQUVDZWxGYmxub2hnQUFDK1JlWUc5S3VtZDFmRzhUeDdaclp2Vi9WWW1iMy9MY3ROVUFBQVFRUVFBQ0JKUVFJNkV1Z2NCY0NDQ0NBUUdZRTVtWjJiL1N2KzhlNi9OcTMvY3p1aFBUTU5CQUZRUUFCQkJCQUFJSDJDUkRRMjJmSm1oQkFBQUVFT2lQUUNQWUgxZU9IRHAwTVkvY3p6Z1duQXJ2OFdzQTU2WjNoWnEwSUlJQUFBZ2dnMENzQkFucXY1Tmt1QWdnZ2dNRHlCUTdvV3VqNzl2Vk5qSTgvcERuZGYwYVhYMHQ3MXBrNGJ2bUtQQk1CQkJCQUFBRUVNaTVBUU05NEExRThCQkJBQUlHbVFITm05NGxhN2ZZd2pGN041ZGZZTXhCQUFBRUVFRUNnYUFJRTlLSzFLUFZCQUFFRWlpeGdJVDBJcWhOalk1OVJKL3JibXBkZnM5NzB1UW5saWx4OTZvWUFBZ2dnZ0FBQ3hSWWdvQmU3ZmFrZEFnZ2dVRVFCRzlaZW1heU4vM2JnNHQvVjVkY3ErdGt1eWNhQ0FBSUlJSUFBQWdqa1dvQ0FudXZtby9BSUlJQkFLUVdzdDl4NnpjT0pzZnB2NkJycG4xWlBlaC9YU0MvbHZrQ2xFVUFBQVFRUUtKUUFBYjFRelVsbEVFQUFnZElJV0VqMzcyRzZSdm92NnZKcnQ5bzEwZ25wcFdsL0tvb0FBZ2dnZ0VBaEJRam9oV3hXS29VQUFnaVVRc0FQZGJlYURsVDdmdG81TnhLRlliOSt0UFBVV1JCQUFBRUVFRUFBZ2R3SkVOQnoxMlFVR0FFRUVFQ2dSY0JDZXZYdzRjT1ByMnZFLzBEWFNQK09abmUzYTZRVDBsdVF1SWtBQWdnZ2dBQUMrUkFnb09lam5TZ2xBZ2dnZ01DRkJXeUN1T3I0K1BqRWJLWHlDdldrSHdzc3BEdkh4SEVYTnVNUkJCQkFBQUVFRU1pZ0FBRTlnNDFDa1JCQUFBRUVWaXd3Ryt6YjEzZnl5Skh2UlM1NHVjTDVtU0NNcXJyNEdpRjl4WlM4QUFFRUVFQUFBUVI2SlVCQTc1VTgyMFVBQVFRUWFLK0FYU05kSWYxWXZYNS9ITHVYNjlMb3MwRVlWTFVSR3diUGdnQUNDQ0NBQUFJSVpGNkFnSjc1SnFLQUNDQ0FBQUxMRnJDUXZuZHYvL0h4OFMrNk1QcHB2YzVtZTdmcnBCUFNsNDNJRXhGQUFBRUVFRUNnVndJRTlGN0pzMTBFRUVBQWdjNElIRHg0M25yU3A4YkdQdStpNEZVNkg5MjJZeUhkcnAzT2dnQUNDQ0NBQUFJSVpGYUFnSjdacHFGZ0NDQ0FBQUtyRm1nT2Q1OGFyWDlXbmVpL3FwbmRiVlgybmtkSVh6VXFMMFFBQVFRUVFBQ0JUZ3NRMERzdHpQb1JRQUFCQkhvallDRmRzN3RQanRVL3BjdXZ2YkVaMHEwc2hQVGV0QWhiUlFBQkJCQkFBSUVuRVNDZ1B3a1FEeU9BQUFJSTVGckFYeWQ5c2xiN1NCeTRONGRSbEw3dkVkSnozYXdVSGdFRUVFQUFnV0lLcEI5VWlsazdhb1VBQWdnZ1VIWUJteVRPUW5wbGFxeitPN0dMLzEwenBOdjk5c1dDQUFJSUlJQUFBZ2hrUm9DQW5wbW1vQ0FJSUlBQUFoMFNzQ0J1UGVZVzBuOHJqaHYvWGlFOW5UU09rTjRoZEZhTEFBSUlJSUFBQWlzWElLQ3YzSXhYSUlBQUFnamtUeUFONmRGVWJmdy9LS1QvUHo2a08yZTk2NFQwL0xVbkpVWUFBUVFRUUtDUUFnVDBRallybFVJQUFRUVFXRUxBZ3JoOVZSVFMvOS9BdVJ2RFNxV3FlNngzblpDK0JCaDNJWUFBQWdnZ2dFQjNCUWpvM2ZWbWF3Z2dnQUFDdlJXd0lHNkJQSndZcTcwbENla2E3azVQZW05YmhhMGpnQUFDQ0NDQWdCY2dvTE1qSUlBQUFnaVVUY0JDdWwwWXZSblM0OTlKZXRJZFBlbGwyeE9vTHdJSUlJQUFBaGtUSUtCbnJFRW9EZ0lJSUlCQVZ3UjhMN3EycEpCZWYzTnp1THQ2MGhudTNoVjlOb0lBQWdnZ2dBQUNTd29RMEpkazRVNEVFRUFBZ1JJSXRJVDAybHRjN040ZlZ2enM3dGJEempucEpkZ0JxQ0lDQ0NDQUFBSlpFeUNnWjYxRktBOENDQ0NBUURjRjVrTDZaSzEyUTh0MTB1MSsrMkpCQUFFRUVFQUFBUVM2SmtCQTd4bzFHMElBQVFRUXlLaEFHc1FYWHlmZGlwcytsdEdpVXl3RUVFQUFBUVFRS0pJQUFiMUlyVWxkRUVBQUFRUldLNURPN3U2dmsrNWMvSnVoTHBUZVhCa2hmYldxdkE0QkJCQkFBQUVFVmlTUWZ2aFkwWXQ0TWdJSUlJQUFBZ1VVU004OXIweU8xZDhkTy9lbVVDbGQ5YlF2UW5vQkc1d3FJWUFBQWdnZ2tEVUJBbnJXV29UeUlJQUFBZ2owVWlEdFNhOU0xV29mZGk3NDF3cnBWaDU3djJ6MHNtQnNHd0VFRUVBQUFRU0tMMEJBTDM0YlUwTUVFRUFBZ1pVSnBDRzlxb25qZmw4aC9UVkJFdElyV2cwaGZXV1dQQnNCQkJCQUFBRUVWaUJBUUY4QkZrOUZBQUVFRUNpTmdJVjBDK01XMHYvVWhlN25kZHVHdWR1MTBtZjFuUVVCQkJCQUFBRUVFR2k3QUFHOTdhU3NFQUVFRUVDZ0lBSVcwbWVEdlh2N3AwYnIvODJGMFUvNW44T3dHamhIU0M5SUkxTU5CQkJBQUFFRXNpUkFRTTlTYTFBV0JCQkFBSUhzQ1J3OGVEN1l0Njl2YW16czh5NTIxd1NCT3h0RVVWVUZuY2xlWVNrUkFnZ2dnQUFDQ09SWmdJQ2U1OWFqN0FnZ2dBQUMzUkVZR1pueFBlbmo0MStLWFBCQzU5eWtKby9yMDhZSjZkMXBBYmFDQUFJSUlJQkFLUVFJNktWb1ppcUpBQUlJSUxCbWdXWlArckY2L2Y1cUdQMkUxbmZJUXJyR3daOWY4N3BaQVFJSUlJQUFBZ2dnSUFFQ09yc0JBZ2dnZ0FBQ3l4Vm85cVEvTmpiMjNVci96QXQwTHZyOVVSVDFFOUtYQzhqekVFQUFBUVFRUU9CaUFnVDBpK253R0FJSUlJQUFBb3NGbWozcFI3OTc5TEgrMkwwb2JzUjNXa2pYMHhqdXZ0aUtueEZBQUFFRUVFQmdSUUlFOUJWeDhXUUVFRUFBQVFRa1lEM3Btamh1Zkh6OHpGUzlmbzFyeFA4ampLSys1dXp1TnZzN0N3SUlJSUFBQWdnZ3NHSUJBdnFLeVhnQkFnZ2dnQUFDRXJDUWJ0ZEYxL1hSSit2MWZ4eTc0RCtHbFlyTjdtN1hTN2N2RmdRUVFBQUJCQkJBWUVVQ0JQUVZjZkZrQkJCQUFBRUVGZ2cwOUpPRjlFQ1hZWHU5Yy9HNzFaTnVQNGY2SXFRYkRBc0NDQ0NBQUFJSUxGdUFnTDVzS3A2SUFBSUlJSURBa2dJVzB1MzlOSm9jcS85bUhMczNhWFozQytoUjRJTFpKVi9CblFnZ2dBQUNDQ0NBd0JJQ0JQUWxVTGdMQVFRUVFBQ0JGUXBZYjdtZGUxNlpxdFUrck9IdVA2ZmJqU0FLcTgzejBsZTRPcDZPQUFJSUlJQUFBbVVVSUtDWHNkV3BNd0lJSUlCQUp3UXNvRGRzOGppRjlMK01JM2VOSXZ0SkRYbXZjaG0yVG5DelRnUVFRQUFCQklvblFFQXZYcHRTSXdRUVFBQ0JYZ28wcjVWK2ZIVDhpNkZ6UCs1YzhGMHV3OWJMQm1IYkNDQ0FBQUlJNUVlQWdKNmZ0cUtrQ0NDQUFBSjVFV2hlSzMyaVh2OTJvMXA5bm92akwvbkxzQ1hYU3VjeWJIbHBSOHFKQUFJSUlJQkFsd1VJNkYwR1ozTUlJSUFBQWlVUmFGNHIvY1Rod3ljbWEvV3JBeGQvdGhuU3VReGJTWFlCcW9rQUFnZ2dnTUJLQlFqb0t4WGorUWdnZ0FBQ0NDeFhJTGxXdXI4MitzUlkvWlV1ZGg5b1hvYk4zbjl0OW5jV0JCQkFBQUVFRUVCZ1RvQ0FQa2ZCRFFRUVFBQUJCRG9pWUpkYTg5ZEduNnpWM3E1cnBiOGg4RmRoMDMzT2NSbTJqcEN6VWdRUVFBQUJCUElwUUVEUFo3dFJhZ1FRUUFDQmZBbWt2ZVVWWFN2OWoxd1F2a0xGUDNPeEdkNTFLWFhPVmM5WEcxTmFCQkJBQUFFRTFpeEFRRjh6SVN0QUFBRUVFRUJnV1FMSlpkajI3dTJmR2h2N3ZJc2F6M2ZPZmNkbWVOY0RNNHZYb01lczE1MEZBUVFRUUFBQkJFb2tRRUF2VVdOVFZRUVFRQUNCREFnMFozaWZHbjMwbStHbWMvczB3L3N0Q3VsOXVtYTY5YkxQYVBqN3JCOEJId1hqR1NndFJVQUFBUVFRUUFDQkxncUVYZHdXbTBJQUFRUVFRQUNCVkdEZnZyNGdtVVF1MkRFOCtBZGhFTDdCSHRMUTlpQjI3cDY0Ny9UTGpoODZmdEx1MGhmRDNRMkhCUUVFRUVBQWdZSUxFTkFMM3NCVUR3RUVFRUFnMHdJMmpOMmZuNzU5ZVBnVm1qVHVlcjB4ajFWblpqNXg5T2pSMDNyTVJyclpaZGxZRUVBQUFRUVFRQUFCQkJCQUFBRUVFRUNnd3dJV3dwYzY1V3lwK3pwY0ZGYVBBQUlJSUlBQUFyMFVvQWU5bC9wc0d3RUVFRUFBZ1hrQnUxNTZ1bGl2T3NQYVV3MitJNEFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NDQ0FBQUlJSUlBQUFnZ2dnQUFDQ0NDQUFBSUlJSUFBQWdnZ2dBQUNDQ0NBQUFJSUlJQUFBZ2dnZ0FBQ0NMUlg0SDhEN2R1VFMvRDQrdjBBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCIsImNyZWRQcm90ZWN0IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiM2Y1OTY3MmYyMGFhNGFmZWI2ZjQ3ZTVlOTE2YjZkOTgiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJlcCI6ZmFsc2UsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzEsMl0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wOC0xNiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQXJjdWx1cyBGSURPIDIuMSBLZXkgQ2FyZCBbUDcxXSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwODE2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDgtMTYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTA5LTEyIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMzNlMjVmNGFjMWE0MzFlYTliZGEzN2RiZGQzZmViZWIxZTBkODhhYyJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIzM2UyNWY0YWMxYTQzMWVhOWJkYTM3ZGJkZDNmZWJlYjFlMGQ4OGFjIl0sImRlc2NyaXB0aW9uIjoiSURFTUlBIElELU9ORSBDYXJkIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjgyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9LHsibWFqb3IiOjEsIm1pbm9yIjoyfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDVXpDQ0FmbWdBd0lCQWdJSkFMMWYvdnUyWFd1Uk1Bb0dDQ3FHU000OUJBTUNNSUdFTVFzd0NRWURWUVFHRXdKVlV6RVJNQThHQTFVRUNBd0lWbWx5WjJsdWFXRXhEekFOQmdOVkJBY01CbEpsYzNSdmJqRVBNQTBHQTFVRUNnd0dTVVJGVFVsQk1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1Sd3dHZ1lEVlFRRERCTkpSRVZOU1VFZ1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRJek1Ea3hOREExTXpnd00xb1lEekl3TlRNd09UQTJNRFV6T0RBeldqQ0JoREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFnTUNGWnBjbWRwYm1saE1ROHdEUVlEVlFRSERBWlNaWE4wYjI0eER6QU5CZ05WQkFvTUJrbEVSVTFKUVRFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFNVUkZUVWxCSUVaSlJFOGdVbTl2ZENCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIYlQrUnBrQW85RWNMK09lbENqOGhpaG5mRlVLRE9wTnNzZHJId3NlK3F1RllWMEhMOWp3UVhPMzU1bWtJNGRocDNUc25iTUowQUo5anI2bzdCb0NFbWpVREJPTUIwR0ExVWREZ1FXQkJRbnM2YWh4cy8vZ3BiYTdYRFpCTnNnREcwbEVEQWZCZ05WSFNNRUdEQVdnQlFuczZhaHhzLy9ncGJhN1hEWkJOc2dERzBsRURBTUJnTlZIUk1FQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURiVk1RcVd6bnpiMGVFWVdRYVFJbjBkbFlEb1dRQWJVSTQ2Yjlqc0MxdUZnSWdkK3hFMHJ1ZlcvN25qS2MxcWtzaTNVaE1vamNGWkMrM2NMVFJoV2dLeGpVPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FJQUFBRDhHTzJqQUFBQUNYQklXWE1BQUM0akFBQXVJd0Y0cFQ5MkFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK0xwc2J4dDNJdmVSS2RQVnhYZUY2MHZXZG03T2J3dTJvMjYvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rcWk1cVBObzN1alM2UDhZdVpsbk0xVmlkV0Vsc1N4dzVMaXF1Tm01c3Z0Lzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284L3BQVFQ4ZTduTHVhcnJsY2E3bnVlcjIxZTJiMzZSdWVOODdkOUwxNThSYi8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBZ1kwaFNUUUFBZWlVQUFJQ0RBQUQ1L3dBQWdPa0FBSFV3QUFEcVlBQUFPcGdBQUJkdmtsL0ZSZ0FBQXRoSlJFRlVlTnJzbHQ5TGsxRVl4Ny92TnRlMHZYT2s3eVM3cXlXQll2bmpJa3RHVTB2REN3a3RWNEtYcHYzd0IvNEJCaUlhL1FDMXdqa1ZVeE5zVXV1dXpkMWs2aUJMQ3hJRnpjRFhPVFp3WThyMnNyMXJwNHVYWnVvZ2dyeUpmUzhlZUw2YzUzdzQ1K0U1SElvUWdvT1VDQWVzR0NBR2lBRUF5WDZMWmRuMTlYV0dZZFJxOVQ4Z2tOMXFhMjBWRGxWWmNaVVFZcHVaS1MwdEhUY2E5eXd6Nkh1cnE2cy96czZTUDJrWHdHSTJBempLcUhRNjNmdDNrNFNRcG9ZR0FNV0ZSWHZLTG1vTEFBd09EUHdkb0xkSEQyQmthT2gzODQzSjVISzU5cFRWMWR3RThHcDhmUCtPUzR0TDVyZm1INkdRa083MG9MdXpjMmp3dVNvcDJkQnJPQ3luazVLTzlQWDNaMlprTUNrcHF5dmZHSVlCY0wrOXcycWRLQ29xQ2dRQ0FIaWVGMm9mUDN4a01yMVcwSXJhdWxwdFFZSFA3d05GN2UyQk5sOERJTzM0Q1FBTmQrdTd1N29BU0VBQnFLdXBKWVJVNmE0RG9HWHhxYW9VcFp3V0E5YUpDVUpJNFFVdGdGUHFrd25TUXdENjlQcm9WeFFNQnR2YjJpaUtldERSd2ZOOEtCVGlPTzdaazZjQStub05MTXNDeU1vOHpmbjlITWZsbk1rQ3NMUzRPRDAxRFVCMzlSb2h4T2wweWhNUzRpaVIzVzZQYkxzekIzRnhjYlJDUVFoUkpDWktKQkt4V0N5VHllUnlHb0JVS3YweS94bUFUbGNwaTQrWHlXUWFqUWFBeitlYm1wd0VVRjVSRGtDbFVoVnFDM2dTbnArYml6NEhuTjhQd08vM1I1eEFnTXZOems1bWtrV1VDTURxNm5mQmR6ZzJCREN0VUFCd09sMi9mSWRBaWc0SUJvT1JLSWpuZVFWTmIzbTNpaStYaUVIcCt3enBHZWx1dC91bDBRZ2dFQWlVWFNtN2RlZjJ2WmFXdExTMGhZV3ZIK1krNVovTnk4bk5qZjVVU0NTU1NJdzQ0WERZNGRoUUtwWER3OE5paXFwdmJCd2RlVkYxb3dvQXU3YVdtbnJNMEtQZjN0NitWRkxjMU54OFB1L2M2TmlZU0NTS1Bza2V0MmQ1ZWRuajhVUWNyOWRyWDdlNzNadEN5ckpyVnFzMUhBNFRRcFpYVnJ4ZXIrQzdOOTBXaThWbXMrMGZDeXIycTRnQllvRC9BUEJ6QUk2Vk5xR1FQVXFuQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTEwLTE5IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJJREVNSUEgSUQtT05FIENhcmQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDIzMTAxOTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTEwLTE5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMi0wOCJ9LHsiYWFndWlkIjoiNDJiNGZiNGEtMjg2Ni00M2IyLTliZjctNmM2NjY5YzJlNWQzIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI0MmI0ZmI0YS0yODY2LTQzYjItOWJmNy02YzY2NjljMmU1ZDMiLCJkZXNjcmlwdGlvbiI6Ikdvb2dsZSBUaXRhbiBTZWN1cml0eSBLZXkgdjIiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciLCJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDSWpDQ0FjaWdBd0lCQWdJQkFqQUtCZ2dxaGtqT1BRUURBakJrTVFzd0NRWURWUVFHRXdKVlV6RVBNQTBHQTFVRUNnd0dSMjl2WjJ4bE1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1TQXdIZ1lEVlFRRERCZFVhWFJoYmlCVFpXTjFjbWwwZVNCTFpYa2dVbTl2ZERBZ0Z3MHlNVEV5TURFeE5USTJNekZhR0E4eU1USXhNVEl3TWpFMU1qWXpNVm93WnpFTE1Ba0dBMVVFQmhNQ1ZWTXhEekFOQmdOVkJBb01Ca2R2YjJkc1pURWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWpNQ0VHQTFVRUF3d2FWR2wwWVc0Z1UyVmpkWEpwZEhrZ1MyVjVJRk5wWjI1cGJtY3dXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUkdTWC8wV21vU3RZZmhtbHpTUEI0U0FSaG1UQnBQaTBvM3lZeWdTNHNtbi80T0ZkR05KZHNQeGt1YjYycE9sV2UwSTZjSlNoOVczRUFIQTJaUE8rUytvMll3WkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVVJUcVFZT3NQSjg5N1g0MHZhditYb1crUzZzZ3dId1lEVlIwakJCZ3dGb0FVMmQ2SnJGQ29FWkFlL0xVcElNeWJsdERzTWgwd0NnWUlLb1pJemowRUF3SURTQUF3UlFJZ1NyM04xNEhkdENmajdRWjBSN2tXZzZJMzE3UUVOYjhxK2ZiTmtvNm5LNG9DSVFENUpoMTRnckRjNkY3Z0hpYjlRVHY4c1VzNnc4Z0YxSllLTUsrTERPWVBZZz09IiwiTUlJQ01qQ0NBZG1nQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpCa01Rc3dDUVlEVlFRR0V3SlZVekVQTUEwR0ExVUVDZ3dHUjI5dloyeGxNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNU0F3SGdZRFZRUUREQmRVYVhSaGJpQlRaV04xY21sMGVTQkxaWGtnVW05dmREQWdGdzB5TVRFeU1ERXhOVEl6TlRGYUdBOHlNVEl4TVRJd01qRTFNak0xTVZvd1pERUxNQWtHQTFVRUJoTUNWVk14RHpBTkJnTlZCQW9NQmtkdmIyZHNaVEVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVnTUI0R0ExVUVBd3dYVkdsMFlXNGdVMlZqZFhKcGRIa2dTMlY1SUZKdmIzUXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUnFtTld6Y0ROSDYzbzhUem9kQjJqazliNDlWUHNmSXZYcGRoYVd4ZkxheW80TEJiRHJYeXhGM0pSMVA2VzZac3FXQ0VZclgwb1lJeEFvZzNoQ0U0eWRvM293ZURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVMmQ2SnJGQ29FWkFlL0xVcElNeWJsdERzTWgwd0h3WURWUjBqQkJnd0ZvQVUyZDZKckZDb0VaQWUvTFVwSU15Ymx0RHNNaDB3RlFZTEt3WUJCQUdDNVJ3Q0FRRUVCZ1FFQXdJQUFEQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQU5JUTQ4L25NcDJLZllOaW92Y3l4V1hKTGl1bDRTdit6Y1JKZXpyZC9XV0FJZ1Z1Y1E1MzFmcXpZN09Eb0srZElEeWtSdWR2bFcveUJxemEvQWRTMFNxNlE9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQURBQUFBQXdDQVlBQUFCWEF2bUhBQUFEMUVsRVFWUjRBZXlYVTVnY1RSU0c2Mkw5MjdiL2FKTHBudDI0MXpHbWQyUGJ4bDFzMjlZb3RtM2JkcVkzbk41b1Vha1RxNDNsZVo1djJYaS9xb01hbEJraU84NHhUTkQxcU5Bd2J5VGRrc2hCdE00YlpUdEZ2cDk3VGR1NFNIbzZVVnU0RnU1SmMzQUE0YUtvMFFUdU5oRldLSTVvUER6RGRIQUN6Y0NLQW9nK2doMnpGakljL0NZVCtpTjUyVElpYklRZ3hXNHpsazhOU2hlcTdQTnR4d2Jya3U1cDVZMmd1OFBEVGRRRExzcFdVaC80S0hxd3FmQ2dDUHFZbDZHL05YTGwwei84alNpSzFRaHorN1Vad0prS254QmovZGNiYWZNcEJFNTZQc1FxdnErVHdOK2VMNG9EcmpVTUhvS0xwRmNwaEorczVPWFhtTEJmeVFKNURJR0hkcWxrbWw2UHBpT1J5b0NqQjRFL3BCczhYb2Y4K0VIZm51Q0tXVk5rd0YrRFZOUDhUb2J4UTNwRjhxb0FObW0xUDM3by9BZ254T2NSZ2JmNXJzZFFPVkY2aTZUVkFjdkFBT2p4MGtCOHAvSGZRaVlxcGpkMlNKOHZDWGdTd0w4dXZ1Y1AyQnROdlE2L0RLWEhTRjRkVUJHQTM2Y0hrejdEQ1dVdEFJKzVhQnVWUGcyczhoOE9zRUo2TkQ4RVV1b29TcTlCSUxjQnFMajgyaUtGRWRHVHgzb3F2QWUvVEtpQXIwa1plTHpTbjBwakE2QnpRanVBcFVRSy9jTjBZQ0JKdFFFRWtmWUdjSlkxQUNrVWxKNE5jREtLMkpLZURleVNOTERhdjJFNk1IQkpZQkw3anhlRDUxY0ZKZmVlbDIrcENnT1Q1UXA2dk9RYzZNV3ZFakpRVXdqKzlJclBjQVZQREthY0xMYk9ZdjlGQmtWa1Q3NnQ1QTcwU2h3dWNKZ0wvdkY5OEN1Vy9JeUx1TW9DL0RNNTJPbkdHZkJ0a3pJUTJjTlhVZXc0c2VrRitNUFZBYmpmZ3J3QS9ZNW9SMXlrM3ZEaFBSTEx5cWtCcGgvL0xZSVFTNlByS3ovQ2RXY3pBQ3VrYTZFejdEL3FCYzkwOFg1STRJNUo1bi9QeEUxU253bUNOaTc5L2thc3V5UkFTdWtZN1k3WDViTnNSRS9mUERtclQxS3NLWklLeW1HdkM0QXlkWXB5bHMrcGFlVjc4SXRrdHMvYlRCY3NiNUFTc0YwS1REeWdYUGJPek9SYWlxWjBQaGNiR3pheDY1SHdQbDZaL1QreHMveUhPKzFoQkN3SkFPWEx6dEZPdGpmY0svaGNkL3lmbElOdFNxN2I5dUkrMi9UR21CbHdWUElJTGJENndnRXZnaGVvMUcyaWZVVHJRQUFNQm9XdXAyZFZ3WVdHTFJjcFhqNFdxUW1yazUwTUx6QkxCY2FPSklQcTdwc0dldmk2cTI5djZ4Zy95aFhuTWRPRWJXbzdITjczM0l1ODk1RFU4UU1XVFNaZytwcHBncDVWN1hIUndWdGZ3T3NUSkk5YlFzY3h4MFRjWUZnNHBIZVF3V1VoTHpoa0dEZ1V1b3Rsa1pFQksyTjFzVFZKZ1ovVEVmNEJlV1oveTd4eW55S3pBZ1lYN2JCWEpFVytUSHBtQ09xVTFSSFgwVHFyOHBjb0xRTU9kbUFHY2hkNi92UGRTWG9uUFdEQ1B4bXdRQURpYkhDL1loaUFVUUFBMFMwS1dTVkdBMDRBQUFBQVNVVk9SSzVDWUlJPSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfSx7ImlkIjoiY3JlZFByb3RlY3QiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiVTJGX1YyIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI0MmI0ZmI0YTI4NjY0M2IyOWJmNzZjNjY2OWMyZTVkMyIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoyMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA2LTEyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJHb29nbGUgVGl0YW4gU2VjdXJpdHkgS2V5IHYyIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMzA2MTIwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wNi0xMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDktMDMifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJmMjg0MGUzMTFhOTVlNWVmYjBkYzBjZjY5YjIzMTZhZDliOTU1YWEyIiwiNzE5OGIxMGQ0MTM5NjJmMmM5MWNmODM2Yzk1NjhiY2I3MjU3ZGZiZiIsImFiYTQ3MDYyM2NmODg5NDI1MzA3MjQ2YjU4MmIxY2ExOWQyMDg4YzMiLCI1ZTI0ZjBlYjM0OWE3MDdiM2FjNGRlNTM2YjkwNWU1OWY1YmNiODQ1Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImYyODQwZTMxMWE5NWU1ZWZiMGRjMGNmNjliMjMxNmFkOWI5NTVhYTIiLCI3MTk4YjEwZDQxMzk2MmYyYzkxY2Y4MzZjOTU2OGJjYjcyNTdkZmJmIiwiYWJhNDcwNjIzY2Y4ODk0MjUzMDcyNDZiNTgyYjFjYTE5ZDIwODhjMyIsIjVlMjRmMGViMzQ5YTcwN2IzYWM0ZGU1MzZiOTA1ZTU5ZjViY2I4NDUiXSwiZGVzY3JpcHRpb24iOiJZdWJpS2V5IDUgRklQUyBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA3LCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAyLTA4In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMi0wOCJ9LHsiYWFndWlkIjoiMzYxYTMwODItMDI3OC00NTgzLWExNmYtNzJhNTI3Zjk3M2U0IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIzNjFhMzA4Mi0wMjc4LTQ1ODMtYTE2Zi03MmE1MjdmOTczZTQiLCJkZXNjcmlwdGlvbiI6ImVXQk0gZUZBNTAwIEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfZGVyIl0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjI1NiwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNwVENDQWtxZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd0hoY05NVGd3TnpBeU1EVXpNVE01V2hjTk1qTXdOekF4TURVek1UTTVXakNCcnpFTE1Ba0dBMVVFQmhNQ1MxSXhFVEFQQmdOVkJBZ01DRk5sYjNWc0xWTnBNUk13RVFZRFZRUUhEQXBIWVc1bmJtRnRMVWQxTVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUWlZkQ1RTQkRRU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUUlmcUhpc2kwb08vZXlPcVNhRHJyOWl0RzJJeW1Ca0huU0RHUUlJWW1UK3ZxQThBZ084MW1vbWMyTGQ1UEdwRU42bXVFNTR3UEhRanZjL3lDaWg4dTJvMVV3VXpBU0JnTlZIUk1CQWY4RUNEQUdBUUgvQWdFQU1CMEdBMVVkRGdRV0JCUzNKL2Z4aUF2MjJpcmRCczk4U09EaEY3a1UvakFMQmdOVkhROEVCQU1DQVFZd0VRWUpZSVpJQVliNFFnRUJCQVFEQWdBSE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRGM0MUxGSzRMSkNCVTJWVktJejdaNnN4UGhVRWtoOG5MU0xLNklYZGtQNXdJaEFJZUtWT1pjaGFWTzVhRjdmYmRYb1NyY3l5MVlZZVVlUExvamNLSTlmWDg0IiwiTUlJQ2dqQ0NBaWlnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQm5URUxNQWtHQTFVRUJoTUNTMUl4RGpBTUJnTlZCQWdNQlZObGIzVnNNUkF3RGdZRFZRUUhEQWRIWVc1bmJtRnRNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRVpNQmNHQTFVRUN3d1FRMlZ5ZEdsbWFXTmhkR1VnVlc1cGRERVpNQmNHQTFVRUF3d1FaVmRDVFNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SUJjTk1qTXdOekV4TURNME5qRTBXaGdQTWpBM016QTJNamd3TXpRMk1UUmFNSUdkTVFzd0NRWURWUVFHRXdKTFVqRU9NQXdHQTFVRUNBd0ZVMlZ2ZFd3eEVEQU9CZ05WQkFjTUIwZGhibWR1WVcweEZ6QVZCZ05WQkFvTURtVlhRazBnUTI4dUxDQk1kR1F1TVJrd0Z3WURWUVFMREJCRFpYSjBhV1pwWTJGMFpTQlZibWwwTVJrd0Z3WURWUVFEREJCbFYwSk5JRU5sY25ScFptbGpZWFJsTVIwd0d3WUpLb1pJaHZjTkFRa0JGZzVwYm1adlFHVXRkMkp0TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBaCtvZUt5TFNnNzk3STZwSm9PdXYySzBiWWpLWUdRZWRJTVpBZ2hpWlA2K29Ed0NBN3pXYWlaell0M2s4YWtRM3FhNFRuakE4ZENPOXovSUtLSHk3YWpWVEJUTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZMY245L0dJQy9iYUt0MEd6M3hJNE9FWHVSVCtNQXNHQTFVZER3UUVBd0lCQmpBUkJnbGdoa2dCaHZoQ0FRRUVCQU1DQUFjd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFOVm5KZGUvL3RCTHE4TUREaStTQWQ2VWRZSVpTbmc0UE1xbXlOcnZaajY0QWlBWDB4U3pBaEZhQ0NwL3VocFZnbmxGK1hCZ3J3QUlzb3RaR1RCNnJrQjMxQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBRXhDQVlBQUFEdkRZZ3FBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFGaWNTVVJCVkhoZTdkMEhlQlhGMnNEeE43M1FDVFZBNkZJRkZLa0NVdXlBRXVtS1lrRlViSUNDSWlLQ1VnUUU3TDBnZGxRc0tDcFNySWdnU0MraEpuUkNKNEgwYjJmdmVELzBraENTbmMyZWsvL3Z1WG1ZZDQ2WGtKTno5c3k3TS9OT1FKWkZBQUFBQUFCQWdRclVmd0lBQUFBQWdBSkVnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUVCQWxrVzNQU3N6TlZYU0R5VEtxYTFiNWRTYWRaSzZlNCtrSHo5bTk0bjMvL21BY1FFaG9SSmN1cFFFUjBWSldKVktFdDZndm9SWHJ5WkJwVXBKUUNEMzRRQUFBQUJmNE5rRVBTc2pRMDV0M2lLSFB2cEVqdit3UU5MMzdaT3MxRFQ5S0lDekNZeU1sTkFhMWFURU5aMmxaSmZPRWxxaHZQV09EOUNQQWdBQUFQQWF6eVhvS2pFL012YzdTWHh6aHB4YXNWTDNBc2lQZ05BUUtkcXh2WlM5WTRBVWFkSlk5d0lBQUFEd0VrOGw2TWQvKzEzMmpIdEtVdGF0MXowQW5GYTg2OVZTWWRnUUNhdFNSZmNBQUFBQThBSlBKT2daSjA3SW5vbFQ1UEFISDR0a1p1cGVBS1lFaElkTGhWRWpKS3BYZHdrSUR0YTlBQUFBQUFwU2dTZm9wN1pzbFIwREIwbnExdTI2QjRBckFnS2syQldYU3BYSkV5U29hRkhkQ1FBQUFLQ2dGR2lDZnVMUDVSSS9ZSkJrSERtaWV3QzRMYnhSUTZuMjVpc1NFaFdsZXdBQUFBQVVoQUpMMEU4c1hTWTdicmxETXBPU2RBK0FnaEphcTRiVS9PaGRDUzVkV3ZjQUFBQUFjRnVCSEpDc2xyWEgzM2t2eVRuZ0VhbWJ0OHIyZ1lNa2cvY2tBQUFBVUdCY1Q5RFRqeDZUN2JmZElSbUhEdXNlQUY1dzhzKy9aT2NqajBrV2hSb0JBQUNBQXVIcUVuZDF4bm44QXcvSnNTL202SjV6RnhnWklVR2xTa2xJamVvU1ZLSzQ3Z1VLT2V0dG5MNXZ2NlR0aUplTUkwY2xLeTFOUDNEdUtrNFlLMlg2OU5JUkFBQUFBTGU0bXFBZlhiaklMZ3AzemtlcEJRWksrUGtOSktwL1B5bld1cVVFbHlrakFVRkIra0VBZjh0TVRaWFVYYnZrNkxmejVORE05eVY5ejE3OVNPNEZsaXdoNS8zd0RVWGpBQUFBQUplNWxxQm5KQ1ZMM0ZYWFNGckNUdDJUTzZFMXEwdkZVU09rZU5zMmRxSU9JSGN5VDU2VWd4OThMUHVmZVY0eWp4M1h2YmxUb2x0WGlaazZ5YnBDQk9nZUFBQUFBS2E1bHZFZW1mUDF1U1huVm1KUW9tZXMxSjR6VzRwZjBvN2tIRGhIZ1JFUlV2YlcvbExMZWcrcG85VE94YkZ2djVkVDhRazZBZ0FBQU9BR1Y3SmV0ZXgyLy9NdjZTZ1hyR1E4YXRCQWlYbHF2QVNHaCt0T0FIa1JWcVd5ZllSYTVNVXRkYy9aWloxS2tmM1B2cUFqQUFBQUFHNXdKVUUvc1hpSnBPL2FvNk96Q0FpUTBqZjNrK2loOTdPOEZuQ0l1dEZWN2RVWHoya20vY1NDUlpKKzVLaU9BQUFBQUpqbXloNTBWYm45NkdkZjZDaG5Lb0dvK2ZIN0VoZ1dxbnZ5eWZyeHN0TFRKZjNFQ2NrNGZseXlVdk5lM1Jwd2l6cXRJTGhZTVh1WnVsMFEwYUdiVmFlMjc1RE5WMTRqV1NrcHVpZG5sWjZaSXFXdjZhSWpBQUFBQUNZWlQ5QlZjcnl1ZVJ2SlBIeEU5K1FnT0ZpcXozcFBpalpwckR2eUxubmRlamsyZjZFay9icFlVclpzbFl6RWcvb1J3SGNFeDFTUmlOcTFwR2lIZGxLc1kzc0pxMWhSUDVKMysxNTZWZlpQbXFxam5CVzlyS05VZi9WRkhRRUFBQUF3eVhpQ25yeG1yV3pwMmwxSE9TdmE4UktwL3ZyTGVaNHR6RHlWSWtlKy9VNFNYM3RUVXRadDBMMkFud2dNbEtLZDJrdVpXL3RMc1JiTjgvdytTVDk2VkRaMXZGSXlEaDNXUGRrTEtsNWM2djd4c3dTR2hla2VBQUFBQUtZWTM0T2UvTmRLM1RxNzBuMTY1UzNweU1xUzQ0dC9sN2pPM1dUWGtPRWs1L0JQbVpseVl0NEMyWDdETGJKdDRDQkp5V09WOWVBU0phVEV0VjExbEROMVZGdnF6bDA2QWdBQUFHQ1M4UVQ5NVByY0pjc0JrUkZTN0pLMk9zbzlWU0YrOThUSnN1T21BWks2ZFp2dUJmeVlTdFIvV0NpYnUxNG5oK2Q4WThmbnFrU1hxM1FyWjFscGFaTEMrd29BQUFCd2hka0VQU3RMMHJadTEwSE93aHZVbDhEUWN5c01wNHErYmIvakhqbjQ2cHYyWG5lZ01NazhkbHgyRGg0bWU2WStZNy9YemtWRXpSb1NXTFNvam5LV3NpZVhKekFBQUFBQXlCZWpDYnJhM3A2Um5LeWpuS216bXMrRlNzNjMzVHBRa2hiOXBIdUFRaWdqUXhKZmVNVmVSWEl1U1hwQVJJUUVsNDNTVWM3U2Q1T2dBd0FBQUc0d080T2VtU21adVR6T0thaENlZDA2TzdYc05uN1lDRG01YklYdUFRbzN0WXJrd0ZzemRIUjI2dWkyZ05EY0ZYN0wyTGRmdHdBQUFBQ1laSHdQdWduN1gzdFRUbnozZzQ0QUtQc21UWk9rRlgvcENBQUFBSUN2TVhyTW10b1h2cWxMcktSdWpOTTkyWXNhTkZDaWh3M1ZVZlpPYm9xVExWMnVzMmZSY3kwdzBONXZHMXdtU2dLalN1bE93S09zZDJUR3psMlNjZUtFWko1STBwMjVFMXFyaHRUKzhsTUpqSWpRUFdlV2xaRWhjWjFqSldYakp0MlR2WkxkdWtxVmFaTjFCQUFBQU1BVTMwclFyWC9xdHR2dWtCTUxjN252M0Q0M3VvT1VIWEN6aE5lcks4SEZpdWtIQUkvTHpKUzB3NGZseE85L3lJSG5YN0lTYWVzOWxKdTNha0NBbEI4eFRNcmRmcXZ1T0RNU2RBQUFBTUI3ZkdxSmU5S3ExYmxPemtOaXFrajFqMlpLOVZkZmtLTE5tNUdjdzdjRUJrcElWSlNVNm55VjFKNHpXeW8rT1ZvQ3dzUDFnem13a3ZqRWwxK1RqS1J6bTNrSEFBQUFVUEI4SjBHM0VvOERyNzZoZzV5Rm45OUFhczcrU0lwZTFGVDNBTDVMRlhRcmMzMGYrNFpUVU1rU3VqZDdHWWNPeXhGMVBqb0FBQUFBbitJekNYcjZrYU9TOU10dk9zcGVjTVh5VXUzMWx5V2tkR25kQS9pSElvM09sOHJQVGJWZTVFRzZKM3RIUHZ0Q3R3QUFBQUQ0Q3A5SjBKTldycExNWThkMWxJM0FRS2s0ZHJTRWxDdXJPd0QvVXJ6TnhWTHFoajQ2eWw3eW55c2s0L2dKSFFFQUFBRHdCYjZUb1AvMnUyNWxMN3hlSFNuUjRSSWRBZjZwN0lCYkpTQTRXRWZaeU1pUXBKVXJkUUFBQUFEQUYvaE1ncDY4YnAxdVphOUVsNnZ0L2JxQVB3dXJYRWtpV2pYWFVmWk9yVjZyV3dBQUFBQjhnVThrNkZrWm1aSzJhYk9Pc2xmc3NrNjZCZmkzWW0zYjZGYjJVdmZ2MXkwQUFBQUF2c0JIRXZSME8way9tN0FLRlhRTDhHK2gxYXZwVnZZeVQzRFVHZ0FBQU9CTGZHYUplNjRFNkQ4QmY4ZHJIUUFBQVBBNy9wV2dBd0FBQUFEZ28walFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUENNaXk2TGJqc3RMVFpWT1hXRW5kR0tkN3NoYzFhS0JFRHh1cW8zL0tURTJWRGEzYVM4YWhRN3JuekJxc1hTNkJrWkU2TWljMVBrRk9yZCtnSS9pejBKZ1lDYTlYUjBmZWNXVCtBa2tZTUVoSFoxYWlSNnpFVEo2Z28zL0t5c2lRdU02eGtySnhrKzdKWHNsdVhhWEt0TWs2QWdBQUFHQUtDWG9lSEp6NXZ1eCtiS3lPNE0raSt2ZVQ2TWNmMVpGM2tLQURBQUFBL29jbDdnQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCd1JrV1hUYmNWbnA2YktwUzZ5a2JvelRQZG1MR2pSUW9vY04xZEUvWmFhbXlvWlc3U1hqMENIZGMyWU4xaTZYd01oSUhabHpjdlVhT2Y3anp6cnl2dVEvVjhqeFJUL3B5Rm5sQjk4ckV1Uy85M2tpR3AwdnhkcTEwWkYzSEptL1FCSUdETkxSbVpYb0VTc3hreWZvNkoreU1qSWtybk9zcEd6Y3BIdXlWN0piVjZreWJiS09BQUFBQUpoQ2dsNElKTDQ1US9ZOGNlWkVMYjhheHEyUmdPQmdIY0V0L3B5Z1o2V2xTVmFtc2N0UzRSTWdFaGdTWXYxcE5RQUEvME9OTThXRmo1MkE0Q0FKQ0FyU1VjRno5Zk9XenlJZzEwalFDd0VTZFAvanp3bjZ0cUhENU5TS2xUcENmZ1dWS0M2MVBuNWZBa05EZFE4QTRIUngzZnRJK2xuR21FNG9QL3dCS1gzVkZUb3FXQmxKU2JMbHhsc2s0L0FSM1dOV1pJdG1FalArQ1FrSVpIY3RjRFlrNklVQUNici84ZWNFUGE3ZnpYSnk4UklkSWI5Q2ExU1h1dk8rMFJFQTROL1d0V3duNlFjTzZNaWM2RW5qcFV6M1dCMFZvTXhNMlQ1MG1Cejd5cDNQaHVBSzVhWDI3SThscEZ3NTNRTWdKOXpHQWdBL0ZsYXJwbTRCQUNDUytORXMxNUx6Z0xBd3FUSjFFc2s1Y0E1STBBSEFqNFdXTDY5YkFJRENMbm5kZXRrejdpa2RtVmR1eUwxU3JFVnpIUUhJRFJKMEFQQmpZWTBhNmhZQW9ERExPSDVjNGdjL0tGa25UK29lczRwZGNabVV1KzBXSFFISUxSSjBBUEJqNFRWcjZCWUFvTkRLeXBMZGs1NlcxQzFiZFlkWklaV2lwY3I0c1JTRkEvS0FkdzBBK0t1Z0lBbXJVRUVIQUlEQzZ2QTMzOHJoRHo3V2tWbUJrUkVTODhJekVseXlwTzRCY0M1STBBSEFUd1dWS2lXQnhZcnFDQUJRR0tYRXg4dXVrYVB0V1hUamdvS2t3cWhIcE1qNWJLOEM4b29FSFFEOFZGRFJJaElZRnFZakFEQXJNek5UVHA0OEtZY09IWkt0MjdiSjBxVkxKVFUxVlQrS2dwQjVLa1YyREg1UU1vOGYxejFtcWFOWnkvVHNyaU1BZVVHQ0RnQitLcVJ5SlFrSUN0SVJBT1NOU3J6VDB0SWtPVGxaRWhNVFpmUG16Yko0OFdKNTcvMzNaZHo0OFRKNHlCQzVOalpXYXRldEsrZlZxeWQxcks5NkRScEk2N1p0NWJoTGlTSE9RTzA3ZjJxeW5GcTVXbmVZRmQ2b29WUWVPMW9rSUVEM0FNZ0xFblFBOEZPaFZXTjBDd0J5cGhMd0F3Y095TnExYTJYMjdObnk0a3N2eVdPalIwdS9tMjZTaTl1MWs2Yk5tdGxKZDZXWUdLblhzS0cwNjlCQmJyNzFWbmw4N0ZoNXdmcHZ2NWs3VitMajQyWHYzcjF5NU9oUk82bEh3VHE2NkNjNS9QNUhPaklyc0doUmlaaytSUUxEdzNVUGdMd2lRUWNBUHhWS2dUZ0FPVGgyN0poY2V2bmxVcmQrZllrc1ZreWlxMVNSSmsyYlNxKytmZVgrSVVOa3dsTlB5VWNmZnl6TGxpMlQ5UnMyeU80OWUwaThmVVRxN2oyeWMvZ0l5VXBQMXowR0JRUkk5Sk9QUzNqVnFyb0RRSDZRb0FPQW53cS9vSkZ1QWNEL1V2dkRGLy8rdTJ6WjZzN1JXM0JIcHZWN2pYL29FY2s0ZEZqM0dHUWw1MUVEYnBiU1hUdnJEZ0Q1UllJT0FINHF2RW9WM1FJQUZCYjdYMzFka24vN1hVZG1SVjdVVkNvT0hhd2pBRTRnUVFjQVB4UVFFU0VoWmNycUNBQlFHQnhmc2xUMlAvZVNqc3dLcmxoQnFqNDNWUUpEUTNVUEFDZVFvQU9BSHdvdVgwNENRb0oxQkFEd2QrbEhqa2pDc0llc2h2bDk1d0doSVZKNThnUUpLY3VOWU1CcEpPZ0E0SWRDU3BhVWdFQXU4UUJRR0toaWNQSERINUgwWFh0MGoxbGw3cnBEaXJkcXFTTUFUbUwwQmdCK0tLUkdOYzZpQllCQzRzRGI3OGlKK1F0MVpGYlI5dTJrNHIyRGRBVEFhU1RvQUR3bHBGeFpDYTFTMmJXdmtJb1YzVWxrcmU4UlVpbjZqUDhHRTE4UjlldnJid3dBOEdkSksxZkp2cW5QNk1pc0VPdnpKV2JLUkc0QUF3WUZaRmwwMjNGcXVjMm1MckdTdWpGTzkyUXZhdEJBaVI0MlZFZi9wSTZMMk5DcXZXUWNPcVI3enF6QjJ1VVNHQm1wSS93dDhjMFpzdWVKQ1RweVZzTzROUklRekQ1WHR4Mlp2MEFTQnVSODk3cEVqMWlKbVh6bTMzdFdSb2JFZFk2VmxJMmJkRS8yU25icktsV21UZGFSL3prVkh5OXhsM1UyZmxac1lKRWlVbWZCZHhKU0prcjNBRURCU2t4TWxLbzFhdGpIclpteWQ5Y3VpWXJ5OW5WdlhjdDJrbjdnZ0k3TWlaNDBYc3AwajlXUk05S1BIWk80YmowbGJVZTg3akVuTUNKQ3FuL3dqaFE1djZIdUFXQUNNK2dBQUFDQUQ5cjF4SGhYa25NSkRKVHlqejVFY2c2NGdBUWRBQUFBOERFSFA1MHRSei83UWtkbWxlamFXY3IwNnFrakFDYVJvQU1BQUFBKzVHVGNadGt6WnB5T3pBcXJjNTVVR1RlR2swRUFsL0JPZzA5UjlRaTI5cnRaMWwzUXd2aFgzTFU5Sk9ORWt2N09BQUFBQlMvanhBbUp2LzhCeVV3eVAwWUpMRlpNWXA2Zlp1OC9CK0FPRW5UNGpxd3MyVGY5ZVVuNjlYZkpPSExVNkZkbThrbXBPSHFrQkJVdG9yODVBS0N3eU16TWxQVDA5RE4rWldSa1dCOUh4dXJyQWpuS3NsNmJ1eWRNeWxXUjEzd0xDcFRvTWFNa29rWU4zVkY0cWZkOFR0Y0Y5UmpnRktxNEZ3TCtVc1g5Mk0rL3lJNWI3eFRyU3FoN3pDbDcvOTFTWWZDOU92SWVxcmc3aHlydXZpOGxKVVhXcmwwcmY2MWNLZnYzNzVjRGlZbjZFWkd3MEZBcFdiS2tsQzFiVm1yWHJpMzE2dGIxZkVWcHVDY3BLVW0yYnQwcXExYXZsajE3OXNpMjdkdGw0OGFOY3VyVUtUbDU4dVFaQjkwUkVSRVNFaElpcFVxVmtnYjE2MHVsU3BXa2F0V3FkcnR5NWNvUzdFTW5tMURGL1Q5OHFZcjdrZSsrbC9oN2hxaTdTTHJIbk5MOSswbmxVWThVdWlQVjB0TFNKTjRhR3l4ZnNVSVNFaElrTGk1T05sbGY2cnFRbkp5cy82di9wOTd6WVdGaFVyeDRjV25Zb0lGOUhhaFdyWm8wYnRUSXZqNzQwalVCM2tDQ1hnajRRNEtldW51UGJMWmVTeG1IaitnZWN5SmJ0NVFhTTkvMDlGNHJFblRua0tEN3BxTkhqOHJjYjcrVkR6NzhVSDc4NlNjNzBjcXRPdWVkSjQ4LzlwajA2TkZEOTZBd1VNbjJ0bTNiWlBIdnY4dWlIMytVdi83NlMxYXVXcVVmZFVaNGVMZzBiOVpNTHJqZ0FtblZzcVcwYk5IQ0hxQjdGUW42Zi9oS2dwNlNzRlBpcnVrdW1jZU82UjV6SWk1c0lqVm52aTJCNFdHNngzK3AxNys2d2Z2TEw3L0kvQVVMNVBjbFMrU1lRODl4cEpXWHRHM1RSdHBmY29tMHNLNEh6UzY2eUw1T0FEa2hRUzhFZkQxQnoweEprYTNYOTVlVHkvL1NQZVlFbFMwanRiK2VMU0ZseStvZWJ5SkJkdzRKZXU3OGJpVTE2OWF2MTVFekxySUdLbzNPUDE5SHVYUEFHa1MvL09xck11WHBwODg0azVGYnN6NzZTTHBkZTYyT3p0MnNUejZSNDhlUDY4aDVWMTV4aFVSSFIrdklHWjk5OXBrY09YcFVSODY3eEJxQTF2VFlVbGkxSEgzVHBrM3kyZXpaOHNtbm44cjZEUnZzUHJjRUJRWFpONFI2OWV3cFYxMTVwVFJvME1DZWFUTnAxYXBWc3V6UFAzV1VzeE1uVHNoREkwYllTM1JOZVhyeVpDbGF0S2lPOHE1OCtmTFMrZXFyZGVRc1gwalFzOUxTWkhPL20rWGtzdVc2eDV6Z2NtV2wxdXhaRWxxaHZPN3hQK28xcjI3UWZXaDlGcno3M250eThPQkI0MXRYQWdJQ3BGaXhZdEtqZTNmcGQvMzEwcng1YytQWGd6TlJOeXMvLytJTE9YTEU3S1JYNmRLbDgvVTVtMWZxNTN0bjVzd3pyb0J5aXJySjBydFhML3NhYndJSmVpSGcwd202OWZMYzg4enprdmpzQzFaYjl4a1NZRjBrcTc3OW1oUnIyVnozZUJjSnVuTkkwSFBuL2lGRDVNV1hYdEtSTSs2NzV4NTVlc29VSGVWTURhWm16Wm9sUXg5OFVCS3RnVlIrcU9XR2YvN3hoOVN2WDEvM25CdjFzZG1vU1JQWnNIR2o3bkhldDk5OEk1MDZkdFNSTTVvMmEyWXY1VGJsbmJmZmxyNTkrdWlvWUtrVkZkOS8vNzFNc2w1ZmFoQ3VscXdXTkRXUVUwdGZCOXg2cS8wOHhjVEUyQU4ycDAyZE5zMU91djJOU21vK3NCSXBFenlmb0Z2WG5GMFRKc3ZCTjk3U0hlYW9NVjNWMTErUzRtM2I2Qjcvb203c2ZqOXZuancxYVpLcytPc3ZWMi9ZblU2OTk2dFhxeWFENzcvZlR2UlVNdXVtMndjT2xMZmZlVWRIWnFpYkVic1RFbHhmTWFDMkxkVS8vM3lqdjlzTzdkdkxkM1BuR3JtR0t4U0pnNmNkKzIyeEhIemhGZVBKdWZVT2t6S0RCdnBFY2c3NGk0U2RPM1VyWjRjUEg1YnJiN2hCYnI3dHRud241NHFhelZPSkV2eVBXcXI2M3Z2djJ6Y2pldlh0YTg4a2V5RTVWOVJnY2NlT0hUSnE5R2o3QnMrMXNiR3lkTm15QWtzUWZFM3JWcTEwcS9CUk5YZ096akNiVFAydHpGMjMrMlZ5cm03eWZ2bmxsOUtrYVZQcDJidTNmVzBveVBlZXV0RzdkZHMydVcvd1lLblhzS0U4UFhWcXZsYUZuYXRldlhycGxqbHFsWm1xRCtPMkpVdVdHUC9kOXJGZVE2YVNjNFVFSFo2VmRpQlJkajN3c1BHWlRTV3lXVk1wZjlkQUhRRnd3eHJyZy90c2k3alVudUcyN2R2TDdDKytjR3k1V3BreVpldzcrL0FmNm5YMDg4OC9TNXQyN2VUbVcyK1ZMVnUzNmtlOEtmbmtTYnVHZ3ZyM1huSFZWZllXRXVTc1JpR3RKSjY2Yjc4a0RIL0V5akROSjVORjJsNHNGZTY5VzBmK1EyM1B1cnBMRitsdUphWHFNOFZyRGgwNkpBOC84b2g5WS9HTEw3ODg2K2VpRXk2eHJqMnEwS1ZwYzcvN1RyZmNNMy9oUXQweVE2MEl1QzQyZjhVZXo0WUVIWjZrOWxvbFBQaVFwRnNmVEthcHZWWXh6MCtYZ0pBUTNRUEFEY2VPSHJVclpXZEhWYzd0ZU9tbGRsVnRKMTE0d1FWRzczekRYV29mOWRBSEhwRExycnpTWHJMcVM5Uk5KMVhrVU4yRTZ0NnpwMnpjNU1MUldUNUk3ZE5WVmZJTEc3WEZNK0hoUnlUandQK2ZUR0ZLY01VS0VqTjVvZ1FZMmxOYkVOU0ttc2xQUHkwdFdyV1NoWXNXNlY3djJyeGxpejI3MysrbW0reDZLeWFGaG9aS2Q4Tkpwcko0OFdMZGNvZTZwcW9pb0NhcG14dnFkQmlUU05EaFBWbFpzdStsVnlYcHAxOTFoemtxS2E4MGFaeUVsQzJqZXdDNDVkang0L2J5OVRQWnZYdTNYRzRsWER0MzdkSTl6aW1NQTMxL3BXYkQybmZzS00rLytLTFBMeFgvOHF1djVLTG16V1hzRTAvWU54M3cvMEtDZzZWQ2hRbzZLanoydi9HMk8yT2hpQWlwK3Z4MHZ4b0xxV01UdTE1empUd3ljcVI5UEpxdlVMUG5IOCthWmMrbS83RjBxZTQxNDdycnJqTitzMW90Y1RkNVNzUy9xYU15MVZZaWsyN3MxMCszekNGQmgrY2MvMzJKSkQ3L3NvN01paHB3aXhTL3BKMk9BTGhKelo2cnMyYi9UUlg0NnRXbmo1SGtYRkhWeHVIN2xscURWN1ZFM09tajBncVNTaVNlR0RkT1dsNThzYXhZc1VMM29tN2R1b1h1YUtyamZ5eVZBOU9mMDVGQmdZRlNZZmhRS2RLa3NlN3dmU3RYcnJTdkRRdDhZTlk4TzN2MjdyVnZVczk4OTExalM5NVZYUWQxREp4SnUzYnZOcDR3bjI3ZXZIbTZaVVpFUklSOXlvcHBKT2p3bExUOSt5WGgvZ2Z0SmU2bVJUUy9TQ29NdlU5SEFBcUN1dHQ5T3JVOGJjZ0REOGlTUC83UVBjNEtDdzB0dEh0Wi9ZazZyL2lLcTYrVy9TNVUzaTRJYWx0SDMzNzlYSjE1OHJLYU5XdnFWdUdRZnV5NDdCeitpQ3MxZUlwZmVabVU2WGU5am55ZldsTGR2bE1uaVU5STBEMitTOTJzSG5qbm5USnQrblFqU1hxUklrV2syelhYNk1pY2IxM2FoNjZlbzNrLy9LQWpNOVRwS2lWS2xOQ1JPU1RvOEF6MVFhUUtvYml4MXlvb3FyVEVUSjFrL0F4M0FEbjc3Vi83MDlUeE4yckd3SlN5WmN0S0tjTjd4MkRXK3ZYcjdSVVdKcytoOTRMSlR6MWw3eE9GU0xPTEx0SXQvNmVPUVUwWU9VclNFbkozeWtWK2hOYXVLVlVtanBPQVFQOUlCMzc4OFVlNXFrc1h2OW9pb3FyUGp4ZzVVcDU1OWxuZDR5eFZqZHkweFM0VndUeVZraUovR0xxNS83Y0J0OTJtVzJhUm9NTXo5ci8rcGlUOStJdU96TEgzblU4ZUw2R1ZvblVQZ0lKeStoTDNvMGVQMmtmT3FBR0pLZVhMbDdjTFRzRTNxV3JIc1QxNnlJRkU4emR5QzlLZEF3ZEtWeXZSd0g4MGJkcFV0L3hmNHJ2dnkvRnZ6TTg0QmhhSmxKanBVeVNvU0JIZDQ5dlVxcXR1M2J2YnM4NytScTBzRy9iUVEvTGVlKy9wSHVlMGJObFNpaGN2cmlNejFMRm5LVmJ5Yk5ybXVEalp1MitmanB5bnpxcHYxN2F0anN3aVFZY25uUGhqcWV5ZlBGMUhacFVlY0xPVTZOQmVSd0FLa3BvTi9kc2JiNzVwL0FpY3BoZGVTQVYzSDZXV0w2cUNUMXUyYk5FOS9ra1ZNWnd3ZnJ5T29QYWVWNnRhVlVmK0xYbk5XdGs3ZWFxT0RBb01rSXBqUmtsazNicTZ3N2R0Mzc1ZHV2Zm80ZmZGRmUrOCsyN0h0MytwYXVSWFgzV1Zqc3pZdDMrLzdMZStUUHRtN2x6ZE1rTXRiM2ZyaUZZU2RCUzQ5RU9ISkdISWNIV0xVUGVZRTltaW1WUWN3cjV6d0N2VUhtSzFWRGt4TVZIR2pCMnJlODFSeGFiZ214WXRXaVJ2elppaEkvK2s5b1MrL2VhYlVyUm9VZDJEa2lWS1NGUlVsSTc4Vi9xeFk3Smo4SU9TZGRKd3hmR0FBQ25kNzNxSjZuYXQ3dkJ0YXNhOGQ5KytkaExvNzFRUnlSdjY5Yk5YRWpuSmRGVnlOWHYrNysxc1RsT3JERXp1ZFZjMzl1KzQvWFlkbVVlQ2pnSmxuM2MrYklTazc5NmplOHdKS2xWS3FreWZ6SG5uZ0llbzVlejc5dTJUOTk1L1g1SnpPQlBkS2VyOFV2Z2U5VG9aTlhxMFBRanpWMm9BT09LaGg2UkpreWE2QjByNUNoWHN5c2wrTFN0TGRqMDVRZEsyL2JOb3Bnbmg5ZXRKOUVNUDJvbTZQeGo3NUpPeTNNVVRENEtDZ3V4aW8ycGxoL3BTVzZaQ3JIR2xXeXV6ZHNUSHk1MkRCamw2TFd6ZXJKbVVLV1AyaUwxdnYvMVd0OHc0ZXV5WXJEdHRSWjdUb2l0V2xHYlc4K1FXRW5RVXFQMXZ6WkFUQzM3VWtVSFdoVE42L0JnSkxZVG5xQUplcHFwVXI5K3dRVjU2MmZ6Umltb2dWYTFhTlIzQmw2aXE3YVlxKzN1Rk92Sm82SkFoT3NMZkdqZHFwRnYrNjlDWGMrVG9aMS9veUp5Z01sRlM5YVhuSk5CUGpxejcrZWVmWmVxMGFUb3lSeFZydk9MeXkrV0Y1NTZUWDMvNlNiWnQyU0o3ZCsyeXYvYnMzQ2tiMXE2VmIrYk1zVyt3MWE5WFQvKy96UG5LK2w1T3poYXJxdVFkREI4LytyTjFEYy9JeU5DUjg5VEpGMDZ2TERoZCsvYnRqUjlKZHpvU2RCU1lFMzhza3dOVG50R1JRVlp5WHZxMi9sTHl5c3QxQndBdmVmT3R0MlRMMXEwNk1xZHExYXF1ZnNEQ0dXcnYrYlBQUDY4ajg2cFVxU0kzMzNTVFBEMTVzc3l6QnNFYjE2MlRyWEZ4c20vM2J0bTBmcjJzVzcxYTVuLy92VHozekRNeWNzUUl1YVpyVjZsWHQ2NEU1K05Va0tqU3BlV2RHVFBzbVRqOFUrM2F0WFhMUDUzYXZrTjJqeDVyejZLYkZCQVNMSlVuUENGaGZsSWdWKzAzSHpCd29JN01VTFBpdlhyMnROL3pjNzc4VWdiZWZydGRzRkNkQnFLMm82Z3Z0U2M1SmlaR0x1M1VTY2FPR1NQTGx5MlQyWjkrS3VjM2JLai9GdWVwRlVYM0R4N3MySjU3OVhQZWNMM1pvL1pVWWMrOWUvZnF5SG5mV2Rka2s5eGMzcTZRb0tOQXBDVWVsSVQ3SDNEbnZQTUxtMGpGQjVtVkFMeHF6dGRmNjVaWmxhS2o4NVZFb1dBY1BIaFFmdnI1WngyWlU3MTZkWGx2NWt3N0lYL3QxVmZsdm52dmxmYVhYR0tmbTYrU2RsWEJWLzAzS21GczE2NmQzSG5ISGZMNDZOSHk2YXhac3VMUFAyVlhmTHg4L09HSDlrQzNTdVhLK20vTm5TbVRKa21NOVQzd3YveDVXMHBHY3JMRVcyT2h6T1BtaTV0RjNYYUxsT2pZUVVlK2I5S1VLYkxWWUZIUjRsYmlQWFBHREhuM25YZnNtN3U1cFpiQWQrbmNXUmIvK3F1ZDBKdXlmY2NPZWY2RkYzU1VmNWRZMXpwVk1NNlVaT3UxL3FkMW5UUkIzY1Q5NGd0eksxRFU3LzhpbDQ5NkpFR0g2N0l5TTJYWDZMR1N2dGZjVVFoL1U4dTVZcDZkS29FY3F3UVVlbTUvd01JWnExZXZ0by9nTStuaTFxM2xqOFdMN2RteXZNeGlxMEc1U3VCanUzV3ppN3l0VzdOR2ZscTRVSHIyNkhIV0k0eHU2TnRYYnJqaEJoM2xuN3B4c05NYXZPZm1hOVdLRmNiUFdsLzExMTluL042NS9WTDdZLzJSR2d2dGZtcUtuRnF6VnZlWVU2Uk5hNms0OUg0ZCtUNjFEOXZKNVBUZjFFcXJEOTkvWDNyMzZtWFBMdWVGMmxMMTdQVHBjdis5OStiNTd6aWJxZGJmNzlTMVVhMEd1TFJqUngyWk1YL0JBdDF5bHFvUWIvSjBqOHN2dmRUMTFVMGs2SEJkNHRzelhUbmpVNEtESkhyQ0V4SWFYVkYzQUNqTWF0ZXFwVnZ3SmFabnoxVmkvY0Y3N3prNmU2U0tSN1ZxMVVyZWYvZGRlM25zeFBIajdSVWMveDZvcTVuMnA1OSsydEVCdkVvdTFIbi91ZmxTUzNWTksyZDlqek45Nzl4K3Fac2YvdWpvRHd2azhBY2Y2OGljNEhMbEpHYnlSQW53bytkeGl2V2VVYWQvbURKNjFDaTU3TExMZEpSMzZyVTdmdHc0WTZ0QURoOCtMSysrOXBxTzhrZGRnOVFOU3BOKytmVlgzWExXWHl0WEdpMHlhN3JLL1ptUW9NTlZTU3RYeWI0cDVndDZLS1g2OXBhU25meG5PUmVBL0ZHenBQQTlKaXZ6S3BkYkEvR0tGYzNkeUZWSjVnTkRoOXF6Nm1yZnV0cXZxcWhLMEcrKy9ycTkveHlGUzhxdVhiSnp4Q2dSZzBXemxJQ3dNSWw1ZnFxRWxETi9JOFl0TzNmdWxMY05IcmZZb25semUzdUxVOVFLbFJlZmYxNGlEWjFFOEpwMURWRjcwcDJnYmtvVU1WaW5aYzNhdGZaTkJhY3RNRFF6cjZpdFI4MnQxNFRiU05EaG12UkRoeVhoM3FIbXovaTBoRGVvSjlHUFBxeHVDZW9lQUlXWldtNFljdzc3Q09FZGE5ZXQweTB6cXJ0VTJWL05iTjh4Y0tDOXJIelV5SkV5ZVBCZ2U5OG5DcGRNZmJ4czVwRWp1c2Vjd0tKRkpNelBUcTZZK2U2Nzlubmdwb3daUGRyeFdpV3Fic1d0dDl5aUkyZHQyNzVkRmk1Y3FLUDhLVnEwcUhUcDBrVkh6bE5IdzZscTdrNVMrODlORm9qcjJyVnJnYXppSVVHSEs3TFMweVhob1Vja0xXR243akZIZlNCVmVYNmFCQnJlVndlZ1lLZ2pZYTYrOGtvWi8rU1Q5cEUzQ2RZQTVlamh3M0xNK2pwNjZKQnMzN0pGZnJNR0FXci8zMTEzM0dHZks5M200b3Z0R1V2NG5zVEVSTjB5STgyRllxV25VM3M5SHhzMVNwNFlNOGJZM2xSNDEvNlhYNVBrSlV0MVpGYkd3VU95OC9FbjdmM3UvdURreVpQeW5NRzk1NjFhdHBTT2h2WmgzM1AzM2NiMk1iL2w0SW9DVlRmRHBDVkxsdWlXTS9iczJTTWJOMjNTa2JPQ0FnUGwrcjU5ZGVRdUVuUzRJdkhEaitYRS9FVTZNaWNnT0VncVRaNGc0WngxRFBpZHFLZ29lZnl4eCt3cTIxOTgvcmtNZS9CQmUrbFpoUW9WN09XREVkYVhtcVdzVkttU05Mdm9Jcm5yemp2bDJXZWVzWXQvZlRGN05za1F6aWh1ODJaN0ZzWnR2QjRMcCtBeVVicmxqdU56djVORG4zK3BJOS8ydy96NWN1REFBUjA1NzVhYmJ6YjJ2cXhtalVzYm5YKytqcHlsNm5Ra0pTWHBLSC9hdFcxcmY1YWFvdjZ0VGw1dmY3Y1NmcWVXK1A5YjVjcVZwZW1GRitySVhTVG9NQzU1elZyWk4yNlNXb2VpZTh3cHFmYWRYNUgvd2g0QXZFTU5sOVN4TlN1V0xaT1JqenhpSityblFnMjQxQkozK0NiVGlleUNoUXRsbThIam1vRFRSZlhzTHBITm11cklCZGJZYTgrVEV5VE5ZR0xybGxtelp1bVc4OVFLcTY0R2wzZXJaZExYeGNicXlGbjc5dTJUcFV1ZFdaVlJxbFFwdTJxNUtXb2ZlbXBxcW83eWI5RWljNU4vM2J0M0w3QWlsU1RvTUNyanhBbEpHRHBjc2d6dUYvcGJXUDI2RXYzSWNEV2EwejBBZkozNmNMei8vdnRsMWtjZkdTM2tCZTh5ZmN5V3FnWjlkZGV1a3BDUW9Ic0Fjd0tDZzZYU0U0OUxnSXZITm1VZVBTWTdSNDF4WmFMRWxKU1VGSm56elRjNmNsNHo2enBUcGt3WkhabHhtY0hFOStOUFB0R3QvT3ZWcTVkdU9lK0VsUmNzWDc1Y1IvbW5ickNhb0c3WTlML3BKaDI1andRZHhtUmxaTWpPa2FNbE5jN2MyWVIvQ3l4V1ZHSmVtQzZCNGVHNkI0QS9HSFRublRKcDRrVEhpL2JBZDFSem9iaWZPa08zV2N1VzhzR0hIem82dXdPY1NVVHRXbEwydnJ0MTVJN2o4K2JMUVI5ZTZ2N3JiNzhaUFZxdGsrRXp3Slc2ZGV2cWx2TlU4VFZWaE0wSjZsZzRWU3ZERkxWVndRbTdkdTgydHYrOFpxMWFjbDd0MmpweUh3azZ6TWpLa3NUM1A1UmpYNW03Mi9sZmdRRlNjZXhqN0RzSC9Fem5xNjZTeVpNbUdWL2lERzlyMUtpUmJwbDE4T0JCNlgvTExkSzBlWE9aOWNrbmN2VG9VZjBJNEx4eXQvYVhzTHAxZE9TT3ZlTW1TdXFldlRyeUxWOS8vYlZ1T1U5OXhuUm8zMTVINW9TSGg4djVEUnZxeUZtN3JXVDEwS0ZET3NvZmRUUmtHNFBIa3FyejBKM1loejUzN2x6ZGNsNzMyTmdDblJnZ1FZY1J5ZXMzeUw2SlU5elpkOTZ6dTVTK3RxdU9BUGlEMHFWTHl5c3Z2MXhnKzcvZ0hlcGNZcmR1MHFoQjQ0WU5HK1Q2ZnYya2JvTUdjdS85OTh1eVpjdnM1YldBazlTS3Y4cVR4a3VBaTZkTFpCdytJZ21QakxKWE9Qb1NWUVRzeDU5KzBwSHoxUEZpNmlnMDA5UjFyR0tGQ2pweTFyRmp4K3lDbDA3cDM3Ky9iamx2MDZaTmpxeFVNcmE4UFN4TWJyNzVaaDBWREJKME9DN2orSEZKdUdld1pDV2YxRDNtaE5hcUlaVkdqMlRmT2VCSDFDRG15YkZqN2J2NFFJMGExblUrT2xwSDdsSEh1NzM4eWl2U3FrMGJhZFNraVR3d2JKaGRpTW50WTluZ3Y0clVyeWVsKy9mVGtUdVNmdmxORHMzK1FrZStRUzF0WDc5K3ZZNmNwMDcvS0ZteXBJN01LbUh3KzZ4WnMwYTM4cS85SlpkSThlTEZkZVNzbmJ0MnlmYnQyM1dVTitxbTZkSmx5M1RrckFiMTZ4ZklaODdwU05EaHJLd3MyZlg0azVLNmJZZnVNRWZ0TzYvNjh2TVNhUEE0Q0FEdVUvdjBidXpuN3FBVjNxVUd6N0hkdXVtb1lHemR0azJlZmU0NWFkMjJyZFNvVlV2NjNYU1RmRHhybGwwOUdjZ3pOYU02K0Y0SnFScWpPMXlRbVdsWGRVL1pibjZjNWhTVnpLVWF2REdtOWhxSHVyU1NvVnpac3JybHZOOFdMOWF0L0ZPbnBiUnMwVUpIenB2NzdiZTZsVGZ4Q1FuNVR2S3owKzNhYXd0ODlSNEpPaHgxY05hbmNuUzJDMFZJckRkT3hkRWpKYnhtRGQwQndCK28yZk9IaHcrMzkrb0JmN3ZuN3JzOWMxVGVYaXNwLytqamorV0dHMitVS3RXcVNZdFdyV1RNMkxHeTZNY2ZqUmF4Z24reWw3cFBlTUxWbFlDWngwOUl3cU9qZldhcHV5cUFabExWR1BkdWtKUXJWMDYzbkxkbnp4N2R5ci9Bd0VDNXllQ044dnh1V2ZqaGh4OTB5MW1oSVNGR2wvZm5GZ2s2SEhOeTR5YlpNL3BKVi9hZGw0aTlSa3BmVjdBektnQ2NWN2xTSmZ2dU5YQzY2dFdyUzQvdTNYWGtIV3JQK3ZJVksrVEo4ZVBsOGl1dmxFcldRTDlYbno3eXNaWEFxOEd5RTRXUTRQK0t0V2d1cGE3dnJTTjNKQzllSWdkbXZxY2piMU9uTEpoVXFuUnAzZkp0Y1hGeHV1V01LNjY0d3RqS2dwVXJWK2E1dG9lNnJuNWo2TWk5cGsyYkdxc1RjQzVJME9HSWpLUWtpYi83Zm5mT082OTdubFIrWWpUN3pnRS8xS2QzYjN0Sk0zQTZ0Ykppek9qUlVxeFlNZDNqUFdyUWVQTGtTWm45K2VkeXcwMDNTZjJHRGVXS3E2NlN6ejc3akpsMW5GV0Z3ZmRLa09GenVQOXQvOVJuNUpRUExIVlhOOEZNZW52R0RLbGVxNVlyWDA5UG02YS9xL01PSGpva3B4d2NoNWNvVVVMYXRtbWpJMmVwbFVqcW1MUzhVTmZUUHcyOUpxNjk1aHI3ODZhZ2thQWozN0l5TS8rejczekxOdDFqVGtCRWhGUjU1bW5PT3dmOGtGcGFOdUMyMjNRRS9GUFZxbFhsaVRGalBERjR5bzBUU1VteWNORWk2WDM5OVZLdlFRTzd5TnlPSFR1WVZjY1poWlF1TFpXZWZGeXRMZFk5NW1VbUpjdk9oMGRLVm5xNjd2RWVWWlRSeWFYYlo2SVN2cDA3ZDdyeXBhcXRtNkxPUVZjM0NaMmlyclU5ZS9UUWtiUFU3MVVWM2N5THpaczN5NEVEQjNUa0hQWHozbUJkcjcyQUJCMzVkdmlMcitUb3A1L3J5Q0RyalZQeHNSRVNjWjc1b3pBQXVLOSsvZnAyRWdaazU0NkJBK1hxcTY3U2tlL1l0MysvWFdTdVZwMDYwdmVHRzJURlgzL3BSNEQvVjZKamV5bldxWU9PM0pHODlFODU4UDZIT3ZJZXRRejZGTWNjNWs1V2x1T25USmljVWY1cXpoemRPamZ6RE8wL3Y3aDFhNm5nZ2VYdENnazY4a1h0Tzk4OVlwUjlVVEN0ZUxldUV0VzdwNDRBK0p0T25UcHg3amx5RkJ3Y0xEUGVla3N1YU5KRTkvaWVUei83ekM0c3B4SjFkUjR3OExjQTYvcFhlZXhvQ1NybHpwRmZmOXMvYWFxYzNPVHMvbVducVBPeTg3cFh1YkRKeU14MGZJYStUSmt5Y3ZsbGwrbklXVXYrK0VNeThsQ284THZ2djljdFovWHQwMGUzQ2g0Sk92SWwvdDRoa3BXU3FpTnpRdXZVdGo2MEhyTm4wUUg0cCtzOTlPRUk3MUw3SXIvKzZpdHAwcml4N3ZFOWFwbjdKNTkrS2syYk43Y3J3Q2NuSit0SFVOaUZsQ3NyRlI1OVdFZnV5RHg1VWhJZWZGZ3lyV1RZYTFUQ2VmVG9VUjJoSVBUcDFVdTNuTFZ2NzE1NzJmKzVPSGp3b1B5NWZMbU9uQk1SRWVHcEFyVWs2TWlYTkpmT080OTVkcW9FRlMycWV3RDRtMHJSMFZLdlhqMGRBVGtyVzdhc3pQdnVPN244MGt0MWoyOVNCWjFVQmZpTDI3YTE5MVVDU3RRMTEwalJEdTEwNUk1VGE5ZkovbGRmMTVGM3FKdFoxRzBvV0IwN2RwU1FrQkFkT2Vla2RmMDcxKzArYTlhdWRYU2YvZC9hWEh5eDBTUHd6aFVKT2p5di9NTVBzdThjOEhOTm1qUXhNZ0NBL3lwWnNxUjg5dW1uTXVUKysrMHplMzJaR25TMnZlUVNtZnZ0dDdvSGhWcGdnRVNQR2lrQkxwLzlmK0RGVnlYWlN0UzlKTjFIem1yM1o5SFIwWEp4cTFZNmN0YlhYMyt0VzdtemFORWlJemRzYmpSNDVudGVrS0REODlKVTlVN3VuZ0orclJyRjRaQUhZVllDTSttcHAyVFdSeDlKbGNxVmRhOXZTang0VUhyMDZpWHZ2ZisrN2tGaEZsNDFSc29QRytMcTFyNnNsQlRaT2ZJeHlYSzQwRmgrc1AzREcvcjI3YXRiempyWDVlcno1OC9YTGVlb2JWT205dG5uRlFrNlBPL2dxMi9Lc1o5LzBSRUFBUDkwVGRldXN1cXZ2K3paZERYWThsV3FJTmFBZ1FObDFpZWY2QjRVWm1WdTZDdmhEZHpkK25OcTlWclorOEpMT2lwNHhkamVtR3RxSlZGa1pLU09uTldoZlh2N2hxalQxT3FoL2Z2MzZ5aG5pWW1Kc3ZUUFAzWGtISFhXZTFSVWxJNjhnUVFkK1JMWm9wbHVtWk9WbWlZN0h4d2hxYnZObm9NSkFQQmRSYTJCdkpwTi84c2F3UFh1MWN2WVFOVzA5UFIwdWYyT08yVDVpaFc2QjRWVllHaW9WSmswUVFMQzNWM3Fudmo2MjVLMGFyV09DcGFwSTc3OGtYcW0xRWtYSnFnalVCczJhS0FqNTZqbDZyOHRYcXlqbkMzKy9YZjcrdWkwL2pmZHBGdmVRWUtPZktreTlTa0pLbVArcmxQR2dVU0pIL3lBSnl1TUFnQzhvM0xseWpKenhneFp1WHk1M0h2UFBSSlZ1clIreEhja0pTVkovNXR2Wm5rdjdCbzhaVzYvVFVmdXlGSlYzWWMvWWxkM0wyaXFOZ24xU1hJbndPQU11cHFkdjdsL2Z4MDU2N2ZmZnRPdG5QMzAwMCs2NVp6eTVjckpwWjA2NmNnN1NOQ1JMeUhXQzd2S00xTWtJTVRNSGJ2VG5WeTZYUFk5KzRLT0FBQTRNelhyVnExYU5aazZaWXBzMnJCQjNucmpEV25Wc3FWUHpjWnQyTGhSSmt5Y3FDTVVXdFpydHZ5ZHQwdG9yWnE2d3gycGNadGw3NHN2NjZqZ3FJU3pTSkVpT2tKT1ZCSWRHaHFxSStkMXZ2cHFDVFB3OTZ1Wjhkd1VmdnMxbDRuOHVWRFYyOVhxSzY4aFFVZStGV3ZkU3FLc0R3ODNKTDc4dWh6NzFmazNLQURBUHhVdlhsejYzWENEL0xSb2tXeGN0MDRtakJ0bkQ4cE1ERFNkOXRJcnI4aStmZnQwaE1JcU1EeGNLazk0VWlRb1NQZTRRNDI1VGhnNGMvcGNxSDNQNFM1WHMvZFY1Y3FXTlpxZ3EycnVqUnMzMXBGelZxMWFaUjg1bVJONy8vbXlaVHB5VHUvZXZYWExXd0t5REI0dW1KV2VMcHU2eEVycXhqamRrNzJvUVFNbGV0aFFIZjJUV3RhOG9WVjd5VGgwU1BlY1dZTzF5eVhRUi9lY21aVDQ1Z3paODhRRUhUbXJZZHdhQ1FnT3RuL1gyMjY5UTVKKy9sVS9ZazV3dWJKUzY2dlBKTVQ2czdBNk1uK0JKQXdZcEtNeks5RWpWbUltbi9uM25wV1JJWEdkWXlWbDR5YmRrNzJTM2JwS2xXbVRkZVIvVHNYSFM5eGxuZTNYc0VtQlJZcEluUVhmU1lnTFcwSk11SC9JRUhueEpYT0ZnKzYrNnk2WlBtMmFqcnhOZld3MmF0TEVudUUwNWR0dnZwRk9IVHZxeUJsTm16V1RWYXZON1N0OTUrMjNwVytmUGpyeU52VTdQSGJzbUh3emQ2NHN0QkozdGNSeXk5YXRSdlkzNXRld0J4NlE4ZVBHNmNoWmF0QmJ0VVlOdXppZEtYdDM3ZkpjQWFaL1c5ZXluYVFmT0tBamM2SW5qWmN5M1dOMWRPNTJUWGhLRHI3K3RvN2NFVkkxUnM2Yk0xdUNDbWg4cmQ2VGRSczBrQjA3ZHVnZTU2blZOdTNhdHRXUjd6cXZkbTE1YVBod0habngwc3N2eTMyREIrdklPUXQvK0VIYXRHbWpvLy8xeWFlZlN0OGJidENSTTlTNTUxczJiWkx3OEhEZDR4MGs2SVdBR3dtNmtuYndvTVJkM1UweTlwdi9rSXRzM1ZKcXZQMmFCQlRTZlVrazZNNGhRYzhkRXZUL1I0SitacjZVb1ArYlNnTFVUTFZLMk5XWG1xbFJsWVVORHBGeVRjMWFxWmwvRTROSUV2VC84SlVFUGVQNGNkbDQ5YldTN25MUjNOTDkra3JseDBmWnkrMEx3aVVkT3VTNmtGaGVYSFhsbGZMbDU1L3JDRGxSMThWcU5XdEttc05IOFkxNDZDRVpPMmFNanY3WGdOdHZseGt6WitySUdYMTY5N2JybFhnUlM5emhtQkRyQTdqeWxJbXVMTUZLWHJ4RTlyN3dzaG9wNng0QUFQSkdWVDZ1VkttUzNENWdnTXorOUZQWnNIYXQvUHpqajNMWEhYZEkxWmdZWTVXUmMyUHYzcjJ5Y3RVcUhhRXdDeXBXVENvOWFTVXhnZTRPM3c5L09FdU8vMWx3UzkyYlhYU1JicG14ZXMwYXljakkwQkZ5VXJac1dXblpvb1dPbkpQVFBuUjFBM0h4a2lVNmNrNlA3dDExeTN0STBPR280bTB2bGpKM3ViQWYzWG9USDN6eFZUbit4MUxkQVFDQU0xVFJvQmJObTh1enp6d2o2NjFrL2FlRkMyWFFYWGNWU0VYNHpNeE0rZnJycjNXRXdrNk5zMHBjMDFsSDdsQXJ6SFlPZjBReWtncm1WSUhhdFd2cmxoa25UcHl3dDd6ZzdGU2h6V3U2ZHRXUmM5U0t0SlNVRkIzOTA1NDllMlRMbGkwNmNrYjU4dVh0bFJOZVJZSU94NVcvWjVCRU5EZDd0MVBKU2t1VG5mYzlJR2t1TEtrSEFCUk82b2luWnMyYXlUUFRwc25Xelp2bHBSZGVrTnExYXVsSDNiSGtqejkwQzRXZE9rb3IrdUZoRWhUbDdzMml0QjN4c252aTVBSlp1ZGpDd0l6dDZWUnl2aW51N050eDhSL1hYbnV0NHlkaXFKVkMyN2R2MTlFL3FUb2hUcTl3Nk5LNXM5R0NldmxGZ2c3SEJZYUZTc3d6VXlTb2JCbmRZMDY2bFp3bkRIdFlzdEpabWdRQU1Fc2QrVFRndHR0azVZb1Y4dVRZc1JJUkVhRWZNVXZ0aVdjSkx2NFdVcmFzUkk4ZTZmcFM5eU1mZnlMSGZqTzNGenc3MWF0Vk0zclVtbHFsOHNNUFArZ0laNk4rSDgyYk5kT1JjK1prczFMSTZSVkU2amk2M2oxNzZzaWJTTkJoUkdpRkNsTDU2WW4vTFNCblV0SlB2OHErNTEvVUVRQUFacWxaZFZVdCtmTlBQNVVpTGhTblZVWHNmSFVKcmhjcjQvdURrbGRlSWNVdWRiYVE1Tm5ZUzkySGpaRDB3NGQxanp2VWxwUDY5ZXJweUF5VkhIcWhLS1N2TUZFUTlFeUZBSk9Ta2h6ZmYxN1J5bEZhdDI2dEkyOGlRWWN4eGR0Y0xLWHZ1RTFIWmlXcS9laS9zd1FRQU9DZURoMDZ5UEJodzNSa2pwcmhVL3RrbmFhSzN6bTlWUFhmMk50clJrQlFrRlI2L0ZFSkxGRmM5N2dqZmQ5KzJUVitrcXRMM1lPc24vWFNUcDEwWk1aZksxZkt0bTNiZElTenVlTHl5eDB2bnJsOHhZci9PUTlkSFgrcEtzYzdxVnUzYnZiNStsNUdnZzV6ckEvOWl2ZmZJeEV0blY4RzgyLzJmdlFISG5MOXJpNEFtS0FTTWllcG1TR25qOFhCZndvbTNYYmJiY2FYdXF2ZjM3OEhyazVRZzFUVENickpJOXdLdTlEeTVhWDhnME4wNUo2am4zOHBSeGY5cUNOM1hISEZGYnBsaGxycDhaWkhqOXp5b2hvMWFrakRCZzEwNUF4MTFPV3UzYnQxOUIrTEZ5OTJkR1dEdXRuVHorSHoxRTBnUVlkUjZwenlLcE1uU2xDcGtyckhISFV1YU1KREk0MmZadzBBcGgwL2ZseTNuUEhKcDUvSytnMGJkQVFubFM1Vnl0NlQ2WXRNSitmS1pvZXJMK09meXZUcUtSRk5MOUNSU3pJelpkZGpZeVg5NkZIZFlaNDZWVUVkOFdYU2pIZmVzWmRVNCt6VVB1NGIrL1hUa1RQVVRaTGZmdnROUi84eFo4NGMzWEpHMWFwVnBkSDU1K3ZJdTBqUVlWeFk1VXBTYWVwVDluSXMwMDdNV3lENzMzaGJSd0RnbTV4YzBoY2ZIeS8zRFI2c0kvOXk4T0JCT1hDZ1lFL3lVQU5WdFNmZE5EWHo0N1R3OEhBSk5KeWtxMldyTUNjZ09FZ3FqMzlDQWlMQ2RZODcxS1RJemtkSDI4bTZHOVJ5Nmw2R0MzdXA0N3pHUHZHRWpncWUweXVwbkthT0tYTzZFdnJjYjcvVnJmL2NxUDdsWHdsN2ZsMTd6VFdlcnQ3K054SjB1S0xFSmUyazFLMDM2Y2lzQTFPbXkvSEZ6aGFVQUFBM3JYQW9xVkg3Zi92ZGVLTWtKaWJxSHYraGt2T3UxMTRyelZxMHNDc3dGK1JnMXZSdVhKV2NGeTl1WnE5eDQ4YU5kY3NNTlNORzhTMnpJbXJWbEhMM0RySzNGcnJwMkxmZnk1SDVDM1JrbnFxOGJYclZ4NnV2dlNacjE2M1RVY0ZRMjVIZWZmZGR1ZW5tbXoxZFpMRmF0V3BTdlhwMUhUbERGWXI3KzJkZXRXcVZveXNhMU0zVVcvcjMxNUcza2FEREhkWUZ0ZUtRK3lTOFNTUGRZYzUvcW93K0xPbUhqK2dlQUhDT0dpQ1dLbFZLUjJhb1k3WHltOVNrcEtUSUxiZmU2bmdGWEM5UU15dlh4c2JhejVQYXM5akZTdFQ3MzNLTDdQN1gva1UzcUwzaHBtK0FoQVFIUzRrU0pYVGtyTXFWS3VtV0djdisvTk0rNHhobWxlMS9vNFRWcTZNamwyUm15YTZSb3lYTnBWVXN6WnMzTjE3Ti9ZU1ZFS3FibWtkZFhMNy9OM1hOWDdseXBWeDYrZVZ5eTRBQjh2R3NXZkxzYzg5NTlnYVhXam5VNy9ycmRlUU1kZU4xMTY1ZGRsc2w2MDcrN09mVnJpMjFyUzlmUUlJTzF3UkdSRWpNYzFNbDBOQXN3T25TZCszNXovbm9IbDhlQk1BM21TNEt0bnJOR2xtN2RxMk96dDNKa3lmbFppczUvOUxoL1h0ZW9LcVo5KzdiVjViODhmOG5kNmd6d2ovODZDTnBmT0dGOHRTa1NVWXFubWZucDU5L05uNWpvRW1USnNhVzBWY3luS0NyMzhYalk4YmtlYUROTVcyNUV4Z2VMbFVtUEduWC9uRlR4c0ZEc3ZPeHNTcTcxRDNtcUpVa1ExellyclBHdXZiMjZ0UEg4Vm9nT1ZGSjZXMjMzeTR0TDc3NHY4ZU5xZmZNcU5HalpmNzgrWGJzUmRmRnhqcTYvVWJkOEZRMzlSU256NmJ2MHFXTDQ1WG5UU0ZCaDZ2Q0tsZVdTbE1tNk1pc0UvTVh5WUYzM3RNUkFEakgxR3ptNmNaUG5KaW5wRVlOOUdLN2Q3Y0x3L2tiTldEdWU4TU5NaStiZ2R1UkkwZmswY2Nla3pyMTY4dTA2ZE9OejJ5ci9lK0RoNWl2b24zaGhSZnFsdk5hdDJxbFcrYk1mTzg5ZWVPTk44N3A5YnhwMHlZWlBIU290R3Zmbmtyd3VSVFpvTDVFM2VMT2RzTFRIWjgzWHc1OThaV096RklKWWFYb2FCMlpzMkRoUW1uVHJwMnNXNzllOTVpeGRkczJHVFo4dU5ScjBFQm12dnZ1Lzl5UVVxOTl0VHBvKy9idHVzZGIxQkwzZW5YcjZzZ1ozOCtiWjIvUCt2SG5uM1dQTTI2em5rZGZRWUlPMTVXOHJKTkUzVGxBUjJidG56UlZrbGF0MWhFQU9NUHA0MlhPUkNYWUw3MzhjcTZUR2pYejhONzc3OHRGelp2TC9BWHU3UXQxaTFxeVAyRGdRUG4ydSs5MFQvWlVrYjNoRHo4c05Xdlh0Z3ZrTFYyNjFQRmo1clpaQStiT1hidmFBMnlUMUw1Sms4V3hhdFdxWlg4UGs5UnpmODk5OTltSnh1clZxOCtZY0t2WDcwWXJLWC9ublhma3lxdXZsa1lYWENBdnZQaWl2WTFCSlM3SWhZQUFxWEQvUFJKYXZhcnVjSWwxamRvejdpbEpkV0VyUTdGaXhlVFJrU04xWkpaS3psdTJibTJ2eWpuczRERythb1dUbWhWWEs0SHFOMndvMDU5OVZrN21jSXppL2dNSDVOcnJybk4xWlZCdXFaVTl2WHYxMHBFelZOMEtkYzEyc3E3SUJkYjFSQjBONXl0STBGRWdLZ3krVDhJYW1OMUhwR1JaRjhHRSt4N2dmSFFBamxMRmNVeFRpZm5RQng2UUlVT0gyck1uYWhuM3Y2aytkWGFzS2lqVXRGa3p1ZVcyMnlUeDRFSDlxUDlReVp2NjJUNmJQVnYzNUU2eTlSbWdibkswYmQ5ZTZqWm9JSTg5L3Jnc3N4SStOVHVUbDlVSmFzQ29LajFQZk9vcGFYTGhoYkxpcjcvMEkrWlVybHhaenJjRzhhYW9HYkNTSmMwZmhacGhQWGNmZlBpaE5HL1ZTaXJGeE5oSnVOcUcwY2RLVWxwZGZMRlVybHBWTHJDZTA5c0dEclJ2TUozK2VsZS9ON1UzRldlbmxycFhHamRXclFmWFBlN0lPSFJJZG80Y0xWa1o1cmNXWG4vOTlVYmZFNmRUeWJSYWxWTzNmbjE1Y1Bod1diNTgrVGtueXVxMXJGYnpxTzB3YWxWSW5YcjE1S291WGV6cjJabXU2MmV5YnQwNnVlT3V1enhaMlYwbDZFN2U1TnV3Y2FOODl2bm5lYnBHWjBkVmJ6ZDlJOUpKQWRZUDc5eFAveStxV05lbUxyR1N1akZPOTJRdmF0QkFpUjQyVkVmL2xKbWFLaHRhdGJmZi9EbHBzSGE1QkVaRzZnaC9TM3h6aHV4NXdzeXk4b1p4YXlRZ2ovczVUbTNiTGx1NlhpZVpTY202eDV5aVYxNG0xWjZmN3NwUmIyNVFWVk1UQmd6UzBabVY2QkVyTVpQUC9IdlBzajRRNGpySFNzckdUYm9uZXlXN2RaVXEweWJyeVArY2lvK1h1TXM2R3o4L1A3QklFYW16NERzSktST2xlM3pML1VPR3lJc3Z2YVFqNTkxdERUeW1UNXVtSSsvN2ErVkthZDZ5cGFNRGlKeW80N0JxV0ltVU9ndjQ3MlJLTGVmK2Zja1MyYmxybDZ0N0piUHp6dHR2Uzk4K2ZYVGtIRFZ6cmhJNXA1YnNxeUovWmFLaTdKc3NIVHQwa1BQUFA5OHVQRlc2ZEdtN1VycmFUNm0rMU1CWmZhbVpNMVdJN3BkZmZwSHZ2djllL3N6REFEMC9IbjNrRVJsdEpRZ21YZHV0bTN4ejJ2RkdYalQ0dnZ0azhxUkpPbkxXdXBidEpOMkZRbWZSazhaTG1lNnhPakxJdWk0bFBEWkdEci8va2U1d2lmWGVxdlRVT0lseTRXZjgyWG8vcW1KcUJaR3dsaTlmM2k0NDFySkZDNmxRc2FKOWJWYlhqckRRVUVtM3JobHFtYnE2cWFxS0k4YkZ4Y212aXhmTGdmMzc1ZWl4WS9wdnlMdW5Ka3lRb1M1c3F6a1g2bmZRdWswYis5cm9sTCt2d1U1UTEveTFxMWI1VElFNGhSbDBGSmp3NnRVazJycVFpd3QzdEU1OE8wOE96SmlwSXdESUh6VTRpN0NTWnJlb0dXUzEzUEt0R1ROazJqUFAyRitxdlg3REJrOGs1NmFvZ2E3YTQrM2tmbnAxVStWQVlxSzlkUHFweVpPbDMwMDN5WVhObWttMW1qV2xkTm15VXJWR0RYdlphWXlWd0t1NDVubm4yZnVnSDNuMFVmbnhwNTljVGM3VlRZTjc3N2xIUitiME1YQmp4V2t2dmZLS2JMS1NIZVNDV3VvKytGNEpLbGRXZDdqRWVtL3RuVGhaVXZmdDB4M21YTnk2ZFlFZG1hVldMYWtiQkpPZmZsb2VlUEJCdStaSHA4c3VremFYWENMdE8zYTBieHlvN1RocTVuM0d6Sm15ZWZObVI1SnpaZlRqajl2NzQ3MUV6VXgzNjlaTlI4NXdLamxYTG1qU3hLZVNjNFVFSFFXcTFGVlhTS20renU1ZHljNyt5ZE1sZVczQm5tMEp3RDlFUmtaS2h3NGRkQVFUVkhKKy8rREI4dnFiYitvZWQ2aVZDZkVKQ1k0TnFQTmowSjEzMmttNmFaZDI2aVRGaXhYVGtUZXBsUlFQUGZ5d2E2dFdmRjFJVkpSVUdqUEtsVW1RMDJVY09pd0p3eDh4dnlyTitybWVuakxGOFFKbFhuZktlaC9jMUwrLzdOaXhRL2Q0dzVXWFgyN1BWSHZSRFE0ZkJlY0dFblFVTE9zQ0d6MXFoSVNmYjc3Z1V0YXBVNUp3NzFESk9PNjlJaHNBZkUvUEhqMTBDMDVUU3lZZkhEWk1YbjM5ZGQxVCtEU29YMThlZnVnaEhabFZwa3dadWV5eXkzVGtYVjkvODQwcyt2RkhIZUZzU2x6YVNZcGQza2xIN2tuNmRiRWNuR1grRklraVJZckl6Qmt6N01KeGhjbSsvZnZ0V1hzdnJaNXExS2lSSjR1d2hZYUdTdGV1WFhYa08walFVZUFDdzhJazVvVm5KTEJZVWQxalR1cTI3Wkx3MEVoN0R6WUE1SWVhZFZRRFJEaExMVzE4Y3R3NGVmSGxsM1ZQNGFNR2xhOWFQMytZOWZub0JqWHo5Y2pERHp0Nm5yRUphdlo4K0VNUGNleGFMZ1VFQmtybHNhTWxLTXI4S294L3NINVBlOFpQa2xNNzRuV0hPWTBiTjVZM1gzL2RmczhVSnF2WHJKRkI5OXpqNkZMdy9GQXJHa3pVSU1tdnBoZGVLTldxdW55cWdRTkkwT0VKWVZVcVMvU1RqOXN6NnFZZC8yNmVIUHp3WXgwQlFONm9Ra0d4RHUrN015MHFLa291YWRkT1I5NmpFckJKa3lmTHVBa1RDdTFTWnBVa1B6TnRtalJ2M2x6M3VFTVZ5K3ZhcFl1T3ZFc1ZhSHhuSmpWbGNrc3RkYS93MElQMnZuUTNaU1VueTg3aEl5VExoU0p1cWtMMytDZWY5T3dTYTFNKy9PZ2ptZkwwMHpvcWVGMDdkN1lUZFMvcGYrT05Qdm02SUVHSFo1VHEybGxLOXJwT1J3WlpIeFo3eDArUzVIWHJkUWNBNU0yd0J4N3dtWmtiOWU5ODdlV1g3VXJ3WHFVR1VsMnNRVjZ0bWpWMVQrR2lCcmNQRHg4dXQ5MTZxKzV4ajNydXh6Nyt1R3V6OXZueHhMaHhkcTBBNUU1VTdMVlNwTzNGT25KUDhyTGxjdUN0R1RveVI3MTJWVEhGeHcyZmR1QkZVNmRQOTh3UmhPb21YNlhvYUIwVnZLSkZpOHBWVjEybEk5OUNnZzd2c0M2dzBTTkhTRmdkODVVV3M1SlBTdnhkOTBtR0gxYy9CbUJldlhyMTdEdjB2a0FOWHRWZXZKaVlHTjNqVFdxUTkvdml4ZmJadW9WcFJpdzRPRmhHUFBTUVBEWnFWSUg5M09yMXJJNTE4L3J6dm52M2Joay9jYUtPY0ZhQmdWSnA5RWdKaUlqUUhlN1ovK3lMa2hKdmZxbTd1cmsxNHVHSDVaV1hYcExJQXZnNUM0SmF2cjF3L254N1paUVhoSVNFeUkzOSt1bW80RjNVdEtsVXJGaFJSNzZGQkIyZUVsUzBpTVM4K0t3RUZqZGY4Q010UGtGMmpoeHQ3NVVDZ0x4UWljeVRUendoVlNwWDFqM2VvLzZOSTBlTWtBY2ZlTUNPNjV4M252Mm5seFVyV3RRdS92VEJ1KzlLeFFvVmRLLy9VdWZjUHp0OXVuM2VlVUV2RVgxZzZGRHAwTDY5anJ6clJTc1IyN2h4bzQ1d051SFZxa241WVVQc3lSQTNaWjQ0SWZGRGgwdW1DM1VEMUxYdTFsdHVrZG1mZlNabHk3cDh4SnlMU3BRb0lVK09IU3MvTFZvazlldlYwNzNlY0Yxc3JHZHFXVnpmdDYvbmJ6Wm1od1FkbmhOZW83cFVmTUpLbkYwWXBCeWJNMWNTUC9oSVJ3Qnc3dFF4V0srLytxb25sN3FyV1ZrMUkzcjZyR3k1Y3VYc1A3MU8vWHU3ZCs4dWZ5NWRLamYxNitjVFM2L3pvbXJWcXZMTm5EbHkrNEFCbmhoTXFsbXc5MmJPbEVibm42OTd2TWsrZG0zRWlFSmJxeUF2eXZUcExlRU42K3ZJUFNmL1dpVUgzbnBIUitaMTdOQkJmdi8xVi91c2RGOU4wTTVFSmI2WFhYcXAvUG5ISC9MUThPR2UvTXhScTNDOE1HdXRLdnVyMmdTK2lnUWRubFNxeTlWU3NxY0wrOUd0RC9aOTQ1NlNrM0diZFFjQW5MdU9IVHZLMUNsVENuejI4M1JxbWVjTHp6NHJqNDRjK1k5L1Y2bFNwWHhxMEtwbXdsNS83VFg1K2NjZnBYV3JWcDU2anZOREpjSzM5Tzh2UzM3N1RkcTJhYU43dlVFZHUvYkY3Tm1lVDlMVnNXdno1czNURWM0bU1DeFVxancxWGdMY3Z0bGxqYlVPUFArU3EyTXR0WlhudTdselpkd1RUOWg3a1gyWnVsNDNhTkJBdnZqc001bno1WmYyVFQydlVqY05lbmJ2cnFPQ282NnA2clBPVjVHZ3c1UFUwU0RxZlBTd3V1YVhZbWFxL2VpRDdwZU1wR1RkQXdEbmJ1RHR0OXVWaEwyUVFLb2w5M08rK2twdXZmWFcvL24zcUprRlZZSGVsNmdCNmdWTm1zaUNIMzZRTDYzRVVTWHF2a3p0amZ6ZVNoNWVlZmxseit3Zi9iZksxbXRJSlRocU50S0wxR3RDblVoUXljUGJTN3dvNHJ6YVVtYWcrMFVJTTVPVEpXSFl3NUtabHFaN3pGT3Jib1k5K0tEOHNYaXhkTHZtR3ArY1RhOWJwNDY4L2NZYjlvMjhLNjY0d2lkdVVIcmh1RFZmcjJGQ2dnN1BDaXBTUktwTW15eUJMcHd6bkxwNWkreDZiSXhkNFIwQThrSU5CdFQrM2JkZWY5M2VRMTBRMUwraDMvWFgyOHZDczV1VlZUTWNCZlh2eXkrMXhGTU5VaGN0V0NBTDVzMlRYajE3K3N4WjlPcDNveEx6OTk5OVYzNzkrV2RwWS8xK3ZENkFWRFBwYXNaT0ZhOEw5OUFXQTFVYzY0UDMzcFB2di8xV0d0UjNmOG0yVDdOZWMrWHZ1bFBDckVUZGJhZFdyNVY5ejcyb0kvZlVybDFiWm4zOHNmeTRjS0ZjY2ZubG5qL3ZYMUhMOHo5OC8zMVo4ZWVmY3IxMVRmZWxMVDVxbVh2MTZ0VjE1TDdpeFl2N3hKR1JPU0ZCaDZkRjFLMGpGY2VPc2w2cDVsK3FSei8vU2c3Ty9rSkhBSkEzYWpDMWRNa1NWODhiVjN2TjI3VnRLejh2V2lSdnZ2Rkdqa3Y3MU5KcU5ZdnV5MVJpMjliNmVkVmU2YTF4Y2ZMVXhJbHk0UVVYMk0rRDE2aUNUajJ1dTA1K1hMREFUc3g3OXVqaFU4djAxZXRsN0pneHNtVHhZdW5Vc1dPQlBjZXFrSjc2L3A5OThvbjlQSGEzbmxOLzJlN2dOclhVdmRLNE1lckNvWHZjay9qcUc1Szh2bUNPdVczVnNxVjg5Y1VYc2x6WHRTampzZFVyYXUrMk9tTHhMeXNwVjZ1RjFHdmNpOWUwczFIdjFkaHUzWFRrUG5XZDhQblB1Q3lEMVRXeTB0TmxVNWRZU2QwWXAzdXlGelZvb0VRUEc2cWpmMUtWSHplMGFpOFpodzdwbmpOcnNIYTVCRVpHNmdoL1MzeHpodXg1WW9LT25OVXdibzBFR0w1NFpHVm1Tc0tJUitYb3g1L3BIbk1DcklGSXphOCtrWWc2ZFhTUE54Mlp2MEFTQmd6UzBabVY2QkVyTVpQUC9IdlB5c2lRdU02eGtySnhrKzdKWHNsdVhlMlZEUDRxN2NBQjJUVnVvdldjbUYwOVlRK0lIbnRVZ2wwNG9jQ0VHZSs4SS9Pc0FZTXBsM2JxSkRmMzc2OGovNUJodmMrK21qTkh4b3dkSytzM2JMQmpweFd4UHZOVW92ckl3dzlMOCtiTmN6MHpwQ3BnLzJZbFhFNGFkT2VkMHJwMWF4MjVUejIvTytMajVRdHJBUDY1OWJWMjNUbzVldlNvZnRROTZ1WkJ5WklscGRsRkY5bUplVGRyb09yTGV5RlBsMmw5SHE5WXNjSSs0bXpCd29WeTRzUUovWWdaYXRhd1JvMGE5cDdXL2pmZFpDKzdONUdVSjR3Y0xlbkhqdW5JbktqciswanhWaTEwVlBEMnYvbTJKSzFZcVNQM2hKOVhXeXJlYzVjOW0xK1ExUFZoN3R5NU1tUG1UUGx6K1hJNWZQaXdmc1FkNm5xdGlveDJ1T1FTT3pGdjJiS2xSUHBKSHFNKzg4YU5INitqLzNVeU9WbSt0cDU3RTUrTDZzYXRXbDNseTBqUUN3RmZUOUNWRE91RGMvTjF2U1YxeXpiZFkwNVk3VnBTNjh0UEpEQThYUGQ0RHdrNjREdlMwdExrajZWTDVaVlhYcEc1MzM0cng2MmtKcStEa2tCclFLdG1ORlV5cmdZZ25hKysyazVhdkw1VTJtMXFhSFB3NEVGWnZYcTFmUHZkZC9iZ2U4a2ZmMGk2TlM1UlgwNVNNMXhxb0swUzhoYlc3K1ZxNjNlaWlxdXBKTjJmcWJQSXY3RUcyTE0rK2NSK2JrK2VQR2tuOFBtaFh0dHF4VUZySzFGUlMxVGJ0V3RuRjhUeWhTWEo4RzFIamh5eHJ4T3E4T0RpeFl0bDlabzE5clhDeVFSU1hTdlVsaHgxcmJqOHNzdWtmZnYyOWg3emlFSnlidnZwUHBzOVczcjM3YXNqNTZqbmQxZDh2TTlzZmNvT0NYb2g0QThKdXBLOGJyMXM3WG1EWkNXYkwrWldzbmNQcVRMaGlRSy91NXNkRW5UQU41MDZkVXJXV0FNL2xiRC8vdnZ2RXArUUlJbFdJaGx2RFNoVWduTTZ0ZiszZkxseWRoRXhWZlN0V2JObTByQmhRMm5jcUpIZkozOG1wRnBqaVowN2Q4cWF0V3Z0UHpmRnhjbldyVnZ0Z2JtYVNVdEtTckpuNE05RS9RNmlTcGUybjNlMXY3R2FsVFRXcTF0WHFzVEUyTCtUeXBVcUZjcEI5dC9VYzdmV2VsNVhybG9sNjlldnQyZlAxR3lrZWw2M2JOa2kveDVvVm9xT3RtY08xWmM2NS82Q0N5NlFtalZyU2lQcnRSMVRwUW9KT1FxY1doMnliZHMyZXlXT3VsNm9tMURIamgyenY5UTFZL2VlUFpKOGh2R29TZ3lqSzFhMGJ6U3A2NFc2Z2FwdTJLbXE4dWRiMTRvcTF1dGIzWWdxek5SblhZdldyZTFyaGRQNjNYQ0R2UFhHR3pyeVhTVG9oWUMvSk9pS09yTjh6eU9qZFdSV3BXY21TK2xydXVySVcwalFBZjl4dG85aFpzZk55KzFRaU4vRnVjbnBlZVc1aEsvS3pmV0MxM2YyWG52OWRSbDB6ejA2Y282NnNmZkRkOS9aQlRoOUhRbDZJWEJrOWhkeTRPWFhkZVNzV2w5L2JpWG9MdDdwdGw2dXU2YzlLeW1ienY2YXlxL0FZc1drOHBoUkV1VEIxeFFKT2dBQUFIekp2bjM3cFBFRkY4akJzK1IwZWFHMkMveTFmTGxmck1BaFFRZDhFQWs2QUFBQWZJVktPVys1OVZaNTc0TVBkSTl6MUlxRjExNTV4UzRtNlE4NG53SUFBQUFBWU16N1ZtSnVJamxYeXBVcko5ZkZ4dXJJOTVHZ0F3QUFBQUNNK1BYWFg0M3NPLy9iblFNSCt2elo1NmNqUVFjQUFBQUFPRzdWNnRYU3EwK2ZNMWE5ZDBMRmloWGx2bnZ2MVpGL0lFRUhBQUFBQURocS9vSUZjdmtWVjhqK0F3ZDBqL09HUC9pZ2ZmeWxQeUZCQndBQUFBQTRJaTB0VFo1LzRRVzVOamJXU01YMnY5V3RXMWNHM242N2p2d0hDVG9BQUFBQUlGOVVwZmIxNjlmTDFWMjZ5SkFISHBDVWxCVDlpUE5VNWZZcGt5WkphR2lvN3ZFZkpPZ0FBQUFBZ0R6YnNHR0QzRGxva0Z6WXJKa3MrdkZIM1d0T3J4NDk1SXJMTDllUmZ5RkJCd0FBQUFDY2swT0hEc25zenorWHpsMjZTS01MTHBBMzMzcEwwdFBUOWFQbVJGZXNLTTlNbjY0ai8wT0NEZ0FBQUFESVVWSlNrcXhidDA3ZWV2dHRpYjN1T3FsZXE1WmRvZjM3SDM2d2w3ZTdJVHc4WEQ1NDd6Mkppb3JTUGY2SEJCMEFBQUFBSUptWm1YTHExQ2w3ZG56RHhvM3kxWnc1TXVxeHgrVHlLNitVV25YcTJFdllCOTU1cDh6NTVodGpSNmRsSnpBd1VCNTc5RkZwM2JxMTd2RlBKT2dBQUFBQVVNaWRPSEZDV3JkcEk0MmFOSkVhdFd2TCtZMGJ5M1U5ZXNqRVNaTms0YUpGa3BpWUtCa1pHZnEvZGwrZlhyMWs2SkFoT3ZKZkpPZ0FBQUFBVU1nVktWSkVkdTdhSmR1MmI3ZVhzM3RKMnpadDVPV1hYcEtnb0NEZDQ3OUkwQUVBQUFDZ2tGTkhsN1Z1MVVwSDN0SDB3Z3ZsMDFtekpDSWlRdmY0TnhKMEFBQUFBSURVT2U4ODNmS0dpMXUzbHJuZmZDT2xTcFhTUGY2UEJCMEFBQUFBSU0yYU5kT3RncVZtODYvcDBrVytuak5IU3BVc3FYc0xCeEowQUFBQUFJQlVxVnhadHdxT1NzNkgzSCsvZlBqQkIxSWtNbEwzRmg0azZBQUFBQUFBaVltSmtXTEZpdW5JZlNWS2xKQjNaOHlRcHlaT2xKQ1FFTjFidUpDZ0F3QUFBQUNrZVBIaUVoNFdwaVAzQkFZRXlHV1hYaXJMbHk2VlhyMTY2ZDdDaVFRZEFBQUFBR0RQV3J1OUR6MjZZa1Y1NmNVWDVhc3Z2ckJuOEFzN0VuUUFBQUFBZ0sxQmd3YTZaVlprUklUY1BXaVFyRnl4UW02OTVaWkNjY1o1YnBDZ0F3QUFBQUJzRnpacG9sdG1oSWVIeXgwREI4ckt2LzZTNlZPblNzbENWcVg5YkVqUUFRQUFBQUMyT25YcTZKYXpxc2JFeU5qSEg1Zk5HemZLODg4K0s5V3FWdFdQNEhRazZBQUFBQUFBVzNSMHRCUXRVa1JIK1ZQSitydjZYWCs5ZkQ5M3JteGN2MTVHUFB5d2xDOWZYaitLTXlGQkJ3QUFBQURZaWhZdEt1WHltRVNyLzIrZDg4NlRPKys0UXhiTm55OGIxcTJUdDk1OFV6cDA2TUFlODF3aVFRY0FBQUFBMk1MQ3dpU21TaFVkblZsQVFJQmQ1RTN0SDI5L3lTVnkzNzMzeXR5dnY1WU5hOWZhUmQrZWUrWVp1ZmppaSszOTVqZzNKT2dBQUFBQWdQOXEyYUtGL1dlNXNtV2xjZVBHMHJGREI3a3VOdFplb2o1enhneVpQMitlckxlUzhWM3g4VEx2dSsvazZjbVQ1ZEpPbmV6bDY4eVU1dzhKT2dBQUFBRGd2MFk5K3Fpa25Ub2x1eElTWk5tU0pmTGQzTG55MFFjZjJFWGUrdlR1TFczYnRMSDNxb2VHaHVyL0I1eENnZzRBQUFBQStDOFM3NEpEZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIdUFqQ1hxQS9iK3p5VHgxU3JjQS81YVpmRkszY2hERS9UY0FBQURBbC9qRUNENHdORVNDaWhYVFVmYVNWcTNSTGNDL25WeTJYTGV5RnhKVlJyY0FBQUFBK0FLZm1XSUx2NkN4Ym1YdjZOZHpkUXZ3WDFscGFYTHNoL2s2eWw1bzVXamRBZ0FBQU9BTGZDWkJqenkvb1c1bDc4UzhCWkorNkpDT0FQOTA3SmRmSlgzUFBoMWxMN0pGTTkwQ0FBQUE0QXQ4SmtFdmVuRXI2MStiODBiMGpLTkhaZmRUVDR0a1p1b2V3TDlrSkNmTDN2R1RSTEt5ZE0rWkJaVXZKK0hWcXVrSUFBQUFnQy93bVFROXJGcFZDYTFlWFVmWk8vcnA1NUw0eVdjNkF2eEhWbnE2N0JvNVdsSTNiOVU5MlN2ZXFZTUVCUHJNMnhzQUFBQ0F4V2RHOElHaG9WS3FWM2NkNVNBalEvYU9mRndPdlBPdVpGbHR3QjlrSkNWSi9JTVB5OUV2NXVpZUhGaUplYW5lUFhRQUFBQUF3RmY0MUJSYlZOL2VFbFNxcEk2eXAyWWE5ejQrVHJiZmZwZWMycnFOSmUvd1dlcTFmT3luWDJUenRUM2xtRXJPejdLMFhZbHNjWkVVeVVYTkJnQUFBQURlRXBCbDBXM0hxZVJpVTVkWVNkMFlwM3V5RnpWb29FUVBHNnFqN08xLzVYWFpOM0dLanM0dUlEaFlJcG8xbGFMdDIwbEVyUm9TVkxhc2ZnVHdxS3hNU1l2ZkpTYzNicFRqMy84Z0taczI2d2ZPTGlBMFJHcDgrb0ZFTnN3NVFWZXJTK0k2eDByS3hrMjZKM3NsdTNXVkt0TW02d2dBQUFDQUtUNlhvR2VtcHNubTJKNlNzbTZEN2dId3QxSTNYUytWeHp5bW8reVJvQU1BQUFEZTQzTlZwQUpEUTZUSzFFa1NXS1NJN2dHZ2hOV3ZLOUVqaHVzSUFBQUFnSzh4bTZBSEJGai95L2xvdFA5S1Q5ZU5zNHVvYzU1VW1qNUpBa0pDZEE5UXVBVlhLQy9WWG45SkFzUERkYzlacUhVenVWdzhvN2FKQUFBQUFERFBlSUllR0ptN21lN2NIQjExdXBLZE9rckY4V1BzUGJkQVlSWVVWVnFxdmYyYWhGYXNxSHZPTGlzdFZUS09IOWRSem9LclY5VXRBQUFBQUNZWlRkRFZPY3pCdWFpNnJwemFzVU8zY3NsSy9xTjZYQ2RWWG5sQkFvc1gwNTFBNFJKYXA3YlUrT1I5ZTFYSnVVZy9kRmpTOXgvUVVjNUNLbFRRTFFBQUFBQW1HZCtESG5aK2ZkM0tXZHFXYlpLeWM2ZU9jcTlFKzNaUzY4dFBKS0o1VTkwRCtEKzE3THhrMzE1UzY3T1BKTHhhTmQyYmU4Y1gveTZTa2FHakhBUUVTRmlWeWpvQUFBQUFZSkx4QkQzaXZOelA3QjMrK0RQZE9qZGhWYXRLemZmZmtlaEo0eVNrYWhYZEMvaWhvQ0NKYUhhaFZQLzRYYWt5Ym93RVJVYnFCM0pQVlhBLy9QRW5Pc3BaWUVTNGhGVS85eHNBQUFBQUFNNmQwV1BXbExURWc3S2hSVnVSekV6ZGs3MlF5cFhrdk8vbldFbEJoTzQ1ZDVrcEtYTHN4NS9sNER2dnlxblZheVh6V083MjJRS2VwYmFLUkpXV3lOWXRwY3lBbXlXeVhqMEpzQkwxdkVwYXRWcTJkZTlySDRONE5xRTFxa3VkSDc2eFo5SUJBQUFBbUdVOFFWYzJYZHREVWxhdDBWSE95ZzY1VnlyY2Q3ZU84aWY5eUJFNXVYR1RKQzlmSVNtYk5rdjZzV09TbFpxbUh3VzhLeWd5UW9LS0Y1ZndDeHBMa1NhTkpheGFOYnN2djFSU3ZxWHZUWEp5MlhMZGs3UFN0L1dYU28rTzBCRUFBQUFBazF4SjBQZTkvSnJzZitwcEhlVXNNREpTcW4veW5qMUxDTUJaQjk1NVQvWSsvbVR1amxnTENwU2FYMzRxa2ZWNUx3SUFBQUJ1TUw0SFhTblorYXBjTDhuTlRFNlcrRHZ2eTFQQk9BRFpPN3J3UjlrM2JtS3V6ejhQcTFWVElzNnJyU01BQUFBQXBybVNvS3NxMEVXdnZrSkhaNWNXbnlCYis5d29KemR2MFQwQThzeEt5STk4KzcwazNIWHZPVzN4aUxybEpydGFQQUFBQUFCM3VKS2dLK1h1dlAyY0J2dnB1L2JJMXRqZWN1anpMM05WekFyQS84bzRjVUoyVFpna0NmY01rYXlVVk4xN2RpSFZxa3FwMkd0MUJBQUFBTUFOcmlYb2tmWHFTdkhZcmpyS25VeVZYQXg5U0xiY2NMT2NXTHFNUkIzSXBjeFRwK1RncDdNbDdvcXVjdWkxdDNKMzV2bmZBZ0trM0gyREpEQTBWSGNBQUFBQWNJTXJSZUwrbG5ZZ1VlSTZkNU1NNjg5elppVU5vVFZyU05GMkYwdVJDNXJZN2FBU0pmU0RRQ0dYbFNucCt3L0lxVTF4a3JSa3FaejRkYkZrV0hGZUZMSGVZOVhmZWswQ0FsMjdmd2NBQUFEQTRtcUNyaHo1WVlHOUYxYlN6MkZHTHp1Y3pRejhQd2ZleW9FbGlrdXRPYk1sckhJbDNRTUFBQURBTGE0bjZDcUoyRFBwYVVsOCtYWGRBY0FMQXNKQ0plYlZGNlY0dXphNkJ3QUFBSUNiM0YvREdoQWdGUjRjSWlXdW93QVY0QmxCZ1ZKaDlFaVNjd0FBQUtBQUZjZ21VM1VtZXVWeFk2VG9wUjEwRDRBQ0V4Z281UjRZTEdYNjlOSWRBQUFBQUFxQyswdmNUNU9WbWlvN0h4c3JSejc2UlBjQWNKTmExbDV4ekNpSjZ0MVQ5d0FBQUFBb0tBV2FvTnVzYjUvNDNnZXliOElVeVV4TzFwMEFUQXVKcVN5VnAweVVvczB1MGowQUFBQUFDbExCSitqYXFlM2JaZWVESStUazhoVlcwcTQ3QVRndUlEUlVTbHpiUmFJZmUwU0NpaGJWdlFBQUFBQUttbWNTZENVclBWMk9mUCtEN0pzOFRkSjJ4TnV6NndDY0VSQVNMQkZOR3R0TDJpUHIxckU2T0tZUUFBQUE4QkpQSmVoL3kweEprZU8vTHBiRU45NldrMzhzc3hOM0FIbGdKZUdCUlNLbDJHV2RwTXl0TjBsay9mcDJVVGdBQUFBQTN1UEpCUDEwcWZ2M3kvRkZQMG5TYjcvTHlZMmJKRzNMTnNsS1M5T1BBdmkzQUNzaEQ2dFZVeUlibnk5RjI3YVJvcTFhU0ZDUkl2cFJBQUFBQUY3bCtRVDlINngvcXBwTlR6dDhSREpPSEpmMGc0Y2tLek5UUHdnVVhvSGhZUkpVdklRRWx5d3B3U1dLU3dDejVBQUFBSURQOGEwRUhRQUFBQUFBUDhVMEd3QUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQUZUdVQvQUVpNFBoc1dEcENoQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImFhZ3VpZCI6IjM2MWEzMDgyLTAyNzgtNDU4My1hMTZmLTcyYTUyN2Y5NzNlNCJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNy0xOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiZVdCTSBlRkE1MDAgRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNzA5MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDctMTgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTA3LTE4In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiZDk0N2E1NjNhNWU4OGVjMmNkMjYzMDQzMTQ1NjdhOTE5ODlmMTU1MSIsIjM1NWY3YzBhZDUyNDkzMDIzZDc1MjFiYzUxMGEwOTY2OGQ0YTYwNTEiLCI2ZDFlMmZiZDFmZWQ3Mzc3MWIwMzlhOGJhNDQ0NDU2MDIxYjJlNDg0IiwiZDc1ZTdiZjliMjQ0NGI0NjY5ODgyN2QxYmUyZTFiOGY3ODFjYzRhNCJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJkOTQ3YTU2M2E1ZTg4ZWMyY2QyNjMwNDMxNDU2N2E5MTk4OWYxNTUxIiwiMzU1ZjdjMGFkNTI0OTMwMjNkNzUyMWJjNTEwYTA5NjY4ZDRhNjA1MSIsIjZkMWUyZmJkMWZlZDczNzcxYjAzOWE4YmE0NDQ0NTYwMjFiMmU0ODQiLCJkNzVlN2JmOWIyNDQ0YjQ2Njk4ODI3ZDFiZTJlMWI4Zjc4MWNjNGE0Il0sImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IEZJUFMgU2VyaWVzIHdpdGggTkZDIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyODcwNywicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAyLTA3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMi0wNyJ9LHsiYWFndWlkIjoiMmZmZDY0NTItMDFkYS00NzFmLTgyMWItZWE0YmY2Yzg2NzZhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyZmZkNjQ1Mi0wMWRhLTQ3MWYtODIxYi1lYTRiZjZjODY3NmEiLCJkZXNjcmlwdGlvbiI6IklEUHJpbWUgOTQxIEZpZG8iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRGRUQ0NBbDJnQXdJQkFnSUpBSUNVVHZrZ3RqNUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GRXhDekFKQmdOVkJBWVRBa1pTTVF3d0NnWURWUVFLREFORVNWTXhDekFKQmdOVkJBc01Ba05UTVNjd0pRWURWUVFEREI1SFpXMWhiSFJ2SUUxMWJIUnBRWEJ3SUVaSlJFOGdVM1ZpWTJFZ1EwRXdIaGNOTWpBd056QTNNVFF6TnpFNFdoY05NekF3TnpBMU1UUXpOekU0V2pCUk1Rc3dDUVlEVlFRR0V3SkdVakVNTUFvR0ExVUVDZ3dEUkVsVE1Rc3dDUVlEVlFRTERBSkRVekVuTUNVR0ExVUVBd3dlUjJWdFlXeDBieUJOZFd4MGFVRndjQ0JHU1VSUElGTjFZbU5oSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFLT2VxQzUvcDBEMWlzQ1lLUUpsVlVPckI2STdETG9jdW5FL1JtOGR1R1RieXhRaHQzQ2JGVlR2M04yTHAyZmJqeGxJKzNzT1NHazMzRlRZa1RxeGNkSklySjdTc2tCY1VTTnJmS09hUVQvNktRY1A0Q203Vis2NTVUcStUV3h5eFdRaER5Z3QxNXFvUDdNdUs2YlQ5U3dwQ2pwZktoYU1TbXlRYU1vVWNSQWJMcWR6QkNhYzBoekIrWmUrZ3FKbG5XVjlVYVNJMnJGc1Z1SDRaRTBjUk8rTU9wYUxnTS9zMjQ4bkdHSHAyMmV3U1FmYm5QYUJiYjhpcXlBUCtjdTUyR0xzVXBLUkplYkUrUjYrUE1ROUpDZFdlUVpSM0RrZlNpZGt2M21jYjRqcTFpSXRhK01xS2hSbndyZlhoOTExS1dMbllBbDlFTkNoTFgwYzZTajFRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3SHdZRFZSMGpCQmd3Rm9BVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUZMckRoYWVnZUtIeFlqSDNFUDN2VUJLaG56TTIwNkFTeGdlWUNPMkVjOXBPbFlKYWVxRkUrc1VhbVVWL3B3akRscU5hU2dGZ3k3VHdlWWt2T21NbjRxU2NzSHF2SjN6R09BaWFmd2FoMXZVSGZDbFhSOCtheE8yaUdPVUYwSktyWjlZWWpiQWE1LzRIQ2x2N2pGUE9kTVdUT1F5bmdvaUhBczNqa3VZanBDTEZsQjRWT2kzZDF3akExcG5UZEJLa0FiN3Q4blR2dysvWGJGdmNRYTczVkg3c2p2b0JxRDNmZE1mUmN1VnE0cVVadFpUNmNHYWdUSEQ2MVR0cWg5b01DWlhjRGJSMVBHWm5OYnF5Y3NXUERJSzBucG1LMy8zbGZWOGMrWnNyeTZlMTcwbWZKTVpwN084bTZDU3o2L1ZMSyt5REpkNzg0MXdwbWVLVGY2SW5aQT09IiwiTUlJQzZUQ0NBZEdnQXdJQkFnSUpBSmJUeXJ1MVgvSVBNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1DTXhJVEFmQmdOVkJBTU1HRWRsYldGc2RHOGdUWFZzZEdsQmNIQWdSa2xFVHlCRFFUQWVGdzB4T0RBMk1USXhORFExTlRCYUZ3MHlPREEyTURreE5EUTFOVEJhTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTVZqS0hXcGJEN1RTbE14b2NqVGw2bklmN3gzMlBtc1E5ekd1TEdHcUEwVVFab0lxM1hMekw2TFlVdko1QTVnMHV5RkdsbEhFZkdBS3JFYUNROEZWdlBTL1VoMEZ5ZnpXaFJBemlUU2lqak1JSVZqampVdjltOXZGbWNYU2NnSGlnN09kejg4NThWMGtyTkg5OXFHbTN3amdhT2VyVFdtdCtqWENVZm4wMUlrVFB3eEcySGxnRWQ0NWpOTFNWN1Zvb2wrS2U4RTJraTRsRWtUZUh6Ym91bFI1R1VicDNuTWk3RTQ3Vk1RYTNiTndueldCYnNhQlNTUWhMazNtNUhhS2hoeGE2d0pESzQ3TmlNQ2tDa2RJSHVXU1FMVkFmbTg1VUFPTnRFT1B3aTBPdUszcWJlOHlLT0ZHZjBLaEI1TU1lQXltN01WL000VzBhNDlvZ1BEOXBNQ0F3RUFBYU1nTUI0d0RBWURWUjBUQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FvUXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSld6NXhMTWs1V05ZYkFiNnlPeEVDQm9aMldlQi9xbDRWSjNPLzMvdE5zeE9ZbnpMZVdvNTQwelFoOXJBbWF4ejdldW1CbHNrTXE0eUdQU05YQjl5Y1dHSGdrY0NlU3pOMnd2OENJekRCczJvQlpqVE5rNjVMQlpEc3NUT0J0TVcvK3VURkhRZmJ1TzNJU0xoSTBEWGZSRWk5TkRNM2pmazExeEhjc2ZoMlJNVitRZE5md1ZhWlpyQ3Erb3VHK0V2a3Y3S3FxK295dTBWRk0vdHo2OFRHbDZ5bGhQRlIxcWg5d3R0cFZqQU9PQ0VRQ0xxUDJkUDI4bHdZQnlDcUhRcVZId2J1anYvTFpqWm5LVzNMWW5kWml4UFBTUkNKc3NERHdKdmgvZjZuVHhnOVpFKy9KY1lyZTVDYUk4bnpWSGFTT0NqTko3RnpVTEc2NEppV092UTUwPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFRd0FBQUFnQ0FZQUFBRG5sVVpxQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUVuUUFBQkowQWQ1bUgzZ0FBQUFaZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakF1TWpIeElHbVZBQUFLMUVsRVFWUjRYdTFkRFhBY1pSbStOT0FmS29nNldPMFFjcmVYM083MVI0MW9IZFNxcURBT2czK2NZRVhCb2xYUlRFbjIyMHRhS1RjNjRtZ0JxekJpRVVWcEJkcWl3d2hxU2RJUzJ1cFlTZ3ZSdHBUU2NrbGpXekhhZ2pwU1JkcjR2THR2anJ2azI3dmR2ZDFMam43UHpETjN0L2QrNy90K2Y4Lys3OGFLME5EYWFyMnFPZFhab3FXeUg5UjBhMEZjdDY3V2RIR1Rab2pWQ2NQcVNlalcxb1F1SHNPeS9lQlRzRG1NLzU0WlQ5aitMV0dJZzdEZkIvc0JjRFBzZjRYZlA4WDNiMnVHMVpIUXpVOG1VdUtkeVdUSG01cWFjaS9qSEFLQnlpZjBiQnIrTHdhWElQWVBrTWRxZkw4WGRXcGxzMUFBMzEvUWpPdzk4TDhTOWI4QlhJUjIrbkRjNkRvemxzazBzbG5rUU14a1BHWE85RUp0Vm5ZR0Y0c1V5Vm5kOFVUYWVwOGJ3KzZMYWtCajVpemRiTkpTMXJ4RVdueVd4ZzM2RW1QZFdvUFBEZWpmN2VBVEdNc0hhRHpUdUM2aGJqME4vcFhtQXNydWdzMFdMUDhOdUJKalpKbVdFbGNsMDltUEoxSm1XMHRMNSt1aUhCdUdrWHNsalg4N25pNEV6Vm5rOUF2a3NRbjU3RVNkaHJCOEJNdVBqT1dQLy80T0hzUi9lN0Q4WWRUbGZ0UmhGZmdkTEc5SHUxd0FmenI1NWpBT2tpUUtodlZiR0I2QzAvL2krMmlOZVJ4OEZnbnZSZnhmYWluelNrN05FMGlJVVBiZjQzd1dtTlROZDdCcEtFQTdMWmZGQVk5enAzeVpUU01EaVFWaS9VK1NnNVFZQUlmT21HMmV3c1VqQS9yaFc3TDRCZXJtajloMFVvQjJPQitUWlRXNEIvazhPeUcveUNpT29XMUlZSDZIOFhQejlMYmNLemlsUUdocE1admhaeUhHd0czZzQyQms4NVo4bzkwRzhYME5pU3MxSXYyUUdrOEtkV3N6dDRzbklQOFJxUjltRFFYRElkWlNiQm9aMElsM1MyT1haWFlwRjQ4TVUxNHduSzFiZVc0MXBMM0ZFUUNKbFBWV3RERzJmdXlWck5SM3RCVGRTakI4WXJJRm95VnRubzJPQ3pCZ3hETkJCNnBYS01Id3hpRDlnSzNLYzZQY2t2QkdKUmkrTWNtQzBZRDRmZEs0WG9oOVcvWVRDWlJnZUtOdndjaGtHdEcyZTJXK2Frc2xHTDR4bVlKQmF4bHBUSStrTlJRZG1HUjNvVU1KaGpmNkZRdzZjQ3J6VTN0Q01MRFd1UXNkM1IrQXczS25CUTVLeW5qaGpkeE9ubkRpQ0VadUdqcnNZV2xNSnRwaVdVSzNCbVQvRmZFdWRoZzZVUGU2Rmd6MGJSNmZhNk1tblkza2xEd2hhWWpMVVU2ZXMyN3QwZ3p6bTdWZ1V1OTZENmZrSHhDYTYyVVZHQ01xOGcwMmpSUW5pbUJvUnZZaWFUd20ybnRmVzl2Q2s3VzBkWUhzL3dKMTYzazZlTVp1UTBXOUN3Ykc5SzFzT3FXQXZJVTBYNXRpRFp0TmJTakJjR0VFZ3RIV2Rzdko4RTJuQXVVeGlicDVoV005Mm9EZjJ5YjhYMEt4M3JFTkYwb3dvZ0htMGhKcHZqYVZZUGpDaVNBWWliVDFlV2tzSmliQ2svUG01VTVpYzhyeFFwbGRNUlBwN0hsc0hocVVZRVFESlJnaDRzVXVHSFNSRCtwSVYrVEo0eEgxTEc5ZGpDSFRpTWxSNFZpRzJFN0hSYmhBS0ZDQ0VRMlVZSVNJRjd0Z29KMnowamhNdEhPZWpsMndlUUZZL2xHWmZTbkZmRFlQQlVvd29rSENNQmRMODdXcEJNTVhLZ3FHSVM1dlRwdG5oMFhVKzA1Wm5BSkRGQXpENkRnZC9wNld4bUhHRGZGRk5oK0gwUWIwd2FPeU1tT0UrT1VOSS9jU0xsQTE2bDB3MEY2NzQ3cTRwUnBHY2RxYTdrdVI1VXRFSDQ1Z0Rtd0tpL0RaajgvN0lFUzM0ck96ZWFhWXpXbFVoM29SakpvelJNR29PQUVOYTBpMmRUR0dlRXA4VEZKbVBEdll2R3JVdTJDRVFicWhrc09GQnN5bGkyV3hhc1RqNk5kMTJwc1h2NTdUQ1FZbEdDNE1TVEJhVzYwM29vMWRiNnF6cVZ0ZlluTTU2QXBCdzlveG9Wd1JNWWxHTkszOTFWeWlLaWpCaUVZd21sUGRMYkpZdFNUYTdxSGlBK3Urb1FURGhTRUpCdHB2aGRUL0dIV3h2OXpXeFJpMHRQaUV0SHdKeGJWc1hoV1VZRVFqR0hSd0d1T2gwZ1Y1a1RPZU1pL2hoUHhEQ1lZTFF4Q01zMXF0Vmd6dThyZXZweXlQandId3NwVmgvU3VWV2pLZEN3U0dFb3lvQkFPNXA4MzNvcCtlazhXc0ZkRit3YThTVm9MaHdoQUVBMzdXVFBCYlJIVGNBZXhHdkpUTkhmUU1OY2Y2QnMrUDllYm54ZnFlUEpXWDJrQ1p6SGdmRXhqQ0dRSWxHTkVKQnNGK0VKRXVkc3ZpMW9iaVQ1eUtmOVNOWU9qV1pqVHlmYUhSdWQ5QUhvdFlwV0E0TnhxSlkxTGZUTlQ1SzJ3ZWk2MGZNaUFVRDRLakJmYm1qOGI2OHN0ajJ3N2FEMnFoZlUvMHh5NlpyekhTMnF1bHBUTmwrd3lJdWhjTWpCVTY2MVFObTJjdVBvUERSWVRSQmpwYlIyTUFPVjlIWnpPUTk4L3cvZll3aVBIdGZqZTBidjJGay9DUGVoR01PcnNPby9MdDY3bzFYRGdWdWlFL0J3THhqeEt4S09YRzJNNmR0aTM2dzhPUmRuR1A3VGNna0Z1ZEM4YlV2QTZqbGtpa084K1R0ZzJJTVhTWXpmeERDWVlMcXhBTUw3ZXZvNzd0dG5GLy8wbllrdGdoRVlseEhMcWF6SjJ0akVxYnM5aXlTV1huMnY0RFFBbEcvYU9zWUJqV0FUYnpEeVVZTGd3c0dMbHBLTHRWNnBOSkhWWjRZSExmL25mSkJXSUNoMkhkUUVYaTZld2xNcjhsZEo1SFl0djdoUktNK2tjNXdVRDc3R1V6LzFDQzRjS0FndUhwOUdkS1hNWG1FSXg4dTBRY1hQallhKzB5bVV3ajJ1dHhxZThpb280WDJ2WStvUVNqL2xGaGwrU1BiT1lmU2pCY0dFQXc2SG9LN0E2VW5jaW81OEdtcHN0ZWVCMUQ3OUJYNWVJZzRmM0RwM09wR09MTWwva2Z4eDJ4ekZyZmo4VlhnbEgvcUxCTHNvWE4vRU1KaGdzRENFWWlWZjcyZFdicEpkdzkrODZSaXNONDlnN3VoM1ZoRjRQRjZRbUovMUxxMWdJdTRobVZCQU1UOXU3eDcwd0pnL1RZZlU2aExKUmdWRWFGWFpJSDJNdy9sR0M0MEtkZ3pKNXRuZ0tmQjZTK21Qai8wSXdaSFMvbklnNUdSeHNoQmdOU2tTamxZaTVSQVBydVVsbWNZbUp5L1huRzNIRXhLNkRpRmtaRXhCall5Q21VUlNYQlFEdVBvQTVibzJiU3lMNmRVL0lFM2lxVW5nWU5tMmdEMTdOMCtHOFZwK1FmU2pCYzZGTXc0cnBsU2YwVUVURk5OaTlGei9ETVdHLytpRVFrSFBibU44UzJiWnQ0K2JoemowbjVKM2lCZEZzMWwvQUUxTDJ1QmFOV1RPcmlBNXlTSnlEdjc4cjgxSnllcnk2V1FBbUdDMzBJUnRPYzNHbG9wOE5TUDJQVXhWTmwxL1RyOHEyeHZ2eDY4UGtpc2ZnbmZsOGY2eDkwZlFVbDRuNUdHcStZdWpoeTVxenUxM0NSaWxDQzRZMTFLUmowV2tndEYvd21SU1VZTHZRaEdGNG1HQWFMWVBQeTJEZzBQZFl6OUg3c3BzeU45UXhVZkMwaVhmeUZQdG9uaTFsTUdxeGNwQ0tVWUhoajNRa0d4Q0twVysvbWRJSkJDWVlMUFFvR3ZZUWE5dVhmNzFscDY2SktsSHQ4L1FzVVIrMFhUWHVBRWd4dnJBL0JvTGZyMlFmSHIvR3psZW1LS1NNWXVua0hUU3pFbEw0K3NGYUNnZm8rQis3V2pPem4yTFFzbk5jR2lEMVVUdWJQb2RuRjVwR0F6cGdndnV0V0J1cjZIN3RPdXJpVWk1UUZYU1dLTXQvSEJONUVheVhVcit3OU1jRXBqdkdLNHZmSWJ3VmR3OElwbEFXTkJaUzVEdldoTjVYbjRlZG9xZDhvaUZ5eDJ3aytpdS8wSXVpbDlLd1RUc2tUNG1seER0cnpSbTVYalBVbzJwWGU2RzQ5Z2p4dncrZkNoTkdoY2Zod1FDOWphVExFRzl4b0dGZVd2aVkrVXVTbTJRK2NvWGR5Nk5ZaU5Pd3lWUHJIR0JoM0pvenVVQ3NlVDVtWFFmRi9qaGcveE9mWE5kMjhnam8wYUgzcExBbE5OR2R0TDVZaTU1dlFnYmVqNCs2Zy85Z3NNcUFPSDNIYVNmd0ViWGNEdm1lVGh2VXBUZTk2eTRRek03NlFtOVkwWjlGcGRQY202dk5wc0F0OXN0eHBPK3ZYNEViRTIwb1RDY3NHU29ubCtCL2Y2V2EvVmNWNTBhU1B4N3RPRGVFQnhnMTB4eStka29YZ2ZBZ3hGaURlMTlBTzMwTS9yRVFPOXlMbUE0aS9CYiszbCtibmtQSUhONFByVUwrMStGd0IyMnZob3gxaWYxRzgxWHBidkEyNVpqSytyMmx4UjI0YTFkOFJQekVmdXdvV2NzRVdpSk16WWorSTN3K1Z0S3NoSGdIL0FQWlNucWpUemZpOHhoNjd1blV1UGRyQTI4TnhZckgvQXozdEk0ajUrVE9MQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiMmZmZDY0NTIwMWRhNDcxZjgyMWJlYTRiZjZjODY3NmEiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wMS0wNCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDEtMDQifSx7ImFhZ3VpZCI6IjY5MmRiNTQ5LTdhZTUtNDRkNS1hMWU1LWRkMjBhNDkzYjcyMyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNjkyZGI1NDktN2FlNS00NGQ1LWExZTUtZGQyMGE0OTNiNzIzIiwiZGVzY3JpcHRpb24iOiJISUQgQ3Jlc2NlbmRvIEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxMCwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURDRENDQXErZ0F3SUJBZ0lRUUFGcVVOVEhaOGtCTjh1L2JDayt4REFLQmdncWhrak9QUVFEQWpCck1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDaE1LU0VsRUlFZHNiMkpoYkRFaU1DQUdBMVVFQ3hNWlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFak1DRUdBMVVFQXhNYVJrbEVUeUJCZEhSbGMzUmhkR2x2YmlCU2IyOTBJRU5CSURFd0hoY05NVGt3TkRJME1Ua3pNVEl6V2hjTk5EUXdOREkzTVRrek1USXpXakJtTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNoTUtTRWxFSUVkc2IySmhiREVpTUNBR0ExVUVDeE1aUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVlTUJ3R0ExVUVBeE1WUmtsRVR5QkJkSFJsYzNSaGRHbHZiaUJEUVNBeU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTRuSzljdHprNkdFR0ZOUUJjcm5CQm1XVStkQ251SFFBQVJyQjJFeWM4TWJzbGprU0ZoWnRmei9SdzZTdVZJRGs1VmFrRHpyS0JBT0o5djBSdmcvNDA2T0NBVGd3Z2dFME1CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdEZ1lEVlIwUEFRSC9CQVFEQWdHR01JR0VCZ2dyQmdFRkJRY0JBUVI0TUhZd0xnWUlLd1lCQlFVSE1BR0dJbWgwZEhBNkx5OW9hV1F1Wm1sa2J5NXZZM053TG1sa1pXNTBjblZ6ZEM1amIyMHdSQVlJS3dZQkJRVUhNQUtHT0doMGRIQTZMeTkyWVd4cFpHRjBhVzl1TG1sa1pXNTBjblZ6ZEM1amIyMHZjbTl2ZEhNdlNFbEVSa2xFVDFKdmIzUmpZVEV1Y0Rkak1COEdBMVVkSXdRWU1CYUFGQjJtM2l3V1NZSHZXVEhiSmlIQXlLRHArQ1NqTUVjR0ExVWRId1JBTUQ0d1BLQTZvRGlHTm1oMGRIQTZMeTkyWVd4cFpHRjBhVzl1TG1sa1pXNTBjblZ6ZEM1amIyMHZZM0pzTDBoSlJFWkpSRTlTYjI5MFkyRXhMbU55YkRBZEJnTlZIUTRFRmdRVURMQ2J1THNsY2Nsck9aSXo1N0Z1MGltU01ROHdDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdEQ1c1SXJiakVJL3kzNWxQang5YSsvc0Y0bFBTb1pkQkhnRmdUV0MrOFZJQ0lFcXMyU1B6VUhnSFZoNjVBamwxb0lVbWhoMEMybHlSL1pkazdPM3UxVElLIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVZNQUFBQ3NDQVlBQUFERytFOE1BQUFBSUdOSVVrMEFBSG9sQUFDQWd3QUErZjhBQUlEcEFBQjFNQUFBNm1BQUFEcVlBQUFYYjVKZnhVWUFBQUFKY0VoWmN3QUFEMkFBQUE5Z0FYcDRSWTBBQUF5Z1NVUkJWSGhlN1oxL2JKVGxIY0J2amhqTmNDNE8rZFhlWFZ0VVRNemlQN29ZWFpZNTFJa0tkMWZObkZIajVvaEJtQTdqMk1Sc1pvbG14aGhOSm9ydDI0S2dzaUZzaW03VEFkTVlSRlFFRlRjVnh3L3J3QUVGUkNoUSt1dWVQYy8xcVFQM1ROcyszM3ZldSt2bmszelM0MmdmbnZlOXQ1OCs3NzNYSXdFQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBVUVwa0c2L1hQcG5JUlI4Z0loNXQ0MXI5Y1lhdEJmd1A5UTNuNngyMFRadFAxRGNwUk1UUE5kZVUxNHV1VnQyTXEyMUZCa3h0TWptckxwVnEwUjgzMTFaWDMycnZMbU1LUDIzMGpxbVAzRHNORWZIenpFVzdFeGZPR1dtTDhvV2trOGtmMXFYU1BYWFZxYVhKVWFQT3FLbXFPck11bWZwcmJUTFZuVXFsTHJlZlZrWk1tUDExL1pPbHc3bHpFQkVIb2ptcnpVWlRiVjMrTDNWangwNHdJUjA5ZXZUSjQxS3BLZG9iakNOSGpodzFkdXpZNUxoMGpkS3IxTFB0cDVjQkpxU3NSaEZSMHQ2Z3pyU1ZjWEdNRHFtcVNTWXordll3RTg2YXF0UzF0ZFhwNjgzdHVqRmpValZqazVQMUtyVzk5OVBMZ1Z6VTVkd1ppSWcrbXFCZU9xZk9sdVlvMHVuMGNUcW1YZmFQdzh3SzFkNU82RlA4dDJyVDZWdjB6Uytic1BiZVcrcmtvbytjT3dFUlVjSmNkTURXNWlpcXE2dVBINWVxNlZ0MUZsYW1PcUk3NjFJMTIwOUoxL1JGOWt2bEVkUDZobTg3Tng0UlVkSnN3ejIyT3A5aVlxcFhvNTMyajJabG1qL3BwSk8rcWo5MnA4ZU1PZDNlZjB4NXhEVFh0TSs1NFlpSWt1YWlEbHVkSStrOWhVOG5qdE8zQ3pFMWQ0NFlNV0tNdm4zUTNCNCtldmpKK25iZktyV0U0WFdraUJqS3k1dlBzdVg1bExwVWFtWnRNcjNmM0s2dFRyNVR1Rk5UbDB3K1dwTkszYXovcnFPMk9qM04zbDJpVEk2bU9qY1lFYkVZNXBxZXRmVTVpcnJxMURPMXlkU0JjVldwRyt4ZGlicXE1QXl6T3RYM0w3UjNsVEQxMFhMbkJpTWlGc05jVStIVTNVVnlWUElNSGRXVnA5WFdxVk5yYXZQNjl2S3FFVlduMnI4dWNlcWovYzROUmtRc2hybW9qRjR2T2hDSUtTS0cxSDBScWdJZ3BvZ1lVbUtLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUVM5N1dDVXVlRUFsTHB3ZFZ2TnY1aUwzbkFicjl4NTAvMXZGOWlLdGF6NERNYTdId0R6K3J2bjB4NngrL09LWWR6RTAyM0dSUG43TU1YU3AzaWVURzkzYlhHa1NVemx2bnZ1eWlvdmpycHpubk5PZzFBZi91czI3N01oaDJmbkpvZDV2UU5lOCtxUCtKbzZMYWRFcTk1ejY0ZGV1WFdCSHFRdzZ1M3RVVzN1bjJyeGpuMXE5WWFkYXNucXp1cW41WlhYeU5RdFU0dUtIVkNKVGdZRWxwbkthYjZhNHFKU1lmclRuUU5uRzlJYUhYM0xQcVIrZXFDTXpWTml6LzdCYThkWldkZVY5ejZ2RUJMMktyWlN3RWxNNWlhay94SFJvMGRuVm81NWQ5NkVhZitNaXY2ZEpTa0ZpS2ljeDlZZVlEbDNlYnRtanpwdTExTy94ajFOaUtpY3g5WWVZd2h0YmRxbFRwdXFWcXJrbzU5aFhKU3N4bFpPWStrTk13elByc1RYcXpzVnZxTHVXdktFeWR5OVR1WHVXcTE4dWZMMXczNzFMMTZzVjY3Y1ZMaWFGcENlZlY0KysrRStWdUdDMmMzK1ZwTVJVVG1McUR6RU5UMkxDYi9VcXNGRWxNZzMvblpPNUtGUzRUenRKUHg2WHpsRlZVeGFxS1hOV3FvL2JEdHV2TEQ2NzI5clZOMzY2eElUcXFQMVZraEpUT1ltcFA4UTBQSVhYaGpybTVGUkg3WmpKRGVxTzM2KzFYMTE4dW50NjFDMlByTmJINVJHeEwwV0pxWnpFMUI5aUdwNEJ4YlJQSGJaSmR5K3pJNFJoL2d2dkYxYkl6dm1VZ3NSVVRtTHFEekVOejZCaWFzdzBxaC9yMC82UVBQbnFCMzdIUnpFbHBuSVNVMytJYVhnR0hWTmpObEovLzNDUEhTa01UNy9XVXBwQkphWnlFbE4vaUdsNHZHS3FIZitUeFhha2NQenhGYjFDTGJYblVJbXBuTVRVSDJJYUh0K1ltcWk5dDIydkhTMGNQMXZ3cW5zK2NVbE01U1NtL2hEVDhIakhOQmVwODI1LzJvNFdqbncrcjhaUFgreWVVeHdTVXptSnFUL0VORHplTWRWKzVhcEg3R2hoMlhld1EyVCtJaEpUT1ltcFA4UTBQQ0l4bW1STzlUK3hJNGJsbVRVdGhkV3hjMTRoSmFaeUVsTi9pR2w0UkdLYWpkUXQ4MTZ4STRabitGV0N4LzlnSmFaeUVsTi9pR2w0cEU2VHo1eXh4STRZbnZjLzJ0djc2NitPZVFXVG1NcEpUUDBocHVHUml1bm82eCszSThiRGlPc2VkYzRybU1SVVRtTHFEekVOajFSTWgxM1JiRWVNQjNQTXh2cmNLVEdWazVqNlEwekRJeFZUY3hHcXE3dmJqaHFlcnU0ZXVXMFpqTVJVVG1McUR6RU5qMWlBOUhHemRsT3JIVFVlYnAwZjR3djVpYW1jeE5RZllob2VzWmhtR3RYQ2xSdnRxUEd3YmJjK2Z1SjZoMzVpS2ljeDlZZVloa2NzcGpwaXR6MjJ4bzRhRCswZFhTb3hNYWEzNlNPbWNoSlRmNGhwZUNSakd1ZHJUZnVJN2FvK01aVXp6cGgrNTFkL1V1Zk9lbHJFYi83OEtiVWhoamV1TUJEVDhJakZOS2JmMGY4c3R6Mit4ajIvWWt0TTVZd3pwcFVDTVEyUFdFeTE1OXkyMUk0YUg2dmUzZTZjVzlFbHBuSVNVMytJYVhncUxhWmI0N29JUlV6bEpLYitFTlB3VkZwTXQrODkyUHUvcWpybVYxU0pxWnpFMUI5aUdwNUtpK211ZmUwcWxuZmhKNlp5RWxOL2lHbDRLaTJtaGZjNHZjempHQnFzeEZST1l1b1BNUTFQeFozbWY4eHB2aXpFdEN3aHB1R3B0Smp1Mkh1SW1JcENUTXNTWWhxZVNvdnBCenYzbTdBNTUxZFVpYW1jY2NiVXZNSEU2MEt1MmJoVEhXanZzaU9IaFppR3A5Sml1bVQxWnVmY2lpNHhsVFBPbUI1cmZoS2JKOTBsdlBnaDlmckdlTjc5aDVpR1J5eW1KZkliVVBYM0xIZlByOWdTVXpuampDbS9tMjhscGdOR0xLWWw4cnY1c1p6aUc0bXBuTVRVSDJJYUhzbVlUby81dXNIK1E1MjlaMWV1K1JWYllpb25NZldIbUlaSExLYVpSclhvcFUxMjFIaFkzN0tibGFrNHhIVHdFdE5CUVV3YjFZcjEyK3lvOFhEMnpLWHV1WVdRbU1wSlRQMGhwdUVSaStua0J0WDZ5U0U3YW5qYTJ2VXAvaVV4dlRHMGtaaktTVXo5SWFiaGtYek9ORTZlV0xYSlBhOVFFbE01aWFrL3hEUThVakU5OFpyNWRzVHc5UFRrNDNuYnZTTWxwbklTVTMrSWFYaWtZbnJxOUNmc2lPSDV5N3AvbVpnNTV4Vk1ZaW9uTWZXSG1JWkhKS1k2WkpmYytad2RNU3lITzd2MU1SUGpjNlY5RWxNNWlhay94RFE4SWpITk5Lb2xxN2ZZRWNNeXJYR1ZlMDZoSmFaeUVsTi9pR2w0UkdJYTA4V25UZHYzeGZjaS9jOUtUT1VrcHY0UTAvQkl4SFQ4dEVWMnRIQzBkK2pUZTMyc3V1WVRpOFJVVG1McUR6RU5qM2RNOVNuKzNPYzMyTkhDWUs3ZW56WHpTZmQ4NHBLWXlrbE0vU0dtNGZHTjZmQWZ6TE1qaFdQR3ZKZWRjNGxWWWlvbk1mV0htSWJISzZhVEc5VGN2NFZkbGQ2K2NJMEpsM3MrY1VwTTVTU20vaERUOEF3NnB0bEluWC9Ibiswb1liaXBlVlU4L3lWSmZ5U21jaEpUZjRocGVBWVYwMHlET3ZmMlord0l4YWU3SjY5K05QdkYwbHlSOWtsTTVTU20vaERUOFBRN3BpWmsrclRlSEd2M1ByWGVmblh4T2RqZXFjWk5YZVNlVXlsSlRPVWtwdjRRMC9Ba3ZuVi83N3N0ZmRhSkQ2bGhWelNyRTYrZXIwNi9hYkhLM0wxYy9TSHdDL09YdmJtMU1BL1hQaXM1aWFtY3hOUWZZZ3FHZzRjNzFWWDNQMTlZQ2J2MlYwbEtUT1VrcHY0UTA2Rk5SMWUzZW5qWnV5cngzUWVjKzZta0phWnlFbE4vaU9uUXBMMnpTeld0Mk5CN1NsL0tGNWsrVDJJcUp6SDFoNWdPSGZMNXZIcTdaWSthTW1lbFNseWdWNkxsR3RFK2lhbWN4TlFmWWxyWmZOeDJXSzE2YjRlNjBielRVN1pSSlNaNVBOYWxKakdWYzlKdmxxbmxiMjR0WElFTTZjcDMvcTJPL2Y1YzU1d0daYVpSUGZqc1A1ei9Wckg5M2NxTitodk00NkxEeERucXBYZTNPOGN1cGl2ZTJxWXV1ZXM1OTV6NjRRbFh6MWU3OTdlcmx0YTJpdkROTGJ2VjJrMnRoWDN6NnlmV3FvbDNQcWRPTUQvd0w5YW44ZnFIdFdzZmxMM0VGTEVFTktlNDV1VklabFZlN3BydE1GZmh5K2xLdklURUZCRlJRR0tLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUkVRQkt6YW11YWpWdWNHSWlNWHhvSzFQaFpGdGFISnNMQ0ppY2N4RnUyeDlLb3dybXNjN054Z1JzUmhtb2wvWStsUWc1amtNMTBZaklrcWFpL0syT2hWS3J1a0Y1NFlqSWtxYWkzYlk2bFF3dWFqYnVmR0lpQkxtdE9mY2Q3d3RUZ1dUaTZZN2R3QWlvb1M1YUptdHpSQ2dQbnJOdVJNUUVYM01ScTIyTWtPSWJPTkc1ODVBUkJ5TXVhWUtmU2xVZjhoRmkvUU95T3VWcW52bklDSitrZWJLZlgzVFdsdVZJVXcyT2sydlVsdUpLaUlPMkZ5ME41RnR1czdXQkFxWXFOWkg2L1RIZlRxc25ZbjZacjJ6RUJHUDBLeENzMUdiYnNTV1JLWmhncTBIQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRUJwa1VqOEI0QW9tK01iVCszSkFBQUFBRWxGVGtTdVFtQ0MiLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjY5MmRiNTQ5N2FlNTQ0ZDVhMWU1ZGQyMGE0OTNiNzIzIiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlfSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0xMC0wOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSElEIENyZXNjZW5kbyBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDgyMTAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0xMC0wOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMTAtMDgifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIzMTExNmE2NDcwNjlkMTQ5M2Y1OGZjNWI1NGU1NDQ5ZTJhNTJkNDNlIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjMxMTE2YTY0NzA2OWQxNDkzZjU4ZmM1YjU0ZTU0NDllMmE1MmQ0M2UiXSwiZGVzY3JpcHRpb24iOiJZdWJpa2V5IEVkZ2UiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTEyLTI5IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZdWJpa2V5IEVkZ2UgKHY0KSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTUwNTIwMDAyIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTEyLTI5In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNGUyOWRmMDVhNTljMTdhNzNjN2VhNjRhOTRmZGZmZjFmOWU5YWUwZiIsImJmMTIzNjVhZmNiMTRkM2RkODIwYmU3ZWM0YmUxNjNjYjdjODVkZTAiLCIxNmU3NzQ5NjQ1MGIyMGMzMmMwYmRlYzJhMjRiMjkxN2JmMTgxNWYzIiwiODU5ZGYwNzc0MTI5ZjAyYmM0MWJmYmE5MWYzY2JhMjcxZGE3Yzg2NiIsImVjOWY3MDk4NzhkZDE0ZGJiNjc2YmJlNDlmMTQwNWVjNzcwZDAyZjAiLCIyY2MxYWZiYWUwODU2OWE1ZGUwODg5ODI0ZTVjNDA0ZDM1NzIxYWQzIiwiOGU5MDAwMzdkMDk1YWQ3YThhZGE2YzRjMTgxNDNiN2RiZWI0NDY3NCIsImI4ODAyM2YyNTQ1ZmRkNmVhNjIwNjBhYjg5ZDMzMjk0MTMyYjliYzkiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNGUyOWRmMDVhNTljMTdhNzNjN2VhNjRhOTRmZGZmZjFmOWU5YWUwZiIsImJmMTIzNjVhZmNiMTRkM2RkODIwYmU3ZWM0YmUxNjNjYjdjODVkZTAiLCIxNmU3NzQ5NjQ1MGIyMGMzMmMwYmRlYzJhMjRiMjkxN2JmMTgxNWYzIiwiODU5ZGYwNzc0MTI5ZjAyYmM0MWJmYmE5MWYzY2JhMjcxZGE3Yzg2NiIsImVjOWY3MDk4NzhkZDE0ZGJiNjc2YmJlNDlmMTQwNWVjNzcwZDAyZjAiLCIyY2MxYWZiYWUwODU2OWE1ZGUwODg5ODI0ZTVjNDA0ZDM1NzIxYWQzIiwiOGU5MDAwMzdkMDk1YWQ3YThhZGE2YzRjMTgxNDNiN2RiZWI0NDY3NCIsImI4ODAyM2YyNTQ1ZmRkNmVhNjIwNjBhYjg5ZDMzMjk0MTMyYjliYzkiXSwiZGVzY3JpcHRpb24iOiJTZWN1cml0eSBLZXkgYnkgWXViaWNvIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiU2VjdXJpdHkgS2V5IGJ5IFl1YmljbyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTEwMDIwMTkxMDE3MDEwIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjEuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNS0xMiJ9LHsiYWFndWlkIjoiYmJmNGI2YTctNjc5ZC1mNmZjLWM0ZjItOGFjMGRkZjkwMTVhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJiYmY0YjZhNy02NzlkLWY2ZmMtYzRmMi04YWMwZGRmOTAxNWEiLCJkZXNjcmlwdGlvbiI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPMiBQUk8gU2VjdXJpdHkgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNTRENDQWUyZ0F3SUJBZ0lKQU05UnpZdTRFSUlsTUFvR0NDcUdTTTQ5QkFNQ01IOHhDekFKQmdOVkJBWVRBa05PTVN3d0tnWURWUVFLRENORmVHTmxiSE5sWTNVZ1JHRjBZU0JVWldOb2JtOXNiMmQ1SUVOdkxpd2dUSFJrTGpFZU1Cd0dBMVVFQ3d3VlJYaGpaV3h6WldOMUlFWnBaRzhnVTJWeWRtVnlNU0l3SUFZRFZRUUREQmxGZUdObGJITmxZM1VnUm1sa2J5QlNiMjkwSUVOQklEQXlNQ0FYRFRFNU1UQXlNekE1TlRBME0xb1lEekl3TlRreE1ERXpNRGsxTURReldqQi9NUXN3Q1FZRFZRUUdFd0pEVGpFc01Db0dBMVVFQ2d3alJYaGpaV3h6WldOMUlFUmhkR0VnVkdWamFHNXZiRzluZVNCRGJ5NHNJRXgwWkM0eEhqQWNCZ05WQkFzTUZVVjRZMlZzYzJWamRTQkdhV1J2SUZObGNuWmxjakVpTUNBR0ExVUVBd3daUlhoalpXeHpaV04xSUVacFpHOGdVbTl2ZENCRFFTQXdNakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSGxxMmpVUU1hbEhqL0JSZVFlZkdpejRFdllKeUZMV1B6NFJmaEpHS3FxbCs4bjk2aFQxbTVnWG9Udm9McmpTVTdYMGNCZW9Uc2doeWgyMit5cnM0K1NqVURCT01CMEdBMVVkRGdRV0JCUSs4U0dXMkJYYnFiMmRjQU9pV0pPVStHQ3NQakFmQmdOVkhTTUVHREFXZ0JRKzhTR1cyQlhicWIyZGNBT2lXSk9VK0dDc1BqQU1CZ05WSFJNRUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEcTh4SVcwWks1eXozRUF6bXV4ODhMQ1RZTzE1N2ZUZnlPaU96QzJBRHlhd0loQU8xUFdZbGVGZ0gvM211RDhjQkFNcjExZkVLZEYvQWFDMTZmdHhhZXpOWEgiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSXdBQUFBWUNBWUFBQUFvTnhWckFBQUFDWEJJV1hNQUFCN0NBQUFld2dGdTBIVStBQUFGSUdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEQ5NGNHRmphMlYwSUdKbFoybHVQU0x2dTc4aUlHbGtQU0pYTlUwd1RYQkRaV2hwU0hweVpWTjZUbFJqZW10ak9XUWlQejRnUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpUVdSdlltVWdXRTFRSUVOdmNtVWdOUzQyTFdNeE5ESWdOemt1TVRZd09USTBMQ0F5TURFM0x6QTNMekV6TFRBeE9qQTJPak01SUNBZ0lDQWdJQ0FpUGlBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBpQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJaUI0Yld4dWN6cDRiWEE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM4aUlIaHRiRzV6T21SalBTSm9kSFJ3T2k4dmNIVnliQzV2Y21jdlpHTXZaV3hsYldWdWRITXZNUzR4THlJZ2VHMXNibk02Y0dodmRHOXphRzl3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzQm9iM1J2YzJodmNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSRmRuUTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpVVjJaVzUwSXlJZ2VHMXdPa055WldGMGIzSlViMjlzUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnUTBNZ0tGZHBibVJ2ZDNNcElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhPQzB3TlMweU0xUXhORG8wTURvMU5Tc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZRMjlzYjNKTmIyUmxQU0l6SWlCd2FHOTBiM05vYjNBNlNVTkRVSEp2Wm1sc1pUMGljMUpIUWlCSlJVTTJNVGsyTmkweUxqRWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0poWkc5aVpUcGtiMk5wWkRwd2FHOTBiM05vYjNBNlpXTXhaVGczTWpFdE56TTNZUzB3TlRSbExXRXpZVGt0TlRGa01UTXpORFpsWlRJNUlpQjRiWEJOVFRwUGNtbG5hVzVoYkVSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1qRTROV1l5WW1ZdE9EVm1PUzFqWmpRM0xXRmlPRGN0T1RGak0ySXpaakJpTnpobElqNGdQSGh0Y0UxTk9raHBjM1J2Y25rK0lEeHlaR1k2VTJWeFBpQThjbVJtT214cElITjBSWFowT21GamRHbHZiajBpWTNKbFlYUmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG95TVRnMVpqSmlaaTA0TldZNUxXTm1ORGN0WVdJNE55MDVNV016WWpObU1HSTNPR1VpSUhOMFJYWjBPbmRvWlc0OUlqSXdNVGd0TURVdE1qTlVNVFE2TkRBNk5UVXJNRGc2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUFvVjJsdVpHOTNjeWtpTHo0Z1BDOXlaR1k2VTJWeFBpQThMM2h0Y0UxTk9raHBjM1J2Y25rK0lEd3ZjbVJtT2tSbGMyTnlhWEIwYVc5dVBpQThMM0prWmpwU1JFWStJRHd2ZURwNGJYQnRaWFJoUGlBOFAzaHdZV05yWlhRZ1pXNWtQU0p5SWo4Ky8wVnhSUUFBR2ZWSlJFRlVhQVhWd1hmY24zVjk3L0hYNS92OVh0ZHYzRHM3SkpBSUFVTFlCWm1DaW1EVkRsZnR3MjNIcVl1cVBWMFd0ZGJXUjYzblZHMnJucmFPdHNoRHJSVWZQUjNXV1MzS1ZoQVpZUW9FUWtMV25kenpONjdyK243ZTUwNGlLTldPODU4K24ybnVpc1MvSjNHOFlaZVoyWlRFSW1EODUrUk9PMFpTVWZpSEpQNkZIeUlFV0JqQXd6Tnc2b2JJM0N5a0NHYUdKTnloTE1Xd2ducm9wTkpJQ0JOVWNvb2kwTzhiK3hmRjZQTEFxSU1jR29kMlcrellEOUZnNDlyQWdiMWkwVEpUSFdHQ3VvNlVoZUVKZGk5bVZyU044Y0tZcTQyZCs4U0tDU08yZ0F3ZElCUVFUUHg3WmxEVmRra1dielRaY0tUSTNkaHZ2ckdsdWVNOWQ4VVRYMFJyK2ptb3lZQ1FPTVNzQkxwQUFqTFFSeHBneG8rUkFtbHI0b2NJWmhlR2tGNWxCcEw0cndoSUNYTERmSCtnRHhlRmtIZ0NDZVN3Zjc4aEV6L0tqTVBFRDVJZ1JYdVJ1ZjIwcFlCWlE3MmY3U3RHSDNZbVR2eEZNaGNnQXdsaUFSTGdHV3dHTkFmV1Fxd21oc2hCY240c0dPQStsOHFDeHhtUUJVM0RTWklqOFY4VFlGQzBqWVVGYmUzMWRQMnk1WkF6VHhBUzVNWkFnUEdqelFCQjFZRHhBOVpaMEtrbWNFSEltYzkzTHZpM0hmSElrcVplalRJZ01FQU83bDhueGs4aDNZTG4zWVEwanVzTTFMeU9FTTVFNHNlQ2dPei9sUFljRUk5eFFUdHh4SGczbnVrWUlMNXJFZGdPQ0NqNGZnWVNzUjVxUmFlanEwSml1cXA0Z2hRTkx3MVY0c2VGQUs5Rk1yNUhRTFRqUWd5Yk1jaU5nN0huMXBXWGZPT2g2c1NMOFBrak1RZExZR0dhd2Q3ZkpYWXZSMFdmRU1BQzFCV0U0bFo2Qy85TW1mNk9jdVRwU0lENGtXVUcwbTdFdmVtMmJjNWpobzFZT3htUE9uTVRwMmFKN0lDQmlZOEovVDdRQWtZQWNaQUFROEVvYzBPMnlMYlJVVU1DTTVDTWRodjJ6VGxrSS9KalJHQVJRaEhJalhpTUdjZEtHbmVNMGpLSU94NnBWKy9MWnVjajd4QU1TUHZvNnhWNDlRWFNPTXpOdzhnRWRGb3dNd01qWTVEU1hwcm1yUlQ2QjR4VmlCOWRFa3R1Sk5xT3RIYys4SmorRURwZDJ4VGFqR2dBR2VNZ2QvOW5ZRThJNElJUVFDd0pnSU1MWEJBTm1neVNrUjJLNE56OUlEdzZMellmTFFyang0WVpORFgwZWs1M0xDQnhTQXAyanBsaGdoWTFzelp4MDFYTkJYTUV0aEFxUUJXOTVoMDA2UXZFRWFoSnRNdVhVTVFYMEZSWDAycDloQ0xOb3dDZXJzZjhQckJWL0tmRVljWi9uempNK0FIdUVBTC9JVGxnWU1aaEJxNmJFUXZwU1VkR0hsUFZ4QlZqZG82eTRSSWdFTnNFTzZKQmxwRUNWTFVUZ2hGTFFUWWNJeU1LUVpNaEcxUU5GS1g0NWoxaVl0Sm9KVU9WK0NFTUdBRUNNQStJL3c4Q1hHQ0FPMWprdjgxWUlzZ09Fb2VJd3l4QVhZbTUvYzZxbFlabmFESkg1Y3pKaElCTW1PQWgzL2psZ1hWV1F6NlJZREFZWHN0Qy9SZDBsa001QXZJM1VIVGZSd0JxZng0am8xdUJMMklSNmdEWkcwSUFCTzRRSTJEZ0RpWU9zUVJ5a0lNWlAwamdHVUxpY1JZQWdRdk1PRVFDTXloYTRCbmtQSUVFRnFCb1FhN0FIVUlFQkRuZmljanBwRWx4aUlESW1zNlluWmtiYURKWU1EejczY2dmbVdrQ1JZTEpDUDArV0FBS0htZUFaRWdRQWdUamtORTJwQWdTaHdqSUFvempnWjlCT2srd3pzQmM3QU8rZ3Zpa3hLUDhKd1M0R0RHNEtFWE9FcXpxdFBBQTN6SGpDNEt0L0JjRXk0Sng4V2liTTJKa0tvb2FlQUQ0Q3VMYkdCUWx4QkVqWmtHZjlYVnRtNGhnQ0l6WnYrWEZEejBZTnA2TkxheEVEbVhuczB5WkV5b28weG5JL29pY29ha2hSTUJlZzN3VFVrbjIxUmduRThRaHJRNG9nMmNIYlFmMjRxd2kySHFTQlJxQkFETWU1dzZwZ000WURIcVFHekNEa0NBVk1PeUJIQ3dBQWdHeEFEbDRCb3NjWnFBTUNHSUx3amhVUGFGc3dBNkM3bUZKbW5sVUhPUVpXbDFXajR5eVJVRWdrQnRseVQydHFBTjc1NFc1c1dSQ2NLcmdETERqZ09VR0NvR2RHTGNDL3lwNGhCOUdFT0NZcVhaNGJXN3NSZEYwRkdhR0lBTXBRc0NlWllGZk03TjNDUDdhUUh3ZkFUbXJSUFpMcmNpdllHeVdXVmVDdFpNZ2w1ckszcFNpUG9iemg4Q0E3eU1naTFHWlhlcHVyNHpHcGcycllsblhBamVVaERzUFdlVFBMZkxIMVVEYWZtK21Mb3lSdHYzRVpOY21xeXhhTkNCdXZUNmV1d1B4TXRSdjQrclJHOXhJTXVnME1OUUJMTnhQYTJRTHVZRnFBTVRuQTgvbm9DSUF4aUVoZ3VjRExQWStUalA0RXVOajkrRFdKNFJBTlhNNmROL0N5TEt6V0p3RmJ5QkVRQkJMVUlERm1RZHhYVWNxN3NUQ2dHSC9LUHB6ejZBemVoSUdOQTJrTm5qZXdmYmJQc3JZNnZ0b1R6NGZhMTZJQmNnWldpT1E2MGZZZnYrSG1GaHhCOTNSbjhQenkzRGRqckdkSmFtN01YQ1FCRVhrRERQR2NnVVd3WEFHZlYxZlcwQnVheTN5ODdnOXY5MjJFdzFiSVRjd2dTQUZROEpqNEg2WlhWRkxId0JtK1M0SEFyeDQ5VEo3UjlrS3h3OFd3UUtQazZCc1FRR1d6ZFlYby9HamRaT2pNaDgyRHBNZ0pqdHA5VVQ4Mzkxa0YrZUdva2pDSmJJTWx4QllyblZrdTJ0dk13OUhtdkpyQlFPV09GQUVUbG5WRGg5c1diaWdjY05NMUJuRWtpQWtrTEVoQkh0M0dXd1ZtZCs4ZDV2enhlL0U5TXl6N2N5THo0ZnFFU2lWMlZscytQeWVZbTJQUGsvRk1zZ0hEUG96V0lDcWdtN25BVHkvZ05rOXI2RW9uMGQ3OUVrMEZZY0lDQUhFRW9FUHY4cWpEN3lUVmNkZHc4UjRReldBTEJCZytXRm1Gci9LYkhNRlUrWHpDQW15Z3dVbzB4NzJQZlNYUEhEbjM3TGxLUTloMWlkRXdHRm0xeW82eDd5VnN2dEc2aGt3b0RQNk5oWm1MbWZaeGhZcFhZelhJQUdDYUNDOWkxNzlGelRYUVRyaFFzcE40SXZmQXVaWmtycGRjWkNnRTJWbmV6WmNJbUswT254MWR0YitMamU2ZU5VSysyRENqcTlkaEJDMDVBRFNpQVhLVmpTYVJqUWl4R0RIZ3IzVDRGbkFyMHA4MndXZHlGdGJJK0czVFRiZXVCQVFnQkFONVBNakxUNTN4NE82ZXRzQys4NC93ZFpPWWk5dGlPOHl5N2NpM2NoQjR0eFd5ejRTNGNRaVFPZzZ2UjU3VEZ5VmdqeVlYU1JZMVFBT2RHSjhxYVJySlB0b1UzUFF1U25ZRmFQUk5tV0RqRERZV2RWK3ZSblo0R3d6MjJCQU5aU1ZuZmlxbzQ3bHM1UE9WZlBMYk8yS1VkdE1YMkFHQlF3NkU5YzBkKzFkeGRyak50Rk9vRGhDWi85NTdIaGdLMGVmQzZFRzV4NEdpNzlPU2g4Z3BLY1IvZGNvdTZmUW40ZnNrQ0pRL3ozVWIyQnF6VTZhUG93c081Ymg0QUpjdS9EbXE3UW5CdlNaWi92V3R6TjI3R2wwSnpjeVdBVFo5VlJ6YjZiZHZvYk41NHFpQldxZ0dvSWl0RWYzc09mQW14aTNTTGQ5S1ZWL0Y2M3VWemo2TElqRk9sUmRnQVVRRUFNTXEzdkpkaFZyMWtKdUxjTW1uNG9xb0w0WlBJT1JHSENJR1ZORVRoSmdCdG45eThNQnJ4OGRzN2NGaFhkMm9oZzJmbVBPK25TUTNReTJEOU5rVTlrcGk0Mi9vR3lGaThwSWtBdHZ4TVNZblIrSytBa0x6WXRHMjNaQnV3eHZ5ejIxNjBhWVFaRkFVUFY3L3FtaXNEOW5WTGYxK3ZTbmU0NHNRTllWamV6dHBmSFVSbjRUc000c3ZNL0VpU0hCVEYvOWhVWDcwN0t0ajQ2MDJJWElOOXpWYko0YWkrL2ZjblM0c0JxSXhsVzBZM3pkdmdVK3VtM2Fqemp0S1A0TWJGTXRrR25Pczc4M2hQREpFT3hSU1JnY2lYZ2J4a3NGbHFLdGFLZjR3djVRVjUxNnJKNjB5am1oMm05WUVKVHNmbzllLzhoOUJ6YWV3Ukh6VTRRQ0ZGcUU4QWE4dW9taXVJV21ENTZoTE1EaWc3UkhIdVNXYTcvRXNQOVJUbm42czRnR2kvVzF5TjVJSE95a003R01oWVUzczdqNFVzUnFpbEFnUGs2T3YwNjczc3RSNjI4bmh4dkkya2gzL0NibUYxK0x1STN4TmVEaDZWVDlWeUdPUlBsbUd2OVRKbGJ0eElENTRWL1NhajhYZkNkemV4ZXhOdFRWV1VUZmdCbVlRVERvRFhmUTB6WW1XcEEybm9QN0NmaGdIeUhmam9tRGtqak14UHBBT0E0RHo5d2c4WDdWK3IyUlRuejVZcTBIZHMvbFB4d3A3VFBCbU9PN2drSGxYSHYzdy82eGlTbi8rVk0ycGJkWHMvWWtqMkk0RUtFS1c1NTZVdkhsbUppb2Vtb3JjMGdyUVFPUEhoajZXMm5zYjhxQ3g4VUlNUmk0OXRkWmYxQVVYREJXcG9tRlNyOWxGczRKQ0F2TTdacjFTL3Z6Zkh6RGVzTU1FRFJ1dDg3M21yY29wL2NFV0I4RHpYUlA5My9xT2kvT1B6bjlhbXZVbnJ3d0M1Z2U4dHBmQlh5Tko3b2I5RHVZbldqWWFaN0ZZclpOTWNOSzJKS0NqVmRtZEJuQWdCc2YwaEhiMkxMdWRhUURJMVFWeUtDejZtU09tZm9rN24rTS9FdDQvUWl0VWVpT2d6Y2c3V0RZK3oxeVBvbWlYRTlqZjRocEI2YjFwSGc1NHl1ZndYQUFaaEFOWEMrbmFtNGw4QjY2NDlCS0I4Z0xNTmQ3SjVWdW80cVJFYnVNd2NKdlkyRU1pMUNNWG9TcUR0aGx4QUFkemRJMGV5azczMkk0bk9PdXUySDk2dE5adFR3eHJDQVl4QVFMKzIvQ3JNL29hdWhWVDZaVmRKaHVycWV0QTNRaU9LUVVqZTg2eFl3cHdVN0hyMjBuZTB2MmRHNC82K3Z1L2lwZ0c5OWxnRmhpSE5JNHZVYTZIUGR2N2h2d2liRk9PRFVCdVJIakl4eVJIZW9HZ2tFTXNHdEczODdCMzFoMjdHb0pFT0RRYlVPM011N2RubG5aRVdYQlZMc2RPNVk1WGg1ZW9DaUtDRE56K1VQVCsvempyWlNRd0lBNnc5cEpaekQwYXdmeitlZVNhU3dtY3BYWk5UVnFwNjlaWWI4aUI4K09SOTZkVXZ4YU1FWWxHV0JMV0pLQkEzSjkyNHpUV09Lb1hEU25LOXVZSkFRRWd3UE42Tlc3ZTJ1Z3pkbVFRU3dSNE5EdWJNYjlyOGpGVnFJK0FmWVpvdCtIK25EMGFTejVCc3EzMEJ2c2d2QU5tajNnZmhSaCtUU2h1Uko1QllpR0FoZ2g2QjZLQkFhc1dINDZYNy95YzFqcksreDdBRFkrOCtYRStBY0l3d1JpU1laMitVdElaMUEzTXhSaEFta3psbjZmYmRzYVJJZWlPSldEREpCRHc0RDIyTGNZOW1CMkRrSjZNclJncW5NelRYMkFiQnlVa0ZqU3d1eDBDUXlmam03UERlTmgwNkRVRjFwOXZaekdwdVdBUUFZWk1NQU0zQ0VBM1RaUXNIV3Uxcy9VTWYvVlVkMXdTYitHUVEwR21FR0lRQXBmZjNSL2Z1M0tGZHpsQWpOUWdHWUlKMjJBWnB2NDBPZmh3ak1EenozZEx0MjV4K1JvNCtybHRpd1BJWFM0cDEzeUoxUHpScnNGcVFWMUF3WjBTMk00QkVrN0RKRmxyQmlOeFl2UDU0VmtWaXpPaVpCc0VlbW5nTE1FNDRENG5ob29ETTdpSUFPRHhXZ1UwVGhKQXR3Z3daZmpKWGRzRFNlMkNQa0lWQU1CTUJEUUREa2tkVTdFdXUraUhyd2FlQW1Ub3pmZ3dHSUZxSWY0QktWUDB4OUM1anE4dVk1UThEM0dJY3BRbE5DZFdNbmV2Y3Y0OXJjK3lyTE9JaXZYcm1DeXVJektEUk5nUEs3SlhlQmN6TUFkc1BzeHU0Mk5SNEg3OFpUaEZPb0tNRURnN0dCMGZDc1IyTHYvQkk1WXR4a0w4SjBicjZPM1B4TUxEa3BrRHBxazBPa2dZckNqcldNajkrM1JUZE1MZXZVNFRLOGVnN0lGYnBBTmhBaEJXQU5tY01SeVk2U0Evb0xZdk15MzF6bGUyV3U0aENYR1lXWlFOZjczL1lwTHk1WjJsUUZLak5BQ0JlaFYwQ21FQUFkaXlYbmRibnJwMXVubWo4cFJ6bDdmc25iZHdNNTV2M3JkbHZEb3lSc01HakhZQVRQVDBFcXdjc0t3RUZFdzNDQ0hRSVRWMGV5aVd1QUdFVWJLRUg3YUFRbk1EQVFPR0dBc0NZWUFBNVI5YXlmWTZRbDd1bVNVN1JybWVIQjcvYVRiQjFQZDU1QjdHM0RMWUxzNXJBMDJBVVRVZ0F0U3NaSHNMMmJQZ1J0b0hDeHZBRnREc0swWU1IbGNDMDhyeUwyRTZocUw0cUFRdXJnbWlVWEJzUDh3dmRZcnFQYk1zbjdsMVp6NkhGaTI1a0p5M3NoZ0hrTGdDUXdRSUNBVnNEQjdMYjNlYmxhdGhSQlBZWGJmQ2c2eUNGWkEvNUU3R2U2K25kRlRZTTJHMHhsckgwTnY1Z0JYL2VPOVBIdzNkRVk1S0NsdzBMR0JjQ29Zb0pGT1MremNtVCs5WTVlMnIxNWhkRHZHMm5GalVJRUJCcGhnVUl0MmFSeTV5cmg5dTVqdGlSUFc4Unl2N0hmZGpJQjRURERERzN2NHpsM0RmV3Vuak5GV29oMk1Ka0x0RUlFQTlJWXdWaksrNmFqNGYrZ3FuTFpKTjJYRjF3em1oUlZVRE5uYVRBTW02Z1hSekJtdDBwQTdWUTJybGhjMGJtUVhNUW5Qck9rTk9jNkNpSVlIV0JDcUJNa01ZNG1FeFlBbG8xOWw5VG1zN1diVDlkQS9WclR0OUJpdFcxWFFzUXlKNjY1WlBIVUh6czlpZ3hMeEJveXJnUUk0SHZRQnpLWndRVm1BNUR5ODZ5WXF3ZklXZE9JRk1ISUNzZDBEUVRWWWh6VlhnRTFCbUFWenpFYUFJNEVhWXovWURLazZGenBYY01IUFBrem5LQ0N0cDlvZmVaeUF3Q0Z5aUFrQ21leVIxTHFkWFBXWTJRTm1KNURLaER0WWdQYllrTVhaLzR0RmlDdUFBejlCTTRSKy8wWTJuN09MZGNkQktqa295UUJqTTlBMVJCYlVpeXl1bjdDN2psNExUMXBqekM3QVlBaG1QRUV3a0tCcUlEc0VDNzhJOXFjMWpFZUUrQjUzMFdtRlgxNDJtdTZxYy82d0F4bHdBUVlJcWd4akhWYTg4cUp3eFVtcndtbVBQbHkvZXFvZER5U3o1WFVqWW0zRmlyYVd6KzRXUVNLWkVWcWdpc01FVGFPT2pHeW9hSGZGY05GR2xCa0xMREVMZyt4L0hjdy9VZ1E3S3JzaVFnNHFaSG0yMGU2VzJaeHhTTGRwdkoyZCt3cnM5VGxETEEwR2tVVTFkelFUdTZEaUdKTE5ZM3dXdEEwTXBQdUJTOEhPQllFRTg0dC9RdEg2T0t1WFFmOVI4UFpUYVkrc1l2YitCWVl6TVBLa2ZSVGxQbUk4SHh6TVFBYjE0TXNFdTVKUTNJTDd5NGlEODBoanM3aFZUTzhCOTF0b3QycFNUTWhBQmpTUS9YTVU1VmZCZDdNNDJFSUlsN0ZtNVJ5akpYeml6NkN1dHZQY04yUjYvVVRUaDhYOUg2ZlYrUnVxR2FBL1RxNStnbDRGcWZVTkx2ejUvYVFDSkE1S0psb1c3R1F6UXhJbVkrajYxb1lqdU5iTjJEY0xHSmlCZUp3QkpUQjBRUXJXM2JEQy9xQXN3cHVHdFNYTU9jakVmaGtkb0NQQVhXUEhMRXZ2bmU5amNqNWlBZWU3aEtocWU4YnhhOEw3V3V2aUtmZmRuUi8rNWozNjBuT2VUcGhNaWd4QVlKVjRhb3hXRm9US2xVRUdCbklJMFg3WmpKY0hWQW1iMkQvamZ6YlJzdThvV2QrenVza2dpL1lnKzUyaklkNkpHV1lRZ2V5QlBaWE8zZEFORndmUmRURW0rVHRhcFI4UnpKNlIzZWgwd2ZZM2ZHYmZlYmRkYyt6TFZsRnJJNE9xRFdxRHdBS2dBOEJid2Y4bktRVkM2MU5VTTU5aDFTUzBPdEFmdlppaTlRSk1zTGh0R2NrZ05uTlEvakxLZDBBOGg1QVhxUHQvRDkxUEVGT21HWFlKY1JsaWlUYWpaZ3IzYWJKZGgvUk94RytoUEVXSWN5aThINXAzSTEra2JxQS8vQjNXcm9VN2J6akFvL2ZEMUJHdzdiWlBNNnlPcENqT29hbitsZjdzQjJsUFFRUjZ1MDlnWk9Sa0hERDdKdFVRcWlHUFNSYVlER1pQRm9jWndreXIreFcvR1F3cmpFSThyaFdNWllLVndPZGRmTWhkNThUQzNybHFNcHhmdTJnYVVRU2pjdDBXc0ZjWDBpdWFhSmZLUlJhMElxTmxOMzVnNlA2ekxuME83Q0dEbzhHZUVZTTluUkRHNkxuUHp1YzNiWnppb2VaQVhxYnhzSzFWaE9YRFNwalpCYVhDUjh6MEJvYzVscml6UEpxOXZTenQwaW9UT3kxalVHbjIwV20vdTczQnRyZmEzRCtZdFpPellEVFphM3BWbUJzMjlydXRrc3JNa0JoUFFiKzR2aDErVHpCbEJsbTZ5NHkzSjJPRjBCYUxScjJZU1NWM1BianFLVitibVZ2M1U4VGVrWmdEOGRtNDMwM09FQU9ZL1J1UjYybTFDdEE4MVg0SVU5QlVteWxiNzhmS1plUStMSC95WlJURFc2bWIvZURUaUxlVDJxTU1Gb2JNN3g2eStoVElmalRXL3pneG5Zc0RGaTZpR1o2QzZkOW9wWXp4eHpTNmltWndCR09qOTFPSDIvRGdaSWRXK2ZzVTZlMjBPckRub1JPcGRTV25QZzNXYk5wSHRyZXhzREJDcXpYSHlDUTBEaUhCL1BSR3hpWlhZUFZlY3ZNUU1yNWZHaG5WK29WNU95MUVEbkZBMkhHbHdsdWlBY1poeGlFdTdUWFpmVUxIaEVLWEUzaGE1YXlpaG1oR0E5UlovK1RHYjdqbjc4ajlFU3hlSEN3Y0QyS1lSVEFya29YbnVQakpBSDJEdG9LbGdpVXlXUFJMSnp2NmgxZ0VGcWZaLzhoMi9jMEp4M05xVVpKeUEyWjZoZEFXSS95clJMZFQ4RXpITnN1ZzB6S2lhV2VLZWduR0xRTXBET2E1Y2lUWXliVUxpMmJkTXY1R25YV2hZVmVEdW1aMnRzeE9HNDFLMmFHVzNTRHBKUlkwSU5oNVlBZ0RCd0wzcklyN0ZxazREVXRnQmpHK21leDNJbjBSTThpQ2ZqTmdjR0RBN0NPUWE1QzlpRmk4RDF0WWo5Y2dRV2ZpRXVycDkrTFZINUhDdlpnNStCejlQaXowbDdHT1g0RDhGaHBianNRaFJpSVc3NllaL2dJcDNvWFVZTTMxcEJMbTUyRlFRWHRxUGEzd3Y1Qy9GRE9ZbVliVG52M2J4UFlPZWdzZllkMnhNS3d5ZzJxZWxqMmJPaCtMNnk5b3QwUmFmUkc1QnVWdjRIb1l4UGRMdXc5dzNuaGJIWGN3UUlJaVFwRmdXQWwzc01BUThZamc5aWI3cmtRWWlZVTlIN04xTGhFRWpYRFE5WXREZjM4MFB0TnFCYzlBSSswSTJYOHBwWEM1c0dNZElRbHhTQlNNR2xDWU1XZzBiZGE4dm9VKzdkbndESjBJZXc3b1kyc2FmOXJxa2ZoenZWa25tOHpnekdEaFRBRVJFWU5SWmRFZmF1dFlsMWVueEhXR3lBZmNMZHRmeHpGN1Z0bTI4L3A5c1NTbVpPZTRjdzRZQnpsR1B3dDMvNWNRd3Bzd3RnMXJKbUlSbmhtQ2dhQVRLbVkwZGR2bjlUd29PUXZtT1VSYVRReVhJLzhZOEZWY0R6QjBHTTZ2WXpnNGhiWEhQNU1tUDVPOFdCSVRoNWhCTlE5MGZvR3lmU0dldndpMkMyOUVkL3hJeXZZRkRCZVBCa3BDQW5HWVo3QjRGbVg3TThEbG9Pc3c3U2Fta3JuK01YajlGTHJwZWVESDBUaVlnV2RvalhhbzYvY1NlRGJEM3Exa2IyaVh4K1AyWEZLTWlKOG0yRGl4UEEwMTROeE10bG1NSjBqYjl0blpaeHhuRE9ma0JCUUN3MkdqaGNWSzAyV3luZ1ZseWVZeFRIQmNDdUVDQzR6V1dWbmkzbVM2cndqY09aZTV2c3E2T3NyMlNlSXhCcGk0YnVENXhRRzdMSm05ME1GU01DUndpU0xTbTZuMWp3dVYzcnV5eGMwc2tVUnJNdERwR2lkTXNaQ0MvYXF5endxOU1rVXJ6STFHQW94YTBFN2E0NVd1N0EvMUoyUGRjRDhDQktwRXU5U09uTVBMOTgzejV4TnRQU3NSR0dZb0FramdFZ20vWjk5UUh5NGpsM2VEN1I5VWptQUNPQldKUThUaVBsdisyZnQxM0JiRTZZUWFDRFh1aHRrYWl1TE5vTmVRd241R0NxTllQc215SThhSVJhTHVRNjRiUWlFUWh4bGdFZXhvVEsvam9KeWgxWUdSU1JqTUMxRVRBaytrUUV4YlVINFhoQmtJczdoS3BwWXZ3MndFcjFuaW1EV0FFU0lNZW1BMlNvelBSLzU4WW9RRXVBQ0RZSmNnQjNPV09IQWRRZng3YWZQcThNRnFVWi9FYUVBS3dSWjdmZVlYS3kwZXVkS3lHcHNhVmt6R1NOdGdCT1RJcHB0R00yQUxLWEVBbUhmUnVLQmdpZkZFQmxuNmxzUC9rT3VLWVBhVW9ldW9FR3dZcEh2cXhyOWVLOXprTURTK1R6U3NNRG9KQXV6MnJEY09oL252S3NWbldORHhMUWlZcHQxMWl6SmZrN1RWekRLUE1TQUFCaUh3NE40NXZlVGhQZjZUVzlieWxMSmd3NkRDek5pWlROZVkrSHFXSGhMRzlFSk4zWWlVN01CSWFhOFJnU0FsRW90ZnFKOTE4MTM5NDFmUTdiK1NRTVpWQVlaa21MV1J1aGh0eWdRaDFCaUxWSXNEakV4SWdQTkVEUWdERXBBSUJybHV5RTJEbVRDV2lCK2dKZ0FkakJITUVwS0ljUWowYU9vaFpnNFlqekdXeUpBaVVDQUhVUU1OQjBrUmNFUWJiQmE0aVIvaS93SDNENVBNcGQydDVRQUFBQUJKUlU1RXJrSmdnZz09Iiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJjcmVkUHJvdGVjdCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9LHsiaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiYmJmNGI2YTctNjc5ZC1mNmZjLWM0ZjItOGFjMGRkZjkwMTVhIn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA4LTAzIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJlU2VjdSBGSURPMsKuIFBybyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMjEwMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjEuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA4LTAzIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wOC0wMyJ9LHsiYWFndWlkIjoiM2UyMjQxNWQtN2ZkZi00ZWE0LThhMGMtZGQ2MGM0MjQ5YjlkIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIzZTIyNDE1ZC03ZmRmLTRlYTQtOGEwYy1kZDYwYzQyNDliOWQiLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gaWVQYXNzIEZJRE8gQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJmakNDQVNXZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQVhNUlV3RXdZRFZRUUREQXhHVkNCR1NVUlBJREF5TURBd0lCY05NVFl3TlRBeE1EQXdNREF3V2hnUE1qQTFNREExTURFd01EQXdNREJhTUJjeEZUQVRCZ05WQkFNTURFWlVJRVpKUkU4Z01ESXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTkJtclJxVk94enRUSlZOMTl2dGRxY0w3dEtRZW9sMm5uTTIveVlndmtzWm5yNTBTS2JWZ0lFa3pIUVZPdTgwTFZFRTNsVmhlTzFIamdneEFsVDZvNFdqWURCZU1CMEdBMVVkRGdRV0JCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFmQmdOVkhTTUVHREFXZ0JSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QU1CZ05WSFJNRUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUJCakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUF3ZlBxZ0lXSVVCK1FCQmFWR3NkSHkwczVSTXhsa3pwU1gvelN5VFptVXBRSWdCMndKNm5aUk04b1gvbkE0M1JoNlNKb3ZNMlh3Q0NILy8rTGlyQkFiQjBNPSIsIk1JSUIyRENDQVg2Z0F3SUJBZ0lRRlo5N3dzMkpHUEVvYTVOSStwOHoxakFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFbmZBS2Jqdk1YMUV5MWI2aytXUVFkTlZNdDlKZ0dXeUozUHZNNEJTSzVYcVRmbysrMG9Bai80dG53eUlMMEhGQlI5U3Qra3RqcVNYRGZqaVhBdXJzODZOQ01FQXdIUVlEVlIwT0JCWUVGTkdobUUyQmY4TzVhL1lIWjcxUUV2NlFSZkZVTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUMzc1QxbEJqR2VGK3hLVHB6VjFLWVUyY2thaFRkNG1MSnl6WU9oYUh2NGlnSWdEMkpZa2Z5SDVRNEJwbzhycm9PMEl0N29ZakYya2d5L2VTWjNVOUdsYXF3PSIsIk1JSUIyRENDQVg2Z0F3SUJBZ0lRR0JVclFiZERybTIwRlpuRHNYMkNCVEFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFc0ZZRUVoaUp1cXFuTWdRalNpaXZCalY3REdDVGY0WEJCSC9CN3V2WnNLeFhTaEYwTDh1RElTV1V2Y0V4aXhSczZnQjNvbGRTcmpveDZMOFQ5NE5PenFOQ01FQXdIUVlEVlIwT0JCWUVGRXU5aHlZUnJSeUp6d1JZdm5EU0NJeHJGaU8zTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJREhTYjJtYk5EQVVOWHZwUFUwb1dLZU55ZTBmUTJsOUQwMUFSMitzTFpkaEFpRUFvM3d6Njg0SUZNVnNDQ1JtdUpxeEg2RlFSRVNOcWV6dW8xRStLa0d4V3VNPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIzZTIyNDE1ZDdmZGY0ZWE0OGEwY2RkNjBjNDI0OWI5ZCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6NiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNC0yNCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRmVpdGlhbiBpZVBhc3MgRklET8KuIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDA0MTcwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA0LTI0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNC0yNCJ9LHsiYWFndWlkIjoiMjM3ODY0NTItZjAyZC00MzQ0LTg3ZWQtYWFmNzAzNzI2ODgxIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyMzc4NjQ1Mi1mMDJkLTQzNDQtODdlZC1hYWY3MDM3MjY4ODEiLCJkZXNjcmlwdGlvbiI6IlNhZmVOZXQgZVRva2VuIEZ1c2lvbiBDQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDNlRDQ0FkR2dBd0lCQWdJSkFKYlR5cnUxWC9JUE1BMEdDU3FHU0liM0RRRUJDd1VBTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRBZUZ3MHhPREEyTVRJeE5EUTFOVEJhRncweU9EQTJNRGt4TkRRMU5UQmFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNVmpLSFdwYkQ3VFNsTXhvY2pUbDZuSWY3eDMyUG1zUTl6R3VMR0dxQTBVUVpvSXEzWEx6TDZMWVV2SjVBNWcwdXlGR2xsSEVmR0FLckVhQ1E4RlZ2UFMvVWgwRnlmeldoUkF6aVRTaWpqTUlJVmpqalV2OW05dkZtY1hTY2dIaWc3T2R6ODg1OFYwa3JOSDk5cUdtM3dqZ2FPZXJUV210K2pYQ1VmbjAxSWtUUHd4RzJIbGdFZDQ1ak5MU1Y3Vm9vbCtLZThFMmtpNGxFa1RlSHpib3VsUjVHVWJwM25NaTdFNDdWTVFhM2JOd256V0Jic2FCU1NRaExrM201SGFLaGh4YTZ3SkRLNDdOaU1Da0NrZElIdVdTUUxWQWZtODVVQU9OdEVPUHdpME91SzNxYmU4eUtPRkdmMEtoQjVNTWVBeW03TVYvTTRXMGE0OW9nUEQ5cE1DQXdFQUFhTWdNQjR3REFZRFZSMFRCQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKV3o1eExNazVXTlliQWI2eU94RUNCb1oyV2VCL3FsNFZKM08vMy90TnN4T1luekxlV281NDB6UWg5ckFtYXh6N2V1bUJsc2tNcTR5R1BTTlhCOXljV0dIZ2tjQ2VTek4yd3Y4Q0l6REJzMm9CWmpUTms2NUxCWkRzc1RPQnRNVy8rdVRGSFFmYnVPM0lTTGhJMERYZlJFaTlORE0zamZrMTF4SGNzZmgyUk1WK1FkTmZ3VmFaWnJDcStvdUcrRXZrdjdLcXErb3l1MFZGTS90ejY4VEdsNnlsaFBGUjFxaDl3dHRwVmpBT09DRVFDTHFQMmRQMjhsd1lCeUNxSFFxVkh3YnVqdi9MWmpabktXM0xZbmRaaXhQUFNSQ0pzc0REd0p2aC9mNm5UeGc5WkUrL0pjWXJlNUNhSThuelZIYVNPQ2pOSjdGelVMRzY0SmlXT3ZRNTA9IiwiTUlJRGRUQ0NBbDJnQXdJQkFnSUpBSUNVVHZrZ3RqNUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GRXhDekFKQmdOVkJBWVRBa1pTTVF3d0NnWURWUVFLREFORVNWTXhDekFKQmdOVkJBc01Ba05UTVNjd0pRWURWUVFEREI1SFpXMWhiSFJ2SUUxMWJIUnBRWEJ3SUVaSlJFOGdVM1ZpWTJFZ1EwRXdIaGNOTWpBd056QTNNVFF6TnpFNFdoY05NekF3TnpBMU1UUXpOekU0V2pCUk1Rc3dDUVlEVlFRR0V3SkdVakVNTUFvR0ExVUVDZ3dEUkVsVE1Rc3dDUVlEVlFRTERBSkRVekVuTUNVR0ExVUVBd3dlUjJWdFlXeDBieUJOZFd4MGFVRndjQ0JHU1VSUElGTjFZbU5oSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFLT2VxQzUvcDBEMWlzQ1lLUUpsVlVPckI2STdETG9jdW5FL1JtOGR1R1RieXhRaHQzQ2JGVlR2M04yTHAyZmJqeGxJKzNzT1NHazMzRlRZa1RxeGNkSklySjdTc2tCY1VTTnJmS09hUVQvNktRY1A0Q203Vis2NTVUcStUV3h5eFdRaER5Z3QxNXFvUDdNdUs2YlQ5U3dwQ2pwZktoYU1TbXlRYU1vVWNSQWJMcWR6QkNhYzBoekIrWmUrZ3FKbG5XVjlVYVNJMnJGc1Z1SDRaRTBjUk8rTU9wYUxnTS9zMjQ4bkdHSHAyMmV3U1FmYm5QYUJiYjhpcXlBUCtjdTUyR0xzVXBLUkplYkUrUjYrUE1ROUpDZFdlUVpSM0RrZlNpZGt2M21jYjRqcTFpSXRhK01xS2hSbndyZlhoOTExS1dMbllBbDlFTkNoTFgwYzZTajFRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3SHdZRFZSMGpCQmd3Rm9BVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUZMckRoYWVnZUtIeFlqSDNFUDN2VUJLaG56TTIwNkFTeGdlWUNPMkVjOXBPbFlKYWVxRkUrc1VhbVVWL3B3akRscU5hU2dGZ3k3VHdlWWt2T21NbjRxU2NzSHF2SjN6R09BaWFmd2FoMXZVSGZDbFhSOCtheE8yaUdPVUYwSktyWjlZWWpiQWE1LzRIQ2x2N2pGUE9kTVdUT1F5bmdvaUhBczNqa3VZanBDTEZsQjRWT2kzZDF3akExcG5UZEJLa0FiN3Q4blR2dysvWGJGdmNRYTczVkg3c2p2b0JxRDNmZE1mUmN1VnE0cVVadFpUNmNHYWdUSEQ2MVR0cWg5b01DWlhjRGJSMVBHWm5OYnF5Y3NXUERJSzBucG1LMy8zbGZWOGMrWnNyeTZlMTcwbWZKTVpwN084bTZDU3o2L1ZMSyt5REpkNzg0MXdwbWVLVGY2SW5aQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVF3QUFBQWdDQVlBQUFEbmxVWnFBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFBQVpkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNakh4SUdtVkFBQUsxRWxFUVZSNFh1MWREWEFjWlJtK05PQWZLb2c2V08wUWNyZVgzTzcxUjQxb0hkU3FxREFPZzMrY1lFWEJvbFhSVEVuMjIwdGFLVGM2NG1nQnF6QmlFVVZwQmRxaXd3aHFTZElTMnVwWVNndlJ0cFRTY2tsald6SGFnanBTUmRyNHZMdHZqcnZrMjd2ZHZkMUxqbjdQekROM3QvZCs3L3QrZjgvKzc4YUswTkRhYXIycU9kWFpvcVd5SDlSMGEwRmN0NjdXZEhHVFpvalZDY1BxU2VqVzFvUXVIc095L2VCVHNEbU0vNTRaVDlqK0xXR0lnN0RmQi9zQmNEUHNmNFhmUDhYM2IydUcxWkhRelU4bVV1S2R5V1RIbTVxYWNpL2pIQUtCeWlmMGJCcitMd2FYSVBZUGtNZHFmTDhYZFdwbHMxQUEzMS9Rak93OThMOFM5YjhCWElSMituRGM2RG96bHNrMHNsbmtRTXhrUEdYTzlFSnRWbllHRjRzVXlWbmQ4VVRhZXA4YncrNkxha0JqNWl6ZGJOSlMxcnhFV255V3hnMzZFbVBkV29QUERlamY3ZUFUR01zSGFEelR1QzZoYmowTi9wWG1Bc3J1Z3MwV0xQOE51QkpqWkptV0VsY2wwOW1QSjFKbVcwdEw1K3VpSEJ1R2tYc2xqWDg3bmk0RXpWbms5QXZrc1FuNTdFU2RockI4Qk11UGpPV1AvLzRPSHNSL2U3RDhZZFRsZnRSaEZmZ2RMRzlIdTF3QWZ6cjU1akFPa2lRS2h2VmJHQjZDMC8vaSsyaU5lUng4RmdudlJmeGZhaW56U2s3TkUwaUlVUGJmNDN3V21OVE5kN0JwS0VBN0xaZkZBWTl6cDN5WlRTTURpUVZpL1UrU2c1UVlBSWZPbUcyZXdzVWpBL3JoVzdMNEJlcm1qOWgwVW9CMk9CK1RaVFc0Qi9rOE95Ry95Q2lPb1cxSVlINkg4WFB6OUxiY0t6aWxRR2hwTVp2aFp5SEd3RzNnNDJCazg1WjhvOTBHOFgwTmlTczFJdjJRR2s4S2RXc3p0NHNuSVA4UnFSOW1EUVhESWRaU2JCb1owSWwzUzJPWFpYWXBGNDhNVTE0d25LMWJlVzQxcEwzRkVRQ0psUFZXdERHMmZ1eVZyTlIzdEJUZFNqQjhZcklGb3lWdG5vMk9DekJneEROQkI2cFhLTUh3eGlEOWdLM0tjNlBja3ZCR0pSaStNY21DMFlENGZkSzRYb2g5Vy9ZVENaUmdlS052d2Noa0d0RzJlMlcrYWtzbEdMNHhtWUpCYXhscFRJK2tOUlFkbUdSM29VTUpoamY2RlF3NmNDcnpVM3RDTUxEV3VRc2QzUitBdzNLbkJRNUt5bmpoamR4T25uRGlDRVp1R2pyc1lXbE1KdHBpV1VLM0JtVC9GZkV1ZGhnNlVQZTZGZ3owYlI2ZmE2TW1uWTNrbER3aGFZakxVVTZlczI3dDBnenptN1ZnVXU5NkQ2ZmtIeENhNjJVVkdDTXE4ZzAyalJRbmltQm9SdllpYVR3bTJudGZXOXZDazdXMGRZSHMvd0oxNjNrNmVNWnVRMFc5Q3diRzlLMXNPcVdBdklVMFg1dGlEWnROYlNqQmNHRUVndEhXZHN2SjhFMm5BdVV4aWJwNWhXTTkyb0RmMnliOFgwS3gzckVORjBvd29nSG0waEpwdmphVllQakNpU0FZaWJUMWVXa3NKaWJDay9QbTVVNWljOHJ4UXBsZE1SUHA3SGxzSGhxVVlFUURKUmdoNHNVdUdIU1JEK3BJVitUSjR4SDFMRzlkakNIVGlNbFI0VmlHMkU3SFJiaEFLRkNDRVEyVVlJU0lGN3Rnb0oyejBqaE10SE9lamwyd2VRRlkvbEdaZlNuRmZEWVBCVW93b2tIQ01CZEw4N1dwQk1NWEtncUdJUzV2VHB0bmgwWFUrMDVabkFKREZBekQ2RGdkL3A2V3htSEdEZkZGTmgrSDBRYjB3YU95TW1PRStPVU5JL2NTTGxBMTZsMHcwRjY3NDdxNHBScEdjZHFhN2t1UjVVdEVINDVnRG13S2kvRFpqOC83SUVTMzRyT3plYWFZeldsVWgzb1JqSm96Uk1Hb09BRU5hMGkyZFRHR2VFcDhURkptUER2WXZHclV1MkNFUWJxaGtzT0ZCc3lsaTJXeGFzVGo2TmQxMnBzWHY1N1RDUVlsR0M0TVNUQmFXNjAzb28xZGI2cXpxVnRmWW5NNTZBcEJ3OW94b1Z3Uk1ZbEdOSzM5MVZ5aUtpakJpRVl3bWxQZExiSll0U1RhN3FIaUErdStvUVREaFNFSkJ0cHZoZFQvR0hXeHY5eld4UmkwdFBpRXRId0p4YlZzWGhXVVlFUWpHSFJ3R3VPaDBnVjVrVE9lTWkvaGhQeERDWVlMUXhDTXMxcXRWZ3p1OHJldnB5eVBqd0h3c3BWaC9TdVZXaktkQ3dTR0VveW9CQU81cDgzM29wK2VrOFdzRmRGK3dhOFNWb0xod2hBRUEzN1dUUEJiUkhUY0FleEd2SlROSGZRTU5jZjZCcytQOWVibnhmcWVQSldYMmtDWnpIZ2ZFeGpDR1FJbEdORUpCc0YrRUpFdWRzdmkxb2JpVDV5S2Y5U05ZT2pXWmpUeWZhSFJ1ZDlBSG90WXBXQTROeHFKWTFMZlROVDVLMndlaTYwZk1pQVVENEtqQmZibWo4YjY4c3RqMnc3YUQycWhmVS8weHk2WnJ6SFMycXVscFRObCt3eUl1aGNNakJVNjYxUU5tMmN1UG9QRFJZVFJCanBiUjJNQU9WOUhaek9ROTgvdy9mWXdpUEh0ZmplMGJ2MkZrL0NQZWhHTU9yc09vL0x0NjdvMVhEZ1Z1aUUvQndMeGp4S3hLT1hHMk02ZHRpMzZ3OE9SZG5HUDdUY2drRnVkQzhiVXZBNmpsa2lrTzgrVHRnMklNWFNZemZ4RENZWUxxeEFNTDdldm83N3R0bkYvLzBuWWt0Z2hFWWx4SExxYXpKMnRqRXFiczlpeVNXWG4ydjREUUFsRy9hT3NZQmpXQVRiekR5VVlMZ3dzR0xscEtMdFY2cE5KSFZaNFlITGYvbmZKQldJQ2gySGRRRVhpNmV3bE1yOGxkSjVIWXR2N2hSS00ra2M1d1VENzdHVXovMUNDNGNLQWd1SHA5R2RLWE1YbUVJeDh1MFFjWFBqWWErMHltVXdqMnV0eHFlOGlvbzRYMnZZK29RU2ovbEZobCtTUGJPWWZTakJjR0VBdzZIb0s3QTZVbmNpbzU4R21wc3RlZUIxRDc5Qlg1ZUlnNGYzRHAzT3BHT0xNbC9rZnh4Mnh6RnJmajhWWGdsSC9xTEJMc29YTi9FTUpoZ3NEQ0VZaVZmNzJkV2JwSmR3OSs4NlJpc040OWc3dWgzVmhGNFBGNlFtSi8xTHExZ0l1NGhtVkJBTVQ5dTd4NzB3SmcvVFlmVTZoTEpSZ1ZFYUZYWklIMk13L2xHQzQwS2Rneko1dG5nS2ZCNlMrbVBqLzBJd1pIUy9uSWc1R1J4c2hCZ05Ta1NqbFlpNVJBUHJ1VWxtY1ltSnkvWG5HM0hFeEs2RGlGa1pFeEJqWXlDbVVSU1hCUUR1UG9BNWJvMmJTeUw2ZFUvSUUzaXFVbmdZTm0yZ0QxN04wK0c4VnArUWZTakJjNkZNdzRycGxTZjBVRVRGTk5pOUZ6L0RNV0cvK2lFUWtIUGJtTjhTMmJadDQrYmh6ajBuNUozaUJkRnMxbC9BRTFMMnVCYU5XVE9yaUE1eVNKeUR2NzhyODFKeWVyeTZXUUFtR0MzMElSdE9jM0dsb3A4TlNQMlBVeFZObDEvVHI4cTJ4dnZ4NjhQa2lzZmduZmw4ZjZ4OTBmUVVsNG41R0dxK1l1amh5NXF6dTEzQ1JpbENDNFkxMUtSajBXa2d0Ri93bVJTVVlMdlFoR0Y0bUdBYUxZUFB5MkRnMFBkWXo5SDdzcHN5TjlReFVmQzBpWGZ5RlB0b25pMWxNR3F4Y3BDS1VZSGhqM1FrR3hDS3BXKy9tZElKQkNZWUxQUW9HdllRYTl1WGY3MWxwNjZKS2xIdDgvUXNVUiswWFRYdUFFZ3h2ckEvQm9MZnIyUWZIci9HemxlbUtLU01ZdW5rSFRTekVsTDQrc0ZhQ2dmbytCKzdXak96bjJMUXNuTmNHaUQxVVR1YlBvZG5GNXBHQXpwZ2d2dXRXQnVyNkg3dE91cmlVaTVRRlhTV0tNdC9IQk41RWF5WFVyK3c5TWNFcGp2R0s0dmZJYndWZHc4SXBsQVdOQlpTNUR2V2hONVhuNGVkb3FkOG9pRnl4MndrK2l1LzBJdWlsOUt3VFRza1Q0bWx4RHRyelJtNVhqUFVvMnBYZTZHNDlnanh2dytmQ2hOR2hjZmh3UUM5amFUTEVHOXhvR0ZlV3ZpWStVdVNtMlErY29YZHk2TllpTk93eVZQckhHQmgzSm96dVVDc2VUNW1YUWZGL2poZy94T2ZYTmQyOGdqbzBhSDNwTEFsTk5HZHRMNVlpNTV2UWdiZWo0KzZnLzlnc01xQU9IM0hhU2Z3RWJYY0R2bWVUaHZVcFRlOTZ5NFF6TTc2UW05WTBaOUZwZFBjbTZ2TnBzQXQ5c3R4cE8rdlg0RWJFMjBvVENjc0dTb25sK0IvZjZXYS9WY1Y1MGFTUHg3dE9EZUVCeGcxMHh5K2Rrb1hnZkFneEZpRGUxOUFPMzBNL3JFUU85eUxtQTRpL0JiKzNsK2Jua1BJSE40UHJVTCsxK0Z3QjIydmhveDFpZjFHODFYcGJ2QTI1WmpLK3IybHhSMjRhMWQ4UlB6RWZ1d29XY3NFV2lKTXpZaitJM3crVnRLc2hIZ0gvQVBaU25xalR6Zmk4eGg2N3VuVXVQZHJBMjhOeFlySC9BejN0STRqNStUT0xBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIyMzc4NjQ1MmYwMmQ0MzQ0ODdlZGFhZjcwMzcyNjg4MSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTA0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0wNCJ9LHsiYWFndWlkIjoiMjM0Y2Q0MDMtMzVhMi00Y2MyLTgwMTUtNzdlYTI4MGM3N2Y1IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyMzRjZDQwMy0zNWEyLTRjYzItODAxNS03N2VhMjgwYzc3ZjUiLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gZVBhc3MgRklETzItTkZDIFNlcmllcyAoQ1RBUDIuMSwgQ1RBUDIuMCwgVTJGKSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUIyVENDQVg2Z0F3SUJBZ0lRRlFOS1crN3piZy83ZCtsVHlySVd3REFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRJeU1EWXdPREF3TURBd01Gb1lEekl3TlRJd05qQTNNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFc0ZZRUVoaUp1cXFuTWdRalNpaXZCalY3REdDVGY0WEJCSC9CN3V2WnNLeFhTaEYwTDh1RElTV1V2Y0V4aXhSczZnQjNvbGRTcmpveDZMOFQ5NE5PenFOQ01FQXdIUVlEVlIwT0JCWUVGRXU5aHlZUnJSeUp6d1JZdm5EU0NJeHJGaU8zTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUUNCME5GUVNOMHo0bFd6L3ljMzZld3JUQ3p0dEsvcUZ2bGFQT0toK1QxbzZ3SWhBUDBvS0tBK2NpY3NEeTNZM24rVmxQOGVCM1BCek1raHZXLzlJU1hDdytWQiIsIk1JSUIyRENDQVg2Z0F3SUJBZ0lRQlRtazNad2lsRlhqc1p5d0hEbk1nREFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRJeU1EWXdPREF3TURBd01Gb1lEekl3TlRJd05qQTNNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFbmZBS2Jqdk1YMUV5MWI2aytXUVFkTlZNdDlKZ0dXeUozUHZNNEJTSzVYcVRmbysrMG9Bai80dG53eUlMMEhGQlI5U3Qra3RqcVNYRGZqaVhBdXJzODZOQ01FQXdIUVlEVlIwT0JCWUVGTkdobUUyQmY4TzVhL1lIWjcxUUV2NlFSZkZVTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJQnlSejRPQWxSWjlIejlLVjdnMlFOdEMwQzhKeEgveExKWThGWkVtdEozc0FpRUFzcmVUMCtlTmtOY1VqSTloNU9QQ29INk5tc09rZ3ZFQUJKWnJGMDdBRGtZPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkQmxvYiIsImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiMjM0Y2Q0MDMzNWEyNGNjMjgwMTU3N2VhMjgwYzc3ZjUiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJub01jR2FQZXJtaXNzaW9uc1dpdGhDbGllbnRQaW4iOmZhbHNlLCJsYXJnZUJsb2JzIjp0cnVlLCJhdXRobnJDZmciOnRydWUsInV2QWNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxNDAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjYsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsibmZjIiwidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAyLTIxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMi0yMSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImJmOGYzOWE1ODI2ZWI5MTBkZTRlNDM2NjM1YTUzMGUzZWNjZTQxMGYiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYmY4ZjM5YTU4MjZlYjkxMGRlNGU0MzY2MzVhNTMwZTNlY2NlNDEwZiJdLCJkZXNjcmlwdGlvbiI6IkhpZGVleiBLZXkgNCBVMkYgU0RLIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsidWstVUEiOiJVMkYgS2V5IFNESyAtINCy0ZbQtCBIaWRlZXoifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNNakNDQWRtZ0F3SUJBZ0lCQWpBS0JnZ3Foa2pPUFFRREFqQ0JoekVYTUJVR0ExVUVBd3dPU0dsa1pXVjZJRkp2YjNRZ1EwRXhIekFkQmdrcWhraUc5dzBCQ1FFV0VHeGxaMkZzUUdocFpHVmxlaTVqYjIweEdqQVlCZ05WQkFvTUVVaHBaR1ZsZWlCSGNtOTFjQ0JKYm1NdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1Rc3dDUVlEVlFRR0V3SlZVekFlRncweU1UQTRNVFl4TnpJME1EVmFGdzAwT1RBeE1ERXhOekkwTURWYU1JR01NUnd3R2dZRFZRUUREQk5JYVdSbFpYb2dSa2xFVHlCU2IyOTBJRU5CTVI4d0hRWUpLb1pJaHZjTkFRa0JGaEJzWldkaGJFQm9hV1JsWlhvdVkyOXRNUm93R0FZRFZRUUtEQkZJYVdSbFpYb2dSM0p2ZFhBZ1NXNWpMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVMTUFrR0ExVUVCaE1DVlZNd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTMEFjVC9oUkZVYmxGY0lwNmJoNFAyWlNxMWFqaVVhZ2hlYzl1ZFNGR0lvVVo0MFkzSUVQbHRrMlR4YndNL1JwV21DRnJac0FkZnl4MjFydllkcEw4Um95OHdMVEFNQmdOVkhSTUVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVGxaOER2M3FBS2VLYzFDMk9pTnZIekdxZzFKVEFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUFIcHRzeCs2R3F2Nm5iYStiVDlmVzduOHhzZkg4UmhJSzhWWUZQS0VzQlpBSWdRaE9TRHhrRGtjeTluYlBUNHgwRW1ERDlVc0w1MDF0a1NzY2ZXYTBhTGJ3PSIsIk1JSUNaRENDQWd1Z0F3SUJBZ0lVSXlsYlNFQUUxNXpTRXZ3RjByOEd3VWQvNW9Fd0NnWUlLb1pJemowRUF3SXdnWWN4RnpBVkJnTlZCQU1NRGtocFpHVmxlaUJTYjI5MElFTkJNUjh3SFFZSktvWklodmNOQVFrQkZoQnNaV2RoYkVCb2FXUmxaWG91WTI5dE1Sb3dHQVlEVlFRS0RCRklhV1JsWlhvZ1IzSnZkWEFnU1c1akxqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRUxNQWtHQTFVRUJoTUNWVk13SGhjTk1qRXdPREUyTVRjeU16RTRXaGNOTkRrd01UQXhNVGN5TXpFNFdqQ0JoekVYTUJVR0ExVUVBd3dPU0dsa1pXVjZJRkp2YjNRZ1EwRXhIekFkQmdrcWhraUc5dzBCQ1FFV0VHeGxaMkZzUUdocFpHVmxlaTVqYjIweEdqQVlCZ05WQkFvTUVVaHBaR1ZsZWlCSGNtOTFjQ0JKYm1NdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1Rc3dDUVlEVlFRR0V3SlZVekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQXFsbUFNQXo0aDVJd2ZWWndTYjRqQWk1b3Q4NUZFMGJ1dUNLczRtZnVkMjFxc281cnB1S0g0M3NLcWJyTkZRU3R4NVJTQzlibUJxZFMybHljbDM1bGFqVXpCUk1CMEdBMVVkRGdRV0JCUldJaVJWV2F5WkJuSDVCbFRuUURpR3lRNk9MVEFmQmdOVkhTTUVHREFXZ0JSV0lpUlZXYXlaQm5INUJsVG5RRGlHeVE2T0xUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lFWlhoNzZYRmhMeEpJVDhGc0lvUUhUd2ZIQ0U4c1VzS3lQcmNMdi8zdG9NQWlCK3BqWTliSTZuS1Q2cUZ1cWdSbitiWEJBZE1lZy8ydlg4d0c0YUJ0b01BQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUlBQUFBQ0FDQVlBQUFHME9WRmRBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQXlScFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1TXkxak1ERXhJRFkyTGpFME5UWTJNU3dnTWpBeE1pOHdNaTh3TmkweE5EbzFOam95TnlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUlNaV1k5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVkpsWmlNaUlIaHRjRHBEY21WaGRHOXlWRzl2YkQwaVFXUnZZbVVnVUdodmRHOXphRzl3SUVOVE5pQW9UV0ZqYVc1MGIzTm9LU0lnZUcxd1RVMDZTVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG94TWpGRE9VSTJPVFZCTURFeE1VVTFRa1JCUkVRd1FrSkZNVVpGUmpoR1JDSWdlRzF3VFUwNlJHOWpkVzFsYm5SSlJEMGllRzF3TG1ScFpEb3hNakZET1VJMlFUVkJNREV4TVVVMVFrUkJSRVF3UWtKRk1VWkZSamhHUkNJK0lEeDRiWEJOVFRwRVpYSnBkbVZrUm5KdmJTQnpkRkpsWmpwcGJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qRXlNVU01UWpZM05VRXdNVEV4UlRWQ1JFRkVSREJDUWtVeFJrVkdPRVpFSWlCemRGSmxaanBrYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2pFeU1VTTVRalk0TlVFd01URXhSVFZDUkVGRVJEQkNRa1V4UmtWR09FWkVJaTgrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrdnI1WElnQUFFLzlKUkVGVWVOcGlERGw2Z1FFUDRBTGlCQ0NlaGtzQkV3N3gvMUNzRGRXOEQwa01CYkJnMFFnQ0FrRDhFVW5jQ1VvL1JsTERpRzRBaWdRT0lJdWs5aThRTTZPN0FKOW1kSFgva2NQZ1B3bWFVUXhoSXRGbWRIQUZaQUEzRUo4aEVCdi9jY2pyZ0F5SUIySmpNbDBBRG9OcERCUUFGaUlDaXFBTFlHQWRpWmIvUjNZQkk1NkF3dXRDOUx4d2dBVGJQZEhEQU9ZS0pTQytoMGR6QUJDN0FQRmViSUhJaUpZdkNBWXNRQUF4RWlnUHdvSDRDeEJ2SlNVYS94TndFU08rQWdVNVN6T2lhY0xxUFNZMHpWWUVFZytHSVN4a1pHZEdwQXdHVHdmcFpKUUZjQmY4SjdNOEFPbjV4MFFndGNHd0U3RkpHUmZZUzJxOUFBTDlCTEwxVFBSQ0ZSMFVZVWtQeUNBTmlFOHdVVkNnZ29BbHNoZnFTQzFNa0wwQWNrVWpPV21CQ1Z0dFE0VHRqTGhpQVNTeEJ5ME5JR010OURBRENDQkM1UUU2K0F6RVBHaGkzNkR0Q0dTd0hJaWppSzFYR0loTXpmK2hsak9pWVc0MGZpY1FSNkxwU3lhM2dZTWM1b3hFSnJrS0xPcm40S3FpbWZCWURET0FpWUV5Z081d2tQbXF1QXBVRUJDbE1ITVI0NUJiUUx3ZHVVQitEY1RuZ2RpSWdmWUF1VlpnaFlXQUNCQjNrOUcwUU1hVHlYRE1MNUFEUXFHY1plUVVSVWdnaDV6bURSTTBIdzhZWUVKcmRGU1JFSS9tQkZJN1NZWDVRaWpkU29MalQ1RllQc0NBQ2JZcU9ZRkEvRklUbkliUzV0aHFvMVFhT3dLNWtEdUZyU1NjUTJRTGwxUWdCeld2SHoyNldBZ1VGdEpBL0FTTC9CMW90ajBHN2ROS1FodjhvS2hrSmFJNEpycVQ5QlJOSXlqRS9nQ3hDcDRtekZtMGhJWVhBQVFRcWUwQmxBWVYxS0x2UUx3ZmlPL1NvcHVJREh5QWVETUo1Y3QvWWhVU0FpZWdobTNHRWEvWTR2Y2ZVaE9Nb2hENGp5Vk55QkRiOXdHQ3E0UTYzTGhDb0FHTDVZeDRMQ2VVNHYrVDRvQWxRRnhQWmhtUDdwQUxoQnlCN2dBeklJNG1Zd1FKRnpERTBlckM2WUNUVkxTY0FVZjNGMjhubTlxVzR4cWdtSW92RGREQ2NuU3pzOUFkOEo4T2xxTTdvaDViZFV3dndBZk42bUFIYUE5QVUvQXpja2w0Z0lMVVRXbmFZV0tDOWdrb3RaemNCa3dmT2YyKzUxU0lnakpZRFl2c0FDNGlOVXZna2ZNaTBvd21tSjNJRHBoSHBPWWxlT1MyRVdrR082eDJSWFpBT0pHYVk2bVlHK1l6UWR0d2xCU3JETkRHS1RtNVlCb0x0RjMzbndxT0lCYnN3MWNiZnFGREllU0l6d0hjZEN3TjVaQWRnQnljTFRTMEZEbXFINk9Id0Njb1hVMm55Z2dqQ3ZpeE5SaG81UHZQdU5JQVJvT0J4aTBqdkMyaUR6VHFsaFBWTDJDRVJra1poUll6QS9GR2ZPVUdDNEdnQXJtOEU0dmNHaURleEFBWmNBUjF4MDJoUmJrNWpvS0hrZHl1R2E3QmloQW9wcmkwWkNJaDRZQndEeEZxclVucFRRRUVFQ1hqQThRQ0RTQXVoUGE0U0NscFFaUGpvTkhYUmJSMEhCT1Z6ZHZPZ0RtRWZKMEJNc1dGN3ZrU3BKamlCZUtYYVBLZ1Nub2hBL2FaSDZQQkVnQUZhQTd6d0tIdUk5U1R5T01wdldpTkFBazArVmw0N0QyTFpPY3ZlZ2VBSHBMbC9UalV2RVB6akFBWkxaMTBORE5XNEZESGl1U2VCN1FNZ01WUVN5NFM0V0JoR21UWFNDVHpGWENva1dmQXYzaUdyQUNvZ3hvWWc2MUZUV1NTcFRaNGlHU3ZINTdhbjJCQWtEcEVDUU84ZEdxOEV3TTJNK0NmWFBnUFRiMXhwS1NBWWh5R3dVSjlzSGdlbC91d2RXVC9FNXNDZGpOQVZpcWhCOVIvaHFFRGNLV0kvNFJhNCt2UlBHL0JRUDVDczhHYUluQ09FQWN5UU5hcGdjQk1xTWFURE1NRFlGczZnUkVBNjVBVVp6QU1Ud0R5MjJ3b3V4czVBSkM3NEVwMGNJZ250TEdFM0lwY1FhZEFTRVZxaXNNREFIa0lnSmJEQVREUGdzWXdCZEhrd3BIazk5QXBNRHhBQVdDSnBRcWtOZ2dqc1NCMXBsSEJxNC9lSVdOaUlHRnVuUUt3a3R3WW9ySTcwTWNUTkVFQjhCMkx3c0JCVW1qZG9ySjVMdGhhZ3Z1d0tGeEZvNFlKcVdNTDk2am9CbE1zWW51WWNGZ0NhaUZ5MGlBUURwQ2cxb3ZLOWgvRkl0YU5iZDBXREx5bFFaSjJST3ZqdTBGN2Mwb001QzFDSTZYd3c3YVk2UXI2eWpsa0FFb0J3VFRPNDd1aHZibjdOTGJuQW83SVFHa0pZdXNZclJrR3JiOVhXTVF1dzdJamNnQ0F0bHhaa1RBbU1CUUFxSE1uaWtWY0QxZHY4RGdEOXRtRm9SZ0lVNUU2ZHpockpHd0RJcWR3RkVSREtSRG1ZbW5TYjhMbUwwSnpVOWRBclNWOEF3cURFT3dDWWxkaTJ5R0VCa1cxY0F3b01BMVN6ejlHODN3ZG9RZ2pkVzRPdWNEVUhXU2VCMFdNREpySG13bHBZaUhSRWxnZ2dQcnVsN0RJZjRQbXRRME1rSzBCMUJ3OEJRM1ArVUlMTmkxcU5ibXBNVGs2ZzRIMGZZWFVCS0IxVDJSUGoxRWpMMmVnTldOcmFPaFpVSXRSR00wK2l1WUdXV2pneUZZRzdKdFJXS0J0ZjJkb1EwUUJxY1BGREMzQWJrSGJJcUNTL0RZOWtnOUFBUEt1TFNTTElBb2ZOYVJBSkJJU0k3c1FXa1NRSlVaSm1kM3dKYXhlSW9nc0VJd3VoRDBJMG9ORzBVTmxSUTlaVVlFUUJSS0lrUkhkeUNMeUlTcVFJZ3NpcU1nS29ZY1NwRkRyOUovaDM2WXp1N1A3ejZ5N2Z4LzhvTE96TzNPK25jdVpNMmZPaHVFZklLT1lmZ1cwUUVIaFB4RUJXSm1oTUNzekxvUXlhbW1NS1BOeER3NmVsMzcvamhpMkNWZ1pBMlRnRzIySHBJSHp2SXZ3cWxOc09VVGFHM3JHZCtvK2tTWmdNVlVXei9oczlNaUw1MERRWFU2Y2htM3d5SS81YnRMek82Tkd3SHlxV0k5R1hyR1Rpd3JMTjBkNkM2V3YwSGpHT2lydlhoUUlHRkVZRzJRMGcvdGV2a0EzNVNza2JkTU5sVVJFM1ZnUXNFZHpZYlNOOGh6dytmd1BORURuYUt4Q3o2YXlVZzB5QytDVWxlK1JaemVZOFhnZHBKZUVVK1pIamJVQXV1UzlzdGtDUmoyRXYwaHYzTFM3Yno4OTEydWpwQTlvejg4R0FXN043QWRWc01heVRuR1R5bm5ra3Vjb3JVK01FdUFtL0ZaSUhzUUlDK2dPTzgzbE91b1FyYWJHQU8yNFBXTmcvTWdndlNPTHViNkRGS2xqcWJTQVVSZFZOU3Ftc1hHMGVPTFE0bVc0Y1NQZ2lpTDlLU1RjNUtLRUtsREh0K2tOUWtBSjhQN3c2UDFmQ3RIRWZsQkh0Qm55UzhBekpnMUQ1cXlIYUFQcnVGWmhOZHF1UzhCRkpxMExOT01GUlFEWHFVdklPS05MZ093VC9BQVN4c2c0QVFkRmJudTl3NHNBMlZuaTNlL2Zjb2duYmpDSzJRWXZBdVRsNkhTSU43QTdOMHBwYlNvQ2prUkl5VEVKUEhaMld0SmNXUUlhMGxCNGdaMjBqaEJZSXhPUTY3aVlCZWtKWEVrS1UvczVtUUJ4T2hGUGZZeEErcUpZSHRzRUFjSTV1Z3orSDh6a1pvRUZJUlhlQVg4N1NtT012WlVodGdDeFd2eERRRzZJckxlUndQSjhqUEU4N29KOUw1UmxqcjgzaWFWa1ZVakNvNk5pdWFiOXdkWXM1SFFNTHhRdElJeW1WNjBwdkpjZElsWElEbURabVV5L0w3WlE4TlVBOTZ5MlVJOTUwdjl6TWlFWm5sMmd3bkNoUWUyRnJTRzB6R2xJd0VTUDlZQUpCU1FJaWtJZ1lFSW1vL2lzTWx4SUhrUURYRnk4REJHeDBZbDh3d1VIOWNBWU5sd1B6cWJ4NTFzSUE1YVpmeHJ3UHRPSHNibDRVZjFJd0F2bXdnekRoZmNFdU1mMDZUWE9zTk9IQkhBZnNxZzFYSGk1ei93SFF4b1hCcENBMjh5Rk9ndUY2ZTVFbzg3UVpManNRdFVGSklBN0h6elpBZ0hEOEcvUVR4bm9QbWZEOU43SXBOM3hlaXRJd2hjTGxSR2FKNTRUd3JDT1E0cFdhQkxjZUhMS3VSem1Cc0lXeTVWQzk3ZHJJUWl2UXFlVEFLNkpiSUgwUUwzYlJVRkFsK0o2ZmhvUWNNSnRuWkVwTlVrWjEyTXVmSTRpZlJkSEFMZXBXQnB6QXJoUW8wTmNGMEM4VkR6a2VJd0pXT1psRlBIYUdrUHNqYW53WnhYcHZXNEVkQ3R1YW80aEFadzJPMWMxQ3pneGhVbmJud1p2L3hQWHpUa0MraFhLeWFHWXYvMENOejFBQnVlYnZ5OG13blBPWFp1OUZDRU8yVXhhZXd3SWtKMjdNUHpmNVNBRS9JVGtoNUVFTmtaY2VNNjVxMFJIRlZZQjR3ZkluNlY2SFZIaHh6UENHZ2xyaTlHRm5aNWpSWmJzQmFuaXExL2hkUWxBMUVqTDQ4OFJFMzRodFFCZnd2c2hBSUV1Tk9zYy8rTVdkeldNN1VueUltcWhUeHpqbHErTlZiK1Zkd1lod0MxdXROK2hxVXZzOCtNZzFPUTE4QVRBSkxKUElPay9IT1hoZUNTOFd5NG9aaTVYQkQwNGlTUThoSVRmdmp6aTRrOTJYTWJ6Z1doOWZrN2EySHRITjhLZHFUeFNWR1pCd2t5R3ovRGpvb2R4UWdMdGI2UnljblFwSkQ3UE1haVJGL05WZ1BtTjE1UGdZZkV4M1FXQWViUFlHaGFGM1BlN3FOejZWQjlrYWdCN1RCWENwdmpPb3VEaU02ZkdmSmROaitBRDFIZXhrcFdnamtLdEMvR0JBZkhwNGNPbUdiVjVldnkrTkJ2TXBrWFdFcHErcGtKeUJ4aTcwbHNpREkvRTNnTHp1OE1zZmduUTNybUdXbEZGY1h4NTZGSmtKSVNhbU1aTkw1bWlmYkNJb3VncTlwS0V5cEl3QTgydWxOME1OQXNxK3hKaG9XQ1o1YU9YVnBiYUE3T1hrZDZNb3FMOEVKUm1ENU1rUDVRYTJBUExNc3pmUFd0M2h0T1ptVDJQTTJmbTNQMkhnOWR6WnZiTTNtdk43TDNXWHV1L0dzRWZVRytRemtNQ1padCtCcXVQbzY5K1R0QkZVNHRVWWlOS09yMytvUzkxTkhtditoQ2c4ZjVPUHpzc1gvcUZ3VEVGdkdkWU40aDFucUJQVkZvUi9jelVKbHFvTGNKNUtFYVhyZ2szUzBKS2s2eFJ5dm45dGFveHZ0K3orRDJvZ3owamdmQVBTWGx2cUw4dXNwZm9kM0hBMmhVSDNKdmFocmxQM2lEenhhNWlwMU1BQlF1SFR6MkR5THc0VjVLSG1XRXFUcFFLOFJCVEFIdGorOVNKY0p0K1ozNm5sTVdYQ2EvSml2QXVOWHBNZjk2VG5JWGpOMW9CbUpOZjlnelFsaFFHNkM5OXVrLzFDQlRpNlBVUjJsaXJGcWs1bjcvVG9CbHVyMUp3ZUZ6NzlEUUZZRFg4aFZSeUpKS1MxdktxblNYbE5DZUVkYXcrM1Qra2VNKzhEYTcxS0FSUDk2UHkvL2pTcU1ETGVFREhZcXNFMHlFVVdnRndVcjJ1SFlYaFkyU0N0dGkwbSs0Unhza3FqQ3pUdlBhcjByVjRGR0pad2piUFZvdmppTDV0ZWpXREFseXZIVG9rdFVOUGJJQ0w5MTYxV0hxcFNiY3laMnNYRk9JV2oxS3kvLzUrZ3ZZbVNhV1EvVlZGVkFERDZ2UmN6UE54VG96U3dlVHRjWDlXanBHVXNFUG5lNk1RU1FKTFRHcmhvaUlvZ0NsRUZ5ZkdlcVBhNFF3WVViVGJtc2pmY3A5SEdlSldMcHF0WTdzNmp3cXdUUHdMOFFVQjErZGdxZFNSK0VXYUh5dWtkcTFOVzB6UnNWNllCd1dZcWpkemM0enpHQUI4NVh1azU4SlVteVZmNE5zWTV6TDIxelJDQVNBMkphQjZWWVJ6V09FTzBnNC9LdzVlNFBBNlhjZm1xWWpuRWdtM1hXSzY5ZU1vQUY0ekNPUk9zenkrUzIzMFZpa3o2RG9FbzBNVklVcW00QWkxbHFiWFd3RkllVnhzZWV3RzdjaEYwdHhVTFBYQ01vbGVZNHUzeDZaNktBQlBMNXN3NTFvY2EraWlyM1F5VEFVYnhZNUMxNEFIanZLZC9kSlNnSGFkbzhLcXpiMGpkblRaRHZGZ0tJUnR3b0VvWDRxTC9LeWtDbkM1aEpjRS9GeVY0MUlubzB4Z0F1SnNQSVNFWW82TnF3Qmp4RDkvRlB3cTVZMGRxZ244NmVTU09WNVZSZWdNT1E1TzBORlJGWUNrL2FCeURjenZiR04rNCtUUWNDeFZSWGdnNEJoMkd0dHNGWUFkcnRkOEdqSUZ5emE0Y2M4ZDdsYlpyUFdSOHh1MkNvQXBVUjFxOVpaWVZxcHphRGdtcTZ5MlZuMC9UR3BRc1ZVckFBc0xMMGtHUVJVRGRESG9VQ3lRclhHS2xPTW5EQ0FNdlRoSUFhcm5FU0poZm5KaldWaFFnNmg2VjNXKzl6OWUvM0dIdmlhOFlGdVdPUHJmbTJoUVdPUGdPaDJxOWpJYktqaE9kcW5DSDI2aXZoSk1XODJYU3VRUllYaXZWQ3RBTFhPQ3NHa0NJajhwOENCQWp2dTRDandLaUZ0a2wvT2pBdmVkb0pwYTlOQ2RSZ0hNRkVDNmtsOVNheEhyU0pEa1lhSnZ1MklJM3d6ZWgxSUo1eTRpdC83NVB0K1BWVlAvUHdVSTh1SmRVTEJPODdTVHZwVm0vSDI3VGcwTEN6WVc0MEw2MUswQUpDb0crWXo1N2JpQ2RCalRaMFlkMjU4cjRhN3h2S0NmenZkQlZrSi9GSUJFeXVFQkJ3NE1hU2d2V0pmUmZiWkw5S0NOUm9DZDI2QzZkOGg4bUNsWjJqZWtzZkU1N3l5dit5eFpqS2JGWEZka2lUQWFmT1Erb0tTV1FOZ0NaMExPT3pzcTQrdVZhcGpNZVVPWTg2NDdNTFdrd2cvYkZqNVQ4czBmK25NRHJ2bDNqc2NEcXRDd1VpamQrWWtJSGhLRUF4YU5YcDNqRHJQUmtXVjBNYnVnbTNJOEhqYlRJUkZlQjFFQS9QMDJ4RGFUY3R4aHNvWm1abmk5amh5UFJZdmx3MHFVMTI0VWdJaWV6eXhPYU12NVdvQzN3R1VaWElkU0dCL2tlQnltaUE4N2JCWFlJK2l1SDhLcm9NdXk4WnR5dnZBeGNYUHYxcUh0OWRyMnh6a2ZnMDdMNHdnMlBWenlETncraTVNbVNQcFZ0dXFCY1Nxc2gxTm95K1QxVFN4QXZ5ZFora0tZOGplTFovWFBidDlheTR2Y0k4WEJiS25rNGVFWGg1RmpkOGk4U083ZU9aSk9abS9Xc0MwODlJSmFBZUtsaWNNanVNT3lBUXB4cmhPSFBBRTYzd1VXeDVHa2d4UHJlNm15LzJIdWVNenlZcnhhajNkam5odTBIdjA4YUhuc0FpUDhhZ1VBc0ZyWlZNMGlUT3hwTis2NXdXcXhTL0poaXB2bi9hTDZwTi9Fdm9JZ3BFbXozTmczSEl2RmY5Ky9sdi9pbnlBRk1QYTBiWldVUjZSMmtSR0hiSENEbExPMWJUQ3ZsbmxjQ2poNFRRVGJlNWlUUmVZWUUyRWFYdUgzVUFmTkc5ZXBjRzBBRStkQUo1UE1RTER1RnN0aklabnlaWEFKV3pqZ1dyVXBvOWhibGFDUGswM2RRWkN1YlgxdStBWUQ5d1ZzVm81NC81Nnd0QXpZSlR2UnlhaXU1cDZ0OEIrUzJnWFVJeXNBZ1BiTnhzZE1HRG1ldHBPY3JGTEhHV3JHMlpRR21uYjBNOGVtMFNnVU1lU1ZFV1FRUnFzTzF4OFpLWU9jekZJREtmZzJYbHBvOXVBYmZzYTI0YWdjUVZDWkVTRWN4dklGWVROeEJpT2M3QktEc0h5YnNpNHI5T0dMUkpJZGx5WnVxbXBsR0gzcmRqVlhIT0lCSG9hdzJBT2NkME1sSmdOcEVxSklBa2tJS0wwajVEak1sY2xPbHBGQjdFVllqWU9adXVqZUZmY2lhVkRGVWxXVGJkT2dqU1MySCs5ME1yVUdNUWpMQTM1ZnBHTytQT21GMGlTTHZsVnZhcW5QNzlSOFcrSmtHNG9ucFV5UEh5VDQyOU82V0QzbzRqdjFKdWY0S01sNkoyTmZRTDF6bzg5MGtLcmdEYktvRzBqdTRVWUp6cVRab3d2R2Jmcmg3NitsekVUV0RNQXZNbHl0SWo0ajlkK0JJUXZvUzlTa3JodXlMaHhKalp4Vmtxd2NDcG0vTzZWY3IyK25Mb0IycS9telIrcFBPWSt6QzRwNzZGZmdTeVphZW9qK1BVUk40TGlnNEJXVSt5OWxKWkJHVmc1RkdlREQ3ZW1SUmJ6bHlHaCtzUkVYYjJUWk9KeEp2ZlZ0d0hieTJ6MUk2TkR3dFdyZit6UksrSTFXQUMvWVJCb3ZsVWhjNXN2blJTTlhDdzZjWlN0MUxXVDZkNFVFUnlmM09BV294bGM2RjVZOGczYWhsTjJkZTNNczdMMDZyWjNudVcrY1pkTjF2Wkk3TkVQMWNMYWhpWW1ERUdHMHJyRDcxMUhBV0Nrd2tjQkJCSUhVajBVZXZGNUhqalREVzlZaEx2NEZNRmJCN28vL0pJVUFBQUFBU1VWT1JLNUNZSUkifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0xMi0xMCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSGlkZWV6IEtleSA0IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAyMTA0MDkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTEyLTEwIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0wOS0xMyJ9LHsiYWFndWlkIjoiYWViNjU2OWMtZjhmYi00OTUwLWFjNjAtMjRjYTJiYmUyZTUyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJhZWI2NTY5Yy1mOGZiLTQ5NTAtYWM2MC0yNGNhMmJiZTJlNTIiLCJkZXNjcmlwdGlvbiI6IkhJRCBDcmVzY2VuZG8gQzIzMDAiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRENUQ0NBcStnQXdJQkFnSVFRQUZxVU5TZTVTV0FJTHM4SDJEUzFEQUtCZ2dxaGtqT1BRUURBakJyTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNoTUtTRWxFSUVkc2IySmhiREVpTUNBR0ExVUVDeE1aUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVqTUNFR0ExVUVBeE1hUmtsRVR5QkJkSFJsYzNSaGRHbHZiaUJTYjI5MElFTkJJREV3SGhjTk1Ua3dOREkwTVRrek1URXlXaGNOTkRRd05ESTNNVGt6TVRFeVdqQm1NUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ2hNS1NFbEVJRWRzYjJKaGJERWlNQ0FHQTFVRUN4TVpRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWVNQndHQTFVRUF4TVZSa2xFVHlCQmRIUmxjM1JoZEdsdmJpQkRRU0F4TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFR2hTTUw3Y3VwQ3hUQkN6c3JjaXB3Z1BvejNkdlQzckJuMXpha0R6Qmc2VWMzSGRHS0pyVmJyRCt5WEY2WTRacWtzVVU3cmJSaXZxT096S3hjSnZQRnFPQ0FUZ3dnZ0UwTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0RnWURWUjBQQVFIL0JBUURBZ0dHTUlHRUJnZ3JCZ0VGQlFjQkFRUjRNSFl3TGdZSUt3WUJCUVVITUFHR0ltaDBkSEE2THk5b2FXUXVabWxrYnk1dlkzTndMbWxrWlc1MGNuVnpkQzVqYjIwd1JBWUlLd1lCQlFVSE1BS0dPR2gwZEhBNkx5OTJZV3hwWkdGMGFXOXVMbWxrWlc1MGNuVnpkQzVqYjIwdmNtOXZkSE12U0VsRVJrbEVUMUp2YjNSallURXVjRGRqTUI4R0ExVWRJd1FZTUJhQUZCMm0zaXdXU1lIdldUSGJKaUhBeUtEcCtDU2pNRWNHQTFVZEh3UkFNRDR3UEtBNm9EaUdObWgwZEhBNkx5OTJZV3hwWkdGMGFXOXVMbWxrWlc1MGNuVnpkQzVqYjIwdlkzSnNMMGhKUkVaSlJFOVNiMjkwWTJFeExtTnliREFkQmdOVkhRNEVGZ1FVMzhiUUFOVzlkeVZCa1dsNTlCbE5MRDA5ZS9Rd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFJVXE3enZwZWRmWlJIdEdydkpKejgyUjk5RCtTcjdiVjd5ckhEZkJzOHY2QWlCYUlXNTBqOFdHVlIxWEhYYUltTktsbG1SeU5sazlrbFg4Z1Rrbk9FdEQ4Zz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVZNQUFBQ3NDQVlBQUFERytFOE1BQUFBSUdOSVVrMEFBSG9sQUFDQWd3QUErZjhBQUlEcEFBQjFNQUFBNm1BQUFEcVlBQUFYYjVKZnhVWUFBQUFKY0VoWmN3QUFEMkFBQUE5Z0FYcDRSWTBBQUF5Z1NVUkJWSGhlN1oxL2JKVGxIY0J2amhqTmNDNE8rZFhlWFZ0VVRNemlQN29ZWFpZNTFJa0tkMWZObkZIajVvaEJtQTdqMk1Sc1pvbG14aGhOSm9ydDI0S2dzaUZzaW03VEFkTVlSRlFFRlRjVnh3L3J3QUVGUkNoUSt1dWVQYy8xcVFQM1ROcyszM3ZldSt2bmszelM0MmdmbnZlOXQ1OCs3NzNYSXdFQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBVUVwa0c2L1hQcG5JUlI4Z0loNXQ0MXI5Y1lhdEJmd1A5UTNuNngyMFRadFAxRGNwUk1UUE5kZVUxNHV1VnQyTXEyMUZCa3h0TWptckxwVnEwUjgzMTFaWDMycnZMbU1LUDIzMGpxbVAzRHNORWZIenpFVzdFeGZPR1dtTDhvV2trOGtmMXFYU1BYWFZxYVhKVWFQT3FLbXFPck11bWZwcmJUTFZuVXFsTHJlZlZrWk1tUDExL1pPbHc3bHpFQkVIb2ptcnpVWlRiVjMrTDNWangwNHdJUjA5ZXZUSjQxS3BLZG9iakNOSGpodzFkdXpZNUxoMGpkS3IxTFB0cDVjQkpxU3NSaEZSMHQ2Z3pyU1ZjWEdNRHFtcVNTWXordll3RTg2YXF0UzF0ZFhwNjgzdHVqRmpValZqazVQMUtyVzk5OVBMZ1Z6VTVkd1ppSWcrbXFCZU9xZk9sdVlvMHVuMGNUcW1YZmFQdzh3SzFkNU82RlA4dDJyVDZWdjB6Uytic1BiZVcrcmtvbytjT3dFUlVjSmNkTURXNWlpcXE2dVBINWVxNlZ0MUZsYW1PcUk3NjFJMTIwOUoxL1JGOWt2bEVkUDZobTg3Tng0UlVkSnN3ejIyT3A5aVlxcFhvNTMyajJabG1qL3BwSk8rcWo5MnA4ZU1PZDNlZjB4NXhEVFh0TSs1NFlpSWt1YWlEbHVkSStrOWhVOG5qdE8zQ3pFMWQ0NFlNV0tNdm4zUTNCNCtldmpKK25iZktyV0U0WFdraUJqS3k1dlBzdVg1bExwVWFtWnRNcjNmM0s2dFRyNVR1Rk5UbDB3K1dwTkszYXovcnFPMk9qM04zbDJpVEk2bU9qY1lFYkVZNXBxZXRmVTVpcnJxMURPMXlkU0JjVldwRyt4ZGlicXE1QXl6T3RYM0w3UjNsVEQxMFhMbkJpTWlGc05jVStIVTNVVnlWUElNSGRXVnA5WFdxVk5yYXZQNjl2S3FFVlduMnI4dWNlcWovYzROUmtRc2hybW9qRjR2T2hDSUtTS0cxSDBScWdJZ3BvZ1lVbUtLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUVM5N1dDVXVlRUFsTHB3ZFZ2TnY1aUwzbkFicjl4NTAvMXZGOWlLdGF6NERNYTdId0R6K3J2bjB4NngrL09LWWR6RTAyM0dSUG43TU1YU3AzaWVURzkzYlhHa1NVemx2bnZ1eWlvdmpycHpubk5PZzFBZi91czI3N01oaDJmbkpvZDV2UU5lOCtxUCtKbzZMYWRFcTk1ejY0ZGV1WFdCSHFRdzZ1M3RVVzN1bjJyeGpuMXE5WWFkYXNucXp1cW41WlhYeU5RdFU0dUtIVkNKVGdZRWxwbkthYjZhNHFKU1lmclRuUU5uRzlJYUhYM0xQcVIrZXFDTXpWTml6LzdCYThkWldkZVY5ejZ2RUJMMktyWlN3RWxNNWlhay94SFJvMGRuVm81NWQ5NkVhZitNaXY2ZEpTa0ZpS2ljeDlZZVlEbDNlYnRtanpwdTExTy94ajFOaUtpY3g5WWVZd2h0YmRxbFRwdXFWcXJrbzU5aFhKU3N4bFpPWStrTk13elByc1RYcXpzVnZxTHVXdktFeWR5OVR1WHVXcTE4dWZMMXczNzFMMTZzVjY3Y1ZMaWFGcENlZlY0KysrRStWdUdDMmMzK1ZwTVJVVG1McUR6RU5UMkxDYi9VcXNGRWxNZzMvblpPNUtGUzRUenRKUHg2WHpsRlZVeGFxS1hOV3FvL2JEdHV2TEQ2NzI5clZOMzY2eElUcXFQMVZraEpUT1ltcFA4UTBQSVhYaGpybTVGUkg3WmpKRGVxTzM2KzFYMTE4dW50NjFDMlByTmJINVJHeEwwV0pxWnpFMUI5aUdwNEJ4YlJQSGJaSmR5K3pJNFJoL2d2dkYxYkl6dm1VZ3NSVVRtTHFEekVOejZCaWFzdzBxaC9yMC82UVBQbnFCMzdIUnpFbHBuSVNVMytJYVhnR0hWTmpObEovLzNDUEhTa01UNy9XVXBwQkphWnlFbE4vaUdsNHZHS3FIZitUeFhha2NQenhGYjFDTGJYblVJbXBuTVRVSDJJYUh0K1ltcWk5dDIydkhTMGNQMXZ3cW5zK2NVbE01U1NtL2hEVDhIakhOQmVwODI1LzJvNFdqbncrcjhaUFgreWVVeHdTVXptSnFUL0VORHplTWRWKzVhcEg3R2hoMlhld1EyVCtJaEpUT1ltcFA4UTBQQ0l4bW1STzlUK3hJNGJsbVRVdGhkV3hjMTRoSmFaeUVsTi9pR2w0UkdLYWpkUXQ4MTZ4STRabitGV0N4LzlnSmFaeUVsTi9pR2w0cEU2VHo1eXh4STRZbnZjLzJ0djc2NitPZVFXVG1NcEpUUDBocHVHUml1bm82eCszSThiRGlPc2VkYzRybU1SVVRtTHFEekVOajFSTWgxM1JiRWVNQjNQTXh2cmNLVEdWazVqNlEwekRJeFZUY3hHcXE3dmJqaHFlcnU0ZXVXMFpqTVJVVG1McUR6RU5qMWlBOUhHemRsT3JIVFVlYnAwZjR3djVpYW1jeE5RZllob2VzWmhtR3RYQ2xSdnRxUEd3YmJjK2Z1SjZoMzVpS2ljeDlZZVloa2NzcGpwaXR6MjJ4bzRhRCswZFhTb3hNYWEzNlNPbWNoSlRmNGhwZUNSakd1ZHJUZnVJN2FvK01aVXp6cGgrNTFkL1V1Zk9lbHJFYi83OEtiVWhoamV1TUJEVDhJakZOS2JmMGY4c3R6Mit4ajIvWWt0TTVZd3pwcFVDTVEyUFdFeTE1OXkyMUk0YUg2dmUzZTZjVzlFbHBuSVNVMytJYVhncUxhWmI0N29JUlV6bEpLYitFTlB3VkZwTXQrODkyUHUvcWpybVYxU0pxWnpFMUI5aUdwNUtpK211ZmUwcWxuZmhKNlp5RWxOL2lHbDRLaTJtaGZjNHZjempHQnFzeEZST1l1b1BNUTFQeFozbWY4eHB2aXpFdEN3aHB1R3B0Smp1Mkh1SW1JcENUTXNTWWhxZVNvdnBCenYzbTdBNTUxZFVpYW1jY2NiVXZNSEU2MEt1MmJoVEhXanZzaU9IaFppR3A5Sml1bVQxWnVmY2lpNHhsVFBPbUI1cmZoS2JKOTBsdlBnaDlmckdlTjc5aDVpR1J5eW1KZkliVVBYM0xIZlByOWdTVXpuampDbS9tMjhscGdOR0xLWWw4cnY1c1p6aUc0bXBuTVRVSDJJYUhzbVlUby81dXNIK1E1MjlaMWV1K1JWYllpb25NZldIbUlaSExLYVpSclhvcFUxMjFIaFkzN0tibGFrNHhIVHdFdE5CUVV3YjFZcjEyK3lvOFhEMnpLWHV1WVdRbU1wSlRQMGhwdUVSaStua0J0WDZ5U0U3YW5qYTJ2VXAvaVV4dlRHMGtaaktTVXo5SWFiaGtYek9ORTZlV0xYSlBhOVFFbE01aWFrL3hEUThVakU5OFpyNWRzVHc5UFRrNDNuYnZTTWxwbklTVTMrSWFYaWtZbnJxOUNmc2lPSDV5N3AvbVpnNTV4Vk1ZaW9uTWZXSG1JWkhKS1k2WkpmYytad2RNU3lITzd2MU1SUGpjNlY5RWxNNWlhay94RFE4SWpITk5Lb2xxN2ZZRWNNeXJYR1ZlMDZoSmFaeUVsTi9pR2w0UkdJYTA4V25UZHYzeGZjaS9jOUtUT1VrcHY0UTAvQkl4SFQ4dEVWMnRIQzBkK2pUZTMyc3V1WVRpOFJVVG1McUR6RU5qM2RNOVNuKzNPYzMyTkhDWUs3ZW56WHpTZmQ4NHBLWXlrbE0vU0dtNGZHTjZmQWZ6TE1qaFdQR3ZKZWRjNGxWWWlvbk1mV0htSWJISzZhVEc5VGN2NFZkbGQ2K2NJMEpsM3MrY1VwTTVTU20vaERUOEF3NnB0bEluWC9Ibiswb1liaXBlVlU4L3lWSmZ5U21jaEpUZjRocGVBWVYwMHlET3ZmMlord0l4YWU3SjY5K05QdkYwbHlSOWtsTTVTU20vaERUOFBRN3BpWmsrclRlSEd2M1ByWGVmblh4T2RqZXFjWk5YZVNlVXlsSlRPVWtwdjRRMC9Ba3ZuVi83N3N0ZmRhSkQ2bGhWelNyRTYrZXIwNi9hYkhLM0wxYy9TSHdDL09YdmJtMU1BL1hQaXM1aWFtY3hOUWZZZ3FHZzRjNzFWWDNQMTlZQ2J2MlYwbEtUT1VrcHY0UTA2Rk5SMWUzZW5qWnV5cngzUWVjKzZta0phWnlFbE4vaU9uUXBMMnpTeld0Mk5CN1NsL0tGNWsrVDJJcUp6SDFoNWdPSGZMNXZIcTdaWSthTW1lbFNseWdWNkxsR3RFK2lhbWN4TlFmWWxyWmZOeDJXSzE2YjRlNjBielRVN1pSSlNaNVBOYWxKakdWYzlKdmxxbmxiMjR0WElFTTZjcDMvcTJPL2Y1YzU1d0daYVpSUGZqc1A1ei9Wckg5M2NxTitodk00NkxEeERucXBYZTNPOGN1cGl2ZTJxWXV1ZXM1OTV6NjRRbFh6MWU3OTdlcmx0YTJpdkROTGJ2VjJrMnRoWDN6NnlmV3FvbDNQcWRPTUQvd0w5YW44ZnFIdFdzZmxMM0VGTEVFTktlNDV1VklabFZlN3BydE1GZmh5K2xLdklURUZCRlJRR0tLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUkVRQkt6YW11YWpWdWNHSWlNWHhvSzFQaFpGdGFISnNMQ0ppY2N4RnUyeDlLb3dybXNjN054Z1JzUmhtb2wvWStsUWc1amtNMTBZaklrcWFpL0syT2hWS3J1a0Y1NFlqSWtxYWkzYlk2bFF3dWFqYnVmR0lpQkxtdE9mY2Q3d3RUZ1dUaTZZN2R3QWlvb1M1YUptdHpSQ2dQbnJOdVJNUUVYM01ScTIyTWtPSWJPTkc1ODVBUkJ5TXVhWUtmU2xVZjhoRmkvUU95T3VWcW52bklDSitrZWJLZlgzVFdsdVZJVXcyT2sydlVsdUpLaUlPMkZ5ME41RnR1czdXQkFxWXFOWkg2L1RIZlRxc25ZbjZacjJ6RUJHUDBLeENzMUdiYnNTV1JLWmhncTBIQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRUJwa1VqOEI0QW9tK01iVCszSkFBQUFBRWxGVGtTdVFtQ0MiLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImFlYjY1NjljZjhmYjQ5NTBhYzYwMjRjYTJiYmUyZTUyIiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlfSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wOS0yNyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSElEIENyZXNjZW5kbyBDMjMwMCIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwODIxMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA5LTI3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wOS0yNyJ9LHsiYWFndWlkIjoiODdkYmM1YTEtNGM5NC00ZGM4LThhNDctOTdkODAwZmQxZjNjIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI4N2RiYzVhMS00Yzk0LTRkYzgtOGE0Ny05N2Q4MDBmZDFmM2MiLCJkZXNjcmlwdGlvbiI6ImVXQk0gZUZBMzIwIEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfZGVyIl0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjI1NiwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNwVENDQWtxZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd0hoY05NVGd3TnpBeU1EVXpNVE01V2hjTk1qTXdOekF4TURVek1UTTVXakNCcnpFTE1Ba0dBMVVFQmhNQ1MxSXhFVEFQQmdOVkJBZ01DRk5sYjNWc0xWTnBNUk13RVFZRFZRUUhEQXBIWVc1bmJtRnRMVWQxTVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUWlZkQ1RTQkRRU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUUlmcUhpc2kwb08vZXlPcVNhRHJyOWl0RzJJeW1Ca0huU0RHUUlJWW1UK3ZxQThBZ084MW1vbWMyTGQ1UEdwRU42bXVFNTR3UEhRanZjL3lDaWg4dTJvMVV3VXpBU0JnTlZIUk1CQWY4RUNEQUdBUUgvQWdFQU1CMEdBMVVkRGdRV0JCUzNKL2Z4aUF2MjJpcmRCczk4U09EaEY3a1UvakFMQmdOVkhROEVCQU1DQVFZd0VRWUpZSVpJQVliNFFnRUJCQVFEQWdBSE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRGM0MUxGSzRMSkNCVTJWVktJejdaNnN4UGhVRWtoOG5MU0xLNklYZGtQNXdJaEFJZUtWT1pjaGFWTzVhRjdmYmRYb1NyY3l5MVlZZVVlUExvamNLSTlmWDg0IiwiTUlJQ2dqQ0NBaWlnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQm5URUxNQWtHQTFVRUJoTUNTMUl4RGpBTUJnTlZCQWdNQlZObGIzVnNNUkF3RGdZRFZRUUhEQWRIWVc1bmJtRnRNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRVpNQmNHQTFVRUN3d1FRMlZ5ZEdsbWFXTmhkR1VnVlc1cGRERVpNQmNHQTFVRUF3d1FaVmRDVFNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SUJjTk1qTXdOekV4TURNME5qRTBXaGdQTWpBM016QTJNamd3TXpRMk1UUmFNSUdkTVFzd0NRWURWUVFHRXdKTFVqRU9NQXdHQTFVRUNBd0ZVMlZ2ZFd3eEVEQU9CZ05WQkFjTUIwZGhibWR1WVcweEZ6QVZCZ05WQkFvTURtVlhRazBnUTI4dUxDQk1kR1F1TVJrd0Z3WURWUVFMREJCRFpYSjBhV1pwWTJGMFpTQlZibWwwTVJrd0Z3WURWUVFEREJCbFYwSk5JRU5sY25ScFptbGpZWFJsTVIwd0d3WUpLb1pJaHZjTkFRa0JGZzVwYm1adlFHVXRkMkp0TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBaCtvZUt5TFNnNzk3STZwSm9PdXYySzBiWWpLWUdRZWRJTVpBZ2hpWlA2K29Ed0NBN3pXYWlaell0M2s4YWtRM3FhNFRuakE4ZENPOXovSUtLSHk3YWpWVEJUTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZMY245L0dJQy9iYUt0MEd6M3hJNE9FWHVSVCtNQXNHQTFVZER3UUVBd0lCQmpBUkJnbGdoa2dCaHZoQ0FRRUVCQU1DQUFjd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFOVm5KZGUvL3RCTHE4TUREaStTQWQ2VWRZSVpTbmc0UE1xbXlOcnZaajY0QWlBWDB4U3pBaEZhQ0NwL3VocFZnbmxGK1hCZ3J3QUlzb3RaR1RCNnJrQjMxQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQStnQUFBRXhDQVlBQUFEdkRZZ3FBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFGaWNTVVJCVkhoZTdkMEhlQlhGMnNEeE43M1FDVFZBNkZJRkZLa0NVdXlBRXVtS1lrRlViSUNDSWlLQ1VnUUU3TDBnZGxRc0tDcFNySWdnU0MraEpuUkNKNEgwYjJmdmVELzBraENTbmMyZWsvL3Z1WG1ZZDQ2WGtKTno5c3k3TS9OT1FKWkZBQUFBQUFCQWdRclVmd0lBQUFBQWdBSkVnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUVCQWxrVzNQU3N6TlZYU0R5VEtxYTFiNWRTYWRaSzZlNCtrSHo5bTk0bjMvL21BY1FFaG9SSmN1cFFFUjBWSldKVktFdDZndm9SWHJ5WkJwVXBKUUNEMzRRQUFBQUJmNE5rRVBTc2pRMDV0M2lLSFB2cEVqdit3UU5MMzdaT3MxRFQ5S0lDekNZeU1sTkFhMWFURU5aMmxaSmZPRWxxaHZQV09EOUNQQWdBQUFQQWF6eVhvS2pFL012YzdTWHh6aHB4YXNWTDNBc2lQZ05BUUtkcXh2WlM5WTRBVWFkSlk5d0lBQUFEd0VrOGw2TWQvKzEzMmpIdEtVdGF0MXowQW5GYTg2OVZTWWRnUUNhdFNSZmNBQUFBQThBSlBKT2daSjA3SW5vbFQ1UEFISDR0a1p1cGVBS1lFaElkTGhWRWpKS3BYZHdrSUR0YTlBQUFBQUFwU2dTZm9wN1pzbFIwREIwbnExdTI2QjRBckFnS2syQldYU3BYSkV5U29hRkhkQ1FBQUFLQ2dGR2lDZnVMUDVSSS9ZSkJrSERtaWV3QzRMYnhSUTZuMjVpc1NFaFdsZXdBQUFBQVVoQUpMMEU4c1hTWTdicmxETXBPU2RBK0FnaEphcTRiVS9PaGRDUzVkV3ZjQUFBQUFjRnVCSEpDc2xyWEgzM2t2eVRuZ0VhbWJ0OHIyZ1lNa2cvY2tBQUFBVUdCY1Q5RFRqeDZUN2JmZElSbUhEdXNlQUY1dzhzKy9aT2NqajBrV2hSb0JBQUNBQXVIcUVuZDF4bm44QXcvSnNTL202SjV6RnhnWklVR2xTa2xJamVvU1ZLSzQ3Z1VLT2V0dG5MNXZ2NlR0aUplTUkwY2xLeTFOUDNEdUtrNFlLMlg2OU5JUkFBQUFBTGU0bXFBZlhiaklMZ3AzemtlcEJRWksrUGtOSktwL1B5bld1cVVFbHlrakFVRkIra0VBZjh0TVRaWFVYYnZrNkxmejVORE05eVY5ejE3OVNPNEZsaXdoNS8zd0RVWGpBQUFBQUplNWxxQm5KQ1ZMM0ZYWFNGckNUdDJUTzZFMXEwdkZVU09rZU5zMmRxSU9JSGN5VDU2VWd4OThMUHVmZVY0eWp4M1h2YmxUb2x0WGlaazZ5YnBDQk9nZUFBQUFBS2E1bHZFZW1mUDF1U1huVm1KUW9tZXMxSjR6VzRwZjBvN2tIRGhIZ1JFUlV2YlcvbExMZWcrcG85VE94YkZ2djVkVDhRazZBZ0FBQU9BR1Y3SmV0ZXgyLy9NdjZTZ1hyR1E4YXRCQWlYbHF2QVNHaCt0T0FIa1JWcVd5ZllSYTVNVXRkYy9aWloxS2tmM1B2cUFqQUFBQUFHNXdKVUUvc1hpSnBPL2FvNk96Q0FpUTBqZjNrK2loOTdPOEZuQ0l1dEZWN2RVWHoya20vY1NDUlpKKzVLaU9BQUFBQUpqbXloNTBWYm45NkdkZjZDaG5Lb0dvK2ZIN0VoZ1dxbnZ5eWZyeHN0TFRKZjNFQ2NrNGZseXlVdk5lM1Jwd2l6cXRJTGhZTVh1WnVsMFEwYUdiVmFlMjc1RE5WMTRqV1NrcHVpZG5sWjZaSXFXdjZhSWpBQUFBQUNZWlQ5QlZjcnl1ZVJ2SlBIeEU5K1FnT0ZpcXozcFBpalpwckR2eUxubmRlamsyZjZFay9icFlVclpzbFl6RWcvb1J3SGNFeDFTUmlOcTFwR2lIZGxLc1kzc0pxMWhSUDVKMysxNTZWZlpQbXFxam5CVzlyS05VZi9WRkhRRUFBQUF3eVhpQ25yeG1yV3pwMmwxSE9TdmE4UktwL3ZyTGVaNHR6RHlWSWtlKy9VNFNYM3RUVXRadDBMMkFud2dNbEtLZDJrdVpXL3RMc1JiTjgvdytTVDk2VkRaMXZGSXlEaDNXUGRrTEtsNWM2djd4c3dTR2hla2VBQUFBQUtZWTM0T2UvTmRLM1RxNzBuMTY1UzNweU1xUzQ0dC9sN2pPM1dUWGtPRWs1L0JQbVpseVl0NEMyWDdETGJKdDRDQkp5V09WOWVBU0phVEV0VjExbEROMVZGdnF6bDA2QWdBQUFHQ1M4UVQ5NVByY0pjc0JrUkZTN0pLMk9zbzlWU0YrOThUSnN1T21BWks2ZFp2dUJmeVlTdFIvV0NpYnUxNG5oK2Q4WThmbnFrU1hxM1FyWjFscGFaTEMrd29BQUFCd2hka0VQU3RMMHJadTEwSE93aHZVbDhEUWN5c01wNHErYmIvakhqbjQ2cHYyWG5lZ01NazhkbHgyRGg0bWU2WStZNy9YemtWRXpSb1NXTFNvam5LV3NpZVhKekFBQUFBQXlCZWpDYnJhM3A2Um5LeWpuS216bXMrRlNzNjMzVHBRa2hiOXBIdUFRaWdqUXhKZmVNVmVSWEl1U1hwQVJJUUVsNDNTVWM3U2Q1T2dBd0FBQUc0d080T2VtU21adVR6T0thaENlZDA2TzdYc05uN1lDRG01YklYdUFRbzN0WXJrd0ZzemRIUjI2dWkyZ05EY0ZYN0wyTGRmdHdBQUFBQ1laSHdQdWduN1gzdFRUbnozZzQ0QUtQc21UWk9rRlgvcENBQUFBSUN2TVhyTW10b1h2cWxMcktSdWpOTTkyWXNhTkZDaWh3M1ZVZlpPYm9xVExWMnVzMmZSY3kwdzBONXZHMXdtU2dLalN1bE93S09zZDJUR3psMlNjZUtFWko1STBwMjVFMXFyaHRUKzhsTUpqSWpRUFdlV2xaRWhjWjFqSldYakp0MlR2WkxkdWtxVmFaTjFCQUFBQU1BVTMwclFyWC9xdHR2dWtCTUxjN252M0Q0M3VvT1VIWEN6aE5lcks4SEZpdWtIQUkvTHpKUzB3NGZseE85L3lJSG5YN0lTYWVzOWxKdTNha0NBbEI4eFRNcmRmcXZ1T0RNU2RBQUFBTUI3ZkdxSmU5S3ExYmxPemtOaXFrajFqMlpLOVZkZmtLTE5tNUdjdzdjRUJrcElWSlNVNm55VjFKNHpXeW8rT1ZvQ3dzUDFnem13a3ZqRWwxK1RqS1J6bTNrSEFBQUFVUEI4SjBHM0VvOERyNzZoZzV5Rm45OUFhczcrU0lwZTFGVDNBTDVMRlhRcmMzMGYrNFpUVU1rU3VqZDdHWWNPeXhGMVBqb0FBQUFBbitJekNYcjZrYU9TOU10dk9zcGVjTVh5VXUzMWx5V2tkR25kQS9pSElvM09sOHJQVGJWZTVFRzZKM3RIUHZ0Q3R3QUFBQUQ0Q3A5SjBKTldycExNWThkMWxJM0FRS2s0ZHJTRWxDdXJPd0QvVXJ6TnhWTHFoajQ2eWw3eW55c2s0L2dKSFFFQUFBRHdCYjZUb1AvMnUyNWxMN3hlSFNuUjRSSWRBZjZwN0lCYkpTQTRXRWZaeU1pUXBKVXJkUUFBQUFEQUYvaE1ncDY4YnAxdVphOUVsNnZ0L2JxQVB3dXJYRWtpV2pYWFVmWk9yVjZyV3dBQUFBQjhnVThrNkZrWm1aSzJhYk9Pc2xmc3NrNjZCZmkzWW0zYjZGYjJVdmZ2MXkwQUFBQUF2c0JIRXZSME8way9tN0FLRlhRTDhHK2gxYXZwVnZZeVQzRFVHZ0FBQU9CTGZHYUplNjRFNkQ4QmY4ZHJIUUFBQVBBNy9wV2dBd0FBQUFEZ28walFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUENNaXk2TGJqc3RMVFpWT1hXRW5kR0tkN3NoYzFhS0JFRHh1cW8zL0tURTJWRGEzYVM4YWhRN3JuekJxc1hTNkJrWkU2TWljMVBrRk9yZCtnSS9pejBKZ1lDYTlYUjBmZWNXVCtBa2tZTUVoSFoxYWlSNnpFVEo2Z28zL0t5c2lRdU02eGtySnhrKzdKWHNsdVhhWEt0TWs2QWdBQUFHQUtDWG9lSEp6NXZ1eCtiS3lPNE0raSt2ZVQ2TWNmMVpGM2tLQURBQUFBL29jbDdnQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCd1JrV1hUYmNWbnA2YktwUzZ5a2JvelRQZG1MR2pSUW9vY04xZEUvWmFhbXlvWlc3U1hqMENIZGMyWU4xaTZYd01oSUhabHpjdlVhT2Y3anp6cnl2dVEvVjhqeFJUL3B5Rm5sQjk4ckV1Uy85M2tpR3AwdnhkcTEwWkYzSEptL1FCSUdETkxSbVpYb0VTc3hreWZvNkoreU1qSWtybk9zcEd6Y3BIdXlWN0piVjZreWJiS09BQUFBQUpoQ2dsNElKTDQ1US9ZOGNlWkVMYjhheHEyUmdPQmdIY0V0L3B5Z1o2V2xTVmFtc2N0UzRSTWdFaGdTWXYxcE5RQUEvME9OTThXRmo1MkE0Q0FKQ0FyU1VjRno5Zk9XenlJZzEwalFDd0VTZFAvanp3bjZ0cUhENU5TS2xUcENmZ1dWS0M2MVBuNWZBa05EZFE4QTRIUngzZnRJK2xuR21FNG9QL3dCS1gzVkZUb3FXQmxKU2JMbHhsc2s0L0FSM1dOV1pJdG1FalArQ1FrSVpIY3RjRFlrNklVQUNici84ZWNFUGE3ZnpYSnk4UklkSWI5Q2ExU1h1dk8rMFJFQTROL1d0V3duNlFjTzZNaWM2RW5qcFV6M1dCMFZvTXhNMlQ1MG1Cejd5cDNQaHVBSzVhWDI3SThscEZ3NTNRTWdKOXpHQWdBL0ZsYXJwbTRCQUNDUytORXMxNUx6Z0xBd3FUSjFFc2s1Y0E1STBBSEFqNFdXTDY5YkFJRENMbm5kZXRrejdpa2RtVmR1eUwxU3JFVnpIUUhJRFJKMEFQQmpZWTBhNmhZQW9ERExPSDVjNGdjL0tGa25UK29lczRwZGNabVV1KzBXSFFISUxSSjBBUEJqNFRWcjZCWUFvTkRLeXBMZGs1NlcxQzFiZFlkWklaV2lwY3I0c1JTRkEvS0FkdzBBK0t1Z0lBbXJVRUVIQUlEQzZ2QTMzOHJoRHo3V2tWbUJrUkVTODhJekVseXlwTzRCY0M1STBBSEFUd1dWS2lXQnhZcnFDQUJRR0tYRXg4dXVrYVB0V1hUamdvS2t3cWhIcE1qNWJLOEM4b29FSFFEOFZGRFJJaElZRnFZakFEQXJNek5UVHA0OEtZY09IWkt0MjdiSjBxVkxKVFUxVlQrS2dwQjVLa1YyREg1UU1vOGYxejFtcWFOWnkvVHNyaU1BZVVHQ0RnQitLcVJ5SlFrSUN0SVJBT1NOU3J6VDB0SWtPVGxaRWhNVFpmUG16Yko0OFdKNTcvMzNaZHo0OFRKNHlCQzVOalpXYXRldEsrZlZxeWQxcks5NkRScEk2N1p0NWJoTGlTSE9RTzA3ZjJxeW5GcTVXbmVZRmQ2b29WUWVPMW9rSUVEM0FNZ0xFblFBOEZPaFZXTjBDd0J5cGhMd0F3Y095TnExYTJYMjdObnk0a3N2eVdPalIwdS9tMjZTaTl1MWs2Yk5tdGxKZDZXWUdLblhzS0cwNjlCQmJyNzFWbmw4N0ZoNXdmcHZ2NWs3VitMajQyWHYzcjF5NU9oUk82bEh3VHE2NkNjNS9QNUhPaklyc0doUmlaaytSUUxEdzNVUGdMd2lRUWNBUHhWS2dUZ0FPVGgyN0poY2V2bmxVcmQrZllrc1ZreWlxMVNSSmsyYlNxKytmZVgrSVVOa3dsTlB5VWNmZnl6TGxpMlQ5UnMyeU80OWUwaThmVVRxN2oyeWMvZ0l5VXBQMXowR0JRUkk5Sk9QUzNqVnFyb0RRSDZRb0FPQW53cS9vSkZ1QWNEL1V2dkRGLy8rdTJ6WjZzN1JXM0JIcHZWN2pYL29FY2s0ZEZqM0dHUWw1MUVEYnBiU1hUdnJEZ0Q1UllJT0FINHF2RW9WM1FJQUZCYjdYMzFka24vN1hVZG1SVjdVVkNvT0hhd2pBRTRnUVFjQVB4UVFFU0VoWmNycUNBQlFHQnhmc2xUMlAvZVNqc3dLcmxoQnFqNDNWUUpEUTNVUEFDZVFvQU9BSHdvdVgwNENRb0oxQkFEd2QrbEhqa2pDc0llc2h2bDk1d0doSVZKNThnUUpLY3VOWU1CcEpPZ0E0SWRDU3BhVWdFQXU4UUJRR0toaWNQSERINUgwWFh0MGoxbGw3cnBEaXJkcXFTTUFUbUwwQmdCK0tLUkdOYzZpQllCQzRzRGI3OGlKK1F0MVpGYlI5dTJrNHIyRGRBVEFhU1RvQUR3bHBGeFpDYTFTMmJXdmtJb1YzVWxrcmU4UlVpbjZqUDhHRTE4UjlldnJid3dBOEdkSksxZkp2cW5QNk1pc0VPdnpKV2JLUkc0QUF3WUZaRmwwMjNGcXVjMm1MckdTdWpGTzkyUXZhdEJBaVI0MlZFZi9wSTZMMk5DcXZXUWNPcVI3enF6QjJ1VVNHQm1wSS93dDhjMFpzdWVKQ1RweVZzTzROUklRekQ1WHR4Mlp2MEFTQnVSODk3cEVqMWlKbVh6bTMzdFdSb2JFZFk2VmxJMmJkRS8yU25icktsV21UZGFSL3prVkh5OXhsM1UyZmxac1lKRWlVbWZCZHhKU0prcjNBRURCU2t4TWxLbzFhdGpIclpteWQ5Y3VpWXJ5OW5WdlhjdDJrbjdnZ0k3TWlaNDBYc3AwajlXUk05S1BIWk80YmowbGJVZTg3akVuTUNKQ3FuL3dqaFE1djZIdUFXQUNNK2dBQUFDQUQ5cjF4SGhYa25NSkRKVHlqejVFY2c2NGdBUWRBQUFBOERFSFA1MHRSei83UWtkbWxlamFXY3IwNnFrakFDYVJvQU1BQUFBKzVHVGNadGt6WnB5T3pBcXJjNTVVR1RlR2swRUFsL0JPZzA5UjlRaTI5cnRaMWwzUXd2aFgzTFU5Sk9ORWt2N09BQUFBQlMvanhBbUp2LzhCeVV3eVAwWUpMRlpNWXA2Zlp1OC9CK0FPRW5UNGpxd3MyVGY5ZVVuNjlYZkpPSExVNkZkbThrbXBPSHFrQkJVdG9yODVBS0N3eU16TWxQVDA5RE4rWldSa1dCOUh4dXJyQWpuS3NsNmJ1eWRNeWxXUjEzd0xDcFRvTWFNa29rWU4zVkY0cWZkOFR0Y0Y5UmpnRktxNEZ3TCtVc1g5Mk0rL3lJNWI3eFRyU3FoN3pDbDcvOTFTWWZDOU92SWVxcmc3aHlydXZpOGxKVVhXcmwwcmY2MWNLZnYzNzVjRGlZbjZFWkd3MEZBcFdiS2tsQzFiVm1yWHJpMzE2dGIxZkVWcHVDY3BLVW0yYnQwcXExYXZsajE3OXNpMjdkdGw0OGFOY3VyVUtUbDU4dVFaQjkwUkVSRVNFaElpcFVxVmtnYjE2MHVsU3BXa2F0V3FkcnR5NWNvUzdFTW5tMURGL1Q5OHFZcjdrZSsrbC9oN2hxaTdTTHJIbk5MOSswbmxVWThVdWlQVjB0TFNKTjRhR3l4ZnNVSVNFaElrTGk1T05sbGY2cnFRbkp5cy82di9wOTd6WVdGaFVyeDRjV25Zb0lGOUhhaFdyWm8wYnRUSXZqNzQwalVCM2tDQ1hnajRRNEtldW51UGJMWmVTeG1IaitnZWN5SmJ0NVFhTTkvMDlGNHJFblRua0tEN3BxTkhqOHJjYjcrVkR6NzhVSDc4NlNjNzBjcXRPdWVkSjQ4LzlwajA2TkZEOTZBd1VNbjJ0bTNiWlBIdnY4dWlIMytVdi83NlMxYXVXcVVmZFVaNGVMZzBiOVpNTHJqZ0FtblZzcVcwYk5IQ0hxQjdGUW42Zi9oS2dwNlNzRlBpcnVrdW1jZU82UjV6SWk1c0lqVm52aTJCNFdHNngzK3AxNys2d2Z2TEw3L0kvQVVMNVBjbFMrU1lRODl4cEpXWHRHM1RSdHBmY29tMHNLNEh6UzY2eUw1T0FEa2hRUzhFZkQxQnoweEprYTNYOTVlVHkvL1NQZVlFbFMwanRiK2VMU0ZseStvZWJ5SkJkdzRKZXU3OGJpVTE2OWF2MTVFekxySUdLbzNPUDE5SHVYUEFHa1MvL09xck11WHBwODg0azVGYnN6NzZTTHBkZTYyT3p0MnNUejZSNDhlUDY4aDVWMTV4aFVSSFIrdklHWjk5OXBrY09YcFVSODY3eEJxQTF2VFlVbGkxSEgzVHBrM3kyZXpaOHNtbm44cjZEUnZzUHJjRUJRWFpONFI2OWV3cFYxMTVwVFJvME1DZWFUTnAxYXBWc3V6UFAzV1VzeE1uVHNoREkwYllTM1JOZVhyeVpDbGF0S2lPOHE1OCtmTFMrZXFyZGVRc1gwalFzOUxTWkhPL20rWGtzdVc2eDV6Z2NtV2wxdXhaRWxxaHZPN3hQK28xcjI3UWZXaDlGcno3M250eThPQkI0MXRYQWdJQ3BGaXhZdEtqZTNmcGQvMzEwcng1YytQWGd6TlJOeXMvLytJTE9YTEU3S1JYNmRLbDgvVTVtMWZxNTN0bjVzd3pyb0J5aXJySjBydFhML3NhYndJSmVpSGcwd202OWZMYzg4enprdmpzQzFaYjl4a1NZRjBrcTc3OW1oUnIyVnozZUJjSnVuTkkwSFBuL2lGRDVNV1hYdEtSTSs2NzV4NTVlc29VSGVWTURhWm16Wm9sUXg5OFVCS3RnVlIrcU9XR2YvN3hoOVN2WDEvM25CdjFzZG1vU1JQWnNIR2o3bkhldDk5OEk1MDZkdFNSTTVvMmEyWXY1VGJsbmJmZmxyNTkrdWlvWUtrVkZkOS8vNzFNc2w1ZmFoQ3VscXdXTkRXUVUwdGZCOXg2cS8wOHhjVEUyQU4ycDAyZE5zMU91djJOU21vK3NCSXBFenlmb0Z2WG5GMFRKc3ZCTjk3U0hlYW9NVjNWMTErUzRtM2I2Qjcvb203c2ZqOXZuancxYVpLcytPc3ZWMi9ZblU2OTk2dFhxeWFENzcvZlR2UlVNdXVtMndjT2xMZmZlVWRIWnFpYkVic1RFbHhmTWFDMkxkVS8vM3lqdjlzTzdkdkxkM1BuR3JtR0t4U0pnNmNkKzIyeEhIemhGZVBKdWZVT2t6S0RCdnBFY2c3NGk0U2RPM1VyWjRjUEg1YnJiN2hCYnI3dHRud241NHFhelZPSkV2eVBXcXI2M3Z2djJ6Y2pldlh0YTg4a2V5RTVWOVJnY2NlT0hUSnE5R2o3QnMrMXNiR3lkTm15QWtzUWZFM3JWcTEwcS9CUk5YZ096akNiVFAydHpGMjMrMlZ5cm03eWZ2bmxsOUtrYVZQcDJidTNmVzBveVBlZXV0RzdkZHMydVcvd1lLblhzS0U4UFhWcXZsYUZuYXRldlhycGxqbHFsWm1xRCtPMkpVdVdHUC9kOXJGZVE2YVNjNFVFSFo2VmRpQlJkajN3c1BHWlRTV3lXVk1wZjlkQUhRRnd3eHJyZy90c2k3alVudUcyN2R2TDdDKytjR3k1V3BreVpldzcrL0FmNm5YMDg4OC9TNXQyN2VUbVcyK1ZMVnUzNmtlOEtmbmtTYnVHZ3ZyM1huSFZWZllXRXVTc1JpR3RKSjY2Yjc4a0RIL0V5akROSjVORjJsNHNGZTY5VzBmK1EyM1B1cnBMRitsdUphWHFNOFZyRGgwNkpBOC84b2g5WS9HTEw3ODg2K2VpRXk2eHJqMnEwS1ZwYzcvN1RyZmNNMy9oUXQweVE2MEl1QzQyZjhVZXo0WUVIWjZrOWxvbFBQaVFwRnNmVEthcHZWWXh6MCtYZ0pBUTNRUEFEY2VPSHJVclpXZEhWYzd0ZU9tbGRsVnRKMTE0d1FWRzczekRYV29mOWRBSEhwRExycnpTWHJMcVM5Uk5KMVhrVU4yRTZ0NnpwMnpjNU1MUldUNUk3ZE5WVmZJTEc3WEZNK0hoUnlUandQK2ZUR0ZLY01VS0VqTjVvZ1FZMmxOYkVOU0ttc2xQUHkwdFdyV1NoWXNXNlY3djJyeGxpejI3MysrbW0reDZLeWFGaG9aS2Q4Tkpwcko0OFdMZGNvZTZwcW9pb0NhcG14dnFkQmlUU05EaFBWbFpzdStsVnlYcHAxOTFoemtxS2E4MGFaeUVsQzJqZXdDNDVkang0L2J5OVRQWnZYdTNYRzRsWER0MzdkSTl6aW1NQTMxL3BXYkQybmZzS00rLytLTFBMeFgvOHF1djVLTG16V1hzRTAvWU54M3cvMEtDZzZWQ2hRbzZLanoydi9HMk8yT2hpQWlwK3Z4MHZ4b0xxV01UdTE1empUd3ljcVI5UEpxdlVMUG5IOCthWmMrbS83RjBxZTQxNDdycnJqTitzMW90Y1RkNVNzUy9xYU15MVZZaWsyN3MxMCszekNGQmgrY2MvMzJKSkQ3L3NvN01paHB3aXhTL3BKMk9BTGhKelo2cnMyYi9UUlg0NnRXbmo1SGtYRkhWeHVIN2xscURWN1ZFM09tajBncVNTaVNlR0RkT1dsNThzYXhZc1VMM29tN2R1b1h1YUtyamZ5eVZBOU9mMDVGQmdZRlNZZmhRS2RLa3NlN3dmU3RYcnJTdkRRdDhZTlk4TzN2MjdyVnZVczk4OTExalM5NVZYUWQxREp4SnUzYnZOcDR3bjI3ZXZIbTZaVVpFUklSOXlvcHBKT2p3bExUOSt5WGgvZ2Z0SmU2bVJUUy9TQ29NdlU5SEFBcUN1dHQ5T3JVOGJjZ0REOGlTUC83UVBjNEtDdzB0dEh0Wi9ZazZyL2lLcTYrVy9TNVUzaTRJYWx0SDMzNzlYSjE1OHJLYU5XdnFWdUdRZnV5NDdCeitpQ3MxZUlwZmVabVU2WGU5am55ZldsTGR2bE1uaVU5STBEMitTOTJzSG5qbm5USnQrblFqU1hxUklrV2syelhYNk1pY2IxM2FoNjZlbzNrLy9LQWpNOVRwS2lWS2xOQ1JPU1RvOEF6MVFhUUtvYml4MXlvb3FyVEVUSjFrL0F4M0FEbjc3Vi83MDlUeE4yckd3SlN5WmN0S0tjTjd4MkRXK3ZYcjdSVVdKcytoOTRMSlR6MWw3eE9GU0xPTEx0SXQvNmVPUVUwWU9VclNFbkozeWtWK2hOYXVLVlVtanBPQVFQOUlCMzc4OFVlNXFrc1h2OW9pb3FyUGp4ZzVVcDU1OWxuZDR5eFZqZHkweFM0VndUeVZraUovR0xxNS83Y0J0OTJtVzJhUm9NTXo5ci8rcGlUOStJdU96TEgzblU4ZUw2R1ZvblVQZ0lKeStoTDNvMGVQMmtmT3FBR0pLZVhMbDdjTFRzRTNxV3JIc1QxNnlJRkU4emR5QzlLZEF3ZEtWeXZSd0g4MGJkcFV0L3hmNHJ2dnkvRnZ6TTg0QmhhSmxKanBVeVNvU0JIZDQ5dlVxcXR1M2J2YnM4NytScTBzRy9iUVEvTGVlKy9wSHVlMGJObFNpaGN2cmlNejFMRm5LVmJ5Yk5ybXVEalp1MitmanB5bnpxcHYxN2F0anN3aVFZY25uUGhqcWV5ZlBGMUhacFVlY0xPVTZOQmVSd0FLa3BvTi9kc2JiNzVwL0FpY3BoZGVTQVYzSDZXV0w2cUNUMXUyYk5FOS9ra1ZNWnd3ZnJ5T29QYWVWNnRhVlVmK0xYbk5XdGs3ZWFxT0RBb01rSXBqUmtsazNicTZ3N2R0Mzc1ZHV2Zm80ZmZGRmUrOCsyN0h0MytwYXVSWFgzV1Zqc3pZdDMrLzdMZStUUHRtN2x6ZE1rTXRiM2ZyaUZZU2RCUzQ5RU9ISkdISWNIV0xVUGVZRTltaW1WUWN3cjV6d0N2VUhtSzFWRGt4TVZIR2pCMnJlODFSeGFiZ214WXRXaVJ2elppaEkvK2s5b1MrL2VhYlVyUm9VZDJEa2lWS1NGUlVsSTc4Vi9xeFk3Smo4SU9TZGRKd3hmR0FBQ25kNzNxSjZuYXQ3dkJ0YXNhOGQ5KytkaExvNzFRUnlSdjY5Yk5YRWpuSmRGVnlOWHYrNysxc1RsT3JERXp1ZFZjMzl1KzQvWFlkbVVlQ2pnSmxuM2MrYklTazc5NmplOHdKS2xWS3FreWZ6SG5uZ0llbzVlejc5dTJUOTk1L1g1SnpPQlBkS2VyOFV2Z2U5VG9aTlhxMFBRanpWMm9BT09LaGg2UkpreWE2QjByNUNoWHN5c2wrTFN0TGRqMDVRZEsyL2JOb3Bnbmg5ZXRKOUVNUDJvbTZQeGo3NUpPeTNNVVRENEtDZ3V4aW8ycGxoL3BTVzZaQ3JIR2xXeXV6ZHNUSHk1MkRCamw2TFd6ZXJKbVVLV1AyaUwxdnYvMVd0OHc0ZXV5WXJEdHRSWjdUb2l0V2xHYlc4K1FXRW5RVXFQMXZ6WkFUQzM3VWtVSFdoVE42L0JnSkxZVG5xQUplcHFwVXI5K3dRVjU2MmZ6Umltb2dWYTFhTlIzQmw2aXE3YVlxKzN1Rk92Sm82SkFoT3NMZkdqZHFwRnYrNjlDWGMrVG9aMS9veUp5Z01sRlM5YVhuSk5CUGpxejcrZWVmWmVxMGFUb3lSeFZydk9MeXkrV0Y1NTZUWDMvNlNiWnQyU0o3ZCsyeXYvYnMzQ2tiMXE2VmIrYk1zVyt3MWE5WFQvKy96UG5LK2w1T3poYXJxdVFkREI4LytyTjFEYy9JeU5DUjg5VEpGMDZ2TERoZCsvYnRqUjlKZHpvU2RCU1lFMzhza3dOVG50R1JRVlp5WHZxMi9sTHl5c3QxQndBdmVmT3R0MlRMMXEwNk1xZHExYXF1ZnNEQ0dXcnYrYlBQUDY4ajg2cFVxU0kzMzNTVFBEMTVzc3l6QnNFYjE2MlRyWEZ4c20vM2J0bTBmcjJzVzcxYTVuLy92VHozekRNeWNzUUl1YVpyVjZsWHQ2NEU1K05Va0tqU3BlV2RHVFBzbVRqOFUrM2F0WFhMUDUzYXZrTjJqeDVyejZLYkZCQVNMSlVuUENGaGZsSWdWKzAzSHpCd29JN01VTFBpdlhyMnROL3pjNzc4VWdiZWZydGRzRkNkQnFLMm82Z3Z0U2M1SmlaR0x1M1VTY2FPR1NQTGx5MlQyWjkrS3VjM2JLai9GdWVwRlVYM0R4N3MySjU3OVhQZWNMM1pvL1pVWWMrOWUvZnF5SG5mV2Rka2s5eGMzcTZRb0tOQXBDVWVsSVQ3SDNEbnZQTUxtMGpGQjVtVkFMeHF6dGRmNjVaWmxhS2o4NVZFb1dBY1BIaFFmdnI1WngyWlU3MTZkWGx2NWt3N0lYL3QxVmZsdm52dmxmYVhYR0tmbTYrU2RsWEJWLzAzS21GczE2NmQzSG5ISGZMNDZOSHk2YXhac3VMUFAyVlhmTHg4L09HSDlrQzNTdVhLK20vTm5TbVRKa21NOVQzd3YveDVXMHBHY3JMRVcyT2h6T1BtaTV0RjNYYUxsT2pZUVVlK2I5S1VLYkxWWUZIUjRsYmlQWFBHREhuM25YZnNtN3U1cFpiQWQrbmNXUmIvK3F1ZDBKdXlmY2NPZWY2RkYzU1VmNWRZMXpwVk1NNlVaT3UxL3FkMW5UUkIzY1Q5NGd0eksxRFU3LzhpbDQ5NkpFR0g2N0l5TTJYWDZMR1N2dGZjVVFoL1U4dTVZcDZkS29FY3F3UVVlbTUvd01JWnExZXZ0by9nTStuaTFxM2xqOFdMN2RteXZNeGlxMEc1U3VCanUzV3ppN3l0VzdOR2ZscTRVSHIyNkhIV0k0eHU2TnRYYnJqaEJoM2xuN3B4c05NYXZPZm1hOVdLRmNiUFdsLzExMTluL042NS9WTDdZLzJSR2d2dGZtcUtuRnF6VnZlWVU2Uk5hNms0OUg0ZCtUNjFEOXZKNVBUZjFFcXJEOTkvWDNyMzZtWFBMdWVGMmxMMTdQVHBjdis5OStiNTd6aWJxZGJmNzlTMVVhMEd1TFJqUngyWk1YL0JBdDF5bHFvUWIvSjBqOHN2dmRUMTFVMGs2SEJkNHRzelhUbmpVNEtESkhyQ0V4SWFYVkYzQUNqTWF0ZXFwVnZ3SmFabnoxVmkvY0Y3N3prNmU2U0tSN1ZxMVVyZWYvZGRlM25zeFBIajdSVWMveDZvcTVuMnA1OSsydEVCdkVvdTFIbi91ZmxTUzNWTksyZDlqek45Nzl4K3Fac2YvdWpvRHd2azhBY2Y2OGljNEhMbEpHYnlSQW53bytkeGl2V2VVYWQvbURKNjFDaTU3TExMZEpSMzZyVTdmdHc0WTZ0QURoOCtMSysrOXBxTzhrZGRnOVFOU3BOKytmVlgzWExXWHl0WEdpMHlhN3JLL1ptUW9NTlZTU3RYeWI0cDVndDZLS1g2OXBhU25meG5PUmVBL0ZHenBQQTlKaXZ6S3BkYkEvR0tGYzNkeUZWSjVnTkRoOXF6Nm1yZnV0cXZxcWhLMEcrKy9ycTkveHlGUzhxdVhiSnp4Q2dSZzBXemxJQ3dNSWw1ZnFxRWxETi9JOFl0TzNmdWxMY05IcmZZb25semUzdUxVOVFLbFJlZmYxNGlEWjFFOEpwMURWRjcwcDJnYmtvVU1WaW5aYzNhdGZaTkJhY3RNRFF6cjZpdFI4MnQxNFRiU05EaG12UkRoeVhoM3FIbXovaTBoRGVvSjlHUFBxeHVDZW9lQUlXWldtNFljdzc3Q09FZGE5ZXQweTB6cXJ0VTJWL05iTjh4Y0tDOXJIelV5SkV5ZVBCZ2U5OG5DcGRNZmJ4czVwRWp1c2Vjd0tKRkpNelBUcTZZK2U2Nzlubmdwb3daUGRyeFdpV3Fic1d0dDl5aUkyZHQyNzVkRmk1Y3FLUDhLVnEwcUhUcDBrVkh6bE5IdzZscTdrNVMrODlORm9qcjJyVnJnYXppSVVHSEs3TFMweVhob1Vja0xXR243akZIZlNCVmVYNmFCQnJlVndlZ1lLZ2pZYTYrOGtvWi8rU1Q5cEUzQ2RZQTVlamh3M0xNK2pwNjZKQnMzN0pGZnJNR0FXci8zMTEzM0dHZks5M200b3Z0R1V2NG5zVEVSTjB5STgyRllxV25VM3M5SHhzMVNwNFlNOGJZM2xSNDEvNlhYNVBrSlV0MVpGYkd3VU95OC9FbjdmM3UvdURreVpQeW5NRzk1NjFhdHBTT2h2WmgzM1AzM2NiMk1iL2w0SW9DVlRmRHBDVkxsdWlXTS9iczJTTWJOMjNTa2JPQ0FnUGwrcjU5ZGVRdUVuUzRJdkhEaitYRS9FVTZNaWNnT0VncVRaNGc0WngxRFBpZHFLZ29lZnl4eCt3cTIxOTgvcmtNZS9CQmUrbFpoUW9WN09XREVkYVhtcVdzVkttU05Mdm9Jcm5yemp2bDJXZWVzWXQvZlRGN05za1F6aWh1ODJaN0ZzWnR2QjRMcCtBeVVicmxqdU56djVORG4zK3BJOS8ydy96NWN1REFBUjA1NzVhYmJ6YjJ2cXhtalVzYm5YKytqcHlsNm5Ra0pTWHBLSC9hdFcxcmY1YWFvdjZ0VGw1dmY3Y1NmcWVXK1A5YjVjcVZwZW1GRitySVhTVG9NQzU1elZyWk4yNlNXb2VpZTh3cHFmYWRYNUgvd2g0QXZFTU5sOVN4TlN1V0xaT1JqenhpSityblFnMjQxQkozK0NiVGlleUNoUXRsbThIam1vRFRSZlhzTHBITm11cklCZGJZYTgrVEV5VE5ZR0xybGxtelp1bVc4OVFLcTY0R2wzZXJaZExYeGNicXlGbjc5dTJUcFV1ZFdaVlJxbFFwdTJxNUtXb2ZlbXBxcW83eWI5RWljNU4vM2J0M0w3QWlsU1RvTUNyanhBbEpHRHBjc2d6dUYvcGJXUDI2RXYzSWNEV2EwejBBZkozNmNMei8vdnRsMWtjZkdTM2tCZTh5ZmN5V3FnWjlkZGV1a3BDUW9Ic0Fjd0tDZzZYU0U0OUxnSXZITm1VZVBTWTdSNDF4WmFMRWxKU1VGSm56elRjNmNsNHo2enBUcGt3WkhabHhtY0hFOStOUFB0R3QvT3ZWcTVkdU9lK0VsUmNzWDc1Y1IvbW5ickNhb0c3WTlML3BKaDI1andRZHhtUmxaTWpPa2FNbE5jN2MyWVIvQ3l4V1ZHSmVtQzZCNGVHNkI0QS9HSFRublRKcDRrVEhpL2JBZDFSem9iaWZPa08zV2N1VzhzR0hIem82dXdPY1NVVHRXbEwydnJ0MTVJN2o4K2JMUVI5ZTZ2N3JiNzhaUFZxdGsrRXp3Slc2ZGV2cWx2TlU4VFZWaE0wSjZsZzRWU3ZERkxWVndRbTdkdTgydHYrOFpxMWFjbDd0MmpweUh3azZ6TWpLa3NUM1A1UmpYNW03Mi9sZmdRRlNjZXhqN0RzSC9Fem5xNjZTeVpNbUdWL2lERzlyMUtpUmJwbDE4T0JCNlgvTExkSzBlWE9aOWNrbmN2VG9VZjBJNEx4eXQvYVhzTHAxZE9TT3ZlTW1TdXFldlRyeUxWOS8vYlZ1T1U5OXhuUm8zMTVINW9TSGg4djVEUnZxeUZtN3JXVDEwS0ZET3NvZmRUUmtHNFBIa3FyejBKM1loejUzN2x6ZGNsNzMyTmdDblJnZ1FZY1J5ZXMzeUw2SlU5elpkOTZ6dTVTK3RxdU9BUGlEMHFWTHl5c3Z2MXhnKzcvZ0hlcGNZcmR1MHFoQjQ0WU5HK1Q2ZnYya2JvTUdjdS85OTh1eVpjdnM1YldBazlTS3Y4cVR4a3VBaTZkTFpCdytJZ21QakxKWE9Qb1NWUVRzeDU5KzBwSHoxUEZpNmlnMDA5UjFyR0tGQ2pweTFyRmp4K3lDbDA3cDM3Ky9iamx2MDZaTmpxeFVNcmE4UFN4TWJyNzVaaDBWREJKME9DN2orSEZKdUdld1pDV2YxRDNtaE5hcUlaVkdqMlRmT2VCSDFDRG15YkZqN2J2NFFJMGExblUrT2xwSDdsSEh1NzM4eWl2U3FrMGJhZFNraVR3d2JKaGRpTW50WTluZ3Y0clVyeWVsKy9mVGtUdVNmdmxORHMzK1FrZStRUzF0WDc5K3ZZNmNwMDcvS0ZteXBJN01LbUh3KzZ4WnMwYTM4cS85SlpkSThlTEZkZVNzbmJ0MnlmYnQyM1dVTitxbTZkSmx5M1RrckFiMTZ4ZklaODdwU05EaHJLd3MyZlg0azVLNmJZZnVNRWZ0TzYvNjh2TVNhUEE0Q0FEdVUvdjBidXpuN3FBVjNxVUd6N0hkdXVtb1lHemR0azJlZmU0NWFkMjJyZFNvVlV2NjNYU1RmRHhybGwwOUdjZ3pOYU02K0Y0SnFScWpPMXlRbVdsWGRVL1pibjZjNWhTVnpLVWF2REdtOWhxSHVyU1NvVnpac3JybHZOOFdMOWF0L0ZPbnBiUnMwVUpIenB2NzdiZTZsVGZ4Q1FuNVR2S3owKzNhYXd0ODlSNEpPaHgxY05hbmNuUzJDMFZJckRkT3hkRWpKYnhtRGQwQndCK28yZk9IaHcrMzkrb0JmN3ZuN3JzOWMxVGVYaXNwLytqamorV0dHMitVS3RXcVNZdFdyV1RNMkxHeTZNY2ZqUmF4Z24reWw3cFBlTUxWbFlDWngwOUl3cU9qZldhcHV5cUFabExWR1BkdWtKUXJWMDYzbkxkbnp4N2R5ci9Bd0VDNXllQ044dnh1V2ZqaGh4OTB5MW1oSVNGR2wvZm5GZ2s2SEhOeTR5YlpNL3BKVi9hZGw0aTlSa3BmVjdBektnQ2NWN2xTSmZ2dU5YQzY2dFdyUzQvdTNYWGtIV3JQK3ZJVksrVEo4ZVBsOGl1dmxFcldRTDlYbno3eXNaWEFxOEd5RTRXUTRQK0t0V2d1cGE3dnJTTjNKQzllSWdkbXZxY2piMU9uTEpoVXFuUnAzZkp0Y1hGeHV1V01LNjY0d3RqS2dwVXJWK2E1dG9lNnJuNWo2TWk5cGsyYkdxc1RjQzVJME9HSWpLUWtpYi83Zm5mT082OTdubFIrWWpUN3pnRS8xS2QzYjN0Sk0zQTZ0Ykppek9qUlVxeFlNZDNqUFdyUWVQTGtTWm45K2VkeXcwMDNTZjJHRGVXS3E2NlN6ejc3akpsMW5GV0Z3ZmRLa09GenVQOXQvOVJuNUpRUExIVlhOOEZNZW52R0RLbGVxNVlyWDA5UG02YS9xL01PSGpva3B4d2NoNWNvVVVMYXRtbWpJMmVwbFVqcW1MUzhVTmZUUHcyOUpxNjk1aHI3ODZhZ2thQWozN0l5TS8rejczekxOdDFqVGtCRWhGUjU1bW5PT3dmOGtGcGFOdUMyMjNRRS9GUFZxbFhsaVRGalBERjR5bzBUU1VteWNORWk2WDM5OVZLdlFRTzd5TnlPSFR1WVZjY1poWlF1TFpXZWZGeXRMZFk5NW1VbUpjdk9oMGRLVm5xNjd2RWVWWlRSeWFYYlo2SVN2cDA3ZDdyeXBhcXRtNkxPUVZjM0NaMmlyclU5ZS9UUWtiUFU3MVVWM2N5THpaczN5NEVEQjNUa0hQWHozbUJkcjcyQUJCMzVkdmlMcitUb3A1L3J5Q0RyalZQeHNSRVNjWjc1b3pBQXVLOSsvZnAyRWdaazU0NkJBK1hxcTY3U2tlL1l0MysvWFdTdVZwMDYwdmVHRzJURlgzL3BSNEQvVjZKamV5bldxWU9PM0pHODlFODU4UDZIT3ZJZXRRejZGTWNjNWs1V2x1T25USmljVWY1cXpoemRPamZ6RE8wL3Y3aDFhNm5nZ2VYdENnazY4a1h0Tzk4OVlwUjlVVEN0ZUxldUV0VzdwNDRBK0p0T25UcHg3amx5RkJ3Y0xEUGVla3N1YU5KRTkvaWVUei83ekM0c3B4SjFkUjR3OExjQTYvcFhlZXhvQ1NybHpwRmZmOXMvYWFxYzNPVHMvbVducVBPeTg3cFh1YkRKeU14MGZJYStUSmt5Y3ZsbGwrbklXVXYrK0VNeThsQ284THZ2djljdFovWHQwMGUzQ2g0Sk92SWwvdDRoa3BXU3FpTnpRdXZVdGo2MEhyTm4wUUg0cCtzOTlPRUk3MUw3SXIvKzZpdHAwcml4N3ZFOWFwbjdKNTkrS2syYk43Y3J3Q2NuSit0SFVOaUZsQ3NyRlI1OVdFZnV5RHg1VWhJZWZGZ3lyV1RZYTFUQ2VmVG9VUjJoSVBUcDFVdTNuTFZ2NzE1NzJmKzVPSGp3b1B5NWZMbU9uQk1SRWVHcEFyVWs2TWlYTkpmT080OTVkcW9FRlMycWV3RDRtMHJSMFZLdlhqMGRBVGtyVzdhc3pQdnVPN244MGt0MWoyOVNCWjFVQmZpTDI3YTE5MVVDU3RRMTEwalJEdTEwNUk1VGE5ZkovbGRmMTVGM3FKdFoxRzBvV0IwN2RwU1FrQkFkT2Vla2RmMDcxKzArYTlhdWRYU2YvZC9hWEh5eDBTUHd6aFVKT2p5di9NTVBzdThjOEhOTm1qUXhNZ0NBL3lwWnNxUjg5dW1uTXVUKysrMHplMzJaR25TMnZlUVNtZnZ0dDdvSGhWcGdnRVNQR2lrQkxwLzlmK0RGVnlYWlN0UzlKTjFIem1yM1o5SFIwWEp4cTFZNmN0YlhYMyt0VzdtemFORWlJemRzYmpSNDVudGVrS0REODlKVTlVN3VuZ0orclJyRjRaQUhZVllDTSttcHAyVFdSeDlKbGNxVmRhOXZTang0VUhyMDZpWHZ2ZisrN2tGaEZsNDFSc29QRytMcTFyNnNsQlRaT2ZJeHlYSzQwRmgrc1AzREcvcjI3YXRiempyWDVlcno1OC9YTGVlb2JWT205dG5uRlFrNlBPL2dxMi9Lc1o5LzBSRUFBUDkwVGRldXN1cXZ2K3paZERYWThsV3FJTmFBZ1FObDFpZWY2QjRVWm1WdTZDdmhEZHpkK25OcTlWclorOEpMT2lwNHhkamVtR3RxSlZGa1pLU09uTldoZlh2N2hxalQxT3FoL2Z2MzZ5aG5pWW1Kc3ZUUFAzWGtISFhXZTFSVWxJNjhnUVFkK1JMWm9wbHVtWk9WbWlZN0h4d2hxYnZObm9NSkFQQmRSYTJCdkpwTi84c2F3UFh1MWN2WVFOVzA5UFIwdWYyT08yVDVpaFc2QjRWVllHaW9WSmswUVFMQzNWM3Fudmo2MjVLMGFyV09DcGFwSTc3OGtYcW0xRWtYSnFnalVCczJhS0FqNTZqbDZyOHRYcXlqbkMzKy9YZjcrdWkwL2pmZHBGdmVRWUtPZktreTlTa0pLbVArcmxQR2dVU0pIL3lBSnl1TUFnQzhvM0xseWpKenhneFp1WHk1M0h2UFBSSlZ1clIreEhja0pTVkovNXR2Wm5rdjdCbzhaVzYvVFVmdXlGSlYzWWMvWWxkM0wyaXFOZ24xU1hJbndPQU11cHFkdjdsL2Z4MDU2N2ZmZnRPdG5QMzAwMCs2NVp6eTVjckpwWjA2NmNnN1NOQ1JMeUhXQzd2S00xTWtJTVRNSGJ2VG5WeTZYUFk5KzRLT0FBQTRNelhyVnExYU5aazZaWXBzMnJCQjNucmpEV25Wc3FWUHpjWnQyTGhSSmt5Y3FDTVVXdFpydHZ5ZHQwdG9yWnE2d3gycGNadGw3NHN2NjZqZ3FJU3pTSkVpT2tKT1ZCSWRHaHFxSStkMXZ2cHFDVFB3OTZ1Wjhkd1VmdnMxbDRuOHVWRFYyOVhxSzY4aFFVZStGV3ZkU3FLc0R3ODNKTDc4dWh6NzFmazNLQURBUHhVdlhsejYzWENEL0xSb2tXeGN0MDRtakJ0bkQ4cE1ERFNkOXRJcnI4aStmZnQwaE1JcU1EeGNLazk0VWlRb1NQZTRRNDI1VGhnNGMvcGNxSDNQNFM1WHMvZFY1Y3FXTlpxZ3EycnVqUnMzMXBGelZxMWFaUjg1bVJONy8vbXlaVHB5VHUvZXZYWExXd0t5REI0dW1KV2VMcHU2eEVycXhqamRrNzJvUVFNbGV0aFFIZjJUV3RhOG9WVjd5VGgwU1BlY1dZTzF5eVhRUi9lY21aVDQ1Z3paODhRRUhUbXJZZHdhQ1FnT3RuL1gyMjY5UTVKKy9sVS9ZazV3dWJKUzY2dlBKTVQ2czdBNk1uK0JKQXdZcEtNeks5RWpWbUltbi9uM25wV1JJWEdkWXlWbDR5YmRrNzJTM2JwS2xXbVRkZVIvVHNYSFM5eGxuZTNYc0VtQlJZcEluUVhmU1lnTFcwSk11SC9JRUhueEpYT0ZnKzYrNnk2WlBtMmFqcnhOZld3MmF0TEVudUUwNWR0dnZwRk9IVHZxeUJsTm16V1RWYXZON1N0OTUrMjNwVytmUGpyeU52VTdQSGJzbUh3emQ2NHN0QkozdGNSeXk5YXRSdlkzNXRld0J4NlE4ZVBHNmNoWmF0QmJ0VVlOdXppZEtYdDM3ZkpjQWFaL1c5ZXluYVFmT0tBamM2SW5qWmN5M1dOMWRPNTJUWGhLRHI3K3RvN2NFVkkxUnM2Yk0xdUNDbWg4cmQ2VGRSczBrQjA3ZHVnZTU2blZOdTNhdHRXUjd6cXZkbTE1YVBod0habngwc3N2eTMyREIrdklPUXQvK0VIYXRHbWpvLy8xeWFlZlN0OGJidENSTTlTNTUxczJiWkx3OEhEZDR4MGs2SVdBR3dtNmtuYndvTVJkM1UweTlwdi9rSXRzM1ZKcXZQMmFCQlRTZlVrazZNNGhRYzhkRXZUL1I0SitacjZVb1ArYlNnTFVUTFZLMk5XWG1xbFJsWVVORHBGeVRjMWFxWmwvRTROSUV2VC84SlVFUGVQNGNkbDQ5YldTN25MUjNOTDkra3JseDBmWnkrMEx3aVVkT3VTNmtGaGVYSFhsbGZMbDU1L3JDRGxSMThWcU5XdEttc05IOFkxNDZDRVpPMmFNanY3WGdOdHZseGt6WitySUdYMTY5N2JybFhnUlM5emhtQkRyQTdqeWxJbXVMTUZLWHJ4RTlyN3dzaG9wNng0QUFQSkdWVDZ1VkttUzNENWdnTXorOUZQWnNIYXQvUHpqajNMWEhYZEkxWmdZWTVXUmMyUHYzcjJ5Y3RVcUhhRXdDeXBXVENvOWFTVXhnZTRPM3c5L09FdU8vMWx3UzkyYlhYU1JicG14ZXMwYXljakkwQkZ5VXJac1dXblpvb1dPbkpQVFBuUjFBM0h4a2lVNmNrNlA3dDExeTN0STBPR280bTB2bGpKM3ViQWYzWG9USDN6eFZUbit4MUxkQVFDQU0xVFJvQmJObTh1enp6d2o2NjFrL2FlRkMyWFFYWGNWU0VYNHpNeE0rZnJycjNXRXdrNk5zMHBjMDFsSDdsQXJ6SFlPZjBReWtncm1WSUhhdFd2cmxoa25UcHl3dDd6ZzdGU2h6V3U2ZHRXUmM5U0t0SlNVRkIzOTA1NDllMlRMbGkwNmNrYjU4dVh0bFJOZVJZSU94NVcvWjVCRU5EZDd0MVBKU2t1VG5mYzlJR2t1TEtrSEFCUk82b2luWnMyYXlUUFRwc25Xelp2bHBSZGVrTnExYXVsSDNiSGtqejkwQzRXZE9rb3IrdUZoRWhUbDdzMml0QjN4c252aTVBSlp1ZGpDd0l6dDZWUnl2aW51N050eDhSL1hYbnV0NHlkaXFKVkMyN2R2MTlFL3FUb2hUcTl3Nk5LNXM5R0NldmxGZ2c3SEJZYUZTc3d6VXlTb2JCbmRZMDY2bFp3bkRIdFlzdEpabWdRQU1Fc2QrVFRndHR0azVZb1Y4dVRZc1JJUkVhRWZNVXZ0aVdjSkx2NFdVcmFzUkk4ZTZmcFM5eU1mZnlMSGZqTzNGenc3MWF0Vk0zclVtbHFsOHNNUFArZ0laNk4rSDgyYk5kT1JjK1prczFMSTZSVkU2amk2M2oxNzZzaWJTTkJoUkdpRkNsTDU2WW4vTFNCblV0SlB2OHErNTEvVUVRQUFacWxaZFZVdCtmTlBQNVVpTGhTblZVWHNmSFVKcmhjcjQvdURrbGRlSWNVdWRiYVE1Tm5ZUzkySGpaRDB3NGQxanp2VWxwUDY5ZXJweUF5VkhIcWhLS1N2TUZFUTlFeUZBSk9Ta2h6ZmYxN1J5bEZhdDI2dEkyOGlRWWN4eGR0Y0xLWHZ1RTFIWmlXcS9laS9zd1FRQU9DZURoMDZ5UEJodzNSa2pwcmhVL3RrbmFhSzN6bTlWUFhmMk50clJrQlFrRlI2L0ZFSkxGRmM5N2dqZmQ5KzJUVitrcXRMM1lPc24vWFNUcDEwWk1aZksxZkt0bTNiZElTenVlTHl5eDB2bnJsOHhZci9PUTlkSFgrcEtzYzdxVnUzYnZiNStsNUdnZzV6ckEvOWl2ZmZJeEV0blY4RzgyLzJmdlFISG5MOXJpNEFtS0FTTWllcG1TR25qOFhCZndvbTNYYmJiY2FYdXF2ZjM3OEhyazVRZzFUVENickpJOXdLdTlEeTVhWDhnME4wNUo2am4zOHBSeGY5cUNOM1hISEZGYnBsaGxycDhaWkhqOXp5b2hvMWFrakRCZzEwNUF4MTFPV3UzYnQxOUIrTEZ5OTJkR1dEdXRuVHorSHoxRTBnUVlkUjZwenlLcE1uU2xDcGtyckhISFV1YU1KREk0MmZadzBBcGgwL2ZseTNuUEhKcDUvSytnMGJkQVFubFM1Vnl0NlQ2WXRNSitmS1pvZXJMK09meXZUcUtSRk5MOUNSU3pJelpkZGpZeVg5NkZIZFlaNDZWVUVkOFdYU2pIZmVzWmRVNCt6VVB1NGIrL1hUa1RQVVRaTGZmdnROUi84eFo4NGMzWEpHMWFwVnBkSDU1K3ZJdTBqUVlWeFk1VXBTYWVwVDluSXMwMDdNV3lENzMzaGJSd0RnbTV4YzBoY2ZIeS8zRFI2c0kvOXk4T0JCT1hDZ1lFL3lVQU5WdFNmZE5EWHo0N1R3OEhBSk5KeWtxMldyTUNjZ09FZ3FqMzlDQWlMQ2RZODcxS1RJemtkSDI4bTZHOVJ5Nmw2R0MzdXA0N3pHUHZHRWpncWUweXVwbkthT0tYTzZFdnJjYjcvVnJmL2NxUDdsWHdsN2ZsMTd6VFdlcnQ3K054SjB1S0xFSmUyazFLMDM2Y2lzQTFPbXkvSEZ6aGFVQUFBM3JYQW9xVkg3Zi92ZGVLTWtKaWJxSHYraGt2T3UxMTRyelZxMHNDc3dGK1JnMXZSdVhKV2NGeTl1WnE5eDQ4YU5kY3NNTlNORzhTMnpJbXJWbEhMM0RySzNGcnJwMkxmZnk1SDVDM1JrbnFxOGJYclZ4NnV2dlNacjE2M1RVY0ZRMjVIZWZmZGR1ZW5tbXoxZFpMRmF0V3BTdlhwMUhUbERGWXI3KzJkZXRXcVZveXNhMU0zVVcvcjMxNUcza2FEREhkWUZ0ZUtRK3lTOFNTUGRZYzUvcW93K0xPbUhqK2dlQUhDT0dpQ1dLbFZLUjJhb1k3WHltOVNrcEtUSUxiZmU2bmdGWEM5UU15dlh4c2JhejVQYXM5akZTdFQ3MzNLTDdQN1gva1UzcUwzaHBtK0FoQVFIUzRrU0pYVGtyTXFWS3VtV0djdisvTk0rNHhobWxlMS9vNFRWcTZNamwyUm15YTZSb3lYTnBWVXN6WnMzTjE3Ti9ZU1ZFS3FibWtkZFhMNy9OM1hOWDdseXBWeDYrZVZ5eTRBQjh2R3NXZkxzYzg5NTlnYVhXam5VNy9ycmRlUU1kZU4xMTY1ZGRsc2w2MDcrN09mVnJpMjFyUzlmUUlJTzF3UkdSRWpNYzFNbDBOQXN3T25TZCszNXovbm9IbDhlQk1BM21TNEt0bnJOR2xtN2RxMk96dDNKa3lmbFppczUvOUxoL1h0ZW9LcVo5KzdiVjViODhmOG5kNmd6d2ovODZDTnBmT0dGOHRTa1NVWXFubWZucDU5L05uNWpvRW1USnNhVzBWY3luS0NyMzhYalk4YmtlYUROTVcyNUV4Z2VMbFVtUEduWC9uRlR4c0ZEc3ZPeHNTcTcxRDNtcUpVa1ExellyclBHdXZiMjZ0UEg4Vm9nT1ZGSjZXMjMzeTR0TDc3NHY4ZU5xZmZNcU5HalpmNzgrWGJzUmRmRnhqcTYvVWJkOEZRMzlSU256NmJ2MHFXTDQ1WG5UU0ZCaDZ2Q0tsZVdTbE1tNk1pc0UvTVh5WUYzM3RNUkFEakgxR3ptNmNaUG5KaW5wRVlOOUdLN2Q3Y0x3L2tiTldEdWU4TU5NaStiZ2R1UkkwZmswY2Nla3pyMTY4dTA2ZE9OejJ5ci9lK0RoNWl2b24zaGhSZnFsdk5hdDJxbFcrYk1mTzg5ZWVPTk44N3A5YnhwMHlZWlBIU290R3Zmbmtyd3VSVFpvTDVFM2VMT2RzTFRIWjgzWHc1OThaV096RklKWWFYb2FCMlpzMkRoUW1uVHJwMnNXNzllOTVpeGRkczJHVFo4dU5ScjBFQm12dnZ1Lzl5UVVxOTl0VHBvKy9idHVzZGIxQkwzZW5YcjZzZ1ozOCtiWjIvUCt2SG5uM1dQTTI2em5rZGZRWUlPMTVXOHJKTkUzVGxBUjJidG56UlZrbGF0MWhFQU9NUHA0MlhPUkNYWUw3MzhjcTZUR2pYejhONzc3OHRGelp2TC9BWHU3UXQxaTFxeVAyRGdRUG4ydSs5MFQvWlVrYjNoRHo4c05Xdlh0Z3ZrTFYyNjFQRmo1clpaQStiT1hidmFBMnlUMUw1Sms4V3hhdFdxWlg4UGs5UnpmODk5OTltSnh1clZxOCtZY0t2WDcwWXJLWC9ublhma3lxdXZsa1lYWENBdnZQaWl2WTFCSlM3SWhZQUFxWEQvUFJKYXZhcnVjSWwxamRvejdpbEpkV0VyUTdGaXhlVFJrU04xWkpaS3psdTJibTJ2eWpuczRERythb1dUbWhWWEs0SHFOMndvMDU5OVZrN21jSXppL2dNSDVOcnJybk4xWlZCdXFaVTl2WHYxMHBFelZOMEtkYzEyc3E3SUJkYjFSQjBONXl0STBGRWdLZ3krVDhJYW1OMUhwR1JaRjhHRSt4N2dmSFFBamxMRmNVeFRpZm5RQng2UUlVT0gyck1uYWhuM3Y2aytkWGFzS2lqVXRGa3p1ZVcyMnlUeDRFSDlxUDlReVp2NjJUNmJQVnYzNUU2eTlSbWdibkswYmQ5ZTZqWm9JSTg5L3Jnc3N4SStOVHVUbDlVSmFzQ29LajFQZk9vcGFYTGhoYkxpcjcvMEkrWlVybHhaenJjRzhhYW9HYkNTSmMwZmhacGhQWGNmZlBpaE5HL1ZTaXJGeE5oSnVOcUcwY2RLVWxwZGZMRlVybHBWTHJDZTA5c0dEclJ2TUozK2VsZS9ON1UzRldlbmxycFhHamRXclFmWFBlN0lPSFJJZG80Y0xWa1o1cmNXWG4vOTlVYmZFNmRUeWJSYWxWTzNmbjE1Y1Bod1diNTgrVGtueXVxMXJGYnpxTzB3YWxWSW5YcjE1S291WGV6cjJabXU2MmV5YnQwNnVlT3V1enhaMlYwbDZFN2U1TnV3Y2FOODl2bm5lYnBHWjBkVmJ6ZDlJOUpKQWRZUDc5eFAveStxV05lbUxyR1N1akZPOTJRdmF0QkFpUjQyVkVmL2xKbWFLaHRhdGJmZi9EbHBzSGE1QkVaRzZnaC9TM3h6aHV4NXdzeXk4b1p4YXlRZ2ovczVUbTNiTGx1NlhpZVpTY202eDV5aVYxNG0xWjZmN3NwUmIyNVFWVk1UQmd6UzBabVY2QkVyTVpQUC9IdlBzajRRNGpySFNzckdUYm9uZXlXN2RaVXEweWJyeVArY2lvK1h1TXM2R3o4L1A3QklFYW16NERzSktST2xlM3pML1VPR3lJc3Z2YVFqNTkxdERUeW1UNXVtSSsvN2ErVkthZDZ5cGFNRGlKeW80N0JxV0ltVU9ndjQ3MlJLTGVmK2Zja1MyYmxybDZ0N0piUHp6dHR2Uzk4K2ZYVGtIRFZ6cmhJNXA1YnNxeUovWmFLaTdKc3NIVHQwa1BQUFA5OHVQRlc2ZEdtN1VycmFUNm0rMU1CWmZhbVpNMVdJN3BkZmZwSHZ2djllL3N6REFEMC9IbjNrRVJsdEpRZ21YZHV0bTN4ejJ2RkdYalQ0dnZ0azhxUkpPbkxXdXBidEpOMkZRbWZSazhaTG1lNnhPakxJdWk0bFBEWkdEci8va2U1d2lmWGVxdlRVT0lseTRXZjgyWG8vcW1KcUJaR3dsaTlmM2k0NDFySkZDNmxRc2FKOWJWYlhqckRRVUVtM3JobHFtYnE2cWFxS0k4YkZ4Y212aXhmTGdmMzc1ZWl4WS9wdnlMdW5Ka3lRb1M1c3F6a1g2bmZRdWswYis5cm9sTCt2d1U1UTEveTFxMWI1VElFNGhSbDBGSmp3NnRVazJycVFpd3QzdEU1OE8wOE96SmlwSXdESUh6VTRpN0NTWnJlb0dXUzEzUEt0R1ROazJqUFAyRitxdlg3REJrOGs1NmFvZ2E3YTQrM2tmbnAxVStWQVlxSzlkUHFweVpPbDMwMDN5WVhObWttMW1qV2xkTm15VXJWR0RYdlphWXlWd0t1NDVubm4yZnVnSDNuMFVmbnhwNTljVGM3VlRZTjc3N2xIUitiME1YQmp4V2t2dmZLS2JMS1NIZVNDV3VvKytGNEpLbGRXZDdqRWVtL3RuVGhaVXZmdDB4M21YTnk2ZFlFZG1hVldMYWtiQkpPZmZsb2VlUEJCdStaSHA4c3VremFYWENMdE8zYTBieHlvN1RocTVuM0d6Sm15ZWZObVI1SnpaZlRqajl2NzQ3MUV6VXgzNjlaTlI4NXdLamxYTG1qU3hLZVNjNFVFSFFXcTFGVlhTS20renU1ZHljNyt5ZE1sZVczQm5tMEp3RDlFUmtaS2h3NGRkQVFUVkhKKy8rREI4dnFiYitvZWQ2aVZDZkVKQ1k0TnFQTmowSjEzMmttNmFaZDI2aVRGaXhYVGtUZXBsUlFQUGZ5d2E2dFdmRjFJVkpSVUdqUEtsVW1RMDJVY09pd0p3eDh4dnlyTitybWVuakxGOFFKbFhuZktlaC9jMUwrLzdOaXhRL2Q0dzVXWFgyN1BWSHZSRFE0ZkJlY0dFblFVTE9zQ0d6MXFoSVNmYjc3Z1V0YXBVNUp3NzFESk9PNjlJaHNBZkUvUEhqMTBDMDVUU3lZZkhEWk1YbjM5ZGQxVCtEU29YMThlZnVnaEhabFZwa3dadWV5eXkzVGtYVjkvODQwcyt2RkhIZUZzU2x6YVNZcGQza2xIN2tuNmRiRWNuR1grRklraVJZckl6Qmt6N01KeGhjbSsvZnZ0V1hzdnJaNXExS2lSSjR1d2hZYUdTdGV1WFhYa08walFVZUFDdzhJazVvVm5KTEJZVWQxalR1cTI3Wkx3MEVoN0R6WUE1SWVhZFZRRFJEaExMVzE4Y3R3NGVmSGxsM1ZQNGFNR2xhOWFQMytZOWZub0JqWHo5Y2pERHp0Nm5yRUphdlo4K0VNUGNleGFMZ1VFQmtybHNhTWxLTXI4S294L3NINVBlOFpQa2xNNzRuV0hPWTBiTjVZM1gzL2RmczhVSnF2WHJKRkI5OXpqNkZMdy9GQXJHa3pVSU1tdnBoZGVLTldxdW55cWdRTkkwT0VKWVZVcVMvU1RqOXN6NnFZZC8yNmVIUHp3WXgwQlFONm9Ra0d4RHUrN015MHFLa291YWRkT1I5NmpFckJKa3lmTHVBa1RDdTFTWnBVa1B6TnRtalJ2M2x6M3VFTVZ5K3ZhcFl1T3ZFc1ZhSHhuSmpWbGNrc3RkYS93MElQMnZuUTNaU1VueTg3aEl5VExoU0p1cWtMMytDZWY5T3dTYTFNKy9PZ2ptZkwwMHpvcWVGMDdkN1lUZFMvcGYrT05Qdm02SUVHSFo1VHEybGxLOXJwT1J3WlpIeFo3eDArUzVIWHJkUWNBNU0yd0J4N3dtWmtiOWU5ODdlV1g3VXJ3WHFVR1VsMnNRVjZ0bWpWMVQrR2lCcmNQRHg4dXQ5MTZxKzV4ajNydXh6Nyt1R3V6OXZueHhMaHhkcTBBNUU1VTdMVlNwTzNGT25KUDhyTGxjdUN0R1RveVI3MTJWVEhGeHcyZmR1QkZVNmRQOTh3UmhPb21YNlhvYUIwVnZLSkZpOHBWVjEybEk5OUNnZzd2c0M2dzBTTkhTRmdkODVVV3M1SlBTdnhkOTBtR0gxYy9CbUJldlhyMTdEdjB2a0FOWHRWZXZKaVlHTjNqVFdxUTkvdml4ZmJadW9WcFJpdzRPRmhHUFBTUVBEWnFWSUg5M09yMXJJNTE4L3J6dm52M2Joay9jYUtPY0ZhQmdWSnA5RWdKaUlqUUhlN1ovK3lMa2hKdmZxbTd1cmsxNHVHSDVaV1hYcExJQXZnNUM0SmF2cjF3L254N1paUVhoSVNFeUkzOSt1bW80RjNVdEtsVXJGaFJSNzZGQkIyZUVsUzBpTVM4K0t3RUZqZGY4Q010UGtGMmpoeHQ3NVVDZ0x4UWljeVRUendoVlNwWDFqM2VvLzZOSTBlTWtBY2ZlTUNPNjV4M252Mm5seFVyV3RRdS92VEJ1KzlLeFFvVmRLLy9VdWZjUHp0OXVuM2VlVUV2RVgxZzZGRHAwTDY5anJ6clJTc1IyN2h4bzQ1d051SFZxa241WVVQc3lSQTNaWjQ0SWZGRGgwdW1DM1VEMUxYdTFsdHVrZG1mZlNabHk3cDh4SnlMU3BRb0lVK09IU3MvTFZvazlldlYwNzNlY0Yxc3JHZHFXVnpmdDYvbmJ6Wm1od1FkbmhOZW83cFVmTUpLbkYwWXBCeWJNMWNTUC9oSVJ3Qnc3dFF4V0srLytxb25sN3FyV1ZrMUkzcjZyR3k1Y3VYc1A3MU8vWHU3ZCs4dWZ5NWRLamYxNitjVFM2L3pvbXJWcXZMTm5EbHkrNEFCbmhoTXFsbXc5MmJPbEVibm42OTd2TWsrZG0zRWlFSmJxeUF2eXZUcExlRU42K3ZJUFNmL1dpVUgzbnBIUitaMTdOQkJmdi8xVi91c2RGOU4wTTVFSmI2WFhYcXAvUG5ISC9MUThPR2UvTXhScTNDOE1HdXRLdnVyMmdTK2lnUWRubFNxeTlWU3NxY0wrOUd0RC9aOTQ1NlNrM0diZFFjQW5MdU9IVHZLMUNsVENuejI4M1JxbWVjTHp6NHJqNDRjK1k5L1Y2bFNwWHhxMEtwbXdsNS83VFg1K2NjZnBYV3JWcDU2anZOREpjSzM5Tzh2UzM3N1RkcTJhYU43dlVFZHUvYkY3Tm1lVDlMVnNXdno1czNURWM0bU1DeFVxancxWGdMY3Z0bGxqYlVPUFArU3EyTXR0WlhudTdselpkd1RUOWg3a1gyWnVsNDNhTkJBdnZqc001bno1WmYyVFQydlVqY05lbmJ2cnFPQ282NnA2clBPVjVHZ3c1UFUwU0RxZlBTd3V1YVhZbWFxL2VpRDdwZU1wR1RkQXdEbmJ1RHR0OXVWaEwyUVFLb2w5M08rK2twdXZmWFcvL24zcUprRlZZSGVsNmdCNmdWTm1zaUNIMzZRTDYzRVVTWHF2a3p0amZ6ZVNoNWVlZmxseit3Zi9iZksxbXRJSlRocU50S0wxR3RDblVoUXljUGJTN3dvNHJ6YVVtYWcrMFVJTTVPVEpXSFl3NUtabHFaN3pGT3Jib1k5K0tEOHNYaXhkTHZtR3ArY1RhOWJwNDY4L2NZYjlvMjhLNjY0d2lkdVVIcmh1RFZmcjJGQ2dnN1BDaXBTUktwTW15eUJMcHd6bkxwNWkreDZiSXhkNFIwQThrSU5CdFQrM2JkZWY5M2VRMTBRMUwraDMvWFgyOHZDczV1VlZUTWNCZlh2eXkrMXhGTU5VaGN0V0NBTDVzMlRYajE3K3N4WjlPcDNveEx6OTk5OVYzNzkrV2RwWS8xK3ZENkFWRFBwYXNaT0ZhOEw5OUFXQTFVYzY0UDMzcFB2di8xV0d0UjNmOG0yVDdOZWMrWHZ1bFBDckVUZGJhZFdyNVY5ejcyb0kvZlVybDFiWm4zOHNmeTRjS0ZjY2ZubG5qL3ZYMUhMOHo5OC8zMVo4ZWVmY3IxMVRmZWxMVDVxbVh2MTZ0VjE1TDdpeFl2N3hKR1JPU0ZCaDZkRjFLMGpGY2VPc2w2cDVsK3FSei8vU2c3Ty9rSkhBSkEzYWpDMWRNa1NWODhiVjN2TjI3VnRLejh2V2lSdnZ2Rkdqa3Y3MU5KcU5ZdnV5MVJpMjliNmVkVmU2YTF4Y2ZMVXhJbHk0UVVYMk0rRDE2aUNUajJ1dTA1K1hMREFUc3g3OXVqaFU4djAxZXRsN0pneHNtVHhZdW5Vc1dPQlBjZXFrSjc2L3A5OThvbjlQSGEzbmxOLzJlN2dOclhVdmRLNE1lckNvWHZjay9qcUc1Szh2bUNPdVczVnNxVjg5Y1VYc2x6WHRTampzZFVyYXUrMk9tTHhMeXNwVjZ1RjFHdmNpOWUwczFIdjFkaHUzWFRrUG5XZDhQblB1Q3lEMVRXeTB0TmxVNWRZU2QwWXAzdXlGelZvb0VRUEc2cWpmMUtWSHplMGFpOFpodzdwbmpOcnNIYTVCRVpHNmdoL1MzeHpodXg1WW9LT25OVXdibzBFR0w1NFpHVm1Tc0tJUitYb3g1L3BIbk1DcklGSXphOCtrWWc2ZFhTUE54Mlp2MEFTQmd6UzBabVY2QkVyTVpQUC9IdlB5c2lRdU02eGtySnhrKzdKWHNsdVhlMlZEUDRxN2NBQjJUVnVvdldjbUYwOVlRK0lIbnRVZ2wwNG9jQ0VHZSs4SS9Pc0FZTXBsM2JxSkRmMzc2OGovNUJodmMrK21qTkh4b3dkSytzM2JMQmpweFd4UHZOVW92ckl3dzlMOCtiTmN6MHpwQ3BnLzJZbFhFNGFkT2VkMHJwMWF4MjVUejIvTytMajVRdHJBUDY1OWJWMjNUbzVldlNvZnRROTZ1WkJ5WklscGRsRkY5bUplVGRyb09yTGV5RlBsMmw5SHE5WXNjSSs0bXpCd29WeTRzUUovWWdaYXRhd1JvMGE5cDdXL2pmZFpDKzdONUdVSjR3Y0xlbkhqdW5JbktqciswanhWaTEwVlBEMnYvbTJKSzFZcVNQM2hKOVhXeXJlYzVjOW0xK1ExUFZoN3R5NU1tUG1UUGx6K1hJNWZQaXdmc1FkNm5xdGlveDJ1T1FTT3pGdjJiS2xSUHBKSHFNKzg4YU5INitqLzNVeU9WbSt0cDU3RTUrTDZzYXRXbDNseTBqUUN3RmZUOUNWRE91RGMvTjF2U1YxeXpiZFkwNVk3VnBTNjh0UEpEQThYUGQ0RHdrNjREdlMwdExrajZWTDVaVlhYcEc1MzM0cng2MmtKcStEa2tCclFLdG1ORlV5cmdZZ25hKysyazVhdkw1VTJtMXFhSFB3NEVGWnZYcTFmUHZkZC9iZ2U4a2ZmMGk2TlM1UlgwNVNNMXhxb0swUzhoYlc3K1ZxNjNlaWlxdXBKTjJmcWJQSXY3RUcyTE0rK2NSK2JrK2VQR2tuOFBtaFh0dHF4VUZySzFGUlMxVGJ0V3RuRjhUeWhTWEo4RzFIamh5eHJ4T3E4T0RpeFl0bDlabzE5clhDeVFSU1hTdlVsaHgxcmJqOHNzdWtmZnYyOWg3emlFSnlidnZwUHBzOVczcjM3YXNqNTZqbmQxZDh2TTlzZmNvT0NYb2g0QThKdXBLOGJyMXM3WG1EWkNXYkwrWldzbmNQcVRMaGlRSy91NXNkRW5UQU41MDZkVXJXV0FNL2xiRC8vdnZ2RXArUUlJbFdJaGx2RFNoVWduTTZ0ZiszZkxseWRoRXhWZlN0V2JObTByQmhRMm5jcUpIZkozOG1wRnBqaVowN2Q4cWF0V3Z0UHpmRnhjbldyVnZ0Z2JtYVNVdEtTckpuNE05RS9RNmlTcGUybjNlMXY3R2FsVFRXcTF0WHFzVEUyTCtUeXBVcUZjcEI5dC9VYzdmV2VsNVhybG9sNjlldnQyZlAxR3lrZWw2M2JOa2kveDVvVm9xT3RtY08xWmM2NS82Q0N5NlFtalZyU2lQcnRSMVRwUW9KT1FxY1doMnliZHMyZXlXT3VsNm9tMURIamgyenY5UTFZL2VlUFpKOGh2R29TZ3lqSzFhMGJ6U3A2NFc2Z2FwdTJLbXE4dWRiMTRvcTF1dGIzWWdxek5SblhZdldyZTFyaGRQNjNYQ0R2UFhHR3pyeVhTVG9oWUMvSk9pS09yTjh6eU9qZFdSV3BXY21TK2xydXVySVcwalFBZjl4dG85aFpzZk55KzFRaU4vRnVjbnBlZVc1aEsvS3pmV0MxM2YyWG52OWRSbDB6ejA2Y282NnNmZkRkOS9aQlRoOUhRbDZJWEJrOWhkeTRPWFhkZVNzV2w5L2JpWG9MdDdwdGw2dXU2YzlLeW1ienY2YXlxL0FZc1drOHBoUkV1VEIxeFFKT2dBQUFIekp2bjM3cFBFRkY4akJzK1IwZWFHMkMveTFmTGxmck1BaFFRZDhFQWs2QUFBQWZJVktPVys1OVZaNTc0TVBkSTl6MUlxRjExNTV4UzRtNlE4NG53SUFBQUFBWU16N1ZtSnVJamxYeXBVcko5ZkZ4dXJJOTVHZ0F3QUFBQUNNK1BYWFg0M3NPLy9iblFNSCt2elo1NmNqUVFjQUFBQUFPRzdWNnRYU3EwK2ZNMWE5ZDBMRmloWGx2bnZ2MVpGL0lFRUhBQUFBQURocS9vSUZjdmtWVjhqK0F3ZDBqL09HUC9pZ2ZmeWxQeUZCQndBQUFBQTRJaTB0VFo1LzRRVzVOamJXU01YMnY5V3RXMWNHM242N2p2d0hDVG9BQUFBQUlGOVVwZmIxNjlmTDFWMjZ5SkFISHBDVWxCVDlpUE5VNWZZcGt5WkphR2lvN3ZFZkpPZ0FBQUFBZ0R6YnNHR0QzRGxva0Z6WXJKa3MrdkZIM1d0T3J4NDk1SXJMTDllUmZ5RkJCd0FBQUFDY2swT0hEc25zenorWHpsMjZTS01MTHBBMzMzcEwwdFBUOWFQbVJGZXNLTTlNbjY0ai8wT0NEZ0FBQUFESVVWSlNrcXhidDA3ZWV2dHRpYjN1T3FsZXE1WmRvZjM3SDM2d2w3ZTdJVHc4WEQ1NDd6Mkppb3JTUGY2SEJCMEFBQUFBSUptWm1YTHExQ2w3ZG56RHhvM3kxWnc1TXVxeHgrVHlLNitVV25YcTJFdllCOTU1cDh6NTVodGpSNmRsSnpBd1VCNTc5RkZwM2JxMTd2RlBKT2dBQUFBQVVNaWRPSEZDV3JkcEk0MmFOSkVhdFd2TCtZMGJ5M1U5ZXNqRVNaTms0YUpGa3BpWUtCa1pHZnEvZGwrZlhyMWs2SkFoT3ZKZkpPZ0FBQUFBVU1nVktWSkVkdTdhSmR1MmI3ZVhzM3RKMnpadDVPV1hYcEtnb0NEZDQ3OUkwQUVBQUFDZ2tGTkhsN1Z1MVVwSDN0SDB3Z3ZsMDFtekpDSWlRdmY0TnhKMEFBQUFBSURVT2U4ODNmS0dpMXUzbHJuZmZDT2xTcFhTUGY2UEJCMEFBQUFBSU0yYU5kT3RncVZtODYvcDBrVytuak5IU3BVc3FYc0xCeEowQUFBQUFJQlVxVnhadHdxT1NzNkgzSCsvZlBqQkIxSWtNbEwzRmg0azZBQUFBQUFBaVltSmtXTEZpdW5JZlNWS2xKQjNaOHlRcHlaT2xKQ1FFTjFidUpDZ0F3QUFBQUNrZVBIaUVoNFdwaVAzQkFZRXlHV1hYaXJMbHk2VlhyMTY2ZDdDaVFRZEFBQUFBR0RQV3J1OUR6MjZZa1Y1NmNVWDVhc3Z2ckJuOEFzN0VuUUFBQUFBZ0sxQmd3YTZaVlprUklUY1BXaVFyRnl4UW02OTVaWkNjY1o1YnBDZ0F3QUFBQUJzRnpacG9sdG1oSWVIeXgwREI4ckt2LzZTNlZPblNzbENWcVg5YkVqUUFRQUFBQUMyT25YcTZKYXpxc2JFeU5qSEg1Zk5HemZLODg4K0s5V3FWdFdQNEhRazZBQUFBQUFBVzNSMHRCUXRVa1JIK1ZQSitydjZYWCs5ZkQ5M3JteGN2MTVHUFB5d2xDOWZYaitLTXlGQkJ3QUFBQURZaWhZdEt1WHltRVNyLzIrZDg4NlRPKys0UXhiTm55OGIxcTJUdDk1OFV6cDA2TUFlODF3aVFRY0FBQUFBMk1MQ3dpU21TaFVkblZsQVFJQmQ1RTN0SDI5L3lTVnkzNzMzeXR5dnY1WU5hOWZhUmQrZWUrWVp1ZmppaSszOTVqZzNKT2dBQUFBQWdQOXEyYUtGL1dlNXNtV2xjZVBHMHJGREI3a3VOdFplb2o1enhneVpQMitlckxlUzhWM3g4VEx2dSsvazZjbVQ1ZEpPbmV6bDY4eVU1dzhKT2dBQUFBRGd2MFk5K3Fpa25Ub2x1eElTWk5tU0pmTGQzTG55MFFjZjJFWGUrdlR1TFczYnRMSDNxb2VHaHVyL0I1eENnZzRBQUFBQStDOFM3NEpEZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIdUFqQ1hxQS9iK3p5VHgxU3JjQS81YVpmRkszY2hERS9UY0FBQURBbC9qRUNENHdORVNDaWhYVFVmYVNWcTNSTGNDL25WeTJYTGV5RnhKVlJyY0FBQUFBK0FLZm1XSUx2NkN4Ym1YdjZOZHpkUXZ3WDFscGFYTHNoL2s2eWw1bzVXamRBZ0FBQU9BTGZDWkJqenkvb1c1bDc4UzhCWkorNkpDT0FQOTA3SmRmSlgzUFBoMWxMN0pGTTkwQ0FBQUE0QXQ4SmtFdmVuRXI2MStiODBiMGpLTkhaZmRUVDR0a1p1b2V3TDlrSkNmTDN2R1RSTEt5ZE0rWkJaVXZKK0hWcXVrSUFBQUFnQy93bVFROXJGcFZDYTFlWFVmWk8vcnA1NUw0eVdjNkF2eEhWbnE2N0JvNVdsSTNiOVU5MlN2ZXFZTUVCUHJNMnhzQUFBQ0F4V2RHOElHaG9WS3FWM2NkNVNBalEvYU9mRndPdlBPdVpGbHR3QjlrSkNWSi9JTVB5OUV2NXVpZUhGaUplYW5lUFhRQUFBQUF3RmY0MUJSYlZOL2VFbFNxcEk2eXAyWWE5ejQrVHJiZmZwZWMycnFOSmUvd1dlcTFmT3luWDJUenRUM2xtRXJPejdLMFhZbHNjWkVVeVVYTkJnQUFBQURlRXBCbDBXM0hxZVJpVTVkWVNkMFlwM3V5RnpWb29FUVBHNnFqN08xLzVYWFpOM0dLanM0dUlEaFlJcG8xbGFMdDIwbEVyUm9TVkxhc2ZnVHdxS3hNU1l2ZkpTYzNicFRqMy84Z0taczI2d2ZPTGlBMFJHcDgrb0ZFTnN3NVFWZXJTK0k2eDByS3hrMjZKM3NsdTNXVkt0TW02d2dBQUFDQUtUNlhvR2VtcHNubTJKNlNzbTZEN2dId3QxSTNYUytWeHp5bW8reVJvQU1BQUFEZTQzTlZwQUpEUTZUSzFFa1NXS1NJN2dHZ2hOV3ZLOUVqaHVzSUFBQUFnSzh4bTZBSEJGai95L2xvdFA5S1Q5ZU5zNHVvYzU1VW1qNUpBa0pDZEE5UXVBVlhLQy9WWG45SkFzUERkYzlacUhVenVWdzhvN2FKQUFBQUFERFBlSUllR0ptN21lN2NIQjExdXBLZE9rckY4V1BzUGJkQVlSWVVWVnFxdmYyYWhGYXNxSHZPTGlzdFZUS09IOWRSem9LclY5VXRBQUFBQUNZWlRkRFZPY3pCdWFpNnJwemFzVU8zY3NsSy9xTjZYQ2RWWG5sQkFvc1gwNTFBNFJKYXA3YlUrT1I5ZTFYSnVVZy9kRmpTOXgvUVVjNUNLbFRRTFFBQUFBQW1HZCtESG5aK2ZkM0tXZHFXYlpLeWM2ZU9jcTlFKzNaUzY4dFBKS0o1VTkwRCtEKzE3THhrMzE1UzY3T1BKTHhhTmQyYmU4Y1gveTZTa2FHakhBUUVTRmlWeWpvQUFBQUFZSkx4QkQzaXZOelA3QjMrK0RQZE9qZGhWYXRLemZmZmtlaEo0eVNrYWhYZEMvaWhvQ0NKYUhhaFZQLzRYYWt5Ym93RVJVYnFCM0pQVlhBLy9QRW5Pc3BaWUVTNGhGVS85eHNBQUFBQUFNNmQwV1BXbExURWc3S2hSVnVSekV6ZGs3MlF5cFhrdk8vbldFbEJoTzQ1ZDVrcEtYTHN4NS9sNER2dnlxblZheVh6V083MjJRS2VwYmFLUkpXV3lOWXRwY3lBbXlXeVhqMEpzQkwxdkVwYXRWcTJkZTlySDRONE5xRTFxa3VkSDc2eFo5SUJBQUFBbUdVOFFWYzJYZHREVWxhdDBWSE95ZzY1VnlyY2Q3ZU84aWY5eUJFNXVYR1RKQzlmSVNtYk5rdjZzV09TbFpxbUh3VzhLeWd5UW9LS0Y1ZndDeHBMa1NhTkpheGFOYnN2djFSU3ZxWHZUWEp5MlhMZGs3UFN0L1dYU28rTzBCRUFBQUFBazF4SjBQZTkvSnJzZitwcEhlVXNNREpTcW4veW5qMUxDTUJaQjk1NVQvWSsvbVR1amxnTENwU2FYMzRxa2ZWNUx3SUFBQUJ1TUw0SFhTblorYXBjTDhuTlRFNlcrRHZ2eTFQQk9BRFpPN3J3UjlrM2JtS3V6ejhQcTFWVElzNnJyU01BQUFBQXBybVNvS3NxMEVXdnZrSkhaNWNXbnlCYis5d29KemR2MFQwQThzeEt5STk4KzcwazNIWHZPVzN4aUxybEpydGFQQUFBQUFCM3VKS2dLK1h1dlAyY0J2dnB1L2JJMXRqZWN1anpMM05WekFyQS84bzRjVUoyVFpna0NmY01rYXlVVk4xN2RpSFZxa3FwMkd0MUJBQUFBTUFOcmlYb2tmWHFTdkhZcmpyS25VeVZYQXg5U0xiY2NMT2NXTHFNUkIzSXBjeFRwK1RncDdNbDdvcXVjdWkxdDNKMzV2bmZBZ0trM0gyREpEQTBWSGNBQUFBQWNJTXJSZUwrbG5ZZ1VlSTZkNU1NNjg5elppVU5vVFZyU05GMkYwdVJDNXJZN2FBU0pmU0RRQ0dYbFNucCt3L0lxVTF4a3JSa3FaejRkYkZrV0hGZUZMSGVZOVhmZWswQ0FsMjdmd2NBQUFEQTRtcUNyaHo1WVlHOUYxYlN6MkZHTHp1Y3pRejhQd2ZleW9FbGlrdXRPYk1sckhJbDNRTUFBQURBTGE0bjZDcUoyRFBwYVVsOCtYWGRBY0FMQXNKQ0plYlZGNlY0dXphNkJ3QUFBSUNiM0YvREdoQWdGUjRjSWlXdW93QVY0QmxCZ1ZKaDlFaVNjd0FBQUtBQUZjZ21VM1VtZXVWeFk2VG9wUjEwRDRBQ0V4Z281UjRZTEdYNjlOSWRBQUFBQUFxQyswdmNUNU9WbWlvN0h4c3JSejc2UlBjQWNKTmExbDV4ekNpSjZ0MVQ5d0FBQUFBb0tBV2FvTnVzYjUvNDNnZXliOElVeVV4TzFwMEFUQXVKcVN5VnAweVVvczB1MGowQUFBQUFDbExCSitqYXFlM2JaZWVESStUazhoVlcwcTQ3QVRndUlEUlVTbHpiUmFJZmUwU0NpaGJWdlFBQUFBQUttbWNTZENVclBWMk9mUCtEN0pzOFRkSjJ4TnV6NndDY0VSQVNMQkZOR3R0TDJpUHIxckU2T0tZUUFBQUE4QkpQSmVoL3kweEprZU8vTHBiRU45NldrMzhzc3hOM0FIbGdKZUdCUlNLbDJHV2RwTXl0TjBsay9mcDJVVGdBQUFBQTN1UEpCUDEwcWZ2M3kvRkZQMG5TYjcvTHlZMmJKRzNMTnNsS1M5T1BBdmkzQUNzaEQ2dFZVeUlibnk5RjI3YVJvcTFhU0ZDUkl2cFJBQUFBQUY3bCtRVDlINngvcXBwTlR6dDhSREpPSEpmMGc0Y2tLek5UUHdnVVhvSGhZUkpVdklRRWx5d3B3U1dLU3dDejVBQUFBSURQOGEwRUhRQUFBQUFBUDhVMEd3QUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQUZUdVQvQUVpNFBoc1dEcENoQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI4N2RiYzVhMTRjOTQ0ZGM4OGE0Nzk3ZDgwMGZkMWYzYyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo2LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjE5MiwidHJhbnNwb3J0cyI6WyJ1c2IiXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMiIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA3LTE4IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJlV0JNIGVGQTMyMCBGSURPMiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxOTA3MDkwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy40IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNy0xOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDctMTgifSx7ImFhaWQiOiI0ZTRlIzQwMGEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhaWQiOiI0ZTRlIzQwMGEiLCJkZXNjcmlwdGlvbiI6IlRvdWNoIElEIG9yIEZhY2UgSUQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MjU2LCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9LHsibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjAsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbImFueSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFZ0FBQUJJQ0FZQUFBQlY3Yk5IQUFBQUFYTlNSMElBcnM0YzZRQUFBQnhwUkU5VUFBQUFBZ0FBQUFBQUFBQWtBQUFBS0FBQUFDUUFBQUFrQUFBRkpidUoyRWtBQUFUeFNVUkJWSGdCN0pZeGJpTkhFRVVGSjE0WUM1akpBZ3NuSHNPT0hQRUFDMmh5QitJTk5LRXpNblNtdWNCaWVRUHlCbUxnbkx5QmVBUFNKMWplZ0g2ZjZocVV5OVBhWGcwSk8rQUFYOTFkVlYzOS81L21RRGZINC9IbWlyd0hWM08rY0VHdUJsME55djk4U2o0dDF4dDB2VUhYRzNUUlg4R2c1amNEbjU5L3JMNERIOEFNYkJ4V3pGdndHM2cvOEpoaEdrcytWTG1hMXhKSDlBVEloR01oWkY3ejJ2TnkvRXZpdzl6OVNzYUlyTUcrMEpRKzg3UjM4cFhIRHROWTRtS3VwcFFvb2taZ0hveFpzLzRFcHVEMkJTaXZPdFdiYWJwOW85THpjL3hMNHNQY0xXQ0lrQXBzd1djZ29iZDkyNGlycm5ZWXh6cHlNdm9PTE1CZjRGODFjWS9XSlVia2FvWnQ3bVBqWWhJQS9nUjNMbnpEV21iTXdBcnNnZDJNdmxINURXaEJad2h6bWZVNytOWDM3cHZueEpmRUwyWVF4TitERDBhWXVRVEpsQzNvTTZJMGRtRC9IRlN1OXp1Yjk0MGxSdVJxTG1JUTVMODFvaElDOVBZbHJOU0UwanJkckZwbk1YNWpaOFl4Sjc0a2ZoR0RqQ0NrWnlCbnpJN2NBa3pCTGFoc240MHBybStPdmwxUElHZmNpdHdQdGkrT0pVYmthaTVpRUdUSFlOc2o2RE14aWUyK0pWSE1TMnYyNlRaT2djeU5adWxGOVBiTmlTK0puOTBnU09vL1k1SDFBbVRNQXhoNUE3UUdOWmlCRnN6QkJxelNXckVKcVB3K3pZbmRneDA0QnZ3VWEwdU15TldjMVNDSXlweEkrSkZZWmFTWmowQURaRVNzZldtOXAzNEphdXVsa2JWdWxGNkE3ZDM0dk9ZNThTWHhZWnNkRXdpK2RTUkZWcVFiVnlJeExUZ0FFL1BhY2U5N002L0FrK3RiKzNOTGpNalZuTk9ncFNNb2M3cnZnZVpnNi9MUm1EVTU0Y0hoTWNYVTY1aUJqT3JNWVA0cDFXMytWd1pCNnZ0RVRFSWt5SnZUc0k2M1JqVUwwUHRmdFJlbnVmcUJLWGdDZldiTmlaKytiNHc2VHpXMTljbmRqcEw0V1c0UVpHYUpWSjg1VVpDTStjZkgyb1JvbERDRGo5dWNuTXhhZzloM1M4eWJ0TFE5SlVia2FzNWxrTWlKY0dPa05FOHhFeUx6YXN0clpEMUtkU3ZHUGJCYVB4NklLNjkrbmJITWE3QURzWGFjZW5mMU9mRWw4Y0VHUVhDY1NENmFlTllpNTRuSG0xV1JYNFlhWDUrYnl5enRxNUlKSSthTDBFYzFadEl2cWlzeElsY3piRE9IUTJZRzlHMnc2ejFtN2dWR2MxUXZFYjdtTmZOVzR2WFE2eUgwMjdQdWJsdE9mRW44SEFiTmpReWp6UEhpb3psNis5RU0xU3pBSFRpOStXZlpKK0ZWaWl1dnVyaDNROHhlVEJQeUcrdFRZa1N1WnJCQlJrSkV3VGFRN0FRVGx4Z3ZVSUx2UWZlbW1jdmdHV2dUYXV1dmtaanFvMUU2MDB4YU1QZG50TnFYRTE4U0g3WlpwNmNIWXRHY3h1V1dnZmlqaVZJTjh3blloeG92VlB1clZEdGlydjArNzAxYWg5emJFaU55TldjeENFTFJnRlppOUpDYkJjS0w1OHp6MzU2OVhuaWN6MjB2KzZhaDcwWTVZakxRMzdJbUo3NGtQc2dnaUx3QksrQ0ZkQVlRYjBMdWliWDlIQ1JrRy9McW81cDFnaGRxWjJpUDlZajlUd2FTOS9GTmlSRzVtcUVHZllTTUVkZm96Um1IM0pmTVVYNXNOOFJHWXZkZ0YzcDVreFloZCtwQmJKM2kvNmxCRzBjdW1uTndPZDJFVGp4ekNUdzYrTDBWOFNWUTd6blFlZ1NpRVZ0bm9zeTFmcWM0NjdIRmNyZWpKRDcwQmttRWlEMDRzaUoyTUhLTTBSeUpOekVhdlRsdHlGbGRvLzZxRGZsNWluZG1wTHpWcjdVdU1TSlhNOVNnUHlCUWlhUWU1ZzN3NWtoZ2Mwbys1NWVzVGJSR2IwN00rYnF1ai9hRUhyWDZFL1A3OXlsV3F6WW52aVEreUNDUnNBY2k4MEJjTjJmaThsNUFOS2NOZS9XVGVRQzdFQitySDdHK24xUVZhazlucTdiRWlGek4zd0FBQVAvL1g5TGxQd0FBQlBOSlJFRlU3VnE3amlOVkZCd2tKQkNzdEIwUUVleTJJR1NEenBhTURzbldNY2wyU0xDU0hSQnNOdjRBeERnaVFuTC93WFJBUGkzeEFUYjhnUDBIMjM4d1ZMVlBtZG9yejROeDBHM0pWNm81OTlZNTUvcFV6WjFaYVRVWHQ3ZTNGMC9GQmRhM0wvTUNXQU8zaGcva21lZkNmbVk1MXEyQUxITFZQYmtzYW5YM2xuMUFrZlJVY1ZkdGZCUGM3S242MlBka2M5aU1ZZDdaUUJKQjhUbUg0OExlaDA3Tm9kRE83dGdidCt2ZWZ3Tm91TzVmSExoM0cxeHFYSTYrZkVpRFdodWNBcTZBL21VY0VQR1FPVFNCZ2lZQTd5WG1RQlZSQmpIbUFlY204WmswV2Z5TTNKQUdOVEhNQnJIa01GellaMEFiT1EzTHdYdnpFUG1kN3BKOEdiMnF2eS9XVVZ2YkhVMXdNK05hY2tNYTlCN0RYSElJTFp4TElCWHY1bFFIOHBYMTh5WGRaNDV5ZVh5V3pvd1pVQ1Q5ejRZMDZETVR4b0diWkRnT3ZRVDBjbWlPQzZJWkU5M0JpRFB2bVFLWHdCV3dBYnhIKzBYVWU3Ni9LK2w1UFpoQkpxakdVT21yb1pBcGE3aXdaNDNFTWRLY1lwZTkveXZxU21BRmVQK1dYZUQ4WHBubVhEbVlRUmp1eTJSb0NhQ1lYanhpRHF5VHVvL01RVzRDVUZScjRHdXNnRXoyWWI4RTlCbjRON2czaURYaTFzSE5qQ3NHTXlpRzJkZ3dGUDZXUEJmMkhMU3pQSVhRdkY0MFlnbHNBUW04S3k2c1p4bjFxL2lNM1B1RDQ3MjZLeHZhSUE2L0Fkd1lEdGpha0JyMmlnSzRrR09mK01mRU5lcjdWN203NGIrdnlUMTlUWEM5aVVNYjlGeWpZcWk3ak9ITG1saGRuWWpxRFFhWHN3WXhBOTRBUzhETjY1alRQWXJnK0NwVlY1SVBic0g5b0FiRk1EOWhJSDZITmFUSEpmaTlLT3hUYy9hdmluZWxDL1VsUUlOMVozdWdwclY4eVR6TzVBcnV4MkJRYlFOS3lBMjRrZ055WWM5WHdhR1ZaNno2NUM1ZjRkeEVEZVBFY2dYT2J0SytqelhSbzN0bndmV1IrekVZVkdKSURYaU5mY25CdEhDZUFKM1Y3TTBCbHdHcGNicXJZWjczSVBJTzhWdmRIVG52bndkWE1uSU5iaENId1BDL0FEbjNXamlYZ0E5UGdYd0pGV3NRYWM0YWtQQkRzV1l0RitwdXJOWmZtSDlHRmJYUEdMbEdZZEJ1bEY1RUFSRUxZR3RpSkh3RnJtQXRZbW9PalpzQ2VVVDFNSmJSVTJFdmZrR09DMXhyZk5tVDltVTBCbUhJZjJ4UUNXSHN4V3RtbkduaTJtcVo3NDJ6bXBubEcvSTQ1OGExVnJzMXZoU3ZPQ2FEU2h1VXhtd0F2b3BNdzJJL0FUcEFCdTdOQWNkK3IyV3VyN04rOVhVSE9PWStGNjg0R29NNEVBYjhEYmdDQ2cwWVBNVzNnQVF5dWpsMTVGeTQxK2R4ejc3ZjdoWDNON2wwamNvZ0h3NkNDNEEvS3VzUUx5R01LeUJuUFNKclBOZS9JbkJ1VUlZem9ibzJldWZHdlNLWHJ0RVpoSUZmQVZzYlhLSVkrV3FtRW9GOWxkVE5tUVBuWm53SWJtSzFUWERyNEJZOEgxcWpNNGhEWXVoVStBYmNKZEMvanFpWmhUZ2FSeXdsRVB1NTVlcW9yNDFqYng3bmEvVWRpcU0wS0FUOURBSDhmZlRHQjhjNUF4cEF4cVRtRkVtdWpKN09lSm96Qi9panVqZmRQMGY3MFJxa0FSVXBKRVM1ME5RYzFtd0JtZGUvRHB3WHhqWFlzKzVQUnQxL1Z4eTlRUkR4QXZnZDZBQUpWNXhLR0hJVXZiYWFUWENGY2V6amkvcFJmUS9GMFJ0RUFSQ1VBemVBak9FK2x6anNhVUpuZWY0eUo1Y0JhK04veGY0TDlUMG1ub1JCRWdKeHI0SHZkV2JFZVFiSU9FWTNwNDBjdWVrM0wxNSs0cjJQMlorVVFTNElncjhDL2dnRFpOQUdaNzJjdjdDL0J0NEN6NzMzLyt4UDFpQ0poSGorR1AwQWZBZDhHdmhhK1dQallBWWQ4OEduMG52VS81V2Npc2hqNWp3YjlNQ2YvNXdOT2h2MDlEOFE0NC9tK1FXZFg5QnhMK2hmVXdUWXlSQ2FyWjhBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wNS0xOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTgtMDUtMTkifSx7ImFhZ3VpZCI6IjlmMGQ4MTUwLWJhYTUtNGMwMC05Mjk5LWFkNjJjOGJiNGU4NyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiOWYwZDgxNTAtYmFhNS00YzAwLTkyOTktYWQ2MmM4YmI0ZTg3IiwiZGVzY3JpcHRpb24iOiJHb1RydXN0IElkZW0gQ2FyZCBGSURPMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCcURDQ0FVK2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakE3TVNBd0hnWURWUVFEREJkSGIxUnlkWE4wSUVaSlJFOHlJRkp2YjNRZ1EwRWdNakVYTUJVR0ExVUVDZ3dPUjI5VWNuVnpkRWxFSUVsdVl5NHdJQmNOTWpFd016QXlNRFl5TXpFM1doZ1BNakExTVRBeU1qTXdOakl6TVRkYU1Ec3hJREFlQmdOVkJBTU1GMGR2VkhKMWMzUWdSa2xFVHpJZ1VtOXZkQ0JEUVNBeU1SY3dGUVlEVlFRS0RBNUhiMVJ5ZFhOMFNVUWdTVzVqTGpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkE3Nlp5RzNlK0Rab1cvS3ZNMzZYSkFKNkJMOWtYTU5qRXY0cUdJRDVsQThaOHVSZU0xWWZNaW81bkVITFUyU1pMUTNxWFJSdnhHTjRJK0g1KzZmVncyalFqQkFNQThHQTFVZEV3UUlNQVlCQWY4Q0FRQXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01CMEdBMVVkRGdRV0JCUnMrVWttTTV4VWs2L3o1UU50V0IyNmk0dzc3REFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUJBK0lYNUYvODdXL2VtWmtpSlRIcXJpTEZaT2E3OTd6c0UvMEtQN0FVNVFnSWdCNjR4RnFQU0JDNEtpMVVyck5YOVYydGhiKzQ1UmJ0U1ZtaTY2V1YrZ2xFPSIsIk1JSUJ6akNDQVhPZ0F3SUJBZ0lKQU1oVi92UVl1NEtBTUFvR0NDcUdTTTQ5QkFNQ01Ec3hJREFlQmdOVkJBTU1GMGR2VkhKMWMzUWdSa2xFVHpJZ1VtOXZkQ0JEUVNBeU1SY3dGUVlEVlFRS0RBNUhiMVJ5ZFhOMFNVUWdTVzVqTGpBZUZ3MHhPVEV5TURRd056QXpNREZhRncwME9URXhNall3TnpBek1ERmFNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXlNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJKSGdLOWZOcU5FV0lZVHNaL2dOaTE3enBFcks3RkMxWW8rRnpxUlZNWUdVSmdBSjl2ZzMxaVRDSjFWWXhiQUtNUWJsTEdrVm4vZGZQNzNnZVRLZWQ5T2pZREJlTUF3R0ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01CMEdBMVVkRGdRV0JCUmdMWFdkV2VyMWtTR3BwZ1BsaVppMUhzWVBoREFmQmdOVkhTTUVHREFXZ0JSZ0xYV2RXZXIxa1NHcHBnUGxpWmkxSHNZUGhEQUtCZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF1anJLV1p3K1MwVGZHMWJKSmNzcW1HdTVXTGJCMkVnb3JEMmhBMnE2Qm9JQ0lRQ2l5eG52QW42TWkrRGRSbnczU1FHUVpvTEtGS3dIcjRYR05JTzVwQUhBSEE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFqQ0FZQUFBRDE3Z2hhQUFBQUJHZEJUVUVBQUxHT2ZQdFJrd0FBQUNCalNGSk5BQUNIRHdBQWpBOEFBUDFTQUFDQlFBQUFmWGtBQU9tTEFBQTg1UUFBR2N4elBJVjNBQUFLTDJsRFExQkpRME1nVUhKdlptbHNaUUFBU01lZGxuZFVWTmNXaDgrOWQzcWh6VERTR1hxVExqQ0E5QzRnSFFSUkdHWUdHTW9Bd3d4TmJJaW9RRVFSRVFGRmtLQ0FBYU9oU0t5SVlpRW9xR0FQU0JCUVlqQ0txS2hrUnRaS2ZIbDU3K1hsOThlOTM5cG43M1AzMlh1ZnRTNEFKRThmTGk4RmxnSWdtU2ZnQjNvNDAxZUZSOUN4L1FBR2VJQUJwZ0F3V2VtcHZrSHV3VUFrTHpjWGVycklDZnlMM2d3QlNQeStaZWpwVDZlRC8wL1NyRlMrQUFESVg4VG1iRTQ2UzhUNUlrN0tGS1NLN1RNaXBzWWtpaGxHaVprdlNsREVjbUtPVytTbG4zMFcyVkhNN0dRZVc4VGluRlBaeVd3eDk0aDRlNGFRSTJMRVI4UUZHVnhPcG9odmkxZ3pTWmpNRmZGYmNXd3loNWtPQUlva3RnczRySGdSbTRpWXhBOE9kQkh4Y2dCd3BMZ3ZPT1lMRm5DeUJPSkR1YVNrWnZPNWNmRUN1aTVMajI1cWJjMmdlM0l5a3pnQ2dhRS9rNVhJNUxQcExpbkpxVXhlTmdDTFovNHNHWEZ0NmFJaVc1cGFXMW9hbWhtWmZsR28vN3I0TnlYdTdTSzlDdmpjTTRqVzk0ZnRyL3hTNmdCZ3pJcHFzK3NQVzh4K0FEcTJBaUIzL3crYjVpRUFKRVY5YTcveHhYbG80bm1KRndoU2JZeU5Nek16amJnY2xwRzRvTC9yZnpyOERYM3hQU1B4ZHIrWGgrN0tpV1VLa3dSMGNkMVlLVWtwUWo0OVBaWEo0dEFOL3p6RS96andyL05ZR3NpSjVmQTVQRkZFcUdqS3VMdzRVYnQ1Yks2QW04S2pjM24vcVluL01PeFBXcHhya1NqMW53QTF5Z2hJM2FBQzVPYytnS0lRQVJKNVVOejEzL3ZtZ3c4RjRwc1hwanF4T1BlZkJmMzdybkNKK0pIT2pmc2M1eElZVEdjSitSbUxhK0pyQ2RDQUFDUUJGY2dERmFBQmRJRWhNQU5Xd0JZNEFqZXdBdmlCWUJBTzFnSVdpQWZKZ0E4eVFTN1lEQXBBRWRnRjlvSktVQVBxUVNOb0FTZEFCemdOTG9ETDREcTRDZTZBQjJBRWpJUG5ZQWE4QWZNUUJHRWhNa1NCNUNGVlNBc3lnTXdnQm1RUHVVRStVQ0FVRGtWRGNSQVBFa0s1MEJhb0NDcUZLcUZhcUJINkZqb0ZYWUN1UWdQUVBXZ1Vtb0oraGQ3RENFeUNxYkF5ckEwYnd3ellDZmFHZytFMWNCeWNCdWZBK2ZCT3VBS3VnNC9CN2ZBRitEcDhCeDZCbjhPekNFQ0lDQTFSUXd3UkJ1S0MrQ0VSU0N6Q1J6WWdoVWc1VW9lMElGMUlMM0lMR1VHbWtYY29ESXFDb3FNTVViWW9UMVFJaW9WS1EyMUFGYU1xVVVkUjdhZ2UxQzNVS0dvRzlRbE5SaXVoRGRBMmFDLzBLblFjT2hOZGdDNUhONkRiMEpmUWQ5RGo2RGNZRElhRzBjRllZVHd4NFpnRXpEcE1NZVlBcGhWekhqT0FHY1BNWXJGWWVhd0IxZzdyaDJWaUJkZ0M3SDdzTWV3NTdDQjJIUHNXUjhTcDRzeHc3cmdJSEErWGh5dkhOZUhPNGdaeEU3aDV2QlJlQzIrRDk4T3o4ZG40RW53OXZndC9BeitPbnlkSUUzUUlkb1JnUWdKaE02R0MwRUs0UkhoSWVFVWtFdFdKMXNRQUlwZTRpVmhCUEU2OFFod2x2aVBKa1BSSkxxUklrcEMwazNTRWRKNTBqL1NLVENacmt4M0pFV1FCZVNlNWtYeVIvSmo4Vm9JaVlTVGhKY0dXMkNoUkpkRXVNU2p4UWhJdnFTWHBKTGxXTWtleVhQS2s1QTNKYVNtOGxMYVVpeFJUYW9OVWxkUXBxV0dwV1dtS3RLbTBuM1N5ZExGMGsvUlY2VWtackl5MmpKc01XeVpmNXJETVJaa3hDa0xSb0xoUVdKUXRsSHJLSmNvNEZVUFZvWHBSRTZoRjFHK28vZFFaV1JuWlpiS2hzbG15VmJKblpFZG9DRTJiNWtWTG9wWFFUdENHYU8rWEtDOXhXc0pac21OSnk1TEJKWE55aW5LT2NoeTVRcmxXdVR0eTcrWHA4bTd5aWZLNzVUdmtIeW1nRlBRVkFoUXlGUTRxWEZLWVZxUXEyaXF5RkFzVlR5amVWNEtWOUpVQ2xkWXBIVmJxVTVwVlZsSDJVRTVWM3E5OFVYbGFoYWJpcUpLZ1VxWnlWbVZLbGFKcXI4cFZMVk05cC9xTUxrdDNvaWZSSytnOTlCazFKVFZQTmFGYXJWcS8ycnk2am5xSWVwNTZxL29qRFlJR1F5TldvMHlqVzJOR1UxWFRWek5YczFuenZoWmVpNkVWcjdWUHExZHJUbHRITzB4N20zYUg5cVNPbkk2WFRvNU9zODVEWGJLdWcyNmFicDN1YlQyTUhrTXZVZStBM2sxOVdOOUNQMTYvU3YrR0FXeGdhY0ExT0dBd3NCUzkxSG9wYjJuZDBtRkRrcUdUWVlaaHMrR29FYzNJeHlqUHFNUG9oYkdtY1lUeGJ1TmU0MDhtRmlaSkp2VW1EMHhsVEZlWTVwbDJtZjVxcG0vR01xc3l1MjFPTm5jMzMyamVhZjV5bWNFeXpyS0R5KzVhVUN4OExiWlpkRnQ4dExTeTVGdTJXRTVaYVZwRlcxVmJEVE9vREg5R01lT0tOZHJhMlhxajlXbnJkemFXTmdLYkV6YS8yQnJhSnRvMjJVNHUxMW5PV1Y2L2ZNeE8zWTVwVjJzM1lrKzNqN1kvWkQvaW9PYkFkS2h6ZU9LbzRjaDJiSENjY05KelNuQTY1dlRDMmNTWjc5em1QT2RpNDdMZTVid3I0dXJoV3VqYTd5YmpGdUpXNmZiWVhkMDl6cjNaZmNiRHdtT2R4M2xQdEtlMzUyN1BZUzlsTDVaWG85Zk1DcXNWNjFmMGVKTzhnN3dydlovNDZQdndmYnA4WWQ4VnZudDhINjdVV3NsYjJlRUgvTHo4OXZnOTh0ZnhUL1AvUGdBVDRCOVFGZkEwMERRd043QTNpQklVRmRRVTlDYllPYmdrK0VHSWJvZ3dwRHRVTWpReXRERjBMc3cxckRSc1pKWHhxdldycm9jcmhIUERPeU93RWFFUkRSR3pxOTFXNzEwOUhta1JXUkE1dEVablRkYWFxMnNWMWlhdFBSTWxHY1dNT2htTmpnNkxib3Ird1BSajFqRm5ZN3hpcW1ObVdDNnNmYXpuYkVkMkdYdUtZOGNwNVV6RTJzV1d4azdHMmNYdGladUtkNGd2ajUvbXVuQXJ1UzhUUEJOcUV1WVMvUktQSkM0a2hTVzFKdU9TbzVOUDhXUjRpYnllRkpXVXJKU0JWSVBVZ3RTUk5KdTB2V2t6Zkc5K1F6cVV2aWE5VTBBVi9VejFDWFdGVzRXakdmWVpWUmx2TTBNelQyWkpaL0d5K3JMMXMzZGtUK1M0NTN5OURyV090YTQ3VnkxM2MrN29lcWYxdFJ1Z0RURWJ1amRxYk16Zk9MN0pZOVBSellUTmladC95RFBKSzgxN3ZTVnNTMWUrY3Y2bS9MR3RIbHViQ3lRSytBWEQyMnkzMVd4SGJlZHU3OTlodm1QL2prK0Y3TUpyUlNaRjVVVWZpbG5GMTc0eS9hcmlxNFdkc1R2N1N5eExEdTdDN09MdEd0cnRzUHRvcVhScFR1bllIdDg5N1dYMHNzS3kxM3VqOWw0dFgxWmVzNCt3VDdodnBNS25vbk8vNXY1ZCt6OVV4bGZlcVhLdWFxMVdxdDVSUFhlQWZXRHdvT1BCbGhybG1xS2E5NGU0aCs3V2V0UzIxMm5YbFIvR0hNNDQvTFErdEw3M2E4YlhqUTBLRFVVTkg0L3dqb3djRFR6YTAyalYyTmlrMUZUU0REY0xtNmVPUlI2NytZM3JONTB0aGkyMXJiVFdvdVBndVBENHMyK2p2eDA2NFgyaSt5VGpaTXQzV3Q5VnQxSGFDdHVoOXV6Mm1ZNzRqcEhPOE02QlV5dE9kWGZaZHJWOWIvVDlrZE5xcDZ2T3lKNHBPVXM0bTM5MjRWek91ZG56cWVlbkw4UmRHT3VPNm41d2NkWEYyejBCUGYyWHZDOWR1ZXgrK1dLdlUrKzVLM1pYVGwrMXVYcnFHdU5heDNYTDYrMTlGbjF0UDFqODBOWnYyZDkrdytwRzUwM3JtMTBEeXdmT0Rqb01YcmpsZXV2eWJhL2IxKytzdkRNd0ZESjBkemh5ZU9RdSsrN2t2YVI3TCs5bjNKOS9zT2toK21IaEk2bEg1WStWSHRmOXFQZGo2NGpseUpsUjE5RytKMEZQSG95eHhwNy9sUDdUaC9IOHArU241Uk9xRTQyVFpwT25wOXluYmo1Yi9XejhlZXJ6K2VtQ242Vi9ybjZoKytLN1h4eC82WnRaTlRQK2t2OXk0ZGZpVi9LdmpyeGU5cnA3MW4vMjhadmtOL056aFcvbDN4NTl4M2pYK3o3cy9jUjg1Z2ZzaDRxUGVoKzdQbmwvZXJpUXZMRHdHL2VFOC9zM0JDa2VBQUFBQ1hCSVdYTUFBQTdFQUFBT3hBR1ZLdzRiQUFBQUlYUkZXSFJEY21WaGRHbHZiaUJVYVcxbEFESXdNVGc2TURVNk1qZ2dNVFk2TkRJNk1UVDlod3JmQUFBSUhVbEVRVlJZUjUxWEMxQlU1eFgrZGxsZ1FkNFBVUkFmaVNoYU5HMWk3Qmh0bTA1S1VrblRXQitOUWEwWUcyT0Rsam9PR2sxaU81MXFOR1Fjazlva1JKczA0SXc2cHVOMFRFeFRhT3NZUzdTU3BocGYxS0FWQlJaaFdSNHJJTHQ3YjcvejM3dnNRaGFDL1M3L3N2ejN2TS81ei9teDZBU0dDWjJQL0ZnczhwZjY2SU5mak1WNE9XeFl6ZC9EZytaWFlFSGxKNS9qdmdXYjhPanFIV2hzY2FuOU8xVXVHRjRFaE1RVTN0cmhSdDdxbDNHcXNocElpQUY4UHFEck5wWVY1T0gxRjFjZ0pqb3FLRkxDSStJSE4yeDRFVENWLzN6Ykg1QThjUkZPVlY4Q1JpY0RVWkZBTkpmVml2SURGYWo2OXhlS1Rpa2tqNmJSRkgxdzVZSkJJdERmNmo5Vm5zYThaM2JRV3k4UVM2K3Q1anQzdDRyQTFzMEYyTHpxY1dPUDZMMWFwNHlLR0RmRzNDRUdDNFFZRUF5Tmp4KzExNXYwS1krdTE1R1dweU1uWDhjMFdVdDFaRCtoSStsaGZXSFJUdDNyOVpuVUJocFhiZFRQSVZ3L2p4RzZZODBXYzVkeWZRRzV3UmkwQnZLTGQyTi8yUWZNY3l4Z1o1Z0ZrdStXZG95Y09BWlYrMytOdXpQVGpIM0N0ZnNkT05ZVzAxRWZ3cERBSFkxUEIvKzJJV05mS2VLWHpEY0lCOENpTVZIQjFmdjJINDloWldFSk1NSU94SXpnRHUzVFdQNGRYVFRFaHZKWGlyRDBzVGtHTWRGVGZRWjEzMTRBWDNjakZiTXUrQ2xRaGFoaTd1WFRnc2praVJoejdCRHNPZG5xRFZnZkZxYXlMd0pmWEcvQzdDVy93czNMekY5S29sR2U4cWFuVnlsZnUzWWhYbnUrUUVnVnZNMnRhSmozRkRxcmp0TEhWTzdZMUw1RXdJZDJxclpRUkx6Nk5QWTkzRzlHYk80aVpCNHRKM21ZTXEvUEFNdTRIOUhEQ0s1d1E3R1BYamUxWXNhRDk2TGluUmVZaVdnaFUzQ3NmZzdPMHRmb2F3eUZSQ3RCdWdxNUMySFdSR1JXSFlidTlURXk4NkZyN2FSTDRuc3hpV0pwbkMwcEExbk9jMHFXTXErK3ljV3ozQU5FbXNwN2JzTVdic1hISCszQzZmZTI5U2x2ZS9jUUxsamk0Q3A5aS82bWtGbVVpODl1cmphTTNMb2RrM3gxaVBybWZZaWVQUlBadmhzWXViMkVLV2dtdDRlVU9ubGk0V210ZytabVNna1ZBWWV6RGFOemxnSnBTVHhEWHFTUFRrTDlYM2NyQWtIM3ljOXc0NGNyNEdtdVVlRVdNWVkzM2FyUUVuOWNnUFNEYnhqRVJBZUZoOW1zTENQV2tZbmFqQm53TlRTUkw0d0d0V055VnlPc1VYWXpRU0pPTXFHV3h2N0NWSmk0Tm1zZXJzeWFCYTM1SnBWTDFRdUxGNzFvZ0gzYTF6Q3BycmFmOHBLM2p5QithajVpNk5EcmJFNSsyTWFtMDFpdmlvSlJuTExNRkNpb1BXUFRMQXNGOTBrcHNsSDhKa2RSd3UxVVFpYjhwUUlUenY0TjRabnBpdTVFOVVWRTVPUmp3NWE5UUJ4VEZoR093azBCdytRSUc5TDdJMkNBNkF4UzdFY1k3R1NVRXBJaTYwYnE5aDNJMXVzeEl2Yzc2djMxbXk1TW03Y0IzM3FrQ0I1aFQ0NGpFNDhpajVoTkRQa0tCQXdZQk1vdXRYZ3E2RlhLeG1mVnZxQjljU0hHM3JNTTV5NWVBektZbnJCUVBnYndaZmNHU2NGQXlBRlNqOFVnYjMxMUR5NWFZdUErZUFqVzlCVGo5SWlCYnA2a0xzNEh2eVpwWUVFWU9nWHNUQU1aQk1JazNpdVoxa2hjdWVzQk5QNWlIVk9UeUhuRHdTUkdkN05aT1Z3b0xseUFqVDliUUNONHhDZ3FNdHhvVG41STdSaEZHRURBQUU0dnRRWkFUTExLWTJIbjZ2YkF3MGtuUFVCMmRhMFhXa01MN3YxNkZ0cHEzOFBMNi9QWmlHaVFNUEdYUFZ3aUU0Q1N3eWNZUVJFZ1Y0Z2lORG9jUDNrOGpXNG12VjVUcDhFZGw0REtEM2JpMDBOYkVXODJLMWNudlRmSGRiQTArUzZTNUFsRy93aUVxQUdibW15R2Fqa05HanBWMTB2NzdXNU1haitIaDc2UnBlamFlVGVZdGZnRnZQSDdJN3lrUkNtZVlJamtyNDVBaUJxUXJxV2hoK0o2MkV3YmtMQnlKYWJxSFVoYUV4aE1ULzl5RHhMR1BZNlQvNnBoRCtBRUZXMnNxYzViUnJzVkRCMEJDWDFRRGRnNHFmeklkckczVDc4SEVWT21ZSEp6RTBidDVhZzI4ZGJCU2xnbXpNZmVzZytCZEU1RXVUZElGQ1VObkNjbHhjdE1TbTVUdGhIRi9sRldHbFhxbVdQMWhVM2s4alVIL256aWpMeENXRUlpeHA5aDE3dndkOWhTT0N1STA1OWZRY29EcS9ETXVsMjhNekRjZnE5djh6VGNhTWFTUmQrRmZ2VXdpcGJuS1hxQnQxRUdFZ3QzUUdxVUFaR1I5RmpHcjRBRnBETVZjeGMraHlrL0tFYWR3Mm5zRTIyOEY4eGMvQ0ptUGxRSVoxdUhlVytnQ0M5NUcxdVJNM2s4NmkvdHg3NGRhMHdPOHJ4Wnpna2FEMi9kTmRvWXJpS2dNN0hRZUxzaSttNUV1U3QrdzRyK0I1QnFDcFZLRm8rYTIvRFRaK2NqbFMzMnBhM3ZBb2xCVnpTcG1YWTM1M3NjanY1dUEzTG5URGYyaWE0VHAxRC95Rko0dWhwWXlNbFVha3hRTDBlM0xUNEZrOXA0c3laTUE5UlhsQjA1Z2VVYk9JYWxveVdhVFVad2k5MU5HbFdNakZkelQvSk1iTnU4SEp1ZUR0eUl2YzFPM0ppN0RMYytyZUNCVFNPMVRYR0kxeDdjUk95TTd5SHo0OE93MEFuWlZ3WUlZL0M5c0xoa0gxNTVxWXlEaFVjd2lxTlp2ZU9TT3VuMXNPczU4Y1JUaitIQXppS0R3VVRqVDliQlZWNUt4WEdrdGxPcDhQbW91aFVSOWpSa1ZCN2dSZVYrZzFqcVRlVEtoU1FVdkpwUG4vM2tGbDdKNXhyWDhLbFBxdTlaMzErbk8xcmFUQ29EemxmMzhDcHU1MVU4VWE5Qkp0ZFkvUkxYQmY1OUhyRzZzN1RNcEpScmYvOXIvSmNNa0lqd3B3L1Y1MnYxMURtcmRRdi9MM2ovK0dmbXJvSE9pdVA2ZjJLenFDUmFLYXpCZUs1eCtrV2tjUzlLYnloWWIxSUtSSzZ4Z2pIby93VkR3Y09yVmIzaytleHhoanVGZ1phaEkySWt6MDJJdVQ4WFk5N2ZCOXRJS1Q2VnZFRmhkSjRoSVNJQ05qYXRmUjQxR2FQUWZmWXMxWTd1VTY0eHo5WUlPKzZxK2dUai8vbWhvVng4QzdDR2hrVGdUbkQ3OG4vMXE5TWZaczRqR2VwVWhqcWV1VTdTbmJ2Mm1oUjNoanN5UUdOaCtqUG8vdWlZWHBlWHJ6dUt0Z1Q5TnhuNi83K2g4SC9WUUNpSWtLRnlIUnJBL3dDNGUrTytaMWNuNFFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjlmMGQ4MTUwYmFhNTRjMDA5Mjk5YWQ2MmM4YmI0ZTg3Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWV9LCJtYXhNc2dTaXplIjoxMDI0LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTEyLTA0IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJHb1RydXN0IElkZW0gQ2FyZCIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNTIwMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTEyLTA0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0xMi0wNCJ9LHsiYWFndWlkIjoiMTJkZWQ3NDUtNGJlZC00N2Q0LWFiYWEtZTcxM2Y1MWQ2MzkzIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIxMmRlZDc0NS00YmVkLTQ3ZDQtYWJhYS1lNzEzZjUxZDYzOTMiLCJkZXNjcmlwdGlvbiI6IkZlaXRpYW4gQWxsaW5PbmUgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUIyRENDQVg2Z0F3SUJBZ0lRR0JVclFiZERybTIwRlpuRHNYMkNCVEFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFc0ZZRUVoaUp1cXFuTWdRalNpaXZCalY3REdDVGY0WEJCSC9CN3V2WnNLeFhTaEYwTDh1RElTV1V2Y0V4aXhSczZnQjNvbGRTcmpveDZMOFQ5NE5PenFOQ01FQXdIUVlEVlIwT0JCWUVGRXU5aHlZUnJSeUp6d1JZdm5EU0NJeHJGaU8zTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJREhTYjJtYk5EQVVOWHZwUFUwb1dLZU55ZTBmUTJsOUQwMUFSMitzTFpkaEFpRUFvM3d6Njg0SUZNVnNDQ1JtdUpxeEg2RlFSRVNOcWV6dW8xRStLa0d4V3VNPSIsIk1JSUIyRENDQVg2Z0F3SUJBZ0lRRlo5N3dzMkpHUEVvYTVOSStwOHoxakFLQmdncWhrak9QUVFEQWpCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNQ0FYRFRFNE1EUXdNVEF3TURBd01Gb1lEekl3TkRnd016TXhNak0xT1RVNVdqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFbmZBS2Jqdk1YMUV5MWI2aytXUVFkTlZNdDlKZ0dXeUozUHZNNEJTSzVYcVRmbysrMG9Bai80dG53eUlMMEhGQlI5U3Qra3RqcVNYRGZqaVhBdXJzODZOQ01FQXdIUVlEVlIwT0JCWUVGTkdobUUyQmY4TzVhL1lIWjcxUUV2NlFSZkZVTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUMzc1QxbEJqR2VGK3hLVHB6VjFLWVUyY2thaFRkNG1MSnl6WU9oYUh2NGlnSWdEMkpZa2Z5SDVRNEJwbzhycm9PMEl0N29ZakYya2d5L2VTWjNVOUdsYXF3PSIsIk1JSUJmakNDQVNXZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQVhNUlV3RXdZRFZRUUREQXhHVkNCR1NVUlBJREF5TURBd0lCY05NVFl3TlRBeE1EQXdNREF3V2hnUE1qQTFNREExTURFd01EQXdNREJhTUJjeEZUQVRCZ05WQkFNTURFWlVJRVpKUkU4Z01ESXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTkJtclJxVk94enRUSlZOMTl2dGRxY0w3dEtRZW9sMm5uTTIveVlndmtzWm5yNTBTS2JWZ0lFa3pIUVZPdTgwTFZFRTNsVmhlTzFIamdneEFsVDZvNFdqWURCZU1CMEdBMVVkRGdRV0JCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFmQmdOVkhTTUVHREFXZ0JSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QU1CZ05WSFJNRUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUJCakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUF3ZlBxZ0lXSVVCK1FCQmFWR3NkSHkwczVSTXhsa3pwU1gvelN5VFptVXBRSWdCMndKNm5aUk04b1gvbkE0M1JoNlNKb3ZNMlh3Q0NILy8rTGlyQkFiQjBNPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIxMmRlZDc0NTRiZWQ0N2Q0YWJhYWU3MTNmNTFkNjM5MyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwidXYiOmZhbHNlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOmZhbHNlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJibGUiLCJuZmMiLCJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNS0yNyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRmVpdGlhbiBCaW9QYXNzIEZJRE8gVVNCL05GQy9CTEUiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDMxMTAwNCIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA1LTI3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wNS0yNyJ9LHsiYWFndWlkIjoiODhiYmQyZjAtMzQyYS00MmU3LTk3MjktZGQxNThiZTU0MDdhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI4OGJiZDJmMC0zNDJhLTQyZTctOTcyOS1kZDE1OGJlNTQwN2EiLCJkZXNjcmlwdGlvbiI6IlByZWNpc2lvbiBJbm5hSVQgS2V5IEZJRE8gMiBMZXZlbCAyIGNlcnRpZmllZCIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsicnNhc3NhX3BrY3N2MTVfc2hhMjU2X3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRGd6Q0NBbXVnQXdJQkFnSVFhWWpueE91azQ3QkdjK0VpaDI3Ym1qQU5CZ2txaGtpRzl3MEJBUXNGQURCSE1STXdFUVlLQ1pJbWlaUHlMR1FCR1JZRFkyOXRNUmt3RndZS0NaSW1pWlB5TEdRQkdSWUpVSEpsWTJsemFXOXVNUlV3RXdZRFZRUURFd3hRY21WamFYTnBiMjR0UTBFd0lCY05NVGt3T0RFek1USXpNRFUzV2hnUE1qRXhPVEE0TVRNeE1qUXdOVGRhTUVjeEV6QVJCZ29Ka2lhSmsvSXNaQUVaRmdOamIyMHhHVEFYQmdvSmtpYUprL0lzWkFFWkZnbFFjbVZqYVhOcGIyNHhGVEFUQmdOVkJBTVRERkJ5WldOcGMybHZiaTFEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBT3M1YXZSeGJ0Uk56YlFEcHZXZ0NNRkNXRVJBRjdKUzliVW0xSEpNemJnMVAzOVVUSnQ0TXJVR3phMTQzT1crVDJDdExhNll3dU9zdkVmb1ZBUm5DZjVRSHV1U3NDMlNTMWduZzEyR0NPYkdCYXNJQkhDMjFSOUhWc0kwVzR1eGY1a2NHTmg4WXlTdHBseFhQY0t4aWcydHJNRDFVNGl6bTRMZU51RlNxY1hmMXhrL2pySW9nZ252TUlWVVlLMFdNM3BSOTFsZWJuaWhzWG5SOEd0V2pBRmRwUUhBT1VZOTRSak45cThueEd1TXVOY2YrMkVaMFZMZVYzdEczaVFaeEp5bDN4OWRaQ3dLNzBXWGozR3RLZHBSL0ZTdWNyaURSTHFiVUZXdU1nS0FYaWZrNG9ranprNWZkNU9GbmV6UGlsN2gwalkzcStIS0tsSGpNOWI0N3dVQ0F3RUFBYU5wTUdjd0V3WUpLd1lCQkFHQ054UUNCQVllQkFCREFFRXdEZ1lEVlIwUEFRSC9CQVFEQWdHR01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQMnJqdzNjTHB3VXpoWjJsdFB0ditjdmRDT2dNQkFHQ1NzR0FRUUJnamNWQVFRREFnRUFNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNWdVhuZWc1MjZCY1BRakJhdlg5UDYwZzBKSUpLYUowQ1JvUFVHODNJbE01cWx5S1FPcm1HNGZwL1BIbmhQRC9tQTdPNGNYTFZ1eERCKzJXK2duaExEaVZFSnBjanlwQjFHWGlWNWhxZmMwWHBtSFQ0OENhOURpdG4xRWVWZUIxdDhyV0NLMThYbzZ4NXhYTVQ5b1RVRHBQNDEwblZDMndmVlEyMUlYQTZia3pnUU1pSzdCQ0pnZ1dKOEhva2dQaG1QYjRSL3BQTndMdUNsdlJ4cHBuMjBaY0pxcFlRSGVJMDJyMExLaHdjZStrWnBqSkQraFVueXJvMjYyUktyT2Y5KzN5OHpyRllDMTBjYnNMVW1VSnM1cEp4eWdqNGZWR2JrQjlqdnNHMXhUdTYya284cVVYNW1YSk50ejNkUlBDRWNHeDR5MnJvbTZ1c2hBUHRxcjFJayJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFhNEFBQUN5Q0FZQUFBQWFsaXZPQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzUUFBQTdFQVpVckRoc0FBR1hyU1VSQlZIaGU3WjBGWUJSSEY4Zi9rWk80S3pHQ3U3czd4YVZDUzRHV09xVkc1V3RMcWJ0Um9GUm9hU2tWcEZDa1VJcTdPeFIzRFVrZzdya2szM3R6ZTNCM3VTUVh6OEg4MmlGM3U3TjdxL09mTi9QbWpWMGVBWWxFSXBGSWJBUjc1YTlFSXBGSUpEYUJGQzZKUkNLUjJCUlN1Q1FTaVVSaVUwamhra2drRW9sTklZVkxJcEZJSkRhRkZDNkpSQ0tSMkJSU3VDUVNpVVJpVTBqaGtrZ2tFb2xOSVlWTElwRklKRGFGRkM2SlJDS1IyQlJTdUNRU2lVUmlVMGpoa2tna0VvbE5JWVZMSXBGSUpEYUZGQzZKUkNLUjJCUlN1Q1FTaVVSaVUwamhra2drRW9sTklZVkxJcEZJSkRhRkZDNkpSQ0tSMkJSU3VDUVNpVVJpVTBqaGtrZ2tFb2xOSVlWTElwRklKRGFGRkM2SlJDS1IyQlJTdUNRU2lVUmlVMGpoa2tna0VvbE5JWVZMSXBGSUpEYUZGQzZKUkNLUjJCUlN1Q1FTaVVSaVUwamhza0J1Ymk0U0U1T1VieEtKUkNLcFNramhzc0NNSDJaaTBsdnY0UHFORzhvU2lVUWlrVlFWN1BJSTViT0UrUHpMS1lpTmlZVmFyVUpPYmc2ZWZlWnBCQVlFS0dzbEVvbEVVdGxJNFZKSVMwM0RWOU9tSXprcENScU5Cams1T1hCd2NFQk1UQXllZTNZODZ0U3ByZVNVU0NRU1NXVWloWXVJajAvQVYxTytSbFpXcGhBclRqNCtQcmg0OFNMYzNOeVFtcEtLM3IxN29tZlA3c29XRW9sRUlxa3M3bmpoMnJGekovNzhjeEZjWEp5Um5aME5aMmRuUFBib1dBUUdCbURXck5uNDc4aFJJVjd4OGZGbzByUXhIaDR6V3RsU0lwRklKSlhCSFMxY0N4Y3V3dGF0MitIdTRZN1UxRlQ0ZVB0ZzNMZ240Tzd1cHVRQVZxNWFnNlZMbDhIZjM0L3lwTURYMXc4UFBuQS9ncXNGS1Rra0VvbEVVcEhja2NJVkhST0RuMmIrZ29URUJEZzVPU0VsSlJVTkc5Ykg2RkVqWVcrZjM5Rnk3NzREbUR0M1BqUWFOZmh5NWVoMEdEUm9BTnEzYjZma2tFZ2tFa2xGY1VjSlYyWm1GdGF2WDQ4bFM1ZkR6ODlYaUZCV2RoYTZkZTJLdm4xNktia3NjKzFhTkdiUC9nMHhzYkZ3ZFhWRlFrSUNRa05DY2YvOTl5QTRPRmpKSlpGSUpKTHk1bzRScnFOSGoyTCtna1ZJSSt2S3hkVUZTVW5KMEdvMXd0MDlJTUJmeVZVNFdWbForR3ZSWW16ZXZFMElIL2VKNWVZQ2pSdlh4LzBqN2xOeVNTUVNpYVE4dWEyRmkwL3Q1TWxUbUROM0h1TGk0dUh0N1MzRWgyblhyaDBHRHJoTGZDNHVGeTlkRXRaWFFtSVMzTWo2U2s5UEYwSjQ3NzNEMGFKRmM3Rk1JcEZJSk9YRGJTdGMyN2Z2d0w3OUIzRDI3RG5oS2NndTd0ZXYzMER0MmpVeGZQaFFWQ3RsOHg0M01XN2F1QVVMeVFMejlQQVFZNzg0VEpTZm53K2FOR21NSHQyN0M0dE9JcEZJSkdYTDdTTmNkQmFKU1VuWXNuVWJObS9lS2hhb1ZDcGhkWEdUbm91TGkyak9xMVdyaGo1L0lheUsyb2UvTCszQ3ROWlBLa3NLSmlVbEJYOHUrRXRZZG5aMmRuQjBkS1RmMHdrcnJISGpodWpab3p1Q2dnTEZzVWdrRW9tazlOaThjRVZGWGNQUlk4ZHcvdHdGL0hma0NGbFdqbkIxZFJGaWxaaVVqTnExYXFKVnl4Wm8xNjZOc2tYaHpEMi9HYU0yZlFCZDJnMDgxdVJCekdqM25MS21jTml5Mjc2RHJMeDlCNFZuSW84TFkyZVFwS1JFVks4ZUlTSnZWSzllSFEwYjFGZTJrRWdrRWtsSnNFbmhPbjdpSkE0ZVBJemp4NDZUUlpXTDlJeU1teEV2T0ZSVFdsb2F3c0xETVhCQVAwU1NhUEJ5YS9qMjFDcU0yL1Fob0hZRFNBQ1Jub0FtZ1kxeG9QOFVKVWZSY0YvYW1qWHJzSFBYYnJLeUhJVUZ4ckNRT3BMVnBWR3I0T1hsamZZa3BQWHIxeFB1K0JLSlJDS3huaW9sWER5ZENJdFFaa2FtR0JDY2twcUNsT1FVMFFSNDhjSWxuTHR3QVRIUk1hS3dkM0xTM293cHlNMXlkbmIyQ0E0T0lxR3FqdTdkdTRob0Y4WGg0YTJUTWV2SWZNQXRrTDdaNlJmeW4vUkUrTG9HWUZPdmoxSFBNMHkvM0VxNHlmTDRpUk80Y3VXcTZQL2lQaTgrWmo1UFBqOU9mSnpoSkxJaElkVVE0TzhIWjJjWHVMdTcwMTg2UjJjdG5MUk9zcGxSSXBGSWpLaHc0VW9tSWZwanpqem9jblN3dDFNRWd0RHBkQ1JDdWZRM0c5bFoyY2pNeWtJR2kxaG1sckJjMkdwaTY0WC9abVptQ3JGS1MwdEhhR2dJT25ab2g0aUlDQ0ZjTEF6RklUb2pDZmVzbTRUTlVZY0FGeDlscVRGMGpObXAwTkJsbXRubGRZd003NlFzdHg0ZUEzYjE2bFhzMzM4QWUvWWRJSkdGR0F1bVVhdEZ2eGlMTDU4L0oyNW0xR3ExVU5NNmpsQ3ZVbXZnU011RWVQSFlhT1Z1c1FYWHFWTkhOR3ZhUkw5QUlwRkk3aEFxWExoNDRPN2tMNmRDbDZ1UHZtNzRlZjRyUHRJL3VYbTV5bmY2VE5ZSjU5T3loVVdGT1JmZzNHZFVyMTQ5MUs5WFYyeGJFdmludmp2eEQ4WnRlSjhFeXhkdzVDYTdRaTRGSDF6S05YU0w2SVJaSFNZZ3pKbTJLU0dKU1luWXZtMG56cHc5aStTVVZHU1RFTE5Rc3lDenF0bVQ5V2huci93bGtXTng0OFNIWUUvTCtXOUdSam9HRHV5UHppUmVaY1hseTVmeDc3Ly80dXV2djhiQmd3ZkZzcjU5KytMcHA1OG1rZXdFRHc4UHNVd2l1VjNZdEdrVGZ2MzFWL3owMDAraXJBa0xDOFBERHorTXdZTUhvMW16WmtvdVNWV2p3b1VyTVRFUlU2ZE1oNDdFaWNkVVpWTXllT094MjdwR3E0R0h1enZjM2R4RWt4a1hsdHhzNXV2bkN6OWYzekxwRTFvZmZRU3Y3cCtGWFZGN1NiVDhhTWt0eTY5UVdFWFM0dUNxOWNJblRVZGlYSjJCeW9xU3c1Yy9OalpXdU9xenFITlRhWHhjdkJBMC9mZDBaTkt5bE5RME9DcldKbzlIUzAvUFFQLytmY25hYksvc3FYVDg4c3N2R0Q5K3ZQQ1N0RVR0MnJVeGMrWk1kT3hZZGtJcGtWUVczQUxDRmJMRml4Y3JTL0x6L1BQUFkvTGt5Y28zNjlpNWN5ZisrdXN2SkNjbml4WVVmcjl2VlBDRXRQeWIzR3JEM1JCY3JuS1pPWHo0Y0xSdlh6WmxSVldnMG9RclBUTURkZXZVd2NpUkkwUVRvY0d5NEtZeVMvRUN5NEp6S2RGNGJPOU1yRDIvR1ZDVEFBb3JpN0gyRWlnQ2w2c0RzdElBbFJZcnUweEN6OEJHSnMyZVpRWFhBUG4yY01xaHp5cDZDRStmUG9PWlA4MmlhK1JRWnNJMWF0UW8vUGJiYjhxM3dwazdkeTd1dTA5R0NaSFlMcWRQbjBiYnRtMnRFaFN1UEhPWlZSVDc5dTFENzk2OUsxeWtpZ05QMWJSeTVVcTBhTkZDV1dLN1ZNN1UvVlRJaThKWW1heFI5T1dvVktKMlVCNmk5WGZVQVl6Wk9RMlJDMFpoN1pWZGdDdFpXV3BYT2c3NkxaRWNyRXhLZmdjMTRPeEpmMVhvOCs4RVJDNS9CalBPckVaNlRyYnlpMlVEWHd0RDN4NDNrL0wzbkJ5ZEVMU3kwc2taTTJaWUxWck1pQkVqeEJRdkVvbXQwcnAxYTZzRkppa3BDWGZmZmJmeXpUSnN0YkVZVkdYUll2ajRXclpzaWIvLy9sdFpZcnVVdlVvVUJRbFdMaHQ1WFBLV3M2MzM5WmsxYUxqOFdRemEvQWxtbjlzRUIvZHFjSER5aGdOWksreUZlS3YwcHdQSnl5MDhjUjdPVHR1eHRlTm83d2dIUncwY1BNTndJVDBPVCt6NkRqV1hQb1g3ZGt4RGRHYVMyR3Q1d0pmdUpxVVVyeXRYcm1EU3BFbktOK3ZoUGdDSnhCWjU0NDAzaWwzeFdyaHdJVFpzMktCOE0rWHMyYk1ZTm15WThzMDJHRFJvRUk0ZlA2NThzMDBxWExneXM3T1JucDZtMXdDSHN2djVtSXdrYkxsK2dpeWZOZWkwL24zWS9kUVR6K3o4SG1lejB1Q2w5b0NieG92MEp3YzVXZW5JeVVpRmxrNjltc1lUamQycW9iMW5EZlQzYjRBQmZnMHhrUDRhcC83K0RkSEh0eDdhZUVhZ3RuTUFmRlV1c0NPTFI1ZWVqSnpzTERpU3BubXEzZUhsN0k4a09xdjVsM1loY002OVVDOFlqVGYvVzRBVlZ3L2dWUEkxNVNqTER0SENtMWM2NWVLYVYweE1qUExOZXJaczJZS1RKMDhxM3lRUzI0RDduUXJyMHlxTTVjdVhLNTlNZWVtbGwvVHZvbzN4NUpORlJ3V3F5bFI0SHhjN0lYenhKWGQ0Mm91UVNQZVB1RmUvb2hqa2tQVnpLdWtxZHNlZnhiWWJwM0VwOVFhdXBNZmpYR28wa3JMVDRhRnlocXVqRmptNU9zUmxweUtUTENBM0p5LzBDMnFCTnQ2UnFPN3FEMytOTzRKcG1hL2FGYTZxb2gwK3VJOHBQanNGc1JuSmlNcE1RRXg2QW80bVg4WEthNGV3Sy9hWXNNUThORzV3Y2RDU05lYUFiQkxKRzFra2J2UTN3alVBRWM0KzhLUGZiT3RURTAwOXE2T3BWNWc0enVMeTMzOUg4Y3ZzWDBVVFlvOGUzZEdyWjNkbFRmSGhEbHZ1U0M0Snk1WXRRLy8rL1pWdkVrblZaOWV1WGNKQmdic29pZ3YzaVczZnZsMzVkZ3Z1bDdkVmJGRndEVlJaNGZyNDJCSWNqRDh2M09ZVHlHcUt5VW9pcXlwUkNKTmFOTlhaMDErVitPeGc1d0FWQ1FjTFJwb3VrMFFqRjk0YUYzaVRLUEc0cTVFUkhhSGxmcWx5NUhEQ1JmeDhiaU8yWFQ5T3g1dUtWRjBHM0J5ZG9HSVJ5OHNSUXBhRFhHVG42SkJGeDVlZGwwM25saXVhVGNOZGZPR3Y5WUNUZ3dxK0pHNThyTzgydkFlQkpLem1YTHg0Q2RPbWZ3c0hPdi91M2JxaWQrK2V5cHJpdzU1SHdnVy9CSHozM1hkNDRva25sRzhTU2RXSFd4aTRtYXlrbUJlVkhLR0hZNkRhS3J0Mzd4WjlYclpJeGZkeEVkYlVVczRtWHNIZTJPTTRueGlGUkxLWW5PbFFhenI1b0pWSEdKcTRWVU1EbHlEVWN2SkZ1TVlMd1NvM09PWFpJeU1qRmYwRG11RGRSbmRqYmJjM3NhNzdXM2lrUnZkeUZ5Mm1rV2NZdm13MkNqdDZmWUJmMmp5TjErc05RWWphSFdsMFRKNTJhbFNqejJGcVQ5U2dZNjduNG8vR3J0WFEzRDBVTGVoOFBPMDFTTXRNUld4cVBBNWRQMFBuZlJJM01pMjdwUXZuRmVYOXNTdGxKMWRKUll1cDZoM1JFb2s1TERSbENmY1IyektIRHg5V1B0a2VGUzVjN0JHbjArWGM4b3NvQUM3bzYxQWhIK25raWVwYzZLdGNFZXpvakFBSHJUNlJOZU5qcjRaYm5oMWNxQ1owZjNnN2JPbjdFYWEyZmd3UFJYYUhqOGE2a0U5czhXVGw2cENSazRWTXN0WlNzOU9RUUtLUlFHS1pTcFllTDh2TXlSWVdrN1cwOGEyRnAycjN4ZC9kMzhEQ0xxK2dqck12dEhUZUhuUzUvUTNIcjZSQVNpRXFGMFRRT1VacVBGQ2J4TGtHL1ZVVkpFckd0YjVLYktXNGZ2MjY4a2tpc1ExSzI2ekg0eXFOcVZtenB2TEpOZ2tJQ0ZBKzJSNFYzbFI0OVdvVVB2N2tNN2k2dXFGSms0YTQ3OTU3bERXbVRENDBId2V2bjRhVG82VVFUblpJeWtxQmw5b05MZnpyNE9HNlBDRmswUS9sdWRRWTBhUjNPZUU4enFWZHg3NzRDemljZUFteDlCbnA4WUF1bmFUY2dYSXErMkp2UWhZc0VoTm8zVkhYUFJqMTNjbFM4Z2hIc0tzL3d1bHpGLytHY0xEaWhUaEZ2N1AwL0Zic0kydEtReFlnVzRGNUJ0UEpDSEU3YUgrdk5IMEFrZTVCeXRKYmNIU0xLVk9uaXo2dXJ0MjZvRy92WHNxYTRsT2FGL25GRjEvRTU1OS9ybnlUU0tvKzgrZlBMOVVZeEV1WExpRWtKRVQ1cGtmMmNWVU9GVzV4OFkzVzMrdzhVZmdXaExPOUJoNXFKM2lvdEhDbnhIODVPVHVva0pHZGlqNGhyZkJSMnlkSXRQcFI3b0lmbmhpeW5KN1kvVDNhTDMwUzdaZU54K0MxYitMcGJWUHcrWC96c0M1cUwySXpTYkFjMVFDSkVueXBCdVZWblZLRVBubEhBbjYxNkdBODZDZnljRHp4QXY0NnZ3bHY3UDhKWXpkOWpONnJYMGVUdjhhZzlUL1A0ZGR6bTVSZnRFd3RqMUM4MkdRRUpyVVlnMUFYWCtTUWhlZW1vbk5VenU5bVVsTnkxQllvaHJtNS9MRHAxNlduWllpL0VvbWsvTEUweHZUdHQ5OVdQdGtXUEJqWmxxbVVQaTVyOEtBQzNFL2pBVjlLL05lYnJDc1hlelhxZW9UaG15NHZZelJaV1c1cXkxNTUrK0xQWWRMKzJiRDd1UWNDZnV5RUdZZm5ZM3ZpWlZ6THpnUWN5SUxqTUU4YUwwRGxTbGVBdnR2eDFDTWtCaXdLWEFzeFRrSW9lUEN4aXY0NDZhYzgwWHFURmVhTkhEc0hIRWxQd083cnB6QjY5V3V3bTFvZnRaWThqdm5uTnVKTVNyUTRGblBxZW9Yam5kYVA0cEY2QStCUDUrWHFvRDlQOWpqVUovN3NCaFVQZUxhQVB0Q3dQbDRoN0hoOG1VUWlxU3hlZmZWVmRPalFRZmxtTyt6ZnYxLzVaSnRVV2VHeW81TFp5OUVaYm1SOXNHQnhNZDQzdkQwZWF6Z0VUclRNRXN1djdFUHZmMTlDaTcrZnh2djdmaVJ4SXBIeElZdkp5Wk5LZkJJb25tT0xhMDFzelZoTXZNNVNzcFNYRWpjcmtnVUlkcWZuWmoyLytqaWRkQm4zclgwRExaWS9nK2UzVDBOVUFZT1JXd2MyeEZPTjdrWkRuMGprNWVRSUQwUkRjcWZ6ZGl4QXVBeUlReWpFMHBSSUpPVVB6MGF4ZE9sU213cWp4S0lWR2hxcWZMTk5xRlN1bW5pb1hlRkxndU9tY29HL3N4ZGVhRFlLclFJYktHdE4yUmg5Qkg3ejdzT0FWUzlqZGV4eHZaQzRCTkRaOFR4V1hNS2JDNUVoc1NWRmY0VmxsUU53eUthY0xLTkUzemt1SWErL21WL1p4anlKMzZGRXh3dlhRQ1RTdGxOT0xVZnc3SDRZc3ZGRFhFdUxFOGRxakFzZDU1QWEzVENzVm5jNlh4ZDRhdWljdGU3dzByb2kxMEwvbDBRaXFYcHcwT3M5ZS9hSVByVEl5TWdxNXlMUFV5VHhNWExvS3Zhc2JOcTBxYkxHZHFsdzU0ekxWNjdnczg4bWk2bnRtemR2aXJ1SFd3NlhzdlBxUWNTbXhpSENNeFFOZld2b1JjR016VEZIOFBiQlA3RHUzSHA5ODk5TlJ3N3pVekpzeTh2cHN5NER5RTdYSjE3bTdJOEFFa2QvbGFzWWQ4Vk9FMnpOOE96S2NaU0hRem9oL1FZSkdUYzFrclhIVFpSczlZbGpNdDYzTWNweXZyeVpDU1NBd0N1TjdzVmJ6UjRTL1hUbUpHWWs0VURNQ1dUbFpvdnBUSnI1MTRVM1c0cG1zSFBMMUdsZjB5Yzd0RzNiR2tNR2wzeGNpblRPa054SmxOWTVnOTNmZzRPRGxXOEZ3MkdnMktxSmpvNFc0YVVzRFhqbTJLeFJVVkdZTm0yYXNxVDRqQjA3RnJWcTFSS3piQmpEUlRyUDk4Y0JndGtpNUprZGVBRDE3VVNGQzllbHk1ZXB3SnRDd3VWVXNIRFJJUjJPUFFWUHNqNUMzWGxHNHZ3OHR2c0gvSGhrb2I2cGpxd1ZJUno1dElNS1pqNDlFZ085OVVSSmw0NGFnZlM3MVZxaFgyQVQ0U2loY3REQXlWRU5MVmxvSm9VNWJacVZwME9xTGhOWmxOSjBhVmhGMXQzOFN6dXc0L0l1ZmJNamp4RmpLMHo4WmN1cmdPTmdpeTRyR1c1YUQvelorWFgwQ2NvL0FTUVBUajRWZndIcDJXbW81VjBkN21TQm1TT0ZLejg4eE1JUXNMazhnalJYRnZ4cTh0UVlmSis0YjlNVzRPTmR1M2F0bU0rTkMzbytkcDcwbEYzSG16ZHZqaTVkdWlnNUs1NktFaTVyNFhpQjlldlhGL2U1Skd6Y3VCR2RPM2RXdnQxWlZJSndYYUVDNzZ0Q2hZc1BpY2RPYWRuYno0eU5NY2N3Zk9ON3VKRWFTMVpXUVpNNUtnVXlDUVYwMldqbVZ4dTFQYXZqeVZwM29hdGZ5U2VmTk9kRXlqVjhjMkk1L3J0eEF1dGlqbE1KU2pVZnJSY0ptaUtZK1dBQjB3SHg1L0Zna3dmeFE1dHhKSmI1QzZUbzFPdndJTkhTV3VqTHMyWGhTazFORlJQM0dRWXZzOGgwN2RxMVdJWEJxbFdyY096WU1jeWVQVnRNSlZFUTNGelRzMmRQOU9uVFIwdzZ5cjlUbnF4YnQ0N3V6VlZ4VFZsSU9RSjVuVHAxbExWRncwRmNPZjdqSDMvOElRcWtnbUJ4N3RhdEd3WU1HSUM2ZGV1S3FUUktjeDlMeTdWcjE3Qm16UnFzWDc5ZVRNWm9EUTBhTk1BTEw3eUEwYU5INjJmMkxnU083c0JoeVhnR0F4NEt3ckFGOGNBREQrRCsrKzhYbjYybHFna1hoNkJxMDZhTjhxMzRjUHpFZnYzWXEvck9vMG9LVjBIOGZtNGpIdHcybVVvOHNuQTR6cC81b2ZQN3k4dTRDVEExR3QxcTlzWEVlb1BSeHJjdVhDMklZRm5DQVg0WFg5eUJML2JQMGpjbGF0ejF4MmxSditoQTArTVI2QnFBa3dPL2dadUZzV3A4V3l3VlNMWXFYQndpNnNzdnY4U3BVNmVVSlhwNFhFeVBIajB3YXhaZHQwTDQ1NTkvOE41NzcySEhqaDNLa3VMQnRYMk80ajF4NGtSbFNkbkFNMGEvOHNvcithSVErUHI2aXI2RTFhdFhLMHNzdzAxS3ZEMFgvaVdoU1pNbXdvcVpNbVdLc3FUaWVQenh4OFg1OC9pbWtzRE5YRHpiTm91dkpmaVplZXFwcDVSditlRUpFbGtzZWFvZGE2aHF3c1dpekJXY2tuSW5DMWVGdDZ1VXRLd2N1dVZ6UExqaFBYcGFTUkRZVzFBMDAzRVRIU2V5V2ppUllMblNEL1FMYVlXOHg3WmlYYmRKNkJIWTJDclJTc3hPdzVXME9Gd2dTODZRTHFmZHdQWE1aR1NMYVUwS3A2TnZIWHplZkF6eUhsbVBsNXFPUWdDTEYyM0x4MmtuanM5d3JKVDQyTWxhdktaTGgvdnZBekh2MGs1bEw3ZW96RnAwV2NKTmVPd3V6QVdRdVdneFhJdm0yWmU1b0xkVWg3cHc0WUt3bmppZ2IwbEZpMkhyaktlMDRPdHFyV1ZRRkNOSGpzUmRkOTFsTVhRT1J4WmhNZUo0a0Z6Z21jUFdHVnNlTEtnbEZTMkdtK1NtVHAwcXpvc3JCdVVOejVBOVljSUU4WHMvL1BCRGlVV0w0ZWVCTFdLK2p1YjMvdlhYWHk5VXRKajA5SFJoZFpXbW4waGltMVM0Y1BGY1dKYk5FTXR3enJzMmZVTFd6RlpvdmFwRGE2ZW01RURKa1pKS0pIdk9sQktMMFJGZHNidlA1MWplK1RXeGJXR3N1TG9mcng3NEJZOXUvQkQ5VnIrR0xpdGVGQU9KV3l4L0ZpMlZ4Tjg3cm5nQmZWZitEMk0zZm9CbmQzMkxYODV0UUZ4V3FySVh5M3pXYUFTTzladUs1eHVRTlptUmpMd2MzYzFqMVI4M0p6b0hSMmZZdXdaakJJbnl0Tk9ybEsxdkw3aEpaOXUyYmNxM2d1SG13MGFOR2luZjlIQ2hGQkVSVWVZeDVoNTU1QkU4OU5CRHlNZ28rUUJ1dHBLNFdhOG9PQjZrdVJjWFc2dlZxbFhEMGFOSGxTVmxBKytYclJmdTlDOFB1RG1RKzJTS081MTlVZkIxNVAwYVltZHlzK3RISDMwa1BsdkRzODgraTcxNzl5cmZKSGNDRmQ1VUdCVjFUWVI4NGxxME5VMkYxWlk5ZzJzWjhmQldrNlZsSm5oODVQSFpxUWpWdUdOK2h4ZlEycnVHc2lZL0NWa3BXRUtXelp2L3pjUFZHMmVnWXl1STk4Yzc0WDZtbTI3dDV0RDZYTEs0OHRnemlQK1MrTkluRDQwSEhxczdDRzgxdkJjcXN1Z2NMVzRMSkpFbDEzcnRXemlSSEFVdnRTc2NEQTRjTjdIVFI4RFBUTVQ3amU4WFRadUZZVXROaFVVMTlWaUMrejNZTXVMK3FZc1hMeXBMeXdjZXk3SjE2OVppajJuaEpocnVZeW9PM0pmQnpXb2RPM2JFa1NOSGxLWGxBOS9YQXdjT29ISGp4c3FTMHZQT08rK1VlNVFJanAzSDEyaklrQ0hDMGk0T2ZEK0ttdG4zVG1zcW5IcDhLVjQ3UEVjRU03QVgvU2hsZzQ3S3drQ3RKMzVvOVJTNkJKcFdOaXVLQ3JlNFRBdnRnc25NelVhbmRlOGloYXliQ0NkZnVObXJLS24xeVlHVFNxeDdPTHdqemcvOHVrRFIrdXZpZG96ZStCRzhadmZIUTJ2ZndNWEV5OUJwM2ZSOVpEeDlQemM3OHJndk1VQlpaU0dwYVQyN3dMdFFvcnkwVFE2bHVKeE1mTEp2SnB4LzdJUjJLeVpneHNsL1dOYnk0VTYvYzd6dlovaUNSRW1ueXdMM1pybno4UnZPaGM3TGkvWWY0ZUtQZC81YmdNK1BXNTZ3emdEWE04UU0wZ1E3QVZSVjJKT01tNUtLQ3p0ZGNJZDdlWXNXdzgxY1BIQTBOalpXV1dJZE0yZk9WRDVaejg2ZE8rSGw1Vlh1b3NYd004SjlYeWRPbkZDV2xJNXg0OFpWU0dnamRoOXYxcXhac1VXTDRmbmhUcDgrclh5VDFGMDRCczl0K0FCcG1jbEl6RWhBUEZYK3l5b2xaeWJoVlB4WmRQMXJOQ2JzbWFIOFlzVlM0Y0xGWmE1Uzd0NzhhNG54ZTJiaWJQSlZWSGZ5Z1N1TGxoQXJmZUxaaXkrbnhHQnRsOWZ4WTZ2SGxTMU0yUlo3SFBVV2pjWHdkVy9qMXpOckFHY3Z3STFxU3l4Q3dycmlYSHdBeFV5OEhTY1dOV2NmTXIxQ3NJZCs2NG10WHlCNDdyMzQ0WlRsSnI4SmRmcGpWOC8zWVVmV2xYMWVybDY4RElrRXpOMUJnem9rWGgrUWVLMk5Mbmk2QVJhclBCR0dTajlxdjZyQ015c1g1dlZYVldEUjRocSsrVmlZZ2toTVRDeXlabDlWWUt1MXRGSDh1VC9yMjIrL1ZiNVZiY3FyaWRUV2VISC9MSnk0VHBVV0twdEV4YnM4RWxmOFBTTXdlZDhzbkVvcWVUOW5TYWx3NFZLcEhLSFY2Z3RjSHZOUkVDbVpxUWhYZThESFFRdGZvK1JpWjRkUXRUdXVEWm1CRHY3NVhkdVBKMXhFeDM5ZlFZZDU5K0E0aVp2dzhOTjYwQnBTRzNheU1DaW5va1A2WkZBalErTExZdlNkMTV2azUwVC9HSlNYTFRhTk82SjFHWGg4N1p2d290K2VjejUvME4yNkhzRTRNV0FLMm5oV2h3TlpsSDZPVGlibjV1L29qS2J1MVRCaDkweWNTTFE4MTQ5K25CSWZGNTJhbXNTemlzTE5JTFlDOThGWk81VTVXMm1GUGJkVkNYWjhZZWVSa3NLV1ZsbjNaNVVuUFBCWEF2eDBkQkhneWxPV0tPVlRlY0ZkRGZhTytPbk1XbVZCeFZIaHdzWHQ3L2JDUWFOd2ZCMmM0RVZXaUhIUzBIM3dKT3RrUWRkWDRjM3U1bVpNUFBRSEdpNTVIRnV2N1FkODZsRE5nQVhTVU5EelgrUEVZa1E3ektGQ2lPTUpKcFBJSlpCWUpGd0FicHpSLzAyZ21rUXkxZUxTNDREc0RNcXY3K1BLdnk4bGNZZ3BxdVVrWktiaGdiVnY0SVh0VTJtNUtjNk9XdnpTL2prU3FIQlM3aXg0bTUyanQ3MUdDSE55QVE0Z3FhbnNxS0M0eWd2QnJacWNPVVBYMEliNCtlZWZFUmVYUHl5WE9XeEoyaEljaXFna2pndHNWZHFLcFdXQW02Y2xnQk9YYlZ3K21NT1QwNmJTODhzUmdNb0tLc3Q1eHZlS2hrdmNDc1hCd1Y1WVhVeDZlc0VYa1B0OS9LaVE5MUdTcTUwRHdwMjlzS1RIVzNCakM4ZUlLMm54YVBQM2VIeTQrenZrcUxWa1liblJqU09SWVhkRGs4UzU2ZUhtcVV6SU9ncFZhZENVcktCUjlRYmoxOTRmWXQrSXViZzhaalh5eGg5QXpOajFPUFhnVXF3ZTlEM2VhL3NNT2xacmpqcHFWN2p6NEdJTzRhU2ptMlhwTjNpWm1nVFR4UmRmSFY4Q3U5bDljZG9zVWp4N1Z2N1E4VmwwRDJnbytyd001eWdTblhld3hnMmVJaHBJZnJKSTdCZ1dMbWRuc2lhcktPd2NZR3M4K09DRHlxZUNLV3RQd0lwZ3pKZ3h5aWZyWURkMWRsRzNOZVRrcGdaWXRLZ3NNc0FWOUt3MGpJcm9pdDk3ZllnR2JxRUF4MDQxdEJpVmtxSUNncGNIRlM1Y2JHMFpSc3ZuNkxMcDJsRkJiNEZnSnk4U0tDMDhTYVJjSGRSa1libmcwelpQUXNWOVMwWWNKS3VveWQ5UFlOZjFZeVFXL25UUCtDTHlqVE5MN01pUWRCWHFQRWRNYWpJS3YzZWRpSlBEZjhkK0VxYlpKRXdQUm5SR002L3FxT2JzVGZraHBoaXA2UmFFbm9HTjhVYUQ0ZGpjOHdNY3YrZDNiTzAzQlYrMGZobzlBcHNETEVpWkpHRDVtaHFWUk9mQU5aSmFDMGZqSHc0UlpZUTlIZWRyelVhaXBuc2dWSGIyOEtEenZKa2NuYUFTVFlMNVNVOUx2L204MlR0Vy9BTmpMYlpZaUJ3NmRLaklmaEoySUxBMXVBbU5velJZQ3pjUkppY25LOTlzaDhMbTk3dWpvVXA2ajRBbW1OMzFkVHdRM2huL0RmNE92M1Y0R1VpOEtOYlpJaFV1WEd4dE9UbHBSZUdiVGNMRjAvaGJncjN4dUJCM0pmSEt5OHZCZTYwZnl6Zi8xcWFZbzJpNjVBbmN5RXpUaDFyaW5YS2hmak9SZUhCL1JFWVNISE4wV0hUWFY0aS9idzdlYmY0d0hnanJBSzF3aVM4ZURUMUNNYUhCTUt3bUN5MWx6QnIwRFcxSCswOFVOUnJoVm1qU0gwYi84QnhlSkVUOS8zMEpzMDZiUmxGZ3ErbUZKaU1RNU9RcEF1L3lSSklzMXV3MjcreVFQOXdUazI0MDlxZ3E5M0d4RTRPdHdlN08yN2R2Vjc1WmhnZTkyaHA4ek54a2FBM3NVRk9hQWRHU0traXVEdUVjaE55SWtYWDdZeHRWM0NQWVU1ckxyekt5dmlxS1NyQzRIS0ZTcTBVVExQZlhaR1phOXVieTAzcVF0ZVVDSnpzMUhxOC9URXdCWXN5QmhBdm9zdWdSRWdVMWxlQzBUaGc1OUk4aHNjV1NFVStXbWpPbXQza1cyYU9XWVVob0d6aGJDSzlVRXZqblhFaElWM1IvR3hkSC9Ja2hJYTMxVFpCNUpKVENhOUZ3TEpTUnJVUlhmenk4NWcxOGYvSmZzYjBCbnI3bGtRYUR4VHhjSG5TK25vNnVkTXl1VUJjUTdTT0Zhc0tpZjR1U2s4YXl1RlVGeWlQWUxRZWFiZGV1bmZBQzVJRzI0ZUhoeXBxeWcrTUZGb2E0OXVWQXk1WXRNWGp3WVBUdDI3ZFlNUTZ0eGRxbVd4NzBMYm5OSUNOZzdxVnRPTXZPYWthMDg2K0xjL2ZOdzZnYXZZRzA2L3IrZmxGZ1ZYMHF4ZUp5MW1yQlU5RG4wSVhLNWFqcEZ1QUNYV092UmlPL0dxanJZMXBBSFUrT1FxdmxMd0J1QVZTYWtTand0YjRwRkVxaVBMMUMyK0x3Z0c4d3J0NUEvWVlGRUp1WmpLa25WK0M1dmJQUWVkMGtkRjMzRmpxdmZRdUROMytLU1lmbllWUHNNU1duWlVLZHZMQ28renVZUzBrNGN1Z3l6WTZITXZGZnp4QTh1ZlV6ckdmbkVTTUNuWDNRUGFTRnVCbnVKTUlzWUJvU2VFdHdFNDREaVlJOTdjK2xDdmR4bFRYVHAwOFh3WFhaR2xpMGFCRldyRmdoeGtaeE5JZFdyVm9wdVVwUFJmZGhmZkRCQi9qdnYvL0VlU3hldkZqRVpPUkIwWnc0dG1KWlljM1FCQjc4VzVSd0Z4ZXViTEFZY3p4Qjg4Z29rZ3JDM2dGcHVWbW91M0FVcGg5ZHJDeTh4ZXpPLzhNZjNkOFQ4VjJSZkJXaUN5UmZJdEdyUXMyS0ZTNWMzQTZ0ZFdMcktVOVlYQmtabGgwMHZEUnU4SGYyUUovdzlzb1NQWW5aNmFpLzVBbm84ckxwNk1rcXVka3N4NG5FZ1pzRzArSXdvOXM3V05YekE5RlhaczRsV3IvNDBuWjBXUFVhN0w1dEJmK2Z1dU01RXBTcFIrWmc4OVVEMkhoMUx6Wkg3Y1hTOHh2eC9wNGYwV1h4WTdDYjFnRDJjKy9GZXdmbllEdVBrYkRBZmVHZGtQZklKb1N3S3lySEtUUnBOdVFjRHFMZnEvdUNoM0NWelhNam1nWFVSeU9mbWlSY0x2Q25QTm9DTE1QcjErUG9PYlNISFZsMWJ1NzVQU3R2TnpqNkF3K281WDRYbmhyRDRKRENGaDFIV3VDbzc5eC93eTd0UEFkUmFha29OLzZnb0NCeFhoeVRqMk1XR282ZExUb2ZIeCswYjk4ZUN4Y3VGREVOK1h0cFljL0Nvcnp1U2pKZzNCSWNpWVNER2ZQNThXOXlKV1BPbkRtaUQ1R1hjYlIzanRFb3FVQWMxTWgyZE1MNHpSK0tjSGFYazBtTWpMZy9zaXZ5bnRpSldiMCt3cEorVTdENHJxOU0wdXFCMzZDWmQxMjlkN1crTUt0VUtseTRHTU5MeXFLbEsyQk1qTXJCRVIyRG15bmZiakZxMDBmSVkzZE85cnBqRHo5dWtqSWs1TUF4TnhPenU3Mkp4MnIwMEc5Z3hxU0RmNkRWUDg5ajZPclhzUzNtTU9BVFNha0d4RVNVV2svYUx4V01Ja29HSlo0UHk4VmJQNUF2a0F0UUhkN2M5eVBhcjVpQVhtc21Zc1cxZzhwZVRUazMrSHYwRCsrb3I4RlFiZWZXTWZMeDBuZnZTTFQ5OXdXa3NHVm1SSFAvZWlUWTduRFhGR3hKWGI5K1E0Zy83WW11NCsxdGNYSFRHUWVSdFFadVF1U0NrWVBhbGdZZXA4V0ZhM25DY2ZsWWtLeUJCWTdIWS9uNyt5dExTazVoa1ZiWWttZEJLUzNEaHc4WEZ1VDc3Nyt2TE1uUDBLRkRoWkR5UklpU0NvVExJUGNRN0kwNWdqcUx4dUpiQzhFU3hsVHZpa0hWV21Kd1NDdVR4RTVxRzNxOWp3Z091bEFGSXZad2FWL2hxQld2UWc2cW1abGwyZUlLY3c5Q05WZlRTU1E1Sk5MZjdKMm5KVEVSVmd4Yk5Kem9OSEp5WUorWmpoMERwbU5VUlA3SjZsWkY3WVBkenozeC9zSGZFSjJkUm9KRSsxYTVLZHRUaHB2N3NwUm9QVWVyc0NjcnlKa0tFSlVyMWtRZlFiOS9Ya0MzOWU4aWpxMHJJemh1NGJJdWI2Qm5aSGVsNDVPT3ozaC9EbHBjU3JpQ3gzYVlqdk55MWJpZ2xsYzRmQ3hZaVFaUzAxSkVyZHpPd1E1cWRydS9UV0hMaXB2T2lrUDE2dFd0ZGtJb0NKNHp6TktNdFdWSmNjTStzUmdiNXFJcURZWjUwQ3hSRnRGQU9QRHdnZ1VMeE15NzFzQ2hzeW9pb3IzRURLcVVwMlVsWXM2SnY2bnNTbEVXRm8yN3lnbStaTFhwQzhUS3BWS0V5OFhWUlJTK2pvNE9pTHRoZWRBblQxOXYzRStZbUpXQzl3NzlwcmVDN09qQzhUcERJa3NMMlNsWTBPTnR0UENxemd0TTZMdnhBL1JaOFNLVmhpUjRIRVdEdlFuRlBzejJJeEw5Y3pPWnIxTzJZY3VKblVWY0E3RGgwallFTHh5RHY2N2tiMkphMWUwdHRBeG9ET2pvNFREWkgrMkRqbVh1c2FYWUhIdGM1RFZRemMwZjN1d2hXUUM1T2JtaTVzeHg3MjVudUIrckpIQ3pHNmZTWUczNHA1SlEwb0thaDVDTUdqVksrVll5Q3ZQMExPMThYaHloNDVOUFBsRytXUTlQS01uUitpVVZSRllxTkxwTXZOVnFIRFlObUNZY3dZeEp6NlNLbXk0clgyS1A2YmNQemNXZVpLcEFWY0s0TFhNcVJiaDh2SDFnUjJZcmQ5eGV2V0pkZkxIN3RrK2xtbkEyaVE1YkdYellTdUtMU0xXR1Y1czlqS0hzMldkR2pjV1BZZVdGN1NReVFaU1hMVDFXRHNQMnRLMjRDZlNaelYvZVB6ZmYzVXowWFRpUEtMOGo0c0lidGxWVXlNa0htZllPR0w3dUxYeG5OalVKNTlqZGgxNW1qcWpCSGp1RzN4TDdvMFRDOXpCUGpHa0UyVkppOW1OTGNITU9EeDhRd3VYSllheHVUM2h5eWRMMGdYQjh2ZEtRa0pDZ2ZDcDdpaHRWM3BqU0Z2Q0ZXVnlsQ2Y3THpaazhwMXBKK2Y3NzcyV2ZWM25ENDJWVHI4UGZPUURKRHl6RzIwMGVVRmJjb3NmcVNhZzIveDZFL0hrL3BSRW1xZHE4dS9IT2dWLzFaUmxYd2lzWkxrVXJISDkvUCtFVjUwQ1d6K1VveXpINWpEbVdmQTByejYzWE54R3lIQWhyakJMM0YyVW1ZMkJZZTN6VXlIUzZna1NxV1FUOCtTRE8wczBTQVhiRk5rYmJpdTNwT3pmelpTUWd3c1VIdmYzclkxUm9HNHlzMWdvUGtnZ09DV3FDaG03VlNNRFNxQ29TVDl1d3RVVy9hYndQUGg0V1U0MFhudHI0SVNhZitFZC9BRVljNlVlMVdlNlg0NzRUNCswY3RUaVRGSVd2emJZcDZMbTRjdVdxaUR6Q1RWbCtmcWJqTW00bmVFWmtubGl5cEhBZlVta29yNmo3blR0M0xwVUxmMkJnb05YTmNKYlFGZENmek42WjNFUmFVdGhxS3MzenlIMjJuMzc2cWZKTlV1Wnd1YVBMd0pka1pVWGZNNXVzZDlPaFJYTXZiSVhuTC8ydzd0SVd4RHVvY1MxWFJ5bkhKRjFsWnpnVmxYTmMvbFVCdUFTdGNMeTl2VVVCekUyRjE2Sk12VnNzOGVIaE9TS0lMWmYxZXZGUkV0Y2l5RXI2dWYwTCtveEcxUG5uT2NSa3A5QjJidm9GeHR0eDBxVUQ4WmR3WDJSUC9OdjdZMnp0K1JGVzluZ1BzenY5RDc5MWVRMi9kbjRWaTdxOWlVMjlQc1NPUHAvaE00NUNuMG8xMWpSS1loOHNRRWI3VXpvK0oreWNodm1YVFpzTjYzdUVZbFN0dTRCc0RoTmx2QjE5cG9maCt6TnJrU1VzdThLNWNQR1NhRExpcHF5UWFpU290eW1sZFVUZ1BpRzEydkk0T0dzb3I3RmFQSGxrYVk2TFJhczBnbDRRcFkzaS8vVFRUeXVmU2c1WFZzckNlMUppZ2V4MDlBNXNJWUlkbVBQZTNsOXcvOW8za01pVmVPNWI1ektKeGNrOGNXdFJPYjBYSllHT3N1TGhpQThPRHB6c2NlMWE0VUZMRHlWZXhCOHNCRnhMdUZuZ0s0bXNwVmtkWDRRUGV3QWEwV1hEKzRqbVlKSWFEOHBIQzR5M1lUSVQwVHVvS2ZJZTI0aTU3WjlGbjhER0NIYnkxSzh6dzB2dGpEWSt0ZkJTdlNISWUyZ2wzbXIrTUlsbEZxVU0ycCt4Q0ZGaThYTHl4bjJiU096aVRPY0crcm4xay9DbGRmb0J5b1p0YUlYS0dmL0ZITVRXSXNhS01USFJNYUo1TlNzckc1R1JrY3JTMjQvaVR1eG9EbGVNMkZXK3FzRVdVMm5nZnMyeThDNDBoOGZIbFJSdTRpdXJtSmx2dmZXVzhrbFN0dVFpZ0N2K1JseExUNERyNzRQdzVyNFplc0VxbzhBTUZVV2xDQmNURU9DSGJGME9uSncwdUY1STIvdXU2eWVSbTVWTVI4cjlVM3k0U2lMck45UTFBSVBET25LMm0veDdkUzgyWGFVYUpEY3JzamdZOHJQSWNCTlFTZ3lXZFhzTEs3dE9Fdm1MeTlzTjc4RW1zc3dDK1VGZzcwVGpmaXRPWXI0YVJ3emJhdG9KNzBESDhueDkvVlQrcG4xZGRJeGFIN3o0MzN5UnJ5RFkyazlPU1JaL1BUemNiMDROY3p0U0dxdkVRSG03dEpjRU56ZkYraThGNVdFTkppVWxLWitLVDNFRCtCWkdhYVpna1JTQ296TlYvcmRoMlpXOXlNaEt4OVFqaXhBMC8zNmtjZ1hjNExuTjc0dGgyaWR6c2xMMFFYbHpMVGMxVndaY2VsWUtkZXZVUm1aR2hpaWtUcDBxZU9iU3lUd0pwTm9OR2hJZXRaSTBiTHJ5N01lMSs4SlRaVHB1NTU2ZDN3b3Jodk9vNmZSRWZoSUtEdHlPM0d5czdqY1ovWU5iNkRPYmtVUW1kWFI2SEdMb0pzV2szVUFjL1lhbDRxK1RiMjBjb3YzVWN3c1NmVmZpdHd6SFIyYVVSdTJPcUlSTG1IRjJnN0tGbm9sMUI5SzV1Tkt4NUlsajB1ZTNoeU5aalB1akRscWNRZGxBZkh5OGNCcmdBdG5IeDFmMEM5eXUzSzVOUmk0dXBpMER4YVU4eEpqNzg2d2RVMmFKTm0zYUtKOUtqNmVucDJoUmtKUXg5dHd2bm9XN1YvMFBqWmVQeC9NN3Z0SlhtS21jRkVLVmt3MDFyZmZuenh3ZHd4RDRuTDlucFdGQVNIdDgydlpaVUNtcWIyMnFBbFNhY05XclYwL0VLVlNwMURoZHlOeE5SMk9Pd0luRVNVV0h5bEhVRFltYkNkK3BQMXpKcFdmbXVRMUlTWTJHcThvSmppUWdOL1BUamN2TmlNY3Fzcko2K3VmdnVGOThlVGNlMnZReGd2NGFqY0JadlJEd2MzZVJmT2JkaSs0clg4SHNNNmJCY1JrL0V0UGRmVDZIWFc0ZXZmdzVVSk40M2Z3OSttMUhGMTk4ZG53eHNzeHFLUy9YRzBnVmx3eHhUSWI4TE1vY2IvSG5jeHVWWFBsaGo3RGtaQjVqcEVONGVFaTUxTHlyQ21WaG1WUkZTbHZaS0k5N3prNFpYQ2txS2V3QldsWnczMlJZV0pqeVRWSm1VSm5obzNGRDZwaFZPRGwwSmc0TW13MDF4MDlsZ2FMeWllY0lQREYwRnFKSExzRnpkWWZveFl2UnBhT3JmMFA4M2VOdHZOeGdHUGIySThIanVwTkIyQ3FSU2hNdVQwOFAwY2ZGcWFDeFhFemZpTTVJMTJYRGtZVkJTWmxVUTZnVGxEK3F4a2ZIbGtEcjdDY0dBQnZ5cXUwZGtaS1poTEcxQjZCWFFFTWw1eTBHckg0ZFE5ZThobDlPcjBJYWh6UHhEQWU4YTFDcVNWZkhBUnV1SGNTWVRSK0pXWTF6eldxOExvNXEvTnIyR1dUVGRzYS95Y2ZLVTdHY1RvN0dQMUdIbE54Nk92bldwZjJxUk8zRmtKK1R2WjA2MzVndVkySmlZNFZBY3EwNzlEWjJ6R0RLeTZ1dnNxbUt6WmRNYVFaY2x6WlNpVEVzN0xkcnBhVlN5ZE1oMUMxRXhEaGw2cnNIb3c3M2F3a0xLeDNEcTdWR2hLdmVLL1RwZW9QaHJYYlhpNU11QzYzOTZvbmxETS9VRWNSZEpGWGdPYTQwNFdMdnVGbzFhd2dYM1lURUpFUkZYVlBXbVBKd2VDZFJLOUJTNGM1TmNsb1NvbXlxRVV5c2F6b2VadFcxdzRqT1NJSTcxUjQ0bnlIUnhnaHpEY0MwWnFQMUdSV1NXR3grRzRUbFBNYUxRL3R6dUNmYXQ3Z3BvcTJYRXZkRnNUbXQ4UkN6ZkRyTTdJSkRjZWVVUGVnWkdkNGU5NFMxUXpiVmFveC9sNDlUN2FqQnp4ZE1yYWl1ZnZWRkU2TURWWjZOOHp1VENGN2hBTDBGY09ya2FWSGo1aWxoZk11aGcxNXk1MUpWckhjVzl2SWMvSDNua29jOG8zdXNvd3B3amtGOHFHeU41TmlxQ3R4Q1pQdzQ1Qmg1TytkUW1jaXBLbEJwd3NVdlMzaEVoQkN1SkJLdXVBS2FLeHE0aHlDQVJJVVBWRTEyaWlOOTBqaG9VTS9EMU9yWUYzK09MS0pjZmQ4UjVUTWtGcFRSWVoxTXBqUGhGMlRZK3JlcHBwbXVqMFhJZDRwdmx2aGJRQ0pCaE5ZVmJWYmtkNzEvdW1ZZjZMaWQyT2gzdVduVGgwUnZuWm5GeGZOdFZYZjJGWDF1eHZudHljcG83MU5ieVpXZjR5ZE9pdjVBalZxRDRLRFNlYWRKSkZVUkZxMlltTUs5akNVbHdhNlFJRTEyK2Jvekt0K2VLcHBLRXk2bVduQVFPTW8zaitjNmNzVHlkQklOUEVMUTFyc203RWhzMk9yaXJ0dDZyb0Zrc3Q0S2VjU1ZoOE1KRitGRzRtU3d6RGl4ODRPbm94TlpSZTJVbkhybW50dUV0ZWMzNmQzbGhXTHhaVkFTOXpjeDRxOVpjblJHUmxZU0JtNHdEU0RheGI4dS9NbUVaczlCNDk5M0k0Rk55VXhCRkE5ZU5xS3BaeGdkYzY2d3lneDU4OGd5ZktKR2R5V0hLVmVqb3BDUmtTNmFkQUpKdEp4RWRIMkpwUFJ3QmJJMEZoZkhHeTByTWpJeUNvM3VJU2tiY3Fpc1NjMUtwWnBDTXQzQUpLUWJCZnRtYXl5WnZRZzVNQU9sTktOMVZRa3VrU3VOaU9vUklsSThXeEtIRGg5V2x1YW5pMTlkNU9YbWtSQTVrRzFpaHlDeXdIaDhsWUhVbkF4Y1NvMkZxNzFhNUdHcml4UDNPM21RcFZTWHJEWmpIdHZ6RFZsYWl1Y2F2N09HeENUenZETlo5SmViTHJtNWtQNFlyOWQ2WVJtSm5uQWxOV0o0U0N0azBUTGozK2ZQWGxwM3JJOHhEYWZUMGp0UzlGY1o4ckh5MWlJeHRqUUZDN043OTE1b05Cb1JUYjkrdmJyS1VvbWs5UEQ3eHlHYlNrcFp6dC9Ga2ZrbDVZK2p2UXBqSTN2Z3FWcDM0Wkc2ZzlIQnFCL0xSK09LNTJyMHdUaGxYV2YvMHNYOUxDOHFWYmk4UEQzaDd1NG1hbnp4Y1FrRjFyYkcxZW90TEsyYllrQ2k1Y3pqcFJReWNySVJSelVIVjBmMVRURmdhOGFCQktFaFQwbGlSbXJpRlhDRWRoTlZZdnM0N1RxMkRQNE9hUThzd29IaHY1Q0FjWmdtYnRNMXlzZTFVd2RIekwrMGxiN2ZvcU52WGRIOEo2d281UmpZa25JbnErdEt1dWw1MVhZbFM1TitrTmR6L3RUc05MeFF1NSt5TmorblQ1MFd3cFdXbm9hMmJjdk8vVmdpWWRnTnZhVE1uVHRYK1ZSNmZ2enhSK1dUcEd6Sm81S0x5eTg5R2djVjNtenpGTDdwK0RKKzdEWUpkMGQyVmRZQUljNCsrS3o5YzVqZThTVmE5d1pHMUxUY0NsVFpWS3B3TVMxYnRrQnFXcG9Rc05WcjF5dExUZUVMM1NlZ0VYUjVPbWpKaXZKVnVlZ0ZSSUg3ck5nRjNVa0lnWkpJT0ZnYzZyaVo5Z2Z0alR0TDIzSjBlSGJjVUpvQStUT1p4UisxSFk4Ty92WGhSTC9YeExzR1Btdytsc1NMWFVPVmZDTHB0enZEbHBrUklXUXRpZCtuZlJrZmd4dlZidEt5VGMxdERRa2ZyM2VpOVN6SUlXUkJEZzVwcVY5cHh1a3paeEdYa0lDYzNGeFVqNGhRbGtva1pVZHBvbkg4K3V1dnlxZlM4OGNmZnlpZkpHV0xIWEk0WWs4cGNhUnlrN3REcWdKY0VsY3E3ZHUxUlhKU2tyQW96cHd1ZUR6WEMvVUhJRE16RFM1VTZKdFBhODlodGx4SUlKeHB1ZUd2U0hTaHRTSWkvQzFTdVJuUWdjV0tOaElUTzFJU055TlhQMG1hRVR5K1FXRElkelBaSXlYWFZJeFlQUG4zYnY2Mmt0ekpDaFJSN1kyd3o3T0h1NzJhckVaOTFQaUJ3UzNncHJJY051ZnMyVFBJemNsQk9vbDdtOVpsTjBXOVJHS2dSbzBheXFmaWswYlBaVm5NNWJWczJUS2twRmcvTjVTa0dGQzVkSU1udFMwbFYxSmpFU1ZpdFZhNmJGUytjREhObXpVWEhrVXB5Y25ZdSsrQXN0U1VlaDVoR0JyU2xpeWdIRGlhdTcza2tiWEZvbUZIWWlEK2tualJYeGNTQnpzejkwMGVpQ2NtY3pSMnZ1RFBaUDFjNXc1TEl4eTRPWkxFNTJZK1ExNnF3ZWl5bEVGNkNxRXVQdlI3anNweDhPK3J4R2RmbFN0MlJCL0ZqcGhqd3V1Um85YS9mMmdPSXB4OG9hSDljUi9jcU1odXlsNU15YzdPd3Q0OSs4WDRGZzhQRDlTdmY2c3RXaUlwS3pqVUVqdEpsWlIzM25tblZHUHZlTnRKazBvV2drMWlCVlRaajhwSWhQMnMzcmg3NDRkNFlzYzNlSFQ3MTBXbXh5aU4ydklGSHQ0NkZVL3ZtWW5PQzhlUTJVVmxZaFd3dWtyK3RKWWhiVnEzRkI1RmZFRUs2K3dkR05aYU5MRnh2NVB4WUU0SHNvTFlzdUdtT2ljV0R5WHhzbVF6TVFwd2N0ZUxrYkM0NlBRNWljOHFYREh6L2d2bUNSMTV5aEtUdlB5WGFqQm1lVGxhUjAzWEFMQjl4NWFXNFJpY2FiL3VqaHA4ZEdBdVh0bjVBOGJUdzNBakxRNGVIS29xVjRmbTNqVVE0V1k1SU96bFMxY1JIUk1yUGdjRkJjTFByK3dqZzBza1BITjBhUWIrOGpUOEgzNzRvZkt0K0h6ODhjYzRjTUJ5aFZWU1JsQjV5WEp6SnVFQ1p1eWFocGxILzhUTTQ0c28vVlZBV29RZkQvK08zNDR0d2tPUm5mQmFnMkg0c3N0RXJtV0lmVlUyVkFwWFByWHIxQmJSdkhsUThxNWR1NUdRWUhtbTF2WUI5ZEhZS3h6cFdlbkl6TDNWL0tZaWdXQjNkS2M4QnlFYWJQbUlaanA3amNocmpDOFBOdVkrTFZvdi9obytrL0RzVEREMWFtcmtHUVlmdFN1dFYvSVo4am82WVUzOE9SSzZXeE1PZXFoZDBEZTRCZXh6Y204ZWcrRTRQQnkwWWt4WE5KblpEclRlbC9iSi9WdTVPaDNlYTFGd2tOSUZpeGJEMWRWRmhNWnExeWIvSkprU1NWblJ0MjlmNVZQSllJdnBuMy95ejBWWEZCczJiTURFaVZRZ1NzcVBuR3pVY1BaRHprT3JzSC93OTFnN1lxR0ltU3FDSzNEbG5JTXZtQ1N1c0t2ZzVCWU0zYU9iMENXb21lakRmNkhCVUxUeUNDUGhLbm1rbGJLaVNnaVhpNHN6NnRhcGhlenNiQ0ZlYTlhc1ZkYms1N2xHdzNFak13R1pSdTdvS2pzU0xpZFBFVDVLVFdheElUbXAxRWpSV1pnZ2p5d3hNWkNaeEVNa2RySW5DMmhuNGxrbGc1NWFydjd3NU9sT3FJSnhLeS85QmxsUTExT3U0VWppQlNXbm5pR1JIZUdoZFJFR212RnhjTkk0cWtUSUZDZVZSbnpuNHg5UnM1c0lEMldKUzVjdTQzcHNyR2dtVktsVmFOUzRrYkpHSWlsN1huLzlkZVZUeWVuZnZ6KysrdW9yNVZ2UmZQUE5OK2pXelhJenVhUU0wYVdqWjlBdDU2L3Uvdld4dGY5VWdDUDE4QVMzNW1RbUlzQTVBSmVIejRhRFVYL1cxZlI0WE14Z280SnR0OHFsU2dnWHd6VStiaTdrQ05xN2R1OHBzTTJjd3pmMURXbUZXQ05yaCtNUittazk5R09vU0FnTUlpTmMwMG1pa3N5YUMxc0VOcWI5NjZDbFdnWG40ZVpIZDdLaTB1THpqeVBwNHRlQXpPTWM0V21vejZ0dkFuVFV1bVBDb1RsS0xqMU9EaHE4MjNJc1dYa1o0QWp3NHZjTmdtZVVPTEF1UndNWldyMnpzbVYrdG16WkprU0xwK3Z2MlVPKzNKTHlwVTZkT3FXZUw0emgyWkE3ZE9oUTZFQmlIcS9Wb2tXTE1wbUFVbUlGRGxwc3UyRWE0S0c5ZHcwczRwblplY2lQc2ZOWVpoSlZsTjF3N2U1ZjRHMDJ6K0Y5Njk1QmRBYmQxd0lxMnhWSmxSRXVqVWFObGkyYUN5OGxudEovNFYrTGxUWDU2UlBXaG9TS0xDRURWQUVJYy9FVEVkcUZ3Q2pKeVVFTmpzSitJVGxLeWFoblpFZzdNZWJLelY0dGd1Rnk0czl3OHNHdjV6Y3J1ZlI4M1BBK0lEdmpaajZSN0ZVSTFIamd5UFhUV0hyRmRQYllJQmNmZk41aEhBS2R2TVg0TFBhQWRPTCtONk9VbkptS2NXUjJ1M0EvbHdVdVhyeUVBd2NQaWlrZWVJeE51M1p0bFRVU1NmbkFYcjFsWVhVeDI3WnRFek0xZCszYUZUTm16TUJ2di8yRzMzLy9IWk1uVDBidDJyVkZCUGpTenJvc0tRWlU1aHlPTzQwZUsxOVRGdWdaVXEwbE52U2Zyb2lYRHNoSVFDTy8ra2pocGtRamttbDkwRjhQWWN1MS9mb214aXBBbFJFdXBrZlBIblQ5ZE9BWmtnOGRPb3lrcEdSbGpTaytaRjE1YUV3dm9JZktSVmd6YWp1OXU3d2hjZlNNbURSVFI0cDJ2alhBUVpiMDQ2MzBWaFJiYWtGT25saHdlYWVTUzQrZjFnMHRmR3REUnplV0xhMmIrZW0zd3QyRDhMK0R2NHQ1dTR3SmN2YkZLODFIWWtTTm5zam13ZEZrSGFabHBTT0xIb0RZdERoMENHaUltcDRGVHdleC9KOFZWS2x4RUo2V3pabzJnVk1aUnVDV1NBcml3UWNmTE5WZ1pITTJidHlJSjU1NEFxTkdqUkw3bmpCaEFrNmRPcVdzbFZRb0duZXN1N1FWblZhOHJDelEwOFd2TmhiMGZBK0lQWXJxN21IWWVkZGtNZ0JNWmFINjRzZHdMZWtxWURaY3FES3BVc0lWR09DUGpwMDZpZmhuWEdqUG1WZjRyTURHUkhwV2d5ZUptWllzSW02eU15UVhSeTJ1cHNXS2Zpb0RkZDFDME5tN0RqUmlQSlhtWmdwUXVlSjA0bFVjU2pEdHUvcWgxZVBnQ1NMWktqUE83K1Bnakd4ZE5ucXRmUmVwWEdzeFFrUEgwVDIwSmI3czlEeSs2dmdDbm1vMERIZlg2STVYVzR6R293MEhLN255YytiTVdSdzllZ3hhcWdGck5Gb01HQ0JuaFpWVURGNWVYc0sxWFhLYjR1SkxWdE5lTlB6cllXUVpOUThPRDJtRGs0OXN3dWxoUDFIbC9GWXpZSHAySnV4bWRzV050QmdxMEtxR3BXV2dTZ2tYMDdON0YvclhEczdPempoNDRCQ2lvNjBiT01mVCtQTWdYbmJVNEQ0dlEzSjFkRUpNYWp3Snl5M3ZRaysxTTFyN1ZDZnJ6QTd1RG81d1U1S0hnd3FxdkZ5c2pUcW81TlRUekxzNjdpSXJ5VDR2eHlTL0s2VlFyYnVZWm1YTXRxOFFtMkY1Q25TZUNMT3VWd1RhQlRWR1RZOVFaV2wrY25RNVdMTDBiMUdBY0I5Qm45NDlZR2ZVT1NxeER1NGZOUjR1Y2J0UUVlZjA3TFBQd3M5UFB6ZVQ1RFpFNjRVamlSZlJhTkZEeWdJOXRkeURZVzlVMXNTbHhTUGd6eEhnQ1c2RjkyRVZvOHFWaXE1dWJ1alpzN3R3aWZmMTljR3NYMzRUQTNldG9acXJuM0I4NEw0dFEzSldhYWgya1ptdnVYQmtSQ2Q0a3dYbFNWYVp0NUs4SExRSTAzcmk3L05ia1p5ZHB1VFU4MTJiY1hDeGM0Q2JuWXJ5YW05dTQwbS9VZFBaRnlucHliaG4zUWY1Uks4NHJGMi9IbEZSTWNqSnlVVllXQ2phdHplTmFsK1ZLS29RTGMyQTFOTEMwZk81NGxNZVZLWWdzck1PcDVKaTdiRXZYR2pheDJFcjNJNlZsVEtGeTFFT1lVZVYrWk1KbDFGejNqMjR3RTJBWmh4UHVBU2ZuN3JxbzhTelJJZytNUGJpcmpyWHQwcFc1OW1MTGpEUVgwempjZjM2ZFN4ZHVreFpVemp0QWh2ejAwdUNkY3RCUTJ1dmdxL0dBN3VpVGVmRnF1Y1pobm9ld2RDU2RjZmhsL1NKUk1sUksvNStmOVRzTisyQXoxcU9oVU51RGx4SndHNXR3NDRkS2dTUUtSMnE5Y0JIKzMvSEt6dG00SitMTzVIS015cGJ5VFd5TEpjdi8xY01EZUFRVWNPSERWWFdWRTJLS2tBcmN5WmJkalFvcjZsZjJHR21zdUJaRk5nYUx5bld6bGJjcVZNbmZQSEZGOG8zMjZFME1SZXR3Y2VuYlB0NEtsUm9XWHd5MDlERUl3S05xZXhyRk5BUU9WUUJmMkRUUjhnd0txZjJ4WjNEa0RXdm9VNW9XelR5cVlWR0h1Rm80aG1CdXE1QlFGcWNYdnlxQUZXMkhXclF3QUhJenRhSmFSZldybDF2VlpOaE1GbGNMbVJocVJ4Vll0eVVJYm1vdFVqT1RER1pkNFlaVjI4Z2RMb3N1SkZZdVRwcVJISWhLNnFhc3c4TzNqaUZJL0dtZlYydC9lcmkwYnI5a0pPcm8zd3F5bjlyTzFmYXpsM2xoTHB1d2JpZUhvODVwOWZpZnp1L3hkZ05INHN3VDBYeCsrOXpxYkIzUlhvNlBWeU5HNk42OWFvZFVMY28xK25TTkRlVjFscmpzWUNjU2twaG9oc1NVckJUVFZHVWhSVmFtc0t1T0pVSmRxUmdyMEJib3FqS1ZHbkNXakZjSVNwTHVHSmVHcXgrbnFpODhpVXI2K3p3WDdDbDM1ZlkzUGNMYk9uN09RNE4rUUh6ZXJ3RFI0ZGJsYkVhcnY3WU9QQWI3T28zaGZKUXZydStFUG4zRDV5T1Q5cy9EMlNsQ2VPZ3NxbXl3bFd2WGwyeXZMb2pNWkdiREgweCthdXY5V0doaXFCbFlFTzZVV3gxYWNuaXVwWGMxSzdZRjIwNmxxR2VWd1I2QkRjWFlabzRacUJ4Q3RTNDQ3ZGovNUM1Yk5wa09DQzhIWjZvTjBERWlPZklHT2JiY1hpblFLMDdnaWc1MFAxOXRzSGRJcXBHWWZ6eHgxd2h6RHk5aTRwcTlQZmZmNSt5cG56aGFDVWx4ZHZiVy9sa21jaklTT1ZUOGVIS1NtbmdzWUNsOFk1ank2WWdRa01MN3FNc2lyTHcyQ3VOSlZ0Y0szVDkrdlhvMDZlUDhxM3FVOVF6VnhvcnZEd3MrRnExYXBXcWdtWDFQR3JaYWJnbnJBdXF1d2VKU2paWHNEbHhoVDNFeVJ1T1ZJNFo0TElxZ01vK2R4V1ZaWVo4OUptZDNsNnVOeFJ0dk9rYXk4Z1poZE83ZHc5NGVIaUtDUlR0N2Uwdzg2ZFp5cHFDYWVSWEcySHVnYUkyd2syR2h1UkdOWTZFekNTa1pwdUdnT29mMFQ3Zk9DdE9IbUtpeWx6TU9wWS84bldYYXMzeFJJUEIzSG9vd3Z5YmIrdEFLOWdOZmxMTGg5SFVyNlorb3dMWXVuVTc5dTdiTC9wa010SXpNSHIwZzhxYThxZEJnNUpQRWxkVXMweXJWaVdMWk0raXdXTjlTa3RKbTlTNElDbXNaczBEZFV0S2FhS3dHeWhOWmFNa0UwWXVYNzRjTFZ0YW5uS25xbEhVUFM5Tk15c1BtQzVydUVKZVVpdVFLN2tjWTlJcTdGWDRMNlgwazNRbVoyY2dWbFRrWmVTTUlubnUyWEZRYTlTaVFEbHo1cnh3MWlnTURsSFNLYVFsNnZ0R2lwayt0UTRhT0pOb3VhaWNvYlpUNFpSWjgxK1lXd0Q2aDNVUWJiZnVsTWZOVVo5Y0tRVTZlNHNndmZOT3JsSnkzNktoVDAxODBtRThJbDJEUkQrYWh2Yk40c2locEtxN1ZjT0g3Y2JCbDhORkZjTHhFeWV4WU9GZm9oYWRuSnlDb1VNSFU2RmRTMWxiL3ZUclYvRGtsWVVSSGg1ZXBEQzFhMWN5eHhLMmxrb3pJNitCa29ZU0dqcDBxQ2dVQ29JSHo1YmsrRmdNdTNjdi9hUjg5OXh6ai9LcGVOU3RXN2RFRGl2Yy9MWjc5MjdjZmZmZHlwTHlvMmJObXNLcnNTUjA3TmhSYkY4WVhIRW9hZVdocE85S1VaUlVUSG03b2xvOWJrSlcwK2FvQXhpOStUTWN1bllVdTZNT0ZTdnRvYlRyNmdGMFdURUJaem1ZZzR5Y1VUVGN2UEx3bUZHSWk0dWptK1dCQXdjT1l2V2FkY3JhZ3FublV3TXRBdXBEN2FnU3RScnU2M0xUdUlqK3B6UXhPZVF0T2xScmdqb2VZU0prbE1FODFwdlNUaUlDUm14cUhKYWQyYWprTnVYaGhvTnhiNjFlSkdTUklzeFR4NkRHR0Z0L0VGbGVoYmVIYzlQZ2I3LzlJYVlyU1V4TVFyT21qZEcrZmNWR3lPamN1ZUNRVTRYQm9sVlVIeGJYSm5uZ2FYRVpQWHEwOHFsMGpCczNUdmxVUEFZTkdxUjhzZ3dYL284Kytxanl6WHFhTkdsU3FDQmFTL3YyN1V2VVhEaG1UTUhCbkszaHp6Ly9MRlljd3VMQ3o5UEtsU3N4WmNvVTlPN2RXMWxxUFR6QXViQW1Yb2F0MWFaTm15cmZySWZ2VzBuZmxhSjQ4Y1VYbFUvRjQ2T1BQbEkrV1lMN29NeWVOYlVMZmozOUw1b3NHWXZXU3g4dlZtcEZxYzJ5cDdBLzRSeWd6Zi9zNlNyQmc5Z3V6MFo4U0xkdTI0NzVmeTZFTjlVMHVOOXIrUENoNkdDRnU3Z3VWNGV6OFplUmxKMENCeEV2STA5RWsrY21SZU43bTBabThNb0xXNUdWa3dWN0VqQnowa25zL0oxOTBET3NiWUdCY1ROMG1kQVdJVmdNOTlXOU5uRVMzRnpkeEVCcmRuMS82c25INkFXcCtIckV5SkVqaXozenJMV1BESHVFTm1yVUNOZXVYVk9XRkE0WEVFbEpTYVh1NHpMQVFWeUxFdytQQ3llTzltQU4zTXg2OUtocG4ybGhjSHkrMGpoMkdNUEgyTFVZamhQYzlMcC92NzQ1dXJSczNyeFpWQzdPbnordkxDazlMT3IvL3Z2dlRZY2ZkbHJnUGlVT3VtME5iTW11WFZ0d1lHNWpFaElTaW0zbHNKVTdmNzcxd1JDS0EwK2V5Y2VqMDFrL1F6RS9lNGNPSFNxd21USGdqNkdJeWMwaGM5bVNCMnhwS2s4VzN2dlVXRXhzOFJqZWIxWTJGVTVycWZJV2x3RVdxYjU5ZWlFeEtWbFlZYk5uLzRZOWU0cU9kOFlkajdWOUlsRGJLd0p1YW1jU0ZqVWM2SVpmTlpzUjFGbWxSWi93OW5CMjBNS0ZuVG1VSmtOREN0RDZJQ3M3QzZ2T2JVTjB5blZsSzFPc0VTMTJlMy8zM1EvZzd1WWhYa3dmYng4ODl1akRsU0phRE1lUWE5dldla3V2T0xQZHN0VzFZOGNPcTl5VVdiUU9IanhZWnFMRnNOWEYzbkhXd0tKaXJXZ3hSNDRjc2RvQmhhZjdLQ3ZSWXJwMDZZTHAwNmNyM3dxSEJXRE5talZsTnE2TlhlWFBuVHVITjk5OHM5UjlkbHp3c3FYRWMzRVplNmx5OCtUcDA2ZXRlbTd1dSs4K3EwV0w0YkpqOGVLQzQ2Q2F3eUpSWHFMRjhQUE84NWxaQ3o5elBGdDBZWDFqdzJ2ZVJUVnhMcU1zaVJTTFQwbVRHVnlCemRGaFdGaDdaVUhGWVRQQ3hkelZ0dzg2dEd1RG1KaFlVUkQ4TVdjZTFxM2ZvS3d0SEhlTks2cDdoaURZeFI4YWV3M1NzaktSYWpaWGw3UEtDUjJxTllNTC9YWFZPTk0ydDVLYnhnbSt6cDRrZms0NEduOEdoMkpPSUp1c3VlS1FUS0k3WmVvM1NoekNiUEgzaVNjZmhVcFZlQk5IZWJOOSszWVJVNjRvL3Z2dlB3d1lNRUQ1WmgzY0g4Yng2ZTY5OTE1bFNYNGFObXlJaXhjdkN1dXNyT0h4U045Ly83M3l6VEpEaGd6QmlSTW5sRy9XYy96NGNSRU52U0M0SnMzbnpqTU1selVzeWl0V3JGQytXWWFieGRncUxJMG5aRUZ3YUtoZHUzWmg5ZXJWSmRvL043ZWVQWHNXdi83NnE3TEVGTzVMUEhQbWpPaHp0QVQzZWZQdno1MDdWMWxpUFlNSEQ3YnFmck5seWM5OGVkTzRjV054cnNIQndjb1N5L1RzMlZPSVhFUkU0VU5sUG1zK0JzNU9aRldteHBDd2tOVmFIa21YQlNSZHhqME5ocU81VCtGOWkrV0J6VFFWR3JQazcyWFl0SEd6cUQxZGpZcENsNDZkTU9MKzRuVmFwMlNtaWI0dUw2MGJWQTZtTHFuWnVkazRFMzhKT2pLM2plZWp5Y3ZqVUVJUS9XVUJybjRrWW9XN3VSdHo2TkIvbVBuekxIalJNV2RrWnBLbDVZV25uMzZLSHJEeUdTaGJFdGdDNUFLUmE5VGNITXNPQlZ3ajVMNHFibElzTGZ5b3ZmZmVleUo2T05jWXVUYjc5dHR2QzRlTWl1Q05OOTdBcGsyYlJGTXRueGRYZnJoUHBhUWQ1TVo4L3ZubnduMmN2Vmxack45NjY2MHljVEt4aHErLy9ocno1czBUemM1c1lYRmZEbHRFcGZFYUxRbExsaXdSWXNxRk1GdlEvQXp4WDRNVnpjNFQvSHh4UVYxY2R1N2NpY3VYTDR0K0xLNDg4WDdMZ3IvKytnc3paODRVMHdlbHA2ZUwva01XWW40dXltTDRRbkhoaWc2M0V2RHhwS2FtaXVQaDU1UXQ3T0wyYlQ2NSszc2N2cm9YR1dSNWNlZEdXUlgwZk9VZDZGMGUxL1FCaklxb25MRitOaWxjekw4clY1SEp2eFRWcWxVVC9TSmNDM2w2WE5GV2d6RmN5T2p5Y29Sd21iOEdIQTJldzBTeGlQRkxrc3N6RzVPMXhjMk5ISHV3T0t4YXRSWnIxcTRWelRYOE1McTd1K1BGRjUrdlVxSWxrVWh1VDNLb2hPY2hPbVVCaTBVWjdhcFUyS3h3TVZ1MmJNZWl4VXVvUnVjaU9qZlpZbmpweFFudzkvZFZjcFFlbnFuWWp2NVQyNU5WVnN3N3hqWGd1ZlArRkZPMGNLMHpKU1VWZGVyVXdzTmpSc05SVlhtaGd5UVNpY1NXc1duaFluZ2FrQmsvekJRZHVoeEhqczM5cmwwNm8zLy95cDBPaEtmZS8yWDI3MGhNVEJCTllmRUpDZWpTdVJPR0RTMTRTaE9KUkNLUkZJM05DeGNURXh1TEgzLzhHV2xwNlNSZUR2UTNEYUZob1JnMThnRjRlbm9vdVNxT2YxZXV4c2FObS9Uanh6UWFJYWFEQmcxQXU3WnRsQndTaVVRaUtTbTNoWEF4U1lsSitQS3JxYUkvaWhOM3dLZVNnSEdVOVE0ZDJna1grUExtM1BrTG1ETm5QbUppb2tXSFB4OUhja29LN3VyVEM5MjdseXlTZzBRaWtVaE1zU2wzK01MSU5ockF4ek1vTXp4WW1TZG0vT0tMeWFKSnNUejU2ZWRaK082N0g4amEwenRmY0grVzhIeWlla0VPOTQ1S0pCS0pwRXk0YllTTERVZTJIVm0wR2pTb2gyYk5tZ2tQUGlldGx2Nm1ZVEpaWTFPbVRzZDVzb3JLaXBUVUZDejdad1dlSHY4Q1RwOCtCNjJUVmxoNlBQRDIzbnVIaVZCT1Fyekt6QkZWSXBGSUpMZU5jTEU4c0Vhd2kzdG1aaGJ1dVhzb25uemljWGg0dUl0cDhGbE1PUFRRdEsrL3dhKy8vWUZMbHkvck55d2h5MG13cHBJUXJsdTdYbmd4Nm5UWklsQXU5MlU5Kzh3NFZBOFBSMmFXNmZ4ZkVvbEVJaWs5dDQxd0dXQUx4ekRCV21Sa0JGNSthUUxHUGpTR2x1V0o1YzdPTGpoKy9BU21UUGthWDAyWmhpdFhyb0NueXJlR2hNUUVMRm55Ti83M3Y5ZXhaY3MyTWQwS08xOXdzeUFIeWYzNHcvZlF1Vk5Ia1pjSEdSZlRlMTRpa1Vna1ZuRGJPR2ZjdUg0RDA2Wi9LNW9LYTlhc2dVZkdQcVNzdWNXS0ZTdXg3OEJCWEkrTkZWTUNjTjZFaEVRUi82dDl1OWFvMzZBKzNDMk1UdWR4V0N4Mlc3ZnZnRnFsRW1PeU1yT3lrSmFhaXJadFdxTno1NDc1d3JYd0tQOVBQL3RTVEpmZXEyY1A5T3JWUTFsVGRWaDhhUWVPSmwxR0hrbHNqNEJHYU91YmZ4NnNWRjBHZmppOUd0bDVPYkF2S0o0aVBVSHMvQkx1N0lmZVFVM2hVa1RNUm43ZzVsL1lqSE9wc1NMZ2NWRndCWURuVWVzYjNBS3R6TUxMWk9aazQ3ZHpHM0ExSXdGM0JUZEhTKytpNCtkdGl6Mk9EVEZIa0oyYmhUSFZ1eVBDVlQvSFZVSldLbWJUdmpKenN3cytWd3ZrMGl2RUVWYWVxOTMvcGhQUS9yaXpXSFoxbjRoWTBKcU9xV2R3TTdHYytmbnNXa1JuSkVKTjUyNzF5MGNaT1VEMG9KRFdtSE4ySFp3MTlKem01WW9adXgrdjFRZU9oUnp2cXFnRDJCTjNXc1R0ektMN09iN09RSGdXSStxTGdkaU1aTXk5dUJrWmRNM3RSUk80WmJoSUNYTHl4c2lJVHNxUy9CeEx2SXcvTDJ5QnE5clpxbXVRUTVWT25ySGhvY2h1WWxKRGM0NGxYc0hxYXdlUWxhdFRtdWN0azBQWExGRHJpWHZET3RCK0xFL2l1RGZ1REZiU05lTXIzc0FqRklOREN2WUc1dU9hYzJFVHJxVEgwM1hKd2pQMERIaHI4c2ZiUEpVY2hiL29mWFBrQU41RjFHaEZ0d2Y5MXlPZ01acnp4STBXeU03UjRiM0RjK0dwOVJCNWk0Si9NaUU3RFMvV0dhVE1OWGlMcE94VWZIRjBNVHcwN2dYdWk0K0ozK3ZxOUs3MERicjFMRmNXZDVSd01ieCt5OVp0SXBxRml3dTlOSFQ2SERlUW0vbzRYRTVvU0FnR0R4NElYMThmTEYrK1FvUnFTazVKRmhhYlJxTVc0OFU0ZjNCd0VJWU5IVlRnRlBhMklGeTkxazdFbXRNY29OUU9FOXM4amZlYjVwL0U4bkxhRFlRdWVJRGVsQ3l5eittbDQ5bFBMVDB4OXZScU9Hcmg3NkJGWnhLUVA3dStvYXpJVHc1ZDgvWXJuc2V1SzN0b0czcUo4blNVQ3JONmFkOXBzWGl6eTBTODA1aU94WWk0ekJRMFdQbzRyaVZjRkZNMy9OMzlIUXdJTFR4bzhJVDlQMlB5N2gvb1lVakM4aUV6MFM5VVh6QWRUN3FDZW92RzBybW0wVSthQ2VwTmdhV1Q1OGpieHBEUWdWN3E1RkgvaUJsbW1jbkhGbVBDeGcvb2t6M0dOcndITXp1K0pKWXpnUXRISS9yR1NWSjdzOGdwWXRZQnBWUVQxOW40UXRObktoaVhEL2dheXk1dHg3Yzd2d0hjcUxLa1M4TkQ5WWZoNXc2V3A4YzRsWHdOdGY4WUJuQzBsL1FFUEV2M2VVckxSNVMxMW5NZzRRS0dyZndmenRGOTBKOS9JY1VHaXlpbHhnRU5jYkRmRkdXaEtUK2ZXWU94Lzd4QTV4Q2tQOWRDNDM3U05hRnoxMUtoZVg3WUxBUlFZVzNNN3VzbjBIcko0M1E5U2RCNFA0VWNtdWhQb09zYzRPS1BVME5uZ21jQk51ZjkveFpnMHZiSllsKzlhdmJHcWg3dktXdnlrNmJMUXR2bFQrTXdWWVpBeitKL0R5eEZBNi84c1J2L29JcmF5Tld2MHpFcWxUcCtaZ3BDekU1aEIwY1MxdTg3djRLeFZMa3loK2NKZFArNkNTQm1KS1ozUjF5L1FrK2NOb3JDcWJIclVkUGR0Sko5THZrS0ltZDJCVHlySy9zeWU3NEZ0Rys2YnZhT1RnaWlDc1JvRXNBUG14Vi8ycUt5d3ZwcVpUbkFrZElQSERpRTNYdjNZcy9lZldRSldZNjZYcFp3MDE2RCt2VkZsQTBXTFJZak96dXFaeWozL056NTgzam4zZmZ4MUxobnNHbnpGcVdmeWs1RXdlQllZZHpjbUVPMW5jREFnQUpGcXl6aGlDQkhqaDdGbmoxN3NYZnZmcHc2ZlVaWlUzcGN1T0RVdXRORmNZWEcwWEtnWDdZa3RDcXFuWE1Obi9LRmVZUWgzRE9VL3Q1S0VaNWhjS1VhTmpLU0VFTld6SUl6NjJEM2MwK2NUWXBTOW1JS2x4MDhVU2ZVdEUrVk02cDdScUNaWHowMDlxMWpPZm5WUVlSZkExVGozekNEbytxN3E2aUc2MFNGR2IxVUE1YzhnVS8vbTZlc3RZeVRQWjByL3phZGszR2NTclpJNnRMNVZLTnpOSnhiT0owYkoxSHc4MXhFSkk3NlpjcjUwOTlxOUoydmk3MUJkQWdORjFEOEc3U051UVZhbXdyclFJOXdzYTFoSDlVOXcwbjM5ZmNDYWljRXUxY1QxOVZ3SEtHMGZ6LzZ5elgyYjBoOFhtNzN2Q2pNNFJxSVdRZi93THVVekRrVWZ3NE4veHBETjlwSEZHeXZkWHl4UktMRkxMKzBFK2RTNkg2cVhWSFhweGFhRm5DL1d2alhSNmk0WHM0NGRHVWZkdHc0cGV6QkZBMUhvbEd1cDZ1VGo5ak8wdjcwcVRicTB6UFExcXVHUmN2eXlUMHo5S0pGdnhsQTE0MnZwZUc2R2FkSVd1N0UxNElzam1peVFMZEVIMUgyWUFyUG1NN0h4YytISzFYRUNvT3RPMWZEKzBIbm8zYXdYS1JxdUNJa25qa1hxdU40b0UxQUl3dm5XUWN0L1J0UUJkcFQ1Tk1wTTdCbksxMGZ4Z2lMVjB2UEN2MnVJLzF1STdvK1RmenFXdHluU0xRK2lDb1NUaGFtT2hIeFdOWDZaMDlGK3dyM01ubzJsUlJCMTQ2dlcyNUdJcTdRYy9mUnpta0lXdkFnV1d1bWN4dFdGSlZtY2YyellpVzJiOStKNU9Ra1ljWHdIRHc4cVdLblRoM1FzMGZ4WjRxMTF1SmlMbCsrSXJ3TTFTUmliVnExUk50MmJiQnAwMmJSYjhXRGh0bWRuZi95Z09iNCtEZzBhZElZSFR0MkVHT3pwdE52T05ETmI5R2lHZTRlYmpseU5WTVdGbGRzVEN4K212VXJZbU5qaEdEcWhWYUw0R3FCZUhhODlmTk1GY1NRRGU5anlZVk5WSm5LdzdzdEg4T2todmtqdUVlbHh5Tnk4U05pcmpGM0tyVCs2ZkV1YWxETk45dW9Wc1lGOW8yc1pDUm5KS0RqaWduQytnQ3RqM1FQeFpIQjMwRjcwMXJSUTJlQ1hxdGV4N3FvL1Z3bndHTGFaNytnbGtqUEtkaVpSVWMxUWJabXVIbk5tSVNzTkxUNTUzbWNwRnFqS0x5WXREajBqK3lPWmQzZjBuODNZK0xCMy9IaC90bEFWaEpXRFppT1htUWhNdHlNeEUwK2pFR0MrTncwVkpENS9UWlFpS01uZlQ4NmRCWnlLUytmQjJOb1hnbHp2aFZxN0p1VEsvRDBsczlvQi9aNHB1NWdURzM3akxJR3VFcS93VTFheGdHYzNhZ1MwWG5OcXpoTVlvUFU2OWc2YkNacXVGVVQrUXpvbTdrOGJqYVYzYmZ4ZmN3L3ZneWd3aHJwY1pqVDdXMk1xTjVGckdQYy9oaUtGTHB2eUV6QW1JWWpNS3RkeVdZWFp0N2MreFBlT3pDYk5OVUxxM3A5Z0xZK3RVVXpyVEY4RmR5b052NzFzVVY0N205NlB1azVXVDFzTm5vRzVvLzYvOGU1alJpNTVqVXFmRDNSTTZRMVZ0T3hKMldienRaZ0RGOWpEcjNtVHBXVG16ZEhvZGJmVCtFMFdZVFFwZVBQbmgraks0bGdPb3U2R1Y0a1JpTzJmb25sRjdaUUpTc0JNM3U4amJFMThrOWErY1d4SlhocDEzVDYwVndNamVpR3Y3cE9WTmJraDV0TnU2OThHZHZaZ3M1S3djbDc1cUFXM3c4ekZsN2NqcnMza09WR3h4N3BIb1l6OUY2WW55OWZQMWV5QUJkYzNJSVI2OTZoOTBpTjF0NDFzYjd2WjNBMldHb0txZGxwY1AyaFBWbEpFWWdrSVZ4RGVRTG9XbkpnOElMZzVuNXZ1Z1o4SFkyNVNCV1M4TmtENkRrS1FodXFITXp0TmdrcWV2SU56emZEUXNtdEw2Zm9PbzlhK1lyNFhXVEVZVXl0ZnBqVmliNVhNSlZpY2YyNTRDK3NXYk9XQk1CZU5NODVxbFQwMXhsMjluWll0R2dwbGl5bGw3R1k4Q1V1cmdUbmtSaXdhQVlHQk9EZWUrN0cxQ2xmNHFFeG8rRHI2dzIxV29YT25UdGd4b3h2TWY3cHA5Q1V4SXVENHJJakIxZDJpa05KNmdaUjE2N2gvUTgvUVVwS3NyaEdQSTBESjdZUXIwVkZZK0trdDRYWVZ5aGNjRkp0a1BzSVFwMTlicVpxenQ1b1REV3lEb0ZOY0duRWZDcTh5SnFpRi9CczlDRXNveGUyVU9qYWVHdmNvZUlLQXhWNkJTVis0Y3hGeTVROHVIT0J6Z1cxc3hlV24xdVBhb3ZHaWxpVDFzSkNFa2JudzhuNDNIeTVObTBvRU9pWkNhSnJ3TXNOZVZpd2pFV3JLSUtwOEk5dzhidTVQU2RQalRQRTJmR2pRb1doTDExamJoSXp6c1BiR1BmdnpPdnlCdnJWN0VXaVJXSkwrZTlmK1NJMnh4NFQ2N3ovSElrVWJ2TE1UTVF6emNlV1NyUVk4Y2dyejcwUFZXQTBkQy9NNzVFSEpTNVFSa1QwUU5TelI1RTNicjlGMGJvRjdaRHV2NGdEU3Bqdnp6aDUwRFBGZjgzS1hJSCs5YUlWOUc3eXNmSDlNcjV1aHNTaWtNM1BnOUlVN0ZncHhSKzM3dWd0cVB6bjZFVFBvQjFhazRYRTArM3orNmJ2UzdSdzBrWTQwbnAvdXYvTzlHeVk3OU00OGJVeEZ5MFQ2RUx5NzRVNGVaczgzNXk0dGFNTldkb1AxdWlKdmZmT3BXZnVCbGxvbnZqbHhOOWsyWmZkcEtMV1V1RjNMamJtT25iczNDbXNHZzdOMUtwbEM5eHo5M0MwYXRVQ1NZbkpDQWp3eDRZTkc1R1NtcXBzWVIzdTdtNUNDSXNyRXViNW16WnRnbWVmR1kvWFgvc2ZCdlR2WjNLYmhiZGk0YzlRUG5qdjNKZFdYSmI5dlZ4c3gwMmFQTDNDOEdGRGhJWEh4OHRpcTZQbHk1Zi9xK1N1R0xqV1cxaU5qZ2x4OHNGOUVWVHIxMlZRWWVxQjc4K3VVZFlVZ0wwRFZsL2RqNlZYOXVCUEVqbERtblZ1QTI1a0ppbVpySUFLKy9aVU81M2ZkUktRZUpsKzJ4MVhFeThoYk1Fb0hPYmFlQmxTWHRVRlEvbkxOYU9pcnJPQkpkM2ZSYWZnbG5yeElndXQyNnJYMEduRmk0am5pUVNwZ081UnZSdW10bmhVeVYxeVJGR2JaNGRjT3I1ZnptN0FkTElvcDV4WWxpOTlSZW5QUzF1eDU0WTFUZHAweG5ZT3VFSTErVlhYRHByYy85L09iOEpXN2pjcUpqbmNYMVlJVDlic2paL0pFdDh4N0NmY3k4OXBKY0NpWHhoYUZuS3VnTkZ6d0k0L2haZG9ka2pPeTZacnRrMDRmeGhmdzVsbnJaOWdVMEMvWjgwNzNzaTdCam9HdDZDSGdpeHV5dnRmZlBrR2Q3QkVoVGNWcmxxMUJpdFhyUlo5VGUzYnRjV0FBZjJVTmNCU3NyUjRpbjV1WHVONWQ5alNzT2J3K0YzblhEeUhEWS9ocWxrejBxcW1RclpnK0JoNDdKVTFSRWZINE5QUHY0U0dqcTE1ODhLYkNxOWN2b3hQUHZ0U2VDL3l1WEt5OWx5NEdZckhoTEZRZW5sNTR2SEhINFdyTW1mVnhVdVg4Y01QTTIrdWUzcmNrK0k2bFlUaU5oV3lKYlc3L3hUVWNTdDh3cnUzRHMzRnUvdCtJaFBHRVdFZUliZ3dhSWF5Um85SlU2RmFTd1VzaVp4SnN4TmRoZFRyV0hQUDcrZ1JVUGljVWplYkNoUE9vNGxQRFJ3WStDM1dYRHVFdnF0ZUpZSGg2MjBQQnhMUlJiMC93Y0FRS3VDSjF3Lytoby8yLzVxdnFiQXc3SDdvUkRVUWIzam01dUg2ZzB1RnQyQmhGTlpVV0JETmxqK0xBOXhVbUh3TlJ4NzRDL1U5ckorZzBYL0JTTVNteGxMMW01NEZibDZrY3g1TW9yVzRFQ2VaNHZENXNjVjRlZXVYd3BvVjkwcXhHaXpDbDUyT0lZQXN5MnNqL3RRdk0rTm1VNkZySUIwcjdVL0h6V2FHOTRQdWYxWXlXWk45c0x6SHU4cXlncW01OUNtY1Nid29tdXBXOTU5R1ZsN3g1L3N5cGx5YkNrbTBYRlF1ZURpeUc1TG9uUGw5TjhCbnovMmhLNjdzeGZua3E3UWdEKzNKK2xyYjkxTzltQmx4czZuUXF3WmRhN3ArL0E2WmlEYnRtZmFSUjVadlVSZzNGYllsVVZyZjUvTUNQUzROUExycFk4dzh2NTd1V3hiR043d1AwMW8vcWF5cEdDcmM0cnAwNVlvUUpYWTNidDI2bGJKVVQ5ZXVuVVRrQ2JZbzJOSklTRWdRazlFVmxSS1V2N3dkdzl0V050blpPdUVxeXhIcjlXNzMxcDlMVWxLeWNnMTBxRmVuN2szUllzSkNRMUE5SWx5SUlJOGY0MzFYTmJqWlQ3U24wakZ5TTBhaFVCNTNqUWY4cUFEemNmRlhraDhjM0FMejlZMFZCZGRPMmVXWEM2NWp3MzVHT0hkeTUyUWdSK09DUVNzbllNSmVFbFBDaWZ2Z2lqZ3NXK1Bxc0Y5Uno3dVdVbmpsb3FWL3d6SVRMV1pFUkdkMEQ2SDNOWU9zWUxLUXVCK3h3SlNkSWl6ZWFCTFNiMCt0VlBaUUFIVFBIS2lRREtEN2ZldisrMFBqR2dBZmVpNXVPK2k5VHFYcjgvVyttWmg5YUE1KytXOCtmam4rTjZXbG1FM3Ayd08vNDN6Y2FiMFlwY2FnSlFtWHVXaVp3dzVLdnZUT0dGOC9mb2RBMTdTOHVGVUY1K2JGaW05eXJmQmYxR3FjaExXUVF5Ym0xYXVtWG1jOEpiODlGVmI2UWprRjhmSHh4VW94TVRIQ1U3RmUvWHJLSGl1UGlPb1J5TXJNRnVmSWtUc3NIVzlCaVVORnNUY2hPNGpjaUtPQ3dBajJidVE4N00zazZLaTZLZFpWaWZQMHdnbW94dXBmVk9GRGx0eDNiY2ZqeUtCdnNZOXF5L3NHNk5PSjRiK2dsUlZqc2dxaUZoVjhPOGo2YXVwRGhYbEdJcW1WTnlidm5ZbDN5UnJrRG0valYrOTJ3SkdlbFQ3Y1pNaldFRm1ob3JtMkRPRitqN1Y5djhEQlliT3dZK2hQMkNuU3ovblN2dUd6TWIvbmgwQm1NaFhTS3B3aDY3RlFjakxSTWFBaFRnLzUwZWorVDhVeCt2NUZ5OUkzY1pvemljU0Mwd1cyVGlzRHJzdzZhTkExc2lmYVZlK01HbjRONkJwa1VjRklsU3l5eE5xRXRVT3ZpRTVvSDlBTW4zWjZCUisxR0t0c1dBQlVVYW11OWNDYVhoL2gwTURwTjk4ZlRpZnZ6dTlwV2hid20zT2EzM0gybE16Um9TWVBhYWhnS2x5NFdyZHVqdlQwRE5GTTkvZXk1VGh5NUtobzRvdUtpc0ozMy84QVQwOTNFV1B3NFlmSFlOclV5Wmo4eFdlWS9LVjE2WXZQUDhIUE03OUhGeVY2UldYenc0enBtRHJsaTJLZHcxZVRQOGRISDcwblFsWHhGQzE3OSs4VFRhdUpTVW1JaTR2SEgzUG1JU2IydWhEMzhQRFFZay9uWFRxS0x1dzNSUi9GNzZkWDZadXNNcFB3ZkowaW1tRno4K0JMTDU2ZnhoMWhMbm9uQjA3c3VhaTI0THBiSE5pSlpQK2c3L0JnL1dGa0NaQ1Y0T3FIdC9iT3dBTmJ2NFFkdXpEZlptU0pzVUYwajZoU2s4NTlKR1hJcGRUcldCZDlHSFpVVUxieGI0RFdKRGF0QS9pdmFXcm1WeGQxMkhWYU9NWFlDOE83WVBSV09mZjVzT09FOGYydlRsYURIejBYeFlKT3ZhZ25kUCtOTTNoLysyUkVURytHVDQ1WWJzWTBnWTZ2TUhodEVWbE15YzFDYlpjQXJPLzFBYmIxL3BRRWV3YkdON3lickNzU1VycFlPNk9QNE9jMnoyQnIzMC93Y3NON2hjTkZrZVRxSFg2Q3FYSmh1SDZjYXBYQTR1SnlwYWpUK2ViRUNtd1NZekQxeDNaWEpReElybkRoaXF4ZUhSSGhZYUk1ajlQc1gvL0F0OS8vaUsrbWZnMVhWemN4ZHhYUG9kVkFzWnA0cG1CdWJyTW1jUk5rVlVNY1d6SE9nUzBvOWw1czJhS0ZhREwwOVBERW1qWHI4TTAzMzRrNGk4ZU9IWWV6c3pOU1U5TFFxWUlGbXQzQ2c1MTlsRyttSkZOQk9mbkVjZ3hmL3lZeXVITTNOeFB1cmtIb0ZkUkN5V0VKZWtYb1pmVXI1eWFoWDlzOWh4ZWFQUVNrUkl2eEtuR1ppY2lyaE9hTkNxVU1tMElUc2xKUWI5azQ5Rmp5T040cVlvd2NjK3NaeVVXMmtUdC9RYmhZR0FSY0hHNDZFOWhSWlk0RXJ6QjhlYnlmazY4WXVPdkRZNWNzb084YlpmTGd4ODNOaGNCanZyeFV0L3FZZVhCOVVhU1pEVDZlMXZaWlRHeE96MmZDZWRHVUdETDNIbngxWktHeXRtaWNIVlgwRHBWQkJaYU9uU09xaUhGc0ZyaVFkaDBUOS8yQzhkdTRyNVBIYlNhaloyaGIxUFFJVVhKVUhKVXlqaXM5SXhOVHBrNFRBNDVWS2g0QUxJb3c2TEoxWXF6VWl4T2VFMjdmNVVWRk9HZVVCUXNXTHNMT25idUVvQWszVnZxZlhlQzVHZkdoTWFQUnFGSGhqZ3RGTVhURCsxaGNoSFBHdGZSNFZGL3lLREp5bEFJb1BZSEtJN1BDaUc4Z1cwZmNGcytGRU5XMnVkeGMzdXRqM0dVVTZzaUFjTTVZL1RyV1hkMHZCbzN5T0NOa0YySWg4TTR5VTlBOHNodjI5dnRLdjB6QjJEbWpzVThrTnZiOUVwNjhUd3VzampxSTN2ODhRK0xsU3NkSmVaS3ZZdldBcjlHeldNNFp3UFVIbDFqcG5QRTVYUk4yemhoVTdzNFp6UGpkTXpEOUtCVjRPWmwwUDUvQXBNYjNLMnRLUjJwMkJsem5EcWVMUUdMUElzSDlYRGNMZHd1b05HQ1BVbTR1L0tUMWVMeFNmNGl5NGhaNjU0elg5YzRaUEo2cHFIM3k3enBxY0dyRVBOVGtiWXhvdGVwbDdJazZMQWJJOHZpc0FwOGxmazU1MExOeTcrZjAva1QwM1prejllUS9lRzRiUFdjOEdKeTlZOU1UbFRVVzRHdkNZc2lXVVVvTVR0dzNEN1VMZE01NG4vTG5JY0l0Qk9mSTBqSm5Hb25Wczl2cGQxbjRVMkxSSzdJN1Z2VzBITFZENzV6UmdRUzRobmpmeEhrWE5qeUd6ejBsQ2tjZldvdDZYaEhLUWozQ09lTlhLZ085cXRPMW8vT2xpaDAzYVpvZytxM3BIV2RSRTljNUNTRmFMK3dmUGtzL1hLU0NxWlJxcDVOV2cxZGZlUWw5Ky9SRzdUcTFFQndVaEZvMWFtQkEvN3Z3di85TktGZlJzaVZZR01lT2ZRak5talZGY0xVZ1ZLdFdEUjA2dE1mTEw3MVFhdEZpMHZpbDVBS0RSRUdNYjdHQWprUXRnOWFMZkR6K2hac0grTUUxVG9ZYUo2OVBpaElGN3VvK24xc1VMWWFyU3VtY055dFpuempFamZrK2pSTUxFZjIxRk4yREhUTFNzbFBwSEpLUWxwVXVQRElMb2xkUUUrd2M5S01ZRXdSMkY2ZHRyTEVJQkh5Y1ZCQ25rL1hCdjFrVTRucG04YlZOUXFhVnpYYnBYSUR6RUFCS3VpTGN1aTBoQmh2emNkSzk0cmg1WllXTFNpdXVIWkt1MEFVbmEwRk45OXY4SGhrbnZwL2M5RVgzWTJ3Tnl3UHZ4Y0JxOGV6UjhWcXpUMzdHU0xnY1JEZ2tVNTZxMFFkSXZLQ3ZWQlgyTFBFK3VBS1dTcFkzNWV2QS9Vc1dHQkxTV29nL08wZUlQa05MK3pJa2pxakMxejN4Q2tKSkVJSUthSkhJNVBNVnoxQVNVdmg1dGNBekRZYmo5KzRrVkNKOG1STldrNENHTFJpSnl4YjY0NFM5d2RkUHZKZjAzSWhJTFJhT3o1RDQzQ2s1Mk9kdmZoZkRmUGcrOEw3NHZMbnlhYjQ5THlQUkZmbW9ZdFUvckQxMkQvMnhVa1NMcVJTTHl4eHVNbFNSVlNGcUJSV0FyVmhjeHJDVnhiRDFWVmE4ZTNnZU5rWWY1dUU1ZUtKbUg5d1huajhvS3NjQ2ZHVEhOTkYvb2k4MDhqOHVMQlkxM0FKRlFOS0J3YTFFNE0rQ21oc1lmdUplUFRBTCsrTE9VajZPQ0ZEVUkyaUh0SndNdFBXdGgvZWJtTVlxVEtFYTR2UDdmc1E1ZXBuWURmbno1ZytML3BMQ1lBdmlnVzJmSXlvOUR0KzBlZ290MllHakVQZ1Y2VVFXb2llOXdGelRXOVIxSWxsY2hkZjVsbDNaZzgrUExSTEc0ckNRZG1SMUZmMk1QYlBuQjV3bVMrQjZSaUlXZEg2MXlHWXZjNzQ5OVMvK3VyaFZ1R2cvVmJzZkhyQmdUWlFVZHFiNjRmUXEvSDExRC9kY2lmTXFDTGFvNjd1SDRGRjZwbXFieGNVenNEN21NQ2J1bncwL3JhZStFQzRVTytUUWZ5cXE4Zi9RNW1tTGZWK3JydTdGblBOYkVKMlZXT2pBNGl5cUVEVDJDTU1qTlhxaVRpRVc3U1VTclUrUExoS0JvSXVxM2ZQWXNTNytEVEMrZG44NEd5cHhabXlMUFliM0RzOFgwVTlDWGZ3d3MrMTRaVTErNXA3ZmlPOU9yeGFEaGprbW9iMjlBOWFheFV2a1o3amo2djhoako0UnE0cHdLbHRqMHVPeHNOT3JxT1ppT2xnK0tpME9BemEraXhCbnZ3TDN4WEZpR250V1J6UFBDSFQwcjBzQzdhZXNxUnlxaEhCVk5OZXVSZU16RWlBV3JrNGRPNkEvV1hyV3dCNStIMzc0cWVoTDR3SFR3NFlPVnRaSUpCS0pwS0tvbEtiQ3l1YlF3VU5DdE5oNnVVVFdsN1VjT25TWXRtTW5DZ2RFUlYwVGxvTkVJcEZJS3BZN3l1STZjL1ljdnZubWU5RWl5UUY5R1I3QWUrWHFWWXdaOVNDNmRyWGN0SExwOGlWOFBmMDdaR2RsQytjUmhzZFQ4U3pLRDl4L0gzcjM2aW1XU1NRU2lhVDh1V09FaTczeFhwczRDUm8xOTZuWUlURXhBVHFPU08vdUxrSW14Y2ZGWTlUb2tXamVyS2wrQXlOZWZlME5ZWjN4Z0dDT2dNSGJ1Ym02d2NXRnRvdFB4TDMzREVPN2RvWFBBU1dSU0NTU3N1R09hU3FjTis5UHNCY0M2elFQY3A0NDhWVk0vZW9MTkc3Y1VJd2RjM04zMCtjeFk5SGlKZERwY3NoS3N4TUM5OXByLzhQWFV5YWpUWnRXdEYybUNPNzcxNklsU202SlJDS1JsRGQzakhDZHYzQVJXcTFHaEpKNmNjTHpDUEQzRjFiVS9TUHVRMWhZcUJBMG5zYWZvM2dZYytiTU9UZzdPNG5Cd0JOZWVCWkJnUUd3ZDdBWGpoazFhMFVLUzQ2ajNGK05zanhwb2tRaWtVaktsanRDdUZoWWNuTnp4SGdGYjUvOHMraEdSRVFJbDN3bko2M283ektRbnBGQndxUVQyM0VrZG83d2Jrek5HalZGWDVkYXJjMFhkMUVpa1VnazVjTWRJVndjSW9sbkxlWndTaHl0ZzVzR2pUbDI3SmdRSlk2aEdCNFdwaXpsZ2RKYXBXL0xRY1FKNU1qdHhodzVja1JzbDVtWmprZ1NQNGxFSXBHVVAzZE1VMkZvU0lnU0I5RVRVNmRORjhGOW8yTmlNUE9uV1VLVXVLblF3OU1qMzl4V2taSFZSZEJmanA4NGZmcDNPSGp3TUdKaVkvSExyNy9qeXBVbzBmZkZNUll0V1hJU2lVUWlLWHZ1S0hkNDlnN2t1V3Q0V240V01aNkdYK3VraFlvc3NZVGtaSXgvOG5IVXJNVlRYcGp5K2h0dmlubnpUTGJUYXNSWXNQajRCREZwSlR0NVNDUVNpYVQ4dWFPRUsvWjZMSDcrZVRZdVhMaElWcEtyc0pZeU1qS0Z0ZlhJMkRFa1BvMlVuS2JFSnlTSTdVNmZQZ00zTi8xMjNMZkZFejArTkdZVVdyU28rTEQrRW9sRWNxZHlSNFo4T25yc09JNGZQeTdjM0VPcUJhTnhrOFltc3d3WHhJa1RKM0hrNkZGazUrUWd5RDhRVFpzMmdydTc1YWtSSkJLSlJGSSszSkhDSlpGSUpCTGI1WTV4enBCSUpCTEo3WUVVTG9sRUlwSFlGRks0SkJLSlJHSlRTT0dTU0NRU2lVMGhoVXNpa1Vna05vVVVMb2xFSXBIWUZGSzRKQktKUkdKVFNPR1NTQ1FTaVUwaGhVc2lrVWdrTm9VVUxvbEVJcEhZRkZLNEpCS0pSR0pUU09HU1NDUVNpVTBoaFVzaWtVZ2tOb1VVTG9sRUlwSFlGRks0SkJLSlJHSlRTT0dTU0NRU2lVMGhoVXNpa1Vna05vVVVMb2xFSXBIWUZGSzRKQktKUkdKVFNPR1NTQ1FTaVUwaGhVc2lrVWdrTm9VVUxvbEVJcEhZRkZLNEpCS0pSR0pUU09HU1NDUVNpVTBoaFVzaWtVZ2tOb1VVTG9sRUlwSFlGRks0SkJLSlJHSkRBUDhINWxEZ2puM2VMWFFBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiODhiYmQyZjAzNDJhNDJlNzk3MjlkZDE1OGJlNTQwN2EiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJtYXhNc2dTaXplIjoyMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOltdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjE2LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjE2LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwiZmlybXdhcmVWZXJzaW9uIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wyIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDktMjciLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IklubmFJVCBLZXkgUEsxMTAwIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTEwMTgwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTA5LTI3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0xMi0xNSJ9LHsiYWFpZCI6IjRlNGUjNDAwOSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFpZCI6IjRlNGUjNDAwOSIsImRlc2NyaXB0aW9uIjoiaU9TIFBhc3Njb2RlIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjI1NiwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjo2MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJ0ZWUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVnQUFBQklDQVlBQUFCVjdiTkhBQUFBQ1hCSVdYTUFBQXNTQUFBTEVnSFMzWDc4QUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFFWjBGTlFRQUFzWTU4KzFHVEFBQUFJR05JVWswQUFIb2xBQUNBZ3dBQStmOEFBSURwQUFCMU1BQUE2bUFBQURxWUFBQVhiNUpmeFVZQUFBbitTVVJCVkhqYTdKeHZiRlAxR3NjL3A2ZHIxNjRWeDJ4cHR4R1lZQnZGRzRqYU9PMmNXeFFDT0lJSm1mZUYrZ0tOUk9VRjBVVHZGWW54ejRneGFqQUdIVjdDUWpSN28xRVRRL3lEaVpHTUYvSmltOTJXc0RuSFhiTnVERFBweWtiLzBmYTVMMlRuTXZhSE16Z3FoWDZUa3p6bmQ1NmM5RHg5L3YyZTUvZjdLVXpIVW1BYnNCR280dnJDZjRHdmdmOEFRN014L0JNWUJlUTZ2MGJQeTJJYUdvRnNRVGphbFQwdkV4U2dFZ2dCaXluZ1Fwd0dWcXZBdjRGMUJYbk1nQTFJS1VBWDhJK0NQR1pGdDNKZWxVb0xzcGdWVVZOQkJ2T2pJS0JMUUFYK2RkNGhYUkZLU2tydytYeWswMmxVVmVXV1cyNGhtODBpSXZoOFBqS1pETGxjRHIvZlR5NlgwK2hzTmtzbWs4SHY5d09ReVdUdytYeW9xa282bmNidjkyTXltVWdtay9qOWZvcUtpa2dta3hwUElwSEE3L2Rqc1ZpSXgrTWFQVEV4WVlSOGtvWUpxTDYrbmg5Ly9KSCsvbjRjRGdkdGJXMmNPbldLVkNyRnNXUEhHQjRlSmhhTDBkSFJ3Y1RFQkdOalk3UzN0L1A3Nzc4VGlVVG83dTRtblU0ek1qSkNaMmNuVnF1Vm5wNGVlbnA2VUZXVjl2WjIrdnI2S0NzcjQ2ZWZmdUw0OGVNNEhBNk9IRG5Dd01BQUhvK0hvMGVQMHR2YlMzbDVPVjkrK2FVaEFqTE14TExaTEZhckZSRWhrOGxndFZvQlNLZlQybmc2bmFhNHVGZ2JuNktUeVNURnhjV1lUQ1pTcVpSR1h6aWVTQ1N3Mld5WXpXYVN5YVJHeCtOeGpaN2lLU29xTXN6RXpFYThSRkVVMXF4WkE4Q3FWYXU0NmFhYkFQRDVmS1JTS1FCdXZmVlc0dkU0QUN0WHJpUVlER284OTk5L1B3QlZWVlhVMU5UOE1TbGN1cFM2dWpvQWxpMWJ4Z01QUEFDQTErdWx2cjRlZ0lxS0N0YXVYUXVBeCtQUmVOeHVOelUxTlpoTS8vLy9UU1lUUFQwOWpJMk5YVmJHZU5scHVkbHNsbzgvL2xqeUFWdTJiRm5vOTUyK0lnMHltODBjUEhpUVJ4OTl0QkRtWjRRL1ZjMDc0WWpJWHlPZ29xS2lhMTV6cmtoQXpjM05QUGJZWTNuM3NWTkJZa0VCU085YzdQbm5uMmZac21XWXpXYTJiZHVHMld6T093RWRPblNJL3Y1K0ZFWGh2ZmZlSXh3T1gzSXVwanVLOWZYMXliV0VtcG9hWFZGTXR3WlZWRlJnc1Zod09CeDg5OTEzZUwzZXZOT2daNTk5bG0rLy9SYUFrWkVSTFVlYlQ0TjAyMGxqWXlOTGx5N1ZoSlNQV0w5K1BWVlZWYWlxeXZ2dnY2L0h4UFFuaWowOVBkZVVpZDE3NzcyNlRFeTNnRnd1bDNpOVh2SDVmREk4UEp5WFFubnl5U2ZGN1hhTDErc1ZpOFZpYkNiOThNTVA0L1Y2c1ZxdGxKU1U1S1dKclYyN2xzcktTa1NFbHBZV0lwR0ljU2IyeXkrL0ZLTFlmS2lxcXNKbXMxRlNVc0pYWDMyRngrUEpPdzNhc1dNSGh3OGZSbEVVQmdjSFNTUVN4a1d4RFJzMlVGbFpTVkZSRVhhN1BTOU5yTGEyRnJmYmphSW83TnUzajZHaEllTk1ySkFvWGdKVER0cmhjSEQ0OE9FWmllTEF3QUNmZnZvcG82T2pLSXJ5dDgzVzdYWTd3V0NRaG9hR0djK2ZlZVladnZubUd4UkY0ZVRKazhZbWlnOCsrQ0JMbGl5aHVMZ1ltMjE2Q1RzY0RsTlhWNmM3S3Z3VmFHNXU1dW1ubjU0MmRzODk5MmpsMmRiV1ZrWkdSdjZhS1BiaGh4OWVkUXNRN3I3N2JrTk1UTGNHYmR5NEVidmRUa2xKQ1Y5ODhjVzBLSGIyN05tOGNOTFBQZmNjMzMvL1BTYVRpWUdCQVdQclFiVzF0VFEwTkxCKy9mb1pKblpoY1J6QTZYU3lmLzkrbkU3bm5PL1R3d1B3eWl1djhOQkREeTJZWnpZL0dBZ0UyTHg1TTVzMmJhSzBWSCszWFplSkRRME56YW11Nzc3N3JzYTNaODhlYVdscGtVd21JeTB0TGJKbno1NFo3OUxEMDlqWUtBY09ISkJJSkNJLy9QQ0R0TGEyeW9vVkszVHpWRmRYejJ0aXRiVzF1a3hNdHdZMU5EUVFEQVpadDI0ZHYvMzIyOXh1UHhwbDY5YXRxS3JLMXExYmlVYWpsOFVUaVVUWXZIa3pGUlVWMU5mWHMzejVjbUt4MkNWNXhzZkg1L3h0TzNmdUpCZ01FZ3dHNmV6c05MWXY1dlA1Y0x2ZEZCY1h6OXVZS3lzckF5Q1h5MkV5bWJUN2hmSTRuVTZ0K1FoUVdsbzY3WDR1bnFsbTVGeXpnV2cwaXFxcURBd002R3BQNnhiUW0yKyt5WW9WS3k3Sk56dzh6T3V2djg3T25UdHBhbXFhMVlIcjRWRVVoYmZlZW9zbm5uaUNuMy8rbWQ3ZTNobStUZy9QaFhqcXFhYzBPaFFLY2VyVUtlTjgwS3BWcXlRUUNFaGRYWjJNam83TzZZTUFzZGxzMHRUVUpGYXJkYzczNmVFQlpQdjI3WExmZmZjdG1HYzJIL1RpaXkvS0hYZmNJWUZBUUJ3T2g3RmhmczJhTlpxSlhhenFGL2ViRW9rRXUzYnRtdmQ5ZW5nQVB2amdBME40NEkvMmR5cVZRbFZWSXBFSWs1T1R4bW5RNE9EZ25CSGhuWGZldWVvU3hUdnZ2SFBlS0hZcHJWeXdCalUyTnJKbzBTSnNOaHNIRGh6QTVYSnB6NnFycTYrNnBEQVFDTXdZZS9YVlYybHJhME5SRkxxNnVveU5ZdVhsNWJoY0xxeFdLNnFxVG5zV0RBWTVlUEFnemMzTmVtb3NmenFxcTZ2WnZYdjNqSEczMjgzeTVjc0JkQXZJRUJQTFIraE5GSFdYTzFhdlhvM0Q0YUNrcElSUFB2a0V0OXVkZHdXemwxOSttU05Iam1nYXBDTVAwbC91S0Nzcm83UzBGSnZOTnNQRThnVTMzbmdqTHBjTFZWVTVmdnk0c1NaMjRzU0phOHJFREk5aWp6Lyt1QmJGOXUzYnB5Mnp5eWZzM3IyYnRyWTJWRldsdTd2YjJDam1jRGcwQWYxZEpkVXJoZDF1Wi9IaVAvYnNMR1IxaWk0VEM0ZkQxMlVVMHkzR1J4NTVSTk9nL2Z2M1Qwc1U4d1d2dmZZYVI0OGVSVkVVUXFHUXNTWm1zVml3V3ExWXJkYThOVEdMeFlMRllrRlYxWGxuL1lVbzltZEVzUjA3ZHJCNDhXTHNkanROVFUyYXM4c243TjI3bDJQSGptRTJtK250N1RWV2c2WXVSVkh5ZHRxeFljT0dCUzhrWC9BcVY2ZlR1U0Q3dlpwd2NUZkcwTGJQOVFyVDVVYUR2UHpZeTlEOEJTOTJ6dVZ5aE1OaGJZUGNWTW5WWnJQaGNyazRmZm8wMld3V2w4dkYrUGc0cVZTS0pVdVdFSTFHU2FWU2VEd2VZckVZaVVRQ2o4ZkQrUGc0aVVRQ3I5ZkxtVE5uaU1mamVEd2VKaWNubVppWXdPdjFNakV4d1prelo2aW9xT0RzMmJQRVlqSEt5OHVabkp4a2ZIeWN5c3BLNHZFNDBXaVVpb29LNHZFNFkyTmowOUlSazhsMDJSM2dCVHRwaDhNaE45eHdnM1k1blU3WnNtV0xpSWhzMzc1ZE5tM2FKQ0lpTDczMGt0VFgxNHVJeUFzdnZDQ0JRRUJFUk41NDR3MnRxTDVyMXk2NS9mYmJSVVRrN2JmZmxydnV1a3RFUkQ3NjZDTzU3YmJiUkVSazc5NjlVbFZWSlNJaXJhMnRzbkxsU2hFUmFXbHBFWS9ISXlJaW4zMzJtZHg4ODgwaUl2TDU1NStMMCttYzloc1hMVm9rWnJQNXo5L3RJeUt6RnJ1bmx2a25rMG50bnpwMzdwekdtMHFsdFByTHVYUG5wdEZURGNGTUpxT05aN05aYlR5YnpXb05RUkhSeG5PNW5OWjB2SEFjTUdwTHBuRk9PaGFMMGQzZHpkallHSk9UazNSM2QzUHk1RW5pOFRoZFhWM2E5c3l1cmk2R2g0ZEpwVktFUWlGR1JrYklack9FUWlHR2hvWklwOU9FUWlFR0J3Zkpack4wZG5ZU0RvY1JFVG82T3ZqMTExL0o1WEowZEhSdzRzUUpUQ1lUN2UzdDlQZjNheng5ZlgyRytTMUQ5ODJiVENiTkwxMEpyU2lLMWtyU1ExL2NUTHljYlU5elZSUU5EZk5USDNpbDlJVWZxSWUrMkFYODdXRytrQWNWTUUxQWtZSVk1a1RFQkJ3cXlHRk9IQ29jc0RSL0FyMTY2cVp3Uk5jY1IzUmRpTUloYjdNYzhuWnhjYmx3VE9CRnh3VCtid0M0RTQyTDZaQ2JlZ0FBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wNS0xOSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTgtMDUtMTkifSx7ImFhaWQiOiIwMDUyIzAwMDEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhaWQiOiIwMDUyIzAwMDEiLCJkZXNjcmlwdGlvbiI6ImktU3ByaW50IGlPUyBGaW5nZXJQcmludCBVQUYgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InVhZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGNEaXNwbGF5UE5HQ2hhcmFjdGVyaXN0aWNzIjpbeyJ3aWR0aCI6MzIwLCJoZWlnaHQiOjQ4MCwiYml0RGVwdGgiOjE2LCJjb2xvclR5cGUiOjMsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MH1dLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFLNEFBQUE5Q0FZQUFBQTAvbElEQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUtUV2xEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOM1dKUDNGajdmOTJVUFZrTFk4TEdYYklFQUlpT3NDTWdRV2FJUWtnQmhoQkFTUU1XRmlBcFdGQlVSbkVoVnhJTFZDa2lkaU9LZ0tMaG5RWXFJV290VlhEanVIOXludFgxNjcrM3QrOWY3dk9lYzUvek9lYzhQZ0JFU0pwSG1vbW9BT1ZLRlBEcllINDlQU01USnZZQUNGVWpnQkNBUTVzdkNad1hGQUFEd0EzbDRmblN3UC93QnIyOEFBZ0J3MVM0a0VzZmgvNE82VUNaWEFDQ1JBT0FpRXVjTEFaQlNBTWd1Vk1nVUFNZ1lBTEJUczJRS0FKUUFBR3g1ZkVJaUFLb05BT3owU1Q0RkFOaXBrOXdYQU5paUhLa0lBSTBCQUprb1J5UUNRTHNBWUZXQlVpd0N3TUlBb0t4QUlpNEV3SzRCZ0ZtMk1rY0NnTDBGQUhhT1dKQVBRR0FBZ0psQ0xNd0FJRGdDQUVNZUU4MERJRXdEb0REU3YrQ3BYM0NGdUVnQkFNRExsYzJYUzlJekZMaVYwQnAzOHZEZzRpSGl3bXl4UW1FWEtSQm1DZVFpbkplYkl4Tkk1d05Nemd3QUFCcjUwY0grT0QrUTUrYms0ZVptNTJ6djlNV2kvbXZ3YnlJK0lmSGYvcnlNQWdRQUVFN1A3OXBmNWVYV0EzREhBYkIxdjJ1cFd3RGFWZ0JvMy9sZE05c0pvRm9LMEhyNWkzazQvRUFlbnFGUXlEd2RIQW9MQyswbFlxRzlNT09MUHY4ejRXL2dpMzcyL0VBZS90dDY4QUJ4bWtDWnJjQ2pnLzF4WVc1MnJsS081OHNFUWpGdTkrY2ovc2VGZi8yT0tkSGlOTEZjTEJXSzhWaUp1RkFpVGNkNXVWS1JSQ0hKbGVJUzZYOHk4UitXL1FtVGR3MEFySVpQd0U2MkI3WExiTUIrN2dFQ2l3NVkwbllBUUg3ekxZd2FDNUVBRUdjME1ubjNBQUNUdi9tUFFDc0JBTTJYcE9NQUFMem9HRnlvbEJkTXhnZ0FBRVNnZ1Nxd1FRY013UlNzd0E2Y3dSMjh3QmNDWVFaRVFBd2t3RHdRUWdia2dCd0tvUmlXUVJsVXdEcllCTFd3QXhxZ0VacmhFTFRCTVRnTjUrQVNYSUhyY0JjR1lCaWV3aGk4aGdrRVFjZ0lFMkVoT29nUllvN1lJczRJRjVtT0JDSmhTRFNTZ0tRZzZZZ1VVU0xGeUhLa0FxbENhcEZkU0NQeUxYSVVPWTFjUVBxUTI4Z2dNb3I4aXJ4SE1aU0JzbEVEMUFKMVFMbW9IeHFLeHFCejBYUTBEMTJBbHFKcjBScTBIajJBdHFLbjBVdm9kWFFBZllxT1k0RFJNUTVtak5saFhJeUhSV0NKV0JvbXh4Wmo1VmcxVm84MVl4MVlOM1lWRzhDZVllOElKQUtMZ0JQc0NGNkVFTUpzZ3BDUVIxaE1XRU9vSmV3anRCSzZDRmNKZzRReHdpY2lrNmhQdENWNkV2bkVlR0k2c1pCWVJxd203aUVlSVo0bFhpY09FMStUU0NRT3laTGtUZ29oSlpBeVNRdEphMGpiU0Mya1U2USswaEJwbkV3bTY1QnR5ZDdrQ0xLQXJDQ1hrYmVRRDVCUGt2dkp3K1MzRkRyRmlPSk1DYUlrVXFTVUVrbzFaVC9sQktXZk1rS1pvS3BSemFtZTFBaXFpRHFmV2tsdG9IWlFMMU9IcVJNMGRab2x6WnNXUTh1a0xhUFYwSnBwWjJuM2FDL3BkTG9KM1lNZVJaZlFsOUpyNkFmcDUrbUQ5SGNNRFlZTmc4ZElZaWdaYXhsN0dhY1l0eGt2bVV5bUJkT1htY2hVTU5jeUc1bG5tQStZYjFWWUt2WXFmQldSeWhLVk9wVldsWDZWNTZwVVZYTlZQOVY1cWd0VXExVVBxMTVXZmFaR1ZiTlE0NmtKMUJhcjFha2RWYnVwTnE3T1VuZFNqMURQVVYranZsLzlndnBqRGJLR2hVYWdoa2lqVkdPM3hobU5JUmJHTW1YeFdFTFdjbFlENnl4cm1FMWlXN0w1N0V4MkJmc2JkaTk3VEZORGM2cG1yR2FSWnAzbWNjMEJEc2F4NFBBNTJaeEt6aUhPRGM1N0xRTXRQeTJ4MW1xdFpxMStyVGZhZXRxKzJtTHRjdTBXN2V2YTczVnduVUNkTEozMU9tMDY5M1VKdWphNlVicUZ1dHQxeitvKzAyUHJlZWtKOWNyMUR1bmQwVWYxYmZTajlSZnE3OWJ2MFI4M01EUUlOcEFaYkRFNFkvRE1rR1BvYTVocHVOSHdoT0dvRWN0b3VwSEVhS1BSU2FNbnVDYnVoMmZqTlhnWFBtYXNieHhpckRUZVpkeHJQR0ZpYVRMYnBNU2t4ZVMrS2MyVWE1cG11dEcwMDNUTXpNZ3MzS3pZck1uc2pqblZuR3VlWWI3WnZOdjhqWVdsUlp6RlNvczJpOGVXMnBaOHl3V1dUWmIzckpoV1BsWjVWdlZXMTZ4SjFsenJMT3R0MWxkc1VCdFhtd3liT3B2THRxaXRtNjNFZHB0dDN4VGlGSThwMGluMVUyN2FNZXo4N0Fyc211d0c3VG4yWWZZbDltMzJ6eDNNSEJJZDFqdDBPM3h5ZEhYTWRteHd2T3VrNFRURHFjU3B3K2xYWnh0bm9YT2Q4elVYcGt1UXl4S1hkcGNYVTIybmlxZHVuM3JMbGVVYTdyclN0ZFAxbzV1N205eXQyVzNVM2N3OXhYMnIrMDB1bXh2SlhjTTk3MEgwOFBkWTRuSE00NTJubTZmQzg1RG5MMTUyWGxsZSs3MGVUN09jSnA3V01HM0kyOFJiNEwzTGUyQTZQajFsK3M3cEF6N0dQZ0tmZXArSHZxYStJdDg5dmlOKzFuNlpmZ2Y4bnZzNytzdjlqL2kvNFhueUZ2Rk9CV0FCd1FIbEFiMkJHb0d6QTJzREh3U1pCS1VITlFXTkJic0dMd3crRlVJTUNRMVpIM0tUYjhBWDhodjVZelBjWnl5YTBSWEtDSjBWV2h2Nk1Nd21UQjdXRVk2R3p3amZFSDV2cHZsTTZjeTJDSWpnUjJ5SXVCOXBHWmtYK1gwVUtTb3lxaTdxVWJSVGRIRjA5eXpXck9SWisyZTlqdkdQcVl5NU85dHF0bkoyWjZ4cWJGSnNZK3lidUlDNHFyaUJlSWY0UmZHWEVuUVRKQW50aWVURTJNUTlpZU56QXVkc21qT2M1SnBVbG5SanJ1WGNvcmtYNXVuT3k1NTNQRmsxV1pCOE9JV1lFcGV5UCtXRElFSlFMeGhQNWFkdVRSMFQ4b1NiaFU5RnZxS05vbEd4dDdoS1BKTG1uVmFWOWpqZE8zMUQrbWlHVDBaMXhqTUpUMUlyZVpFWmtya2o4MDFXUk5iZXJNL1pjZGt0T1pTY2xKeWpVZzFwbHJRcjF6QzNLTGRQWmlzcmt3M2tlZVp0eWh1VGg4cjM1Q1A1Yy9QYkZXeUZUTkdqdEZLdVVBNFdUQytvSzNoYkdGdDR1RWk5U0ZyVU05OW0vdXI1SXd1Q0ZueTlrTEJRdUxDejJMaDRXZkhnSXI5RnV4WWppMU1YZHk0eFhWSzZaSGhwOE5KOXkyakxzcGI5VU9KWVVsWHlhbm5jOG81U2c5S2xwVU1yZ2xjMGxhbVV5Y3R1cnZSYXVXTVZZWlZrVmU5cWw5VmJWbjhxRjVWZnJIQ3NxSzc0c0VhNDV1SlhUbC9WZlBWNWJkcmEza3EzeXUzclNPdWs2MjZzOTFtL3IwcTlha0hWMElid0RhMGI4WTNsRzE5dFN0NTBvWHBxOVk3TnRNM0t6UU0xWVRYdFc4eTJyTnZ5b1RhajlucWRmMTNMVnYydHE3ZSsyU2JhMXIvZGQzdnpEb01kRlR2ZTc1VHN2TFVyZUZkcnZVVjk5VzdTN29MZGp4cGlHN3EvNW43ZHVFZDNUOFdlajN1bGV3ZjJSZS9yYW5SdmJOeXZ2Nyt5Q1cxU05vMGVTRHB3NVp1QWI5cWI3WnAzdFhCYUtnN0NRZVhCSjkrbWZIdmpVT2loenNQY3c4M2ZtWCszOVFqclNIa3IwanEvZGF3dG8yMmdQYUc5NytpTW81MGRYaDFIdnJmL2Z1OHg0Mk4xeHpXUFY1NmduU2c5OGZua2dwUGpwMlNubnAxT1B6M1VtZHg1OTB6OG1XdGRVVjI5WjBQUG5qOFhkTzVNdDEvM3lmUGU1NDlkOEx4dzlDTDNZdHNsdDB1dFBhNDlSMzV3L2VGSXIxdHY2MlgzeSsxWFBLNTA5RTNyTzlIdjAzLzZhc0RWYzlmNDF5NWRuM205Nzhic0c3ZHVKdDBjdUNXNjlmaDI5dTBYZHdydVROeGRlbzk0ci95KzJ2M3FCL29QNm4rMC9yRmx3RzNnK0dEQVlNL0RXUS92RGdtSG52NlUvOU9INGRKSHpFZlZJMFlqalkrZEh4OGJEUnE5OG1UT2srR25zcWNUejhwK1Z2OTU2M09yNTkvOTR2dEx6MWo4MlBBTCtZdlB2NjU1cWZOeTc2dXByenJISThjZnZNNTVQZkdtL0szTzIzM3Z1Tys2MzhlOUg1a28vRUQrVVBQUittUEhwOUJQOXo3bmZQNzhML2VFOC9zbDBwOHpBQUFBQkdkQlRVRUFBTEdPZlB0Umt3QUFBQ0JqU0ZKTkFBQjZKUUFBZ0lNQUFQbi9BQUNBNlFBQWRUQUFBT3BnQUFBNm1BQUFGMitTWDhWR0FBQWFoa2xFUVZSNDJ1eWRlWmhsVlhYMmYydWZPOVN0cWk2cWVtNm1abWo0bW9iRStCR1JNU0pEQ0pNUUNZb2dDa0hGS1lJR0lRb21PQVFrd1NpUnFJZ0NSaU1FR1VRa1lBUVJaQW9OQ0IvSTVORGRBcUdibnJ1NnF1dmVlODVlM3g5NzNhNVRwODZ0dWxWVVF6clBYYzl6bis0K3d6NTdlUGRhNzFwcjc5MmlxclNsTFZ1YnVIWVh0S1VOM0xhMHBRM2N0clNsRGR5MnRJSGJscmEwZ2R1V3RyU0IyNVkyY052U2xqWncyOUtXTm5EYjBoYWdNTlpORVprSDlBSkorakt3RWxnemllL3RidTlycWl3SFBKLzZ4dlpBVitxWlZ5TUNiQUorUDg1ejA0RDlnSDJBUmNCTW9OUHVEUUhyZ2Q4Qmp3TVBBNzhlNzhOZFVjVGx1KzVCYjZGQXNoV24xUVdLVHZVZENrY2c3QUNVZ2RoK20wVDVHbkJiM3J1SzRPWFZmZitFcHgrZk9IQ0JuWUdmQXNYTTljZUJQN0ZCYlZVK0NGeG1ZRXAvLzJyZ0E2bHJYd2VPbU1LK1h3d2MwT1RlVE9CczROM0EvQmJMMndUY0Mxd08vUGgvdVdMclU3Z3hFWGtybVlGcmlCZnViZ2JjMTVNcVBBRDhzd0UzL1hzVDhQRUpmR2M3NFBOQUtWUE9md09mem1qMFVzNzNYczJ2MUtST2J3YnVCODZmQUdnQktqYXhiZ1crQi9Ua1BlUlIvaGNzWHpvUGVPdXdCaDM5bXlMTE9MVlV3ZVN6d09IQTNwbnJud1p1TkRNL25uelJ0RnRXUGd5c0dEWG1VeXZsbkd1N0dmQm1qZkZlYkJPcTFFVFpBSndDekFiZWxyVStYUzZpSkxJMWd6Y0Nqc201L2p6d2xQVlBYd3MwN0hVRDdoQndwbW1uTkFpNmdTOEJ4NDd6L2hGbWlyUHlUZUJITGRiekNXRDFKSnhKQVo3SnVYNUpFOUQrQXJnT2VNeDR2RGUrdmNqQStZNGMyblE0OERmQWhTTm1ScVdMNllVQ2c5NXZyY0N0QUROeUtPSkJ3TWIvMGM1WlNoNDFVLytGelBWamdCT0JIelI1cjlQQW5aWGYybUMzS2g4RjdwdWlOdThDSEpWei9SK0JjNXU4OHhSd1BmQnQ0UHZBM0p6Ni9ZdUJIWUJGblYxaktPcXRSdU5tRy9ETC93bWduUWh3QWY3QkJuei9uQUcvRTFpYjg4NDV3SjQ1Vk9CRFRaNXZKc1VwYlBNZjVkQ0hKY0FGTGJ4N3Q5R2JtektPd2d5UXc0QnJQVXBKSEh0MmRoT1BqaWJNQS9ZQWRqUXpXd1NxRnFINVBmQnNEblZxVldaYTJUc0IwNjJOaVFGdERiQU0rTTBFb2tGSkxuV2ZuTXdIOXJLSVVZK1ZzOGI2L1ZmcENiOGxnRnUzeU1CRHFWQlJvMUovbStPczdkRkVnMTF1a1lxSm12eXBrams1MTE0Q2FpMitmNnRSaVYwQkZZR0NJc0R1SU5SUUR1cnBZMkZuRjRQSjVyRS9EbmkvUlRkNnh5aDd0VG5FVndFL2JMRSsrd0puQVljWTN4NUxsaHZsK3pad2U4NzlzODJDZXB0VTAzTXM3TDBweWliQVY1cFkzQWg0SjNBR0ljelkzYVJPSzRHZkczVzhjMHNBRitCSkErbWxtZXNmTVJPNk9IWHRuNHdmcHVXWkZqWGJscFE4Z0RZMDFkSVczbytCUHdNcUNGNEV2T0ppZENNbzgwcGxUcG85aDNyZ3RoWGdDdURVRnVzMnczeUdZNEViRE96cnhuaitIT0NpQ1Zpa3VjQUo5cnZTckVlY3VyOHd4NkptSjMxMjR0K1U4OXdpUWxqelQxcW8weXliTENjQzM3Vkp1SGFxZ1l2TnNLUFRZUkxydUM4REIxdEh2TXNHTjJ0NlBnajBUK0tiOVNrRTduTk5BSE9iVGFxN2dBM2psSkZyMmdvaW5MUDlmTFlyZFREZ0V5VHcrMU9iYUw2WHJFKzJJY1RMczJHN3Z6RGdIOWZFYko5c05DMHJHNHgyREpwbTdERnEwcEY1N3YyRXBNb1hYNlZseTc2emp6bmRlWlp0bVZHaEFyQkRqb044S3JEQU5QdWFxUVp1WWh6MVlVYkdNQThBM211YTk1S2M5NzVrWm1ZeXNwM3hvOG1rcUpkbnRPeWp4aVVYNW1pSm00QVh6QWw1MmtJL1M2Mk1sN1BhTDFJUUJDK0tRemhwMWx3V2RYWXprQ1JJS1AvOU9RTjNucG5FMWFsdzNTN0FhY0FuTW1OeU5QRDJIRlBjRGZ4OTV0cEdtM2czV2wwYllPOHdrSndNZkNyRDd6OElmQlVZc0g4dk5oNGUyMFE2TFBQOE1xTkprcUlEejJRMCt2VTVvTDNWRk5zaktjVTEyK2pOZWVaM05HUS9vdzBuTWthTVdNYmE1U3N5NWdUOHNIblMyWUY1MkQ2YURhUHNUOGc2alNlMzUyanJRZE82azlFSWgxcUhwZVZZNEpZSmxGYzEwQzZ6Z1hvQXVLY0F6K0dFV0lKRGR1bE91N056dVVJMTBJVFRqYXVtNVUrQm42cUFLS2dsdndWQUZVVE96Wm4wUDg0Sk9SNFAzSnk1ZHBxcWZvZkdlRHFYcHc2L2FFQkpPMXQ3a0IrTEwxbDcweEdVS3htWjVjektGVG4zTHhHTElQbU1tcmE2OVdoSTVHVGJlQnp3bzhtbWZNZVNyNXRLUHpManFNM1A0WlFmYkJHMGpCRldtOHJJeWEybWdTNXJ3YUZwYU1VR3Y5dkhMTXVRSXY4SmNnbm9Belh2dVdYdFNqNHhkd2MwREZHZktMaEdla2xBa1FIdkJIV0NXbktpcGdrT29jc1ZTYXExSzhLa2xXbmh0ampqZXhLZ3JUYm9NaXRvUGswME9JWnJWZlhHUWtlSjdoblRVVlZXckY2Sjk1NmlPQW80bkZmRSs0Y3k3WElqL0pDR29ncmc3OHlaMklXOFo2MkpPOG1vZUwzOERPRnZhZ0t4NkloMUMwS1l2QVdWRFVYUDZhQlBtR1Z0eUZrYUpxMmZhdUNxT1dXUDVIaWZhYmtZK0svWDBSbmIzRjNPT2FJb29sNnZRMGcwM0crVzR3UkNObTBpMHBHZ2I4UExrY0NuRUw1MDk3clZITlhUeTg3bERtcXFxeU5sc3dLTUhhaTRxMUg1bW5xNVQwV1dLYXhLMU9ORjZOMXVIdkhnMFBxTnE5Y2Nvb0N2eDZoUHhDemZDTFBvVmI4TitpMFJVVmNLZmxtcHE1T2VtZE9KaWtYaUpNYXZlb1hFZTV5QUUzbzh1cWVvbmoxMlJ4a0l0WlZPMWVING1JS2dSNEdrRll6MytNL1V4RGlMQnFCbUFWUUxEdExxb25LNUlCZW43dTZQeUc1TmZKSnhWNGVOalZ6VkpWMWRYZWQwZDNkZmxhVWNJa0ljeHc4UERnNWVsUGR1VjFjWHpyVk1XWjlYMVEyVHBBcWJuY0Zpc1VpNVhLYS92NS8xNjlkVHI5ZGZNTjczT2VDUG9pamF0N2UzZDY4b2loWUIyNXFaTERVdjJvRktVYVA0VWhWNXlYdTk3cUZpa2IxbnptRWdTUjRVa1Jnb0pCTFlvRlBkM1NsZnNaZGZBVjdvUkpjSThxeUxvdWNyMDdmNVZiR3Y1emZlK3cyMWFwWDY0SkRHL1FOb0hJOW91ampubzJtZEZEc3JsQ3BsSW9tS3pybnRKVW5tZXUrM0JlYjE5dlhOVmEvelJkalJJVHRwY05DMnBPeWJkYWdWUGFZU0lndmpEWFFzc0tlTUdGN3RLSmNyZTA4S3VBc1dMQmkzdHFWUzZlcGlzWGlVZWNGcFdTOGlaM3J2YTVPZEdLa0pjcWFJL0h6U0tsZUVlcjNPME5BUTNudDZlM3ZwN3U2bVZxdFJyVllaR2hyYU5EQXc4Q0R3NEx4NTh5Z1dpempucHFucVBPLzlEc0JlcXZySHdFRWlNait0ZHdJZDhGUWorYXozL3BabllkUHlubW5zV081NHZxcGNndXI1Q25RSUlBbXAxUXV6SmRDVXZWR29xNmVleENEeW9ncUxvNDdTRFhTVWJ5eE9tMWFWZUtTMTFNaEJ5ZUhRd3oyOFcvSDdrZmp0UVN0aFBnblRac3pZakhYVkxSQU5IeTA3Wk9tVkJLVXdJUk0rY3R4Wk1LbW9RcWxVYWdWVVZLdlZLM0tBZXgvd2VCNDRKM0hza3dBVUNvVkpnVGFPWTRhR2hsSTJ6Qk5GRVpWS2hjN09UbFNWRFJzMnNHSERCcElrd1RtSHF2YXJhci8zL25sVnZjdnEzS09xSjZucUpVQnZvNmRMWHFrVzJIMEkvNFphNGgrNmN2bnZPWC83QlNUQ0JUNU9YcFRFbnlYS3dpVHlMYXhQMWUwdGd2TG5vR2VMNm1rVzRVaDNZSmZHL2h2SlprNnBPUkFZQWZZMUZnMUltTm9sb3lPTTZGUVhxT2ljU1FFM1BkZ1RqT1hSSlBiNHFuaHF2VjZuWEM0aklpMkJYMFJJa29TaG9TRlVGUkhwc0JEVk5MVUNWTlVCdC9mMDlEelczZDJOaUNBaURmQnVCbm9qUmhySDhUZmpPTjRBWE90c2JkOWdBUXBEQ3VKM1RWUWZLZ3hWcWZXdmg0NE9uSXUrZ2ZmWG9INGZVZllWMVRkYStHcyswQWRTR2dQTGJ3SitnT3ArNmRpeUtGK1ZSTitkTTlETGdDY1JmZ01zRWVRbFlJbVA1RVdVVjF5aXAyOUI0R2FkNzBFVnZnc01qVSthYzNzZ0F2M1pwSUJyVHN4a2dUdWxocWtCMXY3K2Z1STRudEI3bFVxbHdhZEZWZitXMFVzc1p3Q1BpUWpyMXExRFZhbFVLa1JSdEZrRE8rZnczbE92MTFIVm53SnJuZExYaUpWUkY2UVFsVHVkY095MDZVamlxVzNjaUxnSWNXNEk5ZmRLVkxoWG5FUENQT2dWWlI3NFhSVGRVMVgzUjNnTG8xUENpNEFqRkxWWXJ1d2xJZWFibGxVTzkxRkIva01kL1RyQ2RaZmdHTlZqVkxWM0MxS0ZaYU5DcmVpRjRxTGxJVGlpelFZSXZFZHpWdEdwVERJQk1SR0FiUEhRZ0FpMVdtMGlrMmxZRld6YVJMbGNCdGlrcXI4QzNwSjU1Q2pnVTBtU1ZHdTFHdDU3QmdZR05tdmNoZ1oyempVMGZpOGhxeFU2TVFHZlJOUmpYYkh2Tmowc0tKVTdhdWliRVNtb2V0VWtFV0FJN3grTW9vSVhWMEJFMWttSURUL2owZHNVajZyZlJUM1htYVpOeTU2cEpNUitPVXJoSDlSRi94NkZjaTArcktnQndpZHh3K0xzMVp6eWVWQkZYRFRaSVhxSWtWbkNDdkJPamVQTHhFVzRLTDljbnlSb0VvTnFDWkZDQ3VFRjArTHgxZ3pjZ1NSSjhONjM3TkNONEN4SlFyVmFiV2pkdTNLQSszK0F5NUlrK1JDZ0RacVFwU09xU3ExV0k0cWljNEVPSFZZdFJPb0g2eXBQN0JoRkZJU09tdmMzQnlxUWltZXIzNzFlajVlaGlvakRSV0djMVBZVGFFakIzcEFEM0xRNjZzdHA0bElmSjhUVVFNSDdFSVh3U1JMYytTaENJcmVUaUJ5ZlMrbTg0bTJzWFZHSFk3UVRrOXNJS3dqVFhQY2NWYjFCcTdXWHlPbFBFUUVScEJEOW9ZaDhEOVdLQVZjSUdjdTMwMlNKd05ZQzNCTlZkVThtbC9LdEF6Y2xTZEp2WFBWZmdVOFNOa2ltNVV6Q1pzNHZXM3czbXl1dkFHOVUxYlBqT0Q0eGNFb0JBYWRLMWZIRFRkNi91Q21wbzRtdTgwbnlsSVJGMStsTTFJWHEvUm5xdmZlcURaSUJJamhBb3FoTFJJN09JVjFQdzJaZXZ6SUhWb2VxNmc5OGJKcTFZWUpGUWdaTmRRSGVmMTgxTjk3ZWxUYlRQazVhai9iSWlNalFNbFd1RWRXUHBCN1pIdUZXUWhieGlTYkY3RTNpcjFVWmpxT0hKS0pjd2hqcldyWVc0UDYxeUt1aXpQZWxPbUVaOEdsVi9Xck9jMitWc0RGd3Vhb3VaWGdYUkorcTdpQWlPNmUxaGplelhFcDBoUy9JQlRXZlVFMWlTQkxVKzYrcjZrR1o4azhEZGtYa0dna0R1UTZJRUprSjdLUGV2MWRINXUwQi9sdEVmcGFLSFR5b3FuRm03TTRBWGtEa3V4TDI4WUZJRDdDN3FoNlA2dnZVajlyTjBKQnZFZGJFUGdwY2tzcUV0UWplRWVQeWQ2cDZLQ1BYZ2J3UmVKQ1FyYnlIc0FESUFUdXE2a0dvdmsxSEx3QzZDdWUrTmRaM3R4cU8rMnBvUnNQVU5qSm5xbnA1SE1mVENmdnA4bVF1bzNjNWpMYXhJbmlScFlWRTM2VlJZVWxKSFBPTFplcHhqS3EvemdieGpBd2xQWWhoVFR4ZzNuTkhQbGcwQVQ2R1NGcjdQNHZxTlNEdnk0empGd2pybjFlWTJ1b0I1b3lFb1c0QTZRcmZIT0g4TFdLU2kvWEZqV2piYWxUZnJxbzNCZkJLMmxxOXczN2pSWEwvVFVRK3BPTnNlU3FNeHcxYmxMeHlKcnUrb0hPS2dkdlZvQmh4SEc4T3B3R2ZTNUprTVdHWDd3R1RLTGZmNDc2dnpuME8wM0pGRVdaSFJSTDFxS3FxOGdGOGZRbm9KN0MwdUl3Uis4eUE5em1JUG9senQ0WU1naUsrTVI3NmNRMlJrRC9QbE5sRGFzVmVwcnovQVBjcDhQOEVIQ3FqdnlzNVVhRnBPWFFwZzdVSWlVWmcvaG4xL21EUitJc2E0c3lGc1VKTXFUcXVBTGxFWFBITHJjU2p4Z1N1YjMyajMzT212Um92T01MU3djbklGWVF0TWxPMXk3REc4QkpDNGppbVdOemMwYmVyNnUycWVpQmhDZUcrcXJvYllZMXNKYVdaWXNLeXdWVWk4cFRWN3piRS9YWjAyRjh6VHBYK3ZmUHg5MFQxQklYRE5FUUlwbWZLcndNYlhkQ1dqd3Y4Mkl2Y29zNXRISzJBQWRnbzZOdWQ5NmNvdk1mb1JWOUthMWFCRFM3UW9nY1F1VWxGN2xFQjUrTVBvSHF4d29IR3Urc3VUTHk3WkhSYzlqTUdYclV4Zld5MGRvdkJSYWhFYVJpdVFQM3BUdjFYUlBWRWhVTTA3QmpaaHVGbGtsVmduUXMwNVhZVnVWWWxlcWxsVFQ5V0lIKzhUTlVFMWhwczlzcEhlSlN2ZzBSUlJLbFVJbzVqa2lRWkVUMnd2M2VyNmt6VFhJMnQ2VVBBV2hGNVJVUnFtK3N1QlRSeWRBRkp1WUIzd2o5dXR3c0xLNTMwSndteFYvQTFuSThSVmJ4Q0lxN1RpNXR0ZzFnMGJiUXB4SVdUVnlMVldNVDRzeXVCaXhDZ0Vqa2txVEdVZUpzY2l2TWVyMUIzaFJsR2JUcHR3ZzhLckN6NmVKV1lPZmNpZUlsd1BnYXYxRjAwVFpFS3NLbmc0MzdIeElJSmtRZ2RGbjBaS2xZb1JpVVVwWjRrSkVsTVVldEVJY1RCa05kR0hXY3p2T3BzQUZoZThQSGFxTkZlaVpDb2pFdlJqK01mZVdEcXFVSWpkZHJDWWh5ODl5TTBlT09kUm56MHRaSVd3bW9ibWNoTzF0VHl2cUdOZzF5KzVOZThaZnBNRHVpYnlheGltVTFhejVyc1FRdjFVQlFoRW1ISWUwck9VVlFsdGo1M0loU2N3MFVSaVNvM3IzaVpNcDZEKzZiVEZVVU1KdkZJYm1sV0pSS2g3QndDMVB6d015WG5jQzZpNnVOR2Zmcnp2UFlPNTNBSVErcnhUWlJhU1J3YmZjenRxMWZ6Y3EzR2s0T0R6Ty9zNHNqWmM5bTUwb1VUNGZlYmhoaEtZaW9pN0ZMcHBCOVpYUkJaSGVybG16cUFsU2dpSWF6ZG1MVEdiVVVyaXNnSThHWUJtdFcwemJUZ1pNRGJtQkI1NVRlU0J0bDZxZXBtcmRzQWNRUElqZXhjcy9vMm5obld1QkVla0tST2txbkh6RktabzJmTjVjanBmWFE3U0h4Q0FVY3NEaFZISk1LTDFTRnVXL1VLdjl5d2daMHJuZnpaOUQ3MjdPeWtNNHBZbHlRc3JjYmdDdHkzZGlXM3ZySWNnSjBxRmQ0NVp5NXY2ZTNESnpIVm9NMDJhOEJWOVJyM3JGM0R5OVVxend6MGJ3YmZEaDBWOXVxZXhuRXpaMUJTR0xLNks2QnhXQWZWVllpNFk4MXFCaFBQbjA3dlk1dW9RR3poTlJHaDVqMlJDT3ZpbUF1WEx1RzV3Y0ZSZmJSdFJ3Y0ZoSmVyUTlRMUxMQS9jZlpzanBrMWx4ZXFRMVM5WjJGWDkrYkRVZ28rRHFmK2lGQ0tpdnhrN1RydVdiT0tsYlVRS254aDArQ1dBVzZhTm93MTZLMjhud1ZkSGlnYndNbWJJR09WbTMwMmI3M0RDRkRtVUpzc3VGdHA3OEt1THM2ZnZ4TVZFWjRhR01DNUNJL2pzZjcxM0xsbVZYb25NQUI3ZEhZeHIxeml5WUVCVnRhYWJ6dyt0Rzg2cDgyZHk1eGltYXFMV0YydmMrZWFWZHl4YWlXcjZzM2ZlMU5QRHpNTFJSWjBkVE90VUtUaUhBczd5a3d2RlBqaHFwVjg5YVVYQVpqZjBjR2l6aTUyNjZ4UTg4cUwxU3BIenBqT3RDamk4MHVYOHV0TkU5c1hNTE5ZWWsxY3g2dUdDVFJyRGdVUmZCS3pzS3VUeURtdWVmbGw3bGk5cWpXbGx4MkVWZ2VFc05HdFdXeXdnN0NlOWJYZ0FFWEMyb1BaaEIwS3MrMVhtT29QWllIZHFrd3ZGcGxYS2plN3ZSdGhHOUYrRXkxM3UzS1o4M2FjenlsenQyVm1jZFJLdm4wSlh2M2hqSDNVRkR0MWRIRHNqSm5qZDdRSVhkR0VVc0pmSSt3S0gxTjZDd1cyTFpjbmhNOVhBOXd6akNObHR6T1hDWHZNZnJRbHdKTWpCMW9nZjYzOTFsbldheUk3R2c1aWRKcjF0WkpGNXEwZk1rWGxiVVBZOHJMSmtpM3JDSm5DMTBOdUlHekdiTWdmTXpyZFBpNGRuR3JnUnBZSldaS0pSMzdCUE51RnIxSG5IR1pVN1VUQ2ZyQTMyNThkRXlqamQ2MW9ocTFFenJQKzJOOFV4MXhhMjFmM1dzZ3ZDSWVSdks3QWhiQWRaRk5xVnUxdG5mYWhoZ05LMk9INUFHSGYyV2N6Q1lac05rVUlXN1QvYjhQS0FoOGo3UHE5bTVDZWJBYmNab1B6VHNMcXIwOVlIZjR6bFhEWWgzQzR5VHJDK29STENTbEtDT3NXdm1QVzQ5Wk1rbUtlMWV0b0c0eExUZE9kUlRodjRqckNGdmN2TVhJTC96SEFTWVNkQVk4YlBaaEpPUG15SjJYSjdpZWtTVTlJdlh0RVNDTHd1UFhEdGszYWU2V0ZtcG90N0o1dnoveVNzS1A2ME16OUl3Z0xaaDZ6OW1QVzZLek1jeWMzRWlDRWhlOGZJK3pVdlordzJBYkR3WnZzbTVjU3pwTDRmL2IzQXdubmIyU3phU2ZabUcxUjRFTEl2NnNONG1LR2oxZHloSE1LVmdMdklSekorU0xoVElFR0lidUxrY2Z1UkJhWS9xc1UvMVBDSXVvdkVIWVVaMG5tb2ZiTWNZUkEvTjZFWUhkRGJyTXlyN09PdnQ2QU90TjQ0SldFRThjZkJiNWg1bXd1NFN5RlcreWRLMjJDTHN4TTBOV21xUThtSEdTaDF0NnpiVkJXV0I4MDZ2d3RlK1lCNEgwMjRQdll0VmxXamhvSVRrM1JoNk10Q2ZJNXdrNlR4UWFzUEdKNGxKV3gyTXBMeXd3THhmM1UydlVWUzM0MGpwQTl4ZDc5WndQaFgxcmR6ODBKbmQzUDhHbWIrNlhhZmo3RGg4VzhZa21NK1paWWV0a1NVOTh3NEY1czVYYWtNblByMDlSbVN3SVg0Tit0WTFmYVlHQ2Ryb3c4aHVjTmR1MTQrL2N0akR3aks3TEdOdmJtNzJMUFh6VEd0dzlPZ1h1ZC9YbEQ2djdOQnFCU3lxbE1DRXZtMHBtLzlPbVJGeHNGU3NzVERKOGMwMmhIbWp2dWF0YytrN3AyckYxckFQNWZiQUtrMTBIc3gvQ0pOaDlKZ1RodGhYNUpPQ1FqeldQcmpEeE5LQzJuQTZ1c3JPK2t0UG01akQ2RjUxNERGYVlScjhvcDcrT21kTkx5RStEYUZIZlZsTUpweUc4eUZPem5oR01OTmdkZDdMM0dCRHZjWXVoenhnUHVWRGxQNXhuSHZEalZ3SU5NYTkyWEdmemZXWWYva1B6TlVwb1pOTXhFTmszd3BiVFM3K3o5YXNaWmZJamgwMnpXMmF6ZUpoMDF5Mml2UHpDZzMyejNsTEFaOEE4eTlmcEpUbDN2U0YxN3RCSGxNazFUSnFRNGwyZmEzTkEydHhpbGVacHdLczAzR1Q2SkpySDdqWGNLaEJNUTc4N3BrNnZOUWZzWXcyZTF2UmY0UTN2M0psTVNhcFRJbThMWmxuQTRSMHYwTTZOd2xQekRETFBQcFJjMlBHdDlkSktCK2hUem04WTlzWEtxZ0x2ZWdMRWlVMkVoZi9HR3BnQ1RaRUpiSFpuR2FvdVpyQmROWTVEenZVMDVBUE5qZERDbW1hNVA5ZEcvcHNwdnRHRmd2QWlhL1ZsTnRiZFpXOG9XQlRnQStEc3pwenVrTlBpVFJxMGEzNzdLSmtFeldXbnZ6aktUZjRacDZYWFdyZ2FBdm12dDZtalNEelFKYTNZeWNzMXlLLzJSVi80MURLK1BQZ1Q0NjFZQU4xWEFqWExLdTh1Y3NmMVNXdmNOaEFQZUdwcHFyV21OZExpa2g5R0gzTFVTRDA1YUFGQ3IvZkN3OGQ4ZjBHVHJTRTY5Tk1VeEY2Y2NSeklBazNIcXVOeWNtcktaL0FzSVJ5VE5uSUEyekxZdHR2bzFqc2U2TFllemxvei9ucHFqeGRlWW85eEpTRmx2WTA3c2J5YzRUb1djOXQ5a2JUekhsTjlQWGt2Z2luVjBPZ3IrZ00ybW04MXJyaEVPYXJzNVZibnJ6WEc3Z0hEWTNJZnRla2VxSTRTUjYwZWJEZmlQVEpzMU5OSXBwc0c2YzBEZG02bnIwOGFybHhxZHVZS3dHN2pCYTJPakloZVo1bXVjMXAwZHFMcnh2RUhqbUplWlJsdVcwbExUY3NiQW1WVTQwT0tjdnpYUS85eWV1ZEQ2N0NiamxYUE5FZjBvbzNmWHZzdkF1ZGlVd3NsVzc4VGVQZHNpRXhkWlBZOHhaK3kvck80M0V4WVYzVWs0ZXZVS1UwSnFmNy9OK3JhVW9sZU5OcmljbUhJNkxQbWtSUXp1TTcvaVFjTEt0SHNNQTE5bi9KTXl4eWEvRTNUT0tqWmo5c29CMVZsV3Nmdk1BY291V1A1TEEva2RGdlo2VHlvazFXdjhlYzQ0SWJuenpPUCtmT28zS3hWeU95NWpIYzdLMUhWWGN6QWZadmcvN05qUkJ2UWg2K0FyVW1YT3NXK205Mzh0c0FFLzFjcDZ4RGgvSmVQeG41eXAvN2JtTkpXTlE5OXV2Tzh5UnU3NFBkQWlJNCtZUnZ4a0UrMjlEK0hFeHNlTjU1NmFlVzZ1VGNZSHJXMVhNL0xNcm9Oc2dqeENPSG16RWI1OHE0VVNmMkdUK21pR0Q2cHJ0Q0g3UHhDZHljZ0UxVHlMNHo1aW5Mc2hiN09KY2RCckZjZHR5MGpncWpsaWJabVluR3RSbkdLcndDMjArMnpLcEdFbXU5cGQwYks4d1N6c1gxbGN1L1d6QjlvYWQ4cWsyL2hiWDdzcldwYkRqTTZjUGxGOFNodWdiZG1helZ0YjJ0SUdibHZhMGdadVc5clNCbTViMnNCdFMxdGVSL24vQXdDTzQxTEJDanowOHdBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wOC0wMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRklETyBMMSBDbGllbnQvQXV0aGVudGljYXRvciBDb21ibyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVUFGMTAwMDIwMTgwMjIxMDA0IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDgtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTA4LTAxIn0seyJhYWlkIjoiMDAyMiMwMTAwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiMDAyMiMwMTAwIiwiZGVzY3JpcHRpb24iOiJNb3ZlbmRhIEVnb21ldCBGSURPIFVBRiBBbmRyb2lkIEZpbmdlcnByaW50IEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X2RlciJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfZGVyIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoiaW1hZ2UvcG5nIiwidGNEaXNwbGF5UE5HQ2hhcmFjdGVyaXN0aWNzIjpbeyJ3aWR0aCI6MTE4MywiaGVpZ2h0IjoxNzM2LCJiaXREZXB0aCI6OCwiY29sb3JUeXBlIjoyLCJjb21wcmVzc2lvbiI6MCwiZmlsdGVyIjowLCJpbnRlcmxhY2UiOjB9LHsid2lkdGgiOjU5MiwiaGVpZ2h0Ijo4NjgsImJpdERlcHRoIjo4LCJjb2xvclR5cGUiOjIsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MH0seyJ3aWR0aCI6ODQ1LCJoZWlnaHQiOjEyNDAsImJpdERlcHRoIjo4LCJjb2xvclR5cGUiOjIsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MH1dLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFNZ0FBQURJQ0FJQUFBQWlPam5KQUFBQUJHZEJUVUVBQUxHUEMveGhCUUFBQUNCalNGSk5BQUI2SmdBQWdJUUFBUG9BQUFDQTZBQUFkVEFBQU9wZ0FBQTZtQUFBRjNDY3VsRThBQUFBQm1KTFIwUUEvd0QvQVArZ3ZhZVRBQUFBQjNSSlRVVUg0Z01CRFNJM2Y1Tjk0QUFBR2VGSlJFRlVlRjd0M1gxd1ZOWGRCL0J6enQyYmZjbHVTRWdJRXBKTkVDWFFJQVJDVUxRKytGYW5pcFNxcmJhV2NiUlRIS3N6OW8rK3pmU2ZwNTNwMDMvYXB4MW0ybWZHZ3ZXbHFIV3FkaXJGbDZLV0NpS1FoSkFJUWhCSXNra3c3MitiM2J1Nzk1N3plLzdZWk4yRTdONlh2V2V6YTg5bm5NNDBuSnZzN3YzdXVlZWVlMTR3QUNCQnNCdlJLeUFJVm9oZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z5SVlBbGNpR0FKWEloZ0NWeUlZQWxjaUdBSlhJaGdDVnlJWUFsY2lHQUpYSWhnQ1Z4OElZSWxWZ25JUFE2OUFqbVAwdGloUTZCcDhzYU5wS3dNWWF4M2dKQU5lUjhzTmpvYU9YQ0E5ZmZIRGg1MGJOeFljTU1OMG9vVklsNExMdStEcGJXM3M4RkJ4Qmp0NmFHOXZlclJvODRkTzV5MzNvb2NlZi9XOGxwK3Q3RWdISTZkT0lGVUZXR01DRUVZczZHaHlFc3ZSZDk2QzFSVjcyaUJvL3dPRnIxNGtWNjRNT3ZDUndnb1N1VFZWNk92dlFhUlNPcERCYjd5T1ZpTXFTMHRNRFUxdDBXRk1VU2prUU1ISW4vNUN3U0RLUTRXK01yallMSEJRYld0YmY1Mk9zWklWYVAvL0tleWJ4OGJHNXVuZ01CWkhnZExqVGZiVTkwQVlvd0FZaDk4b1B6cFQyeG9hUDR5QWpmNUdpd0loZFFUSjVDbTZSVkVhbk56ZU85ZTJ0dXJWMUN3VTc0R1M3dHdnVjY2WkxDL1NqdDFTdG16aDE2NnBGZFFzRTErQm90U3Rha0pRaUdEd1VLRWFPZk9oWjkrV2p0N1ZxK29ZSSs4REJZYkdORGEyNDJtS280UTJ0MGQvdU1mMVpNbjlZb0tOc2pMWUttblRySGhZWFBCUWdoaHpDNWZWcDU5VnYzb295L2FjMnRLWVhJU3BxYjB5bVZQL2ozM2dLa3B0YWtKVVlxSStXOEZJV3h3TVB6Y2MrNW90T0RtbTVFazZSMlEyelNOZG5WcEZ5L1N6azdhM1MydlgrOTY0QUVySHdzSCtSY3NyYU9EZG5XWnJxNFNDSUdKQ2VYUGY0YXBLZWRYdjVxL2p4VFowRkQwN2JkalI0NUFNSWcwRFFGZ2x3c2lFZXp4NkIyYURmbjJzV3FhMnRRRTRYQkczMHVNSVJTS3ZQb3FLSXB6KzNic2N1a2RrR00wVFcxdGpmejk3L1RpUlFTQU1FYVNoQUJZZno4Ykc1TkVzQ3lnL2YzYW1UUFdxNnNFakNFU2lienhCa1Nqcm52dnhZV0ZlZ2ZrQ3RiZkgzM3JyZGlSSXpBMUZYL3VQdjBQR0VNb3hBSUJhZm55dEw4Z1MvSXNXRnByS3hzWnNTRllhT2F4ejl0dlF5amsvdmEzY1ZHUjNnRUxUVlZqVFUzUi9mdHBaeWRDNk1vNkc2SlIydDB0YjlreXo3RlpsMC9CZ3NsSjY4MzJlV0dNTkMzMndRZWdLTzZkTzBsWm1kNEJDNGIxOTBjUEhJaDkrQ0dFUW1uZVBnMEVJQkxKaFl0N1BnVkxPM2VPZG5mYlUxMGxZSXdZVTQ4ZFE2cnEvczUzU0VXRjNnRlpwMWRSZlE1ajJ0Y0h3YUFJbGhtYXBqWTNReVJpVzNXVkRHTzFwUVhDWWZjamowalYxWHFsczhkZ1JaVUFrNVAwOG1XeVpJbGVRZTcwWDJ1T29IMTkydW5UTmxkWHlURFd6cDROUC8yMDF0R2hWelFyVkRWMjlHaG85Kzdvd1lORzc0SXhCa1ZoZ1lCZXVXd3c4SEp6ZzlyYXlzYkdPQVlMSVlReHZYaFIyYnRYUFhWS3J5aGZyTDlmZWVFRlplL2U2UWZ0eHQ4MVk3UzdHK1hBc096OENCWWJIMWVibWhCamVnVXpSZ2dOQkpSbm5sR2JteGZtc1krRmlpb1p4clNyaTRWQ2V1VzR5NDgyRmoxN2x2WDJtdmppWm9JUU5qUVUzcnZYSFFvVjNIeXo2Vk9iQWJNdHFubGd6TWJIMmNBQUtTN1dLOHBYSGdRTFlyRllVeE92WnZ1OE1JYnhjV1hmUGxBVTV4MTNaT0d4RDBTajZ2SGowVGZmcEYxZENLVzk5VXNQWTFBVUdnZzRhbXYxaXZMRi9TUExIT3ZybzJmUFpxbTZTc0FZZ3NISUs2OUFKT0s4Nnk3c2RPb2RZQjN0NjR2dTM2OGVPd2FLWWoxU0NhcEtBd0hFbUEyL0tnTjVFQ3oxNUVrMlBwN3RZS0hwYjMvazlkY2hISGJkZXk5MnUvVU9NQTJpVWZYWXNlaisvZE1qcDIySkFzWXNFSUJ3R0h1OWVrVTV5dlZnc2JFeHRibDV3YjUvR0tOWUxQcldXeEFPdXg5OEVQdDhlZ2VZWUhORmxZQXhIUmhnSXlPU0NGWWEydW5UdExmWCt1Y2V2N1BMcExiREdLbHE3UDMzVVRUcSt0YTNTR21wM2dINnVGUlVDUmhES0VSN2V4ZTJwemVuZ3dXeG1OcmNqR0l4aXg4OWdGUlpDWXFTNlhQcitFeXlJMGRBVWR3UFAwekt5L1VPU0lkWFJaVXNGcU5kWGVpbW0vVEtjWlRUd1dLQmdIYnVuTVZNQUdDbjAzbnZ2ZGp0VnA1L25nME1XUHc5U2RUbVpnaUgzWTgrS2xWVjZaV2RCOStLYWpZYUNJQ2k4R2dYR3BUVHdWS2JtMkZpd21JZ0FNank1WTY2T2xKY2pKMU81Zm5uYVhkM3B1Y1NZKzNNR1dYUEh0Zk9uWTVWcS9SS3o1S05paW9CWTNiNU1reE9MbUN3T0wvRERMRGhZZlhrU2V2ZDM0VEltemJGK3drZGRYWHVYYnNjdGJVMjlOMFRvblYwUlBidGcvRnh2YUxUSUJxTi9mdmY0ZC85TG5ib1VOWjY0eUFZWE5nNXV0bDRrOVpvWjg3UXk1Y3RuZ1lBVWxJaU56UWtmdUM0OWxyM3JsMk9kZXZTSEdTQzI0MEtDdlFLSVlRUTdlcFM5dTVWbm4yVzl2U1llK3FYQ1l3aEVxRUwralRhMG1uakR5SVJ0YW5KK3NOVUFNZmF0WE1HNlVwVlZaN0hIcE0zYlVwMWtGR3lYTEI1cys2Y0JWQ1U2THZ2aG5idmpoMCtuTFdLNm5NQXRMc2JZakc5Y3J6a2FCdUxkbmRySFIwV3Y5OEEyT1dTTjIyNjhsRU1XYkxFL2QzdjRzTEMyT0hEaUZJcnY1OHhhZmx5M1pxUGRuVkY5KytQTlRXaGFEVGJrWXJEbVBYMlFpaUVqZFdzdGx1STk2d0xRRzFwZ1dEUXlvbEhDQUVRdjkreGV2VzgvMGhLU3R3N2R6cnZ2QlBKc3BVR0hNYU8rQ3E2cVVFNHJMejhjdXpJRWVzZEpYTlllSjBJc2JFeDl0bG5lcVY0c2VOdDI0ME5EMnNaTjl2VFRJN0FYcS9yd1FkZDk5eURYUzV6ZndVQSszeHlRMFA2eEdOWkpsN3Y5TVNzREFFZ2hMRGJiVHFnTTArajljcnhZdkxsWm9YVzNrNzcrMDEvbEhFQXBLeE0zcmd4ZlNuc2NybnV1OC8xalcvZ3drSVQyUUp3MU5icTkyakxzbFJUWS9IMUoyTU1PNTBGWC82eTY2R0hzTnR0NG5YR2FScnQ2a0tVNnBYakl1ZmFXS0FvMDgxMmF5Y0d3RkZYSnhtWkV5SEx6cnZ1d2w2djh2TExNRDV1Nk0vSnN0ellhR1NxQXFtc3hHNDNLSXJGU2dzQUlTVDUvYzV0MitRdFcxQWtFbnZuSFdwMmFRYU1hVThQaE1QMlB1STBLT2VDUmJ1NnREbnIxUm9IZ0QwZXViSFI2S0lNa2xTd2RTdDJPcFdYWG1LRGd6clpZa3p5K3gxcjE2WXJNME5hdmh6N2ZLQW9lZ1hud3hqMmVPVHJyM2R1M3g2L3NRVkNpTjlQQXdHajd5c09Zelk4eklhSEpSRXNCS0EyTlVFd2FLait1QktBVkYxdHJrOGNZM25MRnVSeVJWNThrZmIwcFB1N0dNc2JOeHA4Q0kxOVBsSlJZZm81VXJ5aXV2cHE1L2J0OHFaTmlSczZMTXVTMzYrYS9VemlUNk43ZXFRVksvU0syaSszZ3NVR0I5VlRwOHlkakdTU0pEYzBXS2o1NVEwYnNOdXRQUGRjeXVWR0FQQ2lSY2s5cnVsaHQxdXFxdEphVy9VS0ptRU1lNzBGTjk3bzNMYU5YSFhWbkgrVS9QNzRtaC9tUHB4WWJLSGE3eWEvQkp5cHAwNlovcFluQUpDeU1vZGVzejBWeCtyVm51OS8zN0ZtemZ4dFpBREg2dFhFNzUvbm4xS1FhbW9NOXM1UFYxVFhYdXQ1L0hIM3d3OWZtU28wYzIyOTh1YzZNS2FkblJBTzY1V3pYdzRGQzhKaHRhWEZ5SHExOHdOd3JGc256WGRXREpLcXF6Mjdkc2tORGZOa3krbVVOMjgyMWRrb1ZWWWF1dVZrREJjVk9lKyt1L0FIUDVBYkc1RXN6MXNLRnhXUjVjdjFmOXNjR0xQUFBvT0pDYjF5OXN1aFlOR0xGK25GaTVhcksxeFlhS0xabmdLcHFIQS8rcWg4NDQzeE1WalRQMlZNcXF4MDFOV2xQWFF1VWxvcWxaZW5pd0lBd3RpeFpvM25pU2ZjRHoyVWZ2b3lkcnNsdjk5MHNCQ0tON1AwU3Rrdlo0TEZtTnJjUE04MkV3WUJTRFUxam11dTBTdW5qNVNWZVI1NXBDQyt6VlA4UkJJaU56U1luVkNGM1c1U1daa3lDb3poNG1MWGpoMmVwNTZTNit1TmZCK2s2bXBrb0tkakZvd2hHbDJRWmxhdU5ONVpmMyttemZiR1JydVd1Y0pGUmU2ZE8zRmhZZlR0dDFFMFNoWXYxdTF4bllja1NYNy81K2xNQUVDRU9OYXRjKzNZNGZqU2w0emYvMHArUC9aNHdPeThFZ0FhQ0VBMHluV2kwWlZ5SlZocVd4c2JHakwza1NVQWtLVkw1ZnA2dlhJbVlMZmJkZi85Mk9PSi91MXYwdXJWeE5KcVpwTGZqOTN1V2N1R00wYkt5Z3J1dU1ONTIyMTQwYUswUjg5RlNrcWtwVXMxcytzTVlFeDdlMkZxNmo4eFdCQUtaYlR3RllCY1gwK1dMdFVyWnc1Mk9sM2J0cEdpSWxKYWFxclpua0NXTGNPTEZrRjh3anNBY2pqaytucm4xNy91V0xYS1hEZ1FRZ2hoajRmNC9jajhVdlV3UHM0dVh6YllBMmVYbkFpV2R1R0M5ZlZxQWJEWEt6YzBXQXhsZXJKY2NOdHRsc2VkNHNKQ3Fhb3F2amdBV2JyVStaV3ZGTnh5aTVWZWd6aENKTDhmeWJLNTE1T1lHMzNkZFhwRjdaUUR3V0pzZXBzSmE4a0FrRmF1bEZhdTFDdVhBV3N2RENGY1VDQlZWYWt0TGZMR2phNGRPekova2RQWFZyTzNPSlRTN202a2FWbFlLeUFoZTM4cEZYcjVzdWx0SnBJNUhQS21UYnJqT1JlS282N09VMUlpYjlsaXl5c2tTNWVTNG1KcWRxUWF4alErTnpxTDY2eGEvQzdhU0d0dHRiTE5SQndBdWVvcWU1dnQ5bktzWGwxdysrMjJwQW9oUkFvTHBlcHEwNzFaR0xQUjBTenZyYmZBd1lKZ1VHMXBzVDVtQ0VCZXZ6NFhWa1pNeWRvWEpoVlpKbjYvNlV0ei9HbDBmQjJiYkRINUV1Mm1uVDl2ZmIzYStIak94a2FMaCtjbnFhYkd5cUEvVmFVOVBhYVB5c0NDdHJFeTNHWUN3SEhOTlZKTmpWNDVRMFpIUjg5MW5BTUd4Y1hGcGFXbFJVVkZIcHV1WC9hU0tpcHdVWkhwa1Y0WTArNXVVQlM3THNxNkZqSll0SzlQKy9oajYvV053eUUzTnRvMTJiZWpvK05Ydi9wVkpCS1JaZG5qOFZSWFYyK28zM0RUVFRkZGZmWFZlb2RtRmZiNXBPWExXWCsvdWM4TjR5eHZpTEtRd1ZKYlc5bm9xTGtQS0NIK1lGaHZHcFp4bEZKRlVSUkZRUWlOVDR6MzlmVWRQMzc4d0pzSHZ2bU5iOTV6enozTzdIWmJwNEZkTHNudlYxdGE5QXJPbHZVTlVTeGRnK3dBazVOcVM0dTV2cjVrR0RzMmJMQjNMd21NY2Z4L0NTYVNKQ0dFdXJ1Ny8vQi9mM2oxdFZlWjVkZkpBYW1xUXVhREh0OFFSYStVYlJZc1dOcTVjeXdRc0ZoZEdadUdaUW9BVUVvWlk1RFV3aVdFS0lyeXlpdXZuRFgvSUdXT1dDdzJOajQyTkRUVTA5TVREQWIxaXFjajFkUVFJeU85cmhEZkVFV3ZsRDBXNkZLb3FobHRNMkZ3R3BZWmZyLy8vdnZ1UDlkeDd1elpzNHFpNEpuSUVrS0dob2JlZi8vOU5XdldFRXV2ZG1CZzRQRGh3MjN0YlQyQm5vbkpDWWZEOGNNZi92Q0c2Mi9RT3k0bFVseE1saTQxM1lySTdvWW9DeE1zMnR1YjBUWVRocWRoR1ZkZFhmM2trMDlPVFUwZFBIanc2VDgrSFF3R2NkTExhMnR2Q3dhRGkweU9SMEFJSGYzbzZEUFBQTlBSMGFGcFd2d1hlandlVGJVNlNoWWhORFBvVC92a0U3MkNjMlZ6UXhRclg4SE1xUzB0MXJlWmlLK2VZR3dhbGlrWVk1L1A5N1d2ZlczcmYyMU52aUJpakFjR0JrWkhSOU1jTzY5UFAvMTA5KzdkWjg2Y0FRQkprdUlWSGdDQSthdllMSVJJMWRXcEJqR25sTjBOVVJZZ1dHeDhYRDE1TXBObXUvRnBXQlk0SEk0Tkd6WVV6QjRuRTQxR2gwZUdVeDB5THdCNDk5MTNBNEdBTkRNNkZBQktpa3ZXcmwyN3VIUngrbU4xRWI4ZmV6eW1tMWxaM0JCbEFTNkY5T3haMXRkbnNib3lPUTNMR3AvUEo4dXlxcXFKcXlGakxCcUpwajlxam1BdzJIcnE4K2xmQUxCMjdkb252di9FeXBVck0rOTZsY3JMU1drcG5adzA5ekhPYkloaWRwaTFCZG11c1NBV2k1MDRZWHArWElMNWFWZ0xaV0ppWW1CZ0lCNU5BSEM1WEE4ODhFQjlmYjNQNTVNTWpIQlBEeGNXU21rRzFLY3lzeUdLWGprYlpEdFlMQkRRUHZuRVlxb1FRZ1VGeVZPRWM5bFVhRXBOdXVoNHZkN2FWZlp0UStKd1NEVTFScVpnekpMRkpXaXlIU3kxcGNYNmVyWHgzbllPelhZdVp0Y21FcEZjdHQ3R3hnZjltYTYwRWh1aWNKYlZZTEd4TWJXMTFmUm5rUkJmcjdha1JLOWNMZ0prOVYyblFDb3FyQXpjbTlrUVJhOWNwcklhTE8zMGFkclhaN2xUbEJRWFc1bUc5UVVWZnhwdCtsczZzeUdLWHJsTVdUckhsa0EwT3IzTmhEVUEwcG8xMXFaaG1lVndPTEMxaTNWcTl2OUNwMU95Y0JNenN5R0tYcmxNWlM5WXRLdExzN3c3SEFCMnVRb2FHN1BUYkM4cUtwSm5kejh5eGxTejNUK3ozNmltYVdHN0wwQ1MzMjlsdG1COFF4VE9zaFdzK0hxMVp2dGRFZ0JJWmFXMFpvMWVPWHZFKzdFUy94ZGpISTFHKy9yNjBoeHlKYXJSNUI3MmNEamMyZFdacHJ3RnhPODN0TzdJRmVJYm91aVZ5a2lXZ3NWR1JyUU1tKzJOalZubzFvc3JMaTVldG14WmNpd1lZOGRQSEo4d3MyeEwvMEIvWkdZb0FjWlkwelRGN25OSlNrcElSWVhwVDNWbVF4UzljaG5KVXJDME0yZm9aNTlaYjdhWGxNZ2JOdWlWczQzWDYxMi9ibjN5VHdnaDdlM3RML3o1aGFHaElTUFhSRVZSUHZ6d3cwZ2trdWdnOVhxOS9pcnpUYUswcHBlZ01TOExHNkpZT3RNbVFTU2lIajl1L1JIVmZOdE1jSVV4dnZYV1d5dVdWU1NQNzFOVjlhOS8vZXVQZnZ5ajMvLys5MU9wMTVrTkJvUEhqaDNidlh2M29VT0hFaytkRVVLM2JMM2xHanNXdzVrRjQrbTUwYVprWlVPVWJBU0xkblpxNTg5YmJsMmwybWFDcTlyYTJ1OTk3M3RsWldXSkN5TEdtRkxhMGRIeHIwUC9TdE1NUC9QSm1WLyt6eS9mMlA5R05EcjliTEd3c0hEN1Bkc2ZlZVFSSHVPYkpXdFBvL2x2aU1JL1dJbjFhcTBHUzZxdVRyWE5CRDhZNDd2dXV1dkhQL3B4WldYbG5ER2xoSkEwZlFlYU90MldTZ3gwM3JwMTY1TlBQcm1Fenlnb3NtUUpXYnpZZExCbU5rVFJLMmNkOTJDeDRXR3RyVTJ2VkdyeGhhOHNkREZuYkdobzZFVFRpYkd4c2VRZnhrT1dwaHNkQUlCOVB1SUtBSTRlUGZybVcyOXFscGZBVEF0N1BOWlcrdU85SVFyM1lHbnQ3WFJnd0hxenZiVFVrY1ZtZTRLaUtIdjI3bm45OWRkRG9WRHk0QmxDaU52dEpqamwyeWtySzl2VXVHbng0c1dKYkkyTmplM2J0Ky9qano5T2RVaEdIQTZwdWpvSG4wYnpiYmpZczgxRUJ1dlZXbmI4K1BIMzNuc1BKZldZQThES2xTdnZ2dnZ1MnRyYU5HT1VWNjFhOWZQLy92bnAwNmQvKzd2ZmRuZDN4eStkSXlNakh4NzlzTDYrM3ZiK2Q1UllnaVljTnRmWTBEUWFDQ0JLVFlmU0dFdm4yekI2NFlMMjZhZm0zbkJDWXB1SjdEYmJFVUtxcW43d3dRZkpkUlVBVkM2di9PbFBmdnJRdHg5cTJOZ2dwNzRSa3lUSjQvRnMzcno1emp2dlRKNThjZjc4K1JDZk5nMnBxTUFXZXZobWxxRFJLMmNSejJEWnNsNXRyWDFqbUF5Ym5KdzgxM0V1dVhaaGpOMTQwNDNYbVZtN2JIWHRhcmZibmJnZ0RnNE9KdTRUN1lXOVhvdUQvb2FHMkxDNThkYkdjUXdXR3h4VU0xbjRLdDVzOTNyMXl0bHZkR3gwWW1JaU9WaE9wL1BhYTY5TmM4aVZpb3VMRXdQbk1jYVJTSVF5cTR2cXBEWDlOTnJzNXp5eklZcGVPWXM0Qmt0dGIyZURnNmJmY0Z4OGQ3Z0ZXdmhxY25JeStTWU9BR1JaTHZLWnV6UEZaTzRieDhqU1IySEE5Tk5vczVVV3p3MVJlQVVMUWlIMXhJa010NW13ZmIxYWc4TGhNTDFpeVM3VDdXNlRaemtUVWxXVmxhWElNYVpkWFp5YVdieUNwVjI0UUM5ZHNseGQyYkxOaEdYOHFoWk84S0pGWk5reTB6VVd4cXkvbjlPR0tIeUNSZW4wZXJWV2d5V3RXR0hMTmhPNWcydFlzY2RqWlFuSitOTm9QczBzTHNHaUF3T1pybGU3ZWJPVnVqMkhVVWFqTVM1M2hYR1MzMjkwczdFRW5odWljQW1XMXRhVzBYcTE1ZVh5K2xtalZ2S1J4K054SlBYQVRVMU5uZTg0bjZaOGhxdy9qUTRFZ0VNL2lQM0JncW1wNlcwbXJJbXZWMXRlcmxjdTF4VVhGeWNHUjJDTUZVVjUvVyt2WDdwMFNkTzBUTmR1bUE5WnNvUXNXV0k2V0RNYm91aVZNODMrWUdrZEhiU3owM0oxeFhHYkNjUG1YYmZEN0YyaHorZXJxNnRML0I1Q1NHdHI2ODkrOXJQZi9POXZMbDY2bVA1WUN5dy9qWWFKQ2RiZnIxZktOTHZQWDJLOVdwT25ZVm9XdHBrd29IK2dQeHFOSmlmSjRYRDRURzVWUWdpNS9mYmJ5OHZMazBjTGRnZTYzM25ubmM4dWN4aFdFTjlzek94OU5NWVFEdk9ZVzJGenNHaC92M2Jtak1WVUlZUmt1ZUQ2NjdPMnN1KzhSa1pIamh3K01xY2Z5K1B4bEpsZmxuTDl1dldQUGZiWWtpVkxrdGNLVEQrY0t4TVdtMW1KRFZGc1pmajVMbU5zY0ZCbmFCZ2hzWTgrWWlNakZvTUZnTDFlN1BQUnpzNVpjOEFsaVN4YlptV2VreG14V0d4NGVMaXpzL01mLy9qSHlkYVR5YytQR1dOK3Y5L0NxbXNZNDIxM2I2dXNyRHo0ejRPbjJrNk5qWTNGWWpHWHk1WDVvaUR6SWhVVm4yODJaaHlmRFZHTUJndFVOZkxhYTJwcnEwN3JKeEl4L1kxSndCaW1wc0o3OXN6S0pRRDIrUXFmZXNxdTlkeFRhV3RyKy9WdmZqMHlNaElPaCtjc0NTbEowdWJHellXV3VqOHd4dlhyNjY5YmU5MzQrUGpJeU1qSTZBZ0ExUEo1c2s2OFhzbnZONzFFVkh4RGxPRmhhVUdDaFFBZ0hJYkpTWjFnbVhwTFY2SVU1aXo4R28rcDVYdE13eUxSeU1qd2lCSlI1cVNLVXJwbXpacXRXN2VtT3RBSVNaSktTMHRMN1Ywc0RnQ21waUI1aWdyR1pQSGkxQWVrZ0RHRXc3R2pSeDBURStrV0N3RWdKU1hTaWhVRzc2c01Cd3NoaFBIMGYxeGQrZnQ1LzBXRUVFSVk0VG1QalFHQU1WWlZWYlZyMTY3bFdad2paQkRFWXNxTEwycHRiWitmYVl4QlVReWUrRmtvamI3elR1eTk5OUpkYlJoek5EUjRIbi9jWUp2RVRMQyswQUFCWXl4eEIxZFFVRkJTVXRLd3NlRysrKzVibTVzTEp3RkFNTWhHUnVZbXlkcjNVTk1nL2Z3OHhsQXNacnlkSTRJMXplZjFiYWpmSUVtU3krMWFXcjYwdXFaNmRlMXF2OTlmWVBZNVNUYlpldzFKLzN0TS9pRVJyR2wxZFhXLytNVXZKRW1TSkNtbnc1UW5STENteWJLY1ppUzdZSmI1aHA0Z0dDQ0NKWEFoZ2lWd0lZSWxjQ0dDSlhBaGdpVndJWUlsY0NHQ0pYQWhnaVZ3SVlJbGNDR0NKWEJoNWxraFkxbllOV291Z0FYNG8va0NZUHEvTERENWh3d0hTNUtrK0RvK0ZzYVJaUUlBdTkzWTdkWXI5NThIWSt6eDRLS2lMSjBSeHJESFkzemtERFkrZVJKVU5RdERoT2VCTVpibExIMThlY1RJOUJaYjRjSkNVbDV1OEVTWUNKWWdHR2NvZllKZ2xnaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoUWlXd0lVSWxzQ0ZDSmJBaFFpV3dJVUlsc0NGQ0piQWhRaVd3SVVJbHNDRkNKYkFoU1B5Mm10NlpRVEJORWZrbFZmMHlnaUNhUTRrU1hwbEJNRTAwY1lTdUJEQkVyZ1F3Uks0RU1FU3VCREJFcmdRd1JLNEVNRVN1QkRCRXJnUXdSSzRFTUVTdVBoLzVTU2hUbjJXeGw4QUFBQWxkRVZZZEdSaGRHVTZZM0psWVhSbEFESXdNVGd0TURNdE1ERlVNVE02TXpRNk5UVXJNREE2TURCa0VBVDNBQUFBSlhSRldIUmtZWFJsT20xdlpHbG1lUUF5TURFNExUQXpMVEF4VkRFek9qTTBPalUxS3pBd09qQXdGVTI4U3dBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0xMC0zMCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQ2xpZW50L0F1dGhlbnRpY2F0b3IgQ29tYm8gQ2VydGlmaWNhdGlvbiIsImNlcnRpZmljYXRlTnVtYmVyIjoiVUFGMTAwMDIwMTkwNTA2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTEwLTMwIn0seyJhYWlkIjoiMDA1NiMwMDAyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiMDA1NiMwMDAyIiwiZGVzY3JpcHRpb24iOiJQaXhlbFBpbiAtIFBpY3R1cmUgTG9naW4iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImFsbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhdHRlcm5faW50ZXJuYWwiLCJwYURlc2MiOnsibWluQ29tcGxleGl0eSI6MzQzNTk3MzgzNjgsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjkwMH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJpc0tleVJlc3RyaWN0ZWQiOnRydWUsImlzRnJlc2hVc2VyVmVyaWZpY2F0aW9uUmVxdWlyZWQiOnRydWUsIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSGdBQUFCNENBWUFBQUE1WkRiU0FBQUFBWE5TUjBJQXJzNGM2UUFBREZWSlJFRlVlQUh0WFF0d1ZOVVpQdWZ1M2Mxcjg4UThnSVFRQ3BnMGtnUWFYcnViUlo2aXBRelRJdFN4VkxIVGtTUWdVRUVMQXBPUlVZZE9PekRESTlLWlZndVVqakxpMkhhY3R2TFE3Q1lFU3RVYUVFS3JEZzRSYVMwaUVVbXl1ZmYwUDhHNzdvWk45blh1YTNOT0puUHVQZmVjLy9GOTk1eDdIdmVlUllpSGhFWUEvL0dPTFE4a3RJZlJPRWVFS3d2LzEzQXNtaUpHenlzU1dUNW9kQ00xc3crVDQ2QXJvUWdXTkFPUEs5SUZBVTZ3THJCcnA1UVRyQjNXdW1qaUJPc0N1M1pLT2NIYVlhMkxKazZ3THJCcnA1UVRyQjNXdW1qaUJPc0N1M1pLT2NIYVlhMkxKazZ3THJCcnA1UVRyQjNXdW1qaUJPc0N1M1pLT2NIYVlhMkxKazZ3THJCcnA1UVRyQjNXdW1qaUJPc0N1M1pLT2NIYVlhMkxKbEVYclhvb3hZS2NWcExka1QxcDVKWHN5Y1Uzc2lxSFkydE9xbFZNczRsQ3NwaEUvejd2NlVFcjJ1NDVod25xQkJNN0NmeGpUSzRqSkZ5RStEelVodlpVK1ArRnkwV3ZteUlrTE1GQ2l2WG04UG1sN3hmK2NHTG5zS21qY3NYMHBHOFJRb3FBRmZvZk1pU0o2Q3RFU0NrUTZ3K2s3MFNHWklSa1NBVzIwUXFQdHdOdUFpL0M1SmdvQ0VkM09wMGYrQXNZN0NDaENFN0t0WDgyL3ZFWlowY3Vyc2kwWmFkK0d3ajlqb0kzSEN1SDhjZUVqQVJwU3hGQlMzMlNUQW4vR0NIeVY0c2dITmpsY0hnd1ZQZjRsYkNSZ0YvTDJXUVlZMkp4Q2R2RW51SmxrOTRlOTVnYnB4Um1UZ0lpcmJISW9XVnU5UGErczc3MTVNUll5OU55R0tHUGtJRDNpeGp2TTBMTk5tME5Gak9TT2ljODk5MS9GQzJ0dWd2dTBHa1VYS2ExbEFxTUlZQXRKVWdtVzN5SWJGblI1SDBkQzJocm84dlZHb01vSmtWTVI3QTFNK1dMaXUwTDN4bXhzTHdLRUxqYjJNMFB1WS9JNkw0VkhzOVJUQ3hiRzkyT3Q1aXdGb1VROHhBc1lLbGkyd0x2NkVlbVRJU2FlbmNVUHVxZmxhRFpCRW16YXoyZUl3S3kxZSt1bVhwQks2Tk1RWER1akRGbkp1OS8wR3BKdGM0d1FqTWNLem5RejVzallWOWJYWk4zVzE3UnlHY2JTa3E2WXBVVmFUbERUM1RRNTZ6N1NHM1Q5TVBMeTRIY095TjF5dEQ1Q0xIQm9HdnpsVXVYemtLTm5xTzJyWVlsT0h0UzRZVjcyemQ4bGxrMTNBMjFGanFuaVJXZ05vOGhDUCt0MXRPODlXVkNMR3A1WjBpQ3k1NmE0Nmw1NDlFaVpCVksxSExjRUhMaHhpVkUzblRNMjN5azd0U3BBalZzTWhUQmRFdzcwMVB2SGJ2V1hRTzFOa1VOaHcwcEV6cU5jbmZQdXl1YlRqaFoyMmNZZ3EzMnBDL252YmV1elY2VzcyTHRwQ25rRVpJdlllbU5GWjZXQlN6dE5RVEJ0bUdwVitlZVdYL1Jka2VxZjJxUnBaTm1rVVZiTFV5a1YrczhuaCt6c2xsM2dsT0xzaTdQYTN2aW1zVnVLMmZsbEpubHdNU05LQ1A4WXEzWHU0YUZIN29TYk0xS3VUYnI1Sm9iMkNhTVllRk13c2lnblMrWmJLL3plbjhTcjArNkVVeVg4K2E4dmZaaklIZHN2RTRrYW5sWkpudWh1ZjVlUFA3cFF6Qk1PODQrc2ZvOU1TTzVJaDdqaDBCWkM0eVZYNnB2YnA0ZXE2KzZFT3g0ZGJrM3VUQmphcXhHRDZWeXRPTWx5ZVRQUUhKeExINXJUbkR4c3VxVHc1eWpaOFJpN0pBdFEwaU9KSkUvTkJBUzlkcUJwZ1NuRmVkMHdGSmZZc3dwYTM2M2tlbWZlcjNQUkt0V000SUZpNlhYZmJ6MktoaVlGYTJSUEwrQ0FGNWY1Mm1acjV4RkVtdEdjTlh1UlY1WUhab1FpVkU4endBSTlNMWRTeTg4ZWZwMDVnQTVia3ZXaEdCN1NjNmx3dnVycHR5bW5TZEVqUUJNaEJSMDNyejVkS1FGTlNGNDJpc1BkMEJ2RUY0cDVvRUZBakpCOWFzOG5zcElaS2xPY05HU3FyK25qTXJpUTZKSTJJZzhqOFdIMEc2b05HSFh5ZFVsR0w0bXFOeXhhRmprZHZPY0VTTkFrSE5sYy9QOTRmS3JTbkRKVDZlYzVQUE00U2lJL2JwTXlGUGhTcXRLY05tbXVUbmhET0RYWTBjQVh2dXBDTGQrckJyQjlObWJNQy9LeGM2QitpV0p2SEV3SmFvUlhQN3N2YmJCRlBOcnJCQWcwMkdlMmoyUU5GVUlUaCtmZXhIV2VpUHF4ZzlrR0UrUEhBRlpJbzhNbEZzVmdrczN6djVvSUlVOFhRMEV5QThhVHA4T09jK2dDc0VGODh2R3FPRUdseGthQVpqZHNsL3A2bG9VNmlwemduTm5qbTFESWg0VlNobFBVeEVCZ240VVNqcHpnc2V0ZHRNVkl4NDBSZ0JtdGVhRldvUmdUbkJPZGFFcWIraHJqSmNaMVZsZ0VlSzIzalJUZ3VuN3pmQXkzWGd6b3BNSU5zc1l6K3p2QjFPQ1J5eTY2MElrRStEOWplRG5iQkNBblVIVUpiaG9jVlUzRzFPNWxCZ1JxRmpiMGhJMFBjeTBCcWVYNWZHVm94aVpZVkVNV2sraFM1SW1CY3BpU2pCOGZsSVlLSndmNjRKQTBFdU56QWltZTFTQk8veUZPbDA0L1VZcHZBRVExTWxsUm5CV3hmQlB2bEhEai9SQ0FKWVExYW5CMlpOSGZhR1hVMXh2RUFMcTFPRFVrbXdwU0EwLzBRVUJtSmNlSHFpWVdSTnR6UXE1bUJHb2l4OXJnMEJ5NENjdTdBak9TR0ltU3hzY0VsZkxGYTgzWGZHT0dTbFd1NDJaTE1VNEhzZUdnQTFqOWdTTGFiRGJNZytHUUVDV1JidGlpSmlhWldjeWR0M2MwYjZYWE1abGltQXp4cElrQi9WQXplZ0R0ZGxua2Z5dHFUajN3NTh6R2Q3VUVxK1ArRWpFSDBXWkZUd3oyQTNiNW5VcWR2cVpWaExpaVAxQzQ1REJpekpBQUo3QmZpNllFUXdUM1g2aERHemtJdUpBb05SbTgzUEJqR0NZQS9VTGpjTTJYalJlQkREdWViUzZHcjVOdXhYWUVZenhmeFdoUE5ZUkFVTCtFNmlkR2NFQ0llMkJndm14VGdoZ0ZNUURNNElSeHBwdFU2OFRkS1pRQ3ovcEU4UURNNEozdVZ5ZkFNbjhPYXp6YlFBYlVLdFVnOEV4akVqUTNhT3pyME5VdlVVOWdvSGlkNGNvcXNaeE8wa000b0JaRTkzbklVYkhqT1BwMExNRWhxcm45a3laOG1tZzUwd0poaW15TndPRjgyTnRFWUF0V1k3MzE4aVVZTnJSZ2w1YzBET2d2MEorcmg0Q0FoSFVKYmpQZEhMN1hhU2VTMXl5SHdINHhkT1UxS1EzL2VkZkh6Q3R3VlNtSUtERC9aWHdjL1VSZ09ldjkxZlYxZlRWNWFEQW5PQmNwL01vYUxnY3BJV2ZxSTRBSm5oL0tDWE1DVzdBV0Jhd2NEQ1VNcDZtRGdKUWU3dHQ2YW1IUWtsblRqQlZZa0Z5eUxzcGxBRThMWDRFb1BmOHB4MFRKMTRMSlVrVmduZlcxUHdUZXROQkErNVF5bmthR3dTd0lMdzRrQ1JWQ0tiS1lKL01iUU1wNWVuc0VJQ0tkR2FQdy9INlFCSlZJM2hXamVNUVJ2amZBeW5tNll3UXdPZzVJQmsrYUFnZFZDTjRDY1lTRWhDdnhhRnhaNUtLTWZwd3B0UDUwbURDVkNPWUtzM1B6dDRIMGFYQkRPRFg0a0pnVzE5RkdrU0VxZ1EzbEpmM1lDUnNHRVEvdnhRakF2VFptKzl5L1RaY2NWVUpwc29iM2M0RHNJellGTTRRZmowNkJBUUIxOE9jUTIrNFVxb1QzR2VBQmRmRFlEeXNNZUdNNWRjVkJQRHZkenVkRVZVYVRRaCszdWs4UXdTOFV6R1B4N0VqQUUzemRTSFp0aTVTQ1pvUVRJMHBTRTdlQkxYNFhLU0c4WHloRVlBZnExelpmMUUvZE01YnFZQzVkbUZsUzhzRStNRHJKSHdGa2FLZDFzVFJCUE1LdjJ0MHV4Nk94aVBOYWpBMWFwZkQwUVp6WEd1aU1aRG4vUm9Cak0rblphYlhSNHVIcGdSVDR4cHJhbjROZCtLZ2cvTm9uVWowL1BEY3ZTbGFoQ1cvckt5OEVhMnZtaE5NRFV3V2hlVXdkRG9ScmJGRE5MOEVRNklIYnJWKzBTT2dDOEhiSFk2YkthS3dnSGU2d2hNRzA1RjFNQ1I2TFh6TzBEbDBJWmlhQWlSZnRRbDRQbndOMFJIYU5KNktzTkJBSDJueElLRnBMenFVb2ZWZWI3a3NreU93SE1JM0VnOEVTTURibjNlNWZoYVlGTXV4YmpWWU1YYTN5M1VXdm5seFFrMytRRWtiNmpFMHk1dFprRXR4MUwwR0syVFduVHBWSUhmMy9BWGVGQml5djdjRXZXWFl0QjNWN1hHNTlpcTR4QnZyWG9NVkIranNUR1pLOGd3WVFnM056MTh3L2dxbWM1ZXdKSmRpYTVnYXJCRDlNaUdXNDk2V0JwZ1EyVWczdUZiU0V6bW1vd2tSV1JmdmRFOTduN1dmaGlOWWNiQ3V1WGtla2VVRHNEMXVycEtXaURFMHlmdlRNakpxWTVuRWlBUVB3eEpNallmZkh4aloxU3Y5Qm5yWTkwVGlqSm55QUxHZnczY2dqemZXT0Y5UTAyNURFNnc0WHV2eHdDOWQ0eDNRWkk5UTBzd2MwMXBMQkdFZExLTUdiWmlpaGsrbUlKZzYvZ1Rzb05vcG82Y0pJcXZnRkw1VU5WOEFzR0c1MUZMYjZIYThwWlgxcGlGWUFlU3gxdFp4UHA5dkF5Sm9HVFRkcHRnQUZZWS83YkM5eGJONUx0ZkJTRjZ6VVh4bEVadU9ZTVhwTlNkT2pPNzJTVTlDYjNzNUVKMmtwQnNyeG0zd3RlVXplVTduSVNCVzFzTTIweEtzZ0xXNnRUVy94eWM5aUpEOEVQMU5leVZkcnhnQS9STDZDNjhRQzk3WDZIQWNoOW9MOTU5K3dmUUVCMEszeXVPcDlHSDhFRUQ2ZmVpUUZRZGVVL200Q3lab21nakdCK3daOXNOcURYbGk4U0doQ0E0RUFIcmVZekFSWmhNc3o0TDNtR2JDRkdoKzRQVjRqZ0cwWHBnN1B3M1RSTWVBMUtNRkkwYTBOSlNVZE1ValU2MnlDVXR3ZjhEb1hMZlEzVjBLazcxM0VobVZRcnM1SGxyUFlSQ25RNDJuVytEVGZ6c1FSemZ5N0lUMFRnQ25FNXI5NjVEdklpTDRQRFM3ZFArUmRtdGUzcjkyamh2WERjZUdELzhIRXFvYVk3bzhWWm9BQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA4LTMwIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJQaXhlbFBpbiBpT1MiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlVBRjExMDAyMDE4MDUxMTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA4LTMwIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0wOC0zMCJ9LHsiYWFndWlkIjoiMzRmNTc2NmQtMTUzNi00YTI0LTkwMzMtMGUyOTRlNTEwZmIwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIzNGY1NzY2ZC0xNTM2LTRhMjQtOTAzMy0wZTI5NGU1MTBmYjAiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMgd2l0aCBORkMgUHJldmlldyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiYWxsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESHpDQ0FnZWdBd0lCQWdJSkFOcHFENTJUT1R1c01BMEdDU3FHU0liM0RRRUJDd1VBTUNZeEpEQWlCZ05WQkFNTUcxbDFZbWxqYnlCR1NVUlBJRkJ5WlhacFpYY2dRMEVnTWpBeU1EQWVGdzB5TURBNE16RXhPREUzTVRGYUZ3MHlNVEV5TXpFeE9ERTNNVEZhTUNZeEpEQWlCZ05WQkFNTUcxbDFZbWxqYnlCR1NVUlBJRkJ5WlhacFpYY2dRMEVnTWpBeU1EQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU9HQkx0Qm1VUEpRQUNRV1ZFZUJ4ZXpSZ1pkcUdNUDZlVHJQdHk4eXZNOXhBK2ovWDRnMmxSTk1GOWEwanczQmprV1Nzb1dKallUdXpldkdNZzJyYjlNNXFxZC9PRDQ5OE9BazZVRXRNeWJyMTYyQ08yd0I4U24ybnpmelVkYndaVDRkeGwyNTFsZlg1SnNaVlR5SmR1aGxKemJLR2V0TDNKTW1DQXBldFNPMHhjY0dTSVY5R1VvSm03OEtsUU82c21TREFrUkZ4SjhQZzhiRTQ0OXFpSXFQL0sxMHVSZXU2NlVDV2Rhb1hDS3FSZDVpa2JVKzZpZ0pGSFp6OTRVQlByc2dsY1kwRnEwM25yQkJ2cnBFekduaXNCLzQzRTlJdGpyOVVMVjRQUVFtaXVXTWNJUG1GUDFqVE5nS0tuWFpzeGUxMTRCL3pCM1V4aElCMjlyUm9wRUNBd0VBQWFOUU1FNHdIUVlEVlIwT0JCWUVGQUx2b3VLRFVuaGpHeFVSUitNMUsxbU1pQnQ3TUI4R0ExVWRJd1FZTUJhQUZBTHZvdUtEVW5oakd4VVJSK00xSzFtTWlCdDdNQXdHQTFVZEV3UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFFTzQ4QStjKzFFYWM3WllKdkJzM2pBNDBxVmhFS2VFeTJpK0ppQWZ3dUd6Y2ZNVWsvNG9DWjVWNVdETHpHaGFTY2JNTEVvVk1xeEhGVUZYSTFrVTlQTlZvbnlnd1kweFZzM21OcWxDSk0rTFoyUXR4R3FDckRHeE1QQWx1dnNGaHIxbU1hSGs3ZUN6a0pBaGhwdlVhRzlGMDdqbW81VTdIZkZ5UXIwd1F4U2lVZzVubWpYRmdrY3VpMnBNZk9lS0JkZEJ5N09jNnVoZUNSeVB6T0tkWWVrZ2JaUHJOWi8yT25oSnFRLzZTcTlLaHo2aDk5QW1VcE1ZVWl1YTBtekZvU25Ga3lFUkwwUzRoL2JiWmxTRWVDaUpDeEZFREJaQjRaZ09zT1JMMkRITGprVG5lUGdzOWJqVnAzbFZlbElwbHFpK0s2TytNbU1sWUZyT09ld2E1YTQ9IiwiTUlJREtqQ0NBaEtnQXdJQkFnSVVlZitWdkhrY1RRbkVEKyt3Sk0vSXh6U1VMazB3RFFZSktvWklodmNOQVFFTEJRQXdKakVrTUNJR0ExVUVBd3diV1hWaWFXTnZJREl3TWpNZ1JrbEVUeUJRY21WMmFXVjNJRU5CTUI0WERUSXpNRGt5TlRFeE16STBNVm9YRFRJME1USXpNVEV4TXpJME1Wb3dKakVrTUNJR0ExVUVBd3diV1hWaWFXTnZJREl3TWpNZ1JrbEVUeUJRY21WMmFXVjNJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvdUZNVE9LYUUwWXRleE9vaXNTeHArRWJpNUlBNGVzRVNjeDE2bHpRZHFWNi9lWjgyS3RKZU5YRXVOa0JWWkRwYzMyZ1N0dXhMQkg4bWdzb0hCRmFpMkRramZCbjVxYndSL2M1K3NubHdadmpnVkEwaHpLdzlDd0FlQXdSRDVrcld0ODgvQ1Z5Q2tNY2dMU0d3WnMvcmo3Ri9MczNFYmc3TXFMYmJRSjlDb3piYkxkSlVZSUhjUHBTWlB0b01yWmI0R3ZuaTZpVlM5VXZDS2dwcWM2TEdSbW9ZR0c0WlIzbEdKL1hRWmZ1K0dlSlc2N2lpbU1qL3lvWE93eHVjeGl2WkhGazZjUVNnd3V3aW9lTm00d3ZrODNMaFN1V2N0ZjJrQXlRY1o3a1VucE5lZStkNE1ncm1HVTRYTUZMaVRndXRhQitlOVY4ZDVKVGtVT0hpTHp0a1FJREFRQUJvMUF3VGpBZEJnTlZIUTRFRmdRVU01U0I1YkhyVitqcElPTWRKbDd1N2JjblRZOHdId1lEVlIwakJCZ3dGb0FVTTVTQjViSHJWK2pwSU9NZEpsN3U3YmNuVFk4d0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQ293UjNLVExmaWRKeVFGTnFFRmZVcmZaOWFhOWVncE9RdE5SSmRMU3RKNnh1MldmTHd2RzRvakdKbEJLTm5mYTVESWN5UVlmLzhxSjRlbGlBVmVOWHVZbWVNbWdOZ1paeXVZNkcxeVdDRDJWM3NENlo0dWozU2JhRE9IajNnSHZzemdRaHJoVDFoL3B1SFFrbjYraFlLQXA3N2tNN0ljNkFaL1JGYmpwbUxMazJEMHNFMWx6VC8wMmkrQmg3TThzbWFpRFo5KytKR3p4ZVN1bjhXMUhsZVpVbTJxS0dtUmE0WFBkcnlUN3g2S0dVR25VNGEzYnBVbVZlWTlyUS9zZk1kNVpUb28rM3VuRldEem9WVjJ2TnU4KytWTEM5em80MEZhS1FMcjlWQUpESjR5TEVOUjdLcm1WOEwwY0NYS0pHWldBV3RHNVJHVG1ISWhkK25CNDFnPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiJkODUyMmQ5ZjU3NWI0ODY2ODhhOWJhOTlmYTAyZjM1YiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImJpb0Vucm9sbCI6dHJ1ZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3Ijp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6ZmFsc2UsImFsd2F5c1V2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjEwMjQsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjg5NjQsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsInByZWZlcnJlZFBsYXRmb3JtVXZBdHRlbXB0cyI6MywidXZNb2RhbGl0eSI6MiwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjEwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA5LTE3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wOS0xNyJ9LHsiYWFndWlkIjoiODNjNDczMDktYWFiYi00MTA4LTg0NzAtOGJlODM4YjU3M2NiIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI4M2M0NzMwOS1hYWJiLTQxMDgtODQ3MC04YmU4MzhiNTczY2IiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgQmlvIFNlcmllcyAoRW50ZXJwcmlzZSBQcm9maWxlKSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg5NjUsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjUsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjUsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsImNyZWRCbG9iIiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjgzYzQ3MzA5YWFiYjQxMDg4NDcwOGJlODM4YjU3M2NiIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImVwIjpmYWxzZSwiYmlvRW5yb2xsIjpmYWxzZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3IjpmYWxzZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlLCJzZXRNaW5QSU5MZW5ndGgiOnRydWUsIm1ha2VDcmVkVXZOb3RScWQiOmZhbHNlLCJhbHdheXNVdiI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoxMDI0LCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjg5NjUsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjEsInByZWZlcnJlZFBsYXRmb3JtVXZBdHRlbXB0cyI6MywidXZNb2RhbGl0eSI6MiwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjI1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDYiLCJ1cmwiOiJ3d3cueXViaWNvLmNvbSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSBCaW8oRW50ZXJwcmlzZSBQcm9maWxlKSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwODA2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wOC0wNiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDgtMTYifSx7ImFhZ3VpZCI6ImJlNzI3MDM0LTU3NGEtZjc5OS01Yzc2LTA5MjllMDQzMDk3MyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiYmU3MjcwMzQtNTc0YS1mNzk5LTVjNzYtMDkyOWUwNDMwOTczIiwiZGVzY3JpcHRpb24iOiJDcmF5b25pYyBLZXlWYXVsdCBLMSAoVVNCLU5GQy1CTEUgRklETzIgQXV0aGVudGljYXRvcikiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMCwic2VsZkF0dGVzdGVkRkFSIjoxRS0wNSwibWF4VGVtcGxhdGVzIjo1LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjoxNX19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjFFLTA1LCJtYXhUZW1wbGF0ZXMiOjUsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjE1fX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwidGVlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIm5mYyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOlsiaGFyZHdhcmUiXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUI5RENDQVpzQ0ZGaVBrNXI2NHBnV2hBUWppaTA3bXZTRUYxL3VNQW9HQ0NxR1NNNDlCQU1DTUh3eEN6QUpCZ05WQkFZVEFrNU1NUkV3RHdZRFZRUUtEQWhEY21GNWIyNXBZekVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVWTUJNR0ExVUVBd3dNWTNKaGVXOXVhV011WTI5dE1SOHdIUVlKS29aSWh2Y05BUWtCRmhCcGJtWnZRR055WVhsdmJtbGpMbWx2TUNBWERUSXhNVEF4TVRFMU1EazBNRm9ZRHpJd056RXdPVEk1TVRVd09UUXdXakI4TVFzd0NRWURWUVFHRXdKT1RERVJNQThHQTFVRUNnd0lRM0poZVc5dWFXTXhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhGVEFUQmdOVkJBTU1ER055WVhsdmJtbGpMbU52YlRFZk1CMEdDU3FHU0liM0RRRUpBUllRYVc1bWIwQmpjbUY1YjI1cFl5NXBiekJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCRmlpSkhIaGlLQU1xRDQ0Y3JkZU9jOFZPWG40bWhTUXplVmRqYlh4aE5vbWJkemM0V2o2ODF4Rm00UFEzb3NoYXE4b0txaHhhaGRFdWJXdFM5QW1Eb293Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnWjZOMDNhQ21MSDRndWpBWm81TVprZXg2VnZOTlJCaFRXMFY3K1lZWXV4Z0NJQUc1cTBDUklGd1pvZnBQQU9QbEI1NUhDdkp5VmpoSTJMc0RyanU4OGRudCJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFYUUFBQUYwQ0FZQUFBQXpZOEpUQUFBQUNYQklXWE1BQUM0akFBQXVJd0Y0cFQ5MkFBQWY2a2xFUVZSNG5PM2RQM1lieDViSDhiYmVCSk81WndXR1Z5QjRCWUt5eVVTdHdOUUtUSzFBVkRnUjVSVlFYZ0dwYkRKU0t5QzFBa0RaWklDeW1ZaHpXcjR0TjBHUVFIZmRxcnAxNi9zNXA0N2s1MmNTM1FCK0tOejY5MU9EUTh5YnBta0gvNytaTkFEeDNEWk5zeG44OUpVMFBJSkEvMXNyb2QyMVh3WUJQcmZ3NEFBOGNDMWgvMlVROU5lMTM2WmFBMzBoN2JtRU5yMXR3SWRiYVo4bDRLdnEwZGNTNkhNSjhGZnlKNEE2OUQzM0x1QXZ0MG80N25nTzlDN0VmMithNW9nZU9BRFJoZnNuQ1hkM3ZYZHZnZDRGOTdFRU9TRU80Q21YRXU0ZnZkd2xMNEYrTk9pTkE4QVlHd24zOTZYMzJrc085Rlo2NDMvUUd3ZWc1RnFDdmNnWk15VUdlaGZrSnhMazdRSC9md0FZcTVzcDgyZHA1WmlTQXAwZ0I1QmFWNEo1VTBxUHZaUkE3MG9yWndRNWdFeUtLTVZZRC9SdXp2ZzVOWElBUm5RbG1MZFc1N00vTS9BWWR1bDY0aGROMDF3UjVnQU02YW9GU3luL212TXZnNC9wU0lLY2ZWUUFXUFR2VGRQOHAxUVF1cjFrL3NmS1k3UlVjbW1sdk1KY2NnQWw2VW93SHl3OFhpdUJmaVJoenFBbmdCSjFnNld2YzlmV0xkVFF6NlJlVHBnREtOVkNhdXRaS3d3NWUraHRJYlh5ZnBwU3Q5RGcyNDcvSFlDKzdmTUlmcEVKRWlXY1U5Qk5ienpOOFl0ekJmcGN3dHhTcjd6ZlIvbkw0Tyt1dDlvRUNqWWJIRXJ6WEhySWx2TGtVaFlrdWMrUWJ0clB1bW1hdTh4dE9SaUVwZHdEbEc4dTB3a3ZET1JMMTI2OFQ3cytNUkRpWjB5SkJLclFUN2JJMllGY2U4MmI4NHczOUp3UUI2cDJMR1ZlUWwxQmpqQmZ5cE5JT1FWQWI1YXgxMzdzNFZsSUhlWkxMemNPUURTdHpFUkpIZXhGWjFQS01DZklBWXlWSTlpTHpLbFVZYjRteUFFRWFoTjNRSXZhNGlUVmpXR1BkQUNhRmpMZE1FVkh0SWlCMHVNRU4yTXBOeDRBWWpoSlVJWXhIK29wd3B4ZU9ZQVVaZ2w2NjB1cmVUYVAvSW0ycGxjT0lJT3p5S0YrWSsxSmJlV1RKdVlGMHlzSGtNdFI1QTdydWFWbk51WUtMRk1YQ3FCYXNVc3dKbWJyblhxL1FBQVFiY1FPYlBaQjBnVmhEcUJDc2FabVp5c3Z4NnFidTkyZERJQXJzVUw5TE1kTmlySG5NR0VPb0NTeFFqM3BqTDRqd2h3QXZvc1I2c25tcDhjcXRSRG1BRW9WSTlTVGxGNWlUTEpuQUJSQTZXS0VldFRTeXp6Q0F6N2haUXpBZ1RiQ1BQV29xMGkxNTEreWFBaUFKMjJFRmFWUktoamFBNkVzNXdmZ2tYWWxZeDBqS3pVSFF0ZXlqQllBUERwUkR2VlR6WHVrdlMxdVVhZDFBTUFFbW10MVZIdnBtcjF6NnVZQWFxQmRUMWZwcFd2MnpzMXU1ZzRBRVdpT1BhcjAwalY3NXh4UUFhQTJtcVdYb0Y2Nlp1LzhncGN4Z0FwcGxsNkNldWxhODg2WjFRS2dacHF6WGliTlM5ZWNTNms2NVFZQUNxUlZ2bDVPdVhTdGZRbWlUSW9IZ01Kb0hnZzBhanhTcytiRHhsc0E4RGV0TXZhbzZkOWFnNkdUdmhvQWdGT2F2ZlNES3g5YTAyellTUkVBN3RQcXBSOVUvV2lWZmhtMWN3QjRTS3NDY3RCVWNLMWZ4c3dXQU5oTmE4Ykx2VTd6c3gyLzZwWFNFL0NSSnhJQWR2cEw2Ylk4dWRHaFZybUZWYUVBOExnb1didmRROWZhYStVVFR5UUFQR3JUTk0ybHd1MTVNck0xRG9CZTh4d0N3RjVhNDVVL1FqMUdEMTNqVXdjQXZOTWFaOXlaMjFvMUhVNGpBb0REYUt6NXVkcjFtN1EyWW1mdU9RQWNScXZzOHQydzVESlhlQUt1cGRnUEFEZ3NNelY4eis5aG9MOVErS0dmZVFJQjRHQ3JwbWx1Rlc3WGcwRFg2cUVEQU5MbTV2Tm1FT2d6cGRvM2dRNEE0M3hSdUYvM2V1Z2F4OE1SNWdBd25rWjIzZ3QwalhLTFJoMElBR3F6VXBoTThyM0M4bXo0RDRHKzhqSUVnRWswT3NTTFB0QTFacmpRUXdlQWFWVHljOWYydVZrZkVBQlU2SnZDSlM4MGErZ3NLQUtBYVZSNzZLRTE5SlhDWXdHQVdtbDBpSC9SS3JrUTZBQXduVWFHempScjZBQ0FhVlE2eGMrVTlrQ25odzRBbVduMTBKbUREZ0NaVVhJQkFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3Z2tBSEFDY0lkQUJ3NHQ5NElqRXc1WHpaMjZacE50eEVJRDhDdlM1ZFlNK2tQVythcGgzOHM0WnIrUmxkeUgrVGYxNXhpRGlRQm9IdTExd0MvTG44Zlo3Z1NoZGJmNzRiL0x0ckNmb3Y4dWR0UFU4RmtBYUI3a2NmNEs4bWxrNWlXMnc5cm8yRS9PZEIyQU1JUUtDWDdVZ0MvRWpLSnlWcDVYRWZ5V05lU2JCL2Fwcm1zdlluRnBpcTZ6WGRCYlpUN240eVhRQ2VOMDJ6Vm5qZUxMZUxwbW1PSzNsT2dVYmh2WGpWRU9oRjZNb3BaeFdFK0s2MmxnOHdpMlVrUUZOd29ETVAzYmF1aDNvajdhVEFzb3FHVnU1RDEvdFlWbndmZ0wwSWRIdGErY2JUOTB4VHpFNHB4VXkrcVN6bDNtaE50d1JjSU5EdG1BMXE0Ky9vaFQ2cDc3VVQ3TUFBZ1o1ZkgrUkxCZ0VuSWRnQlFhRG4wdzdLQndSNU9JSWQxU1BROHpnZERQQkJWeC9zcDVTdFVCc0NQYTBqQ1J0cTVQRzk0OXNQYWtPZ3B6R1RoVElYbEFPU2FxVUVjOFZzSWRTQVFJL3ZST2FSSCtWK0lCVmJ5SFBBQWppNFJxREhNNU9lNFJubEZUUGVTYkRUVzRkTEJIb2MvUXBQbHF2Yk14K3N2QVZjWWJkRlhYM05sdktLZldleVUrVnJUbHg2MGxPZGtnM2JIdHRDb091WkZ6am8yWjhtMUo4d05EeE83cW1qNVlhbkhMVnk3VC9MbjVvbklNVzJrSmt3THlzT3B1RXBWaThHLzlzVW5GaGxBTHN0aGpzdVlOZkNwWHpnbkNRcUJTM2t2cHhKaWNQNi9hbGhldU5NcnZNODhYT3lsdkdrMDBMMzdrOGw5RDZ6ZmE2Q2M4TWgxUWU0aFI1emY2QkZ2enJXNHYwNk4zQ2Z0Rm05NS8yc0l3YW8veEY2VHduMEFLM2NRRXR2a25WQk5melpZRXFucFh0NDVhQUhXZG9oS0V2NTBLazkzRFZldXdUNkJITmpRWFFsWDZWTERhS1pzVjdrVFlFTHdHYURMU1dzdkM2bnRIN2JoaG9YNEdua0FJRSswdHhJejJjdEllanRoWDlrNUp2UHVwQWU0MEpLYXlXRjlxSHRvcktwdjZIM2kwQWZ5VUtZMTNKcXo4ekErSVRsVUQ4dVpMQlpvOTFVTW1nZGVxOEk5QkdPTW9kNXJSdE41UTUyYTZGKzdLQ3N3bnRndDlEN1E2QWZLT2UweERYVFFyL0xHZXdXUW4xUlVZOThYL082Q2p2MHZoRG9COGdaNXV3RDg5QWlVNDA5VjZqUERNNm1zdEs4N1Y1S29FZVdxMmJPZHEvN0hXZDRibEtIK2ltaFhWWCthT1FHZ2Y2SUhHRytadE9vVWRvTU16eFNoUHFpNGpyNTFPWmhGODNRZTBDZ1B5SkhtRjl4K01Wa3FRZXNieUtXd2l5dlBDNmhsWnhGQkhvRWJZYkJKM3JsNFZLdjNMMVJmdnd6QmoxVm41c1NPMGVoMTAyZzc1QTZGS2lWNjBwWmQ5YmEreVhIZUlEM3RpNXdHMnNDWGRsWndoZjVCVE5Zb2xra0RNalFiMWVVV09LMmtySXA5RjRRNkFNcHB5Y3lyenkrbFB2dFRKa1RUWWtsWFRzdnBQTVVlazhJZEpGeUVMVEcxWjY1cEJnUFdVOEk5Tnlyam10c01RZXl0UkRvQ2xJTmdwYXkyWk5Ic2NvYVV3YmZVcGIxYUErZkw4dWhUcUFyU1BFR0k4enowdzcxczVGWFpISC8vQnJiMHZCN2tVQVBwSEh0aEhrNU5FSjl5dXlKbElPMHRITGZrd1I2Z0RiQm00d3d0eWNrMUtkTU0yWDV2czIyTmpoWFBmUmVYZFY4Nm4vc2phODJEazZUM3pmWWQ3M24zMXYwUmg3VDJNSHBqMDNUdkpYbjlSQnRoUWMwbEtSL2ZsNk9lRTdOcXpYUUY1Rm5tNVFVNWpQcGRYYnRoYnpReC9aQ2IrV2FQemROczVLZ1gwVjZ2QnJleUhVZkVyWWJDZktQSTM3dm91QjFCdjF6OTNYd2diM2E4M3oyOTNFdTEveGk4SGZMNWxLbWNCWHFOWlpjWW05OFpMbk0wc3FIMlhuays3Q1UzMkgxck5ORFpqZlZVR0s1a01WUk1WNnpzOEZyemZJWXdrV0VhNThpOURxcXJLSEhmc05abkdmZWgzak9zeWN2REliN1UrTW9ZeGVqNU5qNWNXbzd6N1FzZmk2bFRvdmhycldOUTRqUWE2Z3UwR2VSWDB6VzdzUE1ZTzlvTFkvSnlvRFVmTWZqRy91aFBDOWd1MXRyWjlGYU9ReDgySEozeGtJZmYzV0JIblBmREN0ZjJ4b2pCeXdmMHF3RSs4a2c5TWFXSGs0TTM5LytUVzU1WU5iU2F6WDNyRFNONTdxYVFJODU1M3hwcE9kVFNwQnZOd3ZCUHJiM2FyM0VVdHE1bXhaZXU3bDNQdzE5L0ZVRmVzeXZkN2tIUVZzbjg1MVBDNWtaWXJuRU1xVmtaRW11dzdBdGJPQVZlZzNWQkhyTTNubnV3eW04SFZlMk5ONnp0RnhpOFhTbytFbWlzUjlMSDRDaDExSk5vTWZxblY5bHZpN1BHejJOM1NzbHR0WndPV3ZLam84bGlMM0ZzTFVEWmtLdnA0cEFqOVU3ejdsMHVKYTl0SzBjSlpaeWIvV3g3YXFDZzFKaWxCTXRMdnpTZUMyNEQvUllBMWU1U2kyMWJmU1VlK2FCNWVQaHJIMkxpVWx6RDNtclovaUdYcGY3UUo5RmVpTnBIeEI4cUpTbktsbHJxZXVjbGtzc09lNkhCYUVIMFZqZU9yZFJlRTI0RC9SWWI4Z2M5Y3Fhdzd4dnFVTE1jb25GYTczOFVGTVBwQ2xoYjUzUTE0YnJRSSsxUFc2T0JVU2Njdk5QaXgzcWxrc3NiTWY4dDdHaGJyWEVzaTMwOWVFNjBHUDFhRk1QMHRFemY5aGloYnJsRWd0aGZ0OGhvVjdhUFF0OWpiZ085QmhmbVZOdjRFT1lQOTQwUTcyRVdVUHNxLzVRKzhRYWpCSm4vNFMrUnR3Ryt2YUdTMW90WmUvOHlHRUlXd3k1RWs3Z3IzRUE5RkM3QmtwTFBSSXo5SFhpTnRCajFKeFQ5czVEUi9OcmFhRnJBVW9ZbTZocGF1SlVmWWFWUG1CTW9EOGl4bEw0VkwzenFhUDR0YllwVTBoTFdaaVZleVZ5U2JwdldxVXZzQXArdlR3emNCSGE1aEhDOXpMaGtXcG5ESDRkckRzMjdQM0kvK2JJNEpMdlhicHJlMjN2WVpuVnZVZmRIQ00zbGNkQS96M0N6L3d6d3MvYzVZaDY2Y0c2YzB4L2t6ZnlvVTRMT3V2ekRRR0ZLYnlWWExUTExjdEVqenZXdkhtUGJXeGR1VFY0T3M1VHpjSnhhRWd2dU9UaTdkVC9HT1dXdjVSLzNtUGVWYkRKVXFpTjlGekg5TXBMTzRHL3U4YTNCaDRIQ3VTdDVCSmpoUHRqaEorNWJWN1FhclpjdWhMTHl3a2xsdExtSTcrbDFJS3B2UFhRWHlqL3ZOdEVnNkZNVFh2YXg1RkIxeDhQVjlvVXR0dEVIUWc0NVMzUWo1Ui9Yb3B5eTRKVmdJL3F5dzlqUXE2MEVzc1FwUllFOFZSeWlSR0tZNzdlVC9VdXdlOG9VVjlpR1JQbUp3VWYrSEF0RFpqTVV3OWRPOUJUbEZ2b25lODJwY1J5SHVFYldrcXBwc2JDTVUrQi9sejU1NlhvTGYyUjRIZVVaRXFKWlM0bEZndEgxVTIxU3ZSdEVNNTVLcmxvci96N3BQenp0czBLNzFGcVcwMHNzVmc1ZHpRRXZYT284TkpEYnlPOHFXUDMwQW56ZjF5T1hCbnBvY1F5eE13V3FQQVM2TnE5YzhvdDZYUWxsZzhqZnB1SEVzc1FlNUJBalpkQWp6RWdHbE9NRmEybFdjbm1VMlB1OWJIRFpmR3hTM3VvaUpjYStpL0tQKyt6OHMvYlZudTU1VkkyMWpvMHpQc1NpOGM5VGhnTWhSb3ZQWFR0M203czZZcXZJdjk4eTZhVVdNNmRiaWw4VGJrRm1xaWg3eGF6NU5KV3V0LzVSbWF4akMyeG5EbmV0SXh5QzFSNUtibG92dUZqRDRqV0dPYmRQZjExWW9uRjh3NlVzY2RxVUJrUGdhNDlJQnI3SzNCdEswUGZTOC84MFBzNmwrWDdOUnowd1ZKL3FQSzJPWmVHTDVGL3Z2YUtWcXY2STlUR2hKYjNFc3NRWVE1MUhnSmR1NFFSdTRkZVE4bmxXc0o4ekwwOHEyeFArRlJuMUtJaUhrb3UycjI1MkhWTjcvUFB4NVpZK2hQNGF6dmc0NnVCeHdCbktMbWs1YmwzUHVWNHVLTUtCajRmdzRBbzFIa0lkTzFGUmJHbkxIcDBLeVdXTVdXRTJrb3MyNWgvRG5VZVNpN2FKUXplYU9OOGtGV2ZoNFo1clNXV2JkVFFvWTZTUzFxZXBpeE9LYkUwY2c4K3NhaUdRSWMrQWgxVFRDbXg5TmdxRm9qRTB3RVhHaWkzN0RlMnhBSWdFWHJvOXpIejRIRlRqb2NEa0JBOWRCeHF4ZXBHd0RZQ0hZZWF5K3lVMnZkeUI4d2kwTk1xdmFUVHl2RnZad1llQzRBdEJQcDlzVmR5ZWhsMDlYTGFQdUFLZ1g1ZmpVdlFwNXBhZ3VuKy8rdW1hZTRxYjdWdG80d0VDUFMwdkEwcVRpbkJqRDFQMUNzNkQxQkhvS2ZuY2E1N1g0STVOS1JXRXVwanpoYjFwc2FUcXhDWmgwRFg3dW5GZnFONTdabDI5MjA1c3BUd2RzSys2VjdVY3RBSkV2SVE2TitVZjE3c3I4S2VTdzJ0SEI5M091Sy9xYlVFUXc4ZDZpaTVQQlI3NWtic0krNHNlQ2ZCUHFZRTg3S3lWYWd6NnVqUTVpSFF0UWNhWXdkNkxhc3RGeU5MTVAzdWpXOHFLc0V3MHdXcTZLRS9wSDFneHJaVlJSdGJUU25CZkpUZWVnMGxtQmNHSGdNY29ZZitVSXJGTXJYdGlmSk9wamNlV21LNHJhUUV3ellLVU9XbGg2NzVGVDNGMStBYUQzYzRrcW1OaHc0RzFsQ0NtYkhhRnBxOEJIcHBVeGN2SzUycU4rWDRPZThsR0hycFVFT2c3NVppU3RuWW85czhPWnRZZ3ZGNHovNHc4QmpnaEpkQS82cjg4MUlNVnYyVjRIZFlOcVVFODFvV0kza3lZMDQ2dE5CRDN5M0ZHK3lhWTl3bWxXQThIb0ZITHgwcXZBUzY5cXlSZWFMQnFqOFQvSTRTZENXWTg1RWxtTjhjbFdDT1dXUUVEWjdtb1d2MzBsUE1kdm5Jd2RRL0hNdWM5VnBMTUdPK3BRQTdlUXAwN1Y1NmlqcjZobDc2UFhNSjllTVIvNDJYRXN3ZjlOSVJ5bE9nZjFiK2VhbW1rMzJnbDM1UEsrV1hLU1dZa2hkc3RmVFNFWW9lK3VQYVJLSGVoZm43Qkwrbk5GTktNQzhMdjVmdldHaUVFSjRDZlJPaGp2NUsrZWM5NWdNbitPdzBwUVJ6S3NGZTZyY2VEdURHWk40MjU5SmVVcDl5RlorMytkVmFoaVdZUTNYZjFuNHR0QVJ6eE9wUlRPVXQwTFduc2JVamU0Y2hyaXMva20yZlk1bXpmbWhKb3VRU3pKanhBK0NlaGNMcDYyTzJSNDF0cVh5YS9GWEN4OTVHZVB6ZTJucENEM1loLzExSjkrSWkwbXNNZGdWbmxjZjkwTFY3Nll1RUExWDkzR284cnBXd0cxTnI3a3N3SlkxVEhDWDhkZ2duUEFaNmpEMVNVaTdOdnFXZWZwQVRLY0VjYWlOVEcwc3FhNTJ4end2RzhCam90eEVXbWFSZW12Mmhzdk0xcDVyUzQzNHIzNEpLbUFYVGp0eVZzbGJueHNxK1dYbXJvVGZ5ZUxScm1qbXU4WWFhK2FOdFRPOThsMWxCOS9lR1VIL1UyZUEralRtWTNLTFExOG4zOFQ2UGdUNkw4S1phWjNpeHRJUjY5SUE3TTNBOWg3U1VnL09sT0g3a2ZWcnE0ZHNxcnhHUGdkN0l4V20vcVhKY0o2Rit2OFhvclI0Vk1ndG16Rng4NzNhRmVlNzNhcWpRMTRmclFOLzNoRTlwT1hycERhSCtvOFVzUGN3THVjZk1VVC84dlYzYStFUG9hOE4xb0RlUjVuVG51dGJhUXoxRkhibGZsY3E5c0d0c2lXeFowRXloME5lRiswQ1BNVGk2enJpQlVpbUJvOTFTOTBxUEN5akJqRG0rejRQUTEzNEpPMW1HdmliY0Izb2I2WTJaZXhWZmpBOHFxeTNYYTZ1RUVzeVVWYk1sMHBxUlpMMEVFM3A5N2dPOWlSaCt1VWZTUzF6T1BqYXNjdC9qVXI0UmVkNmhVWHZBMm5JSkp2VGFxZ2owV0wzMHBZRlArMzdoaWZYQUdkdXM5YVFvd2FRWCs3VnRzUVFUZWsxVkJIb1RzWmR1cFdkMDVHUlRyNlhoRXNLOGtIdDg2bURBTk5VSHFMVVpRNkhYVTAyZ3grcWwzeGxheE5BV1hsc3ZJWWhLK1VhMExIUmpyMFdrOVNOUE5VdmZiRUt2cFpwQWJ5S0duWVhTeTlDc3NKa3c1d1VldTNaU3lMMHRKZGdYbVQ4bzEwYnVVK2gxVkJYb01YdnBGdmV1bmtsSnlHTHRkeTJQelZLUWozMHNwWlJnN2diQmJ1MGIwRkdHSHZsVExYY0pKdlR4VnhYb1RhVFZvMzJ6T3MrMUhaejJrL3NOYzJNMFdPYk50RGQwYVlQU2E3bkduR1hDbWVTRjFRL0RuR000b1krOXVrQnZJZ2ViOVZrR3M4RSs0cW5lSURmeU82MldWYlpQaVpwU1V5MmxCRE5zUy9tV2xDTEE1cElSMXVmMTU5NHJKL1R4Vnhub0d0ZjdXTXUxMThzVXJieVp6NVMvOWw0TmdxS0VlN0hyMnFmVVZPZUZyd3ZvbjdmandCNzhUUDc3VS9tWnBkeVQwTzJZTlFRL2h6OE5ScFpEdkM4czFNOGlsa2h1NVhEaUVnNVEyRGFUTmgrRThmTWR3ZHhkMjVmQjMvdERSYlFQRm9udGZFOXdmNVFETVE1OUx2c1NUS25idDI3YkRBNFI2WjdicjF2Ly91ZkJ0NWxaZ1lQYnZZMGNVWmo3UFhzWCtOOTNSeTFXMTBOdklnK1EzckYzZFJFT0xaTk1LY0hVdERWRDZXM050TVh5QTcyUmtrRE1GeU43VjlzMWRuQjhTZ25HKzlZTVhwcWxiMU1FZXFEWTg3VUpkWHRDWmpxTlhSbmNHcHVXUjd2ZnJNM1JKOUFEYmM5d0lOUjkwNWkyZWpPaFZrd0p4bDZ6dU9BcTlENVZIK2hONUZrdmZTUFU4OU5jZ3pCbDIxcEtNSGFhMWRXem9mZUlRQmNwZWxDRWVqNnhGcFNOTGNGbzdldE5tOTRzYjRWQW9DdEtVZXU4NGp6STVHS3VEcjZiV0lJWmU0d2FMYnhaMkY5L0h3SmRVWXA2K2wzbDUwR21sbXFUc2ltckxXTi8wTkQrYVphbUpqNkZRRmVXYXJWZktTK3dVcVdjWFJKU1NxT3VIcitWMUlFS3ZSOEUrZzRwZTA0bEhGeGJtcFM3SUdvc0lLT3VIcTlaTzhCaUg1WFhJNEgrVU1wcFp0WVByaTFKeXFQaXRIdCsxTlgxbXBYOXpjY0t2UWNFK2hOU0hoS3hkTFQvUnc2cHQ3R05WVExUUGhDNXhsYnkyYW9FZW1TcFQvNDVvN2MrV3VvUWpEMys0ZlhnNzFUdm41S0ZYaitCdmtlYm9iNUpiLzB3dVlJdjFWZDVldXVIdHhzbjc1blErMENnSHlCSHFOOUpXSlc2SFdsc0o1bkNMblZkdHFXMi9tUmJPOHVlMFB0Qm9COG9WNml2Q3prTlA1VkZ4cVBMY2c2eXpkbms2MEVyOFhEeGZVTHZDWUUrUXE1UXZ5UFlmeHpDa2lzOHJNeVl5SDBmTExRcngyczRDUFRFY29aNmpjRnVJY0FzVG4rck1kaXZLaGhiMHJoSEJQcEliWWJaTDl0dExiVlZyelgyWXlPTGJhelBaVjVVTUNQR1kybmxNYUgzaWtBUGtEdlUrM1pSNkNLS2JUUDVrTEl3czZPRWpaeUdMTjA3amJhVWdlL2FTb3loOTQ1QUQyVHA0SUsxZk1oTTJTZ3FsNW04Y1MwdGZTOTluNTBqZVIyVUZ1Nzk2N2ZtUFk1Qzd5R0JyaURsY3ZPeGI0NWpnNzJjdWJ4ZUxPNWY0bTBuVE92aHZwUnZGcXk3K0Z2by9TVFFsYVRjRUdwcVVKMUp3S2VzUjdieStqcVYwcERsWG1OcEd6bU5OWmR2UXptZmgrV2dvOEVhaTRkQzcrL1Z2MW03b2tMZE5rM3ptN3haTFBZMjVqdSt5bDdMNC80bWYyL2tuemNUZjM0NytQT0Z2R0ZMZWRPK2Jacm1nNEhIRWRPdHRQNDZaNFBYeGZQQmg2K0dqZnl1VmRNMFh3ZXZ0U212TFl6dzAyQUtWSWozOU5KLzZPN0RPeU9QSmNTK042Q0hyOG5kOWIwZWZLRGhiOFBuZHI3bm04dEsydmJmTWQ1ZDREMzcvanFtNUtJdjU0cEcyb0ZmVDFtQkMyT0NTeTdQZUVhanVKWVN6S1hEYXl2ZFJrb3NMeWtCd0JzQ1BaNys2L3hyZ3NPTVd3bHk3L1Z5VklwQWo2L3JwZi9hTk0xSDd4ZHFXTjhyLzAxQ0hYQ0pRRStqQzVRMzBqc2tVTks2bENDblZ3NzNDUFMwK3RyNlc4b3cwYTNrQS9RMU15OVFDd0k5anc5U2hxSFhxSzh2ci96S2RFVFVoa0RQWnhnODFOZkRiV1E5QkIrVXFCYUJudDlLNnVzRSt6VERJRCtsbElXYUVlaDJESVA5QThHMEYwRU9iQ0hRN1ZrTlNqRnZHZEI3NEZZKytQNkRJQWZ1STlEdDJnd0dUMTlXWG83WnlQWC9KbzNTRkxBRGdWNkc2MEd2OUUxRmM5a3ZCMldvbXE0Ym1JVHRjOHZTOTFRL3l2YW5SN0pWYlVtbkZPM1RoZmduK1pOeUNqQUNnVjZ1bFpSa1BnejJzbjRsZjVaMGVNQ3RmQVA1ekdabVFCZ0MzWWVOaEdFZmlETUo5dWV5bjdXbHZjdjd3dzQreTkvcGhRTktDSFNmVmpzR0R2dlRhV1lSVHFqWnBRL3JMNFBUYTZpQkF4RVI2UFc0ZlNKUSsyQnZKNTY2M2kreDN4RGFRRDRFT3BxdFBVK29Zd09GWXRvaUFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRXdRNkFEaEJvQU9BRTFxQi9qTXZDQURJNjVuU29iNVREaFlHQUNoNkppZTFBd0R5YVRWK3MxYkpSZVhCQUVDbE5Lb2NHNjFBcCtRQ0FIbDk2UVA5bWljQ0FMSlphUHhpeldtTEtnOElBRERKYlIvb0dqTmRaandIQURESkM0WGI5cU9HL2szaGh4SG9BRENOUm43KzZKaDM1Wks3d0hiRkV3a0FvN1VLK2R1MUh6VjBqYm5vekhRQmdQRTB4aCsvVDJ6UnJLRzNoRG9BakthUm02dG1hNWFMeHRSRlpyb0F3RGdhQTZKZm1xMUExK2lsYXp3d0FLaEZxOVFSZnBEZnh3cEYrVFV2UXdBNDJKSFdnR2dUb2VTaTlXa0RBRFY0cFhDTlAzcm53MEJmS2MxMjBYaUFBRkFEdFJrdXU1d3JkUDJYdkF3QllDK045VDkzVXJiWlNhT09ma2ZaQlFEMjB1aEEzejIxZmZsTTZSZWM4MXdDd0pQV0NsbTdkNFgramNJdldYUG9CUUE4U3FzYWNyTHZGcDhvL2FKam5rc0EyT2xLS1dmM2J1cWxWWFpoY0JRQUh0SWFETDA1OU41cWxGM3VuaHA5QllCS2FRMkc3aTIzOUxUS0xteXBDd0QvMEtxQUhGUnU2V24rVXFZd0FzRGZ0SHJub3p2TEY2bnJQQURnbUdaSGVmU2tFNjFOWXliOWNnQndSbXRteStSTkVKZEtEMkRKdkhRQUZkT2EyZEsxMDZtM1VXdHdOT2hCQUVEaHREckhkeUVIU3JkS3kxT0RId2dBRk9wVU1VT0R0MVhSZkRCTVl3UlFrN2xpZnFwMGlyVjc2UWRQaGdlQXdta3QwbFRwbmZjMGUrbDNTcWRjQTRCbDJybXBWckxXN3FYZk1Pc0ZnR09hczFwVWUrYzk3VThiOWt3SDRKRjJCMWkxZHo2a09mWG1qZ1ZIQUJ6U3JKdmZ4Wnp5cmJsNnRHL3M5UUxBQzYyOVd2b1cvYkFncmVXcnd3Zk1JQ21BMG1rdXhFeFd4WmhGcUE5eFpCMkFrbWtkS1Rkc3lkYnRhQStRM2pIekJVQ2hZb1Q1T3ZYS2V1M0NQNkVPb0RReHd2d3V4d0xNZVlUU0M2RU9vQlN4d2p6YkZpa3hCZ0g2VUdlZ0ZJQlZzY0k4ZWFsbG05YkpScnN1akZBSFlFMk1NY1MrWlQ5WXY0Mnc0R2dZNml3K0FtQ0Y5anp6WVR1emNwR3g2dWw5TTNPaEFLbzBpelFScEcvbXpsNk9WVlBxMnhXRHBRQXlXRVR1c0pwZGgzTVdPZFRYRm1wTUFLcVJJdE5NanhYR3JESDE3WnplT29DSTVwRkxMSDByWW93d3hZMmd0dzVBVzV1Z1YxNVVtRGR5VTFLRStwM1Uxamw4R2tDbzQ0Z3o5clpidEMxeFkwa1o2bmRTaGlIWUFZeTFpTENMN0w2c0tsTHFVTCtUcjBzRU80QjlVZ2Q1MFdIZXl4SHE5TmdCUE9ZNFE1QzdDUE5lcmxDL2t5ZU8xYVpBM1daU3QwNVZJOTl1eGRYTTkya2o3dnR5U0Z2TEp5UXpZNEE2dE5LWnk1azdkOTQ3bENubXFlOXJmYmdmTTU4ZGNHVXV1OERtS0tsc3QycW1Wc2ZlSm1Cc3U1SEIxR04yZUFTSzBjckE1b24wd21NdXp4L2Jsam15NUtlTXo5eENuZ1NyUGVUYnBtazJUZE44bG4rK0h2eTdqZng3QUhHMFc0RTRrL2F6L084enc1TWV1cXg0TFRtUlZNNUFiK1FKdWFCWERNQ0pEMDNUdk0xMUtjOHkzOE5WMHpTL3lVMEFnRkp0cEZlZUxjd2JBejMwb1FWenh3RVVLRnVKWlZ2dUh2clF0ZlRXUDlwNVNBRHdxSTMweUY5YUNQUEdXQTk5aU40NkFNc3VKY3hYbGg3anZ3dzhobDI2bS9SWDB6VC9KK0VPQUJhc3BMenlYMVo2NVVOV0E3M3p2MUtHK1d2SEZDWUFTR2tqSWY3YVdxOTh5SEtnOTdvYitVbm1nMXVlZXdyQXB3OFM1UDl0L2VxczF0Q2YwcFZnM2xHS0FSQlpOMEhqdmVVZStiWVNBNzNYQmZvZmJMWUZRRkZYRWZoVGV1WG1hdVQ3bEJ6b3Zaa0VPeHR0QVpocUpiM3h5eEtEdk9jaDBJZTZVUCtkY2d5QUEyd2t3UC9hMnF1cFdONEN2VGVUVXN6dnpJNEJzT1ZTSmxxNFc4VG9OZENIK25CL1FiMGRxTkpLZXVDZkpNemRxaUhRdHkya3ZaRGVPM1Yzd0pjK3dEL0xuOFhNVWdsVlk2QnZtMG13enlYa1djUUVsS01QN0sveTk5dVNCelZERWVpUEd3Yjdkay8rT1QxN0lMb3VuTDhOZnNscTBOdDJNWWlwcW1tYS93ZmQ5U3R4UXNiclF3QUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImJlNzI3MDM0NTc0YWY3OTk1Yzc2MDkyOWUwNDMwOTczIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjc2MDksInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjI0LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjc2MDAsInRyYW5zcG9ydHMiOlsidXNiIiwibmZjIiwiYmxlIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJmaXJtd2FyZVZlcnNpb24iOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMi0wMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQ3JheW9uaWMgS2V5VmF1bHQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMTExMDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTItMDIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIyLTAzLTA4In0seyJhYWlkIjoiNGU0ZSM0MDA2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiNGU0ZSM0MDA2IiwiZGVzY3JpcHRpb24iOiJBbmRyb2lkIFBJTiIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyNTYsInByb3RvY29sRmFtaWx5IjoidWFmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MTAsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwidGVlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRWdBQUFCSUNBWUFBQUJWN2JOSEFBQUFDWEJJV1hNQUFBc1NBQUFMRWdIUzNYNzhBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQUVaMEZOUVFBQXNZNTgrMUdUQUFBQUlHTklVazBBQUhvbEFBQ0Fnd0FBK2Y4QUFJRHBBQUIxTUFBQTZtQUFBRHFZQUFBWGI1SmZ4VVlBQUFuK1NVUkJWSGphN0p4dmJGUDFHc2MvcDZkcjE2NFZ4MnhwdHhHWVlCdkZHNGphT08yY1d4UUNPSUlKbWZlRitnS05ST1VGMFVUdkZZbnh6NGd4YWpBR0hWN0NRalI3bzFFVFEveURpWkdNRi9KaW05MldzRG5IWGJOdUREUHB5a2IvMGZhNUwyVG5NdmFITXpncWhYNlRrenpuZDU2YzlEeDkvdjJlNS9mN0tVekhVbUFic0JHbzR2ckNmNEd2Z2Y4QVE3TXgvQk1ZQmVRNnYwYlB5MklhR29Gc1FUamFsVDB2RXhTZ0VnZ0JpeW5nUXB3R1ZxdkF2NEYxQlhuTWdBMUlLVUFYOEkrQ1BHWkZ0M0plbFVvTHNwZ1ZVVk5CQnZPaklLQkxRQVgrZGQ0aFhSRktTa3J3K1h5azAybFVWZVdXVzI0aG04MGlJdmg4UGpLWkRMbGNEci9mVHk2WDAraHNOa3NtazhIdjl3T1F5V1R3K1h5b3FrbzZuY2J2OTJNeW1VZ21rL2o5Zm9xS2lrZ21reHBQSXBIQTcvZGpzVmlJeCtNYVBURXhZWVI4a29ZSnFMNituaDkvL0pIKy9uNGNEZ2R0YlcyY09uV0tWQ3JGc1dQSEdCNGVKaGFMMGRIUndjVEVCR05qWTdTM3QvUDc3NzhUaVVUbzd1NG1uVTR6TWpKQ1oyY25WcXVWbnA0ZWVucDZVRldWOXZaMit2cjZLQ3NyNDZlZmZ1TDQ4ZU00SEE2T0hEbkN3TUFBSG8rSG8wZVAwdHZiUzNsNU9WOSsrYVVoQWpMTXhMTFpMRmFyRlJFaGs4bGd0Vm9CU0tmVDJuZzZuYWE0dUZnYm42S1R5U1RGeGNXWVRDWlNxWlJHWHppZVNDU3cyV3lZeldhU3lhUkd4K054alo3aUtTb3FNc3pFekVhOFJGRVUxcXhaQThDcVZhdTQ2YWFiQVBENWZLUlNLUUJ1dmZWVzR2RTRBQ3RYcmlRWURHbzg5OTkvUHdCVlZWWFUxTlQ4TVNsY3VwUzZ1am9BbGkxYnhnTVBQQUNBMSt1bHZyNGVnSXFLQ3RhdVhRdUF4K1BSZU54dU56VTFOWmhNLy8vL1RTWVRQVDA5akkyTlhWYkdlTmxwdWRsc2xvOC8vbGp5QVZ1MmJGbm85NTIrSWcweW04MGNQSGlRUng5OXRCRG1aNFEvVmMwNzRZaklYeU9nb3FLaWExNXpya2hBemMzTlBQYllZM24zc1ZOQllrRUJTTzljN1Bubm4yZlpzbVdZeldhMmJkdUcyV3pPT3dFZE9uU0kvdjUrRkVYaHZmZmVJeHdPWDNJdXBqdUs5ZlgxeWJXRW1wb2FYVkZNdHdaVlZGUmdzVmh3T0J4ODk5MTNlTDNldk5PZ1o1OTlsbSsvL1JhQWtaRVJMVWViVDROMDIwbGpZeU5MbHk3VmhKU1BXTDkrUFZWVlZhaXF5dnZ2djYvSHhQUW5pajA5UGRlVWlkMTc3NzI2VEV5M2dGd3VsM2k5WHZINWZESThQSnlYUW5ueXlTZkY3WGFMMStzVmk4VmliQ2I5OE1NUDQvVjZzVnF0bEpTVTVLV0pyVjI3bHNyS1NrU0VscFlXSXBHSWNTYjJ5eSsvRktMWWZLaXFxc0ptczFGU1VzSlhYMzJGeCtQSk93M2FzV01IaHc4ZlJsRVVCZ2NIU1NRU3hrV3hEUnMyVUZsWlNWRlJFWGE3UFM5TnJMYTJGcmZiamFJbzdOdTNqNkdoSWVOTXJKQW9YZ0pURHRyaGNIRDQ4T0VaaWVMQXdBQ2Zmdm9wbzZPaktJcnl0ODNXN1hZN3dXQ1Fob2FHR2MrZmVlWVp2dm5tR3hSRjRlVEprOFltaWc4KytDQkxsaXlodUxnWW0yMTZDVHNjRGxOWFY2YzdLdndWYUc1dTV1bW5uNTQyZHM4OTkyamwyZGJXVmtaR1J2NmFLUGJoaHg5ZWRRc1E3cjc3YmtOTVRMY0diZHk0RWJ2ZFRrbEpDVjk4OGNXMEtIYjI3Tm04Y05MUFBmY2MzMy8vUFNhVGlZR0JBV1ByUWJXMXRUUTBOTEIrL2ZvWkpuWmhjUnpBNlhTeWYvOStuRTdubk8vVHd3UHd5aXV2OE5CRER5MllaelkvR0FnRTJMeDVNNXMyYmFLMFZIKzNYWmVKRFEwTnphbXU3Nzc3cnNhM1o4OGVhV2xwa1V3bUl5MHRMYkpuejU0Wjc5TEQwOWpZS0FjT0hKQklKQ0kvL1BDRHRMYTJ5b29WSzNUelZGZFh6MnRpdGJXMXVreE10d1kxTkRRUURBWlp0MjRkdi8zMjI5eHVQeHBsNjlhdHFLcksxcTFiaVVhamw4VVRpVVRZdkhrekZSVVYxTmZYczN6NWNtS3gyQ1Y1eHNmSDUveHRPM2Z1SkJnTUVnd0c2ZXpzTkxZdjV2UDVjTHZkRkJjWHo5dVlLeXNyQXlDWHkyRXltYlQ3aGZJNG5VNnQrUWhRV2xvNjdYNHVucWxtNUZ5emdXZzBpcXFxREF3TTZHcFA2eGJRbTIrK3lZb1ZLeTdKTnp3OHpPdXZ2ODdPblR0cGFtcWExWUhyNFZFVWhiZmVlb3Nubm5pQ24zLyttZDdlM2htK1RnL1BoWGpxcWFjME9oUUtjZXJVS2VOODBLcFZxeVFRQ0VoZFhaMk1qbzdPNllNQXNkbHMwdFRVSkZhcmRjNzM2ZUVCWlB2MjdYTGZmZmN0bUdjMkgvVGlpeS9LSFhmY0lZRkFRQndPaDdGaGZzMmFOWnFKWGF6cUYvZWJFb2tFdTNidG12ZDllbmdBUHZqZ0EwTjQ0SS8yZHlxVlFsVlZJcEVJazVPVHhtblE0T0RnbkJIaG5YZmV1ZW9TeFR2dnZIUGVLSFlwclZ5d0JqVTJOckpvMFNKc05oc0hEaHpBNVhKcHo2cXJxNis2cERBUUNNd1llL1hWVjJscmEwTlJGTHE2dW95Tll1WGw1YmhjTHF4V0s2cXFUbnNXREFZNWVQQWd6YzNOZW1vc2Z6cXFxNnZadlh2M2pIRzMyODN5NWNzQmRBdklFQlBMUitoTkZIV1hPMWF2WG8zRDRhQ2twSVJQUHZrRXQ5dWRkd1d6bDE5K21TTkhqbWdhcENNUDBsL3VLQ3NybzdTMEZKdk5Oc1BFOGdVMzNuZ2pMcGNMVlZVNWZ2eTRzU1oyNHNTSmE4ckVESTlpanovK3VCYkY5dTNicHkyenl5ZnMzcjJidHJZMlZGV2x1N3ZiMkNqbWNEZzBBZjFkSmRVcmhkMXVaL0hpUC9ic0xHUjFpaTRUQzRmRDEyVVUweTNHUng1NVJOT2cvZnYzVDBzVTh3V3Z2ZllhUjQ4ZVJWRVVRcUdRc1NabXNWaXdXcTFZcmRhOE5UR0x4WUxGWWtGVjFYbG4vWVVvOW1kRXNSMDdkckI0OFdMc2RqdE5UVTJhczhzbjdOMjdsMlBIam1FMm0rbnQ3VFZXZzZZdVJWSHlkdHF4WWNPR0JTOGtYL0FxVjZmVHVTRDd2WnB3Y1RmRzBMYlA5UXJUNVVhRHZQell5OUQ4QlM5Mnp1VnloTU5oYllQY1ZNblZaclBoY3JrNGZmbzAyV3dXbDh2RitQZzRxVlNLSlV1V0VJMUdTYVZTZUR3ZVlyRVlpVVFDajhmRCtQZzRpVVFDcjlmTG1UTm5pTWZqZUR3ZUppY25tWmlZd092MU1qRXh3Wmt6WjZpb3FPRHMyYlBFWWpIS3k4dVpuSnhrZkh5Y3lzcEs0dkU0MFdpVWlvb0s0dkU0WTJOajA5SVJrOGwwMlIzZ0JUdHBoOE1oTjl4d2czWTVuVTdac21XTGlJaHMzNzVkTm0zYUpDSWlMNzMwa3RUWDE0dUl5QXN2dkNDQlFFQkVSTjU0NHcydHFMNXIxeTY1L2ZiYlJVVGs3YmZmbHJ2dXVrdEVSRDc2NkNPNTdiYmJSRVJrNzk2OVVsVlZKU0lpcmEydHNuTGxTaEVSYVdscEVZL0hJeUlpbjMzMm1keDg4ODBpSXZMNTU1K0wwK21jOWhzWExWb2taclA1ejkvdEl5S3pGcnVubHZrbmswbnRuenAzN3B6R20wcWx0UHJMdVhQbnB0RlREY0ZNSnFPTlo3TlpiVHlieldvTlFSSFJ4bk81bk5aMHZIQWNNR3BMcG5GT09oYUwwZDNkemRqWUdKT1RrM1IzZDNQeTVFbmk4VGhkWFYzYTlzeXVyaTZHaDRkSnBWS0VRaUZHUmtiSVpyT0VRaUdHaG9aSXA5T0VRaUVHQndmSlpyTjBkbllTRG9jUkVUbzZPdmoxMTEvSjVYSjBkSFJ3NHNRSlRDWVQ3ZTN0OVBmM2F6eDlmWDJHK1MxRDk4MmJUQ2JOTDEwSnJTaUsxa3JTUTEvY1RMeWNiVTl6VlJRTkRmTlRIM2lsOUlVZnFJZSsyQVg4N1dHK2tBY1ZNRTFBa1lJWTVrVEVCQndxeUdGT0hDb2NzRFIvQXIxNjZxWndSTmNjUjNSZGlNSWhiN01jOG5aeGNibHdUT0JGeHdUK2J3QzRFNDJMNlpDYmVnQUFBQUJKUlU1RXJrSmdnZz09Iiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJmaWRvLnVhZi5hbmRyb2lkLmtleV9hdHRlc3RhdGlvbiIsImRhdGEiOiJ7XCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXNcIjpbXCJNSUlDaXpDQ0FqS2dBd0lCQWdJSkFLSUZudEVPUTF0WE1Bb0dDQ3FHU000OUJBTUNNSUdZTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNBd0tRMkZzYVdadmNtNXBZVEVXTUJRR0ExVUVCd3dOVFc5MWJuUmhhVzRnVm1sbGR6RVZNQk1HQTFVRUNnd01SMjl2WjJ4bExDQkpibU11TVJBd0RnWURWUVFMREFkQmJtUnliMmxrTVRNd01RWURWUVFERENwQmJtUnliMmxrSUV0bGVYTjBiM0psSUZOdlpuUjNZWEpsSUVGMGRHVnpkR0YwYVc5dUlGSnZiM1F3SGhjTk1UWXdNVEV4TURBME16VXdXaGNOTXpZd01UQTJNREEwTXpVd1dqQ0JtREVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnTUNrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY01EVTF2ZFc1MFlXbHVJRlpwWlhjeEZUQVRCZ05WQkFvTURFZHZiMmRzWlN3Z1NXNWpMakVRTUE0R0ExVUVDd3dIUVc1a2NtOXBaREV6TURFR0ExVUVBd3dxUVc1a2NtOXBaQ0JMWlhsemRHOXlaU0JUYjJaMGQyRnlaU0JCZEhSbGMzUmhkR2x2YmlCU2IyOTBNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUU3bDFleCtIQTIyMERwbjdtdGh2c1RXcGRhbWd1RC85L1NRNTlkeDlFSW0yOXNhLzZGc3ZIcmNWMzBsYWNxcmV3TFZRQlhUNURLeXFPMTA3c1NIVkJwS05qTUdFd0hRWURWUjBPQkJZRUZNaXQ2WGRNUmNPanp3MFdFT1I1UXpvaFdqRFBNQjhHQTFVZEl3UVlNQmFBRk1pdDZYZE1SY09qencwV0VPUjVRem9oV2pEUE1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0tFTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSURVaG8rK0xORVllbk5WZzh4MVlpU0JxM0tObFFmWU5uczZLR1l4bVNHQjdBaUJOQy9OUjJUQjhmVnZhTlRRZHFFY2JZNldGWlR5dFR5U241MDJ2UVgzeHZ3PT1cIixcIk1JSUZZRENDQTBpZ0F3SUJBZ0lKQU9qNkdXTVUwdm9ZTUEwR0NTcUdTSWIzRFFFQkN3VUFNQnN4R1RBWEJnTlZCQVVURUdZNU1qQXdPV1U0TlROaU5tSXdORFV3SGhjTk1UWXdOVEkyTVRZeU9EVXlXaGNOTWpZd05USTBNVFl5T0RVeVdqQWJNUmt3RndZRFZRUUZFeEJtT1RJd01EbGxPRFV6WWpaaU1EUTFNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQXI3YkhnaXV4cHdIc0s3UXVpOHhVRm1Pcjc1Z3ZNc2QvZFRFRERKZFNTeHRmNkFuN3h5cXBSUjkwUEwyYWJ4TTFkRXFsWG5mMnRxdzFOZTRYd2w1amxSZmRuSkxtTjBwVHkvNGxqNC83dHYwU2szaWlLa3lwbkVVdFI2V2ZNZ0gwUVpmS0hNMStkaSt5OVRGUnR2NnkvLzByYitUK1c4YTluc05ML2dnam5hcjg2NDYxcU8wck9zMmNYanAza09HMUZFSjVNVm1GbUJHdG5yS3BhNzNYcFh5VHFSeEIvTTBuMW4vVzluR3FDNEZTWWEwNFQ2TjVSSVpHQk4yejJNVDVJS0diRmxiQzhVclcwRHhXN0FZSW1RUWNIdEdsL20wMFFMVld1dEhRb1ZKWW5GUGxYVGNIWXZBU0x1K1JoaHNiRG14TWdKSjBtY0RwdnNDNFBqdkIrVHh5d0VsZ1M3MHZFMFhtTEQrT0p0dnNCc2xIWnZQQktDT2RUME1TK3RnU09JZmdhK3oxWjFnNytEVmFnZjdxdXZtYWc4amZQaW95S3Z4bksvRWdzVFVWaTJnaHpxOHdtMjd1ZC9tSU03QVkycUVPUlI4R28zVFZCNEh6V1FncFpydDNpNU1JbENhWTUwNEx6U1JpaWdIQ3pBUGxId3MrVzByQjVOK2VyNS8ycEpLbmZCU0RpQ2lGQVZ0Q0xPWjdnTGlNbTBqaE8yQjZ0VVhISS8rTVJQankwMmk1OWxJTk1SUmV2NTZHS3RjZDlxTy8wa1VKV2RaVGRBMlhvUzgyaXhQdlp0WFFwVXB1TDEyYWIrOUVhREs4WjRSSEpZWWZDVDNRNXZOQVhhaVdRKzhQVFdtMlFnQlIvYmt3U1djK05wVUZnTlBOOVB2UWk4V0VnNVVtQUdNQ0F3RUFBYU9CcGpDQm96QWRCZ05WSFE0RUZnUVVObUhoQUh5SUJRbFJpMFJzUi84YVRNbnFUeEl3SHdZRFZSMGpCQmd3Rm9BVU5tSGhBSHlJQlFsUmkwUnNSLzhhVE1ucVR4SXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQVlZd1FBWURWUjBmQkRrd056QTFvRE9nTVlZdmFIUjBjSE02THk5aGJtUnliMmxrTG1kdmIyZHNaV0Z3YVhNdVkyOXRMMkYwZEdWemRHRjBhVzl1TDJOeWJDOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnSUJBQ0RJdzQxTDNLbFhHMGFNaVMvL2NxckcrRVNoSFVHbzhITnN3MzBXMWtKdGpuNlVCd1JNNmpubWl3ZkJQYjhWQTkxY2hiMnZzc0F0WDJ6YlR2cUJKOStMQlBHQ2R3L0U1M1JiZjg2cWh4S2FpQUhPanB2QXk1WTNtMDBtcUMwdy9ad3ZqdTF0d2I0dmhMYUo1TmtVSllzVVM3cm1KS0hIQm5FVExpOEdGcWlFc3FUV3BHLzZpYllDdjdyWURCSkRjUjlXNjJCVzlqZklvQlFjeFVDVUpvdU1QSDI1bExOY0RjMXNzcXZDMnY3aVVnSTlMZW9NMXNOb3ZxUG1RVWlHOXJIbGkxdlh4ekN5YU1UandmdGtKTGtmNjcyNERGaHVLdWcyaklUVjBRa1h2YUpXRjRuVWFIT1ROQTR1SlU5V0R2WkxJMWo4M0ErL3huQUpVdWNJdi96R0oxQU1IMmJvSHFGOENZMTZMcHNZZ0J0NnRLeHhXSDAwWGN5RENkVzJLbEJDZXFiUVBjc0ZtV3lXdWd4ZGNla2hZc0FXeW9TZjgxOE5Vc1pkQldCYVIvT3VrWHJOTGZrUTc5SXlab2haYnZhYk8vWCtNVlQzcnJpQW9LYzhvRTJVd3M2REYrNjBQVjcvV0lQak52WHlTZHFzcEltU043OG1mbHhEcXdMcVJCWWtBM0k3NXFwcExHRzlycDdVQ2RSanhNbDhaREJsZCs3eXZIVmd0MWNWekp4OXhueUdDQzIzVWFpY01EU1hZckI0STRXSFhQR2p4aFp1Q3VQQkxUZE9MVThZUnZNWWRFdlllYldITXB2d0dDRjZiQXgzSkJwSWVPUTF3REI1eTBVU2ljVjNZZ1lHbWkrTlpmaEE0VVJTaDc3WWQ2dXVKT0pFTlJhTlZUemtcIl19IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dfSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMDUtMTkifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTA1LTE5In0seyJhYWd1aWQiOiJjYTg3Y2I3MC00YzFiLTQ1NzktYThlOC00ZWZkZDdjMDA3ZTAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImNhODdjYjcwLTRjMWItNDU3OS1hOGU4LTRlZmRkN2MwMDdlMCIsImRlc2NyaXB0aW9uIjoiRklETyBBbGxpYW5jZSBUcnVVIFNhbXBsZSBGSURPMiBBdXRoZW50aWNhdG9yIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsicnUtUlUiOiLQn9GA0LjQvNC10YAgVHJ1VSBGSURPMiDQsNGD0YLQtdC90YLQuNGE0LjQutCw0YLQvtGA0LAg0L7RgiBGSURPIEFsbGlhbmNlIiwiemgtQ04iOiJGSURPIFRydVUgQWxsaWFuY2VGSURPMiIsImZyLUZSIjoiRXhlbXBsZSBUcnVVIEZJRE8yIGF1dGhlbnRpY2F0b3IgZGUgRklETyBBbGxpYW5jZSJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMCwic2VsZkF0dGVzdGVkRkFSIjoyRS0wNiwibWF4VGVtcGxhdGVzIjo1LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDU3pDQ0FmS2dBd0lCQWdJVVczWEs4eXl3YkFXbGlnbGl4SUY2M2R2cVl5OHdDZ1lJS29aSXpqMEVBd0l3ZkRFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRU52Ykc5eVlXUnZNUTh3RFFZRFZRUUhEQVpFWlc1MlpYSXhFekFSQmdOVkJBb01DbFJ5ZFZVc0lFbHVZeTR4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4RURBT0JnTlZCQU1NQjNSeWRYVXVZV2t3SUJjTk1qTXhNVEF6TWpBek5qVXhXaGdQTWpBMU16RXdNall5TURNMk5URmFNSHd4Q3pBSkJnTlZCQVlUQWxWVE1SRXdEd1lEVlFRSURBaERiMnh2Y21Ga2J6RVBNQTBHQTFVRUJ3d0dSR1Z1ZG1WeU1STXdFUVlEVlFRS0RBcFVjblZWTENCSmJtTXVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUkF3RGdZRFZRUUREQWQwY25WMUxtRnBNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVOQXZidGNjTXI3ai9TUldtcUlFWlRSV05KeWo2bXNZcjVsR2VBZ2RTR3lDOU8wMzU2UkllY3VhVmlPcXowRHhnUzFmLzVLUGJacDF0MHlEMmZWUlg5Nk5RTUU0d0hRWURWUjBPQkJZRUZBNXRMMTBnODh0MnFYbFBsaElTSTJkSXpsYVZNQjhHQTFVZEl3UVlNQmFBRkE1dEwxMGc4OHQycVhsUGxoSVNJMmRJemxhVk1Bd0dBMVVkRXdFQi93UUNNQUF3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnWGZ1dmpzcCs0djVpR09xbmdVZ09nMWhtYmdGUEZNZ0lqeVd4Q0txdy9kOENJRmltTE5YTERJd0Erb0liUDF5T2ZxRTh4azZxNy80TFdPVllrUkFMb0JDMiIsIk1JSURYekNDQWtlZ0F3SUJBZ0lMQkFBQUFBQUJJVmhUQ0tJd0RRWUpLb1pJaHZjTkFRRUxCUUF3VERFZ01CNEdBMVVFQ3hNWFIyeHZZbUZzVTJsbmJpQlNiMjkwSUVOQklDMGdVak14RXpBUkJnTlZCQW9UQ2tkc2IySmhiRk5wWjI0eEV6QVJCZ05WQkFNVENrZHNiMkpoYkZOcFoyNHdIaGNOTURrd016RTRNVEF3TURBd1doY05Namt3TXpFNE1UQXdNREF3V2pCTU1TQXdIZ1lEVlFRTEV4ZEhiRzlpWVd4VGFXZHVJRkp2YjNRZ1EwRWdMU0JTTXpFVE1CRUdBMVVFQ2hNS1IyeHZZbUZzVTJsbmJqRVRNQkVHQTFVRUF4TUtSMnh2WW1Gc1UybG5iakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNd2xkcEI1Qm5naUZ2WEFnN2FFeWlpZS9RVjJFY1d0aUhMOFJnSkR4N0tLblFSZkpNc3VTK0ZnZ2tiaFVxc01nVWR3Yk4xazBldjFMS01QZ2owTUs2NlgxN1lVaGhCNXV6c1RnSGVNQ09GSjBtcGlMeDllK3BabzM0a25sVGlmQnRjK3ljc21XUTF6M3JESTZTWU9neFhHNzF1TDBnUmd5a21tS1BacE8vYkx5Q2lSNVoyS1lWYzNySFFVM0hUZ091NXlMeTZjKzlDN3YvVTlBT0VHTStpQ0s2NVRwam9XYzR6ZFFRNGdPc0MwcDZIcHNrK1FMakpnNlZmTHVRU1NhR2psT0NaZ2RiS2ZkLytSRk8rdUlFbjhyVUFWU05FQ01XRVpYcmlYNzYxM3QyU2Flcjlmd1JQdm0yTDdEV3pnVkdrV3FRUGFidW1EazNGMnhtbUZnaGNDQXdFQUFhTkNNRUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGSS93UzMrb0xrVWtyazFRK21PYWk5N2kzUnU4TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCTFFOdkFVS3IreUF6djk1WlVSVW03bGdBSlFheXpFNGFHS0Fjenltdm1kTG02QUMydXBBclQ5Zkh4RDRxL2MyZEtnOGRFZTNqZ3IyNXNid01wampNNVJjT081TGxYYktyOEVwYnNVOFl0NUNSc3VaUmorOXhUYUdkV1BvTzR6elVodzhsby9zN2F3bE9xekpDSzZmQmRSb3lWM1hwWUtCb3ZIZDdOQURkQmorMUViZGRUS0pkKzgyY0VIaFhYaXBhMDA5NU1KNlJNRzNOemR2UVhtY0lmZWc3akxRaXRDaHdzL3p5clZRNFBrWDQyNjhOWFNiN2hMaTE4WUl2RFFWRVRJNTNPOXpKcmxBR29tZWNzTXg4Nk95WFNoa0RPT3l5R2VNbGhMeFM2N3R0VmI5K0U3Z1VKVGIwbzJITE8wMkpRWlI3cmtwZURNZG16dGNwSFdEOWYiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBUE1BQUFEQ0NBTUFBQUNyRGdRRkFBQUNkbEJNVkVVQUFBRC9BQUQvZ0FEL1ZWWC9nRUQvWmpQL2dDdi9iVW4vZ0VEL2NUbi9nRFAvZEM3L2dFRC9kanYvYlRmL2R6UC9jRUQvZUR6L2NUbnllVGJ5YzBEemVUM3pkRHIwZWpmMGRUWDFlajMxZGp2MmNUbjJkamYyY2o3M2R6ejNjenIzZURqNGVEejRkVHI0ZURuNGRUZjRlVHo0ZGp2NWVUbjVkamo1Y3ozNWR6djVkem41ZERmNmR6ejZkVHI2ZURuNmRUajZlRHI2ZGpuMmREejJkanYyZERyMmR6bjNkenozZFR2M2R6cjNkVG4zZUR6M2RqdjNlRHIzZGpuNGREajRkVHI0ZHpuNGRUbjRkenY0ZHpyNGRUbjRkeno0ZGp2NWRqbjVkanY1ZFRyNWRUbjVkVHY1ZHpyNWR6bjNkanYzZGp2M2RUcjNkanIzZFRuM2RqdjNkVHYzZHpyNGRqcjRkem40ZGp2NGRqcjRkem40ZGp2NGRUcjRkVG40ZGpuNGRqcjRkem40ZGp2NWRqcjVkem41ZFRyNWRqbjVkanIzZGpyM2R6bjNkanYzZGpyM2R6cjNkVHY0ZGpyNGRUcjRkam40ZFR2NGRqcjRkanI0ZHpyNGRqcjRkenI0ZFR2NGRqcjRkanI0ZGpyNGRqbjVkenI1ZGpyNWR6cjVkVHY1ZGpyM2RqcjNkVHYzZGpyM2RqcjNkam40ZHp2NGRqcjRkenI0ZHp2NGRqcjRkVHI0ZGpyNGRqcjRkanI0ZGp2NGR6cjRkenY0ZGpyNGRUcjRkanI0ZFRuNGRqcjRkanI0ZGpyNGRqdjVkanI1ZGpyNWRqcjVkem4zZGpyM2RUcjNkanI0ZGpyNGRqcjRkanI0ZGp2NGRqcjRkem40ZGpyNGRUcjRkanI0ZGpyNGRqcjRkanI0ZGpyNGRqcjRkam40ZGpyNGRqcjRkanI0ZGpyNGRqcjRkenI0ZGpyNGRqcjRkanY0ZGpyNGRqcjRkanI0ZGpyNWRqcjNkanI0ZGpyNGRqcjRkanI0ZHpyNGRqcjRkanI0ZGpuNGRqcjRkanI0ZGpyNGRqcjRkanI0ZGpyNGRqcjRkanI0ZGpyNGRqcjRkanIvLy84VUJibmFBQUFBMEhSU1RsTUFBUUlEQkFVR0J3Z0pDZ3NNRFE0UEVCRVNFeFFWRmhjWUdSb2JIQjBlSHlBaUl5UWxKaWNvS1NvckxTNHZNREV5TlRZM09EazZQRDArUDBCQlFrTkVSa2RJU1V0TVRVNVFVbE5WVjFoYVcxOWdZV0pqWkdWbVoyaHFhMnh0YjNCemRIVjNlSHg5ZjRDQmdvU0ZoNGlKaW91TWpaQ1JrcFNWbVpxY25aNmZvYUtrcGFhbnFhcXJySzZ2c0xPMHRiZTV1N3k5dnIvQXdjTEV4Y2JIeU1uS3k4N1AwTkhTMWRiWDJObmEyOXpkM3QvZzRlTGo1T1htNStqcDZ1dnM3ZTd2OFBIeTgvVDE5dmY0K2ZyNy9QMytDUFcvSkFBQUFBRmlTMGRFMFhuUi93b0FBQWR0U1VSQlZIamEzZHo1V3hWbEZNRHhjMUZjd01RQ0ZTdEtXOVV5TGJWVUxFb05NdG8zQ21pbGZVRkVXMmpmdk5DZTVWSUIzclRTTEtYTk1ncHhwUVF2WHYra3dzZDZyM3J2ekx6dmU4NTV6M3ZQYi9KYzdzd1hjRDR6YzJjR0lOTk1peC9KaFZrOUUzUm16anJ2aXp2S1FYY3FObmxkdktVNkJ2cVRWNzNkMitKZmFvYUIyZVRYZEh0WnZLdGhGSmhQWWNNKzc0cjdHb3ZBYmtvYUQzcFZmS2lsRk96bnJKWkJiNG9QeDg4Qm5QR0dhMDJRYzREcnpuTEFIZkZjbTRFY3huVlhUb0ljUENQRWNtMEhzbzljMjRQc0c5YzRJUHZFZFNwK0xuQ01JSzVSUVE2ZXVUSzQ3bHdJbkZQeFZVNkNMSnRyS3BEbGNrMEpjdkNNY2NRMU5janl1T1lBV1JiWFhDQUw0cG9SNUJDdTErY215QUs0NWdmWk5kZHVRSGJKdFR1UVhYSHRGdVF3cnZ0SlFKNEVrZ2VmYXhrZ3MzSXRCdVRnbWQrT1Z0dytuMklGSHlnbmVGTWtycitsQUhsT0xaVHVvZmpyd2VCNlI4MXdpdjk1Kzg0QXFFUDhZQXVSNjE0S2tJZTJzTFZEdjVKMm9zTXpHNjc3R3NmaHIxRHgwSUZ2NHVqZTNFV0hxTlEzNVpvRTVNS0d2ZisrZGZMWWYrUW11cjA3RTY1SlFNNnYrZjNvbXk4Nzl1K0NMc0s5K09tNlhLK2VSYkZKUFhZNTBNOWovdnZTSXRLak5hMmphNUlqWlBVNWNxWDZvdnBkZERqbG1nWms5UUhFcXJRdmwrNUorOXU2eEJYWFJDQ3JCUXpSckthTzVEb1VMYTU3RzBiakw3YnN1RzFvN2ZHL2lIYnlzNm5CWE5PQnJDWnh3aWI2S05MRUIrblp1U1lFV1UzeXBIM3NKbzZUTVptNUpnVlp6YktUWGxQUXhYTFNMUVBYcENDclVUU3JXWFR5TDJCek5mM0o4QTIwSUt1cHpQVENURHRNSFF0b3VhWUJlVzJHa2xVWlg1cU9OQS9YSkNCUGphY3laQnhQYzJha0diaG1BRGtieldrLy9zN01rdlN2SEkrL2NrVzNFV2c0Zm1VV0RUdnpzbjNMQ1VqN2NVNDlPOGhCTkt0Wjd0MW5KMEVncTJrSytMNkNIL3o2akN3UTVHQ2ExU3dPT2dvZzRab081QkNhMWJRR0h2dVFjRTBFc3BwNHlMZG5ScHFXYXhLUXcybFdVeDl5bUV2Q05RSElhdXJDTndhaEh6YTV2MVlwNnhGeXBrbEUyUFJtUlZvZTE5bEJqa1p6RktSbGNSMEVjalNhb3lHZFpwNWpyaVBld1JwTWMwU2toWEJkc1RIYVNsWkdmY1BXaUtlam5YRTllMjNFTll4SGZzc3dwQjF6SFFheURzM1JrVTduZW9vNGtIVm8xa0ZhelVETFJGa2c2OUdzaFhRNjEyTUZnYXhMc3g3U2FucFl1STRHc2k3TnVraHpjcTM5U0ltb05Hc2p6Y1oxVkpBTmFOWkhtb1hyeUNDYjBHeUNORG5YMFVFMm85a0VhVnF1eTR3dW02MHoyMmdZWGJhSnpYV3gyZDFNQ2NOTnFoYlNhZzRnY3EwSHNqbk5wa2pqYzYwTHNqbk41a2pqY2gycjNtYTgrREhtaTExOHhIaXN1ZFlIMllwbU5XMDIxNXZiY0QxN2pjV1NXNjErMkpQMldDejZ5T29aakNEYjBxem1YcXVMc00yNExyTzhqNlhlZHMvZTh0NEtmYTZMYlc4dlRsaHZQaTgrWkxjR21seWJnb3hCczVwbTZ4c3J1cU92eFV6Nyt3K2JFWFlNekpIK2Y1WkdYdGhTNjJYWjBJeUN0SVBtS3B5ZDNqYVBtbHR4a2kyUlptMjJwUmtMYWM3bWVxeGthNlRabWhPSUp5SXRrZVpxVHFMZUJkbnNSZk55MURNMGRrZ3pOZVBRaklRMFUzTVZJRStiK09aVzdHUXJwRm1hOFdoR1FacWx1UjQvMlFacGp1WUV5V2VFNWtnek5DZUpIbS9STExoNU9VMnlPZEwwemRnMDJ5Tk4zMXdGWk5NbXRMbVZMdGtVYWVwbUNwcHRrYVp1cnFkTU5rU2F1RGxCZlBtT0VkSzB6WVBrVDU1YUlhNjVtVHJaQ0duU1pqcWFyWkFtYmE0Q2hta1QxZHpHa1d5QU5HRXpMYzFxNmdRMTEvSWtROTRYWXBvM3NOMElvM3ZoR0Zsemt2SFdpRVloemMvd0pjUG83U0thZnl4a2JJYXJSVFF2QWRaNVUwRHpHN3pKVU5ManZMbDNBbk16M09HOCtYYnVaSWg5NnJoNXZZTUh6WjkvMEduendGUndNSTg3Ylg3TVJUS00yT0t3K1R0SDk1elBUemxyVGwwSmp1WmxaODB2dVVxRzAvNXcxTnhUNHF3WmJuYlVmQk00bkErY05IL3NNaGttOXpsby90dnhrM0FlZHREYzREWVpobTlpYi80bTMzRXpYRGJJM0h6NGNuQStMekEzUCs4K0djYit5dHE4YzV5QVpyaWV0WGtwaUpqM0dKcy9sSkVNWmZ2Wm12c21DMm1HKzltYTc1T1NESGtkVE0xZkNuckVhTWdWRjFqTmc3TkEwS3hnYVc2V2xCeHl4UVZTTThkVkZEcXptS0c1RW9STm5MeDVsYlJrS04xTjNNeDFGWVhPM0VQY2ZMZThaTWo3bkxRNSs5UGhYYzcwQWNMbTVBd1FPVThUTmo4bE14bEdiaVZyM2paYWFET1VwNmlhSzBEc3ZFN1UvSnJjWkNqK2s2UjUxd1RCelhBclNmTXRrcE1oOWdsQjg3cVk2R1k0N3lCNmMvK0ZJSHdlUlc5K1JIb3lqTmlNM0x4MXBQaG11Q0tGMnB4YUNCN01pNmpOTFQ0a1E5RnZpTTNkcDNyUkREY2lOdDhBbnN6N2FNMGYrWklNWng5QWF2NXJpamZOOEJCUzg0UCtKTVB3alNqTlgrZDcxQXlYRGlJMEg1NExYczF6Q00zUCtwVU1wK3l3YnQ1WjVGa3pMTEZ1dmc2OG0zY3RtOS94THhrbTdiVnEzbittaDgxcHo3Z3dhYTczTVRudEdSY0d6WWxoWGphcjIyZjFtNU16d2ROcE1tNWU1bXN5RkhRWk52OVU2RzB6WEdQWWZDMTRQRzhiTmIvbGN6Sk0zRzNRdlBkMHI1dmhMb1BtTy8xT2h0Z2E3ZWJQWXA0M3d3WDltczBEMDhEN2VWS3orUW4vazJIa0ZxM203MGZsUURNc1NHazBwNjZDbkpoWE5acGZ5WTFrS0o0WCthWHppaG5XNXg5VjJCRjY0bjVmM0FBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiY2E4N2NiNzA0YzFiNDU3OWE4ZTg0ZWZkZDdjMDA3ZTAiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxNiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsidXNiIiwibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTI1N31dLCJmaXJtd2FyZVZlcnNpb24iOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMTAtMDYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTA2In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNWZiYzRiYTc1MzA1MjE4N2FhYjNjNzQxZDFmOWVjNmZiM2M0ZDg3NSJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI1ZmJjNGJhNzUzMDUyMTg3YWFiM2M3NDFkMWY5ZWM2ZmIzYzRkODc1Il0sImRlc2NyaXB0aW9uIjoiSHlwZXJGSURPIFUyRiBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwiaXNLZXlSZXN0cmljdGVkIjp0cnVlLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCeHpDQ0FXeWdBd0lCQWdJQ0VBc3dDZ1lJS29aSXpqMEVBd0l3T2pFTE1Ba0dBMVVFQmhNQ1EwRXhFakFRQmdOVkJBb01DVWhaVUVWU1UwVkRWVEVYTUJVR0ExVUVBd3dPU0ZsUVJWSkdTVVJQSURBeU1EQXdJQmNOTVRnd01UQXhNREF3TURBd1doZ1BNakEwTnpFeU16RXlNelU1TlRsYU1Eb3hDekFKQmdOVkJBWVRBa05CTVJJd0VBWURWUVFLREFsSVdWQkZVbE5GUTFVeEZ6QVZCZ05WQkFNTURraFpVRVZTUmtsRVR5QXdNakF3TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFcktVSTFHMFM3YTZJT0xsbUhpcExsQnV4VFlqc0VFU1F2elFoM2RCN2R2eHhXV203a1dMOTFycTZTN2F5WkcwZ1pQUit6WXFkRnp3QVlEY0c0K2FYNjZOZ01GNHdIUVlEVlIwT0JCWUVGTFpZY2ZNTXdrUUFHYnQzcnl6WkZQRnlwbXNJTUI4R0ExVWRJd1FZTUJhQUZMWlljZk1Nd2tRQUdidDNyeXpaRlBGeXBtc0lNQXdHQTFVZEV3UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDRzIvcHBNR3Q3cGtjUmllNVlJb2hTM3VEUElybWlSY1RqcURjbEtWV2cwZ0loQU5jUE5EWkhFMi96Wit1QjVUaEc5T1p1cyt4U2I0a25rcmJBeVhLWDJ6bS8iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSTBBQUFBV0NBWUFBQUQ5L3g4bEFBQUFCSE5DU1ZRSUNBZ0lmQWhraUFBQUIzRkpSRUZVYUlIdG1rMXkyOWdSeDM4Tkl0TFN6QW5Nbk1ETU5rbVY2YXFweW5KNEE5TW5NQ1NTVmFHME1Md1FzUkJsd1NjUWRZS1JWbG1sUkc1bUcrb0VRNTBnMUM1VVNIUVdqL2grL05CRXRtY20rcThJdkVhL2ZrRDN2L3YxWTRWTk9BeGEvUG03S2ovK1kxb2E4L3dxZi9ucjMvblRkM2ZXOFdmOFp1R3VIV24zbXdnWHdCdnJlR1V2QkJwQWc4UGdIWjk2d3k5aTRUTytMZHI5SmlLdlZsZGpCcjJSWXhYc250U0JpdzJLaG9pOFRhNGRMamdNV2s5bzZqTitDZWowUFVSbXdCaUpyb21vMFFrYVphZnBudFNKNUFhUjZnWkZiMHYzbngzbk53aXBNdWlOVUIyaUVsS0pKcUQxZkhyeS9Db3FGMnNkeGpqRitkbzVqT093TVZWbDZVNmlhMDZQSjdueFR0QUFYcSt1eGl5WTRwSTY2V0wrbWRDZjVaN3BudFJSNS90VWhrdCtGMVdKNUJVaXRaSU5xbE9XTWlic3BiVllwKytCdkZocmQ2dzM3RTFOWUZWZUkycDVUekpoOGU5eHljWjRiU3F2Y3MrSmp2aVAzQ1cyUE1hT0dGNVFvNkt2UzJzVkhYRjZOTWJ6cTdqNzc4M2FaY2JaM3o3bjVMeWdscnpqaUx2ayswV1lPVVNxcU5ZWUhFL29CTTI4MDdoN1Z5RDF6SjFyQnIxUnN1QlN5dElEVkZvSXI1SmJEaGUwK3pQT2pxNnNDeFk4WXFkUVI0QkpRYUlCZkZqOS9nanpFUFlQQVBNaUszdC9BUEtNRm9tSEpJNTFEL1BQNk40UWtkZllJR0txdVZ3dEp1dURJWWJMR0ppaUVpSnExNDFDWlcvR1lYQ1E2TzZlMUltY0g0QWFvZ1Z4QVZmSHEzVS96ZzZBZGhBaXZBZXhtQ0xRQ2VLYTFEZnFGU0R2TkM2MVpOelJNV0RzRnVxckpRMUJqSE9oc3pROXRmdER5THhrNVpiRnZKVXNXdldIZ2trZkdSeUZMT2NObE52QzJNV3FMdnJmWVNJMlRLNUYzaHJqVi9DQ1dpNWRSbmpXS0xmQjRTS242NmtnVWtYMEhNODNqQkxKRmNMVHo5TUpmT013WHdoTFF0cEJDUElUeUUrNHRGZzhEQTNUSEFhdFRLUWFoMW5PRzRUK0RNK3ZsbW9jMVV2T2pveG5HcGtHbGYxUndqZ2lWWlFMNEk5UFl2eWc1OVB1dHhCNUNVQUZEL0RNYi9XVEtGTzk0OU5ST1RXcVhpSVNVMjROSjhPWURnM2l5RW9mT0FBcE1pQXM1dVY3V2QxWmxoU3A0dTdYZ1ZGaTl6cmRvbXVjZklzZFNqTWhHTlU3SUM1Yzg3TEdqc2ZEcEVDdmVOczFrYXJuR1hxN1owa3ppVlozZndoa2MvYzFaMGNwQTUwZVQ2eU9nOVRwQkQ2RG52K3pEQzVDeFYrMUFBQjlpK2Y3c0YvTk9idUl2UkFYbVNacEZxRFRieVdzNnRnWVFDWTUrVTNJNng3UkRwcTVkRjNFUXE1eTljaG01WnZ0eU00ajBsb3Iyd2wybTI1SHVGVFV6N0ZJaEpkZmxGYlRTT2FXNVNwbHhVVnp6Q2FoUDZONzBrS2RmNmFQNm52aVhHbUQ4cEp1UDE4YlJMeTBwV2MrOVliSnh6WlI3S0ZhUzUxZHh3eU9kdnZRM3hJVmJtajNmWllQMXp1blVSdTZKM1d5NWRHdVR2NEVjQkZwWnE3djErNThpaW5MM2JzcEZNMXdlanloMHg4blVTeFN4UXRxYXlOTGFLRUZkckE1VERyb0F6ZkdIbjJmMytYSmJzNFpVY3ZWYnZFT0lZK2JVblNxempnNyt2MUczU29Oc0xDTVNXR0dFWVVheUJCM0g5ckJFT0Z5d3djdjIyR0NvNEU2OWgzdVY0QkR2Q3NCVVA2MVJzNlNzc1NlSjdWQTl6dFQ4UTR3TC9jYW9GUmpiYWJ4RmlvalZFYVorZ1Bnbm1odTMrV1ZkS3hwUTJSMVoxbFY5UzZ4YWZuZ29YcHBmZFk0eHRPazhLOEVGelRERE5RNERGcDV0cEVaRWpVSWoxZGJ2UDRRK042aUsrNHhaSXUrOGNiWlZlK1FRcVFydFh6aFdNQUNEN2N3LzNJRHk2eWRtMXVjcUdWTkVZWVpDczYrcmxpMTRocEhVNXZNSEMyOHdNZlZKb3BYV09NSHZHQllDakNiSFZIUnJxOFBGeVZFU09sYTlKenV5U1JwdWkzbTZZczFQWUZzTi9nKytXWDZPSVVldzVhUEtUSXNGY29tNmo3WUg4QXdWN3VmMHIzeWVTdWJaWGM0dStSK1k5ZXVOY0liVkt1SVpGc1NZYWxwR2R0dTJnZmg2bjFkRVRPOTZaWGsxN0hKRHJNclNxODNsUUZiWmJXK3BTN0l3VmsxNGE0emhwb3RkdHhuaVIzR2JNdnpQUUdKVEVQSzFzZFJQbit4NGl3YmZjSjJCb2gzT0YvS251STdSTGMzNkFhOUVacHhrdWlSZlJ6elhkS2dyV3dLdElLc20ybU9tbDVTcHQxaTJlSVhZUG8waTNtTHl0NGtvVXlSS2hFM2RFL2VjSG84NFRCbzVYb2JBQkh2K0hROHNaNVZLYmVjOVVyNysxOFA5SnhPVUhaR2lRNnNEQUxtSGJyN1UrQkZydDFnampqS1RxVFVjZzIvU21UUnU4VU8xYXRNZ2QxYUhkRk1yTEl3SWkwclB0QU8zaUpNVWExRHRsN1RyWUZsbk1ac2w1dXJZczdRWmV3NDdiNW5JaWREWHhGcCt6MXloZ2pab3ZTTzVVTmoyOFMvYkt3cjhqZnNXRUovUnFmdko4Y0FxdS94Z2lGS2xlU0lJRHRGVnE5ZU1yQTU0eFk3bHVMajBpVDd6WXB6eGJJUythalRTR1dwQVRVa1k0aHl1L2I0SjRQMDdPbjBlRUwzcElFNmVjY3Bka3RWTDNOZDEzd2o2eDVIbTV4dDZEK29USkx6RjF0UkZ6RmRuWCtzTC9wMmtkazJUL21CelVVN3BKM2JyTzVzTjNkd0ZOTHUxeEZxQ0NZTkxCamk4aEUwUGx1cUF5OVdHNUFaRVZmNUx2WWo3QWg3VTd5Z1RnVVAwWHFxRytNQXdwVEZLZ1dlSGsrTXJQb2c5ZngzMHpISWlPVThMRTVsbmI1MHg5QnA2amhabU9PRGZGK2xFMlJiVEcrK1pwUHBHZDhHNWYvVG5CNVBWZ1h1Zlg1QXh5V0h5U0xpM2JQRC9IL0Evcys5b3VNb3R5d2VtbFpaSTNEdy9IZlBaeGgwVCtwMCtxUGtpTitHVHY5WHZFdDZ4cy9CZndHaGhtblljYXlkZ1FBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wOC0wMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSHlwZXJGSURPIFUyRiBTZWN1cml0eSBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDE1MDgwNTAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDgtMDIifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJmODNmMTBjYWJlNTA1MzcwNTFiYTMwODZhYzEwMWFlNDMyNmUwZGUxIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImY4M2YxMGNhYmU1MDUzNzA1MWJhMzA4NmFjMTAxYWU0MzI2ZTBkZTEiXSwiZGVzY3JpcHRpb24iOiJIaWRlZXogS2V5IDMgVTJGIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsidWstVUEiOiJVMkYgS2V5IC0g0LLRltC0IEhpZGVleiJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJyZW1vdGVfaGFuZGxlIl0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJ3aXJlbGVzcyIsImJsdWV0b290aCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ3JUQ0NBbFNnQXdJQkFnSVJBTGhkOTQvNDMxMkltemtpZW05a1V2Z3dDZ1lJS29aSXpqMEVBd0l3Z2FjeEN6QUpCZ05WQkFZVEFsVlRNUXN3Q1FZRFZRUUlEQUpFUlRFT01Bd0dBMVVFQnd3RlJHOTJaWEl4R2pBWUJnTlZCQW9NRVVocFpHVmxlaUJIY205MWNDQkpibU11TVNVd0l3WURWUVFMREJ4SWFXUmxaWG9nUTJWeWRHbG1hV05oZEdVZ1FYVjBhRzl5YVhSNU1SY3dGUVlEVlFRRERBNUlhV1JsWlhvZ1VtOXZkQ0JEUVRFZk1CMEdDU3FHU0liM0RRRUpBUllRYkdWbllXeEFhR2xrWldWNkxtTnZiVEFlRncweE9URXhNamN4TkRFd01UUmFGdzB5T1RFeE1qWXhOREV3TVRSYU1JR2dNUXN3Q1FZRFZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0F3Q1JFVXhHakFZQmdOVkJBb01FVWhwWkdWbGVpQkhjbTkxY0NCSmJtTXVNU1V3SXdZRFZRUUxEQnhJYVdSbFpYb2dRMlZ5ZEdsbWFXTmhkR1VnUVhWMGFHOXlhWFI1TVNBd0hnWURWUVFEREJkSWFXUmxaWG9nUzJWNUlFWkpSRThnVW05dmRDQkRRVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR1ZuWVd4QWFHbGtaV1Y2TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJDQkx5ai9tM1JEelkzSUZkM01zeWc0ZXhta0xHTWhDNmFHSCtVbXpsMDFiYlRtbzZJUWNPYW9xK3JhSUZ3R3ZpM3N3SUNJUENxVUtLbUdvaHJTVW9LdWpaakJrTUIwR0ExVWREZ1FXQkJRSzhZVjl6WWFYRWFnNjMvTkJraHl1QVEzdlBEQWZCZ05WSFNNRUdEQVdnQlNtb2kzRmlreTFxMmlUWFpHTUNKN0lOU0ZxbWpBU0JnTlZIUk1CQWY4RUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCaGpBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBbk44emR0d0ZwRDBPMWhaVjB6WVN2aFN4aThuODBCN2hsMkk3d0pHVW95d0lnUHFHdVVvdmthOXorS3p2VXNmK0dOZFM1WWJueDY1T3p5cXhDTlR4S2pWUT0iLCJNSUlDc1RDQ0FsaWdBd0lCQWdJUkFQK1czUXRud015WGFmdVFvTmFYY3FVd0NnWUlLb1pJemowRUF3SXdnYWN4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSkVSVEVPTUF3R0ExVUVCd3dGUkc5MlpYSXhHakFZQmdOVkJBb01FVWhwWkdWbGVpQkhjbTkxY0NCSmJtTXVNU1V3SXdZRFZRUUxEQnhJYVdSbFpYb2dRMlZ5ZEdsbWFXTmhkR1VnUVhWMGFHOXlhWFI1TVJjd0ZRWURWUVFEREE1SWFXUmxaWG9nVW05dmRDQkRRVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR1ZuWVd4QWFHbGtaV1Y2TG1OdmJUQWVGdzB4T1RFeE1qY3hOREE0TUROYUZ3MHpPVEV4TWpjeE5EQTRNRE5hTUlHbk1Rc3dDUVlEVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUkVVeERqQU1CZ05WQkFjTUJVUnZkbVZ5TVJvd0dBWURWUVFLREJGSWFXUmxaWG9nUjNKdmRYQWdTVzVqTGpFbE1DTUdBMVVFQ3d3Y1NHbGtaV1Y2SUVObGNuUnBabWxqWVhSbElFRjFkR2h2Y21sMGVURVhNQlVHQTFVRUF3d09TR2xrWldWNklGSnZiM1FnUTBFeEh6QWRCZ2txaGtpRzl3MEJDUUVXRUd4bFoyRnNRR2hwWkdWbGVpNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVR1dGgvM2NjVmxJL2hHeUo3elNOYXFoQ0xEeUtNOUp1Wk5qY1RzbkRBWXlSRE9wellFV2lMcXMzamRmVktkM1Zndjgvaitmb0RNU01wSSttd2pPei9wbzJNd1lUQWRCZ05WSFE0RUZnUVVwcUl0eFlwTXRhdG9rMTJSakFpZXlEVWhhcG93SHdZRFZSMGpCQmd3Rm9BVXBxSXR4WXBNdGF0b2sxMlJqQWlleURVaGFwb3dEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQVlZd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ040Z00rOXUzTkJMTWtkRVcxUGFERzlPbFpaaVViNnZoQ01NTmk0NXEwNnNDSUI4QThLbDh0UlYvR2tKWVBTK3J1eTBuTFMzVit0Q0Z6VElFaUJBWWs3aUEiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSUFBQUFDQUNBWUFBQUcwT1ZGZEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFBeVJwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVNeTFqTURFeElEWTJMakUwTlRZMk1Td2dNakF4TWk4d01pOHdOaTB4TkRvMU5qb3lOeUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSU1pXWTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpWSmxaaU1pSUhodGNEcERjbVZoZEc5eVZHOXZiRDBpUVdSdlltVWdVR2h2ZEc5emFHOXdJRU5UTmlBb1RXRmphVzUwYjNOb0tTSWdlRzF3VFUwNlNXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEb3hNakZET1VJMk9UVkJNREV4TVVVMVFrUkJSRVF3UWtKRk1VWkZSamhHUkNJZ2VHMXdUVTA2Ukc5amRXMWxiblJKUkQwaWVHMXdMbVJwWkRveE1qRkRPVUkyUVRWQk1ERXhNVVUxUWtSQlJFUXdRa0pGTVVaRlJqaEdSQ0krSUR4NGJYQk5UVHBFWlhKcGRtVmtSbkp2YlNCemRGSmxaanBwYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pFeU1VTTVRalkzTlVFd01URXhSVFZDUkVGRVJEQkNRa1V4UmtWR09FWkVJaUJ6ZEZKbFpqcGtiMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakV5TVVNNVFqWTROVUV3TVRFeFJUVkNSRUZFUkRCQ1FrVXhSa1ZHT0VaRUlpOCtJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCt2cjVYSWdBQUUvOUpSRUZVZU5waUREbDZnUUVQNEFMaUJDQ2Voa3NCRXc3eC8xQ3NEZFc4RDBrTUJiQmcwUWdDQWtEOEVVbmNDVW8vUmxMRGlHNEFpZ1FPSUl1azlpOFFNNk83QUo5bWRIWC9rY1BnUHdtYVVReGhJdEZtZEhBRlpBQTNFSjhoRUJ2L2NjanJnQXlJQjJKak1sMEFEb05wREJRQUZpSUNpcUFMWUdBZGlaYi9SM1lCSTU2QXd1dEM5THh3Z0FUYlBkSERBT1lLSlNDK2gwZHpBQkM3QVBGZWJJSElpSll2Q0FZc1FBQXhFaWdQd29INEN4QnZKU1VhL3hOd0VTTytBZ1U1U3pPaWFjTHFQU1kwelZZRUVnK0dJU3hrWkdkR3BBd0dUd2ZwWkpRRmNCZjhKN004QU9uNXgwUWd0Y0d3RTdGSkdSZllTMnE5QUFMOUJMTDFUUFJDRlIwVVlVa1B5Q0FOaUU4d1VWQ2dnb0Fsc2hmcVNDMU1rTDBBY2tVak9XbUJDVnR0UTRUdGpMaGlBU1N4QnkwTklHTXQ5REFEQ0NCQzVRRTYrQXpFUEdoaTM2RHRDR1N3SElpamlLMVhHSWhNemYraGxqT2lZVzQwZmljUVI2THBTeWEzZ1lNYzVveEVKcmtLTE9ybjRLcWltZkJZRERPQWlZRXlnTzV3a1BtcXVBcFVFQkNsTUhNUjQ1QmJRTHdkdVVCK0RjVG5nZGlJZ2ZZQXVWWmdoWVdBQ0JCM2s5RzBRTWFUeVhETUw1QURRcUdjWmVRVVJVZ2doNXptRFJNMEh3OFlZRUpyZEZTUkVJL21CRkk3U1lYNVFpamRTb0xqVDVGWVBzQ0FDYllxT1lGQS9GSVRuSWJTNXRocW8xUWFPd0s1a0R1RnJTU2NRMlFMbDFRZ0J6V3ZIejI2V0FnVUZ0SkEvQVNML0Ixb3RqMEc3ZE5LUWh2OG9LaGtKYUk0SnJxVDlCUk5JeWpFL2dDeENwNG16Rm0waElZWEFBUVFxZTBCbEFZVjFLTHZRTHdmaU8vU29wdUlESHlBZURNSjVjdC9ZaFVTQWllZ2htM0dFYS9ZNHZjZlVoT01vaEQ0anlWTnlCRGI5d0dDcTRRNjNMaENvQUdMNVl4NExDZVU0ditUNG9BbFFGeFBaaG1QN3BBTGhCeUI3Z0F6SUk0bVl3UUpGekRFMGVyQzZZQ1RWTFNjQVVmM0YyOG5tOXFXNHhxZ21Jb3ZEZERDY25TenM5QWQ4SjhPbHFNN29oNWJkVXd2d0FmTjZtQUhhQTlBVS9BemNrbDRnSUxVVFduYVlXS0M5Z2tvdFp6Y0Jrd2ZPZjIrNTFTSWdqSllEWXZzQUM0aU5VdmdrZk1pMG93bW1KM0lEcGhIcE9ZbGVPUzJFV2tHTzZ4MlJYWkFPSkdhWTZtWUcrWXpRZHR3bEJTckROREdLVG01WUJvTHRGMzNud3FPSUJic3cxY2JmcUZESWVTSXp3SGNkQ3dONVpBZGdCeWNMVFMwRkRtcUg2T0h3Q2NvWFUybnlnZ2pDdml4TlJobzVQdlB1TklBUm9PQnhpMGp2QzJpRHpUcWxoUFZMMkNFUmtrWmhSWXpBL0ZHZk9VR0M0R2dBcm04RTR2Y0dpRGV4QUFaY0FSMXgwMmhSYms1am9LSGtkeXVHYTdCaWhBb3ByaTBaQ0loNFlCd0R4RnFyVW5wVFFFRUVDWGpBOFFDRFNBdWhQYTRTQ2xwUVpQam9OSFhSYlIwSEJPVnpkdk9nRG1FZkowQk1zV0Y3dmtTcEpqaUJlS1hhUEtnU25vaEEvYVpINlBCRWdBRmFBN3p3S0h1STlTVHlPTXB2V2lOQUFrMCtWbDQ3RDJMWk9jdmVnZUFIcExsL1RqVXZFUHpqQUFaTFoxME5ETlc0RkRIaXVTZUI3UU1nTVZRU3k0UzRXQmhHbVRYU0NUekZYQ29rV2ZBdjNpR3JBQ29neG9ZZzYxRlRXU1NwVFo0aUdTdkg1N2FuMkJBa0RwRUNRTzhkR3E4RXdNMk0rQ2ZYUGdQVGIxeHBLU0FZaHlHd1VKOXNIZ2VsL3V3ZFdUL0U1c0Nkak5BVmlxaEI5Ui9ocUVEY0tXSS80UmE0K3ZSUEcvQlFQNUNzOEdhSW5DT0VBY3lRTmFwZ2NCTXFNYVRETU1EWUZzNmdSRUE2NUFVWnpBTVR3RHkyMndvdXhzNUFKQzc0RXAwY0lnbnRMR0UzSXBjUWFkQVNFVnFpc01EQUhrSWdKYkRBVERQZ3NZd0JkSGt3cEhrOTlBcE1EeEFBV0NKcFFxa05nZ2pzU0IxcGxIQnE0L2VJV05pSUdGdW5RS3drdHdZb3JJNzBNY1RORUVCOEIyTHdzQkJVbWpkb3JKNUx0aGFndnV3S0Z4Rm80WUpxV01MOTZqb0JsTXNZbnVZY0ZnQ2FpRnkwaUFRRHBDZzFvdks5aC9GSXRhTmJkMFdETHlsUVpKMlJPdmp1MEY3YzBvTTVDMUNJNlh3dzdhWTZRcjZ5amxrQUVvQndUVE80N3VodmJuN05MYm5BbzdJUUdrSll1c1lyUmtHcmI5WFdNUXV3N0lqY2dDQXRseFprVEFtTUJRQXFITW5pa1ZjRDFkdjhEZ0Q5dG1Gb1JnSVU1RTZkemhySkd3RElxZHdGRVJES1JEbVltblNiOExtTDBKelU5ZEFyU1Y4QXdxREVPd0NZbGRpMnlHRUJrVzFjQXdvTUExU3p6OUc4M3dkb1FnamRXNE91Y0RVSFdTZUIwV01ESnJIbXdscFlpSFJFbGdnZ1BydWw3RElmNFBtdFEwTWtLMEIxQnc4QlEzUCtVSUxOaTFxTmJtcE1UazZnNEgwZllYVUJLQjFUMlJQajFFakwyZWdOV05yYU9oWlVJdFJHTTAraXVZR1dXamd5RllHN0p0UldLQnRmMmRvUTBRQnFjUEZEQzNBYmtIYklxQ1MvRFk5a2c5QUFQS3VMU1NMSUFvZk5hUkFKQklTSTdzUVdrU1FKVVpKbWQzd0pheGVJb2dzRUl3dWhEMEkwb05HMFVObFJROVpVWUVRQlJLSWtSSGR5Q0x5SVNxUUlnc2lxTWdLb1ljU3BGRHI5Si9oMzZZenU3UDd6Nnk3ZngvOG9MT3pPM08rbmN1Wk0yZk9odUVmSUtPWWZnVzBRRUhoUHhFQldKbWhNQ3N6TG9ReWFtbU1LUE54RHc2ZWwzNy9qaGkyQ1ZnWkEyVGdHMjJIcElIenZJdndxbE5zT1VUYUczckdkK28ra1NaZ01WVVd6L2hzOU1pTDUwRFFYVTZjaG0zd3lJLzVidEx6TzZOR3dIeXFXSTlHWHJHVGl3ckxOMGQ2QzZXdjBIakdPaXJ2WGhRSUdGRVlHMlEwZy90ZXZrQTM1U3NrYmRNTmxVUkUzVmdRc0VkelliU044aHp3K2Z3UE5FRG5hS3hDejZheVVnMHlDK0NVbGUrUlp6ZVk4WGdkcEplRVUrWkhqYlVBdXVTOXN0a0NSajJFdjBodjNMUzdiejg5MTJ1anBBOW96ODhHQVc3TjdBZFZzTWF5VG5HVHlubmtrdWNvclUrTUV1QW0vRlpJSHNRSUMrZ09PODNsT3VvUXJhYkdBTzI0UFdOZy9NZ2d2U09MdWI2REZLbGpxYlNBVVJkVk5TcW1zWEcwZU9MUTRtVzRjU1BnaWlMOUtTVGM1S0tFS2xESHQra05Ra0FKOFA3dzZQMWZDdEhFZmxCSHRCbnlTOEF6SmcxRDVxeUhhQVBydUZaaE5kcXVTOEJGSnEwTE5PTUZSUURYcVV2SU9LTkxnT3dUL0FBU3hzZzRBUWRGYm51OXc0c0EyVm5pM2UvZmNvZ25iakNLMlFZdkF1VGw2SFNJTjdBN04wcHBiU29DamtSSXlURUpQSFoyV3RKY1dRSWEwbEI0Z1oyMGpoQllJeE9RNjdpWUJla0pYRWtLVS9zNW1RQnhPaEZQZll4QStxSllIdHNFQWNJNXVneitIOHprWm9FRklSWGVBWDg3U21PTXZaVWh0Z0N4V3Z4RFFHNklyTGVSd1BKOGpQRTg3b0o5TDVSbGpyODNpYVZrVlVqQ282Tml1YWI5d2RZczVIUU1MeFF0SUl5bVY2MHB2SmNkSWxYSURtRFptVXkvTDdaUThOVUE5NnkyVUk5NTB2OXpNaUVabmwyZ3duQ2hRZTJGclNHMHpHbEl3RVNQOVlBSkJTUUlpa0lnWUVJbW8vaXNNbHhJSGtRRFhGeThEQkd4MFlsOHd3VUg5Y0FZTmx3UHpxYng1MXNJQTVhWmZ4cndQdE9Ic2JsNFVmMUl3QXZtd2d6RGhmY0V1TWYwNlRYT3NOT0hCSEFmc3FnMVhIaTV6L3dIUXhvWEJwQ0EyOHlGT2d1RjZlNUVvODdRWkxqc1F0VUZKSUE3SHp6WkFnSEQ4Ry9RVHhub1BtZkQ5TjdJcE4zeGVpdEl3aGNMbFJHYUo1NFR3ckNPUTRwV2FCTGNlSExLdVJ6bUJzSVd5NVZDOTdkcklRaXZRcWVUQUs2SmJJSDBRTDNiUlVGQWwrSjZmaG9RY01KdG5aRXBOVWtaMTJNdWZJNGlmUmRIQUxlcFdCcHpBcmhRbzBOY0YwQzhWRHprZUl3SldPWmxGUEhhR2tQc2phbndaeFhwdlc0RWRDdHVhbzRoQVp3Mk8xYzFDemd4aFVuYm53WnYveFBYelRrQytoWEt5YUdZdi8wQ056MUFCdWVidnk4bXduUE9YWnU5RkNFTzJVeGFld3dJa0oyN01QemY1U0FFL0lUa2g1RUVOa1pjZU02NXEwUkhGVllCNHdmSW42VjZIVkhoeHpQQ0dnbHJpOUdGblo1alJaYnNCYW5pcTEvaGRRbEExRWpMNDg4UkUzNGh0UUJmd3ZzaEFJRXVOT3NjLytNV2R6V003VW55SW1xaFR4empscStOVmIrVmR3WWh3QzF1dE4raHFVdnM4K01nMU9RMThBVEFKTEpQSU9rL0hPWGhlQ1M4V3k0b1ppNVhCRDA0aVNROGhJVGZ2anppNGs5MlhNYnpnV2g5Zms3YTJIdEhOOEtkcVR4U1ZHWkJ3a3lHei9Eam9vZHhRZ0x0YjZSeWNuUXBKRDdQTWFpUkYvTlZnUG1OMTVQZ1lmRXgzUVdBZWJQWUdoYUYzUGU3cU56NlZCOWthZ0I3VEJYQ3B2ak9vdURpTTZmR2ZKZE5qK0FEMUhleGtwV2dqa0t0Qy9HQkFmSHA0Y09tR2JWNWV2eStOQnZNcGtYV0VwcStwa0p5QnhpNzBsc2lESS9FM2dMenU4TXNmZ25RM3JtR1dsRkZjWHg1NkZKa0pJU2FtTVpOTDVtaWZiQ0lvdWdxOXBLRXlwSXdBODJ1bE4wTU5Bc3EreEpob1dDWjVhT1hWcGJhQTdPWGtkNk1vcUw4RUpSbUQ1TWtQNVFhMkFQTE1zemZQV3QzaHRPWm1UMlBNMmZtM1AySGc5ZHpadmJNM212TjdMM1dYdXUvR3NFZlVHK1F6a01DWlp0K0JxdVBvNjkrVHRCRlU0dFVZaU5LT3IzK29TOTFOSG12K2hDZzhmNU9QenNzWC9xRndURUZ2R2RZTjRoMW5xQlBWRm9SL2N6VUpscW9MY0o1S0VhWHJnazNTMEpLazZ4Unl2bjl0YW94dnQreitEMm9nejBqZ2ZBUFNYbHZxTDh1c3Bmb2QzSEEyaFVIM0p2YWhybFAzaUR6eGE1aXAxTUFCUXVIVHoyRHlMdzRWNUtIbVdFcVRwUUs4UkJUQUh0ais5U0pjSnQrWjM2bmxNV1hDYS9KaXZBdU5YcE1mOTZUbklYak4xb0JtSk5mOWd6UWxoUUc2Qzk5dWsvMUNCVGk2UFVSMmxpckZxazVuNy9Ub0JsdXIxSndlRno3OURRRllEWDhoVlJ5SkpLUzF2S3FuU1hsTkNlRWRhdyszVCtrZU0rOERhNzFLQVJQOTZQeS8valNxTURMZUVESFlxc0UweUVVV2dGd1VyMnVIWVhoWTJTQ3R0aTBtKzRSeHNrcWpDelR2UGFyMHJWNEZHSlp3amJQVm92amlMNXRlaldEQWx5dkhUb2t0VU5QYklDTDkxNjFXSHFwU2JjeVoyc1hGT0lXajFLeS8vNStndlltU2FXUS9WVkZWQURENnZSY3pQTnhUb3pTd2VUdGNYOVdqcEdVc0VQbmU2TVFTUUpMVEdyaG9pSW9nQ2xFRnlmR2VxUGE0UXdZVWJUYm1zamZjcDlIR2VKV0xwcXRZN3M2andxd1RQd0w4UVVCMStkZ3FkU1IrRVdhSHl1a2RxMU5XMHpSc1Y2WUJ3V1lxamR6YzR6ekdBQjg1WHVrNThKVW15VmY0TnNZNXpMMjF6UkNBU0EySmFCNlZZUnpXT0VPMGc0L0t3NWU0UEE2WGNmbXFZam5FZ20zWFdLNjllTW9BRjR6Q09ST3N6eStTMjMwVmlrejZEb0VvME1WSVVxbTRBaTFscWJYV3dGSWVWeHNlZXdHN2NoRjB0eFVMUFhDTW9sZVk0dTN4Nlo2S0FCUEw1c3c1MW9jYStpaXIzUXlUQVVieFk1QzE0QUhqdktkL2RKU2dIYWRvOEtxemIwamRuVFpEdkZnS0lSdHdvRW9YNHFML0t5a0NuQzVoSmNFL0Z5VjQxSW5vMHhnQXVKc1BJU0VZbzZOcXdCanhEOS9GUHdxNVkwZHFnbjg2ZVNTT1Y1VlJlZ01PUTVPME5GUkZZQ2svYUJ5RGN6dmJHTis0K1RRY0N4VlJYZ2c0QmgyR3R0c0ZZQWRydGQ4R2pJRnl6YTRjYzhkN2xiWnJQV1I4eHUyQ29BcFVSMXE5WlpZVnFwemFEZ21xNnkyVm4wL1RHcFFzVlVyQUFzTEwwa0dRUlVEZERIb1VDeVFyWEdLbE9NbkRDQU12VGhJQWFybkVTSmhmbkpqV1ZoUWc2aDZWM1crOXo5ZS8zR0h2aWE4WUZ1V09QcmZtMmhRV09QZ09oMnE5akliS2poT2RxbkNIMjZpdmhKTVc4MlhTdVFSWVhpdlZDdEFMWE9Dc0drQ0lqOHA4Q0JBanZ1NENqd0tpRnRrbC9PakF2ZWRvSnBhOU5DZFJnSE1GRUM2a2w5U2F4SHJTSkRrWWFKdnUySUkzd3plaDFJSjV5NGl0Lzc1UHQrUFZWUC9Qd1VJOHVKZFVMQk84N1NUdnBWbS9IMjdUZzBMQ3pZVzQwTDYxSzBBSkNvRytZejU3YmlDZEJqVFowWWQyNThyNGE3eHZLQ2Z6dmRCVmtKL0ZJQkV5dUVCQnc0TWFTZ3ZXSmZSZmJaTDlLQ05Sb0NkMjZDNmQ4aDhtQ2xaMmpla3NmRTU3eXl2K3l4WmpLYkZYRmRraVRBYWZPUStvS1NXUU5nQ1owTE9PenNxNCt1VmFwak1lVU9ZODY0N01MV2t3Zy9iRmo1VDhzMGYrbk1EcnZsM2pzY0RxdEN3VWlqZCtZa0lIaEtFQXhhTlhwM2pEclBSa1dWME1idWdtM0k4SGpiVElSRmVCMUVBL1AwMnhEYVRjdHhoc29abVpuaTlqaHlQUll2bHcwcVUxMjRVZ0lpZXp5eE9hTXY1V29DM3dHVVpYSWRTR0Iva2VCeW1pQTg3YkJYWUkraXVIOEtyb011eThadHl2dkF4Y1hQdjFxSHQ5ZHIyeHprZmcwN0w0d2cyUFZ6eUROdytpNU1tU1BwVnR1cUJjU3FzaDFOb3krVDFUU3hBdnlkWitrS1k4amVMWi9YUGJ0OWF5NHZjSThYQmJLbms0ZUVYaDVGamQ4aThTTzdlT1pKT1ptL1dzQzA4OUlKYUFlS2xpY01qdU1PeUFRcHhyaE9IUEFFNjN3VVd4NUdrZ3hQcmU2bXkvMkh1ZU16eVlyeGFqM2Rqbmh1MEh2MDhhSG5zQWlQOGFnVUFzRnJaVk0waVRPeHBOKzY1d1dxeFMvSmhpcHZuL2FMNnBOL0V2b0lncEVtejNOZzNISXZGZjkrL2x2L2lueUFGTVBhMGJaV1VSNlIya1JHSGJIQ0RsTE8xYlRDdmxubGNDamg0VFFUYmU1aVRSZVlZRTJFYVh1SDNVQWZORzllcGNHMEFFK2RBSjVQTVFMRHVGc3RqSVpueVpYQUpXempnV3JVcG85aGJsYUNQazAzZFFaQ3ViWDF1K0FZRDl3VnNWbzU0LzU2d3RBellKVHZSeWFpdTVwNnQ4QitTMmdYVUl5c0FnUGJOeHNkTUdEbWV0cE9jckZMSEdXckcyWlFHbW5iME04ZW0wU2dVTWVTVkVXUVFScXNPMXg4WktZT2N6RklES2ZnMlhscG85dUFiZnNhMjRhZ2NRVkNaRVNFY3h2SUZZVE54QmlPYzdCS0RzSHlic2k0cjlPR0xSSklkbHladXFtcGxHSDNyZGpWWEhPSUJIb2F3MkFPY2QwTWxKZ05wRXFKSUFra0lLTDBqNURqTWxjbE9scEZCN0VWWWpZT1p1dWplRmZjaWFWREZVbFdUYmRPZ2pTUzJIKzkwTXJVR01RakxBMzVmcEdPK1BPbUYwaVNMdmxWdmFxblA3OVI4VytKa0c0b25wVXlQSHlUNDI5TzZXRDNvNGp2MUp1ZjRLTWw2SjJOZlFMMXpvODkwa0tyZ0RiS29HMGp1NFVZSnpxVFpvd3ZHYmZyaDc2K2x6RVRXRE1Bdk1seXRJajRqOWQrQklRdm9TOVNrcmh1eUxoeEpqWnhWa3F3Y0NwbS9PNlZjcjIrbkxvQjJxL216UitwUE9ZK3pDNHA3NkZmZ1N5WmFlb2orUFVSTjRMaWc0QldVK3k5bEpaQkdWZzVGR2VERDdlbVJSYnpseUdoK3NSRVhiMlRaT0p4SnZmVnR3SGJ5MnoxSTZORHd0V3JmK3pSSytJMVdBQy9ZUkJvdmxVaGM1c3ZuUlNOWEN3NmNaU3QxTFdUNmQ0VUVSeWYzT0FXb3hsYzZGNVk4ZzNhaGxOMmRlM01zN0wwNnJaM251VytjWmROMXZaSTdORVAxY0xhaGlZbURFR0cwcnJENzExSEFXQ2t3a2NCQkJJSFVqMFVldkY1SGpqVERXOVloTHY0Rk1GYkI3by8vSklVQUFBQUFTVVZPUks1Q1lJSSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wNy0wOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjItMDctMDgifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIzZTFiNjZjYmM4ODYwNWFkYmIzNGUwYTJkNmI4NmU4ODYyYzU2NjI3Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjNlMWI2NmNiYzg4NjA1YWRiYjM0ZTBhMmQ2Yjg2ZTg4NjJjNTY2MjciXSwiZGVzY3JpcHRpb24iOiJPQ1RBVENPIEV6RmluZ2VyMiBVMkYgQVVUSEVOVElDQVRPUiIsImFsdGVybmF0aXZlRGVzY3JpcHRpb25zIjp7ImtvLUtSIjoi7Jil7YOA7L2UIOydtOyngO2VkeqxsDIgVTJGIOyduOymneq4sCBWIDEuMCIsImVuLVVTIjoiT0NUQVRDTyBFekZpbmdlcjIgVTJGIEFVVEhFTlRJQ0FUT1IgViAxLjAifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlEdERDQ0FweWdBd0lCQWdJQkFUQU5CZ2txaGtpRzl3MEJBUXNGQURCeU1Rc3dDUVlEVlFRR0V3SkxVakVaTUJjR0ExVUVDZ3dRVDBOVVFWUkRUeUJEVHk0c0lFeFVSREVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVrTUNJR0ExVUVBd3diVDBOVVFWUkRUeUJTYjI5MElFTkJJRU5sY25ScFptbGpZWFJsTUI0WERUSXdNREl4TVRBME1qWXdNMW9YRFRJMk1ESXdPVEEwTWpZd00xb3djakVMTUFrR0ExVUVCaE1DUzFJeEdUQVhCZ05WQkFvTUVFOURWRUZVUTA4Z1EwOHVMQ0JNVkVReElqQWdCZ05WQkFzTUdVRjFkR2hsYm5ScFkyRjBiM0lnUVhSMFpYTjBZWFJwYjI0eEpEQWlCZ05WQkFNTUcwOURWRUZVUTA4Z1VtOXZkQ0JEUVNCRFpYSjBhV1pwWTJGMFpUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUxaWWErOVlaTEpuNEZXY2tEblkvRVJvQ3VPM1RCdGEwVzNmOFI5U1k1ZDVzQmsyUWl1cGNpSS9sN2Z3UHJIM0ZEa2VWUFhlak1lK2tUMFZvSkplK045RU1XZXIwLzVQWElQOTducnVZY3IwRHhiaFpwZXNRRWVVOEJlSVV1bnBOTm5FSnBveG9KVHdvRG11ODNaS2s0bThnMC9QZnBKd0RobVBDQXFtNzlzRnRQOGc3bEM5cW1zNVRELzZQTnorMmFld0tYVFFBUjFvcGZobldEVXNJWnR1VWZFUmhsR3d4VTdYK2gzb1Eya1NHdzVob2xmS1NiMGczcHdHVGNUVk52ZlVNWEg3Q2FpVHEvSzdUL2pkQUNEKzlhTmp0Y2QzUHlRZXJBOFNhMk4yOHJ2a044WWZLb0RQZzVnQTM3OE9ORFYzQmhyaHRZOFVpRGtCY1RzWEFRRUNBd0VBQWFOVk1GTXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVT0NtSzMxMEd1M3E5RGZYL2J2ZHBzZjRHSThVd0N3WURWUjBQQkFRREFnSDJNQkVHQ1dDR1NBR0crRUlCQVFRRUF3SUFCekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBbkRUY1puZUsvaDBRYjhzRnhnRlM4RmE1ZGpRblNKUVVNRlova3pPc1BoMURWRkRGNG5ERy9IbFUrZDdLYU5oYVE3WEx0N3hBamh6RXlUeUhhTUg3NmdIMDhyMzNOZFZaLzRzTWg5R0lMVTZiU21KWU90ZFZpM3pCM3A2OWJuWVpISlZxdkpLWDVsRXNTcG4vb3BLWWx2dG8ybjAvNHM0YXdKaCtxK0JreVZTUFRSTVg2TGZibjZJUnU0Y2JlUzBXMTN0c1E1U2JwQW85TkgyRkFUelZNTUtTR0VkaVFuZll5Z2RXdnVEQ0xVdFFGMXdHbUdTWXNFUEZUVjZQRzFWUDVIUzRmaHJCTmJ1cmkzOE5JVW9jZmtwZm1PSXkraEhaZ2Z2cFp6b3JrMUd2RjNQWlJJdEpuVFR2NVVqcTBxRDhybnI4MXF3dkdsVENKSUJ0RVVtTndRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRWdBQUFCSUNBWUFBQUJWN2JOSEFBQVNWVWxFUVZSNDJ1MmJCMWhVNTlMSE1Xb1NyN2wrVnZhY3M0MW1UZFNyUm9OWUFDa0xpb29GU3hRN2dZaWlpS0pHRGRnVkxIUkVsbDJhcUlCaWplS05YZkZhWW1LTkhTbTdDeHBqOVB0aWpJVzU4NTV6RnBabEYxZEZZL3g0bjJlZXBTeTc1L3gyL2pQenpyeVltZFd1MmxXN2FsZnRxbDIxcTNhOXcydURXbHBmZnQyN1VleUYrS2FyVGg1dXR2VEkxY2FoQndyL1oxN3V6VVp6YzA4MldyQi9ZOE9sZWJQTTF0K3dNMVBtZi96L0F3cEFIVE5sVWZzR3lUZlRXc1NmKzFXMDZoaFlMTm9IMW5PM2c4V01MQkJPVGdkcVFoSXdvK0pCUERRU3hJUFdBdTBWODZTSlgrYWxCa3RQekRaTHZXSCsvc0xKaExyMTAxUlRtcVhkZkNCS09nK1M2Sk1nRFRzTWxvdHlqUUtTOWc4SGlldFNFTnVIZ05CK0lUUVptMXBRTitybmtXYWg4TUY3NXpuMTBvdm5DcktMbm9zenJvSDRGUUNKYmVlQ3FOTk1hT0c0N05sSG9jY2p6VEl2ZmZqK0FGSVdkbTIycmVTaFpIc1J2QzRncHQwME1QL2kyK2NmcmppNzhMM3hwSTgyYW1Ja3VYZEJINUI0OVRIb0ZIVWMrc1lmaHdHeGg2RlBXQzYwRHNvQ3hqdWhXa0NNMVdSbzBpLzZEelA1clc3dkJhQi9aR21PV3Y3N2wzSkFyZEt2UVBEQjIzRHN1aG9LVkNWUXJDNEJsWnA3dkYyc2dVT1hDbURlaGp6bzRxc0VpV3laUVVDMFpETFVYM0phOFY0QWFwaFY4cjBXVVB1dEJmRHZheHJRYUVwZWFEL2RLSWFKc2Z0QjdMU29DaUNHOW9FRzAzYWZaelBqMzMyNTUycDJpdmZlaFJaYlZLQThaeG9jclJIUEdoVjdDRVE5NWxjQjlQRzA3eTc4N1FHVmxKU01QSFdyNUhtcm5ScjRaTE1LemhlVXZCUWdZb2V2cWNGeVJGeGxpVmxPZ2Zvcnp5YityZUVVRlJVMXdCczhTVzR5N2tjTi9ITmpNV3k2V081QlpXaVAwWDVIK3orMFA5Q2VHd0owRWFHMm5KYWxBOGdmR2c5TytOMHNzYURMdTNPM1hSTHFNNjRLTWVXbTdOcENwblFUeUpSZm1yc29mQVd5cE9ubXNxUWdnYXNpa0hKSjhzZXZ4d2hja2dhWXV5VDNtQnAyd1A3bWJSVzVlVkNqUmYrZ0JvZGRoWER5bG1hSFdsMDZSS1ZTdFM0dUxtNkdJSnVXbHBaYXE5VjMzRFNhMGpCOC9uVmRRS25uMVVDUFNLaEk4MjZyb2FYeXlvSy9URjRDMTlTR2xDejVVOHBWTVZiZ0lvK21uTllkcFJ4ak5GU3ZOUStwN2l2K3BMc3VMcU03aHdEZDZWczA4aGo2ak9xeStDSFZkZmxkeWpaY1E5bXRWVk85b2xWTW4valN0b05TeW5wTnpJTHhJWHRoaFNMdlQrZlZ4Nk1FMFQvbG1xKy9ZR2VXbVZuWDBQdmZ2WHYzbjJwMVNhQktVL3JyN2lzYXNGNXlrSTFCak8wOGFPVy9DV0pPM0lZaWpXYlcyeXgxNnpEOUUvN0Jlb1p6VWdMbG5IQ0p0bC83bUxGYkNzS3U4MEhZS1JpRUhXYUFzUDBNWURwOTg1VHV0bGd0NkI2MmxlNFpNWjkyakI1Q3V5UjkzdHdwcFJYeHNCWjlsWlM1VTZLZ1daOFVvZk9VYmUxemoxMitrYm5uSEN5WEgvOWQ2cGFVWWU2VWNJWHFxM3pBK085NEpGNjRmNGRreVg3dkppdU9TU3hDRDM3TVZzZkVsUG1OelpJTFhUdHR2SDVDT0hzWE1JTWlvZVgwYkFqSXVRaW5iM0VTeGRpMjVNMXpDUTM5Z0pFcE9wdkxsREdVOHpvMTQ3QWFQNm1GSVA1aUxvaTd6Z1p4bDJBUWRaa0Z3bTRoWlhTUHNJdVVVL3dpQXNQTUliU2VxVytCa2duaGIraVk5c05vSVpQYkNCd1RBc3hkNVVmb29lbFBSTjRiZ2ZiYmVybkovSDB4RGNKUHA5WmRkMjFmM1hWWDl6UmNmQ1RaSy9OeTdwWkxHc2hYVllwTFpTalIwVytNeTZkZW1SK2F1eVM1Q2x6bHViUno3Q09odzNJUTkvb1d4T2pHWXJ0NWJNMUJJQWw3TEg2Q0huS0ljbDN2VG1UM0t1OTE1ODZkVHhET2ozaFRsd0dndnY1MU5NY1BTTkJuZlliQVB1NkJlUi8wTGpmbFpLWi9Sbk50ZkVFUWcvU0ROcjVlTVlsYmJ3UU83WnJjQlFQcWJzWTE5cW5JYVFXSUhSZHlsV3B2Qk5SckFRdEoxRE1VNkQ0eCtaU0wzSXZjQk41WUhiUVAwT3JpeFRYRXdDcFNxOVZ0TUxCMlJBQ2Q4R2Z0aTRydTJPRDNndXZYcjM5RW5nYzZBUlNmWTRPZTlBUGU3Q2hqRWhjNEo5b0tla1Fjb3o1ZldVYjFTYmlLWHUxTlBCVmowWHc5UUkveC9VYlVPQmlSVE40VXdheWhaUWxQeERKdWp5TnhYZ3dTVXFYMlFVZ09vU3drb1dQWTg5YURVbkozSGJnbzAyZzA0OUZXNDBYdFJydUU5aHVmbnF1clc1NmhsYUNkUnR1RWZ4K0tZRHdSbmgxK25ZbzJWdCtUZERNbFpSKzNrRzYzNERIVmVUbFllaVNmM0o5MzlSZWQxNzczUnVBSW5KVzJLS2NmaGU3UklPbTdFcVR1eTlrOURndkpaUWxDV295UUZvSFFlUTBFaHU4dnl5OVEzY09MK2RNSWdJZjRxVjdEQzgxQnIxaUpOendGell0TDBScEgvTGtUbWdmK2JneCtQeHUvWG9lUFI4bmY4T243SWRwK0loM2ljZnF3Y25QUE5mUUl5RmtrN1loZWJEa1RiTndTSURyajFQT0NRdFZtNHJVMW5wMG9GNlVYSlpQL0p2Ymdkc2RTanpDUXNwQldnTlN0QXBMSVpUVjR6LzhPQ292VUJxRVFieUNCRWVYUzhzd1pJeDVRemNyUHY5OFlnWFJIVVBQd3RVN3hubmdITFE5L0ZvRkFZL0J4RzRsWCtIaG5YdFNoMjNUTDJjOFpnUjlRdHF1ZjRYM0VXemdvUDY1Uk9LU0lvOXprVDhTZWtTRHhYQVBTZ2F0QU9vQ0gxRThMQ1FPMGJDVjBIcFVCbDY4VlZzb1VYSERWVEw1MzcxNmptdTJmUVIwU3QvQzE0eEhNci9oZUJmajkzS0tpWDRUNHUzcms5dzZoQitzSkhPSjNNb3cvTU0wbkFmV3ZwWUFoWW1kVDkvUkdOUUlISzFvL3lsMytXRFFrbXUydFNBYXZCY2tnaE9TNW1vTlU3azByZ0pIRnd1cVUvK2pDS2NRTG5rQUt0amZiYUlRNnBJTG1ZaE83MVZBUldXb3psTUJkYVV0MVd2WW4wM1JDT1NSelYwVldDNGZZVDE0djVzZ1V6Z0szcEVkQ0w5emdEVWRBWHBGY0UzeElSQVVrNGsya0lkVXZIS3dIcHNBUEYvSjVPS1ZaeGNYM1JHKzNJd3NmNEFmU253UEVma0EvaysrN2UyVTJ3T3gyaHNCaElUVkRTRjNEeTlDVElsLzV6UmpuVkFrQ3lxZTlFb0Q1TWc2RUkySVJVZ3lJaDBWVlFFSnYwa0lTZTBRQTJRcmNMbEE5UmUwdkpTNytGKzc4TFJIT09XMDJ4T3VSZHhpUnNaMldUT2NBRVRQM0JkekdQRVZJdzE4dDdyZ29GSlNuSEdqdkJLQkh4WE9RUm5LUVJNTjRiK0loRVc4U2VVU0I4OWRieXdxTFM5YjhsWEIwYXlZKzQ3RWVIYmpxd0JQYUpyZ0NFQnB0TVFOd1Ezd0xpOWVYR3dPUmJZUEFYZkdZOGtaQVl4TTVTS1BYc1Uxd1ppVHhKaTBrM3BzR1I0Qm9RRFJZRFV3dDhGLzJmYk4zcFhHQWNjZ2U0VHdoZ0NhRzVnSnRqYnY0WmhXQW1HWVRVV3BoUUxrbWhiN1V2Z29EV0RJMVZNRk9CcWp4UEtReDZ5c2dsVXRPRjFJVXlRNi9NMjVKcmQrZEtSRjhRQUwzcmRzcXNCdWZDWXdJTTVrNXhxSG1FOHRCRWRrSm5PV0ZqRU5DYzlPOHAzOUNjN3pSTy9TNFpLQW5LY3NoVVZwSUJpVVh4VXFPZGsvRTdLQU1lY2M2a1U1YjlsMTR3dlNPQW9iNUNoaktoNFBVZ29lRVhpVG9HVlZHNmp5VFhwQzBLaWdQSlRCZnBRTDlGUTlwb29LRE5BNGhqVjFmU1hJRUVpczU5Q2FoWnh6eG9qdm03c25XN3dxZzJNeFRsTjI0emZmcGRuT0FFWDdGUWFJUmtvQ0gxSHdDVU8wWGt1dE9NdWtGY1hlK2dCNlNETUt2MDRIeFMwVlFLVUQ3SkNNazNwdkc2WGdUUXFMMUpFZDdyTWZBcHpoWVE0WFk2eTJ2ekxwazMwalpocFV4Rmw4REkvRkRtZm5xUVpvRXRNMHNCSlIwenFUWHBKQWtNeklWUlA0WjdJU1M4VXNEeHBlRHhFbE9VVGt1NlVsT09Dd0dxTDZKR1BpVTJZMGRsSTMveXRZdStiQ3BYcEhQbUZZQjNBUkRDMG5zeTNrVGdZU1NvNlVCeElNZW1OUWM3KzJUZlU0NE9nM0VVemVDYUFxQnRBRzlpVUF5SXJreE9wTFRRaG9lQzFTL1JIeFQ1VW5LWGRIdWJiTWhBUmZmTzUzcXRmWTUweFpybjFaVGdMSHg1eUJaSWlRcEQwbnJUZEtweElQS1RBbG9mY2FIN0gwcUhKME8wbW1iUVJ5d2lZUGt2OEdBNUJRR0phZWI1ZWlCQ1lEN3VIdVVpeUtZdEVuZU5CaXlDYVZrU2NNd0sxMmpiWmVDOExOQVlOcE9BNmJOVklTRVpvT2dyQkdVcFk0M0VVaVcwNGdIL1dGSzNSQStKL0l3M2x3YVdBUm1nWFQ2WnBBUVNNU2JDQ1NEa3FzbXl5RWs0ZEE0b1BzbGtyTCtHbHFBMENtbEdTbEVhN1JIMVQyekFlNFpoMkRSZDV5MmozZ203REtQNjMwaklPR24wM2xJQVJ5a2xqd2tyZVRRbStnMndRVFFUUk1BbGVRcGM4NEM0NWtDbGtIWllEbURRTW9FQ2V0TkZaSmplTWt4UGkrUW5EYkxZU2tnSElvZTVaRUFsRnZTQTNUbmphVEVwOXlVRnE4S0M2WGJ3dHhaSWNPRUVDMXdYbDlNTzZ3RjBSY0wyTjQzR2V1SS9oWEVEd2c0U0VJeUIydUxrRnJ6a0ZqSitiT1E2RTVzRnR0cUNxQzdaM0d6S2UyZkFsYUJXOEJxNWhhRWxJM2VwSVhFU1U2a0x6a3RKRlp5aVVZa3g1VUNvcUdrSEVCWS9STEtLRGY1YndqclBDYUdGTHpBdVFSYWN4ZUZQWHBEUnpMZElDWndsWCtHaGFzZDFsZWViTnZGUlJsUHVjcnpLT2QxdjlCOUlwOEpleThEVWZjRjNJQ2cyMndRZjg0TkNFU2RlVWdkZ3poSW54RkkwemxJNVpMelo3Mko2aGtCWkJabkNxQm5SY1VhR0JpNEE2UVRONEZOY0E0SENiM0pZb1l4eWFWV1NHNmlvcXJrZENHTjVLdnY4ZzB2bW1ja2JsT2lRT2lCWHRZM0ZoaDNmSzRibGcreWRXVzBMTDZNZG8wRHhqVUdHSmNvdGxNcGNsb0pJc2NsSU80ZFVubEEwUDBiSHRLY2lrbEtaOTZiT2dZWmxoenhwclpCV0VrbjNpY1RFbE1BUFNYN2xnMjd6dUdubkFyV3MzSllTTmF6dG9LVnZ1U3F5M0lUWHBEbFJsUlUzMVY3VEZ6N1JOcFAyN0UwM05abGU5LzJQS1NlM0pDQWhjUk9VbmhJV20rcVJuS1U3WEpvNjdWaHA0bWJPNjZQUXJ6STFUOEhKSk15d1diTzlncElyT1N5V01sSmRlT1NWbksrMml4WFdYSlZON3dWMWJkMkx5Y3gwR1BTYmV0S2ROcTZaRWpBUWpJd1NlSEdUZDhZbFp5bzQ0eHl5VEVkZ3NFU2R3MGJkNStMTkJYUWZtMTdZTS9objhGeWNCcFl6dHdHMWdUUzdHMWdvNFVVbEYwT3lXQ1cwNVlDazVRdkxBWFl1R1NreDFTMXJZdVFaQldRMkVtS1k4VWtwUktrS3BLYlZTNDVOaTUxQ0FLNmR3VE1qemtDeGNWcVAxT25sOS9xTnRsWEtQS0FHWm9PVm5OMmdQWGNIUndrUTVKRFNCV1NTeS9QY3ZyVk40RkV2V0REcTl0anF0VFc3Y2UxZFExTGJxRVJ5ZkhEeTI0Nmt1TWgwWFlyb0cvQU5pZ29WRC9EK3U4elUvc25YZm1lTGd1SVRDWjhGdTBEMGFpTllEVjNKMWgvczZPeTVJSTR5VWtEOVVvQmZ6NHUrWkc0VkRYTEdaV2NUbzlKTXJnNnlTMnZJamtKSzduUUNzbjExSmZjbkhMSkNlMFdnKzNZVFhEbS9DMjhUODFac29Nd3RYOVNEOEVjMHZVaTBrdnhucjhIaEtNeXdHb2VnYlNUZzRUZVZCR1hzblhpRXBGY1JxVXNSK3RYMzZiMm1OaTR0TFlxSkdPUzA4WWxCMjFjcXBybGhEMlhRcWVSRytENER6ZjQyWHpKOUpjcXdOVHFVcGsybTJrdHYwQUZBU3YzWThHM0FTeG5vOXdJS0FPU3N5alBjcnprakc1NGs2cG1PZDBOcjY3a2h1cElUaHVYV01tdDFKSGNVaDNKTFVKUWhpWEgySWVEZzA4V25QenBwdmJlOGw5NkZFVW1sQmlMTXZXSGZzV1kyVllxVG9ETmlBeUVrTU41MDF3amtxdXUramJZWTBvMDJtUFNiZXRXS1FVOGpKUUNlcElUOVY2SU5WUTBxNFNMVndxMDkvUVVuY0g3bGZZMjVGQUJtV2taR2hubkhyMENqbjViUURSdU13WnZuYmlrSzdrZ0k1TDdXamZMS1N2MW1HcENjaElEV1U3b0ZBNXRCaVhEMnJTVG9GSnBkRTkycEJ1ZDdac1lzQjM1YVdVVlNFUnl5K1I1ME41N0UwaDhzNnRtdVpsYmRhcHZBMW5PejNDV28wMW82NWFYQXBVa0YxWWhPVGZPbThTdTRXRFJMd0VtaE83bGczR2xlemhWVUZEUTVMV25sZVF3QWI3WUkyTW5NSDY4bUEvQkVZZWdEV1k1aVU4bVdBVVRUNnBHY2xQMXNweXZYcFo3WWZVZHJWTjlWNVdjQkVzQnNUditETUVNbTcwTHZqdDhHVlRxS3NlRkw1V1dsbHJWV0N1Qm5KNUFkN3hmM1ZFVm91dVZXRFAxOE1rR01XWTdDLzlzTENwempHYzVReHRldlI1VGxWSkFaOE9yTHpueGdBamN4OFZBTzY4VW1MTGllemh3NGhwNzJOUEF0WjRpUThVYWIwU1IweFJralB1aWM4aTNVWHJmWVFVZXVPb0FkRWRZVnQ0YlFlcXpHU3luWm9GbFlIVWJYc05aampiUyt4WjZvUTFDRzdBT09veE1nMUh6ZGtQUzFyTnc5VVlSWU5vMmN0WklzK1cxWmZXQ1NTWEZaN2VucGh6YUp2WFR3ZjljZ3pXcEoyRnN5RjdvTmpFVExFYWtnMlQwQmd6d2FKUFFpM3dSa0o5Mkg1ZkdUVklta2E0QVFocVAzdVNOa3ZzU2JaZ2NtQ0Z5ekdSSjBIWjRHbmdHYlllUXVLT3c3ZnVMK2lkSkROa0RjdEkxUC84dC9MY2hQNGdiaXFDdXZPd3BkMkxrWmtnV1ZPU2N4U0IvSEdhc1BvaEJOQmVHejlrTmcyYnVoSUZCTy9EbWQ0Qlg4QzRZczJBUEs1ZVErS01RdCtrMDVDQU1jakNpV0dYeXZ5Q1FFMnE3M3NCaEtkTU9NWkhqSlhnQnQxOEZsQ0VqTVlQSXc0aEVYc2FJaCtmaDlmVjlyVFJlUTdQdkZoajBBdmo0OUx5bVlMMEdtTjNrMkI0NUFQb3VUWGVKOU9xU2d3TGttQW52VldWdkNjb1RsUHNadEFYa1NKL1p1NzVJN1hULy92M0dxUHZlNUFRN1h2Z1IvcVRxa3hvQ1F2NWY0elozOEpNOTlObnVyUVRmTnkxRHRHNWszME1PVnFGbGNPQTBWL25EbDQ5MDVFbGs4cjk4Wi9NOFBuY2Y4VW9FTW9jY0FTWkF5UGxxczlwVnUycFg3YXBkdGF0MjFhN2E5VWJYZndGdlVFRUg0WWFxbEFBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMi0wNCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRXpmaW5nZXIgRklETyBVMkYiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDIxMDIwNDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDItMDQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA4LTA1In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNDcyNjhlYTEzZDVlMzNkZGJiYjRhZTAwMGMxM2M5NDc4Y2QxNzNhZiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI0NzI2OGVhMTNkNWUzM2RkYmJiNGFlMDAwYzEzYzk0NzhjZDE3M2FmIl0sImRlc2NyaXB0aW9uIjoiWlRQYXNzIENhcmQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6Mn1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1Z6Q0NBZjJnQXdJQkFnSUpBSk1jOFcxSU9TTmhNQW9HQ0NxR1NNNDlCQU1DTUlHR01Rc3dDUVlEVlFRR0V3SlZVekVSTUE4R0ExVUVDQXdJVm1seVoybHVhV0V4RURBT0JnTlZCQWNNQjBGemFHSjFjbTR4RlRBVEJnTlZCQW9NREZwVVVHRnpjeXdnU1c1akxqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRVhNQlVHQTFVRUF3d09XbFJRWVhOeklGSnZiM1FnUTBFd0lCY05Nak13T1RFME1UQTFOVEEyV2hnUE1qQTFNekE1TURZeE1EVTFNRFphTUlHR01Rc3dDUVlEVlFRR0V3SlZVekVSTUE4R0ExVUVDQXdJVm1seVoybHVhV0V4RURBT0JnTlZCQWNNQjBGemFHSjFjbTR4RlRBVEJnTlZCQW9NREZwVVVHRnpjeXdnU1c1akxqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRVhNQlVHQTFVRUF3d09XbFJRWVhOeklGSnZiM1FnUTBFd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTSis2MUxKZjk2MC8wQ3p2amRTMU11ZWtOLzMvTjVEWHg4UStOTHQ2b2g5TmRPREFUVHlqUkNDODBlbkM2cnlSUXJQMWpFZUFUdG1LSnFQVEpwQUdaem8xQXdUakFkQmdOVkhRNEVGZ1FVbFE2OENqelJreTJ4Y0JML2M0N3pwNmpRK0xNd0h3WURWUjBqQkJnd0ZvQVVsUTY4Q2p6Umt5MnhjQkwvYzQ3enA2alErTE13REFZRFZSMFRCQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQmJIYUF5OVU2RlJMbkp1bEhQNzZkRjdWaXNLN0hDMFNwS0R2clY5THRqVUFJaEFMWktzSTVNWFJ5MkMyZjkxWGFJaGZPd01CZUo1UExoV1JrY2R5YlcwcjZNIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBdGhKUkVGVWVOcnNsdDlMazFFWXg3L3ZOdGUwdlhPazd5UzdxeVdCWXZuaklrdEdVMHZEQ3drdFY0S1hwdjN3Qi80QkJpSWEvUUMxd2prVlV4TnNVdXV1emQxazZpQkxDeElGemNEWE9UWndZOHIyc3IxcnA0dVhadW9nZ3J5SmZTOGVlTDZjNTN3NDUrRTVISW9RZ29PVUNBZXNHQ0FHaUFFQXlYNkxaZG4xOVhXR1lkUnE5VDhna04xcWEyMFZEbFZaY1pVUVlwdVpLUzB0SFRjYTl5d3o2SHVycTZzL3pzNlNQMmtYd0dJMkF6aktxSFE2M2Z0M2s0U1Fwb1lHQU1XRlJYdktMbW9MQUF3T0RQd2RvTGRIRDJCa2FPaDM4NDNKNUhLNTlwVFYxZHdFOEdwOGZQK09TNHRMNXJmbUg2R1FrTzcwb0x1emMyand1U29wMmRCck9DeW5rNUtPOVBYM1oyWmtNQ2twcXl2ZkdJWUJjTCs5dzJxZEtDb3FDZ1FDQUhpZUYyb2ZQM3hrTXIxVzBJcmF1bHB0UVlIUDd3TkY3ZTJCTmw4RElPMzRDUUFOZCt1N3U3b0FTRUFCcUt1cEpZUlU2YTREb0dYeHFhb1VwWndXQTlhSkNVSkk0UVV0Z0ZQcWt3blNRd0Q2OVByb1Z4UU1CdHZiMmlpS2V0RFJ3Zk44S0JUaU9PN1prNmNBK25vTkxNc0N5TW84emZuOUhNZmxuTWtDc0xTNE9EMDFEVUIzOVJvaHhPbDB5aE1TNGlpUjNXNlBiTHN6QjNGeGNiUkNRUWhSSkNaS0pCS3hXQ3lUeWVSeUdvQlVLdjB5L3htQVRsY3BpNCtYeVdRYWpRYUF6K2VibXB3RVVGNVJEa0NsVWhWcUMzZ1NucCtiaXo0SG5OOFB3Ty8zUjV4QWdNdk56azVta2tXVUNNRHE2bmZCZHpnMkJEQ3RVQUJ3T2wyL2ZJZEFpZzRJQm9PUktJam5lUVZOYjNtM2lpK1hpRUhwK3d6cEdlbHV0L3VsMFFnZ0VBaVVYU203ZGVmMnZaYVd0TFMwaFlXdkgrWSs1Wi9OeThuTmpmNVVTQ1NTU0l3NDRYRFk0ZGhRS3BYRHc4TmlpcXB2YkJ3ZGVWRjFvd29BdTdhV21uck0wS1BmM3Q2K1ZGTGMxTng4UHUvYzZOaVlTQ1NLUHNrZXQyZDVlZG5qOFVRY3I5ZHJYN2U3M1p0Q3lySnJWcXMxSEE0VFFwWlhWcnhlcitDN045MFdpOFZtcyswZkN5cjJxNGdCWW9EL0FQQnpBSTZWTnFHUVBVcW5BQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTI0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMS0yNCJ9LHsiYWFndWlkIjoiNThiNDRkMGItMGE3Yy1mMzNhLWZkNDgtZjcxNTNjODcxMzUyIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI1OGI0NGQwYi0wYTdjLWYzM2EtZmQ0OC1mNzE1M2M4NzEzNTIiLCJkZXNjcmlwdGlvbiI6IkxlZGdlciBOYW5vIFMgUGx1cyBGSURPMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEwNTAwLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJzZWNwMjU2azFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjozLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjMsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6WyJhbnkiLCJoYXJkd2FyZSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQmdUQ0NBU2NDRkJsbzBzNVFZRmRYYmZ1c1JkUWVvTFg2UWVubE1Bb0dDQ3FHU000OUJBTUNNRU14Q3pBSkJnTlZCQVlUQWtaU01ROHdEUVlEVlFRS0RBWk1aV1JuWlhJeEl6QWhCZ05WQkFNTUdreGxaR2RsY2lCR1NVUlBJRUYwZEdWemRHRjBhVzl1SUVOQk1CNFhEVEl6TURJeU16RXdNek13T0ZvWERUTXpNREl5TURFd016TXdPRm93UXpFTE1Ba0dBMVVFQmhNQ1JsSXhEekFOQmdOVkJBb01Ca3hsWkdkbGNqRWpNQ0VHQTFVRUF3d2FUR1ZrWjJWeUlFWkpSRThnUVhSMFpYTjBZWFJwYjI0Z1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBVEs3blh5SDRwZ04zVE13Q1dTb01EUmU0RVY4SmwzWHp1aGljWi8yZ3ZoK3p6M1dtVzBPWi9FY1JZRUE4RjI2Y2VldU1jZDIxV1FSUktXcGpXRCtKV2lNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUN3Y3NIdUw4WkZMM0ZOeVUvRE9RbjNibXgwOGxubjBPNVJrdExiT25vUEhRSWdPRWk2SW1BWjE4MXE4UkppTDBoYnc3WnF1dW5pUnE2ZmpXakdvQnUxTW9vPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFTWUFBQUVBQ0FZQUFBQWVNZHZ4QUFBQUFYTlNSMElBcnM0YzZRQUFBSVJsV0VsbVRVMEFLZ0FBQUFnQUJRRVNBQU1BQUFBQkFBRUFBQUVhQUFVQUFBQUJBQUFBU2dFYkFBVUFBQUFCQUFBQVVnRW9BQU1BQUFBQkFBSUFBSWRwQUFRQUFBQUJBQUFBV2dBQUFBQUFBQUVzQUFBQUFRQUFBU3dBQUFBQkFBT2dBUUFEQUFBQUFRQUJBQUNnQWdBRUFBQUFBUUFBQVNhZ0F3QUVBQUFBQVFBQUFRQUFBQUFBZTZTQ2t3QUFBQWx3U0ZsekFBQXVJd0FBTGlNQmVLVS9kZ0FBQVZscFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWxoTlVDQkRiM0psSURZdU1DNHdJajRLSUNBZ1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNEtJQ0FnSUNBZ1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSUtJQ0FnSUNBZ0lDQWdJQ0FnZUcxc2JuTTZkR2xtWmowaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTBhV1ptTHpFdU1DOGlQZ29nSUNBZ0lDQWdJQ0E4ZEdsbVpqcFBjbWxsYm5SaGRHbHZiajR4UEM5MGFXWm1Pazl5YVdWdWRHRjBhVzl1UGdvZ0lDQWdJQ0E4TDNKa1pqcEVaWE5qY21sd2RHbHZiajRLSUNBZ1BDOXlaR1k2VWtSR1BnbzhMM2c2ZUcxd2JXVjBZVDRLR1Y3aEJ3QUFENjVKUkVGVWVBSHQzTHVPSkdjVkIvQmQ5bUlITmhMaUloT1FPRWFDQ0RraUlDTkc0ZzM4Q2p3SkNRbENCQVNJQk42Q2hBZ0pKRVJpSkF2WkFveXhmRm52aGUvczlKRnFlM3RtdWs5L3A2ZDY1MWZTTjFWZFZlZFV6YTlxL2wyOTlzeWRPM2Z1dkQvR3N6R2ViT2F4Ykt6WDROSG0rdnhxekdONmNESHpkU0Z3ZjdQODh6R1Blem5OM05mcnZhL2oyanpkWEs5UHZ6SVdUQVFJRUZpVmdHQmExZVZ3TWdRSWhJQmdjaDhRSUxBNkFjRzB1a3ZpaEFnUUVFenVBUUlFVmljZ21GWjNTWndRQVFLQ3lUMUFnTURxQkFUVDZpNkpFeUpBUURDNUJ3Z1FXSjJBWUZyZEpYRkNCQWdJSnZjQUFRS3JFeEJNcTdza1RvZ0FBY0hrSHJndEF2RkxvcVl6RVJCTVozS2hGcWQ1ZDdPYzg4VW1pNWNJaEJXdlMzRFd1RHIvUE1ReDUrYWQ2Qmk5dzJ2VE8rZUhkN2c5RldtVWYwN2o5bnpuTi8rZEh2VkdFTVh4OTVpK1BVWmN2SDJmb1BLQ1IvMVB4L2pqR0crT0VYL1Q2YWdUR3ZXbXF3WEMvdDRZL3hranJsMTQ1L1VZaTZZaGtDWnZqZVZ2alBGNHMyN01URTBDY1EvR2c4N0hZM3gvak4rUEVWT3MzemNUY3QvUFpqd3gvV1VjK0wwNEE5UEpCZklIOE9RSFh2a0I4d2IvNXpqUEdLYlRDanc4OW5Bemd1bU56VW5FeWNRVGs2bGZJQUlwbm5Cam1IWUxSRGpGSjRBWXNXenFGNGkvcHZyNUdKa0o1U1BPQ0tZTW81am5jdm1FRkJLWUtDQzhKMkx1MFNvL3NzVkg1Nk9tZmY5TjZhaURLQ1pBNEZZSlpFQ1Z2Mm5CVktaVFNJQkFsNEJnNnBMVmx3Q0Jzb0JnS3RNcEpFQ2dTMEF3ZGNucVM0QkFXVUF3bGVrVUVpRFFKU0NZdW1UMUpVQ2dMQ0NZeW5RS0NSRG9FaEJNWGJMNkVpQlFGaEJNWlRxRkJBaDBDUWltTGxsOUNSQW9Dd2ltTXAxQ0FnUzZCQVJUbDZ5K0JBaVVCUVJUbVU0aEFRSmRBb0twUzFaZkFnVEtBb0twVEtlUUFJRXVBY0hVSmFzdkFRSmxBY0ZVcGxOSWdFQ1hnR0Rxa3RXWEFJR3lnR0FxMHlra1FLQkxRREIxeWVwTGdFQlpRRENWNlJRU0lOQWxJSmk2WlBVbFFLQXNJSmpLZEFvSkVPZ1NFRXhkc3ZvU0lGQVdFRXhsT29VRUNIUUpDS1l1V1gwSkVDZ0xDS1l5blVJQ0JMb0VCRk9Yckw0RUNKUUZCRk9aVGlFQkFsMENncWxMVmw4Q0JNb0NncWxNcDVBQWdTNEJ3ZFFscXk4QkFtVUJ3VlNtVTBpQVFKZUFZT3FTMVpjQWdiS0FZQ3JUS1NSQW9FdEFNSFhKNmt1QVFGbEFNSlhwRkJJZzBDVWdtTHBrOVNWQW9Dd2dtTXAwQ2drUTZCSVFURjJ5K2hJZ1VCWVFUR1U2aFFRSWRBa0lwaTVaZlFrUUtBc0lwaktkUWdJRXVnUUVVNWVzdmdRSWxBVUVVNWxPSVFFQ1hRS0NxVXRXWHdJRXlnS0NxVXlua0FDQkxnSEIxQ1dyTHdFQ1pRSEJWS1pUU0lCQWw4RDkwZmpMVGZOSFkzNXZqR2ViMTNkM0xDL1h4VzRQRi92RWE5UHBCT0phUEJnanI5Y2hSODdybU5mK2tGcjdFcmhPSU83SnZMZnkvc3g3TG1xWHk4dlhzZS96VElvdjM0d3RZM3I5WW5idzEvamhNSjFXSUM5c3ZKbVlDS3hGSU83TG1DSlhqc21GcjBhRFg0OFI0UlEzK2I0ZjdUSUY0K0FmakJGVHJydDQ1V3VYUUliU3Q4WUJmanpHNDhXQmNsdXN5cHRrZVYxeWUxejMvNDd4aHpHZWptRWlNRU1nNzZWL2oyYS8zVFNNK3kvdnhldU9FZnRHQm4xeDNZNzdidC8zd1B2MnM5L2xBdkZ4TzZZZmpSRVhzam8rSExYeFVUd20xKy9Dd2RmakJhYmNTL0hPR1FsMVRMTkl5ZmpoTUoxV0lKK1U0ck44WEw5OXIyRmNyM2pTL1dnTTEyMGdtS1lLNUQyVmI2Q1Y1czhpbVBJZHQ5SWdhdkpFcXZYcWpoT0lHMkRmVUZydXQrL0g5dVBPVHZWdEZjaVBkYVh2UDRPcFZLeG9WUUxMMExucXhISy9uRisxcjIwRXFnSkhQYkI0MTZ5eXF5TkFvRTFBTUxYUmFreUFRRlZBTUZYbDFCRWcwQ1lnbU5wb05TWkFvQ29nbUtweTZnZ1FhQk1RVEcyMEdoTWdVQlVRVEZVNWRRUUl0QWtJcGpaYWpRa1FxQW9JcHFxY09nSUUyZ1FFVXh1dHhnUUlWQVVFVTFWT0hRRUNiUUtDcVkxV1l3SUVxZ0tDcVNxbmpnQ0JOZ0hCMUVhck1RRUNWUUhCVkpWVFI0QkFtNEJnYXFQVm1BQ0Jxb0JncXNxcEkwQ2dUVUF3dGRGcVRJQkFWVUF3VmVYVUVTRFFKaUNZMm1nMUprQ2dLaUNZcW5McUNCQm9FeEJNYmJRYUV5QlFGUkJNVlRsMUJBaTBDUWltTmxxTkNSQ29DZ2ltcXB3NkFnVGFCQVJURzYzR0JBaFVCUVJUVlU0ZEFRSnRBb0twalZaakFnU3FBb0twS3FlT0FJRTJBY0hVUnFzeEFRSlZBY0ZVbFZOSGdFQ2JnR0JxbzlXWUFJR3FnR0NxeXFralFLQk5RREMxMFdwTWdFQlZRREJWNWRRUklOQW1JSmphYURVbVFLQXFJSmlxY3VvSUVHZ1RFRXh0dEJvVElGQVZFRXhWT1hVRUNMUUpDS1kyV28wSkVLZ0tDS2FxbkRvQ0JOb0VCRk1icmNZRUNGUUZCRk5WVGgwQkFtMENncW1OVm1NQ0JLb0NncWtxcDQ0QWdUWUJ3ZFJHcXpFQkFsVUJ3VlNWVTBlQVFKdUFZR3FqMVpnQWdhcUFZS3JLcVNOQW9FMUFNTFhSYWt5QVFGVkFNRlhsMUJFZzBDWWdtTnBvTlNaQW9Db2dtS3B5NmdnUWFCTVFURzIwR2hNZ1VCVVFURlU1ZFFRSXRBa0lwalphalFrUXFBb0lwcXFjT2dJRTJnUUVVeHV0eGdRSVZBVUVVMVZPSFFFQ2JRS0NxWTFXWXdJRXFnS0NxU3FuamdDQk5nSEIxRWFyTVFFQ1ZRSEJWSlZUUjRCQW00QmdhcVBWbUFDQnFvQmdxc3FwSTBDZ1RVQXd0ZEZxVElCQVZVQXdWZVhVRVNEUUppQ1kybWcxSmtDZ0tpQ1lxbkxxQ0JCb0V4Qk1iYlFhRXlCUUZSQk1WVGwxQkFpMENRaW1ObHFOQ1JDb0NnaW1xcHc2QWdUYUJBUlRHNjNHQkFoVUJRUlRWVTRkQVFKdEFvS3BqVlpqQWdTcUFvS3BLcWVPQUlFMkFjSFVScXN4QVFKVkFjRlVsVk5IZ0VDYmdHQnFvOVdZQUlHcWdHQ3F5cWtqUUtCTlFEQzEwV3BNZ0VCVlFEQlY1ZFFSSU5BbUlKamFhRFVtUUtBcUlKaXFjdW9JRUdnVEVFeHR0Qm9USUZBVkVFeFZPWFVFQ0xRSkNLWTJXbzBKRUtnS0NLYXFuRG9DQk5vRTdyZDExdmdjQk9MNlB4bmozaGpQenVHRUR6ekhwMlAvR0tZekV4Qk1aM2JCSnB4dUJsQUUwbWViZnEveUQrL2Q4VDNtOXp5QlQ0dFRDQWltVXlpdjZ4anhneHJUbTJQOFpJd3Z4NGlQOUsvU0QyOThMNitOOGFjeC9qNkdjQm9JSmdLZEF2R3hLNllmamhFL2dQSGtFMDg4c2J6dk9IVC9mZnV1YmIrZkRaT1lIbHpNZkQwWEFVOU01M0tsNXA1blBqVmxRT1hyQ0phWWRyMk9iY3NuajF6T2ZaOFg3dml5N0prOWNyZmNGcStYZlhLLzNMN2NsclU1WCs2VHk0L0h4bmhpK2lKM01qOHZBY0YwWHRkcjl0bkdEL3p5aDM2NUhNZGF2czdsbkc5dmo5ZTdwcXYyWDI1YjF1YjZuQyszYlM4djk4bmwvSy9OK1hxN3h1dVZDd2ltbFYrZzV0TjdWWDl3WDlYdnEvbDJXRS83ZkdkWnp4azVFd0xIQ2VUSHVlTzZxTDVSQWNGMG8vd08zaURnYWFrQjlkUXRCZE9weFIydlc4QVRVN2Z3Q2ZvTHBoTWdPOFJKQlR3eG5aUzc1MkNDcWNkVlZ3SUVqaEFRVEVmZ0tWMmxnSTl5cTd3c2g1MlVZRHJNeTk3ckYvQlJidjNYNk5vempQK1A2ZGdMNlIzcVd1YldIZmkveUJzZVRGNDB1WWxYUitXS0o2YWJ1R1E5eDh3Znhwem5VUzc3UWQzZUwvZVArWExiY2ptMzVickw1dGtydHgvNmVsa1h5OHZYMlN2bnkrMjVYODV6SC9NekU0Z25KaGZ4ekM3YTVuVHpsM2x6bnQvRjlqdlY5dXZMOXN2MU1WL1dMSmN2MjViNzVEeDdWVjh2NjViTDJYYzVYMjdQNVllYkhmenk3bExxdE10SDVVcGN5TitOOGRZWWo4YUlKNmhER2thd3ZUdkdYemUxOFV1aHBsNkJ1R1p4amI0MnhnL0dpTDh1RUZQK1VGNjh1dDFmNHo2TVgrTDk4eGp2alpGbVk5SFVLQkJ2a25FL3ZqM0dMemZIT1NSUFl0L284WG5VZmp4R3JLaU9kNkxKbUxiZnVTL1crdG9oSUlUMlYyVzF2OVd4ZStZVDZ2ZEdvMnFlUEsrTEo1NlB4b2cvR3BaUFRHUHgyaW1LWTRvVGlUOHhZVHF0UVBqSEQ1dzNnNnZkNDhuSlUvelZSak8zWmk3RVUxTSt5ZWU2Zlk0VCswWW1mUkpmWXNRVTgzMy9NWHg1TU85SXovbE8vaVd1Z1RlRms3TTc0QjRDeXpmTnVFLzN6WWpjOS82K1FiVEh1ZGlGQUFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DZ2dtQ1ppYWtXQXdCd0J3VFRIVVJjQ0JDWUtDS2FKbUZvUklEQkhRREROY2RTRkFJR0pBb0pwSXFaV0JBak1FUkJNY3h4MUlVQmdvb0JnbW9pcEZRRUNjd1FFMHh4SFhRZ1FtQ2dnbUNaaWFrV0F3QndCd1RUSFVSY0NCQ1lLQ0thSm1Gb1JJREJIUURETmNkU0ZBSUdKQW9KcElxWldCQWpNRVJCTWN4eDFJVUJnb29CZ21vaXBGUUVDY3dRRTB4eEhYUWdRbUNnZ21DWmlha1dBd0J3QndUVEhVUmNDQkNZS0NLYUptRm9SSURCSFFERE5jZFNGQUlHSkFvSnBJcVpXQkFqTUVSQk1jeHgxSVVCZ29vQmdtb2lwRlFFQ2N3UUUweHhIWFFnUW1DaHdmMEt2RExkN0UzcHBzYi9BczdIcjAvMTN2NVY3eHIxNTkxWis1emZ6VFVlZVBCN2o2Q3lZRVV5ZmJBd2UzWXpGclQ1cS9OQkZRSmxlRmdnYndmMnlTK2VhSjV2bUh4OTdrQm5COU00NGlZZGp2REZHbkpoM3FJSFFPRVVRUFJqai9USCtOb1p3R2doYlU1cThQZFovWjR3dngzQmZiaUZOZmhuM1plVEovOGI0N296ZWNZTkgwd2lWbUJ2bllmQ2JjYTFpaXBBeXZTaVFiN2kvR0t2ZHorZGpFRSs0Y2IwK3pRdjQ0bVU5N0ZWZStNT3E3RjBSaUhmOWVQZVBKOVF2S2cxdVdVMys4MExNWjl6cnQ0eXYvTzNHZlhyVUUrcU1pNVVua1BQdDd5YUNLN2ZsY3N4aml2VzU3dm1LSFY5MmJjOTF5ejdMMHR3ZTY1YkwrWHE1Ynl4dm45LzI5bmlkeDRybDdmTmVIaU9YdCtmYlBlSjFUTXRqWDZ6WnZTNzN6ZjF6bmpYbUx3dWtVY3lYeTNsdG9pS1dZOHJ0eTIwWFcxNzh1dHcvOTgzNWNzL3RkZms2NTFmdG05dGkzNXppL1BMMXZ1ZWF0WWNjTTJ0eW5yVTV6L1V4MzdWdXViMjhQQ09ZNHVBSnRldEVsdHR5T2VmWDFWNjJQZXR6dm4zYzVmcmw4bVg5c241NzMxeS9xMjY1NzY3bFhKZnpYVDJ1Nm4vZC9zdGF5OWNMWEhZZGx1djNNVi91bjhzNVg1N0Y5cnA4bmZPcjlzMXQyL3RlOXpycnR1ZmJkYkY5MTdydHV1Vit1L2JmdFc1WGo0UFg1WC9xUDdoUUFRRUNCTG9FQkZPWHJMNEVDSlFGQkZPWlRpRUJBbDBDZ3FsTFZsOENCTW9DZ3FsTXA1QUFnUzRCd2RRbHF5OEJBbVVCd1ZTbVUwaUFRSmVBWU9xUzFaY0FnYktBWUNyVDNWaGgyLy9VZG1QZmtRTVQyQktJLy9NNy96UkV6cmQyOFhKbEF2SEwxbkhkNHRjQlRGY0xwRkhjMis3dnE2M1dzRFd1Vi93dHA2ZHhnNysrT2FOWnY1NnlhV2ZXSlBEYXBtLzhJcS9wYW9IOHl3dHBkdlhldHE1RjRQVUlvMzlzenViek1mZlJiaTJYNXZMemlMOFErUFV4UHR6c2trOEZsMWZjdmkxcDhxL3hyY2Q5L2NFWWNhLzdHRHdRVmp6bEU5T24vd2ViYTBWNVU2V0pxZ0FBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiLCJ0eEF1dGhTaW1wbGUiXSwiYWFndWlkIjoiNThiNDRkMGIwYTdjZjMzYWZkNDhmNzE1M2M4NzEzNTIiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEwMjQsInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA5LTE4In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wOS0xOCJ9LHsiYWFndWlkIjoiNDU0ZTUzNDYtNDk0NC00ZmZkLTZjOTMtOGU5MjY3MTkzZTliIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI0NTRlNTM0Ni00OTQ0LTRmZmQtNmM5My04ZTkyNjcxOTNlOWIiLCJkZXNjcmlwdGlvbiI6IkVuc3VyaXR5IEFVVEggQmlvUHJvIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjowLCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRENUQ0NBZkdnQXdJQkFnSUpBTEtLajBzS1RYRGxNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1DRXhIekFkQmdOVkJBTU1Ga1Z1YzNWeWFYUjVJRlJvYVc1RElGSnZiM1FnUTBFd0lCY05NVGd3TnpJek1UTXpOekl4V2hnUE1qQTJPREEzTVRBeE16TTNNakZhTUNFeEh6QWRCZ05WQkFNTUZrVnVjM1Z5YVhSNUlGUm9hVzVESUZKdmIzUWdRMEV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRREVpWmg0dEljQVVQZlVrQ21YYk53V0RJRnZXeHhHUGhKcS8vRnMzdVBCQTRKUVVYaUFIV1VvZjBtTnhmVTM5eWZLMzkvMnlYZ09KNVFvWkd6cFFFR1N3NVNub3kwKzYxb2VJKzBJWGtBYU12ZlZ2dG1Ob08yT0pPNStBRHRsRHU2cmdKdVY2SXBMTFI1U0tYT1Uxek9QSFlyQVBzWXh2M1VMZzI2VzYzek1UcXBDTkNnNHB6d1pSeVhqY0xyVWVDekY0WGNmK3AvRzQyWmRHekJlWmM0eit5Y2NPTXhCeDR3c0djUGcxSEZ5elhsM0ptdHlnN3pVREVxYmplSDhOc3k5K2tUMzFtVlhvY2lnQjNoRzd3Y3RpSW42QTVsUEdNUEpvSTg0UlpkckIzZXM5UWxIWldTbnZkSkdlYUxuTzVYcTRtSWh1ZmJZNHMxVXEvcHZHc0FQQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJTT0VuK1ZGaEkvWkdVVFNVZWhFeU9seHhGeEx6QVNCZ05WSFJNQkFmOEVDREFHQVFIL0FnRUFNQXNHQTFVZER3UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQXJhRG84dW1yZWpYTllRNkJSQm40WHNEZWhEbGlqM0xBTk03Sjd0aW1hTk1mb3hhZHd5UzFudkE4ZTdjTzdPQXczaWVsWWpPNm9pU3B6VXN1NmVIMmxvWjBMSzBma29pYVpabkhLYi80Nm82bzk5NDdpOHR1QU95b1ZyR1B3OWMyOVZvSVFrRTNRai8wUEpabVUwWXViaWxSVU54NmxkSzI1YTBvL3E4bGs3QkwzMk5qV2RUektESlBnZEttcndsMW0zSzJlR212MlpJZ0FQNHBXVW1nMERGNFhTL0phbmtGaWJSWmhzNktnMFYwMkU5UGNiR3lYSW8raHhVOVFzampnSVB0RmlGOCtWdlFiUFRWZU0xWmMwQ3hQbTFYeDIya2kzSWVQcGFEaWd6UzBLZnhrNVJuRnRxWS9aT3lWdGFtL29BUDl0cS9NVGpFUXUxZmxycHBSUT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUtnQUFBQ29DQVlBQUFCMFM2VzBBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBRnhHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnT1M0eExXTXdNREVnTnprdU1UUTJNamc1T1RjM055d2dNakF5TXk4d05pOHlOUzB5TXpvMU56b3hOQ0FnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenBrWXowaWFIUjBjRG92TDNCMWNtd3ViM0puTDJSakwyVnNaVzFsYm5Sekx6RXVNUzhpSUhodGJHNXpPbkJvYjNSdmMyaHZjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5d2FHOTBiM05vYjNBdk1TNHdMeUlnZUcxc2JuTTZlRzF3VFUwOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXRiUzhpSUhodGJHNXpPbk4wUlhaMFBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWRmRtVnVkQ01pSUhodGNEcERjbVZoZEc5eVZHOXZiRDBpUVdSdlltVWdVR2h2ZEc5emFHOXdJREkxTGpBZ0tFMWhZMmx1ZEc5emFDa2lJSGh0Y0RwRGNtVmhkR1ZFWVhSbFBTSXlNREkwTFRBekxUQTFWREUzT2pBME9qSXdLekExT2pNd0lpQjRiWEE2VFc5a2FXWjVSR0YwWlQwaU1qQXlOQzB3TXkwd05WUXhOem93TnpvMU1Tc3dOVG96TUNJZ2VHMXdPazFsZEdGa1lYUmhSR0YwWlQwaU1qQXlOQzB3TXkwd05WUXhOem93TnpvMU1Tc3dOVG96TUNJZ1pHTTZabTl5YldGMFBTSnBiV0ZuWlM5d2JtY2lJSEJvYjNSdmMyaHZjRHBEYjJ4dmNrMXZaR1U5SWpNaUlIaHRjRTFOT2tsdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNlptWTBPR1k0WkdVdFpEWXhPQzAwTWpoa0xUZ3dPR1l0TXpFM01EWTRPVE0zTnpGa0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09tTmlOR1l6TVdVeExUVmlabU10TkRFeE1TMDRNemRsTFdZNFpUazNPVFE1TkRZM1pTSWdlRzF3VFUwNlQzSnBaMmx1WVd4RWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09tTmlOR1l6TVdVeExUVmlabU10TkRFeE1TMDRNemRsTFdZNFpUazNPVFE1TkRZM1pTSStJRHg0YlhCTlRUcElhWE4wYjNKNVBpQThjbVJtT2xObGNUNGdQSEprWmpwc2FTQnpkRVYyZERwaFkzUnBiMjQ5SW1OeVpXRjBaV1FpSUhOMFJYWjBPbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2WTJJMFpqTXhaVEV0TldKbVl5MDBNVEV4TFRnek4yVXRaamhsT1RjNU5EazBOamRsSWlCemRFVjJkRHAzYUdWdVBTSXlNREkwTFRBekxUQTFWREUzT2pBME9qSXdLekExT2pNd0lpQnpkRVYyZERwemIyWjBkMkZ5WlVGblpXNTBQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdNalV1TUNBb1RXRmphVzUwYjNOb0tTSXZQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaWMyRjJaV1FpSUhOMFJYWjBPbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2Wm1ZME9HWTRaR1V0WkRZeE9DMDBNamhrTFRnd09HWXRNekUzTURZNE9UTTNOekZrSWlCemRFVjJkRHAzYUdWdVBTSXlNREkwTFRBekxUQTFWREUzT2pBM09qVXhLekExT2pNd0lpQnpkRVYyZERwemIyWjBkMkZ5WlVGblpXNTBQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdNalV1TUNBb1RXRmphVzUwYjNOb0tTSWdjM1JGZG5RNlkyaGhibWRsWkQwaUx5SXZQaUE4TDNKa1pqcFRaWEUrSUR3dmVHMXdUVTA2U0dsemRHOXllVDRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejdRaTRVZkFBQXJya2xFUVZSNG5PMjllWnhjVjNtbi81eHo3NjE5NlZXOXFDVlo2bFpMc2lTM0ZtUExPd3kyZzVlWVlSaWJtUUVUTWtuSUpKTU1qQVA1MllFZnpFd1NHd0lPTUFseE1wTUViRU5DTUpqeFlIQk1iQ3piV042dEZjbmFkMHZxcnU2dXJyM3Vjczc4VVl0YlVyZjJWbGQxOS9QNXROMnFxcjcxM2pyZmVzLzJudmNWV212cUdTSEVPZit0eitlNzZhNDc3L3hlVzN1Ymw4M21hdXFETUUwVEtZVC9wei85eWQvdjJyM25ubk85VHIyM3J6blpCa3dtdG0wdnZQTWpIMm02NVpaYk9Ianc0R1NiY3h5UlNJUkNzY2p6THp6Zk45bTJUQ2JUV3FCQU5Ka2M1dkRod3h3N2RteXliVG1PZERxTjR6aDRuZ2NnQVRYSkprMEswMTJncG1YNUNBU0QrUHoreWJibE9QeCtQMExLeWhqR0FvcVRiZE5rTUswRktxWFV1M2Z0SWhnSU1EUTBOTm5tSEljLzRFZDVDczl4TGVEY0I5cDF6clFXcU5hYVJZdDZ1Znp5eXhsT0ppZmJuT01JaDhQWXhTSStuODhQR0pOdHoyUXgzUVVxT2p0bjA5WFZSVk56ODJTYmN4eWhZQkRiY1RCTkUyWTg2UFNsVUN3QWtNdmxKdG1TNDVGU1Vpd1VLc3RFMDFhZ2NySU5tT0VVQ0VCTVgzSENqRUJybm1tdXp4bUJUbmNCMURyVFhxQzFqYWo4WjlwK2kyWUVXdXRNY3hjLzNRVmFCNDFmQnlaT0lOTmRvTExXMi84OGdyV21CTk5kb0RYZC9PWEI1OHdZZEJvamFucUlKMFQxUDVOdHltUXgzUVZxbkUvQTgwV2h4czJiYUthN1FHV3RDbFRya3U4VUNNazBsdWwwRjZoUnU3TVFEWWphTmU4aU1lMEZLbXRlQU5OYm90TmVvTFU4U1JKQ0lNVE1KR2s2WXdoWnV4K0JBSVNjRWVpMFJRcGgxR3JUYTAxcEVheFdaM0VYaVdrdFVDR0ZJVVd0ZmdTNjFNWFBySU5PWDZRUVppMDdLQ0hFVEJjLzJRWk1Ka0xJbWgyRGx0WkJCYUptUGZ6RllWcmZ2UkJDeXByMW9LVXVYczU0ME9tTGxNS1FOYndRS29SQUNqa2owT21LRUZJS1dadEh6clhXU0NHUXBTSElqRUNuSTFKS1dkTWVWRXFFRlBXZG51NDhtZFlDRlZKSVdiT1RKSTJRQWtNYU04RWkweFVwcFRDTTJ1M2lCUUxMNy9NRHZzbTJaN0tZM2dJVkVxTkd4NkJRY3BzKzB3b0F0WlY2N3lJeXJRWHE4MW4rVWc5YWUxUXlJNXVtNldkR29OTVMwKy8zeHd6RHBCWm5JUldCV3BZNTQwR25LYVpwbWlIVE5OQTFLTkdLUUEzRDlERXpTWnFXRkV6TGlwbW1oZkpxVDZBVkFzSGd6RUw5ZEVRSThiR1c1cGFGb05HNjl0Sy9WNzR5MFdnRUljUW5KdE9XeVdSYUNyU3BzZkYzWm5kMlBPcjMrd3dwRFpTcVBZRlM3dUtsa0VRajRkL3A2cHI5ZDVOczBhUXc3UVE2cTdYMU0vUG5YL0pYV21zTXc4RHY5OWVrUUN0alVML2ZqK3U0ZExTMy9jZTVjK2Q4eHpDTWxrazI3YUl5YlFRYURvZlhMT3J0M1RSdjdweXZPSTVET3AxR2FVVW9GS3FVZXFrcEtnSVZVcEFyRkNnV2JXYTF0bjUweWVKRk81cWFHajgyeWVaZE5LWjhDdkNHaHZqdGpRME4veUVlai85N0tTWDVRZ0dsRktsMGh2ZGNjU1VCdjUraEdrdi9YVUVEVjExMU5YNmZSVEtaSkJhTFlacEc0L3g1OHg1dGJHaTRPem1TK3Y3ZzRPQ1U3dnBGdlpmS0d5c2kzakxOV0RRYXZiMmxwZm1UMFdqMEJpR2dVQ2lWR1hKZGw3ZTM3K0RmL3RzUDg0L2YreWVLeFFLNVhQNjhTaXBPRkZKS21ob2IrZktYdjhTOTk5N0h2TGx6aU1mamVKNVhxcU1rQk5sc2R0dlEwTkJmSjBkU2o5bTJmZVRFYTlSOSs5YjlEWlNGRlE2SFY4WGpzVHZDNGZETlBzdGFFdkQ3R3pSUUxKYUVhWm9tUjQ0Y29YOGd3YWMvOVNuKy9PdGZRMnNZR0JpZ1Z2ZmpsVklFZzBHaWtRZ1BQL3d3bi95dDM4QTBUWHA2RnFLVVFtdU5aVmtZaGtHeFdMU0xSWHR6THBkN0laVk8vWjlNSnZ1QzFucEdvSk5OVjlmc3IwYkM0VnRDb2RDbGhtR2dQQS9YZGZIS0V4OHBKYlp0czMzSFRub1g5dkJmUHZVcC92Ti8vajBBanZYMzE2dzRLeWlsQ0VjaWhJTkJmdmF6bi9IZi8vdC9ZOTI2bDVrL2J5N1JXS3c2ZnBaU1lob0cwaWl0U3VUeitkMlpiUGFwZ3djUC9mNGszOEo1VWZjQ1hiMXFwVlpLNFRoT0tRS29kRlFYSVFTcDFBaUhEaDNHNS9QeDRROS9tQWUrOUdXNnVycElaekxrY3JtYUYyY0ZwUlNHWWREYzFJVGplZnlQTDM2Umh4NzZLd2FIaHVsb2I2TzVYT05wZEZ1YXBvbVVrcmZXYjZpOXNjdFpVUGNDWGI1czZURFFBT0I1SHBsTW1tUnloRnd1eDRJRjNYem9ReC9pL1RlK241dHYvaFVBK2djR3FnS3VOenpQbzZtNUdjc3dlUDJOTi9qWjAwL3pveDg5enNZTkc3QXNpNmJHUnFLeFdMbjRsMFlwbmZqbDFtMnRrMjMzK1RBRkJMcHNlSEF3MFREUTMwOG9IR2Jod29YTTd1cmlxcXV1NHM2N1BrTDNnZ1VBSkVkR3NHMmJVd1VvSzZWb2JHekVNazF5aFFLWmRMcjZlcVVVRFEwTitDeUxiQzVITnBzRlNwNnFxYkVSZ0tIaFlhU1VOTVRqcDdTNWYyQ2dPcmIwbEdKd2NCQWhCRnByQW9FQXNXZ1VnTUdoSVR6UE84N21TaS9SVXZhYUF3TURQUGFEeDFqNzg1OXo0TUFCZHUzY1NYSmtoT2JtWmhvYkd3ZmUzcjVqMWpsK3REVkIzUXUwZThIOFpGdDdlL3pLSzY3aytodHU0UEwzdklldXJxN3E1blZpY0xEYXFLZkNVNHBZTkVvNm5hYS92NS9Pems2RUVMaXVXejVkS1VrbWsrVHplZUx4T09GUUNFMXBWV0N3L0I0dExTMG9wUmdhR2hyMy9ZUVF6Sm8xaTN3K1R6S1p4Ty8zMDlUVVZMV3hVQ2lRVENhUlV0TGMzSXhoakwzVFZaa0FOVFUxWVphSEtzZU9IZU90dDk3aStlZlg4dW9ycjdCMzc5N0V2djBINnRxRFZtKzBYbjkrOTNkK0o1WFA1M1VGeDNWMWNtUkVEeVFTWi9XVHplVjBMcC9YbDExMm1UWk1VLy9hSno2aHRkWjZjR2hJRHcwUGE2MjF2dXV1dTdScG12cHJYL3RhOWYyMmJ0dW0vWDYvdGl4TDc5eTFTei81azU5b1NrdVlHdEErbjA4TElZNTdUQ21sLytFZi9rR2JwcW5YckZtalBhVjBLcDNXV212OStJOStwQzNMMHRGWVRPL2R0MDk3U28xcDcrRFFrQjRjR3RJRGlZVHVIeGpRdzhta0x0cDIxUzZsbEw3Ly92dVRrOTArNS90VDl3djE4N3NYRUFnRUdCd2FRaWwxVG1OTHJUV2hZSkFmUC9ra216WnRBdUN4NzMrZnYvbWJ2eUVhalpMSlpBQklwVks0cmt1aFVEanVieXRMV1lPRGc3UzF0WEZaWHgrV2FYTDA2RkVPSHo0TVFGOWZINFpoVk1lL3lXUVMxM1ZMM25LVXpZN2pWSC8wT0o1ZktZVmxXUVNEUVJ6SEladk40cm91cVZTcStwcVc1bVo2ZTN2cnUzdGtDdXdrWlZMcDZ1L25PL0ZadTNadDlmZGNMc2RQZi9JVFB2U2hEMVc3MkZBb0JJRFA5KzRSb1lyZ3ROYnMzNytmdSs2OGs0MGJOZ0R3MUZOUGNldXR0ekp2M2p3MmxCK3JrQzZMdnFHaEFZQm9KQUpBWTFNVEFJRkFvSHJkMFZpV2hldTZQUG5qSDdONzkyNVdyVjdOVFRmZVdMM2VhSWFIaCt0ZW9GTjZMNzdTVGJRME45TlVidmdUR3h3Z0dvMVN0RzIrOCtpalNDbTUrK01mQitCclgvODZBRDcvbVFXMFY1YXRraU1qQUl5VS82K1VJcFBOb3JTdVBsZVorQlNMUlZMcE5POGNPVklhL3g0N2RzcjNVRXJoOS91SlJxTWNPM2FNa1pFUlRNc2E5LzdybmZvWDZDbWNwcy9udzNFY3Z2L1lZN3k5YlJzK24rOGtMNnVVSXVEMzg5ajN2MDkvZno4M3ZQZTlQUHp0YjJPYUppKys4QUt2di9FRzBYRDR6RXdwWDl0MVhZRHFJcnJXdXRwdFY1NnJzSDc5ZXVLeEdMTTdPNG5GWW56c294OEZxTlNKUHduRE1NamxjaVFTQ1diUG5zM2l4WXVQRzNJY2QyKzZCc08wenBLNkYraXBmSVRuZWNSak1kQ2F6MzN1Y3p5L2RpMnhXT3k0MTRSQ0lUeWwrT3BYdndyQUgvekJIeUNFNFBPZi96d0EzLzN1ZDk5OXI3SkhHdTg3Y1M0ZUt4QUkwTnZiUzgvQ2hTeFpzb1RPenM1VFhzc3NqMjFYckZqQmJiZmZ6cmF0VzdIRzg2Q3EvajFvM1k5QlQ2VlF3ekJJam96Z0R3UzQrKzY3NlpvenB6cWhxUkFKaDNsNyszWTJidHdJd1AvK1gvK0wvL3ZFRSt6WnN3ZUE1MGVOU3gzSEFTQllIb3NDQklQQjZ1L25FcmEzWXNVS1huNzU1ZXEvbjNuMldXNjY4Y1p4citXNkxnM3hPSysrK2lwSGp4NWxZVzh2eGpocnUzb0tLTFQrQlhvS2RIbmgrOUNoUS9UMjl0TGIyMHMrbjY4K1g5bXZYL3ZjYzlYSG5uamlpZU91c1dIREJsNSs1Uld1V3JPR2FObjdIaXJQektFMGhxeDR1NjZ1cnJPMnNUSUJzeDBIbjJVZFo5OTQ5eFNKUnRteVpRdmJ0bTNqbW11dUdUZmdXcW42SDRUV2ZSZC9LbncrSDZsVWluWHIxdkhFRTArd2QrOWUvS01tUEpGd0dFK3A2bVRvRTcvKzYyemV2SmtYZi9FTE5tN2N5TFhYWFFmQVY3L3lGUUErOXJGU25QQ2Yvc21mOEQvKytJLzUyNy85VzM3ek4zNERLSG5DSzYrOGtreDVod25lN2FiSDhvYVY1eHpIWVhUVWxXM2JBQ2VOVlN2NC9YNTI3dHpKcjk1eEIvLy9GNzdBTTg4OE0rNTRWYzE0MEpwZzNHbFNzVmdrSEludzJjOStscUdoSWZMNS9IRmp1M0FveExjZmZwZ2QyN2NEY08rOTk3S290N2Y2L0QzMzNNTXZYbnlSeHg5L25GMjdkM1ByTGJkdzMzMzM4Y0FERC9ERkwzeWgrcnFGQ3hmeWd4LytFRU5Lc3Rsc2RUWmZtYndjSzgvTVIyOVpWclpLRTRsRXFWaENlWUpWRWFycnVtaXRPVEYvcVczYmRIWjI4dVNUVDZLMTVnTzMzRUxoaEdGTEJUMEZQR2pkQzFSclBlN0F6M1ZkRENucDYrdERBUGxDZ2ZTby9mVjBKc1A4U3k3aDc3LzFMV0xSS0YxZFhTUkhSbkJkRjUvUHgvWFhYOCtqano1S3ZsREFkVjN5K1R6MzMzOC90OTU2SzVzMmI4WXVGbW1kTll2YmJydU5obmljL2xHeHBlbE1ocXV2dVlhSEgzNllVRGlNVXFvcXluUW13eDEzM01IOFN5Nmh1Ym1aVkRxTjY3cWt0V2IxNnRVOC9NZ2ptS1pKTUJna2xVNGZkMCtXWldFWGkzaXVpKzA0SERseWhFV0xGbzE1LzByVjRGbVdzNlR1QmNvcHBrbVZoZTdCd2NIcVk2TzlXQzZYNDVwcnIrV0dHMjRBU3NFWnJ1dGlHQWI1Zko1Z01GanQxbFBwTktsMG1sdyt6N1hYWHN1MTExNWJ2VTdSdGsrS0xjM2xjc3hmc0lCTGx5d0JTakVCbFdDVlhDN0g4dVhMV2JWeUpWQ0tTNVZTNGpnT2MrYk1xWHJ4b2VGaDh2bjhjZGUxYlJ1ZjM4K05OOTNFeSt2V1lWa1c0K2xRS1RVajBNbEdDTVlNNnZROGozZzhUdUNFUmZaTU5rczJsOE9Rc2pUTFR5YVBlNzRpQnNNd3NHMmJ4Q2h4RzRhQjF2cTR4MDc4dTlIL3ptWXlaRWZ0OEZTK0hJWmhWQmZ4VDN6UFhDNUhidFFacWRIWExVWFJ3NXp5Wkd4eDJYUG1DZ1U4enp2SkJsR3JDZmpQZ3JvWDZGaitVMnROS0JSaWVIaVluVHQzWWxsV2FWOGJXTmpiaTkvbkczY1Njam9xWTBXdGRWVVFKMDZDUnIvbVFtSlpGbzVkNU5YWFhzUHpYS1NRRklwRnVoY3NvTEdwaVh6KytMTlZxdjduU0ZOQW9HUGc4L2tJQkFMODN1LytMdC83M2o4d3UzTTJHczNCZzRlNDc0LytpRC8rNHo5aGFIajRyTTdEZTU1SE9Cd21NbXBYcVdqYm1LYko0T0FnVWtvOHo2c0dEbGNZSzZielhHbHNhT0RiMy80MnYvMWJ2MGw3UndlR1lmRE80Y1BjZnNjZFBQcWQ3eElJQkk1YjU1MVpCNjBCOUJoemVNdXl5R2F6N042OUM1L1BYL0owNWZIb3pwMDdnVkozZXpZQ2pjVmk3TnUzajYvODJaL2hPQTYvOS91L3owc3Z2Y1RlUFh2NGk3LzRpK3Jyamg0N3hxYy8vV20yYjkvT0J6N3dBVDcxcVU4QjRMZ3VVc3Jxb3ZxNVJ2WVBEQXhndTE1MTl5Z1lDckZ2NzE1U3FSUU5EWTNIQ2RUenZKbXR6a2xuakc1VWE0MlVzalFHRFFUd0J3TDQvWDVDb1ZCMXEvTnN1OTlnSU1ETEw3L01Zei80QVR0MzdlSzJXMjhsbDh1eHBEd0pldWloaDNqOWpUZFFTdkdOYjN5RDFaZGZ6bWMvKzFrZWZQQkJYbnZ0TlRadDJzVGh3NGY1eGplK3dldHZ2RkU5UjNTMkJJTkJRZ0UvZnIrL2RHOStQL0Y0Zk16QVpzOXpaenpvcERORzdrUWhSQ21DS0pQQjg3enFHTkZ4bkdwczU3blExTlJFUzNNemhVS0J1ejd5RWZLNUhDOXQzY296enp5RDR6Zzg4c2dqZk9RakgrSGFhNitscWJHUkZTdFdzSGJ0V2o3LytjOXoxMTEzc1hIVEpoWXZYc3hmZmZPYi9PRHh4MW15ZUhFMXV1bE1LUmFMRkl2RjZqMVZscS9HR2tiVS95cm9WQkRvR0QyazUza0VnMEdhVzFvWVRvNlVkbHEwcG1nN3RMZTFBK2MyZ1VtTmpDQU5nOXR2dTQxdmZldGJORFUxa1J3WjRkREJnd3drRW56aEMxL2cwVWNmUlVqSjQ0OC96cGUrOUNVMmJ0cEVNQmpramc5K2tFY2VlWVFONjljemI5NDhYbnp4UlpZdlczYldOa1NpRVR4ZFd1QTNESU9CeENBclY2MGlFZzVYWXdVcVRJVnd1L29YNkJoVWRuRCs3Q3RmNVJPZitBUStmd0MweGxPS3ZyNCtSbEtwYzBvWTF0alVoR1BidlBubW0xeC8vZlZrczFsYVdscm9uRDJiNjYrL25uZ3N4aDk5N25NODhNQURQUG5ra3pRME5QRE1zODhTQ0FhNTdiYmJXTFZxRmN1WEwyZjI3Tm5jZWVlZDVNY0preHVQa1ZTSzIyLy9WWjc2NTNsb3BaR0dKSi9MczJqeFlyVFc1QXZIeitKck1hM2syVElsQlNxRUlKZkxNVy9lUEhxNnU0OTdMbDhva0VxbGpsc3pORTJ6R2l0YWNqb25lNTZpYlhQampUZnkxRDgvVFNhVDVzb3JyaUNUelZJc0ZtbHVhdUxtbTI5bTNyeDV6SnM3bDFXclZtRmFGa1hINFo1NzdpR1h5eEh3KzNuMXRkZDQ0WVVYV0wxNk5mRllqRXcyVzQzU0gyVTlRcFM2YnR1MmoxdkNLaFFLeE9OeFB2QXJIemp1THp5dFNZeVJJV1hHZzlZQTQ3WEJpWXZob3hGU1Z2TWVWVWlPak9CNUhrSkl4cHBZSzZYdytYd3N2YlEwS2Nwa3MvaDhwWWxLS3AzbSt1dXVRNWV2TS8rU1N4aEpwU21rMGtTalVacWFta2dNRGhHTFJmbFg3M3NmcnVjeFdENzVlZUlzWHV1UzU3TXNpOGJ5Y1JBbzdVUkpLU2tVQ21NR0tJOFdaK1dhTSt1Z2RVYmxDTWlzMXRKSjNNMWJ0dkRVVDMvS2hnM3JHVXdrU29mdXBKelVmTnZsWTU4WWhrRjdlenQ5SzFadys2L2V3Y0tlSHVEZGJkRXpXWjZhOGFCMWhOWWF3elJwYW1oZzQ4YU4vUG1mUDhqemE1L2owS0hEQkFJQlFxRVFVb2lhS0tjZ0tNV3E1bkk1SG5ua1VmNzZvWWU0NmVhYitmL3V2WTg1WFYxbmZOWmZ6WXhCYTRFems1U1FrcWFHQmw1YXQ0NS84NjgvU1A5QWdnWHpMK0hTU3krdGV0WmFRd2lCa0pMazhERGYvT1pmOFpNbm4rUUhQM3ljMWF0WE01QkluUDRDTlhoUFowdjlMOVNmQVVvcFdwcWFlT3FwcDNqZkRkZWh0YWJ2c3VVRWc4RnFHc05hUkd1TjhqeGlzUmg5bHkwbmtSamdWMjYraWZVYk50RGEwbEk5RVREdTMwK0JNZWlVRjZqV21uZzhUbUp3a0QvOHpHZndXVDQ2T3p2UE9WaGtzbkJkbDU2ZWhhVFRhZjdUSjMrTFZEcGRPaEI0Q3FaQXZQSVVFT2hwMmtBSWdkL240OEd2Zm9VdFc3ZlNzM0JoM1ltemd1TTQ5UGIyOHRycmIvQi9uM2lDd0drS1FOUnF6M0EyMUwxQVQ5Y0U4WGljZDQ0YzRlbC8vbWZhMjJiVlpNR0VzeVVTRHZKL2Z2UTRqdVBnRHdUR2ZkMVVpR2FxZTRHZURzczBPYkIvUDRPRGcwUWlrYnIzS2xwcldscGEyYkpsQzd2MzdDRldUcGt6RmxOaEhYUUtDUFQwaldEYjlqa25GcXRGVE11a2tNOHpPSmc0NVQzVis1Y1Jwb1JBendBSlU2cmNwYTZrT2grbitTWW9vbjh5bUJZQ0ZlWDk3YW5FcVlLZEs0L09CSXRNUWQ1dCtNbndQdUtDYmhwTWhjd2k5Uy9RQzlBRWxRajh5cWxLMjdZblpieXF0Y2Juc3dpRnduaWVkOTdqNXFuUXhkZTlRTSszQ2JUV21KYUo4aFRidCsrZ2FOc0VBZ0cwVWhmZGgwb3BLUllMbUlaSmIrL0MwaWxPeHpsbmtjNEl0QVk0TDBjbkJGSUlYTWRsKzQ2ZHRMVzNjOVZWYTJodG5WV0tEYjJJNlRVclE0disvZ0ZlZi8wMXRyMjluZDZGUGRXeitPZkNWRmdIclh1Qm5wZVQwQnJUc3RpN2R4K3hXSXlQZnZTakxGNjhtS2FtcG5HcmE0eUZZUmpJY294cEJhVVVudkpRWjNpd3N1SWxCd2NIV2Jpd2g3Lzh5Mit5Wis5ZUxsMnlHTnQyVHZQWFkxT0xaY2JQbHJvWDZQbDI4a29wWE5kbFZWOGYzZDNkekprekJ4Zy8xMmRsdk9yeitjb2k5aWdXYlFxRkFvN3RvSlJDU29ubHMwcW5MaU4rcEpTNHJsdktYS2YxdUc3Zk1BeTZ1cnJRV25OWjMyVzh2TzRsM1BNNE9heW5RQjgvQlFSNmZsUXloUGo5ZnFLUkNGTEtrN0xnalNaUTNscnM3KzhuTlpKaWVIaVlUQ1l6cHJjeXBFRWtHcUdoc1lHR2VBTk56VTE0bm5kU0V0MEtydXNTREFhSngySUVnMEZNd3p5dnBhSXBvTThaZ1paNHR5N1BxYnBGd3pBWUhoNW05NjdkOUIvcngrZjMwZGpZU0dkbko1Rm9oSUEvZ0pDaWVwNG9uVTR6UERUTXpoMDdjVjJYV1cyejZPN3VKaHdKNDdsamUyalA4MHEyS0RYV2llcXp1NnVaWmFhcHcrbldIMDNUeEhWZE5tM2FoQ0VOVnF4YVFVdExDL0Y0SEdsSTdLS043ZGlsMDVaU1lsa1dQcDhQcFJUSlpKTEVRSUtkTzNmeTlyYTNXWDM1NmxObU5ybFFhNkZxQ3JqUUdZR2VJWldFc3N1WEw2ZTF0UlYvd0U4aWtXRFhybDBNRFE2UnkrV09DK016VElOd09FeHpVek9OVFkzMExPeGg3aVZ6R1V3TVZzc3JUaFR2SmkrYm1TUk5HN1RXK1B3K21wdWJPWFRvRU52ZjNrNHFsY0t5ckZKU3NVaUVRQ0NBWVJoNG5rZWhVQ0NUelREUVA0QnQyOFFiNGl4WnZJVDJ6blp5MlJ6RlluSENOd05tdXZocGd0YWFjRGhNb1ZEZ2xWZGU0WjNENzlEUTBNRGl4WXVaMVRhTGVEeU9hWmxvcGF1emVDa2x0bU9USEU0eU1EREEwYU5IV2JkdUhYUG56bVZoNzBKQ29SQzVYRzVDUlRxVG83NFdtT0FtcUloelpHU0UxMTk3bldLeFNOK0tQaFlzV0lCcG1veU1qSERvMEtGcU42K1VLcVh2RGdWcGJtcW1wYldGOXZaMmVoZjFzbS92UGpadTJNalJvMGU1K3VxckNVZkNFeXJTbVdXbUd1QjhaN3FudkhaWm5NbGtraGVlZjRHbXBpWnV1T0VHR2hvYlNDUVN2TDN0N1dwNjhVQWdRREFVeEcvNWNWeUh4RUNDd3djUEk2UmdWdHNzZW50N1diUjRFYTJ0cmJ6MTFsczg5OXh6WEhmOWRUUTJOcExKWkNaRXBHb0tuRHV1ZTRGT0pKVXlOcSsrOGlyTnpjMWNjKzAxQkVOQnRtL2Z6aSszL0JJcEpGMXp1dWpvN0tDaG9hRlU0a2FVVGxNVzdTTERROE1jUG5TWWd3Y09NdEEvUU4rS1BtYlBuczJWYTY3a3hlZGY1TTAzM3VTS0s2L0E3L2RQeURtcG1hM09LWTdQNzJQYnRtMW9yVmx6OVJxQ3dTQWIxbTlnNjVhdExPaGV3TktsUzRuRlk2VmM5b2tFeWVFa3RtUGo5L2xwYUd5Z3JhMk5ycTR1ZWhmMXNublRadGIrZkMxcnJsNUR6OEllcnIzdVduNys3TS9ac1gwSHF5OWZQU0VDVlZOZ3IzTkdvS2NnbjgvVDJkbkpuRGx6Q0FhRHZMM3RiYlp1MmNyeXZ1VXNYYm9VVDNsc2YzczdCdzRjcUZiak1DMFR6L1Z3ZGppRXcySG16cHRMZDA4M1Y2NjVra0Fnd1BxMzFpTVF6TDFrTHUrNTRqMG4xWisva0tncGNDaXAvZ1U2Z1UzZ09SNnhlSXhnSU1peG84ZllzbmtMdll0NldicHNLYTdqc21IOUJuYnYyazFiZXh0TGx5MmxxYWtKeTJkaEYyMkdoNGZadTJjdmI3ejJCcGwwaHFYTGxyTDY4dFdrMDJrMmI5NU1jMHN6RFEwTk9JNHpZZkduVTJFTU9pMk9mSndyUWdvODE4TzJiWFpzMzBFb0ZHTEpwVXR3WFplTkd6YXliKzgrVmwrK211dmZlejN6Rjh3djdSb05KeEZDME5QVHczWFhYOGZLVlN2WnRuVWJXelp2QVFFclZxNUFTc21lM1h0QU1LSEIwVk9naDU4Q0hyU0NFQk9TaThnMFRYSzVIQ01qSTNUM2xQYlJkKzNjeGE2ZHUxaTVlaVdMbGl3aW5Vcno5cmEzT1hMa0NHaVFocVNycTR1ZWhUMHNYcklZMjdiWnZuMDdyYk5hbVR0dkx2TVh6R2Z2bnIzTW1Uc0gzM21VeEJtUFVUdEpkZC9GMTcwSHJTd3pUZFJ5dDJtYURBOE5ZeGdHYlcxdDJMYk40VU9IYVdsdFlmNzgrU1NIazd5eTdoVU9IRGhBZDA4M3F5NWZSVmRYRjF0L3VaVU5HelpRS0JSWXZHUXhyYTJ0N055eGsyS2hTR3RySzFwcmhvZUh4NjMxZmlHWUNtUFF1aGZveFdCa1pJUmdNRWc0SENZMWtpS2J5ZEkxcDR0QU1NQ0IvUWNZVGc1ejVab3JXYlI0RWUzdDdTeGR0cFExVjYvaDJORmo3TjJ6RjUvZlIzdEhPNWwwaHBHUkVRS0JBRDdMUjdFd2R0amRoV0lxSEpxYkVlaHAwRnJqT0E0K253L1RNa3V4b21naWtRaU83WkJNSnVubzZLQzl2WjEzRHIvREc2Ky93ZkR3TUhQbXpDbGxWazRrcWhGT3hXSVIyN2J4Ky8ybDgwYnV1VVhLbjRYeEUzdjlpMEQ5Qy9RaXRFR2xLRzNsdlNyL3J1d2tWakllMjdiTmdRTUhLQlFLQ0NGS2tmU2VXNjBidXVUU0pZVExsWStMZHZHY0NubWRvY1hBMUFoWXJudUJUblFUQ0NHd2ZLWFRsWlV5M1ZDcVYxUXBtWjNQNTdGdHV4UUZiNXJrc2prTXc2Q3hxWkdoeEJENzkrK251Ym1adnBWOUJJTkJkdTNhUmFGUW9LbXBhVUtTbVZVMFB4VUVPblZtOFJOSU9CeG1vSCtBUXFGQU9CekdORTB5NlF4U1NvS2hJQWNQSGlRMWtxS3hzWkZBSU1DUkkwZm9YdGhOVDA4UG1YU0cxMTU1amFOSGpoS1B4K252NytmWXNXTmNkdGxsdExhMmtzL25KOHp1S1RBRXJYOFBPdEY0bmtkRHZBSFA4eGhPRGhNS2hRaUZRaVFTQ2ZMNVBNMU56WGlleDJDaWxEMXYwZUpGSkJJSnRtM2RSaUFRWU1YS0ZmU3Q2TU8yYlE0ZVBJaGxXVnh4NVJYTW16K1BZckU0b1Y1dXhvUFdCQlBiQ3E3ckVvNldLaHdmMkhlQTdnWGRORGMzczJYTEZvYUdodWpvNktDcnE0dmRlM2JUTWJ1RCtRdm1rMDZuMmZEV0JqelBZK0hDaFN4ZHZwVGVSYjA0cmtQQUg2aWVWd0ltWkF3NlVlWEFKNE1wSU5DSlJaVkx3blQzZE9NNkx1bE1tdGxkczltM2J4KzdkKyttcmEyTlpjdVg4ZXd6ei9MYXE2L3gvaHZmejdKbHl6QU5rMjFidDNId3dFSGFPOXFKUkNLZ0ladk4wdDdSVGpRV3hYVW1OdFB6VkJEb1RCZC9CdGkyemR5NWMxblF2WUJDdm9CcG1TeTVkQW52SEhxSDNidDJFMitJczNMVlNsS3BGQys5OUJMWlhKYStsWDFjZGMxVnRMUzJNSkljWWYrKy9lemJ0NDlFSW9IbmVSalNPUDBibnljelo1S21DVUtJNmxsMktVdjFNZHM3MnBremR3NGJOMjRrM2hCbjd0eTVTQ0ZadDI0ZHp5ZWZaOW55WlhSMmR0TFIyVUVtbmNHMjdYSnlNQjlhNitwUzFFVFpDek1ldENhNFVHMVFXYmM4VTlFVUNnWDZWdlRSMHRyQzg4ODl6NUVqUjVqVlBvc2JiN3FSNXBabTNuempUWjc1bDJkNDgvVTNTMlVVL1Q0c3l5cWx4UEc4OFhON25xVWQ0MUdxV0ZmL0NwMENIdlNDS1JTdmZPRHRUTVRodVI2V2FiRjgrWEwyUi9jRGdud3VqOS92WitYS2xjeVpNNGQ5ZS9kVmE3bFhFanFVM3VyVTR2U1VBaUVRNXhGaG9MV2UwT013RjRzcElORHpRMHFKNHpna2g1TWtrMGthR2hvSWgwdjVPVS9ubnBWU1JDSVJWcTFlUlQ2ZnIyWUZVVXJSMmRsQlIwY0hydXRXSHpkOXB4aDNDbEhOVDVwSUpCZ2FITVIySEF4cDRLcXpuVXhkMkVTNGs4bjBGbWg1eTdLeHNaSDE2OStpdTZjYnBSVFJXQXhUeXZOYjZLN1UwcXh1azQ2Zk5LeGtTaWxjY0NTVjR2WFhYMmY5K3ZXMHREU2YwMXRYZDVMcVA1aHBtZ3RVYTF6WHBhMnRqVlE2d3c5LzhBUDI3ZDFMSkJwOVYxUVhDeUV3cEN5dG9XN1lRRFFhWWM2Y0xvcUZjMHZ3b0pXYU9SYy9GUkJDNERnT1BkMEw2Ty92Wi9QbVRmZ3MzNlNNMzRRUU9MWkRRenhPUjBjN2puMnUyWlZMVlp0bnV2aGE0QUxscUxkdG01YVdGbHBiVzFHcUVzQnhNZlBVbDZLbHBKUm93SGJzYzU0a2xVWUxlaVp4UXkxd29UeWRFR0tNeXNjWHYzMVZlUW5xZkdid2NPRXk1RTAyZGI4T2VpR3BsUWE5SUhaTUVRODZJOUFwaUJBQ2paNFNDL1ZUUUtCVHJJVGNCVUxycVpIZGJnb0lkSWF4bUNxVHBDa2cwTHB2Z3d2UHUyZW02djdEbVFJQ25lRkVCR1VQT3BQNlpvYmFSYytNUVdlb1ZRUmFUNDI5K1BvWHFKNlp4cDlJYVNkSm9iU2UyTlFsRjRHNkY2aEdUK3pCbmpxbE5EM1M2Y20yNDN5cGU0RUNtY2syb0ZaUlNzMElkTkxSWkNmYmhGcERDSUhydWxpbU5UR3BteThpOVMvUWFUZ0NGVUpVby9USHc3WnQvQUgvUmJScVlxajdhS1pJSkJJRWFHcHNIUGMxczd0bUk2WEVORXM1NU9zWkFUaU9UU1FTNFpMNWx3RFEwbnh5NUgxSGUvdkZOV3lDcU8vV0FuYnYzcDFldS9ZNVJsSnB0RmJWNVJVQkJZQm9MTXFtVFp0TTIzWk1yVFhGb2ozWkpwOFhHc2htTXF4Y3VVbzkreS9QZWkwdHpTcWZMMmpBSjZXUVFrQWdHQ0tWR3NFdUZ1dStmeEgxdmh2V1BYLytIdzRuaDc4c2hVQklpZks4Zy9tc2JXcEZCMmpiOFZ3RUdORjR6UEE4dCs1M1JqWGxqSHVXcVlhSGg1VUc3VE44RnBBTFJmd3B3elRhUGMvRHNpeWlzZGlEdTNidC9zeGsyM3crMUwwSDlmdjlCOXZhMnFyL05nenB5Nlp6ZisvWTZuZE4wNHhYdkNxaWR1STl6eGNCS0sxbFozdFFTaWxCQ3d4TGZqY1FzbTZwM0dJNXQvN0FwQnA2QWFoN2dUcWVrd2o0QTFYeEdZYlJadnJNcE92YTkvb0Qvb2NxeHpkRStaek9WRUZRT2sxZ1NJT2liZDl2K3VVZXk3Sit5L05LMis5S0tVTEI0T0hKdGZMOHFYdUJtb2J2N2RHZTBmTThncUhndmNyVFYzcXU5M1BMTXY1VkpXNjM3Z2RrSjJCSUE4ZHg5dGhlOGU5Q1Z1eGZSbGVka1ZMaXV0Nk95YlB1d2xEM0FyVXNEb0xZNzNsNlh2VUFwTmFOUHIvdlEyVEUrNDJBb1ZFWFBvdHhMV0JJaVNOWkdZbUVmOVV5ekFXTzY1YlRpb1BXT3FkaDgyVGJlTDdVL1Rwb0pwT2xXTFRYR3NhN3Q2S1VKaFFPZmpsUlNIQzAvK2pWb1dBQVE4b3A4U09sUUVwQktCakVWZDdkbVV3NkZmRDUvdG85THQrVFFDbjlrdWU1RTVlKytTSlI5eDYwYUhzWXBsNHZwZmkxMFYyYzUzcUVJNEducy9uaXI3aEtmY3kwek85NHlxdnJibDVya0VMaTkvczUvTTQ3bjBzTUpyNHpiOTdjdjBNUU9mRzFBbjVoaUxyM1AvVXZVTXMwMEVwdE9IR0M3amdPVFkzTk54dEc2cjBEZ3dQZmJXdVoxV0FheGwvVzh6a3lpVUFhRXR0MUhrd01EOTR2VGJra0dvMzhSOGM1c1p5TnhsTnFremNGd3UzcWZoMDBIbzlobUlab245VjJ5TEtzenRGVk0wclo0a1J1LzRHRGk2TEJ5S0hPOXZhN1BNay9hYVhxcm9TUUVBTFROSEFjNTlOSCt3ZStZZm1NUUZORHd6N1g5ZHBHdDJFNXhWT2hhTnN0U3Fuczd0MTdKdEhxODZmdSs0QndPSUxQQ21qYmR2N25pZDEzNlZ3T29jN096aWN4Qk5sQy92dUdOSzdSbW1PRzhlNTRydFovVE5NQXRPM1k5bDFIang3N1JuSWtTVk5ENDArVVVtMWo5UWhLcWI4VFFtWk5jK0xLTEY0czZ0NkQ5dlgxbGMvZktFdEtNZVM2YnVURWZFWlNTZ3pUL003T25idnVEZ1lDZE02ZUhaWHdqNlpwM2FhVVFxbnhFOHBPTHFJY21lUzhLWkIzcGpPcHZVZjdqeEdMeFI2YzNkRnhUNkY0Y2p5eUFQTEZZcXRTS2lHRW9ONDlhTjJQUVE4ZVBGalpXWEVhR3h1KzF4Q1AvNlp0SDcvZnJwVENKOFRIZ29IQXNaRlUrak1kN1Y2NjREaTNPMjcydDhPaDBBT21ZVGE2WG0zRlBVc3AwVXBwcmZWOXFVejZ5d0NXWmRMZDAzMmZJY1E5K1hGU2lHdDR3bTlaaVZJT3h2cDJQakFGUE9qb1Jnb0UvRDJYTGw2ODAzYWNNYmMxVGRNZ215czhpTmFmY1Z5SFFxR0kzK2Z2aUVXaWZ5R2wvSEF0ZlJaS2VjODZqdmRwWWNndFNya2trMG5pOGRpOW9WRDRBVytjTDVPUUFvRzRTc01ybGNjMmI5NXkwV3llQ09wZW9GMWRYVUJwdk9sNUhvME5EZi9ONy9kOTBYRk9UbDBveWxtTWk4WGlvNWxNNXVQU01FQkwwSnA0UEhhRjU2bi9LdURmVld0elhpU3FSUStVUnFHZkJyNmN5MmFmTXd5SnExMEMvZ0JTeXY4cHBmeDlLZVZKdG1sZCt2SzVudmUvYy9uOEp3MzU3dFJpMTY3ZEYrMCtKb0s2RjJobloyZjE5MUlRTDdKOVZrc2FJVUpLalgwc3ZKd1Q5RGxQcVU5S0tYZTVqa3N3RUNvbHRIWHM2end0UHU0enpac1F6Q3ZsMnJ6UXlXekwzYThRU0NGeFhTZWg0YWNHeG1OS3FTZTFDV2dYclJWRjIrNEloNk1QV2FiNXdaT3o3NVdRNVFYOEkwZU9oUXUyblpPajFqK0hoNGN1b04wWG43b1g2Rmpqc01hR2h2Y3ZtSC9KTThWeTZaZngvazRJNGRtT2ZaY1E0bkhIZGpFUUlBVk9VV0VacGxGVXhidjlsdjh1NEJhQkdLMnIwdWhPai83SGVBYSsrNnNVNWVQQWFBUUN6M05mVk9oL2RCem5PMHFyZER3Y3gxTWUybFNVTjhiZUw3VHhJeUZGOUZUM0lZVWdtVXA5ZkdobytGRXBqMStZR1JrWk9ZVnh0VS9kQzdUOWhNaHhYUlpOYTB2emcxS0llOGJ6b3FPUlVuNDNuYzU4VG11MVB4YUxrczhXY0YyTnB4eVVxeEJDTG9oRUl1OXhQWGNlY0NXd0VyaEVsTkxJbFJnMUtaR2kxQTByclVxL285RmFIL0k4YjRPVTRsWFBVM3UwMXV0OWxuOWJKcGNtR0E0aU5Qajh2dExmU05tQjFuOXFHUExYS3dVUnhxSlVkOG5DODlRamh3NGYrVFhET0xsQ1NYOS8vOWw5b0RWRzNRdDAwYUpGSnozbWVSNmVwNGpISWk4cnoxdmpLWFhLWmFUeUdSOWJLZjNGZ04vNjl2REl5RkhQMHdRREFWekh4WE1Wd1dBUXh5bVZrOGtYczFqU21tdFpWby9TdWtzSTBhazlGUkZDQm9WQTJLNlRONlNSTTAzelNMRllPQ2lsM0F2c3llY0x5dktaV0thSjQ3cjRMQi9TRVBnQ1ZybTJ2TmNvRVhkTEtmOEVSUFIwczNBaEJhN2o3aXdXN1VWYUNDM0h1TWZkdTJmR29KTktJQkE0NmJIS1Bma3NIM1BtekU1WWx0Vjh1cnJzNVM0ZnJYWFJjWnh2NXZPRnIxdVdlVEFZQ0dJN0RyWmo0N2NDZ0NDZFRXRmdZSmdHV3BlaWg1U3RNS1NCa0pES3BiRXNINUZ3bUV3NmpXVlpJRXBSMDZiUEpPRDNVYkNMcEVaU3RMVzM0WG5lTEVQSzN3TStKU0IydWhiUldtT2FKcEZ3Mk5teloyL0QwZjcrM0hoZndEUHBRV3FadWhmbzZSYlllN3E3bDRYRDRaKzRualAzVEpjRkRjUEFkVjFIS2ZYM1Vob3ZlcDc3UXI1UU9CaU5SZ0dCNHhSeGlrVjh2aEJhSzBTNVBLSXBUVXpUSUZmTUVncUZjUjJGNjluRUcrS2tVaW44UGd2TDU4ZnpGRXA1c3dyNXd2dWkwY2hWUW9qZjFGcUh6L1NlUzk3V0hYWnQ5NFBIK3Z0ZlRLWEhQLzVlNysxYjl3djE0d2xVYTQwb1RSaTJLTSs3UWlCMkNDbGlweXBEV01IelBLU1VsaUhsYnl1dGY5czBEUlVNQm4rc2xmNFhCQzhJSWJZTFE5aW1hU0NrUkpvbTZXd0tuOC9FRjdBb0tra29FaVNWekNBTnNId21oalFzclhRM2NJT0E5L2tzNnc2L3p4Y2NiMlkrSGxJSVROTlUrdzhjV0pOS3BYZWM2ak9ZQ3RTOUJ6MXgxbHFoSXREdUJRc0lCd05rYzdrMmFSZy9Dd2I4bDdudTJRY3dTeW1yM2FWR0g5TktKNlNRZ3dnR0VPSlFzVmhNbVlaUk5Bd0R4N0Y5bHM4WFU1NmFyYlZ1TlUyelJTblZBcUpkeXZKaGpYUDQyR1ZwVG5aQVNubmp6dDI3ZCtaeitkT0tzOTY3K0xyM29HZUNsQUxiY1kvaE9OZjZMT3VmaEJDM3dObDFmNk1iV2lMYk1IZzNpa2hyUW9FQXFseFp3KzhQVk92TVY1SXNWTDVJNStvUVNudnkzaTl5eGVKZHNXamt5TVVvNTEwTDFIMDAwNW1nZGVsNGhOYWtzN25jclVxcFA0THh2ZTlwcjhmSkpWNjhVVjExMWRPVzYzWldkcWJPUlp4Q0NIeVdSYUZZL0VvNm03MU9LM1ZrS25mcEp6SXRCRnBCVUpvQUZZckZCN0xaN0hWS3FlZHJ0YkdybFk5ZGQzMHlsZnFBNjZrL0ZKejdsNnBlbVY1M1MrbjRzUkFDMS9OK2tjM2wzNnMxbnhkQ0ZFM1RSRWhSRTRITW8ySUJ2dXE0enFwc052ZTBMQytEVFRlbW5VQXJWTFlJRWZ5cDdUZ0xVcW4wL2NwVEJTa25Ud2hTeXZJdWxIb3dsVTVmVXJUdHo1cW1nV2xNai9IbVdFeGJnVllvZTZ0M0JvZUdQcGRPcHhkS0tiL2tlZDc2U3VUVFJJcTFjdWx5ZC81THUyaC9QVmNvTFBhVStveFNhditFdlhFZE1lMEZDdStHNFNtdEQzbGEzK2U0N2lyWGRUOVFMQmEvcjVRcVZwNi9FTzlUR1VPV2hDODA4T05jUHYrdmxWTExiTHY0WDIzYjNpN2x5WHZxMDVWcHNjeDBwcFNLdUZZTHl6NmRTcVdmRGdTREhRRy83MnJidG51Q3dlQVZ3TlZDaUhZNGZzbElWdU5HU2x1YWxlZEVKVndQOER3MW9MVjZ6VENNbDIzYjNtbmJ6cXZoY0hpLzY3Z292eXAxOFZNZ0N2NUNNaVBRY2FoNE95SEVFZGQxZjVqTlpRa0VBa2hwV0xsOGJwa3A1VUxMNzF1c0ZSMUMwT0Y0WGxRZ0xDRVFXaXRiU3BuVjZLTmE2M2MwN0hBZGQyZlJMbTZXVWhiQ29SQ3U1K0c2enJ2dlU5Y245aWVPL3dlV1BpdHhuekZwSXdBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMSIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0IiwiY3JlZFByb3RlY3QiXSwiYWFndWlkIjoiNDU0ZTUzNDY0OTQ0NGZmZDZjOTM4ZTkyNjcxOTNlOWIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsIm5vTWNHYVBlcm1pc3Npb25zV2l0aENsaWVudFBpbiI6ZmFsc2UsImxhcmdlQmxvYnMiOmZhbHNlLCJiaW9FbnJvbGwiOmZhbHNlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOmZhbHNlLCJ1dkJpb0Vucm9sbCI6ZmFsc2UsImF1dGhuckNmZyI6ZmFsc2UsInV2QWNmZyI6ZmFsc2UsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6ZmFsc2UsIm1ha2VDcmVkVXZOb3RScWQiOmZhbHNlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxNTAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjE5MiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV0sImZvcmNlUElOQ2hhbmdlIjpmYWxzZSwibWluUElOTGVuZ3RoIjo0LCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6MTAsInV2TW9kYWxpdHkiOjJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDMtMDkifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTAzLTA5In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYTdjNjVhYzk0NGU4ZDUxNDZmNWNiZWI1ZmMzMjg5MzE5MDhhNTM1MiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJhN2M2NWFjOTQ0ZThkNTE0NmY1Y2JlYjVmYzMyODkzMTkwOGE1MzUyIl0sImRlc2NyaXB0aW9uIjoiS09OQUkgU2VjcDI1NlIxIENvbmZvcm1hbmNlIFRlc3RpbmcgVTJGIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJrekNDQVRpZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQkFNUXN3Q1FZRFZRUUdFd0pMVWpFTk1Bc0dBMVVFQ2hNRVMyOXVZVEVRTUE0R0ExVUVDeE1IVUhKcGRtRjBaVEVRTUE0R0ExVUVBeE1IUzI5dVlVVkRRekFlRncweE5qQTFNVGt3TXpVMk1EQmFGdzB5TmpBMU1Ua3dNelUyTURCYU1FQXhDekFKQmdOVkJBWVRBa3RTTVEwd0N3WURWUVFLRXdSTGIyNWhNUkF3RGdZRFZRUUxFd2RRY21sMllYUmxNUkF3RGdZRFZRUURFd2RMYjI1aFJVTkRNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVlTVVlRStwZHFTUGovb3JYVXhtL2o1YytEcys2UXllWWwvc1Z4TDNEbkdxSHpOeFBXdGpkTFlPTzlNc2ZBQjNwQVNxWWJKWEsvL2JGVjJMUDVRS0pucU1qTUNFd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUNBUVl3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQU01RktCWFgyR3JJS2ZmUldpN05hdnBvVTU5R2lySmlWeFhFQmVyS1AyYnRBaUVBNkljQlJDT0tDMGVJQ2I5anlLYndhUXAyZDRjK202dC9iM0RyWWMvQnNJQT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBU01BQUFBd0NBWUFBQUJhRlJ5c0FBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUVHMlNVUkJWSGhlN1gwSGVKeG5sYTdhcUJlWFZFTFl3QTExTHl4a2wyWGhoa0FvQ1FUQ0xydFBsdWZDaGN2ZUpkd0FTOWdzc1BBc2daREVYYlo2Y1M5SlhPTVNKMjZKNDdqM0psdTJ1alRTU0pyUmpFWmxlbEU1OTMzUFA3ODhWbXlORitjK2ErZlJlZlRwTC9QLzMzZStjdDd2blBPVlAwa21hWkp1WWhxT2hhWldtN3kyNjAzWnVIVzdyTjN5cXV6Y2UwQjZCbjFqdjRlSFIyUjRkRVJHY1M0eUVoY202VWFoU1RDYXBKdWFDRFFuejlUS3NoZldTRkY1dGN5dnFKYTVwUlV5cTZoVWloY3RrWE1YNjJRbzloeUJpR0ZraEhkR1lzZEp1bEZvRW93bTZhWW1oMnRBRnE5NFVaNmROVS9CcUxDOFNvcXFGc244cW9VeXU3UmNscTVjSmE3K0FRV2pvWkhoeThCb2FDakNLQ2JwQnFGSk1KcWttNW9PbnpnakM4cXFwTENrUWlxWHJUUzBvcEl5bVZOV0lmTXFxbVRPL0FWUzE5UXNVYUJRT0JvQkJDa2NhUmdlam1vY2szUmowQ1FZVGRKTlRXczN2aUt6aThzVWhOUkVLNjlVcmVqNW9oS1pDekFxS2l1WDQ2ZlBYR2FtWGRLS0puMUdOeEpOZ3RFazNkUzBhZnN1S1ZtNFJJR0ladG1DNmtWU3RteUZ6Q2d1bGZrNG4xZFVMSWVPSFg4YkdFVWlJVDFPMG8xRGsyQTBTVGMxblRoL1VjR0lwdGxNQUJBMW9ubVYxWVptVkwxUU5hUDY1aFkxMHppYVJqT05QcVBSVWNMVEpCamRTRFFKUnBOMFV4T05yV1ZyMTZ0L2lLTm5zNkFkVVNPYVdWNGhzeW9xNVlVMWF3MGd3blBSWVlBUWppWVFUWTZtM1ZpVTVKS295TkNnU0dnQTlkTW5RUmxFQmFPUzBHa01YOE5ndzlCSW1IMk5CbjJKdFQyQ2Y4YUFoVVNqckhpRFJ2Z3pmNDlST0J6VlJoTEdQMzJOVWVBa0VnSlBPSTVFb25vL2lLQ3hvR2NiUnFRQlJCN0NNY1M3dzNocEFQeGZ2Q0NlMWF1bGE4Wk1HWmcxVHdabXpKZmVad3ZGKzhkbkpQQ0hQNHIzOTgrTHQ3eGFodmJ2aytHZURqUk1EL0labG5aRUcyRDh3NGhyQ0tyN1NGUWJ1Si9weGZrM1I4RjRmRERKanpna2dySVRqOEZMZUFSMy9PQVE4YkFNd3VCK2VGVDVEK0ExR2dkNEEzbnk0SmtCUFpjaGxLRzFWU0pIRG92bjlWMFNPWGxTWkxBUDhlTGRjQmpsRUFSUHpEdUlaUlJoNzg1MFdPNVJDUXo3a1ljUjhlS25JSDVUdnZGd0dDbndsekRTNG5OUlpBeXg0b2NBK0FEUHczeURFVjQ5akZKZ1IyTGx6SURveVlkM05LcnBoWkdURU5MUk9tS3hhT0V4djBQaTBwSkZIWU8vSVR6cFJRaXdYR2dpc1lyZkFTeGdGQU9CZ0d4NDVSVXByYTZXK1dWbE1xZW9TSW9ySzJYZDVzMW9mMUVaR3JvOElkWjFBTzlNMG8xRlNhNTdQaWsyeSszU25YYWJuTXVZTG1jLzhra0pQanRicExrQkRabE5iR0lpQ0FYUnVJZGpMWXVWcndpQ0VBNUd0T0VPK2tOeXRyWk9Ocjd5bWhTWFY4bU1PWVV5ZDBHSmxORE9uMThzSlpWVXB5dmx4YlhyeE9zTEdNSk9RTU9maHpFZzZtRlBDTnlNYXNNZkhnWDRkTFdJRkM4Vi84TmZsZ3QzM1NhMW1jblNtWlVrQTVsSjRrNU5rcTZrSkhHbUpVa25qcmJzSkduS1RaSjZYRGZqdWowM1Izbys5VkVKZlBkckltdGVnNFE2a0Y1UWhrTitCUXVmSHhDQk5BRXZsOUdWd0dnRVV0WC96QnlwKzd0dnk4bXZmRTNPZitQYk1ycHFFVEx0a2w0K1lHUkRQRkhrQzhJb29VRVozcnhSdkk4L0tZSDd2eVh0bVhuU25aNGw5cFJVY1NhRFYvRFhScDd6ODZRaE8xZDYvK0poNlgzaVNYRy9zbG9DWFJkUXdPQnFDS0NBUHdXeUdBWERDczFHWWlFRE9CVEs5YUV3ZnNPSkQ1azZWaWUxS1hkSWUwNkJPSkp6eElaMEp3cDJTNVowSktWTGEwcTZYRWl4eVBuOEFtbit5TDNpZk9qeklvOS9EM1ZRS1dLdFIzcDlFUG9ZSUxNcEJQRlBPelB5Z2pZQlVJdWdETmlaS0pGUGh1c2tmOWhvWTV6VTJON1ZMU2ZPbkpXYUN4ZkY3dXBWTmxoWDJ0R0FDT0FteGRmaEpOMFlsTlJYa0lMR2xpVGRDSU1Jb2FSTWFVa3FrTnB2L1MwRXZpYjIyTldKWUVRZ2lxL2NJUXBMakd3dXQyeDc4eTBwaFFvOWo4T3RzVkJZWG1rY0s2dGtObXo5ZWVWbHN1dXR0N1JoTVNZRk5jU3RXbEFJdlZpVWNVYkYzMzVST243MFUybVljcmNjdTNXS3RFTmcyOVBTcENjdFZYckF2eE9CWUVRZzZzS3hDZGNVY0dkU3N2UW5wZUdZcHNMZWlHRE5USmRqR1puUzhlSDdSRmF1UW5LQVg2OFB3bVBJc0dxSWNXUUNVWHlnNVBWLzlwdlNpL2o2VXBMRWptUGJ0S2xpZitKbitDbWdHbFlVUituckVsZmhiRGw4NzBlbExXODYrQU1BNFZrUEF0OVY4RXhQRWdmQXRCdTh1OUxTOFh1eUhBU0kyc0NuRTREUVhIQ1gyUDdsWHlSY2UxckxpWEZEZVRRS2pLd3lxUFppbEQveG5BK09RcnNhVldUQXcwZjJTRFBTZGlDOUtJSUxQRThVT3NDTERVZDNSb3E0OFR6Zk04bzVUVHdXQUZOcXZqU21USlhhajM5S3VrcG1pamdCVE9nMnlKOFQvTkJFVXZ4aGdSSU1jYzdmR0VhRytQLzZpZFdnVlJFanRyLzRhNU11MVpsQjhlQTBTZi8xbEZTTDNyZ2hCMXJETkFnUmprT1orU3E0cHpPbmlUejltOWhqRTlHbENtVTF4elI1UFhwOUlWbjE4a2FaVTFZdXp4Yk9WK0NaWDFVTis3NVM1c0ttbjFsY0luTXF5bkN2VWw0L2VFRDZnajZWSno5NmVZSWNEUk5lai9ML3NGdmNwVVhTL2Q1UGlBM0NmQ0hmb3NKc2g1RFlrSWRPQ0V5M0JZSUQ0V25CZVRPQXFEa0RXdEFVQ0xVbFZmcndiRC95NVFUNGRHVm5hcTlQQUdad1pXWkpEYlNFTXc4OExITDJwRVJEL1VoMVJQd0I2a21YVXp3UU1VU2hTL20vL0tqNEVFOHYwZzJRRDV4ZnlKd3VzbVFGdEN1UGpMeTZSYnJ2L1F5RU9WMzZrcE9sRGhwY004cTdBVHkyUVd0ckFBalZndTg2SEpzQlJ0WjBhSG1wNUM4Vm5ZTUJVTlRxMm5IZWo4N0M4WUcvRW5kSktiaWgrUVhSWjVuemhJVUZrNDlha0lvNS9rR0hWRE5QWUZiQllKR09OMTZUeGx2ZUp5MU1HL0UxcGFWTUdOcFFobzNVMk1CREY4NVp2bDNwcWRLV21peXR5RXNieXI4Wjk2alp0U04vWnovMDU5SzlGTnBTRkZBSmZtaksrV20va1RjRDRmVVFHSTNJS1BtNlRob1pRa3RCMElKQWlJYVJVT3g4S0RLc2RSUVBPanhub0xaa2RIaVRkS05RRXRYd2RnaXBOU2REemtDUUxxS0J1cE1zMG1YSmxOYTc3NGc5TmdHeEFjUXFsUUFVaVE2cklEajdQYkoyNHhhWkF3MW9aa21aenZrb3JGcW9Ea1lHWHZPM09XV2xzbVBmWGhsRXcyUjdqYUpYRCtHY1lFVGZRb0R0YU5nbkF6Ly9oYlNDTjJvUTdSQU1ha0NlbEV4eFFhZ28vRmJlQi8vdEZnZ0k3blVnZEFLY0tIQ3RFUDVXYUlCdEJDdGNzM2UzSjZlTE5TdEhnaWtwY2g3WFBYZytpSHlmbm5LYmhOYXVoQlQzR2dKOUJZb0hJM1QzMHZ6Z2d3b2lEVXdmY1EzazVJb2pMVWNpOTM5SklxV3o1UGhkZHdNTWsyVVV2M1ZCc0MvbUdRRFVqN1RKZXkvdURTWkQwNEMyNFlWQUR5Wm5pQXZuanFRVTVEUEZNRFVSZHg4NmkxNEF3amxjWDd6emRvazg5ZzlJbnI0bkEzVG9lNk9vMHpOREh4TVZJUTJvR0dwNWZ1Ym85Qm5rTjExY1dSblNtcDJzSURKUk1MV2hidkRJdkJHRU92a3VBS2sxdzZLQTZnQnZiZ1JxZUt5WGxwUnA0dmpaejhGS0ozZ1prWDRFZ3BKUndkU2J5Q1g0ZXljY3lLaUMydlAxY3VqZ01kbTM5NUNjT2xralhaMDk0aG1FTnNycUFSRjQ0djFHUnIxTjBvMUdTYzI1NmRLQmh1YTB3RnlEUUxWQlNMb3B6R2hjclRBUkVsTE10Nk9xTVM0cER6MTlnN0p4MjA2Wk1iOVlKNkJ4SWhxSFhoazQ2c0c1SUlXVjFUcExkcy9CZytLQkdjYjNRa1AwY3BpakhMRXc0aEh2ZDM4Q1FjZ1FPL2p6Z0NjMitBNkVucFJjRllCQm1ESGRsblJwU2N1QTZWVWd0cXlwNk1YejhZNUZoWndDVHlCaklGaDE1a0tZY2kxU0EzQ3lwbHJVVjBPdGtML1RiT3EzM0NYQlpTc2dNQURGTWRCNU8rbjlxRS9xUHZkNUFKNUYvTm5UWWNMQWJJSDJWWWQ0bk8rNUJVQUNEYTRnVjJyQmUwYytnQXBnUWkwdEFnM0hud1RRU2s2RlJwVXU3dVJNUEpzQ1VBV1lRaU9obGxTSHZEWWczODdzUEswZmdnSHJwUnZnU3FBbFFEbm56WUYwZTlXL1piaGtvd0R3ZmdPTW9JSUV3U0xMbHM1amhTMnZUZHlmL2JUVUk2NEI4c2c0SmdqZEFFVTdlSE9rWjB0N012Z0RiN2EwWkpqeWhqOHVDSjRkNmVBWFBEbFFqaVBRUXFtWkhybnJGaG40M25kRVhFNHRSeWRxVnVFQW1oSHhrZHJSTytIQjlrTVRXcmgwaFN3b3JaQ0toVXYwT0x1d1NGNWN1MEZjNkJCTnVwSWpleEtVYml4S29tQUxHcHdmUndxNEM0MThBR1pDTnhwVVBjNFRFdXMzVnFmVWpLZ1JFWWllTFZ5Z1E2eXppeXBrZnZraURZVmxBS2FTS3BsUldDcmxpMWZLMWwxdmpRMjNrb2FpYUtMMGQ3Q1JSbzJSTGZuUkQrWEluZE5nQ3REblkyaEJ6dHcwOWZrMDV1UklFNFQyWW5hcW5MMmxRRHJ1K3dzWmVQZ2hjWDdoQzlMNytmdkY5NFVIeFBQQTU2VDd6KzZCTnBVakhSQ2FGZ0l1QUlFOVBrMnJqaFNMdEdhbVNTZE1EVGVFMzRNZW43NnpsbW52azVFOUwybXZTclgrcWczWEh4RDdWNytoWmlLRnV3ZmcwNXlkRGhBQmYrQ3RQY2Vpd09SR1dmWWlEVHJRTzhDM05XczZBR0dLTkFMNGFZSTFRSmd2Z0xjVzhOQ0owTVg0Y0UzTmlGcGZIUVM5QVh5MzRSNUJTZjFOQUllNjZYZUtiSHBaQVVmOXhXR0t1VjgxSVU0eTdzWVY5U1JrSWxaUDBFczJyNVhhK3o0aTNvemJ4RXBBbmlDMEF6UzdvVUcyWmFUSkJhVEp6c3BPTUFRL1hwaVlkWHlHb0FVd3I4VjFEVHN6WEErQ2IxOVNqdmlmbTQ5ZXhpMTlnQjhGSVA1RDlScXdjRGs0L0NsRXpabHIwVGdEbSt2U0dEanZpTE95S3dCU1BUMDlzU2VSMmpqdGFOSm5kR05Sa2cyTmlZTFlCRUd0bjRZZUhNTEp4dTlKblFJQnk0dzlOZ0doUGpscVJxS1BpS2FaYWtRQUlwcGk4MHVycFloZ0ZEdWFZZGVlZzJOTmtiM1dDRWRjQ0VRMCthZ1pSY0xTVkhOV2JCREFGdkJIOEhHbFpxR1I1Nmh3WDV5U0tZT2YvRy9TdmVFbEVXc3pHanlFREdnNE5EeXFJeXNxZUlpTFE5azZURDhNS1RoMVN0dy8vNVhVdk9mREFJSjhjYVZQVnpPT21naWQ0QVE2QjdTYUkxTlM1ZFMwZEpGcGQyZ0RKaUJkVlR0QzZIem9VYkhHd0VOSHd5Q1EvZFF1Y2Q1QXJSTm1UVitxRVg5TG1rVTZQdkZSOFQ3K1BmRS8vMHNaK2NOTUNUejlQTTVuNi9RRDMwK2ZBcEErSk0xWnQ4QWtoVmFGL0RjaTFDUHVyc3hNQ0hpZUJCQ2NDRTFwdVVKTnJ2bC9may9FQXkyQXpQVDVVSDVCQ1F3YjJxYUVVWjRSR0VsUm1Fb0Q2Q3g0RDNuaTBMNi92bEg4KzQ5TUhBNGRrSkVqQnlXOGRaTjRpdWRMOUxlL0ZkK2ozNWFHVysrR1dacXZBd1hVa3RxUjV5NmMyNUh2Ym5SbXJURG4yak96WkcvQnZiQ2pUcUlPZkJMaEZBR3FiMmd1UnQxZlB4Z1Eyemp6MnRTNGVWNjBjUEhZdmYzNzkwc29aUGorekZHMVNib3hLYW1UUG9BSlFxSjVSQnpOWVJXN1BRSGRSNFltR1gxRE04ckt4d0pueExLQnpKaGZKUE9LU21YL2dVTUdnQ0Vhem5oaGxPTG52Sm1vK0JHWnpsY1o2SmIrZTlGelF4QnQwTnk2OHFCTm9OR1BJTkQwYWZ6VjAyaUpFTHdFMUJQcmtSa2w1Y0JQcG50c0VueDZ0aHhOdWd0bVhySU0wRXdEbU5DWlhJdjRPN0x5TlMyT0dza1R2OEg3YmlPLzRJMUtHNmNYU0FUQ1JTMWpOQ0lERHo2aXdraWZGRWU5YU1vUTRPMHB5ZEk0emZCejFlZmNLK2VlK3FVTWRiUXpBdlhzNnV3Y0xVZU9kUmx6cDNUb216MTR1MFBPTEYwbnA5NzNFV2hjVTFXVE82Y0Nud1lBb3A4UDhTT05EdDVMU1JQWnNSWVJSWVd1ZDhQUkZsVVRMUkVSWTNYVWphL2dTTkNsbzV0MTRTT2pxSDhacHBlSFRNZk9xY0c2QjZSanh4NXB2bTJLOHRiQndROGNxVDAxWjJVclFBMm1wQUJNTTZYL20xOUhqQzVWZEhXK0laM3BBRXpOKzNVU28xaFFoamFIZHFjanRRQWd1Z0FLS3hiSm5QSnFXZkVpdE52WWM4eW1VU1NtSzRDWm5waE1iY284eG5kS1Y3bzN2dE15MHpFVzVUSTlJNWpMVWN6bnRkeGp2dGQ0TXJVM3BoV2YzcnRScTBzSVJnU2hSUE9JckRhSGJIcDFoNnJLbkpKUGpZaE82c0pGaXhXSTZLaW0yVllFa05wNzhJajQvR3pjUmh5Y0hLZ3hBNXRDS3BJc2JNalRxaFhTQUhEZzBMTExraXVOQUlzdUNEdDlSSzc3UGlkeTloeWVOWGlhaUNoYXNBV05MaFQxWi9TUlNMK3pWV1RkV3FtNWZScUVDVDA1VEE4ZE1Vck5rUG9zYUdESjZXcHUyRDcyMXdBR0xyUmtZOUFJRGNDQVpCa0FEUjBqQmtZdENHOERJL0RyZU4rSFJFb1hpOWlSNWlnWVladERYUFNsYUFGcU9iQUlSaVJFRFE2bXE0UVFuSU9xVlhSLzhTR1laUm5pemN6UUFZYVdYSmhPdWRDMmNFNHRoTnFkNnhkUGdLZFFiRklqT3c5andtZ2lndDZIdW8xQUthVXBSNVVGZ1R3TXhRS3lTRVVUWjBaZ2xobndtTGlSa2JZV3FYdjBNWUJQbGpSRCsydk96eEVYeW9BbWNGY0IyaERLdHVVVEg1ZWhnVVlqazN3WFlLVDF3cnhmSnpIS2ljQ29FbTJReVVTQXVDd1BvMHpNVERCY0c1bEFRQkFZYjdielBCSmhnVnhPWVRXWjQ5TzZVa2hNNDlPS1A3NmI2SnJBYUtKNVJOU0lDRVN6Q290bDVvSVMxWUNvTG5PaG9xNmF4aldCaUEzbExRQlJJRGFyZW93UU42Y0RzbFVGVlVwQlE4UFMvclhIVkV1aGh1S3daS2dQaHFOSk5IczhjMmFnSVVkMUJDa2hvZUVMWjNRVC85QTJ3aEhPWFdJSTR0SWp2VE9la3E3a1hLbURlZEdUbGl5ZXRHeXBzU1RESEV4VnMrTU10TEJvZVJFZ3g2OEtoL0xPN01kQUpCRVljWnFFNDUvL1NhVFhodlI4NGh1QmZvYTg4blZPNHpRTGcrdW02RDJMQUFCR1lLSXFJRUVBeUtjMG5aWDZEMzlNUjdVR0MzTGtGSGh0QlFnTkpDUHUxQlJwQm1oZWVQK0hrY2NCZFdRemNzNit2cWEyem1mQUEvbmhQTVVRemlsV09EV0FCM1hDRGlPRTRFZndnQi92TURWUzFoVUN5K1I4TFRTaTZSTEl2bE1jeWNZOExuWWE5STlSdTZ6Skx4RDNyZzFHcEpvZUlaQ21PYzZ2a3hqbFJHQzBvTFJNZ2VoUEJhTXJhU3NreWdQRGVBMkY5eTZmM1gwcExlNFVRQTNwMGlKZDQ5MzRPSmplZUxlQWFXYVNUTkNMLy8zZFFra2NrWmtvbUFWR1l2Wk5kd3lQNmlPaWFVYU5DRUMwb0hLaDBSQVFPSEkybzZoRVRiTUZ1TjV6NExCNEFzWmtPSFBCb2hZb0l1TFNBaVlUVkw4UkhtaHBFRnYyKzlWWlN4N29lK21BMFBVREpDNmtaOHZvMmNQcUIrcS94TnBWaVlJVVpvK3ZUQ1BnZENneUNwRWFoUmFCRzU0bXNYLzY4OUtjbkNKT2dKRUxhWEYrRGRQbGFCSkhqQnozZndYQzdZUkF4Z1EwMXVIUjdKZ1lqS0N4cEUwVjM1WTFLc2dEQ0w1aHhJSjNLYzR4R05heXZPVFBNRXhpaW1zRTVlS0VFSEVtZkhoVnRUU2tacW1UbkpNUjZadHF5YlJBMkZPa0JhYXNOU2xicEt2VllBMlIwdVJUU1UxRVJGam1nOG5qVkJuaU1WWldHZ2ZzWmdvTVQ0MHdxblZvbUpkKzVLdGI3RC84am9JUWgvblBvaHc0U3RpZm1xMmczZ0F6c3ZzNW1OVlJhaFdJQUFKSHpjak04ZlhRdFlBUjAyRmcxalRBVnJ5MFdIWmk0dk9jcm1LK0d3b2JuV2w4WUhrSFF3QWE1RzM4L1lpT0VMTUlPV1dGTGc4V3J3R00zT3lORkE5RzVqbGxRd1BPK1J6ZjU3azU0R1BLMEx1SkVvTVI4bXYyRGl6czhmT0k2Q09pYVVZTmlOczRjTHRQSGdsTVBOSkhSTk9NR2hIZkM0U0NXcmhHZ2FJcDRZK3JwN2dHaWhOeWg0SSs2VnUrV0xXQURnaVpnK1lUem52U0tIalFqREp2Ull2bzQvSXNvNFVsSUFvMm13Q0JSQjluNnpXRkRIR01BaFpHeXN2RmxsWUFMY05JeTUyV0prMVRNN1IzRHdBRW0xS255WEJIRGVLaGRvQVhXUnhzTTlwdUpnYWordFNwSW80V25XZERaVWVkOVBoVHJRNG1HNTN0WTAwcWRrSSsxV1RqZzJDOGczZDhOckYrNWpPSUh6d2hES1NtU2wxNm1tb2lyU2duRHpTNDRkM2JOVnU2a1JnajRrVUNDb0V6K3E3b0pRcU4rQ1FDcldkMGxCb2JNa20wNVlJMitvZ2k2RWdpT3AvODhnQ1RMdXl6QWl4THhBdEE3RU1aMEovRkNhYm5MT2tBejFSeHBsckUvby8vaU1RQ3hveHNhTllqeUx0T1A3aE9ZaFluQXFQaThnb3RUd1ltclVBQUVMcldWZnY2RHY3eEdBODRVZVRCRE9hOWVERGlzK1k1ZzlubUdVd3dJckRFMC9qMWNxb2g0Y2hBdVRIUCtaNEpUdThtU21pbW1UVnh0WGxFZEZiVEhEUG5EaWtRbFZYSm5BV2xVbHl4VUozVjlCSHB1eWhBbzFJWWx4SDR4elZiOUZ2d1BJb0czL21ELzYwYUFHZjhVc2p0NlAwNTZZNGFrclhnenhBUjlBcktna3BjQWlMd2dHbW16OU1vNjk4TWlFTVZZRWViMU9iY1pveW1aYWZvc1BuNWFSWmoxamJTcFQ5RXRtNVJQdFdVUkt2alRGL0dPVEVZY2JiMUZPU3JUNU1URHpMSUZoc2VOaVlCNGh4V294WXhpWXVLNldkZ0dZVUF6aXFza0gvRDlCb1ExNDkvSlBhQ1BPV3ZGM1ZEL3hZRG5lOTBJcnVLNStta1VhTk1qZndtSkRMR0IyTmxRaGxsemdpRVhrYUVQNDBNUVMxSC9NNDJRRkJob0FYQkNZeXVZMitKTC9VZTVZTWFaVzltaXB6blNDMnVQWnhOL3NsUDR3VjFpV3NFQkx5SVZ1TDFFZG1lQ0l5NGhRajVaV0EyakZiTVRKbGhZanAyNnF6WTdNNnhPQmdHZkVFNWNPUzRuRDUzUVlMUTluaVA5Y2oxbDF0ZTJ5SHJONzBpTzk3WUl4Y2FtdkU3ZGR4TDc1NnFPYWZCdEJKTUloQWRPM1pNZkQ1MkJ1U1JaV1Fzc0c3djZnUWZKeEZmL1dWeG1TM3czVUtKd1lpMUhjc3o1V2o4UENLT2x0RlpUUjhSVFROcVJBU2lCU1dWc20zbm0yUEQvaVJUN1NRSUJZZTRzTlBvVmRDUDRCd0pvWVNIY1c3NzJIMDZOTjROTTQzTEZsd0FJeHVPRFZuSjB2L0JUOHR3bEN2YThWYmtHcnhHcHFDeDlwQTRCWnpCQkVLdUpLREVOOXovZVowbDdTaElrem9JMDBVQWl4dGd3cUhxcGd3QXlyL05SQndlUEVrQmdwWVg1cW81MHNSZ1pFL1B4ek11QXpmQmcwNzlnNjFIRnhZRm44blRqMFZBTW50Z0paNHdnUDllUDhCMzFDOGppeXZsVkVxS0RHUWI4Nnk2b0MyMnBXZkZURFlBNTlPL0EyZUkzMkRSQUxFRXhHY0c2ZUJYZENGdmdBdUFCbjhaR1hVcjM5UkNXWHp4Z1huWC9JOTY4TXdBbUd5V3czbTNxOW5ZQm0yVzg2YzRrNXoxeDQ2bGZlcWR5Q0RMRDhRSVJ1bUZVbWk2TGlJUDEycW1tVjJnQVVKbW1Kam1vTVBkdG11M3ptNW5ISjVBV041NGE3OHNXZkdDSEQ1K1N1OTUwY1ozN241THFwY3NsMFhMVnNyaTVhdGs2Y29YZGZIM3ZrT0g4YnV4aUpsaDlmb042bFRmZi9pSVhwdGt0OXRsMGFKRjB0WFZkWm1QaUlDeitkV3RpRytGdkxoMkRkTFhlZlFhZEtyRXU0aXVRVE5DKzV4Z0hoSEJpS05tZWw1VW9wb1JOU0lDRWF0ZC8ra0pEa1I2T3NNUktZR0ltM1Zvc1k5UXhHa0tBR0JHZlRBN3BvdU53czFHbkpVR01FcVdqc3hrT1ptWEpNUDNmeDJQQVlTQzNPd2tzYmdScmxSb1dHL3E5ekNjc2RRN09KOXBCQXg0Y1dkMDV1OGxuR0k0eW11bVFnc0RJTmt0eVRyQ1ZnUHRKdkRBOThIZklJUUptZ3Q0cEQ2Z1R1SUVZT1JOeWtEYTNjb0h1VlV3QzBMckFBQVl3bXlBa2RuQVZFdGk0Qm9yUG9BYkxQMitTSy9JdnAxeU1UTlB0WStMMERvNGU3NHhMVjFjME43T1RZZEovY3dmdEZ4WmxPSWRObllOU0VUMmN6SzRickZZbjN4QzJqNy9KYmtJUUdsT3lnUVE1d0JZMHNTT0RvQXowM1grRUk0TXZiRnpUbG5nb3R1R2xGeTBwRHZrYkpZeEFrbHp1dE9TSXEzSk9kS2FsNno4TnJJY0FGcmNiTVhJYUFnbHAvcmhkUkdMNkU4Rm8ydlpBNXN6dXFucE1CMXFQM1E1Y0xlSlY5QWhtL0cyZHpta3JHcVJiTmk4VllHSjk3aFR4VXZyWHBhNUM0cDBCd0g5VkJMdWI5aThSV2JPblNjVkN4ZnBmZE5IUkRDYU4yK2VPSjNPc1pFN0VqWGR5a1VMOFR6elVpSXQ3VllKUk5qeURLM3AzVVFKd1VqRm5ZaUJybnpwQzV2bCtlcmxNcmRzaVpwaXo1ZVd5ckxTSlZKY0JPMm9yRXhtTGtSaldGSXBieDdkRDFNREVrR2ZVQ0pDWFlSMFdObW9XRGw5V0J6UUpqalJrZVlJZlNTMnpBeGRqR25OVEpYK3Yva0tlSUp0elhaazJqZlhRMndMYUNpK3ZkdWtPVDFiN0RRSElXdzJBQ0FCa1dYUWtaMHA4cWxQb2ZwcHBzSE14RHRjLzZXcEo1aG54SGxTZkY0emgyZjF3S2FOZXlNMFRhK0JkQmdjaVlYMzdKV09qSFRwZ2NDM3BhVWFpNFBKTDgyaDFEUVpmRzRtNGpUbWhXa0NLbmRRK3puRVRCUkFOQzRjNkl3ZjJydFc1TXVQU0JNSENYS042UUU2ZHlrbFZXZFVOeU0vamZsSjZvK2FLSFRnK2JNQVJUZUF5d1ZOaURzajlFTTd1b0Q4OTJzWklIN3daa1U2ekx4YUlDZ1Fka1R2UU8wbEJLUHhacHFSSmlEcEduMUdaYVhWOHRMYWpZcnZweHNiWlhaNXVXemZ2VnQvR3lVNmdWNS9mYmRVVlMwVWo4ZkgvbTZNdkY2LzdxdTBlZHMyNVRPTXpMKzhkYXRVTFYwcVJSVVZzdnJsbC9VNW11ZGRYWGFwQk44Mlc1ZkdNYXlUN1VScTZ1cGtYa21KQWxkWkZVQnc2MnVhQi9xcTNvbnl1NUVvSVJqUkdPSHM2QTFWSzZSNlZvbHFQYityS0pHNVN4ZWloNEI1Tm5PdVZGUXZoWXE1U2tvTEsrWE1vZE5heDlTQURNMGhBZUZaZFczamowOFBIOTByM1dtNU9vdlpsWnltdld4N09zd1JDQnhYczN2K3g4T1h3T2dkcUEwVkRvQ1JmOTkyQlNPT0JsMEdScmh1NVVqZW5YZEIwRGtkQUF6amoxTVVSOVhHbkZnem1oaU0yTVFUMDdXQUVRWCtTbUNFdmxmajhFZVFNbHQ1ZDYvWWZ2VWIyWXY4dEdRVnlFQ3FSVFVjVzBhcTlLUm5pQWZhSVpkeWNBREJtY3lwQ2FrVEJyN2JsSk9xenY1MlM2cFl3VTlQaGtYT2NhMGZ6TFdyZ1ZGRStieCsrbFBBNkQvandDNHFycEF0cis2VUV4Y3VTdW15WllpN1NoeDlPcHRMRTJkOEd6ZHRrUlVyWDdnVVA0SnBjaE40dHU3Y0tWNTBDTUhoWWRuNDZxc0tTQ2ZQblZPZ09uUDJuRDVuYmJjaHJWTHA2blpjRnMrbTExNlRGYXRYeTREUEwxdGUyeWJMVnIxd21YUDgzVVNKelRUa2VIL05TZFY0Rmk1Y0xNL05tU1BQdmJoWW5sbGFMZk1YbE1wL3JGc2k4MkhQYmx1L1U2Sk9WREQrZk9HWUNubU5taEhnVG8vVUV5S0gzcFN1MUJ3VlloT01LSGhXQ0RwWDQwZSs4SWo0M2tFd1Vwb0FqS2lkY2ZGcXM0Vm1CdUZWR2RaejllYmU0R0RFR2RtRDBTRnhVTFh0YXBmV1AzOVFiRGwzQTNDeWRVREFTMU9NZWMxSlYyMUdsOTF3aXhVQVNpUHF2eFgzSmdwT0FFNFhnRVozVTBCZW0zQ1BQaUpxV213L056MFlsVmJKa3BVdlNmbVNaYnI5VFhIMUltbnQ3TlJsUjR5TS9kSExHemZMcHMydmFOeThiNlpEUUtKWjl0ck9YV09PN0RVYlhwYVh0N3dpSWJTZDVTKzhLSlhRcURoZG9OdmVBM2txbGs1b1NPYTdnV0JZQVd2ZkVjTy94TDI4U3dHR0RZM04rb3oyaGU4aVNqeTBEeE9OVHNlTEFaYzA5WGFJeSswUWEwZWJxcFZ1bTBzY0VhY000aUVPU3BxQm9LSjFmUzJsRmFWbzRqbjhFVjlNTUtKbTVJQ1FFQnk0em9uTEh0b2hlSkVIdmc1K2ZFWWkxOUNZcm9rbUFDTVh0L213Y09FcmdabGdoSXlwb3d0QXdqeE9DRVlBc3Y5aU1LSjV4anFKOXRkSjNmMFBBTnh6aFN2eHVjaldEbjd0NmVrNjRzV042RGlWZ21ZYkYrNXk1YjByTTF0bnZVOFV2SGlYV2hGOVNIMEVwbXhqQWJMdWtKQUdvRU04VndhajJES2c2NlQvNzJDRU9EaWhkeUUwbi9OTkxiTDhwWmRrOGZJVnhvNmsrSjJ4RUhEb21DWXZuRnhwcGtjLzBmcE5tM1VIVS9QZVMrdldLeUR4dkxYREp2TkxTdFhKYmJNNzFML1ZadXZVM3doVy9Cb3V3YWk1UXlkMzZBamNvbVhMNWJWdE80eTBFN04vVTFGQ01GSzU2eHNRMzRHM3hQdjZacEdEMjBTMmJ4VFp1VTFHOXV3UmVSWDI4MW1ZWnRFK1BCdWJ5TVphUWJnbVVVc0FSbXpNVFJDVUxwaG9GQnJ2Zlo5SEgyOE03UnRDOXc3UU9ERGlGaG1kRU5aM0JSaWhxTHhlbHd6ODI1UEdqT2k4TEoyeDNRbGVlYzMxYnJwVEE4NTFqVmx1dWx6TTVpNEduR0Nab2V2ZUpncFdtTlRkZUs3dHppa0tTRnpmeHlrUjNDenUvSlNNbXg2TXVPQzJkTkZTT1YvZnBIRWNPWEZTbnAwNVM4N1dYakFHSUJFMnZySlZ6U2N6blVHL3NVaVpnWTdxZFJzM0taOE1tMTk5VGE5TlRXbm43amZWRjNUZ3lGRXBxYWdVYTJmWDJMc0VyYm5GeFdyV01RMmFhWHkyQXZtajF2Uk9sTitOUkluTnRHQy9SR2VVU1dmMkI5RUQ1dW8ycnU3Y1BBVU1iam5hbG5hckhFNlpJa2YvNm5Pb2xYV0FiN3NNaFFlTWdtTHBKeUswQnhPTTZPQUxIWGdEUXBhdFF0eWJZdEVlbTg1cjlzSTAyZXdmK0FSZ0FMcWF5dWUxSkhBTkJEQUs3TjhoTFJrNWw0RlJKM2k0MmMwMFRlSDBVV2lXK2VMQjh5ZW4wN2RqYURMY01zVUYvbGl1MXBRc3NYM2lVK0w0NXg5STc3Ty9rc2lNMzR2OCt0ZmlmV2JHaE1FNjR4a1pmUFkveEQ3dktUa1BUYWdlYWVoUVB0TGdpTnJWd2VqbU1OTTRiZVVGbUdFQjdocUo2MGdZMnM2R2pWSzlaS242amhqTFd3Y09xbFp6c2RFQUxBWnFSZFJ5WnMyZXEzNGhtbDEwT2xPcjRmdW1BN3JIM2FmYUR1UGpCTTFPUjQvdTY4MUp3dFNhWGxpM1RqOHNRSk9PNEVSUW1qdHZ2dFRWTjc0ajVYY2pVVUl3Y3JIQ09xM1MrT1d2U2dPWFM2Z0pnOFpNWVV1enFQQUdJYXowUFp6THpoUEh2ejhKVGFvVDlXd0lYRUxDTTZhQTAvS0tIdDR6cGhtNVUyRkNJQjJ1d3lJb2NWdlh1aWwzNHpuRFRPTXcvVHRDY1dERUhSL2p3WWdDZnpNN3NQbnRqdjZmUEtuTFhGaHY5Zm5nTTRsemxRcDBHZ08xb1JQUUNIdC84UXVSNW5wa2pFWTUxOGYxSXdwT1lhQzRYejNvRGdhakhsUmNvelJPZmE5MEpLWHEzbGdjbGFRSmQ3T0QwZXpLS2xtOVphc082dyt4dVNFQ09wdG5GaGJLN2tQR05qZ2REb2M2cXBlc1dpWG42dXRsTUJpVTA3VzFzbkQ1Y25ueHBUWFMxeitvSmhYVHBtK0pQaWFURjc1UFovYUM4bklOdHA0ZUNZMk15TkhUcC9XNjArbFV1VER6UUsxcjhaSmw2alJYdjlXN2lCS1BwcUVFV0FoaXV5Qm5IdmhMTkNwajQvc3VOT2hPcU9jVUJBcHRMOVJ6T2pGcmtyUEU4NU5mQTVDOCtobWdoSVJLQ25QcEFSSmh4Y2pKZzJLMzVFa3I0dVVFT2dvMTkxbm0vQlZPaER4dG1XS0FFVjdoOFBBN1FoT0JFY3Bnd3FIOUd4eU14Tjh2YlhmOXVmckJlbEJIM0RpdU5YZXFuSUhXeWUwOWJFblFjQi85cGtoL2w4NUxha0ZTYW9XU1VRVDI2Qk1GN3JHdno0b2JXdk1kTUszVGRTVHVmQTVONjNjSEdLM2QrcHFSUmJ3YzhCbDE5dEtHRGJLZ3VrcUJpRHhjYkc2V2lzV0xaZmFDQlZLK2FKRU94NWN0WENnOXpsNU4wM1JzcjEyM1FUWUQzSGhPZ09LN3RBaFdybG1qNEdQdDd0WjdqR1B4eXBYYTNmS2FaaDFOUXZLeGZjY3VxVjY0V0hyZHVtSE11NFlTZ3BFdThCejI2UW9tYWJOS3gvLzRCNERFRkRWZjJpQndQUWcrYUE0Y1BiSG1HMSs4NkVlREREeitJNVJpdTlpWkN1dWNzM3g1d2xtK28wT0FFME13dFdwSHVNZ0N3SUlMcnY3cXpydEQvUm5jWUorak05d0F2anM3SHoxdHVqUmszeUp5ZUFzMEkvUTJyQ255eGNXbi9PYVoraUVZRTlkMUdZN2JSTVJQSVlXUWNPaXQ3WEptNnEwNndzU3ZacHlhem1IdFBOMm4rZ1Q0Y0QvMEVOTEVrMlJhSjRFR2pRbDhBQmdUakc3RWVVYUJqanBvS2JmcGpwaHRlZW1vbXl4cHpBY0lFVGp4N25rY0k2Vno4S0JYZWROMWFPRkJ2Rzc0TkV6UzJmTnhZWXc0WXFwVjU1UFdwS25xd0s1QitYR25oVjZVeGRYQTZHYVpaOVRaMlNsdXQxc25KOGF2NE9lNnNXNEF4K0RnNE5qRXhTQTBvbnBvUmx6V1liVmFkZkppL0NKWVhqTXVsOHQxZVJtQ1BCNlA3a3JKSTRseDg5cWsrTDJNdUdUSVpyUHBURzM5d2dxaVVpMDlsa0h6M1BqNkNvRC9zbDBDak1BZEJIZzB0am01Uk15WFNjb2plNXhZdkVQY3ZJeVhzZmpqMDB3WUVBK2ZONFBHeTN0eDVaRFlaMFNtMFhpNEpTeVhhb2lyVFM1ODVnRUpwQllvOE5SQ0VEcWdMZkhiWDFUNzdianV0cVRLZ1hTTEFVaGhRRUlZcWo4WEZDSkJDdkJRQUhHaWZCU1FXRFlRSUoyUGpOczBoVnJ2L1pqaFRJV3dzSEZ6TWw1bmNxcnVrOU5oS1pEKzUzK0g1L1h6aVpvWkNwOHVMVUVjVVFDVGJzRkJ2WnJsbllDMDZDRlF3d2ZmZ0dZelRmd1p5ZHF6dHlMZERtaCs1TU9XbHlHanYzb0tqTWUyVGxXbUFXQTh4LzhiV1RQcVAzVkEzTW5UZFA1UEkzaGlSMUdYWTFFSE5pZVVXaEhrMEhiVVJaUzFxd0FlNVAvaElRa0dMZ21mbG5Nc1hFWjhCRW14ZTNHazNhNkRESjBGYWVwYjdMZGszdFNha1puWGVBRWw4WnEvbWVERTgvajlqRXpnaUFldjhhQVVmNHduTTYzNHVFMktQeDliTWhMTDFEQTZlVlBRRlRRZzZMd1haZWNTYXcrWE5wUXp3Q2djWm8wYlpLWnI4alNXWjhSdGdnZmp1MVNJQ0RHQTRmRnQ5MkxYSmw5anY0OEw5Snd4Y0QxbVlqRHloSlZCcW9rc2JoZG5ydGd2S2lCUlErS1FPL2NZMG8zdExlazZwTXVadVFRa052eStIejJKMWcwN0dFMmNLeHhZTkl4SEFZbTlLdkxNWGYrVUpaWURCTGIxc2NlZ25SajdDVkU3WWdPbnc1WDdSUGR4VXQ3RDM4S0RIbU5YUTBhSVRQRlZ4cXNWeG5Ma0pEOXVVSmFJV09kaHZMbi9EYVNUS3o2WWFOemJpQ1lodDkzVnlYOXBPU0pybHN0b05HSm9XNG91ZUpFRmVvT0QwU0EwdnI3a0FnVWVCUWdBN01VczhBZGVtVGRQY3I0TTdsNnZtN0w1MEdjd2Y3cGJRS3lIWm5tT0Q1Y1IreG9jdkg2N09OUHYxSkUwRytLM1pscFVXNzVad0doOHZnZ2VwbUR5dDNqTktCNVl6UGZpTlF4VGtBbFE1bmw4MmNXL1R4b1RmSkNaMXBWb2ZIeWtNWUNJQjRTNFlPNHdhWUlTUWVoUzNpL1g5a2p4K2REOE05NXhjYjhOWE1hQjBaWGVlVnZBNzR4SFQvR2ZJZUhRdnFIUEdKVVpWUWRCREpDZ0lkRmtZK1BqQndlcHZkRGhUSCtTcm1XQ2dGQnpha2pLa2M0bi9oa1J1Q1ZBcVlUY003dHE0ckFnOGFmTENNRVY4NGpTRmVmQ0NwaGtXZXJqWUh6MDQ3UWo4QXNVRktyMktYZUxIRDlzN0dwb2xEVUtQZlorTExQY0JkSlkxSnFBa0w2ZlMxZTJiNFhtVmFDZzE1aHJqQWgxQTJDNUxxNDk5Ullacmptc2ozTTFsZEVRa0poR1B4RVlBYVQvcTMxR1IvZWpidEoxcjJ3Q1VHOHl0SmIwRkdPN1dwWWx5am13cWxxZlZ6NVp4VndaaTRiSWRFMGhNc1BiQ085b3B6RFNLMWJMZEUySGU1VDNUQzlRcmV2cVlIVGpETzB6WDFjQ0NBcS95OTA3dGcvUitHMUE5Q3Urc1dJZWZ6U0R1ZFVIMzQzZkJzUzhSekxMbGNKUFBreGV4blp3aUtWdkJzWm92aDhQWkNieG5obW4rWTY1RDVJWnpMeVF2RjZ2cm8wam1XbkhnNTRaQ0Z3TVYwclRUSS9FT1BpTStSeVA1cnZ4NWN4emZnV1ljNnI0WkVJd3NyUEMrRDdWRHJ4QlFESk9vZUsxV2NYNzJiL1M3M2h4WmIwdkRXWU5BSWthRWswMitwQWFDRXJwVTJYd2h6K0YzUG9Va0tnaEdXd2lZcHhUNFJ3Tng3YWZaUnExWi9EK2RBaWVNV2ZGQWNIbVJMeGVOR2cyYnFZWCtLZWY0MkdQZnZDUnlxYUtOY3VEQUJFZEZjOW93RndyUHlHRmtCa3ZEWlAvZUZyYUxUbXExZkV6MlFTOWJnQVJQNmJvdU8vTDBBQ002UXJVSEJUMFNMcXAwZzBPUm0xTmNqWXQyNWhIQkhEdlFwNnNYTFlCL2pwd1hwdWNJdUVmL3dTRk1LRHIxbm9Id0JQWUk0L0J3T0JsamZGSzVFTVAxMC8rdW1xbE1UTkh2NnJiWWtuUmJZSWR5UHZORGtiRnBTVnk4UEFoOFFlTkFRc0tOWU1KQ0F6aHlPV0N6dmJSWWV2UzgvRWdZQWJlSnlERWExK204TWFYZGZ3N1pwb213REdRelByaCsyWSt6RGppMy9FRi9OSnU2OURyTUxSOHZZOTNkdTdjS1N0WHJyeHNQeVg2djBobVBEeU9MeVB5ZnFYNy94bmlkQVp1cWVJTGhST2JhVnlYUm9XZCs3WVFoVmhjTk5ub1ExS25kdU5SdWZqTmg2VEprcVdBUkEySkpodDlTRlRUMi9qNUg1Z0dmVW5UREVDQ2hxVHdNWVQ0b21nVXNHTlZKTDBSUkk5N3pEc0s0dXhmZmxIcUlXZzBKZmlKb1l0bzFCd3k1aWR4V3VqWG1mNStpVzVlaWNlNVJ3NTVNVUJOa1JJUmNuR29BVk1Ua3hZMWVHcjl5Ny9XajFoMjVLV294dUJPc2VnaTBETTRIM3grMWxoak5wb0xpS0NubFhDRGo2WjUvWEwrbzUvUWNpUVlVVnZwUXIxeU1TemZhYzFPbGZyODIwVGUyQ0pPbENVZCt1U3hkeGcyRzZUS2JJemppZmVOMzVDSHNFY2N2MzFLRjlkeUJMSWxNME8xWTViajFjSEk2TzJ2bDk0Sk1DS056eWNGak1KMjVNUnhzWGJhZExzT3ZzRlY5R1o4UEtkcmt1YzhjbnNSbnJkMmRFbmxvcVhpN0J2VTZ6Q0FoKzhUbGhpQ0FBSUcvbWFTQ1VvbW1UNG92bXZFYjZRZkh3K3ZDVFltT01hRGxBSmQ3QjF6WThPT2JydVVWeTlVYllUWDFFaVk3NWFXRmpsKy9EanVJQzh4UURUSkJETUducHNnWmw3SEg4M0FaeGg0bnp5TS85M2MxNHpId3VJeU9YNjZSdmxKN0RQeWNYeHJSQUVKQnlVdE9FVEVVVFlDd0ZETmNRVWsxWkJnc3RHSFJLYzJSOWs0RDRscU93R0pHcEthYk1FZWNJekdqdmhZVEZvTjZudEF3VE1OaFA2cUNySG13WXhBWFB5dVdWZVNNYVdBbzBKY0MwWE42OElIN3hFNWZCQUM1MFltd3pJd2lsNkxrYWwyaEVpTWZXRW5waUh3c1g2Tk9BcHVrVG9Ja2h0eDAwZmxCNmpVWmNHa2VlOFVDVjA4cm8xTnpXdmtXMHNVNThibkEyNXNNR0w5ZUo3OHBlYUoyNEIwSkhOclhmREY5eEFYQndsMHE1YXZRZnM3OWpycVprQ0d3aHc5TmFLNEVyRUJVMWkxNFE0NFJiYnRrdVpwNzlYUk9mcmJHdEFaRGFUbDNGUmdkQ1ZpUHMxM1RlSDN3ZFF5N3psNlhkTGpIdEMyWWQ1amFHbnZoTkF2bHNiV2RyM214MG5OMy9pK2UzQUFRT1hXOC9HaldYNC8yaVBJMUhMTTkzb0grdlZJUzZEZjYwRzZ4aGVQNHdXZEF0NlB1UHZ3ck1mbjFYdDh4cHdTd0VtWW5NSE5OVzY4WmpESkJFT09EcHBFVGFrWGZBNTRCc2Mwdy9pME5IN1VKZE96OXpqUTcva3VlNFpiN3ZLNVFmTHJjb3E3dis4eVRaSHZGbGRVeTk1RFIzVTc1OFJneERsQUFDUnFTRFRadEhnOEtNQWg3bjRjRlFlVUQ5VklvQ0hSWktOWlJYOEVSOWs0N004R1NVQ2loa1NUalQ0a2RXcUhBenJzVDJlcGdqR2k1TmRCUWpqWEJ1dXlTdjg5MDhRS2s2bk9raXlCcEFKeHBtWHA5L1BwaTNKQVE2Si9ZdTg5OTBtd2JERUFxVjhGaUtDcHhjbzQrSFdMQk9TdE9TcW5QL1JKNVp0RDh6Um5PSmt6bUpRbUozUFRSUDd1UWJEV0p3SGtVL2xDWVdvYlJyRU1rT2tiSEl6ME8ybnJOME5UemRCcEMvd3VIRGVSSXhpMVo4R3NCcDhEaUllVEZldmU4eEh4LzdGUXBJZGZnWTNWNnhWSWhSU1Z4Z2JjT24rdTdMampRNmlMVlAyTTFBV1VRWGZCVkpRRE9nK2tjVE9ERWFtd3VFaE9udVhYWWFoaGhPWFZIZHQxazdPVkw3Mm91MWFVVmk2VUY5YXMxeS9iOHBrMUd6YnBsMjI1S1JzQnFiU3lRZzRkTzZwYVZMZXpSelpzM3FUN0VqSGU2aVdMVlN2aHlCakxzNjJ0VFpZdVhTbzdkdXlRNWN1WFMybHBxY2JaMU5ZcXkxYXQxRTNXR04vTXVYTTA3Wm9MdFdONW92L3E2UEZqVWxsZEpUTm16WlNTc2xMWi9NcVdNYTJJaTNNNVMzek8vQVU2MjN2R25MbTZ0SVYwNk5BaFdiMTY5Umd3RWdTUEhqMnE2Yzh0bkNmbFNQTzE3ZHNVNkpnV2ZWOU1hOU9XemZMU210VXl2MmlCekprM1Y5UHJzbmZyTXdRYVB2L2k2cGRrQWZMNjNJem5aZG1LNVhLdTl2d1lJUEdab3ZJcU9YcnFMRnU0SlBHNzlYVVFiS3JZM0RLQ0RiWXVHMm84ekJVS1ppSktOQStwbHBQZklDejhaRGJUNnNGNVIycSsyTC8vT0VyUWJiUUhMOTRsTndyaGFLaThHRWF2c1hXdmVOT01vWFlIR2pUQnFCMm1JTFV1UjU2eGVUNC9ZVjJmUFZVdWZ2SXpFdnpEYkpHRFI4QVVZY2tIanZ6SU1OVmRPZ1VoWFB5Z0laR0J5UEw2WHVuKzliTmlMOGlXcHZ3TUFHK3FoQUVrZllpL0VlQm5uWkl0enZ4Y0ZUZzJsUEZxL0NYeXlJVkhIbEdobzUrSjROdVNEdUZEdmtNNHI4dk1SVjZRcnJuTEcwMWRxRys2dnU1cVVjWVJIZkY4alVYU2MyeTNSRkp1MVh3N2tWNFR6Q0ZxaTl5Z3Z5Y3BXNkl6bnNPRFBzUnR6TE1hd0xtVjd6cmNZbnYwYitVWUJ3UUtPS0ptOE5xUU5SV2Fwa1hhTWl6U2s1NkorazVYL2h2ejhzWDJ0UWNrK093dnhMbWtXRUxiMTR1Y2VGTWlCM2RLWlAwTE12cUhaeVR3bFc5Sno2MzNTbHRtSnRKT2xtQktyb0pPWTNhS25BY0FONk91K1FGS21tM2NwWk5nT0Rya0JVZkdWTldoa1FIa2laVitmY1N5TVlHSUcvc1JpR2FYNExweWtjeXZYZ0l3TWdTYXdUUVpTS3JWWFFOeG9lcmV3NGMxSFc0QndyMkpPTEZ4L1pZdDBtNjNxNytqc0xoRWw0UXd4aTRBK2ZIVFovUWVmK05xL1A0Qmo2YTY2b1dYRkFqcW1wcWxyYXRMNDJEOHpnRm9WL2pkN25iTGZPNExWbGdvYit6Yko0ZE9uTkIwRzYxV25WQlpVbFVsSjJwcWRJTGxpK3ZYNjhSS3hrdWhibXUzNmhZa1hPTkdQczVlcUpjeWdPSGg0eWRVckxnZlVtMTlnL0pWYytHaW1tcm1HcnFEUjQvcGZaN1RCZE1FT2VZNk9hNmI2M2E2NU1TWnM3bzc1ZGJ0Ty9RWkJ0NGowSzljOWFMdU5IQzI1cnlVbEpiTGpwMnZLMDhNbk54WnZYU0Z0TUJzNWFaenIrN1lLY1VsWlFxY3BqTi9EcTRQbkRpbCtVL2lDbXRxQmR4VG1SdGt1Ym12TXI5Nm1wd2lmV25YOEVYWkJQT1FRa2xaQUpOMHFjOU1VY0R6QWp3bzhIVjMzU2JXeDc4bDBhQlB6VUN5eGt4eStRa1pVM3RyT0NUK0wzMUphdStZTG5ZTDk4OHhQaExZQkMyTC9pZ0NFN1dqUHZUQUhBWGovdFd0NmFuU2dtZjVMWG11OW1jUHpla0FmUURBenZRQ0NIQ09ORUs3b0daQS9teGNjb0pqSXdUMURNQXpCTk9TY2UzSm15SlNNVjhiTFh1S3E0SlJ3Q2R0bi9zcXpOTTBzY09zN01sTUYwZHlqazc4SXlDMVpyRU1nMk9xTW91SXBKOGcwaHNUMHpCM2xTUmcrMGZFY1dTbk5LWmtpdzNwY0hDaEUzbHJTMG1SZGtzV1RLMDg2Zi85TTNnQno3TUZVODVqZmdtdGx3UGI1TUwwMnhUSWhyT3pkTjBZVis5eldRL042Qm9BQnJWT2RoWnNEMjZVYlg4eXdSK2RRSEkreXBEYVRnRTZxeXhwdGFBK2tiY2FoQURxazUvbHZnQU5sdVhwUWJteUUrdlBTcGV6N0lCd1RyQnlReU1Hc3F2R3hmeUVBRWJ2eEF4Nlp0VUFvaXJqQXhBNE1zd3NxWkRuRnBUSy9CS0FhY3hNWWcxU2NDZXN6M0hFVGRBT256eXBzNlJacEdzM2JaTEtKVXNVUUxTWUVRMFh5VzdhK3FxbXdWWDc5TTNRSE9LcWZMb2RtSkxUNVphcXhVdmt6UGxhZlk3djl2VDNLNkEwUUNQaU5XZHpGMEliMlhQd29BSWY3ekVRcE9ZVUZjbU9OOThjdTNlaHFVbDU2K3cySE9VWDYrczBidkxEaWJuQm9WRjVZZTBHWGN2RzlIamYzQ1dBT3dTWUkxZ0VId0lMd1lqeDhoNUJoMXVWY0kwYzd6RlB2TGR3NmJLeDkzYnYzYWZ2bUxzWGNPSHVTNnZYNnVadmRPaHo3VjFqVTRzMHdGU2xDY1ozbVA2OG9tSnB0YmJwT3h3bDVKZURqcHpoeHk0NG1zWTVJV3d3VVB0NVpPRGV4ZjFvWkd5c0NTbkJQQ1MzSlVkblUxc0JTTncwalo4OHZvQkdTai9GRUFRcTlDUjY4OTUyR0VKb21xaHR0aEd1aUdMUFRoK1MrRHVrNlcrK2JFd1hRT08zVDBFRGg5RHdZNFpPeXkyNlRFUzN2NEFRZEFKRXlYODNnSlJhM2lCNmZYNFhucjA5TllpK1pKZ08wQUpvanRIM3hLK2d1cElCdkJESUhtcUdBRG11YUc5RnZJRW5mNDhDOUd1anZWckQxZnNqZm1sOStPOTEzZGRGOEVHLzJZQmxpdmp5YnBjR3hNV1BDZmlrbDkra0JRQWhneWgxbWxFY3didXFIWFFaZ1ljb0hrUmxSeThlbGhvQUhiK0J6L1RzMEl6b1MrdE16NVBtNUduaWV1NTVQSThFQ0Y2c2ZXZ0NMTUxlSU9wa0dKcklra1Z5S21VS0FDUkhKM1A2OHl5NmZvd0FSUTJtQS9sdlI1azBJMzZPWHJJRHFRZnduVU1abnNHOVdqelRsb1V5eERrQmh4MUJGOHFkUnc0Mk5PUWJJNnJVcmp0enMzVUxFWUp4SDNoMkpnR1VSNmtSb3N3VWtIVzU4M1VUMnh5RmtvQTBGejB6djdIUHZkZ1ppcXE1K0xSc3pJSE1XalRCaUdRZUp5S2FOa2RQR250ZE0zQ3JFUE1ydFdaWSsvSkdYWWx2WGxQWVp4Zk9WNjJDYVhJenREWnJod292dHgraG9DdlBBQ0tlSHpwMlhNR0NXaFhCd3R4R2hJSDdaL00raGZoQ1E2UGU0eUpjYWpZY2llcm90R2thRE50ZmYwTTFHRzZCVzdWa3VSU1dsT3NXSm55SDhYTVJMclVaOG1VQ0Q4T3hVNmMxWGZPYWVlUldKK1kxQTAwNmJxR3JBSXRyYW45MGhoTjB6S1V1WEhlMzVaVlh4L2hwYld1WGxhdlhxWWIyM0t5NUNzYlVESzBkN1dOYTZ0eWlValhUNko1SnNqLzJKVG1YazZtelpmdnlBUlJvU0J4cDZVU0Q0NmIwaWNod3NSa01YMmtlVWdkNnpUWnFJV2pJRkNMMndwM1pNTE95WU1yZ25NUG5nMC85VlB5aEpnZ3NXaW5rMVEvWm8rOW4xQmRCajRRZXd0RWk5WTgraWdaTmJZME9VZ2hBRmt3cnZNL1BDamxoWXVtV0h3UlVDK0xOVGtjdm4ycjRxQ0JNTGRCNjZOTlJIMHRjNE9laGFiSnc2Z0MzdWVXK1BMMHB0MHZQczgraHN2eTZOL1dWeUFRb0JtNmM0djNkcytBbFRiemdxK2NXYUFTTUU2QkhUU0VJbmprVGh5NTJuZGxNeHpwS1RYZXJORXowaVFrTmp3T3VISnNZYmpnbHR2eTdWZmlEeU5zRjVJSGFJc3U0QWFEdm5QTXMrQTVxYnh5T0dKcW11a1pRcHRSY293Q2t3T1oxY2pCN0dyU2ZWTzBrR21CbXFha0dMWktMV3dsU0JCcCs3NHlERGwzSVZ5Y0F1eXMxQytZMkFDWTFVMXBUMGxGZUZ1MVlQTWd6dFovbXpBTHgvZUM3NHY3eDk5RnhaQ1BmNEE5bFg0OTY1eWVnbUZZQXNOelBURE5ENk1DMEtLNlRxRUdzV3J0V3pSdHFSNldMbGtEMUx6ZkFhQ0ZNbXdyRFoyU0NrV21ta2E3RlZDTVltU1lZV3pjMUlHNERZbW9JNXA1RlhGSFAzeGtvOUJSY2dvZ3BxSzdlUGdVQ21qN2N2K2pOQXdkME1TMkYzQlJ3UjY5YkFZdnZNVjRUTUFodUJDMXpGSXlCMmhkTktZZXpSNGZzZCt5Q0NRUndvc25GcjVrMFdXMnlhczE2QlVwemp5WHVFTUIzK0M3QnlZeUw3OFNERWZOSUh4UFB5UWZmSjJDU0J3SVo3MU9ib3YvSi9LWWNIdEhkQ0JqWS92aEZJSnB3YTE3ZUxMVU56ZExuOGN1ZS9RZTBERXdBcFlPN3BIS2hIRG9PTXcwM2ttVGpjam43bnZjYmpRV0M0MEx2MkQwVkFJSWpWM2dub2tUemtMcS85bVd4Wm1SckR4eWs5Z0doWjAvTTRlWGFLZm5heTlvekliai8rbU1JdHgwUWdDcWd4c0JJS0VRNEtFVTgwdmFyZjVlVzVGdjE0NEEwdzZKbzVHZGpvRWtUc0JYQ3lWNjVHL25vNVhRQzlNaDJtQlZkeVprNlRFL1Rqcjg3OFJ3M3NhY2dFNHc0SjZZWjJvTHRBNStGWWI4ZXdvSStPeGdncEw2TjRvR0lRZkhrOEVucHZPMkRxcTBNNVdaSVBYamlWekg4QUlsQmFwY3duWXlHNVdVTklGL2NqQjV2am1WdUFrSTVVSU5RWGlKNC82ZS9sQ2Jrand0ZXZZamZDMDJtQTJCYm41NHNmYk4vaDRlZ1Y3THNxSDJnWHFpRnNlS1pGSGtOQjl3eWRIQ2JuUHJDcDZVbEowUExoMlowVHdyTXpBd0FPanNQbEtXVlpSa0RPNEswK3FrUXFHRnlIWndWcGhvL0JzQ3liNXA2bDNRODgwZWtDKzFyOCtzd1R6K2d6M1pCby9JaERnS2NGZVVSRkNkQUdMbWg2a3N6L0pvMHc0bkpFSXpUVWxwZExjL09ucTFxUHpXa1l2VEdoZVZWQUFXWTJySG5WR2owLzdXVHVkY1EzeWNBVVVqandZaENUVk1vWG5nSkd0UWFXdHFOT1QwTVhMbFBnTnIxNWg1OWp2WGhHaHhVamFyWjJxNEN6NzJNcUFFUkxQZzduMlBnN3dRcC9tNkNDQUVxM3VSNWVkTkczZS9JZktlenAxZktGeTY1N0I3NUlSaVJQek1lSGsrZXJWSFE1VFhUM2JicmRRVW5tbW5tUFc0Z3g3SXc0eUtBRVZpWU5nTkJpVUJrN25qSkJjSXpaODJSYzNXTlkza2hDSE83bEhodGp0OVZQSExpdFA0T0ZjTXU5dC84WGhwdi9TaE1wd3hvSzhtNnhTdk5LRGE4UkpSd0hsSW9LTjZmUFExTjZ6MXFhakZ1RlNRRUozcFE1eFREUWQyYmRLZjRmek1UYi9PVGpvakxiMVMybnpraDJQbkFlaVFpM29PN3hmYlZiNG9yTFY5T280RlRzOUk1TkRoWGdBSFkyWERzc0JnOU4vMUUzRFNONjdGYXAyYnFPak91eXVjUU4zMWpoM096cERudE52RTgvbStvNFRaa0FJbFJrSEgwUnlnMWwyZzhFREZRN21tcVJWQXhYYmQvQ0dBSFFPZWFMUEJFY0tySm5LYmdRMkJWbFlEelIxQTI5SjdnOWNRRUJLRzF4ZXpyS0Z6VFJUbjhqWWZrUkZhMmFvWUVDUzd6YUFEZzlqLzNERm9PQUNzRzRvTW91RUZjOEhQZWVpT21qSG5wVGJlZGs2RS9QQzNOdDl3cFZtZzFEb0FtUVljbWJUUEtrclBkR3dwd3hIa3I2b3l6dHptcm5xT0UxSEFKL2cyWmFkTC94T01pNTQ4alg0aVorVUZXbTMvOEM2bUJ1ZFlHcllqN2FiTXRkZDJhSitFb1Ixb0k5SGlPREdtWlhCK3hqWENVYTgvK2ZRcElOSDFtenkrV29xcUZNcXVvQktCUUJZRXo5SGV5cCtZQnpMTnJkV0FYemkrUzAyZHE5RjMyL212V3J0Y2VuOWRzS2dRZkNxcHBEakZRMkNuME5IY09IVDRxNTJzdjZyTnZ2TFZYelJScVIvUUwwZi9FN1VEY2ZjWW9sYTJ6VzFmamo5OEhteE1veTZIMTJSMU92YWJncTZaVlhLckQ1ZlM5N0h4OWx3SVdRYUsrdVUyLzR2TXNUQ1A2ZWFpcHNmb0pZTlNlcUMxUjI2TWpuZnhTNnlFWXFkemltczlUQ3lMLy9LUlNQTjk4bmtCTTA1V0FHOC9udXZVdlh3Wkd6QnY5VnZRYnZibnZvRzQwOS96c09mTEdtN3YxR1pyTTg2SEZybDYvVWI4eGwwVExUVHk5RXQyeFhicWYvRmRwK1BvM3BPNHJEMHZISS84Z3ZtLy9FSzhrb0FUemtQUnpPZHgyNFV5dDlNK1pKUTNmZkZUYzl6OGsvVjk4UkZvZS9vYTBQdmhWY1g3OU1SbjQ0dmVsNWJzQUJKOGZNa1BYcHJHaHZ3cDdDR0lJVkdKQnFUZ0ZYSWp2bU1qUGZ5dUJXKzhXSndTVFMwWW9TQzRJQzdVZkRuZXpoeWZ3YWMrTyt4ekdwbk9hd3RFNmRaclkvL3ZIUldZdUVuSGFFUzF5RURWY3F2WWh3OU52Skg2SjRrSElKTXFWa3hrSElNa1JtRkUvZTBwOVNOMFBmbE5OeS9hZlB5R08ySU13VEhDQ1hBREFSNUhMWUt5OEppSk9vV2YwVVpTQlA4Q0pvWGpmYlpmUXNxWFM5dGova3ZhdlBpcHRqLzY5T0wvMUF4bllzRWtDc2ZWK0JCM09RT2RubUhUUkgvSkNrNDFhbHBaakNNZ1V3bE9oZHRUOWV1bCsvRWZTOXZGUFMydkJYZEFnODFDV3VkQWFwOENVblFMQXkwZklnV21iSjIxMzNpTmRmL2N0a1JYbFFKMlRScm1GZEZlalMyMGdCQkRmdjF2NnZ2ZTQxSC85TzNMNk85K1I0TC84QklDS3ZGQXF3UWZyV05jaVhpZFIwMkZ0Y0JKaGJYMmRqa0p4eEd2RGxsZGxEUVRqNEZGai8yZ0dQa2ZUZ0hTdFlNUzloNXBiMnBSdHZuL3MrRW5adC8rZ25qTXdGZ0lBQmRZMGh3aFFPOTdZclJ1aUxWK3hTdW9ibXZSWm1rbDAvTkp2UkxOeXd5dXZTSHRINTFoY0hKWGlQa1U4YWpFaEVBQUpUaHlaNHNnY255TVlFY0Eydkx4Si9TKzh4eEdxVjdadFYyMkZFeTVmMjdWYlI5U1lWdnltYndRVSttNWVXTE5XVHA4N3IvYzQ2c2QzNDAxRGpyelJOMGJBWVJ3MHNmZzdmeU1ZY2E2U21xWnhlMzd2ZVd1ZkhEaDRXTS9KTnplQVc3THlSZlVaTFg5aHRmcW1xQWxTaXpNbmFoNDllUWJndUJueEg0Sm1oTGJLZ2ZBK0ZTdW8yWDdBQjB3aXJxUTNaaEFtb0FUemtQcVJQVjE0cVNVR1lROGJYeElkSFlWWTBPeGd1aEVPTVliUlgrTTlUbFQwZXZCR0NObzhmZ3NFVkFENWxSSisvb2piYnVpWFJ5Qlo1Smd0Mm05dEV2Zk9yV0tiL1p3NC91K1BwT09yWDVPQkJ4NlM4UDJQeU1DRFh4TDdnMStRTG1nVGc0Ly9IeEdveXJKbm53eTVuV3I2Y01TZGdrdHRqT2x4bnlJQ05ISElEN1pOaWdlaWVEQWlFM3gvSUJUUkl6VVJIZEVLY0FJWVloOXNrZWJZY3pSQjlkT1BLQ3Z1aG5rdFZncjNidUpucDdYOEVIVS9HR09ETUFDR09TRFlvQ3p0Ym4yR1N6b1VjVUpzemVRRFhJRVhBanR2cTUrRzhvaEk2TG9oZ0dqOWtNRlI5TkRCRHVsclBpeDlSM1pLZE85T0dkMTdUQWJmM0NmOUoyR3E5SGJvY3pUOXlBTS9nTWs0R0ZoZVh2MFdHaU5IZlBqVC9ERzdMQm0zUTdwd09lcUZ3T0k5K282RzN3R25FWG5STldJNFp3aHd4QTcxdzYraHNQV2FNNWdKVml4Q2FoRW1YWXNEVzR1ZE8wNHdTN2pndFhtUFI4Wk40VFFGMVRSdEdIalBmSTRqVEx4bkFoWjU0eVpxL0kxVFRzd2xKZWJYbHhuTTlKaTJHYytWZ2puYjJZelhQSEpFamVjTThUNGkvUTJ5YlY0em1IeHpYcExKSXdQZmk3K09OMDgxTGZCR0hzaHJmRjU1SkZEeEdZNm1tUi9CMURoUUIvemRlTWJNaDhqL0E4eVBJcE9TNXk0ZUFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNC0yOSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiS09OQSBGSURPMiBCSU9QQVNTIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAyMDA0MjEwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDQtMjkifSx7ImFhZ3VpZCI6ImU3N2UzYzY0LTA1ZTMtNDI4Yi04ODI0LTBjYmViMDRiODI5ZCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZTc3ZTNjNjQtMDVlMy00MjhiLTg4MjQtMGNiZWIwNGI4MjlkIiwiZGVzY3JpcHRpb24iOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzMsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMzg0cjFfZWNkc2Ffc2hhMzg0X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiJlNzdlM2M2NDA1ZTM0MjhiODgyNDBjYmViMDRiODI5ZCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDk2LCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MzI5NDczLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6MTAwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTA1LTAxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wNS0wMSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjZiOTYxNjcxNTdlZDQ4Nzc2MDcwMWJkZjAwNDkwN2QxZmU5MTdlZTEiLCI4ZTE2MTg2ZDE4NDNhOTU2NjI1ZTVkYjM3ZGM3N2RjNzRjMjE5MDRjIiwiOGJmNzExNTc2M2VhNDliNjU0OWUwODNjOWZlOGRjN2I0ZWY2MGUxOSIsIjgwMjQ1ZjhlMzE3Y2JjNzk1YzY2NGJmODQzODllODBhOTdjNWU2MjMiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNmI5NjE2NzE1N2VkNDg3NzYwNzAxYmRmMDA0OTA3ZDFmZTkxN2VlMSIsIjhlMTYxODZkMTg0M2E5NTY2MjVlNWRiMzdkYzc3ZGM3NGMyMTkwNGMiLCI4YmY3MTE1NzYzZWE0OWI2NTQ5ZTA4M2M5ZmU4ZGM3YjRlZjYwZTE5IiwiODAyNDVmOGUzMTdjYmM3OTVjNjY0YmY4NDM4OWU4MGE5N2M1ZTYyMyJdLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgTkVPIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA5LTE2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZdWJpS2V5IE5FTyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTUxMjIzMDA2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wOS0xNiJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjg1ZDI4ZDgzMjRlMjNhYjUwYjAyODU5MmJkYmJmNGU0YWM4YTEzMTciXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiODVkMjhkODMyNGUyM2FiNTBiMDI4NTkyYmRiYmY0ZTRhYzhhMTMxNyJdLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgQmlvIFNlcmllcyAoRW50ZXJwcmlzZSBQcm9maWxlKSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg5NjUsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDYiLCJ1cmwiOiJ3d3cueXViaWNvLmNvbSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSBCaW8gKEVudGVycHJpc2UgUHJvZmlsZSkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIxMDgwNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjQifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA4LTE4In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMmZlYThmMzU3YzdhNTRhNTdmNDVjZGE3MmZhZmIzNGQxZDQ0OWZkNCJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIyZmVhOGYzNTdjN2E1NGE1N2Y0NWNkYTcyZmFmYjM0ZDFkNDQ5ZmQ0Il0sImRlc2NyaXB0aW9uIjoiTkVPV0FWRSBCYWRnZW8gRklETzIiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoyfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRU9EQ0NBOTJnQXdJQkFnSURBSW5CTUFvR0NDcUdTTTQ5QkFNQ01Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd0hoY05NVGd3TWpJeU1qTXdNREF3V2hjTk1qZ3dNVEl4TWpNd01EQXdXakIwTVFzd0NRWURWUVFHRXdKR1VqRVRNQkVHQTFVRUNoTUtRMlZ5ZEVWMWNtOXdaVEVYTUJVR0ExVUVDeE1PTURBd01pQTBNelF5TURJeE9EQXhIVEFiQmdOVkJBTVRGRU5sY25SRmRYSnZjR1VnU1dSbFkzbHpJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVNMVkwrMVNUSnZhRVJPNVdDUitqR2NBeEx2bVBCRGlaWTFOZ0ZGSWhwWDZPQVpBcFFZbXQ2eFNoNzRTd00rbWpnbnNTRWNjNEEyVWYxMzlGZ1o0cnBZbzRJQ1ZUQ0NBbEV3RXdZRFZSMGpCQXd3Q29BSVRaMDF0R3VCUExvd1NnWUlLd1lCQlFVSEFRRUVQakE4TURvR0NDc0dBUVVGQnpBQ2hpNW9kSFJ3T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdmNtVm1aWEpsYm1ObEwyVmpYM0p2YjNRdVkzSjBNRk1HQTFVZElBUk1NRW93U0FZSktvRjZBV2twQVFFQU1Ec3dPUVlJS3dZQkJRVUhBZ0VXTFdoMGRIQnpPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2WTJoaGFXNWxMV1JsTFdOdmJtWnBZVzVqWlRDQ0FXQUdBMVVkSHdTQ0FWY3dnZ0ZUTUQrZ1BhQTdoamxvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMk5sY25SbGRYSnZjR1ZmWldOZmNtOXZkQzVqY213d2dZYWdnWU9nZ1lDR2ZteGtZWEE2THk5c1kzSXhMbU5sY25SbGRYSnZjR1V1Wm5JdlkyNDlRMlZ5ZEVWMWNtOXdaU1V5TUVWc2JHbHdkR2xqSlRJd1VtOXZkQ1V5TUVOQkxHOTFQVEF3TURJbE1qQTBNelF5TURJeE9EQXNiejFEWlhKMFJYVnliM0JsTEdNOVJsSS9ZMlZ5ZEdsbWFXTmhkR1ZTWlhadlkyRjBhVzl1VEdsemREQ0JocUNCZzZDQmdJWitiR1JoY0RvdkwyeGpjakl1WTJWeWRHVjFjbTl3WlM1bWNpOWpiajFEWlhKMFJYVnliM0JsSlRJd1JXeHNhWEIwYVdNbE1qQlNiMjkwSlRJd1EwRXNiM1U5TURBd01pVXlNRFF6TkRJd01qRTRNQ3h2UFVObGNuUkZkWEp2Y0dVc1l6MUdVajlqWlhKMGFXWnBZMkYwWlZKbGRtOWpZWFJwYjI1TWFYTjBNQkVHQTFVZERnUUtCQWhEYVFiaFRGdGpjakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBb0VlcEhNQzVYOWpCS2FHcGhjS2ppZGhpTitabno3djNTM2hjMzEvQXVuc0NJUURLcW9nSzJTWk9YWmN2dkhDQjZVUVNhQTBuTG40UlV3eTFndURpdmJaYndnPT0iLCJNSUlDSFRDQ0FjS2dBd0lCQWdJQ2RkVXdDZ1lJS29aSXpqMEVBd0l3ZXpFTE1Ba0dBMVVFQmhNQ1JsSXhFekFSQmdOVkJBb1RDa05sY25SRmRYSnZjR1V4RnpBVkJnTlZCQXNURGpBd01ESWdORE0wTWpBeU1UZ3dNU1F3SWdZRFZRUURFeHREWlhKMFJYVnliM0JsSUVWc2JHbHdkR2xqSUZKdmIzUWdRMEV4R0RBV0JnTlZCR0VURDA1VVVrWlNMVFF6TkRJd01qRTRNREFlRncweE9EQXhNakl5TXpBd01EQmFGdzB5T0RBeE1qSXlNekF3TURCYU1Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUejJqTmFLT0svTUtkVzJmbWUxdHE2R1JFdVB1dUtXOUhnV1lnTVJyanZaVVRPcUxBTkozTWQ1SHF2MUVOMXpNZDRsV3R5ZnpSbGE3cnY1QVJCb09vVG96WXdOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQkVHQTFVZERnUUtCQWhOblRXMGE0RTh1akFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTXJoYjhTbWZOTGVMTmdhQVZtUTZBT01pTE5MVkhYMGtGVU84MENuVDM4RUFpRUF6TkFndjRkSCtIRGhaU2daV0ppYVB1L25mWlRldUd5NE15ZFBNcTV1cnM0PSIsIk1JSUNIVENDQWNLZ0F3SUJBZ0lDZGRVd0NnWUlLb1pJemowRUF3SXdlekVMTUFrR0ExVUVCaE1DUmxJeEV6QVJCZ05WQkFvVENrTmxjblJGZFhKdmNHVXhGekFWQmdOVkJBc1REakF3TURJZ05ETTBNakF5TVRnd01TUXdJZ1lEVlFRREV4dERaWEowUlhWeWIzQmxJRVZzYkdsd2RHbGpJRkp2YjNRZ1EwRXhHREFXQmdOVkJHRVREMDVVVWtaU0xUUXpOREl3TWpFNE1EQWVGdzB4T0RBeE1qSXlNekF3TURCYUZ3MHlPREF4TWpJeU16QXdNREJhTUhzeEN6QUpCZ05WQkFZVEFrWlNNUk13RVFZRFZRUUtFd3BEWlhKMFJYVnliM0JsTVJjd0ZRWURWUVFMRXc0d01EQXlJRFF6TkRJd01qRTRNREVrTUNJR0ExVUVBeE1iUTJWeWRFVjFjbTl3WlNCRmJHeHBjSFJwWXlCU2IyOTBJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVR6MmpOYUtPSy9NS2RXMmZtZTF0cTZHUkV1UHV1S1c5SGdXWWdNUnJqdlpVVE9xTEFOSjNNZDVIcXYxRU4xek1kNGxXdHlmelJsYTdydjVBUkJvT29Ub3pZd05EQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CRUdBMVVkRGdRS0JBaE5uVFcwYTRFOHVqQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0NnWUlLb1pJemowRUF3SURTUUF3UmdJaEFNcmhiOFNtZk5MZUxOZ2FBVm1RNkFPTWlMTkxWSFgwa0ZVTzgwQ25UMzhFQWlFQXpOQWd2NGRIK0hEaFpTZ1pXSmlhUHUvbmZaVGV1R3k0TXlkUE1xNXVyczQ9IiwiTUlJRU9EQ0NBOTJnQXdJQkFnSURBSW5CTUFvR0NDcUdTTTQ5QkFNQ01Ic3hDekFKQmdOVkJBWVRBa1pTTVJNd0VRWURWUVFLRXdwRFpYSjBSWFZ5YjNCbE1SY3dGUVlEVlFRTEV3NHdNREF5SURRek5ESXdNakU0TURFa01DSUdBMVVFQXhNYlEyVnlkRVYxY205d1pTQkZiR3hwY0hScFl5QlNiMjkwSUVOQk1SZ3dGZ1lEVlFSaEV3OU9WRkpHVWkwME16UXlNREl4T0RBd0hoY05NVGd3TWpJeU1qTXdNREF3V2hjTk1qZ3dNVEl4TWpNd01EQXdXakIwTVFzd0NRWURWUVFHRXdKR1VqRVRNQkVHQTFVRUNoTUtRMlZ5ZEVWMWNtOXdaVEVYTUJVR0ExVUVDeE1PTURBd01pQTBNelF5TURJeE9EQXhIVEFiQmdOVkJBTVRGRU5sY25SRmRYSnZjR1VnU1dSbFkzbHpJRU5CTVJnd0ZnWURWUVJoRXc5T1ZGSkdVaTAwTXpReU1ESXhPREF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVNMVkwrMVNUSnZhRVJPNVdDUitqR2NBeEx2bVBCRGlaWTFOZ0ZGSWhwWDZPQVpBcFFZbXQ2eFNoNzRTd00rbWpnbnNTRWNjNEEyVWYxMzlGZ1o0cnBZbzRJQ1ZUQ0NBbEV3RXdZRFZSMGpCQXd3Q29BSVRaMDF0R3VCUExvd1NnWUlLd1lCQlFVSEFRRUVQakE4TURvR0NDc0dBUVVGQnpBQ2hpNW9kSFJ3T2k4dmQzZDNMbU5sY25SbGRYSnZjR1V1Wm5JdmNtVm1aWEpsYm1ObEwyVmpYM0p2YjNRdVkzSjBNRk1HQTFVZElBUk1NRW93U0FZSktvRjZBV2twQVFFQU1Ec3dPUVlJS3dZQkJRVUhBZ0VXTFdoMGRIQnpPaTh2ZDNkM0xtTmxjblJsZFhKdmNHVXVabkl2WTJoaGFXNWxMV1JsTFdOdmJtWnBZVzVqWlRDQ0FXQUdBMVVkSHdTQ0FWY3dnZ0ZUTUQrZ1BhQTdoamxvZEhSd09pOHZkM2QzTG1ObGNuUmxkWEp2Y0dVdVpuSXZjbVZtWlhKbGJtTmxMMk5sY25SbGRYSnZjR1ZmWldOZmNtOXZkQzVqY213d2dZYWdnWU9nZ1lDR2ZteGtZWEE2THk5c1kzSXhMbU5sY25SbGRYSnZjR1V1Wm5JdlkyNDlRMlZ5ZEVWMWNtOXdaU1V5TUVWc2JHbHdkR2xqSlRJd1VtOXZkQ1V5TUVOQkxHOTFQVEF3TURJbE1qQTBNelF5TURJeE9EQXNiejFEWlhKMFJYVnliM0JsTEdNOVJsSS9ZMlZ5ZEdsbWFXTmhkR1ZTWlhadlkyRjBhVzl1VEdsemREQ0JocUNCZzZDQmdJWitiR1JoY0RvdkwyeGpjakl1WTJWeWRHVjFjbTl3WlM1bWNpOWpiajFEWlhKMFJYVnliM0JsSlRJd1JXeHNhWEIwYVdNbE1qQlNiMjkwSlRJd1EwRXNiM1U5TURBd01pVXlNRFF6TkRJd01qRTRNQ3h2UFVObGNuUkZkWEp2Y0dVc1l6MUdVajlqWlhKMGFXWnBZMkYwWlZKbGRtOWpZWFJwYjI1TWFYTjBNQkVHQTFVZERnUUtCQWhEYVFiaFRGdGpjakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBb0VlcEhNQzVYOWpCS2FHcGhjS2ppZGhpTitabno3djNTM2hjMzEvQXVuc0NJUURLcW9nSzJTWk9YWmN2dkhDQjZVUVNhQTBuTG40UlV3eTFndURpdmJaYndnPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBSUFBQUQ4R08yakFBQUNxVWxFUVZSSXgyUDgvLzgvQXkwQkV3T053YWdGcEZsdzhjS0Zpckl5UjN0N1MxT3owS0RnQmZQbS8vejVrM2l6dm4zOWxwK1RhMnRsdFdUUklvVG9meGhZdFhLbGxwcTZzcndDQWlrb1JJVkh2SDM3OWo5eDROU3BVMEF0UUkxVzVoWndRYWdQenA4N1YxMVppWEF2SXhqOVp6aDU0a1JOWlJXUlB2ajk2eGNET00wek1US2lCOUc4dVhQLy9mc0hORlJBU0xDK3NYSG03Tmx1YnU0UW0zYnQzTGx1N1ZwaUxHQ0VtY3VJYWNHWlU2ZkI0Y1dRWDFBUUd4L243T0l5YWVvVWJWMGRpSXZhbWx1ZVBYdEdVU1QvK2czMkhTT0Rob1lHUklTRmhhV3BwWVdWbFJVbytPSGpoNmI2Qm9vc2dIdnF6NTgvY0RsOWZmM003Q3dJZTgrZTNhdFhycVFnbWVJb2tES3pzL1gxOUVHeS94azZPem9mUDNwRVdVYkRzQVlZUkMzdGJSd2NIRUQyaC9mdjYycHFDUmVPakNUbVpFMHRyWnk4WEFqNzhLRkR5NVl1SmQ1MFZBc1ljZXBLVFU4M05qV0JxT251N0h4dy93RStPLzdqc2dDMzE1bVptUnVibTluWjJZRnF2bnorMGxCZmh6T2cvcU83bFFtL0IrRUFtSHdMaW9vZ0NvNGNPcnhrMFdJaVBVRWdrcEZCVW5LeW1aazVoTjNUMVhYM3poMWlZb0tKY0RUQkE0cUZ1Ym10bFl1YkM4aisrdlZyVFZVMXFIUWh6UWVNQkh5aHJLeGNXRndNVVhuNjFLbjVjK2RTdjhKSlNFeTB0ckdHc0NmMDk5KzZkUXN1eGNMQ0NySDdQNUlyU1lnRGVLRlMzOVRFeDhzSFpILy85cjJ1R2hGUU42NWZoMlZQTm9xcVRDVWxwZUt5VW1neGZQcE1TV0VSTUFNdVg3YXN2N2NYSXFpbHJZWHdGcnhlZy9xT3VHWlNkRXpNM3QxN0RoMDZDUFQwcGswYk4yM2NDSTlGWUtaSno4aEU5OEhmZjM4aEREWTJkaUw5MGRIZHBhdXJpeGF3ckN5c3JlM3R1bnE2aUxUWDBOQUFUb0lzVHg0L3RuZHdpSXlPQXRZRXhGakF6YzN0NCtzTEpMOTkvUW9zRTBWRlJlM3M3UnRibW9HVkZVcWNqVFlkaDc4RkFJaEJMbE5kN2p1MUFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDktMjEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA5LTIxIn0seyJhYWd1aWQiOiI3ZDEzNTFhNi1lMDk3LTQ4NTItYjhiZi1jOWFjNWM5Y2U0YTMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjdkMTM1MWE2LWUwOTctNDg1Mi1iOGJmLWM5YWM1YzljZTRhMyIsImRlc2NyaXB0aW9uIjoiWXViaUtleSBCaW8gU2VyaWVzIC0gTXVsdGktcHJvdG9jb2wgRWRpdGlvbiIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjkyMjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDM4NHIxX2VjZHNhX3NoYTM4NF9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjUsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjAuMCwibWF4VGVtcGxhdGVzIjo1LCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiN2QxMzUxYTZlMDk3NDg1MmI4YmZjOWFjNWM5Y2U0YTMiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImJpb0Vucm9sbCI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjpmYWxzZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoxMDI0LCJtaW5QSU5MZW5ndGgiOjYsImZpcm13YXJlVmVyc2lvbiI6MzI5MjIyLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJwcmVmZXJyZWRQbGF0Zm9ybVV2QXR0ZW1wdHMiOjMsInV2TW9kYWxpdHkiOjIsInJlbWFpbmluZ0Rpc2NvdmVyYWJsZUNyZWRlbnRpYWxzIjoyNX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wNS0wMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDUtMDEifSx7ImFhZ3VpZCI6IjA3YTlmODljLTY0MDctNDU5NC05ZDU2LTYyMWQ1ZjFlMzU4YiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiMDdhOWY4OWMtNjQwNy00NTk0LTlkNTYtNjIxZDVmMWUzNThiIiwiZGVzY3JpcHRpb24iOiJOWFAgU2VtaWNvbmR1Y3Ryb3MgRklETzIgQ29uZm9ybWFuY2UgVGVzdGluZyBDVEFQMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSIsImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjd6Q0NBWldnQXdJQkFnSVViK1Z1LzMzY3YyWHV2dWNacUFtek9VdXRnZ2t3Q2dZSUtvWkl6ajBFQXdJd1RURUxNQWtHQTFVRUJoTUNWVk14R3pBWkJnTlZCQW9NRWs1WVVDQlRaVzFwWTI5dVpIVmpkRzl5Y3pFT01Bd0dBMVVFQ3d3RlEwRWdRVUV4RVRBUEJnTlZCQU1NQ0VOQklFWkpSRTh5TUI0WERURTVNRFl5TnpBNE16TXlObG9YRFRNNU1EWXlNakE0TXpNeU5sb3dUVEVMTUFrR0ExVUVCaE1DVlZNeEd6QVpCZ05WQkFvTUVrNVlVQ0JUWlcxcFkyOXVaSFZqZEc5eWN6RU9NQXdHQTFVRUN3d0ZRMEVnUVVFeEVUQVBCZ05WQkFNTUNFTkJJRVpKUkU4eU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUhBWE1aTGIzQ2VNd094Zy9WY1V6d0h4MXdrdVRBNEVLb3RvaWhzNk9RZVRTY2xLWG9YY1lyajZYOFBCVDhWVnFIdWwzK25CS2pEaUJJK1l4citxZitxTlRNRkV3SFFZRFZSME9CQllFRkVNdUxxZUJjeGlHTmdMelNteE5EQmdCVWZuSk1COEdBMVVkSXdRWU1CYUFGRU11THFlQmN4aUdOZ0x6U214TkRCZ0JVZm5KTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUpubHdZSnBpWFhaSVlsbXZlL25qcXhFV2grS2RVc1k5YjlYSWZLc2x3eUlBaUFIVGRoc1VWRjRPcGlweDgwSWorVXhEUlN0bG1lZ1VBRW5Mcm1rYTNWOHhRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTWNBQUFCSkNBWUFBQUNKdnpKdUFBQUFCbUpMUjBRQS93RC9BUCtndmFlVEFBQU5CMGxFUVZSNDJ1M2RlVkNVNXgwSDhHY1JpV2ZVNEZGTjFZZzFYa1ZCZzg0a2syUTYwOGtrMCtuWVp1bzArYWUxam0zTnRKblVCbzNBMm01SHZEVTZSbERBQXk5STEraGVIQ3JxY3U5eXM0dWc3THVJOTMxVVFFUTUzdjZlWlRHb0NQdnV2cyt6ejd2N012TWRHSlI5MzRkNVArejcvcDRMOFpub0xUNE56UlU5NmVnbmlMR1BBNXRtRFk1ZkZ4RWlkcjdidEdUU3lqUmJTRmRVdXZQanZORytxR1BuZ3J1ZlIrU0IxWk9XeFVlRWlKMGsvWmhKSlZZVTRvMFVXZENrUENzYTBSV0xCUTBtOWd1RmkzZ3ZoQ2VRNi93Sk5KNGxISS8wL1JZYzJqVDdTbHpzZkY3TWJOL3djVW1NanVPN3BYV1ZvWFkyemJaOW82NGJGcU96WCs5K0hzdVRseHEvM2pXWEZ6UExFK2EwRkZZcWJFVld4RE9VK3hCTFVSWFN3K2N0NWlxMEdMNStoK1BRYTZ6aTRPRWQ1Q3lmaFlheGdnUE81OU1HVFpDWkFnNklMUTkrQXdwYWJZTmpibjN4SEVqZ1NEMDE4alJqTUhwTEUwUmJiRVYvcnFoQXc5bkMwWmtNM29nQ1djR0J6K25NenBBaThqZzRQbHJMTGFIUnJsVWErMXc0WGh0cEhQOU8vdmtsdU5nYUpZVGplU2hWS01sY2pXYXdoQU8vZ3lTeWhLTTlUWEV0YVYxRUUya2NNWHJ1bnVxWWZUVEpOaTFVOC8zZ09LVTlIVjlzSEdkSytoZElGRWIzdEFLUytQSnlOSW9OSEozNWloVWNPUFVwdzQzRWNlQm91UU1rMjZUVTI3OTgxYkhGeEJHbm1XajJBUmcvcGdyZGdRZjhUMWpCMGM1bm9OK3dnZ1B5NVBzdG9YWEVjVUNVV3RzdlNiUkhkWlQ3S2J4K0Eya2MzeVNHTjVvdGlzcytoYU16YllCa0tRczRjSnA1QTVySENBNitSUjlZQ1JkM0Iya2NFSnZLV0Q5QTlJZHdMZmREYjhjVkM0Y21aL2hwSDRUUmxRN0lYMW5BMFZuaU5hQUpMT0RBTVNXTno2ZUFnMWZxT0pYSU1IN2QxekhGd0xIMjhMUmF4MzI2NytKd0FERmIwTzlZd09HMUVtOVBPRHJTMGUwOTYrYytJSTBEOGtSNXpEWmRsTnNwZGZVUXdIYUpBbzZPM0xMQU1oK0gwWlVIcGdyMGx2ZHhkQ2FUZG9tM0p4dzROOVJEY3lqZ3dPOGUyV0wwZlVCbjN3WlhqdWNwanIxcDQvTDhCRVpYdEt6Z29GN2lmUlVPWEN6UWJaOStsalNPenI0UCt4ODhhVU8weGhhR2UrQko0NGphSFhZWGJqVnUrUmtPdnVRc2VvOE5ISjFBL3NFQUR2NnBJYUFtUG5aZUcya2NrTHNxUSsxSXQyNm5WSHdBOUdrVXVYb3NUM0JrRmd6TzlUY1lqbGlRZ1IwY0ZFdTh2ZUhBcVVnZW0wTUJCODV1OTI2bmJFdUZITWRkSE90VHBsb2RaVTUveEdGRjdYaHdJeXM0cUpWNCs4TFJrWVlha2plRTNhU0FveU5hWi8rRm9IY05HT2tMUC9lUU5JN0loRG10cHNvQW01L0NjQVFHTGtheGhJTktpYmN2SERqM2p3N01wNEFEWWovL1pRYjNtb0NIOEJTaHgzQUh4NkhqWTg3NE13eG56S3poSUY3aWRRVUhUbWJjbEhMeU9Cd1A1ekV1UFlUcmJMOXk1L1dGNGxpMUwvUUdQSVEzeWpoUW03RWFEV0VMQitFU3I2czQydE1WOWJ2V1JMU1F4Z0ZwVm1xNHliMmQ4ekwxbFlIdy8rdzBjR1FWRGNpVllYUUdocmwvd0NJT1lpVmVWM0hnMkE0R0d5bmd3QU1UVC9RK3NOQVc2KzVyQzhHeDlVaUkyVG1Vd3BXTEIvZWFxeWttSGNaQTVjRUZpd3NGVHlrQitUdWJPQWlWZUlYZ3dFV0N3NXRtWHlhT0E5OWU2ZXlmOVRqdFZjdk53RDNycEhFc1Q1enoyRlNoc0x2OHdHcEJtNzAxUGc3UDdpdXVRdThDbEIxd0xnMEVjV3huRndlQkVxOUFIUHdqYlZBSkRSeVFteXZUTG8xNC9tUjVoVkpuei9Ya2RWM0ZvVDRkTEdoZ29UZHhkUC9BSlZjNG4ySkNROXIxTE9NUXZjUXJGQWRPVHZ3a013VWN1SHExOC9tSGNHNnhwNi9wQ2c2WTNWY0hGOE1qS2VKd0FEbUhndUdjN0FTQTVMQ09ROVFTcnpzNE9tRFdZT0s2ZDVySTQrRGFZN1QyZHgxOUdqQjdFTThpcElFanQ2eC9xZUIrQUlad09JQlkwVUlDUGVVVlVzQWhXb25YSFJ3NEYxT0haVlBBZ1dQOVMwSnBmK2dKVHhiajlmckNFYStaNE5hMFY5WndHS0c2U1dCdU95Y05IQ0tWZU4zRkFXazkrdTNNV2dvNDhNamRnN2dIblRRT21OMzMwR1JSWFBVRkhNN25EN0U3TDI5S0NRZE9rcGR3OEMyNlFNdXJaZzJLaVVQTTlJWkRuenZNN2RsOVRPS3dva05pcjFZaU5SdzR5N3lCQTZkb3o1dDV2b0FqOXVEMEdrLzZDMWpFQWVPaDRrVEc4VWlLT05yaEFmMjMzc0FCcGVWN01HdnducFJ4UkNiTWJjK3ZDS2oyYUdBZWd6aWMvUjUrajZPenhKdU81bFBIQWJsMVpFaXVsSEVrcDQvMWVJaUlqTVB6RkJNR2NwblhvWEcwY1VEYXROdW1XYVNJSTJaMzJCMjhYcE12NHBEYWJkWGZJR3NKQTZrV1V1SVZDUWZmYWdpdzdWd3o3Nm5VY0p3MERSUmxUamlUT0t4b243Unc4RWdCbnc4VEJaS0JqcnRhNGhVTEIwN1Z2akhaVXNLeElYVkttV09XbTQvaWNLNndMaDBjamd2U2lBYkExd1VzbEhqRnhBR3pCaHYzYnd5L0lRVWNzRzNBMDhMS0FFNjBtWEpzbG5MckpZZkRjVkVhMEVpNE1EbkNRUDVKRXdmT1E4MkFRaW5nU0RrNVd0UVZDMW5EVVZxTkpnZ1liczhXRGllUWFmQzkrOTRzOFlxTkErZlV6c25GTE9OWXRUZjBNbHpNRGI2TUE4NXBCWUdCaDNlcDRYQk95ZjBBTCtEc3JSSXZDUnl3bmNIRitNMGZtMWpGY2FZNHlDVDZBZ1FNNGNnL2o0YUtVWUhySVhWVWNUZ3UwQXowaGJkS3ZDUnc0TlFjbVpYQklvNGRtWXN5aWF6T3dkS1FkZGlRaHRCa3AzTHFPSnp2SU9STHZKcVh0N2tpaEtNamZmZUhUT0tJVlM4NUJRUHltbndSaDFxTitnR01qUVRua0J1OWd3T1hlTlBRSWRvbFhoSTQ4RkkrTEQ5enBKd2FsZXNyT09DNkNjZ3ZSK01BL09kd0hvV0U1NUFuZXdXSHQwcThCSEQ4TDNsOStHMldjVVR1bXROV1lBazRKNjhvSXZnUHdGZGV3K0dORXEvWU9McVdEMlc5bExzKzVlMXFzVG9BL1docG5nKzlpb04yaVZkTUhFLzBnV2ZqWStlM1M2V0gvSGpob0FMNW9uYzloZFhvRGEvajZGYmliU0ZkNGhVUlI5dXhiVE5xcERSOEpHcFAyQU80Vjc4algvZ3VwYkxyd3ZRNkR1ZDVMQ0o4ZTNVRHI0VWx4bXU5dU5tTlZBWWU3a3NmSzc5N3VQSzhZVVhybU1MaFBKY3RoSUU4RW1GTTFWMlk4TlFnUlJ5UnNJMVpUbWxnaFF5ZzkvMEJUVlZvT25zNGFKUjRQVXhQRzJ4S2FiTFRtc05UN1g2d0FhWW5NWFgvYTgwTURvb2xYcmZTck90ZjdndHp5SFU1dzdKbEJLKzhwVnJBTEE3SE9SMUR3UlJLdkVMVGtycDVWcjB2NEZpUkZOWmNaRlhja0RHOGxDcmMwY2cwRGtvbFhrR3BUeGx1cExGdWxhdWJZWHE2TkUrY1pxSlp4dkQ4bmh3bGxTOHNQY3NxRGtvbFh0ZEczaG9VbHhQV1JqUlR3UEUwU21kL0R6NWZwYkhpWVU1Wi96SVp4Yk44MjlNRnlDd09TaVhlUHBNVk43bUV4bktnc05xaFk4d1NySm43ZXhvNFZQdG5Yb09MNHJFTUErV1VscUwrOUhCa3dPWWZZZzA0eTBDeDNvTFJvQW1pdE1vNmQwRmx1RDZvcTgydzZub2FqWVdrMWFlQ2pmNisvNStaUTYrLzZpOHoremk4Vk9LRlBvMm1nNXZDcnRIQUVhMjNmOUs5elRIcEZ5YkM5NXRJNDFpZUdQN0VWS200Nktjd2N2RVdCcjNkdGpDUHcxc2wzcG9EbzdLcDdPeWs1VFE5dFJtMklZaW1zWGtOYkhsbTlUTVV1SjluZzdHdlZXdWtndU5aaVRjZDJXakFlR29JcUlXMXFWb3A0R2lFWjR6eFBiVlhwYTRPZ24rdnByRW5JR3lXYWZLSDNtL294OGdvcmtRelhYM2dsUXdPaWlYZURzUDJxUllxRzJicXVGNVhUWW5TMXI3djdwWUVRbkFvOTRiZU5wUGRZOCticVljaDZGdExyV2lhMEdxUXBIRFFLUEhlT1Rvb2o4WSs1SkR5aFdxK1gxL3RoZHVydlRTMldqNTRmTFNyS3lJK3dBc1FNSmdhbUtTVUR4QjArTFlKbGdoZGJLNUdNenk1MENTSGcyU0p0eU1kM2R2YncwcnFCSEMwcmRMWFJialNWcmk5ZWdQKy8yM1NPSndyc0ZlNXNKbmtHdVFQSDFMRlFhckVXN3A3WEs0UUdHN2owSEp4UXRvYXJiY3RJbzNETVdzd2RTcmV1Nk5OeGlGMUhKMXI4UjRVNjV4YkRJRlZYYlA3Q09PNHFzcmdYaGZZV0FYODNHblNPSERTQzRia3lEZ2tqa1BrRW0vcmthMHpiVUpodUlVRGVzRGRhV3ZVc2JxMzRlZGJTT05ZdVh0Mmc5bXF1Q25qa0RnT3NVcThWLzg3Tk5zZEdNSngyTk04YVN2OC9HclNPSEFTZFc4V3lEaDhBSWVqSFpsb3Fyc2xYdGhyL0ViaTJybU5GSEEwS3pYY1pFL2F1VXg5WlNDOGpwMDBqczZCaVlIbE1nNGZ3T0ZKaVRjL1lXS2h1ekNFNElqVzJtUEVhS2ZTd0gxRUE4ZC85cy9FeS9xM3lEaDhBSWR6K1owL0NqblBKazFRc1Njd0JPQ294ajNlWXJWVHFiT2xrc2FCbzhrZS90TEF4R0lMV2l2amtDQU9aNXRXdTNpZWoxTTJ6N3BJQVVjSDd1a1dzNDNSdWd0ajRIWHZrOGF4SWpHODJXUlJYSlp4K0FvT0YwdTg5cFFSUms5aHVJUURlcmhKdEJQbWYzeEJHZ2ZPZHorRWxNZzRmQVJIdHhKdmZpK3oreTdzV2hQUlFnSEhiZHpEVGFLTktoVWZvTlJ5aGFSeDRKd3BDakxMT0h3RVIxOGwzaE03ZmxZbUJveStjQ2kxdGorUmJPTXFiVjBvbmw1TEdzZS9ra092ZFcxbklPUHdBUnpkU3J6M2V0ckxqd0tPMDdobm0zUWI0VGhiU09QQVNUMDVNbHZHNFVNNG5CV3M5NStWZU5QUXcrU040YmNvNEdqQlBkbzAyb2VuMTBMbllEMXBISkVKYzFvTEtnSnFaUncraE1NSjVETThUNlA3L3VFa2NTajF0bGlhN1lPSC9nV2tjZUJzK242S3hYLzZPZEpRSkZ3MFdRU3lnTFcyTm1rREkzZXRqY2lFQ3pwTHpHemIvT2srK011ZDlXTTRiZVFKeTJEYTdZdldjVHU2bjhmeTVHVUpYKytja3lWMmtqUEhmTzRQTnY0UFdoUUVtaGY5a21jQUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCIsIlUyRl9WMiJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjA3YTlmODljNjQwNzQ1OTQ5ZDU2NjIxZDVmMWUzNThiIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxNDcyLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA3LTExIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJOWFAgU2VtaWNvbmR1Y3RvcnMgRklETzIgVGVzdGluZyBBdXRoZW50aWNhb3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDIwNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjYiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTA3LTExIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wNy0xMSJ9LHsiYWFndWlkIjoiZDYxZDNiODctM2U3Yy00YWVhLTljNTAtNDQxYzM3MTkwM2FkIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJkNjFkM2I4Ny0zZTdjLTRhZWEtOWM1MC00NDFjMzcxOTAzYWQiLCJkZXNjcmlwdGlvbiI6IktleVZhdWx0IFNlY3AyNTZSMSBGSURPMiBDVEFQMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoidm9pY2VwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55IiwiaGFyZHdhcmUiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUI2akNDQVpBQ0NRRElSUE8zUjdWdExEQUtCZ2dxaGtqT1BRUURBakI4TVFzd0NRWURWUVFHRXdKVFN6RVJNQThHQTFVRUNnd0lRM0poZVc5dWFXTXhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhGVEFUQmdOVkJBTU1ER055WVhsdmJtbGpMbU52YlRFZk1CMEdDU3FHU0liM0RRRUpBUllRYVc1bWIwQmpjbUY1YjI1cFl5NXBiekFnRncweU1EQTJNVEF4TVRReU1qaGFHQTh5TURjd01EVXlPVEV4TkRJeU9Gb3dmREVMTUFrR0ExVUVCaE1DVTBzeEVUQVBCZ05WQkFvTUNFTnlZWGx2Ym1sak1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SVXdFd1lEVlFRRERBeGpjbUY1YjI1cFl5NWpiMjB4SHpBZEJna3Foa2lHOXcwQkNRRVdFR2x1Wm05QVkzSmhlVzl1YVdNdWFXOHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU1V3NFJ0NjE2M0hSdVhlQnF4ZDdQSGNmNWc5Q21TMGhjamszakdQa3JBNlV6TFNLeWE2bjZ5TzJaMUVic1RYdFUxUmdBY1E4VTYzNW5QcjR5L2ZMR3dNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUNxYUlPLzFjZEtxZWczQi9xd0FQR29nQ1hVaW9mczQ2TzQ0dlNGblBXRm1nSWdEMkVuK3FJTHowNlR6UE5uMDBKT2dtZ0lqTGNWQnk1R1NvMnMzdFlteUpBPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFMY0FBQUE2Q0FZQUFBRHlRTWlaQUFBQUJHZEJUVUVBQUxHT2ZQdFJrd0FBQUNCalNGSk5BQUNIRGdBQWpCSUFBUUZVQUFDQ0t3QUFmVDRBQU8rdkFBQTY2d0FBRkpjSUhOUEhBQUFNRm1sRFExQkpRME1nVUhKdlptbHNaUUFBV01PdGwzZFVVOGtleCtlV0ZFSkNDMFJBU3VnZEtkS2w5eUlnSFd5RUpFQW9FUktDaWgxWlZIQXRxSWlBRFYwQnNhMEZrRVZGUkxHd0NQYitzS0NpcklzRkd5cHZVa0RYODk0Zjc1dzM1OHk5bi96dWIzN3ovYzJkTzVrQlFOR0dsWk9UaFNvQmtNM1BFMFFGK2pBVEVwT1lwQ2NBQVFRQWdEd3dZckdGT2Q2UmtXSHdGeGk3LzdPOHZ3RzlZYmxxSlk0Ri9yZWl6T0VLMlFBZ2taQlRPRUoyTnVTakFPRHE3QnhCSGdDRUxtZzNtSnVYSStZaHlLb0NLQkFBSWk3bU5DbXJpemxGeXBZU241Z29YOGhlQUpDcExKWWdEUUFGc1c1bVBqc054bEVRYTdUaGMzaDh5TldRUGRqcExBN2tlNUF0czdQblFGWWtRelpOK1NGTzJqOWlwb3pIWkxIU3hsbWFpNlNRL1hqQ25DeldmUEQvTHRsWm9yRSs5R0dscGd1Q29zUTV3M0dyeTV3VEttWXE1RlorU25nRVpCWEk1M2tjaWIrWTc2U0xnbUpsL29Oc29TOGNNOEFBQUFVY2xsOG9aQzNJREZGbXJMZU03VmdDU1Z2b2o0Yno4b0pqWkp3aW1CTWxpNC9tODdQQ3cyUnhWcVp6ZzhkNEcxZm9IejNtazhvTENJWU1aeHA2dENBOUpsNnFFKzNJNThXRlExYUEzQ1BNakE2VnRYMVFrTzRiUHVZakVFV0pOUnRDZnBjcUNJaVMrbURxMmNLeHZEQnJOa3ZTRjV3TG1GZGVla3lRdEMyV3dCVW1oSTFwNEhEOS9LVWFNQTZYSHl2VGhzSFo1Uk1sYTF1Y2t4VXA4OGUyY2JNQ282VGpqQjBTNWtlUHRiMlNCeWVZZEJ5d1J4bXNrRWhaWCs5ejhpSmpwTnB3RklRQlgrQUhtRUFFYXdxWUF6SUFyM3V3YVJEK2tqNEpBQ3dnQUdtQUM2eGtsckVXOFpJbmZIaU5CZ1hnTDBoY0lCeHY1eU41eWdYNTBQNTEzQ3E5V29GVXlkTjhTWXRNOEJSeU5xNkplK0J1ZUJpOGVzRnFoenZqTG1QdG1JcGp2Ukw5aVg3RUlHSUEwV3hjQnh1cXpvSlZBSGovd1JZSzcxeVluVmdMZnl5SDcvRUlUd205aEVlRTY0USt3bTBRQjU1SW9zaThadk1LQlQ4cFo0S3BvQTlHQzVCbGwvSmpkcmd4Vk8yQSsrRHVVRC9VampOd1RXQ0ZUNGFaZU9PZU1EY0hhUDFSb1doYzIvZXgvTGsvc2VvZjg1SFpGY3dWSEdRcVVzYmZqTys0MTg5UmZIOFlJdzY4aC83c2lhM0VqbUNkMkduc0F0YUtOUUVtZGdwcnhycXdFMkllbndsUEpETmhyTGNvaWJaTUdJYzM1bVBUWUROZzgrV252bG15L3NYakpjemp6c3NUZnd5K2MzTG1DM2hwNlhsTWI3Z2FjNW5CZkxhMUpkUE94czRHQVBIYUxsMDYzaklrYXpiQ3VQamRsdHNHZ0VzSk5LWjl0N0VNQURqK0ZBRDYrKzgyZ3pkd3VxOEQ0RVFQV3lUSWw5ckV5ekg4eDZBQVJmaFZhQUFkWUFCTVlUNTJ3Qkc0QVMvZ0QwSkFCSWdCaVdBV0hQRjBrQTAxendVTHdUSlFERXJCT3JBSlZJTHRZQmVvQS92QllkQUVXc0ZwY0E1Y0FqM2dPcmdMNTBVL2VBbUd3SHN3Z2lBSUNhRWhkRVFEMFVXTUVBdkVEbkZHUEJCL0pBeUpRaEtSWkNRTjRTTWlaQ0d5SENsRnlwQktaQ2RTai95T0hFZE9JeGVRWHVRMjhoQVpRTjRnbjFFTXBhS3FxRFpxakU1Q25WRnZOQlNOUVdlaWFXZ3VXb0FXb1d2UUNyUUczWWMyb3FmUlMraDF0QTk5aVE1akFKUEhHSmdlWm9VNVk3NVlCSmFFcFdJQ2JERldncFZqTmRnQnJBVys1NnRZSHphSWZjS0pPQjFuNGxad2JnYmhzVGdiejhVWDQ2dnhTcndPYjhRNzhLdjRRM3dJLzBhZ0ViUUlGZ1JYUWpBaGdaQkdtRXNvSnBRVDloQ09FYzdDNzZhZjhKNUlKREtJSmtRbitGMG1Fak9JQzRpcmlWdUpCNGx0eEY3aVkrSXdpVVRTSUZtUTNFa1JKQllwajFSTTJrTGFSenBGdWtMcUozMGt5NU4xeVhia0FISVNtVTh1SkplVDk1SlBrcStRbjVGSDVKVGtqT1JjNVNMa09ITHo1ZGJLN1pacmtic3MxeTgzUWxHbW1GRGNLVEdVRE1veVNnWGxBT1VzNVI3bHJieTh2TDY4aS93MGVaNzhVdmtLK1VQeTUrVWZ5bitpcWxETnFiN1VHVlFSZFEyMWx0cEd2VTE5UzZQUmpHbGV0Q1JhSG0wTnJaNTJodmFBOWxHQnJtQ3RFS3pBVVZpaVVLWFFxSEJGNFpXaW5LS1JvcmZpTE1VQ3hYTEZJNHFYRlFlVjVKU01sWHlWV0VxTGxhcVVqaXZkVkJwV3BpdmJLa2NvWnl1dlZ0NnJmRUg1dVFwSnhWakZYNFdqVXFTeVMrV015bU02UmplZys5TFo5T1gwM2ZTejlINVZvcXFKYXJCcWhtcXA2bjdWYnRVaE5SVzF5V3B4YXZQVXF0Uk9xUFV4TUlZeEk1aVJ4VmpMT015NHdmZzhRWHVDOXdUdWhGVVREa3k0TXVHRCtrUjFMM1d1ZW9uNlFmWHI2cDgxbUJyK0dwa2E2eldhTk81cjRwcm1tdE0wNTJwdTB6eXJPVGhSZGFMYlJQYkVrb21ISjk3UlFyWE10YUswRm1qdDB1clNHdGJXMFE3VXp0SGVvbjFHZTFDSG9lT2xrNkd6VWVla3pvQXVYZGREbDZlN1VmZVU3Z3VtR3RPYm1jV3NZSFl3aC9TMDlJTDBSSG83OWJyMVJ2Uk45R1AxQy9VUDZ0ODNvQmc0RzZRYWJEUm9OeGd5MURXY2FyalFzTUh3anBHY2tiTlJ1dEZtbzA2akQ4WW14dkhHSzR5YmpKK2JxSnNFbXhTWU5KamNNNldaZXBybW10YVlYak1qbWptYlpacHROZXN4UjgwZHpOUE5xOHd2VzZBV2poWThpNjBXdlpZRVN4ZEx2bVdONVUwcnFwVzNWYjVWZzlWRGE0WjFtSFdoZFpQMXEwbUdrNUltclovVU9lbWJqWU5ObHMxdW03dTJLcllodG9XMkxiWnY3TXp0MkhaVmR0ZnNhZllCOWt2c20rMWZUN2FZekoyOGJmSXRCN3JEVkljVkR1ME9YeDJkSEFXT0J4d0huQXlka3AycW5XNDZxenBIT3E5MlB1OUNjUEZ4V2VMUzZ2TEoxZEUxei9XdzY5OXVWbTZaYm52ZG5rOHhtY0tkc252S1kzZDlkNWI3VHZjK0Q2Wkhzc2NPano1UFBVK1daNDNuSXk4REw0N1hIcTluM21iZUdkNzd2Ri81MlBnSWZJNzVmUEIxOVYzazIrYUgrUVg2bGZoMSs2djR4L3BYK2o4STBBOUlDMmdJR0FwMENGd1EyQlpFQ0FvTldoOTBNMWc3bUIxY0h6d1U0aFN5S0tRamxCb2FIVm9aK2lqTVBFd1ExaklWblJveWRjUFVlK0ZHNGZ6d3BnZ1FFUnl4SWVKK3BFbGtidVFmMDRqVElxZFZUWHNhWlJ1MU1Lb3ptaDQ5TzNwdjlQc1luNWkxTVhkalRXTkZzZTF4aW5FejR1cmpQc1Q3eFpmRjl5Vk1TbGlVY0NsUk01R1gySnhFU29wTDJwTTBQTjEvK3FicC9UTWNaaFRQdURIVFpPYThtUmRtYWM3S21uVml0dUpzMXV3anlZVGsrT1M5eVY5WUVhd2ExbkJLY0VwMXloRGJsNzJaL1pManhkbklHZUM2Yzh1NHoxTGRVOHRTbjZlNXAyMUlHMGozVEM5UEgrVDU4aXA1cnpPQ01yWm5mTWlNeUt6TkhNMkt6enFZVGM1T3pqN09WK0ZuOGp2bTZNeVpONmMzeHlLbk9LY3YxelYzVSs2UUlGU3dSNGdJWndxYjgxVGhOcWRMWkNyNlJmUXczeU8vS3YvajNMaTVSK1lweitQUDY1cHZQbi9WL0djRkFRVy9MY0FYc0JlMEw5UmJ1R3podzBYZWkzWXVSaGFuTEc1ZllyQ2thRW4vMHNDbGRjc295ektYL1Zsb1UxaFcrRzU1L1BLV0l1MmlwVVdQZnduOHBhRllvVmhRZkhPRjI0cnRLL0dWdkpYZHEreFhiVm4xcllSVGNySFVwclM4OU10cTl1cUx2OXIrV3ZIcjZKclVOZDFySGRkdVcwZGN4MTkzWTczbityb3k1YktDc3NjYnBtNW8zTWpjV0xMeDNhYlpteTZVVHk3ZnZwbXlXYlM1cnlLc29ubUw0WloxVzc1VXBsZGVyL0twT2xpdFZiMnErc05XenRZcjI3eTJIZGl1dmIxMCsrY2R2QjIzZGdidWJLd3hyaW5mUmR5VnYrdnA3cmpkbmI4NS8xYS9SM05QNlo2dnRmemF2cnFvdW81NnAvcjZ2VnA3MXphZ0RhS0dnWDB6OXZYczk5dmZmTURxd002RGpJT2xoOEFoMGFFWHZ5Zi9mdU53Nk9IMkk4NUhEaHcxT2xwOWpINnNwQkZwbk44NDFKVGUxTmVjMk54N1BPUjRlNHRieTdFL3JQK29iZFZyclRxaGRtTHRTY3JKb3BPanB3cE9EYmZsdEEyZVRqdjl1SDEyKzkwekNXZXVkVXpyNkQ0YmV2Yjh1WUJ6WnpxOU8wK2Rkei9mZXNIMXd2R0x6aGViTGpsZWF1eHk2RHIycDhPZng3b2R1eHN2TzExdTduSHBhZW1kMG52eWl1ZVYwMWY5cnA2N0ZuenQwdlh3NjcwM1ltL2N1am5qWnQ4dHpxM250N051djc2VGYyZms3dEo3aEhzbDk1WHVsei9RZWxEekw3Ti9IZXh6N0R2eDBPOWgxNlBvUjNjZnN4Ky9mQ0o4OHFXLzZDbnRhZmt6M1dmMXorMmV0dzRFRFBTOG1QNmkvMlhPeTVIQjRyK1UvNnArWmZycTZOOWVmM2NOSlF6MXZ4YThIbjJ6K3EzRzI5cDNrOSsxRDBjT1AzaWYvWDdrUThsSGpZOTFuNXcvZFg2Ty8veHNaTzRYMHBlS3IyWmZXNzZGZnJzM21qMDZtc01Tc0NSYkFReFdORFVWZ0RlMUFOQVM0ZDZoQndDS2d2VHNKU21JOUx3b0lmRGZXSG8ra3hSSEFHcmh1U3QyS1FCaGNJK3lEVllqeUZSNEYyKzlZN3dBYW04L1htVkZtR3B2SjQxRmhTY1l3c2ZSMGJmYUFKQmFBUGdxR0IwZDJUbzYrblUzRkhzYmdMWmM2WmxQWElod2Y3L0RXa3c5L2E5K09ua0I4Rzh6SW16MWhUS2RQUUFBQUFsd1NGbHpBQUFXSkFBQUZpUUJteFhHRkFBQUc4NUpSRUZVZUY3dFhRZDBWVlhXUG5sNTZZVTBlYVFRa3BDRUdub1ZFQUdWSWlSVWFZNkFqSXJvcUFnNk9vNkt1c0NGTXpoaUhVQlVtaUxEL01ySWlJQ0E0Q0M5UTVDYVVOSW9VVWdsN2Y3ZnQvUGVNK1RkUURvRTMxNXJyM1BMdWZmZGU4OTM5dG43N0gzMlUzYXkwKzFLRHVieWQwV2JOdjNvc0cvZlBxZU5HOWM3dXJpNCtqWm9FR2hLU0RqcHRHWExGdGZ3OFBCZ2ZCYlByS3dzNDRVTDU1MVJ1amRxMUNnNEx5L2ZXRmhZWUxoNjlhcGpkbmEyOGNxVks4NmVucDd1Zm41K2QvQ2VCUVZGeHFLaUl1djMxTFFpUTM1K25xTjUxNFlNQm9ObU5Eb1hjTnNCVnhtTnhnS1VXa3BLU3BLbWFYa0JBUUc1enM0dWhVNU9Ub1dPam9hOGhJU0VNMkZoWVRuZTN2WHljZmZNYytmT0pmWG8wVE1uSWlJaWQrblN4WWtQUHZpSHZGNjllaGYwNjNkZm9meUFuVzRmY0s5ZXZWcnQzcjNiSlRFeDBUOHpNek1ZMjRHdXJxNUJTVWxKZnZYcStUUUNVRDE4Zkh3aWMzSnkzUURPQURjM1YzOENsU0F1L2d4YThZMUtFY0NsSEIwZENVWXBBVUxsNitzcng0MUdKK1hxNmlMbjNOM2Q1UnlKNXgySTJCdFFRVUdCUWllUmJUeVQ3R2RuNTZETVY3bTV1ZXJ5NWN0eXJMQ3dDRnlnOHZMeXBHNXB3dTlxSGg0ZUJYaU9iTlE5NitYbGxaT1JjU1hCMzkvL011NXpybjc5K3VmUjhjNjJiZHMyTFNNakk2RlBuejVYUm93WWtXOHltY3gzdUQycFRvSDdQLzlaWlhqMzNYY0JVdS9taHc0ZGlrRGpoenM0R0NMUjhORm9OSDhYRjVjSWdNV3BzTER3bXZjaStIQU83S3BNcHZyS3g4ZFhOV2hnQWdqOXdEN3FqanZ1VVBYcTFWTmVYdDdLMzk4UHBaY0NXS1NFZEpackNXYVd6czdPNXJ2V0R1WGs1Q2gwUWdFMk93SUJqODZyZnZubEYzWGh3a1U1bHBxYW9pNWRTc2YrQlpXU2tpeGxldm92NkNEc0tESTRXQW52VVlUM3lzZnhFeGdaVXZDZXAvSDlqcUhqSndMOHAxSlR6Lzg4YmRxMDdMNTk3eTB5WDFKbjZaWUU5NUVqUjlYTW1UTTgwdE12eFJ3L2Zqd0dEZHdHM0R3L1A3OEpHdGtFNldzb0tXbmQzTnhFV2paczJGQkJyVkRCd2NFS3FvUUtDZ3BTZ1lHQkFISURPVSt3VXJwaTJCZkp5cEtnSVFBSW9sOS8vVlZCa2t0SjhHUmxaUXRBQ0NpQ0NMOHJRS05VNVhIV3RVaGMzZ2VkU3A2SDl5b1BvV09LNUNleDQ3QVRlbnQ3eXloQWRuVjFrM2Z6OHZKRXAvT1hEc2ZPQnBWRk9pTUFLZlVCVWx6dmJIMG5sbnd1dmdmVUhKV2NuS3pPbkRtalRwOCtMWHpxMUNuWjUvblNvd0YrbDZwUUd2Z29udWtJdmxrOGZ1dEFaR1Rra2RqWTJQU1JJMGZXR2REZkV1Q2VQbjI2MDQ4Ly90Z0VLa1UzU09DT0FFa1hmUFNtMkxicXJHd3dObWpqeG8xVml4WXRWTk9telZSMGRKVENSeGRRczZFSkRoSUJ5TVpOUzB1ek51NzU4K2VsdkhUcEVvNmxvbUYvVVJjdlhoVGc1dVplaFRUTUVHRFVOU0w0Q1hxb1hncnFCMGFoQUJVU0VpTGJEUnVHeWdnVkdob3FuZHd5Q3BIWUlma3RDUGFmZi81WkhUdDJET1ZSRlI5L1dJRFBqbHVTY0YwUlJxMnpBUDloZExvOUFRSCt1Mk5pWXZZTUhEanczUERodzI5SndOOFVjTStZTWNPNGF0V3FtSXNYMC90Qk43d3JKeWU3Q3lTalQwbHdVY3JpNDZuT25UdXJEaDA2cU5hdFd5c1lUOUtZckVmd3dxaFNKMDZjRkVsMDh1UUpLWG1NVE5DV2xrcS9aNkk2UmVGQW9ITlU0N2VNam81V1VWRlJJakRZR1N6QTU3YzdjZUtFT25qd29OcTdkNi9hczJlUE9uejRzRWo2a20wRTZhNmhuVkpnaTJ5SGlyY0RJOG9Qb2FHTjlpMWI5bm11dWNwTnBWb0Q5NFFKRStydjJMR2pINlJGZnd6YnZRSG0raVUvRk5XR1RwMDZxWjQ5ZTZydTNic0R6RzB3NUhxSmhFbE5UVlg3OXUxVCsvZnZsdzhlSDM5RUpNNlZLNWZOVjl1cEtrUkRtZDgvTWpKS05XL2VUSVFLbVNNazdSR2VwNm9GRlZGdDM3NWRiZHUyVFczWnNrV0VDVlJGODEyS0NaSTlBd0pvQjhyTjZFVHJ1blhydG52V3JGazNSY3JVS0xoSGpSclZBQjlpTUF5Z0VlQWUwRldkektkRU1uZnExRm4xN3QxYjllclZDMkJ1SlZLWitteDhmTHo2My8vK0p4OXc1ODVka01SbmJRd2pPOVU4VWRyVGZxR2c2ZFNwbytyWXNhTnEwNmFONlA4VVRFbEpTZXFubjdhcWpSczNxQTBiTmdqWUxYWUhpYW9rYklMTEFQb1AzdDcxdm1uVnF0WHFEejU0UDVtalJKMmtjZVBHdWVNRGpJR085ejJHT2ZaWWltY052Vi9ERUtqOTZVOS8wcjc5OWxzTlF4eStqNlpCdmRDMmI5K2h2Zm5tbTFyLy92MDFmRGdOSDBXdXNmT3R4NjZ1cmhwVVJPMkpKNTdRdnZ4eXVYYjI3RmtOZ05ZZ2ZEVG83ZHA3NzcwbjdRamhwWGR0RWRwM2UzaDR4QXNEQmd5TTJySmw2eTA1b1dGRGZmdjJqVVF2L3p0ZTZpSjI1V1VJNkhidDJtbHZ2UEdHZHVEQUFma0EvQkQ4Q0I5KytLRTJlUEFRRGIwWWRlMWdycXNNNmE1QkltdFRwMDdWVnE5ZXJVSGRGS0VGOVZOYnRteVo5c0FERDJqUTlXMnVvNzd1N3grd016dzhmTXFJRVNPQ2NPeldJeGg4clUwbTA1ZDRTU3BmOHVDUmtaSGFLNis4b3NFSUVUQmZ2WHBWMjdScGt6WnQyalFOZXB5QTNsTFh6cmNYKy9uNVFXZ04xajc3N0RNdExTMU5nSjZlbnE0dFhyeFl1L2ZlZTZVemxMNEdFajBmdXYxS2RKS0JMNzMwa2xWMXZXbDAxMTEzdGNRRHJhRGJHTHZ5MEVPR0ROSFdyRmtqWU03THl4TkFQL25razFyRGhnM3Rxc2J2a0tGcmF3TUdEQkJnVXcwdEtpclNUcHc0b2YzMXIzL1ZNTXJiMUNkR0lPVVRJaUlpbm52aWlTY2xyS0ZXQ2IzU0IyQjlEL3EwU0dvUEQwL3Q4Y2NuYTBlUEhwV0hQMzM2dEtnaDBkSFJka0RiMmNxK3ZyN2F4SWtUdFMxYnRvaDZtcFdWVlJBYkcvdXlyNi9mVWIzNm5wNWVHY0RaMzZHeUJHSy81Z242ODFCWXZ5blkxQmpQTUg3OGVBMFdzb0I2Ky9idDJwZ3hZelEzTnplYkI3V3puUzFzTUJpMFRwMDZhWXNXTGFhNjhqb3daQVN1SG9JNjg3TmVmZUFwS3l3c2ZIWmMzR0JmN0ZjL1BmLzg4KzRoSVNFZjRjRTR6eU5HSW5zZ1FiMXIxeTZ4anUxNnRKMHJ3aHpWMjdkdm4zTCsvSG54SEQzMjJHUEdaczJhVGZEeThqcFRzcDZGUFR3OExqUnQyblR5bkRsemlxUFRxb1BHamgwYjR1UGo4eE0yQmNBMENqbDloNGVTWVlaV0w4L1oyYzRWWlk3K0w3end3aEJzVzJuOCtBbmVqUm8xbW1WUmUwc3lPd1RzdkoydzkxcGgvNFowM1huR08rKzhzL0hodzRmWFhyNThPWUx4QzNQbnpsVlFQU1M4OU5GSEg1VkovS3BRV0ZpWWlvdUxFeWRPOCtiTnhUbUFGNUNZQitqdzZvY2ZmbEJmZmZXVk9ubnlwUG1LbWljNmt1NisrMjVPYllyRGdqRVpzT2JOWisxVTNlVHA2YmtDN1Q3Q3ZDdkVtS0NSSTBkMjNMdDM3NmZBWGd2ellTc0IrTG1ob2FFdnpadzU4eDNvNUdYR3RaUUo3bEdqUm9WKysrMjNQMXk1Y2lXY3dGNitmTGswK0p0dnZxbGVlKzIxS25rTUdkZkFlK0RCSko2Qkxsd0c2OUROemtlaXl6Y3NySkY0eUJnRXRYTGxTdlh5eXk5TGNFOU5FUUU4YWRJa05XWEtGSW0vNE8vUzNjd096QWhCTzlVWVpUWm8wTUFFQVpkdDNyZlNJNDg4NHJGbXpab1B6cDA3Tnc0cXNQbG9NVkVJUXZCOEJTaytidG15WlJubXd6ZW10OTU2eXdNSy9nNXNpZ0d3Wk1rU3NYRHBsZUt4eWpLSGxYSGp4bG1uaFdpRTBpZzFtVXdsZEhZSCtVMDZkOGFPZlZEYnZIbXoxS1Z6QU9DcmtSa1lqQnJhN3QyNzVYY2dMYlNISDM2WXc1ODhoMTU5TzFjZjh4dER5UFhEdGk2OSsrNjdEaENHendJZll1K1ZadUIwTDlvckJOdmxJNmdMNzZPUWl4OS8vSEZwOU5kZmY3MUt3T0sxcjc3NnFqaDFxSytQSGoxYWRDNjl1aVdaTHo5OCtIQXRPVGxacnAwMWExYTFnbzZXKzRVTEY2VHo4RjN0TmtUdE13ekp0MUNXU1FzV0xHRGs0cU1BdVBoVVNqTUUwVEhnNmNaZXp1N2R1M2NENktTWDBQbENLYnQrL2ZweUFmRjZQSG55WkFIbmtTTkh4SU9wVitkNmpBNm5IVHg0VURvYWpWcTlPaFZsV044Q2JLZ2VXb2NPSFhUcjJMbm1HV29KSnl5dVM1OTg4b2xxMHFUSmMyVUpXRzl2NzIxVHAwNzF4SGJaQk9WK0l3cTVnUEVmOURaeTJMWWNxd3d6OWlBckswdEFGQjRlcmx1blBCd1NFcUlsSkNSb3VibTVXdWZPblhYcmxKY1pBTFJ6NTA0dEl5TkRwTGRlSFR2WERudDVlV1dzV1BIdjRtRHk2OURiYjcvdEFIVjFHVFoxNzlPb1VhTlBVT29UbFByT0dQS3B1VXV3QzZVMjlXM3VWNWJaMDlhdVhTdFMrLzc3QityV3FRajM3dDFiZ3dFcXJ2MnFxQ2NjU1RnS01FcFI3N3lkYTQ4ZEhZM2F3SUd4emJCOVE0SitIdURoNFdFTnppdkp4RzduemwzN1l0dVdnb0tDUGtBaEZlbHRaT01UVEpaamxXRktSUnFqREhOMWNLZ2VYWG41OHVYeWJPaU11dWR2eEl5RG9XZjEwS0ZEdW9FOGRxNTlidHUyM1NDVTVhS0dEVU9mUnFGN0gxOWZ2MzN4OGZIRjZ3MUxFbFNTQkJSU2FmNzgrU0s1T1h4YmpsV0c1OHlaSTVGaDk5eHpyKzc1eXZDZGQ5NHA0UDc0NDQ5MXo5K0kyU2xJbE41NjUrMWMrd3pWZHhyS2N0R1VLYy82dWJ1N2N4VzJ6WDJvS1FBZlBiRDlHODJZTWNNRXNXNmRidUUwSGFmaExQdVZaVXBIaGo2NnVMam9ucThNVTlvbUppYUs5SzJNMjMvbXpKbWkya0JIMHoydng2eEw5UXFqbS93K3Q3dDJ2ZE9tSG9VQm8rRDY5dTByKzNQbnpwUHB6OUwxeUgvNXkwdjAwTWsycDFsbno1NnRPeVBWdG0xYmJjMmF0WEp2Q0NDb1pKdGw0VWZwZW5XWkF3TURYMGRaTHVKQ2I1UEo5QjlzNnQ0THR0bDdLSlZWZkgvMzNab29DRFByUGxlVVY5VXp5S1ZrVExYQWRZOTBpbFFYY2VFdkY2NHlkUVBYL2xXVVlPQmEweDJVbCtoZ3NqaDYrdmZ2TDR0cTZVVXRUWHhQNWhDWk9uV2FmTU9SSXg5UUJ3NGNNSis5bGhJVEU5UXp6enlqdkwzcnFhZWVla3BCRU9pdXdPZDYwZkR3TURyV3VOSkpHWTJPNnV6WnMrYXp0d2RsWm1hV3V5SFo3cERjTzgyN05wU2RuZDJacFJYTVVPcXZXYkRMVkFsMGcxZUZDRzRuSnlkcG5Pb21ncFBlVGJyc0swcGN3OGZyOVlDa1I1YWNKd3c5aUlzYkRDQStEYUNORnM4cWM2SllpSzU3dXV0ZmZQRUZ5VWZ5L3ZzZnFPZWVlMTRkT1hKRXZKNGxDU09CV3JIaTMrckxMNWNyU0hyMTQ0OC9vbHdpYVJub21iVVF2YlZRd2RCSlJqRzRTTXJSbzhmSWJ3VUUxSDdJYzAxUi9mcW1DaTJzOVBIeExUUDJ3MmgwQ21OcEJYZEJRZjQxcm5nTTk5Y3M5cXdzWVppVnhxbHVzdHlUejFsUmd2cUY5eTMvdTFGYU11OEpGOEY2ZUxpclpzMmFxWG56NXFuMDlFc0NZQXN4L1lRbDNRU3pWOTEzMzcxcXdvVHhJaVIrK3VuYXFkeUVoQVRjTTAzU1Znd2FORkExYjk1Q1JnZU9KaVU3ekN1dnZDTFhMMXo0bWVRaENRand4eWo3bmVSY2VlNjVjcXVwZFlES0oyZ3NaRlpIZFFsQ1M3QnNCYmZCNEZDY3RNNU1NQ1lsbTFGVmlDdlpHWVBDRmRUVlRjeTZSTW5KUnE0b01WYWtJbm55UHYzMFV4a2hHT0JGbFlPSmF5Wk5la3drK2hOUFREYlhVcEorZ3BJN0lpSmNrdjZzV3ZWZmdIS2g4dlB6VTEyNmRESFhLdTd3bE9SOGg1MDdkNnJseS84bGlYR1k2bzJxREJNSldXajY5T2t5aWo3MDBFUHEyTEdqQXZRQkEvckxQZDk2NjIvbVduV2ZybFF3VDBkU1VsS1o0Q3dzTEVnemJ4WVQ5TG1va3ZQRzlDUnkrczZ5WDFtbTA0WEdINFlLM2ZPVllUNG5uNDlPb2NxNHl6bURRMGNRNDBmMHp1c3hqVGthMlBTT0RoczJURlo5QThnMjlXZ1F6cG56cnJaaXhRcnhxdEpKMUsxYk41dDY1TEZqeDJxd2EyUTVGc3V5NXR4cFJCNDdkbHlXOFQzLy9QUGFuajE3R04rc1c3ZXVNanJyR3lqTFRkQzdQMGVoZXk4STA0VW9mNVBjVTZaTVlhb3NhMlFXSlVtVEprMnNLY29xU3d4YnBaUnExU3JHZktUcTFMUnBVOG1VdEhYclZwdWtNT1doRFJzMmlyN2VwMDhmODVFYkV5VXlFOU13enVHYmI3NlJCRUhVajBzVGpVNm1NSnM5ZXpZTXhrUzFhTkVpRzMzYlFueUh0OTkrVzdKbnZmUE9PNkpEVTZxWEpvWUcwM2psNzNJVVlVaG9TZFhsZGlDQTFTWXFzQ3g2N2JYWFhTRTA3alB2MmhCRzFQOHpiLzVHNkQxVzEvdWYvL3huOFNxaVlXeDZSa1dZcTNTSzU2UVg2SjZ2REZ2bXpobFFwWGYrUmd6alVJSzNLSWxMamxaMnZua01RVG9VWmJtb2RldTJENkhRdlE5VTZiTkxsaXl4RGNDUGpJeDhCb1ZVWXVJVmdwdjVLQ3pIS3NOVUc2Q0xTb3hLNjladGRPdFVoR0hNYVptWm1hS1dWR1h1Zk1hTUdmSitzYkd4dXVmdFhIdE1BWFAvL1lQYVlQdUdOSG55WlBkNjllb2xZdFBtUGxRSllaaFB4TFl0alI0OXVyNmJtNXZWODdOanh3N3QrUEhqVlhiQTlPdlhUMXp3ZS9ic1pjL1NyVk1lOXZUMDFLQ0tDQ2lIRGgycVc2ZTh6TlhZWjg2Y0VkMlpBVmw2ZGV4Y093ek1aWC93d1VmdTJMNHV6WjgvbndMNFEyenEzc2RrTXYzdzNYZHJ5NTQraTRpSW1JOUNLaE5BVkNtZ2o5dmNxS0w4ajMvOFErNUZ6MTVsQUU1Z2YvMzExM0tQZWZQbVZZczZ3YmdaR3BaY3FBQWRWcmVPbld1ZVlkanZRbmxkZ3FDbHJUVUI3UzZCZmFVWkJ2YlpNV1BHWEgvUndvZ1JJK3FqSXRkVkNZQ1laSWVCL0hRQjgxaGxtZEwvaXkrK0VIRFMybytKaWRHdHA4Y011ZDIyYlp0Y3UyclZxbXBOSC9IZ2d3K0t5c1JrTVdYTmF0aTVaaGwyM1Rzb3l5UW1SR1g2QjZpNE5vdUd5UkI4di9icTFhc2R0bTlNclZxMStnUDBGK2toaktsSVNVbVJPSTdHalJ2YjNMZ2lUSUJUZ2xORnljbkprYmdMNnVFTWVTeGRsNVAwVEwzMi92dnZTeXc0VlJIR2wzTktyblRkcXZLZ1FZUEV3R1NXcklVTEYwbEhya3pNaXAwcnp0U1R1M2Z2WG1aRUlGUVJoNmlvcUtjQWJOMVZPQkIwS2YzNzkrK0tiUnNxYzRGd2VIajRod2tKQ1k5enUydlhydUlWUzA5UFY4T0dEWk5rNUZVaDZPQmNwNmxhdG15cDZBRlBTRGdsRHBDa3BHUTVIeFFVS040K3htOXdhb3dwalY5ODhVVUZxVjF1bDNsRmlZNm1tVE5uY3RXMWhBeHdjVENIUXJycCtkN29YT2FhZHFwbXlzUzNEM3oyMldjenpmdFdHanQyck5lbVRadmVReHZZTEJBbStmdjdING1Pamg0RU82eGlRVkQ0TVNOMElVNkdTdzlobUNsK1JMdDgrYkwyeHovK3NjcVNqYk1vekNPM2FORWlTY0ZHM1pkcUI1bmJOUFNXTGwycXhjWEYxZXE2Umk2Qll5NDdUaE5ldW5SSlJoaEdFTnE1WmhpaitML3czYThoTGlucjBhUEhQVDQrUGlld2E5TkdWSmVEZ29LV1FvVytyZ3U5VE1sTklzQUJzTGtZc2grbXhLUXpnZTVrL0xDQ0xxNm1UWnNtZnlkUlZhSjBwbnZiNHU3UHlNZ1FON05lYjYxTm9nUm53QlFkTTNhcWZtSzd4OGJHanZqb280OVdtQThwcUloQjBBeG1wYVdsalFId2JUeUlucDVlRjhQRHc1NWV0MjdkRitaSmdNclQyclZyRGJCU1gzSjJsajhFbFZobXVxQzVrS0ZZYjU1YlpWM2N6cjgvNW1oOHp6MzNwSDd6elRjaU9ZWVBIKzRESE0yRURzMGNKRGIxalVaalFVaEl5QUtvS3RYLzU1a2RPM2JzaVdIQ09ubk9sZkh6NTMrc1pXZm5DTWk1MXBLTGR1MkdtSjJ2eDh4SDg5UlRUOGtpRnRneGJ3d2RPalFRQnVOc2QzZDN4bGZiMUNlZUFnT0RObmJwMHFVdDltdU94bzhmN3dWRDh4ME0wOVlwR2E0STRZd0dKVGxuTkxpaW5LdEtUQ2I3dkxHZGk1bFR0M1RrMFliaXRETHRLdjdUUnJ0MjdWYTZ1TGp3UHdGdHJtRXFrWUNBZ0kwUW1IM2k0K092cXo1WEsvWHAwNmNsZXFBMThUeVpFWFpQUC8yMHRuLy9mZ0Y1Wm1hVzl2WFhLMldoc1orZm44M0QyL24yWmtZNlF1M1Evdm5QZjByMEpvbi9zUERwcDU5cXNObktIT0hSRWZLaFN5KzcrKzY3dTNDbTZxWVJlbFdiK3ZWTi8zSnlLdGJIeVh6b3pwMjdTSEFUWnp4STdLMTB2anp5eUNOUVowSjExd25hdVc0ejI1UUdIb1VaSlhScWFxcTBQVU4rVjY1Y0tSbkc5UDRieDNJdDQwVkNRME5mSFRKa1NQbFRvOVVHeGNiR05hR1h5Y3ZMNnhxOWlVNGJTSG41aHl2R2RSY1dGb2sza0l1UHAwK2ZMbWtmcWhxM1l1ZWJ4N0RCUkRwendUWGIxREtkeXdYaG4zLyt1VFp5NUVpSjRkRzdsdXpwNlptQkRyRVUrblEvL3ZFdWpsVXJWYXN1dzcvcDI3VnIxK0FMRnk2TWc3VHVqWmUxUGpDbjFlaVlHVFJva0N5dzVUYVBjZFhKcGsyYjFMcDE2OVRtelpzbEJ0cnVNTG4xQ0NPeXhMUjM2TkJSbkhyZHUzZVRoZFlBcU1TNWN4SDArdlhyeGRuSDFVVm9lL09WMXhJRVlDYXUrUTczV2hFVEUvUGZoUXNYMmpodnFvdHFURkhIOEdSQ2J4NmNsWlUxSEVEdm1aMmRiZjJYS3M1dk10Q2Zpd1hvcmJ6cnJyc2srSjd6Mmx4TXpQV0dYSWpBZjZwbDJ1TE16QnA3Znp2cEVJSE1SZFF0Vzhhbzl1M2JNYTREWlh0WkFrZUJ4UCtGcDMrRGk1b3BtTmhPRUdqbXE2OGwyR1hzQUtlZ1MzOFhGaGEydW1uVHB1dWhkelB5dE1hcFZxelFVYU5HZVFPa2ZhR0Qzd3VwM0JkZ0QrWGFTZ3RCTlpFRnNyMTYzUzBPSXFncklpVkkvQjl5cmg3bnloY3lKUVJkNDdlQ2s2ZXVFNFVNMTJjeVh6ci9DcHQvQUVCQXQyelpRcjQvVitHem5kQnVFbkpCaVF5QkplMVFWczV5ZzhGQTZYd0JZUDRKb0Y0SFFLK2ROR25TeWVIRGg5ZDZZOVhlRkl1WmxpMWJabGk0Y0ZIRW9VT0hlMlpsWmZURUkvVEl6TXhvbEplWFozMFdmbFRtTytIS2NBNkRsQno4VDNKTEdvZXJWL05rcVJWQnp1VlhYRGg3L1BnSldUbWVuSnpFeGFaMjFRWkU4SkpockttZ29HQkpKeEVWRmFtaW82UGxmOTY1elJIVDRvSGxjamVxaGN3elF3RHYzYnRQY3Fta3BxYVUrVDJkblYyZ08zdWNnWVQrQ2FEZTByaHg1T2ErZmU4N01uWHExTitrMTAyaVdnZDNhWUlsN2ZESko1ODBnSFRvQ3NCMmhLN1dQajgvdnpVKzlCMlFHdGJuWXdOUWxhR0VZY0FWMTFFeXhRSWJqQ3ZCS1RGZ25JdXVSNm5DYVNTbVQ3Q2tTK0N3eWJRTFhMM09sQW9jV3FudTFPVk9ZQWtQNENwOGdqUXdNRWdGQndmSm1rMG1ycUdBNERmajkrSDNJOUE1MnZIN25ENTlSb1FDMVQ2T2pBeE80L2ZpTitGMzFDTWEveDRlSHFrQThqNUk1ajBtazJsWGNIRHd0b2tUSjZZTkhDaEpUbThwdXVuZzFxTUZDeFk0ZnYvOTl5RUhEeDVxZ1kvZE9pc3Jzd1hBRzNQMTZ0WElqSXdNTndEUyt0d3VMcTZTeXlNc0xGeWlDSm1aaVEzS2h1WFF5aFFPbEZ6VS9TekVvWmFab1NpcEdQSEhXQmFPQkZTQnNyS3lSZVc1ZlBsWG5NOFJZNGxwR2xpSEhTY3ZMeC9YNXNxMVBNZjdFRENGaGVUaWpsSzhmMlBCNWVUa0RNQVZnNVNqbGJ1N3U4VFhBRGdLSUJMUVVtMmcwVVlkMk5mWEQrd2o3OFZ0dmpldnNRQ1h4Ti9teU1VOEswbEpTUUpZZG01S1pPWlRZWG5wMHNVeURUNFNub2Z6emI4Q3pNZHc3M2lEd1hnZ09EandNRHJNL3JGai8zQnh5SkM0T3FFUDNwTGdMb3ZtekpuakJKMHZDTU5tR0I2OUJTUlFCQURXeUdoMGpNckl5R3lBOWcyQVJMWXVNMktEVTU4bkFDalpxTllFQnhkTHNzREFCZ0lRUHo5ZjZRQ1VnUFhxK1lDOTVScFhWemZ3RFZOR1MwZWhwQ09vaW9xS2haZW1jZnZHN2Uvb1dOemhtQjZOSXc4Tk9UMnlkTVRNekN4SkJNU2NNaHlaTGw2OEpLTlFjbklLT21lcWdKa2pGY0hOamxlV0JHYXo0NXNVNHZOY3dIdW5RQ1dNZDNmM1NMN2pqb0JUNkdTSEFPSmpjWEZ4NmVQSGo3L3Bxa1ZWcUU2QiszcTBmUGtLdytMRmk5eUNnZ0xETjIvZTdBZHAxK1RVcVZOZWtIN1JrTVR1YUxRSUFOR2I2ZzZra1Q4a3RDTWExV0FXZUZZZ1VJSlN5cE81VGNsSnlVaHB5azdDa3RLVjB0Wm9kSkp6Qm9PRGxLeFBZdWVnNUwwZXNWTVFoT3dFVkFWb1J6QUhZbloybG9DWDU2ZzZzZVNvQVZWTnpwZXRSaFcvaUllSGV5R2VKUi92ZVJyUGpsdGtKYUF6LzRMZk9BVjE1UmZjNXdSc21iVEV4RE9ubm56eXlaeGh3NGJjdGxiNWJRUHU4dEtHRFJzTVc3ZHVjMXEwYUxIemdBRURncE9Tem5sdjM3N04xZDgvb0NFa3JpZlVGR2NNNmQ0Tkd6WU1oZ3Bpek0zTmNZSys3Z3FnK0FQWTlhQitHUFB6OHh3QlNnZlVsVVd0QVFFQlFSZ2xET3dnQU44MVlacFVvVmpYdkN2RXFwRFdWckhLK0dReXFBZ2RNUm1kcEFDZEl3L0dXZ0drZVdGQlFYNFdBSitNa1NmWDFkVzlJQ2NuS3gzU1BBMUc0bFVuSitNVlBNZlpidDI2NTBENlhvSjZsVHBzMk5EOEprMmk4emtmL1h1bTN4MjRxNXM0SHcrcGFBRTdETFd6MTRENzlPbEVBL1QzYTc0elFLaEZSa1paSlNaVUErdzMxaHdkRGN5V1ZFaEQyVTVWSmFYK0h3QVBnWTYrY0p1SUFBQUFBRWxGVGtTdVFtQ0MiLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6InR4QXV0aFNpbXBsZSIsImZhaWxfaWZfdW5rbm93biI6dHJ1ZX0seyJpZCI6ImNyZWRQcm90ZWN0IiwiZmFpbF9pZl91bmtub3duIjp0cnVlfSx7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOnRydWV9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiZDYxZDNiODctM2U3Yy00YWVhLTljNTAtNDQxYzM3MTkwM2FkIn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTEyLTEyIiwidXJsIjoiaHR0cHM6Ly9jcmF5b25pYy5jb20va2V5dmF1bHQiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkNyYXlvbmljIEtleVZhdWx0IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDExMTAwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTItMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTEyLTEyIn0seyJhYWd1aWQiOiI1Y2ExYWIxZS0xMzM3LWZhNTctZjFkMC1hMTE3ZTcxY2E3MDIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjVjYTFhYjFlLTEzMzctZmE1Ny1mMWQwLWExMTdlNzFjYTcwMiIsImRlc2NyaXB0aW9uIjoiQWxsdGhlbnRpY2F0b3IgQXBwOiByb2FtaW5nIEJMRSBGSURPMiBBbGx0aGVudGljYXRvciBmb3IgV2luZG93cywgTWFjLCBMaW51eCwgYW5kIEFsbHRoZW50aWNhdGUgZG9vciByZWFkZXJzIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjUsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmYWNlcHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MkUtMDYsIm1heFRlbXBsYXRlcyI6NSwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MkUtMDYsIm1heFRlbXBsYXRlcyI6NSwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbImFueSJdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRUl6Q0NBd3VnQXdJQkFnSVVldGVLRjBOSDU1Z3lSSy9ZbUJQVmUzZkFXUWN3RFFZSktvWklodmNOQVFFTEJRQXdnYUF4Q3pBSkJnTlZCQVlUQWxWVE1RNHdEQVlEVlFRSURBVlVaWGhoY3pFUU1BNEdBMVVFQnd3SFNHOTFjM1J2YmpFYU1CZ0dBMVVFQ2d3UlFXeHNkR2hsYm5ScFkyRjBaU0JKYm1NeEZEQVNCZ05WQkFzTUMwVnVaMmx1WldWeWFXNW5NUll3RkFZRFZRUUREQTFCYkd4MGFHVnVkR2xqWVhSbE1TVXdJd1lKS29aSWh2Y05BUWtCRmhab1pXeHdRR0ZzYkhSb1pXNTBhV05oZEdVdVkyOXRNQjRYRFRJek1URXdNakUxTlRnME9Wb1hEVEkwTVRFd01URTFOVGcwT1Zvd2dhQXhDekFKQmdOVkJBWVRBbFZUTVE0d0RBWURWUVFJREFWVVpYaGhjekVRTUE0R0ExVUVCd3dIU0c5MWMzUnZiakVhTUJnR0ExVUVDZ3dSUVd4c2RHaGxiblJwWTJGMFpTQkpibU14RkRBU0JnTlZCQXNNQzBWdVoybHVaV1Z5YVc1bk1SWXdGQVlEVlFRRERBMUJiR3gwYUdWdWRHbGpZWFJsTVNVd0l3WUpLb1pJaHZjTkFRa0JGaFpvWld4d1FHRnNiSFJvWlc1MGFXTmhkR1V1WTI5dE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBajBIck1XOExRZVlBSkdsdkxRTmdjZnl6cDlpTmpYMHlvR2ZBdkhSWTRieDJEcldhTUJoOTFPRXBJanpXaHBCY2NpWWk5Z3ozSmtWRkdMK2RKc0tkbWhKWHhIVkJ3TXFXYlJyVDBkUEtoeWY0blVQN215TDFKU2Ztd0RSSGNvaHh2blNQRTdkVzUxRjBacE8zUHRIM05XTTBvY3ZYMVBnWHlQZXliOUR4aG1xTVRmVHhGZlRsOXozN0w5SnQ0MUoxdmJGOURIRUV2TTlVUmgwdkF6cGVDL1hKQUtWWnBFUEUyWUtpVGliWnFBTkRLT0pPNzdOSWFFTUJFclB6TDdvYy9wdXhRUFVseDRzWE1FRWxmVzc3QkxoL0xlOXpVWWlPRlN4cDhXR0JNNVU5Mld0VGg3bW9kRW5Jd0EzRUgrUWlmNzNqd3BFaXFOSDRpNkdxTkxIQVdRSURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVVSeFhaelBMUUsxYlNmcnkrK1NQaWE5RXQyaHN3SHdZRFZSMGpCQmd3Rm9BVVJ4WFp6UExRSzFiU2ZyeSsrU1BpYTlFdDJoc3dEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGZ3N6VjNXWDJXYk5LTitCaDg1aUltZjcyQ3RuV3ZmY2FpVXdUWHZsNEVyOVoyQi9sV1VqSGxOV1VzdGlOdzdDUlFrSkRrQmpPM3Z5eTcwZjBRQ0pJUFZPOFNBaEpwN0s0VXBDS1ZtZmpibUZCWjVSMk40elN2b2dGcmRuNHIydnV1L2U0c09kWG1xdk12Q0FFVEZGN3IvZWRPY1dPWFhCR2piTmdUYm5aWVBNbk5Sb1Z5NVhBaFhTaTlwTDI5b1BBWTUvNDZuNGxpbk9pRG95MUNHbHBtNGtqa3BFZFV0VWZ3blMvaEV4a0x1aEE2QVZxR29NVlVsZWgvMW5VTUVGYjQzdWJMKzR3M1diOS9yMXhOSlVCN04wd1F5Z3B1ZVowaExaeDErOU5zVDFKUTJiUlo0blhLTG9TZmlRdzhDNG1nM2xoOHNvZjJ6cGVZSUtUS05kVmc9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFLQUFBQUNNQ0FZQUFBRDdvYUpnQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQURPVkpSRUZVZU5yc1hWMTI0andTbFRuOTNzd0syanpONDhBS0dsWVFzb0tHRFV4Z0JZRVYwSmtOeEZrQnNBS2NGVFQ5T0UveDdNRGZDbnFrZEttL2lwRDhLOGt5MUQzSEp3bkJ0blJWVWxWZFdUSmpCQUtCUUNBUUNBUUNnVUFnRUFnRUFvRkFJQkFJQkFLQlFDQVFDQVFDZ1VBZ0VBZ0VRZ3RFUVJmdTMvK2Q4eDhQL0hqNTlaOS9KdFJjdGJoYjhCL2YrUEhFdVR1UUFkWWpiOHgvN1BneFJSK24vTmh5TWxNeXIwYmNyVGwzWnpMQVl2S0cvTWNqUDFZRlgwdUF6SnpNN1lJN1lYaUxncTk5aDA0Y0RIZURnQWdVUnZkV1lud01DSDdqMzkrUTJWMXd0eWo1NmdxNFd3VlQ5Z0RJbTBMUEhUYzRQZVBIOGxiZE1uRDN6SSs0d2VsbjhDVHBUUm9nSnk4R3c1dGJ1RndLaHBqZGlPSFo1TzRBaHBqZGhBRkNyTEtDN0habytmSmJFZWRjYTN6b2tEdkIxMU1YM0VXZUNaeER6NDBkM2lhRFFEdTVNdVB6eGQzYXAyd1RlU0l2aGxobDZySE5ncFVlYW5LbmsxVjhjT2NscElrY2sxZEZWbkdOaFBWUXRnbUVPK2V5VGVTUXdBWDAzR0VBN1prRGtkOTdZbndyTUw1UXVGdTdDbWtpQitSTldYTlp4VFV5RnJCc0V6aDNUbVNieUNKNU1mVGFSUThHbVU2bEJ3TjN0bVFWSHlITjFoWjNrU1VDTjh5TnJPSWFuY28yamlVcDEyNVpQT1N3NmRRQVBVa0RQdHl5ZDlubWlyaHJKZHRFRGNrVHBQbVdWWHhJRDg1bG00NWtGUi9jTlpKdG9wcmtoU0FOOUZKNklPNWFHbUJnc29xUEdNZWFiSE9EM0ZXV2JhSUs1SVVzRFFRdFBSQjM1ZHhGSlhGZVgyUVYxNmdsMnhCM0g1Q3dBdGttTWhDNFlmMlVWWnhMRDZ4RXRpSHV6TnpwWkp1QklWaitRZ1JlUUNZUlAwQkNNU1VhbjRrN0xYZGZnSi9LTHZpVzQ1ZXEwb05XdHJsU3FjVkpMQmdCV1hPVGF3a2dnenV3c0tlb0VtWjQyZ2E0RTZObWZJUGNGV2JETU1CbEErUmEzb0N3RDRBTGpOaHZqY2YzQ0RQaDk3K0grNmVCR3VDQ0dSWkpBWGNUOW52S3p6ZDNJK0J1MGdGMzMrSCtpUzVCNDhlSi95cU9PQUpMUENtRjE2Ni85ZVJhTW1hWUdtdTVDTWNIUk5tWEJ1NWk1djZCZzR3WnBzWThqY1pGWVltYzkzNUVIODkwQmxqRnRiaVl4Nnk4THFFSG1XYktERk5UampwUnBZY0RIRDc4WURUOGtqQ3UwQUFMSzJhdzZEYXhTcTNIbzNxaXRXMExZbXRiRDUwbXJPYmpVWlpINDZJNmxpV3lwUVpZWldodlU1bldEem4ySUZzM0J1TVZkek1JbFR2am9GRmpjS2hzZ0xaZGkvVkg1QU43akwxdWZEU0Zzay9iR0xRbjdveHhib1B3cUxZQjRpeG5heGgyeXdyZ2JLRkxUNTQ0S1pOdGRvRnlWeGhuTnN3TEdodGdFOWRpSEFFY2tCbTZFR3owQUliWTJ1aDVQSEZYMUdsaTF2elowRllHV0JxTHdMWGwvbjdlOTZnTFFBaTJJZHQweFowWTBlVCtncWtqYi9OdWdLS2liNVpjeXphMC9Wa3NaK3V1RU5RaXFZb2QyOGJzMkNTQ0MvN3lxVWQxUkZvYlYrSExMUWZKblN2RmdkYzFzbTJBcGJKTklDVDJjamFsNDg1clhYTjFhWURlZytjR3BOYVJDN3FTYlRybnppVlBQZ3pRdVh4UUlmWjdZT2JaSEJub2gveTBUU2RybDMwc0cvVnBnSVd5amFmc3R5amp0QnJiOUp3N2I3R3lid1BFcnNYSmJ2Y1Y5VCtqYSt2SmJJb3I3cnlMK0YwWm9FVENMRzJiMW5CT1ZldmFXczdQOW80N3k3SktiUVBzY3BkOFVlbld1OTNYMkNGZWhmWWhYTkdvL0ZpeWJoN2tyTXZkcWlWM1UzZzQ5TG1yVWIvTEViQ1Y5R0JaVGpHNnRoNHNLbS9DblJOWnBXOHV1SkgwNERoejFicTJhNXBOQ1VsK0N0RUFqYktOUnlQSVMyU2IwRGRsTXNXMndlM0cxWFVNV0lTVkpodnpOUUs5WjRPOHdkN0F6V1BDTW43TStLLzM0UHBDeEVVbUM3SGluZ1U0K3pOQWNRVGhJMFJqblhqajdXSGt3NFo0NE1jSVJwcytiSDRlN0VKNWFZQmRMQjNzQytZeVcxZFg5b09ibmtEOFJhZ1g2MC8rR0NCSUQ0TE1FWkZaNk5wK2FFYkRETmJmQ3RkOEpwb3FaZXd6K1dEeW9JQk1jc3Q2OGpKRFFKM3lRL1RxZFUvY2NoZkowVVNkVGh3VWtEa2lNdjlreFVMZUdGWFIydUF4ZThGZFFqYjNEdUZSQlhjYjNjek5nTWdzUkFMazFWcTkxNVBaRkI4ZVE3amEreUp0Y2tCa21vTmtVZTgyODYwaXpnSFpabmxEbnFTV3h4ZzBKRE83WXZJK0JNazIwT0VHVDhGN2pFRkRNcTlSdHRreXc0NU9sb3hRZUpJMUMzdW5MKzhlNDFOVE12a1BvWXVKeHVyNyswSlM1dkhSZDdqUGpGN3kwM0FFVk1rRXQ5eEgyVVlHeWJNdTFsM0FnaTNwU2ZvWUgycGxsYnI0WklsTU1ZcU1lckpCZHpETEh4VlAwcGVYRlZwZHd6eXdUT2lHaFMzYnlDQjVFMUtoZWpJQlVFbFc2ZFFBVWJDOUJESkRDYlpUSUc4WjhwdlRBNTBBcUNXcmRHNkFDcGxkYTJCWVZ1bE41aG5RQkVCdFdTVVlBMFJrSmtDbWI5bkdxYXppSXo3czBKTTBsbFU2U1VKcUJ0dXVaUnV2c29vUHR5enE1R2x0U210WkpiZ1JVQk5zdTVKdHhQWHV1NUpWUEhvU1YrN1FpcXdTNUFobzZOVzJaSnZnZDVXeTdFblduTGNuaTU2azA2M2hCaDBUdW1rWmJDZlFhNi9lK0F5ZXBNM2FGQ2V5U3E4TXNFV3dmVWF5U3NadUZBMW5VNXpLS3IwelFPeVdLOGcyVWxhWjlFbFc4ZENCTjZ6YTJoVG5zc3BWUUN6K1VkZGV3RHZHNkRXbzVkeE4xZTFHNExNcHNVTWdFQWdFQW9GQUlCQUlCQUtCUUNBUUNBUUNnVUFnRUFnRUFvRkFJQkFJQkFLQlFDQVFDRFlST2IvQjczZjRpa2ZwYzd6cktIcEUvRnhuOVQwOGx2LytZdWxyV2hjQyt3V0tKYXF2dDdUSzcxTURvbFJ5c3BMRnpQSUYwc0pZWnVqekUveXN1L1hFR0owYlhWRmI3T0duV0w5eHNMbEY4TlVZSVBUU1I4M25CNXQ3aU1BN2JJWFJicTlsTkVCMWtxdi9WT1RTVTdBT3QyZ0R6L1JuY0hEdFplb3V5N3hEditOUmI4NEliU0hYOTA1QzNrS3VheGY4SjI1anYvZXdXeUREVE1pR21nTVcyRzl1cmQ2VkRSQ1NpUmorZkJHOVZMaGVHUDNtSWpsbzIzTlJZaUxYLzM2cGtxekFPdGl2VUw0TUF2bWs1RjR4bFAxZmNKN29WRC81b1EwblVEbEV6SnZCK2ZLK09aeWJxRHMxYU9vMFZLK0Z5aE9yeVpxbURXU1poMURtVjlnaG9TaHBrK2VNNGVNajFETlQrSWpSZDk3amJmNDUweVY4bXV2bWlMK3ppeEh3Ry9vOVJSV1pJemZjZGhROEtYOHYwQ2g3a2F4QWd6d3JwTDJmeC8vM0FER016cGhFWXJReWpPNDcvdisxeG9CbDJiYjgvNTgxNTcvSHgveC9TK1hjVTBFU3RVV2ozZ0xpYXpWWms0MjlaNWViRVltL1Yvei9vc0dYYXNPRG9lL1o1ZVpQVXlncnJ1ZENFOS92ZElvSjVBTFBtdXRLRGc1UW50eW1BYzVScjVVVlBVQkJiTG5oRkRYU0VFYXpEQVhwdXN4UmpsNUhWSTR4SEh0Tlk1NVFRNHBydjhqUkZ1b283dnNzZXI1aEZIMUFaUlAxL3d2T2xSMUZuSnVpMFVXdFU4NytmcXRtVnFOampsSDRjMFJsWGtpajV2Y2R5VWFIem5sU1l2Yi84ZU16MURPR3NtWXd1bVZRMXFGeXIxempiWjVSbXh6Z3VwaDdlZjJKRlFOVTNPOEJ4UzFXM2JETURwR1J2SlJrd1RIME5Hd29ZaVBNUFpSSlNCb3hjbk1MWkh3SmJJcUU2N2xHamIwelpQZERhTXcxL2g5c21mWUQvaFFqeWRKUXA3TWhDeTZTdmFSQnFIV1Y5ejFCdVhieXZtZzB5OEVUWUExMkMyV041YWdMMTAyVUxIaU5YUytNeER0a25Pck9XaHNvN3lPNDcwVlpLRlExQzhaRC80dnl2Mk9IMmJCcE44KzFvZXdQS0o1Y2FqcEFqczRkb2xGTmxVdldxbUZDQXg5UXg3QUZHZnFrdXJyQ2ZlV21ueS9vYzJFY0VULytvYnBtS1B1VGhwOHlMSkRiMWU1TUJnTkdwdkRkMmdWTEVuUUJzbTAzWEFjSFUwWXBnMmRwREhnR1JSaGd5V1k5VXBNVENZYTZrMVJTTU1yL2xDT3ZKVTB1UnNaOExQQWM1NEpyekRVeHNuVGZkWEdIUW9kaEFZY3BDZzNhR1NDUU1FWVozSytpT05GR05sekRaZGVaTFJnYmtwc2k2SGJqK3N0akI4TWo2Ym1tOFk1UmpPeWlYQ2RmTWt4ZHQyb2pHM2FOTTZ1Mm9XTXZwOE5ndEQraERuVFdqS0JmS25aQ2s0YzQrekpBTEwvTUtrZ29vWXJTT0Y0NTltU0tMemVNaGxVR2dhRXBjVUVKV1ZNRHpPb2tVbzBOVUltYkRrWHpna28ySEllMmRTN0VoUmswNU5lS2RjNjZySWNJTVhoNWNEeWFsTVdLMEVZeHVvWnBNUGphb0VpdkVOK09pOW9ZUFFGVitzVFNvRUpQWW1WQnNNTnMrTFBsTnBWWjRzVXVvZ2pQTUpxZldCaXZvWldKMWtJWDlFT0grUUhsZlRRWWd5NHhhVEw2WVdQZUdZeHZVVlNldWk3NHJpempOR1REM3pUWjR4aG1JSTVLcnhCaXFFbnZXMEh2L2dreVJOcXlNYit6djhWU2NkK3YwS3N6K093QmpSNnA1WGRtNU1qNDl6WHF0RVl1OVFRdit6bkM5ZTZRTklJbHBBUTEvZ2wwdnpOOFQ1NlRHNUtzWEdrYktiWW40RVcyY0czaDZkNUF6bEd2elpUeTFCOEIwVnlmMU0zeUVuZVJJeU1kb3oyZVgxRkd1V0lmWnlGa2JLUDJsQ2RsTkgyME1ScEJHV2NvZ0Y2Z0VRKy9QRnJVNDk3eVNJWjNzcTljSjFUbURKVjVEMlZlSWVPN2w2b0F1RWFzWis3ZyszczRQek1aQjF3alFXMnpnckpLRjc5QmcwdXN1YlpzMjFrVmxlSlRpUVN4UmJwT0ZUeEJ6OFlWMnFEWUMxOXJ3ajRLbS9pY0F6OW5walJRaWlxM3JkamdGMldIQnAyQXE3aFQ3bi9Xak5DRjE5UG9YMFh4M0VSeGZhbWhmanFqR0JuS2ZHUWFiVkxzaEE5enhBKzY3eXZ0cTk1dnljOTlWUktmRFAxZnZpem5RWkczY3VBdmRCV0VRQ0FRQ0FRQ2dVQWdFQWdFQW9GQUlCQUlCQUtCUUNBUUNBUUNnVUFnRUFnRUFvRndMZmkvQUFNQVRhaXQ2OW5VVVNFQUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiNWNhMWFiMWUxMzM3ZmE1N2YxZDBhMTE3ZTcxY2E3MDIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MTYsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwiZmlybXdhcmVWZXJzaW9uIjo1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTEwLTE5In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMC0xOSJ9LHsiYWFndWlkIjoiYjkyYzNmOWEtYzAxNC00MDU2LTg4N2YtMTQwYTI1MDExNjNiIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJiOTJjM2Y5YS1jMDE0LTQwNTYtODg3Zi0xNDBhMjUwMTE2M2IiLCJkZXNjcmlwdGlvbiI6IlNlY3VyaXR5IEtleSBieSBZdWJpY28iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NTAyMDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImI5MmMzZjlhYzAxNDQwNTY4ODdmMTQwYTI1MDExNjNiIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlNlY3VyaXR5IEtleSBieSBZdWJpY28iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MTAxNzAwNSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4xLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDUtMTIifSx7ImFhZ3VpZCI6IjU0ZDlmZWU4LWU2MjEtNDI5MS04YjE4LTcxNTdiOTljNWJlYyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNTRkOWZlZTgtZTYyMS00MjkxLThiMTgtNzE1N2I5OWM1YmVjIiwiZGVzY3JpcHRpb24iOiJISUQgQ3Jlc2NlbmRvIEVuYWJsZWQiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJlbi1VUyI6IkhJRCBDcmVzY2VuZG8gRW5hYmxlZCJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQytqQ0NBcUdnQXdJQkFnSVVCOWY2d2VWNExaam5NNVBCQVdFdmpRd3FxKzB3Q2dZSUtvWkl6ajBFQXdJd2F6RUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQW9NQ2toSlJDQkhiRzlpWVd3eElqQWdCZ05WQkFzTUdVRjFkR2hsYm5ScFkyRjBiM0lnUVhSMFpYTjBZWFJwYjI0eEl6QWhCZ05WQkFNTUdrWkpSRThnUVhSMFpYTjBZWFJwYjI0Z1VtOXZkQ0JEUVNBeU1CNFhEVEl5TURJeE5USXhNek13TjFvWERUUTNNREl4TlRJeE16TXdOMW93WmpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBb01Da2hKUkNCSGJHOWlZV3d4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4SGpBY0JnTlZCQU1NRlVaSlJFOGdRWFIwWlhOMFlYUnBiMjRnUTBFZ016QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHS3Q1a3ZKTUpvQU1nYmN5WjFtTWdQd1YvcTVWWlhWMGJYM1dEZUJZY3Q1L2RSVHhXaGczYlEyekptVG1iMi9SV3ROL2NvVmEzSVZqTkhJWW1uV3JqT2pnZ0VtTUlJQklqQU9CZ05WSFE4QkFmOEVCQU1DQVlZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQWZCZ05WSFNNRUdEQVdnQlM3NkRwbDkzdkIyaDVGREx2eU1NdlVCeWozaXpBZEJnTlZIUTRFRmdRVTE4ZHRTd2FZZWE4UW9Mc0t4OGhQaVNOWlYvd3dSQVlEVlIwZkJEMHdPekE1b0RlZ05ZWXphSFIwY0RvdkwyTnliQzVvZVdSeVlXNTBhV1F1WTI5dEwwWkpSRTlCZEhSbGMzUmhkR2x2YmxKdmIzUkRRVEl1WTNKc01IWUdDQ3NHQVFVRkJ3RUJCR293YURBL0JnZ3JCZ0VGQlFjd0FvWXphSFIwY0RvdkwyTnliQzVvZVdSeVlXNTBhV1F1WTI5dEwwWkpSRTlCZEhSbGMzUmhkR2x2YmxKdmIzUkRRVEl1Y0Rkak1DVUdDQ3NHQVFVRkJ6QUJoaGxvZEhSd09pOHZiMk56Y0M1b2VXUnlZVzUwYVdRdVkyOXRNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnFDUVVnT1lHUTFTT0V4MElXZmlBbHNPS00vSlEyWFErQ2k1dGlqblFSVEFpQmhOYTBFOGpXc3NiQWYrbEduQVFOQWUzbmU2WHMzRXhac2lER1l3aEVVcEE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFWTUFBQUNzQ0FZQUFBREcrRThNQUFBQUlHTklVazBBQUhvbEFBQ0Fnd0FBK2Y4QUFJRHBBQUIxTUFBQTZtQUFBRHFZQUFBWGI1SmZ4VVlBQUFBSmNFaFpjd0FBRDJBQUFBOWdBWHA0UlkwQUFBeWdTVVJCVkhoZTdaMS9iSlRsSGNCdmpoak5jQzRPK2RYZVhWdFVUTXppUDdvWVhaWTUxSWtLZDFmTm5GSGo1b2hCbUE3ajJNUnNab2xteGhoTkpvcnQyNEtnc2lGc2ltN1RBZE1ZUkZRRUZUY1Z4dy9yd0FFRlJDaFErdXVlUGMvMXFRUDNUTnMrMzN2ZXUrdm5rM3pTNDJnZm52ZTl0NTgrNzczWEl3RUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQVVFcGtHNi9YUHBuSVJSOGdJaDV0NDFyOWNZYXRCZndQOVEzbjZ4MjBUWnRQMURjcFJNVFBOZGVVMTR1dVZ0Mk1xMjFGQmt4dE1qbXJMcFZxMFI4MzExWlgzMnJ2TG1NS1AyMzBqcW1QM0RzTkVmSHp6RVc3RXhmT0dXbUw4b1drazhrZjFxWFNQWFhWcWFYSlVhUE9xS21xT3JNdW1mcHJiVExWblVxbExyZWZWa1pNbVAxMS9aT2x3N2x6RUJFSG9qbXJ6VVpUYlYzK0wzVmp4MDR3SVIwOWV2VEo0MUtwS2RvYmpDTkhqaHcxZHV6WTVMaDBqZEtyMUxQdHA1Y0JKcVNzUmhGUjB0Nmd6clNWY1hHTURxbXFTU1l6K3ZZd0U4NmFxdFMxdGRYcDY4M3R1akZqVWpWams1UDFLclc5OTlQTGdWelU1ZHdaaUlnK21xQmVPcWZPbHVZbzB1bjBjVHFtWGZhUHc4d0sxZDVPNkZQOHQyclQ2VnYwelMrYnNQYmVXK3Jrb28rY093RVJVY0pjZE1EVzVpaXFxNnVQSDVlcTZWdDFGbGFtT3FJNzYxSTEyMDlKMS9SRjlrdmxFZFA2aG04N054NFJVZEpzd3oyMk9wOWlZcXBYbzUzMmoyWmxtai9wcEpPK3FqOTJwOGVNT2QzZWYweDV4RFRYdE0rNTRZaUlrdWFpRGx1ZEkrazloVThuanRPM0N6RTFkNDRZTVdLTXZuM1EzQjQrZXZqSituYmZLcldFNFhXa2lCakt5NXZQc3VYNWxMcFVhbVp0TXIzZjNLNnRUcjVUdUZOVGwwdytXcE5LM2F6L3JxTzJPajNOM2wyaVRJNm1PamNZRWJFWTVwcWV0ZlU1aXJycTFETzF5ZFNCY1ZXcEcreGRpYnFxNUF5ek90WDNMN1IzbFREMTBYTG5CaU1pRnNOY1UrSFUzVVZ5VlBJTUhkV1ZwOVhXcVZOcmF2UDY5dktxRVZXbjJyOHVjZXFqL2M0TlJrUXNocm1vakY0dk9oQ0lLU0tHMUgwUnFnSWdwb2dZVW1LS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUkVRQmlTa2lvb0RFRkJGUlFHS0tpQ2dnTVVWRUZKQ1lJaUlLU0V3UkVRVWtwb2lJQWhKVFFTOTdXQ1V1ZUVBbExwd2RWdk52NWlMM25BYnI5eDUwLzF2RjlpS3RhejRETWE3SHdEeitydm4weDZ4Ky9PS1lkekUwMjNHUlBuN01NWFNwM2llVEc5M2JYR2tTVXpsdm52dXlpb3ZqcnB6bm5OT2cxQWYvdXMyNzdNaGgyZm5Kb2Q1dlFOZTgrcVArSm82TGFkRXE5NXo2NGRldVhXQkhxUXc2dTN0VVczdW4ycnhqbjFxOVlhZGFzbnF6dXFuNVpYWHlOUXRVNHVLSFZDSlRnWUVscG5LYWI2YTRxSlNZZnJUblFObkc5SWFIWDNMUHFSK2VxQ016Vk5pei83QmE4ZFpXZGVWOXo2dkVCTDJLclpTd0VsTTVpYWsveEhSbzBkblZvNTVkOTZFYWYrTWl2NmRKU2tGaUtpY3g5WWVZRGwzZWJ0bWp6cHUxMU8veGoxTmlLaWN4OVllWXdodGJkcWxUcHVxVnFya281OWhYSlNzeGxaT1kra05Nd3pQcnNUWHF6c1Z2cUx1V3ZLRXlkeTlUdVh1V3ExOHVmTDF3MzcxTDE2c1Y2N2NWTGlhRnBDZWZWNCsrK0UrVnVHQzJjMytWcE1SVVRtTHFEekVOVDJMQ2IvVXFzRkVsTWczL25aTzVLRlM0VHp0SlB4Nlh6bEZWVXhhcUtYTldxby9iRHR1dkxENjcyOXJWTjM2NnhJVHFxUDFWa2hKVE9ZbXBQOFEwUElYWGhqcm01RlJIN1pqSkRlcU8zNisxWDExOHVudDYxQzJQck5iSDVSR3hMMFdKcVp6RTFCOWlHcDRCeGJSUEhiWkpkeSt6STRSaC9ndnZGMWJJenZtVWdzUlVUbUxxRHpFTno2Qmlhc3cwcWgvcjAvNlFQUG5xQjM3SFJ6RWxwbklTVTMrSWFYZ0dIVk5qTmxKLy8zQ1BIU2tNVDcvV1VwcEJKYVp5RWxOL2lHbDR2R0txSGYrVHhYYWtjUHp4RmIxQ0xiWG5VSW1wbk1UVUgySWFIdCtZbXFpOXQyMnZIUzBjUDF2d3FucytjVWxNNVNTbS9oRFQ4SGpITkJlcDgyNS8ybzRXam53K3I4WlBYK3llVXh3U1V6bUpxVC9FTkR6ZU1kVis1YXBIN0doaDJYZXdRMlQrSWhKVE9ZbXBQOFEwUENJeG1tUk85VCt4STRibG1UVXRoZFd4YzE0aEphWnlFbE4vaUdsNFJHS2FqZFF0ODE2eEk0Wm4rRldDeC85Z0phWnlFbE4vaUdsNHBFNlR6NXl4eEk0WW52Yy8ydHY3NjYrT2VRV1RtTXBKVFAwaHB1R1JpdW5vNngrM0k4YkRpT3NlZGM0cm1NUlVUbUxxRHpFTmoxUk1oMTNSYkVlTUIzUE14dnJjS1RHVms1ajZRMHpESXhWVGN4R3FxN3ZiamhxZXJ1NGV1VzBaak1SVVRtTHFEekVOajFpQTlIR3pkbE9ySFRVZWJwMGY0d3Y1aWFtY3hOUWZZaG9lc1pobUd0WENsUnZ0cVBHd2JiYytmdUo2aDM1aUtpY3g5WWVZaGtjc3BqcGl0ejIyeG80YUQrMGRYU294TWFhMzZTT21jaEpUZjRocGVDUmpHdWRyVGZ1STdhbytNWlV6enBoKzUxZC9VdWZPZWxyRWIvNzhLYlVoaGpldU1CRFQ4SWpGTktiZjBmOHN0ejIreGoyL1lrdE01WXd6cHBVQ01RMlBXRXkxNTl5MjFJNGFINnZlM2U2Y1c5RWxwbklTVTMrSWFYZ3FMYVpiNDdvSVJVemxKS2IrRU5Qd1ZGcE10Kzg5MlB1L3Fqcm1WMVNKcVp6RTFCOWlHcDVLaSttdWZlMHFsbmZoSjZaeUVsTi9pR2w0S2kybWhmYzR2Y3pqR0Jxc3hGUk9ZdW9QTVExUHhaM21mOHhwdml6RXRDd2hwdUdwdEpqdTJIdUltSXBDVE1zU1locWVTb3ZwQnp2M203QTU1MWRVaWFtY2NjYlV2TUhFNjBLdTJiaFRIV2p2c2lPSGhaaUdwOUppdW1UMVp1ZmNpaTR4bFRQT21CNXJmaEtiSjkwbHZQZ2g5ZnJHZU43OWg1aUdSeXltSmZJYlVQWDNMSGZQcjlnU1V6bmpqQ20vbTI4bHBnTkdMS1lsOHJ2NXNaemlHNG1wbk1UVUgySWFIc21ZVG8vNXVzSCtRNTI5WjFldStSVmJZaW9uTWZXSG1JWkhMS2FaUnJYb3BVMTIxSGhZMzdLYmxhazR4SFR3RXROQlFVd2IxWXIxMit5bzhYRDJ6S1h1dVlXUW1NcEpUUDBocHVFUmkrbmtCdFg2eVNFN2FuamEydlVwL2lVeHZURzBrWmpLU1V6OUlhYmhrWHpPTkU2ZVdMWEpQYTlRRWxNNWlhay94RFE4VWpFOThacjVkc1R3OVBUazQzbmJ2U01scG5JU1UzK0lhWGlrWW5ycTlDZnNpT0g1eTdwL21aZzU1eFZNWWlvbk1mV0htSVpISktZNlpKZmMrWndkTVN5SE83djFNUlBqYzZWOUVsTTVpYWsveERROElqSE5OS29scTdmWUVjTXlyWEdWZTA2aEphWnlFbE4vaUdsNFJHSWEwOFduVGR2M3hmY2kvYzlLVE9Va3B2NFEwL0JJeEhUOHRFVjJ0SEMwZCtqVGUzMnN1dVlUaThSVVRtTHFEekVOajNkTTlTbiszT2MzMk5IQ1lLN2Vuelh6U2ZkODRwS1l5a2xNL1NHbTRmR042ZkFmekxNamhXUEd2SmVkYzRsVllpb25NZldIbUliSEs2YVRHOVRjdjRWZGxkNitjSTBKbDNzK2NVcE01U1NtL2hEVDhBdzZwdGxJblgvSG4rMG9ZYmlwZVZVOC95VkpmeVNtY2hKVGY0aHBlQVlWMDB5RE92ZjJaK3dJeGFlN0o2OStOUHZGMGx5UjlrbE01U1NtL2hEVDhQUTdwaVprK3JUZUhHdjNQclhlZm5YeE9kamVxY1pOWGVTZVV5bEpUT1VrcHY0UTAvQWt2blYvNzdzdGZkYUpENmxoVnpTckU2K2VyMDYvYWJISzNMMWMvU0h3Qy9PWHZibTFNQS9YUGlzNWlhbWN4TlFmWWdxR2c0YzcxVlgzUDE5WUNidjJWMGxLVE9Va3B2NFEwNkZOUjFlM2Vualp1eXJ4M1FlYys2bWtKYVp5RWxOL2lPblFwTDJ6U3pXdDJOQjdTbC9LRjVrK1QySXFKekgxaDVnT0hmTDV2SHE3WlkrYU1tZWxTbHlnVjZMbEd0RStpYW1jeE5RZllsclpmTngyV0sxNmI0ZTYwYnpUVTdaUkpTWjVQTmFsSmpHVmM5SnZscW5sYjI0dFhJRU02Y3AzL3EyTy9mNWM1NXdHWmFaUlBmanNQNXovVnJIOTNjcU4raHZNNDZMRHhEbnFwWGUzTzhjdXBpdmUycVl1dWVzNTk1ejY0UWxYejFlNzk3ZXJsdGEyaXZETkxidlYyazJ0aFgzejZ5Zldxb2wzUHFkT01EL3dMOWFuOGZxSHRXc2ZsTDNFRkxFRU5LZTQ1dVZJWmxWZTdwcnRNRmZoeStsS3ZJVEVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUkVRQmlTa2lvb0RFRkJGUlFHS0tpQ2dnTVVWRUZKQ1lJaUlLU0V3UkVRVWtwb2lJQWhKVFJFUUJLemFtdWFqVnVjR0lpTVh4b0sxUGhaRnRhSEpzTENKaWNjeEZ1Mng5S293cm1zYzdOeGdSc1JobW9sL1krbFFnNWprTTEwWWpJa3FhaS9LMk9oVktydWtGNTRZaklrcWFpM2JZNmxRd3VhamJ1ZkdJaUJMbXRPZmNkN3d0VGdXVGk2WTdkd0Fpb29TNWFKbXR6UkNnUG5yTnVSTVFFWDNNUnEyMk1rT0liT05HNTg1QVJCeU11YVlLZlNsVWY4aEZpL1FPeU91VnFudm5JQ0ora2ViS2ZYM1RXbHVWSVV3Mk9rMnZVbHVKS2lJTzJGeTBONUZ0dXM3V0JBcVlxTlpINi9USGZUcXNuWW42WnIyekVCR1AwS3hDczFHYmJzU1dSS1poZ3EwSEFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUVCcGtVajhCNEFvbStNYlQrM0pBQUFBQUVsRlRrU3VRbUNDIiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI1NGQ5ZmVlOGU2MjE0MjkxOGIxODcxNTdiOTljNWJlYyIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDEtMDQiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkhJRCBDcmVzY2VuZG8gRW5hYmxlZCIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjIwMTA0MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wMS0wNCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjItMDItMDIifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI1NzkxOGJjMzM4MDM1MDM5MDBlZjE1YWU5YjJhZWYwZDU0N2JkNmY1IiwiYzQ4Yjc4Y2FlYWU3YWY2NWMxY2RhNGEzYjliOWJmYTQ2YmJjMDY1YSIsImJkZWI3ZjAxNWE2NmU0Yzg0NDhiNDE0ZmZkNDFjYTY2OWJiYTZiNGEiLCJlMmRjYWI3ODA5OTA0MDI0MDE3NmIyMmEyMGQ2YzNkOTkzNTA4YmQxIiwiNGZmODg2ZTEwN2RkZDdmMTM2Y2JiNWZjYzlkZjIzMDA2ZTJjMmQyNyIsIjY4NDlhNGY4Y2NmNzlmMTQyMjQ5N2Q3NzljZGM5MDFhODFiNjAyMjEiLCJlM2UyNmYyMmU1NWEzZWUxYTQ0OTNkN2YwMjAwOTg1ZWFmZWUyNTcyIiwiOTliMDExODE5YTliMTUzOWIyOGI4NmY2MjU1NDdmMTczZWI1ZDU3YiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI1NzkxOGJjMzM4MDM1MDM5MDBlZjE1YWU5YjJhZWYwZDU0N2JkNmY1IiwiYzQ4Yjc4Y2FlYWU3YWY2NWMxY2RhNGEzYjliOWJmYTQ2YmJjMDY1YSIsImJkZWI3ZjAxNWE2NmU0Yzg0NDhiNDE0ZmZkNDFjYTY2OWJiYTZiNGEiLCJlMmRjYWI3ODA5OTA0MDI0MDE3NmIyMmEyMGQ2YzNkOTkzNTA4YmQxIiwiNGZmODg2ZTEwN2RkZDdmMTM2Y2JiNWZjYzlkZjIzMDA2ZTJjMmQyNyIsIjY4NDlhNGY4Y2NmNzlmMTQyMjQ5N2Q3NzljZGM5MDFhODFiNjAyMjEiLCJlM2UyNmYyMmU1NWEzZWUxYTQ0OTNkN2YwMjAwOTg1ZWFmZWUyNTcyIiwiOTliMDExODE5YTliMTUzOWIyOGI4NmY2MjU1NDdmMTczZWI1ZDU3YiJdLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZdWJpS2V5IDUgU2VyaWVzIChVU0IpIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAxOTEwMTcwMDgiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhYWd1aWQiOiJhMjUzNDJjMC0zY2RjLTQ0MTQtOGU0Ni1mNDgwN2ZjYTUxMWMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImEyNTM0MmMwLTNjZGMtNDQxNC04ZTQ2LWY0ODA3ZmNhNTExYyIsImRlc2NyaXB0aW9uIjoiWXViaUtleSA1IFNlcmllcyB3aXRoIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjk0NzMsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMzg0cjFfZWNkc2Ffc2hhMzg0X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiJhMjUzNDJjMDNjZGM0NDE0OGU0NmY0ODA3ZmNhNTExYyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDk2LCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MzI5NDczLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6MTAwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTA1LTAxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wNS0wMSJ9LHsiYWFndWlkIjoiMjBmMGJlOTgtOWFmOS05ODZhLTRiNDItOGVjYTRhY2IyOGU0IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIyMGYwYmU5OC05YWY5LTk4NmEtNGI0Mi04ZWNhNGFjYjI4ZTQiLCJkZXNjcmlwdGlvbiI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPMiBGaW5nZXJwcmludCBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjAsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDU0RDQ0FlMmdBd0lCQWdJSkFNOVJ6WXU0RUlJbE1Bb0dDQ3FHU000OUJBTUNNSDh4Q3pBSkJnTlZCQVlUQWtOT01Td3dLZ1lEVlFRS0RDTkZlR05sYkhObFkzVWdSR0YwWVNCVVpXTm9ibTlzYjJkNUlFTnZMaXdnVEhSa0xqRWVNQndHQTFVRUN3d1ZSWGhqWld4elpXTjFJRVpwWkc4Z1UyVnlkbVZ5TVNJd0lBWURWUVFEREJsRmVHTmxiSE5sWTNVZ1JtbGtieUJTYjI5MElFTkJJREF5TUNBWERURTVNVEF5TXpBNU5UQTBNMW9ZRHpJd05Ua3hNREV6TURrMU1EUXpXakIvTVFzd0NRWURWUVFHRXdKRFRqRXNNQ29HQTFVRUNnd2pSWGhqWld4elpXTjFJRVJoZEdFZ1ZHVmphRzV2Ykc5bmVTQkRieTRzSUV4MFpDNHhIakFjQmdOVkJBc01GVVY0WTJWc2MyVmpkU0JHYVdSdklGTmxjblpsY2pFaU1DQUdBMVVFQXd3WlJYaGpaV3h6WldOMUlFWnBaRzhnVW05dmRDQkRRU0F3TWpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkhscTJqVVFNYWxIai9CUmVRZWZHaXo0RXZZSnlGTFdQejRSZmhKR0txcWwrOG45NmhUMW01Z1hvVHZvTHJqU1U3WDBjQmVvVHNnaHloMjIreXJzNCtTalVEQk9NQjBHQTFVZERnUVdCQlErOFNHVzJCWGJxYjJkY0FPaVdKT1UrR0NzUGpBZkJnTlZIU01FR0RBV2dCUSs4U0dXMkJYYnFiMmRjQU9pV0pPVStHQ3NQakFNQmdOVkhSTUVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRRHE4eElXMFpLNXl6M0VBem11eDg4TENUWU8xNTdmVGZ5T2lPekMyQUR5YXdJaEFPMVBXWWxlRmdILzNtdUQ4Y0JBTXIxMWZFS2RGL0FhQzE2ZnR4YWV6TlhIIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUl3QUFBQVlDQVlBQUFBb054VnJBQUFBQ1hCSVdYTUFBQjdDQUFBZXdnRnUwSFUrQUFBRklHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORElnTnprdU1UWXdPVEkwTENBeU1ERTNMekEzTHpFekxUQXhPakEyT2pNNUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdLRmRwYm1SdmQzTXBJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4T0Mwd05TMHlNMVF4TkRvME1EbzFOU3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2UTI5c2IzSk5iMlJsUFNJeklpQndhRzkwYjNOb2IzQTZTVU5EVUhKdlptbHNaVDBpYzFKSFFpQkpSVU0yTVRrMk5pMHlMakVpSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKaFpHOWlaVHBrYjJOcFpEcHdhRzkwYjNOb2IzQTZaV014WlRnM01qRXROek0zWVMwd05UUmxMV0V6WVRrdE5URmtNVE16TkRabFpUSTVJaUI0YlhCTlRUcFBjbWxuYVc1aGJFUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJajRnUEhodGNFMU5Pa2hwYzNSdmNuaytJRHh5WkdZNlUyVnhQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaVkzSmxZWFJsWkNJZ2MzUkZkblE2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRveU1UZzFaakppWmkwNE5XWTVMV05tTkRjdFlXSTROeTA1TVdNellqTm1NR0kzT0dVaUlITjBSWFowT25kb1pXNDlJakl3TVRndE1EVXRNak5VTVRRNk5EQTZOVFVyTURnNk1EQWlJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBb1YybHVaRzkzY3lraUx6NGdQQzl5WkdZNlUyVnhQaUE4TDNodGNFMU5Pa2hwYzNSdmNuaytJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCsvMFZ4UlFBQUdmVkpSRUZVYUFYVndYZmNuM1Y5Ny9IWDUvdjlYdGR2M0RzN0pKQUlBVUxZQlptQ2ltRFZEbGZ0dzIzSHFZdXFQVjBXdGRiV1I2M25WRzJybnJhT3RzaERyUlVmUFIzV1dTM0tWaEFaWVFvRVFrTFduZHp6TjY3cituN2U1MDRpS05XTzg1OCtuMm51aXNTL0ozRzhZWmVaMlpURUltRDg1K1JPTzBaU1VmaUhKUDZGSHlJRVdCakF3ek53Nm9iSTNDeWtDR2FHSk55aExNV3dnbnJvcE5KSUNCTlVjb29pME84Yit4ZkY2UExBcUlNY0dvZDJXK3pZRDlGZzQ5ckFnYjFpMFRKVEhXR0N1bzZVaGVFSmRpOW1WclNOOGNLWXE0MmQrOFNLQ1NPMmdBd2RJQlFRVFB4N1psRFZka2tXYnpUWmNLVEkzZGh2dnJHbHVlTTlkOFVUWDBScitqbW95WUNRT01Tc0JMcEFBakxRUnhwZ3hvK1JBbWxyNG9jSVpoZUdrRjVsQnBMNHJ3aElDWExEZkgrZ0R4ZUZrSGdDQ2VTd2Y3OGhFei9Lak1QRUQ1SWdSWHVSdWYyMHBZQlpRNzJmN1N0R0gzWW1UdnhGTWhjZ0F3bGlBUkxnR1d3R05BZldRcXdtaHNoQmNuNHNHT0ErbDhxQ3h4bVFCVTNEU1pJajhWOFRZRkMwallVRmJlMzFkUDJ5NVpBelR4QVM1TVpBZ1BHanpRQkIxWUR4QTlaWjBLa21jRUhJbWM5M0x2aTNIZkhJa3FaZWpUSWdNRUFPN2w4bnhrOGgzWUxuM1lRMGp1c00xTHlPRU01RTRzZUNnT3ovbFBZY0VJOXhRVHR4eEhnM251a1lJTDVyRWRnT0NDajRmZ1lTc1I1cVJhZWpxMEppdXFwNGdoUU5MdzFWNHNlRkFLOUZNcjVIUUxUalFneWJNY2lOZzdIbjFwV1hmT09oNnNTTDhQa2pNUWRMWUdHYXdkN2ZKWFl2UjBXZkVNQUMxQldFNGxaNkMvOU1tZjZPY3VUcFNJRDRrV1VHMG03RXZlbTJiYzVqaG8xWU94bVBPbk1UcDJhSjdJQ0JpWThKL1Q3UUFrWUFjWkFBUThFb2MwTzJ5TGJSVVVNQ001Q01kaHYyelRsa0kvSmpSR0FSUWhISWpYaU1HY2RLR25lTTBqS0lPeDZwVisvTFp1Y2o3eEFNU1B2bzZ4VjQ5UVhTT016Tnc4Z0VkRm93TXdNalk1RFNYcHJtclJUNkI0eFZpQjlkRWt0dUpOcU90SGMrOEpqK0VEcGQyeFRhakdnQUdlTWdkLzluWUU4STRJSVFRQ3dKZ0lNTFhCQU5tZ3lTa1IySzROejlJRHc2THpZZkxRcmp4NFlaTkRYMGVrNTNMQ0J4U0FwMmpwbGhnaFkxc3paeDAxWE5CWE1FdGhBcVFCVzk1aDAwNlF2RUVhaEp0TXVYVU1RWDBGUlgwMnA5aENMTm93Q2Vyc2Y4UHJCVi9LZkVZY1ovbnpqTStBSHVFQUwvSVRsZ1lNWmhCcTZiRVF2cFNVZEdIbFBWeEJWamRvNnk0UklnRU5zRU82SkJscEVDVkxVVGdoRkxRVFljSXlNS1FaTWhHMVFORktYNDVqMWlZdEpvSlVPVitDRU1HQUVDTUErSS93OENYR0NBTzFqa3Y4MVlJc2dPRW9lSXd5eEFYWW01L2M2cWxZWm5hREpINWN6SmhJQk1tT0FoMy9qbGdYVldRejZSWURBWVhzdEMvUmQwbGtNNUF2STNVSFRmUndCcWZ4NGpvMXVCTDJJUjZnRFpHMElBQk80UUkyRGdEaVlPc1FSeWtJTVpQMGpnR1VMaWNSWUFnUXZNT0VRQ015aGE0Qm5rUElFRUZxQm9RYTdBSFVJRUJEbmZpY2pwcEVseGlJREltczZZblprYmFESllNRHo3M2NnZm1Xa0NSWUxKQ1AwK1dBQUtIbWVBWkVnUUFnVGprTkUycEFnU2h3aklBb3pqZ1o5Qk9rK3d6c0JjN0FPK2d2aWt4S1A4SndTNEdERzRLRVhPRXF6cXRQQUEzekhqQzRLdC9CY0V5NEp4OFdpYk0ySmtLb29hZUFENEN1TGJHQlFseEJFalprR2Y5WFZ0bTRoZ0NJelp2K1hGRHowWU5wNk5MYXhFRG1YbnMweVpFeW9vMHhuSS9vaWNvYWtoUk1CZWczd1RVa24yMVJnbkU4UWhyUTRvZzJjSGJRZjI0cXdpMkhxU0JScUJBRE1lNXc2cGdNNFlESHFRR3pDRGtDQVZNT3lCSEN3QUFnR3hBRGw0Qm9zY1pxQU1DR0lMd2poVVBhRnN3QTZDN21GSm1ubFVIT1FaV2wxV2o0eXlSVUVna0J0bHlUMnRxQU43NTRXNXNXUkNjS3JnRExEamdPVUdDb0dkR0xjQy95cDRoQjlHRU9DWXFYWjRiVzdzUmRGMEZHYUdJQU1wUXNDZVpZRmZNN04zQ1A3YVFId2ZBVG1yUlBaTHJjaXZZR3lXV1ZlQ3RaTWdsNXJLM3BTaVBvYnpoOENBN3lNZ2kxR1pYZXB1cjR6R3BnMnJZbG5YQWplVWhEc1BXZVRQTGZMSDFVRGFmbSttTG95UnR2M0VaTmNtcXl4YU5DQnV2VDZldXdQeE10UnY0K3JSRzl4SU11ZzBNTlFCTE54UGEyUUx1WUZxQU1UbkE4L25vQ0lBeGlFaGd1Y0RMUFkrVGpQNEV1Tmo5K0RXSjRSQU5YTTZkTi9DeUxLeldKd0ZieUJFUUJCTFVJREZtUWR4WFVjcTdzVENnR0gvS1Bweno2QXplaElHTkEya05uamV3ZmJiUHNyWTZ2dG9UejRmYTE2SUJjZ1pXaU9RNjBmWWZ2K0htRmh4QjkzUm44UHp5M0RkanJHZEphbTdNWENRQkVYa0REUEdjZ1VXd1hBR2ZWMWZXMEJ1YXkzeTg3Zzl2OTIyRXcxYklUY3dnU0FGUThKajRINlpYVkZMSHdCbStTNEhBcng0OVRKN1I5a0t4dzhXd1FLUGs2QnNRUUdXemRZWG8vR2pkWk9qTWg4MkRwTWdKanRwOVVUODM5MWtGK2VHb2tqQ0piSU1seEJZcm5Wa3UydHZNdzlIbXZKckJRT1dPRkFFVGxuVkRoOXNXYmlnY2NOTTFCbkVraUFra0xFaEJIdDNHV3dWbWQrOGQ1dnp4ZS9FOU15ejdjeUx6NGZxRVNpVjJWbHMrUHllWW0yUFBrL0ZNc2dIRFBveldJQ3FnbTduQVR5L2dOazlyNkVvbjBkNzlFazBGWWNJQ0FIRUVvRVB2OHFqRDd5VFZjZGR3OFI0UXpXQUxCQmcrV0ZtRnIvS2JITUZVK1h6Q0FteWd3VW8weDcyUGZTWFBIRG4zN0xsS1E5aDFpZEV3R0ZtMXlvNng3eVZzdnRHNmhrd29EUDZOaFptTG1mWnhoWXBYWXpYSUFHQ2FDQzlpMTc5RnpUWFFUcmhRc3BONEl2ZkF1WlprcnBkY1pDZ0UyVm5lelpjSW1LME9ueDFkdGIrTGplNmVOVUsrMkRDanE5ZGhCQzA1QURTaUFYS1ZqU2FSalFpeEdESGdyM1Q0Rm5BcjBwODJ3V2R5RnRiSStHM1RUYmV1QkFRZ0JBTjVQTWpMVDUzeDRPNmV0c0MrODQvd2RaT1lpOXRpTzh5eTdjaTNjaEI0dHhXeXo0UzRjUWlRT2c2dlI1N1RGeVZnanlZWFNSWTFRQU9kR0o4cWFSckpQdG9VM1BRdVNuWUZhUFJObVdEakREWVdkVit2Um5aNEd3ejIyQkFOWlNWbmZpcW80N2xzNVBPVmZQTGJPMktVZHRNWDJBR0JRdzZFOWMwZCsxZHhkcmpOdEZPb0RoQ1ovOTU3SGhnSzBlZkM2RUc1eDRHaTc5T1NoOGdwS2NSL2Rjb3U2ZlFuNGZza0NKUS96M1ViMkJxelU2YVBvd3NPNWJoNEFKY3UvRG1xN1FuQnZTWlovdld0ek4yN0dsMEp6Y3lXQVRaOVZSemI2YmR2b2JONTRxaUJXcWdHb0lpdEVmM3NPZkFteGkzU0xkOUtWVi9GNjN1VnpqNkxJakZPbFJkZ0FVUUVBTU1xM3ZKZGhWcjFrSnVMY01tbjRvcW9MNFpQSU9SR0hDSUdWTkVUaEpnQnRuOXk4TUJyeDhkczdjRmhYZDJvaGcyZm1QTytuU1EzUXkyRDlOa1U5a3BpNDIvb0d5Rmk4cElrQXR2eE1TWW5SK0srQWtMell0RzIzWkJ1d3h2eXoyMTYwYVlRWkZBVVBWNy9xbWlzRDluVkxmMSt2U25lNDRzUU5ZVmplenRwZkhVUm40VHNNNHN2TS9FaVNIQlRGLzloVVg3MDdLdGo0NjAySVhJTjl6VmJKNGFpKy9mY25TNHNCcUl4bFcwWTN6ZHZnVSt1bTNhanpqdEtQNE1iRk10a0duT3M3ODNoUERKRU94UlNSZ2NpWGdieGtzRmxxS3RhS2Y0d3Y1UVY1MTZySjYweWptaDJtOVlFSlRzZm85ZS84aDlCemFld1JIelU0UUNGRnFFOEFhOHVvbWl1SVdtRDU2aExNRGlnN1JISHVTV2E3L0VzUDlSVG5uNnM0Z0dpL1cxeU41SUhPeWtNN0dNaFlVM3M3ajRVc1JxaWxBZ1BrNk92MDY3M3N0UjYyOG5oeHZJMmtoMy9DYm1GMStMdUkzeE5lRGg2VlQ5VnlHT1JQbG1HdjlUSmxidHhJRDU0Vi9TYWo4WGZDZHpleGV4TnRUVldVVGZnQm1ZUVREb0RYZlEwelltV3BBMm5vUDdDZmhnSHlIZmpvbURrampNeFBwQU9BNER6OXdnOFg3VityMlJUbno1WXEwSGRzL2xQeHdwN1RQQm1PTzdna0hsWEh2M3cvNnhpU24vK1ZNMnBiZFhzL1lrajJJNEVLRUtXNTU2VXZIbG1KaW9lbW9yYzBnclFRT1BIaGo2VzJuc2I4cUN4OFVJTVJpNDl0ZFpmMUFVWERCV3BvbUZTcjlsRnM0SkNBdk03WnIxUy92emZIekRlc01NRURSdXQ4NzNtcmNvcC9jRVdCOER6WFJQOTMvcU9pL09Qem45YW12VW5yd3dDNWdlOHRwZkJYeU5KN29iOUR1WW5XallhWjdGWXJaTk1jTksySktDalZkbWRCbkFnQnNmMGhIYjJMTHVkYVFESTFRVnlLQ3o2bVNPbWZvazduK00vRXQ0L1FpdFVlaU9nemNnN1dEWSt6MXlQb21pWEU5amY0aHBCNmIxcEhnNTR5dWZ3WEFBWmhBTlhDK25hbTRsOEI2NjQ5QktCOGdMTU5kN0o1VnVvNHFSRWJ1TXdjSnZZMkVNaTFDTVhvU3FEdGhseEFBZHpkSTBleWs3MzJJNG5PT3V1Mkg5NnROWnRUd3hyQ0FZeEFRTCsyL0NyTS9vYXVoVlQ2WlZkSmh1cnFldEEzUWlPS1FVamU4NnhZd3B3VTdIcjIwbmUwdjJkRzQvNit2dS9pcGdHOTlsZ0ZoaUhOSTR2VWE2SFBkdjdodndpYkZPT0RVQnVSSGpJeHlSSGVvR2drRU1zR3RHMzg3QjMxaDI3R29KRU9EUWJVTzNNdTdkbmxuWkVXWEJWTHNkTzVZNVhoNWVvQ2lLQ0ROeitVUFQrL3pqclpTUXdJQTZ3OXBKWnpEMGF3ZnorZWVTYVN3bWNwWFpOVFZxcDY5WlliOGlCOCtPUjk2ZFV2eGFNRVlsR1dCTFdKS0JBM0o5MjR6VFdPS29YRFNuSzl1WUpBUUVnd1BONk5XN2UydWd6ZG1RUVN3UjRORHViTWI5cjhqRlZxSStBZllab3QrSCtuRDBhU3o1QnNxMzBCdnNndkFObWozZ2ZoUmgrVFNodVJKNUJZaUdBaGdoNkI2S0JBYXNXSDQ2WDcveWMxanJLK3g3QURZKzgrWEUrQWNJd3dSaVNZWjIrVXRJWjFBM014UmhBbWt6bG42ZmJkc2FSSWVpT0pXRERKQkR3NEQyMkxjWTltQjJEa0o2TXJSZ3FuTXpUWDJBYkJ5VWtGalN3dXgwQ1F5ZmptN1BEZU5oMDZEVUYxcDl2WnpHcHVXQVFBWVpNTUFNM0NFQTNUWlFzSFd1MXMvVU1mL1ZVZDF3U2IrR1FRMEdtRUdJUUFwZmYzUi9mdTNLRmR6bEFqTlFnR1lJSjIyQVpwdjQwT2Zod2pNRHp6M2RMdDI1eCtSbzQrcmx0aXdQSVhTNHAxM3lKMVB6UnJzRnFRVjFBd1owUzJNNEJFazdESkZsckJpTnhZdlA1NFZrVml6T2laQnNFZW1uZ0xNRTQ0RDRuaG9vRE03aUlBT0R4V2dVMFRoSkF0d2d3WmZqSlhkc0RTZTJDUGtJVkFNQk1CRFFERGtrZFU3RXV1K2lIcndhZUFtVG96Zmd3R0lGcUlmNEJLVlAweDlDNWpxOHVZNVE4RDNHSWNwUWxOQ2RXTW5ldmN2NDlyYyt5ckxPSWl2WHJtQ3l1SXpLRFJOZ1BLN0pYZUJjek1BZHNQc3h1NDJOUjRINzhaVGhGT29LTUVEZzdHQjBmQ3NSMkx2L0JJNVl0eGtMOEowYnI2TzNQeE1MRGtwa0RwcWswT2tnWXJDanJXTWo5KzNSVGRNTGV2VTRUSzhlZzdJRmJwQU5oQWhCV0FObWNNUnlZNlNBL29MWXZNeTMxemxlMld1NGhDWEdZV1pRTmY3My9ZcEx5NVoybFFGS2pOQUNCZWhWMENtRUFBZGl5WG5kYm5ycDF1bm1qOHBSemw3ZnNuYmR3TTU1djNyZGx2RG95UnNNR2pIWUFUUFQwRXF3Y3NLd0VGRXczQ0NIUUlUVjBleWlXdUFHRVViS0VIN2FBUW5NREFRT0dHQXNDWVlBQTVSOWF5Zlk2UWw3dW1TVTdScm1lSEI3L2FUYkIxUGQ1NUI3RzNETFlMczVyQTAyQVVUVWdBdFNzWkhzTDJiUGdSdG9IQ3h2QUZ0RHNLMFlNSGxjQzA4cnlMMkU2aHFMNHFBUXVyZ21pVVhCc1A4d3ZkWXJxUGJNc243bDFaejZIRmkyNWtKeTNzaGdIa0xnQ1F3UUlDQVZzREI3TGIzZWJsYXRoUkJQWVhiZkNnNnlDRlpBLzVFN0dlNituZEZUWU0yRzB4bHJIME52NWdCWC9lTzlQSHczZEVZNUtDbHcwTEdCY0NvWW9KRk9TK3pjbVQrOVk1ZTJyMTVoZER2RzJuRmpVSUVCQnBoZ1VJdDJhUnk1eXJoOXU1anRpUlBXOFJ5djdIZmRqSUI0VEREREczdjR6bDNEZld1bmpORldvaDJNSmtMdEVJRUE5SVl3VmpLKzZhajRmK2dxbkxaSk4yWEYxd3ptaFJWVURObmFUQU1tNmdYUnpCbXQwcEE3VlEycmxoYzBibVFYTVFuUHJPa05PYzZDaUlZSFdCQ3FCTWtNWTRtRXhZQWxvMTlsOVRtczdXYlQ5ZEEvVnJUdDlCaXRXMVhRc1F5SjY2NVpQSFVIenM5aWd4THhCb3lyZ1FJNEh2UUJ6S1p3UVZtQTVEeTg2eVlxd2ZJV2RPSUZNSElDc2QwRFFUVlloelZYZ0UxQm1BVnp6RWFBSTRFYVl6L1lES2s2RnpwWGNNSFBQa3puS0NDdHA5b2ZlWnlBd0NGeWlBa0NtZXlSMUxxZFhQV1kyUU5tSjVES2hEdFlnUGJZa01YWi80dEZpQ3VBQXo5Qk00UisvMFkybjdPTGRjZEJLamtveVFCak05QTFSQmJVaXl5dW43QzdqbDRMVDFwanpDN0FZQWhtUEVFd2tLQnFJRHNFQzc4STlxYzFqRWVFK0I1MzBXbUZYMTQybXU2cWMvNndBeGx3QVFZSXFneGpIVmE4OHFKd3hVbXJ3bW1QUGx5L2Vxb2REeVN6NVhValltM0ZpcmFXeis0V1FTS1pFVnFnaXNNRVRhT09qR3lvYUhmRmNORkdsQmtMTERFTGcreC9IY3cvVWdRN0tyc2lRZzRxWkhtMjBlNlcyWnh4U0xkcHZKMmQrd3JzOVRsRExBMEdrVVUxZHpRVHU2RGlHSkxOWTN3V3RBME1wUHVCUzhIT0JZRUU4NHQvUXRINk9LdVhRZjlSOFBaVGFZK3NZdmIrQllZek1QS2tmUlRsUG1JOEh4ek1RQWIxNE1zRXU1SlEzSUw3eTRpRDgwaGpzN2hWVE84QjkxdG90MnBTVE1oQUJqU1EvWE1VNVZmQmQ3TTQyRUlJbDdGbTVSeWpKWHppejZDdXR2UGNOMlI2L1VUVGg4WDlINmZWK1J1cUdhQS9UcTUrZ2w0RnFmVU5Mdno1L2FRQ0pBNUtKbG9XN0dRelF4SW1ZK2o2MW9ZanVOYk4yRGNMR0ppQmVKd0JKVEIwUVFyVzNiREMvcUFzd3B1R3RTWE1PY2pFZmhrZG9DUEFYV1BITEV2dm5lOWpjajVpQWVlN2hLaHFlOGJ4YThMN1d1dmlLZmZkblIvKzVqMzYwbk9lVHBoTWlneEFZSlY0YW94V0ZvVEtsVUVHQm5JSTBYN1pqSmNIVkFtYjJEL2pmemJSc3U4b1dkK3p1c2tnaS9ZZys1MmpJZDZKR1dZUWdleUJQWlhPM2RBTkZ3ZlJkVEVtK1R0YXBSOFJ6SjZSM2VoMHdmWTNmR2JmZWJkZGMrekxWbEZySTRPcURXcUR3QUtnQThCYndmOG5LUVZDNjFOVU01OWgxU1MwT3RBZnZaaWk5UUpNc0xodEdja2dObk5RL2pMS2QwQThoNUFYcVB0L0Q5MVBFRk9tR1hZSmNSbGlpVGFqWmdyM2FiSmRoL1JPeEcraFBFV0ljeWk4SDVwM0kxK2ticUEvL0IzV3JvVTdiempBby9mRDFCR3c3YlpQTTZ5T3BDak9vYW4rbGY3c0IybFBRUVI2dTA5Z1pPUmtIREQ3SnRVUXFpR1BTUmFZREdaUEZvY1p3a3lyK3hXL0dRd3JqRUk4cmhXTVpZS1Z3T2RkZk1oZDU4VEMzcmxxTXB4ZnUyZ2FVUVNqY3QwV3NGY1gwaXVhYUpmS1JSYTBJcU5sTjM1ZzZQNnpMbjBPN0NHRG84R2VFWU05blJERzZMblB6dWMzYlp6aW9lWkFYcWJ4c0sxVmhPWERTcGpaQmFYQ1I4ejBCb2M1bHJpelBKcTl2U3p0MGlvVE95MWpVR24yMFdtL3U3M0J0cmZhM0QrWXRaT3pZRFRaYTNwVm1CczI5cnV0a3NyTWtCaFBRYis0dmgxK1R6QmxCbG02eTR5M0oyT0YwQmFMUnIyWVNTVjNQYmpxS1YrYm1WdjNVOFRla1pnRDhkbTQzMDNPRUFPWS9SdVI2Mm0xQ3RBODFYNElVOUJVbXlsYjc4ZktaZVErTEgveVpSVERXNm1iL2VEVGlMZVQycU1NRm9iTTd4NnkraFRJZmpUVy96Z3huWXNERmk2aUdaNkM2ZDlvcFl6eHh6UzZpbVp3QkdPajkxT0gyL0RnWklkVytmc1U2ZTIwT3JEbm9ST3BkU1duUGczV2JOcEh0cmV4c0RCQ3F6WEh5Q1EwRGlIQi9QUkd4aVpYWVBWZWN2TVFNcjVmR2huVitvVjVPeTFFRG5GQTJIR2x3bHVpQWNaaHhpRXU3VFhaZlVMSGhFS1hFM2hhNWF5aWhtaEdBOVJaLytUR2I3am43OGo5RVN4ZUhDd2NEMktZUlRBcmtvWG51UGpKQUgyRHRvS2xnaVV5V1BSTEp6djZoMWdFRnFmWi84aDIvYzBKeDNOcVVaSnlBMlo2aGRBV0kveXJSTGRUOEV6SE5zdWcwektpYVdlS2VnbkdMUU1wRE9hNWNpVFl5YlVMaTJiZE12NUduWFdoWVZlRHVtWjJ0c3hPRzQxSzJhR1czU0RwSlJZMElOaDVZQWdEQndMM3JJcjdGcWs0RFV0Z0JqRyttZXgzSW4wUk04aUNmak5nY0dEQTdDT1FhNUM5aUZpOEQxdFlqOWNnUVdmaUV1cnA5K0xWSDVIQ3ZaZzUrQno5UGl6MGw3R09YNEQ4RmhwYmpzUWhSaUlXNzZZWi9nSXAzb1hVWU0zMXBCTG01MkZRUVh0cVBhM3d2NUMvRkRPWW1ZYlRudjNieFBZT2Vnc2ZZZDJ4TUt3eWcycWVsajJiT2grTDZ5OW90MFJhZlJHNUJ1VnY0SG9ZeFBkTHV3OXczbmhiSFhjd1FJSWlRcEZnV0FsM3NNQVE4WWpnOWliN3JrUVlpWVU5SDdOMUxoRUVqWERROVl0RGYzODBQdE5xQmM5QUkrMEkyWDhwcFhDNXNHTWRJUWx4U0JTTUdsQ1lNV2cwYmRhOHZvVSs3ZG53REowSWV3N29ZMnNhZjlycWtmaHp2VmtubTh6Z3pHRGhUQUVSRVlOUlpkRWZhdXRZbDFlbnhIV0d5QWZjTGR0Znh6RjdWdG0yOC9wOXNTU21aT2U0Y3c0WUJ6bEdQd3QzLzVjUXdwc3d0ZzFySm1JUm5obUNnYUFUS21ZMGRkdm45VHdvT1F2bU9VUmFUUXlYSS84WThGVmNEekIwR002dll6ZzRoYlhIUDVNbVA1TzhXQklUaDVoQk5ROTBmb0d5ZlNHZXZ3aTJDMjlFZC94SXl2WUZEQmVQQmtwQ0FuR1laN0I0Rm1YN004RGxvT3N3N1NhbWtybitNWGo5RkxycGVlREgwVGlZZ1dkb2pYYW82L2NTZURiRDNxMWtiMmlYeCtQMlhGS01pSjhtMkRpeFBBMDE0TnhNdGxtTUowamI5dG5aWnh4bkRPZmtCQlFDdzJHamhjVkswMld5bmdWbHllWXhUSEJjQ3VFQ0M0eldXVm5pM21TNnJ3amNPWmU1dnNxNk9zcjJTZUl4QnBpNGJ1RDV4UUc3TEptOTBNRlNNQ1J3aVNMU202bjFqd3VWM3J1eXhjMHNrVVJyTXREcEdpZE1zWkNDL2FxeXp3cTlNa1VyekkxR0FveGEwRTdhNDVXdTdBLzFKMlBkY0Q4Q0JLcEV1OVNPbk1QTDk4M3o1eE50UFNzUkdHWW9Ba2pnRWdtL1o5OVFIeTRqbDNlRDdSOVVqbUFDT0JXSlE4VGlQbHYrMmZ0MTNCYkU2WVFhQ0RYdWh0a2FpdUxOb05lUXduNUdDcU5ZUHNteUk4YUlSYUx1UTY0YlFpRVFoeGxnRWV4b1RLL2pvSnloMVlHUlNSak1DMUVUQWsra1FFeGJVSDRYaEJrSXM3aEtwcFl2dzJ3RXIxbmltRFdBRVNJTWVtQTJTb3pQUi81OFlvUUV1QUNEWUpjZ0IzT1dPSEFkUWZ4N2FmUHE4TUZxVVovRWFFQUt3Ulo3ZmVZWEt5MGV1ZEt5R3BzYVZrekdTTnRnQk9USXBwdEdNMkFMS1hFQW1IZlJ1S0JnaWZGRUJsbjZsc1Ava091S1lQYVVvZXVvRUd3WXBIdnF4cjllSzl6a01EUytUelNzTURvSkF1ejJyRGNPaC9udktzVm5XTkR4TFFpWXB0MTFpekpmazdUVnpES1BNU0FBQmlIdzRONDV2ZVRoUGY2VFc5YnlsTEpndzZEQ3pOaVpUTmVZK0hxV0hoTEc5RUpOM1lpVTdNQklhYThSZ1NBbEVvdGZxSjkxODEzOTQxZlE3YitTUU1aVkFZWmttTFdSdWhodHlnUWgxQmlMVklzRGpFeElnUE5FRFFnREVwQUlCcmx1eUUyRG1UQ1dpQitnSmdBZGpCSE1FcEtJY1FqMGFPb2haZzRZanpHV3lKQWlVQ0FIVVFNTkIwa1JjRVFiYkJhNGlSL2kvd0gzRDVQTXBkMnQ1UUFBQUFCSlJVNUVya0pnZ2c9PSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfSx7ImlkIjoiY3JlZFByb3RlY3QiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImFhZ3VpZCI6IjIwZjBiZTk4LTlhZjktOTg2YS00YjQyLThlY2E0YWNiMjhlNCJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wOC0wMyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiZVNlY3UgRklETzLCriBGaW5nZXJwcmludCBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MDcwODAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4xLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wOC0wMyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDgtMDMifSx7ImFhZ3VpZCI6ImNhNGNmZjFiLTVhODEtNDQwNC04MTk0LTU5YWFiY2YxNjYwYiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiY2E0Y2ZmMWItNWE4MS00NDA0LTgxOTQtNTlhYWJjZjE2NjBiIiwiZGVzY3JpcHRpb24iOiJJRFByaW1lIDM5MzAgRklETyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDNlRDQ0FkR2dBd0lCQWdJSkFKYlR5cnUxWC9JUE1BMEdDU3FHU0liM0RRRUJDd1VBTUNNeElUQWZCZ05WQkFNTUdFZGxiV0ZzZEc4Z1RYVnNkR2xCY0hBZ1JrbEVUeUJEUVRBZUZ3MHhPREEyTVRJeE5EUTFOVEJhRncweU9EQTJNRGt4TkRRMU5UQmFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNVmpLSFdwYkQ3VFNsTXhvY2pUbDZuSWY3eDMyUG1zUTl6R3VMR0dxQTBVUVpvSXEzWEx6TDZMWVV2SjVBNWcwdXlGR2xsSEVmR0FLckVhQ1E4RlZ2UFMvVWgwRnlmeldoUkF6aVRTaWpqTUlJVmpqalV2OW05dkZtY1hTY2dIaWc3T2R6ODg1OFYwa3JOSDk5cUdtM3dqZ2FPZXJUV210K2pYQ1VmbjAxSWtUUHd4RzJIbGdFZDQ1ak5MU1Y3Vm9vbCtLZThFMmtpNGxFa1RlSHpib3VsUjVHVWJwM25NaTdFNDdWTVFhM2JOd256V0Jic2FCU1NRaExrM201SGFLaGh4YTZ3SkRLNDdOaU1Da0NrZElIdVdTUUxWQWZtODVVQU9OdEVPUHdpME91SzNxYmU4eUtPRkdmMEtoQjVNTWVBeW03TVYvTTRXMGE0OW9nUEQ5cE1DQXdFQUFhTWdNQjR3REFZRFZSMFRCQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKV3o1eExNazVXTlliQWI2eU94RUNCb1oyV2VCL3FsNFZKM08vMy90TnN4T1luekxlV281NDB6UWg5ckFtYXh6N2V1bUJsc2tNcTR5R1BTTlhCOXljV0dIZ2tjQ2VTek4yd3Y4Q0l6REJzMm9CWmpUTms2NUxCWkRzc1RPQnRNVy8rdVRGSFFmYnVPM0lTTGhJMERYZlJFaTlORE0zamZrMTF4SGNzZmgyUk1WK1FkTmZ3VmFaWnJDcStvdUcrRXZrdjdLcXErb3l1MFZGTS90ejY4VEdsNnlsaFBGUjFxaDl3dHRwVmpBT09DRVFDTHFQMmRQMjhsd1lCeUNxSFFxVkh3YnVqdi9MWmpabktXM0xZbmRaaXhQUFNSQ0pzc0REd0p2aC9mNm5UeGc5WkUrL0pjWXJlNUNhSThuelZIYVNPQ2pOSjdGelVMRzY0SmlXT3ZRNTA9IiwiTUlJRGRUQ0NBbDJnQXdJQkFnSUpBSUNVVHZrZ3RqNUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GRXhDekFKQmdOVkJBWVRBa1pTTVF3d0NnWURWUVFLREFORVNWTXhDekFKQmdOVkJBc01Ba05UTVNjd0pRWURWUVFEREI1SFpXMWhiSFJ2SUUxMWJIUnBRWEJ3SUVaSlJFOGdVM1ZpWTJFZ1EwRXdIaGNOTWpBd056QTNNVFF6TnpFNFdoY05NekF3TnpBMU1UUXpOekU0V2pCUk1Rc3dDUVlEVlFRR0V3SkdVakVNTUFvR0ExVUVDZ3dEUkVsVE1Rc3dDUVlEVlFRTERBSkRVekVuTUNVR0ExVUVBd3dlUjJWdFlXeDBieUJOZFd4MGFVRndjQ0JHU1VSUElGTjFZbU5oSUVOQk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkFLT2VxQzUvcDBEMWlzQ1lLUUpsVlVPckI2STdETG9jdW5FL1JtOGR1R1RieXhRaHQzQ2JGVlR2M04yTHAyZmJqeGxJKzNzT1NHazMzRlRZa1RxeGNkSklySjdTc2tCY1VTTnJmS09hUVQvNktRY1A0Q203Vis2NTVUcStUV3h5eFdRaER5Z3QxNXFvUDdNdUs2YlQ5U3dwQ2pwZktoYU1TbXlRYU1vVWNSQWJMcWR6QkNhYzBoekIrWmUrZ3FKbG5XVjlVYVNJMnJGc1Z1SDRaRTBjUk8rTU9wYUxnTS9zMjQ4bkdHSHAyMmV3U1FmYm5QYUJiYjhpcXlBUCtjdTUyR0xzVXBLUkplYkUrUjYrUE1ROUpDZFdlUVpSM0RrZlNpZGt2M21jYjRqcTFpSXRhK01xS2hSbndyZlhoOTExS1dMbllBbDlFTkNoTFgwYzZTajFRSURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3SHdZRFZSMGpCQmd3Rm9BVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUZMckRoYWVnZUtIeFlqSDNFUDN2VUJLaG56TTIwNkFTeGdlWUNPMkVjOXBPbFlKYWVxRkUrc1VhbVVWL3B3akRscU5hU2dGZ3k3VHdlWWt2T21NbjRxU2NzSHF2SjN6R09BaWFmd2FoMXZVSGZDbFhSOCtheE8yaUdPVUYwSktyWjlZWWpiQWE1LzRIQ2x2N2pGUE9kTVdUT1F5bmdvaUhBczNqa3VZanBDTEZsQjRWT2kzZDF3akExcG5UZEJLa0FiN3Q4blR2dysvWGJGdmNRYTczVkg3c2p2b0JxRDNmZE1mUmN1VnE0cVVadFpUNmNHYWdUSEQ2MVR0cWg5b01DWlhjRGJSMVBHWm5OYnF5Y3NXUERJSzBucG1LMy8zbGZWOGMrWnNyeTZlMTcwbWZKTVpwN084bTZDU3o2L1ZMSyt5REpkNzg0MXdwbWVLVGY2SW5aQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVF3QUFBQWdDQVlBQUFEbmxVWnFBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFBQVpkRVZZZEZOdlpuUjNZWEpsQUhCaGFXNTBMbTVsZENBMExqQXVNakh4SUdtVkFBQUsxRWxFUVZSNFh1MWREWEFjWlJtK05PQWZLb2c2V08wUWNyZVgzTzcxUjQxb0hkU3FxREFPZzMrY1lFWEJvbFhSVEVuMjIwdGFLVGM2NG1nQnF6QmlFVVZwQmRxaXd3aHFTZElTMnVwWVNndlJ0cFRTY2tsald6SGFnanBTUmRyNHZMdHZqcnZrMjd2ZHZkMUxqbjdQekROM3QvZCs3L3QrZjgvKzc4YUswTkRhYXIycU9kWFpvcVd5SDlSMGEwRmN0NjdXZEhHVFpvalZDY1BxU2VqVzFvUXVIc095L2VCVHNEbU0vNTRaVDlqK0xXR0lnN0RmQi9zQmNEUHNmNFhmUDhYM2IydUcxWkhRelU4bVV1S2R5V1RIbTVxYWNpL2pIQUtCeWlmMGJCcitMd2FYSVBZUGtNZHFmTDhYZFdwbHMxQUEzMS9Rak93OThMOFM5YjhCWElSMituRGM2RG96bHNrMHNsbmtRTXhrUEdYTzlFSnRWbllHRjRzVXlWbmQ4VVRhZXA4YncrNkxha0JqNWl6ZGJOSlMxcnhFV255V3hnMzZFbVBkV29QUERlamY3ZUFUR01zSGFEelR1QzZoYmowTi9wWG1Bc3J1Z3MwV0xQOE51QkpqWkptV0VsY2wwOW1QSjFKbVcwdEw1K3VpSEJ1R2tYc2xqWDg3bmk0RXpWbms5QXZrc1FuNTdFU2RockI4Qk11UGpPV1AvLzRPSHNSL2U3RDhZZFRsZnRSaEZmZ2RMRzlIdTF3QWZ6cjU1akFPa2lRS2h2VmJHQjZDMC8vaSsyaU5lUng4RmdudlJmeGZhaW56U2s3TkUwaUlVUGJmNDN3V21OVE5kN0JwS0VBN0xaZkZBWTl6cDN5WlRTTURpUVZpL1UrU2c1UVlBSWZPbUcyZXdzVWpBL3JoVzdMNEJlcm1qOWgwVW9CMk9CK1RaVFc0Qi9rOE95Ry95Q2lPb1cxSVlINkg4WFB6OUxiY0t6aWxRR2hwTVp2aFp5SEd3RzNnNDJCazg1WjhvOTBHOFgwTmlTczFJdjJRR2s4S2RXc3p0NHNuSVA4UnFSOW1EUVhESWRaU2JCb1owSWwzUzJPWFpYWXBGNDhNVTE0d25LMWJlVzQxcEwzRkVRQ0psUFZXdERHMmZ1eVZyTlIzdEJUZFNqQjhZcklGb3lWdG5vMk9DekJneEROQkI2cFhLTUh3eGlEOWdLM0tjNlBja3ZCR0pSaStNY21DMFlENGZkSzRYb2g5Vy9ZVENaUmdlS052d2Noa0d0RzJlMlcrYWtzbEdMNHhtWUpCYXhscFRJK2tOUlFkbUdSM29VTUpoamY2RlF3NmNDcnpVM3RDTUxEV3VRc2QzUitBdzNLbkJRNUt5bmpoamR4T25uRGlDRVp1R2pyc1lXbE1KdHBpV1VLM0JtVC9GZkV1ZGhnNlVQZTZGZ3owYlI2ZmE2TW1uWTNrbER3aGFZakxVVTZlczI3dDBnenptN1ZnVXU5NkQ2ZmtIeENhNjJVVkdDTXE4ZzAyalJRbmltQm9SdllpYVR3bTJudGZXOXZDazdXMGRZSHMvd0oxNjNrNmVNWnVRMFc5Q3diRzlLMXNPcVdBdklVMFg1dGlEWnROYlNqQmNHRUVndEhXZHN2SjhFMm5BdVV4aWJwNWhXTTkyb0RmMnliOFgwS3gzckVORjBvd29nSG0waEpwdmphVllQakNpU0FZaWJUMWVXa3NKaWJDay9QbTVVNWljOHJ4UXBsZE1SUHA3SGxzSGhxVVlFUURKUmdoNHNVdUdIU1JEK3BJVitUSjR4SDFMRzlkakNIVGlNbFI0VmlHMkU3SFJiaEFLRkNDRVEyVVlJU0lGN3Rnb0oyejBqaE10SE9lamwyd2VRRlkvbEdaZlNuRmZEWVBCVW93b2tIQ01CZEw4N1dwQk1NWEtncUdJUzV2VHB0bmgwWFUrMDVabkFKREZBekQ2RGdkL3A2V3htSEdEZkZGTmgrSDBRYjB3YU95TW1PRStPVU5JL2NTTGxBMTZsMHcwRjY3NDdxNHBScEdjZHFhN2t1UjVVdEVINDVnRG13S2kvRFpqOC83SUVTMzRyT3plYWFZeldsVWgzb1JqSm96Uk1Hb09BRU5hMGkyZFRHR2VFcDhURkptUER2WXZHclV1MkNFUWJxaGtzT0ZCc3lsaTJXeGFzVGo2TmQxMnBzWHY1N1RDUVlsR0M0TVNUQmFXNjAzb28xZGI2cXpxVnRmWW5NNTZBcEJ3OW94b1Z3Uk1ZbEdOSzM5MVZ5aUtpakJpRVl3bWxQZExiSll0U1RhN3FIaUErdStvUVREaFNFSkJ0cHZoZFQvR0hXeHY5eld4UmkwdFBpRXRId0p4YlZzWGhXVVlFUWpHSFJ3R3VPaDBnVjVrVE9lTWkvaGhQeERDWVlMUXhDTXMxcXRWZ3p1OHJldnB5eVBqd0h3c3BWaC9TdVZXaktkQ3dTR0VveW9CQU81cDgzM29wK2VrOFdzRmRGK3dhOFNWb0xod2hBRUEzN1dUUEJiUkhUY0FleEd2SlROSGZRTU5jZjZCcytQOWVibnhmcWVQSldYMmtDWnpIZ2ZFeGpDR1FJbEdORUpCc0YrRUpFdWRzdmkxb2JpVDV5S2Y5U05ZT2pXWmpUeWZhSFJ1ZDlBSG90WXBXQTROeHFKWTFMZlROVDVLMndlaTYwZk1pQVVENEtqQmZibWo4YjY4c3RqMnc3YUQycWhmVS8weHk2WnJ6SFMycXVscFRObCt3eUl1aGNNakJVNjYxUU5tMmN1UG9QRFJZVFJCanBiUjJNQU9WOUhaek9ROTgvdy9mWXdpUEh0ZmplMGJ2MkZrL0NQZWhHTU9yc09vL0x0NjdvMVhEZ1Z1aUUvQndMeGp4S3hLT1hHMk02ZHRpMzZ3OE9SZG5HUDdUY2drRnVkQzhiVXZBNmpsa2lrTzgrVHRnMklNWFNZemZ4RENZWUxxeEFNTDdldm83N3R0bkYvLzBuWWt0Z2hFWWx4SExxYXpKMnRqRXFiczlpeVNXWG4ydjREUUFsRy9hT3NZQmpXQVRiekR5VVlMZ3dzR0xscEtMdFY2cE5KSFZaNFlITGYvbmZKQldJQ2gySGRRRVhpNmV3bE1yOGxkSjVIWXR2N2hSS00ra2M1d1VENzdHVXovMUNDNGNLQWd1SHA5R2RLWE1YbUVJeDh1MFFjWFBqWWErMHltVXdqMnV0eHFlOGlvbzRYMnZZK29RU2ovbEZobCtTUGJPWWZTakJjR0VBdzZIb0s3QTZVbmNpbzU4R21wc3RlZUIxRDc5Qlg1ZUlnNGYzRHAzT3BHT0xNbC9rZnh4Mnh6RnJmajhWWGdsSC9xTEJMc29YTi9FTUpoZ3NEQ0VZaVZmNzJkV2JwSmR3OSs4NlJpc040OWc3dWgzVmhGNFBGNlFtSi8xTHExZ0l1NGhtVkJBTVQ5dTd4NzB3SmcvVFlmVTZoTEpSZ1ZFYUZYWklIMk13L2xHQzQwS2Rneko1dG5nS2ZCNlMrbVBqLzBJd1pIUy9uSWc1R1J4c2hCZ05Ta1NqbFlpNVJBUHJ1VWxtY1ltSnkvWG5HM0hFeEs2RGlGa1pFeEJqWXlDbVVSU1hCUUR1UG9BNWJvMmJTeUw2ZFUvSUUzaXFVbmdZTm0yZ0QxN04wK0c4VnArUWZTakJjNkZNdzRycGxTZjBVRVRGTk5pOUZ6L0RNV0cvK2lFUWtIUGJtTjhTMmJadDQrYmh6ajBuNUozaUJkRnMxbC9BRTFMMnVCYU5XVE9yaUE1eVNKeUR2NzhyODFKeWVyeTZXUUFtR0MzMElSdE9jM0dsb3A4TlNQMlBVeFZObDEvVHI4cTJ4dnZ4NjhQa2lzZmduZmw4ZjZ4OTBmUVVsNG41R0dxK1l1amh5NXF6dTEzQ1JpbENDNFkxMUtSajBXa2d0Ri93bVJTVVlMdlFoR0Y0bUdBYUxZUFB5MkRnMFBkWXo5SDdzcHN5TjlReFVmQzBpWGZ5RlB0b25pMWxNR3F4Y3BDS1VZSGhqM1FrR3hDS3BXKy9tZElKQkNZWUxQUW9HdllRYTl1WGY3MWxwNjZKS2xIdDgvUXNVUiswWFRYdUFFZ3h2ckEvQm9MZnIyUWZIci9HemxlbUtLU01ZdW5rSFRTekVsTDQrc0ZhQ2dmbytCKzdXak96bjJMUXNuTmNHaUQxVVR1YlBvZG5GNXBHQXpwZ2d2dXRXQnVyNkg3dE91cmlVaTVRRlhTV0tNdC9IQk41RWF5WFVyK3c5TWNFcGp2R0s0dmZJYndWZHc4SXBsQVdOQlpTNUR2V2hONVhuNGVkb3FkOG9pRnl4MndrK2l1LzBJdWlsOUt3VFRza1Q0bWx4RHRyelJtNVhqUFVvMnBYZTZHNDlnanh2dytmQ2hOR2hjZmh3UUM5amFUTEVHOXhvR0ZlV3ZpWStVdVNtMlErY29YZHk2TllpTk93eVZQckhHQmgzSm96dVVDc2VUNW1YUWZGL2poZy94T2ZYTmQyOGdqbzBhSDNwTEFsTk5HZHRMNVlpNTV2UWdiZWo0KzZnLzlnc01xQU9IM0hhU2Z3RWJYY0R2bWVUaHZVcFRlOTZ5NFF6TTc2UW05WTBaOUZwZFBjbTZ2TnBzQXQ5c3R4cE8rdlg0RWJFMjBvVENjc0dTb25sK0IvZjZXYS9WY1Y1MGFTUHg3dE9EZUVCeGcxMHh5K2Rrb1hnZkFneEZpRGUxOUFPMzBNL3JFUU85eUxtQTRpL0JiKzNsK2Jua1BJSE40UHJVTCsxK0Z3QjIydmhveDFpZjFHODFYcGJ2QTI1WmpLK3IybHhSMjRhMWQ4UlB6RWZ1d29XY3NFV2lKTXpZaitJM3crVnRLc2hIZ0gvQVBaU25xalR6Zmk4eGg2N3VuVXVQZHJBMjhOeFlySC9BejN0STRqNStUT0xBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJjYTRjZmYxYjVhODE0NDA0ODE5NDU5YWFiY2YxNjYwYiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTA0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0wNCJ9LHsiYWFndWlkIjoiYWIzMmYwYzYtMjIzOS1hZmJiLWM0NzAtZDJlZjRlMjU0ZGI2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJhYjMyZjBjNi0yMjM5LWFmYmItYzQ3MC1kMmVmNGUyNTRkYjYiLCJkZXNjcmlwdGlvbiI6IlRFU1QgKERVTU1ZIFJFQ09SRCkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDTERDQ0FkSUNDUUN2MXZscUtlVzVlakFLQmdncWhrak9QUVFEQWpDQm5ERUxNQWtHQTFVRUJoTUNRMGd4RHpBTkJnTlZCQWdNQmtkbGJtVjJZVEVRTUE0R0ExVUVCd3dIVm1WeWMyOXBlREVQTUEwR0ExVUVDZ3dHVkU5TFJVNHlNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUk13RVFZRFZRUUREQXAwYjJ0bGJqSXVZMjl0TVNBd0hnWUpLb1pJaHZjTkFRa0JGaEZ2Wm1acFkyVkFkRzlyWlc0eUxtTnZiVEFnRncweE9UQTFNVFF3TmpVME1qRmFHQTh5TURjeU1EVXlNREEyTlRReU1Wb3dnWnd4Q3pBSkJnTlZCQVlUQWtOSU1ROHdEUVlEVlFRSURBWkhaVzVsZG1FeEVEQU9CZ05WQkFjTUIxWmxjbk52YVhneER6QU5CZ05WQkFvTUJsUlBTMFZPTWpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFVE1CRUdBMVVFQXd3S2RHOXJaVzR5TG1OdmJURWdNQjRHQ1NxR1NJYjNEUUVKQVJZUmIyWm1hV05sUUhSdmEyVnVNaTVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUamJTWmQ2MS83SGFveHlveGwzeWg2dGprM3RMNkFTQ0N1bS8ybmRxODZEUUx0K0RVNk1WNmY0LysrdXBBUGJUWlU2aldudklMb3Z0bnNSZ0NXd1VZUk1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lFaU5mTnBBTFpJSDhuMVZ5WHBGeUxJekRlWkVaT0NSaUtoNDR1bmlhQlpQQWlFQW9kYW5PbFBVRUNqR0hFZitFNGRUS2t5Q2xwTGk0SmRFSmtWSFFwSVhFSkE9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQVlBQUFCemVucjBBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBK2RKUkVGVWVOckVsMDlvWEZVVXhuLzN2dmZtanpPZG1aY21jU2FrbVV5R3FvUW9sQlFYTVYySi83RHVsTFlHRkhGUk4wSjBJUWhTVUFwMjJZMHV0QlpMc2FKWU1HaEFUVjFJTnhKcjFaS21OcVVZTTVrWWsya21NekdabWZmdnVoaEp0VUxtalE3TldiNTMzemtmM3puZmQ5NFYwNWwrZ01lQlY0Rjd1VDF4Q1RnR2pJdnBUUDlEd0Zkc1R6d3NnZU5zWHh5WFFIWWJBV1Ixd0FhQ3ZqOFJBcFRDVzkvQUxaZkJkUkdCQUZvaWpnZ0dRYWxtQU5nNjRQbXVyZXU0eFNKMllabEF1cGZvbnZzUXdTQnVjWlhxNVN1NCtYbU03bDJJVUFoYzEwOUtUMittdUwzNE96SWNvdXZZVWN4blJ6Q1N5YzMzMWFuTEZONStsNVYzVGlJVGNYVFRSUGtBSWFZei9TVWcxdWlnV3l3UzZFMlQvWG9jcmEwTmdJM3Z2c2VhblNQWTEwdDRjQThBeFE4K0l2ZmNZYlEyRXhtSk5HcEoyVDhEbW81eVhhejVCZlNOQ3JuREw3TDI1VG1VVzBWcUlTTERRL1NjUG9FNWNnQ25VQ0EvK2pMQnZ0MnRZMERvT3M3S0NnaUpub2hUKzJVV295dUZDQmdveTZHYXUwcGtZQys3Sjg4and5Rm05dTZqTm5NTnZYM25sZ3hJdnd3b3gwRkxKSkFCQTdkVUp0Q2JSdWc2ZUFxaGE0U3pBNnhQWGFENC9ta0FZdnNmdzExYmJaaFhOcVZhejBNRWc4aG9CTHhieEtNVUdpSFd2NTBFSU5pWEJ0d1dBNUFTWlZrbzJ3WXAvK1VQQ2hzdEdxMWpyVnErVXVyTkdKQ3lMRlROUWprTzB2TVE0WENkQ1NsUkd4c29QQklIbndTZzhzT1BDQUl0QkFEWXVUbDZUcjBIbWtaKzlCV2tsQWpEUUZrV1hxVks2c2diUlBZOWdMTjhnOUxaTWZUT3poYTFRRXJzWEk3STBCRG1NMDlqamh3Z2N2OGdUdUZHbmU1U21VQW1UZkwxMXdESVBmOEN6dkl5V214SGl4aHdYSlJ0a3p4NkJJQzFMeWI0NDV2em14TFRFZ21zdVhsV1RwN0NtcDJqL05ubkJQcXlMWEpDSWJEemVTTERRMlRQalFPS21jRmhxbFBUR0x1NjZ6TWdCSGdLWjJrSjVYa1lxZVRtMG1vUVBweFFLYnphT3VhaEF3Q1VQaGxqL2VJa29jemRONldvRkVqUU90b1JRdHg4MWdvVmVKVUtnVlFQc2YyUEFyQjY5bE1FQmdqZzd6VVVDTm1jcW4wTm9Wc3FFK3kvQi8zT1RwUmxVL25wRW5yYnptYjMvbjhIb0NwVmd0bE1mZVZlK1JsbmNRa1pEclhzbDZneEFGeU03cTY2RDh3djRLNnQxWGRBaThKSEpnOHRZZGJiVVNoUWM4cndxM3ZMQVB3enREWVR2YjBEWlZ1dEFTRHZDQU1RZmVSQjdqcnpNWEpIZEd0dGpZMno4dUVaak01VUt3QW9NT3JIakdTU3hLR25HdnZXY29HbEUyOWhrUHIvUnFScU5ZeDBEM3BIdSsrK09yOHRZdWNYNm4vSlBveG95MEdVa1NpMXE5ZW9YTGpvRzRBV2o2T1pKc3F4RzRwQWI5UUc1ZGhvOFJoYVBOYlVkUHNvRG1CSTRQbzIzb3l1UytDbGJRUXdxZ01Ud0JOL1hjOEhibFBoS2VCTllPTFBBUURJc1hxYnNxWktHd0FBQUFCSlJVNUVya0pnZ2c9PSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImFiMzJmMGM2MjIzOWFmYmJjNDcwZDJlZjRlMjU0ZGI2Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjk2LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0yOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMDItMjgifSx7ImFhZ3VpZCI6Ijc2MGVkYTM2LTAwYWEtNGQyOS04NTViLTQwMTJhMTgyY2RlYiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNzYwZWRhMzYtMDBhYS00ZDI5LTg1NWItNDAxMmExODJjZGViIiwiZGVzY3JpcHRpb24iOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyBQcmV2aWV3IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMyOTQ3MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9LHsibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMzg0cjFfZWNkc2Ffc2hhMzg0X3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREtqQ0NBaEtnQXdJQkFnSVVlZitWdkhrY1RRbkVEKyt3Sk0vSXh6U1VMazB3RFFZSktvWklodmNOQVFFTEJRQXdKakVrTUNJR0ExVUVBd3diV1hWaWFXTnZJREl3TWpNZ1JrbEVUeUJRY21WMmFXVjNJRU5CTUI0WERUSXpNRGt5TlRFeE16STBNVm9YRFRJME1USXpNVEV4TXpJME1Wb3dKakVrTUNJR0ExVUVBd3diV1hWaWFXTnZJREl3TWpNZ1JrbEVUeUJRY21WMmFXVjNJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvdUZNVE9LYUUwWXRleE9vaXNTeHArRWJpNUlBNGVzRVNjeDE2bHpRZHFWNi9lWjgyS3RKZU5YRXVOa0JWWkRwYzMyZ1N0dXhMQkg4bWdzb0hCRmFpMkRramZCbjVxYndSL2M1K3NubHdadmpnVkEwaHpLdzlDd0FlQXdSRDVrcld0ODgvQ1Z5Q2tNY2dMU0d3WnMvcmo3Ri9MczNFYmc3TXFMYmJRSjlDb3piYkxkSlVZSUhjUHBTWlB0b01yWmI0R3ZuaTZpVlM5VXZDS2dwcWM2TEdSbW9ZR0c0WlIzbEdKL1hRWmZ1K0dlSlc2N2lpbU1qL3lvWE93eHVjeGl2WkhGazZjUVNnd3V3aW9lTm00d3ZrODNMaFN1V2N0ZjJrQXlRY1o3a1VucE5lZStkNE1ncm1HVTRYTUZMaVRndXRhQitlOVY4ZDVKVGtVT0hpTHp0a1FJREFRQUJvMUF3VGpBZEJnTlZIUTRFRmdRVU01U0I1YkhyVitqcElPTWRKbDd1N2JjblRZOHdId1lEVlIwakJCZ3dGb0FVTTVTQjViSHJWK2pwSU9NZEpsN3U3YmNuVFk4d0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQ293UjNLVExmaWRKeVFGTnFFRmZVcmZaOWFhOWVncE9RdE5SSmRMU3RKNnh1MldmTHd2RzRvakdKbEJLTm5mYTVESWN5UVlmLzhxSjRlbGlBVmVOWHVZbWVNbWdOZ1paeXVZNkcxeVdDRDJWM3NENlo0dWozU2JhRE9IajNnSHZzemdRaHJoVDFoL3B1SFFrbjYraFlLQXA3N2tNN0ljNkFaL1JGYmpwbUxMazJEMHNFMWx6VC8wMmkrQmg3TThzbWFpRFo5KytKR3p4ZVN1bjhXMUhsZVpVbTJxS0dtUmE0WFBkcnlUN3g2S0dVR25VNGEzYnBVbVZlWTlyUS9zZk1kNVpUb28rM3VuRldEem9WVjJ2TnU4KytWTEM5em80MEZhS1FMcjlWQUpESjR5TEVOUjdLcm1WOEwwY0NYS0pHWldBV3RHNVJHVG1ISWhkK25CNDFnPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJjcmVkQmxvYiIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI3NjBlZGEzNjAwYWE0ZDI5ODU1YjQwMTJhMTgyY2RlYiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotMzV9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDk2LCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MzI5NDcyLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxLCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6MTAwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTA0LTA3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wNC0wNyJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImE5N2IzMzE5ZWVjZGI1OTkzYzQxODQyNzY0NDFiMDU5YjQ4NTA2ZjEiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYTk3YjMzMTllZWNkYjU5OTNjNDE4NDI3NjQ0MWIwNTliNDg1MDZmMSJdLCJkZXNjcmlwdGlvbiI6IlRydXN0S2V5IEczMTAgVTJGIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MjU2LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ2dqQ0NBaWlnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQm5URUxNQWtHQTFVRUJoTUNTMUl4RGpBTUJnTlZCQWdNQlZObGIzVnNNUkF3RGdZRFZRUUhEQWRIWVc1bmJtRnRNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRVpNQmNHQTFVRUN3d1FRMlZ5ZEdsbWFXTmhkR1VnVlc1cGRERVpNQmNHQTFVRUF3d1FaVmRDVFNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SUJjTk1qTXdOekV4TURNME5qRTBXaGdQTWpBM016QTJNamd3TXpRMk1UUmFNSUdkTVFzd0NRWURWUVFHRXdKTFVqRU9NQXdHQTFVRUNBd0ZVMlZ2ZFd3eEVEQU9CZ05WQkFjTUIwZGhibWR1WVcweEZ6QVZCZ05WQkFvTURtVlhRazBnUTI4dUxDQk1kR1F1TVJrd0Z3WURWUVFMREJCRFpYSjBhV1pwWTJGMFpTQlZibWwwTVJrd0Z3WURWUVFEREJCbFYwSk5JRU5sY25ScFptbGpZWFJsTVIwd0d3WUpLb1pJaHZjTkFRa0JGZzVwYm1adlFHVXRkMkp0TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBaCtvZUt5TFNnNzk3STZwSm9PdXYySzBiWWpLWUdRZWRJTVpBZ2hpWlA2K29Ed0NBN3pXYWlaell0M2s4YWtRM3FhNFRuakE4ZENPOXovSUtLSHk3YWpWVEJUTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZMY245L0dJQy9iYUt0MEd6M3hJNE9FWHVSVCtNQXNHQTFVZER3UUVBd0lCQmpBUkJnbGdoa2dCaHZoQ0FRRUVCQU1DQUFjd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFOVm5KZGUvL3RCTHE4TUREaStTQWQ2VWRZSVpTbmc0UE1xbXlOcnZaajY0QWlBWDB4U3pBaEZhQ0NwL3VocFZnbmxGK1hCZ3J3QUlzb3RaR1RCNnJrQjMxQT09IiwiTUlJQ3BUQ0NBa3FnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQnJ6RUxNQWtHQTFVRUJoTUNTMUl4RVRBUEJnTlZCQWdNQ0ZObGIzVnNMVk5wTVJNd0VRWURWUVFIREFwSFlXNW5ibUZ0TFVkMU1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFpWZENUU0JEUVNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SGhjTk1UZ3dOekF5TURVek1UTTVXaGNOTWpNd056QXhNRFV6TVRNNVdqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRSWZxSGlzaTBvTy9leU9xU2FEcnI5aXRHMkl5bUJrSG5TREdRSUlZbVQrdnFBOEFnTzgxbW9tYzJMZDVQR3BFTjZtdUU1NHdQSFFqdmMveUNpaDh1Mm8xVXdVekFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUIwR0ExVWREZ1FXQkJTM0ovZnhpQXYyMmlyZEJzOThTT0RoRjdrVS9qQUxCZ05WSFE4RUJBTUNBUVl3RVFZSllJWklBWWI0UWdFQkJBUURBZ0FITUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEYzQxTEZLNExKQ0JVMlZWS0l6N1o2c3hQaFVFa2g4bkxTTEs2SVhka1A1d0loQUllS1ZPWmNoYVZPNWFGN2ZiZFhvU3JjeXkxWVllVWVQTG9qY0tJOWZYODQiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBK2dBQUFFeENBWUFBQUR2RFlncUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUZpY1NVUkJWSGhlN2QwSGVCWEYyc0R4TjczUUNUVkE2RklGRktrQ1V1eUFFdW1LWWtGVWJJQ0NJaUtDVWdRRTdMMGdkbFFzS0NwU3JJZ2dTQytoSm5SQ0o0SDBiMmZ2ZUQvMGtoQ1NuYzJlay8vdnVYbVlkNDZYa0pOejlzeTdNL05PUUpaRkFBQUFBQUJBZ1FyVWZ3SUFBQUFBZ0FKRWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlRUJBbGtXM1BTc3pOVlhTRHlUS3FhMWI1ZFNhZFpLNmU0K2tIejltOTRuMy8vbUFjUUVob1JKY3VwUUVSMFZKV0pWS0V0Nmd2b1JYcnlaQnBVcEpRQ0QzNFFBQUFBQmY0TmtFUFNzalEwNXQzaUtIUHZwRWp2K3dRTkwzN1pPczFEVDlLSUN6Q1l5TWxOQWExYVRFTloybFpKZk9FbHFodlBXT0Q5Q1BBZ0FBQVBBYXp5WG9LakUvTXZjN1NYeHpocHhhc1ZMM0FzaVBnTkFRS2RxeHZaUzlZNEFVYWRKWTl3SUFBQUR3RWs4bDZNZC8rMTMyakh0S1V0YXQxejBBbkZhODY5VlNZZGdRQ2F0U1JmY0FBQUFBOEFKUEpPZ1pKMDdJbm9sVDVQQUhINHRrWnVwZUFLWUVoSWRMaFZFakpLcFhkd2tJRHRhOUFBQUFBQXBTZ1Nmb3A3WnNsUjBEQjBucTF1MjZCNEFyQWdLazJCV1hTcFhKRXlTb2FGSGRDUUFBQUtDZ0ZHaUNmdUxQNVJJL1lKQmtIRG1pZXdDNExieFJRNm4yNWlzU0VoV2xld0FBQUFBVWhBSkwwRThzWFNZN2JybERNcE9TZEErQWdoSmFxNGJVL09oZENTNWRXdmNBQUFBQWNGdUJISkNzbHJYSDMza3Z5VG5nRWFtYnQ4cjJnWU1rZy9ja0FBQUFVR0JjVDlEVGp4NlQ3YmZkSVJtSER1c2VBRjV3OHMrL1pPY2pqMGtXaFJvQkFBQ0FBdUhxRW5kMXhubjhBdy9Kc1MvbTZKNXpGeGdaSVVHbFNrbElqZW9TVktLNDdnVUtPZXR0bkw1dnY2VHRpSmVNSTBjbEt5MU5QM0R1S2s0WUsyWDY5TklSQUFBQUFMZTRtcUFmWGJqSUxncDN6a2VwQlFaSytQa05KS3AvUHluV3VxVUVseWtqQVVGQitrRUFmOHRNVFpYVVhidms2TGZ6NU5ETTl5Vjl6MTc5U080Rmxpd2g1LzN3RFVYakFBQUFBSmU1bHFCbkpDVkwzRlhYU0ZyQ1R0MlRPNkUxcTB2RlVTT2tlTnMyZHFJT0lIY3lUNTZVZ3g5OExQdWZlVjR5angzWHZibFRvbHRYaVprNnlicENCT2dlQUFBQUFLYTVsdkVlbWZQMXVTWG5WbUpRb21lczFKNHpXNHBmMG83a0hEaEhnUkVSVXZiVy9sTExlZytwbzlUT3hiRnZ2NWRUOFFrNkFnQUFBT0FHVjdKZXRleDIvL012NlNnWHJHUThhdEJBaVhscXZBU0doK3RPQUhrUlZxV3lmWVJhNU1VdGRjL1paWjFLa2YzUHZxQWpBQUFBQUc1d0pVRS9zWGlKcE8vYW82T3pDQWlRMGpmM2sraWg5N084Rm5DSXV0RlY3ZFVYejJrbS9jU0NSWkorNUtpT0FBQUFBSmpteWg1MFZibjk2R2RmNkNobktvR28rZkg3RWhnV3Fudnl5ZnJ4c3RMVEpmM0VDY2s0Zmx5eVV2TmUzUnB3aXpxdElMaFlNWHVadWwwUTBhR2JWYWUyNzVETlYxNGpXU2twdWlkbmxaNlpJcVd2NmFJakFBQUFBQ1laVDlCVmNyeXVlUnZKUEh4RTkrUWdPRmlxejNwUGlqWnByRHZ5TG5uZGVqazJmNkVrL2JwWVVyWnNsWXpFZy9vUndIY0V4MVNSaU5xMXBHaUhkbEtzWTNzSnExaFJQNUozKzE1NlZmWlBtcXFqbkJXOXJLTlVmL1ZGSFFFQUFBQXd5WGlDbnJ4bXJXenAybDFIT1N2YThSS3AvdnJMZVo0dHpEeVZJa2UrL1U0U1gzdFRVdFp0MEwyQW53Z01sS0tkMmt1WlcvdExzUmJOOC93K1NUOTZWRFoxdkZJeURoM1dQZGtMS2w1YzZ2N3hzd1NHaGVrZUFBQUFBS1lZMzRPZS9OZEszVHE3MG4xNjVTM3B5TXFTNDR0L2w3ak8zV1RYa09FazUvQlBtWmx5WXQ0QzJYN0RMYkp0NENCSnlXT1Y5ZUFTSmFURXRWMTFsRE4xVkZ2cXpsMDZBZ0FBQUdDUzhRVDk1UHJjSmNzQmtSRlM3SksyT3NvOVZTRis5OFRKc3VPbUFaSzZkWnZ1QmZ5WVN0Ui9XQ2lidTE0bmgrZDhZOGZucWtTWHEzUXJaMWxwYVpMQyt3b0FBQUJ3aGRrRVBTdEwwclp1MTBIT3dodlVsOERRY3lzTXA0cStiYi9qSGpuNDZwdjJYbmVnTU1rOGRseDJEaDRtZTZZK1k3L1h6a1ZFelJvU1dMU29qbktXc2llWEp6QUFBQUFBeUJlakNicmEzcDZSbkt5am5LbXptcytGU3M2MzNUcFFraGI5cEh1QVFpZ2pReEpmZU1WZVJYSXVTWHBBUklRRWw0M1NVYzdTZDVPZ0F3QUFBRzR3TzRPZW1TbVp1VHpPS2FoQ2VkMDZPN1hzTm43WUNEbTViSVh1QVFvM3RZcmt3RnN6ZEhSMjZ1aTJnTkRjRlg3TDJMZGZ0d0FBQUFDWVpId1B1Z243WDN0VFRuejNnNDRBS1BzbVRaT2tGWC9wQ0FBQUFJQ3ZNWHJNbXRvWHZxbExyS1J1ak5NOTJZc2FORkNpaHczVlVmWk9ib3FUTFYydXMyZlJjeTB3ME41dkcxd21TZ0tqU3VsT3dLT3NkMlRHemwyU2NlS0VaSjVJMHAyNUUxcXJodFQrOGxNSmpJalFQV2VXbFpFaGNaMWpKV1hqSnQyVHZaTGR1a3FWYVpOMUJBQUFBTUFVMzByUXJYL3F0dHZ1a0JNTGM3bnYzRDQzdW9PVUhYQ3poTmVySzhIRml1a0hBSS9MekpTMHc0Zmx4TzkveUlIblg3SVNhZXM5bEp1M2FrQ0FsQjh4VE1yZGZxdnVPRE1TZEFBQUFNQjdmR3FKZTlLcTFibE96a05pcWtqMWoyWks5VmRma0tMTm01R2N3N2NFQmtwSVZKU1U2bnlWMUo0eld5bytPVm9Dd3NQMWd6bXdrdmpFbDErVGpLUnptM2tIQUFBQVVQQjhKMEczRW84RHI3NmhnNXlGbjk5QWFzNytTSXBlMUZUM0FMNUxGWFFyYzMwZis0WlRVTWtTdWpkN0dZY095eEYxUGpvQUFBQUFuK0l6Q1hyNmthT1M5TXR2T3NwZWNNWHlVdTMxbHlXa2RHbmRBL2lISW8zT2w4clBUYlZlNUVHNkozdEhQdnRDdHdBQUFBRDRDcDlKMEpOV3JwTE1ZOGQxbEkzQVFLazRkclNFbEN1ck93RC9VcnpOeFZMcWhqNDZ5bDd5bnlzazQvZ0pIUUVBQUFEd0JiNlRvUC8ydTI1bEw3eGVIU25SNFJJZEFmNnA3SUJiSlNBNFdFZlp5TWlRcEpVcmRRQUFBQURBRi9oTWdwNjhicDF1WmE5RWw2dnQvYnFBUHd1clhFa2lXalhYVWZaT3JWNnJXd0FBQUFCOGdVOGs2RmtabVpLMmFiT09zbGZzc2s2NkJmaTNZbTNiNkZiMlV2ZnYxeTBBQUFBQXZzQkhFdlIwTzBrL203QUtGWFFMOEcraDFhdnBWdll5VDNEVUdnQUFBT0JMZkdhSmU2NEU2RDhCZjhkckhRQUFBUEE3L3BXZ0F3QUFBQURnbzBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQQ01peTZMYmpzdExUWlZPWFdFbmRHS2Q3c2hjMWFLQkVEeHVxbzMvS1RFMlZEYTNhUzhhaFE3cm56QnFzWFM2QmtaRTZNaWMxUGtGT3JkK2dJL2l6MEpnWUNhOVhSMGZlY1dUK0Fra1lNRWhIWjFhaVI2ekVUSjZnbzMvS3lzaVF1TTZ4a3JKeGsrN0pYc2x1WGFYS3RNazZBZ0FBQUdBS0NYb2VISno1dnV4K2JLeU80TStpK3ZlVDZNY2YxWkYza0tBREFBQUEvb2NsN2dBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUJ3UmtXWFRiY1ZucDZiS3BTNnlrYm96VFBkbUxHalJRb29jTjFkRS9aYWFteW9aVzdTWGowQ0hkYzJZTjFpNlh3TWhJSFpsemN2VWFPZjdqenpyeXZ1US9WOGp4UlQvcHlGbmxCOThyRXVTLzkza2lHcDB2eGRxMTBaRjNISm0vUUJJR0ROTFJtWlhvRVNzeGt5Zm82Sit5TWpJa3JuT3NwR3pjcEh1eVY3SmJWNmt5YmJLT0FBQUFBSmhDZ2w0SUpMNDVRL1k4Y2VaRUxiOGF4cTJSZ09CZ0hjRXQvcHlnWjZXbFNWYW1zY3RTNFJNZ0VoZ1NZdjFwTlFBQS8wT05NOFdGajUyQTRDQUpDQXJTVWNGejlmT1d6eUlnMTBqUUN3RVNkUC9qenduNnRxSEQ1TlNLbFRwQ2ZnV1ZLQzYxUG41ZkFrTkRkUThBNEhSeDNmdEkrbG5HbUU0b1Avd0JLWDNWRlRvcVdCbEpTYkxseGxzazQvQVIzV05XWkl0bUVqUCtDUWtJWkhjdGNEWWs2SVVBQ2JyLzhlY0VQYTdmelhKeThSSWRJYjlDYTFTWHV2TyswUkVBNE4vV3RXd242UWNPNk1pYzZFbmpwVXozV0IwVm9NeE0yVDUwbUJ6N3lwM1BodUFLNWFYMjdJOGxwRnc1M1FNZ0o5ekdBZ0EvRmxhcnBtNEJBQ0NTK05FczE1THpnTEF3cVRKMUVzazVjQTVJMEFIQWo0V1dMNjliQUlEQ0xubmRldGt6N2lrZG1WZHV5TDFTckVWekhRSElEUkowQVBCallZMGE2aFlBb0RETE9INWM0Z2MvS0ZrblQrb2VzNHBkY1ptVXUrMFdIUUhJTFJKMEFQQmo0VFZyNkJZQW9OREt5cExkazU2VzFDMWJkWWRaSVpXaXBjcjRzUlNGQS9LQWR3MEErS3VnSUFtclVFRUhBSURDNnZBMzM4cmhEejdXa1ZtQmtSRVM4OEl6RWx5eXBPNEJjQzVJMEFIQVR3V1ZLaVdCeFlycUNBQlFHS1hFeDh1dWthUHRXWFRqZ29La3dxaEhwTWo1Yks4Qzhvb0VIUUQ4VkZEUkloSVlGcVlqQURBck16TlRUcDQ4S1ljT0haS3QyN2JKMHFWTEpUVTFWVCtLZ3BCNUtrVjJESDVRTW84ZjF6MW1xYU5aeS9Uc3JpTUFlVUdDRGdCK0txUnlKUWtJQ3RJUkFPU05TcnpUMHRJa09UbFpFaE1UWmZQbXpiSjQ4V0o1Ny8zM1pkejQ4VEo0eUJDNU5qWldhdGV0SytmVnF5ZDFySzk2RFJwSTY3WnQ1YmhMaVNIT1FPMDdmMnF5bkZxNVduZVlGZDZvb1ZRZU8xb2tJRUQzQU1nTEVuUUE4Rk9oVldOMEN3QnlwaEx3QXdjT3lOcTFhMlgyN05ueTRrc3Z5V09qUjB1L20yNlNpOXUxazZiTm10bEpkNldZR0tuWHNLRzA2OUJCYnI3MVZubDg3Rmg1d2ZwdnY1azdWK0xqNDJYdjNyMXk1T2hSTzZsSHdUcTY2Q2M1L1A1SE9qSXJzR2hSaVprK1JRTER3M1VQZ0x3aVFRY0FQeFZLZ1RnQU9UaDI3SmhjZXZubFVyZCtmWWtzVmt5aXExU1JKazJiU3ErK2ZlWCtJVU5rd2xOUHlVY2ZmeXpMbGkyVDlSczJ5TzQ5ZTBpOGZVVHE3ajJ5Yy9nSXlVcFAxejBHQlFSSTlKT1BTM2pWcXJvRFFINlFvQU9BbndxL29KRnVBY0QvVXZ2REYvLyt1MnpaNnM3UlczQkhwdlY3algvb0VjazRkRmozR0dRbDUxRURicGJTWFR2ckRnRDVSWUlPQUg0cXZFb1YzUUlBRkJiN1gzMWRrbi83WFVkbVJWN1VWQ29PSGF3akFFNGdRUWNBUHhRUUVTRWhaY3JxQ0FCUUdCeGZzbFQyUC9lU2pzd0tybGhCcWo0M1ZRSkRRM1VQQUNlUW9BT0FId291WDA0Q1FvSjFCQUR3ZCtsSGprakNzSWVzaHZsOTV3R2hJVko1OGdRSktjdU5ZTUJwSk9nQTRJZENTcGFVZ0VBdThRQlFHS2hpY1BIREg1SDBYWHQwajFsbDdycERpcmRxcVNNQVRtTDBCZ0IrS0tSR05jNmlCWUJDNHNEYjc4aUorUXQxWkZiUjl1Mms0cjJEZEFUQWFTVG9BRHdscEZ4WkNhMVMyYld2a0lvVjNVbGtyZThSVWluNmpQOEdFMThSOWV2cmJ3d0E4R2RKSzFmSnZxblA2TWlzRU92ekpXYktSRzRBQXdZRlpGbDAyM0ZxdWMybUxyR1N1akZPOTJRdmF0QkFpUjQyVkVmL3BJNkwyTkNxdldRY09xUjd6cXpCMnVVU0dCbXBJL3d0OGMwWnN1ZUpDVHB5VnNPNE5SSVF6RDVYdHgyWnYwQVNCdVI4OTdwRWoxaUptWHptMzN0V1JvYkVkWTZWbEkyYmRFLzJTbmJyS2xXbVRkYVIvemtWSHk5eGwzVTJmbFpzWUpFaVVtZkJkeEpTSmtyM0FFREJTa3hNbEtvMWF0akhyWm15ZDljdWlZcnk5blZ2WGN0MmtuN2dnSTdNaVo0MFhzcDBqOVdSTTlLUEhaTzRiajBsYlVlODdqRW5NQ0pDcW4vd2poUTV2Nkh1QVdBQ00rZ0FBQUNBRDlyMXhIaFhrbk1KREpUeWp6NUVjZzY0Z0FRZEFBQUE4REVIUDUwdFJ6LzdRa2RtbGVqYVdjcjA2cWtqQUNhUm9BTUFBQUErNUdUY1p0a3pacHlPekFxcmM1NVVHVGVHazBFQWwvQk9nMDlSOVFpMjlydFoxbDNRd3ZoWDNMVTlKT05Fa3Y3T0FBQUFCUy9qeEFtSnYvOEJ5VXd5UDBZSkxGWk1ZcDZmWnU4L0IrQU9FblQ0anF3czJUZjllVW42OVhmSk9ITFU2RmRtOGttcE9IcWtCQlV0b3I4NUFLQ3d5TXpNbFBUMDlETitaV1JrV0I5SHh1cnJBam5Lc2w2YnV5ZE15bFdSMTN3TENwVG9NYU1rb2tZTjNWRjRxZmQ4VHRjRjlSamdGS3E0RndMK1VzWDkyTSsveUk1Yjd4VHJTcWg3ekNsNy85MVNZZkM5T3ZJZXFyZzdoeXJ1dmk4bEpVWFdybDByZjYxY0tmdjM3NWNEaVluNkVaR3cwRkFwV2JLa2xDMWJWbXJYcmkzMTZ0YjFmRVZwdUNjcEtVbTJidDBxcTFhdmxqMTc5c2kyN2R0bDQ4YU5jdXJVS1RsNTh1UVpCOTBSRVJFU0VoSWlwVXFWa2diMTYwdWxTcFdrYXRXcWRydHk1Y29TN0VNbm0xREYvVDk4cVlyN2tlKytsL2g3aHFpN1NMckhuTkw5KzBubFVZOFV1aVBWMHRMU0pONGFHeXhmc1VJU0VoSWtMaTVPTmxsZjZycVFuSnlzLzZ2L3A5N3pZV0ZoVXJ4NGNXbllvSUY5SGFoV3JabzBidFRJdmo3NDBqVUIza0NDWGdqNFE0S2V1bnVQYkxaZVN4bUhqK2dlY3lKYnQ1UWFNOS8wOUY0ckVuVG5rS0Q3cHFOSGo4cmNiNytWRHo3OFVINzg2U2M3MGNxdE91ZWRKNDgvOXBqMDZORkQ5NkF3VU1uMnRtM2JaUEh2djh1aUgzK1V2Lzc2UzFhdVdxVWZkVVo0ZUxnMGI5Wk1McmpnQW1uVnNxVzBiTkhDSHFCN0ZRbjZmL2hLZ3A2U3NGUGlydWt1bWNlTzZSNXpJaTVzSWpWbnZpMkI0V0c2eDMrcDE3KzZ3ZnZMTDcvSS9BVUw1UGNsUytTWVE4OXhwSldYdEczVFJ0cGZjb20wc0s0SHpTNjZ5TDVPQURraFFTOEVmRDFCejB4SmthM1g5NWVUeS8vU1BlWUVsUzBqdGIrZUxTRmx5K29lYnlKQmR3NEpldTc4YmlVMTY5YXYxNUV6THJJR0tvM09QMTlIdVhQQUdrUy8vT3FyTXVYcHA4ODRrNUZic3o3NlNMcGRlNjJPenQyc1R6NlI0OGVQNjhoNVYxNXhoVVJIUit2SUdaOTk5cGtjT1hwVVI4Njd4QnFBMXZUWVVsaTFISDNUcGszeTJlelo4c21ubjhyNkRSdnNQcmNFQlFYWk40UjY5ZXdwVjExNXBUUm8wTUNlYVROcDFhcFZzdXpQUDNXVXN4TW5Uc2hESTBiWVMzUk5lWHJ5WkNsYXRLaU84cTU4K2ZMUytlcXJkZVFzWDBqUXM5TFNaSE8vbStYa3N1VzZ4NXpnY21XbDF1eFpFbHFodk83eFArbzFyMjdRZldoOUZyejczbnR5OE9CQjQxdFhBZ0lDcEZpeFl0S2plM2ZwZC8zMTByeDVjK1BYZ3pOUk55cy8vK0lMT1hMRTdLUlg2ZEtsOC9VNW0xZnE1M3RuNXN3enJvQnlpcnJKMHJ0WEwvc2Fid0lKZWlIZzB3bTY5ZkxjODh6emt2anNDMVpiOXhrU1lGMGtxNzc5bWhScjJWejNlQmNKdW5OSTBIUG4vaUZENU1XWFh0S1JNKzY3NXg1NWVzb1VIZVZNRGFabXpab2xReDk4VUJLdGdWUitxT1dHZi83eGg5U3ZYMS8zbkJ2MXNkbW9TUlBac0hHajduSGV0OTk4STUwNmR0U1JNNW8yYTJZdjVUYmxuYmZmbHI1OSt1aW9ZS2tWRmQ5Ly83MU1zbDVmYWhDdWxxd1dORFdRVTB0ZkI5eDZxLzA4eGNURTJBTjJwMDJkTnMxT3V2Mk5TbW8rc0JJcEV6eWZvRnZYbkYwVEpzdkJOOTdTSGVhb01WM1YxMStTNG0zYjZCNy9vbTdzZmo5dm5qdzFhWktzK09zdlYyL1luVTY5OTZ0WHF5YUQ3Ny9mVHZSVU11dW0yd2NPbExmZmVVZEhacWliRWJzVEVseGZNYUMyTGRVLy8zeWp2OXNPN2R2TGQzUG5Hcm1HS3hTSmc2Y2QrMjJ4SEh6aEZlUEp1ZlVPa3pLREJ2cEVjZzc0aTRTZE8zVXJaNGNQSDVicmI3aEJicjd0dG53bjU0cWF6Vk9KRXZ5UFdxcjYzdnZ2MnpjamV2WHRhODhrZXlFNVY5UmdjY2VPSFRKcTlHajdCcysxc2JHeWRObXlBa3NRZkUzclZxMTBxL0JSTlhnT3pqQ2JUUDJ0ekYyMysyVnlybTd5ZnZubGw5S2thVlBwMmJ1M2ZXMG95UGVldXRHN2RkczJ1Vy93WUtuWHNLRThQWFZxdmxhRm5hdGV2WHJwbGpscWxabXFEK08ySlV1V0dQL2Q5ckZlUTZhU2M0VUVIWjZWZGlCUmRqM3dzUEdaVFNXeVdWTXBmOWRBSFFGd3d4cnJnL3RzaTdqVW51RzI3ZHZMN0MrK2NHeTVXcGt5WmV3NysvQWY2blgwODg4L1M1dDI3ZVRtVzIrVkxWdTM2a2U4S2Zua1NidUdndnIzWG5IVlZmWVdFdVNzUmlHdEpKNjZiNzhrREgvRXlqRE5KNU5GMmw0c0ZlNjlXMGYrUTIzUHVycExGK2x1SmFYcU04VnJEaDA2SkE4LzhvaDlZL0dMTDc4ODYrZWlFeTZ4cmoycTBLVnBjNy83VHJmY00zL2hRdDB5UTYwSXVDNDJmOFVlejRZRUhaNms5bG9sUFBpUXBGc2ZUS2FwdlZZeHowK1hnSkFRM1FQQURjZU9IclVyWldkSFZjN3RlT21sZGxWdEoxMTR3UVZHNzN6RFhXb2Y5ZEFISHBETHJyelNYckxxUzlSTkoxWGtVTjJFNnQ2enAyemM1TUxSV1Q1STdkTlZWZklMRzdYRk0rSGhSeVRqd1ArZlRHRktjTVVLRWpONW9nUVkybE5iRU5TS21zbFBQeTB0V3JXU2hZc1c2Vjd2MnJ4bGl6MjczKyttbSt4Nkt5YUZob1pLZDhOSnBySjQ4V0xkY29lNnBxb2lvQ2FwbXh2cWRCaVRTTkRoUFZsWnN1K2xWeVhwcDE5MWh6a3FLYTgwYVp5RWxDMmpld0M0NWRqeDQvYnk5VFBadlh1M1hHNGxYRHQzN2RJOXppbU1BMzEvcFdiRDJuZnNLTSsvK0tMUEx4WC84cXV2NUtMbXpXWHNFMC9ZTngzdy8wS0NnNlZDaFFvNktqejJ2L0cyTzJPaGlBaXArdngwdnhvTHFXTVR1MTV6alR3eWNxUjlQSnF2VUxQbkg4K2FaYyttLzdGMHFlNDE0N3JycmpOK3Mxb3RjVGQ1U3NTL3FhTXkxVllpazI3czEwKzN6Q0ZCaCtjYy8zMkpKRDcvc283TWlocHdpeFMvcEoyT0FMaEp6WjZyczJiL1RSWDQ2dFduajVIa1hGSFZ4dUg3bGxxRFY3VkUzT21qMGdxU1NpU2VHRGRPV2w1OHNheFlzVUwzb203ZHVvWHVhS3JqZnl5VkE5T2YwNUZCZ1lGU1lmaFFLZEtrc2U3d2ZTdFhyclN2RFF0OFlOWThPM3YyN3JWdlVzOTg5MTFqUzk1VlhRZDFESnhKdTNidk5wNHduMjdldkhtNlpVWkVSSVI5eW9wcEpPandsTFQ5K3lYaC9nZnRKZTZtUlRTL1NDb012VTlIQUFxQ3V0dDlPclU4YmNnREQ4aVNQLzdRUGM0S0N3MHR0SHRaL1lrNnIvaUtxNitXL1M1VTNpNElhbHRIMzM3OVhKMTU4ckthTld2cVZ1R1FmdXk0N0J6K2lDczFlSXBmZVptVTZYZTlqbnlmV2xMZHZsTW5pVTlJMEQyK1M5MnNIbmpublRKdCtuUWpTWHFSSWtXazJ6WFg2TWljYjEzYWg2NmVvM2svL0tBak05VHBLaVZLbE5DUk9TVG84QXoxUWFRS29iaXgxeW9vcXJURVRKMWsvQXgzQURuNzdWLzcwOVR4TjJyR3dKU3laY3RLS2NON3gyRFcrdlhyN1JVV0pzK2g5NExKVHoxbDd4T0ZTTE9MTHRJdC82ZU9RVTBZT1VyU0VuSjN5a1YraE5hdUtWVW1qcE9BUVA5SUIzNzg4VWU1cWtzWHY5b2lvcXJQanhnNVVwNTU5bG5kNHl4VmpkeTB4UzRWd1R5VmtpSi9HTHE1LzdjQnQ5Mm1XMmFSb01NejlyLytwaVQ5K0l1T3pMSDNuVThlTDZHVm9uVVBnSUp5K2hMM28wZVAya2ZPcUFHSktlWExsN2NMVHNFM3FXckhzVDE2eUlGRTh6ZHlDOUtkQXdkS1Z5dlJ3SDgwYmRwVXQveGY0cnZ2eS9GdnpNODRCaGFKbEpqcFV5U29TQkhkNDl2VXFxdHUzYnZiczg3K1JxMHNHL2JRUS9MZWUrL3BIdWUwYk5sU2loY3ZyaU16MUxGbktWYnliTnJtdURqWnUyK2ZqcHluenFwdjE3YXRqc3dpUVljbm5QaGpxZXlmUEYxSFpwVWVjTE9VNk5CZVJ3QUtrcG9OL2RzYmI3NXAvQWljcGhkZVNBVjNINldXTDZxQ1QxdTJiTkU5L2trVk1ad3dmcnlPb1BhZVY2dGFWVWYrTFhuTld0azdlYXFPREFvTWtJcGpSa2xrM2JxNnc3ZHQzNzVkdXZmbzRmZkZGZSs4KzI3SHQzK3BhdVJYWDNXVmpzell0MysvN0xlK1RQdG03bHpkTWtNdGIzZnJpRllTZEJTNDlFT0hKR0hJY0hXTFVQZVlFOW1pbVZRY3dyNXp3Q3ZVSG1LMVZEa3hNVkhHakIycmU4MVJ4YWJnbXhZdFdpUnZ6WmloSS8razlvUysvZWFiVXJSb1VkMkRraVZLU0ZSVWxJNzhWL3F4WTdKajhJT1NkZEp3eGZHQUFDbmQ3M3FKNm5hdDd2QnRhc2E4ZDkrK2RoTG83MVFSeVJ2NjliTlhFam5KZEZWeU5Ydis3KzFzVGxPckRFenVkVmMzOXUrNC9YWWRtVWVDamdKbG4zYytiSVNrNzk2amU4d0pLbFZLcWt5ZnpIbm5nSWVvNWV6Nzl1MlQ5OTUvWDVKek9CUGRLZXI4VXZnZTlUb1pOWHEwUFFqelYyb0FPT0toaDZSSmt5YTZCMHI1Q2hYc3lzbCtMU3RMZGowNVFkSzIvYk5vcGduaDlldEo5RU1QMm9tNlB4ajc1Sk95M01VVEQ0S0NndXhpbzJwbGgvcFNXNlpDckhHbFd5dXpkc1RIeTUyREJqbDZMV3plckptVUtXUDJpTDF2di8xV3Q4dzRldXlZckR0dFJaN1RvaXRXbEdiVzgrUVdFblFVcVAxdnpaQVRDMzdVa1VIV2hUTjYvQmdKTFlUbnFBSmVwcXBVcjkrd1FWNTYyZnpSaW1vZ1ZhMWFOUjNCbDZpcTdhWXErM3VGT3ZKbzZKQWhPc0xmR2pkcXBGdis2OUNYYytUb1oxL295SnlnTWxGUzlhWG5KTkJQanF6NytlZWZaZXEwYVRveVJ4VnJ2T0x5eStXRjU1NlRYMy82U2JadDJTSjdkKzJ5di9iczNDa2IxcTZWYitiTXNXK3cxYTlYVC8rL3pQbksrbDVPemhhcnF1UWREQjgvK3JOMURjL0l5TkNSODlUSkYwNnZMRGhkKy9idGpSOUpkem9TZEJTWUUzOHNrd05UbnRHUlFWWnlYdnEyL2xMeXlzdDFCd0F2ZWZPdHQyVEwxcTA2TXFkcTFhcXVmc0RDR1dyditiUFBQNjhqODZwVXFTSTMzM1NUUEQxNXNzeXpCc0ViMTYyVHJYRnhzbS8zYnRtMGZyMnNXNzFhNW4vL3ZUejN6RE15Y3NRSXVhWnJWNmxYdDY0RTUrTlVrS2pTcGVXZEdUUHNtVGo4VSszYXRYWExQNTNhdmtOMmp4NXJ6NktiRkJBU0xKVW5QQ0ZoZmxJZ1YrMDNIekJ3b0k3TVVMUGl2WHIydE4vemM3NzhVZ2JlZnJ0ZHNGQ2RCcUsybzZndnRTYzVKaVpHTHUzVVNjYU9HU1BMbHkyVDJaOStLdWMzYktqL0Z1ZXBGVVgzRHg3czJKNTc5WFBlY0wzWm8vWlVZYys5ZS9mcXlIbmZXZGRrazl4YzNxNlFvS05BcENVZWxJVDdIM0RudlBNTG0wakZCNW1WQUx4cXp0ZGY2NVpabGFLajg1VkVvV0FjUEhoUWZ2cjVaeDJaVTcxNmRYbHY1a3c3SVgvdDFWZmx2bnZ2bGZhWFhHS2ZtNitTZGxYQlYvMDNLbUZzMTY2ZDNIbkhIZkw0Nk5IeTZheFpzdUxQUDJWWGZMeDgvT0dIOWtDM1N1WEsrbS9OblNtVEprbU05VDN3di94NVcwcEdjckxFVzJPaHpPUG1pNXRGM1hhTGxPallRVWUrYjlLVUtiTFZZRkhSNGxiaVBYUEdESG4zblhmc203dTVwWmJBZCtuY1dSYi8rcXVkMEp1eWZjY09lZjZGRjNTVWY1ZFkxenBWTU02VVpPdTEvcWQxblRSQjNjVDk0Z3R6SzFEVTcvOGlsNDk2SkVHSDY3SXlNMlhYNkxHU3Z0ZmNVUWgvVTh1NVlwNmRLb0VjcXdRVWVtNS93TUlacTFldnRvL2dNK25pMXEzbGo4V0w3ZG15dk14aXEwRzVTdUJqdTNXemk3eXRXN05HZmxxNFVIcjI2SEhXSTR4dTZOdFhicmpoQmgzbG43cHhzTk1hdk9mbWE5V0tGY2JQV2wvMTExOW4vTjY1L1ZMN1kvMlJHZ3Z0Zm1xS25GcXpWdmVZVTZSTmE2azQ5SDRkK1Q2MUQ5dko1UFRmMUVxckQ5OS9YM3IzNm1YUEx1ZUYybEwxN1BUcGN2Kzk5K2I1N3ppYnFkYmY3OVMxVWEwR3VMUmpSeDJaTVgvQkF0MXlscW9RYi9KMGo4c3Z2ZFQxMVUwazZIQmQ0dHN6WFRualU0S0RKSHJDRXhJYVhWRjNBQ2pNYXRlcXBWdndKYVpuejFWaS9jRjc3ems2ZTZTS1I3VnExVXJlZi9kZGUzbnN4UEhqN1JVYy94Nm9xNW4ycDU5KzJ0RUJ2RW91MUhuL3VmbFNTM1ZOSzJkOWp6Tjk3OXgrcVpzZi91am9Ed3ZrOEFjZjY4aWM0SExsSkdieVJBbndvK2R4aXZXZVVhZC9tREo2MUNpNTdMTExkSlIzNnJVN2Z0dzRZNnRBRGg4K0xLKys5cHFPOGtkZGc5UU5TcE4rK2ZWWDNYTFdYeXRYR2kweWE3cksvWm1Rb01OVlNTdFh5YjRwNWd0NktLWDY5cGFTbmZ4bk9SZUEvRkd6cFBBOUppdnpLcGRiQS9HS0ZjM2R5RlZKNWdORGg5cXo2bXJmdXRxdnFxaEswRysrL3JxOS94eUZTOHF1WGJKenhDZ1JnMFd6bElDd01JbDVmcXFFbEROL0k4WXRPM2Z1bExjTkhyZllvbmx6ZTN1TFU5UUtsUmVmZjE0aURaMUU4SnAxRFZGNzBwMmdia29VTVZpblpjM2F0ZlpOQmFjdE1EUXpyNml0UjgydDE0VGJTTkRobXZSRGh5WGgzcUhtei9pMGhEZW9KOUdQUHF4dUNlb2VBSVdaV200WWN3NzdDT0VkYTlldDB5MHpxcnRVMlYvTmJOOHhjS0M5ckh6VXlKRXllUEJnZTk4bkNwZE1mYnhzNXBFanVzZWN3S0pGSk16UFRxNlkrZTY3OW5uZ3Bvd1pQZHJ4V2lXcWJzV3R0OXlpSTJkdDI3NWRGaTVjcUtQOEtWcTBxSFRwMGtWSHpsTkh3NmxxN2s1Uys4OU5Gb2pyMnJWcmdhemlJVUdISzdMUzB5WGhvVWNrTFdHbjdqRkhmU0JWZVg2YUJCcmVWd2VnWUtnallhNis4a29aLytTVDlwRTNDZFlBNWVqaHczTE0ranA2NkpCczM3SkZmck1HQVdyLzMxMTMzR0dmSzkzbTRvdnRHVXY0bnNURVJOMHlJODJGWXFXblUzczlIeHMxU3A0WU04YlkzbFI0MS82WFg1UGtKVXQxWkZiR3dVT3k4L0VuN2YzdS91RGt5WlB5bk1HOTU2MWF0cFNPaHZaaDMzUDMzY2IyTWIvbDRJb0NWVGZEcENWTGx1aVdNL2JzMlNNYk4yM1NrYk9DQWdQbCtyNTlkZVF1RW5TNEl2SERqK1hFL0VVNk1pY2dPRWdxVFo0ZzRaeDFEUGlkcUtnb2VmeXh4K3dxMjE5OC9ya01lL0JCZStsWmhRb1Y3T1dERWRhWG1xV3NWS21TTkx2b0lybnJ6anZsMldlZXNZdC9mVEY3TnNrUXppaHU4Mlo3RnNadHZCNExwK0F5VWJybGp1Tnp2NU5EbjMrcEk5LzJ3L3o1Y3VEQUFSMDU3NWFiYnpiMnZxeG1qVXNiblgrK2pweWw2blFrSlNYcEtIL2F0VzFyZjVhYW92NnRUbDV2ZjdjU2ZxZVcrUDliNWNxVnBlbUZGK3JJWFNUb01DNTV6VnJaTjI2U1dvZWllOHdwcWZhZFg1SC93aDRBdkVNTmw5U3hOU3VXTFpPUmp6eGlKK3JuUWcyNDFCSjMrQ2JUaWV5Q2hRdGxtOEhqbW9EVFJmWHNMcEhObXVySUJkYllhOCtURXlUTllHTHJsbG16WnVtVzg5UUtxNjRHbDNlclpkTFh4Y2JxeUZuNzl1MlRwVXVkV1pWUnFsUXB1MnE1S1dvZmVtcHFxbzd5YjlFaWM1Ti8zYnQzTDdBaWxTVG9NQ3JqeEFsSkdEcGNzZ3p1Ri9wYldQMjZFdjNJY0RXYTB6MEFmSjM2Y0x6Ly92dGwxa2NmR1Mza0JlOHlmY3lXcWdaOWRkZXVrcENRb0hzQWN3S0NnNlhTRTQ5TGdJdkhObVVlUFNZN1I0MXhaYUxFbEpTVUZKbnp6VGM2Y2w0ejZ6cFRwa3daSFpseG1jSEU5K05QUHRHdC9PdlZxNWR1T2UrRWxSY3NYNzVjUi9tbmJyQ2FvRzdZOUwvcEpoMjVqd1FkeG1SbFpNak9rYU1sTmM3YzJZUi9DeXhXVkdKZW1DNkI0ZUc2QjRBL0dIVG5uVEpwNGtUSGkvYkFkMVJ6b2JpZk9rTzNXY3VXOHNHSEh6bzZ1d09jU1VUdFdsTDJ2cnQxNUk3ajgrYkxRUjllNnY3cmI3OFpQVnF0aytFendKVzZkZXZxbHZOVThUVlZoTTBKNmxnNFZTdkRGTFZWd1FtN2R1ODJ0dis4WnExYWNsN3QyanB5SHdrNnpNaktrc1QzUDVSalg1bTcyL2xmZ1FGU2NleGo3RHNIL0V6bnE2NlN5Wk1tR1YvaURHOXIxS2lSYnBsMThPQkI2WC9MTGRLMGVYT1o5Y2tuY3ZUb1VmMEk0THh5dC9hWHNMcDFkT1NPdmVNbVN1cWV2VHJ5TFY5Ly9iVnVPVTk5eG5SbzMxNUg1b1NIaDh2NURSdnF5Rm03cldUMTBLRkRPc29mZFRSa0c0UEhrcXJ6MEozWWh6NTM3bHpkY2w3MzJOZ0NuUmdnUVljUnllczN5TDZKVTl6WmQ5Nnp1NVMrdHF1T0FQaUQwcVZMeXlzdnYxeGcrNy9nSGVwY1lyZHUwcWhCNDRZTkcrVDZmdjJrYm9NR2N1Lzk5OHV5WmN2czViV0FrOVNLdjhxVHhrdUFpNmRMWkJ3K0lnbVBqTEpYT1BvU1ZRVHN4NTkrMHBIejFQRmk2aWcwMDlSMXJHS0ZDanB5MXJGangreUNsMDdwMzcrL2JqbHYwNlpOanF4VU1yYThQU3hNYnI3NVpoMFZEQkowT0M3aitIRkp1R2V3WkNXZjFEM21oTmFxSVpWR2oyVGZPZUJIMUNEbXliRmo3YnY0UUkwYTFuVStPbHBIN2xISHU3Mzh5aXZTcWswYmFkU2tpVHd3YkpoZGlNbnRZOW5ndjRyVXJ5ZWwrL2ZUa1R1U2Z2bE5EczMrUWtlK1FTMXRYNzkrdlk2Y3AwNy9LRm15cEk3TUttSHcrNnhaczBhMzhxLzlKWmRJOGVMRmRlU3NuYnQyeWZidDIzV1VOK3FtNmRKbHkzVGtyQWIxNnhmSVo4N3BTTkRockt3czJmWDRrNUs2YllmdU1FZnRPNi82OHZNU2FQQTRDQUR1VS92MGJ1em43cUFWM3FVR3o3SGR1dW1vWUd6ZHRrMmVmZTQ1YWQyMnJkU29WVXY2M1hTVGZEeHJsbDA5R2Nnek5hTTYrRjRKcVJxak8xeVFtV2xYZFUvWmJuNmM1aFNWektVYXZER205aHFIdXJTU29WelpzcnJsdk44V0w5YXQvRk9ucGJSczBVSkh6cHY3N2JlNmxUZnhDUW41VHZLejArM2Fhd3Q4OVI0Sk9oeDFjTmFuY25TMkMwVklyRGRPeGRFakpieG1EZDBCd0IrbzJmT0hodyszOStvQmY3dm43cnM5YzFUZVhpc3AvK2pqaitXR0cyK1VLdFdxU1l0V3JXVE0yTEd5Nk1jZmpSYXhnbit5bDdwUGVNTFZsWUNaeDA5SXdxT2pmV2FwdXlxQVpsTFZHUGR1a0pRclYwNjNuTGRueng3ZHlyL0F3RUM1eWVDTjh2eHVXZmpoaHg5MHkxbWhJU0ZHbC9mbkZnazZISE55NHliWk0vcEpWL2FkbDRpOVJrcGZWN0F6S2dDY1Y3bFNKZnZ1TlhDNjZ0V3JTNC91M1hYa0hXclArdklWSytUSjhlUGw4aXV2bEVyV1FMOVhuejd5c1pYQXE4R3lFNFdRNFArS3RXZ3VwYTd2clNOM0pDOWVJZ2RtdnFjamIxT25MSmhVcW5ScDNmSnRjWEZ4dXVXTUs2NjR3dGpLZ3BVclYrYTV0b2U2cm41ajZNaTlwazJiR3FzVGNDNUkwT0dJaktRa2liLzdmbmZPTzY5N25sUitZalQ3emdFLzFLZDNiM3RKTTNBNnRiSml6T2pSVXF4WU1kM2pQV3JRZVBMa1NabjkrZWR5dzAwM1NmMkdEZVdLcTY2U3p6NzdqSmwxbkZXRndmZEtrT0Z6dVA5dC85Um41SlFQTEhWWE44Rk1lbnZHREtsZXE1WXJYMDlQbTZhL3EvTU9Iam9rcHh3Y2g1Y29VVUxhdG1takkyZXBsVWpxbUxTOFVOZlRQdzI5SnE2OTVocjc4NmFna2FBajM3SXlNLyt6NzN6TE50MWpUa0JFaEZSNTVtbk9Pd2Y4a0ZwYU51QzIyM1FFL0ZQVnFsWGxpVEZqUERGNHlvMFRTVW15Y05FaTZYMzk5Vkt2UVFPN3lOeU9IVHVZVmNjWmhaUXVMWldlZkZ5dExkWTk1bVVtSmN2T2gwZEtWbnE2N3ZFZVZaVFJ5YVhiWjZJU3ZwMDdkN3J5cGFxdG02TE9RVmMzQ1oyaXJyVTllL1RRa2JQVTcxVVYzY3lMelpzM3k0RURCM1RrSFBYejNtQmRyNzJBQkIzNWR2aUxyK1RvcDUvcnlDRHJqVlB4c1JFU2NaNzVvekFBdUs5Ky9mcDJFZ1prNTQ2QkErWHFxNjdTa2UvWXQzKy9YV1N1VnAwNjB2ZUdHMlRGWDMvcFI0RC9WNkpqZXluV3FZT08zSkc4OUU4NThQNkhPdklldFF6NkZNY2M1azVXbHVPblRKaWNVZjVxemh6ZE9qZnpETzAvdjdoMWE2bmdnZVh0Q2drNjhrWHRPOTg5WXBSOVVUQ3RlTGV1RXRXN3A0NEErSnRPblRweDdqbHlGQndjTERQZWVrc3VhTkpFOS9pZVR6Lzd6QzRzcHhKMWRSNHc4TGNBNi9wWGVleG9DU3JsenBGZmY5cy9hYXFjM09Ucy9tV25xUE95ODdwWHViREp5TXgwZklhK1RKa3ljdmxsbCtuSVdVdisrRU15OGxDbzhMdnZ2OWN0Wi9YdDAwZTNDaDRKT3ZJbC90NGhrcFdTcWlOelF1dlV0ajYwSHJObjBRSDRwK3M5OU9FSTcxTDdJci8rNml0cDByaXg3dkU5YXBuN0o1OStLazJiTjdjcndDY25KK3RIVU5pRmxDc3JGUjU5V0VmdXlEeDVVaEllZkZneXJXVFlhMVRDZWZUb1VSMmhJUFRwMVV1M25MVnY3MTU3MmYrNU9IandvUHk1ZkxtT25CTVJFZUdwQXJVazZNaVhOSmZPTzQ5NWRxb0VGUzJxZXdENG0wclIwVkt2WGowZEFUa3JXN2FzelB2dU83bjgwa3QxajI5U0JaMVVCZmlMMjdhMTkxVUNTdFExMTBqUkR1MTA1STVUYTlmSi9sZGYxNUYzcUp0WjFHMG9XQjA3ZHBTUWtCQWRPZWVrZGYwNzErMCthOWF1ZFhTZi9kL2FYSHl4MFNQd3poVUpPanl2L01NUHN1OGM4SE5ObWpReE1nQ0EveXBac3FSODl1bW5NdVQrKyswemUzMlpHblMydmVRU21mdnR0N29IaFZwZ2dFU1BHaWtCTHAvOWYrREZWeVhaU3RTOUpOMUh6bXIzWjlIUjBYSnhxMVk2Y3RiWFgzK3RXN216YU5FaUl6ZHNialI0NW50ZWtLREQ4OUpVOVU3dW5nSityUnJGNFpBSFlWWUNNK21wcDJUV1J4OUpsY3FWZGE5dlNqeDRVSHIwNmlYdnZmKys3a0ZoRmw0MVJzb1BHK0xxMXI2c2xCVFpPZkl4eVhLNDBGaCtzUDNERy9yMjdhdGJ6anJYNWVyejU4L1hMZWVvYlZPbTl0bm5GUWs2UE8vZ3EyL0tzWjkvMFJFQUFQOTBUZGV1c3VxdnYrelpkRFhZOGxXcUlOYUFnUU5sMWllZjZCNFVabVZ1NkN2aERkemQrbk5xOVZyWis4SkxPaXA0eGRqZW1HdHFKVkZrWktTT25OV2hmWHY3aHFqVDFPcWgvZnYzNnlobmlZbUpzdlRQUDNYa0hIWFdlMVJVbEk2OGdRUWQrUkxab3BsdW1aT1ZtaVk3SHh3aHFidk5ub01KQVBCZFJhMkJ2SnBOLzhzYXdQWHUxY3ZZUU5XMDlQUjB1ZjJPTzJUNWloVzZCNFZWWUdpb1ZKazBRUUxDM1YzcW52ajYyNUswYXJXT0NwYXBJNzc4a1hxbTFFa1hKcWdqVUJzMmFLQWo1NmpsNnI4dFhxeWpuQzMrL1hmNyt1aTAvamZkcEZ2ZVFZS09mS2t5OVNrSkttUCtybFBHZ1VTSkgveUFKeXVNQWdDOG8zTGx5akp6eGd4WnVYeTUzSHZQUFJKVnVyUit4SGNrSlNWSi81dHZabmt2N0JvOFpXNi9UVWZ1eUZKVjNZYy9ZbGQzTDJpcU5nbjFTWElud09BTXVwcWR2N2wvZngwNTY3ZmZmdE90blAzMDAwKzY1Wnp5NWNySnBaMDY2Y2c3U05DUkx5SFdDN3ZLTTFNa0lNVE1IYnZUblZ5NlhQWTkrNEtPQUFBNE16WHJWcTFhTlprNlpZcHMyckJCM25yakRXblZzcVZQemNadDJMaFJKa3ljcUNNVVd0WnJ0dnlkdDB0b3JacTZ3eDJwY1p0bDc0c3Y2NmpncUlTelNKRWlPa0pPVkJJZEdocXFJK2QxdnZwcUNUUHc5NnVaOGR3VWZ2czFsNG44dVZEVjI5WHFLNjhoUVVlK0ZXdmRTcUtzRHc4M0pMNzh1aHo3MWZrM0tBREFQeFV2WGx6NjNYQ0QvTFJva1d4Y3QwNG1qQnRuRDhwTUREU2Q5dElycjhpK2ZmdDBoTUlxTUR4Y0trOTRVaVFvU1BlNFE0MjVUaGc0Yy9wY3FIM1A0UzVYcy9kVjVjcVdOWnFncTJydWpSczMxcEZ6VnExYVpSODVtUk43Ly9teVpUcHlUdS9ldlhYTFd3S3lEQjR1bUpXZUxwdTZ4RXJxeGpqZGs3Mm9RUU1sZXRoUUhmMlRXdGE4b1ZWN3lUaDBTUGVjV1lPMXl5WFFSL2VjbVpUNDVnelo4OFFFSFRtcllkd2FDUWdPdG4vWDIyNjlRNUorL2xVL1lrNXd1YkpTNjZ2UEpNVDZzN0E2TW4rQkpBd1lwS016SzlFalZtSW1uL24zbnBXUklYR2RZeVZsNHliZGs3MlMzYnBLbFdtVGRlUi9Uc1hIUzl4bG5lM1hzRW1CUllwSW5RWGZTWWdMVzBKTXVIL0lFSG54SlhPRmcrNis2eTZaUG0yYWpyeE5mV3cyYXRMRW51RTA1ZHR2dnBGT0hUdnF5QmxObXpXVFZhdk43U3Q5NSsyM3BXK2ZQanJ5TnZVN1BIYnNtSHd6ZDY0c3RCSjN0Y1J5eTlhdFJ2WTM1dGV3Qng2UThlUEc2Y2haYXRCYnRVWU51emlkS1h0MzdmSmNBYVovVzlleW5hUWZPS0FqYzZJbmpaY3kzV04xZE81MlRYaEtEcjcrdG83Y0VWSTFSczZiTTF1Q0NtaDhyZDZUZFJzMGtCMDdkdWdlNTZuVk51M2F0dFdSN3pxdmRtMTVhUGh3SFpueDBzc3Z5MzJEQit2SU9RdC8rRUhhdEdtam8vLzF5YWVmU3Q4YmJ0Q1JNOVM1NTFzMmJaTHc4SERkNHgwazZJV0FHd202a25id29NUmQzVTB5OXB2L2tJdHMzVkpxdlAyYUJCVFNmVWtrNk00aFFjOGRFdlQvUjRKK1pyNlVvUCtiU2dMVVRMVksyTldYbXFsUmxZVU5EcEZ5VGMxYXFabC9FNE5JRXZULzhKVUVQZVA0Y2RsNDliV1M3bkxSM05MOStrcmx4MGZaeSswTHdpVWRPdVM2a0ZoZVhIWGxsZkxsNTUvckNEbFIxOFZxTld0S21zTkg4WTE0NkNFWk8yYU1qdjdYZ050dmx4a3paK3JJR1gxNjk3YnJsWGdSUzl6aG1CRHJBN2p5bEltdUxNRktYcnhFOXI3d3Nob3A2eDRBQVBKR1ZUNnVWS21TM0Q1Z2dNeis5RlBac0hhdC9QempqM0xYSFhkSTFaZ1lZNVdSYzJQdjNyMnljdFVxSGFFd0N5cFdUQ285YVNVeGdlNE8zdzkvT0V1Ty8xbHdTOTJiWFhTUmJwbXhlczBheWNqSTBCRnlVclpzV1duWm9vV09uSlBUUG5SMUEzSHhraVU2Y2s2UDd0MTF5M3RJME9HbzRtMHZsakozdWJBZjNYb1RIM3p4VlRuK3gxTGRBUUNBTTFUUm9CYk5tOHV6enp3ajY2MWsvYWVGQzJYUVhYY1ZTRVg0ek14TStmcnJyM1dFd2s2TnMwcGMwMWxIN2xBcnpIWU9mMFF5a2dybVZJSGF0V3ZybGhrblRweXd0N3pnN0ZTaHpXdTZkdFdSYzlTS3RKU1VGQjM5MDU0OWUyVExsaTA2Y2tiNTh1WHRsUk5lUllJT3g1Vy9aNUJFTkRkN3QxUEpTa3VUbmZjOUlHa3VMS2tIQUJSTzZvaW5aczJheVRQVHBzbld6WnZscFJkZWtOcTFhdWxIM2JIa2p6OTBDNFdkT2tvcit1RmhFaFRsN3MyaXRCM3hzbnZpNUFKWnVkakN3SXp0NlZSeXZpbnU3TnR4OFIvWFhudXQ0eWRpcUpWQzI3ZHYxOUUvcVRvaFRxOXc2Tks1czlHQ2V2bEZnZzdIQllhRlNzd3pVeVNvYkJuZFkwNjZsWnduREh0WXN0SlptZ1FBTUVzZCtUVGd0dHRrNVlvVjh1VFlzUklSRWFFZk1VdnRpV2NKTHY0V1VyYXNSSThlNmZwUzl5TWZmeUxIZmpPM0Z6dzcxYXRWTTNyVW1scWw4c01QUCtnSVo2TitIODJiTmRPUmMrWmtzMUxJNlJWRTZqaTYzajE3NnNpYlNOQmhSR2lGQ2xMNTZZbi9MU0JuVXRKUHY4cSs1MS9VRVFBQVpxbFpkVlV0K2ZOUFA1VWlMaFNuVlVYc2ZIVUpyaGNyNC91RGtsZGVJY1V1ZGJhUTVObllTOTJIalpEMHc0ZDFqenZVbHBQNjllcnB5QXlWSEhxaEtLU3ZNRkVROUV5RkFKT1NraHpmZjE3UnlsRmF0MjZ0STI4aVFZY3h4ZHRjTEtYdnVFMUhaaVdxL2VpL3N3UVFBT0NlRGgwNnlQQmh3M1JranByaFUvdGtuYWFLM3ptOVZQWGYyTnRyUmtCUWtGUjYvRkVKTEZGYzk3Z2pmZDkrMlRWK2txdEwzWU9zbi9YU1RwMTBaTVpmSzFmS3RtM2JkSVN6dWVMeXl4MHZucmw4eFlyL09ROWRIWCtwS3NjN3FWdTNidmI1K2w1R2dnNXpyQS85aXZmZkl4RXRuVjhHODIvMmZ2UUhIbkw5cmk0QW1LQVNNaWVwbVNHbmo4WEJmd29tM1hiYmJjYVh1cXZmMzc4SHJrNVFnMVRUQ2JySkk5d0t1OUR5NWFYOGcwTjA1SjZqbjM4cFJ4ZjlxQ04zWEhIRkZicGxobHJwOFpaSGo5enlvaG8xYWtqREJnMTA1QXgxMU9XdTNidDE5QitMRnk5MmRHV0R1dG5UeitIejFFMGdRWWRSNnB6eUtwTW5TbENwa3JySEhIVXVhTUpESTQyZlp3MEFwaDAvZmx5M25QSEpwNS9LK2cwYmRBUW5sUzVWeXQ2VDZZdE1KK2ZLWm9lckwrT2Z5dlRxS1JGTkw5Q1JTekl6WmRkall5WDk2RkhkWVo0NlZVRWQ4V1hTakhmZXNaZFU0K3pVUHU0YisvWFRrVFBVVFpMZmZ2dE5SLzh4Wjg0YzNYSkcxYXBWcGRINTUrdkl1MGpRWVZ4WTVVcFNhZXBUOW5JczAwN01XeUQ3MzNoYlJ3RGdtNXhjMGhjZkh5LzNEUjZzSS85eThPQkJPWENnWUUveVVBTlZ0U2ZkTkRYejQ3VHc4SEFKTkp5a3EyV3JNQ2NnT0VncWozOUNBaUxDZFk4NzFLVEl6a2RIMjhtNkc5Unk2bDZHQzN1cDQ3ekdQdkdFamdxZTB5dXBuS2FPS1hPNkV2cmNiNy9WcmYvY3FQN2xYd2w3ZmwxN3pUV2VydDcrTnhKMHVLTEVKZTJrMUswMzZjaXNBMU9teS9IRnpoYVVBQUEzclhBb3FWSDdmL3ZkZUtNa0ppYnFIditoa3ZPdTExNHJ6VnEwc0Nzd0YrUmcxdlJ1WEpXY0Z5OXVacTl4NDhhTmRjc01OU05HOFMyekltclZsSEwzRHJLM0ZycnAyTGZmeTVINUMzUmtucXE4YlhyVng2dXZ2U1pyMTYzVFVjRlEyNUhlZmZkZHVlbm1tejFkWkxGYXRXcFN2WHAxSFRsREZZcjcrMmRldFdxVm95c2ExTTNVVy9yMzE1RzNrYURESGRZRnRlS1EreVM4U1NQZFljNS9xb3crTE9tSGorZ2VBSENPR2lDV0tsVktSMmFvWTdYeW05U2twS1RJTGJmZTZuZ0ZYQzlRTXl2WHhzYmF6NVBhczlqRlN0VDczM0tMN1A3WC9rVTNxTDNocG0rQWhBUUhTNGtTSlhUa3JNcVZLdW1XR2N2Ky9OTSs0eGhtbGUxL280VFZxNk1qbDJSbXlhNlJveVhOcFZVc3paczNOMTdOL1lTVkVLcWJta2RkWEw3L04zWE5YN2x5cFZ4NitlVnl5NEFCOHZHc1dmTHNjODk1OWdhWFdqblU3L3JyZGVRTWRlTjExNjVkZGxzbDYwNys3T2ZWcmkyMXJTOWZRSUlPMXdSR1JFak1jMU1sME5Bc3dPblNkKzM1ei9ub0hsOGVCTUEzbVM0S3Ruck5HbG03ZHEyT3p0M0preWZsWmlzNS85TGgvWHRlb0txWjkrN2JWNWI4OGY4bmQ2Z3p3ai84NkNOcGZPR0Y4dFNrU1VZcW5tZm5wNTkvTm41am9FbVRKc2FXMFZjeW5LQ3IzOFhqWThia2VhRE5NVzI1RXhnZUxsVW1QR25YL25GVHhzRkRzdk94c1NxNzFEM21xSlVrUTF6WXJyUEd1dmIyNnRQSDhWb2dPVkZKNlcyMzN5NHRMNzc0djhlTnFmZk1xTkdqWmY3OCtYYnNSZGZGeGpxNi9VYmQ4RlEzOVJTbno2YnYwcVdMNDVYblRTRkJoNnZDS2xlV1NsTW02TWlzRS9NWHlZRjMzdE1SQURqSDFHem02Y1pQbkppbnBFWU45R0s3ZDdjTHcva2JOV0R1ZThNTk1pK2JnZHVSSTBmazBjY2VrenIxNjh1MDZkT056MnlyL2UrRGg1aXZvbjNoaFJmcWx2TmF0MnFsVytiTWZPODllZU9OTjg3cDlieHAweVlaUEhTb3RHdmZua3J3dVJUWm9MNUUzZUxPZHNMVEhaODNYdzU5OFpXT3pGSUpZYVhvYUIyWnMyRGhRbW5UcnAyc1c3OWU5NWl4ZGRzMkdUWjh1TlJyMEVCbXZ2dnUvOXlRVXE5OXRUcG8rL2J0dXNkYjFCTDNlblhyNnNnWjM4K2JaMi9QK3ZIbm4zV1BNMjZ6bmtkZlFZSU8xNVc4ckpORTNUbEFSMmJ0bnpSVmtsYXQxaEVBT01QcDQyWE9SQ1hZTDczOGNxNlRHalh6OE43Nzc4dEZ6WnZML0FYdTdRdDFpMXF5UDJEZ1FQbjJ1KzkwVC9aVWtiM2hEejhzTld2WHRndmtMVjI2MVBGajVyWlpBK2JPWGJ2YUEyeVQxTDVKazhXeGF0V3FaWDhQazlSemY4OTk5OW1KeHVyVnE4K1ljS3ZYNzBZcktYL25uWGZreXF1dmxrWVhYQ0F2dlBpaXZZMUJKUzdJaFlBQXFYRC9QUkphdmFydWNJbDFqZG96N2lsSmRXRXJRN0ZpeGVUUmtTTjFaSlpLemx1MmJtMnZ5am5zNERHK2FvV1RtaFZYSzRIcU4yd28wNTk5Vms3bWNJemkvZ01INU5ycnJuTjFaVkJ1cVpVOXZYdjEwcEV6Vk4wS2RjMTJzcTdJQmRiMVJCME41eXRJMEZFZ0tneStUOElhbU4xSHBHUlpGOEdFK3g3Z2ZIUUFqbExGY1V4VGlmblFCeDZRSVVPSDJyTW5haG4zdjZrK2RYYXNLaWpVdEZrenVlVzIyeVR4NEVIOXFQOVF5WnY2MlQ2YlBWdjM1RTZ5OVJtZ2JuSzBiZDllNmpab0lJODkvcmdzc3hJK05UdVRsOVVKYXNDb0tqMVBmT29wYVhMaGhiTGlyNy8wSStaVXJseFp6cmNHOGFhb0diQ1NKYzBmaFpwaFBYY2ZmUGloTkcvVlNpckZ4TmhKdU5xRzBjZEtVbHBkZkxGVXJscFZMckNlMDlzR0RyUnZNSjMrZWxlL043VTNGV2VubHJwWEdqZFdyUWZYUGU3SU9IUklkbzRjTFZrWjVyY1dYbi85OVViZkU2ZFR5YlJhbFZPM2ZuMTVjUGh3V2I1OCtUa255dXExckZienFPMHdhbFZJblhyMTVLb3VYZXpyMlptdTYyZXlidDA2dWVPdXV6eFoyVjBsNkU3ZTVOdXdjYU44OXZubmVicEdaMGRWYnpkOUk5SkpBZFlQNzl4UC95K3FXTmVtTHJHU3VqRk85MlF2YXRCQWlSNDJWRWYvbEptYUtodGF0YmZmL0RscHNIYTVCRVpHNmdoL1MzeHpodXg1d3N5eThvWnhheVFnai9zNVRtM2JMbHU2WGllWlNjbTZ4NXlpVjE0bTFaNmY3c3BSYjI1UVZWTVRCZ3pTMFptVjZCRXJNWlBQL0h2UHNqNFE0anJIU3NyR1Rib25leVc3ZFpVcTB5YnJ5UCtjaW8rWHVNczZHejgvUDdCSUVhbXo0RHNKS1JPbGUzekwvVU9HeUlzdnZhUWo1OTF0RFR5bVQ1dW1JKy83YStWS2FkNnlwYU1EaUp5bzQ3QnFXSW1VT2d2NDcyUktMZWYrZmNrUzJibHJsNnQ3SmJQenp0dHZTOTgrZlhUa0hEVnpyaEk1cDVic3F5Si9aYUtpN0pzc0hUdDBrUFBQUDk4dVBGVzZkR203VXJyYVQ2bSsxTUJaZmFtWk0xV0k3cGRmZnBIdnZ2OWUvc3pEQUQwL0huM2tFUmx0SlFnbVhkdXRtM3h6MnZGR1hqVDR2dnRrOHFSSk9uTFd1cGJ0Sk4yRlFtZlJrOFpMbWU2eE9qTEl1aTRsUERaR0RyLy9rZTV3aWZYZXF2VFVPSWx5NFdmODJYby9xbUpxQlpHd2xpOWYzaTQ0MXJKRkM2bFFzYUo5YlZiWGpyRFFVRW0zcmhscW1icTZxYXFLSThiRnhjbXZpeGZMZ2YzNzVlaXhZL3B2eUx1bkpreVFvUzVzcXprWDZuZlF1azBiKzlyb2xMK3Z3VTVRMS95MXExYjVUSUU0aFJsMEZKanc2dFVrMnJxUWl3dDN0RTU4TzA4T3pKaXBJd0RJSHpVNGk3Q1NacmVvR1dTMTNQS3RHVE5rMmpQUDJGK3F2WDdEQms4azU2YW9nYTdhNCsza2ZucDFVK1ZBWXFLOWRQcXB5Wk9sMzAwM3lZWE5ta20xbWpXbGRObXlVclZHRFh2WmFZeVZ3S3U0NW5ubjJmdWdIM24wVWZueHA1OWNUYzdWVFlONzc3bEhSK2IwTVhCanhXa3Z2ZktLYkxLU0hlU0NXdW8rK0Y0SktsZFdkN2pFZW0vdG5UaFpVdmZ0MHgzbVhOeTZkWUVkbWFWV0xha2JCSk9mZmxvZWVQQkJ1K1pIcDhzdWt6YVhYQ0x0TzNhMGJ4eW83VGhxNW4zR3pKbXllZk5tUjVKelpmVGpqOXY3NDcxRXpVeDM2OVpOUjg1d0tqbFhMbWpTeEtlU2M0VUVIUVdxMUZWWFNLbSt6dTVkeWM3K3lkTWxlVzNCbm0wSndEOUVSa1pLaHc0ZGRBUVRWSEorLytEQjh2cWJiK29lZDZpVkNmRUpDWTROcVBOajBKMTMya202YVpkMjZpVEZpeFhUa1RlcGxSUVBQZnl3YTZ0V2ZGMUlWSlJVR2pQS2xVbVEwMlVjT2l3Snd4OHh2eXJOK3JtZW5qTEY4UUpsWG5mS2VoL2MxTCsvN05peFEvZDR3NVdYWDI3UFZIdlJEUTRmQmVjR0VuUVVMT3NDR3oxcWhJU2ZiNzdnVXRhcFU1Snc3MURKT082OUloc0FmRS9QSGoxMEMwNVRTeVlmSERaTVhuMzlkZDFUK0RTb1gxOGVmdWdoSFpsVnBrd1p1ZXl5eTNUa1hWOS84NDBzK3ZGSEhlRnNTbHphU1lwZDNrbEg3a242ZGJFY25HWCtGSWtpUllySXpCa3o3TUp4aGNtKy9mdnRXWHN2clo1cTFLaVJKNHV3aFlhR1N0ZXVYWFhrTzBqUVVlQUN3OElrNW9WbkpMQllVZDFqVHVxMjdaTHcwRWg3RHpZQTVJZWFkVlFEUkRoTExXMThjdHc0ZWZIbGwzVlA0YU1HbGE5YVAzK1k5Zm5vQmpYejljakREenQ2bnJFSmF2WjgrRU1QY2V4YUxnVUVCa3Jsc2FNbEtNcjhLb3gvc0g1UGU4WlBrbE03NG5XSE9ZMGJONVkzWDMvZGZzOFVKcXZYckpGQjk5emo2Rkx3L0ZBckdrelVJTW12cGhkZUtOV3F1bnlxZ1FOSTBPRUpZVlVxUy9TVGo5c3o2cVlkLzI2ZUhQendZeDBCUU42b1FrR3hEdSs3TXkwcUtrb3VhZGRPUjk2akVyQkpreWZMdUFrVEN1MVNacFVrUHpOdG1qUnYzbHozdUVNVnkrdmFwWXVPdkVzVmFIeG5KalZsY2tzdGRhL3cwSVAydm5RM1pTVW55ODdoSXlUTGhTSnVxa0wzK0NlZjlPd1NhMU0rL09nam1mTDAwem9xZUYwN2Q3WVRkUy9wZitPTlB2bTZJRUdIWjVUcTJsbEs5cnBPUndaWkh4Wjd4MCtTNUhYcmRRY0E1TTJ3Qng3d21aa2I5ZTk4N2VXWDdVcndYcVVHVWwyc1FWNnRtalYxVCtHaUJyY1BEeDh1dDkxNnErNXhqM3J1eHo3K3VHdXo5dm54eExoeGRxMEE1RTVVN0xWU3BPM0ZPbkpQOHJMbGN1Q3RHVG95UjcxMlZUSEZ4dzJmZHVCRlU2ZFA5OHdSaE9vbVg2WG9hQjBWdktKRmk4cFZWMTJsSTk5Q2dnN3ZzQzZ3MFNOSFNGZ2Q4NVVXczVKUFN2eGQ5MG1HSDFjL0JtQmV2WHIxN0R2MHZrQU5YdFZldkppWUdOM2pUV3FROS92aXhmYlp1b1ZwUml3NE9GaEdQUFNRUERacVZJSDkzT3Ixckk1MTgvcnp2bnYzYmhrL2NhS09jRmFCZ1ZKcDlFZ0ppSWpRSGU3Wi8reUxraEp2ZnFtN3VyazE0dUdINVpXWFhwTElBdmc1QzRKYXZyMXcvbng3WlpRWGhJU0V5STM5K3VtbzRGM1V0S2xVckZoUlI3NkZCQjJlRWxTMGlNUzgrS3dFRmpkZjhDTXRQa0Yyamh4dDc1VUNnTHhRaWN5VFR6d2hWU3BYMWozZW8vNk5JMGVNa0FjZmVNQ082NXgzbnYybmx4VXJXdFF1L3ZUQnUrOUt4UW9WZEsvL1V1ZmNQenQ5dW4zZWVVRXZFWDFnNkZEcDBMNjlqcnpyUlNzUjI3aHhvNDV3TnVIVnFrbjVZVVBzeVJBM1paNDRJZkZEaDB1bUMzVUQxTFh1MWx0dWtkbWZmU1pseTdwOHhKeUxTcFFvSVUrT0hTcy9MVm9rOWV2VjA3M2VjRjFzckdkcVdWemZ0Ni9uYnpabWh3UWRuaE5lbzdwVWZNSktuRjBZcEJ5Yk0xY1NQL2hJUndCdzd0UXhXSysvK3Fvbmw3cXJXVmsxSTNyNnJHeTVjdVhzUDcxTy9YdTdkKzh1Znk1ZEtqZjE2K2NUUzYvem9tclZxdkxObkRseSs0QUJuaGhNcWxtdzkyYk9sRWJubjY5N3ZNaytkbTNFaUVKYnF5QXZ5dlRwTGVFTjYrdklQU2YvV2lVSDNucEhSK1oxN05CQmZ2LzFWL3VzZEY5TjBNNUVKYjZYWFhxcC9QbkhIL0xROE9HZS9NeFJxM0M4TUd1dEt2dXIyZ1MraWdRZG5sU3F5OVZTc3FjTCs5R3REL1o5NDU2U2szR2JkUWNBbkx1T0hUdksxQ2xUQ256MjgzUnFtZWNMeno0cmo0NGMrWTkvVjZsU3BYeHEwS3Btd2w1LzdUWDUrY2NmcFhXclZwNTZqdk5ESmNLMzlPOHZTMzc3VGRxMmFhTjd2VUVkdS9iRjdObWVUOUxWc1d2ejVzM1RFYzRtTUN4VXFqdzFYZ0xjdnRsbGpiVU9QUCtTcTJNdHRaWG51N2x6WmR3VFQ5aDdrWDJadWw0M2FOQkF2dmpzTTVuejVaZjJUVDJ2VWpjTmVuYnZycU9DbzY2cDZyUE9WNUdndzVQVTBTRHFmUFN3dXVhWFltYXEvZWlEN3BlTXBHVGRBd0RuYnVEdHQ5dVZoTDJRUUtvbDkzTysra3B1dmZYVy8vbjNxSmtGVllIZWw2Z0I2Z1ZObXNpQ0gzNlFMNjNFVVNYcXZrenRqZnplU2g1ZWVmbGx6K3dmL2JmSzFtdElKVGhxTnRLTDFHdENuVWhReWNQYlM3d280cnphVW1hZyswVUlNNU9USldIWXc1S1pscVo3ekZPcmJvWTkrS0Q4c1hpeGRMdm1HcCtjVGE5YnA0NjgvY1liOW8yOEs2NjR3aWR1VUhyaHVEVmZyMkZDZ2c3UENpcFNSS3BNbXl5Qkxwd3puTHA1aSt4NmJJeGQ0UjBBOGtJTkJ0VCszYmRlZjkzZVExMFExTCtoMy9YWDI4dkNzNXVWVlRNY0JmWHZ5eSsxeEZNTlVoY3RXQ0FMNXMyVFhqMTcrc3haOU9wM294THo5OTk5VjM3OStXZHBZLzErdkQ2QVZEUHBhc1pPRmE4TDk5QVdBMVVjNjRQMzNwUHZ2LzFXR3RSM2Y4bTJUN05lYytYdnVsUENyRVRkYmFkV3I1Vjl6NzJvSS9mVXJsMWJabjM4c2Z5NGNLRmNjZm5sbmovdlgxSEw4ejk4LzMxWjhlZWZjcjExVGZlbExUNXFtWHYxNnRWMTVMN2l4WXY3eEpHUk9TRkJoNmRGMUswakZjZU9zbDZwNWwrcVJ6Ly9TZzdPL2tKSEFKQTNhakMxZE1rU1Y4OGJWM3ZOMjdWdEt6OHZXaVJ2dnZGR2prdjcxTkpxTll2dXkxUmkyOWI2ZWRWZTZhMXhjZkxVeElseTRRVVgyTStEMTZpQ1RqMnV1MDUrWExEQVRzeDc5dWpoVTh2MDFldGw3Smd4c21UeFl1blVzV09CUGNlcWtKNzYvcDk5OG9uOVBIYTNubE4vMmU3Z05yWFV2ZEs0TWVyQ29YdmNrL2pxRzVLOHZtQ091VzNWc3FWODljVVhzbHpYdFNqanNkVXJhdSsyT21MeEx5c3BWNnVGMUd2Y2k5ZTBzMUh2MWRodTNYVGtQbldkOFBuUHVDeUQxVFd5MHRObFU1ZFlTZDBZcDN1eUZ6Vm9vRVFQRzZxamYxS1ZIemUwYWk4Wmh3N3Buak5yc0hhNUJFWkc2Z2gvUzN4emh1eDVZb0tPbk5Vd2JvMEVHTDU0WkdWbVNzS0lSK1hveDUvcEhuTUNySUZJemE4K2tZZzZkWFNQTngyWnYwQVNCZ3pTMFptVjZCRXJNWlBQL0h2UHlzaVF1TTZ4a3JKeGsrN0pYc2x1WGUyVkRQNHE3Y0FCMlRWdW92V2NtRjA5WVErSUhudFVnbDA0b2NDRUdlKzhJL09zQVlNcGwzYnFKRGYzNzY4ai81Qmh2YysrbWpOSHhvd2RLK3MzYkxCanB4V3hQdk5Vb3ZySXd3OUw4K2JOY3owenBDcGcvMllsWEU0YWRPZWQwcnAxYXgyNVR6Mi9PK0xqNVF0ckFQNjU5YlYyM1RvNWV2U29mdFE5NnVaQnlaSWxwZGxGRjltSmVUZHJvT3JMZXlGUGwybDlIcTlZc2NJKzRtekJ3b1Z5NHNRSi9ZZ1phdGF3Um8wYTlwN1cvamZkWkMrN041R1VKNHdjTGVuSGp1bkluS2pyKzBqeFZpMTBWUEQydi9tMkpLMVlxU1AzaEo5WFd5cmVjNWM5bTErUTFQVmg3dHk1TW1QbVRQbHorWEk1ZlBpd2ZzUWQ2bnF0aW94MnVPUVNPekZ2MmJLbFJQcEpIcU0rODhhTkg2K2ovM1V5T1ZtK3RwNTdFNStMNnNhdFdsM2x5MGpRQ3dGZlQ5Q1ZET3VEYy9OMXZTVjF5emJkWTA1WTdWcFM2OHRQSkRBOFhQZDREd2s2NER2UzB0TGtqNlZMNVpWWFhwRzUzMzRyeDYya0pxK0Rra0JyUUt0bU5GVXlyZ1lnbmErKzJrNWF2TDVVMm0xcWFIUHc0RUZadlhxMWZQdmRkL2JnZThrZmYwaTZOUzVSWDA1U00xeHFvSzBTOGhiVzcrVnE2M2VpaXF1cEpOMmZxYlBJdjdFRzJMTSsrY1IrYmsrZVBHa244UG1oWHR0cXhVRnJLMUZSUzFUYnRXdG5GOFR5aFNYSjhHMUhqaHl4cnhPcThPRGl4WXRsOVpvMTlyWEN5UVJTWFN2VWxoeDFyYmo4c3N1a2ZmdjI5aDd6aUVKeWJ2dnBQcHM5VzNyMzdhc2o1NmpuZDFkOHZNOXNmY29PQ1hvaDRBOEp1cEs4YnIxczdYbURaQ1diTCtaV3NuY1BxVExoaVFLL3U1c2RFblRBTjUwNmRVcldXQU0vbGJELy92dnZFcCtRSUlsV0lobHZEU2hVZ25NNnRmKzNmTGx5ZGhFeFZmU3RXYk5tMHJCaFEybmNxSkhmSjM4bXBGcGppWjA3ZDhxYXRXdnRQemZGeGNuV3JWdnRnYm1hU1V0S1NySm40TTlFL1E2aVNwZTJuM2UxdjdHYWxUVFdxMXRYcXNURTJMK1R5cFVxRmNwQjl0L1VjN2ZXZWw1WHJsb2w2OWV2dDJmUDFHeWtlbDYzYk5raS94NW9Wb3FPdG1jTzFaYzY1LzZDQ3k2UW1qVnJTaVBydFIxVHBRb0pPUXFjV2gyeWJkczJleVdPdWw2b20xREhqaDJ6djlRMVkvZWVQWko4aHZHb1NneWpLMWEwYnpTcDY0VzZnYXB1MkttcTh1ZGIxNG9xMXV0YjNZZ3F6TlJuWFl2V3JlMXJoZFA2M1hDRHZQWEdHenJ5WFNUb2hZQy9KT2lLT3JOOHp5T2pkV1JXcFdjbVMrbHJ1dXJJVzBqUUFmOXh0bzloWnNmTnkrMVFpTi9GdWNucGVlVzVoSy9LemZXQzEzZjJYbnY5ZFJsMHp6MDZjbzY2c2ZmRGQ5L1pCVGg5SFFsNklYQms5aGR5NE9YWGRlU3NXbDkvYmlYb0x0N3B0bDZ1dTZjOUt5bWJ6djZheXEvQVlzV2s4cGhSRXVUQjF4UUpPZ0FBQUh6SnZuMzdwUEVGRjhqQnMrUjBlYUcyQy95MWZMbGZyTUFoUVFkOEVBazZBQUFBZklWS09XKzU5Vlo1NzRNUGRJOXoxSXFGMTE1NXhTNG02UTg0bndJQUFBQUFZTXo3Vm1KdUlqbFh5cFVySjlmRnh1ckk5NUdnQXdBQUFBQ00rUFhYWDQzc08vL2JuUU1IK3Z6WjU2Y2pRUWNBQUFBQU9HN1Y2dFhTcTArZk0xYTlkMExGaWhYbHZudnYxWkYvSUVFSEFBQUFBRGhxL29JRmN2a1ZWOGorQXdkMGovT0dQL2lnZmZ5bFB5RkJCd0FBQUFBNElpMHRUWjUvNFFXNU5qYldTTVgydjlXdFcxY0czbjY3anZ3SENUb0FBQUFBSUY5VXBmYjE2OWZMMVYyNnlKQUhIcENVbEJUOWlQTlU1Zllwa3laSmFHaW83dkVmSk9nQUFBQUFnRHpic0dHRDNEbG9rRnpZckprcyt2RkgzV3RPcng0OTVJckxMOWVSZnlGQkJ3QUFBQUNjazBPSERzbnN6eitYemwyNlNLTUxMcEEzMzNwTDB0UFQ5YVBtUkZlc0tNOU1uNjRqLzBPQ0RnQUFBQURJVVZKU2txeGJ0MDdlZXZ0dGliM3VPcWxlcTVaZG9mMzdIMzZ3bDdlN0lUdzhYRDU0N3oySmlvclNQZjZIQkIwQUFBQUFJSm1abVhMcTFDbDdkbnpEeG8zeTFadzVNdXF4eCtUeUs2K1VXblhxMkV2WUI5NTVwOHo1NWh0alI2ZGxKekF3VUI1NzlGRnAzYnExN3ZGUEpPZ0FBQUFBVU1pZE9IRkNXcmRwSTQyYU5KRWF0V3ZMK1kwYnkzVTllc2pFU1pOazRhSkZrcGlZS0JrWkdmcS9kbCtmWHIxazZKQWhPdkpmSk9nQUFBQUFVTWdWS1ZKRWR1N2FKZHUyYjdlWHMzdEoyelp0NU9XWFhwS2dvQ0RkNDc5STBBRUFBQUNna0ZOSGw3VnUxVXBIM3RIMHdndmwwMW16SkNJaVF2ZjROeEowQUFBQUFJRFVPZTg4M2ZLR2kxdTNscm5mZkNPbFNwWFNQZjZQQkIwQUFBQUFJTTJhTmRPdGdxVm04Ni9wMGtXK25qTkhTcFVzcVhzTEJ4SjBBQUFBQUlCVXFWeFp0d3FPU3M2SDNIKy9mUGpCQjFJa01sTDNGaDRrNkFBQUFBQUFpWW1Ka1dMRml1bklmU1ZLbEpCM1o4eVFweVpPbEpDUUVOMWJ1SkNnQXdBQUFBQ2tlUEhpRWg0V3BpUDNCQVlFeUdXWFhpckxseTZWWHIxNjZkN0NpUVFkQUFBQUFHRFBXcnU5RHoyNllrVjU2Y1VYNWFzdnZyQm44QXM3RW5RQUFBQUFnSzFCZ3dhNlpWWmtSSVRjUFdpUXJGeXhRbTY5NVpaQ2NjWjVicENnQXdBQUFBQnNGelpwb2x0bWhJZUh5eDBEQjhyS3YvNlM2Vk9uU3NsQ1ZxWDliRWpRQVFBQUFBQzJPblhxNkphenFzYkV5TmpISDVmTkd6Zks4ODgrSzlXcVZ0V1A0SFFrNkFBQUFBQUFXM1IwdEJRdFVrUkgrVlBKK3J2NlhYKzlmRDkzcm14Y3YxNUdQUHl3bEM5ZlhqK0tNeUZCQndBQUFBRFlpaFl0S3VYeW1FU3IvMitkODg2VE8rKzRReGJObnk4YjFxMlR0OTU4VXpwMDZNQWU4MXdpUVFjQUFBQUEyTUxDd2lTbVNoVWRuVmxBUUlCZDVFM3RIMjkveVNWeTM3MzN5dHl2djVZTmE5ZmFSZCtlZStZWnVmamlpKzM5NWpnM0pPZ0FBQUFBZ1A5cTJhS0YvV2U1c21XbGNlUEcwckZEQjdrdU50WmVvajV6eGd5WlAyK2VyTGVTOFYzeDhUTHZ1Ky9rNmNtVDVkSk9uZXpsNjh5VTV3OEpPZ0FBQUFEZ3YwWTkrcWlrblRvbHV4SVNaTm1TSmZMZDNMbnkwUWNmMkVYZSt2VHVMVzNidExIM3FvZUdodXIvQjV4Q2dnNEFBQUFBK0M4Uzc0SkRnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUh1QWpDWHFBL2IrenlUeDFTcmNBLzVhWmZGSzNjaERFL1RjQUFBREFsL2pFQ0Q0d05FU0NpaFhUVWZhU1ZxM1JMY0MvblZ5MlhMZXlGeEpWUnJjQUFBQUErQUtmbVdJTHY2Q3hibVh2Nk5kemRRdndYMWxwYVhMc2gvazZ5bDVvNVdqZEFnQUFBT0FMZkNaQmp6eS9vVzVsNzhTOEJaSis2SkNPQVA5MDdKZGZKWDNQUGgxbEw3SkZNOTBDQUFBQTRBdDhKa0V2ZW5FcjYxK2I4MGIwaktOSFpmZFRUNHRrWnVvZXdMOWtKQ2ZMM3ZHVFJMS3lkTStaQlpVdkorSFZxdWtJQUFBQWdDL3dtUVE5ckZwVkNhMWVYVWZaTy9ycDU1TDR5V2M2QXZ4SFZucTY3Qm81V2xJM2I5VTkyU3ZlcVlNRUJQck0yeHNBQUFDQXhXZEc4SUdob1ZLcVYzY2Q1U0FqUS9hT2ZGd092UE91WkZsdHdCOWtKQ1ZKL0lNUHk5RXY1dWllSEZpSmVhbmVQWFFBQUFBQXdGZjQxQlJiVk4vZUVsU3FwSTZ5cDJZYTl6NCtUcmJmZnBlYzJycU5KZS93V2VxMWZPeW5YMlR6dFQzbG1Fck96N0swWFlsc2NaRVV5VVhOQmdBQUFBRGVFcEJsMFczSHFlUmlVNWRZU2QwWXAzdXlGelZvb0VRUEc2cWo3TzEvNVhYWk4zR0tqczR1SURoWUlwbzFsYUx0MjBsRXJSb1NWTGFzZmdUd3FLeE1TWXZmSlNjM2JwVGozLzhnS1pzMjZ3Zk9MaUEwUkdwOCtvRkVOc3c1UVZlclMrSTZ4MHJLeGsyNkozc2x1M1dWS3RNbTZ3Z0FBQUNBS1Q2WG9HZW1wc25tMko2U3NtNkQ3Z0h3dDFJM1hTK1Z4enltbyt5Um9BTUFBQURlNDNOVnBBSkRRNlRLMUVrU1dLU0k3Z0dnaE5Xdks5RWpodXNJQUFBQWdLOHhtNkFIQkZqL3kvbG90UDlLVDllTnM0dW9jNTVVbWo1SkFrSkNkQTlRdUFWWEtDL1ZYbjlKQXNQRGRjOVpxSFV6dVZ3OG83YUpBQUFBQUREUGVJSWVHSm03bWU3Y0hCMTF1cEtkT2tyRjhXUHNQYmRBWVJZVVZWcXF2ZjJhaEZhc3FIdk9MaXN0VlRLT0g5ZFJ6b0tyVjlVdEFBQUFBQ1laVGREVk9jekJ1YWk2cnB6YXNVTzNjc2xLL3FONlhDZFZYbmxCQW9zWDA1MUE0UkphcDdiVStPUjllMVhKdVVnL2RGalM5eC9RVWM1Q0tsVFFMUUFBQUFBbUdkK0RIblorZmQzS1dkcVdiWkt5YzZlT2NxOUUrM1pTNjh0UEpLSjVVOTBEK0QrMTdMeGszMTVTNjdPUEpMeGFOZDJiZThjWC95NlNrYUdqSEFRRVNGaVZ5am9BQUFBQVlKTHhCRDNpdk56UDdCMysrRFBkT2pkaFZhdEt6ZmZma2VoSjR5U2thaFhkQy9paG9DQ0phSGFoVlAvNFhha3lib3dFUlVicUIzSlBWWEEvL1BFbk9zcFpZRVM0aEZVLzl4c0FBQUFBQU02ZDBXUFdsTFRFZzdLaFJWdVJ6RXpkazcyUXlwWGt2Ty9uV0VsQmhPNDVkNWtwS1hMc3g1L2w0RHZ2eXFuVmF5WHpXTzcyMlFLZXBiYUtSSldXeU5ZdHBjeUFteVd5WGowSnNCTDF2RXBhdFZxMmRlOXJINE40TnFFMXFrdWRINzZ4WjlJQkFBQUFtR1U4UVZjMlhkdERVbGF0MFZIT3lnNjVWeXJjZDdlTzhpZjl5QkU1dVhHVEpDOWZJU21iTmt2NnNXT1NsWnFtSHdXOEt5Z3lRb0tLRjVmd0N4cExrU2FOSmF4YU5ic3Z2MVJTdnFYdlRYSnkyWExkazdQU3QvV1hTbytPMEJFQUFBQUFrMXhKMFBlOS9KcnNmK3BwSGVVc01ESlNxbi95bmoxTENNQlpCOTU1VC9ZKy9tVHVqbGdMQ3BTYVgzNHFrZlY1THdJQUFBQnVNTDRIWFNuWithcGNMOG5OVEU2VytEdnZ5MVBCT0FEWk83cndSOWszYm1LdXp6OFBxMVZUSXM2cnJTTUFBQUFBcHJtU29Lc3EwRVd2dmtKSFo1Y1dueUJiKzl3b0p6ZHYwVDBBOHN4S3lJOTgrNzBrM0hYdk9XM3hpTHJsSnJ0YVBBQUFBQUIzdUpLZ0srWHV2UDJjQnZ2cHUvYkkxdGplY3VqekwzTlZ6QXJBLzhvNGNVSjJUWmdrQ2ZjTWtheVVWTjE3ZGlIVnFrcXAyR3QxQkFBQUFNQU5yaVhva2ZYcVN2SFlyanJLblV5VlhBeDlTTGJjY0xPY1dMcU1SQjNJcGN4VHArVGdwN01sN29xdWN1aTF0M0ozNXZuZkFnS2szSDJESkRBMFZIY0FBQUFBY0lNclJlTCtsbllnVWVJNmQ1TU02ODl6WmlVTm9UVnJTTkYyRjB1UkM1clk3YUFTSmZTRFFDR1hsU25wK3cvSXFVMXhrclJrcVp6NGRiRmtXSEZlRkxIZVk5WGZlazBDQWwyN2Z3Y0FBQURBNG1xQ3JoejVZWUc5RjFiU3oyRkdMenVjelF6OFB3ZmV5b0VsaWt1dE9iTWxySElsM1FNQUFBREFMYTRuNkNxSjJEUHBhVWw4K1hYZEFjQUxBc0pDSmViVkY2VjR1emE2QndBQUFJQ2IzRi9ER2hBZ0ZSNGNJaVd1b3dBVjRCbEJnVkpoOUVpU2N3QUFBS0FBRmNnbVUzVW1ldVZ4WTZUb3BSMTBENEFDRXhnbzVSNFlMR1g2OU5JZEFBQUFBQXFDKzB2Y1Q1T1ZtaW83SHhzclJ6NzZSUGNBY0pOYTFsNXh6Q2lKNnQxVDl3QUFBQUFvS0FXYW9OdXNiNS80M2dleWI4SVV5VXhPMXAwQVRBdUpxU3lWcDB5VW9zMHUwajBBQUFBQUNsTEJKK2phcWUzYlplZURJK1RrOGhWVzBxNDdBVGd1SURSVVNsemJSYUlmZTBTQ2loYlZ2UUFBQUFBS21tY1NkQ1VyUFYyT2ZQK0Q3SnM4VGRKMnhOdXo2d0NjRVJBU0xCRk5HdHRMMmlQcjFyRTZPS1lRQUFBQThCSlBKZWgveTB4SmtlTy9McGJFTjk2V2szOHNzeE4zQUhsZ0plR0JSU0tsMkdXZHBNeXROMGxrL2ZwMlVUZ0FBQUFBM3VQSkJQMTBxZnYzeS9GRlAwblNiNy9MeVkyYkpHM0xOc2xLUzlPUEF2aTNBQ3NoRDZ0VlV5SWJueTlGMjdhUm9xMWFTRkNSSXZwUkFBQUFBRjdsK1FUOUg2eC9xcHBOVHp0OFJESk9ISmYwZzRja0t6TlRQd2dVWG9IaFlSSlV2SVFFbHl3cHdTV0tTd0N6NUFBQUFJRFA4YTBFSFFBQUFBQUFQOFUwR3dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBRlR1VC9BRWk0UGhzV0RwQ2hBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTItMjEiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlRydXN0a2V5IFNvbHV0aW9ucyBUMzEwIFUyRiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAyMDA4MTQwMDMiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjAuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMi0yMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMTItMjEifSx7ImFhZ3VpZCI6IjYwMjhiMDE3LWIxZDQtNGMwMi1iNGIzLWFmY2RhZmM5NmJiMiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNjAyOGIwMTctYjFkNC00YzAyLWI0YjMtYWZjZGFmYzk2YmIyIiwiZGVzY3JpcHRpb24iOiJXaW5kb3dzIEhlbGxvIFNvZnR3YXJlIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInJzYXNzYV9wa2NzdjE1X3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImV5ZXByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmFjZXByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJpc0tleVJlc3RyaWN0ZWQiOmZhbHNlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOltdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFZ0FBQUJJQ0FZQUFBQlY3Yk5IQUFBQ2tVbEVRVlI0MnV5YWkzR0RNQXlHUXllZ0d6QUNuYUNNa0JIb0Joa2huU0FqMEEyU0RhQVQwRTZRYkVBM2NPWFc2WEVwQnRuSW1Ndjl1dE9sbHhqRi9xS0hMVGRSU20wZ2Rua0FBZ0FDSUFBQ0lBQUNJQUFDSUFnQUFSQUFBUkFBQVJBQUFSQkVBRkNTSklOS2twTHVTVHRTWmJRejc2VzI1emhLa3BGV1BidGF6NlE3NXZQdW9sdXVQbXF4bFpLMnlpNzZzOVJ6bmpscE4ySzdDckZXYVVBSE5TMEhUMEF0dzNZcERTanhiZG9QdWF6aUczdWs1NzljdklkZVdzYlFEN0w3TkFZb1dwS21MeThjaHVlTzVyZUI3S0tLclFuUUpkRFluOUFKWkhjNVFCVDdlbklOWTJoanhycUl0c3ZKV1NkeEZ4S3VZbE9sV0ptRTZ6UFBjc0p1TjdXRmlGN21lNURPQXdzNE95WnlHNlRPc3IvS1F6aURhSm0vbWN5MlYxVjArVDBKZVh4cXFscldDOW1HR3kzTzZ3d0ZhSTBTZFIrRU1nOUFFQUFDSUFCeXFWaVpiKy9wcmdGZE42cWIzMDZqM2xUV3MwQko3NlFqdzBrdE8rM2FkNjBQUWhNcmZNOVl3cUs3bFVQZTRqKy9PUjQwY0RhcUplSit4bzgwSnNXaWgxV1RCQWNiOHlzS3JiK1Rmb3dRS3kzdjU1d2JCa2s0OUZKYlF1c3FyNHNuYWRMOWhFdFhDM25PMUcxSEc2VWZ4SWo1b0RuSmxIUE9WVkFlcldHbXZZUXh3YzcwaGlUaDdCaWR5My8zWkZFNmlzeGY4ZXBOaFVDbDRuNWZ0WXFXS3pNUDNJSXF1YUZucXVYTzBzWjF5bi9SV3E2OVN1SzZHZFBYT1JmU3o0SFBuazFiTlhPMCtVWnplNUhxS0lvZE5Zd25IVlZjT1Vpdk5jU3R4ajRDR0ZZaFdBV2dYZ211RjRKemRNaG42d0RVbTFEcG1GeVZZN0l2UXFlVFJkb2QydjJGOGxObi9nY3BXK3JVc09pOW1BbUZ3bFNvM1B3OUpRM3ArOGJoZ25BTWtQTTYxM0J4T0JRcWMyRkVCNFNtUFFTQUFBaUFBQWlBQUFpQUFBaUFJQUFFUUFBRVFBQUVRUGNvM3dJTUFET1hnRmhPVGdodUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiI2MDI4YjAxN2IxZDQ0YzAyYjRiM2FmY2RhZmM5NmJiMiIsIm9wdGlvbnMiOnsicGxhdCI6dHJ1ZSwicmsiOnRydWUsInVwIjp0cnVlfSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMDAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MzIsInRyYW5zcG9ydHMiOlsiaW50ZXJuYWwiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi0yNTd9XSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjE5MDQyfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMDUiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IldpbmRvd3MgSGVsbG8gU29mdHdhcmUgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNDE4MDAzIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDgtMDUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA4LTA1In0seyJhYWd1aWQiOiIzMGI1MDM1ZS1kMjk3LTRmYzEtYjAwYi1hZGRjOTZiYTZhOTciLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjMwYjUwMzVlLWQyOTctNGZjMS1iMDBiLWFkZGM5NmJhNmE5NyIsImRlc2NyaXB0aW9uIjoiT25lU3BhbiBGSURPIFRvdWNoIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbImFueSJdLCJ0Y0Rpc3BsYXlDb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjF6Q0NBWHlnQXdJQkFnSUVlQ29PdVRBS0JnZ3Foa2pPUFFRREFqQnFNUXN3Q1FZRFZRUUdFd0pWVXpFUU1BNEdBMVVFQ2hNSFQyNWxVM0JoYmpFaU1DQUdBMVVFQ3hNWlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFbE1DTUdBMVVFQXhNY1QyNWxVM0JoYmlCRWFXZHBjR0Z6Y3lBM09EVWdSa2xFVHlCRFFUQWVGdzB4T0RBNE1ERXhNRFF3TURoYUZ3MDBPREE0TURFeE1EUXdNRGhhTUdveEN6QUpCZ05WQkFZVEFsVlRNUkF3RGdZRFZRUUtFd2RQYm1WVGNHRnVNU0l3SUFZRFZRUUxFeGxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNU1V3SXdZRFZRUURFeHhQYm1WVGNHRnVJRVJwWjJsd1lYTnpJRGM0TlNCR1NVUlBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFN3BnRXYrN3BCVzN2YWZpM0FHR0pSY1V3ZkxyTGJ2YmZvbzBaWnM0WS8xOGR4UFBzcjk3eVA4cUdQZVZWeEE1Y3F0dkRaMGUwVXFSWU5yeFlKdHIrU0tNUU1BNHdEQVlEVlIwVEJBVXdBd0VCL3pBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWdPcVBwU20raitObDZtcWppNmE5aWJ0eVM2V05xV3hnUTNOSS8vbnEvWHNDSVFEbzF1SGdqNzZZVGZqSlBRSHRHT2NvczJDM3VwVWZTTWlaS1FncGNscjNnZz09IiwiTUlJQjVUQ0NBWXFnQXdJQkFnSUVlQ29PdVRBS0JnZ3Foa2pPUFFRREFqQnNNUXN3Q1FZRFZRUUdFd0pWVXpFUU1BNEdBMVVFQ2hNSFQyNWxVM0JoYmpFaU1DQUdBMVVFQ3hNWlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFbk1DVUdBMVVFQXhNZVQyNWxVM0JoYmlCRWFXZHBjR0Z6Y3lCR1NVUlBJRlJ2ZFdOb0lFTkJNQjRYRFRFNU1EUXlPVEE1TVRnMU9Wb1hEVFEwTURReU9UQTVNVGcxT1Zvd2VURUxNQWtHQTFVRUJoTUNWVk14RURBT0JnTlZCQW9UQjA5dVpWTndZVzR4SWpBZ0JnTlZCQXNUR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4TkRBeUJnTlZCQU1USzA5dVpWTndZVzRnUkdsbmFYQmhjM01nUmtsRVR5QlViM1ZqYUNCQmRIUmxjM1JoZEdsdmJpQkxaWGt3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFmZjFsSEkxQjNWRWp6Z24rTExnYUJqRGI1NGVJSld3L2ozelRYYVQzdW5FSVhwR1FqbUIxSzlSOEthLzEwZ2I0dTJCc29ZWGxyTGZ4RzdtOHpOVUZsb3cwd0N6QUpCZ05WSFJNRUFqQUFNQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUUR2cVFJVy8rK3VsQW1ZVE52aTViWWdkZEw1d0ZBMzI1NVZESy8yZzFYUU9RSWhBT280RHhxeVMyNFJuUm5PZDdYV2l2d09MZEpCbUJCcU8ySTZzNE95aW0wYyIsIk1JSUN1VENDQWwrZ0F3SUJBZ0lKQUtxNWNqWll4STRBTUFvR0NDcUdTTTQ5QkFNQ01JRzRNUXN3Q1FZRFZRUUdFd0pDUlRFUU1BNEdBMVVFQ0F3SFFuSmhZbUZ1ZERFWU1CWUdBMVVFQnd3UFUzUnliMjFpWldWckxVSmxkbVZ5TVJ3d0dnWURWUVFLREJOV1FWTkRUeUJFWVhSaElGTmxZM1Z5YVhSNU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SMHdHd1lEVlFRRERCUldRVk5EVHlCRVVEYzROVVpKUkU4Z1VrOVBWREVjTUJvR0NTcUdTSWIzRFFFSkFSWU5hbTkyUUhaaGMyTnZMbU52YlRBZUZ3MHhPREEwTVRFeE1qUTFNRFJhRncweU9EQTBNRGd4TWpRMU1EUmFNSUc0TVFzd0NRWURWUVFHRXdKQ1JURVFNQTRHQTFVRUNBd0hRbkpoWW1GdWRERVlNQllHQTFVRUJ3d1BVM1J5YjIxaVpXVnJMVUpsZG1WeU1Sd3dHZ1lEVlFRS0RCTldRVk5EVHlCRVlYUmhJRk5sWTNWeWFYUjVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUjB3R3dZRFZRUUREQlJXUVZORFR5QkVVRGM0TlVaSlJFOGdVazlQVkRFY01Cb0dDU3FHU0liM0RRRUpBUllOYW05MlFIWmhjMk52TG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJMRGNZaXVDOTJMUml5cWFHQTFNUklINzNtZ09wYmd3dm94c3IrblBCais0Mzh1SUJPTW45cDRpVDNqS2ZjQmFEUHM0NCtnZzJ0ZllscUZvZDdyTkZzR2pVREJPTUIwR0ExVWREZ1FXQkJTZWpUOS9rOExORmgrVjRzNWc0U2JFME8zOFVUQWZCZ05WSFNNRUdEQVdnQlNlalQ5L2s4TE5GaCtWNHM1ZzRTYkUwTzM4VVRBTUJnTlZIUk1FQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURVTVZYZDRYU0ExYnIrNm4xdzJRazlUY1g1b3VaRFZjYUhzRkREbXgxenRRSWdNdEczb0FCaDZiR1Z6YUxOODBIdGt5Y1dBR1VWU3Q3a0RkUVlJak56VENRPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFESUFBQUJhQ0FJQUFBQjErcExSQUFBQUNYQklXWE1BQUE3REFBQU93d0hIYjZoa0FBQUFCM1JKVFVVSDR3b1hEaGtsQWVEa1hnQUFIdkJKUkVGVWFONlZtM3V3NVZkVjU3OXJyYjEvNTl4N3UrL3QyNTFPdXRPU3Ara1EwdWJKU3pBQkF6NEF4UUZIbUJtdEthUVlRUjFScTBhblJCSkZRTXNwQWFGR0JRY0pEM1d3aUVUR2hFZkVpRVBHQkhsMGg2UlJrdTQ4dWp2OVNQZnQxMzJkODl0N3JlLzhzYy90N3VETVZNMnBVOTJuenIzbmQvZHY3YlhXWHV1enZrZWUzUGZrM1ovNzdEZS8rZERpMHVtcDRjeW9qNWwxUTRXcXFZbzQyYWxhU2tFSW1GSVhERXRHaHFtYUpURlJVYUdJYXBmTlNZR1lxb2prTGdNQ1NGSlZNNUFpb0tncURCS2tpdlFScHFZQ1VlbFNtcHFlMm5yaHRtdDM3RWk3ZG4zOTlqLzU4TUt4NHhETmVhaVdST0FrQXlscGtMVXZnS3FsOEtLbUFGUTFna0hTQ3doTkdRSUdrMWt3UkZSQUo0VTAwMXBkVlVneVdDTlVRVUlJZ29CRWVETHpXZ01VWWExbGZtNzJOOS94amhRUkpFbUNBaEZMSFVTU0VMUmdaZmh3T09VUjRaRk1uVEJwTjZxTUtwck1WRVRjUTFRSVNaWURRTGhBVkJoa3NrU0JTSmgyQXlBaVJBREF3d0dJaUtneHZQUTlFU1FCaEx1Q1NLWUFSQW1BWGxVWVJLbWpJRlRVdy92U1EwRlJNdzFRUUFvMG1VZjE4QWluQUtJUkFYcFdBRXdxSWhEQUlhQUlqUXd5MURRUUVCR0lpcG9rZWhBMFZZaXFHZ1ZFNk1VWFh4cEJrQkNZR1FTTVlOUkJUbVphU2hGSTEzVXBhYklNTUptcUt1aGdETHN1bVFGaUFqTXhZUUFlYmpsRkJFUkYwQmxVUlZWeVNnQVVBTXhNODJEWXBVU2htSVhEdXR3MS80T1FvbHUyYnZVYUJCaE9RTlhhenZlMUNpTW5EVWJVQXBmd2tqU0pLQU1pRmtGTk9ZamNkUlExRlV2SlRGTktRbHBTTXN4U0pWUmdxbDVyMTJXQUpnaVA4QnFpU1RTOGRsMUdnTUtJRUlDTU5CZ01hdWxGSktYT2E4MjVxelZTc25DcVFXd1k0MUhLSFNGZHlnUkFpcWhJV09xU1NiSkJpUmdPT29HR2hxbVNVWU01WjdNS2thdzB6YUNMSmtJb0ttcXFUS0tsVk8wR2lVRjNLcndIVkVSVlJSTklpZ0FTMWEzTENnd0dReUJNQVFMaWFwcFRob2lxbFg0VWhEQXNwYVFxWUJERDNFV0VxTktSdSt5MVRPY3V2SVNtbkx0U2lxa0tqQ0FBVVJPR1dxYlhsS3pVTWRSRUFBK0lDQm5oSWtndGlDSmNzNUkrN3NjcEpSR0JXZ1J6MGtHWFNJckNUREFZQUdxbURFZkE2VGtsVVNRZFJLMkR3Y0JMR1F5SHBFcVhTNDJvUlFRcGQxNUROWExPbzlXeDVWejdJZ3BSeTZMVkswTVkxUVJqQWtRRVUwUW9JQUtJbW1XMVJJR2xwQkFrNjdvVTRTSnFsczB3R3ZXV01rRExHUkVCQUVxRWlVVEtLZVdVYzg2cDlEV0NYUTRYUUpFMHFYaEVtT1hCVUF4aVpyVldlRTA1QVJ6Vmtyck9TeUdEQUlFVURFMnB1VHhFSWlKYlpnUXNtUWxDSkRRQVJzazJHQXdIRUJ0MFhkOFhvcG9JR2U1UU16R3huTXA0Vkl0NDFPbXBtYjcwQ29GQklHcWQyWENsVkJQcFMxV1ZuR3hjUzFTdnRlOXlkdmZtNzZKQ01wRlUwRlNkQWxCVVJjVlVCYXdla040c21aaXE5TzRHaU1yS3lyS0txU2dqTEpta0xLUkNFT2k2YVJXa25Lclhya3NZRFByeE9OeTdKQjRoN3BaeUdtb3B4U1BVbEF4VnErNHFJcW9pQ2dwSkZSR3FlakNacUlnQXFrS2dlazBxcXRDa1lrcHdPRWlpQmtzelV6TnFZcFlrSjQvd1VpTVFoTmZxdGZSbEpFQ3lOQjZWM29PQm5EcXFnZEVOQnd3UDBoMmw3eU5nbWl5WnFRUUpFUkZFUkREMDlLbVRXVTBoWGoyY1hjNFJWTlZrUmhpaElwb0Vxa3BNakZoS0h4N2pVbXAxMHlTcUhsNjhuV3NnVVd0bElNSVRTTEI0RGE5ZE53eXZWREV6TlhRcEMxbmRJeEJPRmEyMVVFUlZFRXhmLy9yWHFqc1JaaG1DWUpoYXVKc2xnNHRZTGFXZFFpcmFWNi9oV2FCcVhvdWFyWXhYVWtxZ010Z2plb1phb2lrOStyNjB4QUZpM05kU2VoSHJTNUdjaElSWm90Q2tsajRFWG5vVGRSQVFBS2tmanoyQ2tFb1lDVWk0THk0dGVpMnFpWFN6SkdxV0xOekZVaTI5Z0hrdzdQc0N1RW5PT2RXSTZtRkNFR3BReldCQWplRUFjc3FyL1VnaEVWQUpxSWE3cXBrSXdXNHdWQ0JFVllVRXc5MDlrU0VpazhQVnRKVXJqKzk5bEF6OC96K2tsUWZQZUFFQUpBQ2UrNXZ0SFJHNTZLSkxabWJuMjBhSm1vaVFTQUZPOGk4RXRWYk5Tb29LSGMrOHlzUzg3VnJQK05IYUQ4NHVTS0Npa0ZZOFNQczRDYkpkcHowQ2dFQmJiRVVsejFRMmlBU0lVQVFhRVpaVFZ2RUtpQkFLVUNaLzlkeWxuTFZIdTRpWnZ2WTFyNzNsbGx1NnJydi9nUWZ1K05TbmxwYVhJUkFCemxsSFd4Yk92dEh5a1ZqS2ZYVUtJMXdBQmdsUlVBSWtBeEN6dGlBUlVRalBXSUlRUWlpQ2M1N054cTk5N1d0Mzd0ejV5VTkrOGkxdmVjc2IzL2pHUC83UWgzYnQydlhXWC9pRlNZbTNkak5reTk1dFRXZHZUQ0FJYXZzck1hbmtRS1JnQ0tpcVppcWk3alVpenR6YVpNKzQ1aU9UbXdSQVVGNzV5bGQ4OElNZjNMQmh3KzdkdS91K0YxRXlObS9lL0s1M3ZhdnJ1dmU4OS9jRTUrNmdyQm5xSFBzQklSSkNCbFRnRVNRaUlnbERvQ0JMS1NtNWFBYjVmM0VyT2JNbWtnTGNldXV0R3pkdWZPQ0JCMjY0NFliQllOQU1zTEN3OE9DREQvN3N6LzdzeHovKzhTTkhEajh6SU5hc3NlYVZKTmQ4Z1RLcE1BR0VxcVZKRFdVSmFpcHJCbDl6MFhNRFozTGJKSWdYdmVoRjExNTc3U09QUExKOSsvWXZmdkdMdi9pTHYvaW1ONzNwRTUvNGhLcmVjTU1OQnc4ZWZQT2IzenpwUk1nekxnL3c3TFVub1FhRlVEU0tBM1NTd1FRd0lBekNXb2xtVVFJUWlLTGxDTEw1TndocFdSeUE0Q1V2ZWVsd09EeHg0c1FkZDl4eDY2MjNpZ3FJMjIrLy9UV3ZlYzJIUC96aEs2NjQ0bk9mK3h6T2RmRXpqbnIyUGtIQ1BhclhuTEtib2FlcFZJWkdoQXBVQVZJaXZIcVhFcVJsZFR2alVsemJ2VE1iMnhMYjNyMTdiN3Z0TmhIQkpQYnc2VTkvK3M0Nzc5eTBhZFBzN0N5L3d4L09XZU9aNEVuSmNqYUdUeElWcWFJYTdoSE5kRkhkYS9WeEtaSVNMTUdTcUVIMFRGN2ltZlVCOTkxMzMyZzAyckZqQjBreHM1VFVWRlJFNUw3NzdvdUk3ZHUzVDVaNzlvbUp1Yy9rQ0FFOXdxR1cxRVNnYkUwUkJBaFhRRTFKTnJlV0RWc0hGMzYzVHEyRFpWRVRVVXllTXJHSnlCWGJ0Ky9acytlYWE2NTUzKy8vdm5ZNURiczhIS2FjWC8zcVY3L3VkYTlybG1rQmJxWm40cGpFbW1WRkZhWVNBRlRZNmlpSVFBRWtydzZWOEFoV1ZVOHBJVFRVYXA0ZWJMMWsvUFIrOUNQV0ltZmpJRnJiOUkxdmZHTTBIcDg0Y2VJLy92elBYM2ZkZFYrNDU1NlRKMCs4K0VVdmZ1VXJYdkhZNDQrcjZzTVBQencxTXpEVDhPakhwZFlhTVhFS1ZUSFZMdW4wekJRamhJQ3BtV2pMWTJCU1ZZRkN4Q3lyR1NCa1NPclFEWXBYeTFNTzFleU1LcFBnZFltUWxMNzE1TDdGMDZlUEhIbjYrUEVUTjk5MDAwdHV2aGxBUk96Y3VldktLN2MvL2ZUUjJ6LzIwYm56NXFhbUJ1SDE5TUxwcGNYVlVweWtpSmpKaGVmUDNuVGRmT25IOXorcVJFZ0lZa0lBQUNReUFJb2cyV1R2VlJVa1MyVUVDTmFRYktJcVhhY3BpY0J5UnJnS2Z2TzNmK2ZQUC9iUjZlbnBuYnNlVEdZRXd2MnE1MXlWek43NzN2ZU5ZbVZtZGpwM0pzejBHdTZycThYZEFYUmR1dXFTV1k2V0YwKzdZQ0JRaGRBc2drQUlrS29UZ0lnR0k2ZFcyaWdqUUNiV2ZuV3NPZXRnV2hMb1JWTFNsR3hxQ3JVSStPRCtBei81aGpmOHptKzk4N2szM3BCemJ2NTA0S21uM3YrQkQzenFyayt0M3pDVHU2UWtHSU5CdDI3ZDBFekg0MUpMeksyZjJuOW9lVit0S3lQbk5DUENURVNnS2cwRXBCYTBBckdVVlJTaWZSbWJtS0hXMHd2U0RYV3dEaFFZTGFjb1l3SlJpNWtKeUZwMjdkMzdxamUrNFh1dnZPcVdtMithbnBwKzhPR0g3djdDNTJ3bzYrYW11Nnc1cVlKMVhMcWttQm1ZaXFuSUZHdXRKNWFqMXBvb1JsZ3lpRElLUkZUV1dneUN6aEN2eWF0b01sRXVIeTlMb0tzTlp1aFFJMnN2Zy9UVFAvYXFVNmNYUC9QbC95VTVTUVM4aWtEQmJ4NDU4TzI3UC8xZDh4c2ZmM3l2VGxreWFYeHJPRXlEQkpSVXBteDFTYkV1YjlsOC91SERwNDRmWDgyNW00MWxDUndTSlFRUmZTV0RRZ0JJSXBnYzlCR0FpQUtrajFkbE1DMW13Z29SNzRzTzdQMXYvODkxdkRvN083ZjlpaXYySHo1OCtVWFB1dlB1dXdjNWZmL05OLzNGNXovN3EvLytUWXNuVGg1N3pyVi85ZG5QbkRjL2YzTDVPQmtYWEhCK1RqV2hTbUM4Tko2YjRaWk42ZGo1M1lFblR4MWM4RnVldS9uWXNjTUh2eGtSSVlxVXRQUUNGUkpwN1NDWUxGUmFBUU95akJITEh0VUc2OUwwaHJISGVmTWJYditXdDJObTVxTy8vYzRmZU5rdDk5MTMzNi85OGk5ZGNNR1dQZnYydmVlNXovdm5SeDlaUHozOTBIMFAvKzQ3M3YzWTNzZm41bVlQSE5xMzVZS3R6N25xMmZkLzVlOTJYUFhjaVBMRkwvenhkVGRlWGtkTC8vVFF0NSs0YTgraFE4dmpmaWFaRGJzdTZJSkFCQVJRVmZjQVZLQm1HdTRlYkVDc1pXSE5BOHZyWW1VMWFVRGt4bWR2LzljdnVXazhIdTk3NnVBSFB2MFpoOHpOelEyblowNnZqbmJ1K2ZiSDdycno5VC8rRXlkUG5QckNJL2RPYjUyNStQTExQdktaUDM3azhXOUQ5UDZ2L3AzcTZSdGZjUE9Wejc1Mnh6VTNmdC9OMTkvMHZkczN6blhhTDFZdmZkL1gzbXQxaWpBQTBuNzRoMzl3MTRPN2xsZFd6VFFQcGhTbzFVOHVMVk16QkhsbW50Q3B6VnRVODZFbkhudnJXLzdEcFJjLzY3ZmY5NEZ0VzdkOGZlOWpsNTIvK2Ntbm5ycnMwa3YrN3F2L2VOWDExMzdmdFRjOCtjUVRsMTV4K1k1bjd6aDY5T2d4N3YrSkgvaTN3enpjZi9EUm1lbjAzT3QzbkR5MWNPRUZzMG01YmlxdWVmYTYrKzk3YW5wR0hqdVd1bTZZYzY2MU1Eem45SUlYUEQrUkVSR3FTb0plcVNidDNGT0labWdhem0vdzRpempyKzU1NGx1LysxN1U4YWxUcDk3ejhUOGRiSmo3bzcvOTB1ejJ5emFObHk1NnptVStQWGpveUtIb1RsODE0Ri92L3R0dEcyZTJ6RTd0UEhUWDZ2R2xjVGwyL1RVdkg0OFBYbjdSTEFIVFllN21NRHoyd2hkZjhyRVBmOW5yaHBSemVJaElEUmRDSUltdDBwK1VRakk1bGNNUjN2QkpLMnh0WnFoWllhcWhXc1plUzAxNWVQRmxVOS8xckkzUDJyWnA0OFlOWFpyTnllYW5kcDdZZThHVzh6ZE9kMU5KVnJKUHorUk4zZFlkMjNlY1BIMlFYQ25qY1VpZ0xOVXkzbnplY0RoVTlJaHdad2d3eUoyREVDZ2toQ0NqZWlVWmxOYm53aXU4MHNjK0hzVzRGMVBwT3FxRk8rdllWMWU4RXV2WHArbXBsSkszc3dKYzZzZWJOc3lsWkNkWFRqNXhkTS9wNVJNTFR5OWRjdGwzblZ4ZUhIVG5sWDZsbGpwYVBiMjh1Rys4ZXZ6MDZmSDZ1UUVaRERUK1U3MjJvaU0xNk5hYSttRG9wRmtLZUFIZ3E4c2NEaSs4NnNxamg0OVpTaHErZXVJWXpBU2F6dDh5Mkh5KzVhNlV3bHFRc0RKYU9YbjZCSllXcHVaVGpTcU01U040K3A4T0wxNTV3ZkhCRTlzMlh6dC8zdk1OeXFoTDdGWldkajcwMEVGSkNkSnFZaW51cmRjQ21FZ0dRZ0FoRVloYUZRQ0RJU0lCNWVxSmhYMWZmOEM2YVoyWld1NVgwSFhRMUcyWW05cXlaV2JUcHNIVWNIWXcyREExUGJEb0ZZc25GcDdZdTNkcXhHMlhucmU4Y0dMUHprZUgyWTRkWHQwd1dGeWVQam03Ym5PcEk1RGRjRnZNak9ZMzdjc0hFK25PYUV5eTVWQ0JKa3NLU05DenFHVTF6ZU5TSmdaVHRpcWtqdnU2c3RJdmRqWTlaWkxUN0ladTh3V0R1ZGt1bVlsTUQ0ZUwvZWhFdjdTeXVIRDg0S0hGSThmcnhzSCtFNGMzekUwOS81WFhMUjg4L3FVdlB2US80K0ZYLzhpaEt5NjlNcWttU2RHZktzc0hudmY4aS9jZldjSHVZM0FHbTJjMzdvbkVZRnRna0F4NlZFR3NWZG9CVUFZekpGRXJ2WSthVkdaME1OVGhBRkZqZFZteEhtUWlUdldqcDU1KzZ1bEhuNWphUEZPMEY2VE41MjI4ZU12NXNtM3JsKy82OHVPUEh2NmJld3BmdWpnL096MDluSS9SeVlTbGlNNjl0RTNLT1ZjZmd3RlJRU1FSZFVTRGVpVFpoZ1hnaHRuWjg4NDdiKy9CUSt0aU5MVnVhaEd1cXB1M2JsMU9uZGRTVDUvU1lUYzZ1aTQyeno5OTh1U202WFI2NmZTSlBVLzBvMUdublN3Vlpvbks1WlhWc25SaUZYN2s4UEhIOWg3YTkvalJhNzdueXBuOFQvM0NnVTF6MCt0blo4cTRWeFZBK243a0hwT0dWelNkNmFCVmhNRnMyb3VTZVBjN2YydHFlbnBoWWVIQ2Jkc1k4ZkR1M2R1dnV2cFoyN1k5ZWZEdytWdTJmT3VoQjYvYmNmV0JoZU56YzNOLytMWDdmK2tWci96SHJ5LzgxQzJ2WC9lcTZZUEhEcTJibXVsUy91U1gvdnoxTC94M0J3NGN1T0gxcjFwOTFlckN3akZWUFg3OCtQWXJybERVSS92M2JOaTQ4Y1RPOTR0WU1nc1ZnTFd3ZFI3YWVrNXRMMVFEN1QyU05GV3YzcHE2Ny83dTdSR01XbzRjUGRxUFJsZnYrSjR1SituSHp6cHY0NGFqeDVhUG45eS9iMTlLV1V5VFpvVUo1T2dqQzd0M2YydlhOeDcwNGpubitmbjVMVnUyenMvUHI0NUdvdDFTN1ZacmZuTC9rcGdXNzAyVmdRaUtpZ2dicjRNSTFjemQxWElMMGwvNWxWOVp2Mzc5c2VQSGgxTlRNM1B6WTF2ZjJoTGJkbUc5NUxKMTQ2WDFoNTQ0ZnVEQTNPeTYwOGFISDM1d2V1dW1uUWYycmh0a0hjamlnY1BqMDZ1amZ2RWpmL3JoRTBkTzNIdnZ2Y2NPSDR2Z29Cc2NQSGpnNnF0M25EcDVZblg1NU96Y2htTkhSNFAxTlZsMlo0M2FXbHBDa2tBZ2t4eXZJcldPVzllNnVycTZ1anFDNnVwb1hLWWNRK040akFqWnMxZVBIRHJwNDdweGJtbDFlYldNdXBscDJYckJoZGRldlhsK2R2WFF3Uk1IRDZ5c0xKODZmcnlPZXJpWEtJL3QyYk95TktwbFVnSHMyclZMUmRUaytNbEZRSWV6NHU2V0UwWnRiaUVDSkVxczlhT0lpSnc3bDRKbjlJVVNaWnhtSlhvbkM1eGM3R2xZT1JVZW5xd1RZT3JTYll1ajFjR3l6YzNQUGZiQU40NDhkakRvWHB5MTlNdmp2aS9oWnlGZU5LRHZJZ0pUQ0dpcVVXb2pLd1JNTlRWYnRjbWpxRURWYTV6aEdDQVpIcU5WS1N1aUxqa0VHdUgvNWRhMy8rZ3Jmdml2NzdyN0cxOTgvd3VmTS9YN1Q1NUdXY2E2NlIrNWJIWEx0c1UvZk9CVWxCb1JFVEZlN2MvaGcrZTIyU1FuM2J6VFJjVk1hM0VWRVpGRWFBTXhFZUVleWVJc1lXc3JpMEF0L1pHbnV2bU53NW5wYnRCdG1KNTZ3MC85NUJjKy8vblAzbjMzTGR1NzZ5KzMxUzhmckRPcERydWJYbFEyTEk2OTFnaG44TUt0VzIrNzlUZEdvL0hVOVBTYmYrWm4rbjZNY3puRTJtQUxiTWl3alVhRGlDUkV1NHVjelV3SlJ1T1RFd1FpQU9HVlh1dUpvK1B4MUZLdGYzRDd4NmFtcG1iV3JYL0ZWWHV1dkhUalB4L29od3VIMy9HS3padm1ZNmdFK0lNdis2R2Zmc01iWnRiTmZQYnV6MzdwNzcrVUxGMTMzZlhuNE1RSlQyMnZ2WlZXakRZU0pBalJCRUcwNFdLMEVTT1RwWE0yc2YxUEFGRnFXVnB4eHVGRGgwZysvZlNSd3d2bGh1MzlpNjVLdi9ESzZaZGZtLy82SDQ0OTc5TE5CRzk5Kzl0enp2djI3WHZiMjk1Mjg4MDM3ZG56Nk8yM2Y3UzU2VG5ZOVJ6Z3FvcWdlMUdaY0Q2ZGtCTTJUd3lGdExRN0lUQnlsbnRHaE5lSzRPMGYrWWpYZXVlZGQvN2VuY2NmZm54MWFhVSs1Nkx1a2YwclAvUGVBd2VQalVGY2Z2bmw5OTU3NzN2ZTg1NzE2OWZmZU9OejNlT1pYb1Z6bDBhdk5sbXVUQmhWZzVSQkJLaU5lWmtTZXU2bitCMGM2QXhMaW9oK3ZMVFVQN0E3WnFiMGg1NDM5LzZmMjdabDAyRDNrMHVIRGgxNjRRdGV1R0hEaHBXVmxaMDdkNTd6b1hNTUpaTlhWSU93OWhPUTVDU0VxcUlOSzVtWkpRTzlMK1U3cnZBZGo2V2xwYTk4NVNzTEN3dDBmK0x3NkxHRG8zZi8yZEZkZTVldnVXTDZubjljK1BhK2xkdHV1NjNVc21QSGpuZS8rOTI3ZCs5K0ppekhHaEZjMjBBQlZGTldBY0dRSUNocHdwRWh0VmExa0tUSjdBejZmZ2JyWHJ2bFJ4NTU1S1V2ZlNsRTFOS0hQbmZTc29ub2ovNzZYaThGMFNEbVg5NXh4eDMva3JXUmtPYXREUWxEQUZSM3VxdnFKTUczd1oyN1R6NmxiVHlEaUlwL0NXSkZ6cUdCazRKdGdxMHJJbnE2UHdPb2lad0Y4T2U4WHNPTFp6Y2hXd0lRSVJOakJsVlYxNjVFQklOUTA1bVo5WVBoOEJrZmxiVUJyYWlJaW9vMEVZRUlnbEZxVkdjUVFmRC9NWFQ1enZGSE04VmdhdUFScWhNK0c0eUltaVlTalNZWk1lMXlubG0zL3VXM3ZQendrY09xeW1qbHJIaUVBRUV5WWkzTVJWVTlBazExRTJ0NWhORXF0dlpCckVVN0k5VE1WQ0ltYXcvR2hSZGVLSlllZi94SmQ0Y29BeXBDU2tLd0hUdlJzb0J6ZVhsbGVXa1JGR2Nra1FCRkpBZ0ZBNEx3ZHRlRFBCaVZvbW81ZDdVNktFUUlES0l3bUVqeDhJaVVja1R0OHJCNHlTbU5TOG1XVytxSldnOGVPbHBxSWFtQ1BweU1sdDFUQUNJV0RCVWpwRWJSNGdvaGFKWWpJaVYxaHFvMS9ZYTE4cCtnU3BJRVVSQWhVSUNRcmh1TXg2dGR6bWFhSVNKYVNtL2RVQ0Jaa2dkek4yZ3ozM0UvYmxJaEZVQlluUUpSMVdhRnhIQXlHaHlNcUJrbWtPb3VFS0pQS2JYUmtBQmlPU3NBNld1ZjA4QXN0UWp3Nm9PY1JOUUQ0V1dRY2d2SDNpTWxwbVFSUWFqbDFMRDVZREFzL1RoWlpsU1FsbkwwckY0RUVSNnR4VkNlTzhTaFZBK0NPZWV1NjBRTXBFY29vS0ttTUxXSXlHYkpsRjdKS0xXcXFydlhDTkJidjlCZ1FVclp4R3FRWXFwU3huM1U4RkxIbzVFSUJiU1VDS3lPVmtVUTdqNEJ2aW9RZGZmR25Fa0VReUFSUWRDakFoVFJsSXhrODFsNlFNQVFVS0RhOTMwd3pOUlVTK2xMclJDcWFBaUY0YVVYQUU2aGowYWppQ2gxckdwQmxyNkEwZmNsM0x1VSszR3ZLaEZ0anM2R2RIbEdOZFgyUkpDYWtRQzRpcnBZNnRvUkdxUmxFMUtVcFJRUm1FcXRSVlNTR1lKQ2xGcW9Ha2tBNldzbEltZ0N1bnRLcWRaU3E2ZVVTdTJiRHpUZmF0dlh4R1FBazZ3Ti9rVGh0WG95MENISXFUTXprQUhXMmtPdFM2YXFmU2xKdEVRVk1uZTVIeGVJUm5GUlZUS0NhdUxoWGxHZE9adDdpVnBVTkpsV2ovQklTZnJTZzBHeWVoWFJ0bi9OaDBWdHN0WXpPYkNOazVxaXJwWSs2SlZPaEtrWlVHb3BmZDkwZ3UxWUt6VkVwYnEzL3E2Nml4SkVzdHlYbnVHMTlLU1lxQ3FpRVZHTldvb2dJT1llZzY0emtNRTFiMmZySzVKSG5VUmlPeHBGcXRQTWlXUkJOcUZnWWxRS0tGTzVqbnNCaEZvSmJRb1VrakNoV000aEZyVW1RSnZYYWdJaklIWGtwaW9xNFNFUU1nQTMxZkc0RjBwRXF4dW9Nb2svallqbU5BS1l0cEZ3YzJwNmRTVnlUcTErZDZCZkhwc2wwVVJBZ1FpcUtFUmFUdllJMURHaWtvd0kwYWFldE5MM1RZSG40ZFZMQ0VwN1ZHOVN3ZHpsYkNtQzJyWlNKTFU5YThkOEtkV3NBMFdUbW1XUXhiMTZBRWdwcXdyQXZwU21TMVJCSUpKMXBzbHJSSzJXRmJRYXBZN0g3Y3hrb1BxWVJFcGFxN2ZEN2Z0ZitwS0xMN3JvcTEvNzJvTVBmdE1ERkhweEFKcU10YXdOVnlBK21mTlRSZHhyemwxREVkR1VCNFNtRk9HcU5oaytpakFFQ0lONlVFa1BWNkQycmlJbUFqTUNYdDFVQ1VrNXExQWticnpoK25lOTg1M2J0bTFiV1I2LzlhM3BubnYrNXBkKytUL1ZKdVVFb2pwRVNCS1NHSFd5bldwbVp1M0FJajBvb2tvUnRWcHF6b2tSN29UQW93WTU2SEpmaW9BZ3UyeDlYMFFONG9DWXFrY05zVkpyeXBuQktreVdmdk0zYmpOZDl5Y2YvTXJKa3lzYjVtZGU5b1BQKy9tZmUvTWYvTkdIMk9RT3lZTFJmQ2hOT2xjZ291MVhMOXJsbER4Z1NkeEY2Y21VYkNyWTN0UThxc0JhSmFFaTFTTnFiYklLOTFEVlVpb2tRS2FrdFl4Rk95VXZ2ZnpTU3krOTlQM3YvZnpkbi8vRXdhZS9mZlgybHl3dHZ2cFpsMTBaNFUwazVjNm96VWFTU3FubjlJV3REbEgzc05SNWpaeXREU1pGRklLY085RWtrOUFCUS9wYXhKSklpSWlabVpvSXhLUjZiVWpZMUVpM1pHSVprSy90L012OVR6MUU4cHU3NzdueWl1c1dIMHFtNWhFcWsrNGVCQmhKelJpVGVhMktxdHFWTzY3NWtWZi91S21vS0ZRZ2xvREtFQkhUeHFlMXpkVTVRWjJUZ2pVWVpKaG9NS0w5UXNUQzhXUC83YisrTjhqRFR4MC9jdmowYmJmOTZxKzk3ZGNmZm1qM3Yzck5qNzNzNWMrOTYzL2NQeDZQcFdWaWo4bVlHRXhvSFRlYXhNV1Q1RzgvL09EZWYvNldSNWlvbWphS0twcE00RFhhdUxIVWFpbXJvSkgwVnVVMnZiSzdrNUt6TlNsdGNkZlVpZUxVNHROLythbC9lTjIvZWZGLy8vTS9PM1hxMU5SdzNSMS84ZkRCdzN0U3psSHJXWkVGU1NLSlNPdGxwY21oek5UVWE0VUFhbTFyd3drNHJTbGx3eUZtQ21ITDRCQTJRVTZ0SlFJNXBRaXZ4UUVobVZNaTRPNHErS3ZQZlB6MEtWeDg4Zm16YzkzK0ovYzhzdWVocis3OHpFVEpvSWhLVERRT210YmFJd0hnWHQxekJGVWdhcVhXbkJJRWFrWjNFU01ncWw2S3BaWXNsRUdvZGxucERCdlFDYUdsNUI0Z0xLVnhQeHJrSVFpUjJILzQ0VC85aTErL2F2dE5NelB6UjU1Ky9OSEhIbEJWMFRiOUNoVkdvQldVNll5MENRcFRxN1YwZzBIRFBRb1ZoVmxXVVJ0MHBWU0lFWkp6b3FnQktpcFpDSVJYUXFKNnpsMnBCWVJwZ2dTZ1pvT2djOUtOb2ZmK1c0LzhmZlZxZWhaM0M5dzlKcElXdGxHL3lJUWxrUjZlVTJxaUFEUFRwQkV3a1ZyR3BYcWI2eEVNU3EzdVVVMUZRSGdGa3BscFN0QTI5azVRdW9mWENuaXJBVUJBTktzUjNwSjFrK2YycFVSUTFiZ21sZ0daekxUcGVCcXlENFJTb3JvbTBaUWdLTzZrMUZwRlRSbWtUSFVEanlDOVJwaFF4QWdYR0NJY0FObVhNdEd0QVVrTWdpYURETHFhcVNZdnRZL0tOak5zYlJVaklvVFNGTVJKTmVta0hRWGg0VXFoV1JmaFFxVVRwdG1TcWpqZ0pTekowdktpQ0V4TjFaaFMwQ05ZYXgxMHd4b0JoQ1Z4OTRuT0QxQnBZUTg0S0tTanJ6VW1CTGZOejdVZjkyQ3I3cHA4RFBTV2NSd01nbUlwTjhWRDZmc0FGYXhsVElhWEhoSjlxUkZCQ05Vb0xHWGNacmFxTmhxUDZNVWpxb2VUSHUxckRVRzFWb1pETWVyN2NlbURVRWljS2ZWSXRRa0JxT0VRU1NJQ0NobFlZK0FLSmRvTVZvendDQkVkajBmaG9hYXRNeTIxQmlsQk5TMWwzR1hyKytwa2wzSU5WMVY2bTR1SHFKVFJpQXlkYUdHQ1lXaWRJVkRLV0NCQkVnRXdnZzFpTlhIUFdSZ2Z3ZXBsd2kzTXFoZEQ3c3NvcWZYVk5VSWhhd2VNRkVZdFBVU1dsc2NDVVpVUWFiTlNuOVRsUHN4ZElWV2tkZVNpOURwUkRrOXNwWkNBTjl0S0E3bElldVo3SlVFQVk4cGcwSkVDQnR4RnRaWlZraFdWN3NpcGVyQk1CdHVUYXJaVWhSUVdjKzFMcnhORloxTWsycWp2eGRTOWZadkNXVVBWSW1wTEx4NEJKOWphQzJjTHZJaVVVNHBHTHlOS2paVG90WkFNME5aTTJMNW9vaUlZcVFvb0tvSms1aDdoVGhGVGJlWERHU0luMG80akpkc3hMTkp5b1dyTGN3Q2FUckt4dkFpMkM3dFhrdWtGMy90aUp4WVhGMWVXbC91KzRtd2p0RlpPTkVRRFVWVjU1Z01pL3lmdWVGYmhLT2VxVXM4SVpNOVEzY2svSWlMSk5PYzhHQTVtWitkdXVPSEcvdzBqSjZpN3daMHZrQUFBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsidXZtIiwiZXh0cyIsImhtYWMtc2VjcmV0IiwidHhBdXRoU2ltcGxlIl0sImFhZ3VpZCI6IjMwYjUwMzVlZDI5NzRmYzFiMDBiYWRkYzk2YmE2YTk3Iiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwidXAiOnRydWUsInV2IjpmYWxzZX0sIm1heE1zZ1NpemUiOjQwOTB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wMi0xMyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiT25lU3BhbiBGSURPIFRvdWNoIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDAyMTMwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTAtMjgiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE4MDkyNjAxNiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjQiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4xIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMi0xOSJ9LHsiYWFndWlkIjoiNmQ0NGJhOWItZjZlYy0yZTQ5LWI5MzAtMGM4ZmU5MjBjYjczIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI2ZDQ0YmE5Yi1mNmVjLTJlNDktYjkzMC0wYzhmZTkyMGNiNzMiLCJkZXNjcmlwdGlvbiI6IlNlY3VyaXR5IEtleSBieSBZdWJpY28gd2l0aCBORkMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NTAxMDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjZkNDRiYTliZjZlYzJlNDliOTMwMGM4ZmU5MjBjYjczIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA1LTEyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgYnkgWXViaWNvIHdpdGggTkZDIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAxODA5MTgwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjIifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNGUzMDM4ZjZhNGViZmQ2Y2VhMmNmZTE0ZTQ0OGM2ZjhmMzA4NTE2NyIsImIzOWU2YThmNWU0ZGE3MTE3MTIxYjJiMTQ4MWFiYjFkMTVmMTU3YmIiLCJiNzY2MzJlMmM3NWU5OTJjOTAyNzdmOTlhZmQyYzEzOTk2OGYzZDJlIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjRlMzAzOGY2YTRlYmZkNmNlYTJjZmUxNGU0NDhjNmY4ZjMwODUxNjciLCJiMzllNmE4ZjVlNGRhNzExNzEyMWIyYjE0ODFhYmIxZDE1ZjE1N2JiIiwiYjc2NjMyZTJjNzVlOTkyYzkwMjc3Zjk5YWZkMmMxMzk5NjhmM2QyZSJdLCJkZXNjcmlwdGlvbiI6IkdlbWFsdG8gTXVsdGlBcHAgRklETyBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRUNUQ0NBdkdnQXdJQkFnSU1SM01FQytVdE1uSFNGU3l0TUEwR0NTcUdTSWIzRFFFQkN3VUFNR294Q3pBSkJnTlZCQVlUQWtaU01RNHdEQVlEVlFRSERBVlViM1Z5Y3pFUU1BNEdBMVVFQ2d3SFIyVnRZV3gwYnpFNU1EY0dBMVVFQXd3d1IyVnRZV3gwYnlCQ2RYTnBibVZ6Y3lCVGIyeDFkR2x2Ym5NZ1EyVnlkR2xtYVdOaGRHVWdRWFYwYUc5eWFYUjVNQjRYRFRFNU1EVXdNakUwTXpVMU0xb1hEVEk1TURVd01URTBNelkxTTFvd1RqRUxNQWtHQTFVRUJoTUNSbEl4RXpBUkJnTlZCQW9NQ2tkbGJXRnNkRzhnVTBFeEREQUtCZ05WQkFzTUEwUkpVekVjTUJvR0ExVUVBd3dUZDNkM0xuUm9ZV3hsYzJkeWIzVndMbU52YlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSzFxM01JQjBla0dCYkt3WjBGV0tNRm9tMWVoc0F5RUwxVWZHWGUxOFpUeWh5VmcrVmNoeS9pSDlvM3NxMGZQQ2t1RHkyOWlBUGp5V1dPUVRmN3FkUzFFVHE4aVJwS05TeHhwbEprVkduU3pMeksreENEeDVNNGRhSEpMcDg4VzJKTzhITDBXY2k4SnJvTm0zVXo3WVIrejRVVTBhcHpPYmRkMmxSd0VFMG1wMVRERkowanhUK3hhaGx6WkFsZGY5Mi8vc1dkZG9ZUnJUb2RjL2pkZWZFWDlibWd3SE5UdDN6SEJKb1A4OHlvUTEyblVLSGVzM04yL3FReDNIakEyK3lTRmZtZFlBcWVyRGVqNTJvcnZBMVYvUXBkODdQVjlEQk5JMHQ5dEIwMXQrNlBidVBvamZlcVNsTkJtMWtUcUt5VTlPS21WdzhCd1FFWFFLbVQrdDBzQ0F3RUFBYU9CeWpDQnh6QVNCZ05WSFJNQkFmOEVDREFHQVFIL0FnRUFNQjBHQTFVZERnUVdCQlF2TXEzMFFqZUhMT3pXbURpNTNLRU9nODZHakRBZkJnTlZIU01FR0RBV2dCUjNWZlduTFdWRFVvaFNsWXJ6ZzIzeVlhQTJiakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdZUVlEVlIwZkJGb3dXREJXb0ZTZ1VvWlFhSFIwY0RvdkwyTnliQzFpY0d0cExtZGxiV0ZzZEc4dVkyOXRMME5TVEM5SFpXMWhiSFJ2UW5WemFXNWxjM05UYjJ4MWRHbHZibk5EWlhKMGFXWnBZMkYwWlVGMWRHaHZjbWwwZVM1amNtd3dEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSGNrSWxRb3BOaUJDRDZtTVNpRWcwN3Rhb1paTlZQTEtBU3Y1NFpxWG9meGhJZG9xbHF0cy9XNU5ZSjZUKy9Gd2huN21TZWJDS253dVVoYXFCeVZrVnQ3a2hlQkl3L0Y2YVBhQWRVOFlJY3VMOGJrdkdQdnQ1b1FtVTk5YnVVVjFwVGJyRWVkVTFSWWxXTGU0RXRuNkxTaUV5S0twc0RvQlFCSFdzSkVqZ1ZxSEtGZVJrUS9XZ0ZtR2MxK3d4UnlLQUdGb3RocnRyYXcxcmVySzNwK0JOeTBHUnRmTU43dE9uVG4yZ2lPdnRPdGViTUJDWXp5ZVJsLzlYQUxmVUM4TXcrT294dmM1MU9FN2xoZTJ5anVPM3hGM1NqRTBheCtjV0FqR1FIaHVJdVZkZlg4Q1Z1L1I1U0c1MnpBOU9vNHl1ZytjaktpZUFBRXUyT1BIK2ltSXlNPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFQUUFBQUFlQ0FJQUFBQ1VrcVJOQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQURzTUFBQTdEQWNkdnFHUUFBQUFZZEVWWWRGTnZablIzWVhKbEFIQmhhVzUwTG01bGRDQTBMakV1TnYxT0NlZ0FBQXlqU1VSQlZIaGU3VnozVzFSWEdwNTk5b2ZzRC92ei9nM0FWSW90bG1oMGRSV3hwcGwxbFNwcUlwMmhvMGF4Sllhc1E3UEZtR2lTVFRTSklFMEVSU1d1amhVcmJSaVVNb09Vd0NEaXdPaSs5OTREYytkT3ZUT1l3ZXk4ei92NGdQZWM3enZsdmQvNXpqMzNJbmpwZ1FkL1VIREZQVER3ckxsWnEyclNnRGV1TngzLzVuelV4d2REMXlwQzErNXptSXJ3RU1VWG54ZWVxNnB0YkdoblREMTUwa2NjV0VkLy95QktOdFMzbHhaZmw4Y2ZvZTBVNU9lV2tzdDhrSjU2UEN3NEwyU05ZdnZXLzlSY2ZLQlNhWnViTlhyOU1MbnNBdFFZSEJVWkh4T3F0RTFOSGFTUUMranJlMnBtWHd1bkl5TUdVbUpjMGRPalk3dzhmTkJhY3ZwYWV1b3hQbk90Q0YyemIyZldpZXJ6ZHhzYk9sUXF5czdUcDBQRU5CLzA5ZzR3ellEazhuSkxRNE5wNDF4M0hDcTJaSHhYY2VaMlEzMGJSa3l0N256eDRnVXhOd3FqdUNIcjQ5OVVyMTZWTFJWR2k3MmlSRjZiUkY1Ull1OFlpVSs4MUNlQkorTWwzckZpNzJqR0NQNmRQM2Z6OWs5KzFHcCtJODRzSVM3NnNNUW5qbllhelRqMWs2UnZYSjlQTHZQQjNObVp2dUlVV0lCQjlFWHNIU1VUeDM5NTZDeTU3Q3lLaTVRQlV2bG92MHdJRnhKaEhHSUJLZW9zdmoxV2piNHpnelpxT1hxeVgwSlhWejhwTVU2QUVnNGRPTE1rY0FmdEJlNllZWTlqVGFKRHBFYVlIaENNZ05ocjA1cC8vdnQwb2RKZzRPck1JcUNIWEVWSjl0N0NaVUU3YU1reHpZamx1TEJHdG10ZmNVek1waS9QVjkwaHBta1l4YTNSOUw0MUkwMG1ZaVlQRFNYT21DSG1UN3FoWS9TT2s0bVNiOTFzSnM0c1lVbGdsbFNZT09xWE1vSmY0MklPazh0OEFGUDBmV0pzaVV5VUpJODdRaTQ3aGVkRCtwWExka3FGQ1NiOUdpWCtFOE85ZUdHV1R2ZU1WSEFLaUM5d0lmYWk0Z3REaVU5TWdEVHVWWWg3NXJSa2FycFpYUmdkTWI0azFha2dJa3BlODJIMjhMRDlkUVpyKzd6Wm44aUVjaENoY013SXoyYU11WTcyRTZlbEpCNGwxbWtZeGQzWitSdXRDYmpoMUI4WHduM01uZG9XNHN3UzNsMnhodzVheGxyakpHNWlLaVBsR0xuc0ZQYm5sMHVGSnMweko3eDh1dWNuVXNFcC9KNlJPM0RCSjV4UmNwMHd1REd5d0s2NEMvSktNVmJqS3pZRWwyMmJ2eWNPYUJqRnJkWDJMcGk3QmJjeTJtZUQwQ2pIS0VndHltWWxUUm1QenR5K3BTYk9MR0VpaXh0My9ydzVtWFNBTWRyRVVIQkdBNzlPRFpDcjFWcFNqVC9jTG00SWpqVnJ2SWtWTWl4WVlWdmNkMnJWazJRSlNEOVlmdTNxeHo1OVJTbWNLVGFLdTd1N2YrUDZncVdCTzRNV2JiZkJ1Yk16V0cwaUxjUG9jNHFaTVF2cFhYMWRHM0ZtQ1JOVzNOQkJmazZKVkNobkc0U09wMDJTejVtVnpoWWlLQk1tWWp2cjlPYlZ2ZUxHZG12Ui9LMW1jOGVEU3dOM2JkMzgvY2lJclp5N3BQZzZVaEdXWHlRek1SdzdUbkJaNEI1TUUvRkJ3eWh1QjFGWmNadEp5c2NhaHh4eHd6cG50bjBjVEZoeGQzZnJwdmdqMGhpRE5FWmdra3lPTGNTRjZudllQWS85UDNXSkpHQzIxaWdiY0tPNDBldzNKeWM1OGx6TFJaU1gzYVMzTHNRdjFzUDViMjkrRlkrRGVJdjdYR1d0dWJpUlpwSExMbURDaW52UHpwUHN5YUN0eFVkRzVPSFMwSkQrL1hjK1E3Ykh2b3BlZkxSaFAxT1hMOXd1Yml6Z3BNUXJnMFZ4RzlDZzhZWW5jdHRCczBvN2UwWW1PMnlqNzM2U0JLV3lrU21BcWFKOW1jaHhpbC9LMVN2MVRBRmVjTHU0c2JzZ0pWNFpMSXA3ZUhpRVhCNC9lTVJ0QjFzeXZrTmRrZGZIWTZhUUx5YkdmMFV1djN5SjlQcjlsV2c1MTkzR3lId25Kc3k5NHA0K0pibS9mNUNVZUdVd0YvZUN1WnZKdFhIRkJCZTNQRmx1OHVUU1FTeGZzbk5jeEgzdjdpTmZNVGtwWUlpZlpjSzRLLyt0SXlWb0ZCVXEvY1JKN0RIQno4akZzWE1pSlJ5R2U4VTl4VC94bXJLQk9TeTB5eFoxcDRPSE5SeVlpVHZtN1ZucDlYVnRIUHVPVXFWOS90enk5bjFDaTF2c0hidDBjVmF1b29Rdlo3Nlp3bFlrNklTNHNjVkI5T1hrMC9nMUxFUkJTb3dDbWZlS3BiaWRUQm9QM2F4WXVvdnZjYlFieGMyTHVCTm16MGdiSEh4T3pQRkJXU25FamNXUWE5TXBVc2MzNjhNTGZqcHhtVmhuWVVLTEc4a0FCcEU1eE9KRnNUYzdpRkowUXR5WEx0eUhkNDdPcGdha0tLODJrQklzbEpYYzROd0dJSUwzMFNOVnBJUmpjTHU0cVZOMEJ5anhpWjMxWm9wejRqNVRiaEs1aVYvNnJORUpZcXhnRFl0OFFSNzNOYVFKTHU1eEkxOXg2L1VqLy9vZ214dTJoUWtmcmJmOFhBalR2SHBWdG9UejJNUTdGbXRJZnorUEEvbi9oOGpkM2QwZnRHaTczZU5lWGtSN3dKcWFCOFFIRFkrNExZTTZhQkNabnRvZ1RuakhYTDFpSVd3eitQbmtaWTR1UVF4T1hxN0p5WUp0dkViaWZtdDZxblBpQnI0NlVpV2pqdC9qYVMxeGpUdEhUSEZxOGpmRUFRMVBXbUlCQ052dnJOak5tWGhZQ0E5V0dKaXp0eGN2SHVqMFpZLzd6bllNUE93bkU0eHR6ZktnSFJKdmsxcllOc3labGRuVzFzMlVzUXUzaXh2ZUpjSUV1NVNKa3Z3a3NjNjk0TXJnK0xIcUpZRlo2Qm8xWlNMdUREcEMrZ0RmK0JRTEU1UWkvNXBZcHpHaHhZM0VEaHZLL054U3ZwdzV6YVVONWNrZmYrVXF6Q3ZhWDVwNDZTSzE2ajBiTm55ZzdQaFQyU05CcVZwUTF2TG5vb1pnWlh2cm9CNlhpazVkdFpCNUN4UDM3SEwwYlNxM2lqdktYeHIzUlhiaHdRTm43SEovUVJuVTZmckQ2V3ZLeHZ3Y1RGa1pad1lkNFh2VUUxampDeW9ZNTdUWEtISzc1VkVnb3RIS1piczVHU0cyaGhGaE9iamFvemVzdk5rcHFQbE5VTm9zS0ZGUmhNU3ZQSjFYVFoyM0R3M3BWNzMzR1FhRVhWZmlFek45U29wYTNVbWJ0d00zaWh1TDVQUXBTYytmVTNmcGE0R2RPMDZ3WC9oNTdjVHRoa09jd3djclVKaGRGNTJWQ21PWkU4Y1RiVHJCci8yQzRpYkI2VVlqUzlWdlZIYWNhcVAwOStNUE5WUXZUUE1pR0l5Tk9rU2J0d1AzaXZ2M09hRWNMMnpKWk03WFNQdnhzMGZjdHREVnBac3pNNDN6bmpIcWhnVXJSdWdsZU1GNXRlQnN1NG15d2FJR0tINWJReThLUEIwY0NscTRuZU1kSXliMWlibHkyZVRveHlJODRuWWNIbkViVGRrVnQ4SHdJbnR2SVNkcHBoL3J4bFpWVXQ4dlFSQmU1WTJDczIxY2NZT1hlbmMzVXVJR2ZqcHgyVi9DT2JDa1Jpa3NPR2R3ME00T3pKcTRkUU11ZmVCakRtdmk3bnIxTDA2TkY3WnU5b2g3MUpSZGNiZTBQUEdYeFdPT1RTcjZ4SzhMejRVVUdLVFdhZ1hWM1Z4bGd4ZDdkdGYzTUdWR1JnekxnN2dIbHFCTW1GaFZlWnNwWXcwV3hSMGdpMGRTMUZEZlhsL1h4b3YzN3ozdTYzdEtUSnZDRTdrdDRBOHNiZ3lOMUllYmJRZklrbW91R1k4R2FuWDZ2NTdUVUprSlVwRXhaWi9UL3EycytYR2ZNYmlPUHZObW02SU81TjlkdnN2OEkyMDJ6TVVOWXZXWU5raytZMm95Tm55OE9HTnFSbkdSa3BnMmhibTRRYWt3ZXVIOHJZc1hibk9hUVl1eTNsK3hwOXRtRW5YcDR2MGxnYnNYLzJPYmk1dzJHYnRKdGc3bFNRbkdGOW9BajdnSjd0MTlOSDFxT2pkc0N4UFdydjdDWVBvZS9jblcvamNxV3FsdDVUbXQ0THhXY0tIN0wrVXRlWTBtVDdJSGRNL29ObkQwSFNVVEpSU2R1a29LV1lKRmNZTm9tQk9VaVpKUC9GQkRUSnZDb3JoQkZ6OHp3NGpKaE5GYURjblFMS0trK0xxdk9JVlQwUW5TT2h4ck9mVU4rT2VmL2tKODBQQ0ltd0tpS1c1NitybVM4VkFBZmNSTWw1ZmRJSVZZS05ib1F1cDA4ODZyNTFXM1JOelFLTnN0ZkwzeS9iY1h6R1dLaFA3RDkvWU9XRStnclluYk9hTFhXRU9JYVZOWUU3ZUxoRGFtK2lkMmFtM2xOcHkzQWwwbm5FTFpxMWQ5enNuQmVJdjc3SmxiQ0FraUwwYmZGREdDa2VIVVp5a3VZc1hTWFhTZjJiZk5lSWtidDdVOExja2tJV09qN21HcnlEdWE3dGRZRmNwN1dMREN4bHVkdzBQNmtTR3JUNFdIaHZSTEFyZHpEaXhCdENRdngrcGZHanA2cEpLK3g1Zy9IZU8weE1rYlJaaHlHNUg3NzNNeU1lRDBhYTRydmhqU3J6SFJMMVQ1Q21NMEhiWWlkMm5KRFRSc3JKRm1wdXlTVklTbXFZVkNsRHpaTDJuVHhvTzl2UVBFd1NoNGk3dWkvQlk2UUs5NlVBTkZ6TmE2c0Z4eTJRWFFCMDdVZmc3aGphR2ZKSDFEcERPM3pkZ2Y1VUhuOFM4OUNvbVphZCtTeTZZd0dBeWJQanBBVHpQcno4RUk1ZGhLVmxYV2trSk80ZFRQVjN4RktVd2JhSnNKektJL2QzWkdlenZaZlhJQWp6T21wZEt4ZzBwRk1DREc2ZzVUUWo0c3A3NFlxanhyZFFzYnVuWWZmWUpObFVRVmpoRkhTVVo0N09GcDFKb1BzM1UydjNpNC9PdkRBQm4yTnBTc3laano2ZU5vRE1KMktENHA0V2hCWHNYMWEwM0V0Q2w0aTd1am8vZDAwYlhpMDBZV0ZTb3R2Z1hLRjIxdDNhb216VmVISzhPRGM4T0NjeEExMTRYdHp6ZDdqOUVSWktRZWp3ak5oNFh3a056SWlId2tlYzNOblYxUExPOXlrSk8wUHU1NitMQnRmMzQ1N1pkeWplcnA5amFnZHRIVE01QXMvem9pTkE4R21jYnMvZlNYMnplYm14bzExdjUyRHhhSzl2YnVacFcydnE0ZFFYZERaRDVxTWRVZEk5VjR4YjdpdTNjZndVaUx1bE92dDNwQzN0T2pReG53MWsxVlFWN3BXSFZlREEvSldSZVdkK2hBeGQwN0xiUTFqVzFsQThQREl5MHRuU2o4NEg0cktrYUU1TUFJeDZ4RmhnZFRKWTk4V1htSDl2WDRVUmV4YUFXOHhlMkJCNjhIWHI3OEh5aHIxQzFibUo3OEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNy0xNiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiVW5pdmVyc2FsIFNlY29uZCBGYWN0b3IgKFUyRikiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDE4MDUyMzAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTA3LTE2In0seyJhYWd1aWQiOiJlYWJiNDZjYy1lMjQxLTgwYmYtYWU5ZS05NmZhNmQyOTc1Y2YiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImVhYmI0NmNjLWUyNDEtODBiZi1hZTllLTk2ZmE2ZDI5NzVjZiIsImRlc2NyaXB0aW9uIjoiVE9LRU4yIFBJTiBQbHVzIFNlY3VyaXR5IEtleSBTZXJpZXMgIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsiZnIiOiJTw6lyaWUgZGUgY2zDqXMgZGUgc8OpY3VyaXTDqSBUT0tFTjIgUElOIFBsdXMifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjYsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNMRENDQWRJQ0NRQ3YxdmxxS2VXNWVqQUtCZ2dxaGtqT1BRUURBakNCbkRFTE1Ba0dBMVVFQmhNQ1EwZ3hEekFOQmdOVkJBZ01Ca2RsYm1WMllURVFNQTRHQTFVRUJ3d0hWbVZ5YzI5cGVERVBNQTBHQTFVRUNnd0dWRTlMUlU0eU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1STXdFUVlEVlFRRERBcDBiMnRsYmpJdVkyOXRNU0F3SGdZSktvWklodmNOQVFrQkZoRnZabVpwWTJWQWRHOXJaVzR5TG1OdmJUQWdGdzB4T1RBMU1UUXdOalUwTWpGYUdBOHlNRGN5TURVeU1EQTJOVFF5TVZvd2dad3hDekFKQmdOVkJBWVRBa05JTVE4d0RRWURWUVFJREFaSFpXNWxkbUV4RURBT0JnTlZCQWNNQjFabGNuTnZhWGd4RHpBTkJnTlZCQW9NQmxSUFMwVk9NakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVUTUJFR0ExVUVBd3dLZEc5clpXNHlMbU52YlRFZ01CNEdDU3FHU0liM0RRRUpBUllSYjJabWFXTmxRSFJ2YTJWdU1pNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVRqYlNaZDYxLzdIYW94eW94bDN5aDZ0amszdEw2QVNDQ3VtLzJuZHE4NkRRTHQrRFU2TVY2ZjQvKyt1cEFQYlRaVTZqV252SUxvdnRuc1JnQ1d3VVlSTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUVpTmZOcEFMWklIOG4xVnlYcEZ5TEl6RGVaRVpPQ1JpS2g0NHVuaWFCWlBBaUVBb2Rhbk9sUFVFQ2pHSEVmK0U0ZFRLa3lDbHBMaTRKZEVKa1ZIUXBJWEVKQT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBWUFBQUJ6ZW5yMEFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUErZEpSRUZVZU5yRWwwOW9YRlVVeG4vM3Z2Zm1qek9kbVpjbWNTYWttVXlHcW9Rb2xCUVhNVjJKLzdEdWxMWUdGSEZSTjBKMElRaFNVQXAyMlkwdXRCWkxzYUpZTUdoQVRWMUlOeEpyMVpLbU5xVVlNNWtZazJrbU16R1ptZmZ2dWhoSnRVTG1qUTdOV2I1MzN6a2Yzem5mZDk0VjA1bCtnTWVCVjRGN3VUMXhDVGdHakl2cFRQOUR3RmRzVHp3c2dlTnNYeHlYUUhZYkFXUjF3QWFDdmo4UkFwVENXOS9BTFpmQmRSR0JBRm9pamdnR1FhbG1BTmc2NFBtdXJldTR4U0oyWVpsQXVwZm9udnNRd1NCdWNaWHE1U3U0K1htTTdsMklVQWhjMTA5S1QyK211TDM0T3pJY291dllVY3huUnpDU3ljMzMxYW5MRk41K2w1VjNUaUlUY1hUVFJQa0FJYVl6L1NVZzF1aWdXeXdTNkUyVC9Yb2NyYTBOZ0kzdnZzZWFuU1BZMTB0NGNBOEF4UTgrSXZmY1liUTJFeG1KTkdwSjJUOERtbzV5WGF6NUJmU05Dcm5ETDdMMjVUbVVXMFZxSVNMRFEvU2NQb0U1Y2dDblVDQS8rakxCdnQydFkwRG9PczdLQ2dpSm5vaFQrMlVXb3l1RkNCZ295NkdhdTBwa1lDKzdKODhqd3lGbTl1NmpObk1OdlgzbmxneEl2d3dveDBGTEpKQUJBN2RVSnRDYlJ1ZzZlQXFoYTRTekE2eFBYYUQ0L21rQVl2c2Z3MTFiYlpoWE5xVmF6ME1FZzhob0JMeGJ4S01VR2lIV3Y1MEVJTmlYQnR3V0E1QVNaVmtvMndZcC8rVVBDaHN0R3ExanJWcStVdXJOR0pDeUxGVE5RamtPMHZNUTRYQ2RDU2xSR3hzb1BCSUhud1NnOHNPUENBSXRCQURZdVRsNlRyMEhta1orOUJXa2xBakRRRmtXWHFWSzZzZ2JSUFk5Z0xOOGc5TFpNZlRPemhhMVFFcnNYSTdJMEJEbU0wOWpqaHdnY3Y4Z1R1RkduZTVTbVVBbVRmTDExd0RJUGY4Q3p2SXlXbXhIaXhod1hKUnRreng2QklDMUx5YjQ0NXZ6bXhMVEVnbXN1WGxXVHA3Q21wMmovTm5uQlBxeUxYSkNJYkR6ZVNMRFEyVFBqUU9LbWNGaHFsUFRHTHU2NnpNZ0JIZ0taMmtKNVhrWXFlVG0wbW9RUHB4UUtiemFPdWFoQXdDVVBobGovZUlrb2N6ZE42V29GRWpRT3RvUlF0eDgxZ29WZUpVS2dWUVBzZjJQQXJCNjlsTUVCZ2pnN3pVVUNObWNxbjBOb1ZzcUUreS9CLzNPVHBSbFUvbnBFbnJiem1iMy9uOEhvQ3BWZ3RsTWZlVmUrUmxuY1FrWkRyWHNsNmd4QUZ5TTdxNjZEOHd2NEs2dDFYZEFpOEpISmc4dFlkYmJVU2hRYzhyd3EzdkxBUHd6dERZVHZiMERaVnV0QVNEdkNBTVFmZVJCN2pyek1YSkhkR3R0alkyejh1RVpqTTVVS3dBb01PckhqR1NTeEtHbkd2dldjb0dsRTI5aGtQci9ScVJxTll4MEQzcEh1KysrT3I4dFl1Y1g2bi9KUG94b3kwR1VrU2kxcTllb1hMam9HNEFXajZPWkpzcXhHNHBBYjlRRzVkaG84UmhhUE5iVWRQc29EbUJJNFBvMjNveXVTK0NsYlFRd3FnTVR3Qk4vWGM4SGJsUGhLZUJOWU9MUEFRRElzWHFic3FaS0d3QUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRCbG9iIiwiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiJlYWJiNDZjY2UyNDE4MGJmYWU5ZTk2ZmE2ZDI5NzVjZiIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxNTM2LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsidXNiIiwibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoyMDQ4LCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NiwiZmlybXdhcmVWZXJzaW9uIjoxLCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjo2LCJjZXJ0aWZpY2F0aW9ucyI6eyJGSURPIjoxfSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjUwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDEtMTciLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlRPS0VOMiBQSU4gUGx1cyBTZWN1cml0eSBLZXkgU2VyaWVzIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyNDAxMTcwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS40In0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDI0LTAxLTE3In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMS0zMCJ9LHsiYWFndWlkIjoiNTM0MTRkNTMtNTU0ZS00NzAwLTAwMDAtMDAwMDAwMDAwMDAwIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI1MzQxNGQ1My01NTRlLTQ3MDAtMDAwMC0wMDAwMDAwMDAwMDAiLCJkZXNjcmlwdGlvbiI6IlNhbXN1bmcgUGFzcyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoyLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInRlZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJ0ZWUiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiaW50ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNwakNDQWtxZ0F3SUJBZ0lCQXpBTUJnZ3Foa2pPUFFRREFnVUFNSUdtTVI4d0hRWURWUVFERXhaVFlXMXpkVzVuSUVWc1pXTjBjbTl1YVdOeklFTkJNUnd3R2dZRFZRUUtFeE5UWVcxemRXNW5JRVZzWldOMGNtOXVhV056TVJjd0ZRWURWUVFMRXc1VFlXMXpkVzVuSUUxdlltbHNaVEVUTUJFR0ExVUVCeE1LVTNWM2IyNGdZMmwwZVRFTE1Ba0dBMVVFQmhNQ1MxSXhLakFvQmdvSmtpYUprL0lzWkFFQkRCcFRZVzF6ZFc1blJHVjJhV05sVW05dmRFTkJTMlY1WDBWRFF6QWdGdzB5TXpBNU1USXdNREk1TkRSYUdBOHlNRFk1TVRJek1URTBOVGsxT1Zvd2dhWXhIekFkQmdOVkJBTVRGbE5oYlhOMWJtY2dSV3hsWTNSeWIyNXBZM01nUTBFeEhEQWFCZ05WQkFvVEUxTmhiWE4xYm1jZ1JXeGxZM1J5YjI1cFkzTXhGekFWQmdOVkJBc1REbE5oYlhOMWJtY2dUVzlpYVd4bE1STXdFUVlEVlFRSEV3cFRkWGR2YmlCamFYUjVNUXN3Q1FZRFZRUUdFd0pMVWpFcU1DZ0dDZ21TSm9tVDhpeGtBUUVNR2xOaGJYTjFibWRFWlhacFkyVlNiMjkwUTBGTFpYbGZSVU5ETUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFN20ydTNaMXhYVktmSldOeU5FM0hMMk0wTlpNT29BRElaTGxzNTluUnRDSHR2UjFtZ1UyeVpOdE9jWVBPNTZ1NURpcmc3bWtTN1NSTXhlWjZzWGVlM0tOak1HRXdId1lEVlIwakJCZ3dGb0FVc3BsemE3ZG5NU3lUZEhpcEpLazNQR09RUmtFd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUNBUVl3SFFZRFZSME9CQllFRkxLWmMydTNaekVzazNSNHFTU3BOenhqa0VaQk1Bd0dDQ3FHU000OUJBTUNCUUFEU0FBd1JRSWdOTXpvRjczRGtTWmIxRlgycU52R09kZjd5OFpZS1FOc1dyaDJObHdxUWo4Q0lRRGRPNmkra2U1ZTVLK2tFcFhsOU9YdTI4V3V1bCtaeTRKZzRtRlRLQ0xTVUE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQRDk0Yld3Z2RtVnljMmx2YmowaU1TNHdJaUJsYm1OdlpHbHVaejBpVlZSR0xUZ2lQejQ4YzNabklIWmxjbk5wYjI0OUlqRXVNU0lnZDJsa2RHZzlJalV5Y0hnaUlHaGxhV2RvZEQwaU5USndlQ0lnZG1sbGQwSnZlRDBpTUNBd0lEVXlMakFnTlRJdU1DSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklpQjRiV3h1Y3pwNGJHbHVhejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TVRrNU9TOTRiR2x1YXlJK1BHUmxabk0rUEdOc2FYQlFZWFJvSUdsa1BTSnBNQ0krUEhCaGRHZ2daRDBpVFRNMk1Dd3dJRXd6TmpBc09EQXdJRXd3TERnd01DQk1NQ3d3SUV3ek5qQXNNQ0JhSWo0OEwzQmhkR2crUEM5amJHbHdVR0YwYUQ0OFkyeHBjRkJoZEdnZ2FXUTlJbWt4SWo0OGNHRjBhQ0JrUFNKTk1qWXNNQ0JETXpNdU9Ua3hNREkzT0N3d0lEUXhMakV6T1RVNE16TXNNQzQ1TnpVZ05EVXVPVEE0TnpjM09DdzFMamMzTnpjM056YzRJRU0wT1M0M01UQXhPVFEwTERrdU5qQTFPVEUyTmpjZ05USXNNVFV1T0RZMU1EVTFOaUExTWl3eU5pQkROVElzTXpZdU1UTTBPVFEwTkNBME9TNDNNRGs0TXpNekxEUXlMak01TkRRME5EUWdORFV1T1RBNE1EVTFOaXcwTmk0eU1qSTFPRE16SUVNME1TNHhNemc0TmpFeExEVXhMakF5TkRZek9Ea2dNek11T1Rrd016QTFOaXcxTWlBeU5pdzFNaUJETVRndU1EQTRPVGN5TWl3MU1pQXhNQzQ0TmpBM056YzRMRFV4TGpBeU5EWXpPRGtnTmk0d09URTFPRE16TXl3ME5pNHlNakkxT0RNeklFTXlMakk1TURFMk5qWTNMRFF5TGpNNU5EUTBORFFnTUN3ek5pNHhNelE1TkRRMElEQXNNallnUXpBc01UVXVPRFkxTURVMU5pQXlMakk0T1Rnd05UVTJMRGt1TmpBMU5UVTFOVFlnTmk0d09UQTROakV4TVN3MUxqYzNOemMzTnpjNElFTXhNQzQ0TmpBd05UVTJMREF1T1RjMUlERTRMakF3T0RZeE1URXNNQ0F5Tml3d0lGb2lQand2Y0dGMGFENDhMMk5zYVhCUVlYUm9QanhzYVc1bFlYSkhjbUZrYVdWdWRDQnBaRDBpYVRJaUlIZ3hQU0l5Tm5CNElpQjVNVDBpTlRKd2VDSWdlREk5SWpJMmNIZ2lJSGt5UFNJd0xqRTVOVGt5TVRFME9IQjRJaUJuY21Ga2FXVnVkRlZ1YVhSelBTSjFjMlZ5VTNCaFkyVlBibFZ6WlNJK1BITjBiM0FnYzNSdmNDMWpiMnh2Y2owaUl6STVNamxDTWlJZ2IyWm1jMlYwUFNJd0pTSStQQzl6ZEc5d1BqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTXhRVFF3UTBNaUlHOW1abk5sZEQwaU1UQXdKU0krUEM5emRHOXdQand2YkdsdVpXRnlSM0poWkdsbGJuUStQR05zYVhCUVlYUm9JR2xrUFNKcE15SStQSEJoZEdnZ1pEMGlUVE0zTGpFNU5EUTBORFFzTUNCTU16Y3VNVGswTkRRME5DdzFMamN5TWpJeU1qSXlJRXd3TERVdU56SXlNakl5TWpJZ1REQXNNQ0JNTXpjdU1UazBORFEwTkN3d0lGb2lQand2Y0dGMGFENDhMMk5zYVhCUVlYUm9QanhqYkdsd1VHRjBhQ0JwWkQwaWFUUWlQanh3WVhSb0lHUTlJazB4TGpnNE16UXlNakV6TERBZ1F6SXVOakl3TnpVNU9EY3NNQ0F6TGpZME16VTJOREF5TERBdU1UZ3hOakV3T0RjeElETXVOalF6TlRZME1ESXNNUzR6TWpFeE1UZ3hPU0JNTXk0Mk5ETTFOalF3TWl3eExqWTRPVEV4TlRZeUlFd3lMak0wTWpjNU16TTVMREV1TmpnNU1URTFOaklnVERJdU16UXlOemt6TXprc01TNHpOalE1TURZMU9TQkRNaTR6TkRJM09UTXpPU3d4TGpBM09UVTNOVGN6SURJdU1UWXpNVGsyTmpRc01DNDRPRGt4TlRNek56RWdNUzQ0TlRneE56WTRMREF1T0RnNU1UVXpNemN4SUVNeExqVXlPVE14TnpnNExEQXVPRGc1TVRVek16Y3hJREV1TkRFMk5EZ3pPVGdzTVM0d056VXlOekE0T0NBeExqTTRNRGcxT1RJM0xERXVNalF5TVRVeE1Ea2dRekV1TXpZMk56azJPRGdzTVM0ek1EQXlOalkxTnlBeExqTTJNRGt3TkRBNExERXVOREV4TnpJeE9EUWdNUzR6T0RZeE5EazBNU3d4TGpVeE56STFOemt6SUVNeExqVXpORFl3T0RBeUxESXVNVE13TkRrM015QXpMalV4TWpRME9UQXlMREl1TkRVMk1URTRPRGNnTXk0M016STFOVGc0TXl3ekxqVTFOVFV6TnpJM0lFTXpMamMxTXpjeE9UTTNMRE11TmpZM01EVTVPQ0F6TGpnd01EYzVORGc0TERNdU9UWXhNVE0wT0RnZ015NDNNemd3TkRrNE5pdzBMalF4TXpBd09UWXpJRU16TGpZeE1UZ3lNekl4TERVdU1qZzVOalV5TURNZ01pNDRNemd3TlRjeUxEVXVOakV5TVRjNU5Ea2dNUzQ0T1RVNE1UQTBNeXcxTGpZeE1qRTNPVFE1SUVNd0xqa3hOVGN5T1RFek5pdzFMall4TWpFM09UUTVJREFzTlM0eU5UazVPRGc1TWlBd0xEUXVNRGc0T0RBd05pQk1NQ3d6TGpZNE9ESTBOemN6SUV3eExqTTVPVFF3T0RJekxETXVOamc0TWpRM056TWdUREV1TkRBeE1qRTJNalVzTkM0eE9USXpNVGczT1NCRE1TNDBNREV5TVRZeU5TdzBMalEzT0RZMU9EWWdNUzQxT1RZd09EQTNNeXcwTGpZMk9USTRNamMxSURFdU9USXhPRFU1TXpJc05DNDJOamt5T0RJM05TQkRNaTR5TnpBM05EQTBMRFF1TmpZNU1qZ3lOelVnTWk0ek9EZ3pPVFUyT1N3MExqUTVNVFV3TlRnNUlESXVORE14TVRnMU5USXNOQzR6TVRVME1UQTJNU0JETWk0ME5UWXlNams1Tml3MExqSXhOak01T1RBMUlESXVORGN4TkRrM05qa3NOQzR3TlRRMk16QTROU0F5TGpReU1UQXdOekF6TERNdU9USTROalEyTnpFZ1F6SXVNVFV4TXpRME1EWXNNeTR5TlRBNU5qa3hNU0F3TGpJNU56a3lNVFkzTnl3eUxqazBNVEk0T0RrMUlEQXVNRGN5TVRFNU9UUTNNeXd4TGpnM01ETXlNamt5SUVNd0xqQXhOek0wTXpZd09EVXNNUzQyTURVMk5ERTRPU0F3TGpBeU16Z3pPVEE1TVRJc01TNHpPVGt3TnpZek5DQXdMakEyTVRjME1EVTJOemNzTVM0eE5qUXlOakF5TVNCRE1DNHlNREF5TWpFMU9ERXNNQzR6TURnNE56TXdNRGNnTUM0NU5UY3hNVEkzTWpjc01DQXhMamc0TXpReU1qRXpMREFnV2lCTk1UZ3VPRFF4TVRFNE5pd3dMakF5T1RZMk16RXdPRGtnUXpFNUxqVTNNRFE0Tnpjc01DNHdNamsyTmpNeE1EZzVJREl3TGpVM056ZzVNREVzTUM0eU1EWTVOamt4TWprZ01qQXVOVGMzT0Rrd01Td3hMak16TlRZME56QTJJRXd5TUM0MU56YzRPVEF4TERFdU56QXdOelV5TVRjZ1RERTVMakk1TWpFNE5qUXNNUzQzTURBM05USXhOeUJNTVRrdU1qa3lNVGcyTkN3eExqTTRNRFEwTkRReElFTXhPUzR5T1RJeE9EWTBMREV1TURrM05EQXdOU0F4T1M0eE1UVTJNRE1zTUM0NU1EZzNPVFF5TlNBeE9DNDRNVFEwTURBeExEQXVPVEE0TnprME1qVWdRekU0TGpRNU1USXpNekVzTUM0NU1EZzNPVFF5TlNBeE9DNHpOemt3TmpnNExERXVNRGt4TmpFMU9EWWdNVGd1TXpReE56Y3NNUzR5TlRrek56QTBPU0JETVRndU16STVOemd6TlN3eExqTXhOamd4TXpNMElERTRMak15TXpBNE56RXNNUzQwTWpZMk5UUXlPQ0F4T0M0ek5EWXlOVFkyTERFdU5UTXdNVGN5TkRnZ1F6RTRMalE1TkRNeE16UXNNaTR4TXpZME1UWTBOeUF5TUM0ME5UQXpPVEV5TERJdU5EWXpNVEUwTWpVZ01qQXVOalkyTURFME5Dd3pMalUwT1RJeE5EVXlJRU15TUM0Mk9EazJOVEkyTERNdU5qVTVNRFUxTkRjZ01qQXVOek0wTURRNU5pd3pMamsxTURjd09UQTNJREl3TGpZM05URTRPRFVzTkM0ek9UZzBNVE0xSUVNeU1DNDFOVEUzTnpRekxEVXVNalkxTVRBd09UTWdNVGt1TnpneU5EazBPU3cxTGpVNE5EZ3dNek16SURFNExqZzFNVEE1TmpJc05TNDFPRFE0TURNek15QkRNVGN1T0RjNE5UZ3hPQ3cxTGpVNE5EZ3dNek16SURFMkxqazNOVFkwTWpnc05TNHlNelUwTXpjNE15QXhOaTQ1TnpVMk5ESTRMRFF1TURjM05UQXdNemNnVERFMkxqazNOVFkwTWpnc015NDJOemM0T0RreE9TQk1NVGd1TXpVNU5URTFOQ3d6TGpZM056ZzRPVEU1SUV3eE9DNHpOVGs1TVRjeUxEUXVNVGd3TmpFME9UZ2dRekU0TGpNMU9Ua3hOeklzTkM0ME5qTXdOVE0xTWlBeE9DNDFOVFV4T0RNMExEUXVOalV3TkRRNU1ETWdNVGd1T0RjNU56VTJOeXcwTGpZMU1EUTBPVEF6SUVNeE9TNHlNalUzTlRnekxEUXVOalV3TkRRNU1ETWdNVGt1TXpReU5EYzJNU3cwTGpRM05URTJNRGt4SURFNUxqTTRNak00TmpVc05DNHpNREE0T0RFM05DQkRNVGt1TkRBMk16VTVOU3cwTGpJd05UVTJPVFkySURFNUxqUXhPVGd4T1RJc05DNHdORE00TURFME5pQXhPUzR6TnpJNE1UQTNMRE11T1RFMk9UUXlPU0JETVRrdU1UQTJOREk0T1N3ekxqSTBOekkyT1RZeklERTNMakkzTVRFMU16Y3NNaTQ1TkRBd056Z3lNU0F4Tnk0d05EYzNOakkzTERFdU9EZ3hNVFV5TXlCRE1UWXVPVGt3TVRBMk9Td3hMall4T1RNMk16WWdNVFl1T1RrNU1EZ3dNU3d4TGpReE5ESXhNRFU0SURFM0xqQXpOVE13TnpRc01TNHhPRE13T1RNNU15QkRNVGN1TVRjeU16RTFNeXd3TGpNek16Z3lOelk0TmlBeE55NDVNakkxTVN3d0xqQXlPVFkyTXpFd09Ea2dNVGd1T0RReE1URTROaXd3TGpBeU9UWTJNekV3T0RrZ1dpQk5Nak11TWpNMk5EZzBOU3d3TGpFMk5qZzRNREl4TVNCTU1qTXVNak0yTWpJNU1TdzBMakV4TVRNM016WTJJRU15TXk0eU16Y3lNRFl6TERRdU1UVTNPVGcwTmpJZ01qTXVNalF3T0RneE9DdzBMakl3TkRBMk56UTFJREl6TGpJME9UWTNOalFzTkM0eU5ERXhOVEU1TkNCRE1qTXVNamMxTVRJeU5pdzBMak0zTVRJek9URXpJREl6TGpNNE56YzFOVFlzTkM0Mk1qRTFPVE13T0NBeU15NDNORFk1TkRreExEUXVOakl4TlRrek1EZ2dRekkwTGpFeE1EZ3pNREVzTkM0Mk1qRTFPVE13T0NBeU5DNHlNakExT0RNMkxEUXVNemN4TWpNNU1UTWdNalF1TWpRNE1UQTFOeXcwTGpJME1URTFNVGswSUVNeU5DNHlOVGsyT1RBMUxEUXVNVGcxTlRJMU1pQXlOQzR5TmpFM05qWXpMRFF1TVRBNU5qVXlNaklnTWpRdU1qVTVOamt3TlN3MExqQTBNakV4T1RnNElFd3lOQzR5TlRrMk9UQTFMREF1TVRZMk9EZ3dNakV4SUV3eU5TNDFOemcyTURnekxEQXVNVFkyT0Rnd01qRXhJRXd5TlM0MU56ZzJNRGd6TERNdU9USXhPRFV6TVRJZ1F6STFMalU0TkRNd01ESXNOQzR3TVRnMk5EUTVPU0F5TlM0MU56UTNNalEwTERRdU1qRTJNems1TURVZ01qVXVOVFkzTkRJMU15dzBMakkyT0RFNU1UYzRJRU15TlM0ME56UTNORGMxTERVdU1qUTJOamN3TnprZ01qUXVOekEzTkRjM0xEVXVOVFkwTXpVMU1qa2dNak11TnpRMk9UUTVNU3cxTGpVMk5ETTFOVEk1SUVNeU1pNDNPRGd5T1RZeUxEVXVOVFkwTXpVMU1qa2dNakl1TURJd05UVTNMRFV1TWpRMk5qY3dOemtnTWpFdU9USTVOVFV6TWl3MExqSTJPREU1TVRjNElFTXlNUzQ1TWpNNE5qRXpMRFF1TWpFMk16azVNRFVnTWpFdU9URTJNamswTkN3MExqQXhPRFkwTkRrNUlESXhMamt4TnprMk9EVXNNeTQ1TWpFNE5UTXhNaUJNTWpFdU9URTNPVFk0TlN3d0xqRTJOamc0TURJeE1TQk1Nak11TWpNMk5EZzBOU3d3TGpFMk5qZzRNREl4TVNCYUlFMHpOQzQyTWprM05qSXhMREF1TURJMU9UWXpOakk0TWlCRE16VXVOVFV6T1RrMU5pd3dMakF5TlRrMk16WXlPRElnTXpZdU16WXdNRE00TWl3d0xqTXpOamcxTkRVek5DQXpOaTQwTlRnM05ESTNMREV1TXpFNU5UQXpPRGNnUXpNMkxqUTJOVFUzTXl3eExqTTVNVEU1TmpreUlETTJMalEyT0RNNE1UUXNNUzQwTmpVeE1UTTNPQ0F6Tmk0ME5qa3pOakEzTERFdU5USTJNVGd3TWpJZ1RETTJMalEyT1RBd05Dd3hMalkxTlRjMU5EQXlJRXd6Tmk0ME5qZzNNakF6TERFdU5qWTJNVGM0T0RRZ1RETTJMalEyT0RjeU1ETXNNUzQ0TXpnd016WTFOQ0JNTXpVdU1UVTFNell3TlN3eExqZ3pPREF6TmpVMElFd3pOUzR4TlRVeE5Td3hMalV6TXpVMU5UVTJJRU16TlM0eE5UUTBORGN4TERFdU5EazROek16TmpJZ016VXVNVFV4TkRrc01TNDBNRFUyTkRFeU15QXpOUzR4TXprME9UQXhMREV1TXpRMU1qWTFOekVnUXpNMUxqRXhOalkxTlRVc01TNHlNekV6TWpFM0lETTFMakF4TnpBNE1EUXNNQzQ1TmpZd016VXpNRFlnTXpRdU5qRTRNVGMzTkN3d0xqazJOakF6TlRNd05pQkRNelF1TWpNNE1UVTRNaXd3TGprMk5qQXpOVE13TmlBek5DNHhNalUxT1RJeExERXVNakUzTlRrNU9Ua2dNelF1TURrNU5qYzNNaXd4TGpNME5USTJOVGN4SUVNek5DNHdPREUzT1RjNExERXVOREUxTkRJeE16SWdNelF1TURjMk1UQTFPU3d4TGpVd09ERXhNREV5SURNMExqQTNOakV3TlRrc01TNDFPVEkzT1RRMklFd3pOQzR3TnpZeE1EVTVMRE11T1RnMk9EazJOeklnUXpNMExqQTNOakV3TlRrc05DNHdOVFEyTXpBNE5TQXpOQzR3T0RBeE9UQTNMRFF1TVRJM05qRXhOVEVnTXpRdU1EZzVOelkyTlN3MExqRTROakV6TURVM0lFTXpOQzR4TVRJMU16UXlMRFF1TXpJM05URTRJRE0wTGpJME16ZzFNREVzTkM0MU5qZ3lOVE16SURNMExqWXlNRGs0T1Rrc05DNDFOamd5TlRNeklFTXpOUzR3TURBME1EWTBMRFF1TlRZNE1qVXpNeUF6TlM0eE16UXhNek1zTkM0ek1qYzFNVGdnTXpVdU1UVTFNell3TlN3MExqRTROakV6TURVM0lFTXpOUzR4TmpZNU5EVXlMRFF1TVRJM05qRXhOVEVnTXpVdU1UY3dOakk0TWl3MExqQTFORFl6TURnMUlETTFMakUyT0RrMU5ERXNNeTQ1T0RZNE9UWTNNaUJNTXpVdU1UWTRPVFUwTVN3ekxqSXlPRGt3TmpjMklFd3pOQzQyTXpRME5EazJMRE11TWpJNE9UQTJOellnVERNMExqWXpORFEwT1RZc01pNDBOalE1TXpBek5pQk1Nell1TkRjNU1UWTJOeXd5TGpRMk5Ea3pNRE0ySUV3ek5pNDBOemt4TmpZM0xETXVPRFk0TlRFek16UWdRek0yTGpRM056QTVNRGdzTXk0NU5qUTBNekEzT0NBek5pNDBOelUwT0RNM0xEUXVNRE00TmpnNU5EVWdNell1TkRZd01ERTFMRFF1TWpFek9UYzNOVGNnUXpNMkxqTTNNamd5T0RJc05TNHhOamsxT0Rjd055QXpOUzQxTlRNNU9UVTJMRFV1TlRBNE16STBPVGNnTXpRdU5qSTJNRGM1TVN3MUxqVXdPRE15TkRrM0lFTXpNeTQzTURNNE5UUTFMRFV1TlRBNE16STBPVGNnTXpJdU9EYzVNek1zTlM0eE5qazFPRGN3TnlBek1pNDNPVE0yTVRZMExEUXVNakV6T1RjM05UY2dRek15TGpjM05Ua3pPQ3cwTGpBek9EWTRPVFExSURNeUxqYzNNamcxTnpZc015NDVOalEwTXpBM09DQXpNaTQzTnpJNE5UYzJMRE11T0RZNE5URXpNelFnVERNeUxqYzNNamcxTnpZc01TNDJOall4TnpnNE5DQkRNekl1TnpjeU9EVTNOaXd4TGpVM01ESTJNVFFnTXpJdU56ZzROekk0TERFdU5EQTVNRGs0TlRjZ016SXVOems1TVRBM05Dd3hMak14T1RVd016ZzNJRU16TWk0NU1UUXhOVEV4TERBdU16TTVOelEyT0RVMUlETXpMamN3TXpnMU5EVXNNQzR3TWpVNU5qTTJNamd5SURNMExqWXlPVGMyTWpFc01DNHdNalU1TmpNMk1qZ3lJRm9nVFRFeUxqRTBORGMwTkRjc01DNHhOalk0T0RBeU1URWdUREV5TGpnd01qSTJNVFlzTkM0eU5qRTFPVGs1T0NCTU1UTXVORFl3TVRnd05Dd3dMakUyTmpnNE1ESXhNU0JNTVRVdU5UZzFNamMwTml3d0xqRTJOamc0TURJeE1TQk1NVFV1TnpBeE9USTFOU3cxTGpRd05USXhNRE0ySUV3eE5DNHpPVFV5TmpJc05TNDBNRFV5TVRBek5pQk1NVFF1TXpVNU9ETTRNaXd3TGpVMU5Ua3pNVEExTkNCTU1UTXVORFl5TWpVMk1pdzFMalF3TlRJeE1ETTJJRXd4TWk0eE16azROVFl6TERVdU5EQTFNakV3TXpZZ1RERXhMakkwTXpBM056a3NNQzQxTlRVNU16RXdOVFFnVERFeExqSXdOemM0T0N3MUxqUXdOVEl4TURNMklFdzVMamt3TkRRd05UZ3NOUzQwTURVeU1UQXpOaUJNTVRBdU1ERTNNak01Tnl3d0xqRTJOamc0TURJeE1TQk1NVEl1TVRRME56UTBOeXd3TGpFMk5qZzRNREl4TVNCYUlFMDNMamt3TVRJMU1qVXNNQzR4TmpZNE9EQXlNVEVnVERndU9EWXpNalV6TlRnc05TNDBNRFV5TVRBek5pQk1OeTQwTmpRek1UUXhMRFV1TkRBMU1qRXdNellnVERZdU56VXpPREk0T0RNc01DNDFOVFU1TXpFd05UUWdURFl1TURJMU9EWTJNRElzTlM0ME1EVXlNVEF6TmlCTU5DNDJNVGN4TkRrNE15dzFMalF3TlRJeE1ETTJJRXcxTGpVNE16RTJPRGN6TERBdU1UWTJPRGd3TWpFeElFdzNMamt3TVRJMU1qVXNNQzR4TmpZNE9EQXlNVEVnV2lCTk1qZ3VNekEwT0RNMkxEVXVNelV3TlRreU5UY2dUREkzTGpBeU5EWXlNek1zTlM0ek5UQTFPVEkxTnlCTU1qY3VNREkwTmpJek15d3dMakUyTmpnNE1ESXhNU0JNTWpndU9UVTVPRGMxTXl3d0xqRTJOamc0TURJeE1TQk1NekF1TVRnM09Ua3dNeXcwTGpNNE5ETTFOVFEzSUV3ek1DNHhNVFk0TnpRNExEQXVNVFkyT0Rnd01qRXhJRXd6TVM0ME1EVTBOVGd4TERBdU1UWTJPRGd3TWpFeElFd3pNUzQwTURVME5UZ3hMRFV1TXpVd05Ua3lOVGNnVERJNUxqVTBPVFF5TkRFc05TNHpOVEExT1RJMU55Qk1Namd1TWpNc01DNDVPVGtnVERJNExqTXdORGd6Tml3MUxqTTFNRFU1TWpVM0lGb2lQand2Y0dGMGFENDhMMk5zYVhCUVlYUm9QanhqYkdsd1VHRjBhQ0JwWkQwaWFUVWlQanh3WVhSb0lHUTlJazB5TkM0ek16VXlPVFkyTERJdU5EY3dNRFkwTXpJZ1F6STFMak13T1RZMU1ESXNNaTQwTnpBd05qUXpNaUF5Tmk0eE1qRXpNak1zTWk0Mk5UWTJNRFUyTkNBeU5pNDNOamt5TnpZNExETXVNREk0T1Rjek5UWWdRekkzTGpReE56SXpNRFVzTXk0ME1ERTJPVGc0TXlBeU55NDVNamsxTURFM0xETXVPVEE0TkRNek5qY2dNamd1TXpBMk1Ea3dNaXcwTGpVMU1ESTFNREUxSUV3eU5pNHpPVFUwTlRjekxEVXVORGd5TlRrNU16Y2dRekkyTGpFNU5qQTROamtzTlM0eE5EWXpNalEzSURJMUxqa3hPVEU0TXpZc05DNDRPREF3T1RJek5pQXlOUzQxTmpRM05EY3pMRFF1TmpnME5qRTNNRGdnUXpJMUxqSXhNRE14TVRFc05DNDBPRGt4TkRFM09TQXlOQzQ0TURBME9UUXlMRFF1TXpreE1qSTFORGNnTWpRdU16TTFNamsyTml3MExqTTVNVEl5TlRRM0lFTXlNeTQ0TURNMk5ESXlMRFF1TXpreE1qSTFORGNnTWpNdU5ERXdORE01TlN3MExqUTVORGcxT1RVeklESXpMakUxTlRZNE9EVXNOQzQzTURJeE1qYzJOaUJETWpJdU9UQXdOVGt4TXl3MExqa3dPVE01TlRjNUlESXlMamMzTXpVMk1Ua3NOUzR4TkRrMU5EQTVNeUF5TWk0M056TTFOakU1TERVdU5ESXlNakExTnpNZ1F6SXlMamMzTXpVMk1Ua3NOUzQzTXpnME5qZ3pNU0F5TWk0NU5qRTROVFl5TERVdU9UWTFNRE16T0RFZ01qTXVNek00TkRRME55dzJMakV3TURnek1ERTNJRU15TXk0M01UUTJPRGNzTmk0eU16Y3pOREV5TlNBeU5DNHlOamc0TXprNExEWXVNemd5TURjeE5UZ2dNalF1T1RrNU9EWTBOaXcyTGpVek5EWTJNemd4SUVNeU5TNHpPVGcyTURVMExEWXVOakV4TVRNNE5pQXlOUzQzT1RrM05qa3NOaTQzTVRFMU5UWTBOQ0F5Tmk0eU1EUXpPVFFzTmk0NE16Y3pORFkzTlNCRE1qWXVOakE0TmpjeU9TdzJMamsyTWpjM09UY2dNall1T1RjMk9UVTBNeXczTGpFek1UZ3hNRFF6SURJM0xqTXdPVEl6T0RNc055NHpORFEzT1RZek1TQkRNamN1TmpReE5USXlNaXczTGpVMU56UXlORGd5SURJM0xqa3hNREV4T0RVc055NDRNamszTXpJeU5pQXlPQzR4TVRVd01qWTVMRGd1TVRZeU56a3dOeUJETWpndU16RTVPVE0xTkN3NExqUTVOVFE1TVRjNElESTRMalF5TWpNNE9UWXNPQzQ1TVRJMU1qazFOU0F5T0M0ME1qSXpPRGsyTERrdU5ERTBNall4TXpjZ1F6STRMalF5TWpNNE9UWXNPUzQzTlRJek1qSTRNeUF5T0M0ek5EUTROVFkzTERFd0xqRXdORE15TVRNZ01qZ3VNVGc1Tnprd09Dd3hNQzQwTmprMU5ESWdRekk0TGpBek5ETTNPRGdzTVRBdU9ETTBOell5T0NBeU55NDNPVE00TVRreExERXhMakUzTXpFNE1UWWdNamN1TkRZM01EY3pNU3d4TVM0ME9ETTNNalkwSUVNeU55NHhOREF6TWpjeUxERXhMamM1TkRrNE5pQXlOaTQzTWpjM05ERXpMREV5TGpBME9ETTFNelFnTWpZdU1qSTVNekUxTXl3eE1pNHlORFExTkRNMElFTXlOUzQzTXpBNE9Ea3pMREV5TGpRME1UQTVNRGdnTWpVdU1UTXlOemM0TWl3eE1pNDFNemt3TURjeElESTBMalF6TkRrNE1UZ3NNVEl1TlRNNU1EQTNNU0JETWpNdU16WXdOVGsyT1N3eE1pNDFNemt3TURjeElESXlMalEyT0RrMk9ESXNNVEl1TXpNeU9ERXhJREl4TGpjMk1EQTVOVGNzTVRFdU9USXdNRFl4TmlCRE1qRXVNRFV4TWpJek15d3hNUzQxTURZNU5UUTRJREl3TGpVd01qazFORGNzTVRBdU9URXdOVEl5T0NBeU1DNHhNVFV5T1N3eE1DNHhNekF3TlRFeElFd3lNaTR4T1RJd05qUTVMRGt1TVRZMU1UZ3lNalVnUXpJeUxqUXlORFkyTXpjc09TNDJNRFEzTXpNMk15QXlNaTQzTkRBek16TTFMRGt1T1RReU5ETTNOelFnTWpNdU1UTTVNRGMwTXl3eE1DNHhOemcyTlRFNUlFTXlNeTQxTXpjNE1UVXhMREV3TGpReE5EVXdPRGdnTWpRdU1EQXpNREV5Tml3eE1DNDFNekl3TnprNElESTBMalV6TkRZMk55d3hNQzQxTXpJd056azRJRU15TlM0d09EZzBOek0yTERFd0xqVXpNakEzT1RnZ01qVXVOVEF6T0RJNE5pd3hNQzQwTVRjM01qVWdNalV1Tnpnd056TXhPU3d4TUM0eE9Ea3dNVFV6SUVNeU5pNHdOVGN5T0RreExEa3VPVFU1T1RRNE16SWdNall1TVRrMk1EZzJPU3c1TGpZNE56WTBNRGc0SURJMkxqRTVOakE0Tmprc09TNHpOekV3TWpBNU5TQkRNall1TVRrMk1EZzJPU3c1TGpFNU5qWXlPVGd6SURJMkxqRXpNak01T1RJc09TNHdOVFV4TVRVM015QXlOaTR3TURVd01qTTJMRGd1T1RRMU56WXpPVElnUXpJMUxqZzNOelkwT0RFc09DNDRNemN4TWpZNE15QXlOUzQzTVRFMU1EWXhMRGd1TnpReE16VTBOallnTWpVdU5UQTJOVGszTml3NExqWTFPVGczTmpnMUlFTXlOUzR6TURFek5ETXhMRGd1TlRjNE1EUXhOamNnTWpVdU1EWXdOemd6TXl3NExqVXhNREUwTXpRNUlESTBMamM0TXpnNExEZ3VORFUxTVRFd01qTWdRekkwTGpVd05qazNOamNzT0M0ME1EQTNPVEUyT1NBeU5DNHlNVGc1T1RjeUxEZ3VNelF3TnpVMU5DQXlNeTQ1TVRrNU5ERTJMRGd1TWpjMU16VTROek1nUXpJekxqUTVPRGN3TWpVc09DNHhPRGd4TmpNeE9DQXlNeTR3T0RZME5qSTJMRGd1TURnME9EZzJORGNnTWpJdU5qZ3lNVGd6T0N3M0xqazJORGd4TXprZ1F6SXlMakkzTnprd05TdzNMamcwTlRBNU9EWTVJREl4TGpreE5URTJNVFlzTnk0Mk56ZzFOamswTnlBeU1TNDFPVE01TlRNNExEY3VORFkyTWprNE16RWdRekl4TGpJM01qYzBOVGtzTnk0eU5UTXpNVEkwTkNBeU1TNHdNVEkwTlRZNExEWXVPVGd3TmpRM05qUWdNakF1T0RFek1EZzJOQ3cyTGpZME9ETXdNemt5SUVNeU1DNDJNVE0zTVRZc05pNHpNVFU1TmpBeUlESXdMalV4TkRBek1EZ3NOUzQ0T1RnNU1qSTBNeUF5TUM0MU1UUXdNekE0TERVdU16azNOVFEzT1RjZ1F6SXdMalV4TkRBek1EZ3NOUzR3TVRVMU16RXpOeUF5TUM0Mk1EVTBNRGc1TERRdU5qUTNPREE1TVRJZ01qQXVOemc0TVRZMU1TdzBMakk1TXpZMk5qVWdRekl3TGprM01Ea3lNVE1zTXk0NU16a3hOalkxTXlBeU1TNHlNamcwTkRFMExETXVOakkyTVRJd01UZ2dNakV1TlRZd056STFOQ3d6TGpNMU16QTVPREF6SUVNeU1TNDRPVE13TURrekxETXVNRGd3Tnprd05Ua2dNakl1TWprME1UY3pMREl1T0RZMU5qWXdOVFlnTWpJdU56WTFNalUwT0N3eUxqY3dOek0xTURZZ1F6SXpMakl6TlRrNU1EUXNNaTQxTkRrd05EQTJNeUF5TXk0M05Ua3pNemMzTERJdU5EY3dNRFkwTXpJZ01qUXVNek0xTWprMk5pd3lMalEzTURBMk5ETXlJRm9nVFRNekxqRXdOek0xTVRVc01pNDBOekF3TmpRek1pQkRNelF1TURneE56QTFMREl1TkRjd01EWTBNeklnTXpRdU9Ea3pNemMzT1N3eUxqWTFOall3TlRZMElETTFMalUwTVRNek1UWXNNeTR3TWpnNU56TTFOaUJETXpZdU1UZzVNamcxTkN3ekxqUXdNVFk1T0RneklETTJMamN3TVRVMU5qVXNNeTQ1TURnME16TTJOeUF6Tnk0d056Z3hORFV4TERRdU5UVXdNalV3TVRVZ1RETTFMakUyTnpVeE1qSXNOUzQwT0RJMU9Ua3pOeUJETXpRdU9UWTRNVFF4T0N3MUxqRTBOak15TkRjZ016UXVOamt4TWpNNE5DdzBMamc0TURBNU1qTTJJRE0wTGpNek5qZ3dNaklzTkM0Mk9EUTJNVGN3T0NCRE16TXVPVGd5TXpZMU9TdzBMalE0T1RFME1UYzVJRE16TGpVM01qVTBPU3cwTGpNNU1USXlOVFEzSURNekxqRXdOek0xTVRVc05DNHpPVEV5TWpVME55QkRNekl1TlRjMU5qazNNU3cwTGpNNU1USXlOVFEzSURNeUxqRTRNalE1TkRRc05DNDBPVFE0TlRrMU15QXpNUzQ1TWpjM05ETXpMRFF1TnpBeU1USTNOallnUXpNeExqWTNNalkwTmpFc05DNDVNRGt6T1RVM09TQXpNUzQxTkRVMk1UWTNMRFV1TVRRNU5UUXdPVE1nTXpFdU5UUTFOakUyTnl3MUxqUXlNakl3TlRjeklFTXpNUzQxTkRVMk1UWTNMRFV1TnpNNE5EWTRNekVnTXpFdU56TXpPVEV4TERVdU9UWTFNRE16T0RFZ016SXVNVEV3TkRrNU5TdzJMakV3TURnek1ERTNJRU16TWk0ME9EWTNOREU1TERZdU1qTTNNelF4TWpVZ016TXVNRFF3T0RrME55dzJMak00TWpBM01UVTRJRE16TGpjM01Ua3hPVFFzTmk0MU16UTJOak00TVNCRE16UXVNVGN3TmpZd01pdzJMall4TVRFek9EWWdNelF1TlRjeE9ESXpPU3cyTGpjeE1UVTFOalEwSURNMExqazNOalEwT0Rrc05pNDRNemN6TkRZM05TQkRNelV1TXpnd056STNOeXcyTGprMk1qYzNPVGNnTXpVdU56UTVNREE1TVN3M0xqRXpNVGd4TURReklETTJMakE0TVRJNU16RXNOeTR6TkRRM09UWXpNU0JETXpZdU5ERXpOVGMzTVN3M0xqVTFOelF5TkRneUlETTJMalk0TWpFM016TXNOeTQ0TWprM016SXlOaUF6Tmk0NE9EY3dPREU0TERndU1UWXlOemt3TnlCRE16Y3VNRGt4T1Rrd01pdzRMalE1TlRRNU1UYzRJRE0zTGpFNU5EUTBORFFzT0M0NU1USTFNamsxTlNBek55NHhPVFEwTkRRMExEa3VOREUwTWpZeE16Y2dRek0zTGpFNU5EUTBORFFzT1M0M05USXpNakk0TXlBek55NHhNVFk1TVRFMUxERXdMakV3TkRNeU1UTWdNell1T1RZeE9EUTFOeXd4TUM0ME5qazFORElnUXpNMkxqZ3dOalF6TXpjc01UQXVPRE0wTnpZeU9DQXpOaTQxTmpVNE56TTVMREV4TGpFM016RTRNVFlnTXpZdU1qTTVNVEk0TERFeExqUTRNemN5TmpRZ1F6TTFMamt4TWpNNE1qRXNNVEV1TnprME9UZzJJRE0xTGpRNU9UYzVOakVzTVRJdU1EUTRNelV6TkNBek5TNHdNREV6TnpBeUxERXlMakkwTkRVME16UWdRek0wTGpVd01qazBORElzTVRJdU5EUXhNRGt3T0NBek15NDVNRFE0TXpNc01USXVOVE01TURBM01TQXpNeTR5TURjd016WTNMREV5TGpVek9UQXdOekVnUXpNeUxqRXpNalkxTVRnc01USXVOVE01TURBM01TQXpNUzR5TkRFd01qTXhMREV5TGpNek1qZ3hNU0F6TUM0MU16SXhOVEEyTERFeExqa3lNREEyTVRZZ1F6STVMamd5TXpJM09ERXNNVEV1TlRBMk9UVTBPQ0F5T1M0eU56VXdNRGsxTERFd0xqa3hNRFV5TWpnZ01qZ3VPRGczTXpRME9Td3hNQzR4TXpBd05URXhJRXd6TUM0NU5qUXhNVGs0TERrdU1UWTFNVGd5TWpVZ1F6TXhMakU1TmpjeE9EWXNPUzQyTURRM016TTJNeUF6TVM0MU1USXpPRGd6TERrdU9UUXlORE0zTnpRZ016RXVPVEV4TVRJNU1Td3hNQzR4TnpnMk5URTVJRU16TWk0ek1EazROams1TERFd0xqUXhORFV3T0RnZ016SXVOemMxTURZM05Td3hNQzQxTXpJd056azRJRE16TGpNd05qY3lNVGdzTVRBdU5UTXlNRGM1T0NCRE16TXVPRFl3TlRJNE5Td3hNQzQxTXpJd056azRJRE0wTGpJM05UZzRNelVzTVRBdU5ERTNOekkxSURNMExqVTFNamM0Tmpnc01UQXVNVGc1TURFMU15QkRNelF1T0RJNU16UTBMRGt1T1RVNU9UUTRNeklnTXpRdU9UWTRNVFF4T0N3NUxqWTROelkwTURnNElETTBMamsyT0RFME1UZ3NPUzR6TnpFd01qQTVOU0JETXpRdU9UWTRNVFF4T0N3NUxqRTVOall5T1RneklETTBMamt3TkRRMU5DdzVMakExTlRFeE5UY3pJRE0wTGpjM056QTNPRFVzT0M0NU5EVTNOak01TWlCRE16UXVOalE1TnpBeU9TdzRMamd6TnpFeU5qZ3pJRE0wTGpRNE16VTJNU3c0TGpjME1UTTFORFkySURNMExqSTNPRFkxTWpVc09DNDJOVGs0TnpZNE5TQkRNelF1TURjek16azNPU3c0TGpVM09EQTBNVFkzSURNekxqZ3pNamd6T0RJc09DNDFNVEF4TkRNME9TQXpNeTQxTlRVNU16UTRMRGd1TkRVMU1URXdNak1nUXpNekxqSTNPVEF6TVRVc09DNDBNREEzT1RFMk9TQXpNaTQ1T1RFd05USXhMRGd1TXpRd056VTFOQ0F6TWk0Mk9URTVPVFkxTERndU1qYzFNelU0TnpNZ1F6TXlMakkzTURjMU56TXNPQzR4T0RneE5qTXhPQ0F6TVM0NE5UZzFNVGMxTERndU1EZzBPRGcyTkRjZ016RXVORFUwTWpNNE5pdzNMamsyTkRneE16a2dRek14TGpBME9UazFPVGdzTnk0NE5EVXdPVGcyT1NBek1DNDJPRGN5TVRZMUxEY3VOamM0TlRZNU5EY2dNekF1TXpZMk1EQTROaXczTGpRMk5qSTVPRE14SUVNek1DNHdORFE0TURBNExEY3VNalV6TXpFeU5EUWdNamt1TnpnME5URXhOaXcyTGprNE1EWTBOelkwSURJNUxqVTROVEUwTVRJc05pNDJORGd6TURNNU1pQkRNamt1TXpnMU56Y3dPU3cyTGpNeE5UazJNRElnTWprdU1qZzJNRGcxTnl3MUxqZzVPRGt5TWpReklESTVMakk0TmpBNE5UY3NOUzR6T1RjMU5EYzVOeUJETWprdU1qZzJNRGcxTnl3MUxqQXhOVFV6TVRNM0lESTVMak0zTnpRMk16Z3NOQzQyTkRjNE1Ea3hNaUF5T1M0MU5qQXlNVGs1TERRdU1qa3pOalkyTlNCRE1qa3VOelF5T1RjMk1Td3pMamt6T1RFMk5qVXpJRE13TGpBd01EUTVOaklzTXk0Mk1qWXhNakF4T0NBek1DNHpNekkzT0RBeUxETXVNelV6TURrNE1ETWdRek13TGpZMk5UQTJORElzTXk0d09EQTNPVEExT1NBek1TNHdOall5TWpjNUxESXVPRFkxTmpZd05UWWdNekV1TlRNM016QTVOaXd5TGpjd056TTFNRFlnUXpNeUxqQXdPREEwTlRNc01pNDFORGt3TkRBMk15QXpNaTQxTXpFek9USTJMREl1TkRjd01EWTBNeklnTXpNdU1UQTNNelV4TlN3eUxqUTNNREEyTkRNeUlGb2dUVEV6TGpjM016SXdOVGNzTWk0ME56QXdNamcxT1NCRE1UUXVOREUxTmpJeE5Dd3lMalEzTURBeU9EVTVJREUxTGpBd09ERTVORFVzTWk0MU9UQXhNREV4TmlBeE5TNDFOVEE1TWpVc01pNDRNamsxTXpFMU9TQkRNVFl1TURrek16QTVOQ3d6TGpBMk9UWTNOamN6SURFMkxqVTBNakl6T0Rrc015NHpPVFkyTmpBd055QXhOaTQ0T1RZMk56VXhMRE11T0RFd09ETTRPVGNnVERFMkxqZzVOalkzTlRFc01pNDBPRGN4T0RFNE1TQk1NVGt1TVRNNU5Ua3lMREl1TkRnM01UZ3hPREVnVERFNUxqRXpPVFU1TWl3eE1pNDFNakU0TVRneElFd3hOaTQ0T1RZMk56VXhMREV5TGpVeU1UZ3hPREVnVERFMkxqZzVOalkzTlRFc01URXVNRGsxT1RVMk15QkRNVFl1TlRReU1qTTRPU3d4TVM0MU5EUXdPRFF6SURFMkxqQTRPREV4TnpRc01URXVPRGsyTnprM05TQXhOUzQxTXpRek1UQTRMREV5TGpFMU16Y3pPRFVnUXpFMExqazRNRFV3TkRJc01USXVOREV3TmpjNU5TQXhOQzR6T0RJek9UTXNNVEl1TlRNNE9UY3hOQ0F4TXk0M016azVOemN6TERFeUxqVXpPRGszTVRRZ1F6RXpMakUxTWprME1qTXNNVEl1TlRNNE9UY3hOQ0F4TWk0MU56UXlNVFF6TERFeUxqUXlOalF3TXpNZ01USXVNREF6Tnprek5Td3hNaTR5TURBMU5USTFJRU14TVM0ME16TXpOekkyTERFeExqazNORE0wTkRRZ01UQXVPVEl4TVRBeE5Td3hNUzQyTkRZeU9Ea2dNVEF1TkRZMk9UZ3dNU3d4TVM0eU1UWXpPRFl6SUVNeE1DNHdNVEk0TlRnMkxERXdMamM0TmpRNE16WWdPUzQyTkRjd01EQXhNU3d4TUM0eU5qQXdPVFFnT1M0ek56QTBOREk1TWl3NUxqWXpOelUzTkRreElFTTVMakE1TXpVek9UWXNPUzR3TVRRMk9UZzBOQ0E0TGprMU5UQTROemswTERndU16QTJOREV6TWpJZ09DNDVOVFV3T0RjNU5DdzNMalV4TXpBM05qVTRJRU00TGprMU5UQTROemswTERZdU56QTRNekEwTkRjZ09TNHdPVEEwTWpRME5DdzFMams1TlRBeE5qSXlJRGt1TXpZeU1UTTFPRElzTlM0ek56RTNPREkwSUVNNUxqWXpNelV3TVRBM0xEUXVOelE0T1RBMU9UTWdPUzQ1T1RNME56VXpPU3cwTGpJeU1qZzNNemN4SURFd0xqUTBNakExT0Rnc015NDNPVEk1TnpFd015QkRNVEF1T0Rrd05qUXlNU3d6TGpNMk1qY3hNRGs0SURFeExqUXdOVFk0TWpNc015NHdNelV3TVRJNU1pQXhNUzQ1T0RjeE56a3pMREl1T0RBNU5URTVORGtnUXpFeUxqVTJPRFkzTmpNc01pNDFPRE16TVRFek5DQXhNeTR4TmpRd01UZzBMREl1TkRjd01ESTROVGtnTVRNdU56Y3pNakExTnl3eUxqUTNNREF5T0RVNUlGb2dUVFF1TVRVek5UUTVOemdzTUNCRE5DNDNPRFE0T0Rrek5Td3dJRFV1TXpZMk16ZzJNeklzTUM0eE1UY3lNVE0zTURFZ05TNDRPVGd3TkRBMk9Td3dMak0xTVRrNU9EUTJNU0JETmk0ME1qazJPVFV3Tml3d0xqVTROalF5TlRnMk1pQTJMamc0T1RBd09EUTBMREF1T1RBek5EQXpNVFUySURjdU1qYzNNREU1TWpJc01TNHpNRFF3TURJME1pQkROeTQyTmpRMk9ETTROaXd4TGpjd05ESTBORE15SURjdU9UWTRPVE14TXpnc01pNHhOelU1TlRnZ09DNHhPVEE0TURBeE55d3lMamN4T1RFME16UTBJRU00TGpReE1qTXlNamd5TERNdU1qWXhPVGN4TlRJZ09DNDFNak13T0RReE5Td3pMamcwTWpNeU1qSTRJRGd1TlRJek1EZzBNVFVzTkM0ME5qQXhPVFUzTWlCRE9DNDFNak13T0RReE5TdzFMakEzTnpNMU5EUTBJRGd1TkRFeU16SXlPRElzTlM0Mk5qQTFOalF3T0NBNExqRTVNRGd3TURFM0xEWXVNakE1TkRZM01qWWdRemN1T1RZNE9UTXhNemdzTmk0M05UZ3pOekEwTkNBM0xqWTJORFk0TXpnMkxEY3VNak15T1RReU9Ua2dOeTR5Tnpjd01Ua3lNaXczTGpZek16VTBNakkxSUVNMkxqZzRPVEF3T0RRMExEZ3VNRE16TnpnME1UWWdOaTQwTWpZNU1qWXdNeXc0TGpNMU1URXhPRGd4SURVdU9EZzVOek16TlRrc09DNDFPRFV4T0RnNE5TQkROUzR6TlRJeE9UVXdNaXc0TGpneE9UWXhOakkxSURRdU56WTRNamMxTVRVc09DNDVNelk0TWprNU5TQTBMakV6Tmprek5UVTRMRGd1T1RNMk9ESTVPVFVnVERJdU1qVTVOVE14TURnc09DNDVNelk0TWprNU5TQk1NaTR5TlRrMU16RXdPQ3d4TWk0MU1qRTROVE01SUV3d0xERXlMalV5TVRnMU16a2dUREFzTUNCTU5DNHhOVE0xTkRrM09Dd3dJRm9nVFRFMExqRXdOVFE0T1Rjc05DNDFPREF5TXpJMU5pQkRNVE11TmprMU5qY3lPQ3cwTGpVNE1ESXpNalUySURFekxqTXhNRGMzTnpFc05DNDJOVFUyTXpVeU55QXhNaTQ1TlRBNE1ESTRMRFF1T0RBMU56STFPVGtnUXpFeUxqVTVNRGd5T0RVc05DNDVOVFU0TVRZM0lERXlMakkzTnpreU56Z3NOUzR4TmpBeU1qVTVOaUF4TWk0d01USXhNREEyTERVdU5ERTNOVEkwTXpNZ1F6RXhMamMwTmpJM016UXNOUzQyTnpVMU16YzBNU0F4TVM0MU16ZzFPVFU1TERVdU9UZ3hOemt6T1RRZ01URXVNemc1TURZNE1TdzJMak16TmpJNU16a3hJRU14TVM0eU16azFOREF6TERZdU5qa3dOemt6T0RrZ01URXVNVFkwTnpjMk5DdzNMakEzTVRjek9EUXhJREV4TGpFMk5EYzNOalFzTnk0ME9EQXhPVGsxTnlCRE1URXVNVFkwTnpjMk5DdzNMamc0T0RNd016TTNJREV4TGpJek9UVTBNRE1zT0M0eU56STBOalF4TXlBeE1TNHpPRGt3TmpneExEZ3VOak14T1RZM01USWdRekV4TGpVek9EVTVOVGtzT0M0NU9URTBOekF4TWlBeE1TNDNORFl5TnpNMExEa3VNekF5TnpJNU5qY2dNVEl1TURFeU1UQXdOaXc1TGpVMk5qUTJNRFVnUXpFeUxqSTNOemt5Tnpnc09TNDRNamswTnpZMk1TQXhNaTQxT1RBNE1qZzFMREV3TGpBek5qQXpJREV5TGprMU1EZ3dNamdzTVRBdU1UZzJPRE0xTkNCRE1UTXVNekV3TnpjM01Td3hNQzR6TXpZNU1qWXlJREV6TGpZNU5UWTNNamdzTVRBdU5ERXhPVGN4TlNBeE5DNHhNRFUwT0RrM0xERXdMalF4TVRrM01UVWdRekUwTGpVeU5qTTRNamNzTVRBdU5ERXhPVGN4TlNBeE5DNDVNVE0zTURFeUxERXdMak16TmpreU5qSWdNVFV1TWpZNE5EZ3pOaXd4TUM0eE9EWTRNelUwSUVNeE5TNDJNakk1TVRrNUxERXdMakF6TmpBeklERTFMamt5TnpFMk56UXNPUzQ0TWpZMk1UYzNOQ0F4Tmk0eE9ESXlOalEyTERrdU5UVTNPRGd6T0RrZ1F6RTJMalF6TnpBeE5UWXNPUzR5T0RrMU1EY3pPU0F4Tmk0Mk16a3hOVFVzT0M0NU56YzRPVEEwT0NBeE5pNDNPRGcyT0RJNExEZ3VOakl6TnpRM09EY2dRekUyTGprek9ESXhNRFlzT0M0eU5qazJNRFV5TmlBeE55NHdNVEk1TnpRMUxEY3VPRGc0TXpBek16Y2dNVGN1TURFeU9UYzBOU3czTGpRNE1ERTVPVFUzSUVNeE55NHdNVEk1TnpRMUxEY3VNRGd5T0RFMk5UUWdNVFl1T1RNNE1qRXdOaXcyTGpjd05qZzNOVEF6SURFMkxqYzRPRFk0TWpnc05pNHpOVEl6TnpVd05pQkRNVFl1TmpNNU1UVTFMRFV1T1RrM09EYzFNRGtnTVRZdU5ETTNNREUxTml3MUxqWTRPVEV4TnpBMUlERTJMakU0TWpJMk5EWXNOUzQwTWpZeE1EQTVOQ0JETVRVdU9USTNNVFkzTkN3MUxqRTJNamN5TnpRM0lERTFMall5TWpreE9Ua3NOQzQ1TlRVNE1UWTNJREUxTGpJMk9EUTRNellzTkM0NE1EVTNNalU1T1NCRE1UUXVPVEV6TnpBeE1pdzBMalkxTlRZek5USTNJREUwTGpVeU5qTTRNamNzTkM0MU9EQXlNekkxTmlBeE5DNHhNRFUwT0RrM0xEUXVOVGd3TWpNeU5UWWdXaUJOTXk0NU9EYzBNRGMzT1N3eUxqRTJNVE13TmpJNElFd3lMakkxT1RVek1UQTRMREl1TVRZeE16QTJNamdnVERJdU1qVTVOVE14TURnc05pNDNOelUxTWpNMk55Qk1NeTQ1T0RjME1EYzNPU3cyTGpjM05UVXlNelkzSUVNMExqTXhPVFk1TVRjM0xEWXVOemMxTlRJek5qY2dOQzQyTWpReU9EVTBNaXcyTGpjeE5UUTROek00SURRdU9UQXhNVGc0TnpRc05pNDFPVFUwTVRRNE1TQkROUzR4TnpjM05EVTVNeXcyTGpRM05UTTBNakkwSURVdU5ERTJNakk0T1RJc05pNHpNRGsxTWpjM05DQTFMall4TlRVNU9UTXNOaTR3T1Rnek1qZzJOaUJETlM0NE1UUTVOamsyT1N3MUxqZzROamMzTWpJeUlEVXVPVGN3TURNMU5UVXNOUzQyTkRBMU5URTVPQ0EyTGpBNE1EYzVOamc0TERVdU16WXdNemd5TmpVZ1F6WXVNVGt4TWpFeU1EZ3NOUzR3T0RBMU56QTJOeUEyTGpJME5qa3pPRGczTERRdU56Z3dNRE14T0RrZ05pNHlORFk1TXpnNE55dzBMalEyTURFNU5UY3lJRU0yTGpJME5qa3pPRGczTERRdU1UTTVOalEwT0RRZ05pNHhPVEV5TVRJd09Dd3pMamd6T1RRMk16UXhJRFl1TURnd056azJPRGdzTXk0MU5Ua3lPVFF3T0NCRE5TNDVOekF3TXpVMU5Td3pMakkzT1RFeU5EYzFJRFV1T0RFME9UWTVOamtzTXk0d016WXhNakEzTXlBMUxqWXhOVFU1T1RNc01pNDRNekF5T0RJd05DQkROUzQwTVRZeU1qZzVNaXd5TGpZeU5EUTBNek0wSURVdU1UYzNOelExT1RNc01pNDBOakUwT0RjM01TQTBMamt3TVRFNE9EYzBMREl1TXpReE5ERTFNVFFnUXpRdU5qSTBNamcxTkRJc01pNHlNakV6TkRJMU55QTBMak14T1RZNU1UYzNMREl1TVRZeE16QTJNamdnTXk0NU9EYzBNRGMzT1N3eUxqRTJNVE13TmpJNElGb2lQand2Y0dGMGFENDhMMk5zYVhCUVlYUm9Qand2WkdWbWN6NDhaeUIwY21GdWMyWnZjbTA5SW5SeVlXNXpiR0YwWlNndE1qTXpMakFnTFRFMk1DNHdLU0krUEdjZ1kyeHBjQzF3WVhSb1BTSjFjbXdvSTJrd0tTSStQR2NnZEhKaGJuTm1iM0p0UFNKMGNtRnVjMnhoZEdVb01qTXpMakFnTVRZd0xqQXBJajQ4WnlCMGNtRnVjMlp2Y20wOUluUnlZVzV6YkdGMFpTZ3RNQzR3TURBeE9EQTFOVFUxTlRVMU5USXdOelUwT0NBd0xqQXBJajQ4WnlCamJHbHdMWEJoZEdnOUluVnliQ2dqYVRFcElqNDhjRzlzZVdkdmJpQndiMmx1ZEhNOUlqQXNNQ0ExTWl3d0lEVXlMRFV5SURBc05USWdNQ3d3SWlCemRISnZhMlU5SW01dmJtVWlJR1pwYkd3OUluVnliQ2dqYVRJcElqNDhMM0J2YkhsbmIyNCtQQzluUGp3dlp6NDhaeUIwY21GdWMyWnZjbTA5SW5SeVlXNXpiR0YwWlNnM0xqVTRNek16TXpNek16TXpNek16TWlBeE5DNDRNRFUxTlRVMU5UVTFOVFUxTlNraVBqeG5JR05zYVhBdGNHRjBhRDBpZFhKc0tDTnBNeWtpUGp4bklHTnNhWEF0Y0dGMGFEMGlkWEpzS0NOcE5Da2lQanh3YjJ4NVoyOXVJSEJ2YVc1MGN6MGlNQ3d3SURNMkxqUTNPVEUyTmpjc01DQXpOaTQwTnpreE5qWTNMRFV1TmpFeU1UYzVORGtnTUN3MUxqWXhNakUzT1RRNUlEQXNNQ0lnYzNSeWIydGxQU0p1YjI1bElpQm1hV3hzUFNJalJrWkdSa1pHSWo0OEwzQnZiSGxuYjI0K1BDOW5Qand2Wno0OEwyYytQR2NnZEhKaGJuTm1iM0p0UFNKMGNtRnVjMnhoZEdVb055NDFPRE16TXpNek16TXpNek16TnpFZ01qUXVORE15TURnd01qVTFORGMzTXpNcElqNDhaeUJqYkdsd0xYQmhkR2c5SW5WeWJDZ2phVFVwSWo0OGNHOXNlV2R2YmlCd2IybHVkSE05SWpBc01DQXpOeTR4T1RRME5EUTBMREFnTXpjdU1UazBORFEwTkN3eE1pNDFNemt3TURjeElEQXNNVEl1TlRNNU1EQTNNU0F3TERBaUlITjBjbTlyWlQwaWJtOXVaU0lnWm1sc2JEMGlJMFpHUmtaR1JpSStQQzl3YjJ4NVoyOXVQand2Wno0OEwyYytQQzluUGp3dlp6NDhMMmMrUEM5emRtYysiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbInV2bSIsImRldmljZVB1YktleSJdLCJhYWd1aWQiOiI1MzQxNGQ1MzU1NGU0NzAwMDAwMDAwMDAwMDAwMDAwMCIsIm9wdGlvbnMiOnsicGxhdCI6dHJ1ZSwicmsiOmZhbHNlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6ZmFsc2UsInV2Ijp0cnVlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZX19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDMtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTAzLTEyIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYmFiMTQ4NzE4MWZhNGI3ZjYwNjRiN2Y2YmJhNmNmZjllZmRmZDcxZSJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJiYWIxNDg3MTgxZmE0YjdmNjA2NGI3ZjZiYmE2Y2ZmOWVmZGZkNzFlIl0sImRlc2NyaXB0aW9uIjoiU2VjdXJpdHkgS2V5IE5GQyBieSBZdWJpY28iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA3LCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0wMiIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMjMwMjAyMDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAyLTAyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMi0wOCJ9LHsiYWFndWlkIjoiZTQxNjIwMWItYWZlYi00MWNhLWEwM2QtMjI4MWMyODMyMmFhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJlNDE2MjAxYi1hZmViLTQxY2EtYTAzZC0yMjgxYzI4MzIyYWEiLCJkZXNjcmlwdGlvbiI6IkFUS2V5LlBybyBDVEFQMi4xIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIwMDAxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyIsInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAyLCJzZWxmQXR0ZXN0ZWRGQVIiOjJFLTA1LCJtYXhUZW1wbGF0ZXMiOjEwLCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCekRDQ0FYR2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakJpTVFzd0NRWURWUVFHRXdKVFJURVNNQkFHQTFVRUNnd0pRVlJMWlhsRFFUQXdNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUnN3R1FZRFZRUURFeEpCZFhSb1pXNTBjbVZ1WkNCRFFTQXdNREF3SUJjTk1UWXdNakkyTURneE1UQTJXaGdQTWpBMU1EQXlNalV3T0RFeE1EWmFNR0l4Q3pBSkJnTlZCQVlUQWxORk1SSXdFQVlEVlFRS0RBbEJWRXRsZVVOQk1EQXhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhHekFaQmdOVkJBTVRFa0YxZEdobGJuUnlaVzVrSUVOQklEQXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQUpjV3FlQ3hnYTlLSmJGTzJUWmRqY2dydFpBZ2ZpOFRYS3UrdjVsY1I1Y2ViNUdKWXh5b0NqaHVlRVNMM2RkbU1Ja3BHeWhzRUV0ZkZVeUJ3c3lGVkNqRmpBVU1CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdDZ1lJS29aSXpqMEVBd0lEU1FBd1JnSWhBTDRUYlAwMHNFTmJURVhHb2FnTTZIa2wyWElEcnhnS2JId293LzlHaWJZVEFpRUF1ZEltN0VHcWZ5YThReWdLY2JrUWZxcndlZlluQnZaS0kweHduL2tLV3g0PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFKWUFBQUE5Q0FJQUFBREF1QWVZQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUVuUUFBQkowQWQ1bUgzZ0FBQkd1U1VSQlZIaGU3WndKZkJQVjlzY3pTL1kwM1JjbzNYY0tCVndSQkhraVQ1OExxeHZDRTNBdG9JSUNCUVRaMmdJdFVpZ3RWR2loS1BvWEFSK3l5UExoQVJaWjFFZFZvUG9RcEtXMEJWcTZaYzlrbHZ4UE1yZlFsaVpObDdRUFAvbCtMblRtbkR1VHlmenV2ZWZjbTBrd3M5a3NjSEV2ZzZPL0x1NVpVQy84ejRCbk5MOFdZWVNJdDNZN0hHc0llSDVNL000c3RPL0NOa2pDc3dQSGFuLzVIUmYvcjBqSTZneis0NS90L2ZrYXRPL0NObWdneFhod0hMYk1OR00yMGQxVGFFYUFXeTREd3pHNEV2N2FYTmdIOWNMQ1I4WkJMOFRFSWpQSHlXTENjWUxvK2pRSHBEUFR0TzdpRlV4SWNucUQzOHZQOXQ2V2dYd3ViTk5VUXBGUVFET0RxODhTY2hudjdtS295bHVuQXU0bmxaNHVDUjJuZVVZS2lySmFQZHJwY2ppZEFXMjVjSmdXSnhWZFBZUTJvaHRmK2w3Rk5TKzg1K2xNQ1ZtRGtUT1pPQlBGMFRTSGJDNmNUcWRKcVAvdmxlOWswYWY4SGpycCsrQkpaVCttcGg0NVhEaVpUcFB3WXVJQ0FoZWJXVmJBbVZtam9XU3hhMWJlUlhTT2hQcmlzdG9UeDNHRkRDTUlqTUFKaGR2MVRkdHBqUmE1WFRpVHpwSHc4clNGQk9tQllSaXJOM0lVSXlBd0FVMlhMczVFYmhmT3BCTWtOSlRkcUQ1OGhKQktZRUxwTi80NTVjTjl6UlJOS09UbEc3NWc5SzU1bnRQcEJBa3ZUVjlNa0FvQkptQllUVlRXb3JEVU9iU3hEb1pUampKZVMzWjkxT0IwT2lRaHpNTU4xNnVxOXgzQ1pWSk9iL0FaTVVLb2RQTVlmTDhpS3A2amFGSXVMMSsvamFOTXFMWUw1OUFoQ1RHQjRNck1GSUlRd3piTnFHSnlWL0QyeURVTEdHTTlkRVRJYUVyVE4vSkdGMDZpUXhKU2xiZXFkdTYzZEVHRDBYdklNR2xJSUcvM2VlWnZzc2dZbU9BTFpmS3lOZmtjemZCMkY4NmdReEplU1VyRGNFSUFpU2l0anRtWWlxeFdJbGZPWlF4cWdaQmc2MnJMMW15MjJsenJuMDZoL1JKUzFiVlZuKzhsNUZMT1NIa01IQ1NQaTBRT0s3N2pucEtGUnBwTkRDNVRsR1ZzWnMyY2RkeDEwZm0wWDhLU2hSbG1NMnZwZ2liMTdTalltTEMwSk1hZ3dVakNWSG1yWXQxbnlPcWlzMm1uaEhTOTZtYitMa0l1TXpPTWNzQURzcWhRcXFvYVF1UHRZcnBWNi9YNEk5S2dZQUhMRVZKWithcGMxekRxSk5vcFljbVNkV1lURFRrblJwTEc0cktUbnYxL0NCN3lROGpRMitWTTBPQXpJWTh5S3EyQXdIRWhhYWlvdUw3cFMzU3dpMDZsUFJJeVd2M04zTzNXaHpNc3oweVpJYzZSSkNZU05pOEVBU2tNVklCYXBGUitiY1VuNkhnWG5VcnpaMmVnYnoxU2VrTGs3OHU3VytUU2UwdXZaWDFDa201b0g0SGhNZ25JQlZzZ0ttZWdtcVdnTkZQWE95Y3pNUEVWdE44U2h1TFNNeEZEN241MkpqZHZTMEhCQ1lsWXJLZW9wWXNXUmtVMVNaMmFrWnlTK3VlZnhVSlNDTmRTcjZwLzhJRUg1aWJOcnFtcGZTdHh1cWU3dTlGa0hEanc0WGVtVGQyOVorK09yM2JJNVFvN21iS0pOdlZMU0pnMWEyWnhjZkdzT2ZPOFBiMDRNMGVRUk83R0hGVERObnE5NGQwWk0rRk80QmhlVzErL01TZmIxOWZlWFcwM0pQcnJNR2FXNWVyVVBWNTZ3ZHJKR29DK0ppS3J2dHd2RUFsQlFGd3M5aDMzcE9XSndrWjNoelBSaGordW9KMDJjdUhDaGYzZkhwREw1VnFkYnVaNzd5QnJTeVRObmI4cGI3TmNKb2NyVXFuVThmRnh1M1pzQnp0RkdmZnMzUnZnNzYvVDZpUmlDVmordkh4bDcvNERuaDRlWnRzYUdnMUd5Z1J0VVJBZUhuNmhxRWlqMXBBa1dhOVNqUms5K3VsL1BNblhzY1hXclovdTNQbTFtOUxOYUtEdUc5RGZTZm9CYlpZUWxJdmR0aHJ0Tk9WRy9nNVM1RzVtV0RMUUl5NS9GYkoyQmlLeFdDcVhRV0VGSE1SV1pMMkx1ZlBtNStibisvajZnbjV3by9zUFNQait1Mk84QzdxQ1ZHbzVBMmMydzluQUloVEM2RzZ4MkpFUXczR1J4S0kza0phYU11WHRSSDhQZDV3a2w2ZWx0U29odENSUEgyK1JVS2pSYUZOU2xpQ3JFMmhiTEtRcDA5WGw2MHRYYkxpYW5GWCt5ZDNwU2NPOVlGbTBZUVdzcGF0eXI2Wm1sOEt4R1Z0czNyQ09NVy8rd28xNStkNWUzdGIrcDRxTGlyNnRYNHZvOUxxYXlsdFZsbEp0cDZqclZYejljYytQVmNqa0xNZUt4YUxmZnYrOXNMQ1F0N2ZJOXE5MmxKVlhDSVZDaXFMNkQrajM4RU1QSVljVGFKdUVGUm41bHhZc3Z2TGhxb3VMNXBFeVMxdDJCQWlQZEZYTkh3cy91ckpnMWFWWmMyN3RPWUljbmNlQ2hSL2xiTXIxOGJIcXAxWkhob2VmS0RpS2ZEYVk5ZjdNMnBxYlpTV1h5bTJYcWh1bFgyemJpZzZBVjVrM1IxV25ncGRRU0dYSktTdVJ0U1hXWmE5WEtPVHd4dXZxVlI4bXpVRlc1OUFHQ1NFS2xtZmtTV1FCaEVUcUh2NWd3S3Rqa2NNQndsTGVsN2dGRVFvM2tjanZxdldqNEU3c2kvTVhmSlNWczlIWDF3ZHVybHF0am91T1BuMnlBUGxzSTVGSVBEMDlsZTd1ZG9xSGg0ZENvVUFIQ0FUVHAwL0RNWXpqT0pGRWV1ck1xZUxpRXVSb3lzRkRoeS8rY1Zrb0V0RTBIUjBSOGRSVHJReTVIYVFORXBabmZXYXFyaElJQ2Nhb0RrdHRVOHN5RTJKeDBNd3ByRmFOU1VUYWMrZHFEcDNvck5XMkpVdVRjelp1OHJQR1A3VmFBOGxxd2ZGL0kxK0xZQjFxUFcrKzhacEdxOE54VENnVXA2Vi9qS3hOV2JzMlN5YVh3ZlZBUEo3MXdReGtkUm9PUzhpWnl6N09KYVFLczRtUkJvY0Z2UHdNc2p1RVJhK2cyYThUQ3FXQTR3aVJ2TE1lamxxeU5HVnQ5bm9mSDB2LzAyZzA4Ykd4SiszR1B3dG02OVcwbDZTa09TYWpFV1ppa0J2dFAzQ2d0cllHT1JvNGZlYUhzNy8rQXZNZmhtRUMvUU5lR2Y4eWNqZ05SeVVzei92U1dGR09DVW5hb0E1YjBwNldKVlFxQTZlK3dtbzFtRVNzK3Ftdzl2Z1o1R2d2eTlQU0llVDRlRnZpSDZUNzBWRlJSNDRjUkQ3YmdINGRrZEREWFRsMnpDaVk4K0U0VGpQc3Vxd055TkhBMnJXWm9COC9KQ1Ftdm9Xc3pzUWhDU0cvTEZ1NTBkSUZhVVlhR05Sanl2UEkwVWFDa3Q3R1lTb05IVkVvNHlOaU84QUp5elV2WDVtK0tuMjFsN2NYVEVtaC8vV09pejEyNUpDZCtjWnRZQlRsQjlLcXFxcGZ6NTB2K3UxM08rWDgrYUtTcTgwRDNzTDU4M1JhTFhSRVNGaTIvZCtYRVBDUVF5QW9LdnI5dSs5UFNxVlNsbVhkUFpTdlRabU1ITTdFSVFtcnRuNnRMeW1CNFo4MWFFSStuSWFzYlVmczQ5Vnp5Z3NzeEJLcHVQNzcwL1duTFhsNW15SVRaQk5LTjdmczlUbnBxek84ZlgxQVB4TkZ4Y2ZGSFQ2NEh5YmRxSkpqNU9adEdURGdnVUZEaHcwYVlyUGNQM0RRalBkbm93TWFDSThJZjJ6b0VDTkY0UVNoVXFuek5tOUJEb0VnTXlzTGpQeW8vdXFFQ2ZJdStZS1lRODIyZEhtT1VDSTNNNHc0b0dmUHQrMnRrTFZLMFB4RUhDYkxISWVUMHBKRmE1SFZZV1JTYWNyeXRPUVZLNzJ0NDZmQWJHWW9VKzdHSEppQm9ScXQwakNNS3VRS0gzOS9mejgvK0dlckJQajdRVmFLRG1qRWdnL25xVlVxekN5UUsyU2I4cENFcGRldUhUaHdTQzZUUWNvcWtZaW5kY2tvQ3JRdVllWDIvZnJMbHdVaUVhdlhCczE1Z3gvSDJnZTBCa2xQZi8rSlkxaXRIcGRKNm82ZVVKMHRjand5V1RURDhDUEhqcmtwRk5BZGVRdEdFbk9TNXZNVkhLS2gxeHVOaHJxNk9sVjlmWDFkbloyaTE3WHdRUFBERHoyWTBMY1BSWnVFcExDOHZHTDNOOStBRWNZR21tVWdSbXAxdXJHalIvbjUrZkdWblUzcnk5dy85bjNLK09jMURPS01URHF3N0NScFhaMXFrV05ZQ0tuMGdIZ3A3dVUvOEpMTnpOQlFXdkZqOUhCY0pPU01sT2NUZy9zZHpFY08yOHZjczVQbWZmSGw5c1pUTkpQSlJKdG95TjFCeHBycTZwUmxTNlpQVFVTK2xyaDU0MlpVWE4rQUh2NTZyVzdVcUpFYnNqTlBuanAxN1BoM01EdEVOVnFDcHBuSWlQQ1hYbndCN1RkaXo3NzlyMDUrM2MvUDEyZzB4c1hFN052enI5ajRCTXRYekRGTXI5T2RQSEVzSWp3Q1ZYVXlyY1NQNi9tNzZvdE9rUUl2UnFDT21aOXNSei9BTEdBdDM5Tm5vRFJaWUd1R05DVFE3OFduYjM3K0wwSXF1M1hvc09iOFJiZUVXT1J6REsxVzJ5YytmdGpRSVptWjJVb3ZEMDh2cjJVcHkwY01IeDRkSFlWcTJPWjI2SDEwOEdBb2FLZnRqSHJ1MmVCZWdScWRYaXdXWHk0dUhqOXhFczB3a01qQXRUMDU0Z2s3K2pFTXUvMnJyd0lDQW1CSTBXZzFKcG9PQ3czcGw5QlBKSEk0RmpURjNxZ0k3eGI2WlV4S1dsVDZndGpsSzNyT2ZCMDViQ0QwOGhYNit3Z0RmRWxmTDJTeVFjamlHZUxBUUtHL3I4U3ZWMW5HblhUQUVlQWVCUWYxMnYvTjF4Q1ErdDNYejZEWHd3QWhFZ3Fudk41RnNlYzI3NzR6WGFXMnJMY1JPRmI0ODgrZ0h3eHBETTNNblBFdXF0RVNKR241SFlPUlk1NS9kdlNZYytmT1V4UTFhc3dMVWJHOVlVaEFOZG9LbkE0NE8zRHNkK0xZQXJlKzhEOTFzNG8zUWxqbU54eWhXVlhIajRSWHVWMVpmK1hxVVVGUWdUTGhPQm4xMjhUM2tkVnNualZuYmtDdmtNalkrS0N3eUVHUFBnWnZtN2VYbHBVRkJvZUZSY1pFeE1aNysvVlk4TkZpM240M042N2ZVTGo3d0JsNjlBcWRPdjA5Wk8wWTBJRkN3NlBDb21JalkzdEh4TVREeVFORHdrZU5HWWZjZG9tSzY2UDA4cjEwNlJKc256eDFXcXJ3Q0krTU5SZ3Npd1p0eFY0dnRLUVBEdE9zYXB1U0ZBY3J3K1ZDL0Z1WG1TRVNvZC9IQ2U3Vkt6VjVhWDI5Q253ZW5wN1oyUnQrK3M5WjN0VUZDRW55dFNtVE5Db05iRnV6WXpObzhNRk14OWM5TU1wbytUQXlOamJHVGVFR2cycDVSVG52cUt5cWd2OXJxbXNxeXBFRktEejc4N0xrMUcyZmZ3RjVBREpaYVVuQzIrR2k2Mm4xcFRFemhqVzU1a212L25QRThML3BORnBvQ1I1ZW5oUCtPUWs1Yk5HeE5kSm12UGZ1T3hLWkdNWVIySVk3Mjdkdm42RkRoL0F1KzZCcnNMWmV2VjVuTkJrSmdvUVpUbGIyK2xEbzFQSDlQdjFzRy94TkdQQVFUREdoRG5UdUYxK1o4TkxMTDM3NjJSZGVQZ0dOVzJvTEVscCt0cWU3YU8ybDRaM0R5SXQyR3NqZnNsa21rOUUwRGJORGxVclRTbERzMkJwcE05emQzVU5EUWxuV0Vnb2dTTTk4ZHpweXRBWmNBOGpIVDJjWExsaXNycTJiTkhHQ201c2J4TmVRNEY2RVVMaDk1Njdubm50dTBLQ0h3VGhuM29kN3Y5bTdPajB0SmlwcVM5NG5RckY0NU9nN0h4TTFsOUFNTjlGdTJ1bFVNTXNJMmVZN0xKTkpjelprcTFRcXVJL3U3c29kdTNidFAyQnpzZFJ5NzlCbUozRDA2UEZ6NXkrQUV0Q0FJc01qUm84YWlSd09JSmZMWjgrYkh4MGJmL0hTNWQyN3YxNjVFajBPYjJtT0ZKVzFadlZuK1huNzl1eG1hUHJiQXdlVTNsNDlBM3VDTnpnNDJNZmJTNlhXbkRtREZwbWJUaXBna0NMSUg4TWZFOXpWMHJzQ0dPTGc5ZDJVL0ROVWJlTHZJNFpQR1AvU2psMjdRVUxJMXllLzlzYTFrc3N5YVF2clc1WitiTjFZdHk0N2RXVTYxTGZ1dFl5Uk1qNCtiTmpXTFhsby95NVdwS2Q3S0pWbWdhVUxMbDIwRUZrZFE2ZlZaYS9KQ0FrTlFmc05RRU9FOXc5aGxkL1Y2UTBVUllNRkpxQzhCYVl4a0FSVERSR3hTUyswSkJZNHhwbG9qbUc3b2RDczVRRitqR2hmTjhsZWx4a1k0QS9KS2c1ekRMRjQ3TGhXUHVWaE9ZNkdHUURMMmluZ3BwcytSTktZd3NLZmYvenByRWdxZ1hvOS9RTmVuVGdST1ZyaTBPSERHemJjK1pJWE5GTm9TVHA5QzcvU3hMZmcyMGtlTkxJZThMNU1wcXRYci9JV1BhakxzdjBUK3ZPN1NFS1lqMXVVbzB5VzM3SmoyTzRyY0JrbXVBeU9zVndHZjIwQXd6Q1FMSmdnaXdldjdSK0h5OStTQjAwYldpdmtpc2NMQ3JMWDMzbFVFSnEyQ1E2Mm5NTUVaN05ZT0RQckFIeXEwaUlyMGxZcGxXNXdwN1Y2M2VUSmsrd3NQVUlmaFNZMWZYcGlRY0VKWk5Hb29ZbFVWbGJ5dTQzUjZYUW1GaHJYbmErRExWdThpTUR3ek14czJENTkrb2VTUHkvUFRacnQ0ZW5PZTlFQzI0V3hpYnFpeXpDUjU2Mk9BMi9BNWgxdHpXc0h6a0Q1akJ3ZXRRWU5UYW5MVjM2emQ1OVVLb0hoWmZPbWpRa0pmWGo3M2F4YXZXYm5ycThsVWdtOHI1cWEydStQSGZYMnNhd3pWRlpWUHY3RVA3eTl2WXdHdzk5SGpFaEpYckpseTlic25FOFVibmNXN2U0Ryt2U2dSeDVaODNFNjJtOUVjWEhKZlE4TzlQSDFBWTJodzV3dlBDdFh5Skd2SmQ2YjhVSFJiNy90Mjd0YnI5TysrZWEwRzdjcWhZUVFKN0RSSTBkKzhQNmRlY2pTWmNrSERoM0dDY0xUM1gzYTFNUm5uM21hdC8veXk2L0xWNnlrR0FZWFlPTmZmckh4bXA5RlFoQ3hvZGYrMVlEN0MrTXEydWxVM25ocjZyY0hEeW9VQ3JWYS9jWnJrMU9UbHlGSGwyT1YwTnBkMm9mOVl6dHk1djlsYnQycWpvMVBnR2tvRE5BbWlpcjg2VXlYZlM1eE41WVcycEc3YlAvWXY2Uit3S3FNTmFTUXhERU04aEVZNjdwUlB3REZRaGVPWXpBYXd5T2laZFpQdmlEMU9IM2llSGg0T08vcUZwd1NKLzdhd0lRU2tra0lzYURsc0tGRHVsYy93TlVMMjB5djBBaVJTQVFTcXVwVlJ3N3Q2OTkvQUhKMEU2NWUyRGJTVjYydUtDMnJxNjIvWG5HalQ1LzRidGNQY1BYQ3RuSHUzSG1hb2FFTE1nd2JGaHJpdksrY09ZNUx3bnNlMTBCNmp5TVEvRC9leExnOFIvNHNRQUFBQUFCSlJVNUVya0pnZ2c9PSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkQmxvYiIsImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiZTQxNjIwMWJhZmViNDFjYWEwM2QyMjgxYzI4MzIyYWEiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsIm5vTWNHYVBlcm1pc3Npb25zV2l0aENsaWVudFBpbiI6ZmFsc2UsImxhcmdlQmxvYnMiOnRydWUsImJpb0Vucm9sbCI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsInV2QmlvRW5yb2xsIjp0cnVlLCJhdXRobnJDZmciOnRydWUsInV2QWNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjpmYWxzZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjIwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjY0LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sIm1heFNlcmlhbGl6ZWRMYXJnZUJsb2JBcnJheSI6MTAyNCwiZm9yY2VQSU5DaGFuZ2UiOmZhbHNlLCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MjAwMDEsIm1heENyZWRCbG9iTGVuZ3RoIjoyNTYsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxMCwidXZNb2RhbGl0eSI6Mn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTAzLTE1IiwidXJsIjoiaHR0cHM6Ly93d3cuYXV0aGVudHJlbmQuY29tLyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjIwMzE1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTAzLTE1In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMi0wOC0wMiJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImYzNjdjNzNjNThhNjdhOTU0MjA3Nzg5MDBkZmY0NzU5YTEzNTRmZWMiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiZjM2N2M3M2M1OGE2N2E5NTQyMDc3ODkwMGRmZjQ3NTlhMTM1NGZlYyJdLCJkZXNjcmlwdGlvbiI6ImF1dGhlbnRvbjEgLSBDVEFQIDIuMSIsImFsdGVybmF0aXZlRGVzY3JpcHRpb25zIjp7ImZyLUZSIjoiYXV0aGVudG9uMSAtIENUQVAgMi4xIiwiZGUtREUiOiJhdXRoZW50b24xIC0gQ1RBUCAyLjEifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn0seyJtYWpvciI6MSwibWlub3IiOjB9LHsibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlEWHpDQ0FrZWdBd0lCQWdJTEJBQUFBQUFCSVZoVENLSXdEUVlKS29aSWh2Y05BUUVMQlFBd1RERWdNQjRHQTFVRUN4TVhSMnh2WW1Gc1UybG5iaUJTYjI5MElFTkJJQzBnVWpNeEV6QVJCZ05WQkFvVENrZHNiMkpoYkZOcFoyNHhFekFSQmdOVkJBTVRDa2RzYjJKaGJGTnBaMjR3SGhjTk1Ea3dNekU0TVRBd01EQXdXaGNOTWprd016RTRNVEF3TURBd1dqQk1NU0F3SGdZRFZRUUxFeGRIYkc5aVlXeFRhV2R1SUZKdmIzUWdRMEVnTFNCU016RVRNQkVHQTFVRUNoTUtSMnh2WW1Gc1UybG5iakVUTUJFR0ExVUVBeE1LUjJ4dlltRnNVMmxuYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTXdsZHBCNUJuZ2lGdlhBZzdhRXlpaWUvUVYyRWNXdGlITDhSZ0pEeDdLS25RUmZKTXN1UytGZ2drYmhVcXNNZ1Vkd2JOMWswZXYxTEtNUGdqME1LNjZYMTdZVWhoQjV1enNUZ0hlTUNPRkowbXBpTHg5ZStwWm8zNGtubFRpZkJ0Yyt5Y3NtV1ExejNyREk2U1lPZ3hYRzcxdUwwZ1JneWttbUtQWnBPL2JMeUNpUjVaMktZVmMzckhRVTNIVGdPdTV5THk2Yys5Qzd2L1U5QU9FR00raUNLNjVUcGpvV2M0emRRUTRnT3NDMHA2SHBzaytRTGpKZzZWZkx1UVNTYUdqbE9DWmdkYktmZC8rUkZPK3VJRW44clVBVlNORUNNV0VaWHJpWDc2MTN0MlNhZXI5ZndSUHZtMkw3RFd6Z1ZHa1dxUVBhYnVtRGszRjJ4bW1GZ2hjQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkkvd1MzK29Ma1VrcmsxUSttT2FpOTdpM1J1OE1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQkxRTnZBVUtyK3lBenY5NVpVUlVtN2xnQUpRYXl6RTRhR0tBY3p5bXZtZExtNkFDMnVwQXJUOWZIeEQ0cS9jMmRLZzhkRWUzamdyMjVzYndNcGpqTTVSY09PNUxsWGJLcjhFcGJzVThZdDVDUnN1WlJqKzl4VGFHZFdQb080enpVaHc4bG8vczdhd2xPcXpKQ0s2ZkJkUm95VjNYcFlLQm92SGQ3TkFEZEJqKzFFYmRkVEtKZCs4MmNFSGhYWGlwYTAwOTVNSjZSTUczTnpkdlFYbWNJZmVnN2pMUWl0Q2h3cy96eXJWUTRQa1g0MjY4TlhTYjdoTGkxOFlJdkRRVkVUSTUzTzl6SnJsQUdvbWVjc014ODZPeVhTaGtET095eUdlTWxoTHhTNjd0dFZiOStFN2dVSlRiMG8ySExPMDJKUVpSN3JrcGVETWRtenRjcEhXRDlmIiwiTUlJRmhEQ0NCR3lnQXdJQkFnSU1iVUk5K3p5RVFVVEQrZG5DTUEwR0NTcUdTSWIzRFFFQkN3VUFNRnN4Q3pBSkJnTlZCQVlUQWtKRk1Sa3dGd1lEVlFRS0V4QkhiRzlpWVd4VGFXZHVJRzUyTFhOaE1URXdMd1lEVlFRREV5aEhiRzlpWVd4VGFXZHVJRWREUXlCU015QlFaWEp6YjI1aGJGTnBaMjRnTWlCRFFTQXlNREl3TUI0WERUSXpNREV5TkRFMU1ERXdNMW9YRFRJMk1ERXlOREUxTURFd00xb3dnYll4Q3pBSkJnTlZCQVlUQWtSRk1ROHdEUVlEVlFRSUV3WkNZWGxsY200eEVUQVBCZ05WQkFjVENFRnpZMmhvWldsdE1Tb3dLQVlEVlFRS0V5RkJTVmhsWTNWMGFYWmxMbU52YlNBb1FYaGxiQ0JXYjI1a1pYSm9ZV2RsYmlreEVqQVFCZ05WQkFzVENXRjFkR2hsYm5SdmJqRVRNQkVHQTFVRUF4TUtRVWxZWldOMWRHbDJaVEV1TUN3R0NTcUdTSWIzRFFFSkFSWWZRVmhGVEM1V1QwNUVSVkpJUVVkRlRrQkJTVmhGUTFWVVNWWkZMa05QVFRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS2YvNEd6R0FVbUpINFI5bUN2Y0orQ2dUVWdQMUROcjhkTjJrRHZTQTl4dUlNYjFOWkpYUWd4U09PQVlxSUJ6Rk5jamtOVmw4MFkzZHJtNHRQSlNsM2tmV1dNMjZ4WUxGc3ZsMUJjcXRyUHJzc3l4SUJ0WDVrVGUycCtNOVJsY1pRY0VqNUNiWXBBU3B1U1RCeXpvT3VmK1ZTZk9VVnFEekNESDRDcXNFQ3l2eUxLckp3OWtqTjRCNmxGWHl6bXJJV3FSbUdXS3g0Y3NvL3d4WUlVTmNPVitwNkk4NFkyejFuRklXRWhjQTZkZ3JKUW5EcEQ1SUdFSmRTeFRuOHQyWm5BTnA0SkVBcDhqNXczdGJVODlSS2kzeVBBdXdzeGkzWGNsb0ZBdEd4dzJ3azduSnlpenE5OHRPNWx3ZmdITi9ZbmdsWXdVNFVGbk9CelA1TXV6UHJFQ0F3RUFBYU9DQWVvd2dnSG1NQTRHQTFVZER3RUIvd1FFQXdJRm9EQ0Jvd1lJS3dZQkJRVUhBUUVFZ1pZd2daTXdUZ1lJS3dZQkJRVUhNQUtHUW1oMGRIQTZMeTl6WldOMWNtVXVaMnh2WW1Gc2MybG5iaTVqYjIwdlkyRmpaWEowTDJkeloyTmpjak53WlhKemIyNWhiSE5wWjI0eVkyRXlNREl3TG1OeWREQkJCZ2dyQmdFRkJRY3dBWVkxYUhSMGNEb3ZMMjlqYzNBdVoyeHZZbUZzYzJsbmJpNWpiMjB2WjNOblkyTnlNM0JsY25OdmJtRnNjMmxuYmpKallUSXdNakF3VFFZRFZSMGdCRVl3UkRCQ0Jnb3JCZ0VFQWFBeUFTZ0tNRFF3TWdZSUt3WUJCUVVIQWdFV0ptaDBkSEJ6T2k4dmQzZDNMbWRzYjJKaGJITnBaMjR1WTI5dEwzSmxjRzl6YVhSdmNua3ZNQWtHQTFVZEV3UUNNQUF3U1FZRFZSMGZCRUl3UURBK29EeWdPb1k0YUhSMGNEb3ZMMk55YkM1bmJHOWlZV3h6YVdkdUxtTnZiUzluYzJkalkzSXpjR1Z5YzI5dVlXeHphV2R1TW1OaE1qQXlNQzVqY213d0tnWURWUjBSQkNNd0lZRWZRVmhGVEM1V1QwNUVSVkpJUVVkRlRrQkJTVmhGUTFWVVNWWkZMa05QVFRBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFnWUlLd1lCQlFVSEF3UXdId1lEVlIwakJCZ3dGb0FVbGpQUjVsZ1hXelIxaW9GV1pOVytTTjZoajg4d0hRWURWUjBPQkJZRUZDNTdMTjNSVzM4ZGV4UWh4ZkhXL1dXdDdjQ1FNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUN2dlBpbTdqb0YwRzR2T2VwU0ZiQ1JndEN3UkF5ZW45Zkh6RFMyN1duc1RiRzlVb3EremlHcmNEK1U1RW5INlVybUYxQnF4WEwxQ2pxRVBybjVZUXRaU3MzcGZ2b25Ya0ZDaHRpWVlPZ0s0Z0lxSnRDVkJhWDNINERIa0kxVjdCaDdiNHZqWkFEOGNKTHhpSmY2QXZJNGUxMUQ5SzV0cFo3WVpRRTVNdzQ5VkR0UThBN3Brak82d1hqSEZYWGdZMWxQdytMUlF1VTNtOUtHQU0zQzRnZTBvdHBXMFh5S0R4cXNLV094bU1YN0lqaFhGRHBLWW9wbW1MUGNUejcwT050YkUyTkh5SWEzVXVqaGNqYmNycG9Oa21hRmlMazJwcUtSWklvSGtaYUZNZDl3YVE5ZjFsUzJ3d1ZReHRIK3ZOVjlOM0srSG5MM25CL0NVMkUwYnRKSCJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFiQUFBQUd4Q0FZQUFBQURFdU9QQUFBQUNYQklXWE1BQUJjU0FBQVhFZ0ZubjlKU0FBQUZGbWxVV0hSWVRVdzZZMjl0TG1Ga2IySmxMbmh0Y0FBQUFBQUFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NGdQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlRV1J2WW1VZ1dFMVFJRU52Y21VZ05pNHdMV013TURNZ056a3VNVFkwTlRJM0xDQXlNREl3THpFd0x6RTFMVEUzT2pRNE9qTXlJQ0FnSUNBZ0lDQWlQaUE4Y21SbU9sSkVSaUI0Yld4dWN6cHlaR1k5SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpFNU9Ua3ZNREl2TWpJdGNtUm1MWE41Ym5SaGVDMXVjeU1pUGlBOGNtUm1Pa1JsYzJOeWFYQjBhVzl1SUhKa1pqcGhZbTkxZEQwaUlpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGJHNXpPbVJqUFNKb2RIUndPaTh2Y0hWeWJDNXZjbWN2WkdNdlpXeGxiV1Z1ZEhNdk1TNHhMeUlnZUcxc2JuTTZjR2h2ZEc5emFHOXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNCb2IzUnZjMmh2Y0M4eExqQXZJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JGZG5ROUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlVWMlpXNTBJeUlnZUcxd09rTnlaV0YwYjNKVWIyOXNQU0pCWkc5aVpTQlFhRzkwYjNOb2IzQWdNakl1TVNBb1YybHVaRzkzY3lraUlIaHRjRHBEY21WaGRHVkVZWFJsUFNJeU1ESXhMVEV4TFRJd1ZERTBPalF3T2pVd0t6QXhPakF3SWlCNGJYQTZUVzlrYVdaNVJHRjBaVDBpTWpBeU15MHdOQzB4TmxReE9Eb3hPVG8xT1Nzd01qb3dNQ0lnZUcxd09rMWxkR0ZrWVhSaFJHRjBaVDBpTWpBeU15MHdOQzB4TmxReE9Eb3hPVG8xT1Nzd01qb3dNQ0lnWkdNNlptOXliV0YwUFNKcGJXRm5aUzl3Ym1jaUlIQm9iM1J2YzJodmNEcERiMnh2Y2sxdlpHVTlJak1pSUhCb2IzUnZjMmh2Y0RwSlEwTlFjbTltYVd4bFBTSnpVa2RDSUVsRlF6WXhPVFkyTFRJdU1TSWdlRzF3VFUwNlNXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEbzJOR1JpWmpVNFpDMDVPVFk0TFRnNE5EY3RZak01TlMwNU1UWTVOalV4WVRRd01HUWlJSGh0Y0UxTk9rUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZOalJrWW1ZMU9HUXRPVGsyT0MwNE9EUTNMV0l6T1RVdE9URTJPVFkxTVdFME1EQmtJaUI0YlhCTlRUcFBjbWxuYVc1aGJFUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZOalJrWW1ZMU9HUXRPVGsyT0MwNE9EUTNMV0l6T1RVdE9URTJPVFkxTVdFME1EQmtJajRnUEhodGNFMU5Pa2hwYzNSdmNuaytJRHh5WkdZNlUyVnhQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaVkzSmxZWFJsWkNJZ2MzUkZkblE2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRvMk5HUmlaalU0WkMwNU9UWTRMVGc0TkRjdFlqTTVOUzA1TVRZNU5qVXhZVFF3TUdRaUlITjBSWFowT25kb1pXNDlJakl3TWpFdE1URXRNakJVTVRRNk5EQTZOVEFyTURFNk1EQWlJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0F5TWk0eElDaFhhVzVrYjNkektTSXZQaUE4TDNKa1pqcFRaWEUrSUR3dmVHMXdUVTA2U0dsemRHOXllVDRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejZ6T1hSbEFBQnVOMGxFUVZSNG5PMjllYncxVFZYZis2MHpQK01MTDYrQ1lCQkJFRVJFb2tFaWlHTWNiaVNLaWthOUdEWEdSRFNScURGcWpPalZhNHk1UkhGRWNjRGdpRW9VSEZIamhCQkh4SWlBZ3N3enZNRDdER2Q2enFuN1I5V3FXbFZkdmZjK3o3UFBQcnQ3cisvbjA2ZDc5eDdPN3Q3ZDlhczExQ3JudmNjd0RNTXdoc2JhV1g4Qnd6QU13N2daVE1BTXd6Q01RV0lDWmhpR1lReVNqYlArQXJlQ2MrNnN2NEl4VWp3czVjWGx3SUxXeHR3WmFpN0VvQVhNTUc2RkdVVnFXWVRNeHorOTM4ZkV6VmcxVE1DTWxXQ0tXTFdlTzRsdzNhckl6U0k4OGo5YXIrMFZOeE0xWTh5WWdCbWpaSUpnMWZ2ZGpNKzFIcDgydGZqNDZqdkk4NjdudFozellJSm1qQWtUTUdNVTlBaldMR0pWclBYbnVNYSsrcmw1NHhzQzQ3SVkrWG9mL2V1bXFKbWdHV1BDQk13WUxET0lWbE9rVU1Ma3FtM1gySy9mYzFyQ1ZYOWhKVlkrbWwwK2ZqZXZCYTIxVGY5YTA3SFFUTXlNb1dFQ1pneUtLYUxWV2hjQzVVc2hjdVI5YVZHdjZ3aFo0Ly9QUzlDYUxzREsraEtSU291djlubjF2b2FvNlcxWFBUWXhNd2FIQ1ppeDlKeEF0TksyRml6WEZhZzF5dWZYZkxVdHI5VkNWb25mcVZHTEVBM0I4bkNNMmhZUjA4ODEzcVBGRHZVYUV6TmprSmlBR1V2TEJHdW5GaTF0SGExVmdpVml0YVlFYWswOWwvYVRsODc3ZlBmLzFOOXBEb2RiYnZ1MktJbHdIUVBIc2ordTAzTksxSXIza1VYeDJIV0ZiS0tZbVpBWnk0WUptTEZVbkVTMGFpdExXVTlydFdCRmdWcjNwVkN0eGRjVys1WElwYytqRkVYOWZXN1pJdk1OOGFLMG9KSUl1U3hheCtyeEVXcWZldjdJcS9jb1FVdmJQZFpaVTh6TUtqT1dEUk13WXltWUlsejF0b2hUc3FMSXdyVmVDNWFEOWZpYTlmajhPbm0vaU5kNlhFUzgxaHZXV2kxaUVBUjBUcWVnMkphbHNLb3FzVHJ5Y09UVU5rR2NaUHVvRXJna2FPUjlXaGk5RXJtV2lLWHZhVmFac1F5WWdCbG5Tbzg3cm1sdGtkMkRTVlI4S1RUcjlhSUVhd08xcmZiM0xnMXJyUkN3ZWNmQ2xDVldDMWhoVmRXTEVxc2pINVliYXY4TkxXaFUyOG82S3dTdGNqT2FWV1lzSlc2b05iQUFxNFU0WUdZUnJtZzlKZkVpVzFaaVhZbGx0VkVMVlZ6WFM3RS92a2MvMTFyNkJLempTcnoxVTVMV0hRR2pSN3pJSW5WREJFc3Q5ZU5pdnhLMkcyUVJPNkxycGhRWG93aWMvcDc2dThzSkdXNmpzcUlNVlFmTUFqTVd5Z1RoNnNTMmRHS0Z1QVo5YVYxdGlHZ3BJZHFjc3Q0QU5sMzVubHI0dEhocEVYTlVHWW5NV2NCRUxPZ0syQkdsaUdtQk92Slp4RzRBaDJTeE91eGJleVZxVGxsdTBIVS94dTAxMmxaWmNRem1YalFXaFFtWXNSQm1GUzV5OG9Ra1U5UVdVYktnZkxDaU5uMFdxTmF5UlJhdFRSK0Z6Q3NSVTJLbS80Y1dyM1dVNjNLS2VNMHFhSzNHWGZyQlJmeUxVcnlPVVVJam9sV0xsd3NDZFVnV3JBUHk0MktKNzlXaXB5MDFpYk9sMkp2dlpqaWFrQmxuZ3JrUWpWUGxwTUpGdHJaYW9xV3RxYlE0MlBKWnJEYUJyY2ErK2owYlN2aGFGbGh0ZmZXNUVPSFdyYkM2OFova1FwVDFqV3A5V0lsWXZSeEVVVHNnaTVuZVY3OWVXMnZwLzdneUVVUUVUYnNYbTY1RkU3SGxacWc2WUJhWWNTcmNoSEJKTW9hT1MwbXNTaXduYlZWTlhIejV1QmF5MnZLYVJieDBQRzZlNGlVVUlxWmNpY2ZNSUdKS3ZMVHI4QkFsVmtxOHBpM3BmUzY3R3BPWXVmeC9qOGxaa0s0aFpPbDR6Qm96VGdPendJeTUweEF2TFdCckRlR1NyRC9KRUJTM29CYWZldGxXNisxcVg3MFVya1RheVIxRmlqMTU3ZWkzdnVaOUFVNUs1SkIxSjFXZWRySkc3VHBzQ2RXK1d1OVgrOUpTV1dueTJZVlZobkl4MHJYR3pDSmJjb2FxQTJhQkdYTmptdFhsR3dPSVVZa1lZbW41NEFMY2pGYlV0b050WDRxVjdOdW11NXhFdkZwcDgzWFN4a25GNjFaaVlIci9KQkVyeG5iUkwyVFRSR3kvV2c0YzdIdTFMejZXMTlhVzJTSFo4cHRGeU5MeCtaQU1NOHhXMDFnYVRNQ01XMllXNFhKaE93MGcxcTVDTFZ4RW9ZcmJPMlNoMmlHdmQzeGJ5RnJpbGR5R3RNV3I2UzZrTFY3MThaMEd0YlhTSzJLMDNZcDkxcGgyS1JZaXBrVXJydmNvMTFyTTlsMTBSNHFJeWJvV01wK3RSZm5PeFhHYVc5RzRWVXpBakZ1aXgxMm9selIyS3dyWHhpVGhvaUZXTGdqV0RuQ3VmdDUzM1llZGVKZUtkYzJTcE5HeXVIb3RMemNuSWZQZFJyelBFcHNrWnAzNFdCVWI2OFRGS0Myc1dyejJQT3hGNGRxVDV5cXhTM0V6TFdReFRyWkdUUG9nV0Z4MWZNeXNNZU9XTUFFemJocmZ0a3FLT0ZjZDMwSmxFZFp1UWFKZ0VVVHJuSWlXRWk5NVhvdFlzcmhjemp3czNJVis4dURram5CVnlSb3Q0VXJicDlUcStzYTJwMHp1bU1VcTAzR3l3cTJvNGxvdGwySVNLMkRYS3pHalhQYVZ1RW04N01DcjlIemlBT3RvbFRuMS9ZcmpOUkV6YmdZVE1PUEV6R0oxVWNhVzZtekNMVmU2Qm1VNUY2MnRjejRJbGw1cThhcVROalo4MTExWWkxWXJNYU5qY2ZueXVJQ09sWFZhN2tPaDF4cnovWlpaWFhXKzVWcE1RdVlwMHVYNzRtSmFySFpiNnloZTIzRmJ2M2M5L284MVNtdnNpQjVyekZ5S3hra3hBVE5PeEFUeGtnSzdPczZWeGxxNXlrMFl4VXVFNlZ5MHVNNTVPRSsvZUltQTFlNUNiWEcxcW1ub0t2UFRFak1tV2x4blJLOUZWbTBuTVl1V1d0TXFveHpiMVVyMEVOZGc0VTUwd1JyVEFsWXZJbmFiUHNmTjFwVllpb1ZyMXBneEYwekFqSm5wY1JscVM2YmpLb3hXMTViUFNSZVNoS0VGNm54OExPS2xSYXdXcm0zS09OY3NpUm5hclRrcHJqVXBRZU9zUk13My9yZWZzUGFVYnNiYXhUZ3A0VVBpV09JS0xLd3gzN1hBcnF2MVRseUxLM2ZYaGQ5bkwzN1dPbG5JMW1KY1RnUk5mMGVIaVpneEl5Wmd4bFFtdVF5OVN0Q0l5UkxyeWxWWVpCUFNkUTJlYnl6bnlCYVpGaSt4M3VyTXdtbkZkNmVsd1UrenRNN2ErcEwvNzZmczZ4VXpKaWQ5Rk81Rm4xUGp4U0pyV1dOaWNaMXpjTjFuOFpMRW11dUVhMkNQOEJ2dFVmNCtoekhPS0pVOWlDSzJwcisvdVJTTmFaaUFHUk9abEtoQmRzdkpWQ1ZhWEhSaXhpVFJ1b0N5dkVTNGxIalZHWWE2L0ZOTHVQcEVhNXFWMVJTcUc4QTdnWGVCdXpOdXZ4bDRHL0FPdGJ3TnVFcloyaDhTV25rWEQwNU9paWo2WmVDOWdIc0FkOFQxUFlIM0FXNlB5OTNCM3g3ZTJ5ZXVYbTFEdjVDdE1ka3FrMlVySHJhc3QrTWg3WkN0c1hQeDBIWjkxOVdycmJEcnFPTEpkS2VwdWFHc1lqMStUR1BXbU5HTENaalJTNS9MVUZ0ZFpKZGhLdlBrbGNYbGNseXJKVm9YQ0tJbExzVGE2dEx1d2s3ZFFxZStDeWRMZis4VnE3ZUQreXZnYjRHWEFHK2lGS3FySnpxREFROWNPK0Y3TGhFRTdSN2c3aUFJM1FPQmh3TWZETHd2K0szdzBwWVFhN2RqeXlLcnhXemQ1U2xVUk1nMnlVSW1XWVhpVmt4Sk53UWhhMldIYnBNSHBFdGxGYkhHNU5vNWlPSWsxcnhPOEJDUk5aZWkwWXNKbU5GaG1zdlFxV0s3eXVxU0pBM2R1SjMzV2Foa09WOXRpOERwUkkyV3U3QWV3NlhGNjhTaWRReThIdHhyZ1QrTnkxOFNyQ3V4bnM2U0szRjVUYlYvZzNDQzdnbnU0Y0JIQVA4UXVBOXdQL0E3NFdYVHJMV09tS21Fai9XNDNxQ01reDM2UEZ5aHJ3cEt5aENWMTNxS1FlVXBWaGxkelhybWdVTmlnb2RTWC9tT1lDNUZvNEhWUWpRS0pvaVhORFoxaFhoeEZ5VjNvV3NMVjcya21KZkxMa09kRnQ4WDUrcHpGVkp0VTIxekRkeUxnRDhBL2hwNFJWeHFuOVVRdVMvd1FRUUw3YkhBWTRCTC9lbjRzbDBMV3VGYWRMbGtWWjNzMFJvM0pza2Mxd2tHNXpXQ3dYck53VlVmMXRkODJDL0pIN3JTaDA3ckw2WnZvUlJjd0VSczNneFZCMHpBakVTZnk1QmdlVWw2ZkpxSEM1VmRTQm5qMGtKMTBjRUZEeGVwTEMvS0xNTzZCRlNmY0UyeXVQUjM1d2g0RmJpL0FYNERlRDd3RmtLck9XYTJDVEcxUndPZlRMRFNIcEJkamtKTHpGcUpIMUk0V005RHBrdFR6U0ppZXBIOThqcEowZDhuRG9KMnVYcUl6Qkt0eFRWOWR4T3grVEZVSFRBQk00Q1o0MTFTMmFKamRWSEd0eTZxOVVWNnhNdVZwYUE2YmlabUY2N2lRcmdUM0hPQlh3ZGVCTHhoSGlkb3dOd1RlQlR3Q2NBL0piZ2FxNWYwSlg3MFpTNzJXV002US9GNnRMaXVSZ3Rza3BEdGtrdFdIYmp3ZWFtS0IrWDhZeVppcDhCUWRjQUV6R2lKbDFoZEtkN2xWS1dMR0FNcFlsMlZsWFhKd1VWZkNwbUlXejIycTg5ZDJDcjMxQkpaQU40SzdxWEF6eEtFNjgyTXd6VTRiKzRndUJnL2gyQ2gzWHYyVlB4NlVIUnRqZW5Dd0VuRWFGdGhWeWhGN0JwWnhLU2lSNXFMek9WWm9iV2dwdTlwSW5ickRGVUhUTUJXbkVxODlMSk9UcEdYREVCSnJ0Q3A4UmVBQ3lKWWNYMkpydVVsVmxwZFRhT1ZGdCtLYytudm1IZ1Z1R2NEdndDOGVHNW5aVFY0S1BCcHdHY0RIekxaS21zS21RZ0xaVFVQN1ZKc3VSTkZ2SzRveTB5TG1JNk5wVG5JWEhRcGtsMktSVnpNUk96V0dLb09tSUN0TUQzaVZTZHJiTG95UFY2N0RHczM0YVhxc1ZoZTRqYXNFelhxS2hvekNkZDE0TVhnZmhMNEplQ3Q4enNsSzhrOWdJOEMvaFh3R1BDWHlxZW5DVm1ScVVoWmprcGJZdGZwV21GWDZMb1Z0VXR4RDFVY21DbkpIU1ppTjg5UWRjQUViRVdaSmw2U3JJRkttM2F4a2taMEY0cDRYVkxyMnZLcXhVc25hc2cwSnpNbmFCd0R6d1gzWThDdllTN0MwK0FUZ2M4bldHWGIvZTdGbGx1eHJuaGZ4OFdtaWRnVlFyenNXc3hZM1BXaEhGV2F0a1dTTzB6RTVzOVFkY0FFYkFXWlJieklNeU52K1NoQVViak9veXd1QjVlOEVxL29RdFRpVldjWjZrU051a0o4TXpuakt2RDc0SjRHdklEeFp4R2VOZXZBaHdOZkFUd091RHhaeVBxS0JldkpNL2NJWXJUcmN6cDlFakVIVjN6WElydEdTQVNScXZlUzNIRm9JalovaHFvRE5wQjV4VGlKZUJHVE5Wd2MxK1ZEck91U0x5MHV2WWhsZHNHVlZUVlNvb2F5dW1xWFlVZTRQUEFjY0Q4RS9QYXBuaFZEY3dUOGNWdytDbmdTdU04bUNVUGRhNngvdnpyNVJoZFhMcWJYb1YzTHNwUEFFNjlaNTlVL3FiNklWZTFZVVV6QVZvaEd0dUVreTBzR0Y4dWc1SXZrQkkzTHhIVWpZVU9xYXpUalhYNTZyQXVBUHdQM0hjQ3ZFdnhIeHRud2h3UWhleGJ3ZGVBZVRVZkl0SjYwRmkxRWhaRFJGYlNPZ0VVeFN0ZHVqNGo1K0hxclpyOWltSUN0Q0EzeDB0T005SW9YWmF4THhPdXkydTZJRjVYTDBJWFBuV1IxSmVGNkpianZCNTVCQ0pnWVo4OEJJZWI0TzhBWEFsOEo3c0d6V1dQT2xTVy9XdFpXMzZTajZUcngxVFhTSTJKSFpCR1QxNW1JalJ3VHNCWEE5emMwNjVQRXkrV3hYRnE0dElDSjlTVnA4aDN4b3VzeWJGcGRCOEF6bzlYMW1ybWZBV01lN0FNL1JCaG45eC9CZlRFcDBhUFhHdlBkamtyTHhkZ1VNSmZmMzhIbmxTZFlYTjVsQzB5OXhCZ3pKbUNyaFc1WTFoeHBFc29OVk15THRuamRGdGVYWGVrNkZNdXJUdGFvM1VKYXVJb2U5WXZCZlF2dzNOTStlbU11dkE3NGNzTHY5YTNnUG54R2E0enlHcWhqWlBXczJTNHFVTWU5VERYZ09nVy84b3ZTUUdlendzYU5DZGpJYVNSdFNQVnZFUzQ5UURtTjcxTGlKY0tWQkt3aFh1ZFEwNS9NNmpLOER2d2d1UDlPcUp4aERJdmZKRXc1ODVYZ25relRHcE5KS3VXeFV3TFZuTHV0WWJIVnd1VmRFQ2FKeFhsUG5vRmE3VS92TVJFYkx5WmdJNmFWY1NqeGlDZ3dVcFJYc2czUCtUTG1KZTdDMjhnQ2xqSU82VnBlbTB3V0wva3UvQTI0ZncvODFpa2V2M0g2dkFYNGVrS3l4M2VDKzZEU0lKSjV4NmE1RkxWRjFoSXVJUWxXdlMyaVJramg5NVREQkUzRVJvb0oyRWlabEM1UEhrUzg2Y01BNVIzeXZGd1hLTjJHV3J4MDBrWkx2UFQ0cnQ0RzZXZkJmVDN3MmxNN2VtUFIvQnJ3VXVEYndYMXV2MHRSYUYyYm5VNk9Rb3RVMmlhWHRKSVlXQksyK0Q1ZC9OY1lJU1pncTBFU0w2Y21vblI1WWtJWjZ5V0RreS83YnRLR1dGK3RiTU5XSWQ1T3cvUjJjTjhLL0FCV1JXT012QmI0QXVCL3g1am0zYnBDMWpkL1d5MWNIYmNoNUVrM1haNDkrcGdzYXNkZWlaekw3MDFKSFdhRmpROFRzQkhTWjMzRmpFT1pSVm1tUTBtV1YwemNrTW9hdFhEMXBjcnJHWk5yeTB1K0EzOEw3bDhEdjMrNmgyNmNNVWZBOXdLdkNtdjMvdTBzUmRSalZ6MFdVcUtHc3J5T0tjV3JYclFGcG9YTWtqcEdpZ25ZeUppUXRDRVpYNjJxOGhjb0J5bnJiRU10WUhWUjN0cnlxb1B5QVB3bXVLOEUvdllVajl0WUxuNE4rSHZnQjhCOVROc1NnMzd4MHVpWVYxMjJxaU5pWGxsbERTdE1QczlFYkNTWWdJMklIc3ZMUmF0cm5SRHpFZ0VyeEl2R1lPV2ViTU0rOFdyR3UzNFUzSDhFN2p5OXd6YVdsSmNEbnd0OEY3aC9uZ1ZEcmcxSjhPaERXMU10MFpMdEk1ZG5qRTR4TWJLUXJTc3J6RVJyWkppQWpSZnRObHh6WlkzREhVSlYrZk05V1lldENodXRoSTFlOGRvSDkwM0FVN0Y0MXlyelZrSmM3RTB4MVg2dDN4b1RmR05kVzFwU05QaVlQQ2RaMnVkTElkT0x4Y05HaGduWVNKaVdkZWh6ckNxNURuMXBmZFhWTlNhVmg1b29YdGZCZlFQd1BhZDZ4TVpRdUFGOEhXSGMzOWVEVzU4dVl0QjJHM2FxM3Jzd3hZb1dORDNwWlJJeGk0ZU5FeE93RVRBcDd1WEtHWlU3Y1MrWFkxOTZxUzB2S2NvNzFmSzZBdTVKd0UrZDlrRWJnK0lHOEJUZ25jQzNnYnN3V2NScXkwbktSSWwxbFN3dVgwN2hrdmFyVE1Ya1RzVGlZYVBEQkd3ODFHbnJhYkF5T1dWZWkxZWR1S0huOUxwQWNDK2VKRldldDRMN3Q4QXZMT1o0allIaGdhY1JMTEh2QW5lK0xXS2VzbDBxVXVocFcyQTM0dmFSYlBzb1l1bzlOajVzaEppQURSeGZOZ0FReFN1TzkwcXpLdnRzZmNsRWt4Y0pZblhKWjB2c0lublN5bVpoWG5vR0tOOEo3a3NJMDU4WXhpU2VRYmlBdmh2Y2RyOGx0azQ3a2FNUU1LOW1ndlo1UnVqYU9rdURuUW5XbkU0ME1pdHN3SmlBRFpnKzF5RjV2RmNxMGt0UDFxRzRELzFzTWErbWVMMHJqdkV5OFRKbTVZY0lGOXAvQWJkVmlsamhTdFRDUTN2bVo3Ryt0SUFWUWtad0p5WWhvK0ZLUEtYRE5FNFpFN0R4b0JNM0poYnFKVnRmWW5YcDhsQTZWWDdMVFo1Qm1hdlJiZmlMaXpwS1l6UThqWENSZlJ1NEtqdFJYOGN3d1FJalcxK0hxS1YyTFZJbWVZaElKbGVpV1dIRHhBUnNvUFJsSGJvc05rVzFEYXJZRjluNm1qak95NWZXVjJGNTdZSDdLdUNuVC8xb2pURnlESHdIY0Fmd1ZlVlRNakdsam9rVlZwakxWcFVJbVJZd0VTL1pObGZpU0RFQkd6WkpVQ1Rya0xiMVZjK3VyQmNSdGNMeW9oM3pLdEtkdngzNDBkTTlQbU1GK00vQSsxQVVBWloxS3pOUnNoRzFCWmFFaThvU28zSXArdElTMC8vUEdDQW1ZQU9rU3R4STQ3MTAxaUZkMTZFSW1CWXhMVjZ6WkJ6Sy8rTkh3WDA3ZHVjYnQ4NHU4RytCKzRCN2JEYytsZHlKdE9OZ3RaQWRrTVhyd01GaGRDK0tLN0dWbVdoVzJFQnBEU0EwbHBoSkE1WmRWOEFrY2FPMnZpN1FGYS9XV0s5bVZmbmZBUGUxV0lVTlkzN2NDVHdKZUhrak1Va3QrdnJXaVVsMWJEZGQzMTVkM3o2NDFBdTN1Ry9VN2pTR2d3bllzQ2tTTjFEaTVkbzNlQ0ZpcmhTdnVyNWhhMDR2WGdydTN3RHZXc3p4R1N2RTN4QkU3RXAvSjAxZjQzVW5yWjVOWE9LNlJWYXRpMW0xMFZ1eFZzWEJIRFNIcGhoTGlnbllnRGlKOWVYYnZWTVJzZk9FVWxKMTBzWWs2NHNyNFA0ZDhMcFRQMUpqVmZrOTRGdm8rUEMwSlZZa0taRkZySGFUdDd3TUltTEZkZTRiMTdveERFekFoa2xLM0VBbGJuZ1YrM0txWUMvbHpYeGVMWFhTUml0ZEhnZ0JobThFZm5jaGgyZXNNdDhQUEt2ZFdVdVdtT3RQVk9xNzNuZklia1RKc0pWWkd1UjZUNWdWTmd4TXdBWkNaWDFCQ0RZN2RSTnVPT1ZXaWRiVmVhOEV5N1hUNWJjSXBhWW14cjErRnR3ekZuR2d4c3F6RDN3OXdWMGRkOVh4c0hUTms2MndQcGQ1dXVaZEk5YnJzaFhXdWVhTjVjY0ViRmdVYWZNK1RwVkNLVjdUYm1RUnNDTHVOV213OGt2QS9RZGdiMUZIYWF3OGJ5WmtKdDQxUFI3V3FqYWpNMi9UNGh0VEF2bDJ2QmN3SzJ3SW1JQU5nTWFObEc2NG1GRzE0Y05jWDhsMVNIbnpTbkhlRTA5S2VZVXdOY3BiVC9jUURhUERIOUtja3FlTy9SYXpMYmdlRVhQWkF1dU1kVFFyYkxpWWdBMEhiWDA1R2xVM2FQZENXOWxZMDFMbUUwOEhmdjJVRDh3d1dod0IveFg0bzlsY2licnlUS2NUNTh2WkZiWmR2eFZXWFA5bWhTMDNKbUJMemhUcnF6Tnd1WkY5ZUZMeFNpTDI1K0MrOHpRUHpqQ21jQTM0QmtMQjZMaXJKV1oxYW4wdFlucDlqaEFqbHZ0Z2czNHJ6Rmh5ckJMSGNPaFlYNzVoZmJtUUhsLzcvOC9GNTdaOTVUcnA2MzNlRmVOZTcxemdBUTZaTlhMdllKc3k1eHRDRnFlVWtkZ254QlAzc2NIZ3MvQ0hoTUsvVHlGZG9IS2RTcTFFSFJQVEFyWlBGcTlkdGQ0QjloM3MrMWk1STk0SFIrb3pqK0wvc2VvY1M0d0oyQkxUeUR4c1dsOU91VTU4NlQ3VTQxOTByN1BQZFpKNm5zOGtqTWt4U200SFBoQjRQK0RlY2JtRGJsMHVNUXZrQmpzazF6RzZycGFyaEU3Q213aHh4dGNBZndlOFpSRUhNeUMrRC9oTWNBL3JxVnBQT0xXRk44SjE3d2NSc1QxZ3orY01SaWsxdGU3alRNNHUvdzhUcmlYR0JHd1lUTEsrTnVPTnVLTnUyTUp0RXEyeVB0ZGhSN3hlQmU0N0ZudDhTNGNqaU5UN0FnOEhIaFhYOXlMM0NPVG04YmZZeUVsamVVUm9XWGNKb3ZaUzRFK0F2eUFNSG44dHE1c0plaWZ3VGNEUGtlWVBnM1pXNGhIbFlINnh3clNJU1RhaUdNS2JCQ3ZzaURDVHMzeXVGZnRkY2t6QWxwOTYzRmRmMFY3ZDI5UWlKcGFYOXZtM3NnNEJ1QkhGYTFVdGdJY0Nud2c4RXZndzRJRnhmMHVrZWxxMVdSczduYTd0SWZ3WTR2TzlCL0FnNERQaTY5NEUvRG53WXVCL0FTOGttQTJyeEc4QXZ3QjhYbmpZbDlpaDc0dXQ2RGJYOThVNVFxZHVWd25jZ1FzZWlSc3Vlemk4eThWK2JiNndKY1Y1UDl6ZnhMbnh4bGtyOTZHTStWcEhwY3Y3NExHNjVPQXljSGNmUEZ6M2lNdnR3TjBkM00ySDUyWEN5cnJ5UmhILytuVndqeWNFQmxhRkR3QStqdEF3UG94dzRpWllWYTM5dDNvVHRTN2s1c1h0d0YwbHVCci9KL0JjNFA4UVd1RlY0S0hBYndIM3l1SWlvY1ZqY2tYNmZZS2xkUTI0QXR4RktOOTVKOEc0bGVWZER0N3R3MnV1RXJ5Nit5NWMvaktqYzZwYVAyWUJHNm9PbUFXMjNDVFhubE5DUm5BaFN0RmVjWlhvOVBsV3RwVzREbnZUNXZmQmZTdXJJMTRmQXp3QmVEendQbVRScW01bFA4UDJMSStGV3BocUY1V092Ymg2dndkL2dkQ1FmM0JNdFBsMTREa0U2MlRzTHNhWEV1YWcrMC9oWWNzSzYzZ25YTTdPVGZkSWRLdnZ4dnRqMzRXTzRRWkJ1Q1NtZG96NmZjd0tXejRzalg0SjhkMkdTOStjUmRrb3I3SVBxWkkyWEx2V1lTdnU1UUIrQ3ZqalV6KzZzMlVMZURUd2M4QXZBMThHL2w1NWxsNUI5K3gxRDE5dnQrYWwwbk5UMWZ1blBWOS9idXYvSnBkVy9KSitHL3luZzM4bThDTGdYd04zdS9YVHROVDhFQ0ZPcTNaMXhvZlJQemJzSEVHOFJOQjI0bXMyWFZqNlptSVlyN3Rud0ppQUxTLzZ4a2szbEF1dXhFM2ZqWC9WRnRpSnJLOTNndnMreHQyOS9GRGd4d25abFU4QWYybTZhR2tSYVltUW5raXhYazlhV3U4cFpnNm1LMnl0NzVhKy94cjRoNE4vT3ZBcndPY3kzaGIzRGNBUGtJWWcxQjJ4cG9pUlJVeGJZbW5rZzZ2bUN2TTJKbXdRbUF0eHVXbGxIOHJBeXkzSlBxUzhJV1daTmV2UUFUd0xlTWtDRDJ5UjNBMzRLb0oxOGw3OXJqN2YySzdqTE9teHkxWmJ2ZWpQMU5zZGR5RFY3K0R5YjEwM3lQVStuU0ZYZktZSC81SEFJMk1zODFzSWJyZXg4VXpnQzNOYVBmUjRLaWdGVEZ0aXRRV1dpbHJIZVBOYUZMRmpsei9meG9RdEdTWmdTMGFWdkNHUDExeE81SkM2aC9WTjJlbFYwaFd3cHZYMWRuRGZ6VGp2eW84SHZvMlFCdDl3RThwNmtsZzEzWG0rL2RwSlFnWTl3a1dPYjlhaXRWWnRUeEsxNG45c2dIOEN1SThDdmhWNEJ1UEtXbndYOEZTQ2tERTlGbGFNbFNRUCtLL3ZsUzJmQnpiZndGTHFseDRUc09VazNaQXVwODZuZWI5Y0tXRDFEWmxxdmZucGsxUTZDRzYxc1UxU3VRWDhPMEt3LzdiUWN4YjZoS3NRS2hjSHROS05kL1hGdzFxdXZXa0NWZ3RWL2JpSXg3aDhIZlFKV3lGa0h2dzlnZThCOTJqZ2E0RTN6bmI2QnNHdkFIOEY3a082VmxodGlYVTZmTDVyaWFYaTF0SFRJVE05ckdISkhFdUxDZGdTNGVuMHBDZFpYNFdBVmIxSlhUS3F0OUk4d0p2QlBXc0J4N1pJN2tQb25YOE9UYXVySlZ3ZGtmTGRPRlM5WFF2YU5CR2JSYnpXRyt1MDdhdkgxWHRidjY4alBPRS9EOXhEQ1c3VXNTVHEzQW44TUtITTFIcDV6RnJ3TzNVU1habVZtTnp0cXROWHU5eWx2SlQ4RHhPdkpjRUViRG5Sc1MvbmN1WDVZdW9JU2hlaWpBM3JKRzVVUGZlaWtYc2U4TEtGSHRycDhoQkNsdHBqSmx0ZHRXaHBnYnJSV05mNzB1S3kyTlVpcHY4ZmxNSlNpRmZzOFd2QjBqRWMvYnZYKytvNTNQU2ljUjc4aHdDL0JPN0xDV24zWStEWndGZUFlM0FqRnViTGM1a0dOL3ZxM3BIN3hnY1Jrd1NwQThMdmNnUnBHSXV4WkppQUxSLzZScEdxQUsyc0tsMCtxbG5ya0p4UjFZeDlYUVgzdll5bm9PeWpDTWtvRDVoc2RVMFNMWjBSS1BYeEpCNGkrd3B4ODIxcnJCVVBheVZuaUdXbGYxKzlGcGZXaHJJTTlHKzdTVmZNNUgvV3Y3Y0R1Q2Y0bndCM08vQWpKei9GUzhjN0NNZngvNFdITFN0WGw2VnNaaVQ2cnVkQ3pubWR6R0Z1eENYREJHdzVFY3RMOXlUMTdMUEpuMS8xSnVVNUhmdnF6VHo4WmNhVG9mWlk0SDhBOSswWHJ6N2hhcVc5SDhqYVY4KzVJRnF0bEhjdFlyVVZCbTNycTNZVmlzVXM2ZHhTNjFLN3dQUmFMOXBLRXlHcnJURUhjQUg4ZDRIYkJINXd4dk83ekR3YitCcHc5MnAzRmxvWmllbitVZTdFZFArNFBLaDUzUWNMdVpVd1krSzFCSmlBTFFtKzZqM0dIbDdxcGJ0Y2ZhTytDWXRNS3VVQzBlNlRUdXhyYjBTeHI0OEVmcFpVWGdqS3RRaUtGaGs5L3VwQUZoY0U2NEJZSDArdHRhRFZZN2RhQTVLVGNEclZZNmMveWFBUU1HVnRhY0dTMzF2aU9KTDZyWmNqUXNiZGNXeUFkWU5lQ05rRjhQOGQzREhCNVRwazNnRDhEUER2dzBPeGtscnh4WTRIbzQ0ZHkvMGpGaGpaUW5aS3lFeThsZ1FUc09XaWNCOTYxZEQ1MHBVa1JVbzcxcGN2ZStOMWdELzlqejhqRklRZE9vOEFmb0tKNHFXdHJ0cmkwa0sxNTh1cHV2WmNtQzlLaTVnSVdjdWRtRnlJVHFYWlZ5MWR5aXFsYkZnN2JrUEtobGIvM2p1VVZzT09PcTR0d3YvZWpNY3Y5N2VJbDF4UEhuRGI0TDhUM0xzSVZzeVFlUTd3eGVCdXkrSTF6UXJiVnV0MEQ4Vk9nVmhnRzZqc1Q1L0hoQUhtUmx3R1RNQ1dqNWI3Y0IwbFhwU0JhTjBETDlMbVhiZWFRQkt4bnlGVUx4MHk5d04ra2lMbUpXdnR4dFB1UXUwaUZMSFN5NjVlK3l4bXRTWFdaNEVkazlQdlBVQmxnYVZ4ZlhRRnJFN1NLU3d2SlY0Ni9mdGMvRTZ5djFXOXc1UG4xWlNVOENSaWw4RC9BTGkzQXI4Lys2bGZPbDRJdkFENHAzbFhKOVpJT1lmZVp0VUJUQlU1eUIzQlpJR1pHM0U1TVFGYkFpcjNZWEkzdWRqN0kxZmdrRUdaRW16V1Bjbk9tQzlQSi80RmhLbFNmbUVoUjNaNjNBNThEL0NRdHVXbHhVdGJYU0pjK3k0STFDNWhrZmtsOVdNdGJETGx4cUh2RnpBOWRpeFY2dkRLamVlcXpGTGZibHgxQTl0WEJrbW15dG1MMndmcSsrelFUaVlST2lKMk8vZ2ZCdmM0NEc5UCtEc3NDNTR3cURrS1dGOHlSeEt3eXYzYXNjQlFpUnlZRzNGcE1RRmJIdEpOSjI0bXIyNjZxa0VyYmpwS0MyeFMxUTBIOFBQQTJ4ZHlTS2ZER3FHNnh1UG90Q0xhYmFqRlM2eW5aR2xGOGJybW9uajVNUFhHZGVDNnk4OXJBVHVNOGJGREZ6L1h0eTJ2UHVFQTFZT3YzSWdwemtsTTRGQy90UXlaMEFQV1pXYmg4OFRwUDVTdzltVkQxcWRRUkF5QUI0TC9RVUw1cWJ1bW5QOWw1YmNKUlg2VlJkNktPUllaaWE2YlZpOERtamQ5SHRUYzYwWTB6aFlUc09VaUpYREU3VFQ3c3JiQWZMN3h0SGpWV1doTjhUb0E5N3lGSHRMOCtRTGdTeWtHS1d1cnF5VmU0aTRVQzB2RTZtb1VycXRxMzNXZnJiRmtmWkV0TU1sQ2JNVzlrbWpJZDlNdXhQaGxVNk5hV1dHRnU5aFZMbVBLU1V2UG84UzFzZ3FieVNTTjA3aEcyZER6Y2NEWEFkOHcwNit3Zk54Rm1DUHRhOHJkdlZZWVhVdE00bzFTbmI0bzd0dHlJOGFBbTFsalo0UUoySkxoczNEcDZndjFPSlphdlBwS1JuWGNoMzhSbDZIeUtPRC9KVlNYaUx0YTRpVUNwc1ZMM0lRaVdQVnlqU3hpdThCdWxjU2h4NE9sUWN4azYwdStReElNM2JCRm4xUGgybEtOWWozZUx4VnRwcHUwMDNGdDBoV3d2ckZvTFZLQ2h3Zi9OZUQrQlBpbENXOVlWanp3YThDWGdydWNkM2M2ZzB4SXF5ZmVXOHJqc1k0YUR3WTJxSG1aTUFFN1kzelZxM09xY2FQSGhlanlUZGFxZDlpcU9vK3NmNHRRZ21lSTdCREU2MzI2NHRXS2UwbVdvUmF2cTRUWmQyVUczaXNPcnZoS3dGd1VDRjhLeEEzWDd6WXNxdE5YUFhJZEE1TWQ2YmZXTVRHNnd5YVNpTVhmZTVzZ3Fuc0UxK0crTDJOeldzRHFrbGExOVZCY0Y3SzlBZjdid2IwSWVPdE12OHB5OFNlRUdhb2ZuWGUxM0xaRnNrekRteUgzbW96THF5MHcrVnl6dk00WUU3RGxRaytkb3VzZmJpaWhTbTZQU3J5UzllWEs3RU5rZlIzY2tKTTNua3h3YzgwUTl4THhrcW5sdFhqZEZaY3J3RjAraXBtRGErSTY5TjNNUTIxNUZZVitSYmg4T2VacllzTW1QWGd0WkpTL2UrM3UyaUJYU3U5a1JmcUcrMUFKYXZ5WG5jUUc0dWVLQlppKzNvUEIvMmR3VDQ0Zk9pU3VBODhsQ1ppSVRDc1cxaGRiN25nMWxOVzIxdmpOYklxVk04UUViSGx3OFUvUlc2eGNpUFhOMVpxc01tVk1VVFpXL0JXaGR6cEVIazZZMDZzUjkwcVdsNE1qWDdvT1crTDFIaGVFUzRUc0tpRVdKZ2tjeWZKeVhiZGhFaTlYaXRiTTRpVmYzRVdMek9mZk8xbGt0VFZHYUdnbGlXUkxMQzcxM1RxeEw1L1BUUzFjcmFvc3hYVUNJYzc0UDRIZm1YWXdTOGh6Z1c4RHQ5a1dyOElLOCtWOVZJdVl6a1JNSFl2S2hXaVcyQmxpQW5hR1ZER1JTZW56cmJGQnJkaFhzK2FoYlAvU0tSL1BhYkZCbUJibGpuN3hPaWFJbHg2Z0xFa2JFdk82QXR3VnhlczlhdnNxS28zZU4ySmVVUmlUY0ZYLzM3djhuVTRTME5jZEZubXMzVjNhSXJzUnJ3UEpmdXdVR0haVkVvbDhwbkpUMW9QYTZ3azBRY1hETG9KL0NyZy9paWR5U0x3YWVCR2h2RmlrMXdLak1XaWMwdHNoWXlwMXgxQ3lPRTI4emhnVHNMTW5OV0NWOVZWWDBxN0hCalhkaDdSNzJWd0g5d2NMTzZUNThpbkFaM1YzdDF5SE4yaTREbDJ3c081eThKNG9YdTl4SWZaMXhXWHJheTlhWDNYTVN6NWYvbCt5dGx3cHFQVjNtMFRkOEVsOExLMHBmOGZqS0tLNkNuNTZyRjJhNm5NTFM3NjErTzcxVW55bnh3Q2ZCL3pZbElOWk5nNkFYNlVRTU9oYVlYMkR4NXYzbDIrNDV4M0dXV01DdGp5MGVzb2JhcEVhYmEzWVY1OEZsdTZ4RnpQTVFhb1hDQk14TXNYNlFvMzNjakdMME1mRWpCam51dUt6RlhZbHVoQ3Yramp1Q3lWZVRxWEtSM0h3cmhTSG14V3Urbld1NTdFMGpzYytOSm95Wmt1RVRLekJ2am5JdElXVjRxbVVTeTFvTFZlaWZ4SzRYMlY0Q1IwdkJONEY3dTU1Vjh1VjJFem1jRG1wUXpxTmhYdmVsWi9sc0RqWW1XRUN0aHhvZDVMRVFab3A5TDdzS2ZaTnZ0ZUphYnlRWVdZZmZoYndFZDNkUmV5THN0S0dsSUNxc3c1VDhrYTB2Q1JwNDNwOHZZaGZpaWVKU0xoU0hQckVxNkN2TWZPVlFEU095K2wxL0J5bllscVM4YWpUOTMxOFV4SHpFVXZlbHgyZHVzTlRwSWpINzVGY2lSOUcrQTIrZjlMQkxpRi9DYndjK01mbDdrTFlxZTR2Mzc3SGVoT2tYUG01Smw1bmdBblkyZU9nakgvUkhxL1NXdXJHcU80WkFyaURnYm9QTHdGZkRtek1ibjNwdEhsSml4Y1JLOFo4K1R6bVM0cjJIaExpWGtldUhPUFZFaS9nUlBHdW1kN2p5NGF3RURQWFBYWkpJaUZ1eTR2bHQ1ZTRqVzZrbXlMbXV4MGYrVGc4K0s4QTl4TU1xM2JtTmVCUEtRU3NJK3hVQTVzckYzMG5uUjVWbFlQeVBqUHhPaVBXcHIvRU9BMThKVEt1SFhBdjVvaGlzbmpWTnhheXZoUDRvNFVjMVh6NVpPQWY1WWNkOFhKZDZ5dkZ2dHlFQWNzdXVnMmRHa3VGS2hIRmhNSEFMbHBBcCtFdWFueDIvZjhsV2VVb2ZsZkpUQlRMVStKKzF3anUwZFpnYlYxbFJGZlg3ejNtQndQL2ZONEh1d0NlbnplMTFhdmRpUFVjYkNuV3JOWWJMbHVxNjNLUCtYeXZHbWVJV1dCTGdyYkFmSzRha0hyTHZ1d2hOZ2N1MTZJb24vM253THNYZUN6ellCdDRFczIwZEdsWUpZbWhjQjhTRzNGZldtQ3lTS2JoTGpuWm94aWs3THJKRUVtNFR1dFlXOGovYTFsbGhZOVJiYU9zaThyNmttdW5OZGFwVGdMU0NSM0pDbnNpdUdjenJEcUpmd3pjU1NoV1REY0dWc1RDZkZsZXFsaWpyQzk1ajhYQmxnT3p3TTZlNUpkWHNZZzY2SzVUZWx2SkczM3hMd2Z3R3dzOG1IbnhDY0FqeTEyMTlYVk0xL3BLQWthd3RPb1NVV0o5U0VWNlBjdHl5MjE0SnVLbDZiSEdaRHpha1ZpaFBsaGo2Uno0WUdFbVY2b1NkRzJGNlVvamZWT3hlQWkveFdNV2NjQno1TjNBSDNaM2F4R2JsbzNZdk5ja0RsWlpZR2FOblFFbVlFdUF1aGs2c3pDVDNZZDk0dFhLUEV3MzB6NjRQMXZrd2N5QmRlQXpnSFB0eElua1JxTmJNaXBOamVKeVVWNHRYbnArcjZKNmV5dm1kVnF1d3BQUzQxYlVJbllqTG9VcnRYSXA2bEpadThSaEE1VHpuSW1JRmVJRnNBMytzeGR4c0hQa2lNNGNaL1U5a2dUTTBYVFZTM0xIaG5wZHk5Tmg0blZHbUlDZExlbmlGNWRFdkRucUtlYW5pVmR2L09zVndPc1dkVFJ6NG40RUFWTVV5UXZLK3FxblNrblY1bjNYMmlpbVJuRTVUYjdaYUMrRGNOWDBpUmhCeVBTOFoya3NuTXN4d1NUbVBydFMwL21ndjQ1aU9pZVBKL3cyUStLdkNKMDQrdU5nS1dtcUZRZWptL0NTckRCbmNiQXp4d1RzREtoNmNNaU5VUG5ZVXkxRTJ0bGpoZnV3TC83MWN1QnRDemltZWZMUGdMdmxoM1dqM1lwOWRTd3dTcGRoSjJuQjU4Szg5VmlxcFJRdllZSkxNUTNtMXBhWXoyUGlXdWRsejFVRmkrbUtXT0l5OE9tbmVuVHo1KytCMSthSCtoNnA0MkFwWnVoeXAxRmJaWkxNa1Z6MTVrSThlMHpBemg3dFBuUlVBMDk5S1Z4OVFmZStnYWo4SDBLTE5CUzJnU2ZRU2Q2b0xZNVc4b2Eyd01UcXFCdnBsRzNvSmpUVXkwN0xFbE5MWVptNjdseG9oYWo3cm9EMVpTVGl3Zjh6d3F3QVErSDF3Q3U3dXlmRndlcnliV2xPTUtvT282TW82Z3VrenFteElFekF6cGJrUG5SMEN2aHFLNnQzRUNvOUE1Y0J0dy91THhkeEZIUGtId0VQeVE4TEs0TVk4NkU3V2FXa3oyc0xURnhrUlhGZXB4cG90MlFKR3pkSit2NituQXZ0Qm1HbTVpVHdyaFQ0WGRlZVY2eHZNa3dQb2FqeWh5N2tzT2JERWZDU2NsY3JmdFZLNXRDeFoxMkZZNTJjY0dWVzJCbGpBbmJHK1BiTkpEZEs3VUtjdFJTUWcxRDBiMmdKSFA4RXVLMXRmV2xMUTF0ZkxRdHN6K1VraGNMQzhCTXk3WVlrWGkxWFl0eW5SZjZRSU55NlFrazZUejZPaGFOaGdibXVrQUZ3ZC9BZnRaQWpuQjh2SW5raEpzWEJPaUxtR3gxSFQrOTBSU1plWjRBSjJObFJ1eDBLOGZKNUxNK0c2N2ZBV21OU0VxOW5XRFhzTGdJZlUrN1NqWFR0SXF2alg0VUwwVmZ1TVpXMDBhcXdNU2p4RWx4WDZKTXJVY1hFOUdCbmZhN0VPdTJJUExHTUZvMUVEb0JQSlBqV2hzSmZBZ2R0OGRKTDBYR2tZWUZSZFJ5VkM5RTRJMHpBRmt6dGNsRHV3M1FqK2JLR1hSMEg2OHk2M0pmQThlTFRQNXk1OHY3QW8vTERWcHhIdThpMGdJa0xVVGZPZXVMSFpIMzVmaGZaa09tend2cVNYY1NsS09kb1VpTEhjZlYvZUF6d0QwNy9tT2JHMjREWDVJZVRyTEJVd2kwbWN0U3VmRjMxeG9GVjVEaHJUTURPaHVLQ3J5MHd5cHVsdm5uNjRsL05CSTRoOGJHRThoQ0tWdkpHVVhtZTNDanJ4cmtZNjZXdEw5Y1FyaUZhWDBMbFNvU0dGZVpLZDZzV0xXMTl0ZHlJVGFIZm9XTXBMeldITk84RlI1bUVVZHg3UHQ5N0hmSHlhbkZseDlHRWJNR1lnSjB0aGVYbDJ2NzRqb2lwMXptMUxqNFhjSCsxa0VPWUg1OUVrWDFZdUs5OE4vNVZXMkJhdUhTalhGdGVZN08rT2lLbXJEQ1pmdVVHUWNnTDBmZTVJa2x4dmxEVitHbTRFVDM0ajEzYzRkMHludUJHVkNTeDhmMGR4eUllNXNyaXYwWGlWT1ZHTkl0c2daaUFuUjNwNHRmdUNNcWJwQ1Zpa3FVNE1YMytuY0NiRjNNY2MrRzlnQS9LRC90aU83VkZVWXRYSzU0enV0alhGSklyVVZ1dExwYWJjbDByYkwrS0ZjcDUweTdFK3ZmZ1ljRHRpenFpT2ZBMzdkMmRHQmlOdEhvb1pvZElIVTF4L1p0Z25SMG1ZTXRCSFVqV3BhUm1jUjNXbjhQZkErOWExTGVmQTQ4QzdsbnVxdDJIU2NCOE93YW1yWWdpbmhOZGFXbnVMRVprZlZYb1k5TUNwQk02V3U3RWRNNThOUmFzVC9qZkQzam9ZbzVwTHJ3WmVIZi8vYUx2dno0ckxEMzJGRlU0eklWNGhwaUFuU0c2OTZZc3NiNkN2cTNVK2Q0TXhEY1EwdWlId3NPQm5hNm9pUHZRVTQ1dmt0aVdGcXhXTWtMS3FQTjBabFVlbGZYbHVsWlNjaVBTclY2U1JFemNoeTZmdC9yY05RWC9OdkFmZU1ySE5FL2VBYndsUDJ3SlQ5Tjk3M29xMzhSRkQyWTJ6Z0FUc0xPaDB4T01ZbFpZWUpRM2s5N1hsNEdZZUNPaFJSb0NXd1NYVktTMmttb1hZa3JpOEtVVlZyakFYS3kyNGVqUHBoc3BLUjdtbFFYclZPVjZwMFRNUnlGVDV6TEZ3T2l2aStnQkhzRndXdTYzVVFpWVVGdGdmY2tjZlozSGRBK2FHL0ZzTUFFN1E2VDNwa1JJUnZpM1ltRFRTa2NWUWpha0FyNjNBeC9TM1QxSnZBb3JRbS83TW1WZXN2RWt2VHcxdm1PeXZvUldNb2RLNkVnV3JPODVkNVFXV0V2RUNqNE1PSGVhQnpSSHJ0RWJFMjVsSXZhNUV0T2tscjYvODJoQ3RrQk13QlpJNjRMMzFjM2p5eHVvMCt1alg3d1NCeFRqWHBhZU80QUhscnRTUSt5NklsYTRFYWxpWHE2TTRTVDNJZU9OZS9WUnV4RmxyYzlSNS94UnhjRG9EajFJNS9DRGdFc0xPNXhiNXpYbHczVFBlRG9XV0Y4SGN0Mlg5Nmp6dEdzaUdvdkJCT3dNMGZFdnlwdWdFMUIycGR1aU4vc1FjTmZCdlhaQnh6QVBIa0k0eUFvZC8ycFpZRElXN0ZBdlhvblhDcm9QQmE4MmRDS01pTHBVcmRjZGdVNzhpM2J5UytJU25ZN0hVdk1xT2o5K3kzVllkeURyQWN6VDdqOGczOXZHNldJQ2RuWWs2MGw2Y2I1OUl4V1dtWi9CQXR1ajZlOWZXaDVPLy9ndjJ0bDBXc1E2RGEvcldnLzZjMGZwUGhRbUhLOElXZW9JK1BLOE5jV0wvQnQwUHRlRFY3SExwZWNOd0kzSmJyOUMwRnpEQzFMRnFmVjkyL284NDVReEFUc2JPaGU4RXE5ZUVYT1R4U3Z0MjJOWWM0QjlhTjVzWmlGU1dtQXROMktyNFQzMjBZSnpEZXRoVlhEeEhQaitqa0RSR1hEVGt6Z0VEODNZNWRJU0JheW12biswZTdEWGhTOXV4MnB0TEJnVHNETkUrYzZURzVIU1JWRlU1Nmg4OWIzdWkzY1MwdktHZ0FQdTM5MDl5UUtyM1lncHBpT05yMWZXd3lxTEYycFFNMVU4REpXVnFCZmxncTBITWpmUDR3TVdjUlJ6NGswVW1ibXRCS2crZDJJZGYwN1dWL1V2TEE2MllFekFsb04wSTZsNFdKM1UwVW5pY0QxQ05xUU14UHNBdDVXNzZnU09WZ3lzc01SOG5xQlN1dzZQeGZyUW56MW05NkhRRXUzV3VmUmRBV3VkNDFZTU1YMzJleE5tYWg0Q1Z3bmp3WHBvaVZpZm1CWFdsMnVMbWJFQVRNRE9DRi9kQU1vVjBSRXUxNzI1SnZiMDNuajZYMzl1dkI5d29iczd4VmdvNHpDMUMxRm5HMHJhL0pFMDFvMjQycXFSemtOMHBZcXcxeFp0T3E4cWZsaFU3ZSt6Wk84RzNIc2hoM0xySEJHbUdLcW83NlZKbGxqUnVYUlQ3a1BqOURFQk8zdFMvTXVWcm9sTzRKZ3lCdFpNeTRkaEpYRGNsMExBNmhoTDRVWjBVMFNNbkRXWDNJZXJZSEZOUTUySFZsWm5JVjYrYTNrZHEvZDFST3h1d0wwV2RTQzNpS2QvZnJ3Sm5jU09rRFhpWGlaaVo0UUoyT0xwNjdVbElmTjBLdFBYeVJ1dHowaVBKN2hKbG83M0lkVG9VZFJaaUVuQWZMZlJMWVFMTldiSjA3SEFWaHAxUG82VmlCVkM1aHZuazBZZFJQMzRJbkNQUlIzRUhIam41S2Y3Ukt0MkszWmNoeDVMNURnTFRNRE9FTzA2ckpZNllhTVRRS1lVc2VMR0daS0EzWlBrS3B5VWdWZ3Zrb0RRRVRHVnBMRHFDUnhDY1E1YzF5M2Jzc2JrSE5kcDlKM3p1VTZJZ3cyRnQ3ZDM5OTJITFNFcjB1Zjd2Q0RHWWpBQk95TmNLVDdwWm5IWnQ5NjZjYWFLRnd4SHdCeTlqVjhkdStxNHZjUmFjQlR1eFRwbVUzem1LcnNUS3hkaXMyTlF1V2lMemdBOW5Rd1Bma2dDVnQwYmZlSlRkeGJyWVN4MUIzT1d6elJPQVJPd0JkSHFxZm1HaUhrNlJYMzdYSWpVbnlmUHZmdFVqbUQrN05CeFArbEdzdU5DcExJWVhIWXJwcmdYVWFncUYrTEswYkkrWFhWT1hYVStmYi9yc1A1ZEN0N3JsSTdoTkpnd1BuS3FCZVo3T3BFZXkwSThLMHpBemhnSkhydkpOMHhmTm1LSFhZWXpCbXlIa0FUUW9DNitXNHZYc1lpWHF5d0k1ZlpLbjhVS0M1bWdNaEhUZWZWZDY2dHZtU2hpZDZjVHgxeGE3bXJ2Ym5wRGFBdFdiemtwRTdIRll3SjJSbmpWZTFQcmlUZFFaY1UxcmJEck5Lc05MQ1U3ZE1hQTFiVGlOWHArcThMTnBhMHV0K0l1UTBYVDllZHl3b3QwQm5TWnFhbXhMLzM0SHNEbWFYMzdPUk03ZDMydVAvMWNyMmcxN2xYdFRVbWZaMGtkcDQ4SjJPTHBpRkREc3VyMCttamNOSFJ2T3ZZWWpvQnQweFN3T2xiVGNTRldyaSs5djYreFhYbVVvR3NYcTY1U3I2ZWYwWmJYMUxGZ2QyYzRBaWFsOTN0STk1ZWI0ZzFScnpIMzRSbGlBbmIyVE9yNTFUZlVwUGdYTUN3TGJKdGlPbzYrTE1SYXhGSkQyN09zZlB4ckNvVXIwVFU2Q2RYNTFTN0g1am05ekhCY2lBZUVUbDVGcDBOWVdWbE5kMktQRjhWWUlDWmdTMEFybWFOZWV0eUhIWFlaam9CdDBwa1FzWlhBMFp2RVFVTzQ2SDZlQ1ZrWFBTYXN0elBnU2dGTDc2MGVjNEhtZERoTFNTVmdrN3daTTNsRFhQLzdqUVZnQW5aR3VLN3JvYjd3VzVQa1RYczhLQmZpQmlFT1ZsRTNsc2sxNkNaWVhiVkZZZkd2THNveWJWbGVuWTZDei9zbXhzSE9NU3dCbTVEa1ZJaFF3N1hmV3ZUN2pBVmpBbmIyZElLL3NyU0N4ZXBGelp2bWtHQ2FESUd0c09wckdEdlpjaTFyd1pYUGFmZFl3WW9MV3BGQjZKZ2NZNnlXUGhGTDUvTUN3MmxJWkJxRENmUzVFWnZpWlc3RHMyVW8xOTJvdVlrZ2NPL3JqeGhPUzMxdTh0TXRkMktuZ2RYeG5PcDlyYzlhYVNvUnI0V3A3aGo0eG11YTUzaUg0VmhnY2tBVlV6MGQwN3doRFkrS3NRQk13SmFIT3F0cG10dWl5WkFFckNmd1B5a08xbXBRaXludnBaRzJKSTRrV0w3ZVYxdGZMZGVzTHkyd1NSMEVEL2loTkNRU1FHM1JFS0NadkNHTng4YUNHTXAxWjh6SWdBV3MxVWpXSXRhSjI3anVjMXE4TEltalRjdWRPRzBBODhSek9aUXNSTW4rbWNDSnhNaXNyclBGQkd4a0RGakFhdnBjaU5yYVNpNUVSMGY4akFvUmRpMzZPbEhEZGNXcnprTHNQY2NEZHlIVzlIby9HbDRTNHd3eEFSc1owdm9NZ1JrYXZhWWw1c3JHMTFjTnM5RmxrblVxNTdOd3hkSzJ3S0Q3Zm1BNEZ0Z2tGNkl4UEV6QWpHV2p6aUtzWFZjNmhsUHZBNEtRbVpoTkpBbSt1QkFicnRoSjR0WEJUQkhqTERBQk01YVZUckxBaEVaMjB2dU1CbFd5UzJ0ODJNemlaUmhuaFFtWXNjemNUS05wUlZTN05PTTF2aUgrTGV0V1AyNWxOaHJHV1RFVTE3V3h1dHhVWSttclFQc0t0N2k5WXU2QzJQYzlaL1VramFYSEJNeFlkaVpaVTBWMm1JaFdZeHpkS3RQSm9DT2ZxNU5pZ21Zc0ZTWmd4akxUYW1PYm91VjdCcHk2NENaZlpiZVhuSXZPck1LK2ZRNkJZTUgyZkpaaExBMG1ZR2VFdGhicXh0YzNHdW16L2JablFxZmFnUy9QeVZwOHJCdmxkV0RkNVJSd1IxbHVhdVZRcmxTWjFWdk8xenJxM1BsUzZNeUN6VXk4UjdXcitpYXRXdU1XTUFGYkhIVlpHaUEzTUxYbFFMdGN6VXJjSDVWZzYvT1JySWpZRUs4N1dQZWhNZDV3VWNCOEtJK0U3NThTWkpXUWE2NDRaNFR6dElFNmgwNTFDaWl2dDJtVzJSaVpkQSsydkFCQU4vYks2bDUzQzhFRTdKUnAzUEM2eDlicnlxbXNqRmFEUGxaYXgxclBoaXVONzBaY2I4YnRUY0k0VmVkRDRmRzZNTzNLb1JwVHNiYUtjd1pzVnVkeW5jYnN3M1IvbDdIU09WWVI5WjU3VkhjUU9wMVB1ZjlYMVFOdzJwaUFuUko5VmtURFZWUEVKcXAxeTZYVCt2eXgwR2Q1eVhsWWo4c0d1UkhlZExEbHd3VFBNcFpKckxMa1BselZqTHJLdWw5eldhaTJnZTE0N2piSmdpWWlKa0xXNXhVWTNmVTN4ZkozUGZmb1d2Vjhzc3owUjV1UW5RNG1ZSE9tY1JQSU9vbVZ5L0VIaWRtSUMwZGNPN29YN09qMmhEdXVuUkVRdlg1cHV5VmM2NFNHZGlzdTJ3NTJQQnc2dUtGaVlqSXQyckd6R0ZpeTVzblgzQ2JoM0cxNzJJbm5jSnQ4WGpjcHozbXpFOFg0cmo5WjE1YS8zaTd1VTlWWlduZmhtbHVQRjVxblc5WE5oR3pPbUlETmlTbkNsUm9RMTdVaXhQVzFxWHZDcnV2U2FUVWdOQjRQblZZRHN1N3llWkpHZG9mUThCNEFSMUdrNUp6ZEFJNmNxdSszcWhZWWxVdWFIQy9janFKMTNvZXAyWGJpa2tRc25zKzZNelZHRjNicm5xbzdVT21lVlBlcDNMT0hoT3RPaWlMTHhlWmNPd1pyUWpZblRNQnVrV25DUlhiZEpJdUxlQk5FOTgyV2k0Mkd6NzNmRkpkZ3NrdW4vcjlqb1dOOXhmT2h4ZXNjb2VHUVh1NWFQSC9id0EwWFJVMmVYOVdHUXE1UGlkSDRmUDNKdVRvUFhDUk1yQ3hDSnRkajM3VTNKbWF4L090NDZ5YmxmWnV1TjZjK0oxcGtqdmE4YW1CQ2RzdVlnTjBrc3dxWFduUkR2QkhGSzdseENNdTJpN0VKSldaMUl6S3hKK3daVHJWdDVWK1JScVJwZlpFYkRoR3Y4NVRpSlc2eGc3ai9oZzhXV0tkaS9RcVNZakx4bXEzUDUzbEtFVHRQRmpGOS9VMTBZdy9sbXBzdzNWRGZ0VmVjTDNWL3luMTdHTVZMTWwvbC9UZmkrb2orT2RZRUU3S2J4QVRzSnBnUTdPMElWK3o1YXVIYTlHSFpJcmpBemprNDUrRzhpKzRjVjdwenBNYzNUY1FjOFExM0FMdW5lUUxtZ0FjdWw3dHFFZE9OaURTMjJ3UXI0UWE1elV3eEhZSjRTZnhMTERCSjdGakpoa0VTT0ZRaWg0NGxicEk3QkNKaTV3bm5XR0ppY3UyMU1oTFRmWEI3WEphZGUxQTBldE02VHZvOGFiZjFPUWNIMGZLNkVhK3o1S0oxY09qRElzOGZ1Y21UaFNMcjZPNWR5V3YxWmpBQk93SFRFalNrOXhVRlMrSmQwb1BkZE5sbnJoTVF6dnZRODcyZzF0S0k3QkFha3JvbjNPdktlU1R3UExMdllsazVCdTdlM2QyTVBhQWFFT250eHRkcjhkb25XbDlVOFM5b0ZxNWRGZEoxNnFvNEdQbmNhUkc3RUR0U2ZWWlkwL3IvWVVLbmFabXZPVTg0b0FmMHY2VHYycE56ZEM3ZW13YytYbWZ4dXRJaGdnMFBCeTZzZFljcUNablBDVWJKeGEyL3BsbGpzMk1DTmlPVHJDN2ZjQlVxOFpKNFZvcDN4ZUQ1amk4Ymprc09Mdmx1UEtJbFlMMDk0ZHVBUjV6R0NUZzlYRU5jeE8yVkdnWENlVGhXcnBvMXRYK2Y0RDY4RVpkajMrK3VXVVcwRlNiWGo4Ulh4YkxkSmxnV09xbGptenpZdVRVbVVUN2NQWFF4eHpFMzFBVXh5Zkx2Q0JqeE9vdENKTy9YTWRvOUIvcyt2TzdBNSt2eTBHWFB3UnE1STlaSzlEQnJiRVpNd0diQWQ0V2l1Tmlsb1ZXaXBRTytXeWpoOHZsbWtCc2l1VytpZUYybUZESHR5cG5ZRTNiTDNRR2VoY0lDVStKVjNPREtpdGdpVzE3SitpSm5nNjF5N0t2QTBSbURxQnRvYWFSMVBMYXd3UHowYk5oQjRjcU8welRMdjNaZCsvaEdmUjF1RVl6UWJROTd3SDVEeUE1ZGRDdVNMVEtkNk5HMHhrekUrakVCbThDc1ZwZUx3aUtpNVVyaDJtNElsNGlYRnJBTEJPR1NSUWZVeFFxVG52QVlNOEphUFdGUGRoUHExNGtGSVhHSkZQY2l4K2xiYzF1dExMNjZmdW1PclN2RzE2bnRtV0pnSXlCZGQ4cnlGMkdYNjByWDJKUnJNSWsvNFZyY0pRallYaVZrNGlVNGlLN0ZsT2dSM1pIaWRlaFlZK1pTN01jRXJJY0o0dFZuZFVtTVMxeUVyUjZ0aUZZdFlPZklncVhYT3EyNTdnbkxaS1NERnpMVkc5WU5veFl3VFozWUliMWluZTNWREpDdk1MWG5vSGFWMWRiWXBubzhNUXR4SkZZL3hGZ1dRVEMwNVY4blhrRDNHcFQ3ZTVjc1lHazdDdGtlV2NqMlhlandIaEtzTWpmRkdqT1hZZzhtWUEybXVReDlOWjZMT0thTDNIdXRCZXNreTNsS29aUGU4Q3lEbXNlQ0hOZGFZNzkyOFd4aDRqVXJzNGlZVGpyYXFQYVAwZXJYMUowbk9RZjZldEtXbDQ0ZjdoTHUxOTBabGxTeXl3VnJiSjBvWkxIZE9WSW4yRnlLVXpBQnErZ1JyMVQzek1XcUVPVEJ5SnZhUmVoaW1pMmxlekJ0dTVESmxLd3dsNU01dEdESk9zVy9YTGErbWlJMmdwNndvSTlqcmRvdmx1OFI0VGVvaFV2M2t1MG1iMU0zMUxXUVNSYnRwS0srbzdqV0dwWS81R3RPWXFoUXhzcTA5U1gxSk9XZTN5VWtjZXo2c0gwOUxyb2p1dVZ5TnZJZUtpemdzbHZSeFd0Y1hJcmFkV2tpcGpBQlV6VEVLeFhwVkRlMUpHalU5ZmhTbXEwTG1WdzZ0cFhHZVBuU3VwTDNiVk1LbG80L2lIaEpqM2cwRFloR05TYnhZYUpvT0ZVQ1IwdTRXdUpsTjNxZ2Rvbkx1aU5rdml0c2RmeE0zank2NnhBVkkweUtrZmZYMXY4V29mTzZUeENqY3dTWDRTNndxenFyMThsaVZ4UXBjUG0rM3BmejduSTg3RWlwcTF6bkptSUtFN0NJNzk3VXFjRjBGTk4zZE9yeEVTMnNLRkl5anV1Q1drVFFDdkdpSzFoNjRMS3VsVGh4RVBOWUdwSUpJZ2I1dUNWVzBlc3V0QnQ3TWhOYzVGck0raFo1dzlpdXVhYmxyOFNyRmpDZCtDSmVFeTFrWW9YcGUxM0VTMXRoblVvN1BpUjdwSG5HNHBjN0pzZUZ3VVFNTUFFRCtzVUxWWFVhbFYzb0tjYUZuSTlXbDRpVlpCQVdBa1pYdkNhS0Z0MzR3NmpGUytnUk1ibVB0Vml0MFdOMVZXNGZvNlMrWGxyWGZ0OWoyUmpyTlRmSmZhMEZyRTZ6UHlTSWpyUUxlNVRKVzdXWFpac2NmdEJXbUlRcHBQT3NCVlJpdlpxVkY3R1ZGN0FlOFVySkdzcDlKOFYyNVlJOFQxbEZRNmZBYXhGckpXWG9zVjJ0ZVppbXhSOUcxWURVVExERWxFZkgzSVZ6b00rdDJGckxnMUZmZTB4d1g5TVZzQ1BDL1h1RFVzajA0UEJpY2JFZDhlcmU5NVVWNWhzZFZhV3VJbUlXRTJQRkJhd3ZZUU1sWHVRNGxGVFBrSVFNYlhGZG9pMWdFZ2RyRFE2ZFJiaTBTMGUrMzJoN3docVhiOXcrbDZJOG5uYmpydVNOM1dEYXRkSjNmdVhCYUs4MW1OcHAwZ0ltcnJ4MTR2eGY1UHU0ZGl0Mnh0WDVmcTlMY2Y5cksweDlQeTFpOGwxV1dzUldWc0Q2RWphb3hNdm5RSzI0REZ2Q2RVbHRYM1E1RGxiWE5Ld3ZYSmtRYjVxMU5YbzNUaDh6Q3Rta0czY2x6dE10MG51T1Z1VTZnNGtpQnRsbDNSRXlGOHBLYVl2c2tPN2djT2tJNjNuL2RFcDlrZm5wR3hZWUtpdlNLZkdhNjBrWUdDc3JZQlVwNXRVU0wzTEZlRjB0UTBUck1wVUY1cnVXVjEwT0tsMndmckpvcmF4dzFkVEg3Y3NiZHlYUHlXbXdxdGVYVUhXWVd1NXJXVVRJdkE5aXN1NUMxbUJud2xxMUZKUFdxbVhkbHhhWWcxUjh1ZlVkdmZweU1sWnNKYTJ3bFJTd1J0eExqOE5JSmFIb2lwY0kxV1hnc2d2RmQyc0JhNGxYUGROeUxWeDlKWG82YnB3RDRCM0F1NEgzQUcrSmo5OUpUb0Zha1N0NHBSdGE0K1paSTd0VDdnRzhGM0F2d2sxOGU5eTNQbnNjTm9tWnp4YVpGcVErTVNzRVRIbGlVdWZWcTMvbXN2VkZ0UjlXV01SV1RzQW1pSmNXTHFsaHVCUEZLMWxkRGk1SDBaSjFxaUx2eW5UNWxHMkVjaG42c3BjMWszQzlEdHdmQXk4Ry9oWjRGZkI2NE01NW54ekRXR0hlRzNnLzRQN0FRNEJIZ1B2SHdCMzlia1hacC9Wa1RYVk8xeHVMRnF3a1hMNGJRZ0NLakZwUEhseXQ2M3pXbHVKS2lkaEtDVmhQeG1HS2UwR2FjREpOVzYvY2hpSmV0eEdFNnphaUd6RUtuTVM5K3BJMUpxYkRxelg3d0t2QlBSOTRMdkEzQkF2cmNQNm54RENNeU52aThxZng4UTVoY3RoSGdIczg4RmpnZnVEWHludTJOb2hrTFIzVWVwRk1ReG1pMDJvVE5KNnVZTWtFcmJKQVdZVm1aVmdwQWF0SUY1Z3I2eHFtbVpKUk1TOGxYcmNSM0lkaWdkV1Y0NmZOcE55YlZmZ2U0SG5nZmdsNFBuRDE5STdkTUl3cDdBRnZpTXZ6Q0JiYUo0SDdET0NUd1crSGw5V0MweGZMYm9sWjBTYkVtRmRUd0lnVFlNWjRtL2ZLR25QNWRmTGVsYkhDVmtiQWVxeXYxbGd2UFVPdENGaHlHOGJsTnArVE9QUllMejFJVVQ1ejZsaXV0NEQ3YWVCSENTN0NlclNpWVJobno5dUFad0UvRHp3TTNKT0FUd1h1VVZwZElocWRNV1JSb0hwajMxRjBKSUhFVTFYRDk5M3lhVEtyc3hheWxZcUhyWVNBdGNSTEoyMVExamFyeFVzeURTOER0MFhMUzZmTnQySmVrOG8veWZmZ1BlQ2VDZndROFBMVE9uakRNT2JLSHNITitFWEF3NEVuZy9zOFlMTzBnbXAzb21RVTlsbG9RQ0ZlM3BXaWRVd3VYbjFFbnRHNW5vWEI1WThhUHlzaFlCWEpuUGNOMXlGcW9MSUxLZkdTcEhHWmJ0WmhQYzZyVmR1c2M2RWVBNzhEN2luQS8xN01NUnVHY1FxOEJQZ1M0T2VBYndIM2o3cEpGVERqMkU2RnB5MWVSeTRJbDU2RklWbGgxZUpZQVN0czlBTFc1enBFWlI2Nm5ESy9ReTRQZGRIbkpBMFJMUkV1N1Rhc3hhdmxOcFQvejZ2QWZTZndUQ3dwd3pER3dCSHdHOEFMZ0M4RDl4OUltWXUxTllaNjNOclc4UzRSTUttQmVBTzQ0ZU1Fcmk1c0owdk1aVGZqU3JrU1J5OWdrVW11d3pSZzJjWHBVQ2pkaDVkUXFmTDBpNWRPMk9qNHR3RitIZHpYQUM5YndBRWJockZZcmdML0RmZ2o0S25nUHFKcmpla0N3YnJ0cmEwbmJYMGw4WEpad0dvaHErTmpPaU55MUl4YXdCb1pQVExYemhyZFdWVjFuVU5kMC9BU3dScXJ4YXN1RGRVNzJlUXU4RjNndnAwd01aQmhHT1BsaGNEamdHOEg5MFhnMThOdWFZdjYwdVdobTd5UnhJc2dWSWVVU3hJeXNudXhHUThicXhVMmFnR0xGTllYY2ZBZ0t2YmwxR1NVdEdzZFhuQjVrSEpkVVg1U3pJdDNnUHNxNENjWGRiU0dZWnc1N3dDK0FuaHA3TGllYTF0am50d0dGeFlZWmR5ckpWNkhCS3ZzVUlzWVpaYmk2SzJ3MFFwWVpYMFY0ekI4WlgzNUtubUQ3cFFvOVNEbE91YlZGSy9YZ2Z0QzRQZE84VGdOdzFoT0RvQ25FZEx2bndidWpuNlg0am85NGtWYnZBN2ljdWpET2xscExvdVlMajRNSTdYQ1JpdGdFVzE5eVZpTW9tUVUzWEZmcllrcFd4WGwrNFRMQWJ3YzNCZGpXWWFHc2VyOERIQVg4Q1BnN2xtS2lvNko0WExGalpZTFVRdlhQbkRnNE1DSDlhRlhsbGlWMENIQ09FcldwcjlrZURTc3IwN3FQR3FPTDdMMXBXZFcxdE9oRkFrYnJqRi9qL28vdkFyY1oySGlaUmhHNEZlQkp4SkNDbkZYMFM3UjlRenBZVDNuQ0dHTVlwWjM4UXI1MkxGMjVSalVOS2VZV2tiSEtBVXMwclMreUduenFlcUdVKzVEWDEwa2RCTTJKZzVTZmhPNGYwbW9YMmdZaGlIOE52RGx3TlVKUTN2b2l0ZzJXY1IwSjd2VnVaNFVrd2VhaVcyRFpuUXV4RmJtSVkyQnl5NExtQ1J2MUl1K01QVEYwUnZ6ZWhlNEx3SCs0SFFQMFRDTWdmTHpoQ2xiL2p1aGdZbElHd1U1c2VPWTBPYUlHMUhpWGZzK3VCQjNDVVZCWk5uM3NPL0NzS0FiUG1ZbDBvaUZuZW9CTHBqUlcyQzE5VVVlK3lYdXc4S0ZHSmR6cmpGSTJaWGlWVXg3Y0FSOEkyRkFvMkVZUmgvUEFMNnZiWVU1eW1sWDZqaTl0Rk82dlNvNjJyNmN1cWxaNVg1TVZ0aFlCVXhmSE5yNldpZGFYNVFYaFRiUnp4R3NNbTE1RmI1bEd0YlhqNEQ3d2NVY20yRVlBK1lZK0daQ1lZTzRxeGF4b3RBQ1pYc2xDV2ZuWGRsMlNWdTFSWnp4UFNhc1NTZCtsTEd3VVFsWUszbkRoVVhHZnhXVk42aDZOYTcwS2V0cFVTYU85ZnB6Y04rNGdPTXpER01jN0FKZkRieStQNmtqalZkRlRiSkxicHVrOElKdXIxSlZJTitlYTJ4MGpFckFJcTNBNkJyaEI5MmthNEVsTjZJdkx3UXRYcTI0RndCM2duc3lZY0pKd3pDTVdYazU4SFdFd0Zha2xUSGRLWGxIN25qcjlxdXd3TWd6UDhzMExxTjBJNDVSd0FUblZmVU5WSGFQdUFkZDE0VzQ0N29sb2lhTzkzb0dvZmFaWVJqR1NmbDU0TGtUc2hKcks0d2MydERpdGVONnhxbU9QYVYrTkFKV3V3KzljaC82aGpsT0NIaDJMZ1RmdUFqb0NZYStBdHhURjNCc2htR01reHZBVXdpZUhMVTdpVmhsaGVuYXJiVTdjZHVWaGNVM0NMR3dOUitXVVFtWE1Cb0JpNlFlaHNzWGdMZ1AwL2d2bENtdS9NcmFCSjg2cjljQjhDMkVtbWVHWVJnM3k4dUE3ODRQT3drZFRpV2cwV2pEeUJtSXV2M2FqRWtjbzNZamprM0FoT1ErMUFrY2NmeVhqb0ZKSGNSYXZLYTZEbjhYM0M4di9MQU13eGdqUDBJby9LdDI2VmhZSFFiUjdrUnRrU1h2VVd6dk50VDdhemZpS0JpamdEWGRoMTRGUW4zNWcrdUxvR1Y5eVlXVWZ2Z2JoQjdUN21LUHl6Q01rZklXNE9uNVlTc3pzVFUrckNOZXNYTys2VlViRnR0QlY0ZFpUdk40RnNVb0JNeDNmM0RJb2lNaVZ2ZGVpc1YxTGEvZTJOY0x3UDMyYVIrVVlSZ3J4YzhBcnk3Yk1sbW5UR3JLZHF6VGx2a3FCa1pNcDNkbWdTMDlUbTNVR1lpNkFyMHMydnFTSDM1U3FTaEgrRXllVHFpOFlSaUdNUy91Qkg2ODNOVWFFdFFVTVpjNzRzVWt1eTVhWU9RMmNUVGlCZU1TTU1naUk0T1hKUWJXc3I1MEQyYWE5Wlg0YTNCL3VKaGpNUXhqeFhnZThOWkd4NWwrVjZJTVhDN1dLT3RMRnBlVDI1SVZOblJCRzV1QTRjc2ZLYVdoVG5BaGRreHUydVdpSE1DdkFXOWU1QUVaaHJFeXZJVG11Rkp0Z1UxeUphYTJUQTBia25GZ2F3MnhHclI0d1FnRXJDLytwY3FvU0JKSFNrTjE1WHFER2NWckQ5eHpGM05ZaG1Hc0tMOVVQdXkxd3FwT3VWNXZ0Skk0b0ZNWGNmQU1Yc0FpbmZnWERiK3h5ejl1MDl3bUMxN3pSMzRGOE1jTE9CakRNRmFYM3dUZTJXMS9PbFpZSXptdEVESEtEcmwySVk2R3NRaVlrTVRMcWQ2S0wzc2xyUis2aUgzMVRVUHdtNFJLMG9aaEdLZkZuWUNLcytzMnFOTXhWNVU2dE10UXQyZTZsRlFyblg3UWpFbkFYUHpqWE01QTFCYVk5aHUzaEt0WnJGYysyNFA3WDRzNENzTXdWcG9qNEhlNnUzWEh2UFl1MVcxYjBhYjV0bkNOd28wNEpnRnJ4Y1BFSmFpbko5QS9kaTFldmZHdk53Q3ZYdGlSR0lheHl2dzFjRFUvVEVManUrS2xSU3d0VGlWdnFOZExnWWRDdUlac2tZMUZ3T29mT1AzSXJxekdvWDNHUlphT2VuMHovdlV5NEkwTE9SVERNRmFkdndkZVcrNmFKYlUrZGRMRkErVXJyOUxZTWhISEltQ2dYSWc2MDBiOWtPdmtXWlcxMVZWa0h2WlZiZjU3NFBwQ0RzTXdqRlhuVGNBYmU4SVphcWt0ckxVcWRGSjB5bDIvaUEyV1FRdFkvVU1vMDdpMnd0YlZEMTJiMjMxdVE5MXI0UlduZlRDR1lSaVJJK0NWM2QxMSsrYVVoZFVSTHYwYU42RnpQbVFHTFdDUmpqKzNjZ05LQ1pVKzRXckZ2Z29Pd2IzbU5JL0FNQXlqNHUveVpwMkpxUGRKMWFGYXhKeGF0eGlGbUkxQndCS05MSnZXRHpwSnVPcUxCTUR0RVpJNERNTXdGc1hmOXovVjZhRFgreWE4WmxTTVJjQUt3V2xZWVMzQldxdWVieVp2QUJ3QWJ6M05iMjhZaGxIUlNCcnJpNGVsN1VZU1d0R210YklRaDh4WUJBeTYxcGVzK3pKM3RPbmQ5M2tPNEpBd3VOQXdER05SdkwyOXU5VmVUYkxHcHIxMzBJeEp3QW9hWThJbW1kVzkxaGNFQWJNTVJNTXdGc2w3ZXZhN0NXMVZIMk95dWpTakVyQ0dlWHhpRTd2eG1JUFQrYnFHWVJpOTdFOS9TVy9uM0hYYnUxRXlLZ0ZUOVBtS0o1cllmYjJVdzlQNGhvWmhHQk93anZOMHhpcGdOMk15OTc3ZTMrSjNNUXpET0NuVzdreG50QUlXYVpuU2ZZdGhHSVl4SU1ZdVlJWmhHTVpJTVFFekRNTXdCb2tKbUdFWWhqRklUTUFNd3pDTVFXSUNaaGlHWVF3U0V6RERNQXhqa0ppQUdZWmhHSVBFQk13d0RNTVlKQ1pnaG1FWXhpQXhBVE1Nd3pBR2lRbVlZUmlHTVVoTXdBekRNSXhCWWdKbUdJWmhEQklUTU1Nd0RHT1FtSUFaaG1FWWc4UUV6REFNd3hna0ptQ0dZUmpHSURFQk13ekRNQWFKQ1poaEdJWXhTRXpBRE1Nd2pFRmlBbVlZaG1FTUVoTXd3ekFNWTVDWWdCbUdZUmlEeEFUTU1BekRHQ1FtWUlaaEdNWWcyVGpyTDJBWVkyUXRMaTQrOXNCeFhBekRtQThtWUlaeGkrd0FEd0xlRDdndjhFRGdYc0JGNEFKQnZLNEJkd0Z2QkY0SnZCNTROZkIzd05IaXY3SmhqQUlUTU1PNENUYUFSd0tmQWZ4RGdtaTk3d25lNzhrQzlpZkFzNEdYWVdKbUdDZkJCTXd3VHNDOWdjY0RYd2c4RE5pdW52ZEJtNmJpd04wZnVEL3dTY0JYQTM4TS9CandHOEE3NXZSOURXUE1tSUFaeGd4Y0JyNE0rQnpnRVhHZkJ6K0RXbmx5S0V6dkxONTZIdHpIQWg4TC9HL2dHY0N6Z01OYitkS0dNWElzQzlFd0pyQU9mQnJ3TzhCM0VNUXJDcGNXSUY4dHgycHBQZGFMZklDWDVWSEFqd0MvQlR6MlZJL09NSWFOQ1poaDlIQTc4RlJDZk9yRDZRaFhMVVJhcUdyUjZsczhwYWpKQjN2QWZ6VHd5OEEzQWVkTzhUZ05ZNmlZZ0JsR2c0Y0R2d0o4SmJBNVdiaHFVVHFhY2VrVHNVTEliZ1AvTGNEUEVESWNEY1BJV0F6TU1DbytDbmdtSWNHaXgxV290L3NFcUJBamNoek16YkFVNy9IZ1B3M2NmWUVuQWkrOTFRTTBqSkZnRnBoaEtENEYrRVU2NHRXeXVzU1N1aUdMQ3prWGg4QkJZOW12SHN0cmI5QzF5cHB1eFVmRTd5WkpKSWF4NnBnRlpoaVJ4eEN5Lys0b3N3c254YnFPSFJ6NXVPMnpDTFVTTmJTRnRhYVc5ZXF4WGpUT2cvOUFjRDlOU09WLytSeVAzVENHaUFtWVlRQVBKYVN0MzRmQzc5ZG5lWWx3SGZuU0VrdlAwN1dpdEhpdHEvVkdYT3RGM3JlbTN1T0pJdlpnY0Q4QlBBNTQyOXpQaEdFTUJ4TXdZK1c1Qi9BOXdQM29kUnQyRWpTOGNoMlNYWUdGTzlDcDVBOFh4RWRiWFNKZW0zR3RGM21lK1BwalZBek5nMzhrdU84RS9nMndOK2Z6WVJoRHdRVE1XSG0rbmpDQWVKcDRPYmpoczJEcHBZaHB4ZGNkKzJ5RjRVdnJTNFJxRTlpcTFzZHhyYitMaUpsRFdXS2ZEKzVQZ2UrZit4a3hqR0ZnQW1hc05COEgvTHV3T1VtOGJrU1hvUmFzZldEZndZRXZFelFPNCt1T1hCQXgrVnl4dnBKNE9kanlvUnJWTmtFWXQ4bWl0eG5mdDY3V3g2alkyRHI0YndiM2ZFSk5SY05ZTlV6QWpKWGxNdkRObE9aT3BJaDVLZkZLd2tYdzNPMzZzSlpGWnhqZTBCWVl3WG9TNjJ0TGlkZE9YSFJHNHFUNG1kN0hIY0EzQWwrTUZRSTJWZzhUTUdObCtUekNtSzhKcmtOeEc0cDQ3UUY3TGdqWExuQTlMcnR4RVhFN0lDZDFTUHhLQkd5VEtGNE9kbndvc25HT2FMVlJpbDRmWW9VNUQvNEo0SDRLZVA0dG5RM0RHQjRtWU1aS2NnbjQwbkpYYzV5WGlubUoxWFhkQjlHNjV1Q3FEMU45aVpEdGtRWHNrSElPUyswKzNBYTJvM2lkSnd0ZW40QkpOcUlzSGpYZytSendyNEhmVnYvTU1GWUJFekJqSlhrY3VUQ3YybDJYaGpwQ2lWZTB2SzREVndqaWRRVzRTaEN4YTJRclRBVHNpRElHSmhhWXVBN1B4ZGVMKzdCMk9lb3hZNDVTeU5MclBQakhnZnNJNEVWek9EZUdNUlJNd0l5VjVJbmx3ODU0cjBiU3hsNFVyNnR4dVNzdVdzUjJ5Ykd3V1FUc1BHWHNTLzUvUGRoWkw4MVkyQ2J3K1ppQUdhdUZDWml4Y253WXVicTgybDFrSHFweFhwSzRzUWRjZDNBdFdsNTNBZStKYXhHdzY0VE14SDFDN0d5YWdJbnJVS3d2eUxFeVBWWk1qdzNUNDhJS2QrTEhFR2FGZnNPdG55TERHQVFtWU1iSzhWaEM5bDVVRnAzdFY5YzUxTWtidTRUNDExV3lnR2tyN0ZwME1lNzVNcWJWRXJBdHN1dFE0bDc2TlhxY1dEM1FXYWZUSi9IeTRCOEU3aDlpQW1hc0RpWmd4a3F4QmZ6ajlsTjF4UTFKM2hBTFRMSU9yNUhkaUZka2NkMFltS1RmRndMbVlNT0hyMUVJWEt6VW9hdHpiRlhMSVZuRW1yVVdOK094UGZjV3pvOWhEQWtUTUdPbHVCdndFZlM2RDczTFJYbTFnQ1VMakRJRDhTcHdOYm9WcnhFU1BmWjlZeHlZZ3pXZk14RjF4aUZrOFJMaGtoVDduZmg1MjNHL1dJWlNMN0hEWStLSEhON3ltVEtNNWNjRXpGZ3A3azJZR0xKeUg2YkZxK29iNUJoWWJZVkpLbjNhZGpHQnc2c0VEbGRtRmE0UlJFenFKQjc3dkYrTDF3N1JGUm5GS3cyTXBueXYvdDRwcGY3aGhBSGE3NXpmS1RPTXBjVUV6RmdwSHRqL1ZPMUNsQmhZc3dJSHNPdUNZTzBSMXZ2QWdZdnhMeCtuV1hHVmdJbjRWT0lsWThOMFZZOTlYNmJZcHlMQnZ1cytsQVB3TzNIaVN4TXdZeFd3Q1MyTmxlSUQyN3M3YWZTVTA2Um9LMHhpWFBzKzFrS2tPMEZsc1loTFVvb0J5OFNYTGd1ZS91eWlycUw2bkw1cFd0RGJHOENEYnZyc0dNYXdNQXZNV0NudTFkMlZNaEJkNlVMVXlSeDFCZm9rV0Q0SVVVdXdqc1dGR1AxN3pzZHRIMXgrTjJMY3ExWGR2aFpDUFdOengrMkpjaUc2OWpFYXhpZ3hBVE5XaWt1enZheXV5RkZZWkM2WG1aSk13eVBLNnZNaVhrVmxKOWQ5VGhKRytwWmtjYW01eFRxdVEvV2RIY0RGR2MrRllRd2RFekJqcGVocDNIMzgwM0xORll1MjBuUXloUWlNNjRwTThYblY2NC9WNTJuM1pSSlErVnpmRmExbUZ1S0VZelNNMFdFeE1NTlFMcmdUdkg2Vzl6UkZ4MDBRSDhNd1pzY0V6RmdwZGljODUwcGhhdFlqOUkzdE9NYkx1VndWUTFlT0wvNUZITENjbnZmZElyMjYzdUdhdk5ZMVB1dG1qdEV3eG9RSm1MRlNURWd2MThKU0M5YzZzT0hLa2s2cHRKTVBGVGFrVHVHYUt3V3NXRVN3ZlA3Y291Nmg2OVkrWEtjVXpqN3JMKzJ6RkhwalZUQUJNMWFLTjNWM3VXcGJDMWhSbDlESHdjWXVERGplVk11R1Y2TGpzNWk1eG1ldU9TVmVycXg1dU9saDA1WDFEM1VSMzlwYTY0aVpieCtqWVl3U1MrSXdWb3EvYmU5dUNVMnJMcUZNUkNuVjVMY0o0N2EyVU9uemxCVTRkS0hlTllMQWJSQ3NyU1NLNUhKUld6Ny9QeEUyYlkyMWhDdHRId0d2T3ZGWk1ZeGhZZ0ptckJRdkl6VHkwZldncHlQUkFsWlhoQmVCa1Vrb3p4RkNUZWRRQTQ2ZHFyN2g4K2VMdUdoWDVLWVB5elo1MmFtV2JSZkVURmVrcitjRks2d3ZCKzVkd0t2bmNhSU1Zd0NZZ0JrcnhkdUF2Nk9veUtGRlRGdGY2d1IzM3Bidml0ZDV5b2tyYnhERmk1enk3bHplSjhWODY0SzkyejUvcG56dU9VSVIzeDJmclRMdFVwem9Rdnh6TEluRFdCMU13SXlWNGozQUM0RUh4OG9ZY1hmTGhTaHhMN0crenRFdTlWUVUycVg4VEpsOEVrTHNhME5aWGpzaVhnNHVlTGhBWHM3SDU4Uk5LUUpXeDhNNi9FSDhNb2F4Q2xnU2g3RlNIQUYvUkRFUVM2Zk5PNExRMVBFdmNldWRKNHFNQytPRkx3SVhYUlFkbE9oRTYyckx4Y1dYbHR3T2NENis3eUxsT29sWWZKM0V3MFRBYWhkaXNzS3VFc1RaTUZZRnM4Q01sZU4zZ2RjUnBsV0o2RGlWOThxRlNKNTg4aHlxYnFGdjFENUVXVjh4N2YxUXVSRFhZenhMckRteHVpNzZVT0hxSW5sZGlDRmxNa2N0WG5JQTdxK0FsOHpsREJuR01EQUJNMWFPVnhOY2JVOHMzWWhRdWhFM0NPSWpFMG5XVmVaYk5RdDFBb2Q4eGhHQXo4a2JPMlNMNjFLMVhIUkIwQzR3bXd1eEVMRmZBOTQ5bHpOa0dNUEFCTXhZU1o0T2ZBNUJHU2pqU1dzRVVSTTNvaTdrTzYzd2JqM1AxMkY4RGtMOGE4dkJ1U2hRbHdoelQxNTJjTm1IN1V1KzY0NlVKSTZXZUNYZUR2eVBXenduaGpFMFRNQ01sZVJQZ2VjRG41cXRzTHFFbEJheExkclY2Zlc2dHI3V0NmTjlIY1hxRy9JNTU0aldsd2lYaUJjcW5oYVRPT29zeEdic3k0SDdTZUQxOHo5TmhySFVtSUFaSzhraDhGVGdvK2xVYjY4RlRGZUo3eXdxVmY3WWwvTjlyUU1ITVQ0bUFyYnRnM1Yxa1dCdFhVYUpGeUV1SnRhWGlKZE9uOWNKSEluWEVpeEt3MWcxVE1DTWxlVVBnV2NELzdKcmhZSEswSFhkdWJpU0ZlWkxRZE1XMkNZaDVWN1M2Q1dCNDN5TWMybnhTZ0pHemo2c2t6ZWFzUzhIN3VuMFZoZ3hqRkZqQW1hc0xFZkFOd01mQzl5L0sySWlZRDZXZm1vSldHMkZTVUtJRElMZTl3MEI4OTBFanBaNGJjV2tENTA2WDhTL0hMZ1hBTjh6MTdOaUdNUEJCTXhZYWQ0QWZBUHdZd1MvblVKbkpFSlh3SktRS2ZFU0FWd25pTThCcFF0eEp5WnhhQUZyaWhkVmdXRDFmUkp2QmI0V3VENlBFMkVZQThRRXpGaDVuZzA4RFBoUHBSV215MHRCR1EvYml1c2psd1hzdUhyUEprSEFDZ3ZNNXlRT1dlb3hYenBwbzVWMTZBQ093UDBuNEVWelBoZUdNU1JNd0l5Vnh3UGZCandRK096K2VGaWQxT0VweGV0WXZYNmRJRVFpWUNtSmcxenpVS3l1T21takZxOW0zT3Vwd0kvTzhSd1l4aEF4QVRNTVFtWGVMeU9veCtOblQrclFscGNlRUMxbHFBNHBCVXpTNkVYRUpvbFhiOUxHOXdIL2VYNkhiaGlEeFFUTU1DSjNBbDlLVUlwUGI0OFBjK1NxOG5VeWg0OHZjajRMMkExS0Fkc2sxMElVSVp2bU5pekU2d2VBcnlFb28yR3NPbGJNMXpBVTd3RCtCZkJENFdGSHZDaW5XeEdyS2syMzRyTjdzRk1taWpKaG94QXYxN1c4aXRqWEFiaHZCcjZLa0p0dkdJWlpZSWJSNFM2Q08vRVZoTVNPMjl1Vk91cDRHT3I1RGZJMEt5a3pVYVpUSVF0WEsrT3c0elo4STdpdkEzN3F0QTdZTUFhS0NaaGhOUERBZHhGS1RuMEg4QkhnMXNOVDJtdmhWZmtvSWMwbFJraWhUNW1KUGxmVkVKZGhQVkZsWVhVZEFzOEg5dzNBLzVuN0VSckc4REVYb21GTTRBWEFKNEg3c1hLM2lNeDZyREl2Z3JWTk9YdXpUdFNRVkhrOXgxZHYwc1lOY044QlBCNFRMOFBvd3dUTU1LWndEZml6YmxKRnFvNVJpWmlPaWVtRURkbXVheHcya3pZT2dCY0VJVE1Nb3dkeklSckdES2diUmFmV1M5VU5vbnRRaEUxUGNDa3V4RG9KUksrYlJYbzNUK0U0REdOTW1JQVp4c25SOVJLUEtVczlIUU5yVlFGZy9mcGFzSnFWTmx3bFpvWmhkREVCTTR3WmNUUm5jSllxSGZKWUVqWmEyWW5hRXV1TTg4TEV5ekJPaEFtWVlad0FKV0s2WGlKa0laUDl2djMyNWlMUG1YZ1p4Z2t3QVRPTUUxS0pXUFZVUjd6cTEzVkVxL0U1aG1ITWdBbVlZZHdFbFR1eEpXVFFIUUJkUCsvVURoTXh3emdoSm1DR2NaTk1FYkcrZlozOUpsNkdjWE9ZZ0JuR0xTRGlNMFhJcHI3Zk1JeVRZd0ptR0hPZ0lXUlRYMnNZeHExaEFtWVljOFRFeVRBV2g1V1NNZ3pETUFhSkNaaGhHSVl4U0V6QURNTXdqRUZpQW1ZWWhtRU1FaE13d3pBTVk1Q1lnQm1HWVJpRHhBVE1NQXpER0NRbVlJWmhHTVlnTVFFekRNTXdCb2tKbUdFWWhqRklUTUFNd3pDTVFXSUNaaGlHWVF3U0V6RERNQXhqa0ppQUdZWmhHSVBFQk13d0RNTVlKQ1pnaG1FWXhpQXhBVE1Nd3pBR2lRbVlZUmlHTVVoTXdBekRNSXhCWWdKbUdJWmhEQklUTU1Nd0RHT1FtSUFaeGd3Y0xmai8rVFA0bjRZeE5FekFER01HcnJGWVFUa0VyaS93L3huR0VERUJNNHdaZUFPd3Y4RC9kdzE0MHdML24yRU1FUk13dzVpQmx3SlhGL2ovM2c2OGZvSC96ekNHaUFtWVljekFPNEMvWE9ELyt5UGdZSUgvenpDR2lBbVlZY3pJenl6by94d0RQN2VnLzJVWVE4WUV6REJtNUxlQmx5M2cvL3d1OEJjTCtEK0dNWFJNd0F4alJ0NEFmRC9CUWpvdGRvR25FcEk0RE1PWWpBbVlZWnlBSHdkKzZ4US8vNW1uL1BtR01TWk13QXpqQkZ3SHZnSjQrU2w4OXU4RDN3amNPSVhQTm93eFlnSm1HQ2ZrbGNBVGdiK2I0MmUrRVBnaTRNNDVmcVpoakIwVE1NTzRDZjRNZUR6d2UzUDRySjhIUGhONDlSdyt5ekJXQ1JNd3c3aEpYZ284QWZoL3VEbkw2ZlhBa3dpVzExdm0rTDBNWTFYWU9Pc3ZZQmhENWgzQVU0Qm5BVjhDZkR6d0VPQkN6K3Z2SktUaVB3LzRDVXk0RE9OV01BRXpqRG53U3VEcmdEdUFEd1llQU53WHVEc2g3ZjRkd09zSWNiTy9CcTZjemRjMGpGRmhBbVlZYytRZGhMalk3NTN0MXpDTWxjQmlZSVpoR01ZZ01RRXpETU13Qm9rSm1HRVloakZJVE1BTXd6Q01RV0lDWmhpR1lRd1NFekRETUF4amtKaUFHWVpoR0lQRUJNd3dETU1ZSkNaZ2htRVl4aUF4QVRNTXd6QUdpUW1ZWVJpR01VakdMbURlZzlmckNZdGhHSVl4SUVZcllQN2tvbVFpWmhpR01TREdLbUMxR0NWTHkwMnd2UHBFYi8wMHZxRmhHTVlFYktxUTZZenFIUG11S09uSExWZGkvWnJXWTdaTzVkc2FobUgwWSszT2RNWnFnZUc2QXRWWjNHUWhTMndCbTZmNmJRM0RNRW91VG45SmI5dldpUDJQa2pFSldHMUZ5WHJxajB6N0IwNzdONEc3bmNwWE5nekRhSE5Iei82YkVhV2J5QWtZQkdNUnNFSzhYRmVjanRXNlh2VHp6UXRqRTdqOU5MKzlZUmhHeFh1M2QwL3FiRStNOGZlOGQ5Q01SY0NBd20wSXBXRDFpWmQrdm5ZbnBzL1pBZDczVkwrNVlSaEd5ZjI2dS9xUzA5TDJ0QmkvejY4WkJXTVFzT0xIYUZoZjNtV2hPbExMSkNFcjJBWnZBbVlZeGlKNS8vNm4rbUw1czhiN1I4T2dCY3oxL3lDRis5Qm44ZW9Uc2I0ZkhnZ242VUduY3dpR1lSaE5QaWh2dHJ4RE9wYmY4akxwMEVpTFVRamFvQVdzd290NXJIb2J4NjRTTDFjS21CYTFZOXFaaVFBOEFCc1BaaGpHWXJnTTNLZTd1eU5lYm5wODM3dlFpUitsRlRZV0FVcy9paFl2c3ZXVkxDL2ZGYkRDbmRpWG1mZ2dlb09xaG1FWWMrWCt3UHYxSjJMVTNxVzB1SWFRU1pzbXNhOEpucXZCTVJZQkE1cGp2K3JZMXcyMXRFU3NOd0Q2WU9EZWl6Z0l3ekJXbmc4QTdsbnU2Z3R6RkdFUjZhQzdVdEJTTzlZUXIwR0wyWmdFek1jL0tZa2ovbGhhdkFvUmM2V1FUVXJtOER2Z1AzeFJSMklZeHNyaWdFZFROTTYxaDBsM3pPdTR2aGF5MmtMenFuMmsrc3hCTWlZQmd5citwZDJIcm11QkhmcTJOZFpLNmdEZ1V4WjRJSVpockNZN3dDZDBkMnMzNEVtOFM4Y3VMTDR4ekdpd3dpV01SY0JhUFlyYXZDN0VxMXJMano0eHBmNGpNVGVpWVJpbnk4TUpJWXVJYm9mcWhBM2RNWjhvWWo0bnRkVkNObWdHTDJCMTNFdGxJa3JQNDVoc1VoKzZJRnF5M0lqN2FoSFRLYWpwQXJvZC9QKzF5SU16REdQbCtBeGd2UkhHb0NGZVBvZENkR2U4MlNsdnVRK0h6dUFGckViMU1Md1BQMXBoZ2Zrc1hnZkFnU3RkaWJybjBrbm9XQU0rRmRoZTZCRVpockVxdkRmd1Q4cGRXcmdLcjVMUGJab0lXQkl4SGQvMzBmS0N6cURud1RNMkFTc1NPVlFtemhIaFJ5M0VpeUJlK29jdi9NWTBmdXlQQmo1a2dRZGtHTWJxOE5IQVEvcFQ1MXNoa2NQRzBySENsSWpWbnp0b3hpWmdFSHNaVGxYZ3FDd3NMV0w3S0RGRENabnZ4c0k4d0czZ1AzZkJCMlFZeHZqWkFKNUltZ2VzbFM0dlM2Y3RjK1U2dFdNNmxLSXp0Qm5KbUxBeENWajZZZW80R0xISDRrdnJxN1YwTERGS0M4d0RmQUZ3MzBVZGxXRVlLOEVqZ1UvcGlYdnBkb3h1Ui96QXg4NjR6NTRsY1M5S1o5eVBMWUVEUmlKZzlZOGlZeVVrQnFZeWRlUkgzNitXV3NEcUFHZ25tZU5KQ3pndXd6QldBd2Y4ZTRweWRVWHN5N2NGYkthT3VNdHQ0YWppWHpBU0FhdW9nNVdTeUNIQlRmMURGeUxtVG1DRi9kL0FCeS9xaUF6REdEV2ZESHhpbFZHdGxsYmNLN1ZmcnQwUkw4SWhQZVBBQnMvWUJDeGRBR3JjUTJHQitlckhCL2Jpc3U4YlBaaXF0bGo2MGU4Ti9xc1hkRkNHWVl5WDg4RFhBcGZDdzc3WWwvWWkxWjN2UFVvUk95UjAxb3V5VW1hQkxUSFZlTENtRzFFRk92ZGRGaTc1OFdXdFJTeVZaS0Y3WWZINTRCKzNzQ00wREdPTWZBbncwVlBHZktIRXkzVTczN29kRTAvU0RSOUVMTGtQNjJyMFk0aUhqVWJBS3BJYlVRMWtsaC8wME1lZ3B4S3hYYXFMZ0d5R2l3WFhxZEN4QVh3OWNNZUNEODR3akhId0lPREorV0hMK3Fyajk1S3drZG91cjlvdUY1NlhnZzNKQWh2alZDb3dUZ0ZyWmlNU2ZraWRpYmp2dXoyWXBvajUvZ2t3ZVJUNGIxam80Um1HTVFhMmdHOEY3dGR2ZmRWeHIyUjV1ZHp4bHM3M1Bqa01vdVA0cmZKNG94R3lVUW5ZaEd6RVZIYUZyaHR4RjloMWpZdUJhSXJUTFROVlhBaFBBdi80UlJ5Z1lSaWo0Y3VCSjdRVE4rb0J5enJ1SlZhWHRGZEZ1eVdKYUw1L1BDc3dEdmNoakV6QUtqcCtaRlV6N01DWHB2aXVoK3VVRjBRbkhrYlB2R0Zid0g4REhycXdRek1NWThqOEUrQWIrOFVyVlE5Q2lWZU1mVW43VkxkWE9oR3RDSDM0VXJ4R0lWekNXQVVzWFJEYUNrT1o0MDZKRi9saXVBNWNyNnl4SWg1R2p5dngvdUNmQnR4dFFRZG9HTVl3dVIvd05PRHU1ZTZpcysyN3JzTTlYNHFYTENsK0g5dTBOSlpWRXRER1Z2OVFNem9CYTgxNW81TTVuTExBNklwWWNXRzRNaVpXMTB6c3VCSS9EdndQQXhkUC9TZ053eGdpOXdLZUJUeDRzdXRReEtzZTd0TnBwMXdXc1gyZlMwbEpDbjFuK0ErTXgzMElJWkZ1ck9nTFJNWkJhTC95QWFIWHNnVnNSeGZpZHR5VzlSYXdTVGhQR3dUQmw4V3AveVVkQWZkWjROOEY3c3ZqUHpFTXd3QzREZmhoNE5GZDhlcE1rVUlaOXhMaHVnWmNjM0ROaCszcjBTcmJjMUhBWXBKYW4vVTFHdUVTUmlsZ0xtUWZpc0NraThUbFFwaUgwUUxiOUxsbnMxMHR0WGl0MHhVd1dmU0Y0ZjRWK0x2QWZWUDhZTU13VnB2THdOT0JUNTBnWHBUaXBhMHViWGtsOFVLNUVMMXlIN29WU040UVJpbGdpcVlWNXNxTFpKTndFV3cxbHMyNGJEaFk5MW5FUkxnMDJoM3J2aHI4N2VDK0VyaDZLb2RtR01ZUWVCK0NlRDJ1N1Rhc1hZZWRqRU9pNVVWb1NxNnA1VHJkWVQ4clkzM0IrQVZNNkx0UTFnay8vZ1packxhcTlTYXc0VXNMektIY2h1ci9GQ0wyUmVBdmcvczN3RHRQNTdnTXcxaGkzaC80Y2VDeHM4Vzh0T1cxNTRLTFVBdldWYktJU2JLWldGOEh4SWtzbGZWVnhML0dabjNCaUFWTXVSRnJLOHo1VXNSRXdIYkpnclhwZ250UnV3OWxxUzJ3aVpiWVo0Si9iM0JQQmw0ODMwTTBER09KK1dqZ2U0RVB2cm14WHRkOWpudGRCYTVRV21BcC9rVTVzN3l1SERScTZ3dEdtSVdvYVdVa2tzZFo2SXRHWi9oY0E2NzZmTkhJaFpONlBuVEhpZlZWci9jQUh3WCt1ZUMvZ0s3YUdZWXhMallKNWFHZUEvNEU0bFZuR2w1enVkM1JiZEJWbFBWRnQrQkNQZTRMR0tmMUJTTzJ3Q3JreHp0MlFVT09BS2RFYkYxWld4c3V1d3pYWGR0OTJJcUIxUlJ1eHZzQVB3YitROEg5VitDdGN6dzR3ekNXZ3djQ1R3RStyNy96N09sbVErdHNRNGw1MVozb1pJRzVQTXhISnJFc1NrZTVGYkcrWUFVRXJNcEloUERqRXQySWE0UWZmODNCbWcrUEpWbGpuVEp4WXhZQjB4ZkxXclZtTGJnUy9jZUQreS9BY3doWHJtRVl3K1k4WWFiMi93QzhmN2ZxaGM0MmxFem9QZy9RVmVDcUN3SjJsNE83UEZ4eGNDVUsyalZmSm04VWlSczB4R3VzMWhlc2dJQXA2aDZSakx0d1hva1hXYkRxdU5kSnhNdFRUSzVheHN3ZUJ2Nm5nZWRFYSt4UGIvWElETU00TXo0UitCcmdFOXBXMXpTM1lUM082eXBCck80aWloZEt2Q2lyYjZUWVZ5TjFmaVZZQ1FGckpYUzRmRUc1ZUJFNFpZV0pnSzBSckRQbnA3c08rMUprdFFBV1grc3p3RCthSUdUZkI3eUNhQjRhaHJIVWJBQWZEbndsOENraDIxaW8yNEZpbkJlVFkrL2lLcnlyV25RQ2gxaGZkZnk5NlRvY3MvVUZLeUpnRFZKTUxKcmVqdXlQZHJWZ1RSQ3Yya1dnMXo0S3A0aVlwekdHN0o3Z3Znejh2d0IrSHR4emdOOGpYTEdHWVN3WGw0Q1BBejRmK0hUd3FnSHRTOVpvVmRqb3RieUE5OGppc2dWV2lKZkxaYU51VUphTldpbnhnaFVTc0lZVkJqR3RQbDVjOGtRU3EwcklvQlN3MW9WYUNGazA2VGZvRjdIMGVlZkIvUXZ3bnd2OE9iaGZBWDRSZUIyaHUyVVl4dGx3SG5ndzhBVGdZNEVQQmIrVm4rN3p2QlN6S2Z1dTViVkhWN3p1SW9oWDRUNGt4TVN1a3lldkxLWk1jU3ZvT2hTYzk4TTladWRPbnBUdVN6RnlSTGVoeTVtSU1vaDVCemdIbkhkdzBZY2F2WmNJVldGdWkrdkxEaTdINXk0Q0Z3algrdzY1SkpWVThraVpqZkovS1lXc0k1Szd3SXZCL1Nid0Y4QXJnZGRpZ21ZWXA4bEZ3Z0RrRHdBZVJZaHhmUkQ0emZKbDA0VHJXRmxkblFrcFVlSWxDUnRVQWtZVXNQajhkUmNFTEZYZGlJT1dhd0c3S2V0cnFEcXdNaGFZMExERWp0VUQ1MHEzSWNUbmF0T04wc282Y25FN1hyVGk3ejRpaXBpeXhvN3B0OFlLUlQ0SDdpUEJmMlI4MDJ1QTF3T3ZCZmNLNEZYeDhkdUFPOGsraVdGZWlvYXhHQnloWjNvT2VDL2dEc0lVSnc4QVBoRDhQd0R1Qy95RDdsdDlZNjJGeTVQZGVkcGxXTSttZkQwSzBsVWZFalJTM0V1NURlOGlaeDFLeFkwMFArRTh4V3ZJckp5QVZYU1NPa1NzUkxDaUcxRmUyT2xwaVhENThxTFY1V0dPQ0JiZEViazRjS3V5UjZ2Q2gzd2Qxb0Q3Zzd0LytiME53emdkNm51c1Q3dzZ3a1UzV1VPN0RYZDlyS2Jobyt0UWk1YXZ4bnloQ2llNG1MVGh5NlNObFJVdldGRUI2eGtidG9heXhpb1IwMWRGSVdDK3ZHRDFjcWkyZCtLNlZlRiswaml6UXNTcWJjTXdUZ2ZmMk80VHJsYVdZVjBhU3JzTjY3alhGZDhkckh6VlpjdExpMWRLbWFlY2szQmxXVWtCZzQ0clVkYkhVTzVVNHVVcE13dTFuN3Z1ZGVsRlRINlpaMHdxM1crb1piMUs0VzhsZXJRU1NRekRtRCsxZ0xVVzhiN29jSUcrL3c5aXRxQ3VzS0hGSzVXSmNubWNWNnEwNGRWZzVZWjRhZkZNMzNmVnJDOVlZUUdEaVptSlRSRnpqVUR0QlBFNjBJc1BMdmNEeXVRT1dTU0JSSTgvYXlWNlFDbGdKbWFHTVIvNnJLNWljVGxjMFBLKzZQdCszeXUzSVdwQ1Nrb0JrNUpSZW9xVVhSZGpYajNpcFRNT1YxYThZTVVGREdZWE1hTGxKZHYwRDFBc0x1SnEyVkZMWjg0eCtxdC85RlhBTndFempQblF0THBxajRzdjcvbFd4MVc3RE1WdEtQVU5wVlJVMzl4ZTF3bkNWUXhVN2hHdmxZMTdhVlpld0dBMkVWUFBGYjB3dWoyd09uQXJGL041Y3ZMVEhsSEVvbXRSaTlpc3NiRkN2SnlKbVdHY0NEODVVY09USzd2ck9vWXRxMHVFcTU2SXNuWWRhaXRNUDViWDdibXlRTytoTDZkSE1mR3FNQUdMVEJBeHJ5d3d1ZWdMVjZJRVZYMHBZSkl5cTEwSjU5U3lRenN1TnMwYWE3b1VWL29xTm94Ym85ZGxTQll0M1ZrOWNrRmM2dnU5S1Y0dVp4NWUxNHVMcjFIdHc0RlhNeXU3T0QwS1pjS0dpWmZDQkV6UkVERlBFSTRqY1IvNjdGYlFjYkRVRzRzWGR1MCtsSXY1SEhtZ2N4SXhTaEhUQTU5RnlOWm9XMlBRYjNtWlJXWVlKWDBOZmt2QVdsYlhFYm42ZXgzbkZtK0xGTnBOQXVhekcxSGlXN3UrRWk1Wm5ISVoranpPeXhJMmVqQUJxMmhrSjBxNXFVNDJJbEhJVkNhaUNGa2R5QlczNFRteWtPbDRtQmF4VGNMQTU0NGxGak1WV3pFeE1NRXlqSnVoSTE2TkVNR2tSQzNkVWQxemVkQnhFaXFVaTVBc1hQdkVERU1mTzc2b3NhTytPODRyZlZjVHI0d0pXSU8rRkh1VmhWZ0hkdE5GN3JPQUhVWi85cjRQRi9hZWh4MEg1M3hwZ2ZWWllUb210a0hJVkt3VE8rTFhMZGFHWWN4R1J4aDhLVjUxakh0U290WWU0VjRYb2Ryek9hNGxqK1YxT2p0WkxEcHhUVGFyYTJEaTFjUUVySWVlbUJpbzVBNXlabUs2MktQNWYrakRSYWt0c1gxQ3pHdVh0dlVsQWxhbjJDY3J6SFZGekt3d3c3ZzVmTFdkT3FYS0Ftc1ZLU2hjaDJxc1Z4S3h1SmFFREJHdUE1MmdvUzJ1UnFKR2MwWmxFNjh1Sm1BVFVDSUdqZVFPbnkvOE9wbmpocXNFak9BdTJBSjJ2Qkl0MTAza1NBSVc0MkNiQkFIYjhKT3pFaHRmM3pBTVJVc0F0SVVqOTdWTzNLZ3I3RWlTaFZoUSt2NU9ZaFpkZzVLWm1Hb1kra3E0NVA4b2wyRW5XUU5NdlBvd0FadUNYRGlONUE1WHhjRjA3NjJPaVIwU0x1Z3R3a1dkeE1ybjdhMG9jRnMreDhGYXlSeXBtcjJqS0Rwc2dtVVlKME83RG92a0RVZnZRT1hlWWdXVXJzRWtkTW9qbytmdmtnTGdSMDZKSjVqTDhDU3MzSFFxdDRMdnV1dnFaWTJRYUNIdVBrbkFTT254TGlab3VDeFVPdVlsanpmSUZ0Z3NLZlZnQW1ZWUo2V1R3RUYvOXFHSWo0elBTa0ttVXVvUDlENlVhSkV6QzhWVDAzSVZucG5WTlZRZE1BRTdJUTBSazdValdFUmlHYTJUNXhuVG1ZU2JaR0VTWWR1a0hBTW0yeUorZmRVNWdEUUZqR0VZSjhRM0JpL1RiNFdsTkhwS3E2d3UzcTJYbzFxNFZOeThGcTB6Y3hrT1ZRZE13RzZTV1lRTXRjUVVlSjJNSWNKVVpCcnFiUzErcml6MmExbUlobkhyMU1LaFhYbXRZdDNpK3BQNGxYWUpwbjJWWUNWcmF4bUZTeGlxRHBpQTNTSTlic1cwTFJZWldYeFNMTXZueDFyWXRIQ0pCVmNuYjZ6UkVDNnp4QXhqTm53cEZDMHJUSThIMDVVNGttdFJ4RTJKM0xFU0wxM29vQll1cXUwemozVU5WUWNzaWVNV21aQ3BDSG5BczFNWDhiSFBTUmdTTDlQV1ZTRll2clRpSkdtamxYM29obmtKR3NhWlVZdVlKRTRjK3lxdG5yS1lyd3lacWQyTitua3RoTDNDRmYrZjNibzNpUW5ZSE9qSlZOUWtJU05XOWlCYVViSEg1cHl5c0pTZ2FXdHJ6YXQ0bDRpbVdWMkdjZXY0TEY0Nkl6R0prTS9idFhXV3NwQmR0clphU1JrbVhLZUFDZGdjNlJFeUVTNVppd2pKOHltalVBUkt1UjNUZnZKemhldFEzUUVtWklaeE1qb2VrM2lUSmhGemFsM3RPNjczcStma3N6c3hMakRobWljbVlLZEFKV1J4TXlGQ0ZsK2FxdDNYcnNGa2FZbHcrZnc2MlREUk1vdzU0Zk45VzF0ak5JU3MySmMvb3JsR3ZkNllJeVpncDhnRUlhdXRNZ2hDVmF4OTk3a2lhU1MrMlVUTU1HNEIzeENXbGlpNWFnMmRqaW1ZYUMwVXkwSmNNTDR0T0hVbVk5Kyt2c2VHWWN5SGpsdnhoTnZBOElScnFEcGdGdGlDMFJmMkZCZWpMOTgyNjhjYmhqRURzN2JZemFTczFndUhKbHBqd0FUc0RLa3YrQjVCMDQrbkNaVGRRSVl4SDZiZVN5WllaNDhKMkJMUnVpRXFsNlBkTUlheFlFeW9scGRCeDhBTXd6Q00xV1Z0K2tzTXd6QU1ZL2t3QVRNTXd6QUdpUW1ZWVJpR01VaitmK1BKZlBlY2FxcEtBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDMtMjgiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6ImF1dGhlbnRvbjEgLSBDVEFQMi4xIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAyMzAzMjgwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjUuMCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMy0yOCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTAtMDMifSx7ImFhaWQiOiIwMDY2IzAwMDEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhaWQiOiIwMDY2IzAwMDEiLCJkZXNjcmlwdGlvbiI6IkNBUFkgVUFGIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjMsInByb3RvY29sRmFtaWx5IjoidWFmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9kZXIiXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJ0ZWUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsidGVlIl0sImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6WyJhbnkiXSwidGNEaXNwbGF5Q29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGNEaXNwbGF5UE5HQ2hhcmFjdGVyaXN0aWNzIjpbeyJ3aWR0aCI6MzIsImhlaWdodCI6MzIsImJpdERlcHRoIjoxLCJjb2xvclR5cGUiOjMsImNvbXByZXNzaW9uIjowLCJmaWx0ZXIiOjAsImludGVybGFjZSI6MCwicGx0ZSI6W3siciI6MjU1LCJnIjoyNTUsImIiOjI1NX1dfV0sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFLbjJsRFExQnBZMk1BQUVqSGxaWUhVSlBaRnNmdjk2VTNXa0xvRUhvVHBCTkFlZzFkT3RnSVNZQlFRa2dJS2paVUZsZGdMYWlJZ0xLZ2l4UUYxd0xJV2hBTHRrWEFBdFlOc2lpbzYyTEJoc3Ard0NQdXZwazNiL1prem5kL2MrYmNjOCs5dVhmbUR3QjVrQzBVWnNBS0FHUUtja1FSL2w2TXVQZ0VCdTR4Z0FBQitSa0FGVFpITFBRTUR3OEdpTTJOLzdSM2Q1QnN4RzVhVE5jQy84NFV1VHd4QndBb0hPRWtycGlUaWZCeHhEczVRbEVPQUNqRWdmN3lIT0UwbHlOTUV5RU5JbnhvbWxObXVYT2FrMmI1MWt4T1ZJUTN3cU1BNE1sc3RpZ0ZBTkpiSk03STVhUWdkY2cwaEswRVhMNEFZUitFM1RpcGJDN0NCUWpQeTh6TW11WWpDSnNrL2ExT3lqOXFKc2xxc3RrcE1wN2R5NHpoZmZoaVlRWjc1Yjg4anY5dm1SbVN1VFgwRVNlbmlnSWlwc2ZwYzB2UENwS3hJQ2swYkk3NTNKbjhHVTZWQkVUUE1VZnNuVERIWExaUGtHeHVSbWp3SENmei9WaXlPam1zcURrV1pVWEk2dlBFdnBGenpCWjlXMHVTSHUwcFc1ZkhrdFhNUzQyS25lTmNma3pvSEl2VEk0Tys1WGpMNGlKSmhLem5aSkdmYkkrWjRyL3RpOCtTNWVla1JnWEk5c2orMWh0UEhDZnJnY3Z6OFpYRkJkR3lIR0dPbDZ5K01DTmNscy9MOEpmRnhibVJzcms1eUdYN05qZGNkajVwN01Ed09RYVJ3QWJZQVd0Z0JXSnplQ3VtN3pUd3poS3VGUEZUVW5NWW5zaXI0VEZZQW83bFBJYU5sVFVUZ09rM09Qc1h2eG1jZVZzUUhmOHRsbzJzN2ZRYmNoY1BmNHNsQ2dGbzNRVUF2ZnBiekZBWEFQa1NBTnFsSElrb2R6YUdudjVnQUJISUF4cFFBOXJJSFRJQkZraDNEc0FGZUFCZkVBakNRQlNJQjBzQkI2U0NUQ0FDeThGcXNCNFVnbUt3RGV3Q0ZhQWE3QWYxNERBNEN0ckFLWEFPWEFMWFFDKzREZTRES1JnQno4RTRlQWNtSVFqQ1FSU0lDcWxCT3BBaFpBN1pRRXpJRGZLRmdxRUlLQjVLaEZJZ0FTU0JWa01ib1dLb0ZLcUFhcUFHNkdmb0pIUU91Z0wxUVhlaElXZ01lZzE5Z2xFd0dhYkJXckFSUEI5bXdwNXdFQndGTDRGVDRHdzREeTZBdDhEbGNDMThDRzZGejhIWDROdXdGSDRPVDZBQWlvU2lvM1JSRmlnbXloc1Zoa3BBSmFORXFMV29JbFFacWhiVmpPcEFkYU51b3FTb0Y2aVBhQ3lhaW1hZ0xkQXU2QUIwTkpxRHprYXZSWmVnSzlEMTZGYjBCZlJOOUJCNkhQMFZROEZvWXN3eHpoZ1dKZzZUZ2xtT0tjU1VZZW93SnpBWE1iY3hJNWgzV0N5V2pqWEdPbUlEc1BIWU5Pd3FiQWwyTDdZRjI0bnR3dzVqSjNBNG5Cck9IT2VLQzhPeGNUbTRRdHdlM0NIY1dWdy9iZ1QzQVUvQzYrQnQ4SDc0Qkx3QXZ3RmZobS9FbjhIMzQ1L2lKd2tLQkVPQ015R013Q1dzSkd3bEhDQjBFRzRRUmdpVFJFV2lNZEdWR0VWTUk2NG5saE9iaVJlSkQ0aHZTQ1NTSHNtSnRKREVKK1dUeWtsSFNKZEpRNlNQWkNXeUdkbWJ2SmdzSVc4aEh5UjNrdStTMzFBb0ZDT0tCeVdCa2tQWlFtbWduS2M4b255UW84cFp5ckhrdUhMcjVDcmxXdVg2NVY3S0UrUU41VDNsbDhybnlaZkpINU8vSWY5Q2dhQmdwT0N0d0ZaWXExQ3BjRkpoUUdGQ2thcG9yUmltbUtsWW90aW9lRVZ4VkFtblpLVGtxOFJWS2xEYXIzUmVhWmlLb3VwVHZha2M2a2JxQWVwRjZnZ05Tek9tc1docHRHTGFZVm9QYlZ4WlNkbE9PVVo1aFhLbDhtbGxLUjFGTjZLejZCbjByZlNqOUR2MFR5cGFLcDRxUEpYTktzMHEvU3J2VlRWVVBWUjVxa1dxTGFxM1ZUK3BNZFI4MWRMVnRxdTFxVDFVUjZ1YnFTOVVYNjYrVC8yaStnc05tb2FMQmtlalNPT294ajFOV05OTU0wSnpsZVoremV1YUUxcmFXdjVhUXEwOVd1ZTFYbWpUdFQyMDA3UjNhcC9SSHRPaDZyanA4SFYyNnB6VmVjWlFabmd5TWhqbGpBdU1jVjFOM1FCZGlXNk5iby91cEo2eFhyVGVCcjBXdllmNlJIMm1mckwrVHYwdS9YRURIWU1RZzlVR1RRYjNEQW1HVE1OVXc5MkczWWJ2all5TllvMDJHYlVaalJxckdyT004NHliakIrWVVFemNUYkpOYWsxdW1XSk5tYWJwcG50TmU4MWdNM3V6VkxOS3N4dm1zTG1ET2Q5OHIzbmZQTXc4cDNtQ2ViWHpCaXpJRnA0V3VSWk5Ga09XZE10Z3l3MldiWll2NXh2TVQ1aS9mWDczL0s5VzlsWVpWZ2VzN2xzcldRZGFiN0R1c0g1dFkyYkRzYW0wdVdWTHNmV3pYV2ZiYnZ2S3p0eU9aN2ZQYnRDZWFoOWl2OG0reS82TGc2T0R5S0haWWN6UndESFJzY3B4Z0VsamhqTkxtSmVkTUU1ZVR1dWNUamw5ZEhad3puRSs2dnluaTRWTHVrdWp5K2dDNHdXOEJRY1dETHZxdWJKZGExeWxiZ3kzUkxjZjNhVHV1dTVzOTFyM3h4NzZIbHlQT28rbm5xYWVhWjZIUEY5NldYbUp2RTU0dmZkMjlsN2ozZW1EOHZIM0tmTHA4Vlh5amZhdDhIM2twK2VYNHRma04rNXY3Ny9LdnpNQUV4QVVzRDFnZ0tYRjRyQWFXT09Cam9GckFpOEVrWU1pZ3lxQ0hnZWJCWXVDTzBMZ2tNQ1FIU0VQUWcxREJhRnRZU0NNRmJZajdHRzRjWGgyK0M4THNRdkRGMVl1ZkJKaEhiRTZvanVTR3Jrc3NqSHlYWlJYMU5hbys5RW0wWkxvcmhqNW1NVXhEVEh2WTMxaVMyT2xjZlBqMXNSZGkxZVA1OGUzSitBU1loTHFFaVlXK1M3YXRXaGtzZjNpd3NWM2xoZ3ZXYkhreWxMMXBSbExUeStUWDhaZWRpd1JreGliMkpqNG1SM0dybVZQSkxHU3FwTEdPZDZjM1p6blhBL3VUdTRZejVWWHludWE3SnBjbWp5YTRwcXlJMlVzMVQyMUxQVUYzNXRmd1grVkZwQlduZlkrUFN6OVlQcFVSbXhHU3lZK016SHpwRUJKa0M2NGtLV2R0U0tyVDJndUxCUktzNTJ6ZDJXUGk0SkVkV0pJdkVUY25rTkR4TTUxaVlua084bFFybHR1WmU2SDVUSExqNjFRWENGWWNYMmwyY3JOSzUvbStlWDl0QXE5aXJPcWE3WHU2dldyaDlaNHJxbFpDNjFOV3R1MVRuOWR3YnFSZlAvOCt2WEU5ZW5yZjkxZ3RhRjB3OXVOc1JzN0NyUUs4Z3VHdi9QL3JxbFFybEJVT0xESlpWUDE5K2p2K2QvM2JMYmR2R2Z6MXlKdTBkVmlxK0t5NHM4bG5KS3JQMWovVVA3RDFKYmtMVDFiSGJidTI0YmRKdGgyWjd2Nzl2cFN4ZEs4MHVFZElUdGFkekoyRnUxOHUydlpyaXRsZG1YVnU0bTdKYnVsNWNIbDdYc005bXpiODdraXRlSjJwVmRsUzVWbTFlYXE5M3U1ZS92M2VleHJydGFxTHE3KzlDUC94OEVhLzVyV1dxUGFzdjNZL2JuN254eUlPZEQ5RS9PbmhqcjF1dUs2THdjRkI2WDFFZlVYR2h3YkdobzFHN2Myd1UyU3ByRkRpdy8xSHZZNTNONXMwVnpUUW04cFBnS09TSTQ4K3pueDV6dEhnNDUySFdNZWF6NXVlTHpxQlBWRVVTdlV1ckoxdkMyMVRkb2UzOTUzTXZCa1Y0ZEx4NGxmTEg4NWVFcjNWT1ZwNWROYnp4RFBGSnlaT3B0M2RxSlQyUG5pWE1xNTRhNWxYZmZQeDUyL2RXSGhoWjZMUVJjdlgvSzdkTDdicy92c1pkZkxwNjQ0WHpsNWxYbTE3WnJEdGRicjl0ZFAvR3IvNjRrZWg1N1dHNDQzMm51ZGVqdjZGdlNkNlhmdlAzZlQ1K2FsVzZ4YjEyNkgzdTY3RTMxbmNHRHhnSFNRT3poNk4rUHVxM3U1OXlidjV6L0FQQ2g2cVBDdzdKSG1vOXJmVEg5cmtUcElUdy81REYxL0hQbjQvakJuK1BudjR0OC9qeFE4b1R3cGU2cnp0R0hVWnZUVW1OOVk3N05GejBhZUM1OVB2aWo4US9HUHFwY21MNC8vNmZIbjlmRzQ4WkZYb2xkVHIwdmVxTDA1K05idWJkZEUrTVNqZDVudkp0OFhmVkQ3VVArUitiSDdVK3lucDVQTFArTStsMzh4L2RMeE5lanJnNm5NcVNraFc4U2VrUUlveE9Ia1pBQmVId1NBRWc4QXRSY0E0cUpaalR4ajBLeXVueUh3djNoV1I4K1lBd0Q3RVMwZWxROUFNREpXSW02RXNMd0hBT0dJUjNrQTJOWlc1djh4Y2JLdHpXd3RVaHNpVGNxbXB0NGcyaEJuQ3NDWGdhbXB5YmFwcVM5MVNMUDNBT2g4TjZ2TnAwMzVQQUNxTTEyY1BhQ1IvOThhK1MrWXp3ZDFqR2lEZFFBQUFDQmpTRkpOQUFCNkpnQUFnSVFBQVBvQUFBQ0E2QUFBZFRBQUFPcGdBQUE2bUFBQUYzQ2N1bEU4QUFBQUJtSkxSMFFBL3dEL0FQK2d2YWVUQUFBQUNYQklXWE1BQUFzU0FBQUxFZ0hTM1g3OEFBQUFCM1JKVFVVSDRnY05CQzBNK1llcS9BQUFBSGQwUlZoMFVtRjNJSEJ5YjJacGJHVWdkSGx3WlNBNFltbHRBQW80WW1sdENpQWdJQ0FnSURRd0NqTTROREkwT1RSa01EUXdOREF3TURBd01EQXdNREF3TURNNE5ESTBPVFJrTURReU5UQXdNREF3TURBd01EQXhNR1EwTVdRNFkyUTVPR1l3TUdJeU1EUmxPVGd3TURrNU9BcGxZMlk0TkRJM1pRcW1VOE9PQUFBTVJucFVXSFJTWVhjZ2NISnZabWxzWlNCMGVYQmxJR2xqWXdBQVdNT3RtV3VXNUtnUmhmOXJGVjRDQkJBUXkrRVY1M2ovRy9DSGxOVlYzWmxqZTN5c0dsb3BDVUVRajNzdm11dWZjMTcvNEVqUzJoWE9NVmZUV0VNTk9vUEUrNVl1M1RWWEtaSnJGZ21sRlN0ZFFxaWJmOExwWkUrVHpHVzlOR3FxcVlZY1N5Z2h6L0E2L3J6K2Q0Y3o2L1VhL1Q1V2t2WExzcjk1WEgrdmU0eWF0ZFNrNmJrc3Ivc3FsK1p6VzlmellPVG5QQU1MRGxYcWM1MWU1eUNwVmp3WHZ1NWJlMDJRTDl4NXUvRjUwT2ZYQTYwLzczK3RsUHUvOVYvNTUwQ1p5RHltcHYzTTBNSWtDTEdLMXZ0NitKZEZvU3IyMTVkRk03N3VwM0RwWnRXbSszbVF2eDVzdXBNUytucWhmUTAwQ2RCUy83by9YcFpLdS9TdkxLcC9iYWwrc1BTNkg5VDNCNzlGNS90b0dmdFAzaWxEVnZ1ZncvOS95NlAvWWlCY09HdjVjeW55ZFQyMVZjbXR5TmYxL1M5NXAwTTlqeUxYMjRPdGtuZjJ0L3YyaXRTZjl4dFJhYVc4RDBRSjUvUkt1Si8zczhhYzgvZ3c4V1RpK1Q2UXF2R1d2VnRVYzdhUy83eFAwanBwNHU4REVmUmNTbnE3VDU1L1docCtIYVhrK0Q1UTA1THRGdzU5djlDMWthTDE3VDRyS0pyMzIwQWs0U2pwM1Jkbm9KenlmbDlhTFVVK09Wc0pzMzRJODZvL1UrUG5Db3dWZkxBb255WGs5aDVOb3ZiSmQvaTB0RTlSNHhGaEx1OHY2QzRmQmpvZ2wrVkRRcDV5L0FINlB3ZWFoT2h0eVJTdzR0UHlZV2tQMUgyYUdWNTV5eVB0TExtWDhEWlFDTWY4eEVDSjN5a2U5T01lbUlnM1d2MVZKam1wTTdpUmtBWU10UXYyZzhNZUNqckJ5cUNsSnRreWhlRVNRNlhiOGI4SThzZmhhWjFuTjUzZHZCWTF0RThkYTN5Y25tdzlSWno2K3RSUE1lTmUyaUE1NzVXcCthZU9CT1VoVVcrM0MwYmJoNjRLeWFoZmZSNGZmUVBFR2ZCVXZoK0tvVkc4Y1QrNEpDeEQxc3QvREpERzgrS3hPbmNHT3Roem9sRjRxZkRTQVRkdEIrcFkzRkVOMUZmRmtvWlZqUUhhZU9rSEJqQW1OZDd2aVlFNkwzVmVHcncwZUduTVExZ0hGQisrT1NTOGVHbngrNVRhNXZjZXQ5SElCOXJBM1ZSL3hGT1IzakVtbXRFOFJDazBPckNNRTdXWWRqaU9qeVJxSkxRUjY0a1FqWGZoeEZoSnlJalpzVEVJSmtlakUrYkd6aHlkem9QejRJeUZjWEplbkJmbnpYbHpkdnA3aDcxWW1vUWpyakp0QlJHbE9iNXQ2S2RJRzRTTVo0Vm56QzZWZTVVWFlWNGhkSUtJRUVJc25hS1Z3Y3ZNS1BoRDhJV2NJT0VEOFhJbmRRcURyRlNDRldrckpDWUIxV2tlRHJZbjVWbWxhRlBkSVRWdUdEY1lQWFd1Qjllem9qWjRZUi9LbmlHNUVXMmxERktnR21pTE9obmhRRTQrd0FiU2hJekptUUV6Q1pmeFVTYVNHVXZ6ekNFeldNWW5KMHV5YnpKdGhZS0FLZ1NqcEU3bVdDZ0ZNVnBZT3pWSk1TbXBST3UwUWFHREpvV2xGc0pkQ1BQOXh4SlY2cTNDRkV1VTZLbjJvSFZjNUI3eXpGYlE3cmQwVkNLak93VllKcHhhcnFSRVpmYWFGa2ppQ0NRU0JoU29URnlOWjRpek9xQ2p1bEJQekZxOUlWc0dDZXloa1Q4dG4xTHVKUE1PclhHTnRhMXpQYmptbmJacmFDU2prYnNtK01oWXB6SFRvV1JEcUZqamQrYzNEcmZKYnlZeFh1Z3hoczZ5T3BaMVVxS3pwRTdaZEZLZ2Q4Qy80NHUrWnVoK0FzMGY2bndrQzZQRUF3dVVPbFZENXpGTzlYREc4WU1JemtnR1NrZmxwVEFMZVlRR1FkcnRNSHNOODVRWm1Uc1pkSjAvRXZUb3pjVVNGMzVaOUZ0ay9KbzhYL3pHSFp0MDJJSkZtL0NoSThPdUhyWU42bEhEeGdkN2IrclNnbE4zVHBZN3lPQmt0ZU1ySHlrNHkvWjlxaHN2aVY0a0NNQ3NPS0JpczFGY2d3ZXJuamNqaFh6L0Y3TURveXZHTm1Qc2VHdGFqTHV4dUJvcHF5aXdTQlROa2RxSjBsT1VTZHZBOUlGcW9URUpPaElBb0hWeWVoYUFvRkNaVUFlRmh6NUJlZmVZMjdqZ2tnVTZiQ1lGSGFKRVNDcVdvaEhPQUMxR0xHTkZWbldxN2NoWkZMTkYxUm0xZWRRaEdNbzk3MWVzWUVQTk1jSnpzVGFMdGU5SWJzWHFOVFp3aEVLUEtKVFlXbyt0ZTJ5TDM5NGZ4TWtsbW81b0ZxOW9nOXhkSzFKaHNVdVBIZGYwV29HakhVbU4ySEhvaURtT05PSmdtWU1CQjVhTTFlTUJJRklnVGlnN3pqcml4RDl6empoeDhBSzFGbFc4NnNFd2k0UTZMZ2JiQ1BLTmRSdWZiTXR4azFCN1czU2k0V2xmMFpVTEh2anc2THZMamFYNG5zSVQwcHlzQXpUQU9rSUYvalhXRERsMW5EbTM4SktJVkRuNlNLVHh1N3ZJV3BCT0Y0QkxBQ3RKbGlWTmtlUUhMRjF5WHV4S3ArUStKSzlPZGxGaDlDMUtzM3BKbWFnR2g4SVpHWHFYSTZoMTBIWWp3TFJzVWl0VnhnQjFUZGh0U1VzdWpSUnFIVHRXRnNEa0VtTlVQQzltUzBBVHFnY0RVeEdrbm5RYndMRURJaUlqS2Foc011aEhSc2lCdHBtTS9SSTZvY3NsYzFWQWM4ckNMNnVxTEdaZW03d2thOURQZ21GQWVCVktSbGdnVU43RkxZcXpFbmVBS3lGZmRGNjRoZkpkZzBJZ2xUUGh3MFZ4Y0haSnh6YlJsTVFHdUo4VEhWTUNtMVAxbEVaTGlaQmxiRVh5WENuYlRubTFSUEtuQWtDWGhpaWNrb3F2ZExZQmlOT2tmU2ZkQmxsa0JCcDhZVE5WMUdtTE9UWElwalVzYXJPQlB1VU9rakdURFZidXdCM0Q5Sm9USzRWWVBMSGdOSlMwN0QyTjNRaG9UU2lxTkZuUjNPbEtpd2hUTG9sRVRVQk0ybkkyb2pRWUNTUWhQakU1ejUzTThDMHdJMUpPODRISWd6MTRsaVRVZmxFWGt6VGQyQU5WWWJ1TWdrY3hoWExIZnFhRHVxRERqTHpNcldjS25Bb0RPTmc0RkRDNXJNM1dXNjZqMEVFQ1ZLVkRiWGlwVnBRbkx6Y1lxK1dScWVQY2dFZUtCVm1JU3pzQ25iNDkxZHlaQ0RzZzlubmxlOFBBeUFPektjQk1WUE1jUFpOU21XNTVHYkZZYktVUUFWdDNKaFVlcmtUdjQ4cnM2L0I4dmVDaFdFQjJvQjZzZ0F1QmcwSmxGcEtnU0tXdUFYVmdyUkJHaUxVWEhGYU9STS9OQ1RJN0kySGJoNndwaExxQXdrV2hWdTNzZEJ4eGlQU3ZsQklzWGhvcDJDb2lkSTVpZ0l3aE9HMGN4cXVsODFidk5HZWdnZHVHMGRnaHpFUUR4ZWJTc3RqMnJOckttbFpBcHNKT3NleXhDcEFQZzhjQ0FTQzFzS0dRV2IxZkdNTU9Qdk9vZzZNWUpyaFViQ295Q2RlU1RGWTFRUzM1QlAxc0xyZVJQY3hrMVBnK1h6Z1dXemE1bENwWGVGMnJrY1Iwb3JJVmV0YTJKeHVvcEdZZDFVeW01TWJLSFlsUWRURHg2Snpkc2JQcTdINmhYUnY0alhZWWFINDRaYk1CMzVOc3dPT09VbkFnSFRVRzBTTmJOcUVoMzZPVmlrUWd2bFJ6eHc3RUtLbEQwUXgyR1RFL1g0WW1ZUUp0VU80VjU1eDFWUVhZMVZ0bEEwdWFKZmdGbnRCZEczMU5lclZtVjdVTmJHV3RSTGFpdnlvQVh3ZUZCTERXMldpSFZOaXRVRUwxNk5jTkFtNmVBdzRJbUZ4OUYxUlp2WkFTN1dpS0JrbTFPQmNnRWtBNkFOZ3prRkFiVlFwOXJrYXF0N3dwOWt3byswQWRIZWNLZm1IVGxNYlZxbmxqeU1iZUZEVFl6UUJ0TTR6MTNhakwxbWR2VUgzRGhXMzRiRk1CRE80dGtHdnh5bkp2Vy9VaU9MdDVnamNONFl4MlE2NGhONkFXMUdmc3phQVBRTHNiVkg2S3hjQVNFQWRKMVNnNjZxUVV0ekx0dXV1UStCb1N5dkNtNFFoanMydHRZQmhKaGJvejgwa1NOR09YWlFPc0g5ME5GclJKbCtuVmx1WUxraFdEK0d6M1Rib3NGanJNSFkybnlOc0ZyYkxsaDJMaEM1cHBCNkFwZkJwTW1Ta3FxcHdDYkZjdm5jblFLbmlna3pTazJlNVkxUnRFMG1idUFDdzlEREV6ZTRmMFlaUStLTE94RFVhZmZhSUVWODVYWDVENWhqczJ0SDhTR0l2T1p3aGtiRUYxOVlFTUdYSEJWeG5HbnlCOXd2ZDlzMExLMUtqa21FWnAvVUtmWVhpMUFiQ1JkVzFnRGJWTmZTKzJNOUNxOFRJb1Bmb29qTFQ1Y2RJc2ptbmpDSjZ4a0xZczRBTEh3VFNIK2FGUzk0Sm9acGV6VVJSYVVRNWdmSEZJRDBZQVNOSmlMNERzQjI1bnlZT1ZrUTJaWGZWTTE2UTJFQ1FrU0ZxempUbmhEeVl6QkVxYk9HT0NGbk1Nbll3MFdjaUVzQ1o0Qm5Ib0JCVFFyWFg2YU5jNmUrZ3drRzFwc2hoa2FQTEZibWtCOXd1K3dZK0dIUUJSM3Fzc3ZGWEswZ1dLTXg1dVdFMWh4YzFBcGdoaTRrNjRWdmVCNzFHLzdFSm02OGd2VkxBcERENFhpbWM1NnNBN094dm9NZ3h1WjdZN0UzMVQwa1hBQmxhbURYaHRhR1JubjVRaE9CL1dQdDlld1l0TkFrQ0p5SUF4MFZpay9pS2VZR3JmZ0NiZ01ueGNHMmpkQ04rOWJDSVQyaWF3MjZFK253anB3bjVpRjQvb2hlaU9sc0VsMFJ4SThneUJRRHRla09GdzIrV3F5L1VFRGFYWjZOVElPcVFPTlZBZFpQR09raCsxT3VHa1VCb09ORi9VeU03RDk1cGdKR1hyZnJIeE9wK2I0NDhQRDEvZmlFUTU3ZzhRWU5kOVo1WDdheURjL3ZSZ2VWK2ZwZi84eEJyRGovOEg4T05lK0UvM3J6OGYvUFo5Kzl2STI3TCsrdEplWGwvTzhueXVFVERQUUtLdlQycXZyOURsOWJHa1BOL0owYWNwZlRqL2RnRCtMRElsK2MyeU1SNmZRS3ZIa1o1ZTN4K3IzRDZDN3V0OW4zNzNlWFY5bG9ZNE9xY1pUZ3gvZklyL0doa0t2cy90MjAvRDJlU005bTFSK0l2aitoY1Q5VG9SQXJQM2xRQUFBQ1YwUlZoMFVtRjNJSEJ5YjJacGJHVWdkSGx3WlNCcGNIUmpBQXBwY0hSakNpQWdJQ0FnSUNBd0NzRFcvR1lBQUFlY1NVUkJWRWpIclZaYmJKeFhFWjQ1Ly9rdmU4bXVkKzFkcjJNN2R1ekd1VFNoaWRLRXBpRnBCQ1VSRW9RS2FGVUVSUlZDb2srZ1ZqeENIM2ppQWZIQ0V3OG9TQ0JCS3dqUW9wYVdGQXBOUSt2Z0pzM0ZjWnlMTDdHOWErL052M2YvKzMvTzhIRFdibWdyVkM3bjZUOXo1ajl6WnVhYitRYUpTQkl3aEZqS3VicWZNclJTMWdRQUlrQ0UvMzF4U2NRUWJ5dzdQM2w5c2VaRUd1SjlnK2x2UHRSdjZ0ci94UVpuaUUwbitzRkxjN1luaUVoaitLZkpaaXpwbWVOREcwcVNBT0ZmakJFQUFoQUIzQ1ZYd3ZmcE1BQjQ0V0sxMW83eUtmNzVmVDJIUmpQWmhQYjI3YlhyRlFjUmhDUUFZQWlJUUFTMC9qT3V4MURKTjRSM0w3VmxmaVF1ekxjMXhDY09sYjcyNE9hbmp3ODlNSnBwK2VLZHVSWUFhQXlKYUxibWxWY0RSRUFBQWhCU2hyRkVCTnVMeW5hZ1BCQ1NJaUhsdWpVaWlvU01wZVR6RGI5c0Ixc0wxcEd4cmxnU1ozaHNlLzZsUy9WYlZSY0FhdTN3UjYvTXo5Vjl4bkQvVVBxcFl3T1dydjNzemFWclplZnhnNlZUWjh0Tkp6cTVyK2Z4ZzMxVEZlZUhmNXc5TXBiNytpZjZBZURsSzdYbng1ZWZPamJBSzNib0JtS2trQUJBQmdRQTIwdkpIMzlsdTZFeEFIaHVmUG55Z3JNcG9jV0NYcjNhM0pLM3ZyQy90K21LaFViNDB6ZVc1aHRCTnNHZlA3K3lkekF6bExkYXZyeTY2Q2pVVEpYZHBpdDZNeWF6M1ZnUTlLUjFsUllBMERVMldrZ081aTB2Rk9NemE3a1UvOTduaHI5eHRDK2hzeHNySGdCWW5QbVI1SXc5YzN4d3JEY1JDL2p6VkNOdDhlR2VSTFVWclhreEFDdzJnNEdjMlo4eldSQkxJTEIwZG5kK1ZHNWpTZHQ2azQ4ZEtPN3NTeDhaeXhrY2c1Z1ViSUtZSGoxUS9OVE83aWNlTEJrY1oycytBSXdXRWcwbmFqaFJMR1RaRGdmemxzRVpSOFNOdDI4c2pTRUFiTEw0ZHorN2RYa3RPRE5aSDU5WkN5TFNWRDRKa2diYjFwc0VnSUZjb2pkak5KMFlBTVpLaWRNVHNtS0hhWXV2dXZFOXhRUUE4S1RCQU1FSnhQdHdSa1NJK1BMbDZxbXpaZHNUMlFRM2RKVFVPVEk0S3FkTnpsS201Z1Noa0RSU1NPcWNMVGFEcE1HRXBORmlBZ0JZUHFYckRDdDJxQW9LQUJZYS9yZC9lZjBYYjVYZFVQenE3UldEc3ljUGw1NDlPV3h5OWg0SzE3MldSRUlTMTFBUTlXV043aFNmYi9nM1Y3eVVxUTNtTFFCZy9Ua3ptK1RYeWs3TGo3bUdBSEJwb1hWaHJxMHp0cklXckxUQ1QrL0tmL25qZlNPRlpCUVRBZ0lBUS9SQzJRcGlBSEJEMlhEaVRSYlhFQzFkRytxMjV1citsY1gyUU03c1NSc0F3QVp5MWxDM1ZXMUZwODR1QmJHWXFib3ZYNjUzcC9uZUxXay9rcElnaytBQU1GVjIyb0hRR0tqQ2pnUzlQdFVFZ0xkdXJkWmFZVi9XVUduYlZrcFc3UEI2eFZVSmtFUWNBQjdhM25WcG9UMCswNXBjbW80RTJaNFk3ckYyOUtXbmw5MlVxWjI3YVpzNi91SGRPdGRRM1NJa0pBMzJ5cFhHOUxKYlhZc1l3OTBES1JXNjBVSUNBQ0xSU1FBUmNBQjRlRmYzeE56YXVadHJRY3dra2M3d3ljTjlBTEMxeHhvdFdKTmxaMkt1ZGVMZW5CQTBYWEVVVEJNNjI5MmYrdXUwelJtT0ZxMVA3c2dyQTBQZENVdG5ZU3kzOWlTVUpsYzk2enNuaGw4c1ZhOHVPZ21EZldaUDk4Nit0SkNrYSt6cDQxdCsvWStWWXNaNDlQN2k1SkpUYllWRXhCQ0NtTDU2cUcrMG1LeTFveS91TDFpNnBraWxOMnZrVW56TkV3TjVDd0FRa0t0MnFERjhaRi94a1gzdjlXZU5JUkZzN3JLKzlmQVdKZHd6c0dualZCSVpuSDNwL3Q1MVRIY2dibWpNRFdWL3pzeFluSlFIeWhFQ0lFbUlxSURPRUR0eUF0V2tFWkdJaEFSZFEwUmdpQXF5c1NSdFhYbHAxZi9kaFdxMUZSN2IzZ1VBVXBMR2tHMzBic2JVbjhEdVloWjFGME5FQUlhb1VCVEc1SVdpVS9PSWlLQ012WHVuL2R0M2Focml4d2JTRzBURS8wTUdSQUFZekJ0N0JsSzZ4dTUrQndEa1UvcEl3WHhnSkt1QzJRa0RFYWs0c0gvTHYvUUJ3b0lQREFaRUpJZzRZK29JRUJBQXBhVC9ndGtWWnVBakRCOE1FV3F0OEcvVERSVkhvZzdIMG5xTFZkdHFLK3dvQUJBQlE2aTN3MW83N0FCaG5hNkRTSzY2RVJFMW5MQWR4S0JJLy95c1hiR0RNNU4xRlUzMUlseVBpZHA2WVR3eGE3dWgyQmd2eG1kc1YvVmdCRVhYQUhDdDdQeG1Zam1XOU1aMDg5cFNHd0M0RzRxMkx4NDcwTGZxaGhmbTE2Ykt6c205aGRNVHk0V01zYTJZVEJxOGJQczNWN3dkcGVURk82M1p1bmRpZCtIMmlydDNTMmF4R2ZUbnpOZk8xZytPWkN0MmFPbnM4RDA1THhJcFU3TzkyT1JNSlpVbERXMUx0L1g5RjI0dHJZYmwxYUEzYXp4M3ZySi9PTnViTWVjYmdSZkptWnJmMzJXMkE3R3RtT3BKbTFjV1dsNGtBV0RYNXRTZFJuQjBMRit4dytXMWNIZC9HZ0RhZ1VpYnZHS0h1c1pVMEZqTGo4ZEtxV2RQanY3OTFtcmRpU3pPVW9hMnVjdThkM1BLMHBtbE01T3pvWjZFcVRPTjRXZ3hlWFBGTFdVTUFPQWFJNExSWXBJekxLU05iRUwzSWpGYjllWWJmcTBkYWhxcTVIR0RzOStmcjJ3dEpFcFowOUpSRXZYbnpMOU1OVXlPc1lUYlZUZHRhbjRraUtEaGhBTjUwd3RsSnFFRGdKQzB5ZEpldkxoaTZreGpEQUJtYTk2QmtjeDlnNW1mbjFzc1pVMkxzdzU0NzlTOTB4TVZQeEtMVGUrMWF6VWlldk5HczlvS1ptdnUrWm5WZWp0bytaSHRSUXNOYjluMlg3MVNqV0pKUlBWMkVFVGl6R1N0MmdxYVRraEVUU2RzZVJFUnpkZmRaZHRYd2crcGd3K3RLYlZ1VjkyRnBuOTBMSytHbjQ5VStxcVNKWkZxbjZxa0pYWFlrWUFRT2lNaklvU3gxRlgzV1M4eEtRbHhRNldEYjFyL1FvQi9BcVpJR1hMM3pUaEVBQUFBYkdWWVNXWk5UUUFxQUFBQUNBQUVBUm9BQlFBQUFBRUFBQUErQVJzQUJRQUFBQUVBQUFCR0FTZ0FBd0FBQUFFQUFnQUFoMmtBQkFBQUFBRUFBQUJPQUFBQUFBQUFBRWdBQUFBQkFBQUFTQUFBQUFFQUFxQUNBQVFBQUFBQkFBQUVUYUFEQUFRQUFBQUJBQUFDb3dBQUFBQU95UDVmQUFBQUpYUkZXSFJrWVhSbE9tTnlaV0YwWlFBeU1ERTRMVEEzTFRFelZEQTBPalExT2pFeUt6QXdPakF3NmhaTzBnQUFBQ1YwUlZoMFpHRjBaVHB0YjJScFpua0FNakF4T0Mwd055MHhNMVF3TkRvME5Ub3hNaXN3TURvd01KdEw5bTRBQUFBWWRFVllkR1Y0YVdZNlJYaHBaa2x0WVdkbFRHVnVaM1JvQURZM05TQUpBTXdBQUFBWWRFVllkR1Y0YVdZNlJYaHBaa2x0WVdkbFYybGtkR2dBTVRFd01RWW5OcThBQUFBU2RFVllkR1Y0YVdZNlJYaHBaazltWm5ObGRBQTNPTW5VZXljQUFBQW9kRVZZZEdsall6cGpiM0I1Y21sbmFIUUFRMjl3ZVhKcFoyaDBJRUZ3Y0d4bElFbHVZeTRzSURJd01UZ3ZUQVZCQUFBQUYzUkZXSFJwWTJNNlpHVnpZM0pwY0hScGIyNEFSR2x6Y0d4aGVSY2JsYmdBQUFBQVNVVk9SSzVDWUlJPSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0wNy0yMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTgtMDctMjAifSx7ImFhZ3VpZCI6ImNmY2IxM2EyLTI0NGYtNGIzNi05MDc3LTgyYjc5ZDZhN2RlNyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiY2ZjYjEzYTItMjQ0Zi00YjM2LTkwNzctODJiNzlkNmE3ZGU3IiwiZGVzY3JpcHRpb24iOiJVU0IvTkZDIFBhc3Njb2RlIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfZGVyIl0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjMsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNDVENDQWErZ0F3SUJBZ0lKQVBBemVnY1U2c1ZBTUFvR0NDcUdTTTQ5QkFNQ01IWXhDekFKQmdOVkJBWVRBa1JGTVNFd0h3WURWUVFLRXhoSmJtWnBibVZ2YmlCVVpXTm9ibTlzYjJkcFpYTWdRVWN4S1RBbkJnTlZCQXNUSUVOQklHWnZjaUJCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUmt3RndZRFZRUURFeEJKYm1acGJtVnZiaUJHU1VSUElFTkJNQjRYRFRFNE1EUXlOVEV6TXpVeE0xb1hEVEl6TURNeE1ERXpNelV4TTFvd2RqRUxNQWtHQTFVRUJoTUNSRVV4SVRBZkJnTlZCQW9UR0VsdVptbHVaVzl1SUZSbFkyaHViMnh2WjJsbGN5QkJSekVwTUNjR0ExVUVDeE1nUTBFZ1ptOXlJRUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhHVEFYQmdOVkJBTVRFRWx1Wm1sdVpXOXVJRVpKUkU4Z1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU1ZiRDRvK1F3bHRpeFRvT1pTRkVwdER4RGErY1pPbW55OXJQOFd5eHRnY3dINHlOSXQzN3p3ZGo1OG9HVWdqQkNVZUQ4VERONTJBQURhOUtTVk9jc2pveVl3SkRBU0JnTlZIUk1CQWY4RUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lDQkRBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlBMU5ocXVKTlArV3IzTGUyOVI5QmN4ZEFFSmQyWVd4SER5OFpFaTlraGptQUloQUt6UmQ5ZjVkZjRrUTlRQVVOWnJTbFQvbXk3T0lYaU14MHdIOGVNWTQyRmYiXSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiY2ZjYjEzYTItMjQ0Zi00YjM2LTkwNzctODJiNzlkNmE3ZGU3In19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA0LTE2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTTEU3OCBDVEFQIFVTQi9ORkMgUmVmIERlc2lnbiIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTgwOTI2MDE1IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMTYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA0LTE2In0seyJhYWd1aWQiOiI5MWFkNmI5My0yNjRiLTQ5ODctODczNy0zYTY5MGNhZDY5MTciLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjkxYWQ2YjkzLTI2NGItNDk4Ny04NzM3LTNhNjkwY2FkNjkxNyIsImRlc2NyaXB0aW9uIjoiVG9rZW4gUmluZyBGSURPMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX3N1cnJvZ2F0ZSIsImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQi9EQ0NBYUdnQXdJQkFnSVVFTC9Xa1pmbnhEdzlzODVYelVTSmd5Y0pqclF3Q2dZSUtvWkl6ajBFQXdJd2NURUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQWdNQ0U1bGR5QlpiM0pyTVJZd0ZBWURWUVFLREExVWIydGxibWw2WlNCSmJtTXVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUk13RVFZRFZRUUREQXBVYjJ0bGJpQlNhVzVuTUI0WERUSXhNRFl5TVRFMk1UY3pORm9YRFRNeE1EWXhPVEUyTVRjek5Gb3dlekVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFnTUNFNWxkeUJaYjNKck1SWXdGQVlEVlFRS0RBMVViMnRsYm1sNlpTQkpibU11TVNJd0lBWURWUVFMREJsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVIwd0d3WURWUVFEREJSVWIydGxiakVnUVhWMGFHVnVkR2xqWVhSdmNqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJMY3dVNUFkblFhWWJsTGlXNFhzd0Q4czZ6ZVErbkVBdktLanh5MzJQSzFDV1V4dnY1UkFnUTZ3VVFKSllWVTRSY3FWZmRyR0ZxSTlkSUF1djFuZWMzeWpEVEFMTUFrR0ExVWRFd1FDTUFBd0NnWUlLb1pJemowRUF3SURTUUF3UmdJaEFMdCtIejNsK2dmWkdFQW0vZWU1TWdwMklCQ3crVVlMU2c3cjJMWFJDOVNrQWlFQTF6anplajZ0ejlzb1Mwb3oyVnM0RDZBdHpvWFkySFdaQmdZdDhHMUtuaUU9Il0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIiwiVTJGX1YyIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiOTFhZDZiOTMyNjRiNDk4Nzg3MzczYTY5MGNhZDY5MTciLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1diI6dHJ1ZX0sInBpblV2QXV0aFByb3RvY29scyI6WzFdfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDEtMjUiLCJ1cmwiOiJodHRwczovL3Rva2VucmluZy5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJUb2tlbiBSaW5nIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMjAxMjUwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuNC4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDEtMjUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAxLTExIn0seyJhYWd1aWQiOiI5Zjc3ZTI3OS1hNmUyLTRkNTgtYjcwMC0zMWU1OTQzYzZhOTgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjlmNzdlMjc5LWE2ZTItNGQ1OC1iNzAwLTMxZTU5NDNjNmE5OCIsImRlc2NyaXB0aW9uIjoiSHlwZXIgRklETyBQcm8iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnh6Q0NBV3lnQXdJQkFnSUNFQXN3Q2dZSUtvWkl6ajBFQXdJd09qRUxNQWtHQTFVRUJoTUNRMEV4RWpBUUJnTlZCQW9NQ1VoWlVFVlNVMFZEVlRFWE1CVUdBMVVFQXd3T1NGbFFSVkpHU1VSUElEQXlNREF3SUJjTk1UZ3dNVEF4TURBd01EQXdXaGdQTWpBME56RXlNekV5TXpVNU5UbGFNRG94Q3pBSkJnTlZCQVlUQWtOQk1SSXdFQVlEVlFRS0RBbElXVkJGVWxORlExVXhGekFWQmdOVkJBTU1Ea2haVUVWU1JrbEVUeUF3TWpBd01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXJLVUkxRzBTN2E2SU9MbG1IaXBMbEJ1eFRZanNFRVNRdnpRaDNkQjdkdnh4V1dtN2tXTDkxcnE2UzdheVpHMGdaUFIrellxZEZ6d0FZRGNHNCthWDY2TmdNRjR3SFFZRFZSME9CQllFRkxaWWNmTU13a1FBR2J0M3J5elpGUEZ5cG1zSU1COEdBMVVkSXdRWU1CYUFGTFpZY2ZNTXdrUUFHYnQzcnl6WkZQRnlwbXNJTUF3R0ExVWRFd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ0cyL3BwTUd0N3BrY1JpZTVZSW9oUzN1RFBJcm1pUmNUanFEY2xLVldnMGdJaEFOY1BORFpIRTIvelordUI1VGhHOU9adXMreFNiNGtua3JiQXlYS1gyem0vIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUkwQUFBQVdDQVlBQUFEOS94OGxBQUFBQkhOQ1NWUUlDQWdJZkFoa2lBQUFCM0ZKUkVGVWFJSHRtazF5MjlnUngzOE5JdExTekFuTW5NRE1Oa21WNmFxcHluSjRBOU1uTUNTU1ZhRzBNTHdRc1JCbHdTY1FkWUtSVmxtbFJHNW1HK29FUTUwZzFDNVVTSFFXai9oKy9OQkV0bWNtK3E4SXZFYS9ma0Qzdi92MVk0Vk5PQXhhL1BtN0tqLytZMW9hOC93cWYvbnIzL25UZDNmVzhXZjhadUd1SFduM213Z1h3QnZyZUdVdkJCcEFnOFBnSFo5Nnd5OWk0VE8rTGRyOUppS3ZWbGRqQnIyUll4WHNudFNCaXcyS2hvaThUYTRkTGpnTVdrOW82ak4rQ2VqMFBVUm13QmlKcm9tbzBRa2FaYWZwbnRTSjVBYVI2Z1pGYjB2M254M25Od2lwTXVpTlVCMmlFbEtKSnFEMWZIcnkvQ29xRjJzZHhqakYrZG81ak9Pd01WVmw2VTZpYTA2UEo3bnhUdEFBWHErdXhpeVk0cEk2NldMK21kQ2Y1WjdwbnRSUjUvdFVoa3QrRjFXSjVCVWl0WklOcWxPV01pYnNwYlZZcCsrQnZGaHJkNnczN0UxTllGVmVJMnA1VHpKaDhlOXh5Y1o0YlNxdmNzK0pqdmlQM0NXMlBNYU9HRjVRbzZLdlMyc1ZIWEY2Tk1ienE3ajc3ODNhWmNiWjN6N241THlnbHJ6amlMdmsrMFdZT1VTcXFOWVlIRS9vQk0yODA3aDdWeUQxekoxckJyMVJzdUJTeXRJRFZGb0lyNUpiRGhlMCt6UE9qcTZzQ3hZOFlxZFFSNEJKUWFJQmZGajkvZ2p6RVBZUEFQTWlLM3QvQVBLTUZvbUhKSTUxRC9QUDZONFFrZGZZSUdLcXVWd3RKdXVESVliTEdKaWlFaUpxMTQxQ1pXL0dZWENRNk82ZTFJbWNINEFhb2dWeEFWZkhxM1Uvemc2QWRoQWl2QWV4bUNMUUNlS2ExRGZxRlNEdk5DNjFaTnpSTVdEc0Z1cXJKUTFCakhPaHN6UTl0ZnREeUx4azVaYkZ2SlVzV3ZXSGdra2ZHUnlGTE9jTmxOdkMyTVdxTHZyZllTSTJUSzVGM2hyalYvQ0NXaTVkUm5qV0tMZkI0U0tuNjZrZ1VrWDBITTgzakJMSkZjTFR6OU1KZk9Nd1h3aExRdHBCQ1BJVHlFKzR0Rmc4REEzVEhBYXRUS1FhaDFuT0c0VCtETSt2bG1vYzFVdk9qb3huR3BrR2xmMVJ3amdpVlpRTDRJOVBZdnlnNTlQdXR4QjVDVUFGRC9ETWIvV1RLRk85NDlOUk9UV3FYaUlTVTI0Tko4T1lEZzNpeUVvZk9BQXBNaUFzNXVWN1dkMVpsaFNwNHU3WGdWRmk5enJkb211Y2ZJc2RTak1oR05VN0lDNWM4N0xHanNmRHBFQ3ZlTnMxa2FybkdYcTdaMGt6aVZaM2Z3aGtjL2MxWjBjcEE1MGVUNnlPZzlUcEJENkRudit6REM1Q3hWKzFBQUI5aStmN3NGL05PYnVJdlJBWG1TWnBGcURUYnlXczZ0Z1lRQ1k1K1UzSTZ4N1JEcHE1ZEYzRVFxNXk5Y2htNVp2dHlNNGowbG9yMndsMm0yNUh1RlRVejdGSWhKZGZsRmJUU09hVzVTcGx4VVZ6ekNhaFA2Tjcwa0tkZjZhUDZudmlYR21EOHBKdVAxOGJSTHkwcFdjKzlZYkp4elpSN0tGYVM1MWR4d3lPZHZ2UTN4SVZibWozZlpZUDF6dW5VUnU2SjNXeTVkR3VUdjRFY0JGcFpxN3YxKzU4aWluTDNic3BGTTF3ZWp5aDB4OG5VU3hTeFF0cWF5TkxhS0VGZHJBNVREcm9BemZHSG4yZjMrWEpiczRaVWN2VmJ2RU9JWStiVW5TcXpqZzcrdjFHM1NvTnNMQ01TV0dHRVlVYXlCQjNIOXJCRU9GeXd3Y3YyMkdDbzRFNjloM3VWNEJEdkNzQlVQNjFSczZTc3NTZUo3VkE5enRUOFE0d0wvY2FvRlJqYmFieEZpb2pWRWFaK2dQZ25taHUzK1dWZEt4cFEyUjFaMWxWOVM2eGFmbmdvWHBwZmRZNHh0T2s4SzhFRnpUREROUTRERnA1dHBFWkVqVUlqMWRidlA0UStONmlLKzR4Wkl1KzhjYlpWZStRUXFRcnRYemhXTUFDRDdjdy8zSUR5NnlkbTF1Y3FHVk5FWVlaQ3M2K3JsaTE0aHBIVTV2TUhDMjh3TWZWSm9wWFdPTUh2R0JZQ2pDYkhWSFJycThQRnlWRVNPbGE5Snp1eVNScHVpM202WXMxUFlGc04vZysrV1g2T0lVZXc1YVBLVElzRmNvbTZqN1lIOEF3Vjd1ZjByM3llU3ViWlhjNHUrUitZOWV1TmNJYlZLdUlaRnNTWWFscEdkdHUyZ2ZoNm4xZEVUTzk2WlhrMTdISkRyTXJTcTgzbFFGYlpiVytwUzdJd1ZrMTRhNHpocG90ZHR4bmlSM0diTXZ6UFFHSlRFUEsxc2RSUG4reDRpd2JmY0oyQm9oM09GL0tudUk3UkxjMzZBYTlFWnB4a3VpUmZSenpYZEtncld3S3RJS3NtMm1PbWw1U3B0MWkyZUlYWVBvMGkzbUx5dDRrb1V5UktoRTNkRS9lY0hvODRUQm81WG9iQUJIditIUThzWjVWS2JlYzlVcjcrMThQOUp4T1VIWkdpUTZzREFMbUhicjdVK0JGcnQxZ2pqaktUcVRVY2cyL1NtVFJ1OFVPMWF0TWdkMWFIZEZNckxJd0lpMHJQdEFPM2lKTVVhMUR0bDdUcllGbG5NWnNsNXVyWXM3UVpldzQ3YjVuSWlkRFh4RnArejF5aGdqWm92U081VU5qMjhTL2JLd3I4amZzV0VKL1JxZnZKOGNBcXUveGdpRktsZVNJSUR0RlZxOWVNckE1NHhZN2x1TGowaVQ3ellwenhiSVMrYWpUU0dXcEFUVWtZNGh5dS9iNEo0UDA3T24wZUVMM3BJRTZlY2NwZGt0VkwzTmQxM3dqNng1SG01eHQ2RCtvVEpMekYxdFJGekZkblgrc0wvcDJrZGsyVC9tQnpVVTdwSjNick81c04zZHdGTkx1MXhGcUNDWU5MQmppOGhFMFBsdXFBeTlXRzVBWkVWZjVMdllqN0FoN1U3eWdUZ1VQMFhxcUcrTUF3cFRGS2dXZUhrK01yUG9nOWZ4MzB6SElpT1U4TEU1bG5iNTB4OUJwNmpoWm1PT0RmRitsRTJSYlRHKytacFBwR2Q4RzVmL1RuQjVQVmdYdWZYNUF4eVdIeVNMaTNiUEQvSC9BL3MrOW91TW90eXdlbWxaWkkzRHcvSGZQWnhoMFQrcDArcVBraU4rR1R2OVh2RXQ2eHMvQmZ3R2hobW5ZY2F5ZGdRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjlmNzdlMjc5YTZlMjRkNThiNzAwMzFlNTk0M2M2YTk4Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNy0xNyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSHlwZXIgRklET8KuIFBybyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwODA1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDgtMDgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA3LTE3In0seyJhYWd1aWQiOiIwYmI0MzU0NS1mZDJjLTQxODUtODdkZC1mZWIwYjI5MTZhY2UiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjBiYjQzNTQ1LWZkMmMtNDE4NS04N2RkLWZlYjBiMjkxNmFjZSIsImRlc2NyaXB0aW9uIjoiU2VjdXJpdHkgS2V5IE5GQyBieSBZdWJpY28gLSBFbnRlcnByaXNlIEVkaXRpb24iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA3LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjBiYjQzNTQ1ZmQyYzQxODU4N2RkZmViMGIyOTE2YWNlIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbIm5mYyIsInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjozMjg3MDd9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMy0yOCIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vcHJvZHVjdHMvIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyAtIEVudGVycHJpc2UgRWRpdGlvbiIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI4MDAzIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMi0wMiIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTZWN1cml0eSBLZXkgTkZDIGJ5IFl1YmljbyAtIEVudGVycHJpc2UgRWRpdGlvbiIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMjAyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAyLTAyIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMy0yOSJ9LHsiYWFndWlkIjoiNzM0MDIyNTEtZjJhOC00ZjAzLTg3M2UtM2NiNmRiNjA0YjAzIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI3MzQwMjI1MS1mMmE4LTRmMDMtODczZS0zY2I2ZGI2MDRiMDMiLCJkZXNjcmlwdGlvbiI6InVUcnVzdCBGSURPMiBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MTAwLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlEVWpDQ0FqcWdBd0lCQWdJR1EyRnNZV2xDTUEwR0NTcUdTSWIzRFFFQkN3VUFNRFV4TXpBeEJnTlZCQU1NS2tsa1pXNTBhWFlnUmtsRVR5QlNiMjkwSUVOQklGTmxjbWxoYkNBM05EQTROVGN3T1RJeE1UazNNREFnRncweU1EQTBNamt3TlRReE1qQmFHQTh5TURZd01EUXhPVEExTkRFeU1Gb3dOVEV6TURFR0ExVUVBd3dxU1dSbGJuUnBkaUJHU1VSUElGSnZiM1FnUTBFZ1UyVnlhV0ZzSURjME1EZzFOekE1TWpFeE9UY3dNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXRHQitFT0JwMkpkM3Y3VkVBa1pZVVF1dU8yL2E1MXZ0TC90dkdDSkhUYlErbTh1ZjNnRTZ0V3k4ekRZb2owWmQrKy9FSWpnZ2RSck9EMWRZSDVsK3k1aXBSVDNKc202WlUxTkJ1dFQrWDhLcjVLOFR4NkVROFMveVN4WXZGb1RKZHNQUHp0N1l0WlJ4SDhFN0dNYjdvTzh3ZWpLRDJnQlRyVEVTczNkMkZNWWE0ai90ckU2Myt0KzROcWNrSlcwdGVPNmVPRm1JYVhRS1B4L3d1SVgzUmVFOVpvTkNRT25OajNVWkROUlpaWEwxVkVUQ3JSb2dRY3ZqL2NRY1lGU3dTZUIyM1RrZXNOUXhSS3JpRWJlVitqOHlxVkUyVHV6SklQejRKMTB1Mk9tbXJSUU94dzhDZEVOWk1hajZFdC90WTUxYUdsQUhyNng5cFI4cVczUGhDUUlEQVFBQm8yWXdaREFkQmdOVkhRNEVGZ1FVR2QreU41R0hzYm9ZUS9YNHRweFozKzJqdHFBd0h3WURWUjBqQkJnd0ZvQVVHZCt5TjVHSHNib1lRL1g0dHB4WjMrMmp0cUF3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUVWVDU4OXhCSTNldjZjSFVMN3FGSGVDTU8xUzJNVWh0OHdNVlA2R1dQb2QxRTFyeWt5eVM2ZSt2Qm9rT2ZaUFRFVDcrMmVGMFFCTlgvNzRHOTZWK3F2bDVuWkhJUnFJeFowY3p3M2UrYS80VS9ZYzM2bStyMnZncGp6UEluOUdGTDZzN3Rtd2cxK2JOeVB5VTZ5cGtFZVY0NkFjZjBiV2UvSUFiODVWUUpaV2RBR2hIU0oxZFVWYjg4bDdPZXFrUVJucWUzbTNjMjAxSkROQ2QxdzUvM0xVKzhmbW1qT21hdHNHd3c0eVJHdzNjR0RwV1E5aDFWWnBTdVVkZm03T2gvdWw3UG5majl1MDVnSVlhWEJvOXpYQXoxc2VQTFY3aGtmYlM3cnlQTDB4RFVlNkZiSUcyNjdyTkppaDRlSzZ5a05QRU5HaVJRZXc4dzFBU2RuTGlLbz0iLCJNSUlDdURDQ0FhQ2dBd0lCQWdJQ0VBUXdEUVlKS29aSWh2Y05BUUVMQlFBd0p6RWxNQ01HQTFVRUF3d2NTV1JsYm5ScGRpQkdTVVJQSUVsdWRHVnliV1ZrYVdGMFpTQkRRVEFnRncweU1EQTRNVFF4TmpNNU5UUmFHQTh5TURVd01Ea3dOakUyTXprMU5Gb3diekVMTUFrR0ExVUVCaE1DVlZNeEZUQVRCZ05WQkFvTURFbGtaVzUwYVhZZ1NXNWpMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVsTUNNR0ExVUVBd3djZFZSeWRYTjBJRVpKUkU4eUlGTmxZM1Z5YVhSNUlFdGxlU0JRTVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkhYaHBsYjhmdTRMUDlYYzBnNURWWDF1MjYrcTJWU3BVRFZIM043TXYrcEtGTTh0T1BnM3hha2ZCZFh4ZS9DRUxJQ1BlaWJRVHVvelQ2NDFpRGxXc3NxamJ6QnRNQjBHQTFVZERnUVdCQlJldXU0cmNIN3Flc0VFbFRqSmRxcGRlcHk2YVRBSkJnTlZIUk1FQWpBQU1CTUdDeXNHQVFRQmd1VWNBZ0VCQkFRREFnUXdNQjhHQTFVZEl3UVlNQmFBRkxiZSt0ZzEyK2w3NG0zQksva0dGaHZLM0JZL01Bc0dBMVVkRHdRRUF3SUY0REFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBVXhWUDFQZkFiTlcyNXV2Z3BydXhsdGdnZlBib1lMY1FhYnpGSHNsZDJQM3JpaXBjMzRMWEx4bW96QnJqZHc1Ry9wa1RzVWpzanltTjhrNDU1U3d6eUZnVFlKeDY5RHlLV3hJaWpoY0NIS3Qya1F5cGZtaWFkMmdJRy93VldyQ1hnYzFuSUxvSUJEdUxVeUZmQ0g3ZWYzZ0x1aXJ5NnJvMlJWcTZHVUtXODNFL1NVSGRsVVRKa1NxcFc4RTNHT3ZmZkhORmpXSGI4YTE5b0VaZGZQM2tDejY1cDYvMk1TeHh2MndUdDhkUTVVbGRYQUVCWEJQU1Rmc3E1YmIwTnNxd252QkZrdkFhS2ordWV5US9TOW81UFFySW43SmhHaXBYcmF1NDM4aG10MFJFUTY3WFBGaTQ2Q3BNUzBUOXNCUEd5U0lvTE1tblRjbkhyMFVvdHBzQ3hRPT0iLCJNSUlEUURDQ0FpaWdBd0lCQWdJQ0VBQXdEUVlKS29aSWh2Y05BUUVMQlFBd05URXpNREVHQTFVRUF3d3FTV1JsYm5ScGRpQkdTVVJQSUZKdmIzUWdRMEVnVTJWeWFXRnNJRGMwTURnMU56QTVNakV4T1Rjd01DQVhEVEl3TURReU9UQTJOVGMwTkZvWUR6SXdOVEF3TkRJeU1EWTFOelEwV2pBbk1TVXdJd1lEVlFRRERCeEpaR1Z1ZEdsMklFWkpSRThnU1c1MFpYSnRaV1JwWVhSbElFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXVvQW96VVNtdmVOdTJNY3NyTFJpRGMydlorT0RjSXpvV05GNjV6UlVROVVqRllXNWRZWGthTFlKUnNJejVzZGlnWXljTWlHZ2FvTkZPbHlSMHdTUlgwcFpTOUFXWFdNN3BSc1pRUDlUZHdEaGdudGlGU2RtZWVhaUtFU1lPVGgrWUdsc2RZNFIwWmZ2NU4zMkZwd3NIMHZZMkYvS2NyM0pYNmk1dktrekJTbTFtZ0VJZGZsTkFHOXMvRzA5TXBuejBNZS8xeUlqSnY5VjlERUFXSEpuNk1ZTitmYklCZm92bENLWVFYTlRHeGZBZ3lRODJnYXNCVldrdWlVRXp0WTJVYmZneUEycFVaODZPSWRpbkNxT3BnbDkyYlpoMWpWeE5GamVwdnlmV0ttbEFZWVN0dThqVDVrZXZBTlFGeXM0UU8wNjNsWkI5T3N0NEFvaE5Nc2hVUUlEQVFBQm8yWXdaREFkQmdOVkhRNEVGZ1FVdHQ3NjJEWGI2WHZpYmNFcitRWVdHOHJjRmo4d0h3WURWUjBqQkJnd0ZvQVVHZCt5TjVHSHNib1lRL1g0dHB4WjMrMmp0cUF3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBT0JnTlZIUThCQWY4RUJBTUNBWVl3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUZDbG1rRExlN0YvQ1JtUnU3MmlLS05xaUxmWVcwOExEN1RrUVdvejUzbklBanM4OHNNc2JmckVTanJBUEpjNGdzYkNGWlRMYzJGeDN6MTU2ZlR3V0VBK1BEY1lNRm5ya2FMVEJJdlhZWUVkUDUwdVJVd1Z4dHdNcTFIdURGTjVPYVhwOW1DNWZBUFNQSU84OVNXVVdiUTEzTCtuUjRJcUo3TzBoQnlLS2NXSzF6ZFR5OFRrNUxhZEhNSjVlTEZuSGFwWit1UnQ3YW1WQ3VmOEZhM3F1WVVBZjR3UUgyMllpaTBwdnAxR1ZpNEtwTVh1d2hMQWl2clEyNEF1K2kreWh3SHFWemdobDlFOEZKbG8wWWxLL2JySEpFczNHZEt3SFVBWkF2S2RQZmxrT0NZOHovY1NpYmRJRGhvd09XdEg2bEd2UWh4RHpYQitBbmt4TXVUTVFDOD0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBR1FBQUFBT0NBWUFBQURaamJsb0FBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUFmZmFWUllkRmhOVERwamIyMHVZV1J2WW1VdWVHMXdBQUFBQUFBOFAzaHdZV05yWlhRZ1ltVm5hVzQ5SXUrN3Z5SWdhV1E5SWxjMVRUQk5jRU5sYUdsSWVuSmxVM3BPVkdONmEyTTVaQ0kvUGlBOGVEcDRiWEJ0WlhSaElIaHRiRzV6T25nOUltRmtiMkpsT201ek9tMWxkR0V2SWlCNE9uaHRjSFJyUFNKQlpHOWlaU0JZVFZBZ1EyOXlaU0ExTGpZdFl6RTBPQ0EzT1M0eE5qUXdNellzSURJd01Ua3ZNRGd2TVRNdE1ERTZNRFk2TlRjZ0lDQWdJQ0FnSUNJK0lEeHlaR1k2VWtSR0lIaHRiRzV6T25Ka1pqMGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNVGs1T1M4d01pOHlNaTF5WkdZdGMzbHVkR0Y0TFc1ekl5SStJRHh5WkdZNlJHVnpZM0pwY0hScGIyNGdjbVJtT21GaWIzVjBQU0lpSUhodGJHNXpPbmh0Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0x5SWdlRzFzYm5NNlpHTTlJbWgwZEhBNkx5OXdkWEpzTG05eVp5OWtZeTlsYkdWdFpXNTBjeTh4TGpFdklpQjRiV3h1Y3pwd2FHOTBiM05vYjNBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZjR2h2ZEc5emFHOXdMekV1TUM4aUlIaHRiRzV6T25odGNFMU5QU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2YlcwdklpQjRiV3h1Y3pwemRFVjJkRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDNOVWVYQmxMMUpsYzI5MWNtTmxSWFpsYm5RaklpQjRiV3h1Y3pwemRGSmxaajBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDNOVWVYQmxMMUpsYzI5MWNtTmxVbVZtSXlJZ2VHMXdPa055WldGMGIzSlViMjlzUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnTWpFdU1TQW9UV0ZqYVc1MGIzTm9LU0lnZUcxd09rTnlaV0YwWlVSaGRHVTlJakl3TWpBdE1EUXRNVEJVTVRFNk5EWTZNVFl0TURRNk1EQWlJSGh0Y0RwTmIyUnBabmxFWVhSbFBTSXlNREl3TFRBMExURXdWREV4T2pRMk9qTXlMVEEwT2pBd0lpQjRiWEE2VFdWMFlXUmhkR0ZFWVhSbFBTSXlNREl3TFRBMExURXdWREV4T2pRMk9qTXlMVEEwT2pBd0lpQmtZenBtYjNKdFlYUTlJbWx0WVdkbEwzQnVaeUlnY0dodmRHOXphRzl3T2tOdmJHOXlUVzlrWlQwaU15SWdjR2h2ZEc5emFHOXdPa2xEUTFCeWIyWnBiR1U5SW5OU1IwSWdTVVZETmpFNU5qWXRNaTR4SWlCNGJYQk5UVHBKYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pVeU0yRmtNek5rTFRrd01qTXROR05sTlMwNU1HSm1MV1V6Wm1FeFpEZGpNR0ZsTmlJZ2VHMXdUVTA2Ukc5amRXMWxiblJKUkQwaVlXUnZZbVU2Wkc5amFXUTZjR2h2ZEc5emFHOXdPakJoTVRGbFpUZG1MV1E1WlRRdFlXTTBOQzFoTTJJMkxUbGxabVZrWVRBME5EQTVaaUlnZUcxd1RVMDZUM0pwWjJsdVlXeEViMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPbUk0WkdSbVlUQTVMVGRpTTJNdE5ETXdNeTFpTlRsbUxXRTJNVFF5WlRkaU1USmhZU0krSUR4NGJYQk5UVHBJYVhOMGIzSjVQaUE4Y21SbU9sTmxjVDRnUEhKa1pqcHNhU0J6ZEVWMmREcGhZM1JwYjI0OUltTnlaV0YwWldRaUlITjBSWFowT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNllqaGtaR1poTURrdE4ySXpZeTAwTXpBekxXSTFPV1l0WVRZeE5ESmxOMkl4TW1GaElpQnpkRVYyZERwM2FHVnVQU0l5TURJd0xUQTBMVEV3VkRFeE9qUTJPakUyTFRBME9qQXdJaUJ6ZEVWMmREcHpiMlowZDJGeVpVRm5aVzUwUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnTWpFdU1TQW9UV0ZqYVc1MGIzTm9LU0l2UGlBOGNtUm1PbXhwSUhOMFJYWjBPbUZqZEdsdmJqMGlZMjl1ZG1WeWRHVmtJaUJ6ZEVWMmREcHdZWEpoYldWMFpYSnpQU0ptY205dElHRndjR3hwWTJGMGFXOXVMM1p1WkM1aFpHOWlaUzV3YUc5MGIzTm9iM0FnZEc4Z2FXMWhaMlV2Y0c1bklpOCtJRHh5WkdZNmJHa2djM1JGZG5RNllXTjBhVzl1UFNKellYWmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG8xTWpOaFpETXpaQzA1TURJekxUUmpaVFV0T1RCaVppMWxNMlpoTVdRM1l6QmhaVFlpSUhOMFJYWjBPbmRvWlc0OUlqSXdNakF0TURRdE1UQlVNVEU2TkRZNk16SXRNRFE2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQXlNUzR4SUNoTllXTnBiblJ2YzJncElpQnpkRVYyZERwamFHRnVaMlZrUFNJdklpOCtJRHd2Y21SbU9sTmxjVDRnUEM5NGJYQk5UVHBJYVhOMGIzSjVQaUE4ZUcxd1RVMDZTVzVuY21Wa2FXVnVkSE0rSUR4eVpHWTZRbUZuUGlBOGNtUm1PbXhwSUhOMFVtVm1PbXhwYm10R2IzSnRQU0pTWldabGNtVnVZMlZUZEhKbFlXMGlJSE4wVW1WbU9tWnBiR1ZRWVhSb1BTSmpiRzkxWkMxaGMzTmxkRG92TDJOakxXRndhUzF6ZEc5eVlXZGxMbUZrYjJKbExtbHZMMkZ6YzJWMGN5OWhaRzlpWlMxc2FXSnlZWEpwWlhNdlpqRTVPRFUzT0RBdE5tWXlZUzB4TVdVMExUZ3haVEl0TmpGak16TTVNemN6TmpoaU8yNXZaR1U5TnpNME5qazVNR1F0TVRJek5DMDBObUpqTFRsak56RXROR1ZtT1RVek5XSXdZV1ZoSWlCemRGSmxaanBFYjJOMWJXVnVkRWxFUFNKMWRXbGtPamxqWkRNMVpqZ3hMVFJrTVRZdE5UVTBZUzFpTWpVM0xXUTJaVEUyTXpSbE1qVXdaaUl2UGlBOEwzSmtaanBDWVdjK0lEd3ZlRzF3VFUwNlNXNW5jbVZrYVdWdWRITStJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCtub2FNYWdBQUJadEpSRUZVV0VmTm1HbHNWRlVVeC85djNreW5RNmZ0VE1mUUJVUVdCWWtVRVdrRENnWVZWR1JSMllLSWlaRW9Hc1FGaUlwYitHVDhRUHhrakd5QkVBdW0wbUtDTEFuR3hJaWFBTklLQXNWU3BBWWpiYWVkbWM3U1dkN2lQZmZkenN6clRJdUVxZVdYbkx4NzdqSzU3NTU3bGpkU28vc2VIVmxRdTBNbzNiZ0dJejdaSkhwU1hLaWFqK0NwSDFDdGgwUlAvK2k2RHVWYU84Sy9ua1hYcmxwMDF1K0hyYmdNa3NVaVp2U1ByaWl3T1BJeHVhMFJUZFVMMFhQdUlpejJQREdhUW92SGtUOStIQ2FlUHNMMXEyOXRSdnRudXlFWE9ybWU4SGxSZWZrRXZOdHEwTFpsYTdML1Jvajcva2FWN2tQejNKVUlIVC9COTBYb3FnWUpPdTROWE1BSnlZVTgxd2hJa21TTUpSVElIamNxci96QzlYUWFpKzRHbXdoSmxybE83K0Nvbklqcm44cE5RcHV6bFpmQ3RXQU94dFp0dytSTERWQUNYdWlhSm1iY1BKTE5obUJENWt2L1g5REJFODdLS3VqeEJHOFRrczJLYU90RkpObzZSSTlCNUxmelVJSmRTV01RV2pqTUhXRFFEZElYKzdnN01IYmZEcWdCditoaG00bkZvZmg4bVJMMFEvVUZ4S3hNeVBzSU1ycU1ZZkFmUE1iMW9hTDA3VmVoUmNKQ001QXRoY3d6OXdyTndMdDlMeXpXQXFFWjc2RWhCdmVTSjNOdmtNanAzM0Z1L0N3MFRWOEU3OVlhMFd1bVpNVWlkbnZzM04zSkdBVlZVM0RYc2E4d3JuNm5XZXAyWVV6dEYyS1ZHVzRNVlUwWkpTOGYvdnFqdk4wZmFpQ0loTkxPd2s5YlVyUklqeGcxazBpYlE1SkE2Z0wxaDJmVlluYXcwZVNlQ011d2ZCNHEwL0h1Mk1mN2U2RTkzTFp5QlcvbjNDQXErL0ZJODNuMG5MbUFsbGRlUXVqblUyTEVqSHZ4UE9peEdEOVUrOWhSS0pvekM2NW5uakFKelhFOS9iaFlZWVpDUStHak01TWh3cEp2aDYvMklHOW5nNHd4NnZPUE1hMjdIVk9EclZ5cTlBNjRuMk9IMk1jb1pJeHBiR3hxeUpoSFVqMkFwNmJqV2JZY2VpUXFOQ09jUnE4Mk00ODMxbE1lMUdMZHBuQ2x4cnRSdG1rZGIrZmNJSlNzSmVUeEE3TEp3K0hmZjBpTW1NbWZQSkhIWGluUGh0QlBKOUc2ZWlQK1hQVzZTUzR2WFFQdjdscXh3b3dlamNLOWZDRi9FdlNDU3FUVCtFMTJDSDBoYnlRb29jdk9ZVndJaXZOOTg1a09sVC9sQW1NZWlkVlZ4UHV1QitVQk5SNFVtb0VSdGd3djhXNW4zcEVlcmxqaGt1ZXBnR1BTQks0UGJnNlJMVkE2dW9SaXh1b3A0UWNoV2ExSS9OT0d6aS9yNGZ2Nlc1TjAxWDJEU01OWnNjS01wckdZeTBLZnFxVml0b1hsRVZvbnNjdnduMGtMTDdtZ29Ib0taRWN4dXdDR1VRbko0ZUI1Zy9CdXIySGh5c0hiaEJvS28reTkxNFEyMkFZaExFWUptRUY2TjVWLzVGbDloTFluU2RtM3lJcHBuc3p0WmFPVFZZN0ZZWWUvN3JEcGhZZUMwdlV2czZvcElqVERDNk10elFpZk9zTkNlaWdacmlqWHFIcVF6KzlsY0EzQzNORTJzbHdvWnBTT1RuN29kSk5rdHd1Rmp6d0E1OHhxa3hRK09KMVhaUU5SOHV4VDBIckRsdDJPd09IdmVadU1QRlJRdGFXb2dWVEJ3ZlppTGZiZzByeFY3T25tZllRZVpWNysyQUtoR2VUY0lCUVROUVNoK0xzUjE2NWgrTm9YeElpWm5vWnpSdnhtVlZZUlM4NTNIdHJES3EyOUpwbHcvQUNHcjN0UnJNaU9hOWw4YUlvd0NIbWFWV2JWMWhHZXc0WUt1Y2dKNTZScDVtOFN1bnlVMzdqbkc2alJJRXZtYTRWbWtIT0Q1STBhZ1lvTjc2RDhvemR4MytVVzJDcEt4WWdaWDkwaEk5WXo5NDIxdEtMN3V4L2hQM0EwUTdwcURvZ1YyWEhPdUorSHIrUnRwS3FtNlJMUFRVTkp0bStTZEdOUVpMRFlDbEE0ZTRib01jaTVRZXlqUjJMa2xnOVJzWGs5N0dOdUY3MW0yajdkeHArMFFmb3JKSHl5RWMxelY2Qmw4ZW9NdWNocWV6NTNnQkJVUFB0aDdtbTlETFV4Q00velN6SytTZEtoSEVNVldWOXlicERyUVRIK3J3M3ZRbllWaXg2MkNXWVVxOXVkWFpDS3VmM2hYcllRV2srcTlyOVY4Q3hkQ2ozTHZzaElsR1BLM2plK1BkSVpkSVBvaXNwQzBoVjA3dG1QcHVvRitHUCtjdGhjNVFQZStCdWxoSG1SRHZhUmVZdFI5c0ViVUdPcGFxc1hQUjVIOFVOeitIZU9HZUJmSjM1NkNMOEdkRDhBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiNzM0MDIyNTFmMmE4NGYwMzg3M2UzY2I2ZGI2MDRiMDMiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWV9LCJtYXhNc2dTaXplIjoyMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwiZmlybXdhcmVWZXJzaW9uIjoxMDB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wOC0yMSIsInVybCI6Imh0dHBzOi8vd3d3LmlkZW50aXYuY29tIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJ1VHJ1c3QgRklETzIgU2VjdXJpdHkgS2V5IiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDA4MjEwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA4LTIxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMi0wNC0wNyJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImM4ODlhYmQwMTYyN2I5OGQyZjdjMWNkOWQ1ZDE2ZDJkMDI2MmY2OTYiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYzg4OWFiZDAxNjI3Yjk4ZDJmN2MxY2Q5ZDVkMTZkMmQwMjYyZjY5NiJdLCJkZXNjcmlwdGlvbiI6IkVnaXMgVTJGIEJMRSBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwiLCJiYURlc2MiOnsic2VsZkF0dGVzdGVkRlJSIjowLjAsInNlbGZBdHRlc3RlZEZBUiI6MC4wLCJtYXhUZW1wbGF0ZXMiOjAsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwiYmx1ZXRvb3RoIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCYkRDQ0FSR2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakFkTVJzd0dRWURWUVFERXhKRloybHpkR1ZqSUVOQklHWnZjaUJWTWtZd0hoY05NVFl3TWpJMk1EZ3hNVEEyV2hjTk1Ua3dNakkxTURneE1UQTJXakFkTVJzd0dRWURWUVFERXhKRloybHpkR1ZqSUVOQklHWnZjaUJWTWtZd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFSUDNBRTZWczV0RkJDSU1leG1kWGlSRmM4UWN5VHJjNm5sMWZFb0JLd01kQk10amYvdnpQanJyQWl0azVRMk9qTzlZTnkyNkNpNFRNSVlJd3I4WUJRb28wSXdRREFkQmdOVkhRNEVGZ1FVeUltcjBCWW51WTB2ZkJ6WjFkRnRMUUppOXBZd0h3WURWUjBqQkJnd0ZvQVVNdXJpUC9DMWlGZzR2cUJHMTVrNHZIaE9zM2d3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUpRTU82bjZQSTlFUFl4Nk1qdXNJRm83R1BCMVk4WXB6K1VCbVVqNkNVbDJBaUVBaDBFMm1wYVRWVFJwMXBhV1VsSHZuWUdCdTNTMDRIcmQzN09SMGxYb1hSMD0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTWdBQUFCcUNBWUFBQUQ1akI1N0FBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc0lBQUE3Q0FSVW9Tb0FBQUJ6WlNVUkJWSGhlN1owSFlGUkZHc2YvNmIwSFFraWpTSkVpZ2hwQWxONmJJQkE2eWlrSW5BVVZEanp1UEUrOXBsaG9LaXJxSVVWQUZGQzZpQ2pGQStsSWs2YVVRSUJBRXRLem0vdStlZTlsYTVMZHpTYlpsZm5wc0p2WnQ3UHo1czEvdnZubXpjenpLQ1lna1VpczRxbStTaVFTSzBpQlNDUmxJQVVpa1pTQkZJaEVVZ1pTSU5XSUhCMXhmVW9keGNvNWZ4NnBxOVpDbjU4UER3OFBOVmJpRExqSVBieThrUGpJS1BoR2hxdXhFbGVrVklGYysyRW45ajgyQVlVWm1lSmlTcHhIc1U0UEx6OC9QTEIxTFlMcTExZGpKYTVJNlYwc05ocHNPV1J3ZnZCVVh5VXVUeGsraUhJUlBUdzg0ZUVwZzFPRHNWZ2tMbzNkVGpyM3lHU3dQMGpjazlKOWtPMjdzUC94aVNqS3lJS0h0K0tEaUVQNWdoY1ZvVml2RjNHU2NpQXI0ZW5ycTc1VkxFYXhUa2R4NUlOOCt6V0M2dFVUY1JMWHhENkJrQ2k4QWdNUjJxUXhmTUxEcFVoc2dVcjMycmJ2UmVNaUJlSisyQ1VRZldFaEF1c2tvY1dzbVFpN3R5V0s4d3RFdk1RS0plNkZCelkxdkFzZ1VXaWpnVklnN29QOUFxbFhGeTNuejBaWTgyWWlUbEkrRzVJYW9iaXdTQXJFRGJIL1RqckxTWGF0YklLTFNyUS9WcHNnaVRzZ3A1cElKR1VnQlNLUmxJSDlQa2hkOGtIZWV4dGhMY2p4TktJb054ZFpQeCtEdnFDQTNOTGI2d1pZTWYzbjRlMk5pUHZ1S1JtcFlrVEJVdkZ1VEdvc2hzYWxEK0orT0UwZzJXZk9ZdStqNDVGM0pRMmVubVNZYmhlTlVPbnB5U2Z6all4RXgxMWIxVWdGS1JEM3gya0N1WFhxRFA0M2FBVHlVbE52djhtTlZPRjlvNlBSNWVoZWszWkJDc1Q5Y1o0UFFqWER3OHVUZ2pjOHFTSjRVcGZqZGdoYzZibDdKVjdWb3BEOGZwQk91a1JTQmxJZ0Vra1p1TFZBMkgwcUswZ2tGY1Z0QlNJRW9OZERuNWRQSVE4Nk5mQjdQYzhSbzgra1NDUVZ4VDBGd2haQ3A0TlBSRGdhL25rcUdyNHdGWTJtVDBHakY2YUk5M2RNL2lOOG9pTEZNWHlzUk9Jb2Jpa1Fydkw2b2lMRXB3eEJnK2VlUW9Qbm4wYURLYy9RSzRlbjBXakduMUQ3NFlmRTZqMXBSU1FWd2YwRVFoV2U3OGNFSlNVaWFkd2phcVFsaVdOR3dDYzhWTFVpYXFSRVlpZHVKeEMyQ0o3ZVhvZ2JPaGdCdFdQVldFdUM2OWREVEk5dVFpRFVJVk5qSlJMN2NDK0JzTzlCWGF1QXVEalVmcWl2R2xrNmRTYzhydmdpOUIySnhCSGNSeUFzRG43UkY2TkdsNDRJYm5pSEVsOEdRUTBiSU83aEFlQjE0WEo1c01RUjNNcUNjSGZKbHl4Qy9JaWhhb3daWmowcG52b1JOMlFnL0dwRUs3NklSR0luYmlNUVVmZkpDc1NuUEl5dzVrMUZuREZwbTdjZ2RkMTY5UzhENFMxYklPcitOc0tDeUJFdGliMjRqMERJaitEN0h2SERocWd4Qm5UNStUZzk2eDJjWDdpRUxJVmxWeXArUkFxOC9QeVZicFlVaWNRTzNFSWczUExyQzRzUTI3OHZRcG8wVm1NTlhQMW1LNjV2MzRYMC8vMkVHM3QrVW1NTlJMVzdIN1VIOWhNaWsvS1EySVByQzRTZGMvSWYvR3BHaTBwdUR0OFRPYjlrR1R4OGZhREx5Y0c1ano2bDc1aGFFWjZHejhQQ1BzRkIwaGVSMklYTEM0UmJmTzRheFhUcmpQQldMWlZJSTY1OTl6M1NkL3hZc2o0amRkVnFYTisxVy8zVVFHVGJaTlRvMmhuNmdrTHBpMGhzeHJVRndoVlpYMHorZ3k5aUJ6NEVUM28xaGljbVhsanhKWFM1dVhRbWRDcnF4dEFYbHF4UWp6REEwMDVpQi9TRFQxaUljUGFsTHlLeEJaY1dDRmRoWFg0ZVlucDJSNDFPN1pWSUl6S1BIa2ZhdW8xaVJWOEpYdDVJMi9RTjBuZGIraUxSSGRvaHVtTjc2bVpKWDBSaUc2NHJFUFk5cUtYM0RncEMwdVBXNTF5ZGZlOUQ2UEx5eFkxQXRoeDgzNE10QlQvMEozWGxhZ3Qvd3pzb0dMVjY5NlN6SmtHeEZaRkl5c0ZsQlNKYWVLcmd0ZnIwUkdpekppTE9tS3ZmL1lDMHpkL0NrNXp6RXJRdGQ4Z3B2N0Q4YytTY09hZjhiVVRjNEFHSWF0dGFPUGZTRjVHVWgyc0toQ3N1Qlg1c1FLMytmZUFkR0tSK29NQ1c0ZkxxcjZETFVYd1A0NzJvaENXaHVLTE1MUHo2MzBWcXJDbHNrY1FPSStydlNDU2w0WklDNFNyTElvaG9rNHlZN2wyVlNDTnU3RCtJeStzMkNVdFJHcDUrZnVUQWY0R2JCdzZxTVFhaTJyVkZ6YTZkeEwwVktROUpXYmlzQmVHNzQ0bVBqaEwzTU15NXZHWXQ4dFBTaEtWZ3VLdGtIQVRzaTl6TXdLVlZYMWxZQ1ord1VNVDA2azdmSjh0ajlwbEVZb3pMQ1VSVWNtcloyWExVNk54QmpUV1F2bnNQTGk1ZExycEk0czU0R1lFZDhVdkx2MFRXMFJQcXR3M0VEdXlQME9aTnlWTEpPVnFTMG5FOUM2SW5nZEIvQ2FPR3dqc2dRSTAwa1B2cmVZUzBhSTZhTEtBdUhjc01OYnQxUVhEakJzaTllRkg5dGdIdndFRDZqZUhRNTVFZkl3VWlLUVhuYlQxNitneDJEeG1Gdk5RcjhPUnVrWkhqYkN2Q2V1aUtFSm1jalB1V0x4VFBFamVGcytwWXV1SmJabmtxdUhFVGU0YU5Kai9sTUR4OWZFeWNmVnNSeFVlV3lqY3FDbDBPbTk3QkZ3VkxuOHV0UjkwWDE3SWdYTm1LUFZDcmYyOHI0bURzcjhDTXFQaFdLcjh2enc0ZVBsU0lVdnkyUkdLR3l3aEVXQTlxaVVPYk5rYjhrSUZxYk9YRHU1K0VObTlHdjAyL0wwVWlNY04xTEFoVlR1cnZJVDVsRUx4RFE5WEl5c2NuTkFTeGZYb3BkOWFsUUNSbXVJUkFOT3NSM0tnaDZqenhtQnBiZFNTT0hZbWcrblVwSDNKRVMyS0tTempwSWd2a3VFWjFiSStFa1VQRisvSmFjKzRTZVFiNm8wYjdCOFN6MjQzaENZN1h0KzFBMGExYkpmZEtTb1h5eWI5MC91TkZ1TDU3anpqZUhtZGQ1RjA2NmI5YlhFY2dGUGp4YmJ6b1NhbFpLaUlaeTdRNEwwRjFFdEYyMHhvRTE2bWp4aXJrcFY3R2pwNFBJZXZvY1RGZHhSTCtQZlV0UTNsbGtZbDVYZlJlQ2tTaVVlMWRMS1dDVVJlTG55Tk9yVGZQdVBVT3BoQkNJU3dFdmhFUllpMjZiMlNFUmZBT0N4VVA2ekhIdzlPTC9CajZycFh2Y0ZvKzlNcHBpOS9nM3dvS29wSWdTOEtXaXlwN0tXMkc1RGFrV2dXaXRiN2U0YUZvOXRhL2NkZXMxOUY4MW1zaTNEVjdwdGlJMmlzd1FBaklhZER2K1ZGcjMzRDZGUHFOTjBwK3I4V3NtYmp6bFJmaEYxdUxoQ0pGSWxHb2RndkNjNjU0NUNweDVEQ3hZMG5DOEJRUjRvY09SbUJjYlJUZXlyYld3Nm9RdkFJeE1DR09mbU9RNGZlR0RVYmRjV01SMDYwTEhVSGlrQUtSRU5VbUVHNmh1Vi9PSTFmMW5weWd4aHJnWjMyY2Vuc2V2ZEVMdjhCcFVEZU83NkNmKytBVEZHV1QrTXlvTzNFOGZLanJ4WU1BVWlTUzZyTWdhdVdMNmQ0WmZ0RlI0cjB4RjVhdFJQYXY1OFVBZ1RNTkNEdmd2TGxEeHNFanVMN3pSelhXUUdCU1BLSTdkU1NmcU5ERWo1ZmNubFRQS0JiOXBMNUlCLy9ZR0NTdldJVGdPK3FySHlnVVptVmhWODhCSWszeEJGa3JhWEZlQXFpYjFQcUxwZFJkU2xCakZmS3ZYTVdQZzRjaisrUXBxNk5ZZk1vOFloYVJmQS9hcmxtcFRIczNJdnZNT2V3YWtJS0N0R3VLUU1zNEYxRjhsVFNLZFpNczNZOTdkaU1yTTRzTW45S1c4VFBaUTBOQzBhSERnL0QzOXhkeHRsQkE1N3ZsMisrUWsyTnFOVG43UmJvaTNOV3NHWm8wdVZPTkJVNmMvQVdYVXkvQnkwdFo3MC8yWGxqVnBrMmFJTXFvUWN2SXpNVDJIN1lqaHl5K1p3VXN2WTU2Q3Z6N3pab2FWbzhlUFhvTVI0NGVoWmZaVUwxT3I4Tjk5OXlMdW5WTlJ5L3RKVGMzajhya1crUlIzclZyek5kTVI5ZW5iZXRrSkNZbVZvOUFSQVZsMzRQNi9TM212S25HR2toZHV4RUhKendsS3BKV3FjeXBpRUM0VnZDTlNVLy9BSExPWDBPdGZyM1ZEMVRvczhOVFhzQ0ZKY3NBNzdJbk1WYW1RSTRlTzRieEV5Ymk3TmxmNFUzNVlBb0xDOUN3WVVNc1c3b0lNVFZyaWpoYldQTFpNa3liL21kVmFOcjVGQ09mcmtPVE81dGczcHhadVBQT1JtbzhNT092TCtLelpTc1F5SU1rQko4bWkreTllWFBRdVhNbkVjZWNKQ0VOR3prYWFXbHBKV0t5SHlVZms1OTVHdFAvTkVXTkF6WnMzSXduSms0U1pheGNBdzdGVkFhRkdEUndJT2JNNXJwVCtyVXBqMisyZkl2SHgwOFFqWTZIaHlKQ0hWMm5nS0JBYk5tNFRnakVWSnBWQVZkT3FpRDhiSSs2azhhcmtRYUtzbk53N3YwRjBOSEZZSCtoVXVEQ3ByUjExSnFlbmI5QVdCTVQ2TE9FVWNQZ0U4bVBUcWpPamVhSzRlWHRTOEdiQk9LbEJub3ZoR1o3eFZpNGVERmVmdVVmUWh6aSsycGFuQWEzd3ZQZm5Xc2lEaVl2cndDM2J0MUNObDBQSldUVDM5a29vQXBrRE5jcmJ4S0dhUjd0RGNyM3pTMUZ6eDdkMExMVjNmVE9ReHlqSGV0TGpkNk9uVHV4ZDk4QjVVQUh5TW5KeGNKRmk0VzE4UEh4RVdsN2NmbyszdWpmcDQ4UUIxUGxBdUZXbFIrZnh1czFRdSswM0VZMGZkZVB5TmgvVU56ZmNMeHRLQjl1a2JqVnlEenlNMjVZMlNLSU42a0xiZEZjaUxrVUkxc0ZLRGN0dWV2Q2xadURrbS9iYjJZZVBIZ0lNMmUrSlZwb3JnaGFHdHhxK3ZuN1llcVU1OUNnZ2VXakpEeXAyK2xGMThBMFdKdGxZSmxIZTRQMmZXdm5OSGJNR0JRVkZZcjM0amc2bnZOeTQrWk5iUDVtaTRoM0JMYk9lL2Z1RTRMVDhzQzlpdkR3Y0hUdnppT1pDbFV2RUJLSFAzVU42b3ovZ3hwalFFLzkwRk52ekJGRHY1UnJMaEgxazBxQ0xyZ3VPeGZuRml3a0lWZytaS2YrVXhQRjhseXhJWGExaWNSeHVBOC83Yzh6a0o2ZUxpcVZxQVIwSGl3T1Bwc1haN3lBaHdjTVVBNnVFTlFyNEo2QmcwRkpRZnZIbFBZUFBvaTJiZHFRU0F6WFJ4UFNpaFdmaTY2ZEk3dys4MDFra2EvTDVhTEJYYmUyclZ1alMrZk9ha3dWQzBRVUJsVzJHcDNiSTZTeHFVbG4wbmZ1d3MxOSs4VW9VeVZMb3dRUE1xblhkK3pFalo4c3pYVmttMlJoNlZqVVZxNmRTMU5ZVUlpWFhuNFZKMDc4QWo4L1AxTngwT3VvRWNNeGF1UUk5V2pINGZUWU9yR2o2MmpJNVZkeW1BdFZTMkZNZUhnWWVuVHZWcEp2RG53dVhMRXZYa3JGMXEzYjFDTnQ1L1NwMHpodzRJRG8xbW5sd3FHSWVndERVd1lMcTZKUmRRTGhURkFHL0dKcUluNTRpaHBwZ085N25KbnpyaUlNYmlIVVZxSXlFUzBSV2FxQ0d4azQvZlljTmRZQVQzMUplblEwdkVQY2E5TnJyblRQUGo4VjI3ZnZvTk5UdWlWYUplQStkOS9ldlRGaitqVDE2SW9SR2hxQzNyMTdZZENnaC9Id3dBRU9oVUVVQmc5K0dFMnQ3SC9HMTZoZnZ6Nm9YYnUyeUw4eGZuNitXUER4SjhqTXpGSmp5b2ZUK0hUSlV1U1JxSTE5SHJaUWQ5OTFGenAyTk4wSG9jb0V3cWZHbFN3aXVaWEZDQmlUdm1zM2J1NC9SQjZmb3lNaGpzRXk5Q0lyY25YYmRtVCtmRXlKTkNJeStWNUV0VzBqbkhYekMrU3F2UHZlKzlpeTlUdjRCL2lYdEpCTUVYVWgyTitZTVdNNkF0VFJxWW9TV3lzV3I3N3lkOHlaOVJiZWZ1c05od09Qb3ZVajU5Z2FzYlZxb1hPbkRrTGN4bkJMZi9iY09YeXo1UnMxcG54NFJIRGJ0dTlGbzZIQjVjT08vK2pSSTlVWUExVm5RY2hFOG16WnVwT2VnSGVRNmZSMEZzNzV4WitoS0NORFdBN1JzbGNWcWhXaEpnUm41czYzdEJUa3A0Z05KS2lsNUhPZzBsUS9jRTFXclY2RDJYUG5JVGMzUjFRQ3JTeTVoYXhYdno3bXpuNGJ0V0ppUkp5ekVBNTZCUU8zNW1WZDl4SERoeUVvTUxDa3E4WEhjbUMvWWNuUzVhS2Jad3RyMTY4VG9pcHh6Q2t0SHI1dTJmSnVkT3hndVl0T2xRaUVNNkhMTHlEZm94TWk3bTJseGhySVBuTVdWelpzSm4vQWFCdlJxb1phbzJ2ZmIwZkdvY05xaElHSTF2Y2h2RVZ6TWZybXl2TDRZY2QyL1BOZi94SHZ1WFhWS2dEZmhBc0pEcVp1MVovUXVKR2w3K2NPTkdyWVVIUi9qSjExaG4yUkkwZU80TkRoSTJwTTJTeGU4cGtRcEZZMkRLZlpsUnp6T0N1UEZhOThnWEFtU1BVOHY2bU9sVTJvZVJYZmlYLzhSenpLZ0hJdE1sN1Y4Ryt5djFGdzlhclZSeWY0UmtaUzNoOVZMSTFhcUs3R2I3LzlobW5UWnVEeWxTc1dJMVk4dlB2czVNbm8ydFV3Zk9sdWNCZG83S05qeEgwS1BpOE80cnBSdUVFOWo5VmtPYmtoS0l0RjVIdWN2M0JCWEd1dG5uSDUxS2haQXdNSDloZC9tMVBwQXVIcUpPNTdVQitTTjJvejU4YWVmVWpmOFQreFZXaDF3OU5hTHE1Y2hYd1Npamt4dlhzSWYwUlBsbEJyZVZ3Rm5wTHkxNy85SFJjdVhoSVZTWU12UHZmYng0OTdESStNR2FYR3VpK3RXcllVVTJLTWZSR3U2QUgrL3NLdk9ISFNjb05BamN5c1cxaXo1aXY0cUpaVm82Q2dFUDM3OVVXTjZCcHFqQ21WS3hDdVNCUzh5UGVJSHpsVUxINHlodTg5WEZ6MnVaaDdSYmsyeVhoVkkzNmJXaGIyZzA2KzlwWWFhMHFkY1dPVmgvaW81K1VhRkdQNmpMOElwOXhYM2VtZXowVVRSOTgrdlRIbHVjbGtWYXFrTjEycHNHVWNscElpS3JuZXFQeUZzMDRXOUt1dnZsWmpMTm0yYlJzT0hqb2swdERncmhWM3EwYVNmMU1hbFZwcWZBcnM5SWFTNnEwOUFDZnJ4Q2xjL21xOTBuVnhKaFhRbVFkWnNyVDFtNUI1eEhKRUsrS2VsbUpEYlY3OVdOM3k0SDQwODk3N0M3QjIzWHI0cVphRHhjRVdMcDhzWGRzMnJURnR5dk1pL3ZkQ3A4NGRrSlNVQkQzVksyTkw3a3ZkeU9VclZ1THExV3RxakNrcnYvaFNXQXN1SDYyTWVEaThlNCt1cUYvUGRMS3NNWlZ2UVlqNlQwKzBPdW53L0tLbHlGTTNvUll0dU4ydzcyQ1pMbTk0N1VoNld1RVZYRXNYenpvMHg1OWFtMFRlVkVKcmpZMHVVTlhpQVIreUZqeGlOV3YySE9GamFIbm5DeTlHck9yVndac3pYMGRpa2pLbnFMTEl6YzBWTGZPZW4zNFNVemNjQ1QvdDNTdStmOEhLRnJIbXhOU01RYytlUGVpZHdjbG1lRlRxOHBYTCtIcmRXalhHQU05TTN2THRWbkVNbzMyUHU2TkRCZzB1c2J6V3FEeUJVQ1o0Ymt0STB6dmhIUmxPMXVJWGNaK0JBNzlQMjd3VmFSczJ3NHY2ajQ1VVp2b1MrUEVGV2NkUFVEaUp6S09VTm9Xc1l5ZkVvOW1LOHd2Rk1YYkRsWXkrZG1uMTE3aTJiVHZsbGRJMnlyZC9YQng4b3lMcHdPb1JCNWVWbDdjbmpsQitYbjcxVlhFWDJuZzRsN3RXMFZIUmVPbkZ2NksybFZFWlozUHgwaVU4TS9sNVBETDJjWXg5Zkp4ajRiSHhHRFZtTEZaOC9vV2FhdG1NSGpVQ1FVRUI0bHk1c212bjdrbU41YWJOVzVCMjFYVDZ5ZUxGUzhXeGZKeDJMSGMvNzcrL0xab2FUZkczUnVVSmhETkRGNDQzbXo0dzdrbnNIalFDdTRlT1ZzTGdFVGo0NUROa1BhNEt4OWdSMkNJVnBxZmowTlBQaS9SMnAxQzZISWFNeElFSlR5TW5OZFdodEVVaFV0cDVGeTlqLzRTbktOOGpEZmtlTkJ6N3gwMUNFVGw4ZEtUeWhTcUcrOUJYcWR5bVQ1K09HemN5eE14ZTdhSnI1QmZraTNsdFZRRlhQR1dtN3kweDI5ZXhjRXZNaXlvMG4xVmRDanpOdjIrZlBtUXBUWjExdHFTSERoMFdNd2cwamh6NUdXdStXcU1PWGloV2h3UFAzaDJhTXNURUo3RkdwWGF4V0NDOC9qdi8yblhrWDcrT2d1dnBJdkRmUlZuS3doM3ppMnNyL0QyMlVJWHBHWlMya3E1SW0wSmgrazIrY2hWS216cjU1TEJubXVhYkEvVngyYThTS1R1WWZrWGd2TjNNeU1DbDFNdFdMeTViRTY1d2YzdjVaUkxRRFRXMjh1RDhjTXZOZWFsbzBMcEF0akNNS2pjdjNHSkxvSFdaK1B1Wm1abjRlaTM1dFNvclZxN0VqWnNaSW4zdGNuRVhsQmQrZFd4djZSZWJVNmtDWVZnazJqUE1qUU8zMG81V1lBMytQaS9tc2tpYjRweVNObDgwczdSRitweDJCZE4zRkpFdk5XaG9yU0lIanVjSys5dHY1L0h5Sy85RU5qK21ydEl4L0w0alFVbEIrOGMybWpadElsYjk2WTEydk9Gelp5dXk5YnR0T0hQbXJHZ2d2bDYzUVl4eUdjUE8rWmpSb3hFUkVhN0dsRTZsQzBUaWZNd0Z3aTBpZDNVWXJuRDhFVmVVRFpzMll0bXk1U0src3VEZjQ2NE81OEhSd05ORmVKNFlMNlcxRmU0eThmMkxnQUEvY2U2YTBOaUs2SFJGZUh2MkhLeGR2NTY2bzJrbFpjWEhzTVhoS1RlOWhLTmZQcFVnRUZYUm5PSGJJWWh6TGZtbnl1Q0x6UldENXlCMTc5WVZDUW54b3JJeGloWHhGTmJqblhmbjQreFp5NmY5T290QS93QzBhblUzMmxCcjNqcjVQb2RDR3dvOEpKMWd0blM2UEhnYWZFSjhRa25qd1BDNTgvTGs3N1o5ajduejNoTmRLeTFlRTlHd2xNRWtMTnZXOHp0M1RmcmdVY2k3ZkZsMFRXNHJxRlh5cGY1d2w4TjcxQWdGUlRjVlc1TSs2YW5KT0hmMnJMQUlHbnpKbE12bWdiNTllMkhtZi82TjlSczI0cm1wMDhUOUFSYUhWaUc0ZGU3VXNRUGVuUGthSWlONTlNMDJwazU3QVl1WExFVVE3enBKY0Zvc3hnOC9tSThlSkVnTnJwenNwUE9OTzYybGRnVGVFTUxmMzArc1hiR0hCUjk5akZmKzhXOFNnckk2a2RIS2g0TnhXYkQxNElia2cvbnZpcmxkdHVBMEM4S3I3bmdqQnA1VHhXczdicmNncHFDb1pWSFo4TVhtZm5Udm50M3hLam5qTEI3dWJuVHIwdG5FYWVXS3dSc3BjR3Y2enZ6M1JaeXo0UW9ZRWhLQ3NOQlFoTktyb3lFc0xOUnVjVEE4Ulo2bjhITkRZSHplSERSeGFMQ0Z2Yjl0RzV2RndUak5naFJjdjQ0TGk1ZWg0RmEyU2FadUM2Z0l2UUlDY01lelQ2b1JDcUpnNlRObldoQytYQnp1YWRVU0gzMzRBWUtERGMrUVAzZnVIQ1k5K1F4K1BucFVITS9YZ1k5bDBRU0hCT085dVhQUXJ0Mzk2dEZsWTZzRmNRWDRadWxicythVU9oS21WSEhLZjBFaHZ0KzZCWFhySkNrZjJJRFRCQ0t4cERJRXdpMWxmRndjRm42eUFQV3NmSmNuN1QzK3hDUnFMUXZWb1UxRFY2dDU4K2I0NUtNUEVCMWx1VkdmT2U0a2tMTlVQa09HamNLMWExZE51cUlhbkhkZTg5R0ZMT3pISDlwblNlVW9scHZCRnpzZ0lCQWhvV0ZxakNrZE9yUVhkNXE1SlRWdSszaW84L0NSSTJLZCt1K051dFJvUC9oQVcvS0hETVBHR3Z3MyswbmNqWHRzck9WeWkvS1FBbkZMTEN1Q01ZLzk0VkhjZlhjTHNocksxSHkySWh4NDFkNjZkZXZ4OWJwMTZwRy9IL3IwN29Yd2lEQWhCdk95NFdIb2xpMWJvbFVyeThWNjVlR2dRRzR6SDZNaVZJTS9GbGU3Tmw3OHl3dmtuNFNRLzJHWXI4UldoU3ZRNjYrL2lXUEhqNnRIL3o1NHNOMERhTk82ZGNsUXR3YWZPMDhyU1JreUNJRlducnRmSG5ZTGhLOTN0UzZOZFNOWUd0WFZsTFM0cXdYK09Ha0NYUy9EVmo4c0VyRjI0dGRmeGI1UXJrbnBsckVzZUJPODJyR3hKdGFEMy9NQUJjZjM3TkZkamJVUHU1eDBkaTU5SWlKUXExOHZCTVRWRmp0OVNFcUh4Y0dGZStyTjJXTGVHRSs3WVNyaXBMT3oyYkJCQXl4ZXRCQTFhMFNMdU5MZ1RhK24vK1ZGckZxMWl2d1dRK3ZKbDV4Yld0NEhkK0tFSjlSWVUyeDEwcStucCtQTEwxY2pPeWZiNmdpU3JYQitXaWNuaTJGWVJ6aDkrZ3llbVBoSG5EcDlXalFDM0Jnb0RRUHc3RE5QNGFrbko2bEgyb2Q5QWxFUDVRVkQ5Sy80WDFJR3BCQXVNeTgvUC9IS0Y0MnBLb0V3eDQrZlJNcUlFU1NXVytKbUd1ZUI4OEticEVXRWgySCtPL09Rbkh5ZmVyUUJXd1Z5NHVSSkRCOHhHbGZTMGtURmRBVHlxSkNmbDQ5bkovUG0xVlBWV1B1WVAvOER2UGFHWWhXMUFRb2V1VXRNVE1Cbml6OUZYRnljK014ZTdKSzhkb0Y1TjBMdVpubjR5bEJtb0RMaTNlV054VkhWTkc3Y0VOT25UaFg5Y0c1UkdjNExUNU5QVDcrQlYvLzVMMlR3ZGtzT3dwV1JwM2F3Z0IwTzZ2ZTlyQ3grc3dXZXZieDY3Vm9TUkpGSk9mT28xckFoUXh3V0IrT0FEMktZVFNxRDdjRmgyRkNUd0xRZ291eTAzT3lnY3VDMUY4YnBjSXUvNzhBQkxQam9FL0czbzFnN1gwZURJK3pZOVNOK09mbUxhQVMwTkxqTEZoa1pnVDU5elI1dFlTZU9keG9sVllEaVlKc0gzaXBKcStTMndFSjRjdEpFTkd2V1JGUWNRenJGNHRFRnMrZStRMzZLNVJKamQ0Q24zUENNWmU3K2FUNFFueGV2MmUvY3NTUHFKTmwrMTl3YXBRcUUrOG42M0R3VTVlYWdLRWNHWndaZFRxNll2OFdPZTFuNCt2aWhWa3hOSk1USElUNnV0aHJpRUVOeDVzL1NLSS9ZMkZqaHJQS0dCN3pQclpaZVFudzhZbXZGWU9ueUZjTGgxdUMxNXZ6MEtPNSthWUgzd09WK3ZURThTblRyVnBiSmNYWUgvaDBLWE5udFplKysvZGkrYzZkb0JEVHJ3WGtLRFF0RDMzN1d0eksxaDFLZGRGN2JmWHJlZk9oSUlOcm9pOFE1OE14VkQrcDNOM2xwaG5nTVhXa1VVR1hNek1nVXJiNTI4Zmx5OFlOZW9pSWpIUm8xU3VNVmtXdzk2TDNXb1dFbm1aZm9Sa1ZGbGt3WS9HN2JEemgyL0pqd0R4ZytYcThyUXMvdTNaQlV4L0RvTTE2VXRIYjlCdVNROEQzVnB6VFpDNmZOVDNiaWFmUEo5MWtPR0pURm1FZkhVbDYzaTQwWHVJeTRmQXJJbW5TamZIN3c3anlyejlHM2gxSUZ3bzhwMEJYWXR0K3B4REY0c3p4M2JIeTR5ampxTHppVDR5ZE9JR1hvU0dTUkJkTkcwTGpyeU05aFhMSDhNenh3djIwVE04dWlkSUZJSkM0TUMrRnZMNzJDUlV1V21Feks1R0h3MW0yU3NXTHBFdlhJaWlIN1RoSzNKUFZ5S25iczJrbENNYlR2L0o2M0llM1RzNWNhVTNHa1FDUnV5ZWRmZkNtZXNPdkQ5K1JVNjhHVE01czJiNDVldlJ5YlZtSU5LUkNKMjFGSUR2MnlaWitMbTR1TTVoUHg2RlduOWcrSzNSZWRoUlNJeE8zNDc4SlBjZW5TSlpOUlBCWkhqZWhvREI5bStYaS9paUFGSW5FcmVGckp4bzJieFh0dEpFMTByOGc1SC9CUWYwU1RTSnlKRklqRXJkaTArUnZzM2JjUE9yMWUzQi9pd0hmUjR4TVRNTHlNeHhnNGloem1sYmdWL0lEUzdUdDJ3Sk5uSnF1M092UEplanpRcmgyZUdQY0grUG82OTBGTVVpQVNTUm5JTHBaRVVpckEvd0ZBenJnV1duZDBqQUFBQUFCSlJVNUVya0pnZ2c9PSJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA5LTE0IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJVbml2ZXJzYWwgU2Vjb25kIEZhY3RvciAoVTJGKSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTgwMjIxMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTA5LTE0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0wOS0xNCJ9LHsiYWFndWlkIjoiYzFmOWEwYmMtMWRkMi00MDRhLWIyN2YtOGUyOTA0N2E0M2ZkIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJjMWY5YTBiYy0xZGQyLTQwNGEtYjI3Zi04ZTI5MDQ3YTQzZmQiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBGSVBTIFNlcmllcyB3aXRoIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMjg3MDYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyIsImVkMjU1MTlfZWRkc2Ffc2hhNTEyX3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo2LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJREhqQ0NBZ2FnQXdJQkFnSUVHMEJUOXpBTkJna3Foa2lHOXcwQkFRc0ZBREF1TVN3d0tnWURWUVFERXlOWmRXSnBZMjhnVlRKR0lGSnZiM1FnUTBFZ1UyVnlhV0ZzSURRMU56SXdNRFl6TVRBZ0Z3MHhOREE0TURFd01EQXdNREJhR0E4eU1EVXdNRGt3TkRBd01EQXdNRm93TGpFc01Db0dBMVVFQXhNaldYVmlhV052SUZVeVJpQlNiMjkwSUVOQklGTmxjbWxoYkNBME5UY3lNREEyTXpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUMvandZdWhCVmxxYWlZV0VNc3JXRmlzZ0orUHRNOTFlU3JwSTRUSzdVNTNtd0NJYXdTREh5OHZVbWs1TjJLQWo5YWJ2VDlOUDVTTVMxaFFpM3VzeG9ZR29uWFFnZk82Wlh5VUE5YStLQWtxZEZuQm5seXVnU2VDT2VwOEVkWkZmc2FSRnRNamt3ejVHY3oyUHk0dklZdkNkTUhQdHdhejBiVnV6bmV1ZUlFejZUblFqRTYzUmR0Mnpid25lYndURzVaeWJlV1N3Ynp5K0JKMzRaSGNVaFBBWTg5eUpRWHVFMEl6TVpGY0VCYlBOUmJXRUNSS2dqcS8vcVQ5bm1ET0ZWbFNSQ3Qyd2lxUFN6bHV3bit2K3N1UUVCc1VqVEdNRWQyNXRLWFhUa05XMjF3SVdieGVTeVVvVFh3THZHUzZ4bHdRU2dOcGsycVhZd2Y4aVhnN1ZXWkFnTUJBQUdqUWpCQU1CMEdBMVVkRGdRV0JCUWdJdnowYk5HSmhqZ3BUb2tzeUtwUDl4djlvREFQQmdOVkhSTUVDREFHQVFIL0FnRUFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqdmp1T01EU2ErSlhGQ0x5QktzeWNYdEJWWnNKNFVlM0xiYUVzUFk0TVlOL2hJUTVaTTVwN0VqZmNuTUc0Q3RZa05zZk5IYzBBaEJMZHE0NXJuVDg3cS82TzN2VUV0Tk1hZmJoVTZrdGhYN1krOVhGTjlOcG1ZeHIrZWtWWTV4T3hpOGg5SkRJZ29NUDRWQjF1UzBhdW5MMUlHcXJOb29MOW1tRm5MMmtMVlZlZTYvVlI2QzUrS1NUQ01DV3BwTXVKSVpJSTJ2OW80ZGtvWjhZN1FSalFsTGZZemQzcUd0S2J3N3hhRjFVc0cvNXhVYi9CdHdiMlgyZzRJbnBpQi95dC8zQ3BRWHBpV1gvSzRtQnZVS2lHbjA1WnNxZVkxZ3g0ZzB4TEJxY1U5cHNteVB6SytWc2d3MmplUlE1SmxLRHlxRTBoZWJmQzF0dkZ1MENDckpGY3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFmQ0FZQUFBQ0dWcytNQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUhZWUFBQjJHQVYyaUU0RUFBQWJOU1VSQlZGaEhwVmQ3VE5WMUZELzNkNTl3ZVFTSWdTOUFRQVhjRkxBUVppOWZwZVZ6MXRZL1dUWnI1V3hwYzdXNWtuTGE1akkzWjg1c3JTMm5NMnNqdFd3WlM3SVVINEg0eENuRVF4NERBWkY3NFY3dXM4ODV2OS9sSW5CdlZKL0I0UHY5bnUvNW51LzVudk01NTZmekEvUXYwSGIvSXJYM1ZGS1BvNDVjbm00aW5VSVdZd0xGUm1aUVV1d2pGRy9OMWlSSGgxRVowTlJWUnVkcXQxQmQrMm5TS3lTL09oeXMwK2xrM2UvM2tROXF2RDRaVXRhNFZWU1V1WTBlaXB5aVRoQWZvY29PUlZnRHV1dzNxS1JpQWQzcmJjRXRqVGpZSW9mNldhSHNDbXpWUFdDTXgrY2doOHRMcVdNS2FNV3NVakxxbzJSdEpJUTBvT3ptZXJwUXU0ZXNaZ3NPTmtHeEg3ZDBrZHZUVDE3czRPTVU3Vkk4WmhqZ0dhTStBcTlpRU51OFBpZjF1ZHowN013dktXZjhHbFZvQ0VZMDRQQzVXZFRhWFlGYlI4dk52TDUrM0tnZmI1eE5NeWE5UmFtSml5bmFNbEdUVnRGbHI2YmE5dStwcW5FWDR1TXVSUmdqU1lFaHJON3V0RkZlNmxxYWw3TmZrdzVpbUFHSHluUHBiazhWbVkweHN0bnB0bEZDVkNZdHpUdUJOODNRcE1MalR0ZXZkUHpTVW5KN2U4bWtqeFozOWZYYktEZmxkWnFidlUrVFVnR25CVkY2ZlEyaVBIZzRXMTZVV1V3dnpiazE2c01aRStQbjBwdno3SlNldUF5ZXM4bGNwQ21hS3VvL3ArcVdyMlVjd0lBSFdydlAwWUV6aFhBdExBYnNzSGhwN2lHYW12eWlqUDhyeXFyWFVXWDlYb293eHlBdWZOQnJwNDNQT0JGWFpsa2Y4TURSaXFjcHlvd0F3cHV6MngrZld2ei9EdGRlOXNtc3p5Z3RjUjZDMXdiZHpCbDZPbHE1V05ZWTRvR2F0aEpNcmtURXgwakFSU0hBVnMrNXJZa1FOWGIrUWdmUExzUTZnWHlJbnNyZVFmbXBtN1JWRllmTDg2bjFmaVVPa1l2U2hrVVB4dmJ1a3pveTZLMWloTTFobzNYelc2RXZTZlhBK2RwaVdHYVdkK2RvWHpMem1Hd0tZRkxDQXNSQWxQQkFoTWxDRlhVN3RCVVZQcjhIZ1ZjSkhXcStGMDBwbHIrRE1UZHJQNHp2eFkxMWtOTWh4VCtTZVRHZytkNFY1TFFKaXR5VUdKTkI4VkZac2pnWUJaTS9JSS9YQ1RrajBxeURPcEYyQVZRMTdDSWpVcC9EblQxVWtMNUY1Z2RqK3NTMXdnMWdFM2dpZ202MGZDWHpTblBYYnlBUGJJWHYrSURwRTE2VGhhSElTOXNreWhsbU1FNUYzY2ZxQUtocTJDMEU1UEgxZ1lhWGFMUERrWkcwSERKT25LV0hwNTFJMHo1U091eDhlMVdBdVp6ZEhRclRrcDhUbWpYb0krbGEwd0dac3p1YnFiTzNpZlE2QS9XN3ZWU1lzVjNtUjBKS3drS2M0V0hpQmttUjhJM0NDZ0k4N29PTDRxelQ1UCtSVUpCZWpFT2dBUEs4aFlQemF0TStlSVRwMklPOXlUUW1lcm9tUFJ4eDFxeEFjc2lsZS91YlNlRWJjV1FHWUVDZ2hjTFkySHlLam9nakgyNWhNcGpwVXYxT3VnbGk0ZWgyZVJ3ME8zMmJKamt5dUNnTnpnMHZ6bFlNU2lTczB1b280TUc3aE1PakNFYVgxeUZFMG5TdmpCenVUbkVwSzg2WjhJb3FGQUl1Ync4a2c5QXJFYVJFV1NaSStqSDRYYnA2ZzlFOUVuSlQzb2FSekROK01VSkJRREhuNTZhOG9VbUVCdXNPeEJzL041K3RKRWJQa0FGRGo4VUd2T3MvSVd2Y1NnbEdCaHZTNy9GVFlmcFdHWWREWThmUEF4V1NBMzVzVEM0cDQrTG00QWFxSW9QZVF0ZnVmSzZKaDBaaHhsYnNVWE9TbVhOaWZENVpUQWt5RG9mYmJjY2x4bkE4V05BcXhDYlJOeWtoWHhRcGFEdzY3ZlhVWWJzaUcwS2h0djJvZUl2aDhyaFFNWU9jRUFxWEcvZUkrem5nT2M1eXhyOHE4MklBTTFjL0ZMRk9wbHF1NWVGUVhyTVp6R2NWQ2pZYkxXRzVJNEJUMWV1UnJsYnh0Tk90TWl0RERFaExYSUl5bkFBdnVPRVdFM1gzTmRBZnQ5NFZnYUc0MlhJUXQwWlg2UGVDRS9xUUZlOXJLNkh4N1lVNTBLdkg3Zlc0ZlMrcTdLS0JKeHNnZ0JYNXBTQUdoMWpJclZoNXpRNnczUmZhYWhCWG0vYUNiQ1pUakNVRlVUeVdacVc5cDYyTWpKUFhWcU9yUGdNTzROdjc0R2tmK293ZnROVkJEUW5qRkpxSFN3MTdwWHZoV1c1S1pxZS9RNDlOL1VTVENBVldvUVhGSUhCSFhYZTNGUHJVRHN1R0RtdEYvaEhLVEhwZWt4aGlBT1BJK1NKcTZTNkhGNEk5WVd6a0JKVG80NmlVTXpXcDhQaXIvUmlkdUx4S1lzU2tzVjh2TGxPUXZoR1gyWWxSME9CaEJqQyt1L2dFY3ZZMEFwSzdZazQxTnhqUFNRbldGSFRGNjZVcmpnZXZCOEN1NWErbDJ2WVNSUHR1VkRvNzNoaGRNU0huVVg3dFRqc1ZaR3hBbC9XcHRpT0lFUTFnbkwyOW1YNi90UjF0bWxrWWo4VzRYK0NTaldjVURHWTFOcFMvQzdoU0txaU1MTS9sMlFtU1daNzNEZHorZ2lvOEJDRU5ZUFE0NnFua3p3WFVicXZCa3hqVVFzV2ZaRmdidW8zckFmK3dON2pPTzkwK3lueDRQaTNMKzBuWUwxU2NoRFVnQVA0Z1BWLzdJZDFxKzFIU2htdUdrSXFXUlBneXhNRnFQOEhmalRualh3WTViUWZiSmN0Nk9JektnTUhvdEYvSGUxZWdzYXhIU3FHNndmZG1RNXg4TnlURkZxQmNwMmlTb3dIUjN5azUrMzZoRjd2WEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiYzFmOWEwYmMxZGQyNDA0YWIyN2Y4ZTI5MDQ3YTQzZmQiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsibmZjIiwidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwibWluUElOTGVuZ3RoIjo2LCJmaXJtd2FyZVZlcnNpb24iOjMyODcwNiwiY2VydGlmaWNhdGlvbnMiOnsiRklQUy1DTVZQLTIiOjIsIkZJUFMtQ01WUC0yLVBIWSI6M319fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0wMy0yOCIsInVybCI6Imh0dHBzOi8vd3d3Lnl1Ymljby5jb20vcHJvZHVjdHMiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgNSBGSVBTIFNlcmllcyB3aXRoIE5GQyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI4MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMi0xOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWUsgNSBGSVBTIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTAxMTgwMDQiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy43IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDItMTgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAzLTI5In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMGU4MDIwZDc4MmI2N2QwMGY0NzgzOWY0NDJkZGMyNDJkYmU0ZmMyZiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIwZTgwMjBkNzgyYjY3ZDAwZjQ3ODM5ZjQ0MmRkYzI0MmRiZTRmYzJmIl0sImRlc2NyaXB0aW9uIjoiVmVyaU1hcmsgRFQgRmluZ2VycHJpbnQgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTEyLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDZkRDQ0FpT2dBd0lCQWdJSkFQNGZTUlFwUnAzcU1Bb0dDQ3FHU000OUJBTUNNSUdaTVFzd0NRWURWUVFHRXdKVlV6RUxNQWtHQTFVRUNBd0NRMEV4RVRBUEJnTlZCQWNNQ0ZOaGJpQktiM05sTVJnd0ZnWURWUVFLREE5VGVXNWhjSFJwWTNNc0lFbHVZeTR4RERBS0JnTlZCQXNNQTFCRFJERVZNQk1HQTFVRUF3d01VM2x1WVhCMGFXTnpJRU5CTVNzd0tRWUpLb1pJaHZjTkFRa0JGaHhqWlhKMExXRjFkR2h2Y21sMGVVQnplVzVoY0hScFkzTXVZMjl0TUNBWERUSXdNRFl3T0RJek5UQXdPVm9ZRHpJd05URXdOakE0TWpNMU1EQTVXakNCbVRFTE1Ba0dBMVVFQmhNQ1ZWTXhDekFKQmdOVkJBZ01Ba05CTVJFd0R3WURWUVFIREFoVFlXNGdTbTl6WlRFWU1CWUdBMVVFQ2d3UFUzbHVZWEIwYVdOekxDQkpibU11TVF3d0NnWURWUVFMREFOUVEwUXhGVEFUQmdOVkJBTU1ERk41Ym1Gd2RHbGpjeUJEUVRFck1Da0dDU3FHU0liM0RRRUpBUlljWTJWeWRDMWhkWFJvYjNKcGRIbEFjM2x1WVhCMGFXTnpMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkxQUW01MERnQjk4MHJkSUlwNkhZTm8rbmZRZVVoUHNtNHM3OE5ST2VMTU9oZXVLbjhaeFBYREhEK1NLcUJIQW5YTmJ0b1E4ZzRjaCtxaVMrc1d2SnVPalVEQk9NQjBHQTFVZERnUVdCQlJEbldvMjRDMlBwRVN6VmJKUHoxWkZUZWJTSnpBZkJnTlZIU01FR0RBV2dCUkRuV28yNEMyUHBFU3pWYkpQejFaRlRlYlNKekFNQmdOVkhSTUVCVEFEQVFIL01Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lFU2trNzZrdEZuREJEeVNlYkpIdHczVGNKSVhUZk5vNU5nNEFqODhCSTdSQWlCdEViNW94dWk4U3pzVVo2d2NRUWpuNWFCNW5kMmFOSkJoWksraUZISEd4Zz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQTRrQUFBRERDQVlBQUFBdkJWVENBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBZ0FFbEVRVlI0bk8zZFRYSWJPYmFHNGVTTm1xdDZCVkt0UU9vVm1GNkJWVk5PSksvQXJJakxzZVV4QjVaWFlHbHdPUzE1QlNXdG9LUVZsTFNDdGxiQUczQi9hYWVaSk1XZmM1QUE4bjBpRk4wbVhSWi9NZ0VjNE9CZ1VQM3YvLzFhVmRWSlplOStQaDE5ZGZoM294cE1aa2RWVlIxNS84NzVkSFRiZWhBQUFBQUFJdnRGQWVKZkRyLzJkVlZWV1FjK0NoRHZxNm82YUQxcDZ6cjN6d29BQUFCQUdmNkg3M0c1d1dRV1ZsaHZJZ1NJRC9QcDZMejFLQUFBQUFCMGdDQnh0Y3VxcW81WFBtdmp1YXFxWWFmdkVnQUFBQUFhQ0JLWEdFeG00NnFxenRyUG1Qb1dJSmF3YnhNQUFBQkFPWDdodS96WllESUxLM3NmVzAvWUc4K25vL3ZPM2lnQStCVG5LcUpvR1ZBS2JaK3hMRkRJUFE3MEFFRmlnd1pMTjYwbjdIMllUMGRYM2J4TEFQaEoyQlA5M3ZBanliNW9HVkFZNndLRjNPTkFENUJ1S2hFTDFYeVpUMGNYclVjQkFBQUFJQUVFaVQvRUtGVHpvRmw3QUFBQUFFZ1NRV0xjUWpXbjVQRURBSUNJcUtJT1lHdTlEeElIazlsSnBFSTFvWkxwWSt0UkFBQUFBRWhJcjRORTdVT01zZm42TFpWTUFRQUFBT1NnN3l1SnR4RUsxVnhUeVJRQUFBQkFMbm9iSkE0bXM2c0loV3J1NXRNUmhXb0FBQUFBWktPWFFlSmdNanVQVUtqbUtSU3FhVDBLQUFBQUFBbnJYWkNvUWpXZlcwL1lvcElwQUFBQWdDejFLa2lNV0tqbW5FSTFBQUFBQUhMVXQ1WEVHSVZxL3BoUFJ6ZXRSd0VBQUFBZ0E3MEpFaU1WcWdtVlRDOWJqd0lBQUFCQUpub1JKRVlxVlBOUVZkVzQ5U2dBQUFBQVpLVDRJREZpb1pvaGhXb0FBQUFBNUs3b0lERlNvUm9DUkFBQUFBREZLSDBsTVVhaG1qR1ZUQUVBQUFDVTRwZFN2OGxJaFdvK3phZWpxOWFqQUpDUHg2cXE3Z3hmTFZrVkFBQmtyc2dnTVZLaG1pL3o2WWhDTlFDeXBva3VKcnNBQU1CM3hhV2JSaXBVRXlxWm5yY2VCUUFBQUlETUZSVWtSaXhVYzBxaEdnQUFBQUFsS20wbDhTWkNvWm9RSUQ2MkhnVUFBQUNBQWhRVEpBNG1zOHVxcWw2MW5yRDFkajRkZWE5VUFnQUFBRUJuaWdnU1Zham1YZXNKVzlkVU1nVUFBQUJRdXV5RFJCV3F1V3c5WWV0dVBoMVJxQVlBQUFCQThiSU9FbFdveG5zZjRsUFloOWg2RkFBQUFBQUtsUHRLWWdnUUQxdVAycUdTS1FBQUFJQmV5Zll3L1VpRmFzN24wOUY5NjFHZ1E0UEo3S2lxcXFNTlhzRTlFeHlBcjhGa050emdGM3lsTDhFMmxDa1Z0dFBVLzF1NzNhR0EzalovUC9RdFo2MUhmM2ErNFhXL2svbDBkT0gxYjZQZkdEOXRKOHNnTVZLaG1qL20wOUZONjlHZVduZGpVZkhWVG1OZ1VBOE82bzc0WkplMDZzRmtWdi9mdXpCUURRMWYvY05STGk5cmZCK2JlT1F6TFl2MnZCL3BHcWpid0hCTkhHLzdSaHYzWXRqQzhLajc4RkgzSW0zb0RoYnV6MVgzNnFOK3FwUUhmdXBqVDlYbUQxOW83N2U2WG5SOWJmVGZLUGg3S1VoODZmbDlaUjhrTGdUUnF3THFlL1hMaktPTTZITS9hclRidityL2I1MTF1REIrcW5RUDFXMTJrcE4rNnJPR0MrUEhhdGYrWmxEOTcvK0ZmK1N2MWpQN2UrMXgwZXNEdUgyaEFkM1hkZDhLMVRRNjIrWU50dTJOOWR4bzlPNzFQVEViczBiamhoN3E4L2RNbjE3MHJPL29SclBUdlF4d0doTWdpNTNMUG0wTVFYbG0xQVkyNzBYdlRKVkZEL1g5eUlDeFRmZnBzREdKdHV2Mzg5enNuOVQyZGRKSDZabzcxOCttRXc4ZlBGZmFOTWoyR0JOdWJENGREYnI4L2R0UUg3NzRzMi9mMGV3M3lFQllvVEYrcWovL3JTZnY5bENQbitvMnU3UCtYZTNJV08zSUptUEk4TnJEYVEyWEw3M3VySUpFZlJEM3pnUHAwRkVQK3hEWURDYXo1cXlsNTgzMTFMaVJlcjA2cTJ1NC90eFBuU2M3dHZXZ1NzRTNKVi8vamNGbS9STXJNSDlxZENySkJPV0R5U3dNT04rM250aWR5d1NoQncweXppTzBnZHQ2MXVUTlZaOERSdlZScHhIdTB6dDkzbEVHZTQxQjNYaUhQb0Fnc1VNZDlPR01ueG9pdGduYmVsRGdGVFZnSEV4bVk2MjhONi9ENThaRVF6MldHNjVZK0ZuYm51UVdKTjQ2eis2R0QvYW84QUZ5ZllOMUZhRDBjdkNqRk9ud21iOXBQWm1lK2p1NktHWDFhOGNaZTI4UGpYdWh5MW5JWGdXSm1pUVk2MzVNYVpDeHlwUHV4VjZjMDl2NGZzNDc2cU8rYUliZDVScGVNYWpieHRwQm5jSHJJMGhjUW1Pbjg0Nzc4TDZPbjdvZXQyN3IydnM3MHBqbWNpSDErMXB0MThyVjU4YkVhTE45WGJrNGxrMlFxRUkxbnZzUW4vVWhyZnh3YzdYRFVuUXNSUTkrRWhqc1dMak9PVmpVZ09jOHdoNmFmZFd6a0ZmTEdtcFBmUWtTTlZFelRtekZjQnVsdDVkREJVK3gwM3hYTWYyODFROWZHUVFaQkltUkpEeDJxbnJRSHFUODJXOHFaQ2lNcmVNS2ZUYTNqYjdzWWR0Q20wdmFveWVkNXZEVHY1RkZrS2pPL1hQckNWdHZTN3ZaOWt4cGlhbW94azZkN0RpVFZjTk51UTVNckNVNDROeFU5Rlhja29QRVFnWWFpN1llRUtSTU05c3hxcFh2NmttZjk4N1h0TjdqbGRFRUJVR2lzNHpHVGxXQjQ2Y2o5ZDJwVCt4dTQ1TytJNU1KNElXc3lyMXFxQ2l6NGFQKzJGcFJURDVJakZTbzV0TjhPaHEzSHMyWUJuNDVOSEJORDVwMXlUS05Jb1BCenI2U0g1eXFnN2txNUR1SXNvcGJhcENZYVJ1NGphd21iaFpwSUg0Um9WSzVsUzlxLzdZYTZEbU1ZUWdTSFdYY2J1dzltZEdsUW9QRHB2cmM5YjIrbjRXc3l1OEI0cm9UQ0dSbEVjbUZoYmk3K1hUMHZTcHEwb2ZwcXhPNWNiNVp2NVFVSUlZR2ZqQ1pQV3JRbDFzakYyWlovOUpOa0kxd25RNG1zeENZL0Yxd2dGanArL2xiRFVweU5DTjJYOUIzRURyTGY4SzFwYllRR3dqN1Z6SnVBN2Z4ZmpDWjNlZDRiU2dRdWM4b1FLeVVHZks0emZtQWtjWXdNSkQ1MktsU3BrUVlQOTNrMUNaby9CU0N3MzhLRGhBclhWTi82YjN1UkJOT2RadjVaV0VGOFZ5VE82dCsvak9Zek9hNlBuNXF3N1FLL1VGL2ZLV3gxRGRKQjRscVhMMHJtUlp4MUlWdXRFdGRITG1uVmIzVDRHZlptVmRKMGMzMFdIamp0dWl6Z3VJazZOcS9WY3BFaVlPeHN6WG5iRUhDVEtxdWd6OExTaTE5eWJFQ2wrVGJ5cG9HU2JuMlU5c085THpITU5oVFlXT25xakdaY2RwNkpqRjZqZmZHbVN5cGU3L0h4Rys5Z1BLOFIrenlSbTNZVC8rOXNoTWU5TWVMK3ZVbEd5VHFwdld1WkxwMTZraUtHdWtzT2MzS3ZpUU1mbTYzbWJXTnFURWdMVFV3ZWNsWkNvR2lydjJTVmc5WDRheXNOUXBjUmQ3R2dkcktwQU5GRGNadkNoa1F2bitwL1ZNZzJjZnJNUnVOL3FPa3NWT2xOdUhQbENaem14cHRRWjhtOUpyTzFHWnZIQ2pxV3EzYmsvRUxzVXRJR1IzVVAxVlYvYXVxcXQ5VlNLZTJMR092WGtFOFVDWFpOSU5FUmJqZU4yMnJpaytPTkJOem0zSEZ2blVPbHMxNGRLM25BOUttVGdQRnh1Ukk4WjBNQi9FdngyVE5kMGtIaW8xcWZDVVY4MXJaL3VsNzZOUHFTSFkwcmlpOS96aExMU1ZkRS8rUGhiVUZ1emplTWxDc3g4SFAyeFlwQ2dHbHp0ZzgxUUpaY0xBazdmUzJzWnI0N2ZjbEZ5UTJpbjk0ZWx2Q0dUTnE1UDdzd2VEb2N3cUJZbVAycSs4RDBxYXpMdmFRUmlwb2xZcTdQRjVtWEkxVXBiNVAxdFRxUUhGZDhZTG9scFJyTDhtcVFER3JmZlY5b3o3cmMwLzZqM0RmSmJGOXA1SFd5L2pwdjQ2M2FDdnFnTzZtOWN5R3RQcjQwdUpZM1o1OTYxZVRDaEliNTNaNFhrRFhKWlFLam5Rc1NFbzZEUlFiUVVuZlo3K1dlUmZ6dStsaE1RaFNUUmNvbGE4UEUyVGJPdGhuRUdHdDhBQ3hkdFlzOUtEWmVTWXVFcVdndnJUMDBwY2NkcGxwMEtnYjBMZlBmUk5uRys1eHJ0dlFmUmU0WGxxNS9EN2VDRzFaYWl1SlZ1Y0lyZkt3ejNraXFlaGhnRmo3M01WbWJIWDZwUTkwOW5VWmNRV2piOFVnU0RWdDBDQ1BWTDdWamhPcUVPM2RwNmZpWTJNQW51MnhKS1ZUMjlHbkluTk5uYVNrOTZodXdEN2VyNnUvc1pDU3V2TjRRTEZEM1I0L0w4dW9YSHpzbDlhLzBoRkYwcDZyTkU4bFZBanNjWUJZQzFXaGhySDJrL0o1Yit4QUEwTFhlNnlueFNCWVNlelBxcFNWc0xwL3Myd1FFSXNDMVQ1bFh0eXdpcGl1bmdlSXRUcFFqREtHNnRtMmtIMkZzZTNKaW9JMHpjQisyZk9ManBhc1RwNDJBOFFOeDJvblNRU0pXaDN5bkJtdUQ3SE11cEtwT3FBdUE1Ym5KUVBXazhnTndJRTY0MVUza3hsZGw2a0hpQTlMR28zWTMwa3RuSzl6N3BYT3JaWEtMczgwWFhiOVYwcmZjQXRjU3RnL2JTVDFBSEhaOWVGNmJiemc2b1hEbGQybzdZeVpXdmFrNitOUjMwSGRKcDdvT3hoR2FCY1BsM3ovU0VCQ0FXTGRYM2M1a1JCbERLWCtPdlVBTWFYeDA2SEdOeTlsSW14UzZPWndUVXgxdDAwODFIbVFxSmtHN3oyQzU3bFhNdFhuRkhPdnlaTitYL2pjN2wvNi9QVDZUdFFabjBib2pLL3FFcjJPVXFrVStLRHY0VkdON3RkTnJ1ZkdkM0txN3lWR3czZXBGUXlQenVjaVl1UDlzSEQ5YjVUaW9jLzhTSi83aWNIbi90QjZwTDlTQ0JEclFMQU9TQjUxZmF5OTNyVUsycndYWTd5WHd6Q2JyUE92b21uVUZ2RDJwS0lQTjJ2dXo1OG1XQlM4bmpvR0RLeVlKRVlyS3JFRHhIcjg5SzJkV05WZlJ4NDNOUjNxdFhtT2NZNFN1UitlNm41OHgvRlR6Ty9tMjlFNlM5cXpiZU9YeFFuTFp1RDdTdGZtSml1Sjk1MEdpWkVLMVh4UTZkZHNSZnFjS2wxWTRmZGNMcmxJMTlKTmQxOFBEaUoweG0vQzc4ajl1MTJoMmNIYzdocHdOYjhUWFVPbkNyUTg5L01kYkRnYnRoWE5TbnAzOUpzTU90ZHFmT2JmcjB1OTl1R093VHI3RWJ2M3BYRXY3alRacUh2NHRnNWFOQUFaUjdpbXh5SHRNM0lXemFWelgvV3NjOEsyRGtUVlg5d29jT2dpZUVCRTJpNnlha1hGMnRianB4WGpwbkdrbGNaanRRMWRadWQ0ZUZiL2UyTTFmcXArWEV2bkViNmJpOFdEOHNON0dFeG05UjgzeVE0SkU1Yy9CWUVhaDl4b2duSmwxdGZpbnRXdVZ4SzlON1ZmeDU1RmRYTGgvRG1Gd2ZIRnNndG1Wd3Vkc2RmZWxCRDhIT1dlUml4MUIzUGxzZXF0eitoS245blllVlhPWTJEcWVSK2JYLzlOR2pCYzdUaUJRdnBhTis3MGZibXNpdXNlUDFmN2VPVTQ4RGpRZ0NOS0lSdHRpZkFNdks0M09FajZSYm9uejVXR2VOWFRBNzJMRnVrNHRVcDk5NldDdzMydnk1dkczdFlZKysvRDN1WGJBaWJiNjhEd3ltdDdoc1lIVndvV1BTZkN6cFFCc2pqUjhLQTRZTGhMcGtiNDl6VDIrRWNQbmE3NGQ0YU4vK2Eyc3lBeFFxR2FoNDczTDVsUVkrRzF0K05aRFp2YkFGd1grcW5laDNWbmZLQ0dOT2Z2MlRWQVdXWStIVjNxdk1jYnA4bUhnelVOME5ZYXE2QWVQdW56anpiUjBCZ0lqUFcreG11K0IvWWp4bld0NnlIS0NxNSt6MURYd3NmV1g3QXhqbmh1bitka3psdnJkaklNZ2hwYlhsSXNzdE5NRzd0ZCtOK05hUlZoMDhydW02eFVYR2VRNVJBais4cWwvMUNnTTlTZzN2dDk1RHpaWG1mL1hNVjYvYUVOYW95ZnZJTDQ4Wkp4YmIwbmYrZXhrQUxGT3RoYzFkN1Y3Y1MzODVrN0NSSWpGYW9aRnJMQzVCVTgzR212WnF6QmtGZG4vRTZyVnJtbDVVVVBEcHZVV0hnZTdYRmhlTzE2N1Fjd0gzUnVZMkYxZDZoT1lmSGVJTjAwanFqQjRTSk4zSHgxS3BSMUdDTTEzN0d5WjkyZnU2eXE2ejQ4VGFTNGlVbXEzQkpIeG1NdXR4VWJDNnFzNjUxOWRlNzlHWVI3dGxHUHd1djkxSlhKb3g4dnRvZG50ZGVkSFBXaiszTG8yR2FjTHdrUzYvTTlEMWFsaW01b1padWlOcnkrenI3OSs5SFBTWXhVcUthSUFGR3JyUjVwTUo5Q3ZuTHNBVkg0VHViVDBha0daSlp5U3lrT3M0OG5YUVlvVmFPaGN5cU9jbWg0SHBOSDU5VnBnTGdvRERaMGIveld1RCtlTTV6OHlFMFk3TDBPNStkMi9WbnJlbnpiZXNKR2pQT0J2ZHJoMHhpRjUzU0dzblhmdEtrbnRVbS82bHIwS3Y1bEl2RUEwVFA3cXRJRSswbXN6NkRPTm5DK050OTBjUWIxanNJZThhT3VBc1FteHpialFHbXQzNmtOdk5PZkx4Yk9UclJTdCtIMVpGWGNJREZTQVphM3VWY3lyWDU4Vmg1cGxHKzczcWpzY0dPZFJUeklmUi9QR3BEdXZhZkdTaU5RZkhiNDU2MEdwdFpuTDM1S0tVQnNDZ01DM1Irdkk2WUk5dFYxek1IZUpuUmRmbkQ0cDk4NERTcStjVnhGZkJ2eis5RzlGN3VpY0dpUGpsSnRrekxrMlc1ZWE0STlhdit0Q1hidlNZeEx6emJDUUJpai9CNG1VeE9iUUJrN3RSbkxndlk2aUR1MHVNNmJCL2hyeTBQZGhuOVBvWTY5a3VoZHFDYlp3ZDhPUERiR0pyTjZvZ2J2Uyt1SjNlV3dtamhNY1FaV2pZSEhTc095Um00ckN2NHQ3NFBuSEs0VnJTeVdVSFFyVlYrMFlwUGNhbzIrOTd2V0UvdXpubXhwOG1nL3JqdnFyMDZkSnMyVzZYelN0aVFhNkhxTk1hODFidW1NYzZCNG1IaDloL01VQyt3NGpwOWEyN0kwZnZ5a1A1N3BlcStmQzRIZFFEOHIyM3BOY3RSL3I2NjJmZDdZRTMvWFhLV05GaVJHS0ZUenBaVEcxcW5jZjFMcGRYS3VOQnNMcDRuUGdsVXByM0NyOGJVZW1CNGFyUEJhbitNVSt6Z0FwQ24xYkJPUHZzd2xuVXp0cm5WLzlkVFZnRlhwZlRFbWFQNWc5ZENPcmtPdjc2M3pBTEdtMStFeGlWU3BNbm1xNDZpVTA2L3ZQVEpBbHFVQUs4NnBWeTQvS3JiYTUzZWNOL2JDUHkzMkUxR0N4QWlGYWg0aTdibUl4YnB6N0dwR2RxMjZZTUM2djdPRmc4S3VnUzU0ZExBclo3UTJaQjBrbG5pdUpncWpRWWYxaW9IWFNxSkg4Qm0xNHZBaXphUjdEY1NyeGRsNm1CZzdiV1c2U3lWQWJEZzFuR0J2T2lqaFZJQ09YRHBrSUt3YS96UnJTWVFEK0crMm5aQVBrd0VxOEZRSGlNL2EvLzFUdStzZUpFWW9WUE9zWmVnaVZnYzBpMlBaSUQwazJNQjlwOEhRcDlZVHV5RkkzSU5TRDZ3SFJwNHBibHNyWWI4eWVzTTZpRGgwV2lXd0RoS2ZFcG5VOUZ4TkpKWGNrR01OaDliS1NncU1KOWdYcGJ5YW1LeEd0WEpMUzhkUGpWb1M5WGd0WkduZWg2RHZwV0F4UEsvVng4ZEdnYWNIN2M5dmpZOWNqOENJVktnbVN1V3ppS3pML2VjUU9GM29kZTc3dm8vRHBBU0J3RjZzRC9aZU5STzJxYVdONUk1aUY2UUFkaGJhc2NhWlZsWk9ITTdldEo0SVNpS0EwckZOZHc0RmVSNVNyZzZhS2E5VnhOYktTaXJVUG54d3lOS3JzN0pZNmQ3ZXBYRmwzWlZ0VCtNWWpvdkc5ZjlPeDhJOWFVdEZjeXg4cFBaL3NUOVplOWFuOTBxaWQ2R2FxSlhQSXJHY0RmdVFROEJrUEFPVDAxay9LYkpPeC9TOC83ZkY3Q2h5RTJWbWVsZXFqbWM1T0U5bEZiSG04VnBJZWJmbnNZcVkvUGhKUmE0ODBrNUpPZDJCOWpPYlRrYS90REtvYStCRXdWNmQ3bnFvMWNYM2paK3poZkZZMk03dzIwdlY5ajJEeEdVSFExdEtjcC9kUHBTYWF6V29mczVzSnNqcXRSSWs3a0dOaFdYVjJjcnd2TVI5ZVp3NUNuaXluZ1JkTytEWVFkRjdoalhHc041bnhDcWlJUlhlc0Y1RmZNcW91clJIdHRqaHNxSXAySWgxRy9aaW02MmpzMEt3OTZ1T3ovcWdjZHpkd2s5NC9QZXFxdjYxNmRuQW51bW1uZ0ZpMHZ2czltRDVucktxNGhndVZxUFVucEJ5ZXNRaDVIdTVONzUvazFuQkN4MWZpbVcwZ1dXVVV2WnNPQWkyRGhLdFUwMVRuUGk5Y2FqZUNqc2VZOEZzeHBlT2FkR25ySHJ2NU5ZNEJYaTR6Y1NTc2l2TkpxSmluNU5vcGRRWkRzdjNsV00rdVZXRGxGU3hsQXhaejNTbnNwSllzZEtNREZtbXZGa0hpWmIvM2xPaTZYMnMvQ1ZLcVhqV3dkRmRodHVZUEZZOXp5aGdzNzNTdHNEbEdpUVdWeGxNaloxVk90eDFwdFZlQ1JMVFlEMVEyNmVqc1Y0UlB0TStLaUFYbG9NTzY1UnJ5ejNIcVE2dUNCTFQ1WEw4U3V1UnhEbFZKcStZVk4yWjVUN1JUaWZaY3cwU3cwQ3Z0STIxbGpkamxwMmFVa1F0OW4ra3RIS1ZuY1FtR0R6U2htK1lJVVZHa2t5ZDMvWmNyZzBrV1NSRS9aTGxvSSsyeDQ1MVdtaU9xNGcxaitDV0lIRTNsbTEycCsxRnJrRmk4TEd3RlFITDk1SnpIcm5GUUNHbGlwcTVzcHlWM09mYTloZzRodjFkdHdrVjFBSFdTWFYvZFMrQ1JMSDhEbWgzREdpU3dycXZ6L2JZQndXMzFwVk95YnJaVFRFMU1UeURSS3NEMHRjcGFVWEE2bVo4eURUVnRHWXlpMGRLWVRHOEd0dGpCWXJNbEtKWEVtNGJVdzRTU1RsTmozWGIvVlJBVVRQcklQZUFzZFJPQ0JJM2NCTWhVRHdvb2ZIV2pKaFY5VHFxZXY0WHM3VUZVQ0VMNnhMMHRYRFAvVG1Zekc3cENKR3dWQ2Y5VE8rWnpDYzNFVjhmS3V0dXl5UElwVy9zTWRkMDAzQnVoL1hCa2t1RUl3OXl2N2t0QTVya0Q4OS9nVlhRYjUwS2hlNTR6KzZHNm5oL0VTd2lSYWtmNk4wVGxwT3Z0REUyQ0JJWGVCem16dlhhdWVJTDE1dzZyZ1RVem5TZ2FxNVk5YkxIWjFxT1dDbEFkYkFZenV3Y094VG1BTENjOTJUeXZzalFTWWoyazFzZW9QOVEwTm5LMXNFdVk2bHVXVjduVy9NOFRQOGJIWkllQXJnL1cwL2EranlZek80em5YVzF2QW5QTTE4TnNkcGpTZ1c1UW9SOUlvUEo3TW1oZlA4cTRmZDhWSEdzTzNXNnR3VU5Jb0RVa0dxS2JWZ0hMaVh0T2JWK0wyRmY0aEg5WHorNUI0blZqMEZlMkovNHJ2V2tyVnRkekxsMU9KWUJ6V0hFd1hUS3FIQmFsaENvdmUvZ0hiMnFEMnNlVEdZUGVoMDNkSmlBS1NiMXNBM3JJREgzZ2pYZmhZV1N3V1QyYkx3Q2RjSnFlajlGT3dJajB2N0VYQXZadkdvOUFxRHBNa0xhK2t1T3RjTDRqMUpTTHpsR0F6Q1IrcVFlOTNsYVRMK1BqTTlHWE1YNi9YRDk5MVRzY3hKajdFOHNvWkFORExDbnJCektEdkE0TEhoWGg4cU0rSHN3bVgwTmJRN0hhYUJuK3BRaWFyblNTV3J0L2l5RGx0VDN3KzdDZXRzVlk2bWVpaG9rS2tVclJvR1piQXJac0JMaGlvYXRJUFBwNk5MNGtIOHJJWVBoVE1kcEVEQ2lMMHdIb29sUDZsa0dpVlNyM1o5bEttV0ozNGYxU2lKanFaNkt2WkpZNmJEU0dBZnRmODRrQUdNdkJyQzU4d1RTVHRkcEJvenp3V1IyazNubFpTQ1dsQWVpVE9ZbXdxRXdYNGw3N2F6ZkU5ZC9UMFVQRXVVaTBoSi9LR1JERUFZVUltSTJncFUzbXJDcVZ4anBiRkVLNjRGb3lsVzVMZTliQ29Da3BiVDlpSlZEWWJWT2oyRkFkem9KRXJXL0tNYUtRSzZGYkFDc29HeUV0OHVmVFZhOXd2ZzNoL2FqQkE0RDBTUW5VQnpPNUNOSTNBK3BqNXNwY2E4bEl1dHFKYkhTZVliajFoUDJVaTlrdzJBUjJOSjhPcnJLTUZDczFZZjJFeXdpZDVZRDBWVHZCZXZYeFo3RS9aZ0dpUVZXTnEyWkZraWlyK3Fuem9MRTZzZEE3N3IxaEwxc0N0a0EyRXptZ1dLMUVDd3lPNDRjV2E2S0hTUmE4TWx5Y1B5VTRUbk95QlBYR2ZiV2FaQW9NYzVQckRJcVpBTmdRd29VZjArOG1NMUxYdW5zeFpTTytBQTJZYjBxbGxTUXFKb0diMXBQN0k1VlJNVEN0WWE5ZFI0a1J0eWZXRkhJQmlpUDlpZ09DOWlEOFg0d21kMnpxb2lNV0tmcW5TYldSMXRuSUZFaklTM3Myd1BXU0dFbE1lYit4TEQ1L0tiMUtJQ3NoVFprUGgyRlRJRVBtYitWNHpBRFROWURjdUN3bitzZ3NlckYxdU1TZ3NTMGtKSUpySkZFa0ZqRjNaLzRhakNaWGJZZTdRNmRCbUJrUGgyRmxNMS9KM3JvL3FZT1ZBV1ZmZFRJd1JmajF6aE9ZVFZSOTk5aDY0bmRQV2xDSEFDeWtFeVFLTEgySjc1akFBYVVTYXVLUSsxVmZNcjRUWDZtblVJR3JMTnpEaU5sRnEya0lOVjZqekJaVEFDeWtsU1FHSGwvNGlVcFhVQzV3bDdGK1hSMHBBcW91YTRzRWlnaWRSN0J6N2pqdmJrWHhxdUlRY3BIY2ZYVnE3NS9BTUE2djZ4NXJoTmhGV0F3bVlWWnhNL092Ly9iL3NRUUtIWmNrdHI2ZDkrUnd2b2RoeGFqVG1XLzBxVFFXQlVVTFEvSDloWW10TzVKVlVPS1F2ODVtTXkrR0ZjQnJlc0hSSi9JMVhsdzcxcFA3SWRVVThSR0FUVHNMYmtnc2RLZ1RnMzFXZXRKVzRmcWlEbzdKRlJCY2V2eFBkeHFYeGFBaFhzdFpDb29sZXhVUDVZRFd5K3BUR2dCcTF3NTNFdkhnOG5zYWo0ZFJWdEpWOXZnc1RLYVVoMEU5QU5CSXZhVzJwN0VwbGo3RTFNb1pKUHpHVzlBVmtLZ0ZTYWk1dE5SQ0JML3BYUlU2K0liMWc0WmFDSlZPb2JHWS8vdldheDBhd1dJdHc1WkJzK2ttcG95blNqVGdnUmV4a3A0RHlVYkpFYmVuOWgxSVJ0dVBxQURtUVdNWnd4b2tEQ3ZEQmIzZmJtTkFQRzQ5ZVQrTHNrQU1NVjRhVE9tK3kyNWh2c3A1WlhFbU9jblZoMFhzckhjTzVmU1FjUkFOaklKR0ZsTlJKSzA5OWVybW5BSUZGMVc0OVR2ZXdXSXo5eXp5U3R1NGkyRkkyUlFocVNEeENydStZbjF2cDh1Ymk3TElKR0tyY0NlRWc0WXd6NnQwOWFqUUJvODk4T0hsZlI3eThsY0ZjbnpDaEFyVmhIdHphY2o2OEo4Slk2WnJOOVR6dWNPWXcvSkI0a1NhMy9pWVVkbkdWazJlbXhXQmd5dENCaGp0RWVyZEhxR0hMQ0tKblU5QjVRaG1QczdyQ3J1YzBSR1NOc09BV2RWVlI4ZEt4MC9VVVF1Q3dTSndBcFpCSW1SOXlkMlVjakdNc2Yra0ZRRHdFY2pZQXlkOEc5VlZYM3FvUERVcTQ3UGtBUFdpZEZYaDhybi93d21zNUQ5YzdwSm54ZnVtYkJ5T0pqTVF1Yk9YNDZyaHpYT04vVmpPUkZ4V0dCN2FoMGtjcXhhVHlWNUJNWXlFYzlQckZUSTVsNnpvdTUwenRTRFlhYzE3R2hGRk9pTitYVDBxRlc5c1FwcmVCekF2Y29wZTUyUW9uQmZEQ2F6QzYzU2VYdFRINzJoUHZSeFlkTDFWdzJZVHlLZmpmckpJUzBTUDl3YkYyWVpGbGFCMW5xZkpXZE85MVF1NmFiZlJOeWZXSFZReU1aeU5aRUtpRUJFV2wwOFVpcHFqSlZGVmltUXJQbDBkTm5CSHQ1akJZenZHei92RkV6RURCQWY1dE1SS2VHK3JJT1dZdlo1YTFYVWVyS1NJTEduc2dvU0pkYit4TmlGYkN4WC9paHNBWFJBRTFsSFNrUDFkRXhhT1JKMzN2SGUzUzQ4TTBrYmhmVXFiVW5mbWZsN1lWVzh2N0lMRWh2N0UyT0lXY2pHOGlZc01jY2V5SUwyTFliSnJOK2RWeFVwVG9Ca3FhOGVkckJudHl2ZkFrU3FtZnJUOFdpV0RqbytLOXVTOVNKQjN5WjYwSkRqU21MZFFQelJlc0xISysydjhINVBYNDF2UnRKZGdBN05wNk1iNTBFeVFTS1MxcU5Bc1E0UU9lZzlIdXNxdXRsbllDbTc1RTNyaWYyd2l0aGpXUWFKVmZ3OUQrOGpuVTFtdVhHYVBVdEF4elJvOUxvWFNUZEY4blFQREF0ZWtTQkE3SVoxbHRlYkFqS3dQTWFwQklrOWxtMlFLR0h3OWRSNjFNZFZoRUkybG8xZVNla1RRTGEwb3VneG9jVktJckpRY0tCSWdOZ2RqNjFBdVdkZ2VieCtnc1FleXpwSVZDcExyQlNCQXdXS2JyUDNLcWx2MllseWtDK1FCby9PbTVWRTVPYWlvTlRUMEZjZkVTQjJRK01sNjBXQzgxd0xnZzBtczZIRDJaOTM3TEh0dDl4WEVtUHZUenlPY0phTzVkbG5oNndtQXQxem1BQUNzcUJEN0VPLytaK3FxdjZNZkJ5RmwzQU80Z2tENk01WnJ5WWVaTHlhNkRIVzQ3enRuc3MrU0t6aTcwOTg0MXpJNXNaNHB2V1NVdmxBRXVodzBSdWgzeGxNWnFGdi9xZXFxck5DM25kWXVYck5PWWpKc0p4VXI0MXoyNXVvMSt0eGo5Rm45VndSUWFMRTNKL29Wc2hHTTVPbWV4TkpPd1dTd0tvRGVrSDc5KzkxbUgwSndzVHRoL2wwZE1TWmNkKy8zODQ1WldnY09BV2ZuanhlNzUwK1gvUllNVUZpNVAySmxYTWhHK3VnN3AzeTFRRjBoNzFMS0o3NnhWdWRNNXk3YjhHaDloN21QTmxxM2Zha3ROTG1FU0M5eVdYTXBOZHBmZXhGRldGckZUSlEwa3BpN1AySmJvVnNOSHR6M1hwaVA2NUZkd0M4eUhyUTBmc1ZEYVNsRVNEbXZ1L3dTV09KYjhGaDduc1BIVjUvTXBXVjU5UFJsVk14cEZ6R1RCNUI4ak9wcHFoS0N4S3IrUHNUUFF2WldQKzdoOXowUUtkeVA0TUxXRW43b25JT0VFTmcrS21xcW44cnJmU3lzTUkwbHR0eFVqdDQzaU5RT2t3OTdWVDFNYXdybWdaWEZHVkNWV0tRS0RIM0o3b1VzdEcrQit0Zzk1V3F6QUdJejNwZ3hVb2lVbkpqSENDR3ZXWnZxNnI2WGNIYlhldHY3UC92WDJ2RnNBNE14d1VmYVUzZ2RiZ0FBQS80U1VSQlZHRzV2K3c0c2VJdWwwNnJpV2VwVm9qWHF2MzcxaE0yY3R1VENTZS9sUGpCaGhrUUZaYjV1L1drajFESTVsNkhabHNhTytTYWgwWXZmRVljalFGRW9vR0c5UW9MZXh5UkJPTVZqVERCZTc1UUlPWjczNm9Vd0RyZGNWa0s5NUYrdmk2NVI4Sy8rYlduWnh1RzkvNnE5ZWp1emxNcGlxY3gzNlZUMFBSNU1KazlwbFN3U1BlQVYyYllOUVZyVUNzeVNLeTBQM0V3bVlVWndvK3RKMzJFL1BXaFplY1RidFRCWkhidFVOcVlRQkdJUkIyNjlXRHFpWFFncEVEWHQ5V1JFQ0ZBWEh2K29KNnJCK3lzcG0vdTFqaUlTaVpJbEV0ZGh4N3B6amZXNDdzOTNUZ1docUlhUHI0ck5kMzBtOGo3RTcwSzJZd2QweWhJUFFYOFhUaDA2QXlPa1FyTGdYbjJSV0lTWmgzZ0hLYVVpcW5yeGl2QUNkZjNiUXBIZjJqY1pya2kzTVFxSW41U2RKQW9NZmNubWhleWNXNzRRcUI0bjl2QnNiVlV6bXBDWEdGZ2tzczFxMEdVeDFseEZLRkNLcXhXRVo5VnFSSU9OSmF3M3RkNW1WSUZVQzBNV0orYldPczhVRlNBNkhGb2ZxWEZDS3Q3R1lVb1BranM0UHhFODBJMmF2aXNHL2RhQ0d6dnRZY3pDeUh0WXpDWmhaV1V2d2tVKzBVRGtzOVZWZjBUcm9GVWl3cFVQd0xFejYwbjl2ZnNzUDhaMkpyNkRhdFZSUGJZK3JOdU53NFNQRS9QczArb0E4V28vVTdvOTV3RHhJcFZmQ3pUaDVYRTJPY25WaXBrczJ4RC9UN09uZEpPS3pWOGZ3NG1zNXVVVjJpMGdoUlNJZjVxcEZzdzg5VXZ6Y21NVjNWUmdUQXhrOUsxTzVqTXhrNEJZa1hsT1NRa2l3UEg4WjFIUVBkRzdWMFNOTjc3NFBoYUR0VHZSRmxGYlJ3dDR4a2dQbWd4QXZoSkw0TEVLdjcreEVvYm5jMEdyY29UOTU2OWVxTlZ4WXRVVWtqQ1o2alg4MVdEN3NXOVhkbXNnTUxFc3UvN1VBVVovdEZFUjJlcmk3cGViNTBMWnBHU2gxU1F5WkVSclJSNWpJTStKclkvOGNJeDdiVDJUdU1sdDRrU2ZhYjNUbWNoMXA0ampDMlJxZDRFaVJKemYrS0JBa1d6WUVzcFp0ZXRKMndkYU1EOXFKbXk2S3N6U3EwNDEyRDdINzJlVlNsTkJ6bWx5bUozdXBkZU9oTG1qV1o1UTBuMHExalhocTdaQzNYb1hrVUZLZ29MSURHVy9ZUG5mWU1mdkZhTVBxdk5UV1dQNHFsajlsVXRURkQrWloyRjFkaFM4M25OMk1mS1JVK1BoTUVHZWhVa2RyQS84ZGk2UWRheEZkNHpaSlVhcG5mTnZWK2VqWC9ZV3hoU1Z0UXcva2VONDZhREJvTEVmdGptZXo1UWVzNmZ6WURSK2hwV1ozNmxhM2JkWklZRkNnc2dOYVpWZTFQZVkxd0tuZmZuVmVQZ1RLdHJuWCtQa2JLdmFtOGFtU3c3ajBmVVI5MHViS254ZEUyYUtkWXA5cHpFVlRvNFAvRk1CKzFiM29oRHJWaDRuWk96NkZWai85ZUQ4dVBEeitPMk0xQ05nNURyQTQrSCt2TStnMnVDeEg3WTlYdXVBOFp2ZXpvYTEvQzlydUdOajVOUWF0R0pmaXlMZG15Q3dnSW9YZGhhY01OMTd1NUNnWWlIUTQwVkxsUW9KN1N2WDBNNzIrai9hNkU5L1Q0bW1FOUhwcGxMSWZzcThuanZqZlpvUGpmZSsvMnFjWkpXSCt1K1pCaHhURmRwc1lGSlI2elZ1eUN4MHY1RXpmYkVTbS81cUVEUjVHeXowSUhxOWQ5R0hxUldXaDA5cnN2NmgwUDVsY0w3VWdyY2tXTUQrQzNsbElxUDVkb3cxWFJUeDgwOUhycUduMStvcnJqdlJNYSs3cGp4UllLZWpOdjFRMVdQSEJJbytsSEFkdWM4QmpyVU9LRTVWbGdyQkUzVzZmUWE3NTA0RjM1WnREZ3hXUzMwTVYzM0orRzFuSEtQNFNWOTI1UFlGQ05mdmNtNmtNMjlacDVpdm9kVkRodXJqYXQrdkdmSVdFMHNtL2YzZTdEaXVxMS91dTdRU2NORGlqejJ4eDVyVC93NHBUUDRDcFJpbStKU0JFYmJkTHpyT2J6a0lLSCtaTWplZG15aXQwRmlCL3NUUFFyWnBCUW9kbzBnc1d4OS9uN3AwSkdxZGF2dit6aFFpdUNqOWhPZnAzdzhVNDdVcG5nZUZiRUx0M1kra1VDeGEzV0FTS0VhYktTWDZhWTFwVng4VU1HSkdPcENObVl6ZU5wak9ld285VFFsSWVYMGhNYXZQTWFwcHJsNXl6V05oTjNXNllST0Z0UDI2cFM5OFBOVks1bk5DWlI3VXVnMkY0NkswTllWenlNV3R1RjY3bVlJRkpYNkdUUDFOQlVFaU5oYXI0UEU2a2NqT1l5NFA5RzhrRTBqVUx4S3FMSHZ3amtic1l2VTExWEVFQ0J5SmlKU1pyTFBmZ3ZObEwybE50bjc5b0xGL2NsMVFIcGZGMkJaLzU5blo2aEFPNFZKNWdQdFIzWDdqQlVvMXNkTDlNV1Q5aUFTSUdJcmZkNlQyQlI3ZitKSDZ3TllHNm1uWHFXdGMwREthWm42dGg4dnRFVy9FeUFpZFZxMUt5MkZiM0YvOGp0bEcvMnBNL0htWWFKWGFiQmpGVVhKbHI3RGxMYXR1SzRtVnY5OXo2RnRmZDJUclRxaGlpbFpWdGdKUVdJMyt4TXI2MEkybGQ3SGZEb0tEZXluMXBQOWNKaDdoNDJmNlI1WnVXcFFvQ2VsQkZHcEY3bm80MlRHc1ZJV3c3N0p2d2VUV2IxM01zdUpTZ1VRcVdUaFJQa010VnA1VXZqRStxZjVkSFJDQ2paMlJaQW9hakJpYnVJMkwyUlRtMDlIWTgyU1BiV2VMQjlWSU12U3A5WGhPMlo4a1J2bnc5bHpjYWlnOGMvQlpQWlZBV05XRTVaYVhYdWJ3T3JhY2F5cXRxRjRqeWJXVXl2Z3M2ODZHNFh0TjlnTFFXSkQySjhZdWJPckM5bVlhOHlTOVdsVjhVNEgyS0ljZlJpQWhnNzlqekJZWWNZWG1UcW55dlozZGJHZHNNSjRtOVBxb2dMRkZGSlAzVk5PbXpUMis2MlF2aWFrZngrUmpRSUxCSWx0c2ZjbmhrSTJMck05U2ordFZ4VkxIbWlIUnZHMUJ0bWxGUlhvdGJDcXBwbmUxNFdXTC8raTFVTU95a2UyZEp6Q0JkOWd5eXV0TGo1YTF5SHdva3lHRSsxbDYwcjB3THF4cXZoN3BsbFlkeG9IblRQWkNDc0VpUXM2MnA5b1hzaW1LUVJPYXZ6ZUZwU0MrcXdVa2QvVUtCSWNGa3pYOExsbWUvOG80RHF1Ty9SVHprQkVDVFRSMGZkejZGWTVWTkdiMnh6T2UxVEFkTkpoR21abkFYVllnWnRQUjBjWmpaZWVWQW1iU1hLWUkwaGNvb1A5aVpYWC9zU21rRXJTYVB4eVhWbjhvbHo3WDBPS0NBUHNmdEhnNVZMWDhiK1ZUcDFUd1BpRlZXOFViTnp4Q2xUcXdzcml2VmYya0xVTzB6QVB1dzZtTXhndjNXa3NkRVFsYkhnaFNGeWhnLzJKQjdIT25GTGpOMndNc2xQZlMvSkZEZlcvdFBKQ3JqM3FWTlJ4STJEOGtPZ0E5VW1ybjcvcCtpVTRSSkVheHluMHZaRE5PZ2ZLSHJxTlZhQmxINDAwek5mcWkyTkpZaTluWTd6MFd3S1Rrazk2RGI5cG9wR3hFRnoxL2pEOUY1eEdQbVEyVlBXNlVscWR1MGJaNjdFMjF3LzFuZzhqdmQ5VjdoUXczektneGlaMExZZWZDdzI4aHZvNTZlZ0lqUys2aG05WTdVYWYxSUhpWURLNzFCbURXQzYwUzQ4NlBENzVpc2JxaSt0MDJWTVZLenB1L2NYOVBEVDYvcVFDSUxYajlYanBwREZlOHU1ZjdocDlDWld2RWRVdkdsaTlkdmlsMlYvTW9iTlRZNUQ4SG9KOXFVRytVUU40cE1GMVBjZytjUWlVbjNXTmZOWC9ocC9IeEJyQnExaXJ1d2tLbmFIVkxIZlVUZlFhcE40MEs5M3FQcTd2NWFIKzEySXk1RWtUU2ZVMWZKOWhSMjU5blh1OWY4dCtLcmZBM2ZLOVI3ayt3eXIvWURLN1VVR2JQcDExdW8wREJWNVpCSXJWajJBcFRBQmNOaWJrNnZiMVYvMHNCbzlQUys2NXV2OS9WTitmVFYvYm1KVDhWbkJNTlNYcS91Vmt4LzZsSGhNOU52cVNuTWNmMXJGRlR2MXFNV1BId1h3K2J6MElMTE5RWEdlVGplWDNpd0VDSzROSWlTWkU2a21nb3hjbWhKclg3aU1yaE1CbWxLbHlGVEVySjBlL2t6NVlGZ1hSTDUyWGVVODFVcVNLSUJFQUFMaFFrWllMQXNRWGhaV2tiRllVQVpTUElCRUFBSmhTNXNubGt0UkRyUGFzYzFQSlVnRFFPWUpFQUFCZ1FpbDJGeFN0MmRtRFZoUkpRUVRRS1k3QUFBQUFlMU9CcUZzQ3hMMGNLOGdHZ0U2eGtnZ0FBUGJpWEp6bUlWS1Y1SlNxc0w2bTBCdUFMbkZPSWdBQTJObGdNZ3RuNW4wMi9nU2Z0S2Z4S25icVphUHFjZk40aDlqbkIxOXVVQmtUQU55d2tnZ0FBSGJpRUNDRzRQQmlQaDFkdFo3cGtQTWg4cXU4VGUxekFOQWZCSWtBQUdCcnhnSGlzNExEeTlZemlWSEFHUFlObmptL3NxZjVkTFR1N0ZZQWNFT1FDQUFBdHFJaU5YOGJmV3BoeitGcGJrYy9SQW9XT1dRZlFDZW9iZ29BQURhbVl5NnNpcXBjNjhpSDdNNEdESzk1UGgyRjFkVFhXZ24xY043dHV3VFFWNndrQWdDQWpRMG1zN0N5OWNiZ0U3dFdrSlc5UnVEc3NWL3hYNXliQ0NBMlZoSUJBTUJHdEEvUklrQzhLeVZBclA2N3F2aFYxVkFmV2svdTd6VDIrd0VBZ2tRQUFQQWlyWlpaRkpaNUxqSHdhUVNLMXFtbkJJa0FvaU5JQkFBQW14Z2JIWlkvTGpWOVV1L0xlb1YwMkhvRUFKeXhKeEVBQUt5bFZjUkhneUN4RjhjNkRDYXpzRC94VmV1SjNmMldZM0VmQVBsaUpSRUFBTHpFYWhVeCtYTVFqVmdmZ3M5NWlRQ2lJa2dFQUFBdnNVcWh0QTZlVW1WOXR1Rko2eEVBY0VTUUNBQUFWaHBNWnFGd3l1R3E1N2Z3MEplakhQUStMU3VkL3RwNkJBQWNFU1FDQUlCMXJBcW4zTGNlS1J0bkd3TElGa0VpQUFCWXgrb0lCZ3F2QUVBbUNCSUJBTUJTcW1wcWtXb0tBTWdJUVNJQUFGakZzbUJLMzlKTkFTQmJCSWtBQUdBVnk0UGMrMWFoazRxa0FMSkZrQWdBQUdCb01Ka2RHWjByQ1FDZElFZ0VBQUNyV0I3aTNxZVZOY3NWMklwVVhRQ3hFU1FDQUlCVkNCSjNZMVVSdHNaeEdnQ2lJa2dFQUFBeEhDb05zMmlxQ1B2RzhqM09wNlBiMW9NQTRJZ2dFUUFBckdLZDVuamVlcVE4WStOMzlOQjZCQUNjRVNRQ0FJQlZyTk1jeDFwcEs1TGVtM1dReUg1RUFORVJKQUlBZ0ZXc2c4UURoeUFxSlZjT1ZVMXZXbzhBZ0RPQ1JBQUFzSXJIS3RiN3dXUldYQkdid1dSMmFyMFhVZGlQQ0NDNndYdys1MU1IQUFCTERTWXpqNEhDVTZoMk9wK09pcWphcWFEMzFtRVY4Y3Q4T3JLdWxBb0FMMklsRVFBQXJITzM1cmxkSFlhZ3FvVDlpWTRCWXFYMFZRQ0lqaUFSQUFDczQ3VW43bGlCWXJhcHA4NEI0dE44T21JL0lvQk9FQ1FDQUlCMVBGZXo2a0F4dTVUS3dXUVdDdkQ4N1JRZ0JoZXRSd0FnRXZZa0FnQ0F0UWFUV1FnVXo5YjlIUU1ocmZWOFBoMDlwdnh0RENhekl3WE9yMXBQMmdtcmlFZXgzeHNBMUZoSkJBQUFMNG14cWhXQ3JuOUNRRHFZeklhdFp6c1dna01GeS84NEI0Z1ZxNGdBdXNaS0lnQUFlRkdrMWNTbUI2M1kzWFM1dXFpQTlUemllNytiVDBmSkJja0Erb1VnRVFBQXZFaHBsdmVPZS9EV2VWQ0JtRzgvbmtkbnFPTHFVRCtucXNRYXkzUDR2ZlBweU9OOFNnRFlHRUVpQUFEWWlJcTFmRXpnMDNwV3dCcCt2allPbkgvY2ROVlJ3V0JkV1RVRWhFZjY4M0hyTDhmengzdzZ1dXp3OXdQQU53U0pBQUJnWTRQSjdEYkNucncrdXA1UFIrZDkveEFBcElIQ05RQUFZQnNoQmZPSlQ4eFVTS2NkRi9SK0FHU09JQkVBQUd4TSt3RlBsZktKL1Qxb0g2TGJQa3NBMkJaQklnQUEySW9LcXd3SkZQZEdnQWdnU1FTSkFBQmdhd1NLZXlOQUJKQXNna1FBQUxDVFJxRElIc1h0ZkNGQUJKQXlxcHNDQUlDOTZEaUpHNnFlYnVURGZEcTZ5T0IxQXVneGdrUUFBR0JpTUptRjRPYzluK1pTWWJYMWZENGQzUzU3RWdCU1Fyb3BBQUF3b1JXeWYydS9IWDc0RkE3cUowQUVrQXRXRWdFQWdMbkJaQmJPL1F0QjQwR1BQOTI3Y1A2aDltNENRRFlJRWdFQWdBdnRWUnpycDAvQllnZ09MMWc1QkpBcmdrUUFBT0NxUjhFaXdTR0FJaEFrQWdDQUtCUXNuaXBZUEM3a1V3L25SRjVWVlhVNW40NGVXODhDUUlZSUVnRUFRSFNEeWV4SXdXSUlHZzh6K3dhZWRlVEh6WHc2dW1rOUN3Q1pJMGdFQUFDZEdreG1KenFVL3pUaHN4WkRLdW10QWtNSzBRQW9Ha0VpQUFCSXltQXlDd0hqU2VNbmRtcHFDQWhENm1nSUJ1L1pZd2lnYndnU0FRQkE4clRhK0t0V0hDc0ZrTDgyL3Y4bUJYR2VGUHpWNnVEdnNRNEs1OVBSMTlaL0JRQjlVbFhWL3dQaFdLM3RNUFZ0R1FBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMTItMDgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEyLTA4In0seyJhYWd1aWQiOiI1MDRkNzE0OS00ZTRjLTM4NDEtNDU1NS01NTQ0NWE2NzczNTciLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjUwNGQ3MTQ5LTRlNGMtMzg0MS00NTU1LTU1NDQ1YTY3NzM1NyIsImRlc2NyaXB0aW9uIjoiV2lTRUNVUkUgQXV0aFRyb24gVVNCIEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJ6aC1UVyI6IldpU0VDVVJFIEF1dGhUcm9uIFVTQiBGSURPMiDouqvku73pqZforYnlmagifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURSakNDQXUyZ0F3SUJBZ0lVWlBoU0R0eEk1bGcycWd5KzdJR0RKaEdxUE9nd0NnWUlLb1pJemowRUF3SXdnWWN4Q3pBSkJnTlZCQVlUQWxSWE1ROHdEUVlEVlFRSURBWlVZV2x3WldreEVqQVFCZ05WQkFjTUNWTnZiV1YzYUdWeVpURVdNQlFHQTFVRUNnd05WMmxUUlVOVlVrVWdTVzVqTGpFZ01CNEdDU3FHU0liM0RRRUpBUllSWVdSdGFXNUFaWGhoYlhCc1pTNXZjbWN4R1RBWEJnTlZCQU1NRUZkcFUwVkRWVkpGSUZKdmIzUWdRMEV3SGhjTk1qRXdNVEk0TURneU56SXdXaGNOTXpFd01USTJNRGd5TnpJd1dqQ0JoekVMTUFrR0ExVUVCaE1DVkZjeER6QU5CZ05WQkFnTUJsUmhhWEJsYVRFU01CQUdBMVVFQnd3SlUyOXRaWGRvWlhKbE1SWXdGQVlEVlFRS0RBMVhhVk5GUTFWU1JTQkpibU11TVNBd0hnWUpLb1pJaHZjTkFRa0JGaEZoWkcxcGJrQmxlR0Z0Y0d4bExtOXlaekVaTUJjR0ExVUVBd3dRVjJsVFJVTlZVa1VnVW05dmRDQkRRVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQmlXdkZhZi9JaEZNT1dOcWx3ZXFyNEdmTzBtdS8xQjE4SjAzT0crcFNsdFJpeDlHalJvakJ5YTRMQVJ5WE1QOG53MlhoOVB2d09CbTlRZWRNQzY2WEdqZ2dFek1JSUJMekFkQmdOVkhRNEVGZ1FVZCtZdmo2STNZOGNLSDNRUk5MbEM4L09wOTdjd2djY0dBMVVkSXdTQnZ6Q0J2SUFVZCtZdmo2STNZOGNLSDNRUk5MbEM4L09wOTdlaGdZMmtnWW93Z1ljeEN6QUpCZ05WQkFZVEFsUlhNUTh3RFFZRFZRUUlEQVpVWVdsd1pXa3hFakFRQmdOVkJBY01DVk52YldWM2FHVnlaVEVXTUJRR0ExVUVDZ3dOVjJsVFJVTlZVa1VnU1c1akxqRWdNQjRHQ1NxR1NJYjNEUUVKQVJZUllXUnRhVzVBWlhoaGJYQnNaUzV2Y21jeEdUQVhCZ05WQkFNTUVGZHBVMFZEVlZKRklGSnZiM1FnUTBHQ0ZHVDRVZzdjU09aWU5xb012dXlCZ3lZUnFqem9NQXdHQTFVZEV3RUIvd1FDTUFBd05nWURWUjBmQkM4d0xUQXJvQ21nSjRZbGFIUjBjRG92TDNkM2R5NWxlR0Z0Y0d4bExtOXlaeTlsZUdGdGNHeGxYMk5oTG1OeWJEQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQmYzcDhMSjNQbGZNc3hUeldnakhhYWw2dXpJbzV0eDNvK0VVeWJkRFk0b2dJZ1Y2blIxTVVFMXdLejF1Qzcva0VOZy9GcEpPZXRGYUplUGNnb25lRXdzS0E9IiwiTUlJQ016Q0NBZG1nQXdJQkFnSVViYXJWOFBxQzlJbmsxZGtvRFh1TzV6aFA4Mmd3Q2dZSUtvWkl6ajBFQXdJd2VERUxNQWtHQTFVRUJoTUNWRmN4S2pBb0JnTlZCQW9NSVZkcFUwVkRWVkpGSUZSbFkyaHViMnh2WjJsbGN5QkRiM0p3YjNKaGRHbHZiakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVaTUJjR0ExVUVBd3dRVjJsVFJVTlZVa1VnVW05dmRDQkRRVEFnRncweU1qQXpNak13TkRBeU5UZGFHQTh5TURVeU1ETXhOVEEwTURJMU4xb3dlREVMTUFrR0ExVUVCaE1DVkZjeEtqQW9CZ05WQkFvTUlWZHBVMFZEVlZKRklGUmxZMmh1YjJ4dloybGxjeUJEYjNKd2IzSmhkR2x2YmpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFWk1CY0dBMVVFQXd3UVYybFRSVU5WVWtVZ1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQlBOV0xLQUdPVWZScEJPSEVmamRMcldQNnNIa0ZURVBPeFVkT3p1NStTVkFSNEtxTm90dndsdDhaVExGeTZ0Q1YvOUNxMWZRRUpjYmxwQUczTTJ2K3BhalB6QTlNQjBHQTFVZERnUVdCQlJNcnB6L1Vvb21FeEZJU2g2YUtaUUcyN0piampBTUJnTlZIUk1FQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQkJqQUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQWVJSEVpckNWQ3VPeWE2aC9yYUg0T1paYnF1OTQzNFpVR1lCR1F0Z0RUblFJaEFPeWxBM3o2S0N3R0xuYkZCd2lLRHdqY2gwakV1ek5ndmRoTHR5aG5FbVJKIiwiTUlJREVqQ0NBcmVnQXdJQkFnSVVMS0xCU1Z3RHE5aXQzcCsweXZ5Q1BrMkZGTG93Q2dZSUtvWkl6ajBFQXdJd2RqRUxNQWtHQTFVRUJoTUNWRmN4RHpBTkJnTlZCQWdNQmxSaGFYQmxhVEVQTUEwR0ExVUVCd3dHVkdGcGQyRnVNU293S0FZRFZRUUtEQ0ZYYVZORlExVlNSU0JVWldOb2JtOXNiMmRwWlhNZ1EyOXljRzl5WVhScGIyNHhHVEFYQmdOVkJBTU1FRmRwVTBWRFZWSkZJRkp2YjNRZ1EwRXdJQmNOTWpFd05EQTNNVEV4TmpBMFdoZ1BNakEzTVRBek1qWXhNVEUyTURSYU1IWXhDekFKQmdOVkJBWVRBbFJYTVE4d0RRWURWUVFJREFaVVlXbHdaV2t4RHpBTkJnTlZCQWNNQmxSaGFYZGhiakVxTUNnR0ExVUVDZ3doVjJsVFJVTlZVa1VnVkdWamFHNXZiRzluYVdWeklFTnZjbkJ2Y21GMGFXOXVNUmt3RndZRFZRUUREQkJYYVZORlExVlNSU0JTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVFSFVld1BwV2J4UXJLQjd6bEltR3RTRjAxbUtISlEyZjRhaUp2VVVKdENnbStMTUpIbUJjMElNZUZWTTBIYk5Nc3BYdWNVUTkzZmNLakJ5MTh2RUFncU9DQVI4d2dnRWJNQjBHQTFVZERnUVdCQlRId3pjSjNYb1JjMzczWTdOWElzYTJJZXBrZXpDQnN3WURWUjBqQklHck1JR29nQlRId3pjSjNYb1JjMzczWTdOWElzYTJJZXBrZTZGNnBIZ3dkakVMTUFrR0ExVUVCaE1DVkZjeER6QU5CZ05WQkFnTUJsUmhhWEJsYVRFUE1BMEdBMVVFQnd3R1ZHRnBkMkZ1TVNvd0tBWURWUVFLRENGWGFWTkZRMVZTUlNCVVpXTm9ibTlzYjJkcFpYTWdRMjl5Y0c5eVlYUnBiMjR4R1RBWEJnTlZCQU1NRUZkcFUwVkRWVkpGSUZKdmIzUWdRMEdDRkN5aXdVbGNBNnZZcmQ2ZnRNcjhnajVOaFJTNk1Bd0dBMVVkRXdFQi93UUNNQUF3TmdZRFZSMGZCQzh3TFRBcm9DbWdKNFlsYUhSMGNEb3ZMM2QzZHk1bGVHRnRjR3hsTG05eVp5OWxlR0Z0Y0d4bFgyTmhMbU55YkRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQXZ4QytGcnBHSUhMN1dwOXU1ZDVQdHlFYU94U1pNWmVVTmNjN3ZrMjNSYThDSVFEdWJPeTVLQ25reVZmSHIrT3JQZk4rOElzRGpUaTdyR1NXV2loOUIyWS9aUT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBdGhKUkVGVWVOcnNsdDlMazFFWXg3L3ZOdGUwdlhPazd5UzdxeVdCWXZuaklrdEdVMHZEQ3drdFY0S1hwdjN3Qi80QkJpSWEvUUMxd2prVlV4TnNVdXV1emQxazZpQkxDeElGemNEWE9UWndZOHIyc3IxcnA0dVhadW9nZ3J5SmZTOGVlTDZjNTN3NDUrRTVISW9RZ29PVUNBZXNHQ0FHaUFFQXlYNkxaZG4xOVhXR1lkUnE5VDhna04xcWEyMFZEbFZaY1pVUVlwdVpLUzB0SFRjYTl5d3o2SHVycTZzL3pzNlNQMmtYd0dJMkF6aktxSFE2M2Z0M2s0U1Fwb1lHQU1XRlJYdktMbW9MQUF3T0RQd2RvTGRIRDJCa2FPaDM4NDNKNUhLNTlwVFYxZHdFOEdwOGZQK09TNHRMNXJmbUg2R1FrTzcwb0x1emMyand1U29wMmRCck9DeW5rNUtPOVBYM1oyWmtNQ2twcXl2ZkdJWUJjTCs5dzJxZEtDb3FDZ1FDQUhpZUYyb2ZQM3hrTXIxVzBJcmF1bHB0UVlIUDd3TkY3ZTJCTmw4RElPMzRDUUFOZCt1N3U3b0FTRUFCcUt1cEpZUlU2YTREb0dYeHFhb1VwWndXQTlhSkNVSkk0UVV0Z0ZQcWt3blNRd0Q2OVByb1Z4UU1CdHZiMmlpS2V0RFJ3Zk44S0JUaU9PN1prNmNBK25vTkxNc0N5TW84emZuOUhNZmxuTWtDc0xTNE9EMDFEVUIzOVJvaHhPbDB5aE1TNGlpUjNXNlBiTHN6QjNGeGNiUkNRUWhSSkNaS0pCS3hXQ3lUeWVSeUdvQlVLdjB5L3htQVRsY3BpNCtYeVdRYWpRYUF6K2VibXB3RVVGNVJEa0NsVWhWcUMzZ1NucCtiaXo0SG5OOFB3Ty8zUjV4QWdNdk56azVta2tXVUNNRHE2bmZCZHpnMkJEQ3RVQUJ3T2wyL2ZJZEFpZzRJQm9PUktJam5lUVZOYjNtM2lpK1hpRUhwK3d6cEdlbHV0L3VsMFFnZ0VBaVVYU203ZGVmMnZaYVd0TFMwaFlXdkgrWSs1Wi9OeThuTmpmNVVTQ1NTU0l3NDRYRFk0ZGhRS3BYRHc4TmlpcXB2YkJ3ZGVWRjFvd29BdTdhV21uck0wS1BmM3Q2K1ZGTGMxTng4UHUvYzZOaVlTQ1NLUHNrZXQyZDVlZG5qOFVRY3I5ZHJYN2U3M1p0Q3lySnJWcXMxSEE0VFFwWlhWcnhlcitDN045MFdpOFZtcyswZkN5cjJxNGdCWW9EL0FQQnpBSTZWTnFHUVBVcW5BQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI1MDRkNzE0OTRlNGMzODQxNDU1NTU1NDQ1YTY3NzM1NyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6MjUsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9LHsidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi04fV0sImZpcm13YXJlVmVyc2lvbiI6Mn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTExLTExIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJBdXRoVHJvbiBVU0IgS2V5IEZJRE8yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMTA0MjEwMDIiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMyIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIxLTExLTExIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMS0xMS0xMSJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjNiYzEyMTFjMTJkOTUyYTMyYjAzYzU1Yjg4ZDNlYTZmN2QxNTJmMTgiLCI4ZGMyYTZmMjkzZWE0ODQ1YmI3NmE0MmM0MmI4OTYwMWFhYjU0N2Y4Il0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjNiYzEyMTFjMTJkOTUyYTMyYjAzYzU1Yjg4ZDNlYTZmN2QxNTJmMTgiLCI4ZGMyYTZmMjkzZWE0ODQ1YmI3NmE0MmM0MmI4OTYwMWFhYjU0N2Y4Il0sImRlc2NyaXB0aW9uIjoiR29UcnVzdCBJZGVtIEtleSBVMkYgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnFUQ0NBVStnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBN01TQXdIZ1lEVlFRRERCZEhiMVJ5ZFhOMElFWkpSRTh5SUZKdmIzUWdRMEVnTVRFWE1CVUdBMVVFQ2d3T1IyOVVjblZ6ZEVsRUlFbHVZeTR3SUJjTk1qRXdNekF5TURZeE9EUTRXaGdQTWpBMU1UQXlNak13TmpFNE5EaGFNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXhNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJJemtNZHROWnQwWk96Tyt1MWYyRUtaUlNuZmh2eXdiaG9uQkY5TlNQcTJXRzdudVJpL3l2WjhsRGp3cDVkYXJRNk9kWmcrSHFiU1NlWEpYdzdVcGNsU2pRakJBTUE4R0ExVWRFd1FJTUFZQkFmOENBUUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQjBHQTFVZERnUVdCQlJqV3hUbzFFcTMzWnJ4ZkxEV3NzZGRiRC92WlRBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlCK0UwOUd6bWNZbE05NXFUL2FmblBVOXE2WEpteE9TS1dBUk81K2tnVW5XZ0loQUlhOW41cDQwdGNHZm1lRjYvV3ZZb2pBTnV5a1FxaFZrOFduZmcxNVM2OXIiLCJNSUlCenpDQ0FYYWdBd0lCQWdJQ0FTQXdDZ1lJS29aSXpqMEVBd0l3T3pFZ01CNEdBMVVFQXd3WFIyOVVjblZ6ZENCR1NVUlBNaUJTYjI5MElFTkJJREV4RnpBVkJnTlZCQW9NRGtkdlZISjFjM1JKUkNCSmJtTXVNQ0lZRHpJd01Ua3hNakEwTURZMU9UUXdXaGdQTWpBMU1UQTBNRGN3TXpBMU1EQmFNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXhNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBNW1qWXNqb3dBSTBqbnBpLy9DSjNLbnpoR2JUVW1zdE5XcU43OGlvRzFDVEs5Z1BnUGw5VWlGT0pPL3YrRmZGSytQeHYxMGM2MDRkdmxJREFiS3craWpaakJrTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0RnWURWUjBQQVFIL0JBUURBZ0VHTUIwR0ExVWREZ1FXQkJTZ1d0WTBuRWNtUG1HREx1Q3djZUtlSlBTY296QWZCZ05WSFNNRUdEQVdnQlNnV3RZMG5FY21QbUdETHVDd2NlS2VKUFNjb3pBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBa3JMTTVWM0RuRDBYY1ZVRlcrTk1GY0JaQ08xRnh5WXo0VmtQSDNBN0tHUUlnSGF5VGZVODhvSUVpTU5heDEzdGdaYW9oaE1BWEVNanFUeUl0YmNUVDhRYz0iLCJNSUlCelRDQ0FYT2dBd0lCQWdJSkFMUzNTaWJHRFhUUE1Bb0dDQ3FHU000OUJBTUNNRHN4SURBZUJnTlZCQU1NRjBkdlZISjFjM1FnUmtsRVR6SWdVbTl2ZENCRFFTQXhNUmN3RlFZRFZRUUtEQTVIYjFSeWRYTjBTVVFnU1c1akxqQWVGdzB4T1RFeU1EUXdOalU1TkRCYUZ3MDBPVEV4TWpZd05qVTVOREJhTURzeElEQWVCZ05WQkFNTUYwZHZWSEoxYzNRZ1JrbEVUeklnVW05dmRDQkRRU0F4TVJjd0ZRWURWUVFLREE1SGIxUnlkWE4wU1VRZ1NXNWpMakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQTVtallzam93QUkwam5waS8vQ0ozS256aEdiVFVtc3ROV3FONzhpb0cxQ1RLOWdQZ1BsOVVpRk9KTy92K0ZmRksrUHh2MTBjNjA0ZHZsSURBYkt3K2lqWURCZU1Bd0dBMVVkRXdFQi93UUNNQUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQjBHQTFVZERnUVdCQlNnV3RZMG5FY21QbUdETHVDd2NlS2VKUFNjb3pBZkJnTlZIU01FR0RBV2dCU2dXdFkwbkVjbVBtR0RMdUN3Y2VLZUpQU2NvekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUF4b1ZzNnFqN0RYMnhpeENqamNEVWR4QlRKbVNUTGIwZjFyUkd3ckFCelRRSWhBUHQwUDMycXpBZWVwRjQvL3RnenhxTm9La1dEY2FQUFNYcmcreHpybFZIdyJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFqQ0FZQUFBRDE3Z2hhQUFBQUJHZEJUVUVBQUxHT2ZQdFJrd0FBQUNCalNGSk5BQUNIRHdBQWpBOEFBUDFTQUFDQlFBQUFmWGtBQU9tTEFBQTg1UUFBR2N4elBJVjNBQUFLTDJsRFExQkpRME1nVUhKdlptbHNaUUFBU01lZGxuZFVWTmNXaDgrOWQzcWh6VERTR1hxVExqQ0E5QzRnSFFSUkdHWUdHTW9Bd3d4TmJJaW9RRVFSRVFGRmtLQ0FBYU9oU0t5SVlpRW9xR0FQU0JCUVlqQ0txS2hrUnRaS2ZIbDU3K1hsOThlOTM5cG43M1AzMlh1ZnRTNEFKRThmTGk4RmxnSWdtU2ZnQjNvNDAxZUZSOUN4L1FBR2VJQUJwZ0F3V2VtcHZrSHV3VUFrTHpjWGVycklDZnlMM2d3QlNQeStaZWpwVDZlRC8wL1NyRlMrQUFESVg4VG1iRTQ2UzhUNUlrN0tGS1NLN1RNaXBzWWtpaGxHaVprdlNsREVjbUtPVytTbG4zMFcyVkhNN0dRZVc4VGluRlBaeVd3eDk0aDRlNGFRSTJMRVI4UUZHVnhPcG9odmkxZ3pTWmpNRmZGYmNXd3loNWtPQUlva3RnczRySGdSbTRpWXhBOE9kQkh4Y2dCd3BMZ3ZPT1lMRm5DeUJPSkR1YVNrWnZPNWNmRUN1aTVMajI1cWJjMmdlM0l5a3pnQ2dhRS9rNVhJNUxQcExpbkpxVXhlTmdDTFovNHNHWEZ0NmFJaVc1cGFXMW9hbWhtWmZsR28vN3I0TnlYdTdTSzlDdmpjTTRqVzk0ZnRyL3hTNmdCZ3pJcHFzK3NQVzh4K0FEcTJBaUIzL3crYjVpRUFKRVY5YTcveHhYbG80bm1KRndoU2JZeU5Nek16amJnY2xwRzRvTC9yZnpyOERYM3hQU1B4ZHIrWGgrN0tpV1VLa3dSMGNkMVlLVWtwUWo0OVBaWEo0dEFOL3p6RS96andyL05ZR3NpSjVmQTVQRkZFcUdqS3VMdzRVYnQ1Yks2QW04S2pjM24vcVluL01PeFBXcHhya1NqMW53QTF5Z2hJM2FBQzVPYytnS0lRQVJKNVVOejEzL3ZtZ3c4RjRwc1hwanF4T1BlZkJmMzdybkNKK0pIT2pmc2M1eElZVEdjSitSbUxhK0pyQ2RDQUFDUUJGY2dERmFBQmRJRWhNQU5Xd0JZNEFqZXdBdmlCWUJBTzFnSVdpQWZKZ0E4eVFTN1lEQXBBRWRnRjlvSktVQVBxUVNOb0FTZEFCemdOTG9ETDREcTRDZTZBQjJBRWpJUG5ZQWE4QWZNUUJHRWhNa1NCNUNGVlNBc3lnTXdnQm1RUHVVRStVQ0FVRGtWRGNSQVBFa0s1MEJhb0NDcUZLcUZhcUJINkZqb0ZYWUN1UWdQUVBXZ1Vtb0oraGQ3RENFeUNxYkF5ckEwYnd3ellDZmFHZytFMWNCeWNCdWZBK2ZCT3VBS3VnNC9CN2ZBRitEcDhCeDZCbjhPekNFQ0lDQTFSUXd3UkJ1S0MrQ0VSU0N6Q1J6WWdoVWc1VW9lMElGMUlMM0lMR1VHbWtYY29ESXFDb3FNTVViWW9UMVFJaW9WS1EyMUFGYU1xVVVkUjdhZ2UxQzNVS0dvRzlRbE5SaXVoRGRBMmFDLzBLblFjT2hOZGdDNUhONkRiMEpmUWQ5RGo2RGNZRElhRzBjRllZVHd4NFpnRXpEcE1NZVlBcGhWekhqT0FHY1BNWXJGWWVhd0IxZzdyaDJWaUJkZ0M3SDdzTWV3NTdDQjJIUHNXUjhTcDRzeHc3cmdJSEErWGh5dkhOZUhPNGdaeEU3aDV2QlJlQzIrRDk4T3o4ZG40RW53OXZndC9BeitPbnlkSUUzUUlkb1JnUWdKaE02R0MwRUs0UkhoSWVFVWtFdFdKMXNRQUlwZTRpVmhCUEU2OFFod2x2aVBKa1BSSkxxUklrcEMwazNTRWRKNTBqL1NLVENacmt4M0pFV1FCZVNlNWtYeVIvSmo4Vm9JaVlTVGhKY0dXMkNoUkpkRXVNU2p4UWhJdnFTWHBKTGxXTWtleVhQS2s1QTNKYVNtOGxMYVVpeFJUYW9OVWxkUXBxV0dwV1dtS3RLbTBuM1N5ZExGMGsvUlY2VWtackl5MmpKc01XeVpmNXJETVJaa3hDa0xSb0xoUVdKUXRsSHJLSmNvNEZVUFZvWHBSRTZoRjFHK28vZFFaV1JuWlpiS2hzbG15VmJKblpFZG9DRTJiNWtWTG9wWFFUdENHYU8rWEtDOXhXc0pac21OSnk1TEJKWE55aW5LT2NoeTVRcmxXdVR0eTcrWHA4bTd5aWZLNzVUdmtIeW1nRlBRVkFoUXlGUTRxWEZLWVZxUXEyaXF5RkFzVlR5amVWNEtWOUpVQ2xkWXBIVmJxVTVwVlZsSDJVRTVWM3E5OFVYbGFoYWJpcUpLZ1VxWnlWbVZLbGFKcXI4cFZMVk05cC9xTUxrdDNvaWZSSytnOTlCazFKVFZQTmFGYXJWcS8ycnk2am5xSWVwNTZxL29qRFlJR1F5TldvMHlqVzJOR1UxWFRWek5YczFuenZoWmVpNkVWcjdWUHExZHJUbHRITzB4N20zYUg5cVNPbkk2WFRvNU9zODVEWGJLdWcyNmFicDN1YlQyTUhrTXZVZStBM2sxOVdOOUNQMTYvU3YrR0FXeGdhY0ExT0dBd3NCUzkxSG9wYjJuZDBtRkRrcUdUWVlaaHMrR29FYzNJeHlqUHFNUG9oYkdtY1lUeGJ1TmU0MDhtRmlaSkp2VW1EMHhsVEZlWTVwbDJtZjVxcG0vR01xc3l1MjFPTm5jMzMyamVhZjV5bWNFeXpyS0R5KzVhVUN4OExiWlpkRnQ4dExTeTVGdTJXRTVaYVZwRlcxVmJEVE9vREg5R01lT0tOZHJhMlhxajlXbnJkemFXTmdLYkV6YS8yQnJhSnRvMjJVNHUxMW5PV1Y2L2ZNeE8zWTVwVjJzM1lrKzNqN1kvWkQvaW9PYkFkS2h6ZU9LbzRjaDJiSENjY05KelNuQTY1dlRDMmNTWjc5em1QT2RpNDdMZTVid3I0dXJoV3VqYTd5YmpGdUpXNmZiWVhkMDl6cjNaZmNiRHdtT2R4M2xQdEtlMzUyN1BZUzlsTDVaWG85Zk1DcXNWNjFmMGVKTzhnN3dydlovNDZQdndmYnA4WWQ4VnZudDhINjdVV3NsYjJlRUgvTHo4OXZnOTh0ZnhUL1AvUGdBVDRCOVFGZkEwMERRd043QTNpQklVRmRRVTlDYllPYmdrK0VHSWJvZ3dwRHRVTWpReXRERjBMc3cxckRSc1pKWHhxdldycm9jcmhIUERPeU93RWFFUkRSR3pxOTFXNzEwOUhta1JXUkE1dEVablRkYWFxMnNWMWlhdFBSTWxHY1dNT2htTmpnNkxib3Ird1BSajFqRm5ZN3hpcW1ObVdDNnNmYXpuYkVkMkdYdUtZOGNwNVV6RTJzV1d4azdHMmNYdGladUtkNGd2ajUvbXVuQXJ1UzhUUEJOcUV1WVMvUktQSkM0a2hTVzFKdU9TbzVOUDhXUjRpYnllRkpXVXJKU0JWSVBVZ3RTUk5KdTB2V2t6Zkc5K1F6cVV2aWE5VTBBVi9VejFDWFdGVzRXakdmWVpWUmx2TTBNelQyWkpaL0d5K3JMMXMzZGtUK1M0NTN5OURyV090YTQ3VnkxM2MrN29lcWYxdFJ1Z0RURWJ1amRxYk16Zk9MN0pZOVBSellUTmladC95RFBKSzgxN3ZTVnNTMWUrY3Y2bS9MR3RIbHViQ3lRSytBWEQyMnkzMVd4SGJlZHU3OTlodm1QL2prK0Y3TUpyUlNaRjVVVWZpbG5GMTc0eS9hcmlxNFdkc1R2N1N5eExEdTdDN09MdEd0cnRzUHRvcVhScFR1bllIdDg5N1dYMHNzS3kxM3VqOWw0dFgxWmVzNCt3VDdodnBNS25vbk8vNXY1ZCt6OVV4bGZlcVhLdWFxMVdxdDVSUFhlQWZXRHdvT1BCbGhybG1xS2E5NGU0aCs3V2V0UzIxMm5YbFIvR0hNNDQvTFErdEw3M2E4YlhqUTBLRFVVTkg0L3dqb3djRFR6YTAyalYyTmlrMUZUU0REY0xtNmVPUlI2NytZM3JONTB0aGkyMXJiVFdvdVBndVBENHMyK2p2eDA2NFgyaSt5VGpaTXQzV3Q5VnQxSGFDdHVoOXV6Mm1ZNzRqcEhPOE02QlV5dE9kWGZaZHJWOWIvVDlrZE5xcDZ2T3lKNHBPVXM0bTM5MjRWek91ZG56cWVlbkw4UmRHT3VPNm41d2NkWEYyejBCUGYyWHZDOWR1ZXgrK1dLdlUrKzVLM1pYVGwrMXVYcnFHdU5heDNYTDYrMTlGbjF0UDFqODBOWnYyZDkrdytwRzUwM3JtMTBEeXdmT0Rqb01YcmpsZXV2eWJhL2IxKytzdkRNd0ZESjBkemh5ZU9RdSsrN2t2YVI3TCs5bjNKOS9zT2toK21IaEk2bEg1WStWSHRmOXFQZGo2NGpseUpsUjE5RytKMEZQSG95eHhwNy9sUDdUaC9IOHArU241Uk9xRTQyVFpwT25wOXluYmo1Yi9XejhlZXJ6K2VtQ242Vi9ybjZoKytLN1h4eC82WnRaTlRQK2t2OXk0ZGZpVi9LdmpyeGU5cnA3MW4vMjhadmtOL056aFcvbDN4NTl4M2pYK3o3cy9jUjg1Z2ZzaDRxUGVoKzdQbmwvZXJpUXZMRHdHL2VFOC9zM0JDa2VBQUFBQ1hCSVdYTUFBQTdFQUFBT3hBR1ZLdzRiQUFBQUlYUkZXSFJEY21WaGRHbHZiaUJVYVcxbEFESXdNVGc2TURVNk1qZ2dNVFk2TkRJNk1UVDlod3JmQUFBSUhVbEVRVlJZUjUxWEMxQlU1eFgrZGxsZ1FkNFBVUkFmaVNoYU5HMWk3Qmh0bTA1S1VrblRXQitOUWEwWUcyT0Rsam9PR2sxaU81MXFOR1Fjazlva1JKczA0SXc2cHVOMFRFeFRhT3NZUzdTU3BocGYxS0FWQlJaaFdSNHJJTHQ3YjcvejM3dnNRaGFDL1M3L3N2ejN2TS81ei9teDZBU0dDWjJQL0ZnczhwZjY2SU5mak1WNE9XeFl6ZC9EZytaWFlFSGxKNS9qdmdXYjhPanFIV2hzY2FuOU8xVXVHRjRFaE1RVTN0cmhSdDdxbDNHcXNocElpQUY4UHFEck5wWVY1T0gxRjFjZ0pqb3FLRkxDSStJSE4yeDRFVENWLzN6Ykg1QThjUkZPVlY4Q1JpY0RVWkZBTkpmVml2SURGYWo2OXhlS1Rpa2tqNmJSRkgxdzVZSkJJdERmNmo5Vm5zYThaM2JRV3k4UVM2K3Q1anQzdDRyQTFzMEYyTHpxY1dPUDZMMWFwNHlLR0RmRzNDRUdDNFFZRUF5Tmp4KzExNXYwS1krdTE1R1dweU1uWDhjMFdVdDFaRCtoSStsaGZXSFJUdDNyOVpuVUJocFhiZFRQSVZ3L2p4RzZZODBXYzVkeWZRRzV3UmkwQnZLTGQyTi8yUWZNY3l4Z1o1Z0ZrdStXZG95Y09BWlYrMytOdXpQVGpIM0N0ZnNkT05ZVzAxRWZ3cERBSFkxUEIvKzJJV05mS2VLWHpEY0lCOENpTVZIQjFmdjJINDloWldFSk1NSU94SXpnRHUzVFdQNGRYVFRFaHZKWGlyRDBzVGtHTWRGVGZRWjEzMTRBWDNjakZiTXUrQ2xRaGFoaTd1WFRnc2praVJoejdCRHNPZG5xRFZnZkZxYXlMd0pmWEcvQzdDVy93czNMekY5S29sR2U4cWFuVnlsZnUzWWhYbnUrUUVnVnZNMnRhSmozRkRxcmp0TEhWTzdZMUw1RXdJZDJxclpRUkx6Nk5QWTkzRzlHYk80aVpCNHRKM21ZTXEvUEFNdTRIOUhEQ0s1d1E3R1BYamUxWXNhRDk2TGluUmVZaVdnaFUzQ3NmZzdPMHRmb2F3eUZSQ3RCdWdxNUMySFdSR1JXSFlidTlURXk4NkZyN2FSTDRuc3hpV0pwbkMwcEExbk9jMHFXTXErK3ljV3ozQU5FbXNwN2JzTVdic1hISCszQzZmZTI5U2x2ZS9jUUxsamk0Q3A5aS82bWtGbVVpODl1cmphTTNMb2RrM3gxaVBybWZZaWVQUlBadmhzWXViMkVLV2dtdDRlVU9ubGk0V210ZytabVNna1ZBWWV6RGFOemxnSnBTVHhEWHFTUFRrTDlYM2NyQWtIM3ljOXc0NGNyNEdtdVVlRVdNWVkzM2FyUUVuOWNnUFNEYnhqRVJBZUZoOW1zTENQV2tZbmFqQm53TlRTUkw0d0d0V055VnlPc1VYWXpRU0pPTXFHV3h2N0NWSmk0Tm1zZXJzeWFCYTM1SnBWTDFRdUxGNzFvZ0gzYTF6Q3BycmFmOHBLM2p5QithajVpNk5EcmJFNSsyTWFtMDFpdmlvSlJuTExNRkNpb1BXUFRMQXNGOTBrcHNsSDhKa2RSd3UxVVFpYjhwUUlUenY0TjRabnBpdTVFOVVWRTVPUmp3NWE5UUJ4VEZoR093azBCdytRSUc5TDdJMkNBNkF4UzdFY1k3R1NVRXBJaTYwYnE5aDNJMXVzeEl2Yzc2djMxbXk1TW03Y0IzM3FrQ0I1aFQ0NGpFNDhpajVoTkRQa0tCQXdZQk1vdXRYZ3E2RlhLeG1mVnZxQjljU0hHM3JNTTV5NWVBektZbnJCUVBnYndaZmNHU2NGQXlBRlNqOFVnYjMxMUR5NWFZdUErZUFqVzlCVGo5SWlCYnA2a0xzNEh2eVpwWUVFWU9nWHNUQU1aQk1JazNpdVoxa2hjdWVzQk5QNWlIVk9UeUhuRHdTUkdkN05aT1Z3b0xseUFqVDliUUNONHhDZ3FNdHhvVG41STdSaEZHRURBQUU0dnRRWkFUTExLWTJIbjZ2YkF3MGtuUFVCMmRhMFhXa01MN3YxNkZ0cHEzOFBMNi9QWmlHaVFNUEdYUFZ3aUU0Q1N3eWNZUVJFZ1Y0Z2lORG9jUDNrOGpXNG12VjVUcDhFZGw0REtEM2JpMDBOYkVXODJLMWNudlRmSGRiQTArUzZTNUFsRy93aUVxQUdibW15R2Fqa05HanBWMTB2NzdXNU1haitIaDc2UnBlamFlVGVZdGZnRnZQSDdJN3lrUkNtZVlJamtyNDVBaUJxUXJxV2hoK0o2MkV3YmtMQnlKYWJxSFVoYUV4aE1ULzl5RHhMR1BZNlQvNnBoRCtBRUZXMnNxYzViUnJzVkRCMEJDWDFRRGRnNHFmeklkckczVDc4SEVWT21ZSEp6RTBidDVhZzI4ZGJCU2xnbXpNZmVzZytCZEU1RXVUZElGQ1VObkNjbHhjdE1TbTVUdGhIRi9sRldHbFhxbVdQMWhVM2s4alVIL256aWpMeENXRUlpeHA5aDE3dndkOWhTT0N1STA1OWZRY29EcS9ETXVsMjhNekRjZnE5djh6VGNhTWFTUmQrRmZ2VXdpcGJuS1hxQnQxRUdFZ3QzUUdxVUFaR1I5RmpHcjRBRnBETVZjeGMraHlrL0tFYWR3Mm5zRTIyOEY4eGMvQ0ptUGxRSVoxdUhlVytnQ0M5NUcxdVJNM2s4NmkvdHg3NGRhMHdPOHJ4Wnpna2FEMi9kTmRvWXJpS2dNN0hRZUxzaSttNUV1U3QrdzRyK0I1QnFDcFZLRm8rYTIvRFRaK2NqbFMzMnBhM3ZBb2xCVnpTcG1YWTM1M3NjanY1dUEzTG5URGYyaWE0VHAxRC95Rko0dWhwWXlNbFVha3hRTDBlM0xUNEZrOXA0c3laTUE5UlhsQjA1Z2VVYk9JYWxveVdhVFVad2k5MU5HbFdNakZkelQvSk1iTnU4SEp1ZUR0eUl2YzFPM0ppN0RMYytyZUNCVFNPMVRYR0kxeDdjUk95TTd5SHo0OE93MEFuWlZ3WUlZL0M5c0xoa0gxNTVxWXlEaFVjd2lxTlp2ZU9TT3VuMXNPczU4Y1JUaitIQXppS0R3VVRqVDliQlZWNUt4WEdrdGxPcDhQbW91aFVSOWpSa1ZCN2dSZVYrZzFqcVRlVEtoU1FVdkpwUG4vM2tGbDdKNXhyWDhLbFBxdTlaMzErbk8xcmFUQ29EemxmMzhDcHU1MVU4VWE5Qkp0ZFkvUkxYQmY1OUhyRzZzN1RNcEpScmYvOXIvSmNNa0lqd3B3L1Y1MnYxMURtcmRRdi9MM2ovK0dmbXJvSE9pdVA2ZjJLenFDUmFLYXpCZUs1eCtrV2tjUzlLYnloWWIxSUtSSzZ4Z2pIby93VkR3Y09yVmIzaytleHhoanVGZ1phaEkySWt6MDJJdVQ4WFk5N2ZCOXRJS1Q2VnZFRmhkSjRoSVNJQ05qYXRmUjQxR2FQUWZmWXMxWTd1VTY0eHo5WUlPKzZxK2dUai8vbWhvVng4QzdDR2hrVGdUbkQ3OG4vMXE5TWZaczRqR2VwVWhqcWV1VTdTbmJ2Mm1oUjNoanN5UUdOaCtqUG8vdWlZWHBlWHJ6dUt0Z1Q5TnhuNi83K2g4SC9WUUNpSWtLRnlIUnJBL3dDNGUrTytaMWNuNFFBQUFBQkpSVTVFcmtKZ2dnPT0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wMy0wOSIsInVybCI6Imh0dHBzOi8vd3d3LmdvdHJ1c3RpZC5jb20vaWRlbS1rZXkiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlUyRiBBdXRoZW50aWNhdG9yIChJZGVtIFNlbnNlKSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTYwMzIzMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjIuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDktMTgiLCJ1cmwiOiJodHRwczovL3d3dy5nb3RydXN0aWQuY29tL2lkZW0ta2V5IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJVMkYgQXV0aGVudGljYXRvciAoSWRlbSBTZW5zZSkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDE2MDMyMzAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yLjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMy4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA5LTExIiwidXJsIjoiaHR0cHM6Ly93d3cuZ290cnVzdGlkLmNvbS9pZGVtLWtleSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiVTJGIEF1dGhlbnRpY2F0b3IgKElkZW0gU2Vuc2UpIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAxNjAzMjMwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMi4wIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMDMtMDkifSx7ImFhZ3VpZCI6ImEzOTc1NTQ5LWIxOTEtZmQ2Ny1iOGZiLTAxN2UyOTE3ZmRiMyIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiYTM5NzU1NDktYjE5MS1mZDY3LWI4ZmItMDE3ZTI5MTdmZGIzIiwiZGVzY3JpcHRpb24iOiJFeGNlbHNlY3UgZVNlY3UgRklETzIgTkZDIFNlY3VyaXR5IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyNTYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNTRENDQWUyZ0F3SUJBZ0lKQU05UnpZdTRFSUlsTUFvR0NDcUdTTTQ5QkFNQ01IOHhDekFKQmdOVkJBWVRBa05PTVN3d0tnWURWUVFLRENORmVHTmxiSE5sWTNVZ1JHRjBZU0JVWldOb2JtOXNiMmQ1SUVOdkxpd2dUSFJrTGpFZU1Cd0dBMVVFQ3d3VlJYaGpaV3h6WldOMUlFWnBaRzhnVTJWeWRtVnlNU0l3SUFZRFZRUUREQmxGZUdObGJITmxZM1VnUm1sa2J5QlNiMjkwSUVOQklEQXlNQ0FYRFRFNU1UQXlNekE1TlRBME0xb1lEekl3TlRreE1ERXpNRGsxTURReldqQi9NUXN3Q1FZRFZRUUdFd0pEVGpFc01Db0dBMVVFQ2d3alJYaGpaV3h6WldOMUlFUmhkR0VnVkdWamFHNXZiRzluZVNCRGJ5NHNJRXgwWkM0eEhqQWNCZ05WQkFzTUZVVjRZMlZzYzJWamRTQkdhV1J2SUZObGNuWmxjakVpTUNBR0ExVUVBd3daUlhoalpXeHpaV04xSUVacFpHOGdVbTl2ZENCRFFTQXdNakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSGxxMmpVUU1hbEhqL0JSZVFlZkdpejRFdllKeUZMV1B6NFJmaEpHS3FxbCs4bjk2aFQxbTVnWG9Udm9McmpTVTdYMGNCZW9Uc2doeWgyMit5cnM0K1NqVURCT01CMEdBMVVkRGdRV0JCUSs4U0dXMkJYYnFiMmRjQU9pV0pPVStHQ3NQakFmQmdOVkhTTUVHREFXZ0JRKzhTR1cyQlhicWIyZGNBT2lXSk9VK0dDc1BqQU1CZ05WSFJNRUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEcTh4SVcwWks1eXozRUF6bXV4ODhMQ1RZTzE1N2ZUZnlPaU96QzJBRHlhd0loQU8xUFdZbGVGZ0gvM211RDhjQkFNcjExZkVLZEYvQWFDMTZmdHhhZXpOWEgiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSXdBQUFBWUNBWUFBQUFvTnhWckFBQUFDWEJJV1hNQUFCN0NBQUFld2dGdTBIVStBQUFGSUdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEQ5NGNHRmphMlYwSUdKbFoybHVQU0x2dTc4aUlHbGtQU0pYTlUwd1RYQkRaV2hwU0hweVpWTjZUbFJqZW10ak9XUWlQejRnUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpUVdSdlltVWdXRTFRSUVOdmNtVWdOUzQyTFdNeE5ESWdOemt1TVRZd09USTBMQ0F5TURFM0x6QTNMekV6TFRBeE9qQTJPak01SUNBZ0lDQWdJQ0FpUGlBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBpQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJaUI0Yld4dWN6cDRiWEE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM4aUlIaHRiRzV6T21SalBTSm9kSFJ3T2k4dmNIVnliQzV2Y21jdlpHTXZaV3hsYldWdWRITXZNUzR4THlJZ2VHMXNibk02Y0dodmRHOXphRzl3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzQm9iM1J2YzJodmNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSRmRuUTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpVVjJaVzUwSXlJZ2VHMXdPa055WldGMGIzSlViMjlzUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnUTBNZ0tGZHBibVJ2ZDNNcElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhPQzB3TlMweU0xUXhORG8wTURvMU5Tc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZRMjlzYjNKTmIyUmxQU0l6SWlCd2FHOTBiM05vYjNBNlNVTkRVSEp2Wm1sc1pUMGljMUpIUWlCSlJVTTJNVGsyTmkweUxqRWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0poWkc5aVpUcGtiMk5wWkRwd2FHOTBiM05vYjNBNlpXTXhaVGczTWpFdE56TTNZUzB3TlRSbExXRXpZVGt0TlRGa01UTXpORFpsWlRJNUlpQjRiWEJOVFRwUGNtbG5hVzVoYkVSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1qRTROV1l5WW1ZdE9EVm1PUzFqWmpRM0xXRmlPRGN0T1RGak0ySXpaakJpTnpobElqNGdQSGh0Y0UxTk9raHBjM1J2Y25rK0lEeHlaR1k2VTJWeFBpQThjbVJtT214cElITjBSWFowT21GamRHbHZiajBpWTNKbFlYUmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG95TVRnMVpqSmlaaTA0TldZNUxXTm1ORGN0WVdJNE55MDVNV016WWpObU1HSTNPR1VpSUhOMFJYWjBPbmRvWlc0OUlqSXdNVGd0TURVdE1qTlVNVFE2TkRBNk5UVXJNRGc2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUFvVjJsdVpHOTNjeWtpTHo0Z1BDOXlaR1k2VTJWeFBpQThMM2h0Y0UxTk9raHBjM1J2Y25rK0lEd3ZjbVJtT2tSbGMyTnlhWEIwYVc5dVBpQThMM0prWmpwU1JFWStJRHd2ZURwNGJYQnRaWFJoUGlBOFAzaHdZV05yWlhRZ1pXNWtQU0p5SWo4Ky8wVnhSUUFBR2ZWSlJFRlVhQVhWd1hmY24zVjk3L0hYNS92OVh0ZHYzRHM3SkpBSUFVTFlCWm1DaW1EVkRsZnR3MjNIcVl1cVBWMFd0ZGJXUjYzblZHMnJucmFPdHNoRHJSVWZQUjNXV1MzS1ZoQVpZUW9FUWtMV25kenpONjdyK243ZTUwNGlLTldPODU4K24ybnVpc1MvSjNHOFlaZVoyWlRFSW1EODUrUk9PMFpTVWZpSEpQNkZIeUlFV0JqQXd6Tnc2b2JJM0N5a0NHYUdKTnloTE1Xd2ducm9wTkpJQ0JOVWNvb2kwTzhiK3hmRjZQTEFxSU1jR29kMlcrellEOUZnNDlyQWdiMWkwVEpUSFdHQ3VvNlVoZUVKZGk5bVZyU044Y0tZcTQyZCs4U0tDU08yZ0F3ZElCUVFUUHg3WmxEVmRra1dielRaY0tUSTNkaHZ2ckdsdWVNOWQ4VVRYMFJyK2ptb3lZQ1FPTVNzQkxwQUFqTFFSeHBneG8rUkFtbHI0b2NJWmhlR2tGNWxCcEw0cndoSUNYTERmSCtnRHhlRmtIZ0NDZVN3Zjc4aEV6L0tqTVBFRDVJZ1JYdVJ1ZjIwcFlCWlE3MmY3U3RHSDNZbVR2eEZNaGNnQXdsaUFSTGdHV3dHTkFmV1Fxd21oc2hCY240c0dPQStsOHFDeHhtUUJVM0RTWklqOFY4VFlGQzBqWVVGYmUzMWRQMnk1WkF6VHhBUzVNWkFnUEdqelFCQjFZRHhBOVpaMEtrbWNFSEltYzkzTHZpM0hmSElrcVplalRJZ01FQU83bDhueGs4aDNZTG4zWVEwanVzTTFMeU9FTTVFNHNlQ2dPei9sUFljRUk5eFFUdHh4SGczbnVrWUlMNXJFZGdPQ0NqNGZnWVNzUjVxUmFlanEwSml1cXA0Z2hRTkx3MVY0c2VGQUs5Rk1yNUhRTFRqUWd5Yk1jaU5nN0huMXBXWGZPT2g2c1NMOFBrak1RZExZR0dhd2Q3ZkpYWXZSMFdmRU1BQzFCV0U0bFo2Qy85TW1mNk9jdVRwU0lENGtXVUcwbTdFdmVtMmJjNWpobzFZT3htUE9uTVRwMmFKN0lDQmlZOEovVDdRQWtZQWNaQUFROEVvYzBPMnlMYlJVVU1DTTVDTWRodjJ6VGxrSS9KalJHQVJRaEhJalhpTUdjZEtHbmVNMGpLSU94NnBWKy9MWnVjajd4QU1TUHZvNnhWNDlRWFNPTXpOdzhnRWRGb3dNd01qWTVEU1hwcm1yUlQ2QjR4VmlCOWRFa3R1Sk5xT3RIYys4SmorRURwZDJ4VGFqR2dBR2VNZ2QvOW5ZRThJNElJUVFDd0pnSU1MWEJBTm1neVNrUjJLNE56OUlEdzZMellmTFFyang0WVpORFgwZWs1M0xDQnhTQXAyanBsaGdoWTFzelp4MDFYTkJYTUV0aEFxUUJXOTVoMDA2UXZFRWFoSnRNdVhVTVFYMEZSWDAycDloQ0xOb3dDZXJzZjhQckJWL0tmRVljWi9uempNK0FIdUVBTC9JVGxnWU1aaEJxNmJFUXZwU1VkR0hsUFZ4QlZqZG82eTRSSWdFTnNFTzZKQmxwRUNWTFVUZ2hGTFFUWWNJeU1LUVpNaEcxUU5GS1g0NWoxaVl0Sm9KVU9WK0NFTUdBRUNNQStJL3c4Q1hHQ0FPMWprdjgxWUlzZ09Fb2VJd3l4QVhZbTUvYzZxbFlabmFESkg1Y3pKaElCTW1PQWgzL2psZ1hWV1F6NlJZREFZWHN0Qy9SZDBsa001QXZJM1VIVGZSd0JxZng0am8xdUJMMklSNmdEWkcwSUFCTzRRSTJEZ0RpWU9zUVJ5a0lNWlAwamdHVUxpY1JZQWdRdk1PRVFDTXloYTRCbmtQSUVFRnFCb1FhN0FIVUlFQkRuZmljanBwRWx4aUlESW1zNlluWmtiYURKWU1EejczY2dmbVdrQ1JZTEpDUDArV0FBS0htZUFaRWdRQWdUamtORTJwQWdTaHdqSUFvempnWjlCT2srd3pzQmM3QU8rZ3Zpa3hLUDhKd1M0R0RHNEtFWE9FcXpxdFBBQTN6SGpDNEt0L0JjRXk0Sng4V2liTTJKa0tvb2FlQUQ0Q3VMYkdCUWx4QkVqWmtHZjlYVnRtNGhnQ0l6WnYrWEZEejBZTnA2TkxheEVEbVhuczB5WkV5b28weG5JL29pY29ha2hSTUJlZzN3VFVrbjIxUmduRThRaHJRNG9nMmNIYlFmMjRxd2kySHFTQlJxQkFETWU1dzZwZ000WURIcVFHekNEa0NBVk1PeUJIQ3dBQWdHeEFEbDRCb3NjWnFBTUNHSUx3amhVUGFGc3dBNkM3bUZKbW5sVUhPUVpXbDFXajR5eVJVRWdrQnRseVQydHFBTjc1NFc1c1dSQ2NLcmdETERqZ09VR0NvR2RHTGNDL3lwNGhCOUdFT0NZcVhaNGJXN3NSZEYwRkdhR0lBTXBRc0NlWllGZk03TjNDUDdhUUh3ZkFUbXJSUFpMcmNpdllHeVdXVmVDdFpNZ2w1ckszcFNpUG9iemg4Q0E3eU1naTFHWlhlcHVyNHpHcGcycllsblhBamVVaERzUFdlVFBMZkxIMVVEYWZtK21Mb3lSdHYzRVpOY21xeXhhTkNCdXZUNmV1d1B4TXRSdjQrclJHOXhJTXVnME1OUUJMTnhQYTJRTHVZRnFBTVRuQTgvbm9DSUF4aUVoZ3VjRExQWStUalA0RXVOajkrRFdKNFJBTlhNNmROL0N5TEt6V0p3RmJ5QkVRQkJMVUlERm1RZHhYVWNxN3NUQ2dHSC9LUHB6ejZBemVoSUdOQTJrTm5qZXdmYmJQc3JZNnZ0b1R6NGZhMTZJQmNnWldpT1E2MGZZZnYrSG1GaHhCOTNSbjhQenkzRGRqckdkSmFtN01YQ1FCRVhrRERQR2NnVVd3WEFHZlYxZlcwQnVheTN5ODdnOXY5MjJFdzFiSVRjd2dTQUZROEpqNEg2WlhWRkxId0JtK1M0SEFyeDQ5VEo3UjlrS3h3OFd3UUtQazZCc1FRR1d6ZFlYby9HamRaT2pNaDgyRHBNZ0pqdHA5VVQ4Mzkxa0YrZUdva2pDSmJJTWx4QllyblZrdTJ0dk13OUhtdkpyQlFPV09GQUVUbG5WRGg5c1diaWdjY05NMUJuRWtpQWtrTEVoQkh0M0dXd1ZtZCs4ZDV2enhlL0U5TXl6N2N5THo0ZnFFU2lWMlZscytQeWVZbTJQUGsvRk1zZ0hEUG96V0lDcWdtN25BVHkvZ05rOXI2RW9uMGQ3OUVrMEZZY0lDQUhFRW9FUHY4cWpEN3lUVmNkZHc4UjRReldBTEJCZytXRm1Gci9LYkhNRlUrWHpDQW15Z3dVbzB4NzJQZlNYUEhEbjM3TGxLUTloMWlkRXdHRm0xeW82eDd5VnN2dEc2aGt3b0RQNk5oWm1MbWZaeGhZcFhZelhJQUdDYUNDOWkxNzlGelRYUVRyaFFzcE40SXZmQXVaWmtycGRjWkNnRTJWbmV6WmNJbUswT254MWR0YitMamU2ZU5VSysyRENqcTlkaEJDMDVBRFNpQVhLVmpTYVJqUWl4R0RIZ3IzVDRGbkFyMHA4MndXZHlGdGJJK0czVFRiZXVCQVFnQkFONVBNakxUNTN4NE82ZXRzQys4NC93ZFpPWWk5dGlPOHl5N2NpM2NoQjR0eFd5ejRTNGNRaVFPZzZ2UjU3VEZ5VmdqeVlYU1JZMVFBT2RHSjhxYVJySlB0b1UzUFF1U25ZRmFQUk5tV0RqRERZV2RWK3ZSblo0R3d6MjJCQU5aU1ZuZmlxbzQ3bHM1UE9WZlBMYk8yS1VkdE1YMkFHQlF3NkU5YzBkKzFkeGRyak50Rk9vRGhDWi85NTdIaGdLMGVmQzZFRzV4NEdpNzlPU2g4Z3BLY1IvZGNvdTZmUW40ZnNrQ0pRL3ozVWIyQnF6VTZhUG93c081Ymg0QUpjdS9EbXE3UW5CdlNaWi92V3R6TjI3R2wwSnpjeVdBVFo5VlJ6YjZiZHZvYk41NHFpQldxZ0dvSWl0RWYzc09mQW14aTNTTGQ5S1ZWL0Y2M3VWemo2TElqRk9sUmRnQVVRRUFNTXEzdkpkaFZyMWtKdUxjTW1uNG9xb0w0WlBJT1JHSENJR1ZORVRoSmdCdG45eThNQnJ4OGRzN2NGaFhkMm9oZzJmbVBPK25TUTNReTJEOU5rVTlrcGk0Mi9vR3lGaThwSWtBdHZ4TVNZblIrSytBa0x6WXRHMjNaQnV3eHZ5ejIxNjBhWVFaRkFVUFY3L3FtaXNEOW5WTGYxK3ZTbmU0NHNRTllWamV6dHBmSFVSbjRUc000c3ZNL0VpU0hCVEYvOWhVWDcwN0t0ajQ2MDJJWElOOXpWYko0YWkrL2ZjblM0c0JxSXhsVzBZM3pkdmdVK3VtM2Fqemp0S1A0TWJGTXRrR25Pczc4M2hQREpFT3hSU1JnY2lYZ2J4a3NGbHFLdGFLZjR3djVRVjUxNnJKNjB5am1oMm05WUVKVHNmbzllLzhoOUJ6YWV3Ukh6VTRRQ0ZGcUU4QWE4dW9taXVJV21ENTZoTE1EaWc3UkhIdVNXYTcvRXNQOVJUbm42czRnR2kvVzF5TjVJSE95a003R01oWVUzczdqNFVzUnFpbEFnUGs2T3YwNjczc3RSNjI4bmh4dkkya2gzL0NibUYxK0x1STN4TmVEaDZWVDlWeUdPUlBsbUd2OVRKbGJ0eElENTRWL1NhajhYZkNkemV4ZXhOdFRWV1VUZmdCbVlRVERvRFhmUTB6WW1XcEEybm9QN0NmaGdIeUhmam9tRGtqak14UHBBT0E0RHo5d2c4WDdWK3IyUlRuejVZcTBIZHMvbFB4d3A3VFBCbU9PN2drSGxYSHYzdy82eGlTbi8rVk0ycGJkWHMvWWtqMkk0RUtFS1c1NTZVdkhsbUppb2Vtb3JjMGdyUVFPUEhoajZXMm5zYjhxQ3g4VUlNUmk0OXRkWmYxQVVYREJXcG9tRlNyOWxGczRKQ0F2TTdacjFTL3Z6Zkh6RGVzTU1FRFJ1dDg3M21yY29wL2NFV0I4RHpYUlA5My9xT2kvT1B6bjlhbXZVbnJ3d0M1Z2U4dHBmQlh5Tko3b2I5RHVZbldqWWFaN0ZZclpOTWNOSzJKS0NqVmRtZEJuQWdCc2YwaEhiMkxMdWRhUURJMVFWeUtDejZtU09tZm9rN24rTS9FdDQvUWl0VWVpT2d6Y2c3V0RZK3oxeVBvbWlYRTlqZjRocEI2YjFwSGc1NHl1ZndYQUFaaEFOWEMrbmFtNGw4QjY2NDlCS0I4Z0xNTmQ3SjVWdW80cVJFYnVNd2NKdlkyRU1pMUNNWG9TcUR0aGx4QUFkemRJMGV5azczMkk0bk9PdXUySDk2dE5adFR3eHJDQVl4QVFMKzIvQ3JNL29hdWhWVDZaVmRKaHVycWV0QTNRaU9LUVVqZTg2eFl3cHdVN0hyMjBuZTB2MmRHNC82K3Z1L2lwZ0c5OWxnRmhpSE5JNHZVYTZIUGR2N2h2d2liRk9PRFVCdVJIakl4eVJIZW9HZ2tFTXNHdEczODdCMzFoMjdHb0pFT0RRYlVPM011N2RubG5aRVdYQlZMc2RPNVk1WGg1ZW9DaUtDRE56K1VQVCsvempyWlNRd0lBNnc5cEpaekQwYXdmeitlZVNhU3dtY3BYWk5UVnFwNjlaWWI4aUI4K09SOTZkVXZ4YU1FWWxHV0JMV0pLQkEzSjkyNHpUV09Lb1hEU25LOXVZSkFRRWd3UE42Tlc3ZTJ1Z3pkbVFRU3dSNE5EdWJNYjlyOGpGVnFJK0FmWVpvdCtIK25EMGFTejVCc3EzMEJ2c2d2QU5tajNnZmhSaCtUU2h1Uko1QllpR0FoZ2g2QjZLQkFhc1dINDZYNy95YzFqcksreDdBRFkrOCtYRStBY0l3d1JpU1laMitVdElaMUEzTXhSaEFta3psbjZmYmRzYVJJZWlPSldEREpCRHc0RDIyTGNZOW1CMkRrSjZNclJncW5NelRYMkFiQnlVa0ZqU3d1eDBDUXlmam03UERlTmgwNkRVRjFwOXZaekdwdVdBUUFZWk1NQU0zQ0VBM1RaUXNIV3Uxcy9VTWYvVlVkMXdTYitHUVEwR21FR0lRQXBmZjNSL2Z1M0tGZHpsQWpOUWdHWUlKMjJBWnB2NDBPZmh3ak1EenozZEx0MjV4K1JvNCtybHRpd1BJWFM0cDEzeUoxUHpScnNGcVFWMUF3WjBTMk00QkVrN0RKRmxyQmlOeFl2UDU0VmtWaXpPaVpCc0VlbW5nTE1FNDRENG5ob29ETTdpSUFPRHhXZ1UwVGhKQXR3Z3daZmpKWGRzRFNlMkNQa0lWQU1CTUJEUUREa2tkVTdFdXUraUhyd2FlQW1Ub3pmZ3dHSUZxSWY0QktWUDB4OUM1anE4dVk1UThEM0dJY3BRbE5DZFdNbmV2Y3Y0OXJjK3lyTE9JaXZYcm1DeXVJektEUk5nUEs3SlhlQmN6TUFkc1BzeHU0Mk5SNEg3OFpUaEZPb0tNRURnN0dCMGZDc1IyTHYvQkk1WXR4a0w4SjBicjZPM1B4TUxEa3BrRHBxazBPa2dZckNqcldNajkrM1JUZE1MZXZVNFRLOGVnN0lGYnBBTmhBaEJXQU5tY01SeVk2U0Evb0xZdk15MzF6bGUyV3U0aENYR1lXWlFOZjczL1lwTHk1WjJsUUZLak5BQ0JlaFYwQ21FQUFkaXlYbmRibnJwMXVubWo4cFJ6bDdmc25iZHdNNTV2M3JkbHZEb3lSc01HakhZQVRQVDBFcXdjc0t3RUZFdzNDQ0hRSVRWMGV5aVd1QUdFVWJLRUg3YUFRbk1EQVFPR0dBc0NZWUFBNVI5YXlmWTZRbDd1bVNVN1JybWVIQjcvYVRiQjFQZDU1QjdHM0RMWUxzNXJBMDJBVVRVZ0F0U3NaSHNMMmJQZ1J0b0hDeHZBRnREc0swWU1IbGNDMDhyeUwyRTZocUw0cUFRdXJnbWlVWEJzUDh3dmRZcnFQYk1zbjdsMVp6NkhGaTI1a0p5M3NoZ0hrTGdDUXdRSUNBVnNEQjdMYjNlYmxhdGhSQlBZWGJmQ2c2eUNGWkEvNUU3R2U2K25kRlRZTTJHMHhsckgwTnY1Z0JYL2VPOVBIdzNkRVk1S0NsdzBMR0JjQ29Zb0pGT1MremNtVCs5WTVlMnIxNWhkRHZHMm5GalVJRUJCcGhnVUl0MmFSeTV5cmg5dTVqdGlSUFc4Unl2N0hmZGpJQjRURERERzN2NHpsM0RmV3Vuak5GV29oMk1Ka0x0RUlFQTlJWXdWaksrNmFqNGYrZ3FuTFpKTjJYRjF3em1oUlZVRE5uYVRBTW02Z1hSekJtdDBwQTdWUTJybGhjMGJtUVhNUW5Qck9rTk9jNkNpSVlIV0JDcUJNa01ZNG1FeFlBbG8xOWw5VG1zN1diVDlkQS9WclR0OUJpdFcxWFFzUXlKNjY1WlBIVUh6czlpZ3hMeEJveXJnUUk0SHZRQnpLWndRVm1BNUR5ODZ5WXF3ZklXZE9JRk1ISUNzZDBEUVRWWWh6VlhnRTFCbUFWenpFYUFJNEVhWXovWURLazZGenBYY01IUFBrem5LQ0N0cDlvZmVaeUF3Q0Z5aUFrQ21leVIxTHFkWFBXWTJRTm1KNURLaER0WWdQYllrTVhaLzR0RmlDdUFBejlCTTRSKy8wWTJuN09MZGNkQktqa295UUJqTTlBMVJCYlVpeXl1bjdDN2psNExUMXBqekM3QVlBaG1QRUV3a0tCcUlEc0VDNzhJOXFjMWpFZUUrQjUzMFdtRlgxNDJtdTZxYy82d0F4bHdBUVlJcWd4akhWYTg4cUp3eFVtcndtbVBQbHkvZXFvZER5U3o1WFVqWW0zRmlyYVd6KzRXUVNLWkVWcWdpc01FVGFPT2pHeW9hSGZGY05GR2xCa0xMREVMZyt4L0hjdy9VZ1E3S3JzaVFnNHFaSG0yMGU2VzJaeHhTTGRwdkoyZCt3cnM5VGxETEEwR2tVVTFkelFUdTZEaUdKTE5ZM3dXdEEwTXBQdUJTOEhPQllFRTg0dC9RdEg2T0t1WFFmOVI4UFpUYVkrc1l2YitCWVl6TVBLa2ZSVGxQbUk4SHh6TVFBYjE0TXNFdTVKUTNJTDd5NGlEODBoanM3aFZUTzhCOTF0b3QycFNUTWhBQmpTUS9YTVU1VmZCZDdNNDJFSUlsN0ZtNVJ5akpYeml6NkN1dHZQY04yUjYvVVRUaDhYOUg2ZlYrUnVxR2FBL1RxNStnbDRGcWZVTkx2ejUvYVFDSkE1S0psb1c3R1F6UXhJbVkrajYxb1lqdU5iTjJEY0xHSmlCZUp3QkpUQjBRUXJXM2JEQy9xQXN3cHVHdFNYTU9jakVmaGtkb0NQQVhXUEhMRXZ2bmU5amNqNWlBZWU3aEtocWU4YnhhOEw3V3V2aUtmZmRuUi8rNWozNjBuT2VUcGhNaWd4QVlKVjRhb3hXRm9US2xVRUdCbklJMFg3WmpKY0hWQW1iMkQvamZ6YlJzdThvV2QrenVza2dpL1lnKzUyaklkNkpHV1lRZ2V5QlBaWE8zZEFORndmUmRURW0rVHRhcFI4UnpKNlIzZWgwd2ZZM2ZHYmZlYmRkYyt6TFZsRnJJNE9xRFdxRHdBS2dBOEJid2Y4bktRVkM2MU5VTTU5aDFTUzBPdEFmdlppaTlRSk1zTGh0R2NrZ05uTlEvakxLZDBBOGg1QVhxUHQvRDkxUEVGT21HWFlKY1JsaWlUYWpaZ3IzYWJKZGgvUk94RytoUEVXSWN5aThINXAzSTEra2JxQS8vQjNXcm9VN2J6akFvL2ZEMUJHdzdiWlBNNnlPcENqT29hbitsZjdzQjJsUFFRUjZ1MDlnWk9Sa0hERDdKdFVRcWlHUFNSYVlER1pQRm9jWndreXIreFcvR1F3cmpFSThyaFdNWllLVndPZGRmTWhkNThUQzNybHFNcHhmdTJnYVVRU2pjdDBXc0ZjWDBpdWFhSmZLUlJhMElxTmxOMzVnNlA2ekxuME83Q0dEbzhHZUVZTTluUkRHNkxuUHp1YzNiWnppb2VaQVhxYnhzSzFWaE9YRFNwalpCYVhDUjh6MEJvYzVscml6UEpxOXZTenQwaW9UT3kxalVHbjIwV20vdTczQnRyZmEzRCtZdFpPellEVFphM3BWbUJzMjlydXRrc3JNa0JoUFFiKzR2aDErVHpCbEJsbTZ5NHkzSjJPRjBCYUxScjJZU1NWM1BianFLVitibVZ2M1U4VGVrWmdEOGRtNDMwM09FQU9ZL1J1UjYybTFDdEE4MVg0SVU5QlVteWxiNzhmS1plUStMSC95WlJURFc2bWIvZURUaUxlVDJxTU1Gb2JNN3g2eStoVElmalRXL3pneG5Zc0RGaTZpR1o2QzZkOW9wWXp4eHpTNmltWndCR09qOTFPSDIvRGdaSWRXK2ZzVTZlMjBPckRub1JPcGRTV25QZzNXYk5wSHRyZXhzREJDcXpYSHlDUTBEaUhCL1BSR3hpWlhZUFZlY3ZNUU1yNWZHaG5WK29WNU95MUVEbkZBMkhHbHdsdWlBY1poeGlFdTdUWFpmVUxIaEVLWEUzaGE1YXlpaG1oR0E5UlovK1RHYjdqbjc4ajlFU3hlSEN3Y0QyS1lSVEFya29YbnVQakpBSDJEdG9LbGdpVXlXUFJMSnp2NmgxZ0VGcWZaLzhoMi9jMEp4M05xVVpKeUEyWjZoZEFXSS95clJMZFQ4RXpITnN1ZzB6S2lhV2VLZWduR0xRTXBET2E1Y2lUWXliVUxpMmJkTXY1R25YV2hZVmVEdW1aMnRzeE9HNDFLMmFHVzNTRHBKUlkwSU5oNVlBZ0RCd0wzcklyN0ZxazREVXRnQmpHK21leDNJbjBSTThpQ2ZqTmdjR0RBN0NPUWE1QzlpRmk4RDF0WWo5Y2dRV2ZpRXVycDkrTFZINUhDdlpnNStCejlQaXowbDdHT1g0RDhGaHBianNRaFJpSVc3NllaL2dJcDNvWFVZTTMxcEJMbTUyRlFRWHRxUGEzd3Y1Qy9GRE9ZbVliVG52M2J4UFlPZWdzZllkMnhNS3d5ZzJxZWxqMmJPaCtMNnk5b3QwUmFmUkc1QnVWdjRIb1l4UGRMdXc5dzNuaGJIWGN3UUlJaVFwRmdXQWwzc01BUThZamc5aWI3cmtRWWlZVTlIN04xTGhFRWpYRFE5WXREZjM4MFB0TnFCYzlBSSswSTJYOHBwWEM1c0dNZElRbHhTQlNNR2xDWU1XZzBiZGE4dm9VKzdkbndESjBJZXc3b1kyc2FmOXJxa2ZoenZWa25tOHpnekdEaFRBRVJFWU5SWmRFZmF1dFlsMWVueEhXR3lBZmNMZHRmeHpGN1Z0bTI4L3A5c1NTbVpPZTRjdzRZQnpsR1B3dDMvNWNRd3Bzd3RnMXJKbUlSbmhtQ2dhQVRLbVkwZGR2bjlUd29PUXZtT1VSYVRReVhJLzhZOEZWY0R6QjBHTTZ2WXpnNGhiWEhQNU1tUDVPOFdCSVRoNWhCTlE5MGZvR3lmU0dldndpMkMyOUVkL3hJeXZZRkRCZVBCa3BDQW5HWVo3QjRGbVg3TThEbG9Pc3c3U2Fta3JuK01YajlGTHJwZWVESDBUaVlnV2RvalhhbzYvY1NlRGJEM3Exa2IyaVh4K1AyWEZLTWlKOG0yRGl4UEEwMTROeE10bG1NSjBqYjl0blpaeHhuRE9ma0JCUUN3MkdqaGNWSzAyV3luZ1ZseWVZeFRIQmNDdUVDQzR6V1dWbmkzbVM2cndqY09aZTV2c3E2T3NyMlNlSXhCcGk0YnVENXhRRzdMSm05ME1GU01DUndpU0xTbTZuMWp3dVYzcnV5eGMwc2tVUnJNdERwR2lkTXNaQ0MvYXF5endxOU1rVXJ6STFHQW94YTBFN2E0NVd1N0EvMUoyUGRjRDhDQktwRXU5U09uTVBMOTgzejV4TnRQU3NSR0dZb0FramdFZ20vWjk5UUh5NGpsM2VEN1I5VWptQUNPQldKUThUaVBsdisyZnQxM0JiRTZZUWFDRFh1aHRrYWl1TE5vTmVRd241R0NxTllQc215SThhSVJhTHVRNjRiUWlFUWh4bGdFZXhvVEsvam9KeWgxWUdSU1JqTUMxRVRBaytrUUV4YlVINFhoQmtJczdoS3BwWXZ3MndFcjFuaW1EV0FFU0lNZW1BMlNvelBSLzU4WW9RRXVBQ0RZSmNnQjNPV09IQWRRZng3YWZQcThNRnFVWi9FYUVBS3dSWjdmZVlYS3kwZXVkS3lHcHNhVmt6R1NOdGdCT1RJcHB0R00yQUxLWEVBbUhmUnVLQmdpZkZFQmxuNmxzUC9rT3VLWVBhVW9ldW9FR3dZcEh2cXhyOWVLOXprTURTK1R6U3NNRG9KQXV6MnJEY09oL252S3NWbldORHhMUWlZcHQxMWl6SmZrN1RWekRLUE1TQUFCaUh3NE40NXZlVGhQZjZUVzlieWxMSmd3NkRDek5pWlROZVkrSHFXSGhMRzlFSk4zWWlVN01CSWFhOFJnU0FsRW90ZnFKOTE4MTM5NDFmUTdiK1NRTVpWQVlaa21MV1J1aGh0eWdRaDFCaUxWSXNEakV4SWdQTkVEUWdERXBBSUJybHV5RTJEbVRDV2lCK2dKZ0FkakJITUVwS0ljUWowYU9vaFpnNFlqekdXeUpBaVVDQUhVUU1OQjBrUmNFUWJiQmE0aVIvaS93SDNENVBNcGQydDVRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRCbG9iIiwiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiJhMzk3NTU0OWIxOTFmZDY3YjhmYjAxN2UyOTE3ZmRiMyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxNTM2LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsyLDFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6OTYsInRyYW5zcG9ydHMiOlsidXNiIiwibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN30seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTh9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoyMDQ4LCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjoyNTYsIm1heENyZWRCbG9iTGVuZ3RoIjozMiwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjYsImNlcnRpZmljYXRpb25zIjp7IkZJRE8iOjF9LCJyZW1haW5pbmdEaXNjb3ZlcmFibGVDcmVkZW50aWFscyI6NTB9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wNS0wOSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIE5GQyBTZWN1cml0eSBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIyMDUwOTAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjQifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDUtMDkifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEyLTA4In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNDE4Mzc3ZTIxM2RiMTRhYmM2NTA5ZGI1ZTEwYzk1OThiNDJmOTJlYSIsIjUyNWVhOTZjNDdiOWE0NzkzM2EwOWI0ODcxYzM5OGRmNjQwN2FhYTQiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNDE4Mzc3ZTIxM2RiMTRhYmM2NTA5ZGI1ZTEwYzk1OThiNDJmOTJlYSIsIjUyNWVhOTZjNDdiOWE0NzkzM2EwOWI0ODcxYzM5OGRmNjQwN2FhYTQiXSwiZGVzY3JpcHRpb24iOiJGZWl0aWFuIE11bHRpUGFzcyBGSURPIFNlY3VyaXR5IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJpc0tleVJlc3RyaWN0ZWQiOnRydWUsImlzRnJlc2hVc2VyVmVyaWZpY2F0aW9uUmVxdWlyZWQiOnRydWUsIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJmakNDQVNXZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQVhNUlV3RXdZRFZRUUREQXhHVkNCR1NVUlBJREF5TURBd0lCY05NVFl3TlRBeE1EQXdNREF3V2hnUE1qQTFNREExTURFd01EQXdNREJhTUJjeEZUQVRCZ05WQkFNTURFWlVJRVpKUkU4Z01ESXdNREJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTkJtclJxVk94enRUSlZOMTl2dGRxY0w3dEtRZW9sMm5uTTIveVlndmtzWm5yNTBTS2JWZ0lFa3pIUVZPdTgwTFZFRTNsVmhlTzFIamdneEFsVDZvNFdqWURCZU1CMEdBMVVkRGdRV0JCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFmQmdOVkhTTUVHREFXZ0JSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QU1CZ05WSFJNRUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUJCakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUF3ZlBxZ0lXSVVCK1FCQmFWR3NkSHkwczVSTXhsa3pwU1gvelN5VFptVXBRSWdCMndKNm5aUk04b1gvbkE0M1JoNlNKb3ZNMlh3Q0NILy8rTGlyQkFiQjBNPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFGQUFBQUFVQ0FNQUFBQXRCa3JsQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUJIWnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU5pMWpNREUwSURjNUxqRTFOamM1Tnl3Z01qQXhOQzh3T0M4eU1DMHdPVG8xTXpvd01pQWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cGtZejBpYUhSMGNEb3ZMM0IxY213dWIzSm5MMlJqTDJWc1pXMWxiblJ6THpFdU1TOGlJSGh0Ykc1ek9uQm9iM1J2YzJodmNEMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzl3YUc5MGIzTm9iM0F2TVM0d0x5SWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREUwSUNoTllXTnBiblJ2YzJncElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhOaTB4TWkwek1GUXhORG96TXpvd09Dc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01UWXRNVEl0TXpCVU1EYzZNekU2TlRrck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZTR2x6ZEc5eWVUMGlNakF4TmkweE1pMHpNRlF4TlRvek1Eb3lOeXN3T0Rvd01DWWplRGs3NXBhSDVMdTJJT2FjcXVhZ2grbWltQzB4SU9XM3N1YUprK1c4Z0NZamVFRTdJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakpGTnpGQ1JrWkRRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lpQjRiWEJOVFRwRWIyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qSkZOekZDUmtaRVF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWo0Z1BIaHRjRTFOT2tSbGNtbDJaV1JHY205dElITjBVbVZtT21sdWMzUmhibU5sU1VROUluaHRjQzVwYVdRNk1rVTNNVUpHUmtGRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpSUhOMFVtVm1PbVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TWtVM01VSkdSa0pETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlMejRnUEM5eVpHWTZSR1Z6WTNKcGNIUnBiMjQrSUR3dmNtUm1PbEpFUmo0Z1BDOTRPbmh0Y0cxbGRHRStJRHcvZUhCaFkydGxkQ0JsYm1ROUluSWlQejQ3N0pYRkFBQUFZRkJNVkVYLy8vOEVWcUlYWmF2RzJPb3FjTEcyek9Pa3d0MEJTSnRxbGNYVjR1K2F1dGxXaGJ6azdQVUFNWTlIY3JLanROYnE4ZmVBbDhhQm9zeno5dnBkanNHR3F0RjNuOHVUc05TWnBjNkpzTlQ1K3YweFlLbnU4UGZmNS9MNDhmZy9mcmljekpnWUFBQURBRWxFUVZSNDJrUlVDWmJESUFqRlhaT1kxVGF0TmMzOWJ6a3NTWWMzcjRNRTRmTUJBYUQ2emw4eS85VE9nZXQ4ZDVqZk43OGJ3TS9kRENScFI1MjF6WGZvakhKMDVJSXloQkFVU1ZBT05kR3pCWXQyZjdLRnJma0phQWtIaDlGWmhjRFhIUmtUS285TUxpaEdhYXZJbW5WM3F5RVgwRXByZ3ovNER3VUQ3a0NIUm5kOFFGTjQzR280VVZtRERnemE0dzI3b2l6ZEEyK2NLK3V1VXBqam8yK3h3Yy80Mlc1MHg1TEdZZURCc1IwSFZJeDV4OGlGNjBDYmxiVEVFa0ZyMjdiTkRCVVZTcTFPS1ZQYkU2MmIzRUg4RnFCZzVPT09FdWMydDhaSmlxTU91R3ArY0tqZzd3VkdjZW96cU40cHhnVlBRa2pGWWdiVkpLRFVoRENqWXJhd1A1cTRFVGdDOWZJTVJIdGl0cFFjQ3ZKT0VMY2JNc1FnbmNpUmtsanB5UWp2RzQ0anFCVUVURmlCaTFQRUl5ZWtPenNXK1R5NWNMSG9zNVIrZE1TMUx0U1N4ZjNnUUhjelIyQ0k0Z01OcFc0SVJBMVFNYTZ0SjQrQzZ1SHVHRThtTkRJeUZxZy9PUC9NTVV1ZVM2SXE4UzkwZEFlQkpTRXkvcUtrSytCTnd6OGNZWTRqYjVKNnU0aVdDSTJCMVo1NkxXNWtFYzRoa2RNcHN2VUM1NTg1U1gwUXViY2dOcXlmZ0RGRWNUdCs0MC8wUzVOeDB3YUN3M09La2NPYkE1SW4wQVlwMDFwamp3Mm42MjZVRGp0SHdhMjhpSHVUS3F0cnYrcmVXNDFOWjZpR2xyN3V1TEpDZmtGdGN0Y0cwNHNnbTFlTlMrWmFEbnBhVEVyR295WDVKSzJpTXo4eHMwbk93V0djUERONDlxYUNkNGJ6Sm96RFptL2FCSytFb3pMdytYaE5CaVl3SGYwc2lPdTFYUGtHL3pLd3ZxWUtjZlN3REVjSC9vVWUwN2VzL1dROHJJeWcyRE9Yajh0amtaZHVEQi9iOGh6RGxsTU1PQ1M1QkVuZDUzNGY4dGkzVVpjNGtNczN4THlhZk1Tc0poZEc4WFBxak5rNXRBZ08yNWZlS0NoblZkRGovSjBGTWtPc1UveE1CdjB3RmhZZUVHZlZIMTNmdURVMHlERkxhNGZjN1JuV0hCZnVURlYydEVtTndhZGM3YWMzVVkyamZCbDdIVDM2ZmUzNGlRTzVtTkNGRkJXMDdLalBncWhPTFUwMXZaOFB1ZVoySkNsRlpOOGprVXM2OXVrYTllUHA2K0VmTDRBRjUrTnl3U2Jpckh0Y0I4TWwvZ2t3QUVqa0s2NEtqSFBlQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMiIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTExLTAxIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJNdWx0aVBhc3MgRklETyBTZWN1cml0eSBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjEwMDAyMDE4MDIyODAwNiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4wLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4xIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTExLTAxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOC0xMS0wMSJ9LHsiYWFndWlkIjoiMTkwODNjM2QtODM4My00YjE4LWJjMDMtOGYxYzlhYjJmZDFiIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiIxOTA4M2MzZC04MzgzLTRiMTgtYmMwMy04ZjFjOWFiMmZkMWIiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI5NDczLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AzODRyMV9lY2RzYV9zaGEzODRfcmF3IiwiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiMTkwODNjM2Q4MzgzNGIxOGJjMDM4ZjFjOWFiMmZkMWIiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJsYXJnZUJsb2JzIjp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZSwiYWx3YXlzVXYiOmZhbHNlfSwibWF4TXNnU2l6ZSI6MTI4MCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH0seyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTM1fV0sIm1heFNlcmlhbGl6ZWRMYXJnZUJsb2JBcnJheSI6NDA5NiwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjMyOTQ3MywibWF4Q3JlZEJsb2JMZW5ndGgiOjMyLCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6MSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjEwMH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyNC0wNS0wMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjQtMDUtMDEifSx7ImFhZ3VpZCI6ImRhMWZhMjYzLThiMjUtNDJiNi1hODIwLWMwMDM2ZjIxYmE3ZiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZGExZmEyNjMtOGIyNS00MmI2LWE4MjAtYzAwMzZmMjFiYTdmIiwiZGVzY3JpcHRpb24iOiJBVEtleS5DYXJkIE5GQyIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjo1MDEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMDEsInNlbGZBdHRlc3RlZEZBUiI6NEUtMDUsIm1heFRlbXBsYXRlcyI6MiwibWF4UmV0cmllcyI6MTUsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQmJUQ0NBUlNnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBdE1Tc3dLUVlEVlFRRERDSkJkWFJvWlc1MGNtVnVaQ0JCVkV0bGVTQlNiMjkwSUVOQklESXdNakl3T1RBNE1DQVhEVEl5TURrd09EQTRNemcxTjFvWUR6SXdOakl3T0RJNU1EZ3pPRFUzV2pBdE1Tc3dLUVlEVlFRRERDSkJkWFJvWlc1MGNtVnVaQ0JCVkV0bGVTQlNiMjkwSUVOQklESXdNakl3T1RBNE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRS9OK3YvUGJ4NjR0RHZNTWlTa2Nqd1A1TThEMklVZnJHbDBIbnpvSE1KR1V3YitSNDhNZXpXaTFKM1pCWGVPcFNIZmpyZ3hGZm8zaXJMZUxWd0lLN0M2TWpNQ0V3RHdZRFZSMFRCQWd3QmdFQi93SUJBREFPQmdOVkhROEJBZjhFQkFNQ0FRWXdDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdXcW4zZU4reTBWOTMzTUdqM2ZRcmRyVVhzOFZtVXByRXM3QzBOVjk4RFRJQ0lFWUMrKzlkTzRjamFVUnVXNGJkdE96SXEwUDRjVFdkN3BTY0JhakxOM2R4Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUdvQUFBQXBDQUlBQUFCU2p5c0NBQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBRW5RQUFCSjBBZDVtSDNnQUFBbnVTVVJCVkdoRDdacDNWRlJYSHNkLzlEcERHNGJlMFRXYVk4dHVMTWZHSVdZMUdCTk5OS3RSWTFuTkJpUlIwRTEwZFNNaTRpcFNyQ3NubXhWREY2VVp3Uko3QVlPS3JzYkZSTERTZzQwK3dPejN2ZnVFeHpBWVRPQ1B4Zm1lNzVsejcrLyszaHY0Y04vOTNUc0RmZTh6SjB2YS81QnNVSTg2V3pZb1M5djFkblNjc25lSmNzZE1TeVdIZEhKS0ljc2VzMVU2dVdXUVZXSGtidUZ0ZTRzb2Q5ejBWTEk3Nmo2cUlHanpEMzlkMXdNT3ViRXFOSTNzTTBoV0dCVWp2RzF2RVlkdkg4bHkzNXN2QkhwRys4aXNOK003Ny9PaEVPZ1p2U3o0OXBKUkVoa21rOGx2ZHp4Ui9yelAyVzFmRm53WitpNFo1SnBCN3M5eEpubGtraWRlVmVMdDdiR2ZaTmMvQzJhM2Zibnc4WURVRzF3U1NUZUJ0RlBJaklmSWFLcXhCcCtxTWExU3lMVDY1dTJuTndvTDFrWW1rMFFsUVd3TlBsVWpNMzlSQU11RTlwTmxCcm1wNUxSYWcwL1ZDYVRGMGxvVXRYaTlGYjVyTDVtcTVMUmFnNitkOTVNOGI5WmZrS09vZnJSREptWDVLU1R0YkFKcThMVnpBbEZ6WXdOeWppNlk4emVpeDRVRmFCY0VSL0ExUkRVWjF1QnJjeXJaNWs2WnczS0NpY0tKa2thOHhyckpaSUNTb3BJUGEvQzFHWHRneGNPSFNEamgvL0Vtb3EwNk9rRkU5UldsaVB5d2NuMEttYXZrd3hwOGdsUEovcXozVkphd21tZ2o3eENpMktHdnNpQjJnaDBub0FhZllLeDZkY1VsR0MwK2MrcmtzbVU1YTlia2ZQa2xmTnpQRjBVWThTdCtLL2FSbGNwVkdueWMwOGp4NUlnSmJQUTVTaUk5bFFtb3djY1poLytuTndxYUcrb1VUeC9ERFZWVkxMT3B2azd4NkJFTG9wdS9jR2txMllrdjFPQ0RQYkV4amlINkJxV1c5T0YvRXpWVWxDSHowZ2VmeEFwQmc5MUVjVVNvenFJTE5maTRWVSszS3VjaTRuZS9Ua3doQzlBRXJNWkgzQVM4NnJjaWxlVEl3YjVQcVd4R0pIZnlMREhCenZDVkZCZHZXQnNTdWphNHVycUdqWW9WdlgxSFZGZ0VFdUpqdmtGM1EzREl4blhyYnhjVi9mZkdqVTNyUTdlRVI0b2R0VGtpY2xNWTBuWkViWW5ZR0xZbFBJSy9oeHB0RFk5QXdyYklLS0hmVFhvZXZuUnl6bllaeXVKZ3dVNFhiZmg4VitBY2dnaUt4clVscXhGcHFxMUZrV0hYd3AzaHk4MDViMFJhZWtUZ3lFWmJOWC9XSERNOUkzTjlvNzZPTGl5aVEyUk1Pa2V5c2hQajQ5R3dsVnFJTFRjMXN6SXlSVnBrV0xnSjZSb1E1ZWZuc3d2RnVweDMwWkRJaEhTQVd3aDFrNTZITDRGMHFzNTlqK0M5bU9Sa01tTEJqdmhRTVJKSmg3OWFlZmFOcWRqbHNNek84RjI2ZU5IYVdHcGhZRkplemkwQ3JmSmRzRWhtTEhHeWtyOCtjSWdRVWlwQlIyNXFmdUxZOGIwSkNaWUdKaTdXdG1JajJjSGNpbVhhU2l5Y1pEYVQzMVJUNWY0NDFzdFpabU5uWmluMHUwK2Q0a3NubDRQeVYxZ3dqV3hiRDdZZDhjRjRycSt2V0lkZ1EwVjU2d1I4SVh3QmkvMUJ5bGxtTzZUZkFDSEVpOE1uTWY4Mjg0RFE3MXg0ek8zTXJTVGErdVhsNVVLSTE5MDdkNlRhQm1BWEZ2b1BJZFI5NmhSZkl1bVZaWDJIU1BIZWpDUXlaRVJndGZnd0FYRjA0MitnUERYU0o0MGNFT3c2dmlXK2k2ME1UWjJ0YmZ1N2ViSklxN3FPRDdMUU4zYTBrdnN1V0NqMGVjMmUvaWRIbVJ6M0YvcmRLdlg0MHNuMWdNU2RSZEJBbDJHQzFlS0RVVUFLZ3JoVnZMYndOcHVBWGNRWDRPdlAyQTF3NzhQbnR0TUw0Zk5iK0RId1lla1Ura3BsZFhVMTVxT0RwZlVYQWN1RVVMZEtMVDQzckhTbDN4NUZGeE1RMDdDVkVZeWRpdUlKZC9pOTZyZFNqQThUTUlXRXYvQ3h3VjdZYlA4aVByVFhyMWxyYm1Ec2J1ZjRxa2RmUGxGVkROK1JRNGR2L2ZUVHhuV2hVWnZEeFk0TTI0eDZLcVFxbFpXVmxSSnRQWHR6V2NpYUlCWUo5UC9VMGRKYXFtTlFWOHQ5UU5tTnVsTlVoRmMxK0xEcVpaRFRvN3hMbFNmUFpkc05RcmVWRVF5eVRYVlBrSGw5NmQ5VHlVWThsRUxTSHpkc3dWQk4wUzJrUFIrZmk5eHUrWklBME9ucjVJb2F5dEk2aXVFN2VmeEVZbHk4RVduYlNDM0V0a2JsYmY5VXZqUGhMUlFRRzZrNTYxb1lHS003YitZczFsWFJwcERROXllOU0yM3l1OEdydUozREM0bUl1RmUxRHkrL2xoa0RnUW83bVA4S3pTS0ZKRGhqb0sweUNtVDhFTEI2UGdlZjNGZ0thaTdXZGg1MmpwaDY5dVpXNGtra0ZzT0h5cHVTbUlUYTZ1bmdMTGFIblJOdUlxVHl1bmIxUDlqNjJFak1EMlptN3R5NmpTOG1lc1VQSGdqRHo0UmRKSDcvZ01XZm5qNXg4cnZEUnphR3JCY0d1cXhPOEJtQUhTdXlucnpiMFhrUkE1LzE5U1ZjT1liVTRuT1YyNDM2L2JBSlh0NnVOdlltV3JyMzc5MWp5V0l4ZkFlN3R2WXhEUjg4RkN2cDZ3TUhEKzQzQVBzVkgrL3h3b0JJK09Yekxsd1FPaUtkUFhVNk9TNit1Wm43SEFUNjhlYk5lM2Z2TmpZMjVwdzd6eUtuamgwL25IVUlEZlg0a2tnM2tiUCtiemVPZEpmbkJyTGJkc1RuWWUva1ptT1BicE5DWWFabjZHYnIwTTlGS0ZaaU1YeGRMQjFNV1FjT1dCdEwyUFRFVEx4NjVZb3c4RXlKc2ZIREJ3MFJPaUw1L25uUm5BOW1maEc0WEplb2d0Lzk3TnEyZmNwYmIxdWJTUEdZbzR1TndadGp2RDVmR3ZqYWdJR3NRS25pcThyTnd5bnRZVzQzdU9wY2J1MGRZVUoxWFB1c2pDUmxaY0xHSmVicjNjQmthMmFKbFo1Rld2VXI4RUY5bkZ5NVA0K3R3NGpCd2tmaVlnWDZmN1o0SWZlbFRXZkNRZEIvNFNkbzdOK2JZa2phTExncGRNT0VjZDZzWFZSWWlPTVFHZ0srbk1tejJVQVBxU00rVk43S2lrbzJDazMwZWdOUG5LbVc3dVc4UzBLSTE2L0R0MnZiRG14V1pFYVNJOW5jZzZhaW9GV3I1ODBRcG91S2dsYXVIanRzUkI5SGw3bDh0VW1Jalh2UDUyMDJOSEdjZDJaYU9tdERiUS92ZnJJNVBmcmRKOWR1L0h3bXAvdDlOdmZ4NVN2WTRuVEVwM0pvdzRuTjNkYlIwVkl1OUhreGZJY09adFhXMUZ3NG4zTXA3Mko3NStWZDRJNlZLaG8yaUZ2KytqbTdDZjMyd29VNEhRc2RrWEFLeE5rWmplU0V4QmxUcHFFQmZGTW5UdUlIbFpQR1QwaUlqV2R0cUExZktqbmhvS3F5Y25XckRkSzVrdDBSWDd2VDFaR3NiS211QVdiTjdPa3poQkREWjhwdFhHSmpZdkE3NDBLeE1ZcGRzWkQ2VEJkeWNyRmZRZkdOMjdPSFJSNVdQWXpldnBPMW1ieEdqaHJ6aCtGQ1I2bHNhV21wcnE1aFJLQzVNMlppRVVTRHgrZkRnbkc3OTZERXNYYlU1Z2pzb3RDZ3M2OTRwNUpoT2tuVHlhem5uTVo5SFV3RmE3ZmlMYytkT2F1Rm41VG93ZjM3L0EvVEpvQXpJbTR3ZXNjL3VYNUxDOXJhUk5pRnhNWHN3WElETG1LajVwaHE2ZkdYdG1uODZMRW91QTRXMWtKZnFmeFg5RmU0ajlCNUp1eGFVQ0ljTEdSV2hpYXUvTzVuMFVmejVDWm1xTmM0Ukk0ZlBRNlJyM1pHanhzMmtrL250T2lqK2ZnVEF1TE9MVnYxMk94cnFQcTV0cmlrcnFTMFIxMEwzMy9RVk1OdC9adWFGS1ZRU1ltd08yZ3ZqS0RxNFp3dmRFdEt5MHBMRkFwRlEwTkRXV2xwWlVXRjJGQnIvV0c2WFZTRU00YWRtV1VFL3puZ0w2cXVycmE1bWZ1d2tnbnZ3aHIxOWZWNHhheHNiRlN3Q0JNaXJGRmZWNGRYTlV2QS83VStmSDhhamhsNHFJVitENnRYNFh2NjVBbW1IaDdiRllFOThnRkJSL1VxZkV2OS9ISCtrK2pvTjlRTHoyQlBxL2ZnQXpKc1ZnYi9ydi9LNWNKL0JQZTRsTXIvQWMvQVJuNmxSZFFhQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkQmxvYiIsImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiLCJsYXJnZUJsb2JLZXkiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiZGExZmEyNjM4YjI1NDJiNmE4MjBjMDAzNmYyMWJhN2YiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsIm5vTWNHYVBlcm1pc3Npb25zV2l0aENsaWVudFBpbiI6ZmFsc2UsImxhcmdlQmxvYnMiOnRydWUsImJpb0Vucm9sbCI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsInV2QmlvRW5yb2xsIjp0cnVlLCJhdXRobnJDZmciOnRydWUsInV2QWNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJtYWtlQ3JlZFV2Tm90UnFkIjpmYWxzZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjE2LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjgwLCJ0cmFuc3BvcnRzIjpbIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5IjoxMDI0LCJmb3JjZVBJTkNoYW5nZSI6ZmFsc2UsIm1pblBJTkxlbmd0aCI6NCwiZmlybXdhcmVWZXJzaW9uIjo1MDEsIm1heENyZWRCbG9iTGVuZ3RoIjo2NCwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjMsInV2TW9kYWxpdHkiOjIsInJlbWFpbmluZ0Rpc2NvdmVyYWJsZUNyZWRlbnRpYWxzIjozOH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTAyIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJBVEtleS5DYXJkIE5GQyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMxMTAyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMTEtMDIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEyLTA4In0seyJhYWd1aWQiOiI2MDAyZjAzMy0zYzA3LWNlM2UtZDBmNy0wZmZlNWVkNDI1NDMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjYwMDJmMDMzLTNjMDctY2UzZS1kMGY3LTBmZmU1ZWQ0MjU0MyIsImRlc2NyaXB0aW9uIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIEZpbmdlcnByaW50IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyNTYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsiZWQyNTUxOV9lZGRzYV9zaGE1MTJfcmF3Iiwic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MC4wLCJzZWxmQXR0ZXN0ZWRGQVIiOjFFLTA1LCJtYXhUZW1wbGF0ZXMiOjMwLCJtYXhSZXRyaWVzIjo1LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIiwiYmFEZXNjIjp7InNlbGZBdHRlc3RlZEZSUiI6MUUtMDUsInNlbGZBdHRlc3RlZEZBUiI6MC4wMSwibWF4VGVtcGxhdGVzIjozMCwibWF4UmV0cmllcyI6NSwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNTRENDQWUyZ0F3SUJBZ0lKQU05UnpZdTRFSUlsTUFvR0NDcUdTTTQ5QkFNQ01IOHhDekFKQmdOVkJBWVRBa05PTVN3d0tnWURWUVFLRENORmVHTmxiSE5sWTNVZ1JHRjBZU0JVWldOb2JtOXNiMmQ1SUVOdkxpd2dUSFJrTGpFZU1Cd0dBMVVFQ3d3VlJYaGpaV3h6WldOMUlFWnBaRzhnVTJWeWRtVnlNU0l3SUFZRFZRUUREQmxGZUdObGJITmxZM1VnUm1sa2J5QlNiMjkwSUVOQklEQXlNQ0FYRFRFNU1UQXlNekE1TlRBME0xb1lEekl3TlRreE1ERXpNRGsxTURReldqQi9NUXN3Q1FZRFZRUUdFd0pEVGpFc01Db0dBMVVFQ2d3alJYaGpaV3h6WldOMUlFUmhkR0VnVkdWamFHNXZiRzluZVNCRGJ5NHNJRXgwWkM0eEhqQWNCZ05WQkFzTUZVVjRZMlZzYzJWamRTQkdhV1J2SUZObGNuWmxjakVpTUNBR0ExVUVBd3daUlhoalpXeHpaV04xSUVacFpHOGdVbTl2ZENCRFFTQXdNakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCSGxxMmpVUU1hbEhqL0JSZVFlZkdpejRFdllKeUZMV1B6NFJmaEpHS3FxbCs4bjk2aFQxbTVnWG9Udm9McmpTVTdYMGNCZW9Uc2doeWgyMit5cnM0K1NqVURCT01CMEdBMVVkRGdRV0JCUSs4U0dXMkJYYnFiMmRjQU9pV0pPVStHQ3NQakFmQmdOVkhTTUVHREFXZ0JRKzhTR1cyQlhicWIyZGNBT2lXSk9VK0dDc1BqQU1CZ05WSFJNRUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEcTh4SVcwWks1eXozRUF6bXV4ODhMQ1RZTzE1N2ZUZnlPaU96QzJBRHlhd0loQU8xUFdZbGVGZ0gvM211RDhjQkFNcjExZkVLZEYvQWFDMTZmdHhhZXpOWEgiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSXdBQUFBWUNBWUFBQUFvTnhWckFBQUFDWEJJV1hNQUFCN0NBQUFld2dGdTBIVStBQUFGSUdsVVdIUllUVXc2WTI5dExtRmtiMkpsTG5odGNBQUFBQUFBUEQ5NGNHRmphMlYwSUdKbFoybHVQU0x2dTc4aUlHbGtQU0pYTlUwd1RYQkRaV2hwU0hweVpWTjZUbFJqZW10ak9XUWlQejRnUEhnNmVHMXdiV1YwWVNCNGJXeHVjenA0UFNKaFpHOWlaVHB1Y3pwdFpYUmhMeUlnZURwNGJYQjBhejBpUVdSdlltVWdXRTFRSUVOdmNtVWdOUzQyTFdNeE5ESWdOemt1TVRZd09USTBMQ0F5TURFM0x6QTNMekV6TFRBeE9qQTJPak01SUNBZ0lDQWdJQ0FpUGlBOGNtUm1PbEpFUmlCNGJXeHVjenB5WkdZOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6RTVPVGt2TURJdk1qSXRjbVJtTFhONWJuUmhlQzF1Y3lNaVBpQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJaUI0Yld4dWN6cDRiWEE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM4aUlIaHRiRzV6T21SalBTSm9kSFJ3T2k4dmNIVnliQzV2Y21jdlpHTXZaV3hsYldWdWRITXZNUzR4THlJZ2VHMXNibk02Y0dodmRHOXphRzl3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzQm9iM1J2YzJodmNDOHhMakF2SWlCNGJXeHVjenA0YlhCTlRUMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMMjF0THlJZ2VHMXNibk02YzNSRmRuUTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl6Vkhsd1pTOVNaWE52ZFhKalpVVjJaVzUwSXlJZ2VHMXdPa055WldGMGIzSlViMjlzUFNKQlpHOWlaU0JRYUc5MGIzTm9iM0FnUTBNZ0tGZHBibVJ2ZDNNcElpQjRiWEE2UTNKbFlYUmxSR0YwWlQwaU1qQXhPQzB3TlMweU0xUXhORG8wTURvMU5Tc3dPRG93TUNJZ2VHMXdPazF2WkdsbWVVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUhodGNEcE5aWFJoWkdGMFlVUmhkR1U5SWpJd01Ua3RNRFV0TURWVU1EazZNek02TkRjck1EZzZNREFpSUdSak9tWnZjbTFoZEQwaWFXMWhaMlV2Y0c1bklpQndhRzkwYjNOb2IzQTZRMjlzYjNKTmIyUmxQU0l6SWlCd2FHOTBiM05vYjNBNlNVTkRVSEp2Wm1sc1pUMGljMUpIUWlCSlJVTTJNVGsyTmkweUxqRWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0poWkc5aVpUcGtiMk5wWkRwd2FHOTBiM05vYjNBNlpXTXhaVGczTWpFdE56TTNZUzB3TlRSbExXRXpZVGt0TlRGa01UTXpORFpsWlRJNUlpQjRiWEJOVFRwUGNtbG5hVzVoYkVSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1qRTROV1l5WW1ZdE9EVm1PUzFqWmpRM0xXRmlPRGN0T1RGak0ySXpaakJpTnpobElqNGdQSGh0Y0UxTk9raHBjM1J2Y25rK0lEeHlaR1k2VTJWeFBpQThjbVJtT214cElITjBSWFowT21GamRHbHZiajBpWTNKbFlYUmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG95TVRnMVpqSmlaaTA0TldZNUxXTm1ORGN0WVdJNE55MDVNV016WWpObU1HSTNPR1VpSUhOMFJYWjBPbmRvWlc0OUlqSXdNVGd0TURVdE1qTlVNVFE2TkRBNk5UVXJNRGc2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUFvVjJsdVpHOTNjeWtpTHo0Z1BDOXlaR1k2VTJWeFBpQThMM2h0Y0UxTk9raHBjM1J2Y25rK0lEd3ZjbVJtT2tSbGMyTnlhWEIwYVc5dVBpQThMM0prWmpwU1JFWStJRHd2ZURwNGJYQnRaWFJoUGlBOFAzaHdZV05yWlhRZ1pXNWtQU0p5SWo4Ky8wVnhSUUFBR2ZWSlJFRlVhQVhWd1hmY24zVjk3L0hYNS92OVh0ZHYzRHM3SkpBSUFVTFlCWm1DaW1EVkRsZnR3MjNIcVl1cVBWMFd0ZGJXUjYzblZHMnJucmFPdHNoRHJSVWZQUjNXV1MzS1ZoQVpZUW9FUWtMV25kenpONjdyK243ZTUwNGlLTldPODU4K24ybnVpc1MvSjNHOFlaZVoyWlRFSW1EODUrUk9PMFpTVWZpSEpQNkZIeUlFV0JqQXd6Tnc2b2JJM0N5a0NHYUdKTnloTE1Xd2ducm9wTkpJQ0JOVWNvb2kwTzhiK3hmRjZQTEFxSU1jR29kMlcrellEOUZnNDlyQWdiMWkwVEpUSFdHQ3VvNlVoZUVKZGk5bVZyU044Y0tZcTQyZCs4U0tDU08yZ0F3ZElCUVFUUHg3WmxEVmRra1dielRaY0tUSTNkaHZ2ckdsdWVNOWQ4VVRYMFJyK2ptb3lZQ1FPTVNzQkxwQUFqTFFSeHBneG8rUkFtbHI0b2NJWmhlR2tGNWxCcEw0cndoSUNYTERmSCtnRHhlRmtIZ0NDZVN3Zjc4aEV6L0tqTVBFRDVJZ1JYdVJ1ZjIwcFlCWlE3MmY3U3RHSDNZbVR2eEZNaGNnQXdsaUFSTGdHV3dHTkFmV1Fxd21oc2hCY240c0dPQStsOHFDeHhtUUJVM0RTWklqOFY4VFlGQzBqWVVGYmUzMWRQMnk1WkF6VHhBUzVNWkFnUEdqelFCQjFZRHhBOVpaMEtrbWNFSEltYzkzTHZpM0hmSElrcVplalRJZ01FQU83bDhueGs4aDNZTG4zWVEwanVzTTFMeU9FTTVFNHNlQ2dPei9sUFljRUk5eFFUdHh4SGczbnVrWUlMNXJFZGdPQ0NqNGZnWVNzUjVxUmFlanEwSml1cXA0Z2hRTkx3MVY0c2VGQUs5Rk1yNUhRTFRqUWd5Yk1jaU5nN0huMXBXWGZPT2g2c1NMOFBrak1RZExZR0dhd2Q3ZkpYWXZSMFdmRU1BQzFCV0U0bFo2Qy85TW1mNk9jdVRwU0lENGtXVUcwbTdFdmVtMmJjNWpobzFZT3htUE9uTVRwMmFKN0lDQmlZOEovVDdRQWtZQWNaQUFROEVvYzBPMnlMYlJVVU1DTTVDTWRodjJ6VGxrSS9KalJHQVJRaEhJalhpTUdjZEtHbmVNMGpLSU94NnBWKy9MWnVjajd4QU1TUHZvNnhWNDlRWFNPTXpOdzhnRWRGb3dNd01qWTVEU1hwcm1yUlQ2QjR4VmlCOWRFa3R1Sk5xT3RIYys4SmorRURwZDJ4VGFqR2dBR2VNZ2QvOW5ZRThJNElJUVFDd0pnSU1MWEJBTm1neVNrUjJLNE56OUlEdzZMellmTFFyang0WVpORFgwZWs1M0xDQnhTQXAyanBsaGdoWTFzelp4MDFYTkJYTUV0aEFxUUJXOTVoMDA2UXZFRWFoSnRNdVhVTVFYMEZSWDAycDloQ0xOb3dDZXJzZjhQckJWL0tmRVljWi9uempNK0FIdUVBTC9JVGxnWU1aaEJxNmJFUXZwU1VkR0hsUFZ4QlZqZG82eTRSSWdFTnNFTzZKQmxwRUNWTFVUZ2hGTFFUWWNJeU1LUVpNaEcxUU5GS1g0NWoxaVl0Sm9KVU9WK0NFTUdBRUNNQStJL3c4Q1hHQ0FPMWprdjgxWUlzZ09Fb2VJd3l4QVhZbTUvYzZxbFlabmFESkg1Y3pKaElCTW1PQWgzL2psZ1hWV1F6NlJZREFZWHN0Qy9SZDBsa001QXZJM1VIVGZSd0JxZng0am8xdUJMMklSNmdEWkcwSUFCTzRRSTJEZ0RpWU9zUVJ5a0lNWlAwamdHVUxpY1JZQWdRdk1PRVFDTXloYTRCbmtQSUVFRnFCb1FhN0FIVUlFQkRuZmljanBwRWx4aUlESW1zNlluWmtiYURKWU1EejczY2dmbVdrQ1JZTEpDUDArV0FBS0htZUFaRWdRQWdUamtORTJwQWdTaHdqSUFvempnWjlCT2srd3pzQmM3QU8rZ3Zpa3hLUDhKd1M0R0RHNEtFWE9FcXpxdFBBQTN6SGpDNEt0L0JjRXk0Sng4V2liTTJKa0tvb2FlQUQ0Q3VMYkdCUWx4QkVqWmtHZjlYVnRtNGhnQ0l6WnYrWEZEejBZTnA2TkxheEVEbVhuczB5WkV5b28weG5JL29pY29ha2hSTUJlZzN3VFVrbjIxUmduRThRaHJRNG9nMmNIYlFmMjRxd2kySHFTQlJxQkFETWU1dzZwZ000WURIcVFHekNEa0NBVk1PeUJIQ3dBQWdHeEFEbDRCb3NjWnFBTUNHSUx3amhVUGFGc3dBNkM3bUZKbW5sVUhPUVpXbDFXajR5eVJVRWdrQnRseVQydHFBTjc1NFc1c1dSQ2NLcmdETERqZ09VR0NvR2RHTGNDL3lwNGhCOUdFT0NZcVhaNGJXN3NSZEYwRkdhR0lBTXBRc0NlWllGZk03TjNDUDdhUUh3ZkFUbXJSUFpMcmNpdllHeVdXVmVDdFpNZ2w1ckszcFNpUG9iemg4Q0E3eU1naTFHWlhlcHVyNHpHcGcycllsblhBamVVaERzUFdlVFBMZkxIMVVEYWZtK21Mb3lSdHYzRVpOY21xeXhhTkNCdXZUNmV1d1B4TXRSdjQrclJHOXhJTXVnME1OUUJMTnhQYTJRTHVZRnFBTVRuQTgvbm9DSUF4aUVoZ3VjRExQWStUalA0RXVOajkrRFdKNFJBTlhNNmROL0N5TEt6V0p3RmJ5QkVRQkJMVUlERm1RZHhYVWNxN3NUQ2dHSC9LUHB6ejZBemVoSUdOQTJrTm5qZXdmYmJQc3JZNnZ0b1R6NGZhMTZJQmNnWldpT1E2MGZZZnYrSG1GaHhCOTNSbjhQenkzRGRqckdkSmFtN01YQ1FCRVhrRERQR2NnVVd3WEFHZlYxZlcwQnVheTN5ODdnOXY5MjJFdzFiSVRjd2dTQUZROEpqNEg2WlhWRkxId0JtK1M0SEFyeDQ5VEo3UjlrS3h3OFd3UUtQazZCc1FRR1d6ZFlYby9HamRaT2pNaDgyRHBNZ0pqdHA5VVQ4Mzkxa0YrZUdva2pDSmJJTWx4QllyblZrdTJ0dk13OUhtdkpyQlFPV09GQUVUbG5WRGg5c1diaWdjY05NMUJuRWtpQWtrTEVoQkh0M0dXd1ZtZCs4ZDV2enhlL0U5TXl6N2N5THo0ZnFFU2lWMlZscytQeWVZbTJQUGsvRk1zZ0hEUG96V0lDcWdtN25BVHkvZ05rOXI2RW9uMGQ3OUVrMEZZY0lDQUhFRW9FUHY4cWpEN3lUVmNkZHc4UjRReldBTEJCZytXRm1Gci9LYkhNRlUrWHpDQW15Z3dVbzB4NzJQZlNYUEhEbjM3TGxLUTloMWlkRXdHRm0xeW82eDd5VnN2dEc2aGt3b0RQNk5oWm1MbWZaeGhZcFhZelhJQUdDYUNDOWkxNzlGelRYUVRyaFFzcE40SXZmQXVaWmtycGRjWkNnRTJWbmV6WmNJbUswT254MWR0YitMamU2ZU5VSysyRENqcTlkaEJDMDVBRFNpQVhLVmpTYVJqUWl4R0RIZ3IzVDRGbkFyMHA4MndXZHlGdGJJK0czVFRiZXVCQVFnQkFONVBNakxUNTN4NE82ZXRzQys4NC93ZFpPWWk5dGlPOHl5N2NpM2NoQjR0eFd5ejRTNGNRaVFPZzZ2UjU3VEZ5VmdqeVlYU1JZMVFBT2RHSjhxYVJySlB0b1UzUFF1U25ZRmFQUk5tV0RqRERZV2RWK3ZSblo0R3d6MjJCQU5aU1ZuZmlxbzQ3bHM1UE9WZlBMYk8yS1VkdE1YMkFHQlF3NkU5YzBkKzFkeGRyak50Rk9vRGhDWi85NTdIaGdLMGVmQzZFRzV4NEdpNzlPU2g4Z3BLY1IvZGNvdTZmUW40ZnNrQ0pRL3ozVWIyQnF6VTZhUG93c081Ymg0QUpjdS9EbXE3UW5CdlNaWi92V3R6TjI3R2wwSnpjeVdBVFo5VlJ6YjZiZHZvYk41NHFpQldxZ0dvSWl0RWYzc09mQW14aTNTTGQ5S1ZWL0Y2M3VWemo2TElqRk9sUmRnQVVRRUFNTXEzdkpkaFZyMWtKdUxjTW1uNG9xb0w0WlBJT1JHSENJR1ZORVRoSmdCdG45eThNQnJ4OGRzN2NGaFhkMm9oZzJmbVBPK25TUTNReTJEOU5rVTlrcGk0Mi9vR3lGaThwSWtBdHZ4TVNZblIrSytBa0x6WXRHMjNaQnV3eHZ5ejIxNjBhWVFaRkFVUFY3L3FtaXNEOW5WTGYxK3ZTbmU0NHNRTllWamV6dHBmSFVSbjRUc000c3ZNL0VpU0hCVEYvOWhVWDcwN0t0ajQ2MDJJWElOOXpWYko0YWkrL2ZjblM0c0JxSXhsVzBZM3pkdmdVK3VtM2Fqemp0S1A0TWJGTXRrR25Pczc4M2hQREpFT3hSU1JnY2lYZ2J4a3NGbHFLdGFLZjR3djVRVjUxNnJKNjB5am1oMm05WUVKVHNmbzllLzhoOUJ6YWV3Ukh6VTRRQ0ZGcUU4QWE4dW9taXVJV21ENTZoTE1EaWc3UkhIdVNXYTcvRXNQOVJUbm42czRnR2kvVzF5TjVJSE95a003R01oWVUzczdqNFVzUnFpbEFnUGs2T3YwNjczc3RSNjI4bmh4dkkya2gzL0NibUYxK0x1STN4TmVEaDZWVDlWeUdPUlBsbUd2OVRKbGJ0eElENTRWL1NhajhYZkNkemV4ZXhOdFRWV1VUZmdCbVlRVERvRFhmUTB6WW1XcEEybm9QN0NmaGdIeUhmam9tRGtqak14UHBBT0E0RHo5d2c4WDdWK3IyUlRuejVZcTBIZHMvbFB4d3A3VFBCbU9PN2drSGxYSHYzdy82eGlTbi8rVk0ycGJkWHMvWWtqMkk0RUtFS1c1NTZVdkhsbUppb2Vtb3JjMGdyUVFPUEhoajZXMm5zYjhxQ3g4VUlNUmk0OXRkWmYxQVVYREJXcG9tRlNyOWxGczRKQ0F2TTdacjFTL3Z6Zkh6RGVzTU1FRFJ1dDg3M21yY29wL2NFV0I4RHpYUlA5My9xT2kvT1B6bjlhbXZVbnJ3d0M1Z2U4dHBmQlh5Tko3b2I5RHVZbldqWWFaN0ZZclpOTWNOSzJKS0NqVmRtZEJuQWdCc2YwaEhiMkxMdWRhUURJMVFWeUtDejZtU09tZm9rN24rTS9FdDQvUWl0VWVpT2d6Y2c3V0RZK3oxeVBvbWlYRTlqZjRocEI2YjFwSGc1NHl1ZndYQUFaaEFOWEMrbmFtNGw4QjY2NDlCS0I4Z0xNTmQ3SjVWdW80cVJFYnVNd2NKdlkyRU1pMUNNWG9TcUR0aGx4QUFkemRJMGV5azczMkk0bk9PdXUySDk2dE5adFR3eHJDQVl4QVFMKzIvQ3JNL29hdWhWVDZaVmRKaHVycWV0QTNRaU9LUVVqZTg2eFl3cHdVN0hyMjBuZTB2MmRHNC82K3Z1L2lwZ0c5OWxnRmhpSE5JNHZVYTZIUGR2N2h2d2liRk9PRFVCdVJIakl4eVJIZW9HZ2tFTXNHdEczODdCMzFoMjdHb0pFT0RRYlVPM011N2RubG5aRVdYQlZMc2RPNVk1WGg1ZW9DaUtDRE56K1VQVCsvempyWlNRd0lBNnc5cEpaekQwYXdmeitlZVNhU3dtY3BYWk5UVnFwNjlaWWI4aUI4K09SOTZkVXZ4YU1FWWxHV0JMV0pLQkEzSjkyNHpUV09Lb1hEU25LOXVZSkFRRWd3UE42Tlc3ZTJ1Z3pkbVFRU3dSNE5EdWJNYjlyOGpGVnFJK0FmWVpvdCtIK25EMGFTejVCc3EzMEJ2c2d2QU5tajNnZmhSaCtUU2h1Uko1QllpR0FoZ2g2QjZLQkFhc1dINDZYNy95YzFqcksreDdBRFkrOCtYRStBY0l3d1JpU1laMitVdElaMUEzTXhSaEFta3psbjZmYmRzYVJJZWlPSldEREpCRHc0RDIyTGNZOW1CMkRrSjZNclJncW5NelRYMkFiQnlVa0ZqU3d1eDBDUXlmam03UERlTmgwNkRVRjFwOXZaekdwdVdBUUFZWk1NQU0zQ0VBM1RaUXNIV3Uxcy9VTWYvVlVkMXdTYitHUVEwR21FR0lRQXBmZjNSL2Z1M0tGZHpsQWpOUWdHWUlKMjJBWnB2NDBPZmh3ak1EenozZEx0MjV4K1JvNCtybHRpd1BJWFM0cDEzeUoxUHpScnNGcVFWMUF3WjBTMk00QkVrN0RKRmxyQmlOeFl2UDU0VmtWaXpPaVpCc0VlbW5nTE1FNDRENG5ob29ETTdpSUFPRHhXZ1UwVGhKQXR3Z3daZmpKWGRzRFNlMkNQa0lWQU1CTUJEUUREa2tkVTdFdXUraUhyd2FlQW1Ub3pmZ3dHSUZxSWY0QktWUDB4OUM1anE4dVk1UThEM0dJY3BRbE5DZFdNbmV2Y3Y0OXJjK3lyTE9JaXZYcm1DeXVJektEUk5nUEs3SlhlQmN6TUFkc1BzeHU0Mk5SNEg3OFpUaEZPb0tNRURnN0dCMGZDc1IyTHYvQkk1WXR4a0w4SjBicjZPM1B4TUxEa3BrRHBxazBPa2dZckNqcldNajkrM1JUZE1MZXZVNFRLOGVnN0lGYnBBTmhBaEJXQU5tY01SeVk2U0Evb0xZdk15MzF6bGUyV3U0aENYR1lXWlFOZjczL1lwTHk1WjJsUUZLak5BQ0JlaFYwQ21FQUFkaXlYbmRibnJwMXVubWo4cFJ6bDdmc25iZHdNNTV2M3JkbHZEb3lSc01HakhZQVRQVDBFcXdjc0t3RUZFdzNDQ0hRSVRWMGV5aVd1QUdFVWJLRUg3YUFRbk1EQVFPR0dBc0NZWUFBNVI5YXlmWTZRbDd1bVNVN1JybWVIQjcvYVRiQjFQZDU1QjdHM0RMWUxzNXJBMDJBVVRVZ0F0U3NaSHNMMmJQZ1J0b0hDeHZBRnREc0swWU1IbGNDMDhyeUwyRTZocUw0cUFRdXJnbWlVWEJzUDh3dmRZcnFQYk1zbjdsMVp6NkhGaTI1a0p5M3NoZ0hrTGdDUXdRSUNBVnNEQjdMYjNlYmxhdGhSQlBZWGJmQ2c2eUNGWkEvNUU3R2U2K25kRlRZTTJHMHhsckgwTnY1Z0JYL2VPOVBIdzNkRVk1S0NsdzBMR0JjQ29Zb0pGT1MremNtVCs5WTVlMnIxNWhkRHZHMm5GalVJRUJCcGhnVUl0MmFSeTV5cmg5dTVqdGlSUFc4Unl2N0hmZGpJQjRURERERzN2NHpsM0RmV3Vuak5GV29oMk1Ka0x0RUlFQTlJWXdWaksrNmFqNGYrZ3FuTFpKTjJYRjF3em1oUlZVRE5uYVRBTW02Z1hSekJtdDBwQTdWUTJybGhjMGJtUVhNUW5Qck9rTk9jNkNpSVlIV0JDcUJNa01ZNG1FeFlBbG8xOWw5VG1zN1diVDlkQS9WclR0OUJpdFcxWFFzUXlKNjY1WlBIVUh6czlpZ3hMeEJveXJnUUk0SHZRQnpLWndRVm1BNUR5ODZ5WXF3ZklXZE9JRk1ISUNzZDBEUVRWWWh6VlhnRTFCbUFWenpFYUFJNEVhWXovWURLazZGenBYY01IUFBrem5LQ0N0cDlvZmVaeUF3Q0Z5aUFrQ21leVIxTHFkWFBXWTJRTm1KNURLaER0WWdQYllrTVhaLzR0RmlDdUFBejlCTTRSKy8wWTJuN09MZGNkQktqa295UUJqTTlBMVJCYlVpeXl1bjdDN2psNExUMXBqekM3QVlBaG1QRUV3a0tCcUlEc0VDNzhJOXFjMWpFZUUrQjUzMFdtRlgxNDJtdTZxYy82d0F4bHdBUVlJcWd4akhWYTg4cUp3eFVtcndtbVBQbHkvZXFvZER5U3o1WFVqWW0zRmlyYVd6KzRXUVNLWkVWcWdpc01FVGFPT2pHeW9hSGZGY05GR2xCa0xMREVMZyt4L0hjdy9VZ1E3S3JzaVFnNHFaSG0yMGU2VzJaeHhTTGRwdkoyZCt3cnM5VGxETEEwR2tVVTFkelFUdTZEaUdKTE5ZM3dXdEEwTXBQdUJTOEhPQllFRTg0dC9RdEg2T0t1WFFmOVI4UFpUYVkrc1l2YitCWVl6TVBLa2ZSVGxQbUk4SHh6TVFBYjE0TXNFdTVKUTNJTDd5NGlEODBoanM3aFZUTzhCOTF0b3QycFNUTWhBQmpTUS9YTVU1VmZCZDdNNDJFSUlsN0ZtNVJ5akpYeml6NkN1dHZQY04yUjYvVVRUaDhYOUg2ZlYrUnVxR2FBL1RxNStnbDRGcWZVTkx2ejUvYVFDSkE1S0psb1c3R1F6UXhJbVkrajYxb1lqdU5iTjJEY0xHSmlCZUp3QkpUQjBRUXJXM2JEQy9xQXN3cHVHdFNYTU9jakVmaGtkb0NQQVhXUEhMRXZ2bmU5amNqNWlBZWU3aEtocWU4YnhhOEw3V3V2aUtmZmRuUi8rNWozNjBuT2VUcGhNaWd4QVlKVjRhb3hXRm9US2xVRUdCbklJMFg3WmpKY0hWQW1iMkQvamZ6YlJzdThvV2QrenVza2dpL1lnKzUyaklkNkpHV1lRZ2V5QlBaWE8zZEFORndmUmRURW0rVHRhcFI4UnpKNlIzZWgwd2ZZM2ZHYmZlYmRkYyt6TFZsRnJJNE9xRFdxRHdBS2dBOEJid2Y4bktRVkM2MU5VTTU5aDFTUzBPdEFmdlppaTlRSk1zTGh0R2NrZ05uTlEvakxLZDBBOGg1QVhxUHQvRDkxUEVGT21HWFlKY1JsaWlUYWpaZ3IzYWJKZGgvUk94RytoUEVXSWN5aThINXAzSTEra2JxQS8vQjNXcm9VN2J6akFvL2ZEMUJHdzdiWlBNNnlPcENqT29hbitsZjdzQjJsUFFRUjZ1MDlnWk9Sa0hERDdKdFVRcWlHUFNSYVlER1pQRm9jWndreXIreFcvR1F3cmpFSThyaFdNWllLVndPZGRmTWhkNThUQzNybHFNcHhmdTJnYVVRU2pjdDBXc0ZjWDBpdWFhSmZLUlJhMElxTmxOMzVnNlA2ekxuME83Q0dEbzhHZUVZTTluUkRHNkxuUHp1YzNiWnppb2VaQVhxYnhzSzFWaE9YRFNwalpCYVhDUjh6MEJvYzVscml6UEpxOXZTenQwaW9UT3kxalVHbjIwV20vdTczQnRyZmEzRCtZdFpPellEVFphM3BWbUJzMjlydXRrc3JNa0JoUFFiKzR2aDErVHpCbEJsbTZ5NHkzSjJPRjBCYUxScjJZU1NWM1BianFLVitibVZ2M1U4VGVrWmdEOGRtNDMwM09FQU9ZL1J1UjYybTFDdEE4MVg0SVU5QlVteWxiNzhmS1plUStMSC95WlJURFc2bWIvZURUaUxlVDJxTU1Gb2JNN3g2eStoVElmalRXL3pneG5Zc0RGaTZpR1o2QzZkOW9wWXp4eHpTNmltWndCR09qOTFPSDIvRGdaSWRXK2ZzVTZlMjBPckRub1JPcGRTV25QZzNXYk5wSHRyZXhzREJDcXpYSHlDUTBEaUhCL1BSR3hpWlhZUFZlY3ZNUU1yNWZHaG5WK29WNU95MUVEbkZBMkhHbHdsdWlBY1poeGlFdTdUWFpmVUxIaEVLWEUzaGE1YXlpaG1oR0E5UlovK1RHYjdqbjc4ajlFU3hlSEN3Y0QyS1lSVEFya29YbnVQakpBSDJEdG9LbGdpVXlXUFJMSnp2NmgxZ0VGcWZaLzhoMi9jMEp4M05xVVpKeUEyWjZoZEFXSS95clJMZFQ4RXpITnN1ZzB6S2lhV2VLZWduR0xRTXBET2E1Y2lUWXliVUxpMmJkTXY1R25YV2hZVmVEdW1aMnRzeE9HNDFLMmFHVzNTRHBKUlkwSU5oNVlBZ0RCd0wzcklyN0ZxazREVXRnQmpHK21leDNJbjBSTThpQ2ZqTmdjR0RBN0NPUWE1QzlpRmk4RDF0WWo5Y2dRV2ZpRXVycDkrTFZINUhDdlpnNStCejlQaXowbDdHT1g0RDhGaHBianNRaFJpSVc3NllaL2dJcDNvWFVZTTMxcEJMbTUyRlFRWHRxUGEzd3Y1Qy9GRE9ZbVliVG52M2J4UFlPZWdzZllkMnhNS3d5ZzJxZWxqMmJPaCtMNnk5b3QwUmFmUkc1QnVWdjRIb1l4UGRMdXc5dzNuaGJIWGN3UUlJaVFwRmdXQWwzc01BUThZamc5aWI3cmtRWWlZVTlIN04xTGhFRWpYRFE5WXREZjM4MFB0TnFCYzlBSSswSTJYOHBwWEM1c0dNZElRbHhTQlNNR2xDWU1XZzBiZGE4dm9VKzdkbndESjBJZXc3b1kyc2FmOXJxa2ZoenZWa25tOHpnekdEaFRBRVJFWU5SWmRFZmF1dFlsMWVueEhXR3lBZmNMZHRmeHpGN1Z0bTI4L3A5c1NTbVpPZTRjdzRZQnpsR1B3dDMvNWNRd3Bzd3RnMXJKbUlSbmhtQ2dhQVRLbVkwZGR2bjlUd29PUXZtT1VSYVRReVhJLzhZOEZWY0R6QjBHTTZ2WXpnNGhiWEhQNU1tUDVPOFdCSVRoNWhCTlE5MGZvR3lmU0dldndpMkMyOUVkL3hJeXZZRkRCZVBCa3BDQW5HWVo3QjRGbVg3TThEbG9Pc3c3U2Fta3JuK01YajlGTHJwZWVESDBUaVlnV2RvalhhbzYvY1NlRGJEM3Exa2IyaVh4K1AyWEZLTWlKOG0yRGl4UEEwMTROeE10bG1NSjBqYjl0blpaeHhuRE9ma0JCUUN3MkdqaGNWSzAyV3luZ1ZseWVZeFRIQmNDdUVDQzR6V1dWbmkzbVM2cndqY09aZTV2c3E2T3NyMlNlSXhCcGk0YnVENXhRRzdMSm05ME1GU01DUndpU0xTbTZuMWp3dVYzcnV5eGMwc2tVUnJNdERwR2lkTXNaQ0MvYXF5endxOU1rVXJ6STFHQW94YTBFN2E0NVd1N0EvMUoyUGRjRDhDQktwRXU5U09uTVBMOTgzejV4TnRQU3NSR0dZb0FramdFZ20vWjk5UUh5NGpsM2VEN1I5VWptQUNPQldKUThUaVBsdisyZnQxM0JiRTZZUWFDRFh1aHRrYWl1TE5vTmVRd241R0NxTllQc215SThhSVJhTHVRNjRiUWlFUWh4bGdFZXhvVEsvam9KeWgxWUdSU1JqTUMxRVRBaytrUUV4YlVINFhoQmtJczdoS3BwWXZ3MndFcjFuaW1EV0FFU0lNZW1BMlNvelBSLzU4WW9RRXVBQ0RZSmNnQjNPV09IQWRRZng3YWZQcThNRnFVWi9FYUVBS3dSWjdmZVlYS3kwZXVkS3lHcHNhVmt6R1NOdGdCT1RJcHB0R00yQUxLWEVBbUhmUnVLQmdpZkZFQmxuNmxzUC9rT3VLWVBhVW9ldW9FR3dZcEh2cXhyOWVLOXprTURTK1R6U3NNRG9KQXV6MnJEY09oL252S3NWbldORHhMUWlZcHQxMWl6SmZrN1RWekRLUE1TQUFCaUh3NE40NXZlVGhQZjZUVzlieWxMSmd3NkRDek5pWlROZVkrSHFXSGhMRzlFSk4zWWlVN01CSWFhOFJnU0FsRW90ZnFKOTE4MTM5NDFmUTdiK1NRTVpWQVlaa21MV1J1aGh0eWdRaDFCaUxWSXNEakV4SWdQTkVEUWdERXBBSUJybHV5RTJEbVRDV2lCK2dKZ0FkakJITUVwS0ljUWowYU9vaFpnNFlqekdXeUpBaVVDQUhVUU1OQjBrUmNFUWJiQmE0aVIvaS93SDNENVBNcGQydDVRQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiLCJGSURPXzJfMSJdLCJleHRlbnNpb25zIjpbImNyZWRCbG9iIiwiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCIsImxhcmdlQmxvYktleSIsIm1pblBpbkxlbmd0aCJdLCJhYWd1aWQiOiI2MDAyZjAzMzNjMDdjZTNlZDBmNzBmZmU1ZWQ0MjU0MyIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwidXYiOmZhbHNlLCJwaW5VdkF1dGhUb2tlbiI6dHJ1ZSwibGFyZ2VCbG9icyI6dHJ1ZSwiYmlvRW5yb2xsIjpmYWxzZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3IjpmYWxzZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlLCJzZXRNaW5QSU5MZW5ndGgiOnRydWUsIm1ha2VDcmVkVXZOb3RScWQiOnRydWUsImFsd2F5c1V2IjpmYWxzZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzIsMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6OCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjIwNDgsImZvcmNlUElOQ2hhbmdlIjpmYWxzZSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjI1NiwibWF4Q3JlZEJsb2JMZW5ndGgiOjMyLCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6NiwicHJlZmVycmVkUGxhdGZvcm1VdkF0dGVtcHRzIjoxLCJ1dk1vZGFsaXR5IjoyLCJjZXJ0aWZpY2F0aW9ucyI6eyJGSURPIjoxfSwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjUwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDUtMTYiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkV4Y2Vsc2VjdSBlU2VjdSBGSURPMiBGaW5nZXJwcmludCBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMDUxNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA1LTE2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMi0wOCJ9LHsiYWFndWlkIjoiNWZkYjgxYjgtNTNmMC00OTY3LWE4ODEtZjVlYzI2ZmU0ZDE4IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI1ZmRiODFiOC01M2YwLTQ5NjctYTg4MS1mNWVjMjZmZTRkMTgiLCJkZXNjcmlwdGlvbiI6IlZpbkNTUyBGSURPMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiLCJiYXNpY19zdXJyb2dhdGUiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjlUQ0NBWnNDRkRXNDRhZ2x4WmlZL0ozREpGQzRlNW83NDIyME1Bb0dDQ3FHU000OUJBTUNNSHd4Q3pBSkJnTlZCQVlUQWxaT01SSXdFQVlEVlFRSURBbEliME5vYVUxcGJtZ3hEekFOQmdOVkJBb01CbFpwYmtOVFV6RVBNQTBHQTFVRUN3d0dVbTl2ZEVOQk1SWXdGQVlEVlFRRERBMWpZUzUyYVc1amMzTXVibVYwTVI4d0hRWUpLb1pJaHZjTkFRa0JGaEJoWkcxcGJrQjJhVzVqYzNNdWJtVjBNQ0FYRFRFNU1UQXlNekEwTVRnMU5Gb1lEekl3TmpreE1ERXdNRFF4T0RVMFdqQjhNUXN3Q1FZRFZRUUdFd0pXVGpFU01CQUdBMVVFQ0F3SlNHOURhR2xOYVc1b01ROHdEUVlEVlFRS0RBWldhVzVEVTFNeER6QU5CZ05WQkFzTUJsSnZiM1JEUVRFV01CUUdBMVVFQXd3TlkyRXVkbWx1WTNOekxtNWxkREVmTUIwR0NTcUdTSWIzRFFFSkFSWVFZV1J0YVc1QWRtbHVZM056TG01bGREQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJPMFpsUk1xa09QUnFITmE0WGo3b1R2RUtITHRqV2V4dnVBQzhXTGxLNTNUSUdYYzJKSjNHYkVhVm8xMHRGam5MSExYaGVLYWRaQ2oySEV6M05KU2FVSXdDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTEhlcWtjbDhPN2t5MWlSWGljVkFDN3gyenNVMTJ2UzNCT1Z5WENnZWRFM0FpQmxNKyt4bnpPT0VzMm0zc0Y4L1p0Ync2VUwvQU1UMVpYdDVmeXFVaEl1V3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFNd0FBQURNQ0FZQUFBQS9Ja3p5QUFBQUJHZEJUVUVBQUxHUEMveGhCUUFBQUNCalNGSk5BQUI2SmdBQWdJUUFBUG9BQUFDQTZBQUFkVEFBQU9wZ0FBQTZtQUFBRjNDY3VsRThBQUFBQm1KTFIwUUEvd0QvQVArZ3ZhZVRBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBQUIzUkpUVVVINUFVWkF3bzJrK09uR3dBQUhlNUpSRUZVZU5ydG5YbDRaRldkOXorL2UydTVTWGZUVzFLaFFZUUJHNlNUQUFPNDRMaWdvZ09Nci9vd3pEaUtEZzZpcUtpTUl5Q0RPQW9pSUw2STRvSW9Mb0NDd3FpdmlPSTJNR3dxQ2kxMEtyM1FyTTNXcWFRWE9wM2tWbEoxZnU4ZnA5SjBOOWxxU1c3ZHF2TjVudXJrZVRwMTY5eGI5M3ZQT2I4VkhBNkh3K0Z3T0J3T2g4UGhjRGdjRG9mRDRYQTRIQTZIdytGd09Cd09oOFBoY0RnY0RvZkQ0WEE0SEE2SHcrRndPQndPaDhQaGNEZ2NEb2ZENFhBNEhBNUhzeU5SRDhBUkQwYTYwNEFpekJQd1JZMDNmdStJaUlpaWlnQUdSVldSb3FLaHFncXRhNGFpSG43TmNJSnBja2E2TXFneDRubGVFbUVCc0FCWURMSVlXRko2TFFZV0Fuc0FMVUJ5dDFjQ01NQVlNTHJUenhBWUFvWjMrcmtWR0FDMmxINGZSSFZJVkVkVVRRRjhEVmJub3I0c2srSUUweVNNckdoamJHaU0xSUowRWxpTXNDZklmc0J5WUg5Z1AyQVpWaUR6Z1ZZZ0JYalU5ajRaRjlZSVZrQ0R3R1lnQnp4VGVqME5QSTJ5RWRGK2xPZFFDVWtrRFBrUmdyV2JJN3VPVGpBTlN0aWRBYU9DSi9OQlhneDBBWWNBSzRDWEFIdGlaNDFrMUdPZEFNWE9VTnV3WW5vV2VCSjRISGpNL3E1UG8vUUxiRE5xUmdVSWVnZG1mV0JPTUEzQ2FQY1NpcVlWa2RFMEl2c0Fod04vVi9yNUVxQU51M1JxQk1hQTU0QStySkFlQVI3RkN1b3BvQS9WemFEYkFRMnkvVFg3WUNlWUdCTjJkNkJHRVpFV2hJT0FvNEhYQTRkaGwxZjFPSHRNaDhIdWZZWkxyKzNZNVZ1SUZVb0JLR0xGbnlxOWtvQmZlaG5zN0xRWitDdHdOL0E3SUIvMDlGVTl1RVo1NGpRVllYY0dVQi9WQThTVFk0RmpnU094czBpY0hvSWhkdSt5QVZnUFBBdzhnZDNEYkFHZVEzVUVZUXlWTVVHTENBYkZsTTdUMTNHaENBbVFKQkJnOTJGTGdVV0FqK0xYYXNCeHVyaE5UYmlpRFh3ZlZPY2pjaFJ3SXZEM3dEN1lqWGtjR01OdTZoOEUvZ3pjRHp5RWFqL29rQ0JHSlVmUUUvVXdKOGNKcHM0Sk85dVJSQktLeFNVcXZBbDRML0JxckNVckRveGhOK3AzQUw5SDlYNlVwMUlweVErTktBdlcxcThKZVNLY1lPcVUvQ0Z0cVBFQkZpSzhEZmdBZHRtVmpucHNNMlFBdUFQMEo4RGRHSjRSS0taNzR5V1EzWEdDcVVQc0hvVUE1QmpnbzhEcmlJZFFGRHViL0F6MHh5aXJ4Q05mS0FqelZsZS80YTRIM0thL2pzaDNaY0FVUlZXNkVENEJuSUQxdk5jN0JydHAvd0h3WXpIRlIxVEUxTktjV3krNEdhWU9DRmQwZ0tjQWl4QjVML0F4NEcraUh0Y01lUnI0THFyZnd4UWZSMFRud29FWUZXNkdpWmg4VndhdldLUW8vdUhBWjREamlJZi9aQVQ0R2FxWENUd0FtUFRxVFZHUGFkWnhNMHlFaEYybHZZckllNEJ6c2ZGY2NhQVh1QVRscHdqRHRYQUl4Z1VubUFnSVYzUllsNXZTaHNpNXdHbllZTWQ2SncvY2lPcUZ4a3M5NUp1UWRMWnhsMThUNFFReng0U2Q3ZUI1b0hvZ0lsOEUza0k4SEk4RHdFV29Yb1ZJVTgwcU8rTUVNNGVFWFcySWwwSzFlQ1R3VmVDVlVZOXBoandNK2dtTTNvS0lDYkx4OXFWVVF4eWViQTFCdmp1RDhaT29LYndldUliNGlPVis0RitMcWVUTkFrMHRGbkF6ekp3UWRyV1Y0Z0xONjRDcnNlSDJjZUFlNElPZ1dSQ2FkUm0yTTA0d3MwellsUUVSZ0ZjQTN3RTZveDdURFBrRDZLa2dhencxcEJyUUNWa0pUakN6eUZqblVvcGVBcFFWQ05jQ1IwUTlwaG15Q2pnWmVBQlZtbjBadGpOdUR6T0xGQ1VCeXQ0SWx4TWZzVHlGOHU4Z0QyQ01FOHR1T01ITUV0WXBxWHNnWEF5OE9lcnh6SkJoNFB6TnIydTdIYU1Fdlc0WnRqdHVTVFlMNUxzeW9FVlB2Y1E1d1BuRUp3VHBDbEU5V3lIdlpwYUpjWUtwTVdGbk8vZ2VLTWNCMTJMVGh1UEFuU2p2Qko0SnNzNGFOaGx1U1ZacnJCZC9QK0FDNGlPV3pTaWZSM2hHVktNZVMxM2pCRk5Ed3E0T1JEVUo4bkZzZG1SY3VFNHd0NEVTOTR6STJTWXVhK3U2eHpvbkJiV0ZLVTZPZWp4bHNCNzBTaFVwQkQxT0xOUGhacGhhSVI1Z09vQnpzQlVsNDRBQzMxRkpyc090eEdhRUUwd05DTHN5cU84RGNoSndWTlRqS1lNc3F0ZUxLVGgveXd4eGdxa0ZJa2pSTE1kV2RvbkxOVlhnT2hMK2sxSTBVWThsTnNUbHk2MWJ3cTRNT2pZbXdQdUFnNkllVHhrOGl1cFBLUnJTYTV5RGNxWTR3VlNMQ0pKSXZCUjRSOVJES1pOYjFSUWVSZDNzVWc0VFdzbEd1anBBMUxNYlFURXR6cEUxSVdGWEJqOVlRREVjZkJmeHljY0hXK0Q3LzRtZlZCZXlYeDRUbTVXdC83OWRSTjRCNU1MdXpFcFVueEM4ZkZFTXJUMXVDZ2RBaEdLNGJYK1F1TTB1cTBCWFJqMklPRExoa2t4UVJPbkhadHVkQ1BKcnhMdEpoWTk2ZUllRjNabFdQZUlvaHJ2ajRzaXVQV0ZucHZSZ2tiY1NuNFN3Y1g2RGVGdHdxN0d5bVRTV0xGelJCcDZQamJpVjl3Qm5BZnNDL2RnNlZMY0J0NkhhbTVxL2FDamN0b25XSnFoTHRlUDYyQkpKU3hENUJmQ3FxTWRUQnB0UlBSNlJlOTF5ckh5bURiNE11eksyYVk4dmg0QjhHbmdydG9tTlludDRyQVIrRGZ4ZTFLekQ4OEppMGREYXdLSGh1bGNyK2FVTEFONE8zSUR0U1JJWDdnRDlQOENnOCt5WHo3UldzaUNiUS93OHFLeENPUVU0RTlzV1RiQ05hNDRCdmdqOFJzWDdzU3J2OTBUMkRUc3pYdGpaRWZYNXpRcmhrdm1vTVQ3d051SWxGb0I3RUcvUWVmWXJvNnp3L3JBcmc2SWlJa2VCZkE3YkltNTMwUld4L1FaL0NkeUU2a29nTEJyRHZOV05VZlF0N080QWREbkliNG1YZFd3RStFZmdWcmNjcTR5eTgySHlLNWFpZmdKVU94QTVDMXUxY2JMbVBwdUIyNEVmb25vNzRtOVZVNlFseGhHeG81M3RHTThENjlXL2tuajVzdFlCYndTZWRvS3BqTEsvN1BUcVRhVnlPOUtIY2k1d09yWjc3VVFzd1Q3UnJrZmtaakNuaWJEWDhONCs0Y0ZMb3o3M2lqQWlvSnJDcGgzSFNTd0F2YUthdytXOFZFekZYM2lRN1VNd28rbWh2bXV4WHU0N3AvcHo0RFhBMXhINWxiZWs3UXdTL2w1NnpFTHJKSTBUSWlDeUgvQ3lxSWRTQVg5VlQ4YkU2YVZpcW5wQ3ByUDk1RnN6WUJ0OHZodjRQcmFuNFdUNHdLSEFaU0MzNVB1QzB3WHRNSWZ1elVobkp1cHJNUzE2d0k2by9hT0F2YU1lVDVua2dRZFFYSkpZRlZTOXBBaXlPYnRFVTMwUzFZOENud08yVGZNMkgvaGI0TXVJM0RKcUN1OFRrY1ZoZHdmaGl2b1ZUcjRsalppaVlHZkxtcld5bmlNR1FCL0NtY2Vxb21acjhGSSt4WFpSdlJnNEE5dVpham9TMkZUZWJ5RDhOL0EyUEExS1RzRzZSTVZySjU3THNhZFFjazR2MVZIVFRXdVF6YUZDQVFyWGdKNENySm5oVzFQQUc0QWZJTjYzRVRraTM5bmg1ZXR0ZjJQM0x3Y1JuM1o2Ty9Nb21NR29CeEYzYW03bENYcHlTQkhGUy80V2VBL3d4ekxlUGgrN0YvcTVldnluQ3Bud2tBNUdPOXVqdms3a094ZVAvM29ZOFdqVXVqdnJrVVJSM0JSVEZiTmlGazJ2M29RV3hnRHVSL1ZrNE5ZeUQ3RTN0Z0RlVDFDT00wSWk2bVdhU2hJcEdvLzRsSHpkR1lQdDhVTGFGUld2aWxuekk3VDA1cUNRQi9IV283d2Z1QkhLaW8vMWdWY0RQMFM4endON2pYVHZ5V2pua21pdWxBanFld3VKVC9YOW5ja3pzejJsWXhwbTFmRVdyTmxLZWtoQjlHbFVUd2UrQ3hUS1BNeGk0Q3hFYmhMTUc0MzRYb1N6elRMZ1JWRjllQlVNQXM2V1hBTm0zVk10ai9aUmlvb2RRUFVzNEp0TTdhdVo4RERBcTBDdVI3eFBBb3Z5WFIwTXpYMCt6djdZNklXNDhSem9acmQ3cVo0NUMrMElzamtRdGdwNkxuQUZNRnJCWVRMQUJZaDhUMFc3Tlptd2hiOW5tZEdYN3RESWdWaUxYdHpZaERMa3lzQld6NXpHUWdVOU9WUVpSUFV6d0dYWXRYVzVKSUMzZzl5VUdOTVRGUHpaWHFKcHdtYzB0UkRnZ0xtOFhqVmttMERvS3M5WHo1d0hENVptbWlIUXp3R1hVcGxvd0pZMHVocVJzeERtaDkyektSb2huZCtTSnA3K0Y0Q3RCZ3JHTld1b21raWliVXQ3bWhIUWk3SEpaNVdLWmpGd1BzaVhVZGtyN081Z3RMdjJQaHVEWVBEbVl6ZjljV1J6UzArZjg4SFVnTWpDMDYxb1pBVFZpNEQvUytXaVNRR25JRndEZW9qQnN6MWFhb2gxOExNSDhkendBd3lPSExvWG5xdEJWaldSNW5NRVBYMGdNZ0o2RWZBbEtqTUVnTFdpSFFQeUE5RFhqeFkzTXd2N21xWEUwOE1QTUNJWXZLSmJrbFZMNUFsUU50SlpobEV1Qkw1SytYNmFuZWtHK1g0cTJYYUNvRkxUZlkyeUJHaU45bXBWVEloQ1lxM3o4bGRMNUlJQm00eUc2TENvWGdCY1RYa1JBYnZ6WXVBYkt0NUpHTHl3VmdHY3dtTGkyMDluSk9vQk5BcDFJUmdvbVp5RmJhQ2ZBcTZqdXNTTkR1RExlSEtLaC9GcjVLdFpUUHh5WU1hcFp0WjI3RVRkQ0FaMkdBSTJvM28yOExNcUQ3Y1UrS0lSN3pTakpFYXFGODJpcUsrUEkzcnFTakFBRWhvUXlZR2V5ZFIxQW1iQ0l1Qmk4ZVRER0VsVVVpZXRlUEFlcUFqQXZLaXZUUlc0M1g2TnFEdkJwTmVQYjB6bE1lRGp3T29xRDdrSGNLSDRmRVRFSk1PdThrek9CUzhKNGdPMFJIMXRITkZUZDRJQmF6bVRZaEU4V1FuNmNhb1BUVjhBWEtEaW5TcXFaVVU3cTNoNDZSYUl0MkNTVVErZ1VhaEx3UUNrVncrZ3huRDN0dHh2Z1hPWnZyREdkQ3dBTGxUUGY1ZG5Dakp6MFFpcGdTY2d2aFl5aUdmQWFGMVN0NElCYU9uSjhab0ZHVVROOWNEbFZHL3RXUUpjYXZ6RThlQ1JuNkdmSmt6TkUrSnJJWU9TWUhTdk9HL0Q2b082Rmd4QU9wdERrUUtxWDhKV3lxK1daU0NYSSthVmlreWZIaUNBNzhYaVdrMUJTa1VvTG9wYjNmVDZJeFkzZ1MzaEpOdUFUd04zMWVDUXkwRytnbktnaWpEYU9YVWltbWdSYkpIMXVKSUd4bXRDTzZvZ05sZXdGR243QkhBMjhGZ05Edmx5aE11QUR1Tk5zZHBTR0QzNEtDWGV6citVZWg3cXJNdFZFeHZCcExNNXdJQW0vNFN0S0xPOUJvZjlCK0MvVUcyWjNBaWdKQjdyaGZMVHF1dUpsUHpiVjFBWDNsODFzUkVNUU5EVEQ0eUIwUnVBcTZpKzdxa0FweUJ5S3BOWXpqeFZwRkFFQ0tNKy95cEl5MVduaWZOZlZrK3NCQU9sUUUxUFJrRXZCWDVUaTBNQ244SlB2Z254Mk4yeG1aUThZdk5JaHFNKzl5cElJWjVUU3cySW5XQXNCcEFjNkhuWWJtZlYwZ0ZjakpybGlLRDdQdjhma2gya05KRU5SWDNXVmRDcVNFeS82L29pbGhjeDZPa0hOZUFuN3FlNnVnQTdjemdpNTZNc3lDK1ljRDlUcmVNMFNsbzhFVS9FVFRMVkVrdkJBQVRaZmlnVVFma0I4TjgxT3V5SmlKd21VcER3aGJVQnRoQmYwM0lBSkZ6bnNlcUpyV0JnUFBHTUllQWlZRzBORHBrRVBxRWtqNTRnRXVBNTRtdGFEbFJJcXB0Z3FpYldnZ0h3Rk5SR05GOUNiVElMOThTYW1qdDJleDV2SmI2V3NnQ1ZKRTR4VlJON3dhU3lmWWdxcU40RS9MeEdoMzB0SWgvMmlzYmJLWFJtSy9HMWxBVUlDV2RWcnA0NFIrRHVJUDNzQ1BtOVdvZXhOYzZPQXZhdDhwQWU4Q0hqKy8rTGJac09kdE0vU0R4cmt3V2dNdzd4MzdwOFJ5L1BYU1FtUmhTQmhROXZqZnA4SXFNaEJDT2JCZ21YdFpKNDE1NHJDemRzL0Rwd01kVkhGN2NELzRucUttQVRNSVRJQUxhK2N0eElnYVNuK29QOGlxVm9JZ25HTEVYa2RkZ0h6NkxkL3F3UHVDdnN6dHdEc24xMGRKQTkxc1YxMHEyTWhoQU1XQU5BZUFPQWZnL2tXR3dMd0dwNUF5S245dmYwZmFHdHMzMVlSSjZOK2p3ckpNa1VDWERoaW5ZMDVVUFJISW5JeGNCcm1UeUhaaGprNTZEbnBkSUxIZzFYekNkWTNUeWROR0svaDlrRkF5QUQyRUxudGZDYitNRHA3ZDBkUitMN0JlQ3BxRSt4UXFZVURMNEhSVDBJNU52QU1VeWRjTllLdkJQa2F4amE4WnRyWTlSUWdnbDYrMEFWMVB3UDFWZWRHV2NmNEpOaWlnRTJXanFPVENxWXNET0RseThJOEFGcy84Nlo4bWFFZndKaHBNdzZDWEdtb1FRRDQ5MEJ2RHh3SlhiTlhRdmVnbmduWU5NSzR1aUxtWHlHOGNDay9RendwaktQNlFQSG95Wm9wZ2lDaGhNTVlHY1pZKzZqZGhFQUFmQWYyT1ZJTGRJSzVocWZxY3RFTGNVMnF5cVhGd0h6bXlscm9DRUZFMlJ6NEhsRjRCcHFOOHNjQm55V2VOWlhGaVlWakFBeVNtWDVQbm5pT2VOV1RFTUtCaWpOTXZwWHltOTVQaGsrc0p4NFZtRHhnUGtUL284Q3lrWmdmUVhIN1JGanRqWFBncXlCQlpQTzVzQ1RBclp3Umh5WFViVm1Zc0dnSUd3SHJxVzgwSjhCNElmcSt5YlZSRzFuR2xZdzlxbW5vUG9uNEM5Umo2Y09tS2RBOGVCZEMzN1lBaU1LcWpjQzMySm1TN01oNEJJMTVrNVZSWndmcGpGUUJjVGJCdndpNnJIVUFmTVFuOElFOFErbEl2RERLT2NCbndBZXdFWm5EKzMyMmdMY0RieGYwSzk2bmhSYnNzMGpGbWlDSk8rd3V3UGdVR3c2YzQyYXhjU1NLMW0rNE1PczIwYlFPL0ZOYmdOTlZSVEpJTEtmS2p2Q2FjVCtNd1Q2YUhxN3QyVzBWVW4zMXNxZUVoOGFKalJtR3RZRER3SnZqbm9nRWRMSzJ1Y0VUeVkxQXR2S1BDaldzdGg4YXBnQkRiMGtBK3k2VEdRWStHUFVRNG1ZZVNwTjhIM1BNZzEvQVlOc3JyU1o0WDRxYnpyYkNMU0tFMHpWTk1jRnRMNkdoN0ZoK3MxS0lDS0podCswempMTnNZZXh5L1ljeUViaW1RQldDd0tVSkRGdkVEdlUzVWFnUG1NWUg1RTlRQmFqTEVZSUFFVVpBZDJDelpBZFJDaFNFSUkxdGRtU05ZVmdTdHZjSVpYbW5tRjBCdDkzZUhBYmpJMUJrRjZLeUlIWVJEb0RQSXZxUTZSU2cyWjRPNjFydDg3b1EwdFd5aVR3TjhCKzJOQ2liY0Jqb21hRElzVmdHdE4wMk4wRytBZ2FLTEppVERnYXZKY0JMd0U2RU9aanowMFJ4a0NHWUVmMHdwOUljR2ZZbFZtSEozbkdDZ1JyS3I4Tm1tS0dMclVlVHlMY0RCd2I5WGdpWWpYb0c0QSs2M2ZabGEzTEZ4S2swd0NMRUhrbmNESndNUFlHVjJ4NjlrcmcyNmorQWhpWjZrWVB1eko0YXNSNC91SEFoN0FXeWd3MnhHZ01lQWE0QmVXYlk2VFdwaVJQZW9KeGxjcjNCb2k4RVRnRmVBM1F4c3p2WFFWeXdCM0E5MFgxTmlDZnJ0Qi8xQ1NDeVFBc1FPUlh3S3VqSGs5RVBJck5wSHc2NkhuaDhxUTBFeXpESnQvOUU1UFBSc1BBbGFKNnZzTGdSS0lKdXpPSXFxaDRKMkxyTEV4Vlk2RVhPQjNoRG93eWZyeXdNMFBRbXlQczdqZ0VPQXQ0RzdhTFhEVnNBMzZFVFdGL1hEQ2tlL3JMT3NDY0MwWVBhaU9mOHNFK0tWYUEzb2JxNDRJM3BqSkcwTE81NXA5cGJ3YmRIK1Ivc011Q1p1UkowTmVDUEw2N1lPd01yUE1RK1JydzNoa2Nxd0JjaERFWElMc3VxVVk2TTdhTXMzSU13clhNYk0vWUE3d0RXQlAwOUJIYWVuQUprQk9CQzdCQnI3WGtYdUFNaEh0M0Z1bE1pTkJLcHNQQVIwRnVSN3hyVkRnSkV2dmt1OXE4ZkEweitKNC9scndHbTcvUnJDUW1Lb1NSNzhxVUl2emxMZGliZG9iSDRvT0l2Snpka3NkRUFOVkZDR2N6Y3dOTE4vQXgwSVI5dUVrQWNpYTJRME90eFFMd0N1QTdxTDRDRWNycHJEM25ncEYxQTFBc2dKZTRIK1VEMlBpa2R3TGZBL205aXY4MUZlLzRzRHVUeVhlM1N6akRQcFNUb2JZRzk5N0FhVFNKa1dNU0VzQUxCS01vcUVsanhWSk9wK2dNSWlmZ3kvZ2UwU0lDd2l1QXZ5dHpmUDhBY2dCcUV0aW1XWi9CdG94L2ZxZzJtbm9UTmdwaEs5V1Y3dTBFdVJ4MHYzTHF0RWR5QXdXck54RjJaaERmKzRPcXZnLzdKRGtNVzhMb1FPQzlJQThwY2dmd3U3QXJzeEswRDVGaU9zd2o2NStiOWpQR0RteW5HSGlndWd6a0l1Q1ZVWnhySFpFQVRiOWdGVzV2bG5hZ3E0SmpIa0hSekN1VjZ5Vy9vcjJVZkNsSFVINmkzVExnN1lpM0VEZ0RtK1VLMXRod04vQmJvQmRsQU5FOHlIeGdmK3llOU0zQUFaUS9BUndGY2phcS94NTJaVVpuc2pTTGROTWZkbVZLY3ppSEE5OEVYamJSbndHUFkwUDA3d1Q5QzhxVEFvUDU0dGlZTHg3elZtOGk3SjVIb2JBL1htS2plQ3BwUkRxdys2VFRnRmRWY0RFYmpVSGdPT0NlbmZjd3BmM2RDcERiS0Q4NGRSWG9NVUIvMEpPejM2Zm5nNW92QVIrdllJd2gxZ1R0WTAzWmR3Q1hpdXFkNmpIczU0WGt1dWZIUHRMWkFZb25QdnRpditjUEFndkwvTXpuZ0g4QmZpM0ZJdW5WQTFQK2NhUkxsQ0NiSzIzd1pDWHdQdUFidk5DS0ZRQXZMYjFPQXRtTXNFRmhReXFSZWhyWUZIWjNEQUdwUkNLM0NMdzJoTDJ3VDV3WEVjOE15ZGxnd2lXWlJYd3FlNkQ0N1B6UUZRWDFBRlBwZzNoOFZoa0R2b1B5V1lRK0xUTGh4cnpGUmt1YnNEdnpHTXA1aUR5RXRjb3RLZU16RndLbmllcWRlTjYwVlFralg5TUhQVG55bmUwWXorc1IxVk1RK1RxVFZ6RHhzRGI0TnV5czVKZzVQdmJwSFFldUY5VlBLbXlieUdlME8zWjJheStJS1h4ZnZXUUcrQnpsM2R0SEszSWt3cDNUL1dGZExGUFN2ZjM0cGdBaTYxRjlQN2FvZUJQVklwa1RQT0lobUY3Zzh5cXlyUnh6YjVEdFI3MmtBYTdHbW8zTFlSSENXOVR6bWM3SVZCZUNBVWoxYmdLS0lQSUVkaTE2SGZGdFlGU3YxUHZ5MUFEZlFsaGYyZU5Td2RZYXVMR0NOeDh0eGNLUzZUNjNiZ1FERVBRTUVQVDBnZXBHVk04QXZrWnpoK1RYRXFINkF1Mnp6UWJnVjJpcFdWYVo3TFI4dXdjbzF3TytISkhsVEZPVXNLNEVzK1BFc3prUTJZcnF1ZGoxcUt2NlVodnFQUlJxRmFvYnFscU4yMTVCR3lrL2xXTVJjTWgwZjFTWGdnSHNUSU1Nby9vRmJDeFJNMGNhMTRwNkY4dzY5ZnhScWFZWHB3aUlqRkpaR3NQQitENWg1K1NlLzdvVkRPeVlsc2RROHkxc3hPdUdxTWNVYytyZGtESWdha2hueXd1SW5PUThLem5YL2FVd2xoUnY4dWRLWFFzR3h1M3ZZa1o2K201QzlkK3dWaFJIK1NpVmxZT2RTNm92TzF1cFZDd1pSVnFtbXVEcVhqQmdSZFBTMVFiaTN3YThCNmEzbHp0ZWdHSnJJZGN6VVM4WkZ5UFNPdFhHUHhhQ0FRaXlBMkFLQUg4Ri9oVnJPblJtNTVsVHhGa2NwNk9WNTZNTkppUTJnZ0VJZXZ0SkR3SG9FNmgrRUxpYytIWTJubXZHaUhrKy94eVFvcEVFQXlDUDlvM2IyN2VnT2w3YWRHUFU0NG9CSVRZQTB6RTVQdE00ZDJNbm1IRkt4b0E4UmE3Q1pnbjJSRDJtT3NjSlpubzhwdEZFYkFVRDF1eXNHQlZQZm9QcXZ3Qy9wTlFhMXZFQ0JvSGgrcmNzUjg2VWhvZFlDd2FnWlhVL1puUU1SRmFYek01WFlDdk5PM1lsaCtxZzAwdDF4RjR3QUMxck5oSDA5Q0ZDdjZEbllEUDJub3g2WEhYR015aGg5SmJiZU5NUWdoa24zWk5ERFhrTkM5OHRMZEh1eEsxQnh0bWd2bTg4ZFpiNGFtZ293UUFFdlRrU2dhZ2lmeWlKNXF1NEpab0M2MFFOcWQ2QnFnL1d6RFNjWUFDU1BRTzBaUHRBZUJiVnM3RnhhQTlIUGE0STJRYXNqWG9RalVCRENtYWNvQ2NIUW41a1pObDEyR3FPdDlCa2JiSkxiSVFxdytZZFFJTUxCcXhvV3BMUEFQb0FxaWRqNjEwMVYyTkdXSWRMajZnSkRTOFlnR0JOYmp3NllETnFMc0dXMWJtTDV2SFozS2Q0K2FyeVRCeEFrd2htbkNDYmc2SVloTnRSL1dmZ1Vtemx6VVptR0xoWDBGcmttVFE5VFNVWUtNMDJxL29BTm9xYVQ0TytHL2dUalR2YlBJNjZzS0ZhMFhTQ0dTZkk1c0JRd0pOZmdaNEFYRWhqZGc2K0d6TzJFVzNVNThIYzByU0NBVWl2N2lkNHNBK1VaekhtZk9BZmdWL1FPSGtqSVhBcmZsSUR0eHlyQ1UwdG1IR0NiQTQ4ejZEY2crcTdnWS9SR0g2TEhsVHZ3VzMyYTRZVFRJbWdwNDhnMjRlSGJrdVBEVjBGK2xiZ0s4VFhIS3ZBai9DazM4V1AxUTRubU4xSVpmdVJ0ZHRCV1MvR25BbDZJbmFaRmtZOXRqSlpoZXBOdHNOV0kyN05vc0VKWmhLQ2JBNzFLQUQvQzNvU3RwM0NTdUpoVGNzRFYrRDVUK0tDTFd1S0U4d1VCRDM5QkQwNVJCazBJdGVpdkJVNEQzaUkrbzR6dVFuVkd6RkZndDY0cmlqckV5ZVlHWkRPNW1oZHRSSFFwOFhvSmNEeHdPZXhqWjdxVFRqM292cFpSTGFYVWYyKzBtcGV1N3hIRkZRTUZSNExhanQ3VjNvK1U3N1BDYVlNZ215T2RHOU9NVHdpUmYwTXFzY0JYd0Nlb0Q2RTh5RHdFVVFlMFJsYnhoVFFJU3Jib3czdS9EN1A3TGpmdGxad0xLVW1VUmNLYUo3SzZuRlBXL2ZBQ2FZQ2d0NCswcXR6Um1HdHFuNEtPQlpiTlAwaG90dmozQVdjb25DZnFOSXkwOW5GM3VQOXdDTVZmT1pxcjFqWVBoNmpsbHc5UU9uM0xPWDdzcmFpdXFiNnk2QlF5Rytuc2dxcGo2Q2FtOG9NN3dSVEJTM1pIQzNabkJIVnRhTG1zNkRIQXVkZ2l3M09sZk56QlBndXlydEJWb29XU1pmUmlBZ0E4YllETjFPZTJJZUFtNDJmTktsdzIrNy85MGZLdjJIL0FHU3I5Um1scy8yUURCUnIyU3hubGxIZ1poVnZjS3FPRjA0d05TQ2R6WkhPOXFzV2VjemtpMTlFT1E0NEdmZ0pOdHhtTnBackJyc0UreENxSDBIWUVQUnN0QlZDeXlESTVrb3RJdmdSZHBhYUtUOUQ5ZmVneU1QUFY2Q1ZZZ0U4NzFsc2I1K1pGbG5zQjY1QVpLaGFqNUhBZU11TDI0R2ZsdkhXdTFDOVFkU1FucUpOb1BOb3pRSmhkeHVLajZpbUVUa0kyeGI3VGNDaDJCYmYxVHlveHJCUDd4K0JYcDlldE0rVDRaWU50RlFSK3BMdjZrRHRuWEFFdHVYZFlkTzg1WGVvZmdEaGNSa3pwTmZ1S3RLd3V3T1VOTUo1d0psTVhVMXlDM0NPbUxHclZYeFRpeENlc0ExWTFnSG92aUJYQVg4L3pWc2VCRTVWdU05VG5YS0dkb0taWllhNjJtaE5MU0EvT3RTS3lBSFlacll2QjdxQkYyTWIzTFl3dVlpSzJLWEZzOENmc1IyNjdwQmljU09lUjdxM05ybHcrYzRNeHZNUTFVNkVUMkpibEMvbCtYdkVsTVp3bzZoZXJ1STk2WnNDeVVscUJJVGRHVkJhRURrSitBaHdNTHRXbFJ3QjdnTXVFOVZmQW9XeWw1SlRNTmJaVHRIelFQVkZpUHdIOE0vQXNwMnVzMktqT0c0Ri9RTGk5MUlzRVBST0xWZ25tRGxtcERNREdCSHg1aUdTQWZZQjlzTittWXV3alZ1TFdPZmpWdUFwclBsNkEwYjc4YVNRZm1Rek1sejd6aFhhRFhudFFOQzBRamNpcjhLSzJnRHJVYjFIckdGalJqZjNhR2M3bnFvVVBHL1AwckVPQmVaajIrbjlCZVhQeGRhV0xmN1EwTFEzYXFYa3V6SUFDWVVERVhrMThCS3NhRFlBOTZCa2dYeGEraENYQk9Gd09Cd09oOFBoY0RnY0RvZkQ0WEE0SEE2SHcrRndPQndPaDhQaGNEZ2NEb2ZENFhBNEhBNkh3K0Z3T0J3T2g4UGhjRGdjRG9mRDRYQTRIQTZIdytGd09Cd09oOFBoY0RnY0RvZkQ0WEE0SEE2SHcrRndPQndPaDhQaGNEUVkveDhRTEV0d2x5OE9OQUFBQUNWMFJWaDBaR0YwWlRwamNtVmhkR1VBTWpBeU1DMHdOUzB5TlZRd016b3hNRG8xTkMwd05Eb3dNQVdqUzZvQUFBQWxkRVZZZEdSaGRHVTZiVzlrYVdaNUFESXdNakF0TURVdE1qVlVNRE02TVRBNk5UUXRNRFE2TURCMC92TVdBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI1ZmRiODFiODUzZjA0OTY3YTg4MWY1ZWMyNmZlNGQxOCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0yNSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiVmluQ1NTIEZJRE8ywq4gQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMjI0MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMjUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTI1In0seyJhYWd1aWQiOiIyZDNiZWMyNi0xNWVlLTRmNWQtODhiMi01MzYyMjQ5MDI3MGIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjJkM2JlYzI2LTE1ZWUtNGY1ZC04OGIyLTUzNjIyNDkwMjcwYiIsImRlc2NyaXB0aW9uIjoiSElEIENyZXNjZW5kbyBLZXkgVjIiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDK3pDQ0FxR2dBd0lCQWdJVUlMd0c1NmVYTEsrbUtXcDQ2SG9YT1krYjZNMHdDZ1lJS29aSXpqMEVBd0l3YXpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBb01Da2hKUkNCSGJHOWlZV3d4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4SXpBaEJnTlZCQU1NR2taSlJFOGdRWFIwWlhOMFlYUnBiMjRnVW05dmRDQkRRU0F5TUI0WERUSXlNVEV3TkRJeE1UQXlOMW9YRFRRM01URXdOREl4TVRBeU4xb3daakVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFvTUNraEpSQ0JIYkc5aVlXd3hJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhIakFjQmdOVkJBTU1GVVpKUkU4Z1FYUjBaWE4wWVhScGIyNGdRMEVnTlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkNIbktQc2pLTmRBczBTQ05nc1dsUzREY29iazdBN2xrelFEa01rYUxuTGU2aWJXOHIrN2szcm44SVVTbys1eE1NTHRJRUovc3ZKTWdCWld4VW9EeHNXamdnRW1NSUlCSWpBT0JnTlZIUThCQWY4RUJBTUNBWVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZkJnTlZIU01FR0RBV2dCUzc2RHBsOTN2QjJoNUZETHZ5TU12VUJ5ajNpekFkQmdOVkhRNEVGZ1FVRERPRERaZFRpUFdyV25qRGlNd3NaZ3lvZXp3d1JBWURWUjBmQkQwd096QTVvRGVnTllZemFIUjBjRG92TDJOeWJDNW9lV1J5WVc1MGFXUXVZMjl0TDBaSlJFOUJkSFJsYzNSaGRHbHZibEp2YjNSRFFUSXVZM0pzTUhZR0NDc0dBUVVGQndFQkJHb3dhREEvQmdnckJnRUZCUWN3QW9ZemFIUjBjRG92TDJOeWJDNW9lV1J5WVc1MGFXUXVZMjl0TDBaSlJFOUJkSFJsYzNSaGRHbHZibEp2YjNSRFFUSXVjRGRqTUNVR0NDc0dBUVVGQnpBQmhobG9kSFJ3T2k4dmIyTnpjQzVvZVdSeVlXNTBhV1F1WTI5dE1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lCMjRMZTJ6dDdaL1cvUDl6RTlOZnF6Z1BaakJJcEtrMXF1cWdiWlk2Ni9GQWlFQXRzUlk1YnhhTjlNREtHYWVmYVRTNnpnTVZieFVsRXBEbjQ5QzZWU1dnbUU9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQVZNQUFBQ3NDQVlBQUFERytFOE1BQUFBSUdOSVVrMEFBSG9sQUFDQWd3QUErZjhBQUlEcEFBQjFNQUFBNm1BQUFEcVlBQUFYYjVKZnhVWUFBQUFKY0VoWmN3QUFEMkFBQUE5Z0FYcDRSWTBBQUF5Z1NVUkJWSGhlN1oxL2JKVGxIY0J2amhqTmNDNE8rZFhlWFZ0VVRNemlQN29ZWFpZNTFJa0tkMWZObkZIajVvaEJtQTdqMk1Sc1pvbG14aGhOSm9ydDI0S2dzaUZzaW03VEFkTVlSRlFFRlRjVnh3L3J3QUVGUkNoUSt1dWVQYy8xcVFQM1ROcyszM3ZldSt2bmszelM0MmdmbnZlOXQ1OCs3NzNYSXdFQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBVUVwa0c2L1hQcG5JUlI4Z0loNXQ0MXI5Y1lhdEJmd1A5UTNuNngyMFRadFAxRGNwUk1UUE5kZVUxNHV1VnQyTXEyMUZCa3h0TWptckxwVnEwUjgzMTFaWDMycnZMbU1LUDIzMGpxbVAzRHNORWZIenpFVzdFeGZPR1dtTDhvV2trOGtmMXFYU1BYWFZxYVhKVWFQT3FLbXFPck11bWZwcmJUTFZuVXFsTHJlZlZrWk1tUDExL1pPbHc3bHpFQkVIb2ptcnpVWlRiVjMrTDNWangwNHdJUjA5ZXZUSjQxS3BLZG9iakNOSGpodzFkdXpZNUxoMGpkS3IxTFB0cDVjQkpxU3NSaEZSMHQ2Z3pyU1ZjWEdNRHFtcVNTWXordll3RTg2YXF0UzF0ZFhwNjgzdHVqRmpValZqazVQMUtyVzk5OVBMZ1Z6VTVkd1ppSWcrbXFCZU9xZk9sdVlvMHVuMGNUcW1YZmFQdzh3SzFkNU82RlA4dDJyVDZWdjB6Uytic1BiZVcrcmtvbytjT3dFUlVjSmNkTURXNWlpcXE2dVBINWVxNlZ0MUZsYW1PcUk3NjFJMTIwOUoxL1JGOWt2bEVkUDZobTg3Tng0UlVkSnN3ejIyT3A5aVlxcFhvNTMyajJabG1qL3BwSk8rcWo5MnA4ZU1PZDNlZjB4NXhEVFh0TSs1NFlpSWt1YWlEbHVkSStrOWhVOG5qdE8zQ3pFMWQ0NFlNV0tNdm4zUTNCNCtldmpKK25iZktyV0U0WFdraUJqS3k1dlBzdVg1bExwVWFtWnRNcjNmM0s2dFRyNVR1Rk5UbDB3K1dwTkszYXovcnFPMk9qM04zbDJpVEk2bU9qY1lFYkVZNXBxZXRmVTVpcnJxMURPMXlkU0JjVldwRyt4ZGlicXE1QXl6T3RYM0w3UjNsVEQxMFhMbkJpTWlGc05jVStIVTNVVnlWUElNSGRXVnA5WFdxVk5yYXZQNjl2S3FFVlduMnI4dWNlcWovYzROUmtRc2hybW9qRjR2T2hDSUtTS0cxSDBScWdJZ3BvZ1lVbUtLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUVM5N1dDVXVlRUFsTHB3ZFZ2TnY1aUwzbkFicjl4NTAvMXZGOWlLdGF6NERNYTdId0R6K3J2bjB4NngrL09LWWR6RTAyM0dSUG43TU1YU3AzaWVURzkzYlhHa1NVemx2bnZ1eWlvdmpycHpubk5PZzFBZi91czI3N01oaDJmbkpvZDV2UU5lOCtxUCtKbzZMYWRFcTk1ejY0ZGV1WFdCSHFRdzZ1M3RVVzN1bjJyeGpuMXE5WWFkYXNucXp1cW41WlhYeU5RdFU0dUtIVkNKVGdZRWxwbkthYjZhNHFKU1lmclRuUU5uRzlJYUhYM0xQcVIrZXFDTXpWTml6LzdCYThkWldkZVY5ejZ2RUJMMktyWlN3RWxNNWlhay94SFJvMGRuVm81NWQ5NkVhZitNaXY2ZEpTa0ZpS2ljeDlZZVlEbDNlYnRtanpwdTExTy94ajFOaUtpY3g5WWVZd2h0YmRxbFRwdXFWcXJrbzU5aFhKU3N4bFpPWStrTk13elByc1RYcXpzVnZxTHVXdktFeWR5OVR1WHVXcTE4dWZMMXczNzFMMTZzVjY3Y1ZMaWFGcENlZlY0KysrRStWdUdDMmMzK1ZwTVJVVG1McUR6RU5UMkxDYi9VcXNGRWxNZzMvblpPNUtGUzRUenRKUHg2WHpsRlZVeGFxS1hOV3FvL2JEdHV2TEQ2NzI5clZOMzY2eElUcXFQMVZraEpUT1ltcFA4UTBQSVhYaGpybTVGUkg3WmpKRGVxTzM2KzFYMTE4dW50NjFDMlByTmJINVJHeEwwV0pxWnpFMUI5aUdwNEJ4YlJQSGJaSmR5K3pJNFJoL2d2dkYxYkl6dm1VZ3NSVVRtTHFEekVOejZCaWFzdzBxaC9yMC82UVBQbnFCMzdIUnpFbHBuSVNVMytJYVhnR0hWTmpObEovLzNDUEhTa01UNy9XVXBwQkphWnlFbE4vaUdsNHZHS3FIZitUeFhha2NQenhGYjFDTGJYblVJbXBuTVRVSDJJYUh0K1ltcWk5dDIydkhTMGNQMXZ3cW5zK2NVbE01U1NtL2hEVDhIakhOQmVwODI1LzJvNFdqbncrcjhaUFgreWVVeHdTVXptSnFUL0VORHplTWRWKzVhcEg3R2hoMlhld1EyVCtJaEpUT1ltcFA4UTBQQ0l4bW1STzlUK3hJNGJsbVRVdGhkV3hjMTRoSmFaeUVsTi9pR2w0UkdLYWpkUXQ4MTZ4STRabitGV0N4LzlnSmFaeUVsTi9pR2w0cEU2VHo1eXh4STRZbnZjLzJ0djc2NitPZVFXVG1NcEpUUDBocHVHUml1bm82eCszSThiRGlPc2VkYzRybU1SVVRtTHFEekVOajFSTWgxM1JiRWVNQjNQTXh2cmNLVEdWazVqNlEwekRJeFZUY3hHcXE3dmJqaHFlcnU0ZXVXMFpqTVJVVG1McUR6RU5qMWlBOUhHemRsT3JIVFVlYnAwZjR3djVpYW1jeE5RZllob2VzWmhtR3RYQ2xSdnRxUEd3YmJjK2Z1SjZoMzVpS2ljeDlZZVloa2NzcGpwaXR6MjJ4bzRhRCswZFhTb3hNYWEzNlNPbWNoSlRmNGhwZUNSakd1ZHJUZnVJN2FvK01aVXp6cGgrNTFkL1V1Zk9lbHJFYi83OEtiVWhoamV1TUJEVDhJakZOS2JmMGY4c3R6Mit4ajIvWWt0TTVZd3pwcFVDTVEyUFdFeTE1OXkyMUk0YUg2dmUzZTZjVzlFbHBuSVNVMytJYVhncUxhWmI0N29JUlV6bEpLYitFTlB3VkZwTXQrODkyUHUvcWpybVYxU0pxWnpFMUI5aUdwNUtpK211ZmUwcWxuZmhKNlp5RWxOL2lHbDRLaTJtaGZjNHZjempHQnFzeEZST1l1b1BNUTFQeFozbWY4eHB2aXpFdEN3aHB1R3B0Smp1Mkh1SW1JcENUTXNTWWhxZVNvdnBCenYzbTdBNTUxZFVpYW1jY2NiVXZNSEU2MEt1MmJoVEhXanZzaU9IaFppR3A5Sml1bVQxWnVmY2lpNHhsVFBPbUI1cmZoS2JKOTBsdlBnaDlmckdlTjc5aDVpR1J5eW1KZkliVVBYM0xIZlByOWdTVXpuampDbS9tMjhscGdOR0xLWWw4cnY1c1p6aUc0bXBuTVRVSDJJYUhzbVlUby81dXNIK1E1MjlaMWV1K1JWYllpb25NZldIbUlaSExLYVpSclhvcFUxMjFIaFkzN0tibGFrNHhIVHdFdE5CUVV3YjFZcjEyK3lvOFhEMnpLWHV1WVdRbU1wSlRQMGhwdUVSaStua0J0WDZ5U0U3YW5qYTJ2VXAvaVV4dlRHMGtaaktTVXo5SWFiaGtYek9ORTZlV0xYSlBhOVFFbE01aWFrL3hEUThVakU5OFpyNWRzVHc5UFRrNDNuYnZTTWxwbklTVTMrSWFYaWtZbnJxOUNmc2lPSDV5N3AvbVpnNTV4Vk1ZaW9uTWZXSG1JWkhKS1k2WkpmYytad2RNU3lITzd2MU1SUGpjNlY5RWxNNWlhay94RFE4SWpITk5Lb2xxN2ZZRWNNeXJYR1ZlMDZoSmFaeUVsTi9pR2w0UkdJYTA4V25UZHYzeGZjaS9jOUtUT1VrcHY0UTAvQkl4SFQ4dEVWMnRIQzBkK2pUZTMyc3V1WVRpOFJVVG1McUR6RU5qM2RNOVNuKzNPYzMyTkhDWUs3ZW56WHpTZmQ4NHBLWXlrbE0vU0dtNGZHTjZmQWZ6TE1qaFdQR3ZKZWRjNGxWWWlvbk1mV0htSWJISzZhVEc5VGN2NFZkbGQ2K2NJMEpsM3MrY1VwTTVTU20vaERUOEF3NnB0bEluWC9Ibiswb1liaXBlVlU4L3lWSmZ5U21jaEpUZjRocGVBWVYwMHlET3ZmMlord0l4YWU3SjY5K05QdkYwbHlSOWtsTTVTU20vaERUOFBRN3BpWmsrclRlSEd2M1ByWGVmblh4T2RqZXFjWk5YZVNlVXlsSlRPVWtwdjRRMC9Ba3ZuVi83N3N0ZmRhSkQ2bGhWelNyRTYrZXIwNi9hYkhLM0wxYy9TSHdDL09YdmJtMU1BL1hQaXM1aWFtY3hOUWZZZ3FHZzRjNzFWWDNQMTlZQ2J2MlYwbEtUT1VrcHY0UTA2Rk5SMWUzZW5qWnV5cngzUWVjKzZta0phWnlFbE4vaU9uUXBMMnpTeld0Mk5CN1NsL0tGNWsrVDJJcUp6SDFoNWdPSGZMNXZIcTdaWSthTW1lbFNseWdWNkxsR3RFK2lhbWN4TlFmWWxyWmZOeDJXSzE2YjRlNjBielRVN1pSSlNaNVBOYWxKakdWYzlKdmxxbmxiMjR0WElFTTZjcDMvcTJPL2Y1YzU1d0daYVpSUGZqc1A1ei9Wckg5M2NxTitodk00NkxEeERucXBYZTNPOGN1cGl2ZTJxWXV1ZXM1OTV6NjRRbFh6MWU3OTdlcmx0YTJpdkROTGJ2VjJrMnRoWDN6NnlmV3FvbDNQcWRPTUQvd0w5YW44ZnFIdFdzZmxMM0VGTEVFTktlNDV1VklabFZlN3BydE1GZmh5K2xLdklURUZCRlJRR0tLaUNnZ01VVkVGSkNZSWlJS1NFd1JFUVVrcG9pSUFoSlRSRVFCaVNraW9vREVGQkZSUUdLS2lDZ2dNVVZFRkpDWUlpSUtTRXdSRVFVa3BvaUlBaEpUUkVRQkt6YW11YWpWdWNHSWlNWHhvSzFQaFpGdGFISnNMQ0ppY2N4RnUyeDlLb3dybXNjN054Z1JzUmhtb2wvWStsUWc1amtNMTBZaklrcWFpL0syT2hWS3J1a0Y1NFlqSWtxYWkzYlk2bFF3dWFqYnVmR0lpQkxtdE9mY2Q3d3RUZ1dUaTZZN2R3QWlvb1M1YUptdHpSQ2dQbnJOdVJNUUVYM01ScTIyTWtPSWJPTkc1ODVBUkJ5TXVhWUtmU2xVZjhoRmkvUU95T3VWcW52bklDSitrZWJLZlgzVFdsdVZJVXcyT2sydlVsdUpLaUlPMkZ5ME41RnR1czdXQkFxWXFOWkg2L1RIZlRxc25ZbjZacjJ6RUJHUDBLeENzMUdiYnNTV1JLWmhncTBIQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRUJwa1VqOEI0QW9tK01iVCszSkFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiMmQzYmVjMjYxNWVlNGY1ZDg4YjI1MzYyMjQ5MDI3MGIiLCJvcHRpb25zIjp7InJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWV9LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo1LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjgwfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDEtMjAiLCJ1cmwiOiJodHRwczovL3d3dy5oaWRnbG9iYWwuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSElEIENyZXNjZW5kbyBLZXkgVjIiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMDEyMDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAxLTIwIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0wMS0yNCJ9LHsiYWFndWlkIjoiY2I2OTQ4MWUtOGZmNy00MDM5LTkzZWMtMGEyNzI5YTE1NGE4IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJjYjY5NDgxZS04ZmY3LTQwMzktOTNlYy0wYTI3MjlhMTU0YTgiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NTAxMDAsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciLCJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJjYjY5NDgxZThmZjc0MDM5OTNlYzBhMjcyOWExNTRhOCIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiWXViaUtleSA1QSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTgxMDMxMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA1LTEyIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiOTZmMGNjYzEzNWRmZjlkY2Q2YjNmZmUxODUyZmUwNmU4ZjVjYWJlYiJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI5NmYwY2NjMTM1ZGZmOWRjZDZiM2ZmZTE4NTJmZTA2ZThmNWNhYmViIl0sImRlc2NyaXB0aW9uIjoiSW1wcm92ZUlEIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NDUsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6Mn0seyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NiwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNiVENDQWhPZ0F3SUJBZ0lKQUtNOUZxazArWDkvTUFvR0NDcUdTTTQ5QkFNQ01JR1JNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVZtbHlaMmx1YVdFeEVEQU9CZ05WQkFjTUIwRnphR0oxY200eEdEQVdCZ05WQkFvTUQwbHRjSEp2ZG1WSlJDd2dTVzVqTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFZk1CMEdBMVVFQXd3V1NXMXdjbTkyWlVsRUlFWkpSRThnVW05dmRDQkRRVEFnRncweU1qRXlNREV3T1RJNU5UaGFHQTh5TURVeU1URXlNekE1TWprMU9Gb3dnWkV4Q3pBSkJnTlZCQVlUQWxWVE1SRXdEd1lEVlFRSURBaFdhWEpuYVc1cFlURVFNQTRHQTFVRUJ3d0hRWE5vWW5WeWJqRVlNQllHQTFVRUNnd1BTVzF3Y205MlpVbEVMQ0JKYm1NdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SOHdIUVlEVlFRRERCWkpiWEJ5YjNabFNVUWdSa2xFVHlCU2IyOTBJRU5CTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZlgwc0Z5a2l2Q0c5NVBpNWpXV2cwTXNhMHhvWHFHNVIrNlhvaGtQU09XcW1jSlcrQ2tDNERXT0FBRHpERFladWh4MHMxQi9VazJCb1ZpOW1SSXFhZ3FOUU1FNHdIUVlEVlIwT0JCWUVGTUpwS2gzWGNmUk5pWFZXZjZQbnVkWmkyTXMzTUI4R0ExVWRJd1FZTUJhQUZNSnBLaDNYY2ZSTmlYVldmNlBudWRaaTJNczNNQXdHQTFVZEV3UUZNQU1CQWY4d0NnWUlLb1pJemowRUF3SURTQUF3UlFJZ005MFlWMFRUMzlWN0JEeG5mRktKYmpVL0h2RW5Kc2tjRmdXVjkvdEtyZmtDSVFEZkNDVGZDendZUldKcFhydU44d1JmNERZMUVhNjRnampJOWo1bGxoSVB0dz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQUlBQUFEOEdPMmpBQUFBQ1hCSVdYTUFBQzRqQUFBdUl3RjRwVDkyQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBdGhKUkVGVWVOcnNsdDlMazFFWXg3L3ZOdGUwdlhPazd5UzdxeVdCWXZuaklrdEdVMHZEQ3drdFY0S1hwdjN3Qi80QkJpSWEvUUMxd2prVlV4TnNVdXV1emQxazZpQkxDeElGemNEWE9UWndZOHIyc3IxcnA0dVhadW9nZ3J5SmZTOGVlTDZjNTN3NDUrRTVISW9RZ29PVUNBZXNHQ0FHaUFFQXlYNkxaZG4xOVhXR1lkUnE5VDhna04xcWEyMFZEbFZaY1pVUVlwdVpLUzB0SFRjYTl5d3o2SHVycTZzL3pzNlNQMmtYd0dJMkF6aktxSFE2M2Z0M2s0U1Fwb1lHQU1XRlJYdktMbW9MQUF3T0RQd2RvTGRIRDJCa2FPaDM4NDNKNUhLNTlwVFYxZHdFOEdwOGZQK09TNHRMNXJmbUg2R1FrTzcwb0x1emMyand1U29wMmRCck9DeW5rNUtPOVBYM1oyWmtNQ2twcXl2ZkdJWUJjTCs5dzJxZEtDb3FDZ1FDQUhpZUYyb2ZQM3hrTXIxVzBJcmF1bHB0UVlIUDd3TkY3ZTJCTmw4RElPMzRDUUFOZCt1N3U3b0FTRUFCcUt1cEpZUlU2YTREb0dYeHFhb1VwWndXQTlhSkNVSkk0UVV0Z0ZQcWt3blNRd0Q2OVByb1Z4UU1CdHZiMmlpS2V0RFJ3Zk44S0JUaU9PN1prNmNBK25vTkxNc0N5TW84emZuOUhNZmxuTWtDc0xTNE9EMDFEVUIzOVJvaHhPbDB5aE1TNGlpUjNXNlBiTHN6QjNGeGNiUkNRUWhSSkNaS0pCS3hXQ3lUeWVSeUdvQlVLdjB5L3htQVRsY3BpNCtYeVdRYWpRYUF6K2VibXB3RVVGNVJEa0NsVWhWcUMzZ1NucCtiaXo0SG5OOFB3Ty8zUjV4QWdNdk56azVta2tXVUNNRHE2bmZCZHpnMkJEQ3RVQUJ3T2wyL2ZJZEFpZzRJQm9PUktJam5lUVZOYjNtM2lpK1hpRUhwK3d6cEdlbHV0L3VsMFFnZ0VBaVVYU203ZGVmMnZaYVd0TFMwaFlXdkgrWSs1Wi9OeThuTmpmNVVTQ1NTU0l3NDRYRFk0ZGhRS3BYRHc4TmlpcXB2YkJ3ZGVWRjFvd29BdTdhV21uck0wS1BmM3Q2K1ZGTGMxTng4UHUvYzZOaVlTQ1NLUHNrZXQyZDVlZG5qOFVRY3I5ZHJYN2U3M1p0Q3lySnJWcXMxSEE0VFFwWlhWcnhlcitDN045MFdpOFZtcyswZkN5cjJxNGdCWW9EL0FQQnpBSTZWTnFHUVBVcW5BQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDEtMTciLCJ1cmwiOiJodHRwczovL3d3dy5pbXByb3ZlaWQuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSW1wcm92ZUlEIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjAwMDIwMjMwMTE3MDAyIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDEtMTcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTA1LTE4In0seyJhYWd1aWQiOiIwMDc2NjMxYi1kNGEwLTQyN2YtNTc3My0wZWM3MWM5ZTAyNzkiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjAwNzY2MzFiLWQ0YTAtNDI3Zi01NzczLTBlYzcxYzllMDI3OSIsImRlc2NyaXB0aW9uIjoiSFlQUiBGSURPMiBBdXRoZW50aWNhdG9yIiwiYWx0ZXJuYXRpdmVEZXNjcmlwdGlvbnMiOnsiZW4tVVMiOiJIWVBSIEZJRE8yIEF1dGhlbnRpY2F0b3IifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmFjZXByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InZvaWNlcHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJleWVwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGF0dGVybl9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiaGFuZHByaW50X2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJsb2NhdGlvbl9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsic29mdHdhcmUiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5ldHdvcmsiLCJ3aWZpX2RpcmVjdCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ0F6Q0NBYWdDQ1FDRzNVcjR6cVk5M2pBS0JnZ3Foa2pPUFFRREFqQ0JoekVMTUFrR0ExVUVCaE1DVlZNeEN6QUpCZ05WQkFnTUFrNVpNUkV3RHdZRFZRUUhEQWhPWlhjZ1dXOXlhekVTTUJBR0ExVUVDZ3dKU0ZsUVVpQkRiM0p3TVJBd0RnWURWUVFMREFkU2IyOTBJRU5CTVJFd0R3WURWUVFEREFob2VYQnlMbU52YlRFZk1CMEdDU3FHU0liM0RRRUpBUllRYzNWd2NHOXlkRUJvZVhCeUxtTnZiVEFnRncweU1qQTVNVE13TWpBNE1qWmFHQTh5TURjeU1EZ3pNVEF5TURneU5sb3dnWWN4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSk9XVEVSTUE4R0ExVUVCd3dJVG1WM0lGbHZjbXN4RWpBUUJnTlZCQW9NQ1VoWlVGSWdRMjl5Y0RFUU1BNEdBMVVFQ3d3SFVtOXZkQ0JEUVRFUk1BOEdBMVVFQXd3SWFIbHdjaTVqYjIweEh6QWRCZ2txaGtpRzl3MEJDUUVXRUhOMWNIQnZjblJBYUhsd2NpNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFzRVFPZy9CNTNyS0lGSm40blVmUE5WUHF6RFpWTGhXaWZLbHFTWVhWZzFaNjg4bU9iQTZDbmwrUEpVdzI3MjdFbUlFMllIQXdCQmZQd1B5KzkyTkVTTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDV1RseWxTeUV5aG9UQnNnN1VWWjNhblozeTlabUJPdGRkaDJmblM3MGFiUUloQUpGUXN6Z1E5NEZMVlBQdWtsNy9qbjdndGJtc28zRXFNZFdPVmVFbzlLMFIiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFDTmdBQUFqWUNBWUFBQUFBRElMUEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFCQU5wVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTVRRMUlEYzVMakUyTXpRNU9Td2dNakF4T0M4d09DOHhNeTB4TmpvME1Eb3lNaUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGJHNXpPbVJqUFNKb2RIUndPaTh2Y0hWeWJDNXZjbWN2WkdNdlpXeGxiV1Z1ZEhNdk1TNHhMeUlnZUcxd1RVMDZUM0pwWjJsdVlXeEViMk4xYldWdWRFbEVQU0oxZFdsa09qVkVNakE0T1RJME9UTkNSa1JDTVRFNU1UUkJPRFU1TUVRek1UVXdPRU00SWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2tRNFJUaEVSamN3TnpNMU56RXhSVGs1TVRVMVJVVTJORU0zTUVFd05ERXhJaUI0YlhCTlRUcEpibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPa1E0UlRoRVJqWkdOek0xTnpFeFJUazVNVFUxUlVVMk5FTTNNRUV3TkRFeElpQjRiWEE2UTNKbFlYUnZjbFJ2YjJ3OUlrRmtiMkpsSUZCb2IzUnZjMmh2Y0NCRFF5QXlNREU1SUNoTllXTnBiblJ2YzJncElqNGdQSGh0Y0UxTk9rUmxjbWwyWldSR2NtOXRJSE4wVW1WbU9tbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNVEJoTWpKa01HVXRNalV6TnkwMFpqVTFMV0V6TlRjdFpqRTNZemswWTJabE5Ua3hJaUJ6ZEZKbFpqcGtiMk4xYldWdWRFbEVQU0poWkc5aVpUcGtiMk5wWkRwd2FHOTBiM05vYjNBNk9UZzVZVEF6WTJZdE5qbGhaUzB4WkRRd0xXSTBPV1l0T1dReE1URmxNR1UyWWpNMUlpOCtJRHhrWXpwMGFYUnNaVDRnUEhKa1pqcEJiSFErSUR4eVpHWTZiR2tnZUcxc09teGhibWM5SW5ndFpHVm1ZWFZzZENJK1VISnBiblE4TDNKa1pqcHNhVDRnUEM5eVpHWTZRV3gwUGlBOEwyUmpPblJwZEd4bFBpQThMM0prWmpwRVpYTmpjbWx3ZEdsdmJqNGdQQzl5WkdZNlVrUkdQaUE4TDNnNmVHMXdiV1YwWVQ0Z1BEOTRjR0ZqYTJWMElHVnVaRDBpY2lJL1BsMkR5eDBBQUp5ZFNVUkJWSGphN04zL2JWeFZHb0RoRTBRQktXRWFRRW9KTGlFZHJEdllOSUNTaUFJUUZaQlVzTmtLR0NyQWlBSVlLaUJiZ1hjT014UC9VUElTa25qR25ua2U2VWoyaEQvZ3MzV1VlKy9MdVk4dUx5OEhBQUFBQUFBQUFBRHdmbDhaQVFBQUFBQUFBQUFBZkpqQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFJTEFCZ0FBQUFBQUFBQUFnc0FHQUFBQUFBQUFBQUNDd0FZQUFBQUFBQUFBQUlMQUJnQUFBQUFBQUFBQWdzQUdBQUFBQUFBQUFBQ0N3QVlBQUFBQUFBQUFBSUxBQmdBQUFBQUFBQUFBZ3NBR0FBQUFBQUFBQUFDQ3dBWUFBQUFBQUFBQUFNTFhSZ0RzZlBQazIxUDh6MzZ5WGhkKytnQUFBQ2R0WGhzK05nYjJhR2tFOExjVzJ3VjNaYlZkQUgvcnQ0dnZEQUVRMkFBbmFkNDQvZGQ2UGQxZXBEOHlFZ0FBZ0pNMnJ3K2ZHd01IOW5iYy9KK0FWdXYxeDdXdlY5dXZMN2IvTEJ5N3MvWDYwUmc0Z052NzdQeitmKy81czZWUkFjQnBlWFI1ZVdrS3dGK08vQVNiMjFITmpiM1FUeDhBQU9Da3pXdkdYNHlCQjJhMVhmTkI3Ni9qS3REWmZRN0g0UGZoRkJ2dXYxMTBNL2ZlUDY1OUw0aUVJK0lFRzJCeWdnMXd6Q3FxQVFBQWdKMWRsT0Rha1lka2NlMTM5dWtIZnEvbmc5MmZ4MVYwc3pRMkhwaVh3eWsyM0g5UC91YlBsK05tZkxNYU4wOHNBd0FlQ0lFTmNJd1hNNklhQUFBQS9xazM2L1hNR0RnaXV3ZStaN2MrWDQzTmc5MTU2czF5T1BHRysrM1YyTHpDYjJFVVBHQm5IL2g4dHdmL3V0MlhsMFlGQVBlYndBWTRCcUlhQUFBQVB0Yzg1VU5nd3lsWWJOZThqL0o4KzlrODZXWTVycUlicnpYaFBubDk3WGNWanNuWmV6NjdHRmNScE9nR0FPNlpSNWVYbDZZQS9PV2JKOTgrcEgvZEx4blZQUExUQndBQVlPM1A5WHBzRFBDWDNVUGVHWjh0aDFOdU9KeTVMLzl1ZithRUxiZDc4UzY0RVVEQ0FmeDI4WjBoQUU2d0FSNFVKOVVBQUFCd2w1YmJhMDVnY3g5bXJ2UHQ5NnR4OVpCM09RUTM3TStNQ1g0WVRySGhkSjJObTZmZFhOemFqd1UzQUxBblRyQUIzcm1uSjlqc0k2cHhnZzBBQUFEVCtYcjlhQXp3VVZicjlXWjR3TXQrT01VR1BteTUzWXZubm54aEhIQTNuR0FEVEFJYjRKMTdGTmdzMXV2ZlkzOG4xUWhzQUFBQW1PYUQyeitOQVQ3SmNyMytPellQZUZmR3dSMllBZVM1TVVCNk82N2l4emREL0FoZmpNQUdtQVEyd0RzSERtd1dZeFBVek5OcW51eDdML1RUQndBQVlPdVhBMXlYd3JGWmpjMkQzZGZEYVFwOE9ZdXhPY1VHK0hnWDI3MVkvQWlmU1dBRFRGOFpBWERnaStKblkzUHpjbDRjZnovY3hBUUFBT0N3WGhzQmZMYkZ1SG5QWjU0ODh0UlkrRXlyOVhwbERQQ1B6UHZ0MzIvMzRya252eGp1d1FQQUp4UFlBUHUyR0tJYUFBQUE3cStsRWNBWHRSaWIxL3I4WjJ4ZXdUWmptek5qNFJPOU5BTDRaUE0rL1BOeGRXLysyWGFQQmdBK2tzQUcySWZGRU5VQUFBRHdNTXhYS2F5TUFlN0U0N0dKYlg0YTdoSHhhZWIrL01ZWTRMTXR4czJUYlo1dDkyZ0FJQWhzZ0x2OEM3cW9CZ0FBZ0lmSXcxdTRlNHR4ZGUvSXcxMytpUitNQUw2bzNXdWs1aWxqODdTeGN5TUJnUGNUMkFCZjBtS0lhZ0FBQUhqNGZqWUMyS3ZiRDNlZkdnbGhPYnpPRCs3SzNIOS8zTzdIN3U4RHdDMENHK0J6TFlhb0JnQUFnT015VDdCNWF3eHdFUFBoN294czVuMm1GMk56N3dsdWUya0VjS2ZtaVdMWFR4azdIMDRaQXdDQkRmQkpGa05VQXdBQXdISHptaWc0ck1WNlBSK2JlMC96TklVekkrR2E1WHBkR0FQc3haUHRQcng3RnJBd0VnQk9sY0FHK0Zqekw4MmlHZ0FBZ1AxZmkzRVlYaE1GOThmNWV2MDBOdmVrNXRkT1VXRDZ3UWhncjNhbjJzeTllSjQwZG1Za0FKd2FnUTFRRmtOVUF3QUFjQ2puMjJzeEQ1SVB3d2syY1A4c3h0VXBDaStHQ1BIVXZWcXZsVEhBUWN6WCtWMFBId0hnSkFoc2dOc1dRMVFEQUFCd2FPZGo4eEI1ZW1vY0IvRjJiRjVCQXR3L016eTgvdnFvaFpHY3JKZEdBQWUxMk83RGY0NU4rQ2dNQitDb0NXeUE2M2JITzRwcTRQL3MzZTkxMjBpNjRPRjM3NW52bzQxZ2NDTm9kUVJtUjlCMkJFWkhZRHNDU3hIWWpzRG9DS3lPb05rUnRDYUM0V1NnREhaWkptbjlseWdTQlJSUXozTU9qdS9PZnVKTE5RUzRmcTRDQUlEeHRIRWQxeVN2akdRMGZ4Z0JUT0tlNmJpU2VuVmhGeHNvd2Mzd01hMHZORVlDd0J3SmJJQzdEOEVBQUFDTXA0M2JjVTFpQjV2eE9DWUtwbU4zWEVtNkZzWlJsZCtOQUlxUjFoaDIvNURYRG1NQXpJN0FCZ0FBQUtBTWJkeVBhNUswVUxFd25sR3N3czRJTURYcGZpbTBxY3ZuMkJ6ckI1VDNiQ3UwQVdCV0JEWUFBQUFBNDJ2ajRiaG01MWNqR28xZGJHQ2FGaUcwcVVXS2E3NFlBeFQ5bkN1MEFXQVdCRFlBQUFBQTQycmo2YmdtY1V6VWVQNHdBcGkwUlFodGFtQVhHNWpHTTYvUUJvQkpFOWdBQUFBQWpLZU41K09hcEFrTEVXTlpoa1ZibUlORmJDS2JiKzZuczVUdTAzWWNnK2s4Ly82OXZzNWljeFFxQUV5R3dBWUFBQUJnSEczc0Y5ZnMyTVZtUEJadFlUN1N2WFMzZzRLRjNYazVOd0tZakhULy9iaTlINThaQndCVEliQUJBQUFBR0Y0Ykw0dHJrcmZHTmhySFJNRTg3OE83aFYyaHpUeXMxbGRuRERBcE4wT2IxamdBS0ozQUJnQUFBR0JZYmJ3OHJrbE93eUx3V0paR0FMTzBXOWo5T3l6c3pvVmRiR0NhbXUzemNUcktiMkVjQUpSS1lBTUFBQUF3bkRZT2kydDJIQk0xanF0d1RCVE1XUlBYQzd1bnhqRnBLL2RybUxURjlsN3NHRDhBaWlTd0FRQUFBQmhHRzhmRk5jbXZ4amlhdjR3QVptOFJtOTFzTE94TzJ4Y2pnRms4TjZkam85NGJCUUFsRWRnQUFBQUE1TmZHOFhGTnNqREswZGdSQWVxNlovOG5IQnMxVmN0d3RCL01RUW9kUDhVbWZQUU1ERUFSQkRZQUFBQUFlYlhSVDF5VHBJVUd4MFNOWTdXK0xvMEJxbkVTam8yYXNuTWpnTms0RGNkR0FWQUlnUTBBQUFCQVBtMzBGOWZzdkRMVzBTeU5BS3F6aU0zdUNXZGhZWGRxOTJ0UkpNenZ1VHJ0TGlZMkIyQTBBaHNBQUFDQVBOcm9QNjVKTENxTTUzY2pnR3A5RE1lVVRNMFhJNERaU2FIanQ5anNhTk1ZQndCREU5Z0FBQUFBOUsrTlBIRk4wb1RqU3NhU2RrTzRNZ2FvVnJyL3BrWGRUMkUzbXlub1luTzhIekEvaTloRWorK05Bb0FoQ1d3QUFBQUErdFZHdnJobVoySE1vN2t3QXFoZVd0QzFtODAwbkJzQnpGWUtIVlB3YURjYkFBWWpzQUVBQUFEb1R4djU0NXJrclZHUDVnOGpBTUp1TmxQUmhWMXNZTzRXWVRjYkFBWWlzQUVBQUFEb1J4dkR4RFZKT2lMS2d1NDRsa1lBM0xEYnpjYlJmZVg2M1FoZzltN3VadU1aR1lCc0JEWUFBQUFBeDJ0anVMaG01N1d4aitJcUhCTUYzTmJFSnJJNU00b2lmZDdldTRINVc2eXYvM2hPQmlBWGdRMEFBQURBY2RvWVBxNUpmalg2MFRnbUNuakl4OWlFTm8xUkZDWEZOVitNQWFxUmRyRDVGbzd3QXlBRGdRMEFBQURBNGRvWUo2NUovTXZjOFN5TkFIaEVPaXJxNyszdkI4cGhGeHVvVHpyQzc4OXdoQjhBUFJMWUFBQUFBQnltamZIaW1oMlJ6VGhXNit2U0dJQkhuR3gvUDN3TnV5ZVV3dkYrVUtkZDlQamVLQURvZzhBR0FBQUE0T1hhR0QrdVNSd1ROUjdIUkFINy9LNndlMEk1em8wQXFwV09pMHJIUm9rZUFUaUt3QVlBQUFEZ1pkb29JNjVKRnI2TzBkZ0pBZGhIaW12K0RFZEdsV0MxdmpwamdHcWxuUi8vRHRFakFFY1EyQUFBQUFEc3I0MXk0cHFrQ1lzRVkwbEhSSzJNQWRqRHpTT2pHSmRkYktCdTZkbFo5QWpBd1FRMkFBQUFBUHRwbzh6RjBkZSttdEVzalFCNDRlK1J0SHVDSTByR3N3bzdrRUh0Ukk4QUhFeGdBd0FBQVBDOE5zcjlTL2hmZlQyaitjTUlnQmRLdTQ3OUp4enhONll2UmdDRTZCR0FBd2hzQUFBQUFKN1dSdG4vd2pVdDFqYStwbEhZQlFFNFJGck1kVVRKZUpaaEJ6TGcram42UCtISVZRRDJKTEFCQUFBQWVGd2IwOWcrZnVHckdvM0lCamlVSTByR2MyNEV3RmFLSHY4TzBTTUFleERZQUFBQUFEeXNqZWtzZkRvbWFqeU9pUUtPL1YzamlKTGhMZGZYcFRFQU42VG4vay9HQU1CVEJEWUFBQUFBOTdVeHJWMEZYb2ZGMmJFc2pRQTRVanFhNU05d1JNblF2aGdCY01mNzlmWE5jelVBanhIWUFBQUFBTnpXeGpTUDdGajQ2a2F4Q3JzZ0FNY1QyUXl2Mjk3REFXNTZ2YjBmaTJ3QXVFZGdBd0FBQUhDdGpXbkdOWWxqb3NienV4RUFQVWlMdVg5dmZ4Y3hqSE1qQUI2UVlzZi9oT2dSZ0RzRU5nQUFBQUFiYlV3M3JrbGUrd3BIc3pRQ29FZnBkOUY3WXhoRUYzYXhBUjZXb2tjN2l3RndpOEFHQUFBQVlQcHhUWklXQVN3QWpDTWRFYlV5QnFCSG4yYndlMmtxN0VJR1BQVjhiV2N4QUg0UTJBQUFBQUMxYTJNK2k1aHZmWjJqdVRBQ3dPK25TZnE4dnE2TUFYakMxeERaQUJBQ0d3QUFBS0J1YmN4cjhYTGhLeDNOWDBZQVpQbzlsWFpQT0RHS2JGSmM4OFVZZ0dla2Q0WlB4Z0JRTjRFTkFBQUFVS3MyNXJjelFEb2lxdkhWamlMdFlHTUhCQ0RYdmYzUEVObmtaQmNiWUIvdnc4NWlBRlVUMkFBQUFBQTFhbU8rZnpuKzJ0YzdtcVVSQUptSWJQSktjWTJqL29EYTN5TUFlSWJBQmdBQUFLaE5HL1ArUy9GWHZ1TFIvR0VFUUVhN3lLWXhpaXpPalFEd1BnSEFVLzVoQkFBQUFFQkYycGovWDRhbkhXelNEZ2VPdWhoZTJ2MWdaUXc4WVBISS8vNnZ1QjFMTEl5S1o2VEk1dS8xOWN2NnVqU09YcVg3OTg5aGw2QTVPOW4rTi9TUW00RnlFMEkyOW51dlNEOVR2M251QnFpSHdBWUFBQUNvUlJ2MS9FdlRGTmwwdnZMQnBjV1ZwVEh3Z0pmK1hOeGNCRjVzLzN4MTUvOU52ZExQUjlySlJtVFRQL09jdjVjZUJYYTYvVzl1ZDEvKzUvYlBKa1E0Yko2NW0rMzlXR1FEVUFHQkRRQUFBRkNETnVyYXhqMHR4SGUrZHBpc203SFc4b0gvLzJaN3BVWGVmMjMvWEJoYlZVUTJNSXliLzMwOUZPZnNBcHpGamZ2eHFiRlY1ZlRHL1Zoa0F6QnpBaHNBQUFCZzd0cW9LNjVKMHIrbS9jMVhEN08xMmw3TE8vOTdFOWVMdXltMFd4alZySWxzWUh5Ny8vYnUzbzkzOStLZnR2ZGkwYzI4aVd3QUtpR3dBUUFBQU9hc2pmcmltbVQzTDZtWGZnU2dLcXZ0ZFhPWGhkM3VOcnRGM3NhWVpuZS9GOWxBZVM0ZitHOXljZWQrZkdKTXN5S3lBYWlBd0FZQUFBQ1lxemJxakd0MmZnMkJEWEIva2JlSnpjTHVyMkdCZHk1MmtjMy9oa1ZkS05ueXpyUFo2WjM3TWRPWHZ0TlBZU2RKZ05uNkh5TUFBQUFBWnFpTnV1T2E1TFVmQStBQnEvWFZyYTgzNit2L3JxK2YxOWQ1MlAxazZuYVJqV0FLcGlQZGR6L0hac2VULzdPOUwzL2UzcWZ4SGdKQWdRUTJBQUFBd055MDRTKzFreVljQlFNOEx5M3duc1VtdEVrN29LUi9kWDloTEpPME81NUVaQVBUbE82OUg3YjM0cCszLzdmNDBmc0lBQVVSMkFBQUFBQnowb2Evekw3SkxqYkFTNnppOXU0MllwdnBFZG5BUE94MnQ5bkZqMkliN3lVQUZFQmdBd0FBQU14RkcvNFMrNjVmalFBNDBGWGNqMjJXeGpJSnU4Z0dtSWRWM0k1dHpzTXhVbE42UHprekJvRDVFTmdBQUFBQWM5Q0d1T1loaTdDTEFYQzhYV3p6UzFqY25ZcFR2eGRobHRLOTl5eXVqNUhxdHZkb3l2VngrNjRDd0F3SWJBQUFBSUNwYThNaTRsTWNFd1gwYVJYWGk3dHBkeHRIU1BuOUNJd2pIUm4xMi9aKy9GczRRcXBrWDBOa0F6QUxBaHNBQUFCZ3l0cXdlUGljVjBZQVpKTGltaFRaMk5XbTdOK1Q3NDBCWm0yM3k5alBjYjJyRGVYNUZKdmR4UUNZTUlFTkFBQUFNRlZ0aUd2MllRY2JJTGRWWE85cVl4ZUY4bndLT3lkQUxYYTcydnpmRUQ2V0poM2IrbWVJYkFBbVRXQURBQUFBVEZFYjRwcDlwYi9NRjlrQVErbGlzNFBDTCt0cmFSekZTTDh6TGVwQ1BkS3VObWR4SFQ2dWpLU1k1L0t2Mno4Qm1DQ0JEUUFBQURBMWJZaHJYc294VWNEUWxyR0piTkxpYm1jY1JiQnpBdFNwMjk2TDM0VHdzUVNuMi9zeEFCTWtzQUVBQUFDbXBBMXh6U0hzWUFPTVpSV2IzUk9FTnVPemN3TFU3U0kyNGFNZHhzWjM2cDBHWUpvRU5nQUFBTUJVdE9Fdm9nL1ZoRjBMZ0hHdFFtaFRndlM3NEpzeFFOV1dJYlFwNWQzbXpCZ0Fwa1ZnQXdBQUFFeEJHK0thWXkyTUFDakFLcTVEbXd2akdPMzNnZCtwd0RLdVE1dVZjWXppWTlocEVtQlNCRFlBQUFCQTZkcXdFTmlIdDBZQUZHUzF2dDZFSFJURy9OM2FHZ093dlFlbjZQRzNFTnFNSWIzbjJHa1NZQ0lFTmdBQUFFREoyaERYOUNYOXhmMkpNUUNGV2NZbXNrbXh6Y280Qm1WUkY3aXBXMTgvcjYvejlYVmxISU5KeitmZlBLY0RUSVBBQmdBQUFDaFZHK0thdnRtQ0hpaFZPaTRxN2FCZ1lYZFlmNFpGWGVCYXV2K2ViZS9IblhFTXBvbE5aQU5BNFFRMkFBQUFRSW5hRU5mazhLc1JBSVU3aTgwT0NoZEdNWWdVMS94cERNQWRLYlJKUjBhbEhjWXVqV01RaS9YMXlSZ0F5aWF3QVFBQUFFclRocmdtRjdzVUFGT3dpczJSVWIrRVk2T0drSTZKc3FnTFBHUVptK2p4UTloZGJBanZ3NDZUQUVVVDJBQUFBQUFsYVVOY2swdjYxOGR2akFHWWtHVmNIeHRGWHUrM3Y0TUJIdko1ZXorMnUxaCs2VjJvTVFhQU1nbHNBQUFBZ0ZLMElhN0pKY1UxYVNjSS8vSVltS0t6Mk95Z3NEU0tyTkl1TnFmR0FEd2lQVWUrMlY2ZUtmTkpPMDUrTXdhQU1nbHNBQUFBZ0JLMElhN0pSVndEek9sZTVwaVNmRTYydjRzZEp3ZzhKZTFpWXplYnZCemRCMUFvZ1EwQUFBQXd0amJFTmJtSWE0QzVTY2VVL0x5OXY5RS9pN3JBUHV4bWsxODZ1dSsxTVFDVVJXQURBQUFBaktrTmNVMHU0aHBncmxheGlXek9qU0xiNzJhTHVzQSs3R2FUVjNwUGFvd0JvQndDR3dBQUFHQXNiWWhyY2hIWEFEVTRpMDFvc3pLSzNsblVCZmExMjgzbU44K2V2VXRIOW4wekJvQnlDR3dBQUFDQU1iUWhyc2xGWEFQVWRzOUxrVTFuRkwwNjhYc2FlS0Z1K3d6cUNMOStwYVA3em93Qm9Bd0NHd0FBQUdCb2JWaTB5MFZjQTlRbzNmTitDN3NuOUcwUkZuV0JseitMcHVqeHMxSDA2dVAybmd6QXlBUTJBQUFBd0pEYUVOZmtJcTRCYXRlRjNSUDZsaFoxVDQwQmVLRVBzVGsyeW5OcGY5STcxSWt4QUl4TFlBTUFBQUFNcFExeFRTN2lHb0RiOThNTG8raU5SVjNnRUJjaGV1eFRFNXZvRVlBUkNXd0FBQUNBSWJRaHJzbEZYQU53VzdvZnBwMFRQaGhGTDlJT05oWjFnV09lVTBXUC9YaS92bDRiQThCNEJEWUFBQUJBYm0ySWEzSVIxd0E4N3JON1pHL1NvdTdDR0lBRDdLTEhjNlBvaFYzRkFFWWtzQUVBQUFCeWFrTmNrNHU0QnVCNXkzQkVTVjhzNmdMSE9JdE5hT1BaOVRnbjNxOEF4aU93QVFBQUFISnB3MS8rNWlLdUFYajVQWE5wRkVkcHdsRlJ3SEV1UE1QMjRuVTRLZ3BnRkFJYkFBQUFJSWMyeERXNWlHc0FYdTVxZSsvc2pPSW9qb29DK25pVy9kK3dzOWl4UG9WZHhRQUdKN0FCQUFBQSt0YUd1Q2FYYm4zOUhPSWFnRVA5dHI3T2plRW9mc2NEeDlwRmp4ZEdjYkFtN0NvR01EaUJEUUFBQU5Dbk5peTg1ZExGWm1FWWdPT2N1WjhlcGRuT0VPQVlLYko1RTNZV080WmR4UUFHSnJBQkFBQUErdEtHdUNhWExpd0dBK1M0cjlvUjdEQnAxNFRHR0lBZXBIdnhaMk00bVBjdmdBRUpiQUFBQUlBK3RPRXZkM1BwUWx3RGtPdittbzRvRWRrY3h1OTlvQzhmUE84ZXJBbTdpZ0VNUm1BREFBQUFIS3NOaTJ5NWRHR3hBU0NueXhEWkhHcXhmUVlBOE53N3JuZGhWekdBUVFoc0FBQUFnR08wSWE3SnBRdUxEQUJERU5rYzd0UDZPakVHd1BQdnFFNjhrd0VNUTJBREFBQUFIS29OZjVHYlN4Y1dGd0NHSkxJNVRGclUvV2dNZ09mZzBTM1cxMnRqQU1oTFlBTUFBQUFjb2cxeFRTNWRXRlFBR0lQSTVqRHYxOWVwTVFDZWgwZjN5UWdBOGhMWUFBQUFBQy9WaHJnbWx5NHNKZ0NNU1dSekdJdTZnT2ZpOFRYcjY4d1lBUElSMkFBQUFBQXYwWWE0SnBjdUxDSUFsRUJrODNLTGNEUUo0UG00Qk85aUU5b0FrSUhBQmdBQUFOaFhHK0thWExxd2VBQlFFcEhOeTluRkJ2Q2NQTDZUOWZYUkdBRHlFTmdBQUFBQSsyaERYSk5MRnhZTkFFb2tzbm1aSmh4TkFuaGVMdVhkN2RRWUFQb25zQUVBQUFDZTA0YTRKcGN1TEJZQWxDeEZOaCtNWVcvcGFKSVRZd0F5UFRkM3hyQTN1NG9CWkNDd0FRQUFBSjdTaHJnbWx5N0VOUUR1MS9QaWFCSWdwOTlDWkxPdnhmWUNvRWNDR3dBQUFPQXhiWWhyY3VuQ1lpM0ExTzdiNThhd2wvZXhPUzRLSUlmMERMMDBocjE0bHdQb21jQUdBQUFBZUVnYi9rSTJseTdFTlFCVGRCWjJUdGlYWFd5QW5ON0U1Z2cvbnRaczMrc0E2SW5BQmdBQUFMaXJEWEZOTGwySWF3Q216TTRKK3o5TG5Cb0RrTW5WK3ZwbCt5ZFBFendDOUVoZ0F3QUFBTnpVaHJnbWx5N0VOUUJ6WU9lRS9Yd3lBaUFqa2MxK210Z2MzUWRBRHdRMkFBQUF3RTRiNHBwY3VoRFhBTXpGMWZhZWJsSDNhWXZ0QlpCTGloMC9HTU96MGk0Mko4WUFjRHlCRFFBQUFKQzBJYTdKcFF0eERjRGNwRVhkTjhid0xFZVRBRU04YTU4Ync1TlNYR01YRzRBZUNHd0FBQUNBTnNRMXVYUWhyZ0dZcTJYWU9lRTVpN0NMRFpEZjJmcTZNSVludlF1NzJBQWNUV0FEQUFBQWRXdERYSk5MRitJYWdMbjdIQloxbjJNWEcyQUk2Ymw3WlF5UHNvc05RQThFTmdBQUFGQ3ZOc1ExdVhRaHJnR29SYnJmWHhyRG94WmhGeHNndjZ2WUhOMTNaUlNQc29zTndKRUVOZ0FBQUZDbk5zUTF1WFFocmdHb3lkWDJ2bTlSOTNGMnNRR0drR0pIUi9jOTdtVDdIZ2pBZ1FRMkFBQUFVSjgyeERXNWRDR3VBYWlSUmQybkxkWlhZd3pBUU0vam5URTg2cDBSQUJ4T1lBTUFBQUIxYVVOY2swc1g0aHFBMm44UGRNYndLTHZZQUVOSndhT2oreDdXaEYxc0FBNG1zQUVBQUlCNnRDR3V5YVVMY1EwQW0wWGRsVEU4K2h6U0dBTXdnQ3ZQNWs4U1BBSWNTR0FEQUFBQWRXaERYSk5MRi80Q0g0Q050S2o3eGhnZVpWRVhHSXFqK3g3WHJLL1h4Z0R3Y2dJYkFBQUFtTDgyeERXNWRDR3VBZUMydEtoN2Jnd1BTZ3U2SjhZQURPVHorbG9hdzRQZUdRSEF5d2xzQUFBQVlON2FFTmZrMG9XNEJvQ0huY1VtdE9HMkZOZThOd1pnUU9sNS9jb1k3bGxzTHdCZVFHQURBQUFBODlXR3VDYVhMc1ExQUR6Tm91N0QzaG9CTUtDVjUzYjNZNEMrQ0d3QUFBQmdudG9RMStUU2hiK2tCK0I1am9wNldMTjlUZ0VZeXNYMjR2NDdZMk1NQVBzVDJBQUFBTUQ4cEtNWHhEVjVkQ0d1QVdCL244TlJVUTk1WndUQXdPd3E5ckRXQ0FEMko3QUJBQUNBZVVsaHpTZGp5S0lMY1EwQUwrZDN4MzJuMnd0Z0tDbXVzYXZZZllKSGdCY1EyQUFBQU1COHBMaW1OWVlzdXJCQUNzQmhIQlgxTUl1NndORFNybUpMWTdqbHhEc2t3UDRFTmdBQUFEQVA0cHA4dWhEWEFIQ2NzL1cxTW9aYjBuUExpVEVBQS9OY2Y5OWJJd0RZajhBR0FBQUFwazljazA4WC9oSWVnSDc0ZlhLZjV4ZGdhS3V3cTloZGkzQnNIOEJlQkRZQUFBQXdiZUthZkxxd0dBcEFmNWJyNjhJWWJuRk1GRENHZEZUVXloamNqd0ZlU21BREFBQUEweVd1eWFjTGNRMEEvZnV3dnE2TTRZY21OanNuQUF6cGFucy81dHBySXdCNG5zQUdBQUFBcGtsY2swOFg0aG9BOGxpdHJ5L0djTXRiSXdCR2tIWVVXeHJERHlmZUx3R2VKN0FCQUFDQTZSSFg1Tk9GdUFhQXZNN0MwU1EzcFYwVFRvd0JHSUhuL3RzRWp3RFBFTmdBQUFEQXRJaHI4dW5DWDdJRE1JeHpJL2doeFRXT0pnSEdzRnBmbjQzaGgwVnNqdTRENEJFQ0d3QUFBSmdPY1UwK1hZaHJBQmoyOTg3U0dINndhd0l3bGhROFhobkREOTQzQVo0Z3NBRUFBSUJwRU5mazA0VzRCb0RoMmNYbTJpTHNtZ0NNSThVMVg0emhCOEVqd0JNRU5nQUFBRkErY1UwK1hZaHJBQmpITXV4aWM1Tmpvb0N4cEdPaVZzYndYYk8rVG8wQjRHRUNHd0FBQUNpYnVDYWZMc1ExQUl6TDc2RnI3NHdBR0VuYXhjYXVZdGZzWWdQd0NJRU5BQUFBbEV0Y2swOFhGalVCR045cSt6c0p1eVlBNDc4ZnJJemhPKytnQUk4UTJBQUFBRUNaeERYNWRDR3VBYUFjZGsyNFp0Y0V3UDE0ZkNmaDJENkFCd2xzQUFBQW9Eemltbnk2RU5jQVVKWlYyTVZteDRJdU1QYTd3c29ZdnZ2VkNBRHVFOWdBQUFCQVdjUTErWFFocmdHZ1RIWk4yR2pDTVZHQSszRUpCSThBRHhEWUFBQUFRRG5FTmZsMElhNEJvRnlyc0l2TmptT2lnTEhmRzFiRzRKZ29nSWNJYkFBQUFLQU00cHA4dWhEWEFGQytMMGJ3blFWZFlHeDJzZGx3VEJUQUhRSWJBQUFBR0orNEpwOHV4RFVBVE1QbCtsb2FnMk9pZ05GZHJLOHJZNGlGRVFEY0pyQUJBQUNBY1lscjh1bENYQVBBdE5nMVlXTmhCTUNJVWx4alZ6SEJJOEE5QWhzQUFBQVlqN2dtbnk3RU5RQk16M0o5cll3aDNob0JNTExQUnVCK0RIQ1h3QVlBQUFER0lhN0pwd3R4RFFEVFpSZWJ6WTRKSjhZQWpPaHErMTVSdTRVUkFGd1QyQUFBQU1Ed3hEWDVkQ0d1QVdENnY4dXVqQ0ZlR3dFd01zZEViWUxIeGhnQU5nUTJBQUFBTUN4eFRUNWRpR3NBbUFlTHVoRy9HZ0V3c3N2WUhOMVh1NFVSQUd3SWJBQUFBR0E0NHBwOHVoRFhBREN2MzJ1MVd4Z0JVSURmalVEd0NMQWpzQUVBQUlCaGlHdnk2VUpjQThDOHJOYlhSZVV6T0FtUkRWREd1MGJ0eC9hNUZ3TnNDV3dBQUFBZ1AzRk5QbDJJYXdDWUo3c21XTlFGeW5ubnFKbmdFV0JMWUFNQUFBQjVpV3Z5NlVKY0E4QjhwUjFzVnBYUHdMRWtRQW0rR0lIQUJpQVIyQUFBQUVBKzRwcDh1aERYQURCL3RSOFRkUnFiblJNQXhyUmFYOHZLWnlCNEJBaUJEUUFBQU9RaXJzbW5DM0VOQUhXd2E0SmRFNEF5MUg1c24rQVJJQVEyQUFBQWtJTzRKcDh1eERVQTFHTzF2aTRybjhFclB3WkFBUzZNUVBBSUlMQUJBQUNBZm9scjh1bENYQU5BZldyZk5XSGhSd0Fvd05YMmZhUm1na2VnZWdJYkFBQUE2SSs0SnA4dXhEVUExUHM3c0dhT0pRRks4WWY3TVVEZEJEWUFBQURRRDNGTlBsMklhd0NvVjlvMW9mYWpTUlorRElBQ1hHenZ5ZTdGQUpVUzJBQUFBTUR4eERYNWRDR3VBUUM3SmdDVVFmQUlVREdCRFFBQUFCeEhYSk5QRitJYUFFaHFYOUI5NVVjQUtFVHR3ZVBDandCUU00RU5BQUFBSEU1Y2swOFg0aG9BMkVsSGtpd3IvdndMUHdKQUlXby9KdW9uUHdKQXpRUTJBQUFBY0JoeFRUNWRpR3NBNEM3SFJBR1VvZVpkeFJhK2ZxQm1BaHNBQUFCNE9YRk5QbDJJYXdEZ0liVWZFN1h3SXdBVTRxK0tQL3ZKK21yOENBQzFFdGdBQUFEQXk0aHI4dWxDWEFNQWoxbXRyOHVLUDc5alNZQlMxQjQ4MmxFTXFKYkFCZ0FBQVBZbnJzbW5DM0VOQUR4bldmRm50NkFMbE9LcTh2dnhLejhDUUswRU5nQUFBTEFmY1UwK1hZaHJBR0FmZjFUODJRVTJnUHV4K3pIQXFBUTJBQUFBOER4eFRUNWRpR3NBWUYvTDJPeWNVS3VGSHdHZ29QdHhyUVEyUUxVRU5nQUFBUEEwY1UwK1hZaHJBT0NsbGhWL2RvdTZRQ2t1bzk3ZzhXUjlOWDRFZ0JvSmJBQUFBT0J4NHBwOHVoRFhBTUFoL3FyNHMvL0wxdzhVWkZueFp4YzhBbFVTMkFBQUFNRER4RFg1ZENHdUFZQkRMU3YrN0JaMGdaTFVIRHk2SHdOVkV0Z0FBQURBZmVLYWZMb1Exd0RBTVdvK2xzU0NMbENTWmNXZi9TZGZQMUFqZ1EwQUFBRGNKcTdKcHd0eERRRDBZVm5wNXo1Wlg0MnZIeWhFemNHamV6RlFKWUVOQUFBQVhCUFg1Tk9GdUFZQStsTHpzU1NOcng4b3lMTFN6MjFITWFCS0Foc0FBQURZRU5mazA0VzRCZ0Q2ZEZueFo3ZW9DNVNrNXVEUi9SaW9qc0FHQUFBQXhEVTVkU0d1QVlDK0xTdis3UC95OVFNRnFUbDRiSHo5UUcwRU5nQUFBTlJPWEpOUEYrSWFBTWhsV2VubnRtTUM0RjdzZmd3d0NvRU5BQUFBTlJQWDVOT0Z1QVlBY3FwMTE0VEdWdys0SHhmQmptSkFkUVEyQUFBQTFFcGNrMDhYNGhvQXlPM2ZsWDd1eGxjUEZFYndDRkFKZ1EwQUFBQTFFdGZrMDRXNEJnQ0djRm54WjNjc0NWQ1NXb05IOTJLZ09nSWJBQUFBYWlPdXlhY0xjUTBBREtYbXdPYkUxdys0SDdzWEF3eE5ZQU1BQUVCTnhEWDVkQ0d1QVlDaDFicW9hOWNFb0NUTGlqKzcrekZRRllFTkFBQUF0UkRYNU5PRnVBWUF4ckNxOUhQYk5RRndQM1kvQmhpY3dBWUFBSUFhaUd2eTZVSmNBd0JqK1hlbG4vc25YejFRbUZXbG45c09Oa0JWQkRZQUFBRE1uYmdtbnk3RU5RQXdwbHFQaUxKakFsQ2F2OXlQQWVaUFlBTUFBTUNjaVd2eTZVSmNBd0JqVzFYNnVSdGZQVkNZcTBvLzk3OTg5VUJOQkRZQUFBRE1sYmdtbnk3RU5RQlFnbHAzc0dsODlZRDdzZnN4d05BRU5nQUFBTXlSdUNhZkxzUTFBRkNTbFJFQXVCY0RrSi9BQmdBQWdMa1IxK1RUaGJnR0FFcXpxdlJ6TDN6MWdIdXhlekhBa0FRMkFBQUF6SW00SnA4dXhEVUFVS0tWRVFBVTRkSUlBT1pOWUFNQUFNQmNpR3Z5NlVKY0F3Q2wrbStsbi92RVZ3OFU1c29JQU9aTllBTUFBTUFjaUd2eTZVSmNBd0FscTNWQjk5UlhEeFJtVmVublh2anFnVm9JYkFBQUFKZzZjVTArWFlockFLQjBqaVFCS01OL2pRQmczZ1EyQUFBQVRKbTRKcDh1eERVQUFBQUE4SjNBQmdBQWdLa1MxK1RUaGJnR0FLYWkxaDFzZnZMVkE0VlpWdnE1RzE4OVVBdUJEUUFBQUZNa3JzbW5DM0VOQUV6SlZhV2YrOFJYRDFDRXhnaUFXZ2hzQUFBQW1CcHhUVDVkaUdzQUFBQU9jV1VFQVBNbXNBRUFBR0JLeERYNWRDR3VBWUNwdWpRQ0FQZGlBUElTMkFBQUFEQVY0cHA4dWhEWEFNQ1UyVFVCQUFBeUU5Z0FBQUF3QmVLYWZMb1Exd0FBMDdNd0FvQWkvR1FFUUMwRU5nQUFBSlJPWEpOUEYrSWFBQUNBdnRTNG85aUpyeDJvaGNBR0FBQ0Frb2xyOHVsQ1hBTUFjN0V5QW9BaVhCb0J3SHdKYkFBQUFDaVZ1Q2FmTHNRMUFEQW4velVDQUFESVMyQURBQUJBaWNRMStYUWhyZ0VBQUFDQUZ4SFlBQUFBVUJweFRUNWRpR3NBQUFBQTRNVUVOZ0FBQUpSRVhKTlBGK0lhQUFBQUFEaUl3QVlBQUlCU2lHdnk2VUpjQXdBQUFBQUhFOWdBQUFCUUFuRk5QbDJJYXdBQUFBRGdLQUliQUFBQXhpYXV5YWNMY1EwQUFBQUFIRTFnQXdBQXdKakVOZmwwSWE0QkFBQUFnRjRJYkFBQUFCaUx1Q2FmTHNRMUFBQUFBTkFiZ1EwQUFBQmpFTmZrMDRXNEJnQUFBQUI2SmJBQkFBQmdhT0thZkxvUTF3QUFBQUJBN3dRMkFBQUFERWxjazA4WDRob0FBQUFBeUVKZ0F3QUF3RkRFTmZsMElhNEJBQUFBZ0d3RU5nQUFBQXhCWEpOUEYrSWFBS2pkUDQwQUFBRHlFdGdBQUFDUW03Z21ueTdFTlFCQXhLa1JBTGdmQTVDWHdBWUFBSUNjeERYNWRDR3VBUUFBS01tSkVRRE1sOEFHQUFDQVhNUTErWFFocmdFQTZuWnBCQUJGK01zSWdGb0liQUFBQU1oQlhKTlBGK0lhQUlBckl3QUFZRWdDR3dBQUFQb21yc21uQzNFTkFIRGZ3Z2dBUm5kcUJBRHpKckFCQUFDZ1QrS2FmTG9RMXdBQUFKVHF4QWdBNWsxZ0F3QUFRRi9FTmZsMElhNEJBQUNnUEk3c0E2b2hzQUVBQUtBUDRwcDh1aERYQUFDUFcxVDZ1Zi95MVFPRnFmV0lxRXRmUFZBTGdRMEFBQURIRXRmazA0VzRCZ0FBWUFvY0VRVXdjd0liQUFBQWppR3V5YWNMY1EwQThMekdDQUNLOEU4akFKZzNnUTBBQUFDSEV0ZmswNFc0QmdEWVQxUHA1M1lrQ1ZBYVIwUUJ6SnpBQmdBQWdFT0lhL0xwUWx3REFPeXYxaDBUcm56MVFHRnFQU0xLL1Jpb2hzQUdBQUNBbHhMWDVOT0Z1QVlBZUpsVEl3QndQd1lnUDRFTkFBQUFMeUd1eWFjTGNRMEE4SEpOcFovYmtTUkFTV3JkdldicHF3ZHFJckFCQUFCZ1grS2FmTG9RMXdBQWgya3EvZHlPSkFGS1l2Y2FnQW9JYkFBQUFOaUh1Q2FmTHNRMUFNQmhhbDNRRmRjQXBXa3EvZHdyWHoxUUU0RU5BQUFBenhIWDVOT0Z1QVlBT0Z5dFI1STRIZ29vVFZQcDUvNnZyeDZvaWNBR0FBQ0FwNGhyOHVsQ1hBTUFIR2RoQkFCRitLblN6MjFITWFBcUFoc0FBQUFlSTY3SnB3dHhEUUJ3dkg5Vitybi84dFVEaFdrcS9keDJGQU9xSXJBQkFBRGdJZUthZkxvUTF3QUEvV2lNQUtBSXAwWUFNSDhDR3dBQUFPNFMxK1RUaGJnR0FPalBvdExQdmZUVkErN0Y3c2NBUXhQWUFBQUFjSk80SnA4dXhEVUFRSC9zbGdCUWhxYlN6MzNscXdkcUk3QUJBQUJnUjF5VFR4ZmlHZ0NnWDAzRm4zM3A2d2NLOGxPbG4vdlNWdy9VUm1BREFBQkFJcTdKcHd0eERRRFF2MXAzc0xGakF1Qis3SDRNTUFxQkRRQUFBT0thZkxvUTF3QUFlYnlxOUhQYk1RRW96YUxTei8xdlh6MVFHNEVOQUFCQTNjUTErWFFocmdFQThsbFUrcmxYdm5xZ0lLY1ZmM2JCSTFBZGdRMEFBRUM5eERYNWRDR3VBUUR5cVhsQjk3KytmcUFnaTRvL3V5T2lnT29JYkFBQUFPb2tyc21uQzNFTkFKRFhvdUxQdnZUMUF3WDV5ZjBZb0I0Q0d3QUFnUHFJYS9McFFsd0RBT1JYODRMdXl0Y1BGR1RoWGd4UUQ0RU5BQUJBWGNRMStYUWhyZ0VBaHJHbytMT3ZmUDFBSVpydDVWNE1VQW1CRFFBQVFEM0VOZmwwSWE0QkFJYlJSTDBMdWt0ZlAxQ1FSY1dmL1M5ZlAxQWpnUTBBQUVBZHhEWDVkQ0d1QVFDR3M2ajRzNjk4L1VCQlhya2ZBOVJGWUFNQUFEQi80cHA4dWhEWEFBRERxbmxCOTkrK2ZxQWdpNG8vKzZXdkg2aVJ3QVlBQUdEZXhEWDVkQ0d1QVFDRzk3cml6MjVCRnloRkUvVWUxK2QrREZUckgwWUFBQUF3VytLYWZGSlkweGtEQURDdzAvVjFVdkhudDZBTGxLTG0ySEhwNndkcVpRY2JBQUNBZVJMWDVDT3VBUURHc3FqNHM2L1cxNVVmQWFBUU5SL1hKM1lFcWlXd0FRQUFtQjl4VFQ3aUdnQmdURzhyL3V3V2RJR1MxTHlEemI5OS9VQ3RCRFlBQUFEeklxN0pSMXdEQUl3cEhRMTFXdkhuLzh1UEFGQ0kxNVYvZnNFalVDMkJEUUFBd0h5SWEvSVIxd0FBWTdPZ0MxQ0dYOTJQQWVva3NBRUFBSmdIY1UwKzRob0FvQVMxTCtndS9RZ0FoVmk0RndQVVNXQURBQUF3ZmVLYWZNUTFBRUFwYXQ3QnhtNEpRQ25TVVgxTnhaL2ZjWDFBMVFRMkFBQUEweWF1eVVkY0F3Q1VvdmJqb1paK0JJQkN2SzM4OHdzZWdhb0piQUFBQUtaTFhKT1B1QVlBS0VudHgwUFpNUUVvaGVBUm9HSUNHd0FBZ0drUzErUWpyZ0VBU25JU0ZuVHRtQUNVb1Biam9kSzkrTXFQQVZBemdRMEFBTUQwaUd2eUVkY0FBS1ZKY2MxSnhaOS90YjBBeHZhdThzKy85Q01BMUU1Z0F3QUFNQzNpbW56RU5RQkFpV28vSG1ycFJ3QW9STzI3aWYzYmp3QlFPNEVOQUFEQWRJaHI4aEhYQUFBbGNqeFV4RjkrRElBQzFMNmJXSExoeHdDb25jQUdBQUJnR3NRMStZaHJBSUJTZWY2emd3MVFocmVWZi83TDlYWGx4d0NvbmNBR0FBQ2dmT0thZk1RMUFFREozbFgrK2RPQzdzcVBBVEF5dTRtSkhRRytFOWdBQUFDVVRWeVRqN2dHQUNqWjZmcHFLcC9CMG84QlVBRHY1STdyQS9oT1lBTUFBRkF1Y1UwKzRob0FvSFR2ak1DQ0x1QitYSWlsRVFBSWJBQUFBRW9scnNsSFhBTUFsTTV4SkJ0TEl3Qkd0Z2k3aWFWNzhaVWZCUUNCRFFBQVFJbkVOZm1JYXdDQUtValBnaWVWejJBWkZuU0I4YjAxZ3ZqRENBQTJCRFlBQUFCbEVkZmtJNjRCQUtiQ2NTUVdkSUh4TmQ3UHYxc2FBY0NHd0FZQUFLQWM0cHA4eERVQXdGUXN3bkVreVlVUkFDUHpmaDZ4V2wrWHhnQ3c4UThqQUFBQUdGM2EvdjliYkJaVDZKKzRCZ0NZa285RzhIMUJkMlVNd01qc0ppWjJCTGhGWUFNQUFEQ3VGTmY4dWI1T2pTSUxjUTBBTUNWTmlLNFRDN3JBMk5ydCszcnQvaklDZ0d1T2lBSUFBQmlQdUNZdmNRMEFNRFYycjluNDNRZ0E5K1BSWFlYZ0VlQVdnUTBBQU1BNHhEVjVpV3NBZ0tscFlyTmpRdTNTZ3U2bE1RQWphcmYzNU5xSmF3RHVFTmdBQUFBTVQxeVRsN2dHQUppaWQwYnduUVZkWUd4dmplQTd4ME1CM0NHd0FRQUFHSmE0Smk5eERRQXcxV2ZFMWhpKys4TUlnQkV0dGhlQ1I0QjdCRFlBQUFEREVkZmtKYTRCQUticS9mWlpzWGJwZUNnTHVzQ1lQaHJCZHhmYmV6SUFOd2hzQUFBQWhpR3V5VXRjQXdCTStUblI4VkFiNGhwZ1RJdXdlODJPM2NRQUhpQ3dBUUFBeUU5Y2s1ZTRCZ0NZTXJ2WFhMT2dDNHpKN2pVYmRoTURlSVRBQmdBQUlDOXhUVjdpR2dCZzZzK0tkcS9ac0tBTGpHa1JkcS9aY1R3VXdDTUVOZ0FBQVBtSWEvSVMxd0FBVS9jcDdGNno0N2tPR1B0K3pJYmR4QUFlSWJBQkFBRElRMXlUbDdnR0FKaTZabjIxeHZERDcwWUFqS1QxN3Y2RDNjUUFuaUN3QVFBQTZKKzRKaTl4RFFBd0J4K040SWZWK3JvMEJzRDllSFRldFFHZUlMQUJBQURvbDdnbUwzRU5BREFIaTdCN3pVMWZqQUFZeVZsc2RoUmp3MjVpQUU4UTJBQUFBUFJIWEpPWHVBWUFtQXU3SmR6bU9CSmdySGY0ZDhid3d5cnNKZ2J3SklFTkFBQkFQOFExZVlsckFJQzVhR096Z3cwYkthNVpHUU13Z28vYmQzazI3Q1lHOEF5QkRRQUF3UEhFTlhtSmF3Q0FPVDAzMnIzbXRqK01BQmhCZW45L2J3eTNlTzhHZUliQUJnQUE0RGppbXJ6RU5RREFuS1RGM01ZWWZyanlyQWVNNUpNUjNOSnQ3OGtBUEVGZ0F3QUFjRGh4VFY3aUdnQmdUcHF3ZTgxZG52V0FNYlRocUw2N2ZqY0NnT2NKYkFBQUFBNGpyc2xMWEFNQXpNMVhJN2puaXhFQUk3ekwyNzNtdHRYNldob0R3UE1FTmdBQUFDOG5yc2xMWEFNQXpFMGJka3U0YXhtYlJWMkFJWDNjdnROelRld0lzQ2VCRFFBQXdNdUlhL0lTMXdBQWMzeCt0RnZDZlJaMGdhRXQxdGQ3WTdqSE96akFuZ1EyQUFBQSt4UFg1Q1d1QVFEbTZHdllMZUd1MWZxNk1BWmc0UGQ1Ui9YZGw5N0JyNHdCWUQ4Q0d3QUFnUDJJYS9JUzF3QUFjL1I2ZTNHYjNXdUFvYVdkYXhwamNEOEdPSWJBQmdBQTRIbmltcnpFTlFEQVhKOGg3Wlp3MzVWblAyQmc2VjMrb3pIY3MxeGZsOFlBc0QrQkRRQUF3TlBFTlhtSmF3Q0F1WEkwMU1QUzBWQ09Jd0dHZktmL1pnd1BzbnNOd0FzSmJBQUFBQjRucnNsTFhBTUF6Sldqb1I1M2JnVEFnTkxPTlkweDNMT0tUZkFJd0FzSWJBQUFBQjRtcnNsTFhBTUF6UGs1MHRGUUQwdUx1U3RqQUFheVdGL3ZqZUZCWWtlQUF3aHNBQUFBN2hQWDVDV3VBUURtN0ZzNEd1b3hqaU1CaG55dmR6VFV3OUl4ZlhhdkFUaUF3QVlBQU9BMmNVMWU0aG9BWU03U1Rna0xZM2pRY25zQkRPRnJpQjBmazJMSEsyTUFlRG1CRFFBQXdEVnhUVjdpR2dCZ3p0SXo1Q2RqZUpUalNJQ2hwTmp4dFRFOEtJVTFuNDBCNERBQ0d3QUFnQTF4VFY3aUdnQmc3cytTamlKNTNDcnNYZ01NUSt6NE5MdlhBQnhCWUFNQUFDQ3V5VTFjQXdETVhUcUtwREdHUjltOUJoanEzVjdzK0RUdjVnQkhFTmdBQUFDMUU5ZmtKYTRCQU9idUxCeEY4cFNWNTBGZ0lDbXVhWXpoVWQzMm5nekFnUVEyQUFCQXpjUTFlWWxyQUlDNVc2eXZqOGJ3Skx2WEFFTTQyOTZUY1Q4R3lFWmdBd0FBMUVwY2s1ZTRCZ0NZdXlZY1JmS2NsV2RDWUFCcEZ6R3g0OU82c0hzTndORUVOZ0FBUUkzRU5YbUphd0NBR3A0bnYyMy81SEYyU3dCeVMrLzFYNDNCL1JoZ0NBSWJBQUNnTnVLYXZNUTFBRUFOdm5xZWZOYktjeUV3d1B1OTJQRjU1MkgzR29CZUNHd0FBSUNhaUd2eUV0Y0FBRFg0Rkp2alNIamFCeU1BTWt2djk0MHhQT2xxZlgwMkJvQitDR3dBQUlCYWlHdnlFdGNBQURWbzE5ZDdZM2pXY24xZEdBT1FrWjNFOXZNbE5wRU5BRDBRMkFBQUFEVVExK1FscmdFQWFwQjJyZmxxREhzNU53SWdvN1NUV0dzTXo3SjdEVURQQkRZQUFNRGNpV3Z5RXRjQUFEVkl6NUxpbXYwc3R4ZEFEbTNZU1d4ZktYYTBldzFBandRMkFBREFuSWxyOGhMWEFBQTFPTjArVTU0WXhkN1BpQUE1dENGMjNOY3E3RjREMER1QkRRQUFNRmZpbXJ6RU5RQkFMYytVMzBKY3M2LzBmTGd5QmlBRE80bTl6QWNqQU9pZndBWUFBSmdqY1UxZTRob0FvS1pueXNZbzlwS09JYkdnQytTdzIwbU0vU3pYMTRVeEFQUlBZQU1BQU15TnVDWXZjUTBBNEptU2gzeUpUV1FEMENmSDlMMmMyQkVnRTRFTkFBQXdKeFpDOGhMWEFBQ2VLWG5JYW4yZEdRUFFNM0hOeTZWMzlrdGpBTWhEWUFNQUFNeUZoWkM4eERVQWdHZEtIbU8zQktCdjRwcVhjMVFmUUdZQ0d3QUFZQTRzaE9RbHJnRUFQRlB5bU9YNnVqQUdvRWZpbXNPY2g2UDZBTElTMkFBQUFGTm5JU1F2Y1EwQTRKbVM1NTRYQWZvaXJqbE1PaGJxc3pFQTVDV3dBUUFBcHN4Q1NGN2lHZ0RBTXlWUFNic2xySXdCNkltNDVuQ09oZ0lZZ01BR0FBQ1lLZ3NoZVlsckFBRFBsRHhsRlhaTEFQb2pyamxjZW5kZkdnTkFmZ0liQUFCZ2lpeUU1Q1d1QVFCcTBIaW1QUHFaOGNvWWdCNjhEbkhOb2RKOTJPNDFBQVA1aHhFQUFBQVRJNjdKUzF3REFOVEFUZ25IdVFpN0pRRDlhTmZYVjJNNFdJcHJ4STRBQTdHRERRQUFNQ1hpbXJ6RU5RQkFEY1ExeDduYVBqY0NIT3Q5aUd1T3NmUU9EekFzZ1EwQUFEQVY0cHE4eERVQVFBM2E5ZlYzaUd1T2NSNTJTd0NPbDhLYVQ4WndNTEVqd0FnRU5nQUF3QlNJYS9JUzF3QUFOVGdMT3lVY2E3bStQaHNEY09UNy9iZllCSThjTHNXT0syTUFHTlkvakFBQUFDaWN1Q1l2Y1EwQVVNUHpaTm9sb1RXS285Z3RBVGhXRTV1NHh2djljUzVEN0Fnd0NvRU5BQUJRTW5GTlh1SWFBTUR6SlB1eVd3SndqTlB0L2RnUmZmMjh5d013QWtkRUFRQUFwYklZa3BlNEJnQ1l1L1FjK1IvUGs3MVlodDBTZ01PMTYrdnZFTmYwNFVOc2RyQUJZQVFDR3dBQW9FVGltcnpFTlFEQTNMVmhNYmN2am9ZQ2pubTMvN3E5T040eXhJNEFvM0pFRkFBQVVCcHhUVjdpR2dCZzdzK1NuMklUMk5DUHRGdkN5aGlBRjJyVzF6ZnY5cjBST3dJVXdBNDJBQUJBU2NRMWVZbHJBSUE1TzkwK1M3WkcwWnNMejQvQUFWN0haaGN4Ny9iOUVUc0NGRUJnQXdBQWxFSmNrNWU0QmdDWXM5YXpaTzlXWWJjRTRPWFNMbUxmd2hGOWZSSTdBaFRDRVZFQUFFQUp4RFY1aVdzQWdEay9Sem9TS3Q4ejVKVXhBSHRLNy9OZnZkZjN6dEZRQUFXeGd3MEFBREEyY1UxZTRob0FZSzRXc1RtQ3BEV0szcDJ2cjZVeEFIdDY3NzArbXpjaGRnUW9oaDFzQUFDQU1ZbHI4aExYQUFCemRiYStQaHBERnBmYitRTHM4MDZmam9OYUdFVVdZa2VBd2doc0FBQ0FzWWhyOGhMWEFBQno1QWlTdk5JdUNXK01BZGpENiszOStNUW9zbGlHMkJHZ09JNklBZ0FBeGlDdXlVdGNBd0RNMFZsc2pvVHlESm4zT1hKbERNQXo3L1BmdHBlNEpnK3hJMENoN0dBREFBQU1UVnlUbDdnR0FKaWJSV3gyU1dpTUlxdlA2K3ZDR0lBbnZJL044WHpDbXJ4U1hITmxEQURsc1lNTkFBQXdKSEZOWHVJYUFHQnV6NDZmdHMrUGpYRmt0VnhmSDR3QmVNVHA5bDc4S2NRMXVaMXY3OGtBRk1nT05nQUF3RkRFTlhtSmF3Q0FPV25EUXU1UUhFVUNQUFVldjl1MWh2elNMbUpueGdCUUxvRU5BQUF3QkhGTlh1SWFBR0F1MHZOaUNtc1dSakdZWDhKUkpNQjliV3pDbXNZb0JySGF2dHNEVURDQkRRQUFrSnU0Smk5eERRQXdsMmZHRk5hMFJqSDRzK1NsTVFBM0xHSVQxaXlNWWpDN25jVEVqZ0NGRTlnQUFBQTVpV3Z5RXRjQUFITjRYa3pIajd3THgwRU5yZk1zQ2R6UXhDYXNhWTFpY0I5QzdBZ3dDUUliQUFBZ0YzRk5YdUlhQUdEcTJ0anNXaU9zR2Q1bE9Jb0V1SDUzVDZIalI2TVl4YmwzZTREcEVOZ0FBQUE1aUd2eUV0Y0FBRlBXeG1ZaHR6R0tVYXpXMXkvR0FON2J3dzVpWTd0WVgyZkdBREFkQWhzQUFLQnY0cHE4eERVQXdGUzFJYXdaMjlYNmVyUDlFNmozblYxWU16NDdpUUZNa01BR0FBRG9rN2dtTDNFTkFEQkZiUWhyU25xZXZEUUdxUFo5WFZoVGhoUTUvaEppUjRESkVkZ0FBQUI5RWRma0phNEJBS2IyYlBnNmhEV2xQVTllR0FOVUo5MkRVMVRUaHJDbUJPSWFnQWtUMkFBQUFIMFExK1FscmdFQXBxS0p6U0t1SFJMSzBubWVoT3FjeG5WWVExbnY5M1lTQTVnb2dRMEFBSEFzY1UxZTRob0FZQW9XNit0dFdNZ3RVYmQ5cGdUcTBHN3Z4d3VqS1BMOTNrNWlBQk1tc0FFQUFJNGhyc2xMWEFNQWxQNHNtSTZCZXVkNXNGaHBsNFFQeGdDejE4UjFXTk1ZUjVFK2U3OEhtRDZCRFFBQWNDaHhUVjdpR2dDZ1ZMdGpSMTZIWTZCS2x1S2FYOWJYbFZIQWJMWHI2OWZ0L1poeXBYZDdzU1BBREFoc0FBQ0FRNGhyOGhMWEFBQ2xhZUo2dDVyR09JcVhvaHB4RGN5VHlIRmF1bkJNSDhCc0NHd0FBSUNYRXRma0phNEJBRXA2N210amMrU0laNy9wRU5mQS9KeHU3OFVwcW1tTVl6SWMwd2N3TXdJYkFBRGdKY1ExZVlsckFJQ3hOYkZad0UxSGppeU1ZM0oyY2MybFVjRGtpV3FtelRGOUFETWtzQUVBQVBZbHJzbExYQU1BakNVOTMrMmlHczk2MHlXdWdlbTdHVGcyeGpGWjRocUFtUkxZQUFBQSt4RFg1Q1d1QVFDRzFNUm04ZlpWYkJaelQ0eGtGdDZFdUFhbTV2VE8vWmpwRTljQXpKakFCZ0FBZUk2NEppOXhEUUNRV3hQWEM3aUxzQ3ZDWEo4cGw4WUF4VHU5Y3o4V09NN0xLc1ExQUxNbXNBRUFBSjRpcnNsTFhBTUE1TERZWGo5dG4rTWFJL0ZNQ1F5dTJkNkQwL1ZxKzZlZ1pyNVNWUE1teERVQXN5YXdBUUFBbnZJMXhEVzVXQWdCQUk3VnhQWHVOR0lhejVUQWVFNXYzSVBGTlBWSlVVM2F1Y1l4ZlFBeko3QUJBQUNlNGk4RTg3QVFBZ0RzYTdkSXUvc3poVFJOaUtEeFRBbERXOXo0ODU5eEhkUTBSbE0xY1ExQVJRUTJBQUFBdzdJUUFnQjFhdUxoUmRqRmpmODd4VE1uRC96djRKa1MrdlBRN2pLN2tISG4xU1AvTzl4MHViMGZpMnNBS2lHd0FZajRmMFlBTUJuTDJQeXJJSmdxQ3lGQUtmNE1pL2NBVTNTMWZhYThNSW9zMnRnY2t3dnduQlRWL0xLOUx3TlFDWUVOQUFEQU1NUTFBQUFjd3pFaytlMmUxMFUyd0ZQRU5RQ1YraDhqQUFBQXlFNWNBd0RBTWNRMXcrbTJ6KzhBRHhIWEFGUk1ZQU1BQUpDWHVBWUFnR09JYTRiWGhjZ0d1RTljQTFBNWdRMEFBRUErNGhvQUFJNlJGbk4vRG5ITkdMb1EyUUMzN3ducGZpeXVBYWpZUDR3QUFBQWdDM0VOQUFESHNGUEMrSGJQODErTkFxcS9Gd2p1QUxDRERRQUFRQWJpR2dBQWpuRVI0cHBTZEdGaEhXcjJ3VDBBZ0IwNzJBQUFBUFJMWEFNQXdERzZzSmo3LzltNzErTzRqU3dBbzdjY3dXYXc1UkFjZ2tKUUJxMFFtSUdVQVpYQlZRYmNETVlaakRPQU0rQm1zSU9kaGtWSnBEUVA5QXpRT0tjSzFTei9iSktvb2Z2VDdTVitUMFltMllDLzd3SFlNSUVOQUFEQWZQelBOd0FBcmpGT1NuaTBEWXMwZmM0WDJVRC94dWxoNHhTeHZhMEE0Q1ZYUkFFQUFNeERYQU1Bd0tXZTYrZEpjYzJ5WlpndUJMMGJRbHdEd0J0TXNBRUFBTGlldUFZQWdFdVpsTEF1MCtkK2syeWdQL3Y2UG42MkZRQzh4Z1FiQUFDQTY0aHJBQUM0MUhpWSszdUlhOVltd3lRYjZQSDMrbzhRMXdEd0V3SWJBQUNBeTRsckFBQzQxUGc1MHFTRWRYLy9SRGJRaHdlL3p3Q2N3aFZSQUFBQWx4SFhBQUJ3cWZFdzk5RTJyTjcwOTREcm9tQ2R4c0R4L2VIWjJRb0FUaUd3QVFBQU9KKzRCZ0NBU3pqTTdjLzBkNEhJQnRabFg5L0hnNjBBNEZTdWlBSUFBRGlQdUFZQWdFdU1oN2wvaExpbVJ4bXVsNEcxL2M2T1YvUU50Z0tBY3doc0FBQUFUaWV1QVFEZ0V1Tm5TSWU1L1grUFJUYXdiTS8xOS9SRC9Sb0F6dUtLS0FBQWdOT0lhd0FBT05kNGdQdmdjK1JtVE45bjEwWEI4Z3h4dkJKcWJ5c0F1SlFKTmdBQUFMOG1yZ0VBNEZ6akllNDdueU0zSjhNa0cxaWFwemhlMFNldUFlQXFBaHNBQUlDZkU5Y0FBSEN1OGZQakdOYzR6TjN1OTE5a0EvYzNYUW4xUGx3SkJjQU1YQkVGQUFEd05uRU5BQURubUE1em4yekY1azEvUjdndUN1NWpYOS9IUWtjQVptT0NEUUFBd092RU5RQUFuR01YeHl0SXhEVk1Na3l5Z1h0NERGZENBZENBQ1RZQUFBQS9FdGNBQUhDT2h6Z2U2TUwzcHI4clRMS0I5b2I2OS96T1ZnRFFnc0FHQUFEZ1c3c1Exd0FBY0JwWGtIQ0s2ZThMa1EyMDgxVGZ4OCsyQW9CV1hCRUZBQUFBQUFEbit4U3VJT0YwR2E2TGdoYkdvT1o5ZmNRMUFEUmxnZzBBQUFBQUFKek8xQm91bFhVMXlRYm1ZV29OQURkbGdnMEFBQUFBQUp6RzFCcXVsV0dTRFZ6TDFCb0E3c0lFR3dBQUFBQUErTGxkSEtPSXdWWXdnNnlyU1Rad3ZzYzR4bzdDR2dCdXpnUWJBQUFBQUFCNDNYaUErM0I0M29XNGhubGxtR1FENTlqWGQvRkRpR3NBdUJNVGJBQUFBQUFBNEVjWkRuSnAvek0yTXNrRzNqYStnejhmbm8rMkFvQjdFOWdBQUFBQUFNQlg0NVNFTWF6WjJRcHVJT3Nxc29FZlBkWDM4V0FyQUZnQ2dRMEFBQUFBQUJ5bkpIdzZQSSsyZ2h2THVvcHM0R2lJNHhWcU8xc0J3Skw4WmdzQUFBQUFBTmk0UER5L2g3aUcrLzRNZnJBTmJOd1lPajdVOS9IT2RnQ3dOQ2JZQUFBQUFBQ3dWYnM0SHVidWJRVUxrSFUxeVlZdEdnUEhjWXJZczYwQVlLa0VOZ0FBQUFBQWJNMFFyaDlobWJLdUlodTJZbGZmeDRPdEFHRHBYQkVGQUFBQUFNQldESEU4eUhYOUNFdVc0Ym9vK2plK2c5L1ZaN0FkQUt5QkNUWUFBQUFBQVBSdXZITGs4K0g1YUN0WWlheXJTVGIwWm9qajFYeFB0Z0tBdFJIWUFBQUFBQURRcXltc2VheGZ3NXBrWFVVMjlHQTRQSjllL0Z3RHdPb0liQUFBQUFBQTZJMndobDVrWFVVMnJOVVF3aG9BT2lHd0FRQUFBQUNnRjhJYWVwUjFGZG13SmtNSWF3RG9qTUFHQUFBQUFJQzFHdzdQbHhEVzBLK3NxOGlHcGR2SE1YUk1Xd0ZBYndRMkFBQUFBQUNzMVJBbUpMQWQwOCs1eUlZbDJ0WDM4YzVXQU5BcmdRMEFBQUFBQUd1emkrT0VoQ2Rid2Naa1hVVTJMT2xuY253ZjcyMEZBTDBUMkFBQUFBQUFzQllaRG5JaDZ5cXk0VjZlNCtzMVVJUHRBR0FyQkRZQUFBQUFBQ3paY0hpK0hKN0hPQjdxQWlJYjdtT01HeitIYS9rQTJDaUJEUUFBQUFBQVN6UmUvL1FsWEFNRmI4bTZpbXk0eGMrYTZXRUFiSjdBQmdBQUFBQ0FwUmppR05Wa3VIWUVUcEYxRmRrd3QybGF6Umc1bWg0R0FDR3dBUUFBQUFEZy92THcvQ2RNcTRGTGYzOUdJaHV1OVZ6Znc2YlZBTUFyQkRZQUFBQUFBTnlENlFnd242eXJ5SVpMdUpJUEFFNGdzQUVBQUFBQTRGYkdxR1k2eEIxc0I4d3E2eXF5NFJUamUzaWFIQ1p5QklBVENHd0FBQUFBQUdoSlZBTzNrM1VWMmZBYVVRMEFYRUZnQXdBQUFBREEzRVExY0Q5WlY1RU5FYUlhQUppTndBWUFBQUFBZ0d1Tmg3YTdjSWdMUzVGMUZkbHN6L0RkK3hnQW1JbkFCZ0FBQUFDQVM0eFRhblp4UE1UZDJRNVluS3lyeUtaL0w5L0ZlOXNCQUcwSWJBQUFBQUFBT01VUTN4N2ltbElEeTVkMUZkbjBaUW9jL3d4VGFnRGdaZ1EyQUFBQUFBQzg1dVVCN3ZqMVlFdGdsYkt1SXB2MTJ0WDM4SjhoY0FTQXV4SFlBQUFBQUFBd0h0YStQTHpkaHdOYzZFbldWV1N6ZkVOOUIvOVYzOGM3V3dJQXl5Q3dBUUFBQUFEWWxxRSswMlFhMDJsZ0c3S3VJcHRsdlk5ZnhqVGlSZ0JZTUlFTkFBQUFBRUNmcHFrMDQvUDNpNjhkM3NKMlpWMUZOcmMxeE5lWVpub2Y3MndMQUt5THdBWUFBQUFBWUwyR0Y4OTBhRHNHTkR0YkE3d2g2eXF5YVdOOEIzLzJQZ2FBL2doc0FBQUFBQUNXWi9maTYvR1E5ci94ZFNMTjlOOU1vZ0V1bFhVVjJjenZYNGZuMzRmbm82MEFnTDRJYkFBaVB0a0NnTlVZYkFFQWNNWG5pQysyZ1FYOEhMNzFtWFpuZTRBYnk3cUtiT1pYNnZyQlZnQkFQd1EyQVA0bEFRQUF3QllNL3Y0RGdCOWtYVVUyOHl0MUZka0FRQ2Qrc3dVQUFBQUFBQUNibFNFQ2FhV0VlQWtBdWlHd0FRQUFBQUFBMkxZTWtVMHJKVVEyQU5BRmdRMEFBQUFBQUFBWklwdFdTb2hzQUdEMUJEWUFBQUFBQUFDTU1rUTJyWlFRMlFEQXFnbHNBQUFBQUFBQW1HU0liRm9wSWJJQmdOVVMyQUFBQUFBQUFQQlNoc2ltbFJJaUd3QllKWUVOQUFBQUFBQUEzOHNRMmJSU1FtUURBS3Nqc0FFQUFBQUFBT0ExR1NLYlZrcUliQUJnVlFRMkFBQUFBQUFBdkNWRFpOTktDWkVOQUt5R3dBWUFBQUFBQUlDZnlSRFp0RkpDWkFNQXF5Q3dBUUFBQUFBQTRGY3lSRGF0bEJEWkFNRGlDV3dBQUFBQUFBQTRSWWJJcHBVU0loc0FXRFNCRFFBQUFBQUFBS2ZLRU5tMFVrSmtBd0NMSmJBQkFBQUFBQURnSEJraW0xWktpR3dBWUpFRU5nQUFBQUFBQUp3clEyVFRTZ21SRFFBc2pzQUdBQUFBQUFDQVMyU0liRm9wSWJJQmdFVVIyQUFBQUFBQUFIQ3BESkZOS3lWRU5nQ3dHQUliQUFBQUFBQUFycEVoc21tbGhNZ0dBQlpCWUFNQUFBQUFBTUMxTWtRMnJaUVEyUURBM1Fsc0FBQUFBQUFBbUVPR3lLYVZFaUliQUxncmdRMEFBQUFBQUFCenlSRFp0RkpDWkFNQWR5T3dBUUFBQUFBQVlFNFpJcHRXU29oc0FPQXVCRFlBQUFBQUFBRE1MVU5rMDBvSmtRMEEzSnpBQmdBQUFBQUFnQll5UkRhdGxCRFpBTUJOQ1d3QUFBQUFBQUJvSlVOazAwb0prUTBBM0l6QUJnQUFBQUFBZ0pZeVJEYXRsQkRaQU1CTkNHd0FBQUFBQUFCb0xVTmswMG9Ka1EwQU5DZXdBUUFBQUFBQTRCWXlSRGF0bEJEWkFFQlRBaHNBQUFBQUFBQnVKVU5rMDBvSmtRMEFOQ093QVFBQUFBQUE0Sll5UkRhdGxCRFpBRUFUQWhzQUFBQUFBQUJ1TFVOazAwb0prUTBBekU1Z0F3QUFBQUFBd0Qxa2lHeGFLU0d5QVlCWkNXd0FBQUFBQUFDNGx3eVJUU3NsUkRZQU1CdUJEUUFBQUFBQUFQZVVJYkpwcFlUSUJnQm1JYkFCQUFBQUFBRGczakpFTnEyVUVOa0F3TlVFTmdBQUFBQUFBQ3hCaHNpbWxSSWlHd0M0aXNBR0FBQUFBQUNBcGNnUTJiUlNRbVFEQUJjVDJBQUFBQUFBQUxBa0dTS2JWa3FJYkFEZ0lnSWJBQUFBQUFBQWxpWkRaTk5LQ1pFTkFKeE5ZQU1BQUFBQUFNQVNaWWhzV2lraHNnR0Fzd2hzQUFBQUFBQUFXS29Na1UwckpVUTJBSEF5Z1EwQUFBQUFBQUJMbGlHeWFhV0V5QVlBVGlLd0FRQUFBQUFBWU9reVJEYXRsQkRaQU1BdkNXd0FBQUFBQUFCWWd3eVJUU3NsUkRZQThGTUNHd0FBQUFBQUFOWWlRMlRUU2dtUkRRQzhTV0FEQUFBQUFBREFtbVNJYkZvcEliSUJnRmNKYkFBQUFBQUFBRmliREpGTkt5VkVOZ0R3QTRFTkFBQUFBQUFBYTVRaHNtbWxoTWdHQUw0aHNBRUFBQUFBQUdDdE1rUTJyWlFRMlFEQVB3UTJBQUFBQUFBQXJGbUd5S2FWRWlJYkFQZy9nUTBBQUFBQUFBQnJseUd5YWFXRXlBWUFCRFlBQUFBQUFBQjBJVU5rMDBvSmtRMEFHeWV3QVFBQUFBQUFvQmNaSXB0V1NvaHNBTmd3Z1EwQUFBQUFBQUE5eVJEWnRGSkNaQVBBUmdsc0FBQUFBQUFBNkUyR3lLYVZFaUliQURaSVlBTUFBQUFBQUVDUE1rUTJyWlFRMlFDd01RSWJBQUFBQUFBQWVwVWhzbW1saE1nR2dBMFIyQUFBQUFBQUFOQ3pESkZOS3lWRU5nQnNoTUFHQUFBQUFBQ0EzbVdJYkZvcEliSUJZQU1FTmdBQUFBQUFBR3hCaHNpbWxSSWlHd0E2SjdBQkFBQUFBQUJnS3pKRU5xMlVFTmtBMERHQkRRQUFBQUFBQUZ1U0liSnBwWVRJQm9CT0NXd0FBQUFBQUFEWW1neVJUU3NsUkRZQWRFaGdBd0FBQUFBQXdCWmxpR3hhS1NHeUFhQXpBaHNBQUFBQUFBQzJLa05rMDBvSmtRMEFIUkhZQUFBQUFBQUFzR1VaSXB0V1NvaHNBT2pFL3dSZzc5Nk81RGlTTkl6K0Q2dklhckFVQVNKUUF4OFJxTUdNQkRzaXVBZ1VnYU5CaXdBUnNCb3NDbWlRQU5FSTlLVzhLaS9ubUlYVnUyYzl1RmwrbGlHd0FRQUFBQUFBNE93Nklwc3BGWkVOQUFjZ3NBRUFBQUFBQUFDUnphU0t5QWFBblJQWUFBQUFBQUFBd0djZGtjMlVpc2dHZ0IwVDJBQUFBQUFBQU1CZk9pS2JLUldSRFFBN0piQUJBQUFBQUFDQWIzVkVObE1xSWhzQWRraGdBd0FBQUFBQUFOL3JpR3ltVkVRMkFPeU13QVlBQUFBQUFBQ2UxaEhaVEttSWJBRFlFWUVOQUFBQUFBQUEvRmhIWkRPbElySUJZQ2NFTmdBQUFBQUFBTERXRWRsTXFZaHNBTmdCZ1EwQUFBQUFBQUQ4WEVka002VWlzZ0ZnNHdRMkFBQUFBQUFBOER3ZGtjMlVpc2dHZ0EwVDJBQUFBQUFBQU1EemRVUTJVeW9pR3dBMlNtQURBQUFBQUFBQUw5TVIyVXlwaUd3QTJDQ0JEUUFBQUFBQUFMeGNSMlF6cFNLeUFXQmpCRFlBQUFBQUFBRHdPaDJSelpTS3lBYUFEUkhZQUFBQUFBQUF3T3QxUkRaVEtpSWJBRFpDWUFNQUFBQUFBQUJ2MHhIWlRLbUliQURZQUlFTkFBQUFBQUFBdkYxSFpET2xJcklCNE00RU5nQUFBQUFBQUhBZEhaSE5sSXJJQm9BN0V0Z0FBQUFBQUFEQTlYUkVObE1xSWhzQTdrUmdBd0FBQUFBQUFOZlZFZGxNcVloc0FMZ0RnUTBBQUFBQUFBQmNYMGRrTTZVaXNnSGd4Z1EyQUFBQUFBQUFNS01qc3BsU0Vka0FjRU1DR3dBQUFBQUFBSmpURWRsTXFZaHNBTGdSZ1EwQUFBQUFBQURNNm9oc3BsUkVOZ0RjZ01BR0FBQUFBQUFBNW5WRU5sTXFJaHNBaGdsc0FBQUFBQUFBNERZNklwc3BGWkVOQUlNRU5nQUFBQUFBQUhBN0haSE5sSXJJQm9BaEFoc0FBQUFBQUFDNHJZN0laa3BGWkFQQUFJRU5BQUFBQUFBQTNGNUhaRE9sSXJJQjRNb0VOZ0FBQUFBQUFIQWZIWkhObElySUJvQXJFdGdBQUFBQUFBREEvWFJFTmxNcUloc0Fya1JnQXdBQUFBQUFBUGZWRWRsTXFZaHNBTGdDZ1EwQUFBQUFBQURjWDBka002VWlzZ0hnalFRMkFBQUFBQUFBc0EwZGtjMlVpc2dHZ0RjUTJBQUFBQUFBQU1CMmRFUTJVeW9pR3dCZVNXQURBQUFBQUFBQTI5SVIyVXlwaUd3QWVBV0JEUUFBQUFBQUFHeFBSMlF6cFNLeUFlQ0ZCRFlBQUFBQUFBQ3dUUjJSelpTS3lBYUFGeERZQUFBQUFBQUF3SFoxUkRaVEtpSWJBSjVKWUFNQUFBQUFBQURiMWhIWlRLbUliQUI0Qm9FTkFBQUFBQUFBYkY5SFpET2xJcklCNENjRU5nQUFBQUFBQUxBUEhaSE5sSXJJQm9BRmdRMEFBQUFBQUFEc1IwZGtNNlVpc2dIZ0J3UTJBQUFBQUFBQXNDOGRrYzJVaXNnR2dDY0liQUFBQUFBQUFHQi9PaUtiS1JXUkRRQi9JN0FCQUFBQUFBQ0FmZXFJYktaVVJEWUFmRVZnQXdBQUFBQUFBUHZWRWRsTXFZaHNBSGdrc0FFQUFBQUFBSUI5NjRoc3BsUkVOZ0JFWUFNQUFBQUFBQUJIMEJIWlRLbUliQUJPVDJBREFBQUFBQUFBeDlBUjJVeXBpR3dBVGsxZ0F3QUFBQUFBQU1mUkVkbE1xWWhzQUU1TFlBTUFBQUFBQUFESDBoSFpUS21JYkFCT1NXQURBQUFBQUFBQXg5TVIyVXlwaUd3QVRrZGdBd0FBQUFBQUFNZlVFZGxNcVloc0FFNUZZQU1BQUFBQUFBREgxUkhaVEttSWJBQk9RMkFEQUFBQUFBQUF4OVlSMlV5cGlHd0FUa0ZnQXdBQUFBQUFBTWZYRWRsTXFZaHNBQTVQWUFNQUFBQUFBQURuMEJIWlRLbUliQUFPVFdBREFBQUFBQUFBNTlFUjJVeXBpR3dBRGt0Z0F3QUFBQUFBQU9mU0VkbE1xWWhzQUE1SllBTUFBQUFBQUFEbjB4SFpUS21JYkFBT1IyQURBQUFBQUFBQTU5UVIyVXlwaUd3QURrVmdBd0FBQUFBQUFPZlZFZGxNcVloc0FBNURZQU1BQUFBQUFBRG4xaEhaVEttSWJBQU9RV0FEQUFBQUFBQUFkRVEyVXlvaUc0RGRFOWdBQUFBQUFBQUFGeDJSelpTS3lBWmcxd1EyQUFBQUFBQUF3QmNka2MyVWlzZ0dZTGNFTmdBQUFBQUFBTURYT2lLYktSV1JEY0F1Q1d3QUFBQUFBQUNBdit1SWJLWlVSRFlBdXlPd0FRQUFBQUFBQUo3U0VkbE1xWWhzQUhaRllBTUFBQUFBQUFEOFNFZGtNNlVpc2dIWURZRU5BQUFBQUFBQXNOSVIyVXlwaUd3QWRrRmdBd0FBQUFBQUFQeE1SMlF6cFNLeUFkZzhnUTBBQUFBQUFBRHdIQjJSelpTS3lBWmcwd1EyQUFBQUFBQUF3SE4xUkRaVEtpSWJnTTBTMkFBQUFBQUFBQUF2MFJIWlRLbUliQUEyU1dBREFBQUFBQUFBdkZSSFpET2xJcklCMkJ5QkRRQUFBQUFBQVBBYUhaSE5sSXJJQm1CVEJEWUFBQUFBQUFEQWEzVkVObE1xSWh1QXpSRFlBQUFBQUFBQUFHL1JFZGxNcVloc0FEWkJZQU1BQUFBQUFBQzhWVWRrTTZVaXNnRzRPNEVOQUFBQUFBQUFjQTBka2MyVWlzZ0c0SzRFTmdBQUFBQUFBTUMxZEVRMlV5b2lHNEM3RWRnQUFBQUFBQUFBMTlRUjJVeXBpR3dBN2tKZ0F3QUFBQUFBQUZ4YlIyUXpwU0t5QWJnNWdRMEFBQUFBQUFBd29TT3ltVklSMlFEY2xNQUdBQUFBQUFBQW1OSVIyVXlwaUd3QWJrWmdBd0FBQUFBQUFFenFpR3ltVkVRMkFEY2hzQUVBQUFBQUFBQ21kVVEyVXlvaUc0QnhBaHNBQUFBQUFBRGdGam9pbXlrVmtRM0FLSUVOQUFBQUFBQUFjQ3Nka2MyVWlzZ0dZSXpBQmdBQUFBQUFBTGlsanNobVNrVmtBekJDWUFNQUFBQUFBQURjV2tka002VWlzZ0c0T29FTkFBQUFBQUFBY0E4ZGtjMlVpc2dHNEtvRU5nQUFBQUFBQU1DOWRFUTJVeW9pRzRDckVkZ0FBQUFBQUFBQTk5UVIyVXlwaUd3QXJrSmdBd0FBQUFBQUFOeGJSMlF6cFNLeUFYZ3pnUTBBQUFBQUFBQ3dCUjJSelpTS3lBYmdUUVEyQUFBQUFBQUF3RlowUkRaVEtpSWJnRmNUMkFBQUFBQUFBQUJiMGhIWlRLbUliQUJlUldBREFBQUFBQUFBYkUxSFpET2xJcklCZURHQkRRQUFBQUFBQUxCRkhaSE5sSXJJQnVCRkJEWUFBQUFBQUFEQVZuVkVObE1xSWh1QVp4UFlBQUFBQUFBQUFGdldFZGxNcVloc0FKNUZZQU1BQUFBQUFBQnNYVWRrTTZVaXNnSDRLWUVOQUFBQUFBQUFzQWNka2MyVWlzZ0dZRWxnQXdBQUFBQUFBT3hGUjJRenBTS3lBZmdoZ1EwQUFBQUFBQUN3SngyUnpaU0t5QWJnU1FJYkFBQUFBQUFBWUc4Nklwc3BGWkVOd0hjRU5nQUFBQUFBQU1BZWRVUTJVeW9pRzRCdkNHd0FBQUFBQUFDQXZlcUliS1pVUkRZQWZ4TFlBQUFBQUFBQUFIdldFZGxNcVloc0FENFIyQUFBQUFBQUFBQjcxeEhaVEttSWJBQUVOZ0FBQUFBQUFNQWhkRVEyVXlvaUcrRGtCRFlBQUFBQUFBREFVWFJFTmxNcUlodmd4QVEyQUFBQUFBQUF3SkYwUkRaVEtpSWI0S1FFTmdBQUFBQUFBTURSZEVRMlV5b2lHK0NFQkRZQUFBQUFBQURBRVhWRU5sTXFJaHZnWkFRMkFBQUFBQUFBd0ZGMVJEWlRLaUliNEVRRU5nQUFBQUFBQU1DUmRVUTJVeW9pRytBa0JEWUFBQUFBQUFEQTBYVkVObE1xSWh2Z0JBUTJBQUFBQUFBQXdCbDBSRFpUS2lJYjRPQUVOZ0FBQUFBQUFNQlpkRVEyVXlvaUcrREFCRFlBQUFBQUFBREFtWFJFTmxNcUlodmdvQVEyQUFBQUFBQUF3TmwwUkRaVEtpSWI0SUFFTmdBQUFBQUFBTUFaZFVRMlV5b2lHK0JnQkRZQUFBQUFBQURBV1hWRU5sTXFJaHZnUUFRMkFBQUFBQUFBd0psMVJEWlRLaUliNENBRU5nQUFBQUFBQU1EWmRVUTJVeW9pRytBQUJEWUFBQUFBQUFBQUlwdEpGWkVOc0hNQ0d3QUFBQUFBQUlEUE9pS2JLUldSRGJCakFoc0FBQUFBQUFDQXYzUkVObE1xSWh0Z3B3UTJBQUFBQUFBQUFOL3FpR3ltVkVRMndBNEpiQUFBQUFBQUFBQysxeEhaVEttSWJJQ2RFZGdBQUFBQUFBQUFQSzBqc3BsU0Vka0FPeUt3QVFBQUFBQUFBUGl4anNobVNrVmtBK3lFd0FZQUFBQUFBQUJnclNPeW1WSVIyUUE3SUxBQkFBQUFBQUFBK0xtT3lHWktSV1FEYkp6QUJ2amFQeCtYUXdBQUFBQUFBTDdYRWRsTXFZaHNnQTBUMkFCL2Qxa0svMjBNQUFBQUFBQUFUK3FJYktaVVJEYkFSZ2xzZ0tmOFpqRUVBQUFBQUFENG9ZNTNLVk1xSWh0Z2d3UTJ3R294L1BYaitXQVVBQUFBQUFBQTMrbUliS1pVUkRiQXhnaHNnSlhmUDU1M0Vka0FBQUFBQUFBOHBTT3ltVklSMlFBYklyQUJmdWJoNC9udngxOEFBQUFBQUFDKzFSSFpUS21JYklDTkVOZ0F6M0g1Z3MzbFN6Wi9HQVVBQUFBQUFNQjNPaUtiS1JXUkRiQUJBaHZndWI1RU5tMFVBQUFBQUFBQTMrbUliS1pVUkRiQW5RbHNnSmU2TEliL01nWUFBQUFBQUlEdmRFUTJVeW9pRytDT0JEYkFhL3pUY2dnQUFBQUFBUENranZjb1V5b2lHK0JPQkRiQVc1YkR5NVZSSDR3Q0FBQUFBQURnR3gyUnpaU0t5QWE0QTRFTjhCWi9SR1FEQUFBQUFBRHdsSTdJWmtwRlpBUGNtTUFHZUt1SGorZS9IMzhCQUFBQUFBRDRTMGRrTTZVaXNnRnVTR0FEWE1QbEN6YVhMOW44WVJRQUFBQUFBQURmNkloc3BsUkVOc0NOQ0d5QWEva1MyYlJSQUFBQUFBQUFmS01qc3BsU0Vka0FOeUN3QWE3dHNoeit5eGdBQUFBQUFBQyswUkhaVEttSWJJQmhBaHRnd2o4dGlBQUFBQUFBQU4vcGVJY3lwU0t5QVFZSmJJREpCZkZ5WmRRSG93QUFBQUFBQVBoVFIyUXpwU0t5QVlZSWJJQkpmK1J6WlBQZUtBQUFBQUFBQVA3VUVkbE1xWWhzZ0FFQ0cyRGF3OGZ6eStNdkFBQUFBQUFBbjNWRU5sTXFJaHZneWdRMndDMWNyb202Zk1ubWQ2TUFBQUFBQUFENFUwZGtNNlVpc2dHdVNHQUQzTW9sc3ZuMWNWRUVBQUFBQUFEZ3M0N0laa3BGWkFOY2ljQUd1TFhMZ3ZpYk1RQUFBQUFBQVB5cEk3S1pVaEhaQUZjZ3NBSHU0ZCtXUkFBQUFBQUFnRzkwdkQrWlVoSFpBRzhrc0FIdXVTVCtrczlYUndFQUFBQUFBQ0N5bVZRUjJRQnZJTEFCN3VuaDQzbjM4YnczQ2dBQUFBQUFnRTg2SXBzcEZaRU44RW9DRytEZUxwSE5MNCsvQUFBQUFBQUFpR3dtVlVRMndDc0liSUF0dUZ3VGRmbVN6ZTlHQVFBQUFBQUE4RWxIWkRPbElySUJYa2hnQTJ6RkpiTDU5WEZaQkFBQUFBQUFRR1F6cVNLeUFWNUFZQU5zeldWSi9NMFlBQUFBQUFBQVB1bUliS1pVUkRiQU13bHNnQzM2OStPaStNRW9BQUFBQUFBQVJEYURLaUliNEJrRU5zQ1dGOFYzRWRrQUFBQUFBQUJjZEVRMlV5b2lHK0FuQkRiQWxqM2tjMlR6WUJRQUFBQUFBQUFpbTBFVmtRMndJTEFCdGs1a0F3QUFBQUFBOEplT3lHWktSV1FEL0lEQUJ0aUR5elZSN3g0WFJnQUFBQUFBZ0xQcmlHeW1WRVEyd0JNRU5zQmVmSGhjRk5zb0FBQUFBQUFBUkRhREtpSWI0RzhFTnNEZS9NT3lDQUFBQUFBQThFbkhlNU1wRlpFTjhCV0JEYkRuWmZHRFVRQUFBQUFBQUNmWEVkbE1xWS9uZjQwQnVCRFlBSHRlRnQ5RlpBTUFBQUFBQU5BUjJVejVIeU1BTGdRMndKNDk1SE5rODJBVUFBQUFBQURBeVhWRU5nQmpCRGJBM29sc0FBQUFBQUFBUHV1SWJBQkdDR3lBSTdoY0UvWHVjV2tFQUFBQUFBQTRzNDdJQnVEcUJEYkFVWHg0WEJiYktBQUFBQUFBZ0pQcmlHd0Fya3BnQXh6TlB5eU1BQUFBQUFBQUlodUFheExZQUVkZEdIL041Ni9hQUFBQUFBQUFuRlZIWkFOd0ZRSWI0S2grLzNqZVJXUURBQUFBQUFDY1cwZGs4eGIvTVFMZ1FtQURITm5EeC9QTDR5OEFBQUFBQU1CWmRVUTJBRzhpc0FHTzduMCtmOGxHWkFNQUFBQUFBSnhaUjJRRDhHb0NHK0FNTHRkRS9mSzRPQUlBQUFBQUFKeFZSMlFEOENvQ0crQk1MZ3ZqdjQwQkFBQUFBQUE0c1k3SUJ1REZCRGJBMmZ4bWFRUUFBQUFBQUU2dTQzMEp3SXNJYklDekxvMi81dlBWVVFBQUFBQUFBR2ZVRWRrQVBKdkFCamlyM3orZWR4SFpBQUFBQUFBQTU5VVIyUUE4aThBR09MT0hqK2NYWXdBQUFBQUFBRTZzSTdKWmVUQUM0RUpnQTV6ZGV5TUFBQUFBQUFCT3JpT3krUkczSVFDZkNHd0FBQUFBQUFBQTZJaHNBSDVJWUFNQUFBQUFBQURBUlVka0EvQWtnUTBBQUFBQUFBQUFYM1JFTmdEZkVkZ0FBQUFBQUFBQThMV095QWJnR3dJYkFBQUFBQUFBQVA2dUk3SUIrSlBBQmdBQUFBQUFBSUNuZEVRMkFKOEliQUFBQUFBQUFBRDRrYzY1STV2My9nTEFoY0FHQUFBQUFBQUFnSlhPZVNPYjl4NC9jQ0d3QVFBQUFBQUFBT0JuT3E2TEFrNU1ZQU1BQUFBQUFBREFjM1JFTnNCSkNXd0FBQUFBQUFBQWVLNk95QVk0SVlFTkFBQUFBQUFBQUMvUkVka0FKeU93QVFBQUFBQUFBT0NsT2lJYjRFUUVOZ0FBQUFBQUFBQzhSa2RrQTV5RXdBWUFBQUFBQUFDQTErb2NON0w1NFBFQ1h3aHNBQUFBQUFBQUFIaUx6akVqbXdlUEZ2aENZQU1BQUFBQUFBREFXM1ZjRndVY21NQUdBQUFBQUFBQWdHdm9pR3lBZ3hMWUFBQUFBQUFBQUhBdEhaRU5jRUFDR3dBQUFBQUFBQUN1cVNPeUFRNUdZQU1BQUFBQUFBREF0WFZFTnNDQkNHd0FBQUFBQUFBQW1OQVIyUUFISWJBQkFBQUFBQUFBWUVwSFpBTWNnTUFHQUFBQUFBQUFnRW1kZlVZMi8vSG9nQzhFTmdBQUFBQUFBQUJNNi9pU0RiQmpBaHNBQUFBQUFBQUFicUVqc2dGMlNtQURBQUFBQUFBQXdLMTBSRGJBRGdsc0FBQUFBQUFBQUxpbGpzZ0cyQm1CRFFBQUFBQUFBQUMzMWhIWkFEc2lzQUVBQUFBQUFBRGdIam9pRzJBbkJEWUFBQUFBQUFBQTNFdEhaQVBzZ01BR0FBQUFBQUFBZ0h2cWJET3llZkJvZ0M4RU5nQUFBQUFBQUFEY1cyZDdrYzBIandYNFFtQURBQUFBQUFBQXdCWjBYQmNGYkpUQUJnQUFBQUFBQUlDdDZJaHNnQTBTMkFBQUFBQUFBQUN3SlIyUkRiQXhBaHNBQUFBQUFBQUF0cVlqc2dFMlJHQURBQUFBQUFBQXdCWjFSRGJBUmdoc0FBQUFBQUFBQU5pcWpzZ0cyQUNCRFFBQUFBQUFBQUJiMXJsUFpQUEI2SUV2QkRZQUFBQUFBQUFBYkYzbjlwSE5nN0VEWHdoc0FBQUFBQUFBQU5pRGp1dWlnRHNSMkFBQUFBQUFBQUN3RngyUkRYQUhBaHNBQUFBQUFBQUE5cVFqc2dGdVRHQURBQUFBQUFBQXdONTBSRGJBRFFsc0FBQUFBQUFBQU5pampzZ0d1QkdCRFFBQUFBQUFBQUI3MVJIWkFEY2dzQUVBQUFBQUFBQmd6em9pRzJDWXdBWUFBQUFBQUFDQXZldGNON0w1dzBpQnJ3bHNBQUFBQUFBQUFEaUNqaS9aQUVNRU5nQUFBQUFBQUFBY1JVZGtBd3dRMkFBQUFBQUFBQUJ3SkIyUkRYQmxBaHNBQUFBQUFBQUFqcVlqc2dHdVNHQURBQUFBQUFBQXdCRjFSRGJBbFFoc0FBQUFBQUFBQURpcWpzZ0d1QUtCRFFBQUFBQUFBQUJIMWhIWkFHOGtzQUVBQUFBQUFBRGc2RG92aTJ3ZWpBejRtc0FHQUFBQUFBQUFnRFBvUEQreStUL2pBcjRtc0FFQUFBQUFBQURnTERxdWl3SmVRV0FEQUFBQUFBQUF3SmwwUkRiQUN3bHNBQUFBQUFBQUFEaWJqc2dHZUFHQkRRQUFBQUFBQUFCbjFCSFpBTThrc0FFQUFBQUFBQURnckRvaUcrQVpCRFlBQUFBQUFBQUFuRmxIWkFQOGhNQUdBQUFBQUFBQWdMUHJmQnZadkRjUzRHc0NHd0FBQUFBQUFBRDROcko1Ynh6QTEvN0xDQUFBQUFBQUFBRGdrellDNENrQ0d3QUFBQUFBQUFENFN4c0I4SGV1aUFJQUFBQUFBQUFBZ0FXQkRRQUFBQUFBQUFBQUxBaHNBQUFBQUFBQUFBQmdRV0FEQUFBQUFBQUFBQUFMQWhzQUFBQUFBQUFBQUZnUTJBQUFBQUFBQUFBQXdJTEFCZ0FBQUFBQUFBQUFGZ1EyQUFBQUFBQUFBQUN3SUxBQkFBQUFBQUFBQUlBRmdRMEFBQUFBQUFBQUFDd0liQUFBQUFBQUFBQUFZRUZnQXdBQUFBQUFBQUFBQ3dJYkFBQUFBQUFBQUFCWUVOZ0FBQUFBQUFBQUFNQ0N3QVlBQUFBQUFBQUFBQllFTmdBQUFBQUFBQUFBc0NDd0FRQUFBQUFBQUFDQUJZRU5BQUFBQUFBQUFBQXNDR3dBQUFBQUFBQUFBR0JCWUFNQUFBQUFBQUFBQUFzQ0d3QUFBQUFBQUFBQVdCRFlBQUFBQUFBQUFBREFnc0FHQUFBQUFBQUFBQUFXQkRZQUFBQUFBQUFBQUxBZ3NBRUFBQUFBQUFBQWdBV0JEUUFBQUFBQUFBQUFMQWhzQUFBQUFBQUFBQUJnUVdBREFBQUFBQUFBQUFBTEFoc0FBQUFBQUFBQUFGZ1EyQUFBQUFBQUFBQUF3SUxBQmdBQUFBQUFBQUFBRmdRMkFBQUFBQUFBQUFDd0lMQUJBQUFBQUFBQUFJQUZnUTBBQUFBQUFBQUFBQ3dJYkFBQUFBQUFBQUFBWUVGZ0F3QUFBQUFBQUFBQUN3SWJBQUFBQUFBQUFBQllFTmdBQUFBQUFBQUFBTUNDd0FZQUFBQUFBQUFBQUJZRU5nQUFBQUFBQUFBQXNDQ3dBUUFBQUFBQUFBQ0FCWUVOQUFBQUFBQUFBQUFzQ0d3QUFBQUFBQUFBQUdCQllBTUFBQUFBQUFBQUFBc0NHd0FBQUFBQUFBQUFXQkRZQUFBQUFBQUFBQURBZ3NBR0FBQUFBQUFBQUFBV0JEWUFBQUFBQUFBQUFMQWdzQUVBQUFBQUFBQUFnQVdCRFFBQUFBQUFBQUFBTEFoc0FBQUFBQUFBQUFCZ1FXQURBQUFBQUFBQUFBQUxBaHNBQUFBQUFBQUFBRmdRMkFBQUFBQUFBQUFBd0lMQUJnQUFBQUFBQUFBQUZnUTJBQUFBQUFBQUFBQ3dJTEFCQUFBQUFBQUFBSUFGZ1EwQUFBQUFBQUFBQUN3SWJBQUFBQUFBQUFBQVlFRmdBd0FBQUFBQUFBQUFDd0liQUFBQUFBQUFBQUJZRU5nQUFBQUFBQUFBQU1DQ3dBWUFBQUFBQUFBQUFCWUVOZ0FBQUFBQUFBQUFzQ0N3QVFBQUFBQUFBQUNBQllFTkFBQUFBQUFBQUFBc0NHd0FBQUFBQUFBQUFHQkJZQU1BQUFBQUFBQUFBQXNDR3dBQUFBQUFBQUFBV0JEWUFBQUFBQUFBQUFEQWdzQUdBQUFBQUFBQUFBQVdCRFlBQUFBQUFBQUFBTEFnc0FFQUFBQUFBQUFBZ0FXQkRRQUFBQUFBQUFBQUxBaHNBQUFBQUFBQUFBQmdRV0FEQUFBQUFBQUFBQUFMQWhzQUFBQUFBQUFBQUZnUTJBQUFBQUFBQUFBQXdJTEFCZ0FBQUFBQUFBQUFGZ1EyQUFBQUFBQUFBQUN3SUxBQkFBQUFBQUFBQUlBRmdRMEFBQUFBQUFBQUFDd0liQUFBQUFBQUFBQUFZRUZnQXdBQUFBQUFBQUFBQ3dJYkFBQUFBQUFBQUFCWUVOZ0FBQUFBQUFBQUFNQ0N3QVlBQUFBQUFBQUFBQllFTmdBQUFBQUFBQUFBc0NDd0FRQUFBQUFBQUFDQUJZRU5BQUFBQUFBQUFBQXNDR3dBQUFBQUFBQUFBR0JCWUFNQUFBQUFBQUFBQUFzQ0d3QUFBQUFBQUFBQVdCRFlBQUFBQUFBQUFBREFnc0FHQUFBQUFBQUFBQUFXQkRZQUFBQUFBQUFBQUxBZ3NBRUFBQUFBQUFBQWdBV0JEUUFBQUFBQUFBQUFMQWhzQUFBQUFBQUFBQUJnUVdBREFBQUFBQUFBQUFBTEFoc0FBQUFBQUFBQUFGZ1EyQUFBQUFBQUFBQUF3SUxBQmdBQUFBQUFBQUFBRmdRMkFBQUFBQUFBQUFDd0lMQUJBQUFBQUFBQUFJQUZnUTBBQUFBQUFBQUFBQ3dJYkFBQUFBQUFBQUFBWUVGZ0F3QUFBQUFBQUFBQUN3SWJBQUFBQUFBQUFBQllFTmdBQUFBQUFBQUFBTUNDd0FZQUFBQUFBQUFBQUJZRU5nQUFBQUFBQUFBQXNDQ3dBUUFBQUFBQUFBQ0FCWUVOQUFBQUFBQUFBQUFzQ0d3QUFBQUFBQUFBQUdCQllBTUFBQUFBQUFBQUFBc0NHd0FBQUFBQUFBQUFXQkRZQUFBQUFBQUFBQURBZ3NBR0FBQUFBQUFBQUFBV0JEWUFBQUFBQUFBQUFMQWdzQUVBQUFBQUFBQUFnQVdCRFFBQUFBQUFBQUFBTEFoc0FBQUFBQUFBQUFCZ1FXQURBQUFBQUFBQUFBQUxBaHNBQUFBQUFBQUFBRmdRMkFBQUFBQUFBQUFBd0lMQUJnQUFBQUFBQUFBQUZnUTJBQUFBQUFBQUFBQ3dJTEFCQUFBQUFBQUFBSUFGZ1EwQUFBQUFBQUFBQUN3SWJBQUFBQUFBQUFBQVlFRmdBd0FBQUFBQUFBQUFDd0liQUFBQUFBQUFBQUJZRU5nQUFBQUFBQUFBQU1DQ3dBWUFBQUFBQUFBQUFCWUVOZ0FBQUFBQUFBQUFzQ0N3QVFBQUFBQUFBQUNBQllFTkFBQUFBQUFBQUFBc0NHd0FBQUFBQUFBQUFHQkJZQU1BQUFBQUFBQUFBQXNDR3dBQUFBQUFBQUFBV0JEWUFBQUFBQUFBQUFEQWdzQUdBQUFBQUFBQUFBQVdCRFlBQUFBQUFBQUFBTEFnc0FFQUFBQUFBQUFBZ0FXQkRRQUFBQUFBQUFBQUxBaHNBQUFBQUFBQUFBQmdRV0FEQUFBQUFBQUFBQUFMQWhzQUFBQUFBQUFBQUZnUTJBQUFBQUFBQUFBQXdJTEFCZ0FBQUFBQUFBQUFGZ1EyQUFBQUFBQUFBQUN3SUxBQkFBQUFBQUFBQUlBRmdRMEFBQUFBQUFBQUFDd0liQUFBQUFBQUFBQUFZRUZnQXdBQUFBQUFBQUFBQ3dJYkFBQUFBQUFBQUFCWUVOZ0FBQUFBQUFBQUFNQ0N3QVlBQUFBQUFBQUFBQllFTmdBQUFBRC96OTRkMWNhTmhtRVk5VVdKRkVJZ0JFSWdESVF3YUJrRWdwZEJJSFFaRElSQUNJVDlMWSswbFhiMXRFMW1rckhuSE9tVDc5L3JSLzRCQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFnUEtYQ1FBQUFBQUF1SFVDR3dBQW9NempEdU5lVFFFQUFBQUF3SzBTMkFBQUFMOHlqN3VmUkRZQUFBQUFBTndvZ1EwQUFQQTdqdVB1VGw4QUFBQUFBTGdwQWhzQUFPQjN2VXpybjJ4K21BSUFBQUFBZ0ZzaXNBRUFBUDdFOGt6VUV0bk1wZ0FBQUFBQTRGWUliQUFBZ0xjNGpIczBBd0FBQUFBQXQwQmdBd0FBdk5YVHRJWTJBQUFBQUFDd2F3SWJBQURnUGVaeGQ5UDZkQlFBQUFBQUFPeVN3QVlBQUhpdjQ3ajcweGNBQUFBQUFIWkhZQU1BQUp5RHlBWUFBQUFBZ04wUzJBQUFBT2V5UEJPMVBCYzFtd0lBQUFBQWdEMFIyQUFBQU9kMkdQZmREQUFBQUFBQTdJWEFCZ0FBdUlSdjB4cmFBQUFBQUFEQTVnbHNBQUNBUzVtbjljbW9WMU1BQUFBQUFMQmxBaHNBQU9DU2p1UHVUMThBQUFBQUFOZ2tnUTBBQUhCcEloc0FBQUFBQURaTllBTUFBSHlFNVptbzVibW8yUlFBQUFBQUFHeU53QVlBQVBoSWgzSGZ6UUFBQUFBQXdKWUliQUFBZ0kvMmJWcERHd0FBQUFBQTJBU0JEUUFBOEJubWNmZlQrblFVQUFBQUFBQmNOWUVOQUFEd1dYNU1hMlR6WWdvQUFBQUFBSzZad0FZQUFQaE14M0YzcHk4QUFBQUFBRndsZ1EwQUFQRFpsbWVpbGovWnpLWUFBQUFBQU9BYUNXd0FBSUJyc0VRMmgzRlBwZ0FBQUFBQTROb0liQUFBZ0d2eU9LMmhEUUFBQUFBQVhBMkJEUUFBY0czbWFYMHk2dFVVQUFBQUFBQmNBNEVOQUFCd2pYNU1hMlR6WWdvQUFBQUFBRDZid0FZQUFMaFd4M0YzcHk4QUFBQUFBSHdhZ1EwQUFIRE5sbWVpbGovWnpLWUFBQUFBQU9DekNHd0FBSUJydDBRMmgwbGtBd0FBQUFEQUp4SFlBQUFBVzNFNEhRQUFBQUFBZkNpQkRRQUFzQ1h6dUlkcC9hc05BQUFBQUFCOENJRU5BQUN3TmMvajdpZVJEUUFBQUFBQUgwUmdBd0FBYk5GeDNOZlRGd0FBQUFBQUxrcGdBd0FBYk5YeUI1dmxUemJQcGdBQUFBQUE0SklFTmdBQXdKWXRrYzNEdU5rVUFBQUFBQUJjaXNBR0FBRFlnOFBwQUFBQUFBRGc3QVEyQUFEQVhzelQramViVjFNQUFBQUFBSEJPQWhzQUFHQlBuc2ZkVHlJYkFBQUFBQURPU0dBREFBRHN6WEhjMTlNWEFBQUFBQURlVFdBREFBRHMwZklIbStWUE5zK21BQUFBQUFEZ3ZRUTJBQURBWGkyUnpjTzQyUlFBQUFBQUFMeUh3QVlBQU5pN3c3aEhNd0FBQUFBQThGWUNHd0FBNEJZOFRXdG84Mm9LQUFBQUFBRCtsTUFHQUFDNEZmTzQrMGxrQXdBQUFBREFIeExZQUFBQXQrUTQ3dTcwQlFBQUFBQ0EzeUt3QVFBQWJzM0x0UDdKNW9jcEFBQUFBQUQ0SFFJYkFBRGdGaTNQUkMyUnpXd0tBQUFBQUFCK1JXQURBQURjc3NPNFJ6TUFBQUFBQUZBRU5nQUF3SzE3bXRiUTV0VVVBQUFBQUFEOEg0RU5BQURBK2xUVThtU1V5QVlBQUFBQWdQOFEyQUFBQUt5TzQrN0cvVzBLQUFBQUFBQitKckFCQUFENDE4dTRiMllBQUFBQUFPQm5BaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFBQUFBQUFnQ0d3QUFBQUFBQUFBQUNBSWJBQUFBQUFBQUFBQUlBaHNBQUFBQUFBQUFBQWdDR3dBQUFBQUFBQUFBQ0FJYkFBQUFBQUFBQUFBSUFoc0FBQUFBQUFBQUFBZ0NHd0FBQUFBQUFBQUFDQUliQUFBQUFBQUFBQUFJQWhzQUFBQUFic0hSQkFBQUFNQmJDV3dBQUFBQTJMdDUzS01aQUFBQWdMY1MyQUFBQUFDd1ovTzRneGtBQUFDQTl4RFlBQUFBQUxCWDN5ZHhEUUFBQUhBR1gwd0FBQUFBd0E0dFljMXNCZ0FBQU9BYy9NRUdBQUFBZ0wwUjF3QUFBQUJuSmJBQkFBQUFZRS9FTlFBQUFNRFpDV3dBQUFBQTJJUFhjUStUdUFZQUFBQzRnQzhtQUFBQUFHRGpscmptZnR6UkZBQUFBTUFsK0lNTkFBQUFBRnNtcmdFQUFBQXVUbUFEQUFBQXdGYUphd0FBQUlBUEliQUJBQUFBWUl1V3FFWmNBd0Q4dzg2OTNUUVFRMUVVTlpJYlN3a3BJYVdrQTBwd0NaUkFDU2xsT2dpMlJCQUk0anhJWnV6eFd0SnQ0SHh2WFFDQVdVUVRBQUFBQU5DWlUxd3ptUUlBQUFDWWd3ODJBQUFBQVBSRVhBTUFBQURNVG1BREFBQUFRQy9FTlFBQUFNQWlCRFlBQUFBQTlPQXRpR3NBQUFDQWhRaHNBQUFBQUdoZHlyY040aG9BQUFCZ0lRSWJBQUFBQUZxVzh1M01BQUFBQUN4SllBTUFBQUJBcTFJUTF3QUFBQUFORU5nQUFBQUEwS0o5RU5jQUFBQUFqWWdtQUFBQUFLQXhKYXhKWmdBQUFBQmE0WU1OQUFBQUFDMFIxd0FBQUFETkVkZ0FBQUFBMEFweERRQUFBTkFrZ1EwQUFBQUFTNXZ5YllPNEJnQUFBR2hVTkFFQUFBQUFDeXB4elNiZndSUUFBQUJBcTN5d0FRQUFBR0FwNGhvQUFBQ2dDd0liQUFBQUFKWWdyZ0VBQUFDNkliQUJBQUFBWUc0bHFoSFhBQUFBQU4ySUpnQUFBQUJnUnFlNFpqSUZBQUFBMEFzZmJBQUFBQUNZaTdnR0FBQUE2SkxBQmdBQUFJQTVpR3NBQUFDQWJnbHNBQUFBQUhpMnR5Q3VBUUFBQURvbXNBRUFBQURnbVZLK2JSRFhBQUFBQUIwVDJBQUFBQUR3TENuZnpnd0FBQUJBN3dRMkFBQUFBRHhEQ3VJYUFBQUFZQ1VFTmdBQUFBQTgyajZJYXdBQUFJQVZpU1lBQUFBQTRJRktXSlBNQUFBQUFLeUpEellBQUFBQVBJcTRCZ0FBQUZnbGdRMEFBQUFBanlDdUFRQUFBRlpMWUFNQUFBREFmMHo1dGtGY0F3QUFBS3hZTkFFQUFBQUFkeXB4elNiZndSUUFBQURBbXZsZ0F3QUFBTUE5eERVQUFBREFNQVEyQUFBQUFOeEtYQU1BQUFBTVJXQURBQUFBd0MxS1ZDT3VBUUFBQUlZU1RRQUFBQURBbFU1eHpXUUtBQUFBWUNRKzJBQUFBQUJ3RFhFTkFBQUFNQ3lCRFFBQUFBQ1hpR3NBQUFDQW9RbHNBQUFBQUtoNUQrSWFBQUFBWUhBQ0d3QUFBQURPU1VGY0F3QUFBQ0N3QVFBQUFPQlBLZC9PREFBQUFBQUNHd0FBQUFCK1MwRmNBd0FBQVBCRllBTUFBQURBZDY5QlhBTUFBQUR3UXpRQkFBQUFBSjlLV0pQTUFBQUFBUENURHpZQUFBQUFGT0lhQUFBQWdETUVOZ0FBQUFDSWF3QUFBQUFxQkRZQUFBQUE0NXFDdUFZQUFBRGdvbWdDQUFBQWdDR1Z1R2FUNzJBS0FBQUFnRG9mYkFBQUFBREdJNjRCQUFBQXVNSEw4WGkwQWdBQUFBQUFBQUFBbk9HRERRQUFBQUFBQUFBQVZBaHNBQUFBQUFBQUFBQ2dRbUFEQUFBQUFBQUFBQUFWQWhzQUFBQUFBQUFBQUtnUTJBQUFBQUFBQUFBQVFJWEFCZ0FBQUFBQUFBQUFLZ1EyQUFBQUFBQUFBQUJRSWJBQkFBQUFBQUFBQUlDS0R3SGF0UU1CQUFBQUFFSCsxaHRNVUJ3Sk5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBaG1BREFBQUFBQUFBQUFCRHNBRUFBQUFBQUFBQWdDSFlBQUFBQUFBQUFBREFFR3dBQUFBQUFBQUFBR0FJTmdBQUFBQUFBQUFBTUFRYkFBQUFBQUFBQUFBWWdnMEFBQUFBQUFBQUFBekJCZ0FBQUFBQUFBQUFobUFEQUFBQUFBQUFBQUJEc0FFQUFBQUFBQUFBZ0NIWUFBQUFBQUFBQUFEQUVHd0FBQUFBQUFBQUFHQUlOZ0FBQUFBQUFBQUFNQVFiQUFBQUFBQUFBQUFZZ2cwQUFBQUFBQUFBQUF6QkJnQUFBQUFBQUFBQWhtQURBQUFBQUFBQUFBQkRzQUVBQUFBQUFBQUFnQ0hZQUFBQUFBQUFBQURBRUd3QUFBQUFBQUFBQUdBSU5nQUFBQUFBQUFBQU1BUWJBQUFBQUFBQUFBQVlnZzBBQUFBQUFBQUFBQXpCQmdBQUFBQUFBQUFBUnRYOG5FK0FVY2s0QUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIwMDc2NjMxYmQ0YTA0MjdmNTc3MzBlYzcxYzllMDI3OSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZSwiY3JlZE1nbXQiOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjh9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0xMC0yMCIsInVybCI6Imh0dHBzOi8vd3d3Lmh5cHIuY29tLyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiSFlQUiBGSURPMiBNb2JpbGUgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjIxMDIwMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMTAtMjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTAxLTExIn0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiNTU2ZDI3ZjM4YjIzMWJiM2Q4MThiZmMxYjYxNWYyNjBmNmIwOGYyMCJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyI1NTZkMjdmMzhiMjMxYmIzZDgxOGJmYzFiNjE1ZjI2MGY2YjA4ZjIwIl0sImRlc2NyaXB0aW9uIjoiTUsgS2V5cGFzcyBTMSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjF9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUIrekNDQWFLZ0F3SUJBZ0lKQUk5Z2luMUFEMytETUFvR0NDcUdTTTQ5QkFNQ01Ga3hDekFKQmdOVkJBWVRBbFpPTVJNd0VRWURWUVFJREFwT2IzSjBhQ0JUYVdSbE1RNHdEQVlEVlFRSERBVklZVTV2YVRFUk1BOEdBMVVFQ2d3SVRVc2dSM0p2ZFhBeEVqQVFCZ05WQkFNTUNXMXJMbU52YlM1MmJqQWVGdzB4T0RFeU1qUXdNekV3TlRGYUZ3MHlPREV5TWpFd016RXdOVEZhTUZreEN6QUpCZ05WQkFZVEFsWk9NUk13RVFZRFZRUUlEQXBPYjNKMGFDQlRhV1JsTVE0d0RBWURWUVFIREFWSVlVNXZhVEVSTUE4R0ExVUVDZ3dJVFVzZ1IzSnZkWEF4RWpBUUJnTlZCQU1NQ1cxckxtTnZiUzUyYmpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk8xcndpM05rbVd6ZDBPR0o1T09jYU1ScXdWOFpEaVhUQzV1UXhVMnVQaElSNUN4VVU3QjcxZG5zZ0xpajVua2FaRWE5aGtmMkp6NmYvaWgzK0h4REVtalV6QlJNQjBHQTFVZERnUVdCQlJWYlNmeml5TWJzOWdZdjhHMkZmSmc5ckNQSURBZkJnTlZIU01FR0RBV2dCUlZiU2Z6aXlNYnM5Z1l2OEcyRmZKZzlyQ1BJREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJQkVQZW1hL2p0YU8xLzFxZVdNNlNyckp0R0JsY25HQ0pkazN0RmVaTnpDdEFpQXpDaU5XQmJyUTJLbEtzdys3UXEveDFBYnpVdncrU3lXbFBuSjBtVXJET3c9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFoWUFBQURmQkFNQUFBQllFWWUxQUFBQUcxQk1WRVVBVEpoQWViS0Fwc3kvMHVYZXUxem16SVh2M2E3Mzd0Yi8vLy9MWm42U0FBQVB5RWxFUVZSNDJ1MmRUWktqT2hMSEFXKzhWRlJ0V0ZMMGhpWDJiRGhBZGI4TDlHSU84R0ptRGpBeDhaWklldDNOc2NjSUJQcElTU2tNMWVDeUYxM1JHQXZwUnlyL3FRK1NKTkUrcHk3OCtmV3VmNzZCWjlIRS9LaGw4K0oySUd1NlhYM01DaU9xOXdQRm9yWlk1QW9LSW82a3phNVpJQXpqTzRvRnNWZ29YOTZzb2l6ZmNHYjQrMWlrMFdZQnMrQVdpa3p0UDhJaW1HWXIrMk1ScnQyZktCYXRWZkJadFpscVpKTHRta1VhNlRrZExJckU3WW5ZMURmcXBOa3ppNUJoL0JmSHdzZjRSb0NYdDA5MW8zTGVOWXNzMGl4QUZsNUZKVm52S2dRZWt1MmFoZDlzZitCWWVCWDFaZ3hNNkVoMU8yL2ZMRTR4Z3VwZzRWTlVsdlNkb3ovcGZMT2ZadGNzZk5VRHpBSml3WHc5citjZ1dCUm53V1hYTEU0eG5oTmswZnE2U0R1eTRQM0J2Yk5JWWp3bnlNS25xRjJiU2NOcGhPL1lONHM4eGl3QUZ0d2J0VXdzWHJzRHNIREdXKzg0RnY0eDZzQ2lMSVN0N0o2Rnl6QitJRm5ZaWxwMXRyOFFnSGJ2TDF5RzhSM0p3anRHdlZuTndLSk8rOTYwZXhhd3JQNTh4N0ZnL2xoV3hoZkQzMmIzTEU1b3p3bXdhUDE5cnRkU0VWL2NydEx1UE81MEdjYXZkeVFMRWlpTm5BWVd0MDVTWkFkZ2NVS2JoY1dDaDl5UEdLZjJuYVhrT3grbk9nM2pPNUlGOVUzakRDZmtFNVhxQ0N4eW5LQUNMUHlLT25TaVpyU2d0RHNDaXhSckZoYUxjRXhmRDhMQ3ljN25PMTJHOGZNZHlZSWhmQTlKMHFxN2tuMlpoWWRGaXZPY0Zvc1dFY1V5L0dyTUxsam92ZnpYTzVZRndlanpNTWRYZFVkaG9abjIzMWdXSEJuUWwyWFpkWWRob2QzUDcxZ1dRVVhkN3lmQkdjYVBkeXlMSXFpb2gyU2hHTWFmYUJaSi9LcmtJVmprQ0JVeFdMQzRhZlhqc0VqaiswZ2R2MEI3REJaS083QytrOFF0UFIySUJjb3d2bmtWTmVzZWhJVmlHRGdXQjFiVUlJdFRaQXgrWUVVTnNwaDcreThVaXdNcmFwZ0Z3akMrK2JySTZZRll6SWJ4RThIaXlJcUtZSEdPbWVNaitLWFovYk1nQzJUMTIyTW9xc1hpeTRKNDY1dG5HdWQ4WUJaVjdUR000RnBSY2VDZ0UyREJQWVl4eXVyWFAxMHNEcTJvTmd2QS9abXkrazhYaTJNcktzQ0NodUt0cjUyTHhiRVZGV0RoTll6ZWUvN2haSEZzUllWWStBeWpsOVcvWEN6WXNSVVZZc0VUcjJIODBibFl0QWZ2SWdDTHppZXJmNy8veDhuaTRJb0tzdkRLNnRmT3hZSWZYRkZCRmw3RDZKd3NqcTZvTUFzYVdHaUdXZFJIbnNaeHNnREVNUXV6T0xxaU9saFEvM29peU9Md2l1cGc0WTIzSEN3T3I2Z3VGclhYTUVBVzVPaUs2bUxoamJkQUZzZFhWQmNMdjZ4Q0xPaXhwM0Y4TEh6eEZzamkrSXJxWk5INUpqNGhGc25oRmRYTndoZHZBU3pZNFlOT0R3dkFNTTRlRnZYeEZkWERncm9kQU1EaUFSVFZ3NExIK0l0SFVGUVBDOHZzZlRyeUVPN0N3NEpIeEJlUGJoZUdZZmpqenVLaC9ZWHBQZjNqa2ZhaGRjUVFoOEE0OVFGRzdINFcxUEVGRkhlU0I0NDdEY05JUS9OYWp6d2VNYnhuY0w3enZwbGYxcWVNS1J2L0NYcmRydjB2dml4dnVNaFNvNWZwWmNIeDgrRDNxQ3FUOW1ja1l1T1NrTWpTcGswQ1hPVlZ5akJVaUJxVHdxYyt3K0kzN0JxOHgrQzgxbkpWZlhOZG40Mkh4aXh0TXd1dVhFem4xd0t0S0d4WGZsVXUrWXBrd2NGbXJUdmZXVGdyd1BSdEVCTUxyamxxTFpFZGpzVUZWcnpnMDVOQTExOTFIdnppcnNISWdwcmpaRU96VkJnb0ZxWnZlOFd4b05EUk5kZEhMSitydEd4a1FRd1d0UWM2aGdWM1NWNUlDQW5nQmJIclpvaE80cDFrSGxpOEdmTW53Q3pUYXhRTDU1UmRpQVVGMnJUaWVtcnRlLzZSZ1hOSnhMY2hGOEdDT25jM2gxaHdRQnpYVzJmbjNnYzFRQmExZDZjMmdnVng3bTRPQm91MWZYdlgyMzlSZXgrTWhWaHcvMDd0TUF2cTN2WWVaTUh0RnFIMzVaeVhtTVY4bHlFV3JmOG5ZUllrY2FiUkNnOGkvdEVoV2NUdmdKNGFsdDNDUXZabTNtV1ZSV2syNWFXQ2ZoSmtNVmV5ajA1TG92cjVKUU9xMWZieEVWMEhyb1lBTVZ0b3FWRlJadndreUtJMVNpeVUyN1ltaTFoVjVhWWtVdDJlbU8xNGFwZldaRWdXeEl4aWl2a1NhN0tJVmRYVzZrbTFaay9NUm1vRkZOTkZHeFFMYnQ4a01oMVprMFhzZnZEQ1ZodWlWb05acFRDZ1dLSzJMc1NDMm82TVRiZHRWUmFScWdyWURsVUZpRmx5MUFKZGo2ckZoRmpVUUxWcXlYZFZGbkdxeWlCYzZuMnpNNFlVa0xVUjVXQ0lCUUVLb1BJcXE3S0lVOVVXempjMU93eTdSempTTXMzRUFpdzQ2TkxKZUhCVkZuR3FXb2NheHVEQm10bnh1RkwxQUF1NEFGbVJkVmxFcVNvQnI2alVnNWxGVU5naEYyWlk2bVRSZ3NiS3hxUHJzb2hTVmRod2xJWXhzMDR0WEtSeU9NQ2locDNZaUhoZEZqR3F5bUdIMGxvc1RFNTU1N2l2WVJZRjNNamg4Tm9zSWxTVndUZFphWmlEUlFWVFRSRXNDRnlsOFZjcnM0aFFWUXAvelUwV1dhaFhxY2NETEJ3RjBFMVlSS2hxNjdqZ0FoWkZGSXZNWWFMNXlpd2lOaXU1V0pDcFlWWXZjc0dkKzQ2ZkJmT3lPSy9OQXErcXJZTlVZYkE0UTY3a0hoWm5SeWRiblFWZVZldWd3YU5adFB0a2dWZlZZbThzVHF1elFHZUpXY3JpZkMrTHlzRWlXNTBGZXBPOGkwWDdPQ3pRcXJxVVJYWWNGbWhWL1F3c3NLcGFSN1BnNjJqcUI3TEE3Z0Z1bzFsMFc3SGdHMmtxV2xWZHNWYUlSZEo1UXRWbExOaG1MSkNxNm9yQkY3RHdqODJTSUF1NkdRdWtxbEtITC9Hd1dEWm1EN05vdHhtYjRWWFZNWDhSWm5HR3FTcXR6U05aRkp1TTJTTlUxYVVLSGhhT09iNTZQZ3lFWTh5Y0tITU5qWnN0V0NCVjFkSDdQU3djYzcvRWJPM0pNV2ZFZkgxczlUbStHRlYxekY1NldERGZ4c3ZLY0IzNm5jazlMT2dtOCtCUnFscjdaclZoZ3dmSnRxcUJ1WlpvS3crTFlpeDFFeFk0VmFXd0wvR3hLS0IrcGEwTEV0UFl1TFg0Vk1GZEpOK0dCVTVWT2R4L2ZDeUNhOHYyaW10ckxVcFdzSHRydG1HQjNOSkhiTVBndVpkRmNNK0JiSHBqZkoxcExMUnQwenpaWkowOVVsVnJLL3JnNU94bDBkbSsrS0l2M0RLalRNMXFKQXROeVl0dDlsOUVxaW96UXpGT2tnQ0wyaXlPT1RhNDU3cUY1am9MQmNZbDJXWmZUcXlxRW1OL0ZrbENMS2FDeCtkQnJoYnJRbTNKOUVSQlk3Q1luaHQ1VXpZRWJNTUNtZlpnTnAvK1BkUnZROHU5TE9iZWw1VTNFb1ZkL0xSeTk5SjBaUUp0aHF1RzJyMTg2Zmk4cC9HMEhRdmM0MmZBWHRjUUMrcmY2K3JZUDVzRExPenFiY1FDT1ZhdG8xazQ5dTAyL2hPYUVJdTAyNDRGVWxWNVBBdnFOd3Z3QkgxVGRlVjZLZjFHTExBendIVTBDK2krYS9HQzU5Sk9GbW0zSlF2azQyZWNSTE5nU2FCbzZyUWFKNHRtVXhiWUdXQVd6Y0sycFZOZ09OU0VXTHgybTdKQUp4TzZSTE13MjVvR3ZGRGVtU3dJUE8yMkdRdWNxcG93c2c3QlFvZVJObjVqZSswc0ZuclB4RDZUdVp3RlB2bllWYTgzZ29YNmVHOFc2SG12bmMxQ296a1hrSlRhcDhHdytOKy90TSsvd1pONGFYNmNENS9MeDVDemFycnA2VndFZUh2a1k5L3BGMytSK21zR2xUSDc5Tnk0VXNCT1VqTW9qUzR3VHlTTm9LcTQ3N1g1QzI3ZG4vMmxxVUN5V1BKaGZqL3daTEZuRnFnbkdKOHNQaHNMaG4wVS9oT3dvUGc0NStGWjFPaDBFWS9QZ3VDeUFud0dGalRaVGxLUHhxTGVVRVlPeG9JbEc3ck9nN0VneVlhdWMrOHNTbWhpSXZ1Y0xMUlJkNEhNSWZLWUxMaVM1K05LMExsbEhwS0ZuSUFxeTlCVTFlT3pvSjRWdjgvR292WGxsUHBrTE9xUE5JdWRzeWcrMGl4MnpzSy9aUDdaV2VUZEoyVmg3emw0N1Q0ckN5MWI3ZVlvZGo4Mll3cU50TnFZdkg5dGNBZmpWRjRXY2pQWmIzWmUzZlB6WlBGazhXVHhaUEZrOFdUeFpQRms4V1R4WlBGazhXVHhaUEZrOFdUeFpQSGdMSzVsR2RpUDdmbXc4cTczdE9temRER2IramRoY2JscmMwRHJmUEFEVjJYMTdiOGtXVzhuenlJV05GbUR4ZEpsSWJYaGRmSzdXWkNWV0l6TGhSem9McXpDc09ESkloYlhaalVXUEZtSnhiZ2NRZ0FESVFtR1JidUlCWE04QjVnczZ5SlpyRm1mZFJaeVhjUXkraGwzSmRaMi9DeUtSYXRMclRESXdtcEVzdXkrTm5lekdCeHdmaDhMc21oVmZrMFdkZlNtUTVCRmYxZXo0YStqandSWkxIdjMrZEJIMW1GUlJPK29nbG53VVVvNDBObDVnMk94eUdPeGJrVVc2U29zZWdQTC9UZHdHeFpkdDJZZmFmUXdzaHBDVVRXd25NN2d0K01PRnRTd2NXWkVveXFMT1ZMVldHUm1PUHdsRlBOV3E3Sm90U2F3UWRLS09WNjR6QTkrM3Y2UUtidmIyV1RCNVh2Rmh2cTlhUm1QS3ZYbENrTjhtZG0rVTNPNyttTjdmWEZuTnIya0pldUxvK05UNHZKa2tXMU5uckJRVTJjcEcycVowdmtwZTZxbEdpR0ptMFhmbHJseGwwVExNYWl4SU5wckN5dkZRcFZJdnJZemJaa3N5Tm9zdUxwcmhGcWJyWWdTVldwWi8yd1d0Y0tDcTJVWUxHcjFPNFVGVlljMVdnRXlKYUhCSWxtYnhWQzFWd1cvdXR1S3F2OEpzR2pIOTgxVjZ0RGlaTE5JOUJRL2xUWWFrREMwQW1UeXhzMVpjR1dYbWFnTEVXd3VvaHFGT05JL0x6Nm03NnFFajFORytCcUxTamJ1OW9PWG9aT3JMUHJ4dU1CYkRiVTNXTkI1d011SCszTVpESU9LVkV0bFpiTElwdXZmMUZENDR6dFpLQThMTW5HNzZkQWpTSDhwR1RUSXRHNjVXMVA3MzBrVzhxVzFSRkpRNHM1NnRFS2lvRlBkcFlBaFJ3WkVYTEtZVTdscUxCcUZoZWFLRjdNWS9Wd2pyOFdUS1pSajBublZvM0UzSGhac2Jod2REVTE0ZW9NRkdmOE8zK25hTVFsTVBSeW5VejY1Qm1CeDZ0Wm5NY0E0aVd2TmplMHZTR1ZWcVpMdHpjVkM2U1AxbklFek0xbE0yZ0N3R0hRc2x4SGdxUEJNU2NHbnNqaHZ3V0tBVWNucXppelU0S0hxSmhrTXNwaENuOEppd2FlZkY4TXQxMkoyQVNNZGdiSFpnVmNRaTJvVEZnTEdDV0tSS3JIeTJBb1BpMjVpY1pKeWtCb3MyTlQ2WW5CSSt2aEZ3TWpGTlRpWms2czBIOGhDQ0FiRUlzT3pLRlFXWjNWMkk0S0ZJTkMvd2U4OG9aZ3ZZYkRvTm1MUlgvbE9GbVFNeUNybEZKQkY1Mk14U01pdEFLSys3TzlEV1FqUGZSY0xkVHhDbHR2RklPYkRTM1p1MzlPMC9IZ1dGR2FCOXhmdGNQemVQakpvaUxDTGRDemd3MWt3bUVXQ1prSGtBRTdWRVp0Rk4wMXorRm1jYWhGMDllcnMwaEdReFhrcnU1aHZZcEFGVGVTUHExRStuQ3hPSVJaWno0TTEwZ2xOOFFVZk9SWWhGc1Y5TEhyaHNsaU1JV2pIcXlBTG9nN0NXOWxFZ0VVeC9yMzYvRVU5cDQ0L2pjTWtoV1BpWkVIa1dHNTlIZWxiS0N3MXlLS1F5eHF5M2FKdVY1MUZNLzZnVjBxZXVYWGtOSTFIYW5HeFFockdFTCtMNkYxblVjL3ZFVzJHZUc0SmkzRmhtU2lzRlJiRC9NbzFVVmtVWXNDcGpGTzUrUG1VTjNNZXAxNFNuVVUvdmhYUlpKOUZ6Mkl4VkVSTVlNbHg2bFVmcC9iVnljUnRxd3dXdDM5ZituRnFMVWZYK2JLNTMzbmR6R1l4VFdzcExHcHova0xMN2FEUFh5Z3NwbGRSak5OREZndHRFcWxXbHlhNXJDQ2QwMFRxTEdUV2tlbUU1ajRXRGNCaWV0Kzh3b0xDTEY3VnlWd09zSkR2L2FJaEZxazZyNVhQSSttem1sNWRaekc5LzBTbTl1dnVZakdYcjdKZ05vdmhlaWFMVEova3Y5Z3NxRDdmZVhLeXFGenpuZW9ySEhRV3crbXpJZWQzc1hqcFFCWkRvMTVWVFIzNEdDeSttQXNlb3R5WGRoNmJqVVZOZzlIR3hhSnl6b1BMbzFWbnNlQXlaQzlHRzkxa2p4SmJ1T3ZtMmp1N0ZseVY0Nmk5Ti9ENnlEVzBnZWh0dURINzI2L1ZicGZ6SWJBK3Q4YzhqVThXYTZ5UlBoZ0x1dTBqN1FkaGNSMFh6TGJNZEhBVUZrVWZFMitaTHVkQUxNZ0haSDA0Q292dDg2SWNqa1h6Wk5HSGxyMnphSDdMbGNXV292OER3aWZFektwNHJVZ0FBQUFBU1VWT1JLNUNZSUk9In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDEtMDciLCJ1cmwiOiJtay5jb20udm4iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlUyRiBBdXRoZW50aWNhdG9yIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMTAwMjAxODA3MDkwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTAxLTA3In0seyJhYWd1aWQiOiJkN2E0MjNhZC0zZTE5LTQ0OTItOTIwMC03ODEzN2RjY2MxMzYiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImQ3YTQyM2FkLTNlMTktNDQ5Mi05MjAwLTc4MTM3ZGNjYzEzNiIsImRlc2NyaXB0aW9uIjoiVml2b0tleSBBcGV4IEZJRE8yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ056Q0NBYjJnQXdJQkFnSVVjOGNSRXNZOGsrdHUvQWw1YWZZRVlSMG5DNWN3Q2dZSUtvWkl6ajBFQXdJd2FURUxNQWtHQTFVRUJoTUNWVk14RURBT0JnTlZCQW9NQjFacGRtOUxaWGt4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4SkRBaUJnTlZCQU1NRzFacGRtOUxaWGtnUVhSMFpYTjBZWFJwYjI0Z1VtOXZkQ0JEUVRBZUZ3MHlNakE0TVRBeE56UXdNRGxhRncwek1qQTRNRGt4TnpRd01EbGFNR2t4Q3pBSkJnTlZCQVlUQWxWVE1SQXdEZ1lEVlFRS0RBZFdhWFp2UzJWNU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1TUXdJZ1lEVlFRRERCdFdhWFp2UzJWNUlFRjBkR1Z6ZEdGMGFXOXVJRkp2YjNRZ1EwRXdkakFRQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFUa2owNG81ZzVxZDlKYi9vbTRiRDRseFd3Y2xwU2tSbUZzL2xKTldSSWtXK2tvdDY2L3dSSHUyU3UvMUJUSmVnU0VqUE4yVTBWK3IycUoreFZjdVhqb3p2U0twdHMyYWkzMXRCdXRucVlYb3YyWDRWTTBHMTRHRklpSERqbXFVcXVqSmpBa01CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMmdBTUdVQ01FMVRvbnFFWnlzN1N3VE1QY3FpM3Y3aUozaGtsem5rWjN6elZ3UEl0MjYwUU9kdVRleVpaL2gyd0RWRHR0ZlhtQUl4QUpUVUd5L092U0dldHhXK2drQ3J4L1FCU1BrSTBiVFVFWG5rdzlsMzNUaUdvdzZVTForNTBRKzk2L2NHaEtia3BRPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZ0NBWUFBQUJ6ZW5yMEFBQU1PbnBVV0hSU1lYY2djSEp2Wm1sc1pTQjBlWEJsSUdWNGFXWUFBSGphcFpocmNpTTVEb1QvOHhSN0JCSWsrRGdPbnhGN2d6bitmcURLNnJiYkhUTzlZOW1xVWxXSkJKR0pSTkp1Ly9YZjQvN0RUNVNRWE5KU2M4dlo4NU5hYXRJNXFmNzEwKzk3OE9tKzN4OTVidkg1MDNYM3ZpRmNpaHpqNjJQTnovTWYxOE43Z05laGM2WS9EVlRuYzJOOHZ0SFNNMzc5TXRBemM3U0k3SHc5QTdWbm9DaXZHK0Vab0wrVzVYT3I1ZWNsalAwNnJvK1YxTmVmczdkVVA0Zjl5K2RDOXBZeVR4VFpNVVRQZTR4UEFOSCt4TVhPU2VYZGJudDc1enhHdmRjL0JpTWgzK1hwL2RPSTZGaW82ZHVIUHFIeVBndmZYM2RmMFVyeVBCSy9KRG0vajk5ZWQwRy8zSWp2ZWVUbm1WTjl6dVR6OVhqOGVFWDBKZnYyZDg2cTU2NlpWZlNVU1hWK0Z2WE9tcDN3SElNa203bzZRc3UrOEtjTVVlNnI4YXF3ZWtLRjVTY3pEczViRUpBNElZVVZlamhoMytNTWt4Q1RiQ2VGRTVFcDhWNnNzVWlUR1EyL1pLOXdwTVFXRjhoS25CZjJGT1VkUzdqVE5qL2RuYTB5OHdvOEtvSEJndkhpVDEvdVQ3OXdqcFZDQ0w2K2MwVmNJcFpzd2pEazdKM0hRQ1NjSjZsNkUvengrdnBqdUVZUVZNdXlsVWdqc2VNMXhORHdRd25pQlRyeW9ISjgxV0FvNnhtQUZERzFFa3lJSUFCcUlXckl3UmVSRWdLSnJBRFVDVjFpa2dFQ1FWVVdRVXFLTVlOTkZadWFyNVJ3SHhVVkxqdXVJMllnb1RISEFqWXRkc0JLU2VGUFNSVU9kWTJhVkRWcjBhcE5lNDQ1WmMwNWwyeWkyRXNzeVJVdHVaUlNTeXU5eHBxcTFseExyYlhWM3FSRlJGTmJicVhWMWxydnpOa1p1ZlB0emdPOUR4bHhwS0Z1NUZGR0hXMzBDWDFtbWpyekxMUE9OdnVTRlJmNnNmSXFxNjYyK2c0Ykt1MjBkZWRkZHQxdDl3UFZUblFuSFQzNWxGTlBPLzJOMmdQckw2OC9RQzA4cU1sRnloNHNiOVM0V3NySEVNSGtSQTB6QUJPWEFvZ1hnd0JDaTJIbWEwaEpERG5EekRjeG5ST0NWTU5zQlVNTUJOTU9vaWQ4WU9ma2hhZ2g5Njl3Y3lWOXdrMytYK1NjUWZlSHlQMksyM2VvTFd0RDh5TDJxa0pMcXVtZzU1a3V0VnVqa3dZcXE4U2x4RHBiM3JQUXN0UHMyMU1NZTJTeWNoWUJyVEpLSXBBOTRoNno1MFphaVBXd01nSStMZXk2bElzemErQk8xN3hkejNrUFBUMHNvYWI2ckN5LzA4TENuS09wYnZKaFdRQ1NJckd2MFFmTEJNQW92VzNtOWIxc3RGaGRIVHc5QUtaVkJGT1ZrN3lyVHI0K2hGeXUweEs1eUpHSmwrK2taK1JNb1NLZ2xhV1UzSFFVbmRzdDFiNXpDYU90VEloTTJvR3hzc0tqeFg1aDBlbXpzQnlXU3hZamcrOCsxNG9Nd0dncmpaTmlkeE1jKzRJU0k4VHNuMno2bnBXcFl5YXhpK2xVUTk5VFJpSS9hWTRTSjh1dHEvU3lvTDB1YXNNMUtMZ2hIQ1RRR0xlTjA4bDNzaEViMy9Jc01mZVIraGdzTExlbGgxejF0b0E4enROSGtRR2pwdXQ5bnJaNUFoUURPTXduNWF1SGRPYWN3a0puQlpwMkxCbDhNY2RRWjk3Wkw2UGdzS3Z3elhVZFBkQUVHOGcxNkxFOGxUSmcyU3hiSXZSS1BNdElGSXVXbEhLWTFBUHBad29OakpTSmhGcklqdnF3VHdOUU5raFRuY3R2RXA0NlRFNlpEUFd0d2lQRDU3cHJtcXZmUk1JUzMyY3lRa3lxcGJvMHFldCtVb1BvZWdGZWpUNUlEcU9WUTFsb050cGQ3UmtiazJqaGFkcTd0THd5ZGNNWFNwc0xxVjBFUXRFVWdVTTZSeWJWdFFOQTZqeTVhYk83aFZ0cVRSYmxyUk5SOFlVVWd0R2sxTWJjTXJMYm8wbzNMaThncFQ0cFozUmpnejhpWmFrRzNVRlpSUTVLbktrTUs1Q284TDZQUUU0cUFpemQ1VUJpSW5raFY1d3VVbHFNbU13VlIxVjZ6UUp6djFZTk1wcG5LY0c0Q210bkFWOGxuMkZSbGZCSTFsRjdpTUNVTWx5M0FsZ1hDekhTUWZJeS9JclVLOFJ1eEJJU3Bkb0NuVktyMFkvM3RCeEtIeXZuYUJvNmRaSTJRSklFa2ZPb25ZbFRyR3N1UkhpRWt4THl4TkJhS0liQ1V4RXltRmJPNlFxQ1g2TnVVc2h2U1pQYVJBdm1VZ0dXM3ViUU5NQ0xuS1V3RDRYRTBHZ1BQanlZWW1RWTNNREd3WEJrYjBKMjZEMVFjYzVxUzRZb1VyRlJKZDhOL0s0SkJsVktrSUNwVnVTVUZtSUJtcGhMYzRvMFEzZzRlVktnZ0JzckFuUEU0SGdvMFlpU3hkTFI1NEFYV1lUNlk3MXFlZXEwajJBWlJDN2NUYVVtR0N1TmlhZy80eTByNkthYTJRcVdML2RBUVZOcENBQkNqN2o1T09leUVueHBieDdVR2pXZDI1MmEyU2l4c1ZjMnREb3ByYStVNWpqSTlyYTFHcnFvUEJ4SDRjQWkwaU5ZdDdnQnoySnRmUThySDlxUTBTb3ZMOGF1UXhZV2VuVzhWVkMxaW9GZnFaTHpUYW1kdGpiZno5QnR1RUJ6SVpSbDBuVVFaMW9nN3p1WnpOQnhXT3llMUlKaGdOWkFDNERONXBQUXlnV3JTYWFsZzQwZlhaVXVhUFZzNm1OeUpsY1hOL0t4NmFxMExmVEdVbmdZOWFXaExKUVVXaCtBYWdzaXpJU01RSmN5NHNvSkpCUEVpSzFEcnJiakZhNWpMRnNlaHBES2ZrV0kzOWtDOXhqSDlrMW9hRjB1c2x4b1R3OG9GUmc3dFdiK2dDNkFwU2J1aGtEeWR1ampoZGFpdFdFdHRwRVUvSk4xRXRTRGRidXNQdDR1aUVLQkJHMnQ1cFBJY2FHVVdCK2x3VmVpdC9RSWE3czVxRCs2QkZxYWtTU0tOcFlNN0puMDZwcktBbk5mV1NaaVdPay90aEtpWjB3a2RlRjZJQkRkcUZ2QjZCWlRNMThQdXdZM1VBcDBId1JZcWJjNFFZbWxFTUdwOWFBMHBreGtLdWlncmN5OVBRL0RhaUNnblpJN1hNMk0yUkVXc29KKzRzM0tzRXlSRmROR05CdHhUeEUxUjFmbklNTlVFU2paSXBHTFRRMTI2NmNNaVVkMk42L1dRTGw5WkpBMnhCMUJEWHZxellUZU5wZXNPUUFqVHdFUHRDUHZTQ0hrUnRCc24rdkVvbUFhUkdTWkRNSE9FVXhjeTlWQU93U3NlelZoZkNVc1h3S3dzOGRla3lZazZNQTJCMWRXU0xkaFlIZnF3dXBBRVJ4SE1YZENUcW5CU0E3TjkreURtSnVOTUxyV3JTYXlqRy90YXRMN0IxeWpFN0FrOWhYWUNXQkJvN3pSUDZxYXhHSmRzaUNMZ1FqSU80RlNKTFJSOXBtb3FuWHhHSjFTNlNIRFpDeUZadFFGM2JYa1lSbW9DWHFUOGhnVmlDWUVwQnRZNXEwTTh4U0FsRWFyUnhZS2laQWxmcmM1RWhhUjRTcmxLekpLdHpBSDJZazRQWkViSDVlQnMyR1pSemZCc0g2VXJRa1hSN083TEcxc2xaNGtFc1FrdE80WFRPNXBUL0pZMExWazRuQVRoRk9BSEZaL1FsdWVmQ3k0RVZhVE1JRjR5UjJLN0tBeUN5eTJuS1A4bUE4Tjh4ckppYlJqQmZDd1ZoTmpXb1BNR1dHemFuSG1nZ1RZckFxeHNiWTFzeE9hTkNxSm1oUWFaZWlSZHdidjA3d0J5cHZ2emdEWVVCb01KWHJzMER1QXgwZVpmNmRBS0xTS04xaXpJa2pkaEhoWnc0UXVOZEc1WGhQUnl1WkhJcDRqRGRMa1lMd0lSZ1BGSVFBdTdhcUZPckloVGpmZGExM2d3YVVVbEdCRjIyZWNqRXlTWXFxdXE4Tm5lYXlJbXE1UERNdkd0bDlaUlRFT1RxeFNQM2hKYkx4OUFtTzhDYll0VlQ3WGV4ZGRDSjJJVHVNZTl5R1h0QnJRZDkzTmRoODBkL1k5bSsyRFdBOWIyTHlJRWFNVGwzS2RXbHMzQjl3ZlliaG9pamxmVXVIcHJoTGVHdlE1Q2UranVhdUdtS0t2MXUvN2xlZm9HbTIyU0xqdXAySyswQ3RLbkswY1hSUk9zaHM2NWs3eFlLSDVyWlRBTkpHbFYrZGlHaENDK1lJbGxFaXhNb0F1a3FjNWJ5dk1JM1J3UklFdTB0YndrYlJnTUFlN0FUd1ZJOUVJa0V2NklObGNXTzVWRzV1YXpJVkY3YW9KRmkyT0lxUVptN1hGalMwNHlZNnhEMDlCVU12QnRpQ1ZMeVF6ZmNtMmMvbjJkM2RGdk51L0NYOXp0SDJCR1ZuRUdpZGFEU2VmQVpnR3VzSHhYTU0vczhPOFVMVEVPYVp3WktOb1cwNENxUGNoN0Q0K0RpT0M4dUVrT3h2Q0tvK2xoUGwyOExIbUhwd2xHVWtxTGIyT2tRVDBTdXNFRWtwejNZUDlCd1N5Mks1TEx6T1JQM29VU1g1TUtlSVBIMkVmbktLZ3JwbklySWhTR09aSTJVS1JLY1FVMjJFZTJhK3NiTndJTENKTysrWGMvZkN2b3JVMjk5SHV2ai9TNlRlN3JER3ZiMFA4QmVwQlpOSUVRTldFYTd0Qnpxa0hpd1diQjVRUUZ6ZkFCcEZQN0QzcE9IZ1RxbW5haG93MlJSRk9hby92eXRYdTJlL1JZWnpZdkUrL1NUV3c3cjN0Z0kwTWtJOWM3cGYxWTZOTkErMjNCL1M3bWMzQjJnK1Z4SjZ4cnM0dW0wWnB2amhpdTlnZEN6c1NvOHIxTHVYdkZ2M2o2RDVmaU9HSmRXeHpVRXR3OG9FK0hkazBlZ3ppM1RCa3NYeFFLNUVxZytsd3NvbERIMHNKMTA2WjJObHhRaFBBTkpiZ2gyNm5wTWRoWVhxOWJvUzJMVjV0WjF1TjYrYlgyQjBKUURZYVFYbk1iUG1vK3ZqUGwyVkg5L01GKzRlSHJRL1ZQWlRHd1ZsQk1YWUdkQkxjSkp2NFF5UWd3aG9weE5lMmpiZ3h2ZkRJcXR3YzY2MzJSTWsyZjhsQWRvYjlqNEpkaExkRjJkY28wQ1cyL1YzMXJvU21wZUh1eWlaU0cyblZUMi96ODI5citIZEg5L1ZDczY1cjY3TVN4Mll1K0lPY3A0L2wwU0dnbGxwbm51ejZNWmRvay9qcXRya3MyOUZZRjhXZVRMcGhJVUlHTVBjTnRiVStzK1RmaWE4ZDNjOFh5amxuMmYvdi93ZE9PWkgxOFZhV0FRQUFBWVZwUTBOUVNVTkRJSEJ5YjJacGJHVUFBSGljZlpFOVNNTkFITVZmVzZXbFZFVHNJTVVoUW5XeUlDcmlLRlVzZ29YU1ZtalZ3ZVRTTDJqU2tLUzRPQXF1QlFjL0Zxc09MczY2T3JnS2d1QUhpS09UazZLTGxQaS9wTkFpeG9QamZyeTc5N2g3QjNpYlZhWVlQUk9Bb3BwNk9oRVhjdmxWd2YrS0FJSVl3QWdpSWpPMFpHWXhDOWZ4ZFE4UFgrOWlQTXY5M0oralR5NFlEUEFJeEhOTTAwM2lEZUtaVFZQanZFOGNabVZSSmo0bkh0ZnBnc1NQWEpjY2Z1TmNzdG5MTThONk5qMVBIQ1lXU2wwc2RURXI2d3J4TkhGVVZsVEs5K1ljbGpsdmNWYXFkZGErSjM5aHFLQ3VaTGhPY3hnSkxDR0pGQVJJcUtPQ0trekVhRlZKTVpDbS9iaUxQMkw3VStTU3lGVUJJOGNDYWxBZzJuN3dQL2pkclZHY21uU1NRbkdnOThXeVBrWUIveTdRYWxqVzk3Rmx0VTRBM3pOd3BYYjh0U1l3KzBsNm82TkZqNEQrYmVEaXVxTkplOERsRGpEMHBJbTZhRXMrbXQ1aUVYZy9vMi9LQTRPM1FIRE42YTI5ajlNSElFdGRMZDhBQjRmQVdJbXkxMTNlSGVqdTdkOHo3ZjUrQUhvbWNxcDdIamlCQUFBTkdHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0S1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVdFMVFJRU52Y21VZ05DNDBMakF0UlhocGRqSWlQZ29nUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0S0lDQThjbVJtT2tSbGMyTnlhWEIwYVc5dUlISmtaanBoWW05MWREMGlJZ29nSUNBZ2VHMXNibk02ZUcxd1RVMDlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl0YlM4aUNpQWdJQ0I0Yld4dWN6cHpkRVYyZEQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wzTlVlWEJsTDFKbGMyOTFjbU5sUlhabGJuUWpJZ29nSUNBZ2VHMXNibk02WkdNOUltaDBkSEE2THk5d2RYSnNMbTl5Wnk5a1l5OWxiR1Z0Wlc1MGN5OHhMakV2SWdvZ0lDQWdlRzFzYm5NNlIwbE5VRDBpYUhSMGNEb3ZMM2QzZHk1bmFXMXdMbTl5Wnk5NGJYQXZJZ29nSUNBZ2VHMXNibk02ZEdsbVpqMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzkwYVdabUx6RXVNQzhpQ2lBZ0lDQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpQ2lBZ0lIaHRjRTFOT2tSdlkzVnRaVzUwU1VROUltZHBiWEE2Wkc5amFXUTZaMmx0Y0RvMk9XRXhZbU13TlMwME0ySmtMVFJoTWpRdE9UUTNNQzAxTkdNNFlUSTNZemN4WW1NaUNpQWdJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNREptWkdKbFptWXRNVEpsT1MwME16azRMVGhrTURRdE1EVTBNekV4WVdabFlqRTJJZ29nSUNCNGJYQk5UVHBQY21sbmFXNWhiRVJ2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2WkdOak5qa3lZemN0WWpKaU5TMDBOV0ZsTFdGbU9HUXRaakF5WldVd1lUSTVaRFUxSWdvZ0lDQmtZenBHYjNKdFlYUTlJbWx0WVdkbEwzQnVaeUlLSUNBZ1IwbE5VRHBCVUVrOUlqSXVNQ0lLSUNBZ1IwbE5VRHBRYkdGMFptOXliVDBpVjJsdVpHOTNjeUlLSUNBZ1IwbE5VRHBVYVcxbFUzUmhiWEE5SWpFMk5qQXhOVEk1TURFd016VTNPREFpQ2lBZ0lFZEpUVkE2Vm1WeWMybHZiajBpTWk0eE1DNHpNQ0lLSUNBZ2RHbG1aanBQY21sbGJuUmhkR2x2YmowaU1TSUtJQ0FnZUcxd09rTnlaV0YwYjNKVWIyOXNQU0pIU1UxUUlESXVNVEFpUGdvZ0lDQThlRzF3VFUwNlNHbHpkRzl5ZVQ0S0lDQWdJRHh5WkdZNlUyVnhQZ29nSUNBZ0lEeHlaR1k2YkdrS0lDQWdJQ0FnYzNSRmRuUTZZV04wYVc5dVBTSnpZWFpsWkNJS0lDQWdJQ0FnYzNSRmRuUTZZMmhoYm1kbFpEMGlMeUlLSUNBZ0lDQWdjM1JGZG5RNmFXNXpkR0Z1WTJWSlJEMGllRzF3TG1scFpEcGhZamxqWVRSa05DMHhNRFEzTFRSalpHUXRPREF5TmkwME9USTFZalk1T0ROalltTWlDaUFnSUNBZ0lITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa2RwYlhBZ01pNHhNQ0FvVjJsdVpHOTNjeWtpQ2lBZ0lDQWdJSE4wUlhaME9uZG9aVzQ5SWpJd01qSXRNRGd0TVRCVU1UQTZNelU2TURFaUx6NEtJQ0FnSUR3dmNtUm1PbE5sY1Q0S0lDQWdQQzk0YlhCTlRUcElhWE4wYjNKNVBnb2dJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQZ29nUEM5eVpHWTZVa1JHUGdvOEwzZzZlRzF3YldWMFlUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvOFAzaHdZV05yWlhRZ1pXNWtQU0ozSWo4KzZITXROd0FBQUFaaVMwZEVBUDhBQUFCQk12d045UUFBQUFsd1NGbHpBQUFMRXdBQUN4TUJBSnFjR0FBQUFBZDBTVTFGQitZSUNoRWpBUEJKUjd3QUFBa0RTVVJCVkZqRHJaWjdiRlAzRmNjLzkySEhkcHo0RmNkeERFbklDNUtROEF5UVVKSlFDcFFXTmxoYnRJMnFhOVZ1MDlST2svYmYxRC8yUjZmOVcwMWJKMjNhMWtudGltZ1I3V2hYU2ltbGtKSUdTRWxEQWlIazZSREhlVGh4N05qNGZlLytJSmlZQUsybWZmKzZ1dWZjMy9tZWM3N24zSitncXFvS29LcVFVaFNTS1lWVVNpR1JTdUlMM01MckQrSDFoNWdPUnZDSElnVENNVzdGRWlpS1NsbUJtY2ZXbGpJODRlZlNvQmVkUnNaczFKRnZ5cWF5MEVhWjA0cUlnaWlLaUpLSUxJcklrb1Fna0lad2gwQWtscUIzZElxck4zMjRwd0o0L1NFU0tRVUFkY0ZaWFhqUWF5WFdsK1JUVStKZ1lNeEg2NDF4a2d1K2tpaFFsbTlpYTlWeWdwRVlaM3BHMFdzMWxOaHpXZW15VVZ0YWdGR25UUk9RQVZJcGhYQTBSdkJXbEI3M0ZMNVFGSEV4VFVBamlWUTRUQWlDU0lYVGpEblh3TVhyTitrYzlhVjl0TEpJL1lvQ3FvcnRlS1lEbkxrMlJpeVpBalhLWERpQ3c2UW5Hb3Vqa3lWa1dicEx3QjhJY3JIbkJ2VjFWZVRvczNpL3ZZL0pZQ1I5Y0VwUmFha3VwS2wyQllJZ01PNExjT0x5SUc3ZlBCcFpwTUpoUmlOTGxCZVl5RFVhNkJtYTRPTHcxTzBTQTdrR0xRYzJWMUJUbk0vQWlKdUNQQnZMblE0QVJJQklOTWFmajUzbTB5ODdLTW8zOFd4TExVNXpkcHFBb3FvVTIwMDRyVGs0TFVhdWpmbTRPUk1DQWVwWE9EaTRyWVlmTjYvR2JzNmh0WHVFOXFISmRPdXNSaDNQdGRSUVcrS2c4K3AxM2p0MWp1QjhLTE1GQXVBTjN1THdxWGI4d1JBSDl6VHg0bU5yK05mWkhrYW1nMGlpd0plOVkyUnB0Y1NTU2E2NnB4RUVVQlhJTnhuSU0yV1RwWkg0NnJxSEVkOTh1bjB1aTVGRFRUVVVXTEk1M2Q3QithNnIrT2ZER1NLVTAyb0VRckU0eDl1Nm1KMi94VTkvc0pNWGRxemh2Zk85WFBQTU1EUWRaT0tMS3loQUpKRktDKzdDd0FUNVppT3lMTkhlTjRZS2lJSkF1Y1BFMDQ5VVl6Rm9PZjU1S3gzWCs0a25rdHdqclVVRUZnenhaSXF6WFgyRUkxRis4Y3h1RG02cjVzU2xmanFHSmdrdkJNNlNKUXJOQm5KMUdtSkpoV1B0ZmN4SDR5UVZGVmtVcUN2SzQ0bU5sZWcxY1BUVUdhNzBENmVuNUhhcTl4SVFCQXhhVFhyT1Vvckt4VDQzaVhjKzRxVURPM204dm9JY3ZaWnp2V09Jb2tCVFpTR1dyQlJtbmNpdHBFSWdZYUo5Y0pxWlVKUXQ1VTYycnlsRlRVWTVkcXFON3FGUjFEdnpDMmcxTXFJb1poSVFKUkZicmhIZlhERGRQMVZWNlJqd2tIanZFNTdiMjBKVDNRcHk5RmxFNGduMGtTbis4dGQvY09Ud01UWTFidUJYcjd6TW96WHJDRVZUYktvcUlqQTN5NG5XZG5yZFl3aUxhcTZxS2prR0hiSXNaeTZpU0N6R0Z4ZXY4UGNQenpJVkNHWHNnSlNpc3NxVng0OGUzOGFhcW5LU2lRU3YvUEpsdm1odFE2dVJTYVpTNUZtdEhEMXltRUxYTXR4akhrNThlWUhoOFNsRU1iUGNPcTJXSFp2VzBseS9EcU5CZjNjTUZVVWxQOC9LODN1YnFWN3V5QkNLSkFyMGpmdjQyd2VuT1hlcEN6VVp4K3NaUjZ1NW5ZVXNTZmhtWndrRkEvVDA5WFBzZENzajNxWEJ6Y1pzZGpkdXBMS2tpRVVkSWQyTUFiZUhTZDhzQjNkdnBiNmlDSTBrM1hVU0JNYjk4N3gxb3BXSjJTQlYxZFZJaSt5cktzb3hXMnljdm5pWktYOGdvK3lDSU9DMG1YbXl1UUZaa3VqcEgwUkZ6ZFNBVHF2RlpUUHptdy9POFAyR09nN3NhTUNjYzRYK20xNVVSZUhtYklpa29xQ3FBbjJqNDd6MHd2TUlxSVJESVJBRUR1emZ6OHg4bUVRaW1RNXFNdWpSYW1Sc3BseTJiVnpEaUdlQ014M2ZzTytSVFJqMXVrd0NraVJpczVxdzV4bzUzdGJGNUd5UVEwOXNReEpGRXNra2h6OCtSLy80TlB1YjF1RTBham5mOWhYNzl1NUZFa1VVUmVHbXg0UGRicWVocm9yV3pxdm9zN1RzMmJhWlBJc1pSVkU1MjlISjVkNEI5TG9zckJiejBpa0FNT1htVUZ0Y3dPbXVJRi9mY0ZOZTVPVG5UKzBpbmtpeVpmVTRxOHVXWTlPcXZQYTcxN2pVMVUyV1ZvdlZZaVljRGpNWERGRld2SXpmdnZvcTJ6ZXVZV0ptbHFyU0Vvd0dQV2M3dnFHN2Y1aVVvcEJ2TVdHM1dqSzBrYWFTWjg1bGMyMEY1bXc5aXFyU096aEtkLzhJdlVPalRBWkNXQTBhUGp6K2I2NzIzU0JibDRVc0NnVG01a2dtRXVRWWRFeE8rM2p6bjI4aXEwbEVTYUxmZlJPM2Q1SUI5eGpKbElKR2xsbFp2QXlIelhyL1RhalZ5RHl5ZmpVcFJlV2RrK2ZwY1h0NTQ4akhxSXBLWTEwbGsxNFBIWjJkR1hzc1EyekF3UEFJbloyWFdidXBnZmRQdDJMUTZaaVk5YU9SSlI3ZHVKYXQ2K3ZTMDdPRUFJQXVTMHVSeThIeis3Yno3cWZuNmZQNGlDUlNQTlZTank4eWd5ekxGQzF6cFFNS2dyQXdVbXFhVUNvZUo5OWl4anN6aDBhV01HVWIyTlc0a2NKOE84WnNBL2NpZzRCV0l6TXpPOGU0ejgrTCszZHc5TE0ydW9hOXhCTUoxbStzNXcrdnY1N2U1UnFOaE5GZ0lCcUxFMHZFRVJiZUd3d0c0b2tVR2xuR2xXZGhaMk05Z1hDWUNkOE1LMHVXTHlHUXZwTGR3YlEvd0IvZlBrNldYay9MaG1wYU8zdTVNakM2RUZoTlo5MVlzNElmUHJtZFMxMDluTy91UlV4WDQvYktMYkJaMkZKWHpiQm5BdmU0bDUvczM0UGRZbjU0QlFEc0ZoUE45Ylg4NmQyVHpJZkNQTFpsRFhaekRyN1pPWHlCRUYxREhxTEpGS0Z3aEpTaUVvM0ZtZllIa0VTUklrY2UrUll6Qm9PZUZTNG5Wd2VHNmV3YlpQLzJSdkxNSnU0SCtYNHZOOWV0b3IyN2oxTmZYeWNjamZIc0UwMlVGVFVRQ0lWNTQvQkhYQjcwTFBuR2xwdkQwenRieUxPYThmbm4rT3lyRHJvR1JxZ3VLV0o5OWNvTXdkNTNEQmZEYU5CeGNOZFdISlpjTGc2TTRmZlBZVFBuVU9weVlEUG4zdmV3YklPT29rSUg1aHdqaVVTQ2J3WkdNT3IxN0d6WWdORmc0RUdRSDJRb2NSWHcwcjRtZnYvV2Z6aDVvWnNzdlo1UUpNYTFvVEdVVE5rQU1EVTd4K2NYTGxPWW4wZGJaemNDc0x0aFBTVXU1NUlmMDNjaW9KRmxOdFd1NHVEMlNZNmUvUnIza1U5SUtpcnowVGdzalU4MG51QmtXd2RhV2VKV0xNNldta3JXVlZXaXk5THlNTWdQTTVweXN2bGVjejFlbjUvVzdrSFUrMlMrR0xGRWduZ3lTZmt5SjgzMTY3QTlRSGpmcW9IRktIVFlPYlNuaVEzbHkwQVFIdW9yQUM2N2xkMk45UlM3bkh3WGZDc0JBYWdvV2NaemUxdW9LeTY0eDZxeXVCLzVWak43bXhxb0tpdEJnUDhQZ1RzWGtwcUtFbjcyMUM1V2x6aVhNRlJWS0xCYWVHWm5NelVWcFE4Y3VmK1p3TzJybVVoVldSRy9QclNYK2xYRmR6TlVvYlN3Z0VOUDdtQmxhVEdTK0oyUHZQOHEvallvcXNyVWpKOExQZjFzcWEzRVBUNkJLejhQcHozdm9lUDJJUHdYK3VpcWpvY0RkUGdBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOltdLCJhYWd1aWQiOiJkN2E0MjNhZDNlMTk0NDkyOTIwMDc4MTM3ZGNjYzEzNiIsIm9wdGlvbnMiOnsicmsiOnRydWUsInVwIjp0cnVlLCJ1diI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInRyYW5zcG9ydHMiOlsibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTA4LTE0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMi0wOC0xNCJ9LHsiYWFndWlkIjoiYmE3NmEyNzEtNmViNi00MTcxLTg3NGQtYjY0MjhkYmUzNDM3IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJiYTc2YTI3MS02ZWI2LTQxNzEtODc0ZC1iNjQyOGRiZTM0MzciLCJkZXNjcmlwdGlvbiI6IkFUS2V5LlByb1MiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NTAwMDEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMDIsInNlbGZBdHRlc3RlZEZBUiI6MkUtMDUsIm1heFRlbXBsYXRlcyI6MTAsIm1heFJldHJpZXMiOjUsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCYlRDQ0FSU2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakF0TVNzd0tRWURWUVFERENKQmRYUm9aVzUwY21WdVpDQkJWRXRsZVNCU2IyOTBJRU5CSURJd01qSXdPVEE0TUNBWERUSXlNRGt3T0RBNE16ZzFOMW9ZRHpJd05qSXdPREk1TURnek9EVTNXakF0TVNzd0tRWURWUVFERENKQmRYUm9aVzUwY21WdVpDQkJWRXRsZVNCU2IyOTBJRU5CSURJd01qSXdPVEE0TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFL04rdi9QYng2NHREdk1NaVNrY2p3UDVNOEQySVVmckdsMEhuem9ITUpHVXdiK1I0OE1leldpMUozWkJYZU9wU0hmanJneEZmbzNpckxlTFZ3SUs3QzZNak1DRXdEd1lEVlIwVEJBZ3dCZ0VCL3dJQkFEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ1dxbjNlTit5MFY5MzNNR2ozZlFyZHJVWHM4Vm1VcHJFczdDME5WOThEVElDSUVZQysrOWRPNGNqYVVSdVc0YmR0T3pJcTBQNGNUV2Q3cFNjQmFqTE4zZHgiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBSllBQUFBOUNBSUFBQURBdUFlWUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUJHdVNVUkJWSGhlN1p3SmZCUFY5c2N6Uy9ZMDNSY28zWGNLQlZ3UkJIa2lUNThMcXh2Q0UzQXRvSUlDQlFUWjJnSXRVaWd0VkdpaEtQb1hBUit5eVBMaEFSWloxRWRWb1BvUXBLVzBCVnE2WmM5a2x2eFBNcmZRbGlaTmw3UVBQL2wrTG5UbW5EdVR5Znp1dmVmY20wa3dzOWtzY0hFdmc2Ty9MdTVaVUMvOHo0Qm5OTDhXWVlTSXQzWTdIR3NJZUg1TS9NNHN0Ty9DTmtqQ3N3UEhhbi81SFJmL3Iwakk2Z3orNDUvdC9ma2F0Ty9DTm1nZ3hYaHdITGJNTkdNMjBkMVRhRWFBV3k0RHd6RzRFdjdhWE5nSDljTENSOFpCTDhURUlqUEh5V0xDY1lMbytqUUhwRFBUdE83aUZVeEljbnFEMzh2UDl0NldnWHd1Yk5OVVFwRlFRRE9EcTg4U2NobnY3bUtveWx1bkF1NG5sWjR1Q1IybmVVWUtpckphUGRycGNqaWRBVzI1Y0pnV0p4VmRQWVEyb2h0ZitsN0ZOUys4NStsTUNWbURrVE9aT0JQRjBUU0hiQzZjVHFkSnFQL3ZsZTlrMGFmOEhqcnArK0JKWlQrbXBoNDVYRGlaVHBQd1l1SUNBaGViV1ZiQW1WbWpvV1N4YTFiZVJYU09oUHJpc3RvVHgzR0ZEQ01Jak1BSmhkdjFUZHRwalJhNVhUaVR6cEh3OHJTRkJPbUJZUmlyTjNJVUl5QXdBVTJYTHM1RWJoZk9wQk1rTkpUZHFENThoSkJLWUVMcE4vNDU1Y045elJSTktPVGxHNzVnOUs1NW50UHBCQWt2VFY5TWtBb0JKbUJZVFZUV29yRFVPYlN4RG9aVGpqSmVTM1o5MU9CME9pUWh6TU1OMTZ1cTl4M0NaVkpPYi9BWk1VS29kUE1ZZkw4aUtwNmphRkl1TDErL2phTk1xTFlMNTlBaENUR0I0TXJNRklJUXd6Yk5xR0p5Vi9EMnlEVUxHR005ZEVUSWFFclROL0pHRjA2aVF4SlNsYmVxZHU2M2RFR0QwWHZJTUdsSUlHLzNlZVp2c3NnWW1PQUxaZkt5TmZrY3pmQjJGODZnUXhKZVNVckRjRUlBaVNpdGp0bVlpcXhXSWxmT1pReHFnWkJnNjJyTDFteTIybHpybjA2aC9SSlMxYlZWbis4bDVGTE9TSGtNSENTUGkwUU9LNzdqbnBLRlJwcE5EQzVUbEdWc1pzMmNkZHgxMGZtMFg4S1NoUmxtTTJ2cGdpYjE3U2pZbUxDMEpNYWd3VWpDVkhtcll0MW55T3FpczJtbmhIUzk2bWIrTGtJdU16T01jc0FEc3FoUXFxb2FRdVB0WXJwVjYvWDRJOUtnWUFITEVWSlorYXBjMXpEcUpOb3BZY21TZFdZVERUa25ScExHNHJLVG52MS9DQjd5UThqUTIrVk0wT0F6SVk4eUtxMkF3SEVoYWFpb3VMN3BTM1N3aTA2bFBSSXlXdjNOM08zV2h6TXN6MHlaSWM2UkpDWVNOaThFQVNrTVZJQmFwRlIrYmNVbjZIZ1huVXJ6WjJlZ2J6MVNla0xrNzh1N1crVFNlMHV2WlgxQ2ttNW9INEhoTWduSUJWc2dLbWVnbXFXZ05GUFhPeWN6TVBFVnROOFNodUxTTXhGRDduNTJKamR2UzBIQkNZbFlyS2VvcFlzV1JrVTFTWjJha1p5Uyt1ZWZ4VUpTQ05kU3I2cC84SUVINWliTnJxbXBmU3R4dXFlN3U5RmtIRGp3NFhlbVRkMjlaKytPcjNiSTVRbzdtYktKTnZWTFNKZzFhMlp4Y2ZHc09mTzhQYjA0TTBlUVJPN0dIRlRETm5xOTRkMFpNK0ZPNEJoZVcxKy9NU2ZiMTlmZVhXMDNKUHJyTUdhVzVlclVQVjU2d2RySkdvQytKaUtydnR3dkVBbEJRRndzOWgzM3BPV0p3a1ozaHpQUmhqK3VvSjAyY3VIQ2hmM2ZIcERMNVZxZGJ1Wjc3eUJyU3lUTm5iOHBiN05jSm9jclVxblU4ZkZ4dTNac0J6dEZHZmZzM1J2Zzc2L1Q2aVJpQ1ZqK3ZIeGw3LzREbmg0ZVp0c2FHZzFHeWdSdFVSQWVIbjZocUVpajFwQWtXYTlTalJrOSt1bC9QTW5Yc2NYV3JaL3UzUG0xbTlMTmFLRHVHOURmU2ZvQmJaWVFsSXZkdGhydE5PVkcvZzVTNUc1bVdETFFJeTUvRmJKMkJpS3hXQ3FYUVdFRkhNUldaTDJMdWZQbTUrYm4rL2o2Z241d28vc1BTUGordTJPOEM3cUNWR281QTJjMnc5bkFJaFRDNkc2eDJKRVF3M0dSeEtJM2tKYWFNdVh0Ukg4UGQ1d2tsNmVsdFNvaHRDUlBIMitSVUtqUmFGTlNsaUNyRTJoYkxLUXAwOVhsNjB0WGJMaWFuRlgreWQzcFNjTzlZRm0wWVFXc3BhdHlyNlptbDhLeEdWdHMzckNPTVcvK3dvMTUrZDVlM3RiK3A0cUxpcjZ0WDR2bzlMcWF5bHRWbGxKdHA2anJWWHo5Y2MrUFZjamtMTWVLeGFMZmZ2KzlzTENRdDdmSTlxOTJsSlZYQ0lWQ2lxTDZEK2ozOEVNUElZY1RhSnVFRlJuNWx4WXN2dkxocW91TDVwRXlTMXQyQkFpUGRGWE5Id3MvdXJKZzFhVlpjMjd0T1lJY25jZUNoUi9sYk1yMThiSHFwMVpIaG9lZktEaUtmRGFZOWY3TTJwcWJaU1dYeW0yWHFodWxYMnpiaWc2QVY1azNSMVduZ3BkUVNHWEpLU3VSdFNYV1phOVhLT1R3eHV2cVZSOG16VUZXNTlBR0NTRUtsbWZrU1dRQmhFVHFIdjVnd0t0amtjTUJ3bExlbDdnRkVRbzNrY2p2cXZXajRFN3NpL01YZkpTVnM5SFgxd2R1cmxxdGpvdU9QbjJ5QVBsc0k1RklQRDA5bGU3dWRvcUhoNGRDb1VBSENBVFRwMC9ETVl6ak9KRkVldXJNcWVMaUV1Um95c0ZEaHkvK2NWa29FdEUwSFIwUjhkUlRyUXk1SGFRTkVwWm5mV2FxcmhJSUNjYW9Ea3R0VThzeUUySngwTXdwckZhTlNVVGFjK2RxRHAzb3JOVzJKVXVUY3padThyUEdQN1ZhQThscXdmRi9JMStMWUIxcVBXKys4WnBHcThOeFRDZ1VwNlYvakt4TldiczJTeWFYd2ZWQVBKNzF3UXhrZFJvT1M4aVp5ejdPSmFRS3M0bVJCb2NGdlB3TXNqdUVSYStnMmE4VENxV0E0d2lSdkxNZWpscXlOR1Z0OW5vZkgwdi8wMmcwOGJHeEorM0dQd3RtNjlXMGw2U2tPU2FqRVdaaWtCdnRQM0NndHJZR09SbzRmZWFIczcvK0F2TWZobUVDL1FOZUdmOHljamdOUnlVc3ovdlNXRkdPQ1VuYW9BNWIwcDZXSlZRcUE2ZSt3bW8xbUVTcytxbXc5dmdaNUdndnk5UFNJZVQ0ZUZ2aUg2VDcwVkZSUjQ0Y1JEN2JnSDRka2RERFhUbDJ6Q2lZOCtFNFRqUHN1cXdOeU5IQTJyV1pvQjgvSkNRbXZvV3N6c1FoQ1NHL0xGdTUwZElGYVVZYUdOUmp5dlBJMFVhQ2t0N0dZU29OSFZFbzR5TmlPOEFKeXpVdlg1bStLbjIxbDdjWFRFbWgvL1dPaXoxMjVKQ2QrY1p0WUJUbEI5S3FxcXBmejUwdit1MTNPK1g4K2FLU3E4MEQzc0w1ODNSYUxYUkVTRmkyL2QrWEVQQ1FReUFvS3ZyOXUrOVBTcVZTbG1YZFBaU3ZUWm1NSE03RUlRbXJ0bjZ0THltQjRaODFhRUkrbklhc2JVZnM0OVZ6eWdzc3hCS3B1UDc3MC9XbkxYbDVteUlUWkJOS043ZnM5VG5wcXpPOGZYMUFQeE5GeGNmRkhUNjRIeWJkcUpKajVPWnRHVERnZ1VGRGh3MGFZclBjUDNEUWpQZG5vd01hQ0k4SWYyem9FQ05GNFFTaFVxbnpObTlCRG9FZ015c0xqUHlvL3VxRUNmSXUrWUtZUTgyMmRIbU9VQ0kzTTR3NG9HZlB0KzJ0a0xWSzBQeEVIQ2JMSEllVDBwSkZhNUhWWVdSU2Fjcnl0T1FWSzcydDQ2ZkFiR1lvVSs3R0hKaUJvUnF0MGpDTUt1UUtIMzkvZno4LytHZXJCUGo3UVZhS0RtakVnZy9ucVZVcXpDeVFLMlNiOHBDRXBkZXVIVGh3U0M2VFFjb3FrWWluZGNrb0NyUXVZZVgyL2ZyTGx3VWlFYXZYQnMxNWd4L0gyZ2UwQmtsUGYvK0pZMWl0SHBkSjZvNmVVSjB0Y2p3eVdUVEQ4Q1BIanJrcEZOQWRlUXRHRW5PUzV2TVZIS0toMXh1TmhycTZPbFY5ZlgxZG5aMmkxN1h3UVBQRER6MlkwTGNQUlp1RXBMQzh2R0wzTjkrQUVjWUdtbVVnUm1wMXVyR2pSL241K2ZHVm5VM3J5OXcvOW4zSytPYzFET0tNVERxdzdDUnBYWjFxa1dOWUNLbjBnSGdwN3VVLzhKTE56TkJRV3ZGajlIQmNKT1NNbE9jVGcvc2R6RWNPMjh2Y3M1UG1mZkhsOXNaVE5KUEpSSnRveU4xQnhwcnE2cFJsUzZaUFRVUytscmg1NDJaVVhOK0FIdjU2clc3VXFKRWJzak5QbmpwMTdQaDNNRHRFTlZxQ3BwbklpUENYWG53QjdUZGl6Nzc5cjA1KzNjL1AxMmcweHNYRTdOdnpyOWo0Qk10WHpERk1yOU9kUEhFc0lqd0NWWFV5cmNTUDYvbTc2b3RPa1FJdlJxQ09tWjlzUnovQUxHQXQzOU5ub0RSWllHdUdOQ1RRNzhXbmIzNytMMElxdTNYb3NPYjhSYmVFV09SekRLMVcyeWMrZnRqUUlabVoyVW92RDA4dnIyVXB5MGNNSHg0ZEhZVnEyT1oyNkgxMDhHQW9hS2Z0akhydTJlQmVnUnFkWGl3V1h5NHVIajl4RXMwd2tNakF0VDA1NGdrNytqRU11LzJycndJQ0FtQkkwV2cxSnBvT0N3M3BsOUJQSkhJNEZqVEYzcWdJN3hiNlpVeEtXbFQ2Z3RqbEszck9mQjA1YkNEMDhoWDYrd2dEZkVsZkwyU3lRY2ppR2VMQVFLRy9yOFN2VjFuR25YVEFFZUFlQlFmMTJ2L04xeENRK3QzWHo2RFh3d0FoRWdxbnZONUZzZWMyNzc0elhhVzJyTGNST0ZiNDg4K2dId3hwRE0zTW5QRXVxdEVTSkduNUhZT1JZNTUvZHZTWWMrZk9VeFExYXN3TFViRzlZVWhBTmRvS25BNDRPM0RzZCtMWUFyZSs4RDkxczRvM1Fsam1OeHloV1ZYSGo0Ulh1VjFaZitYcVVVRlFnVExoT0JuMTI4VDNrZFZzbmpWbmJrQ3ZrTWpZK0tDd3lFR1BQZ1p2bTdlWGxwVUZCb2VGUmNaRXhNWjcrL1ZZOE5GaTNuNDNONjdmVUxqN3dCbDY5QXFkT3YwOVpPMFkwSUZDdzZQQ29tSWpZM3RIeE1URHlRTkR3a2VOR1lmY2RvbUs2NlAwOHIxMDZSSnNuengxV3Fyd0NJK01OUmdzaXdadHhWNHZ0S1FQRHRPc2FwdVNGQWNydytWQy9GdVhtU0VTb2QvSENlN1ZLelY1YVgyOUNud2VucDdaMlJ0KytzOVozdFVGQ0VueXRTbVROQ29OYkZ1ell6Tm84TUZNeDljOU1NcG8rVEF5TmpiR1RlRUdnMnA1UlRudnFLeXFndjlycW1zcXlwRUZLRHo3ODdMazFHMmZmd0Y1QURKWmFVbkMyK0dpNjJuMXBURXpoalc1NWttdi9uUEU4TC9wTkZwb0NSNWVuaFArT1FrNWJOR3hOZEptdlBmdU94S1pHTVlSMklZNzI3ZHZuNkZEaC9BdSs2QnJzTFpldlY1bk5Ca0pnb1FaVGxiMitsRG8xUEg5UHYxc0cveE5HUEFRVERHaERuVHVGMStaOE5MTEwzNzYyUmRlUGdHTlcyb0xFbHArdHFlN2FPMmw0WjNEeUl0MkdzamZzbGttazlFMERiTkRsVXJUU2xEczJCcHBNOXpkM1VORFFsbldFZ29nU005OGR6cHl0QVpjQThqSFQyY1hMbGlzcnEyYk5IR0NtNXNieE5lUTRGNkVVTGg5NTY3bm5udHUwS0NId1RobjNvZDd2OW03T2owdEppcHFTOTRuUXJGNDVPZzdIeE0xbDlBTU45RnUydWxVTU1zSTJlWTdMSk5KY3paa3ExUXF1SS91N3NvZHUzYnRQMkJ6c2RSeTc5Qm1KM0QwNlBGejV5K0FFdENBSXNNalJvOGFpUndPSUpmTFo4K2JIeDBiZi9IUzVkMjd2MTY1RWowT2IybU9GSlcxWnZWbitYbjc5dXhtYVByYkF3ZVUzbDQ5QTN1Q056ZzQyTWZiUzZYV25EbURGcG1iVGlwZ2tDTElIOE1mRTl6VjByc0NHT0xnOWQyVS9ETlViZUx2STRaUEdQL1NqbDI3UVVMSTF5ZS85c2Exa3NzeWFRdnJXNVorYk4xWXR5NDdkV1U2MUxmdXRZeVJNajQrYk5qV0xYbG8veTVXcEtkN0tKVm1nYVVMTGwyMEVGa2RRNmZWWmEvSkNBa05RZnNOUUVPRTl3OWhsZC9WNlEwVVJZTUZKcUM4QmFZeGtBUlREUkd4U1MrMEpCWTR4cGxvam1HN29kQ3M1UUYrakdoZk44bGVseGtZNEEvSktnNXpETEY0N0xoV1B1VmhPWTZHR1FETDJpbmdwcHMrUk5LWXdzS2ZmL3pwckVncWdYbzkvUU5lblRnUk9WcmkwT0hER3piYytaSVhORk5vU1RwOUM3L1N4TGZnMjBrZU5MSWU4TDVNcHF0WHIvSVdQYWpMc3YwVCt2TzdTRUtZajF1VW8weVczN0pqMk80cmNCa211QXlPc1Z3R2YyMEF3ekNRTEpnZ2l3ZXY3UitIeTkrU0IwMGJXaXZraXNjTENyTFgzM2xVRUpxMkNRNjJuTU1FWjdOWU9EUHJBSHlxMGlJcjBsWXBsVzV3cDdWNjNlVEprK3dzUFVJZmhTWTFmWHBpUWNFSlpOR29vWWxVVmxieXU0M1I2WFFtRmhyWG5hK0RMVnU4aU1Ed3pNeHMyRDU5K29lU1B5L1BUWnJ0NGVuT2U5RUMyNFd4aWJxaXl6Q1I1NjJPQTIvQTVoMXR6V3NIemtENWpCd2V0UVlOVGFuTFYzNnpkNTlVS29IaFpmT21qUWtKZlhqNzNheGF2V2JucnE4bFVnbThyNXFhMnUrUEhmWDJzYXd6VkZaVlB2N0VQN3k5dll3R3c5OUhqRWhKWHJKbHk5YnNuRThVYm5jVzdlNEcrdlNnUng1WjgzRTYybTlFY1hISmZROE85UEgxQVkyaHc1d3ZQQ3RYeUpHdkpkNmI4VUhSYjcvdDI3dGJyOU8rK2VhMEc3Y3FoWVFRSjdEUkkwZCs4UDZkZWNqU1pja0hEaDNHQ2NMVDNYM2ExTVJubjNtYXQvL3l5Ni9MVjZ5a0dBWVhZT05mZnJIeG1wOUZRaEN4b2RmKzFZRDdDK01xMnVsVTNuaHI2cmNIRHlvVUNyVmEvY1pyazFPVGx5RkhsMk9WME5wZDJvZjlZenR5NXY5bGJ0MnFqbzFQZ0drb0ROQW1paXI4NlV5WGZTNXhONVlXMnBHN2JQL1l2NlIrd0txTU5hU1F4REVNOGhFWTY3cFJQd0RGUWhlT1l6QWF3eU9pWmRaUHZpRDFPSDNpZUhoNE9PL3FGcHdTSi83YXdJUVNra2tJc2FEbHNLRkR1bGMvd05VTDIweXYwQWlSU0FRU3F1cFZSdzd0Njk5L0FISjBFNjVlMkRiU1Y2MnVLQzJycTYyL1huR2pUNS80YnRjUGNQWEN0bkh1M0htYW9hRUxNZ3diRmhyaXZLK2NPWTVMd25zZTEwQjZqeU1RL0QvZXhMZzhSLzRzUUFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZEJsb2IiLCJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6ImJhNzZhMjcxNmViNjQxNzE4NzRkYjY0MjhkYmUzNDM3Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInBpblV2QXV0aFRva2VuIjp0cnVlLCJub01jR2FQZXJtaXNzaW9uc1dpdGhDbGllbnRQaW4iOmZhbHNlLCJsYXJnZUJsb2JzIjp0cnVlLCJiaW9FbnJvbGwiOmZhbHNlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOmZhbHNlLCJ1dkJpb0Vucm9sbCI6dHJ1ZSwiYXV0aG5yQ2ZnIjp0cnVlLCJ1dkFjZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6ZmFsc2UsImFsd2F5c1V2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMSwyXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo2NCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjEwMjQsImZvcmNlUElOQ2hhbmdlIjpmYWxzZSwibWluUElOTGVuZ3RoIjo0LCJmaXJtd2FyZVZlcnNpb24iOjUwMDAxLCJtYXhDcmVkQmxvYkxlbmd0aCI6MjU2LCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6MTAsInV2TW9kYWxpdHkiOjJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wNi0yMyIsInVybCI6Imh0dHBzOi8vYXV0aGVudHJlbmQuY29tL2F0a2V5LXByby8iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkFUS2V5LlBybyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjIwNjIzMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNC4xIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTA2LTIzIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMi0xMC0wNyJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjJlYjlmZjM1NzJmNjc2MjhkMTI5MWEzYjU3OTI0ZjgxOGFhZDllNzIiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMmViOWZmMzU3MmY2NzYyOGQxMjkxYTNiNTc5MjRmODE4YWFkOWU3MiJdLCJkZXNjcmlwdGlvbiI6Ikh5cGVyIEZJRE8gVTJGIE1pbmkgU2VjdXJpdHkgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiLCJyZW1vdGVfaGFuZGxlIl0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnh6Q0NBV3lnQXdJQkFnSUNFQXN3Q2dZSUtvWkl6ajBFQXdJd09qRUxNQWtHQTFVRUJoTUNRMEV4RWpBUUJnTlZCQW9NQ1VoWlVFVlNVMFZEVlRFWE1CVUdBMVVFQXd3T1NGbFFSVkpHU1VSUElEQXlNREF3SUJjTk1UZ3dNVEF4TURBd01EQXdXaGdQTWpBME56RXlNekV5TXpVNU5UbGFNRG94Q3pBSkJnTlZCQVlUQWtOQk1SSXdFQVlEVlFRS0RBbElXVkJGVWxORlExVXhGekFWQmdOVkJBTU1Ea2haVUVWU1JrbEVUeUF3TWpBd01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXJLVUkxRzBTN2E2SU9MbG1IaXBMbEJ1eFRZanNFRVNRdnpRaDNkQjdkdnh4V1dtN2tXTDkxcnE2UzdheVpHMGdaUFIrellxZEZ6d0FZRGNHNCthWDY2TmdNRjR3SFFZRFZSME9CQllFRkxaWWNmTU13a1FBR2J0M3J5elpGUEZ5cG1zSU1COEdBMVVkSXdRWU1CYUFGTFpZY2ZNTXdrUUFHYnQzcnl6WkZQRnlwbXNJTUF3R0ExVWRFd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ0cyL3BwTUd0N3BrY1JpZTVZSW9oUzN1RFBJcm1pUmNUanFEY2xLVldnMGdJaEFOY1BORFpIRTIvelordUI1VGhHOU9adXMreFNiNGtua3JiQXlYS1gyem0vIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUkwQUFBQVdDQVlBQUFEOS94OGxBQUFBQkhOQ1NWUUlDQWdJZkFoa2lBQUFCM0ZKUkVGVWFJSHRtazF5MjlnUngzOE5JdExTekFuTW5NRE1Oa21WNmFxcHluSjRBOU1uTUNTU1ZhRzBNTHdRc1JCbHdTY1FkWUtSVmxtbFJHNW1HK29FUTUwZzFDNVVTSFFXai9oKy9OQkV0bWNtK3E4SXZFYS9ma0Qzdi92MVk0Vk5PQXhhL1BtN0tqLytZMW9hOC93cWYvbnIzL25UZDNmVzhXZjhadUd1SFduM213Z1h3QnZyZUdVdkJCcEFnOFBnSFo5Nnd5OWk0VE8rTGRyOUppS3ZWbGRqQnIyUll4WHNudFNCaXcyS2hvaThUYTRkTGpnTVdrOW82ak4rQ2VqMFBVUm13QmlKcm9tbzBRa2FaYWZwbnRTSjVBYVI2Z1pGYjB2M254M25Od2lwTXVpTlVCMmlFbEtKSnFEMWZIcnkvQ29xRjJzZHhqakYrZG81ak9Pd01WVmw2VTZpYTA2UEo3bnhUdEFBWHErdXhpeVk0cEk2NldMK21kQ2Y1WjdwbnRSUjUvdFVoa3QrRjFXSjVCVWl0WklOcWxPV01pYnNwYlZZcCsrQnZGaHJkNnczN0UxTllGVmVJMnA1VHpKaDhlOXh5Y1o0YlNxdmNzK0pqdmlQM0NXMlBNYU9HRjVRbzZLdlMyc1ZIWEY2Tk1ienE3ajc3ODNhWmNiWjN6N241THlnbHJ6amlMdmsrMFdZT1VTcXFOWVlIRS9vQk0yODA3aDdWeUQxekoxckJyMVJzdUJTeXRJRFZGb0lyNUpiRGhlMCt6UE9qcTZzQ3hZOFlxZFFSNEJKUWFJQmZGajkvZ2p6RVBZUEFQTWlLM3QvQVBLTUZvbUhKSTUxRC9QUDZONFFrZGZZSUdLcXVWd3RKdXVESVliTEdKaWlFaUpxMTQxQ1pXL0dZWENRNk82ZTFJbWNINEFhb2dWeEFWZkhxM1Uvemc2QWRoQWl2QWV4bUNMUUNlS2ExRGZxRlNEdk5DNjFaTnpSTVdEc0Z1cXJKUTFCakhPaHN6UTl0ZnREeUx4azVaYkZ2SlVzV3ZXSGdra2ZHUnlGTE9jTmxOdkMyTVdxTHZyZllTSTJUSzVGM2hyalYvQ0NXaTVkUm5qV0tMZkI0U0tuNjZrZ1VrWDBITTgzakJMSkZjTFR6OU1KZk9Nd1h3aExRdHBCQ1BJVHlFKzR0Rmc4REEzVEhBYXRUS1FhaDFuT0c0VCtETSt2bG1vYzFVdk9qb3huR3BrR2xmMVJ3amdpVlpRTDRJOVBZdnlnNTlQdXR4QjVDVUFGRC9ETWIvV1RLRk85NDlOUk9UV3FYaUlTVTI0Tko4T1lEZzNpeUVvZk9BQXBNaUFzNXVWN1dkMVpsaFNwNHU3WGdWRmk5enJkb211Y2ZJc2RTak1oR05VN0lDNWM4N0xHanNmRHBFQ3ZlTnMxa2FybkdYcTdaMGt6aVZaM2Z3aGtjL2MxWjBjcEE1MGVUNnlPZzlUcEJENkRudit6REM1Q3hWKzFBQUI5aStmN3NGL05PYnVJdlJBWG1TWnBGcURUYnlXczZ0Z1lRQ1k1K1UzSTZ4N1JEcHE1ZEYzRVFxNXk5Y2htNVp2dHlNNGowbG9yMndsMm0yNUh1RlRVejdGSWhKZGZsRmJUU09hVzVTcGx4VVZ6ekNhaFA2Tjcwa0tkZjZhUDZudmlYR21EOHBKdVAxOGJSTHkwcFdjKzlZYkp4elpSN0tGYVM1MWR4d3lPZHZ2UTN4SVZibWozZlpZUDF6dW5VUnU2SjNXeTVkR3VUdjRFY0JGcFpxN3YxKzU4aWluTDNic3BGTTF3ZWp5aDB4OG5VU3hTeFF0cWF5TkxhS0VGZHJBNVREcm9BemZHSG4yZjMrWEpiczRaVWN2VmJ2RU9JWStiVW5TcXpqZzcrdjFHM1NvTnNMQ01TV0dHRVlVYXlCQjNIOXJCRU9GeXd3Y3YyMkdDbzRFNjloM3VWNEJEdkNzQlVQNjFSczZTc3NTZUo3VkE5enRUOFE0d0wvY2FvRlJqYmFieEZpb2pWRWFaK2dQZ25taHUzK1dWZEt4cFEyUjFaMWxWOVM2eGFmbmdvWHBwZmRZNHh0T2s4SzhFRnpUREROUTRERnA1dHBFWkVqVUlqMWRidlA0UStONmlLKzR4Wkl1KzhjYlpWZStRUXFRcnRYemhXTUFDRDdjdy8zSUR5NnlkbTF1Y3FHVk5FWVlaQ3M2K3JsaTE0aHBIVTV2TUhDMjh3TWZWSm9wWFdPTUh2R0JZQ2pDYkhWSFJycThQRnlWRVNPbGE5Snp1eVNScHVpM202WXMxUFlGc04vZysrV1g2T0lVZXc1YVBLVElzRmNvbTZqN1lIOEF3Vjd1ZjByM3llU3ViWlhjNHUrUitZOWV1TmNJYlZLdUlaRnNTWWFscEdkdHUyZ2ZoNm4xZEVUTzk2WlhrMTdISkRyTXJTcTgzbFFGYlpiVytwUzdJd1ZrMTRhNHpocG90ZHR4bmlSM0diTXZ6UFFHSlRFUEsxc2RSUG4reDRpd2JmY0oyQm9oM09GL0tudUk3UkxjMzZBYTlFWnB4a3VpUmZSenpYZEtncld3S3RJS3NtMm1PbWw1U3B0MWkyZUlYWVBvMGkzbUx5dDRrb1V5UktoRTNkRS9lY0hvODRUQm81WG9iQUJIditIUThzWjVWS2JlYzlVcjcrMThQOUp4T1VIWkdpUTZzREFMbUhicjdVK0JGcnQxZ2pqaktUcVRVY2cyL1NtVFJ1OFVPMWF0TWdkMWFIZEZNckxJd0lpMHJQdEFPM2lKTVVhMUR0bDdUcllGbG5NWnNsNXVyWXM3UVpldzQ3YjVuSWlkRFh4RnArejF5aGdqWm92U081VU5qMjhTL2JLd3I4amZzV0VKL1JxZnZKOGNBcXUveGdpRktsZVNJSUR0RlZxOWVNckE1NHhZN2x1TGowaVQ3ellwenhiSVMrYWpUU0dXcEFUVWtZNGh5dS9iNEo0UDA3T24wZUVMM3BJRTZlY2NwZGt0VkwzTmQxM3dqNng1SG01eHQ2RCtvVEpMekYxdFJGekZkblgrc0wvcDJrZGsyVC9tQnpVVTdwSjNick81c04zZHdGTkx1MXhGcUNDWU5MQmppOGhFMFBsdXFBeTlXRzVBWkVWZjVMdllqN0FoN1U3eWdUZ1VQMFhxcUcrTUF3cFRGS2dXZUhrK01yUG9nOWZ4MzB6SElpT1U4TEU1bG5iNTB4OUJwNmpoWm1PT0RmRitsRTJSYlRHKytacFBwR2Q4RzVmL1RuQjVQVmdYdWZYNUF4eVdIeVNMaTNiUEQvSC9BL3MrOW91TW90eXdlbWxaWkkzRHcvSGZQWnhoMFQrcDArcVBraU4rR1R2OVh2RXQ2eHMvQmZ3R2hobW5ZY2F5ZGdRQUFBQUJKUlU1RXJrSmdnZz09In0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDgtMDIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ikh5cGVyIEZJRE_CriBNaW5pIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJVMkYxMDAwMjAxODA5MTgwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy40IiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjEuMCJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMTktMDgtMDIifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJjZDlkZDc3Y2Y1ODBkZmUwNWQ5ZDA4OTg2NWExNjRkYmI2NDMyY2QyIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImNkOWRkNzdjZjU4MGRmZTA1ZDlkMDg5ODY1YTE2NGRiYjY0MzJjZDIiXSwiZGVzY3JpcHRpb24iOiJUcnVzdEtleSBUMTEwIFUyRiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoidTJmIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImVjY194OTYyX3JhdyJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwicmVtb3RlX2hhbmRsZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoyNTYsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDcFRDQ0FrcWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakNCcnpFTE1Ba0dBMVVFQmhNQ1MxSXhFVEFQQmdOVkJBZ01DRk5sYjNWc0xWTnBNUk13RVFZRFZRUUhEQXBIWVc1bmJtRnRMVWQxTVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVjTUJvR0ExVUVBd3dUWlZkQ1RTQkRRU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdIaGNOTVRnd056QXlNRFV6TVRNNVdoY05Nak13TnpBeE1EVXpNVE01V2pDQnJ6RUxNQWtHQTFVRUJoTUNTMUl4RVRBUEJnTlZCQWdNQ0ZObGIzVnNMVk5wTVJNd0VRWURWUVFIREFwSFlXNW5ibUZ0TFVkMU1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFpWZENUU0JEUVNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFJZnFIaXNpMG9PL2V5T3FTYURycjlpdEcySXltQmtIblNER1FJSVltVCt2cUE4QWdPODFtb21jMkxkNVBHcEVONm11RTU0d1BIUWp2Yy95Q2loOHUybzFVd1V6QVNCZ05WSFJNQkFmOEVDREFHQVFIL0FnRUFNQjBHQTFVZERnUVdCQlMzSi9meGlBdjIyaXJkQnM5OFNPRGhGN2tVL2pBTEJnTlZIUThFQkFNQ0FRWXdFUVlKWUlaSUFZYjRRZ0VCQkFRREFnQUhNQW9HQ0NxR1NNNDlCQU1DQTBrQU1FWUNJUURjNDFMRks0TEpDQlUyVlZLSXo3WjZzeFBoVUVraDhuTFNMSzZJWGRrUDV3SWhBSWVLVk9aY2hhVk81YUY3ZmJkWG9TcmN5eTFZWWVVZVBMb2pjS0k5Zlg4NCIsIk1JSUNnakNDQWlpZ0F3SUJBZ0lCQVRBS0JnZ3Foa2pPUFFRREFqQ0JuVEVMTUFrR0ExVUVCaE1DUzFJeERqQU1CZ05WQkFnTUJWTmxiM1ZzTVJBd0RnWURWUVFIREFkSFlXNW5ibUZ0TVJjd0ZRWURWUVFLREE1bFYwSk5JRU52TGl3Z1RIUmtMakVaTUJjR0ExVUVDd3dRUTJWeWRHbG1hV05oZEdVZ1ZXNXBkREVaTUJjR0ExVUVBd3dRWlZkQ1RTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd0lCY05Nak13TnpFeE1ETTBOakUwV2hnUE1qQTNNekEyTWpnd016UTJNVFJhTUlHZE1Rc3dDUVlEVlFRR0V3SkxVakVPTUF3R0ExVUVDQXdGVTJWdmRXd3hFREFPQmdOVkJBY01CMGRoYm1kdVlXMHhGekFWQmdOVkJBb01EbVZYUWswZ1EyOHVMQ0JNZEdRdU1Sa3dGd1lEVlFRTERCQkRaWEowYVdacFkyRjBaU0JWYm1sME1Sa3dGd1lEVlFRRERCQmxWMEpOSUVObGNuUnBabWxqWVhSbE1SMHdHd1lKS29aSWh2Y05BUWtCRmc1cGJtWnZRR1V0ZDJKdExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQWgrb2VLeUxTZzc5N0k2cEpvT3V2MkswYllqS1lHUWVkSU1aQWdoaVpQNitvRHdDQTd6V2FpWnpZdDNrOGFrUTNxYTRUbmpBOGRDTzl6L0lLS0h5N2FqVlRCVE1CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdIUVlEVlIwT0JCWUVGTGNuOS9HSUMvYmFLdDBHejN4STRPRVh1UlQrTUFzR0ExVWREd1FFQXdJQkJqQVJCZ2xnaGtnQmh2aENBUUVFQkFNQ0FBY3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTlZuSmRlLy90QkxxOE1ERGkrU0FkNlVkWUlaU25nNFBNcW15TnJ2Wmo2NEFpQVgweFN6QWhGYUNDcC91aHBWZ25sRitYQmdyd0FJc290WkdUQjZya0IzMUE9PSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUErZ0FBQUV4Q0FZQUFBRHZEWWdxQUFBQUFYTlNSMElBcnM0YzZRQUFBQVJuUVUxQkFBQ3hqd3Y4WVFVQUFBQUpjRWhaY3dBQUVuUUFBQkowQWQ1bUgzZ0FBRmljU1VSQlZIaGU3ZDBIZUJYRjJzRHhONzNRQ1RWQTZGSUZGS2tDVXV5QUV1bUtZa0ZVYklDQ0lpS0NVZ1FFN0wwZ2RsUXNLQ3BTcklnZ1NDK2hKblJDSjRIMGIyZnZlRC8wa2hDU25jMmVrLy92dVhtWWQ0NlhrSk56OXN5N00vTk9RSlpGQUFBQUFBQkFnUXJVZndJQUFBQUFnQUpFZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVFQkFsa1czUFNzek5WWFNEeVRLcWExYjVkU2FkWks2ZTQra0h6OW05NG4zLy9tQWNRRWhvUkpjdXBRRVIwVkpXSlZLRXQ2Z3ZvUlhyeVpCcFVwSlFDRDM0UUFBQUFCZjROa0VQU3NqUTA1dDNpS0hQdnBFanYrd1FOTDM3Wk9zMURUOUtJQ3pDWXlNbE5BYTFhVEVOWjJsWkpmT0VscWh2UFdPRDlDUEFnQUFBUEFhenlYb0tqRS9NdmM3U1h4emhweGFzVkwzQXNpUGdOQVFLZHF4dlpTOVk0QVVhZEpZOXdJQUFBRHdFazhsNk1kLysxMzJqSHRLVXRhdDF6MEFuRmE4NjlWU1lkZ1FDYXRTUmZjQUFBQUE4QUpQSk9nWkowN0lub2xUNVBBSEg0dGtadXBlQUtZRWhJZExoVkVqSktwWGR3a0lEdGE5QUFBQUFBcFNnU2ZvcDdac2xSMERCMG5xMXUyNkI0QXJBZ0trMkJXWFNwWEpFeVNvYUZIZENRQUFBS0NnRkdpQ2Z1TFA1UkkvWUpCa0hEbWlld0M0TGJ4UlE2bjI1aXNTRWhXbGV3QUFBQUFVaEFKTDBFOHNYU1k3YnJsRE1wT1NkQStBZ2hKYXE0YlUvT2hkQ1M1ZFd2Y0FBQUFBY0Z1QkhKQ3NsclhIMzNrdnlUbmdFYW1idDhyMmdZTWtnL2NrQUFBQVVHQmNUOURUang2VDdiZmRJUm1IRHVzZUFGNXc4cysvWk9jamowa1doUm9CQUFDQUF1SHFFbmQxeG5uOEF3L0pzUy9tNko1ekZ4Z1pJVUdsU2tsSWplb1NWS0s0N2dVS09ldHRuTDV2djZUdGlKZU1JMGNsS3kxTlAzRHVLazRZSzJYNjlOSVJBQUFBQUxlNG1xQWZYYmpJTGdwM3prZXBCUVpLK1BrTkpLcC9QeW5XdXFVRWx5a2pBVUZCK2tFQWY4dE1UWlhVWGJ2azZMZno1TkRNOXlWOXoxNzlTTzRGbGl3aDUvM3dEVVhqQUFBQUFKZTVscUJuSkNWTDNGWFhTRnJDVHQyVE82RTFxMHZGVVNPa2VOczJkcUlPSUhjeVQ1NlVneDk4TFB1ZmVWNHlqeDNYdmJsVG9sdFhpWms2eWJwQ0JPZ2VBQUFBQUthNWx2RWVtZlAxdVNYblZtSlFvbWVzMUo0elc0cGYwbzdrSERoSGdSRVJVdmJXL2xMTGVnK3BvOVRPeGJGdnY1ZFQ4UWs2QWdBQUFPQUdWN0pldGV4Mi8vTXY2U2dYckdROGF0QkFpWGxxdkFTR2grdE9BSGtSVnFXeWZZUmE1TVV0ZGMvWlpaMUtrZjNQdnFBakFBQUFBRzV3SlVFL3NYaUpwTy9hbzZPekNBaVEwamYzaytpaDk3TzhGbkNJdXRGVjdkVVh6MmttL2NTQ1JaSis1S2lPQUFBQUFKam15aDUwVmJuOTZHZGY2Q2huS29HbytmSDdFaGdXcW52eXlmcnhzdExUSmYzRUNjazRmbHl5VXZOZTNScHdpenF0SUxoWU1YdVp1bDBRMGFHYlZhZTI3NUROVjE0aldTa3B1aWRubFo2WklxV3Y2YUlqQUFBQUFDWVpUOUJWY3J5dWVSdkpQSHhFOStRZ09GaXF6M3BQaWpacHJEdnlMbm5kZWprMmY2RWsvYnBZVXJac2xZekVnL29Sd0hjRXgxU1JpTnExcEdpSGRsS3NZM3NKcTFoUlA1SjMrMTU2VmZaUG1xcWpuQlc5cktOVWYvVkZIUUVBQUFBd3lYaUNucnhtcld6cDJsMUhPU3ZhOFJLcC92ckxlWjR0ekR5VklrZSsvVTRTWDN0VFV0WnQwTDJBbndnTWxLS2Qya3VaVy90THNSYk44L3crU1Q5NlZEWjF2Rkl5RGgzV1Bka0xLbDVjNnY3eHN3U0doZWtlQUFBQUFLWVkzNE9lL05kSzNUcTcwbjE2NVMzcHlNcVM0NHQvbDdqTzNXVFhrT0VrNS9CUG1abHlZdDRDMlg3RExiSnQ0Q0JKeVdPVjllQVNKYVRFdFYxMWxETjFWRnZxemwwNkFnQUFBR0NTOFFUOTVQcmNKY3NCa1JGUzdKSzJPc285VlNGKzk4VEpzdU9tQVpLNmRadnVCZnlZU3RSL1dDaWJ1MTRuaCtkOFk4Zm5xa1NYcTNRcloxbHBhWkxDK3dvQUFBQndoZGtFUFN0TDByWnUxMEhPd2h2VWw4RFFjeXNNcDRxK2JiL2pIam40NnB2MlhuZWdNTWs4ZGx4MkRoNG1lNlkrWTcvWHprVkV6Um9TV0xTb2puS1dzaWVYSnpBQUFBQUF5QmVqQ2JyYTNwNlJuS3lqbkttem1zK0ZTczYzM1RwUWtoYjlwSHVBUWlnalF4SmZlTVZlUlhJdVNYcEFSSVFFbDQzU1VjN1NkNU9nQXdBQUFHNHdPNE9lbVNtWnVUek9LYWhDZWQwNk83WHNObjdZQ0RtNWJJWHVBUW8zdFlya3dGc3pkSFIyNnVpMmdORGNGWDdMMkxkZnR3QUFBQUNZWkh3UHVnbjdYM3RUVG56M2c0NEFLUHNtVFpPa0ZYL3BDQUFBQUlDdk1Yck1tdG9YdnFsTHJLUnVqTk05MllzYU5GQ2lodzNWVWZaT2JvcVRMVjJ1czJmUmN5MHcwTjV2RzF3bVNnS2pTdWxPd0tPc2QyVEd6bDJTY2VLRVpKNUkwcDI1RTFxcmh0VCs4bE1KaklqUVBXZVdsWkVoY1oxakpXWGpKdDJUdlpMZHVrcVZhWk4xQkFBQUFNQVUzMHJRclgvcXR0dnVrQk1MYzdudjNENDN1b09VSFhDemhOZXJLOEhGaXVrSEFJL0x6SlMwdzRmbHhPOS95SUhuWDdJU2FlczlsSnUzYWtDQWxCOHhUTXJkZnF2dU9ETVNkQUFBQU1CN2ZHcUplOUtxMWJsT3prTmlxa2oxajJaSzlWZGZrS0xObTVHY3c3Y0VCa3BJVkpTVTZueVYxSjR6V3lvK09Wb0N3c1AxZ3ptd2t2akVsMStUaktSem0za0hBQUFBVVBCOEowRzNFbzhEcjc2aGc1eUZuOTlBYXM3K1NJcGUxRlQzQUw1TEZYUXJjMzBmKzRaVFVNa1N1amQ3R1ljT3l4RjFQam9BQUFBQW4rSXpDWHI2a2FPUzlNdHZPc3BlY01YeVV1MzFseVdrZEduZEEvaUhJbzNPbDhyUFRiVmU1RUc2SjN0SFB2dEN0d0FBQUFENENwOUowSk5XcnBMTVk4ZDFsSTNBUUtrNGRyU0VsQ3VyT3dEL1Vyek54VkxxaGo0NnlsN3lueXNrNC9nSkhRRUFBQUR3QmI2VG9QLzJ1MjVsTDd4ZUhTblI0UklkQWY2cDdJQmJKU0E0V0VmWnlNaVFwSlVyZFFBQUFBREFGL2hNZ3A2OGJwMXVaYTlFbDZ2dC9icUFQd3VyWEVraVdqWFhVZlpPclY2cld3QUFBQUI4Z1U4azZGa1ptWksyYWJPT3NsZnNzazY2QmZpM1ltM2I2RmIyVXZmdjF5MEFBQUFBdnNCSEV2UjBPMGsvbTdBS0ZYUUw4RytoMWF2cFZ2WXlUM0RVR2dBQUFPQkxmR2FKZTY0RTZEOEJmOGRySFFBQUFQQTcvcFdnQXdBQUFBRGdvMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBDTWl5NkxianN0TFRaVk9YV0VuZEdLZDdzaGMxYUtCRUR4dXFvMy9LVEUyVkRhM2FTOGFoUTdybnpCcXNYUzZCa1pFNk1pYzFQa0ZPcmQrZ0kvaXowSmdZQ2E5WFIwZmVjV1QrQWtrWU1FaEhaMWFpUjZ6RVRKNmdvMy9LeXNpUXVNNnhrckp4ays3SlhzbHVYYVhLdE1rNkFnQUFBR0FLQ1hvZUhKejV2dXgrYkt5TzRNK2krdmVUNk1jZjFaRjNrS0FEQUFBQS9vY2w3Z0FBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQndSa1dYVGJjVm5wNmJLcFM2eWtib3pUUGRtTEdqUlFvb2NOMWRFL1phYW15b1pXN1NYajBDSGRjMllOMWk2WHdNaElIWmx6Y3ZVYU9mN2p6enJ5dnVRL1Y4anhSVC9weUZubEI5OHJFdVMvOTNraUdwMHZ4ZHExMFpGM0hKbS9RQklHRE5MUm1aWG9FU3N4a3lmbzZKK3lNaklrcm5Pc3BHemNwSHV5VjdKYlY2a3liYktPQUFBQUFKaENnbDRJSkw0NVEvWThjZVpFTGI4YXhxMlJnT0JnSGNFdC9weWdaNldsU1ZhbXNjdFM0Uk1nRWhnU1l2MXBOUUFBLzBPTk04V0ZqNTJBNENBSkNBclNVY0Z6OWZPV3p5SWcxMGpRQ3dFU2RQL2p6d242dHFIRDVOU0tsVHBDZmdXVktDNjFQbjVmQWtORGRROEE0SFJ4M2Z0SStsbkdtRTRvUC93QktYM1ZGVG9xV0JsSlNiTGx4bHNrNC9BUjNXTldaSXRtRWpQK0NRa0laSGN0Y0RZazZJVUFDYnIvOGVjRVBhN2Z6WEp5OFJJZEliOUNhMVNYdXZPKzBSRUE0Ti9XdFd3bjZRY082TWljNkVuanBVejNXQjBWb014TTJUNTBtQno3eXAzUGh1QUs1YVgyN0k4bHBGdzUzUU1nSjl6R0FnQS9GbGFycG00QkFDQ1MrTkVzMTVMemdMQXdxVEoxRXNrNWNBNUkwQUhBajRXV0w2OWJBSURDTG5uZGV0a3o3aWtkbVZkdXlMMVNyRVZ6SFFISURSSjBBUEJqWVkwYTZoWUFvRERMT0g1YzRnYy9LRmtuVCtvZXM0cGRjWm1VdSswV0hRSElMUkowQVBCajRUVnI2QllBb05ES3lwTGRrNTZXMUMxYmRZZFpJWldpcGNyNHNSU0ZBL0tBZHcwQStLdWdJQW1yVUVFSEFJREM2dkEzMzhyaER6N1drVm1Ca1JFUzg4SXpFbHl5cE80QmNDNUkwQUhBVHdXVktpV0J4WXJxQ0FCUUdLWEV4OHV1a2FQdFdYVGpnb0trd3FoSHBNajViSzhDOG9vRUhRRDhWRkRSSWhJWUZxWWpBREFyTXpOVFRwNDhLWWNPSFpLdDI3YkowcVZMSlRVMVZUK0tncEI1S2tWMkRINVFNbzhmMXoxbXFhTlp5L1RzcmlNQWVVR0NEZ0IrS3FSeUpRa0lDdElSQU9TTlNyelQwdElrT1RsWkVoTVRaZlBtemJKNDhXSjU3LzMzWmR6NDhUSjR5QkM1TmpaV2F0ZXRLK2ZWcXlkMXJLOTZEUnBJNjdadDViaExpU0hPUU8wN2YycXluRnE1V25lWUZkNm9vVlFlTzFva0lFRDNBTWdMRW5RQThGT2hWV04wQ3dCeXBoTHdBd2NPeU5xMWEyWDI3Tm55NGtzdnlXT2pSMHUvbTI2U2k5dTFrNmJObXRsSmQ2V1lHS25Yc0tHMDY5QkJicjcxVm5sODdGaDV3ZnB2djVrN1YrTGo0Mlh2M3IxeTVPaFJPNmxId1RxNjZDYzUvUDVIT2pJcnNHaFJpWmsrUlFMRHczVVBnTHdpUVFjQVB4VktnVGdBT1RoMjdKaGNldm5sVXJkK2ZZa3NWa3lpcTFTUkprMmJTcSsrZmVYK0lVTmt3bE5QeVVjZmZ5ekxsaTJUOVJzMnlPNDllMGk4ZlVUcTdqMnljL2dJeVVwUDF6MEdCUVJJOUpPUFMzalZxcm9EUUg2UW9BT0Fud3Evb0pGdUFjRC9VdnZERi8vK3Uyelo2czdSVzNCSHB2VjdqWC9vRWNrNGRGajNHR1FsNTFFRGJwYlNYVHZyRGdENVJZSU9BSDRxdkVvVjNRSUFGQmI3WDMxZGtuLzdYVWRtUlY3VVZDb09IYXdqQUU0Z1FRY0FQeFFRRVNFaFpjcnFDQUJRR0J4ZnNsVDJQL2VTanN3S3JsaEJxajQzVlFKRFEzVVBBQ2VRb0FPQUh3b3VYMDRDUW9KMUJBRHdkK2xIamtqQ3NJZXNodmw5NXdHaElWSjU4Z1FKS2N1TllNQnBKT2dBNElkQ1NwYVVnRUF1OFFCUUdLaGljUEhESDVIMFhYdDBqMWxsN3JwRGlyZHFxU01BVG1MMEJnQitLS1JHTmM2aUJZQkM0c0RiNzhpSitRdDFaRmJSOXUyazRyMkRkQVRBYVNUb0FEd2xwRnhaQ2ExUzJiV3ZrSW9WM1Vsa3JlOFJVaW42alA4R0UxOFI5ZXZyYnd3QThHZEpLMWZKdnFuUDZNaXNFT3Z6SldiS1JHNEFBd1lGWkZsMDIzRnF1YzJtTHJHU3VqRk85MlF2YXRCQWlSNDJWRWYvcEk2TDJOQ3F2V1FjT3FSN3pxekIydVVTR0JtcEkvd3Q4YzBac3VlSkNUcHlWc080TlJJUXpENVh0eDJadjBBU0J1Ujg5N3BFajFpSm1Yem0zM3RXUm9iRWRZNlZsSTJiZEUvMlNuYnJLbFdtVGRhUi96a1ZIeTl4bDNVMmZsWnNZSkVpVW1mQmR4SlNKa3IzQUVEQlNreE1sS28xYXRqSHJabXlkOWN1aVlyeTluVnZYY3Qya243Z2dJN01pWjQwWHNwMGo5V1JNOUtQSFpPNGJqMGxiVWU4N2pFbk1DSkNxbi93amhRNXY2SHVBV0FDTStnQUFBQ0FEOXIxeEhoWGtuTUpESlR5ano1RWNnNjRnQVFkQUFBQThERUhQNTB0UnovN1FrZG1sZWphV2NyMDZxa2pBQ2FSb0FNQUFBQSs1R1RjWnRrelpweU96QXFyYzU1VUdUZUdrMEVBbC9CT2cwOVI5UWkyOXJ0WjFsM1F3dmhYM0xVOUpPTkVrdjdPQUFBQUJTL2p4QW1Kdi84QnlVd3lQMFlKTEZaTVlwNmZadTgvQitBT0VuVDRqcXdzMlRmOWVVbjY5WGZKT0hMVTZGZG04a21wT0hxa0JCVXRvcjg1QUtDd3lNek1sUFQwOUROK1pXUmtXQjlIeHVyckFqbktzbDZidXlkTXlsV1IxM3dMQ3BUb01hTWtva1lOM1ZGNHFmZDhUdGNGOVJqZ0ZLcTRGd0wrVXNYOTJNKy95STViN3hUclNxaDd6Q2w3LzkxU1lmQzlPdkllcXJnN2h5cnV2aThsSlVYV3JsMHJmNjFjS2Z2Mzc1Y0RpWW42RVpHdzBGQXBXYktrbEMxYlZtclhyaTMxNnRiMWZFVnB1Q2NwS1VtMmJ0MHFxMWF2bGoxNzlzaTI3ZHRsNDhhTmN1clVLVGw1OHVRWkI5MFJFUkVTRWhJaXBVcVZrZ2IxNjB1bFNwV2thdFdxZHJ0eTVjb1M3RU1ubTFERi9UOThxWXI3a2UrK2wvaDdocWk3U0xySG5OTDkrMG5sVVk4VXVpUFYwdExTSk40YUd5eGZzVUlTRWhJa0xpNU9ObGxmNnJxUW5KeXMvNnYvcDk3ellXRmhVcng0Y1duWW9JRjlIYWhXclpvMGJ0VEl2ajc0MGpVQjNrQ0NYZ2o0UTRLZXVudVBiTFplU3htSGorZ2VjeUpidDVRYU05LzA5RjRyRW5UbmtLRDdwcU5IajhyY2I3K1ZEejc4VUg3ODZTYzcwY3F0T3VlZEo0OC85cGowNk5GRDk2QXdVTW4ydG0zYlpQSHZ2OHVpSDMrVXYvNzZTMWF1V3FVZmRVWjRlTGcwYjlaTUxyamdBbW5Wc3FXMGJOSENIcUI3RlFuNmYvaEtncDZTc0ZQaXJ1a3VtY2VPNlI1eklpNXNJalZudmkyQjRXRzZ4MytwMTcrNndmdkxMNy9JL0FVTDVQY2xTK1NZUTg5eHBKV1h0RzNUUnRwZmNvbTBzSzRIelM2NnlMNU9BRGtoUVM4RWZEMUJ6MHhKa2EzWDk1ZVR5Ly9TUGVZRWxTMGp0YitlTFNGbHkrb2VieUpCZHc0SmV1NzhiaVUxNjlhdjE1RXpMcklHS28zT1AxOUh1WFBBR2tTLy9PcXJNdVhwcDg4NGs1RmJzejc2U0xwZGU2Mk96dDJzVHo2UjQ4ZVA2OGg1VjE1eGhVUkhSK3ZJR1o5OTlwa2NPWHBVUjg2N3hCcUExdlRZVWxpMUhIM1RwazN5MmV6WjhzbW5uOHI2RFJ2c1ByY0VCUVhaTjRSNjlld3BWMTE1cFRSbzBNQ2VhVE5wMWFwVnN1elBQM1dVc3hNblRzaERJMGJZUzNSTmVYcnlaQ2xhdEtpTzhxNTgrZkxTK2VxcmRlUXNYMGpRczlMU1pITy9tK1hrc3VXNng1emdjbVdsMXV4WkVscWh2Tzd4UCtvMXIyN1FmV2g5RnJ6NzNudHk4T0JCNDF0WEFnSUNwRml4WXRLamUzZnBkLzMxMHJ4NWMrUFhnek5STnlzLy8rSUxPWExFN0tSWDZkS2w4L1U1bTFmcTUzdG41c3d6cm9CeWlyckowcnRYTC9zYWJ3SUplaUhnMHdtNjlmTGM4OHp6a3Zqc0MxWmI5eGtTWUYwa3E3NzltaFJyMlZ6M2VCY0p1bk5JMEhQbi9pRkQ1TVdYWHRLUk0rNjc1eDU1ZXNvVUhlVk1EYVptelpvbFF4OThVQkt0Z1ZSK3FPV0dmLzd4aDlTdlgxLzNuQnYxc2Rtb1NSUFpzSEdqN25IZXQ5OThJNTA2ZHRTUk01bzJhMll2NVRibG5iZmZscjU5K3Vpb1lLa1ZGZDkvLzcxTXNsNWZhaEN1bHF3V05EV1FVMHRmQjl4NnEvMDh4Y1RFMkFOMnAwMmROczFPdXYyTlNtbytzQklwRXp5Zm9GdlhuRjBUSnN2Qk45N1NIZWFvTVYzVjExK1M0bTNiNkI3L29tN3Nmajl2bmp3MWFaS3MrT3N2VjIvWW5VNjk5NnRYcXlhRDc3L2ZUdlJVTXV1bTJ3Y09sTGZmZVVkSFpxaWJFYnNURWx4Zk1hQzJMZFUvLzN5anY5c083ZHZMZDNQbkdybUdLeFNKZzZjZCsyMnhISHpoRmVQSnVmVU9rektEQnZwRWNnNzRpNFNkTzNVclo0Y1BINWJyYjdoQmJyN3R0bnduNTRxYXpWT0pFdnlQV3FyNjN2dnYyemNqZXZYdGE4OGtleUU1VjlSZ2NjZU9IVEpxOUdqN0JzKzFzYkd5ZE5teUFrc1FmRTNyVnExMHEvQlJOWGdPempDYlRQMnR6RjIzKzJWeXJtN3lmdm5sbDlLa2FWUHAyYnUzZlcwb3lQZWV1dEc3ZGRzMnVXL3dZS25Yc0tFOFBYVnF2bGFGbmF0ZXZYcnBsamxxbFptcUQrTzJKVXVXR1AvZDlyRmVRNmFTYzRVRUhaNlZkaUJSZGozd3NQR1pUU1d5V1ZNcGY5ZEFIUUZ3d3hycmcvdHNpN2pVbnVHMjdkdkw3QysrY0d5NVdwa3laZXc3Ky9BZjZuWDA4ODgvUzV0MjdlVG1XMitWTFZ1MzZrZThLZm5rU2J1R2d2cjNYbkhWVmZZV0V1U3NSaUd0Sko2NmI3OGtESC9FeWpETko1TkYybDRzRmU2OVcwZitRMjNQdXJwTEYrbHVKYVhxTThWckRoMDZKQTgvOG9oOVkvR0xMNzg4NitlaUV5NnhyajJxMEtWcGM3LzdUcmZjTTMvaFF0MHlRNjBJdUM0MmY4VWV6NFlFSFo2azlsb2xQUGlRcEZzZlRLYXB2Vll4ejArWGdKQVEzUVBBRGNlT0hyVXJaV2RIVmM3dGVPbWxkbFZ0SjExNHdRVkc3M3pEWFdvZjlkQUhIcERMcnJ6U1hyTHFTOVJOSjFYa1VOMkU2dDZ6cDJ6YzVNTFJXVDVJN2ROVlZmSUxHN1hGTStIaFJ5VGp3UCtmVEdGS2NNVUtFak41b2dRWTJsTmJFTlNLbXNsUFB5MHRXcldTaFlzVzZWN3YycnhsaXoyNzMrK21tK3g2S3lhRmhvWktkOE5KcHJKNDhXTGRjb2U2cHFvaW9DYXBteHZxZEJpVFNORGhQVmxac3UrbFZ5WHBwMTkxaHprcUthODBhWnlFbEMyamV3QzQ1ZGp4NC9ieTlUUFp2WHUzWEc0bFhEdDM3ZEk5emltTUEzMS9wV2JEMm5mc0tNKy8rS0xQTHhYLzhxdXY1S0xteldYc0UwL1lOeDN3LzBLQ2c2VkNoUW82S2p6MnYvRzJPMk9oaUFpcCt2eDB2eG9McVdNVHUxNXpqVHd5Y3FSOVBKcXZVTFBuSDgrYVpjK20vN0YwcWU0MTQ3cnJyak4rczFvdGNUZDVTc1MvcWFNeTFWWWlrMjdzMTArM3pDRkJoK2NjLzMySkpENy9zbzdNaWhwd2l4Uy9wSjJPQUxoSnpaNnJzMmIvVFJYNDZ0V25qNUhrWEZIVnh1SDdsbHFEVjdWRTNPbWowZ3FTU2lTZUdEZE9XbDU4c2F4WXNVTDNvbTdkdW9YdWFLcmpmeXlWQTlPZjA1RkJnWUZTWWZoUUtkS2tzZTd3ZlN0WHJyU3ZEUXQ4WU5ZOE8zdjI3clZ2VXM5ODkxMWpTOTVWWFFkMURKeEp1M2J2TnA0d24yN2V2SG02WlVaRVJJUjl5b3BwSk9qd2xMVDkreVhoL2dmdEplNm1SVFMvU0NvTXZVOUhBQXFDdXR0OU9yVThiY2dERDhpU1AvN1FQYzRLQ3cwdHRIdFovWWs2ci9pS3E2K1cvUzVVM2k0SWFsdEgzMzc5WEoxNThyS2FOV3ZxVnVHUWZ1eTQ3QnoraUNzMWVJcGZlWm1VNlhlOWpueWZXbExkdmxNbmlVOUkwRDIrUzkyc0huam5uVEp0K25RalNYcVJJa1drMnpYWDZNaWNiMTNhaDY2ZW8zay8vS0FqTTlUcEtpVktsTkNST1NUbzhBejFRYVFLb2JpeDF5b29xclRFVEoxay9BeDNBRG43N1YvNzA5VHhOMnJHd0pTeVpjdEtLY043eDJEVyt2WHI3UlVXSnMraDk0TEpUejFsN3hPRlNMT0xMdEl0LzZlT1FVMFlPVXJTRW5KM3lrVitoTmF1S1ZVbWpwT0FRUDlJQjM3ODhVZTVxa3NYdjlvaW9xclBqeGc1VXA1NTlsbmQ0eXhWamR5MHhTNFZ3VHlWa2lKL0dMcTUvN2NCdDkybVcyYVJvTU16OXIvK3BpVDkrSXVPekxIM25VOGVMNkdWb25VUGdJSnkraEwzbzBlUDJrZk9xQUdKS2VYTGw3Y0xUc0UzcVdySHNUMTZ5SUZFOHpkeUM5S2RBd2RLVnl2UndIODBiZHBVdC94ZjRydnZ5L0Z2ek04NEJoYUpsSmpwVXlTb1NCSGQ0OXZVcXF0dTNidmJzODcrUnEwc0cvYlFRL0xlZSsvcEh1ZTBiTmxTaWhjdnJpTXoxTEZuS1ZieWJOcm11RGpadTIrZmpweW56cXB2MTdhdGpzd2lRWWNublBoanFleWZQRjFIWnBVZWNMT1U2TkJlUndBS2twb04vZHNiYjc1cC9BaWNwaGRlU0FWM0g2V1dMNnFDVDF1MmJORTkva2tWTVp3d2ZyeU9vUGFlVjZ0YVZVZitMWG5OV3RrN2VhcU9EQW9Na0lwalJrbGszYnE2dzdkdDM3NWR1dmZvNGZmRkZlKzgrMjdIdDMrcGF1UlhYM1dWanN6WXQzKy83TGUrVFB0bTdsemRNa010YjNmcmlGWVNkQlM0OUVPSEpHSEljSFdMVVBlWUU5bWltVlFjd3I1endDdlVIbUsxVkRreE1WSEdqQjJyZTgxUnhhYmdteFl0V2lSdnpaaWhJLytrOW9TKy9lYWJVclJvVWQyRGtpVktTRlJVbEk3OFYvcXhZN0pqOElPU2RkSnd4ZkdBQUNuZDczcUo2bmF0N3ZCdGFzYThkOSsrZGhMbzcxUVJ5UnY2OWJOWEVqbkpkRlZ5Tlh2KzcrMXNUbE9yREV6dWRWYzM5dSs0L1hZZG1VZUNqZ0psbjNjK2JJU2s3OTZqZTh3SktsVktxa3lmekhubmdJZW81ZXo3OXUyVDk5NS9YNUp6T0JQZEtlcjhVdmdlOVRvWk5YcTBQUWp6VjJvQU9PS2hoNlJKa3lhNkIwcjVDaFhzeXNsK0xTdExkajA1UWRLMi9iTm9wZ25oOWV0SjlFTVAyb202UHhqNzVKT3kzTVVURDRLQ2d1eGlvMnBsaC9wU1c2WkNySEdsV3l1emRzVEh5NTJEQmpsNkxXemVySm1VS1dQMmlMMXZ2LzFXdDh3NGV1eVlyRHR0Ulo3VG9pdFdsR2JXOCtRV0VuUVVxUDF2elpBVEMzN1VrVUhXaFRONi9CZ0pMWVRucUFKZXBxcFVyOSt3UVY1NjJmelJpbW9nVmExYU5SM0JsNmlxN2FZcSszdUZPdkpvNkpBaE9zTGZHamRxcEZ2KzY5Q1hjK1RvWjEvb3lKeWdNbEZTOWFYbkpOQlBqcXo3K2VlZlplcTBhVG95UnhWcnZPTHl5K1dGNTU2VFgzLzZTYlp0MlNKN2QrMnl2L2JzM0NrYjFxNlZiK2JNc1crdzFhOVhULysvelBuSytsNU96aGFycXVRZERCOC8rck4xRGMvSXlOQ1I4OVRKRjA2dkxEaGQrL2J0alI5SmR6b1NkQlNZRTM4c2t3TlRudEdSUVZaeVh2cTIvbEx5eXN0MUJ3QXZlZk90dDJUTDFxMDZNcWRxMWFxdWZzRENHV3J2K2JQUFA2OGo4NnBVcVNJMzMzU1RQRDE1c3N5ekJzRWIxNjJUclhGeHNtLzNidG0wZnIyc1c3MWE1bi8vdlR6M3pETXljc1FJdWFaclY2bFh0NjRFNStOVWtLalNwZVdkR1RQc21UajhVKzNhdFhYTFA1M2F2a04yang1cno2S2JGQkFTTEpVblBDRmhmbElnViswM0h6QndvSTdNVUxQaXZYcjJ0Ti96Yzc3OFVnYmVmcnRkc0ZDZEJxSzJvNmd2dFNjNUppWkdMdTNVU2NhT0dTUExseTJUMlo5K0t1YzNiS2ovRnVlcEZVWDNEeDdzMko1NzlYUGVjTDNaby9aVVljKzllL2ZxeUhuZldkZGtrOXhjM3E2UW9LTkFwQ1VlbElUN0gzRG52UE1MbTBqRkI1bVZBTHhxenRkZjY1WlpsYUtqODVWRW9XQWNQSGhRZnZyNVp4MlpVNzE2ZFhsdjVrdzdJWC90MVZmbHZudnZsZmFYWEdLZm02K1NkbFhCVi8wM0ttRnMxNjZkM0huSEhmTDQ2Tkh5NmF4WnN1TFBQMlZYZkx4OC9PR0g5a0MzU3VYSyttL05uU21USmttTTlUM3d2L3g1VzBwR2NyTEVXMk9oek9QbWk1dEYzWGFMbE9qWVFVZStiOUtVS2JMVllGSFI0bGJpUFhQR0RIbjNuWGZzbTd1NXBaYkFkK25jV1JiLytxdWQwSnV5ZmNjT2VmNkZGM1NVZjVkWTF6cFZNTTZVWk91MS9xZDFuVFJCM2NUOTRndHpLMURVNy84aWw0OTZKRUdINjdJeU0yWFg2TEdTdnRmY1VRaC9VOHU1WXA2ZEtvRWNxd1FVZW01L3dNSVpxMWV2dG8vZ00rbmkxcTNsajhXTDdkbXl2TXhpcTBHNVN1Qmp1M1d6aTd5dFc3TkdmbHE0VUhyMjZISFdJNHh1Nk50WGJyamhCaDNsbjdweHNOTWF2T2ZtYTlXS0ZjYlBXbC8xMTE5bi9ONjUvVkw3WS8yUkdndnRmbXFLbkZxelZ2ZVlVNlJOYTZrNDlINGQrVDYxRDl2SjVQVGYxRXFyRDk5L1gzcjM2bVhQTHVlRjJsTDE3UFRwY3YrOTkrYjU3emlicWRiZjc5UzFVYTBHdUxSalJ4MlpNWC9CQXQxeWxxb1FiL0owajhzdnZkVDExVTBrNkhCZDR0c3pYVG5qVTRLREpIckNFeElhWFZGM0FDak1hdGVxcFZ2d0phWm56MVZpL2NGNzd6azZlNlNLUjdWcTFVcmVmL2RkZTNuc3hQSGo3UlVjL3g2b3E1bjJwNTkrMnRFQnZFb3UxSG4vdWZsU1MzVk5LMmQ5anpOOTc5eCtxWnNmL3Vqb0R3dms4QWNmNjhpYzRITGxKR2J5UkFud28rZHhpdldlVWFkL21ESjYxQ2k1N0xMTGRKUjM2clU3ZnR3NFk2dEFEaDgrTEsrKzlwcU84a2RkZzlRTlNwTisrZlZYM1hMV1h5dFhHaTB5YTdySy9abVFvTU5WU1N0WHliNHA1Z3Q2S0tYNjlwYVNuZnhuT1JlQS9GR3pwUEE5Sml2ektwZGJBL0dLRmMzZHlGVko1Z05EaDlxejZtcmZ1dHF2cXFoSzBHKysvcnE5L3h5RlM4cXVYYkp6eENnUmcwV3psSUN3TUlsNWZxcUVsRE4vSThZdE8zZnVsTGNOSHJmWW9ubHplM3VMVTlRS2xSZWZmMTRpRFoxRThKcDFEVkY3MHAyZ2Jrb1VNVmluWmMzYXRmWk5CYWN0TURRenI2aXRSODJ0MTRUYlNORGhtdlJEaHlYaDNxSG16L2kwaERlb0o5R1BQcXh1Q2VvZUFJV1pXbTRZY3c3N0NPRWRhOWV0MHkwenFydFUyVi9OYk44eGNLQzlySHpVeUpFeWVQQmdlOThuQ3BkTWZieHM1cEVqdXNlY3dLSkZKTXpQVHE2WStlNjc5bm5ncG93WlBkcnhXaVdxYnNXdHQ5eWlJMmR0Mjc1ZEZpNWNxS1A4S1ZxMHFIVHAwa1ZIemxOSHc2bHE3azVTKzg5TkZvanIyclZyZ2F6aUlVR0hLN0xTMHlYaG9VY2tMV0duN2pGSGZTQlZlWDZhQkJyZVZ3ZWdZS2dqWWE2Kzhrb1ovK1NUOXBFM0NkWUE1ZWpodzNMTStqcDY2SkJzMzdKRmZyTUdBV3IvMzExMzNHR2ZLOTNtNG92dEdVdjRuc1RFUk4weUk4MkZZcVduVTNzOUh4czFTcDRZTThiWTNsUjQxLzZYWDVQa0pVdDFaRmJHd1VPeTgvRW43ZjN1L3VEa3laUHluTUc5NTYxYXRwU09odlpoMzNQMzNjYjJNYi9sNElvQ1ZUZkRwQ1ZMbHVpV00vYnMyU01iTjIzU2tiT0NBZ1BsK3I1OWRlUXVFblM0SXZIRGorWEUvRVU2TWljZ09FZ3FUWjRnNFp4MURQaWRxS2dvZWZ5eHgrd3EyMTk4L3JrTWUvQkJlK2xaaFFvVjdPV0RFZGFYbXFXc1ZLbVNOTHZvSXJucnpqdmwyV2Vlc1l0L2ZURjdOc2tRemlodTgyWjdGc1p0dkI0THArQXlVYnJsanVOenY1TkRuMytwSTkvMncvejVjdURBQVIwNTc1YWJiemIydnF4bWpVc2JuWCsranB5bDZuUWtKU1hwS0gvYXRXMXJmNWFhb3Y2dFRsNXZmN2NTZnFlVytQOWI1Y3FWcGVtRkYrcklYU1RvTUM1NXpWclpOMjZTV29laWU4d3BxZmFkWDVIL3doNEF2RU1ObDlTeE5TdVdMWk9Sanp4aUorcm5RZzI0MUJKMytDYlRpZXlDaFF0bG04SGptb0RUUmZYc0xwSE5tdXJJQmRiWWE4K1RFeVROWUdMcmxsbXpadW1XODlRS3E2NEdsM2VyWmRMWHhjYnF5Rm43OXUyVHBVdWRXWlZScWxRcHUycTVLV29mZW1wcXFvN3liOUVpYzVOLzNidDNMN0FpbFNUb01Dcmp4QWxKR0RwY3NnenVGL3BiV1AyNkV2M0ljRFdhMHowQWZKMzZjTHovL3Z0bDFrY2ZHUzNrQmU4eWZjeVdxZ1o5ZGRldWtwQ1FvSHNBY3dLQ2c2WFNFNDlMZ0l2SE5tVWVQU1k3UjQxeFphTEVsSlNVRkpuenpUYzZjbDR6NnpwVHBrd1pIWmx4bWNIRTkrTlBQdEd0L092VnE1ZHVPZStFbFJjc1g3NWNSL21uYnJDYW9HN1k5TC9wSmgyNWp3UWR4bVJsWk1qT2thTWxOYzdjMllSL0N5eFdWR0plbUM2QjRlRzZCNEEvR0hUbm5USnA0a1RIaS9iQWQxUnpvYmlmT2tPM1djdVc4c0dISHpvNnV3T2NTVVR0V2xMMnZydDE1STdqOCtiTFFSOWU2djdyYjc4WlBWcXRrK0V6d0pXNmRldnFsdk5VOFRWVmhNMEo2bGc0VlN2REZMVlZ3UW03ZHU4MnR2KzhacTFhY2w3dDJqcHlId2s2ek1qS2tzVDNQNVJqWDVtNzIvbGZnUUZTY2V4ajdEc0gvRXpucTY2U3laTW1HVi9pREc5cjFLaVJicGwxOE9CQjZYL0xMZEswZVhPWjlja25jdlRvVWYwSTRMeHl0L2FYc0xwMWRPU092ZU1tU3VxZXZUcnlMVjkvL2JWdU9VOTl4blJvMzE1SDVvU0hoOHY1RFJ2cXlGbTdyV1QxMEtGRE9zb2ZkVFJrRzRQSGtxcnowSjNZaHo1MzdsemRjbDczMk5nQ25SZ2dRWWNSeWVzM3lMNkpVOXpaZDk2enU1Uyt0cXVPQVBpRDBxVkx5eXN2djF4Zys3L2dIZXBjWXJkdTBxaEI0NFlORytUNmZ2Mmtib01HY3UvOTk4dXlaY3ZzNWJXQWs5U0t2OHFUeGt1QWk2ZExaQncrSWdtUGpMSlhPUG9TVlFUc3g1OSswcEh6MVBGaTZpZzAwOVIxckdLRkNqcHkxckZqeCt5Q2wwN3AzNysvYmpsdjA2Wk5qcXhVTXJhOFBTeE1icjc1WmgwVkRCSjBPQzdqK0hGSnVHZXdaQ1dmMUQzbWhOYXFJWlZHajJUZk9lQkgxQ0RteWJGajdidjRRSTBhMW5VK09scEg3bEhIdTczOHlpdlNxazBiYWRTa2lUd3diSmhkaU1udFk5bmd2NHJVcnllbCsvZlRrVHVTZnZsTkRzMytRa2UrUVMxdFg3OSt2WTZjcDA3L0tGbXlwSTdNS21Idys2eFpzMGEzOHEvOUpaZEk4ZUxGZGVTc25idDJ5ZmJ0MjNXVU4rcW02ZEpseTNUa3JBYjE2eGZJWjg3cFNORGhyS3dzMmZYNGs1SzZiWWZ1TUVmdE82LzY4dk1TYVBBNENBRHVVL3YwYnV6bjdxQVYzcVVHejdIZHV1bW9ZR3pkdGsyZWZlNDVhZDIycmRTb1ZVdjYzWFNUZkR4cmxsMDlHY2d6TmFNNitGNEpxUnFqTzF5UW1XbFhkVS9aYm42YzVoU1Z6S1VhdkRHbTlocUh1clNTb1Z6WnNycmx2TjhXTDlhdC9GT25wYlJzMFVKSHpwdjc3YmU2bFRmeENRbjVUdkt6MCszYWF3dDg5UjRKT2h4MWNOYW5jblMyQzBWSXJEZE94ZEVqSmJ4bURkMEJ3QitvMmZPSGh3KzM5K29CZjd2bjdyczljMVRlWGlzcC8rampqK1dHRzIrVUt0V3FTWXRXcldUTTJMR3k2TWNmalJheGduK3lsN3BQZU1MVmxZQ1p4MDlJd3FPamZXYXB1eXFBWmxMVkdQZHVrSlFyVjA2M25MZG56eDdkeXIvQXdFQzV5ZUNOOHZ4dVdmamhoeDkweTFtaElTRkdsL2ZuRmdrNkhITnk0eWJaTS9wSlYvYWRsNGk5UmtwZlY3QXpLZ0NjVjdsU0pmdnVOWEM2NnRXclM0L3UzWFhrSFdyUCt2SVZLK1RKOGVQbDhpdXZsRXJXUUw5WG56N3lzWlhBcThHeUU0V1E0UCtLdFdndXBhN3ZyU04zSkM5ZUlnZG12cWNqYjFPbkxKaFVxblJwM2ZKdGNYRnh1dVdNSzY2NHd0aktncFVyVithNXRvZTZybjVqNk1pOXBrMmJHcXNUY0M1STBPR0lqS1FraWIvN2ZuZk9PNjk3bmxSK1lqVDd6Z0UvMUtkM2IzdEpNM0E2dGJKaXpPalJVcXhZTWQzalBXclFlUExrU1puOStlZHl3MDAzU2YyR0RlV0txNjZTeno3N2pKbDFuRldGd2ZkS2tPRnp1UDl0LzlSbjVKUVBMSFZYTjhGTWVudkdES2xlcTVZclgwOVBtNmEvcS9NT0hqb2tweHdjaDVjb1VVTGF0bW1qSTJlcGxVanFtTFM4VU5mVFB3MjlKcTY5NWhyNzg2YWdrYUFqMzdJeU0vK3o3M3pMTnQxalRrQkVoRlI1NW1uT093ZjhrRnBhTnVDMjIzUUUvRlBWcWxYbGlURmpQREY0eW8wVFNVbXljTkVpNlgzOTlWS3ZRUU83eU55T0hUdVlWY2NaaFpRdUxaV2VmRnl0TGRZOTVtVW1KY3ZPaDBkS1ZucTY3dkVlVlpUUnlhWGJaNklTdnAwN2Q3cnlwYXF0bTZMT1FWYzNDWjJpcnJVOWUvVFFrYlBVNzFVVjNjeUx6WnMzeTRFREIzVGtIUFh6M21CZHI3MkFCQjM1ZHZpTHIrVG9wNS9yeUNEcmpWUHhzUkVTY1o3NW96QUF1SzkrL2ZwMkVnWms1NDZCQStYcXE2N1NrZS9ZdDMrL1hXU3VWcDA2MHZlR0cyVEZYMy9wUjREL1Y2SmpleW5XcVlPTzNKRzg5RTg1OFA2SE92SWV0UXo2Rk1jYzVrNVdsdU9uVEppY1VmNXF6aHpkT2pmekRPMC92N2gxYTZuZ2dlWHRDZ2s2OGtYdE85ODlZcFI5VVRDdGVMZXVFdFc3cDQ0QStKdE9uVHB4N2pseUZCd2NMRFBlZWtzdWFOSkU5L2llVHovN3pDNHNweEoxZFI0dzhMY0E2L3BYZWV4b0NTcmx6cEZmZjlzL2FhcWMzT1RzL21XbnFQT3k4N3BYdWJESnlNeDBmSWErVEpreWN2bGxsK25JV1V2KytFTXk4bENvOEx2dnY5Y3RaL1h0MDBlM0NoNEpPdklsL3Q0aGtwV1NxaU56UXV2VXRqNjBIck5uMFFINHArczk5T0VJNzFMN0lyLys2aXRwMHJpeDd2RTlhcG43SjU5K0trMmJON2Nyd0NjbkordEhVTmlGbENzckZSNTlXRWZ1eUR4NVVoSWVmRmd5cldUWWExVENlZlRvVVIyaElQVHAxVXUzbkxWdjcxNTcyZis1T0hqd29QeTVmTG1PbkJNUkVlR3BBclVrNk1pWE5KZk9PNDk1ZHFvRUZTMnFld0Q0bTByUjBWS3ZYajBkQVRrclc3YXN6UHZ1TzduODBrdDFqMjlTQloxVUJmaUwyN2ExOTFVQ1N0UTExMGpSRHUxMDVJNVRhOWZKL2xkZjE1RjNxSnRaMUcwb1dCMDdkcFNRa0JBZE9lZWtkZjA3MSswK2E5YXVkWFNmL2QvYVhIeXgwU1B3emhVSk9qeXYvTU1Qc3U4YzhITk5talF4TWdDQS95cFpzcVI4OXVtbk11VCsrKzB6ZTMyWkduUzJ2ZVFTbWZ2dHQ3b0hoVnBnZ0VTUEdpa0JMcC85ZitERlZ5WFpTdFM5Sk4xSHptcjNaOUhSMFhKeHExWTZjdGJYWDMrdFc3bXphTkVpSXpkc2JqUjQ1bnRla0tERDg5SlU5VTd1bmdKK3JSckY0WkFIWVZZQ00rbXBwMlRXUng5SmxjcVZkYTl2U2p4NFVIcjA2aVh2dmYrKzdrRmhGbDQxUnNvUEcrTHExcjZzbEJUWk9mSXh5WEs0MEZoK3NQM0RHL3IyN2F0Ynpqclg1ZXJ6NTgvWExlZW9iVk9tOXRubkZRazZQTy9ncTIvS3NaOS8wUkVBQVA5MFRkZXVzdXF2dit6WmREWFk4bFdxSU5hQWdRTmwxaWVmNkI0VVptVnU2Q3ZoRGR6ZCtuTnE5VnJaKzhKTE9pcDR4ZGplbUd0cUpWRmtaS1NPbk5XaGZYdjdocWpUMU9xaC9mdjM2eWhuaVltSnN2VFBQM1hrSEhYV2UxUlVsSTY4Z1FRZCtSTFpvcGx1bVpPVm1pWTdIeHdocWJ2Tm5vTUpBUEJkUmEyQnZKcE4vOHNhd1BYdTFjdllRTlcwOVBSMHVmMk9PMlQ1aWhXNkI0VlZZR2lvVkprMFFRTEMzVjNxbnZqNjI1SzBhcldPQ3BhcEk3NzhrWHFtMUVrWEpxZ2pVQnMyYUtBajU2amw2cjh0WHF5am5DMysvWGY3K3VpMC9qZmRwRnZlUVlLT2ZLa3k5U2tKS21QK3JsUEdnVVNKSC95QUp5dU1BZ0M4bzNMbHlqSnp4Z3hadVh5NTNIdlBQUkpWdXJSK3hIY2tKU1ZKLzV0dlpua3Y3Qm84Wlc2L1RVZnV5RkpWM1ljL1lsZDNMMmlxTmduMVNYSW53T0FNdXBxZHY3bC9meDA1NjdmZmZ0T3RuUDMwMDArNjVaenk1Y3JKcFowNjZjZzdTTkNSTHlIV0M3dktNMU1rSU1UTUhidlRuVnk2WFBZOSs0S09BQUE0TXpYclZxMWFOWms2WllwczJyQkIzbnJqRFduVnNxVlB6Y1p0MkxoUkpreWNxQ01VV3RacnR2eWR0MHRvclpxNnd4MnBjWnRsNzRzdjY2amdxSVN6U0pFaU9rSk9WQklkR2hxcUkrZDF2dnBxQ1RQdzk2dVo4ZHdVZnZzMWw0bjh1VkRWMjlYcUs2OGhRVWUrRld2ZFNxS3NEdzgzSkw3OHVoejcxZmszS0FEQVB4VXZYbHo2M1hDRC9MUm9rV3hjdDA0bWpCdG5EOHBNRERTZDl0SXJyOGkrZmZ0MGhNSXFNRHhjS2s5NFVpUW9TUGU0UTQyNVRoZzRjL3BjcUgzUDRTNVhzL2RWNWNxV05acWdxMnJ1alJzMzFwRnpWcTFhWlI4NW1STjcvL215WlRweVR1L2V2WFhMV3dLeURCNHVtSldlTHB1NnhFcnF4ampkazcyb1FRTWxldGhRSGYyVFd0YThvVlY3eVRoMFNQZWNXWU8xeXlYUVIvZWNtWlQ0NWd6Wjg4UUVIVG1yWWR3YUNRZ090bi9YMjI2OVE1SisvbFUvWWs1d3ViSlM2NnZQSk1UNnM3QTZNbitCSkF3WXBLTXpLOUVqVm1JbW4vbjNucFdSSVhHZFl5Vmw0eWJkazcyUzNicEtsV21UZGVSL1RzWEhTOXhsbmUzWHNFbUJSWXBJblFYZlNZZ0xXMEpNdUgvSUVIbnhKWE9GZys2KzZ5NlpQbTJhanJ4TmZXdzJhdExFbnVFMDVkdHZ2cEZPSFR2cXlCbE5teldUVmF2TjdTdDk1KzIzcFcrZlBqcnlOdlU3UEhic21Id3pkNjRzdEJKM3RjUnl5OWF0UnZZMzV0ZXdCeDZROGVQRzZjaFphdEJidFVZTnV6aWRLWHQzN2ZKY0FhWi9XOWV5bmFRZk9LQWpjNklualpjeTNXTjFkTzUyVFhoS0RyNyt0bzdjRVZJMVJzNmJNMXVDQ21oOHJkNlRkUnMwa0IwN2R1Z2U1Nm5WTnUzYXR0V1I3enF2ZG0xNWFQaHdIWm54MHNzdnkzMkRCK3ZJT1F0LytFSGF0R21qby8vMXlhZWZTdDhiYnRDUk05UzU1MXMyYlpMdzhIRGQ0eDBrNklXQUd3bTZrbmJ3b01SZDNVMHk5cHYva0l0czNWSnF2UDJhQkJUU2ZVa2s2TTRoUWM4ZEV2VC9SNEorWnI2VW9QK2JTZ0xVVExWSzJOV1htcWxSbFlVTkRwRnlUYzFhcVpsL0U0TklFdlQvOEpVRVBlUDRjZGw0OWJXUzduTFIzTkw5K2tybHgwZlp5KzBMd2lVZE91UzZrRmhlWEhYbGxmTGw1NS9yQ0RsUjE4VnFOV3RLbXNOSDhZMTQ2Q0VaTzJhTWp2N1hnTnR2bHhrelorcklHWDE2OTdicmxYZ1JTOXpobUJEckE3anlsSW11TE1GS1hyeEU5cjd3c2hvcDZ4NEFBUEpHVlQ2dVZLbVMzRDVnZ016KzlGUFpzSGF0L1B6amozTFhIWGRJMVpnWVk1V1JjMlB2M3IyeWN0VXFIYUV3Q3lwV1RDbzlhU1V4Z2U0TzN3OS9PRXVPLzFsd1M5MmJYWFNSYnBteGVzMGF5Y2pJMEJGeVVyWnNXV25ab29XT25KUFRQblIxQTNIeGtpVTZjazZQN3QxMXkzdEkwT0dvNG0wdmxqSjN1YkFmM1hvVEgzenhWVG4reDFMZEFRQ0FNMVRSb0JiTm04dXp6endqNjYxay9hZUZDMlhRWFhjVlNFWDR6TXhNK2ZycnIzV0V3azZOczBwYzAxbEg3bEFyekhZT2YwUXlrZ3JtVklIYXRXdnJsaGtuVHB5d3Q3emc3RlNoeld1NmR0V1JjOVNLdEpTVUZCMzkwNTQ5ZTJUTGxpMDZja2I1OHVYdGxSTmVSWUlPeDVXL1o1QkVORGQ3dDFQSlNrdVRuZmM5SUdrdUxLa0hBQlJPNm9pblpzMmF5VFBUcHNuV3padmxwUmRla05xMWF1bEgzYkhrano5MEM0V2RPa29yK3VGaEVoVGw3czJpdEIzeHNudmk1QUpadWRqQ3dJenQ2VlJ5dmludTdOdHg4Ui9YWG51dDR5ZGlxSlZDMjdkdjE5RS9xVG9oVHE5dzZOSzVzOUdDZXZsRmdnN0hCWWFGU3N3elV5U29iQm5kWTA2Nmxad25ESHRZc3RKWm1nUUFNRXNkK1RUZ3R0dGs1WW9WOHVUWXNSSVJFYUVmTVV2dGlXY0pMdjRXVXJhc1JJOGU2ZnBTOXlNZmZ5TEhmak8zRnp3NzFhdFZNM3JVbWxxbDhzTVBQK2dJWjZOK0g4MmJOZE9SYytaa3MxTEk2UlZFNmppNjNqMTc2c2liU05CaFJHaUZDbEw1NlluL0xTQm5VdEpQdjhxKzUxL1VFUUFBWnFsWmRWVXQrZk5QUDVVaUxoU25WVVhzZkhVSnJoY3I0L3VEa2xkZUljVXVkYmFRNU5uWVM5MkhqWkQwdzRkMWp6dlVscFA2OWVycHlBeVZISHFoS0tTdk1GRVE5RXlGQUpPU2toemZmMTdSeWxGYXQyNnRJMjhpUVljeHhkdGNMS1h2dUUxSFppV3EvZWkvc3dRUUFPQ2VEaDA2eVBCaHczUmtqcHJoVS90a25hYUszem05VlBYZjJOdHJSa0JRa0ZSNi9GRUpMRkZjOTdnamZkOSsyVFYra3F0TDNZT3NuL1hTVHAxMFpNWmZLMWZLdG0zYmRJU3p1ZUx5eXgwdm5ybDh4WXIvT1E5ZEhYK3BLc2M3cVZ1M2J2YjUrbDVHZ2c1enJBLzlpdmZmSXhFdG5WOEc4Mi8yZnZRSEhuTDlyaTRBbUtBU01pZXBtU0duajhYQmZ3b20zWGJiYmNhWHVxdmYzNzhIcms1UWcxVFRDYnJKSTl3S3U5RHk1YVg4ZzBOMDVKNmpuMzhwUnhmOXFDTjNYSEhGRmJwbGhscnA4WlpIajl6eW9obzFha2pEQmcxMDVBeDExT1d1M2J0MTlCK0xGeTkyZEdXRHV0blR6K0h6MUUwZ1FZZFI2cHp5S3BNblNsQ3BrcnJISEhVdWFNSkRJNDJmWncwQXBoMC9mbHkzblBISnA1L0srZzBiZEFRbmxTNVZ5dDZUNll0TUorZktab2VyTCtPZnl2VHFLUkZOTDlDUlN6SXpaZGRqWXlYOTZGSGRZWjQ2VlVFZDhXWFNqSGZlc1pkVTQrelVQdTRiKy9YVGtUUFVUWkxmZnZ0TlIvOHhaODRjM1hKRzFhcFZwZEg1NSt2SXUwalFZVnhZNVVwU2FlcFQ5bklzMDA3TVd5RDczM2hiUndEZ201eGMwaGNmSHkvM0RSNnNJLzl5OE9CQk9YQ2dZRS95VUFOVnRTZmRORFh6NDdUdzhIQUpOSnlrcTJXck1DY2dPRWdxajM5Q0FpTENkWTg3MUtUSXprZEgyOG02RzlSeTZsNkdDM3VwNDd6R1B2R0VqZ3FlMHl1cG5LYU9LWE82RXZyY2I3L1ZyZi9jcVA3bFh3bDdmbDE3elRXZXJ0NytOeEowdUtMRUplMmsxSzAzNmNpc0ExT215L0hGemhhVUFBQTNyWEFvcVZIN2YvdmRlS01rSmlicUh2K2hrdk91MTE0cnpWcTBzQ3N3RitSZzF2UnVYSldjRnk5dVpxOXg0OGFOZGNzTU5TTkc4UzJ6SW1yVmxITDNEckszRnJycDJMZmZ5NUg1QzNSa25xcThiWHJWeDZ1dnZTWnIxNjNUVWNGUTI1SGVmZmRkdWVubW16MWRaTEZhdFdwU3ZYcDFIVGxERllyNysyZGV0V3FWb3lzYTFNM1VXL3IzMTVHM2thRERIZFlGdGVLUSt5UzhTU1BkWWM1L3FvdytMT21IaitnZUFIQ09HaUNXS2xWS1IyYW9ZN1h5bTlTa3BLVElMYmZlNm5nRlhDOVFNeXZYeHNiYXo1UGFzOWpGU3RUNzMzS0w3UDdYL2tVM3FMM2hwbStBaEFRSFM0a1NKWFRrck1xVkt1bVdHY3YrL05NKzR4aG1sZTEvbzRUVnE2TWpsMlJteWE2Um95WE5wVlVzelpzM04xN04vWVNWRUtxYm1rZGRYTDcvTjNYTlg3bHlwVng2K2VWeXk0QUI4dkdzV2ZMc2M4OTU5Z2FYV2puVTcvcnJkZVFNZGVOMTE2NWRkbHNsNjA3KzdPZlZyaTIxclM5ZlFJSU8xd1JHUkVqTWMxTWwwTkFzd09uU2QrMzV6L25vSGw4ZUJNQTNtUzRLdG5yTkdsbTdkcTJPenQzSmt5ZmxaaXM1LzlMaC9YdGVvS3FaOSs3YlY1Yjg4ZjhuZDZnendqLzg2Q05wZk9HRjh0U2tTVVlxbm1mbnA1OS9ObjVqb0VtVEpzYVcwVmN5bktDcjM4WGpZOGJrZWFETk1XMjVFeGdlTGxVbVBHblgvbkZUeHNGRHN2T3hzU3E3MUQzbXFKVWtRMXpZcnJQR3V2YjI2dFBIOFZvZ09WRko2VzIzM3k0dEw3NzR2OGVOcWZmTXFOR2paZjc4K1hic1JkZkZ4anE2L1ViZDhGUTM5UlNuejZidjBxV0w0NVhuVFNGQmg2dkNLbGVXU2xNbTZNaXNFL01YeVlGMzN0TVJBRGpIMUd6bTZjWlBuSmlucEVZTjlHSzdkN2NMdy9rYk5XRHVlOE1OTWkrYmdkdVJJMGZrMGNjZWt6cjE2OHUwNmRPTnoyeXIvZStEaDVpdm9uM2hoUmZxbHZOYXQycWxXK2JNZk84OWVlT05OODdwOWJ4cDB5WVpQSFNvdEd2Zm5rcnd1UlRab0w1RTNlTE9kc0xUSFo4M1h3NTk4WldPekZJSllhWG9hQjJaczJEaFFtblRycDJzVzc5ZTk1aXhkZHMyR1RaOHVOUnIwRUJtdnZ2dS85eVFVcTk5dFRwbysvYnR1c2RiMUJMM2VuWHI2c2daMzgrYloyL1ArdkhubjNXUE0yNnpua2RmUVlJTzE1VzhySk5FM1RsQVIyYnRuelJWa2xhdDFoRUFPTVBwNDJYT1JDWFlMNzM4Y3E2VEdqWHo4Tjc3Nzh0RnpadkwvQVh1N1F0MWkxcXlQMkRnUVBuMnUrOTBUL1pVa2IzaER6OHNOV3ZYdGd2a0xWMjYxUEZqNXJaWkErYk9YYnZhQTJ5VDFMNUprOFd4YXRXcVpYOFBrOVJ6Zjg5OTk5bUp4dXJWcTgrWWNLdlg3MFlyS1gvbm5YZmt5cXV2bGtZWFhDQXZ2UGlpdlkxQkpTN0loWUFBcVhEL1BSSmF2YXJ1Y0lsMWpkb3o3aWxKZFdFclE3Rml4ZVRSa1NOMVpKWkt6bHUyYm0ydnlqbnM0REcrYW9XVG1oVlhLNEhxTjJ3bzA1OTlWazdtY0l6aS9nTUg1TnJycm5OMVpWQnVxWlU5dlh2MTBwRXpWTjBLZGMxMnNxN0lCZGIxUkIwTjV5dEkwRkVnS2d5K1Q4SWFtTjFIcEdSWkY4R0UreDdnZkhRQWpsTEZjVXhUaWZuUUJ4NlFJVU9IMnJNbmFobjN2NmsrZFhhc0tpalV0Rmt6dWVXMjJ5VHg0RUg5cVA5UXladjYyVDZiUFZ2MzVFNnk5Um1nYm5LMGJkOWU2alpvSUk4OS9yZ3NzeEkrTlR1VGw5VUphc0NvS2oxUGZPb3BhWExoaGJMaXI3LzBJK1pVcmx4WnpyY0c4YWFvR2JDU0pjMGZoWnBoUFhjZmZQaWhORy9WU2lyRnhOaEp1TnFHMGNkS1VscGRmTEZVcmxwVkxyQ2UwOXNHRHJSdk1KMytlbGUvTjdVM0ZXZW5scnBYR2pkV3JRZlhQZTdJT0hSSWRvNGNMVmtaNXJjV1huLzk5VWJmRTZkVHliUmFsVk8zZm4xNWNQaHdXYjU4K1Rrbnl1cTFyRmJ6cU8wd2FsVkluWHIxNUtvdVhlenIyWm11NjJleWJ0MDZ1ZU91dXp4WjJWMGw2RTdlNU51d2NhTjg5dm5uZWJwR1owZFZiemQ5STlKSkFkWVA3OXhQL3krcVdOZW1MckdTdWpGTzkyUXZhdEJBaVI0MlZFZi9sSm1hS2h0YXRiZmYvRGxwc0hhNUJFWkc2Z2gvUzN4emh1eDV3c3l5OG9aeGF5UWdqL3M1VG0zYkxsdTZYaWVaU2NtNng1eWlWMTRtMVo2ZjdzcFJiMjVRVlZNVEJnelMwWm1WNkJFck1aUFAvSHZQc2o0UTRqckhTc3JHVGJvbmV5VzdkWlVxMHlicnlQK2NpbytYdU1zNkd6OC9QN0JJRWFtejREc0pLUk9sZTN6TC9VT0d5SXN2dmFRajU5MXREVHltVDV1bUkrLzdhK1ZLYWQ2eXBhTURpSnlvNDdCcVdJbVVPZ3Y0NzJSS0xlZitmY2tTMmJscmw2dDdKYlB6enR0dlM5OCtmWFRrSERWenJoSTVwNWJzcXlKL1phS2k3SnNzSFR0MGtQUFBQOTh1UEZXNmRHbTdVcnJhVDZtKzFNQlpmYW1aTTFXSTdwZGZmcEh2dnY5ZS9zekRBRDAvSG4za0VSbHRKUWdtWGR1dG0zeHoydkZHWGpUNHZ2dGs4cVJKT25MV3VwYnRKTjJGUW1mUms4WkxtZTZ4T2pMSXVpNGxQRFpHRHIvL2tlNXdpZlhlcXZUVU9JbHk0V2Y4MlhvL3FtSnFCWkd3bGk5ZjNpNDQxckpGQzZsUXNhSjliVmJYanJEUVVFbTNyaGxxbWJxNnFhcUtJOGJGeGNtdml4ZkxnZjM3NWVpeFkvcHZ5THVuSmt5UW9TNXNxemtYNm5mUXVrMGIrOXJvbEwrdndVNVExL3kxcTFiNVRJRTRoUmwwRkpqdzZ0VWsycnFRaXd0M3RFNThPMDhPekppcEl3RElIelU0aTdDU1pyZW9HV1MxM1BLdEdUTmsyalBQMkYrcXZYN0RCazhrNTZhb2dhN2E0KzNrZm5wMVUrVkFZcUs5ZFBxcHlaT2wzMDAzeVlYTm1rbTFtaldsZE5teVVyVkdEWHZaYVl5VndLdTQ1bm5uMmZ1Z0gzbjBVZm54cDU5Y1RjN1ZUWU43NzdsSFIrYjBNWEJqeFdrdnZmS0tiTEtTSGVTQ1d1bysrRjRKS2xkV2Q3akVlbS90blRoWlV2ZnQweDNtWE55NmRZRWRtYVZXTGFrYkJKT2ZmbG9lZVBCQnUrWkhwOHN1a3phWFhDTHRPM2EwYnh5bzdUaHE1bjNHekpteWVmTm1SNUp6WmZUamo5djc0NzFFelV4MzY5Wk5SODV3S2psWExtalN4S2VTYzRVRUhRV3ExRlZYU0ttK3p1NWR5YzcreWRNbGVXM0JubTBKd0Q5RVJrWktodzRkZEFRVFZISisvK0RCOHZxYmIrb2VkNmlWQ2ZFSkNZNE5xUE5qMEoxMzJrbTZhWmQyNmlURml4WFRrVGVwbFJRUFBmeXdhNnRXZkYxSVZKUlVHalBLbFVtUTAyVWNPaXdKd3g4eHZ5ck4rcm1lbmpMRjhRSmxYbmZLZWgvYzFMKy83Tml4US9kNHc1V1hYMjdQVkh2UkRRNGZCZWNHRW5RVUxPc0NHejFxaElTZmI3N2dVdGFwVTVKdzcxREpPTzY5SWhzQWZFL1BIajEwQzA1VFN5WWZIRFpNWG4zOWRkMVQrRFNvWDE4ZWZ1Z2hIWmxWcGt3WnVleXl5M1RrWFY5Lzg0MHMrdkZISGVGc1NsemFTWXBkM2tsSDdrbjZkYkVjbkdYK0ZJa2lSWXJJekJrejdNSnhoY20rL2Z2dFdYc3ZyWjVxMUtpUko0dXdoWWFHU3RldVhYWGtPMGpRVWVBQ3c4SWs1b1ZuSkxCWVVkMWpUdXEyN1pMdzBFaDdEellBNUllYWRWUURSRGhMTFcxOGN0dzRlZkhsbDNWUDRhTUdsYTlhUDMrWTlmbm9Calh6OWNqRER6dDZuckVKYXZaOCtFTVBjZXhhTGdVRUJrcmxzYU1sS01yOEtveC9zSDVQZThaUGtsTTc0bldIT1kwYk41WTNYMy9kZnM4VUpxdlhySkZCOTl6ajZGTHcvRkFyR2t6VUlNbXZwaGRlS05XcXVueXFnUU5JME9FSllWVXFTL1NUajlzejZxWWQvMjZlSFB6d1l4MEJRTjZvUWtHeER1KzdNeTBxS2tvdWFkZE9SOTZqRXJCSmt5Zkx1QWtUQ3UxU1pwVWtQek50bWpSdjNsejN1RU1WeSt2YXBZdU92RXNWYUh4bkpqVmxja3N0ZGEvdzBJUDJ2blEzWlNVbnk4N2hJeVRMaFNKdXFrTDMrQ2VmOU93U2ExTSsvT2dqbWZMMDB6b3FlRjA3ZDdZVGRTL3BmK09OUHZtNklFR0haNVRxMmxsSzlycE9Sd1paSHhaN3gwK1M1SFhyZFFjQTVNMndCeDd3bVprYjllOTg3ZVdYN1Vyd1hxVUdVbDJzUVY2dG1qVjFUK0dpQnJjUER4OHV0OTE2cSs1eGozcnV4ejcrdUd1ejl2bnh4TGh4ZHEwQTVFNVU3TFZTcE8zRk9uSlA4ckxsY3VDdEdUb3lSNzEyVlRIRnh3MmZkdUJGVTZkUDk4d1JoT29tWDZYb2FCMFZ2S0pGaThwVlYxMmxJOTlDZ2c3dnNDNncwU05IU0ZnZDg1VVdzNUpQU3Z4ZDkwbUdIMWMvQm1CZXZYcjE3RHYwdmtBTlh0VmV2SmlZR04zalRXcVE5L3ZpeGZiWnVvVnBSaXc0T0ZoR1BQU1FQRFpxVklIOTNPcjFySTUxOC9yenZudjNiaGsvY2FLT2NGYUJnVkpwOUVnSmlJalFIZTdaLyt5TGtoSnZmcW03dXJrMTR1R0g1WldYWHBMSUF2ZzVDNEphdnIxdy9ueDdaWlFYaElTRXlJMzkrdW1vNEYzVXRLbFVyRmhSUjc2RkJCMmVFbFMwaU1TOCtLd0VGamRmOENNdFBrRjJqaHh0NzVVQ2dMeFFpY3lUVHp3aFZTcFgxajNlby82TkkwZU1rQWNmZU1DTzY1eDNudjJubHhVcld0UXUvdlRCdSs5S3hRb1ZkSy8vVXVmY1B6dDl1bjNlZVVFdkVYMWc2RkRwMEw2OWpyenJSU3NSMjdoeG80NXdOdUhWcWtuNVlVUHN5UkEzWlo0NElmRkRoMHVtQzNVRDFMWHUxbHR1a2RtZmZTWmx5N3A4eEp5TFNwUW9JVStPSFNzL0xWb2s5ZXZWMDczZWNGMXNyR2RxV1Z6ZnQ2L25ielptaHdRZG5oTmVvN3BVZk1KS25GMFlwQnliTTFjU1AvaElSd0J3N3RReFdLKy8rcW9ubDdxcldWazFJM3I2ckd5NWN1WHNQNzFPL1h1N2QrOHVmeTVkS2pmMTYrY1RTNi96b21yVnF2TE5uRGx5KzRBQm5oaE1xbG13OTJiT2xFYm5uNjk3dk1rK2RtM0VpRUpicXlBdnl2VHBMZUVONit2SVBTZi9XaVVIM25wSFIrWjE3TkJCZnYvMVYvdXNkRjlOME01RUpiNlhYWHFwL1BuSEgvTFE4T0dlL014UnEzQzhNR3V0S3Z1cjJnUytpZ1FkbmxTcXk5VlNzcWNMKzlHdEQvWjk0NTZTazNHYmRRY0FuTHVPSFR2SzFDbFRDbnoyODNScW1lY0x6ejRyajQ0YytZOS9WNmxTcFh4cTBLcG13bDUvN1RYNStjY2ZwWFdyVnA1Nmp2TkRKY0szOU84dlMzNzdUZHEyYWFON3ZVRWR1L2JGN05tZVQ5TFZzV3Z6NXMzVEVjNG1NQ3hVcWp3MVhnTGN2dGxsamJVT1BQK1NxMk10dFpYbnU3bHpaZHdUVDloN2tYMlp1bDQzYU5CQXZ2anNNNW56NVpmMlRUMnZVamNOZW5idnJxT0NvNjZwNnJQT1Y1R2d3NVBVMFNEcWZQU3d1dWFYWW1hcS9laUQ3cGVNcEdUZEF3RG5idUR0dDl1VmhMMlFRS29sOTNPKytrcHV2ZlhXLy9uM3FKa0ZWWUhlbDZnQjZnVk5tc2lDSDM2UUw2M0VVU1hxdmt6dGpmemVTaDVlZWZsbHord2YvYmZLMW10SUpUaHFOdEtMMUd0Q25VaFF5Y1BiUzd3bzRyemFVbWFnKzBVSU01T1RKV0hZdzVLWmxxWjd6Rk9yYm9ZOStLRDhzWGl4ZEx2bUdwK2NUYTlicDQ2OC9jWWI5bzI4SzY2NHdpZHVVSHJodURWZnIyRkNnZzdQQ2lwU1JLcE1teXlCTHB3em5McDVpK3g2Ykl4ZDRSMEE4a0lOQnRUKzNiZGVmOTNlUTEwUTFMK2gzL1hYMjh2Q3M1dVZWVE1jQmZYdnl5KzF4Rk1OVWhjdFdDQUw1czJUWGoxNytzeFo5T3Azb3hMejk5OTlWMzc5K1dkcFkvMSt2RDZBVkRQcGFzWk9GYThMOTlBV0ExVWM2NFAzM3BQdnYvMVdHdFIzZjhtMlQ3TmVjK1h2dWxQQ3JFVGRiYWRXcjVWOXo3Mm9JL2ZVcmwxYlpuMzhzZnk0Y0tGY2Nmbmxuai92WDFITDh6OTgvMzFaOGVlZmNyMTFUZmVsTFQ1cW1YdjE2dFYxNUw3aXhZdjd4SkdST1NGQmg2ZEYxSzBqRmNlT3NsNnA1bCtxUnovL1NnN08va0pIQUpBM2FqQzFkTWtTVjg4YlYzdk4yN1Z0S3o4dldpUnZ2dkZHamt2NzFOSnFOWXZ1eTFSaTI5YjZlZFZlNmExeGNmTFV4SWx5NFFVWDJNK0QxNmlDVGoydXUwNStYTERBVHN4Nzl1amhVOHYwMWV0bDdKZ3hzbVR4WXVuVXNXT0JQY2Vxa0o3Ni9wOTk4b245UEhhM25sTi8yZTdnTnJYVXZkSzRNZXJDb1h2Y2svanFHNUs4dm1DT3VXM1ZzcVY4OWNVWHNselh0U2pqc2RVcmF1KzJPbUx4THlzcFY2dUYxR3ZjaTllMHMxSHYxZGh1M1hUa1BuV2Q4UG5QdUN5RDFUV3kwdE5sVTVkWVNkMFlwM3V5RnpWb29FUVBHNnFqZjFLVkh6ZTBhaThaaHc3cG5qTnJzSGE1QkVaRzZnaC9TM3h6aHV4NVlvS09uTlV3Ym8wRUdMNTRaR1ZtU3NLSVIrWG94NS9wSG5NQ3JJRkl6YTgra1lnNmRYU1BOeDJadjBBU0JnelMwWm1WNkJFck1aUFAvSHZQeXNpUXVNNnhrckp4ays3SlhzbHVYZTJWRFA0cTdjQUIyVFZ1b3ZXY21GMDlZUStJSG50VWdsMDRvY0NFR2UrOEkvT3NBWU1wbDNicUpEZjM3NjhqLzVCaHZjKyttak5IeG93ZEsrczNiTEJqcHhXeFB2TlVvdnJJd3c5TDgrYk5jejB6cENwZy8yWWxYRTRhZE9lZDBycDFheDI1VHoyL08rTGo1UXRyQVA2NTliVjIzVG81ZXZTb2Z0UTk2dVpCeVpJbHBkbEZGOW1KZVRkcm9PckxleUZQbDJsOUhxOVlzY0krNG16QndvVnk0c1FKL1lnWmF0YXdSbzBhOXA3Vy9qZmRaQys3TjVHVUo0d2NMZW5IanVuSW5LanIrMGp4VmkxMFZQRDJ2L20ySksxWXFTUDNoSjlYV3lyZWM1YzltMStRMVBWaDd0eTVNbVBtVFBseitYSTVmUGl3ZnNRZDZucXRpb3gydU9RU096RnYyYktsUlBwSkhxTSs4OGFOSDYrai8zVXlPVm0rdHA1N0U1K0w2c2F0V2wzbHkwalFDd0ZmVDlDVkRPdURjL04xdlNWMXl6YmRZMDVZN1ZwUzY4dFBKREE4WFBkNER3azY0RHZTMHRMa2o2Vkw1WlZYWHBHNTMzNHJ4NjJrSnErRGtrQnJRS3RtTkZVeXJnWWduYSsrMms1YXZMNVUybTFxYUhQdzRFRlp2WHExZlB2ZGQvYmdlOGtmZjBpNk5TNVJYMDVTTTF4cW9LMFM4aGJXNytWcTYzZWlpcXVwSk4yZnFiUEl2N0VHMkxNKytjUitiaytlUEdrbjhQbWhYdHRxeFVGcksxRlJTMVRidFd0bkY4VHloU1hKOEcxSGpoeXhyeE9xOE9EaXhZdGw5Wm8xOXJYQ3lRUlNYU3ZVbGh4MXJiajhzc3VrZmZ2MjloN3ppRUp5YnZ2cFBwczlXM3IzN2FzajU2am5kMWQ4dk05c2Zjb09DWG9oNEE4SnVwSzhicjFzN1htRFpDV2JMK1pXc25jUHFUTGhpUUsvdTVzZEVuVEFONTA2ZFVyV1dBTS9sYkQvL3Z2dkVwK1FJSWxXSWhsdkRTaFVnbk02dGYrM2ZMbHlkaEV4VmZTdFdiTm0wckJoUTJuY3FKSGZKMzhtcEZwamlaMDdkOHFhdFd2dFB6ZkZ4Y25XclZ2dGdibWFTVXRLU3JKbjRNOUUvUTZpU3BlMm4zZTF2N0dhbFRUV3ExdFhxc1RFMkwrVHlwVXFGY3BCOXQvVWM3ZldlbDVYcmxvbDY5ZXZ0MmZQMUd5a2VsNjNiTmtpL3g1b1ZvcU90bWNPMVpjNjUvNkNDeTZRbWpWclNpUHJ0UjFUcFFvSk9RcWNXaDJ5YmRzMmV5V091bDZvbTFESGpoMnp2OVExWS9lZVBaSjhodkdvU2d5aksxYTBielNwNjRXNmdhcHUyS21xOHVkYjE0b3ExdXRiM1lncXpOUm5YWXZXcmUxcmhkUDYzWENEdlBYR0d6cnlYU1RvaFlDL0pPaUtPck44enlPamRXUldwV2NtUytscnV1cklXMGpRQWY5eHRvOWhac2ZOeSsxUWlOL0Z1Y25wZWVXNWhLL0t6ZldDMTNmMlhudjlkUmwwenowNmNvNjZzZmZEZDkvWkJUaDlIUWw2SVhCazloZHk0T1hYZGVTc1dsOS9iaVhvTHQ3cHRsNnV1NmM5S3ltYnp2NmF5cS9BWXNXazhwaFJFdVRCMXhRSk9nQUFBSHpKdm4zN3BQRUZGOGpCcytSMGVhRzJDL3kxZkxsZnJNQWhRUWQ4RUFrNkFBQUFmSVZLT1crNTlWWjU3NE1QZEk5ejFJcUYxMTU1eFM0bTZRODRud0lBQUFBQVlNejdWbUp1SWpsWHlwVXJKOWZGeHVySTk1R2dBd0FBQUFDTStQWFhYNDNzTy8vYm5RTUgrdnpaNTZjalFRY0FBQUFBT0c3VjZ0WFNxMCtmTTFhOWQwTEZpaFhsdm52djFaRi9JRUVIQUFBQUFEaHEvb0lGY3ZrVlY4aitBd2Qwai9PR1AvaWdmZnlsUHlGQkJ3QUFBQUE0SWkwdFRaNS80UVc1TmpiV1NNWDJ2OVd0VzFjRzNuNjdqdndIQ1RvQUFBQUFJRjlVcGZiMTY5ZkwxVjI2eUpBSEhwQ1VsQlQ5aVBOVTVmWXBreVpKYUdpbzd2RWZKT2dBQUFBQWdEemJzR0dEM0Rsb2tGellySmtzK3ZGSDNXdE9yeDQ5NUlyTEw5ZVJmeUZCQndBQUFBQ2NrME9IRHNuc3p6K1h6bDI2U0tNTExwQTMzM3BMMHRQVDlhUG1SRmVzS005TW42NGovME9DRGdBQUFBRElVVkpTa3F4YnQwN2VldnR0aWIzdU9xbGVxNVpkb2YzN0gzNndsN2U3SVR3OFhENTQ3ejJKaW9yU1BmNkhCQjBBQUFBQUlKbVptWExxMUNsN2RuekR4bzN5MVp3NU11cXh4K1R5SzYrVVduWHEyRXZZQjk1NXA4ejU1aHRqUjZkbEp6QXdVQjU3OUZGcDNicTE3dkZQSk9nQUFBQUFVTWlkT0hGQ1dyZHBJNDJhTkpFYXRXdkwrWTBieTNVOWVzakVTWk5rNGFKRmtwaVlLQmtaR2ZxL2RsK2ZYcjFrNkpBaE92SmZKT2dBQUFBQVVNZ1ZLVkpFZHU3YUpkdTJiN2VYczN0SjJ6WnQ1T1dYWHBLZ29DRGQ0NzlJMEFFQUFBQ2drRk5IbDdWdTFVcEgzdEgwd2d2bDAxbXpKQ0lpUXZmNE54SjBBQUFBQUlEVU9lODgzZktHaTF1M2xybmZmQ09sU3BYU1BmNlBCQjBBQUFBQUlNMmFOZE90Z3FWbTg2L3Awa1crbmpOSFNwVXNxWHNMQnhKMEFBQUFBSUJVcVZ4WnR3cU9TczZIM0grL2ZQakJCMUlrTWxMM0ZoNGs2QUFBQUFBQWlZbUprV0xGaXVuSWZTVktsSkIzWjh5UXB5Wk9sSkNRRU4xYnVKQ2dBd0FBQUFDa2VQSGlFaDRXcGlQM0JBWUV5R1dYWGlyTGx5NlZYcjE2NmQ3Q2lRUWRBQUFBQUdEUFdydTlEejI2WWtWNTZjVVg1YXN2dnJCbjhBczdFblFBQUFBQWdLMUJnd2E2WlZaa1JJVGNQV2lRckZ5eFFtNjk1WlpDY2NaNWJwQ2dBd0FBQUFCc0Z6WnBvbHRtaEllSHl4MERCOHJLdi82UzZWT25Tc2xDVnFYOWJFalFBUUFBQUFDMk9uWHE2SmF6cXNiRXlOakhINWZOR3pmSzg4OCtLOVdxVnRXUDRIUWs2QUFBQUFBQVczUjB0QlF0VWtSSCtWUEorcnY2WFgrOWZEOTNybXhjdjE1R1BQeXdsQzlmWGorS015RkJCd0FBQUFEWWloWXRLdVh5bUVTci8yK2Q4ODZUTysrNFF4Yk5ueThiMXEyVHQ5NThVenAwNk1BZTgxd2lRUWNBQUFBQTJNTEN3aVNtU2hVZG5WbEFRSUJkNUUzdEgyOS95U1Z5MzczM3l0eXZ2NVlOYTlmYVJkK2VlK1ladWZqaWkrMzk1amczSk9nQUFBQUFnUDlxMmFLRi9XZTVzbVdsY2VQRzByRkRCN2t1TnRaZW9qNXp4Z3laUDIrZXJMZVM4VjN4OFRMdnUrL2s2Y21UNWRKT25lemw2OHlVNXc4Sk9nQUFBQURndjBZOStxaWtuVG9sdXhJU1pObVNKZkxkM0xueTBRY2YyRVhlK3ZUdUxXM2J0TEgzcW9lR2h1ci9CNXhDZ2c0QUFBQUErQzhTNzRKRGdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSHVBakNYcUEvYit6eVR4MVNyY0EvNWFaZkZLM2NoREUvVGNBQUFEQWwvakVDRDR3TkVTQ2loWFRVZmFTVnEzUkxjQy9uVnkyWExleUZ4SlZScmNBQUFBQStBS2ZtV0lMdjZDeGJtWHY2TmR6ZFF2d1gxbHBhWExzaC9rNnlsNW81V2pkQWdBQUFPQUxmQ1pCanp5L29XNWw3OFM4QlpKKzZKQ09BUDkwN0pkZkpYM1BQaDFsTDdKRk05MENBQUFBNEF0OEprRXZlbkVyNjErYjgwYjBqS05IWmZkVFQ0dGtadW9ld0w5a0pDZkwzdkdUUkxLeWRNK1pCWlV2SitIVnF1a0lBQUFBZ0Mvd21RUTlyRnBWQ2ExZVhVZlpPL3JwNTVMNHlXYzZBdnhIVm5xNjdCbzVXbEkzYjlVOTJTdmVxWU1FQlByTTJ4c0FBQUNBeFdkRzhJR2hvVktxVjNjZDVTQWpRL2FPZkZ3T3ZQT3VaRmx0d0I5a0pDVkovSU1QeTlFdjV1aWVIRmlKZWFuZVBYUUFBQUFBd0ZmNDFCUmJWTi9lRWxTcXBJNnlwMllhOXo0K1RyYmZmcGVjMnJxTkplL3dXZXExZk95blgyVHp0VDNsbUVyT3o3SzBYWWxzY1pFVXlVWE5CZ0FBQUFEZUVwQmwwVzNIcWVSaVU1ZFlTZDBZcDN1eUZ6Vm9vRVFQRzZxajdPMS81WFhaTjNHS2pzNHVJRGhZSXBvMWxhTHQyMGxFclJvU1ZMYXNmZ1R3cUt4TVNZdmZKU2MzYnBUajMvOGdLWnMyNndmT0xpQTBSR3A4K29GRU5zdzVRVmVyUytJNngwckt4azI2SjNzbHUzV1ZLdE1tNndnQUFBQ0FLVDZYb0dlbXBzbm0ySjZTc202RDdnSHd0MUkzWFMrVnh6eW1vK3lSb0FNQUFBRGU0M05WcEFKRFE2VEsxRWtTV0tTSTdnR2doTld2SzlFamh1c0lBQUFBZ0s4eG02QUhCRmoveS9sb3RQOUtUOWVOczR1b2M1NVVtajVKQWtKQ2RBOVF1QVZYS0MvVlhuOUpBc1BEZGM5WnFIVXp1Vnc4bzdhSkFBQUFBRERQZUlJZUdKbTdtZTdjSEIxMXVwS2RPa3JGOFdQc1BiZEFZUllVVlZxcXZmMmFoRmFzcUh2T0xpc3RWVEtPSDlkUnpvS3JWOVV0QUFBQUFDWVpUZERWT2N6QnVhaTZycHphc1VPM2NzbEsvcU42WENkVlhubEJBb3NYMDUxQTRSSmFwN2JVK09SOWUxWEp1VWcvZEZqUzl4L1FVYzVDS2xUUUxRQUFBQUFtR2QrREhuWitmZDNLV2RxV2JaS3ljNmVPY3E5RSszWlM2OHRQSktKNVU5MEQrRCsxN0x4azMxNVM2N09QSkx4YU5kMmJlOGNYL3k2U2thR2pIQVFFU0ZpVnlqb0FBQUFBWUpMeEJEM2l2TnpQN0IzKytEUGRPamRoVmF0S3pmZmZrZWhKNHlTa2FoWGRDL2lob0NDSmFIYWhWUC80WGFreWJvd0VSVWJxQjNKUFZYQS8vUEVuT3NwWllFUzRoRlUvOXhzQUFBQUFBTTZkMFdQV2xMVEVnN0toUlZ1UnpFemRrNzJReXBYa3ZPL25XRWxCaE80NWQ1a3BLWExzeDUvbDREdnZ5cW5WYXlYeldPNzIyUUtlcGJhS1JKV1d5Tll0cGN5QW15V3lYajBKc0JMMXZFcGF0VnEyZGU5ckg0TjROcUUxcWt1ZEg3NnhaOUlCQUFBQW1HVThRVmMyWGR0RFVsYXQwVkhPeWc2NVZ5cmNkN2VPOGlmOXlCRTV1WEdUSkM5ZklTbWJOa3Y2c1dPU2xacW1Id1c4S3lneVFvS0tGNWZ3Q3hwTGtTYU5KYXhhTmJzdnYxUlN2cVh2VFhKeTJYTGRrN1BTdC9XWFNvK08wQkVBQUFBQWsxeEowUGU5L0pyc2YrcHBIZVVzTURKU3FuL3luajFMQ01CWkI5NTVUL1krL21UdWpsZ0xDcFNhWDM0cWtmVjVMd0lBQUFCdU1MNEhYU25aK2FwY0w4bk5URTZXK0R2dnkxUEJPQURaTzdyd1I5azNibUt1eno4UHExVlRJczZyclNNQUFBQUFwcm1Tb0tzcTBFV3Z2a0pIWjVjV255QmIrOXdvSnpkdjBUMEE4c3hLeUk5OCs3MGszSFh2T1czeGlMcmxKcnRhUEFBQUFBQjN1SktnSytYdXZQMmNCdnZwdS9iSTF0amVjdWp6TDNOVnpBckEvOG80Y1VKMlRaZ2tDZmNNa2F5VVZOMTdkaUhWcWtxcDJHdDFCQUFBQU1BTnJpWG9rZlhxU3ZIWXJqcktuVXlWWEF4OVNMYmNjTE9jV0xxTVJCM0lwY3hUcCtUZ3A3TWw3b3F1Y3VpMXQzSjM1dm5mQWdLazNIMkRKREEwVkhjQUFBQUFjSU1yUmVMK2xuWWdVZUk2ZDVNTTY4OXpaaVVOb1RWclNORjJGMHVSQzVyWTdhQVNKZlNEUUNHWGxTbnArdy9JcVUxeGtyUmtxWno0ZGJGa1dIRmVGTEhlWTlYZmVrMENBbDI3ZndjQUFBREE0bXFDcmh6NVlZRzlGMWJTejJGR0x6dWN6UXo4UHdmZXlvRWxpa3V0T2JNbHJISWwzUU1BQUFEQUxhNG42Q3FKMkRQcGFVbDgrWFhkQWNBTEFzSkNKZWJWRjZWNHV6YTZCd0FBQUlDYjNGL0RHaEFnRlI0Y0lpV3Vvd0FWNEJsQmdWSmg5RWlTY3dBQUFLQUFGY2dtVTNVbWV1VnhZNlRvcFIxMEQ0QUNFeGdvNVI0WUxHWDY5TklkQUFBQUFBcUMrMHZjVDVPVm1pbzdIeHNyUno3NlJQY0FjSk5hMWw1eHpDaUo2dDFUOXdBQUFBQW9LQVdhb051c2I1LzQzZ2V5YjhJVXlVeE8xcDBBVEF1SnFTeVZwMHlVb3MwdTBqMEFBQUFBQ2xMQkoramFxZTNiWmVlREkrVGs4aFZXMHE0N0FUZ3VJRFJVU2x6YlJhSWZlMFNDaWhiVnZRQUFBQUFLbW1jU2RDVXJQVjJPZlArRDdKczhUZEoyeE51ejZ3Q2NFUkFTTEJGTkd0dEwyaVByMXJFNk9LWVFBQUFBOEJKUEplaC95MHhKa2VPL0xwYkVOOTZXazM4c3N4TjNBSGxnSmVHQlJTS2wyR1dkcE15dE4wbGsvZnAyVVRnQUFBQUEzdVBKQlAxMHFmdjN5L0ZGUDBuU2I3L0x5WTJiSkczTE5zbEtTOU9QQXZpM0FDc2hENnRWVXlJYm55OUYyN2FSb3ExYVNGQ1JJdnBSQUFBQUFGN2wrUVQ5SDZ4L3FwcE5UenQ4UkRKT0hKZjBnNGNrS3pOVFB3Z1VYb0hoWVJKVXZJUUVseXdwd1NXS1N3Q3o1QUFBQUlEUDhhMEVIUUFBQUFBQVA4VTBHd0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBZVFJSU9BQUFBQUlBSGtLQURBQUFBQU9BQkpPZ0FBQUFBQUhnQUNUb0FBQUFBQUI1QWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFGVHVUL0FFaTRQaHNXRHBDaEFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0xMi0yMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiVHJ1c3RLZXkgU29sdXRpb25zIFQxMTAgVTJGIEF1dGhlbnRpY2F0b3IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDIwMDgxNDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjciLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTEyLTIxIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0xMi0yMSJ9LHsiYWFndWlkIjoiZWU4ODI4NzktNzIxYy00OTEzLTk3NzUtM2RmY2NlOTcwNzJhIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJlZTg4Mjg3OS03MjFjLTQ5MTMtOTc3NS0zZGZjY2U5NzA3MmEiLCJkZXNjcmlwdGlvbiI6Ill1YmlLZXkgNSBTZXJpZXMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MzI4NzA2LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciLCJlZDI1NTE5X2VkZHNhX3NoYTUxMl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjY0LCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJlZTg4Mjg3OTcyMWM0OTEzOTc3NTNkZmNjZTk3MDcyYSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOmZhbHNlLCJ1cCI6dHJ1ZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMiwxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0Ijo4LCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjEyOCwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fSx7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotOH1dLCJtaW5QSU5MZW5ndGgiOjQsImZpcm13YXJlVmVyc2lvbiI6MzI4NzA2fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ill1YmlLZXkgNSBTZXJpZXMgKFVTQikiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE5MTAxNzAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4xLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDUtMTIifSx7ImFhZ3VpZCI6Ijg4NzY2MzFiLWQ0YTAtNDI3Zi01NzczLTBlYzcxYzllMDI3OSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiODg3NjYzMWItZDRhMC00MjdmLTU3NzMtMGVjNzFjOWUwMjc5IiwiZGVzY3JpcHRpb24iOiJTb2xvIFNlY3AyNTZSMSBGSURPMiBDVEFQMiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCOURDQ0Fab0NDUURFUjJPU2ovUytqREFLQmdncWhrak9QUVFEQWpDQmdERUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQWdNQ0UxaGNubHNZVzVrTVJJd0VBWURWUVFLREFsVGIyeHZJRXRsZVhNeEVEQU9CZ05WQkFzTUIxSnZiM1FnUTBFeEZUQVRCZ05WQkFNTURITnZiRzlyWlhsekxtTnZiVEVoTUI4R0NTcUdTSWIzRFFFSkFSWVNhR1ZzYkc5QWMyOXNiMnRsZVhNdVkyOXRNQ0FYRFRFNE1URXhNVEV5TlRFME1sb1lEekl3TmpneE1ESTVNVEkxTVRReVdqQ0JnREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFnTUNFMWhjbmxzWVc1a01SSXdFQVlEVlFRS0RBbFRiMnh2SUV0bGVYTXhFREFPQmdOVkJBc01CMUp2YjNRZ1EwRXhGVEFUQmdOVkJBTU1ESE52Ykc5clpYbHpMbU52YlRFaE1COEdDU3FHU0liM0RRRUpBUllTYUdWc2JHOUFjMjlzYjJ0bGVYTXVZMjl0TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFV0hBTjBDQ0pWWmRNczBva3RaNW05M3V4bUIxaXlxOEVMUkx0cVZGTFNPaUhRRWFiNTZxUlRCL1F6cnBHQVkrK1kybXcrdlJ1UU1OaEJpVTBLendqQmpBS0JnZ3Foa2pPUFFRREFnTklBREJGQWlFQXo5U2xyQVhJbEV1ODd2cmE1NHJJQ1BzKzRiMHFocDNQZHpjVGc3cnZuUDBDSUdqeHpsdGVRUXgralFHZDdyd1NadUU1UldVUFZ5Z1loVXN0UU85ek5VT3MiXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTFFBQUFDMENBTUFBQUFLRS9ZQUFBQUFCR2RCVFVFQUFMR1BDL3hoQlFBQUFDQmpTRkpOQUFCNkpnQUFnSVFBQVBvQUFBQ0E2QUFBZFRBQUFPcGdBQUE2bUFBQUYzQ2N1bEU4QUFBQytsQk1WRVgvLy8vdzhQRFgxOWUrdmIybHBLU2tvNk8vdnI3YTJkbjE5UFg2K3ZxN3VycDZlSGhmWEZ4R1FrTXNLU29qSHlBekx6Qk5Ta3RvWldhS2lJalMwZExZMTlpRGdZSDgrL3paMk5sNGRuY3hMUzZYbFpXNnVibjQrUGpvNStkNGRYWWxJU0k1TlRhdXJLMysvdjY0dDdjc0tDbFpWbGZ2Nysram9hSGs1T1E1TmpmcjYrdmczK0JsWW1KV1UxU29wcWZIeHNZbUl5TTlPVHBTVDFBL1BEMDRORFY4ZVhyVzFkWDgvUHplM3Q2SGhZVXRLaXE4dXJzdkt5emo0K1B2N3U1ZlhGMW5aR1hSME5Fbkl5VGg0T0QwOVBRckp5aGFWMWptNXVaK2ZIMUVRRUhGeE1US3ljcTN0YmFpb0tHTmk0eTJ0TFh1N2U3R3hjV3hzTENlbkp5Umo1Q21wYVhRejgrUmo0OC9PenpFdzhTV2xKUlZVbE1tSWlOVFVGR1VrcFA5L2YzSXg4ZUlob1pIUkVWa1lXS2tvcUtlblozVTA5TmhYbC9UMHRKS1IwZDdlWGtrSUNHQ2dJQnNhbXByYVduVjFOUXFKaWRyYUdubDVlVzBzN05YVkZUczdPeEZRVUwyOXZZK09qdDJjM1FvSkNWY1dWcWFtSm5NeTh2TnpNeWJtWm82TnpqbjV1YzNNelRwNmVsWVZWWDcrL3RtWkdSaVgyRE96YzFTVGsrVms1T1BqWTNxNnVvME1URnRhMnVCZjM5TVNVcUdoSVZlVzF2THlzdXdyNitxcUtpM3RyWTFNVEx5OHZMajR1SmJXRm5LeWNsQ1B6OHBKU2FxcWFsSVJVYmMzTnlzcTZ1eXNiR3pzckoxY25QZjN0OHpNREV1S2l1Wmw1aWhuNkNjbXByMjlmWEp5TWhQVEUyTGlJbjM5L2RkV2xzOE9EbHpjWEZ5Y0hDQWZuNVVVVktYbHBaTFIwaDBjbkpZVlZhNXVMaERRRUNRam82Zm5aNUpSa1p4Ym05allHRXdMQzFNU0VsbFkyUHo4L05CUGo5UlRrN2IydHJEd3NKUVRVMnBwNmh3Ylc1T1MweUxpWXBnWFY3UHpzNzUrZmxxWjJneUxpODdPRGpDd2NHZG01dUpoNGVycXFwQVBUNm5wYWJRME5DRWdZSitlM3p4OGZHdHJLekF2Nzl5YjNDRmc0U1NrSkZ1YTJ5MXM3Uzl1N3l3cnEvRHdzT01pb3VFZ29QYzI5dVlscGU5dkwxOWVudnQ3ZTNkM2QwMk1qT3ZyYTdwNk9pZ25wOXBabWQzZEhYQndNRGk0ZUZHUTBSL2ZYNk9qSXh2YkczVzF0YWMxMlY0QUFBQUFXSkxSMFFBaUFVZFNBQUFBQWQwU1UxRkIrSUpHaGM2SEkwdDhtQUFBQTJUU1VSQlZIamE3Vng1ZkJSRkZpN0NIVWthUkF5M3dVQzR4SkFBUzdqQ0VRZ29rVlBrVEJpeWlrQ0d5NFVWQ1VIT29JYVFjQ2NZZ3NncHl4RkFFVGNDSWdSdzVVZ011QXJveGd0V0ZQQllWMTEzZjcvTjFPdWVldFZkM1RNMUVTWi85UGRQcHQ1Ui9hVzd1dnBWMWFzaXhJWU5HelpzMkxCaHc0WU5HelpzMkxCaHc0WU5HelpzU0tOU1FPVXFWYXRWcitGdkhsNmladUE5dFlLQ0ZSVzE2OXhiOXo1ZnE2cDNQMFBJSGFSY3YwRkR4WUNnUnI3ZDhjYW9qaVozakhMVEIwSVZJWm85R0ZaUlNUZHZvWmdpdkdYRkpOMHFWTEZBVU91S1NMcUtZbzAyYlNzZTZZZGFlQ0N0dEt0d3BNTWU5c1JaVVNJcUd1bjJPb0tSVVIwNlJ1cGtuU1E3Mnp0TytnSE1MdmdQbmFQTFpDRmR1bmJqV0hldldLU2I5RUFYaUlweHkzdjJ3cVI3Vnl6U2ZWRDlzWDJSb2w4ZHBJbVQrOFRjYWRLQnFQNytuS1lldnRVREtoVHBxcWorUjNqVm8wZzEwT2paTXY2eFFZTUhEeG9TUDFTUzlJQmh3eCt2TytLSndKRSsveitqVVAyamVWVkViNFl4T3JlQXNlTVNOTGZReFBHZHZTWHRtSkQwUjlib25ueEs3Z2xxbUlnYndXTmVPajA5U2QrVDE1cnNGZW51VS9RZGJISlRIMGczeDFVNHAzcnp4TnBPY3lvR09LZWpqNzBKNlJtSlJqOWxabEpOYWRKOStDb2FQaFB4Snc4ZW5hTVVJYUpZR3hHVG5tVVNMOHorc3l6cEdzYWFucDFhYlk2NVErTmd4UVRCalMxSkR6YnpVNTZyTDh0NnJxaWFsSG1wOWNUbTgyTk5yNjJrUEc5QmVvRzVuN0pRTm82Y2IxWlRtd2VHVkRKWUwxcHNjVzJsMlJKVDBnTVRyQnlYcGtteVhtWmVWOElMTC9LMmpwZXd1bHV2OU9YaE03RmtkcGdKNll3VjJLeFQ1dU5aSzdtUnh5cEowcFZNWGl6QTZqWFlkaTNTUks2anNWL05WTnlYckRjaC9RaVNaTU9keUptT1pMRWJKRm5mdDBLeHdzdTVic3VRalV5Y0Y2aEpONkVuLzRwRFNIb0RlaE1XYmxiOW9oc2dzN21TcEVucmxaYXNsZkdhNGF0SXVJWDU0dy9VVmlIcGJlZ0JiV2VPOXpKeHdrT3lyT2VNMkdISk90a0JkaWhjallwRzdtaktwTGVJZE5wT1ZzNUUxMzBSMmIwbVM3cnN1cnRHVzdIK0N6WGFuY2NramJEM0tpYmZtU1lndlFlVnVYZGtMNU92bGlkZDFsNkhXelNTdk9vdWsrN29hWEpmc2I3SWRJK0E5RDVXbk1KZGRCMjZSTDR2ckFtSmlaaGUyNFQxZnBjK2laVVA4SjdvOGFjTFNNOW14WU9jM3d4a09OODMwbVZ3OUVsL2VhYUF0Tk1WUTc3T3lvbThXeERUdkNFZ2pUcWRmWnpmVUdTNDNtZlNMalJwdi95UUlZNTdzMHhSaXhXZjRWMzJNODAwQVduMElBYnhqbkZNODFTNVNMdlFPajJJSiswYWloMW14YW04K1Z0TTgxY2o2WHhVTE9BZDMyYWFJK1VtWFlhalhHajBOdDhJa25qYmUvaUdveU9kZzRyVmVNZGpaZzNIVjh6SGpidEZtU0NjRmQvaFRZOHpUVzhqYVlLNlN0MWsxYnRNTTlGYlh0RjFUakRzMFd0UDRsdGRTRWdtM3dnUVVNTkpGcEJHMFEzZkNQb2h3eTNFV3l4RVhsbDY1U2FrZEpZTmlySlk4UlJ2aVQ2b3l3V2tUN05pQTg3dkRESWM1alhwcGNpcm8xNDVIQ2s3RVM3MDREOEZMWkZoZ1lCME1pc3U1YTVRZ083S1VPSXQwR3V2S08vcGxLaGZWdjVXVm02TE9zSk4yRENWeVdNTEJhUlIyZGtGTzZKM1lhL1huTW43bUhURDZwd3VCbjhlenhMK01aOURoZzRVdDRRVEFlbCtxQ1BLUW81OTBWMDQ3ejNwSE83ekY0V2ptYzZkc0lvT1doc2hBUnJUWUk0VFJhVEpCVmJ1VWNnYzcwZDJSZDZUeGoyQ0MzVmUzVkRzRXM4cCtDQVB5MnZUeVltY0VpYTVlRWFyb2dnOWtlemRRdEo0SURvN1IzT3Nna1pjOHlRNGsxekZnQldIbjMxWEwxTWY2bGdrMmpFU1pKZnduTUtIUkVnYU4xNWxwUm9oanNjWGtBdVhraFV2c0ZoZGw2dUJtMHhrNHQ4ck43Ly9IQjZnWHN3M0lUMEREOFozVG1yVS9xTzVIK01MUENuRm1mU3pITmVxY0UveXhjZGFtYVVVRVJQUzVFUEwraS9LVGpLTkxGRThBWDBScWxyWlhTYW1wTWxaQzcrOEs1S2NDYW5meGdQbnEzZ2RJTW5jemgxRmlValA2Vy8rZ0xaS2N5N3JrTTlaVVk1c3hGdEhtTFNRV0JZTENlZnkwajR4dVVEMkdxK1pZamdpc2swNWp3dlFXK2NlRU5rZFlOTWpabE85VCt3VU9YYVFYOFpXOGVrUjhXajgzRDhFUzBURnV6cnA3UllmTFVZR1pwUHFQWk1NYzdSVEdudWlab1d3K09UbmRCV2VXbVUyQjV0LytTUzZmTnlUVlhaejZwRm80WU9mV3N4NGN5bnEvTElQTnZZbE00Tkh5NEVMN3NtYzlQQ1VPdjE3Ynh0VjJ0UFN0dmhTNnFyUDl1Ly83UFBVVXJrRm4wcER4bVpsaGsrYXUrL29TRWU1R2R1d1ljT0dEUnMyYk5pd1ljTkdoY1hsY0JlK01ORnVvZHJ3L3I2dlRONFIxS1ZEekMvRnlxM3FLSFNYdjFsS2tQNUs1ZHpLM3lRbFNLK0hQR3BuVlg5emxDQmRvSEord3Q4VUpVZ0h3cHlkODMxL001UWdmUTA0aDI3eW9VNS9rYTZjQXB4ZjlUYy9DZEtsc0V3VStxQy82VW1RdmdTY0U2NzdtNTBFNlgvQzZtTENjSCtUa3lBOUVQSmRFbnhaVmZBWDZmYkFPZklyZjFPVElMMEhwc3NqVFhQdHc5WWtUUjgzdXMzZWRzbHIwWkl4Y1RSeFFaeWVXMHgxckR4ZzJMcXZ6NDQ3bmpYeFd2WDgzNE4wTGl6QXhqWTNzYys0Z1hKRThrNnlIUTdmVUVtVVErQ3ppQzZRdWxQeTRsRUdseEo4dmhLUmhvNzBHdGovRkd1eUZCSjlGTzlBY3VGMWQ1NEc1STZNRVhoOWkwUEZDZUc2R2hxTzNVMGt3Wk4rSGppbm1Held5dGlyR0xCRGk3VWhUL2tkZ1J2ZEpSTDNLZjFkV2JCak0wcDJ3WllqWFFTTFppazN4Yll4cDdSbWNmcFcwb1ZtYW1Hbm1rVlJUSk9DNG5JTWJwT3BHZVErZGxGekJmTGVycld0M1dFdHMzWmVOSkVDSmowU25uMWVOYkhwQm1qTm9lYzd3K3QyK3pva1RmU1lBZnJQYWNrWUZFSmFSN3pyWnlHa3lZMityTzRUdWJJTThsUys5cGwwSDdnTGVhVml5K2hEVkwwUVpaVTFuVWRGaDJHLzRuZTAwRUh2Ri9LOVN4eEVmLzlBVFdhalBtWVBEY3ljN3hFWk1OS1QxWWVWTWtOc09ZSnFlM0VyZFE1d2gxUmxBc3ZmMytqOGJpSVRldE5MZnNUcWYxRjFKcEdCbS9UVDdteUVSNFZ2OHhrNkp2aitVOTF0cEM5WnR3eGEyRXJkZGRtUlpCcTlFOURKMEwyeFAvSDZEaTVaYlljdnBEdWpwSjV0SXNOL1U5VVBldkY3VkF5TC9qWHBFcnR1Y3l1a1NjRkw0NkFmZ1JGOERWL1FHcVN5SjFUU0FWeUN2U0JTV2tJRDdIQ2pvcDFMdmhGK1ExNEYzL2RFVUJuc0RReWgvZDFadmdKSXNoOVBKQUNrejhFT2pMeXhNQzdjMmRkZ2Q4VHNmbHlpQ3NoQmVJajJCUjl3ZXByeGZVcGRBNmZkNVBmOGduaklWaGVrWmxicW9odWM5N09XV25YYUVFUFFiVGtsRG1NRmJYRkRwb25Vc1RpWjhSY25hejZFUUFjMFZiSmJ0aUx0NnVzYzBJa1ozcVpDT2dVaTNDQzhHTFdiSWRUNUtOTFNGaHVab1piVUhWekhxNU55Z1pHR2I4b1N5RmZSZDV6WHFQUnhVUTEwSTBrM2VBWnA5RDg0Z2JRYnVmNGlROHYyTzVaK1JYYS9sb2gwU21VUVZJTnYxR0krSG9Ea3gwdHRCYmhGVmVxOTIwY0xNOXgrejlOeXFidU1EbDZZT1c1VndlM3lrZFk0RTNJREJCZTQxK1dxNGdFcUwyakNXVzQvK2gvaGVQVnozdTNYNU92V2VTVldwRkdNVkZQTncxcUF6VDd6UkZvYm05SEdza1BiZ2xwY1l1aVl0elRUZWJiNHBBdVJCSkJPdVlaRTI5V1lHcDlaYzhFVGFTMU9nazI3MnJCbnZhdVFzSWk3WXRxc3BUcGY1N0lBSWdVZ3pYLzZJYXhSVHZWam9wT2VTR3Q3cjBMb2pUeXVsdWhtUjJOT1prQlNJcDhvRjN5TnlFQTQ3M0VRcW5xZFNlaXUxdENZREZPNDQ1WEI5T2JDSHRDaGxGcWc2THI1RThiM1FxZEVKTHhJSkNBa1hVUGRBOFFtbUdCUG1UZUhITFdtbitwdjZlOUJycC9OVEEvYUNMbVNXa3ZMKys0b00rWVNUNHROaHFtOGJ1N05nL0JWOE9wMGtoZGNsaEErMDlSMjZ3RC9sNlFTL1EzeWxiU1doWHRPNndiVzBPSW4zdFFJWjBLNG9wVHQ5QzN6dEJOMU02UW15bVFqbTVBT2V3RlkzMURMTmVrTVRxSTNOVWJUVWRsVm9xWjExL0xvc0ptMi9CM2xKMDF1UTNmcUxGWExOQ1pKRWQyMVdSUExnSWVWTkNCczR5Q0Vubnd3aENuKzQzNEdQR0NNWDB5OGh1bEt3RUFZNjJlcnNRNGtUazh6MnYxSW8xbThYakNBQmxjVFlQb21HeDExUU45TDVUZERGWkR2SzVFb2E3N21jaDRheUdyNG5NK0I5OFdZTnZ3Yi9hcjF3eUk2TGtpR1FXVlhKQjlEcXpoaHFBSUNCNGs0eEp4MENBUy9kQ3VpMi9DMFBxTjFOeDFydjhYSjZGQzJkdHF2cmovNEU1M2ZUWHhMNlJjeVZpSlgxbUpKTGdhbUZDSmhtMFVHRE1oMEhWZ2E3SENld0FrZE5NT2FUb2J4NHpQWW8zUklkejdFQURybGVjeDd6cGFMbjBQVWZoOG1SOVdzNkt2NFcrSDRrc3ArMWQwbEd2blRscjJXazZ2N1hZNXpuNXRpMktpVS9qdVIxalpIL2hkSzZ1NlNZKzdiR3JiK0JKV3MySzd6YTZvbFNaZm8wcFRWTXk3bVhXTC81WnFYcVdpbXAzTkZ2Q2Fkcng0d0ErdHl4ZHBaRHg5MzNUTGhmejlYcWZzS0ZPT0tESTY5VlV2ZHRsYlNVOXVnc25IOFYvRjlseFJ0ZlZNN0pTeFZnck0xYVZJUFZsK0N2Nk9sRU9HK2oxQkJRRlNxNmd5cDduMU50bm9za3hycldwUFc5cldzaEo3Zk1TTE9jTGsyc3dSdTZzYTVRMGJOZHRIQk5Vb0R1Zkc1QjlMa0ovNDV0NTdHWDIzSGdueWgyMVNxL1VqMC83VFNIMnlTa0NsN1JPWk5laWFtZVloVjZRWTF1T3FleTlpYzdqN0FxOFd4STRVbWJzKzY5RDNFWjkra0ZTejdtQjBVVi9LRzdOa2V2bUZSN3F5am96YmxOalgvSEVCUWVNdThpdWlZOXB0KzY3cXJlMEFPcVRDQXJ1MXBmOU9Rd28rMDAzbkozelRrQUVmVUJKYS9vcnVJWEJyVkh5Ny9icUc3Z2R1MDZ3cTdDVkZzQlY2bXhpaFNObDU0NnlkMTNTN0k0Vzg2M3BKbWlKUGZ6ZWwzMGs1dno5N3pPeGpwRks4UHZ2QTdma21FT0RyMFlFejVLN3Q3S0x3eXB2bkFMdm4rcG1IRGhnMGJObXpZc0dIRGhnMGJkdy8vQjJaSElKNkRtNlQ4QUFBQUpYUkZXSFJrWVhSbE9tTnlaV0YwWlFBeU1ERTRMVEE1TFRJMlZESXpPalU0T2pJNEt6QXlPakF3ZnpQWWRRQUFBQ1YwUlZoMFpHRjBaVHB0YjJScFpua0FNakF4T0Mwd09TMHlObFF5TXpvMU9Eb3lPQ3N3TWpvd01BNXVZTWtBQUFCWGVsUllkRkpoZHlCd2NtOW1hV3hsSUhSNWNHVWdhWEIwWXdBQWVKemo4Z3dJY1ZZb0tNcFB5OHhKNVZJQUF5TUxMbU1MRXlNVFM1TVVBeE1nUklBMHcyUURJN05VSU12WTFNakV6TVFjeEFmTGdFaWdTaTRBNmhjUmRQSkNOWlVBQUFBQVNVVk9SSzVDWUlJPSIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiODg3NjYzMWJkNGEwNDI3ZjU3NzMwZWM3MWM5ZTAyNzkiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWV9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA0LTAyIiwidXJsIjoiaHR0cHM6Ly9zb2xva2V5cy5jb20iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlNvbG8gRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkxMDAxMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDQtMDIifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA0LTAyIn0seyJhYWd1aWQiOiJmZWMwNjdhMS1mMWQwLTRjNWUtYjRjMC1jYzMyMzc0NzU0NjEiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImZlYzA2N2ExLWYxZDAtNGM1ZS1iNGMwLWNjMzIzNzQ3NTQ2MSIsImRlc2NyaXB0aW9uIjoiS1g3MDEgU21hcnRUb2tlbiBGSURPIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfSx7Im1ham9yIjoxLCJtaW5vciI6MX1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJhRENDQVErZ0F3SUJBZ0lVSlVyNVRCTCtSL3JGZnpUZkdxOHREZGF3QXdrd0NnWUlLb1pJemowRUF3SXdJVEVmTUIwR0ExVUVBd3dXUzJWNVdHVnVkR2xqSUVaSlJFOGdVbTl2ZENCRFFUQWdGdzB5TURBM01qZ3dPVFEwTlRKYUdBOHlNRGN3TURjeE5qQTVORFExTWxvd0lURWZNQjBHQTFVRUF3d1dTMlY1V0dWdWRHbGpJRVpKUkU4Z1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk1LSTJrRytqbUE3SGFXb3BQZG52aEJ3UmNicWcrbUpSU2FPaFNxZEJmSTAwc2NJeDM5eWVoczROQ0lFZHpsT2dDRXR3SEdoVEZ6SUZBWGFoZ1NoVXBlakl6QWhNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3Q3dZRFZSMFBCQVFEQWdJRU1Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lITTlXOW9uQ0hDSXlpbHdCVmtWK1JVMURzVEpOaWJmeGE2Vi9ISkZQZVFVQWlCNjlxTy93OWJ4ZWJxK1pkNkJ0a1NYalQzSEtmTmVYWVA3UDliL3dNenBqUT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQU1nQUFBRElDQVlBQUFDdFdLNmVBQUFKVkVsRVFWUjQydTJkVFc4V1ZSU0ErNC84Uy93UWRuWWxyS1FyNmFxSkM0MHNNTUZFRFFzV0pEWWFValFnMFZDSlJBc1NCUW9xUmRxeForS1E2ZmpPekwwejk5eDd6cnpQazB5a1dOcDMybm5lYys0NTkyTmpBd0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFLSTVmdkhUWWZ2aUp3SXJPYnAxdTNyNTRjZlY0ZGJsNnVuNXpiZlhpKzJkNnE5clgxU3Y3OTZydkl0dzh1aEdkWHgvcHpyKy92M3ErTnQzVjE4SkpMbjcreS9WdGYyOWF2dTdHOVhGYno2cnp0LzhwTnJhKzdMKytQclBkNnFEbDAvUExlMzVrZnRxMzY5Y20xOWQ5WC9QZjErL1VUM2J2SEJHaXI3citjVkxia1Nwamg2L2MvTHI1OVh4RHgvMHk1QllrRnVQSDV4NVFJWXUrVHo1Zk85aVhQbng2NkQ3bFV0azJYLzJtNDk3Zm5Od2NFNGUrQkF4dXBkRUdxdjNWVXN4RkNHVUJKRUlFZnFnZEI4YWoyS0kzQklocHR5elJCVHo2VlJvMU9pN0pCVXpsVDQ5K0dpNkZETUVrZFJoNm9QU1RrVThwU0NTUHM2NVg3a2s4cGlOSEhQbHNDSkpQYkNXTVVVS01TWUtNalZ5ZUpVa0pxVWF1MFEwY3pmWUhZVFB2V1FNVTBTTzFHSk1FQ1RsdytKQmt0VDNLNWVwTVlta1ZpbmxhSzZzWXd5cFJHbUlFU21JL0dKVFB5eVdKZEdRdzl3WWJPcWczRUlVa2FwVWRFVktVUkN0QjZhNUxGVzR0Ty9WeEJ1Q2pEMDA1R2pLdjZwUjQ0Kzk2dmpPZS9weVJBZ3lkMkR1UlJKdE9jeU1SVjdkM0syMEJORk1zK3F5YlE0eElnVFJTcStzU1pKRERqTnBscVJCbW9MOHM1LytGNW1zZE90WWtGS1M1SktqYVpvaVNHeVZLc2Q0WTZJZzB1aktLVWh1U2VRZFBmZjlJWWdIT1l4R2tKeVNwT3JyeEZ6eVBSSEVneHpHQmRHV3BJUWNqRUZpeGh3UHI1YVY0L1FLZmEybEJOR1NwSlFjWnVabVdSZEV2UUVZY0VsUndPSWdWbnN1VTBrNXpQUkJMQXRTejZrcUxFZnNOQk5aODFIeW9Vb2xTV2s1VEl3L3pBdVNxd2s0RkQwZXhlZkJKYW85S1NVcExZZXB1VmhXQlNuUzYraktjVHIybWZwenpkRlIxNURFZ2h5bXByeGJGTVJDYWlYVFdPYjhYRXRXdEtZK2JDWDZPR1pUSzlPQ0ZFNnQ1c3JSa0dMUlZHNUpTaFlaek1saFVaRFNWYXRVY2lESkF1U3dLRWpKNkJFalI4eDJRRWppVkE1cmdwU01IaUZ5OUMzbHJRc0tJN0pZa1NUbVljd2hpV2s1ckFsU0tucUV5QkhTelI4ckNTT0prdzBhTEFweThtVFhkRnFWcWpUc1VaSVV1NVc0bE1PU0lMUDJyTW94NWtqWVAvRW9pY3p6V2pzNXJBaFNyeXZQS2NkcEtpZmZVN040Z0NRTGtNT0tJRm1YendiSzBhMVMxUkpIUnJtUVRyeUZ6blV1U2R6SllVV1FiT2xWcUJ6dHRTZWRmeE83TGdWSkhNdGhSaENyY2lTU1JENS9uU1Z4SzRjRlFlcXRleXpMMGZNMXBLVGJYRUhDQkRRVkxVZ2lHeVdFcnNNSWtjUzFIQ1lFMFY0dEdDaEhVSlB5TkJVY0xEUU1pUkxZZGJjZ1Njd3Vqa1BGQnZPN3RYc1FSSFd0ZVVTMWFsU1FGVjlMZWpmZHYrdEwwV0orSng0bGFUY1U1ZlhMd3JHTkpWQmNFQ09sM01GR1pUZTk2cTVWRVNsYUVlTE0vKytPWHdMbmNIbVRaTEVzVXBDQVFYRnd1dGQ2d09zMGFxQWYwbTQ4MWw5cmFIRHZaT0MrOXBLVUZFUmxZVlJBNU9nKzZQOTdzRmM4eEdOeWpIWG5RNnBqU0lJZzZvS0VyQ0ZmMVhkcC83dGFrZ2x5ckpKa2RQQStFa21zckV4Y1cwbEtDcUl4dlgzT1lIeFZVeTlXam03VkttUVM1dGljTUF0UnBKRUVRVHdMY245blBIcU1WTTNha2t5V283V1hWbENVSEhuZEZ0YUtMNmF2c2M2Q3lKeXVGRjM3M21yVlJGbER4azFhODU4V2ZmSVRncFFWWk01NWgwMGtDcDJwN0NXQ0lNaWFwMWhKQk9sRWhOSHBOQ092VzJQQkVpa1dnL1RwMzdNWllFK1pKOVpUdWgzNldqS1FIM3JOTWorS1FUcGwzbnhsM3FHQmQ2ZnNHalZYYkVWanNEM29YeW5Kd1B3dXlyd0lvcktEWW15anNLOHhHQ1ZKdCtQZVN1VjZKUWxvRkZxSUhqUUtsemJWWkVvM2ZjVkRQUHJ1MzRvQ285TlJKa3gvb1l1T0lCdVcxcDJ2RW1GVWtvaU9lOHc1SThpQklMTkxxYWtsNlV2NXVoMzJ0NHVsdWxOS3hwcUtBVlUySzNMRWJ1Z20xYTFtWFFqVDNWTXVtTkxlc0NIUm1wQ3hkLytRZGZVaEVjU2JIRU1McGhaUkVtYkpiVndKV0tKSkhUMmU3TmIvUFRQMkdKSmtnZXZTUTdZdVlzbnRPbXphRUZuYWpaVkRIclFseXNHbURha0V5WFhFczR3UkFsYnpKWlVrUUE1dkc4aE5lYzFzKytObDQ3alFuZHhuU3FMMW9IbVVnNDNqdkcwOXFpZ0pjckQxcU03bTFiblNyTmhqRDJLbnZBZWtjT3NxQjV0WHp6bitJRWMxUy9Gc2tGQkJQSjQySmV0UlVyOW04d2ZuV0JPa2ppTGVEOUJ4c3FON3JCeHJlN3FVTlVHc0g4RldSN21lTXU1U0l3ZEhzSEdJcC9vaG5qSmxIVGs0eEhNWngwQ1BMRjZLeGNwNmNxdHljQXgwcENDaDg1cFVKWG1ZWnVVY2NpeEFFcE9DS0Mya3lpbUp6R2IxSm9lRjEyeE9Fb3VDVE9vL0dKUEUyNWpEMG9SSlUzMFNxNEpZU0xWQ3R4THFJbHZqbEg3SVpDZVVxVDkzQzVLWVdVOWlXaEFEcVZiTTRUZE5PYmYwd3lYamlMblBSV2xKWkMwK2dvU2tXZ0Y3MjZwZmdTc0JoZlpCTWw3bHNDS0ppZVcrMWdXSm51cWhkSVcrMXBLN2tLU1V3NElrSm81dzh5Q0lDVWtDMDZ3bHlWRTZLcHJZNXRTTElQV1lwTUNNM3hoQlNtM3lwaWxIU1VrUXhGUDUxNmdnT2VRb0pRbUNlRXEzREFxU1U0NFNrcGdRNU5YTlhWVkJ0RjUzOWpsYmhzWWcwb1FzSVVkdVNVd0k4dWJnNEp5V0hJZGJsMVZ2c082VDVKcjlHeWlJZGhYTHltNkhPU1F4VWNVU25sKzhwQ0tJcEc4NVhyL3E3b3lSZ21pZTVXRnRLMUJ0U2N6YzY5R3QyOG5sZUxaNUlhdjlkVU5STTVwRWROUFhhWjljTFVuTW5XUWw2WkRINkpGdEFCOGhTT29vWW4wVGFZMGo0c3pkcjR4RjVGMC9oUnd2dG5lSzJsOXZJNVE2N1lvUUpHVUgyc3NPNnluWGtaZ1plMmhJb2owd0x4WlJJZ1ZKSVltMzR3ZFNTR0orU3lDUlpHcTY5ZWVWVDgzZVhEMUdtZE9KbnlDSU1IWHF1NXR0Y1RySU5QV3BhMkhNUm82K0JtSm9OSkdVU3FNaHFDcExiQW8yVVpEbW5UVzAvQ3VmVjdMSFVXTHc3bnB6NjlkMzc5V1JRU1JveXNFU1llUmprVWdpanVkZnBEejQ5WEVHa29vTlNUTkRrQVpKbDJRQUwxR2xTYjlFQ1BsWS9uNHhoODUwM2h4RUFMbkhKckxJbitYdlhFVU1XREhRLzI5cm54UnlBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBZ0cvK0JRQjlkOEg1OUNaSUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiLCJjcmVkUHJvdGVjdCJdLCJhYWd1aWQiOiJmZWMwNjdhMWYxZDA0YzVlYjRjMGNjMzIzNzQ3NTQ2MSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzEsMl0sInRyYW5zcG9ydHMiOlsidXNiIiwibmZjIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDMtMjciLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IktYNzAxIFNtYXJ0VG9rZW4gRklETyIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI3MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDMtMjcifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTEwIn0seyJhYWd1aWQiOiIzMGI1MDM1ZS1kMjk3LTRmZjEtYjAwYi1hZGRjOTZiYTZhOTgiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjMwYjUwMzVlLWQyOTctNGZmMS1iMDBiLWFkZGM5NmJhNmE5OCIsImRlc2NyaXB0aW9uIjoiT25lU3BhbiBESUdJUEFTUyBGWDEgQklPIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCIsImJhRGVzYyI6eyJzZWxmQXR0ZXN0ZWRGUlIiOjAuMDMsInNlbGZBdHRlc3RlZEZBUiI6MUUtMDUsIm1heFRlbXBsYXRlcyI6NSwibWF4UmV0cmllcyI6MywiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJibHVldG9vdGgiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNEakNDQWJTZ0F3SUJBZ0lFZUljYkNUQUtCZ2dxaGtqT1BRUURBakJsTVFzd0NRWURWUVFHRXdKVlV6RVFNQTRHQTFVRUNoTUhUMjVsVTNCaGJqRWlNQ0FHQTFVRUN4TVpRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWdNQjRHQTFVRUF4TVhUMjVsVTNCaGJpQkVTVWRKVUVGVFV5QkdXREVnUTBFd0lCY05Nak13T0RBME1USXpOVEkyV2hnUE1qQTFNekE0TURReE1qTTFNalphTUdVeEN6QUpCZ05WQkFZVEFsVlRNUkF3RGdZRFZRUUtFd2RQYm1WVGNHRnVNU0l3SUFZRFZRUUxFeGxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNU0F3SGdZRFZRUURFeGRQYm1WVGNHRnVJRVJKUjBsUVFWTlRJRVpZTVNCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHRGd2VzdjbU51VGp6N3VrRUI0Y0xDUE53KzJlNU5TeHNoblNLTHVpbHJNZE1LNkpBWlZtSW5zQjVvbDdmT2E2YTFzdzU3Z2gxM050dTBkaFdyb21EbWpVREJPTUIwR0ExVWREZ1FXQkJUbm04TjgvSnZDZU5RY1Y3RXUyVU8xWFU0VEVqQWZCZ05WSFNNRUdEQVdnQlRubThOOC9KdkNlTlFjVjdFdTJVTzFYVTRURWpBTUJnTlZIUk1FQlRBREFRSC9NQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURESUZabmxUSGtvQlVBNEJ1TE4vQUI3N0IzMjkwS2tNYXpld3VaQ3c3c1R3SWdOdDlxV2dxMU5INnI3aFBHUGtwSHJDMmRVM202N0V1L1o5SkwxUVhiZW8wPSIsIlx0TUlJQ29qQ0NBa2lnQXdJQkFnSVVWbjJiV3ZzMEtsMjdqZ3d1MWNMbDhQeERvMzR3Q2dZSUtvWkl6ajBFQXdJd2dhY3hDekFKQmdOVkJBWVRBa0pGTVJBd0RnWURWUVFJREFkQ2NtRmlZVzUwTVJnd0ZnWURWUVFIREE5VGRISnZiV0psWldzdFFtVjJaWEl4RURBT0JnTlZCQW9NQjA5dVpWTndZVzR4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4RERBS0JnTlZCQU1NQTBOWU1URW9NQ1lHQ1NxR1NJYjNEUUVKQVJZWmFtOW9ZVzR1ZG1WeWNtVndkRUJ2Ym1WemNHRnVMbU52YlRBZUZ3MHlNakV5TURJeE1UUTFNamhhRncwek1qRXhNamt4TVRRMU1qaGFNSUduTVFzd0NRWURWUVFHRXdKQ1JURVFNQTRHQTFVRUNBd0hRbkpoWW1GdWRERVlNQllHQTFVRUJ3d1BVM1J5YjIxaVpXVnJMVUpsZG1WeU1SQXdEZ1lEVlFRS0RBZFBibVZUY0dGdU1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1Rd3dDZ1lEVlFRRERBTkRXREV4S0RBbUJna3Foa2lHOXcwQkNRRVdHV3B2YUdGdUxuWmxjbkpsY0hSQWIyNWxjM0JoYmk1amIyMHdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUmZIL0FuQzJIQVYyQjQ0U2Jmb1NNZWdCUTJVeGErU2xZaHA4WUdlRW9sdmFNU1RUU01WRWcycWFsSFBDd2MyMFdmdHNIR1dJRFBhdUI0bnk3N1JmcXlvMUF3VGpBZEJnTlZIUTRFRmdRVXdENDViNlYyYStDeEdGY3NqakVtQm10L1JVc3dId1lEVlIwakJCZ3dGb0FVd0Q0NWI2VjJhK0N4R0Zjc2pqRW1CbXQvUlVzd0RBWURWUjBUQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBejFRSlFQYVBZVnFiVitXL3B4Sm0xWlh5Tks1aG4vcEJLMUpYR0lQWGRYNENJQ2dhbGcyMzl6eEtiMkZoK0g1UTM4L3E3WlRzTmxNNjFTY1kyazNHZGw5MCJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFMUUFBQUR1Q0FNQUFBQ25CdDJSQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUE0UnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURjdU1pMWpNREF3SURjNUxqRmlOalZoTnpsaU5Dd2dNakF5TWk4d05pOHhNeTB5TWpvd01Ub3dNU0FnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlJSGh0Ykc1ek9uTjBVbVZtUFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdmMxUjVjR1V2VW1WemIzVnlZMlZTWldZaklpQjRiV3h1Y3pwNGJYQTlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzhpSUhodGNFMU5Pazl5YVdkcGJtRnNSRzlqZFcxbGJuUkpSRDBpZUcxd0xtUnBaRG95WWpGa1pUUXlOUzFoTm1Wa0xUQXlORFV0WVRZMFppMWlZMlk1T0dWaU5HSTRPRGNpSUhodGNFMU5Pa1J2WTNWdFpXNTBTVVE5SW5odGNDNWthV1E2TURCRlEwUkRORGMzTWpVd01URkZSRUkwTVRGRE1EYzVOek01TmtSR09ERWlJSGh0Y0UxTk9rbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNREJGUTBSRE5EWTNNalV3TVRGRlJFSTBNVEZETURjNU56TTVOa1JHT0RFaUlIaHRjRHBEY21WaGRHOXlWRzl2YkQwaVFXUnZZbVVnVUdodmRHOXphRzl3SURJekxqUWdLRmRwYm1SdmQzTXBJajRnUEhodGNFMU5Pa1JsY21sMlpXUkdjbTl0SUhOMFVtVm1PbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2WWpSbE1XWTFNekl0TXpaaU9DMWpNRFExTFRneE9UTXRNVEJoWkRnNU9XUXdZalZsSWlCemRGSmxaanBrYjJOMWJXVnVkRWxFUFNKaFpHOWlaVHBrYjJOcFpEcHdhRzkwYjNOb2IzQTZNall4WVdKaVkyWXRZemcxTkMwek16UTFMVGd5TUdJdE5tVXdaVFl6TlRJNE1qVmpJaTgrSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGlBOEwzSmtaanBTUkVZK0lEd3ZlRHA0YlhCdFpYUmhQaUE4UDNod1lXTnJaWFFnWlc1a1BTSnlJajgrL0JRUG53QUFBWUJRVEZSRldsdGpMUzB3VzF0ZFRFMVRabVZtSXlRamk0dVNiV3h0VlZWWTZPam9HeHdiTURFeVJFUkxTa3BNTGpBeGtaR1ZiRzEzTkRVNC92Nyt1cnE4eXN2TmVucDc4L1B6K2ZuNVVWSldMQzB1bXBxY2MzSnpZV0ZpcXF1dGlvcU5zYkt6UVVKR2xaV1lPenhDd3NQRk1USTBORFUyZzRLRW9xS2xPVGsrcnE2eUtpd3VoSVNLWkdScmZIeUIwZExVRXhRVE56ZzVNalExMjl2YmRYVjVuWjJnS0NrcC9QejhwYVdvek0zUE9EazZ0YmE0VDA5VFBUNC9LU29zWVdGbHhjYkhDZ3NLYkdwc3ZiN0FSMGRNVjFoYUlDSWlhMnBxSlNZbWFXcHZQajlESmljcXg4akthV2xvUzBwWFoyZG96OURTWGw5bXVMaTZiM0I0T2pzOWw1aWN2OERDUjBkUWo0K1VIaDhkWkdOa2g0aU1YbDVnMXRiWEZoZ1lyNit4Wm1kdloyWm5hV2hwYjI5d1oyaHJIeUFmaDRhSVkyUm1mMytBcDZpcUVSSVFEZzhPTGk4dkZSWVZTRWhVSFI0ZU1qTXpLaXNyRHhBUGFtbHEzK0RnYTJ0ckppY25HQmtZKy92N2o0K1JiR3h3WTJKamw1ZVpMekF3S3k0dWEycHIvLy8vUzVZcE9RQUFBSUIwVWs1VC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy93QTRCVXRuQUFBZldrbEVRVlI0MnV5ZGkxdmFTTnZHRFFTRHhNVGlFVHhHRzlUU3FyQklMYUwxQUh4VVhVL0ZFMlYxZ2NWamxGQUsxdHJnL3V2ZjgweEFyUVlJOXQyVnZhNU9JT1JFK0hGenp6TXp5WkEwL1AwZlRBMi9vSDlCLzRMK0JmMEx1dWIwdHVtM0w1WFNiMDF2Nnc3NlM4UVVLcE5TNmt2YU5WNW4wRjk0SjErb25KeWgrUzkxQmQzcWNZcUZBbFVST2hNNmpkVVY5RnZPeWxkVjJyU3Z0TllUZEpkZ1pmbktRb1BTKy9hMzlRVDl0VmtVcXdoZHlJVFA2d3c2SUlyVjdGR29PNldGNnA3T21QNkwwSFZuRDhGYTNkUDFwblNYRHFXZG9YcFRla21IMHVIOVFuMHB2ZVRXa1JIUDZ3MWFWMFlzMUprOXFoY3VUbE9kZVZxUDBzN1FmdWFYUFg0KzVJbDZhbm4vUVh1WTZqQWovdWZxSHZxVTNxKzdFbEZQTFMvVVdXY2xJcXNqVG9lLzFwbW45U2hkWDlDNjRuUm9QMTluMEdKMWU0VFA2d3g2UmxlY3p0ZFY5T2kwNmlvUkxWMTFCUzNxQ25uN25mODFwUUg2c3E2Z2Y2TjBsWWdUVGZVRXZWM1FBMzA1TVY0bjBPU1k0cVJUajZjdlQ5dnFTV21QMDZWRGFjdHBTeDFCdDNKOGRhVUxJY3U1cmJWK29EdE52SjdtMXI0bDNGVS8wSC9zdS9Wa1JJdGw0a3Y5UUUvcGdVYWxQeC9VRFhTcnpTSzZkTlR5TE9rSmMydTlRRGVsVTFDTVYyOEVYSUkvT3VzRnVtMGlyYXZ1WWJGWTV1ZnFCTG8xdUs5SGFRaDVsdlJackxVK29KdjJMU0ZkU2wrbTkwNC9OOVVIOU9HK0phVXI1RjFhVWhObkxYVUIzUm5lVDZmMVFJTTlVdWVmODUzMUFEMDFBVjRWZFNtZERwMmZ6L2ZWQWZSWFh6cGxDcnZkdXV3UnVqei9QUFAyK2FFN2wwTmVKMi9WbFJFdDRmM0x6Nkd1NTRmdW1nM2xaM2w5R1RGdHN1eFBtT29DZWpuc0xGaDFuQ2dLRWFWUFExL3JST21DRG5zVWlEMzJUK3RCNmM1WlU5aEp1WFY2R3V4Ukw1NTI4anFqUjloeWVScCtmbnUwRG9qTDRlVmxYVXJ2cHdGNlAzM1ErdXpRTVdyV0lzN3FMRnpTOC9ObnA4S3pRNzlkbzViVFZuRzBlaDhWcUpydW0rYlA1ay85encvOVJseE9VME9qb3pxVVRsdENsdmw2Z0c0RjZKQTFNaFQ1QVZxckQ1WnpPWlJPWlN6ekUxd2QyRU4wV2tkZExqZlBTaEtnOFJRdkZlQUx3TGpBRjhnclBuREdtdytiUWtwNi9sOVR1dlh0MTY2SGlTenBwSzFXbDNYVWlqRVBFM0xlamNtem9LNG9GR2E5eTdQZVROclcrZlh4em5CL2Ixdi9aOUJkVFgrMFRiNyswR0JidFdGYUxiN2EvTFppNHR3aUlMTkZacUl5cjZwYzVDMnVvQXJPd3F6RjVUY2FMemlPQyt3WU9iL05hTFFaL2NYQi9NYXplN0x5cGF2MVo2RTd4eWNCMTdqVExDd05sVTFXdDNpSFZpaXg4L2VsVjFmWmx5Mm4xdEZSMTZpYWhrcmpTSEVCcmxreWZwcHJhbjA2ZEd0VDM0dUdob3Nkb1JsMmJLMlFzRm5MM25vWEgzZFQ2Z3dNbE4wYnN1elBpcUtWREtWa0pZL2lBcHlCYjlYODZiZTNUNE51L2EzeFRZT05heGFHRUJqMnlJb1U3cGlDZ2VYeGxVenlaRG5rdnpKUjQyNlJFend0VXBSWUhIaWNMQ2ErK0hRNktTZUJILzFydlBVSjBFMWJmemFzY3VBS29yRW8zdnNJL0VENENGYjlaSjR2Zld5NTVLVHUzb2x6Nm5BN2NxcWJPS25aWW5MQzdxM1dqMDIxUXI5dEczdlRjTkc4dElTK0VLMTN3RCtBbEViM0dWUU01eDFSYVg3V09Vdk5VakFpa3ppTmMwNTR3QWhlcUdYbjh1d3lKQmdCdDJoZG12cGFFM1RUNElzTllCNHFlaGwxNXN2clJ3Qkx5Q1hRdTI5U1JJWk5WR1l5cVpJNlN5OWtraUF2WS8wTHNPRm5zUWFiYW9EK3cvTm5nMjFISU15akpOOVlyUTd0UE9oUUI0ZEk1dHpGWlNSemlnNjMydzBCSE44TzAxWVJwOXdrdDduSjhDQ3hMRXM1bDVkRDRmQnlDTWpoeHhDRmRiM1Fidy9HWGpRWUEyaG5aSWJ5RGtvOFNENFlIaVVvV1dEc2NMZ2NMbnlRSjh4aWlXUEZoVlo0T2h4a0pTeDAvSkJrZk1nT3Q4UGhsdFVwMlMyejl1V1FDYWxOZVRESmFKcys2SzdKMThCTUFqTkdUcDlLWENKL0FFeVlIZmNYQXFjcU4yRzk5eVEveUEvTTdqdFc4Z3JJV0U2SnlyTEpaQXFGVFdIdkxEczZyUU82dGF1NzhjV0dmNmNaZFI3MStSNXBhaVc2a25teXFFU0NtaEpKcllUdkFTRDR4NEZXVVNFaHdVaVdnUkZBWlJFbjRZVThjTnFoTEtkTUlSaVduWlNXMW8rVTNuN3RJZEZaZ0tJS1ZBWnFIK2pwaW1DYXVmZDhuSHhrTklxdlBqTHJVeC9xNjhQMDRGZERBNEg0Rkt0K0E0Y2QvMlZpTW9WbktkOTRWZWpPUnM4R21BTUN4eER1R0tpdHJzaU1FT0Q4ZnF4dHFLUFM1TzFjTWRrZXZENU14dHNwcmppVWxzTTBCODhBTitOV2lPeXlZa29qZG5qV3VkUlVCZnJyN3RpZlptT2dlYWg1eUtlNjJCZFpDcGdOdmRkcjhiVjRmRzBOSDcvRGFPMW9qVjQ3aXE4ZDBXdDAvQzdSTk16QndqaTlodE8wdWgzTUh1Rm9qUXl3Qlk0ZnA5NWVROURzNTF4RjdIQWEvOVpqbXFYVzNsYUdubjc5c2NGMnNRTkt1MGlzOFBrRWZ5ekw1SklNa3lORDhZSFBoWVVjczhEQUtMZkE1SEF5dDVCVGwrUmdDcWRoYmdHWGs0M0lDTmJnRnJnSmJzZmdTRjJDcTJHM2RBeTRIWWd0c2lwMTJNa2VWSVJ1NmhoN1kxdTlhTjVwUnBuaEVlR3VHZnlveCtubW4wa01jOU1iREFwSTdXWk5sbFFLY2lNVmFhb0EzZG9JMFE2RXZ0aFI4NGxWQ0NiL1ZXU1ZPMnN3K0NWV1pHVTJaRW1GVXBBWmgxdkxRN2UvSG50ak51NWNyRWJVSEMxRWsvODZNcVFQVEcvUXhySVEvNlIwR2l4aWNycC9Ld3Y5ZFF5RVhqVmVyQTZwek54YThobVFpZGpSb0UwQ3FXV3ZCYWhOeTdNZHJlV2c1MUJvLzhYcXpxanFqZCtmaXhtcFk1eGRCdXFVSloxS21ieXVwbkxRQjFpdXJLNnVMbUhSWi9YMUpwOExHYWw3RFlMRXNuSUdwUTU1blpObG9McytOYjRJMm95ck95VFl5Y0hrOHlFamRjd2dRNzJQU0EydXRuM1ZodjZ0NHpXMHJ5NVdsOUFjc3BCam5oSDU1bVpoelVBTWtybTBvS3ZGY1czb2c5Y2ZOOHlycXhmRTBZNVk4am1SaWRReEtHUllKVzNaUzRmeTlrRk42TmJkeGhkbzZXWmtkZ3VNRm5JV3l1WW9IVTlVL2NRRWJrZnIyUTQyaThhem11c01uQVJoRDAvMHBreXpobFl0Nk02eHhqOUpOc1NLSi91am8wdWZrT3lmZk5VMzB0OVRCU2VlT0I0OE9lajczcEdncXlBbiswZjZEaWI3azFvN1pHSkJCZUtINmc5dnBGTUwrc3NZc2ZTRldoakdtVWZNY1daa3BiM3Q0R0J6cGYya3B3Sk5OajY4K083bHdNSEF5L1cydzBwZmorNlphbCtaN252VjFyNHl5Y1FmcmM1ZEd5S1FFd3NXQ0NDaHZPTTNMZWh0Z0M2NVE3em5qdHVQNkppYmEra0JmOFNUVnkvYmg4dFNKN0luNHljZE43RGRUVWZmK0ZTMkxEVjkyTDdkbndRanhYc0c1K1k2YUExL0NCSmt4ZlFsRk9aNWFWc0wrdVQxMkliWmVORU1RZHJIK3BtSDJZOCtYdTlqb29rYmdNaEdiMGJHRDh0UVo3TUg3Y1BST0hnVjNFb1B0dzhrc21XWSs4ZEhidWpmQ1YwMDJmZnUrSkhXQzFnRlllVVFtRG9VcHFhMG9BY2J4elpzeGd0U2hDc2xTOS9adEtmOUJIL3FSTWN4MEdhamsrc2RjVzJXa1hjZDBYaXVmK3BrcEQ4WnB6dmVqV2gvdTNqSCttVDA5dnZFNmI2VlpPS1JxVzFvYWhPYU9wenAxNEJ1YmR6OUNOQTdKQi95TWVaQmxLUDd0bThTNk5mRGRrSWRIOWpVbERBK3ZONGZwVHZhcHI5ZkRSNHNEdFAwNGJqbXQvdS8rUFJBWEkwZFVUWFFiUGZSajByRm9BaEtoMGxPbkIzV2dtN1ovUWkxcFIyaXROakwvQmlZRTU3MVQ3RFBIQk1kWG4rSlAyUjhiSDFZQzRaK05VM0hPK1phT2tZT1Jqb081NDdqOU1DQmx0VHh3L1VPdW1ldyszdDNOejZ2dmtVUDMza2U3SkM1RG1LaG1MKzBXQ0I4OUxScVFBODJRcU5sUjRWbXI1a2YzeC90Zm5tVGhaOTBzK2Q0NEh1N0J6U1BUNTlvd0NSNjJnK2p6T0xWNGR4VXk5VEtWWDhiRSsxdjc5SElpL1RKZER4KzNINXlNalV5ZFRKMU1OY1R2OW5lb2g4cTNlQUdmK1RWbUhla0JkMENaY3NxMXp5RVJ6UGszZ2ZROGVrcDNHTmljckdsYlhNRStHL283dTFzVmtQQWxaN29ZVnZIOW5ETHllSGh5dkZtZnhTK3h1T2ZKSHZ6OGpzZFA5Nk1YMStQZGZUMk1vc1EwcWVtNDFyMkVJblNJZTlhT1dqYkJVQUR0ZmdBT251eitEMktyM1IzKy9na25TV1ovM0hPZ2FXRGkxbDZjbXF5Ky92QTRjQ25rNm51a1dqdTVhQkdORXZPOWRPSjQ4MmJaUGY2WVBiUXN6SVFqM1l2UGxBQmFucEZlNkRTZERsby93WGE0N0hTV1dhN2hYeHlQTm5lN3FGTG1tcEFmMTlNUktjbXZ4OXVIclljOTdXTURJNUVpOS8zb1kxV2h1UHg0YzJlN3F1K3RyNytaUHQwZ3I1Q0J6NVFHdXlCU3UrQjByUzJwd24wS0NyOUNEclJOa25zMGJNNXZiNUlNZ3pkUDhjOHRnZDhNaE9kR2trbTJ3NDNQZFA5SFl1SE5ETjM5VmpwYkJLV0pvN2J2dDNFSmdkNmVwTnprL0hvWkZ2aXNUM2tXMCt2VmZJMEhveDdsQkhwdmdFYW1SZEhqZ2NtNTFCaXpFa2FRZUc0M1hOOU5kQTlPTkxkUFRJOHNObWRpSGU4TzE3VDJIQnpKQm8vWHV6bzZUbnVnZWNpbEl6VGZab1prU1ZLVjdDSGJRY3pJa1NQaHhtUkpqRWc0Um1NRGtQdEF5VE81bDUyYTBTUExEUFhIZTBaSHQ0ODNoN3VPN2tDSjBXL3Y5VDRSVWc0Z3RDNHVMallCcy90eFNTVVh2MjBWc2lUcTNsYVZkcmhFQjhxVFdDd1RJa1AvOUdYQUtHakxlODhXclVLZW5LT1NjVGpVQnh1OS9lUGVCS1E0eWFqTjVxeDhTcWFTM3BBWm53bWI2S1RqK3dHOWlobXhDcEs3NHppb2NDSDBRUE5PazZxTlBIaFBxd0N4VDN0azVyRmN5SzVNaFhOSm5vR1BCM1RtNTU0TmpxbEZXVEl0MnYvR0UvY0pycGovSkgxUVdtM0d2SXFlZHJzMzJrZXhjUGZqendOV2ZGZ3BRTzFUakpvNko2WG16ZmFGU0Y2ZUx3N21ramttSGoyMkFOeGJMeE1mVEI3MDdhZExLM0tSajN0ZlkrcUJlQnA4VTdwS2hrUldvaVBsTDVKTEF5OHUxcUxyaVdneGdDVnlyWmt1U29uL0NaOVBWRWExTHVPOXZTTlg1V3J3eWFTYlhQRDhTaktITTMycngvOFgrSnhpN3lrOUY2bEVoRXpvclk5NEVNU2srdHQzeUd2SDE5dHJrOHg4ZkoxKytHWDdTZkRuaDdQOE1tNzdlUHlyWVU0TTdYZTFvTHhZM0I3dlR1UjBEaU1FSlFWdlNIUDVkQlFHb3REejhoY2UvdEsrOXpKY2NYMlZuemhhcnA5WlFWYUpWY1Z2aHUydG81UDVtQi9LM05USGJTRzJUQjZ5RHBLUkZUYThiZ1lMNlkxT3VjWkh1NWdxclZZczlBWU9SNGU2MW1qczVVM2pOTk14L0N3aDZIajJnZHNRR2xGTE5ieUtzWHBVVHlQVUFZYTgyTThIcy9xT0FBQTJ5VVNPcmJESFpacjI2RFNpbHd0ZWpTUTZBSEZPRnNPK3Q4OThvRnhXbUdyVlUwUkdrOU8vUlQwQWxOS1NYZ3UvQ3kwWENua0RSYnRnV2NweFNkREEyYmkyaEMwR1RtT00vck5obXNJN014UFExY3V4aThBMm1wMThFK0RCdUtvd2M4SlE1RlI0aktyZFRTeXhBWHBKK3F0aHJ4UzRSS3ZGRDN3dzU2a05HaHM4QWVFR2ZVc3FIcEdGTHptdG80R0REZFB3YjZEeG9ZdFhkRWVUOHlJZ0d3VWxnQlRWakttVU5xQ2gyanpHVloyWUtlVHBlQk44aWVWTGwrNFlJWEorcFNNeUN6RS9NMUxEcmZiYnJvOFBadUg0ZXpzOCtmUHB4T1hvWXpiNFJiRkpVUE4zb2E2UjdGRUJPamwzeXZhQXl0TXRVSXp0SmxiY3NoczNqSUJxSi9QRVBuMDlIVGk5UFR6MmVkemt3TFliaTVSNjA0eFRwZHFlYk9WUWw0RXZWZ3JOQlB6QjN3eUc3NmNnSFI2aXN6ekJIdmlGTC9CL0VTSWRiajVTSXlwWFdrU1BTeVY3RkVNZVRWQzU1aWdUWEM3TTVhSmlmUHpDWkQ2OUJ3ZHZaZTJYRTRRMGVFYlRPUmxOMnMxTTdrYVBYMVg5emdxMjdBbGhVdU4wTG1ib0cxR0ZrMlg1K2ZJZko3SzIwRWZCVDlQc1h2VDUwVDBzN00wNjJCNVd5M1VxajBxRmk0dHU1Z1IwUjYxZVpySkJXMFJtUTlaTEplQXZlZGxFYmFVV0ZtVTh2dG44K2p6Yzd0RHBQdzF4TDRmbGRhTTA0TzdMOHkyUU8zMnlBWE5FYmRrMmdQb2M4dnNQZUJiY01WN2lRWS9PL1VDdFptcExlVGRGdVAwLzFCcEpnYk1kcE1wQmRSNVJJWXF6bVBzOENrRXdMUFBlWWZNQjVNMUZlT1Y0elI0Mm16Y0VXcUVabUpCUWJTblFpYlRYc3JPRW1BTmFvWE5YQ0kxYU0xYTllKzdldUVDOW1qd3EvYlFYeUxtYUlOUmxDd1drOGtVVmpTc2NVY3RJZlhuQ2J1Ykdzb3UxR0tQNHFIZTJVclF0Y1ZweGhCMHNKY1RJRVZlUytCN1NWWXNaMURjbklzaXhTVnJoVTVYVkJyc2dYMEM5VUl6c1kwWmgyVWVDbXRUUldKQ3pWcXdrRXk3V1ZGbklVT2crYXJRSkhwWTlkc2pFYk9KczFqUnNDaFZvZEVoV0VSNjNaTEE2STNUTEs5VTlQUldNWHFJVm9lb0U1b3g5UHJrMC9uNStjOFpXYW1lMk13RVFGK3lJbTlJNmxSYTVKV0tyWEdFTnFyTkxiMUtnOUFzL25WbFBxV0hHUndTQW4rY2h0MlVQcWxCYVZHcW5CRzdpL1lBcGEyS0xtZ205aWJDZmdhaEp4UzlDUXh5dWcvRnBMNzlRekhPczVVOHZSN1k4Smd4NUVGMVd0YXBkSzlCREFQemZKalZ5U3ptMGRWNTJlNW45TnFqbEJFMXE2WnZRdUtmeEI3WXlWWVg5QUs5eG9uN05RbU5VaytjV21URmwyVjBRbGRVdXNmdGFvQTRMZWlIWm1KLytpUVVPaVRyWnBaTkFBMGxER3ZRQjgycVNwZXJleHgvWUQ2QTBnVGFvY3ZUdWZjYllnaVl6eVJXdjlMMmM2QTJ5WlFlZjJCR1ZDb2VyRG5tdUlhRzFVQ3p6NkZYNlhqQ3pGNEM5TGxZZ3oyVVBXamFwTjI4b0ZOcHFXS2M3bUZsamlndDY0VE8wZDhDL09mYTNLSDZZMktmWlYzeG5BNW9nM2hYWWRKU3VrT1V1UTJqcXJTdXVzZEM3N2VJSFMzdHJjRWRDdXVGVnVTNXhNclhqTDZRUjFYS2lCNW9MaU0wVVZxUHA1bnJEOVpsWXVsYTNLSFk5eWZPSjJaMTVjUzc2RkV1STNhd2JpUCs1UUtWbHZVcC9WNDBBZlNwVWx2QzVtOWVsTXlNTG50SXhaQ1h5bWdwUFVZNUxqWldWYVYxUlk5Y0xNWmk4Tml2alptMWdOSmh0MkpMNmd0NXBXSmNVK2t4WGpadVFKd0dwV1ZSbHozZUc5Z1VRck8xVWFlZ3pXNnlVamFteHFxcHBqMFUyUWkxUElqVFZxdXVXbDZ1MThEdVljU3JEWm9OWFZvdXc3S2VCaTVXVGFWaUp4WHRyaFBIa3B2RFJzQ29XM1JiS1QyZWpnV2ZwSFRJWXJHRVJkNnZ5eDd5WFltb0JkMkI5bGh0aGxxZXc2M1BIakVES1JEUGE4eUkrVkFvbldGNW5Vcnp0OTJCTkRPaUJQWkFwVVczVzEvSTY0MDVzSTUzV2x2SVU4QjhGTVd5UWFhMldsNFpwUjNjaHVwcFVTZjBlMnNHR2dCbjlwcjhJZVBmQlVWRmp0VWFwelU5VGFIU0FWVGFJZXM1ZlpHN1BwcWh6bXFwVFdPU0hNS1NNQ1R5cmlPZEpXS3h3cVNkRVNIa29kTE5QcXZiclErYTdtMW16d0Y2cjVhNmgyVEZFektzTXFQajRBY3FMYkdWR2dHZXkvVFNocis1MlNmTE9tdDUyVjRiYTRFVzRnUmZrNlh4bjRxc3d1bXJtc29LVmNrZXlkT0pBUEcwN05ZWFBVajRDT054M0ZwcVRDd2s3TlpvMDFVMU5iQjh4WU0xSGZQblFTZ1JtMTM0MTBaOTBMM3ZJL3huYkl2WEFFM1pJVUhOOUZwbkk2QnljK3N3SFNIL25SeDF5L3BDM3MxTm9wZERmNXhONkcrNlNGNUlUcFlWOUJ6T0k0Vkx4YXBwVjQvbll3TjQyaVU2SEtMZVF3Z0dOb09IdWt5Nm9UUDVmRDRzc1E2Ym5xTTFkMHBENGJKYzlreUFFUnUyYmxubklZVGNkVXhnTGFmbjU1ZDZwVWFoOGR4aWhNN2Q2UFEwWHdwNTVVOHpCOVFTa2RKNUxNOFE1SjNuKzVlWEpwMUNGekpBRFVKenVnK0xWVGxxU2s3SkJRUVgvaEZXMFhrc3J6Y21VS0Z6aStYU3EwL29UQ2JqdFlQUVVVWXZ0S3EwcFdLdjNnQ0dQTm10OTRUK2dzSEFVaGJZcVVWZldWNndad29LNi9EclBtcGE1YkNZcW5ReEk3STZqeUNEcXdPOEY2Z3YwMVdwd1JXeUl0a3AzakVUMTNkZURqMWR1WEFCNkk5bWNvUkpsTVVhemdURWZDeGVrZEtTcWtJdHlUTVJhSHhLb2h3eDZOMTViMG5wdlZTcWZFYUVPTzBqbDhQUWZUSW5Dd2FCeHNnZS9JS1pTdFNTS3lETStGd3l5L3I4dWs4VXFRZlZ3MVhzWVNUUnc2cGY2WnRjTkdhVytKQWxuZDVMbGMrTmtoSUpCRGhCY0FHemtOQjcwaGFWbGdnMEtsME9PbWhzYnJiV3BqUkdFRTZpUW1sTUp1MTRMVUY5Rks5UzB6empwbHpDVVEyN0RzTCtxSENGYytOWGFzZ2J4U3REMU5JZGlJa2RjWklTMmt1bFU2bFVYbUw1eDhnekhFbUNMTG1FV0cxbmJDV3FvajNJQ2YxbXdRVkN5MUl0Si9RWnczcy9SRlA0Q1ZPaGtNbHIvd0VZWXNaTXdNOXhSczRvc0x4UE1OVFF3UWFWcGhRK1hLVzNHSGphaFpkVlVHcnFPc0hFZXMyc2tpSDN5VFNad2w2N1hTcWR6bmRFbGdLY2VzV0FDTVhPY0xGYU9nVWhOT3lxa3RKYmF1RUMwREpiR3pUNmVpTWk4ZmxReW1ReTViM2VESHdVdENWY3Zwa1pJU0FFa0ZsdzJNSFkxOG1iR3FFTFBGOEp1bHUxeHlnTEZTYWwxajR3dEdHTmcxYUdGNFRPNXpNQXpZcHVseThTRVdZRURqS2g0TEx6a1daYm90YWVOVUZXOWJTbGdqMkNSR2tvWEtoYSt6RGxibUx2andTSzRqUGV2RGREbEhZNGZCR2l0RERqS0VpUlpzNVFhemMzNG1tKzVHbTZuRDJ3R0Vkb3BmWXViaUQybTk2QWFKY2tlOFp1cDJTV0tCMlo4VGw0T3p2RWNlWkU3YnRFcFNVMWVwVDVSOUYzN0Y0ZldIS0JQVmpwQ2YzeWNsQVIrZXN2N0VnQkdaRlY4Rm9Ha0RtZ2JlVUxjUDVnOUFtZE40blN0eG54cUd4R3hNTmlJRFgxcEc2YkMweTBOL3JpbTRFVGZHNFdEMmpKcmtpQXM1bk5odmlUK3B1cTUxejRxbkU2c0lRWjhTbjJLUFliUzF6SGpxN2ZIQjBkeFdJR1NBQWNvMitZcC8xL200UzgyNHlvMllkcDZ4TXFMVmpSMDlMVHV5S0Rwb25vZGF5MzkvMTFiK3lhVGl3OHZUUHlYZUZTOW9UK29GckxHd1VyL2d5MEtyaDZyWldmNmoxZENubEtwUktSS0wwejVCUFJIckU2NmFrT0diRkszZU5iQTZubHllS1RQZjBQUVBONmxJYU02R2FwdW9FdVNHcDlPcVFkOHI0WGxXWkZrZVhyQmxyMWRMcHl2endJZVFCZFAwcmZWVTNwTWlVaVJnK2lkRDE1bWc5WDZkV0xjYnJHNXRZL2JRK1NFUzBWNHJUWkJpMFhQSHdzOWRaZnlDdHJqMVVDTGRZUmRKVTI0dmRQUlUremNqMHBUVnJqbGtwL3dUWTJROVZVcmlkN1ZHa2pEcExDQlpVR2U5Uk5NUzVWcmsvZlprUzVqdXloU0JKVnNUVk9sQVo3c0hWbGowSzFxbW5RU0pTdUkzdEFjMDB5VmMySVdQZW9HNlZqUWQ1dXI2ajBWYU1INGpUVVBlcElhUnRQZ2FjdHBPNHhwblg1bDM2ODBBNkpIcXljTWRRSHROOHVVYnpKc2xmdVFqdC9YMzE2L1diMUFwdGJvdWkwSmVzQk9zaGxpS2VoT3AxWHZtdEJUNDAxL3RsdzBUd0s3aEF6Z1hwUU9oY1VuQVZLSWRmNXk4Z25XdERUbnQwWE5tUHpFQjVrb1NJM0M4L092SkN3aldha0FwVkNTMmRjYzFyUXYvMjFoY2Q2aDBCcGxxK0h1aWxZbW9YZ2tkbXpwRkltZStTTDVsWGNGZ1l4SnpaYjhTcnBYbjhkUUpzRk95VkpYc3ZlbmlrdkdiczByNWQzdlB2NlQ3TVJjaUl2OG5ack52ZmNqcVk1bHhPaWh3bVlUUmxIaCtiMTh2NCs2Um44MkFDdFJMeE9QVHRyVGo2NzBBRVFtckx2UWV3SVM1RTI3Y3NwTnZWdXZjWklQY3BEcUxhTGE4OXJFSVlPV0VGbkpiKzNGd3A1SFZ5VE5uU3I1MVBqaHdhdWVRaXJUT3lzOEx6UUMvNGhPMVdRN0ttOVZBcUU5cnd0ZDEzVGIxdWVCdHZPMGlqMk5PSm5uN1dBWVlJQ1ZwWW83eDVlaTFVVzJzcGRqTFh6YU92MUI2anBxVklYcU9EemFjMFlsa1E3WlVlaFE2R3czV2ZyTEh1QjRhbXhyWTROTTVTS1JXckRNMm1kQTJhSHZTQVZGTk5lQ0tvZERxR3YvRldSbTJJdHU5OGEvTTFMYmtJdFVXYm1PY1JtR1BPUUl5TlJsSlFIYjVneThreXNxY0pGcy92KzZuNzlCdk9pVERyUVNVN2hLUGx2WXk4dzBjQ29ESGFXcEV3cUJJWldJdjZEU2xmNjdvcSszdkpnMkl1SVJHdmU3dmJIR1NiM0w0cWNqTnFHck9CbWl1S2RlTm82YjNkeEg1c3FYbE45M0RDNTlkR0FFVVJVVkd5bk5XQklGSytLa2lSRDhSb3B5ZUtpKzh1S1U4WHJxQ1JMNzBqZVgzSC9mYVVWeFUyU3VYaU1tN0ZDdzVDaUNyeWRuUDhGUTc4WnFITEovY214NlpZWERUWk9pS2krQm8vWUtaZGd0Sm1Ed2FDWkRFRjF5bHlhdlYxS3BrdXJnN2pGM1h2VVRlNXZVZHlIdVRneUIyMW0rRlNyU0VsNExoSzhZU0xuMlIwendjR3VLdEJmUGYzVExSK2d0cmQwUzQwMzBxQjRjcmNabHR5RWh0eVFoaFdMaTNoUjVIRVNPM2JCcTdxY0YrRWQ4RDZjSUhlY0lUZC9nZG9qTEdQVlc4SGdUbG15akNMM0E2TElFM0NwQWdTN2d0Y1VDdWVCV2JCOStsTDFqZ3lkc2NZQm9QWUhoSWdhK1ZnRlR3bnl2S0wralpaWCs2RlFzSkNIR1ZoRktkZzlDcENMR3lqSUltRzNDVWtodDZ2aEpSN21ZVXdwWkJuT1Vnb01tTm13MUpPd0IycWhBQnFETHpBTDhzNXdDR1RPS0M3QlBQekgyK28zN0dnSzdyNXErUkMwN1FTR1JvdlpFWktDblU5NGxSb2xCY0h3YTFDSWpHc0pLNEtUZFR4QlJqUm80NUVKMEJPK0FlSVRjaDZaZVZJaEFrWW8rZ3Aybk1GdllRZHVMM1pteU9ESlh2TncxOSt0T202Tmd0Uzczd3htTGpBelpCV0pvb3JLWEVRaVB6R0xjeFJiRkoxU2Z3QjFVd0lKaVNoZFJNVlpnbi8zQXhSVVlCU2FET0JqQ2hvcWt0TWJEaU95NHBqaGdzT2RPbTlDMDNSMDlXcHk3TDNaendsTG95NHIvdkdlVjMvMW9qOVUwVkZnOUNTeGlmcUMyaGZ0UUJCQlRyeUhrWUkyVUplUVZYaGZMdFVaZ0tyeW9qbFFjbWZHbTg5N3ZYYTdJa2NFWTdDL1UvZWRjenFQeC9wT1BvRkZqSUl3RkhGaEEweVZoSXhnc09Na3ZrcnFFNWRBN3NGQksyVWVMU2hrN0JsWW1sSGZBek5PcDkwSmk3ell3d1dJV1lkUDRNeTlVMTAxM0tPb3RlL04xcXN0ejN1empRc0lNeEdmUTVheG54b2FVY0djcEU2UjZlSnkwbDhKZjNsSk00RlJpMU9VYWx6VkUvZ0Q0Qm83VHBGQ1VDS2RpRnlSSmM1MjlIR2x0YlpiV0gzNU5uWnk4cW5ualFHeGhabVppSHBMbjN2WFdISTh1cytNNC83MWwrN1B1Qnc2a2t1VzFkZElSQkE0VzI5eXNLbm0rMjY5YmV0cGZEVTFPUFloWnZOekFRSU9hWWs4WnU2bWwwb3ZQNmFscGVJVzk1ZmR2cGIyRWlIelErcEU2U2tFT0Z2dzZLL0Q5cmRQdVMxYlY5dlk4S3ZOazA4Zi8zcHZNUHU1bWxJZ3dBVmdySTdJQXU1MmxneWxrZnFLaVNNZHREaS9PWGFVOUF3dmRqMzFCbmhkNzFyR0pnZGVUVzAxamlXUFlySFlSbTlzSTBaU0F3eVlERGdxTHROSURiaUZnZlQ4dUo5Z1VZUGhVWXIxdmo5YSsydWhwK080WmFYelorN2ExOXE1UHJuVnZUVXlNclhWc3J2YjJIalZDR20zcFFWbVdtRFlIUno4UGpnNDJOL1kvd2xTLys3V0lFa3QrR3pwMzkyOWdyZDhhdXlIOTdXMHdCSTE0V0pZZ2V0MnIyQU0rNFhYeHF1cmxxdXhzYkZQazNOTjFXNDVYZjMraUsxdk81disyRjVjV1Y5LzkrNWRPNlozTUxtK1RrWnQwMjJiYlpzRHJ3NGdEYnphdkplbXQxZmFZUHh5WldWdVpXV2xIZDZLYjhmeHlzREE5QUNrZytMakFNZlRBOU1IQnk4MzU1cDAzQjd4ZjNGbjl3cmY5eC9hN3o4Sy9mY3Y2Ri9RdjZCL1FkZFYrbjhCQmdDN0NtWWRoNnBZeUFBQUFBQkpSVTVFcmtKZ2dnPT0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsidXZtIiwiY3JlZEJsb2IiLCJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6IjMwYjUwMzVlZDI5NzRmZjFiMDBiYWRkYzk2YmE2YTk4Iiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwicGluVXZBdXRoVG9rZW4iOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImJpb0Vucm9sbCI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsInV2QmlvRW5yb2xsIjp0cnVlLCJhdXRobnJDZmciOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwiYWx3YXlzVXYiOnRydWV9LCJtYXhNc2dTaXplIjo4MDkyLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjgsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MzIyLCJ0cmFuc3BvcnRzIjpbInVzYiIsImJsZSIsIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XSwibWF4U2VyaWFsaXplZExhcmdlQmxvYkFycmF5Ijo0MDU2LCJtaW5QSU5MZW5ndGgiOjQsIm1heENyZWRCbG9iTGVuZ3RoIjo2NCwibWF4UlBJRHNGb3JTZXRNaW5QSU5MZW5ndGgiOjQsInByZWZlcnJlZFBsYXRmb3JtVXZBdHRlbXB0cyI6MywidXZNb2RhbGl0eSI6MiwicmVtYWluaW5nRGlzY292ZXJhYmxlQ3JlZGVudGlhbHMiOjE2NX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTE2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJPbmVTcGFuIERJR0lQQVNTIEZYMSBCSU8iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMTExNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTE2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMi0xOSJ9LHsiYWFndWlkIjoiYjI2NzIzOWItOTU0Zi00MDQxLWEwMWItZWU0ZjMzYzE0NWI2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJiMjY3MjM5Yi05NTRmLTQwNDEtYTAxYi1lZTRmMzNjMTQ1YjYiLCJkZXNjcmlwdGlvbiI6ImF1dGhlbnRvbjEgLSBDVEFQMi4xIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjYsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfSx7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURYekNDQWtlZ0F3SUJBZ0lMQkFBQUFBQUJJVmhUQ0tJd0RRWUpLb1pJaHZjTkFRRUxCUUF3VERFZ01CNEdBMVVFQ3hNWFIyeHZZbUZzVTJsbmJpQlNiMjkwSUVOQklDMGdVak14RXpBUkJnTlZCQW9UQ2tkc2IySmhiRk5wWjI0eEV6QVJCZ05WQkFNVENrZHNiMkpoYkZOcFoyNHdIaGNOTURrd016RTRNVEF3TURBd1doY05Namt3TXpFNE1UQXdNREF3V2pCTU1TQXdIZ1lEVlFRTEV4ZEhiRzlpWVd4VGFXZHVJRkp2YjNRZ1EwRWdMU0JTTXpFVE1CRUdBMVVFQ2hNS1IyeHZZbUZzVTJsbmJqRVRNQkVHQTFVRUF4TUtSMnh2WW1Gc1UybG5iakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNd2xkcEI1Qm5naUZ2WEFnN2FFeWlpZS9RVjJFY1d0aUhMOFJnSkR4N0tLblFSZkpNc3VTK0ZnZ2tiaFVxc01nVWR3Yk4xazBldjFMS01QZ2owTUs2NlgxN1lVaGhCNXV6c1RnSGVNQ09GSjBtcGlMeDllK3BabzM0a25sVGlmQnRjK3ljc21XUTF6M3JESTZTWU9neFhHNzF1TDBnUmd5a21tS1BacE8vYkx5Q2lSNVoyS1lWYzNySFFVM0hUZ091NXlMeTZjKzlDN3YvVTlBT0VHTStpQ0s2NVRwam9XYzR6ZFFRNGdPc0MwcDZIcHNrK1FMakpnNlZmTHVRU1NhR2psT0NaZ2RiS2ZkLytSRk8rdUlFbjhyVUFWU05FQ01XRVpYcmlYNzYxM3QyU2Flcjlmd1JQdm0yTDdEV3pnVkdrV3FRUGFidW1EazNGMnhtbUZnaGNDQXdFQUFhTkNNRUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGSS93UzMrb0xrVWtyazFRK21PYWk5N2kzUnU4TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCTFFOdkFVS3IreUF6djk1WlVSVW03bGdBSlFheXpFNGFHS0Fjenltdm1kTG02QUMydXBBclQ5Zkh4RDRxL2MyZEtnOGRFZTNqZ3IyNXNid01wampNNVJjT081TGxYYktyOEVwYnNVOFl0NUNSc3VaUmorOXhUYUdkV1BvTzR6elVodzhsby9zN2F3bE9xekpDSzZmQmRSb3lWM1hwWUtCb3ZIZDdOQURkQmorMUViZGRUS0pkKzgyY0VIaFhYaXBhMDA5NU1KNlJNRzNOemR2UVhtY0lmZWc3akxRaXRDaHdzL3p5clZRNFBrWDQyNjhOWFNiN2hMaTE4WUl2RFFWRVRJNTNPOXpKcmxBR29tZWNzTXg4Nk95WFNoa0RPT3l5R2VNbGhMeFM2N3R0VmI5K0U3Z1VKVGIwbzJITE8wMkpRWlI3cmtwZURNZG16dGNwSFdEOWYiLCJNSUlGaERDQ0JHeWdBd0lCQWdJTWJVSTkrenlFUVVURCtkbkNNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1Gc3hDekFKQmdOVkJBWVRBa0pGTVJrd0Z3WURWUVFLRXhCSGJHOWlZV3hUYVdkdUlHNTJMWE5oTVRFd0x3WURWUVFERXloSGJHOWlZV3hUYVdkdUlFZERReUJTTXlCUVpYSnpiMjVoYkZOcFoyNGdNaUJEUVNBeU1ESXdNQjRYRFRJek1ERXlOREUxTURFd00xb1hEVEkyTURFeU5ERTFNREV3TTFvd2diWXhDekFKQmdOVkJBWVRBa1JGTVE4d0RRWURWUVFJRXdaQ1lYbGxjbTR4RVRBUEJnTlZCQWNUQ0VGelkyaG9aV2x0TVNvd0tBWURWUVFLRXlGQlNWaGxZM1YwYVhabExtTnZiU0FvUVhobGJDQldiMjVrWlhKb1lXZGxiaWt4RWpBUUJnTlZCQXNUQ1dGMWRHaGxiblJ2YmpFVE1CRUdBMVVFQXhNS1FVbFlaV04xZEdsMlpURXVNQ3dHQ1NxR1NJYjNEUUVKQVJZZlFWaEZUQzVXVDA1RVJWSklRVWRGVGtCQlNWaEZRMVZVU1ZaRkxrTlBUVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLZi80R3pHQVVtSkg0UjltQ3ZjSitDZ1RVZ1AxRE5yOGROMmtEdlNBOXh1SU1iMU5aSlhRZ3hTT09BWXFJQnpGTmNqa05WbDgwWTNkcm00dFBKU2wza2ZXV00yNnhZTEZzdmwxQmNxdHJQcnNzeXhJQnRYNWtUZTJwK005UmxjWlFjRWo1Q2JZcEFTcHVTVEJ5em9PdWYrVlNmT1VWcUR6Q0RINENxc0VDeXZ5TEtySnc5a2pONEI2bEZYeXptcklXcVJtR1dLeDRjc28vd3hZSVVOY09WK3A2STg0WTJ6MW5GSVdFaGNBNmRnckpRbkRwRDVJR0VKZFN4VG44dDJabkFOcDRKRUFwOGo1dzN0YlU4OVJLaTN5UEF1d3N4aTNYY2xvRkF0R3h3MndrN25KeWl6cTk4dE81bHdmZ0hOL1luZ2xZd1U0VUZuT0J6UDVNdXpQckVDQXdFQUFhT0NBZW93Z2dIbU1BNEdBMVVkRHdFQi93UUVBd0lGb0RDQm93WUlLd1lCQlFVSEFRRUVnWll3Z1pNd1RnWUlLd1lCQlFVSE1BS0dRbWgwZEhBNkx5OXpaV04xY21VdVoyeHZZbUZzYzJsbmJpNWpiMjB2WTJGalpYSjBMMmR6WjJOamNqTndaWEp6YjI1aGJITnBaMjR5WTJFeU1ESXdMbU55ZERCQkJnZ3JCZ0VGQlFjd0FZWTFhSFIwY0RvdkwyOWpjM0F1WjJ4dlltRnNjMmxuYmk1amIyMHZaM05uWTJOeU0zQmxjbk52Ym1Gc2MybG5iakpqWVRJd01qQXdUUVlEVlIwZ0JFWXdSREJDQmdvckJnRUVBYUF5QVNnS01EUXdNZ1lJS3dZQkJRVUhBZ0VXSm1oMGRIQnpPaTh2ZDNkM0xtZHNiMkpoYkhOcFoyNHVZMjl0TDNKbGNHOXphWFJ2Y25rdk1Ba0dBMVVkRXdRQ01BQXdTUVlEVlIwZkJFSXdRREErb0R5Z09vWTRhSFIwY0RvdkwyTnliQzVuYkc5aVlXeHphV2R1TG1OdmJTOW5jMmRqWTNJemNHVnljMjl1WVd4emFXZHVNbU5oTWpBeU1DNWpjbXd3S2dZRFZSMFJCQ013SVlFZlFWaEZUQzVXVDA1RVJWSklRVWRGVGtCQlNWaEZRMVZVU1ZaRkxrTlBUVEFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQWdZSUt3WUJCUVVIQXdRd0h3WURWUjBqQkJnd0ZvQVVsalBSNWxnWFd6UjFpb0ZXWk5XK1NONmhqODh3SFFZRFZSME9CQllFRkM1N0xOM1JXMzhkZXhRaHhmSFcvV1d0N2NDUU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ3Z2UGltN2pvRjBHNHZPZXBTRmJDUmd0Q3dSQXllbjlmSHpEUzI3V25zVGJHOVVvcSt6aUdyY0QrVTVFbkg2VXJtRjFCcXhYTDFDanFFUHJuNVlRdFpTczNwZnZvblhrRkNodGlZWU9nSzRnSXFKdENWQmFYM0g0REhrSTFWN0JoN2I0dmpaQUQ4Y0pMeGlKZjZBdkk0ZTExRDlLNXRwWjdZWlFFNU13NDlWRHRROEE3cGtqTzZ3WGpIRlhYZ1kxbFB3K0xSUXVVM205S0dBTTNDNGdlMG90cFcwWHlLRHhxc0tXT3htTVg3SWpoWEZEcEtZb3BtbUxQY1R6NzBPTnRiRTJOSHlJYTNVdWpoY2piY3Jwb05rbWFGaUxrMnBxS1JaSW9Ia1phRk1kOXdhUTlmMWxTMnd3VlF4dEgrdk5WOU4zSytIbkwzbkIvQ1UyRTBidEpIIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQWJBQUFBR3hDQVlBQUFBREV1T1BBQUFBQ1hCSVdYTUFBQmNTQUFBWEVnRm5uOUpTQUFBRkZtbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTmk0d0xXTXdNRE1nTnprdU1UWTBOVEkzTENBeU1ESXdMekV3THpFMUxURTNPalE0T2pNeUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ01qSXVNU0FvVjJsdVpHOTNjeWtpSUhodGNEcERjbVZoZEdWRVlYUmxQU0l5TURJeExURXhMVEl3VkRFME9qUXdPalV3S3pBeE9qQXdJaUI0YlhBNlRXOWthV1o1UkdGMFpUMGlNakF5TXkwd05DMHhObFF4T0RveE9UbzFPU3N3TWpvd01DSWdlRzF3T2sxbGRHRmtZWFJoUkdGMFpUMGlNakF5TXkwd05DMHhObFF4T0RveE9UbzFPU3N3TWpvd01DSWdaR002Wm05eWJXRjBQU0pwYldGblpTOXdibWNpSUhCb2IzUnZjMmh2Y0RwRGIyeHZjazF2WkdVOUlqTWlJSEJvYjNSdmMyaHZjRHBKUTBOUWNtOW1hV3hsUFNKelVrZENJRWxGUXpZeE9UWTJMVEl1TVNJZ2VHMXdUVTA2U1c1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRvMk5HUmlaalU0WkMwNU9UWTRMVGc0TkRjdFlqTTVOUzA1TVRZNU5qVXhZVFF3TUdRaUlIaHRjRTFOT2tSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk5qUmtZbVkxT0dRdE9UazJPQzA0T0RRM0xXSXpPVFV0T1RFMk9UWTFNV0UwTURCa0lpQjRiWEJOVFRwUGNtbG5hVzVoYkVSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk5qUmtZbVkxT0dRdE9UazJPQzA0T0RRM0xXSXpPVFV0T1RFMk9UWTFNV0UwTURCa0lqNGdQSGh0Y0UxTk9raHBjM1J2Y25rK0lEeHlaR1k2VTJWeFBpQThjbVJtT214cElITjBSWFowT21GamRHbHZiajBpWTNKbFlYUmxaQ0lnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRG8yTkdSaVpqVTRaQzA1T1RZNExUZzRORGN0WWpNNU5TMDVNVFk1TmpVeFlUUXdNR1FpSUhOMFJYWjBPbmRvWlc0OUlqSXdNakV0TVRFdE1qQlVNVFE2TkRBNk5UQXJNREU2TURBaUlITjBSWFowT25OdlpuUjNZWEpsUVdkbGJuUTlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQXlNaTR4SUNoWGFXNWtiM2R6S1NJdlBpQThMM0prWmpwVFpYRStJRHd2ZUcxd1RVMDZTR2x6ZEc5eWVUNGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NnpPWFJsQUFCdU4wbEVRVlI0bk8yOWVidzFUVlhmKzYwelArTUxMNitDWUJCQkVFUkVva0VpaUdNY2JpU0tpa2E5R0RYR1JEU1JxREZxak9qVmE0eTVSSEZFY2NEZ2lFb1VIRkhqaEJCSHhJaUFnc3d6dk1EN0RHZDZ6cW43UjlXcVdsVmR2ZmMrejdQUFBydDdyKy9uMDZkNzl4N083dDdkOWFzMTFDcm52Y2N3RE1Nd2hzYmFXWDhCd3pBTXc3Z1pUTUFNd3pDTVFXSUNaaGlHWVF5U2piUCtBcmVDYys2c3Y0SXhVandzNWNYbHdJTFd4dHdaYWk3RW9BWE1NRzZGR1VWcVdZVE14eis5MzhmRXpWZzFUTUNNbFdDS1dMV2VPNGx3M2FySXpTSTg4ajlhciswVk54TTFZOHlZZ0JtalpJSmcxZnZkak0rMUhwODJ0Zmo0Nmp2STg2N250WjN6WUlKbWpBa1RNR01VOUFqV0xHSlZyUFhudU1hKytybDU0eHNDNDdJWStYb2YvZXVtcUptZ0dXUENCTXdZTERPSVZsT2tVTUxrcW0zWDJLL2ZjMXJDVlg5aEpWWSttbDArZmpldkJhMjFUZjlhMDdIUVRNeU1vV0VDWmd5S0thTFZXaGNDNVVzaGN1UjlhVkd2NndoWjQvL1BTOUNhTHNESytoS1JTb3V2OW5uMXZvYW82VzFYUFRZeE13YUhDWml4OUp4QXROSzJGaXpYRmFnMXl1ZlhmTFV0cjlWQ1ZvbmZxVkdMRUEzQjhuQ00yaFlSMDg4MTNxUEZEdlVhRXpOamtKaUFHVXZMQkd1bkZpMXRIYTFWZ2lWaXRhWUVhazA5bC9hVGw4NzdmUGYvMU45cERvZGJidnUyS0lsd0hRUEhzait1MDNOSzFJcjNrVVh4MkhXRmJLS1ltWkFaeTRZSm1MRlVuRVMwYWl0TFdVOXJ0V0JGZ1ZyM3BWQ3R4ZGNXKzVYSXBjK2pGRVg5Zlc3Wkl2TU44YUswb0pJSXVTeGF4K3J4RVdxZmV2N0lxL2NvUVV2YlBkWlpVOHpNS2pPV0RSTXdZeW1ZSWx6MXRvaFRzcUxJd3JWZUM1YUQ5ZmlhOWZqOE9ubS9pTmQ2WEVTODFodldXaTFpRUFSMFRxZWcySmFsc0tvcXNUcnljT1RVTmtHY1pQdW9FcmdrYU9SOVdoaTlFcm1XaUtYdmFWYVpzUXlZZ0JsblNvODdybWx0a2QyRFNWUjhLVFRyOWFJRWF3TzFyZmIzTGcxcnJSQ3dlY2ZDbENWV0MxaGhWZFdMRXFzakg1WWJhdjhOTFdoVTI4bzZLd1N0Y2pPYVZXWXNKVzZvTmJBQXE0VTRZR1lScm1nOUpmRWlXMVppWFlsbHRWRUxWVnpYUzdFL3ZrYy8xMXI2Qkt6alNyejFVNUxXSFFHalI3eklJblZEQkVzdDllTml2eEsyRzJRUk82THJwaFFYb3dpYy9wNzZ1OHNKR1c2anNxSU1WUWZNQWpNV3lnVGg2c1MyZEdLRnVBWjlhVjF0aUdncElkcWNzdDRBTmwzNW5scjR0SGhwRVhOVUdZbk1XY0JFTE9nSzJCR2xpR21CT3ZKWnhHNEFoMlN4T3V4YmV5VnFUbGx1MEhVL3h1MDEybFpaY1F6bVhqUVdoUW1Zc1JCbUZTNXk4b1FrVTlRV1ViS2dmTENpTm4wV3FOYXlSUmF0VFIrRnpDc1JVMkttLzRjV3IzV1U2M0tLZU0wcWFLM0dYZnJCUmZ5TFVyeU9VVUlqb2xXTGx3c0NkVWdXckFQeTQyS0o3OVdpcHkwMWliT2wySnZ2WmppYWtCbG5ncmtRalZQbHBNSkZ0clphb3FXdHFiUTQyUEpackRhQnJjYSsrajBiU3ZoYUZsaHRmZlc1RU9IV3JiQzY4Wi9rUXBUMWpXcDlXSWxZdlJ4RVVUc2dpNW5lVjc5ZVcydnAvN2d5RVVRRVRic1htNjVGRTdIbFpxZzZZQmFZY1NyY2hIQkpNb2FPUzBtc1Npd25iVlZOWEh6NXVCYXkydkthUmJ4MFBHNmU0aVVVSXFaY2ljZk1JR0pLdkxUcjhCQWxWa3E4cGkzcGZTNjdHcE9ZdWZ4L2o4bFprSzRoWk9sNHpCb3pUZ096d0l5NTB4QXZMV0JyRGVHU3JEL0pFQlMzb0JhZmV0bFc2KzFxWDcwVXJrVGF5UjFGaWoxNTdlaTN2dVo5QVU1SzVKQjFKMVdlZHJKRzdUcHNDZFcrV3U5WCs5SlNXV255MllWVmhuSXgwclhHekNKYmNvYXFBMmFCR1hOam10WGxHd09JVVlrWVltbjU0QUxjakZiVXRvTnRYNHFWN051bXU1eEV2RnBwODNYU3hrbkY2MVppWUhyL0pCRXJ4bmJSTDJUVFJHeS9XZzRjN0h1MUx6NlcxOWFXMlNIWjhwdEZ5Tkx4K1pBTU04eFcwMWdhVE1DTVcyWVc0WEpoT3cwZzFxNUNMVnhFb1lyYk8yU2gyaUd2ZDN4YnlGcmlsZHlHdE1XcjZTNmtMVjcxOFowR3RiWFNLMkswM1lwOTFwaDJLUllpcGtVcnJ2Y28xMXJNOWwxMFI0cUl5Ym9XTXArdFJmbk94WEdhVzlHNFZVekFqRnVpeDEyb2x6UjJLd3JYeGlUaG9pRldMZ2pXRG5DdWZ0NTMzWWVkZUplS2RjMlNwTkd5dUhvdEx6Y25JZlBkUnJ6UEVwc2tacDM0V0JVYjY4VEZLQzJzV3J6MlBPeEY0ZHFUNXlxeFMzRXpMV1F4VHJaR1RQb2dXRngxZk15c01lT1dNQUV6YmhyZnRrcUtPRmNkMzBKbEVkWnVRYUpnRVVUcm5JaVdFaTk1WG90WXNyaGN6andzM0lWKzh1RGtqbkJWeVJvdDRVcmJwOVRxK3NhMnAwenVtTVVxMDNHeXdxMm80bG90bDJJU0syRFhLekdqWFBhVnVFbTg3TUNyOUh6aUFPdG9sVG4xL1lyak5SRXpiZ1lUTU9QRXpHSjFVY2FXNm16Q0xWZTZCbVU1RjYydGN6NElsbDVxOGFxVE5qWjgxMTFZaTFZck1hTmpjZm55dUlDT2xYVmE3a09oMXhyei9aWlpYWFcrNVZwTVF1WXAwdVg3NG1KYXJIWmI2eWhlMjNGYnYzYzkvbzgxU212c2lCNXJ6RnlLeGtreEFUTk94QVR4a2dLN09zNlZ4bHE1eWswWXhVdUU2VnkwdU01NU9FKy9lSW1BMWU1Q2JYRzFxbW5vS3ZQVEVqTW1XbHhuUks5RlZtMG5NWXVXV3RNcW94emIxVXIwRU5kZzRVNTB3UnJUQWxZdkluYWJQc2ZOMXBWWWlvVnIxcGd4RjB6QWpKbnBjUmxxUzZiaktveFcxNWJQU1JlU2hLRUY2bng4TE9LbFJhd1dybTNLT05jc2lSbmFyVGtwcmpVcFFlT3NSTXczL3JlZnNQYVVic2JheFRncDRVUGlXT0lLTEt3eDM3WEFycXYxVGx5TEszZlhoZDluTDM3V09sbkkxbUpjVGdSTmYwZUhpWmd4SXlaZ3hsUW11UXk5U3RDSXlSTHJ5bFZZWkJQU2RRMmVieXpueUJhWkZpK3gzdXJNd21uRmQ2ZWx3VSt6dE03YStwTC83NmZzNnhVekppZDlGTzVGbjFQanhTSnJXV05pY1oxemNOMW44WkxFbXV1RWEyQ1A4QnZ0VWY0K2h6SE9LSlU5aUNLMnByKy91UlNOYVppQUdST1psS2hCZHN2SlZDVmFYSFJpeGlUUnVvQ3l2RVM0bEhqVkdZYTYvRk5MdVBwRWE1cVYxUlNxRzhBN2dYZUJ1ek51dnhsNEcvQU90YndOdUVyWjJoOFNXbmtYRDA1T2lpajZaZUM5Z0hzQWQ4VDFQWUgzQVc2UHk5M0IzeDdlMnlldVhtMUR2NUN0TWRrcWsyVXJIcmFzdCtNaDdaQ3RzWFB4MEhaOTE5V3JyYkRycU9MSmRLZXB1YUdzWWoxK1RHUFdtTkdMQ1pqUlM1L0xVRnRkWkpkaEt2UGtsY1hsY2x5ckpWb1hDS0lsTHNUYTZ0THV3azdkUXFlK0N5ZExmKzhWcTdlRCt5dmdiNEdYQUcraUZLcXJKenFEQVE5Y08rRjdMaEVFN1I3ZzdpQUkzUU9CaHdNZkRMd3YrSzN3MHBZUWE3ZGp5eUtyeFd6ZDVTbFVSTWcyeVVJbVdZWGlWa3hKTndRaGEyV0hicE1IcEV0bEZiSEc1Tm81aU9JazFyeE84QkNSTlplaTBZc0ptTkZobXN2UXFXSzd5dXFTSkEzZHVKMzNXYWhrT1Y5dGk4RHBSSTJXdTdBZXc2WEY2OFNpZFF5OEh0eHJnVCtOeTE4U3JDdXhuczZTSzNGNVRiVi9nM0NDN2dudTRjQkhBUDhRdUE5d1AvQTc0V1hUckxXT21LbUVqL1c0M3FDTWt4MzZQRnlocndwS3loQ1YxM3FLUWVVcFZobGR6WHJtZ1VOaWdvZFNYL21PWUM1Rm80SFZRalFLSm9pWE5EWjFoWGh4RnlWM29Xc0xWNzJrbUpmTExrT2RGdDhYNStwekZWSnRVMjF6RGR5TGdEOEEvaHA0UlZ4cW45VVF1Uy93UVFRTDdiSEFZNEJML2VuNHNsMExXdUZhZExsa1ZaM3MwUm8zSnNrYzF3a0c1eldDd1hyTndWVWYxdGQ4MkMvSkg3clNoMDdyTDZadm9SUmN3RVJzM2d4VkIwekFqRVNmeTVCZ2VVbDZmSnFIQzVWZFNCbmowa0oxMGNFRkR4ZXBMQy9LTE1PNkJGU2ZjRTJ5dVBSMzV3aDRGYmkvQVg0RGVEN3dGa0tyT1dhMkNURzFSd09mVExEU0hwQmRqa0pMekZxSkgxSTRXTTlEcGt0VHpTSmllcEg5OGpwSjBkOG5Eb0oydVhxSXpCS3R4VFY5ZHhPeCtURlVIVEFCTTRDWjQxMVMyYUpqZFZIR3R5NnE5VVY2eE11VnBhQTZiaVptRjY3aVFyZ1QzSE9CWHdkZUJMeGhIaWRvd053VGVCVHdDY0EvSmJnYXE1ZjBKWDcwWlM3MldXTTZRL0Y2dExpdVJndHNrcER0a2t0V0hiandlYW1LQitYOFl5WmlwOEJRZGNBRXpHaUpsMWhkS2Q3bFZLV0xHQU1wWWwyVmxYWEp3VVZmQ3BtSVd6MjJxODlkMkNyMzFCSlpBTjRLN3FYQXp4S0U2ODJNd3pVNGIrNGd1QmcvaDJDaDNYdjJWUHg2VUhSdGplbkN3RW5FYUZ0aFZ5aEY3QnBaeEtTaVI1cUx6T1Zab2JXZ3B1OXBJbmJyREZVSFRNQlduRXE4OUxKT1RwR1hERUJKcnRDcDhSZUFDeUpZY1gySnJ1VWxWbHBkVGFPVkZ0K0tjK252bUhnVnVHY0R2d0M4ZUc1blpUVjRLUEJwd0djREh6TFpLbXNLbVFnTFpUVVA3VkpzdVJORnZLNG95MHlMbUk2TnBUbklYSFFwa2wyS1JWek1ST3pXR0tvT21JQ3RNRDNpVlNkcmJMb3lQVjY3REdzMzRhWHFzVmhlNGphc0V6WHFLaG96Q2RkMTRNWGdmaEw0SmVDdDh6c2xLOGs5Z0k4Qy9oWHdHUENYeXFlbkNWbVJxVWhaamtwYll0ZnBXbUZYNkxvVnRVdHhEMVVjbUNuSkhTWmlOODlRZGNBRWJFV1pKbDZTcklGS20zYXhra1owRjRwNFhWTHIydktxeFVzbmFzZzBKek1uYUJ3RHp3WDNZOEN2WVM3QzArQVRnYzhuV0dYYi9lN0ZsbHV4cm5oZng4V21pZGdWUXJ6c1dzeFkzUFdoSEZXYXRrV1NPMHpFNXM5UWRjQUViQVdaUmJ6SU15TnYrU2hBVWJqT295d3VCNWU4RXEvb1F0VGlWV2NaNmtTTnVrSjhNem5qS3ZENzRKNEd2SUR4WnhHZU5ldkFod05mQVR3T3VEeFp5UHFLQmV2Sk0vY0lZclRyY3pwOUVqRUhWM3pYSXJ0R1NBU1JxdmVTM0hGb0lqWi9ocW9ETnBCNXhUaUplQkdUTlZ3YzErVkRyT3VTTHkwdXZZaGxkc0dWVlRWU29vYXl1bXFYWVVlNFBQQWNjRDhFL1BhcG5oVkRjd1Q4Y1Z3K0NuZ1N1TThtQ1VQZGE2eC92enI1UmhkWExxYlhvVjNMc3BQQUU2OVo1OVUvcWI2SVZlMVlVVXpBVm9oR3R1RWt5MHNHRjh1ZzVJdmtCSTNMeEhVallVT3FhelRqWFg1NnJBdUFQd1AzSGNDdkV2eEh4dG53aHdRaGV4YndkZUFlVFVmSXRKNjBGaTFFaFpEUkZiU09nRVV4U3RkdWo0ajUrSHFyWnI5aW1JQ3RDQTN4MHRPTTlJb1haYXhMeE91eTJ1NklGNVhMMElYUG5XUjFKZUY2SmJqdkI1NUJDSmdZWjg4QkllYjRPOEFYQWw4SjdzR3pXV1BPbFNXL1d0WlczNlNqNlRyeDFUWFNJMkpIWkJHVDE1bUlqUndUc0JYQTl6YzA2NVBFeStXeFhGcTR0SUNKOVNWcDhoM3hvdXN5YkZwZEI4QXpvOVgxbXJtZkFXTWU3QU0vUkJobjl4L0JmVEVwMGFQWEd2UGRqa3JMeGRnVU1KZmYzOEhubFNkWVhONWxDMHk5eEJnekptQ3JoVzVZMWh4cEVzb05WTXlMdG5qZEZ0ZVhYZWs2Rk11clR0YW8zVUphdUlvZTlZdkJmUXZ3M05NK2VtTXV2QTc0Y3NMdjlhM2dQbnhHYTR6eUdxaGpaUFdzMlM0cVVNZTlURFhnT2dXLzhvdlNRR2V6d3NhTkNkaklhU1J0U1BWdkVTNDlRRG1ONzFMaUpjS1ZCS3doWHVkUTA1L002aks4RHZ3Z3VQOU9xSnhoREl2ZkpFdzU4NVhnbmt6VEdwTkpLdVd4VXdMVm5MdXRZYkhWd3VWZEVDYUp4WGxQbm9GYTdVL3ZNUkViTHlaZ0k2YVZjU2p4aUNnd1VwUlhzZzNQK1RMbUplN0MyOGdDbGpJTzZWcGVtMHdXTC9rdS9BMjRmdy84MWlrZXYzSDZ2QVg0ZWtLeXgzZUMrNkRTSUpKNXg2YTVGTFZGMWhJdUlRbFd2UzJpUmtqaDk1VERCRTNFUm9vSjJFaVpsQzVQSGtTODZjTUE1UjN5dkZ3WEtOMkdXcngwMGtaTHZQVDRydDRHNldmQmZUM3cybE03ZW1QUi9CcndVdURid1gxdXYwdFJhRjJiblU2T1FvdFUyaWFYdEpJWVdCSzIrRDVkL05jWUlTWmdxMEVTTDZjbW9uUjVZa0laNnlXRGt5LzdidEtHV0YrdGJNTldJZDVPdy9SMmNOOEsvQUJXUldPTXZCYjRBdUIveDVqbTNicEMxamQvV3kxY0hiY2g1RWszWFo0OStwZ3Nhc2RlaVp6TDcwMUpIV2FGalE4VHNCSFNaMzNGakVPWlJWbW1RMG1XVjB6Y2tNb2F0WEQxcGNyckdaTnJ5MHUrQTM4TDdsOER2Mys2aDI2Y01VZkE5d0t2Q212My91MHNSZFJqVnowV1VxS0dzcnlPS2NXclhyUUZwb1hNa2pwR2lnbll5SmlRdENFWlg2MnE4aGNvQnlucmJFTXRZSFZSM3RyeXFvUHlBUHdtdUs4RS92WVVqOXRZTG40TitIdmdCOEI5VE5zU2czN3gwdWlZVjEyMnFpTmlYbGxsRFN0TVBzOUViQ1NZZ0kySUhzdkxSYXRyblJEekVnRXJ4SXZHWU9XZWJNTSs4V3JHdTM0VTNIOEU3ank5d3phV2xKY0Rud3Q4RjdoL25nVkRyZzFKOE9oRFcxTXQwWkx0STVkbmpFNHhNYktRclNzcnpFUnJaSmlBalJmdE5seHpaWTNESFVKVitmTTlXWWV0Q2h1dGhJMWU4ZG9IOTAzQVU3RjQxeXJ6VmtKYzdFMHgxWDZ0M3hvVGZHTmRXMXBTTlBpWVBDZFoydWRMSWRPTHhjTkdoZ25ZU0ppV2RlaHpyQ3E1RG4xcGZkWFZOU2FWaDVvb1h0ZkJmUVB3UGFkNnhNWlF1QUY4SFdIYzM5ZURXNTh1WXRCMkczYXEzcnN3eFlvV05EM3BaUkl4aTRlTkV4T3dFVEFwN3VYS0daVTdjUytYWTE5NnFTMHZLY283MWZLNkF1NUp3RStkOWtFYmcrSUc4QlRnbmNDM2dic3dXY1JxeTBuS1JJbDFsU3d1WDA3aGt2YXJUTVhrVHNUaVlhUERCR3c4MUducmFiQXlPV1ZlaTFlZHVLSG45THBBY0MrZUpGV2V0NEw3dDhBdkxPWjRqWUhoZ2FjUkxMSHZBbmUrTFdLZXNsMHFVdWhwVzJBMzR2YVJiUHNvWXVvOU5qNXNoSmlBRFJ4Zk5nQVF4U3VPOTBxekt2dHNmY2xFa3hjSlluWEpaMHZzSW5uU3ltWmhYbm9HS044Sjdrc0kwNThZeGlTZVFiaUF2aHZjZHI4bHRrNDdrYU1RTUs5bWd2WjVSdWphT2t1RG5RblduRTQwTWl0c3dKaUFEWmcrMXlGNXZGY3Ewa3RQMXFHNEQvMXNNYSttZUwwcmp2RXk4VEptNVljSUY5cC9BYmRWaWxqaFN0VENRM3ZtWjdHK3RJQVZRa1p3SnlZaG8rRktQS1hETkU0WkU3RHhvQk0zSmhicUpWdGZZblhwOGxBNlZYN0xUWjVCbWF2UmJmaUxpenBLWXpROGpYQ1JmUnU0S2p0Ulg4Y3d3UUlqVzErSHFLVjJMVkltZVloSUpsZWlXV0hEeEFSc29QUmxIYm9zTmtXMURhcllGOW42bWpqT3k1ZldWMkY1N1lIN0t1Q25ULzFvalRGeURId0hjQWZ3VmVWVE1qR2xqb2tWVnBqTFZwVUltUll3RVMvWk5sZmlTREVCR3paSlVDVHJrTGIxVmMrdXJCY1J0Y0x5b2gzekt0S2R2eDM0MGRNOVBtTUYrTS9BKzFBVUFaWjFLek5Sc2hHMUJaYUVpOG9TbzNJcCt0SVMwLy9QR0NBbVlBT2tTdHhJNDcxMDFpRmQxNkVJbUJZeExWNnpaQnpLLytOSHdYMDdkdWNidDg0dThHK0IrNEI3YkRjK2xkeUp0T05ndFpBZGtNWHJ3TUZoZEMrS0s3R1ZtV2hXMkVCcERTQTBscGhKQTVaZFY4QWtjYU8ydmk3UUZhL1dXSzltVmZuZkFQZTFXSVVOWTM3Y0NUd0plSGtqTVVrdCt2cldpVWwxYkRkZDMxNWQzejY0MUF1M3VHL1U3alNHZ3duWXNDa1NOMURpNWRvM2VDRmlyaFN2dXI1aGEwNHZYZ3J1M3dEdldzenhHU3ZFM3hCRTdFcC9KMDFmNDNVbnJaNU5YT0s2UlZhdGkxbTEwVnV4VnNYQkhEU0hwaGhMaWduWWdEaUo5ZVhidlZNUnNmT0VVbEoxMHNZazY0c3I0UDRkOExwVFAxSmpWZms5NEZ2bytQQzBKVllrS1pGRnJIYVR0N3dNSW1MRmRlNGIxN294REV6QWhrbEszRUFsYm5nViszS3FZQy9selh4ZUxYWFNSaXRkSGdnQmhtOEVmbmNoaDJlc010OFBQS3ZkV1V1V21PdFBWT3E3M25mSWJrVEpzSlZaR3VSNlQ1Z1ZOZ3hNd0FaQ1pYMUJDRFk3ZFJOdU9PVldpZGJWZWE4RXk3WFQ1YmNJcGFZbXhyMStGdHd6Rm5HZ3hzcXpEM3c5d1YwZGQ5WHhzSFROazYyd1BwZDV1dVpkSTlicnNoWFd1ZWFONWNjRWJGZ1VhZk0rVHBWQ0tWN1RibVFSc0NMdU5XbXc4a3ZBL1FkZ2IxRkhhYXc4Ynlaa0p0NDFQUjdXcWphak0yL1Q0aHRUQXZsMnZCY3dLMndJbUlBTmdNYU5sRzY0bUZHMTRjTmNYOGwxU0huelNuSGVFMDlLZVlVd05jcGJUL2NRRGFQREg5S2NrcWVPL1JhekxiZ2VFWFBaQXV1TWRUUXJiTGlZZ0EwSGJYMDVHbFUzYVBkQ1c5bFkwMUxtRTA4SGZ2MlVEOHd3V2h3Qi94WDRvOWxjaWJyeVRLY1Q1OHZaRmJaZHZ4VldYUDltaFMwM0ptQkx6aFRycXpOd3VaRjllRkx4U2lMMjUrQys4elFQempDbWNBMzRCa0xCNkxpckpXWjFhbjB0WW5wOWpoQWpsdnRnZzM0cnpGaHlyQkxIY09oWVg3NWhmYm1RSGwvNy84L0Y1N1o5NVRycDYzM2VGZU5lNzF6Z0FRNlpOWEx2WUpzeTV4dENGcWVVa2RnbnhCUDNzY0hncy9DSGhNSy9UeUZkb0hLZFNxMUVIUlBUQXJaUEZxOWR0ZDRCOWgzcysxaTVJOTRIUitvemorTC9zZW9jUzR3SjJCTFR5RHhzV2w5T3VVNTg2VDdVNDE5MHI3UFBkWko2bnM4a2pNa3hTbTRIUGhCNFArRGVjYm1EYmwwdU1RdmtCanNrMXpHNnJwYXJoRTdDbXdoeHh0Y0Fmd2U4WlJFSE15QytEL2hNY0EvcnFWcFBPTFdGTjhKMTd3Y1JzVDFneitjTVJpazF0ZTdqVE00dS93OFRyaVhHQkd3WVRMSytOdU9OdUtOdTJNSnRFcTJ5UHRkaFI3eGVCZTQ3Rm50OFM0Y2ppTlQ3QWc4SEhoWFg5eUwzQ09UbThiZll5RWxqZVVSb1dYY0pvdlpTNEUrQXZ5QU1Ibjh0cTVzSmVpZndUY0RQa2VZUGczWlc0aEhsWUg2eHdyU0lTVGFpR01LYkJDdnNpRENUczN5dUZmdGRja3pBbHA5NjNGZGYwVjdkMjlRaUpwYVg5dm0zc2c0QnVCSEZhMVV0Z0ljQ253ZzhFdmd3NElGeGYwdWtlbHExV1JzN25hN3RJZndZNHZPOUIvQWc0RFBpNjk0RS9EbndZdUIvQVM4a21BMnJ4RzhBdndCOFhuallsOWloNzR1dDZEYlg5OFU1UXFkdVZ3bmNnUXNlaVJzdWV6aTh5OFYrYmI2d0pjVjVQOXpmeExueHhsa3I5NkdNK1ZwSHBjdjc0TEc2NU9BeWNIY2ZQRnozaU12dHdOMGQzTTJINTJYQ3lycnlSaEgvK25Wd2p5Y0VCbGFGRHdBK2p0QXdQb3h3NGlaWVZhMzl0M29UdFM3azVzWHR3RjBsdUJyL0ovQmM0UDhRV3VGVjRLSEFid0gzeXVJaW9jVmpja1g2ZllLbGRRMjRBdHhGS045NUo4RzRsZVZkRHQ3dHcydXVFcnk2K3k1Yy9qS2pjNnBhUDJZQkc2b09tQVcyM0NUWG5sTkNSbkFoU3RGZWNaWG85UGxXdHBXNERudlQ1dmZCZlN1ckkxNGZBendCZUR6d1BtVFJxbTVsUDhQMkxJK0ZXcGhxRjVXT3ZiaDZ2d2QvZ2RDUWYzQk10UGwxNERrRTYyVHNMc2FYRXVhZyswL2hZY3NLNjNnblhNN09UZmRJZEt2dnh2dGozNFdPNFFaQnVDU21kb3o2ZmN3S1d6NHNqWDRKOGQyR1M5K2NSZGtvcjdJUHFaSTJYTHZXWVN2dTVRQitDdmpqVXorNnMyVUxlRFR3YzhBdkExOEcvbDU1bGw1QjkreDFEMTl2dCthbDBuTlQxZnVuUFY5L2J1di9KcGRXL0pKK0cveW5nMzhtOENMZ1h3TjN1L1hUdE5UOEVDRk9xM1oxeG9mUlB6YnNIRUc4Uk5CMjRtczJYVmo2Wm1JWXI3dG53SmlBTFMvNnhrazNsQXV1eEUzZmpYL1ZGdGlKcks5M2d2cyt4dDI5L0ZEZ3h3blpsVThBZjJtNmFHa1JhWW1RbmtpeFhrOWFXdThwWmc2bUsyeXQ3NWErL3hyNGg0Ti9PdkFyd09jeTNoYjNEY0FQa0lZZzFCMnhwb2lSUlV4YlltbmtnNnZtQ3ZNMkptd1FtQXR4dVdsbEg4ckF5eTNKUHFTOElXV1pOZXZRQVR3TGVNa0NEMnlSM0EzNEtvSjE4bDc5cmo3ZjJLN2pMT214eTFaYnZlalAxTnNkZHlEVjcrRHliMTAzeVBVK25TRlhmS1lILzVIQUkyTXM4MXNJYnJleDhVemdDM05hUGZSNEtpZ0ZURnRpdFFXV2lsckhlUE5hRkxGamx6L2Z4b1F0R1NaZ1MwYVZ2Q0dQMTF4TzVKQzZoL1ZOMmVsVjBoV3dwdlgxZG5EZnpUanZ5bzhIdm8yUUJ0OXdFOHA2a2xnMTNYbSsvZHBKUWdZOXdrV09iOWFpdFZadFR4SzE0bjlzZ0g4Q3VJOEN2aFY0QnVQS1dud1g4RlNDa0RFOUZsYU1sU1FQK0svdmxTMmZCemJmd0ZMcWx4NFRzT1VrM1pBdXA4Nm5lYjljS1dEMURabHF2Zm5wazFRNkNHNjFzVTFTdVFYOE8wS3cvN2JRY3hiNmhLc1FLaGNIdE5LTmQvWEZ3MXF1dldrQ1ZndFYvYmlJeDdoOEhmUUpXeUZrSHZ3OWdlOEI5MmpnYTRFM3puYjZCc0d2QUg4RjdrTzZWbGh0aVhVNmZMNXJpYVhpMXRIVElUTTlyR0hKSEV1TENkZ1M0ZW4wcENkWlg0V0FWYjFKWFRLcXQ5STh3SnZCUFdzQng3Wkk3a1Bvblg4T1RhdXJKVndka2ZMZE9GUzlYUXZhTkJHYlJieldHK3UwN2F2SDFYdGJ2NjhqUE9FL0Q5eERDVzdVc1NUcTNBbjhNS0hNMUhwNXpGcndPM1VTWFptVm1OenRxdE5YdTl5bHZKVDhEeE92SmNFRWJEblJzUy9uY3VYNVl1b0lTaGVpakEzckpHNVVQZmVpa1hzZThMS0ZIdHJwOGhCQ2x0cGpKbHRkdFdocGdiclJXTmY3MHVLeTJOVWlwdjhmbE1KU2lGZnM4V3ZCMGpFYy9idlgrK281M1BTaWNSNzhod0MvQk83TENXbjNZK0Rad0ZlQWUzQWpGdWJMYzVrR04vdnEzcEg3eGdjUmt3U3BBOEx2Y2dScEdJdXhaSmlBTFIvNlJwR3FBSzJzS2wwK3FsbnJrSnhSMVl4OVhRWDN2WXlub095akNNa29ENWhzZFUwU0xaMFJLUFh4SkI0aSt3cHg4MjFyckJVUGF5Vm5pR1dsZjErOUZwZldocklNOUcrN1NWZk01SC9XdjdjRHVDZjRud0IzTy9Bakp6L0ZTOGM3Q01meC80V0hMU3RYbDZWc1ppVDZydWRDem5tZHpHRnV4Q1hEQkd3NUVjdEw5eVQxN0xQSm4xLzFKdVU1SGZ2cXpUejhaY2FUb2ZaWTRIOEE5KzBYcno3aGFxVzlIOGphVjgrNUlGcXRsSGN0WXJVVkJtM3JxM1lWaXNVczZkeFM2MUs3d1BSYUw5cEtFeUdyclRFSGNBSDhkNEhiQkg1d3h2Tzd6RHdiK0JwdzkycDNGbG9aaWVuK1VlN0VkUCs0UEtoNTNRY0x1WlV3WStLMUJKaUFMUW0rNmozR0hsN3FwYnRjZmFPK0NZdE1LdVVDMGU2VFR1eHJiMFN4cjQ4RWZwWlVYZ2pLdFFpS0ZoazkvdXBBRmhjRTY0QllIMCt0dGFEVlk3ZGFBNUtUY0RyVlk2Yy95YUFRTUdWdGFjR1MzMXZpT0pMNnJaY2pRc2JkY1d5QWRZTmVDTmtGOFA4ZDNESEI1VHBrM2dEOERQRHZ3ME94a2xyeHhZNEhvNDRkeS8wakZoalpRblpLeUV5OGxnUVRzT1dpY0I5NjFkRDUwcFVrUlVvNzFwY3ZlK04xZ0QvOWp6OGpGSVFkT284QWZvS0o0cVd0cnRyaTBrSzE1OHVwdXZaY21DOUtpNWdJV2N1ZG1GeUlUcVhaVnkxZHlpcWxiRmc3YmtQS2hsYi8zanVVVnNPT09xNHR3di9lak1jdjk3ZUlsMXhQSG5EYjRMOFQzTHNJVnN5UWVRN3d4ZUJ1eStJMXpRcmJWdXQwRDhWT2dWaGdHNmpzVDUvSGhBSG1SbHdHVE1DV2o1YjdjQjBsWHBTQmFOMERMOUxtWGJlYVFCS3hueUZVTHgweTl3TitraUxtSld2dHh0UHVRdTBpRkxIU3k2NWUreXhtdFNYV1o0RWRrOVB2UFVCbGdhVnhmWFFGckU3U0tTd3ZKVjQ2L2Z0Yy9FNnl2MVc5dzVQbjFaU1U4Q1JpbDhEL0FMaTNBcjgvKzZsZk9sNEl2QUQ0cDNsWEo5WklPWWZlWnRVQlRCVTV5QjNCWklHWkczRTVNUUZiQWlyM1lYSTN1ZGo3STFmZ2tFR1pFbXpXUGNuT21DOVBKLzRGaEtsU2ZtRWhSM1o2M0E1OEQvQ1F0dVdseFV0YlhTSmMreTRJMUM1aGtma2w5V010YkRMbHhxSHZGekE5ZGl4VjZ2REtqZWVxekZMZmJseDFBOXRYQmttbXl0bUwyd2ZxKyt6UVRpWVJPaUoyTy9nZkJ2YzQ0RzlQK0Rzc0M1NHdxRGtLV0Y4eVJ4S3d5djNhc2NCUWlSeVlHM0ZwTVFGYkh0Sk5KMjRtcjI2NnFrRXJianBLQzJ4UzFRMEg4UFBBMnhkeVNLZkRHcUc2eHVQb3RDTGFiYWpGUzZ5blpHbEY4YnJtb25qNU1QWEdkZUM2eTg5ckFUdU04YkZERnovWHR5MnZQdUVBMVlPdjNJZ3B6a2xNNEZDL3RReVowQVBXWldiaDg4VHBQNVN3OW1WRDFxZFFSQXlBQjRML1FVTDVxYnVtblA5bDViY0pSWDZWUmQ2S09SWVppYTZiVmk4RG1qZDlIdFRjNjBZMHpoWVRzT1VpSlhERTdUVDdzcmJBZkw3eHRIalZXV2hOOFRvQTk3eUZIdEw4K1FMZ1N5a0dLV3VycXlWZTRpNFVDMHZFNm1vVXJxdHEzM1dmcmJGa2ZaRXRNTWxDYk1XOWttaklkOU11eFBobFU2TmFXV0dGdTloVkxtUEtTVXZQbzhTMXNncWJ5U1NOMDdoRzJkRHpjY0RYQWQ4dzA2K3dmTnhGbUNQdGE4cmR2VllZWFV0TTRvMVNuYjRvN3R0eUk4YUFtMWxqWjRRSjJKTGhzM0RwNmd2MU9KWmF2UHBLUm5YY2gzOFJsNkh5S09EL0pWU1hpTHRhNGlVQ3BzVkwzSVFpV1BWeWpTeGl1OEJ1bGNTaHg0T2xRY3hrNjB1K1F4SU0zYkJGbjFQaDJsS05ZajNlTHhWdHBwdTAwM0Z0MGhXd3ZyRm9MVktDaHdmL05lRCtCUGlsQ1c5WVZqendhOENYZ3J1Y2QzYzZnMHhJcXlmZVc4cmpzWTRhRHdZMnFIbVpNQUU3WTN6VnEzT3FjYVBIaGVqeVRkYXFkOWlxT28rc2Y0dFFnbWVJN0JERTYzMjY0dFdLZTBtV29SYXZxNFRaZDJVRzNpc09ydmhLd0Z3VUNGOEt4QTNYN3pZc3F0TlhQWElkQTVNZDZiZldNVEc2d3lhU2lNWGZlNXNncW5zRTErRytMMk56V3NEcWtsYTE5VkJjRjdLOUFmN2J3YjBJZU90TXY4cHk4U2VFR2FvZm5YZTEzTFpGc2t6RG15SDNtb3pMcXkwdytWeXp2TTRZRTdEbFFrK2RvdXNmYmlpaFNtNlBTcnlTOWVYSzdFTmtmUjNja0pNM25reHdjODBROXhMeGtxbmx0WGpkRlpjcndGMCtpcG1EYStJNjlOM01RMjE1RllWK1JiaDhPZVpyWXNNbVBYZ3RaSlMvZSszdTJpQlhTdTlrUmZxRysxQUphdnlYbmNRRzR1ZUtCWmkrM29QQi8yZHdUNDRmT2lTdUE4OGxDWmlJVENzVzFoZGI3bmcxbE5XMjF2ak5iSXFWTThRRWJIbHc4VS9SVzZ4Y2lQWE4xWnFzTW1WTVVUWlcvQldoZHpwRUhrNlkwNnNSOTBxV2w0TWpYN29PVytMMUhoZUVTNFRzS2lFV0pna2N5Zkp5WGJkaEVpOVhpdGJNNGlWZjNFV0x6T2ZmTzFsa3RUVkdhR2dsaVdSTExDNzEzVHF4TDUvUFRTMWNyYW9zeFhVQ0ljNzRQNEhmbVhZd1M4aHpnVzhEdDlrV3I4SUs4K1Y5Vkl1WXprUk1IWXZLaFdpVzJCbGlBbmFHVkRHUlNlbnpyYkZCcmRoWHMrYWhiUC9TS1IvUGFiRkJtQmJsam43eE9pYUlseDZnTEVrYkV2TzZBdHdWeGVzOWF2c3FLbzNlTjJKZVVSaVRjRlgvMzd2OG5VNFMwTmNkRm5tczNWM2FJcnNScndQSmZ1d1VHSFpWRW9sOHBuSlQxb1BhNndrMFFjWERMb0ovQ3JnL2lpZHlTTHdhZUJHaHZGaWsxd0tqTVdpYzB0c2hZeXAxeDFDeU9FMjh6aGdUc0xNbk5XQ1Y5VlZYMHE3SEJqWGRoN1I3MlZ3SDl3Y0xPNlQ1OGluQVozVjN0MXlITjJpNERsMndzTzV5OEo0b1h1OXhJZloxeFdYcmF5OWFYM1hNU3o1Zi9sK3l0bHdwcVBWM20wVGQ4RWw4TEswcGY4ZmpLS0s2Q241NnJGMmE2bk1MUzc2MStPNzFVbnlueHdDZkIvellsSU5aTmc2QVg2VVFNT2hhWVgyRHg1djNsMis0NXgzR1dXTUN0ankwZXNvYmFwRWFiYTNZVjU4Rmx1NnhGelBNUWFvWENCTXhNc1g2UW8zM2NqR0wwTWZFakJqbnV1S3pGWFlsdWhDditqanVDeVZlVHFYS1IzSHdyaFNIbXhXdStuV3U1N0UwanNjK05Kb3laa3VFVEt6QnZqbkl0SVdWNHFtVVN5MW9MVmVpZnhLNFgyVjRDUjB2Qk40Rjd1NTVWOHVWMkV6bWNEbXBRenFOaFh2ZWxaL2xzRGpZbVdFQ3RoeG9kNUxFUVpvcDlMN3NLZlpOdnRlSmFieVFZV1lmZmhid0VkM2RSZXlMc3RLR2xJQ3FzdzVUOGthMHZDUnA0M3A4dlloZmlpZUpTTGhTSFByRXE2Q3ZNZk9WUURTT3krbDEvQnluWWxxUzhhalQ5MzE4VXhIekVVdmVseDJkdXNOVHBJakg3NUZjaVI5RytBMitmOUxCTGlGL0Nid2MrTWZsN2tMWXFlNHYzNzdIZWhPa1hQbTVKbDVuZ0FuWTJlT2dqSC9SSHEvU1d1ckdxTzRaQXJpRGdib1BMd0ZmRG16TWJuM3B0SGxKaXhjUks4WjgrVHptUzRyMkhoTGlYa2V1SE9QVkVpL2dSUEd1bWQ3ank0YXdFRFBYUFhaSklpRnV5NHZsdDVlNGpXNmtteUxtdXgwZitUZzgrSzhBOXhNTXEzYm1OZUJQS1FTc0kreFVBNXNyRjMwbm5SNVZsWVB5UGpQeE9pUFdwci9FT0ExOEpUS3VIWEF2NW9oaXNualZOeGF5dmhQNG80VWMxWHo1Wk9BZjVZY2Q4WEpkNnl2RnZ0eUVBY3N1dWcyZEdrdUZLaEhGaE1IQUxscEFwK0V1YW54Mi9mOGxXZVVvZmxmSlRCVExVK0orMXdqdTBkWmdiVjFsUkZmWDd6M21Cd1AvZk40SHV3Q2VuemUxMWF2ZGlQVWNiQ25Xck5ZYkxsdXE2M0tQK1h5dkdtZUlXV0JMZ3JiQWZLNGFrSHJMdnV3aE5nY3UxNklvbi8zbndMc1hlQ3p6WUJ0NEVzMjBkR2xZSlltaGNCOFNHM0ZmV21DeVNLYmhMam5ab3hpazdMckpFRW00VHV0WVc4ai9hMWxsaFk5UmJhT3NpOHI2a211bk5kYXBUZ0xTQ1IzSkNuc2l1R2N6ckRxSmZ3emNTU2hXVERjR1ZzVENmRmxlcWxpanJDOTVqOFhCbGdPendNNmU1SmRYc1lnNjZLNVRlbHZKRzMzeEx3ZndHd3M4bUhueENjQWp5MTIxOVhWTTEvcEtBa2F3dE9vU1VXSjlTRVY2UGN0eXkyMTRKdUtsNmJIR1pEemFrVmloUGxoajZSejRZR0VtVjZvU2RHMkY2VW9qZlZPeGVBaS94V01XY2NCejVOM0FIM1ozYXhHYmxvM1l2TmNrRGxaWllHYU5uUUVtWUV1QXVoazZzekNUM1lkOTR0WEtQRXczMHo2NFAxdmt3Y3lCZGVBemdIUHR4SW5rUnFOYk1pcE5qZUp5VVY0dFhucCtyNko2ZXl2bWRWcXV3cFBTNDFiVUluWWpMb1VydFhJcDZsSlp1OFJoQTVUem5JbUlGZUlGc0EzK3N4ZHhzSFBraU00Y1ovVTlrZ1RNMFhUVlMzTEhobnBkeTlOaDRuVkdtSUNkTGVuaUY1ZEV2RG5xS2VhbmlWZHYvT3NWd09zV2RUUno0bjRFQVZNVXlRdksrcXFuU2tuVjVuM1gyaWltUm5FNVRiN1phQytEY05YMGlSaEJ5UFM4WjJrc25Nc3h3U1RtUHJ0UzAvbWd2NDVpT2llUEovdzJRK0t2Q0owNCt1TmdLV21xRlFlam0vQ1NyREJuY2JBenh3VHNES2g2Y01pTlVQbllVeTFFMnRsamhmdXdMLzcxY3VCdEN6aW1lZkxQZ0x2bGgzV2ozWXA5ZFN3d1NwZGhKMm5CNThLODlWaXFwUlF2WVlKTE1RM20xcGFZejJQaVd1ZGx6MVVGaSttS1dPSXk4T21uZW5UejUrK0IxK2FIK2g2cDQyQXBadWh5cDFGYlpaTE1rVnoxNWtJOGUwekF6aDd0UG5SVUEwOTlLVng5UWZlK2dhajhIMEtMTkJTMmdTZlFTZDZvTFk1VzhvYTJ3TVRxcUJ2cGxHM29KalRVeTA3TEVsTkxZWm02N2x4b2hhajdyb0QxWlNUaXdmOHp3cXdBUStIMXdDdTd1eWZGd2VyeWJXbE9NS29PbzZNbzZndWt6cW14SUV6QXpwYmtQblIwQ3ZocUs2dDNFQ285QTVjQnR3L3VMeGR4RkhQa0h3RVB5UThMSzRNWTg2RTdXYVdrejJzTFRGeGtSWEZlcHhwb3QyUUpHemRKK3Y2K25BdnRCbUdtNWlUd3JoVDRYZGVlVjZ4dk1rd1BvYWp5aHk3a3NPYkRFZkNTY2xjcmZ0Vks1dEN4WjEyRlk1MmNjR1ZXMkJsakFuYkcrUGJOSkRkSzdVS2N0UlNRZzFEMGIyZ0pIUDhFdUsxdGZXbExRMXRmTFF0c3orVWtoY0xDOEJNeTdZWWtYaTFYWXR5blJmNlFJTnk2UWtrNlR6Nk9oYU5oZ2JtdWtBRndkL0FmdFpBam5COHZJbmtoSnNYQk9pTG1HeDFIVCs5MFJTWmVaNEFKMk5sUnV4MEs4Zko1TE0rRzY3ZkFXbU5TRXE5bldEWHNMZ0lmVSs3U2pYVHRJcXZqWDRVTDBWZnVNWlcwMGFxd01TanhFbHhYNkpNclVjWEU5R0JuZmE3RU91MklQTEdNRm8xRURvQlBKUGpXaHNKZkFnZHQ4ZEpMMFhHa1lZRlJkUnlWQzlFNEkwekFGa3p0Y2xEdXczUWorYktHWFIwSDY4eTYzSmZBOGVMVFA1eTU4djdBby9MRFZweEh1OGkwZ0lrTFVUZk9ldUxIWkgzNWZoZlprT216d3ZxU1hjU2xLT2RvVWlMSGNmVi9lQXp3RDA3L21PYkcyNERYNUllVHJMQlV3aTBtY3RTdWZGMzF4b0ZWNURoclRNRE9odUtDcnkwd3lwdWx2bm42NGwvTkJJNGg4YkdFOGhDS1Z2SkdVWG1lM0Nqcnhya1k2Nld0TDljUXJpRmFYMExsU29TR0ZlWktkNnNXTFcxOXRkeUlUYUhmb1dNcEx6V0hOTzhGUjVtRVVkeDdQdDk3SGZIeWFuRmx4OUdFYk1HWWdKMHRoZVhsMnY3NGpvaXAxem0xTGo0WGNIKzFrRU9ZSDU5RWtYMVl1Szk4Ti81VlcyQmF1SFNqWEZ0ZVk3TytPaUttckRDWmZ1VUdRY2dMMGZlNUlrbHh2bERWK0dtNEVUMzRqMTNjNGQweW51QkdWQ1N4OGYwZHh5SWU1c3JpdjBYaVZPVkdOSXRzZ1ppQW5SM3A0dGZ1Q01xYnBDVmlrcVU0TVgzK25jQ2JGM01jYytHOWdBL0tEL3RpTzdWRlVZdFhLNTR6dXRqWEZKSXJVVnV0THBhYmNsMHJiTCtLRmNwNTB5N0UrdmZnWWNEdGl6cWlPZkEzN2QyZEdCaU50SG9vWm9kSUhVMXgvWnRnblIwbVlNdEJIVWpXcGFSbWNSM1duOFBmQSs5YTFMZWZBNDhDN2xudXF0MkhTY0I4T3dhbXJZZ2luaE5kYVdudUxFWmtmVlhvWTlNQ3BCTTZXdTdFZE01OE5SYXNUL2pmRDNqb1lvNXBMcndaZUhmLy9hTHZ2ejRyTEQzMkZGVTR6SVY0aHBpQW5TRzY5Nllzc2I2Q3ZxM1UrZDRNeERjUTB1aUh3c09CbmE2b2lQdlFVNDV2a3RpV0ZxeFdNa0xLcVBOMFpsVWVsZlhsdWxaU2NpUFNyVjZTUkV6Y2h5NmZ0L3JjTlFYL052QWZlTXJITkUvZUFid2xQMndKVDlOOTczb3EzOFJGRDJZMnpnQVRzTE9oMHhPTVlsWllZSlEzazk3WGw0R1llQ09oUlJvQ1d3U1hWS1Mya21vWFlrcmk4S1VWVnJqQVhLeTI0ZWpQcGhzcEtSN21sUVhyVk9WNnAwVE1SeUZUNXpMRndPaXZpK2dCSHNGd1d1NjNVUWlZVUZ0Z2Zja2NmWjNIZEErYUcvRnNNQUU3UTZUM3BrUklSdmkzWW1EVFNrY1ZRamFrQXI2M0F4L1MzVDFKdkFvclFtLzdNbVZlc3ZFa3ZUdzF2bU95dm9SV01vZEs2RWdXck84NWQ1UVdXRXZFQ2o0TU9IZWFCelJIcnRFYkUyNWxJdmE1RXRPa2xyNi84MmhDdGtCTXdCWkk2NEwzMWMzanl4dW8wK3VqWDd3U0J4VGpYcGFlTzRBSGxydFNRK3k2SWxhNEVhbGlYcTZNNFNUM0llT05lL1ZSdXhGbHJjOVI1L3hSeGNEb0RqMUk1L0NEZ0VzTE81eGI1elhsdzNUUGVEb1dXRjhIY3QyWDk2anp0R3NpR292QkJPd00wZkV2eXB1Z0UxQjJwZHVpTi9zUWNOZkJ2WFpCeHpBUEhrSTR5QW9kLzJwWllESVc3RkF2WG9uWENyb1BCYTgyZENLTWlMcFVyZGNkZ1U3OGkzYnlTK0lTblk3SFV2TXFPajkreTNWWWR5RHJBY3pUN2o4ZzM5dkc2V0lDZG5ZazYwbDZjYjU5SXhXV21aL0JBdHVqNmU5ZldoNU8vL2d2MnRsMFdzUTZEYS9yV2cvNmMwZnBQaFFtSEs4SVdlb0krUEs4TmNXTC9CdDBQdGVEVjdITHBlY053STNKYnI5QzBGekRDMUxGcWZWOTIvbzg0NVF4QVRzYk9oZThFcTllRVhPVHhTdnQyMk5ZYzRCOWFONXNaaUZTV21BdE4yS3I0VDMyMFlKekRldGhWWER4SFBqK2prRFJHWERUa3pnRUQ4M1k1ZElTQmF5bXZuKzBlN0RYaFM5dXgycHRMQmdUc0RORStjNlRHNUhTUlZGVTU2aDg5YjN1aTNjUzB2S0dnQVB1MzkwOXlRS3IzWWdwcGlPTnIxZld3eXFMRjJwUU0xVThESldWcUJmbGdxMEhNamZQNHdNV2NSUno0azBVbWJtdEJLZytkMklkZjA3V1YvVXZMQTYyWUV6QWxvTjBJNmw0V0ozVTBVbmljRDFDTnFRTXhQc0F0NVc3NmdTT1ZneXNzTVI4bnFCU3V3NlB4ZnJRbnoxbTk2SFFFdTNXdWZSZEFXdWQ0MVlNTVgzMmV4Tm1haDRDVnduandYcG9pVmlmbUJYV2wydUxtYkVBVE1ET0NGL2RBTW9WMFJFdTE3MjVKdmIwM25qNlgzOXV2Qjl3b2JzN3hWZ280ekMxQzFGbkcwcmEvSkUwMW8yNDJxcVJ6a04wcFlxdzF4WnRPcThxZmxoVTdlK3paTzhHM0hzaGgzTHJIQkdtR0txbzc2VkpsbGpSdVhSVDdrUGo5REVCTzN0Uy9NdVZyb2xPNEpneUJ0Wk15NGRoSlhEY2wwTEE2aGhMNFVaMFUwU01uRFdYM0llcllIRk5RNTJIVmxabklWNithM2tkcS9kMVJPeHV3TDBXZFNDM2lLZC9mcndKbmNTT2tEWGlYaVppWjRRSjJPTHA2N1VsSWZOMEt0UFh5UnV0ejBpUEo3aEpsbzczSWRUb1VkUlppRW5BZkxmUkxZUUxOV2JKMDdIQVZocDFQbzZWaUJWQzVodm5rMFlkUlAzNEluQ1BSUjNFSEhqbjVLZjdSS3QySzNaY2h4NUw1RGdMVE1ET0VPMDZySlk2WWFNVFFLWVVzZUxHR1pLQTNaUGtLcHlVZ1ZndmtvRFFFVEdWcExEcUNSeENjUTVjMXkzYnNzYmtITmRwOUozenVVNklndzJGdDdkMzk5MkhMU0VyMHVmN3ZDREdZakFCT3lOY0tUN3BabkhadDk2NmNhYUtGd3hId0J5OWpWOGR1K3E0dmNSYWNCVHV4VHBtVTN6bUtyc1RLeGRpczJOUXVXaUx6Z0E5blF3UGZrZ0NWdDBiZmVKVGR4YnJZU3gxQjNPV3p6Uk9BUk93QmRIcXFmbUdpSGs2UlgzN1hJalVueWZQdmZ0VWptRCs3TkJ4UCtsR3N1TkNwTElZWEhZcnByZ1hVYWdxRitMSzBiSStYWFZPWFhVK2ZiL3JzUDVkQ3Q3cmxJN2hOSmd3UG5LcUJlWjdPcEVleTBJOEswekF6aGdKSHJ2Sk4weGZObUtIWFlZekJteUhrQVRRb0M2K1c0dlhzWWlYcXl3STVmWktuOFVLQzVtZ01oSFRlZlZkNjZ0dm1TaGlkNmNUeDF4YTdtcnZibnBEYUF0V2J6a3BFN0hGWXdKMlJualZlMVByaVRkUVpjVTFyYkRyTktzTkxDVTdkTWFBMWJUaU5YcCtxOExOcGEwdXQrSXVRMFhUOWVkeXdvdDBCblNacWFteEwvMzRIc0RtYVgzN09STTdkMzJ1UC8xY3IyZzE3bFh0VFVtZlowa2RwNDhKMk9McGlGRERzdXIwK21qY05IUnZPdllZam9CdDB4U3dPbGJUY1NGV3JpKzl2Nit4WFhtVW9Hc1hxNjVTcjZlZjBaYlgxTEZnZDJjNEFpYWw5M3RJOTVlYjRnMVJyekgzNFJsaUFuYjJUT3I1MVRmVXBQZ1hNQ3dMYkp0aU9vNitMTVJheEZKRDI3T3NmUHhyQ29VcjBUVTZDZFg1MVM3SDVqbTl6SEJjaUFlRVRsNUZwME5ZV1ZsTmQyS1BGOFZZSUNaZ1MwQXJtYU5lZXR5SEhYWVpqb0J0MHBrUXNaWEEwWnZFUVVPNDZINmVDVmtYUFNhc3R6UGdTZ0ZMNzYwZWM0SG1kRGhMU1NWZ2s3d1pNM2xEWFAvN2pRVmdBblpHdUs3cm9iN3dXNVBrVFhzOEtCZmlCaUVPVmxFM2xzazE2Q1pZWGJWRllmR3ZMc295YlZsZW5ZNkN6L3NteHNIT01Td0JtNURrVkloUXc3WGZXdlQ3akFWakFuYjJkSUsvc3JTQ3hlcEZ6WnZta0dDYURJR3RzT3ByR0R2WmNpMXJ3WlhQYWZkWXdZb0xXcEZCNkpnY1k2eVdQaEZMNS9NQ3cybElaQnFEQ2ZTNUVadmlaVzdEczJVbzE5Mm91WWtnY08vcmp4aE9TMzF1OHRNdGQyS25nZFh4bk9wOXJjOWFhU29ScjRXcDdoajR4bXVhNTNpSDRWaGdja0FWVXowZDA3d2hEWStLc1FCTXdKYUhPcXRwbXR1aXlaQUVyQ2Z3UHlrTzFtcFFpeW52cFpHMkpJNGtXTDdlVjF0ZkxkZXNMeTJ3U1IwRUQvaWhOQ1FTUUczUkVLQ1p2Q0dOeDhhQ0dNcDFaOHpJZ0FXczFValdJdGFKMjdqdWMxcThMSW1qVGN1ZE9HMEE4OFJ6T1pRc1JNbittY0NKeE1pc3JyUEZCR3hrREZqQWF2cGNpTnJhU2k1RVIwZjhqQW9SZGkzNk9sSERkY1dyemtMc1BjY0RkeUhXOUhvL0dsNFM0d3d4QVJzWjB2b01nUmthdmFZbDVzckcxMWNOczlGbGtuVXE1N053eGRLMndLRDdmbUE0RnRna0Y2SXhQRXpBakdXanppS3NYVmM2aGxQdkE0S1FtWmhOSkFtK3VCQWJydGhKNHRYQlRCSGpMREFCTTVhVlRyTEFoRVoyMHZ1TUJsV3lTMnQ4Mk16aVpSaG5oUW1Zc2N6Y1RLTnBSVlM3Tk9NMXZpSCtMZXRXUDI1bE5ockdXVEVVMTdXeHV0eFVZK21yUVBzS3Q3aTlZdTZDMlBjOVovVWtqYVhIQk14WWRpWlpVMFYybUloV1l4emRLdFBKb0NPZnE1TmlnbVlzRlNaZ3hqTFRhbU9ib3VWN0JweTY0Q1pmWmJlWG5Jdk9yTUsrZlE2QllNSDJmSlpoTEEwbVlHZUV0aGJxeHRjM0d1bXovYlpuUXFmYWdTL1B5VnA4ckJ2bGRXRGQ1UlJ3UjFsdWF1VlFybFNaMVZ2TzF6cnEzUGxTNk15Q3pVeThSN1dyK2lhdFd1TVdNQUZiSEhWWkdpQTNNTFhsUUx0Y3pVcmNINVZnNi9PUnJJallFSzg3V1BlaE1kNXdVY0I4S0krRTc1OFNaSldRYTY0NFo0VHp0SUU2aDA1MUNpaXZ0Mm1XMlJpWmRBKzJ2QUJBTi9iSzZsNTNDOEVFN0pScDNQQzZ4OWJyeXFtc2pGYURQbFpheDFyUGhpdU43MFpjYjhidFRjSTRWZWRENGZHNk1PM0tvUnBUc2JhS2N3WnNWdWR5bmNic3czUi9sN0hTT1ZZUjlaNTdWSGNRT3AxUHVmOVgxUU53MnBpQW5SSjlWa1REVlZQRUpxcDF5NlhUK3Z5eDBHZDV5WGxZajhzR3VSSGVkTERsd3dUUE1wWkpyTExrUGx6VmpMckt1bDl6V2FpMmdlMTQ3amJKZ2lZaUprTFc1eFVZM2ZVM3hmSjNQZmZvV3ZWOHNzejBSNXVRblE0bVlIT21jUlBJT29tVnkvRUhpZG1JQzBkY083b1g3T2oyaER1dW5SRVF2WDVwdXlWYzY0U0dkaXN1Mnc1MlBCdzZ1S0ZpWWpJdDJyR3pHRml5NXNuWDNDYmgzRzE3MklubmNKdDhYamNwejNtekU4WDRyajlaMTVhLzNpN3VVOVZaV25maG1sdVBGNXFuVzlYTmhHek9tSUROaVNuQ2xSb1ExN1VpeFBXMXFYdkNydXZTYVRVZ05CNFBuVllEc3U3eWVaSkdkb2ZROEI0QVIxR2s1SnpkQUk2Y3F1KzNxaFlZbFV1YUhDL2NqcUoxM29lcDJYYmlra1FzbnMrNk16VkdGM2JybnFvN1VPbWVWUGVwM0xPSGhPdE9paUxMeGVaY093WnJRalluVE1CdWtXbkNSWGJkSkl1TGVCTkU5ODJXaTQyR3o3M2ZGSmRnc2t1bi9yOWpvV045eGZPaHhlc2NvZUdRWHU1YVBIL2J3QTBYUlUyZVg5V0dRcTVQaWRINGZQM0p1VG9QWENSTXJDeENKdGRqMzdVM0ptYXgvT3Q0NnlibGZadXVONmMrSjFwa2p2YThhbUJDZHN1WWdOMGtzd3FYV25SRHZCSEZLN2x4Q011Mmk3RUpKV1oxSXpLeEord1pUclZ0NVYrUlJxUnBmWkViRGhHdjg1VGlKVzZ4ZzdqL2hnOFdXS2RpL1FxU1lqTHhtcTNQNTNsS0VUdFBGakY5L1UxMFl3L2xtcHN3M1ZEZnRWZWNMM1YveW4xN0dNVkxNbC9sL1RmaStvaitPZFlFRTdLYnhBVHNKcGdRN08wSVYrejVhdUhhOUdIWklyakF6ams0NStHOGkrNGNWN3B6cE1jM1RjUWM4UTEzQUx1bmVRTG1nQWN1bDd0cUVkT05pRFMyMndRcjRRYTV6VXd4SFlKNFNmeExMREJKN0ZqSmhrRVNPRlFpaDQ0bGJwSTdCQ0ppNXdubldHSmljdTIxTWhMVGZYQjdYSmFkZTFBMGV0TTZUdm84YWJmMU9RY0gwZks2RWErejVLSjFjT2pESXM4ZnVjbVRoU0xyNk81ZHlXdjFaakFCT3dIVEVqU2s5eFVGUytKZDBvUGRkTmxucmhNUXp2dlE4NzJnMXRLSTdCQWFrcm9uM092S2VTVHdQTEx2WWxrNUJ1N2UzZDJNUGFBYUVPbnR4dGRyOGRvbldsOVU4UzlvRnE1ZEZkSjE2cW80R1BuY2FSRzdFRHRTZlZaWTAvci9ZVUtuYVptdk9VODRvQWYwdjZUdjJwTnpkQzdlbXdjK1htZnh1dEloZ2cwUEJ5NnNkWWNxQ1puUENVYkp4YTIvcGxsanMyTUNOaU9UckM3ZmNCVXE4Wko0Vm9wM3hlRDVqaThiamtzT0x2bHVQS0lsWUwwOTRkdUFSNXpHQ1RnOVhFTmN4TzJWR2dYQ2VUaFdycG8xdFgrZjRENjhFWmRqMysrdVdVVzBGU2JYajhSWHhiTGRKbGdXT3Fsam16ell1VFVtVVQ3Y1BYUXh4ekUzMUFVeHlmTHZDQmp4T290Q0pPL1hNZG85Qi9zK3ZPN0E1K3Z5MEdYUHdScTVJOVpLOURCcmJFWk13R2JBZDRXaXVOaWxvVldpcFFPK1d5amg4dmxta0JzaXVXK2llRjJtRkRIdHlwbllFM2JMM1FHZWhjSUNVK0pWM09ES2l0Z2lXMTdKK2lKbmc2MXk3S3ZBMFJtRHFCdG9hYVIxUExhd3dQejBiTmhCNGNxTzB6VEx2M1pkKy9oR2ZSMXVFWXpRYlE5N3dINUR5QTVkZEN1U0xUS2Q2TkcweGt6RStqRUJtOENzVnBlTHdpS2k1VXJoMm00SWw0aVhGckFMQk9HU1JRZlV4UXFUbnZBWU04SmFQV0ZQZGhQcTE0a0ZJWEdKRlBjaXgrbGJjMXV0TEw2NmZ1bU9yU3ZHMTZudG1XSmdJeUJkZDhyeUYyR1g2MHJYMkpSck1Jay80VnJjSlFqWVhpVms0aVU0aUs3RmxPZ1IzWkhpZGVoWVkrWlM3TWNFckljSjR0Vm5kVW1NUzF5RXJSNnRpRll0WU9mSWdxWFhPcTI1N2duTFpLU0RGekxWRzlZTm94WXdUWjNZSWIxaW5lM1ZESkN2TUxYbm9IYVYxZGJZcG5vOE1RdHhKRlkveEZnV1FUQzA1VjhuWGtEM0dwVDdlNWNzWUdrN0N0a2VXY2oyWGVqd0hoS3NNamZGR2pPWFlnOG1ZQTJtdVF4OU5aNkxPS2FMM0h1dEJlc2t5M2xLb1pQZThDeURtc2VDSE5kYVk3OTI4V3hoNGpVcnM0aVlUanJhcVBhUDBlclgxSjBuT1FmNmV0S1dsNDRmN2hMdTE5MFpsbFN5eXdWcmJKMG9aTEhkT1ZJbjJGeUtVekFCcStnUnIxVDN6TVdxRU9UQnlKdmFSZWhpbWkybGV6QnR1NURKbEt3d2w1TTV0R0RKT3NXL1hMYSttaUkyZ3A2d29JOWpyZG92bHU4UjRUZW9oVXYza3UwbWIxTTMxTFdRU1JidHBLSytvN2pXR3BZLzVHdE9ZcWhReHNxMDlTWDFKT1dlM3lVa2NlejZzSDA5THJvanV1VnlOdkllS2l6Z3NsdlJ4V3RjWElyYWRXa2lwakFCVXpURUt4WHBWRGUxSkdqVTlmaFNtcTBMbVZ3NnRwWEdlUG5TdXBMM2JWTUtsbzQvaUhoSmozZzBEWWhHTlNieFlhSm9PRlVDUjB1NFd1SmxOM3FnZG9uTHVpTmt2aXRzZGZ4TTNqeTY2eEFWSTB5S2tmZlgxdjhXb2ZPNlR4Q2pjd1NYNFM2d3F6cXIxOGxpVnhRcGNQbSszcGZ6N25JODdFaXBxMXpuSm1JS0U3Q0k3OTdVcWNGMEZOTjNkT3J4RVMyc0tGSXlqdXVDV2tUUUN2R2lLMWg2NExLdWxUaHhFUE5ZR3BJSklnYjV1Q1ZXMGVzdXRCdDdNaE5jNUZyTStoWjV3OWl1dWFibHI4U3JGakNkK0NKZUV5MWtZb1hwZTEzRVMxdGhuVW83UGlSN3BIbkc0cGM3SnNlRndVUU1NQUVEK3NVTFZYVWFsVjNvS2NhRm5JOVdsNGlWWkJBV0FrWlh2Q2FLRnQzNHc2akZTK2dSTWJtUHRWaXQwV04xVlc0Zm82UytYbHJYZnQ5ajJSanJOVGZKZmEwRnJFNnpQeVNJanJRTGU1VEpXN1dYWlpzY2Z0QldtSVFwcFBPc0JWUml2WnFWRjdHVkY3QWU4VXJKR3NwOUo4VjI1WUk4VDFsRlE2ZkFheEZySldYb3NWMnRlWmlteFI5RzFZRFVUTERFbEVmSDNJVnpvTSt0MkZyTGcxRmZlMHh3WDlNVnNDUEMvWHVEVXNqMDRQQmljYkVkOGVyZTk1VVY1aHNkVmFXdUltSVdFMlBGQmF3dllRTWxYdVE0bEZUUGtJUU1iWEZkb2kxZ0VnZHJEUTZkUmJpMFMwZSszMmg3d2hxWGI5dytsNkk4bm5ianJ1U04zV0RhdGRKM2Z1WEJhSzgxbU5wcDBnSW1ycngxNHZ4ZjVQdTRkaXQyeHRYNWZxOUxjZjlySzB4OVB5MWk4bDFXV3NSV1ZzRDZFamFveE12blFLMjRERnZDZFVsdFgzUTVEbGJYTkt3dlhKa1FiNXExTlhvM1RoOHpDdG1rRzNjbHp0TXQwbnVPVnVVNmc0a2lCdGxsM1JFeUY4cEthWXZza083Z2NPa0k2M24vZEVwOWtmbnBHeFlZS2l2U0tmR2E2MGtZR0NzcllCVXA1dFVTTDNMRmVGMHRRMFRyTXBVRjVydVdWMTBPS2wyd2ZySm9yYXh3MWRUSDdjc2JkeVhQeVdtd3F0ZVhVSFdZV3U1cldVVEl2QTlpc3U1QzFtQm53bHExRkpQV3FtWGRseGFZZzFSOHVmVWR2ZnB5TWxac0phMndsUlN3UnR4TGo4TklKYUhvaXBjSTFXWGdzZ3ZGZDJzQmE0bFhQZE55TFZ4OUpYbzZicHdENEIzQXU0SDNBRytKajk5SlRvRmFrU3Q0cFJ0YTQrWlpJN3RUN2dHOEYzQXZ3azE4ZTl5M1Buc2NOb21aenhhWkZxUStNU3NFVEhsaVV1ZlZxMy9tc3ZWRnRSOVdXTVJXVHNBbWlKY1dMcWxodUJQRksxbGREaTVIMFpKMXFpTHZ5blQ1bEcyRWNobjZzcGMxazNDOUR0d2ZBeThHL2haNEZmQjY0TTU1bnh6RFdHSGVHM2cvNFA3QVE0QkhnUHZId0IzOWJrWFpwL1ZrVFhWTzF4dUxGcXdrWEw0YlFnQ0tqRnBQSGx5dDYzeldsdUpLaWRoS0NWaFB4bUdLZTBHYWNESk5XNi9jaGlKZXR4R0U2emFpR3pFS25NUzkrcEkxSnFiRHF6WDd3S3ZCUFI5NEx2QTNCQXZyY1A2bnhEQ015TnZpOHFmeDhRNWhjdGhIZ0hzODhGamdmdURYeW51Mk5vaGtMUjNVZXBGTVF4bWkwMm9UTko2dVlNa0VyYkpBV1lWbVpWZ3BBYXRJRjVncjZ4cW1tWkpSTVM4bFhyY1IzSWRpZ2RXVjQ2Zk5wTnliVmZnZTRIbmdmZ2w0UG5EMTlJN2RNSXdwN0FGdmlNdnpDQmJhSjRIN0RPQ1R3VytIbDlXQzB4Zkxib2xaMFNiRW1GZFR3SWdUWU1aNG0vZktHblA1ZGZMZWxiSENWa2JBZXF5djFsZ3ZQVU90Q0ZoeUc4YmxOcCtUT1BSWUx6MUlVVDV6NmxpdXQ0RDdhZUJIQ1M3Q2VyU2lZUmhuejl1QVp3RS9EendNM0pPQVR3WHVVVnBkSWhxZE1XUlJvSHBqMzFGMEpJSEVVMVhEOTkzeWFUS3JzeGF5bFlxSHJZU0F0Y1JMSjIxUTFqYXJ4VXN5RFM4RHQwWExTNmZOdDJKZWs4by95ZmZnUGVDZUNmd1E4UExUT25qRE1PYktIc0hOK0VYQXc0RW5nL3M4WUxPMGdtcDNvbVFVOWxsb1FDRmUzcFdpZFV3dVhuMUVudEc1bm9YQjVZOGFQeXNoWUJYSm5QY04xeUZxb0xJTEtmR1NwSEdaYnRaaFBjNnJWZHVzYzZFZUE3OEQ3aW5BLzE3TU1SdUdjUXE4QlBnUzRPZUFid0gzajdwSkZURGoyRTZGcHkxZVJ5NElsNTZGSVZsaDFlSllBU3RzOUFMVzV6cEVaUjY2bkRLL1F5NFBkZEhuSkEwUkxSRXU3VGFzeGF2bE5wVC96NnZBZlNmd1RDd3B3ekRHd0JId0c4QUxnQzhEOXg5SW1ZdTFOWVo2M05yVzhTNFJNS21CZUFPNDRlTUVyaTVzSjB2TVpUZmpTcmtTUnk5Z2tVbXV3elJnMmNYcFVDamRoNWRRcWZMMGk1ZE8yT2o0dHdGK0hkelhBQzlid0FFYmhyRllyZ0wvRGZnajRLbmdQcUpyamVrQ3dicnRyYTBuYlgwbDhYSlp3R29ocStOak9pTnkxSXhhd0JvWlBUTFh6aHJkV1ZWMW5VTmQwL0FTd1Jxcnhhc3VEZFU3MmVRdThGM2d2cDB3TVpCaEdPUGxoY0RqZ0c4SDkwWGcxOE51YVl2NjB1V2htN3lSeElzZ1ZJZVVTeEl5c251eEdROGJxeFUyYWdHTEZOWVhjZkFnS3ZibDFHU1V0R3NkWG5CNWtISmRVWDVTekl0M2dQc3E0Q2NYZGJTR1ladzU3d0MrQW5ocDdMaWVhMXRqbnR3R0Z4WVlaZHlySlY2SEJLdnNVSXNZWlpiaTZLMncwUXBZWlgwVjR6QjhaWDM1S25tRDdwUW85U0RsT3ViVkZLL1hnZnRDNFBkTzhUZ053MWhPRG9DbkVkTHZud2J1am42WDRqbzk0a1ZidkE3aWN1akRPbGxwTG91WUxqNE1JN1hDUml0Z0VXMTl5VmlNb21RVTNYRmZyWWtwV3hYbCs0VExBYndjM0JkaldZYUdzZXI4REhBWDhDUGc3bG1LaW82SjRYTEZqWllMVVF2WFBuRGc0TUNIOWFGWGxsaVYwQ0hDT0VyV3ByOWtlRFNzcjA3cVBHcU9MN0wxcFdkVzF0T2hGQWticmpGL2ovby92QXJjWjJIaVpSaEc0RmVCSnhKQ0NuRlgwUzdSOVF6cFlUM25DR0dNWXBaMzhRcjUyTEYyNVJqVU5LZVlXa2JIS0FVczByUyt5R256cWVxR1UrNURYMTBrZEJNMkpnNVNmaE80ZjBtb1gyZ1loaUg4TnZEbHdOVUpRM3ZvaXRnMldjUjBKN3ZWdVo0VWt3ZWFpVzJEWm5RdXhGYm1JWTJCeXk0TG1DUnYxSXUrTVBURjBSdnplaGU0THdIKzRIUVAwVENNZ2ZMemhDbGIvanVoZ1lsSUd3VTVzZU9ZME9hSUcxSGlYZnMrdUJCM0NVVkJaTm4zc08vQ3NLQWJQbVlsMG9pRm5lb0JMcGpSVzJDMTlVVWUreVh1dzhLRkdKZHpyakZJMlpYaVZVeDdjQVI4STJGQW8yRVlSaC9QQUw2dmJZVTV5bWxYNmppOXRGTzZ2U282MnI2Y3VxbFo1WDVNVnRoWUJVeGZITnI2V2lkYVg1UVhoVGJSenhHc01tMTVGYjVsR3RiWGo0RDd3Y1VjbTJFWUErWVkrR1pDWVlPNHF4YXhvdEFDWlhzbENXZm5YZGwyU1Z1MVJaenhQU2FzU1NkK2xMR3dVUWxZSzNuRGhVWEdmeFdWTjZoNk5hNzBLZXRwVVNhTzlmcHpjTis0Z09NekRHTWM3QUpmRGJ5K1A2a2pqVmRGVGJKTGJwdWs4SUp1cjFKVklOK2VhMngwakVyQUlxM0E2QnJoQjkya2E0RWxONkl2THdRdFhxMjRGd0IzZ25zeVljSkp3ekNNV1hrNThIV0V3RmFrbFRIZEtYbEg3bmpyOXF1d3dNZ3pQOHMwTHFOMEk0NVJ3QVRuVmZVTlZIYVB1QWRkMTRXNDQ3b2xvaWFPOTNvR29mYVpZUmpHU2ZsNTRMa1RzaEpySzR3YzJ0RGl0ZU42eHFtT1BhVitOQUpXdXcrOWNoLzZoamxPQ0hoMkxnVGZ1QWpvQ1lhK0F0eFRGM0JzaG1HTWt4dkFVd2llSExVN2lWaGxoZW5hcmJVN2NkdVZoY1UzQ0xHd05SK1dVUW1YTUJvQmk2UWVoc3NYZ0xnUDAvZ3ZsQ211L01yYUJKODZyOWNCOEMyRW1tZUdZUmczeTh1QTc4NFBPd2tkVGlXZzBXakR5Qm1JdXYzYWpFa2NvM1lqamszQWhPUSsxQWtjY2Z5WGpvRkpIY1JhdkthNkRuOFgzQzh2L0xBTXd4Z2pQMElvL0t0MjZWaFlIUWJSN2tSdGtTWHZVV3p2TnRUN2F6ZmlLQmlqZ0RYZGgxNEZRbjM1Zyt1TG9HVjl5WVdVZnZnYmhCN1Q3bUtQeXpDTWtmSVc0T241WVNzenNUVStyQ05lc1hPKzZWVWJGdHRCVjRkWlR2TjRGc1VvQk14M2YzRElvaU1pVnZkZWlzVjFMYS9lMk5jTHdQMzJhUitVWVJncnhjOEFyeTdiTWxtblRHcktkcXpUbHZrcUJrWk1wM2RtZ1MwOVRtM1VHWWk2QXIwczJ2cVNIMzVTcVNoSCtFeWVUcWk4WVJpR01TL3VCSDY4M05VYUV0UVVNWmM3NHNVa3V5NWFZT1EyY1RUaUJlTVNNTWdpSTRPWEpRYldzcjUwRDJhYTlaWDRhM0IvdUpoak1ReGp4WGdlOE5aR3g1bCtWNklNWEM3V0tPdExGcGVUMjVJVk5uUkJHNXVBNGNzZkthV2hUbkFoZGt4dTJ1V2lITUN2QVc5ZTVBRVpockV5dklUbXVGSnRnVTF5SmFhMlRBMGJrbkZnYXcyeEdyUjR3UWdFckMvK3BjcW9TQkpIU2tOMTVYcURHY1ZyRDl4ekYzTllobUdzS0w5VVB1eTF3cXBPdVY1dnRKSTRvRk1YY2ZBTVhzQWluZmdYRGIreHl6OXUwOXdtQzE3elIzNEY4TWNMT0JqRE1GYVgzd1RlMlcxL09sWllJem10RURIS0RybDJJWTZHc1FpWWtNVExxZDZLTDNzbHJSKzZpSDMxVFVQd200Ukswb1poR0tmRm5ZQ0tzK3MycU5NeFY1VTZ0TXRRdDJlNmxGUXJuWDdRakVuQVhQempYTTVBMUJhWTlodTNoS3RackZjKzI0UDdYNHM0Q3NNd1Zwb2o0SGU2dTNYSHZQWXUxVzFiMGFiNXRuQ053bzA0SmdGcnhjUEVKYWluSjlBL2RpMWV2Zkd2TndDdlh0aVJHSWF4eXZ3MWNEVS9URUxqdStLbFJTd3RUaVZ2cU5kTGdZZEN1SVpza1kxRndPb2ZPUDNJcnF6R29YM0dSWmFPZW4wei92VXk0STBMT1JURE1GYWR2d2RlVys2YUpiVStkZExGQStVcnI5TFlNaEhISW1DZ1hJZzYwMGI5a092a1daVzExVlZrSHZaVmJmNTc0UHBDRHNNd2pGWG5UY0FiZThJWmFxa3RyTFVxZEZKMHlsMi9pQTJXUVF0WS9VTW8wN2kyd3RiVkQxMmIyMzF1UTkxcjRSV25mVENHWVJpUkkrQ1YzZDExKythVWhkVVJMdjBhTjZGelBtUUdMV0NSamorM2NnTktDWlUrNFdyRnZnb093YjNtTkkvQU1BeWo0dS95WnAySnFQZEoxYUZheEp4YXR4aUZtSTFCd0JLTkxKdldEenBKdU9xTEJNRHRFWkk0RE1Nd0ZzWGY5ei9WNmFEWCt5YThabFNNUmNBS3dXbFlZUzNCV3F1ZWJ5WnZBQndBYnozTmIyOFlobEhSU0Jycmk0ZWw3VVlTV3RHbXRiSVFoOHhZQkF5NjFwZXMrekozdE9uZDkza080SkF3dU5Bd0RHTlJ2TDI5dTlWZVRiTEdwcjEzMEl4SndBb2FZOEltbWRXOTFoY0VBYk1NUk1Nd0ZzbDdldmE3Q1cxVkgyT3l1alNqRXJDR2VYeGlFN3Z4bUlQVCticUdZUmk5N0U5L1NXL24zSFhidTFFeUtnRlQ5UG1LSjVyWWZiMlV3OVA0aG9aaEdCT3dqdk4weGlwZ04yTXk5NzdlMytKM01RekRPQ25XN2t4bnRBSVdhWm5TZll0aEdJWXhJTVl1WUlaaEdNWklNUUV6RE1Nd0Jva0ptR0VZaGpGSVRNQU13ekNNUVdJQ1poaUdZUXdTRXpERE1BeGprSmlBR1laaEdJUEVCTXd3RE1NWUpDWmdobUVZeGlBeEFUTU13ekFHaVFtWVlSaUdNVWhNd0F6RE1JeEJZZ0ptR0laaERCSVRNTU13REdPUW1JQVpobUVZZzhRRXpEQU13eGdrSm1DR1lSakdJREVCTXd6RE1BYUpDWmhoR0lZeFNFekFETU13akVGaUFtWVlobUVNRWhNd3d6QU1ZNUNZZ0JtR1lSaUR4QVRNTUF6REdDUW1ZSVpoR01ZZzJUanJMMkFZWTJRdExpNCs5c0J4WEF6RG1BOG1ZSVp4aSt3QUR3TGVEN2d2OEVEZ1hzQkY0QUpCdks0QmR3RnZCRjRKdkI1NE5mQjN3TkhpdjdKaGpBSVRNTU80Q1RhQVJ3S2ZBZnhEZ21pOTd3bmU3OGtDOWlmQXM0R1hZV0ptR0NmQkJNd3dUc0M5Z2NjRFh3ZzhETml1bnZkQm02Yml3TjBmdUQvd1NjQlhBMzhNL0Jqd0c4QTc1dlI5RFdQTW1JQVp4Z3hjQnI0TStCemdFWEdmQnorRFdubHlLRXp2TE41Nkh0ekhBaDhML0cvZ0djQ3pnTU5iK2RLR01YSXNDOUV3SnJBT2ZCcndPOEIzRU1RckNwY1dJRjh0eDJwcFBkYUxmSUNYNVZIQWp3Qy9CVHoyVkkvT01JYU5DWmhoOUhBNzhGUkNmT3JENlFoWExVUmFxR3JSNmxzOHBhakpCM3ZBZnpUd3k4QTNBZWRPOFRnTlk2aVlnQmxHZzRjRHZ3SjhKYkE1V2JocVVUcWFjZWtUc1VMSWJnUC9MY0RQRURJY0RjUElXQXpNTUNvK0NuZ21JY0dpeDFXb3Qvc0VxQkFqY2h6TXpiQVU3L0hnUHczY2ZZRW5BaSs5MVFNMGpKRmdGcGhoS0Q0RitFVTY0dFd5dXNTU3VpR0xDemtYaDhCQlk5bXZIc3RyYjlDMXlwcHV4VWZFN3laSkpJYXg2cGdGWmhpUnh4Q3kvKzRvc3dzbnhicU9IUno1dU8yekNMVVNOYlNGdGFhVzllcXhYalRPZy85QWNEOU5TT1YvK1J5UDNUQ0dpQW1ZWVFBUEphU3QzNGZDNzlkbmVZbHdIZm5TRWt2UDA3V2l0SGl0cS9WR1hPdEYzcmVtM3VPSkl2WmdjRDhCUEE1NDI5elBoR0VNQnhNd1krVzVCL0E5d1Azb2RSdDJFalM4Y2gyU1hZR0ZPOUNwNUE4WHhFZGJYU0plbTNHdEYzbWUrUHBqVkF6TmczOGt1TzhFL2cyd04rZnpZUmhEd1FUTVdIbStuakNBZUpwNE9iamhzMkRwcFlocHhkY2QrMnlGNFV2clM0UnFFOWlxMXNkeHJiK0xpSmxEV1dLZkQrNVBnZStmK3hreGpHRmdBbWFzTkI4SC9MdXdPVW04YmtTWG9SYXNmV0Rmd1lFdkV6UU80K3VPWEJBeCtWeXh2cEo0T2RqeW9SclZOa0VZdDhtaXR4bmZ0NjdXeDZqWTJEcjRid2IzZkVKTlJjTllOVXpBakpYbE12RE5sT1pPcEloNUtmRkt3a1h3M08zNnNKWkZaeGplMEJZWXdYb1M2MnRMaWRkT1hIUkc0cVQ0bWQ3SEhjQTNBbCtNRlFJMlZnOFRNR05sK1R6Q21LOEpya054RzRwNDdRRjdMZ2pYTG5BOUxydHhFWEU3SUNkMVNQeEtCR3lUS0Y0T2Rud29zbkdPYUxWUmlsNGZZb1U1RC80SjRINEtlUDR0blEzREdCNG1ZTVpLY2duNDBuSlhjNXlYaW5tSjFYWGRCOUc2NXVDcUQxTjlpWkR0a1FYc2tISU9TKzArM0FhMm8zaWRKd3RlbjRCSk5xSXNIalhnK1J6d3I0SGZWdi9NTUZZQkV6QmpKWGtjdVRDdjJsMlhoanBDaVZlMHZLNERWd2ppZFFXNFNoQ3hhMlFyVEFUc2lESUdKaGFZdUE3UHhkZUwrN0IyT2VveFk0NVN5TkxyUFBqSGdmc0k0RVZ6T0RlR01SUk13SXlWNUlubHc4NTRyMGJTeGw0VXI2dHh1U3N1V3NSMnliR3dXUVRzUEdYc1MvNS9QZGhaTDgxWTJDYncrWmlBR2F1RkNaaXhjbndZdWJxODJsMWtIcXB4WHBLNHNRZGNkM0F0V2w1M0FlK0pheEd3NjRUTXhIMUM3R3lhZ0luclVLd3Z5TEV5UFZaTWp3M1Q0OElLZCtMSEVHYUZmc090bnlMREdBUW1ZTWJLOFZoQzlsNVVGcDN0VjljNTFNa2J1NFQ0MTFXeWdHa3I3RnAwTWU3NU1xYlZFckF0c3V0UTRsNzZOWHFjV0QzUVdhZlRKL0h5NEI4RTdoOWlBbWFzRGlaZ3hrcXhCZnpqOWxOMXhRMUozaEFMVExJT3I1SGRpRmRrY2QwWW1LVGZGd0xtWU1PSHIxRUlYS3pVb2F0emJGWExJVm5FbXJVV04rT3hQZmNXem85aERBa1RNR09sdUJ2d0VmUzZENzNMUlhtMWdDVUxqRElEOFNwd05ib1ZyeEVTUGZaOVl4eVlneldmTXhGMXhpRms4Ukxoa2hUN25maDUyM0cvV0laU0w3SERZK0tISE43eW1US001Y2NFekZncDdrMllHTEp5SDZiRnErb2I1QmhZYllWSktuM2FkakdCdzZzRURsZG1GYTRSUkV6cUpCNzd2RitMMXc3UkZSbkZLdzJNcG55di90NHBwZjdoaEFIYTc1emZLVE9NcGNVRXpGZ3BIdGovVk8xQ2xCaFlzd0lIc091Q1lPMFIxdnZBZ1l2eEx4K25XWEdWZ0luNFZPSWxZOE4wVlk5OVg2YllweUxCdnVzK2xBUHdPM0hpU3hNd1l4V3dDUzJObGVJRDI3czdhZlNVMDZSb0sweGlYUHMrMWtLa08wRmxzWWhMVW9vQnk4U1hMZ3VlL3V5aXJxTDZuTDVwV3REYkc4Q0RidnJzR01hd01Bdk1XQ251MWQyVk1oQmQ2VUxVeVJ4MUJmb2tXRDRJVVV1d2pzV0ZHUDE3enNkdEgxeCtOMkxjcTFYZHZoWkNQV056eCsySmNpRzY5akVheGlneEFUTldpa3V6dmF5dXlGRllaQzZYbVpKTXd5UEs2dk1pWGtWbEo5ZDlUaEpHK3Baa2NhbTV4VHF1US9XZEhjREZHYytGWVF3ZEV6QmpwZWhwM0gzODAzTE5GWXUyMG5ReWhRaU02NHBNOFhuVjY0L1Y1Mm4zWlJKUStWemZGYTFtRnVLRVl6U00wV0V4TU1OUUxyZ1R2SDZXOXpSRngwMFFIOE13WnNjRXpGZ3BkaWM4NTBwaGF0WWo5STN0T01iTHVWd1ZRMWVPTC81RkhMQ2NudmZkSXIyNjN1R2F2TlkxUHV0bWp0RXd4b1FKbUxGU1RFZ3YxOEpTQzljNnNPSEtrazZwdEpNUEZUYWtUdUdhS3dXc1dFU3dmUDdjb3U2aDY5WStYS2NVemo3ckwrMnpGSHBqVlRBQk0xYUtOM1YzdVdwYkMxaFJsOURId2NZdUREamVWTXVHVjZManM1aTV4bWV1T1NWZXJxeDV1T2xoMDVYMUQzVVIzOXBhNjRpWmJ4K2pZWXdTUytJd1ZvcS9iZTl1Q1UyckxxRk1SQ25WNUxjSjQ3YTJVT256bEJVNGRLSGVOWUxBYlJDc3JTU0s1SEpSV3o3L1B4RTJiWTIxaEN0dEh3R3ZPdkZaTVl4aFlnSm1yQlF2SXpUeTBmV2dweVBSQWxaWGhCZUJrVWtvenhGQ1RlZFFBNDZkcXI3aDgrZUx1R2hYNUtZUHl6WjUyYW1XYlJmRVRGZWtyK2NGSzZ3dkIrNWR3S3ZuY2FJTVl3Q1lnQmtyeGR1QXY2T295S0ZGVEZ0ZjZ3UjMzcGJ2aXRkNXlva3JieERGaTV6eTdsemVKOFY4NjRLOTJ6NS9wbnp1T1VJUjN4MmZyVEx0VXB6b1F2eHpMSW5EV0IxTXdJeVY0ajNBQzRFSHg4b1ljWGZMaFNoeEw3Ryt6dEV1OVZRVTJxWDhUSmw4RWtMc2EwTlpYanNpWGc0dWVMaEFYczdINThSTktRSld4OE02L0VIOE1vYXhDbGdTaDdGU0hBRi9SREVRUzZmTk80TFExUEV2Y2V1ZEo0cU1DK09GTHdJWFhSUWRsT2hFNjJyTHhjV1hsdHdPY0Q2Kzd5TGxPb2xZZkozRXcwVEFhaGRpc3NLdUVzVFpNRllGczhDTWxlTjNnZGNScGxXSjZEaVY5OHFGU0o1ODhoeXFicUZ2MUQ1RVdWOHg3ZjFRdVJEWFl6eExyRG14dWk3NlVPSHFJbmxkaUNGbE1rY3RYbklBN3ErQWw4emxEQm5HTURBQk0xYU9WeE5jYlU4czNZaFF1aEUzQ09JakUwbldWZVpiTlF0MUFvZDh4aEdBejhrYk8yU0w2MUsxWEhSQjBDNHdtd3V4RUxGZkE5NDlsek5rR01QQUJNeFlTWjRPZkE1QkdTampTV3NFVVJNM29pN2tPNjN3YmozUDEyRjhEa0w4YTh2QnVTaFFsd2h6VDE1MmNObUg3VXUrNjQ2VUpJNldlQ1hlRHZ5UFd6d25oakUwVE1DTWxlUlBnZWNEbjVxdHNMcUVsQmF4TGRyVjZmVzZ0cjdXQ2ZOOUhjWHFHL0k1NTRqV2x3aVhpQmNxbmhhVE9Pb3N4R2JzeTRIN1NlRDE4ejlOaHJIVW1JQVpLOGtoOEZUZ28rbFViNjhGVEZlSjd5d3FWZjdZbC9OOXJRTUhNVDRtQXJidGczVjFrV0J0WFVhSkZ5RXVKdGFYaUpkT245Y0pISW5YRWl4S3cxZzFUTUNNbGVVUGdXY0QvN0pyaFlISzBIWGR1YmlTRmVaTFFkTVcyQ1loNVY3UzZDV0I0M3lNYzJueFNnSkd6ajZza3plYXNTOEg3dW4wVmhneGpGRmpBbWFzTEVmQU53TWZDOXkvSzJJaVlENldmbW9KV0cyRlNVS0lESUxlOXcwQjg5MEVqcFo0YmNXa0Q1MDZYOFMvSExnWEFOOHoxN05pR01QQkJNeFlhZDRBZkFQd1l3Uy9uVUpuSkVKWHdKS1FLZkVTQVZ3bmlNOEJwUXR4SnlaeGFBRnJpaGRWZ1dEMWZSSnZCYjRXdUQ2UEUyRVlBOFFFekZoNW5nMDhEUGhQcFJXbXkwdEJHUS9iaXVzamx3WHN1SHJQSmtIQUNndk01eVFPV2VveFh6cHBvNVYxNkFDT3dQMG40RVZ6UGhlR01TUk13SXlWeHdQZkJqd1ErT3orZUZpZDFPRXB4ZXRZdlg2ZElFUWlZQ21KZzF6elVLeXVPbW1qRnE5bTNPdXB3SS9POFJ3WXhoQXhBVE1NUW1YZUx5T294K05uVCtyUWxwY2VFQzFscUE0cEJVelM2RVhFSm9sWGI5TEc5d0gvZVg2SGJoaUR4UVRNTUNKM0FsOUtVSXBQYjQ4UGMrU3E4blV5aDQ4dmNqNEwyQTFLQWRzazEwSVVJWnZtTml6RTZ3ZUFyeUVvbzJHc09sYk0xekFVN3dEK0JmQkQ0V0ZIdkNpbld4R3JLazIzNHJON3NGTW1pakpob3hBdjE3VzhpdGpYQWJodkJyNktrSnR2R0laWllJYlI0UzZDTy9FVmhNU08yOXVWT3VwNEdPcjVEZkkwS3lrelVhWlRJUXRYSytPdzR6WjhJN2l2QTM3cXRBN1lNQWFLQ1poaE5QREFkeEZLVG4wSDhCSGcxc05UMm12aFZma29JYzBsUmtpaFQ1bUpQbGZWRUpkaFBWRmxZWFVkQXM4SDl3M0EvNW43RVJyRzhERVhvbUZNNEFYQUo0SDdzWEszaU14NnJESXZnclZOT1h1elR0U1FWSGs5eDFkdjBzWU5jTjhCUEI0VEw4UG93d1RNTUtad0RmaXpibEpGcW81UmlaaU9pZW1FRGRtdWF4dzJrellPZ0JjRUlUTU1vd2R6SVJyR0RLZ2JSYWZXUzlVTm9udFFoRTFQY0NrdXhEb0pSSytiUlhvM1QrRTRER05NbUlBWnhzblI5UktQS1VzOUhRTnJWUUZnL2ZwYXNKcVZObHdsWm9aaGRERUJNNHdaY1RSbmNKWXFIZkpZRWpaYTJZbmFFdXVNODhMRXl6Qk9oQW1ZWVp3QUpXSzZYaUprSVpQOXZ2MzI1aUxQbVhnWnhna3dBVE9NRTFLSldQVlVSN3pxMTNWRXEvRTVobUhNZ0FtWVlkd0VsVHV4SldUUUhRQmRQKy9VRGhNeHd6Z2hKbUNHY1pOTUViRytmWjM5Smw2R2NYT1lnQm5HTFNEaU0wWElwcjdmTUl5VFl3Sm1HSE9nSVdSVFgyc1l4cTFoQW1ZWWM4VEV5VEFXaDVXU01nekRNQWFKQ1poaEdJWXhTRXpBRE1Nd2pFRmlBbVlZaG1FTUVoTXd3ekFNWTVDWWdCbUdZUmlEeEFUTU1BekRHQ1FtWUlaaEdNWWdNUUV6RE1Nd0Jva0ptR0VZaGpGSVRNQU13ekNNUVdJQ1poaUdZUXdTRXpERE1BeGprSmlBR1laaEdJUEVCTXd3RE1NWUpDWmdobUVZeGlBeEFUTU13ekFHaVFtWVlSaUdNVWhNd0F6RE1JeEJZZ0ptR0laaERCSVRNTU13REdPUW1JQVp4Z3djTGZqLytUUDRuNFl4TkV6QURHTUdyckZZUVRrRXJpL3cveG5HRURFQk00d1plQU93djhEL2R3MTQwd0wvbjJFTUVSTXd3NWlCbHdKWEYvai8zZzY4Zm9IL3p6Q0dpQW1ZWWN6QU80Qy9YT0QvK3lQZ1lJSC96ekNHaUFtWVljekl6eXpvL3h3RFA3ZWcvMlVZUThZRXpEQm01TGVCbHkzZy8vd3U4QmNMK0QrR01YUk13QXhqUnQ0QWZEL0JRam90ZG9HbkVwSTRETU9ZakFtWVlaeUFId2QrNnhRLy81bW4vUG1HTVNaTXdBempCRndIdmdKNCtTbDg5dThEM3dqY09JWFBOb3d4WWdKbUdDZmtsY0FUZ2IrYjQyZStFUGdpNE00NWZxWmhqQjBUTU1PNENmNE1lRHp3ZTNQNHJKOEhQaE40OVJ3K3l6QldDUk13dzdoSlhnbzhBZmgvdURuTDZmWEFrd2lXMTF2bStMME1ZMVhZT09zdllCaEQ1aDNBVTRCbkFWOENmRHp3RU9CQ3ordnZKS1RpUHcvNENVeTRET05XTUFFempEbndTdURyZ0R1QUR3WWVBTndYdURzaDdmNGR3T3NJY2JPL0JxNmN6ZGMwakZGaEFtWVljK1FkaExqWTc1M3QxekNNbGNCaVlJWmhHTVlnTVFFekRNTXdCb2tKbUdFWWhqRklUTUFNd3pDTVFXSUNaaGlHWVF3U0V6RERNQXhqa0ppQUdZWmhHSVBFQk13d0RNTVlKQ1pnaG1FWXhpQXhBVE1Nd3pBR2lRbVlZUmlHTVVqR0xtRGVnOWZyQ1l0aEdJWXhJRVlyWVA3a29tUWlaaGlHTVNER0ttQzFHQ1ZMeTAyd3ZQcEViLzAwdnFGaEdNWUViS3FRNll6cUhQbXVLT25ITFZkaS9acldZN1pPNWRzYWhtSDBZKzNPZE1acWdlRzZBdFZaM0dRaFMyd0JtNmY2YlEzRE1Fb3VUbjlKYjl2V2lQMlBrakVKV0cxRnlYcnFqMHo3QjA3N040RzduY3BYTmd6RGFITkh6LzZiRWFXYnlBa1lCR01Sc0VLOFhGZWNqdFc2WHZUenpRdGpFN2o5TkwrOVlSaEd4WHUzZDAvcWJFK004ZmU4ZDlDTVJjQ0F3bTBJcFdEMWlaZCt2bllucHMvWkFkNzNWTCs1WVJoR3lmMjZ1L3FTMDlMMnRCaS96NjhaQldNUXNPTEhhRmhmM21XaE9sTExKQ0VyMkFadkFtWVl4aUo1Ly82bittTDVzOGI3UjhPZ0JjejEveUNGKzlCbjhlb1RzYjRmSGdnbjZVR25jd2lHWVJoTlBpaHZ0cnhET3BiZjhqTHAwRWlMVVFqYW9BV3N3b3Q1ckhvYng2NFNMMWNLbUJhMVk5cVppUUE4QUJzUFpoakdZcmdNM0tlN3V5TmVibnA4Mzd2UWlSK2xGVFlXQVVzL2loWXZzdldWTEMvZkZiRENuZGlYbWZnZ2VvT3FobUVZYytYK3dQdjFKMkxVM3FXMHVJYVFTWnNtc2E4Sm5xdkJNUllCQTVwanYrclkxdzIxdEVTc053RDZZT0RlaXpnSXd6QlduZzhBN2xudTZndHpGR0VSNmFDN1V0QlNPOVlRcjBHTDJaZ0V6TWMvS1lrai9saGF2QW9SYzZXUVRVcm04RHZnUDN4UlIySVl4c3JpZ0VkVE5NNjFoMGwzek91NHZoYXkya0x6cW4yaytzeEJNaVlCZ3lyK3BkMkhybXVCSGZxMk5kWks2Z0RnVXhaNElJWmhyQ1k3d0NkMGQyczM0RW04UzhjdUxMNHh6R2l3d2lXTVJjQmFQWXJhdkM3RXExckxqejR4cGY0ak1UZWlZUmlueThNSklZdUlib2ZxaEEzZE1aOG9ZajRudGRWQ05tZ0dMMkIxM0V0bElrclA0NWhzVWgrNklGcXkzSWo3YWhIVEthanBBcm9kL1ArMXlJTXpER1BsK0F4Z3ZSSEdvQ0ZlUG9kQ2RHZTgyU2x2dVErSHp1QUZyRWIxTUx3UFAxcGhnZmtzWGdmQWdTdGRpYnJuMGtub1dBTStGZGhlNkJFWmhyRXF2RGZ3VDhwZFdyZ0tyNUxQYlpvSVdCSXhIZC8zMGZLQ3pxRG53VE0yQVNzU09WUW16aEhoUnkzRWl5QmUrb2N2L01ZMGZ1eVBCajVrZ1Fka0dNYnE4TkhBUS9wVDUxc2hrY1BHMHJIQ2xJalZuenRveGlaZ0VIc1pUbFhncUN3c0xXTDdLREZEQ1pudnhzSTh3RzNnUDNmQkIyUVl4dmpaQUo1SW1nZXNsUzR2UzZjdGMrVTZ0V002bEtJenRCbkptTEF4Q1ZqNlllbzRHTEhINGt2cnE3VjBMREZLQzh3RGZBRnczMFVkbFdFWUs4RWpnVS9waVh2cGRveHVSL3pBeDg2NHo1NGxjUzlLWjl5UExZRURSaUpnOVk4aVl5VWtCcVl5ZGVSSDM2K1dXc0RxQUdnbm1lTkpDemd1d3pCV0F3ZjhlNHB5ZFVYc3k3Y0ZiS2FPdU10dDRhamlYekFTQWF1b2c1V1N5Q0hCVGYxREZ5TG1UbUNGL2QvQUJ5L3FpQXpER0RXZkRIeGlsVkd0bGxiY0s3VmZydDBSTDhJaFBlUEFCcy9ZQkN4ZEFHcmNRMkdCK2VySEIvYmlzdThiUFppcXRsajYwZThOL3FzWGRGQ0dZWXlYODhEWEFwZkN3NzdZbC9ZaTFaM3ZQVW9ST3lSMDFvdXlVbWFCTFRIVmVMQ21HMUVGT3ZkZEZpNzU4V1d0UlN5VlpLRjdZZkg1NEIrM3NDTTBER09NZkFudzBWUEdmS0hFeTNVNzM3b2RFMC9TRFI5RUxMa1A2MnIwWTRpSGpVYkFLcEliVVExa2xoLzAwTWVncHhLeFhhcUxnR3lHaXdYWHFkQ3hBWHc5Y01lQ0Q4NHdqSEh3SU9ESitXSEwrcXJqOTVLd2tkb3VyOW91RjU2WGdnM0pBaHZqVkNvd1RnRnJaaU1TZmtpZGlianZ1ejJZcG9qNS9na3dlUlQ0YjFqbzRSbUdNUWEyZ0c4Rjd0ZHZmZFZ4cjJSNXVkenhsczczUGprTW91UDRyZko0b3hHeVVRblloR3pFVkhhRnJodHhGOWgxall1QmFJclRMVE5WWEFoUEF2LzRSUnlnWVJpajRjdUJKN1FUTitvQnl6cnVKVmFYdEZkRnV5V0phTDUvUENzd0R2Y2hqRXpBS2pwK1pGVXo3TUNYcHZpdWgrdVVGMFFuSGtiUHZHRmJ3SDhESHJxd1F6TU1ZOGo4RStBYis4VXJWUTlDaVZlTWZVbjdWTGRYT2hHdENIMzRVcnhHSVZ6Q1dBVXNYUkRhQ2tPWjQwNkpGL2xpdUE1Y3I2eXhJaDVHanl2eC91Q2ZCdHh0UVFkb0dNWXd1Ui93Tk9EdTVlNmlzKzI3cnNNOVg0cVhMQ2wrSDl1ME5KWlZFdERHVnY5UU16b0JhODE1bzVNNW5MTEE2SXBZY1dHNE1pWlcxMHpzdUJJL0R2d1BBeGRQL1NnTnd4Z2k5d0tlQlR4NHN1dFF4S3NlN3ROcHAxd1dzWDJmUzBsSkNuMW4rQStNeDMwSUlaRnVyT2dMUk1aQmFML3lBYUhYc2dWc1J4ZmlkdHlXOVJhd1NUaFBHd1RCbDhXcC95VWRBZmRaNE44RjdzdmpQekVNd3dDNERmaGg0TkZkOGVwTWtVSVo5eExodWdaY2MzRE5oKzNyMFNyYmMxSEFZcEphbi9VMUd1RVNSaWxnTG1RZmlzQ2tpOFRsUXBpSDBRTGI5TGxuczEwdHRYaXQweFV3V2ZTRjRmNFYrTHZBZlZQOFlNTXdWcHZMd05PQlQ1MGdYcFRpcGEwdWJYa2w4VUs1RUwxeUg3b1ZTTjRRUmlsZ2lxWVY1c3FMWkpOd0VXdzFsczI0YkRoWTkxbkVSTGcwMmgzcnZocjg3ZUMrRXJoNktvZG1HTVlRZUIrQ2VEMnU3VGFzWFllZGpFT2k1VVZvU3E2cDVUcmRZVDhyWTMzQitBVk02THRRMWdrLy9nWlpyTGFxOVNhdzRVc0x6S0hjaHVyL0ZDTDJSZUF2Zy9zM3dEdFA1N2dNdzFoaTNoLzRjZUN4czhXOHRPVzE1NEtMVUF2V1ZiS0lTYktaV0Y4SHhJa3NsZlZWeEwvR1puM0JpQVZNdVJGcks4ejVVc1JFd0hiSmdyWHBnbnRSdXc5bHFTMndpWmJZWjRKL2IzQlBCbDQ4MzBNMERHT0orV2pnZTRFUHZybXhYdGQ5am50ZEJhNVFXbUFwL2tVNXM3eXVIRFJxNnd0R21JV29hV1Vra3NkWjZJdEdaL2hjQTY3NmZOSEloWk42UG5USGlmVlZyL2NBSHdYK3VlQy9nSzdhR1lZeExqWUo1YUdlQS80RTRsVm5HbDV6dWQzUmJkQlZsUFZGdCtCQ1BlNExHS2YxQlNPMndDcmt4enQyUVVPT0FLZEViRjFaV3hzdXV3elhYZHQ5MklxQjFSUnV4dnNBUHdiK1E4SDlWK0N0Y3p3NHd6Q1dnd2NDVHdFK3I3L3o3T2xtUSt0c1E0bDUxWjNvWklHNVBNeEhKckVzU2tlNUZiRytZQVVFck1wSWhQRGpFdDJJYTRRZmY4M0JtZytQSlZsam5USnhZeFlCMHhmTFdyVm1MYmdTL2NlRCt5L0Fjd2hYcm1FWXcrWThZYWIyL3dDOGY3ZnFoYzQybEV6b1BnL1FWZUNxQ3dKMmw0TzdQRnh4Y0NVSzJqVmZKbThVaVJzMHhHdXMxaGVzZ0lBcDZoNlJqTHR3WG9rWFdiRHF1TmRKeE10VFRLNWF4c3dlQnY2bmdlZEVhK3hQYi9YSURNTTRNejRSK0JyZ0U5cFcxelMzWVQzTzZ5cEJyTzRpaWhkS3ZDaXJiNlRZVnlOMWZpVllDUUZySlhTNGZFRzVlQkU0WllXSmdLMFJyRFBucDdzTysxSmt0UUFXWCtzendEK2FJR1RmQjd5Q2FCNGFockhVYkFBZkRud2w4Q2toMjFpbzI0RmluQmVUWSsvaUtyeXJXblFDaDFoZmRmeTk2VG9jcy9VRkt5SmdEVkpNTEpyZWp1eVBkclZnVFJDdjJrV2cxejRLcDRpWXB6R0c3Sjdndmd6OHZ3QitIdHh6Z044alhMR0dZU3dYbDRDUEF6NGYrSFR3cWdIdFM5Wm9WZGpvdGJ5QTk4amlzZ1ZXaUpmTFphTnVVSmFOV2lueGdoVVNzSVlWQmpHdFBsNWM4a1FTcTBySW9CU3cxb1ZhQ0ZrMDZUZm9GN0gwZWVmQi9Rdndud3Y4T2JoZkFYNFJlQjJodTJVWXh0bHdIbmd3OEFUZ1k0RVBCYitWbis3enZCU3pLZnV1NWJWSFY3enVJb2hYNFQ0a3hNU3VreWV2TEtaTWNTdm9PaFNjOThNOVp1ZE9ucFR1U3pGeVJMZWh5NW1JTW9oNUJ6Z0huSGR3MFljYXZaY0lWV0Z1aSt2TERpN0g1eTRDRndqWCt3NjVKSlZVOGtpWmpmSi9LWVdzSTVLN3dJdkIvU2J3RjhBcmdkZGlnbVlZcDhsRndnRGtEd0FlUlloeGZSRDR6ZkpsMDRUcldGbGRuUWtwVWVJbENSdFVBa1lVc1BqOGRSY0VMRlhkaUlPV2F3RzdLZXRycURxd01oYVkwTERFanRVRDUwcTNJY1RuYXRPTjBzbzZjbkU3WHJUaTd6NGlpcGl5eG83cHQ4WUtSVDRIN2lQQmYyUjgwMnVBMXdPdkJmY0s0Rlh4OGR1QU84aytpV0ZlaW9heEdCeWhaM29PZUMvZ0RzSVVKdzhBUGhEOFB3RHVDL3lEN2x0OVk2MkZ5NVBkZWRwbFdNK21mRDBLMGxVZkVqUlMzRXU1RGU4aVp4MUt4WTAwUCtFOHhXdklySnlBVlhTU09rU3NSTENpRzFGZTJPbHBpWEQ1OHFMVjVXR09DQmJkRWJrNGNLdXlSNnZDaDN3ZDFvRDdnN3QvK2IwTnd6Z2Q2bnVzVDd3NndrVTNXVU83RFhkOXJLYmhvK3RRaTVhdnhueWhDaWU0bUxUaHk2U05sUlV2V0ZFQjZ4a2J0b2F5eGlvUjAxZEZJV0MrdkdEMWNxaTJkK0s2VmVGKzBqaXpRc1NxYmNNd1RnZmYyTzRUcmxhV1lWMGFTcnNONjdqWEZkOGRySHpWWmN0TGkxZEttYWVjazNCbFdVa0JnNDRyVWRiSFVPNVU0dVVwTXd1MW43dnVkZWxGVEg2Wlowd3EzVytvWmIxSzRXOGxlclFTU1F6RG1EKzFnTFVXOGI3b2NJRysvdzlpdHFDdXNLSEZLNVdKY25tY1Y2cTA0ZFZnNVlaNGFmRk0zM2ZWckM5WVlRR0RpWm1KVFJGempVRHRCUEU2MElzUEx2Y0R5dVFPV1NTQlJJOC9heVY2UUNsZ0ptYUdNUi82cks1aWNUbGMwUEsrNlB0KzN5dTNJV3BDU2tvQms1SlJlb3FVWFJkalhqM2lwVE1PVjFhOFlNVUZER1lYTWFMbEpkdjBEMUFzTHVKcTJWRkxaODR4K3F0LzlGWEFOd0V6alBuUXRMcHFqNHN2Ny9sV3gxVzdETVZ0S1BVTnBWUlUzOXhlMXduQ1ZReFU3aEd2bFkxN2FWWmV3R0EyRVZQUEZiMHd1ajJ3T25BckYvTjVjdkxUSGxIRW9tdFJpOWlzc2JGQ3ZKeUptV0djQ0Q4NVVjT1RLN3ZyT29ZdHEwdUVxNTZJc25ZZGFpdE1QNWJYN2JteVFPK2hMNmRITWZHcU1BR0xUQkF4cnl3d3VlZ0xWNklFVlgwcFlKSXlxMTBKNTlTeVF6c3VOczBhYTdvVVYvb3FOb3hibzlkbFNCWXQzVms5Y2tGYzZ2dTlLVjR1Wng1ZTE0dUxyMUh0dzRGWE15dTdPRDBLWmNLR2laZkNCRXpSRURGUEVJNGpjUi82N0ZiUWNiRFVHNHNYZHUwK2xJdjVISG1nY3hJeFNoSFRBNTlGeU5ab1cyUFFiM21aUldZWUpYME5ma3ZBV2xiWEVibjZleDNuRm0rTEZOcE5BdWF6RzFIaVc3dStFaTVabkhJWitqek95eEkyZWpBQnEyaGtKMHE1cVU0MklsSElWQ2FpQ0ZrZHlCVzM0VG15a09sNG1CYXhUY0xBNTQ0bEZqTVZXekV4TU1FeWpKdWhJMTZORU1Ha1JDM2RVZDF6ZWRCeEVpcVVpNUFzWFB2RURFTWZPNzZvc2FPK084NHJmVmNUcjR3SldJTytGSHVWaFZnSGR0TkY3ck9BSFVaLzlyNFBGL2FlaHgwSDUzeHBnZlZaWVRvbXRrSElWS3dUTytMWExkYUdZY3hHUnhoOEtWNTFqSHRTb3RZZTRWNFhvZHJ6T2E0bGorVjFPanRaTERweFRUYXJhMkRpMWNRRXJJZWVtQmlvNUE1eVptSzYyS1A1ZitqRFJha3RzWDFDekd1WHR2VWxBbGFuMkNjcnpIVkZ6S3d3dzdnNWZMV2RPcVhLQW1zVktTaGNoMnFzVnhLeHVKYUVEQkd1QTUyZ29TMnVScUpHYzBabEU2OHVKbUFUVUNJR2plUU9ueS84T3Buamhxc0VqT0F1MkFKMnZCSXQxMDNrU0FJVzQyQ2JCQUhiOEpPekVodGYzekFNUlVzQXRJVWo5N1ZPM0tncjdFaVNoVmhRK3Y1T1loWmRnNUtabUdvWStrcTQ1UDhvbDJFbldRTk12UG93QVp1Q1hEaU41QTVYeGNGMDc2Mk9pUjBTTHVndHdrV2R4TXJuN2Ewb2NGcyt4OEZheVJ5cG1yMmpLRHBzZ21VWUowTzdEb3ZrRFVmdlFPWGVZZ1dVcnNFa2RNb2pvK2Z2a2dMZ1IwNkpKNWpMOENTczNIUXF0NEx2dXV2cVpZMlFhQ0h1UGtuQVNPbnhMaVpvdUN4VU91WWxqemZJRnRnc0tmVmdBbVlZSjZXVHdFRi85cUdJajR6UFNrS21VdW9QOUQ2VWFKRXpDOFZUMDNJVm5wblZOVlFkTUFFN0lRMFJrN1VqV0VSaUdhMlQ1eG5UbVlTYlpHRVNZZHVrSEFNbTJ5SitmZFU1Z0RRRmpHRVlKOFEzQmkvVGI0V2xOSHBLcTZ3dTNxMlhvMXE0Vk55OEZxMHpjeGtPVlFkTXdHNlNXWVFNdGNRVWVKMk1JY0pVWkJycWJTMStyaXoyYTFtSWhuSHIxTUtoWFhtdFl0M2krcFA0bFhZSnBuMlZZQ1ZyYXhtRlN4aXFEcGlBM1NJOWJzVzBMUllaV1h4U0xNdm54MXJZdEhDSkJWY25iNnpSRUM2enhBeGpObndwRkMwclRJOEgwNVU0a210UnhFMkozTEVTTDEzb29CWXVxdTB6ajNVTlZRY3NpZU1XbVpDcENIbkFzMU1YOGJIUFNSZ1NMOVBXVlNGWXZyVGlKR21qbFgzb2hua0pHc2FaVVl1WUpFNGMreXF0bnJLWXJ3eVpxZDJOK25rdGhMM0NGZitmM2JvM2lRbllIT2pKVk5Ra0lTTlc5aUJhVWJISDVweXlzSlNnYVd0cnphdDRsNGltV1YyR2NldjRMRjQ2SXpHSmtNL2J0WFdXc3BCZHRyWmFTUmttWEtlQUNkZ2M2UkV5RVM1Wml3ako4eW1qVUFSS3VSM1Rmdkp6aGV0UTNRRW1aSVp4TWpvZWszaVRKaEZ6YWwzdE82NzNxK2Zrc3pzeExqRGhtaWNtWUtkQUpXUnhNeUZDRmwrYXF0M1hyc0ZrYVlsdytmdzYyVERSTW93NTRmTjlXMXRqTklTczJKYy9vcmxHdmQ2WUl5WmdwOGdFSWF1dE1naENWYXg5OTdraWFTUysyVVRNTUc0QjN4Q1dsaWk1YWcyZGppbVlhQzBVeTBKY01MNHRPSFVtWTkrK3ZzZUdZY3lIamx2eGhOdkE4SVJycURwZ0Z0aUMwUmYyRkJlakw5ODI2OGNiaGpFRHM3Yll6YVNzMWd1SEpscGp3QVRzREtrditCNUIwNCtuQ1pUZFFJWXhINmJlU3laWVo0OEoyQkxSdWlFcWw2UGRNSWF4WUV5b2xwZEJ4OEFNd3pDTTFXVnQra3NNd3pBTVkva3dBVE1Nd3pBR2lRbVlZUmlHTVVqK2YrUEpmUGVjYXFwS0FBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xIl0sImV4dGVuc2lvbnMiOlsiY3JlZEJsb2IiLCJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwibGFyZ2VCbG9iS2V5IiwibWluUGluTGVuZ3RoIl0sImFhZ3VpZCI6ImIyNjcyMzliOTU0ZjQwNDFhMDFiZWU0ZjMzYzE0NWI2Iiwib3B0aW9ucyI6eyJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsImxhcmdlQmxvYnMiOnRydWUsImVwIjpmYWxzZSwiYXV0aG5yQ2ZnIjp0cnVlLCJjcmVkTWdtdCI6dHJ1ZSwic2V0TWluUElOTGVuZ3RoIjp0cnVlLCJhbHdheXNVdiI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjAwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxLDJdLCJtYXhTZXJpYWxpemVkTGFyZ2VCbG9iQXJyYXkiOjEwMjQsIm1pblBJTkxlbmd0aCI6NCwibWF4Q3JlZEJsb2JMZW5ndGgiOjMyLCJtYXhSUElEc0ZvclNldE1pblBJTkxlbmd0aCI6OH19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTAzLTI4IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJhdXRoZW50b24xIC0gQ1RBUDIuMSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjMwMzI4MDA2IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjQuMCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS41LjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjMtMDMtMjgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIzLTEwLTAzIn0seyJhYWd1aWQiOiJiNTBkNWUwYS03ZjgxLTQ5NTktOWIxMi1mNDU0MDc0MDc1MDMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImI1MGQ1ZTBhLTdmODEtNDk1OS05YjEyLWY0NTQwNzQwNzUwMyIsImRlc2NyaXB0aW9uIjoiSURQcmltZSAzOTQwIEZJRE8iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjI1NiwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50IiwicmVtb3RlX2hhbmRsZSJdLCJpc0tleVJlc3RyaWN0ZWQiOmZhbHNlLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUM2VENDQWRHZ0F3SUJBZ0lKQUpiVHlydTFYL0lQTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVEFlRncweE9EQTJNVEl4TkRRMU5UQmFGdzB5T0RBMk1Ea3hORFExTlRCYU1DTXhJVEFmQmdOVkJBTU1HRWRsYldGc2RHOGdUWFZzZEdsQmNIQWdSa2xFVHlCRFFUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1WaktIV3BiRDdUU2xNeG9jalRsNm5JZjd4MzJQbXNROXpHdUxHR3FBMFVRWm9JcTNYTHpMNkxZVXZKNUE1ZzB1eUZHbGxIRWZHQUtyRWFDUThGVnZQUy9VaDBGeWZ6V2hSQXppVFNpampNSUlWampqVXY5bTl2Rm1jWFNjZ0hpZzdPZHo4ODU4VjBrck5IOTlxR20zd2pnYU9lclRXbXQralhDVWZuMDFJa1RQd3hHMkhsZ0VkNDVqTkxTVjdWb29sK0tlOEUya2k0bEVrVGVIemJvdWxSNUdVYnAzbk1pN0U0N1ZNUWEzYk53bnpXQmJzYUJTU1FoTGszbTVIYUtoaHhhNndKREs0N05pTUNrQ2tkSUh1V1NRTFZBZm04NVVBT050RU9Qd2kwT3VLM3FiZTh5S09GR2YwS2hCNU1NZUF5bTdNVi9NNFcwYTQ5b2dQRDlwTUNBd0VBQWFNZ01CNHdEQVlEVlIwVEJBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUNBb1F3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUpXejV4TE1rNVdOWWJBYjZ5T3hFQ0JvWjJXZUIvcWw0VkozTy8zL3ROc3hPWW56TGVXbzU0MHpRaDlyQW1heHo3ZXVtQmxza01xNHlHUFNOWEI5eWNXR0hna2NDZVN6TjJ3djhDSXpEQnMyb0JaalROazY1TEJaRHNzVE9CdE1XLyt1VEZIUWZidU8zSVNMaEkwRFhmUkVpOU5ETTNqZmsxMXhIY3NmaDJSTVYrUWROZndWYVpackNxK291RytFdmt2N0txcStveXUwVkZNL3R6NjhUR2w2eWxoUEZSMXFoOXd0dHBWakFPT0NFUUNMcVAyZFAyOGx3WUJ5Q3FIUXFWSHdidWp2L0xaalpuS1czTFluZFppeFBQU1JDSnNzRER3SnZoL2Y2blR4ZzlaRSsvSmNZcmU1Q2FJOG56VkhhU09Dak5KN0Z6VUxHNjRKaVdPdlE1MD0iLCJNSUlEZFRDQ0FsMmdBd0lCQWdJSkFJQ1VUdmtndGo1Q01BMEdDU3FHU0liM0RRRUJDd1VBTUZFeEN6QUpCZ05WQkFZVEFrWlNNUXd3Q2dZRFZRUUtEQU5FU1ZNeEN6QUpCZ05WQkFzTUFrTlRNU2N3SlFZRFZRUUREQjVIWlcxaGJIUnZJRTExYkhScFFYQndJRVpKUkU4Z1UzVmlZMkVnUTBFd0hoY05NakF3TnpBM01UUXpOekU0V2hjTk16QXdOekExTVRRek56RTRXakJSTVFzd0NRWURWUVFHRXdKR1VqRU1NQW9HQTFVRUNnd0RSRWxUTVFzd0NRWURWUVFMREFKRFV6RW5NQ1VHQTFVRUF3d2VSMlZ0WVd4MGJ5Qk5kV3gwYVVGd2NDQkdTVVJQSUZOMVltTmhJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF2QUtPZXFDNS9wMEQxaXNDWUtRSmxWVU9yQjZJN0RMb2N1bkUvUm04ZHVHVGJ5eFFodDNDYkZWVHYzTjJMcDJmYmp4bEkrM3NPU0drMzNGVFlrVHF4Y2RKSXJKN1Nza0JjVVNOcmZLT2FRVC82S1FjUDRDbTdWKzY1NVRxK1RXeHl4V1FoRHlndDE1cW9QN011SzZiVDlTd3BDanBmS2hhTVNteVFhTW9VY1JBYkxxZHpCQ2FjMGh6QitaZStncUpsbldWOVVhU0kyckZzVnVINFpFMGNSTytNT3BhTGdNL3MyNDhuR0dIcDIyZXdTUWZiblBhQmJiOGlxeUFQK2N1NTJHTHNVcEtSSmViRStSNitQTVE5SkNkV2VRWlIzRGtmU2lka3YzbWNiNGpxMWlJdGErTXFLaFJud3JmWGg5MTFLV0xuWUFsOUVOQ2hMWDBjNlNqMVFJREFRQUJvMUF3VGpBZEJnTlZIUTRFRmdRVVdMdmhSQlVQbjh1TElmNjgrZ3YvTlpJd0dTSXdId1lEVlIwakJCZ3dGb0FVV0x2aFJCVVBuOHVMSWY2OCtndi9OWkl3R1NJd0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBRkxyRGhhZWdlS0h4WWpIM0VQM3ZVQktobnpNMjA2QVN4Z2VZQ08yRWM5cE9sWUphZXFGRStzVWFtVVYvcHdqRGxxTmFTZ0ZneTdUd2VZa3ZPbU1uNHFTY3NIcXZKM3pHT0FpYWZ3YWgxdlVIZkNsWFI4K2F4TzJpR09VRjBKS3JaOVlZamJBYTUvNEhDbHY3akZQT2RNV1RPUXluZ29pSEFzM2prdVlqcENMRmxCNFZPaTNkMXdqQTFwblRkQktrQWI3dDhuVHZ3Ky9YYkZ2Y1FhNzNWSDdzanZvQnFEM2ZkTWZSY3VWcTRxVVp0WlQ2Y0dhZ1RIRDYxVHRxaDlvTUNaWGNEYlIxUEdabk5icXljc1dQRElLMG5wbUszLzNsZlY4Yytac3J5NmUxNzBtZkpNWnA3TzhtNkNTejYvVkxLK3lESmQ3ODQxd3BtZUtUZjZJblpBPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBUXdBQUFBZ0NBWUFBQURubFVacUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUFBWmRFVllkRk52Wm5SM1lYSmxBSEJoYVc1MExtNWxkQ0EwTGpBdU1qSHhJR21WQUFBSzFFbEVRVlI0WHUxZERYQWNaUm0rTk9BZktvZzZXTzBRY3JlWDNPNzFSNDFvSGRTcXFEQU9nMytjWUVYQm9sWFJURW4yMjB0YUtUYzY0bWdCcXpCaUVVVnBCZHFpd3docVNkSVMydXBZU2d2UnRwVFNja2xqV3pIYWdqcFNSZHI0dkx0dmpydmsyN3ZkdmQxTGpuN1B6RE4zdC9kKzcvdCtmOC8rNzhhSzBORGFhcjJxT2RYWm9xV3lIOVIwYTBGY3Q2N1dkSEdUWm9qVkNjUHFTZWpXMW9RdUhzT3kvZUJUc0RtTS81NFpUOWorTFdHSWc3RGZCL3NCY0RQc2Y0WGZQOFgzYjJ1RzFaSFF6VThtVXVLZHlXVEhtNXFhY2kvakhBS0J5aWYwYkJyK0x3YVhJUFlQa01kcWZMOFhkV3BsczFBQTMxL1FqT3c5OEw4UzliOEJYSVIyK25EYzZEb3psc2swc2xua1FNeGtQR1hPOUVKdFZuWUdGNHNVeVZuZDhVVGFlcDhidys2TGFrQmo1aXpkYk5KUzFyeEVXbnlXeGczNkVtUGRXb1BQRGVqZjdlQVRHTXNIYUR6VHVDNmhiajBOL3BYbUFzcnVnczBXTFA4TnVCSmpaSm1XRWxjbDA5bVBKMUptVzB0TDUrdWlIQnVHa1hzbGpYODduaTRFelZuazlBdmtzUW41N0VTZGhyQjhCTXVQak9XUC8vNE9Ic1IvZTdEOFlkVGxmdFJoRmZnZExHOUh1MXdBZnpyNTVqQU9raVFLaHZWYkdCNkMwLy9pKzJpTmVSeDhGZ252UmZ4ZmFpbnpTazdORTBpSVVQYmY0M3dXbU5UTmQ3QnBLRUE3TFpmRkFZOXpwM3laVFNNRGlRVmkvVStTZzVRWUFJZk9tRzJld3NVakEvcmhXN0w0QmVybWo5aDBVb0IyT0IrVFpUVzRCL2s4T3lHL3lDaU9vVzFJWUg2SDhYUHo5TGJjS3ppbFFHaHBNWnZoWnlIR3dHM2c0MkJrODVaOG85MEc4WDBOaVNzMUl2MlFHazhLZFdzenQ0c25JUDhScVI5bURRWERJZFpTYkJvWjBJbDNTMk9YWlhZcEY0OE1VMTR3bksxYmVXNDFwTDNGRVFDSmxQVld0REcyZnV5VnJOUjN0QlRkU2pCOFlySUZveVZ0bm8yT0N6Qmd4RE5CQjZwWEtNSHd4aUQ5Z0szS2M2UGNrdkJHSlJpK01jbUMwWUQ0ZmRLNFhvaDlXL1lUQ1pSZ2VLTnZ3Y2hrR3RHMmUyVytha3NsR0w0eG1ZSkJheGxwVEkra05SUWRtR1Izb1VNSmhqZjZGUXc2Y0NyelUzdENNTERXdVFzZDNSK0F3M0tuQlE1S3luamhqZHhPbm5EaUNFWnVHanJzWVdsTUp0cGlXVUszQm1UL0ZmRXVkaGc2VVBlNkZnejBiUjZmYTZNbW5ZM2tsRHdoYVlqTFVVNmVzMjd0MGd6em03VmdVdTk2RDZma0h4Q2E2MlVWR0NNcThnMDJqUlFuaW1Cb1J2WWlhVHdtMm50Zlc5dkNrN1cwZFlIcy93SjE2M2s2ZU1adVEwVzlDd2JHOUsxc09xV0F2SVUwWDV0aURadE5iU2pCY0dFRWd0SFdkc3ZKOEUybkF1VXhpYnA1aFdNOTJvRGYyeWI4WDBLeDNyRU5GMG93b2dIbTBoSnB2amFWWVBqQ2lTQVlpYlQxZVdrc0ppYkNrL1BtNVU1aWM4cnhRcGxkTVJQcDdIbHNIaHFVWUVRREpSZ2g0c1V1R0hTUkQrcElWK1RKNHhIMUxHOWRqQ0hUaU1sUjRWaUcyRTdIUmJoQUtGQ0NFUTJVWUlTSUY3dGdvSjJ6MGpoTXRIT2VqbDJ3ZVFGWS9sR1pmU25GZkRZUEJVb3dva0hDTUJkTDg3V3BCTU1YS2dxR0lTNXZUcHRuaDBYVSswNVpuQUpERkF6RDZEZ2QvcDZXeG1IR0RmRkZOaCtIMFFiMHdhT3lNbU9FK09VTkkvY1NMbEExNmwwdzBGNjc0N3E0cFJwR2NkcWE3a3VSNVV0RUg0NWdEbXdLaS9EWmo4LzdJRVMzNHJPemVhYVl6V2xVaDNvUmpKb3pSTUdvT0FFTmEwaTJkVEdHZUVwOFRGSm1QRHZZdkdyVXUyQ0VRYnFoa3NPRkJzeWxpMld4YXNUajZOZDEycHNYdjU3VENRWWxHQzRNU1RCYVc2MDNvbzFkYjZxenFWdGZZbk01NkFwQnc5b3hvVndSTVlsR05LMzkxVnlpS2lqQmlFWXdtbFBkTGJKWXRTVGE3cUhpQSt1K29RVERoU0VKQnRwdmhkVC9HSFd4djl6V3hSaTB0UGlFdEh3SnhiVnNYaFdVWUVRakdIUndHdU9oMGdWNWtUT2VNaS9oaFB4RENZWUxReENNczFxdFZnenU4cmV2cHl5UGp3SHdzcFZoL1N1VldqS2RDd1NHRW95b0JBTzVwODMzb3ArZWs4V3NGZEYrd2E4U1ZvTGh3aEFFQTM3V1RQQmJSSFRjQWV4R3ZKVE5IZlFNTmNmNkJzK1A5ZWJueGZxZVBKV1gya0NaekhnZkV4akNHUUlsR05FSkJzRitFSkV1ZHN2aTFvYmlUNXlLZjlTTllPaldaalR5ZmFIUnVkOUFIb3RZcFdBNE54cUpZMUxmVE5UNUsyd2VpNjBmTWlBVUQ0S2pCZmJtajhiNjhzdGoydzdhRDJxaGZVLzB4eTZacnpIUzJxdWxwVE5sK3d5SXVoY01qQlU2NjFRTm0yY3VQb1BEUllUUkJqcGJSMk1BT1Y5SFp6T1E5OC93L2ZZd2lQSHRmamUwYnYyRmsvQ1BlaEdNT3JzT28vTHQ2N28xWERnVnVpRS9Cd0x4anhLeEtPWEcyTTZkdGkzNnc4T1JkbkdQN1RjZ2tGdWRDOGJVdkE2amxraWtPOCtUdGcySU1YU1l6ZnhEQ1lZTHF4QU1MN2V2bzc3dHRuRi8vMG5Za3RnaEVZbHhITHFhekoydGpFcWJzOWl5U1dYbjJ2NERRQWxHL2FPc1lCaldBVGJ6RHlVWUxnd3NHTGxwS0x0VjZwTkpIVlo0WUhMZi9uZkpCV0lDaDJIZFFFWGk2ZXdsTXI4bGRKNUhZdHY3aFJLTStrYzV3VUQ3N0dVei8xQ0M0Y0tBZ3VIcDlHZEtYTVhtRUl4OHUwUWNYUGpZYSsweW1Vd2oydXR4cWU4aW9vNFgydlkrb1FTai9sRmhsK1NQYk9ZZlNqQmNHRUF3NkhvSzdBNlVuY2lvNThHbXBzdGVlQjFENzlCWDVlSWc0ZjNEcDNPcEdPTE1sL2tmeHgyeHpGcmZqOFZYZ2xIL3FMQkxzb1hOL0VNSmhnc0RDRVlpVmY3MmRXYnBKZHc5Kzg2UmlzTjQ5Zzd1aDNWaEY0UEY2UW1KLzFMcTFnSXU0aG1WQkFNVDl1N3g3MHdKZy9UWWZVNmhMSlJnVkVhRlhaSUgyTXcvbEdDNDBLZGd6SjV0bmdLZkI2UyttUGovMEl3WkhTL25JZzVHUnhzaEJnTlNrU2psWWk1UkFQcnVVbG1jWW1KeS9YbkczSEV4SzZEaUZrWkV4QmpZeUNtVVJTWEJRRHVQb0E1Ym8yYlN5TDZkVS9JRTNpcVVuZ1lObTJnRDE3TjArRzhWcCtRZlNqQmM2Rk13NHJwbFNmMFVFVEZOTmk5RnovRE1XRy8raUVRa0hQYm1OOFMyYlp0NCtiaHpqMG41SjNpQmRGczFsL0FFMUwydUJhTldUT3JpQTV5U0p5RHY3OHI4MUp5ZXJ5NldRQW1HQzMwSVJ0T2MzR2xvcDhOU1AyUFV4Vk5sMS9UcjhxMnh2dng2OFBraXNmZ25mbDhmNng5MGZRVWw0bjVHR3ErWXVqaHk1cXp1MTNDUmlsQ0M0WTExS1JqMFdrZ3RGL3dtUlNVWUx2UWhHRjRtR0FhTFlQUHkyRGcwUGRZejlIN3Nwc3lOOVF4VWZDMGlYZnlGUHRvbmkxbE1HcXhjcENLVVlIaGozUWtHeENLcFcrL21kSUpCQ1lZTFBRb0d2WVFhOXVYZjcxbHA2NkpLbEh0OC9Rc1VSKzBYVFh1QUVneHZyQS9Cb0xmcjJRZkhyL0d6bGVtS0tTTVl1bmtIVFN6RWxMNCtzRmFDZ2ZvK0IrN1dqT3puMkxRc25OY0dpRDFVVHViUG9kbkY1cEdBenBnZ3Z1dFdCdXI2SDd0T3VyaVVpNVFGWFNXS010L0hCTjVFYXlYVXIrdzlNY0VwanZHSzR2Zklid1ZkdzhJcGxBV05CWlM1RHZXaE41WG40ZWRvcWQ4b2lGeXgyd2sraXUvMEl1aWw5S3dUVHNrVDRtbHhEdHJ6Um01WGpQVW8ycFhlNkc0OWdqeHZ3K2ZDaE5HaGNmaHdRQzlqYVRMRUc5eG9HRmVXdmlZK1V1U20yUStjb1hkeTZOWWlOT3d5VlBySEdCaDNKb3p1VUNzZVQ1bVhRZkYvamhnL3hPZlhOZDI4Z2pvMGFIM3BMQWxOTkdkdEw1WWk1NXZRZ2JlajQrNmcvOWdzTXFBT0gzSGFTZndFYlhjRHZtZVRodlVwVGU5Nnk0UXpNNzZRbTlZMFo5RnBkUGNtNnZOcHNBdDlzdHhwTyt2WDRFYkUyMG9UQ2NzR1NvbmwrQi9mNldhL1ZjVjUwYVNQeDd0T0RlRUJ4ZzEweHkrZGtvWGdmQWd4RmlEZTE5QU8zME0vckVRTzl5TG1BNGkvQmIrM2wrYm5rUElITjRQclVMKzErRndCMjJ2aG94MWlmMUc4MVhwYnZBMjVaaksrcjJseFIyNGExZDhSUHpFZnV3b1djc0VXaUpNellqK0kzdytWdEtzaEhnSC9BUFpTbnFqVHpmaTh4aDY3dW5VdVBkckEyOE54WXJIL0F6M3RJNGo1K1RPTEFBQUFBRWxGVGtTdVFtQ0MiLCJzdXBwb3J0ZWRFeHRlbnNpb25zIjpbeyJpZCI6ImhtYWMtc2VjcmV0IiwiZmFpbF9pZl91bmtub3duIjpmYWxzZX1dLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJhYWd1aWQiOiJiNTBkNWUwYS03ZjgxLTQ5NTktOWIxMi1mNDU0MDc0MDc1MDMifX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDEtMDYiLCJ1cmwiOiJodHRwczovL3d3dy50aGFsZXNncm91cC5jb20vZW4_Z2NsaWQ9Q2owS0NRaUEzTlhfQlJEUUFSSXNBTEEzZklLLXp4aU5VMXFROWdtLVNKdFF1MlVMdVl1eEp0VW9fWWxqelhiNWtiWTUxMHh1dUpvY1hFd2FBcGo1RUFMd193Y0IiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IklEUHJpbWUgMzk0MCBGSURPIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDExMTgwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMS4xIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDYtMTYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTAxLTA2In0seyJhYWd1aWQiOiI4Yzk3YTczMC0zZjdiLTQxYTYtODdkNi0xZTliNjJiZGE2ZjAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjhjOTdhNzMwLTNmN2ItNDFhNi04N2Q2LTFlOWI2MmJkYTZmMCIsImRlc2NyaXB0aW9uIjoiRlQtSkNPUyBGSURPIEZpbmdlcnByaW50IENhcmQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwibmZjIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCMkRDQ0FYNmdBd0lCQWdJUUZaOTd3czJKR1BFb2E1TkkrcDh6MWpBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pEVGpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERURTRNRFF3TVRBd01EQXdNRm9ZRHpJd05EZ3dNek14TWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRW5mQUtianZNWDFFeTFiNmsrV1FRZE5WTXQ5SmdHV3lKM1B2TTRCU0s1WHFUZm8rKzBvQWovNHRud3lJTDBIRkJSOVN0K2t0anFTWERmamlYQXVyczg2TkNNRUF3SFFZRFZSME9CQllFRk5HaG1FMkJmOE81YS9ZSFo3MVFFdjZRUmZGVU1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFDM3NUMWxCakdlRit4S1RwelYxS1lVMmNrYWhUZDRtTEp5ellPaGFIdjRpZ0lnRDJKWWtmeUg1UTRCcG84cnJvTzBJdDdvWWpGMmtneS9lU1ozVTlHbGFxdz0iLCJNSUlCMkRDQ0FYNmdBd0lCQWdJUUdCVXJRYmREcm0yMEZabkRzWDJDQlRBS0JnZ3Foa2pPUFFRREFqQkxNUXN3Q1FZRFZRUUdFd0pWVXpFZE1Cc0dBMVVFQ2d3VVJtVnBkR2xoYmlCVVpXTm9ibTlzYjJkcFpYTXhIVEFiQmdOVkJBTU1GRVpsYVhScFlXNGdSa2xFVHlCU2IyOTBJRU5CTUNBWERURTRNRFF3TVRBd01EQXdNRm9ZRHpJd05EZ3dNek14TWpNMU9UVTVXakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXNGWUVFaGlKdXFxbk1nUWpTaWl2QmpWN0RHQ1RmNFhCQkgvQjd1dlpzS3hYU2hGMEw4dURJU1dVdmNFeGl4UnM2Z0Izb2xkU3Jqb3g2TDhUOTROT3pxTkNNRUF3SFFZRFZSME9CQllFRkV1OWh5WVJyUnlKendSWXZuRFNDSXhyRmlPM01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWURWUjBQQVFIL0JBUURBZ0VHTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSURIU2IybWJOREFVTlh2cFBVMG9XS2VOeWUwZlEybDlEMDFBUjIrc0xaZGhBaUVBbzN3ejY4NElGTVZzQ0NSbXVKcXhINkZRUkVTTnFlenVvMUUrS2tHeFd1TT0iLCJNSUlCZmpDQ0FTV2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakFYTVJVd0V3WURWUVFEREF4R1ZDQkdTVVJQSURBeU1EQXdJQmNOTVRZd05UQXhNREF3TURBd1doZ1BNakExTURBMU1ERXdNREF3TURCYU1CY3hGVEFUQmdOVkJBTU1ERVpVSUVaSlJFOGdNREl3TURCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk5CbXJScVZPeHp0VEpWTjE5dnRkcWNMN3RLUWVvbDJubk0yL3lZZ3Zrc1pucjUwU0tiVmdJRWt6SFFWT3U4MExWRUUzbFZoZU8xSGpnZ3hBbFQ2bzRXallEQmVNQjBHQTFVZERnUVdCQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBZkJnTlZIU01FR0RBV2dCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFNQmdOVkhSTUVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCQmpBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBd2ZQcWdJV0lVQitRQkJhVkdzZEh5MHM1Uk14bGt6cFNYL3pTeVRabVVwUUlnQjJ3SjZuWlJNOG9YL25BNDNSaDZTSm92TTJYd0NDSC8vK0xpckJBYkIwTT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRkFBQUFBVUNBTUFBQUF0QmtybEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFCSFpwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTURFMElEYzVMakUxTmpjNU55d2dNakF4TkM4d09DOHlNQzB3T1RvMU16b3dNaUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenBrWXowaWFIUjBjRG92TDNCMWNtd3ViM0puTDJSakwyVnNaVzFsYm5Sekx6RXVNUzhpSUhodGJHNXpPbkJvYjNSdmMyaHZjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5d2FHOTBiM05vYjNBdk1TNHdMeUlnZUcxc2JuTTZlRzF3VFUwOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXRiUzhpSUhodGJHNXpPbk4wVW1WbVBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWU1pXWWpJaUI0YlhBNlEzSmxZWFJ2Y2xSdmIydzlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFMElDaE5ZV05wYm5SdmMyZ3BJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4TmkweE1pMHpNRlF4TkRvek16b3dPQ3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2U0dsemRHOXllVDBpTWpBeE5pMHhNaTB6TUZReE5Ub3pNRG95Tnlzd09Eb3dNQ1lqZURrNzVwYUg1THUySU9hY3F1YWdoK21pbUMweElPVzNzdWFKaytXOGdDWWplRUU3SWlCNGJYQk5UVHBKYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pKRk56RkNSa1pEUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakpGTnpGQ1JrWkVRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lqNGdQSGh0Y0UxTk9rUmxjbWwyWldSR2NtOXRJSE4wVW1WbU9tbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNa1UzTVVKR1JrRkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUlITjBVbVZtT21SdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1rVTNNVUpHUmtKRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpTHo0Z1BDOXlaR1k2UkdWelkzSnBjSFJwYjI0K0lEd3ZjbVJtT2xKRVJqNGdQQzk0T25odGNHMWxkR0UrSUR3L2VIQmhZMnRsZENCbGJtUTlJbklpUHo0NzdKWEZBQUFBWUZCTVZFWC8vLzhFVnFJWFphdkcyT29xY0xHMnpPT2t3dDBCU0p0cWxjWFY0dSthdXRsV2hiems3UFVBTVk5SGNyS2p0TmJxOGZlQWw4YUJvc3p6OXZwZGpzR0dxdEYzbjh1VHNOU1pwYzZKc05UNSt2MHhZS251OFBmZjUvTDQ4ZmcvZnJpY3pKZ1lBQUFEQUVsRVFWUjQya1JVQ1piRElBakZYWk9ZMVRhdE5jMzliemtzU1ljM3I0TUU0Zk1CQWFENnpsOHkvOVRPZ2V0OGQ1amZONzhid00vZERDUnBSNTIxelhmb2pISjA1SUl5aEJBVVNWQU9OZEd6Qll0MmY3S0ZyZmtKYUFrSGg5RlpoY0RYSFJrVEtvOU1MaWhHYWF2SW1uVjNxeUVYMEVwcmd6LzREd1VEN2tDSFJuZDhRRk40M0dvNFVWbUREZ3phNHcyN29pemRBMitjSyt1dVVwampvMit4d2MvNDJXNTB4NUxHWWVEQnNSMEhWSXg1eDhpRjYwQ2JsYlRFRWtGcjI3Yk5EQlVWU3ExT0tWUGJFNjJiM0VIOEZxQmc1T09PRXVjMnQ4WkppcU1PdUdwK2NLamc3d1ZHY2VvenFONHB4Z1ZQUWtqRllnYlZKS0RVaERDallyYXdQNXE0RVRnQzlmSU1SSHRpdHBRY0N2Sk9FTGNiTXNRZ25jaVJrbGpweVFqdkc0NGpxQlVFVEZpQmkxUEVJeWVrT3pzVytUeTVjTEhvczVSK2RNUzFMdFNTeGYzZ1FIY3pSMkNJNGdNTnBXNElSQTFRTWE2dEo0K0M2dUh1R0U4bU5ESXlGcWcvT1AvTU1VdWVTNklxOFM5MGRBZUJKU0V5L3FLa0srQk53ejhjWVk0amI1SjZ1NGlXQ0kyQjFaNTZMVzVrRWM0aGtkTXBzdlVDNTU4NVNYMFF1YmNnTnF5ZmdERkVjVHQrNDAvMFM1Tngwd2FDdzNPS2tjT2JBNUluMEFZcDAxcGpqdzJuNjI2VURqdEh3YTI4aUh1VEtxdHJ2K3JlVzQxTlo2aUdscjd1dUxKQ2ZrRnRjdGNHMDRzZ20xZU5TK1phRG5wYVRFckdveVg1SksyaU16OHhzMG5Pd1dHY1BETjQ5cWFDZDRiekpvekRabS9hQksrRW96THcrWGhOQmlZd0hmMHNpT3UxWFBrRy96S3d2cVlLY2ZTd0RFY0gvb1VlMDdlcy9XUThySXlnMkRPWGo4dGprWmR1REIvYjhoekRsbE1NT0NTNUJFbmQ1MzRmOHRpM1VaYzRrTXMzeEx5YWZNU3NKaGRHOFhQcWpOazV0QWdPMjVmZUtDaG5WZERqL0owRk1rT3NVL3hNQnYwd0ZoWWVFR2ZWSDEzZnVEVTB5REZMYTRmYzdSbldIQmZ1VEZWMnRFbU53YWRjN2FjM1VZMmpmQmw3SFQzNmZlMzRpUU81bU5DRkZCVzA3S2pQZ3FoT0xVMDF2WjhQdWVaMkpDbEZaTjhqa1VzNjl1a2E5ZVBwNitFZkw0QUY1K055d1NiaXJIdGNCOE1sL2drd0FFamtLNjRLakhQZUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiOGM5N2E3MzAzZjdiNDFhNjg3ZDYxZTliNjJiZGE2ZjAiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2IjpmYWxzZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3IjpmYWxzZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6NiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5Nn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA0LTI0IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJGVC1KQ09TIEZJRE_CriBGaW5nZXJwcmludCBDYXJkIiwiY2VydGlmaWNhdGVOdW1iZXIiOiJGSURPMjAwMjAyMDA0MTcwMDEiLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4zIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA0LTI0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMC0wNC0yNCJ9LHsiYWFndWlkIjoiOTliZjQ2MTAtZWMyNi00MjUyLWIzMWYtNzM4MGNjZDU5ZGI1IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiI5OWJmNDYxMC1lYzI2LTQyNTItYjMxZi03MzgwY2NkNTlkYjUiLCJkZXNjcmlwdGlvbiI6IlpUUGFzcyBDYXJkIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjQ1LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MX0seyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjo2NCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjo4LCJibG9ja1Nsb3dkb3duIjowfX0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNWekNDQWYyZ0F3SUJBZ0lKQUpNYzhXMUlPU05oTUFvR0NDcUdTTTQ5QkFNQ01JR0dNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVZtbHlaMmx1YVdFeEVEQU9CZ05WQkFjTUIwRnphR0oxY200eEZUQVRCZ05WQkFvTURGcFVVR0Z6Y3l3Z1NXNWpMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVYTUJVR0ExVUVBd3dPV2xSUVlYTnpJRkp2YjNRZ1EwRXdJQmNOTWpNd09URTBNVEExTlRBMldoZ1BNakExTXpBNU1EWXhNRFUxTURaYU1JR0dNUXN3Q1FZRFZRUUdFd0pWVXpFUk1BOEdBMVVFQ0F3SVZtbHlaMmx1YVdFeEVEQU9CZ05WQkFjTUIwRnphR0oxY200eEZUQVRCZ05WQkFvTURGcFVVR0Z6Y3l3Z1NXNWpMakVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVYTUJVR0ExVUVBd3dPV2xSUVlYTnpJRkp2YjNRZ1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU0orNjFMSmY5NjAvMEN6dmpkUzFNdWVrTi8zL041RFh4OFErTkx0Nm9oOU5kT0RBVFR5alJDQzgwZW5DNnJ5UlFyUDFqRWVBVHRtS0pxUFRKcEFHWnpvMUF3VGpBZEJnTlZIUTRFRmdRVWxRNjhDanpSa3kyeGNCTC9jNDd6cDZqUStMTXdId1lEVlIwakJCZ3dGb0FVbFE2OENqelJreTJ4Y0JML2M0N3pwNmpRK0xNd0RBWURWUjBUQkFVd0F3RUIvekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUJiSGFBeTlVNkZSTG5KdWxIUDc2ZEY3VmlzSzdIQzBTcEtEdnJWOUx0alVBSWhBTFpLc0k1TVhSeTJDMmY5MVhhSWhmT3dNQmVKNVBMaFdSa2NkeWJXMHI2TSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFDQUFBQUFnQ0FJQUFBRDhHTzJqQUFBQUNYQklXWE1BQUM0akFBQXVJd0Y0cFQ5MkFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK0xwc2J4dDNJdmVSS2RQVnhYZUY2MHZXZG03T2J3dTJvMjYvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rcWk1cVBObzN1alM2UDhZdVpsbk0xVmlkV0Vsc1N4dzVMaXF1Tm01c3Z0Lzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284L3BQVFQ4ZTduTHVhcnJsY2E3bnVlcjIxZTJiMzZSdWVOODdkOUwxNThSYi8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBZ1kwaFNUUUFBZWlVQUFJQ0RBQUQ1L3dBQWdPa0FBSFV3QUFEcVlBQUFPcGdBQUJkdmtsL0ZSZ0FBQXRoSlJFRlVlTnJzbHQ5TGsxRVl4Ny92TnRlMHZYT2s3eVM3cXlXQll2bmpJa3RHVTB2REN3a3RWNEtYcHYzd0IvNEJCaUlhL1FDMXdqa1ZVeE5zVXV1dXpkMWs2aUJMQ3hJRnpjRFhPVFp3WThyMnNyMXJwNHVYWnVvZ2dyeUpmUzhlZUw2YzUzdzQ1K0U1SElvUWdvT1VDQWVzR0NBR2lBRUF5WDZMWmRuMTlYV0dZZFJxOVQ4Z2tOMXFhMjBWRGxWWmNaVVFZcHVaS1MwdEhUY2E5eXd6Nkh1cnE2cy96czZTUDJrWHdHSTJBempLcUhRNjNmdDNrNFNRcG9ZR0FNV0ZSWHZLTG1vTEFBd09EUHdkb0xkSEQyQmthT2gzODQzSjVISzU5cFRWMWR3RThHcDhmUCtPUzR0TDVyZm1INkdRa083MG9MdXpjMmp3dVNvcDJkQnJPQ3luazVLTzlQWDNaMlprTUNrcHF5dmZHSVlCY0wrOXcycWRLQ29xQ2dRQ0FIaWVGMm9mUDN4a01yMVcwSXJhdWxwdFFZSFA3d05GN2UyQk5sOERJTzM0Q1FBTmQrdTd1N29BU0VBQnFLdXBKWVJVNmE0RG9HWHhxYW9VcFp3V0E5YUpDVUpJNFFVdGdGUHFrd25TUXdENjlQcm9WeFFNQnR2YjJpaUtldERSd2ZOOEtCVGlPTzdaazZjQStub05MTXNDeU1vOHpmbjlITWZsbk1rQ3NMUzRPRDAxRFVCMzlSb2h4T2wweWhNUzRpaVIzVzZQYkxzekIzRnhjYlJDUVFoUkpDWktKQkt4V0N5VHllUnlHb0JVS3YweS94bUFUbGNwaTQrWHlXUWFqUWFBeitlYm1wd0VVRjVSRGtDbFVoVnFDM2dTbnArYml6NEhuTjhQd08vM1I1eEFnTXZOems1bWtrV1VDTURxNm5mQmR6ZzJCREN0VUFCd09sMi9mSWRBaWc0SUJvT1JLSWpuZVFWTmIzbTNpaStYaUVIcCt3enBHZWx1dC91bDBRZ2dFQWlVWFNtN2RlZjJ2WmFXdExTMGhZV3ZIK1krNVovTnk4bk5qZjVVU0NTU1NJdzQ0WERZNGRoUUtwWER3OE5paXFwdmJCd2RlVkYxb3dvQXU3YVdtbnJNMEtQZjN0NitWRkxjMU54OFB1L2M2TmlZU0NTS1Bza2V0MmQ1ZWRuajhVUWNyOWRyWDdlNzNadEN5ckpyVnFzMUhBNFRRcFpYVnJ4ZXIrQzdOOTBXaThWbXMrMGZDeXIycTRnQllvRC9BUEJ6QUk2Vk5xR1FQVXFuQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzEiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0IiwiY3JlZEJsb2IiLCJtaW5QaW5MZW5ndGgiXSwiYWFndWlkIjoiOTliZjQ2MTBlYzI2NDI1MmIzMWY3MzgwY2NkNTlkYjUiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInBpblV2QXV0aFRva2VuIjp0cnVlLCJlcCI6ZmFsc2UsImF1dGhuckNmZyI6dHJ1ZSwiY3JlZE1nbXQiOnRydWUsInNldE1pblBJTkxlbmd0aCI6dHJ1ZSwibWFrZUNyZWRVdk5vdFJxZCI6dHJ1ZSwiYWx3YXlzVXYiOmZhbHNlfSwibWF4TXNnU2l6ZSI6MTAyNCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMSwyXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMCwidHJhbnNwb3J0cyI6WyJuZmMiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV0sImZvcmNlUElOQ2hhbmdlIjpmYWxzZSwibWluUElOTGVuZ3RoIjo0LCJtYXhDcmVkQmxvYkxlbmd0aCI6MzIsIm1heFJQSURzRm9yU2V0TWluUElOTGVuZ3RoIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6Ik5PVF9GSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTExLTI0In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyMy0xMS0yNCJ9LHsiYWFndWlkIjoiYTFmNTJiZTUtZGZhYi00MzY0LWI1MWMtMmJkNDk2YjE0YTU2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJhMWY1MmJlNS1kZmFiLTQzNjQtYjUxYy0yYmQ0OTZiMTRhNTYiLCJkZXNjcmlwdGlvbiI6Ik9DVEFUQ08gRXpGaW5nZXIyIEZJRE8yIEFVVEhFTlRJQ0FUT1IiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJrby1LUiI6IuyYpe2DgOy9lCDsnbTsp4DtlZHqsbAyIEZJRE8yIOyduOymneq4sCBWIDEuMCIsImVuLVVTIjoiT0NUQVRDTyBFekZpbmdlcjIgRklETzIgQVVUSEVOVElDQVRPUiBWIDEuMCJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCIsImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbImFueSJdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRHREQ0NBcHlnQXdJQkFnSUJBVEFOQmdrcWhraUc5dzBCQVFzRkFEQnlNUXN3Q1FZRFZRUUdFd0pMVWpFWk1CY0dBMVVFQ2d3UVQwTlVRVlJEVHlCRFR5NHNJRXhVUkRFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFa01DSUdBMVVFQXd3YlQwTlVRVlJEVHlCU2IyOTBJRU5CSUVObGNuUnBabWxqWVhSbE1CNFhEVEl3TURJeE1UQTBNall3TTFvWERUSTJNREl3T1RBME1qWXdNMW93Y2pFTE1Ba0dBMVVFQmhNQ1MxSXhHVEFYQmdOVkJBb01FRTlEVkVGVVEwOGdRMDh1TENCTVZFUXhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhKREFpQmdOVkJBTU1HMDlEVkVGVVEwOGdVbTl2ZENCRFFTQkRaWEowYVdacFkyRjBaVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMWllhKzlZWkxKbjRGV2NrRG5ZL0VSb0N1TzNUQnRhMFczZjhSOVNZNWQ1c0JrMlFpdXBjaUkvbDdmd1BySDNGRGtlVlBYZWpNZStrVDBWb0pKZStOOUVNV2VyMC81UFhJUDk3bnJ1WWNyMER4YmhacGVzUUVlVThCZUlVdW5wTk5uRUpwb3hvSlR3b0RtdTgzWktrNG04ZzAvUGZwSndEaG1QQ0FxbTc5c0Z0UDhnN2xDOXFtczVURC82UE56KzJhZXdLWFRRQVIxb3BmaG5XRFVzSVp0dVVmRVJobEd3eFU3WCtoM29RMmtTR3c1aG9sZktTYjBnM3B3R1RjVFZOdmZVTVhIN0NhaVRxL0s3VC9qZEFDRCs5YU5qdGNkM1B5UWVyQThTYTJOMjhydmtOOFlmS29EUGc1Z0EzNzhPTkRWM0Jocmh0WThVaURrQmNUc1hBUUVDQXdFQUFhTlZNRk13RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVU9DbUszMTBHdTNxOURmWC9idmRwc2Y0R0k4VXdDd1lEVlIwUEJBUURBZ0gyTUJFR0NXQ0dTQUdHK0VJQkFRUUVBd0lBQnpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQW5EVGNabmVLL2gwUWI4c0Z4Z0ZTOEZhNWRqUW5TSlFVTUZaL2t6T3NQaDFEVkZERjRuREcvSGxVK2Q3S2FOaGFRN1hMdDd4QWpoekV5VHlIYU1INzZnSDA4cjMzTmRWWi80c01oOUdJTFU2YlNtSllPdGRWaTN6QjNwNjlibllaSEpWcXZKS1g1bEVzU3BuL29wS1lsdnRvMm4wLzRzNGF3SmgrcStCa3lWU1BUUk1YNkxmYm42SVJ1NGNiZVMwVzEzdHNRNVNicEFvOU5IMkZBVHpWTU1LU0dFZGlRbmZZeWdkV3Z1RENMVXRRRjF3R21HU1lzRVBGVFY2UEcxVlA1SFM0ZmhyQk5idXJpMzhOSVVvY2ZrcGZtT0l5K2hIWmdmdnBaem9yazFHdkYzUFpSSXRKblRUdjVVanEwcUQ4cm5yODFxd3ZHbFRDSklCdEVVbU53UT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVnQUFBQklDQVlBQUFCVjdiTkhBQUFTVlVsRVFWUjQydTJiQjFoVTU5TEhNV29TcjdsK1Z2YWNzNDFtVGRTclJvTllBQ2tMaW9vRlN4UTdnWWlpaUtKR0RkZ1ZMSFJFbGwyYXFJQmlqZUtOWGZGYVltS05IU203Q3hwajlQdGlqSVc1ODU1ekZwWmxGMWRGWS94NG4yZWVwU3k3NS94Mi9qUHp6cnlZbWRXdTJsVzdhbGZ0cWwyMXEzYTl3MnVEV2xwZmZ0MjdVZXlGK0thclRoNXV0dlRJMWNhaEJ3ci9aMTd1elVaemMwODJXckIvWThPbGViUE0xdCt3TTFQbWYvei9Bd3BBSFRObFVmc0d5VGZUV3NTZisxVzA2aGhZTE5vSDFuTzNnOFdNTEJCT1RnZHFRaEl3bytKQlBEUVN4SVBXQXUwVjg2U0pYK2FsQmt0UHpEWkx2V0grL3NMSmhMcjEwMVJUbXFYZGZDQktPZytTNkpNZ0RUc01sb3R5alFLUzlnOEhpZXRTRU51SGdOQitJVFFabTFwUU4rcm5rV2FoOE1GNzV6bjEwb3ZuQ3JLTG5vc3pyb0g0RlFDSmJlZUNxTk5NYU9HNDdObEhvY2NqelRJdmZmaitBRklXZG0yMnJlU2haSHNSdkM0Z3B0MDBNUC9pMitjZnJqaTc4TDN4cEk4MmFtSWt1WGRCSDVCNDlUSG9GSFVjK3NZZmh3R3hoNkZQV0M2MERzb0N4anVoV2tDTTFXUm8waS82RHpQNXJXN3ZCYUIvWkdtT1d2NzdsM0pBcmRLdlFQREIyM0RzdWhvS1ZDVlFyQzRCbFpwN3ZGMnNnVU9YQ21EZWhqem80cXNFaVd5WlFVQzBaRExVWDNKYThWNEFhcGhWOHIwV1VQdXRCZkR2YXhyUWFFcGVhRC9kS0lhSnNmdEI3TFNvQ2lDRzlvRUcwM2FmWnpQajMzMjU1MnAyaXZmZWhSWmJWS0E4WnhvY3JSSFBHaFY3Q0VROTVsY0I5UEcwN3k3ODdRR1ZsSlNNUEhXcjVIbXJuUnI0WkxNS3poZVV2QlFnWW9ldnFjRnlSRnhsaVZsT2dmb3J6eWIrcmVFVUZSVTF3QnM4U1c0eTdrY04vSE5qTVd5NldPNUJaV2lQMFg1SCt6KzBQOUNlR3dKMEVhRzJuSmFsQThnZkdnOU8rTjBzc2FETHUzTzNYUkxxTTY0S01lV203TnBDcG5RVHlKUmZtcnNvZkFXeXBPbm1zcVFnZ2FzaWtISko4c2V2eHdoY2tnYVl1eVQzbUJwMndQN21iUlc1ZVZDalJmK2dCb2RkaFhEeWxtYUhXbDA2UktWU3RTNHVMbTZHSUp1V2xwWmFxOVYzM0RTYTBqQjgvblZkUUtubjFVQ1BTS2hJODI2cm9hWHl5b0svVEY0QzE5U0dsQ3o1VThwVk1WYmdJbyttbk5ZZHBSeGpORlN2TlErcDdpditwTHN1THFNN2h3RGQ2VnMwOGhqNmpPcXkrQ0hWZGZsZHlqWmNROW10VlZPOW9sVk1uL2pTdG9OU3lucE56SUx4SVh0aGhTTHZUK2ZWeDZNRTBUL2xtcSsvWUdlV21WblgwUHZmdlh2M24ycDFTYUJLVS9ycjdpc2FzRjV5a0kxQmpPMDhhT1cvQ1dKTzNJWWlqV2JXMnl4MTZ6RDlFLzdCZW9aelVnTGxuSENKdGwvN21MRmJDc0t1ODBIWUtSaUVIV2FBc1AwTVlEcDk4NVR1dGxndDZCNjJsZTRaTVo5MmpCNUN1eVI5M3R3cHBSWHhzQlo5bFpTNVU2S2dXWjhVb2ZPVWJlMXpqMTIra2JubkhDeVhILzlkNnBhVVllNlVjSVhxcTN6QStPOTRKRjY0ZjRka3lYN3ZKaXVPU1N4Q0QzN01Wc2ZFbFBtTnpaSUxYVHR0dkg1Q09Ic1hNSU1pb2VYMGJBakl1UWluYjNFU3hkaTI1TTF6Q1EzOWdKRXBPcHZMbERHVTh6bzE0N0FhUDZtRklQNWlMb2k3emdaeGwyQVFkWmtGd200aFpYU1BzSXVVVS93aUFzUE1JYlNlcVcrQmtnbmhiK2lZOXNOb0laUGJDQndUQXN4ZDVVZm9vZWxQUk40YmdmYmJlcm5KL0gweERjSlBwOVpkZDIxZjNYVlg5elJjZkNUWksvTnk3cFpMR3NoWFZZcExaU2pSMFcrTXk2ZGVtUithdXlTNUNsemx1YlJ6N0NPaHczSVE5L29XeE9qR1lydDViTTFCSUFsN0xINkNIbktJY2wzdlRtVDNLdTkxNTg2ZFR4RE9qM2hUbHdHZ3Z2NTFOTWNQU05CbmZZYkFQdTZCZVIvMExqZmxaS1ovUm5OdGZFRVFnL1NETnI1ZU1ZbGJid1FPN1pyY0JRUHFic1kxOXFuSWFRV0lIUmR5bFdwdkJOUnJBUXRKMURNVTZENHgrWlNMM0l2Y0JONVlIYlFQME9yaXhUWEV3Q3BTcTlWdE1MQjJSQUNkOEdmdGk0cnUyT0QzZ3V2WHIzOUVuZ2M2QVJTZlk0T2U5QVBlN0NoakVoYzRKOW9LZWtRY296NWZXVWIxU2JpS1h1MU5QQlZqMFh3OVFJL3gvVWJVT0JpUlRONFV3YXloWlFsUHhESnVqeU54WGd3U1VxWDJRVWdPb1N3a29XUFk4OWFEVW5KM0hiZ28wMmcwNDlGVzQwWHRScnVFOWh1Zm5xdXJXNTZobGFDZFJ0dUVmeCtLWUR3Um5oMStuWW8yVnQrVGRETWxaUisza0c2MzRESFZlVGxZZWlTZjNKOTM5UmVkMTc3M1J1QUluSlcyS0tjZmhlN1JJT203RXFUdXk5azlEZ3ZKWlFsQ1dveVFGb0hRZVEwRWh1OHZ5eTlRM2NPTCtkTUlnSWY0cVY3REM4MUJyMWlKTnp3RnpZdEwwUnBIL0xrVG1nZitiZ3grUHh1L1hvZVBSOG5mOE9uN0lkcCtJaDNpY2Zxd2NuUFBOZlFJeUZrazdZaGViRGtUYk53U0lEcmoxUE9DUXRWbTRyVTFucDBvRjZVWEpaUC9KdmJnZHNkU2p6Q1FzcEJXZ05TdEFwTElaVFY0ei84T0NvdlVCcUVRYnlDQkVlWFM4c3daSXg1UXpjclB2OThZZ1hSSFVQUHd0VTd4bm5nSExROS9Gb0ZBWS9CeEc0bFgrSGhuWHRTaDIzVEwyYzhaZ1I5UXRxdWY0WDNFV3pnb1A2NVJPS1NJbzl6a1Q4U2VrU0R4WEFQU2dhdEFPb0NIMUU4TENRTzBiQ1YwSHBVQmw2OFZWc29VWEhEVlRMNTM3MTZqbXUyZlFSMFN0L0MxNHhITXIvaGVCZmo5M0tLaVg0VDR1M3JrOXc2aEIrc0pIT0ozTW93L01NMG5BZld2cFlBaFltZFQ5L1JHTlFJSEsxby95bDMrV0RRa211MnRTQWF2QmNrZ2hPUzVtb05VN2swcmdKSEZ3dXFVLytqQ0tjUUxua0FLdGpmYmFJUTZwSUxtWWhPNzFWQVJXV296bE1CZGFVdDFXdlluMDNSQ09TUnpWMFZXQzRmWVQxNHY1c2dVemdLM3BFZENMOXpnRFVkQVhwRmNFM3hJUkFVazRrMmtJZFV2SEt3SHBzQVBGL0o1T0tWWnhjWDNSRyszSXdzZjRBZlNud1BFZmtBL2srKzdlMlUyd094MmhzQmhJVFZEU0YzRHk5Q1RJbC81elJqblZBa0N5cWU5RW9ENU1nNkVJMklSVWd5SWgwVlZRRUp2MGtJU2UwUUEyUXJjTGxBOVJlMHZKUzcrRis3OExSSE9PVzAyeE91UmR4aVJzWjJXVE9jQUVUUDNCZHpHUEVWSXcxOHQ3cmdvRkpTbkhHanZCS0JIeFhPUVJuS1FSTU40YitJaEVXOFNlVVNCODlkYnl3cUxTOWI4bFhCMGF5WSs0N0VlSGJqcXdCUGFKcmdDRUJwdE1RTndRM3dMaTllWEd3T1JiWVBBWGZHWThrWkFZeE01U0tQWHNVMXdaaVR4SmkwazNwc0dSNEJvUURSWURVd3Q4Ri8yZmJOM3BYR0FjY2dlNFR3aGdDYUc1Z0p0amJ2NFpoV0FtR1lUVVdwaFFMa21oYjdVdmdvRFdESTFWTUZPQnFqeFBLUXg2eXNnbFV0T0YxSVV5UTYvTTI1SnJkK2RLUkY4UUFMM3Jkc3FzQnVmQ1l3SU01azV4cUhtRTh0QkVka0puT1dGakVOQ2M5TzhwMzlDYzd6Uk8vUzRaS0FuS2NzaFVWcElCaVVYeFVxT2RrL0U3S0FNZWNjNmtVNWI5bDE0d3ZTT0FvYjVDaGpLaDRQVWdvZUVYaVRvR1ZWRzZqeVRYcEMwS2lnUEpUQmZwUUw5RlE5cG9vS0ROQTRoalYxZlNYSUVFaXM1OUNhaFp4enhvanZtN3NuVzd3cWcyTXhUbE4yNHpmZnBkbk9BRVg3RlFhSVJrb0NIMUh3Q1VPMFhrdXRPTXVrRmNYZStnQjZTRE1LdjA0SHhTMFZRS1VEN0pDTWszcHZHNlhnVFFxTDFKRWQ3ck1mQXB6aFlRNFhZNnkydnpMcGszMGpaaHBVeEZsOERJL0ZEbWZucVFab0V0TTBzQkpSMHpxVFhwSkFrTXpJVlJQNFo3SVNTOFVzRHhwZUR4RWxPVVRrdTZVbE9PQ3dHcUw2SkdQaVUyWTBkbEkzL3l0WXUrYkNwWHBIUG1GWUIzQVJEQzBuc3kza1RnWVNTbzZVQnhJTWVtTlFjNysyVGZVNDRPZzNFVXplQ2FBcUJ0QUc5aVVBeUlya3hPcExUUWhvZUMxUy9SSHhUNVVuS1hkSHViYk1oQVJmZk81M3F0Zlk1MHhacm4xWlRnTEh4NXlCWklpUXBEMG5yVGRLcHhJUEtUQWxvZmNhSDdIMHFISjBPMG1tYlFSeXdpWVBrdjhHQTVCUUdKYWViNWVpQkNZRDd1SHVVaXlLWXRFbmVOQml5Q2FWa1NjTXdLMTJqYlplQzhMTkFZTnBPQTZiTlZJU0Vab09nckJHVXBZNDNFVWlXMDRnSC9XRkszUkErSi9JdzNsd2FXQVJtZ1hUNlpwQVFTTVNiQ0NTRGtxc215eUVrNGRBNG9Qc2xrckwrR2xxQTBDbWxHU2xFYTdSSDFUMnpBZTRaaDJEUmQ1eTJqM2dtN0RLUDYzMGpJT0duMDNsSUFSeWtsandrcmVUUW0rZzJ3UVRRVFJNQWxlUXBjODRDNDVrQ2xrSFpZRG1EUU1vRUNldE5GWkpqZU1reFBpK1FuRGJMWVNrZ0hJb2U1WkVBbEZ2U0EzVG5qYVRFcDl5VUZxOEtDNlhid3R4WkljT0VFQzF3WGw5TU82d0YwUmNMMk40M0dldUkvaFhFRHdnNFNFSXlCMnVMa0ZyemtGakorYk9RNkU1c0Z0dHFDcUM3WjNHektlMmZBbGFCVzhCcTVoYUVsSTNlcElYRVNVNmtMemt0SkZaeWlVWWt4NVVDb3FHa0hFQlkvUkxLS0RmNWJ3anJQQ2FHRkx6QXVRUmFjeGVGUFhwRFJ6TGRJQ1p3bFgrR2hhc2QxbGVlYk52RlJSbFB1Y3J6S09kMXY5QjlJcDhKZXk4RFVmY0YzSUNnMjJ3UWY4NE5DRVNkZVVnZGd6aElueEZJMHpsSTVaTHpaNzJKNmhrQlpCWm5DcUJuUmNVYUdCaTRBNlFUTjRGTmNBNEhDYjNKWW9ZeHlhVldTRzZpb3Fya2RDR041S3Z2OGcwdm1tY2tibE9pUU9pQlh0WTNGaGgzZks0YmxnK3lkV1cwTEw2TWRvMER4alVHR0pjb3RsTXBjbG9KSXNjbElPNGRVbmxBMFAwYkh0S2Npa2xLWjk2Yk9nWVpsaHp4cHJaQldFa24zaWNURWxNQVBTWDdsZzI3enVHbm5BcldzM0pZU05henRvS1Z2dVNxeTNJVFhwRGxSbFJVMzFWN1RGejdSTnBQMjdFMDNOWmxlOS8yUEtTZTNKQ0FoY1JPVW5oSVdtK3FSbktVN1hKbzY3VmhwNG1iTzY2UFFyekkxVDhISkpNeXdXYk85Z3BJck9TeVdNbEpkZU9TVm5LKzJpeFhXWEpWTjd3VjFiZDJMeWN4MEdQU2JldEtkTnE2WkVqQVFqSXdTZUhHVGQ4WWxaeW80NHh5eVRFZGdzRVNkdzBiZDUrTE5CWFFmbTE3WU0vaG44RnljQnBZenR3RzFnVFM3RzFnbzRVVWxGME95V0NXMDVZQ2s1UXZMQVhZdUdTa3gxUzFyWXVRWkJXUTJFbUtZOFVrcFJLa0twS2JWUzQ1Tmk1MUNBSzZkd1RNanprQ3hjVnFQMU9ubDkvcU50bFhLUEtBR1pvT1ZuTjJnUFhjSFJ3a1E1SkRTQldTU3kvUGN2clZONEZFdldERHE5dGpxdFRXN2NlMWRRMUxicUVSeWZIRHkyNDZrdU1oMFhZcm9HL0FOaWdvVkQvRCt1OHpVL3NuWGZtZUxndUlUQ1o4RnUwRDBhaU5ZRFYzSjFoL3M2T3k1SUk0eVVrRDlVb0JmejR1K1pHNFZEWExHWldjVG85Sk1yZzZ5UzJ2SWprSks3blFDc24xMUpmY25ITEpDZTBXZyszWVRYRG0vQzI4VDgxWnNvTXd0WDlTRDhFYzB2VWkwa3Z4bnI4SGhLTXl3R29lZ2JTVGc0VGVWQkdYc25YaUVwRmNScVVzUit0WDM2YjJtTmk0dExZcUpHT1MwOFlsQjIxY3FwcmxoRDJYUXFlUkcrRDREemY0Mlh6SjlKY3F3TlRxVXBrMm0ya3R2MEFGQVN2M1k4RzNBU3hubzl3SUtBT1NzeWpQY3J6a2pHNTRrNnBtT2QwTnI2N2todXBJVGh1WFdNbXQxSkhjVWgzSkxVSlFoaVhIMkllRGcwOFduUHpwcHZiZThsOTZGRVVtbEJpTE12V0hmc1dZMlZZcVRvRE5pQXlFa01ONTAxd2prcXV1K2piWVkwbzAybVBTYmV0V0tRVThqSlFDZXBJVDlWNklOVlEwcTRTTFZ3cTA5L1FVbmNIN2xmWTI1RkFCbVdrWkdobm5IcjBDam41YlFEUnVNd1p2bmJpa0s3a2dJNUw3V2pmTEtTdjFtR3BDY2hJRFdVN29GQTV0QmlYRDJyU1RvRkpwZEU5MnBCdWQ3WnNZc0IzNWFXVVZTRVJ5eStSNTBONTdFMGg4czZ0bXVabGJkYXB2QTFuT3ozQ1dvMDFvNjVhWEFwVWtGMVloT1RmT204U3U0V0RSTHdFbWhPN2xnM0dsZXpoVlVGRFE1TFdubGVRd0FiN1lJMk1uTUg2OG1BL0JFWWVnRFdZNWlVOG1XQVVUVDZwR2NsUDFzcHl2WHBaN1lmVWRyVk45VjVXY0JFc0JzVHYrRE1FTW03MEx2anQ4R1ZUcUtzZUZMNVdXbGxyVldDdUJuSjVBZDd4ZjNWRVZvdXVWV0RQMThNa0dNV1k3Qy85c0xDcHpqR2M1UXh0ZXZSNVRsVkpBWjhPckx6bnhnQWpjeDhWQU82OFVtTExpZXpodzRocDcyTlBBdFo0aVE4VWFiMFNSMHhSa2pQdWljOGkzVVhyZllRVWV1T29BZEVkWVZ0NGJRZXF6R1N5blpvRmxZSFViWHNOWmpqYlMreFo2b1ExQ0c3QU9Pb3hNZzFIemRrUFMxck53OVVZUllObzJjdFpJcytXMVpmV0NTU1hGWjdlbnBoemFKdlhUd2Y5Y2d6V3BKMkZzeUY3b05qRVRMRWFrZzJUMEJnendhSlBRaTN3UmtKOTJINWZHVFZJbWthNEFRaHFQM3VTTmt2c1NiWmdjbUNGeXpHUkowSFo0R25nR2JZZVF1S093N2Z1TCtpZEpETmtEY3RJMVAvOHQvTGNoUDRnYmlxQ3V2T3dwZDJMa1prZ1dWT1NjeFNCL0hHYXNQb2hCTkJlR3o5a05nMmJ1aElGQk8vRG1kNEJYOEM0WXMyQVBLNWVRK0tNUXQrazA1Q0FNY2pDaVdHWHl2eUNRRTJxNzNzQmhLZE1PTVpIakpYZ0J0MThGbENFak1ZUEl3NGhFWHNhSWgrZmg5ZlY5clRSZVE3UHZGaGowQXZqNDlMeW1ZTDBHbU4zazJCNDVBUG91VFhlSjlPcVNnd0xrbUFudlZXVnZDY29UbFBzWnRBWGtTSi9adTc1STdYVC8vdjNHcVB2ZTVBUTdYdmdSL3FUcWt4b0NRdjVmNHpaMzhKTTk5Tm51clFUZk55MUR0RzVrMzBNT1ZxRmxjT0EwVi9uRGw0OTA1RWxrOHI5OFovTThQbmNmOFVvRU1vY2NBU1pBeVBscXM5cFZ1MnBYN2FwZHRhdDIxYTdhOVViWGZ3RnZVRUVINFlhcWxBQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiYTFmNTJiZTVkZmFiNDM2NGI1MWMyYmQ0OTZiMTRhNTYiLCJvcHRpb25zIjp7InV2Ijp0cnVlfSwiZmlybXdhcmVWZXJzaW9uIjo1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDMtMjAiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6Ik9DVEFUQ08gRXpGaW5nZXIyIEZJRE8yIEFVVEhFTlRJQ0FUT1IiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIwMDMyMDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDMtMjAifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA3LTI3In0seyJhYWd1aWQiOiJiYTg2ZGM1Ni02MzVmLTQxNDEtYWVmNi0wMDIyN2IxYjlhZjYiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImJhODZkYzU2LTYzNWYtNDE0MS1hZWY2LTAwMjI3YjFiOWFmNiIsImRlc2NyaXB0aW9uIjoiVHJ1VSBXaW5kb3dzIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbInNvZnR3YXJlIl0sImNyeXB0b1N0cmVuZ3RoIjoyNTYsImF0dGFjaG1lbnRIaW50IjpbImludGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDU3pDQ0FmS2dBd0lCQWdJVVczWEs4eXl3YkFXbGlnbGl4SUY2M2R2cVl5OHdDZ1lJS29aSXpqMEVBd0l3ZkRFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRU52Ykc5eVlXUnZNUTh3RFFZRFZRUUhEQVpFWlc1MlpYSXhFekFSQmdOVkJBb01DbFJ5ZFZVc0lFbHVZeTR4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4RURBT0JnTlZCQU1NQjNSeWRYVXVZV2t3SUJjTk1qTXhNVEF6TWpBek5qVXhXaGdQTWpBMU16RXdNall5TURNMk5URmFNSHd4Q3pBSkJnTlZCQVlUQWxWVE1SRXdEd1lEVlFRSURBaERiMnh2Y21Ga2J6RVBNQTBHQTFVRUJ3d0dSR1Z1ZG1WeU1STXdFUVlEVlFRS0RBcFVjblZWTENCSmJtTXVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUkF3RGdZRFZRUUREQWQwY25WMUxtRnBNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVOQXZidGNjTXI3ai9TUldtcUlFWlRSV05KeWo2bXNZcjVsR2VBZ2RTR3lDOU8wMzU2UkllY3VhVmlPcXowRHhnUzFmLzVLUGJacDF0MHlEMmZWUlg5Nk5RTUU0d0hRWURWUjBPQkJZRUZBNXRMMTBnODh0MnFYbFBsaElTSTJkSXpsYVZNQjhHQTFVZEl3UVlNQmFBRkE1dEwxMGc4OHQycVhsUGxoSVNJMmRJemxhVk1Bd0dBMVVkRXdFQi93UUNNQUF3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnWGZ1dmpzcCs0djVpR09xbmdVZ09nMWhtYmdGUEZNZ0lqeVd4Q0txdy9kOENJRmltTE5YTERJd0Erb0liUDF5T2ZxRTh4azZxNy80TFdPVllrUkFMb0JDMiJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUJBQUFBQVFBQ0FZQUFBQi9IU3VEQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBRjBLU1VSQlZIZ0I3TjE5ako3bGZTZjZDMnppQVk5anh1QVpEMmFoWUNmbm5PaWtvRVE1U3VWSVNjN21sS3BObFFybmp6UlVjYzVxU1Z1emxUWndDbG1wTVEzMGFCT3pCYTFXSGdvNTJ0V01OalE2MGxpTkRwRktUcnB0VnBtMjJpb1JKTkxaczRrZFVtTHd2TmdlZzJjY0R5OW1uOTlqaGhqamwzbDVudWUrci92NmZLUlowMDFLc1ptNW4vdjZYcitYeXo3dzBWOS9QUUVBQUFDTmRua0NBQUFBR2s4QUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVVRQUFBQUFFQUJCQUFBQUFCUUFBRUFBQUFBRkVBQUFBQUFBQVZZbTRES2ZlYWFJMmxYNndzQW9Fbm1UbCtleG1jM3BmMnRyL2hyb0ZxWGZlQ2p2LzU2QWlxMzVZcFgya0hBYmU5OE1RRUE1TzZwRnplbXNXUFhwc2xYcmtoQVBRZ0FvR2EycjF0SVg3cnVVRHNRQUFESXpkTW5yMHBqUjY5TnovejhxZ1RVaXdBQWFpb3FBYUlpUUJBQUFPUWdTdnhIcG9mU1V5OXRURUE5bVFFQU5SVWZucEdjLzJvckNEQWZBQUNvSzMzK2tBOFZBSkFCOHdFQWdEcUtjditIcG9iMStVTW1CQUNRa1IzclQ2VGRnOVBhQWdDQVNoMDQxWmRHWmdiMStVTm10QUJBUmlibU42U0paemVZRHdBQVZDSksvRWVQYms3N1p3Y1NrQjhCQUdSb2NUNkF0Z0FBb0ZlaXp6K20rK3Z6aDN4cEFZRE1SUlhBN3MzVGFVZi9pUVFBMEduUjUvL296R0E2c05DWGdMd0pBS0FodEFVQUFKMFVnLzMyVGc3cjg0Y0dFUUJBdzBRSXNIUGdXT3EvL0hRQ0FGZ3VhLzJndVFRQTBFRFdCZ0lBSy9IVWl4dlR5TXlRZ3o4MGxBQUFHaXlDZ0QrOS9qbHRBUURBUlVXZmZ3ejRVKzRQelNZQWdBS1lEd0FBbkUvMCtjZkJQellNQWMxbkRTQVVJRDdVSitiNjArMERzMmxYS3dnQUFNcW16eC9LcEFJQUNtTStBQUNVTFM0Rm9zOC9iditCc2dnQW9GQzNYSGt5M2J2bHNMWUFBQ2lFUG45QUFBQ0ZNeDhBQUpvdFN2eEhqMjVPKzJjSEVsQTJNd0NnY0RFZklHNENicjk2TnUwY09KWUFnT1lZYmQzNDYvTUhGcWtBQU41a1BnQUFORU9VK3o4ME5helBIM2dMRlFEQW0rSWxZZS9rY0hxbTlkS2dMUUFBOHZQbVo3aytmK0E4VkFBQUY3VHo2dGwwKzhBeFFRQUExTnppV3I4WThnZHdJU29BZ0FzYVB6NlFKdWI3dFFVQVFJMHRIdnoxK1FPWG9nSUFXSktvQXZqRG9jUHAxcXRPSmdDZ2V0YjZBY3NsQUFDV3hkcEFBS2hXOVBtUFRBKzFxL1FBbGtNQUFLeEloQUN4TnJELzh0TUpBT2kreFQ1L2EvMkFsUklBQUN0bWJTQUE5TVpUTDI1TVk4ZXV0ZFlQV0JVQkFMQnFFUVQ4NmZYUGFRc0FnQTdUNXc5MGtnQUE2Qmp6QVFDZ002TEVQL3I4bjNwcFl3TG9GR3NBZ1k2Smw1U0p1ZjUwKzhCczJ0VUtBZ0NBNWRIbkQzU1RDZ0NnSzh3SEFJRGxpWEwvaDZhRzlma0RYU01BQUxwcXgvb1RhZmZndExZQUFMaUFBNmY2MHNqTW9ENS9vT3UwQUFCZE5URy9JVTA4dThGOEFBQTRSNVQ0ang3ZG5QYlBEaVNBWGhBQUFEMFI4d0hpWmtOYkFBQ2tkcDkvVFBmWDV3LzBraFlBb09laUNtRDM1dW0wby85RUFvQ1NSSi8vb3pPRDZjQkNYd0xvTlFFQVVCbHRBUUNVSWdiNzdaMGMxdWNQVkVvQUFGUnVzUzFBRUFCQTAxanJCOVNKQUFDb0JXc0RBV2lhcDE3Y21FWm1oaHo4Z2RvUUFBQzFFa0hBbDY0N2xMYXZXMGdBa0tQbzg0OEJmOHI5Z2JvUkFBQzFaRDRBQUxtSlB2ODQrTWZtRzRBNkVnQUF0Ullod0s3V0Z3RFVsVDUvSUJjQ0FLRDJ6QWNBb0s0bTV2cmJmZjV4K3c5UWR3SUFJQnN4RnlEbUEyZ0xBS0JxK3Z5QkhBa0FnT3lZRHdCQVZhTEVmL1RvNXJSL2RpQUI1R1p0QXNoTURGZUtHNWRmYlFVQjVnTUEwQ3VqclJ0L2ZmNUF6bFFBQUZrekh3Q0Fib3R5LzRlbWh2WDVBOWxUQVFCa0xWN0c5azRPcDJkYUwyZmFBZ0RvcERjL1kvVDVBdzJoQWdCb0ZQTUJBRml0eGJWK01lUVBvRWxVQUFDTnNqZ2ZRRnNBQUN1eGVQRFg1dzgwa1FvQW9MR2lDbUQzNXVtMG8vOUVBb0NMc2RZUEtJRUFBR2c4YlFFQVhFajArWTlNRDZXSitmNEUwSFFDQUtBWUVRTHNIRGlXK2k4L25RQW8yMktmdjdWK1FFa0VBRUJSckEwRTRLa1hONmF4WTlkYTZ3Y1VSd0FBRkNtQ2dEKzkvamx0QVFBRjBlY1BsRTRBQUJUTmZBQ0E1b3NTLytqemowMHhBQ1d6QmhBb1dyd01Uc3oxcDlzSFp0T3VWaEFBUUhQbzh3ZDRLeFVBQUc4d0h3Q2dPYUxjLzZHcFlYMytBR2NSQUFDYzQ1WXJUNlo3dHh6V0ZnQ1FvVGp3NzUwYzF1Y1BjQjRDQUlBTE1COEFJQjlSNGo5NmRIUGFQenVRQURnL013QUFMaURtQThRTjB1MVh6NmFkQThjU0FQVVVmZjR4M1YrZlA4REZxUUFBV0FMekFRRHFKL3I4SDUwWlRBY1craElBbDZZQ0FHQUozdXdwYmIxc2Fnc0FxSlkrZjRDVlVRRUFzQUk3cjU1TnR3OGNFd1FBOUpDMWZnQ3Jvd0lBWUFYR2p3K2tpZmwrYlFFQVBmTFVpeHZUeU15UWd6L0FLcWdBQUZpbHFBTDQwbldIMHZaMUN3bUF6b28rL3hqd3A5d2ZZUFVFQUFBZFltMGdRT2RFbjM4Yy9HTWpDd0NkSVFBQTZMQUlBWGExdmdCWVBuMytBTjBqQUFEb0Ftc0RBWll2eXYwZm1ocHUzLzREMEhrQ0FJQXVpaURnVDY5L1Rsc0F3RVhvOHdmb0RRRUFRQStZRHdEd2RsSGlQM3AwYzlvL081QUE2RDVyQUFGNklJWll4YzNXcjdhQ0FQTUJBRks3eno5dS9mWDVBL1NPQ2dDQUhqTWZBQ2laUG4rQTZnZ0FBQ3F5WS8ySnRIdHdXbHNBVUlRNDhPK2RITmJuRDFBaExRQUFGWm1ZMzVBbW50MWdQZ0RRYUl0ci9hTGNINEJxQ1FBQUtyWTRIMEJiQU5BMCt2d0I2a1VMQUVDTlJCWEE3czNUYVVmL2lRU1FLMnY5QU9wSkFBQlFROW9DZ0J4Rm4vL0k5RkNhbU85UEFOU1BBQUNneGhiYkFnUUJRSjB0OXZudmIzMHA5d2VvTHdFQVFNMVpHd2pVMlZNdmJreGp4NjYxMWc4Z0F3SUFnRXhFRVBDbDZ3Nmw3ZXNXRWtEVjlQa0Q1RWNBQUpBWjh3R0FLa1dKLytqUnpXbi83RUFDSUM4Q0FJQk1SUWl3cS9VRjBDdWpyUnQvZmY0QStSSUFBR1RNZkFDZ0Y2TGMvNkdwWVgzK0FKa1RBQUEwUU13RmlQa0EyZ0tBVG9vRC85N0pZWDMrQUtrWkJBQUFEV0krQU5BSit2d0JtbWx0QXFBeG5ucHBZL3VtN3Zhclo5UE9nV01KWUxuR1p6ZTFwL3ZyOHdkb0hoVUFBQTFsUGdDd0hOSG4vK2pNWURxdzBKY0FhQ1lWQUFBTjlXYnZidXVsWGxzQWNDSDYvQUhLb1FJQW9CQTdyNTVOdHc4Y0V3UUFiVkhpSCtYKzF2b0JsRU1GQUVBaHhvOFBwSW41Zm0wQlFIcnF4WTFwWkdiSXdSK2dNQ29BQUFvVVZRQi9PSFE0M1hyVnlRU1VJL3I4WThDZmNuK0FNZ2tBQUFwbWJTQ1VJVzc2UjZhSDJwdENBQ2lYQUFDQWRnZ1Fhd1A3THorZGdPYlE1dy9BMlFRQUFMUlpHd2pORXVYK0QwME50NmY4QTBBUUFBRHdGaEVFL09uMXoya0xnRXdkT05XWFJtWUc5ZmtEOERZQ0FBRE95M3dBeUV1VStJOGUzWnoyenc0a0FEZ2Zhd0FCT0s4WUZqWXgxNTl1SDVoTnUxcEJBRkJmMGVjZjAvMzErUU53TVNvQUFMZ2s4d0dnbnZUNUE3QWNBZ0FBbHV5V0swK21lN2NjMWhZQUZZc0QvOTdKWVgzK0FDeUxBQUNBWlRNZkFLcXh1Tll2eXYwQllMbk1BQUJnMldJK1FOdzgzbjcxYk5vNWNDd0IzYWZQSDREVlVnRUF3S3FZRHdEZEZYMytjZkJYN2cvQWFxa0FBR0JWM3V4RmJoMVN0QVZBNThUUDFzajBVSnFZNzA4QTBBa3FBQURvcUoxWHo2YmJCNDRKQW1DRkZ2djg5N2UrbFBzRDBFaytWYWlkS0NNZWNuQ0FiSTBmSDBqM0hMcWhQU2NBV0o2SnVmNzB1Lzk0azE1L3lGaTh4MnFMbzY1OHNsQTdVZkw0K0kwL1RidXVPWktBUEMyMkJkeng3TFowWUdGZEFpNHUrdnp2L3RrTmFjOEwxN2QvZm9EOHJMLzhkUHY5OWZFYm56V3pnOXBhcy9XbWQvMXhnaHFaZXZXS3RHbk5hK20zTngxdHA2ZnpwOWVrZ3d0OUNjalBYT3ZuOThrWEI5SlU2MEN6YmQxQzZsOXpPZ0cvRUxmOFh6MHltUDd0OUpiMjV4K1FweDNyNTlJRFd3K2xIZjF6NmE5ZmVxY3FPR3JMREFCcXFmL3kxOUxYYmo3WSt2WE1ZU0ZLSXZmTkRMVVBFVUMrWWtpZzZoNDRZL1RvdGZyOElYTzNYSFV5N2RwMHBQMXJpQXFlYUlOVHlVTmRxUUNnbGw1Ky9mTDBqc3RlVDdlKzhUQzk0UjB2cDUwRHMybkwybGZTZ1pmNzJsVUJRSDZpSlBKYnJWdVJxQVRZdm00aFFZbWkzRDhPQ0JOekcxcWZkNWNsSUQ5Ujd2KzVhMmZTdnh5YWZNdlEyOUZqbTlNL3pLOVBVRmNxQUtpMXI5MTA4RzJUeENOUmplRklTcXNnYnhFQWZPbTZRN1lGVUl3M1YyYnFEWWFzUlNWYmJMdFpyRlJkRkQvak1mc0c2a3dBUUszZGN1WEo5UEEvZWU2OC8xbDdQL0xNWVBzR0JjaFh6UHFJMWdCQkFFMFZKZjZqUnplbi9iTURDY2hYbFBuZk8zVDRncDlYRWZDNW9LTHV0QUJRYXpFUTZkWldDSEMrQjIyVUVIOTB3d2x0QVpDNUdQTDV0L01iMmdNREY5dCtvQ25HWnplbCsxKzQzcTAvWkN6VytqMTQzZlB0bS84TERiTjk2c1dOYWV6WXRRbnFUZ1VBdFJlSC8yZ0Z1SlJvQy9qTFZ1cHFVQ0RrSzM3ZW94ckEvbVJ5RjMzK2o4NE1wZ08yMkVDMm9zLy9zMitVKzE5S2xQNGIvRWNPVkFCUWUzRXJHRDFXNzdueTV4Zjk3MFZaVnF4ZXNUWVE4aFUvNzlIV2MvRFV1dlEvWFhuSzJrQ3lFd2VBUGEwYi83Z0pQUGJhMmdUa2FXZnIwQjlyL1c1WlFtVmFWUHI4OVlsM0pzaUJDZ0N5Y081YXdFczU4d0syVlJBQW1UTWZnRnhFbjM4Y0FxejFnN3pGZ1gvM3RkTnBlOStwSmYzM3JmMGpOeW9BeUVLc0JYeWw5VUwxZ2ZYelMvcnZ4NjNoYjE1OTNId0F5TnppZkFCckE2bXo2UDM5VjgvZmtQN2g1SHByL1NCVFovZjViMXI3NnBMLzkwWm1oc3o0SUNzcUFNaks0emMrbTdhdDRCQVE4d0ZHanhyTUFqbUxLb0RkbTZmVGp2NFRDZW9nK3Z6ajg4WExQK1FyK3Z3L09YRHN2R3Y5THNYYVAzSWtBQ0FyRjFzTGVDbnhrSTRYTmV0WklHL2FBcWhhbFBpUFRBLzVQSUhNeGVmSjdzR3BaUi84RjkzOXN4c0VnR1JIQUVCMkhyNyt1U1VOWkxtUUF3dnIyZ09hYkF1QXZDMXVDeEFFMEN2Ni9LRVo0ajF5MTZZanEzcWZqTmFmdlZQRENYSWpBQ0E3OGJMLzJJM1Byaml0WFJRUDd0Rmoxd29DSUdQV0J0SXJVZTcvVU90bDM2QXZ5RmVVKzkvVnV2SHZ4R2VHdFgva3loQkFzaE5yd3Q1eDJldnAxbFdrdG1GNzMwSjdiZUJsbDEyVy91dXBLeE9RbjhXMWdkOTZhV1A3Sm1mVDJ0Y1NkTktCVTMzcFR3NWYxMTdyTjJlZ0xHUXBEdjZmM25RMC9kRjF6NmYzTEhHNi84WEVYS240N0lFY3FRQWdTOHRkQzNncDVnTkFNNWdQUUtkRWlmL28wYzFwLyt4QUF2SVY0ZkM5UTRjNzlya1E3NHkvKzQ4M2FRTWlXeW9BeUZLc0JaeDlkVzM3QnI4VFlzVlkvTDJzRFlTOHhkckEvY2MzdGY5NnRWVkNsQ3Y2L085LzRYckR2U0JqMjlhZFNsOGNmcUc5MWkvZTh6b2wxdjZwSENWbktnREkybW9IQWw2SStRQ1FQL01CV0M1OS9wQy9LUGYvYk92WkgydjlPczNhUDVwQUFFRFdWck1XOEZLMEJVQXpiRisza0w1MDNTRnRBVnhRUE8vM1RnNjc4WWZNN1d3ZCtpUDQ3VlNMNkxrTS9xTUp0QUNRdGFsWHIyaS8xTWNMZnFjdHRnWEU3ZUhCbC90VUEwQ21qcjIydHQwV0VEL0QyMXJQaWs2V2dwSzM2T0g5ODJQWHRNdjk0L01FeUZOVWcwWlY2RWMzbkdnUGl1NkdxQTUxS1VRVHFBQWdlNTFhQzNncDJnSWdmL0c4dVAzcTJmWXRFV1dMUHYrbzhqTElDL0kxMUhxbTN6ZDB1Q3Z0b0dlTDUwUU0vblA3VHhPb0FDQjduVm9MZUNteE5uRG53R3k2TEowWk5QYnk2NWNsSUMveHZQaUhrK3ZiYXdPakVxQWIxVVBVVy9UNVI3bi9reTllN1RrT21WcGM2L2ZBZGMvM3BMMHJLb1dzL2FNcFZBRFFDTEVXOExFYmY5cXpIbC96QWFBWnJBMHNSenkzUjZhSDBzUjhmd0x5MWUwKy8zTVovRWZUQ0FCb2pCM3JUNlFIdGo2ZmVpaytGTzQrZElPMkFNamN6cXRuMnhPakJRSE5FNlc3VWU2L3YvV2wzQi95RldYK3V6WWQ2WHE1LzdtaVlzaUZEMDBpQUtCUnVyVVc4RkxNQjREOFdSdllQQk56L2UyZDNmcDJJVi9SNTMvWDVxbjJZT1plKzI3ckdSSkRRcUZKQkFBMFNqZlhBbDVLOUJidm54MUlvMGV2VFVDK0lnajR3NkhEWFo4clF2ZEVuMyswYVZuckIvbUtQdjlQRGh4clYyZjFxdHovWE5iKzBVU0dBTklvc2NZcFBpVGVjK1hQVTYvRklNS29Qb2pidy9sV0dCQ0RBb0g4UkpnWFF3S3REY3hQbFBoLzljaGcrcmZUVzZ6MWc0enRXRCtYSHRoNnFIM3IzNjIxZnBkaTdSOU5wUUtBeG9tQmdGKzcrV0JsYWZHaVoxbzNVRitaR3RZV0FKbUx0b0NkRmQ1QXNUUlJmYVhQSC9KV1ZaLy91ZUxXLzU1RE43ajlwNUZVQU5BNEw3OStlVS9XQWw1S2xCSEgyc0F0YTE5SkIxN3VhMWNGQVBtSk12Sy9PZkZPYXdOcktzcjk0MFU5Vm5SWjZ3ZDVpbkwvejEwN2svN2wwR1F0aHJIRzdCQXRSRFNWQ2dBYTYyczNIYXpOUk85SWtQY2YzNVRHWndjU2tLOTRwdnpwOWMvWkZsQUQ4VnlONmR4ZTBpRnZ1NjQ1VW1tZi83bXMvYVBwVkFEUVdOR0RmOXZHZWt6empwdkRENnlmTng4QU10Y2U5dGtLODh3SHFNNWluLy8vZWZnNmZmNlFzU2p6aisxTlZmYjVuMC9jL250UG84a0VBRFJXdkJqZWV1WEpXdDNVeFdFaFB1aTBCVURlNHVVd0JnVkd5NUZ0QWIwelBydXB2WkxMclQva0s5YjZQWGpkOCsyYi83cUZxREg0Yit5WWJVNDBteFlBR2kwTy85RUtVRmZSRWpEK3htMGlrS2Q0enNTZ3dLandvVHVpei8vUm1jRjB3SzBjWkN2Ni9ELzdScmwvWFZuN1J3bFVBTkJvVWE1YjFWckFwWGpQbGFmYUZRSGFBaUJmOFp5SkFYU3grU05LV3JVRmRFNjhpTzlwM2ZqSGpkeXgxOVltSUUreFNTWFcrbFU5M2Y5aW9zTG9yMCs4TTBIVHFRQ2c4ZXF5RnZCU3pyem9iaFVFUU9haUVpQXFBZ3dLWExubzg0K1hjV3Y5SUc5eDROOTk3WFRhM25jcTFabTFmNVJFQlFDTkZ6MjZyN1JlSUdNSVg1M0ZyZUZ2WG4zY2ZBRElYSVI0Znp1L3dkckFGWW9lM0gvMS9BM3BIMDZ1dDlZUE1uVjJuLyttdGErbXVyUDJqNUtvQUtBWWo5LzRiSHRxZHk3R2psNmJSbzhhUkFNNU14OWc2YUxQUDU1N1hzSWhYOUhuLzhtQlk3VmE2M2NwMXY1UkdnRUF4YmpseXBQcDRYL3lYTXBKZkNqRkMvRlRMMjFNUUw2MEJWeFlsUGlQVEE5NXprSG00am0zZTNBcW00UC9vcy85NHk5cHY2UW9BZ0NLRXZ0bTZ6eUE1a0lPTEt4ckQ4S3lMUUR5dHZQcTJmYk5tQ0JBbno4MFJieFg3ZHAwSk12M3EyZzUyanMxbktBa0FnQ0tFaS9kajkzNGJIYnA5S0w0b0JvOWRxMGdBREttTGVCTXVmOURyWmR1QTdjZ1g5SG52eXZ6WjVtMWY1VElFRUNLRXV1NjNuSFo2K25XREZQcXNMMXZvYjAyY01PYTAvcGtJVk9MYXdPLzlkTEc5bzNacHJXdnBWSWNPTldYL3VUd2RlMjFmbk1HblVLV29zLy8wNXVPcG51M0hFN3ZxZmwwLzR1Sk9VdnhMSWJTcUFDZ09MbXNCYndVOHdHZ0dVcVlEeEFsL3FOSE42Zjlzd01KeUZlRWx2Y09IYzcrZVdYd0h5VlRBVUJ4WWkzZzdLdHIyemZwT1lzVlkvRjcyTDd1VlByL1RsMXBiU0JrS29aUDdUKytxZjNYdVZZblhVejArZC8vd3ZXcWxpQmpjZkMvcjNYd2o1TC9lUC9JWGF6OU0vaVBVcWtBb0ZpNURnUzhFUE1CSUg5Tm1nK2d6eC95RitYK24yMDlrMko0YVZORUs5THZQdmRMQ1VvbEFLQllPYTRGdkJSdEFkQU0yOWN0cEM5ZGR5akxNdHQ0RHUyZEhIYmpENW5iOWNiQlAvZVd5WE1aL0VmcHRBQlFyS2xYcjJpL1hNZUxkbE1zdGdYRTdXSDgvbjcyOHJvRTVPZllhMnZiYlFGUjBiT3Q5WXpLb2VRMit2ei8vTmcxNmFISjY5TFBYbmxIQXZJVTFaRlJKUm52RXpFNHVVbWlXdElsQ2FWVEFVRFJtaklROEVLMEJVRCtJcWo4MVZhb0Y3ZHhkUlY5L2xGOUZDRUFrS2RZNnhkOS9rMXFqenhiM1ByZmMrZ0d0LzhVVHdVQVJZdUJnRG12QmJ5VVdCdTRjMkEyWGRiNjY4bFhyekFvRURJVTYvS2luRDdXQmtZbFFKMnFscUxQUDhyOW4zeng2dGJ6OUxJRTVHZHhyZDhEMXozZjZHMGs0OGMzV2ZzSFNRVUF0S3NBSHJ2eHA0MyswQXZtQTBBejdGaC9JdTBlbks3MG1lVjVBczJ3YytCWWUvQm9VeXNoRjFuN0I3OGdBSURVeklHQUZ4SWZnbnRlMkdyOURXUXVabjNFaTNzdmc0QW84WTl5Ly8ydEwrWCtrSzhvODkrMTZVaGp5LzNQRlpWS0FrczRRd3NBcERNREFXOXRoUUJOcndJSVVVTDhtMWNmVDF2V3ZwSU92TnluTFFBeUZTSGUzODV2NkZsYndNUmNmN3IvaGV2YkpiVEsvU0ZQN1Q3L0xZZlRuZGZPRlBIT0U3N2JlbmI5WDBjR0UzQ0dDZ0I0UTBsVkFHZUxNdDdSMWhlUXIzaVIzNzE1T3Uzb1A1RTZMZnI4NHpsaHJSL2tLL3I4UHpsd3JKRnIvUzdGMmo5NEt4VUE4SWFvQW9nUHhmZGMrZk5Va2lqL2kxTGlxQVRRRmdCNWlrR0JmMzNpblIxZEd4Z2wvbDl0M1pyOTIra3Q3ZWNqa0tmNGpQK2o0UmNhdWRidlVxejlnN2RUQVFCbmFmcGF3RXM1c0xBdTdYbmhlbXNESVhNeEcyRG5LbTc2b2lwSW56L2tyYlErLzNOWit3Zm5wd0lBenRMMHRZQ1hzbW50YSsyMWdlWURRTjZpWFA5dlRyeHoyZk1Cb3R3L1hwajErVU8rb3R6LzgwT1Q2YTdOMDhYMCtaL1B5TXlRMWlVNER4VUFjQjVmdStsZzBSK2FJUkx6L2NjM3BmSFpnUVRrSzU1bGYzcjljeGQ5cHNYUGUweko5cklNK1NxNXovOWMxdjdCaFFrQTREeEtIUWg0UHZaOVF6T2NiMjFnbFBpUEh0MmM5Z3Y2SUd0UjVuL3YwT0hpTHk4VzdYbisralF4MzUrQXQ5TUNBT2RSMGxyQVM0a1M0aGdjcEMwQThoWkRQcU9xSjBTYjAvanNwdlphUDdmK2tLOXQ2MDZsTHc2L2tIYTF3cjFPRFA5c2doajg5L1haYXhKd2Zpb0E0QUxpOEIrdEFMeFZ0QVNNdHc0UkJnVkN2cUk4MklBL3lGZVUrMysyZGVpUGNuL2V5dG8vdURnVkFIQUJjMi9jZEpjNkVQQkMzblBscVhaRmdMV0JrQzhEL2lCZnNlSGpnYTJIaXAzdWZ6R3h3U1NHbUFJWEp2NkhpNGkrV0xka2J4ZlZFZmR1T2R5dWtQQUNBZ0RkRjUrM2o5M3cwN1I3ODNUeFEvN09KMjc5djJWZUVWeVNDZ0M0aUZnTCtFb3JBUGpBK3ZuRTIwVy9ZUXdXTXg4QUFMcGpxQlc2UDNqZDgrMCsvMDFyWDAyY243Vi9zRFN1TnVFU3hvOFBwR2RPK2tDNW1OczJ2cGlldU9uZ21TRkViaVVBWU5XaXp6OCtWeCsvOFZuVmRwY1F0LysyRmNIU0NBQmdDYUtuakV1TEZXT1B0VjVVb2lvQUFGaVorQng5NHVZRDdjOVZ3ZnFsN1hsaGF3S1dSZ0FBU3hBbFpSTno5c2t1eGRuekFZYXNVUVNBSll1Yi9vZXZmNjc5T2VyZ3Z6U3g5czlRWWxpNnRRbFlrdWd0aXc5bUg4aExFMEZBdEFYRUIvUG9zV3V0RFFTQUM0akFQTXI5VmRBdDM5Z3hWWnF3SElZQXdoTEZXc0IzWFBhNnRZREx0TDF2SWQyMjhhVzBydlZuWnpnUEFQeEM5UGwvZXRQUjlvMy9lL3BPSlpiSDJqOVlQaTBBc0F5eEZuRFNUZmF5OVYvK1dydVBNZG9DM0c0QVFFbzcxcysxQi96cDgxK1plQjhiTTZNSmxrMEFBTXNRVlFBK2JGWnVjVDVBOURlYUR3QkFpUmI3L0IvWWVxajl1Y2pLZUIrRGxSRUF3RExGbWhsckFWY25YbjVpUHNDOVE0Y0ZBUUFVSWNyOTc5bzgzVDc4Vyt1M09nZE85Vm43Qnlza0FJQVZzQmF3TTI3YitHTDdSV2pud0d3Q2dLYUtBWCt4MXUvMmdXT0oxYnYvc0xWL3NGSUNBRmlCR0dZbmVlNk1LSC9jdlhuS2ZBQUFHaWR1K3VQelRaOS81OFIySWZPWVlPV3NBWVFWR3BrZVREdjZUL2hBNzVERitRQzNYSG5TMmtBQXNoYnRiZmNOSFZicTMySHR3WC9XL3NHcXFBQ0FGWXFCZ09Pem14S2RGVzBCTVI4Z3FnTE1Cd0FnSjR0OS92RTU1dkRmZVZGOTZmWWZWa2NBQUt0Z0xXRDN4RnlBbUErZ0xRQ0FIT3djT0tiUHY0dXMvWVBPRUFEQUtrUVZ3TjdKNFVSM0xMWUZSUC9rdG5XbkVnRFV6ZUphdjkydG0zOXRnZDNqOEErZFlRWUFyRklNQkl5MWdFcjl1aWVDZ01kdi9HbDc4SS81QUFEVWdUNy8zdm51WEwvaHk5QWhLZ0NnQS9iTkRDYTZiM0UrUUt4VEFvQXFSSjkvZkE0OWZ1T3pEdjg5OHVqTVVBSTZRd0FBSFhCd29jOUF3QjZLZFVyV0JnTFFhL0c1RTMzKzF2cjFqclYvMEZrQ0FPaVFzYVBYcExuVGZxUjZaWEUrd0dPdEd4amJBZ0RvcHNVKy8vamNjZkR2SFd2L29QUFdiTDNwWFgrY2dGVjcrZlhMMHl1dEFPQUQ2K2NUdmJOcDdXdnRqUUZiMXI2U0RyemNsK1pQcjBrQTBBbFI3di81b2NuMmFyOHR3dWFlRzVrWmFzOWFBanJIRUVEb29QSGpBKzMxUDE0U2VpL21BOFFOemJkZTJwaEdUUW9HWUJYaTRQL0oxdWQ1ZkthNzhhOUczUDRiL0FlZHAxNFpPc3hhd09wRThHSStBQUNyRVdGeURQalQ1MSt0a1dtRC82QWJWQUJBaDFrTFdMM0YrUUE3K2sra2ZUTkQxZ1lDY0VuYjFwMXFsL3I3L0s1ZURQNmJtTzlQUU9kZDlvR1AvdnJyQ2Vpb09JREdMVFQxRUM4U284ZXVGUVFBOERaUjd2L1oxbTEvbFB0VEQzYzh1ODNrZitnU1F3Q2hDK2JlR0VSM3ExdUVXdGpldDVCMjlNKzFCd1RHeWtZQUNEdGJoLzRIdGg1eTYxOGpNY2RuWW01REFyckREQURva3YyekE5WUMxc2hpVzBCVVprUnJBQURsaWdOL2ZCN3Mzanl0ejc5RzR0Yi9Xd2IvUVZlcEFJQXVzUmF3bnZyWG5FNGYzWERDMmtDQUFnMjF3dUFIcjNzKzdZb0JmMnNjL092RzJqL29QdGVUMEVXeEZqQUdBbEkvc1Rid2lkYnRUN3dFRGxuYkNOQm8wZWNmei90NDdpdjNyeWRyLzZBM0JBRFFaWGJTMTF1c2VYcjQrdWVzRFFSb3FPanpmK0xtQSszblBmVzE1NFd0Q2VnK0FRQjBXWlN5VGN4WlpWTm5aODhIVUEwQTBBeHgweDhCcno3LytvdHRQWWIwUW0rc1RVRFhSVTlidkloNEFhbTNDQUtpUE5UYVFJQjhSWkI3MSthcDl2WVg4akIyVExVazlJb0tBT2lCNkdzYm45MlV5TVBaOHdFQXlNTmluLy9qTno3cjhKK1JhSldjRkxoRHp3Z0FvRWRpTGFBUHVMeEV2MmkwQlpnUEFGQnZPOWJQdFEvKzhkeFdiWmVQZUM4YU15c0pla29BQUQweWQzcU5EN2tNTGM0SGVLejFZbWsrQUVDOUxQYjVQN0QxVVB0NVRWNjhGMEh2Q1FDZ2gySzlqYldBZWRxK2JxSGRGbkR2MEdGQkFFREZvdHovcnMzVDdjTy90WDU1T25DcXo5by9xSUFBQUhyTVdzQzh4WHlBZU9IY09UQ2JBT2k5NlBPUHRYNjNEeHhMNU92K3c5YitRUlVFQU5CanNSWlE0cDIzS0RQZHZYbktmQUNBSG9xYi9uanU2dlBQWDJ6Yk1SY0pxbUVOSUZSZ1pIb3c3ZWcvNFFVbWM0dnpBVzY1OHFTMWdRQmRFbTFYOXcwZFZ1cmZFTzNCZjliK1FXVlVBRUFGWWlDZ3RZRE5zYmcyTUtvQ3pBY0E2SXpGUHY5NHZqcjhOMGRVUWJyOWgrb0lBS0FpMWdJMlQ4d0ZpUGtBMmdJQVZtZm53REY5L2cxazdSOVVUd0FBRllrcWdMMlR3NGxtV1d3TCtKb2JLNEJsaStmbVl6ZjhOTzF1M2Z4cmsyc2VoMytvbmhrQVVLRVlDQmhyQVIwVW15ZUNnS2dHaUVGSDVnTUFYSncrLythTHowTkRrS0Y2S2dDZ1l2dG1CaFBOdFRnZllKZXAxUUJ2RTMzKzhYeDgvTVpuSGY0Ynp1QS9xSWMxVzI5NjF4OG5vREt6cjYxdEh3emZjK1hQRTgwVkw3WWYzZkJTbWorOUpoMWM2RXNBcFl0NUtWKysvbWZwQSt2bjB6c3VlejNSWEc3L29UNVVBRUFOakIyOUpzMmQ5dVBZZEdmUEI3QXRBQ2hWQktMUkloWFBRNVZSeldmdEg5U0xDZ0NvZ1pkZnZ6eTkwZ29BNGhhRTV1dGZjN3E5TVdETDJsZlNnWmY3MmxVQkFFMFh3ZWRkZzlQdDFYNWJoS0RGR0prWmFzODhBdXJCbFNQVXhQaHhhd0ZMRS9NQkhyL3hwKzMrVjRDbU9ydlAzNXJVc3NSN2pkSi9xQmNCQU5TSXRZRGw2Yi84dGZTWjFvdHh0QVY0TVFhYUpzcjk0K0QvR1lOUWl6UXlQWlNBZXJFR0VHckVXc0J5TGM0SDJORi9JdTJiR2JJMkVNaGFmSTd0Mm5URTUxbkJZdkRmeEh4L0F1cmxzZzk4OU5lTlhZVWFpWU5nM0FaVHRuaHhHajEyclNBQXlFcVUrMysyZGR0Lys4Q3hSTm51ZUhhYjFrYW9JVU1Bb1dibTNoZ0lkNnRiazZKdDcxdElPL3JuckEwRXNoRjkvbjkwM2ZOdS9VbWpSNjlORTNNYkVsQS9aZ0JBRGUyZkhiQVdrTGVzRFRRZkFLaXJPUERIYzBxZlB5RnUvZmZQYmtwQVBha0FnQnF5RnBDenhkckFxQWF3TmhDb2sxanI5MkRyeGo5dS91TTVCU0hXL3YzWFUxY21vSjVjTVVKTnhWckFHQWdJaTJKdDRCT3RXN1o0MlI2eVF4dW95T0phdjNnZUtmZm5iTmIrUWYwSkFLREdvb2NPemhWbHRnOWYvNXkyQUtEbmRnNGNTMC9jZktEOUhJSnozWFBvaGdUVW13QUFhaXpXQWs3TVdhSEQyNTA5SDJEYnVsTUpvSnZpcGorQ3g5MmJwL1g1YzE2eHZjYlVmNmkvdFFtb3RlaWxpeGN2TDF5Y1R3UUJqOS80VTJzRGdhNklkcU83TmsrMTU1REF4WXdkVTdVSU9WQUJBRFVYYWZxNGFicGN3dG56QVFCV2E3SFAvL0VibjNYNDU1S2laZEh0UCtSQkFBQVppTFdBUGxoWml1akx0VFlRV0kxNGZzVEIzMW8vbGlMZVQ4Yk1MSUpzQ0FBZ0EzT24xNlNSNmNFRVM3RTRIK0N4MWd1OGJRSEFVaTMyK2Nmelk0dG5CMHZrOEE5NU1RTUFNakV4djZHOUZ0REtKWlpxKzdxRmRsdUErUURBeFVTNS8xMkRVeXFIV0xZRHAvcXMvWVBNcUFDQWpGZ0x5RXJFZklDNDFUTWZBRGpiWXA5L3JQVnorR2NsN2orOE5RRjVXYlAxcG5mOWNRS3lNUFhxRmUxK3pQZGMrZk1FeTlHLzVuUzdlaVJlOHVkUHIwa0hGL29TVUs1NEhueDU2OC9hQS83ZWNkbnJDWllycXN2Yy9rTit0QUJBWnNhT1h0TzYwVDF1TUJNcnNqZ2ZZRWYvaWJSdlpraGJBQlJtMjdwVDZhN04wOXJKV0pYMjREOXIveUJMQWdESVRBd0VqTFdBeXJsWmpiajFpeS96QWFBTVVlNy8yZGJueHUwRHh4S3Mxdmp4VGJZVFFhYk1BSUFNV1F0SXB5ek9COUQvQzgyMXMzWG9qejUvaDM4NklkNC80ajBFeUpNQUFESVVWUUI3SjRjVGRNSmlXOERYYmpyWWJnMEFtaUhLL0IrNzRhZHA5K1pwYldOMGpMVi9rRGN0QUpDcFozNStsYldBZEZRRUFROWM5N3kyQU1qY1VPdG4rYjZod3o0ZjZEaUQveUIvS2dBZ1kvdG1CaE4wV3JRRlBISFR3ZmFjQ2JlR2tJL0Z0WDZQMy9pc3d6OWRZZkFmNU04YVFNalk3R3RyclFXa2ErSUE4ZEVOTDFrYkNCbUlPUjVmdnY1bjZRUHI1NjMxb3l0aUFQRmZuM2huQXZLbUFnQXlGMnNCNTA3N1VhWTd6cDRQRUdYRlFMMUVVQmVEUE9QblZNVU8zZEllL0hmYzREOW9BaFVBa0xtWFg3ODh2ZElLQU9MV0I3cWxmODNwdEhOZ05tMVorMG82OEhKZnV5b0FxRTRFY25jTlRxZTdOayszZ3pyb3BwR1pvZmJzSVNCL2hnQkNBNHkzVXZuYk5oNVAyOVl0Sk9pbW1BK3dZOE5jZXdYVXFFblEwSFBSNS8vSmdXUHRsWDV1L09tRnVQMDMrQSthUTkwd05NUys2YUVFdmRCLytXdnBNOWNjYWJjRlJOOHgwQnM3MXMrMUIveDl4b0JPZXNqYVlXZ1dGUURRRU5ZQzBtdUw4d0VpQlBqSzFMQzFnZEFsOFZ6ZnRlbUk1enM5RjJ2L2xQNURzMXoyZ1kvK3VsR3gwQkJ4SUh1c2RUdmtab2dxeEl2aTZMRnJCUUhRSVZIdS85bldiWCtVKzBNVjduaDJXN3NGQUdnT1F3Q2hRZVpPcjJtdmY3clZMUkVWMk42M2tIYjB6NlhMTHJzcy9kZFRWeVpnNVhhMUR2NS9kTjN6YnYycFRNeDVtWmpia0lCbU1RTUFHaWFHczFrTFNGV2lDbVgzNWluekFXQ0Y0c0FmUHovNi9LbFNlKzNmN0tZRU5JOEtBR2dZYXdHcGcxZ2JHTlVBMWdiQzBzUmF2d2RiTi81eDh4OC9QMUNsV1B1bmtndWF5UkJBYUtCWUM3aWovNFRTVVNvWGF3UGphM3gyb1BWOXVjbDhBRGlIUG4vcXh0by9hRFoxd3RCUWRyUlRKenNIWnRQRDF6K25MUURPc3JOMTZIL2k1Z01PLzlUS1BZZHVTRUJ6Q1FDZ29XSnRqd1NmT2xsY0d4ajl6YXBUS0ZsOC8wY2d0bnZ6dEQ1L2FpVzJ1Wmo2RDgybUJRQWFiT3pvdGUxV0FDK1kxRWtFQVhINHNUYVEwa1NmLzMxRGh3VmcxRklNRUI0N3Bub1FtazRGQURSWXBQampwdmhTVXpFYjRJbWJEcDRaZWlha29zR2l6eisrengrLzhWbUhmMm9yM2hmYy9rUHpDUUNnNFdJdG9BOTA2aXpXblQzV09oaVpEMEFUeGZkMUhQeXQ5YVBPNGoxaHpPd2dLSUlBQUJwdTd2U2FOREk5bUtET3pwNFBFR1hTa0x2RlB2LzR2dDdpZTVxYWMvaUhjcGdCQUFXWW1OK1Fuamw1bGRKVGFpOE9TdEVXWUQ0QXVZcHkvN3NHcDFTMGtJMm5UeG9hRENWUkFRQ0ZzQmFRbk1SOGdNZHYvR203YnhweXNOam5IMnY5SFA3SnlVTlR3d2tveDVxdE43M3JqeFBRZUZPdlh0SHVQMzNQbFQ5UGtJTjNYUFo2dTJvbERsUHpwOWVrZ3d0OUNlb292aysvdlBWbmFVZi9YUHY3Rm5JUjFWWnUvNkVzV2dDZ0lHTkhyMm5kckI0M2lJcXNMTTRIaUpXVysyYUd0QVZRRzl2V25VcDNiWjdXWGtXVzJvUC9yUDJENGdnQW9DQXhFRERXL0NpckprZHh1eHBmNWdOUXRTajMvMnpyT1hyN3dMRUV1Um8vYnUwZmxNZ01BQ2hNVFByMWdVL09ZajVBVEZmWFowMFZkcllPL2RIbjcvQlB6dUk5SU5ZRUErVVJBRUNCOWs0YStFUGV6bDRiR0swQjBHMVI1aC9mYjdzM1QydWpJbnZXL2tHNXRBQkFnWjc1K1ZYV0F0SUlFUVE4Y04zejJnTG9tcUhXOTloOVE0YzlMMmtNZy8rZ2JDb0FvRkI3cmYyaFFhSXQ0SW5XN1d6TXQ0Z0RHNnpXbTJ2OVd0OVhEdjgwaWNGL1VEWnJBS0ZRTVJEUVdrQ2FKZzVxTVNqUTJrQldJL3I4SDloNktIMWcvWHlDSm9sQndIOTk0cDBKS0pjS0FDaFlyQVdjTysweFFMT2NQUjhnMXJUQlVrV0FGQU1tOWZuVFJPM0JmOGNOL29QU3FRQ0FncjM4K3VYcGxWWUE0SmFMSnVwZmN6cjk1dFhIMDVhMXI2UURML2UxcXdMZ2ZOcDkvcTNRNk01clo5b0JFalRSeU14UWV3WVFVRFpYZjFDNDhkWnR3TUdGZFFtYTZ1ejVBSEMyeFQ3L3gyOTh0dDA2QWswVnQvOEcvd0ZCQUFDa2ZkTkRDWnJ1TTYyRFhyUUYzUGJPRnhQc1dEL1hQdmpIOTRWeWY1ck8rbDlna1FBQWVITXRJRFRkNG55QXgxb0hQOXNDeXJUWTV4OUQvcFQ3VTRKWSs2ZjBIMWdrQUFEYVlpMmdnWUNVWXZ1NmhYWmJ3TDFEaHdVQmhZaHkvN3MyVDdjUC85YjZVUkpyLzRDemVkc0gycUkvTU5ZRFFVbGlQc0N1VFdZRGxPQ3V3YWwwKzhDeEJDVVpQWHB0Ky9NZFlKRUFBSGpUL3RrQlZRQUEwQUR0dFgrQ2ZlQWMzdlNCTjgyZFhwTkdEQVFFZ095TnRXNy9oZnJBdVR3VmdMZUlOVUVHQWdKQXZxejlBeTVFQUFDOFRmUU1BZ0I1dXVmUURRbmdmQVFBd052RXVpQTNCd0NRbjFqN1ovQWZjQ0VDQU9DODlBNENRRjdpYzl2YVArQml2TjBENTJVdElBRGtKVDYzM2Y0REZ5TUFBQzRvMWdKNmtRQ0Erb3ZQNnpFemZJQkxFQUFBRjNSbUxlQmdBZ0RxemVFZldBb0JBSEJSRS9NYnJBVUVnQnA3K3FUaHZjRFNDQUNBUzdJV0VBRHE2NkdwNFFTd0ZBSUE0SkppTGFDQmdBQlFQOWIrQWNzaEFBQ1daT3pvTmRZQ0FrQ050QWYvV2ZzSExJTzNlV0JKWWlDZ0tnQUFxSS94NDliK0Fjc2pBQUNXTENZTWU5RUFnT3JGNTNHczZ3VllEZ0VBc0N4N0p3MGFBb0NxV2ZzSHJJUUFBRmlXR0Fob0xTQUFWQ2NHLzFuN0I2eUVBQUJZdHIzV0RRRkFaUXorQTFaS0FBQXNXL1FkR2dnSUFMMFhuNy9tOFFBckpRQUFWc1JhUUFEb3JmYmd2K01HL3dFcjUrMGRXSkZZQ3poMlpITUNBSHJETmg1Z3RRUUF3SXFOdDI0aERpNnNTd0JBZDhYQjMrQS9ZTFVFQU1DcTdKc2VTZ0JBZCsxNVlXc0NXQzBCQUxBcTFnSUNRSGZGMnIrREMzMEpZTFVFQU1DcXhWcEFBd0VCb0R1cy9RTTZ4UnM3c0dyV0FnSkFkNHdhL0FkMGtBQUE2SWo5c3dPcUFBQ2dnK0xnSDVQL0FUckYyenJRRWJFV2NNUkFRQURvR0lkL29OTUVBRURIeEhvaUF3RUJZUFdzL1FPNlFRQUFkTlNvMndvQVdMVjdEdDJRQURwTkFBQjBWS3dGZEdNQkFDc1hhLzhNL2dPNlFRQUFkRnowTEJvSUNBRExGNStmMXY0QjNlSU5IZWc0YXdFQllHWGk4OVB0UDlBdEFnQ2dLMkl0b0JjWUFGZzZhLytBYmhNQUFGMXhaaTNnWUFJQWxzYmhIK2cyQVFEUU5SUHpHNndGQklBbCtPNWN2eUc2UU5jSkFJQ3VzaFlRQUM3dDBabWhCTkJ0QWdDZ3EySXRvSUdBQUhCaDF2NEJ2U0lBQUxwdTdPZzExZ0lDd0htMEIvOVord2YwaURkeW9PdGlJS0FxQUFCNHV4ajg1L1lmNkJVQkFOQVRYbkFBNEszaWM5SGdQNkNYQkFCQXoreWRIRTRBd0JrajB3Yi9BYjBsQUFCNkpnWUNXZ3NJQUdjRy8wM005eWVBWGhJQUFEMjFkMG9WQUFBWS9BZFVRUUFBOUZUME80NGU5ZElEUUxsR3pjVUJLaUlBQUhwdS8reUF0WUFBRkNrTy90OHkrQStvaURkd29PZGlMZURZa2MwSkFFcGpLdzVRSlFFQVVJbng0d01HQWdKUUZHdi9nS29KQUlES21BVUFRRW4ydkxBMUFWUkpBQUJVeGxwQUFFb1JhLzhPTHZRbGdDb0pBSUJLeFZwQUF3RUJhRHByLzRBNjhOWU5WQ3I2SWNkbk55VUFhQ3ByLzRDNkVBQUFsYk1XRUlDbWlvUC9tSmszUUUxNDR3WXFGMnNCUjZhSEVnQTBqY00vVUNjQ0FLQVdZaTJTZ1lBQU5NbUJVMzNXL2dHMUlnQUFhc05hUUFDYTVQN0QxdjRCOVNJQUFHb2oxZ0s2S1FHZ0NXTHRuOEYvUU4wSUFJQmFHWmtlTkJBUWdLeTFCLzlaK3dmVWtMZHNvRlppSUtDMWdBRGtMS3JaM1A0RGRTUUFBR29uMWdKNmNRSWdSOWIrQVhVbUFBQnFKNm9BOWs0T0p3RElqY00vVUdjQ0FLQ1dZaUNndFlBQTVPUzdjLzJHMlFLMUpnQUFhbXZmekdBQ2dGdzhPak9VQU9wTUFBRFUxc0dGUGdNQkFjaUN0WDlBRGdRQVFLMk5IYjNHV2tBQWFzM2FQeUFYM3FxQldvdUJnR05ITmljQXFLc1kvT2YySDhpQkFBQ292ZkhqMWdJQ1VFL3grV1R3SDVBTEFRQ1FCV3NCQWFpamtXbUQvNEI4Q0FDQUxGZ0xDRURkeE9DL2lmbitCSkFMQVFDUWpiMVRxZ0FBcUErRC80RGNDQUNBYkVTZjVlaFJMMXNBVkcvVTREOGdRd0lBSUN2N1p3ZXNCUVNnVW5Idy81YkJmMENHdkVVRFdiRVdFSUNxV2ZzSDVFb0FBR1FuMWdJYUNBaEFGYXo5QTNJbUFBQ3laQllBQUZYWTg4TFdCSkFyQVFDUXBWZ0xPREZuOVJJQXZSTnIvdzR1OUNXQVhBa0FnR3lOekF3WkNBaEF6MWo3QitUT216T1FyZWpESEovZGxBQ2cyNno5QTVwQUFBQmtMZFlDZWlFRG9KdmljMmJNN0JtZ0FRUUFRTmJhYXdHOWxBSFFSVDVuZ0tZUUFBRFppM1ZNMWdJQzBBMEhUdlZaK3djMGhnQUFhQVJyQVFIb2h2c1BXL3NITkljQUFHaUVXQXZvaGdhQVRvcTFmK2JNQUUwaUFBQWFZMlI2MEZwQUFEcWlQZmpQMmorZ1lid3BBNDBSQXdHdEJRU2dFNktxek8wLzBEUUNBS0JSckFVRVlMV3MvUU9hU2dBQU5FcFVBZXlkSEU0QXNGSU8vMEJUQ1FDQXhvbUJnTllDQXJBUzM1M3JOMVFXYUN3QkFOQkkrMllHRXdBczE2TXpRd21ncVFRQVFDTWRYT2d6RUJDQVpiSDJEMmc2QVFEUVdHTkhyN0VXRUlBbHNmWVBLSUUzWTZDeFlpRGcySkhOQ1FBdUpRYi91ZjBIbWs0QUFEVGErSEZyQVFHNHVQaWNNUGdQS0lFQUFHZzhhd0VCdUppUmFZUC9nRElJQUlER3N4WVFnQXVKd1g4VDgvMEpvQVFDQUtBSWU2ZFVBUUR3ZGdiL0FTVVJBQUJGaVA3TzBhTmU4Z0Q0aFZHRC80RENDQUNBWXV5ZkhiQVdFSUMyT1BoL3krQS9vRERlaElGaVdBc0l3Q0pyLzRBU0NRQ0Fvc1JhUUFNQkFjcG03UjlRS2dFQVVCeXpBQURLdHVlRnJRbWdSQUlBb0RpeEZuQml6c29uZ0JMRjJyK0RDMzBKb0VRQ0FLQklJek5EQmdJQ0ZNamFQNkJrM242QklrWC81L2pzcGdSQU9hejlBMG9uQUFDS0ZXc0J2UWdDbENHZTkyTm13QUNGRXdBQXhXcXZCZlF5Q0ZBRXozc0FBUUJRdUZnRFpTMGdRTE1kT05WbjdSOUFFZ0FBV0FzSTBIRDNIN2IyRHlBSUFJRGl4VnBBTjBNQXpSUnIvOHg3QVRoREFBRFFNakk5YUMwZ1FNTzBCLzlaK3dmd0ptKzdBT25NUUVCckFRR2FKYXE3M1A0RC9JSUFBT0FOMWdJQ05JZTFmd0J2SndBQWVFTlVBZXlkSEU0QTVNL2hIK0R0QkFBQVo0bUJnTllDQXVUdHUzUDlocnNDbkljQUFPQWMrMllHRXdENWVuUm1LQUh3ZGdJQWdITWNYT2d6RUJBZ1U5YitBVnlZQUFEZ1BNYU9YbU10SUVCbXJQMER1RGh2dHdEbkVRTUJ4NDVzVGdEa0l3Yi91ZjBIdURBQkFNQUZqQiszRmhBZ0YvRzhOdmdQNE9JRUFBQVhZUzBnUUI1R3BnMytBN2dVQVFEQVJWZ0xDRkIvTWZodllyNC9BWEJ4QWdDQVM5ZzdwUW9Bb000TS9nTllHZ0VBd0NWRVgrbm9VUytYQUhVMGF2QWZ3SklKQUFDV1lQL3NnTFdBQURVVEIvLzlzNXNTQUV2amJSWmdDYXdGQktpZldQc25uQVZZT2s5TWdDV0t0WUFHQWdMVWc3Vi9BTXNuQUFCWUJyTUFBT3JobmtNM0pBQ1dSd0FBc0F5eEZuQml6cW9wZ0NyRjJqK0Qvd0NXVHdBQXNFd2pNME42VGdFcVpPMGZ3TXA0Z3dWWXByaDFHamQxR3FBUzF2NEJySndBQUdBRllpMmdGMUNBM29ybjdwaFpMQUFySmdBQVdJSDJXa0F2b1FBOTVia0xzRG9DQUlBVml2VlQxZ0lDOU1hQlUzM1cvZ0dza2dBQVlCV3NCUVRvamZzUGIwMEFySTRBQUdBVllpMmdHeW1BN3JMMkQ2QXpCQUFBcXpReVBXZ3RJRUNYdEFmL1dmc0gwQkhlV0FGV0tRWUNXZ3NJMEIzanh6ZTUvUWZvRUFFQVFBZFlDd2pRZWZGY2plY3JBSjBoQUFEb2dLZ0MyRHM1bkFEb0hHdi9BRHBMQUFEUUlURVEwRnBBZ002SXdYK0dyQUowbGdBQW9JUDJ6UXdtQUZiUDREK0F6aE1BQUhUUXdZVStBd0VCVnNuYVA0RHVFQUFBZE5qWTBXdXNCUVJZSVd2L0FMckhHeXBBaDhWQXdMRWpteE1BeXhlRC85eitBM1NIQUFDZ0M4YVBXd3NJc0Z6eDNEVDRENkI3QkFBQVhXSXRJTUR5akV3UEpRQzZSd0FBMENYV0FnSXNYUXorbTVqdlR3QjBqd0FBb0l2MlRxa0NBRmdLZy84QXVrOEFBTkJGMGM4NmV0UkxMY0RGakJyOEI5QVRBZ0NBTHRzL08yQXRJTUFGeE1GLy8reW1CRUQzZVNNRjZESnJBUUV1TE5iK0NVa0Jlc1BURnFBSFlpMmdnWUFBYjJYdEgwQnZDUUFBZXNRc0FJQzN1dWZRRFFtQTNoRUFBUFJJckFXY21MUGlDaURFMmorRC93QjZTd0FBMEVNak0wTjZYUUdTdFg4QVZmQVdDdEJEY2RzMWJ0bzFVRGhyL3dDcUlRQUE2TEZZQytqRkZ5aFZQUC9HekVRQnFJUUFBS0RIMm1zQnZmd0NoZkw4QTZpT0FBQ2dBckgyeWxwQW9EUlB0NTU3MXY0QlZFY0FBRkFSYXdHQjBqdzBOWndBcUk0QUFLQWlzUmJRVFJoUUNtdi9BS29uQUFDbzBNajBvTFdBUU9PMUIvOVord2RRT1crZEFCV0tnWURXQWdKTk4zNThrOXQvZ0JvUUFBQlV6RnBBb01uaStSYlBPUUNxSndBQXFGaFVBZXlkTkJnTGFDWnIvd0RxUXdBQVVBTXhFTkJhUUtCcFl2Q2ZZYWNBOVNFQUFLaUpmVE9EQ2FCSkRQNERxQmNCQUVCTkhGem9NeEFRYUl4NG5wbHZBbEF2QWdDQUdoazdlbzIxZ0VEMjJvUC9qaHY4QjFBMzNqSUJhaVFHQW80ZDJad0FjaGFELzl6K0E5U1BBQUNnWnNhUFd3c0k1Q3VlWHdiL0FkU1RBQUNnaHF3RkJITGwrUVZRWHdJQWdCcXlGaERJVWF6OWkrY1hBUFVrQUFDb3FiMVRidEdBdkZqN0IxQnZBZ0NBbW9vKzJ0R2pYcWFCUEl3YS9BZFFld0lBZ0JyYlB6dGdMU0JRZSsyMWY3T2JFZ0QxNXEwU29NYXNCUVJ5RUd2L2hKVUE5ZWRKRFZCenNSYlFRRUNncnF6OUE4aUhBQUFnQTJZQkFIVjF6NkViRWdCNUVBQUFaQ0RXYWszTTlTZUFPb20xZndiL0FlUkRBQUNRaVpHWklUMjJRRzNFODhqYVA0QzhlSk1FeUVUY3NvMmJzZzNVUkR5UDNQNEQ1RVVBQUpDUldBdm9oUnVvV2p5SHhzd21BY2lPQUFBZ0krMjFnRjY2Z1lwNURnSGtTUUFBa0psWXQyVXRJRkNWcDF2UEgydi9BUElrQUFESWtMV0FRRlVlbWhwT0FPUkpBQUNRb1ZnTDZBWU82RFZyL3dEeUpnQUF5TlRJOUtDMWdFRFB0QWYvV2ZzSGtEVnZqZ0NaaW9HQTFnSUN2VEorM05vL2dOd0pBQUF5WmkwZzBBdnhuSW5uRFFCNUV3QUFaQ3lxQVBaT0dzZ0ZkSmUxZndETklBQUF5RndNQkxRV0VPaVdHUHhuNkNoQU13Z0FBQnBnMzh4Z0F1Z0dnLzhBbWtNQUFOQUFCeGY2REFRRU9pNmVLK2FNQURTSEFBQ2dJY2FPWG1NdElOQXg3Y0YveHczK0EyZ1NiNG9BRFJFREFjZU9iRTRBblJDRC85eitBelNMQUFDZ1FjYVBXd3NJckY0OFJ3eitBMmdlQVFCQXcxZ0xDS3lXNXdoQU13a0FBQnJHV2tCZ05XTHRYenhIQUdnZUFRQkFBKzJkR2pZUUVGZ1JhLzhBbXN2YklVQURSZit1dFlEQWNvMGEvQWZRYUFJQWdJYmFQenVnQ2dCWXN2YmFQOEVoUUtONU13Um9LR3NCZ2VXSXRYOUNRNEJtODVRSGFMQllDMmdnSUhBcDF2NEJsRUVBQU5CdzBkTUxjREgzSExvaEFkQjhBZ0NBaG90MVhoTnovUW5nZkdMdG44Ri9BR1VRQUFBVVlHUm1TRzh2OERieFhMRDJENkFjM2dZQkNtQXRJSEErOFZ4dyt3OVFEZ0VBUUNGaUxhQVhmV0JSUEEvR3pBZ0JLSW9BQUtBUXNSWndaSG93QVFTSGY0RHlDQUFBQ2pJeHY4RmFRQ0E5M1hvT1dQc0hVQjRCQUVCaHJBVUVIcG9hVGdDVVJ3QUFVSmhZQzJnZ0lKVEwyaitBY2drQUFBbzBkdlFhYXdHaFFPM0JmOWIrQVJUTDJ4OUFnV0lnb0NvQUtNLzRjV3YvQUVvbUFBQW9sTFdBVUpiNGVZK2Zld0RLSlFBQUtGUlVBZXlkTkFnTVNtSHRId0FDQUlDQ3hVQkFhd0doK1dMd243Vi9BQWdBQUFxM2IyWXdBYzFtOEI4QVFRQUFVTGlEQzMwR0FrS0R4YyszZVI4QUJBRUFBTllDUWtPMUIvOGROL2dQZ0RPODdRSFFIZ2c0ZG1SekFwb2xCdis1L1FkZ2tRQUFnTGJ4MWkzaHdZVjFDV2lHT1BnYi9BZkEyUVFBQUx4cDMvUlFBcHJCbWs4QXppVUFBT0JOMWdKQ004VGF2L2g1Qm9DekNRQUFlSXU5VThNR0FrTG1yUDBENEh5ODRRSHdGdEUzYkMwZzVHdlU0RDhBTGtBQUFNRGI3SjhkVUFVQUdXcXYvUlBnQVhBQjN1NEFlQnRyQVNGUHNmWlBlQWZBaGZpRUFPQzhZaTJnZ1lDUUQydi9BTGdVQVFBQUZ4Uzl4RUFlN2psMFF3S0FpeEVBQUhCQnNVWnNZcTQvQWZVV2EvOE0vZ1BnVWdRQUFGelV5TXlRbm1Lb3NmajV0UFlQZ0tYd1JnZkFSVmtMQ1BVV1A1OXUvd0ZZQ2dFQUFKY1Vhd0VkTUtCKzR1ZHl6S3dPQUpaSUFBREFKY1Zhd0pIcHdRVFVpOE0vQU1zaEFBQmdTU2JtTjFnTENEWHlkT3ZuMGRvL0FKWkRBQURBa2xrTENQWHgwTlJ3QW9EbEVBQUFzR1N4RnRCQVFLaWV0WDhBcklRQUFJQmxHVHQ2amJXQVVLSDI0RDlyL3dCWUFXOXdBQ3hMREFSVUJRRFZHVDl1N1I4QUt5TUFBR0RackFXRWFzVFBYZno4QWNCS0NBQUFXTGFvQXRnN2FRQVo5SnExZndDc2hnQUFnQldKZ1lEV0FrTHZ4T0EvYS84QVdBMEJBQUFydG05bU1BRzlZZkFmQUtzbEFBQmd4UTR1OUJrSUNEMFFQMmZtYmdDd1dnSUFBRmJGV2tEb3J2Ymd2K01HL3dHd2V0N1lBRmlWR0FnNGRtUnpBcm9qQnYrNS9RZWdFd1FBQUt6YWVPdDI4dURDdWdSMFZoejhEZjREb0ZNRUFBQjB4TDdwb1FSMGxuV2JBSFNTQUFDQWpyQVdFRG9yMXY3Rnp4VUFkSW9BQUlDTzJUczFiQ0FnZElpMWZ3QjBtcmMwQURvbStwV3RCWVRWR3pYNEQ0QXVFQUFBMEZIN1p3ZFVBY0FxdE5mK0NkSUE2QUp2YUFCMGxMV0FzRHF4OWsrSUJrQTMrSFFCb09OaUxhQ0JnTEI4MXY0QjBFMENBQUM2SW5xWWdlVzU1OUFOQ1FDNlJRQUFRRmZFK3JLSnVmNEVMRTJzL1RQNEQ0QnVFZ0FBMERVak0wTjZtV0VKNHVmRTJqOEF1czFiR1FCZFl5MGdMRTM4bkxqOUI2RGJCQUFBZEZXc0JYU3dnUXVMbjQ4eE16TUE2QUVCQUFCZEZXc0JSNllIRTNCK0R2OEE5SW9BQUlDdW01amZZQzBnbk1mVHJaOExhLzhBNkJVQkFBQTlZUzBndk4xRFU4TUpBSHBGQUFCQVQ4UmFRQU1CNFJlcy9RT2cxd1FBQVBUTTJORnJyQVdFOU1iZ1Aydi9BT2d4YjJFQTlFd01CRlFGQUNtTkg3ZjJENERlRXdBQTBGTXg4ZHpCaDVMRjkzK3N4d1NBWGhNQUFOQnpleWNOUHFOYzF2NEJVQlVCQUFBOUZ3TUJyUVdrUkRINHo5by9BS29pQUFDZ0VudXRQNk5BQnY4QlVDVUJBQUNWaUQ1b0F3RXBTWHkvbTM4QlFKVUVBQUJVeGxwQVN0RWUvSGZjNEQ4QXF1V3RDNERLeEZyQXNTT2JFelNkN1JjQTFJRUFBSUJLamJkdVJROHVyRXZRVkhId04vZ1BnRG9RQUFCUXVYM1RRd21hYXM4TFd4TUExSUVBQUlES1dRdElVOFhhdjRNTGZRa0E2a0FBQUVBdHhGcEFBd0ZwR212L0FLZ1RiMW9BMUlLMWdEVE5xTUYvQU5TTUFBQ0EydGcvTzZBS2dFYUlnMzlNL2dlQU92R1dCVUJ0eEZyQUVRTUJhUUNIZndEcVNBQUFRSzNFdWpRREFjbVp0WDhBMUpVQUFJRGFHWFY3U3NidU9YUkRBb0E2RWdBQVVEdXhGdEFOS2ptS3RYOEcvd0ZRVndJQUFHb3BlcWdOQkNRbjhmMXE3UjhBZGViTkNvQmFzaGFRM01UM3E5dC9BT3BNQUFCQWJjVmFRQWNxY21EdEh3QTVFQUFBVUZ0bjFnSU9KcWc3aDM4QWNpQUFBS0RXSnVZM1dBdElyWDEzcnQvUVNnQ3lJQUFBb1Bhc0JhVE9IcDBaU2dDUUF3RUFBTFVYYXdFTkJLU09yUDBESUNjQ0FBQ3lNSGIwR21zQnFaWDI0RDlyL3dESWlEY3BBTElRQXdGVkFWQW5NZmpQN1Q4QU9SRUFBSkFOQnk3cUlyNFBEZjRESURjQ0FBQ3lzbmR5T0VIVnJQMERJRWNDQUFDeUVnTUJyUVdrU2pINHorMC9BRGtTQUFDUW5iMVRxZ0NvanNGL0FPUktBQUJBZHFMLzJrQkFxaERmZCtaUUFKQXJBUUFBV2JJV2tGNkxnLy8rNHdNSkFITGx6UW1BTE1WYXdMRWpteFAwaWkwVUFPUk9BQUJBdHNaYnQ3RUhGOVlsNkRaci93Qm9BZ0VBQUZuYk56MlVvTnYydkxBMUFVRHVCQUFBWk0xYVFMb3QxdjRkWE9oTEFKQTdBUUFBMll1MWdBWUMwaTNXL2dIUUZONldBTWlldFlCMHk2akJmd0EwaUFBQWdFYllQenVnQ29DT2lvTi9UUDRIZ0tid3BnUkFJOFJhd0JFREFla2doMzhBbWtZQUFFQmp4Sm8yQXdIcGhBT24rcXo5QTZCeEJBQUFOTXFvVzFzNjRQN0QxdjRCMER3Q0FBQWFKZFlDdXJsbE5XTHRuOEYvQURTUkFBQ0F4b25lYlFNQldZbjI0RDlyL3dCb0tHOUhBRFNPdFlDc1ZGU1B1UDBIb0trRUFBQTBVcXdGZEpCak9hejlBNkRwQkFBQU5OS1p0WUNEQ1piSzRSK0FwaE1BQU5CWUUvTWJyQVZrU2I0NzEyOTRKQUNOSndBQW9OR3NCV1FwSHAwWlNnRFFkQUlBQUJvdDFnSWFDTWpGV1BzSFFDa0VBQUEwM3RqUmE2d0Y1THlzL1FPZ0pONkdBR2k4R0Fpb0NvRHppY0YvYnY4QktJVUFBSUFpT09oeHJ2aCtNUGdQZ0pJSUFBQW94dDdKNFFTTFJxWU4vZ09nTEFJQUFJb1JBd0d0QlNURTRMK0orZjRFQUNVUkFBQlFsTDFUcWdCSUJ2OEJVQ1FCQUFCRmliNXZBd0hMTm1vZUJBQ0ZFZ0FBVUJ4ckFjc1ZCLzl2R2Z3SFFLRzgvUUJRbkZnTE9IWmtjNkk4dGtFQVVESUJBQUJGR2o4K2tBNHVyRXVVdzlvL0FFb25BQUNnV1B1c2dTdktuaGUySmdBbzJkb0VBSVdLdFlCYnJuZ2wwWHpmZW5Gak9yalFsd0NnWkNvQUFDaWFrdkF5UE4wS2V3Q2dkQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQ2dBQUlBQUFBQUtJQUFBQUFBQUFvZ0FBQUFBSUFDQ0FBQUFBQVNOSjhBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ0NBQUFBQUNnQUFJQUFBQUFLSUFBQUFBQUFBb2dBQUFBQUlBQ3JFMEFBRUF0L2RXNy8vOVVoYTlNRHFkdnZiUXhsZUMyalMrbWU0Y09weXI4MHgvOWp3bDZTUVVBQUFBQUZFQUFBQUFBQUFVUUFBQUFBRUFCQkFBQUFBQlFBQUVBQUFBQUZFQUFBQUFBQUFXd0JwQ2UreS8vNlp1Si9EM3dsWWZUazAvOVZXSjVIbjM0eTRtVVRzek5wN201dWZaZkg1NmFhdi9QazVObmZuMmg5ZXZocWVsRWMzMTR4d2ZUM1hkOUxsWGg5KzcrUWpvOFdjYjMxNmQyZmlMOWR1dXJDcC80OUQ5TEFOU1BBQUNnaDk1LzYzc1RTL09qQXo5cEJ3SS9idjM2L1dkKzBBb0dwdE9QRHY0a2tiLysvdjQwdkdVbzBWMGIrdGY3Y3diZ0xRUUFBTlRTdTdmZjNQNDFRcE5QZmZMTUxXWUVBdDk3K29mdFFPRDdyVjhGQWdBQVN5Y0FBQ0FiY2FQNWtROTlzUDBWRGs5T3RRT0JiejcxN2ZTOVozNllBQUM0TUFFQUFObUs4dWFQLzFwOGZhd2RCbngxOUlsV0lQQURNd1FBQU01REFBQkFJMFFZc09lK3o3Zi8rc20vL0hZckRQaWFJQUFBNEN6V0FBTFFPRkVSOEkwLy93OXB6NzJmVDhORGd3a0FBQUVBQUEwbUNBQUErQVVCQUFDTkYwSEFuejN5NWZUeDJ6NldBQUJLSlFBQW9BaUxNd0llZmZqTHFnRUFnQ0lKQUFBb3l2dHZmVys3R3VERE96NllBQUJLSWdBQW9EaFJEZkRRZzE5TWQrNjZJd0VBbEVJQUFFQ3g3dHoxNmZUNTNaOUxBQUFsRUFBQVVMVGYvdVFuMmxzQ0FBQ2FUZ0FBUVBGaVM4RGVCNzZZQUFDYVRBQUFBQzBmK2RBSFZRSUFBSTBtQUFDQU4wUWxnTUdBQUVCVENRQUE0Q3d4R1BCVE8zOHJBUUEwalFBQUFNNFJJY0R3MEdBQ0FHZ1NBUUFBbkdORC8vcjAwSU9HQWdJQXpTSUFBSUR6ZVBmMm05dVZBQUFBVFNFQUFJQUxpRmtBV2dFQWdLWVFBQURBQlVRcndKNzc3azRBQUUwZ0FBQ0FpM2ovcmU5Tjc3dmx2UWtBSUhjQ0FBQzRoRHQzM1pFQUFISW5BQUNBUzFBRkFBQTBnUUFBQUpiZ0l4LzZZQUlBeU5uYUJFRFBQUG1YMzA2bG1adWZUeWZtNXRMdzBGQjdxRjU4dld2N3R2YXZPZm1OMi82MzlOWFJKMXEvbC9rRUFKQWpBUUE5OTcvOHI3K1JjdkJmL3RNM1V4VytPdnExOWlHRFpucGc3eU9KTTlwQndMYWJXemZydjVMZWY4di8zQTRGNml6K2VYL2p0bytscjQ5L0l3RUE1RWdBQUVBbDRpYjkrOC84c1AwVmhyY01wVHQzZmJvVkJyeTMvZGQxOU9FZHZ5SUFBQUN5SlFBQW9CWU9UMDZsQjc1eXBrSWlidG8vMXdvRDZoWUV4RERBcUFUUUJnQUE1TWdRUUFCcTU1dFBmVHQ5NHRQL3JOMFNVemUyQVFBQXVSSUFBRkJiTVE4amdvQ29EcWlMcUFJQUFNaVJBQUNBV292RC8rOTg3Zy9Tanc3OEpOWEIrMjc1NVFRQWtDTUJBQUMxRnozM3YzLzNGMm9SQXJ4Nys4M1pyVEFFQUFnQ0FBQ3lFQ0hBSCs3NWsxb000TnRTMHkwRkFBQVhJd0FBSUJ0bk5nVThuS3IyUDJ5N0tRRUE1RVlBQUVCV3ZqUHg5K2w3VC84d1ZTbmFBQUFBY2lNQUFDQTdWYThIM0xKbFN3SUF5STBBQUlEc2ZQK1pIMVphQlhEZDBHQUNBTWlOQUFDQUxIMW40dTlTVld3QkFBQnlKQUFBSUVzeEM2QXF3N1lBQUFBWkVnQUFrS1hZQ0JCZkFBQXNqUUFBZ0d6OTZNQ3pxU3JhQUFDQTNBZ0FBTWpXaWZtNVZKVitBUUFBa0JrQkFBRFowZ0lBQUxCMEFnQUFBQUFvZ0FBQWdHeVp4ZzhBc0hRQ0FBQ3lWV1VMd056Y2ZBSUF5SWtBQUlCc1ZWa0JjRUlBQUFCa1JnQUFRTFkyck85UEFBQXNqUUFBZ0d4ZHQyVXdWY0gyQVFBZ1J3SUFBTEswb1g5OWV0ZjJtMU1WQkFBQVFJNEVBQUJrNlgyM3ZEZFY1YVg1a3drQUlEY0NBQUN5OU9FZHY1S3E4dU1EQnhNQVFHNEVBQUJrWjNob0tIMzgxejZXcXZLakF6OUpBQUM1RVFBQWtKMHFELy9CQ2tBQUlFY0NBQUN5RXJmL2QrNzZkS3JTOTUvNVlRSUF5STBBQUlDc1ZINzRmL29IQ1FBZ1J3SUFBTEp4NTY0N0tpLy8vOUZCL2Y4QVFKNEVBQUJrNGVPM2ZhenkyLy93TjkvOSt3UUFrQ01CQUFDMUY0Zi9QZmQ5UGxVdGh2L3Avd2NBY3JVMkFVQ05SZGwvSFc3K3cvY2MvZ0dBakFrQUFLaWxtUFlmdC83dnYvVzlxUzYrK1pmL2J3SUF5SlVBQUlCYVdWenpWL1d3djNNZG5weEszNW5RL3c4QTVFc0FBRURsTnF4Zm56NzhvVjlKdjNIYngycDE0MzgyNWY4QVFPNEVBQUQwMVBEUVlOclEzNS9ldmYzbTlPNXRONmYzdFE3ODhkZDE5OVhScnlVQWdKd0pBQUI2NkJ0UC9QdFVxdUV0UXlsWFR6NzE3WFI0Y2pvQkFPUk1BQURRUXprZmdrdm05aDhBYUlMTEV3QndRWEg0ZC9zUEFEU0JBQUFBTGlBbS8zOTkvQnNKQUtBSkJBQUFjQUVQNzNzOG5aaWJUd0FBVFNBQUFJRHppTkwvNzB6OGZRSUFhQW9CQUFDY0kwci92enI2UkFJQWFCSUJBQUNjSlE3L3YzZjNGeEpBeWZyWG5FNUE4d2dBQU9BTjBlOGZoMzlULzRHNm1EdGR6ZXQ2LytXdnBWSU1yWDBsVldIdTlKb0V2U1lBQUlBM09Qd0RkVFAzV2pXSHhQN0xWUUIwMjl4cmptTDBudTg2QUdoNTRDdVBwQjhmK0VrQ29Ld0tnQzFYVkZVQjRDaEc3NjFOQUZDd0tQdC9aTi9qNmNtbnZwMEE2cWFxUStLMnZsT3BGRnVxYWdGNFRRc0F2U2NBQUtCWWl6My9idjZCdXBxdjZKQzQ1WXBYVXluV3I2bW0ybUgrZFJVQTlKN3ZPZ0NLRk5QK2YrZHovOExoSDZpMXlWZXZTRldJRm9CUzVnQnNYN2VRcWpENThqc1M5Sm9BQUlEaWZQL3BIN1FPLzM5ZzRCOVFlMVdXaVc5YjEvdzJnRzBWSGY1RFZlRU9aZE1DQUVCUkh0NzNlUHI2K0RjUzFabWJtMHRWNmUvdmIvMi9aUVEvRy9yWHB5cEVkUTJkTS9scWRhL3IyL29XMGpNL3Z5bzEyWmExTDZlcVRMM2lLRWJ2cVFBQW9BZy9PdkNUZEVmcjF0L2h2M3B6Yy9PcEt0Y05EYVpTbkFrN3lOMThoYnZpdDcraitSVUF0MXoxODFTVnlWZFVBTkI3WWljQUdpMEcvWDE5L0MvU1YwZWZTRkRWclhnVmhvZUdVaFZPVkJqd05OR0JVMzJwS2pzMnpMV3VxVk9qYmErd3plSGdRblgvYmltWEFBQ0F4dnFiaWI5UGoreDdUSzkvemJ3d1ZkMi9qK0V0MVJ5S1MxSmxpMGNUelZlNEt6NEdBZDV5NWNuR3RnRzBmMzlYblV4Vk9MQ3dMa0VWQkFBQU5FNE0rWHU4ZGVQLy9XZCttT0JzSlFVQTc5NStjNnJDUy9QVkhLaWFLc3JFNTFvaFFGVVQrZU9BM05RQVlFZC9kV0hWbEFHQVZFUUFBRUFqUk5ueGR5YitMajM1bDk5MjhLKzVLb2ZFVlZVVzMydlI2bEJWdThQazVHU2lzeUlFcUdwVjNXM3ZmREdOSGIwMk5WR1ZBVUNWclIyVVRRQUFRTlppdUY4Yy9HTzRuOTdqZk1TL3F5b09xRlhkaXZmYXU3ZFY5L3Q4UWN0TngwV3ZlRlVCd0pZclhtbGtHOEJRNi9lMW8vOUVxc3BCTFFCVXhCWUFBTElXSmQwTy8vbXBxazg4UW9maExjM2ZCUEN1Q29NT2F3QTdyK3ArOFYzWEhFbE5jK3VWMWJhcVBIT3luSUdrMUlzQUFJQ3N4WUh1aS9mZW5jakxqdzQ4bTZyeS9sdmVtNXJ1L2JmOGNxcUtNSzd6cWo0c3hoeUF1REZ2a3M5VUdHcEVvRE4zMmpHTWF2ak9BeUI3SC9uUUI5T25kdjVXSWg4bjVxdnJ2UzJoRGVEZDIyOUtWZm54d1o4a09tdnFsYldWSHhoM2JXcE9GVURNTmRoU1lhQnhVUDgvRlJJQUFOQUlkKzc2ZEJvZWFuNXBkMVBFN0lhcWZIakhyNlFtaTBHSFZXMDdpTnQvRlFDZE4zZDZUZVdIeHRzMnZ0aWVCWkM3cUdUNFRNVXREVTNkcWtBZURBRUVLRUQwNUhhekx6Y09HMVd2VjR0V2dEMzMzWjErLys0dkpPcXYwazBBcmUvVjk5M3kzc1p1aS9qd2h6NllxdkxqQXdjVDNYRmdvYSt5bmZXTDd0bzhuVDczM0MrbG5NVThneTBWdHpNSUFLaVNBQUNnQUU4KzllMzAxZEVuVXJlOGE5dk42V3RmL1hlcGF1Ky85YjN0Vm9DdmovOUZvdDUrZExDNkdRQWh2bGVhR2dEODVtMGZTMVg1a2ZML3JwbVk2MDg3QjQ2bEttM3JPNVYyYjU1S0l6TjVydE9NMHYvNHFsTDAvOGRhUjZpS0ZnQUFWaTE2ZnI4NityVlVCMW9COGhBVkFGV1dpamQxWmtTVS8xZTVBZUI3VHpjelZLbURnelVaSExkellMYnlRL1JLUk9uLzdzSHFOMVJNekcxSVVDVUJBQUFkRVJVR1ZmWjFMNHBXZ0ljZS9HS2kvaVlyYkFPSTc1UDNOWEFiUUFSZ1ZWSUIwRDB4QjZBdXErTjJEMDZuYmV0T3BWekU0Zi9oNjU5TC9aZWZUbFdMU2c2b2tnQUFnSTc1MGxjZVNYVVFVOTZyUGdoeGFkOTc1Z2VwU25mdXVpTTFTZHorZi96WHFpdi9Qek5yWkRyUlBSUHo5VGc4OWwvK1ducjRuL3dzaXhCZzhmQmZkZDkvaU5ML2d3czJBRkF0QVFBQUhWT3ZWb0E3MnJNSnFLLy9kcUQ2T1FCTnFnS29PdlQ2YnhYUGRTakJ4SW4rMnV5UFh3d0JkcXl2YnFYbnBkVHA4QitVLzFNSEFnQUFPcW91clFEaDN6ejRSKzFTYitxcERrUDQ3ci92ODQzNEhxbjY5ai84NSsvK1hhSzc2ckFPOEd3UkFqeXc5VkI3c243ZFJERHgrSTNQMXVid0gvWWZIMGhRTlFFQUFCMVhsMWFBV1BmMnp6L1RyREx2SnVuMmVzcWxpTytSVCszOFJNcmRubGFRVWJXcVd6cEtNWHIwMmxRM24ya0ZBSEhUUGxTRHcvYjZ5MCszMXhWR01GR0hudjlGVDUrOHl2Ui9ha0VBQUVESDFha1Y0TGMvK1lsR0RudHJpdS9Wb0FvZzJrVnkvaDZKZi81b1o2aVMvdi9laVIzeWRXa0RPTnN0VjUxTVQ5eDBzRjBOVUVVUUVBZi8rTC85eE0wSDB1MFZyMHM4bjIrOXRERkJIUWdBQU9pS09yVUNOS1hNdTRucXNqWXV2a2R5WEI4WmN5N3FNUER5T3hQSy8zdHBmSFpUcXF2RmFvQjdodzczSkFnNCsrQWYvN2ZyZE91L0tHNytueElBVUJNQ0FBQzY1Zy8zL0VtbHU5NFhhUVdvci85Y2s0TmpmSS9FK3NpY2dxTG8rNDg1RjNYd045LzkrMFR2N0o4ZHFHVVZ3S0xvdTc5dDQ0dnRpb0FJQTI1NzU0c2REUVBpMEI5Ly8vaDcxL25ndjJpc2htMGJsR3R0QW9BdWliTGdhQVc0KzY3UHBhcEZLMERjVXRaaDhCeS9FQUZSVkFGVVhjSWVZbjNrb3c5L09mMyszVitvUlhCMU1YSDQvN05IL25VN3VLaGEvSno3dWVxdEdBWVlWUUIxSEw1M3JtZ05pSzl3WmczZXVuUmdvYSs5RGk5Q2pQai9tN3BBYjN5RUJqRm9jTXNWcjdhK1hrN2IzckdRYm0zOXZlb3dhMkNwM1A1VE53SUFBTHJxNitQZlNCL2U4U3UxT09ERkRlOXZmZnAvci8zaHJqUVJ6TlRoK3lORUNQQWZILzkzNmZjKy80VjBlS3FlUGUxUjloODMvM1U0L0ljNnpIRW9VVlFCN0J3NFZ1dWI3M05GWlVCODdlaXY3K3JBVG5QN1Q5MW9BUUNnNng3WSswZ3REdDFSM3YzRmUrOU8xTXMzbi9wMnJVS1pPRmovMlNOZnJ1Vmd3RS90L0szMHRhLyt1OW9jL3NPZnQwSStlbSt4Q29ENmN2dFBIUWtBQU9pNnhWYUFPdmpJaHo3WVBrUlJIM0g0cjlzUXVjVVFJQ2JzMTBHVS9FZDd3dDEzM1pucUpBWjkvcmdtd3o1TFZQZFpBS1Z6KzA4ZGVXSUEwQlBSQ2xDWGllOHhOVDNIaWU5Tjl1UmZmanZWVVh5dmZPT0pmNTgrZnR2SFVoVTJyRi9mRGlIK1krdld2eTV0RW1mN3V0di9Ta1VWd01oMGZhcEIrSVduWHR6bzlwOWFFZ0FBMEROMWFnWFljNTlXZ0RxSklYSjFDWWpPRmRVQWUrNzcvSnRCUUJ6S3UyM3g0UDhYZi80ZjJpRkVIYmNUUkdYUGswL1ZNN2dwU1J3eW56bDVWYUkrb3ZSLzdKamJmK3BKQUFCQXo5U3BGU0J1VTdVQzFFdmRENU9MUVVBY3l2ZmMrL24wa1IwZjdHZ1lFRlVwbjlyNWlYYXAvMS85UC85M2JRLytpeHorNjJQdjFMQldnQnFKMHYvSkMydzJnS3JaQWdCQVQ5VnBLMEFjc0w3ejNiK3Q3YlQzMHNRd3dNOUZlMGFOQnR5ZFR4ektQLzVySDJ0L2hlaURiMzhkUE5NUEgxVXVFWGFkbUQ5L3RVc2M5RGYwOTdjM0R2UzMvbDd2M25aeisrZWg3ci92czduOXI1ZjJqZk9SelduMzRGU2lXa3IvcVRzQkFBQTlGNjBBc1dxdDZ0dk54VmFBMlB0T1BUdysra1M2djNYTG5wTTR5TWRYU2VMd2YzaFNjRlluNDhjSDByYStVK20yZDc2WXFFWUVNU016WmpKUWIycUZBT2k1dXJVQ1JDVUE5ZkROOXNIU0xXYWRuZm41ZlNKUlB5UFRnMHJQS3hJdEdQY2N1a0VyQnJYbk94U0FTdFJySzhBZDZWM2J5cnJCcmJNdmZlV1JSSDA1L05kWGJBV0lRNmdRb1BmMkhyN09uenRaRUFBQVVKbTZiQVVJLytiQlA2cjF3TFdTMUhralFPbWk5Ri92ZjczRklYVFBDMXZkUlBmUTZORnIwOFI4ZjRJY2VESUFVSms2dFFMRUFMWi8vcGs3RXZWUXAzQ0lNK0xmUjExK1hybTRnd3Q5NmU2ZktVZnZoVGo4eDlSL3lJV25BZ0NWcWxNcndHOS84aFBwZmJkVXY1MkFlb1ZEbkJIL1Bneit5NGNRb1BzYy9zbVJKd0lBbGF2VGJXOU1vTmNLVUE5MUNvZEtGMlgvOGUrRHZBZ0J1c2ZobjF4NUdnQlFPYTBBWE1pOWV4NjBGYUJpcWpIeUZpSEE3LzdqVFFiVWRkQyttU0dIZjdJbEFBQ2dGclFDY0Q1UkdmSi9mUEZQekFPb1NQeTUvOTdkWDFENm43azQvTWQyZ0lNTDZ4SXJGNVVVVVZHeGYzWWdRYTRFQUFEVWhsWUF6dWZIQjMrU0h0NzNlS0wzOVAwM1I0UUFuL3ZIbTlxbDZ5emZnVk5uS2ltZStmbFZDWEltQUFDZ051cldDdkRGZSs5TzFNTTNuL3EyTXZRZWl6OXZmZi9ORTZYcmV5ZUh0UVFzdy9qc3B2Uzd6LzJTUHpNYVFRQUFRSzNVcVJYZ0l4LzZZUHJVenQ5SzFNTlhSNThRQXZSSS9EbkhuemZOOU5STEc5c3RBZkVyRnhZSC9pajVINWtaVE5BVUFnQUFhcWRPclFCMzd2cDBHaDd5OGxjWFFvRHVjL2d2UXh4dW94SkFOY0Q1UmF1RWtuK2FTQUFBUU8zVXFSVWc1Z0RzdVU4clFKMElBYnJINGI4OFVRVnd4N1BiMHNqMGtDQ2c1ZW1UVjdYL1BLSlZ3dnBFbXNoM05RQzFWS2RXZ1BmZitsNnRBRFVUaDFTREFUc3IvandkL3NzMWZueWczUllRTjk4bEJnRng4STl5Ly9nekVJVFFaQUlBQUdwTEt3QVhFeUhSSFhmK1FidGloSlZyci9yNy9CY00vS045OEkyYjd6Z0VsOUFhRURmOFQ3MjQ4YzJEdjNKL1NpQUFBS0MyNG1EM3dGY2VUbldnRmFDZVlrWGc3OTM5cjlLUER2d2tzWHp4NS9ZN24vc1g2ZnZQMUtQYWhucUlnLzlpYThDZTU3YzJibGhnM1BiSFlMODdmckk5N1owYWR2Q25LQUlBQUdydE94Ti9uLzdtdTMrZjZrQXJRRDFGVVBRN24vc0Rjd0dXNmV2amY1RisvKzR2dFA3OHBoTmN5TVQ4aG5ZMVFJUUI4V3Njbm5NVS85elIzdkRwMXU4amJ2dGp0WjhlZjBxME5nRkF6VDI0OStIVzRmcy90Ry9ocTNiM1hYZW03ejM5Zy9iTk0vVVMvZXRQUHZWWDZjOGUvdGRwZU10UTR2d2lNUG5TVng1eDY4K3lSRlhBNUNzYjI5VUEvWmVmVHJkY09aOTJiSmhMMjlhZFN0dlhMYVM2aVgvZU9QVC9vSFc3UHpHM3dXRWYzaUFBQUtEMm9rYzVXZ0VlZXZDTHFRNyt6WU4vMUw1eHJzdDhBbjRoRHJlZitQUS9TNS9hK1luMDI2MHZRY0F2eFBkcjNQcEhyNy92WFZZakR0TlJHUkJmWVRFUTJOYTMwUHIxWk9wZjgxcFBRNEU0N0I5WVdKZW1YbmxIZXVia2xlbVpuNjkzNEljTEVBQUFrSVhGVm9DUGZPaURxV3B4cVB6bm43a2pQVEppQ24xZHhTRTN2bWRpZU9QSGIvdFlLdDMzbi81Qit0TGVSNVQ3MHhYbkJnSWhRb0doSzE1T1c5YStrcmE4NDVVMHRQYlZ0UDd5MTlLV0sxNXAvK2ZuL25xaHYrL2NhMnZhZngySC9NWC8rU2N2cjJ2L3Vuam9kOWlIcFJNQUFKQ05PclVDL1BZblA5RTZZUDZkTXVvYU96TkU4cEYyYTBDcFFVQWMvQjl2L2Y1OW45SnI3Y1A2UWw4NjJQcEtDazZnTnNSbEFHUmpzUldnTHU2LzcvTzFDQ080dU1VZ0lGb0RubnpxMjQxZkczaW0xUDhiN2RWK3NTSEI0UitBUlNvQUFNaEtsSFhISWE0T3Q3bGFBZkt5R0FTRTMyaDkvL3ptYmY4MHZlL1dYMDVORWJmOWY5UDYrZmhtNitkRGp6OEE1eU1BQUNBN2oreDdQTDMvbHZmV1lzQ2JWb0E4eFNFNXZ1Sjc2TU03UHBnKzB2cktNUXlJUS8vM1d0OTdULzdsdDlQaEtmMzlBRnljQUFBdW9Lb1NVYmMyemViN3FqUGk5eE5yektJRXZ3N3UvT3dkNmQ0dlB1am5OMFB4TXhubDh2RVZZY0Q3V3NGU2hBSHYzbjV6TFRjSXhEOXZWTUg4dHdNL1NmKzVGVHo1bmdOZ09TNzd3RWQvL2ZVRUFNQmJSQUR3N20wM3BmZmYrc3Z0WDkrMWZWdFBaejdFWWY5SHJZTiszT3gvcjNYVEgxVW1EdndBcklZQUFBQmdpU0lBZU5lMm05dS9ScFhBaHY3K05EdzArR1l3c0ZnMWNMSHFnVGpFejgzTnRmODZEdmt2VEU2bnVmbjUxcTlUN2Y4c0R2MlRVMU1PK3dCMG5BQUFBQUFBQ21BTklBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBQUFBQlJBQUFBQUFBQUZFQUFBQUFCQUFRUUFBQUFBVUFBQkFBRC92UjA3RUFBQUFBQVE1Rzg5eUlVUkFBQURBZ0FBQUFBR0JBQUFBQUFNQ0FBQUFBQVlFQUFBQUFBd0lBQUFBQUJnUUFBQUFBREFnQUFBQUFDQUFRRUFBQUFBQXdJQUFBQUFCZ1FBQUFBQURBZ0FBQUFBR0JBQUFBQUFNQ0FBQUFBQVlFQUFBQUFBd0lBQUFBQUFnQUVCQUFBQUFBTUNBQUFBQUFZRUFBQUFBQXdJQUFBQUFCZ1FBQUFBQURBZ0FBQUFBR0JBQUFBQUFNQ0FBQUFBQUlBQkFRQUFBQUFEQWdBQUFBQUdCQUFBQUFBTUNBQUFBQUFZRUFBQUFBQXdJQUFBQUFCZ0lEUEk4elNGYmJsY0FBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiYmE4NmRjNTY2MzVmNDE0MWFlZjYwMDIyN2IxYjlhZjYiLCJvcHRpb25zIjp7InBsYXQiOnRydWUsInJrIjp0cnVlLCJ1cCI6dHJ1ZSwidXYiOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMDAsIm1heENyZWRlbnRpYWxJZExlbmd0aCI6MTI4LCJ0cmFuc3BvcnRzIjpbImludGVybmFsIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJmaXJtd2FyZVZlcnNpb24iOjF9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiUkVWT0tFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTEyLTIwIn0seyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMy0xMS0wNyJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTItMjAifSx7ImFhZ3VpZCI6IjNlMDc4ZmZkLTRjNTQtNDU4Ni04YmFhLWE3N2RhMTEzYWVjNSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiM2UwNzhmZmQtNGM1NC00NTg2LThiYWEtYTc3ZGExMTNhZWM1IiwiZGVzY3JpcHRpb24iOiJIaWRlZXogS2V5IDMgRklETzIiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJ1ay1VQSI6IkZJRE8yIEtleSAtINCy0ZbQtCBIaWRlZXoifSwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sImlzS2V5UmVzdHJpY3RlZCI6dHJ1ZSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVsZXNzIiwiYmx1ZXRvb3RoIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDc1RDQ0FsaWdBd0lCQWdJUkFQK1czUXRud015WGFmdVFvTmFYY3FVd0NnWUlLb1pJemowRUF3SXdnYWN4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSkVSVEVPTUF3R0ExVUVCd3dGUkc5MlpYSXhHakFZQmdOVkJBb01FVWhwWkdWbGVpQkhjbTkxY0NCSmJtTXVNU1V3SXdZRFZRUUxEQnhJYVdSbFpYb2dRMlZ5ZEdsbWFXTmhkR1VnUVhWMGFHOXlhWFI1TVJjd0ZRWURWUVFEREE1SWFXUmxaWG9nVW05dmRDQkRRVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR1ZuWVd4QWFHbGtaV1Y2TG1OdmJUQWVGdzB4T1RFeE1qY3hOREE0TUROYUZ3MHpPVEV4TWpjeE5EQTRNRE5hTUlHbk1Rc3dDUVlEVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUkVVeERqQU1CZ05WQkFjTUJVUnZkbVZ5TVJvd0dBWURWUVFLREJGSWFXUmxaWG9nUjNKdmRYQWdTVzVqTGpFbE1DTUdBMVVFQ3d3Y1NHbGtaV1Y2SUVObGNuUnBabWxqWVhSbElFRjFkR2h2Y21sMGVURVhNQlVHQTFVRUF3d09TR2xrWldWNklGSnZiM1FnUTBFeEh6QWRCZ2txaGtpRzl3MEJDUUVXRUd4bFoyRnNRR2hwWkdWbGVpNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVR1dGgvM2NjVmxJL2hHeUo3elNOYXFoQ0xEeUtNOUp1Wk5qY1RzbkRBWXlSRE9wellFV2lMcXMzamRmVktkM1Zndjgvaitmb0RNU01wSSttd2pPei9wbzJNd1lUQWRCZ05WSFE0RUZnUVVwcUl0eFlwTXRhdG9rMTJSakFpZXlEVWhhcG93SHdZRFZSMGpCQmd3Rm9BVXBxSXR4WXBNdGF0b2sxMlJqQWlleURVaGFwb3dEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQVlZd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ040Z00rOXUzTkJMTWtkRVcxUGFERzlPbFpaaVViNnZoQ01NTmk0NXEwNnNDSUI4QThLbDh0UlYvR2tKWVBTK3J1eTBuTFMzVit0Q0Z6VElFaUJBWWs3aUEiLCJNSUlDclRDQ0FsU2dBd0lCQWdJUkFMaGQ5NC80MzEySW16a2llbTlrVXZnd0NnWUlLb1pJemowRUF3SXdnYWN4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSkVSVEVPTUF3R0ExVUVCd3dGUkc5MlpYSXhHakFZQmdOVkJBb01FVWhwWkdWbGVpQkhjbTkxY0NCSmJtTXVNU1V3SXdZRFZRUUxEQnhJYVdSbFpYb2dRMlZ5ZEdsbWFXTmhkR1VnUVhWMGFHOXlhWFI1TVJjd0ZRWURWUVFEREE1SWFXUmxaWG9nVW05dmRDQkRRVEVmTUIwR0NTcUdTSWIzRFFFSkFSWVFiR1ZuWVd4QWFHbGtaV1Y2TG1OdmJUQWVGdzB4T1RFeE1qY3hOREV3TVRSYUZ3MHlPVEV4TWpZeE5ERXdNVFJhTUlHZ01Rc3dDUVlEVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUkVVeEdqQVlCZ05WQkFvTUVVaHBaR1ZsZWlCSGNtOTFjQ0JKYm1NdU1TVXdJd1lEVlFRTERCeElhV1JsWlhvZ1EyVnlkR2xtYVdOaGRHVWdRWFYwYUc5eWFYUjVNU0F3SGdZRFZRUUREQmRJYVdSbFpYb2dTMlY1SUVaSlJFOGdVbTl2ZENCRFFURWZNQjBHQ1NxR1NJYjNEUUVKQVJZUWJHVm5ZV3hBYUdsa1pXVjZMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkNCTHlqL20zUkR6WTNJRmQzTXN5ZzRleG1rTEdNaEM2YUdIK1VtemwwMWJiVG1vNklRY09hb3ErcmFJRndHdmkzc3dJQ0lQQ3FVS0ttR29oclNVb0t1alpqQmtNQjBHQTFVZERnUVdCQlFLOFlWOXpZYVhFYWc2My9OQmtoeXVBUTN2UERBZkJnTlZIU01FR0RBV2dCU21vaTNGaWt5MXEyaVRYWkdNQ0o3SU5TRnFtakFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJoakFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUFuTjh6ZHR3RnBEME8xaFpWMHpZU3ZoU3hpOG44MEI3aGwySTd3SkdVb3l3SWdQcUd1VW92a2E5eitLenZVc2YrR05kUzVZYm54NjVPenlxeENOVHhLalZRPSJdLCJpY29uIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFJQUFBQUNBQ0FZQUFBRzBPVkZkQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUF5UnBWRmgwV0UxTU9tTnZiUzVoWkc5aVpTNTRiWEFBQUFBQUFEdy9lSEJoWTJ0bGRDQmlaV2RwYmowaTc3dS9JaUJwWkQwaVZ6Vk5NRTF3UTJWb2FVaDZjbVZUZWs1VVkzcHJZemxrSWo4K0lEeDRPbmh0Y0cxbGRHRWdlRzFzYm5NNmVEMGlZV1J2WW1VNmJuTTZiV1YwWVM4aUlIZzZlRzF3ZEdzOUlrRmtiMkpsSUZoTlVDQkRiM0psSURVdU15MWpNREV4SURZMkxqRTBOVFkyTVN3Z01qQXhNaTh3TWk4d05pMHhORG8xTmpveU55QWdJQ0FnSUNBZ0lqNGdQSEprWmpwU1JFWWdlRzFzYm5NNmNtUm1QU0pvZEhSd09pOHZkM2QzTG5jekxtOXlaeTh4T1RrNUx6QXlMekl5TFhKa1ppMXplVzUwWVhndGJuTWpJajRnUEhKa1pqcEVaWE5qY21sd2RHbHZiaUJ5WkdZNllXSnZkWFE5SWlJZ2VHMXNibk02ZUcxd1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZJaUI0Yld4dWN6cDRiWEJOVFQwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOTRZWEF2TVM0d0wyMXRMeUlnZUcxc2JuTTZjM1JTWldZOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXpWSGx3WlM5U1pYTnZkWEpqWlZKbFppTWlJSGh0Y0RwRGNtVmhkRzl5Vkc5dmJEMGlRV1J2WW1VZ1VHaHZkRzl6YUc5d0lFTlROaUFvVFdGamFXNTBiM05vS1NJZ2VHMXdUVTA2U1c1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRveE1qRkRPVUkyT1RWQk1ERXhNVVUxUWtSQlJFUXdRa0pGTVVaRlJqaEdSQ0lnZUcxd1RVMDZSRzlqZFcxbGJuUkpSRDBpZUcxd0xtUnBaRG94TWpGRE9VSTJRVFZCTURFeE1VVTFRa1JCUkVRd1FrSkZNVVpGUmpoR1JDSStJRHg0YlhCTlRUcEVaWEpwZG1Wa1JuSnZiU0J6ZEZKbFpqcHBibk4wWVc1alpVbEVQU0o0YlhBdWFXbGtPakV5TVVNNVFqWTNOVUV3TVRFeFJUVkNSRUZFUkRCQ1FrVXhSa1ZHT0VaRUlpQnpkRkpsWmpwa2IyTjFiV1Z1ZEVsRVBTSjRiWEF1Wkdsa09qRXlNVU01UWpZNE5VRXdNVEV4UlRWQ1JFRkVSREJDUWtVeFJrVkdPRVpFSWk4K0lEd3ZjbVJtT2tSbGMyTnlhWEIwYVc5dVBpQThMM0prWmpwU1JFWStJRHd2ZURwNGJYQnRaWFJoUGlBOFAzaHdZV05yWlhRZ1pXNWtQU0p5SWo4K3ZyNVhJZ0FBRS85SlJFRlVlTnBpRERsNmdRRVA0QUxpQkNDZWhrc0JFdzd4LzFDc0RkVzhEMGtNQmJCZzBRZ0NBa0Q4RVVuY0NVby9SbExEaUc0QWlnUU9JSXVrOWk4UU02TzdBSjltZEhYL2tjUGdQd21hVVF4aEl0Rm1kSEFGWkFBM0VKOGhFQnYvY2NqcmdBeUlCMkpqTWwwQURvTnBEQlFBRmlJQ2lxQUxZR0FkaVpiL1IzWUJJNTZBd3V0QzlMeHdnQVRiUGRIREFPWUtKU0MraDBkekFCQzdBUEZlYklISWlKWXZDQVlzUUFBeEVpZ1B3b0g0Q3hCdkpTVWEveE53RVNPK0FnVTVTek9pYWNMcVBTWTB6VllFRWcrR0lTeGtaR2RHcEF3R1R3ZnBaSlFGY0JmOEo3TThBT241eDBRZ3RjR3dFN0ZKR1JmWVMycTlBQUw5QkxMMVRQUkNGUjBVWVVrUHlDQU5pRTh3VVZDZ2dvQWxzaGZxU0MxTWtMMEFja1VqT1dtQkNWdHRRNFR0akxoaUFTU3hCeTBOSUdNdDlEQURDQ0JDNVFFNitBekVQR2hpMzZEdENHU3dISWlqaUsxWEdJaE16ZitobGpPaVlXNDBmaWNRUjZMcFN5YTNnWU1jNW94RUpya0tMT3JuNEtxaW1mQllERE9BaVlFeWdPNXdrUG1xdUFwVUVCQ2xNSE1SNDVCYlFMd2R1VUIrRGNUbmdkaUlnZllBdVZaZ2hZV0FDQkIzazlHMFFNYVR5WERNTDVBRFFxR2NaZVFVUlVnZ2g1em1EUk0wSHc4WVlFSnJkRlNSRUkvbUJGSTdTWVg1UWlqZFNvTGpUNUZZUHNDQUNiWXFPWUZBL0ZJVG5JYlM1dGhxbzFRYU93SzVrRHVGclNTY1EyUUxsMVFnQnpXdkh6MjZXQWdVRnRKQS9BU0wvQjFvdGowRzdkTktRaHY4b0toa0phSTRKcnFUOUJSTkl5akUvZ0N4Q3A0bXpGbTBoSVlYQUFRUXFlMEJsQVlWMUtMdlFMd2ZpTy9Tb3B1SURIeUFlRE1KNWN0L1loVVNBaWVnaG0zR0VhL1k0dmNmVWhPTW9oRDRqeVZOeUJEYjl3R0NxNFE2M0xoQ29BR0w1WXg0TENlVTR2K1Q0b0FsUUZ4UFpobVA3cEFMaEJ5QjdnQXpJSTRtWXdRSkZ6REUwZXJDNllDVFZMU2NBVWYzRjI4bm05cVc0eHFnbUlvdkRkRENjblN6czlBZDhKOE9scU03b2g1YmRVd3Z3QWZONm1BSGFBOUFVL0F6Y2tsNGdJTFVUV25hWVdLQzlna290WnpjQmt3Zk9mMis1MVNJZ2pKWURZdnNBQzRpTlV2Z2tmTWkwb3dtbUozSURwaEhwT1lsZU9TMkVXa0dPNngyUlhaQU9KR2FZNm1ZRytZelFkdHdsQlNyRE5ER0tUbTVZQm9MdEYzM253cU9JQmJzdzFjYmZxRkRJZVNJendIY2RDd041WkFkZ0J5Y0xUUzBGRG1xSDZPSHdDY29YVTJueWdnakN2aXhOUmhvNVB2UHVOSUFSb09CeGkwanZDMmlEelRxbGhQVkwyQ0VSa2taaFJZekEvRkdmT1VHQzRHZ0FybThFNHZjR2lEZXhBQVpjQVIxeDAyaFJiazVqb0tIa2R5dUdhN0JpaEFvcHJpMFpDSWg0WUJ3RHhGcXJVbnBUUUVFRUNYakE4UUNEU0F1aFBhNFNDbHBRWlBqb05IWFJiUjBIQk9WemR2T2dEbUVmSjBCTXNXRjd2a1NwSmppQmVLWGFQS2dTbm9oQS9hWkg2UEJFZ0FGYUE3endLSHVJOVNUeU9NcHZXaU5BQWswK1ZsNDdEMkxaT2N2ZWdlQUhwTGwvVGpVdkVQempBQVpMWjEwTkROVzRGREhpdVNlQjdRTWdNVlFTeTRTNFdCaEdtVFhTQ1R6RlhDb2tXZkF2M2lHckFDb2d4b1lnNjFGVFdTU3BUWjRpR1N2SDU3YW4yQkFrRHBFQ1FPOGRHcThFd00yTStDZlhQZ1BUYjF4cEtTQVloeUd3VUo5c0hnZWwvdXdkV1QvRTVzQ2RqTkFWaXFoQjlSL2hxRURjS1dJLzRSYTQrdlJQRy9CUVA1Q3M4R2FJbkNPRUFjeVFOYXBnY0JNcU1hVERNTURZRnM2Z1JFQTY1QVVaekFNVHdEeTIyd291eHM1QUpDNzRFcDBjSWdudExHRTNJcGNRYWRBU0VWcWlzTURBSGtJZ0piREFURFBnc1l3QmRIa3dwSGs5OUFwTUR4QUFXQ0pwUXFrTmdnanNTQjFwbEhCcTQvZUlXTmlJR0Z1blFLd2t0d1lvckk3ME1jVE5FRUI4QjJMd3NCQlVtamRvcko1THRoYWd2dXdLRnhGbzRZSnFXTUw5NmpvQmxNc1ludVljRmdDYWlGeTBpQVFEcENnMW92SzloL0ZJdGFOYmQwV0RMeWxRWkoyUk92anUwRjdjMG9NNUMxQ0k2WHd3N2FZNlFyNnlqbGtBRW9Cd1RUTzQ3dWh2Ym43TkxibkFvN0lRR2tKWXVzWXJSa0dyYjlYV01RdXc3SWpjZ0NBdGx4WmtUQW1NQlFBcUhNbmlrVmNEMWR2OERnRDl0bUZvUmdJVTVFNmR6aHJKR3dESXFkd0ZFUkRLUkRtWW1uU2I4TG1MMEp6VTlkQXJTVjhBd3FERU93Q1lsZGkyeUdFQmtXMWNBd29NQTFTeno5Rzgzd2RvUWdqZFc0T3VjRFVIV1NlQjBXTURKckhtd2xwWWlIUkVsZ2dnUHJ1bDdESWY0UG10UTBNa0swQjFCdzhCUTNQK1VJTE5pMXFOYm1wTVRrNmc0SDBmWVhVQktCMVQyUlBqMUVqTDJlZ05XTnJhT2haVUl0UkdNMCtpdVlHV1dqZ3lGWUc3SnRSV0tCdGYyZG9RMFFCcWNQRkRDM0Fia0hiSXFDUy9EWTlrZzlBQVBLdUxTU0xJQW9mTmFSQUpCSVNJN3NRV2tTUUpVWkptZDN3SmF4ZUlvZ3NFSXd1aEQwSTBvTkcwVU5sUlE5WlVZRVFCUktJa1JIZHlDTHlJU3FRSWdzaXFNZ0tvWWNTcEZEcjlKL2gzNll6dTdQN3o2eTdmeC84b0xPek8zTytuY3VaTTJmT2h1RWZJS09ZZmdXMFFFSGhQeEVCV0ptaE1Dc3pMb1F5YW1tTUtQTnhEdzZlbDM3L2poaTJDVmdaQTJUZ0cyMkhwSUh6dkl2d3FsTnNPVVRhRzNyR2QrbytrU1pnTVZVV3ovaHM5TWlMNTBEUVhVNmNobTN3eUkvNWJ0THpPNk5Hd0h5cVdJOUdYckdUaXdyTE4wZDZDNld2MEhqR09pcnZYaFFJR0ZFWUcyUTBnL3RldmtBMzVTc2tiZE1ObFVSRTNWZ1FzRWR6WWJTTjhoencrZndQTkVEbmFLeEN6NmF5VWcweUMrQ1VsZStSWnplWThYZ2RwSmVFVStaSGpiVUF1dVM5c3RrQ1JqMkV2MGh2M0xTN2J6ODkxMnVqcEE5b3o4OEdBVzdON0FkVnNNYXlUbkdUeW5ua2t1Y29yVStNRXVBbS9GWklIc1FJQytnT084M2xPdW9RcmFiR0FPMjRQV05nL01nZ3ZTT0x1YjZERktsanFiU0FVUmRWTlNxbXNYRzBlT0xRNG1XNGNTUGdpaUw5S1NUYzVLS0VLbERIdCtrTlFrQUo4UDd3NlAxZkN0SEVmbEJIdEJueVM4QXpKZzFENXF5SGFBUHJ1RlpoTmRxdVM4QkZKcTBMTk9NRlJRRFhxVXZJT0tOTGdPd1QvQUFTeHNnNEFRZEZibnU5dzRzQTJWbmkzZS9mY29nbmJqQ0syUVl2QXVUbDZIU0lON0E3TjBwcGJTb0Nqa1JJeVRFSlBIWjJXdEpjV1FJYTBsQjRnWjIwamhCWUl4T1E2N2lZQmVrSlhFa0tVL3M1bVFCeE9oRlBmWXhBK3FKWUh0c0VBY0k1dWd6K0g4emtab0VGSVJYZUFYODdTbU9NdlpVaHRnQ3hXdnhEUUc2SXJMZVJ3UEo4alBFODdvSjlMNVJsanI4M2lhVmtWVWpDbzZOaXVhYjl3ZFlzNUhRTUx4UXRJSXltVjYwcHZKY2RJbFhJRG1EWm1VeS9MN1pROE5VQTk2eTJVSTk1MHY5ek1pRVpubDJnd25DaFFlMkZyU0cwekdsSXdFU1A5WUFKQlNRSWlrSWdZRUltby9pc01seElIa1FEWEZ5OERCR3gwWWw4d3dVSDljQVlObHdQenFieDUxc0lBNWFaZnhyd1B0T0hzYmw0VWYxSXdBdm13Z3pEaGZjRXVNZjA2VFhPc05PSEJIQWZzcWcxWEhpNXovd0hReG9YQnBDQTI4eUZPZ3VGNmU1RW84N1FaTGpzUXRVRkpJQTdIenpaQWdIRDhHL1FUeG5vUG1mRDlON0lwTjN4ZWl0SXdoY0xsUkdhSjU0VHdyQ09RNHBXYUJMY2VITEt1UnptQnNJV3k1VkM5N2RySVFpdlFxZVRBSzZKYklIMFFMM2JSVUZBbCtKNmZob1FjTUp0blpFcE5Va1oxMk11Zkk0aWZSZEhBTGVwV0JwekFyaFFvME5jRjBDOFZEemtlSXdKV09abEZQSGFHa1BzamFud1p4WHB2VzRFZEN0dWFvNGhBWncyTzFjMUN6Z3hoVW5ibndadi94UFh6VGtDK2hYS3lhR1l2LzBDTnoxQUJ1ZWJ2eThtd25QT1hadTlGQ0VPMlV4YWV3d0lrSjI3TVB6ZjVTQUUvSVRraDVFRU5rWmNlTTY1cTBSSEZWWUI0d2ZJbjZWNkhWSGh4elBDR2dscmk5R0ZuWjVqUlpic0JhbmlxMS9oZFFsQTFFakw0ODhSRTM0aHRRQmZ3dnNoQUlFdU5Pc2MvK01XZHpXTTdVbnlJbXFoVHh6amxxK05WYitWZHdZaHdDMXV0TitocVV2czgrTWcxT1ExOEFUQUpMSlBJT2svSE9YaGVDUzhXeTRvWmk1WEJEMDRpU1E4aElUZnZqemk0azkyWE1iemdXaDlmazdhMkh0SE44S2RxVHhTVkdaQndreUd6L0Rqb29keFFnTHRiNlJ5Y25RcEpEN1BNYWlSRi9OVmdQbU4xNVBnWWZFeDNRV0FlYlBZR2hhRjNQZTdxTno2VkI5a2FnQjdUQlhDcHZqT291RGlNNmZHZkpkTmorQUQxSGV4a3BXZ2prS3RDL0dCQWZIcDRjT21HYlY1ZXZ5K05Cdk1wa1hXRXBxK3BrSnlCeGk3MGxzaURJL0UzZ0x6dThNc2ZnblEzcm1HV2xGRmNYeDU2RkprSklTYW1NWk5MNW1pZmJDSW91Z3E5cEtFeXBJd0E4MnVsTjBNTkFzcSt4SmhvV0NaNWFPWFZwYmFBN09Ya2Q2TW9xTDhFSlJtRDVNa1A1UWEyQVBMTXN6ZlBXdDNodE9abVQyUE0yZm0zUDJIZzlkelp2Yk0zbXZON0wzV1h1dS9Hc0VmVUcrUXprTUNaWnQrQnF1UG82OStUdEJGVTR0VVlpTktPcjMrb1M5MU5IbXYraENnOGY1T1B6c3NYL3FGd1RFRnZHZFlONGgxbnFCUFZGb1IvY3pVSmxxb0xjSjVLRWFYcmdrM1MwSktrNnhSeXZuOXRhb3h2dCt6K0Qyb2d6MGpnZkFQU1hsdnFMOHVzcGZvZDNIQTJoVUgzSnZhaHJsUDNpRHp4YTVpcDFNQUJRdUhUejJEeUx3NFY1S0htV0VxVHBRSzhSQlRBSHRqKzlTSmNKdCtaMzZubE1XWENhL0ppdkF1TlhwTWY5NlRuSVhqTjFvQm1KTmY5Z3pRbGhRRzZDOTl1ay8xQ0JUaTZQVVIybGlyRnFrNW43L1RvQmx1cjFKd2VGejc5RFFGWURYOGhWUnlKSktTMXZLcW5TWGxOQ2VFZGF3KzNUK2tlTSs4RGE3MUtBUlA5NlB5Ly9qU3FNRExlRURIWXFzRTB5RVVXZ0Z3VXIydUhZWGhZMlNDdHRpMG0rNFJ4c2txakN6VHZQYXIwclY0RkdKWndqYlBWb3ZqaUw1dGVqV0RBbHl2SFRva3RVTlBiSUNMOTE2MVdIcXBTYmN5WjJzWEZPSVdqMUt5Ly81K2d2WW1TYVdRL1ZWRlZBREQ2dlJjelBOeFRvelN3ZVR0Y1g5V2pwR1VzRVBuZTZNUVNRSkxUR3Job2lJb2dDbEVGeWZHZXFQYTRRd1lVYlRibXNqZmNwOUhHZUpXTHBxdFk3czZqd3F3VFB3TDhRVUIxK2RncWRTUitFV2FIeXVrZHExTlcwelJzVjZZQndXWXFqZHpjNHp6R0FCODVYdWs1OEpVbXlWZjROc1k1ekwyMXpSQ0FTQTJKYUI2VllSeldPRU8wZzQvS3c1ZTRQQTZYY2ZtcVlqbkVnbTNYV0s2OWVNb0FGNHpDT1JPc3p5K1MyMzBWaWt6NkRvRW8wTVZJVXFtNEFpMWxxYlhXd0ZJZVZ4c2Vld0c3Y2hGMHR4VUxQWENNb2xlWTR1M3g2WjZLQUJQTDVzdzUxb2NhK2lpcjNReVRBVWJ4WTVDMTRBSGp2S2QvZEpTZ0hhZG84S3F6YjBqZG5UWkR2RmdLSVJ0d29Fb1g0cUwvS3lrQ25DNWhKY0UvRnlWNDFJbm8weGdBdUpzUElTRVlvNk5xd0JqeEQ5L0ZQd3E1WTBkcWduODZlU1NPVjVWUmVnTU9RNU8wTkZSRllDay9hQnlEY3p2YkdOKzQrVFFjQ3hWUlhnZzRCaDJHdHRzRllBZHJ0ZDhHaklGeXphNGNjOGQ3bGJaclBXUjh4dTJDb0FwVVIxcTlaWllWcXB6YURnbXE2eTJWbjAvVEdwUXNWVXJBQXNMTDBrR1FSVURkREhvVUN5UXJYR0tsT01uRENBTXZUaElBYXJuRVNKaGZuSmpXVmhRZzZoNlYzVys5ejllLzNHSHZpYThZRnVXT1ByZm0yaFFXT1BnT2gycTlqSWJLamhPZHFuQ0gyNml2aEpNVzgyWFN1UVJZWGl2VkN0QUxYT0NzR2tDSWo4cDhDQkFqdnU0Q2p3S2lGdGtsL09qQXZlZG9KcGE5TkNkUmdITUZFQzZrbDlTYXhIclNKRGtZYUp2dTJJSTN3emVoMUlKNXk0aXQvNzVQdCtQVlZQL1B3VUk4dUpkVUxCTzg3U1R2cFZtL0gyN1RnMExDellXNDBMNjFLMEFKQ29HK1l6NTdiaUNkQmpUWjBZZDI1OHI0YTd4dktDZnp2ZEJWa0ovRklCRXl1RUJCdzRNYVNndldKZlJmYlpMOUtDTlJvQ2QyNkM2ZDhoOG1DbFoyamVrc2ZFNTd5eXYreXhaaktiRlhGZGtpVEFhZk9RK29LU1dRTmdDWjBMT096c3E0K3VWYXBqTWVVT1k4NjQ3TUxXa3dnL2JGajVUOHMwZituTURydmwzanNjRHF0Q3dVaWpkK1lrSUhoS0VBeGFOWHAzakRyUFJrV1YwTWJ1Z20zSThIamJUSVJGZUIxRUEvUDAyeERhVGN0eGhzb1ptWm5pOWpoeVBSWXZsdzBxVTEyNFVnSWllenl4T2FNdjVXb0Mzd0dVWlhJZFNHQi9rZUJ5bWlBODdiQlhZSStpdUg4S3JvTXV5OFp0eXZ2QXhjWFB2MXFIdDlkcjJ4emtmZzA3TDR3ZzJQVnp5RE53K2k1TW1TUHBWdHVxQmNTcXNoMU5veStUMVRTeEF2eWRaK2tLWThqZUxaL1hQYnQ5YXk0dmNJOFhCYktuazRlRVhoNUZqZDhpOFNPN2VPWkpPWm0vV3NDMDg5SUphQWVLbGljTWp1TU95QVFweHJoT0hQQUU2M3dVV3g1R2tneFByZTZteS8ySHVlTXp5WXJ4YWozZGpuaHUwSHYwOGFIbnNBaVA4YWdVQXNGclpWTTBpVE94cE4rNjV3V3F4Uy9KaGlwdm4vYUw2cE4vRXZvSWdwRW16M05nM0hJdkZmOSsvbHYvaW55QUZNUGEwYlpXVVI2UjJrUkdIYkhDRGxMTzFiVEN2bG5sY0NqaDRUUVRiZTVpVFJlWVlFMkVhWHVIM1VBZk5HOWVwY0cwQUUrZEFKNVBNUUxEdUZzdGpJWm55WlhBSld6amdXclVwbzloYmxhQ1BrMDNkUVpDdWJYMXUrQVlEOXdWc1ZvNTQvNTZ3dEF6WUpUdlJ5YWl1NXA2dDhCK1MyZ1hVSXlzQWdQYk54c2RNR0RtZXRwT2NyRkxIR1dyRzJaUUdtbmIwTThlbTBTZ1VNZVNWRVdRUVJxc08xeDhaS1lPY3pGSURLZmcyWGxwbzl1QWJmc2EyNGFnY1FWQ1pFU0VjeHZJRllUTnhCaU9jN0JLRHNIeWJzaTRyOU9HTFJKSWRseVp1cW1wbEdIM3JkalZYSE9JQkhvYXcyQU9jZDBNbEpnTnBFcUpJQWtrSUtMMGo1RGpNbGNsT2xwRkI3RVZZallPWnV1amVGZmNpYVZERlVsV1RiZE9nalNTMkgrOTBNclVHTVFqTEEzNWZwR08rUE9tRjBpU0x2bFZ2YXFuUDc5UjhXK0prRzRvbnBVeVBIeVQ0MjlPNldEM280anYxSnVmNEtNbDZKMk5mUUwxem84OTBrS3JnRGJLb0cwanU0VVlKenFUWm93dkdiZnJoNzYrbHpFVFdETUF2TWx5dElqNGo5ZCtCSVF2b1M5U2tyaHV5TGh4SmpaeFZrcXdjQ3BtL082VmNyMituTG9CMnEvbXpSK3BQT1krekM0cDc2RmZnU3laYWVvaitQVVJONExpZzRCV1UreTlsSlpCR1ZnNUZHZUREN2VtUlJiemx5R2grc1JFWGIyVFpPSnhKdmZWdHdIYnkyejFJNk5Ed3RXcmYrelJLK0kxV0FDL1lSQm92bFVoYzVzdm5SU05YQ3c2Y1pTdDFMV1Q2ZDRVRVJ5ZjNPQVdveGxjNkY1WThnM2FobE4yZGUzTXM3TDA2clozbnVXK2NaZE4xdlpJN05FUDFjTGFoaVltREVHRzByckQ3MTFIQVdDa3drY0JCQklIVWowVWV2RjVIampURFc5WWhMdjRGTUZiQjdvLy9KSVVBQUFBQVNVVk9SSzVDWUlJIiwic3VwcG9ydGVkRXh0ZW5zaW9ucyI6W3siaWQiOiJobWFjLXNlY3JldCIsImZhaWxfaWZfdW5rbm93biI6ZmFsc2V9XSwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiIzZTA3OGZmZDRjNTQ0NTg2OGJhYWE3N2RhMTEzYWVjNSIsIm9wdGlvbnMiOnsicGxhdCI6ZmFsc2UsInJrIjp0cnVlLCJjbGllbnRQaW4iOnRydWUsInVwIjp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sImZpcm13YXJlVmVyc2lvbiI6MX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJOT1RfRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wNy0xMSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjItMDctMTEifSx7ImFhZ3VpZCI6ImVjMzFiNGNjLTJhY2MtNGI4ZS05YzAxLWJhZGUwMGNjYmUyNiIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZWMzMWI0Y2MtMmFjYy00YjhlLTljMDEtYmFkZTAwY2NiZTI2IiwiZGVzY3JpcHRpb24iOiJLZXlYZW50aWMgRklETzIgU2VjcDI1NlIxIEZJRE8yIENUQVAyIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCIsImNhRGVzYyI6eyJiYXNlIjoxMCwibWluTGVuZ3RoIjo0LCJtYXhSZXRyaWVzIjowLCJibG9ja1Nsb3dkb3duIjowfX1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUJhRENDQVErZ0F3SUJBZ0lVSlVyNVRCTCtSL3JGZnpUZkdxOHREZGF3QXdrd0NnWUlLb1pJemowRUF3SXdJVEVmTUIwR0ExVUVBd3dXUzJWNVdHVnVkR2xqSUVaSlJFOGdVbTl2ZENCRFFUQWdGdzB5TURBM01qZ3dPVFEwTlRKYUdBOHlNRGN3TURjeE5qQTVORFExTWxvd0lURWZNQjBHQTFVRUF3d1dTMlY1V0dWdWRHbGpJRVpKUkU4Z1VtOXZkQ0JEUVRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk1LSTJrRytqbUE3SGFXb3BQZG52aEJ3UmNicWcrbUpSU2FPaFNxZEJmSTAwc2NJeDM5eWVoczROQ0lFZHpsT2dDRXR3SEdoVEZ6SUZBWGFoZ1NoVXBlakl6QWhNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3Q3dZRFZSMFBCQVFEQWdJRU1Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lITTlXOW9uQ0hDSXlpbHdCVmtWK1JVMURzVEpOaWJmeGE2Vi9ISkZQZVFVQWlCNjlxTy93OWJ4ZWJxK1pkNkJ0a1NYalQzSEtmTmVYWVA3UDliL3dNenBqUT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQU1nQUFBRElDQVlBQUFDdFdLNmVBQUFKVkVsRVFWUjQydTJkVFc4V1ZSU0ErNC84Uy93UWRuWWxyS1FyNmFxSkM0MHNNTUZFRFFzV0pEWWFValFnMFZDSlJBc1NCUW9xUmRxeForS1E2ZmpPekwwejk5eDd6cnpQazB5a1dOcDMybm5lYys0NTkyTmpBd0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFLSTVmdkhUWWZ2aUp3SXJPYnAxdTNyNTRjZlY0ZGJsNnVuNXpiZlhpKzJkNnE5clgxU3Y3OTZydkl0dzh1aEdkWHgvcHpyKy92M3ErTnQzVjE4SkpMbjcreS9WdGYyOWF2dTdHOVhGYno2cnp0LzhwTnJhKzdMKytQclBkNnFEbDAvUExlMzVrZnRxMzY5Y20xOWQ5WC9QZjErL1VUM2J2SEJHaXI3citjVkxia1Nwamg2L2MvTHI1OVh4RHgvMHk1QllrRnVQSDV4NVFJWXUrVHo1Zk85aVhQbng2NkQ3bFV0azJYLzJtNDk3Zm5Od2NFNGUrQkF4dXBkRUdxdjNWVXN4RkNHVUJKRUlFZnFnZEI4YWoyS0kzQklocHR5elJCVHo2VlJvMU9pN0pCVXpsVDQ5K0dpNkZETUVrZFJoNm9QU1RrVThwU0NTUHM2NVg3a2s4cGlOSEhQbHNDSkpQYkNXTVVVS01TWUtNalZ5ZUpVa0pxVWF1MFEwY3pmWUhZVFB2V1FNVTBTTzFHSk1FQ1RsdytKQmt0VDNLNWVwTVlta1ZpbmxhSzZzWXd5cFJHbUlFU21JL0dKVFB5eVdKZEdRdzl3WWJPcWczRUlVa2FwVWRFVktVUkN0QjZhNUxGVzR0Ty9WeEJ1Q2pEMDA1R2pLdjZwUjQ0Kzk2dmpPZS9weVJBZ3lkMkR1UlJKdE9jeU1SVjdkM0syMEJORk1zK3F5YlE0eElnVFJTcStzU1pKRERqTnBscVJCbW9MOHM1LytGNW1zZE90WWtGS1M1SktqYVpvaVNHeVZLc2Q0WTZJZzB1aktLVWh1U2VRZFBmZjlJWWdIT1l4R2tKeVNwT3JyeEZ6eVBSSEVneHpHQmRHV3BJUWNqRUZpeGh3UHI1YVY0L1FLZmEybEJOR1NwSlFjWnVabVdSZEV2UUVZY0VsUndPSWdWbnN1VTBrNXpQUkJMQXRTejZrcUxFZnNOQk5aODFIeW9Vb2xTV2s1VEl3L3pBdVNxd2s0RkQwZXhlZkJKYW85S1NVcExZZXB1VmhXQlNuUzYraktjVHIybWZwenpkRlIxNURFZ2h5bXByeGJGTVJDYWlYVFdPYjhYRXRXdEtZK2JDWDZPR1pUSzlPQ0ZFNnQ1c3JSa0dMUlZHNUpTaFlaek1saFVaRFNWYXRVY2lESkF1U3dLRWpKNkJFalI4eDJRRWppVkE1cmdwU01IaUZ5OUMzbHJRc0tJN0pZa1NUbVljd2hpV2s1ckFsU0tucUV5QkhTelI4ckNTT0prdzBhTEFweThtVFhkRnFWcWpUc1VaSVV1NVc0bE1PU0lMUDJyTW94NWtqWVAvRW9pY3p6V2pzNXJBaFNyeXZQS2NkcEtpZmZVN040Z0NRTGtNT0tJRm1YendiSzBhMVMxUkpIUnJtUVRyeUZ6blV1U2R6SllVV1FiT2xWcUJ6dHRTZWRmeE83TGdWSkhNdGhSaENyY2lTU1JENS9uU1Z4SzRjRlFlcXRleXpMMGZNMXBLVGJYRUhDQkRRVkxVZ2lHeVdFcnNNSWtjUzFIQ1lFMFY0dEdDaEhVSlB5TkJVY0xEUU1pUkxZZGJjZ1Njd3Vqa1BGQnZPN3RYc1FSSFd0ZVVTMWFsU1FGVjlMZWpmZHYrdEwwV0orSng0bGFUY1U1ZlhMd3JHTkpWQmNFQ09sM01GR1pUZTk2cTVWRVNsYUVlTE0vKytPWHdMbmNIbVRaTEVzVXBDQVFYRnd1dGQ2d09zMGFxQWYwbTQ4MWw5cmFIRHZaT0MrOXBLVUZFUmxZVlJBNU9nKzZQOTdzRmM4eEdOeWpIWG5RNnBqU0lJZzZvS0VyQ0ZmMVhkcC83dGFrZ2x5ckpKa2RQQStFa21zckV4Y1cwbEtDcUl4dlgzT1lIeFZVeTlXam03VkttUVM1dGljTUF0UnBKRUVRVHdMY245blBIcU1WTTNha2t5V283V1hWbENVSEhuZEZ0YUtMNmF2c2M2Q3lKeXVGRjM3M21yVlJGbER4azFhODU4V2ZmSVRncFFWWk01NWgwMGtDcDJwN0NXQ0lNaWFwMWhKQk9sRWhOSHBOQ092VzJQQkVpa1dnL1RwMzdNWllFK1pKOVpUdWgzNldqS1FIM3JOTWorS1FUcGwzbnhsM3FHQmQ2ZnNHalZYYkVWanNEM29YeW5Kd1B3dXlyd0lvcktEWW15anNLOHhHQ1ZKdCtQZVN1VjZKUWxvRkZxSUhqUUtsemJWWkVvM2ZjVkRQUHJ1MzRvQ285TlJKa3gvb1l1T0lCdVcxcDJ2RW1GVWtvaU9lOHc1SThpQklMTkxxYWtsNlV2NXVoMzJ0NHVsdWxOS3hwcUtBVlUySzNMRWJ1Z20xYTFtWFFqVDNWTXVtTkxlc0NIUm1wQ3hkLytRZGZVaEVjU2JIRU1McGhaUkVtYkpiVndKV0tKSkhUMmU3TmIvUFRQMkdKSmtnZXZTUTdZdVlzbnRPbXphRUZuYWpaVkRIclFseXNHbURha0V5WFhFczR3UkFsYnpKWlVrUUE1dkc4aE5lYzFzKytObDQ3alFuZHhuU3FMMW9IbVVnNDNqdkcwOXFpZ0pjckQxcU03bTFiblNyTmhqRDJLbnZBZWtjT3NxQjV0WHp6bitJRWMxUy9Gc2tGQkJQSjQySmV0UlVyOW04d2ZuV0JPa2ppTGVEOUJ4c3FON3JCeHJlN3FVTlVHc0g4RldSN21lTXU1U0l3ZEhzSEdJcC9vaG5qSmxIVGs0eEhNWngwQ1BMRjZLeGNwNmNxdHljQXgwcENDaDg1cFVKWG1ZWnVVY2NpeEFFcE9DS0Mya3lpbUp6R2IxSm9lRjEyeE9Fb3VDVE9vL0dKUEUyNWpEMG9SSlUzMFNxNEpZU0xWQ3R4THFJbHZqbEg3SVpDZVVxVDkzQzVLWVdVOWlXaEFEcVZiTTRUZE5PYmYwd3lYamlMblBSV2xKWkMwK2dvU2tXZ0Y3MjZwZmdTc0JoZlpCTWw3bHNDS0ppZVcrMWdXSm51cWhkSVcrMXBLN2tLU1V3NElrSm81dzh5Q0lDVWtDMDZ3bHlWRTZLcHJZNXRTTElQV1lwTUNNM3hoQlNtM3lwaWxIU1VrUXhGUDUxNmdnT2VRb0pRbUNlRXEzREFxU1U0NFNrcGdRNU5YTlhWVkJ0RjUzOWpsYmhzWWcwb1FzSVVkdVNVd0k4dWJnNEp5V0hJZGJsMVZ2c082VDVKcjlHeWlJZGhYTHltNkhPU1F4VWNVU25sKzhwQ0tJcEc4NVhyL3E3b3lSZ21pZTVXRnRLMUJ0U2N6YzY5R3QyOG5sZUxaNUlhdjlkVU5STTVwRWROUFhhWjljTFVuTW5XUWw2WkRINkpGdEFCOGhTT29vWW4wVGFZMGo0c3pkcjR4RjVGMC9oUnd2dG5lSzJsOXZJNVE2N1lvUUpHVUgyc3NPNnluWGtaZ1plMmhJb2owd0x4WlJJZ1ZKSVltMzR3ZFNTR0orU3lDUlpHcTY5ZWVWVDgzZVhEMUdtZE9KbnlDSU1IWHF1NXR0Y1RySU5QV3BhMkhNUm82K0JtSm9OSkdVU3FNaHFDcExiQW8yVVpEbW5UVzAvQ3VmVjdMSFVXTHc3bnB6NjlkMzc5V1JRU1JveXNFU1llUmprVWdpanVkZnBEejQ5WEVHa29vTlNUTkRrQVpKbDJRQUwxR2xTYjlFQ1BsWS9uNHhoODUwM2h4RUFMbkhKckxJbitYdlhFVU1XREhRLzI5cm54UnlBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBZ0cvK0JRQjlkOEg1OUNaSUFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImVjMzFiNGNjMmFjYzRiOGU5YzAxYmFkZTAwY2NiZTI2Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MTIwMCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sInRyYW5zcG9ydHMiOlsidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDgtMDUiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IktleVhlbnRpYyBGSURPMiBTZWNwMjU2UjEgRklETzIgQ1RBUDIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwODA1MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjIiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wOC0wNSJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTItMDgifSx7ImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyJjNTdkMDY0MTY1MzIyNWIxNzNiYzZiNGQ5NTg3OWY4NzkxNTIyMmY5IiwiOTIzODgxZmUyZjIxNGVlNDY1NDg0MzcxYWViNzJlOTdmNWE1OGUwYSIsIjRiNTQ2MTQyMzZjNGM0ZTkzYmViMmQzZGMxYjc1YjYyOTc4ZWU0ODgiLCJjZTY4ZDFiNzVmYjRjZDNkYTA3N2ZkM2Y4MzNjNGQ2ZTIwYmYyODdjIl0sIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbImM1N2QwNjQxNjUzMjI1YjE3M2JjNmI0ZDk1ODc5Zjg3OTE1MjIyZjkiLCI5MjM4ODFmZTJmMjE0ZWU0NjU0ODQzNzFhZWI3MmU5N2Y1YTU4ZTBhIiwiNGI1NDYxNDIzNmM0YzRlOTNiZWIyZDNkYzFiNzViNjI5NzhlZTQ4OCIsImNlNjhkMWI3NWZiNGNkM2RhMDc3ZmQzZjgzM2M0ZDZlMjBiZjI4N2MiXSwiZGVzY3JpcHRpb24iOiJGZWl0aWFuIEJpb1Bhc3MgRklETyBTZWN1cml0eSBLZXkiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwiaXNLZXlSZXN0cmljdGVkIjp0cnVlLCJpc0ZyZXNoVXNlclZlcmlmaWNhdGlvblJlcXVpcmVkIjp0cnVlLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlCZmpDQ0FTV2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakFYTVJVd0V3WURWUVFEREF4R1ZDQkdTVVJQSURBeU1EQXdJQmNOTVRZd05UQXhNREF3TURBd1doZ1BNakExTURBMU1ERXdNREF3TURCYU1CY3hGVEFUQmdOVkJBTU1ERVpVSUVaSlJFOGdNREl3TURCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk5CbXJScVZPeHp0VEpWTjE5dnRkcWNMN3RLUWVvbDJubk0yL3lZZ3Zrc1pucjUwU0tiVmdJRWt6SFFWT3U4MExWRUUzbFZoZU8xSGpnZ3hBbFQ2bzRXallEQmVNQjBHQTFVZERnUVdCQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBZkJnTlZIU01FR0RBV2dCUkpGV1F0MWJ2RzNqTTZYZ21WL0ljak50Ty9DekFNQmdOVkhSTUVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCQmpBS0JnZ3Foa2pPUFFRREFnTkhBREJFQWlBd2ZQcWdJV0lVQitRQkJhVkdzZEh5MHM1Uk14bGt6cFNYL3pTeVRabVVwUUlnQjJ3SjZuWlJNOG9YL25BNDNSaDZTSm92TTJYd0NDSC8vK0xpckJBYkIwTT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRkFBQUFBVUNBTUFBQUF0QmtybEFBQUFHWFJGV0hSVGIyWjBkMkZ5WlFCQlpHOWlaU0JKYldGblpWSmxZV1I1Y2NsbFBBQUFCSFpwVkZoMFdFMU1PbU52YlM1aFpHOWlaUzU0YlhBQUFBQUFBRHcvZUhCaFkydGxkQ0JpWldkcGJqMGk3N3UvSWlCcFpEMGlWelZOTUUxd1EyVm9hVWg2Y21WVGVrNVVZM3ByWXpsa0lqOCtJRHg0T25odGNHMWxkR0VnZUcxc2JuTTZlRDBpWVdSdlltVTZibk02YldWMFlTOGlJSGc2ZUcxd2RHczlJa0ZrYjJKbElGaE5VQ0JEYjNKbElEVXVOaTFqTURFMElEYzVMakUxTmpjNU55d2dNakF4TkM4d09DOHlNQzB3T1RvMU16b3dNaUFnSUNBZ0lDQWdJajRnUEhKa1pqcFNSRVlnZUcxc2JuTTZjbVJtUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMekF5THpJeUxYSmtaaTF6ZVc1MFlYZ3Ribk1qSWo0Z1BISmtaanBFWlhOamNtbHdkR2x2YmlCeVpHWTZZV0p2ZFhROUlpSWdlRzFzYm5NNmVHMXdQU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2SWlCNGJXeHVjenBrWXowaWFIUjBjRG92TDNCMWNtd3ViM0puTDJSakwyVnNaVzFsYm5Sekx6RXVNUzhpSUhodGJHNXpPbkJvYjNSdmMyaHZjRDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5d2FHOTBiM05vYjNBdk1TNHdMeUlnZUcxc2JuTTZlRzF3VFUwOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOXRiUzhpSUhodGJHNXpPbk4wVW1WbVBTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM2hoY0M4eExqQXZjMVI1Y0dVdlVtVnpiM1Z5WTJWU1pXWWpJaUI0YlhBNlEzSmxZWFJ2Y2xSdmIydzlJa0ZrYjJKbElGQm9iM1J2YzJodmNDQkRReUF5TURFMElDaE5ZV05wYm5SdmMyZ3BJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4TmkweE1pMHpNRlF4TkRvek16b3dPQ3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVFl0TVRJdE16QlVNRGM2TXpFNk5Ua3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2U0dsemRHOXllVDBpTWpBeE5pMHhNaTB6TUZReE5Ub3pNRG95Tnlzd09Eb3dNQ1lqZURrNzVwYUg1THUySU9hY3F1YWdoK21pbUMweElPVzNzdWFKaytXOGdDWWplRUU3SWlCNGJYQk5UVHBKYm5OMFlXNWpaVWxFUFNKNGJYQXVhV2xrT2pKRk56RkNSa1pEUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJaUI0YlhCTlRUcEViMk4xYldWdWRFbEVQU0o0YlhBdVpHbGtPakpGTnpGQ1JrWkVRelkzUmpFeFJUWTVOemhFUVRsRFFrSTJORFl6Umprd0lqNGdQSGh0Y0UxTk9rUmxjbWwyWldSR2NtOXRJSE4wVW1WbU9tbHVjM1JoYm1ObFNVUTlJbmh0Y0M1cGFXUTZNa1UzTVVKR1JrRkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUlITjBVbVZtT21SdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNk1rVTNNVUpHUmtKRE5qZEdNVEZGTmprM09FUkJPVU5DUWpZME5qTkdPVEFpTHo0Z1BDOXlaR1k2UkdWelkzSnBjSFJwYjI0K0lEd3ZjbVJtT2xKRVJqNGdQQzk0T25odGNHMWxkR0UrSUR3L2VIQmhZMnRsZENCbGJtUTlJbklpUHo0NzdKWEZBQUFBWUZCTVZFWC8vLzhFVnFJWFphdkcyT29xY0xHMnpPT2t3dDBCU0p0cWxjWFY0dSthdXRsV2hiems3UFVBTVk5SGNyS2p0TmJxOGZlQWw4YUJvc3p6OXZwZGpzR0dxdEYzbjh1VHNOU1pwYzZKc05UNSt2MHhZS251OFBmZjUvTDQ4ZmcvZnJpY3pKZ1lBQUFEQUVsRVFWUjQya1JVQ1piRElBakZYWk9ZMVRhdE5jMzliemtzU1ljM3I0TUU0Zk1CQWFENnpsOHkvOVRPZ2V0OGQ1amZONzhid00vZERDUnBSNTIxelhmb2pISjA1SUl5aEJBVVNWQU9OZEd6Qll0MmY3S0ZyZmtKYUFrSGg5RlpoY0RYSFJrVEtvOU1MaWhHYWF2SW1uVjNxeUVYMEVwcmd6LzREd1VEN2tDSFJuZDhRRk40M0dvNFVWbUREZ3phNHcyN29pemRBMitjSyt1dVVwampvMit4d2MvNDJXNTB4NUxHWWVEQnNSMEhWSXg1eDhpRjYwQ2JsYlRFRWtGcjI3Yk5EQlVWU3ExT0tWUGJFNjJiM0VIOEZxQmc1T09PRXVjMnQ4WkppcU1PdUdwK2NLamc3d1ZHY2VvenFONHB4Z1ZQUWtqRllnYlZKS0RVaERDallyYXdQNXE0RVRnQzlmSU1SSHRpdHBRY0N2Sk9FTGNiTXNRZ25jaVJrbGpweVFqdkc0NGpxQlVFVEZpQmkxUEVJeWVrT3pzVytUeTVjTEhvczVSK2RNUzFMdFNTeGYzZ1FIY3pSMkNJNGdNTnBXNElSQTFRTWE2dEo0K0M2dUh1R0U4bU5ESXlGcWcvT1AvTU1VdWVTNklxOFM5MGRBZUJKU0V5L3FLa0srQk53ejhjWVk0amI1SjZ1NGlXQ0kyQjFaNTZMVzVrRWM0aGtkTXBzdlVDNTU4NVNYMFF1YmNnTnF5ZmdERkVjVHQrNDAvMFM1Tngwd2FDdzNPS2tjT2JBNUluMEFZcDAxcGpqdzJuNjI2VURqdEh3YTI4aUh1VEtxdHJ2K3JlVzQxTlo2aUdscjd1dUxKQ2ZrRnRjdGNHMDRzZ20xZU5TK1phRG5wYVRFckdveVg1SksyaU16OHhzMG5Pd1dHY1BETjQ5cWFDZDRiekpvekRabS9hQksrRW96THcrWGhOQmlZd0hmMHNpT3UxWFBrRy96S3d2cVlLY2ZTd0RFY0gvb1VlMDdlcy9XUThySXlnMkRPWGo4dGprWmR1REIvYjhoekRsbE1NT0NTNUJFbmQ1MzRmOHRpM1VaYzRrTXMzeEx5YWZNU3NKaGRHOFhQcWpOazV0QWdPMjVmZUtDaG5WZERqL0owRk1rT3NVL3hNQnYwd0ZoWWVFR2ZWSDEzZnVEVTB5REZMYTRmYzdSbldIQmZ1VEZWMnRFbU53YWRjN2FjM1VZMmpmQmw3SFQzNmZlMzRpUU81bU5DRkZCVzA3S2pQZ3FoT0xVMDF2WjhQdWVaMkpDbEZaTjhqa1VzNjl1a2E5ZVBwNitFZkw0QUY1K055d1NiaXJIdGNCOE1sL2drd0FFamtLNjRLakhQZUFBQUFBRWxGVGtTdVFtQ0MifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOC0xMS0wMSIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRmVpdGlhbiBCaW9QYXNzIEZJRE8gVTJGIFNlY3VyaXR5IEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiVTJGMTAwMDIwMTgwMjI4MDA1IiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjAuMSIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjEifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMTEtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTExLTAxIn0seyJhYWd1aWQiOiI1ZDYyOTIxOC1kM2E1LTExZWQtYWZhMS0wMjQyYWMxMjAwMDIiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjVkNjI5MjE4LWQzYTUtMTFlZC1hZmExLTAyNDJhYzEyMDAwMiIsImRlc2NyaXB0aW9uIjoiU3dpc3NiaXQgaVNoaWVsZCBLZXkgUHJvIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6NjQsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ2lUQ0NBZzZnQXdJQkFnSVVPa21VMzVJaWNYb1ZQamZ2d3BHN01ONnRIUFV3Q2dZSUtvWkl6ajBFQXdNd1F6RUxNQWtHQTFVRUJoTUNSRVV4RkRBU0JnTlZCQW9NQzFOM2FYTnpZbWwwSUVGSE1SNHdIQVlEVlFRRERCVlRkMmx6YzJKcGRDQkdTVVJQSUZKdmIzUWdRMEV3SUJjTk1qRXhNREEzTURrek1EUXlXaGdQTWpBMU1URXdNRGN3T1RNd05ESmFNRU14Q3pBSkJnTlZCQVlUQWtSRk1SUXdFZ1lEVlFRS0RBdFRkMmx6YzJKcGRDQkJSekVlTUJ3R0ExVUVBd3dWVTNkcGMzTmlhWFFnUmtsRVR5QlNiMjkwSUVOQk1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdGdPQzdJS3hpcE1KN2JWUFRUODNPZTkweHpIUENlYnh5Q3RnL1dyc1RyUmFTbllpZ21KQ0I4L2pxQk40T1FHMmRaNWpjTnNMNlN3SG9zWURSSmMrTzF6azlpNUdFWldmM0lyOTkyQTZkdU1zcDUxbHE0ZkFnYS9VelROOS9FYnpvNEhBTUlHOU1CMEdBMVVkRGdRV0JCVGZ4emc4R0d6WUFpZEtMNjN1aFNpcmFYSklLREIrQmdOVkhTTUVkekIxZ0JUZnh6ZzhHR3pZQWlkS0w2M3VoU2lyYVhKSUtLRkhwRVV3UXpFTE1Ba0dBMVVFQmhNQ1JFVXhGREFTQmdOVkJBb01DMU4zYVhOelltbDBJRUZITVI0d0hBWURWUVFEREJWVGQybHpjMkpwZENCR1NVUlBJRkp2YjNRZ1EwR0NGRHBKbE4rU0luRjZGVDQzNzhLUnV6RGVyUnoxTUF3R0ExVWRFd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmtBTUdZQ01RRHN2NEs2TmZKdmZ2emQwT3lnd0ovQUJpTHRndEpXaFhUZVVsbHRkcWE0V3NPTTl0dng2MzZ2NUZJdlpSa0sxWG9DTVFDZG9QUSthNGZEQkVpTnVqMFdzMzN1VVFoR3Jwc2VQREdmVlhuNGtFcGJUSUJlT2RWQXgvL1RyTUMvU1ZiK2JzZz0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBTkVBQUFETUNBSUFBQUJpRU5IOUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFEc01BQUE3REFjZHZxR1FBQUNadlNVUkJWSGhlN1owSGRCelYxWURYRFRlYXNTazJFRXd4WU1DQUFRT0duMERvRUNkQUNLWWtRQ0NoQkVpQUVFZ2doSVFFSEFpaGR4TEFYYkxhRnExNjc3MnZldTk5cC9lWjFYL2Z6RXBhMWdXRFo2V1Y5dDN6SFIwZGczWm4zL3ZtdnZ0bTU3MnhqT0hBTWJXQm5jTXgxWEVnNTFSVkhYVVROYzF0OW9LS3QrTHpINDNNdXptOGRIMUV3NmxSblN0dGd5c2M3bU5paVdPYzFERk9FalBib2FDdm9jZFgyWWRPaStxNE9MTCsxdkRTeHlOejM0N1BpeTJvcUd2dGNCTUUyT0wxNXR0aXY4NEpndERXMFpGVTVubzNyZndSVzhsMVlhVnJ0cFlmL1hYdG5HMXRsbWkzSlU2eUpJOVpVakdoQlBRNDlIdlU2Tnh0cmNkc3JUMTdlOFgxdTBzZXR4Vi9rRjZlV2w3YjJkVWxpcUxYbmdQR3ZwMWpHTWJWMUJxV1ZmS2NOZmZHOE5JendocU9EdStjdjZmUEVqbHNpU0VzTnNiaTRDeXh2STZBQ1EzMDduYXdxUGZCZ1lqaHd5SUdqZzdyT0hOMzNTMWhKWCsyNVVmbGx0VzN0SE1jNTNWby83RVA1d2lDS0sxdi9peTk5S0dvb3ZVN3lsZnNiSm9UMW9ja2k1ZVI1dkNMamJaWVNmVEdtRkFEK2gyY2krV1FDZUNEblowYjFudmN6c1pMZHBROUdsUDBaV1paWlZNclJWRmVrL1lUL3M1QmhnUGhQa2dxdkN1aWFNM3Ura1hoUFhPaVJpeFdHZ2tPMkpseDRiQnpvUWxwc1ZMSUFUREJVTUpLelkwYVdSTGVzemFzN3Q0OUJaK2xGVlUwdEJ3NDIzM0RPWjduYTV2YlBrc3Z1V3RQNFNrN1hmUEMreTF4ZW02elEwYWw5bnA3VE1nRFZvQjI4UkpJc2lDODc3UWQxZmRGRm55VldkYlkxZ0h6QWE5VmU4V2tjekR2YU92b2hCcnVvYWpDTThQckYwVDJJNWRoSUljWGhaZkdneWxtYjlCUUM5cEJjUzlBOGx1d3AvZWM4TnJIWWdxaWM4czZ1N28xVGZPNjljMllkTTVOa01sbHJ1ZGljaS9jVnJvb3ZCdkpDelVqSkZKc0crYkFnQ0hnaVZPd3hJbEx3am8zYkM5NTBaYWJVVkczdjhKdTBqbFhTL3Q3YWVVM2haVXUzOTVnaVJ6U3B3c3NydHN3QndlSk1oUTRzMmZnMkcxMW04SkxQc21vYUdqcjJPZlZrMG5uN1BubGoxcUx6OWhWTnkrOEQya0xOUno4OUg5cERHWS93TVFDVFNuSStXRzlaKytxL1oyOUpLR29jbkI0Mkt1WFQwdzY5MVpjM3ZWaEpjdkNPOUJmR2pVY1RuS1lnd2ZWZHJwMk5tYjU3cmFiZHhlOW41QlgwOUx1MWNzbkpwMTdOQ0wzekczbGgwWDBvMG9PQ2J2WGkySXdCd2FjQVhQaXhJWGh2V3UvTHYxZGRGNUtkWk5YTDUrWWRPN204TktqdjY3MVZuSXdZL1Y3T1F6bVlIQXc0TnljaUtGanZxcTVMYklzdkxMRHE1ZFBURHEzUHFKKy9zNE8vYy8wYnhwOFh3aURPVWpzK3ZBYTQxNndvLzN5NkliUHF3ZThldm5FcEhPblJuZWlMKzl0RTk4MDdQVnlHTXkzWXRPck9oZ25vMGJQdG5XOTYzSjc5ZktKU2VkVzJnYjE2eU9jZnJrRk80ZjVYaGp5eEhJV3A3ZzZkdWpOT3NhcmwwOU1PcmZDNGJZa2U5QlZGcjlYd1dDK0swNEJYRnJsZEcrcDU3MTYrY1NrYzhmRWt1Z2VLZXdjNXRCeGl1RFNDWEhFNncwSHZDWjhqSk5Dem9HaGZuK1B3WHhYRE9maXFkZSt6VGs5ejJIbk1JZU9OOCtScnpYczQrNFM3QndtQUdEbk1GTU5kZzR6MVdEbkxORWhqMStEQkpyUWRjNW83cWg5RVJsS3dPZWRZdTFtdVhPR1dQdkVWeksvL3hSTnpKa2docGc3ZTRGUFozeE0vM1lMS0xQV09jTWVReWwwUXJzbm1WQXRDclg3QWl1eHlFWXN0Uk5IT29obERuSjVMSFdza3pyZVNhMk1vMWJGVXlmR1V5ZU5jM0xDN09HVUJQTGtCSEpWSEhWTUxMbkVSczZieXB2VFpwVno0MWxxVWpqOUZ6aVA1MXFSV3d0MXQ0NktKVmM0U2ZCcGRRSjFaaks5THBXK0tKMitQSU8rS291K05wdTVJWWU5SlkvZGxNL2VWc0QrcklDOXM1RDllU0Y3bDg3bW9sbkMzVVhzZmNYbzU2WTg5cklNR2hSY2JDZTlqZWJYcElGZzlqaG5wQzVJWXhHUXpORHZNSEFzc3BGd0hwOFVUNTZaVEsxUG82L01vbS9JWlVDbWU0cTVoOHY0SnlyNTUycUV2OVFLcjlZTGJ6UUs3elFMSDdTSUg3ZEtuN1ZKLzJ1WHZ1NlF0blZLMjd1a0hWM1NUcDFkczRYZDNWSmtqeFRXTGNIbmZhS1MyNWpKTEl2Vm5ZTUc5R3ZWUURBYm5ETk8wUEdzTmkrR1dHS0hURWFkbGtpdlQyT3V6VUdKNnBGeTlvVWEvdlVHNGNOV0VXU0s2SkdkQTBycWtKSTdxcFlRYWlXbDFkSmFFNk8xc0ZvN3AzVndXaGVuOWZCYXI2RDE2ZlRQTGdaRnpTMTdoaVJQbVZ2OXVGVzh2WUE3UG82eVJPbUZoMS9iQm9JWjdOeUVhbnFKQnBYWmtYYnk1SGpxZ2xUNjJoeG1jeEgzWkNYL1NwM3dmb3U0clZPMDkwc1pRMHF4VzZtbDFWWVd5VFFpZVNqRnc2dGpzbWRzM3lzdFF5QUdCYytlYnZtWEpkeUo0SnhSN1BvMWNpQ1kyYzdwdVEwUzJ4RU9jblVpRFdNRUZDdC9yQmJlYlJIRHUyVklZMldFMnNScVBXQ1k3S0VWRDZkNlJNMGphMk9xWjh6ai9XUWhIWkRDdzd1a1gyRG52aDF2ZWtPNURRcVJ0Y2tVVkdtUGxNUFFLVzd2bE5LR2xHcEtoWkdSVnNBdHJOYUJvcFBUZG5aSzl4WnpNSUhGemgwUVBiMHR0S0haL3RWWnpPUGxIQXlnem42bGlsUzdlWTJRWWNUMFFDYkQ4YTBCbGVzTzdOeUI4QTZtYmhoTVZ6ako5ZWswVFBpM05BaldYcm1HVXFFK3cwbnR1d1oyN3R2UW5WdGdJMDZNSjYvUFlaNTM4V0hkY2dXaDlnc29zWGtQRk1kM0NlemMvakV5WEJTeHhJYXV0TjFSd0w3UktLUU15WjI4cG1EWkRpR3djL3RIZDI2cGpUdzNoWDZ3bFB1c1ZTeDJxNk9TQnd0M2lJR2QyeGRnbXc1a3VIV3A5TU5sM0xZT3lVV3AzTUZ1dzQzalFJR2QyeGQ2aGx0c0o4NUpvVUM0N1oxU0E2M2k2czJzd001OWsvRU1kNWlWV0pOTTNWL0tiZFdGazdCdzVnVjI3cHZvazRiNVZ1TGtCT3BuaGV3bmJXSXR6bkJtQjNidW0rak9IUnRIM3BqTHZOa2t3S1NCdzhLWkhkaTVjWXhSRmNvNEczbFJPdjBuRjU4MnJNQXMxWHNvT013TDdOdzR1bkFMck1TcGlhaU1pK2lSZTRUOWJMS040OUFDT3plT1Bxb3VqeVZ2eUdYZWJoYXJLRlhHT1M0d2daMGJKNHFZWnlYT1M2WC9VTTBsRDhyREVzNXhnWW9lWHR2ZEpkMFgwczdwbGR6Y2FHSzVrOXlVei82dlhXeGpOUVYvZFIrd0dCUzFpRzRKM2JNWkg3TE9lYjlVSlM1QVNZN1BHSmJaS2Z4NkM5NUo4NkRiT1FGNFd3REdkRm56QXRsMjl0SE1hRnM3cGJ1THVKV2g2eHg4NWlnQ2p1YTJmUGF6TnFtWm1hS3JJNkxxb1dRUERPTDlndGJOby9VUXJhd0cvZEhJYVBXMFdndFFhbzFPTmFWV2taTlV6a3pneUYzNkIwa2NVTFkwQ2pmbnNjYzY5ZlVRZ0YrUEJJSmdjMjV1REhGZUNnVkpMbmt3c05kSFFHZEdHUnNRd1MyMWpGQXpoNVg0QWRuYUsrL3BsbmQzeWRzNjVhODZwQy9hcFUvYnhJOWJ4WTlheEE5YXhQZWJ4ZmVheFhkMTN0R0JLYzVNQkk0Y1BnNThpci9XQ2ZlVmNPdlQ2U01kb2JuV0VGMGljUjl1SjYvUFpxQ2JHeGdOUnJRQUJRelpVQ2xtRFN1N3U2VjNXOFNYYTRXbnE3aEh5cmtIU3ptWXhHMHU1TzRzNUc0cllEY1ZzTGZtTWJma01UZmxNamZtTWpma01OZm5NTmRsSTY3VitkSE1CQzNqelVXZjRvcE01cHdVK3ZnNDhqRGJYdDBST0lMRk9mMmEzTHdZOUUzWEF5V2N2VThlQ1V5U2c0b05Ycm1VVUhkMVNTKzVoTHVMMmF1em1YVnA5QmxKYUhVN2xEWEh4NkYxL0N1Y0ZIemtvNEZZOGlnSENXa0FPTUtPZ0xOaTFyRFVUaTYwb1M4WTUvaDFSMEFKRnVkUU1ZSFdwVjZVVHI5VWk3N3BDc1ExT1JBT0tyYjBZZVhmamVJdmlya042ZlJKOGVRUkRoSUdkRU42eE1UbU1VWk43VXZFckFNK0ZMVDgxQXlwRXdTTGMrakRFOGM1cVIvbnNSKzNTczJzK2NNcUNEY2tldElHbGIvWENUQktRbFpEKzNSQWN4dTJHYjhZdjRjT0U1L2FyenNDU2hBNUYwMmNua2ovcG95TDZaVUhSUE96bkZ2MjVJNm9yOVVMMStVd0sySkoxT0xvUlBkcGVyOUR3Z1NJb0hBTytqc1Npam55b2pUbVpaZVFNNkpRWmwrV2c1RzZobEkvYkpFMjViTW54bEZ6OVhlY3RoTTl4QWtlNXhiWlNKaFN3UnkrbGxKRkdBak5DOVV6Qm9uVDJpcy9YTWF0VHFUbXc5c1pJNHZmWVdDbWh1bDNidHlBWmJIazdRWHNyaTY1bXpmNUxoSkdRUlBWTnh2RUgyWXhpMjNlMmhIbnRta2pTSnliRTAyY0dFODlXTW81K3hYQzdLc2tmWUlXMVNQL3Vvdy9QWkhTYytxVXo5UXd2a3kvYzNxU1cyQWx6MHFtZjEvRlo0K29ncWxydWp5ZXNUcEtmYnRadkQ2SFJVK1FncmVEU3M3dkdEQlRTWkE0dDhST1hweE8vNlZXZ0VIUTFGcHVERXJEM0JIbEQ5WDhlYWswbEl6RzIva2ZBMllxbVg3bklPdEVFMGM1eUt1eW1IODFDaTdLNUpXcmJ0bmo2SmZ2MTIvWFFaczFnM0I0WUoxZWdzUzVGVTd5cGx6bS9SYWhpVEhUT1VpWlhieTJyVlBhbE1lQzFwUFhSL3lPQVRPVlRMTnpxS0pIUDFmcTl5OTkwU2EyYzJiT1dTVnRySTVXUDJnUnI4NWlGcUlaS3hZdUNBZ1M1MDZPSnpjWHNaQ1F1Z1V6bldQVk1TZ1F0elNLbDJiUWFEdDY3Rnd3RUFUT29Tc1hxeE1vS0xuQ3UrVStVNy8xSWhWUHpvanljcTF3WVJxTjNnNWZKUWtHZ3NTNTB4T3BoMHE1cUI1NTBGVG5SbVZQMnBEeXh4ciszQlFLdlIxMkxoaVlmdWNpa0FkbkpGR1BsSFBXUG5uSVZPZUdKVS9pb1B4MEZYZDI4dmpWWUw4RHdFdzlRZUxjbWlUcTBYTE9aclp6OEdweEEvS1RsZHlaMkxuZ0lYaWNlNndjM1I1c3JuTXdVanY3NVNjcXVEWFl1ZUJoMXVjNWNPNUo3RnhRRVNSekNLam5qTHMxeloxRERJdWUrQUg1ZDNoc0RTcUN4TG5UOUhsclpJL0pkd2lQU0o2VVFmUmw2MXFZdDJMbmdvUWdjVzUxQXZYTEVpNnNXKzRWekhTT2tEMVp3OHFMTHY3ODFQSHJjNzd2anBrV2dzUzVrK09welVYY3RrNnBpemZ6ZXdoRzhSUzcxWC9XQ3h2U0dmdzlSTEFRSk02aDcxc0wyQy9heFRaVGQwUVhWVTh0cmI3YkxGNlZ4YUJsdytBY3ZwRnAyZ2tDNTlEUEZVNjBoNnZwOTVXb25yRk9YdHZhTVg1ZmlYSHpIRTUxMDB1UU9IZTBmdi9jR3dHNGZ3NUt1dGcrK1VIOWNaSGU1VjdZdWVsbG1wMEQ5Tnl6MUlidUUvNXJuZm4zQ1V2YVdPR28rcUpMdUNpTldZTHZFdzRHZ3NTNUJWYnk3R1RxbVdvK1owUUJTOHlOVmxiN2I3dDBSd0Y3QXRwTmtyQkU0RlEzclV5L2M5RDkrcnF2SHlTUUQ1ZHhDUU95NlF1cTNiSW5ZMWgreWNYRDdCVXRpUURuY0ZVM2pRU0pjOER5V1BMT1FqYThSK29UVFY3Zkttc2VtRWxFOWtpUGxITm5KZE9MNFUxUnRqTjJ2aG4zejhEM3dEQUJZdnFkQTZDekk0bWxkclJSK2lkdFlpT3JTcWJ1SVF5dkpXcm9vc24vT3REZXVlY21VL0JlaHVoZTV3d216TVB5QlpUZ2NXNitsYncwZy81SGcxQk1LR3dBTm5XbEZVOGxxWDdWSVQxWnlWMmR6WnllU0IzbnBHRHVNdDg0Z0NnOTUza3hVdUNCbWZpZlRXSkMvZS9LeEhsaTROdXd3VW5RT09lR2tnNm1FVTlWOHZFRDhvanA4d2c5MnpHS3A1SFI0Z2JrdDVyRng4cjVXL1BZaTlPWTA1Qjg1SkVPWXFFTlBTTUE3ZjVuZEo1ZjE4NElab1Iyd2VNY05ObXFPT3JuaGV6WEhWS25xYXUvZkFQbUowT1NWa0dxOWo3NXd4YnBMeTdoc1FwdWN4SGF3L1dIMmN5bEdjeUZhY3c1S2RTYVpHcDFJdHA1ODhSNGFtVWNkWHdjQ1Y0ZXE3UENES0I0Qlk3UldhWnp0QU54bEE3YTAxUGYxaFB0aG1sRHUyRXVBV3pFWWh1eHlFWXN0S0puUFM2d0VwQ2g1OFhzNnlTWnlNVEJhV0ZRT0Fmb2pRWE5mV1VtODNxREFJTmc0TFpNaHhmbVZNK2c0R2xpdEJLM21qSW93L1FDeHR6M1c4UXREY0xMdGNKejFmeVRGZHl2eXpnby91NHU5dTR0L0pOODlzZDU3QzE1N00yNWlKdHkwU2JEMzVzYmM1bnJnUnptMmh6dkhyOVhaekUvekdLdXlxU3Z6S1EzWnRLWFo5SlFhVnlhVGwrU1JsK1VScTlQb3k5SW84NVBwYzVOb2RZbVUyY2xVV2NrVWFjbVVqOUlvRmJwKzlHQ3dXRHFJanV5ME92WnhIaU5uZHMzMEM1UmNQcVMwSlMvcmVEQUEwYnh2blZBQTh5RzJuRklSUHZ6MTlGb0EvWGNFVFYxU0hIMnk5RzlVbGkzdEwwTDZhaHZvQzU5MUNwOTJDcDkwQUoyU3UrMWlJZkN1L3IrNWY5cEV0OXFFdi9kS0w3WktQNnJVZHpTS01MNTlzOEc0ZFVHNGUvMXdpdDF3bDlyQmNqRUw3cUVQN21FRjJyNFAxYnp6MWJ4djYrQ1U0Si92SUwvVFRuM0VKd1lwZHpkUmR3ZGFMdHQ5cHBzWmtNNnl0TS9TRVFXTHJhUjNxMExna3ErSUhJdUdsMmxnMUhtcC9sb29Xc25yeW1CR21EM0VTQ2ZxS0g5MUVuWk15cUJoWjUrUWV2aHRTNWVhOWNmRjlIQ2FKQVhvUnhzMEtrL05PcG9oSXRDMUZCYXRVNFZwVlVTU2dXaGxCTktHYUdVRWtxSld5bDJLNFdqU3NHb2tqK3E1STBxMlNOSzVyQ1NQcVRBaVpFMEtFUHQ2MENuaHd5bkI5UWtIN1dDdGVMejFmd0RwZHlOT2N5NlZCcFNJTHE1WVVJN3YyYWZGb0xGT1FDMGkwUmx5b1owK3RVNkFWcDVhbEpkVUlYSGc5RDBuOFl2Y0RJWUQrVUJaUDNFRUFBVnlnTjBoc0JrbkZUUVNUSWdvTk9qU1gvV0JSZ1ozaTFES24yMm1yK3prSVV4K3VSNFZCUk81cnpwVFhoQjVCd0FKVWcwY1VvQzJvZ3V2RnZxTVhWTi82d1BhQ3haODRDSW9HQTNyOVZTV3NhUXNxdExnaFA0M21LWW9kTXdkMEU3eEUvTUxYeGJmaW9KT3VkZ0ptR0htUVQ5ajNvZUJwZkF6U1JDSVhqVjB5ZDRpa2JWSFowU2xJTXdBVnFUaEhhTDl5YTg2ZEl1dUp6VE0vOTg5TjByZFg4SkMyVUsxRldtZmlVUmlrSExIaWhKWWNEOW9FVjhxSlM3TUkzK3hxMkVVMjllY0Rsbk5BRjZ0Q0Y1UlFiOVdyMEFGVFJqOWxmK29SbGdYaTJ0UXNVQzA5NHJNcG5sc1JRYVp3M3pmTHRnQ2dndTV3d2lpVGxSYUlYRVBVWHMxazZwUFFEUEp3bk5nUElZR3RQZXAveTVScmdxYS93aEdWT2Y3WUxST2IwaElOVmRrRW8vVThVbkQ4aW03Mm9kc2dFVDRWN0JrelFnditRUy9pK0xXZWFZanRvdUdKM1RUenRvaTZOanlldHltUDgwaVpXa3l1SFpoRWtCN1RnZ2FISDk4bk0xL0laMCtvaUoyczZ2RndKSE1EcG5vTGZDNmdUcW5tTHVxdzZwa2Rhd2RXWUZUTXM2T2MzYWgzWnlPVGVGV21ERmVjNUFQL2tXVzhselV1akhLamlZdy9hSkhselptUld5TnRiS2FYQXkvN3lRUFNtZW1nL2FUZGtJRzd6TzZTTXNOTVRoZG5KREJ2MThqWkEwcVBTTCtNcUphY0dyYU1INWxnYngybXpHKytTTXFSbGhnOWM1QUp6VHJ4SXZpeVdoNEgyNVRrZ2RVb1lEY0d0ZHlNYXc1RWtZVUg1ZnlhOU5waGZFNk5wTlFhb0xhdWNBUGRYQmZHS0ZrN3cyaDNtMW5zOFlrb2ZNdlhVOWhFUHhqRFd6MnVkdDBvL3oyQlZPZlJ1aEtkQXUySjBEaklaQVR4UW1yODJtLzFiSEp3OHFmWUxIM0dXd0lSdXM2c2tZVnA2dDR0ZWwwZ3R0eGlNMEFyeVQwQXh3RHRDZG14dERIT3RFejl0OHlTWEFWQjltWHBMSmEvNURNZURNYldTMFQ5cWtuK2F6eDhWUnFLa2pzWFBBZUtxRFV4QUcyU3N5R0Rndnc3c2xGNlhTZ1hodWY0aUZXL0xBMFBGTUZiODJoZGEzMThET0dVQmI2T1pCdGp2S1RxNVBveDR1WlQ5ckU0dEcxU0Y4RGVYUUFvYUxPa3A3cjFtOEpwdGRZcXpDTkZyYnJ3dk1Zc1k0WjZCckJ5ZmlZaHR4WmhKMVJ5SHp6M3JCMnF1NEtBM013emNEZk0vd2pJMkludWhlK2Q1aWJtVThOYzhRRGpzM0NiU0ZmbXZuUWl0eFlqeDVSU2J6U0JuL1FZc0Vvd05Nd1FnWnp5MitUNGphV0k3K3hGR1lTU3dPOUU1Q004ODV3RGdMMFJEZ1htb256MHFpYjgxam42MFdQbTBUNC9xVmNrSnQ1N1JoRWQweGl6UGZRUWEwVXkydC9xZEp2QzRuOE5lSFo2UnpnT0VjMGc0U0hscDJlbTRLZldNdTg1c3lEa2JiclIxUzRvQlNTcWd0ckRZZ2VDakZJNmpvV2hTNnJJY3QzRTkwODlyT0x1bStZdlJWR0dyWXdNMGtacXB6RXhqbVJhR2x4VWM1eURNU3FmL0xaRFlYc2s5WDhhODFpSisyU1dIZHNyTmZUaDlDNjZaS0NhV0tWR29wdEh5cmxVUHJDNkdoZXdXdFgvQU1pSjVCMFFQWmNVUkM2d2xnS2dmRE5FRHFVRHEwdnViRkYrYjdBamtZNEZRRXI2STFOVEM2U1JwYVphUHFTMittUHVDREp3MHEwRzVuSjlQb0JpZnMzSDZaU0hoQU5GcmdEdWF0aWlQUFNxWTJaRERYNWJKM0ZIQVBsSEpQVlBEUDEvQ3YxQWxiR29TM204UVBXOFV2MnRIaVBEaXo5L1JJVUQ3Yit1VFlmam1oWDA0YWtGTUcwV0srekdFbFd5ZDNXTWtmVVlHQ1VVU2hHMUgwZlNrbTFCSkNoUnhjUnFoUUJsUVNhaFdwdWlnVmhyWUdHaVZtT0JONmVHMVExTnl5eHFxZUtic1d4Q3BqY0dEL2JCQTJaTkNCL2NwL3hqdm55NFI4ZW52TnM2SzlubGJFVWlmSFV6REpQVCtOdWpTRHZpcUx2ajZIdVRXUHVhMkF2YXVRdmE4WUdmbnJNdTdSY3ZDUysxMGw5MHdWOTF3MS8zdzEvMmNYLzZLTGY4bkZ2K3ppWDZrVi9nYlVJVjZ0bitRZjN4M29WR2pyMXh1RWZ6VUlielFLYnpZS2J6V0o3elNqaGRZZnRZcWZ0MHRmdGt2Yk82V0lIc25XRHhNakdkSXpKT1plWG9Qc0dORDhCMWtXMHYvSGJSS1VkSXZ0MkxtRFpDTG5vZDA2MEFZbzZGK2kwU1U5eUgrTGJjUVJkclFuQ05USVVQOGQ3MFRwOEtRRXRQM0M2a1RxdEVScVRSSUYyWEZ0TW5WT0NuVmVDclV1RmUzVmNFRXFkV0VxdFQ2TnVRaElSMXlzYzhuM0JiSXZjR2tHYzFrR2Mza21zekdUZ2FrMzFBTS96R1orbE1QY2tNdmNuTXY4SkorNUU4NkhFaGJPQkVqUFVOcEg5c2dsYm5WQTFBSTNLOUp2SWRaMmRjdTNGN0RMWUJwaE5HWWd0SnRWenZtaEMrZTE4Q0F4L3NSQWZ4RW9FeWV4SXVZZUdwQjlBUmk4ZklGVFlxR05XR1FubGpxSXd4MVFIaERMblNUMHlxbUoxUGtwOUhYWnpFT2wzTDhhUlNoTW14Z3RjTGRNUS8zcTZKY2ZLR0ZQakF2a1BldXoyVGxnUWlCZnNTSU5qTTJMRHBLSnZ6SVYzK1B4SGg2a1p3TjAyUE5qMEYycnkyT1JmSkFJWWVqZjBTWFYwU29YbUhRSFV4a29aS0hHT0NPSjh0N2FCUGcxNmFFenk1Mzdma3lZT2wxNC9kTVoxeEZxMDNVcDFNTmwzSzR1cVlWUkF6RzNVTFN4Z2xIbGhScjBxQ3B3M1hzQWZvMXo2R0RuZ290OXlnZmFvZDJQaVNWV1lsMEtEYk9jK0g0WmFqdlY3TnNJNGVYS1NSWG1TWmVsTTFEN1l1ZENHOE8vQ0hTbi9qVlp6TDhhQTdYYXZJWlNZVFo5dGI0TUVUc1g4b0IyZTVBRXF4T29CMHE0UGQxU3I2blA0ek9pZ1VZM21OeVlNNzdpR2xLczMyRWNPdGk1bVlSZTJ4MmxQNmRxUzZOUVRacjh6Q0NJRmtiN3RGWDhTUjV6QXZRNGRnNkRKSWhDazFtWVZ6NVp5Y0VjMC9UckpoMmM5bVc3ZEdjQmMyTGc3aG5HenMwa2pLb3VHaTBOMlZ6RTZvLzFOdm41TGQyOHRyMVR1cWVJUFRsdzMvUmo1MllZK25pMzFFN2VsTXQ4MFM2MXNLcHM2dXkxVjlEQ3V1VmZsbkNuSkl3N0I2TDdIY01oZ3AyYllZQUJrV2l6NzZzeW1iZWJ4Q3BTNVUwZFh2c0VMYUpIZnJDVWc1a0tkZzZqZzV4eno0MGhOcVRSLzZnVENrY1YydFFySnYyaUZ0VXJQMVRHbldvNEY0R2R3K2pPellraExraWxYM0lKV2NNS1llbzNFbEFnUnZmS0Q1ZHhweVZpNXpBR3VuUHc4OXdVNnJscVBuVlFIalYxYzc1SjU1TDBaZjNZT2N5RWMydVRxV2VxK0NUMGJEUlR4MVpoZkd3MW5NUDFIR2JDZzdPVHFkOVg4b245OHJEWnprWDJ5TCtDT1FTTXJkZzVETUx3SUlaWW0wSTlYY1VubXAzbllONjZwMXQrQUY4cndVd3k3aHpVYzMrbzVsUE1ydWQ2ZVcxWGwzeGZNZmNEN0J6R2krNGN6RnZQVDZQLzdCSXl6SjYzZG5IYXRrNXBjMUVnVnh4aTUyWVl1bk56WTRpTDArbFg2b1M4VWNYY1hZTGFXZTIvN2RMdGhleEsvSDByeGd0eWpwaHZKVGRtTVc4MGllV2t5ZmVwTnpQYVI2M2lyZm5NY2REanlMbTlEdURRd2M3Tk1IVG5GdG5KYTNPWmoxdkZCa2FWVEwyZnFZN1czbTRTcjh0bGx1UDc1ekFJRUE0ODBEZFlodUZ2WjVmVXcydG1LdWNacXlMVjF4dUVLN09ZeVdlQytSM0RvWU9kbTBub3pzMkpKazVPSUI4cVkrTUhaTkxVWWc3MExYR3JmM0VKRjZjeFN3TzNPeE4yYmlhaFM3RFlSbDZZQ3BOV3Z0Q3RLS1lPckpLK0k5Z3pWZnc1eWZSQ1kvc0k3RnhJbzFkeUlBRlU5NXZ5MkU5YXhXYlc1UDJVYVdVc2NWRDVUUm0vT29HYVB6Nk8reC9Hb1lPZG14a1lCa1NnZlRET1RhR2ZydUpnWURYM1VSbVFNSWRFVDFTdnZMbVlBNjNuR01MQisvb2R5YUdEblF0ZW9MOE5vTzhodyttUEdEM09TZDFSd1A2M1hXeWdOY0hVZ1ZYMWpMVnoycGNkMGkzNTdPU0Q1N0J6b1lWaG15RmNCUHBsbVFNOUQralZlaUZ2Qk4ycWFlNUtDREM0bWxMZmJoYmhMUTZ6Nlc4YUNPR0FvSE51NHN6R0dFUVQ4NktKeFZaaVpUeDFUVFlEVTRlRUFibFBNSDlsSzB5QnMwZVVsMXpDK1duMEhKaEFoSXB6aG0yUnZwdlR6QW9pOXNMM1AwMzhEdmlvQml5d292M0xUb29uTDBxamYxN0VRaWNsRHNqZHZDYWJyeHg2cUt1MVYzNmtYTDliRS9vQ25QUHRHaE1KS3VmbVdnbkk2b3ZzeEJJN09hdXdUYkxVcnVNZ0QzZVFVRFlkNlNDUGlpV1h4WkxMNDhoajQ4Z1Q0cWtUNDlGK2VHdVNxSE5UcUV2UzZSOWxNL2NVc3krNGVLaTBDdHpLSU5xbXhOc3A1a1lMbzMzV0p2MjBnRDB1VHQ5OExoU2NnM3grcElNNEpaRzZJSTIrTEpPK1F1ZnlXY0hHRE1RVm1jeVZPc1lPaHpCUVhtZHNjcGpIYk1wbmJpOWs3eXBpZjFIQy9hcVVlN3lDZjdvSzdmSzVwVUg0cUZVTTc1RXloNVZHVmlNRHR1TWhlRnhHcUgrdkV5N1BZQTUzR0tPTmZ3ZVpSckE0cDIvRmVrb2lXcmI1UkNYM2NoMXY3SVFLclRBTGVGVUhiZXhhanpaMkJaUGVhQlQrM1NTODB5eSszeXArM0NwKzNpWkNHdHZaSlVYMHlMWmVPV0ZBeVJoV2lrWVZGNFdlT3pBa2VUZ1ZhUkc0UUZmbUJwUkh5dmpURStuREFuYzEyQ0Fvbk5QTE9LaGRMa3lqNGZ6ZTFTMUJNVnZzUmhTT0tnVXpuMEszVW9SUWk5M2VEYXpMQ2JXQ1JMdFgxNHp2WHQzTWFxQlhGNi9CL0dCSVJGdTJjNnBIbVpLSGhrTDJoUGY5dWxQYWxNOGVIUnZJSFRZTmdzVTVmWjB3ek5MLzNTUkNrb2M1bEtUdlhRK0lzd3ZqUThFa3dBRDYyd0RTbUtZRGxrMkZhRDVCS3g0NEpWNnRGeTdKb05HeitRTXFIQkJVemtHSkErVkxDeHVBV1JtTy9VY3ZXcnN2UVIwSnhiUXg1dmgza0xrRWxYTS96R0xlYXhIcmFGVTI5UW83amdNRUROL2xwQUlsNXRWWnpOR0J1My9KbDZCeTdxb3NCc3BxS0hITTNZTUR4LzRDV25sRTBxeDlLTW10VHFBV1FGOWc1M0FFTkZnVmtwejZacU53VlJhOWRPSTVKSUJmQjVrTGRpNlVvNU5ES3d1OU8zL3B2WUNkd3hIQUlHVXRZMGg1b1VhNEpKMDVQSEM3cE84TmRpNDBRMURSWFNRd1k3c3hsem5XU2FMSDhCc0RxMS9YQkFMc1hBaUdvbm1hR0cxN2wzUi9DWGRxSWpVdlp2elphSDc5RWlDd2M2RVdpZ2R0R2h6VkkvKzJnajh2bGRZZllhZzc1OWNwZ1FNN0YxS2hqWTMxOEo2NGZ2bTVhbjVEQnN4VjlWdElEUHc2SlhCZzUwSW5KTTNUeVd1T2Zobm1EVmRrMGdGODBzMkJ3YzZGU0lqYVdBdXJSdmRLejFiekd6T1paYkhqOHdic0hIYk85SUFDemkxNUtnaDFXNmYwWkFWM1NUbzkrUjBYdER6ZzF4MkJCanMzdTBQVzBJWGZ0Q0hsUDAzaVBjWHN1bFRxQ0llM3dhZkJOZ1BzM0t3TWFEOUc4Y0Q4dE1TdDd1cVMvK1FTYnNwbFRrbWdGdHFtTDcxTmdKMmJmU0dveUxaaXR4cmVKYjFhTDl4VHpGMmNUaDhYUjg2SHBwNFlVbjNiZjRvSkt1ZXV6bUkrYUVIN1cybFRjbi9zN0FnNFBTVU5mVnRQeUo1ZVFhdW4xWndSWlhlWEJEMzZRQW0zTVpOZUZVK2k5QWFORExiNXRmeTBFRlRPWFpQRmZOZ2lOakVtYjhNeCswTFQ5N09CMFhOVTh2VHdXaU9qbFJCcThxQzh1MXQ2dTFsNHJvYmZYTVJlbWNtY2xrZ2Q2ZER2Tlo5WXhlalg4dE5DVURtM01ZTjVyVjZBMDdSUDBOeXlCeGlXWmpVaVlraG5VR2RBUVBUcDlBcmdrNmVMOThBa29KM1RXbG10aVVWcHpFV3A1U1JhWnBFK0pEdjc1YkJ1NmRNMmNVdWo4RXcxZjI4eGUwMDJ2VGFGUHM0SnBkdjQ5ZDVwSDB6OUNBcm5BUDJ4cE9la1VMOHU0ejVvRmFONjVkaCtoSzF2Tm1QdFJjVDB5dEc5Y2xRUElxSmIydE10UWJyYTFTWHQ2SlMyZGtwZmRVai9iUmMvYXhNL2FoSGZheEZoK3ZsNmcvaEtIZjk4RGY5VUpmZFFHWGRYRVh0ekhudGxGbk5lS2cyemhHV3hwSGZoRnN4TWpmUm1tT2ZYNE5OSXNEZ1hUY3lMSWVBNExzOWs3aXhpSHk3akhpMUhnSUt6R1BpWUJxRE9yMHE1QjB1NSswdllYNWF3a0s3dUxtTHZLbVIvVnNEZVZzRCtKSis5SlkrOU1ZZTlOcHU5S3BPNUxJTlpuMGF2VGFaaDZGeVZRRUhYSE81QUZkdGN2Um05QktGcUV3U0xjekhFbkJoaXNaMDRObzQ4SlpFNkk0azZNeG14Sm1rMkF4L1Q0SFFna1FLSFRrMUVpL2doWGYwZ2dUcEpYOU8vTW82Qzdqbk9TYTdRbC9zZjVTQVB0NU9MYkdoWWdCYno2bVdrTkMvQk41ajZFVHpPR1VBN0FuREtoaFRHcDBaRWZ3TnZydG9uSUphQjM3OERlN1ZxY0JGY3prRjdvYk5XUDEvOTlwSUphZlJNTmlIWkJETkZNaitDTGM5TnRpUG13UGkxMnd3aTZKekR6SHF3YzVpcEJqdUhtV3F3YzVpcDVxQ2RvN0J6R0hNd25JdW5YbXNRdlhyNWhJOXpzYVFsWmN3U3kvdi9QUWJ6WFFIblVpRFBFYThmMkxrVkRyY2wyWU9kdzVnQWpKWkpubFhPMFMzMXZGY3ZuNWgwYnFWMUFPbnA0Q3hXeW1JbC9WOEZnemtZd0J6d0o1WUQ3Vlk3QnQrc3BiMTYrY1NrYzZkRmRWaWlSaTAyQmdGLzV2ZGFHTXpCWUtNc050cGlweTJSSTJ1dG5lL1dqSHIxOG9sSjV5N2FVemQvUnp2Nk0waDE4R2UrTDRUQkhDUmdtNE8xUkxzUDI5RzJNYXIraStwK3IxNCtNZW5jcmVFbHk3NTJ6WWthdHNSSkZqdmovMW9Zek1IZ1lDeHg0cHlJd1JWZjE5d1JXUnBSMWVIVnl5Y21uZnR0Wk83WjI4b1dSdlJiNGlXa0tpN3BNTjhWY0FiTWlSTVhoZmVldDdYMG1aaTh0T3BtcjE0K01lbmNPL0Y1TjRhVkhCUFdnWkljL0NVYVhyRjJtSU1HaEFObmRITlc3Rzc5Y1ZqUlI0bjVycFoycjE0K01lbWNzNkR5dDdhU3MzYlh6US92OVFxTFp4S1lnOGNRTG9aY3NMdm4zTjJ1Wnh3bHlTVlZROE1qWHIxOFl0SzV1dGFPRDlQTGJ3MHJXYkd0emhJeGFJbVgwV1FDcHpyTVFVR2lLN3RRbFlYM0g3K3Q5cmJ3NGkreUtwczd1aVJKOHVybEU1UE9FU1NaVmw3N0oydnVKVHRLbDRSM3c2aU1YZ1ZmcThOOEsyQUllT0lVTEhIQzRXRWRHM2VXL05XZW0xTlZUOVA3dURnSE1lbWNxcW9kblYyUk9hV1B4aFN1RGFzOUxLSVBaVXNubUtkZk9zSG1ZZmJHcU9IMEs4QVdHN1Z3VDgrNnNKcW5iSVgyL1BLZW5sN1BmcGJOVHpvSElRaENRMnY3bDVsbDkwWVVuTGFqZWtGNEg3cHVnaTZkUUdHSWF6dk1Yb0FWNEFZWTRoUVhodmV1MlY3NVlGVEI5dXl5bG80dVVkekhONjFHZk1NNUNKWmxLeHBhUGswcHVpK3ljTzN1dXFYaDNYTWpoMUhtaE5vT1FQSkJ6Z1AvY05vTFNZeGgxSmd1R0VwWXFYbFJ3NGVIZGEwTHEzMHdzdkRMak9LYTVqWklYbDZmOWhYK3prRlFGRlhaMlBwVlp2bWowWVViZHBRZXY3TnhibGd2dW9BQ0ZTSVlEVytEaDlxUUJRMm1EQnBNalFIUXhzemIzYjF5UjhQR25hVlBXZ3UzWjVlN1d0b1podkdhdEovWWgzTVFITWMxdExSSDU1YTlhTS9idEtmMDdMQzY1V0h0aDRYM1d2WU1XcUxkM25lRklSeXFQVXdJSWVnWmh3RUg1a1FNd21DNmZIZmJPYnRyYjlzRGs0WThxT0dhMnpzUG5PR00yTGR6RURBZWQzVjNwMWZXZlp4WjhaU2o1T2F3NHJWYlM1ZC83WnE3dFFYZENnQkhrRHlHN3ZIRWhBN1E0OUR2a2NQenQ3VWN1OVYxM3JheVc4T0tuM2FVZkpaWmtWVlYzOVBUczg4ckkzdkhmcDJEMERTTkpNbjYxdmI0b29yM0V3dWVpczc3YVVUWlpWRU5aMXU3VG5FTXJuSzZUM0FTSitocjBER3pIUXI2R25wOHRXTndyYlZ6WTFUOTdSR2xUOGZrZjVpVW4xUmMyZFRlQ2ZVWTJPTDE1dHZpUU00Wkljdnk0T0JnZFZOclNuVnpXR1g3NTlVRDc3cmNiOVl4VytyNTE0QUc5Q2h3ek95bm5vY2UvM2NkODI3TjZCZlYvWHVxMnROcW1sM05yVU5EUTRxaWVGMDV1UGgyNTNEZ01EZXdjemltTnNiRy9oKzlQNytLZktPK1JnQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiXSwiZXh0ZW5zaW9ucyI6WyJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiI1ZDYyOTIxOGQzYTUxMWVkYWZhMTAyNDJhYzEyMDAwMiIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZX0sIm1heE1zZ1NpemUiOjEyMDAsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJ0cmFuc3BvcnRzIjpbInVzYiIsIm5mYyJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA5LTEzIiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJTd2lzc2JpdCBpU2hpZWxkIEtleSBQcm8iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIzMDkxMzAwMiIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNS4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIzLTA5LTEzIn1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAyNC0wMi0xMyJ9LHsiYWFndWlkIjoiZDQxZjVhNjktYjgxNy00MTQ0LWExM2MtOWViZDZkOTI1NGQ2IiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWd1aWQiOiJkNDFmNWE2OS1iODE3LTQxNDQtYTEzYy05ZWJkNmQ5MjU0ZDYiLCJkZXNjcmlwdGlvbiI6IkFUS2V5LkNhcmQgQ1RBUDIuMCIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjozMDAwMDM5LCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwiaXNGcmVzaFVzZXJWZXJpZmljYXRpb25SZXF1aXJlZCI6dHJ1ZSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQnpEQ0NBWEdnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpCaU1Rc3dDUVlEVlFRR0V3SlRSVEVTTUJBR0ExVUVDZ3dKUVZSTFpYbERRVEF3TVNJd0lBWURWUVFMREJsQmRYUm9aVzUwYVdOaGRHOXlJRUYwZEdWemRHRjBhVzl1TVJzd0dRWURWUVFERXhKQmRYUm9aVzUwY21WdVpDQkRRU0F3TURBd0lCY05NVFl3TWpJMk1EZ3hNVEEyV2hnUE1qQTFNREF5TWpVd09ERXhNRFphTUdJeEN6QUpCZ05WQkFZVEFsTkZNUkl3RUFZRFZRUUtEQWxCVkV0bGVVTkJNREF4SWpBZ0JnTlZCQXNNR1VGMWRHaGxiblJwWTJGMGIzSWdRWFIwWlhOMFlYUnBiMjR4R3pBWkJnTlZCQU1URWtGMWRHaGxiblJ5Wlc1a0lFTkJJREF3TURCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkFKY1dxZUN4Z2E5S0piRk8yVFpkamNncnRaQWdmaThUWEt1K3Y1bGNSNWNlYjVHSll4eW9Damh1ZUVTTDNkZG1NSWtwR3loc0VFdGZGVXlCd3N5RlZDakZqQVVNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUw0VGJQMDBzRU5iVEVYR29hZ002SGtsMlhJRHJ4Z0tiSHdvdy85R2liWVRBaUVBdWRJbTdFR3FmeWE4UXlnS2Nia1FmcXJ3ZWZZbkJ2WktJMHh3bi9rS1d4ND0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRHdBQUFBOENBWUFBQUE2L05seUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFDeEVBQUFzUkFYOWtYNUVBQUFVMFNVUkJWR2hEN1ZwYmM5TkdGRDYyYk1XT0x6aTJrd0oyTHBBV1NndDBJRUJ2VDMzdGRLWXo3VnQvWUI4NncyL2dwWjAyaFlkT0FrK0ZhU0JwSURlSDJDVyt5ejNmYXJlUjA5aXlva3M4anIrWk05YXV0T3Y5OU8zWmM3UlM2S2VWdFE2ZEk0VGw3N25CbVBDb1kweDQxREVtUE9vWUtBN1htbTB5YUxqRGRaaENGSXRxc3RRYnRvUkI5dnViYzZSSHd0UVpVczZoRUZHalpkRERwNjlzU2R0T2FTaXJheHBGd21HS2FzTnBHSnZPdjRQTXdvRjh1RE9zMGxvdzZCaHRwL1JoczBVLzNMNUNVWjdTd1BQZENtMi9xNUtHZVhTR2FEUEJtVVNjM3MrblJMblphdE9QSzJzMEdZMkljaTg0SnZ6cnl4MzZjNi9DMCtoc0NiZU1EbjJRUzlIbjg5T2lQQ2hoeDJFcHpNcUM3RW0rRktSaERCaUxVemdtN0JZR1Q4VTJxd1BEY2RBSWxEQkl4aUlhcFNlaXduQ011aUFSR0dHc29tM0RvRzgvbXFXdlB5d0l3ekhxZ293Q2dSRnVzcEszTGs3SjBoRlFoM05CSVJEQ1VMREZTdDYrOUgvQ3FNTzVvRlFPaERBVS9IZ21JMHRFN3hvdHFuSzRVOEE1aEprZzREdGhLR2V3Z3ZlS09WbER0UEo2bi83WTNKY2xvcVZDTmpDVmZTY001YTdsMDdKa2hxWG5wYkl3UlRERThmVDZkRG9RbFgwbHJIeDN5YUx1S3FzYkRvV0ZyYnc1VXZudTVWd2dLdnRLR0RGMmtkTS9QTTBvckc2OXBTZ3lOYmJWTjI5bExZbnNDZGY2SFpkOUl3eWw2dTAyUFNqbVpRM1JzNjE5Zmt3M3A3QXdXYWR3djVBVGJmeFUyVGZDZUpwWnlDU0ZjZ3BQL2k2Unhtb2JyQ0lNeDA4MlN2SXNrYzZaRjlxZ3JWL3doVEFVYXJRTittek9mSklCWHV5VkthVkhLTW1Xa0liajFFU0V6MVhrVlVRUFpuT2lyVjhxKzBJWUNzMm1KN3UyV3haemFmcnU1ang5YzZQWVphaUQ3eXBNNmxFcWNsdS9WUGFjTUpScHNrTFdsZGtwbHRpWDBZY2ZLbnRPR0l0c2dSVzZFTk5salhOazRycm93NDhGMi9HT3gvS3JYWHBScW5RdFJsWWdyT0M1M0JTbjB4V1M2cXphVjFmZW84c1hKa1Y1OCtDUUh2MjFSUk9XdmhDTGVWai85YUgxMkZuQkRGak1wdWpUT1RNSytMYmowUS9Jb3VMc3QxZW5rclF3bFJBWkZrakNINFVKeWF6M1YyNEd5UE80Rm0zUUZuMmdMNjgzQ1R3akRIK3I4VjMrY242YTdzL214UW85bDBtSWVtekZtSVlycllxWmRlbzhya1VidEVVZlgvQXYrdlRTbHowakRQR3k3SHY1UkV6V0VQMjh0dDF6NnArRUtFLy9YMTd1eUJMUmRESW0rdlRTbHowaGpQRTBPRU5DUHF5dy9VK1Z5dlZXbDU1MmdOOGUxQnJjdGlacmlPNWN5cksvc3NxeTdCYmVFT1lwbCtMNFdaQ0xFYkM4dmlmZUJpQ0ZIQlM0Rm04NUhtL3N5aHFpSWsveEpQZnQxYlQyaEREZTY5emxaMXFGMG1HZFN0VzY5RmxuUUp0ZHRHZFR1TU45SS92eUFxNEpZeFhWdFJETjg2cXE4TnY2RG9jYXpaRzZDbWlEdHN2clJ5b3ZjTi9pM1pFSEtyc21qRHVQRlZXaExIeXczak4rRGdLMDNXSS9SbDhLOXp4UzJSVmgzSEdvY1pVVEFBVW9FNU5KaWh0TWNCKy9iK3pKa3BtTEkwRnhxN0tya1NIYitjU3lFNG5OdWRlVnFvaXBib0dYZFp2bFE5R253cTJMR2ZHZmJuQnF3bGcxeFM1Rk5rbDFUZzd3Zkx2TXZvdTZmcjVyamN2OVlqVDZ3UG5IRmwrK01aTVJieXZjcU93cWx3YnBHcS9RWmlRMkNWaHo1K1BBUU9NODRJZ2sybUsxcW55emVzMEk5STgyYVg0UXdUR3V3eGNKVGM2M3NlRVhlQzRORlpEdnh2bFBZUDNJQWhnd0NKWnJUV0g5eUFMb0grZHhiWVdUbUFQK0JkbCtNOGdPcmdpZkJpQ0FWUmpXajZ3Q3lLbnJZVzdJQW80Slk0cGhPbUh4T0V2REdFN2p5K05QSG83ak9PRmhoYWVMbGx1L0NRS0RqdEdXTUw1d3c2TWZ0bDVPOHFWaE1Jd05hU2ZHYWdmYktRMmNxMDhQUnczRHZSTDVnREhoVWNlWThLaGpUSGkwUWZRdjNXeHdxWndHMDJ3QUFBQUFTVVZPUks1Q1lJST0iLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCIsIkZJRE9fMl8xX1BSRSJdLCJleHRlbnNpb25zIjpbImNyZWRQcm90ZWN0IiwiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiZDQxZjVhNjliODE3NDE0NGExM2M5ZWJkNmQ5MjU0ZDYiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjpmYWxzZSwidXAiOnRydWUsInV2Ijp0cnVlLCJiaW9FbnJvbGwiOnRydWUsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6dHJ1ZSwidXZCaW9FbnJvbGwiOnRydWUsImNyZWRNZ210Ijp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoyMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxMjgsInRyYW5zcG9ydHMiOlsiYmxlIiwidXNiIl0sImFsZ29yaXRobXMiOlt7InR5cGUiOiJwdWJsaWMta2V5IiwiYWxnIjotN31dLCJmaXJtd2FyZVZlcnNpb24iOjMwMDAwMzl9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wMi0yNiIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiQXV0aGVuVHJlbmQgVGVjaG5vbG9neSBJbmMuIEFUS2V5LmNhcmQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDE4MDkyNjAxOSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zLjQiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMC4wIn0seyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDE5LTAyLTI2In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wMi0yNiJ9LHsiYXR0ZXN0YXRpb25DZXJ0aWZpY2F0ZUtleUlkZW50aWZpZXJzIjpbIjg1YzhkNDY5MDY0NzU5MWI1YWM5Zjc1NmNkODc1ZTk4MDQ2MWZmYzQiLCJlNTU4NzhhYjBiMGE1ODRlNGMxYWRkNTYzM2UxOWMyNWYwODk5YTJkIiwiNDNjMGY4MDliMWQ3NTYxNmFhMTUyYzNjYmE1N2Q3MzQ2NTA1N2YyMSIsIjExYzA5MTBhOTc4MmJhM2QwYmQ4Zjg2YmJhNDllMjgyMzY1Y2MwNWMiLCJjOTM2YjY4ZWVjODU4MjMwZmUwNzQ2NDM1OWMxYjVjMGQ3ZWZlNDdkIiwiZDBkODQ0ZWRmZjExN2M5NzlhMDVmYTY2OGEzMjk2YmNlNjk2NTU5OCIsImVkNWJkYjk2MDExZTNkNDU3ZDg1OGFmMzllMzBhYzU3YzVhYzk1ZTYiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiODVjOGQ0NjkwNjQ3NTkxYjVhYzlmNzU2Y2Q4NzVlOTgwNDYxZmZjNCIsImU1NTg3OGFiMGIwYTU4NGU0YzFhZGQ1NjMzZTE5YzI1ZjA4OTlhMmQiLCI0M2MwZjgwOWIxZDc1NjE2YWExNTJjM2NiYTU3ZDczNDY1MDU3ZjIxIiwiMTFjMDkxMGE5NzgyYmEzZDBiZDhmODZiYmE0OWUyODIzNjVjYzA1YyIsImM5MzZiNjhlZWM4NTgyMzBmZTA3NDY0MzU5YzFiNWMwZDdlZmU0N2QiLCJkMGQ4NDRlZGZmMTE3Yzk3OWEwNWZhNjY4YTMyOTZiY2U2OTY1NTk4IiwiZWQ1YmRiOTYwMTFlM2Q0NTdkODU4YWYzOWUzMGFjNTdjNWFjOTVlNiJdLCJkZXNjcmlwdGlvbiI6IlNlY3VyaXR5IEtleSBieSBZdWJpY28gd2l0aCBORkMiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MiwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURIakNDQWdhZ0F3SUJBZ0lFRzBCVDl6QU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TlpkV0pwWTI4Z1ZUSkdJRkp2YjNRZ1EwRWdVMlZ5YVdGc0lEUTFOekl3TURZek1UQWdGdzB4TkRBNE1ERXdNREF3TURCYUdBOHlNRFV3TURrd05EQXdNREF3TUZvd0xqRXNNQ29HQTFVRUF4TWpXWFZpYVdOdklGVXlSaUJTYjI5MElFTkJJRk5sY21saGJDQTBOVGN5TURBMk16RXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDL2p3WXVoQlZscWFpWVdFTXNyV0Zpc2dKK1B0TTkxZVNycEk0VEs3VTUzbXdDSWF3U0RIeTh2VW1rNU4yS0FqOWFidlQ5TlA1U01TMWhRaTN1c3hvWUdvblhRZ2ZPNlpYeVVBOWErS0FrcWRGbkJubHl1Z1NlQ09lcDhFZFpGZnNhUkZ0TWprd3o1R2N6MlB5NHZJWXZDZE1IUHR3YXowYlZ1em5ldWVJRXo2VG5RakU2M1JkdDJ6YnduZWJ3VEc1WnliZVdTd2J6eStCSjM0WkhjVWhQQVk4OXlKUVh1RTBJek1aRmNFQmJQTlJiV0VDUktnanEvL3FUOW5tRE9GVmxTUkN0MndpcVBTemx1d24rditzdVFFQnNValRHTUVkMjV0S1hYVGtOVzIxd0lXYnhlU3lVb1RYd0x2R1M2eGx3UVNnTnBrMnFYWXdmOGlYZzdWV1pBZ01CQUFHalFqQkFNQjBHQTFVZERnUVdCQlFnSXZ6MGJOR0poamdwVG9rc3lLcFA5eHY5b0RBUEJnTlZIUk1FQ0RBR0FRSC9BZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBanZqdU9NRFNhK0pYRkNMeUJLc3ljWHRCVlpzSjRVZTNMYmFFc1BZNE1ZTi9oSVE1Wk01cDdFamZjbk1HNEN0WWtOc2ZOSGMwQWhCTGRxNDVyblQ4N3EvNk8zdlVFdE5NYWZiaFU2a3RoWDdZKzlYRk45TnBtWXhyK2VrVlk1eE94aThoOUpESWdvTVA0VkIxdVMwYXVuTDFJR3FyTm9vTDltbUZuTDJrTFZWZWU2L1ZSNkM1K0tTVENNQ1dwcE11SklaSUkydjlvNGRrb1o4WTdRUmpRbExmWXpkM3FHdEtidzd4YUYxVXNHLzV4VWIvQnR3YjJYMmc0SW5waUIveXQvM0NwUVhwaVdYL0s0bUJ2VUtpR24wNVpzcWVZMWd4NGcweExCcWNVOXBzbXlQeksrVnNndzJqZVJRNUpsS0R5cUUwaGViZkMxdHZGdTBDQ3JKRmN3PT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQ0FBQUFBZkNBWUFBQUNHVnMrTUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFIWVlBQUIyR0FWMmlFNEVBQUFiTlNVUkJWRmhIcFZkN1ROVjFGRC8zZDU5d2VRU0lnUzlBUUFYY0ZMQVFaaTlmcGVWejF0WS9XVFpyNVd4cGM3VzVrbkxhNWpJM1o4NXNyUzJuTTJzanRXd1pTN0lVSDRINHhDbkVReDREQVpGNzRWN3VzODg1djkvbEluQnZWSi9CNFB2OW51LzVudS81bnZNNTU2ZnpBL1F2MEhiL0lyWDNWRktQbzQ1Y25tNGluVUlXWXdMRlJtWlFVdXdqRkcvTjFpUkhoMUVaME5SVlJ1ZHF0MUJkKzJuU0t5Uy9PaHlzMCtsazNlLzNrUTlxdkQ0WlV0YTRWVlNVdVkwZWlweWlUaEFmb2NvT1JWZ0R1dXczcUtSaUFkM3JiY0V0alRqWUlvZjZXYUhzQ216VlBXQ014K2NnaDh0THFXTUthTVdzVWpMcW8yUnRKSVEwb096bWVycFF1NGVzWmdzT05rR3hIN2Qwa2R2VFQxN3M0T01VN1ZJOFpoamdHYU0rQXE5aUVOdThQaWYxdWR6MDdNd3ZLV2Y4R2xWb0NFWTA0UEM1V2RUYVhZRmJSOHZOdkw1KzNLZ2ZiNXhOTXlhOVJhbUppeW5hTWxHVFZ0RmxyNmJhOXUrcHFuRVg0dU11UlJnalNZRWhyTjd1dEZGZTZscWFsN05ma3c1aW1BR0h5blBwYms4Vm1ZMHhzdG5wdGxGQ1ZDWXR6VHVCTjgzUXBNTGpUdGV2ZFB6U1VuSjdlOG1ranhaMzlmWGJLRGZsZFpxYnZVK1RVZ0duQlZGNmZRMmlQSGc0VzE2VVdVd3Z6YmsxNnNNWkUrUG4wcHZ6N0pTZXVBeWVzOGxjcENtYUt1by9wK3FXcjJVY3dJQUhXcnZQMFlFemhYQXRMQWJzc0hocDdpR2FtdnlpalA4cnlxclhVV1g5WG9vd3h5QXVmTkJycDQzUE9CRlhabGtmOE1EUmlxY3B5b3dBd3B1ejJ4K2ZXdnovRHRkZTlzbXN6eWd0Y1I2QzF3YmR6Qmw2T2xxNVdOWVk0b0dhdGhKTXJrVEV4MGpBUlNIQVZzKzVyWWtRTlhiK1FnZlBMc1E2Z1h5SW5zcmVRZm1wbTdSVkZZZkw4Nm4xZmlVT2tZdlNoa1VQeHZidWt6b3k2SzFpaE0xaG8zWHpXNkV2U2ZYQStkcGlXR2FXZCtkb1h6THptR3dLWUZMQ0FzUkFsUEJBaE1sQ0ZYVTd0QlVWUHI4SGdWY0pIV3ErRjAwcGxyK0RNVGRyUDR6dnhZMTFrTk1oeFQrU2VUR2crZDRWNUxRSml0eVVHSk5COFZGWnNqZ1lCWk0vSUkvWENUa2owcXlET3BGMkFWUTE3Q0lqVXAvRG5UMVVrTDVGNWdkaitzUzF3ZzFnRTNnaWdtNjBmQ1h6U25QWGJ5QVBiSVh2K0lEcEUxNlRoYUhJUzlza3lobG1NRTVGM2NmcUFLaHEyQzBFNVBIMWdZYVhhTFBEa1pHMEhESk9uS1dIcDUxSTB6NVNPdXg4ZTFXQXVaemRIUXJUa3A4VG1qWG9JK2xhMHdHWnN6dWJxYk8zaWZRNkEvVzd2VlNZc1YzbVIwSkt3a0tjNFdIaUJrbVI4STNDQ2dJODdvT0w0cXpUNVArUlVKQmVqRU9nQVBLOGhZUHphdE0rZUlUcDJJTzl5VFFtZXJvbVBSeHgxcXhBY3NpbGUvdWJTZUViY1dRR1lFQ2doY0xZMkh5S2pvZ2pIMjVoTXBqcFV2MU91Z2xpNGVoMmVSdzBPMzJiSmpreXVDZ056ZzB2emxZTVNpU3MwdW9vNE1HN2hNT2pDRWFYMXlGRTBuU3ZqQnp1VG5FcEs4Nlo4SW9xRkFJdWJ3OGtnOUFyRWFSRVdTWkkrakg0WGJwNmc5RTlFbkpUM29hUnpETitNVUpCUURIbjU2YThvVW1FQnVzT3hCcy9ONSt0SkViUGtBRkRqOFVHdk9zL0lXdmNTZ2xHQmh2UzcvRlRZZnBXR1lkRFk4ZlBBeFdTQTM1c1RDNHA0K0xtNEFhcUlvUGVRdGZ1Zks2SmgwWmh4bGJzVVhPU21YTmlmRDVaVEFreURvZmJiY2NseG5BOFdOQXF4Q2JSTnlraFh4UXBhRHc2N2ZYVVlic2lHMEtodHYyb2VJdmg4cmhRTVlPY0VBcVhHL2VJK3puZ09jNXl4cjhxODJJQU0xYy9GTEZPcGxxdTVlRlFYck1aekdjVkNqWWJMV0c1STRCVDFldVJybGJ4dE5PdE1pdERERWhMWElJeW5BQXZ1T0VXRTNYM05kQWZ0OTRWZ2FHNDJYSVF0MFpYNlBlQ0UvcVFGZTlySzZIeDdZVTUwS3ZIN2ZXNGZTK3E3S0tCSnhzZ2dCWDVwU0FHaDFqSXJWaDV6UTZ3M1JmYWFoQlhtL2FDYkNaVGpDVUZVVHlXWnFXOXA2Mk1qSlBYVnFPclBnTU80TnY3NEdrZitvd2Z0TlZCRFFuakZKcUhTdzE3cFh2aFdXNUtacWUvUTQ5Ti9VU1RDQVZXb1FYRklIQkhYWGUzRlByVURzdUdEbXRGL2hIS1RIcGVreGhpQU9QSStTSnE2UzZIRjRJOVlXemtCSlRvNDZpVU16V3A4UGlyL1JpZHVMeEtZc1Nrc1Y4dkxsT1F2aEdYMllsUjBPQmhCakMrdS9nRWN2WTBBcEs3WWs0MU54alBTUW5XRkhURjY2VXJqZ2V2QjhDdTVhK2wydllTUlB0dVZEbzczaGhkTVNIblVYN3RUanNWWkd4QWwvV3B0aU9JRVExZ25MMjltWDYvdFIxdG1sa1lqOFc0WCtDU2pXY1VER1kxTnBTL0M3aFNLcWlNTE0vbDJRbVNXWjczRGR6K2dpbzhCQ0VOWVBRNDZxbmt6d1hVYnF2Qmt4alVRc1dmWkZnYnVvM3JBZit3TjdqT085MCt5bng0UGkzTCswbllMMVNjaERVZ0FQNGdQVi83SWQxcSsxSFNobXVHa0lxV1JQZ3l4TUZxUDhIZmpUbmpYd1k1YlFmYkpjdDZPSXpLZ01Ib3RGL0hlMWVnc2F4SFNxRzZ3ZmRtUTV4OE55VEZGcUJjcDJpU293SFIzeWs1KzM2aEY3dlhBQUFBQUVsRlRrU3VRbUNDIn0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMDUtMTIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IlNlY3VyaXR5IEtleSBieSBZdWJpY28iLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDE5MTAxNzAxMCIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4xLjEiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMC0wNS0xMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjAtMDUtMTIifSx7ImFhZ3VpZCI6ImU4NmFkZGNkLTc3MTEtNDdlNS1iNDJhLWMxODI1N2IwYmY2MSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiZTg2YWRkY2QtNzcxMS00N2U1LWI0MmEtYzE4MjU3YjBiZjYxIiwiZGVzY3JpcHRpb24iOiJJRENvcmUgMzEyMSBGaWRvIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjAsImJsb2NrU2xvd2Rvd24iOjB9fSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6MCwiYmxvY2tTbG93ZG93biI6MH19XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSURkVENDQWwyZ0F3SUJBZ0lKQUlDVVR2a2d0ajVDTUEwR0NTcUdTSWIzRFFFQkN3VUFNRkV4Q3pBSkJnTlZCQVlUQWtaU01Rd3dDZ1lEVlFRS0RBTkVTVk14Q3pBSkJnTlZCQXNNQWtOVE1TY3dKUVlEVlFRRERCNUhaVzFoYkhSdklFMTFiSFJwUVhCd0lFWkpSRThnVTNWaVkyRWdRMEV3SGhjTk1qQXdOekEzTVRRek56RTRXaGNOTXpBd056QTFNVFF6TnpFNFdqQlJNUXN3Q1FZRFZRUUdFd0pHVWpFTU1Bb0dBMVVFQ2d3RFJFbFRNUXN3Q1FZRFZRUUxEQUpEVXpFbk1DVUdBMVVFQXd3ZVIyVnRZV3gwYnlCTmRXeDBhVUZ3Y0NCR1NVUlBJRk4xWW1OaElFTkJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXZBS09lcUM1L3AwRDFpc0NZS1FKbFZVT3JCNkk3RExvY3VuRS9SbThkdUdUYnl4UWh0M0NiRlZUdjNOMkxwMmZianhsSSszc09TR2szM0ZUWWtUcXhjZEpJcko3U3NrQmNVU05yZktPYVFULzZLUWNQNENtN1YrNjU1VHErVFd4eXhXUWhEeWd0MTVxb1A3TXVLNmJUOVN3cENqcGZLaGFNU215UWFNb1VjUkFiTHFkekJDYWMwaHpCK1plK2dxSmxuV1Y5VWFTSTJyRnNWdUg0WkUwY1JPK01PcGFMZ00vczI0OG5HR0hwMjJld1NRZmJuUGFCYmI4aXF5QVArY3U1MkdMc1VwS1JKZWJFK1I2K1BNUTlKQ2RXZVFaUjNEa2ZTaWRrdjNtY2I0anExaUl0YStNcUtoUm53cmZYaDkxMUtXTG5ZQWw5RU5DaExYMGM2U2oxUUlEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVV0x2aFJCVVBuOHVMSWY2OCtndi9OWkl3R1NJd0h3WURWUjBqQkJnd0ZvQVVXTHZoUkJVUG44dUxJZjY4K2d2L05aSXdHU0l3REFZRFZSMFRCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGTHJEaGFlZ2VLSHhZakgzRVAzdlVCS2huek0yMDZBU3hnZVlDTzJFYzlwT2xZSmFlcUZFK3NVYW1VVi9wd2pEbHFOYVNnRmd5N1R3ZVlrdk9tTW40cVNjc0hxdkozekdPQWlhZndhaDF2VUhmQ2xYUjgrYXhPMmlHT1VGMEpLclo5WVlqYkFhNS80SENsdjdqRlBPZE1XVE9ReW5nb2lIQXMzamt1WWpwQ0xGbEI0Vk9pM2Qxd2pBMXBuVGRCS2tBYjd0OG5UdncrL1hiRnZjUWE3M1ZIN3Nqdm9CcUQzZmRNZlJjdVZxNHFVWnRaVDZjR2FnVEhENjFUdHFoOW9NQ1pYY0RiUjFQR1puTmJxeWNzV1BESUswbnBtSzMvM2xmVjhjK1pzcnk2ZTE3MG1mSk1acDdPOG02Q1N6Ni9WTEsreURKZDc4NDF3cG1lS1RmNkluWkE9PSIsIk1JSUM2VENDQWRHZ0F3SUJBZ0lKQUpiVHlydTFYL0lQTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ014SVRBZkJnTlZCQU1NR0VkbGJXRnNkRzhnVFhWc2RHbEJjSEFnUmtsRVR5QkRRVEFlRncweE9EQTJNVEl4TkRRMU5UQmFGdzB5T0RBMk1Ea3hORFExTlRCYU1DTXhJVEFmQmdOVkJBTU1HRWRsYldGc2RHOGdUWFZzZEdsQmNIQWdSa2xFVHlCRFFUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1WaktIV3BiRDdUU2xNeG9jalRsNm5JZjd4MzJQbXNROXpHdUxHR3FBMFVRWm9JcTNYTHpMNkxZVXZKNUE1ZzB1eUZHbGxIRWZHQUtyRWFDUThGVnZQUy9VaDBGeWZ6V2hSQXppVFNpampNSUlWampqVXY5bTl2Rm1jWFNjZ0hpZzdPZHo4ODU4VjBrck5IOTlxR20zd2pnYU9lclRXbXQralhDVWZuMDFJa1RQd3hHMkhsZ0VkNDVqTkxTVjdWb29sK0tlOEUya2k0bEVrVGVIemJvdWxSNUdVYnAzbk1pN0U0N1ZNUWEzYk53bnpXQmJzYUJTU1FoTGszbTVIYUtoaHhhNndKREs0N05pTUNrQ2tkSUh1V1NRTFZBZm04NVVBT050RU9Qd2kwT3VLM3FiZTh5S09GR2YwS2hCNU1NZUF5bTdNVi9NNFcwYTQ5b2dQRDlwTUNBd0VBQWFNZ01CNHdEQVlEVlIwVEJBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUNBb1F3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUpXejV4TE1rNVdOWWJBYjZ5T3hFQ0JvWjJXZUIvcWw0VkozTy8zL3ROc3hPWW56TGVXbzU0MHpRaDlyQW1heHo3ZXVtQmxza01xNHlHUFNOWEI5eWNXR0hna2NDZVN6TjJ3djhDSXpEQnMyb0JaalROazY1TEJaRHNzVE9CdE1XLyt1VEZIUWZidU8zSVNMaEkwRFhmUkVpOU5ETTNqZmsxMXhIY3NmaDJSTVYrUWROZndWYVpackNxK291RytFdmt2N0txcStveXUwVkZNL3R6NjhUR2w2eWxoUEZSMXFoOXd0dHBWakFPT0NFUUNMcVAyZFAyOGx3WUJ5Q3FIUXFWSHdidWp2L0xaalpuS1czTFluZFppeFBQU1JDSnNzRER3SnZoL2Y2blR4ZzlaRSsvSmNZcmU1Q2FJOG56VkhhU09Dak5KN0Z6VUxHNjRKaVdPdlE1MD0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBUXdBQUFBZ0NBWUFBQURubFVacUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUFBWmRFVllkRk52Wm5SM1lYSmxBSEJoYVc1MExtNWxkQ0EwTGpBdU1qSHhJR21WQUFBSzFFbEVRVlI0WHUxZERYQWNaUm0rTk9BZktvZzZXTzBRY3JlWDNPNzFSNDFvSGRTcXFEQU9nMytjWUVYQm9sWFJURW4yMjB0YUtUYzY0bWdCcXpCaUVVVnBCZHFpd3docVNkSVMydXBZU2d2UnRwVFNja2xqV3pIYWdqcFNSZHI0dkx0dmpydmsyN3ZkdmQxTGpuN1B6RE4zdC9kKzcvdCtmOC8rNzhhSzBORGFhcjJxT2RYWm9xV3lIOVIwYTBGY3Q2N1dkSEdUWm9qVkNjUHFTZWpXMW9RdUhzT3kvZUJUc0RtTS81NFpUOWorTFdHSWc3RGZCL3NCY0RQc2Y0WGZQOFgzYjJ1RzFaSFF6VThtVXVLZHlXVEhtNXFhY2kvakhBS0J5aWYwYkJyK0x3YVhJUFlQa01kcWZMOFhkV3BsczFBQTMxL1FqT3c5OEw4UzliOEJYSVIyK25EYzZEb3psc2swc2xua1FNeGtQR1hPOUVKdFZuWUdGNHNVeVZuZDhVVGFlcDhidys2TGFrQmo1aXpkYk5KUzFyeEVXbnlXeGczNkVtUGRXb1BQRGVqZjdlQVRHTXNIYUR6VHVDNmhiajBOL3BYbUFzcnVnczBXTFA4TnVCSmpaSm1XRWxjbDA5bVBKMUptVzB0TDUrdWlIQnVHa1hzbGpYODduaTRFelZuazlBdmtzUW41N0VTZGhyQjhCTXVQak9XUC8vNE9Ic1IvZTdEOFlkVGxmdFJoRmZnZExHOUh1MXdBZnpyNTVqQU9raVFLaHZWYkdCNkMwLy9pKzJpTmVSeDhGZ252UmZ4ZmFpbnpTazdORTBpSVVQYmY0M3dXbU5UTmQ3QnBLRUE3TFpmRkFZOXpwM3laVFNNRGlRVmkvVStTZzVRWUFJZk9tRzJld3NVakEvcmhXN0w0QmVybWo5aDBVb0IyT0IrVFpUVzRCL2s4T3lHL3lDaU9vVzFJWUg2SDhYUHo5TGJjS3ppbFFHaHBNWnZoWnlIR3dHM2c0MkJrODVaOG85MEc4WDBOaVNzMUl2MlFHazhLZFdzenQ0c25JUDhScVI5bURRWERJZFpTYkJvWjBJbDNTMk9YWlhZcEY0OE1VMTR3bksxYmVXNDFwTDNGRVFDSmxQVld0REcyZnV5VnJOUjN0QlRkU2pCOFlySUZveVZ0bm8yT0N6Qmd4RE5CQjZwWEtNSHd4aUQ5Z0szS2M2UGNrdkJHSlJpK01jbUMwWUQ0ZmRLNFhvaDlXL1lUQ1pSZ2VLTnZ3Y2hrR3RHMmUyVytha3NsR0w0eG1ZSkJheGxwVEkra05SUWRtR1Izb1VNSmhqZjZGUXc2Y0NyelUzdENNTERXdVFzZDNSK0F3M0tuQlE1S3luamhqZHhPbm5EaUNFWnVHanJzWVdsTUp0cGlXVUszQm1UL0ZmRXVkaGc2VVBlNkZnejBiUjZmYTZNbW5ZM2tsRHdoYVlqTFVVNmVzMjd0MGd6em03VmdVdTk2RDZma0h4Q2E2MlVWR0NNcThnMDJqUlFuaW1Cb1J2WWlhVHdtMm50Zlc5dkNrN1cwZFlIcy93SjE2M2s2ZU1adVEwVzlDd2JHOUsxc09xV0F2SVUwWDV0aURadE5iU2pCY0dFRWd0SFdkc3ZKOEUybkF1VXhpYnA1aFdNOTJvRGYyeWI4WDBLeDNyRU5GMG93b2dIbTBoSnB2amFWWVBqQ2lTQVlpYlQxZVdrc0ppYkNrL1BtNVU1aWM4cnhRcGxkTVJQcDdIbHNIaHFVWUVRREpSZ2g0c1V1R0hTUkQrcElWK1RKNHhIMUxHOWRqQ0hUaU1sUjRWaUcyRTdIUmJoQUtGQ0NFUTJVWUlTSUY3dGdvSjJ6MGpoTXRIT2VqbDJ3ZVFGWS9sR1pmU25GZkRZUEJVb3dva0hDTUJkTDg3V3BCTU1YS2dxR0lTNXZUcHRuaDBYVSswNVpuQUpERkF6RDZEZ2QvcDZXeG1IR0RmRkZOaCtIMFFiMHdhT3lNbU9FK09VTkkvY1NMbEExNmwwdzBGNjc0N3E0cFJwR2NkcWE3a3VSNVV0RUg0NWdEbXdLaS9EWmo4LzdJRVMzNHJPemVhYVl6V2xVaDNvUmpKb3pSTUdvT0FFTmEwaTJkVEdHZUVwOFRGSm1QRHZZdkdyVXUyQ0VRYnFoa3NPRkJzeWxpMld4YXNUajZOZDEycHNYdjU3VENRWWxHQzRNU1RCYVc2MDNvbzFkYjZxenFWdGZZbk01NkFwQnc5b3hvVndSTVlsR05LMzkxVnlpS2lqQmlFWXdtbFBkTGJKWXRTVGE3cUhpQSt1K29RVERoU0VKQnRwdmhkVC9HSFd4djl6V3hSaTB0UGlFdEh3SnhiVnNYaFdVWUVRakdIUndHdU9oMGdWNWtUT2VNaS9oaFB4RENZWUxReENNczFxdFZnenU4cmV2cHl5UGp3SHdzcFZoL1N1VldqS2RDd1NHRW95b0JBTzVwODMzb3ArZWs4V3NGZEYrd2E4U1ZvTGh3aEFFQTM3V1RQQmJSSFRjQWV4R3ZKVE5IZlFNTmNmNkJzK1A5ZWJueGZxZVBKV1gya0NaekhnZkV4akNHUUlsR05FSkJzRitFSkV1ZHN2aTFvYmlUNXlLZjlTTllPaldaalR5ZmFIUnVkOUFIb3RZcFdBNE54cUpZMUxmVE5UNUsyd2VpNjBmTWlBVUQ0S2pCZmJtajhiNjhzdGoydzdhRDJxaGZVLzB4eTZacnpIUzJxdWxwVE5sK3d5SXVoY01qQlU2NjFRTm0yY3VQb1BEUllUUkJqcGJSMk1BT1Y5SFp6T1E5OC93L2ZZd2lQSHRmamUwYnYyRmsvQ1BlaEdNT3JzT28vTHQ2N28xWERnVnVpRS9Cd0x4anhLeEtPWEcyTTZkdGkzNnc4T1JkbkdQN1RjZ2tGdWRDOGJVdkE2amxraWtPOCtUdGcySU1YU1l6ZnhEQ1lZTHF4QU1MN2V2bzc3dHRuRi8vMG5Za3RnaEVZbHhITHFhekoydGpFcWJzOWl5U1dYbjJ2NERRQWxHL2FPc1lCaldBVGJ6RHlVWUxnd3NHTGxwS0x0VjZwTkpIVlo0WUhMZi9uZkpCV0lDaDJIZFFFWGk2ZXdsTXI4bGRKNUhZdHY3aFJLTStrYzV3VUQ3N0dVei8xQ0M0Y0tBZ3VIcDlHZEtYTVhtRUl4OHUwUWNYUGpZYSsweW1Vd2oydXR4cWU4aW9vNFgydlkrb1FTai9sRmhsK1NQYk9ZZlNqQmNHRUF3NkhvSzdBNlVuY2lvNThHbXBzdGVlQjFENzlCWDVlSWc0ZjNEcDNPcEdPTE1sL2tmeHgyeHpGcmZqOFZYZ2xIL3FMQkxzb1hOL0VNSmhnc0RDRVlpVmY3MmRXYnBKZHc5Kzg2UmlzTjQ5Zzd1aDNWaEY0UEY2UW1KLzFMcTFnSXU0aG1WQkFNVDl1N3g3MHdKZy9UWWZVNmhMSlJnVkVhRlhaSUgyTXcvbEdDNDBLZGd6SjV0bmdLZkI2UyttUGovMEl3WkhTL25JZzVHUnhzaEJnTlNrU2psWWk1UkFQcnVVbG1jWW1KeS9YbkczSEV4SzZEaUZrWkV4QmpZeUNtVVJTWEJRRHVQb0E1Ym8yYlN5TDZkVS9JRTNpcVVuZ1lObTJnRDE3TjArRzhWcCtRZlNqQmM2Rk13NHJwbFNmMFVFVEZOTmk5RnovRE1XRy8raUVRa0hQYm1OOFMyYlp0NCtiaHpqMG41SjNpQmRGczFsL0FFMUwydUJhTldUT3JpQTV5U0p5RHY3OHI4MUp5ZXJ5NldRQW1HQzMwSVJ0T2MzR2xvcDhOU1AyUFV4Vk5sMS9UcjhxMnh2dng2OFBraXNmZ25mbDhmNng5MGZRVWw0bjVHR3ErWXVqaHk1cXp1MTNDUmlsQ0M0WTExS1JqMFdrZ3RGL3dtUlNVWUx2UWhHRjRtR0FhTFlQUHkyRGcwUGRZejlIN3Nwc3lOOVF4VWZDMGlYZnlGUHRvbmkxbE1HcXhjcENLVVlIaGozUWtHeENLcFcrL21kSUpCQ1lZTFBRb0d2WVFhOXVYZjcxbHA2NkpLbEh0OC9Rc1VSKzBYVFh1QUVneHZyQS9Cb0xmcjJRZkhyL0d6bGVtS0tTTVl1bmtIVFN6RWxMNCtzRmFDZ2ZvK0IrN1dqT3puMkxRc25OY0dpRDFVVHViUG9kbkY1cEdBenBnZ3Z1dFdCdXI2SDd0T3VyaVVpNVFGWFNXS010L0hCTjVFYXlYVXIrdzlNY0VwanZHSzR2Zklid1ZkdzhJcGxBV05CWlM1RHZXaE41WG40ZWRvcWQ4b2lGeXgyd2sraXUvMEl1aWw5S3dUVHNrVDRtbHhEdHJ6Um01WGpQVW8ycFhlNkc0OWdqeHZ3K2ZDaE5HaGNmaHdRQzlqYVRMRUc5eG9HRmVXdmlZK1V1U20yUStjb1hkeTZOWWlOT3d5VlBySEdCaDNKb3p1VUNzZVQ1bVhRZkYvamhnL3hPZlhOZDI4Z2pvMGFIM3BMQWxOTkdkdEw1WWk1NXZRZ2JlajQrNmcvOWdzTXFBT0gzSGFTZndFYlhjRHZtZVRodlVwVGU5Nnk0UXpNNzZRbTlZMFo5RnBkUGNtNnZOcHNBdDlzdHhwTyt2WDRFYkUyMG9UQ2NzR1NvbmwrQi9mNldhL1ZjVjUwYVNQeDd0T0RlRUJ4ZzEweHkrZGtvWGdmQWd4RmlEZTE5QU8zME0vckVRTzl5TG1BNGkvQmIrM2wrYm5rUElITjRQclVMKzErRndCMjJ2aG94MWlmMUc4MVhwYnZBMjVaaksrcjJseFIyNGExZDhSUHpFZnV3b1djc0VXaUpNellqK0kzdytWdEtzaEhnSC9BUFpTbnFqVHpmaTh4aDY3dW5VdVBkckEyOE54WXJIL0F6M3RJNGo1K1RPTEFBQUFBRWxGVGtTdVFtQ0MiLCJhdXRoZW50aWNhdG9yR2V0SW5mbyI6eyJ2ZXJzaW9ucyI6WyJVMkZfVjIiLCJGSURPXzJfMCJdLCJleHRlbnNpb25zIjpbImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6ImU4NmFkZGNkNzcxMTQ3ZTViNDJhYzE4MjU3YjBiZjYxIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWV9LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjQtMDEtMDQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDI0LTAxLTA0In0seyJhYWd1aWQiOiI5NTQ0MmIyZS1mMTVlLTRkZWYtYjI3MC1lZmIxMDZmYWNiNGUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6Ijk1NDQyYjJlLWYxNWUtNGRlZi1iMjcwLWVmYjEwNmZhY2I0ZSIsImRlc2NyaXB0aW9uIjoiZVdCTSBlRkEzMTAgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MjU2LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ3BUQ0NBa3FnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpDQnJ6RUxNQWtHQTFVRUJoTUNTMUl4RVRBUEJnTlZCQWdNQ0ZObGIzVnNMVk5wTVJNd0VRWURWUVFIREFwSFlXNW5ibUZ0TFVkMU1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFY01Cb0dBMVVFQXd3VFpWZENUU0JEUVNCRFpYSjBhV1pwWTJGMFpURWRNQnNHQ1NxR1NJYjNEUUVKQVJZT2FXNW1iMEJsTFhkaWJTNWpiMjB3SGhjTk1UZ3dOekF5TURVek1UTTVXaGNOTWpNd056QXhNRFV6TVRNNVdqQ0JyekVMTUFrR0ExVUVCaE1DUzFJeEVUQVBCZ05WQkFnTUNGTmxiM1ZzTFZOcE1STXdFUVlEVlFRSERBcEhZVzVuYm1GdExVZDFNUmN3RlFZRFZRUUtEQTVsVjBKTklFTnZMaXdnVEhSa0xqRWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRWNNQm9HQTFVRUF3d1RaVmRDVFNCRFFTQkRaWEowYVdacFkyRjBaVEVkTUJzR0NTcUdTSWIzRFFFSkFSWU9hVzVtYjBCbExYZGliUzVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRSWZxSGlzaTBvTy9leU9xU2FEcnI5aXRHMkl5bUJrSG5TREdRSUlZbVQrdnFBOEFnTzgxbW9tYzJMZDVQR3BFTjZtdUU1NHdQSFFqdmMveUNpaDh1Mm8xVXdVekFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUIwR0ExVWREZ1FXQkJTM0ovZnhpQXYyMmlyZEJzOThTT0RoRjdrVS9qQUxCZ05WSFE4RUJBTUNBUVl3RVFZSllJWklBWWI0UWdFQkJBUURBZ0FITUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEYzQxTEZLNExKQ0JVMlZWS0l6N1o2c3hQaFVFa2g4bkxTTEs2SVhka1A1d0loQUllS1ZPWmNoYVZPNWFGN2ZiZFhvU3JjeXkxWVllVWVQTG9qY0tJOWZYODQiLCJNSUlDZ2pDQ0FpaWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakNCblRFTE1Ba0dBMVVFQmhNQ1MxSXhEakFNQmdOVkJBZ01CVk5sYjNWc01SQXdEZ1lEVlFRSERBZEhZVzVuYm1GdE1SY3dGUVlEVlFRS0RBNWxWMEpOSUVOdkxpd2dUSFJrTGpFWk1CY0dBMVVFQ3d3UVEyVnlkR2xtYVdOaGRHVWdWVzVwZERFWk1CY0dBMVVFQXd3UVpWZENUU0JEWlhKMGFXWnBZMkYwWlRFZE1Cc0dDU3FHU0liM0RRRUpBUllPYVc1bWIwQmxMWGRpYlM1amIyMHdJQmNOTWpNd056RXhNRE0wTmpFMFdoZ1BNakEzTXpBMk1qZ3dNelEyTVRSYU1JR2RNUXN3Q1FZRFZRUUdFd0pMVWpFT01Bd0dBMVVFQ0F3RlUyVnZkV3d4RURBT0JnTlZCQWNNQjBkaGJtZHVZVzB4RnpBVkJnTlZCQW9NRG1WWFFrMGdRMjh1TENCTWRHUXVNUmt3RndZRFZRUUxEQkJEWlhKMGFXWnBZMkYwWlNCVmJtbDBNUmt3RndZRFZRUUREQkJsVjBKTklFTmxjblJwWm1sallYUmxNUjB3R3dZSktvWklodmNOQVFrQkZnNXBibVp2UUdVdGQySnRMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkFoK29lS3lMU2c3OTdJNnBKb091djJLMGJZaktZR1FlZElNWkFnaGlaUDYrb0R3Q0E3eldhaVp6WXQzazhha1EzcWE0VG5qQThkQ085ei9JS0tIeTdhalZUQlRNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3SFFZRFZSME9CQllFRkxjbjkvR0lDL2JhS3QwR3ozeEk0T0VYdVJUK01Bc0dBMVVkRHdRRUF3SUJCakFSQmdsZ2hrZ0JodmhDQVFFRUJBTUNBQWN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQU5WbkpkZS8vdEJMcThNRERpK1NBZDZVZFlJWlNuZzRQTXFteU5ydlpqNjRBaUFYMHhTekFoRmFDQ3AvdWhwVmdubEYrWEJncndBSXNvdFpHVEI2cmtCMzFBPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBK2dBQUFFeENBWUFBQUR2RFlncUFBQUFBWE5TUjBJQXJzNGM2UUFBQUFSblFVMUJBQUN4and2OFlRVUFBQUFKY0VoWmN3QUFFblFBQUJKMEFkNW1IM2dBQUZpY1NVUkJWSGhlN2QwSGVCWEYyc0R4TjczUUNUVkE2RklGRktrQ1V1eUFFdW1LWWtGVWJJQ0NJaUtDVWdRRTdMMGdkbFFzS0NwU3JJZ2dTQytoSm5SQ0o0SDBiMmZ2ZUQvMGtoQ1NuYzJlay8vdnVYbVlkNDZYa0pOejlzeTdNL05PUUpaRkFBQUFBQUJBZ1FyVWZ3SUFBQUFBZ0FKRWdnNEFBQUFBZ0FlUW9BTUFBQUFBNEFFazZBQUFBQUFBZUFBSk9nQUFBQUFBSGtDQ0RnQUFBQUNBQjVDZ0F3QUFBQURnQVNUb0FBQUFBQUI0QUFrNkFBQUFBQUFlUUlJT0FBQUFBSUFIa0tBREFBQUFBT0FCSk9nQUFBQUFBSGdBQ1RvQUFBQUFBQjVBZ2c0QUFBQUFnQWVRb0FNQUFBQUE0QUVrNkFBQUFBQUFlRUJBbGtXM1BTc3pOVlhTRHlUS3FhMWI1ZFNhZFpLNmU0K2tIejltOTRuMy8vbUFjUUVob1JKY3VwUUVSMFZKV0pWS0V0Nmd2b1JYcnlaQnBVcEpRQ0QzNFFBQUFBQmY0TmtFUFNzalEwNXQzaUtIUHZwRWp2K3dRTkwzN1pPczFEVDlLSUN6Q1l5TWxOQWExYVRFTloybFpKZk9FbHFodlBXT0Q5Q1BBZ0FBQVBBYXp5WG9LakUvTXZjN1NYeHpocHhhc1ZMM0FzaVBnTkFRS2RxeHZaUzlZNEFVYWRKWTl3SUFBQUR3RWs4bDZNZC8rMTMyakh0S1V0YXQxejBBbkZhODY5VlNZZGdRQ2F0U1JmY0FBQUFBOEFKUEpPZ1pKMDdJbm9sVDVQQUhINHRrWnVwZUFLWUVoSWRMaFZFakpLcFhkd2tJRHRhOUFBQUFBQXBTZ1Nmb3A3WnNsUjBEQjBucTF1MjZCNEFyQWdLazJCV1hTcFhKRXlTb2FGSGRDUUFBQUtDZ0ZHaUNmdUxQNVJJL1lKQmtIRG1pZXdDNExieFJRNm4yNWlzU0VoV2xld0FBQUFBVWhBSkwwRThzWFNZN2JybERNcE9TZEErQWdoSmFxNGJVL09oZENTNWRXdmNBQUFBQWNGdUJISkNzbHJYSDMza3Z5VG5nRWFtYnQ4cjJnWU1rZy9ja0FBQUFVR0JjVDlEVGp4NlQ3YmZkSVJtSER1c2VBRjV3OHMrL1pPY2pqMGtXaFJvQkFBQ0FBdUhxRW5kMXhubjhBdy9Kc1MvbTZKNXpGeGdaSVVHbFNrbElqZW9TVktLNDdnVUtPZXR0bkw1dnY2VHRpSmVNSTBjbEt5MU5QM0R1S2s0WUsyWDY5TklSQUFBQUFMZTRtcUFmWGJqSUxncDN6a2VwQlFaSytQa05KS3AvUHluV3VxVUVseWtqQVVGQitrRUFmOHRNVFpYVVhidms2TGZ6NU5ETTl5Vjl6MTc5U080Rmxpd2g1LzN3RFVYakFBQUFBSmU1bHFCbkpDVkwzRlhYU0ZyQ1R0MlRPNkUxcTB2RlVTT2tlTnMyZHFJT0lIY3lUNTZVZ3g5OExQdWZlVjR5angzWHZibFRvbHRYaVprNnlicENCT2dlQUFBQUFLYTVsdkVlbWZQMXVTWG5WbUpRb21lczFKNHpXNHBmMG83a0hEaEhnUkVSVXZiVy9sTExlZytwbzlUT3hiRnZ2NWRUOFFrNkFnQUFBT0FHVjdKZXRleDIvL012NlNnWHJHUThhdEJBaVhscXZBU0doK3RPQUhrUlZxV3lmWVJhNU1VdGRjL1paWjFLa2YzUHZxQWpBQUFBQUc1d0pVRS9zWGlKcE8vYW82T3pDQWlRMGpmM2sraWg5N084Rm5DSXV0RlY3ZFVYejJrbS9jU0NSWkorNUtpT0FBQUFBSmpteWg1MFZibjk2R2RmNkNobktvR28rZkg3RWhnV3Fudnl5ZnJ4c3RMVEpmM0VDY2s0Zmx5eVV2TmUzUnB3aXpxdElMaFlNWHVadWwwUTBhR2JWYWUyNzVETlYxNGpXU2twdWlkbmxaNlpJcVd2NmFJakFBQUFBQ1laVDlCVmNyeXVlUnZKUEh4RTkrUWdPRmlxejNwUGlqWnByRHZ5TG5uZGVqazJmNkVrL2JwWVVyWnNsWXpFZy9vUndIY0V4MVNSaU5xMXBHaUhkbEtzWTNzSnExaFJQNUozKzE1NlZmWlBtcXFqbkJXOXJLTlVmL1ZGSFFFQUFBQXd5WGlDbnJ4bXJXenAybDFIT1N2YThSS3AvdnJMZVo0dHpEeVZJa2UrL1U0U1gzdFRVdFp0MEwyQW53Z01sS0tkMmt1WlcvdExzUmJOOC93K1NUOTZWRFoxdkZJeURoM1dQZGtMS2w1YzZ2N3hzd1NHaGVrZUFBQUFBS1lZMzRPZS9OZEszVHE3MG4xNjVTM3B5TXFTNDR0L2w3ak8zV1RYa09FazUvQlBtWmx5WXQ0QzJYN0RMYkp0NENCSnlXT1Y5ZUFTSmFURXRWMTFsRE4xVkZ2cXpsMDZBZ0FBQUdDUzhRVDk1UHJjSmNzQmtSRlM3SksyT3NvOVZTRis5OFRKc3VPbUFaSzZkWnZ1QmZ5WVN0Ui9XQ2lidTE0bmgrZDhZOGZucWtTWHEzUXJaMWxwYVpMQyt3b0FBQUJ3aGRrRVBTdEwwclp1MTBIT3dodlVsOERRY3lzTXA0cStiYi9qSGpuNDZwdjJYbmVnTU1rOGRseDJEaDRtZTZZK1k3L1h6a1ZFelJvU1dMU29qbktXc2llWEp6QUFBQUFBeUJlakNicmEzcDZSbkt5am5LbXptcytGU3M2MzNUcFFraGI5cEh1QVFpZ2pReEpmZU1WZVJYSXVTWHBBUklRRWw0M1NVYzdTZDVPZ0F3QUFBRzR3TzRPZW1TbVp1VHpPS2FoQ2VkMDZPN1hzTm43WUNEbTViSVh1QVFvM3RZcmt3RnN6ZEhSMjZ1aTJnTkRjRlg3TDJMZGZ0d0FBQUFDWVpId1B1Z243WDN0VFRuejNnNDRBS1BzbVRaT2tGWC9wQ0FBQUFJQ3ZNWHJNbXRvWHZxbExyS1J1ak5NOTJZc2FORkNpaHczVlVmWk9ib3FUTFYydXMyZlJjeTB3ME41dkcxd21TZ0tqU3VsT3dLT3NkMlRHemwyU2NlS0VaSjVJMHAyNUUxcXJodFQrOGxNSmpJalFQV2VXbFpFaGNaMWpKV1hqSnQyVHZaTGR1a3FWYVpOMUJBQUFBTUFVMzByUXJYL3F0dHZ1a0JNTGM3bnYzRDQzdW9PVUhYQ3poTmVySzhIRml1a0hBSS9MekpTMHc0Zmx4TzkveUlIblg3SVNhZXM5bEp1M2FrQ0FsQjh4VE1yZGZxdnVPRE1TZEFBQUFNQjdmR3FKZTlLcTFibE96a05pcWtqMWoyWks5VmRma0tMTm01R2N3N2NFQmtwSVZKU1U2bnlWMUo0eld5bytPVm9Dd3NQMWd6bXdrdmpFbDErVGpLUnptM2tIQUFBQVVQQjhKMEczRW84RHI3NmhnNXlGbjk5QWFzNytTSXBlMUZUM0FMNUxGWFFyYzMwZis0WlRVTWtTdWpkN0dZY095eEYxUGpvQUFBQUFuK0l6Q1hyNmthT1M5TXR2T3NwZWNNWHlVdTMxbHlXa2RHbmRBL2lISW8zT2w4clBUYlZlNUVHNkozdEhQdnRDdHdBQUFBRDRDcDlKMEpOV3JwTE1ZOGQxbEkzQVFLazRkclNFbEN1ck93RC9VcnpOeFZMcWhqNDZ5bDd5bnlzazQvZ0pIUUVBQUFEd0JiNlRvUC8ydTI1bEw3eGVIU25SNFJJZEFmNnA3SUJiSlNBNFdFZlp5TWlRcEpVcmRRQUFBQURBRi9oTWdwNjhicDF1WmE5RWw2dnQvYnFBUHd1clhFa2lXalhYVWZaT3JWNnJXd0FBQUFCOGdVOGs2RmtabVpLMmFiT09zbGZzc2s2NkJmaTNZbTNiNkZiMlV2ZnYxeTBBQUFBQXZzQkhFdlIwTzBrL203QUtGWFFMOEcraDFhdnBWdll5VDNEVUdnQUFBT0JMZkdhSmU2NEU2RDhCZjhkckhRQUFBUEE3L3BXZ0F3QUFBQURnbzBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQSUVFSEFBQUFBTUFEU05BQkFBQUFBUEFBRW5RQUFBQUFBRHlBQkIwQUFBQUFBQThnUVFjQUFBQUF3QU5JMEFFQUFBQUE4QUFTZEFBQUFBQUFQSUFFSFFBQUFBQUFEeUJCQndBQUFBREFBMGpRQVFBQUFBRHdBQkowQUFBQUFBQThnQVFkQUFBQUFBQVBJRUVIQUFBQUFNQURTTkFCQUFBQUFQQUFFblFBQUFBQUFEeUFCQjBBQUFBQUFBOGdRUWNBQUFBQXdBTkkwQUVBQUFBQThBQVNkQUFBQUFBQVBJQUVIUUFBQUFBQUR5QkJCd0FBQUFEQUEwalFBUUFBQUFEd0FCSjBBQUFBQUFBOGdBUWRBQUFBQUFBUElFRUhBQUFBQU1BRFNOQUJBQUFBQVBBQUVuUUFBQUFBQUR5QUJCMEFBQUFBQUE4Z1FRY0FBQUFBd0FOSTBBRUFBQUFBOEFBU2RBQUFBQUFBUElBRUhRQUFBQUFBRHlCQkJ3QUFBQURBQTBqUUFRQUFBQUR3QUJKMEFBQUFBQUE4Z0FRZEFBQUFBQUFQQ01peTZMYmpzdExUWlZPWFdFbmRHS2Q3c2hjMWFLQkVEeHVxbzMvS1RFMlZEYTNhUzhhaFE3cm56QnFzWFM2QmtaRTZNaWMxUGtGT3JkK2dJL2l6MEpnWUNhOVhSMGZlY1dUK0Fra1lNRWhIWjFhaVI2ekVUSjZnbzMvS3lzaVF1TTZ4a3JKeGsrN0pYc2x1WGFYS3RNazZBZ0FBQUdBS0NYb2VISno1dnV4K2JLeU80TStpK3ZlVDZNY2YxWkYza0tBREFBQUEvb2NsN2dBQUFBQUFlQUFKT2dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUJ3UmtXWFRiY1ZucDZiS3BTNnlrYm96VFBkbUxHalJRb29jTjFkRS9aYWFteW9aVzdTWGowQ0hkYzJZTjFpNlh3TWhJSFpsemN2VWFPZjdqenpyeXZ1US9WOGp4UlQvcHlGbmxCOThyRXVTLzkza2lHcDB2eGRxMTBaRjNISm0vUUJJR0ROTFJtWlhvRVNzeGt5Zm82Sit5TWpJa3JuT3NwR3pjcEh1eVY3SmJWNmt5YmJLT0FBQUFBSmhDZ2w0SUpMNDVRL1k4Y2VaRUxiOGF4cTJSZ09CZ0hjRXQvcHlnWjZXbFNWYW1zY3RTNFJNZ0VoZ1NZdjFwTlFBQS8wT05NOFdGajUyQTRDQUpDQXJTVWNGejlmT1d6eUlnMTBqUUN3RVNkUC9qenduNnRxSEQ1TlNLbFRwQ2ZnV1ZLQzYxUG41ZkFrTkRkUThBNEhSeDNmdEkrbG5HbUU0b1Avd0JLWDNWRlRvcVdCbEpTYkxseGxzazQvQVIzV05XWkl0bUVqUCtDUWtJWkhjdGNEWWs2SVVBQ2JyLzhlY0VQYTdmelhKeThSSWRJYjlDYTFTWHV2TyswUkVBNE4vV3RXd242UWNPNk1pYzZFbmpwVXozV0IwVm9NeE0yVDUwbUJ6N3lwM1BodUFLNWFYMjdJOGxwRnc1M1FNZ0o5ekdBZ0EvRmxhcnBtNEJBQ0NTK05FczE1THpnTEF3cVRKMUVzazVjQTVJMEFIQWo0V1dMNjliQUlEQ0xubmRldGt6N2lrZG1WZHV5TDFTckVWekhRSElEUkowQVBCallZMGE2aFlBb0RETE9INWM0Z2MvS0ZrblQrb2VzNHBkY1ptVXUrMFdIUUhJTFJKMEFQQmo0VFZyNkJZQW9OREt5cExkazU2VzFDMWJkWWRaSVpXaXBjcjRzUlNGQS9LQWR3MEErS3VnSUFtclVFRUhBSURDNnZBMzM4cmhEejdXa1ZtQmtSRVM4OEl6RWx5eXBPNEJjQzVJMEFIQVR3V1ZLaVdCeFlycUNBQlFHS1hFeDh1dWthUHRXWFRqZ29La3dxaEhwTWo1Yks4Qzhvb0VIUUQ4VkZEUkloSVlGcVlqQURBck16TlRUcDQ4S1ljT0haS3QyN2JKMHFWTEpUVTFWVCtLZ3BCNUtrVjJESDVRTW84ZjF6MW1xYU5aeS9Uc3JpTUFlVUdDRGdCK0txUnlKUWtJQ3RJUkFPU05TcnpUMHRJa09UbFpFaE1UWmZQbXpiSjQ4V0o1Ny8zM1pkejQ4VEo0eUJDNU5qWldhdGV0SytmVnF5ZDFySzk2RFJwSTY3WnQ1YmhMaVNIT1FPMDdmMnF5bkZxNVduZVlGZDZvb1ZRZU8xb2tJRUQzQU1nTEVuUUE4Rk9oVldOMEN3QnlwaEx3QXdjT3lOcTFhMlgyN05ueTRrc3Z5V09qUjB1L20yNlNpOXUxazZiTm10bEpkNldZR0tuWHNLRzA2OUJCYnI3MVZubDg3Rmg1d2ZwdnY1azdWK0xqNDJYdjNyMXk1T2hSTzZsSHdUcTY2Q2M1L1A1SE9qSXJzR2hSaVprK1JRTER3M1VQZ0x3aVFRY0FQeFZLZ1RnQU9UaDI3SmhjZXZubFVyZCtmWWtzVmt5aXExU1JKazJiU3ErK2ZlWCtJVU5rd2xOUHlVY2ZmeXpMbGkyVDlSczJ5TzQ5ZTBpOGZVVHE3ajJ5Yy9nSXlVcFAxejBHQlFSSTlKT1BTM2pWcXJvRFFINlFvQU9BbndxL29KRnVBY0QvVXZ2REYvLyt1MnpaNnM3UlczQkhwdlY3algvb0VjazRkRmozR0dRbDUxRURicGJTWFR2ckRnRDVSWUlPQUg0cXZFb1YzUUlBRkJiN1gzMWRrbi83WFVkbVJWN1VWQ29PSGF3akFFNGdRUWNBUHhRUUVTRWhaY3JxQ0FCUUdCeGZzbFQyUC9lU2pzd0tybGhCcWo0M1ZRSkRRM1VQQUNlUW9BT0FId291WDA0Q1FvSjFCQUR3ZCtsSGprakNzSWVzaHZsOTV3R2hJVko1OGdRSktjdU5ZTUJwSk9nQTRJZENTcGFVZ0VBdThRQlFHS2hpY1BIREg1SDBYWHQwajFsbDdycERpcmRxcVNNQVRtTDBCZ0IrS0tSR05jNmlCWUJDNHNEYjc4aUorUXQxWkZiUjl1Mms0cjJEZEFUQWFTVG9BRHdscEZ4WkNhMVMyYld2a0lvVjNVbGtyZThSVWluNmpQOEdFMThSOWV2cmJ3d0E4R2RKSzFmSnZxblA2TWlzRU92ekpXYktSRzRBQXdZRlpGbDAyM0ZxdWMybUxyR1N1akZPOTJRdmF0QkFpUjQyVkVmL3BJNkwyTkNxdldRY09xUjd6cXpCMnVVU0dCbXBJL3d0OGMwWnN1ZUpDVHB5VnNPNE5SSVF6RDVYdHgyWnYwQVNCdVI4OTdwRWoxaUptWHptMzN0V1JvYkVkWTZWbEkyYmRFLzJTbmJyS2xXbVRkYVIvemtWSHk5eGwzVTJmbFpzWUpFaVVtZkJkeEpTSmtyM0FFREJTa3hNbEtvMWF0akhyWm15ZDljdWlZcnk5blZ2WGN0MmtuN2dnSTdNaVo0MFhzcDBqOVdSTTlLUEhaTzRiajBsYlVlODdqRW5NQ0pDcW4vd2poUTV2Nkh1QVdBQ00rZ0FBQUNBRDlyMXhIaFhrbk1KREpUeWp6NUVjZzY0Z0FRZEFBQUE4REVIUDUwdFJ6LzdRa2RtbGVqYVdjcjA2cWtqQUNhUm9BTUFBQUErNUdUY1p0a3pacHlPekFxcmM1NVVHVGVHazBFQWwvQk9nMDlSOVFpMjlydFoxbDNRd3ZoWDNMVTlKT05Fa3Y3T0FBQUFCUy9qeEFtSnYvOEJ5VXd5UDBZSkxGWk1ZcDZmWnU4L0IrQU9FblQ0anF3czJUZjllVW42OVhmSk9ITFU2RmRtOGttcE9IcWtCQlV0b3I4NUFLQ3d5TXpNbFBUMDlETitaV1JrV0I5SHh1cnJBam5Lc2w2YnV5ZE15bFdSMTN3TENwVG9NYU1rb2tZTjNWRjRxZmQ4VHRjRjlSamdGS3E0RndMK1VzWDkyTSsveUk1Yjd4VHJTcWg3ekNsNy85MVNZZkM5T3ZJZXFyZzdoeXJ1dmk4bEpVWFdybDByZjYxY0tmdjM3NWNEaVluNkVaR3cwRkFwV2JLa2xDMWJWbXJYcmkzMTZ0YjFmRVZwdUNjcEtVbTJidDBxcTFhdmxqMTc5c2kyN2R0bDQ4YU5jdXJVS1RsNTh1UVpCOTBSRVJFU0VoSWlwVXFWa2diMTYwdWxTcFdrYXRXcWRydHk1Y29TN0VNbm0xREYvVDk4cVlyN2tlKytsL2g3aHFpN1NMckhuTkw5KzBubFVZOFV1aVBWMHRMU0pONGFHeXhmc1VJU0VoSWtMaTVPTmxsZjZycVFuSnlzLzZ2L3A5N3pZV0ZoVXJ4NGNXbllvSUY5SGFoV3JabzBidFRJdmo3NDBqVUIza0NDWGdqNFE0S2V1bnVQYkxaZVN4bUhqK2dlY3lKYnQ1UWFNOS8wOUY0ckVuVG5rS0Q3cHFOSGo4cmNiNytWRHo3OFVINzg2U2M3MGNxdE91ZWRKNDgvOXBqMDZORkQ5NkF3VU1uMnRtM2JaUEh2djh1aUgzK1V2Lzc2UzFhdVdxVWZkVVo0ZUxnMGI5Wk1McmpnQW1uVnNxVzBiTkhDSHFCN0ZRbjZmL2hLZ3A2U3NGUGlydWt1bWNlTzZSNXpJaTVzSWpWbnZpMkI0V0c2eDMrcDE3KzZ3ZnZMTDcvSS9BVUw1UGNsUytTWVE4OXhwSldYdEczVFJ0cGZjb20wc0s0SHpTNjZ5TDVPQURraFFTOEVmRDFCejB4SmthM1g5NWVUeS8vU1BlWUVsUzBqdGIrZUxTRmx5K29lYnlKQmR3NEpldTc4YmlVMTY5YXYxNUV6THJJR0tvM09QMTlIdVhQQUdrUy8vT3FyTXVYcHA4ODRrNUZic3o3NlNMcGRlNjJPenQyc1R6NlI0OGVQNjhoNVYxNXhoVVJIUit2SUdaOTk5cGtjT1hwVVI4Njd4QnFBMXZUWVVsaTFISDNUcGszeTJlelo4c21ubjhyNkRSdnNQcmNFQlFYWk40UjY5ZXdwVjExNXBUUm8wTUNlYVROcDFhcFZzdXpQUDNXVXN4TW5Uc2hESTBiWVMzUk5lWHJ5WkNsYXRLaU84cTU4K2ZMUytlcXJkZVFzWDBqUXM5TFNaSE8vbStYa3N1VzZ4NXpnY21XbDF1eFpFbHFodk83eFArbzFyMjdRZldoOUZyejczbnR5OE9CQjQxdFhBZ0lDcEZpeFl0S2plM2ZwZC8zMTByeDVjK1BYZ3pOUk55cy8vK0lMT1hMRTdLUlg2ZEtsOC9VNW0xZnE1M3RuNXN3enJvQnlpcnJKMHJ0WEwvc2Fid0lKZWlIZzB3bTY5ZkxjODh6emt2anNDMVpiOXhrU1lGMGtxNzc5bWhScjJWejNlQmNKdW5OSTBIUG4vaUZENU1XWFh0S1JNKzY3NXg1NWVzb1VIZVZNRGFabXpab2xReDk4VUJLdGdWUitxT1dHZi83eGg5U3ZYMS8zbkJ2MXNkbW9TUlBac0hHajduSGV0OTk4STUwNmR0U1JNNW8yYTJZdjVUYmxuYmZmbHI1OSt1aW9ZS2tWRmQ5Ly83MU1zbDVmYWhDdWxxd1dORFdRVTB0ZkI5eDZxLzA4eGNURTJBTjJwMDJkTnMxT3V2Mk5TbW8rc0JJcEV6eWZvRnZYbkYwVEpzdkJOOTdTSGVhb01WM1YxMStTNG0zYjZCNy9vbTdzZmo5dm5qdzFhWktzK09zdlYyL1luVTY5OTZ0WHF5YUQ3Ny9mVHZSVU11dW0yd2NPbExmZmVVZEhacWliRWJzVEVseGZNYUMyTGRVLy8zeWp2OXNPN2R2TGQzUG5Hcm1HS3hTSmc2Y2QrMjJ4SEh6aEZlUEp1ZlVPa3pLREJ2cEVjZzc0aTRTZE8zVXJaNGNQSDVicmI3aEJicjd0dG53bjU0cWF6Vk9KRXZ5UFdxcjYzdnZ2MnpjamV2WHRhODhrZXlFNVY5UmdjY2VPSFRKcTlHajdCcysxc2JHeWRObXlBa3NRZkUzclZxMTBxL0JSTlhnT3pqQ2JUUDJ0ekYyMysyVnlybTd5ZnZubGw5S2thVlBwMmJ1M2ZXMG95UGVldXRHN2RkczJ1Vy93WUtuWHNLRThQWFZxdmxhRm5hdGV2WHJwbGpscWxabXFEK08ySlV1V0dQL2Q5ckZlUTZhU2M0VUVIWjZWZGlCUmRqM3dzUEdaVFNXeVdWTXBmOWRBSFFGd3d4cnJnL3RzaTdqVW51RzI3ZHZMN0MrK2NHeTVXcGt5WmV3NysvQWY2blgwODg4L1M1dDI3ZVRtVzIrVkxWdTM2a2U4S2Zua1NidUdndnIzWG5IVlZmWVdFdVNzUmlHdEpKNjZiNzhrREgvRXlqRE5KNU5GMmw0c0ZlNjlXMGYrUTIzUHVycExGK2x1SmFYcU04VnJEaDA2SkE4LzhvaDlZL0dMTDc4ODYrZWlFeTZ4cmoycTBLVnBjNy83VHJmY00zL2hRdDB5UTYwSXVDNDJmOFVlejRZRUhaNms5bG9sUFBpUXBGc2ZUS2FwdlZZeHowK1hnSkFRM1FQQURjZU9IclVyWldkSFZjN3RlT21sZGxWdEoxMTR3UVZHNzN6RFhXb2Y5ZEFISHBETHJyelNYckxxUzlSTkoxWGtVTjJFNnQ2enAyemM1TUxSV1Q1STdkTlZWZklMRzdYRk0rSGhSeVRqd1ArZlRHRktjTVVLRWpONW9nUVkybE5iRU5TS21zbFBQeTB0V3JXU2hZc1c2Vjd2MnJ4bGl6MjczKyttbSt4Nkt5YUZob1pLZDhOSnBySjQ4V0xkY29lNnBxb2lvQ2FwbXh2cWRCaVRTTkRoUFZsWnN1K2xWeVhwcDE5MWh6a3FLYTgwYVp5RWxDMmpld0M0NWRqeDQvYnk5VFBadlh1M1hHNGxYRHQzN2RJOXppbU1BMzEvcFdiRDJuZnNLTSsvK0tMUEx4WC84cXV2NUtMbXpXWHNFMC9ZTngzdy8wS0NnNlZDaFFvNktqejJ2L0cyTzJPaGlBaXArdngwdnhvTHFXTVR1MTV6alR3eWNxUjlQSnF2VUxQbkg4K2FaYyttLzdGMHFlNDE0N3JycmpOK3Mxb3RjVGQ1U3NTL3FhTXkxVllpazI3czEwKzN6Q0ZCaCtjYy8zMkpKRDcvc283TWlocHdpeFMvcEoyT0FMaEp6WjZyczJiL1RSWDQ2dFduajVIa1hGSFZ4dUg3bGxxRFY3VkUzT21qMGdxU1NpU2VHRGRPV2w1OHNheFlzVUwzb203ZHVvWHVhS3JqZnl5VkE5T2YwNUZCZ1lGU1lmaFFLZEtrc2U3d2ZTdFhyclN2RFF0OFlOWThPM3YyN3JWdlVzOTg5MTFqUzk1VlhRZDFESnhKdTNidk5wNHduMjdldkhtNlpVWkVSSVI5eW9wcEpPandsTFQ5K3lYaC9nZnRKZTZtUlRTL1NDb012VTlIQUFxQ3V0dDlPclU4YmNnREQ4aVNQLzdRUGM0S0N3MHR0SHRaL1lrNnIvaUtxNitXL1M1VTNpNElhbHRIMzM3OVhKMTU4ckthTld2cVZ1R1FmdXk0N0J6K2lDczFlSXBmZVptVTZYZTlqbnlmV2xMZHZsTW5pVTlJMEQyK1M5MnNIbmpublRKdCtuUWpTWHFSSWtXazJ6WFg2TWljYjEzYWg2NmVvM2svL0tBak05VHBLaVZLbE5DUk9TVG84QXoxUWFRS29iaXgxeW9vcXJURVRKMWsvQXgzQURuNzdWLzcwOVR4TjJyR3dKU3laY3RLS2NON3gyRFcrdlhyN1JVV0pzK2g5NExKVHoxbDd4T0ZTTE9MTHRJdC82ZU9RVTBZT1VyU0VuSjN5a1YraE5hdUtWVW1qcE9BUVA5SUIzNzg4VWU1cWtzWHY5b2lvcXJQanhnNVVwNTU5bG5kNHl4VmpkeTB4UzRWd1R5VmtpSi9HTHE1LzdjQnQ5Mm1XMmFSb01NejlyLytwaVQ5K0l1T3pMSDNuVThlTDZHVm9uVVBnSUp5K2hMM28wZVAya2ZPcUFHSktlWExsN2NMVHNFM3FXckhzVDE2eUlGRTh6ZHlDOUtkQXdkS1Z5dlJ3SDgwYmRwVXQveGY0cnZ2eS9GdnpNODRCaGFKbEpqcFV5U29TQkhkNDl2VXFxdHUzYnZiczg3K1JxMHNHL2JRUS9MZWUrL3BIdWUwYk5sU2loY3ZyaU16MUxGbktWYnliTnJtdURqWnUyK2ZqcHluenFwdjE3YXRqc3dpUVljbm5QaGpxZXlmUEYxSFpwVWVjTE9VNk5CZVJ3QUtrcG9OL2RzYmI3NXAvQWljcGhkZVNBVjNINldXTDZxQ1QxdTJiTkU5L2trVk1ad3dmcnlPb1BhZVY2dGFWVWYrTFhuTld0azdlYXFPREFvTWtJcGpSa2xrM2JxNnc3ZHQzNzVkdXZmbzRmZkZGZSs4KzI3SHQzK3BhdVJYWDNXVmpzell0MysvN0xlK1RQdG03bHpkTWtNdGIzZnJpRllTZEJTNDlFT0hKR0hJY0hXTFVQZVlFOW1pbVZRY3dyNXp3Q3ZVSG1LMVZEa3hNVkhHakIycmU4MVJ4YWJnbXhZdFdpUnZ6WmloSS8razlvUysvZWFiVXJSb1VkMkRraVZLU0ZSVWxJNzhWL3F4WTdKajhJT1NkZEp3eGZHQUFDbmQ3M3FKNm5hdDd2QnRhc2E4ZDkrK2RoTG83MVFSeVJ2NjliTlhFam5KZEZWeU5Ydis3KzFzVGxPckRFenVkVmMzOXUrNC9YWWRtVWVDamdKbG4zYytiSVNrNzk2amU4d0pLbFZLcWt5ZnpIbm5nSWVvNWV6Nzl1MlQ5OTUvWDVKek9CUGRLZXI4VXZnZTlUb1pOWHEwUFFqelYyb0FPT0toaDZSSmt5YTZCMHI1Q2hYc3lzbCtMU3RMZGowNVFkSzIvYk5vcGduaDlldEo5RU1QMm9tNlB4ajc1Sk95M01VVEQ0S0NndXhpbzJwbGgvcFNXNlpDckhHbFd5dXpkc1RIeTUyREJqbDZMV3plckptVUtXUDJpTDF2di8xV3Q4dzRldXlZckR0dFJaN1RvaXRXbEdiVzgrUVdFblFVcVAxdnpaQVRDMzdVa1VIV2hUTjYvQmdKTFlUbnFBSmVwcXBVcjkrd1FWNTYyZnpSaW1vZ1ZhMWFOUjNCbDZpcTdhWXErM3VGT3ZKbzZKQWhPc0xmR2pkcXBGdis2OUNYYytUb1oxL295SnlnTWxGUzlhWG5KTkJQanF6NytlZWZaZXEwYVRveVJ4VnJ2T0x5eStXRjU1NlRYMy82U2JadDJTSjdkKzJ5di9iczNDa2IxcTZWYitiTXNXK3cxYTlYVC8rL3pQbksrbDVPemhhcnF1UWREQjgvK3JOMURjL0l5TkNSODlUSkYwNnZMRGhkKy9idGpSOUpkem9TZEJTWUUzOHNrd05UbnRHUlFWWnlYdnEyL2xMeXlzdDFCd0F2ZWZPdHQyVEwxcTA2TXFkcTFhcXVmc0RDR1dyditiUFBQNjhqODZwVXFTSTMzM1NUUEQxNXNzeXpCc0ViMTYyVHJYRnhzbS8zYnRtMGZyMnNXNzFhNW4vL3ZUejN6RE15Y3NRSXVhWnJWNmxYdDY0RTUrTlVrS2pTcGVXZEdUUHNtVGo4VSszYXRYWExQNTNhdmtOMmp4NXJ6NktiRkJBU0xKVW5QQ0ZoZmxJZ1YrMDNIekJ3b0k3TVVMUGl2WHIydE4vemM3NzhVZ2JlZnJ0ZHNGQ2RCcUsybzZndnRTYzVKaVpHTHUzVVNjYU9HU1BMbHkyVDJaOStLdWMzYktqL0Z1ZXBGVVgzRHg3czJKNTc5WFBlY0wzWm8vWlVZYys5ZS9mcXlIbmZXZGRrazl4YzNxNlFvS05BcENVZWxJVDdIM0RudlBNTG0wakZCNW1WQUx4cXp0ZGY2NVpabGFLajg1VkVvV0FjUEhoUWZ2cjVaeDJaVTcxNmRYbHY1a3c3SVgvdDFWZmx2bnZ2bGZhWFhHS2ZtNitTZGxYQlYvMDNLbUZzMTY2ZDNIbkhIZkw0Nk5IeTZheFpzdUxQUDJWWGZMeDgvT0dIOWtDM1N1WEsrbS9OblNtVEprbU05VDN3di94NVcwcEdjckxFVzJPaHpPUG1pNXRGM1hhTGxPallRVWUrYjlLVUtiTFZZRkhSNGxiaVBYUEdESG4zblhmc203dTVwWmJBZCtuY1dSYi8rcXVkMEp1eWZjY09lZjZGRjNTVWY1ZFkxenBWTU02VVpPdTEvcWQxblRSQjNjVDk0Z3R6SzFEVTcvOGlsNDk2SkVHSDY3SXlNMlhYNkxHU3Z0ZmNVUWgvVTh1NVlwNmRLb0VjcXdRVWVtNS93TUlacTFldnRvL2dNK25pMXEzbGo4V0w3ZG15dk14aXEwRzVTdUJqdTNXemk3eXRXN05HZmxxNFVIcjI2SEhXSTR4dTZOdFhicmpoQmgzbG43cHhzTk1hdk9mbWE5V0tGY2JQV2wvMTExOW4vTjY1L1ZMN1kvMlJHZ3Z0Zm1xS25GcXpWdmVZVTZSTmE2azQ5SDRkK1Q2MUQ5dko1UFRmMUVxckQ5OS9YM3IzNm1YUEx1ZUYybEwxN1BUcGN2Kzk5K2I1N3ppYnFkYmY3OVMxVWEwR3VMUmpSeDJaTVgvQkF0MXlscW9RYi9KMGo4c3Z2ZFQxMVUwazZIQmQ0dHN6WFRualU0S0RKSHJDRXhJYVhWRjNBQ2pNYXRlcXBWdndKYVpuejFWaS9jRjc3ems2ZTZTS1I3VnExVXJlZi9kZGUzbnN4UEhqN1JVYy94Nm9xNW4ycDU5KzJ0RUJ2RW91MUhuL3VmbFNTM1ZOSzJkOWp6Tjk3OXgrcVpzZi91am9Ed3ZrOEFjZjY4aWM0SExsSkdieVJBbndvK2R4aXZXZVVhZC9tREo2MUNpNTdMTExkSlIzNnJVN2Z0dzRZNnRBRGg4K0xLKys5cHFPOGtkZGc5UU5TcE4rK2ZWWDNYTFdYeXRYR2kweWE3cksvWm1Rb01OVlNTdFh5YjRwNWd0NktLWDY5cGFTbmZ4bk9SZUEvRkd6cFBBOUppdnpLcGRiQS9HS0ZjM2R5RlZKNWdORGg5cXo2bXJmdXRxdnFxaEswRysrL3JxOS94eUZTOHF1WGJKenhDZ1JnMFd6bElDd01JbDVmcXFFbEROL0k4WXRPM2Z1bExjTkhyZllvbmx6ZTN1TFU5UUtsUmVmZjE0aURaMUU4SnAxRFZGNzBwMmdia29VTVZpblpjM2F0ZlpOQmFjdE1EUXpyNml0UjgydDE0VGJTTkRobXZSRGh5WGgzcUhtei9pMGhEZW9KOUdQUHF4dUNlb2VBSVdaV200WWN3NzdDT0VkYTlldDB5MHpxcnRVMlYvTmJOOHhjS0M5ckh6VXlKRXllUEJnZTk4bkNwZE1mYnhzNXBFanVzZWN3S0pGSk16UFRxNlkrZTY3OW5uZ3Bvd1pQZHJ4V2lXcWJzV3R0OXlpSTJkdDI3NWRGaTVjcUtQOEtWcTBxSFRwMGtWSHpsTkh3NmxxN2s1Uys4OU5Gb2pyMnJWcmdhemlJVUdISzdMUzB5WGhvVWNrTFdHbjdqRkhmU0JWZVg2YUJCcmVWd2VnWUtnallhNis4a29aLytTVDlwRTNDZFlBNWVqaHczTE0ranA2NkpCczM3SkZmck1HQVdyLzMxMTMzR0dmSzkzbTRvdnRHVXY0bnNURVJOMHlJODJGWXFXblUzczlIeHMxU3A0WU04YlkzbFI0MS82WFg1UGtKVXQxWkZiR3dVT3k4L0VuN2YzdS91RGt5WlB5bk1HOTU2MWF0cFNPaHZaaDMzUDMzY2IyTWIvbDRJb0NWVGZEcENWTGx1aVdNL2JzMlNNYk4yM1NrYk9DQWdQbCtyNTlkZVF1RW5TNEl2SERqK1hFL0VVNk1pY2dPRWdxVFo0ZzRaeDFEUGlkcUtnb2VmeXh4K3dxMjE5OC9ya01lL0JCZStsWmhRb1Y3T1dERWRhWG1xV3NWS21TTkx2b0lybnJ6anZsMldlZXNZdC9mVEY3TnNrUXppaHU4Mlo3RnNadHZCNExwK0F5VWJybGp1Tnp2NU5EbjMrcEk5LzJ3L3o1Y3VEQUFSMDU3NWFiYnpiMnZxeG1qVXNiblgrK2pweWw2blFrSlNYcEtIL2F0VzFyZjVhYW92NnRUbDV2ZjdjU2ZxZVcrUDliNWNxVnBlbUZGK3JJWFNUb01DNTV6VnJaTjI2U1dvZWllOHdwcWZhZFg1SC93aDRBdkVNTmw5U3hOU3VXTFpPUmp6eGlKK3JuUWcyNDFCSjMrQ2JUaWV5Q2hRdGxtOEhqbW9EVFJmWHNMcEhObXVySUJkYllhOCtURXlUTllHTHJsbG16WnVtVzg5UUtxNjRHbDNlclpkTFh4Y2JxeUZuNzl1MlRwVXVkV1pWUnFsUXB1MnE1S1dvZmVtcHFxbzd5YjlFaWM1Ti8zYnQzTDdBaWxTVG9NQ3JqeEFsSkdEcGNzZ3p1Ri9wYldQMjZFdjNJY0RXYTB6MEFmSjM2Y0x6Ly92dGwxa2NmR1Mza0JlOHlmY3lXcWdaOWRkZXVrcENRb0hzQWN3S0NnNlhTRTQ5TGdJdkhObVVlUFNZN1I0MXhaYUxFbEpTVUZKbnp6VGM2Y2w0ejZ6cFRwa3daSFpseG1jSEU5K05QUHRHdC9PdlZxNWR1T2UrRWxSY3NYNzVjUi9tbmJyQ2FvRzdZOUwvcEpoMjVqd1FkeG1SbFpNak9rYU1sTmM3YzJZUi9DeXhXVkdKZW1DNkI0ZUc2QjRBL0dIVG5uVEpwNGtUSGkvYkFkMVJ6b2JpZk9rTzNXY3VXOHNHSEh6bzZ1d09jU1VUdFdsTDJ2cnQxNUk3ajgrYkxRUjllNnY3cmI3OFpQVnF0aytFendKVzZkZXZxbHZOVThUVlZoTTBKNmxnNFZTdkRGTFZWd1FtN2R1ODJ0dis4WnExYWNsN3QyanB5SHdrNnpNaktrc1QzUDVSalg1bTcyL2xmZ1FGU2NleGo3RHNIL0V6bnE2NlN5Wk1tR1YvaURHOXIxS2lSYnBsMThPQkI2WC9MTGRLMGVYT1o5Y2tuY3ZUb1VmMEk0THh5dC9hWHNMcDFkT1NPdmVNbVN1cWV2VHJ5TFY5Ly9iVnVPVTk5eG5SbzMxNUg1b1NIaDh2NURSdnF5Rm03cldUMTBLRkRPc29mZFRSa0c0UEhrcXJ6MEozWWh6NTM3bHpkY2w3MzJOZ0NuUmdnUVljUnllczN5TDZKVTl6WmQ5Nnp1NVMrdHF1T0FQaUQwcVZMeXlzdnYxeGcrNy9nSGVwY1lyZHUwcWhCNDRZTkcrVDZmdjJrYm9NR2N1Lzk5OHV5WmN2czViV0FrOVNLdjhxVHhrdUFpNmRMWkJ3K0lnbVBqTEpYT1BvU1ZRVHN4NTkrMHBIejFQRmk2aWcwMDlSMXJHS0ZDanB5MXJGangreUNsMDdwMzcrL2JqbHYwNlpOanF4VU1yYThQU3hNYnI3NVpoMFZEQkowT0M3aitIRkp1R2V3WkNXZjFEM21oTmFxSVpWR2oyVGZPZUJIMUNEbXliRmo3YnY0UUkwYTFuVStPbHBIN2xISHU3Mzh5aXZTcWswYmFkU2tpVHd3YkpoZGlNbnRZOW5ndjRyVXJ5ZWwrL2ZUa1R1U2Z2bE5EczMrUWtlK1FTMXRYNzkrdlk2Y3AwNy9LRm15cEk3TUttSHcrNnhaczBhMzhxLzlKWmRJOGVMRmRlU3NuYnQyeWZidDIzV1VOK3FtNmRKbHkzVGtyQWIxNnhmSVo4N3BTTkRockt3czJmWDRrNUs2YllmdU1FZnRPNi82OHZNU2FQQTRDQUR1VS92MGJ1em43cUFWM3FVR3o3SGR1dW1vWUd6ZHRrMmVmZTQ1YWQyMnJkU29WVXY2M1hTVGZEeHJsbDA5R2Nnek5hTTYrRjRKcVJxak8xeVFtV2xYZFUvWmJuNmM1aFNWektVYXZER205aHFIdXJTU29WelpzcnJsdk44V0w5YXQvRk9ucGJSczBVSkh6cHY3N2JlNmxUZnhDUW41VHZLejArM2Fhd3Q4OVI0Sk9oeDFjTmFuY25TMkMwVklyRGRPeGRFakpieG1EZDBCd0IrbzJmT0hodyszOStvQmY3dm43cnM5YzFUZVhpc3AvK2pqaitXR0cyK1VLdFdxU1l0V3JXVE0yTEd5Nk1jZmpSYXhnbit5bDdwUGVNTFZsWUNaeDA5SXdxT2pmV2FwdXlxQVpsTFZHUGR1a0pRclYwNjNuTGRueng3ZHlyL0F3RUM1eWVDTjh2eHVXZmpoaHg5MHkxbWhJU0ZHbC9mbkZnazZISE55NHliWk0vcEpWL2FkbDRpOVJrcGZWN0F6S2dDY1Y3bFNKZnZ1TlhDNjZ0V3JTNC91M1hYa0hXclArdklWSytUSjhlUGw4aXV2bEVyV1FMOVhuejd5c1pYQXE4R3lFNFdRNFArS3RXZ3VwYTd2clNOM0pDOWVJZ2RtdnFjamIxT25MSmhVcW5ScDNmSnRjWEZ4dXVXTUs2NjR3dGpLZ3BVclYrYTV0b2U2cm41ajZNaTlwazJiR3FzVGNDNUkwT0dJaktRa2liLzdmbmZPTzY5N25sUitZalQ3emdFLzFLZDNiM3RKTTNBNnRiSml6T2pSVXF4WU1kM2pQV3JRZVBMa1NabjkrZWR5dzAwM1NmMkdEZVdLcTY2U3p6NzdqSmwxbkZXRndmZEtrT0Z6dVA5dC85Um41SlFQTEhWWE44Rk1lbnZHREtsZXE1WXJYMDlQbTZhL3EvTU9Iam9rcHh3Y2g1Y29VVUxhdG1takkyZXBsVWpxbUxTOFVOZlRQdzI5SnE2OTVocjc4NmFna2FBajM3SXlNLyt6NzN6TE50MWpUa0JFaEZSNTVtbk9Pd2Y4a0ZwYU51QzIyM1FFL0ZQVnFsWGxpVEZqUERGNHlvMFRTVW15Y05FaTZYMzk5Vkt2UVFPN3lOeU9IVHVZVmNjWmhaUXVMWldlZkZ5dExkWTk1bVVtSmN2T2gwZEtWbnE2N3ZFZVZaVFJ5YVhiWjZJU3ZwMDdkN3J5cGFxdG02TE9RVmMzQ1oyaXJyVTllL1RRa2JQVTcxVVYzY3lMelpzM3k0RURCM1RrSFBYejNtQmRyNzJBQkIzNWR2aUxyK1RvcDUvcnlDRHJqVlB4c1JFU2NaNzVvekFBdUs5Ky9mcDJFZ1prNTQ2QkErWHFxNjdTa2UvWXQzKy9YV1N1VnAwNjB2ZUdHMlRGWDMvcFI0RC9WNkpqZXluV3FZT08zSkc4OUU4NThQNkhPdklldFF6NkZNY2M1azVXbHVPblRKaWNVZjVxemh6ZE9qZnpETzAvdjdoMWE2bmdnZVh0Q2drNjhrWHRPOTg5WXBSOVVUQ3RlTGV1RXRXN3A0NEErSnRPblRweDdqbHlGQndjTERQZWVrc3VhTkpFOS9pZVR6Lzd6QzRzcHhKMWRSNHc4TGNBNi9wWGVleG9DU3JsenBGZmY5cy9hYXFjM09Ucy9tV25xUE95ODdwWHViREp5TXgwZklhK1RKa3ljdmxsbCtuSVdVdisrRU15OGxDbzhMdnZ2OWN0Wi9YdDAwZTNDaDRKT3ZJbC90NGhrcFdTcWlOelF1dlV0ajYwSHJObjBRSDRwK3M5OU9FSTcxTDdJci8rNml0cDByaXg3dkU5YXBuN0o1OStLazJiTjdjcndDY25KK3RIVU5pRmxDc3JGUjU5V0VmdXlEeDVVaEllZkZneXJXVFlhMVRDZWZUb1VSMmhJUFRwMVV1M25MVnY3MTU3MmYrNU9IandvUHk1ZkxtT25CTVJFZUdwQXJVazZNaVhOSmZPTzQ5NWRxb0VGUzJxZXdENG0wclIwVkt2WGowZEFUa3JXN2FzelB2dU83bjgwa3QxajI5U0JaMVVCZmlMMjdhMTkxVUNTdFExMTBqUkR1MTA1STVUYTlmSi9sZGYxNUYzcUp0WjFHMG9XQjA3ZHBTUWtCQWRPZWVrZGYwNzErMCthOWF1ZFhTZi9kL2FYSHl4MFNQd3poVUpPanl2L01NUHN1OGM4SE5ObWpReE1nQ0EveXBac3FSODl1bW5NdVQrKyswemUzMlpHblMydmVRU21mdnR0N29IaFZwZ2dFU1BHaWtCTHAvOWYrREZWeVhaU3RTOUpOMUh6bXIzWjlIUjBYSnhxMVk2Y3RiWFgzK3RXN216YU5FaUl6ZHNialI0NW50ZWtLREQ4OUpVOVU3dW5nSityUnJGNFpBSFlWWUNNK21wcDJUV1J4OUpsY3FWZGE5dlNqeDRVSHIwNmlYdnZmKys3a0ZoRmw0MVJzb1BHK0xxMXI2c2xCVFpPZkl4eVhLNDBGaCtzUDNERy9yMjdhdGJ6anJYNWVyejU4L1hMZWVvYlZPbTl0bm5GUWs2UE8vZ3EyL0tzWjkvMFJFQUFQOTBUZGV1c3VxdnYrelpkRFhZOGxXcUlOYUFnUU5sMWllZjZCNFVabVZ1NkN2aERkemQrbk5xOVZyWis4SkxPaXA0eGRqZW1HdHFKVkZrWktTT25OV2hmWHY3aHFqVDFPcWgvZnYzNnlobmlZbUpzdlRQUDNYa0hIWFdlMVJVbEk2OGdRUWQrUkxab3BsdW1aT1ZtaVk3SHh3aHFidk5ub01KQVBCZFJhMkJ2SnBOLzhzYXdQWHUxY3ZZUU5XMDlQUjB1ZjJPTzJUNWloVzZCNFZWWUdpb1ZKazBRUUxDM1YzcW52ajYyNUswYXJXT0NwYXBJNzc4a1hxbTFFa1hKcWdqVUJzMmFLQWo1NmpsNnI4dFhxeWpuQzMrL1hmNyt1aTAvamZkcEZ2ZVFZS09mS2t5OVNrSkttUCtybFBHZ1VTSkgveUFKeXVNQWdDOG8zTGx5akp6eGd4WnVYeTUzSHZQUFJKVnVyUit4SGNrSlNWSi81dHZabmt2N0JvOFpXNi9UVWZ1eUZKVjNZYy9ZbGQzTDJpcU5nbjFTWElud09BTXVwcWR2N2wvZngwNTY3ZmZmdE90blAzMDAwKzY1Wnp5NWNySnBaMDY2Y2c3U05DUkx5SFdDN3ZLTTFNa0lNVE1IYnZUblZ5NlhQWTkrNEtPQUFBNE16WHJWcTFhTlprNlpZcHMyckJCM25yakRXblZzcVZQemNadDJMaFJKa3ljcUNNVVd0WnJ0dnlkdDB0b3JacTZ3eDJwY1p0bDc0c3Y2NmpncUlTelNKRWlPa0pPVkJJZEdocXFJK2QxdnZwcUNUUHc5NnVaOGR3VWZ2czFsNG44dVZEVjI5WHFLNjhoUVVlK0ZXdmRTcUtzRHc4M0pMNzh1aHo3MWZrM0tBREFQeFV2WGx6NjNYQ0QvTFJva1d4Y3QwNG1qQnRuRDhwTUREU2Q5dElycjhpK2ZmdDBoTUlxTUR4Y0trOTRVaVFvU1BlNFE0MjVUaGc0Yy9wY3FIM1A0UzVYcy9kVjVjcVdOWnFncTJydWpSczMxcEZ6VnExYVpSODVtUk43Ly9teVpUcHlUdS9ldlhYTFd3S3lEQjR1bUpXZUxwdTZ4RXJxeGpqZGs3Mm9RUU1sZXRoUUhmMlRXdGE4b1ZWN3lUaDBTUGVjV1lPMXl5WFFSL2VjbVpUNDVnelo4OFFFSFRtcllkd2FDUWdPdG4vWDIyNjlRNUorL2xVL1lrNXd1YkpTNjZ2UEpNVDZzN0E2TW4rQkpBd1lwS016SzlFalZtSW1uL24zbnBXUklYR2RZeVZsNHliZGs3MlMzYnBLbFdtVGRlUi9Uc1hIUzl4bG5lM1hzRW1CUllwSW5RWGZTWWdMVzBKTXVIL0lFSG54SlhPRmcrNis2eTZaUG0yYWpyeE5mV3cyYXRMRW51RTA1ZHR2dnBGT0hUdnF5QmxObXpXVFZhdk43U3Q5NSsyM3BXK2ZQanJ5TnZVN1BIYnNtSHd6ZDY0c3RCSjN0Y1J5eTlhdFJ2WTM1dGV3Qng2UThlUEc2Y2haYXRCYnRVWU51emlkS1h0MzdmSmNBYVovVzlleW5hUWZPS0FqYzZJbmpaY3kzV04xZE81MlRYaEtEcjcrdG83Y0VWSTFSczZiTTF1Q0NtaDhyZDZUZFJzMGtCMDdkdWdlNTZuVk51M2F0dFdSN3pxdmRtMTVhUGh3SFpueDBzc3Z5MzJEQit2SU9RdC8rRUhhdEdtam8vLzF5YWVmU3Q4YmJ0Q1JNOVM1NTFzMmJaTHc4SERkNHgwazZJV0FHd202a25id29NUmQzVTB5OXB2L2tJdHMzVkpxdlAyYUJCVFNmVWtrNk00aFFjOGRFdlQvUjRKK1pyNlVvUCtiU2dMVVRMVksyTldYbXFsUmxZVU5EcEZ5VGMxYXFabC9FNE5JRXZULzhKVUVQZVA0Y2RsNDliV1M3bkxSM05MOStrcmx4MGZaeSswTHdpVWRPdVM2a0ZoZVhIWGxsZkxsNTUvckNEbFIxOFZxTld0S21zTkg4WTE0NkNFWk8yYU1qdjdYZ050dmx4a3paK3JJR1gxNjk3YnJsWGdSUzl6aG1CRHJBN2p5bEltdUxNRktYcnhFOXI3d3Nob3A2eDRBQVBKR1ZUNnVWS21TM0Q1Z2dNeis5RlBac0hhdC9QempqM0xYSFhkSTFaZ1lZNVdSYzJQdjNyMnljdFVxSGFFd0N5cFdUQ285YVNVeGdlNE8zdzkvT0V1Ty8xbHdTOTJiWFhTUmJwbXhlczBheWNqSTBCRnlVclpzV1duWm9vV09uSlBUUG5SMUEzSHhraVU2Y2s2UDd0MTF5M3RJME9HbzRtMHZsakozdWJBZjNYb1RIM3p4VlRuK3gxTGRBUUNBTTFUUm9CYk5tOHV6enp3ajY2MWsvYWVGQzJYUVhYY1ZTRVg0ek14TStmcnJyM1dFd2s2TnMwcGMwMWxIN2xBcnpIWU9mMFF5a2dybVZJSGF0V3ZybGhrblRweXd0N3pnN0ZTaHpXdTZkdFdSYzlTS3RKU1VGQjM5MDU0OWUyVExsaTA2Y2tiNTh1WHRsUk5lUllJT3g1Vy9aNUJFTkRkN3QxUEpTa3VUbmZjOUlHa3VMS2tIQUJSTzZvaW5aczJheVRQVHBzbld6WnZscFJkZWtOcTFhdWxIM2JIa2p6OTBDNFdkT2tvcit1RmhFaFRsN3MyaXRCM3hzbnZpNUFKWnVkakN3SXp0NlZSeXZpbnU3TnR4OFIvWFhudXQ0eWRpcUpWQzI3ZHYxOUUvcVRvaFRxOXc2Tks1czlHQ2V2bEZnZzdIQllhRlNzd3pVeVNvYkJuZFkwNjZsWnduREh0WXN0SlptZ1FBTUVzZCtUVGd0dHRrNVlvVjh1VFlzUklSRWFFZk1VdnRpV2NKTHY0V1VyYXNSSThlNmZwUzl5TWZmeUxIZmpPM0Z6dzcxYXRWTTNyVW1scWw4c01QUCtnSVo2TitIODJiTmRPUmMrWmtzMUxJNlJWRTZqaTYzajE3NnNpYlNOQmhSR2lGQ2xMNTZZbi9MU0JuVXRKUHY4cSs1MS9VRVFBQVpxbFpkVlV0K2ZOUFA1VWlMaFNuVlVYc2ZIVUpyaGNyNC91RGtsZGVJY1V1ZGJhUTVObllTOTJIalpEMHc0ZDFqenZVbHBQNjllcnB5QXlWSEhxaEtLU3ZNRkVROUV5RkFKT1NraHpmZjE3UnlsRmF0MjZ0STI4aVFZY3h4ZHRjTEtYdnVFMUhaaVdxL2VpL3N3UVFBT0NlRGgwNnlQQmh3M1JranByaFUvdGtuYWFLM3ptOVZQWGYyTnRyUmtCUWtGUjYvRkVKTEZGYzk3Z2pmZDkrMlRWK2txdEwzWU9zbi9YU1RwMTBaTVpmSzFmS3RtM2JkSVN6dWVMeXl4MHZucmw4eFlyL09ROWRIWCtwS3NjN3FWdTNidmI1K2w1R2dnNXpyQS85aXZmZkl4RXRuVjhHODIvMmZ2UUhIbkw5cmk0QW1LQVNNaWVwbVNHbmo4WEJmd29tM1hiYmJjYVh1cXZmMzc4SHJrNVFnMVRUQ2JySkk5d0t1OUR5NWFYOGcwTjA1SjZqbjM4cFJ4ZjlxQ04zWEhIRkZicGxobHJwOFpaSGo5enlvaG8xYWtqREJnMTA1QXgxMU9XdTNidDE5QitMRnk5MmRHV0R1dG5UeitIejFFMGdRWWRSNnB6eUtwTW5TbENwa3JySEhIVXVhTUpESTQyZlp3MEFwaDAvZmx5M25QSEpwNS9LK2cwYmRBUW5sUzVWeXQ2VDZZdE1KK2ZLWm9lckwrT2Z5dlRxS1JGTkw5Q1JTekl6WmRkall5WDk2RkhkWVo0NlZVRWQ4V1hTakhmZXNaZFU0K3pVUHU0YisvWFRrVFBVVFpMZmZ2dE5SLzh4Wjg0YzNYSkcxYXBWcGRINTUrdkl1MGpRWVZ4WTVVcFNhZXBUOW5JczAwN01XeUQ3MzNoYlJ3RGdtNXhjMGhjZkh5LzNEUjZzSS85eThPQkJPWENnWUUveVVBTlZ0U2ZkTkRYejQ3VHc4SEFKTkp5a3EyV3JNQ2NnT0VncWozOUNBaUxDZFk4NzFLVEl6a2RIMjhtNkc5Unk2bDZHQzN1cDQ3ekdQdkdFamdxZTB5dXBuS2FPS1hPNkV2cmNiNy9WcmYvY3FQN2xYd2w3ZmwxN3pUV2VydDcrTnhKMHVLTEVKZTJrMUswMzZjaXNBMU9teS9IRnpoYVVBQUEzclhBb3FWSDdmL3ZkZUtNa0ppYnFIditoa3ZPdTExNHJ6VnEwc0Nzd0YrUmcxdlJ1WEpXY0Z5OXVacTl4NDhhTmRjc01OU05HOFMyekltclZsSEwzRHJLM0ZycnAyTGZmeTVINUMzUmtucXE4YlhyVng2dXZ2U1pyMTYzVFVjRlEyNUhlZmZkZHVlbm1tejFkWkxGYXRXcFN2WHAxSFRsREZZcjcrMmRldFdxVm95c2ExTTNVVy9yMzE1RzNrYURESGRZRnRlS1EreVM4U1NQZFljNS9xb3crTE9tSGorZ2VBSENPR2lDV0tsVktSMmFvWTdYeW05U2twS1RJTGJmZTZuZ0ZYQzlRTXl2WHhzYmF6NVBhczlqRlN0VDczM0tMN1A3WC9rVTNxTDNocG0rQWhBUUhTNGtTSlhUa3JNcVZLdW1XR2N2Ky9OTSs0eGhtbGUxL280VFZxNk1qbDJSbXlhNlJveVhOcFZVc3paczNOMTdOL1lTVkVLcWJta2RkWEw3L04zWE5YN2x5cFZ4NitlVnl5NEFCOHZHc1dmTHNjODk1OWdhWFdqblU3L3JyZGVRTWRlTjExNjVkZGxzbDYwNys3T2ZWcmkyMXJTOWZRSUlPMXdSR1JFak1jMU1sME5Bc3dPblNkKzM1ei9ub0hsOGVCTUEzbVM0S3Ruck5HbG03ZHEyT3p0M0preWZsWmlzNS85TGgvWHRlb0txWjkrN2JWNWI4OGY4bmQ2Z3p3ai84NkNOcGZPR0Y4dFNrU1VZcW5tZm5wNTkvTm41am9FbVRKc2FXMFZjeW5LQ3IzOFhqWThia2VhRE5NVzI1RXhnZUxsVW1QR25YL25GVHhzRkRzdk94c1NxNzFEM21xSlVrUTF6WXJyUEd1dmIyNnRQSDhWb2dPVkZKNlcyMzN5NHRMNzc0djhlTnFmZk1xTkdqWmY3OCtYYnNSZGZGeGpxNi9VYmQ4RlEzOVJTbno2YnYwcVdMNDVYblRTRkJoNnZDS2xlV1NsTW02TWlzRS9NWHlZRjMzdE1SQURqSDFHem02Y1pQbkppbnBFWU45R0s3ZDdjTHcva2JOV0R1ZThNTk1pK2JnZHVSSTBmazBjY2VrenIxNjh1MDZkT056MnlyL2UrRGg1aXZvbjNoaFJmcWx2TmF0MnFsVytiTWZPODllZU9OTjg3cDlieHAweVlaUEhTb3RHdmZua3J3dVJUWm9MNUUzZUxPZHNMVEhaODNYdzU5OFpXT3pGSUpZYVhvYUIyWnMyRGhRbW5UcnAyc1c3OWU5NWl4ZGRzMkdUWjh1TlJyMEVCbXZ2dnUvOXlRVXE5OXRUcG8rL2J0dXNkYjFCTDNlblhyNnNnWjM4K2JaMi9QK3ZIbm4zV1BNMjZ6bmtkZlFZSU8xNVc4ckpORTNUbEFSMmJ0bnpSVmtsYXQxaEVBT01QcDQyWE9SQ1hZTDczOGNxNlRHalh6OE43Nzc4dEZ6WnZML0FYdTdRdDFpMXF5UDJEZ1FQbjJ1KzkwVC9aVWtiM2hEejhzTld2WHRndmtMVjI2MVBGajVyWlpBK2JPWGJ2YUEyeVQxTDVKazhXeGF0V3FaWDhQazlSemY4OTk5OW1KeHVyVnE4K1ljS3ZYNzBZcktYL25uWGZreXF1dmxrWVhYQ0F2dlBpaXZZMUJKUzdJaFlBQXFYRC9QUkphdmFydWNJbDFqZG96N2lsSmRXRXJRN0ZpeGVUUmtTTjFaSlpLemx1MmJtMnZ5am5zNERHK2FvV1RtaFZYSzRIcU4yd28wNTk5Vms3bWNJemkvZ01INU5ycnJuTjFaVkJ1cVpVOXZYdjEwcEV6Vk4wS2RjMTJzcTdJQmRiMVJCME41eXRJMEZFZ0tneStUOElhbU4xSHBHUlpGOEdFK3g3Z2ZIUUFqbExGY1V4VGlmblFCeDZRSVVPSDJyTW5haG4zdjZrK2RYYXNLaWpVdEZrenVlVzIyeVR4NEVIOXFQOVF5WnY2MlQ2YlBWdjM1RTZ5OVJtZ2JuSzBiZDllNmpab0lJODkvcmdzc3hJK05UdVRsOVVKYXNDb0tqMVBmT29wYVhMaGhiTGlyNy8wSStaVXJseFp6cmNHOGFhb0diQ1NKYzBmaFpwaFBYY2ZmUGloTkcvVlNpckZ4TmhKdU5xRzBjZEtVbHBkZkxGVXJscFZMckNlMDlzR0RyUnZNSjMrZWxlL043VTNGV2VubHJwWEdqZFdyUWZYUGU3SU9IUklkbzRjTFZrWjVyY1dYbi85OVViZkU2ZFR5YlJhbFZPM2ZuMTVjUGh3V2I1OCtUa255dXExckZienFPMHdhbFZJblhyMTVLb3VYZXpyMlptdTYyZXlidDA2dWVPdXV6eFoyVjBsNkU3ZTVOdXdjYU44OXZubmVicEdaMGRWYnpkOUk5SkpBZFlQNzl4UC95K3FXTmVtTHJHU3VqRk85MlF2YXRCQWlSNDJWRWYvbEptYUtodGF0YmZmL0RscHNIYTVCRVpHNmdoL1MzeHpodXg1d3N5eThvWnhheVFnai9zNVRtM2JMbHU2WGllWlNjbTZ4NXlpVjE0bTFaNmY3c3BSYjI1UVZWTVRCZ3pTMFptVjZCRXJNWlBQL0h2UHNqNFE0anJIU3NyR1Rib25leVc3ZFpVcTB5YnJ5UCtjaW8rWHVNczZHejgvUDdCSUVhbXo0RHNKS1JPbGUzekwvVU9HeUlzdnZhUWo1OTF0RFR5bVQ1dW1JKy83YStWS2FkNnlwYU1EaUp5bzQ3QnFXSW1VT2d2NDcyUktMZWYrZmNrUzJibHJsNnQ3SmJQenp0dHZTOTgrZlhUa0hEVnpyaEk1cDVic3F5Si9aYUtpN0pzc0hUdDBrUFBQUDk4dVBGVzZkR203VXJyYVQ2bSsxTUJaZmFtWk0xV0k3cGRmZnBIdnZ2OWUvc3pEQUQwL0huM2tFUmx0SlFnbVhkdXRtM3h6MnZGR1hqVDR2dnRrOHFSSk9uTFd1cGJ0Sk4yRlFtZlJrOFpMbWU2eE9qTEl1aTRsUERaR0RyLy9rZTV3aWZYZXF2VFVPSWx5NFdmODJYby9xbUpxQlpHd2xpOWYzaTQ0MXJKRkM2bFFzYUo5YlZiWGpyRFFVRW0zcmhscW1icTZxYXFLSThiRnhjbXZpeGZMZ2YzNzVlaXhZL3B2eUx1bkpreVFvUzVzcXprWDZuZlF1azBiKzlyb2xMK3Z3VTVRMS95MXExYjVUSUU0aFJsMEZKanc2dFVrMnJxUWl3dDN0RTU4TzA4T3pKaXBJd0RJSHpVNGk3Q1NacmVvR1dTMTNQS3RHVE5rMmpQUDJGK3F2WDdEQms4azU2YW9nYTdhNCsza2ZucDFVK1ZBWXFLOWRQcXB5Wk9sMzAwM3lZWE5ta20xbWpXbGRObXlVclZHRFh2WmFZeVZ3S3U0NW5ubjJmdWdIM24wVWZueHA1OWNUYzdWVFlONzc3bEhSK2IwTVhCanhXa3Z2ZktLYkxLU0hlU0NXdW8rK0Y0SktsZFdkN2pFZW0vdG5UaFpVdmZ0MHgzbVhOeTZkWUVkbWFWV0xha2JCSk9mZmxvZWVQQkJ1K1pIcDhzdWt6YVhYQ0x0TzNhMGJ4eW83VGhxNW4zR3pKbXllZk5tUjVKelpmVGpqOXY3NDcxRXpVeDM2OVpOUjg1d0tqbFhMbWpTeEtlU2M0VUVIUVdxMUZWWFNLbSt6dTVkeWM3K3lkTWxlVzNCbm0wSndEOUVSa1pLaHc0ZGRBUVRWSEorLytEQjh2cWJiK29lZDZpVkNmRUpDWTROcVBOajBKMTMya202YVpkMjZpVEZpeFhUa1RlcGxSUVBQZnl3YTZ0V2ZGMUlWSlJVR2pQS2xVbVEwMlVjT2l3Snd4OHh2eXJOK3JtZW5qTEY4UUpsWG5mS2VoL2MxTCsvN05peFEvZDR3NVdYWDI3UFZIdlJEUTRmQmVjR0VuUVVMT3NDR3oxcWhJU2ZiNzdnVXRhcFU1Snc3MURKT082OUloc0FmRS9QSGoxMEMwNVRTeVlmSERaTVhuMzlkZDFUK0RTb1gxOGVmdWdoSFpsVnBrd1p1ZXl5eTNUa1hWOS84NDBzK3ZGSEhlRnNTbHphU1lwZDNrbEg3a242ZGJFY25HWCtGSWtpUllySXpCa3o3TUp4aGNtKy9mdnRXWHN2clo1cTFLaVJKNHV3aFlhR1N0ZXVYWFhrTzBqUVVlQUN3OElrNW9WbkpMQllVZDFqVHVxMjdaTHcwRWg3RHpZQTVJZWFkVlFEUkRoTExXMThjdHc0ZWZIbGwzVlA0YU1HbGE5YVAzK1k5Zm5vQmpYejljakREenQ2bnJFSmF2WjgrRU1QY2V4YUxnVUVCa3Jsc2FNbEtNcjhLb3gvc0g1UGU4WlBrbE03NG5XSE9ZMGJONVkzWDMvZGZzOFVKcXZYckpGQjk5emo2Rkx3L0ZBckdrelVJTW12cGhkZUtOV3F1bnlxZ1FOSTBPRUpZVlVxUy9TVGo5c3o2cVlkLzI2ZUhQendZeDBCUU42b1FrR3hEdSs3TXkwcUtrb3VhZGRPUjk2akVyQkpreWZMdUFrVEN1MVNacFVrUHpOdG1qUnYzbHozdUVNVnkrdmFwWXVPdkVzVmFIeG5KalZsY2tzdGRhL3cwSVAydm5RM1pTVW55ODdoSXlUTGhTSnVxa0wzK0NlZjlPd1NhMU0rL09nam1mTDAwem9xZUYwN2Q3WVRkUy9wZitPTlB2bTZJRUdIWjVUcTJsbEs5cnBPUndaWkh4Wjd4MCtTNUhYcmRRY0E1TTJ3Qng3d21aa2I5ZTk4N2VXWDdVcndYcVVHVWwyc1FWNnRtalYxVCtHaUJyY1BEeDh1dDkxNnErNXhqM3J1eHo3K3VHdXo5dm54eExoeGRxMEE1RTVVN0xWU3BPM0ZPbkpQOHJMbGN1Q3RHVG95UjcxMlZUSEZ4dzJmZHVCRlU2ZFA5OHdSaE9vbVg2WG9hQjBWdktKRmk4cFZWMTJsSTk5Q2dnN3ZzQzZ3MFNOSFNGZ2Q4NVVXczVKUFN2eGQ5MG1HSDFjL0JtQmV2WHIxN0R2MHZrQU5YdFZldkppWUdOM2pUV3FROS92aXhmYlp1b1ZwUml3NE9GaEdQUFNRUERacVZJSDkzT3Ixckk1MTgvcnp2bnYzYmhrL2NhS09jRmFCZ1ZKcDlFZ0ppSWpRSGU3Wi8reUxraEp2ZnFtN3VyazE0dUdINVpXWFhwTElBdmc1QzRKYXZyMXcvbng3WlpRWGhJU0V5STM5K3VtbzRGM1V0S2xVckZoUlI3NkZCQjJlRWxTMGlNUzgrS3dFRmpkZjhDTXRQa0Yyamh4dDc1VUNnTHhRaWN5VFR6d2hWU3BYMWozZW8vNk5JMGVNa0FjZmVNQ082NXgzbnYybmx4VXJXdFF1L3ZUQnUrOUt4UW9WZEsvL1V1ZmNQenQ5dW4zZWVVRXZFWDFnNkZEcDBMNjlqcnpyUlNzUjI3aHhvNDV3TnVIVnFrbjVZVVBzeVJBM1paNDRJZkZEaDB1bUMzVUQxTFh1MWx0dWtkbWZmU1pseTdwOHhKeUxTcFFvSVUrT0hTcy9MVm9rOWV2VjA3M2VjRjFzckdkcVdWemZ0Ni9uYnpabWh3UWRuaE5lbzdwVWZNSktuRjBZcEJ5Yk0xY1NQL2hJUndCdzd0UXhXSysvK3Fvbmw3cXJXVmsxSTNyNnJHeTVjdVhzUDcxTy9YdTdkKzh1Znk1ZEtqZjE2K2NUUzYvem9tclZxdkxObkRseSs0QUJuaGhNcWxtdzkyYk9sRWJubjY5N3ZNaytkbTNFaUVKYnF5QXZ5dlRwTGVFTjYrdklQU2YvV2lVSDNucEhSK1oxN05CQmZ2LzFWL3VzZEY5TjBNNUVKYjZYWFhxcC9QbkhIL0xROE9HZS9NeFJxM0M4TUd1dEt2dXIyZ1MraWdRZG5sU3F5OVZTc3FjTCs5R3REL1o5NDU2U2szR2JkUWNBbkx1T0hUdksxQ2xUQ256MjgzUnFtZWNMeno0cmo0NGMrWTkvVjZsU3BYeHEwS3Btd2w1LzdUWDUrY2NmcFhXclZwNTZqdk5ESmNLMzlPOHZTMzc3VGRxMmFhTjd2VUVkdS9iRjdObWVUOUxWc1d2ejVzM1RFYzRtTUN4VXFqdzFYZ0xjdnRsbGpiVU9QUCtTcTJNdHRaWG51N2x6WmR3VFQ5aDdrWDJadWw0M2FOQkF2dmpzTTVuejVaZjJUVDJ2VWpjTmVuYnZycU9DbzY2cDZyUE9WNUdndzVQVTBTRHFmUFN3dXVhWFltYXEvZWlEN3BlTXBHVGRBd0RuYnVEdHQ5dVZoTDJRUUtvbDkzTysra3B1dmZYVy8vbjNxSmtGVllIZWw2Z0I2Z1ZObXNpQ0gzNlFMNjNFVVNYcXZrenRqZnplU2g1ZWVmbGx6K3dmL2JmSzFtdElKVGhxTnRLTDFHdENuVWhReWNQYlM3d280cnphVW1hZyswVUlNNU9USldIWXc1S1pscVo3ekZPcmJvWTkrS0Q4c1hpeGRMdm1HcCtjVGE5YnA0NjgvY1liOW8yOEs2NjR3aWR1VUhyaHVEVmZyMkZDZ2c3UENpcFNSS3BNbXl5Qkxwd3puTHA1aSt4NmJJeGQ0UjBBOGtJTkJ0VCszYmRlZjkzZVExMFExTCtoMy9YWDI4dkNzNXVWVlRNY0JmWHZ5eSsxeEZNTlVoY3RXQ0FMNXMyVFhqMTcrc3haOU9wM294THo5OTk5VjM3OStXZHBZLzErdkQ2QVZEUHBhc1pPRmE4TDk5QVdBMVVjNjRQMzNwUHZ2LzFXR3RSM2Y4bTJUN05lYytYdnVsUENyRVRkYmFkV3I1Vjl6NzJvSS9mVXJsMWJabjM4c2Z5NGNLRmNjZm5sbmovdlgxSEw4ejk4LzMxWjhlZWZjcjExVGZlbExUNXFtWHYxNnRWMTVMN2l4WXY3eEpHUk9TRkJoNmRGMUswakZjZU9zbDZwNWwrcVJ6Ly9TZzdPL2tKSEFKQTNhakMxZE1rU1Y4OGJWM3ZOMjdWdEt6OHZXaVJ2dnZGR2prdjcxTkpxTll2dXkxUmkyOWI2ZWRWZTZhMXhjZkxVeElseTRRVVgyTStEMTZpQ1RqMnV1MDUrWExEQVRzeDc5dWpoVTh2MDFldGw3Smd4c21UeFl1blVzV09CUGNlcWtKNzYvcDk5OG9uOVBIYTNubE4vMmU3Z05yWFV2ZEs0TWVyQ29YdmNrL2pxRzVLOHZtQ091VzNWc3FWODljVVhzbHpYdFNqanNkVXJhdSsyT21MeEx5c3BWNnVGMUd2Y2k5ZTBzMUh2MWRodTNYVGtQbldkOFBuUHVDeUQxVFd5MHRObFU1ZFlTZDBZcDN1eUZ6Vm9vRVFQRzZxamYxS1ZIemUwYWk4Wmh3N3Buak5yc0hhNUJFWkc2Z2gvUzN4emh1eDVZb0tPbk5Vd2JvMEVHTDU0WkdWbVNzS0lSK1hveDUvcEhuTUNySUZJemE4K2tZZzZkWFNQTngyWnYwQVNCZ3pTMFptVjZCRXJNWlBQL0h2UHlzaVF1TTZ4a3JKeGsrN0pYc2x1WGUyVkRQNHE3Y0FCMlRWdW92V2NtRjA5WVErSUhudFVnbDA0b2NDRUdlKzhJL09zQVlNcGwzYnFKRGYzNzY4ai81Qmh2YysrbWpOSHhvd2RLK3MzYkxCanB4V3hQdk5Vb3ZySXd3OUw4K2JOY3owenBDcGcvMllsWEU0YWRPZWQwcnAxYXgyNVR6Mi9PK0xqNVF0ckFQNjU5YlYyM1RvNWV2U29mdFE5NnVaQnlaSWxwZGxGRjltSmVUZHJvT3JMZXlGUGwybDlIcTlZc2NJKzRtekJ3b1Z5NHNRSi9ZZ1phdGF3Um8wYTlwN1cvamZkWkMrN041R1VKNHdjTGVuSGp1bkluS2pyKzBqeFZpMTBWUEQydi9tMkpLMVlxU1AzaEo5WFd5cmVjNWM5bTErUTFQVmg3dHk1TW1QbVRQbHorWEk1ZlBpd2ZzUWQ2bnF0aW94MnVPUVNPekZ2MmJLbFJQcEpIcU0rODhhTkg2K2ovM1V5T1ZtK3RwNTdFNStMNnNhdFdsM2x5MGpRQ3dGZlQ5Q1ZET3VEYy9OMXZTVjF5emJkWTA1WTdWcFM2OHRQSkRBOFhQZDREd2s2NER2UzB0TGtqNlZMNVpWWFhwRzUzMzRyeDYya0pxK0Rra0JyUUt0bU5GVXlyZ1lnbmErKzJrNWF2TDVVMm0xcWFIUHc0RUZadlhxMWZQdmRkL2JnZThrZmYwaTZOUzVSWDA1U00xeHFvSzBTOGhiVzcrVnE2M2VpaXF1cEpOMmZxYlBJdjdFRzJMTSsrY1IrYmsrZVBHa244UG1oWHR0cXhVRnJLMUZSUzFUYnRXdG5GOFR5aFNYSjhHMUhqaHl4cnhPcThPRGl4WXRsOVpvMTlyWEN5UVJTWFN2VWxoeDFyYmo4c3N1a2ZmdjI5aDd6aUVKeWJ2dnBQcHM5VzNyMzdhc2o1NmpuZDFkOHZNOXNmY29PQ1hvaDRBOEp1cEs4YnIxczdYbURaQ1diTCtaV3NuY1BxVExoaVFLL3U1c2RFblRBTjUwNmRVcldXQU0vbGJELy92dnZFcCtRSUlsV0lobHZEU2hVZ25NNnRmKzNmTGx5ZGhFeFZmU3RXYk5tMHJCaFEybmNxSkhmSjM4bXBGcGppWjA3ZDhxYXRXdnRQemZGeGNuV3JWdnRnYm1hU1V0S1NySm40TTlFL1E2aVNwZTJuM2UxdjdHYWxUVFdxMXRYcXNURTJMK1R5cFVxRmNwQjl0L1VjN2ZXZWw1WHJsb2w2OWV2dDJmUDFHeWtlbDYzYk5raS94NW9Wb3FPdG1jTzFaYzY1LzZDQ3k2UW1qVnJTaVBydFIxVHBRb0pPUXFjV2gyeWJkczJleVdPdWw2b20xREhqaDJ6djlRMVkvZWVQWko4aHZHb1NneWpLMWEwYnpTcDY0VzZnYXB1MkttcTh1ZGIxNG9xMXV0YjNZZ3F6TlJuWFl2V3JlMXJoZFA2M1hDRHZQWEdHenJ5WFNUb2hZQy9KT2lLT3JOOHp5T2pkV1JXcFdjbVMrbHJ1dXJJVzBqUUFmOXh0bzloWnNmTnkrMVFpTi9GdWNucGVlVzVoSy9LemZXQzEzZjJYbnY5ZFJsMHp6MDZjbzY2c2ZmRGQ5L1pCVGg5SFFsNklYQms5aGR5NE9YWGRlU3NXbDkvYmlYb0x0N3B0bDZ1dTZjOUt5bWJ6djZheXEvQVlzV2s4cGhSRXVUQjF4UUpPZ0FBQUh6SnZuMzdwUEVGRjhqQnMrUjBlYUcyQy95MWZMbGZyTUFoUVFkOEVBazZBQUFBZklWS09XKzU5Vlo1NzRNUGRJOXoxSXFGMTE1NXhTNG02UTg0bndJQUFBQUFZTXo3Vm1KdUlqbFh5cFVySjlmRnh1ckk5NUdnQXdBQUFBQ00rUFhYWDQzc08vL2JuUU1IK3Z6WjU2Y2pRUWNBQUFBQU9HN1Y2dFhTcTArZk0xYTlkMExGaWhYbHZudnYxWkYvSUVFSEFBQUFBRGhxL29JRmN2a1ZWOGorQXdkMGovT0dQL2lnZmZ5bFB5RkJCd0FBQUFBNElpMHRUWjUvNFFXNU5qYldTTVgydjlXdFcxY0czbjY3anZ3SENUb0FBQUFBSUY5VXBmYjE2OWZMMVYyNnlKQUhIcENVbEJUOWlQTlU1Zllwa3laSmFHaW83dkVmSk9nQUFBQUFnRHpic0dHRDNEbG9rRnpZckprcyt2RkgzV3RPcng0OTVJckxMOWVSZnlGQkJ3QUFBQUNjazBPSERzbnN6eitYemwyNlNLTUxMcEEzMzNwTDB0UFQ5YVBtUkZlc0tNOU1uNjRqLzBPQ0RnQUFBQURJVVZKU2txeGJ0MDdlZXZ0dGliM3VPcWxlcTVaZG9mMzdIMzZ3bDdlN0lUdzhYRDU0N3oySmlvclNQZjZIQkIwQUFBQUFJSm1abVhMcTFDbDdkbnpEeG8zeTFadzVNdXF4eCtUeUs2K1VXblhxMkV2WUI5NTVwOHo1NWh0alI2ZGxKekF3VUI1NzlGRnAzYnExN3ZGUEpPZ0FBQUFBVU1pZE9IRkNXcmRwSTQyYU5KRWF0V3ZMK1kwYnkzVTllc2pFU1pOazRhSkZrcGlZS0JrWkdmcS9kbCtmWHIxazZKQWhPdkpmSk9nQUFBQUFVTWdWS1ZKRWR1N2FKZHUyYjdlWHMzdEoyelp0NU9XWFhwS2dvQ0RkNDc5STBBRUFBQUNna0ZOSGw3VnUxVXBIM3RIMHdndmwwMW16SkNJaVF2ZjROeEowQUFBQUFJRFVPZTg4M2ZLR2kxdTNscm5mZkNPbFNwWFNQZjZQQkIwQUFBQUFJTTJhTmRPdGdxVm04Ni9wMGtXK25qTkhTcFVzcVhzTEJ4SjBBQUFBQUlCVXFWeFp0d3FPU3M2SDNIKy9mUGpCQjFJa01sTDNGaDRrNkFBQUFBQUFpWW1Ka1dMRml1bklmU1ZLbEpCM1o4eVFweVpPbEpDUUVOMWJ1SkNnQXdBQUFBQ2tlUEhpRWg0V3BpUDNCQVlFeUdXWFhpckxseTZWWHIxNjZkN0NpUVFkQUFBQUFHRFBXcnU5RHoyNllrVjU2Y1VYNWFzdnZyQm44QXM3RW5RQUFBQUFnSzFCZ3dhNlpWWmtSSVRjUFdpUXJGeXhRbTY5NVpaQ2NjWjVicENnQXdBQUFBQnNGelpwb2x0bWhJZUh5eDBEQjhyS3YvNlM2Vk9uU3NsQ1ZxWDliRWpRQVFBQUFBQzJPblhxNkphenFzYkV5TmpISDVmTkd6Zks4ODgrSzlXcVZ0V1A0SFFrNkFBQUFBQUFXM1IwdEJRdFVrUkgrVlBKK3J2NlhYKzlmRDkzcm14Y3YxNUdQUHl3bEM5ZlhqK0tNeUZCQndBQUFBRFlpaFl0S3VYeW1FU3IvMitkODg2VE8rKzRReGJObnk4YjFxMlR0OTU4VXpwMDZNQWU4MXdpUVFjQUFBQUEyTUxDd2lTbVNoVWRuVmxBUUlCZDVFM3RIMjkveVNWeTM3MzN5dHl2djVZTmE5ZmFSZCtlZStZWnVmamlpKzM5NWpnM0pPZ0FBQUFBZ1A5cTJhS0YvV2U1c21XbGNlUEcwckZEQjdrdU50WmVvajV6eGd5WlAyK2VyTGVTOFYzeDhUTHZ1Ky9rNmNtVDVkSk9uZXpsNjh5VTV3OEpPZ0FBQUFEZ3YwWTkrcWlrblRvbHV4SVNaTm1TSmZMZDNMbnkwUWNmMkVYZSt2VHVMVzNidExIM3FvZUdodXIvQjV4Q2dnNEFBQUFBK0M4Uzc0SkRnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUh1QWpDWHFBL2IrenlUeDFTcmNBLzVhWmZGSzNjaERFL1RjQUFBREFsL2pFQ0Q0d05FU0NpaFhUVWZhU1ZxM1JMY0MvblZ5MlhMZXlGeEpWUnJjQUFBQUErQUtmbVdJTHY2Q3hibVh2Nk5kemRRdndYMWxwYVhMc2gvazZ5bDVvNVdqZEFnQUFBT0FMZkNaQmp6eS9vVzVsNzhTOEJaSis2SkNPQVA5MDdKZGZKWDNQUGgxbEw3SkZNOTBDQUFBQTRBdDhKa0V2ZW5FcjYxK2I4MGIwaktOSFpmZFRUNHRrWnVvZXdMOWtKQ2ZMM3ZHVFJMS3lkTStaQlpVdkorSFZxdWtJQUFBQWdDL3dtUVE5ckZwVkNhMWVYVWZaTy9ycDU1TDR5V2M2QXZ4SFZucTY3Qm81V2xJM2I5VTkyU3ZlcVlNRUJQck0yeHNBQUFDQXhXZEc4SUdob1ZLcVYzY2Q1U0FqUS9hT2ZGd092UE91WkZsdHdCOWtKQ1ZKL0lNUHk5RXY1dWllSEZpSmVhbmVQWFFBQUFBQXdGZjQxQlJiVk4vZUVsU3FwSTZ5cDJZYTl6NCtUcmJmZnBlYzJycU5KZS93V2VxMWZPeW5YMlR6dFQzbG1Fck96N0swWFlsc2NaRVV5VVhOQmdBQUFBRGVFcEJsMFczSHFlUmlVNWRZU2QwWXAzdXlGelZvb0VRUEc2cWo3TzEvNVhYWk4zR0tqczR1SURoWUlwbzFsYUx0MjBsRXJSb1NWTGFzZmdUd3FLeE1TWXZmSlNjM2JwVGozLzhnS1pzMjZ3Zk9MaUEwUkdwOCtvRkVOc3c1UVZlclMrSTZ4MHJLeGsyNkozc2x1M1dWS3RNbTZ3Z0FBQUNBS1Q2WG9HZW1wc25tMko2U3NtNkQ3Z0h3dDFJM1hTK1Z4enltbyt5Um9BTUFBQURlNDNOVnBBSkRRNlRLMUVrU1dLU0k3Z0dnaE5Xdks5RWpodXNJQUFBQWdLOHhtNkFIQkZqL3kvbG90UDlLVDllTnM0dW9jNTVVbWo1SkFrSkNkQTlRdUFWWEtDL1ZYbjlKQXNQRGRjOVpxSFV6dVZ3OG83YUpBQUFBQUREUGVJSWVHSm03bWU3Y0hCMTF1cEtkT2tyRjhXUHNQYmRBWVJZVVZWcXF2ZjJhaEZhc3FIdk9MaXN0VlRLT0g5ZFJ6b0tyVjlVdEFBQUFBQ1laVGREVk9jekJ1YWk2cnB6YXNVTzNjc2xLL3FONlhDZFZYbmxCQW9zWDA1MUE0UkphcDdiVStPUjllMVhKdVVnL2RGalM5eC9RVWM1Q0tsVFFMUUFBQUFBbUdkK0RIblorZmQzS1dkcVdiWkt5YzZlT2NxOUUrM1pTNjh0UEpLSjVVOTBEK0QrMTdMeGszMTVTNjdPUEpMeGFOZDJiZThjWC95NlNrYUdqSEFRRVNGaVZ5am9BQUFBQVlKTHhCRDNpdk56UDdCMysrRFBkT2pkaFZhdEt6ZmZma2VoSjR5U2thaFhkQy9paG9DQ0phSGFoVlAvNFhha3lib3dFUlVicUIzSlBWWEEvL1BFbk9zcFpZRVM0aEZVLzl4c0FBQUFBQU02ZDBXUFdsTFRFZzdLaFJWdVJ6RXpkazcyUXlwWGt2Ty9uV0VsQmhPNDVkNWtwS1hMc3g1L2w0RHZ2eXFuVmF5WHpXTzcyMlFLZXBiYUtSSldXeU5ZdHBjeUFteVd5WGowSnNCTDF2RXBhdFZxMmRlOXJINE40TnFFMXFrdWRINzZ4WjlJQkFBQUFtR1U4UVZjMlhkdERVbGF0MFZIT3lnNjVWeXJjZDdlTzhpZjl5QkU1dVhHVEpDOWZJU21iTmt2NnNXT1NsWnFtSHdXOEt5Z3lRb0tLRjVmd0N4cExrU2FOSmF4YU5ic3Z2MVJTdnFYdlRYSnkyWExkazdQU3QvV1hTbytPMEJFQUFBQUFrMXhKMFBlOS9KcnNmK3BwSGVVc01ESlNxbi95bmoxTENNQlpCOTU1VC9ZKy9tVHVqbGdMQ3BTYVgzNHFrZlY1THdJQUFBQnVNTDRIWFNuWithcGNMOG5OVEU2VytEdnZ5MVBCT0FEWk83cndSOWszYm1LdXp6OFBxMVZUSXM2cnJTTUFBQUFBcHJtU29Lc3EwRVd2dmtKSFo1Y1dueUJiKzl3b0p6ZHYwVDBBOHN4S3lJOTgrNzBrM0hYdk9XM3hpTHJsSnJ0YVBBQUFBQUIzdUpLZ0srWHV2UDJjQnZ2cHUvYkkxdGplY3VqekwzTlZ6QXJBLzhvNGNVSjJUWmdrQ2ZjTWtheVVWTjE3ZGlIVnFrcXAyR3QxQkFBQUFNQU5yaVhva2ZYcVN2SFlyanJLblV5VlhBeDlTTGJjY0xPY1dMcU1SQjNJcGN4VHArVGdwN01sN29xdWN1aTF0M0ozNXZuZkFnS2szSDJESkRBMFZIY0FBQUFBY0lNclJlTCtsbllnVWVJNmQ1TU02ODl6WmlVTm9UVnJTTkYyRjB1UkM1clk3YUFTSmZTRFFDR1hsU25wK3cvSXFVMXhrclJrcVp6NGRiRmtXSEZlRkxIZVk5WGZlazBDQWwyN2Z3Y0FBQURBNG1xQ3JoejVZWUc5RjFiU3oyRkdMenVjelF6OFB3ZmV5b0VsaWt1dE9iTWxySElsM1FNQUFBREFMYTRuNkNxSjJEUHBhVWw4K1hYZEFjQUxBc0pDSmViVkY2VjR1emE2QndBQUFJQ2IzRi9ER2hBZ0ZSNGNJaVd1b3dBVjRCbEJnVkpoOUVpU2N3QUFBS0FBRmNnbVUzVW1ldVZ4WTZUb3BSMTBENEFDRXhnbzVSNFlMR1g2OU5JZEFBQUFBQXFDKzB2Y1Q1T1ZtaW83SHhzclJ6NzZSUGNBY0pOYTFsNXh6Q2lKNnQxVDl3QUFBQUFvS0FXYW9OdXNiNS80M2dleWI4SVV5VXhPMXAwQVRBdUpxU3lWcDB5VW9zMHUwajBBQUFBQUNsTEJKK2phcWUzYlplZURJK1RrOGhWVzBxNDdBVGd1SURSVVNsemJSYUlmZTBTQ2loYlZ2UUFBQUFBS21tY1NkQ1VyUFYyT2ZQK0Q3SnM4VGRKMnhOdXo2d0NjRVJBU0xCRk5HdHRMMmlQcjFyRTZPS1lRQUFBQThCSlBKZWgveTB4SmtlTy9McGJFTjk2V2szOHNzeE4zQUhsZ0plR0JSU0tsMkdXZHBNeXROMGxrL2ZwMlVUZ0FBQUFBM3VQSkJQMTBxZnYzeS9GRlAwblNiNy9MeVkyYkpHM0xOc2xLUzlPUEF2aTNBQ3NoRDZ0VlV5SWJueTlGMjdhUm9xMWFTRkNSSXZwUkFBQUFBRjdsK1FUOUg2eC9xcHBOVHp0OFJESk9ISmYwZzRja0t6TlRQd2dVWG9IaFlSSlV2SVFFbHl3cHdTV0tTd0N6NUFBQUFJRFA4YTBFSFFBQUFBQUFQOFUwR3dBQUFBQUFIa0NDRGdBQUFBQ0FCNUNnQXdBQUFBRGdBU1RvQUFBQUFBQjRBQWs2QUFBQUFBQWVRSUlPQUFBQUFJQUhrS0FEQUFBQUFPQUJKT2dBQUFBQUFIZ0FDVG9BQUFBQUFCNUFnZzRBQUFBQWdBZVFvQU1BQUFBQTRBRWs2QUFBQUFBQWVBQUpPZ0FBQUFBQUhrQ0NEZ0FBQUFDQUI1Q2dBd0FBQUFEZ0FTVG9BQUFBQUFCNEFBazZBQUFBQUFBRlR1VC9BRWk0UGhzV0RwQ2hBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6Ijk1NDQyYjJlZjE1ZTRkZWZiMjcwZWZiMTA2ZmFjYjRlIiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2IjpmYWxzZSwidXNlclZlcmlmaWNhdGlvbk1nbXRQcmV2aWV3IjpmYWxzZSwiY3JlZGVudGlhbE1nbXRQcmV2aWV3Ijp0cnVlfSwibWF4TXNnU2l6ZSI6MjA0OCwicGluVXZBdXRoUHJvdG9jb2xzIjpbMV0sIm1heENyZWRlbnRpYWxDb3VudEluTGlzdCI6NiwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjoxOTIsInRyYW5zcG9ydHMiOlsidXNiIl19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDIiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNy0xOCIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiZVdCTSBlRkEzMTAgRklETzIgQXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwNzA5MDAzIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDctMTgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTA3LTE4In0seyJhYWlkIjoiMDA2RiMwMDAxIiwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhYWlkIjoiMDA2RiMwMDAxIiwiZGVzY3JpcHRpb24iOiJIYW5rbyBVQUYgQ2xpZW50L0F1dGhlbnRpY2F0b3IgQ29tYm8gZm9yIEFuZHJvaWQiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1YWYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X2RlciJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfZGVyIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfc3Vycm9nYXRlIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImhhbmRwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoidm9pY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZXllcHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhdHRlcm5faW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZhY2VwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6ImZpbmdlcnByaW50X2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJzb2Z0d2FyZSJdLCJhdHRhY2htZW50SGludCI6WyJpbnRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOlsiYW55Il0sInRjRGlzcGxheUNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6W10sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQXd3QUFBRXNDQVlBQUFCdVREUmtBQUFBQm1KTFIwUUFBQUFBQUFENVE3dC9BQUFBQ1hCSVdYTUFBQTdEQUFBT3d3SEhiNmhrQUFBQUIzUkpUVVVINEFVVUVCZ1VTZXdSemdBQUlBQkpSRUZVZU5ydDNYK01IR2VkNS9IUFU5VmQvU05HakFOUkRBdlpOcHZ4eERnM04vSEdTOUE0Q29vMm1Gc2hPWm9qV2kyQ0xBaUQ3eUNjUU1UNWcrVDI3aUNKZEFtcklCR1F3Zy90RVNJamxNTnlwSWdqNUdRUkpSYmNCaG1mTjg3RW5wQVp3QXRHUUdiUUpUUDlzNTc3d3oxSkhIczhNMTFQVlQvVi9YNUpWclNMdTZyNysxUzM2MVBQTDJPdEZRQUFBQUNjVDBBSkFBQUFBQkFZQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFCQVlBQUFBQUJBWUFBQUFBQkFZQUFBQUFJREFBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUlEQUFBQUFBSURBQUFBQUFJREFBQUFBQUFETENwUUFjOGFVRzJXOUpXanI4c0NvWm96ZUVvWWEvL05GK3dIZjMvc3ZJdlB4SU5TN09sYkhiVWZQdEkzK0dMZjBtMjNXbnFabEFRQUFDQXpvd1hGak5oVXJ1anhzYTJzUWFDeW9xRmFXcE9LNWY4LzNHMjhiYUVOZ05CSVlUU3JRWk5TOXFuOVpOV3JGT213N2VrYUJUaFdibXExWlc2ZjFBUUFBQ0F5NFVFQUk5YTRORlkyc3BmVUxaVlh5L0xtTHdaa1FJVW1xU0MrVXpMRzJkTXhJSjBZYmRwb3JBd0FBZ01Bd2xPYU1LYmNpYlpaMFZjRm8rNGFLYXJTMkZJWWFENlZ4NlV3UFJMdXR4em9GVFMrVzlNekV2RjNneWdFQUFDQXdESFJJV0NycW5aSDBsNFdLZGtXVVpQV0x2NkJkQldsWHFYR205NkVUNnlmTnR2NkYrUThBQUFBRWhvRU1DVlZLMHJNdzFIZ1lhandxU3JObE05Y0tkSkNlQndBQUFBSkRMcDJvbU0xQnJIY1h5cnErYXJyekVlQk1FS2hXa2o2ejNQUFFzSHEwMHRLelRKb0dBQUFFQm5ocnpwaHlzNktyaTdGdUxBZXFLYVFtV1FoRGpWZWw4VGpVd2t6SkhHbzJkWWdoU3dBQWdNQUFieXozSmtRVlRaVWt0dHJyazhCb0pBbzFGVlUwdGR6cnNMVnBqMUFaQUFCQVlFQmZURWRtZXpIUWRlVkFrL1FtK0dXNTEyRzJZaGJhYlgydjJOYVRERmNDQUFBRUJtUVdGTXFCUGxndGRKZENoYmNDbzVHb3FMMHFhdTlNeVJ4NHVhb2ZNRWthQUFBUUdPRGNuREhsVmtIWEZrTHRJaWprVXhScUttcG9pdUFBQUFBSURIRHFaTlhzTEpiMWtZalZqZ2dPQUFBQUJBWXNXeDU2VkFwVWs2RWVneHdjaWswZFlJNERBQUFnTUdCTlRsVE01c2pxVXd3OUdwN2dFSmQxL1V6Uk1Ea2FBQUFRR0xDeW94dk55SVlsZmJRY2FKSWVoZUd5UERrNkRyVnJPakw3V1k0VkFBQVFHUENLNVFuTkc0dmF5eDRLUXg0Y0F0V3FnVDcvZk5rY2JqVDBYVGFBQXdBQUJJWWhOMU15V3dzbGZTd0tHSDZFVnhVRFRSWXJtanhaTWc5RlRmMlFZVW9BQU1CblBQTk93ZEdOWnVRWGtmbDRGT3FMQVdFQkt5aUYrcEF0Ni82Wmt0bEtOUUFBZ0svb1lYRHNaTlhzZktQVlI0SUN5NlJpRFluZGFDUUs5Y1ZmUk9heHNLWHYwTnNBQUFBSURBTnFlVkp6aVVuTjZPV0xXTkN1T05TN1prcm1IMGNiZHBxS0FBQUFYekFreVlIcHlHeC9ZMTFmS2dhYXBCcm8rY3Y0YW0vRHgrZU1LVk1SQUFEZ0Ezb1lFcGd6cHR3cDZzUFZnblpSRFRqN1VoYTBLdzQwZHFKaXZqcTJaR2VwQ0FBQTZDZDZHSHAwM0poTnRxUTdDNFFGcFBIRkRGUXJHOTA3VXpRM1VBMEFBRUJneUptVFZiTnpRMFgzc3dJUzBoWVZ0ZmY1c3Zrc1E1UUFBQUNCSVFmbWpDbi9JaklmTDBtZm9ScklTakhRcEMzci91UEdiS0lhQUFDQXdPQ3A0OFpzaWlQZHhoQWs5T1dMYWpTeW9hTDdUMWJOVHFvQkFBQUlESjZaS1ptdDFiTHVERU9OVXczMFUwbjZ6RXpKZkpCS0FBQUFBb01uVGxiTnppalVGd1BEUm16d1F4UnE2b1dTK1FmbU5RQUFBQUtEQjVpdk1IeWFMVDB3WDlLZWh2VGxPTmFjais4eEREVnVTN3FUZVEwQUFJREFBUFRCeEx4ZDJMSm9uOXBjdDdmV3JmYTFZaDMyN3NzYnFGWXRFeG9BQUFDQkFlaXJzU1U3ZTNuZDNqZGYwcDVtUndlOCtnSjNKME5QUjJZN0xRVUFBTkxBVHM5OTBHenBBZGZIaklyYVMyWFROVEZ2RnlUdFAyN01vVkpKZjFjTU5PbkxlNnNXOVBucHlOeTl0V21QMEZJQUFJREFrSE9qTGZ1NDYyUCtzbW9JREJuWlp1MXBTZmVkcUppRGtkV25mTm5BajlBQUFBRFN3SkFrb0VkalMzWjJjOTNlMnBDK0hGc3QrQklhV0hZVkFBQVFHQUNQYkZtMFQvMnByRnZiYlQzbXcvdUpRazBSR2dBQUFJRUI4TWpFdkYzNGk2YjlSck9qLyt4RGJ3T2hBUUFBRUJnQUQ0MDI3TFNwNnhZZmVoc0lEUUFBZ01BQWVLaG1iZjB2bXZZYmkyM2QzZS9laGlqVTFFelIzRUNyQUFBQUFnUGdtYTFOZStSUFpkM2E2ZWhZWDBORFVYdlpwd0VBQUJBWUFBOU56TnVGZHpUc0Z4b2RQZFRQOTlGZGNwWFFBQUFBQ0F5QWo3WTA3TUYrRDFHcUZ2VDVFeFd6bWRZQUFBQUVCc0JEVzV2MnlHSmRkL1J6aUZJazNYN2NtRTIwQmdBQUlEQUFIdHBtN2VtZ3FYdGFzUTczNVF0dk5GSXQ2ODQ1WThxMEJnQUFJREFBSHFwWlc3KzhidTlyZG5TZ1g2RWhqblFib1FFQUFCQVlBSStOTnV6K3hiYnU3c2U1dzFEam5hSStUQ3NBQUFBQ0ErQ3hyVTE3cEYrN1F4Y0syc1VlRFFBQWdNQUFlRzYwWWFjWDY3cWpINkVoS21ydlRNbHNwUlVBQUFDQkFmRFlObXRQOXlzMEZBSjlqcFdUQUFBQWdRSElRV2pveDg3UWdkRklKZElubUFRTkFBQUlESURuSnVidFF0RFVQVm1IaGpEVWVDdlNGQzBBQUFBR05qRE1HVk0rdXRHTTBLVEl1NXExOVg2RWhpalVGUE1aQUFEQXdBYUdUbEVmcnRTMWtTWUZvYUYzaFVDZkkzZ0RBSUNCQ3d6VGtkbGVLR2dYelFsQ1E4SWZCS09SRFV2NktOVUhBQUFERXhpT2JqUWo1VkNmcENreHFLRmhxYW12WjdsNlVqSFFKUHN6QUFDQWdRa01HNWIwMGNDSUlSUVlXUDFZY2pVcWFpOUxyUUlBZ053SGhwTlZzN01ZYUpKbUJLSEJ2VXFrVDFCNUFBQ1EyOEJ3ZEtNWktWcDloQ2JFTUlXR2VrZGZ5K3A4WWFoeGhpWUJBSURjQm9ZM3ZLeWJHSXFFWWJPMWFZODBwQzluZGI1Q1FYL0xxa2tBQUJBWWNtZW1aTGF5S2hLRzFaWkYrMVN6b3dPWi9FQ3dhaElBQUFTR3ZMM2hPV1BLQmFPUDBYUVlacU1OdXorcjVWYUxnU2JaMEEwQUFBSkRiclFLdWpZSVZLUHBNUFJmM3FidXlXb1NkQ0hRNSthTUtWTjFBQUFJREY0N3V0R01SRVh0cGRtQU0zczBMTloxUnlZL0ZFWWpyWUt1cGVvQUFCQVl2TVpZYXVCczI2dzluZFVrNktpb3ZVeUFCZ0NBd09DdEV4V3ptVDBYZ0hOdFdiUlB0ZHQ2TEl0enZlRmwzVVRGQVFBZ01IZ3Bzdm9VelFXY1g5alNkN0tZejFBb2FOZUppdGxNeFFFQUlEQjRaVG95MjVub0RLeXNabTI5S2QyVlNUaXh1cEdLQXdCQVlQQktPZEFIYVNyZ3dzYVc3R3lqbzRmU1BnL0xyQUlBUUdEd3lzbXEyVW52QXZJdXF4dnNxS2tmeHJIbTBqNFBlNkVBQUVCZzhNS2NNZVdpMVVkb0p1U2RNWHJmVE1sOE1PMjlER3JXMXB0R1gwMzloeU5RYlRveTIybFpBQUFJREgzVkt1amF3SWhsSERFUW9sQlRjYVRiMGc0TldRMU5ZcWdnQUFBRWhyNHJoTnBGRTJHUWhLSEdzd2dOV1F4Tm9wY0JBQUFDUTEreE1oSUlEYjJyV1Z0dlczMHI3YzlTTW5vL0xRb0FHRWJHbUl1Tk1aUEdtSnVOTWZjWVl3NGFZK3dxZjc3Ui9idFR4cGdKWTB5RndKQUF3eDB3NktHaFhkSi9UUE1jb3cwNzNZcDFPTzNQd2I0TXp2OEJ1bWNOLytDczltZExYcy92NlEyQlRlblBMVnkveGhwakRxYjBYcllNNG5Yc3czZlVRVzJYLzl5YzA5K0VxZTUxKzBkSlQwbjZ0cVI5a25hdjRSQjd1bi8zKzVKK0xtblJHUFA1YnZEd05qeDRHUmpvWGNBdzZDNVBtbW93YmpUMDNkVEREL3N5WUxDOU9jVmpYMFo1SlVtN2pURnZvd3k1Y28yajR4ektXVkM0cFJzU3ZyL0djTEJXZDNXRHh4UGRNT0pkY0NoNGVpTjFIZDlGclBXR3VGT1cwNmRUU3hzMG45WDdqMEpOelJUTjcwZGI5dkUwanIvTjJ0TXpKWE1nQ2pXVlp2QTVic3gzdDFsN21pc1NBNmlXNHJIZlEzbGZjYU9rK3lsRGJyajROK1VSYSsycG5JU0ZxVzVJU051Tzdua2VNY2JjWnEwOVNXQll3WW1LMlZ3T05NbDNFV3U5SWM3N1o0aUsyanRUTXFkR0czWTZsUnY2cGc3RVpWMmY1b3BqVWFUckplM25pc1FBMnBEeXpRSE91Sm5Ba0EvZDNpQVhUOWNQNU9DelhpenB2K3ZNTUtJczdkYVpucmQvYjYzMW9rN2VEVWtLWXIyYnJ5T0dUU0hRNTQ0YnN5bU5ZOWVzcmJmYitsNnFvU2ZVVk5vclB3RjljazJhQngraytSNUp3NU14Wm9JeTVNTDFqbzdqOVhDa2JqRDZZUi9Dd210OTM1ZTVUbDRGaGpsanlta09uUUI4RlJpTlZDSjlJcTJiN21KYlQ4WldDMmwraG1aRlY5T1NHRUFiVXo3K0paVDRGVHNwUVM0TS9IQ2tibGc0SUQ5NkFiL2l3K1J3cndJRE54d1labUdvOFdhazk2Vng3Q3g2R1lveGs1OHhrTkordW5ncEpYN0Z6WlRBYjhNd0hLazc0ZGlYc0xEczIvM3VnZk1xTUhERGdXRlhDdldodEpZcFRidVhJUWhVWTRsVkROak4wY1Vabk9ZS0t2MktIY1lZNWpENmJSaUdJLzAzK1RtLzZPc1ovU2I1SFJoT1ZNeG1sbElGcE1qcVUya01UYXBaVzIvRmVqVFZIeFRtSUdHd3ZEbURjeEN5ejhZcWlYNGI2T0ZJeHBqMzZzd2VDVjRHYWtuL1llZ0RBemNhUVBlN0VLaldLdWphTkk2OVdOV1BVdzA3VEg3R1lLbGxjSTQ5bFBrc2QrVmw1OXRoTStqRGticlgzWjA1K0g3MFphRUVMd0xEbkRIbFF1Q3Ntd3ZJdmFpb3ZVYzNHdWZMb0U3TTI0Vm1KOTBmNjZXaTNra0xZa0JzeU9Jay9SeG00S250bE1CTGd6NGM2V1BLeDFMSGZYbkk0RVZnV0NycW5XbXVFUS9rMFJ0ZTFrMXBIRGNPOUpNMDN6Y2JMMktBWEpQUmVkNU1xYy9DYjRpZlhQUjhlemtjcWR1NzhKV2N0TU8rZmp4azhDSXdSTkpmOGowRXpsWW9hRmNhazRqSGx1eHNwNk5qS1FhR3lUUjZSNEErMkpqUmVXcVUraXgzMGV2aTNRMzF4WEx6Wk52WDFaSCtYYzZhNVAxREZ4am1qQ2tYQ3RyRjF4RTRWMmpUV1Rtc1lkT2QvRnh0NkVwYUR3TWdxNjcvVFpUNkhDeXpQcGp0NGV0d0pKZEwrajRpYVpla3NkZjh1VXJTcHgyZUkvTTl5L29lR0JqdkRLeXNHR2d5alY2R1NrdlBwdm0rQ3gzbUpDSGZNbjdDVGNBKzEwMlVZT0RhdzlmaFNLNG1jMHZTMzF0cmI3VFcvc2hhZS9JMWY0NWFhKy92aG9lbkhaeG5kL2Q5RDA5Z1lEZ1NzT3JOOTErN1BtYk4ybnFhazUvRFVPTU1TMExPWlRtdllBdmxQc2NlaGlWNUZaNEhlVGpTWHprNnpxZXR0UTllNkM5WWEwOUsrb1JuNzl2L3dNQndKR0FOZ2FHZ1hTbmRmUDg4emZkZGVsbnZvUFdRWTdVTXo3V2JjcDhYdzVJR3F4MThIWTdrWXY3Q0k1Syt0WmEvYUswOUt1bGVCK2U4SnNzaTlUVXd0Q0kyckFIV29ycW85N2crNW1qRFRxZTU4ek85aDhpNURWbWVyRjlycTN2dWs1VEFDd003SEtuTFJlL0pnOWJhcFhVR2pLUXkzV0N1MzBPU3J1SjdDS3l1R0tTeklrSTdUdStKRDcySHlMbHJNajVmbFpLZkkvTngyamdueUE3MGNDU0hRZjNINi96N1J4eTkvOHkrSDMwTkRBWEQ1aXpBbXI2b1JpTXpKYk0xaFVPbk9pd3BwZmNNWkdGanh1ZGpDTi81c1lCQ2Z3MzZjS1NhZzJNOFlxMTljVDB2NlBaR2ZOUEJ1VE9iYTlXM3dIRGNtRTFCd05yVHdEbzQ3NUVyTmpXYjVodTJaMWFFQVBJbzY5MVUzMHJKejJ1S0V2VFZvQTlIY3JHazhULzMrRG9YLy81bTlxQ2hiNEdoV05IbGZBK0J0WXRDOS85dzFxeXR0MklkVHUxN2JyU1Rsa1BlOUdsMW5zdW8vSGt4TEtsLzM0T0tCbnQxSk1uTmtzYlBaZnk2MThyc1FVUGZBa1BZRmtNVmdIVktZNGlQN2VpWjFINWdBdFZZWGhVNWxLU2J2OWZKalBzbys0b1lsdFFmcm9hTkgvTDRNN29ZZXZpN0hsLzNrb056Wi9hZ29kQ3ZGZ3BDdll2dm90L0tSdmYrc21xRzduTTNXM3BndEdVZjkvVHRYU1ZwMnVVQjQ0S2VUL01OZDVkWFBjSTNDamxTUy9EYUI5WGpNcW5HbU1vNlYxb1pGcmQwNjRwc1hlZmdHRDRQUjVMYzlLRDh2c2ZYemVYcFl1aExEOE54WXpZRlJqeDFCTmFiOEZOWUtHQnN5YzZtL0o2dm9PV1FNMG1XVlAxZGd0ZStuZEtmMXc1anpBUmx5RTUzT05KZERnNTFnR3FtS3JPZXliNEVCdVl2QUQxK1lWTWE0cFBtUElaUWZOK1JPejB2cVdxdFRmSmRxbEg2RlRFZktsdkRNQnpKbFQ4TXhmMUhQMDdLL0FXZ2QybnNvSnptUElZdzFQaWNNV1ZhRGpuUzY3am1wN3YvN1hVZXd3Wkt2NktiS1VHbUJuNDRrcXM5R05hN3BDcUJZVDBuRFZocUVlaFZLa044QXFYNm85NG82eTIwSEhLazEzSE5QKzcrOTJTUHI3K0cwcStJWVVuWjNVZ3pIQW45RHd4enhwVFpmd0hvWFJwRGZGNnU2cmVwL3RDMEdaYUUzTndzSlZsU2RhSDczMS8xK1BxTnRNQUYvUTBseUFURGtkRC93TUNUUmlCaFlBZzE3dnFZRS9OMklkVWZHc05EQXVSR2tpVlZsOWRWLzAyUHI5OUQrUy9vcnU3VGI2UnJHRlpIZ3UrQmdTZU5RSExIamRuaytwaHBUbnhtR0NKeUpFbTRYVjVYL1lWZUQ4QW1aYXZhVGduU3czQWsrQk1ZZU5JSUpCWkY3b2N1bU5qSkpqSXJCWVlhRTUrUkUwa21IczkxLzd1WTRCaFZtdUNDcnFNRXVRaGtERWNpTUNTK2NlQkpJNUJVTE9kUElXT2I3aVl5REVkRVRyaVllUHpyQksrOWtpYTRJSVlscGVzcUI4ZGdPQktCd1VsZ3FGRjJJUEUzOXhMWGg3UkZwYnJEckRINk14b09PZEJ6NzUyMTltVDN2MG0rUzIrbENWWjFMU1ZJall2bGF4bU9SR0JJSm8xeDE4QXdNa2FYT2c4TVZ2K2E2cHZ1SkpwTUNtVEYxY1RqZTN0ODNXVTB3YXB1b2dScC9MdGlKaVR0Y0hDb24xSk5Ba01pYVl5N0JwQ1RIeHVqelZRQm50OHdKVmxTOWZVQm9kZVZ4OTVEUzZ3ZTZoSzJGYzdQeFc3YVR5LzN0SUhBMExzVXhsMER3NmdZYU5MMU1VdjFkUGRpQ01XUUpIalBaUy9ZY3oyK2JnZk5zQ1pYVXdMblhBeEhlcEF5RWhoY25PMFNTZzc0cVdadFBkV3ZQL09Ya0lPdlFZTFh2bjRZUnMrcmpobGp0dEFVcTJKWWtrTU9oeU05UlRVSkRBNHVTUGZqcmdIa3g5R05ab1Fxd0dNYkhCNXJMc0ZyZWJpMnVqM3NXZUdVcStGSVJ5a2xnU0V4aGlRQTd1UnhFWUZLblhsTThGcVNKVldmZWQzLy9ZY0V4K0xoMnRwY1R3bWNZVGdTL0FrTURFa0EzQ21VbGJ1MXlPTU9nUUZlYzNaOVdtdGZUUER5SzJpS05abGE1WDlmcEVTcll6Z1N2QXNNQUlZODVGaTlpU3JBWXowdnFickN5akNQOUhnNFZoUmJtOTBYR3BiRTVtRnJ4bkFrK0JNWVRsUU1QNEFBQUMrbHRFeG5yOHRMN3FGRjFveGhTY2t4SEFuK0JBWUFNS0d1cEFyd1ZKSWxWVmZhcE8wWnp3TE1JTHFGRWlRS3ltOFR3NUd3Qm9YTWtrbXNza0lLbnBZL1g3UWZvQW9BMExOYUNzZDhLY0ZyM3l6cHhTRnJnOXNsM2JYTzErd3d4a3d3SEtabkxucG9HSTVFWUhBbzF0c0lEQUNRaVJQR0dLcXdQa21XVlAzcEN2Ly9GeElHbUdIYk1iZlhPUWM3SlhIRDJwc3BCOGRnT05JUVlFZ1NnTXlFUnR1b0FqeDFUUXJIVExKS3o2WWhiSU5qa3A3dTRYVTNjL211WDNjNDBtNEhoMkk0RW9FQkFCeis0Qml4Y1J0OGxXUkoxZlBPVlZoaDVhUzFHc2I1UG92cTdXbjFqdTdTb09melRTN3RGVEVjQ1FRR0FBRFd3YmVWaWJZTWFUdjArclI2cGFWQjU3bTBWOFJ3SlBnWEdGZ2RCUURnSXdjckV2MzZBdi9idlQwZWMvY3d0a1gzYVhVdnc1SytZb3lwY0RXdldVME1SNEtQZ1FFQUFFOGxXVkpWMXRxbEMvelBDd21DekxEMk10emY0K3UyY3ltdjJVME9qc0Z3SkFJREFBQkRvNWJndGF1TmtYOHV3YkdyUTlvZWgzcDgzWFZjeW12bVlnZ2V3NUVJREFDUWpqbGp5bFFCbmtteXBPcHFZK1IvbCtEWTd4aXlkcWhLa3JYMmxLUkhlbmo5WFF4THloVERrUWdNQUpDT1JsbHZvUXJ3ekJVSlhydmFiczYvVDNEc3R3NVpPN3cySUIzbzhSaXZINWEwd09XZENvWWpFUmdBQUJncVNaYjdYVzAzNXo4a09QWmxROXdtai9iNHVvKzg3djkranNzN0ZReEhJakFBQURCVTlpVjQ3UVYzYzdiV3Z0aW45NVZyM2JyMXNvZkNIZ2VyWG1GMVA2Y0VCQVlBU0UyN3JpV3FBRjg0R1BPK2x0MmN2OW5IOTVkbkQvZjR1cXU1c2xOM0ZTVWdNQUJBYXJaWmU1b3F3Q052VC9qNlg2L2g3OHozOGYzbDJjOTZmTjFOWE5hcFk5OExBZ01BQUVQamtpUXZYbVVQaG1YUEpEaEZiVmdicGpzczZmWWVYc3F3cEd5dzd3V0JBUUNRWTJQV1d0UExIL1crTTNGZVhacmd0V3NkYXZSU2duTnNHUEpyK1lrZVgvZCtmZ1pTeDc0WEJBYjNUSnpvQnhNQWdEUWtXVkoxclVPTmt2UXdYRFBrYlhHa3gyTk5PYWc5THV3dWVuSUlETTdGVm5PVUd3RGdtU1JMcW1aeE03cHhtTnVpTytTcmwyRkp1NDB4YitQeVh0RTNIUjJIQ2VZRUJnQUFCbDZTcFV2WDFITnVyVDJaNEJ4N2FDTDlvTWZYWFUvcFZ2Uy8xTnR1MnEvSEJITUNBd0M0MWVub0dGV0FMeHlzOHZLN2RmemRweE84ejZGK1V0N2RVYmlYK2sxeGxWL1FBUWZIWUlJNWdRRUEzSXFOL2g5VmdFZVNMbG42KzNYODNSOG5PRStWcHVwcForSGRHcTQ1SU90MXlORnhtR0ErQkFxWjNTZ1U5RHpsVHM5TTBkeEFGZHhkcTJOTGRwWktBQVB2a29Tdi84TTYvdTZ2RXB6blNra25oN3l0ZnRUajYraGxXSUcxOXBReDVwRnVzRXBpcXNkQUJ3TERBTjA4eHBvTEF2L1h3WTZLMmt0cnVkRnM2UUZKQklaVS9vRmExeEFPSUcyWEpydWU3WXZyK091L1NYQ3F0L0xiWVUvMmVITzdtOHY4Z2c0NHFORnVZOHpickxXbktPZmd5bXhJVXJ1dXBUd1dxQ1A5SzVjSjRDcUJyMnNJQjVDMkpFdXFybmZDYUpLd2ZObVF0TWRxSzBJZDRKSjF6dFd3cEJzcEpZSEJpVzNXbnFiY0FBQ1BKRmxTZGIxRGhKS0U1ZmNNU1h1c3RpTFVJUzVadDdxOUFpNldXTDJaYWhJWUFNQUo1akxCTTBtV1ZGM3ZuSVJmSnpqWERwcnFsWnZiUjZpRWN3ODdPTVlPWTh3RXBTUXdPTkdLZFppU0F3RDZ6Y0dTcXV1YWs5RGRnQ3pKKzkxQ3EwbVN2a1lKblB1Wm8rUHNwSlFFaGx5SU8wTzFJeWFRTzZXNmZrc1Y0SW1rUzZyMk1pY2h5ZENQUzJneXB6ZTNlRFhNdmlnM3c1Sys0aUNJZzhBZ3hUYmRsV2NLVm05eS9rWHE2Qmt1RThDTm1yVjFxZ0JQSkwwQjcyVk93bnlDODExS2t6bTl1Y1haSG5aMG5PMlVrc0NRWExpdU5hc0JEQkNHSk1JelNXL0FlL24zN0tjSnpuY0ZUZWI4NWhhdmV0TFJjYTZqbEFRR0IwOEcwbDJpMUFhNnlQa3hpL2xjRGhid2pZbjFFbFdBUnhMZGdLOXpEd1lYTnROa3ptOXU4ZXIxdkNUcGRnZUh1c3NZY3pFVkpUQWtzbFJPMUIyNytvY3g3bjlRMHc0NXdMQ0lyZWFvQWp5U1pFblZYbGZxU1RMRWRROU41dnptRm1kN3d0RnhycWFVQklaRUp1YnRBaVVIaHZiWGhsMUE0Wk1rUzZxZTdQRjFpMG5lTUU5dVU3bTV4YXVPT0RyT1RaU1N3SkJZbXVPWWk0RW1YUjl6Yk1uT2Nwa0F5VFdiNmZZd0F1dTQ4VTY2a3NzK1k0eGQ3eDhsMjR0Qmt0NU02NTExYy9zMFpYREhZYy9OSHNJdGdjSEJCZG5UVW5Sck5tZE0yZlV4NDVpaEZFQlM3UFlPajd3OXArKzdSdE9kZFhQN0lKVnd6bFhQemZzcEpZRWgyWmM4WFBmdW1PdlNLT3N0cm8vWkVmTVlnRVRmb1k2T1VRVjRKSzk3R215aTZjN3lGQ1Z3SHNRT3kwM1B6UlRWSkRBa3ZCalR2ZmsyUm4vbS9EMnpGd09RTkhRL1R4WGdrYnp1YVhBbFRYZld6ZTFSTVN3cERTNTZiblliWTk1R0tRa01QVXQ5VGtBbmhUR2VUTllFRW1sYlBVY1Y0Skc4N21td2hhWkw1ZVlXWjNQVmMzTWpwU1F3Skx1blQzRjRRaHBMcTc1YzFXKzVWSURleFMzOWhpckFJeU01ZmQrN2FicHpIS1FFYmpuc3VibVphaElZRW1rcnZjQ1F4a3BKRS9OMmdZblBRTytZOEF6UDdNdnJHMmVZeHprM3Q2ZlUrNzRZV0ptTG5wc2R4cGdKanovakgyaG16d05EeDZZNzhmbEV4VGp2WldoYlorc1RBME1semFXVWdSNXV1Q3M1L3dnc3JYcXVBNVRBdVI4NU9zNU9qOE9tazkzYWpURkRNVlN3TDRHaGNaRmVTUGNmQlBjVG54bUREZlQ0bzh5aUFmREwyM1ArL3Q5QkU1N2pVVXJnL0diNnBOejAzSHhsQUVLNnp6THJYU3YwNDlOTnpOdUYyYktaQzRKMDFwUU8yOW9xeDh1dE5TN1NDOVdHdjFmTXNEN0ZUV01JR3R5S0M2eVFCSzlja3ZQMy8xYWE4SnliMnhlTk1kK1V0SWRxT0hWQWJ1Yk5iSmZvYVU3SnlheE9WT2pYSjJ4YkhZbFMyb1FtQ1BVdVNkOXdIWEplS0psallhaHhINitZeSt2MnZtSDhwdnl5YWdnTW5tTzNkSGptMHB5Ly84dG93dk42bU1EZzNDRkh4N25PNDhCd3IvbzNweWxYeXlRSC9UcHhta044QXFPUlZPWXhoTTYrUE1CUVlQNENQSFJGenQvL1Bwcnd2SDVHQ2R4eU9LSDhMbVBNeFFOY3FuN2UrR2MyNUxkdmdhSFMwck5wSHQvRStyZXVqN2xZWWl3MnNCNXh3S1pLOE01STNqOEFZOExQZTNQN29zNDhMWVpicmlhVVgrM3A1K3ZuZloyTDRZVXZEWHhncUZsYlQzTS9ocUp4UHpOL1l0NHVwUG1lZ1VIVFdtTCtBcnd6Q0UvbzMwNHpuaGZMcTdybmFrTDVUWjUrUGhjMzNMMzJXcm9ZWHZoQ1ZvVUsrdGxLblZnL1NlMkRCYW9kM1dpY1AwbHFXRlpqQU5ZaWpqWEgvZ3Z3aVlzbjg5WmFrL1NQcExHRWIrTVNXdk84V1A3Y3NXN1B6VGNkSEdxUHAzdUl1T2hoK0tzZVgvY2VCK2ZPYkMrSnZnYUdabHYva3VieHF3MzM0OG9xTFQwYld5M3dNd0pjR0h1WHdFTkpuOHk3ZW9LZDlCLzVTMm5LODk3Y0xrbTZuVW80OTdDajQxenY0V2Y3dFlOajdGN3Z3NGh1ZU5yaDRKby9OUlNCWVp1MXA5UGNRYmtZNjBiWHg2eFpXMi9IVEg0RzF1RG5sQUNlU2ZwazNza1NoZzQyakxxR3BselJEeWlCYzY0bWxFOTVHakpkUEFqWXZzNi8vMDRINTh4MHprN1E3OFpLOHlsa0VLaDIzSmhOcm8vN2NwVWZKT0JDWXF1RjBZYWRwaEx3VE5Jbjh5NTdsNVBjcEd5a0tWZThBVHdxc2RpQzQ1cTZHcGEwMjlOZGtmKzNpOCsyenIvL1NRZm4vT2xRQlFhbC9CU3lHTGwvRWpNeGJ4ZWFIYmFpQjFaOEVFQXZIUHlVZEVsVmw4dUJKK210WUwrQkMzdVFFampuYWxqU2V6MzhiQzd1US9jWll5Ylc4aGVOTWUrVm13M3hNbDNocWUrQlliUmhwOU9jRTFBTTlQNDBqa3N2QTlDL0J3RkFqNUl1aE9GeUNjTkUvOWg3T29IVUYwOVJBdWVlZEhTY216MzhiSzVHdW54OXRkQmdqSm1VOUppRGN6MXRyVDJaWlpGODZHRkk5V2xrWURReUhabnRybzlMTHdOd2ZneEhnc2VTTHFrNjUvQzlKQTBmVlpyei9MckRrbGhpMVcxTlhVMG8zN0hXSi9GNS9HeVNmbTZNdWNjWU0ybU0yZkthUDVQR21Ic2NodG5NZTlHOENBek5acnJERjRxQnJrdmp1UFF5QU5rK0FBQjY1V2l6czBXSGJ5bnArdWxYMHFvWHhBTTk5NTV3ZEp5LzhmQ3p1YnlmMjljTkJpZGU4K2NwdWQwREp2TmVOQzhDUStxckpRV2FUR1B5ODhTOFhXaTI5QUMvSWNDcjRpQzkvVldBQkJKdmR1WjRDY09rNFdNRFRYcEJQTGh3ejlYUW5idDgyNjA4WjcxU2ozVGY3L0FGQmtscWQ1eU02VnBSRktXei9tK3hyU2ZURER0QXJzSkNyTG14SlR0TEplQWhyelk3Y3pEK21CNkcxY01kdzVMYzF0VGxQaGZiUGZ5SVg4dEpVOXpiajVONkV4aGUzcER1TW1oUnFLazBkbjZ1V1Z0dkduMlZueElnL2VBUEpKQjBTZFY3UGZzODc2RkpCK1lHTUU5Y0RVdmE3ZUZuZXpJSElmTVJhKzNob1E0TUUvTjJvUlVyMVNKY3RKak91TG14SlR2YjZPZ2hma2N3N05JTy9rQUNWM2o0bnBLRWtCMDA2YXArUmduYzZ0NnN1dmlkMzJlTXVkaXp6N1lrNmI5NjNnUjllM0FSK0ZTRlZ1d3N1WjVYV3IxcmNITzFBQUFMcFVsRVFWUU1raFExOVVPR0ptR1l0ZHQ2YkdMZUxsQUplQ3JwYi85UGZmdEFubTZDNWRNTm9Lc054M0EyVnl2MFhPM2hOWE5VN29aZE9ROEwvZXBkOEM0d2JHM2FJMm5mZEtmVnkxQ3p0cjdZMEpmNEhjR3dpZzFybjhOcit6eDhUMGxEeUNVMDY2b2VwZ1RPdWZxdHY4blR6M2VmL0J1YTlMU2svOUxQTnhENDFrcXBUMzVPc1pkaG03V25HOUtYK1MzQjBJV0ZXSFBzdlFCZk9WcVJKWTFkVlpQdXhYQXByYnVxSnltQlc5Mm44QzZHSmUzeGNRUEM3dENrV3h4OVJsZGhZYXI3dmdnTXk0cnQ5TC9jYWZVeVNOS1dSZnNVRzdwaDJMUUNIYVFLOE5qYlBYMWZjd2xmZndWTnU2YWJ2OXVwaEhPdWhpVmQ3K2wxYzByU2xBZWhZVGtzbk9wM1RRcStOVkxOMnZwTXlSeUlRazJsZFk0bzFOU0ppdmxKV3NzL2pqYnMvaGRLNXZJdzFIaFdkWnNwbWh0Y0gvUGxEWHFhTWVsWVRXeTFFTldaWEFpdnVSaTY4K3NVM2xmU3ZSaEdhTm8xZVlJU09QY2pSOGVaVWg5MkxWNXJhRERHVE9uTVVLQTl3eHdXdkF3TTBwa2RsS05HZW9GQmtrS3JHM1ZtbkZvcWdxYnU2VVM2TGF2UUVCVzExL21OWUYzUFN5SXc0SUphc1I3ZFltMmRTc0JqaVlmdXBERWNvSHREa3VRUSt5VGRSdk91NmdnbGNIN3RualRHUEtMa3k2UHVOc1pzY2JBdlNacWg0VC9wek5DMmIyZDQ2dHNsM2RmdllVaG4zZGY2MkVCWkxMRmFERFE1SFpuVU5nNnBXVnNQbXJvbnR0eHdZN0F0VnZWanFnRFBKUjI2aytaS080a21WL3EyTktXbk4zMUxrajVOSlp4ek5mejZ2YjVmUDliYUIzVm1hR1BheTVyZUsybk1XbnUzVDJIQjI4QWdTUjJUL3Bqb2NxaFB6aGxUVGpNMExOWjFCNkVCZzZyWjBRR0dyU0VIa2c3ZG1VL3h2U1Y5c3ZwbW1uZE5XTVhOdlVPT2puTnpUb0xuS1d2dGJaTGVKT252NVc0bHBhZTdnWGJNV251YnI3MHR4bHJyYmVNOFh6YWZMUWFhVFBNY2pZNGUydEt3cVlhVDQ4WnNxcFoxWjJETy9LUDE1NHYyQTY3UDhjdXErWit1ajFtMzJwZldQQStmUDNlenBRZEdXL1p4MzYvbE5OcG52ZldjTDJrUGdRRUFNSXk2cXp5OVU5SVdTWmZwekE3c3EyMnFlSy9PRFBkK1R0SS8rekpIWVRVRm45OWN4K2hnVWVrR2hsS29ENTJvbVArYjVvM3hObXRQSHpmbWptcEp0d2FCYW56Rk1Bam9YUUFBRExQdXpmNHB1WnNFN3EzQTV6YzN0bVJuMDU3TElFbkZXQjlPK3h6YnJEMXRHcnFqMDlFeHZtSVlCQzlYOVFPcUFBREE0QXQ4ZjROWnpHVUlRNDJuc1N6cDY5V3NyYitqWWIvQVpZZThvM2NCQUFBQ2d6ZXk2bVdJaXRwN29tSTJjMGtBcTZOM0FRQUFBb05Yc3VobGtLVEk2bE5wcnBvRURJSkdSdy9SdXdBQUFJSEJLMk5MZHJiWmNiYmU3OHJGQ0ZSclJlbHVHQWZrV1d5MUVEWDFReW9CQUFDQndUdFpEWUdJUWsybHVhRWJrR2Z0dHI1WFkxZG5BQUFJREQ2YW1MY0x6WllleU9KYzVWQ2ZQRzdNSmk0UDRGVnhyRG5YKzFNQUFBQUNnMVBGdHA2TVk4MmxYaFNqa1Vxa1R6Q2ZBWGhWMCtpclZBRUFBQUtEMTJyVzF0dFczOHJpWEdHbzhVNHgvZjBaZ0R4b3hUcnMrNjdmQUFDQXdDQkpHbTNZNlN5V1daV2tRa0c3c3RpZkFmQlpiTFh3VWtYL1JDVUFBQ0F3NUVhV055OVJVWHVaQkkxaDFtN3JleXlqQ2dBQWdTRlhzcHdBTFRFSkdzT3IwOUV4SmpvREFFQmd5S1hSbG4yODA5R3hUSXBrTkZJdDYwNUNBNGJOVWxOZnB3b0FBQkFZdUpsWlkyaGc1U1FNazJaTEQyeXo5alNWQUFDQXdKQmIyNnc5bmVYUXBERFVlQnpwTmtJREJoMURrUUFBd0VBRUJpbmJvVW1FQmd3TGhpSUJBSUNCQ1F6TE56ZXhWV2FydUxCSEF3WVpRNUVBQU1EQUJZWnQxcDV1R2YyUExNOVpLR2pYVE1sOGtFc0lnNlFWNnpCRGtRQUF3TUFGQmtuYXNtaWZhcmYxV0pibmpFSk5FUm93U0M2djIvdW9BZ0FBR01qQUlFbGhTOStKWTgwUkdnQUFBQUFDd3pscTF0WVhHL3BTMXVlTlFrMjlVREwvd0VSb0FBQUFFQmc4dDgzYTA0dHQzWjMxZVZrOUNRQUFBQVNHbk5qYXRFZWFIUjBnTkFBQUFBQUVodk1hYmRqOVdlN1A4TnJRWU11Ni83Z3htN2k4QUFBQVFHRHcrY00xZFUrVyt6TzhjbDZqa1dwWmQ4NlV6Rll1TVFBQUFCQVlQRld6dHI1WTF4MzlDZzFScUM5T1IyWTdseGtBQUFBSURKN2FadTNwZHF4LzdOZjVxd1Y5bm1WWEFRQUFRR0R3MkdqRFR2ZGo1YVJsTExzS0FBQUFBb1BudGpidGtVWkhEL1hyL011VG9VOVV6R1l1T3dBQUFCQVlQTFNsWVEvMlk3blZWNHB0TkZJMnVuZW1hRzdnMGdNQUFBQ0J3VU9qRGJ1L242RkJrcUtpOWo1Zk5wODl1dEdNY0FrQ0FBQ0F3T0JoYUdpMzlWZy8zME14ME9RYjYvb1NTNjhDQUFDQXdPQ2hzS1h2OUdOanQ3T0szMTE2OVJlUitUZ1RvZ0VBQUVCZzhFak4ybnJRMUQzOURnMlNWQ2hvbHkzcmZub2JBQUFBUUdBZ05KeS9JVjdUMjhEY0JnQUFBQkFZUEFzTi9aNEl2YXhRMEs0MzF2VWxWbElDQUFBQWdjR2owT0RENmttdk5JclJTRlRVM3RteVlWSTBBQUFBK3FwQUNWNDEyckQ3WjBwR1VhZ3BMNEpEb0Zva2ZmSDVzam5jTVRvNHRtUm5hYVVNdmhTaGRqMWZObGU2UEdab3RJM0tBZ0FBQXNPZ2hJYWkrWDFVMUY1ZjNsTXgwR1JSbWlRNFpCZlVBcWxHSlFBQUFBZ001dzhOTGZ2NGRHVCtXQzNvOHo2OXIrWGc4RUxKSEd0WVBWcHA2ZG1hdFhWYURBQUFBQVNHakcxdDJpTW5LbVpmSk4wZUdIbTFhbEVZYXJ3cWpjZWhGbVpLNWxEYjZya3FMVGwwMm5VdFVRVUFBSkEySmoxZndOaVNuVjJzNnc0ZmxsMDliK09kV1lwMXlyZWVFS1J2c2EyN3QxbDdta29BQUFBQ1E1OXRzL1owME5ROXJWaUhxUWI2TGJaYWVHbEp0Mnh0MmlOVUF3QUFFQmc4VWJPMmZubmQzdGZvNkNHcWdYN3BkSFRzVDJYZFNzOENBQURJRWlQZjEyRkx3eDZjS1prVGhVQ2Y4MjFlQXdaYnM2TURvdzI3bjBvQUFJQ3MwY093VHFNTk8vMm5zbTcxZFY0REJrdHN0YkRZMXQyRUJRQUFRR0RJa1lsNXUvQ09odjBDUTVTUXBrNUh4eGJydW9QNUNnQUFvSjhZa3BRQVE1U1Fsa1pIRDIxcDJJTlVBZ0FBOUJzOURBbU5OdXkwcWV1V2RsdVBVUTBrRmNlYXExdnRJeXdBQUFCZjBNUGdRSGUzNVcvTWxNeFQ5RGFnVjQyT0hvcWErdUVZdTNjREFBQ1AwTVBnRUwwTjZNVnJleFZxaEFVQUFPQVplaGdjbzdjQjYwR3ZBZ0FBSURBTXFkR0duWjR6NXBaR3BQZVZRbjJJaXVDMU9oMGRXMnJxNjJ6Q0JnQUFDQXhEck52YmNQQzRNVDh0bGZSM3hVQ1RWR1c0eFZZTDlZNit4bEtwQUFDQXdJQlhkSjhpM3pjZG1TZktnVDRZQktwUmxlR3pQUHhvSzhPUEFBQUFnUUhuMDMycWZHU21hRzRvRlBTM3pHOFlEczJPRHJ4YzFROG01dTBDMVFBQUFBUUdyR3EwWlIrZk0rYkpaa0hYRWh3R1Z5dlc0WTdSd2JHR25hVWFBQUNBd0lCMTZjNXZPQk1jSWsxRm9hYW95dnJGVmd1K0JhNVhna0tkb0FBQUFBZ01jQk1jOWgvZGFINXcwVXZhUVkvRCtuU3NqZ2ZHajhua0JBVUFBRUJnUUdxNjQ5c1pxcFJEelk0T3hJRitRbEFBQUFBRUJxUnVlYWlTcE1lbkk3T2RWWlg4RkZzdHRHSTl1bGpWajVuTURBQUFDQXpvaStWVmxVNVV6T1pDUjM5ZEtHZ1hWZWx6VUlnMVY0KzF2OUxTczF0WUhoVUFBQkFZNElPeEpUc3I2UnRITjVxSEwzcEpPd3FoZHRIcmtHRklzRnBveHpyRXNDTUFBRUJnZ05lVzV6bElldnhFeFd3T1lyMjdFT2g2NWpxa294WHJjQ3ZXRTVXV25oMmxOd0VBQUJBWWtDZmRYb2RaU2Z0blNtYXJwS3NJRDhsMU9qcldEblZvc2FSbm1Kc0FBQUJBWUJnSW93MDdMV21hOE5DYlZxekRjYUNuQ1FrQUFBQUVocUVLRDhlTjJSUVY5Ry9DUU84T1E0MVRuVFBpV0hOdHF5T1NmbDVzYXZaeWhoc0JBQUFRR0liUk5tdFBTenF0TS9zN2xGdVJObHRwckNDTkQxT0FpSzBXNG83K1Q2ZWc2ZGFTbnUvV0JRQUFBQVFHTE92dTc3RGMrM0J3enBoeW82eTNCRzFkYmtKZEdScHRlLzBRcGxKZHY4M2paMjNGT2h4YnpYYXNmdFc0U0M4d3pBZ0FBS0IzeGxwTEZTQkplbTJJVUtCTFJodDJ2Ky92K1dUVjdEUXRWUlRvVkxPcGVYb1BBQUFBQ0F3QUFBQUFNaEpRQWdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBRUJnQUFBQUFFQmdBQUFBQUVCZ0FBQUFBZ01BQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQUFnTUFBQUFBQWdNQUFBQUFBZ01BQUFBQURBc3Y4UGxkcjZOSFIzKzdZQUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjAtMTAtMTQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTEwLTE0In0seyJhYWd1aWQiOiJjZGJkYWVhMi1jNDE1LTUwNzMtNTBmNy1jMDRlOTY4NjQwYjYiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImNkYmRhZWEyLWM0MTUtNTA3My01MGY3LWMwNGU5Njg2NDBiNiIsImRlc2NyaXB0aW9uIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIFNlY3VyaXR5IEtleSIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoyLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2ludGVybmFsIiwiY2FEZXNjIjp7ImJhc2UiOjEwLCJtaW5MZW5ndGgiOjQsIm1heFJldHJpZXMiOjgsImJsb2NrU2xvd2Rvd24iOjB9fV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQ1ZqQ0NBZjJnQXdJQkFnSUpBTm9NMzlaWTc1WnBNQW9HQ0NxR1NNNDlCQU1DTUlHR01Rc3dDUVlEVlFRR0V3SkRUakV6TURFR0ExVUVDZ3dxVTJobGJucG9aVzRnUlhoalpXeHpaV04xSUVSaGRHRWdWR1ZqYUc1dmJHOW5lU0JEYnk0Z1RIUmtNUjR3SEFZRFZRUUxEQlZGZUdObGJITmxZM1VnUm1sa2J5QlRaWEoyWlhJeElqQWdCZ05WQkFNTUdVVjRZMlZzYzJWamRTQkdhV1J2SUZKdmIzUWdRMEVnTURFd0lCY05NVGt3TVRJNU1ESXdPRE15V2hnUE1qQTFPVEF4TVRrd01qQTRNekphTUlHR01Rc3dDUVlEVlFRR0V3SkRUakV6TURFR0ExVUVDZ3dxVTJobGJucG9aVzRnUlhoalpXeHpaV04xSUVSaGRHRWdWR1ZqYUc1dmJHOW5lU0JEYnk0Z1RIUmtNUjR3SEFZRFZRUUxEQlZGZUdObGJITmxZM1VnUm1sa2J5QlRaWEoyWlhJeElqQWdCZ05WQkFNTUdVVjRZMlZzYzJWamRTQkdhV1J2SUZKdmIzUWdRMEVnTURFd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUVityT0ZFMk12Q3hLbkoycUVNbDF4VisxSUJGaFdWekZQZS83QVNqVklFY1Y5cHBLMGkraVQ4Q3FRSmNjeEJwejVkT1RlczZBc2FwQ205YTN5ZUI4RG8xQXdUakFkQmdOVkhRNEVGZ1FVOUlLdnZwYmd4cy82U29pZlhlbkZORHRJN0NNd0h3WURWUjBqQkJnd0ZvQVU5SUt2dnBiZ3hzLzZTb2lmWGVuRk5EdEk3Q013REFZRFZSMFRCQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQkgwOXJsdUQrUnVqNnR5N2pZaEFyWW16bkVvcFZrLytreGR6ZlJxUXgxSlFJZ1NvTVhrUGM5a2Zsdm13RFJkUXErWE4xYmpIODRkQUY5cmpveU1sRWtONXc9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUl3QUFBQVlDQVlBQUFBb054VnJBQUFBQ1hCSVdYTUFBQjdDQUFBZXdnRnUwSFUrQUFBRklHbFVXSFJZVFV3NlkyOXRMbUZrYjJKbExuaHRjQUFBQUFBQVBEOTRjR0ZqYTJWMElHSmxaMmx1UFNMdnU3OGlJR2xrUFNKWE5VMHdUWEJEWldocFNIcHlaVk42VGxSamVtdGpPV1FpUHo0Z1BIZzZlRzF3YldWMFlTQjRiV3h1Y3pwNFBTSmhaRzlpWlRwdWN6cHRaWFJoTHlJZ2VEcDRiWEIwYXowaVFXUnZZbVVnV0UxUUlFTnZjbVVnTlM0MkxXTXhORElnTnprdU1UWXdPVEkwTENBeU1ERTNMekEzTHpFekxUQXhPakEyT2pNNUlDQWdJQ0FnSUNBaVBpQThjbVJtT2xKRVJpQjRiV3h1Y3pweVpHWTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5MekU1T1Rrdk1ESXZNakl0Y21SbUxYTjViblJoZUMxdWN5TWlQaUE4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWlCNGJXeHVjenA0YlhBOUltaDBkSEE2THk5dWN5NWhaRzlpWlM1amIyMHZlR0Z3THpFdU1DOGlJSGh0Ykc1ek9tUmpQU0pvZEhSd09pOHZjSFZ5YkM1dmNtY3ZaR012Wld4bGJXVnVkSE12TVM0eEx5SWdlRzFzYm5NNmNHaHZkRzl6YUc5d1BTSm9kSFJ3T2k4dmJuTXVZV1J2WW1VdVkyOXRMM0JvYjNSdmMyaHZjQzh4TGpBdklpQjRiV3h1Y3pwNGJYQk5UVDBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5NFlYQXZNUzR3TDIxdEx5SWdlRzFzYm5NNmMzUkZkblE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5elZIbHdaUzlTWlhOdmRYSmpaVVYyWlc1MEl5SWdlRzF3T2tOeVpXRjBiM0pVYjI5c1BTSkJaRzlpWlNCUWFHOTBiM05vYjNBZ1EwTWdLRmRwYm1SdmQzTXBJaUI0YlhBNlEzSmxZWFJsUkdGMFpUMGlNakF4T0Mwd05TMHlNMVF4TkRvME1EbzFOU3N3T0Rvd01DSWdlRzF3T2sxdlpHbG1lVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlIaHRjRHBOWlhSaFpHRjBZVVJoZEdVOUlqSXdNVGt0TURVdE1EVlVNRGs2TXpNNk5EY3JNRGc2TURBaUlHUmpPbVp2Y20xaGREMGlhVzFoWjJVdmNHNW5JaUJ3YUc5MGIzTm9iM0E2UTI5c2IzSk5iMlJsUFNJeklpQndhRzkwYjNOb2IzQTZTVU5EVUhKdlptbHNaVDBpYzFKSFFpQkpSVU0yTVRrMk5pMHlMakVpSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWpFNE5XWXlZbVl0T0RWbU9TMWpaalEzTFdGaU9EY3RPVEZqTTJJelpqQmlOemhsSWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKaFpHOWlaVHBrYjJOcFpEcHdhRzkwYjNOb2IzQTZaV014WlRnM01qRXROek0zWVMwd05UUmxMV0V6WVRrdE5URmtNVE16TkRabFpUSTVJaUI0YlhCTlRUcFBjbWxuYVc1aGJFUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNakU0TldZeVltWXRPRFZtT1MxalpqUTNMV0ZpT0RjdE9URmpNMkl6WmpCaU56aGxJajRnUEhodGNFMU5Pa2hwYzNSdmNuaytJRHh5WkdZNlUyVnhQaUE4Y21SbU9teHBJSE4wUlhaME9tRmpkR2x2YmowaVkzSmxZWFJsWkNJZ2MzUkZkblE2YVc1emRHRnVZMlZKUkQwaWVHMXdMbWxwWkRveU1UZzFaakppWmkwNE5XWTVMV05tTkRjdFlXSTROeTA1TVdNellqTm1NR0kzT0dVaUlITjBSWFowT25kb1pXNDlJakl3TVRndE1EVXRNak5VTVRRNk5EQTZOVFVyTURnNk1EQWlJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBb1YybHVaRzkzY3lraUx6NGdQQzl5WkdZNlUyVnhQaUE4TDNodGNFMU5Pa2hwYzNSdmNuaytJRHd2Y21SbU9rUmxjMk55YVhCMGFXOXVQaUE4TDNKa1pqcFNSRVkrSUR3dmVEcDRiWEJ0WlhSaFBpQThQM2h3WVdOclpYUWdaVzVrUFNKeUlqOCsvMFZ4UlFBQUdmVkpSRUZVYUFYVndYZmNuM1Y5Ny9IWDUvdjlYdGR2M0RzN0pKQUlBVUxZQlptQ2ltRFZEbGZ0dzIzSHFZdXFQVjBXdGRiV1I2M25WRzJybnJhT3RzaERyUlVmUFIzV1dTM0tWaEFaWVFvRVFrTFduZHp6TjY3cituN2U1MDRpS05XTzg1OCtuMm51aXNTL0ozRzhZWmVaMlpURUltRDg1K1JPTzBaU1VmaUhKUDZGSHlJRVdCakF3ek53Nm9iSTNDeWtDR2FHSk55aExNV3dnbnJvcE5KSUNCTlVjb29pME84Yit4ZkY2UExBcUlNY0dvZDJXK3pZRDlGZzQ5ckFnYjFpMFRKVEhXR0N1bzZVaGVFSmRpOW1WclNOOGNLWXE0MmQrOFNLQ1NPMmdBd2RJQlFRVFB4N1psRFZka2tXYnpUWmNLVEkzZGh2dnJHbHVlTTlkOFVUWDBScitqbW95WUNRT01Tc0JMcEFBakxRUnhwZ3hvK1JBbWxyNG9jSVpoZUdrRjVsQnBMNHJ3aElDWExEZkgrZ0R4ZUZrSGdDQ2VTd2Y3OGhFei9Lak1QRUQ1SWdSWHVSdWYyMHBZQlpRNzJmN1N0R0gzWW1UdnhGTWhjZ0F3bGlBUkxnR1d3R05BZldRcXdtaHNoQmNuNHNHT0ErbDhxQ3h4bVFCVTNEU1pJajhWOFRZRkMwallVRmJlMzFkUDJ5NVpBelR4QVM1TVpBZ1BHanpRQkIxWUR4QTlaWjBLa21jRUhJbWM5M0x2aTNIZkhJa3FaZWpUSWdNRUFPN2w4bnhrOGgzWUxuM1lRMGp1c00xTHlPRU01RTRzZUNnT3ovbFBZY0VJOXhRVHR4eEhnM251a1lJTDVyRWRnT0NDajRmZ1lTc1I1cVJhZWpxMEppdXFwNGdoUU5MdzFWNHNlRkFLOUZNcjVIUUxUalFneWJNY2lOZzdIbjFwV1hmT09oNnNTTDhQa2pNUWRMWUdHYXdkN2ZKWFl2UjBXZkVNQUMxQldFNGxaNkMvOU1tZjZPY3VUcFNJRDRrV1VHMG03RXZlbTJiYzVqaG8xWU94bVBPbk1UcDJhSjdJQ0JpWThKL1Q3UUFrWUFjWkFBUThFb2MwTzJ5TGJSVVVNQ001Q01kaHYyelRsa0kvSmpSR0FSUWhISWpYaU1HY2RLR25lTTBqS0lPeDZwVisvTFp1Y2o3eEFNU1B2bzZ4VjQ5UVhTT016Tnc4Z0VkRm93TXdNalk1RFNYcHJtclJUNkI0eFZpQjlkRWt0dUpOcU90SGMrOEpqK0VEcGQyeFRhakdnQUdlTWdkLzluWUU4STRJSVFRQ3dKZ0lNTFhCQU5tZ3lTa1IySzROejlJRHc2THpZZkxRcmp4NFlaTkRYMGVrNTNMQ0J4U0FwMmpwbGhnaFkxc3paeDAxWE5CWE1FdGhBcVFCVzk1aDAwNlF2RUVhaEp0TXVYVU1RWDBGUlgwMnA5aENMTm93Q2Vyc2Y4UHJCVi9LZkVZY1ovbnpqTStBSHVFQUwvSVRsZ1lNWmhCcTZiRVF2cFNVZEdIbFBWeEJWamRvNnk0UklnRU5zRU82SkJscEVDVkxVVGdoRkxRVFljSXlNS1FaTWhHMVFORktYNDVqMWlZdEpvSlVPVitDRU1HQUVDTUErSS93OENYR0NBTzFqa3Y4MVlJc2dPRW9lSXd5eEFYWW01L2M2cWxZWm5hREpINWN6SmhJQk1tT0FoMy9qbGdYVldRejZSWURBWVhzdEMvUmQwbGtNNUF2STNVSFRmUndCcWZ4NGpvMXVCTDJJUjZnRFpHMElBQk80UUkyRGdEaVlPc1FSeWtJTVpQMGpnR1VMaWNSWUFnUXZNT0VRQ015aGE0Qm5rUElFRUZxQm9RYTdBSFVJRUJEbmZpY2pwcEVseGlJREltczZZblprYmFESllNRHo3M2NnZm1Xa0NSWUxKQ1AwK1dBQUtIbWVBWkVnUUFnVGprTkUycEFnU2h3aklBb3pqZ1o5Qk9rK3d6c0JjN0FPK2d2aWt4S1A4SndTNEdERzRLRVhPRXF6cXRQQUEzekhqQzRLdC9CY0V5NEp4OFdpYk0ySmtLb29hZUFENEN1TGJHQlFseEJFalprR2Y5WFZ0bTRoZ0NJelp2K1hGRHowWU5wNk5MYXhFRG1YbnMweVpFeW9vMHhuSS9vaWNvYWtoUk1CZWczd1RVa24yMVJnbkU4UWhyUTRvZzJjSGJRZjI0cXdpMkhxU0JScUJBRE1lNXc2cGdNNFlESHFRR3pDRGtDQVZNT3lCSEN3QUFnR3hBRGw0Qm9zY1pxQU1DR0lMd2poVVBhRnN3QTZDN21GSm1ubFVIT1FaV2wxV2o0eXlSVUVna0J0bHlUMnRxQU43NTRXNXNXUkNjS3JnRExEamdPVUdDb0dkR0xjQy95cDRoQjlHRU9DWXFYWjRiVzdzUmRGMEZHYUdJQU1wUXNDZVpZRmZNN04zQ1A3YVFId2ZBVG1yUlBaTHJjaXZZR3lXV1ZlQ3RaTWdsNXJLM3BTaVBvYnpoOENBN3lNZ2kxR1pYZXB1cjR6R3BnMnJZbG5YQWplVWhEc1BXZVRQTGZMSDFVRGFmbSttTG95UnR2M0VaTmNtcXl4YU5DQnV2VDZldXdQeE10UnY0K3JSRzl4SU11ZzBNTlFCTE54UGEyUUx1WUZxQU1UbkE4L25vQ0lBeGlFaGd1Y0RMUFkrVGpQNEV1Tmo5K0RXSjRSQU5YTTZkTi9DeUxLeldKd0ZieUJFUUJCTFVJREZtUWR4WFVjcTdzVENnR0gvS1Bweno2QXplaElHTkEya05uamV3ZmJiUHNyWTZ2dG9UejRmYTE2SUJjZ1pXaU9RNjBmWWZ2K0htRmh4QjkzUm44UHp5M0RkanJHZEphbTdNWENRQkVYa0REUEdjZ1VXd1hBR2ZWMWZXMEJ1YXkzeTg3Zzl2OTIyRXcxYklUY3dnU0FGUThKajRINlpYVkZMSHdCbStTNEhBcng0OVRKN1I5a0t4dzhXd1FLUGs2QnNRUUdXemRZWG8vR2pkWk9qTWg4MkRwTWdKanRwOVVUODM5MWtGK2VHb2tqQ0piSU1seEJZcm5Wa3UydHZNdzlIbXZKckJRT1dPRkFFVGxuVkRoOXNXYmlnY2NOTTFCbkVraUFra0xFaEJIdDNHV3dWbWQrOGQ1dnp4ZS9FOU15ejdjeUx6NGZxRVNpVjJWbHMrUHllWW0yUFBrL0ZNc2dIRFBveldJQ3FnbTduQVR5L2dOazlyNkVvbjBkNzlFazBGWWNJQ0FIRUVvRVB2OHFqRDd5VFZjZGR3OFI0UXpXQUxCQmcrV0ZtRnIvS2JITUZVK1h6Q0FteWd3VW8weDcyUGZTWFBIRG4zN0xsS1E5aDFpZEV3R0ZtMXlvNng3eVZzdnRHNmhrd29EUDZOaFptTG1mWnhoWXBYWXpYSUFHQ2FDQzlpMTc5RnpUWFFUcmhRc3BONEl2ZkF1WlprcnBkY1pDZ0UyVm5lelpjSW1LME9ueDFkdGIrTGplNmVOVUsrMkRDanE5ZGhCQzA1QURTaUFYS1ZqU2FSalFpeEdESGdyM1Q0Rm5BcjBwODJ3V2R5RnRiSStHM1RUYmV1QkFRZ0JBTjVQTWpMVDUzeDRPNmV0c0MrODQvd2RaT1lpOXRpTzh5eTdjaTNjaEI0dHhXeXo0UzRjUWlRT2c2dlI1N1RGeVZnanlZWFNSWTFRQU9kR0o4cWFSckpQdG9VM1BRdVNuWUZhUFJObVdEakREWVdkVit2Um5aNEd3ejIyQkFOWlNWbmZpcW80N2xzNVBPVmZQTGJPMktVZHRNWDJBR0JRdzZFOWMwZCsxZHhkcmpOdEZPb0RoQ1ovOTU3SGhnSzBlZkM2RUc1eDRHaTc5T1NoOGdwS2NSL2Rjb3U2ZlFuNGZza0NKUS96M1ViMkJxelU2YVBvd3NPNWJoNEFKY3UvRG1xN1FuQnZTWlovdld0ek4yN0dsMEp6Y3lXQVRaOVZSemI2YmR2b2JONTRxaUJXcWdHb0lpdEVmM3NPZkFteGkzU0xkOUtWVi9GNjN1VnpqNkxJakZPbFJkZ0FVUUVBTU1xM3ZKZGhWcjFrSnVMY01tbjRvcW9MNFpQSU9SR0hDSUdWTkVUaEpnQnRuOXk4TUJyeDhkczdjRmhYZDJvaGcyZm1QTytuU1EzUXkyRDlOa1U5a3BpNDIvb0d5Rmk4cElrQXR2eE1TWW5SK0srQWtMell0RzIzWkJ1d3h2eXoyMTYwYVlRWkZBVVBWNy9xbWlzRDluVkxmMSt2U25lNDRzUU5ZVmplenRwZkhVUm40VHNNNHN2TS9FaVNIQlRGLzloVVg3MDdLdGo0NjAySVhJTjl6VmJKNGFpKy9mY25TNHNCcUl4bFcwWTN6ZHZnVSt1bTNhanpqdEtQNE1iRk10a0duT3M3ODNoUERKRU94UlNSZ2NpWGdieGtzRmxxS3RhS2Y0d3Y1UVY1MTZySjYweWptaDJtOVlFSlRzZm85ZS84aDlCemFld1JIelU0UUNGRnFFOEFhOHVvbWl1SVdtRDU2aExNRGlnN1JISHVTV2E3L0VzUDlSVG5uNnM0Z0dpL1cxeU41SUhPeWtNN0dNaFlVM3M3ajRVc1JxaWxBZ1BrNk92MDY3M3N0UjYyOG5oeHZJMmtoMy9DYm1GMStMdUkzeE5lRGg2VlQ5VnlHT1JQbG1HdjlUSmxidHhJRDU0Vi9TYWo4WGZDZHpleGV4TnRUVldVVGZnQm1ZUVREb0RYZlEwelltV3BBMm5vUDdDZmhnSHlIZmpvbURrampNeFBwQU9BNER6OXdnOFg3VityMlJUbno1WXEwSGRzL2xQeHdwN1RQQm1PTzdna0hsWEh2M3cvNnhpU24vK1ZNMnBiZFhzL1lrajJJNEVLRUtXNTU2VXZIbG1KaW9lbW9yYzBnclFRT1BIaGo2VzJuc2I4cUN4OFVJTVJpNDl0ZFpmMUFVWERCV3BvbUZTcjlsRnM0SkNBdk03WnIxUy92emZIekRlc01NRURSdXQ4NzNtcmNvcC9jRVdCOER6WFJQOTMvcU9pL09Qem45YW12VW5yd3dDNWdlOHRwZkJYeU5KN29iOUR1WW5XallhWjdGWXJaTk1jTksySktDalZkbWRCbkFnQnNmMGhIYjJMTHVkYVFESTFRVnlLQ3o2bVNPbWZvazduK00vRXQ0L1FpdFVlaU9nemNnN1dEWSt6MXlQb21pWEU5amY0aHBCNmIxcEhnNTR5dWZ3WEFBWmhBTlhDK25hbTRsOEI2NjQ5QktCOGdMTU5kN0o1VnVvNHFSRWJ1TXdjSnZZMkVNaTFDTVhvU3FEdGhseEFBZHpkSTBleWs3MzJJNG5PT3V1Mkg5NnROWnRUd3hyQ0FZeEFRTCsyL0NyTS9vYXVoVlQ2WlZkSmh1cnFldEEzUWlPS1FVamU4NnhZd3B3VTdIcjIwbmUwdjJkRzQvNit2dS9pcGdHOTlsZ0ZoaUhOSTR2VWE2SFBkdjdodndpYkZPT0RVQnVSSGpJeHlSSGVvR2drRU1zR3RHMzg3QjMxaDI3R29KRU9EUWJVTzNNdTdkbmxuWkVXWEJWTHNkTzVZNVhoNWVvQ2lLQ0ROeitVUFQrL3pqclpTUXdJQTZ3OXBKWnpEMGF3ZnorZWVTYVN3bWNwWFpOVFZxcDY5WlliOGlCOCtPUjk2ZFV2eGFNRVlsR1dCTFdKS0JBM0o5MjR6VFdPS29YRFNuSzl1WUpBUUVnd1BONk5XN2UydWd6ZG1RUVN3UjRORHViTWI5cjhqRlZxSStBZllab3QrSCtuRDBhU3o1QnNxMzBCdnNndkFObWozZ2ZoUmgrVFNodVJKNUJZaUdBaGdoNkI2S0JBYXNXSDQ2WDcveWMxanJLK3g3QURZKzgrWEUrQWNJd3dSaVNZWjIrVXRJWjFBM014UmhBbWt6bG42ZmJkc2FSSWVpT0pXRERKQkR3NEQyMkxjWTltQjJEa0o2TXJSZ3FuTXpUWDJBYkJ5VWtGalN3dXgwQ1F5ZmptN1BEZU5oMDZEVUYxcDl2WnpHcHVXQVFBWVpNTUFNM0NFQTNUWlFzSFd1MXMvVU1mL1ZVZDF3U2IrR1FRMEdtRUdJUUFwZmYzUi9mdTNLRmR6bEFqTlFnR1lJSjIyQVpwdjQwT2Zod2pNRHp6M2RMdDI1eCtSbzQrcmx0aXdQSVhTNHAxM3lKMVB6UnJzRnFRVjFBd1owUzJNNEJFazdESkZsckJpTnhZdlA1NFZrVml6T2laQnNFZW1uZ0xNRTQ0RDRuaG9vRE03aUlBT0R4V2dVMFRoSkF0d2d3WmZqSlhkc0RTZTJDUGtJVkFNQk1CRFFERGtrZFU3RXV1K2lIcndhZUFtVG96Zmd3R0lGcUlmNEJLVlAweDlDNWpxOHVZNVE4RDNHSWNwUWxOQ2RXTW5ldmN2NDlyYyt5ckxPSWl2WHJtQ3l1SXpLRFJOZ1BLN0pYZUJjek1BZHNQc3h1NDJOUjRINzhaVGhGT29LTUVEZzdHQjBmQ3NSMkx2L0JJNVl0eGtMOEowYnI2TzNQeE1MRGtwa0RwcWswT2tnWXJDanJXTWo5KzNSVGRNTGV2VTRUSzhlZzdJRmJwQU5oQWhCV0FObWNNUnlZNlNBL29MWXZNeTMxemxlMld1NGhDWEdZV1pRTmY3My9ZcEx5NVoybFFGS2pOQUNCZWhWMENtRUFBZGl5WG5kYm5ycDF1bm1qOHBSemw3ZnNuYmR3TTU1djNyZGx2RG95UnNNR2pIWUFUUFQwRXF3Y3NLd0VGRXczQ0NIUUlUVjBleWlXdUFHRVViS0VIN2FBUW5NREFRT0dHQXNDWVlBQTVSOWF5Zlk2UWw3dW1TVTdScm1lSEI3L2FUYkIxUGQ1NUI3RzNETFlMczVyQTAyQVVUVWdBdFNzWkhzTDJiUGdSdG9IQ3h2QUZ0RHNLMFlNSGxjQzA4cnlMMkU2aHFMNHFBUXVyZ21pVVhCc1A4d3ZkWXJxUGJNc243bDFaejZIRmkyNWtKeTNzaGdIa0xnQ1F3UUlDQVZzREI3TGIzZWJsYXRoUkJQWVhiZkNnNnlDRlpBLzVFN0dlNituZEZUWU0yRzB4bHJIME52NWdCWC9lTzlQSHczZEVZNUtDbHcwTEdCY0NvWW9KRk9TK3pjbVQrOVk1ZTJyMTVoZER2RzJuRmpVSUVCQnBoZ1VJdDJhUnk1eXJoOXU1anRpUlBXOFJ5djdIZmRqSUI0VEREREczdjR6bDNEZld1bmpORldvaDJNSmtMdEVJRUE5SVl3VmpLKzZhajRmK2dxbkxaSk4yWEYxd3ptaFJWVURObmFUQU1tNmdYUnpCbXQwcEE3VlEycmxoYzBibVFYTVFuUHJPa05PYzZDaUlZSFdCQ3FCTWtNWTRtRXhZQWxvMTlsOVRtczdXYlQ5ZEEvVnJUdDlCaXRXMVhRc1F5SjY2NVpQSFVIenM5aWd4THhCb3lyZ1FJNEh2UUJ6S1p3UVZtQTVEeTg2eVlxd2ZJV2RPSUZNSElDc2QwRFFUVlloelZYZ0UxQm1BVnp6RWFBSTRFYVl6L1lES2s2RnpwWGNNSFBQa3puS0NDdHA5b2ZlWnlBd0NGeWlBa0NtZXlSMUxxZFhQV1kyUU5tSjVES2hEdFlnUGJZa01YWi80dEZpQ3VBQXo5Qk00UisvMFkybjdPTGRjZEJLamtveVFCak05QTFSQmJVaXl5dW43QzdqbDRMVDFwanpDN0FZQWhtUEVFd2tLQnFJRHNFQzc4STlxYzFqRWVFK0I1MzBXbUZYMTQybXU2cWMvNndBeGx3QVFZSXFneGpIVmE4OHFKd3hVbXJ3bW1QUGx5L2Vxb2REeVN6NVhValltM0ZpcmFXeis0V1FTS1pFVnFnaXNNRVRhT09qR3lvYUhmRmNORkdsQmtMTERFTGcreC9IY3cvVWdRN0tyc2lRZzRxWkhtMjBlNlcyWnh4U0xkcHZKMmQrd3JzOVRsRExBMEdrVVUxZHpRVHU2RGlHSkxOWTN3V3RBME1wUHVCUzhIT0JZRUU4NHQvUXRINk9LdVhRZjlSOFBaVGFZK3NZdmIrQllZek1QS2tmUlRsUG1JOEh4ek1RQWIxNE1zRXU1SlEzSUw3eTRpRDgwaGpzN2hWVE84QjkxdG90MnBTVE1oQUJqU1EvWE1VNVZmQmQ3TTQyRUlJbDdGbTVSeWpKWHppejZDdXR2UGNOMlI2L1VUVGg4WDlINmZWK1J1cUdhQS9UcTUrZ2w0RnFmVU5Mdno1L2FRQ0pBNUtKbG9XN0dRelF4SW1ZK2o2MW9ZanVOYk4yRGNMR0ppQmVKd0JKVEIwUVFyVzNiREMvcUFzd3B1R3RTWE1PY2pFZmhrZG9DUEFYV1BITEV2dm5lOWpjajVpQWVlN2hLaHFlOGJ4YThMN1d1dmlLZmZkblIvKzVqMzYwbk9lVHBoTWlneEFZSlY0YW94V0ZvVEtsVUVHQm5JSTBYN1pqSmNIVkFtYjJEL2pmemJSc3U4b1dkK3p1c2tnaS9ZZys1MmpJZDZKR1dZUWdleUJQWlhPM2RBTkZ3ZlJkVEVtK1R0YXBSOFJ6SjZSM2VoMHdmWTNmR2JmZWJkZGMrekxWbEZySTRPcURXcUR3QUtnQThCYndmOG5LUVZDNjFOVU01OWgxU1MwT3RBZnZaaWk5UUpNc0xodEdja2dObk5RL2pMS2QwQThoNUFYcVB0L0Q5MVBFRk9tR1hZSmNSbGlpVGFqWmdyM2FiSmRoL1JPeEcraFBFV0ljeWk4SDVwM0kxK2ticUEvL0IzV3JvVTdiempBby9mRDFCR3c3YlpQTTZ5T3BDak9vYW4rbGY3c0IybFBRUVI2dTA5Z1pPUmtIREQ3SnRVUXFpR1BTUmFZREdaUEZvY1p3a3lyK3hXL0dRd3JqRUk4cmhXTVpZS1Z3T2RkZk1oZDU4VEMzcmxxTXB4ZnUyZ2FVUVNqY3QwV3NGY1gwaXVhYUpmS1JSYTBJcU5sTjM1ZzZQNnpMbjBPN0NHRG84R2VFWU05blJERzZMblB6dWMzYlp6aW9lWkFYcWJ4c0sxVmhPWERTcGpaQmFYQ1I4ejBCb2M1bHJpelBKcTl2U3p0MGlvVE95MWpVR24yMFdtL3U3M0J0cmZhM0QrWXRaT3pZRFRaYTNwVm1CczI5cnV0a3NyTWtCaFBRYis0dmgxK1R6QmxCbG02eTR5M0oyT0YwQmFMUnIyWVNTVjNQYmpxS1YrYm1WdjNVOFRla1pnRDhkbTQzMDNPRUFPWS9SdVI2Mm0xQ3RBODFYNElVOUJVbXlsYjc4ZktaZVErTEgveVpSVERXNm1iL2VEVGlMZVQycU1NRm9iTTd4NnkraFRJZmpUVy96Z3huWXNERmk2aUdaNkM2ZDlvcFl6eHh6UzZpbVp3QkdPajkxT0gyL0RnWklkVytmc1U2ZTIwT3JEbm9ST3BkU1duUGczV2JOcEh0cmV4c0RCQ3F6WEh5Q1EwRGlIQi9QUkd4aVpYWVBWZWN2TVFNcjVmR2huVitvVjVPeTFFRG5GQTJIR2x3bHVpQWNaaHhpRXU3VFhaZlVMSGhFS1hFM2hhNWF5aWhtaEdBOVJaLytUR2I3am43OGo5RVN4ZUhDd2NEMktZUlRBcmtvWG51UGpKQUgyRHRvS2xnaVV5V1BSTEp6djZoMWdFRnFmWi84aDIvYzBKeDNOcVVaSnlBMlo2aGRBV0kveXJSTGRUOEV6SE5zdWcwektpYVdlS2VnbkdMUU1wRE9hNWNpVFl5YlVMaTJiZE12NUduWFdoWVZlRHVtWjJ0c3hPRzQxSzJhR1czU0RwSlJZMElOaDVZQWdEQndMM3JJcjdGcWs0RFV0Z0JqRyttZXgzSW4wUk04aUNmak5nY0dEQTdDT1FhNUM5aUZpOEQxdFlqOWNnUVdmaUV1cnA5K0xWSDVIQ3ZaZzUrQno5UGl6MGw3R09YNEQ4RmhwYmpzUWhSaUlXNzZZWi9nSXAzb1hVWU0zMXBCTG01MkZRUVh0cVBhM3d2NUMvRkRPWW1ZYlRudjNieFBZT2Vnc2ZZZDJ4TUt3eWcycWVsajJiT2grTDZ5OW90MFJhZlJHNUJ1VnY0SG9ZeFBkTHV3OXczbmhiSFhjd1FJSWlRcEZnV0FsM3NNQVE4WWpnOWliN3JrUVlpWVU5SDdOMUxoRUVqWERROVl0RGYzODBQdE5xQmM5QUkrMEkyWDhwcFhDNXNHTWRJUWx4U0JTTUdsQ1lNV2cwYmRhOHZvVSs3ZG53REowSWV3N29ZMnNhZjlycWtmaHp2VmtubTh6Z3pHRGhUQUVSRVlOUlpkRWZhdXRZbDFlbnhIV0d5QWZjTGR0Znh6RjdWdG0yOC9wOXNTU21aT2U0Y3c0WUJ6bEdQd3QzLzVjUXdwc3d0ZzFySm1JUm5obUNnYUFUS21ZMGRkdm45VHdvT1F2bU9VUmFUUXlYSS84WThGVmNEekIwR002dll6ZzRoYlhIUDVNbVA1TzhXQklUaDVoQk5ROTBmb0d5ZlNHZXZ3aTJDMjlFZC94SXl2WUZEQmVQQmtwQ0FuR1laN0I0Rm1YN004RGxvT3N3N1NhbWtybitNWGo5RkxycGVlREgwVGlZZ1dkb2pYYW82L2NTZURiRDNxMWtiMmlYeCtQMlhGS01pSjhtMkRpeFBBMDE0TnhNdGxtTUowamI5dG5aWnh4bkRPZmtCQlFDdzJHamhjVkswMld5bmdWbHllWXhUSEJjQ3VFQ0M0eldXVm5pM21TNnJ3amNPWmU1dnNxNk9zcjJTZUl4QnBpNGJ1RDV4UUc3TEptOTBNRlNNQ1J3aVNMU202bjFqd3VWM3J1eXhjMHNrVVJyTXREcEdpZE1zWkNDL2FxeXp3cTlNa1VyekkxR0FveGEwRTdhNDVXdTdBLzFKMlBkY0Q4Q0JLcEV1OVNPbk1QTDk4M3o1eE50UFNzUkdHWW9Ba2pnRWdtL1o5OVFIeTRqbDNlRDdSOVVqbUFDT0JXSlE4VGlQbHYrMmZ0MTNCYkU2WVFhQ0RYdWh0a2FpdUxOb05lUXduNUdDcU5ZUHNteUk4YUlSYUx1UTY0YlFpRVFoeGxnRWV4b1RLL2pvSnloMVlHUlNSak1DMUVUQWsra1FFeGJVSDRYaEJrSXM3aEtwcFl2dzJ3RXIxbmltRFdBRVNJTWVtQTJTb3pQUi81OFlvUUV1QUNEWUpjZ0IzT1dPSEFkUWZ4N2FmUHE4TUZxVVovRWFFQUt3Ulo3ZmVZWEt5MGV1ZEt5R3BzYVZrekdTTnRnQk9USXBwdEdNMkFMS1hFQW1IZlJ1S0JnaWZGRUJsbjZsc1Ava091S1lQYVVvZXVvRUd3WXBIdnF4cjllSzl6a01EUytUelNzTURvSkF1ejJyRGNPaC9udktzVm5XTkR4TFFpWXB0MTFpekpmazdUVnpES1BNU0FBQmlIdzRONDV2ZVRoUGY2VFc5YnlsTEpndzZEQ3pOaVpUTmVZK0hxV0hoTEc5RUpOM1lpVTdNQklhYThSZ1NBbEVvdGZxSjkxODEzOTQxZlE3YitTUU1aVkFZWmttTFdSdWhodHlnUWgxQmlMVklzRGpFeElnUE5FRFFnREVwQUlCcmx1eUUyRG1UQ1dpQitnSmdBZGpCSE1FcEtJY1FqMGFPb2haZzRZanpHV3lKQWlVQ0FIVVFNTkIwa1JjRVFiYkJhNGlSL2kvd0gzRDVQTXBkMnQ1UUFBQUFCSlJVNUVya0pnZ2c9PSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImFhZ3VpZCI6ImNkYmRhZWEyLWM0MTUtNTA3My01MGY3LWMwNGU5Njg2NDBiNiJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wOS0wMyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRXhjZWxzZWN1IGVTZWN1IEZJRE8yIFNlY3VyaXR5IEtleSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwMzI3MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDktMDMifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTA5LTAzIn0seyJhYWd1aWQiOiJiYzJmZTQ5OS0wZDhlLTRmZmUtOTZmMy05NGE4Mjg0MGNmOGMiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImJjMmZlNDk5LTBkOGUtNGZmZS05NmYzLTk0YTgyODQwY2Y4YyIsImRlc2NyaXB0aW9uIjoiT0NUQVRDTyBFelF1YW50IEZJRE8yIEFVVEhFTlRJQ0FUT1IiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJrby1LUiI6IuyYpe2DgOy9lCDsnbTsp4DtgIDtirggRklETzIg7J247Kad6riwIFYgMS4wIiwiZW4tVVMiOiJPQ1RBVENPIEV6UXVhbnQgRklETzIgQVVUSEVOVElDQVRPUiBWIDEuMCJ9LCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6NSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCIsImJhc2ljX3N1cnJvZ2F0ZSJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dXSwia2V5UHJvdGVjdGlvbiI6WyJoYXJkd2FyZSIsInNlY3VyZV9lbGVtZW50Il0sIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjEyOCwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiLCJ3aXJlZCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJRHREQ0NBcHlnQXdJQkFnSUJBVEFOQmdrcWhraUc5dzBCQVFzRkFEQnlNUXN3Q1FZRFZRUUdFd0pMVWpFWk1CY0dBMVVFQ2d3UVQwTlVRVlJEVHlCRFR5NHNJRXhVUkRFaU1DQUdBMVVFQ3d3WlFYVjBhR1Z1ZEdsallYUnZjaUJCZEhSbGMzUmhkR2x2YmpFa01DSUdBMVVFQXd3YlQwTlVRVlJEVHlCU2IyOTBJRU5CSUVObGNuUnBabWxqWVhSbE1CNFhEVEl3TURJeE1UQTBNall3TTFvWERUSTJNREl3T1RBME1qWXdNMW93Y2pFTE1Ba0dBMVVFQmhNQ1MxSXhHVEFYQmdOVkJBb01FRTlEVkVGVVEwOGdRMDh1TENCTVZFUXhJakFnQmdOVkJBc01HVUYxZEdobGJuUnBZMkYwYjNJZ1FYUjBaWE4wWVhScGIyNHhKREFpQmdOVkJBTU1HMDlEVkVGVVEwOGdVbTl2ZENCRFFTQkRaWEowYVdacFkyRjBaVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMWllhKzlZWkxKbjRGV2NrRG5ZL0VSb0N1TzNUQnRhMFczZjhSOVNZNWQ1c0JrMlFpdXBjaUkvbDdmd1BySDNGRGtlVlBYZWpNZStrVDBWb0pKZStOOUVNV2VyMC81UFhJUDk3bnJ1WWNyMER4YmhacGVzUUVlVThCZUlVdW5wTk5uRUpwb3hvSlR3b0RtdTgzWktrNG04ZzAvUGZwSndEaG1QQ0FxbTc5c0Z0UDhnN2xDOXFtczVURC82UE56KzJhZXdLWFRRQVIxb3BmaG5XRFVzSVp0dVVmRVJobEd3eFU3WCtoM29RMmtTR3c1aG9sZktTYjBnM3B3R1RjVFZOdmZVTVhIN0NhaVRxL0s3VC9qZEFDRCs5YU5qdGNkM1B5UWVyQThTYTJOMjhydmtOOFlmS29EUGc1Z0EzNzhPTkRWM0Jocmh0WThVaURrQmNUc1hBUUVDQXdFQUFhTlZNRk13RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVU9DbUszMTBHdTNxOURmWC9idmRwc2Y0R0k4VXdDd1lEVlIwUEJBUURBZ0gyTUJFR0NXQ0dTQUdHK0VJQkFRUUVBd0lBQnpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQW5EVGNabmVLL2gwUWI4c0Z4Z0ZTOEZhNWRqUW5TSlFVTUZaL2t6T3NQaDFEVkZERjRuREcvSGxVK2Q3S2FOaGFRN1hMdDd4QWpoekV5VHlIYU1INzZnSDA4cjMzTmRWWi80c01oOUdJTFU2YlNtSllPdGRWaTN6QjNwNjlibllaSEpWcXZKS1g1bEVzU3BuL29wS1lsdnRvMm4wLzRzNGF3SmgrcStCa3lWU1BUUk1YNkxmYm42SVJ1NGNiZVMwVzEzdHNRNVNicEFvOU5IMkZBVHpWTU1LU0dFZGlRbmZZeWdkV3Z1RENMVXRRRjF3R21HU1lzRVBGVFY2UEcxVlA1SFM0ZmhyQk5idXJpMzhOSVVvY2ZrcGZtT0l5K2hIWmdmdnBaem9yazFHdkYzUFpSSXRKblRUdjVVanEwcUQ4cm5yODFxd3ZHbFRDSklCdEVVbU53UT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVnQUFBQklDQVlBQUFCVjdiTkhBQUFTVlVsRVFWUjQydTJiQjFoVTU5TEhNV29TcjdsK1Z2YWNzNDFtVGRTclJvTllBQ2tMaW9vRlN4UTdnWWlpaUtKR0RkZ1ZMSFJFbGwyYXFJQmlqZUtOWGZGYVltS05IU203Q3hwajlQdGlqSVc1ODU1ekZwWmxGMWRGWS94NG4yZWVwU3k3NS94Mi9qUHp6cnlZbWRXdTJsVzdhbGZ0cWwyMXEzYTl3MnVEV2xwZmZ0MjdVZXlGK0thclRoNXV0dlRJMWNhaEJ3ci9aMTd1elVaemMwODJXckIvWThPbGViUE0xdCt3TTFQbWYvei9Bd3BBSFRObFVmc0d5VGZUV3NTZisxVzA2aGhZTE5vSDFuTzNnOFdNTEJCT1RnZHFRaEl3bytKQlBEUVN4SVBXQXUwVjg2U0pYK2FsQmt0UHpEWkx2V0grL3NMSmhMcjEwMVJUbXFYZGZDQktPZytTNkpNZ0RUc01sb3R5alFLUzlnOEhpZXRTRU51SGdOQitJVFFabTFwUU4rcm5rV2FoOE1GNzV6bjEwb3ZuQ3JLTG5vc3pyb0g0RlFDSmJlZUNxTk5NYU9HNDdObEhvY2NqelRJdmZmaitBRklXZG0yMnJlU2haSHNSdkM0Z3B0MDBNUC9pMitjZnJqaTc4TDN4cEk4MmFtSWt1WGRCSDVCNDlUSG9GSFVjK3NZZmh3R3hoNkZQV0M2MERzb0N4anVoV2tDTTFXUm8waS82RHpQNXJXN3ZCYUIvWkdtT1d2NzdsM0pBcmRLdlFQREIyM0RzdWhvS1ZDVlFyQzRCbFpwN3ZGMnNnVU9YQ21EZWhqem80cXNFaVd5WlFVQzBaRExVWDNKYThWNEFhcGhWOHIwV1VQdXRCZkR2YXhyUWFFcGVhRC9kS0lhSnNmdEI3TFNvQ2lDRzlvRUcwM2FmWnpQajMzMjU1MnAyaXZmZWhSWmJWS0E4WnhvY3JSSFBHaFY3Q0VROTVsY0I5UEcwN3k3ODdRR1ZsSlNNUEhXcjVIbXJuUnI0WkxNS3poZVV2QlFnWW9ldnFjRnlSRnhsaVZsT2dmb3J6eWIrcmVFVUZSVTF3QnM4U1c0eTdrY04vSE5qTVd5NldPNUJaV2lQMFg1SCt6KzBQOUNlR3dKMEVhRzJuSmFsQThnZkdnOU8rTjBzc2FETHUzTzNYUkxxTTY0S01lV203TnBDcG5RVHlKUmZtcnNvZkFXeXBPbm1zcVFnZ2FzaWtISko4c2V2eHdoY2tnYVl1eVQzbUJwMndQN21iUlc1ZVZDalJmK2dCb2RkaFhEeWxtYUhXbDA2UktWU3RTNHVMbTZHSUp1V2xwWmFxOVYzM0RTYTBqQjgvblZkUUtubjFVQ1BTS2hJODI2cm9hWHl5b0svVEY0QzE5U0dsQ3o1VThwVk1WYmdJbyttbk5ZZHBSeGpORlN2TlErcDdpditwTHN1THFNN2h3RGQ2VnMwOGhqNmpPcXkrQ0hWZGZsZHlqWmNROW10VlZPOW9sVk1uL2pTdG9OU3lucE56SUx4SVh0aGhTTHZUK2ZWeDZNRTBUL2xtcSsvWUdlV21WblgwUHZmdlh2M24ycDFTYUJLVS9ycjdpc2FzRjV5a0kxQmpPMDhhT1cvQ1dKTzNJWWlqV2JXMnl4MTZ6RDlFLzdCZW9aelVnTGxuSENKdGwvN21MRmJDc0t1ODBIWUtSaUVIV2FBc1AwTVlEcDk4NVR1dGxndDZCNjJsZTRaTVo5MmpCNUN1eVI5M3R3cHBSWHhzQlo5bFpTNVU2S2dXWjhVb2ZPVWJlMXpqMTIra2JubkhDeVhILzlkNnBhVVllNlVjSVhxcTN6QStPOTRKRjY0ZjRka3lYN3ZKaXVPU1N4Q0QzN01Wc2ZFbFBtTnpaSUxYVHR0dkg1Q09Ic1hNSU1pb2VYMGJBakl1UWluYjNFU3hkaTI1TTF6Q1EzOWdKRXBPcHZMbERHVTh6bzE0N0FhUDZtRklQNWlMb2k3emdaeGwyQVFkWmtGd200aFpYU1BzSXVVVS93aUFzUE1JYlNlcVcrQmtnbmhiK2lZOXNOb0laUGJDQndUQXN4ZDVVZm9vZWxQUk40YmdmYmJlcm5KL0gweERjSlBwOVpkZDIxZjNYVlg5elJjZkNUWksvTnk3cFpMR3NoWFZZcExaU2pSMFcrTXk2ZGVtUithdXlTNUNsemx1YlJ6N0NPaHczSVE5L29XeE9qR1lydDViTTFCSUFsN0xINkNIbktJY2wzdlRtVDNLdTkxNTg2ZFR4RE9qM2hUbHdHZ3Z2NTFOTWNQU05CbmZZYkFQdTZCZVIvMExqZmxaS1ovUm5OdGZFRVFnL1NETnI1ZU1ZbGJid1FPN1pyY0JRUHFic1kxOXFuSWFRV0lIUmR5bFdwdkJOUnJBUXRKMURNVTZENHgrWlNMM0l2Y0JONVlIYlFQME9yaXhUWEV3Q3BTcTlWdE1MQjJSQUNkOEdmdGk0cnUyT0QzZ3V2WHIzOUVuZ2M2QVJTZlk0T2U5QVBlN0NoakVoYzRKOW9LZWtRY296NWZXVWIxU2JpS1h1MU5QQlZqMFh3OVFJL3gvVWJVT0JpUlRONFV3YXloWlFsUHhESnVqeU54WGd3U1VxWDJRVWdPb1N3a29XUFk4OWFEVW5KM0hiZ28wMmcwNDlGVzQwWHRScnVFOWh1Zm5xdXJXNTZobGFDZFJ0dUVmeCtLWUR3Um5oMStuWW8yVnQrVGRETWxaUisza0c2MzRESFZlVGxZZWlTZjNKOTM5UmVkMTc3M1J1QUluSlcyS0tjZmhlN1JJT203RXFUdXk5azlEZ3ZKWlFsQ1dveVFGb0hRZVEwRWh1OHZ5eTlRM2NPTCtkTUlnSWY0cVY3REM4MUJyMWlKTnp3RnpZdEwwUnBIL0xrVG1nZitiZ3grUHh1L1hvZVBSOG5mOE9uN0lkcCtJaDNpY2Zxd2NuUFBOZlFJeUZrazdZaGViRGtUYk53U0lEcmoxUE9DUXRWbTRyVTFucDBvRjZVWEpaUC9KdmJnZHNkU2p6Q1FzcEJXZ05TdEFwTElaVFY0ei84T0NvdlVCcUVRYnlDQkVlWFM4c3daSXg1UXpjclB2OThZZ1hSSFVQUHd0VTd4bm5nSExROS9Gb0ZBWS9CeEc0bFgrSGhuWHRTaDIzVEwyYzhaZ1I5UXRxdWY0WDNFV3pnb1A2NVJPS1NJbzl6a1Q4U2VrU0R4WEFQU2dhdEFPb0NIMUU4TENRTzBiQ1YwSHBVQmw2OFZWc29VWEhEVlRMNTM3MTZqbXUyZlFSMFN0L0MxNHhITXIvaGVCZmo5M0tLaVg0VDR1M3JrOXc2aEIrc0pIT0ozTW93L01NMG5BZld2cFlBaFltZFQ5L1JHTlFJSEsxby95bDMrV0RRa211MnRTQWF2QmNrZ2hPUzVtb05VN2swcmdKSEZ3dXFVLytqQ0tjUUxua0FLdGpmYmFJUTZwSUxtWWhPNzFWQVJXV296bE1CZGFVdDFXdlluMDNSQ09TUnpWMFZXQzRmWVQxNHY1c2dVemdLM3BFZENMOXpnRFVkQVhwRmNFM3hJUkFVazRrMmtJZFV2SEt3SHBzQVBGL0o1T0tWWnhjWDNSRyszSXdzZjRBZlNud1BFZmtBL2srKzdlMlUyd094MmhzQmhJVFZEU0YzRHk5Q1RJbC81elJqblZBa0N5cWU5RW9ENU1nNkVJMklSVWd5SWgwVlZRRUp2MGtJU2UwUUEyUXJjTGxBOVJlMHZKUzcrRis3OExSSE9PVzAyeE91UmR4aVJzWjJXVE9jQUVUUDNCZHpHUEVWSXcxOHQ3cmdvRkpTbkhHanZCS0JIeFhPUVJuS1FSTU40YitJaEVXOFNlVVNCODlkYnl3cUxTOWI4bFhCMGF5WSs0N0VlSGJqcXdCUGFKcmdDRUJwdE1RTndRM3dMaTllWEd3T1JiWVBBWGZHWThrWkFZeE01U0tQWHNVMXdaaVR4SmkwazNwc0dSNEJvUURSWURVd3Q4Ri8yZmJOM3BYR0FjY2dlNFR3aGdDYUc1Z0p0amJ2NFpoV0FtR1lUVVdwaFFMa21oYjdVdmdvRFdESTFWTUZPQnFqeFBLUXg2eXNnbFV0T0YxSVV5UTYvTTI1SnJkK2RLUkY4UUFMM3Jkc3FzQnVmQ1l3SU01azV4cUhtRTh0QkVka0puT1dGakVOQ2M5TzhwMzlDYzd6Uk8vUzRaS0FuS2NzaFVWcElCaVVYeFVxT2RrL0U3S0FNZWNjNmtVNWI5bDE0d3ZTT0FvYjVDaGpLaDRQVWdvZUVYaVRvR1ZWRzZqeVRYcEMwS2lnUEpUQmZwUUw5RlE5cG9vS0ROQTRoalYxZlNYSUVFaXM1OUNhaFp4enhvanZtN3NuVzd3cWcyTXhUbE4yNHpmZnBkbk9BRVg3RlFhSVJrb0NIMUh3Q1VPMFhrdXRPTXVrRmNYZStnQjZTRE1LdjA0SHhTMFZRS1VEN0pDTWszcHZHNlhnVFFxTDFKRWQ3ck1mQXB6aFlRNFhZNnkydnpMcGszMGpaaHBVeEZsOERJL0ZEbWZucVFab0V0TTBzQkpSMHpxVFhwSkFrTXpJVlJQNFo3SVNTOFVzRHhwZUR4RWxPVVRrdTZVbE9PQ3dHcUw2SkdQaVUyWTBkbEkzL3l0WXUrYkNwWHBIUG1GWUIzQVJEQzBuc3kza1RnWVNTbzZVQnhJTWVtTlFjNysyVGZVNDRPZzNFVXplQ2FBcUJ0QUc5aVVBeUlya3hPcExUUWhvZUMxUy9SSHhUNVVuS1hkSHViYk1oQVJmZk81M3F0Zlk1MHhacm4xWlRnTEh4NXlCWklpUXBEMG5yVGRLcHhJUEtUQWxvZmNhSDdIMHFISjBPMG1tYlFSeXdpWVBrdjhHQTVCUUdKYWViNWVpQkNZRDd1SHVVaXlLWXRFbmVOQml5Q2FWa1NjTXdLMTJqYlplQzhMTkFZTnBPQTZiTlZJU0Vab09nckJHVXBZNDNFVWlXMDRnSC9XRkszUkErSi9JdzNsd2FXQVJtZ1hUNlpwQVFTTVNiQ0NTRGtxc215eUVrNGRBNG9Qc2xrckwrR2xxQTBDbWxHU2xFYTdSSDFUMnpBZTRaaDJEUmQ1eTJqM2dtN0RLUDYzMGpJT0duMDNsSUFSeWtsandrcmVUUW0rZzJ3UVRRVFJNQWxlUXBjODRDNDVrQ2xrSFpZRG1EUU1vRUNldE5GWkpqZU1reFBpK1FuRGJMWVNrZ0hJb2U1WkVBbEZ2U0EzVG5qYVRFcDl5VUZxOEtDNlhid3R4WkljT0VFQzF3WGw5TU82d0YwUmNMMk40M0dldUkvaFhFRHdnNFNFSXlCMnVMa0ZyemtGakorYk9RNkU1c0Z0dHFDcUM3WjNHektlMmZBbGFCVzhCcTVoYUVsSTNlcElYRVNVNmtMemt0SkZaeWlVWWt4NVVDb3FHa0hFQlkvUkxLS0RmNWJ3anJQQ2FHRkx6QXVRUmFjeGVGUFhwRFJ6TGRJQ1p3bFgrR2hhc2QxbGVlYk52RlJSbFB1Y3J6S09kMXY5QjlJcDhKZXk4RFVmY0YzSUNnMjJ3UWY4NE5DRVNkZVVnZGd6aElueEZJMHpsSTVaTHpaNzJKNmhrQlpCWm5DcUJuUmNVYUdCaTRBNlFUTjRGTmNBNEhDYjNKWW9ZeHlhVldTRzZpb3Fya2RDR041S3Z2OGcwdm1tY2tibE9pUU9pQlh0WTNGaGgzZks0YmxnK3lkV1cwTEw2TWRvMER4alVHR0pjb3RsTXBjbG9KSXNjbElPNGRVbmxBMFAwYkh0S2Npa2xLWjk2Yk9nWVpsaHp4cHJaQldFa24zaWNURWxNQVBTWDdsZzI3enVHbm5BcldzM0pZU05henRvS1Z2dVNxeTNJVFhwRGxSbFJVMzFWN1RGejdSTnBQMjdFMDNOWmxlOS8yUEtTZTNKQ0FoY1JPVW5oSVdtK3FSbktVN1hKbzY3VmhwNG1iTzY2UFFyekkxVDhISkpNeXdXYk85Z3BJck9TeVdNbEpkZU9TVm5LKzJpeFhXWEpWTjd3VjFiZDJMeWN4MEdQU2JldEtkTnE2WkVqQVFqSXdTZUhHVGQ4WWxaeW80NHh5eVRFZGdzRVNkdzBiZDUrTE5CWFFmbTE3WU0vaG44RnljQnBZenR3RzFnVFM3RzFnbzRVVWxGME95V0NXMDVZQ2s1UXZMQVhZdUdTa3gxUzFyWXVRWkJXUTJFbUtZOFVrcFJLa0twS2JWUzQ1Tmk1MUNBSzZkd1RNanprQ3hjVnFQMU9ubDkvcU50bFhLUEtBR1pvT1ZuTjJnUFhjSFJ3a1E1SkRTQldTU3kvUGN2clZONEZFdldERHE5dGpxdFRXN2NlMWRRMUxicUVSeWZIRHkyNDZrdU1oMFhZcm9HL0FOaWdvVkQvRCt1OHpVL3NuWGZtZUxndUlUQ1o4RnUwRDBhaU5ZRFYzSjFoL3M2T3k1SUk0eVVrRDlVb0JmejR1K1pHNFZEWExHWldjVG85Sk1yZzZ5UzJ2SWprSks3blFDc24xMUpmY25ITEpDZTBXZyszWVRYRG0vQzI4VDgxWnNvTXd0WDlTRDhFYzB2VWkwa3Z4bnI4SGhLTXl3R29lZ2JTVGc0VGVWQkdYc25YaUVwRmNScVVzUit0WDM2YjJtTmk0dExZcUpHT1MwOFlsQjIxY3FwcmxoRDJYUXFlUkcrRDREemY0Mlh6SjlKY3F3TlRxVXBrMm0ya3R2MEFGQVN2M1k4RzNBU3hubzl3SUtBT1NzeWpQY3J6a2pHNTRrNnBtT2QwTnI2N2todXBJVGh1WFdNbXQxSkhjVWgzSkxVSlFoaVhIMkllRGcwOFduUHpwcHZiZThsOTZGRVVtbEJpTE12V0hmc1dZMlZZcVRvRE5pQXlFa01ONTAxd2prcXV1K2piWVkwbzAybVBTYmV0V0tRVThqSlFDZXBJVDlWNklOVlEwcTRTTFZ3cTA5L1FVbmNIN2xmWTI1RkFCbVdrWkdobm5IcjBDam41YlFEUnVNd1p2bmJpa0s3a2dJNUw3V2pmTEtTdjFtR3BDY2hJRFdVN29GQTV0QmlYRDJyU1RvRkpwZEU5MnBCdWQ3WnNZc0IzNWFXVVZTRVJ5eStSNTBONTdFMGg4czZ0bXVabGJkYXB2QTFuT3ozQ1dvMDFvNjVhWEFwVWtGMVloT1RmT204U3U0V0RSTHdFbWhPN2xnM0dsZXpoVlVGRFE1TFdubGVRd0FiN1lJMk1uTUg2OG1BL0JFWWVnRFdZNWlVOG1XQVVUVDZwR2NsUDFzcHl2WHBaN1lmVWRyVk45VjVXY0JFc0JzVHYrRE1FTW03MEx2anQ4R1ZUcUtzZUZMNVdXbGxyVldDdUJuSjVBZDd4ZjNWRVZvdXVWV0RQMThNa0dNV1k3Qy85c0xDcHpqR2M1UXh0ZXZSNVRsVkpBWjhPckx6bnhnQWpjeDhWQU82OFVtTExpZXpodzRocDcyTlBBdFo0aVE4VWFiMFNSMHhSa2pQdWljOGkzVVhyZllRVWV1T29BZEVkWVZ0NGJRZXF6R1N5blpvRmxZSFViWHNOWmpqYlMreFo2b1ExQ0c3QU9Pb3hNZzFIemRrUFMxck53OVVZUllObzJjdFpJcytXMVpmV0NTU1hGWjdlbnBoemFKdlhUd2Y5Y2d6V3BKMkZzeUY3b05qRVRMRWFrZzJUMEJnendhSlBRaTN3UmtKOTJINWZHVFZJbWthNEFRaHFQM3VTTmt2c1NiWmdjbUNGeXpHUkowSFo0R25nR2JZZVF1S093N2Z1TCtpZEpETmtEY3RJMVAvOHQvTGNoUDRnYmlxQ3V2T3dwZDJMa1prZ1dWT1NjeFNCL0hHYXNQb2hCTkJlR3o5a05nMmJ1aElGQk8vRG1kNEJYOEM0WXMyQVBLNWVRK0tNUXQrazA1Q0FNY2pDaVdHWHl2eUNRRTJxNzNzQmhLZE1PTVpIakpYZ0J0MThGbENFak1ZUEl3NGhFWHNhSWgrZmg5ZlY5clRSZVE3UHZGaGowQXZqNDlMeW1ZTDBHbU4zazJCNDVBUG91VFhlSjlPcVNnd0xrbUFudlZXVnZDY29UbFBzWnRBWGtTSi9adTc1STdYVC8vdjNHcVB2ZTVBUTdYdmdSL3FUcWt4b0NRdjVmNHpaMzhKTTk5Tm51clFUZk55MUR0RzVrMzBNT1ZxRmxjT0EwVi9uRGw0OTA1RWxrOHI5OFovTThQbmNmOFVvRU1vY2NBU1pBeVBscXM5cFZ1MnBYN2FwZHRhdDIxYTdhOVViWGZ3RnZVRUVINFlhcWxBQUFBQUJKUlU1RXJrSmdnZz09IiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiRklET18yXzAiXSwiYWFndWlkIjoiYmMyZmU0OTkwZDhlNGZmZTk2ZjM5NGE4Mjg0MGNmOGMiLCJvcHRpb25zIjp7InV2Ijp0cnVlfSwiZmlybXdhcmVWZXJzaW9uIjo1fX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDYtMDgiLCJ1cmwiOiJ3d3cub2N0YXRjby5jb20iLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkV6UXVhbnQgRklETzIgRmluZ2VycHJpbnQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIxMDYwODAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4zIiwiY2VydGlmaWNhdGlvblJlcXVpcmVtZW50c1ZlcnNpb24iOiIxLjMifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDYtMDgifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIxLTA4LTEwIn0seyJhYWd1aWQiOiJlYjNiMTMxZS01OWRjLTUzNmEtZDE3Ni1jYjczMDZkYTEwZjUiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImViM2IxMzFlLTU5ZGMtNTM2YS1kMTc2LWNiNzMwNmRhMTBmNSIsImRlc2NyaXB0aW9uIjoiZWxsaXB0aWNTZWN1cmUgTUlSa2V5IFVTQiBBdXRoZW50aWNhdG9yIiwiYXV0aGVudGljYXRvclZlcnNpb24iOjIsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfaW50ZXJuYWwiLCJjYURlc2MiOnsiYmFzZSI6MTAsIm1pbkxlbmd0aCI6NCwibWF4UmV0cmllcyI6OCwiYmxvY2tTbG93ZG93biI6MH19XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlDWVRDQ0FlZWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakJwTVNRd0lnWURWUVFEREJ0bGJHeHBjSFJwWTFObFkzVnlaU0JHU1VSUElGSnZiM1FnUTBFeEd6QVpCZ05WQkFzTUVtVnNiR2x3ZEdsamMyVmpkWEpsTG1OdmJURVhNQlVHQTFVRUNnd09aV3hzYVhCMGFXTlRaV04xY21VeEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRFNU1EUXdOakV6TXpFeU5Gb1hEVE0wTURRd05qRXpNekV5TkZvd2FURWtNQ0lHQTFVRUF3d2JaV3hzYVhCMGFXTlRaV04xY21VZ1JrbEVUeUJTYjI5MElFTkJNUnN3R1FZRFZRUUxEQkpsYkd4cGNIUnBZM05sWTNWeVpTNWpiMjB4RnpBVkJnTlZCQW9NRG1Wc2JHbHdkR2xqVTJWamRYSmxNUXN3Q1FZRFZRUUdFd0pWVXpCMk1CQUdCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCSWNpb0xsZExueHZTcC8vR2FKMHNxN2hNOTJQUTR6VzdDUGxabFVtMnN5aXBwd2IvV1hQd1BST1RkbVFmMkdEYmc1VUFBMklZcE5acHBVZXExdmduV3ZMbXVKNyt1K0tXQksyM2R6MVM2U1lPUHRrNXZIZkdvbXBDN0lLaThNdWpLTmpNR0V3RGdZRFZSMFBBUUgvQkFRREFnR0dNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGQ0ZSNnQ5K2kvZjZEOW1lb2dPTFlwVWxicWF6TUI4R0ExVWRJd1FZTUJhQUZDRlI2dDkraS9mNkQ5bWVvZ09MWXBVbGJxYXpNQW9HQ0NxR1NNNDlCQU1DQTJnQU1HVUNNUUQyS1pkenM2Nmgxa0NFR3FtRlZyMFVlM2phTi9Cd2ZmWXVYNEttK1lURGlVN2pLRVpkeHpqQXJ3RlNtdGlBSXpBQ01FTmVMS0RhQWJPRkl2aXFZNUt0MmNYUWtXelRncjEzNFZsQThoVUJQR0U2S0hnNmdpSmFIZ1BaTFNZNkFGV0gyQT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQU1nQUFBQlhDQVlBQUFCQmFBb0lBQUFBQkhOQ1NWUUlDQWdJZkFoa2lBQUFBQWx3U0ZsekFBQURmQUFBQTN3QkpxRkpJQUFBQUJsMFJWaDBVMjltZEhkaGNtVUFkM2QzTG1sdWEzTmpZWEJsTG05eVo1dnVQQm9BQUJlblNVUkJWSGljN1oxNVhGemwxY2QvNTdrWG1HeG1jWWxwR28yYWhDaEwzSDE5UDFiamtscDNyVTVnZ0ZCcXJiUkdJVWx0Z01UVzBWcUJ4Q2FRdUZlckRjc01qTXRyWFJxMWphaHYxVlo1TlVCaWtzWllheFdqTWJzQmhyblBlZitBR2U2OU04TU1oR0VBNy9mem1jOG45enpiSVRQblB0dDV6a01ZSXRqdGVjY3FTbWNLQzU1Rm9Oa0FaZ000Q293SkFNYUNNQmFNMFhGV2M2aHlFSXhYTkUxWjdQR3MrM2U4bFJsSlVMd2F6czNOUGJLelU4NlY0SXNJdUFoZEJtRnhlT3pXZkVxNng3UHVzM2dyTWxKUUI3T3h2THc4VzBlSDcyb0c1M283dFVzQnFIR3owSkhKSkVYVlZnTElpcmNpSTRWQk1aQ01qSXlUaUJKKzBkYlI2U0Jnd21DMCtTM200bmdyTUpLSXFZSFlzN05QVVNSS0FHUUNIRzF2c1F1Z0xXQnNaZUtQaWZrQUJMNWhZRDgwMnNjS3kxanFQTndRRU9lQytXNmRhRnpjbEJtQnhNUkFjbkp5cG1nYVZySmtCd0FSSWZzV0JqWUkwQWFmcitNTmo4ZnpWU3gwR3Fsa1p1YU1qdDlNY3VRem9BWml0OXNWVlUyOHhhZnhid0NNRDV1UnNaMEpWVklWVlo2cXFvOEhVZ2NMaTRGa3dBekVucDE5aXNLb1lzYnBZYkpJQWoydENhNnNyNmw1Q3dBUFZOc1dGckZpUUF3a0l5c25seVEvQ0dCTWlHUkpvS2VscER2ZGRWVWZEa1I3RmhhRHhXRVp5RlZYM1R4NnpKaHZIZ0J6WHVnYzlMb20rQlpQVGZYbXcybkh3aUplOU50QXNyS3lKa3IrNWdVQS94MGllVGVJUzl5MU5iK0hOWlN5R01iMHkwQ3lzN08vS3lWZUJuQ0tPWTJCbDZYUHU4QmFqUm9jTkJXYkZjbkYvbWRpOHNWVG41RkdueGNJTXpKeVo1R2l2UXJHY2FZa0g0anVuRDFyUnBuVDZiVDJLaXhHQkgweUVMczlkNnFTb0wwVndqajJFOFIxTGxmVmhnSFV6Y0lpN2tROXhMTGI3ZU1WVlhzeGhISHNaRW1YdSt1cS9tK0FkYk93aUR0UkdZamRiaCtscUVrdkFEekhsUFNKSUo1WFcxZnp6eGpvWm1FUmR5SzVnUUFBRkRXeEV1RHpUT0pkbWtLWDF0YldXc1poTVdLSk9BZHhPSExtTTdqT1ZPb1FFeTZ1cTZsNUoyYWFXVmdNQVhvMWtLeXNySm1TNlQwQVIrakVHa3RjWGxkWDgwcHNWYk93aUQ5aGgxaE9wMU5JcGlvWWpRTWd1c3N5RG90dkMyRU5aTXUyYlRjQk9NY2tidEE2Tys2TnJVb1dGa09Ia0VNc2g4TnhGRU5zQVhDa1RyeEw4eVdrZVR4UGZqRTRxbGxZeEorUVBZZ0VsY0pvSEFDanlESU9pMjhiUVFhU2xaVjFJb0h5REVMR3U3Tm56M3h5Y0ZTeXNCZzZCQm1JbEtJSXhnMUVUUWkrMmZLdnN2ZzJZcGlEMk8yNVV4WFY5eEZBU1RxeHkrMnFzY0xJV0h3ck1mUWdRdFVXbTR5RENiSnNrSFd5c0JneUJJWlNjK2ZPVlFuSTBTY3k2QVczeTlVMCtHcFpXQXdOQWozSTVLbFRmd0Jnc2o2UkdLc0dYU01MaXlGRW9BY1JrbkxaZURyMms5bXpaN3d4K0NwWkRGZEsweW9XRStoeUFHQ2lWMHFhQ2xiR1c2ZkRSUVdBcTIrOGNSeTNkVnhsU0NGVVdTdFhrU2xMcjFoRzNPT09JeG52bDdRc3F1dXRUSy8xcFZVdUpmQWsvek1ESHhVM0wvcDl1UHpscWF0UGxrSXNNQWladnlwcFhyUTZkUDFyN2lESXNaSDBrRVR0eFBpS21MZTFIUnovcHZOZlAyNlBWSVlnVGdiNEVnQWdsditKbEg4NG9BTEE2RVBlODBHdzZSTllVNnJpbzlMd29kNWVyK3pZMHVwa0lNRXZJOEwrc2pNZVdWL2NtTCt2ci9XVnoxbHpOa3N1WitQaTRtWUFZUTBFaEdSaWxKaUUyd0NFTkJCQTNzYWdZeUxwUXQyRENTYUNiZHorZzJXcGxZOG5zbmIza2sxTGRrY3FPNUlRQUVBa0x6S0tlVnRkM2JwdDhWQm9PTEZqYyt0VTZJeWpteVBnYmMvdlQzMHNlVmtJOGZIOXFXdUFHUXRDb1Zjb0xXVnBhOVBpcmN4Z0lnQ0FJUzdVQ3huMFduelVHVjRJaGNMOWVKYzRwejloQzVNV2t2TDBpbVFBVjRWSUduUHY3UHVQRENHUEIxTUF1WDRJNlJOelJGWlcxc1NnbzdURURmRlJaM2docFF4bklKT1R4dTNQN1V0ZHpGU0VNTDV4YW1MblVPaEYvSHhISkdncjRxM0VZS0ZLS1ZKQmJQaGlFb1I0UFY0S1JZUGRiaCtycWttWFN2QjVBblFzTTQ4Q2FDZUViTlE2MWZXRGRnMFppZW5oNHVJUlVGUnZyMzk4dm1lK0ZxbWFlK2FzbWdxSjdIRHBtaFRIQTRoWlVBekJmSlZHaVg4enlNaDdERUEzTU9NT0FPYmVNR2RGeWdQTGwyNWFPT0tkVjFVaUpKdSs0dDNWMWRXdDhWR25kL0x5OGlhMGQzUXVCYUdRbVVjVEFBWjNPOHd3d0FSRjFiUk1SL2F6Z3Jpb3RyWjJSeXoxSWViak9meVp6Qk4zZk5oNlBZRDZTUFVrc0xxWXdZbmgwb1VJTzVRYkdFZ2NLR20rWlk5SnVnZkFiOHZTS3o4Q3cyVktTNVJLNS9jQnJJdXBYa01Bd1lSa2syeExYRFNKUUhaMmRscDdSK2Y3QUVvaVhPYXBBTGhCTWpVNUhEbU9XT3JFRkdFQ1RWakc2TVdFQUpTZDhjaDRacjZwMTNZNDdGQXU1aFEzRmJvQnZHK1dNM0JHSE5RWmRGUm1KT3UvUVFKdmpaczJZY2pJeUprakpiK0p2dDJlTkliQjFSbU9IRnVkcS9xSm1DakdtQjRoN01XY3N0UzE4OUNDOEVlVU85c1dBaFQrTGhVQVFJeDdrQWdRNGUvTU9FMHZFNHlqKzFOWDZhbXJwME5UWmdUcUllWVRrcWMwaEJ1S091RVVvK1pNT2xOcThudEVOSlZCQ1FSOEpjSHZlUk50RGM3Ry9FT2h5cTFNWDN1Q2ova2tmeHRMbXdvMlVHRHh1aGY5VWxiTmdGQ25BNENRcktsRVBGVS9qSmFnai9yMEY4Y1l1OTAraVFRL3g4SEdzUVBNNndEeFBqTjNRcUdUaUpGaENrOGtDUEtoakl6c2xycTZtbmNIVWk4R1V6bXRtUllwSHdrdUJrSWJ5Sm9aYTVJT01kOGF1Ylg0R2dnNHhMRUk2bnNNNFBMMGltVFdxQUhnWXdNMWcyK2Q3NW4vMStBbW1jcFMxLzZZaU85Z3lTY1FkYjJKcVB2SEtnRFl2TzM3UzlNclYzY2syRmFZRFVXQ0p4UDRWUUJnQnNyUzFzNURNLzRTU1VjU3dnWHdtUURBZ3Y1SGdJMC9QTkUxOWh3eUtBbEpkOEM0RjhCZ3ZsZnplVTkydTJ2dmNydXIvMVJYVi9QbnV0cnErOTJ1NnUrQllRZHdzQ2M3SlJIaEFRendsZGNyVXg2Y2pPREpLd0RhWkhoa1hIaHZlb1g1YkQ4QTRKdFIvQ01BVTB6aUVGZEZjRndOaEFsbmh4RDNhYWQ4eGFtVk01bnBOUUFCNHlCd1FWSFRvZ2ZOZVowcEQ0d3RUMXY3REJFL0R1Q0VYcW85Z2hoMzJyd2RiOTR6WjlWVWZVSlJVOEU3QUFVV05vajVaNUYwTEorejVteUF6dXdwSXg4VU1MMlpKZEhCb0pKeHd1RndIQVdXdHhpRXpQZTQzYlhMUFI2UE4xUVp0N3ZtS1RDdUJkRHpoaU9jbFpHUlBXOGdkV05GbXg1Q2ZFaUNsNXFGb21zSjEwQzl2VjRoeHUwbWNTY1RmaEdpM2lQTGs4dmpjamxuV2RxYWZEQk9OY3NWeVc5RlcwZHB5cW9aVXNOck1MNE1pb3VhRjkxdnpsdHZyMWRzd3VjRytGcWRlQytBYW9CK0JhQ0VnRWNKOUdsUE1wK3VTdVg1VmVldUdxV3ZpOEdQQkI0STE1aU55QXhMK2ZPZUo5cmUxckwzcnlvQWcxOE9TVDdRV3lXRGk3Z0NRT0I4Q2dGYlc3LzQvTzVlQ2dBQTNPNmF2Mlk2c3A4QThOTkFXWUVNaEJucTlBY3A1ZkgrYmwvSEo4dWFDMThxUzZ0NFQvOG1BbkJ0Mlp4VktjVWJsd1I2bDQrMmZQNURJcHBwS2wvZGtXQjd3K1lOZG52UzFGSFRFTEozT1h3azVLelN0TXJBaTVFaEU0bnBPRUhpZWdiZkVLSkk2L2lrVVM5SFUzZFpTdVZ4RUhnVmdQN0hXVkxjWEJoeUwyWEgxdFpiQVZ6Ukk2SGZ0MHRsaVhQVFFzT0wyem5YcWRxK25yZ0VRQ202Umx5bmVRK29kd0JZN3MvVElkVmFtL0N0UkZmb0tqVkJLamNDK0Uyb2RrdlRIcHdJZE03M1B6UGtnMDQ0cFFyQVlIVkUxQmJGM3oxSThBV21rZEVmR2hvYW9ocjdDdUpISkZPUGdRQjJoeVBiSEhpNzMyenhOazlQOVBwdGx6SG0wRGdjczNQS3B3QkFMRXFaK0dsZGRvSlVmZ0hneGg0Qm1Yc0tTY1RsenNiOFEyV3BsYnRBT01ydzkzUXQ5Y2JvcGk1NjFMaFFJd0RxWGtJUGxSdFludCtZM3htcDFudFNmemNOaE5jQVRPOHB6TXVMbXhhRlBJVG5QT09SMGZDMkxmTi81d1IyRlRVWDNod3liNFBUQjJCRldWcWxRSmVSQU1TM3JUNTE5Y3JGSHl6ZUN3RE9UUXNQbHFaV1ZoT2hleFJDUDYyMzE5OGJha0dBdVBNbm9NRHFhRnVTbEg4RXVpelBZQkJkbTI1REF3bjZqdjVaSTQ1Nm9qMXIxcXozQVFTK1JBYkdNWERKUUgwNkV0dG5IQmk3RDEyZi9mamltTSt3ODlqUFJnUEEwcGJibmdYUWJGSXBweXlsOGpnQUtFK3Z2QmpCTWNlZUttcGExTFdDU0JTMDBSblBwVjQ5ekhpd3FMa3dpbFZCbXFxUytocUFFM3RFdkx5NGFWSFl1R3Eyem82TDBlTkkyZGtwNUM4anRkSis1Sjc3MERNZkd0ZnVvMHVOK3RJRDZON05aZkMwajdkK2ZvV3BDakNZUUxyUkJxUEc3NVFwWUpqUUFpeG95RnhFVHlERHBhQkNLaUdYOUVMaGREb2xBUkZkdEFlU0w0NXVmUXNBdXBjVHpXL0pCQWdzQWdCbUJNMUpCTWx5M1dPUWdWQ2tQWmZZczVmQXQ1VzBGQzZNTXY4OEFDZjFQTktkdlJrSEFJQjduR1laZU9lT2pVcytpOVNJczhIcEErTjVYVHZuNjlPWGJTcllERWFQbHdCVGtDTnBXZnFhU3dITThqOUx3c1ArZjZzQURxQm5aUUdDT2VKWmdjR0NJWGVSYm9qRlFqc0J3TitqS2J0Z3dZSmpPbjF5TUkzOUM0WDRNZi9EaWJPbjFPM1kwbm9uZFAveEFHNHVUNjk4a1JtWG1NcSt1TFJwY1dERmhVbittMHo3aXhTL2xhd1BHYWl3S2JMZVAzVHBCenNUcFM5b1FoNEUwelQvMTAzQU9XVnBsZEc2MWdkV0U0a1FQQkVuUEFUZ1BBQmc0QWNyMDllZThNdW0yejdXdGZ0enY4c1FnZDR1Ymk1bzlDY0pFQXlUY2dsTWpGS3BtRU1rTnVxZkJZdHJvaTNyOC9GMUJnSGpIVUY4Wml3K1lPMzBCRlhNMEY4Rk1kOHpYNlBnWG1RTU01NkJlY21aWVhpemt0U3YwQVQrK3VuUi91MTlSWURtRmpjWEVrSzd4VXdoaWZYOU1BNzk3MnF5Vnlndk9WTWU2UDNsUzRZNDBJbm8raTFHOHdsTUN4aVlZSzYyWGU1NUN1QXZ1eCtGRHpJd25DcExxVHlPd0lGaEY3TTBMRHVyelBRWmdVLzNDd1Q0SkF3Um1IZzlNZTRNUElQdFdWbFo5OVhXMWpiMlZzNXV0NDluOEhLOWpBaFZrY29OTkJNU2JkVjd2TzIvaG42U2FnNEdEbW9vYmlrd0w1a0d6MEhBQTdiQUVBNDFzWE9oejV0d0FZeXhDU1pBb01vSjU0Vk9SSC9DbElGbkNOd09CSVkwNTlnVTM1K2MwNSs0UE56cFJDTGF6UnhZR0RnQW9NOFh3Ukw0WTdQTXVjbnBMVStyZUlMUk5iUWx4azFyWnF5NXEyQjdRUWVJOGdGV3VwWGUxWDV3L0ZQNnNpb1J0b0o3emlFd3lPeWJGVGZxYW1yZXlYUmtONkxINzBlUlRFL2JjM0l1OFZSWGJ3OVZ4bTYzajFYVUJBK0F3QzQzQVFjU0VwUitINFB0TC9tTitaM2w2UlVydXllS0lTR1dRZU55U2ZKVEVieDVQV1hOakRWSkJkc0xPZ1phVHorM045NitxeXkxc2dBRTgvL1YrVWxwRXdyUkhPNlVZakFFNXZibXZiZU1TcHR3QklPNmZPSVlGeWFOTzFEbm5PdTh2bnNWeWdDejRjZjlqK0xtUXZOUXROOG9QdlVobjZyZGppNWZ2YU8vc2Nscm5Tbk9aMEg4RTUzU2o1bU5WeEREN0hzMWU2Q1VHZ2dJWWltTVB1WEhLeHIvdytISVh0UjFscVdMeXk2N0xDa3pNL3NHUlUxb0JNaXdLY2pNZDY5YnQrN3J3ZEpaejZoRDRuRUE0U2FiN3hhMUxIclZMSlNDUTducmkzWWJ2anVneW9XZ3VLV3dIb3luelhJQ2xhNU1yVWp2UzExT09PV0V4RkUvWXNJTFBmWHcxYmF2Sno3aGhEUG9EVURTc0U5MWZ2bHBhNzlqemhPeW5UTWU2YzE1RlFCdys0ZTNmZ0p3b0g0aThUT2JtSGdEZW5wTHFaQjQxRnhPY0xDQlRNckp5VEc3UDhRTmw2dHFBd0gzbWNRVEdWZ3RtYjdNZEdSdHpYUmt0NHlmTU9sckVEd0F6VExrSkx4eXhCRmpLd2RQWXlQZGIveVE0Wk1Jd2IwSEFQZzI3bThGRU9RcG9NWGE3YjBibVVBL1IvRHdKa2tqVWR2WGs1TDVqZm1kU1dPMCtRQTE2TVE1U2FrVDE1cnp0aDI5NTAwQWZsL0FCUGJKKzBNWmtwN3k5RFgvWmZPMmYxbVdWdmxNV2RyYXkzck5UK0tobmdlK0FBeG40SW53a21IaTNvMFFRcllBTUl3dE82VzhvRGVsQmh1WHE2YUlnVWRDSktuZEJwRUNZRXh3TXIydWRYcXZmL1RSUnlOdWFzV1M5a1RidzdwSm9wOFAyNXIzL1NsVS91NnhmbEN2SXdacEwyVFord1ZmRVdoeGNBcW4ySTdZSDNJbnVqZVd2TDJrcmIwTjF3RDhubDlHaEZ2SzBpcnUwdWR6TmpoOVRQUXJuZWc2VzlyRXAzNTc4dXFnRjNhOXZWNHBUNi84RVRPdlI5ZDNmeDNBOTV4aVB5V3N6OTJKeWNlK3hJUlAvQ3FBb1Bka0NEa01GclcxdFhzQU1xd1drVFNlVVI4Q2NKMnI1bWNFK2ltQUtJWkszQUdnOUl2Vy8xemk4WGppN2x2bWJNdy9wQkZkektCNWdZL1VydTV0MHNzaEp1cHlFUGRDaXBvTGFnQThHNVRBV0ZLYXZ2YWk0Qks5NDl4ZXNGOU45RjBHZ3pjQS9ib3N0ZExnajFiU1ZPQWl4bU02MFhXS0t2NVZsbGI1U2xsYTVhcnkxSW9WcFdtVjFUdTJ0SDdLakNjQitJOEs3Q1BXY25vN3dUbmZNMThqcHNkQ0pIM1UwYlFucEJ1U0NnQU0za0RRK2ZzVER6VURBUUM0WE5XUDVlWGxQZFhlN3IwSmhBeUE1c0FZVmFRRlRDOHFDdTZ2cWFrWlVuR1psamNWdGdCb2lib0E0ZDltVHcvaXdkMEwwWHh5b2FLS0N3Qk0wb2tGc1Z5M0ttVlZlbDlEQU4zZWVQdXU4dFBXem1PZi9GLzR2WFFKSzByVEsvZVdOQlVHZnJnVGtteTM3TzVvOS9hNGlDQVJYUnVQODVnSUlicUkvd2lTMXl4dFh2eGhKQjJFVkI2VHd2ZHI2SDgzaklmRHZheTZ3djV3VUJTVG1mYWNuQ0d6bXFYbnlTZWYzT3QyMTk3bmR0V2VwZm04bzhEYWNacFBPVjd6ZWNlNVhUVnBibmQxOFZBempuNGhnM3NRME9DZUMxbis0ZUpXSWl3SmtUVFZTMHJRaERZYWl0Ni83WFBCTkEvQTU5MGlJc2JEWmFtVkFVZkIvTWI4enBLV3dvV3l5Mm14dDZYNS9TRGNoMFJicW42anRUZVdibHI0QlJQMGpwWnQwcWVFZFoxUkFlRFE2TVEzUnJkMXRFTzNJNmxxdkFEQUhkRTBHaTg4SG84R0lNU20ydkJIZ3RjS2tHR0l3MXF3STJsYm03TEJsbVIwUnlkRmhuZXhrZUw3TEZoLy93dlkyeFkyQmxwUlUrRWZTK2VzYVlJMEJ2WUFkWG5VNnBkclZaLzRiYWVxZGMwVkZRNDdGRjdhVXZEUmlwUUh6dENFTDdEckxRV0NscStYTlJlK0JPQ2wwcFJWTTZBb2M0WEVWQkNQa295dlFHTGptRGE4MmRkbDcrNWdmL3JWT1BleUxiZUcxVFhRVzJVNnN1c0F6TmVsZlRJN2VlYUpWdmhSaTVGRWVYckYxY3owblArWkpaOWRzbWxSV0NmWXdGdUJCY3loUm8vZnZHM2JrRnJOc3JBNGJQVE9pb3gvOUdZY2dNNUFkbjcyMlhvQU93Mkpra0tOUHkwc2hpWDNwUDV1R2dNQmQzZ1NDRHJ1YXlaZ0lBME5EVDRRR1hzUndoVVpHVGx6Z2twWldBeERWRkp1UnBlckNRRHNhVXV3ZVNLVk1VeThWSUZWTUo2aElGTFlGRG5jd21MNDRaenJWQUg2c2YrWm1COExGekpJajhGQXFxdXJXeG40b3lFSDQ0YU1qSnpUWVdFeGpFbmFOZkVxOUp5TFoxSXAvSlVTT29MOFZoVGlGZEJIQkFFVUluN1k2ZXpkSjhiQ1lpaERQVzczSU9EUFN6OG8vR2R2K2YwRS9laHJhMnQzZ09rUHB0clAycnAxKzQzbXZCWVd3NEdWNlN2SGtNQmVBbm02UDFGSHB3L3AySldibTN1a3QxUGJBaGdpYTN5dEtwUTJWQU5iVzFqRUFpV1VjT1BHalcycHFlbDdRWVlMWFVaTHBqTlBQam01YXZQbXpSRmpuRnBZakFUQ3ppdG16NTc1T0lDM2pWSytRRWxJK2xYSUFoWVdJNUJlNDlYYWMzSm1LQm8zd25pT1dpUFFsUzVYOWZyWXFtWmhFWDk2WFpueVZGZHZad3E2dTBKaDRxY2REc2U1TWRUTHdtSklFSElPb21kVGMvUG1sTFQwS1FUb1k4MG1BSFJOV2xycTh5MHRMYnRpcUorRlJWeUphbTlqVkZMQ0lnQnZtc1JITVltWE16SnlaNFVxWTJFeEVvajZ6Z3k3M1Q1ZXFJa05oS0JRK0xzSjhrcVh5L1YyeUlJV0ZzT1lxSGZIUFI3UFB1bFRyZ1FDaDk3OVRBTEV5eGtaMmQ4ZldOVXNMT0pQbjI5ZHlzakluVVZDZXdVSUNpQ2dNWEQzeWNrejc3RU9XUTBlZVhsNUU3eGVieUFhcHBSU3V0M3VvRXMzTGZwSG4vMnI2dXJXYlZNVk9oZWdKbE9TUXNCZFc3Zis4eTlES2E3V1NLZTkzWGUrWkhyUC93RXBmNHRjeWlKYSt1V0FXRjFkM1NwSXpqV0VsZStHZ1F0OUdtL0t5TW9wdEJ3Y0xZWTcvZjRCMTliVzd0RTA3end3UFI0aWVTSXhWMnpadXYzMTdPenN0TVBRejhJaXJoeldHOTdqOGJTNTNkVTNFYkFBcG90NHV1RHpOSWtQTWpPem43Zk9sRmdNUndaa0NPUnkxVlFUNUZuNjBKS0dOZ2hYa3VCM016T3puM1k0SE9kaGdLOWt0ckNJRlFNMlIzQzVYRnRtSjg4Nmg0Q0YzSFZ0YjNCYmhCOHl4SnVaanV6dG1abFpkMlprWkF5WnUwZ3NMRUlSa3plNXcrR1l6QkRsNkJwNlJUQkMzZ2FpRFF6ZUlKamZjTGxjTzN2UGI2RW5NelBuYWhBL3B4TzF1VjAxRWE4RHNJaU9tQTUxN0RrNXlZckdKUUN5MFIzRk1RcDJBOWhLNEMzTTJFRkVCd0U2S0VudWcwYjdXR0ZyajBXSGdEZ1h6UHE3NHkwREdVQUdaUzVnWDdEZ0JLVlRXd0tpYkF5aE94QkhLRis2WFRXVEkyZXppSWFJM3J3RHdlYW1wcjB0TGMxL25qYnR1eFdqYktNL1FGY000Qk1IcS8xdkZZVG5XcHFibjRtM0dpT0Z1SzBtNWVYbFRlam84TTJWNElzRWNERURwOFJMbHhIRTEyQXQzZTEyZng0NXEwVTBESm5sMWdVTEZoelRvV2twUWxJeUU1S3A2NjdFb3dHYUFQQllBR01SOGhZcEN3SU9NUEN5SXJCNFJGejlNSVQ0Znk5L3lmYk9oZGZCQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImFhZ3VpZCI6ImViM2IxMzFlLTU5ZGMtNTM2YS1kMTc2LWNiNzMwNmRhMTBmNSJ9fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0xMC0yOCIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwOTI2MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMTAtMDEifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE5LTEwLTI4In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYmQ3OWU4ZGVhZmNhMTdhNDcyZTRjMzdmMmM3Yzg2MTI2OGU0OWZkNSIsImE3MjA5Njc3MjMyNmIxYjI4MmIyODZjM2U3ZDY0MDg5YmQ3YWFhZDkiLCIwMDI4MTI1MGJhM2ZjZjM1ZDk1MTJlMDY3NzEzNWVlYzc3YThmYjdhIiwiODhjN2MzNGIwYzljYmJiZGJiZDdkNGMwZGU0MDRlMTRhNzRiNmM4YSIsImFhOGNlNmZkY2Q3MjJmNzAxZWUwNjU3ZTE4ZmE5ZjJhNjg1ZTgxY2QiXSwibWV0YWRhdGFTdGF0ZW1lbnQiOnsibGVnYWxIZWFkZXIiOiJTdWJtaXNzaW9uIG9mIHRoaXMgc3RhdGVtZW50IGFuZCByZXRyaWV2YWwgYW5kIHVzZSBvZiB0aGlzIHN0YXRlbWVudCBpbmRpY2F0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgYXBwcm9wcmlhdGUgYWdyZWVtZW50IGxvY2F0ZWQgYXQgaHR0cHM6Ly9maWRvYWxsaWFuY2Uub3JnL21ldGFkYXRhL21ldGFkYXRhLWxlZ2FsLXRlcm1zLy4iLCJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiYmQ3OWU4ZGVhZmNhMTdhNDcyZTRjMzdmMmM3Yzg2MTI2OGU0OWZkNSIsImE3MjA5Njc3MjMyNmIxYjI4MmIyODZjM2U3ZDY0MDg5YmQ3YWFhZDkiLCIwMDI4MTI1MGJhM2ZjZjM1ZDk1MTJlMDY3NzEzNWVlYzc3YThmYjdhIiwiODhjN2MzNGIwYzljYmJiZGJiZDdkNGMwZGU0MDRlMTRhNzRiNmM4YSIsImFhOGNlNmZkY2Q3MjJmNzAxZWUwNjU3ZTE4ZmE5ZjJhNjg1ZTgxY2QiXSwiZGVzY3JpcHRpb24iOiJZSzQgU2VyaWVzIEtleSBieSBZdWJpY28iLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJ1MmYiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjoxfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiZWNjX3g5NjJfcmF3Il0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCIsInJlbW90ZV9oYW5kbGUiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCIsIndpcmVkIl0sInRjRGlzcGxheSI6W10sImF0dGVzdGF0aW9uUm9vdENlcnRpZmljYXRlcyI6WyJNSUlESGpDQ0FnYWdBd0lCQWdJRUcwQlQ5ekFOQmdrcWhraUc5dzBCQVFzRkFEQXVNU3d3S2dZRFZRUURFeU5aZFdKcFkyOGdWVEpHSUZKdmIzUWdRMEVnVTJWeWFXRnNJRFExTnpJd01EWXpNVEFnRncweE5EQTRNREV3TURBd01EQmFHQTh5TURVd01Ea3dOREF3TURBd01Gb3dMakVzTUNvR0ExVUVBeE1qV1hWaWFXTnZJRlV5UmlCU2IyOTBJRU5CSUZObGNtbGhiQ0EwTlRjeU1EQTJNekV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy9qd1l1aEJWbHFhaVlXRU1zcldGaXNnSitQdE05MWVTcnBJNFRLN1U1M213Q0lhd1NESHk4dlVtazVOMktBajlhYnZUOU5QNVNNUzFoUWkzdXN4b1lHb25YUWdmTzZaWHlVQTlhK0tBa3FkRm5Cbmx5dWdTZUNPZXA4RWRaRmZzYVJGdE1qa3d6NUdjejJQeTR2SVl2Q2RNSFB0d2F6MGJWdXpuZXVlSUV6NlRuUWpFNjNSZHQyemJ3bmVid1RHNVp5YmVXU3dienkrQkozNFpIY1VoUEFZODl5SlFYdUUwSXpNWkZjRUJiUE5SYldFQ1JLZ2pxLy9xVDlubURPRlZsU1JDdDJ3aXFQU3psdXduK3Yrc3VRRUJzVWpUR01FZDI1dEtYWFRrTlcyMXdJV2J4ZVN5VW9UWHdMdkdTNnhsd1FTZ05wazJxWFl3ZjhpWGc3VldaQWdNQkFBR2pRakJBTUIwR0ExVWREZ1FXQkJRZ0l2ejBiTkdKaGpncFRva3N5S3BQOXh2OW9EQVBCZ05WSFJNRUNEQUdBUUgvQWdFQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWp2anVPTURTYStKWEZDTHlCS3N5Y1h0QlZac0o0VWUzTGJhRXNQWTRNWU4vaElRNVpNNXA3RWpmY25NRzRDdFlrTnNmTkhjMEFoQkxkcTQ1cm5UODdxLzZPM3ZVRXROTWFmYmhVNmt0aFg3WSs5WEZOOU5wbVl4citla1ZZNXhPeGk4aDlKRElnb01QNFZCMXVTMGF1bkwxSUdxck5vb0w5bW1Gbkwya0xWVmVlNi9WUjZDNStLU1RDTUNXcHBNdUpJWklJMnY5bzRka29aOFk3UVJqUWxMZll6ZDNxR3RLYnc3eGFGMVVzRy81eFViL0J0d2IyWDJnNElucGlCL3l0LzNDcFFYcGlXWC9LNG1CdlVLaUduMDVac3FlWTFneDRnMHhMQnFjVTlwc215UHpLK1ZzZ3cyamVSUTVKbEtEeXFFMGhlYmZDMXR2RnUwQ0NySkZjdz09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWZDQVlBQUFDR1ZzK01BQUFBQVhOU1IwSUFyczRjNlFBQUFBUm5RVTFCQUFDeGp3djhZUVVBQUFBSmNFaFpjd0FBSFlZQUFCMkdBVjJpRTRFQUFBYk5TVVJCVkZoSHBWZDdUTlYxRkQvM2Q1OXdlUVNJZ1M5QVFBWGNGTEFRWmk5ZnBlVnoxdFkvV1RacjVXeHBjN1c1a25MYTVqSTNaODVzclMybk0yc2p0V3daUzdJVUg0SDR4Q25FUXg0REFaRjc0Vjd1czg4NXY5L2xJbkJ2VkovQjRQdjludS81bnUvNW52TTU1NmZ6QS9RdjBIYi9JclgzVkZLUG80NWNubTRpblVJV1l3TEZSbVpRVXV3akZHL04xaVJIaDFFWjBOUlZSdWRxdDFCZCsyblNLeVMvT2h5czArbGszZS8za1E5cXZENFpVdGE0VlZTVXVZMGVpcHlpVGhBZm9jb09SVmdEdXV3M3FLUmlBZDNyYmNFdGpUallJb2Y2V2FIc0NtelZQV0NNeCtjZ2g4dExxV01LYU1Xc1VqTHFvMlJ0SklRMG9Pem1lcnBRdTRlc1pnc09Oa0d4SDdkMGtkdlRUMTdzNE9NVTdWSThaaGpnR2FNK0FxOWlFTnU4UGlmMXVkejA3TXd2S1dmOEdsVm9DRVkwNFBDNVdkVGFYWUZiUjh2TnZMNSszS2dmYjV4Tk15YTlSYW1KaXluYU1sR1RWdEZscjZiYTl1K3BxbkVYNHVNdVJSZ2pTWUVock43dXRGRmU2bHFhbDdOZmt3NWltQUdIeW5QcGJrOFZtWTB4c3RucHRsRkNWQ1l0elR1Qk44M1FwTUxqVHRldmRQelNVbko3ZThta2p4WjM5ZlhiS0RmbGRacWJ2VStUVWdHbkJWRjZmUTJpUEhnNFcxNlVXVXd2emJrMTZzTVpFK1BuMHB2ejdKU2V1QXllczhsY3BDbWFLdW8vcCtxV3IyVWN3SUFIV3J2UDBZRXpoWEF0TEFic3NIaHA3aUdhbXZ5aWpQOHJ5cXJYVVdYOVhvb3d4eUF1Zk5CcnA0M1BPQkZYWmxrZjhNRFJpcWNweW93QXdwdXoyeCtmV3Z6L0R0ZGU5c21zenlndGNSNkMxd2JkekJsNk9scTVXTllZNG9HYXRoSk1ya1RFeDBqQVJTSEFWcys1cllrUU5YYitRZ2ZQTHNRNmdYeUluc3JlUWZtcG03UlZGWWZMODZuMWZpVU9rWXZTaGtVUHh2YnVrem95NksxaWhNMWhvM1h6VzZFdlNmWEErZHBpV0dhV2QrZG9Yekx6bUd3S1lGTENBc1JBbFBCQWhNbENGWFU3dEJVVlByOEhnVmNKSFdxK0YwMHBscitETVRkclA0enZ4WTExa05NaHhUK1NlVEdnK2Q0VjVMUUppdHlVR0pOQjhWRlpzamdZQlpNL0lJL1hDVGtqMHF5RE9wRjJBVlExN0NJalVwL0RuVDFVa0w1RjVnZGorc1Mxd2cxZ0UzZ2lnbTYwZkNYelNuUFhieUFQYklYditJRHBFMTZUaGFISVM5c2t5aGxtTUU1RjNjZnFBS2hxMkMwRTVQSDFnWWFYYUxQRGtaRzBIREpPbktXSHA1MUkwejVTT3V4OGUxV0F1WnpkSFFyVGtwOFRtalhvSStsYTB3R1pzenVicWJPM2lmUTZBL1c3dlZTWXNWM21SMEpLd2tLYzRXSGlCa21SOEkzQ0NnSTg3b09MNHF6VDVQK1JVSkJlakVPZ0FQSzhoWVB6YXRNK2VJVHAySU85eVRRbWVyb21QUnh4MXF4QWNzaWxlL3ViU2VFYmNXUUdZRUNnaGNMWTJIeUtqb2dqSDI1aE1wanBVdjFPdWdsaTRlaDJlUncwTzMyYkpqa3l1Q2dOemcwdnpsWU1TaVNzMHVvbzRNRzdoTU9qQ0VhWDF5RkUwblN2akJ6dVRuRXBLODZaOElvcUZBSXVidzhrZzlBckVhUkVXU1pJK2pINFhicDZnOUU5RW5KVDNvYVJ6RE4rTVVKQlFESG41NmE4b1VtRUJ1c094QnMvTjUrdEpFYlBrQUZEajhVR3ZPcy9JV3ZjU2dsR0JodlM3L0ZUWWZwV0dZZERZOGZQQXhXU0EzNXNUQzRwNCtMbTRBYXFJb1BlUXRmdWZLNkpoMFpoeGxic1VYT1NtWE5pZkQ1WlRBa3lEb2ZiYmNjbHhuQThXTkFxeENiUk55a2hYeFFwYUR3NjdmWFVZYnNpRzBLaHR2Mm9lSXZoOHJoUU1ZT2NFQXFYRy9lSSt6bmdPYzV5eHI4cTgySUFNMWMvRkxGT3BscXU1ZUZRWHJNWnpHY1ZDalliTFdHNUk0QlQxZXVScmxieHROT3RNaXREREVoTFhJSXluQUF2dU9FV0UzWDNOZEFmdDk0VmdhRzQyWElRdDBaWDZQZUNFL3FRRmU5cks2SHg3WVU1MEt2SDdmVzRmUytxN0tLQkp4c2dnQlg1cFNBR2gxaklyVmg1elE2dzNSZmFhaEJYbS9hQ2JDWlRqQ1VGVVR5V1pxVzlwNjJNakpQWFZxT3JQZ01PNE52NzRHa2Yrb3dmdE5WQkRRbmpGSnFIU3cxN3BYdmhXVzVLWnFlL1E0OU4vVVNUQ0FWV29RWEZJSEJIWFhlM0ZQclVEc3VHRG10Ri9oSEtUSHBla3hoaUFPUEkrU0pxNlM2SEY0STlZV3prQkpUbzQ2aVVNeldwOFBpci9SaWR1THhLWXNTa3NWOHZMbE9RdmhHWDJZbFIwT0JoQmpDK3UvZ0VjdlkwQXBLN1lrNDFOeGpQU1FuV0ZIVEY2NlVyamdldkI4Q3U1YStsMnZZU1JQdHVWRG83M2hoZE1TSG5VWDd0VGpzVlpHeEFsL1dwdGlPSUVRMWduTDI5bVg2L3RSMXRtbGtZajhXNFgrQ1NqV2NVREdZMU5wUy9DN2hTS3FpTUxNL2wyUW1TV1o3M0RkeitnaW84QkNFTllQUTQ2cW5rendYVWJxdkJreGpVUXNXZlpGZ2J1bzNyQWYrd043ak9POTAreW54NFBpM0wrMG5ZTDFTY2hEVWdBUDRnUFYvN0lkMXErMUhTaG11R2tJcVdSUGd5eE1GcVA4SGZqVG5qWHdZNWJRZmJKY3Q2T0l6S2dNSG90Ri9IZTFlZ3NheEhTcUc2d2ZkbVE1eDhOeVRGRnFCY3AyaVNvd0hSM3lrNSszNmhGN3ZYQUFBQUFFbEZUa1N1UW1DQyJ9LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRCIsImVmZmVjdGl2ZURhdGUiOiIyMDIwLTA5LTE2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJZdWJpa2V5IDQiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IlUyRjExMDAyMDE3MDMyNDAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS4yLjUifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIwLTA5LTE2In0seyJhdHRlc3RhdGlvbkNlcnRpZmljYXRlS2V5SWRlbnRpZmllcnMiOlsiMGE0MjZlZTE3YWZkMTY1MzNiMWNkZmE5NWRlMWU5MjBhNmFlZGYzYSJdLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImF0dGVzdGF0aW9uQ2VydGlmaWNhdGVLZXlJZGVudGlmaWVycyI6WyIwYTQyNmVlMTdhZmQxNjUzM2IxY2RmYTk1ZGUxZTkyMGE2YWVkZjNhIl0sImRlc2NyaXB0aW9uIjoiVml2b0tleSBBcGV4IFUyRiIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6InUyZiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJlY2NfeDk2Ml9yYXciXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWxlc3MiLCJuZmMiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNOekNDQWIyZ0F3SUJBZ0lVYzhjUkVzWThrK3R1L0FsNWFmWUVZUjBuQzVjd0NnWUlLb1pJemowRUF3SXdhVEVMTUFrR0ExVUVCaE1DVlZNeEVEQU9CZ05WQkFvTUIxWnBkbTlMWlhreElqQWdCZ05WQkFzTUdVRjFkR2hsYm5ScFkyRjBiM0lnUVhSMFpYTjBZWFJwYjI0eEpEQWlCZ05WQkFNTUcxWnBkbTlMWlhrZ1FYUjBaWE4wWVhScGIyNGdVbTl2ZENCRFFUQWVGdzB5TWpBNE1UQXhOelF3TURsYUZ3MHpNakE0TURreE56UXdNRGxhTUdreEN6QUpCZ05WQkFZVEFsVlRNUkF3RGdZRFZRUUtEQWRXYVhadlMyVjVNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNU1F3SWdZRFZRUUREQnRXYVhadlMyVjVJRUYwZEdWemRHRjBhVzl1SUZKdmIzUWdRMEV3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVGtqMDRvNWc1cWQ5SmIvb200YkQ0bHhXd2NscFNrUm1Gcy9sSk5XUklrVytrb3Q2Ni93Ukh1MlN1LzFCVEplZ1NFalBOMlUwVityMnFKK3hWY3VYam96dlNLcHRzMmFpMzF0QnV0bnFZWG92Mlg0Vk0wRzE0R0ZJaUhEam1xVXF1akpqQWtNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQW9HQ0NxR1NNNDlCQU1DQTJnQU1HVUNNRTFUb25xRVp5czdTd1RNUGNxaTN2N2lKM2hrbHpua1ozenpWd1BJdDI2MFFPZHVUZXlaWi9oMndEVkR0dGZYbUFJeEFKVFVHeS9PdlNHZXR4Vytna0NyeC9RQlNQa0kwYlRVRVhua3c5bDMzVGlHb3c2VUxaKzUwUSs5Ni9jR2hLYmtwUT09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUNBQUFBQWdDQVlBQUFCemVucjBBQUFNT25wVVdIUlNZWGNnY0hKdlptbHNaU0IwZVhCbElHVjRhV1lBQUhqYXBaaHJjaU01RG9ULzh4UjdCQklrK0RnT254Rjdnem4rZnFESzZyYmJIVE85WTltcVVsV0pCSkdKUk5KdS8vWGY0LzdEVDVTUVhOSlNjOHZaODVOYWF0STVxZjcxMCs5NzhPbSszeDk1YnZINTAzWDN2aUZjaWh6ajYyUE56L01mMThON2dOZWhjNlkvRFZUbmMyTjh2dEhTTTM3OU10QXpjN1NJN0h3OUE3Vm5vQ2l2RytFWm9MK1c1WE9yNWVjbGpQMDZybytWMU5lZnM3ZFVQNGY5eStkQzlwWXlUeFRaTVVUUGU0eFBBTkgreE1YT1NlWGRibnQ3NXp4R3ZkYy9CaU1oMytYcC9kT0k2RmlvNmR1SFBxSHlQZ3ZmWDNkZjBVcnlQQksvSkRtL2o5OWVkMEcvM0lqdmVlVG5tVk45enVUejlYajhlRVgwSmZ2MmQ4NnE1NjZaVmZTVVNYVitGdlhPbXAzd0hJTWttN282UXN1KzhLY01VZTZyOGFxd2VrS0Y1U2N6RHM1YkVKQTRJWVVWZWpoaDMrTU1reENUYkNlRkU1RXA4VjZzc1VpVEdRMi9aSzl3cE1RV0Y4aEtuQmYyRk9VZFM3alROai9kbmEweTh3bzhLb0hCZ3ZIaVQxL3VUNzl3anBWQ0NMNitjMFZjSXBac3dqRGs3SjNIUUNTY0o2bDZFL3p4K3ZwanVFWVFWTXV5bFVnanNlTTF4TkR3UXduaUJUcnlvSEo4MVdBbzZ4bUFGREcxRWt5SUlBQnFJV3JJd1JlUkVnS0pyQURVQ1YxaWtnRUNRVlVXUVVxS01ZTk5GWnVhcjVSd0h4VVZManV1STJZZ29USEhBall0ZHNCS1NlRlBTUlVPZFkyYVZEVnIwYXBOZTQ0NVpjMDVsMnlpMkVzc3lSVXR1WlJTU3l1OXhwcXExbHhMcmJYVjNxUkZSRk5iYnFYVjFscnZ6TmtadWZQdHpnTzlEeGx4cEtGdTVGRkdIVzMwQ1gxbW1qcnpMTFBPTnZ1U0ZSZjZzZklxcTY2MitnNGJLdTIwZGVkZGR0MXQ5d1BWVG5RbkhUMzVsRk5QTy8yTjJnUHJMNjgvUUMwOHFNbEZ5aDRzYjlTNFdzckhFTUhrUkEwekFCT1hBb2dYZ3dCQ2kySG1hMGhKRERuRHpEY3huUk9DVk1Oc0JVTU1CTk1Pb2lkOFlPZmtoYWdoOTY5d2N5Vjl3azMrWCtTY1FmZUh5UDJLMjNlb0xXdEQ4eUwycWtKTHF1bWc1NWt1dFZ1amt3WXFxOFNseERwYjNyUFFzdFBzMjFNTWUyU3ljaFlCclRKS0lwQTk0aDZ6NTBaYWlQV3dNZ0krTGV5NmxJc3phK0JPMTd4ZHoza1BQVDBzb2FiNnJDeS8wOExDbktPcGJ2SmhXUUNTSXJHdjBRZkxCTUFvdlczbTliMXN0RmhkSFR3OUFLWlZCRk9Wazd5clRyNCtoRnl1MHhLNXlKR0psKytrWitSTW9TS2dsYVdVM0hRVW5kc3QxYjV6Q2FPdFRJaE0yb0d4c3NLanhYNWgwZW16c0J5V1N4WWpnKzgrMTRvTXdHZ3JqWk5pZHhNYys0SVNJOFRzbjJ6Nm5wV3BZeWF4aStsVVE5OVRSaUkvYVk0U0o4dXRxL1N5b0wwdWFzTTFLTGdoSENUUUdMZU4wOGwzc2hFYjMvSXNNZmVSK2hnc0xMZWxoMXoxdG9BOHp0TkhrUUdqcHV0OW5yWjVBaFFET013bjVhdUhkT2Fjd2tKbkJacDJMQmw4TWNkUVo5N1pMNlBnc0t2d3pYVWRQZEFFRzhnMTZMRThsVEpnMlN4Ykl2UktQTXRJRkl1V2xIS1kxQVBwWndvTmpKU0poRnJJanZxd1R3TlFOa2hUbmN0dkVwNDZURTZaRFBXdHdpUEQ1N3BybXF2ZlJNSVMzMmN5UWt5cXBibzBxZXQrVW9Qb2VnRmVqVDVJRHFPVlExbG9OdHBkN1JrYmsyamhhZHE3dEx3eWRjTVhTcHNMcVYwRVF0RVVnVU02UnliVnRRTkE2ank1YWJPN2hWdHFUUmJsclJOUjhZVVVndEdrMU1iY01yTGJvMG8zTGk4Z3BUNHBaM1JqZ3o4aVpha0czVUZaUlE1S25La01LNUNvOEw2UFFFNHFBaXpkNVVCaUlua2hWNXd1VWxxTW1Nd1ZSMVY2elFKenYxWU5NcHBuS2NHNENtdG5BVjhsbjJGUmxmQkkxbEY3aU1DVU1seTNBbGdYQ3pIU1FmSXkvSXJVSzhSdXhCSVNwZG9DblZLcjBZLzN0QnhLSHl2bmFCbzZkWkkyUUpJRWtmT29uWWxUckdzdVJIaUVreEx5eE5CYUtJYkNVeEV5bUZiTzZRcUNYNk51VXNodlNaUGFSQXZtVWdHVzN1YlFOTUNMbktVd0Q0WEUwR2dQUGp5WVltUVkzTURHd1hCa2IwSjI2RDFRY2M1cVM0WW9VckZSSmQ4Ti9LNEpCbFZLa0lDcFZ1U1VGbUlCbXBoTGM0bzBRM2c0ZVZLZ2dCc3JBblBFNEhnbzBZaVN4ZExSNTRBWFdZVDZZNzFxZWVxMGoyQVpSQzdjVGFVbUdDdU5pYWcvNHkwcjZLYWEyUXFXTC9kQVFWTnBDQUJDajdqNU9PZXlFbnhwYng3VUdqV2QyNTJhMlNpeHNWYzJ0RG9wcmErVTVqakk5cmExR3Jxb1BCeEg0Y0FpMGlOWXQ3Z0J6Mkp0ZlE4ckg5cVEwU292TDhhdVF4WVdlblc4VlZDMWlvRmZxWkx6VGFtZHRqYmZ6OUJ0dUVCeklaUmwwblVRWjFvZzd6dVp6TkJ4V095ZTFJSmhnTlpBQzRETjVwUFF5Z1dyU2FhbGc0MGZYWlV1YVBWczZtTnlKbGNYTi9LeDZhcTBMZlRHVW5nWTlhV2hMSlFVV2grQWFnc2l6SVNNUUpjeTRzb0pKQlBFaUsxRHJyYmpGYTVqTEZzZWhwREtma1dJMzlrQzl4akg5azFvYUYwdXNseG9UdzhvRlJnN3RXYitnQzZBcFNidWhrRHlkdWpqaGRhaXRXRXR0cEVVL0pOMUV0U0RkYnVzUHQ0dWlFS0JCRzJ0NXBQSWNhR1VXQitsd1ZlaXQvUUlhN3M1cUQrNkJGcWFrU1NLTnBZTTdKbjA2cHJLQW5OZldTWmlXT2svdGhLaVowd2tkZUY2SUJEZHFGdkI2QlpUTTE4UHV3WTNVQXAwSHdSWXFiYzRRWW1sRU1HcDlhQTBwa3hrS3VpZ3JjeTlQUS9EYWlDZ25aSTdYTTJNMlJFV3NvSis0czNLc0V5UkZkTkdOQnR4VHhFMVIxZm5JTU5VRVNqWklwR0xUUTEyNjZjTWlVZDJONi9XUUxsOVpKQTJ4QjFCRFh2cXpZVGVOcGVzT1FBalR3RVB0Q1B2U0NIa1J0QnNuK3ZFb21BYVJHU1pETUhPRVV4Y3k5VkFPd1NzZXpWaGZDVXNYd0t3czhkZWt5WWs2TUEyQjFkV1NMZGhZSGZxd3VwQUVSeEhNWGRDVHFuQlNBN045K3lEbUp1Tk1McldyU2F5akcvdGF0TDdCMXlqRTdBazloWFlDV0JCbzd6UlA2cWF4R0pkc2lDTGdRaklPNEZTSkxSUjlwbW9xblh4R0oxUzZTSERaQ3lGWnRRRjNiWGtZUm1vQ1hxVDhoZ1ZpQ1lFcEJ0WTVxME04eFNBbEVhclJ4WUtpWkFsZnJjNUVoYVI0U3JsS3pKS3R6QUgyWWs0UFpFYkg1ZUJzMkdaUnpmQnNINlVyUWtYUjdPN0xHMXNsWjRrRXNRa3RPNFhUTzVwVC9KWTBMVms0bkFUaEZPQUhGWi9RbHVlZkN5NEVWYVRNSUY0eVIySzdLQXlDeXkybktQOG1BOE44eHJKaWJSakJmQ3dWaE5qV29QTUdXR3phbkhtZ2dUWXJBcXhzYlkxc3hPYU5DcUptaFFhWmVpUmR3YnYwN3dCeXB2dnpnRFlVQm9NSlhyczBEdUF4MGVaZjZkQUtMU0tOMWl6SWtqZGhIaFp3NFF1TmRHNVhoUFJ5dVpISXA0akRkTGtZTHdJUmdQRklRQXU3YXFGT3JJaFRqZmRhMTNnd2FVVWxHQkYyMmVjakV5U1lxcXVxOE5uZWF5SW1xNVBETXZHdGw5WlJURU9UcXhTUDNoSmJMeDlBbU84Q2JZdFZUN1hleGRkQ0oySVR1TWU5eUdYdEJyUWQ5M05kaDgwZC9ZOW0rMkRXQTliMkx5SUVhTVRsM0tkV2xzM0I5d2ZZYmhvaWpsZlV1SHByaExlR3ZRNUNlK2p1YXVHbUtLdjF1LzdsZWZvR20yMlNManVwMksrMEN0S25LMGNYUlJPc2hzNjVrN3hZS0g1clpUQU5KR2xWK2RpR2hDQytZSWxsRWl4TW9BdWtxYzVieXZNSTNSd1JJRXUwdGJ3a2JSZ01BZTdBVHdWSTlFSWtFdjZJTmxjV081Vkc1dWF6SVZGN2FvSkZpMk9JcVFabTdYRmpTMDR5WTZ4RDA5QlVNdkJ0aUNWTHlRemZjbTJjL24yZDNkRnZOdS9DWDl6dEgyQkdWbkVHaWRhRFNlZkFaZ0d1c0h4WE1NL3M4TzhVTFRFT2Fad1pLTm9XMDRDcVBjaDdENCtEaU9DOHVFa094dkNLbytsaFBsMjhMSG1IcHdsR1VrcUxiMk9rUVQwU3VzRUVrcHozWVA5QndTeTJLNUxMek9SUDNvVVNYNU1LZUlQSDJFZm5LS2dycG5JckloU0dPWkkyVUtSS2NRVTIyRWUyYStzYk53SUxDSk8rK1hjL2ZDdm9yVTI5OUh1dmovUzZUZTdyREd2YjBQOEJlcEJaTklFUU5XRWE3dEJ6cWtIaXdXYkI1UVFGemZBQnBGUDdEM3BPSGdUcW1uYWhvdzJSUkZPYW8vdnl0WHUyZS9SWVp6WXZFKy9TVFd3N3IzdGdJME1rSTljN3BmMVk2Tk5BKzIzQi9TN21jM0IyZytWeEo2eHJzNHVtMFpwdmpoaXU5Z2RDenNTbzhyMUx1WHZGdjNqNkQ1ZmlPR0pkV3h6VUV0dzhvRStIZGswZWd6aTNUQmtzWHhRSzVFcWcrbHdzb2xESDBzSjEwNloyTmx4UWhQQU5KYmdoMjZucE1kaFlYcTlib1MyTFY1dFoxdU42K2JYMkIwSlFEWWFRWG5NYlBtbyt2alBsMlZIOS9NRis0ZUhyUS9WUFpUR3dWbEJNWFlHZEJMY0pKdjRReVFnd2hvcHhOZTJqYmd4dmZESXF0d2M2NjMyUk1rMmY4bEFkb2I5ajRKZGhMZEYyZGNvMENXMi9WMzFyb1NtcGVIdXlpWlNHMm5WVDIvejgyOXIrSGRIOS9WQ3M2NXI2N01TeDJZdStJT2NwNC9sMFNHZ2xscG5udXo2TVpkb2svanF0cmtzMjlGWUY4V2VUTHBoSVVJR01QY050YlUrcytUZmlhOGQzYzhYeWpsbjJmL3Yvd2RPT1pIMThWYVdBUUFBQVlWcFEwTlFTVU5ESUhCeWIyWnBiR1VBQUhpY2ZaRTlTTU5BSE1WZlc2V2xWRVRzSU1VaFFuV3lJQ3JpS0ZVc2dvWFNWbWpWd2VUU0wyalNrS1M0T0FxdUJRYy9GcXNPTHM2Nk9yZ0tndUFIaUtPVGs2S0xsUGkvcE5BaXhvUGpmcnk3OTdoN0IzaWJWYVlZUFJPQW9wcDZPaEVYY3ZsVndmK0tBSUlZd0FnaUlqTzBaR1l4QzlmeGRROFBYKzlpUE12OTNKK2pUeTRZRFBBSXhITk0wMDNpRGVLWlRWUGp2RThjWm1WUkpqNG5IdGZwZ3NTUFhKY2NmdU5jc3RuTE04TjZOajFQSENZV1NsMHNkVEVyNndyeE5IRlVWbFRLOStZY2xqbHZjVmFxZGRhK0ozOWhxS0N1WkxoT2N4Z0pMQ0dKRkFSSXFLT0NLa3pFYUZWSk1aQ20vYmlMUDJMN1UrU1N5RlVCSThjQ2FsQWcybjd3UC9qZHJWR2NtblNTUW5HZzk4V3lQa1lCL3k3UWFsalc5N0ZsdFU0QTN6TndwWGI4dFNZdyswbDZvNk5GajREK2JlRGl1cU5KZThEbERqRDBwSW02YUVzK210NWlFWGcvbzIvS0E0TzNRSERONmEyOWo5TUhJRXRkTGQ4QUI0ZkFXSW15MTEzZUhlanU3ZDh6N2Y1K0FIb21jcXA3SGppQkFBQU5HR2xVV0hSWVRVdzZZMjl0TG1Ga2IySmxMbmh0Y0FBQUFBQUFQRDk0Y0dGamEyVjBJR0psWjJsdVBTTHZ1NzhpSUdsa1BTSlhOVTB3VFhCRFpXaHBTSHB5WlZONlRsUmplbXRqT1dRaVB6NEtQSGc2ZUcxd2JXVjBZU0I0Yld4dWN6cDRQU0poWkc5aVpUcHVjenB0WlhSaEx5SWdlRHA0YlhCMGF6MGlXRTFRSUVOdmNtVWdOQzQwTGpBdFJYaHBkaklpUGdvZ1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNEtJQ0E4Y21SbU9rUmxjMk55YVhCMGFXOXVJSEprWmpwaFltOTFkRDBpSWdvZ0lDQWdlRzFzYm5NNmVHMXdUVTA5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM5dGJTOGlDaUFnSUNCNGJXeHVjenB6ZEVWMmREMGlhSFIwY0RvdkwyNXpMbUZrYjJKbExtTnZiUzk0WVhBdk1TNHdMM05VZVhCbEwxSmxjMjkxY21ObFJYWmxiblFqSWdvZ0lDQWdlRzFzYm5NNlpHTTlJbWgwZEhBNkx5OXdkWEpzTG05eVp5OWtZeTlsYkdWdFpXNTBjeTh4TGpFdklnb2dJQ0FnZUcxc2JuTTZSMGxOVUQwaWFIUjBjRG92TDNkM2R5NW5hVzF3TG05eVp5OTRiWEF2SWdvZ0lDQWdlRzFzYm5NNmRHbG1aajBpYUhSMGNEb3ZMMjV6TG1Ga2IySmxMbU52YlM5MGFXWm1MekV1TUM4aUNpQWdJQ0I0Yld4dWN6cDRiWEE5SW1oMGRIQTZMeTl1Y3k1aFpHOWlaUzVqYjIwdmVHRndMekV1TUM4aUNpQWdJSGh0Y0UxTk9rUnZZM1Z0Wlc1MFNVUTlJbWRwYlhBNlpHOWphV1E2WjJsdGNEbzJPV0V4WW1Nd05TMDBNMkprTFRSaE1qUXRPVFEzTUMwMU5HTTRZVEkzWXpjeFltTWlDaUFnSUhodGNFMU5Pa2x1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TURKbVpHSmxabVl0TVRKbE9TMDBNems0TFRoa01EUXRNRFUwTXpFeFlXWmxZakUySWdvZ0lDQjRiWEJOVFRwUGNtbG5hVzVoYkVSdlkzVnRaVzUwU1VROUluaHRjQzVrYVdRNlpHTmpOamt5WXpjdFlqSmlOUzAwTldGbExXRm1PR1F0WmpBeVpXVXdZVEk1WkRVMUlnb2dJQ0JrWXpwR2IzSnRZWFE5SW1sdFlXZGxMM0J1WnlJS0lDQWdSMGxOVURwQlVFazlJakl1TUNJS0lDQWdSMGxOVURwUWJHRjBabTl5YlQwaVYybHVaRzkzY3lJS0lDQWdSMGxOVURwVWFXMWxVM1JoYlhBOUlqRTJOakF4TlRJNU1ERXdNelUzT0RBaUNpQWdJRWRKVFZBNlZtVnljMmx2YmowaU1pNHhNQzR6TUNJS0lDQWdkR2xtWmpwUGNtbGxiblJoZEdsdmJqMGlNU0lLSUNBZ2VHMXdPa055WldGMGIzSlViMjlzUFNKSFNVMVFJREl1TVRBaVBnb2dJQ0E4ZUcxd1RVMDZTR2x6ZEc5eWVUNEtJQ0FnSUR4eVpHWTZVMlZ4UGdvZ0lDQWdJRHh5WkdZNmJHa0tJQ0FnSUNBZ2MzUkZkblE2WVdOMGFXOXVQU0p6WVhabFpDSUtJQ0FnSUNBZ2MzUkZkblE2WTJoaGJtZGxaRDBpTHlJS0lDQWdJQ0FnYzNSRmRuUTZhVzV6ZEdGdVkyVkpSRDBpZUcxd0xtbHBaRHBoWWpsallUUmtOQzB4TURRM0xUUmpaR1F0T0RBeU5pMDBPVEkxWWpZNU9ETmpZbU1pQ2lBZ0lDQWdJSE4wUlhaME9uTnZablIzWVhKbFFXZGxiblE5SWtkcGJYQWdNaTR4TUNBb1YybHVaRzkzY3lraUNpQWdJQ0FnSUhOMFJYWjBPbmRvWlc0OUlqSXdNakl0TURndE1UQlVNVEE2TXpVNk1ERWlMejRLSUNBZ0lEd3ZjbVJtT2xObGNUNEtJQ0FnUEM5NGJYQk5UVHBJYVhOMGIzSjVQZ29nSUR3dmNtUm1Pa1JsYzJOeWFYQjBhVzl1UGdvZ1BDOXlaR1k2VWtSR1BnbzhMM2c2ZUcxd2JXVjBZVDRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQUtJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBS0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUFvZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lBbzhQM2h3WVdOclpYUWdaVzVrUFNKM0lqOCs2SE10TndBQUFBWmlTMGRFQVA4QUFBQkJNdndOOVFBQUFBbHdTRmx6QUFBTEV3QUFDeE1CQUpxY0dBQUFBQWQwU1UxRkIrWUlDaEVqQVBCSlI3d0FBQWtEU1VSQlZGakRyWlo3YkZQM0ZjYy85MkhIZHB6NEZjZHhERW5JQzVLUThBeVFVSkpRQ3BRV05saGJ0STJxYTlWdTA5Uk9rL2JmMUQvMlI2ZjlXMDFiSjIzYTFrbnRpbWdSN1doWFNpbWxrSklHU0VsREFpSGs2UkRIZVRoeDdOajRmZS8rSUppWUFLMm1mZis2dXVmYzMvbWVjNzduM0orZ3Fxb0tvS3FRVWhTU0tZVlVTaUdSU3VJTDNNTHJEK0gxaDVnT1J2Q0hJZ1RDTVc3RkVpaUtTbG1CbWNmV2xqSTg0ZWZTb0JlZFJzWnMxSkZ2eXFheTBFYVowNHFJZ2lpS2lKS0lMSXJJa29RZ2tJWndoMEFrbHFCM2RJcXJOMzI0cHdKNC9TRVNLUVVBZGNGWlhYalFheVhXbCtSVFUrSmdZTXhINjQxeGtndStraWhRbG05aWE5VnlncEVZWjNwRzBXczFsTmh6V2VteVVWdGFnRkduVFJPUUFWSXBoWEEwUnZCV2xCNzNGTDVRRkhFeFRVQWppVlE0VEFpQ1NJWFRqRG5Yd01Yck4ra2M5YVY5dExKSS9Zb0Nxb3J0ZUtZRG5MazJSaXlaQWpYS1hEaUN3NlFuR291amt5VmtXYnBMd0I4SWNySG5CdlYxVmVUb3MzaS92WS9KWUNSOWNFcFJhYWt1cEtsMkJZSWdNTzRMY09MeUlHN2ZQQnBacE1KaFJpTkxsQmVZeURVYTZCbWE0T0x3MU8wU0E3a0dMUWMyVjFCVG5NL0FpSnVDUEJ2TG5RNEFSSUJJTk1hZmo1M20weTg3S01vMzhXeExMVTV6ZHBxQW9xb1UyMDA0clRrNExVYXVqZm00T1JNQ0FlcFhPRGk0cllZZk42L0diczZodFh1RTlxSEpkT3VzUmgzUHRkUlFXK0tnOCtwMTNqdDFqdUI4S0xNRkF1QU4zdUx3cVhiOHdSQUg5elR4NG1OcitOZlpIa2FtZzBpaXdKZTlZMlJwdGNTU1NhNjZweEVFVUJYSU54bklNMldUcFpINDZycUhFZDk4dW4wdWk1RkRUVFVVV0xJNTNkN0IrYTZyK09mREdTS1UwMm9FUXJFNHg5dTZtSjIveFU5L3NKTVhkcXpodmZPOVhQUE1NRFFkWk9LTEt5aEFKSkZLQys3Q3dBVDVaaU95TE5IZU40WUtpSUpBdWNQRTA0OVVZekZvT2Y1NUt4M1grNGtua3R3anJVVUVGZ3p4WklxelhYMkVJMUYrOGN4dURtNnI1c1NsZmpxR0pna3ZCTTZTSlFyTkJuSjFHbUpKaFdQdGZjeEg0eVFWRlZrVXFDdks0NG1ObGVnMWNQVFVHYTcwRDZlbjVIYXE5eElRQkF4YVRYck9Vb3JLeFQ0M2lYYys0cVVETzNtOHZvSWN2Wlp6dldPSW9rQlRaU0dXckJSbW5jaXRwRUlnWWFKOWNKcVpVSlF0NVU2MnJ5bEZUVVk1ZHFxTjdxRlIxRHZ6QzJnMU1xSW9aaElRSlJGYnJoSGZYRERkUDFWVjZSandrSGp2RTU3YjIwSlQzUXB5OUZsRTRnbjBrU24rOHRkL2NPVHdNVFkxYnVCWHI3ek1velhyQ0VWVGJLb3FJakEzeTRuV2RucmRZd2lMYXE2cUtqa0dIYklzWnk2aVNDekdGeGV2OFBjUHp6SVZDR1hzZ0pTaXNzcVZ4NDhlMzhhYXFuS1NpUVN2L1BKbHZtaHRRNnVSU2FaUzVGbXRIRDF5bUVMWE10eGpIazU4ZVlIaDhTbEVNYlBjT3EyV0hadlcwbHkvRHFOQmYzY01GVVVsUDgvSzgzdWJxVjd1eUJDS0pBcjBqZnY0Mndlbk9YZXBDelVaeCtzWlI2dTVuWVVzU2ZobVp3a0ZBL1QwOVhQc2RDc2ozcVhCemNac2RqZHVwTEtraUVVZElkMk1BYmVIU2Q4c0IzZHZwYjZpQ0kwazNYVVNCTWI5ODd4MW9wV0oyU0JWMWRWSWkreXJLc294VzJ5Y3ZuaVpLWDhnbyt5Q0lPQzBtWG15dVFGWmt1anBIMFJGemRTQVRxdkZaVFB6bXcvTzhQMkdPZzdzYU1DY2M0WCttMTVVUmVIbWJJaWtvcUNxQW4yajQ3ejB3dk1JcUlSRElSQUVEdXpmejh4OG1FUWltUTVxTXVqUmFtUnNwbHkyYlZ6RGlHZUNNeDNmc08rUlRSajF1a3dDa2lSaXM1cXc1eG81M3RiRjVHeVFRMDlzUXhKRkVza2toejgrUi8vNE5QdWIxdUUwYWpuZjloWDc5dTVGRWtVVVJlR214NFBkYnFlaHJvcld6cXZvczdUczJiYVpQSXNaUlZFNTI5SEo1ZDRCOUxvc3JCYnowaWtBTU9YbVVGdGN3T211SUYvZmNGTmU1T1RuVCswaW5raXlaZlU0cTh1V1k5T3F2UGE3MTdqVTFVMldWb3ZWWWlZY0RqTVhERkZXdkl6ZnZ2b3EyemV1WVdKbWxxclNFb3dHUFdjN3ZxRzdmNWlVb3BCdk1XRzNXakswa2FhU1o4NWxjMjBGNW13OWlxclNPemhLZC84SXZVT2pUQVpDV0EwYVBqeitiNjcyM1NCYmw0VXNDZ1RtNWtnbUV1UVlkRXhPKzNqem4yOGlxMGxFU2FMZmZSTzNkNUlCOXhqSmxJSkdsbGxadkF5SHpYci9UYWpWeUR5eWZqVXBSZVdkaytmcGNYdDU0OGpIcUlwS1kxMGxrMTRQSFoyZEdYc3NRMnpBd1BBSW5aMlhXYnVwZ2ZkUHQyTFE2WmlZOWFPUkpSN2R1SmF0Nit2UzA3T0VBSUF1UzB1Unk4SHorN2J6N3FmbjZmUDRpQ1JTUE5WU2p5OHlneXpMRkMxenBRTUtnckF3VW1xYVVDb2VKOTlpeGpzemgwYVdNR1ViMk5XNGtjSjhPOFpzQS9jaWc0QldJek16TzhlNHo4K0wrM2R3OUxNMnVvYTl4Qk1KMW0rczV3K3Z2NTdlNVJxTmhORmdJQnFMRTB2RUVSYmVHd3dHNG9rVUdsbkdsV2RoWjJNOWdYQ1lDZDhNSzB1V0x5R1F2cExkd2JRL3dCL2ZQazZXWGsvTGhtcGFPM3U1TWpDNkVGaE5aOTFZczRJZlBybWRTMTA5bk8vdVJVeFg0L2JLTGJCWjJGSlh6YkJuQXZlNGw1L3MzNFBkWW41NEJRRHNGaFBOOWJYODZkMlR6SWZDUExabERYWnpEcjdaT1h5QkVGMURIcUxKRktGd2hKU2lFbzNGbWZZSGtFU1JJa2NlK1JZekJvT2VGUzRuVndlRzZld2JaUC8yUnZMTUp1NEgrWDR2TjlldG9yMjdqMU5mWHljY2pmSHNFMDJVRlRVUUNJVjU0L0JIWEI3MExQbkdscHZEMHp0YnlMT2E4Zm5uK095ckRyb0dScWd1S1dKOTljb013ZDUzREJmRGFOQnhjTmRXSEpaY0xnNk00ZmZQWVRQblVPcHlZRFBuM3Zld2JJT09va0lINWh3amlVU0Nid1pHTU9yMTdHellnTkZnNEVHUUgyUW9jUlh3MHI0bWZ2L1dmemg1b1pzc3ZaNVFKTWExb1RHVVROa0FNRFU3eCtjWExsT1luMGRiWnpjQ3NMdGhQU1V1NTVJZjAzY2lvSkZsTnRXdTR1RDJTWTZlL1JyM2tVOUlLaXJ6MFRnc2pVODBudUJrV3dkYVdlSldMTTZXbWtyV1ZWV2l5OUx5TU1nUE01cHlzdmxlY3oxZW41L1c3a0hVKzJTK0dMRkVnbmd5U2ZreUo4MzE2N0E5UUhqZnFvSEZLSFRZT2JTbmlRM2x5MEFRSHVvckFDNjdsZDJOOVJTN25Id1hmQ3NCQWFnb1djWnplMXVvS3k2NHg2cXl1Qi81VmpON214cW9LaXRCZ1A4UGdUc1hrcHFLRW43MjFDNVdsemlYTUZSVktMQmFlR1puTXpVVnBROGN1Zitad08ycm1VaFZXUkcvUHJTWCtsWEZkek5Vb2JTd2dFTlA3bUJsYVRHUytKMlB2UDhxL2pZb3FzclVqSjhMUGYxc3FhM0VQVDZCS3o4UHB6M3ZvZVAySVB3WCt1aXFqb2NEZFBnQUFBQUFTVVZPUks1Q1lJST0ifSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiTk9UX0ZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjItMDgtMTQifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDIyLTA4LTE0In0seyJhYWd1aWQiOiIxYzA4NjUyOC01OGQ1LWYyMTEtODIzYy0zNTY3ODZlMzYxNDAiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6IjFjMDg2NTI4LTU4ZDUtZjIxMS04MjNjLTM1Njc4NmUzNjE0MCIsImRlc2NyaXB0aW9uIjoiQXRvcyBDYXJkT1MgRklETzIiLCJhbHRlcm5hdGl2ZURlc2NyaXB0aW9ucyI6eyJkZS1ERSI6IkF0b3MgQ2FyZE9TIEZJRE8yIn0sImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJtYXRjaGVyUHJvdGVjdGlvbiI6WyJvbl9jaGlwIl0sImNyeXB0b1N0cmVuZ3RoIjoxMjgsImF0dGFjaG1lbnRIaW50IjpbImV4dGVybmFsIiwid2lyZWQiLCJ3aXJlbGVzcyIsIm5mYyJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQm5UQ0NBVU9nQXdJQkFnSUpBS0lGbnRFT1ExdFhNQW9HQ0NxR1NNNDlCQU1DTUZReEN6QUpCZ05WQkFZVEFrZEZNUTB3Q3dZRFZRUUtEQVJCZEc5ek1TSXdJQVlEVlFRTERCbEJkWFJvWlc1MGFXTmhkRzl5SUVGMGRHVnpkR0YwYVc5dU1SSXdFQVlEVlFRRERBbEJkRzl6SUhKdmIzUXdIaGNOTWpJd016QTRNVEV5TURJNVdoY05NemN3TXpBME1URXlNREk1V2pCVU1Rc3dDUVlEVlFRR0V3SkhSVEVOTUFzR0ExVUVDZ3dFUVhSdmN6RWlNQ0FHQTFVRUN3d1pRWFYwYUdWdWRHbGpZWFJ2Y2lCQmRIUmxjM1JoZEdsdmJqRVNNQkFHQTFVRUF3d0pRWFJ2Y3lCeWIyOTBNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVqMjhVREVjU3FHUlVUMVBNRGFzbWoyR2Q2QnNUVFMwTTFPMlc5ZE0wWUVZOWhyRGdEL0Fzd1JWY1JieG55dDN4ZENQMEtoSWllZ05JUndVY1ZFSnZlekFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBNjFtQ0NvQ25EeENrVkJYRG1oam1HMDFpYmRSV1Y2M2o1U2NTakJGbklrY0NJRUFkMVd3YjFpVXlLQmZqcHhrL1IvdDBPc3B0UE9JRjg3dVNoeTNsWHZiSCIsIk1JSUJzakNDQVZpZ0F3SUJBZ0lKQUtJRm50RU9RMXRYTUFvR0NDcUdTTTQ5QkFNQ01GUXhDekFKQmdOVkJBWVRBa2RGTVEwd0N3WURWUVFLREFSQmRHOXpNU0l3SUFZRFZRUUxEQmxCZFhSb1pXNTBhV05oZEc5eUlFRjBkR1Z6ZEdGMGFXOXVNUkl3RUFZRFZRUUREQWxCZEc5eklISnZiM1F3SGhjTk1qQXdPVEE1TURZeE5EVTRXaGNOTXpBd09UQTNNRFl4TkRVNFdqQlVNUXN3Q1FZRFZRUUdFd0pIUlRFTk1Bc0dBMVVFQ2d3RVFYUnZjekVpTUNBR0ExVUVDd3daUVhWMGFHVnVkR2xqWVhSdmNpQkJkSFJsYzNSaGRHbHZiakVTTUJBR0ExVUVBd3dKUVhSdmN5QnliMjkwTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFcEtSMGY2VmRxMFBZWHhIN0pWTWtHeE5vTTRYb0hGdVErZTdxZiswNFA0SjJHR1M5dlhGTFZRWjVjb0ZuUlBmQ2ZsRENMa3phZk0zUUVkY1lDVm95UEtNVE1CRXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpRUF6WHBvdzMvNHlPWE5iQUxvZE12NUtJb3JubjV3UlJJMzZZUXB2M1diaDAwQ0lFeTE0U3k3THJsZ0pTWlRHME1kNXdqUWJ5b1ZUZlUvMm9aeXA5RW5wbERMIl0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQktjQUFBTktDQVlBQUFCZi9TMnZBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBVEVsSlJFRlVlTnJzM2QxNUU4bTJNT0RhNTluM3h6dUNyWWxnVEFTSUNJQUxYeU1TTUJBQkpnS0RFN0M0OWdXZUNCQVJZQ0lZVFFUakU4SDNxVnl0OFErUzBWKzNxcXZlOTNrRXpQNFpyT3JxN3FyVmE2ME9BUUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRFlrMzhaQWdBQUFMamorR0l3KzNWdzV6OTUrTTl6L3p2N0hLNzRiNTNPUG44dCtlOG1ELzc1S3B3ZFhUc1ExRUp3Q2dBQWdEcmNCcDNtbjd2QnBmbC9scHNZcExxNjgrY2Z6WituelNlRXM2T0pnMHVmQ1U1UndnM21xMEZnZ1Q5bU4rbVBocUg2NjhObzl1dXJ5a2ZoM2V4Y3VESVpBS2pvL2o4SUtjZ1VnMDcvYlg2Zi8yZWxtOTc1eEN5dGVXRHIybnFBblAzYkVGQ0FvU0ZnZ2JqNEVKeGk0Qm9SRGt3REFJcDFmQkh2ODNlRFVMWGY5d2RoV1JEdStDTCtPZzlXVFVNS1hrMmJqekpDOWtwd0NpajN4bng4Y2VnSkVRQkFJZUxhTGdXZ2ZnOHBDSFZvVU5aMkVKWUY4STR2SGdhdTBwK3RwK21BNEJSUXNsZmh0ajRmQUlBK1NjR280ZXp6dFBsZE5uQzdGZ2V1VXNiVlBHajFJd2hhMFFMQkthQmtveEQ3N1FBQWtML1VLMm80K3p3UGdsRzVtV2V0dmJoenZPS3ZkNE5XazVDQ1ZsUER4Ym9FcDRDU0hjeHVtaTltTjhoTFF3RUFrS0hVTTJvZWpGS20xejkzZzFidm0yTTZMdy84Rm03N1djbXk0bEdDVTBEcDRtSkhjQW9BSUJmeDRXRmFvOFhmWlVlVloxNGVPTHh6ek9Pdms1Q0NWcWswVU1DS093U25nTkxGUmM5cnd3QUFzRWNDVWl3UFdNVU1xNnVRQWxaVHcxUW53U21nZExHMGJ6UzcwWTBOQlFCQWgxSVBxVGNoQmFRR0JvUUZodUYrd0NxV0JFN0N2SWZWMmRIRUVOVkJjQXFvUVh4S056WU1BQUF0Tzc2SVdWRXhHQldEVW5wSXNhNzUvRWs5ckc2YnJrL0NQTU5LZGxXUkJLZUFHcnk0V1NpZEhWMGJDZ0NBRnFRc3FmZEIyUjY3TjIrNi9yYVphOU9RZ2xXZlpWYVZRM0FLcUVWY0tJME5Bd0RBRHFXMzdjV2cxTkJnMEpIQjdET2FmZjRLS1VoRkFRU25nRnJFMVBLeFlRQUEySUhZMHpNRnBRWUdBOWpXL3hnQ29CS0hUYm81QUFDYmlrR3A0NHMvWjM4NkR3SlQ3TmVWSVNpSHpDbWdKckcwNzZOaEFBQllrMHdwOHFPZmJFRUVwNENhdkFxQ1V3QUFxeE9VQWpxZ3JBK29TU3p0ODBwakFJQmZpWTNPankrK0J1VjdRQWRrVGdHMWlkbFQ2dE1CQUJaSlBUcFBRMnFIQU5BSm1WTkFiU3kwQUFBV09iNDRtZjM2M1hvSjZKcmdGRkNid1UyYU9nQUFTU3JoaTIvZ2k3MmxEZ3dJUFRFMUJPVlExZ2ZVS0piMlRRd0RBRkMxNDRzWWlJb0JxYmNHZzk0NU81b2FoSExJbkFKcUpGVWRBS2hieWlTUEpYd0NVOERlQ1U0Qk5UcVlMY2dFcUFDQU9oMWZ4SWJuOFUxOEE0TUI1RUJaSDFDcjU3UFBwV0VBQUtxUjNzVDNaZlk1TkJoQVRtUk9BYlVhTlgwV0FBREtsN0xHWXhtZndCU1FIY0Vwb0daSyt3Q0E4cVV5dnBneDVjRWNwYmcyQkdWUjFnZlVMSmIyalEwREFGQ2tsQ1VlZzFKRGcwRmhyZ3hCV1dST0FUVjcwZlJlQUFBb3kvRkZMTitMWlh4RGd3SGtUbkFLcUozU1BnQ2dMTWNYdytCdGZFQ1BDRTRCdFh0bENBQ0FZaHhmakVJS1RPa3ZCZlNHNEJSUXUwT2xmUUJBRVZKZzZ0eEFBSDBqT0FVUXdzZ1FBQUM5SmpBRjlKamdGSURTUGdDZ3p3U21xTTgzUTFBV3dTbUEyQ3cwdmRFR0FLQmZCS2FBQWdoT0FTU3lwd0NBZmhHWUFnb2hPQVdRakF3QkFOQWJBbE5BUVFTbkFKS0QyU0x2aFdFQUFMS1gxaXdDVTBBeEJLY0FiajAzQkFCQTFsS2ZUSUVwb0NpQ1V3QzNaRTRCQVBrNnZqaVkvZm8xeEl4dnFOdkVFSlJGY0FyZzFrSFR2d0VBSUVjQ1UwQ1IvbTBJNkwyem8zL3QvV2M0dnZnU1pOMlVJcGIyalEwREFKQ1Y0NHZUMmErSEJnSW9rY3dwMkg2aEVKOWVDVXlWNDBWelRBRUFjbGx2am1hL3ZqVVFRS2tFcDJCN0FsT09LUUJBTzQ0dkJyTmZUdzBFVURKbGZiQTliM2dyejV1Z3RBK2dwczMvY0t2Ly85blJ4Q0RTb3RnK1FsWTNVRFRCS2RodU1Uc0lzbXhLZEhoemJNK09wb1lDb0lqN2Rkell4OHlUd1QvWCtWMXU5bzh2N3Y3VDlleHoxZnc1M2tmK3V2T2ZYYy91TFZjT0NHdk1yWk9nenhRczRscGFHTUVwMkk3QVZObkg5cU5oQUNqQys5bG4xTkhmRllOZXc2WC9iUXBrVFp2UHQzLytMUHVLbitmS1lUTjNnWWZPanE0TlFsa0VwMkE3cnd4QjBjZFdjQXFnL3h2OCtMQWh0MGJTZytZenZQTnp4bCtuSVdVRGZMdjVYY0NxZHVlR0FLaUY0QlJzdnRpTmkwcHAxdVU2dkhsaXFmd0NvTS8zNm9PZWJmQUh6ZWRGOC9QSFgrTjlhQkpTd0dvaVc2Q2F1ZnZXT2hPb2llQVViTzZOSVNqZXE2Q2VIYURQWW1DcTc0MmtENXRQeXY0NnZwZ0hxLzZRV1ZXb0ZGUlZ6Z2RVUlhBS05xZmZWQjNIK0oxaEFPamxCdjlGb2ZmcTIyQlZ5cXk2RERGUWxiS3FwZzU4RVdMemZtL25BNm9pT0FXYkxYampvbkJnSUlvM3VIbTl1Q2ZUQUx1OGg2YUc0V2RIbHkzL0hiWDA2N2tOd3FXc3FzOGhCcXdFcXZwNmZneERkODM3MloxRmE4VllndnZqa2YvUC80YmxwWnNEZTQxSHViNFZTSEFLTnFNUmVsM0hlbUlZQUxiYWNNZGdVUXlnUEc5Ky94QlN4azliU2lqbjI4UThxK3IwVHFCcXJFOVZyeWpueTh0OERmanR3VDlQT3cwQXB3ZmpCM2ZPOC9qbi83M3o1OXI2azAxTnpmSUlUc0ZtUm9hZ0duRVQ5ZG93QUd5MG9ZclgwRmZoZm5sZGZBdmRTWXQvNXpBb3ZaOXZZT2VCcWhnSS9OeHF0aHE3bXJ0REE3RVhrNUFDSGo5QzZqZDZsVlZROS80TGVpWkw1cy9CbmZNKy92bnBuVDlEOXY1bENHQ2poZllYQTFHVmwxVXY2STh2UnFHL3FlVlBMZlREZVBiNXkybThkTUYvWWhCMmZzMkkxNHY0MHBEUmtrM1JzOWJLcGRQbTdIdFFEclBNZFhOTitLVHNMOHR6NTZ0N1ZpZmkzSS9CbnZrYk1LOEtuMWZ4ZW5qWVhKZExtVi94dUQwemxjc2ljd3JXOTl3UVZIbk1hMzdhL01waXVkZEdodUJSSjRaZ1p4dWdGeXRzZmk1Yjd1TVgzMmczY0RDV09takdLRFpUajhmaGc3NksyWncvUS9mYVZzVjEzTGRRWXorMjlIMm5UV21nT1VhMkJLZGdmVW9GYXR6Y0gxKzgwN01ENEtjTjlVRklBZEFZbEJxczhQOTQxK0xQRXY5Ky9YcFdON3o1SEYvRWpXc01VbzBOeVY2WnU3c1YxMnpwVFpiS1dhRVhCS2RndllWdlhJQ3IyNjVUREVwYXVBT2srK0VnUEY2NnQ4aTQ1WXlGY3dkbUk0T2JzVHUrT0EyeDNDK0VqeDdHZEg0K0RZT01sbDJaQjZTczJjcm1HbFVnd1NsWWo1Syt1bys5aFE1USt5WjZFRktHeDJpRC8vY0htL3VzSFRUSDlzMXNQQVdwdXVVdDBOdUo4L1JUYUQ4QVRqNStHSUx5Q0U3QjZndmYrV3V3cWRPTG0wMlpSUTlRNXoxd0VEWVBTb1VnYTZwUEJLbTZYMStPRE1SRzRqVkZTU29VUW5BS1ZpY3d4WXViUlRwQVBSdm5RZGd1S0RYWFp0WlUvTmtHRHRiT0NWSjE0NjBoV05zMENFcEJjZjdIRU1ESzNoaUM2a203QitvUXN6bU9MMDVtZi9vemJCK1ltclNXTlpXeVRrNGRzRmJOZzFSL05uTUNhNHQ5aWNIUkdKVDZUV0FLeWlNNEJhc3RmZ2V6WHc4TlJQVU9tN2tBVVBJOUwyWnl4S0RVcnQ0ZTlxbkZuemIrckY1VTBvMFVwRHErK0xQSlZtUDdjMjBZWlAydEtqWTZqMEdwRTBNQlpWTFdCNnVwcmFSdkhQUS9XQ2FPaTRVUlVPcEcrWHpIbStWcGE2OXhUMWxUc3BxN053anA3WDR4NHlkbXNVd015Y1prVGYxYXpKWjYzZHAxQk1pR3pDbXdlUGg1STlGbWJ4QnpBU0F2TVNQMCtPTEw3RTlmdys2ek9HUk5sV3Q0TTJlT0w4NmJRQ0hyMDgvMGNaT1FzcVVFcGxnME55aU00QlQ4ZXRFZXkvbHFLdW03YkhxRHVPZ3ZObWptQkVBSjk3aVQyYS9mVzl3a2oxdjZ1V1ZONVdNVVVqOHFqYjNYbThQeG5CUFVXeTQyNEgrbUNUL1VRMWtmL0ZwdG1UTHpwOXlmUTNvcXl1STVjV1VZZ0I1dmpPUDFQVFlTYnpQWWZ0bml4bExXVkY1U1kvcmppK2NobFdCTkRja3ZQVGNFUzczVzhCenFJM01LZnEybWxPdXJPd3RLS2RUTGpRd0IwRXZwTFh3eEtCVkwrTnJPQXYzYzJuZVFOWldyWWZCV3YzWEdpcDhKVEVHbEJLZmc4UVZ3WExnUEt2ckd0eHVKOUxSYmdHcXhneVlkSDZCUDk3UzRHWTRsZkYyVVgxMjMyQ2RHMWxUKzRsdjl2aXVEdDc1Y2s4QVVWRXh3Q2g1WDI1UFpoeHVKejZiQVV0THhnVDV0aGs5Q093M1BsMmx6Z3lscnFoOWlBT2E3WGxRTERRM0JUOTRKVEVIZEJLZmdjVFZseDF6KzFDTWlQZlhXaU5MY0FQb3FabWpFREphWXlkS3R0a3I2UmtIV1ZOL0VYbFJmYjk0S3lkeFRRM0RQZUxibS9HZ1lXSVBlcndVU25JTGxDK0RhM3FMeXg1TC9YR25mWWdmTkpna2cxL3RZdkVaMTBWdnFvZWxzbzluV3h1RzlBOXRMdzVDeXFEell1UjBQa25pdGVHY1lXSXUzT0JaSmNBcVdxNjFzYTFrUTZnOVR3UndCZWlRMVBUK2YvU2wrOXZHUTViS2w3eFUzOUFNSHVMZmlYUHpTTk9TditmdzhETEwvN25vdDBBQkVnbE93YkdGZjF4dlpsci91TzVYMlRVMktoVjQwY3dVZ3A0M3YxejNmdzlycVY2alhWQm5lTnMzU0I1VitmMDNpYjMxc01jc1M2Qm5CS1Zpc3RyVHpYMjBrbFBhWkswRHU5bGZHZDFjN0pYMHBrT0Y2VzQ1NXMvUmhoZC85ZDRmL1Jud28rc0V3QUhPQ1U3QllUZVZhcTd6dTIxdjdsdk1rSDlpL1ZDcTFyeksrdXlhdXRhd296dFd2RmI3TlQrWlU4a2s1SDNDWDRCVDh2TUNQaTZXNjN0TDNLK2twK05Ua1dMTEk5QVlpWUovM3JPT0xMeUdXU3VXaHJUNkZJd2U3V0tjM1BkTHFLWk1mT3VRM3ZKMlBUZG1URkVwd0NpeUFWOTFJZkRJMWxsSnFBblF2QmNhL1puVU4rblVtN2liZnM3YTM1OWE2OXZwYWZJREt3Nnk1c2F3cHRqQTFCR1VTbklLZnZhcnE0cjc2UmtMZktYTUd5R2VUbTNyMjVGVWkxTlo5d2pXMkR2TStWQ1dYdlEwYzVodmVCQTM4UkhBSzdpLzJCNkd1WGdDcmJ5VE9qcWF6WDcxUlpkbUN1dXpGTkpEWHZXb1VVc1pVYmxrbTMxcjRycldWMnRkdUVGSUdWYW4zMUtGREhOckpzQVI2VDNBSzd2T1d2dDMrNzJ2aXlUN1F2aFNZeXFIeCtTSnRiRGhIRG5wMTR0eiszc3gxeWpNeEJNQWlnbE53WDAxdkE5cmtkZDlqVTJRcFQvYUJkcVczbXAxbmZFK1p0dkR2RmZpdjEzbUJBYXFuRG1zTEdaWkFFUVNuNEhiUkgxUElCeFY5NC9VYm5LZm1sVkt4Rnh2TTV0RFFNQUF0M2FOaVVPbzA0NTl3MHNKM2p2ZGtKZE4xaXdHcUU4TlFsS2toWUV1YTZSZEtjQXB1MWZaMGR0TWdreWFXNWhEUXBSU1lHbVgrVTdaeGI1Q1JTdlMrT1FkS01IQTRCYWZZMmc5RFVDYkJLYWh6RVh5MVJmbEZER3A1WW1FT0FWM29SMkFxbXJUdzd4VHdaMjVVU0lCcTRGQUNMQ1k0QldueFA2eHN3YkI1WTNPbGZZODVtTTBsQVNwZ1YvZW12Z1NtcnBwN3d5Ni9lN3duSytuanJsRkJHVlQxT2p1YUdBUmdFY0VwU0dwN09qdmU4dit2dEcrNTU0WUEyRnAvQWxOUkc1dE5nWDRXRWFBQ0tKVGdGTlMzQ0w3YytnbjMyWkhTdnNjWHpnZUdBZGhZdndKVFVSdjlQd1Q2ZWV3K2U5N0Q4M3JvMElYNUM0Z0FmaUk0QmFrTXE2Wmd3cTZ5bnBUMkxlZUpQN0RwUGFsdmdhbG9zdU14aVBka0cza2VNL0lXdjk3eUFJOXRlVUJlS01FcDhKYStUWDB5ZFpieXhCOVkzL0hGMjlDL3dOUjBpeGRzTERNMEdWaEJmSXZmeUREMGp1RFUvand0NUh0Y09aUmxFcHlpOW8xQXZFSFdsT1V5M2xuVDJyT2pxK0Ixd011OGFKcjVBcXg2UDRxYjdOTWUvdVNURnY2ZEF2eXM2bHlBcW5lVTlRRUxDVTVSdTlyS3IzYmR5RnhwbjdrRmJDdVZsL2UxeVhNYi9hYUdKZ1ZyT05mUHFWZWVHZ0pnRWNFcGFsZlQwOW5ycHBINUxpbnRXKzZWSVFCK0tUVUg3dlBieDY1MlBCNkQyYThERTRNMWZkRm91emVHaGdCWVJIQ0ttamNFY2ZGYjExdjZkaTMxR1ZIM3ZkaWgwajVnaGZ2UTE5RG5IaXhuUnhNYlZ6SndjSE11ZVZ0dVg2NTlJNE1BUENRNFJjMXFLN3Y2M0xOL2J3a3N2b0JsbTdPNGlmNFMrdDBjZU5MQ3YxUEpENXNTb09vUGZlV0Fud2hPVWJPYXlxNm1MVHpkbnROM3lod0QxaGRMK2ZwZWh0Ukc1dXpRMUdBTDhadzZOUXpaOCtJWU50ZmVub1k5RTV5aVR1bUdXRk52Z3ZZQ1NLbTB6MDFpc1lFZUdNQ0NlOUJKS0NONzk4ZU94MlVROUp0aWU2UG1IQ052N3cwQmNKZmdGUFV1WE9yeXVlZi8vajZUUFFYY1NtL21LMlZUdHV2TUtjRjhkdVY5YzY3bFpPcXdQRmlMZTRDM2oydjJaSTNQdFNHalMvODJCQWdZVkhBak9qdHF1Mmw1ek13Nk42MFdpb3ZqZDRZQktPRE5mUGZ0L3Q2aTN4UzdkRDQ3NTY2YURPOGN6cGZwN09keFZPNkxKWmpQREVObmM3Q2I5ZWp4eFhDRC8xZnNGU2RZV1RuQktXcmRIQXdxK3NidFp6V2RIVjNQeGpVR3FGNllZRDhaM0R5OVBUdlNtd3ZxdnZjY2hCU1lLcVZaY3hzUFBXeE0yS1gwMG9IamkyYzM2eFJ5Tkp3ZG43ZXo0L1BSVUJSazg1NVExc3FWVTlaSGpXb3JzK3JxUXYrSHFiV1V0OUlBTVVPZ3BPQ0xadWowZ1FicGZiZzJLdThEZ3VBVWRScFY5RjI3UzJjL094b0h0ZW5MeUNpRG1oMWZqQXE4OS95MTR6R3FjWE42NWI3WjBib3ZuWU01bURvY0MzMXBza3VCaWdsT1Vkc0dJUVlKYXJyNWZlcjQ3NU9PdTloQlJndGpvTnY3emlDVW1ia3gyZkcvcjhiZzFPdHdkdlNmMmU4dlo1OXhFS2hxMDJsekx1N2IxS0ZZS0I2YnJ3SlVVRGZCS1dwVFczbFYxOEVpcFgzbUhuRGZsMURtUTVGZGI3SUhsYzJMNlQ4TjVXTlB3ck9qMTdNLy9SWml3R3IzZ1QvbS9hZkkyYUZqQkhYN2x5R2dLc2NYZjRkNk1xZmlZdmZsSHNiNHp3bzNHYXY2ajZhc25jL0hreEJmS1Y2M1oxczBKOFg4Vyt6czZGODdIcXV2b2E2ZVUrTW1JTFZzUE9KOTlFMUk1YUN5U1hibncyemNUMXdUTWo4MzRsdU9yWmVnT2pLbnFHbVRVTnNDYjE5WlRFcjdsdE43Q3VxNTV4d1d2QW1kdFBEdkhGUTJRNzQ5K3QvR2ZwSHB0ZSsvM1d6VWxZUHR5bnZOdDdNWDErdEsvS0JDZ2xQVXBLYXlxdmkwYVY5Qm9zK20ybEt2REFGVUlHMnFTaTVQbWJidzd4eFVOa3NtSy8ydll2YkkyZEhIMldkZThqZDFnbTN0Zkk5Lzk1WGhYMGtNSUFwUVFXVUVwNmhwbzFCVDFzcmwzdEtoVXc4TmkrZkZocGswWkFYYUZUT21TajdYdmFsdk85T04zcVFiMzRwN0c2UlM4clM1dzZhOGJoOGN0M1dPVXdoL3luU0RlZ2hPVVl2YXlxbjIzWmhjOXBTNUNIVktHNm0zaFgvTFhXZC8xSllkc2QzNHhTQlZLdmY3RUFRN05yV2Y4ajc5L3phNU5uejN4bU9vZytBVXRhaXBuT3I2NXMwLyt6VTI1Y3hGcU5SNUJkOXgxd0dSWVdWejVOdlcvNFpVN25jeSs5T1RvTmRqMzg3VnFhSGY0RmdkWDN4UjVnZGxFNXlpZkttTXFxYUY3LzRYcWFsY1FWK0Z4UTZscUVPeDk1dVRrRXBSeWliN1kxdFhPendXMCtiTnZNK0NvTWNtOStPVFBmeTlqdE5tWXVaNXpLSWFHZ29vaytBVXRkek1hdklwazU5RGFkOXlzcWVnTk9sQnlCc0RzWkdubFgzZjNUKzhTUUhEbUVYMTBYUmF5NXM5OUlMOFp0ZzNGbzlWYkpSK0tvc0t5aU00aFVCQVdhWk5RL0ljakUyOXBmU2RndktjaGpwNkowMGM2cTN2MCszMGlVcWxmdTlDeXFMU2kybzFCODI1MnlXWjVkdUxmZjFrVVVGaEJLY29XM29hVmxNSlZUNTlKOUxpV3grTXhRWksrNkNvZTAzY0lBazZiNjZtNitHMGcvdnZKS1NHNmU3QnEzblJjWkJEY0dwWGE2bVVSZlhGbTVDaERJSlRsSzYyRW90UG1mMDhmNWlDNWlaVTRMeWk3OXBHU2RLQjhkdXhsRVVWZTFHOWMzcG1kZzZudnB4VFE3NHo4MTVVSjRZQytrMXdpaHB1V0xXNGFoWThPZkhVMXR5RXNoMWZ4UEtTZ1lGZ1JkMlcyNTBkeFI1VVQ0SXl2MThaTk9keVZ5YUdmS2RpZ1B2OTdCaitPZnVNREFmMGsrQVVKVzhZRGl2Yk1PVFhnRHlWOW8xTnhpVUxxZU1MQVNybzkzMG1iWWpxTXQzeEdBNHJHNy91UzdwU0w4cmZnbkt5WDNuZllaTnRUZEhiRWRmOTU3UGorRlUvS3VnZndTbEtWbHZaVks1WlNrcjdsbnR1Q0tEWFlxWkZiVytNbWpyc1BaUWVGc1ZHNldPRHNkUkJjMDUzWVdLNFd6VU1xUitWSUJYMGlPQVVKYXNwSzJXU1lVbmZmRUVjZzJiS0NSWWJlUlV5OUZScXdQdmVRTERtUFhHeXg3ODc5cUY2SFFTb0h2TytrK2JhK2s1MVpSZ0VxYUEzQktjb2RkTVFBMU0xYmZvL1ovN3o2VDIxbk5JKzZPc210a2E3RDY0TVRLWE9qMkVNVUdtVXZ2OXoyOXFvTzhNZ1NBWFpFNXlpVkxXVlMrVyt3UGxrU3BxclVJeVVXVEV5RURzeHFPaTdUclA1U1ZLajlOZW0zMEtqVHJLbnREM1loMkZJUVNxTjB5RkRnbE9VdUdtSUdWTTFaYU5jTnIwazhwV2FzVTVOem9WZUtPMkQzbEhPeHlieXVnK2VIWTJEQU5YK3p2R1VoYWp0d1g0TVFtcWNIb05VSjlaaGtBZkJLY3JjN05kVjB0ZVhKMi9TMTVjYkdRTG9pYnF6cGlZbVFHRUVxSmJmbDd2Sm5ySTIycTk0akdNZ01nYXB6anM2NXNBU2dsT1VxS1l5cWV0bVlka0huMDNOcFY0WkF1Z05XVk9VUllCcW4rZTZ0Z2Q1aUErMVJ5RUZxYjRxK1lQOUVKeWlMRFdXOVBWbjhSdEwrNjVNMG9VT1BhMkRYdHhqQmtHbUl5VktBYW9QQnVLZTlyT250RDNJMFREY0wvbXpQb09PQ0U1Um10cmVmTmEzWnBxeXB4NWJCQU81a3pYRk52SitRSE4yZERMN2Rld3czZk9tZzc5RDlsU2VCdUcyNU8rTGJDcG9uK0FVRmhIOUZVdjYrdGFyUUcrRjVaVDJRYzdxeTh4ZGZOOWhHLytYL1U5NGRoVEwreVlPMVQ5R0hUVExIaHZtN01WcmY4eW0rbnYyT1oxOURnMEo3SjdnRkNWdEhBWWhsa2ZWbzMrTG1iT2pxVVh2VWdPTEhjamEyMURYeXpZVytXRWFWT0ZsVUlZL2Q5Q2MrMjJ1amE2REFGWGY1c1AzMlpvdGZ0NTYweC9zanVBVUphbnRpZlpuUDNkeFpFOUJ2dDRZQXFxUWdpVXhnMHFtWEhmM1pxVjkvUk1mS0o3T1BuOHIrNFBkRUp6Q3hxR2ZwazBUelQ1UzJyZmNDME1BR1VxYkRrL0hxVWRhWTNpRFh6Sm9QZkNReG50aXFIdTlmcHVYL2NYZnJlZGdBNEpUbExKeE9BeXBjV0V0K3B0OWxKN0lDbEF0WHdCYjBFQitaRTBsVTBPd2xhYzl1MS9IZTdVMytDVmRaRThaNi82TER6RkdzODhYZ1NwWW4rQVVGZzM5Tk83NXovK0hLYnZVYzBNQUdVa1BQL1NEaXc4VnpvN0docUV5NlExK0V3TVJoazF2MHpiSGVtS3NpL0l3VUhVcVVBV1BFNXlpRkRWZDdLK2F4dUo5WHV6R0RZNWVGdVl5OUlHc3FYUzlWdUpWTC8ybmt2Y2QvQjJ5cDhvMGI2UXVvd29lSVRoRi94MWZESU9Tdmo1UzJyZHNBYU9wSnVSeWY0a2JDaHVJK1BhMlZKSk5qZElETWNISkxxNEZLWHZLK3FqMGRaN1NQMWhJY0lvUzFGYlNWOHFpUlduZmNrcjdJSi9OYU8yTjBEODJHMloyc3ludHA5Ui82ckw2NDlmTnc2TjNUcFdxcmdseFRnbFVRUkNjb3B6TlF5MHVlMS9TZDMraE96VjlsOHpwbExFQjdOZXJ5cjkvdkVhM1hXWlVVMFpXMzN1WEtlL3I0dUZSV3VjcDc2dVBRQlhWRTV5aTM5SkZ1NlpOZkduWlJsTFhsN01nZ2YzZVh3WWhOa0d1MjdzT3l2bXVUTGFlU0hPaDlxeWVGNjAzUms4K0JnL3dhaVpRUlpVRXAraTcyc3FmU2d2bWZEYUZsM3BsQ0dDdlJwVi8vOHNtdzVWZDZpYXcwWjcwUXBOSjVVZXhpOTVUWGtMQW5FQVYxUkNjb3M4THZJUEtOZytYeFRXa1BUdUtUOHluSnZOQ3c5NXZZcURmYWc0UXk1QnBUd25YOWRxREp0MWNHMUt2dDQ5T0dlNjRHNmo2Yy9ZNW5YME9EUXVsRUp5aXoycDdhdkRaOXpMSGdRNmt4ZjZnNGhINDFHRi93MmxsWTl2L2VaWG1SczFCazhNT0h4NTlDQjdpc2Z4YThuYjIrZDRFcWs0ODFLVHZCS2ZvczVwSytxNExMcThZbThwTEtlMEQ1MTdYNGthNHU4QkRLUy81V0c5RFdZSVBvZTdtNkM4Nk9qL2lHTDkwU1dhRjY4cjcyU2NHcWI3ZXZGWFNpM1hvSWNFcCtpbGRjT3Q2UzErcDBzWkVROXpGRHFWclE4RWJ6eng5S0s2RVBDKy9GM0x2am5Qa1U4WEg4VldIWXgzWFNNcHNXZFZ3OWptZmZmU25vbmNFcCtpclVXWGY5N1B2WndFTWRLRHVrcjVwMC9DNmF6VTlvQ2dubStIczZDVFVXM0oyMkdrSjFkbFJ6R2IwZ2dJMjJTOTlVZlpIWHdoT1ljUGVqODNDcFBEdk9EYWxsL0xFQzdvMXJQaTdmOWpUMzN0dGZwa3o3cysvRkJ2Unl6Um5FNE53Vy9iMzVhYnNEeklrT0VYL3BLaC9UYVZPNVQ4cFMrVUJuZ2d1VzFBbzdZTXUxWnF0dUsrc3FmUjMxN1dPS2VlYW51Yk10Tkp6NXVrZTFrb3hRS1hzbG0zRW9PcTViQ3B5SkRoRkg0MHErNzYxbEx6OVlXb3Y5Y1lRUUNkQmcxaHlWV3N3ZUo4Wk1IOVZOdGFINWs0aG0veXVtMDZuL2xQUFhLelpnVUc0bjAwMU5DVHNtK0FVZlZSYlNWOHRLZHd5cHg1YkFBUE90WGJ2TmVPOS92MTErYjJvYjVQbVRxM1pQTU05akhkY0Y3NTJ1V2JIOTc2dlRUYlZXMi82WTE4RXAraVgraHJWMXZNbW5KU3VQamJKRnpyd3RoWG94Tk5Ldi9lK00xK21sWTEzaWRsNXRiNjViei9YakJRUUZLQmkxK0llNnpTa2JLcFRKWDkwVFhDS3ZxbXRGMGh0MlVSSys1WjdiZ2lnZGNNS3YzTU9QZit1ekxQZSsxanBOV04vRDQ0RXFHaFB6Sng2RzFLUTZsekpIMTBSbk1JaUlGOVhzNFhIdEtxamUzWjBHVFQ2WEdZa3pScGFWRjltN3R5NHlWemQ1N1gvdXJwcmYybWJ2WHF6bndkN3pTNFJvS0tMOVdjcStmc3FTRVhiQktmbzAwTHVSV1ViaDgrVkhtbTlwNVpUMmdmdHFYWFJuVXM1bHV3cGM4bXgzSVFBRmQzTjgzbGZxcEhob0EyQ1UvUkpiV1ZOWXhzbEtqOEhvRXMxOXB1YVpKU2hXMXR3cXJ6cmVXclVmVlhoZWZRMGc3R1BhMFlCS3Jvd21IM09CYWxvZytBVWZWSlQxc2psM3NzczlydTRuWnJ1Uzg0QnBYM1Fsc01LdjNOT0dicC9WVGZmeXJ5ZTE1ajFuY2UxUTRDS2JnMkNJQlU3SmpoRlA2U1N2cG8yNWJVM0JsZmF0NXdGQU96K0hqTUk5ZldieXFFUitsMDFadHlVK05CdFhPRnh6Q2ZRbUFKVVQ0TCtuWFFuM2p2blFTcnRKOWlLNEJSOTRTMTlkZmxzeWpzWG9OUE5aWDN5eXRBOU81cFVlQXpLS3lWTmM2ckdOY3hoUnNjZ0JucWZoVG9EdnV6UFlQYjVvbkU2MnhDY0luL3BhVlJOa2ZoeHRTVjk5eGRXRmxYTEZzRDdmRE1RQ0JLVUlzY00zZHF1K3kvTXJXTGt0Um0vRFZESlJHY2Y1MElNVUgyeFhtVmRnbE5ZdkZuVTVVcjIxSElqUXdBN1ZWdm0xUFZzODVyanByVzI0TlJCb1dVd05RWkVmcy91SjRvUE9zK09YczcrOU1FbG5qM3QzMktwMzRsK3FheEtjSW8rcUttTUtkY05nOFd0Y3dKS05xenMrMDR5L2JsK1ZEajNTbnhyMzNYR2M2d3RoeGtmajVQWnJ5K0RQbFRzeC91UWdsUWpROEd2Q0U2UnQ1UU9XdE9tUVVEbWRqRTFEVXI3bGhuTXpvMUR3d0E3dWMvVWVDN2xtcUU3cWZCWWxQb1cxdHF5d0FkWkg4ZjA0UE5KcGVjWSt4ZlBqZk9tSDVYMUswc0pUcEgvb3EwdW54eHk0N0VpMlZPd3EwMWxmZko4RUpMNjVOUzRhVlBhVjRhOE45M3hvZC9aVWV4RHBjeVBmUm5PUHQ5dlN2MWdBY0VwYk1Eek1hMTBZVzV4dXhtdjY0VWFOcFM3ZDVYNVN6Y20xam9GU05uUFU5ZVNMSTlOREF3OENiTFQyWi8zNGZqaXV5d3FIaEtjSWwrcHBLK21pNVpBek04THFHdmpzdFNnMEVhNjBMWGZLL3Urazh4L3ZtOFZ6c0Zob1crMW1sUjJIUC9iby9WVkRGTEhBSlVzS3ZZbDd2RmtVWEdQNEJRNWUxUFo5L1YydXNXOHZYQzU1NFlBdGphbzdQdm1mazJkV1BNVW83WkFZLzhlcU1xaVl2OWtVZkVQd1NseVZsTld5SldTdnFVTHAzSHdoaG5uQ05oUTd1NStrL2MxZjFMcFBCd1YyQmk5dG1QWnoydkovU3dxNnkzMmRlNTg5VVkvQktmSVU0cWVEeXI2eHJLbUhxZTBiN0VETjNMWTZsNHpxT3diNTk1dnF1WnJmbm1OMGV2ck8zWFE4K04xRWxJV2xUVVgrenAvNGh2OXpndDlneWtyRUp3aVY3VzlpY3hDNEhGSys1WlQyZ2ViRzFUMmZTYzkrVG0vVlRvZjN4ZjRuZXJLQ2orK0dQYjY1MDl2OUhzNSsxTjhxOS9VTFlJOUdJV1VSYVhNcjBLQ1UrUjhZYXJGVmZOMGtlV0xwUmk4azJxKzJBdFBtR0JqdFMxK2YvVGs1NnoxZ2MyZ3dHellINEUrcnJzbXM4OXZzeis5dHY1aVQvZm1yNzBQOXJJMndTbnlrOTVBVnRObSs1T0R2cEt4SVZoSzd5bllURzJCM1dsUE5zYlRVRy9XUm1uWlU1UEtqbDlabStuVTl6TUdxZlNqWWgvM1ozMm9LaU00Ulk1cUsxTlMwcmNhZmJtV2UyVUlZQ08vVi9WdCs5VnNYUFpVR2FZdU03Mi9ibHczL2FoaWtHcHNRT2hZNmtORkZRU255RkZOV1NDWFBXbE9tOFBpNk1vaWQ2bGhoWTJkWVJkcXlwenFXKytmbW5zTmxwTTlWVi9iZ25JRDNpbElGY3Y4QktubzJraUFxZzZDVStRbFBTMnNhYk9nMGZkNlpFOHRwN1FQMWxmVC9hWmZEMEpTbGxldEQyOUt5NTZhdUtZVUpEVk5GNlNpYXpGQTlVV2YxYklKVHBHYm1rcjY0cUpiU2Q5NkxJS1dVOW9INjZ1cElYb2YzNEJYOHozeXRLQk4yTFNpNDFiUHhsbVFpdTdGQjdGZkJhaktKVGhGUHRLRlJra2ZqeStFYW5zdDlUcWJiSy9kQlpicjQvMm01dXppdUNaNlc4aDMrYXVxZTNHTmE3UGJJTlhIb0hFNjdaOWpBbFNGRXB3aUo3V1ZKU25wMjR6U3Z1VmtUOEdxNnV2VDFyL0EvdG5SWmVVYjNmZUZ6Tk9wQzA0RlVwRHFYYmg5dTUvalRsdGlnRW9QcWdJSlRwR1ROeFY5MSt0bTBjMzZqTnR5K2s3QjZnYUdvQmZHbFgvL0VqWmdVOU80SXZPMys1MGR4U0JWektpUzhVNDdhMTVOMG9zak9FVWUwcFBCbWxLaHh3NzZ4b3VldU1nVm9GcTIyVmJhQnl5K2RrNTYrcFBYbmkwYjM4YnF3VU8vMXJSRGcvRFBkV2M4K3p5Wi9lbVp0Uzh0aUUzU1R3MURPUVNueUVWdEN5K2xhZHRSRXJuY0cwTUFGTFM1alZrWDA4cEg0YnpYL1ZYNkd4aGxsM1BndGk5VkxQblRsNHBkZVZ2WTIwMnJKamhGTG1ycWxUTnRGdHRzVHViVWNwNnd3Mm8wVSsyUFQrYXEvaW9VSVBXbGlpVi8vd21wNUc5aVVOaUJjNVVEWlJDY1l2L1N4YVNtQzRyQXl2YUxtL2pFYld3Z2xteGlsSURBS21xNjcvUjlBK2krbWZxcnVMWlQwbG91bHZ6RmNqOXYrV01Ydk1HdkFJSlQ1S0MyTjR4OWNzaDNRbW5mY3M4TkFWRFFKbllhQktpaTh4Ni92Vy9xOExIMC9JNXYrYnZOcG5LdXM0a1ltUHBpR1BwTmNJb2MxUFFrOEtwWlpMUDlZcWIyVjR3L1p1VHBFVkFZdlJyN1hkNW43Y01xYTd1WVRmVXlwR3lxZCtZTmE0b3ZrRGd4RFAwbE9NVitwWksrZ2NVMUcvSjBiVG5sSDBCSm05WkxHOVYvTmwvZVRwWDdNV0xiOHoxbVUzMmNmV0tRS3I3dGJ4dzhrR1ExNy9XZjZpL0JLZmF0dGplTENhYnNsbURmY2tyN2dOSW9pMC9lNmo5Rk5lSkxoT0tiL2xMWjMwdHJhVmJnQlJJOUpUakZ2dFcwdUpvbzZkdjVnbVVTUEVsZmZtNHA3UVBLTWc2eUoyNDNYN0lEcUcvZGQ5bVUvWG5iSDQ4NVZON1hUNEpUN0U5NjZsZlQ1bG1XVHpzOFFWdHVaQWlBZ2phbTE2NzUvMGo5cHp5RW9OWnJ3ZjIzL2NYK1ZGY0doanZlOS9nRkV0VVNuR0tmYWlzN3NxQnVoNkRmY3E4TUFWQ1lENGJnSHpGejZxdGhvR3EzL2FsaWJ5cUJLdTVTM3Rjei96WUU3RVY2MGplcTdGdi9QZnZlamozZGJsemlVeVBscEVCSkc5SGppM0dRR1hyM09uOSswNU1IWEIvaWV1Zmp6U2RsemNRcWpWY2hCWEtwVDN5QnhMQnBBMElQeUp4aVh6VHloRzdZd0FHbDBSajk0WFUrQnFqSWhheWRITWlvSXZGMjB4NFJuR0pmdkVrTXVxRzBEeWh0MHhrM21CTURjYzhvOHdiQU5mWEcwclEvdjJ2R29rQ1ZhMGdkWW5icHlERDBnK0FVM1VzbGZUS25vQnNEYjNRQ0NxVDMxTS9lWjd3SmN4OGlEN2VCcXRoTWZmN1dQMzFoUzc4MjBndUNVK3pEeUJCQXAyUlB3YyttRlgzWDhnSURxWWZJeERUK3lia3NBVmo1T2pKLzY5L0xrQUpWOGZkeGtQMVdta0h6bG5neUp6aUZqVEtVencwWmZqYXQ2THVXV2xJbGUycXg4OHhML0NBL0tWQjFlZk55Z2JPanU0R3FxY0Vwd2h0RGtEL0JLYnFWM3B3aHRSdTY1WWtSVU9KbWNoS1U0eXp6UHBzbTZVckw2ZWYxWlI2b2lqMnFZcStxK0JiQXFZSHByYUZyVWY0RXAraWFEVExzaDVjUVFNM0tYWlMvYzNDWHl1VXRmZ2RWamJyWDFwZDRUSzltbjNjQ1ZiMG5leXB6Z2xPNEtFQWRCSWJodnRwNmlwUVpJSWpOalZQcERZdkZBTlgzNW1VMDVoNXNmODI1RzZqU282cHZhK0g5WGd2NUJjRXB1cE9lMmc0TUJPeHBjNkJKTHR6ZllOU2w1UHZ2QjV2RFI4WDExOWM5WnM4cHBhSFUrOGpESGxYS2pITmZDM3RZbXpYQkticWtFVHJzbDlJK3FOZWc0QTNpZFBicko0ZjRVZk1BMVQ0Mlp2K3RhSnlucGxxbFVxQnEvdGEvV0c1OFpWQ3NoVm1QNEJSZEVxbUdmWitEMHBtaDFvM2s3NFYvUHoxZ2ZpMWUvNy9NN2dPbkhmKzlBOWNVcXBIZSt2ZHg5b205cWViOXFXUjI1clVXSGhpR1BBbE8wWTMwcE02RkFISzRLUU0xYmlUTERrekhEYUhtNkt0NjIvU2g2bXBkcHF5UE90MzJwNHJaVks5bm40bEJ5Y0xRRU9SSmNJcXVTS0dFUENpdkJZdnhVamVDbHpaL0s0c0JveGlnZXR2cTM1S3lkV3ZLMlAxbWFySGsralNlZlo2RmxFMDFEcktwN0V2NWllQVVYWkd0QWJsc1VLVXpRNTBieWYwMXhPN1NhOU42WlRGb2REcWJGMTlidkMvSW1vSzdValpWdkU3RnQvM0ZiTStwUWJFdkpSR2Nvb3ZGOEl2Z05jTGdwZ3pzMjZDQ2pWL2M2SDF3cU5jeURPMWxVUTByRzB0TnNGbjFXalh2VFJXRFZLL05uYjNzVDhtTTRCUmRVRVlFemtuSTBhU3k3MXRIRnN2WjBVbVFqYkN1ZVJaVkRGSU5kL2p2L2IyeWNWU3F4U2JYckhIVFFQMVpVSnJjbGFlR0lEK0NVN1FyOVJvUW1ZYmNOcWgxbFBjQTlTN0dsZmR0ZW44SUlaYjVuZStvMUsrMmU0M3NGelozZGpScCtsSUpVblZ6clNNemdsTzBUV0FLOGlSN0N1SkdvQzdEeW83dFI1TjhZNlBaNTg5d2ZISGFQR2hjWC9yL0RTcTdwc2ljWWpmWHI5c2dsWUNuKzJFMUJLZG9tN2NoUUo0RWppR3Bhek5aVjlaazdEMDFOY1czRXZ0UXhTRFZ5UWFaVkxWdC9pYW1DenVWZ2xTeDNPKzFhMWtyOThPaFFjaUw0QlJ0bnZBREcyREkxa0JwSDl5bzdhbDBQWXZ4bE1XaXZHOTdNUVBxZlVoQnFuWEsvV3JyNlRJMVZXanBXamFlL1JxRFZESGdManR2ZDZ5RE15TTRSWnNFcGlCdmJ3d0JWQmVjcWl0Z29MeHYxMFloQmFtK3J2QzJxOXJXZ1grWkhyUjRMYnR1WHZZUWcxUVRBN0lUdnh1Q3ZBaE8wU1k5YlNCdkFzaFEzNGF5dnZQKzdPaGQwTGRsMTRheno1ZHdmREh2UzNVL0F5RmxWdzBxR3hNQkE3cTRuazJiZmxRdmd5eXFiUTBNUVY0RXAyaEhXcFJJbFlTOEhhenc1QnRLVjEvUW9zN3ovcldOWEd1YnU5aVg2dnRzWHNYUDJ5WlFWZU1jbTVvT2RPYnM2RExJb3RyVzBCRGtSWENLdG93TUFmU0NseFpRK3dLL3hvWDkwd3FQY3d4Q3ZqUGhXeFdEVXFjaEJxclM3elc1dnNsb2dXNnZhL01zcWc4R1kwUHJ2K2lCRmdsTzBSWWxmZEFQbzQxZkV3N2xxQzE3cXM2TXlkUlVlR3k2NHhwQ1lkZTJrOW12TVVnbE8zUjlBME9RRDhFcGRpK2xjenZSd1VZVmJDeHpYWXpYKzdaTy9hZG93emREd0Y2bExPQVlvSm9hakRYdmgyUkRjSW8yeUpxQ2ZsSGFSKzErdUZkWHM0R0xtUVg2VDdGckFwN2tjSDJMOC9DSitiaVdnU0hJaCtBVWJSZ1pBdWlWRjByN3FOeWt5dk8rN2czY2E5TWUxeEFLdkw3RndIdk1vQktnV3MzL0dvSjhDRTZ4VytrTlFEYTUwRDhqUTBERmkva2FGL0dEcXQvV21kNTBwWWt3dXpCdEFnS1F5L1Z0SHFDYUdveGY4bmI1akFoT3NXdktnNkNmbE9OU3U0bDdkblVidUpQWnI1ZW1QcTRkRkhoOWl3R3FsMEVKTXowaU9NV3VhYXdNL1hUb2RicFVyc2FHeHQ3V21jcjdsTC9nMmtGNWxEQ3ZRc1ZQUmdTbjJKM2ppNUVUSEhxK1VZVjZUWnozVlc3ZTV1VXZzZ3R3N2FERWExek1EdjFvSUpaUzFwY1J3U2wyU1VrZjlKdlNQbXBld05lNndYemoyQXRRc2JIWWIycHFHTWpjQjljMytrQndpdDFJWlFGSytxRGZZb05rVDVDbzJhVFM4OTc5TzVXL3ZIUUs0SnBCZ2RlM0dKaDZaeURJbmVBVXUySmhDMldRUFVYTi9xajBlOHVlU2h1NFNkQ2ZCZGNNeXJ5K2pZTzM5NUU1d1Nsc2FJRzdCSnFwMmFUUzd6ME14eGREaC8rZkRad0FGYTRabE9pRElTQm5nbE5zTDczaHk2SVd5cURFaDNxbDBxNXBwZDllOXRUdFBCamJ4TEdDU1ZNdUJYMFJtNk9iczJSTGNJcGRzSkdGc25pNUFiVXYzdXU4bDZlSFRVUm5SeWV6WDhjR2drY282YU52MTdYcml1OXh5OGtjem9iZ0ZMdWdwQTlLMjZSQ3ZiNVYvTjNQSGY1N0c3bFkzamMyRUN4aGs0OTdIT3lRNEJUYlNXLzI4bll2S012QjdOd2VHUWFxZEhaVWM5bUQzbE0vendjQktoYTVtczJOcVdHZ2h5YUdnRndKVHJFdFdWTlFKcVY5MUt6bWpJajNEdjhEQWxUWTRGUE85V3dhdkxYdjRaZzRuek1oT01XMmxQOUFxZWYyOGNXQllhQlNOZmVTR1hvcHdzTE5pd0FWZDMwMkJQVFkxQkNRSThFcE5wZEsrZ1lHQW9wbGcwcWQ2aTd0aTA0RnB4Zk9peGlnZW0wZ3FuZlZ2TmtUK2tyZktiSWtPTVUydkhZYXlxWnNsNXJWWE5vM21IM2VtZ0lMbkIyTmd3QlY3V1JOQWJSQWNJcHR5S3FBc2cyOVdyNlE0OGdtYW45Ti9Idm4veEszQWFwcmcxRWxiK21qNzZhR2dCd0pUckdaMUk5Q3lqK1VUeENhT3FYU3Z0b1g4T2Ntd3RMNU1aNzkraXdJVU5WbTRpMTlGTUFjSmt1Q1UyekttN3lnRGtyN3FGbnRHUkl4ZTFKNTN6S3A3MUFNVU9rL1ZBOGxmVkNXaVNISWgrQVU2MHROVW1WVFFCME9tNWNmMEYrL0c0S05mVElFeXZzZUpVQlZrNWdscDZRUG9DWC9OZ1Jzb0xhU3Z0ZE4rajRsUzlrQnB3WmlvVmMyWHIybUJIdFRzWHpuK0dJUzZ1N2JGZWRQTE85N1prSXNuU2N4YVBGa05sZmlPSTBNU0xFdW0yTU5RQXRrVHJHSm1rcjZyZ1dtcXVFNEx5ZFRzdDlrdm0xSEdVOHE3enN4REw5d2RoU2JwSHVUWDdsa1VrSjV2aG1DZkFoT3NaNzZTdnFrYjllenFaQ3V2OXhBYVYrdnlaemE3dG93RHBwZVI3RzhiMmdZVnBvdlQ4eVo0bHcxSlp4UUFtczZzaVE0eGJwcXk2RDR3eUYzdkxueHByY2JDb0tnd3Raa1RDUmZtb2RVUENZRk1YNExHdTI2QmtDZS9tc0lyQk56SkRoRkxSdlVUVnczcnhLbkhvNzNjaTk2ZXg0VGVVcTZuYkVodUJFRFUxOE53d3BpTnU3WlVlelQ5Y0ZnRkxFZWRBMmdKRU5EWUoyWUk4RXBWcGZlMWxQVEJzZENwTWJOaE9PK2ZGTjZmS0gzVkg5NVk5OTIxNGFwYThNL0RwdkczNncyZDA1Q2FpWnZBOVJmc3FZb2FUOTNFRHl3dW51Tm5oaUVmQWhPc1k3YU5xYWE0TlpKYWQ5eXp3MUJidzBOZ1h2Q0RvMW1HNXlSWVZocjh4UEwvR1RuOWs4TUtuNDBETmpQRlh0K2t4SEJLZFpSVTBuZlZPUExhamNSbDI1V2oyNUk5WnZwcDBHVC9jcm0xNFpKMEVQb3JuUFpsR3ZObjFnYTluTDJwM2Z1TWIxeTJXUlZReWxlR1lKLzJPdGxSbkNLMWFRM2RkVzBzZkdFdlBiRktNdjBiVE02ZGNqK01UUUVXOU0vNkw1emIvSmMwOWxSek1LSmIvT2JHQXpuUEhTOG54dGFDOXdqT0pVWndTbFdWVnVVZmV5UVYwMS9pZVg2VmRxWGVnWFJ4Mk9YNTN5YUJBSFB1MUtEZEFHcTlhOUxxVm02TEtyYzE0THVJWlRsdlNHNDU0Y2h5SXZnRkt1cUtYWC95bUtrK28zRGxRM29JOWNDcFgyT1hkMWtVdHduUUxYNXZXYWVSU1ZiMTdrTzdaSTF0WGpQUjFZRXAxajFZamFvNkJzcjZTUFlMRHhxMUxPZmQrcVEvVU9Qb0cybFY4cWJVL2NKVUcwK242Wk5MNnFYNWxWVzlwczFGZGZleHhkLzNyeDR3RU1GdHA5UGNRNTV5K3JQMTEvQnFjd0lUckdLMmtyNkJDV0lCQ25MdVNiWThOVjdQVytMaklxZkNWQnR0MG1LYTQ4bjVwWnovTTYxZWhCU1FDRUdxZlIzWXh1bm9hNUVnMVZNREVGK0JLZFlSVTFQMmkrVjlORnNGT0xURkU5VUZqdjA1cmZlR2pwMk83aytqSU9nNXlJQ1ZOdk5xL2hHdjVQWm4zNnpjZHFyZldkTnhXdjA2TUY1RmYvNSsreS9pNSszc3FsWVl6Nk5Rdjh5M3J2d3pSRGtSM0NLWDEzUVhqUTN4VnI4NGFCemgreXA1ZnEwMExFQXVlK05JZGlKMTRaZ0lRR3FiZDAyVEkrZnFRSHAzTDZ6cGg1cldoM1BxNWdGODNlVFRhVlVtMS90NDVUekxUWXhCUGtSbk9KWGFudTdrNUkreklmVktBL3JMejFNZGhOQW1GamNMalVQVUkwTXhaWno3T3dvWmxIRlFPalVnSFRpUTJaWlU0OWZ5MFA0TXZ2L3hFRFZxWUF3RCtaU25BOENVNC9mdzhtTTRCU1BYZFFPUWwxcG9KYzNLZlZ3ZStPYTJud3VOZWpSUXRneC9EbHc4Tll3N09RZUtjajMrRHc3dnlsQll0dDcwYmdKVXNXTUh1dVU5c1N4L2Jqbm4rSDlGdGYwNzAwVDliZkt0NnUvUHcxRGZFRGdIclY4ejBlV0JLZDRURzJwd2txNE1DL1cwNWZzS1p1NW43MlJQYlhWd3YrZ1dmakxWUGkxMDZiOHlIemIxbTAvS2tHcWRuelk2MFBLOU1CbnRPVy9aUkJTMmQrZmQvcFREUnphcXU1UG95QXc5U3ZhUFdSS2NJckgxRlRTZDkyOEtRY2VNaStXNjBjQTI2dUNGNUU5dGZuQ1gyQnFmV216WkpPOGkrdlo5WU1nMWRTZzdFVHM4N1h2cktuVEhmLzc1djJwQktycXVUL0Y0NjJVejlxK3QvNWxDRmh5Y1J2YzNNenFFVlBtTmJkbDJmbndKZFNYU2JpcWw3MEk3TWFGdVdEQ0lyOTVRK25hOThZdjV0TEdZbGJLYXcrRGRqNHZSeUdWZ3cwTXhzYWU3YlVIelcwWlZoZmlBNXZQd1J1cTNadnFkRFdiOTA4TVE1NWtUckZNYlJ0eGIrbkQvTmhNWHpJc0xjQVg4NFIxOWNWL1hQUUxjbTduSUtRR3pzcjhkdW0ySjFWOHU5L0VnS3p0TW9QbXlPODcvTHNlWmxScHB0N3ZlOU5iOTZhMWFOZVJNY0VwbHFucFRWeFRUM0g1NWNKZmY0OWwraExJL3VGUUxUVFVzSHFseFgrYzUzcDQ3TTRvcE9iTlEwT3gwM3ZWSktTSEtlNVhxNHRqOVc3UDE1Zmh6YlY0UDJKQVk5NU0vZThtY1B4QzhMZ1g5Nlg0WXBwNFh6cDFiMXFMUFYvR0JLZFlmTEdySy9ydUlvVjVzcm1EbnJ3dVh0K3A1ZDU3YXY3b1BURnUzTDVZL085Y1hHdDhiYkkyaksyTjZyNTh5cUMwTFpjTTF2bGJ1dVAxN3UrYitaVDZWTGsvNUhXdUh6UzlwV0w3bGFFQldYTXRxSlExYS84MkJDd3dxdXo3U3U5a0ZYOVVlRzZzS3BiMmpiTmZrUERZaGlRK0xYKzIxemRWNWJnQlNKdEcvZWJhOWZabWpJOHYzc2xpM25pdW5vVDRCazVCcVUwMnFpZDdQblp4WFRISWRIeUdZUjc4T0w2SUcvcEpTRzg1bTlqZzcrMmU5TmE1dnBWUGhpQnZHcUt6Nk9MM1o2aW5xZWEwNmRNQXpvM3QvQ2Y3d0liajl5dXg3OHBMd3hEbS9hVmlZRXJHUUxmaTV2ZTFqZS9LODNUWXpGUFh0YzA4MmV2YlhGT3c0WHRQajk5VnVCK3M4bUNqM1hraUtMVzlPRWQvTTFmekpuT0tSUXZ5bWhZNXNxWlliL09lRmdqOExHYVhqSHV3bUxhSmUrd1l4bjRqdGIrNU5KWHhuWm9PZXpFTXFVbHp2Slo4RUtSNmRLMTJHcFQwYk9QRFhnTlR5ZHNlMzVNT3cyMi9xamduNThHcUgwRm0xYTdPODNoK3h4N0FJNE94b3pXOHdGVDJCS2Q0NkZWbDMzZnNrTE9HejBGdzZyRnJSKzduVTN6Q3EwVHJjYVBaZ3ZqSGJBSDNzY0tOUU53a250dndaeklQVTdBMGxtQjh0S0c0TjBmZjI2eHVMWWR5dnBnQjg2YWdNWjBIcStiZmJ4clNBNkZ2elhoUFRMdVZ6L0VYemR3WUdKQ2RVdExYQThyNmVIaFJyS25zSmQ0c256am9PRWQyNXJlc241YW1iSVB2RHROSzNsVVZvTkt6SjJjeE1EVU9lVFN1M3RmOEhBWVpGTHYwWk85WlV6Rkx0YjdqT1FrcFlQV2pXWVByQlpubVFseFR2bWpPY2FYa2JjMjlzNk5uaGlGL2dsUGN2VGpHQytNWG15LzQ1U2IydllIbzZUa1ZYNVV0QUxHcWNmRWxmbW5UZjJwRDBLTTVHVE5ZYThuQ1NPdXlHRFFkT3ZRNzh5R0RyS2xCU0c5YUl3V3NwbUVlc0VwQnErdEt6dTJuemJudC90TysyTXR3YkJqeUp6akYzUXRsYlU5eC9xTlVBSXZLbmNvL0cvSDRJZ2JnbGZhdDdySloxRjBYZUI2Zm1nczl2dGFrRW8zTFF1ZG1YSXZGTElxQlExM2dQZXI0NG1zUWNIek1kWmdIcWtMNHEvbDkydHZNeVhST3h3RFUwK1ozeDc1YlhuN1ZJNEpUM0wxNDFwUlI0SzFVYkhPdWZBK2VkQzN6Sk90VS9mVGE3bk9IYWUxQXdPc2lTakQwN0NuUmVQYjVZelkvTDNzOEwrUGFLd1pLbndjQjA3WmNOL2VuNlo2UDlYRDI2MWVIWTZ2N1VUeVczeDc4OC80enJ0SjVQTys5OWQ4N2Y1YXR2Vit5cG5wRVEzVG1GOVFYbFYwOC8zRFEyY0xuSURpMXpLdG1zWmlyaVVPMHR0U3I2L2hpLytVd205L2pCa0ZRcWxTamtCcjV4NDNwWmJOcHpUK2pLczNKWVJDUTZzcTdUREp2UEJ6Wi9uNFV3cUxzbytPTCtPdjFuVFZJL1BPUE8vK0xhZk41NkhyaHc1Y1VTSHhvRUc0ekd2L2IvUG5BbWpCYlU0R3BmcEU1eGZ3Q1hGdXBpNUkrdGpsZjRrTGtid094ZENId1crYkhUK2JiNXE2YVRkNmtKK2RxM0Z4b0pGM3ZYSTBQb2lZaG42eUtPQi8xbWVsZUh2M3pqaS9pMjM1UEhRN29qS3lwbmhHY29zYU5kdmxOZnVuaXZORzdhTG5jUy90c0VIWnhIVTJOaGFlWjN0Tkd3YXU0dVcvZXcyYmVlTG05SGpZcEt5cCtoclBQN3lFRm9zekYvUjMzWjVrRUoyTy9TaVZlME5XNTc2M3N2YU9zajFEaEJsdEpIN3VhUjRKVGk4V2dRTTRCNEZqNkl6aTFuVkZJcFZUamtNUGIwL1RzNGRmbS9WL3V6cHY0NitTZmpVd0kvM2Zuejc4S1pneUM4cDdjeFdQNE1wTk0rZE1nTUFWZGVtY0kra2ZtRkxXOU5TVFdsZi9IUVdkSG0yR2xmWDA5ejVUMjdkbzAzTDQ5YmRyUk1aeS85U2lXU1FsSUFRKzl6S0pSZnJwV2ZYYzRvRE9UMmJuL3pERDBqOHdwRyt4QnFPdVZwcGNPT2pzUm44U21ySkdSd2ZqSndjMUxGdkorZTVhbTlyc1Y3eVduTjUvamk2dVFzbEZpZHVGdWV2M2N2Z1VwM3E5K2IzNlhoUUFzOHlHamU1Qk1YZWlXOWkwOUpUaEZiVStiUHp2azdGRGNmSThNdzBLeHZDcm40TlRZaHFFMTgvS3B0emYvZEh3eERTbXo2dUdydnhlNVd4YjErNTEvRm9nQ1ZyKys1L0ptMGVPTHVFWVlPaVRRbVR6N1liSVNaWDIxcTZ1MEpmKzNpTkhIYytodkcrZWw4bjRyNXZGRmZLWDN5R0VDS0VZZURkRFRQVVlUZExEWFl3My9Zd2lxM2xRUFFsMWxMVXI2TUsrNmxYdG1wa3hLZ0hMRWdOU3pqQjZLdkE4Q1U5QWw1WHc5SnpoVnR6ZVZmVjhiVWRyd3lSQXM5VHpybnk2OVlXN3FNQUgwWGw2QnFkUUUvYTNEQXAzNXVQYzNCN00xd2FtNjFkUnZLcVo1WGpuazdGeWFWMU1Ec2VRYWs4b2FjdmJCWVFMb3ZaZVpyZlAwTklUdVhGblBsVUZ3cWxicGljNmdvbThzdTRVMktlMWJidFNEWTNmdE1BSDAxdXVzTWlZMFFZZDlYQU9zNVFxZ0lYcE9qaS9pamV5cmdlaTF5ZXppK013d1pIZHUvVCtENEx4N1pINmNoTlFiQklEK2JVckhHYTAzTkVHSGJyMmJYUU0rR29ZeXlKd0NvSFp4VWVPSkcwQy9mTWdxTUpWb2dnN2R1UlNZS292Z0ZBQjFTNm5nU244QittTTh1M2FmWlBVVHBRb0lUZENoRzdIUGxMZnpGVVp3Q2dCa1R3SDBSUXhNNWJncDFRUWR1aEhYYS9wTUZVaHdDZ0RTQXNlYlhnRHlsbWRnS3ZVdVBIUjRvQk12dllXOVRJSlRBQkNsdmdWVEF3R1FwVndEVTRQWnIyOGNIdWhFWG0vblpLY0Vwd0RnN3FJSGdOemtXc29YblFkTjBLRUxIek44Q1FJN0pEZ0ZBSFBwYWR5bGdTQWpzWFRodCtaM3FOR0hiQU5UeHhjdlpyOE9IU0pvWFF4UXZ6TU1aUk9jQW9ENzR1SkhrMDF5TUcvNk9wMzkvdXhtY1E1MWVaM2RXL25tamk5aXR0UzVRd1N0eXpsemtoMFNuQUtBdTFJZ1FITjA5aTBHcHA3OTAvUTFOdTFQaS9PeG9hRVNyek12NFZIT0IrMFRtS3FJNEJRQVBKU2FvMDhNQkh1MCtHMUVhWkgrMGZCUXNIbGdkcHp0VDNoOE1aejkrc0toZ2xZSlRGVkdjQW9BRm5zZGxQZXhyN24zMk51SVV0OE5DM1pLTkE5TVRiTDlDWlh6UVJjRXBpb2tPQVVBaXdNQVV3RUE5bUMxVXFiMHYza1dCRkFwUjJyK3Z5aGpNQy92WjUrQnd3V3RFWmlxbE9BVUFDd1BBTVEzOXltaG9pdnI5ZGhKMlNYUGdqZjVVY0ptTkdWTTVSMXNUZVY4YngwdWFNMUhnYWw2Q1U0QndPTUJnSGMyLzNSZ3MrYlBLY3NrQnFnbWhwQ2UrbkN6R2MwL01LV2NEOXEvRDc0ekRQVVNuQUtBWDFNK1JWdXV3N1p2SlV0djhvdHpWSllmZlp2N3NmSC9TVTkrWHVWODBONjE0Rm5tYitla0E0SlRBTERLNWwrQWl0d1g1T21KODB2emxCNklHWDlQbXRMcC9CMWZESUp5UG1qcldwRDNTeERvak9BVUFLeTI4WThMS0gwUTJKVnBzeUMvMnZFOHZRejZVSkczY1RQM3B6MjYvc2VmOWJmbVp3ZDI0N0tWK3lDOUpUZ0ZBT3R0L0FXbzJOWThhK1NxcFhrNjcwT2x6SStjek12NDh1OHZ0Zmk4bWphTm1tT1FhdUp3d2xaaXI3bVh2YndXMEJyQktRQlliNE15RGdKVWJDN09uL2JmU3BiNlVDbnpJeGY5S3VONy9OeWFOajNldklnQTFqZHQ3b0VuaG9LSEJLY0FZUDNOeVRnSVVMRys3dDlLbG9JQk1qM1k5N3gvMHFzeXZ0WE9yWWtnRmF3bDNvK2U2Qy9GTW9KVEFMRFp4bVFjQktoWXpiengrY21lNXVyOGJYN3ZnaXdxdWpQUGxqb3ArbHNLVXNFcTk4Q1h5dmo0RmNFcEFOaDhVeklPQWxTc3RrR2ZaREJmUDk3OExEYlF0RytlTFZWUG8rUDdRYXF4S1FBM0pxR1VrbDVhSnpnRkFOdHRTT0ltSkFhb1BBMWsyUVo5bXRGOG5jcWlva1YxWkVzOWZvNU43alJPSDVzU1ZHcWVMZldzdUpKZVdpTTRCUURiYjBiaUJ1U1p6VDZOYWNpOTRldHRGcFduMmV4cUkxcGZ0dFRqNTlqZHQvdDljSCtnSWg5djVyMXNLZFlrT0FVQXU5bUlYRFdiZlJ1enVvMURYeHErcHMxemZKdGZES3hPSFRvMk5HOXlmR0lvbHA1bkp5RUZxVjQ3MXlqWUpLUUhNKy8wbG1JVC96WUVBTEREVGNqeFJkem9uODQrSXdOU2xiamhmTmZMSjhVcGtQYmJiTzdHRGZTYjJlZkE0V1RGT2YvYW03ZFdQcy9pWm4xODh6bStHRGJuMmdzRFF5SFhnZzlORmpsc1RPWVVBT3g2QTVKS09mU2hxa2Nxa2V0N0NVUEs3bmdTOU1uaGNmRzZGZ094dndsTWJYeXVUWnFzeFhuSjM5U2cwTk5yd1lmbS91ZSt3ZFprVGdGQU81dVArSFE4bHZpZHp6NkhCcVJJVjgwbWZWTFF2STJiNU5lenVmdDU5dnY3Mldmb01ITkgzSWgrVkxLejAvUHQ1T1p6ZkJHenFGNEYyVlRrTDU3L24xd0wyRFhCS1FCb2IrT1IrbENsY3FuM0JxU29oZm1IcHFsNHFYTjNFbUwva0ZSK0ZNdFVCVmpyTm03bS9OUlF0SGJPeGN6THk5azVOd2dwUUJYTC9nWUdoc3p1ZllKU3RFWndDZ0RhMzNURXArSng0eUdMcXY4K05wdjA2MHJtN2lTa0FPc29wQUNyelhKZHhrRlFxdXR6YnRwY1p6N096cnQ0djVqM3B0SUxqbjBSbEtJVGdsTUEwTTJHWTU1RjliYlo1TnRvMktUM2FmNk9RMnJrUEFxQ1ZPWTdYZDQzVWcvRFZQYjNQQWhVMFoxNC9uKzZ1UjRJU3RHQmZ4bUNqS1RVK2E4R290ZGlnOHRuaGlHN2Mrdi9HUVRuWFdaek1tNHN2Tkd2TC9NcnZaSE1KdjNuTll1ZVZPVVpCMEdwUHB4L0FsVzBmZC83ck1rNVhaTTVCUUJkUzA4ZzQ1UHcrRVR5MUFZLzIwMzZaMjhqV3pxSEorRzJKMVZzNGp3eUtMMmxaS2QvNTEvcVR5V2ppdDFlQnk1dnJnVXBZdzg2SjNNcUp6S25TaUJ6S3M5elMrYVU4NjRQMTM5WktIa1lCNWtqbTh6aFFVaTljVVkyeUwxeDFXeEV4NGFpcUwzRVBGQTFNQ0NzdElhS0QySmlZRXB3bWowVG5NcnZoaUk0WlpQTTdzOHR3U25uWFovdUE0SlUzWnRuam93RnBYWXlqMGNoWlZPWngza2FCMW1CTlp5SGc1Q0NWTStkaXp3d0RTa2c1WjVIVnBUMUFVQXVia3VsNHFZaUJxbEdCcVZWTWtmYW1jZmprSnFueDNrc215cW51UzQ3b3FiemNCcm1iLzJMVXZuZjA1QUNWZDRhVzU5cFNHVjduNVh0a1N1WlV6bVJPVlVDbVZONW5sc3lwNXgzZloyN0I4M0dQbTd3Qnc3MVRzU04rZGdDdmZPNXJDL08vamFqbjJSSHNPRGVjamRZNWY1U3BxdHcyOXpjL1k3c0NVN2xkYU9JTndmQktadGtkbjl1Q1U0NTcwcTVSN3l5dWQvWWVQYjVvMmtrekg3bjhpamNsaHFaeTdzMURiSWpXUCtjUEdqT1I1bFYvWFlkVWpEcVcwaFprbE5EUXA4SVR1VjFZNGczZ2xNRDBXdFhzeHZCTzhPUTNia2w2T3U4SzIxT3kwSlpmWkgrUjFESzFJZTVIRGZFQXdPeTRUWHdkcDRMU0xHcmMzUFluSmUvaHhTc2NuN21LZDdudm9YMG9HNWlPT2d6d1NrQXNMa3Z4VFNrckpGdk1xUjZPWmZqQnZodXFSR0wzUTI4VG1SSDBOSDVHUitFSEFZQnEzMmJCTUVvQ2lVNEJRQmxiZTZIZHpiM3BXZFZLV0VvZXo0UEg4em5XbDAvMkpES2ppSzM4elRlZS83Yi9INFlaUFR1U2p6dnA4MjVmK1hjcDNTQ1V3QlE3cVpodmxGNGVtZlQwR2RYemNkQ3ZlNU44SHcrRHdyOXB1WTVwWnl2ZytZVE02M21mYTM0MlRUY0JxR216bnRxSlRnRkFQVnVHSjdlK1hPT0MvVzRPUDl4ODJmbEMvdzhsK2RsUm4zTjJuaTRJVFhQcWVrK0ZNMS9ud2V2Y3J3ZjdmcDhqNSsvbXZ2YnRYTWViZ2xPQVFEekxLdURPNXY3L3cyM21WWUhZWGRaVjlmTm9ueis1eC9ObnlmTlF0M1RZcmFkeTNmbjhlR0R1VHpzOENlNU85ZS8zWm5ud1lZVWZua2VENWZjZjU3ZStmTXU3MDJidW5zdXgvUDkveDc4NTFkZXlBR3JFWndDQURiWk9LeWFvVExWQzRvTTUrL0RUZTAybTl6SnZYOFNlSUtjenUzSERNTDlUSzFmbmJzZW9BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE4UC9aZzBNQ0FBQUFBRUgvWDd2Q0JnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBREFLQUVHQUN0WXVIdzdmV2xKQUFBQUFFbEZUa1N1UW1DQyIsImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIkZJRE9fMl8wIl0sImV4dGVuc2lvbnMiOlsiaG1hYy1zZWNyZXQiXSwiYWFndWlkIjoiMWMwODY1Mjg1OGQ1ZjIxMTgyM2MzNTY3ODZlMzYxNDAiLCJvcHRpb25zIjp7InBsYXQiOmZhbHNlLCJyayI6dHJ1ZSwiY2xpZW50UGluIjp0cnVlLCJ1cCI6ZmFsc2V9LCJtYXhNc2dTaXplIjoxMjgwLCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwiZmlybXdhcmVWZXJzaW9uIjoxfX0sInN0YXR1c1JlcG9ydHMiOlt7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEX0wxIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMjEtMDYtMjIiLCJjZXJ0aWZpY2F0aW9uRGVzY3JpcHRvciI6IkNhcmRPUyBGSURPMiIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMjEwNjIyMDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuMyJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMS0wNi0yMiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjEtMTEtMjQifSx7ImFhZ3VpZCI6Ijc3MDEwYmQ3LTIxMmEtNGZjOS1iMjM2LWQyY2E1ZTlkNDA4NCIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiNzcwMTBiZDctMjEyYS00ZmM5LWIyMzYtZDJjYTVlOWQ0MDg0IiwiZGVzY3JpcHRpb24iOiJGZWl0aWFuIEJpb1Bhc3MgRklETzIgQXV0aGVudGljYXRvciIsImF1dGhlbnRpY2F0b3JWZXJzaW9uIjoxLCJwcm90b2NvbEZhbWlseSI6ImZpZG8yIiwic2NoZW1hIjozLCJ1cHYiOlt7Im1ham9yIjoxLCJtaW5vciI6MH1dLCJhdXRoZW50aWNhdGlvbkFsZ29yaXRobXMiOlsic2VjcDI1NnIxX2VjZHNhX3NoYTI1Nl9yYXciXSwicHVibGljS2V5QWxnQW5kRW5jb2RpbmdzIjpbImNvc2UiXSwiYXR0ZXN0YXRpb25UeXBlcyI6WyJiYXNpY19mdWxsIl0sInVzZXJWZXJpZmljYXRpb25EZXRhaWxzIjpbW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6Im5vbmUifV0sW3sidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InBhc3Njb2RlX2V4dGVybmFsIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJmaW5nZXJwcmludF9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjJEQ0NBWDZnQXdJQkFnSVFHQlVyUWJkRHJtMjBGWm5Ec1gyQ0JUQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVzRllFRWhpSnVxcW5NZ1FqU2lpdkJqVjdER0NUZjRYQkJIL0I3dXZac0t4WFNoRjBMOHVESVNXVXZjRXhpeFJzNmdCM29sZFNyam94Nkw4VDk0Tk96cU5DTUVBd0hRWURWUjBPQkJZRUZFdTloeVlSclJ5Snp3Ull2bkRTQ0l4ckZpTzNNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lESFNiMm1iTkRBVU5YdnBQVTBvV0tlTnllMGZRMmw5RDAxQVIyK3NMWmRoQWlFQW8zd3o2ODRJRk1Wc0NDUm11SnF4SDZGUVJFU05xZXp1bzFFK0trR3hXdU09IiwiTUlJQmZqQ0NBU1dnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBWE1SVXdFd1lEVlFRRERBeEdWQ0JHU1VSUElEQXlNREF3SUJjTk1UWXdOVEF4TURBd01EQXdXaGdQTWpBMU1EQTFNREV3TURBd01EQmFNQmN4RlRBVEJnTlZCQU1NREVaVUlFWkpSRThnTURJd01EQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOQm1yUnFWT3h6dFRKVk4xOXZ0ZHFjTDd0S1Flb2wybm5NMi95WWd2a3NabnI1MFNLYlZnSUVrekhRVk91ODBMVkVFM2xWaGVPMUhqZ2d4QWxUNm80V2pZREJlTUIwR0ExVWREZ1FXQkJSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QWZCZ05WSFNNRUdEQVdnQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBTUJnTlZIUk1FQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQkJqQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQXdmUHFnSVdJVUIrUUJCYVZHc2RIeTBzNVJNeGxrenBTWC96U3lUWm1VcFFJZ0Iyd0o2blpSTThvWC9uQTQzUmg2U0pvdk0yWHdDQ0gvLytMaXJCQWJCME09IiwiTUlJQjJEQ0NBWDZnQXdJQkFnSVFGWjk3d3MySkdQRW9hNU5JK3A4ejFqQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVuZkFLYmp2TVgxRXkxYjZrK1dRUWROVk10OUpnR1d5SjNQdk00QlNLNVhxVGZvKyswb0FqLzR0bnd5SUwwSEZCUjlTdCtrdGpxU1hEZmppWEF1cnM4Nk5DTUVBd0hRWURWUjBPQkJZRUZOR2htRTJCZjhPNWEvWUhaNzFRRXY2UVJmRlVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQzNzVDFsQmpHZUYreEtUcHpWMUtZVTJja2FoVGQ0bUxKeXpZT2hhSHY0aWdJZ0QySllrZnlINVE0QnBvOHJyb08wSXQ3b1lqRjJrZ3kvZVNaM1U5R2xhcXc9Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUZBQUFBQVVDQU1BQUFBdEJrcmxBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQkhacFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1Tmkxak1ERTBJRGM1TGpFMU5qYzVOeXdnTWpBeE5DOHdPQzh5TUMwd09UbzFNem93TWlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwa1l6MGlhSFIwY0RvdkwzQjFjbXd1YjNKbkwyUmpMMlZzWlcxbGJuUnpMekV1TVM4aUlIaHRiRzV6T25Cb2IzUnZjMmh2Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOXdhRzkwYjNOb2IzQXZNUzR3THlJZ2VHMXNibk02ZUcxd1RVMDlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl0YlM4aUlIaHRiRzV6T25OMFVtVm1QU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2YzFSNWNHVXZVbVZ6YjNWeVkyVlNaV1lqSWlCNGJYQTZRM0psWVhSdmNsUnZiMnc5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBeU1ERTBJQ2hOWVdOcGJuUnZjMmdwSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE5pMHhNaTB6TUZReE5Eb3pNem93T0Nzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlNHbHpkRzl5ZVQwaU1qQXhOaTB4TWkwek1GUXhOVG96TURveU55c3dPRG93TUNZamVEazc1cGFINUx1MklPYWNxdWFnaCttaW1DMHhJT1czc3VhSmsrVzhnQ1lqZUVFN0lpQjRiWEJOVFRwSmJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qSkZOekZDUmtaRFF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2pKRk56RkNSa1pFUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJajRnUEhodGNFMU5Pa1JsY21sMlpXUkdjbTl0SUhOMFVtVm1PbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWtVM01VSkdSa0ZETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlJSE4wVW1WbU9tUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNa1UzTVVKR1JrSkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUx6NGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NDc3SlhGQUFBQVlGQk1WRVgvLy84RVZxSVhaYXZHMk9vcWNMRzJ6T09rd3QwQlNKdHFsY1hWNHUrYXV0bFdoYnprN1BVQU1ZOUhjcktqdE5icThmZUFsOGFCb3N6ejl2cGRqc0dHcXRGM244dVRzTlNacGM2SnNOVDUrdjB4WUtudThQZmY1L0w0OGZnL2ZyaWN6SmdZQUFBREFFbEVRVlI0MmtSVUNaYkRJQWpGWFpPWTFUYXROYzM5Ynprc1NZYzNyNE1FNGZNQkFhRDZ6bDh5LzlUT2dldDhkNWpmTjc4YndNL2REQ1JwUjUyMXpYZm9qSEowNUlJeWhCQVVTVkFPTmRHekJZdDJmN0tGcmZrSmFBa0hoOUZaaGNEWEhSa1RLbzlNTGloR2FhdkltblYzcXlFWDBFcHJnei80RHdVRDdrQ0hSbmQ4UUZONDNHbzRVVm1ERGd6YTR3MjdvaXpkQTIrY0srdXVVcGpqbzIreHdjLzQyVzUweDVMR1llREJzUjBIVkl4NXg4aUY2MENibGJURUVrRnIyN2JOREJVVlNxMU9LVlBiRTYyYjNFSDhGcUJnNU9PT0V1YzJ0OFpKaXFNT3VHcCtjS2pnN3dWR2Nlb3pxTjRweGdWUFFrakZZZ2JWSktEVWhEQ2pZcmF3UDVxNEVUZ0M5ZklNUkh0aXRwUWNDdkpPRUxjYk1zUWduY2lSa2xqcHlRanZHNDRqcUJVRVRGaUJpMVBFSXlla096c1crVHk1Y0xIb3M1UitkTVMxTHRTU3hmM2dRSGN6UjJDSTRnTU5wVzRJUkExUU1hNnRKNCtDNnVIdUdFOG1OREl5RnFnL09QL01NVXVlUzZJcThTOTBkQWVCSlNFeS9xS2tLK0JOd3o4Y1lZNGpiNUo2dTRpV0NJMkIxWjU2TFc1a0VjNGhrZE1wc3ZVQzU1ODVTWDBRdWJjZ05xeWZnREZFY1R0KzQwLzBTNU54MHdhQ3czT0trY09iQTVJbjBBWXAwMXBqancybjYyNlVEanRId2EyOGlIdVRLcXRydityZVc0MU5aNmlHbHI3dXVMSkNma0Z0Y3RjRzA0c2dtMWVOUytaYURucGFURXJHb3lYNUpLMmlNejh4czBuT3dXR2NQRE40OXFhQ2Q0YnpKb3pEWm0vYUJLK0Vvekx3K1hoTkJpWXdIZjBzaU91MVhQa0cvekt3dnFZS2NmU3dERWNIL29VZTA3ZXMvV1E4ckl5ZzJET1hqOHRqa1pkdURCL2I4aHpEbGxNTU9DUzVCRW5kNTM0Zjh0aTNVWmM0a01zM3hMeWFmTVNzSmhkRzhYUHFqTms1dEFnTzI1ZmVLQ2huVmREai9KMEZNa09zVS94TUJ2MHdGaFllRUdmVkgxM2Z1RFUweURGTGE0ZmM3Um5XSEJmdVRGVjJ0RW1Od2FkYzdhYzNVWTJqZkJsN0hUMzZmZTM0aVFPNW1OQ0ZGQlcwN0tqUGdxaE9MVTAxdlo4UHVlWjJKQ2xGWk44amtVczY5dWthOWVQcDYrRWZMNEFGNStOeXdTYmlySHRjQjhNbC9na3dBRWprSzY0S2pIUGVBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6Ijc3MDEwYmQ3MjEyYTRmYzliMjM2ZDJjYTVlOWQ0MDg0Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJ1diI6ZmFsc2UsInVzZXJWZXJpZmljYXRpb25NZ210UHJldmlldyI6ZmFsc2UsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjIwNDgsInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjEwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjk2LCJ0cmFuc3BvcnRzIjpbInVzYiJdLCJhbGdvcml0aG1zIjpbeyJ0eXBlIjoicHVibGljLWtleSIsImFsZyI6LTd9XX19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDE4LTEwLTI2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJGZWl0aWFuIEJpb1Bhc3MgRklETzIgYXV0aGVudGljYXRvciIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTgwOTI5MDAxIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNCIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4xLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTgtMTAtMjYifV0sInRpbWVPZkxhc3RTdGF0dXNDaGFuZ2UiOiIyMDE4LTEwLTI2In0seyJhYWd1aWQiOiJkOTRhMjlkOS01MmRkLTQyNDctOWMyZC04YjgxOGI2MTAzODkiLCJtZXRhZGF0YVN0YXRlbWVudCI6eyJsZWdhbEhlYWRlciI6IlN1Ym1pc3Npb24gb2YgdGhpcyBzdGF0ZW1lbnQgYW5kIHJldHJpZXZhbCBhbmQgdXNlIG9mIHRoaXMgc3RhdGVtZW50IGluZGljYXRlcyBhY2NlcHRhbmNlIG9mIHRoZSBhcHByb3ByaWF0ZSBhZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL2ZpZG9hbGxpYW5jZS5vcmcvbWV0YWRhdGEvbWV0YWRhdGEtbGVnYWwtdGVybXMvLiIsImFhZ3VpZCI6ImQ5NGEyOWQ5LTUyZGQtNDI0Ny05YzJkLThiODE4YjYxMDM4OSIsImRlc2NyaXB0aW9uIjoiVmVyaU1hcmsgR3VhcmQgRmluZ2VycHJpbnQgS2V5IiwiYXV0aGVudGljYXRvclZlcnNpb24iOjEsInByb3RvY29sRmFtaWx5IjoiZmlkbzIiLCJzY2hlbWEiOjMsInVwdiI6W3sibWFqb3IiOjEsIm1pbm9yIjowfV0sImF1dGhlbnRpY2F0aW9uQWxnb3JpdGhtcyI6WyJzZWNwMjU2cjFfZWNkc2Ffc2hhMjU2X3JhdyJdLCJwdWJsaWNLZXlBbGdBbmRFbmNvZGluZ3MiOlsiY29zZSJdLCJhdHRlc3RhdGlvblR5cGVzIjpbImJhc2ljX2Z1bGwiXSwidXNlclZlcmlmaWNhdGlvbkRldGFpbHMiOltbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoibm9uZSJ9LHsidXNlclZlcmlmaWNhdGlvbk1ldGhvZCI6InByZXNlbmNlX2ludGVybmFsIn0seyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoiZmluZ2VycHJpbnRfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9pbnRlcm5hbCJ9XV0sImtleVByb3RlY3Rpb24iOlsiaGFyZHdhcmUiLCJzZWN1cmVfZWxlbWVudCJdLCJpc0tleVJlc3RyaWN0ZWQiOnRydWUsImlzRnJlc2hVc2VyVmVyaWZpY2F0aW9uUmVxdWlyZWQiOnRydWUsIm1hdGNoZXJQcm90ZWN0aW9uIjpbIm9uX2NoaXAiXSwiY3J5cHRvU3RyZW5ndGgiOjExMiwiYXR0YWNobWVudEhpbnQiOlsiZXh0ZXJuYWwiXSwidGNEaXNwbGF5IjpbXSwiYXR0ZXN0YXRpb25Sb290Q2VydGlmaWNhdGVzIjpbIk1JSUNmRENDQWlPZ0F3SUJBZ0lKQVA0ZlNSUXBScDNxTUFvR0NDcUdTTTQ5QkFNQ01JR1pNUXN3Q1FZRFZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0F3Q1EwRXhFVEFQQmdOVkJBY01DRk5oYmlCS2IzTmxNUmd3RmdZRFZRUUtEQTlUZVc1aGNIUnBZM01zSUVsdVl5NHhEREFLQmdOVkJBc01BMUJEUkRFVk1CTUdBMVVFQXd3TVUzbHVZWEIwYVdOeklFTkJNU3N3S1FZSktvWklodmNOQVFrQkZoeGpaWEowTFdGMWRHaHZjbWwwZVVCemVXNWhjSFJwWTNNdVkyOXRNQ0FYRFRJd01EWXdPREl6TlRBd09Wb1lEekl3TlRFd05qQTRNak0xTURBNVdqQ0JtVEVMTUFrR0ExVUVCaE1DVlZNeEN6QUpCZ05WQkFnTUFrTkJNUkV3RHdZRFZRUUhEQWhUWVc0Z1NtOXpaVEVZTUJZR0ExVUVDZ3dQVTNsdVlYQjBhV056TENCSmJtTXVNUXd3Q2dZRFZRUUxEQU5RUTBReEZUQVRCZ05WQkFNTURGTjVibUZ3ZEdsamN5QkRRVEVyTUNrR0NTcUdTSWIzRFFFSkFSWWNZMlZ5ZEMxaGRYUm9iM0pwZEhsQWMzbHVZWEIwYVdOekxtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTFBRbTUwRGdCOTgwcmRJSXA2SFlObytuZlFlVWhQc200czc4TlJPZUxNT2hldUtuOFp4UFhESEQrU0txQkhBblhOYnRvUThnNGNoK3FpUytzV3ZKdU9qVURCT01CMEdBMVVkRGdRV0JCUkRuV28yNEMyUHBFU3pWYkpQejFaRlRlYlNKekFmQmdOVkhTTUVHREFXZ0JSRG5XbzI0QzJQcEVTelZiSlB6MVpGVGViU0p6QU1CZ05WSFJNRUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUVTa2s3Nmt0Rm5EQkR5U2ViSkh0dzNUY0pJWFRmTm81Tmc0QWo4OEJJN1JBaUJ0RWI1b3h1aThTenNVWjZ3Y1FRam41YUI1bmQyYU5KQmhaSytpRkhIR3hnPT0iXSwiaWNvbiI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBNGtBQUFERENBWUFBQUF2QlZUQ0FBQUFDWEJJV1hNQUFDNGpBQUF1SXdGNHBUOTJBQUFnQUVsRVFWUjRuTzNkVFhJYk9iYUc0ZVNObXF0NkJWS3RRT29WbUY2QlZWTk9KSy9BcklqTHNlVXhCNVpYWUdsd09TMTVCU1d0b0tRVmxMU0N0bGJBRzNCL2FhZVpKTVdmYzVBQThuMGlGTjBtWFJaL01nRWM0T0JnVVAzdi8vMWFWZFZKWmU5K1BoMTlkZmgzb3hwTVprZFZWUjE1Lzg3NWRIVGJlaEFBQUFBQUl2dEZBZUpmRHIvMmRWVlZXUWMrQ2hEdnE2bzZhRDFwNnpyM3p3b0FBQUJBR2Y2SDczRzV3V1FXVmxodklnU0lEL1BwNkx6MUtBQUFBQUIwZ0NCeHRjdXFxbzVYUG12anVhcXFZYWZ2RWdBQUFBQWFDQktYR0V4bTQ2cXF6dHJQbVBvV0lKYXdieE1BQUFCQU9YN2h1L3paWURJTEszc2ZXMC9ZRzgrbm8vdk8zaWdBK0JUbktxSm9HVkFLYloreExGRElQUTcwQUVGaWd3WkxONjBuN0gyWVQwZFgzYnhMQVBoSjJCUDkzdkFqeWI1b0dWQVk2d0tGM09OQUQ1QnVLaEVMMVh5WlQwY1hyVWNCQUFBQUlBRUVpVC9FS0ZUem9GbDdBQUFBQUVnU1FXTGNRalduNVBFREFJQ0lxS0lPWUd1OUR4SUhrOWxKcEVJMW9aTHBZK3RSQUFBQUFFaElyNE5FN1VPTXNmbjZMWlZNQVFBQUFPU2c3eXVKdHhFSzFWeFR5UlFBQUFCQUxub2JKQTRtczZzSWhXcnU1dE1SaFdvQUFBQUFaS09YUWVKZ01qdVBVS2ptS1JTcWFUMEtBQUFBQUFuclhaQ29RaldmVzAvWW9wSXBBQUFBZ0N6MUtraU1XS2ptbkVJMUFBQUFBSExVdDVYRUdJVnEvcGhQUnpldFJ3RUFBQUFnQTcwSkVpTVZxZ21WVEM5Ymp3SUFBQUJBSm5vUkpFWXFWUE5RVmRXNDlTZ0FBQUFBWktUNElERmlvWm9oaFdvQUFBQUE1SzdvSURGU29Sb0NSQUFBQUFERktIMGxNVWFobWpHVlRBRUFBQUNVNHBkU3Y4bEloV28remFlanE5YWpBSkNQeDZxcTdneGZMVmtWQUFCa3JzZ2dNVktobWkvejZZaENOUUN5cG9rdUpyc0FBTUIzeGFXYlJpcFVFeXFabnJjZUJRQUFBSURNRlJVa1JpeFVjMHFoR2dBQUFBQWxLbTBsOFNaQ29ab1FJRDYySGdVQUFBQ0FBaFFUSkE0bXM4dXFxbDYxbnJEMWRqNGRlYTlVQWdBQUFFQm5pZ2dTVmFqbVhlc0pXOWRVTWdVQUFBQlF1dXlEUkJXcXVXdzlZZXR1UGgxUnFBWUFBQUJBOGJJT0VsV294bnNmNGxQWWg5aDZGQUFBQUFBS2xQdEtZZ2dRRDF1UDJxR1NLUUFBQUlCZXlmWXcvVWlGYXM3bjA5Rjk2MUdnUTRQSjdLaXFxcU1OWHNFOUV4eUFyOEZrTnR6Z0YzeWxMOEUybENrVnR0UFUvMXU3M2FHQTNqWi9QL1F0WjYxSGYzYSs0WFcvay9sMGRPSDFiNlBmR0Q5dEo4c2dNVktobWovbTA5Rk42OUdlV25kalVmSFZUbU5nVUE4TzZvNzRaSmUwNnNGa1Z2L2Z1ekJRRFExZi9jTlJMaTlyZkIrYmVPUXpMWXYydkIvcEdxamJ3SEJOSEcvN1JodjNZdGpDOEtqNzhGSDNJbTNvRGhidXoxWDM2cU4rcXBRSGZ1cGpUOVhtRDE5bzc3ZTZYblI5YmZUZktQaDdLVWg4NmZsOVpSOGtMZ1RScXdMcWUvWExqS09NNkhNL2FyVGJ2K3IvYjUxMXVEQitxblFQMVcxMmtwTis2ck9HQytQSGF0ZitabEQ5Ny8rRmYrU3YxalA3ZSsxeDBlc0R1SDJoQWQzWGRkOEsxVFE2MitZTnR1Mk45ZHhvOU83MVBURWJzMGJqaGg3cTgvZE1uMTcwck8vb1JyUFR2UXh3R2hNZ2k1M0xQbTBNUVhsbTFBWTI3MFh2VEpWRkQvWDl5SUN4VGZmcHNER0p0dXYzODl6c245VDJkZEpINlpvNzE4K21FdzhmUEZmYU5NajJHQk51YkQ0ZERicjgvZHRRSDc3NHMyL2YwZXczeUVCWW9URitxai8vclNmdjlsQ1BuK28ydTdQK1hlM0lXTzNJSm1QSThOckRhUTJYTDczdXJJSkVmUkQzemdQcDBGRVAreERZRENhejVxeWw1ODMxMUxpUmVyMDZxMnU0L3R4UG5TYzd0dldnU3NFM0pWLy9qY0ZtL1JNck1IOXFkQ3JKQk9XRHlTd01PTiszbnRpZHl3U2hCdzB5emlPMGdkdDYxdVROVlo4RFJ2VlJweEh1MHp0OTNsRUdlNDFCM1hpSFBvQWdzVU1kOU9HTW54b2l0Z25iZWxEZ0ZUVmdIRXhtWTYyOE42L0Q1OFpFUXoyV0c2NVkrRm5ibnVRV0pONDZ6KzZHRC9hbzhBRnlmWU4xRmFEMGN2Q2pGT253bWI5cFBabWUranU2S0dYMWE4Y1plMjhQalh1aHkxbklYZ1dKbWlRWTYzNU1hWkN4eXBQdXhWNmMwOXY0ZnM0NzZxTythSWJkNVJwZU1hamJ4dHBCbmNIckkwaGNRbU9uODQ3NzhMNk9uN29ldDI3cjJ2czcwcGptY2lIMSsxcHQxOHJWNThiRWFMTjlYYms0bGsyUXFFSTFudnNRbi9VaHJmeHdjN1hEVW5Rc1JROStFaGpzV0xqT09WalVnT2M4d2g2YWZkV3prRmZMR21wUGZRa1NOVkV6VG16RmNCdWx0NWREQlUreDAzeFhNZjI4MVE5ZkdRUVpCSW1SSkR4MnFuclFIcVQ4Mlc4cVpDaU1yZU1LZlRhM2piN3NZZHRDbTB2YW95ZWQ1dkRUdjVGRmtLak8vWFByQ1Z0dlM3dlo5a3hwaWFtb3hrNmQ3RGlUVmNOTnVRNU1yQ1U0NE54VTlGWGNrb1BFUWdZYWk3WWVFS1JNTTlzeHFwWHY2a21mOTg3WHRON2psZEVFQlVHaXM0ekdUbFdCNDZjajlkMnBUK3h1NDVPK0k1TUo0SVdzeXIxcXFDaXo0YVArMkZwUlRENUlqRlNvNXROOE9ocTNIczJZQm40NU5IQk5ENXAxeVRLTklvUEJ6cjZTSDV5cWc3a3E1RHVJc29wYmFwQ1lhUnU0amF3bWJoWnBJSDRSb1ZLNWxTOXEvN1lhNkRtTVlRZ1NIV1hjYnV3OW1kR2xRb1BEcHZyYzliMituNFdzeXU4QjRyb1RDR1JsRWNtRmhiaTcrWFQwdlNwcTBvZnBxeE81Y2I1WnY1UVVJSVlHZmpDWlBXclFsMXNqRjJaWi85Sk5rSTF3blE0bXN4Q1kvRjF3Z0ZqcCsvbGJEVXB5TkNOMlg5QjNFRHJMZjhLMXBiWVFHd2o3VnpKdUE3ZnhmakNaM2VkNGJTZ1F1YzhvUUt5VUdmSzR6Zm1Ba2NZd01KRDUyS2xTcGtRWVA5M2sxQ1pvL0JTQ3czOEtEaEFyWFZOLzZiM3VSQk5PZFp2NVpXRUY4VnlUTzZ0Ky9qT1l6T2E2UG41cXc3UUsvVUYvZktXeDFEZEpCNGxxWEwwcm1SWngxSVZ1dEV0ZEhMbW5WYjNUNEdmWm1WZEowYzMwV0hqanR1aXpndUlrNk5xL1ZjcEVpWU94c3pYbmJFSENUS3F1Z3o4TFNpMTl5YkVDbCtUYnlwb0dTYm4yVTlzTzlMekhNTmhUWVdPbnFqR1pjZHA2SmpGNmpmZkdtU3lwZTcvSHhHKzlnUEs4Uit6eVJtM1lULys5c2hNZTlNZUwrdlVsR3lUcXB2V3VaTHAxNmtpS0d1a3NPYzNLdmlRTWZtNjNtYldOcVRFZ0xUVXdlY2xaQ29HaXJ2MlNWZzlYNGF5c05RcGNSZDdHZ2RyS3BBTkZEY1p2Q2hrUXZuK3AvVk1nMmNmck1SdU4vcU9rc1ZPbE51SFBsQ1p6bXhwdFFaOG05SnJPMUdadkhDanFXcTNiay9FTHNVdElHUjNVUDFWVi9hdXFxdDlWU0tlMkxHT3ZYa0U4VUNYWk5JTkVSYmplTjIycmlrK09OQk56bTNIRnZuVU9sczE0ZEszbkE5S21UZ1BGeHVSSThaME1CL0V2eDJUTmQwa0hpbzFxZkNVVjgxclovdWw3Nk5QcVNIWTByaWk5L3poTExTVmRFLytQaGJVRnV6amVNbENzeDhIUDJ4WXBDZ0dsenRnODFRSlpjTEFrN2ZTMnNacjQ3ZmNsRnlRMmluOTRlbHZDR1ROcTVQN3N3ZURvY3dxQlltUDJxKzhEMHFhekx2YVFSaXBvbFlxN1BGNW1YSTFVcGI1UDF0VHFRSEZkOFlMb2xwUnJMOG1xUURHcmZmVjlvejdyYzAvNmozRGZKYkY5cDVIV3kvanB2NDYzYUN2cWdPNm05Y3lHdFByNDB1SlkzWjU5NjFlVENoSWI1M1o0WGtEWEpaUUtqblFzU0VvNkRSUWJRVW5mWjcrV2VSZnp1K2xoTVFoU1RSY29sYThQRTJUYk90aG5FR0d0OEFDeGR0WXM5S0RaZVNZdUVxV2d2clQwMHBjY2RwbHAwS2diMExmUGZSTm5HKzV4cnR2UWZSZTRYbHE1L0Q3ZUNHMVphaXVKVnVjSXJmS3d6M2tpcWVoaGdGajczTVZtYkhYNnBROTA5blVaY1FXamI4VWdTRFZ0MENDUFZMN1ZqaE9xRU8zZHA2ZmlZMk1BbnUyeEpLVlQyOUduSW5OTm5hU2s5Nmh1d0Q3ZXI2dS9zWkNTdXZONFFMRkQzUjQvTDh1b1hIenNsOWEvMGhGRjBwNnJORThsVkFqc2NZQllDMVdoaHJIMmsvSjViK3hBQTBMWGU2eW54U0JZU2V6UHFwU1ZzTHAvczJ3UUVJc0MxVDVsWHR5d2lwaXVuZ2VJdFRwUWpES0c2dG0ya0gyRnNlM0ppb0kwemNCKzJmT0xqcGFzVHA0MkE4UU54Mm9uU1FTSldoM3luQm11RDdITXVwS3BPcUF1QTVibkpRUFdrOGdOd0lFNjQxVTNreGxkbDZrSGlBOUxHbzNZMzBrdG5LOXo3cFhPclpYS0xzODBYWGI5VjByZmNBdGNTdGcvYlNUMUFISFo5ZUY2YmJ6ZzZvWERsZDJvN1l5Wld2YWs2K05SMzBIZEpwN29PeGhHYUJjUGwzei9TRUJDQVdMZFgzYzVrUkJsREtYK092VUFNYVh4MDZIR055OWxJbXhTNk9ad1RVeDF0MDA4MUhtUXFKa0c3ejJDNTdsWE10WG5GSE92eVpOK1gvamM3bC82L1BUNlR0UVpuMGJvaksvcUVyMk9VcWtVK0tEdjRWR043dGROcnVmR2QzS3E3eVZHdzNlcEZReVB6dWNpWXVQOXNIRDliNVRpb2MvOFNKLzdpY0huL3RCNnBMOVNDQkRyUUxBT1NCNTFmYXk5M3JVSzJyd1hZN3lYd3pDYnJQT3ZvbW5VRnZEMnBLSVBOMnZ1ejU4bVdCUzhuam9HREt5WUpFWXJLckVEeEhyODlLMmRXTlZmUng0M05SM3F0WG1PY1k0U3VSK2U2bjU4eC9GVHpPL20yOUU2UzlxemJlT1h4UW5MWnVEN1N0Zm1KaXVKOTUwR2laRUsxWHhRNmRkc1JmcWNLbDFZNGZkY0xybEkxOUpOZDE4UERpSjB4bS9DNzhqOXUxMmgyY0hjN2hwd05iOFRYVU9uQ3JRODkvTWRiRGdidGhYTlNucDM5SnNNT3RkcWZPYmZyMHU5OXVHT3dUcjdFYnYzcFhFdjdqVFpxSHY0dGc1YU5BQVpSN2lteHlIdE0zSVd6YVZ6WC9Xc2M4SzJEa1RWWDl3b2NPZ2llRUJFMmk2eWFrWEYydGJqcHhYanBuR2tsY1pqdFExZFp1ZDRlRmIvZTJNMWZxcCtYRXZuRWI2Ymk4V0Q4c043R0V4bTlSODN5UTRKRTVjL0JZRWFoOXhvZ25KbDF0ZmludFd1VnhLOU43VmZ4NTVGZFhMaC9EbUZ3ZkhGc2d0bVZ3dWRzZGZlbEJEOEhPV2VSaXgxQjNQbHNlcXR6K2hLbjluWWVWWE9ZMkRxZVIrYlgvOU5HakJjN1RpQlF2cGFOKzcwZmJtc2l1c2VQMWY3ZU9VNDhEalFnQ05LSVJ0dGlmQU12SzQzT0VqNlJib256NVdHZU5YVEE3MkxGdWs0dFVwOTk2V0N3MzJ2eTV2RzN0WVkrKy9EM3VYYkFpYmI2OER3eW10N2hzWUhWd29XUFNmQ3pwUUJzampSOEtBNFlMaExwa2I0OXpUMitFY1BuYTc0ZDRhTi8rYTJzeUF4UXFHYWg0NzNMNWxRWStHMXQrTlpEWnZiQUZ3WCtxbmVoM1ZuZktDR05PZnYyVFZBV1dZK0hWM3F2TWNicDhtSGd6VU4wTllhcTZBZVB1bnpqemJSMEJnSWpQVyt4bXUrQi9ZanhuV3Q2eUhLQ3E1K3oxRFh3c2ZXWDdBeGpuaHVuK2Rremx2cmRqSU1naHBiWGxJc3N0Tk1HN3RkK04rTmFSVmgwOHJ1bTZ4VVhHZVE1UkFqKzhxbC8xQ2dNOVNnM3Z0OTVEelpYbWYvWE1WNi9hRU5hb3lmdklMNDhaSnhiYjBuZitleGtBTEZPdGhjMWQ3VjdjUzM4NWs3Q1JJakZhb1pGckxDNUJVODNHbXZacXpCa0Zkbi9FNnJWcm1sNVVVUERwdlVXSGdlN1hGaGVPMTY3UWN3SDNSdVkyRjFkNmhPWWZIZUlOMDBqcWpCNFNKTjNIeDFLcFIxR0NNMTM3R3laOTJmdTZ5cTZ6NDhUYVM0aVVtcTNCSkh4bU11dHhVYkM2cXM2NTE5ZGU3OUdZUjd0bEdQd3V2OTFKWEpveDh2dG9kbnRkZWRIUFdqKzNMbzJHYWNMd2tTNi9NOUQxYWxpbTVvWlp1aU5yeSt6cjc5KzlIUFNZeFVxS2FJQUZHcnJSNXBNSjlDdm5Mc0FWSDRUdWJUMGFrR1pKWnlTeWtPczQ4blhRWW9WYU9oY3lxT2NtaDRIcE5INTlWcGdMZ29ERFowYi96V3VEK2VNNXo4eUUwWTdMME81K2QyL1ZucmVuemJlc0pHalBPQnZkcmgweGlGNTNTR3NuWGZ0S2tudFVtLzZscjBLdjVsSXZFQTBUUDdxdElFKzBtc3o2RE9ObkMrTnQ5MGNRYjFqc0llOGFPdUFzUW14emJqUUdtdDM2a052Tk9mTHhiT1RyUlN0K0gxWkZYY0lERlNBWmEzdVZjeXJYNThWaDVwbEcrNzNxanNjR09kUlR6SWZSL1BHcER1dmFmR1NpTlFmSGI0NTYwR3B0Wm5MMzVLS1VCc0NnTUMzUit2STZZSTl0VjF6TUhlSm5SZGZuRDRwOTg0RFNxK2NWeEZmQnZ6KzlHOUY3dWljR2lQamxKdGt6TGsyVzVlYTRJOWF2K3RDWGJ2U1l4THp6YkNRQmlqL0I0bVV4T2JRQms3dFJuTGd2WTZpRHUwdU02YkIvaHJ5MFBkaG45UG9ZNjlrdWhkcUNiWndkOE9QRGJHSnJONm9nYnZTK3VKM2VXd21qaE1jUVpXallISFNzT3lSbTRyQ3Y0dDc0UG5ISzRWclN5V1VIUXJWViswWXBQY2FvMis5N3ZXRS91em5teHA4bWcvcmp2cXIwNmRKczJXNlh6U3RpUWE2SHFOTWE4MWJ1bU1jNkI0bUhoOWgvTVVDK3c0anA5YTI3STBmdnlrUDU3cGVxK2ZDNEhkUUQ4cjIzcE5jdFIvcjY2MmZkN1lFMy9YWEtXTkZpUkdLRlR6cFpURzFxbmNmMUxwZFhLdU5Cc0xwNG5QZ2xVcHIzQ3I4YlVlbUI0YXJQQmFuK01VK3pnQXBDbjFiQk9QdnN3bG5VenRyblYvOWRUVmdGWHBmVEVtYVA1ZzlkQ09ya092NzYzekFMR20xK0V4aVZTcE1ubXE0NmlVMDYvdlBUSkFscVVBSzg2cFZ5NC9LcmJhNTNlY04vYkNQeTMyRTFHQ3hBaUZhaDRpN2JtSXhicHo3R3BHZHEyNllNQzZ2N09GZzhLdWdTNTRkTEFyWjdRMlpCMGtsbml1SmdxalFZZjFpb0hYU3FKSDhCbTE0dkFpemFSN0RjU3J4ZGw2bUJnN2JXVzZTeVZBYkRnMW5HQnZPaWpoVklDT1hEcGtJS3dhL3pSclNZUUQrRysyblpBUGt3RXE4RlFIaU0vYS8vMVR1K3NlSkVZb1ZQT3NaZWdpVmdjMGkyUFpJRDBrMk1COXA4SFFwOVlUdXlGSTNJTlNENndIUnA0cGJsc3JZYjh5ZXNNNmlEaDBXaVd3RGhLZkVwblU5RnhOSkpYY2tHTU5oOWJLU2dxTUo5Z1hwYnlhbUt4R3RYSkxTOGRQalZvUzlYZ3RaR25laDZEdnBXQXhQSy9WeDhkR2dhY0g3Yzl2alk5Y2o4Q0lWS2dtU3VXemlLekwvZWNRT0Yzb2RlNzd2by9EcEFTQndGNnNEL1plTlJPMnFhV041STVpRjZRQWRoYmFzY2FaVmxaT0hNN2V0SjRJU2lLQTByRk5kdzRGZVI1U3JnNmFLYTlWeE5iS1NpclVQbnh3eU5LcnM3Slk2ZDdlcFhGbDNaVnRUK01Zam92RzlmOU94OEk5YVV0RmN5eDhwUFovc1Q5WmU5YW45MHFpZDZHYXFKWFBJckdjRGZ1UVE4QmtQQU9UMDFrL0tiSk94L1M4LzdmRjdDaHlFMlZtZWxlcWptYzVPRTlsRmJIbThWcEllYmZuc1lxWS9QaEpSYTQ4MGs1Sk9kMkI5ak9iVGthL3RES29hK0JFd1Y2ZDducW8xY1gzaloremhmRlkyTTd3MjB2VjlqMkR4R1VIUTF0S2NwL2RQcFNhYXpXb2ZzNXNKc2pxdFJJazdrR05oV1hWMmNyd3ZNUjllWnc1Q25peW5nUmRPK0RZUWRGN2hqWEdzTjVueENxaUlSWGVzRjVGZk1xb3VyUkh0dGpoc3FJcDJJaDFHL1ppbTYyanMwS3c5NnVPei9xZ2NkemR3azk0L1BlcXF2NjE2ZG5BbnVtbW5nRmkwdnZzOW1ENW5yS3E0aGd1VnFQVW5wQnllc1FoNUh1NU43NS9rMW5CQ3gxZmltVzBnV1dVVXZac09BaTJEaEt0VTAxVG5QaTljYWplQ2pzZVk4RnN4cGVPYWRHbnJIcnY1Tlk0QlhpNHpjU1NzaXZOSnFKaW41Tm9wZFFaRHN2M2xXTSt1VldEbEZTeGxBeFp6M1Nuc3BKWXNkS01ERm1tdkZrSGlaYi8zbE9pNlgycy9DVktxWGpXd2RGZGh0dVlQRlk5enloZ3M3M1N0c0RsR2lRV1Z4bE1qWjFWT3R4MXB0VmVDUkxUWUQxUTI2ZWpzVjRSUHRNK0tpQVhsb01PNjVScnl6M0hxUTZ1Q0JMVDVYTDhTdXVSeERsVkpxK1lWTjJaNVQ3UlRpZlpjdzBTdzBDdnRJMjFsamRqbHAyYVVrUXQ5bitrdEhLVm5jUW1HRHpTaG0rWUlVVkdra3lkMy9aY3JnMGtXU1JFL1pMbG9JKzJ4NDUxV21pT3E0ZzFqK0NXSUhFM2xtMTJwKzFGcmtGaThMR3dGUUhMOTVKekhybkZRQ0dsaXBxNXNweVYzT2ZhOWhnNGh2MWR0d2tWMUFIV1NYVi9kUytDUkxIOERtaDNER2lTd3JxdnovYllCd1czMXBWT3liclpUVEUxTVR5RFJLc0QwdGNwYVVYQTZtWjh5RFRWdEdZeWkwZEtZVEc4R3R0akJZck1sS0pYRW00YlV3NFNTVGxOajNYYi9WUkFVVFBySVBlQXNkUk9DQkkzY0JNaFVEd29vZkhXakpoVjlUcXFldjRYczdVRlVDRUw2eEwwdFhEUC9UbVl6RzdwQ0pHd1ZDZjlUTytaekNjM0VWOGZLdXR1eXlQSXBXL3NNZGQwMDNCdWgvWEJra3VFSXc5eXY3a3RBNXJrRDg5L2dWWFFiNTBLaGU1NHorNkc2bmgvRVN3aVJha2Y2TjBUbHBPdnRERTJDQklYZUJ6bXp2WGF1ZUlMMTV3NnJnVFV6blNnYXE1WTliTEhaMXFPV0NsQWRiQVl6dXdjT3hUbUFMQ2M5MlR5dnNqUVNZajJrMXNlb1A5UTBObksxc0V1WTZsdVdWN25XL004VFA4YkhaSWVBcmcvVzAvYStqeVl6TzR6blhXMXZBblBNMThOc2RwalNnVzVRb1I5SW9QSjdNbWhmUDhxNGZkOFZIR3NPM1c2dHdVTklvRFVrR3FLYlZnSExpWHRPYlYrTDJGZjRoSDlYeis1QjRuVmowRmUySi80cnZXa3JWdGR6TGwxT0pZQnpXSEV3WFRLcUhCYWxoQ292ZS9nSGIycUQyc2VUR1lQZWgwM2RKaUFLU2Ixc0EzcklESDNnalhmaFlXU3dXVDJiTHdDZGNKcWVqOUZPd0lqMHY3RVhBdlp2R285QXFEcE1rTGEra3VPdGNMNGoxSlNMemxHQXpDUitxUWU5M2xhVEwrUGpNOUdYTVg2L1hEOTkxVHNjeEpqN0U4c29aQU5ETENuckJ6S0R2QTRMSGhYaDhxTStIc3dtWDBOYlE3SGFhQm4rcFFpYXJuU1NXcnQvaXlEbHRUM3crN0NldHNWWTZtZWlob2tLa1VyUm9HWmJBclpzQkxoaW9hdElQUHA2Tkw0a0g4cklZUGhUTWRwRURDaUwwd0hvb2xQNmxrR2lWU3IzWjlsS21XSjM0ZjFTaUpqcVo2S3ZaSlk2YkRTR0FmdGY4NGtBR012QnJDNTh3VFNUdGRwQm96endXUjJrM25sWlNDV2xBZWlUT1ltd3FFd1g0bDc3YXpmRTlkL1QwVVBFdVVpMGhKL0tHUkRFQVlVSW1JMmdwVTNtckNxVnhqcGJGRUs2NEZveWxXNUxlOWJDb0NrcGJUOWlKVkRZYlZPajJGQWR6b0pFclcvS01hS1FLNkZiQUNzb0d5RXQ4dWZUVmE5d3ZnM2gvYWpCQTREMFNRblVCek81Q05JM0ErcGo1c3BjYThsSXV0cUpiSFNlWWJqMWhQMlVpOWt3MkFSMk5KOE9ycktNRkNzMVlmMkV5d2lkNVlEMFZUdkJldlh4WjdFL1pnR2lRVldOcTJaRmtpaXIrcW56b0xFNnNkQTc3cjFoTDFzQ3RrQTJFem1nV0sxRUN3eU80NGNXYTZLSFNSYThNbHljUHlVNFRuT3lCUFhHZmJXYVpBb01jNVByRElxWkFOZ1F3b1VmMCs4bU0xTFh1bnN4WlNPK0FBMlliMHFsbFNRcUpvR2IxcFA3STVWUk1UQ3RZYTlkUjRrUnR5ZldGSElCaWlQOWlnT0M5aUQ4WDR3bWQyenFvaU1XS2ZxblNiV1IxdG5JRkVqSVMzczJ3UFdTR0VsTWViK3hMRDUvS2IxS0lDc2hUWmtQaDJGVElFUG1iK1Y0ekFEVE5ZRGN1Q3duK3Nnc2VyRjF1TVNnc1Mwa0pJSnJKRkVrRmpGM1ovNGFqQ1pYYlllN1E2ZEJtQmtQaDJGbE0xL0ozcm8vcVlPVkFXVmZkVEl3UmZqMXpoT1lUVlI5OTloNjRuZFBXbENIQUN5a0V5UUtMSDJKNzVqQUFhVVNhdUtRKzFWZk1yNFRYNm1uVUlHckxOekRpTmxGcTJrSU5WNmp6QlpUQUN5a2xTUUdIbC80aVVwWFVDNXdsN0YrWFIwcEFxb3VhNHNFaWdpZFI3Qno3amp2YmtYeHF1SVFjcEhjZlhWcTc1L0FNQTZ2Nng1cmhOaEZXQXdtWVZaeE0vT3YvL2Ivc1FRS0haY2t0cjZkOStSd3ZvZGh4YWpUbVcvMHFUUVdCVVVMUS9IOWhZbXRPNUpWVU9LUXY4NW1NeStHRmNCcmVzSFJKL0kxWGx3NzFwUDdJZFVVOFJHQVRUc0xia2dzZEtnVGczMVdldEpXNGZxaURvN0pGUkJjZXZ4UGR4cVh4YUFoWHN0WkNvb2xleFVQNVlEV3krcFRHZ0JxMXc1M0V2SGc4bnNhajRkUlZ0SlY5dmdzVEthVWgwRTlBTkJJdmFXMnA3RXBsajdFMU1vWkpQekdXOUFWa0tnRlNhaTV0TlJDQkwvcFhSVTYrSWIxZzRaYUNKVk9vYkdZLy92V2F4MGF3V0l0dzVaQnMra21wb3luU2pUZ2dSZXhrcDREeVViSkViZW45aDFJUnR1UHFBRG1RV01ad3hva0RDdkRCYjNmYm1OQVBHNDllVCtMc2tBTU1WNGFUT20reTI1aHZzcDVaWEVtT2NuVmgwWHNySGNPNWZTUWNSQU5qSUpHRmxOUkpLMDk5ZXJtbkFJRkYxVzQ5VHZld1dJejl5enlTdHU0aTJGSTJSUWhxU0R4Q3J1K1luMXZwOHViaTdMSUpHS3JjQ2VFZzRZd3o2dDA5YWpRQm84OThPSGxmUjd5OGxjRmNuekNoQXJWaEh0emFjajY4SjhKWTZack45VHp1Y09Zdy9KQjRrU2EzL2lZVWRuR1ZrMmVteFdCZ3l0Q0JoanRFZXJkSHFHSExDS0puVTlCNVFobVBzN3JDcnVjMFJHU05zT0FXZFZWUjhkS3gwL1VVUXVDd1NKd0FwWkJJbVI5eWQyVWNqR01zZitrRlFEd0VjallBeWQ4RzlWVlgzcW9QRFVxNDdQa0FQV2lkRlhoOHJuL3d3bXM1RDljN3BKbnhmdW1iQnlPSmpNUXViT1g0NnJoelhPTi9Wak9SRnhXR0I3YWgwa2NxeGFUeVY1Qk1ZeUVjOVByRlRJNWw2em91NTB6dFNEWWFjMTdHaEZGT2lOK1hUMHFGVzlzUXByZUJ6QXZjb3BlNTJRb25CZkRDYXpDNjNTZVh0VEg3MmhQdlJ4WWRMMVZ3MllUeUtmamZySklTMFNQOXdiRjJZWkZsYUIxbnFmSldkTzkxUXU2YWJmUk55ZldIVlF5TVp5TlpFS2lFQkVXbDA4VWlwcWpKVkZWaW1RclBsMGRObkJIdDVqQll6dkd6L3ZGRXpFREJBZjV0TVJLZUcrcklPV1l2WjVhMVhVZXJLU0lMR25zZ29TSmRiK3hOaUZiQ3hYL2loc0FYUkFFMWxIU2tQMWRFeGFPUkozM3ZIZTNTNDhNMGtiaGZVcWJVbmZtZmw3WVZXOHY3SUxFaHY3RTJPSVdjakc4aVlzTWNjZXlJTDJMWWJKck4rZFZ4VXBUb0JrcWE4ZWRyQm50eXZmQWtTcW1mclQ4V2lXRGpvK0s5dVM5U0pCM3laNjBKRGpTbUxkUVB6UmVzTEhLKzJ2OEg1UFg0MXZSdEpkZ0E3TnA2TWI1MEV5UVNLUzFxTkFzUTRRT2VnOUh1c3F1dGxuWUNtNzVFM3JpZjJ3aXRoaldRYUpWZnc5RCs4am5VMW11WEdhUFV0QXh6Um85TG9YU1RkRjhuUVBEQXRla1NCQTdJWjFsdGViQWpLd1BNYXBCSWs5bG0yUUtHSHc5ZFI2MU1kVmhFSTJsbzFlU2VrVFFMYTBvdWd4b2NWS0lySlFjS0JJZ05nZGo2MUF1V2RnZWJ4K2dzUWV5enBJVkNwTHJCU0JBd1dLYnJQM0txbHYyWWx5a0MrUUJvL09tNVZFNU9haW9OVFQwRmNmRVNCMlErTWw2MFdDODF3TGdnMG1zNkhEMlo5MzdMSHR0OXhYRW1QdlR6eU9jSmFPNWRsbmg2d21BdDF6bUFBQ3NxQkQ3RU8vK1orcXF2Nk1mQnlGbDNBTzRna0Q2TTVacnlZZVpMeWE2REhXNDd6dG5zcytTS3ppNzA5ODQxekk1c1o0cHZXU1V2bEFFdWh3MFJ1aDN4bE1acUZ2L3FlcXFyTkMzbmRZdVhyTk9ZakpzSnhVcjQxejI1dW8xK3R4ajlGbjlWd1JRYUxFM0ovb1ZzaEdNNU9tZXhOSk93V1N3S29EZWtINzkrOTFtSDBKd3NUdGgvbDBkTVNaY2QrLzM4NDVaV2djT0FXZm5qeGU3NTArWC9SWU1VRmk1UDJKbFhNaEcrdWc3cDN5MVFGMGg3MUxLSjc2eFZ1ZE01eTdiOEdoOWg3bVBObHEzZmFrdE5MbUVTQzl5V1hNcE5kcGZleEZGV0ZyRlRKUTBrcGk3UDJKYm9Wc05IdHozWHBpUDY1RmR3Qzh5SHJRMGZzVkRhU2xFU0RtdnUvd1NXT0piOEZoN25zUEhWNS9NcFdWNTlQUmxWTXhwRnpHVEI1QjhqT3BwcWhLQ3hLcitQc1RQUXZaV1ArN2g5ejBRS2R5UDRNTFdFbjdvbklPRUVOZytLbXFxbjhycmZTeXNNSTBsdHR4VWp0NDNpTlFPa3c5N1ZUMU1hd3JtZ1pYRkdWQ1ZXS1FLREgzSjdvVXN0RytCK3RnOTVXcXpBR0l6M3BneFVvaVVuSmpIQ0NHdldadnE2cjZYY0hiWGV0djdQL3ZYMnZGc0E0TXh3VWZhVTNnZGJnQUFBLzRTVVJCVkdHNXYrdzRzZUl1bDA2cmlXZXBWb2pYcXYzNzFoTTJjdHVUQ1NlL2xQakJoaGtRRlpiNXUvV2tqMURJNWw2SFpsc2FPK1NhaDBZdmZFWWNqUUZFb29HRzlRb0xleHlSQk9NVmpUREJlNzVRSU9aNzM2b1V3RHJkY1ZrSzk1Rit2aTY1UjhLLytiV25aeHVHOS82cTllanV6bE1waXFjeDM2VlQwUFI1TUprOXBsU3dTUGVBVjJiWU5RVnJVQ3N5U0t5MFAzRXdtWVVad28rdEozMkUvUFdoWmVjVGJ0VEJaSGJ0VU5xWVFCR0lSQjI2OVdEcWlYUWdwRURYdDlXUkVDRkFYSHYrb0o2ckIreXNwbS91MWppSVNpWklsRXRkaHg3cHpqZlc0N3M5M1RnV2hxSWFQcjRyTmQzMG04ajdFNzBLMll3ZDB5aElQUVg4WFRoMDZBeU9rUXJMZ1huMlJXSVNaaDNnSEthVWlxbnJ4aXZBQ2RmM2JRcEhmMmpjWnJraTNNUXFJbjVTZEpBb01mY25taGV5Y1c3NFFxQjRuOXZCc2JWVXptcENYR0Zna3NzMXEwR1V4MWx4RktGQ0txeFdFWjlWcVJJT05KYXczdGQ1bVZJRlVDME1XSitiV09zOFVGU0E2SEZvZnFYRkNLdDdHWVVvUGtqczRQeEU4MEkyYXZpc0cvZGFDR3p2dFljekN5SHRZekNaaFpXVXZ3a1UrMFVEa3M5VlZmMFRyb0ZVaXdwVVB3TEV6NjBuOXZmc3NQOFoySnI2RGF0VlJQYlkrck51Tnc0U1BFL1BzMCtvQThXby9VN285NXdEeElwVmZDelRoNVhFMk9jblZpcGtzMnhEL1Q3T25kSk9LelY4Znc0bXM1dVVWMmkwZ2hSU0lmNXFwRnN3ODlVdnpjbU1WM1ZSZ1RBeGs5SzFPNWpNeGs0QllrWGxPU1FraXdQSDhaMUhRUGRHN1YwU05ONzc0UGhhRHRUdlJGbEZiUnd0NHhrZ1BtZ3hBdmhKTDRMRUt2Nyt4RW9ibmMwR3Jjb1Q5NTY5ZXFOVnhZdFVVa2pDWjZqWDgxV0Q3c1c5WGRtc2dNTEVzdS83VUFVWi90RkVSMmVyaTdwZWI1MExacEdTaDFTUXlaRVJyUlI1aklNK0pyWS84Y0l4N2JUMlR1TWx0NGtTZmFiM1RtY2gxcDRqakMyUnFkNEVpUkp6ZitLQkFrV3pZRXNwWnRldEoyd2RhTUQ5cUpteTZLc3pTcTA0MTJEN0g3MmVWU2xOQnptbHltSjN1cGRlT2hMbWpXWjVRMG4wcTFqWGhxN1pDM1hvWGtVRktnb0xJREdXL1lQbmZZTWZ2RmFNUHF2TlRXV1A0cWxqOWxVdFRGRCtaWjJGMWRoUzgzbk4yTWZLUlUrUGhNRUdlaFVrZHJBLzhkaTZRZGF4RmQ0elpKVWFwbmZOdlYrZWpYL1lXeGhTVnRRdy9rZU40NmFEQm9MRWZ0am1lejVRZXM2ZnpZRFIraHBXWjM2bGEzYmRaSVlGQ2dzZ05hWlZlMVBlWTF3S25mZm5WZVBnVEt0cm5YK1BrYkt2YW04YW1TdzdqMGZVUjkwdWJLbnhkRTJhS2RZcDlwekVWVG80UC9GTUIrMWIzb2hEclZoNG5aT3o2RlZqLzllRDh1UER6K08yTTFDTmc1RHJBNCtIK3ZNK2cydUN4SDdZOVh1dUE4WnZlem9hMS9DOXJ1R05qNU5RYXRHSmZpeUxkbXlDd2dJb1hkaGFjTU4xN3U1Q2dZaUhRNDBWTGxRb0o3U3ZYME03MitqL2E2RTkvVDRtbUU5SHBwbExJZnNxOG5qdmpmWm9QamZlKy8ycWNaSldIK3UrWkJoeFRGZHBzWUZKUjZ6VnV5Q3gwdjVFemZiRVNtLzVxRURSNUd5ejBJSHE5ZDlHSHFSV1doMDlyc3Y2aDBQNWxjTDdVZ3Jja1dNRCtDM2xsSXFQNWRvdzFYUlR4ODA5SHJxR24xK29ycmp2Uk1hKzdwanhSWUtlak52MVExV1BIQklvK2xIQWR1YzhCanJVT0tFNVZsZ3JCRTNXNmZRYTc1MDRGMzVadERneFdTMzBNVjMzSitHMW5IS1A0U1Y5MjVQWUZDTmZ2Y202a00yOVpwNWl2b2RWRGh1cmphdCt2R2ZJV0Uwc20vZjNlN0RpdXExL3V1N1FTY05EaWp6Mnh4NXJUL3c0cFRQNENwUmltK0pTQkViYmRMenJPYnprSUtIK1pNamVkbXlpdDBGaUIvc1RQUXJacEJRb2RvMGdzV3g5L243cDBKR3FkYXZ2K3poUWl1Q2o5aE9mcDN3OFU0N1VwbmdlRmJFTHQzWStrVUN4YTNXQVNLRWFiS1NYNmFZMXBWeDhVTUdKR09wQ05tWXplTnBqT2V3bzlUUWxJZVgwaE1hdlBNYXBwcmw1eXpXTmhOM1c2WVJPRnRQMjZwUzk4UE5WSzVuTkNaUjdVdWcyRjQ2SzBOWVZ6eU1XdHVGNjdtWUlGSlg2R1RQMU5CVUVpTmhhcjRQRTZrY2pPWXk0UDlHOGtFMGpVTHhLcUxIdndqa2JzWXZVMTFYRUVDQnlKaUpTWnJMUGZndk5sTDJsTnRuNzlvTEYvY2wxUUhwZkYyQlovNTluWjZoQU80Vko1Z1B0UjNYN2pCVW8xc2RMOU1XVDlpQVNJR0lyZmQ2VDJCUjdmK0pINndOWUc2bW5YcVd0YzBES2FabjZ0aDh2dEVXL0V5QWlkVnExS3kyRmIzRi84anRsRy8ycE0vSG1ZYUpYYWJCakZVWEpscjdEbExhdHVLNG1Wdjk5ejZGdGZkMlRyVHFoaWlsWlZ0Z0pRV0kzK3hNcjYwSTJsZDdIZkRvS0RleW4xcFA5Y0poN2g0MmY2UjVadVdwUW9DZWxCRkdwRjdubzQyVEdzVklXdzc3SnZ3ZVRXYjEzTXN1SlNnVVFxV1RoUlBrTXRWcDVVdmpFK3FmNWRIUkNDaloyUlpBb2FqQmlidUkyTDJSVG0wOUhZODJTUGJXZUxCOVZJTXZTcDlYaE8yWjhrUnZudzlsemNhaWc4Yy9CWlBaVkFXTldFNVphWFh1YndPcmFjYXlxdHFGNGp5YldVeXZnczY4Nkc0WHROOWdMUVdKRDJKOFl1Yk9yQzltWWE4eVM5V2xWOFU0SDJLSWNmUmlBaGc3OWp6QllZY1lYbVRxbnl2WjNkYkdkc01KNG05UHFvZ0xGRkZKUDNWTk9telQyKzYyUXZpYWtmeCtSalFJTEJJbHRzZmNuaGtJMkxyTTlTait0VnhWTEhtaUhSdkcxQnRtbEZSWG90YkNxcHBuZTE0V1dMLytpMVVNT3lrZTJkSnpDQmQ5Z3l5dXRMajVhMXlId29reUdFKzFsNjByMHdMcXhxdmg3cGxsWWR4b0huVFBaQ0NzRWlRczYycDlvWHNpbUtRUk9hdnplRnBTQytxd1VrZC9VS0JJY0Zrelg4TGxtZS84bzREcXVPL1JUemtCRUNUVFIwZmR6NkZZNVZOR2IyeHpPZTFUQWROSmhHbVpuQVhWWWdadFBSMGNaalplZVZBbWJTWEtZSTBoY29vUDlpWlhYL3NTbWtFclNhUHh5WFZuOG9sejdYME9LQ0FQc2Z0SGc1VkxYOGIrVlRwMVR3UGlGVlc4VWJOenhDbFRxd3NyaXZWZjJrTFVPMHpBUHV3Nm1NeGd2M1drc2RFUWxiSGdoU0Z5aGcvMkpCN0hPbkZMak4yd01zbFBmUy9KRkRmVy90UEpDcmozcVZOUnhJMkQ4a09nQTlVbXJuNy9wK2lVNFJKRWF4eW4wdlpETk9nZktIcnFOVmFCbEg0MDB6TmZxaTJOSllpOW5ZN3owV3dLVGtrOTZEYjlwb3BHeEVGejEvakQ5RjV4R1BtUTJWUFc2VWxxZHUwYlo2N0UyMXcvMW5nOGp2ZDlWN2hRdzN6S2d4aVowTFllZkN3Mjhodm81NmVnSWpTKzZobTlZN1VhZjFJSGlZREs3MUJtRFdDNjBTNDg2UEQ3NWlzYnFpK3QwMlZNVkt6cHUvY1g5UERUNi9xUUNJTFhqOVhqcHBERmU4dTVmN2hwOUNaV3ZFZFV2R2xpOWR2aWwyVi9Nb2JOVFk1RDhIb0o5cVVHK1VRTjRwTUYxUGNnK2NRaVVuM1dOZk5YL2hwL0h4QnJCcTFpcnV3a0tuYUhWTEhmVVRmUWFwTjQwSzkzcVBxN3Y1YUgrMTJJeTVFa1RTZlUxZko5aFIyNTluWHU5Zjh0K0tyZkEzZks5UjdrK3d5ci9ZREs3VVVHYlBwMTF1bzBEQlY1WkJJclZqMkFwVEFCY05pYms2dmIxVi8wc0JvOVBTKzY1dXY5L1ZOK2ZUVi9ibUpUOFZuQk1OU1hxL3VWa3gvNmxIaE05TnZxU25NY2YxckZGVHYxcU1XUEh3WHcrYnowSUxMTlFYR2VUamVYM2l3RUNLNE5JaVNaRTZrbWdveGNtaEpyWDdpTXJoTUJtbEtseUZURXJKMGUva3o1WUZnWFJMNTJYZVU4MVVxU0tJQkVBQUxoUWtaWUxBc1FYaFpXa2JGWVVBWlNQSUJFQUFKaFM1c25sa3RSRHJQYXNjMVBKVWdEUU9ZSkVBQUJnUWlsMkZ4U3QyZG1EVmhSSlFRVFFLWTdBQUFBQWUxT0JxRnNDeEwwY0s4Z0dnRTZ4a2dnQUFQYmlYSnptSVZLVjVKU3FzTDZtMEJ1QUxuRk9JZ0FBMk5sZ01ndG41bjAyL2dTZnRLZnhLbmJxWmFQcWNmTjRoOWpuQjE5dVVCa1RBTnl3a2dnQUFIYmlFQ0NHNFBCaVBoMWR0Wjdwa1BNaDhxdThUZTF6QU5BZkJJa0FBR0JyeGdIaXM0TER5OVl6aVZIQUdQWU5uam0vc3FmNWRMVHU3RllBY0VPUUNBQUF0cUlpTlg4YmZXcGh6K0ZwYmtjL1JBb1dPV1FmUUNlb2Jnb0FBRGFtWXk2c2lxcGM2OGlIN000R0RLOTVQaDJGMWRUWFdnbjFjTjd0dXdUUVY2d2tBZ0NBalEwbXM3Q3k5Y2JnRTd0V2tKVzlSdURzc1YveFg1eWJDQ0EyVmhJQkFNQkd0QS9SSWtDOEt5VkFyUDY3cXZoVjFWQWZXay91N3pUMit3RUFna1FBQVBBaXJaWlpGSlo1TGpId2FRU0sxcW1uQklrQW9pTklCQUFBbXhnYkhaWS9MalY5VXUvTGVvVjAySG9FQUp5eEp4RUFBS3lsVmNSSGd5Q3hGOGM2RENhenNEL3hWZXVKM2YyV1kzRWZBUGxpSlJFQUFMekVhaFV4K1hNUWpWZ2Znczk1aVFDaUlrZ0VBQUF2c1VxaHRBNmVVbVY5dHVGSjZ4RUFjRVNRQ0FBQVZocE1acUZ3eXVHcTU3ZncwSmVqSFBRK0xTdWQvdHA2QkFBY0VTUUNBSUIxckFxbjNMY2VLUnRuR3dMSUZrRWlBQUJZeCtvSUJncXZBRUFtQ0JJQkFNQlNxbXBxa1dvS0FNZ0lRU0lBQUZqRnNtQkszOUpOQVNCYkJJa0FBR0FWeTRQYysxYWhrNHFrQUxKRmtBZ0FBR0JvTUprZEdaMHJDUUNkSUVnRUFBQ3JXQjdpM3FlVk5jc1YySXBVWFFDeEVTUUNBSUJWQ0JKM1kxVVJ0c1p4R2dDaUlrZ0VBQUF4SENvTnMyaXFDUHZHOGozT3A2UGIxb01BNElnZ0VRQUFyR0tkNW5qZWVxUThZK04zOU5CNkJBQ2NFU1FDQUlCVnJOTWN4MXBwSzVMZW0zV1F5SDVFQU5FUkpBSUFnRldzZzhRRGh5QXFKVmNPVlUxdldvOEFnRE9DUkFBQXNJckhLdGI3d1dSV1hCR2J3V1IyYXIwWFVkaVBDQ0M2d1h3KzUxTUhBQUJMRFNZemo0SENVNmgyT3ArT2lxamFxYUQzMW1FVjhjdDhPckt1bEFvQUwySWxFUUFBckhPMzVybGRIWWFncW9UOWlZNEJZcVgwVlFDSWppQVJBQUNzNDdVbjdsaUJZcmFwcDg0QjR0TjhPbUkvSW9CT0VDUUNBSUIxUEZlejZrQXh1NVRLd1dRV0N2RDg3UlFnQmhldFJ3QWdFdllrQWdDQXRRYVRXUWdVejliOUhRTWhyZlY4UGgwOXB2eHREQ2F6SXdYT3IxcFAyZ21yaUVleDN4c0ExRmhKQkFBQUw0bXhxaFdDcm45Q1FEcVl6SWF0WnpzV2drTUZ5Lzg0QjRnVnE0Z0F1c1pLSWdBQWVGR2sxY1NtQjYzWTNYUzV1cWlBOVR6aWU3K2JUMGZKQmNrQStvVWdFUUFBdkVocGx2ZU9lL0RXZVZDQm1HOC9ua2RucU9McVVEK25xc1FheTNQNHZmUHB5T044U2dEWUdFRWlBQURZaUlxMWZFemcwM3BXd0JwK3ZqWU9uSC9jZE5WUndXQmRXVFVFaEVmNjgzSHJMOGZ6eDN3NnV1enc5d1BBTndTSkFBQmdZNFBKN0RiQ25ydyt1cDVQUitkOS94QUFwSUhDTlFBQVlCc2hCZk9KVDh4VVNLY2RGL1IrQUdTT0lCRUFBR3hNK3dGUGxmS0ovVDFvSDZMYlBrc0EyQlpCSWdBQTJJb0txd3dKRlBkR2dBZ2dTUVNKQUFCZ2F3U0tleU5BQkpBc2drUUFBTENUUnFESUhzWHRmQ0ZBQkpBeXFwc0NBSUM5NkRpSkc2cWVidVREZkRxNnlPQjFBdWd4Z2tRQUFHQmlNSm1GNE9jOW4rWlNZYlgxZkQ0ZDNTNTdFZ0JTUXJvcEFBQXdvUld5ZjJ1L0hYNzRGQTdxSjBBRWtBdFdFZ0VBZ0xuQlpCYk8vUXRCNDBHUFA5MjdjUDZoOW00Q1FEWUlFZ0VBZ0F2dFZSenJwMC9CWWdnT0wxZzVCSkFyZ2tRQUFPQ3FSOEVpd1NHQUloQWtBZ0NBS0JRc25pcFlQQzdrVXcvblJGNVZWWFU1bjQ0ZVc4OENRSVlJRWdFQVFIU0R5ZXhJd1dJSUdnOHord2FlZGVUSHpYdzZ1bWs5Q3dDWkkwZ0VBQUNkR2t4bUp6cVUvelRoc3haREt1bXRBa01LMFFBb0drRWlBQUJJeW1BeUN3SGpTZU1uZG1wcUNBaEQ2bWdJQnUvWll3aWdid2dTQVFCQThyVGErS3RXSENzRmtMODIvdjhtQlhHZUZQelY2dUR2c1E0SzU5UFIxOVovQlFCOVVsWFYvd1BoV0szdE1QVnRHUUFBQUFCSlJVNUVya0pnZ2c9PSIsInN1cHBvcnRlZEV4dGVuc2lvbnMiOlt7ImlkIjoiY3JlZFByb3RlY3QiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfSx7ImlkIjoiaG1hYy1zZWNyZXQiLCJmYWlsX2lmX3Vua25vd24iOmZhbHNlfV0sImF1dGhlbnRpY2F0b3JHZXRJbmZvIjp7InZlcnNpb25zIjpbIlUyRl9WMiIsIkZJRE9fMl8wIiwiRklET18yXzFfUFJFIl0sImV4dGVuc2lvbnMiOlsiY3JlZFByb3RlY3QiLCJobWFjLXNlY3JldCJdLCJhYWd1aWQiOiJkOTRhMjlkOTUyZGQ0MjQ3OWMyZDhiODE4YjYxMDM4OSIsIm9wdGlvbnMiOnsicmsiOnRydWUsImNsaWVudFBpbiI6dHJ1ZSwidXAiOnRydWUsInV2Ijp0cnVlLCJ1c2VyVmVyaWZpY2F0aW9uTWdtdFByZXZpZXciOnRydWUsImNyZWRlbnRpYWxNZ210UHJldmlldyI6dHJ1ZX0sIm1heE1zZ1NpemUiOjc2MDksInBpblV2QXV0aFByb3RvY29scyI6WzFdLCJtYXhDcmVkZW50aWFsQ291bnRJbkxpc3QiOjIwLCJtYXhDcmVkZW50aWFsSWRMZW5ndGgiOjI1Nn19LCJzdGF0dXNSZXBvcnRzIjpbeyJzdGF0dXMiOiJGSURPX0NFUlRJRklFRF9MMSIsImVmZmVjdGl2ZURhdGUiOiIyMDIyLTAxLTA2IiwiY2VydGlmaWNhdGlvbkRlc2NyaXB0b3IiOiJWZXJpTWFya-KEoiBHdWFyZCBGaW5nZXJwcmludCBLZXkiLCJjZXJ0aWZpY2F0ZU51bWJlciI6IkZJRE8yMDAyMDIyMDEwNjAwMSIsImNlcnRpZmljYXRpb25Qb2xpY3lWZXJzaW9uIjoiMS40LjAiLCJjZXJ0aWZpY2F0aW9uUmVxdWlyZW1lbnRzVmVyc2lvbiI6IjEuNCJ9LHsic3RhdHVzIjoiRklET19DRVJUSUZJRUQiLCJlZmZlY3RpdmVEYXRlIjoiMjAyMi0wMS0wNiJ9XSwidGltZU9mTGFzdFN0YXR1c0NoYW5nZSI6IjIwMjMtMTEtMTUifSx7ImFhZ3VpZCI6IjgzM2I3MjFhLWZmNWYtNGQwMC1iYjJlLWJkZGEzZWMwMWUyOSIsIm1ldGFkYXRhU3RhdGVtZW50Ijp7ImxlZ2FsSGVhZGVyIjoiU3VibWlzc2lvbiBvZiB0aGlzIHN0YXRlbWVudCBhbmQgcmV0cmlldmFsIGFuZCB1c2Ugb2YgdGhpcyBzdGF0ZW1lbnQgaW5kaWNhdGVzIGFjY2VwdGFuY2Ugb2YgdGhlIGFwcHJvcHJpYXRlIGFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBzOi8vZmlkb2FsbGlhbmNlLm9yZy9tZXRhZGF0YS9tZXRhZGF0YS1sZWdhbC10ZXJtcy8uIiwiYWFndWlkIjoiODMzYjcyMWEtZmY1Zi00ZDAwLWJiMmUtYmRkYTNlYzAxZTI5IiwiZGVzY3JpcHRpb24iOiJGZWl0aWFuIGVQYXNzIEZJRE8yIEF1dGhlbnRpY2F0b3IiLCJhdXRoZW50aWNhdG9yVmVyc2lvbiI6MSwicHJvdG9jb2xGYW1pbHkiOiJmaWRvMiIsInNjaGVtYSI6MywidXB2IjpbeyJtYWpvciI6MSwibWlub3IiOjB9XSwiYXV0aGVudGljYXRpb25BbGdvcml0aG1zIjpbInNlY3AyNTZyMV9lY2RzYV9zaGEyNTZfcmF3Il0sInB1YmxpY0tleUFsZ0FuZEVuY29kaW5ncyI6WyJjb3NlIl0sImF0dGVzdGF0aW9uVHlwZXMiOlsiYmFzaWNfZnVsbCJdLCJ1c2VyVmVyaWZpY2F0aW9uRGV0YWlscyI6W1t7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJub25lIn1dLFt7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwcmVzZW5jZV9pbnRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicHJlc2VuY2VfaW50ZXJuYWwifSx7InVzZXJWZXJpZmljYXRpb25NZXRob2QiOiJwYXNzY29kZV9leHRlcm5hbCJ9XSxbeyJ1c2VyVmVyaWZpY2F0aW9uTWV0aG9kIjoicGFzc2NvZGVfZXh0ZXJuYWwifV1dLCJrZXlQcm90ZWN0aW9uIjpbImhhcmR3YXJlIiwic2VjdXJlX2VsZW1lbnQiXSwibWF0Y2hlclByb3RlY3Rpb24iOlsib25fY2hpcCJdLCJjcnlwdG9TdHJlbmd0aCI6MTI4LCJhdHRhY2htZW50SGludCI6WyJleHRlcm5hbCJdLCJ0Y0Rpc3BsYXkiOltdLCJhdHRlc3RhdGlvblJvb3RDZXJ0aWZpY2F0ZXMiOlsiTUlJQjJEQ0NBWDZnQXdJQkFnSVFHQlVyUWJkRHJtMjBGWm5Ec1gyQ0JUQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKVlV6RWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SlZVekVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVzRllFRWhpSnVxcW5NZ1FqU2lpdkJqVjdER0NUZjRYQkJIL0I3dXZac0t4WFNoRjBMOHVESVNXVXZjRXhpeFJzNmdCM29sZFNyam94Nkw4VDk0Tk96cU5DTUVBd0hRWURWUjBPQkJZRUZFdTloeVlSclJ5Snp3Ull2bkRTQ0l4ckZpTzNNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lESFNiMm1iTkRBVU5YdnBQVTBvV0tlTnllMGZRMmw5RDAxQVIyK3NMWmRoQWlFQW8zd3o2ODRJRk1Wc0NDUm11SnF4SDZGUVJFU05xZXp1bzFFK0trR3hXdU09IiwiTUlJQjJEQ0NBWDZnQXdJQkFnSVFGWjk3d3MySkdQRW9hNU5JK3A4ejFqQUtCZ2dxaGtqT1BRUURBakJMTVFzd0NRWURWUVFHRXdKRFRqRWRNQnNHQTFVRUNnd1VSbVZwZEdsaGJpQlVaV05vYm05c2IyZHBaWE14SFRBYkJnTlZCQU1NRkVabGFYUnBZVzRnUmtsRVR5QlNiMjkwSUVOQk1DQVhEVEU0TURRd01UQXdNREF3TUZvWUR6SXdORGd3TXpNeE1qTTFPVFU1V2pCTE1Rc3dDUVlEVlFRR0V3SkRUakVkTUJzR0ExVUVDZ3dVUm1WcGRHbGhiaUJVWldOb2JtOXNiMmRwWlhNeEhUQWJCZ05WQkFNTUZFWmxhWFJwWVc0Z1JrbEVUeUJTYjI5MElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVuZkFLYmp2TVgxRXkxYjZrK1dRUWROVk10OUpnR1d5SjNQdk00QlNLNVhxVGZvKyswb0FqLzR0bnd5SUwwSEZCUjlTdCtrdGpxU1hEZmppWEF1cnM4Nk5DTUVBd0hRWURWUjBPQkJZRUZOR2htRTJCZjhPNWEvWUhaNzFRRXY2UVJmRlVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQzNzVDFsQmpHZUYreEtUcHpWMUtZVTJja2FoVGQ0bUxKeXpZT2hhSHY0aWdJZ0QySllrZnlINVE0QnBvOHJyb08wSXQ3b1lqRjJrZ3kvZVNaM1U5R2xhcXc9IiwiTUlJQmZqQ0NBU1dnQXdJQkFnSUJBVEFLQmdncWhrak9QUVFEQWpBWE1SVXdFd1lEVlFRRERBeEdWQ0JHU1VSUElEQXlNREF3SUJjTk1UWXdOVEF4TURBd01EQXdXaGdQTWpBMU1EQTFNREV3TURBd01EQmFNQmN4RlRBVEJnTlZCQU1NREVaVUlFWkpSRThnTURJd01EQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOQm1yUnFWT3h6dFRKVk4xOXZ0ZHFjTDd0S1Flb2wybm5NMi95WWd2a3NabnI1MFNLYlZnSUVrekhRVk91ODBMVkVFM2xWaGVPMUhqZ2d4QWxUNm80V2pZREJlTUIwR0ExVWREZ1FXQkJSSkZXUXQxYnZHM2pNNlhnbVYvSWNqTnRPL0N6QWZCZ05WSFNNRUdEQVdnQlJKRldRdDFidkczak02WGdtVi9JY2pOdE8vQ3pBTUJnTlZIUk1FQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQkJqQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQXdmUHFnSVdJVUIrUUJCYVZHc2RIeTBzNVJNeGxrenBTWC96U3lUWm1VcFFJZ0Iyd0o2blpSTThvWC9uQTQzUmg2U0pvdk0yWHdDQ0gvLytMaXJCQWJCME09Il0sImljb24iOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUZBQUFBQVVDQU1BQUFBdEJrcmxBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQkhacFZGaDBXRTFNT21OdmJTNWhaRzlpWlM1NGJYQUFBQUFBQUR3L2VIQmhZMnRsZENCaVpXZHBiajBpNzd1L0lpQnBaRDBpVnpWTk1FMXdRMlZvYVVoNmNtVlRlazVVWTNwcll6bGtJajgrSUR4NE9uaHRjRzFsZEdFZ2VHMXNibk02ZUQwaVlXUnZZbVU2Ym5NNmJXVjBZUzhpSUhnNmVHMXdkR3M5SWtGa2IySmxJRmhOVUNCRGIzSmxJRFV1Tmkxak1ERTBJRGM1TGpFMU5qYzVOeXdnTWpBeE5DOHdPQzh5TUMwd09UbzFNem93TWlBZ0lDQWdJQ0FnSWo0Z1BISmtaanBTUkVZZ2VHMXNibk02Y21SbVBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1THpBeUx6SXlMWEprWmkxemVXNTBZWGd0Ym5NaklqNGdQSEprWmpwRVpYTmpjbWx3ZEdsdmJpQnlaR1k2WVdKdmRYUTlJaUlnZUcxc2JuTTZlRzF3UFNKb2RIUndPaTh2Ym5NdVlXUnZZbVV1WTI5dEwzaGhjQzh4TGpBdklpQjRiV3h1Y3pwa1l6MGlhSFIwY0RvdkwzQjFjbXd1YjNKbkwyUmpMMlZzWlcxbGJuUnpMekV1TVM4aUlIaHRiRzV6T25Cb2IzUnZjMmh2Y0QwaWFIUjBjRG92TDI1ekxtRmtiMkpsTG1OdmJTOXdhRzkwYjNOb2IzQXZNUzR3THlJZ2VHMXNibk02ZUcxd1RVMDlJbWgwZEhBNkx5OXVjeTVoWkc5aVpTNWpiMjB2ZUdGd0x6RXVNQzl0YlM4aUlIaHRiRzV6T25OMFVtVm1QU0pvZEhSd09pOHZibk11WVdSdlltVXVZMjl0TDNoaGNDOHhMakF2YzFSNWNHVXZVbVZ6YjNWeVkyVlNaV1lqSWlCNGJYQTZRM0psWVhSdmNsUnZiMnc5SWtGa2IySmxJRkJvYjNSdmMyaHZjQ0JEUXlBeU1ERTBJQ2hOWVdOcGJuUnZjMmdwSWlCNGJYQTZRM0psWVhSbFJHRjBaVDBpTWpBeE5pMHhNaTB6TUZReE5Eb3pNem93T0Nzd09Eb3dNQ0lnZUcxd09rMXZaR2xtZVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJSGh0Y0RwTlpYUmhaR0YwWVVSaGRHVTlJakl3TVRZdE1USXRNekJVTURjNk16RTZOVGtyTURnNk1EQWlJR1JqT21admNtMWhkRDBpYVcxaFoyVXZjRzVuSWlCd2FHOTBiM05vYjNBNlNHbHpkRzl5ZVQwaU1qQXhOaTB4TWkwek1GUXhOVG96TURveU55c3dPRG93TUNZamVEazc1cGFINUx1MklPYWNxdWFnaCttaW1DMHhJT1czc3VhSmsrVzhnQ1lqZUVFN0lpQjRiWEJOVFRwSmJuTjBZVzVqWlVsRVBTSjRiWEF1YVdsa09qSkZOekZDUmtaRFF6WTNSakV4UlRZNU56aEVRVGxEUWtJMk5EWXpSamt3SWlCNGJYQk5UVHBFYjJOMWJXVnVkRWxFUFNKNGJYQXVaR2xrT2pKRk56RkNSa1pFUXpZM1JqRXhSVFk1TnpoRVFUbERRa0kyTkRZelJqa3dJajRnUEhodGNFMU5Pa1JsY21sMlpXUkdjbTl0SUhOMFVtVm1PbWx1YzNSaGJtTmxTVVE5SW5odGNDNXBhV1E2TWtVM01VSkdSa0ZETmpkR01URkZOamszT0VSQk9VTkNRalkwTmpOR09UQWlJSE4wVW1WbU9tUnZZM1Z0Wlc1MFNVUTlJbmh0Y0M1a2FXUTZNa1UzTVVKR1JrSkROamRHTVRGRk5qazNPRVJCT1VOQ1FqWTBOak5HT1RBaUx6NGdQQzl5WkdZNlJHVnpZM0pwY0hScGIyNCtJRHd2Y21SbU9sSkVSajRnUEM5NE9uaHRjRzFsZEdFK0lEdy9lSEJoWTJ0bGRDQmxibVE5SW5JaVB6NDc3SlhGQUFBQVlGQk1WRVgvLy84RVZxSVhaYXZHMk9vcWNMRzJ6T09rd3QwQlNKdHFsY1hWNHUrYXV0bFdoYnprN1BVQU1ZOUhjcktqdE5icThmZUFsOGFCb3N6ejl2cGRqc0dHcXRGM244dVRzTlNacGM2SnNOVDUrdjB4WUtudThQZmY1L0w0OGZnL2ZyaWN6SmdZQUFBREFFbEVRVlI0MmtSVUNaYkRJQWpGWFpPWTFUYXROYzM5Ynprc1NZYzNyNE1FNGZNQkFhRDZ6bDh5LzlUT2dldDhkNWpmTjc4YndNL2REQ1JwUjUyMXpYZm9qSEowNUlJeWhCQVVTVkFPTmRHekJZdDJmN0tGcmZrSmFBa0hoOUZaaGNEWEhSa1RLbzlNTGloR2FhdkltblYzcXlFWDBFcHJnei80RHdVRDdrQ0hSbmQ4UUZONDNHbzRVVm1ERGd6YTR3MjdvaXpkQTIrY0srdXVVcGpqbzIreHdjLzQyVzUweDVMR1llREJzUjBIVkl4NXg4aUY2MENibGJURUVrRnIyN2JOREJVVlNxMU9LVlBiRTYyYjNFSDhGcUJnNU9PT0V1YzJ0OFpKaXFNT3VHcCtjS2pnN3dWR2Nlb3pxTjRweGdWUFFrakZZZ2JWSktEVWhEQ2pZcmF3UDVxNEVUZ0M5ZklNUkh0aXRwUWNDdkpPRUxjYk1zUWduY2lSa2xqcHlRanZHNDRqcUJVRVRGaUJpMVBFSXlla096c1crVHk1Y0xIb3M1UitkTVMxTHRTU3hmM2dRSGN6UjJDSTRnTU5wVzRJUkExUU1hNnRKNCtDNnVIdUdFOG1OREl5RnFnL09QL01NVXVlUzZJcThTOTBkQWVCSlNFeS9xS2tLK0JOd3o4Y1lZNGpiNUo2dTRpV0NJMkIxWjU2TFc1a0VjNGhrZE1wc3ZVQzU1ODVTWDBRdWJjZ05xeWZnREZFY1R0KzQwLzBTNU54MHdhQ3czT0trY09iQTVJbjBBWXAwMXBqancybjYyNlVEanRId2EyOGlIdVRLcXRydityZVc0MU5aNmlHbHI3dXVMSkNma0Z0Y3RjRzA0c2dtMWVOUytaYURucGFURXJHb3lYNUpLMmlNejh4czBuT3dXR2NQRE40OXFhQ2Q0YnpKb3pEWm0vYUJLK0Vvekx3K1hoTkJpWXdIZjBzaU91MVhQa0cvekt3dnFZS2NmU3dERWNIL29VZTA3ZXMvV1E4ckl5ZzJET1hqOHRqa1pkdURCL2I4aHpEbGxNTU9DUzVCRW5kNTM0Zjh0aTNVWmM0a01zM3hMeWFmTVNzSmhkRzhYUHFqTms1dEFnTzI1ZmVLQ2huVmREai9KMEZNa09zVS94TUJ2MHdGaFllRUdmVkgxM2Z1RFUweURGTGE0ZmM3Um5XSEJmdVRGVjJ0RW1Od2FkYzdhYzNVWTJqZkJsN0hUMzZmZTM0aVFPNW1OQ0ZGQlcwN0tqUGdxaE9MVTAxdlo4UHVlWjJKQ2xGWk44amtVczY5dWthOWVQcDYrRWZMNEFGNStOeXdTYmlySHRjQjhNbC9na3dBRWprSzY0S2pIUGVBQUFBQUVsRlRrU3VRbUNDIiwiYXV0aGVudGljYXRvckdldEluZm8iOnsidmVyc2lvbnMiOlsiVTJGX1YyIiwiRklET18yXzAiLCJGSURPXzJfMV9QUkUiXSwiZXh0ZW5zaW9ucyI6WyJjcmVkUHJvdGVjdCIsImhtYWMtc2VjcmV0Il0sImFhZ3VpZCI6IjgzM2I3MjFhZmY1ZjRkMDBiYjJlYmRkYTNlYzAxZTI5Iiwib3B0aW9ucyI6eyJwbGF0IjpmYWxzZSwicmsiOnRydWUsImNsaWVudFBpbiI6ZmFsc2UsInVwIjp0cnVlLCJjcmVkZW50aWFsTWdtdFByZXZpZXciOnRydWV9LCJtYXhNc2dTaXplIjoyMDQ4LCJwaW5VdkF1dGhQcm90b2NvbHMiOlsxXSwibWF4Q3JlZGVudGlhbENvdW50SW5MaXN0IjoxMCwibWF4Q3JlZGVudGlhbElkTGVuZ3RoIjo5NiwidHJhbnNwb3J0cyI6WyJ1c2IiXSwiYWxnb3JpdGhtcyI6W3sidHlwZSI6InB1YmxpYy1rZXkiLCJhbGciOi03fV19fSwic3RhdHVzUmVwb3J0cyI6W3sic3RhdHVzIjoiRklET19DRVJUSUZJRURfTDEiLCJlZmZlY3RpdmVEYXRlIjoiMjAxOS0wNS0yNyIsImNlcnRpZmljYXRpb25EZXNjcmlwdG9yIjoiRmVpdGlhbiBlUGFzcyBGSURPMiBVU0Igb25seSIsImNlcnRpZmljYXRlTnVtYmVyIjoiRklETzIwMDIwMTkwMzExMDAzIiwiY2VydGlmaWNhdGlvblBvbGljeVZlcnNpb24iOiIxLjMuNiIsImNlcnRpZmljYXRpb25SZXF1aXJlbWVudHNWZXJzaW9uIjoiMS4wLjAifSx7InN0YXR1cyI6IkZJRE9fQ0VSVElGSUVEIiwiZWZmZWN0aXZlRGF0ZSI6IjIwMTktMDUtMjciLCJjZXJ0aWZpY2F0aW9uUG9saWN5VmVyc2lvbiI6IjEuMy42In1dLCJ0aW1lT2ZMYXN0U3RhdHVzQ2hhbmdlIjoiMjAxOS0wNS0yNyJ9XX0.wvzlnnrO2eLxdTnu113znscieQrzmMIJJJKjsrrCQ8hOYpXmW2CHhDe_xuLFDDchur16zKKshNz7BqcXeHJE1M6Pg5P1UIUHunHUIuxdXU2COso_ua4JckP-9h5he5kJdr9bDvgq9wiiI9sq_adOflF5dfA9QnW4PVC2GRN5xaHWWjZ24bUwe-oOHTXxN1KgW08ClTO6I3Mw-oAUeq0V2uL692rLvU_LltFq2bbvOvk05HUwtYXQSTx0DtZiTV6menSO_MjCxxw8VMvO-oL4EUzv6glXEYzASN5F_--jCKC10zrcLxvy4rESmg5MGHtHHHAJfPdmHSMLJKQ2Wc7m0Q \ No newline at end of file diff --git a/authentik/stages/authenticator_webauthn/mds/root-r3.crt b/authentik/stages/authenticator_webauthn/mds/root-r3.crt new file mode 100644 index 0000000000..232c4b6121 Binary files /dev/null and b/authentik/stages/authenticator_webauthn/mds/root-r3.crt differ diff --git a/authentik/stages/authenticator_webauthn/migrations/0001_squashed_0011_webauthndevice_aaguid.py b/authentik/stages/authenticator_webauthn/migrations/0001_squashed_0011_webauthndevice_aaguid.py new file mode 100644 index 0000000000..9e783e7752 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/migrations/0001_squashed_0011_webauthndevice_aaguid.py @@ -0,0 +1,168 @@ +# Generated by Django 5.0.4 on 2024-04-18 11:29 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [ + ("authentik_stages_authenticator_webauthn", "0001_initial"), + ("authentik_stages_authenticator_webauthn", "0002_default_setup_flow"), + ("authentik_stages_authenticator_webauthn", "0003_webauthndevice_confirmed"), + ("authentik_stages_authenticator_webauthn", "0004_auto_20210304_1850"), + ( + "authentik_stages_authenticator_webauthn", + "0005_authenticatewebauthnstage_user_verification", + ), + ( + "authentik_stages_authenticator_webauthn", + "0006_authenticatewebauthnstage_authenticator_attachment_and_more", + ), + ( + "authentik_stages_authenticator_webauthn", + "0007_rename_last_used_on_webauthndevice_last_t", + ), + ("authentik_stages_authenticator_webauthn", "0008_alter_webauthndevice_credential_id"), + ("authentik_stages_authenticator_webauthn", "0009_authenticatewebauthnstage_friendly_name"), + ( + "authentik_stages_authenticator_webauthn", + "0010_webauthndevicetype_authenticatorwebauthnstage_and_more", + ), + ("authentik_stages_authenticator_webauthn", "0011_webauthndevice_aaguid"), + ] + + initial = True + + dependencies = [ + ("authentik_flows", "0016_auto_20201202_1307"), + ("authentik_flows", "0027_auto_20231028_1424"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="WebAuthnDeviceType", + fields=[ + ("aaguid", models.UUIDField(primary_key=True, serialize=False, unique=True)), + ("description", models.TextField()), + ("icon", models.TextField(null=True)), + ], + options={ + "verbose_name": "WebAuthn Device type", + "verbose_name_plural": "WebAuthn Device types", + }, + ), + migrations.CreateModel( + name="AuthenticatorWebAuthnStage", + fields=[ + ( + "stage_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="authentik_flows.stage", + ), + ), + ( + "configure_flow", + models.ForeignKey( + blank=True, + help_text="Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="authentik_flows.flow", + ), + ), + ( + "user_verification", + models.TextField( + choices=[ + ("required", "Required"), + ("preferred", "Preferred"), + ("discouraged", "Discouraged"), + ], + default="preferred", + ), + ), + ( + "authenticator_attachment", + models.TextField( + choices=[("platform", "Platform"), ("cross-platform", "Cross Platform")], + default=None, + null=True, + ), + ), + ( + "resident_key_requirement", + models.TextField( + choices=[ + ("discouraged", "Discouraged"), + ("preferred", "Preferred"), + ("required", "Required"), + ], + default="preferred", + ), + ), + ("friendly_name", models.TextField(null=True)), + ( + "device_type_restrictions", + models.ManyToManyField( + blank=True, to="authentik_stages_authenticator_webauthn.webauthndevicetype" + ), + ), + ], + options={ + "verbose_name": "WebAuthn Authenticator Setup Stage", + "verbose_name_plural": "WebAuthn Authenticator Setup Stages", + }, + bases=("authentik_flows.stage", models.Model), + ), + migrations.CreateModel( + name="WebAuthnDevice", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ("name", models.TextField(max_length=200)), + ("credential_id", models.TextField(unique=True)), + ("public_key", models.TextField()), + ("sign_count", models.IntegerField(default=0)), + ("rp_id", models.CharField(max_length=253)), + ("created_on", models.DateTimeField(auto_now_add=True)), + ("last_t", models.DateTimeField(default=django.utils.timezone.now)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ( + "confirmed", + models.BooleanField(default=True, help_text="Is this device ready for use?"), + ), + ( + "device_type", + models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_stages_authenticator_webauthn.webauthndevicetype", + ), + ), + ("aaguid", models.TextField(default="00000000-0000-0000-0000-000000000000")), + ], + options={ + "verbose_name": "WebAuthn Device", + "verbose_name_plural": "WebAuthn Devices", + }, + ), + ] diff --git a/authentik/stages/authenticator_webauthn/migrations/0010_webauthndevicetype_authenticatorwebauthnstage_and_more.py b/authentik/stages/authenticator_webauthn/migrations/0010_webauthndevicetype_authenticatorwebauthnstage_and_more.py new file mode 100644 index 0000000000..ad5b967bd3 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/migrations/0010_webauthndevicetype_authenticatorwebauthnstage_and_more.py @@ -0,0 +1,45 @@ +# Generated by Django 5.0.3 on 2024-04-02 23:38 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_flows", "0027_auto_20231028_1424"), + ("authentik_stages_authenticator_webauthn", "0009_authenticatewebauthnstage_friendly_name"), + ] + + operations = [ + migrations.CreateModel( + name="WebAuthnDeviceType", + fields=[ + ("aaguid", models.UUIDField(primary_key=True, serialize=False, unique=True)), + ("description", models.TextField()), + ("icon", models.TextField(null=True)), + ], + options={ + "verbose_name": "WebAuthn Device type", + "verbose_name_plural": "WebAuthn Device types", + }, + ), + migrations.RenameModel("AuthenticateWebAuthnStage", "AuthenticatorWebAuthnStage"), + migrations.AddField( + model_name="webauthndevice", + name="device_type", + field=models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_DEFAULT, + to="authentik_stages_authenticator_webauthn.webauthndevicetype", + ), + ), + migrations.AddField( + model_name="authenticatorwebauthnstage", + name="device_type_restrictions", + field=models.ManyToManyField( + blank=True, to="authentik_stages_authenticator_webauthn.webauthndevicetype" + ), + ), + ] diff --git a/authentik/stages/authenticator_webauthn/migrations/0011_webauthndevice_aaguid.py b/authentik/stages/authenticator_webauthn/migrations/0011_webauthndevice_aaguid.py new file mode 100644 index 0000000000..d7baa62c84 --- /dev/null +++ b/authentik/stages/authenticator_webauthn/migrations/0011_webauthndevice_aaguid.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.4 on 2024-04-18 11:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "authentik_stages_authenticator_webauthn", + "0010_webauthndevicetype_authenticatorwebauthnstage_and_more", + ), + ] + + operations = [ + migrations.AddField( + model_name="webauthndevice", + name="aaguid", + field=models.TextField(default="00000000-0000-0000-0000-000000000000"), + ), + ] diff --git a/authentik/stages/authenticator_webauthn/models.py b/authentik/stages/authenticator_webauthn/models.py index 5f47681956..fc0e7f6867 100644 --- a/authentik/stages/authenticator_webauthn/models.py +++ b/authentik/stages/authenticator_webauthn/models.py @@ -1,5 +1,4 @@ """WebAuthn stage""" -from typing import Optional from django.contrib.auth import get_user_model from django.db import models @@ -15,6 +14,8 @@ from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage from authentik.lib.models import SerializerModel from authentik.stages.authenticator.models import Device +UNKNOWN_DEVICE_TYPE_AAGUID = "00000000-0000-0000-0000-000000000000" + class UserVerification(models.TextChoices): """The degree to which the Relying Party wishes to verify a user's identity. @@ -66,7 +67,7 @@ class AuthenticatorAttachment(models.TextChoices): CROSS_PLATFORM = "cross-platform" -class AuthenticateWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage): +class AuthenticatorWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage): """WebAuthn stage""" user_verification = models.TextField( @@ -77,18 +78,22 @@ class AuthenticateWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage): choices=ResidentKeyRequirement.choices, default=ResidentKeyRequirement.PREFERRED, ) - authenticator_attachment = models.TextField( + authenticator_attachment = models.TextField( # noqa: DJ001 choices=AuthenticatorAttachment.choices, default=None, null=True ) + device_type_restrictions = models.ManyToManyField("WebAuthnDeviceType", blank=True) + @property def serializer(self) -> type[BaseSerializer]: - from authentik.stages.authenticator_webauthn.api import AuthenticateWebAuthnStageSerializer + from authentik.stages.authenticator_webauthn.api.stages import ( + AuthenticatorWebAuthnStageSerializer, + ) - return AuthenticateWebAuthnStageSerializer + return AuthenticatorWebAuthnStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.authenticator_webauthn.stage import AuthenticatorWebAuthnStageView return AuthenticatorWebAuthnStageView @@ -97,7 +102,7 @@ class AuthenticateWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage): def component(self) -> str: return "ak-stage-authenticator-webauthn-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: return UserSettingSerializer( data={ "title": self.friendly_name or str(self._meta.verbose_name), @@ -127,6 +132,11 @@ class WebAuthnDevice(SerializerModel, Device): created_on = models.DateTimeField(auto_now_add=True) last_t = models.DateTimeField(default=now) + aaguid = models.TextField(default=UNKNOWN_DEVICE_TYPE_AAGUID) + device_type = models.ForeignKey( + "WebAuthnDeviceType", on_delete=models.SET_DEFAULT, null=True, default=None + ) + @property def descriptor(self) -> PublicKeyCredentialDescriptor: """Get a publickeydescriptor for this device""" @@ -140,13 +150,37 @@ class WebAuthnDevice(SerializerModel, Device): @property def serializer(self) -> Serializer: - from authentik.stages.authenticator_webauthn.api import WebAuthnDeviceSerializer + from authentik.stages.authenticator_webauthn.api.devices import WebAuthnDeviceSerializer return WebAuthnDeviceSerializer def __str__(self): - return str(self.name) or str(self.user) + return str(self.name) or str(self.user_id) class Meta: verbose_name = _("WebAuthn Device") verbose_name_plural = _("WebAuthn Devices") + + +class WebAuthnDeviceType(SerializerModel): + """WebAuthn device type, used to restrict which device types are allowed""" + + aaguid = models.UUIDField(primary_key=True, unique=True) + + description = models.TextField() + icon = models.TextField(null=True) + + @property + def serializer(self) -> Serializer: + from authentik.stages.authenticator_webauthn.api.device_types import ( + WebAuthnDeviceTypeSerializer, + ) + + return WebAuthnDeviceTypeSerializer + + class Meta: + verbose_name = _("WebAuthn Device type") + verbose_name_plural = _("WebAuthn Device types") + + def __str__(self) -> str: + return f"WebAuthn device type {self.description} ({self.aaguid})" diff --git a/authentik/stages/authenticator_webauthn/stage.py b/authentik/stages/authenticator_webauthn/stage.py index 35b42e6aee..02f9ad2107 100644 --- a/authentik/stages/authenticator_webauthn/stage.py +++ b/authentik/stages/authenticator_webauthn/stage.py @@ -1,14 +1,19 @@ """WebAuthn stage""" + from json import loads +from uuid import UUID from django.http import HttpRequest, HttpResponse from django.http.request import QueryDict +from django.utils.translation import gettext_lazy as _ from rest_framework.fields import CharField from rest_framework.serializers import ValidationError from webauthn import options_to_json from webauthn.helpers.bytes_to_base64url import bytes_to_base64url from webauthn.helpers.exceptions import InvalidRegistrationResponse from webauthn.helpers.structs import ( + AttestationConveyancePreference, + AuthenticatorAttachment, AuthenticatorSelectionCriteria, PublicKeyCredentialCreationOptions, ResidentKeyRequirement, @@ -29,7 +34,12 @@ from authentik.flows.challenge import ( WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView -from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage, WebAuthnDevice +from authentik.stages.authenticator_webauthn.models import ( + UNKNOWN_DEVICE_TYPE_AAGUID, + AuthenticatorWebAuthnStage, + WebAuthnDevice, + WebAuthnDeviceType, +) from authentik.stages.authenticator_webauthn.utils import get_origin, get_rp_id SESSION_KEY_WEBAUTHN_CHALLENGE = "authentik/stages/authenticator_webauthn/challenge" @@ -64,7 +74,7 @@ class AuthenticatorWebAuthnChallengeResponse(ChallengeResponse): ) except InvalidRegistrationResponse as exc: self.stage.logger.warning("registration failed", exc=exc) - raise ValidationError(f"Registration failed. Error: {exc}") + raise ValidationError(f"Registration failed. Error: {exc}") from None credential_id_exists = WebAuthnDevice.objects.filter( credential_id=bytes_to_base64url(registration.credential_id) @@ -72,6 +82,30 @@ class AuthenticatorWebAuthnChallengeResponse(ChallengeResponse): if credential_id_exists: raise ValidationError("Credential ID already exists.") + stage: AuthenticatorWebAuthnStage = self.stage.executor.current_stage + aaguid = registration.aaguid + allowed_aaguids = stage.device_type_restrictions.values_list("aaguid", flat=True) + if allowed_aaguids.exists(): + invalid_error = ValidationError( + _( + "Invalid device type. Contact your {brand} administrator for help.".format( + brand=self.stage.request.brand.branding_title + ) + ) + ) + # If there are any restrictions set and we didn't get an aaguid, invalid + if not aaguid: + raise invalid_error + # If one of the restrictions is the "special" unknown device type UUID + # but we do have a device type for the given aaguid, invalid + if ( + UUID(UNKNOWN_DEVICE_TYPE_AAGUID) in allowed_aaguids + and not WebAuthnDeviceType.objects.filter(aaguid=aaguid).exists() + ): + return registration + # Otherwise just check if the given aaguid is in the allowed aaguids + if UUID(aaguid) not in allowed_aaguids: + raise invalid_error return registration @@ -83,14 +117,14 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): def get_challenge(self, *args, **kwargs) -> Challenge: # clear session variables prior to starting a new registration self.request.session.pop(SESSION_KEY_WEBAUTHN_CHALLENGE, None) - stage: AuthenticateWebAuthnStage = self.executor.current_stage + stage: AuthenticatorWebAuthnStage = self.executor.current_stage user = self.get_pending_user() # library accepts none so we store null in the database, but if there is a value # set, cast it to string to ensure it's not a django class authenticator_attachment = stage.authenticator_attachment if authenticator_attachment: - authenticator_attachment = str(authenticator_attachment) + authenticator_attachment = AuthenticatorAttachment(str(authenticator_attachment)) registration_options: PublicKeyCredentialCreationOptions = generate_registration_options( rp_id=get_rp_id(self.request), @@ -103,6 +137,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): user_verification=UserVerificationRequirement(str(stage.user_verification)), authenticator_attachment=authenticator_attachment, ), + attestation=AttestationConveyancePreference.DIRECT, ) self.request.session[SESSION_KEY_WEBAUTHN_CHALLENGE] = registration_options.challenge @@ -127,13 +162,21 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): credential_id=bytes_to_base64url(webauthn_credential.credential_id) ).first() if not existing_device: + name = "WebAuthn Device" + device_type = WebAuthnDeviceType.objects.filter( + aaguid=webauthn_credential.aaguid + ).first() + if device_type and device_type.description: + name = device_type.description WebAuthnDevice.objects.create( + name=name, user=self.get_pending_user(), public_key=bytes_to_base64url(webauthn_credential.credential_public_key), credential_id=bytes_to_base64url(webauthn_credential.credential_id), sign_count=webauthn_credential.sign_count, rp_id=get_rp_id(self.request), - name="WebAuthn Device", + device_type=device_type, + aaguid=webauthn_credential.aaguid, ) else: return self.executor.stage_invalid("Device with Credential ID already exists.") diff --git a/authentik/stages/authenticator_webauthn/tasks.py b/authentik/stages/authenticator_webauthn/tasks.py new file mode 100644 index 0000000000..498c2a11ab --- /dev/null +++ b/authentik/stages/authenticator_webauthn/tasks.py @@ -0,0 +1,69 @@ +"""MDS Helpers""" + +from functools import lru_cache +from json import loads +from pathlib import Path + +from django.core.cache import cache +from django.db.transaction import atomic +from fido2.mds3 import filter_revoked, parse_blob + +from authentik.root.celery import CELERY_APP +from authentik.stages.authenticator_webauthn.models import ( + UNKNOWN_DEVICE_TYPE_AAGUID, + WebAuthnDeviceType, +) + +CACHE_KEY_MDS_NO = "goauthentik.io/stages/authenticator_webauthn/mds_no" +AAGUID_BLOB_PATH = Path(__file__).parent / "mds" / "aaguid.json" +MDS_BLOB_PATH = Path(__file__).parent / "mds" / "blob.jwt" +MDS_CA_PATH = Path(__file__).parent / "mds" / "root-r3.crt" + + +@lru_cache +def mds_ca() -> bytes: + """Cache MDS Signature CA, GlobalSign Root CA - R3""" + with open(MDS_CA_PATH, mode="rb") as _raw_root: + return _raw_root.read() + + +@CELERY_APP.task() +def webauthn_mds_import(force=False): + """Background task to import FIDO Alliance MDS blob into database""" + with open(MDS_BLOB_PATH, mode="rb") as _raw_blob: + blob = parse_blob(_raw_blob.read(), mds_ca()) + with atomic(): + WebAuthnDeviceType.objects.update_or_create( + aaguid=UNKNOWN_DEVICE_TYPE_AAGUID, + defaults={ + "description": "authentik: Unknown devices", + }, + ) + if cache.get(CACHE_KEY_MDS_NO) == blob.no and not force: + return + for entry in blob.entries: + aaguid = entry.aaguid + if not aaguid: + continue + if not filter_revoked(entry): + WebAuthnDeviceType.objects.filter(aaguid=str(aaguid)).delete() + continue + metadata = entry.metadata_statement + WebAuthnDeviceType.objects.update_or_create( + aaguid=str(aaguid), + defaults={"description": metadata.description, "icon": metadata.icon}, + ) + cache.set(CACHE_KEY_MDS_NO, blob.no) + + +@CELERY_APP.task() +def webauthn_aaguid_import(force=False): + """Background task to import AAGUIDs into database""" + with open(AAGUID_BLOB_PATH, mode="rb") as _raw_blob: + entries = loads(_raw_blob.read()) + with atomic(): + for aaguid, details in entries.items(): + WebAuthnDeviceType.objects.update_or_create( + aaguid=str(aaguid), + defaults={"description": details.get("name"), "icon": details.get("icon_light")}, + ) diff --git a/authentik/stages/authenticator_webauthn/tests.py b/authentik/stages/authenticator_webauthn/tests.py index 28f67a6c92..c22ee64259 100644 --- a/authentik/stages/authenticator_webauthn/tests.py +++ b/authentik/stages/authenticator_webauthn/tests.py @@ -1,4 +1,5 @@ """Test WebAuthn API""" + from base64 import b64decode from django.urls import reverse @@ -11,15 +12,24 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.tests import FlowTestCase from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.lib.generators import generate_id -from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage, WebAuthnDevice +from authentik.stages.authenticator_webauthn.models import ( + UNKNOWN_DEVICE_TYPE_AAGUID, + AuthenticatorWebAuthnStage, + WebAuthnDevice, + WebAuthnDeviceType, +) from authentik.stages.authenticator_webauthn.stage import SESSION_KEY_WEBAUTHN_CHALLENGE +from authentik.stages.authenticator_webauthn.tasks import ( + webauthn_aaguid_import, + webauthn_mds_import, +) class TestAuthenticatorWebAuthnStage(FlowTestCase): """Test WebAuthn API""" def setUp(self) -> None: - self.stage = AuthenticateWebAuthnStage.objects.create( + self.stage = AuthenticatorWebAuthnStage.objects.create( name=generate_id(), ) self.flow = create_test_flow() @@ -45,12 +55,6 @@ class TestAuthenticatorWebAuthnStage(FlowTestCase): plan.context[PLAN_CONTEXT_PENDING_USER] = self.user session = self.client.session session[SESSION_KEY_PLAN] = plan - session[SESSION_KEY_WEBAUTHN_CHALLENGE] = b64decode( - ( - "o90Yh1osqW3mjGift+6WclWOya5lcdff/G0mqueN3hChacMUz" - "V4mxiDafuQ0x0e1d/fcPai0fx/jMBZ8/nG2qQ==" - ).encode() - ) session.save() response = self.client.get( @@ -88,6 +92,217 @@ class TestAuthenticatorWebAuthnStage(FlowTestCase): "requireResidentKey": False, "userVerification": "preferred", }, - "attestation": "none", + "attestation": "direct", }, ) + + def test_register(self): + """Test registration""" + plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + session = self.client.session + session[SESSION_KEY_PLAN] = plan + session[SESSION_KEY_WEBAUTHN_CHALLENGE] = b64decode( + b"03Xodi54gKsfnP5I9VFfhaGXVVE2NUyZpBBXns/JI+x6V9RY2Tw2QmxRJkhh7174EkRazUntIwjMVY9bFG60Lw==" + ) + session.save() + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), + data={ + "component": "ak-stage-authenticator-webauthn", + "response": { + "id": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "rawId": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "type": "public-key", + "registrationClientExtensions": "{}", + "response": { + "clientDataJSON": ( + "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmd" + "lIjoiMDNYb2RpNTRnS3NmblA1STlWRmZoYUdYVlZFMk5VeV" + "pwQkJYbnNfSkkteDZWOVJZMlR3MlFteFJKa2hoNzE3NEVrU" + "mF6VW50SXdqTVZZOWJGRzYwTHciLCJvcmlnaW4iOiJodHRw" + "Oi8vbG9jYWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" + ), + "attestationObject": ( + "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYSZYN5Yg" + "OjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NdAAAAAPv8MA" + "cVTk7MjAtuAgVX170AFJKp5q1S5wxvjsLEjR5IoWGWjc-bp" + "QECAyYgASFYIKtcZHPumH37XHs0IM1v3pUBRIqHVV_SE-Lq" + "2zpJAOVXIlgg74Fg_WdB0kuLYqCKbxogkEPaVtR_iR3IyQFIJAXBzds" + ), + }, + }, + }, + SERVER_NAME="localhost", + SERVER_PORT="9000", + ) + self.assertEqual(response.status_code, 200) + self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) + self.assertTrue(WebAuthnDevice.objects.filter(user=self.user).exists()) + + def test_register_restricted_device_type_deny(self): + """Test registration with restricted devices (fail)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() + self.stage.device_type_restrictions.set( + WebAuthnDeviceType.objects.filter( + description="Android Authenticator with SafetyNet Attestation" + ) + ) + + plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + session = self.client.session + session[SESSION_KEY_PLAN] = plan + session[SESSION_KEY_WEBAUTHN_CHALLENGE] = b64decode( + b"03Xodi54gKsfnP5I9VFfhaGXVVE2NUyZpBBXns/JI+x6V9RY2Tw2QmxRJkhh7174EkRazUntIwjMVY9bFG60Lw==" + ) + session.save() + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), + data={ + "component": "ak-stage-authenticator-webauthn", + "response": { + "id": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "rawId": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "type": "public-key", + "registrationClientExtensions": "{}", + "response": { + "clientDataJSON": ( + "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmd" + "lIjoiMDNYb2RpNTRnS3NmblA1STlWRmZoYUdYVlZFMk5VeV" + "pwQkJYbnNfSkkteDZWOVJZMlR3MlFteFJKa2hoNzE3NEVrU" + "mF6VW50SXdqTVZZOWJGRzYwTHciLCJvcmlnaW4iOiJodHRw" + "Oi8vbG9jYWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" + ), + "attestationObject": ( + "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYSZYN5Yg" + "OjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NdAAAAAPv8MA" + "cVTk7MjAtuAgVX170AFJKp5q1S5wxvjsLEjR5IoWGWjc-bp" + "QECAyYgASFYIKtcZHPumH37XHs0IM1v3pUBRIqHVV_SE-Lq" + "2zpJAOVXIlgg74Fg_WdB0kuLYqCKbxogkEPaVtR_iR3IyQFIJAXBzds" + ), + }, + }, + }, + SERVER_NAME="localhost", + SERVER_PORT="9000", + ) + self.assertEqual(response.status_code, 200) + self.assertStageResponse( + response, + flow=self.flow, + component="ak-stage-authenticator-webauthn", + response_errors={ + "response": [ + { + "string": ( + "Invalid device type. Contact your authentik administrator for help." + ), + "code": "invalid", + } + ] + }, + ) + self.assertFalse(WebAuthnDevice.objects.filter(user=self.user).exists()) + + def test_register_restricted_device_type_allow(self): + """Test registration with restricted devices (allow)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() + self.stage.device_type_restrictions.set( + WebAuthnDeviceType.objects.filter(description="iCloud Keychain") + ) + + plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + session = self.client.session + session[SESSION_KEY_PLAN] = plan + session[SESSION_KEY_WEBAUTHN_CHALLENGE] = b64decode( + b"03Xodi54gKsfnP5I9VFfhaGXVVE2NUyZpBBXns/JI+x6V9RY2Tw2QmxRJkhh7174EkRazUntIwjMVY9bFG60Lw==" + ) + session.save() + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), + data={ + "component": "ak-stage-authenticator-webauthn", + "response": { + "id": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "rawId": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "type": "public-key", + "registrationClientExtensions": "{}", + "response": { + "clientDataJSON": ( + "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmd" + "lIjoiMDNYb2RpNTRnS3NmblA1STlWRmZoYUdYVlZFMk5VeV" + "pwQkJYbnNfSkkteDZWOVJZMlR3MlFteFJKa2hoNzE3NEVrU" + "mF6VW50SXdqTVZZOWJGRzYwTHciLCJvcmlnaW4iOiJodHRw" + "Oi8vbG9jYWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" + ), + "attestationObject": ( + "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYSZYN5Yg" + "OjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NdAAAAAPv8MA" + "cVTk7MjAtuAgVX170AFJKp5q1S5wxvjsLEjR5IoWGWjc-bp" + "QECAyYgASFYIKtcZHPumH37XHs0IM1v3pUBRIqHVV_SE-Lq" + "2zpJAOVXIlgg74Fg_WdB0kuLYqCKbxogkEPaVtR_iR3IyQFIJAXBzds" + ), + }, + }, + }, + SERVER_NAME="localhost", + SERVER_PORT="9000", + ) + self.assertEqual(response.status_code, 200) + self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) + self.assertTrue(WebAuthnDevice.objects.filter(user=self.user).exists()) + + def test_register_restricted_device_type_allow_unknown(self): + """Test registration with restricted devices (allow, unknown device type)""" + webauthn_mds_import(force=True) + webauthn_aaguid_import() + WebAuthnDeviceType.objects.filter(description="iCloud Keychain").delete() + self.stage.device_type_restrictions.set( + WebAuthnDeviceType.objects.filter(aaguid=UNKNOWN_DEVICE_TYPE_AAGUID) + ) + + plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) + plan.context[PLAN_CONTEXT_PENDING_USER] = self.user + session = self.client.session + session[SESSION_KEY_PLAN] = plan + session[SESSION_KEY_WEBAUTHN_CHALLENGE] = b64decode( + b"03Xodi54gKsfnP5I9VFfhaGXVVE2NUyZpBBXns/JI+x6V9RY2Tw2QmxRJkhh7174EkRazUntIwjMVY9bFG60Lw==" + ) + session.save() + response = self.client.post( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), + data={ + "component": "ak-stage-authenticator-webauthn", + "response": { + "id": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "rawId": "kqnmrVLnDG-OwsSNHkihYZaNz5s", + "type": "public-key", + "registrationClientExtensions": "{}", + "response": { + "clientDataJSON": ( + "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmd" + "lIjoiMDNYb2RpNTRnS3NmblA1STlWRmZoYUdYVlZFMk5VeV" + "pwQkJYbnNfSkkteDZWOVJZMlR3MlFteFJKa2hoNzE3NEVrU" + "mF6VW50SXdqTVZZOWJGRzYwTHciLCJvcmlnaW4iOiJodHRw" + "Oi8vbG9jYWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" + ), + "attestationObject": ( + "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYSZYN5Yg" + "OjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NdAAAAAPv8MA" + "cVTk7MjAtuAgVX170AFJKp5q1S5wxvjsLEjR5IoWGWjc-bp" + "QECAyYgASFYIKtcZHPumH37XHs0IM1v3pUBRIqHVV_SE-Lq" + "2zpJAOVXIlgg74Fg_WdB0kuLYqCKbxogkEPaVtR_iR3IyQFIJAXBzds" + ), + }, + }, + }, + SERVER_NAME="localhost", + SERVER_PORT="9000", + ) + self.assertEqual(response.status_code, 200) + self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) + self.assertTrue(WebAuthnDevice.objects.filter(user=self.user).exists()) diff --git a/authentik/stages/authenticator_webauthn/urls.py b/authentik/stages/authenticator_webauthn/urls.py index 9116dbceab..6695a097e6 100644 --- a/authentik/stages/authenticator_webauthn/urls.py +++ b/authentik/stages/authenticator_webauthn/urls.py @@ -1,12 +1,15 @@ """API URLs""" -from authentik.stages.authenticator_webauthn.api import ( - AuthenticateWebAuthnStageViewSet, + +from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeViewSet +from authentik.stages.authenticator_webauthn.api.devices import ( WebAuthnAdminDeviceViewSet, WebAuthnDeviceViewSet, ) +from authentik.stages.authenticator_webauthn.api.stages import AuthenticatorWebAuthnStageViewSet api_urlpatterns = [ - ("stages/authenticator/webauthn", AuthenticateWebAuthnStageViewSet), + ("stages/authenticator/webauthn", AuthenticatorWebAuthnStageViewSet), + ("stages/authenticator/webauthn_device_types", WebAuthnDeviceTypeViewSet), ( "authenticators/admin/webauthn", WebAuthnAdminDeviceViewSet, diff --git a/authentik/stages/captcha/api.py b/authentik/stages/captcha/api.py index b8ff793ceb..8d833197cd 100644 --- a/authentik/stages/captcha/api.py +++ b/authentik/stages/captcha/api.py @@ -1,4 +1,5 @@ """CaptchaStage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/captcha/apps.py b/authentik/stages/captcha/apps.py index 69df384a2c..26c454ec3f 100644 --- a/authentik/stages/captcha/apps.py +++ b/authentik/stages/captcha/apps.py @@ -1,4 +1,5 @@ """authentik captcha app""" + from django.apps import AppConfig diff --git a/authentik/stages/captcha/models.py b/authentik/stages/captcha/models.py index 7ef2b65472..e0e126b056 100644 --- a/authentik/stages/captcha/models.py +++ b/authentik/stages/captcha/models.py @@ -24,7 +24,7 @@ class CaptchaStage(Stage): return CaptchaStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.captcha.stage import CaptchaStageView return CaptchaStageView diff --git a/authentik/stages/captcha/tests.py b/authentik/stages/captcha/tests.py index e83fdd1169..d5d63d8c20 100644 --- a/authentik/stages/captcha/tests.py +++ b/authentik/stages/captcha/tests.py @@ -1,4 +1,5 @@ """captcha tests""" + from django.urls import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow diff --git a/authentik/stages/captcha/urls.py b/authentik/stages/captcha/urls.py index b0fd79df66..67484428ca 100644 --- a/authentik/stages/captcha/urls.py +++ b/authentik/stages/captcha/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.captcha.api import CaptchaStageViewSet api_urlpatterns = [("stages/captcha", CaptchaStageViewSet)] diff --git a/authentik/stages/consent/api.py b/authentik/stages/consent/api.py index ee8940325e..7b4b2f886b 100644 --- a/authentik/stages/consent/api.py +++ b/authentik/stages/consent/api.py @@ -1,4 +1,5 @@ """ConsentStage API Views""" + from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user from rest_framework import mixins @@ -39,7 +40,7 @@ class UserConsentSerializer(StageSerializer): class Meta: model = UserConsent - fields = ["pk", "expires", "user", "application", "permissions"] + fields = ["pk", "expires", "expiring", "user", "application", "permissions"] class UserConsentViewSet( diff --git a/authentik/stages/consent/apps.py b/authentik/stages/consent/apps.py index ba4b04e60c..0c0e664fb7 100644 --- a/authentik/stages/consent/apps.py +++ b/authentik/stages/consent/apps.py @@ -1,4 +1,5 @@ """authentik consent app""" + from django.apps import AppConfig diff --git a/authentik/stages/consent/migrations/0006_alter_userconsent_expires.py b/authentik/stages/consent/migrations/0006_alter_userconsent_expires.py new file mode 100644 index 0000000000..7f186e7965 --- /dev/null +++ b/authentik/stages/consent/migrations/0006_alter_userconsent_expires.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_stages_consent", "0005_alter_consentstage_mode"), + ] + + operations = [ + migrations.AlterField( + model_name="userconsent", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + ] diff --git a/authentik/stages/consent/models.py b/authentik/stages/consent/models.py index bf042cccfd..b180082e60 100644 --- a/authentik/stages/consent/models.py +++ b/authentik/stages/consent/models.py @@ -37,7 +37,7 @@ class ConsentStage(Stage): return ConsentStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.consent.stage import ConsentStageView return ConsentStageView @@ -65,7 +65,7 @@ class UserConsent(SerializerModel, ExpiringModel): return UserConsentSerializer def __str__(self): - return f"User Consent {self.application} by {self.user}" + return f"User Consent {self.application_id} by {self.user_id}" class Meta: unique_together = (("user", "application", "permissions"),) diff --git a/authentik/stages/consent/stage.py b/authentik/stages/consent/stage.py index 61677559cd..7fbc9283fa 100644 --- a/authentik/stages/consent/stage.py +++ b/authentik/stages/consent/stage.py @@ -1,5 +1,5 @@ """authentik consent stage""" -from typing import Optional + from uuid import uuid4 from django.http import HttpRequest, HttpResponse @@ -98,7 +98,7 @@ class ConsentStageView(ChallengeStageView): if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context: user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] - consent: Optional[UserConsent] = UserConsent.filter_not_expired( + consent: UserConsent | None = UserConsent.filter_not_expired( user=user, application=application ).first() self.executor.plan.context[PLAN_CONTEXT_CONSENT] = consent diff --git a/authentik/stages/consent/tests.py b/authentik/stages/consent/tests.py index 35b508a5a8..872539ad24 100644 --- a/authentik/stages/consent/tests.py +++ b/authentik/stages/consent/tests.py @@ -1,7 +1,9 @@ """consent tests""" -from time import sleep + +from datetime import timedelta from django.urls import reverse +from freezegun import freeze_time from authentik.core.models import Application from authentik.core.tasks import clean_expired_models @@ -53,7 +55,7 @@ class TestConsentStage(FlowTestCase): "token": session[SESSION_KEY_CONSENT_TOKEN], }, ) - # pylint: disable=no-member + self.assertEqual(response.status_code, 200) self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) self.assertFalse(UserConsent.objects.filter(user=self.user).exists()) @@ -135,11 +137,12 @@ class TestConsentStage(FlowTestCase): self.assertTrue( UserConsent.objects.filter(user=self.user, application=self.application).exists() ) - sleep(1) - clean_expired_models.delay().get() - self.assertFalse( - UserConsent.objects.filter(user=self.user, application=self.application).exists() - ) + with freeze_time() as frozen_time: + frozen_time.tick(timedelta(seconds=3)) + clean_expired_models.delay().get() + self.assertFalse( + UserConsent.objects.filter(user=self.user, application=self.application).exists() + ) def test_permanent_more_perms(self): """Test permanent consent from user""" diff --git a/authentik/stages/consent/urls.py b/authentik/stages/consent/urls.py index 5be8f69c42..cc2457b6c7 100644 --- a/authentik/stages/consent/urls.py +++ b/authentik/stages/consent/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.consent.api import ConsentStageViewSet, UserConsentViewSet api_urlpatterns = [ diff --git a/authentik/stages/deny/api.py b/authentik/stages/deny/api.py index bdadff7491..ed55253326 100644 --- a/authentik/stages/deny/api.py +++ b/authentik/stages/deny/api.py @@ -1,4 +1,5 @@ """deny Stage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/deny/apps.py b/authentik/stages/deny/apps.py index f7ccba4620..4b1e4a1709 100644 --- a/authentik/stages/deny/apps.py +++ b/authentik/stages/deny/apps.py @@ -1,4 +1,5 @@ """authentik deny stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/deny/models.py b/authentik/stages/deny/models.py index c5ab2c2519..49fcb035d1 100644 --- a/authentik/stages/deny/models.py +++ b/authentik/stages/deny/models.py @@ -1,4 +1,5 @@ """deny stage models""" + from django.db import models from django.utils.translation import gettext_lazy as _ from django.views import View @@ -19,7 +20,7 @@ class DenyStage(Stage): return DenyStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.deny.stage import DenyStageView return DenyStageView diff --git a/authentik/stages/deny/stage.py b/authentik/stages/deny/stage.py index 606f504a10..a5cd134661 100644 --- a/authentik/stages/deny/stage.py +++ b/authentik/stages/deny/stage.py @@ -1,4 +1,5 @@ """Deny stage logic""" + from django.http import HttpRequest, HttpResponse from authentik.flows.stage import StageView diff --git a/authentik/stages/deny/tests.py b/authentik/stages/deny/tests.py index 17e9d49bb6..f61bc7cfdd 100644 --- a/authentik/stages/deny/tests.py +++ b/authentik/stages/deny/tests.py @@ -1,4 +1,5 @@ """deny tests""" + from django.urls import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow diff --git a/authentik/stages/deny/urls.py b/authentik/stages/deny/urls.py index 4c31ee8955..f5da121473 100644 --- a/authentik/stages/deny/urls.py +++ b/authentik/stages/deny/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.deny.api import DenyStageViewSet api_urlpatterns = [("stages/deny", DenyStageViewSet)] diff --git a/authentik/stages/dummy/api.py b/authentik/stages/dummy/api.py index b443b822c1..4792329696 100644 --- a/authentik/stages/dummy/api.py +++ b/authentik/stages/dummy/api.py @@ -1,4 +1,5 @@ """DummyStage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/dummy/models.py b/authentik/stages/dummy/models.py index 41aa022184..e215ede196 100644 --- a/authentik/stages/dummy/models.py +++ b/authentik/stages/dummy/models.py @@ -1,4 +1,5 @@ """dummy stage models""" + from django.db import models from django.utils.translation import gettext as _ from django.views import View @@ -21,7 +22,7 @@ class DummyStage(Stage): return DummyStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.dummy.stage import DummyStageView return DummyStageView diff --git a/authentik/stages/dummy/stage.py b/authentik/stages/dummy/stage.py index 77423dd4e4..e95c740817 100644 --- a/authentik/stages/dummy/stage.py +++ b/authentik/stages/dummy/stage.py @@ -1,4 +1,5 @@ """authentik multi-stage authentication engine""" + from django.http.response import HttpResponse from rest_framework.fields import CharField @@ -11,6 +12,7 @@ class DummyChallenge(Challenge): """Dummy challenge""" component = CharField(default="ak-stage-dummy") + name = CharField() class DummyChallengeResponse(ChallengeResponse): @@ -34,5 +36,6 @@ class DummyStageView(ChallengeStageView): data={ "type": ChallengeTypes.NATIVE.value, "title": self.executor.current_stage.name, + "name": self.executor.current_stage.name, } ) diff --git a/authentik/stages/dummy/tests.py b/authentik/stages/dummy/tests.py index 20296802a6..1b52f76ef8 100644 --- a/authentik/stages/dummy/tests.py +++ b/authentik/stages/dummy/tests.py @@ -1,4 +1,5 @@ """dummy tests""" + from django.urls import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow diff --git a/authentik/stages/dummy/urls.py b/authentik/stages/dummy/urls.py index 195c5487b9..f57b2437aa 100644 --- a/authentik/stages/dummy/urls.py +++ b/authentik/stages/dummy/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.dummy.api import DummyStageViewSet api_urlpatterns = [("stages/dummy", DummyStageViewSet)] diff --git a/authentik/stages/email/api.py b/authentik/stages/email/api.py index b77fff2e7e..14f5a0108a 100644 --- a/authentik/stages/email/api.py +++ b/authentik/stages/email/api.py @@ -1,4 +1,5 @@ """EmailStage API Views""" + from drf_spectacular.utils import extend_schema from rest_framework.decorators import action from rest_framework.request import Request @@ -6,8 +7,8 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet +from authentik.core.api.object_types import TypeCreateSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import TypeCreateSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.email.models import EmailStage, get_template_choices diff --git a/authentik/stages/email/apps.py b/authentik/stages/email/apps.py index ba748c18fd..007ca8ac5d 100644 --- a/authentik/stages/email/apps.py +++ b/authentik/stages/email/apps.py @@ -1,10 +1,7 @@ """authentik email stage config""" -from structlog.stdlib import get_logger from authentik.blueprints.apps import ManagedAppConfig -LOGGER = get_logger() - class AuthentikStageEmailConfig(ManagedAppConfig): """authentik email stage config""" @@ -13,7 +10,3 @@ class AuthentikStageEmailConfig(ManagedAppConfig): label = "authentik_stages_email" verbose_name = "authentik Stages.Email" default = True - - def reconcile_global_load_stages_emails_tasks(self): - """Load stages.emails tasks""" - self.import_module("authentik.stages.email.tasks") diff --git a/authentik/stages/email/management/commands/test_email.py b/authentik/stages/email/management/commands/test_email.py index fd65b9e5c4..ee4a6d4310 100644 --- a/authentik/stages/email/management/commands/test_email.py +++ b/authentik/stages/email/management/commands/test_email.py @@ -1,4 +1,5 @@ """Send a test-email with global settings""" + from uuid import uuid4 from django.core.management.base import no_translations @@ -29,7 +30,7 @@ class Command(TenantCommand): delete_stage = True message = TemplateEmailMessage( subject="authentik Test-Email", - to=[options["to"]], + to=[("", options["to"])], template_name="email/setup.html", template_context={}, ) diff --git a/authentik/stages/email/models.py b/authentik/stages/email/models.py index fcc63868c8..a695b861b7 100644 --- a/authentik/stages/email/models.py +++ b/authentik/stages/email/models.py @@ -1,7 +1,7 @@ """email stage models""" + from os import R_OK, access from pathlib import Path -from typing import Type from django.conf import settings from django.core.mail.backends.base import BaseEmailBackend @@ -87,7 +87,7 @@ class EmailStage(Stage): return EmailStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.email.stage import EmailStageView return EmailStageView @@ -97,7 +97,7 @@ class EmailStage(Stage): return "ak-stage-email-form" @property - def backend_class(self) -> Type[BaseEmailBackend]: + def backend_class(self) -> type[BaseEmailBackend]: """Get the email backend class to use""" return EmailBackend diff --git a/authentik/stages/email/stage.py b/authentik/stages/email/stage.py index 160a68e922..9a81a7a287 100644 --- a/authentik/stages/email/stage.py +++ b/authentik/stages/email/stage.py @@ -1,4 +1,5 @@ """authentik multi-stage authentication engine""" + from datetime import timedelta from uuid import uuid4 @@ -110,7 +111,7 @@ class EmailStageView(ChallengeStageView): try: message = TemplateEmailMessage( subject=_(current_stage.subject), - to=[f"{pending_user.name} <{email}>"], + to=[(pending_user.name, email)], language=pending_user.locale(self.request), template_name=current_stage.template, template_context={ diff --git a/authentik/stages/email/tasks.py b/authentik/stages/email/tasks.py index 407995b29f..8a6089ea11 100644 --- a/authentik/stages/email/tasks.py +++ b/authentik/stages/email/tasks.py @@ -1,7 +1,8 @@ """email stage tasks""" + from email.utils import make_msgid from smtplib import SMTPException -from typing import Any, Optional +from typing import Any from celery import group from django.core.mail import EmailMultiAlternatives @@ -46,7 +47,7 @@ def get_email_body(email: EmailMultiAlternatives) -> str: retry_backoff=True, base=SystemTask, ) -def send_mail(self: SystemTask, message: dict[Any, Any], email_stage_pk: Optional[str] = None): +def send_mail(self: SystemTask, message: dict[Any, Any], email_stage_pk: str | None = None): """Send Email for Email Stage. Retries are scheduled automatically.""" self.save_on_success = False message_id = make_msgid(domain=DNS_NAME) diff --git a/authentik/stages/email/templates/email/account_confirmation.txt b/authentik/stages/email/templates/email/account_confirmation.txt index 0a1fc70d1b..4f894e3835 100644 --- a/authentik/stages/email/templates/email/account_confirmation.txt +++ b/authentik/stages/email/templates/email/account_confirmation.txt @@ -1,4 +1,4 @@ -{% load i18n %}{% translate "Welcome!" %} +{% load i18n %}{% autoescape off %}{% translate "Welcome!" %} {% translate "We're excited to have you get started. First, you need to confirm your account. Just open the link below." %} @@ -6,3 +6,4 @@ -- Powered by goauthentik.io. +{% endautoescape %} diff --git a/authentik/stages/email/templates/email/event_notification.txt b/authentik/stages/email/templates/email/event_notification.txt index bd7d928969..3494e694e5 100644 --- a/authentik/stages/email/templates/email/event_notification.txt +++ b/authentik/stages/email/templates/email/event_notification.txt @@ -1,4 +1,4 @@ -{% load authentik_stages_email %}{% load i18n %}{% translate "Dear authentik user," %} +{% load authentik_stages_email %}{% load i18n %}{% autoescape off %}{% translate "Dear authentik user," %} {% translate "The following notification was created:" %} @@ -16,3 +16,4 @@ This email was sent from the notification transport {{ name }}. -- Powered by goauthentik.io. +{% endautoescape %} diff --git a/authentik/stages/email/templates/email/password_reset.txt b/authentik/stages/email/templates/email/password_reset.txt index 0c13ad2f89..7c4aa89b11 100644 --- a/authentik/stages/email/templates/email/password_reset.txt +++ b/authentik/stages/email/templates/email/password_reset.txt @@ -1,4 +1,4 @@ -{% load i18n %}{% load humanize %}{% blocktrans with username=user.username %}Hi {{ username }},{% endblocktrans %} +{% load i18n %}{% load humanize %}{% autoescape off %}{% blocktrans with username=user.username %}Hi {{ username }},{% endblocktrans %} {% blocktrans %} You recently requested to change your password for your authentik account. Use the link below to set a new password. @@ -10,3 +10,4 @@ If you did not request a password change, please ignore this Email. The link abo -- Powered by goauthentik.io. +{% endautoescape %} diff --git a/authentik/stages/email/templates/email/setup.txt b/authentik/stages/email/templates/email/setup.txt index 6d0eb0ce00..e6d9eaa427 100644 --- a/authentik/stages/email/templates/email/setup.txt +++ b/authentik/stages/email/templates/email/setup.txt @@ -1,7 +1,8 @@ -{% load i18n %}authentik Test-Email +{% load i18n %}{% autoescape off %}authentik Test-Email {% blocktrans %} This is a test email to inform you, that you've successfully configured authentik emails. {% endblocktrans %} -- Powered by goauthentik.io. +{% endautoescape %} diff --git a/authentik/stages/email/templatetags/authentik_stages_email.py b/authentik/stages/email/templatetags/authentik_stages_email.py index 9b3dfb194a..6b55da2bd6 100644 --- a/authentik/stages/email/templatetags/authentik_stages_email.py +++ b/authentik/stages/email/templatetags/authentik_stages_email.py @@ -1,4 +1,5 @@ """authentik core inlining template tags""" + from base64 import b64encode from pathlib import Path diff --git a/authentik/stages/email/tests/test_api.py b/authentik/stages/email/tests/test_api.py index 4488a578e7..04194e368c 100644 --- a/authentik/stages/email/tests/test_api.py +++ b/authentik/stages/email/tests/test_api.py @@ -1,4 +1,5 @@ """email stage api tests""" + from django.urls import reverse from rest_framework.serializers import ValidationError from rest_framework.test import APITestCase diff --git a/authentik/stages/email/tests/test_sending.py b/authentik/stages/email/tests/test_sending.py index 5c67c8842f..631983ab67 100644 --- a/authentik/stages/email/tests/test_sending.py +++ b/authentik/stages/email/tests/test_sending.py @@ -1,4 +1,5 @@ """email tests""" + from smtplib import SMTPException from unittest.mock import MagicMock, PropertyMock, patch @@ -38,6 +39,7 @@ class TestEmailStageSending(FlowTestCase): session = self.client.session session[SESSION_KEY_PLAN] = plan session.save() + Event.objects.filter(action=EventAction.EMAIL_SENT).delete() url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) with patch( diff --git a/authentik/stages/email/tests/test_stage.py b/authentik/stages/email/tests/test_stage.py index 2775499373..e1a6665ad8 100644 --- a/authentik/stages/email/tests/test_stage.py +++ b/authentik/stages/email/tests/test_stage.py @@ -1,4 +1,5 @@ """email tests""" + from unittest.mock import MagicMock, PropertyMock, patch from django.core import mail diff --git a/authentik/stages/email/tests/test_templates.py b/authentik/stages/email/tests/test_templates.py index f8531b078e..a9bee2ed13 100644 --- a/authentik/stages/email/tests/test_templates.py +++ b/authentik/stages/email/tests/test_templates.py @@ -1,4 +1,5 @@ """email tests""" + from os import chmod, unlink from pathlib import Path from shutil import rmtree @@ -8,6 +9,7 @@ from unittest.mock import PropertyMock, patch from django.conf import settings from django.core.mail.backends.locmem import EmailBackend +from django.core.mail.message import sanitize_address from django.urls import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow @@ -18,6 +20,7 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.tests import FlowTestCase from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.stages.email.models import EmailStage, get_template_choices +from authentik.stages.email.utils import TemplateEmailMessage def get_templates_setting(temp_dir: str) -> dict[str, Any]: @@ -88,3 +91,12 @@ class TestEmailStageTemplates(FlowTestCase): event.context["message"], "Exception occurred while rendering E-mail template" ) self.assertEqual(event.context["template"], "invalid.html") + + def test_template_address(self): + """Test addresses are correctly parsed""" + message = TemplateEmailMessage(to=[("foo@bar.baz", "foo@bar.baz")]) + [sanitize_address(addr, "utf-8") for addr in message.recipients()] + self.assertEqual(message.recipients(), ["foo@bar.baz"]) + message = TemplateEmailMessage(to=[("some-name", "foo@bar.baz")]) + [sanitize_address(addr, "utf-8") for addr in message.recipients()] + self.assertEqual(message.recipients(), ["some-name "]) diff --git a/authentik/stages/email/urls.py b/authentik/stages/email/urls.py index f435ae56e5..fbbfdfe4e9 100644 --- a/authentik/stages/email/urls.py +++ b/authentik/stages/email/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.email.api import EmailStageViewSet api_urlpatterns = [("stages/email", EmailStageViewSet)] diff --git a/authentik/stages/email/utils.py b/authentik/stages/email/utils.py index 8f7f702ce2..8ec37e9b6a 100644 --- a/authentik/stages/email/utils.py +++ b/authentik/stages/email/utils.py @@ -1,4 +1,5 @@ """email utils""" + from email.mime.image import MIMEImage from functools import lru_cache from pathlib import Path @@ -9,7 +10,7 @@ from django.template.loader import render_to_string from django.utils import translation -@lru_cache() +@lru_cache def logo_data() -> MIMEImage: """Get logo as MIME Image for emails""" path = Path("web/icons/icon_left_brand.png") @@ -24,8 +25,19 @@ def logo_data() -> MIMEImage: class TemplateEmailMessage(EmailMultiAlternatives): """Wrapper around EmailMultiAlternatives with integrated template rendering""" - def __init__(self, template_name=None, template_context=None, language="", **kwargs): - super().__init__(**kwargs) + def __init__( + self, to: list[tuple[str]], template_name=None, template_context=None, language="", **kwargs + ): + sanitized_to = [] + # Ensure that all recipients are valid + for recipient_name, recipient_email in to: + if recipient_name == recipient_email: + sanitized_to.append(recipient_email) + else: + sanitized_to.append(f"{recipient_name} <{recipient_email}>") + super().__init__(to=sanitized_to, **kwargs) + if not template_name: + return with translation.override(language): html_content = render_to_string(template_name, template_context) try: diff --git a/authentik/stages/identification/api.py b/authentik/stages/identification/api.py index 1f2ab50578..9ad97320e8 100644 --- a/authentik/stages/identification/api.py +++ b/authentik/stages/identification/api.py @@ -1,4 +1,5 @@ """Identification Stage API Views""" + from django.utils.translation import gettext_lazy as _ from rest_framework.exceptions import ValidationError from rest_framework.viewsets import ModelViewSet diff --git a/authentik/stages/identification/apps.py b/authentik/stages/identification/apps.py index e44ebc159f..184a52af77 100644 --- a/authentik/stages/identification/apps.py +++ b/authentik/stages/identification/apps.py @@ -1,4 +1,5 @@ """authentik identification stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/identification/models.py b/authentik/stages/identification/models.py index 8b8b3d1fda..323b93ebf1 100644 --- a/authentik/stages/identification/models.py +++ b/authentik/stages/identification/models.py @@ -102,7 +102,7 @@ class IdentificationStage(Stage): return IdentificationStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.identification.stage import IdentificationStageView return IdentificationStageView diff --git a/authentik/stages/identification/signals.py b/authentik/stages/identification/signals.py index c5d1bdca6f..7eb44435f3 100644 --- a/authentik/stages/identification/signals.py +++ b/authentik/stages/identification/signals.py @@ -1,4 +1,5 @@ """authentik identification signals""" + from django.core.signals import Signal # Arguments: request: HttpRequest, uid_field: Value entered by user diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index b71792ff60..8be41825d5 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -1,15 +1,16 @@ """Identification stage logic""" + from dataclasses import asdict from random import SystemRandom from time import sleep -from typing import Any, Optional +from typing import Any from django.core.exceptions import PermissionDenied from django.db.models import Q from django.http import HttpResponse from django.utils.translation import gettext as _ from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema_field -from rest_framework.fields import BooleanField, CharField, DictField, ListField +from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, ListField from rest_framework.serializers import ValidationError from sentry_sdk.hub import Hub @@ -65,6 +66,7 @@ class IdentificationChallenge(Challenge): user_fields = ListField(child=CharField(), allow_empty=True, allow_null=True) password_fields = BooleanField() application_pre = CharField(required=False) + flow_designation = ChoiceField(FlowDesignation.choices) enroll_url = CharField(required=False) recovery_url = CharField(required=False) @@ -83,7 +85,7 @@ class IdentificationChallengeResponse(ChallengeResponse): password = CharField(required=False, allow_blank=True, allow_null=True) component = CharField(default="ak-stage-identification") - pre_user: Optional[User] = None + pre_user: User | None = None def validate(self, attrs: dict[str, Any]) -> dict[str, Any]: """Validate that user exists, and optionally their password""" @@ -122,7 +124,7 @@ class IdentificationChallengeResponse(ChallengeResponse): if not current_stage.show_matched_user: self.stage.executor.plan.context[PLAN_CONTEXT_PENDING_USER_IDENTIFIER] = uid_field # when `pretend` is enabled, continue regardless - if current_stage.pretend_user_exists: + if current_stage.pretend_user_exists and not current_stage.password_stage: return attrs raise ValidationError("Failed to authenticate.") self.pre_user = pre_user @@ -158,7 +160,7 @@ class IdentificationStageView(ChallengeStageView): response_class = IdentificationChallengeResponse - def get_user(self, uid_value: str) -> Optional[User]: + def get_user(self, uid_value: str) -> User | None: """Find user instance. Returns None if no user was found.""" current_stage: IdentificationStage = self.executor.current_stage query = Q() @@ -193,11 +195,12 @@ class IdentificationStageView(ChallengeStageView): challenge = IdentificationChallenge( data={ "type": ChallengeTypes.NATIVE.value, - "primary_action": self.get_primary_action(), "component": "ak-stage-identification", + "primary_action": self.get_primary_action(), "user_fields": current_stage.user_fields, "password_fields": bool(current_stage.password_stage), "show_source_labels": current_stage.show_source_labels, + "flow_designation": self.executor.flow.designation, } ) # If the user has been redirected to us whilst trying to access an @@ -236,7 +239,9 @@ class IdentificationStageView(ChallengeStageView): ui_login_button = source.ui_login_button(self.request) if ui_login_button: button = asdict(ui_login_button) - button["challenge"] = ui_login_button.challenge.data + source_challenge = ui_login_button.challenge + source_challenge.is_valid() + button["challenge"] = source_challenge.data ui_sources.append(button) challenge.initial_data["sources"] = ui_sources return challenge @@ -245,7 +250,7 @@ class IdentificationStageView(ChallengeStageView): self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = response.pre_user current_stage: IdentificationStage = self.executor.current_stage if not current_stage.show_matched_user: - self.executor.plan.context[ - PLAN_CONTEXT_PENDING_USER_IDENTIFIER - ] = response.validated_data.get("uid_field") + self.executor.plan.context[PLAN_CONTEXT_PENDING_USER_IDENTIFIER] = ( + response.validated_data.get("uid_field") + ) return self.executor.stage_ok() diff --git a/authentik/stages/identification/tests.py b/authentik/stages/identification/tests.py index 375a9d04da..671d5aab6c 100644 --- a/authentik/stages/identification/tests.py +++ b/authentik/stages/identification/tests.py @@ -1,4 +1,5 @@ """identification tests""" + from django.urls import reverse from rest_framework.exceptions import ValidationError @@ -99,6 +100,42 @@ class TestIdentificationStage(FlowTestCase): user_fields=["email"], ) + def test_invalid_with_password_pretend(self): + """Test with invalid email and invalid password in single step (with pretend_user_exists)""" + self.stage.pretend_user_exists = True + pw_stage = PasswordStage.objects.create(name="password", backends=[BACKEND_INBUILT]) + self.stage.password_stage = pw_stage + self.stage.save() + form_data = { + "uid_field": self.user.email + "test", + "password": self.user.username + "test", + } + url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) + response = self.client.post(url, form_data) + self.assertStageResponse( + response, + self.flow, + component="ak-stage-identification", + password_fields=True, + primary_action="Log in", + response_errors={ + "non_field_errors": [{"code": "invalid", "string": "Failed to authenticate."}] + }, + sources=[ + { + "challenge": { + "component": "xak-flow-redirect", + "to": "/source/oauth/login/test/", + "type": ChallengeTypes.REDIRECT.value, + }, + "icon_url": "/static/authentik/sources/default.svg", + "name": "test", + } + ], + show_source_labels=False, + user_fields=["email"], + ) + def test_invalid_with_username(self): """Test invalid with username (user exists but stage only allows email)""" form_data = {"uid_field": self.user.username} diff --git a/authentik/stages/identification/urls.py b/authentik/stages/identification/urls.py index a25cd978e3..b2606fc9d5 100644 --- a/authentik/stages/identification/urls.py +++ b/authentik/stages/identification/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.identification.api import IdentificationStageViewSet api_urlpatterns = [("stages/identification", IdentificationStageViewSet)] diff --git a/authentik/stages/invitation/api.py b/authentik/stages/invitation/api.py index 827662d538..bc63ae38d8 100644 --- a/authentik/stages/invitation/api.py +++ b/authentik/stages/invitation/api.py @@ -1,4 +1,5 @@ """Invitation Stage API Views""" + from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet from rest_framework.serializers import ModelSerializer diff --git a/authentik/stages/invitation/apps.py b/authentik/stages/invitation/apps.py index efd799420b..db3b53d787 100644 --- a/authentik/stages/invitation/apps.py +++ b/authentik/stages/invitation/apps.py @@ -1,10 +1,11 @@ """authentik invitation stage app config""" + from django.apps import AppConfig -class AuthentikStageUserInvitationConfig(AppConfig): +class AuthentikStageInvitationConfig(AppConfig): """authentik invitation stage config""" name = "authentik.stages.invitation" label = "authentik_stages_invitation" - verbose_name = "authentik Stages.User Invitation" + verbose_name = "authentik Stages.Invitation" diff --git a/authentik/stages/invitation/migrations/0008_alter_invitation_expires.py b/authentik/stages/invitation/migrations/0008_alter_invitation_expires.py new file mode 100644 index 0000000000..45a04df432 --- /dev/null +++ b/authentik/stages/invitation/migrations/0008_alter_invitation_expires.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-29 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_stages_invitation", "0007_invitation_flow"), + ] + + operations = [ + migrations.AlterField( + model_name="invitation", + name="expires", + field=models.DateTimeField(default=None, null=True), + ), + ] diff --git a/authentik/stages/invitation/models.py b/authentik/stages/invitation/models.py index ef6cb1cb27..b1ead478f5 100644 --- a/authentik/stages/invitation/models.py +++ b/authentik/stages/invitation/models.py @@ -1,4 +1,5 @@ """invitation stage models""" + from uuid import uuid4 from django.db import models @@ -31,7 +32,7 @@ class InvitationStage(Stage): return InvitationStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.invitation.stage import InvitationStageView return InvitationStageView @@ -78,7 +79,7 @@ class Invitation(SerializerModel, ExpiringModel): return InvitationSerializer def __str__(self): - return f"Invitation {str(self.invite_uuid)} created by {self.created_by}" + return f"Invitation {str(self.invite_uuid)} created by {self.created_by_id}" class Meta: verbose_name = _("Invitation") diff --git a/authentik/stages/invitation/signals.py b/authentik/stages/invitation/signals.py index 2b42214072..34e91b4986 100644 --- a/authentik/stages/invitation/signals.py +++ b/authentik/stages/invitation/signals.py @@ -1,4 +1,5 @@ """authentik invitation signals""" + from django.core.signals import Signal # Arguments: request: HttpRequest, invitation: Invitation diff --git a/authentik/stages/invitation/stage.py b/authentik/stages/invitation/stage.py index 742fde1601..3a9cc5746c 100644 --- a/authentik/stages/invitation/stage.py +++ b/authentik/stages/invitation/stage.py @@ -1,5 +1,4 @@ """invitation stage logic""" -from typing import Optional from deepmerge import always_merger from django.core.exceptions import ValidationError @@ -21,7 +20,7 @@ INVITATION = "invitation" class InvitationStageView(StageView): """Finalise Authentication flow by logging the user in""" - def get_token(self) -> Optional[str]: + def get_token(self) -> str | None: """Get token from saved get-arguments or prompt_data""" # Check for ?token= and ?itoken= if INVITATION_TOKEN_KEY in self.request.session.get(SESSION_KEY_GET, {}): @@ -33,7 +32,7 @@ class InvitationStageView(StageView): return self.executor.plan.context[PLAN_CONTEXT_PROMPT][INVITATION_TOKEN_KEY_CONTEXT] return None - def get_invite(self) -> Optional[Invitation]: + def get_invite(self) -> Invitation | None: """Check the token, find the invite and check it's flow""" token = self.get_token() if not token: diff --git a/authentik/stages/invitation/tests.py b/authentik/stages/invitation/tests.py index 75989a147c..20d4f92259 100644 --- a/authentik/stages/invitation/tests.py +++ b/authentik/stages/invitation/tests.py @@ -1,4 +1,5 @@ """invitation tests""" + from unittest.mock import MagicMock, patch from django.urls import reverse diff --git a/authentik/stages/invitation/urls.py b/authentik/stages/invitation/urls.py index 6a8f087c96..5422cb05f5 100644 --- a/authentik/stages/invitation/urls.py +++ b/authentik/stages/invitation/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.invitation.api import InvitationStageViewSet, InvitationViewSet api_urlpatterns = [ diff --git a/authentik/stages/password/__init__.py b/authentik/stages/password/__init__.py index d5c73cc96b..6c59258a05 100644 --- a/authentik/stages/password/__init__.py +++ b/authentik/stages/password/__init__.py @@ -1,4 +1,5 @@ """Backend paths""" + BACKEND_INBUILT = "authentik.core.auth.InbuiltBackend" BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend" BACKEND_APP_PASSWORD = "authentik.core.auth.TokenBackend" # nosec diff --git a/authentik/stages/password/api.py b/authentik/stages/password/api.py index d90450e5e7..7ede2ade8f 100644 --- a/authentik/stages/password/api.py +++ b/authentik/stages/password/api.py @@ -1,4 +1,5 @@ """PasswordStage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/password/apps.py b/authentik/stages/password/apps.py index 2ff268260b..d8231d7b72 100644 --- a/authentik/stages/password/apps.py +++ b/authentik/stages/password/apps.py @@ -1,4 +1,5 @@ """authentik core app config""" + from django.apps import AppConfig diff --git a/authentik/stages/password/models.py b/authentik/stages/password/models.py index 792a81afc3..9887b68543 100644 --- a/authentik/stages/password/models.py +++ b/authentik/stages/password/models.py @@ -1,5 +1,4 @@ """password stage models""" -from typing import Optional from django.contrib.postgres.fields import ArrayField from django.db import models @@ -52,7 +51,7 @@ class PasswordStage(ConfigurableStage, Stage): return PasswordStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.password.stage import PasswordStageView return PasswordStageView @@ -61,7 +60,7 @@ class PasswordStage(ConfigurableStage, Stage): def component(self) -> str: return "ak-stage-password-form" - def ui_user_settings(self) -> Optional[UserSettingSerializer]: + def ui_user_settings(self) -> UserSettingSerializer | None: if not self.configure_flow: return None return UserSettingSerializer( diff --git a/authentik/stages/password/stage.py b/authentik/stages/password/stage.py index de80c67250..18d78383fb 100644 --- a/authentik/stages/password/stage.py +++ b/authentik/stages/password/stage.py @@ -1,5 +1,6 @@ """authentik password stage""" -from typing import Any, Optional + +from typing import Any from django.contrib.auth import _clean_credentials from django.contrib.auth.backends import BaseBackend @@ -35,8 +36,8 @@ SESSION_KEY_INVALID_TRIES = "authentik/stages/password/user_invalid_tries" def authenticate( - request: HttpRequest, backends: list[str], stage: Optional[Stage] = None, **credentials: Any -) -> Optional[User]: + request: HttpRequest, backends: list[str], stage: Stage | None = None, **credentials: Any +) -> User | None: """If the given credentials are valid, return a User object. Customized version of django's authenticate, which accepts a list of backends""" diff --git a/authentik/stages/password/tests.py b/authentik/stages/password/tests.py index 4d8b9a38f6..0d48e0e74e 100644 --- a/authentik/stages/password/tests.py +++ b/authentik/stages/password/tests.py @@ -1,4 +1,5 @@ """password tests""" + from unittest.mock import MagicMock, patch from django.core.exceptions import PermissionDenied diff --git a/authentik/stages/password/urls.py b/authentik/stages/password/urls.py index 8e89847ca0..094df29ff5 100644 --- a/authentik/stages/password/urls.py +++ b/authentik/stages/password/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.password.api import PasswordStageViewSet api_urlpatterns = [("stages/password", PasswordStageViewSet)] diff --git a/authentik/stages/prompt/api.py b/authentik/stages/prompt/api.py index 7d484f5988..5dfeac90fb 100644 --- a/authentik/stages/prompt/api.py +++ b/authentik/stages/prompt/api.py @@ -1,4 +1,5 @@ """Prompt Stage API Views""" + from drf_spectacular.utils import extend_schema from rest_framework.decorators import action from rest_framework.request import Request @@ -8,7 +9,7 @@ from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin -from authentik.core.exceptions import PropertyMappingExpressionException +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.flows.api.stages import StageSerializer from authentik.flows.challenge import ChallengeTypes, HttpChallengeResponse from authentik.flows.planner import FlowPlan diff --git a/authentik/stages/prompt/apps.py b/authentik/stages/prompt/apps.py index c584b2968c..d2f794ef76 100644 --- a/authentik/stages/prompt/apps.py +++ b/authentik/stages/prompt/apps.py @@ -1,4 +1,5 @@ """authentik prompt stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/prompt/models.py b/authentik/stages/prompt/models.py index 3005c157d5..1a4a6c1123 100644 --- a/authentik/stages/prompt/models.py +++ b/authentik/stages/prompt/models.py @@ -1,5 +1,6 @@ """prompt models""" -from typing import Any, Optional, Type + +from typing import Any, Type # noqa: UP035 from urllib.parse import urlparse, urlunparse from uuid import uuid4 @@ -22,8 +23,8 @@ from rest_framework.fields import ( from rest_framework.serializers import BaseSerializer from structlog.stdlib import get_logger -from authentik.core.exceptions import PropertyMappingExpressionException from authentik.core.expression.evaluator import PropertyMappingEvaluator +from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.core.models import User from authentik.flows.models import Stage from authentik.lib.models import SerializerModel @@ -142,7 +143,7 @@ class Prompt(SerializerModel): initial_value_expression = models.BooleanField(default=False) @property - def serializer(self) -> Type[BaseSerializer]: + def serializer(self) -> Type[BaseSerializer]: # noqa: UP006 from authentik.stages.prompt.api import PromptSerializer return PromptSerializer @@ -152,8 +153,8 @@ class Prompt(SerializerModel): prompt_context: dict, user: User, request: HttpRequest, - dry_run: Optional[bool] = False, - ) -> Optional[tuple[dict[str, Any]]]: + dry_run: bool | None = False, + ) -> tuple[dict[str, Any]] | None: """Get fully interpolated list of choices""" if self.type not in CHOICE_FIELDS: return None @@ -177,7 +178,7 @@ class Prompt(SerializerModel): if dry_run: raise wrapped from exc - if isinstance(raw_choices, (list, tuple, set)): + if isinstance(raw_choices, list | tuple | set): choices = raw_choices else: choices = [raw_choices] @@ -192,7 +193,7 @@ class Prompt(SerializerModel): prompt_context: dict, user: User, request: HttpRequest, - dry_run: Optional[bool] = False, + dry_run: bool | None = False, ) -> str: """Get fully interpolated placeholder""" if self.type in CHOICE_FIELDS: @@ -207,7 +208,7 @@ class Prompt(SerializerModel): try: return evaluator.evaluate(self.placeholder) except Exception as exc: # pylint:disable=broad-except - wrapped = PropertyMappingExpressionException(str(exc)) + wrapped = PropertyMappingExpressionException(str(exc), None) LOGGER.warning( "failed to evaluate prompt placeholder", exc=wrapped, @@ -221,7 +222,7 @@ class Prompt(SerializerModel): prompt_context: dict, user: User, request: HttpRequest, - dry_run: Optional[bool] = False, + dry_run: bool | None = False, ) -> str: """Get fully interpolated initial value""" @@ -257,50 +258,52 @@ class Prompt(SerializerModel): return value - def field(self, default: Optional[Any], choices: Optional[list[Any]] = None) -> CharField: + def field(self, default: Any | None, choices: list[Any] | None = None) -> CharField: """Get field type for Challenge and response. Choices are only valid for CHOICE_FIELDS.""" field_class = CharField kwargs = { "required": self.required, } - if self.type in (FieldTypes.TEXT, FieldTypes.TEXT_AREA): - kwargs["trim_whitespace"] = False - kwargs["allow_blank"] = not self.required - if self.type in (FieldTypes.TEXT_READ_ONLY, FieldTypes.TEXT_AREA_READ_ONLY): - field_class = ReadOnlyField - # required can't be set for ReadOnlyField - kwargs["required"] = False - if self.type == FieldTypes.EMAIL: - field_class = EmailField - kwargs["allow_blank"] = not self.required - if self.type == FieldTypes.NUMBER: - field_class = IntegerField - if self.type == FieldTypes.CHECKBOX: - field_class = BooleanField - kwargs["required"] = False + match self.type: + case FieldTypes.TEXT | FieldTypes.TEXT_AREA: + kwargs["trim_whitespace"] = False + kwargs["allow_blank"] = not self.required + case FieldTypes.TEXT_READ_ONLY, FieldTypes.TEXT_AREA_READ_ONLY: + field_class = ReadOnlyField + # required can't be set for ReadOnlyField + kwargs["required"] = False + case FieldTypes.EMAIL: + field_class = EmailField + kwargs["allow_blank"] = not self.required + case FieldTypes.NUMBER: + field_class = IntegerField + case FieldTypes.CHECKBOX: + field_class = BooleanField + kwargs["required"] = False + case FieldTypes.DATE: + field_class = DateField + case FieldTypes.DATE_TIME: + field_class = DateTimeField + case FieldTypes.FILE: + field_class = InlineFileField + case FieldTypes.SEPARATOR: + kwargs["required"] = False + kwargs["label"] = "" + case FieldTypes.HIDDEN: + field_class = HiddenField + kwargs["required"] = False + kwargs["default"] = self.placeholder + case FieldTypes.STATIC: + kwargs["default"] = self.placeholder + kwargs["required"] = False + kwargs["label"] = "" + + case FieldTypes.AK_LOCALE: + kwargs["allow_blank"] = True + if self.type in CHOICE_FIELDS: field_class = ChoiceField kwargs["choices"] = choices or [] - if self.type == FieldTypes.DATE: - field_class = DateField - if self.type == FieldTypes.DATE_TIME: - field_class = DateTimeField - if self.type == FieldTypes.FILE: - field_class = InlineFileField - if self.type == FieldTypes.SEPARATOR: - kwargs["required"] = False - kwargs["label"] = "" - if self.type == FieldTypes.HIDDEN: - field_class = HiddenField - kwargs["required"] = False - kwargs["default"] = self.placeholder - if self.type == FieldTypes.STATIC: - kwargs["default"] = self.placeholder - kwargs["required"] = False - kwargs["label"] = "" - - if self.type == FieldTypes.AK_LOCALE: - kwargs["allow_blank"] = True if default: kwargs["default"] = default @@ -336,7 +339,7 @@ class PromptStage(Stage): return PromptStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.prompt.stage import PromptStageView return PromptStageView diff --git a/authentik/stages/prompt/signals.py b/authentik/stages/prompt/signals.py index a98f249ba5..b2a05aaa54 100644 --- a/authentik/stages/prompt/signals.py +++ b/authentik/stages/prompt/signals.py @@ -1,4 +1,5 @@ """authentik prompt stage signals""" + from django.core.signals import Signal # Arguments: password: str, plan_context: dict[str, Any] diff --git a/authentik/stages/prompt/stage.py b/authentik/stages/prompt/stage.py index df0af1be70..05fd04f84a 100644 --- a/authentik/stages/prompt/stage.py +++ b/authentik/stages/prompt/stage.py @@ -1,7 +1,9 @@ """Prompt Stage Logic""" + +from collections.abc import Callable, Iterator from email.policy import Policy from types import MethodType -from typing import Any, Callable, Iterator +from typing import Any from django.db.models.query import QuerySet from django.http import HttpRequest, HttpResponse @@ -130,7 +132,7 @@ class PromptChallengeResponse(ChallengeResponse): password_fields: QuerySet[Prompt] = self.stage_instance.fields.filter( type=FieldTypes.PASSWORD ) - if password_fields.exists() and password_fields.count() == 2: + if password_fields.exists() and password_fields.count() == 2: # noqa: PLR2004 self._validate_password_fields(*[field.field_key for field in password_fields]) engine = ListPolicyEngine( @@ -148,22 +150,26 @@ class PromptChallengeResponse(ChallengeResponse): return attrs -def username_field_validator_factory() -> Callable[[PromptChallenge, str], Any]: +def username_field_validator_factory() -> Callable[[PromptChallengeResponse, str], Any]: """Return a `clean_` method for `field`. Clean method checks if username is taken already.""" - def username_field_validator(self: PromptChallenge, value: str) -> Any: + def username_field_validator(self: PromptChallengeResponse, value: str) -> Any: """Check for duplicate usernames""" - if User.objects.filter(username=value).exists(): + pending_user = self.stage.get_pending_user() + query = User.objects.all() + if pending_user.pk: + query = query.exclude(username=pending_user.username) + if query.filter(username=value).exists(): raise ValidationError("Username is already taken.") return value return username_field_validator -def password_single_validator_factory() -> Callable[[PromptChallenge, str], Any]: +def password_single_validator_factory() -> Callable[[PromptChallengeResponse, str], Any]: """Return a `clean_` method for `field`. Clean method checks if username is taken already.""" - def password_single_clean(self: PromptChallenge, value: str) -> Any: + def password_single_clean(self: PromptChallengeResponse, value: str) -> Any: """Send password validation signals for e.g. LDAP Source""" password_validate.send(sender=self, password=value, plan_context=self.plan.context) return value diff --git a/authentik/stages/prompt/tests.py b/authentik/stages/prompt/tests.py index 43232fc753..564e573e8d 100644 --- a/authentik/stages/prompt/tests.py +++ b/authentik/stages/prompt/tests.py @@ -1,4 +1,5 @@ """Prompt tests""" + from unittest.mock import MagicMock, patch from django.test import RequestFactory @@ -22,7 +23,6 @@ from authentik.stages.prompt.stage import ( ) -# pylint: disable=too-many-public-methods class TestPromptStage(FlowTestCase): """Prompt tests""" diff --git a/authentik/stages/prompt/urls.py b/authentik/stages/prompt/urls.py index dca48c8ade..61d0fe6215 100644 --- a/authentik/stages/prompt/urls.py +++ b/authentik/stages/prompt/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.prompt.api import PromptStageViewSet, PromptViewSet api_urlpatterns = [ diff --git a/authentik/stages/user_delete/api.py b/authentik/stages/user_delete/api.py index 1c557d7146..4f931154e4 100644 --- a/authentik/stages/user_delete/api.py +++ b/authentik/stages/user_delete/api.py @@ -1,4 +1,5 @@ """User Delete Stage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/user_delete/apps.py b/authentik/stages/user_delete/apps.py index b1ca8455cd..e73dbfaab9 100644 --- a/authentik/stages/user_delete/apps.py +++ b/authentik/stages/user_delete/apps.py @@ -1,4 +1,5 @@ """authentik delete stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/user_delete/models.py b/authentik/stages/user_delete/models.py index 154e4f9ae4..be7aec4d35 100644 --- a/authentik/stages/user_delete/models.py +++ b/authentik/stages/user_delete/models.py @@ -18,7 +18,7 @@ class UserDeleteStage(Stage): return UserDeleteStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.user_delete.stage import UserDeleteStageView return UserDeleteStageView diff --git a/authentik/stages/user_delete/stage.py b/authentik/stages/user_delete/stage.py index a17c98addb..3ea73f1268 100644 --- a/authentik/stages/user_delete/stage.py +++ b/authentik/stages/user_delete/stage.py @@ -1,4 +1,5 @@ """Delete stage logic""" + from django.contrib import messages from django.contrib.auth import logout from django.http import HttpRequest, HttpResponse diff --git a/authentik/stages/user_delete/tests.py b/authentik/stages/user_delete/tests.py index 832b8d0173..b0ff6ff09b 100644 --- a/authentik/stages/user_delete/tests.py +++ b/authentik/stages/user_delete/tests.py @@ -1,4 +1,5 @@ """delete tests""" + from unittest.mock import patch from django.urls import reverse diff --git a/authentik/stages/user_delete/urls.py b/authentik/stages/user_delete/urls.py index e629a5220e..bf45df6540 100644 --- a/authentik/stages/user_delete/urls.py +++ b/authentik/stages/user_delete/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.user_delete.api import UserDeleteStageViewSet api_urlpatterns = [("stages/user_delete", UserDeleteStageViewSet)] diff --git a/authentik/stages/user_login/api.py b/authentik/stages/user_login/api.py index dad5f777c0..4107b3d66b 100644 --- a/authentik/stages/user_login/api.py +++ b/authentik/stages/user_login/api.py @@ -1,4 +1,5 @@ """Login Stage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/user_login/apps.py b/authentik/stages/user_login/apps.py index 1fcc87d43a..a8a65ef4fe 100644 --- a/authentik/stages/user_login/apps.py +++ b/authentik/stages/user_login/apps.py @@ -1,4 +1,5 @@ """authentik login stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/user_login/middleware.py b/authentik/stages/user_login/middleware.py index 73e42e1acb..649c4a0c63 100644 --- a/authentik/stages/user_login/middleware.py +++ b/authentik/stages/user_login/middleware.py @@ -1,4 +1,5 @@ """Sessions bound to ASN/Network and GeoIP/Continent/etc""" + from django.conf import settings from django.contrib.auth.middleware import AuthenticationMiddleware from django.contrib.auth.signals import user_logged_out @@ -22,8 +23,7 @@ LOGGER = get_logger() class SessionBindingBroken(SentryIgnoredException): """Session binding was broken due to specified `reason`""" - # pylint: disable=too-many-arguments - def __init__( + def __init__( # noqa: PLR0913 self, reason: str, old_value: str, new_value: str, old_ip: str, new_ip: str ) -> None: self.reason = reason diff --git a/authentik/stages/user_login/models.py b/authentik/stages/user_login/models.py index 27bb6f3bf8..025e960763 100644 --- a/authentik/stages/user_login/models.py +++ b/authentik/stages/user_login/models.py @@ -71,7 +71,7 @@ class UserLoginStage(Stage): return UserLoginStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.user_login.stage import UserLoginStageView return UserLoginStageView diff --git a/authentik/stages/user_login/stage.py b/authentik/stages/user_login/stage.py index f771f8faaf..7669acdb66 100644 --- a/authentik/stages/user_login/stage.py +++ b/authentik/stages/user_login/stage.py @@ -1,4 +1,5 @@ """Login stage logic""" + from datetime import timedelta from django.contrib import messages @@ -8,6 +9,7 @@ from django.utils.translation import gettext as _ from rest_framework.fields import BooleanField, CharField from authentik.core.models import AuthenticatedSession, User +from authentik.events.middleware import audit_ignore from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, PLAN_CONTEXT_SOURCE from authentik.flows.stage import ChallengeStageView @@ -94,11 +96,14 @@ class UserLoginStageView(ChallengeStageView): self.logger.warning("User is not active, login will not work.") delta = self.set_session_duration(remember) self.set_session_ip() - login( - self.request, - user, - backend=backend, - ) + # the `user_logged_in` signal will update the user to write the `last_login` field + # which we don't want to log as we already have a dedicated login event + with audit_ignore(): + login( + self.request, + user, + backend=backend, + ) self.logger.debug( "Logged in", backend=backend, diff --git a/authentik/stages/user_login/tests.py b/authentik/stages/user_login/tests.py index b61f89fd59..e9b02b483c 100644 --- a/authentik/stages/user_login/tests.py +++ b/authentik/stages/user_login/tests.py @@ -1,4 +1,5 @@ """login tests""" + from time import sleep from unittest.mock import patch @@ -132,13 +133,14 @@ class TestUserLoginStage(FlowTestCase): reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), data={"remember_me": True}, ) + _now = now().timestamp() self.assertEqual(response.status_code, 200) self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) self.assertNotEqual(list(self.client.session.keys()), []) session_key = self.client.session.session_key session = AuthenticatedSession.objects.filter(session_key=session_key).first() self.assertAlmostEqual( - session.expires.timestamp() - now().timestamp(), + session.expires.timestamp() - _now, timedelta_from_string(self.stage.session_duration).total_seconds() + timedelta_from_string(self.stage.remember_me_offset).total_seconds(), delta=1, diff --git a/authentik/stages/user_login/urls.py b/authentik/stages/user_login/urls.py index 63e21c7466..2db9f89bed 100644 --- a/authentik/stages/user_login/urls.py +++ b/authentik/stages/user_login/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.user_login.api import UserLoginStageViewSet api_urlpatterns = [ diff --git a/authentik/stages/user_logout/api.py b/authentik/stages/user_logout/api.py index 2168df0fb6..07a8b39893 100644 --- a/authentik/stages/user_logout/api.py +++ b/authentik/stages/user_logout/api.py @@ -1,4 +1,5 @@ """Logout Stage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/user_logout/apps.py b/authentik/stages/user_logout/apps.py index 467b4a189b..1388728a58 100644 --- a/authentik/stages/user_logout/apps.py +++ b/authentik/stages/user_logout/apps.py @@ -1,4 +1,5 @@ """authentik logout stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/user_logout/models.py b/authentik/stages/user_logout/models.py index 76e6f0db39..92fd36c99a 100644 --- a/authentik/stages/user_logout/models.py +++ b/authentik/stages/user_logout/models.py @@ -17,7 +17,7 @@ class UserLogoutStage(Stage): return UserLogoutStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.user_logout.stage import UserLogoutStageView return UserLogoutStageView diff --git a/authentik/stages/user_logout/stage.py b/authentik/stages/user_logout/stage.py index f0cf806664..84bba66dd3 100644 --- a/authentik/stages/user_logout/stage.py +++ b/authentik/stages/user_logout/stage.py @@ -1,4 +1,5 @@ """Logout stage logic""" + from django.contrib.auth import logout from django.http import HttpRequest, HttpResponse diff --git a/authentik/stages/user_logout/tests.py b/authentik/stages/user_logout/tests.py index fdca95e898..c571354d62 100644 --- a/authentik/stages/user_logout/tests.py +++ b/authentik/stages/user_logout/tests.py @@ -1,4 +1,5 @@ """logout tests""" + from django.urls import reverse from authentik.core.tests.utils import create_test_admin_user, create_test_flow @@ -36,7 +37,6 @@ class TestUserLogoutStage(FlowTestCase): reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) ) - # pylint: disable=no-member self.assertEqual(response.status_code, 200) self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) @@ -53,6 +53,5 @@ class TestUserLogoutStage(FlowTestCase): reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) ) - # pylint: disable=no-member self.assertEqual(response.status_code, 200) self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) diff --git a/authentik/stages/user_logout/urls.py b/authentik/stages/user_logout/urls.py index 76a3b3ceb1..074f5a8bb0 100644 --- a/authentik/stages/user_logout/urls.py +++ b/authentik/stages/user_logout/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.user_logout.api import UserLogoutStageViewSet api_urlpatterns = [("stages/user_logout", UserLogoutStageViewSet)] diff --git a/authentik/stages/user_write/api.py b/authentik/stages/user_write/api.py index 1abca9e9f2..43d112aeb2 100644 --- a/authentik/stages/user_write/api.py +++ b/authentik/stages/user_write/api.py @@ -1,4 +1,5 @@ """User Write Stage API Views""" + from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin diff --git a/authentik/stages/user_write/apps.py b/authentik/stages/user_write/apps.py index 62e933daeb..c5cbb244c5 100644 --- a/authentik/stages/user_write/apps.py +++ b/authentik/stages/user_write/apps.py @@ -1,4 +1,5 @@ """authentik write stage app config""" + from django.apps import AppConfig diff --git a/authentik/stages/user_write/models.py b/authentik/stages/user_write/models.py index eb1dfd2c77..a4e94a71b9 100644 --- a/authentik/stages/user_write/models.py +++ b/authentik/stages/user_write/models.py @@ -55,7 +55,7 @@ class UserWriteStage(Stage): return UserWriteStageSerializer @property - def type(self) -> type[View]: + def view(self) -> type[View]: from authentik.stages.user_write.stage import UserWriteStageView return UserWriteStageView diff --git a/authentik/stages/user_write/signals.py b/authentik/stages/user_write/signals.py index 34e7cfdba3..988931006b 100644 --- a/authentik/stages/user_write/signals.py +++ b/authentik/stages/user_write/signals.py @@ -1,4 +1,5 @@ """authentik user_write signals""" + from django.core.signals import Signal # Arguments: request: HttpRequest, user: User, data: dict[str, Any], created: bool diff --git a/authentik/stages/user_write/stage.py b/authentik/stages/user_write/stage.py index 5117f03583..77c0ed25af 100644 --- a/authentik/stages/user_write/stage.py +++ b/authentik/stages/user_write/stage.py @@ -1,5 +1,6 @@ """Write stage logic""" -from typing import Any, Optional + +from typing import Any from django.contrib.auth import update_session_auth_hash from django.db import transaction @@ -11,6 +12,7 @@ from rest_framework.exceptions import ValidationError from authentik.core.middleware import SESSION_KEY_IMPERSONATE_USER from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection, UserTypes from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION +from authentik.events.utils import sanitize_item from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import StageView from authentik.flows.views.executor import FlowExecutorView @@ -46,9 +48,9 @@ class UserWriteStageView(StageView): # this is just a sanity check to ensure that is removed if parts[0] == "attributes": parts = parts[1:] - set_path_in_dict(user.attributes, ".".join(parts), value) + set_path_in_dict(user.attributes, ".".join(parts), sanitize_item(value)) - def ensure_user(self) -> tuple[Optional[User], bool]: + def ensure_user(self) -> tuple[User | None, bool]: """Ensure a user exists""" user_created = False path = self.executor.plan.context.get( diff --git a/authentik/stages/user_write/tests.py b/authentik/stages/user_write/tests.py index 0fe661e6bd..1fa3f18888 100644 --- a/authentik/stages/user_write/tests.py +++ b/authentik/stages/user_write/tests.py @@ -1,4 +1,5 @@ """write tests""" + from unittest.mock import patch from django.urls import reverse diff --git a/authentik/stages/user_write/urls.py b/authentik/stages/user_write/urls.py index c68a06e8c7..c6d6c79e8f 100644 --- a/authentik/stages/user_write/urls.py +++ b/authentik/stages/user_write/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from authentik.stages.user_write.api import UserWriteStageViewSet api_urlpatterns = [("stages/user_write", UserWriteStageViewSet)] diff --git a/authentik/tenants/api/domains.py b/authentik/tenants/api/domains.py index dc0fa244d6..9532edd7ba 100644 --- a/authentik/tenants/api/domains.py +++ b/authentik/tenants/api/domains.py @@ -1,4 +1,5 @@ """Serializer for tenants models""" + from django.apps import apps from django.http import HttpResponseNotFound from rest_framework.filters import OrderingFilter, SearchFilter diff --git a/authentik/tenants/api/settings.py b/authentik/tenants/api/settings.py index bcd5da66d2..db3b9c3342 100644 --- a/authentik/tenants/api/settings.py +++ b/authentik/tenants/api/settings.py @@ -1,4 +1,5 @@ """Serializer for tenants models""" + from django_tenants.utils import get_public_schema_name from rest_framework.generics import RetrieveUpdateAPIView from rest_framework.permissions import SAFE_METHODS @@ -24,6 +25,8 @@ class SettingsSerializer(ModelSerializer): "impersonation", "user_directory_fields", "user_directory_attributes", + "default_token_duration", + "default_token_length", ] diff --git a/authentik/tenants/api/tenants.py b/authentik/tenants/api/tenants.py index 5662a392b8..33e28f81d9 100644 --- a/authentik/tenants/api/tenants.py +++ b/authentik/tenants/api/tenants.py @@ -1,4 +1,5 @@ """Serializer for tenants models""" + from datetime import timedelta from hmac import compare_digest diff --git a/authentik/tenants/apps.py b/authentik/tenants/apps.py index 851ae1e153..7b064b7d9f 100644 --- a/authentik/tenants/apps.py +++ b/authentik/tenants/apps.py @@ -1,4 +1,5 @@ """authentik tenants app""" + from django.db import DEFAULT_DB_ALIAS from django.db.models.signals import post_migrate from django_tenants.utils import get_public_schema_name @@ -15,7 +16,7 @@ def ensure_default_tenant(*args, using=DEFAULT_DB_ALIAS, **kwargs): with schema_context(get_public_schema_name()): Tenant.objects.using(using).update_or_create( defaults={"name": "Default", "ready": True}, - schema_name="public", + schema_name=get_public_schema_name(), ) @@ -27,11 +28,8 @@ class AuthentikTenantsConfig(ManagedAppConfig): verbose_name = "authentik Tenants" default = True - def reconcile_global_load_checks(self): - """Load tenant checks""" - self.import_module("authentik.tenants.checks") - - def reconcile_global_default_tenant(self): + @ManagedAppConfig.reconcile_global + def default_tenant(self): """Make sure default tenant exists, especially after a migration""" post_migrate.connect(ensure_default_tenant) ensure_default_tenant() diff --git a/authentik/tenants/checks.py b/authentik/tenants/checks.py index 7b63c261d6..72c7228f51 100644 --- a/authentik/tenants/checks.py +++ b/authentik/tenants/checks.py @@ -1,4 +1,5 @@ """authentik tenants system checks""" + from django.core.checks import Error, register from authentik.lib.config import CONFIG diff --git a/authentik/tenants/db.py b/authentik/tenants/db.py new file mode 100644 index 0000000000..e6735a01de --- /dev/null +++ b/authentik/tenants/db.py @@ -0,0 +1,29 @@ +from random import choice + +from django.conf import settings + + +class FailoverRouter: + """Support an primary/read-replica PostgreSQL setup (reading from replicas + and write to primary only)""" + + def __init__(self) -> None: + super().__init__() + self.database_aliases = set(settings.DATABASES.keys()) + self.read_replica_aliases = list(self.database_aliases - {"default"}) + self.replica_enabled = len(self.read_replica_aliases) > 0 + + def db_for_read(self, model, **hints): + if not self.replica_enabled: + return "default" + return choice(self.read_replica_aliases) # nosec + + def db_for_write(self, model, **hints): + return "default" + + def allow_relation(self, obj1, obj2, **hints): + """Relations between objects are allowed if both objects are + in the primary/replica pool.""" + if obj1._state.db in self.database_aliases and obj2._state.db in self.database_aliases: + return True + return None diff --git a/authentik/tenants/management/__init__.py b/authentik/tenants/management/__init__.py index 032509107f..2f59bac740 100644 --- a/authentik/tenants/management/__init__.py +++ b/authentik/tenants/management/__init__.py @@ -1,4 +1,5 @@ """authentik tenants management command utils""" + from django.core.management.base import BaseCommand from django.db import connection from django_tenants.utils import get_public_schema_name @@ -24,7 +25,7 @@ class TenantCommand(BaseCommand): def handle(self, *args, **options): verbosity = int(options.get("verbosity")) - # pylint: disable=no-member + schema_name = options["schema_name"] or self.schema_name connection.set_schema_to_public() if verbosity >= 1: diff --git a/authentik/tenants/migrations/0002_tenant_default_token_duration_and_more.py b/authentik/tenants/migrations/0002_tenant_default_token_duration_and_more.py new file mode 100644 index 0000000000..0aa7accfc8 --- /dev/null +++ b/authentik/tenants/migrations/0002_tenant_default_token_duration_and_more.py @@ -0,0 +1,35 @@ +# Generated by Django 5.0.2 on 2024-02-20 08:26 + +import django.core.validators +from django.db import migrations, models + +import authentik.lib.utils.time +from authentik.lib.config import CONFIG + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_tenants", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="tenant", + name="default_token_duration", + field=models.TextField( + default=CONFIG.get("default_token_duration", "minutes=30"), + help_text="Default token duration", + validators=[authentik.lib.utils.time.timedelta_string_validator], + ), + ), + migrations.AddField( + model_name="tenant", + name="default_token_length", + field=models.PositiveIntegerField( + default=CONFIG.get_int("default_token_length", 60), + help_text="Default token length", + validators=[django.core.validators.MinValueValidator(1)], + ), + ), + ] diff --git a/authentik/tenants/migrations/0003_alter_tenant_default_token_duration.py b/authentik/tenants/migrations/0003_alter_tenant_default_token_duration.py new file mode 100644 index 0000000000..30fb9b92ff --- /dev/null +++ b/authentik/tenants/migrations/0003_alter_tenant_default_token_duration.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.4 on 2024-05-01 15:32 + +import authentik.lib.utils.time +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_tenants", "0002_tenant_default_token_duration_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="tenant", + name="default_token_duration", + field=models.TextField( + default="days=1", + help_text="Default token duration", + validators=[authentik.lib.utils.time.timedelta_string_validator], + ), + ), + ] diff --git a/authentik/tenants/migrations/0004_merge_20240524_1807.py b/authentik/tenants/migrations/0004_merge_20240524_1807.py new file mode 100644 index 0000000000..d48b0fed21 --- /dev/null +++ b/authentik/tenants/migrations/0004_merge_20240524_1807.py @@ -0,0 +1,13 @@ +# Generated by Django 5.0.6 on 2024-05-24 18:07 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_tenants", "0002_tenant_user_directory_and_more"), + ("authentik_tenants", "0003_alter_tenant_default_token_duration"), + ] + + operations = [] diff --git a/authentik/tenants/models.py b/authentik/tenants/models.py index 5408bde4af..38e8c647ce 100644 --- a/authentik/tenants/models.py +++ b/authentik/tenants/models.py @@ -1,9 +1,11 @@ """Tenant models""" + import re from uuid import uuid4 from django.apps import apps from django.core.exceptions import ValidationError +from django.core.validators import MinValueValidator from django.db import models from django.db.utils import IntegrityError from django.dispatch import receiver @@ -21,6 +23,9 @@ LOGGER = get_logger() VALID_SCHEMA_NAME = re.compile(r"^t_[a-z0-9]{1,61}$") +DEFAULT_TOKEN_DURATION = "days=1" # nosec +DEFAULT_TOKEN_LENGTH = 60 + def _validate_schema_name(name): if not VALID_SCHEMA_NAME.match(name): @@ -90,7 +95,16 @@ class Tenant(TenantMixin, SerializerModel): blank=True, ) user_directory_attributes = models.JSONField( - help_text=_("Attributes to show in the user directory."), default=list, blank=True + help_text=_("Attributes to show in the user directory."), default=list, blank=True) + default_token_duration = models.TextField( + help_text=_("Default token duration"), + default=DEFAULT_TOKEN_DURATION, + validators=[timedelta_string_validator], + ) + default_token_length = models.PositiveIntegerField( + help_text=_("Default token length"), + default=DEFAULT_TOKEN_LENGTH, + validators=[MinValueValidator(1)], ) def save(self, *args, **kwargs): @@ -98,11 +112,6 @@ class Tenant(TenantMixin, SerializerModel): raise IntegrityError("Cannot create schema named template") super().save(*args, **kwargs) - def delete(self, *args, **kwargs): - if self.schema_name in ("public", "template"): - raise IntegrityError("Cannot delete schema public or template") - super().delete(*args, **kwargs) - @property def serializer(self) -> Serializer: from authentik.tenants.api.tenants import TenantSerializer @@ -147,7 +156,7 @@ def tenant_needs_sync(sender, tenant, **kwargs): with tenant: for app in apps.get_app_configs(): if isinstance(app, ManagedAppConfig): - app._reconcile(ManagedAppConfig.RECONCILE_TENANT_PREFIX) + app._reconcile(ManagedAppConfig.RECONCILE_TENANT_CATEGORY) tenant.ready = True tenant.save() diff --git a/authentik/tenants/scheduler.py b/authentik/tenants/scheduler.py index b6189dfa5f..753831ae0b 100644 --- a/authentik/tenants/scheduler.py +++ b/authentik/tenants/scheduler.py @@ -1,7 +1,9 @@ """Tenant-aware Celery beat scheduler""" + from tenant_schemas_celery.scheduler import ( TenantAwarePersistentScheduler as BaseTenantAwarePersistentScheduler, ) +from tenant_schemas_celery.scheduler import TenantAwareScheduleEntry class TenantAwarePersistentScheduler(BaseTenantAwarePersistentScheduler): @@ -10,3 +12,11 @@ class TenantAwarePersistentScheduler(BaseTenantAwarePersistentScheduler): @classmethod def get_queryset(cls): return super().get_queryset().filter(ready=True) + + def apply_entry(self, entry: TenantAwareScheduleEntry, producer=None): + # https://github.com/maciej-gol/tenant-schemas-celery/blob/master/tenant_schemas_celery/scheduler.py#L85 + # When (as by default) no tenant schemas are set, the public schema is excluded + # so we need to explicitly include it here, otherwise the task is not executed + if entry.tenant_schemas is None: + entry.tenant_schemas = self.get_queryset().values_list("schema_name", flat=True) + return super().apply_entry(entry, producer) diff --git a/authentik/tenants/signals.py b/authentik/tenants/signals.py new file mode 100644 index 0000000000..643ae610ab --- /dev/null +++ b/authentik/tenants/signals.py @@ -0,0 +1,14 @@ +"""authentik tenants signals""" + +from django.db import models +from django.db.models.signals import pre_delete +from django.dispatch import receiver +from django_tenants.utils import get_public_schema_name + +from authentik.tenants.models import Tenant + + +@receiver(pre_delete, sender=Tenant) +def tenants_ensure_no_default_delete(sender, instance: Tenant, **kwargs): + if instance.schema_name == get_public_schema_name(): + raise models.ProtectedError("Cannot delete schema public", instance) diff --git a/authentik/tenants/tests/test_api.py b/authentik/tenants/tests/test_api.py index 263b9f2498..87f8490186 100644 --- a/authentik/tenants/tests/test_api.py +++ b/authentik/tenants/tests/test_api.py @@ -1,4 +1,5 @@ """Test Tenant API""" + from json import loads from django.urls import reverse diff --git a/authentik/tenants/tests/test_domain.py b/authentik/tenants/tests/test_domain.py index 36d3fa8115..03f6d224bc 100644 --- a/authentik/tenants/tests/test_domain.py +++ b/authentik/tenants/tests/test_domain.py @@ -1,4 +1,5 @@ """Test Domain API""" + from json import loads from django.urls import reverse diff --git a/authentik/tenants/tests/test_event_retention.py b/authentik/tenants/tests/test_event_retention.py index daaa908f10..7900e6ff2f 100644 --- a/authentik/tenants/tests/test_event_retention.py +++ b/authentik/tenants/tests/test_event_retention.py @@ -1,4 +1,5 @@ """Test event retention""" + from django.test.client import RequestFactory from django_tenants.utils import get_public_schema_name from rest_framework.test import APITestCase diff --git a/authentik/tenants/tests/test_recovery.py b/authentik/tenants/tests/test_recovery.py index 572753b893..e100dbd3c7 100644 --- a/authentik/tenants/tests/test_recovery.py +++ b/authentik/tenants/tests/test_recovery.py @@ -1,4 +1,5 @@ """Test Tenant Recovery API""" + from json import loads from django.urls import reverse @@ -70,7 +71,7 @@ class TestRecovery(TenantAPITestCase): body = loads(response.content.decode()) token = Token.objects.get(intent=TokenIntents.INTENT_RECOVERY, user=self.user) self.assertIn(token.key, body["url"]) - self.assertEqual(len(Token.objects.all()), 1) + self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 1) @CONFIG.patch("outposts.disable_embedded_outpost", True) @CONFIG.patch("tenants.enabled", True) @@ -86,4 +87,4 @@ class TestRecovery(TenantAPITestCase): headers=HEADERS, ) self.assertEqual(response.status_code, 404) - self.assertEqual(len(Token.objects.all()), 0) + self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 0) diff --git a/authentik/tenants/urls.py b/authentik/tenants/urls.py index 8cac045520..b75ed6b43b 100644 --- a/authentik/tenants/urls.py +++ b/authentik/tenants/urls.py @@ -1,4 +1,5 @@ """API URLs""" + from django.conf import settings from django.urls import path diff --git a/authentik/tenants/utils.py b/authentik/tenants/utils.py index aabc2e931f..7b5e000a8c 100644 --- a/authentik/tenants/utils.py +++ b/authentik/tenants/utils.py @@ -1,9 +1,26 @@ """Tenant utils""" -from django.db import connection +from django.db import connection +from django_tenants.utils import get_public_schema_name + +from authentik.lib.config import CONFIG +from authentik.root.install_id import get_install_id from authentik.tenants.models import Tenant def get_current_tenant() -> Tenant: """Get tenant for current request""" return Tenant.objects.get(schema_name=connection.schema_name) + + +def get_unique_identifier() -> str: + """Get a globally unique identifier that does not change""" + install_id = get_install_id() + if CONFIG.get_bool("tenants.enabled"): + tenant = get_current_tenant() + # Only use tenant's uuid if this request is not from the "public" + # (i.e. default) tenant + if tenant.schema_name == get_public_schema_name(): + return install_id + return str(get_current_tenant().tenant_uuid) + return install_id diff --git a/blueprints/default/default-brand.yaml b/blueprints/default/default-brand.yaml index c9c3a3ac6d..835427a294 100644 --- a/blueprints/default/default-brand.yaml +++ b/blueprints/default/default-brand.yaml @@ -26,6 +26,9 @@ entries: !Find [authentik_flows.flow, [slug, default-user-settings-flow]] identifiers: domain: authentik-default - default: True + default: true state: created + conditions: + # Only create default brand if no other default brand exists + - !Condition [NOR, !Find [authentik_brands.brand, [default, True]]] model: authentik_brands.brand diff --git a/blueprints/default/flow-default-authenticator-webauthn-setup.yaml b/blueprints/default/flow-default-authenticator-webauthn-setup.yaml index ef712e43a8..3706ec4d18 100644 --- a/blueprints/default/flow-default-authenticator-webauthn-setup.yaml +++ b/blueprints/default/flow-default-authenticator-webauthn-setup.yaml @@ -17,7 +17,7 @@ entries: identifiers: name: default-authenticator-webauthn-setup id: default-authenticator-webauthn-setup - model: authentik_stages_authenticator_webauthn.authenticatewebauthnstage + model: authentik_stages_authenticator_webauthn.authenticatorwebauthnstage - identifiers: order: 0 stage: !KeyOf default-authenticator-webauthn-setup diff --git a/blueprints/default/flow-default-source-enrollment.yaml b/blueprints/default/flow-default-source-enrollment.yaml index 9618f16ad5..b789bd5714 100644 --- a/blueprints/default/flow-default-source-enrollment.yaml +++ b/blueprints/default/flow-default-source-enrollment.yaml @@ -16,7 +16,7 @@ entries: placeholder: Username placeholder_expression: false required: true - type: text + type: username field_key: username label: Username identifiers: diff --git a/blueprints/default/flow-default-user-settings-flow.yaml b/blueprints/default/flow-default-user-settings-flow.yaml index ac2d79125a..06d8b17ae9 100644 --- a/blueprints/default/flow-default-user-settings-flow.yaml +++ b/blueprints/default/flow-default-user-settings-flow.yaml @@ -22,7 +22,7 @@ entries: return '' initial_value_expression: true required: true - type: text + type: username field_key: username label: Username identifiers: @@ -93,21 +93,21 @@ entries: prompt_data = request.context.get("prompt_data") if not request.user.group_attributes(request.http_request).get( - USER_ATTRIBUTE_CHANGE_EMAIL, request.tenant.default_user_change_email + USER_ATTRIBUTE_CHANGE_EMAIL, request.http_request.tenant.default_user_change_email ): if prompt_data.get("email") != request.user.email: ak_message("Not allowed to change email address.") return False if not request.user.group_attributes(request.http_request).get( - USER_ATTRIBUTE_CHANGE_NAME, request.tenant.default_user_change_name + USER_ATTRIBUTE_CHANGE_NAME, request.http_request.tenant.default_user_change_name ): if prompt_data.get("name") != request.user.name: ak_message("Not allowed to change name.") return False if not request.user.group_attributes(request.http_request).get( - USER_ATTRIBUTE_CHANGE_USERNAME, request.tenant.default_user_change_username + USER_ATTRIBUTE_CHANGE_USERNAME, request.http_request.tenant.default_user_change_username ): if prompt_data.get("username") != request.user.username: ak_message("Not allowed to change username.") diff --git a/blueprints/schema.json b/blueprints/schema.json index e54530a04f..32d40e4d4e 100644 --- a/blueprints/schema.json +++ b/blueprints/schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://goauthentik.io/blueprints/schema.json", "type": "object", - "title": "authentik Blueprint schema", + "title": "authentik 2024.4.2 Blueprint schema", "required": [ "version", "entries" @@ -115,191 +115,6 @@ } } }, - { - "type": "object", - "required": [ - "model", - "identifiers" - ], - "properties": { - "model": { - "const": "authentik_events.event" - }, - "id": { - "type": "string" - }, - "state": { - "type": "string", - "enum": [ - "absent", - "present", - "created", - "must_created" - ], - "default": "present" - }, - "conditions": { - "type": "array", - "items": { - "type": "boolean" - } - }, - "attrs": { - "$ref": "#/$defs/model_authentik_events.event" - }, - "identifiers": { - "$ref": "#/$defs/model_authentik_events.event" - } - } - }, - { - "type": "object", - "required": [ - "model", - "identifiers" - ], - "properties": { - "model": { - "const": "authentik_events.notificationtransport" - }, - "id": { - "type": "string" - }, - "state": { - "type": "string", - "enum": [ - "absent", - "present", - "created", - "must_created" - ], - "default": "present" - }, - "conditions": { - "type": "array", - "items": { - "type": "boolean" - } - }, - "attrs": { - "$ref": "#/$defs/model_authentik_events.notificationtransport" - }, - "identifiers": { - "$ref": "#/$defs/model_authentik_events.notificationtransport" - } - } - }, - { - "type": "object", - "required": [ - "model", - "identifiers" - ], - "properties": { - "model": { - "const": "authentik_events.notification" - }, - "id": { - "type": "string" - }, - "state": { - "type": "string", - "enum": [ - "absent", - "present", - "created", - "must_created" - ], - "default": "present" - }, - "conditions": { - "type": "array", - "items": { - "type": "boolean" - } - }, - "attrs": { - "$ref": "#/$defs/model_authentik_events.notification" - }, - "identifiers": { - "$ref": "#/$defs/model_authentik_events.notification" - } - } - }, - { - "type": "object", - "required": [ - "model", - "identifiers" - ], - "properties": { - "model": { - "const": "authentik_events.notificationrule" - }, - "id": { - "type": "string" - }, - "state": { - "type": "string", - "enum": [ - "absent", - "present", - "created", - "must_created" - ], - "default": "present" - }, - "conditions": { - "type": "array", - "items": { - "type": "boolean" - } - }, - "attrs": { - "$ref": "#/$defs/model_authentik_events.notificationrule" - }, - "identifiers": { - "$ref": "#/$defs/model_authentik_events.notificationrule" - } - } - }, - { - "type": "object", - "required": [ - "model", - "identifiers" - ], - "properties": { - "model": { - "const": "authentik_events.notificationwebhookmapping" - }, - "id": { - "type": "string" - }, - "state": { - "type": "string", - "enum": [ - "absent", - "present", - "created", - "must_created" - ], - "default": "present" - }, - "conditions": { - "type": "array", - "items": { - "type": "boolean" - } - }, - "attrs": { - "$ref": "#/$defs/model_authentik_events.notificationwebhookmapping" - }, - "identifiers": { - "$ref": "#/$defs/model_authentik_events.notificationwebhookmapping" - } - } - }, { "type": "object", "required": [ @@ -1410,6 +1225,43 @@ } } }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_sources_scim.scimsource" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_sources_scim.scimsource" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_sources_scim.scimsource" + } + } + }, { "type": "object", "required": [ @@ -1751,7 +1603,7 @@ ], "properties": { "model": { - "const": "authentik_stages_authenticator_webauthn.authenticatewebauthnstage" + "const": "authentik_stages_authenticator_webauthn.authenticatorwebauthnstage" }, "id": { "type": "string" @@ -1773,10 +1625,10 @@ } }, "attrs": { - "$ref": "#/$defs/model_authentik_stages_authenticator_webauthn.authenticatewebauthnstage" + "$ref": "#/$defs/model_authentik_stages_authenticator_webauthn.authenticatorwebauthnstage" }, "identifiers": { - "$ref": "#/$defs/model_authentik_stages_authenticator_webauthn.authenticatewebauthnstage" + "$ref": "#/$defs/model_authentik_stages_authenticator_webauthn.authenticatorwebauthnstage" } } }, @@ -2668,6 +2520,154 @@ } } }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_providers_google_workspace.googleworkspaceprovider" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_providers_google_workspace.googleworkspaceprovider" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_providers_google_workspace.googleworkspaceprovider" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_providers_google_workspace.googleworkspaceprovidermapping" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_providers_google_workspace.googleworkspaceprovidermapping" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_providers_google_workspace.googleworkspaceprovidermapping" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_providers_microsoft_entra.microsoftentraprovider" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_providers_microsoft_entra.microsoftentraprovider" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_providers_microsoft_entra.microsoftentraprovider" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_providers_microsoft_entra.microsoftentraprovidermapping" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_providers_microsoft_entra.microsoftentraprovidermapping" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_providers_microsoft_entra.microsoftentraprovidermapping" + } + } + }, { "type": "object", "required": [ @@ -2779,6 +2779,228 @@ } } }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_stages_source.sourcestage" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_stages_source.sourcestage" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_stages_source.sourcestage" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_events.event" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_events.event" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_events.event" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_events.notificationtransport" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_events.notificationtransport" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_events.notificationtransport" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_events.notification" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_events.notification" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_events.notification" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_events.notificationrule" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_events.notificationrule" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_events.notificationrule" + } + } + }, + { + "type": "object", + "required": [ + "model", + "identifiers" + ], + "properties": { + "model": { + "const": "authentik_events.notificationwebhookmapping" + }, + "id": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "absent", + "present", + "created", + "must_created" + ], + "default": "present" + }, + "conditions": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "attrs": { + "$ref": "#/$defs/model_authentik_events.notificationwebhookmapping" + }, + "identifiers": { + "$ref": "#/$defs/model_authentik_events.notificationwebhookmapping" + } + } + }, { "type": "object", "required": [ @@ -2835,7 +3057,8 @@ "title": "Is primary" }, "tenant": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Tenant" } }, @@ -2863,249 +3086,6 @@ }, "required": [] }, - "model_authentik_events.event": { - "type": "object", - "properties": { - "user": { - "type": "object", - "additionalProperties": true, - "title": "User" - }, - "action": { - "type": "string", - "enum": [ - "login", - "login_failed", - "logout", - "user_write", - "suspicious_request", - "password_set", - "secret_view", - "secret_rotate", - "invitation_used", - "authorize_application", - "source_linked", - "impersonation_started", - "impersonation_ended", - "flow_execution", - "policy_execution", - "policy_exception", - "property_mapping_exception", - "system_task_execution", - "system_task_exception", - "system_exception", - "configuration_error", - "model_created", - "model_updated", - "model_deleted", - "email_sent", - "update_available", - "custom_" - ], - "title": "Action" - }, - "app": { - "type": "string", - "minLength": 1, - "title": "App" - }, - "context": { - "type": "object", - "additionalProperties": true, - "title": "Context" - }, - "client_ip": { - "type": [ - "string", - "null" - ], - "minLength": 1, - "title": "Client ip" - }, - "expires": { - "type": "string", - "format": "date-time", - "title": "Expires" - }, - "brand": { - "type": "object", - "additionalProperties": true, - "title": "Brand" - } - }, - "required": [] - }, - "model_authentik_events.notificationtransport": { - "type": "object", - "properties": { - "name": { - "type": "string", - "minLength": 1, - "title": "Name" - }, - "mode": { - "type": "string", - "enum": [ - "local", - "webhook", - "webhook_slack", - "email" - ], - "title": "Mode" - }, - "webhook_url": { - "type": "string", - "title": "Webhook url" - }, - "webhook_mapping": { - "type": "integer", - "title": "Webhook mapping" - }, - "send_once": { - "type": "boolean", - "title": "Send once", - "description": "Only send notification once, for example when sending a webhook into a chat channel." - } - }, - "required": [] - }, - "model_authentik_events.notification": { - "type": "object", - "properties": { - "event": { - "type": "object", - "properties": { - "user": { - "type": "object", - "additionalProperties": true, - "title": "User" - }, - "action": { - "type": "string", - "enum": [ - "login", - "login_failed", - "logout", - "user_write", - "suspicious_request", - "password_set", - "secret_view", - "secret_rotate", - "invitation_used", - "authorize_application", - "source_linked", - "impersonation_started", - "impersonation_ended", - "flow_execution", - "policy_execution", - "policy_exception", - "property_mapping_exception", - "system_task_execution", - "system_task_exception", - "system_exception", - "configuration_error", - "model_created", - "model_updated", - "model_deleted", - "email_sent", - "update_available", - "custom_" - ], - "title": "Action" - }, - "app": { - "type": "string", - "minLength": 1, - "title": "App" - }, - "context": { - "type": "object", - "additionalProperties": true, - "title": "Context" - }, - "client_ip": { - "type": [ - "string", - "null" - ], - "minLength": 1, - "title": "Client ip" - }, - "expires": { - "type": "string", - "format": "date-time", - "title": "Expires" - }, - "brand": { - "type": "object", - "additionalProperties": true, - "title": "Brand" - } - }, - "required": [ - "action", - "app" - ], - "title": "Event" - }, - "seen": { - "type": "boolean", - "title": "Seen" - } - }, - "required": [] - }, - "model_authentik_events.notificationrule": { - "type": "object", - "properties": { - "name": { - "type": "string", - "minLength": 1, - "title": "Name" - }, - "transports": { - "type": "array", - "items": { - "type": "integer", - "description": "Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI." - }, - "title": "Transports", - "description": "Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI." - }, - "severity": { - "type": "string", - "enum": [ - "notice", - "warning", - "alert" - ], - "title": "Severity", - "description": "Controls which severity level the created notifications will have." - }, - "group": { - "type": "integer", - "title": "Group", - "description": "Define which group of users this notification should be sent and shown to. If left empty, Notification won't ben sent." - } - }, - "required": [] - }, - "model_authentik_events.notificationwebhookmapping": { - "type": "object", - "properties": { - "name": { - "type": "string", - "minLength": 1, - "title": "Name" - }, - "expression": { - "type": "string", - "minLength": 1, - "title": "Expression" - } - }, - "required": [] - }, "model_authentik_flows.flow": { "type": "object", "properties": { @@ -3200,11 +3180,13 @@ "type": "object", "properties": { "target": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Target" }, "stage": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Stage" }, "evaluate_on_plan": { @@ -3264,12 +3246,14 @@ "description": "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system." }, "tls_verification": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Tls verification", "description": "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." }, "tls_authentication": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Tls authentication", "description": "Certificate/Key used for authentication. Can be left empty for no authentication." } @@ -3329,7 +3313,8 @@ "title": "Providers" }, "service_connection": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Service connection", "description": "Select Service-Connection authentik should use to manage this outpost. Leave empty if authentik should not handle the deployment." }, @@ -3453,7 +3438,6 @@ "authentik.admin", "authentik.api", "authentik.crypto", - "authentik.events", "authentik.flows", "authentik.outposts", "authentik.policies.dummy", @@ -3475,6 +3459,7 @@ "authentik.sources.oauth", "authentik.sources.plex", "authentik.sources.saml", + "authentik.sources.scim", "authentik.stages.authenticator", "authentik.stages.authenticator_duo", "authentik.stages.authenticator_sms", @@ -3500,7 +3485,11 @@ "authentik.core", "authentik.enterprise", "authentik.enterprise.audit", - "authentik.enterprise.providers.rac" + "authentik.enterprise.providers.google_workspace", + "authentik.enterprise.providers.microsoft_entra", + "authentik.enterprise.providers.rac", + "authentik.enterprise.stages.source", + "authentik.events" ], "title": "App", "description": "Match events created by selected application. When left empty, all applications are matched." @@ -3514,11 +3503,6 @@ null, "authentik_tenants.domain", "authentik_crypto.certificatekeypair", - "authentik_events.event", - "authentik_events.notificationtransport", - "authentik_events.notification", - "authentik_events.notificationrule", - "authentik_events.notificationwebhookmapping", "authentik_flows.flow", "authentik_flows.flowstagebinding", "authentik_outposts.dockerserviceconnection", @@ -3549,6 +3533,7 @@ "authentik_sources_plex.plexsourceconnection", "authentik_sources_saml.samlsource", "authentik_sources_saml.usersamlsourceconnection", + "authentik_sources_scim.scimsource", "authentik_stages_authenticator_duo.authenticatorduostage", "authentik_stages_authenticator_duo.duodevice", "authentik_stages_authenticator_sms.authenticatorsmsstage", @@ -3558,7 +3543,7 @@ "authentik_stages_authenticator_totp.authenticatortotpstage", "authentik_stages_authenticator_totp.totpdevice", "authentik_stages_authenticator_validate.authenticatorvalidatestage", - "authentik_stages_authenticator_webauthn.authenticatewebauthnstage", + "authentik_stages_authenticator_webauthn.authenticatorwebauthnstage", "authentik_stages_authenticator_webauthn.webauthndevice", "authentik_stages_captcha.captchastage", "authentik_stages_consent.consentstage", @@ -3583,9 +3568,19 @@ "authentik_core.application", "authentik_core.token", "authentik_enterprise.license", + "authentik_providers_google_workspace.googleworkspaceprovider", + "authentik_providers_google_workspace.googleworkspaceprovidermapping", + "authentik_providers_microsoft_entra.microsoftentraprovider", + "authentik_providers_microsoft_entra.microsoftentraprovidermapping", "authentik_providers_rac.racprovider", "authentik_providers_rac.endpoint", - "authentik_providers_rac.racpropertymapping" + "authentik_providers_rac.racpropertymapping", + "authentik_stages_source.sourcestage", + "authentik_events.event", + "authentik_events.notificationtransport", + "authentik_events.notification", + "authentik_events.notificationrule", + "authentik_events.notificationwebhookmapping" ], "title": "Model", "description": "Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched." @@ -3761,11 +3756,13 @@ "type": "object", "properties": { "policy": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Policy" }, "group": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Group" }, "user": { @@ -3773,7 +3770,8 @@ "title": "User" }, "target": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Target" }, "negate": { @@ -3815,19 +3813,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -3838,12 +3839,14 @@ "description": "DN under which objects are accessible." }, "search_group": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Search group", "description": "Users in this group can do search queries. If not set, every user can execute search queries." }, "certificate": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Certificate" }, "tls_server_name": { @@ -3933,19 +3936,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -3993,7 +3999,8 @@ "description": "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint." }, "signing_key": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Signing Key", "description": "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256." }, @@ -4044,19 +4051,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -4075,7 +4085,8 @@ "description": "Validate SSL Certificates of upstream servers" }, "certificate": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Certificate" }, "skip_path_regex": { @@ -4149,19 +4160,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -4194,19 +4208,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -4268,17 +4285,23 @@ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "http://www.w3.org/2000/09/xmldsig#dsa-sha1" ], "title": "Signature algorithm" }, "signing_kp": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Signing Keypair", "description": "Keypair used to sign outgoing Responses going to the Service Provider." }, "verification_kp": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Verification Certificate", "description": "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default." }, @@ -4347,14 +4370,16 @@ "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, "property_mappings_group": { "type": "array", "items": { - "type": "integer", + "type": "string", + "format": "uuid", "description": "Property mappings used for group creation/updating." }, "title": "Property mappings group", @@ -4377,7 +4402,8 @@ "title": "Exclude users service account" }, "filter_group": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Filter group" } }, @@ -4442,12 +4468,14 @@ "title": "Enabled" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow to use when authenticating existing users." }, "enrollment_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Enrollment flow", "description": "Flow to use when enrolling new users." }, @@ -4487,12 +4515,14 @@ "title": "Server URI" }, "peer_certificate": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Peer certificate", "description": "Optionally verify the LDAP Server's Certificate against the CA Chain in this keypair." }, "client_certificate": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Client certificate", "description": "Client certificate to authenticate against the LDAP Server's Certificate." }, @@ -4551,6 +4581,11 @@ "title": "Object uniqueness field", "description": "Field which contains a unique Identifier." }, + "password_login_update_internal_password": { + "type": "boolean", + "title": "Password login update internal password", + "description": "Update internal authentik password when login succeeds with LDAP" + }, "sync_users": { "type": "boolean", "title": "Sync users" @@ -4565,20 +4600,23 @@ "title": "Sync groups" }, "sync_parent_group": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Sync parent group" }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, "property_mappings_group": { "type": "array", "items": { - "type": "integer", + "type": "string", + "format": "uuid", "description": "Property mappings used for group creation/updating." }, "title": "Property mappings group", @@ -4639,12 +4677,14 @@ "title": "Enabled" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow to use when authenticating existing users." }, "enrollment_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Enrollment flow", "description": "Flow to use when enrolling new users." }, @@ -4687,6 +4727,7 @@ "discord", "facebook", "github", + "gitlab", "google", "mailcow", "okta", @@ -4703,7 +4744,6 @@ "null" ], "maxLength": 255, - "minLength": 1, "title": "Request Token URL", "description": "URL used to request the initial token. This URL is only required for OAuth 1." }, @@ -4713,7 +4753,6 @@ "null" ], "maxLength": 255, - "minLength": 1, "title": "Authorization URL", "description": "URL the user is redirect to to conest the flow." }, @@ -4723,7 +4762,6 @@ "null" ], "maxLength": 255, - "minLength": 1, "title": "Access Token URL", "description": "URL used by authentik to retrieve tokens." }, @@ -4733,7 +4771,6 @@ "null" ], "maxLength": 255, - "minLength": 1, "title": "Profile URL", "description": "URL used by authentik to get user information." }, @@ -4817,12 +4854,14 @@ "title": "Enabled" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow to use when authenticating existing users." }, "enrollment_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Enrollment flow", "description": "Flow to use when enrolling new users." }, @@ -4929,12 +4968,14 @@ "title": "Enabled" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow to use when authenticating existing users." }, "enrollment_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Enrollment flow", "description": "Flow to use when enrolling new users." }, @@ -4969,7 +5010,8 @@ "title": "Icon" }, "pre_authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Pre authentication flow", "description": "Flow used before authentication." }, @@ -5023,12 +5065,14 @@ "title": "Binding type" }, "verification_kp": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Verification Certificate", "description": "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default." }, "signing_kp": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Signing Keypair", "description": "Keypair used to sign outgoing Responses going to the Identity Provider." }, @@ -5049,6 +5093,10 @@ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "http://www.w3.org/2000/09/xmldsig#dsa-sha1" ], "title": "Signature algorithm" @@ -5082,6 +5130,52 @@ }, "required": [] }, + "model_authentik_sources_scim.scimsource": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name", + "description": "Source's display Name." + }, + "slug": { + "type": "string", + "maxLength": 50, + "minLength": 1, + "pattern": "^[-a-zA-Z0-9_]+$", + "title": "Slug", + "description": "Internal source name, used in URLs." + }, + "enabled": { + "type": "boolean", + "title": "Enabled" + }, + "user_matching_mode": { + "type": "string", + "enum": [ + "identifier", + "email_link", + "email_deny", + "username_link", + "username_deny" + ], + "title": "User matching mode", + "description": "How the source determines if an existing user should be authenticated or a new user enrolled." + }, + "user_path_template": { + "type": "string", + "minLength": 1, + "title": "User path template" + }, + "icon": { + "type": "string", + "minLength": 1, + "title": "Icon" + } + }, + "required": [] + }, "model_authentik_stages_authenticator_duo.authenticatorduostage": { "type": "object", "properties": { @@ -5173,7 +5267,8 @@ "title": "Flow set" }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -5315,7 +5410,8 @@ "title": "Flow set" }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -5479,7 +5575,8 @@ "title": "Flow set" }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -5610,7 +5707,8 @@ "title": "Flow set" }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -5764,7 +5862,8 @@ "configuration_stages": { "type": "array", "items": { - "type": "integer", + "type": "string", + "format": "uuid", "description": "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." }, "title": "Configuration stages", @@ -5785,11 +5884,19 @@ ], "title": "Webauthn user verification", "description": "Enforce user verification for WebAuthn devices." + }, + "webauthn_allowed_device_types": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "title": "Webauthn allowed device types" } }, "required": [] }, - "model_authentik_stages_authenticator_webauthn.authenticatewebauthnstage": { + "model_authentik_stages_authenticator_webauthn.authenticatorwebauthnstage": { "type": "object", "properties": { "name": { @@ -5880,7 +5987,8 @@ "title": "Flow set" }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -5921,6 +6029,14 @@ "required" ], "title": "Resident key requirement" + }, + "device_type_restrictions": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "title": "Device type restrictions" } }, "required": [] @@ -6164,10 +6280,17 @@ "type": "object", "properties": { "expires": { - "type": "string", + "type": [ + "string", + "null" + ], "format": "date-time", "title": "Expires" }, + "expiring": { + "type": "boolean", + "title": "Expiring" + }, "user": { "type": "object", "properties": { @@ -6198,7 +6321,8 @@ "groups": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Groups" }, @@ -6781,17 +6905,20 @@ "description": "When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown" }, "enrollment_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Enrollment flow", "description": "Optional enrollment flow, which is linked at the bottom of the page." }, "recovery_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Recovery flow", "description": "Optional recovery flow, which is linked at the bottom of the page." }, "passwordless_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Passwordless flow", "description": "Optional passwordless flow, which is linked at the bottom of the page." }, @@ -6925,7 +7052,10 @@ "title": "Name" }, "expires": { - "type": "string", + "type": [ + "string", + "null" + ], "format": "date-time", "title": "Expires" }, @@ -6940,7 +7070,8 @@ "description": "When enabled, the invitation will be deleted after usage." }, "flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow", "description": "When set, only the configured flow can use this invitation." } @@ -7052,7 +7183,8 @@ "description": "Selection of backends to test the password against." }, "configure_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Configure flow", "description": "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage." }, @@ -7336,14 +7468,16 @@ "fields": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Fields" }, "validation_policies": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Validation policies" } @@ -7773,7 +7907,8 @@ "description": "When set, newly created users are inactive and cannot login." }, "create_users_group": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Create users group", "description": "Optionally add newly created users to this group." }, @@ -7823,31 +7958,38 @@ "title": "Branding favicon" }, "flow_authentication": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow authentication" }, "flow_invalidation": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow invalidation" }, "flow_recovery": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow recovery" }, "flow_unenrollment": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow unenrollment" }, "flow_user_settings": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow user settings" }, "flow_device_code": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Flow device code" }, "web_certificate": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Web certificate", "description": "Web Certificate used by the authentik Core webserver." }, @@ -7902,7 +8044,8 @@ "description": "Users added to this group will be superusers." }, "parent": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Parent" }, "users": { @@ -7920,7 +8063,8 @@ "roles": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Roles" } @@ -7957,7 +8101,8 @@ "groups": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Groups" }, @@ -8101,7 +8246,10 @@ "title": "Description" }, "expires": { - "type": "string", + "type": [ + "string", + "null" + ], "format": "date-time", "title": "Expires" }, @@ -8128,6 +8276,205 @@ }, "required": [] }, + "model_authentik_providers_google_workspace.googleworkspaceprovider": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "property_mappings": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "title": "Property mappings" + }, + "property_mappings_group": { + "type": "array", + "items": { + "type": "string", + "format": "uuid", + "description": "Property mappings used for group creation/updating." + }, + "title": "Property mappings group", + "description": "Property mappings used for group creation/updating." + }, + "delegated_subject": { + "type": "string", + "format": "email", + "maxLength": 254, + "minLength": 1, + "title": "Delegated subject" + }, + "credentials": { + "type": "object", + "additionalProperties": true, + "title": "Credentials" + }, + "scopes": { + "type": "string", + "minLength": 1, + "title": "Scopes" + }, + "exclude_users_service_account": { + "type": "boolean", + "title": "Exclude users service account" + }, + "filter_group": { + "type": "string", + "format": "uuid", + "title": "Filter group" + }, + "user_delete_action": { + "type": "string", + "enum": [ + "do_nothing", + "delete", + "suspend" + ], + "title": "User delete action" + }, + "group_delete_action": { + "type": "string", + "enum": [ + "do_nothing", + "delete", + "suspend" + ], + "title": "Group delete action" + }, + "default_group_email_domain": { + "type": "string", + "minLength": 1, + "title": "Default group email domain" + } + }, + "required": [] + }, + "model_authentik_providers_google_workspace.googleworkspaceprovidermapping": { + "type": "object", + "properties": { + "managed": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "title": "Managed by authentik", + "description": "Objects that are managed by authentik. These objects are created and updated automatically. This flag only indicates that an object can be overwritten by migrations. You can still modify the objects via the API, but expect changes to be overwritten in a later update." + }, + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "expression": { + "type": "string", + "minLength": 1, + "title": "Expression" + } + }, + "required": [] + }, + "model_authentik_providers_microsoft_entra.microsoftentraprovider": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "property_mappings": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "title": "Property mappings" + }, + "property_mappings_group": { + "type": "array", + "items": { + "type": "string", + "format": "uuid", + "description": "Property mappings used for group creation/updating." + }, + "title": "Property mappings group", + "description": "Property mappings used for group creation/updating." + }, + "client_id": { + "type": "string", + "minLength": 1, + "title": "Client id" + }, + "client_secret": { + "type": "string", + "minLength": 1, + "title": "Client secret" + }, + "tenant_id": { + "type": "string", + "minLength": 1, + "title": "Tenant id" + }, + "exclude_users_service_account": { + "type": "boolean", + "title": "Exclude users service account" + }, + "filter_group": { + "type": "string", + "format": "uuid", + "title": "Filter group" + }, + "user_delete_action": { + "type": "string", + "enum": [ + "do_nothing", + "delete", + "suspend" + ], + "title": "User delete action" + }, + "group_delete_action": { + "type": "string", + "enum": [ + "do_nothing", + "delete", + "suspend" + ], + "title": "Group delete action" + } + }, + "required": [] + }, + "model_authentik_providers_microsoft_entra.microsoftentraprovidermapping": { + "type": "object", + "properties": { + "managed": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "title": "Managed by authentik", + "description": "Objects that are managed by authentik. These objects are created and updated automatically. This flag only indicates that an object can be overwritten by migrations. You can still modify the objects via the API, but expect changes to be overwritten in a later update." + }, + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "expression": { + "type": "string", + "minLength": 1, + "title": "Expression" + } + }, + "required": [] + }, "model_authentik_providers_rac.racprovider": { "type": "object", "properties": { @@ -8137,19 +8484,22 @@ "title": "Name" }, "authentication_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authentication flow", "description": "Flow used for authentication when the associated application is accessed by an un-authenticated user." }, "authorization_flow": { - "type": "integer", + "type": "string", + "format": "uuid", "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -8163,6 +8513,11 @@ "minLength": 1, "title": "Connection expiry", "description": "Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" + }, + "delete_token_on_disconnect": { + "type": "boolean", + "title": "Delete token on disconnect", + "description": "When set to true, connection tokens will be deleted upon disconnect." } }, "required": [] @@ -8201,7 +8556,8 @@ "property_mappings": { "type": "array", "items": { - "type": "integer" + "type": "string", + "format": "uuid" }, "title": "Property mappings" }, @@ -8251,6 +8607,354 @@ }, "required": [] }, + "model_authentik_stages_source.sourcestage": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "flow_set": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "slug": { + "type": "string", + "maxLength": 50, + "minLength": 1, + "pattern": "^[-a-zA-Z0-9_]+$", + "title": "Slug", + "description": "Visible in the URL." + }, + "title": { + "type": "string", + "minLength": 1, + "title": "Title", + "description": "Shown as the Title in Flow pages." + }, + "designation": { + "type": "string", + "enum": [ + "authentication", + "authorization", + "invalidation", + "enrollment", + "unenrollment", + "recovery", + "stage_configuration" + ], + "title": "Designation", + "description": "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." + }, + "policy_engine_mode": { + "type": "string", + "enum": [ + "all", + "any" + ], + "title": "Policy engine mode" + }, + "compatibility_mode": { + "type": "boolean", + "title": "Compatibility mode", + "description": "Enable compatibility mode, increases compatibility with password managers on mobile devices." + }, + "layout": { + "type": "string", + "enum": [ + "stacked", + "content_left", + "content_right", + "sidebar_left", + "sidebar_right" + ], + "title": "Layout" + }, + "denied_action": { + "type": "string", + "enum": [ + "message_continue", + "message", + "continue" + ], + "title": "Denied action", + "description": "Configure what should happen when a flow denies access to a user." + } + }, + "required": [ + "name", + "slug", + "title", + "designation" + ] + }, + "title": "Flow set" + }, + "source": { + "type": "integer", + "title": "Source" + }, + "resume_timeout": { + "type": "string", + "minLength": 1, + "title": "Resume timeout", + "description": "Amount of time a user can take to return from the source to continue the flow (Format: hours=-1;minutes=-2;seconds=-3)" + } + }, + "required": [] + }, + "model_authentik_events.event": { + "type": "object", + "properties": { + "user": { + "type": "object", + "additionalProperties": true, + "title": "User" + }, + "action": { + "type": "string", + "enum": [ + "login", + "login_failed", + "logout", + "user_write", + "suspicious_request", + "password_set", + "secret_view", + "secret_rotate", + "invitation_used", + "authorize_application", + "source_linked", + "impersonation_started", + "impersonation_ended", + "flow_execution", + "policy_execution", + "policy_exception", + "property_mapping_exception", + "system_task_execution", + "system_task_exception", + "system_exception", + "configuration_error", + "model_created", + "model_updated", + "model_deleted", + "email_sent", + "update_available", + "custom_" + ], + "title": "Action" + }, + "app": { + "type": "string", + "minLength": 1, + "title": "App" + }, + "context": { + "type": "object", + "additionalProperties": true, + "title": "Context" + }, + "client_ip": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "title": "Client ip" + }, + "expires": { + "type": "string", + "format": "date-time", + "title": "Expires" + }, + "brand": { + "type": "object", + "additionalProperties": true, + "title": "Brand" + } + }, + "required": [] + }, + "model_authentik_events.notificationtransport": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "mode": { + "type": "string", + "enum": [ + "local", + "webhook", + "webhook_slack", + "email" + ], + "title": "Mode" + }, + "webhook_url": { + "type": "string", + "title": "Webhook url" + }, + "webhook_mapping": { + "type": "integer", + "title": "Webhook mapping" + }, + "send_once": { + "type": "boolean", + "title": "Send once", + "description": "Only send notification once, for example when sending a webhook into a chat channel." + } + }, + "required": [] + }, + "model_authentik_events.notification": { + "type": "object", + "properties": { + "event": { + "type": "object", + "properties": { + "user": { + "type": "object", + "additionalProperties": true, + "title": "User" + }, + "action": { + "type": "string", + "enum": [ + "login", + "login_failed", + "logout", + "user_write", + "suspicious_request", + "password_set", + "secret_view", + "secret_rotate", + "invitation_used", + "authorize_application", + "source_linked", + "impersonation_started", + "impersonation_ended", + "flow_execution", + "policy_execution", + "policy_exception", + "property_mapping_exception", + "system_task_execution", + "system_task_exception", + "system_exception", + "configuration_error", + "model_created", + "model_updated", + "model_deleted", + "email_sent", + "update_available", + "custom_" + ], + "title": "Action" + }, + "app": { + "type": "string", + "minLength": 1, + "title": "App" + }, + "context": { + "type": "object", + "additionalProperties": true, + "title": "Context" + }, + "client_ip": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "title": "Client ip" + }, + "expires": { + "type": "string", + "format": "date-time", + "title": "Expires" + }, + "brand": { + "type": "object", + "additionalProperties": true, + "title": "Brand" + } + }, + "required": [ + "action", + "app" + ], + "title": "Event" + }, + "seen": { + "type": "boolean", + "title": "Seen" + } + }, + "required": [] + }, + "model_authentik_events.notificationrule": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "transports": { + "type": "array", + "items": { + "type": "string", + "format": "uuid", + "description": "Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI." + }, + "title": "Transports", + "description": "Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI." + }, + "severity": { + "type": "string", + "enum": [ + "notice", + "warning", + "alert" + ], + "title": "Severity", + "description": "Controls which severity level the created notifications will have." + }, + "group": { + "type": "string", + "format": "uuid", + "title": "Group", + "description": "Define which group of users this notification should be sent and shown to. If left empty, Notification won't ben sent." + } + }, + "required": [] + }, + "model_authentik_events.notificationwebhookmapping": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name" + }, + "expression": { + "type": "string", + "minLength": 1, + "title": "Expression" + } + }, + "required": [] + }, "model_authentik_blueprints.metaapplyblueprint": { "type": "object", "properties": { diff --git a/blueprints/system/providers-google-workspace.yaml b/blueprints/system/providers-google-workspace.yaml new file mode 100644 index 0000000000..243712854f --- /dev/null +++ b/blueprints/system/providers-google-workspace.yaml @@ -0,0 +1,42 @@ +version: 1 +metadata: + labels: + blueprints.goauthentik.io/system: "true" + name: System - Google Workspace Provider - Mappings +entries: + - identifiers: + managed: goauthentik.io/providers/google_workspace/user + model: authentik_providers_google_workspace.googleworkspaceprovidermapping + attrs: + name: "authentik default Google Workspace Mapping: User" + # https://developers.google.com/admin-sdk/directory/reference/rest/v1/users#User + expression: | + # Google require givenName and familyName to be set + givenName, familyName = request.user.name, " " + formatted = request.user.name + " " + # This default sets givenName to the name before the first space + # and the remainder as family name + # if the user's name has no space the givenName is the entire name + if " " in request.user.name: + givenName, _, familyName = request.user.name.partition(" ") + formatted = request.user.name + return { + "name": { + "fullName": formatted, + "familyName": familyName.strip(), + "givenName": givenName.strip(), + "displayName": formatted, + }, + "password": request.user.password, + "suspended": not request.user.is_active, + } + - identifiers: + managed: goauthentik.io/providers/google_workspace/group + model: authentik_providers_google_workspace.googleworkspaceprovidermapping + attrs: + name: "authentik default Google Workspace Mapping: Group" + # https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups#Group + expression: | + return { + "name": group.name, + } diff --git a/blueprints/system/providers-microsoft-entra.yaml b/blueprints/system/providers-microsoft-entra.yaml new file mode 100644 index 0000000000..9a69f95940 --- /dev/null +++ b/blueprints/system/providers-microsoft-entra.yaml @@ -0,0 +1,39 @@ +version: 1 +metadata: + labels: + blueprints.goauthentik.io/system: "true" + name: System - Microsoft Entra Provider - Mappings +entries: + - identifiers: + managed: goauthentik.io/providers/microsoft_entra/user + model: authentik_providers_microsoft_entra.microsoftentraprovidermapping + attrs: + name: "authentik default Microsoft Entra Mapping: User" + # https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0 + expression: | + from msgraph.generated.models.password_profile import PasswordProfile + + user = { + "display_name": request.user.name, + "account_enabled": request.user.is_active, + "mail_nickname": request.user.username, + "user_principal_name": request.user.email, + } + if creating: + user["password_profile"] = PasswordProfile( + password=request.user.password + ) + return user + - identifiers: + managed: goauthentik.io/providers/microsoft_entra/group + model: authentik_providers_microsoft_entra.microsoftentraprovidermapping + attrs: + name: "authentik default Microsoft Entra Mapping: Group" + # https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=http#request-body + expression: | + return { + "display_name": group.name, + "mail_enabled": False, + "security_enabled": True, + "mail_nickname": slugify(group.name), + } diff --git a/blueprints/system/providers-rac.yaml b/blueprints/system/providers-rac.yaml index 63a568673f..ef530cea20 100644 --- a/blueprints/system/providers-rac.yaml +++ b/blueprints/system/providers-rac.yaml @@ -23,6 +23,8 @@ entries: enable-full-window-drag: "true" enable-desktop-composition: "true" enable-menu-animations: "true" + enable-wallpaper: "true" + enable-font-smoothing: "true" - identifiers: managed: goauthentik.io/providers/rac/ssh-default model: authentik_providers_rac.racpropertymapping diff --git a/blueprints/system/sources-ldap.yaml b/blueprints/system/sources-ldap.yaml index dbf8891e7b..66e1462eee 100644 --- a/blueprints/system/sources-ldap.yaml +++ b/blueprints/system/sources-ldap.yaml @@ -11,7 +11,6 @@ entries: name: "authentik default LDAP Mapping: DN to User Path" object_field: "path" expression: | - dn = ldap.get("distinguishedName") path_elements = [] for pair in dn.split(","): attr, _, value = pair.partition("=") diff --git a/docker-compose.yml b/docker-compose.yml index 20fa2f8e14..f473bac488 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,4 @@ --- -version: "3.4" services: postgresql: @@ -32,7 +31,7 @@ services: volumes: - redis:/data server: - image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.6} + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.2} restart: unless-stopped command: server environment: @@ -53,7 +52,7 @@ services: - postgresql - redis worker: - image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.6} + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.2} restart: unless-stopped command: worker environment: diff --git a/go.mod b/go.mod index 1d3481dea1..f18349e233 100644 --- a/go.mod +++ b/go.mod @@ -1,37 +1,37 @@ module goauthentik.io -go 1.21 +go 1.22.2 require ( beryju.io/ldap v0.1.0 github.com/coreos/go-oidc v2.2.1+incompatible - github.com/getsentry/sentry-go v0.26.0 + github.com/getsentry/sentry-go v0.27.0 github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1 - github.com/go-ldap/ldap/v3 v3.4.6 - github.com/go-openapi/runtime v0.27.0 - github.com/go-openapi/strfmt v0.22.0 - github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/go-ldap/ldap/v3 v3.4.8 + github.com/go-openapi/runtime v0.28.0 + github.com/go-openapi/strfmt v0.23.0 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.1 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 github.com/gorilla/websocket v1.5.1 - github.com/jellydator/ttlcache/v3 v3.1.1 + github.com/jellydator/ttlcache/v3 v3.2.0 github.com/mitchellh/mapstructure v1.5.0 github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 github.com/pires/go-proxyproto v0.7.0 - github.com/prometheus/client_golang v1.18.0 - github.com/redis/go-redis/v9 v9.4.0 - github.com/sethvargo/go-envconfig v1.0.0 + github.com/prometheus/client_golang v1.19.1 + github.com/redis/go-redis/v9 v9.5.1 + github.com/sethvargo/go-envconfig v1.0.3 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/wwt/guac v1.3.2 - goauthentik.io/api/v3 v3.2023106.4 + goauthentik.io/api/v3 v3.2024042.7 golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab - golang.org/x/oauth2 v0.16.0 - golang.org/x/sync v0.6.0 + golang.org/x/oauth2 v0.20.0 + golang.org/x/sync v0.7.0 gopkg.in/yaml.v2 v2.4.0 layeh.com/radius v0.0.0-20210819152912-ad72663a72ab ) @@ -47,39 +47,36 @@ require ( github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.21.5 // indirect - github.com/go-openapi/errors v0.21.0 // indirect - github.com/go-openapi/jsonpointer v0.20.1 // indirect - github.com/go-openapi/jsonreference v0.20.3 // indirect - github.com/go-openapi/loads v0.21.3 // indirect - github.com/go-openapi/spec v0.20.12 // indirect - github.com/go-openapi/swag v0.22.5 // indirect - github.com/go-openapi/validate v0.22.4 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/go-openapi/analysis v0.23.0 // indirect + github.com/go-openapi/errors v0.22.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/loads v0.22.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/validate v0.24.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - go.mongodb.org/mongo-driver v1.13.1 // indirect - go.opentelemetry.io/otel v1.17.0 // indirect - go.opentelemetry.io/otel/metric v1.17.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b8090ba274..acef59fa57 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= -github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= +github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -69,8 +69,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA= -github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -84,35 +84,35 @@ github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 h1:O6yi4xa9b2D github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27/go.mod h1:AYvN8omj7nKLmbcXS2dyABYU6JB1Lz1bHmkkq1kf4I4= github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno= github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw= -github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= -github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= +github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ= +github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.21.5 h1:3tHfEBh6Ia8eKc4M7khOGjPOAlWKJ10d877Cr9teujI= -github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M= -github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= -github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= -github.com/go-openapi/jsonpointer v0.20.1 h1:MkK4VEIEZMj4wT9PmjaUmGflVBr9nvud4Q4UVFbDoBE= -github.com/go-openapi/jsonpointer v0.20.1/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.3 h1:EjGcjTW8pD1mRis6+w/gmoBdqv5+RbE9B85D1NgDOVQ= -github.com/go-openapi/jsonreference v0.20.3/go.mod h1:FviDZ46i9ivh810gqzFLl5NttD5q3tSlMLqLr6okedM= -github.com/go-openapi/loads v0.21.3 h1:8sSH2FIm/SnbDUGv572md4YqVMFne/a9Eubvcd3anew= -github.com/go-openapi/loads v0.21.3/go.mod h1:Y3aMR24iHbKHppOj91nQ/SHc0cuPbAr4ndY4a02xydc= -github.com/go-openapi/runtime v0.27.0 h1:ukHSkyGp8gtDkwE1Mue2FofNh8kLfYv3xkCXWeLr0hM= -github.com/go-openapi/runtime v0.27.0/go.mod h1:fijeJEiEclyS8BRurYE1DE5TLb9/KZl6eAdbzjsrlLU= -github.com/go-openapi/spec v0.20.12 h1:cgSLbrsmziAP2iais+Vz7kSazwZ8rsUZd6TUzdDgkVI= -github.com/go-openapi/spec v0.20.12/go.mod h1:iSCgnBcwbMW9SfzJb8iYynXvcY6C/QFrI7otzF7xGM4= -github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI= -github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= -github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugys= -github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-openapi/validate v0.22.4 h1:5v3jmMyIPKTR8Lv9syBAIRxG6lY0RqeBPB1LKEijzk8= -github.com/go-openapi/validate v0.22.4/go.mod h1:qm6O8ZIcPVdSY5219468Jv7kBdGvkiZLPOmqnqTUZ2A= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= +github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= +github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= +github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= +github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -137,10 +137,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -150,8 +146,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -167,7 +161,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -176,26 +169,42 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jellydator/ttlcache/v3 v3.1.1 h1:RCgYJqo3jgvhl+fEWvjNW8thxGWsgxi+TPhRir1Y9y8= -github.com/jellydator/ttlcache/v3 v3.1.1/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE= +github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -206,11 +215,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 h1:D9EvfGQvlkKaDr2CRKN++7HbSXbefUNDrPq60T+g24s= github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484/go.mod h1:O1EljZ+oHprtxDDPHiMWVo/5dBT6PlvWX5PSwj80aBA= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= @@ -227,23 +233,23 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac h1:jWKYCNlX4J5s8M0nHYkh7Y7c9gRVDEb3mq51j5J0F5M= github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= -github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sethvargo/go-envconfig v1.0.0 h1:1C66wzy4QrROf5ew4KdVw942CQDa55qmlYmw9FZxZdU= -github.com/sethvargo/go-envconfig v1.0.0/go.mod h1:Lzc75ghUn5ucmcRGIdGQ33DKJrcjk4kihFYgSTBmjIc= +github.com/sethvargo/go-envconfig v1.0.3 h1:ZDxFGT1M7RPX0wgDOCdZMidrEB+NrayYr6fL0/+pk4I= +github.com/sethvargo/go-envconfig v1.0.3/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -254,6 +260,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -261,37 +268,34 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/wwt/guac v1.3.2 h1:sH6OFGa/1tBs7ieWBVlZe7t6F5JAOWBry/tqQL/Vup4= github.com/wwt/guac v1.3.2/go.mod h1:eKm+NrnK7A88l4UBEcYNpZQGMpZRryYKoz4D/0/n1C0= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -goauthentik.io/api/v3 v3.2023106.4 h1:HYVgTdFIQzGvLkl0PugAkhdvRXOW1+0Dw5dHunlmf7Q= -goauthentik.io/api/v3 v3.2023106.4/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= +goauthentik.io/api/v3 v3.2024042.7 h1:cc8YSjoJZgMBlXQFlbY9HFrfu7gYziUBCN8HZomWgBA= +goauthentik.io/api/v3 v3.2024042.7/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -299,10 +303,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -364,20 +368,22 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -388,8 +394,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -417,32 +423,29 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -516,8 +519,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -569,10 +570,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/config/struct.go b/internal/config/struct.go index 0964d7583c..17dd3ba246 100644 --- a/internal/config/struct.go +++ b/internal/config/struct.go @@ -25,13 +25,14 @@ type Config struct { } type RedisConfig struct { - Host string `yaml:"host" env:"HOST, overwrite"` - Port int `yaml:"port" env:"PORT, overwrite"` - DB int `yaml:"db" env:"DB, overwrite"` - Username string `yaml:"username" env:"USERNAME, overwrite"` - Password string `yaml:"password" env:"PASSWORD, overwrite"` - TLS bool `yaml:"tls" env:"TLS, overwrite"` - TLSReqs string `yaml:"tls_reqs" env:"TLS_REQS, overwrite"` + Host string `yaml:"host" env:"HOST, overwrite"` + Port int `yaml:"port" env:"PORT, overwrite"` + DB int `yaml:"db" env:"DB, overwrite"` + Username string `yaml:"username" env:"USERNAME, overwrite"` + Password string `yaml:"password" env:"PASSWORD, overwrite"` + TLS bool `yaml:"tls" env:"TLS, overwrite"` + TLSReqs string `yaml:"tls_reqs" env:"TLS_REQS, overwrite"` + TLSCaCert *string `yaml:"tls_ca_certs" env:"TLS_CA_CERT, overwrite"` } type ListenConfig struct { @@ -50,12 +51,12 @@ type StorageConfig struct { } type StorageMediaConfig struct { - Backend string `yaml:"backend" env:"AUTHENTIK_STORAGE_MEDIA_BACKEND"` + Backend string `yaml:"backend" env:"AUTHENTIK_STORAGE__MEDIA__BACKEND"` File StorageFileConfig `yaml:"file"` } type StorageFileConfig struct { - Path string `yaml:"path" env:"AUTHENTIK_STORAGE_MEDIA_FILE_PATH"` + Path string `yaml:"path" env:"AUTHENTIK_STORAGE__MEDIA__FILE__PATH"` } type ErrorReportingConfig struct { diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 30ddb3464e..e9bd7f9e53 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -29,4 +29,4 @@ func UserAgent() string { return fmt.Sprintf("authentik@%s", FullVersion()) } -const VERSION = "2023.10.6" +const VERSION = "2024.4.2" diff --git a/internal/crypto/backend/fips_disabled.go b/internal/crypto/backend/fips_disabled.go new file mode 100644 index 0000000000..418cd1a144 --- /dev/null +++ b/internal/crypto/backend/fips_disabled.go @@ -0,0 +1,5 @@ +//go:build requirefips + +package backend + +var FipsEnabled = true diff --git a/internal/crypto/backend/fips_enabled.go b/internal/crypto/backend/fips_enabled.go new file mode 100644 index 0000000000..49a0c95bb4 --- /dev/null +++ b/internal/crypto/backend/fips_enabled.go @@ -0,0 +1,5 @@ +//go:build !requirefips + +package backend + +var FipsEnabled = false diff --git a/internal/crypto/backend/openssl_disabled.go b/internal/crypto/backend/openssl_disabled.go new file mode 100644 index 0000000000..aeb9e85404 --- /dev/null +++ b/internal/crypto/backend/openssl_disabled.go @@ -0,0 +1,5 @@ +//go:build !goexperiment.systemcrypto + +package backend + +var OpensslEnabled = false diff --git a/internal/crypto/backend/openssl_enabled.go b/internal/crypto/backend/openssl_enabled.go new file mode 100644 index 0000000000..11c4d1b081 --- /dev/null +++ b/internal/crypto/backend/openssl_enabled.go @@ -0,0 +1,5 @@ +//go:build goexperiment.systemcrypto + +package backend + +var OpensslEnabled = true diff --git a/internal/crypto/backend/openssl_version.go b/internal/crypto/backend/openssl_version.go new file mode 100644 index 0000000000..80d5bbd119 --- /dev/null +++ b/internal/crypto/backend/openssl_version.go @@ -0,0 +1,17 @@ +package backend + +import ( + "bytes" + "os/exec" +) + +func OpensslVersion() string { + cmd := exec.Command("openssl", "version") + var out bytes.Buffer + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return "" + } + return out.String() +} diff --git a/internal/gounicorn/gounicorn.go b/internal/gounicorn/gounicorn.go index 0f328c9439..a3692f3106 100644 --- a/internal/gounicorn/gounicorn.go +++ b/internal/gounicorn/gounicorn.go @@ -96,18 +96,15 @@ func (g *GoUnicorn) healthcheck() { g.log.Debug("starting healthcheck") // Default healthcheck is every 1 second on startup // once we've been healthy once, increase to 30 seconds - for range time.Tick(time.Second) { + for range time.NewTicker(time.Second).C { if g.Healthcheck() { g.alive = true - g.log.Info("backend is alive, backing off with healthchecks") + g.log.Debug("backend is alive, backing off with healthchecks") g.HealthyCallback() break } g.log.Debug("backend not alive yet") } - for range time.Tick(30 * time.Second) { - g.Healthcheck() - } } func (g *GoUnicorn) Reload() { diff --git a/internal/outpost/ak/api.go b/internal/outpost/ak/api.go index 1f744010a7..fca9a6fb9c 100644 --- a/internal/outpost/ak/api.go +++ b/internal/outpost/ak/api.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "os/signal" + "runtime" "syscall" "time" @@ -15,11 +16,12 @@ import ( "github.com/google/uuid" "github.com/gorilla/websocket" "github.com/prometheus/client_golang/prometheus" + log "github.com/sirupsen/logrus" + "goauthentik.io/api/v3" "goauthentik.io/internal/constants" + cryptobackend "goauthentik.io/internal/crypto/backend" "goauthentik.io/internal/utils/web" - - log "github.com/sirupsen/logrus" ) type WSHandler func(ctx context.Context, args map[string]interface{}) @@ -184,9 +186,13 @@ func (a *APIController) OnRefresh() error { func (a *APIController) getWebsocketPingArgs() map[string]interface{} { args := map[string]interface{}{ - "version": constants.VERSION, - "buildHash": constants.BUILD("tagged"), - "uuid": a.instanceUUID.String(), + "version": constants.VERSION, + "buildHash": constants.BUILD("tagged"), + "uuid": a.instanceUUID.String(), + "golangVersion": runtime.Version(), + "opensslEnabled": cryptobackend.OpensslEnabled, + "opensslVersion": cryptobackend.OpensslVersion(), + "fipsEnabled": cryptobackend.FipsEnabled, } hostname, err := os.Hostname() if err == nil { diff --git a/internal/outpost/ak/crypto.go b/internal/outpost/ak/crypto.go index d6d988e23d..b084367e12 100644 --- a/internal/outpost/ak/crypto.go +++ b/internal/outpost/ak/crypto.go @@ -54,7 +54,7 @@ func (cs *CryptoStore) getFingerprint(uuid string) string { func (cs *CryptoStore) Fetch(uuid string) error { cfp := cs.getFingerprint(uuid) if cfp == cs.fingerprints[uuid] { - cs.log.WithField("uuid", uuid).Info("Fingerprint hasn't changed, not fetching cert") + cs.log.WithField("uuid", uuid).Debug("Fingerprint hasn't changed, not fetching cert") return nil } cs.log.WithField("uuid", uuid).Info("Fetching certificate and private key") diff --git a/internal/outpost/flow/executor.go b/internal/outpost/flow/executor.go index 10dca6bb5f..d1e898308c 100644 --- a/internal/outpost/flow/executor.go +++ b/internal/outpost/flow/executor.go @@ -86,7 +86,9 @@ func NewFlowExecutor(ctx context.Context, flowSlug string, refConfig *api.Config Jar: jar, Transport: fe, } - fe.token = strings.Split(refConfig.DefaultHeader["Authorization"], " ")[1] + if authz, ok := refConfig.DefaultHeader["Authorization"]; ok { + fe.token = strings.Split(authz, " ")[1] + } config.AddDefaultHeader(HeaderAuthentikOutpostToken, fe.token) fe.api = api.NewAPIClient(config) return fe diff --git a/internal/outpost/flow/solvers_mfa.go b/internal/outpost/flow/solvers_mfa.go index f2952eb3df..30de3e3718 100644 --- a/internal/outpost/flow/solvers_mfa.go +++ b/internal/outpost/flow/solvers_mfa.go @@ -10,12 +10,17 @@ const CodePasswordSeparator = ";" var alphaNum = regexp.MustCompile(`^[a-zA-Z0-9]*$`) -// CheckPasswordInlineMFA For protocols that only support username/password, check if the password -// contains the TOTP code -func (fe *FlowExecutor) CheckPasswordInlineMFA() { - password := fe.Answers[StagePassword] - // We already have an authenticator answer - if fe.Answers[StageAuthenticatorValidate] != "" { +// Sets the secret answers for the flow executor for protocols that only support username/password +// according to used options +func (fe *FlowExecutor) SetSecrets(password string, mfaCodeBased bool) { + if fe.Answers[StageAuthenticatorValidate] != "" || fe.Answers[StagePassword] != "" { + return + } + fe.Answers[StagePassword] = password + if !mfaCodeBased { + // If code-based MFA is disabled StageAuthenticatorValidate answer is set to password. + // This allows flows with a mfa stage only. + fe.Answers[StageAuthenticatorValidate] = password return } // password doesn't contain the separator diff --git a/internal/outpost/flow/solvers_mfa_test.go b/internal/outpost/flow/solvers_mfa_test.go new file mode 100644 index 0000000000..7b523b05d5 --- /dev/null +++ b/internal/outpost/flow/solvers_mfa_test.go @@ -0,0 +1,68 @@ +package flow_test + +import ( + "context" + "encoding/base64" + "fmt" + "strconv" + "testing" + + "github.com/gorilla/securecookie" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "goauthentik.io/api/v3" + "goauthentik.io/internal/outpost/flow" +) + +func testSecret() string { + return base64.RawURLEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) +} + +func TestFlowExecutor_SetSecrets_Plain(t *testing.T) { + fe := flow.NewFlowExecutor(context.TODO(), "", api.NewConfiguration(), logrus.Fields{}) + pw := testSecret() + fe.SetSecrets(pw, false) + assert.Equal(t, pw, fe.Answers[flow.StagePassword]) + assert.Equal(t, pw, fe.Answers[flow.StageAuthenticatorValidate]) +} + +func TestFlowExecutor_SetSecrets_TOTP_6(t *testing.T) { + fe := flow.NewFlowExecutor(context.TODO(), "", api.NewConfiguration(), logrus.Fields{}) + pw := testSecret() + totp := 123456 + formatted := fmt.Sprintf("%s%s%d", pw, flow.CodePasswordSeparator, totp) + fe.SetSecrets(formatted, true) + assert.Equal(t, pw, fe.Answers[flow.StagePassword]) + assert.Equal(t, strconv.Itoa(totp), fe.Answers[flow.StageAuthenticatorValidate]) +} + +func TestFlowExecutor_SetSecrets_TOTP_8(t *testing.T) { + fe := flow.NewFlowExecutor(context.TODO(), "", api.NewConfiguration(), logrus.Fields{}) + pw := testSecret() + totp := 12345678 + formatted := fmt.Sprintf("%s%s%d", pw, flow.CodePasswordSeparator, totp) + fe.SetSecrets(formatted, true) + assert.Equal(t, pw, fe.Answers[flow.StagePassword]) + assert.Equal(t, strconv.Itoa(totp), fe.Answers[flow.StageAuthenticatorValidate]) +} + +func TestFlowExecutor_SetSecrets_TOTP_TooLong(t *testing.T) { + fe := flow.NewFlowExecutor(context.TODO(), "", api.NewConfiguration(), logrus.Fields{}) + pw := testSecret() + totp := 1234567890 + formatted := fmt.Sprintf("%s%s%d", pw, flow.CodePasswordSeparator, totp) + fe.SetSecrets(formatted, true) + assert.Equal(t, formatted, fe.Answers[flow.StagePassword]) + assert.Equal(t, "", fe.Answers[flow.StageAuthenticatorValidate]) +} + +func TestFlowExecutor_SetSecrets_TOTP_NoCode(t *testing.T) { + fe := flow.NewFlowExecutor(context.TODO(), "", api.NewConfiguration(), logrus.Fields{}) + pw := testSecret() + fe.SetSecrets(pw, true) + assert.Equal(t, pw, fe.Answers[flow.StagePassword]) + assert.Equal(t, "", fe.Answers[flow.StageAuthenticatorValidate]) + fe.SetSecrets(pw+flow.CodePasswordSeparator, true) + assert.Equal(t, pw, fe.Answers[flow.StagePassword]) + assert.Equal(t, "", fe.Answers[flow.StageAuthenticatorValidate]) +} diff --git a/internal/outpost/ldap/bind/direct/bind.go b/internal/outpost/ldap/bind/direct/bind.go index cffa0cf366..b7850e853d 100644 --- a/internal/outpost/ldap/bind/direct/bind.go +++ b/internal/outpost/ldap/bind/direct/bind.go @@ -23,10 +23,7 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul fe.Params.Add("goauthentik.io/outpost/ldap", "true") fe.Answers[flow.StageIdentification] = username - fe.Answers[flow.StagePassword] = req.BindPW - if db.si.GetMFASupport() { - fe.CheckPasswordInlineMFA() - } + fe.SetSecrets(req.BindPW, db.si.GetMFASupport()) passed, err := fe.Execute() flags := flags.UserFlags{ diff --git a/internal/outpost/ldap/search/direct/direct.go b/internal/outpost/ldap/search/direct/direct.go index 7ac59f834c..1122bd611b 100644 --- a/internal/outpost/ldap/search/direct/direct.go +++ b/internal/outpost/ldap/search/direct/direct.go @@ -113,7 +113,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, errs.Go(func() error { if flags.CanSearch { uapisp := sentry.StartSpan(errCtx, "authentik.providers.ldap.search.api_user") - searchReq, skip := utils.ParseFilterForUser(c.CoreApi.CoreUsersList(uapisp.Context()), parsedFilter, false) + searchReq, skip := utils.ParseFilterForUser(c.CoreApi.CoreUsersList(uapisp.Context()).IncludeGroups(true), parsedFilter, false) if skip { req.Log().Trace("Skip backend request") @@ -150,7 +150,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, if needGroups { errs.Go(func() error { gapisp := sentry.StartSpan(errCtx, "authentik.providers.ldap.search.api_group") - searchReq, skip := utils.ParseFilterForGroup(c.CoreApi.CoreGroupsList(gapisp.Context()), parsedFilter, false) + searchReq, skip := utils.ParseFilterForGroup(c.CoreApi.CoreGroupsList(gapisp.Context()).IncludeUsers(true), parsedFilter, false) if skip { req.Log().Trace("Skip backend request") return nil diff --git a/internal/outpost/ldap/search/memory/memory.go b/internal/outpost/ldap/search/memory/memory.go index fa25ed96f5..b889edba04 100644 --- a/internal/outpost/ldap/search/memory/memory.go +++ b/internal/outpost/ldap/search/memory/memory.go @@ -38,8 +38,8 @@ func NewMemorySearcher(si server.LDAPServerInstance) *MemorySearcher { ds: direct.NewDirectSearcher(si), } ms.log.Debug("initialised memory searcher") - ms.users = paginator.FetchUsers(ms.si.GetAPIClient().CoreApi.CoreUsersList(context.TODO())) - ms.groups = paginator.FetchGroups(ms.si.GetAPIClient().CoreApi.CoreGroupsList(context.TODO())) + ms.users = paginator.FetchUsers(ms.si.GetAPIClient().CoreApi.CoreUsersList(context.TODO()).IncludeGroups(true)) + ms.groups = paginator.FetchGroups(ms.si.GetAPIClient().CoreApi.CoreGroupsList(context.TODO()).IncludeUsers(true)) return ms } diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index 3f3fcaa3b6..0a308280da 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -192,7 +192,9 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A }) }) - mux.HandleFunc("/outpost.goauthentik.io/start", a.handleAuthStart) + mux.HandleFunc("/outpost.goauthentik.io/start", func(w http.ResponseWriter, r *http.Request) { + a.handleAuthStart(w, r, "") + }) mux.HandleFunc("/outpost.goauthentik.io/callback", a.handleAuthCallback) mux.HandleFunc("/outpost.goauthentik.io/sign_out", a.handleSignOut) switch *p.Mode { diff --git a/internal/outpost/proxyv2/application/mode_forward.go b/internal/outpost/proxyv2/application/mode_forward.go index 47b5dd47b1..4a2c987d9e 100644 --- a/internal/outpost/proxyv2/application/mode_forward.go +++ b/internal/outpost/proxyv2/application/mode_forward.go @@ -59,19 +59,11 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque a.log.Trace("path can be accessed without authentication") return } - a.handleAuthStart(rw, r) // set the redirect flag to the current URL we have, since we redirect // to a (possibly) different domain, but we want to be redirected back // to the application // X-Forwarded-Uri is only the path, so we need to build the entire URL - s, _ := a.sessions.Get(r, a.SessionName()) - if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { - s.Values[constants.SessionRedirect] = fwd.String() - err = s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session") - } - } + a.handleAuthStart(rw, r, fwd.String()) } func (a *Application) forwardHandleCaddy(rw http.ResponseWriter, r *http.Request) { @@ -110,19 +102,11 @@ func (a *Application) forwardHandleCaddy(rw http.ResponseWriter, r *http.Request a.log.Trace("path can be accessed without authentication") return } - a.handleAuthStart(rw, r) // set the redirect flag to the current URL we have, since we redirect // to a (possibly) different domain, but we want to be redirected back // to the application // X-Forwarded-Uri is only the path, so we need to build the entire URL - s, _ := a.sessions.Get(r, a.SessionName()) - if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { - s.Values[constants.SessionRedirect] = fwd.String() - err = s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session") - } - } + a.handleAuthStart(rw, r, fwd.String()) } func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request) { @@ -185,17 +169,9 @@ func (a *Application) forwardHandleEnvoy(rw http.ResponseWriter, r *http.Request a.log.Trace("path can be accessed without authentication") return } - a.handleAuthStart(rw, r) // set the redirect flag to the current URL we have, since we redirect // to a (possibly) different domain, but we want to be redirected back // to the application // X-Forwarded-Uri is only the path, so we need to build the entire URL - s, _ := a.sessions.Get(r, a.SessionName()) - if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { - s.Values[constants.SessionRedirect] = fwd.String() - err = s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session before redirect") - } - } + a.handleAuthStart(rw, r, fwd.String()) } diff --git a/internal/outpost/proxyv2/application/mode_forward_caddy_test.go b/internal/outpost/proxyv2/application/mode_forward_caddy_test.go index c2994f7dac..6e0e860e0e 100644 --- a/internal/outpost/proxyv2/application/mode_forward_caddy_test.go +++ b/internal/outpost/proxyv2/application/mode_forward_caddy_test.go @@ -47,16 +47,14 @@ func TestForwardHandleCaddy_Single_Headers(t *testing.T) { a.forwardHandleCaddy(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://test.goauthentik.io/app", st.Redirect) } func TestForwardHandleCaddy_Single_Claims(t *testing.T) { @@ -134,14 +132,12 @@ func TestForwardHandleCaddy_Domain_Header(t *testing.T) { a.forwardHandleCaddy(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://test.goauthentik.io/app", st.Redirect) } diff --git a/internal/outpost/proxyv2/application/mode_forward_envoy_test.go b/internal/outpost/proxyv2/application/mode_forward_envoy_test.go index a8b2abfa00..dbb8b5412f 100644 --- a/internal/outpost/proxyv2/application/mode_forward_envoy_test.go +++ b/internal/outpost/proxyv2/application/mode_forward_envoy_test.go @@ -32,16 +32,14 @@ func TestForwardHandleEnvoy_Single_Headers(t *testing.T) { a.forwardHandleEnvoy(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://ext.t.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://ext.t.goauthentik.io/app", st.Redirect) } func TestForwardHandleEnvoy_Single_Claims(t *testing.T) { @@ -102,15 +100,13 @@ func TestForwardHandleEnvoy_Domain_Header(t *testing.T) { a.forwardHandleEnvoy(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://test.goauthentik.io/app", st.Redirect) } diff --git a/internal/outpost/proxyv2/application/mode_forward_traefik_test.go b/internal/outpost/proxyv2/application/mode_forward_traefik_test.go index 227dc1cb52..a6b8963a83 100644 --- a/internal/outpost/proxyv2/application/mode_forward_traefik_test.go +++ b/internal/outpost/proxyv2/application/mode_forward_traefik_test.go @@ -47,16 +47,14 @@ func TestForwardHandleTraefik_Single_Headers(t *testing.T) { a.forwardHandleTraefik(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://test.goauthentik.io/app", st.Redirect) } func TestForwardHandleTraefik_Single_Claims(t *testing.T) { @@ -134,14 +132,12 @@ func TestForwardHandleTraefik_Domain_Header(t *testing.T) { a.forwardHandleTraefik(rr, req) assert.Equal(t, http.StatusFound, rr.Code) - loc, _ := rr.Result().Location() - s, _ := a.sessions.Get(req, a.SessionName()) + loc, st := a.assertState(t, req, rr) shouldUrl := url.Values{ "client_id": []string{*a.proxyConfig.ClientId}, "redirect_uri": []string{"https://ext.t.goauthentik.io/outpost.goauthentik.io/callback?X-authentik-auth-callback=true"}, "response_type": []string{"code"}, - "state": []string{s.Values[constants.SessionOAuthState].(string)}, } assert.Equal(t, fmt.Sprintf("http://fake-auth.t.goauthentik.io/auth?%s", shouldUrl.Encode()), loc.String()) - assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) + assert.Equal(t, "http://test.goauthentik.io/app", st.Redirect) } diff --git a/internal/outpost/proxyv2/application/mode_proxy_test.go b/internal/outpost/proxyv2/application/mode_proxy_test.go index a33f7cb96a..7534350db8 100644 --- a/internal/outpost/proxyv2/application/mode_proxy_test.go +++ b/internal/outpost/proxyv2/application/mode_proxy_test.go @@ -56,7 +56,7 @@ func TestProxy_Redirect_Subdirectory(t *testing.T) { loc, _ := rr.Result().Location() assert.Equal( t, - "https://ext.t.goauthentik.io/subdir/outpost.goauthentik.io/start?rd=https%3A%2F%2Fext.t.goauthentik.io%2Ffoo", + "https://ext.t.goauthentik.io/subdir/outpost.goauthentik.io/start?rd=https%3A%2F%2Fext.t.goauthentik.io%2Fsubdir%2Ffoo", loc.String(), ) } diff --git a/internal/outpost/proxyv2/application/oauth.go b/internal/outpost/proxyv2/application/oauth.go index 9f9c18d8f2..f2dc93319d 100644 --- a/internal/outpost/proxyv2/application/oauth.go +++ b/internal/outpost/proxyv2/application/oauth.go @@ -1,13 +1,10 @@ package application import ( - "encoding/base64" "net/http" "net/url" "strings" - "time" - "github.com/gorilla/securecookie" "goauthentik.io/api/v3" "goauthentik.io/internal/outpost/proxyv2/constants" ) @@ -48,69 +45,59 @@ func (a *Application) checkRedirectParam(r *http.Request) (string, bool) { return u.String(), true } -func (a *Application) handleAuthStart(rw http.ResponseWriter, r *http.Request) { - newState := base64.RawURLEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) +func (a *Application) handleAuthStart(rw http.ResponseWriter, r *http.Request, fwd string) { + state, err := a.createState(r, fwd) + if err != nil { + a.log.WithError(err).Warning("failed to create state") + return + } s, _ := a.sessions.Get(r, a.SessionName()) - // Check if we already have a state in the session, - // and if we do we don't do anything here - currentState, ok := s.Values[constants.SessionOAuthState].(string) - if ok { - claims, err := a.checkAuth(rw, r) - if err != nil && claims != nil { - a.log.Trace("auth start request with existing authenticated session") - a.redirect(rw, r) - return - } - a.log.Trace("session already has state, sending redirect to current state") - http.Redirect(rw, r, a.oauthConfig.AuthCodeURL(currentState), http.StatusFound) - return - } - rd, ok := a.checkRedirectParam(r) - if ok { - s.Values[constants.SessionRedirect] = rd - a.log.WithField("rd", rd).Trace("Setting redirect") - } - s.Values[constants.SessionOAuthState] = newState - err := s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session") - } - http.Redirect(rw, r, a.oauthConfig.AuthCodeURL(newState), http.StatusFound) -} - -func (a *Application) handleAuthCallback(rw http.ResponseWriter, r *http.Request) { - s, err := a.sessions.Get(r, a.SessionName()) - if err != nil { - a.log.WithError(err).Trace("failed to get session") - } - state, ok := s.Values[constants.SessionOAuthState] - if !ok { - a.log.Warning("No state saved in session") - a.redirect(rw, r) - return - } - claims, err := a.redeemCallback(state.(string), r.URL, r.Context()) - if err != nil { - a.log.WithError(err).Warning("failed to redeem code") - rw.WriteHeader(400) - // To prevent the user from just refreshing and cause more errors, delete - // the state from the session - delete(s.Values, constants.SessionOAuthState) - err := s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session") - rw.WriteHeader(400) - return - } - return - } - s.Options.MaxAge = int(time.Until(time.Unix(int64(claims.Exp), 0)).Seconds()) - s.Values[constants.SessionClaims] = &claims err = s.Save(r, rw) if err != nil { a.log.WithError(err).Warning("failed to save session") - rw.WriteHeader(400) - return } - a.redirect(rw, r) + http.Redirect(rw, r, a.oauthConfig.AuthCodeURL(state), http.StatusFound) +} + +func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { + s, err := a.sessions.Get(r, a.SessionName()) + if err != nil { + a.log.WithError(err).Warning("failed to decode session") + } + if r.Header.Get(constants.HeaderAuthorization) != "" && *a.proxyConfig.InterceptHeaderAuth { + rw.WriteHeader(401) + er := a.errorTemplates.Execute(rw, ErrorPageData{ + Title: "Unauthenticated", + Message: "Due to 'Receive header authentication' being set, no redirect is performed.", + ProxyPrefix: "/outpost.goauthentik.io", + }) + if er != nil { + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + } + } + + redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path) + + if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { + dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") + // In forward_domain we only check that the current URL's host + // ends with the cookie domain (remove the leading period if set) + if !strings.HasSuffix(r.URL.Hostname(), dom) { + a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found") + redirectUrl = a.proxyConfig.ExternalHost + } + } + if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { + s.Values[constants.SessionRedirect] = redirectUrl + err = s.Save(r, rw) + if err != nil { + a.log.WithError(err).Warning("failed to save session before redirect") + } + } + + urlArgs := url.Values{ + redirectParam: []string{redirectUrl}, + } + authUrl := urlJoin(a.proxyConfig.ExternalHost, "/outpost.goauthentik.io/start") + http.Redirect(rw, r, authUrl+"?"+urlArgs.Encode(), http.StatusFound) } diff --git a/internal/outpost/proxyv2/application/oauth_callback.go b/internal/outpost/proxyv2/application/oauth_callback.go index 13f28e67a3..ac64626378 100644 --- a/internal/outpost/proxyv2/application/oauth_callback.go +++ b/internal/outpost/proxyv2/application/oauth_callback.go @@ -3,22 +3,43 @@ package application import ( "context" "fmt" + "net/http" "net/url" + "time" - log "github.com/sirupsen/logrus" + "goauthentik.io/internal/outpost/proxyv2/constants" "golang.org/x/oauth2" ) -func (a *Application) redeemCallback(savedState string, u *url.URL, c context.Context) (*Claims, error) { - state := u.Query().Get("state") - a.log.WithFields(log.Fields{ - "states": savedState, - "expected": state, - }).Trace("tracing states") - if savedState != state { - return nil, fmt.Errorf("invalid state") +func (a *Application) handleAuthCallback(rw http.ResponseWriter, r *http.Request) { + state := a.stateFromRequest(r) + if state == nil { + a.log.Warning("invalid state") + a.redirect(rw, r) + return } + claims, err := a.redeemCallback(r.URL, r.Context()) + if err != nil { + a.log.WithError(err).Warning("failed to redeem code") + a.redirect(rw, r) + return + } + s, err := a.sessions.Get(r, a.SessionName()) + if err != nil { + a.log.WithError(err).Trace("failed to get session") + } + s.Options.MaxAge = int(time.Until(time.Unix(int64(claims.Exp), 0)).Seconds()) + s.Values[constants.SessionClaims] = &claims + err = s.Save(r, rw) + if err != nil { + a.log.WithError(err).Warning("failed to save session") + rw.WriteHeader(400) + return + } + a.redirect(rw, r) +} +func (a *Application) redeemCallback(u *url.URL, c context.Context) (*Claims, error) { code := u.Query().Get("code") if code == "" { return nil, fmt.Errorf("blank code") diff --git a/internal/outpost/proxyv2/application/oauth_state.go b/internal/outpost/proxyv2/application/oauth_state.go new file mode 100644 index 0000000000..798e658396 --- /dev/null +++ b/internal/outpost/proxyv2/application/oauth_state.go @@ -0,0 +1,95 @@ +package application + +import ( + "encoding/base32" + "encoding/base64" + "fmt" + "net/http" + + "github.com/golang-jwt/jwt/v5" + "github.com/gorilla/securecookie" + "github.com/mitchellh/mapstructure" +) + +type OAuthState struct { + Issuer string `json:"iss" mapstructure:"iss"` + SessionID string `json:"sid" mapstructure:"sid"` + State string `json:"state" mapstructure:"state"` + Redirect string `json:"redirect" mapstructure:"redirect"` +} + +func (oas *OAuthState) GetExpirationTime() (*jwt.NumericDate, error) { return nil, nil } +func (oas *OAuthState) GetIssuedAt() (*jwt.NumericDate, error) { return nil, nil } +func (oas *OAuthState) GetNotBefore() (*jwt.NumericDate, error) { return nil, nil } +func (oas *OAuthState) GetIssuer() (string, error) { return oas.Issuer, nil } +func (oas *OAuthState) GetSubject() (string, error) { return oas.State, nil } +func (oas *OAuthState) GetAudience() (jwt.ClaimStrings, error) { return nil, nil } + +var base32RawStdEncoding = base32.StdEncoding.WithPadding(base32.NoPadding) + +func (a *Application) createState(r *http.Request, fwd string) (string, error) { + s, _ := a.sessions.Get(r, a.SessionName()) + if s.ID == "" { + // Ensure session has an ID + s.ID = base32RawStdEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) + } + st := &OAuthState{ + Issuer: fmt.Sprintf("goauthentik.io/outpost/%s", a.proxyConfig.GetClientId()), + State: base64.RawURLEncoding.EncodeToString(securecookie.GenerateRandomKey(32)), + SessionID: s.ID, + Redirect: fwd, + } + if fwd == "" { + // This should only really be hit for nginx forward_auth + // as for that the auth start redirect URL is generated by the + // reverse proxy, and as such we won't have a request we just + // denied to reference for final URL + rd, ok := a.checkRedirectParam(r) + if ok { + a.log.WithField("rd", rd).Trace("Setting redirect") + st.Redirect = rd + } + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, st) + tokenString, err := token.SignedString([]byte(a.proxyConfig.GetCookieSecret())) + if err != nil { + return "", err + } + return tokenString, nil +} + +func (a *Application) stateFromRequest(r *http.Request) *OAuthState { + stateJwt := r.URL.Query().Get("state") + token, err := jwt.Parse(stateJwt, func(token *jwt.Token) (interface{}, error) { + // Don't forget to validate the alg is what you expect: + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return []byte(a.proxyConfig.GetCookieSecret()), nil + }) + if err != nil { + a.log.WithError(err).Warning("failed to parse state jwt") + return nil + } + iss, err := token.Claims.GetIssuer() + if err != nil { + a.log.WithError(err).Warning("state jwt without issuer") + return nil + } + if iss != fmt.Sprintf("goauthentik.io/outpost/%s", a.proxyConfig.GetClientId()) { + a.log.WithField("issuer", iss).Warning("invalid state jwt issuer") + return nil + } + claims := &OAuthState{} + err = mapstructure.Decode(token.Claims, &claims) + if err != nil { + a.log.WithError(err).Warning("failed to mapdecode") + return nil + } + s, _ := a.sessions.Get(r, a.SessionName()) + if claims.SessionID != s.ID { + a.log.WithField("is", claims.SessionID).WithField("should", s.ID).Warning("mismatched session ID") + return nil + } + return claims +} diff --git a/internal/outpost/proxyv2/application/session.go b/internal/outpost/proxyv2/application/session.go index b30934fb42..a332a7d505 100644 --- a/internal/outpost/proxyv2/application/session.go +++ b/internal/outpost/proxyv2/application/session.go @@ -2,6 +2,8 @@ package application import ( "context" + "crypto/tls" + "crypto/x509" "fmt" "math" "net/http" @@ -19,6 +21,7 @@ import ( "goauthentik.io/internal/outpost/proxyv2/codecs" "goauthentik.io/internal/outpost/proxyv2/constants" "goauthentik.io/internal/outpost/proxyv2/redisstore" + "goauthentik.io/internal/utils" ) const RedisKeyPrefix = "authentik_proxy_session_" @@ -31,11 +34,40 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) maxAge = int(*t) + 1 } if a.isEmbedded { + var tls *tls.Config + if config.Get().Redis.TLS { + tls = utils.GetTLSConfig() + switch strings.ToLower(config.Get().Redis.TLSReqs) { + case "none": + case "false": + tls.InsecureSkipVerify = true + case "required": + break + } + ca := config.Get().Redis.TLSCaCert + if ca != nil { + // Get the SystemCertPool, continue with an empty pool on error + rootCAs, _ := x509.SystemCertPool() + if rootCAs == nil { + rootCAs = x509.NewCertPool() + } + certs, err := os.ReadFile(*ca) + if err != nil { + a.log.WithError(err).Fatalf("Failed to append %s to RootCAs", *ca) + } + // Append our cert to the system pool + if ok := rootCAs.AppendCertsFromPEM(certs); !ok { + a.log.Println("No certs appended, using system certs only") + } + tls.RootCAs = rootCAs + } + } client := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%s:%d", config.Get().Redis.Host, config.Get().Redis.Port), - // Username: config.Get().Redis.Password, - Password: config.Get().Redis.Password, - DB: config.Get().Redis.DB, + Addr: fmt.Sprintf("%s:%d", config.Get().Redis.Host, config.Get().Redis.Port), + Username: config.Get().Redis.Username, + Password: config.Get().Redis.Password, + DB: config.Get().Redis.DB, + TLSConfig: tls, }) // New default RedisStore diff --git a/internal/outpost/proxyv2/application/test.go b/internal/outpost/proxyv2/application/test.go index 827bf79703..f7970776c4 100644 --- a/internal/outpost/proxyv2/application/test.go +++ b/internal/outpost/proxyv2/application/test.go @@ -2,6 +2,9 @@ package application import ( "net/http" + "net/http/httptest" + "net/url" + "testing" "goauthentik.io/api/v3" "goauthentik.io/internal/outpost/ak" @@ -45,11 +48,11 @@ func newTestApplication() *Application { Name: ak.TestSecret(), ClientId: api.PtrString(ak.TestSecret()), ClientSecret: api.PtrString(ak.TestSecret()), + CookieDomain: api.PtrString(""), CookieSecret: api.PtrString(ak.TestSecret()), ExternalHost: "https://ext.t.goauthentik.io", InternalHost: api.PtrString("http://backend"), InternalHostSslValidation: api.PtrBool(true), - CookieDomain: api.PtrString(""), Mode: api.PROXYMODE_FORWARD_SINGLE.Ptr(), SkipPathRegex: api.PtrString("/skip.*"), BasicAuthEnabled: api.PtrBool(true), @@ -67,3 +70,25 @@ func newTestApplication() *Application { ts.apps = append(ts.apps, a) return a } + +func (a *Application) assertState(t *testing.T, req *http.Request, response *httptest.ResponseRecorder) (*url.URL, *OAuthState) { + loc, _ := response.Result().Location() + q := loc.Query() + state := q.Get("state") + a.log.WithField("actual", state).Warning("actual state") + // modify request to set state so we can parse it + nr := req.Clone(req.Context()) + nrq := nr.URL.Query() + nrq.Set("state", state) + nr.URL.RawQuery = nrq.Encode() + // parse state + parsed := a.stateFromRequest(nr) + if parsed == nil { + panic("Could not parse state") + } + + // Remove state from URL + q.Del("state") + loc.RawQuery = q.Encode() + return loc, parsed +} diff --git a/internal/outpost/proxyv2/application/utils.go b/internal/outpost/proxyv2/application/utils.go index d895fa0be9..248d7ddf09 100644 --- a/internal/outpost/proxyv2/application/utils.go +++ b/internal/outpost/proxyv2/application/utils.go @@ -3,88 +3,29 @@ package application import ( "net/http" "net/url" - "path" "strconv" - "strings" - - "goauthentik.io/api/v3" - "goauthentik.io/internal/outpost/proxyv2/constants" ) -func urlPathSet(originalUrl string, newPath string) string { - u, err := url.Parse(originalUrl) - if err != nil { - return originalUrl - } - u.Path = newPath - return u.String() -} - func urlJoin(originalUrl string, newPath string) string { - u, err := url.Parse(originalUrl) + u, err := url.JoinPath(originalUrl, newPath) if err != nil { return originalUrl } - u.Path = path.Join(u.Path, newPath) - return u.String() -} - -func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { - s, err := a.sessions.Get(r, a.SessionName()) - if err != nil { - a.log.WithError(err).Warning("failed to decode session") - } - if r.Header.Get(constants.HeaderAuthorization) != "" && *a.proxyConfig.InterceptHeaderAuth { - rw.WriteHeader(401) - er := a.errorTemplates.Execute(rw, ErrorPageData{ - Title: "Unauthenticated", - Message: "Due to 'Receive header authentication' being set, no redirect is performed.", - ProxyPrefix: "/outpost.goauthentik.io", - }) - if er != nil { - http.Error(rw, "Internal Server Error", http.StatusInternalServerError) - } - } - - redirectUrl := urlPathSet(a.proxyConfig.ExternalHost, r.URL.Path) - - if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { - dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") - // In forward_domain we only check that the current URL's host - // ends with the cookie domain (remove the leading period if set) - if !strings.HasSuffix(r.URL.Hostname(), dom) { - a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found") - redirectUrl = a.proxyConfig.ExternalHost - } - } - if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { - s.Values[constants.SessionRedirect] = redirectUrl - err = s.Save(r, rw) - if err != nil { - a.log.WithError(err).Warning("failed to save session before redirect") - } - } - - urlArgs := url.Values{ - redirectParam: []string{redirectUrl}, - } - authUrl := urlJoin(a.proxyConfig.ExternalHost, "/outpost.goauthentik.io/start") - http.Redirect(rw, r, authUrl+"?"+urlArgs.Encode(), http.StatusFound) + return u } func (a *Application) redirect(rw http.ResponseWriter, r *http.Request) { - redirect := a.proxyConfig.ExternalHost - s, _ := a.sessions.Get(r, a.SessionName()) - redirectR, ok := s.Values[constants.SessionRedirect] - if ok { - redirect = redirectR.(string) + fallbackRedirect := a.proxyConfig.ExternalHost + state := a.stateFromRequest(r) + if state == nil { + rw.WriteHeader(http.StatusBadRequest) + return } - rd, ok := a.checkRedirectParam(r) - if ok { - redirect = rd + if state.Redirect == "" { + state.Redirect = fallbackRedirect } - a.log.WithField("redirect", redirect).Trace("final redirect") - http.Redirect(rw, r, redirect, http.StatusFound) + a.log.WithField("redirect", state.Redirect).Trace("final redirect") + http.Redirect(rw, r, state.Redirect, http.StatusFound) } // toString Generic to string function, currently supports actual strings and integers diff --git a/internal/outpost/proxyv2/hs256/hs256.go b/internal/outpost/proxyv2/hs256/hs256.go index 3df8c73e82..29ace0995d 100644 --- a/internal/outpost/proxyv2/hs256/hs256.go +++ b/internal/outpost/proxyv2/hs256/hs256.go @@ -3,9 +3,10 @@ package hs256 import ( "context" "encoding/base64" + "fmt" "strings" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" ) type KeySet struct { @@ -15,17 +16,23 @@ type KeySet struct { func NewKeySet(secret string) *KeySet { return &KeySet{ - m: jwt.GetSigningMethod("HS256"), + m: jwt.SigningMethodHS256, secret: secret, } } -func (ks *KeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) { - parts := strings.Split(jwt, ".") - err := ks.m.Verify(strings.Join(parts[0:2], "."), parts[2], []byte(ks.secret)) +func (ks *KeySet) VerifySignature(ctx context.Context, rawJWT string) ([]byte, error) { + _, err := jwt.Parse(rawJWT, func(token *jwt.Token) (interface{}, error) { + // Don't forget to validate the alg is what you expect: + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return []byte(ks.secret), nil + }) if err != nil { return nil, err } + parts := strings.Split(rawJWT, ".") payload, err := base64.RawURLEncoding.DecodeString(parts[1]) return payload, err } diff --git a/internal/outpost/radius/handle_access_request.go b/internal/outpost/radius/handle_access_request.go index ea2b5c860b..49f1775965 100644 --- a/internal/outpost/radius/handle_access_request.go +++ b/internal/outpost/radius/handle_access_request.go @@ -21,10 +21,7 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR fe.Params.Add("goauthentik.io/outpost/radius", "true") fe.Answers[flow.StageIdentification] = username - fe.Answers[flow.StagePassword] = rfc2865.UserPassword_GetString(r.Packet) - if r.pi.MFASupport { - fe.CheckPasswordInlineMFA() - } + fe.SetSecrets(rfc2865.UserPassword_GetString(r.Packet), r.pi.MFASupport) passed, err := fe.Execute() if err != nil { diff --git a/internal/web/brand_tls/brand_tls.go b/internal/web/brand_tls/brand_tls.go index b2d57584fb..7f19e33eb6 100644 --- a/internal/web/brand_tls/brand_tls.go +++ b/internal/web/brand_tls/brand_tls.go @@ -78,7 +78,7 @@ func (w *Watcher) GetCertificate(ch *tls.ClientHelloInfo) (*tls.Certificate, err if bestSelection == nil { return w.fallback, nil } - cert := w.cs.Get(*bestSelection.WebCertificate.Get()) + cert := w.cs.Get(bestSelection.GetWebCertificate()) if cert == nil { return w.fallback, nil } diff --git a/internal/web/proxy.go b/internal/web/proxy.go index 56f81a0726..ccc9bd0eb0 100644 --- a/internal/web/proxy.go +++ b/internal/web/proxy.go @@ -32,9 +32,6 @@ func (ws *WebServer) configureProxy() { } rp.ErrorHandler = ws.proxyErrorHandler rp.ModifyResponse = ws.proxyModifyResponse - ws.m.Path("/-/health/live/").HandlerFunc(sentry.SentryNoSample(func(rw http.ResponseWriter, r *http.Request) { - rw.WriteHeader(204) - })) ws.m.PathPrefix("/").HandlerFunc(sentry.SentryNoSample(func(rw http.ResponseWriter, r *http.Request) { if !ws.g.IsRunning() { ws.proxyErrorHandler(rw, r, errors.New("authentik starting")) diff --git a/internal/web/static.go b/internal/web/static.go index 1d6d1888ec..617c94578f 100644 --- a/internal/web/static.go +++ b/internal/web/static.go @@ -14,26 +14,27 @@ import ( ) func (ws *WebServer) configureStatic() { - statRouter := ws.lh.NewRoute().Subrouter() - statRouter.Use(ws.staticHeaderMiddleware) - indexLessRouter := statRouter.NewRoute().Subrouter() - indexLessRouter.Use(web.DisableIndex) - distFs := http.FileServer(http.Dir("./web/dist")) - distHandler := http.StripPrefix("/static/dist/", distFs) - authentikHandler := http.StripPrefix("/static/authentik/", http.FileServer(http.Dir("./web/authentik"))) - helpHandler := http.FileServer(http.Dir("./website/help/")) - indexLessRouter.PathPrefix("/static/dist/").Handler(distHandler) - indexLessRouter.PathPrefix("/static/authentik/").Handler(authentikHandler) + staticRouter := ws.lh.NewRoute().Subrouter() + staticRouter.Use(ws.staticHeaderMiddleware) + staticRouter.Use(web.DisableIndex) - // Prevent font-loading issues on safari, which loads fonts relatively to the URL the browser is on - indexLessRouter.PathPrefix("/if/flow/{flow_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + distFs := http.FileServer(http.Dir("./web/dist")) + authentikHandler := http.StripPrefix("/static/authentik/", http.FileServer(http.Dir("./web/authentik"))) + + // Root file paths, from which they should be accessed + staticRouter.PathPrefix("/static/dist/").Handler(http.StripPrefix("/static/dist/", distFs)) + staticRouter.PathPrefix("/static/authentik/").Handler(authentikHandler) + + // Also serve assets folder in specific interfaces since fonts in patternfly are imported + // with a relative path + staticRouter.PathPrefix("/if/flow/{flow_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) web.DisableIndex(http.StripPrefix(fmt.Sprintf("/if/flow/%s", vars["flow_slug"]), distFs)).ServeHTTP(rw, r) }) - indexLessRouter.PathPrefix("/if/admin/assets").Handler(http.StripPrefix("/if/admin", distFs)) - indexLessRouter.PathPrefix("/if/user/assets").Handler(http.StripPrefix("/if/user", distFs)) - indexLessRouter.PathPrefix("/if/rac/{app_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + staticRouter.PathPrefix("/if/admin/assets").Handler(http.StripPrefix("/if/admin", distFs)) + staticRouter.PathPrefix("/if/user/assets").Handler(http.StripPrefix("/if/user", distFs)) + staticRouter.PathPrefix("/if/rac/{app_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) web.DisableIndex(http.StripPrefix(fmt.Sprintf("/if/rac/%s", vars["app_slug"]), distFs)).ServeHTTP(rw, r) @@ -42,12 +43,13 @@ func (ws *WebServer) configureStatic() { // Media files, if backend is file if config.Get().Storage.Media.Backend == "file" { fsMedia := http.FileServer(http.Dir(config.Get().Storage.Media.File.Path)) - indexLessRouter.PathPrefix("/media/").Handler(http.StripPrefix("/media", fsMedia)) + staticRouter.PathPrefix("/media/").Handler(http.StripPrefix("/media", fsMedia)) } - statRouter.PathPrefix("/if/help/").Handler(http.StripPrefix("/if/help/", helpHandler)) - statRouter.PathPrefix("/help").Handler(http.RedirectHandler("/if/help/", http.StatusMovedPermanently)) + staticRouter.PathPrefix("/if/help/").Handler(http.StripPrefix("/if/help/", http.FileServer(http.Dir("./website/help/")))) + staticRouter.PathPrefix("/help").Handler(http.RedirectHandler("/if/help/", http.StatusMovedPermanently)) + // Static misc files ws.lh.Path("/robots.txt").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Header()["Content-Type"] = []string{"text/plain"} rw.WriteHeader(200) diff --git a/ldap.Dockerfile b/ldap.Dockerfile index 6efe55e3bf..44347e6738 100644 --- a/ldap.Dockerfile +++ b/ldap.Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # Stage 1: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.6-bookworm AS builder +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.22-fips-bookworm AS builder ARG TARGETOS ARG TARGETARCH @@ -12,20 +12,26 @@ ARG GOARCH=$TARGETARCH WORKDIR /go/src/goauthentik.io +RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ + dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu + RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \ --mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \ --mount=type=bind,target=/go/src/goauthentik.io/gen-go-api,src=./gen-go-api \ --mount=type=cache,target=/go/pkg/mod \ go mod download -ENV CGO_ENABLED=0 COPY . . RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \ - GOARM="${TARGETVARIANT#v}" go build -o /go/ldap ./cmd/ldap + if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \ + CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \ + go build -o /go/ldap ./cmd/ldap # Stage 2: Run -FROM gcr.io/distroless/static-debian11:debug +FROM ghcr.io/goauthentik/fips-debian:bookworm-slim-fips ARG GIT_BUILD_HASH ENV GIT_BUILD_HASH=$GIT_BUILD_HASH @@ -44,4 +50,6 @@ EXPOSE 3389 6636 9300 USER 1000 +ENV GOFIPS=1 + ENTRYPOINT ["/ldap"] diff --git a/lifecycle/ak b/lifecycle/ak index 941b12594d..2ae5f4792f 100755 --- a/lifecycle/ak +++ b/lifecycle/ak @@ -7,7 +7,6 @@ function log { function wait_for_db { python -m lifecycle.wait_for_db - python -m lifecycle.migrate log "Bootstrap completed" } @@ -55,7 +54,7 @@ function cleanup { } function prepare_debug { - poetry install --no-ansi --no-interaction + VIRTUAL_ENV=/ak-root/venv poetry install --no-ansi --no-interaction touch /unittest.xml chown authentik:authentik /unittest.xml } @@ -65,7 +64,6 @@ if [[ "${AUTHENTIK_REMOTE_DEBUG}" == "true" ]]; then fi if [[ "$1" == "server" ]]; then - wait_for_db set_mode "server" # If we have bootstrap credentials set, run bootstrap tasks outside of main server # sync, so that we can sure the first start actually has working bootstrap @@ -75,7 +73,6 @@ if [[ "$1" == "server" ]]; then fi run_authentik elif [[ "$1" == "worker" ]]; then - wait_for_db set_mode "worker" check_if_root "python -m manage worker" elif [[ "$1" == "worker-status" ]]; then @@ -86,6 +83,8 @@ elif [[ "$1" == "bash" ]]; then /bin/bash elif [[ "$1" == "test-all" ]]; then prepare_debug + chmod 777 /root + pip install --force-reinstall /wheels/* check_if_root "python -m manage test authentik" elif [[ "$1" == "healthcheck" ]]; then run_authentik healthcheck $(cat $MODE_FILE) diff --git a/lifecycle/ak.py b/lifecycle/ak.py index deac5a7d6d..b17c070ab7 100644 --- a/lifecycle/ak.py +++ b/lifecycle/ak.py @@ -1,4 +1,5 @@ """Wrapper for lifecycle/ak, to be installed by poetry""" + from os import system from pathlib import Path from sys import argv diff --git a/lifecycle/gunicorn.conf.py b/lifecycle/gunicorn.conf.py index 2ae3d8ca8e..c158680697 100644 --- a/lifecycle/gunicorn.conf.py +++ b/lifecycle/gunicorn.conf.py @@ -1,13 +1,15 @@ """Gunicorn config""" + import os from hashlib import sha512 -from multiprocessing import cpu_count from os import makedirs from pathlib import Path from tempfile import gettempdir from typing import TYPE_CHECKING -from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME +from cryptography.exceptions import InternalError +from cryptography.hazmat.backends.openssl.backend import backend +from defusedxml import defuse_stdlib from prometheus_client.values import MultiProcessValue from authentik import get_full_version @@ -16,11 +18,25 @@ from authentik.lib.logging import get_logger_config from authentik.lib.utils.http import get_http_session from authentik.lib.utils.reflection import get_env from authentik.root.install_id import get_install_id_raw +from lifecycle.migrate import run_migrations +from lifecycle.wait_for_db import wait_for_db from lifecycle.worker import DjangoUvicornWorker if TYPE_CHECKING: + from gunicorn.app.wsgiapp import WSGIApplication from gunicorn.arbiter import Arbiter + from authentik.root.asgi import AuthentikAsgi + +defuse_stdlib() + +try: + backend._enable_fips() +except InternalError: + pass + +wait_for_db() + _tmp = Path(gettempdir()) worker_class = "lifecycle.worker.DjangoUvicornWorker" worker_tmp_dir = str(_tmp.joinpath("authentik_worker_tmp")) @@ -34,17 +50,14 @@ bind = f"unix://{str(_tmp.joinpath('authentik-core.sock'))}" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings") os.environ.setdefault("PROMETHEUS_MULTIPROC_DIR", prometheus_tmp_dir) +preload_app = True + max_requests = 1000 max_requests_jitter = 50 logconfig_dict = get_logger_config() -# if we're running in kubernetes, use fixed workers because we can scale with more pods -# otherwise (assume docker-compose), use as much as we can -if SERVICE_HOST_ENV_NAME in os.environ: - default_workers = 2 -else: - default_workers = max(cpu_count() * 0.25, 1) + 1 # Minimum of 2 workers +default_workers = 2 workers = CONFIG.get_int("web.workers", default_workers) threads = CONFIG.get_int("web.threads", 4) @@ -99,6 +112,18 @@ def pre_fork(server: "Arbiter", worker: DjangoUvicornWorker): worker._worker_id = _next_worker_id(server) +def post_worker_init(worker: DjangoUvicornWorker): + """Notify ASGI app that its started up""" + # Only trigger startup DB logic on first worker + # Startup code that imports code or is otherwise needed in every worker + # does not use this signal, so we can skip this safely + if worker._worker_id != 1: + return + app: WSGIApplication = worker.app + root_app: AuthentikAsgi = app.callable + root_app.call_startup() + + if not CONFIG.get_bool("disable_startup_analytics", False): env = get_env() should_send = env not in ["dev", "ci"] @@ -120,7 +145,7 @@ if not CONFIG.get_bool("disable_startup_analytics", False): }, timeout=5, ) - # pylint: disable=broad-exception-caught + except Exception: # nosec pass @@ -128,3 +153,5 @@ if CONFIG.get_bool("remote_debug"): import debugpy debugpy.listen(("0.0.0.0", 6800)) # nosec + +run_migrations() diff --git a/lifecycle/migrate.py b/lifecycle/migrate.py index 489ffa909a..ea22aa8fb7 100755 --- a/lifecycle/migrate.py +++ b/lifecycle/migrate.py @@ -53,21 +53,23 @@ class BaseMigration: def wait_for_lock(cursor: Cursor): """lock an advisory lock to prevent multiple instances from migrating at once""" + global LOCKED # noqa: PLW0603 LOGGER.info("waiting to acquire database lock") cursor.execute("SELECT pg_advisory_lock(%s)", (ADV_LOCK_UID,)) - # pylint: disable=global-statement - global LOCKED LOCKED = True def release_lock(cursor: Cursor): """Release database lock""" + global LOCKED # noqa: PLW0603 if not LOCKED: return + LOGGER.info("releasing database lock") cursor.execute("SELECT pg_advisory_unlock(%s)", (ADV_LOCK_UID,)) + LOCKED = False -if __name__ == "__main__": +def run_migrations(): conn = connect( dbname=CONFIG.get("postgresql.name"), user=CONFIG.get("postgresql.user"), @@ -81,6 +83,7 @@ if __name__ == "__main__": ) curr = conn.cursor() try: + wait_for_lock(curr) for migration_path in Path(__file__).parent.absolute().glob("system_migrations/*.py"): spec = spec_from_file_location("lifecycle.system_migrations", migration_path) if not spec: @@ -93,14 +96,11 @@ if __name__ == "__main__": continue migration = sub(curr, conn) if migration.needs_migration(): - wait_for_lock(curr) LOGGER.info("Migration needs to be applied", migration=migration_path.name) migration.run() LOGGER.info("Migration finished applying", migration=migration_path.name) - release_lock(curr) LOGGER.info("applying django migrations") environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings") - wait_for_lock(curr) try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -116,3 +116,9 @@ if __name__ == "__main__": ) finally: release_lock(curr) + curr.close() + conn.close() + + +if __name__ == "__main__": + run_migrations() diff --git a/lifecycle/system_migrations/template_schema.py b/lifecycle/system_migrations/template_schema.py new file mode 100644 index 0000000000..9ab53c0605 --- /dev/null +++ b/lifecycle/system_migrations/template_schema.py @@ -0,0 +1,12 @@ +from lifecycle.migrate import BaseMigration + + +class Migration(BaseMigration): + def needs_migration(self) -> bool: + self.cur.execute( + "SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'template';" + ) + return not bool(self.cur.rowcount) + + def run(self): + self.cur.execute("CREATE SCHEMA IF NOT EXISTS template; COMMIT;") diff --git a/lifecycle/system_migrations/to_0_13_authentik.py b/lifecycle/system_migrations/to_0_13_authentik.py index b621859d7c..c56d3b2d1f 100644 --- a/lifecycle/system_migrations/to_0_13_authentik.py +++ b/lifecycle/system_migrations/to_0_13_authentik.py @@ -116,6 +116,7 @@ class Migration(BaseMigration): host=CONFIG.get("redis.host"), port=6379, db=db, + username=CONFIG.get("redis.username"), password=CONFIG.get("redis.password"), ) redis.flushall() diff --git a/lifecycle/wait_for_db.py b/lifecycle/wait_for_db.py index 005846a2c2..72c1ce42dc 100755 --- a/lifecycle/wait_for_db.py +++ b/lifecycle/wait_for_db.py @@ -3,60 +3,61 @@ import authentik. This is done by the dockerfile.""" from sys import exit as sysexit from time import sleep -from urllib.parse import quote_plus from psycopg import OperationalError, connect from redis import Redis from redis.exceptions import RedisError -from authentik.lib.config import CONFIG - -CONFIG.log("info", "Starting authentik bootstrap") - -# Sanity check, ensure SECRET_KEY is set before we even check for database connectivity -if CONFIG.get("secret_key") is None or len(CONFIG.get("secret_key")) == 0: - CONFIG.log("info", "----------------------------------------------------------------------") - CONFIG.log("info", "Secret key missing, check https://goauthentik.io/docs/installation/.") - CONFIG.log("info", "----------------------------------------------------------------------") - sysexit(1) +from authentik.lib.config import CONFIG, redis_url -while True: - try: - conn = connect( - dbname=CONFIG.get("postgresql.name"), - user=CONFIG.get("postgresql.user"), - password=CONFIG.get("postgresql.password"), - host=CONFIG.get("postgresql.host"), - port=CONFIG.get_int("postgresql.port"), - sslmode=CONFIG.get("postgresql.sslmode"), - sslrootcert=CONFIG.get("postgresql.sslrootcert"), - sslcert=CONFIG.get("postgresql.sslcert"), - sslkey=CONFIG.get("postgresql.sslkey"), - ) - conn.cursor() - break - except OperationalError as exc: - sleep(1) - CONFIG.log("info", f"PostgreSQL connection failed, retrying... ({exc})") -CONFIG.log("info", "PostgreSQL connection successful") +def check_postgres(): + while True: + try: + conn = connect( + dbname=CONFIG.get("postgresql.name"), + user=CONFIG.get("postgresql.user"), + password=CONFIG.get("postgresql.password"), + host=CONFIG.get("postgresql.host"), + port=CONFIG.get_int("postgresql.port"), + sslmode=CONFIG.get("postgresql.sslmode"), + sslrootcert=CONFIG.get("postgresql.sslrootcert"), + sslcert=CONFIG.get("postgresql.sslcert"), + sslkey=CONFIG.get("postgresql.sslkey"), + ) + conn.cursor() + break + except OperationalError as exc: + sleep(1) + CONFIG.log("info", f"PostgreSQL connection failed, retrying... ({exc})") + CONFIG.log("info", "PostgreSQL connection successful") -REDIS_PROTOCOL_PREFIX = "redis://" -if CONFIG.get_bool("redis.tls", False): - REDIS_PROTOCOL_PREFIX = "rediss://" -REDIS_URL = ( - f"{REDIS_PROTOCOL_PREFIX}:" - f"{quote_plus(CONFIG.get('redis.password'))}@{quote_plus(CONFIG.get('redis.host'))}:" - f"{CONFIG.get_int('redis.port')}/{CONFIG.get('redis.db')}" -) -while True: - try: - redis = Redis.from_url(REDIS_URL) - redis.ping() - break - except RedisError as exc: - sleep(1) - CONFIG.log("info", f"Redis Connection failed, retrying... ({exc})", redis_url=REDIS_URL) -CONFIG.log("info", "Redis Connection successful") -CONFIG.log("info", "Finished authentik bootstrap") +def check_redis(): + url = CONFIG.get("cache.url") or redis_url(CONFIG.get("redis.db")) + while True: + try: + redis = Redis.from_url(url) + redis.ping() + break + except RedisError as exc: + sleep(1) + CONFIG.log("info", f"Redis Connection failed, retrying... ({exc})") + CONFIG.log("info", "Redis Connection successful") + + +def wait_for_db(): + CONFIG.log("info", "Starting authentik bootstrap") + # Sanity check, ensure SECRET_KEY is set before we even check for database connectivity + if CONFIG.get("secret_key") is None or len(CONFIG.get("secret_key")) == 0: + CONFIG.log("info", "----------------------------------------------------------------------") + CONFIG.log("info", "Secret key missing, check https://goauthentik.io/docs/installation/.") + CONFIG.log("info", "----------------------------------------------------------------------") + sysexit(1) + check_postgres() + check_redis() + CONFIG.log("info", "Finished authentik bootstrap") + + +if __name__ == "__main__": + wait_for_db() diff --git a/lifecycle/worker.py b/lifecycle/worker.py index 41d09d5cbd..9d5c09fe88 100644 --- a/lifecycle/worker.py +++ b/lifecycle/worker.py @@ -1,4 +1,5 @@ """Uvicorn worker""" + from uvicorn.workers import UvicornWorker @@ -11,3 +12,5 @@ class DjangoUvicornWorker(UvicornWorker): "lifespan": "off", "ws": "wsproto", } + + _worker_id: int diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 36e5d27b58..b5e901f33a 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -18,32 +18,32 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: authentik/api/schema.py:25 +#: authentik/api/schema.py msgid "Generic API Error" msgstr "" -#: authentik/api/schema.py:33 +#: authentik/api/schema.py msgid "Validation Error" msgstr "" -#: authentik/blueprints/api.py:43 +#: authentik/blueprints/api.py msgid "Blueprint file does not exist" msgstr "" -#: authentik/blueprints/api.py:54 -#, python-format -msgid "Failed to validate blueprint: %(logs)s" +#: authentik/blueprints/api.py +#, python-brace-format +msgid "Failed to validate blueprint: {logs}" msgstr "" -#: authentik/blueprints/api.py:59 +#: authentik/blueprints/api.py msgid "Either path or content must be set." msgstr "" -#: authentik/blueprints/models.py:30 +#: authentik/blueprints/models.py msgid "Managed by authentik" msgstr "" -#: authentik/blueprints/models.py:32 +#: authentik/blueprints/models.py msgid "" "Objects that are managed by authentik. These objects are created and updated " "automatically. This flag only indicates that an object can be overwritten by " @@ -51,255 +51,268 @@ msgid "" "to be overwritten in a later update." msgstr "" -#: authentik/blueprints/models.py:112 +#: authentik/blueprints/models.py msgid "Blueprint Instance" msgstr "" -#: authentik/blueprints/models.py:113 +#: authentik/blueprints/models.py msgid "Blueprint Instances" msgstr "" -#: authentik/blueprints/v1/exporter.py:62 -#, python-format -msgid "authentik Export - %(date)s" +#: authentik/blueprints/v1/exporter.py +#, python-brace-format +msgid "authentik Export - {date}" msgstr "" -#: authentik/blueprints/v1/tasks.py:145 authentik/crypto/tasks.py:87 +#: authentik/blueprints/v1/tasks.py authentik/crypto/tasks.py #, python-format msgid "Successfully imported %(count)d files." msgstr "" -#: authentik/brands/models.py:22 +#: authentik/brands/models.py msgid "" "Domain that activates this brand. Can be a superset, i.e. `a.b` for `aa.b` " "and `ba.b`" msgstr "" -#: authentik/brands/models.py:58 +#: authentik/brands/models.py msgid "Web Certificate used by the authentik Core webserver." msgstr "" -#: authentik/brands/models.py:84 +#: authentik/brands/models.py msgid "Brand" msgstr "" -#: authentik/brands/models.py:85 +#: authentik/brands/models.py msgid "Brands" msgstr "" -#: authentik/core/api/providers.py:122 -msgid "SAML Provider from Metadata" +#: authentik/core/api/providers.py +msgid "" +"When not set all providers are returned. When set to true, only backchannel " +"providers are returned. When set to false, backchannel providers are excluded" msgstr "" -#: authentik/core/api/providers.py:123 -msgid "Create a SAML Provider by importing its Metadata." -msgstr "" - -#: authentik/core/api/users.py:149 +#: authentik/core/api/users.py msgid "No leading or trailing slashes allowed." msgstr "" -#: authentik/core/api/users.py:152 +#: authentik/core/api/users.py msgid "No empty segments in user path allowed." msgstr "" -#: authentik/core/models.py:92 +#: authentik/core/models.py msgid "name" msgstr "" -#: authentik/core/models.py:94 +#: authentik/core/models.py msgid "Users added to this group will be superusers." msgstr "" -#: authentik/core/models.py:168 +#: authentik/core/models.py msgid "Group" msgstr "" -#: authentik/core/models.py:169 +#: authentik/core/models.py msgid "Groups" msgstr "" -#: authentik/core/models.py:184 +#: authentik/core/models.py +msgid "Add user to group" +msgstr "" + +#: authentik/core/models.py +msgid "Remove user from group" +msgstr "" + +#: authentik/core/models.py msgid "User's display name." msgstr "" -#: authentik/core/models.py:280 authentik/providers/oauth2/models.py:295 +#: authentik/core/models.py authentik/providers/oauth2/models.py msgid "User" msgstr "" -#: authentik/core/models.py:281 +#: authentik/core/models.py msgid "Users" msgstr "" -#: authentik/core/models.py:283 -#: authentik/stages/email/templates/email/password_reset.html:28 +#: authentik/core/models.py +#: authentik/stages/email/templates/email/password_reset.html msgid "Reset Password" msgstr "" -#: authentik/core/models.py:284 +#: authentik/core/models.py msgid "Can impersonate other users" msgstr "" -#: authentik/core/models.py:285 authentik/rbac/models.py:54 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can assign permissions to users" msgstr "" -#: authentik/core/models.py:286 authentik/rbac/models.py:55 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can unassign permissions from users" msgstr "" -#: authentik/core/models.py:308 +#: authentik/core/models.py +msgid "Can preview user data sent to providers" +msgstr "" + +#: authentik/core/models.py +msgid "View applications the user has access to" +msgstr "" + +#: authentik/core/models.py msgid "" "Flow used for authentication when the associated application is accessed by " "an un-authenticated user." msgstr "" -#: authentik/core/models.py:318 +#: authentik/core/models.py msgid "Flow used when authorizing this provider." msgstr "" -#: authentik/core/models.py:330 +#: authentik/core/models.py msgid "" "Accessed from applications; optional backchannel providers for protocols " "like LDAP and SCIM." msgstr "" -#: authentik/core/models.py:385 +#: authentik/core/models.py msgid "Application's display Name." msgstr "" -#: authentik/core/models.py:386 +#: authentik/core/models.py msgid "Internal application name, used in URLs." msgstr "" -#: authentik/core/models.py:398 +#: authentik/core/models.py msgid "Open launch URL in a new browser tab or window." msgstr "" -#: authentik/core/models.py:462 +#: authentik/core/models.py msgid "Application" msgstr "" -#: authentik/core/models.py:463 +#: authentik/core/models.py msgid "Applications" msgstr "" -#: authentik/core/models.py:469 +#: authentik/core/models.py msgid "Use the source-specific identifier" msgstr "" -#: authentik/core/models.py:471 +#: authentik/core/models.py msgid "" "Link to a user with identical email address. Can have security implications " "when a source doesn't validate email addresses." msgstr "" -#: authentik/core/models.py:475 +#: authentik/core/models.py msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." msgstr "" -#: authentik/core/models.py:478 +#: authentik/core/models.py msgid "" "Link to a user with identical username. Can have security implications when " "a username is used with another source." msgstr "" -#: authentik/core/models.py:482 +#: authentik/core/models.py msgid "" "Use the user's username, but deny enrollment when the username already " "exists." msgstr "" -#: authentik/core/models.py:489 +#: authentik/core/models.py msgid "Source's display Name." msgstr "" -#: authentik/core/models.py:490 +#: authentik/core/models.py msgid "Internal source name, used in URLs." msgstr "" -#: authentik/core/models.py:509 +#: authentik/core/models.py msgid "Flow to use when authenticating existing users." msgstr "" -#: authentik/core/models.py:518 +#: authentik/core/models.py msgid "Flow to use when enrolling new users." msgstr "" -#: authentik/core/models.py:526 +#: authentik/core/models.py msgid "" "How the source determines if an existing user should be authenticated or a " "new user enrolled." msgstr "" -#: authentik/core/models.py:698 +#: authentik/core/models.py msgid "Token" msgstr "" -#: authentik/core/models.py:699 +#: authentik/core/models.py msgid "Tokens" msgstr "" -#: authentik/core/models.py:704 +#: authentik/core/models.py msgid "View token's key" msgstr "" -#: authentik/core/models.py:740 +#: authentik/core/models.py msgid "Property Mapping" msgstr "" -#: authentik/core/models.py:741 +#: authentik/core/models.py msgid "Property Mappings" msgstr "" -#: authentik/core/models.py:778 +#: authentik/core/models.py msgid "Authenticated Session" msgstr "" -#: authentik/core/models.py:779 +#: authentik/core/models.py msgid "Authenticated Sessions" msgstr "" -#: authentik/core/sources/flow_manager.py:190 -#, python-format +#: authentik/core/sources/flow_manager.py +#, python-brace-format msgid "" -"Request to authenticate with %(source)s has been denied. Please authenticate " +"Request to authenticate with {source} has been denied. Please authenticate " "with the source you've previously signed up with." msgstr "" -#: authentik/core/sources/flow_manager.py:242 +#: authentik/core/sources/flow_manager.py msgid "Configured flow does not exist." msgstr "" -#: authentik/core/sources/flow_manager.py:272 -#: authentik/core/sources/flow_manager.py:324 -#, python-format -msgid "Successfully authenticated with %(source)s!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully authenticated with {source}!" msgstr "" -#: authentik/core/sources/flow_manager.py:296 -#, python-format -msgid "Successfully linked %(source)s!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully linked {source}!" msgstr "" -#: authentik/core/sources/flow_manager.py:315 +#: authentik/core/sources/flow_manager.py msgid "Source is not configured for enrollment." msgstr "" -#: authentik/core/templates/if/end_session.html:7 +#: authentik/core/templates/if/end_session.html msgid "End session" msgstr "" -#: authentik/core/templates/if/end_session.html:11 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" "You've logged out of %(application)s.\n" msgstr "" -#: authentik/core/templates/if/end_session.html:19 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -309,11 +322,11 @@ msgid "" " " msgstr "" -#: authentik/core/templates/if/end_session.html:25 +#: authentik/core/templates/if/end_session.html msgid "Go back to overview" msgstr "" -#: authentik/core/templates/if/end_session.html:29 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -321,7 +334,7 @@ msgid "" " " msgstr "" -#: authentik/core/templates/if/end_session.html:36 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -329,361 +342,455 @@ msgid "" " " msgstr "" -#: authentik/core/templates/if/error.html:18 +#: authentik/core/templates/if/error.html msgid "Go home" msgstr "" -#: authentik/core/templates/login/base_full.html:75 +#: authentik/core/templates/login/base_full.html msgid "Powered by authentik" msgstr "" -#: authentik/core/views/apps.py:53 -#: authentik/providers/oauth2/views/authorize.py:434 -#: authentik/providers/oauth2/views/device_init.py:70 -#: authentik/providers/saml/views/sso.py:70 +#: authentik/core/views/apps.py authentik/providers/oauth2/views/authorize.py +#: authentik/providers/oauth2/views/device_init.py +#: authentik/providers/saml/views/sso.py #, python-format msgid "You're about to sign into %(application)s." msgstr "" -#: authentik/crypto/api.py:179 +#: authentik/crypto/api.py msgid "Subject-alt name" msgstr "" -#: authentik/crypto/models.py:30 +#: authentik/crypto/builder.py +msgid "rsa" +msgstr "" + +#: authentik/crypto/builder.py +msgid "ecdsa" +msgstr "" + +#: authentik/crypto/models.py msgid "PEM-encoded Certificate data" msgstr "" -#: authentik/crypto/models.py:33 +#: authentik/crypto/models.py msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." msgstr "" -#: authentik/crypto/models.py:101 +#: authentik/crypto/models.py msgid "Certificate-Key Pair" msgstr "" -#: authentik/crypto/models.py:102 +#: authentik/crypto/models.py msgid "Certificate-Key Pairs" msgstr "" -#: authentik/enterprise/api.py:33 +#: authentik/enterprise/api.py msgid "Enterprise is required to create/update this object." msgstr "" -#: authentik/enterprise/models.py:183 +#: authentik/enterprise/models.py msgid "License" msgstr "" -#: authentik/enterprise/models.py:184 +#: authentik/enterprise/models.py msgid "Licenses" msgstr "" -#: authentik/enterprise/models.py:206 +#: authentik/enterprise/models.py msgid "License Usage" msgstr "" -#: authentik/enterprise/models.py:207 +#: authentik/enterprise/models.py msgid "License Usage Records" msgstr "" -#: authentik/enterprise/policy.py:18 +#: authentik/enterprise/policy.py msgid "Enterprise required to access this feature." msgstr "" -#: authentik/enterprise/policy.py:20 +#: authentik/enterprise/policy.py msgid "Feature only accessible for internal users." msgstr "" -#: authentik/enterprise/providers/rac/models.py:48 -#: authentik/stages/user_login/models.py:39 +#: authentik/enterprise/providers/google_workspace/models.py +#: authentik/enterprise/providers/microsoft_entra/models.py +#: authentik/providers/scim/models.py authentik/sources/ldap/models.py +msgid "Property mappings used for group creation/updating." +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Providers" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mapping" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mappings" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider User" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Users" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Group" +msgstr "" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Groups" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Providers" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mapping" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mappings" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider User" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Group" +msgstr "" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Groups" +msgstr "" + +#: authentik/enterprise/providers/rac/models.py +#: authentik/stages/user_login/models.py msgid "" "Determines how long a session lasts. Default of 0 means that the sessions " "lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" msgstr "" -#: authentik/enterprise/providers/rac/models.py:71 +#: authentik/enterprise/providers/rac/models.py +msgid "When set to true, connection tokens will be deleted upon disconnect." +msgstr "" + +#: authentik/enterprise/providers/rac/models.py msgid "RAC Provider" msgstr "" -#: authentik/enterprise/providers/rac/models.py:72 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Providers" msgstr "" -#: authentik/enterprise/providers/rac/models.py:100 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoint" msgstr "" -#: authentik/enterprise/providers/rac/models.py:101 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoints" msgstr "" -#: authentik/enterprise/providers/rac/models.py:122 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mapping" msgstr "" -#: authentik/enterprise/providers/rac/models.py:123 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mappings" msgstr "" -#: authentik/enterprise/providers/rac/views.py:108 +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection token" +msgstr "" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection tokens" +msgstr "" + +#: authentik/enterprise/providers/rac/views.py msgid "Maximum connection limit reached." msgstr "" -#: authentik/enterprise/providers/rac/views.py:112 +#: authentik/enterprise/providers/rac/views.py msgid "(You are already connected in another tab/window)" msgstr "" -#: authentik/events/api/tasks.py:100 -#, python-format -msgid "Successfully started task %(name)s." +#: authentik/enterprise/stages/source/models.py +msgid "" +"Amount of time a user can take to return from the source to continue the " +"flow (Format: hours=-1;minutes=-2;seconds=-3)" msgstr "" -#: authentik/events/models.py:303 +#: authentik/enterprise/stages/source/models.py +msgid "Source Stage" +msgstr "" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stages" +msgstr "" + +#: authentik/events/api/tasks.py +#, python-brace-format +msgid "Successfully started task {name}." +msgstr "" + +#: authentik/events/models.py msgid "Event" msgstr "" -#: authentik/events/models.py:304 +#: authentik/events/models.py msgid "Events" msgstr "" -#: authentik/events/models.py:310 +#: authentik/events/models.py msgid "authentik inbuilt notifications" msgstr "" -#: authentik/events/models.py:311 +#: authentik/events/models.py msgid "Generic Webhook" msgstr "" -#: authentik/events/models.py:312 +#: authentik/events/models.py msgid "Slack Webhook (Slack/Discord)" msgstr "" -#: authentik/events/models.py:313 +#: authentik/events/models.py msgid "Email" msgstr "" -#: authentik/events/models.py:331 +#: authentik/events/models.py msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." msgstr "" -#: authentik/events/models.py:396 +#: authentik/events/models.py msgid "Severity" msgstr "" -#: authentik/events/models.py:401 +#: authentik/events/models.py msgid "Dispatched for user" msgstr "" -#: authentik/events/models.py:410 +#: authentik/events/models.py msgid "Event user" msgstr "" -#: authentik/events/models.py:504 +#: authentik/events/models.py msgid "Notification Transport" msgstr "" -#: authentik/events/models.py:505 +#: authentik/events/models.py msgid "Notification Transports" msgstr "" -#: authentik/events/models.py:511 +#: authentik/events/models.py msgid "Notice" msgstr "" -#: authentik/events/models.py:512 +#: authentik/events/models.py msgid "Warning" msgstr "" -#: authentik/events/models.py:513 +#: authentik/events/models.py msgid "Alert" msgstr "" -#: authentik/events/models.py:538 +#: authentik/events/models.py msgid "Notification" msgstr "" -#: authentik/events/models.py:539 +#: authentik/events/models.py msgid "Notifications" msgstr "" -#: authentik/events/models.py:549 +#: authentik/events/models.py msgid "" "Select which transports should be used to notify the user. If none are " "selected, the notification will only be shown in the authentik UI." msgstr "" -#: authentik/events/models.py:557 +#: authentik/events/models.py msgid "Controls which severity level the created notifications will have." msgstr "" -#: authentik/events/models.py:562 +#: authentik/events/models.py msgid "" "Define which group of users this notification should be sent and shown to. " "If left empty, Notification won't ben sent." msgstr "" -#: authentik/events/models.py:580 +#: authentik/events/models.py msgid "Notification Rule" msgstr "" -#: authentik/events/models.py:581 +#: authentik/events/models.py msgid "Notification Rules" msgstr "" -#: authentik/events/models.py:601 +#: authentik/events/models.py msgid "Webhook Mapping" msgstr "" -#: authentik/events/models.py:602 +#: authentik/events/models.py msgid "Webhook Mappings" msgstr "" -#: authentik/events/models.py:663 +#: authentik/events/models.py msgid "Run task" msgstr "" -#: authentik/events/models.py:664 +#: authentik/events/models.py msgid "System Task" msgstr "" -#: authentik/events/models.py:665 +#: authentik/events/models.py msgid "System Tasks" msgstr "" -#: authentik/events/system_tasks.py:126 +#: authentik/events/system_tasks.py msgid "Task has not been run yet." msgstr "" -#: authentik/flows/api/flows.py:295 -#, python-format -msgid "Flow not applicable to current user/request: %(messages)s" +#: authentik/flows/api/flows.py +#, python-brace-format +msgid "Flow not applicable to current user/request: {messages}" msgstr "" -#: authentik/flows/api/flows_diagram.py:68 -#: authentik/flows/api/flows_diagram.py:94 -#, python-format -msgid "Policy (%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Policy ({type})" msgstr "" -#: authentik/flows/api/flows_diagram.py:71 -#, python-format -msgid "Binding %(order)d" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Binding {order}" msgstr "" -#: authentik/flows/api/flows_diagram.py:118 +#: authentik/flows/api/flows_diagram.py msgid "Policy passed" msgstr "" -#: authentik/flows/api/flows_diagram.py:122 -#, python-format -msgid "Stage (%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Stage ({type})" msgstr "" -#: authentik/flows/api/flows_diagram.py:146 -#: authentik/flows/api/flows_diagram.py:206 +#: authentik/flows/api/flows_diagram.py msgid "Policy denied" msgstr "" -#: authentik/flows/api/flows_diagram.py:156 -#: authentik/flows/api/flows_diagram.py:168 -#: authentik/flows/api/flows_diagram.py:205 -#: authentik/flows/api/flows_diagram.py:227 +#: authentik/flows/api/flows_diagram.py msgid "End of the flow" msgstr "" -#: authentik/flows/api/flows_diagram.py:169 +#: authentik/flows/api/flows_diagram.py msgid "Requirement not fulfilled" msgstr "" -#: authentik/flows/api/flows_diagram.py:177 +#: authentik/flows/api/flows_diagram.py msgid "Flow authentication requirement" msgstr "" -#: authentik/flows/api/flows_diagram.py:183 +#: authentik/flows/api/flows_diagram.py msgid "Requirement fulfilled" msgstr "" -#: authentik/flows/api/flows_diagram.py:196 +#: authentik/flows/api/flows_diagram.py msgid "Pre-flow policies" msgstr "" -#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:194 +#: authentik/flows/api/flows_diagram.py authentik/flows/models.py msgid "Flow" msgstr "" -#: authentik/flows/exceptions.py:19 +#: authentik/flows/exceptions.py msgid "Flow does not apply to current user." msgstr "" -#: authentik/flows/models.py:115 -#, python-format -msgid "Dynamic In-memory stage: %(doc)s" +#: authentik/flows/models.py +#, python-brace-format +msgid "Dynamic In-memory stage: {doc}" msgstr "" -#: authentik/flows/models.py:130 +#: authentik/flows/models.py msgid "Visible in the URL." msgstr "" -#: authentik/flows/models.py:132 +#: authentik/flows/models.py msgid "Shown as the Title in Flow pages." msgstr "" -#: authentik/flows/models.py:139 +#: authentik/flows/models.py msgid "" "Decides what this Flow is used for. For example, the Authentication flow is " "redirect to when an un-authenticated user visits authentik." msgstr "" -#: authentik/flows/models.py:148 +#: authentik/flows/models.py msgid "Background shown during execution" msgstr "" -#: authentik/flows/models.py:155 +#: authentik/flows/models.py msgid "" "Enable compatibility mode, increases compatibility with password managers on " "mobile devices." msgstr "" -#: authentik/flows/models.py:163 +#: authentik/flows/models.py msgid "Configure what should happen when a flow denies access to a user." msgstr "" -#: authentik/flows/models.py:169 +#: authentik/flows/models.py msgid "Required level of authentication and authorization to access a flow." msgstr "" -#: authentik/flows/models.py:195 +#: authentik/flows/models.py msgid "Flows" msgstr "" -#: authentik/flows/models.py:198 +#: authentik/flows/models.py msgid "Can export a Flow" msgstr "" -#: authentik/flows/models.py:199 +#: authentik/flows/models.py msgid "Can inspect a Flow's execution" msgstr "" -#: authentik/flows/models.py:200 +#: authentik/flows/models.py msgid "View Flow's cache metrics" msgstr "" -#: authentik/flows/models.py:201 +#: authentik/flows/models.py msgid "Clear Flow's cache metrics" msgstr "" -#: authentik/flows/models.py:217 +#: authentik/flows/models.py msgid "Evaluate policies during the Flow planning process." msgstr "" -#: authentik/flows/models.py:221 +#: authentik/flows/models.py msgid "Evaluate policies when the Stage is present to the user." msgstr "" -#: authentik/flows/models.py:228 +#: authentik/flows/models.py msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -691,332 +798,354 @@ msgid "" "RESTART_WITH_CONTEXT restarts the flow while keeping the current context." msgstr "" -#: authentik/flows/models.py:251 +#: authentik/flows/models.py msgid "Flow Stage Binding" msgstr "" -#: authentik/flows/models.py:252 +#: authentik/flows/models.py msgid "Flow Stage Bindings" msgstr "" -#: authentik/flows/models.py:267 +#: authentik/flows/models.py msgid "" "Flow used by an authenticated user to configure this Stage. If empty, user " "will not be able to configure this stage." msgstr "" -#: authentik/flows/models.py:307 +#: authentik/flows/models.py msgid "Flow Token" msgstr "" -#: authentik/flows/models.py:308 +#: authentik/flows/models.py msgid "Flow Tokens" msgstr "" -#: authentik/lib/utils/time.py:27 +#: authentik/flows/views/executor.py +msgid "Invalid next URL" +msgstr "" + +#: authentik/lib/sync/outgoing/tasks.py +msgid "Starting full provider sync" +msgstr "" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of users" +msgstr "" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of groups" +msgstr "" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-brace-format +msgid "Stopping sync due to error: {error}" +msgstr "" + +#: authentik/lib/utils/time.py #, python-format msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." msgstr "" -#: authentik/lib/validators.py:16 +#: authentik/lib/validators.py #, python-brace-format msgid "The fields {field_names} must be used together." msgstr "" -#: authentik/outposts/api/service_connections.py:127 +#: authentik/outposts/api/service_connections.py msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." msgstr "" -#: authentik/outposts/api/service_connections.py:135 +#: authentik/outposts/api/service_connections.py msgid "Invalid kubeconfig" msgstr "" -#: authentik/outposts/models.py:123 +#: authentik/outposts/models.py msgid "" "If enabled, use the local connection. Required Docker socket/Kubernetes " "Integration" msgstr "" -#: authentik/outposts/models.py:153 +#: authentik/outposts/models.py msgid "Outpost Service-Connection" msgstr "" -#: authentik/outposts/models.py:154 +#: authentik/outposts/models.py msgid "Outpost Service-Connections" msgstr "" -#: authentik/outposts/models.py:162 +#: authentik/outposts/models.py msgid "" "Can be in the format of 'unix://' when connecting to a local docker " "daemon, or 'https://:2376' when connecting to a remote system." msgstr "" -#: authentik/outposts/models.py:174 +#: authentik/outposts/models.py msgid "" "CA which the endpoint's Certificate is verified against. Can be left empty " "for no validation." msgstr "" -#: authentik/outposts/models.py:186 +#: authentik/outposts/models.py msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." msgstr "" -#: authentik/outposts/models.py:204 +#: authentik/outposts/models.py msgid "Docker Service-Connection" msgstr "" -#: authentik/outposts/models.py:205 +#: authentik/outposts/models.py msgid "Docker Service-Connections" msgstr "" -#: authentik/outposts/models.py:213 +#: authentik/outposts/models.py msgid "" "Paste your kubeconfig here. authentik will automatically use the currently " "selected context." msgstr "" -#: authentik/outposts/models.py:219 +#: authentik/outposts/models.py msgid "Verify SSL Certificates of the Kubernetes API endpoint" msgstr "" -#: authentik/outposts/models.py:236 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connection" msgstr "" -#: authentik/outposts/models.py:237 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connections" msgstr "" -#: authentik/outposts/models.py:253 +#: authentik/outposts/models.py msgid "" "Select Service-Connection authentik should use to manage this outpost. Leave " "empty if authentik should not handle the deployment." msgstr "" -#: authentik/outposts/models.py:420 +#: authentik/outposts/models.py msgid "Outpost" msgstr "" -#: authentik/outposts/models.py:421 +#: authentik/outposts/models.py msgid "Outposts" msgstr "" -#: authentik/policies/denied.py:24 +#: authentik/policies/denied.py msgid "Access denied" msgstr "" -#: authentik/policies/dummy/models.py:44 +#: authentik/policies/dummy/models.py msgid "Dummy Policy" msgstr "" -#: authentik/policies/dummy/models.py:45 +#: authentik/policies/dummy/models.py msgid "Dummy Policies" msgstr "" -#: authentik/policies/event_matcher/api.py:20 -#: authentik/policies/event_matcher/models.py:56 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected application. When left empty, all " "applications are matched." msgstr "" -#: authentik/policies/event_matcher/api.py:29 -#: authentik/policies/event_matcher/models.py:64 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected model. When left empty, all models are " "matched. When an app is selected, all the application's models are matched." msgstr "" -#: authentik/policies/event_matcher/api.py:42 +#: authentik/policies/event_matcher/api.py msgid "At least one criteria must be set." msgstr "" -#: authentik/policies/event_matcher/models.py:48 +#: authentik/policies/event_matcher/models.py msgid "" "Match created events with this action type. When left empty, all action " "types will be matched." msgstr "" -#: authentik/policies/event_matcher/models.py:73 +#: authentik/policies/event_matcher/models.py msgid "" "Matches Event's Client IP (strict matching, for network matching use an " "Expression Policy)" msgstr "" -#: authentik/policies/event_matcher/models.py:143 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policy" msgstr "" -#: authentik/policies/event_matcher/models.py:144 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policies" msgstr "" -#: authentik/policies/expiry/models.py:45 +#: authentik/policies/expiry/models.py #, python-format msgid "Password expired %(days)d days ago. Please update your password." msgstr "" -#: authentik/policies/expiry/models.py:49 +#: authentik/policies/expiry/models.py msgid "Password has expired." msgstr "" -#: authentik/policies/expiry/models.py:53 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policy" msgstr "" -#: authentik/policies/expiry/models.py:54 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policies" msgstr "" -#: authentik/policies/expression/models.py:40 +#: authentik/policies/expression/models.py msgid "Expression Policy" msgstr "" -#: authentik/policies/expression/models.py:41 +#: authentik/policies/expression/models.py msgid "Expression Policies" msgstr "" -#: authentik/policies/models.py:22 +#: authentik/policies/models.py msgid "all, all policies must pass" msgstr "" -#: authentik/policies/models.py:23 +#: authentik/policies/models.py msgid "any, any policy must pass" msgstr "" -#: authentik/policies/models.py:46 +#: authentik/policies/models.py msgid "Policy Binding Model" msgstr "" -#: authentik/policies/models.py:47 +#: authentik/policies/models.py msgid "Policy Binding Models" msgstr "" -#: authentik/policies/models.py:86 +#: authentik/policies/models.py msgid "Negates the outcome of the policy. Messages are unaffected." msgstr "" -#: authentik/policies/models.py:89 +#: authentik/policies/models.py msgid "Timeout after which Policy execution is terminated." msgstr "" -#: authentik/policies/models.py:92 +#: authentik/policies/models.py msgid "Result if the Policy execution fails." msgstr "" -#: authentik/policies/models.py:145 +#: authentik/policies/models.py msgid "Policy Binding" msgstr "" -#: authentik/policies/models.py:146 +#: authentik/policies/models.py msgid "Policy Bindings" msgstr "" -#: authentik/policies/models.py:167 +#: authentik/policies/models.py msgid "" "When this option is enabled, all executions of this policy will be logged. " "By default, only execution errors are logged." msgstr "" -#: authentik/policies/models.py:189 +#: authentik/policies/models.py msgid "Policy" msgstr "" -#: authentik/policies/models.py:190 +#: authentik/policies/models.py msgid "Policies" msgstr "" -#: authentik/policies/models.py:193 +#: authentik/policies/models.py msgid "View Policy's cache metrics" msgstr "" -#: authentik/policies/models.py:194 +#: authentik/policies/models.py msgid "Clear Policy's cache metrics" msgstr "" -#: authentik/policies/password/models.py:27 +#: authentik/policies/password/models.py msgid "Field key to check, field keys defined in Prompt stages are available." msgstr "" -#: authentik/policies/password/models.py:44 +#: authentik/policies/password/models.py msgid "How many times the password hash is allowed to be on haveibeenpwned" msgstr "" -#: authentik/policies/password/models.py:49 +#: authentik/policies/password/models.py msgid "" "If the zxcvbn score is equal or less than this value, the policy will fail." msgstr "" -#: authentik/policies/password/models.py:72 +#: authentik/policies/password/models.py msgid "Password not set in context" msgstr "" -#: authentik/policies/password/models.py:134 +#: authentik/policies/password/models.py #, python-format msgid "Password exists on %(count)d online lists." msgstr "" -#: authentik/policies/password/models.py:154 +#: authentik/policies/password/models.py msgid "Password is too weak." msgstr "" -#: authentik/policies/password/models.py:162 +#: authentik/policies/password/models.py msgid "Password Policy" msgstr "" -#: authentik/policies/password/models.py:163 +#: authentik/policies/password/models.py msgid "Password Policies" msgstr "" -#: authentik/policies/reputation/api.py:18 +#: authentik/policies/reputation/api.py msgid "Either IP or Username must be checked" msgstr "" -#: authentik/policies/reputation/models.py:67 +#: authentik/policies/reputation/models.py msgid "Reputation Policy" msgstr "" -#: authentik/policies/reputation/models.py:68 +#: authentik/policies/reputation/models.py msgid "Reputation Policies" msgstr "" -#: authentik/policies/reputation/models.py:96 +#: authentik/policies/reputation/models.py msgid "Reputation Score" msgstr "" -#: authentik/policies/reputation/models.py:97 +#: authentik/policies/reputation/models.py msgid "Reputation Scores" msgstr "" -#: authentik/policies/templates/policies/denied.html:7 -#: authentik/policies/templates/policies/denied.html:11 +#: authentik/policies/templates/policies/denied.html msgid "Permission denied" msgstr "" -#: authentik/policies/templates/policies/denied.html:21 +#: authentik/policies/templates/policies/denied.html msgid "User's avatar" msgstr "" -#: authentik/policies/templates/policies/denied.html:25 +#: authentik/policies/templates/policies/denied.html msgid "Not you?" msgstr "" -#: authentik/policies/templates/policies/denied.html:33 +#: authentik/policies/templates/policies/denied.html msgid "Request has been denied." msgstr "" -#: authentik/policies/templates/policies/denied.html:44 +#: authentik/policies/templates/policies/denied.html msgid "Messages:" msgstr "" -#: authentik/policies/templates/policies/denied.html:54 +#: authentik/policies/templates/policies/denied.html msgid "Explanation:" msgstr "" -#: authentik/policies/templates/policies/denied.html:58 +#: authentik/policies/templates/policies/denied.html #, python-format msgid "" "\n" @@ -1024,28 +1153,28 @@ msgid "" " " msgstr "" -#: authentik/policies/views.py:68 +#: authentik/policies/views.py msgid "Failed to resolve application" msgstr "" -#: authentik/providers/ldap/models.py:25 +#: authentik/providers/ldap/models.py msgid "DN under which objects are accessible." msgstr "" -#: authentik/providers/ldap/models.py:34 +#: authentik/providers/ldap/models.py msgid "" "Users in this group can do search queries. If not set, every user can " "execute search queries." msgstr "" -#: authentik/providers/ldap/models.py:53 +#: authentik/providers/ldap/models.py msgid "" "The start for uidNumbers, this number is added to the user.pk to make sure " "that the numbers aren't too low for POSIX users. Default is 2000 to ensure " "that we don't collide with local users uidNumber" msgstr "" -#: authentik/providers/ldap/models.py:62 +#: authentik/providers/ldap/models.py msgid "" "The start for gidNumbers, this number is added to a number generated from " "the group.pk to make sure that the numbers aren't too low for POSIX groups. " @@ -1053,8 +1182,7 @@ msgid "" "primary groups gidNumber" msgstr "" -#: authentik/providers/ldap/models.py:76 -#: authentik/providers/radius/models.py:34 +#: authentik/providers/ldap/models.py authentik/providers/radius/models.py msgid "" "When enabled, code-based multi-factor authentication can be used by " "appending a semicolon and the TOTP code to the password. This should only be " @@ -1063,1278 +1191,1293 @@ msgid "" "contains a semicolon." msgstr "" -#: authentik/providers/ldap/models.py:108 +#: authentik/providers/ldap/models.py msgid "LDAP Provider" msgstr "" -#: authentik/providers/ldap/models.py:109 +#: authentik/providers/ldap/models.py msgid "LDAP Providers" msgstr "" -#: authentik/providers/oauth2/id_token.py:27 +#: authentik/providers/oauth2/id_token.py msgid "Based on the Hashed User ID" msgstr "" -#: authentik/providers/oauth2/id_token.py:28 +#: authentik/providers/oauth2/id_token.py msgid "Based on user ID" msgstr "" -#: authentik/providers/oauth2/id_token.py:29 +#: authentik/providers/oauth2/id_token.py msgid "Based on user UUID" msgstr "" -#: authentik/providers/oauth2/id_token.py:30 +#: authentik/providers/oauth2/id_token.py msgid "Based on the username" msgstr "" -#: authentik/providers/oauth2/id_token.py:33 +#: authentik/providers/oauth2/id_token.py msgid "Based on the User's Email. This is recommended over the UPN method." msgstr "" -#: authentik/providers/oauth2/id_token.py:38 +#: authentik/providers/oauth2/id_token.py msgid "" "Based on the User's UPN, only works if user has a 'upn' attribute set. Use " "this method only if you have different UPN and Mail domains." msgstr "" -#: authentik/providers/oauth2/models.py:43 +#: authentik/providers/oauth2/models.py msgid "Confidential" msgstr "" -#: authentik/providers/oauth2/models.py:44 +#: authentik/providers/oauth2/models.py msgid "Public" msgstr "" -#: authentik/providers/oauth2/models.py:66 +#: authentik/providers/oauth2/models.py msgid "Same identifier is used for all providers" msgstr "" -#: authentik/providers/oauth2/models.py:68 +#: authentik/providers/oauth2/models.py msgid "Each provider has a different issuer, based on the application slug." msgstr "" -#: authentik/providers/oauth2/models.py:75 +#: authentik/providers/oauth2/models.py msgid "code (Authorization Code Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:76 +#: authentik/providers/oauth2/models.py msgid "id_token (Implicit Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:77 +#: authentik/providers/oauth2/models.py msgid "id_token token (Implicit Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:78 +#: authentik/providers/oauth2/models.py msgid "code token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:79 +#: authentik/providers/oauth2/models.py msgid "code id_token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:80 +#: authentik/providers/oauth2/models.py msgid "code id_token token (Hybrid Flow)" msgstr "" -#: authentik/providers/oauth2/models.py:86 +#: authentik/providers/oauth2/models.py msgid "HS256 (Symmetric Encryption)" msgstr "" -#: authentik/providers/oauth2/models.py:87 +#: authentik/providers/oauth2/models.py msgid "RS256 (Asymmetric Encryption)" msgstr "" -#: authentik/providers/oauth2/models.py:88 +#: authentik/providers/oauth2/models.py msgid "ES256 (Asymmetric Encryption)" msgstr "" -#: authentik/providers/oauth2/models.py:94 +#: authentik/providers/oauth2/models.py msgid "Scope used by the client" msgstr "" -#: authentik/providers/oauth2/models.py:98 +#: authentik/providers/oauth2/models.py msgid "" "Description shown to the user when consenting. If left empty, the user won't " "be informed." msgstr "" -#: authentik/providers/oauth2/models.py:117 +#: authentik/providers/oauth2/models.py msgid "Scope Mapping" msgstr "" -#: authentik/providers/oauth2/models.py:118 +#: authentik/providers/oauth2/models.py msgid "Scope Mappings" msgstr "" -#: authentik/providers/oauth2/models.py:128 +#: authentik/providers/oauth2/models.py msgid "Client Type" msgstr "" -#: authentik/providers/oauth2/models.py:130 +#: authentik/providers/oauth2/models.py msgid "" "Confidential clients are capable of maintaining the confidentiality of their " "credentials. Public clients are incapable" msgstr "" -#: authentik/providers/oauth2/models.py:137 +#: authentik/providers/oauth2/models.py msgid "Client ID" msgstr "" -#: authentik/providers/oauth2/models.py:143 +#: authentik/providers/oauth2/models.py msgid "Client Secret" msgstr "" -#: authentik/providers/oauth2/models.py:149 +#: authentik/providers/oauth2/models.py msgid "Redirect URIs" msgstr "" -#: authentik/providers/oauth2/models.py:150 +#: authentik/providers/oauth2/models.py msgid "Enter each URI on a new line." msgstr "" -#: authentik/providers/oauth2/models.py:155 +#: authentik/providers/oauth2/models.py msgid "Include claims in id_token" msgstr "" -#: authentik/providers/oauth2/models.py:157 +#: authentik/providers/oauth2/models.py msgid "" "Include User claims from scopes in the id_token, for applications that don't " "access the userinfo endpoint." msgstr "" -#: authentik/providers/oauth2/models.py:166 +#: authentik/providers/oauth2/models.py msgid "" "Access codes not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "" -#: authentik/providers/oauth2/models.py:174 -#: authentik/providers/oauth2/models.py:182 +#: authentik/providers/oauth2/models.py msgid "" "Tokens not valid on or after current time + this value (Format: hours=1;" "minutes=2;seconds=3)." msgstr "" -#: authentik/providers/oauth2/models.py:191 +#: authentik/providers/oauth2/models.py msgid "" "Configure what data should be used as unique User Identifier. For most " "cases, the default should be fine." msgstr "" -#: authentik/providers/oauth2/models.py:198 +#: authentik/providers/oauth2/models.py msgid "Configure how the issuer field of the ID Token should be filled." msgstr "" -#: authentik/providers/oauth2/models.py:203 +#: authentik/providers/oauth2/models.py msgid "Signing Key" msgstr "" -#: authentik/providers/oauth2/models.py:207 +#: authentik/providers/oauth2/models.py msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." msgstr "" -#: authentik/providers/oauth2/models.py:214 +#: authentik/providers/oauth2/models.py msgid "" "Any JWT signed by the JWK of the selected source can be used to authenticate." msgstr "" -#: authentik/providers/oauth2/models.py:287 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Provider" msgstr "" -#: authentik/providers/oauth2/models.py:288 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Providers" msgstr "" -#: authentik/providers/oauth2/models.py:297 -#: authentik/providers/oauth2/models.py:430 +#: authentik/providers/oauth2/models.py msgid "Scopes" msgstr "" -#: authentik/providers/oauth2/models.py:317 +#: authentik/providers/oauth2/models.py msgid "Code" msgstr "" -#: authentik/providers/oauth2/models.py:318 +#: authentik/providers/oauth2/models.py msgid "Nonce" msgstr "" -#: authentik/providers/oauth2/models.py:319 +#: authentik/providers/oauth2/models.py msgid "Code Challenge" msgstr "" -#: authentik/providers/oauth2/models.py:321 +#: authentik/providers/oauth2/models.py msgid "Code Challenge Method" msgstr "" -#: authentik/providers/oauth2/models.py:341 +#: authentik/providers/oauth2/models.py msgid "Authorization Code" msgstr "" -#: authentik/providers/oauth2/models.py:342 +#: authentik/providers/oauth2/models.py msgid "Authorization Codes" msgstr "" -#: authentik/providers/oauth2/models.py:384 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Token" msgstr "" -#: authentik/providers/oauth2/models.py:385 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Tokens" msgstr "" -#: authentik/providers/oauth2/models.py:395 +#: authentik/providers/oauth2/models.py msgid "ID Token" msgstr "" -#: authentik/providers/oauth2/models.py:414 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Token" msgstr "" -#: authentik/providers/oauth2/models.py:415 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Tokens" msgstr "" -#: authentik/providers/oauth2/models.py:442 +#: authentik/providers/oauth2/models.py msgid "Device Token" msgstr "" -#: authentik/providers/oauth2/models.py:443 +#: authentik/providers/oauth2/models.py msgid "Device Tokens" msgstr "" -#: authentik/providers/oauth2/views/authorize.py:489 -#: authentik/providers/saml/views/flows.py:87 -#, python-format -msgid "Redirecting to %(app)s..." +#: authentik/providers/oauth2/views/authorize.py +#: authentik/providers/saml/views/flows.py +#, python-brace-format +msgid "Redirecting to {app}..." msgstr "" -#: authentik/providers/oauth2/views/device_init.py:151 +#: authentik/providers/oauth2/views/device_init.py msgid "Invalid code" msgstr "" -#: authentik/providers/oauth2/views/userinfo.py:55 -#: authentik/providers/oauth2/views/userinfo.py:56 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your User Information" msgstr "" -#: authentik/providers/oauth2/views/userinfo.py:57 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access you Email addresses" msgstr "" -#: authentik/providers/oauth2/views/userinfo.py:58 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your Groups" msgstr "" -#: authentik/providers/oauth2/views/userinfo.py:59 +#: authentik/providers/oauth2/views/userinfo.py msgid "authentik API Access on behalf of your user" msgstr "" -#: authentik/providers/proxy/api.py:52 +#: authentik/providers/proxy/api.py msgid "User and password attributes must be set when basic auth is enabled." msgstr "" -#: authentik/providers/proxy/api.py:63 +#: authentik/providers/proxy/api.py msgid "Internal host cannot be empty when forward auth is disabled." msgstr "" -#: authentik/providers/proxy/models.py:54 +#: authentik/providers/proxy/models.py msgid "Validate SSL Certificates of upstream servers" msgstr "" -#: authentik/providers/proxy/models.py:55 +#: authentik/providers/proxy/models.py msgid "Internal host SSL Validation" msgstr "" -#: authentik/providers/proxy/models.py:61 +#: authentik/providers/proxy/models.py msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." msgstr "" -#: authentik/providers/proxy/models.py:70 +#: authentik/providers/proxy/models.py msgid "" "Regular expressions for which authentication is not required. Each new line " "is interpreted as a new Regular Expression." msgstr "" -#: authentik/providers/proxy/models.py:78 +#: authentik/providers/proxy/models.py msgid "" "When enabled, this provider will intercept the authorization header and " "authenticate requests based on its value." msgstr "" -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py msgid "Set HTTP-Basic Authentication" msgstr "" -#: authentik/providers/proxy/models.py:86 +#: authentik/providers/proxy/models.py msgid "" "Set a custom HTTP-Basic Authentication header based on values from authentik." msgstr "" -#: authentik/providers/proxy/models.py:91 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Username Key" msgstr "" -#: authentik/providers/proxy/models.py:93 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the user part of the HTTP-Basic Header. If not " "set, the user's Email address is used." msgstr "" -#: authentik/providers/proxy/models.py:99 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Password Key" msgstr "" -#: authentik/providers/proxy/models.py:100 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the password part of the HTTP-Basic Header." msgstr "" -#: authentik/providers/proxy/models.py:154 +#: authentik/providers/proxy/models.py msgid "Proxy Provider" msgstr "" -#: authentik/providers/proxy/models.py:155 +#: authentik/providers/proxy/models.py msgid "Proxy Providers" msgstr "" -#: authentik/providers/radius/models.py:18 +#: authentik/providers/radius/models.py msgid "Shared secret between clients and server to hash packets." msgstr "" -#: authentik/providers/radius/models.py:24 +#: authentik/providers/radius/models.py msgid "" "List of CIDRs (comma-separated) that clients can connect from. A more " "specific CIDR will match before a looser one. Clients connecting from a non-" "specified CIDR will be dropped." msgstr "" -#: authentik/providers/radius/models.py:60 +#: authentik/providers/radius/models.py msgid "Radius Provider" msgstr "" -#: authentik/providers/radius/models.py:61 +#: authentik/providers/radius/models.py msgid "Radius Providers" msgstr "" -#: authentik/providers/saml/api/providers.py:258 +#: authentik/providers/saml/api/providers.py msgid "Invalid XML Syntax" msgstr "" -#: authentik/providers/saml/api/providers.py:268 -#, python-format -msgid "Failed to import Metadata: %(message)s" +#: authentik/providers/saml/api/providers.py +#, python-brace-format +msgid "Failed to import Metadata: {messages}" msgstr "" -#: authentik/providers/saml/models.py:38 +#: authentik/providers/saml/models.py msgid "ACS URL" msgstr "" -#: authentik/providers/saml/models.py:43 +#: authentik/providers/saml/models.py msgid "" "Value of the audience restriction field of the assertion. When left empty, " "no audience restriction will be added." msgstr "" -#: authentik/providers/saml/models.py:47 +#: authentik/providers/saml/models.py msgid "Also known as EntityID" msgstr "" -#: authentik/providers/saml/models.py:51 +#: authentik/providers/saml/models.py msgid "Service Provider Binding" msgstr "" -#: authentik/providers/saml/models.py:53 +#: authentik/providers/saml/models.py msgid "" "This determines how authentik sends the response back to the Service " "Provider." msgstr "" -#: authentik/providers/saml/models.py:63 +#: authentik/providers/saml/models.py msgid "NameID Property Mapping" msgstr "" -#: authentik/providers/saml/models.py:65 +#: authentik/providers/saml/models.py msgid "" "Configure how the NameID value will be created. When left empty, the " "NameIDPolicy of the incoming request will be considered" msgstr "" -#: authentik/providers/saml/models.py:74 +#: authentik/providers/saml/models.py msgid "" "Assertion valid not before current time + this value (Format: hours=-1;" "minutes=-2;seconds=-3)." msgstr "" -#: authentik/providers/saml/models.py:82 +#: authentik/providers/saml/models.py msgid "" "Assertion not valid on or after current time + this value (Format: hours=1;" "minutes=2;seconds=3)." msgstr "" -#: authentik/providers/saml/models.py:91 +#: authentik/providers/saml/models.py msgid "" "Session not valid on or after current time + this value (Format: hours=1;" "minutes=2;seconds=3)." msgstr "" -#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA1" msgstr "" -#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA256" msgstr "" -#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA384" msgstr "" -#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA512" msgstr "" -#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA1" msgstr "" -#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA256" msgstr "" -#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA384" msgstr "" -#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA512" msgstr "" -#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA1" +msgstr "" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA256" +msgstr "" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA384" +msgstr "" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA512" +msgstr "" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "DSA-SHA1" msgstr "" -#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "" "When selected, incoming assertion's Signatures will be validated against " "this certificate. To allow unsigned Requests, leave on default." msgstr "" -#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Verification Certificate" msgstr "" -#: authentik/providers/saml/models.py:136 +#: authentik/providers/saml/models.py msgid "Keypair used to sign outgoing Responses going to the Service Provider." msgstr "" -#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Signing Keypair" msgstr "" -#: authentik/providers/saml/models.py:142 +#: authentik/providers/saml/models.py msgid "Default relay_state value for IDP-initiated logins" msgstr "" -#: authentik/providers/saml/models.py:171 +#: authentik/providers/saml/models.py msgid "SAML Provider" msgstr "" -#: authentik/providers/saml/models.py:172 +#: authentik/providers/saml/models.py msgid "SAML Providers" msgstr "" -#: authentik/providers/saml/models.py:196 +#: authentik/providers/saml/models.py msgid "SAML Property Mapping" msgstr "" -#: authentik/providers/saml/models.py:197 +#: authentik/providers/saml/models.py msgid "SAML Property Mappings" msgstr "" -#: authentik/providers/scim/models.py:23 +#: authentik/providers/saml/models.py +msgid "SAML Provider from Metadata" +msgstr "" + +#: authentik/providers/saml/models.py +msgid "SAML Providers from Metadata" +msgstr "" + +#: authentik/providers/scim/models.py msgid "Base URL to SCIM requests, usually ends in /v2" msgstr "" -#: authentik/providers/scim/models.py:24 +#: authentik/providers/scim/models.py msgid "Authentication token" msgstr "" -#: authentik/providers/scim/models.py:30 authentik/sources/ldap/models.py:98 -msgid "Property mappings used for group creation/updating." -msgstr "" - -#: authentik/providers/scim/models.py:72 +#: authentik/providers/scim/models.py msgid "SCIM Provider" msgstr "" -#: authentik/providers/scim/models.py:73 +#: authentik/providers/scim/models.py msgid "SCIM Providers" msgstr "" -#: authentik/providers/scim/models.py:93 +#: authentik/providers/scim/models.py msgid "SCIM Mapping" msgstr "" -#: authentik/providers/scim/models.py:94 +#: authentik/providers/scim/models.py msgid "SCIM Mappings" msgstr "" -#: authentik/providers/scim/tasks.py:57 -msgid "Starting full SCIM sync" -msgstr "" - -#: authentik/providers/scim/tasks.py:67 -#, python-format -msgid "Syncing page %(page)d of users" -msgstr "" - -#: authentik/providers/scim/tasks.py:71 -#, python-format -msgid "Syncing page %(page)d of groups" -msgstr "" - -#: authentik/providers/scim/tasks.py:103 -#, python-format -msgid "Failed to sync user %(user_name)s due to remote error: %(error)s" -msgstr "" - -#: authentik/providers/scim/tasks.py:114 authentik/providers/scim/tasks.py:155 -#, python-format -msgid "Stopping sync due to error: %(error)s" -msgstr "" - -#: authentik/providers/scim/tasks.py:144 -#, python-format -msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" -msgstr "" - -#: authentik/rbac/models.py:51 +#: authentik/rbac/models.py msgid "Role" msgstr "" -#: authentik/rbac/models.py:52 +#: authentik/rbac/models.py msgid "Roles" msgstr "" -#: authentik/rbac/models.py:66 +#: authentik/rbac/models.py msgid "System permission" msgstr "" -#: authentik/rbac/models.py:67 +#: authentik/rbac/models.py msgid "System permissions" msgstr "" -#: authentik/rbac/models.py:69 +#: authentik/rbac/models.py msgid "Can view system info" msgstr "" -#: authentik/rbac/models.py:70 -msgid "Can view system tasks" -msgstr "" - -#: authentik/rbac/models.py:71 -msgid "Can view users in the user directory" -msgstr "" - -#: authentik/rbac/models.py:72 -msgid "Can run system tasks" -msgstr "" - -#: authentik/rbac/models.py:73 +#: authentik/rbac/models.py msgid "Can access admin interface" msgstr "" -#: authentik/rbac/models.py:74 +#: authentik/rbac/models.py msgid "Can view system settings" msgstr "" -#: authentik/rbac/models.py:75 +#: authentik/rbac/models.py msgid "Can edit system settings" msgstr "" -#: authentik/recovery/management/commands/create_admin_group.py:12 +#: authentik/recovery/management/commands/create_admin_group.py msgid "Create admin group if the default group gets deleted." msgstr "" -#: authentik/recovery/management/commands/create_recovery_key.py:16 +#: authentik/recovery/management/commands/create_recovery_key.py msgid "Create a Key which can be used to restore access to authentik." msgstr "" -#: authentik/recovery/views.py:24 +#: authentik/recovery/views.py msgid "Used recovery-link to authenticate." msgstr "" -#: authentik/sources/ldap/models.py:41 +#: authentik/sources/ldap/models.py msgid "Server URI" msgstr "" -#: authentik/sources/ldap/models.py:50 +#: authentik/sources/ldap/models.py msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this " "keypair." msgstr "" -#: authentik/sources/ldap/models.py:59 +#: authentik/sources/ldap/models.py msgid "" "Client certificate to authenticate against the LDAP Server's Certificate." msgstr "" -#: authentik/sources/ldap/models.py:62 +#: authentik/sources/ldap/models.py msgid "Bind CN" msgstr "" -#: authentik/sources/ldap/models.py:64 +#: authentik/sources/ldap/models.py msgid "Enable Start TLS" msgstr "" -#: authentik/sources/ldap/models.py:65 +#: authentik/sources/ldap/models.py msgid "Use Server URI for SNI verification" msgstr "" -#: authentik/sources/ldap/models.py:67 +#: authentik/sources/ldap/models.py msgid "Base DN" msgstr "" -#: authentik/sources/ldap/models.py:69 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for User-queries." msgstr "" -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py msgid "Addition User DN" msgstr "" -#: authentik/sources/ldap/models.py:74 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for Group-queries." msgstr "" -#: authentik/sources/ldap/models.py:75 +#: authentik/sources/ldap/models.py msgid "Addition Group DN" msgstr "" -#: authentik/sources/ldap/models.py:81 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Users." msgstr "" -#: authentik/sources/ldap/models.py:84 +#: authentik/sources/ldap/models.py msgid "Field which contains members of a group." msgstr "" -#: authentik/sources/ldap/models.py:88 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Groups." msgstr "" -#: authentik/sources/ldap/models.py:91 +#: authentik/sources/ldap/models.py msgid "Field which contains a unique Identifier." msgstr "" -#: authentik/sources/ldap/models.py:105 +#: authentik/sources/ldap/models.py +msgid "Update internal authentik password when login succeeds with LDAP" +msgstr "" + +#: authentik/sources/ldap/models.py msgid "" "When a user changes their password, sync it back to LDAP. This can only be " "enabled on a single LDAP source." msgstr "" -#: authentik/sources/ldap/models.py:248 +#: authentik/sources/ldap/models.py msgid "LDAP Source" msgstr "" -#: authentik/sources/ldap/models.py:249 +#: authentik/sources/ldap/models.py msgid "LDAP Sources" msgstr "" -#: authentik/sources/ldap/models.py:271 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mapping" msgstr "" -#: authentik/sources/ldap/models.py:272 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mappings" msgstr "" -#: authentik/sources/ldap/signals.py:52 +#: authentik/sources/ldap/signals.py msgid "Password does not match Active Directory Complexity." msgstr "" -#: authentik/sources/oauth/clients/oauth2.py:68 +#: authentik/sources/oauth/clients/oauth2.py msgid "No token received." msgstr "" -#: authentik/sources/oauth/models.py:24 +#: authentik/sources/oauth/models.py msgid "Request Token URL" msgstr "" -#: authentik/sources/oauth/models.py:26 +#: authentik/sources/oauth/models.py msgid "" "URL used to request the initial token. This URL is only required for OAuth 1." msgstr "" -#: authentik/sources/oauth/models.py:32 +#: authentik/sources/oauth/models.py msgid "Authorization URL" msgstr "" -#: authentik/sources/oauth/models.py:33 +#: authentik/sources/oauth/models.py msgid "URL the user is redirect to to conest the flow." msgstr "" -#: authentik/sources/oauth/models.py:38 +#: authentik/sources/oauth/models.py msgid "Access Token URL" msgstr "" -#: authentik/sources/oauth/models.py:39 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to retrieve tokens." msgstr "" -#: authentik/sources/oauth/models.py:44 +#: authentik/sources/oauth/models.py msgid "Profile URL" msgstr "" -#: authentik/sources/oauth/models.py:45 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to get user information." msgstr "" -#: authentik/sources/oauth/models.py:48 +#: authentik/sources/oauth/models.py msgid "Additional Scopes" msgstr "" -#: authentik/sources/oauth/models.py:107 +#: authentik/sources/oauth/models.py msgid "OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:108 +#: authentik/sources/oauth/models.py msgid "OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:116 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:117 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:125 +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Source" +msgstr "" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Sources" +msgstr "" + +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:126 +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:134 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:135 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:143 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:144 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:152 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:161 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:170 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:171 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:179 +#: authentik/sources/oauth/models.py msgid "Google OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:180 +#: authentik/sources/oauth/models.py msgid "Google OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:188 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:189 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:197 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:198 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:206 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:207 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:215 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:216 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:224 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:225 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:247 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connection" msgstr "" -#: authentik/sources/oauth/models.py:248 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connections" msgstr "" -#: authentik/sources/oauth/views/callback.py:100 -#, python-format -msgid "Authentication failed: %(reason)s" +#: authentik/sources/oauth/views/callback.py +#, python-brace-format +msgid "Authentication failed: {reason}" msgstr "" -#: authentik/sources/plex/models.py:37 +#: authentik/sources/plex/models.py msgid "Client identifier used to talk to Plex." msgstr "" -#: authentik/sources/plex/models.py:44 +#: authentik/sources/plex/models.py msgid "" "Which servers a user has to be a member of to be granted access. Empty list " "allows every server." msgstr "" -#: authentik/sources/plex/models.py:50 +#: authentik/sources/plex/models.py msgid "Allow friends to authenticate, even if you don't share a server." msgstr "" -#: authentik/sources/plex/models.py:52 +#: authentik/sources/plex/models.py msgid "Plex token used to check friends" msgstr "" -#: authentik/sources/plex/models.py:95 +#: authentik/sources/plex/models.py msgid "Plex Source" msgstr "" -#: authentik/sources/plex/models.py:96 +#: authentik/sources/plex/models.py msgid "Plex Sources" msgstr "" -#: authentik/sources/plex/models.py:112 +#: authentik/sources/plex/models.py msgid "User Plex Source Connection" msgstr "" -#: authentik/sources/plex/models.py:113 +#: authentik/sources/plex/models.py msgid "User Plex Source Connections" msgstr "" -#: authentik/sources/saml/models.py:40 +#: authentik/sources/saml/models.py msgid "Redirect Binding" msgstr "" -#: authentik/sources/saml/models.py:41 +#: authentik/sources/saml/models.py msgid "POST Binding" msgstr "" -#: authentik/sources/saml/models.py:42 +#: authentik/sources/saml/models.py msgid "POST Binding with auto-confirmation" msgstr "" -#: authentik/sources/saml/models.py:70 +#: authentik/sources/saml/models.py msgid "Flow used before authentication." msgstr "" -#: authentik/sources/saml/models.py:77 +#: authentik/sources/saml/models.py msgid "Issuer" msgstr "" -#: authentik/sources/saml/models.py:78 +#: authentik/sources/saml/models.py msgid "Also known as Entity ID. Defaults the Metadata URL." msgstr "" -#: authentik/sources/saml/models.py:82 +#: authentik/sources/saml/models.py msgid "SSO URL" msgstr "" -#: authentik/sources/saml/models.py:83 +#: authentik/sources/saml/models.py msgid "URL that the initial Login request is sent to." msgstr "" -#: authentik/sources/saml/models.py:89 +#: authentik/sources/saml/models.py msgid "SLO URL" msgstr "" -#: authentik/sources/saml/models.py:90 +#: authentik/sources/saml/models.py msgid "Optional URL if your IDP supports Single-Logout." msgstr "" -#: authentik/sources/saml/models.py:96 +#: authentik/sources/saml/models.py msgid "" "Allows authentication flows initiated by the IdP. This can be a security " "risk, as no validation of the request ID is done." msgstr "" -#: authentik/sources/saml/models.py:104 +#: authentik/sources/saml/models.py msgid "" "NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent." msgstr "" -#: authentik/sources/saml/models.py:115 +#: authentik/sources/saml/models.py msgid "Delete temporary users after" msgstr "" -#: authentik/sources/saml/models.py:118 +#: authentik/sources/saml/models.py msgid "" "Time offset when temporary users should be deleted. This only applies if " "your IDP uses the NameID Format 'transient', and the user doesn't log out " "manually. (Format: hours=1;minutes=2;seconds=3)." msgstr "" -#: authentik/sources/saml/models.py:142 +#: authentik/sources/saml/models.py msgid "Keypair used to sign outgoing Responses going to the Identity Provider." msgstr "" -#: authentik/sources/saml/models.py:226 +#: authentik/sources/saml/models.py msgid "SAML Source" msgstr "" -#: authentik/sources/saml/models.py:227 +#: authentik/sources/saml/models.py msgid "SAML Sources" msgstr "" -#: authentik/sources/saml/models.py:242 +#: authentik/sources/saml/models.py msgid "User SAML Source Connection" msgstr "" -#: authentik/sources/saml/models.py:243 +#: authentik/sources/saml/models.py msgid "User SAML Source Connections" msgstr "" -#: authentik/stages/authenticator_duo/models.py:79 +#: authentik/sources/scim/models.py +msgid "SCIM Source" +msgstr "" + +#: authentik/sources/scim/models.py +msgid "SCIM Sources" +msgstr "" + +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_duo/models.py:80 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_duo/models.py:103 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Device" msgstr "" -#: authentik/stages/authenticator_duo/models.py:104 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Devices" msgstr "" -#: authentik/stages/authenticator_sms/models.py:57 +#: authentik/stages/authenticator_sms/models.py msgid "" "When enabled, the Phone number is only used during enrollment to verify the " "users authenticity. Only a hash of the phone number is saved to ensure it is " "not reused in the future." msgstr "" -#: authentik/stages/authenticator_sms/models.py:68 +#: authentik/stages/authenticator_sms/models.py msgid "Optionally modify the payload being sent to custom providers." msgstr "" -#: authentik/stages/authenticator_sms/models.py:81 -#, python-format -msgid "Use this code to authenticate in authentik: %(token)s" +#: authentik/stages/authenticator_sms/models.py +#, python-brace-format +msgid "Use this code to authenticate in authentik: {token}" msgstr "" -#: authentik/stages/authenticator_sms/models.py:180 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_sms/models.py:181 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_sms/models.py:226 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Device" msgstr "" -#: authentik/stages/authenticator_sms/models.py:227 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Devices" msgstr "" -#: authentik/stages/authenticator_sms/stage.py:57 -#: authentik/stages/authenticator_totp/stage.py:41 -#: authentik/stages/authenticator_totp/stage.py:44 +#: authentik/stages/authenticator_sms/stage.py +#: authentik/stages/authenticator_totp/stage.py msgid "Code does not match" msgstr "" -#: authentik/stages/authenticator_sms/stage.py:73 +#: authentik/stages/authenticator_sms/stage.py msgid "Invalid phone number" msgstr "" -#: authentik/stages/authenticator_static/models.py:52 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_static/models.py:53 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_static/models.py:98 +#: authentik/stages/authenticator_static/models.py msgid "Static Device" msgstr "" -#: authentik/stages/authenticator_static/models.py:99 +#: authentik/stages/authenticator_static/models.py msgid "Static Devices" msgstr "" -#: authentik/stages/authenticator_static/models.py:129 +#: authentik/stages/authenticator_static/models.py msgid "Static Token" msgstr "" -#: authentik/stages/authenticator_static/models.py:130 +#: authentik/stages/authenticator_static/models.py msgid "Static Tokens" msgstr "" -#: authentik/stages/authenticator_totp/models.py:25 +#: authentik/stages/authenticator_totp/models.py msgid "6 digits, widely compatible" msgstr "" -#: authentik/stages/authenticator_totp/models.py:26 +#: authentik/stages/authenticator_totp/models.py msgid "8 digits, not compatible with apps like Google Authenticator" msgstr "" -#: authentik/stages/authenticator_totp/models.py:62 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_totp/models.py:63 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_totp/models.py:244 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Device" msgstr "" -#: authentik/stages/authenticator_totp/models.py:245 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Devices" msgstr "" -#: authentik/stages/authenticator_validate/challenge.py:123 -msgid "Invalid Token" +#: authentik/stages/authenticator_validate/challenge.py +msgid "" +"Invalid Token. Please ensure the time on your device is accurate and try " +"again." msgstr "" -#: authentik/stages/authenticator_validate/models.py:18 +#: authentik/stages/authenticator_validate/challenge.py +#: authentik/stages/authenticator_webauthn/stage.py +#, python-brace-format +msgid "Invalid device type. Contact your {brand} administrator for help." +msgstr "" + +#: authentik/stages/authenticator_validate/models.py msgid "Static" msgstr "" -#: authentik/stages/authenticator_validate/models.py:19 +#: authentik/stages/authenticator_validate/models.py msgid "TOTP" msgstr "" -#: authentik/stages/authenticator_validate/models.py:20 +#: authentik/stages/authenticator_validate/models.py msgid "WebAuthn" msgstr "" -#: authentik/stages/authenticator_validate/models.py:21 +#: authentik/stages/authenticator_validate/models.py msgid "Duo" msgstr "" -#: authentik/stages/authenticator_validate/models.py:22 +#: authentik/stages/authenticator_validate/models.py msgid "SMS" msgstr "" -#: authentik/stages/authenticator_validate/models.py:49 +#: authentik/stages/authenticator_validate/models.py msgid "" "Stages used to configure Authenticator when user doesn't have any compatible " "devices. After this configuration Stage passes, the user is not prompted " "again." msgstr "" -#: authentik/stages/authenticator_validate/models.py:56 +#: authentik/stages/authenticator_validate/models.py msgid "Device classes which can be used to authenticate" msgstr "" -#: authentik/stages/authenticator_validate/models.py:64 +#: authentik/stages/authenticator_validate/models.py msgid "" "If any of the user's device has been used within this threshold, this stage " "will be skipped" msgstr "" -#: authentik/stages/authenticator_validate/models.py:70 +#: authentik/stages/authenticator_validate/models.py msgid "Enforce user verification for WebAuthn devices." msgstr "" -#: authentik/stages/authenticator_validate/models.py:92 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stage" msgstr "" -#: authentik/stages/authenticator_validate/models.py:93 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stages" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:112 +#: authentik/stages/authenticator_validate/stage.py +msgid "No (allowed) MFA authenticator configured." +msgstr "" + +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stage" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:113 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stages" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:151 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Device" msgstr "" -#: authentik/stages/authenticator_webauthn/models.py:152 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Devices" msgstr "" -#: authentik/stages/captcha/models.py:14 +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device type" +msgstr "" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device types" +msgstr "" + +#: authentik/stages/captcha/models.py msgid "Public key, acquired your captcha Provider." msgstr "" -#: authentik/stages/captcha/models.py:15 +#: authentik/stages/captcha/models.py msgid "Private key, acquired your captcha Provider." msgstr "" -#: authentik/stages/captcha/models.py:37 +#: authentik/stages/captcha/models.py msgid "Captcha Stage" msgstr "" -#: authentik/stages/captcha/models.py:38 +#: authentik/stages/captcha/models.py msgid "Captcha Stages" msgstr "" -#: authentik/stages/consent/models.py:30 +#: authentik/stages/consent/models.py msgid "" "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "" -#: authentik/stages/consent/models.py:50 +#: authentik/stages/consent/models.py msgid "Consent Stage" msgstr "" -#: authentik/stages/consent/models.py:51 +#: authentik/stages/consent/models.py msgid "Consent Stages" msgstr "" -#: authentik/stages/consent/models.py:72 +#: authentik/stages/consent/models.py msgid "User Consent" msgstr "" -#: authentik/stages/consent/models.py:73 +#: authentik/stages/consent/models.py msgid "User Consents" msgstr "" -#: authentik/stages/deny/models.py:32 +#: authentik/stages/deny/models.py msgid "Deny Stage" msgstr "" -#: authentik/stages/deny/models.py:33 +#: authentik/stages/deny/models.py msgid "Deny Stages" msgstr "" -#: authentik/stages/dummy/models.py:34 +#: authentik/stages/dummy/models.py msgid "Dummy Stage" msgstr "" -#: authentik/stages/dummy/models.py:35 +#: authentik/stages/dummy/models.py msgid "Dummy Stages" msgstr "" -#: authentik/stages/email/models.py:26 +#: authentik/stages/email/models.py msgid "Password Reset" msgstr "" -#: authentik/stages/email/models.py:30 +#: authentik/stages/email/models.py msgid "Account Confirmation" msgstr "" -#: authentik/stages/email/models.py:59 +#: authentik/stages/email/models.py msgid "" "When enabled, global Email connection settings will be used and connection " "settings below will be ignored." msgstr "" -#: authentik/stages/email/models.py:74 +#: authentik/stages/email/models.py msgid "Activate users upon completion of stage." msgstr "" -#: authentik/stages/email/models.py:78 +#: authentik/stages/email/models.py msgid "Time in minutes the token sent is valid." msgstr "" -#: authentik/stages/email/models.py:132 +#: authentik/stages/email/models.py msgid "Email Stage" msgstr "" -#: authentik/stages/email/models.py:133 +#: authentik/stages/email/models.py msgid "Email Stages" msgstr "" -#: authentik/stages/email/stage.py:126 +#: authentik/stages/email/stage.py msgid "Exception occurred while rendering E-mail template" msgstr "" -#: authentik/stages/email/stage.py:140 +#: authentik/stages/email/stage.py msgid "Successfully verified Email." msgstr "" -#: authentik/stages/email/stage.py:147 authentik/stages/email/stage.py:173 +#: authentik/stages/email/stage.py msgid "No pending user." msgstr "" -#: authentik/stages/email/stage.py:163 +#: authentik/stages/email/stage.py msgid "Email sent." msgstr "" -#: authentik/stages/email/stage.py:176 +#: authentik/stages/email/stage.py msgid "Email Successfully sent." msgstr "" -#: authentik/stages/email/templates/email/account_confirmation.html:10 -#: authentik/stages/email/templates/email/account_confirmation.txt:1 +#: authentik/stages/email/templates/email/account_confirmation.html +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "Welcome!" msgstr "" -#: authentik/stages/email/templates/email/account_confirmation.html:19 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just press the button below." msgstr "" -#: authentik/stages/email/templates/email/account_confirmation.html:24 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "Confirm Account" msgstr "" -#: authentik/stages/email/templates/email/account_confirmation.html:36 +#: authentik/stages/email/templates/email/account_confirmation.html #, python-format msgid "" "\n" @@ -2343,13 +2486,13 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/account_confirmation.txt:3 +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just open the link below." msgstr "" -#: authentik/stages/email/templates/email/event_notification.html:46 +#: authentik/stages/email/templates/email/event_notification.html #, python-format msgid "" "\n" @@ -2358,26 +2501,26 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/event_notification.txt:1 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Dear authentik user," msgstr "" -#: authentik/stages/email/templates/email/event_notification.txt:3 +#: authentik/stages/email/templates/email/event_notification.txt msgid "The following notification was created:" msgstr "" -#: authentik/stages/email/templates/email/event_notification.txt:8 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Additional attributes:" msgstr "" -#: authentik/stages/email/templates/email/event_notification.txt:13 +#: authentik/stages/email/templates/email/event_notification.txt #, python-format msgid "" "\n" "This email was sent from the notification transport %(name)s.\n" msgstr "" -#: authentik/stages/email/templates/email/password_reset.html:10 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2385,7 +2528,7 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/password_reset.html:21 +#: authentik/stages/email/templates/email/password_reset.html msgid "" "\n" " You recently requested to change your password for your authentik " @@ -2393,7 +2536,7 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/password_reset.html:39 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2402,19 +2545,19 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/password_reset.txt:1 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "Hi %(username)s," msgstr "" -#: authentik/stages/email/templates/email/password_reset.txt:3 +#: authentik/stages/email/templates/email/password_reset.txt msgid "" "\n" "You recently requested to change your password for your authentik account. " "Use the link below to set a new password.\n" msgstr "" -#: authentik/stages/email/templates/email/password_reset.txt:7 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "" "\n" @@ -2422,11 +2565,11 @@ msgid "" "above is valid for %(expires)s.\n" msgstr "" -#: authentik/stages/email/templates/email/setup.html:9 +#: authentik/stages/email/templates/email/setup.html msgid "authentik Test-Email" msgstr "" -#: authentik/stages/email/templates/email/setup.html:17 +#: authentik/stages/email/templates/email/setup.html msgid "" "\n" " This is a test email to inform you, that you've " @@ -2434,391 +2577,390 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/setup.txt:2 +#: authentik/stages/email/templates/email/setup.txt msgid "" "\n" "This is a test email to inform you, that you've successfully configured " "authentik emails.\n" msgstr "" -#: authentik/stages/identification/api.py:20 +#: authentik/stages/identification/api.py msgid "When no user fields are selected, at least one source must be selected" msgstr "" -#: authentik/stages/identification/models.py:29 +#: authentik/stages/identification/models.py msgid "" "Fields of the user object to match against. (Hold shift to select multiple " "options)" msgstr "" -#: authentik/stages/identification/models.py:47 +#: authentik/stages/identification/models.py msgid "When enabled, user fields are matched regardless of their casing." msgstr "" -#: authentik/stages/identification/models.py:52 +#: authentik/stages/identification/models.py msgid "" "When a valid username/email has been entered, and this option is enabled, " "the user's username and avatar will be shown. Otherwise, the text that the " "user entered will be shown" msgstr "" -#: authentik/stages/identification/models.py:60 +#: authentik/stages/identification/models.py msgid "" "When enabled, the stage will succeed and continue even when incorrect user " "info is entered." msgstr "" -#: authentik/stages/identification/models.py:72 +#: authentik/stages/identification/models.py msgid "Optional enrollment flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:81 +#: authentik/stages/identification/models.py msgid "Optional recovery flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:90 +#: authentik/stages/identification/models.py msgid "Optional passwordless flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:94 +#: authentik/stages/identification/models.py msgid "Specify which sources should be shown." msgstr "" -#: authentik/stages/identification/models.py:115 +#: authentik/stages/identification/models.py msgid "Identification Stage" msgstr "" -#: authentik/stages/identification/models.py:116 +#: authentik/stages/identification/models.py msgid "Identification Stages" msgstr "" -#: authentik/stages/identification/stage.py:188 +#: authentik/stages/identification/stage.py msgid "Log in" msgstr "" -#: authentik/stages/identification/stage.py:189 +#: authentik/stages/identification/stage.py msgid "Continue" msgstr "" -#: authentik/stages/invitation/models.py:21 +#: authentik/stages/invitation/models.py msgid "" "If this flag is set, this Stage will jump to the next Stage when no " "Invitation is given. By default this Stage will cancel the Flow when no " "invitation is given." msgstr "" -#: authentik/stages/invitation/models.py:44 +#: authentik/stages/invitation/models.py msgid "Invitation Stage" msgstr "" -#: authentik/stages/invitation/models.py:45 +#: authentik/stages/invitation/models.py msgid "Invitation Stages" msgstr "" -#: authentik/stages/invitation/models.py:60 +#: authentik/stages/invitation/models.py msgid "When set, only the configured flow can use this invitation." msgstr "" -#: authentik/stages/invitation/models.py:64 +#: authentik/stages/invitation/models.py msgid "When enabled, the invitation will be deleted after usage." msgstr "" -#: authentik/stages/invitation/models.py:71 +#: authentik/stages/invitation/models.py msgid "Optional fixed data to enforce on user enrollment." msgstr "" -#: authentik/stages/invitation/models.py:84 +#: authentik/stages/invitation/models.py msgid "Invitation" msgstr "" -#: authentik/stages/invitation/models.py:85 +#: authentik/stages/invitation/models.py msgid "Invitations" msgstr "" -#: authentik/stages/invitation/stage.py:62 +#: authentik/stages/invitation/stage.py msgid "Invalid invite/invite not found" msgstr "" -#: authentik/stages/password/models.py:20 +#: authentik/stages/password/models.py msgid "User database + standard password" msgstr "" -#: authentik/stages/password/models.py:24 +#: authentik/stages/password/models.py msgid "User database + app passwords" msgstr "" -#: authentik/stages/password/models.py:28 +#: authentik/stages/password/models.py msgid "User database + LDAP password" msgstr "" -#: authentik/stages/password/models.py:38 +#: authentik/stages/password/models.py msgid "Selection of backends to test the password against." msgstr "" -#: authentik/stages/password/models.py:43 +#: authentik/stages/password/models.py msgid "" "How many attempts a user has before the flow is canceled. To lock the user " "out, use a reputation policy and a user_write stage." msgstr "" -#: authentik/stages/password/models.py:75 +#: authentik/stages/password/models.py msgid "Password Stage" msgstr "" -#: authentik/stages/password/models.py:76 +#: authentik/stages/password/models.py msgid "Password Stages" msgstr "" -#: authentik/stages/password/stage.py:124 +#: authentik/stages/password/stage.py msgid "Invalid password" msgstr "" -#: authentik/stages/prompt/models.py:43 +#: authentik/stages/prompt/models.py msgid "Text: Simple Text input" msgstr "" -#: authentik/stages/prompt/models.py:45 +#: authentik/stages/prompt/models.py msgid "Text area: Multiline Text Input." msgstr "" -#: authentik/stages/prompt/models.py:48 +#: authentik/stages/prompt/models.py msgid "Text (read-only): Simple Text input, but cannot be edited." msgstr "" -#: authentik/stages/prompt/models.py:52 +#: authentik/stages/prompt/models.py msgid "Text area (read-only): Multiline Text input, but cannot be edited." msgstr "" -#: authentik/stages/prompt/models.py:58 +#: authentik/stages/prompt/models.py msgid "" "Username: Same as Text input, but checks for and prevents duplicate " "usernames." msgstr "" -#: authentik/stages/prompt/models.py:60 +#: authentik/stages/prompt/models.py msgid "Email: Text field with Email type." msgstr "" -#: authentik/stages/prompt/models.py:64 +#: authentik/stages/prompt/models.py msgid "" "Password: Masked input, multiple inputs of this type on the same prompt need " "to be identical." msgstr "" -#: authentik/stages/prompt/models.py:71 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a group of radio buttons." msgstr "" -#: authentik/stages/prompt/models.py:73 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a dropdown." msgstr "" -#: authentik/stages/prompt/models.py:80 +#: authentik/stages/prompt/models.py msgid "" "File: File upload for arbitrary files. File content will be available in " "flow context as data-URI" msgstr "" -#: authentik/stages/prompt/models.py:85 +#: authentik/stages/prompt/models.py msgid "Separator: Static Separator Line" msgstr "" -#: authentik/stages/prompt/models.py:86 +#: authentik/stages/prompt/models.py msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "" -#: authentik/stages/prompt/models.py:87 +#: authentik/stages/prompt/models.py msgid "Static: Static value, displayed as-is." msgstr "" -#: authentik/stages/prompt/models.py:89 +#: authentik/stages/prompt/models.py msgid "authentik: Selection of locales authentik supports" msgstr "" -#: authentik/stages/prompt/models.py:116 +#: authentik/stages/prompt/models.py msgid "Name of the form field, also used to store the value" msgstr "" -#: authentik/stages/prompt/models.py:124 +#: authentik/stages/prompt/models.py msgid "" "Optionally provide a short hint that describes the expected input value. " "When creating a fixed choice field, enable interpreting as expression and " "return a list to return multiple choices." msgstr "" -#: authentik/stages/prompt/models.py:132 +#: authentik/stages/prompt/models.py msgid "" "Optionally pre-fill the input with an initial value. When creating a fixed " "choice field, enable interpreting as expression and return a list to return " "multiple default choices." msgstr "" -#: authentik/stages/prompt/models.py:321 +#: authentik/stages/prompt/models.py msgid "Prompt" msgstr "" -#: authentik/stages/prompt/models.py:322 +#: authentik/stages/prompt/models.py msgid "Prompts" msgstr "" -#: authentik/stages/prompt/models.py:349 +#: authentik/stages/prompt/models.py msgid "Prompt Stage" msgstr "" -#: authentik/stages/prompt/models.py:350 +#: authentik/stages/prompt/models.py msgid "Prompt Stages" msgstr "" -#: authentik/stages/prompt/stage.py:108 +#: authentik/stages/prompt/stage.py msgid "Passwords don't match." msgstr "" -#: authentik/stages/user_delete/models.py:31 +#: authentik/stages/user_delete/models.py msgid "User Delete Stage" msgstr "" -#: authentik/stages/user_delete/models.py:32 +#: authentik/stages/user_delete/models.py msgid "User Delete Stages" msgstr "" -#: authentik/stages/user_delete/stage.py:18 +#: authentik/stages/user_delete/stage.py msgid "No Pending User." msgstr "" -#: authentik/stages/user_login/models.py:47 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured network" msgstr "" -#: authentik/stages/user_login/models.py:52 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured GeoIP location" msgstr "" -#: authentik/stages/user_login/models.py:55 +#: authentik/stages/user_login/models.py msgid "Terminate all other sessions of the user logging in." msgstr "" -#: authentik/stages/user_login/models.py:61 +#: authentik/stages/user_login/models.py msgid "" "Offset the session will be extended by when the user picks the remember me " "option. Default of 0 means that the remember me option will not be shown. " "(Format: hours=-1;minutes=-2;seconds=-3)" msgstr "" -#: authentik/stages/user_login/models.py:84 +#: authentik/stages/user_login/models.py msgid "User Login Stage" msgstr "" -#: authentik/stages/user_login/models.py:85 +#: authentik/stages/user_login/models.py msgid "User Login Stages" msgstr "" -#: authentik/stages/user_login/stage.py:85 +#: authentik/stages/user_login/stage.py msgid "No Pending user to login." msgstr "" -#: authentik/stages/user_login/stage.py:112 +#: authentik/stages/user_login/stage.py msgid "Successfully logged in!" msgstr "" -#: authentik/stages/user_logout/models.py:30 +#: authentik/stages/user_logout/models.py msgid "User Logout Stage" msgstr "" -#: authentik/stages/user_logout/models.py:31 +#: authentik/stages/user_logout/models.py msgid "User Logout Stages" msgstr "" -#: authentik/stages/user_write/models.py:31 +#: authentik/stages/user_write/models.py msgid "When set, newly created users are inactive and cannot login." msgstr "" -#: authentik/stages/user_write/models.py:39 +#: authentik/stages/user_write/models.py msgid "Optionally add newly created users to this group." msgstr "" -#: authentik/stages/user_write/models.py:68 +#: authentik/stages/user_write/models.py msgid "User Write Stage" msgstr "" -#: authentik/stages/user_write/models.py:69 +#: authentik/stages/user_write/models.py msgid "User Write Stages" msgstr "" -#: authentik/stages/user_write/stage.py:141 +#: authentik/stages/user_write/stage.py msgid "No Pending data." msgstr "" -#: authentik/stages/user_write/stage.py:147 +#: authentik/stages/user_write/stage.py msgid "No user found and can't create new user." msgstr "" -#: authentik/stages/user_write/stage.py:164 -#: authentik/stages/user_write/stage.py:178 +#: authentik/stages/user_write/stage.py msgid "Failed to update user. Please try again later." msgstr "" -#: authentik/tenants/models.py:29 +#: authentik/tenants/models.py msgid "" "Schema name must start with t_, only contain lowercase letters and numbers " "and be less than 63 characters." msgstr "" -#: authentik/tenants/models.py:53 +#: authentik/tenants/models.py msgid "Configure how authentik should show avatars for users." msgstr "" -#: authentik/tenants/models.py:57 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their name." msgstr "" -#: authentik/tenants/models.py:60 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their email address." msgstr "" -#: authentik/tenants/models.py:63 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their username." msgstr "" -#: authentik/tenants/models.py:69 +#: authentik/tenants/models.py msgid "" "Events will be deleted after this duration.(Format: weeks=3;days=2;hours=3," "seconds=2)." msgstr "" -#: authentik/tenants/models.py:73 +#: authentik/tenants/models.py msgid "The option configures the footer links on the flow executor pages." msgstr "" -#: authentik/tenants/models.py:79 +#: authentik/tenants/models.py msgid "" "When enabled, all the events caused by a user will be deleted upon the " "user's deletion." msgstr "" -#: authentik/tenants/models.py:85 +#: authentik/tenants/models.py msgid "Globally enable/disable impersonation." msgstr "" -#: authentik/tenants/models.py:88 -msgid "Fields to show in the user directory." +#: authentik/tenants/models.py +msgid "Default token duration" msgstr "" -#: authentik/tenants/models.py:93 -msgid "Attributes to show in the user directory." +#: authentik/tenants/models.py +msgid "Default token length" msgstr "" -#: authentik/tenants/models.py:116 +#: authentik/tenants/models.py msgid "Tenant" msgstr "" -#: authentik/tenants/models.py:117 +#: authentik/tenants/models.py msgid "Tenants" msgstr "" -#: authentik/tenants/models.py:137 +#: authentik/tenants/models.py msgid "Domain" msgstr "" -#: authentik/tenants/models.py:138 +#: authentik/tenants/models.py msgid "Domains" msgstr "" diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index ac13c057d2..480d6161e0 100644 Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 4349653e81..78d1bce05e 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -10,8 +10,8 @@ # Kyllian Delaye-Maillot, 2023 # Manuel Viens, 2023 # Mordecai, 2023 -# nerdinator , 2023 # Charles Leclerc, 2024 +# nerdinator , 2024 # Marc Schmitt, 2024 # #, fuzzy @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-23 08:02+0000\n" +"POT-Creation-Date: 2024-05-03 00:08+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n" "Last-Translator: Marc Schmitt, 2024\n" "Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n" @@ -29,37 +29,32 @@ msgstr "" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: authentik/admin/api/tasks.py:127 -#, python-format -msgid "Successfully re-scheduled Task %(name)s!" -msgstr "La Tâche %(name)s a bien été reprogrammée !" - -#: authentik/api/schema.py:25 +#: authentik/api/schema.py msgid "Generic API Error" msgstr "Erreur d'API Générique" -#: authentik/api/schema.py:33 +#: authentik/api/schema.py msgid "Validation Error" msgstr "Erreur de Validation" -#: authentik/blueprints/api.py:43 +#: authentik/blueprints/api.py msgid "Blueprint file does not exist" msgstr "Le fichier de plan n'existe pas" -#: authentik/blueprints/api.py:54 -#, python-format -msgid "Failed to validate blueprint: %(logs)s" -msgstr "Échec de validation du plan: %(logs)s" +#: authentik/blueprints/api.py +#, python-brace-format +msgid "Failed to validate blueprint: {logs}" +msgstr "Échec de validation du plan : {logs}" -#: authentik/blueprints/api.py:59 +#: authentik/blueprints/api.py msgid "Either path or content must be set." msgstr "Le chemin ou le contenu doit être défini." -#: authentik/blueprints/models.py:30 +#: authentik/blueprints/models.py msgid "Managed by authentik" msgstr "Géré par authentik" -#: authentik/blueprints/models.py:32 +#: authentik/blueprints/models.py msgid "" "Objects that are managed by authentik. These objects are created and updated" " automatically. This flag only indicates that an object can be overwritten " @@ -72,25 +67,25 @@ msgstr "" " attendez-vous à ce que ces changements soient écrasés par une mise-à-jour " "ultérieure." -#: authentik/blueprints/models.py:112 +#: authentik/blueprints/models.py msgid "Blueprint Instance" msgstr "Instance du plan" -#: authentik/blueprints/models.py:113 +#: authentik/blueprints/models.py msgid "Blueprint Instances" msgstr "Instances du plan" -#: authentik/blueprints/v1/exporter.py:62 -#, python-format -msgid "authentik Export - %(date)s" -msgstr "Export authentik - %(date)s" +#: authentik/blueprints/v1/exporter.py +#, python-brace-format +msgid "authentik Export - {date}" +msgstr "Export authentik - {date}" -#: authentik/blueprints/v1/tasks.py:151 authentik/crypto/tasks.py:93 +#: authentik/blueprints/v1/tasks.py authentik/crypto/tasks.py #, python-format msgid "Successfully imported %(count)d files." msgstr " %(count)d fichiers importés avec succès." -#: authentik/brands/models.py:22 +#: authentik/brands/models.py msgid "" "Domain that activates this brand. Can be a superset, i.e. `a.b` for `aa.b` " "and `ba.b`" @@ -98,81 +93,98 @@ msgstr "" "Domain qui active cette marque. Peut être un super-ensemble, c'est-à-dire " "`a.b` pour `aa.b` et `ba.b`" -#: authentik/brands/models.py:58 +#: authentik/brands/models.py msgid "Web Certificate used by the authentik Core webserver." msgstr "Certificate Web utilisé par le serveur web d'authentik core." -#: authentik/brands/models.py:84 +#: authentik/brands/models.py msgid "Brand" msgstr "Marque" -#: authentik/brands/models.py:85 +#: authentik/brands/models.py msgid "Brands" msgstr "Marques" -#: authentik/core/api/providers.py:122 +#: authentik/core/api/providers.py msgid "SAML Provider from Metadata" msgstr "Fournisseur SAML depuis métadonnées" -#: authentik/core/api/providers.py:123 +#: authentik/core/api/providers.py msgid "Create a SAML Provider by importing its Metadata." msgstr "Créer un fournisseur SAML en important ses métadonnées." -#: authentik/core/api/users.py:149 +#: authentik/core/api/users.py msgid "No leading or trailing slashes allowed." msgstr "" "Les barres obliques, ou slashes, de tête ou de queue ne sont pas autorisées." -#: authentik/core/api/users.py:152 +#: authentik/core/api/users.py msgid "No empty segments in user path allowed." msgstr "Les segments vides dans le chemin utilisateur ne sont pas autorisés." -#: authentik/core/models.py:85 +#: authentik/core/models.py msgid "name" msgstr "nom" -#: authentik/core/models.py:87 +#: authentik/core/models.py msgid "Users added to this group will be superusers." msgstr "Les utilisateurs ajoutés à ce groupe seront des super-utilisateurs." -#: authentik/core/models.py:161 +#: authentik/core/models.py msgid "Group" msgstr "Group" -#: authentik/core/models.py:162 +#: authentik/core/models.py msgid "Groups" msgstr "Groupes" -#: authentik/core/models.py:177 +#: authentik/core/models.py +msgid "Add user to group" +msgstr "Ajouter un utilisateur au groupe" + +#: authentik/core/models.py +msgid "Remove user from group" +msgstr "Retirer l'utilisateur du groupe" + +#: authentik/core/models.py msgid "User's display name." msgstr "Nom d'affichage de l'utilisateur" -#: authentik/core/models.py:273 authentik/providers/oauth2/models.py:295 +#: authentik/core/models.py authentik/providers/oauth2/models.py msgid "User" msgstr "Utilisateur" -#: authentik/core/models.py:274 +#: authentik/core/models.py msgid "Users" msgstr "Utilisateurs" -#: authentik/core/models.py:276 -#: authentik/stages/email/templates/email/password_reset.html:28 +#: authentik/core/models.py +#: authentik/stages/email/templates/email/password_reset.html msgid "Reset Password" msgstr "Réinitialiser le mot de passe" -#: authentik/core/models.py:277 +#: authentik/core/models.py msgid "Can impersonate other users" msgstr "Peut se faire passer pour d'autres utilisateurs" -#: authentik/core/models.py:278 authentik/rbac/models.py:54 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can assign permissions to users" msgstr "Peut assigner des permissions aux utilisateurs" -#: authentik/core/models.py:279 authentik/rbac/models.py:55 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can unassign permissions from users" msgstr "Peut enlever des permissions aux utilisateurs" -#: authentik/core/models.py:293 +#: authentik/core/models.py +msgid "Can preview user data sent to providers" +msgstr "" +"Peut prévisualiser les données utilisateurs transmises aux fournisseurs" + +#: authentik/core/models.py +msgid "View applications the user has access to" +msgstr "Voir les applications auquel l'utilisateur a accès" + +#: authentik/core/models.py msgid "" "Flow used for authentication when the associated application is accessed by " "an un-authenticated user." @@ -180,11 +192,11 @@ msgstr "" "Flux utilisé lors d'authentification quand l'application associée est " "accédée par un utilisateur non-authentifié." -#: authentik/core/models.py:303 +#: authentik/core/models.py msgid "Flow used when authorizing this provider." msgstr "Flux utilisé lors de l'autorisation de ce fournisseur." -#: authentik/core/models.py:315 +#: authentik/core/models.py msgid "" "Accessed from applications; optional backchannel providers for protocols " "like LDAP and SCIM." @@ -192,32 +204,32 @@ msgstr "" "Accès à partir d'applications ; fournisseurs optionnels de canaux de retour " "pour des protocoles tels que LDAP et SCIM." -#: authentik/core/models.py:370 +#: authentik/core/models.py msgid "Application's display Name." msgstr "Nom d'affichage de l'application" -#: authentik/core/models.py:371 +#: authentik/core/models.py msgid "Internal application name, used in URLs." msgstr "Nom de l'application interne, utilisé dans les URLs." -#: authentik/core/models.py:383 +#: authentik/core/models.py msgid "Open launch URL in a new browser tab or window." msgstr "" "Ouvrir l'URL de lancement dans une nouvelle fenêtre ou un nouvel onglet." -#: authentik/core/models.py:447 +#: authentik/core/models.py msgid "Application" msgstr "Application" -#: authentik/core/models.py:448 +#: authentik/core/models.py msgid "Applications" msgstr "Applications" -#: authentik/core/models.py:454 +#: authentik/core/models.py msgid "Use the source-specific identifier" msgstr "Utiliser l'identifiant spécifique à la source" -#: authentik/core/models.py:456 +#: authentik/core/models.py msgid "" "Link to a user with identical email address. Can have security implications " "when a source doesn't validate email addresses." @@ -225,7 +237,7 @@ msgstr "" "Lier à un utilisateur avec une adresse email identique. Peut avoir des " "implications de sécurité lorsqu'une source ne valide pas les adresses email." -#: authentik/core/models.py:460 +#: authentik/core/models.py msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." @@ -233,7 +245,7 @@ msgstr "" "Utiliser l'adresse courriel de l'utilisateur, mais refuser l'inscription " "lorsque celle-ci existe déjà." -#: authentik/core/models.py:463 +#: authentik/core/models.py msgid "" "Link to a user with identical username. Can have security implications when " "a username is used with another source." @@ -242,7 +254,7 @@ msgstr "" "problèmes de sécurité si ce nom d'utilisateur est partagé avec une autre " "source." -#: authentik/core/models.py:467 +#: authentik/core/models.py msgid "" "Use the user's username, but deny enrollment when the username already " "exists." @@ -250,23 +262,23 @@ msgstr "" "Utiliser le nom d'utilisateur, mais refuser l'inscription si celui-ci existe" " déjà." -#: authentik/core/models.py:474 +#: authentik/core/models.py msgid "Source's display Name." msgstr "Nom d'affichage de la source." -#: authentik/core/models.py:475 +#: authentik/core/models.py msgid "Internal source name, used in URLs." msgstr "Nom interne de la source, utilisé dans les URLs." -#: authentik/core/models.py:494 +#: authentik/core/models.py msgid "Flow to use when authenticating existing users." msgstr "Flux à utiliser pour authentifier les utilisateurs existants." -#: authentik/core/models.py:503 +#: authentik/core/models.py msgid "Flow to use when enrolling new users." msgstr "Flux à utiliser pour inscrire les nouveaux utilisateurs." -#: authentik/core/models.py:511 +#: authentik/core/models.py msgid "" "How the source determines if an existing user should be authenticated or a " "new user enrolled." @@ -274,67 +286,66 @@ msgstr "" "Comment la source détermine si un utilisateur existant doit être authentifié" " ou un nouvelle utilisateur doit être inscrit." -#: authentik/core/models.py:683 +#: authentik/core/models.py msgid "Token" msgstr "Jeton" -#: authentik/core/models.py:684 +#: authentik/core/models.py msgid "Tokens" msgstr "Jetons" -#: authentik/core/models.py:689 +#: authentik/core/models.py msgid "View token's key" msgstr "Voir la clé du jeton" -#: authentik/core/models.py:725 +#: authentik/core/models.py msgid "Property Mapping" msgstr "Mappage de propriété" -#: authentik/core/models.py:726 +#: authentik/core/models.py msgid "Property Mappings" msgstr "Mappages de propriété" -#: authentik/core/models.py:763 +#: authentik/core/models.py msgid "Authenticated Session" msgstr "Session Authentifiée" -#: authentik/core/models.py:764 +#: authentik/core/models.py msgid "Authenticated Sessions" msgstr "Sessions Authentifiées" -#: authentik/core/sources/flow_manager.py:190 -#, python-format +#: authentik/core/sources/flow_manager.py +#, python-brace-format msgid "" -"Request to authenticate with %(source)s has been denied. Please authenticate" -" with the source you've previously signed up with." +"Request to authenticate with {source} has been denied. Please authenticate " +"with the source you've previously signed up with." msgstr "" -"La requête d'authentification avec %(source)s a été refusée. Merci de vous " +"La requête d'authentification avec {source} a été refusée. Merci de vous " "authentifier avec la source utilisée précédemment." -#: authentik/core/sources/flow_manager.py:242 +#: authentik/core/sources/flow_manager.py msgid "Configured flow does not exist." msgstr "Le flux configuré n'existe pas." -#: authentik/core/sources/flow_manager.py:272 -#: authentik/core/sources/flow_manager.py:324 -#, python-format -msgid "Successfully authenticated with %(source)s!" -msgstr "Authentifié avec succès avec %(source)s!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully authenticated with {source}!" +msgstr "Authentifié avec succès avec {source} !" -#: authentik/core/sources/flow_manager.py:296 -#, python-format -msgid "Successfully linked %(source)s!" -msgstr "%(source)s lié avec succès!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully linked {source}!" +msgstr "{source} liée avec succès !" -#: authentik/core/sources/flow_manager.py:315 +#: authentik/core/sources/flow_manager.py msgid "Source is not configured for enrollment." msgstr "La source n'est pas configurée pour l'inscription." -#: authentik/core/templates/if/end_session.html:7 +#: authentik/core/templates/if/end_session.html msgid "End session" msgstr "Terminer la Session" -#: authentik/core/templates/if/end_session.html:11 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -343,7 +354,7 @@ msgstr "" "\n" "Vous vous êtes déconnecté de %(application)s.\n" -#: authentik/core/templates/if/end_session.html:19 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -354,11 +365,11 @@ msgstr "" " Vous vous êtes déconnecté de %(application)s. Vous pouvez retourner à la vue d'ensemble pour lancer une autre application, ou vous déconnecter de votre compte %(branding_title)s .\n" " " -#: authentik/core/templates/if/end_session.html:25 +#: authentik/core/templates/if/end_session.html msgid "Go back to overview" msgstr "Retourner à la vue d'ensemble" -#: authentik/core/templates/if/end_session.html:29 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -369,7 +380,7 @@ msgstr "" " Déconnexion de %(branding_title)s\n" " " -#: authentik/core/templates/if/end_session.html:36 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -380,31 +391,38 @@ msgstr "" " Reconnexion à %(application)s\n" " " -#: authentik/core/templates/if/error.html:18 +#: authentik/core/templates/if/error.html msgid "Go home" msgstr "Retourner à l'accueil" -#: authentik/core/templates/login/base_full.html:75 +#: authentik/core/templates/login/base_full.html msgid "Powered by authentik" msgstr "Propulsé par authentik" -#: authentik/core/views/apps.py:53 -#: authentik/providers/oauth2/views/authorize.py:434 -#: authentik/providers/oauth2/views/device_init.py:70 -#: authentik/providers/saml/views/sso.py:70 +#: authentik/core/views/apps.py authentik/providers/oauth2/views/authorize.py +#: authentik/providers/oauth2/views/device_init.py +#: authentik/providers/saml/views/sso.py #, python-format msgid "You're about to sign into %(application)s." msgstr "Vous êtes sur le point de vous connecter à %(application)s." -#: authentik/crypto/api.py:179 +#: authentik/crypto/api.py msgid "Subject-alt name" msgstr "Nom alternatif subject" -#: authentik/crypto/models.py:30 +#: authentik/crypto/builder.py +msgid "rsa" +msgstr "rsa" + +#: authentik/crypto/builder.py +msgid "ecdsa" +msgstr "ecdsa" + +#: authentik/crypto/models.py msgid "PEM-encoded Certificate data" msgstr "Données du certificat au format PEM" -#: authentik/crypto/models.py:33 +#: authentik/crypto/models.py msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." @@ -412,44 +430,44 @@ msgstr "" "Clé privée optionnelle. Si définie, vous pouvez utiliser pour le " "chiffrement." -#: authentik/crypto/models.py:101 +#: authentik/crypto/models.py msgid "Certificate-Key Pair" msgstr "Paire de clé/certificat" -#: authentik/crypto/models.py:102 +#: authentik/crypto/models.py msgid "Certificate-Key Pairs" msgstr "Paires de clé/certificat" -#: authentik/enterprise/api.py:33 +#: authentik/enterprise/api.py msgid "Enterprise is required to create/update this object." msgstr "Entreprise est requis pour créer/mettre à jour cet objet." -#: authentik/enterprise/models.py:183 +#: authentik/enterprise/models.py msgid "License" msgstr "Licence" -#: authentik/enterprise/models.py:184 +#: authentik/enterprise/models.py msgid "Licenses" msgstr "Licences" -#: authentik/enterprise/models.py:206 +#: authentik/enterprise/models.py msgid "License Usage" msgstr "Utilisation de la licence" -#: authentik/enterprise/models.py:207 +#: authentik/enterprise/models.py msgid "License Usage Records" msgstr "Registre d'utilisation de la licence" -#: authentik/enterprise/policy.py:18 +#: authentik/enterprise/policy.py msgid "Enterprise required to access this feature." msgstr "Entreprise est requis pour accéder à cette fonctionnalité." -#: authentik/enterprise/policy.py:20 +#: authentik/enterprise/policy.py msgid "Feature only accessible for internal users." msgstr "Fonctionnalité accessible aux utilisateurs internes uniquement." -#: authentik/enterprise/providers/rac/models.py:48 -#: authentik/stages/user_login/models.py:39 +#: authentik/enterprise/providers/rac/models.py +#: authentik/stages/user_login/models.py msgid "" "Determines how long a session lasts. Default of 0 means that the sessions " "lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" @@ -458,63 +476,97 @@ msgstr "" "session dure jusqu'à la fermeture du navigateur. (Format : " "hours=-1;minutes=-2;seconds=-3)" -#: authentik/enterprise/providers/rac/models.py:71 +#: authentik/enterprise/providers/rac/models.py +msgid "When set to true, connection tokens will be deleted upon disconnect." +msgstr "" +"Si activé, les jetons de connexion seront supprimés lors de la déconnexion." + +#: authentik/enterprise/providers/rac/models.py msgid "RAC Provider" msgstr "Fournisseur RAC" -#: authentik/enterprise/providers/rac/models.py:72 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Providers" msgstr "Fournisseurs RAC" -#: authentik/enterprise/providers/rac/models.py:100 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoint" msgstr "Point de terminaison RAC" -#: authentik/enterprise/providers/rac/models.py:101 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoints" msgstr "Points de terminaison RAC" -#: authentik/enterprise/providers/rac/models.py:122 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mapping" msgstr "Mappage de propriété RAC" -#: authentik/enterprise/providers/rac/models.py:123 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mappings" msgstr "Mappages de propriété RAC" -#: authentik/enterprise/providers/rac/views.py:108 +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection token" +msgstr "Jeton de connexion RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection tokens" +msgstr "Jeton de connexions RAC" + +#: authentik/enterprise/providers/rac/views.py msgid "Maximum connection limit reached." msgstr "Limite maximum de connection atteinte." -#: authentik/enterprise/providers/rac/views.py:112 +#: authentik/enterprise/providers/rac/views.py msgid "(You are already connected in another tab/window)" msgstr "(Vous êtes déjà connecté dans un autre onglet/une autre fenêtre)" -#: authentik/events/models.py:289 +#: authentik/enterprise/stages/source/models.py +msgid "" +"Amount of time a user can take to return from the source to continue the " +"flow (Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "" +"Durée que l'utilisateur peut prendre pour revenir de la source pour " +"continuer le flux (Format: hours=-1;minutes=-2;seconds=-3)" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stage" +msgstr "Étape Source" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stages" +msgstr "Étapes Source" + +#: authentik/events/api/tasks.py +#, python-brace-format +msgid "Successfully started task {name}." +msgstr "La tâche {name} a été démarrée avec succès." + +#: authentik/events/models.py msgid "Event" msgstr "Évènement" -#: authentik/events/models.py:290 +#: authentik/events/models.py msgid "Events" msgstr "Évènements" -#: authentik/events/models.py:296 +#: authentik/events/models.py msgid "authentik inbuilt notifications" msgstr "notifications intégrées à authentik" -#: authentik/events/models.py:297 +#: authentik/events/models.py msgid "Generic Webhook" msgstr "Webhook Générique" -#: authentik/events/models.py:298 +#: authentik/events/models.py msgid "Slack Webhook (Slack/Discord)" msgstr "Webhook Slack (ou Discord)" -#: authentik/events/models.py:299 +#: authentik/events/models.py msgid "Email" msgstr "Courriel" -#: authentik/events/models.py:317 +#: authentik/events/models.py msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." @@ -522,47 +574,47 @@ msgstr "" "Envoyer une seule fois la notification, par exemple lors de l'envoi d'un " "webhook dans un canal de discussion." -#: authentik/events/models.py:382 +#: authentik/events/models.py msgid "Severity" msgstr "Sévérité" -#: authentik/events/models.py:387 +#: authentik/events/models.py msgid "Dispatched for user" msgstr "Distribué pour l'utilisateur" -#: authentik/events/models.py:396 +#: authentik/events/models.py msgid "Event user" msgstr "Évènement utilisateur" -#: authentik/events/models.py:490 +#: authentik/events/models.py msgid "Notification Transport" msgstr "Transport de Notification" -#: authentik/events/models.py:491 +#: authentik/events/models.py msgid "Notification Transports" msgstr "Transports de notification" -#: authentik/events/models.py:497 +#: authentik/events/models.py msgid "Notice" msgstr "Note" -#: authentik/events/models.py:498 +#: authentik/events/models.py msgid "Warning" msgstr "Avertissement" -#: authentik/events/models.py:499 +#: authentik/events/models.py msgid "Alert" msgstr "Alerte" -#: authentik/events/models.py:524 +#: authentik/events/models.py msgid "Notification" msgstr "Notification" -#: authentik/events/models.py:525 +#: authentik/events/models.py msgid "Notifications" msgstr "Notifications" -#: authentik/events/models.py:535 +#: authentik/events/models.py msgid "" "Select which transports should be used to notify the user. If none are " "selected, the notification will only be shown in the authentik UI." @@ -571,11 +623,11 @@ msgstr "" "défaut, la notification sera simplement affichée dans l'interface " "utilisateur authentik." -#: authentik/events/models.py:543 +#: authentik/events/models.py msgid "Controls which severity level the created notifications will have." msgstr "Contrôle quel niveau de sévérité les notifications créées auront." -#: authentik/events/models.py:548 +#: authentik/events/models.py msgid "" "Define which group of users this notification should be sent and shown to. " "If left empty, Notification won't ben sent." @@ -583,103 +635,110 @@ msgstr "" "Définir à quel groupe d'utilisateur cette notification doit être envoyée et " "affichée. Si laissé vide, les notifications ne seront pas envoyées." -#: authentik/events/models.py:566 +#: authentik/events/models.py msgid "Notification Rule" msgstr "Règle de Notification" -#: authentik/events/models.py:567 +#: authentik/events/models.py msgid "Notification Rules" msgstr "Règles de notification" -#: authentik/events/models.py:587 +#: authentik/events/models.py msgid "Webhook Mapping" msgstr "Mappage de Webhook" -#: authentik/events/models.py:588 +#: authentik/events/models.py msgid "Webhook Mappings" msgstr "Mappages de Webhook" -#: authentik/events/monitored_tasks.py:207 +#: authentik/events/models.py +msgid "Run task" +msgstr "Lancer la tâche" + +#: authentik/events/models.py +msgid "System Task" +msgstr "Tâches du système" + +#: authentik/events/models.py +msgid "System Tasks" +msgstr "Tâches du système" + +#: authentik/events/system_tasks.py msgid "Task has not been run yet." msgstr "Tâche pas encore exécutée." -#: authentik/flows/api/flows.py:295 -#, python-format -msgid "Flow not applicable to current user/request: %(messages)s" +#: authentik/flows/api/flows.py +#, python-brace-format +msgid "Flow not applicable to current user/request: {messages}" msgstr "" -"Ce flux n'est pas applicable à l'utilisateur ou à la requête courrante : " -"%(messages)s" +"Ce flux n'est pas applicable à l'utilisateur ou à la requête courante : " +"{messages}" -#: authentik/flows/api/flows_diagram.py:68 -#: authentik/flows/api/flows_diagram.py:94 -#, python-format -msgid "Policy (%(type)s)" -msgstr "Politique (%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Policy ({type})" +msgstr "Politique ({type})" -#: authentik/flows/api/flows_diagram.py:71 -#, python-format -msgid "Binding %(order)d" -msgstr "Liaison %(order)d" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Binding {order}" +msgstr "Liaison {order}" -#: authentik/flows/api/flows_diagram.py:118 +#: authentik/flows/api/flows_diagram.py msgid "Policy passed" msgstr "Politique acceptée" -#: authentik/flows/api/flows_diagram.py:122 -#, python-format -msgid "Stage (%(type)s)" -msgstr "Étape (%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Stage ({type})" +msgstr "Étape ({type})" -#: authentik/flows/api/flows_diagram.py:146 -#: authentik/flows/api/flows_diagram.py:206 +#: authentik/flows/api/flows_diagram.py msgid "Policy denied" msgstr "Politique refusée" -#: authentik/flows/api/flows_diagram.py:156 -#: authentik/flows/api/flows_diagram.py:168 -#: authentik/flows/api/flows_diagram.py:205 -#: authentik/flows/api/flows_diagram.py:227 +#: authentik/flows/api/flows_diagram.py msgid "End of the flow" msgstr "Fin du flux" -#: authentik/flows/api/flows_diagram.py:169 +#: authentik/flows/api/flows_diagram.py msgid "Requirement not fulfilled" msgstr "Exigence non satisfaite" -#: authentik/flows/api/flows_diagram.py:177 +#: authentik/flows/api/flows_diagram.py msgid "Flow authentication requirement" msgstr "Exigence d'authentification du flux" -#: authentik/flows/api/flows_diagram.py:183 +#: authentik/flows/api/flows_diagram.py msgid "Requirement fulfilled" msgstr "Exigence satisfaite" -#: authentik/flows/api/flows_diagram.py:196 +#: authentik/flows/api/flows_diagram.py msgid "Pre-flow policies" msgstr "Politiques pré-flux" -#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:194 +#: authentik/flows/api/flows_diagram.py authentik/flows/models.py msgid "Flow" msgstr "Flux" -#: authentik/flows/exceptions.py:19 +#: authentik/flows/exceptions.py msgid "Flow does not apply to current user." msgstr "Le flux ne s'applique pas à l'utilisateur actuel" -#: authentik/flows/models.py:115 -#, python-format -msgid "Dynamic In-memory stage: %(doc)s" -msgstr "Étape dynamique en mémoire : %(doc)s" +#: authentik/flows/models.py +#, python-brace-format +msgid "Dynamic In-memory stage: {doc}" +msgstr "Étape dynamique en mémoire : {doc}" -#: authentik/flows/models.py:130 +#: authentik/flows/models.py msgid "Visible in the URL." msgstr "Visible dans l'URL" -#: authentik/flows/models.py:132 +#: authentik/flows/models.py msgid "Shown as the Title in Flow pages." msgstr "Afficher comme Titre dans les pages de Flux." -#: authentik/flows/models.py:139 +#: authentik/flows/models.py msgid "" "Decides what this Flow is used for. For example, the Authentication flow is " "redirect to when an un-authenticated user visits authentik." @@ -687,11 +746,11 @@ msgstr "" "Détermine l'usage de ce flux. Par exemple, un flux d'authentification est la" " destination d'un visiteur d'authentik non authentifié." -#: authentik/flows/models.py:148 +#: authentik/flows/models.py msgid "Background shown during execution" msgstr "Fond d'écran affiché durant l'exécution" -#: authentik/flows/models.py:155 +#: authentik/flows/models.py msgid "" "Enable compatibility mode, increases compatibility with password managers on" " mobile devices." @@ -699,47 +758,47 @@ msgstr "" "Activer le mode de compatibilité, améliore la compatibilité avec les " "gestionnaires de mot de passe sur les équipements mobiles." -#: authentik/flows/models.py:163 +#: authentik/flows/models.py msgid "Configure what should happen when a flow denies access to a user." msgstr "" "Configuration de ce qu'il se passe lorsqu'un flux refuse l'accès à un " "utilisateur." -#: authentik/flows/models.py:169 +#: authentik/flows/models.py msgid "Required level of authentication and authorization to access a flow." msgstr "" "Niveau d'authentification et d'authorisation requis pour accéder à un flux." -#: authentik/flows/models.py:195 +#: authentik/flows/models.py msgid "Flows" msgstr "Flux" -#: authentik/flows/models.py:198 +#: authentik/flows/models.py msgid "Can export a Flow" msgstr "Peut exporter un flux" -#: authentik/flows/models.py:199 +#: authentik/flows/models.py msgid "Can inspect a Flow's execution" msgstr "Peut inspecter l'exécution d'un flux" -#: authentik/flows/models.py:200 +#: authentik/flows/models.py msgid "View Flow's cache metrics" msgstr "Voir les métriques de cache du flux" -#: authentik/flows/models.py:201 +#: authentik/flows/models.py msgid "Clear Flow's cache metrics" msgstr "Nettoyer les métriques de cache du flux" -#: authentik/flows/models.py:217 +#: authentik/flows/models.py msgid "Evaluate policies during the Flow planning process." msgstr "Évaluer les politiques durant la planification du flux." -#: authentik/flows/models.py:221 +#: authentik/flows/models.py msgid "Evaluate policies when the Stage is present to the user." msgstr "" "Évaluer les politiques lorsque l'étape est présentée est l'utilisateur." -#: authentik/flows/models.py:228 +#: authentik/flows/models.py msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -751,15 +810,15 @@ msgstr "" "l'éxecuteur. RESTART redémarre le flux au début. RESTART_WITH_CONTEXT " "redémarre le flux au début tout en conservant le contexte actuel." -#: authentik/flows/models.py:251 +#: authentik/flows/models.py msgid "Flow Stage Binding" msgstr "Liaison de l'étape de flux" -#: authentik/flows/models.py:252 +#: authentik/flows/models.py msgid "Flow Stage Bindings" msgstr "Liaisons d'étape de flux" -#: authentik/flows/models.py:267 +#: authentik/flows/models.py msgid "" "Flow used by an authenticated user to configure this Stage. If empty, user " "will not be able to configure this stage." @@ -767,36 +826,40 @@ msgstr "" "Flux utilisé par un utilisateur authentifié pour configurer cette étape. " "S'il est vide, l'utilisateur ne sera pas en mesure de le configurer." -#: authentik/flows/models.py:307 +#: authentik/flows/models.py msgid "Flow Token" msgstr "Jeton du flux" -#: authentik/flows/models.py:308 +#: authentik/flows/models.py msgid "Flow Tokens" msgstr "Jetons du flux" -#: authentik/lib/utils/time.py:27 +#: authentik/flows/views/executor.py +msgid "Invalid next URL" +msgstr "URL suivante invalide" + +#: authentik/lib/utils/time.py #, python-format msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." msgstr "%(value)sn'est pas dans le bon format de 'hours=3;minutes=1'." -#: authentik/lib/validators.py:16 +#: authentik/lib/validators.py #, python-brace-format msgid "The fields {field_names} must be used together." msgstr "Les champs {field_names} doivent être utilisés ensemble." -#: authentik/outposts/api/service_connections.py:127 +#: authentik/outposts/api/service_connections.py msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." msgstr "" "Vous pouvez seulement utiliser un kubeconfig vide quand vous vous connectez " "à un cluster local." -#: authentik/outposts/api/service_connections.py:135 +#: authentik/outposts/api/service_connections.py msgid "Invalid kubeconfig" msgstr "kubeconfig invalide" -#: authentik/outposts/models.py:123 +#: authentik/outposts/models.py msgid "" "If enabled, use the local connection. Required Docker socket/Kubernetes " "Integration" @@ -804,15 +867,15 @@ msgstr "" "Si activé, utilise la connexion locale. L'intégration Docker " "socket/Kubernetes est requise" -#: authentik/outposts/models.py:153 +#: authentik/outposts/models.py msgid "Outpost Service-Connection" msgstr "Connexion de service de l'avant-poste" -#: authentik/outposts/models.py:154 +#: authentik/outposts/models.py msgid "Outpost Service-Connections" msgstr "Connexions de service de l'avant-poste" -#: authentik/outposts/models.py:162 +#: authentik/outposts/models.py msgid "" "Can be in the format of 'unix://' when connecting to a local docker " "daemon, or 'https://:2376' when connecting to a remote system." @@ -821,7 +884,7 @@ msgstr "" " local, ou \"https://:2376\" pour une connexion à un système " "distant." -#: authentik/outposts/models.py:174 +#: authentik/outposts/models.py msgid "" "CA which the endpoint's Certificate is verified against. Can be left empty " "for no validation." @@ -829,7 +892,7 @@ msgstr "" "AC auprès de laquelle le certificat du terminal est vérifié. Peut être " "laissé vide en l'absence de validation." -#: authentik/outposts/models.py:186 +#: authentik/outposts/models.py msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." @@ -837,15 +900,15 @@ msgstr "" "Certificat et clé utilisés pour l'authentification. Peut être laissé vide si" " pas d'authentification." -#: authentik/outposts/models.py:204 +#: authentik/outposts/models.py msgid "Docker Service-Connection" msgstr "Connexion de service Docker" -#: authentik/outposts/models.py:205 +#: authentik/outposts/models.py msgid "Docker Service-Connections" msgstr "Connexions de service Docker" -#: authentik/outposts/models.py:213 +#: authentik/outposts/models.py msgid "" "Paste your kubeconfig here. authentik will automatically use the currently " "selected context." @@ -853,19 +916,19 @@ msgstr "" "Coller votre kubeconfig ici. authentik va automatiquement utiliseur le " "contexte actuellement sélectionné." -#: authentik/outposts/models.py:219 +#: authentik/outposts/models.py msgid "Verify SSL Certificates of the Kubernetes API endpoint" msgstr "Vérifier les certificats SSL de l'API Kubernetes" -#: authentik/outposts/models.py:236 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connection" msgstr "Connexion de service Kubernetes" -#: authentik/outposts/models.py:237 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connections" msgstr "Connexions de service Kubernetes" -#: authentik/outposts/models.py:253 +#: authentik/outposts/models.py msgid "" "Select Service-Connection authentik should use to manage this outpost. Leave" " empty if authentik should not handle the deployment." @@ -873,28 +936,28 @@ msgstr "" "Sélectionner la connexion de service qu'authentik doit utiliser pour gérer " "cet avant-poste. Laisser vide si authentik ne doit pas gérer le déploiement." -#: authentik/outposts/models.py:420 +#: authentik/outposts/models.py msgid "Outpost" msgstr "Avant-poste" -#: authentik/outposts/models.py:421 +#: authentik/outposts/models.py msgid "Outposts" msgstr "Avant-postes" -#: authentik/policies/denied.py:24 +#: authentik/policies/denied.py msgid "Access denied" msgstr "Accès refusé" -#: authentik/policies/dummy/models.py:44 +#: authentik/policies/dummy/models.py msgid "Dummy Policy" msgstr "Politique Factice" -#: authentik/policies/dummy/models.py:45 +#: authentik/policies/dummy/models.py msgid "Dummy Policies" msgstr "Politiques Factices" -#: authentik/policies/event_matcher/api.py:20 -#: authentik/policies/event_matcher/models.py:56 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected application. When left empty, all " "applications are matched." @@ -902,8 +965,8 @@ msgstr "" "Inclure les évènements créés par cette application. S'il est laissé vide, " "toutes les applications seront incluses." -#: authentik/policies/event_matcher/api.py:29 -#: authentik/policies/event_matcher/models.py:64 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected model. When left empty, all models are " "matched. When an app is selected, all the application's models are matched." @@ -912,11 +975,11 @@ msgstr "" "laissé vide, tous les modèles sont pris en compte. Lorsqu'une application " "est sélectionnée, tous les modèles de l'application sont pris en compte." -#: authentik/policies/event_matcher/api.py:42 +#: authentik/policies/event_matcher/api.py msgid "At least one criteria must be set." msgstr "Au moins un critère doit être défini." -#: authentik/policies/event_matcher/models.py:48 +#: authentik/policies/event_matcher/models.py msgid "" "Match created events with this action type. When left empty, all action " "types will be matched." @@ -924,7 +987,7 @@ msgstr "" "Inclure les événements créés avec ce type d'action. S'il est laissé vide, " "tous les types d'action seront inclus." -#: authentik/policies/event_matcher/models.py:73 +#: authentik/policies/event_matcher/models.py msgid "" "Matches Event's Client IP (strict matching, for network matching use an " "Expression Policy)" @@ -932,78 +995,78 @@ msgstr "" "Inclure l'adresse IP du client de l'évènement (correspondante stricte, pour " "un correspondance sur le réseau utiliser une politique d'expression)" -#: authentik/policies/event_matcher/models.py:143 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policy" msgstr "Politique d'association d'évènements" -#: authentik/policies/event_matcher/models.py:144 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policies" msgstr "Politiques d'association d'évènements" -#: authentik/policies/expiry/models.py:45 +#: authentik/policies/expiry/models.py #, python-format msgid "Password expired %(days)d days ago. Please update your password." msgstr "" "Mot de passe expiré il y a %(days)d jours. Merci de mettre à jour votre mot " "de passe." -#: authentik/policies/expiry/models.py:49 +#: authentik/policies/expiry/models.py msgid "Password has expired." msgstr "Le Mot de Passe a expiré." -#: authentik/policies/expiry/models.py:53 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policy" msgstr "Politique d'expiration de Mot de Passe" -#: authentik/policies/expiry/models.py:54 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policies" msgstr "Politiques d'expiration de mot de passe" -#: authentik/policies/expression/models.py:40 +#: authentik/policies/expression/models.py msgid "Expression Policy" msgstr "Politique d'Expression" -#: authentik/policies/expression/models.py:41 +#: authentik/policies/expression/models.py msgid "Expression Policies" msgstr "Politiques d'expression" -#: authentik/policies/models.py:22 +#: authentik/policies/models.py msgid "all, all policies must pass" msgstr "toutes, toutes les politiques doivent réussir" -#: authentik/policies/models.py:23 +#: authentik/policies/models.py msgid "any, any policy must pass" msgstr "n'importe, n'importe quelle politique doit réussir" -#: authentik/policies/models.py:46 +#: authentik/policies/models.py msgid "Policy Binding Model" msgstr "Liaison de modèle de politique" -#: authentik/policies/models.py:47 +#: authentik/policies/models.py msgid "Policy Binding Models" msgstr "Liaison de modèles de politique" -#: authentik/policies/models.py:86 +#: authentik/policies/models.py msgid "Negates the outcome of the policy. Messages are unaffected." msgstr "Inverse la sortie de la politique. Les messages ne sont pas affectés." -#: authentik/policies/models.py:89 +#: authentik/policies/models.py msgid "Timeout after which Policy execution is terminated." msgstr "Expiration après que l'exécution de la politique soit terminée." -#: authentik/policies/models.py:92 +#: authentik/policies/models.py msgid "Result if the Policy execution fails." msgstr "Résultat si l'éxecution de la Politique échoue." -#: authentik/policies/models.py:145 +#: authentik/policies/models.py msgid "Policy Binding" msgstr "Liaison de politique" -#: authentik/policies/models.py:146 +#: authentik/policies/models.py msgid "Policy Bindings" msgstr "Liaisons des politiques" -#: authentik/policies/models.py:167 +#: authentik/policies/models.py msgid "" "When this option is enabled, all executions of this policy will be logged. " "By default, only execution errors are logged." @@ -1011,108 +1074,107 @@ msgstr "" "Si activée, toutes les exécutions de cette politique seront enregistrées. " "Par défaut, seules les erreurs d'exécution sont consignées." -#: authentik/policies/models.py:189 +#: authentik/policies/models.py msgid "Policy" msgstr "Politique" -#: authentik/policies/models.py:190 +#: authentik/policies/models.py msgid "Policies" msgstr "Politiques" -#: authentik/policies/models.py:193 +#: authentik/policies/models.py msgid "View Policy's cache metrics" msgstr "Voir les métriques de cache de la politique" -#: authentik/policies/models.py:194 +#: authentik/policies/models.py msgid "Clear Policy's cache metrics" msgstr "Nettoyer les métriques de cache de la politique" -#: authentik/policies/password/models.py:27 +#: authentik/policies/password/models.py msgid "Field key to check, field keys defined in Prompt stages are available." msgstr "" "Clé de champ à vérifier ; les clés de champ définies dans les étapes de " "d'invite sont disponibles." -#: authentik/policies/password/models.py:44 +#: authentik/policies/password/models.py msgid "How many times the password hash is allowed to be on haveibeenpwned" msgstr "" "Combien de fois le hachage du mot de passe est-il autorisé sur " "haveibeenpwned" -#: authentik/policies/password/models.py:49 +#: authentik/policies/password/models.py msgid "" "If the zxcvbn score is equal or less than this value, the policy will fail." msgstr "" "Si le score zxcvbn est égal ou inférieur à cette valeur, la politique " "échouera." -#: authentik/policies/password/models.py:72 +#: authentik/policies/password/models.py msgid "Password not set in context" msgstr "Mot de passe non défini dans le contexte" -#: authentik/policies/password/models.py:134 +#: authentik/policies/password/models.py #, python-format msgid "Password exists on %(count)d online lists." msgstr "Le mot de passe existe sur %(count)d liste en ligne." -#: authentik/policies/password/models.py:154 +#: authentik/policies/password/models.py msgid "Password is too weak." msgstr "Le mot de passe est trop faible." -#: authentik/policies/password/models.py:162 +#: authentik/policies/password/models.py msgid "Password Policy" msgstr "Politique de Mots de Passe" -#: authentik/policies/password/models.py:163 +#: authentik/policies/password/models.py msgid "Password Policies" msgstr "Politiques de Mot de Passe" -#: authentik/policies/reputation/api.py:18 +#: authentik/policies/reputation/api.py msgid "Either IP or Username must be checked" msgstr "L'IP ou le nom d'utilisateur doit être vérifé" -#: authentik/policies/reputation/models.py:67 +#: authentik/policies/reputation/models.py msgid "Reputation Policy" msgstr "Politique de Réputation" -#: authentik/policies/reputation/models.py:68 +#: authentik/policies/reputation/models.py msgid "Reputation Policies" msgstr "Politiques de Réputation" -#: authentik/policies/reputation/models.py:96 +#: authentik/policies/reputation/models.py msgid "Reputation Score" msgstr "Score de Réputation" -#: authentik/policies/reputation/models.py:97 +#: authentik/policies/reputation/models.py msgid "Reputation Scores" msgstr "Scores de Réputation" -#: authentik/policies/templates/policies/denied.html:7 -#: authentik/policies/templates/policies/denied.html:11 +#: authentik/policies/templates/policies/denied.html msgid "Permission denied" msgstr "Permission refusée" -#: authentik/policies/templates/policies/denied.html:21 +#: authentik/policies/templates/policies/denied.html msgid "User's avatar" msgstr "Avatar de l'utilisateu" -#: authentik/policies/templates/policies/denied.html:25 +#: authentik/policies/templates/policies/denied.html msgid "Not you?" msgstr "Pas vous ?" -#: authentik/policies/templates/policies/denied.html:33 +#: authentik/policies/templates/policies/denied.html msgid "Request has been denied." msgstr "La requête a été refusée." -#: authentik/policies/templates/policies/denied.html:44 +#: authentik/policies/templates/policies/denied.html msgid "Messages:" msgstr "Messages:" -#: authentik/policies/templates/policies/denied.html:54 +#: authentik/policies/templates/policies/denied.html msgid "Explanation:" msgstr "Explication :" -#: authentik/policies/templates/policies/denied.html:58 +#: authentik/policies/templates/policies/denied.html #, python-format msgid "" "\n" @@ -1123,15 +1185,15 @@ msgstr "" " L'association de politique '%(name)s' a renvoyé le résultat '%(result)s'\n" " " -#: authentik/policies/views.py:68 +#: authentik/policies/views.py msgid "Failed to resolve application" msgstr "Impossible de résoudre l'application" -#: authentik/providers/ldap/models.py:25 +#: authentik/providers/ldap/models.py msgid "DN under which objects are accessible." msgstr "DN sous lequel les objets sont accessibles." -#: authentik/providers/ldap/models.py:34 +#: authentik/providers/ldap/models.py msgid "" "Users in this group can do search queries. If not set, every user can " "execute search queries." @@ -1139,7 +1201,7 @@ msgstr "" "Les utilisateurs dans ce groupe peuvent faire des requêtes de recherche. Si " "laissé vide, tous les utilisateurs peuvent faire des requêtes de recherche." -#: authentik/providers/ldap/models.py:53 +#: authentik/providers/ldap/models.py msgid "" "The start for uidNumbers, this number is added to the user.pk to make sure " "that the numbers aren't too low for POSIX users. Default is 2000 to ensure " @@ -1150,7 +1212,7 @@ msgstr "" "défaut est 2000 pour s'assurer que nous n'entrons pas en collision avec les " "uidNumber des utilisateurs locaux" -#: authentik/providers/ldap/models.py:62 +#: authentik/providers/ldap/models.py msgid "" "The start for gidNumbers, this number is added to a number generated from " "the group.pk to make sure that the numbers aren't too low for POSIX groups. " @@ -1163,8 +1225,7 @@ msgstr "" "n'entrons pas en collision avec les groupes locaux ou les gidNumber des " "groupes primaires des utilisateurs" -#: authentik/providers/ldap/models.py:76 -#: authentik/providers/radius/models.py:34 +#: authentik/providers/ldap/models.py authentik/providers/radius/models.py msgid "" "When enabled, code-based multi-factor authentication can be used by " "appending a semicolon and the TOTP code to the password. This should only be" @@ -1178,37 +1239,37 @@ msgstr "" " se lieront à ce fournisseur ont un dispositif TOTP configuré, faute de quoi" " un mot de passe peut être rejeté à tort s'il contient un point-virgule." -#: authentik/providers/ldap/models.py:108 +#: authentik/providers/ldap/models.py msgid "LDAP Provider" msgstr "Fournisseur LDAP" -#: authentik/providers/ldap/models.py:109 +#: authentik/providers/ldap/models.py msgid "LDAP Providers" msgstr "Fournisseurs LDAP" -#: authentik/providers/oauth2/id_token.py:27 +#: authentik/providers/oauth2/id_token.py msgid "Based on the Hashed User ID" msgstr "Basé sur le hash de l'ID utilisateur" -#: authentik/providers/oauth2/id_token.py:28 +#: authentik/providers/oauth2/id_token.py msgid "Based on user ID" msgstr "Basé sur l'ID de l'utilisateur" -#: authentik/providers/oauth2/id_token.py:29 +#: authentik/providers/oauth2/id_token.py msgid "Based on user UUID" msgstr "Basé sur le UUID de l'utilisateur" -#: authentik/providers/oauth2/id_token.py:30 +#: authentik/providers/oauth2/id_token.py msgid "Based on the username" msgstr "Basé sur le nom d'utilisateur" -#: authentik/providers/oauth2/id_token.py:33 +#: authentik/providers/oauth2/id_token.py msgid "Based on the User's Email. This is recommended over the UPN method." msgstr "" "Basé sur le courriel utilisateur. Ceci est recommandé par rapport à la " "méthode UPN." -#: authentik/providers/oauth2/id_token.py:38 +#: authentik/providers/oauth2/id_token.py msgid "" "Based on the User's UPN, only works if user has a 'upn' attribute set. Use " "this method only if you have different UPN and Mail domains." @@ -1217,65 +1278,65 @@ msgstr "" "attribut \"upn\" renseigné. Utiliser cette méthode seulement si les domaines" " UPN et courriel sont différents." -#: authentik/providers/oauth2/models.py:43 +#: authentik/providers/oauth2/models.py msgid "Confidential" msgstr "Confidentiel" -#: authentik/providers/oauth2/models.py:44 +#: authentik/providers/oauth2/models.py msgid "Public" msgstr "Public" -#: authentik/providers/oauth2/models.py:66 +#: authentik/providers/oauth2/models.py msgid "Same identifier is used for all providers" msgstr "Le même identifiant est utilisé pour tous les fournisseurs" -#: authentik/providers/oauth2/models.py:68 +#: authentik/providers/oauth2/models.py msgid "Each provider has a different issuer, based on the application slug." msgstr "" "Chaque fournisseur a un émetteur différent, basé sur le slug de " "l'application." -#: authentik/providers/oauth2/models.py:75 +#: authentik/providers/oauth2/models.py msgid "code (Authorization Code Flow)" msgstr "code (Authorization Code Flow)" -#: authentik/providers/oauth2/models.py:76 +#: authentik/providers/oauth2/models.py msgid "id_token (Implicit Flow)" msgstr "id_token (Implicit Flow)" -#: authentik/providers/oauth2/models.py:77 +#: authentik/providers/oauth2/models.py msgid "id_token token (Implicit Flow)" msgstr "id_token token (Implicit Flow)" -#: authentik/providers/oauth2/models.py:78 +#: authentik/providers/oauth2/models.py msgid "code token (Hybrid Flow)" msgstr "code token (Hybrid Flow)" -#: authentik/providers/oauth2/models.py:79 +#: authentik/providers/oauth2/models.py msgid "code id_token (Hybrid Flow)" msgstr "code id_token (Hybrid Flow)" -#: authentik/providers/oauth2/models.py:80 +#: authentik/providers/oauth2/models.py msgid "code id_token token (Hybrid Flow)" msgstr "code id_token token (Hybrid Flow)" -#: authentik/providers/oauth2/models.py:86 +#: authentik/providers/oauth2/models.py msgid "HS256 (Symmetric Encryption)" msgstr "HS256 (chiffrement symétrique)" -#: authentik/providers/oauth2/models.py:87 +#: authentik/providers/oauth2/models.py msgid "RS256 (Asymmetric Encryption)" msgstr "RS256 (chiffrement asymétrique)" -#: authentik/providers/oauth2/models.py:88 +#: authentik/providers/oauth2/models.py msgid "ES256 (Asymmetric Encryption)" msgstr "ES256 (Chiffrement Asymétrique)" -#: authentik/providers/oauth2/models.py:94 +#: authentik/providers/oauth2/models.py msgid "Scope used by the client" msgstr "Portées utilisées par le client" -#: authentik/providers/oauth2/models.py:98 +#: authentik/providers/oauth2/models.py msgid "" "Description shown to the user when consenting. If left empty, the user won't" " be informed." @@ -1283,19 +1344,19 @@ msgstr "" "Description montrée à l'utilisateur lors de l'approbation. Aucune " "information présentée à l'utilisateur si laissé vide." -#: authentik/providers/oauth2/models.py:117 +#: authentik/providers/oauth2/models.py msgid "Scope Mapping" msgstr "Mappage de Portée" -#: authentik/providers/oauth2/models.py:118 +#: authentik/providers/oauth2/models.py msgid "Scope Mappings" msgstr "Mappage de Portée" -#: authentik/providers/oauth2/models.py:128 +#: authentik/providers/oauth2/models.py msgid "Client Type" msgstr "Type de Client" -#: authentik/providers/oauth2/models.py:130 +#: authentik/providers/oauth2/models.py msgid "" "Confidential clients are capable of maintaining the confidentiality of their" " credentials. Public clients are incapable" @@ -1303,27 +1364,27 @@ msgstr "" "Les clients confidentiels sont capable de maintenir la confidentialité de " "leurs identifiants. Les clients publics n'en sont pas capables." -#: authentik/providers/oauth2/models.py:137 +#: authentik/providers/oauth2/models.py msgid "Client ID" msgstr "ID client" -#: authentik/providers/oauth2/models.py:143 +#: authentik/providers/oauth2/models.py msgid "Client Secret" msgstr "Secret du client" -#: authentik/providers/oauth2/models.py:149 +#: authentik/providers/oauth2/models.py msgid "Redirect URIs" msgstr "URIs de redirection" -#: authentik/providers/oauth2/models.py:150 +#: authentik/providers/oauth2/models.py msgid "Enter each URI on a new line." msgstr "Entrez chaque URI sur une nouvelle ligne." -#: authentik/providers/oauth2/models.py:155 +#: authentik/providers/oauth2/models.py msgid "Include claims in id_token" msgstr "Include les demandes utilisateurs dans id_token" -#: authentik/providers/oauth2/models.py:157 +#: authentik/providers/oauth2/models.py msgid "" "Include User claims from scopes in the id_token, for applications that don't" " access the userinfo endpoint." @@ -1331,7 +1392,7 @@ msgstr "" "Inclure depuis la portée les demandes utilisateurs dans id_token, pour les " "applications qui n'accèdent pas au point de terminaison userinfo." -#: authentik/providers/oauth2/models.py:166 +#: authentik/providers/oauth2/models.py msgid "" "Access codes not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." @@ -1339,8 +1400,7 @@ msgstr "" "Les codes d'accès ne seront plus valide à partir de l'heure actuelle + cette" " valeur (Format : hours=1;minutes=2;seconds=3)." -#: authentik/providers/oauth2/models.py:174 -#: authentik/providers/oauth2/models.py:182 +#: authentik/providers/oauth2/models.py msgid "" "Tokens not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." @@ -1348,7 +1408,7 @@ msgstr "" "Les jetons ne seront plus valides à partir de l'heure actuelle + cette " "valeur (Format: hours=1;minutes=2;seconds=3)." -#: authentik/providers/oauth2/models.py:191 +#: authentik/providers/oauth2/models.py msgid "" "Configure what data should be used as unique User Identifier. For most " "cases, the default should be fine." @@ -1356,15 +1416,15 @@ msgstr "" "Configure quelle donnée utiliser pour l'identifiant unique utilisateur. La " "valeur par défaut devrait être correcte dans la plupart des cas." -#: authentik/providers/oauth2/models.py:198 +#: authentik/providers/oauth2/models.py msgid "Configure how the issuer field of the ID Token should be filled." msgstr "Configure comment le champ émetteur du jeton ID sera rempli." -#: authentik/providers/oauth2/models.py:203 +#: authentik/providers/oauth2/models.py msgid "Signing Key" msgstr "Clé de signature" -#: authentik/providers/oauth2/models.py:207 +#: authentik/providers/oauth2/models.py msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." @@ -1372,7 +1432,7 @@ msgstr "" "Clé utilisée pour signer les jetons. Nécessaire uniquement lorsque " "l'algorithme JWT est réglé sur RS256." -#: authentik/providers/oauth2/models.py:214 +#: authentik/providers/oauth2/models.py msgid "" "Any JWT signed by the JWK of the selected source can be used to " "authenticate." @@ -1380,119 +1440,117 @@ msgstr "" "Tout JWT signé par le JWK de la source sélectionnée peut être utilisé pour " "s'authentifier." -#: authentik/providers/oauth2/models.py:287 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Provider" msgstr "Fournisseur OAuth2/OpenID" -#: authentik/providers/oauth2/models.py:288 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Providers" msgstr "Fournisseurs OAuth2/OpenID" -#: authentik/providers/oauth2/models.py:297 -#: authentik/providers/oauth2/models.py:430 +#: authentik/providers/oauth2/models.py msgid "Scopes" msgstr "Portées" -#: authentik/providers/oauth2/models.py:317 +#: authentik/providers/oauth2/models.py msgid "Code" msgstr "Code" -#: authentik/providers/oauth2/models.py:318 +#: authentik/providers/oauth2/models.py msgid "Nonce" msgstr "Nonce" -#: authentik/providers/oauth2/models.py:319 +#: authentik/providers/oauth2/models.py msgid "Code Challenge" msgstr "Challenge à code" -#: authentik/providers/oauth2/models.py:321 +#: authentik/providers/oauth2/models.py msgid "Code Challenge Method" msgstr "Méthode de challenge à code" -#: authentik/providers/oauth2/models.py:341 +#: authentik/providers/oauth2/models.py msgid "Authorization Code" msgstr "Code d'autorisation" -#: authentik/providers/oauth2/models.py:342 +#: authentik/providers/oauth2/models.py msgid "Authorization Codes" msgstr "Codes d'autorisation" -#: authentik/providers/oauth2/models.py:384 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Token" msgstr "Jeton d'accès OAuth2" -#: authentik/providers/oauth2/models.py:385 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Tokens" msgstr "Jetons d'accès OAuth2" -#: authentik/providers/oauth2/models.py:395 +#: authentik/providers/oauth2/models.py msgid "ID Token" msgstr "ID du jeton" -#: authentik/providers/oauth2/models.py:414 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Token" msgstr "Jeton de rafraîchissement OAuth2" -#: authentik/providers/oauth2/models.py:415 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Tokens" msgstr "Jetons de rafraîchissement OAuth2" -#: authentik/providers/oauth2/models.py:442 +#: authentik/providers/oauth2/models.py msgid "Device Token" msgstr "Jeton d'équipement" -#: authentik/providers/oauth2/models.py:443 +#: authentik/providers/oauth2/models.py msgid "Device Tokens" msgstr "Jetons d'équipement" -#: authentik/providers/oauth2/views/authorize.py:489 -#: authentik/providers/saml/views/flows.py:87 -#, python-format -msgid "Redirecting to %(app)s..." -msgstr "Redirection vers %(app)s..." +#: authentik/providers/oauth2/views/authorize.py +#: authentik/providers/saml/views/flows.py +#, python-brace-format +msgid "Redirecting to {app}..." +msgstr "Redirection vers {app}..." -#: authentik/providers/oauth2/views/device_init.py:151 +#: authentik/providers/oauth2/views/device_init.py msgid "Invalid code" msgstr "Code invalide" -#: authentik/providers/oauth2/views/userinfo.py:55 -#: authentik/providers/oauth2/views/userinfo.py:56 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your User Information" msgstr "Compatibilité GitHub : accès aux informations utilisateur" -#: authentik/providers/oauth2/views/userinfo.py:57 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access you Email addresses" msgstr "Compatibilité GitHub : accès aux adresses email" -#: authentik/providers/oauth2/views/userinfo.py:58 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your Groups" msgstr "Compatibilité GitHub : accès aux groupes" -#: authentik/providers/oauth2/views/userinfo.py:59 +#: authentik/providers/oauth2/views/userinfo.py msgid "authentik API Access on behalf of your user" msgstr "Accès à l'API authentik au nom des utilisateurs" -#: authentik/providers/proxy/api.py:52 +#: authentik/providers/proxy/api.py msgid "User and password attributes must be set when basic auth is enabled." msgstr "" "Les attributs utilisateur et mot de passe doivent être définis lorsque " "l'authentification basique est activée." -#: authentik/providers/proxy/api.py:63 +#: authentik/providers/proxy/api.py msgid "Internal host cannot be empty when forward auth is disabled." msgstr "" "L'hôte interne ne peut pas être vide lorsque le transfert d'authentification" " est désactivée." -#: authentik/providers/proxy/models.py:54 +#: authentik/providers/proxy/models.py msgid "Validate SSL Certificates of upstream servers" msgstr "Valider les certificats SSL des serveurs en amont" -#: authentik/providers/proxy/models.py:55 +#: authentik/providers/proxy/models.py msgid "Internal host SSL Validation" msgstr "Validation SSL de l'hôte interne" -#: authentik/providers/proxy/models.py:61 +#: authentik/providers/proxy/models.py msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." @@ -1500,7 +1558,7 @@ msgstr "" "Activer le support du transfert d'authentification dans traefik et nginx " "auth_request. Exclusif avec internal_host." -#: authentik/providers/proxy/models.py:70 +#: authentik/providers/proxy/models.py msgid "" "Regular expressions for which authentication is not required. Each new line " "is interpreted as a new Regular Expression." @@ -1509,7 +1567,7 @@ msgstr "" "Chaque nouvelle ligne est interprétée comme une nouvelle expression " "régulière." -#: authentik/providers/proxy/models.py:78 +#: authentik/providers/proxy/models.py msgid "" "When enabled, this provider will intercept the authorization header and " "authenticate requests based on its value." @@ -1517,11 +1575,11 @@ msgstr "" "Quand activé, ce fournisseur va intercepter l'en-tête d'authorisation et " "authentifier les requêtes en fonction de sa valeur." -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py msgid "Set HTTP-Basic Authentication" msgstr "Définir l'authentification HTTP-Basic" -#: authentik/providers/proxy/models.py:86 +#: authentik/providers/proxy/models.py msgid "" "Set a custom HTTP-Basic Authentication header based on values from " "authentik." @@ -1529,11 +1587,11 @@ msgstr "" "Définir un en-tête d'authentification HTTP-Basic personnalisé basé sur les " "valeurs de authentik." -#: authentik/providers/proxy/models.py:91 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Username Key" msgstr "Clé de l'utilisateur HTTP-Basic" -#: authentik/providers/proxy/models.py:93 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the user part of the HTTP-Basic Header. If not" " set, the user's Email address is used." @@ -1542,31 +1600,31 @@ msgstr "" " HTTP-Basic. S'il n'est pas défini, le courriel de l'utilisateur est " "utilisée." -#: authentik/providers/proxy/models.py:99 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Password Key" msgstr "Clé du mot de passe HTTP-Basic" -#: authentik/providers/proxy/models.py:100 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the password part of the HTTP-Basic Header." msgstr "" "Attribut d'utilisateur/groupe utilisé pour la champ mot de passe de l'en-" "tête HTTP-Basic." -#: authentik/providers/proxy/models.py:154 +#: authentik/providers/proxy/models.py msgid "Proxy Provider" msgstr "Fournisseur Proxy" -#: authentik/providers/proxy/models.py:155 +#: authentik/providers/proxy/models.py msgid "Proxy Providers" msgstr "Fournisseur de Proxy" -#: authentik/providers/radius/models.py:18 +#: authentik/providers/radius/models.py msgid "Shared secret between clients and server to hash packets." msgstr "" "Secret partagé entre les clients et le serveur pour hacher les paquets." -#: authentik/providers/radius/models.py:24 +#: authentik/providers/radius/models.py msgid "" "List of CIDRs (comma-separated) that clients can connect from. A more " "specific CIDR will match before a looser one. Clients connecting from a non-" @@ -1577,28 +1635,28 @@ msgstr "" "moins spécifique. Les clients se connectant depuis un CIDR non spécifié " "seront rejetés." -#: authentik/providers/radius/models.py:60 +#: authentik/providers/radius/models.py msgid "Radius Provider" msgstr "Fournisseur Radius" -#: authentik/providers/radius/models.py:61 +#: authentik/providers/radius/models.py msgid "Radius Providers" msgstr "Fournisseurs Radius" -#: authentik/providers/saml/api/providers.py:258 +#: authentik/providers/saml/api/providers.py msgid "Invalid XML Syntax" msgstr "Syntaxe XML Invalide" -#: authentik/providers/saml/api/providers.py:268 -#, python-format -msgid "Failed to import Metadata: %(message)s" -msgstr "Échec d'import des metadata : %(message)s" +#: authentik/providers/saml/api/providers.py +#, python-brace-format +msgid "Failed to import Metadata: {messages}" +msgstr "Échec d'import des métadonnées : {messages}" -#: authentik/providers/saml/models.py:38 +#: authentik/providers/saml/models.py msgid "ACS URL" msgstr "ACS URL" -#: authentik/providers/saml/models.py:43 +#: authentik/providers/saml/models.py msgid "" "Value of the audience restriction field of the assertion. When left empty, " "no audience restriction will be added." @@ -1606,15 +1664,15 @@ msgstr "" "Valeur du champ de restriction d'audience de l'assertion. Si vide, aucune " "restriction d'audience ne sera ajoutée." -#: authentik/providers/saml/models.py:47 +#: authentik/providers/saml/models.py msgid "Also known as EntityID" msgstr "Aussi appelé EntityID" -#: authentik/providers/saml/models.py:51 +#: authentik/providers/saml/models.py msgid "Service Provider Binding" msgstr "Liaison du fournisseur de services" -#: authentik/providers/saml/models.py:53 +#: authentik/providers/saml/models.py msgid "" "This determines how authentik sends the response back to the Service " "Provider." @@ -1622,11 +1680,11 @@ msgstr "" "Cela détermine la manière dont authentik renvoie la réponse au fournisseur " "de services." -#: authentik/providers/saml/models.py:63 +#: authentik/providers/saml/models.py msgid "NameID Property Mapping" msgstr "Mappage de la propriété NameID" -#: authentik/providers/saml/models.py:65 +#: authentik/providers/saml/models.py msgid "" "Configure how the NameID value will be created. When left empty, the " "NameIDPolicy of the incoming request will be considered" @@ -1634,7 +1692,7 @@ msgstr "" "Configure la manière dont la valeur NameID sera créée. Si laissé vide, la " "NameIDPolicy de la requête entrante sera prise en compte" -#: authentik/providers/saml/models.py:74 +#: authentik/providers/saml/models.py msgid "" "Assertion valid not before current time + this value (Format: " "hours=-1;minutes=-2;seconds=-3)." @@ -1642,7 +1700,7 @@ msgstr "" "L'assertion ne sera plus valide à partir de l'heure actuelle + cette valeur " "(Format: hours=-1;minutes=-2;seconds=-3)." -#: authentik/providers/saml/models.py:82 +#: authentik/providers/saml/models.py msgid "" "Assertion not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." @@ -1650,7 +1708,7 @@ msgstr "" "Assertion non valide après écoulement de ce délai (format : " "hours=1;minutes=2;seconds=3)" -#: authentik/providers/saml/models.py:91 +#: authentik/providers/saml/models.py msgid "" "Session not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." @@ -1658,43 +1716,59 @@ msgstr "" "La session n'est plus valide à partir de l'heure actuelle + cette valeur " "(Format: hours=1;minutes=2;seconds=3)." -#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA1" msgstr "SHA1" -#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA256" msgstr "SHA256" -#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA384" msgstr "SHA384" -#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA512" msgstr "SHA512" -#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA1" msgstr "RSA-SHA1" -#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA256" msgstr "RSA-SHA256" -#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA384" msgstr "RSA-SHA384" -#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA512" msgstr "RSA-SHA512" -#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA1" +msgstr "ECDSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA256" +msgstr "ECDSA-SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA384" +msgstr "ECDSA-SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA512" +msgstr "ECDSA-SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "DSA-SHA1" msgstr "DSA-SHA1" -#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "" "When selected, incoming assertion's Signatures will be validated against " "this certificate. To allow unsigned Requests, leave on default." @@ -1703,161 +1777,161 @@ msgstr "" "rapport à ce certificat. Pour autoriser les requêtes non signées, laissez la" " valeur par défaut." -#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Verification Certificate" msgstr "Certificat de validation" -#: authentik/providers/saml/models.py:136 +#: authentik/providers/saml/models.py msgid "Keypair used to sign outgoing Responses going to the Service Provider." msgstr "" "Paire de clés utilisées pour signer les réponses sortantes allant vers le " "fournisseur de services." -#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Signing Keypair" msgstr "Paire de clés de Signature" -#: authentik/providers/saml/models.py:142 +#: authentik/providers/saml/models.py msgid "Default relay_state value for IDP-initiated logins" msgstr "Valeur par défaut de relay_state des connexions initiées par l'IdP" -#: authentik/providers/saml/models.py:171 +#: authentik/providers/saml/models.py msgid "SAML Provider" msgstr "Fournisseur SAML" -#: authentik/providers/saml/models.py:172 +#: authentik/providers/saml/models.py msgid "SAML Providers" msgstr "Fournisseurs SAML" -#: authentik/providers/saml/models.py:196 +#: authentik/providers/saml/models.py msgid "SAML Property Mapping" msgstr "Mappages de propriétés SAML" -#: authentik/providers/saml/models.py:197 +#: authentik/providers/saml/models.py msgid "SAML Property Mappings" msgstr "Mappages de propriétés SAML" -#: authentik/providers/scim/models.py:23 +#: authentik/providers/scim/models.py msgid "Base URL to SCIM requests, usually ends in /v2" msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2" -#: authentik/providers/scim/models.py:24 +#: authentik/providers/scim/models.py msgid "Authentication token" msgstr "Jeton d'authentification" -#: authentik/providers/scim/models.py:30 authentik/sources/ldap/models.py:98 +#: authentik/providers/scim/models.py authentik/sources/ldap/models.py msgid "Property mappings used for group creation/updating." msgstr "" "Mappages de propriétés utilisés lors de la création et de la mise à jour des" " groupes." -#: authentik/providers/scim/models.py:72 +#: authentik/providers/scim/models.py msgid "SCIM Provider" msgstr "Fournisseur SCIM" -#: authentik/providers/scim/models.py:73 +#: authentik/providers/scim/models.py msgid "SCIM Providers" msgstr "Fournisseurs SCIM" -#: authentik/providers/scim/models.py:93 +#: authentik/providers/scim/models.py msgid "SCIM Mapping" msgstr "Mappage SCIM" -#: authentik/providers/scim/models.py:94 +#: authentik/providers/scim/models.py msgid "SCIM Mappings" msgstr "Mappages SCIM" -#: authentik/providers/scim/tasks.py:56 +#: authentik/providers/scim/tasks.py msgid "Starting full SCIM sync" msgstr "Démarrage d'une synchronisation SCIM complète" -#: authentik/providers/scim/tasks.py:66 +#: authentik/providers/scim/tasks.py #, python-format msgid "Syncing page %(page)d of users" msgstr "Synchronisation de la page %(page)d d'utilisateurs" -#: authentik/providers/scim/tasks.py:70 +#: authentik/providers/scim/tasks.py #, python-format msgid "Syncing page %(page)d of groups" msgstr "Synchronisation de la page %(page)d de groupes" -#: authentik/providers/scim/tasks.py:102 -#, python-format -msgid "Failed to sync user %(user_name)s due to remote error: %(error)s" +#: authentik/providers/scim/tasks.py +#, python-brace-format +msgid "Failed to sync user {user_name} due to remote error: {error}" msgstr "" -"Échec de synchronisation de l'utilisateur %(user_name)s dû à une erreur " -"distante : %(error)s" +"Échec de synchronisation de l'utilisateur {user_name} dû à une erreur " +"distante : {error}" -#: authentik/providers/scim/tasks.py:113 authentik/providers/scim/tasks.py:154 -#, python-format -msgid "Stopping sync due to error: %(error)s" -msgstr "Arrêt de la synchronisation due à l'erreur : %(error)s" +#: authentik/providers/scim/tasks.py +#, python-brace-format +msgid "Stopping sync due to error: {error}" +msgstr "Arrêt de la synchronisation due à l'erreur : {error}" -#: authentik/providers/scim/tasks.py:143 -#, python-format -msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" +#: authentik/providers/scim/tasks.py +#, python-brace-format +msgid "Failed to sync group {group_name} due to remote error: {error}" msgstr "" -"Échec de synchronisation du group %(group_name)s dû à une erreur distante : " -"%(error)s" +"Échec de synchronisation du groupe {group_name} dû à une erreur distante : " +"{error}" -#: authentik/rbac/models.py:51 +#: authentik/rbac/models.py msgid "Role" msgstr "Rôle" -#: authentik/rbac/models.py:52 +#: authentik/rbac/models.py msgid "Roles" msgstr "Rôles" -#: authentik/rbac/models.py:66 +#: authentik/rbac/models.py msgid "System permission" msgstr "Permission système" -#: authentik/rbac/models.py:67 +#: authentik/rbac/models.py msgid "System permissions" msgstr "Permissions système" -#: authentik/rbac/models.py:69 +#: authentik/rbac/models.py msgid "Can view system info" msgstr "Peut voir les informations du système" -#: authentik/rbac/models.py:70 +#: authentik/rbac/models.py msgid "Can view system tasks" msgstr "Peut voir les tâches du système" -#: authentik/rbac/models.py:71 +#: authentik/rbac/models.py msgid "Can run system tasks" msgstr "Peut lancer des tâches système" -#: authentik/rbac/models.py:72 +#: authentik/rbac/models.py msgid "Can access admin interface" msgstr "Peut accéder à l'interface d'administration" -#: authentik/rbac/models.py:73 +#: authentik/rbac/models.py msgid "Can view system settings" msgstr "Peut voir les réglages système" -#: authentik/rbac/models.py:74 +#: authentik/rbac/models.py msgid "Can edit system settings" msgstr "Peut modifier les réglages système" -#: authentik/recovery/management/commands/create_admin_group.py:12 +#: authentik/recovery/management/commands/create_admin_group.py msgid "Create admin group if the default group gets deleted." msgstr "Crée le groupe adminstrateur si le groupe par défaut est supprimé." -#: authentik/recovery/management/commands/create_recovery_key.py:16 +#: authentik/recovery/management/commands/create_recovery_key.py msgid "Create a Key which can be used to restore access to authentik." msgstr "" "Crée une clé qui peut être utilisée pour restaurer l'accès à authentik." -#: authentik/recovery/views.py:24 +#: authentik/recovery/views.py msgid "Used recovery-link to authenticate." msgstr "Utiliser un lien de récupération pour se connecter." -#: authentik/sources/ldap/models.py:41 +#: authentik/sources/ldap/models.py msgid "Server URI" msgstr "URI du serveur" -#: authentik/sources/ldap/models.py:50 +#: authentik/sources/ldap/models.py msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this" " keypair." @@ -1865,60 +1939,66 @@ msgstr "" "Éventuellement vérifier le certificat du server LDAP par rapport à la chaine" " d'autorité de certification de cette paire de clés." -#: authentik/sources/ldap/models.py:59 +#: authentik/sources/ldap/models.py msgid "" "Client certificate to authenticate against the LDAP Server's Certificate." msgstr "Certificat du client pour authentifier le certificat du serveur LDAP." -#: authentik/sources/ldap/models.py:62 +#: authentik/sources/ldap/models.py msgid "Bind CN" msgstr "Bind DN" -#: authentik/sources/ldap/models.py:64 +#: authentik/sources/ldap/models.py msgid "Enable Start TLS" msgstr "Activer Start TLS" -#: authentik/sources/ldap/models.py:65 +#: authentik/sources/ldap/models.py msgid "Use Server URI for SNI verification" msgstr "Utiliser l'URI du serveur pour la vérification SNI" -#: authentik/sources/ldap/models.py:67 +#: authentik/sources/ldap/models.py msgid "Base DN" msgstr "DN racine" -#: authentik/sources/ldap/models.py:69 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for User-queries." msgstr "Ajouté avant le DN de base pour les requêtes sur des utilisateurs." -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py msgid "Addition User DN" msgstr "Préfixe DN utilisateurs" -#: authentik/sources/ldap/models.py:74 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for Group-queries." msgstr "Ajouté avant le DN de base pour les requêtes sur des groupes." -#: authentik/sources/ldap/models.py:75 +#: authentik/sources/ldap/models.py msgid "Addition Group DN" msgstr "Préfixe DN groupes" -#: authentik/sources/ldap/models.py:81 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Users." msgstr "Les objets appliqués à ce filtre seront des utilisateurs." -#: authentik/sources/ldap/models.py:84 +#: authentik/sources/ldap/models.py msgid "Field which contains members of a group." msgstr "Champ qui contient les membres d'un groupe." -#: authentik/sources/ldap/models.py:88 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Groups." msgstr "Les objets appliqués à ce filtre seront des groupes." -#: authentik/sources/ldap/models.py:91 +#: authentik/sources/ldap/models.py msgid "Field which contains a unique Identifier." msgstr "Champ qui contient un identifiant unique." -#: authentik/sources/ldap/models.py:105 +#: authentik/sources/ldap/models.py +msgid "Update internal authentik password when login succeeds with LDAP" +msgstr "" +"Mettre à jour le mot de passe interne à authentik lorsque la connexion avec " +"LDAP réussi" + +#: authentik/sources/ldap/models.py msgid "" "When a user changes their password, sync it back to LDAP. This can only be " "enabled on a single LDAP source." @@ -1926,35 +2006,35 @@ msgstr "" "Lorsqu'un utilisateur change son mot de passe, le synchroniser à nouveau " "vers LDAP. Ne peut être activé que sur une seule source LDAP." -#: authentik/sources/ldap/models.py:248 +#: authentik/sources/ldap/models.py msgid "LDAP Source" msgstr "Source LDAP" -#: authentik/sources/ldap/models.py:249 +#: authentik/sources/ldap/models.py msgid "LDAP Sources" msgstr "Sources LDAP" -#: authentik/sources/ldap/models.py:271 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mapping" msgstr "Mappage de propriété LDAP" -#: authentik/sources/ldap/models.py:272 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mappings" msgstr "Mappages de propriété LDAP" -#: authentik/sources/ldap/signals.py:52 +#: authentik/sources/ldap/signals.py msgid "Password does not match Active Directory Complexity." msgstr "Le mot de passe ne correspond pas à la complexité d'Active Directory." -#: authentik/sources/oauth/clients/oauth2.py:68 +#: authentik/sources/oauth/clients/oauth2.py msgid "No token received." msgstr "Pas de jeton reçu." -#: authentik/sources/oauth/models.py:24 +#: authentik/sources/oauth/models.py msgid "Request Token URL" msgstr "URL du jeton de requête" -#: authentik/sources/oauth/models.py:26 +#: authentik/sources/oauth/models.py msgid "" "URL used to request the initial token. This URL is only required for OAuth " "1." @@ -1962,165 +2042,173 @@ msgstr "" "URL utilisée pour demander le jeton initial. Cette URL est uniquement " "requise pour OAuth 1." -#: authentik/sources/oauth/models.py:32 +#: authentik/sources/oauth/models.py msgid "Authorization URL" msgstr "URL d'autorisation" -#: authentik/sources/oauth/models.py:33 +#: authentik/sources/oauth/models.py msgid "URL the user is redirect to to conest the flow." msgstr "URL vers laquelle l'utilisateur est redirigé pour consentir au flux." -#: authentik/sources/oauth/models.py:38 +#: authentik/sources/oauth/models.py msgid "Access Token URL" msgstr "URL du jeton d'accès" -#: authentik/sources/oauth/models.py:39 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to retrieve tokens." msgstr "URL utilisée par authentik pour récupérer les jetons." -#: authentik/sources/oauth/models.py:44 +#: authentik/sources/oauth/models.py msgid "Profile URL" msgstr "URL de profil" -#: authentik/sources/oauth/models.py:45 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to get user information." msgstr "" "URL utilisée par authentik pour obtenir des informations sur l'utilisateur." -#: authentik/sources/oauth/models.py:48 +#: authentik/sources/oauth/models.py msgid "Additional Scopes" msgstr "Portées additionnelles" -#: authentik/sources/oauth/models.py:107 +#: authentik/sources/oauth/models.py msgid "OAuth Source" msgstr "Source OAuth" -#: authentik/sources/oauth/models.py:108 +#: authentik/sources/oauth/models.py msgid "OAuth Sources" msgstr "Sources OAuth" -#: authentik/sources/oauth/models.py:116 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Source" msgstr "Source d'OAuth GitHub" -#: authentik/sources/oauth/models.py:117 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Sources" msgstr "Sources d'OAuth GitHub" -#: authentik/sources/oauth/models.py:125 +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Source" +msgstr "Source d'OAuth GitLab" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Sources" +msgstr "Sources d'OAuth GitLab" + +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Source" msgstr "Source d'OAuth Twitch" -#: authentik/sources/oauth/models.py:126 +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Sources" msgstr "Sources d'OAuth Twitch" -#: authentik/sources/oauth/models.py:134 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Source" msgstr "Source d'OAuth Mailcow" -#: authentik/sources/oauth/models.py:135 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Sources" msgstr "Sources d'OAuth Mailcow" -#: authentik/sources/oauth/models.py:143 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Source" msgstr "Source d'OAuth Twitter" -#: authentik/sources/oauth/models.py:144 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Sources" msgstr "Sources d'OAuth Twitter" -#: authentik/sources/oauth/models.py:152 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Source" msgstr "Source d'OAuth Facebook" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Sources" msgstr "Sources d'OAuth Facebook" -#: authentik/sources/oauth/models.py:161 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Source" msgstr "Source d'OAuth Discord" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Sources" msgstr "Sources d'OAuth Discord" -#: authentik/sources/oauth/models.py:170 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Source" msgstr "Source d'OAuth Patreon" -#: authentik/sources/oauth/models.py:171 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Sources" msgstr "Sources d'OAuth Patreon" -#: authentik/sources/oauth/models.py:179 +#: authentik/sources/oauth/models.py msgid "Google OAuth Source" msgstr "Source d'OAuth Google" -#: authentik/sources/oauth/models.py:180 +#: authentik/sources/oauth/models.py msgid "Google OAuth Sources" msgstr "Source d'OAuth Google" -#: authentik/sources/oauth/models.py:188 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Source" msgstr "Source d'OAuth Azure AD" -#: authentik/sources/oauth/models.py:189 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Sources" msgstr "Source d'OAuth Azure AD" -#: authentik/sources/oauth/models.py:197 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Source" msgstr "Source d'OAuth OpenID" -#: authentik/sources/oauth/models.py:198 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Sources" msgstr "Sources d'OAuth OpenID" -#: authentik/sources/oauth/models.py:206 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Source" msgstr "Source d'OAuth Apple" -#: authentik/sources/oauth/models.py:207 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Sources" msgstr "Sources d'OAuth Apple" -#: authentik/sources/oauth/models.py:215 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Source" msgstr "Source d'OAuth Okta" -#: authentik/sources/oauth/models.py:216 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Sources" msgstr "Sources d'OAuth Okta" -#: authentik/sources/oauth/models.py:224 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Source" msgstr "Source d'OAuth Reddit" -#: authentik/sources/oauth/models.py:225 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Sources" msgstr "Sources d'OAuth Reddit" -#: authentik/sources/oauth/models.py:247 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connection" msgstr "Connexion de l'utilisateur à la source OAuth" -#: authentik/sources/oauth/models.py:248 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connections" msgstr "Connexion de l'utilisateur aux sources OAuth" -#: authentik/sources/oauth/views/callback.py:100 -#, python-format -msgid "Authentication failed: %(reason)s" -msgstr "Échec d'authentification : %(reason)s" +#: authentik/sources/oauth/views/callback.py +#, python-brace-format +msgid "Authentication failed: {reason}" +msgstr "Échec d'authentification : {reason}" -#: authentik/sources/plex/models.py:37 +#: authentik/sources/plex/models.py msgid "Client identifier used to talk to Plex." msgstr "Identificateur client utilisé pour communiquer avec Plex." -#: authentik/sources/plex/models.py:44 +#: authentik/sources/plex/models.py msgid "" "Which servers a user has to be a member of to be granted access. Empty list " "allows every server." @@ -2128,72 +2216,72 @@ msgstr "" "De quels serveurs un utilisateur doit être membre afin d'être autorisé. Une " "liste vide autorise tous les serveurs." -#: authentik/sources/plex/models.py:50 +#: authentik/sources/plex/models.py msgid "Allow friends to authenticate, even if you don't share a server." msgstr "" "Autoriser les amis à se connecter, même si vous ne partagez pas de serveur." -#: authentik/sources/plex/models.py:52 +#: authentik/sources/plex/models.py msgid "Plex token used to check friends" msgstr "Jeton plex utilisé pour vérifier les amis" -#: authentik/sources/plex/models.py:95 +#: authentik/sources/plex/models.py msgid "Plex Source" msgstr "Source Plex" -#: authentik/sources/plex/models.py:96 +#: authentik/sources/plex/models.py msgid "Plex Sources" msgstr "Sources Plex" -#: authentik/sources/plex/models.py:112 +#: authentik/sources/plex/models.py msgid "User Plex Source Connection" msgstr "Connexion de l'utilisateur à la source Plex" -#: authentik/sources/plex/models.py:113 +#: authentik/sources/plex/models.py msgid "User Plex Source Connections" msgstr "Connexion de l'utilisateur aux sources Plex" -#: authentik/sources/saml/models.py:40 +#: authentik/sources/saml/models.py msgid "Redirect Binding" msgstr "Liaison de Redirection" -#: authentik/sources/saml/models.py:41 +#: authentik/sources/saml/models.py msgid "POST Binding" msgstr "Liaison POST" -#: authentik/sources/saml/models.py:42 +#: authentik/sources/saml/models.py msgid "POST Binding with auto-confirmation" msgstr "Liaison POST avec auto confirmation" -#: authentik/sources/saml/models.py:70 +#: authentik/sources/saml/models.py msgid "Flow used before authentication." msgstr "Flux à utiliser avant authentification." -#: authentik/sources/saml/models.py:77 +#: authentik/sources/saml/models.py msgid "Issuer" msgstr "Émetteur" -#: authentik/sources/saml/models.py:78 +#: authentik/sources/saml/models.py msgid "Also known as Entity ID. Defaults the Metadata URL." msgstr "Aussi appelé Entity ID. URL de métadonnée par défaut." -#: authentik/sources/saml/models.py:82 +#: authentik/sources/saml/models.py msgid "SSO URL" msgstr "URL SSO" -#: authentik/sources/saml/models.py:83 +#: authentik/sources/saml/models.py msgid "URL that the initial Login request is sent to." msgstr "URL de destination de la requête initiale de login." -#: authentik/sources/saml/models.py:89 +#: authentik/sources/saml/models.py msgid "SLO URL" msgstr "URL SLO" -#: authentik/sources/saml/models.py:90 +#: authentik/sources/saml/models.py msgid "Optional URL if your IDP supports Single-Logout." msgstr "URL optionnel si votre IDP supporte la déconnection unique." -#: authentik/sources/saml/models.py:96 +#: authentik/sources/saml/models.py msgid "" "Allows authentication flows initiated by the IdP. This can be a security " "risk, as no validation of the request ID is done." @@ -2202,7 +2290,7 @@ msgstr "" " un risque de sécurité, aucune validation de l'ID de la requête n'est " "effectuée." -#: authentik/sources/saml/models.py:104 +#: authentik/sources/saml/models.py msgid "" "NameID Policy sent to the IdP. Can be unset, in which case no Policy is " "sent." @@ -2210,11 +2298,11 @@ msgstr "" "Politique NameID envoyée au fournisseur d'identité. Peut être vide, auquel " "cas aucune politique n'est envoyée." -#: authentik/sources/saml/models.py:115 +#: authentik/sources/saml/models.py msgid "Delete temporary users after" msgstr "Supprimer les utilisateurs temporaires après" -#: authentik/sources/saml/models.py:118 +#: authentik/sources/saml/models.py msgid "" "Time offset when temporary users should be deleted. This only applies if " "your IDP uses the NameID Format 'transient', and the user doesn't log out " @@ -2225,46 +2313,54 @@ msgstr "" "transitoire ('transient') et que l'utilisateur ne se déconnecte pas " "manuellement. (Format : heures=1;minutes=2;secondes=3)." -#: authentik/sources/saml/models.py:142 +#: authentik/sources/saml/models.py msgid "" "Keypair used to sign outgoing Responses going to the Identity Provider." msgstr "" "Paire de clés utilisées pour signer les réponses sortantes allant vers le " "fournisseur d'identité." -#: authentik/sources/saml/models.py:226 +#: authentik/sources/saml/models.py msgid "SAML Source" msgstr "Source SAML" -#: authentik/sources/saml/models.py:227 +#: authentik/sources/saml/models.py msgid "SAML Sources" msgstr "Sources SAML" -#: authentik/sources/saml/models.py:242 +#: authentik/sources/saml/models.py msgid "User SAML Source Connection" msgstr "Connexion de l'utilisateur à la source SAML" -#: authentik/sources/saml/models.py:243 +#: authentik/sources/saml/models.py msgid "User SAML Source Connections" msgstr "Connexion de l'utilisateur aux sources SAML" -#: authentik/stages/authenticator_duo/models.py:79 +#: authentik/sources/scim/models.py +msgid "SCIM Source" +msgstr "Source SCIM" + +#: authentik/sources/scim/models.py +msgid "SCIM Sources" +msgstr "Sources SCIM" + +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stage" msgstr "Étape de configuration du Duo Authenticator" -#: authentik/stages/authenticator_duo/models.py:80 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stages" msgstr "Étapes de configuration du Duo Authenticator" -#: authentik/stages/authenticator_duo/models.py:103 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Device" msgstr "Appareil Duo" -#: authentik/stages/authenticator_duo/models.py:104 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Devices" msgstr "Appareils Duo" -#: authentik/stages/authenticator_sms/models.py:57 +#: authentik/stages/authenticator_sms/models.py msgid "" "When enabled, the Phone number is only used during enrollment to verify the " "users authenticity. Only a hash of the phone number is saved to ensure it is" @@ -2275,117 +2371,128 @@ msgstr "" "téléphone est enregistré pour assurer qu'il ne sera pas réutilisé dans le " "futur." -#: authentik/stages/authenticator_sms/models.py:68 +#: authentik/stages/authenticator_sms/models.py msgid "Optionally modify the payload being sent to custom providers." msgstr "" "Éventuellement modifier le contenu envoyé aux fournisseurs personnalisés." -#: authentik/stages/authenticator_sms/models.py:81 -#, python-format -msgid "Use this code to authenticate in authentik: %(token)s" -msgstr "Utilisez ce code pour s'authentifier à authentik : %(token)s" +#: authentik/stages/authenticator_sms/models.py +#, python-brace-format +msgid "Use this code to authenticate in authentik: {token}" +msgstr "Utilisez ce code pour s'authentifier à authentik : {token}" -#: authentik/stages/authenticator_sms/models.py:180 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stage" msgstr "Étape de configuration de l'authentificateur SMS" -#: authentik/stages/authenticator_sms/models.py:181 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stages" msgstr "Étapes de configuration de l'authentificateur SMS" -#: authentik/stages/authenticator_sms/models.py:226 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Device" msgstr "Appareil SMS" -#: authentik/stages/authenticator_sms/models.py:227 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Devices" msgstr "Appareils SMS" -#: authentik/stages/authenticator_sms/stage.py:57 -#: authentik/stages/authenticator_totp/stage.py:41 -#: authentik/stages/authenticator_totp/stage.py:44 +#: authentik/stages/authenticator_sms/stage.py +#: authentik/stages/authenticator_totp/stage.py msgid "Code does not match" msgstr "Le Code ne correspond pas" -#: authentik/stages/authenticator_sms/stage.py:73 +#: authentik/stages/authenticator_sms/stage.py msgid "Invalid phone number" msgstr "Numéro de téléphone invalide" -#: authentik/stages/authenticator_static/models.py:52 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stage" msgstr "Étape de configuration de l'authentificateur statique" -#: authentik/stages/authenticator_static/models.py:53 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stages" msgstr "Étapes de configuration de l'authentificateur statique" -#: authentik/stages/authenticator_static/models.py:98 +#: authentik/stages/authenticator_static/models.py msgid "Static Device" msgstr "Équipement statique" -#: authentik/stages/authenticator_static/models.py:99 +#: authentik/stages/authenticator_static/models.py msgid "Static Devices" msgstr "Équipements statiques" -#: authentik/stages/authenticator_static/models.py:129 +#: authentik/stages/authenticator_static/models.py msgid "Static Token" msgstr "Jeton statique" -#: authentik/stages/authenticator_static/models.py:130 +#: authentik/stages/authenticator_static/models.py msgid "Static Tokens" msgstr "Jetons statiques" -#: authentik/stages/authenticator_totp/models.py:25 +#: authentik/stages/authenticator_totp/models.py msgid "6 digits, widely compatible" msgstr "6 chiffres, compatibilité large" -#: authentik/stages/authenticator_totp/models.py:26 +#: authentik/stages/authenticator_totp/models.py msgid "8 digits, not compatible with apps like Google Authenticator" msgstr "" "8 chiffres, incompatible avec certaines applications telles que Google " "Authenticator" -#: authentik/stages/authenticator_totp/models.py:62 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stage" msgstr "Étape de configuration de l'authentificateur TOTP" -#: authentik/stages/authenticator_totp/models.py:63 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stages" msgstr "Étapes de configuration de l'authentificateur TOTP" -#: authentik/stages/authenticator_totp/models.py:244 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Device" msgstr "Équipement TOTP" -#: authentik/stages/authenticator_totp/models.py:245 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Devices" msgstr "Équipements TOTP" -#: authentik/stages/authenticator_validate/challenge.py:123 -msgid "Invalid Token" -msgstr "Jeton Invalide" +#: authentik/stages/authenticator_validate/challenge.py +msgid "" +"Invalid Token. Please ensure the time on your device is accurate and try " +"again." +msgstr "" +"Jeton invalide. Merci de vous assurer que le temps défini sur votre appareil" +" est juste et de réessayer," -#: authentik/stages/authenticator_validate/models.py:18 +#: authentik/stages/authenticator_validate/challenge.py +#: authentik/stages/authenticator_webauthn/stage.py +#, python-brace-format +msgid "Invalid device type. Contact your {brand} administrator for help." +msgstr "" +"Type d'appareil invalide. Merci de contacter l'administrateur de {brand} " +"pour de l'assistance." + +#: authentik/stages/authenticator_validate/models.py msgid "Static" msgstr "Statique" -#: authentik/stages/authenticator_validate/models.py:19 +#: authentik/stages/authenticator_validate/models.py msgid "TOTP" msgstr "TOTP" -#: authentik/stages/authenticator_validate/models.py:20 +#: authentik/stages/authenticator_validate/models.py msgid "WebAuthn" msgstr "WebAuthn" -#: authentik/stages/authenticator_validate/models.py:21 +#: authentik/stages/authenticator_validate/models.py msgid "Duo" msgstr "Duo" -#: authentik/stages/authenticator_validate/models.py:22 +#: authentik/stages/authenticator_validate/models.py msgid "SMS" msgstr "SMS" -#: authentik/stages/authenticator_validate/models.py:49 +#: authentik/stages/authenticator_validate/models.py msgid "" "Stages used to configure Authenticator when user doesn't have any compatible" " devices. After this configuration Stage passes, the user is not prompted " @@ -2395,11 +2502,11 @@ msgstr "" "n'a pas d'appareil compatible. Une fois cette étape franchie, l'utilisateur " "ne sera plus sollicité." -#: authentik/stages/authenticator_validate/models.py:56 +#: authentik/stages/authenticator_validate/models.py msgid "Device classes which can be used to authenticate" msgstr "Classes d'appareils pouvant être utilisées pour se connecter" -#: authentik/stages/authenticator_validate/models.py:64 +#: authentik/stages/authenticator_validate/models.py msgid "" "If any of the user's device has been used within this threshold, this stage " "will be skipped" @@ -2407,97 +2514,109 @@ msgstr "" "Si l'un des appareils de l'utilisateur a été utilisé au sein de ce seuil, " "cette étape sera sautée" -#: authentik/stages/authenticator_validate/models.py:70 +#: authentik/stages/authenticator_validate/models.py msgid "Enforce user verification for WebAuthn devices." msgstr "Imposer la vérification de l'utilisateur pour les appareils WebAuthn." -#: authentik/stages/authenticator_validate/models.py:92 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stage" msgstr "Étape de validation de l'authentificateur" -#: authentik/stages/authenticator_validate/models.py:93 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stages" msgstr "Étapes de validation de l'authentificateur" -#: authentik/stages/authenticator_webauthn/models.py:112 +#: authentik/stages/authenticator_validate/stage.py +msgid "No (allowed) MFA authenticator configured." +msgstr "Pas d'authentificateur MFA (autorisé) configuré." + +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stage" msgstr "Étape de validation de l'authentificateur WebAuthn" -#: authentik/stages/authenticator_webauthn/models.py:113 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stages" msgstr "Étapes de validation de l'authentificateur WebAuthn" -#: authentik/stages/authenticator_webauthn/models.py:151 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Device" msgstr "Appareil WebAuthn" -#: authentik/stages/authenticator_webauthn/models.py:152 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Devices" msgstr "Équipements WebAuthn" -#: authentik/stages/captcha/models.py:14 +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device type" +msgstr "Type d'appareil WebAuthn" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device types" +msgstr "Types d'appareil WebAuthn" + +#: authentik/stages/captcha/models.py msgid "Public key, acquired your captcha Provider." msgstr "Clé publique, acquise auprès de votre fournisseur captcha." -#: authentik/stages/captcha/models.py:15 +#: authentik/stages/captcha/models.py msgid "Private key, acquired your captcha Provider." msgstr "Clé privée, acquise auprès de votre fournisseur captcha." -#: authentik/stages/captcha/models.py:37 +#: authentik/stages/captcha/models.py msgid "Captcha Stage" msgstr "Étape de Captcha" -#: authentik/stages/captcha/models.py:38 +#: authentik/stages/captcha/models.py msgid "Captcha Stages" msgstr "Étapes de Captcha" -#: authentik/stages/consent/models.py:30 +#: authentik/stages/consent/models.py msgid "" "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "" "Durée d'expiration du consentement (Format : hours=1;minutes=2;seconds=3)." -#: authentik/stages/consent/models.py:50 +#: authentik/stages/consent/models.py msgid "Consent Stage" msgstr "Étape de Consentement" -#: authentik/stages/consent/models.py:51 +#: authentik/stages/consent/models.py msgid "Consent Stages" msgstr "Étapes de Consentement" -#: authentik/stages/consent/models.py:72 +#: authentik/stages/consent/models.py msgid "User Consent" msgstr "Consentement Utilisateur" -#: authentik/stages/consent/models.py:73 +#: authentik/stages/consent/models.py msgid "User Consents" msgstr "Consentements Utilisateur" -#: authentik/stages/deny/models.py:32 +#: authentik/stages/deny/models.py msgid "Deny Stage" msgstr "Étape de Refus" -#: authentik/stages/deny/models.py:33 +#: authentik/stages/deny/models.py msgid "Deny Stages" msgstr "Étapes de Refus" -#: authentik/stages/dummy/models.py:34 +#: authentik/stages/dummy/models.py msgid "Dummy Stage" msgstr "Étape factice" -#: authentik/stages/dummy/models.py:35 +#: authentik/stages/dummy/models.py msgid "Dummy Stages" msgstr "Étapes factices" -#: authentik/stages/email/models.py:26 +#: authentik/stages/email/models.py msgid "Password Reset" msgstr "Réinitialiser le Mot de Passe" -#: authentik/stages/email/models.py:30 +#: authentik/stages/email/models.py msgid "Account Confirmation" msgstr "Confirmation du Compte" -#: authentik/stages/email/models.py:59 +#: authentik/stages/email/models.py msgid "" "When enabled, global Email connection settings will be used and connection " "settings below will be ignored." @@ -2505,48 +2624,48 @@ msgstr "" "Si activé, les paramètres globaux de connexion courriel seront utilisés et " "les paramètres de connexion ci-dessous seront ignorés." -#: authentik/stages/email/models.py:74 +#: authentik/stages/email/models.py msgid "Activate users upon completion of stage." msgstr "Activer les utilisateurs à la complétion de l'étape." -#: authentik/stages/email/models.py:78 +#: authentik/stages/email/models.py msgid "Time in minutes the token sent is valid." msgstr "Temps en minutes durant lequel le jeton envoyé est valide." -#: authentik/stages/email/models.py:132 +#: authentik/stages/email/models.py msgid "Email Stage" msgstr "Étape Email" -#: authentik/stages/email/models.py:133 +#: authentik/stages/email/models.py msgid "Email Stages" msgstr "Étape Email" -#: authentik/stages/email/stage.py:126 +#: authentik/stages/email/stage.py msgid "Exception occurred while rendering E-mail template" msgstr "Une erreur s'est produite lors de la modélisation du couriel" -#: authentik/stages/email/stage.py:140 +#: authentik/stages/email/stage.py msgid "Successfully verified Email." msgstr "Email vérifié avec succès." -#: authentik/stages/email/stage.py:147 authentik/stages/email/stage.py:173 +#: authentik/stages/email/stage.py msgid "No pending user." msgstr "Pas d'utilisateurs en attente." -#: authentik/stages/email/stage.py:163 +#: authentik/stages/email/stage.py msgid "Email sent." msgstr "Email envoyé." -#: authentik/stages/email/stage.py:176 +#: authentik/stages/email/stage.py msgid "Email Successfully sent." msgstr "Couriel envoyé avec succès." -#: authentik/stages/email/templates/email/account_confirmation.html:10 -#: authentik/stages/email/templates/email/account_confirmation.txt:1 +#: authentik/stages/email/templates/email/account_confirmation.html +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "Welcome!" msgstr "Bienvenue !" -#: authentik/stages/email/templates/email/account_confirmation.html:19 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just press the button below." @@ -2554,11 +2673,11 @@ msgstr "" "Nous sommes ravis que vous puissiez commencer. Tout d'abord, vous devez " "confirmer votre compte. Il vous suffit d'appuyer sur le bouton ci-dessous." -#: authentik/stages/email/templates/email/account_confirmation.html:24 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "Confirm Account" msgstr "Confirmer le Compte" -#: authentik/stages/email/templates/email/account_confirmation.html:36 +#: authentik/stages/email/templates/email/account_confirmation.html #, python-format msgid "" "\n" @@ -2569,7 +2688,7 @@ msgstr "" " Si cela ne fonctionne pas, copier et coller ce lien dans votre navigateur : %(url)s\n" " " -#: authentik/stages/email/templates/email/account_confirmation.txt:3 +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just open the link below." @@ -2577,7 +2696,7 @@ msgstr "" "Nous sommes ravis que vous puissiez commencer. Tout d'abord, vous devez " "confirmer votre compte. Il vous suffit d'ouvrir le lien ci-dessous." -#: authentik/stages/email/templates/email/event_notification.html:46 +#: authentik/stages/email/templates/email/event_notification.html #, python-format msgid "" "\n" @@ -2588,19 +2707,19 @@ msgstr "" " Cet email a été envoyé depuis le transport de notification %(name)s.\n" " " -#: authentik/stages/email/templates/email/event_notification.txt:1 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Dear authentik user," msgstr "Cher utilisateur d'authentik." -#: authentik/stages/email/templates/email/event_notification.txt:3 +#: authentik/stages/email/templates/email/event_notification.txt msgid "The following notification was created:" msgstr "La notification suivante a été créée :" -#: authentik/stages/email/templates/email/event_notification.txt:8 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Additional attributes:" msgstr "Attributs additionnels" -#: authentik/stages/email/templates/email/event_notification.txt:13 +#: authentik/stages/email/templates/email/event_notification.txt #, python-format msgid "" "\n" @@ -2609,7 +2728,7 @@ msgstr "" "\n" "Cet email a été envoyé depuis le transport de notification %(name)s.\n" -#: authentik/stages/email/templates/email/password_reset.html:10 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2620,7 +2739,7 @@ msgstr "" " Salut %(username)s,\n" " " -#: authentik/stages/email/templates/email/password_reset.html:21 +#: authentik/stages/email/templates/email/password_reset.html msgid "" "\n" " You recently requested to change your password for your authentik account. Use the button below to set a new password.\n" @@ -2630,7 +2749,7 @@ msgstr "" " Vous avez récemment demandé à changer le mot de passe de votre compte authentik. Utilisez le bouton ci-dessous pour définir un nouveau mot de passe.\n" " " -#: authentik/stages/email/templates/email/password_reset.html:39 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2641,12 +2760,12 @@ msgstr "" " Si vous n'avez pas requis de changement de mot de passe, veuillez ignorer cet e-mail. Le lien ci-dessus est valide pendant %(expires)s.\n" " " -#: authentik/stages/email/templates/email/password_reset.txt:1 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "Hi %(username)s," msgstr "Bonjour %(username)s," -#: authentik/stages/email/templates/email/password_reset.txt:3 +#: authentik/stages/email/templates/email/password_reset.txt msgid "" "\n" "You recently requested to change your password for your authentik account. Use the link below to set a new password.\n" @@ -2654,7 +2773,7 @@ msgstr "" "\n" "Vous avez récemment demandé à changer le mot de passe de votre compte authentik. Utilisez le lien ci-dessous pour définir un nouveau mot de passe.\n" -#: authentik/stages/email/templates/email/password_reset.txt:7 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "" "\n" @@ -2663,11 +2782,11 @@ msgstr "" "\n" "Si vous n'avez pas requis de changement de mot de passe, veuillez ignorer cet e-mail. Le lien ci-dessus est valide pendant %(expires)s.\n" -#: authentik/stages/email/templates/email/setup.html:9 +#: authentik/stages/email/templates/email/setup.html msgid "authentik Test-Email" msgstr "Email de Test d'authentik" -#: authentik/stages/email/templates/email/setup.html:17 +#: authentik/stages/email/templates/email/setup.html msgid "" "\n" " This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2676,7 +2795,7 @@ msgstr "" "\n" "Ceci est un email de test pour vous informer que vous avez configuré les emails d'authentik avec succès." -#: authentik/stages/email/templates/email/setup.txt:2 +#: authentik/stages/email/templates/email/setup.txt msgid "" "\n" "This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2684,13 +2803,13 @@ msgstr "" "\n" "Ceci est un email de test pour vous informer que vous avez configuré les emails d'authentik avec succès.\n" -#: authentik/stages/identification/api.py:20 +#: authentik/stages/identification/api.py msgid "When no user fields are selected, at least one source must be selected" msgstr "" "Quand aucun champ utilisateur n'est sélectionné, au moins une source doit " "être sélectionnée." -#: authentik/stages/identification/models.py:29 +#: authentik/stages/identification/models.py msgid "" "Fields of the user object to match against. (Hold shift to select multiple " "options)" @@ -2698,13 +2817,13 @@ msgstr "" "Champs de l'objet utilisateur contre lesquels faire correspondre. (Maintenir" " Majuscule pour sélectionner plusieurs options)" -#: authentik/stages/identification/models.py:47 +#: authentik/stages/identification/models.py msgid "When enabled, user fields are matched regardless of their casing." msgstr "" "Si activé, les champs de l'utilisateur sont mis en correspondance en " "ignorant leur casse." -#: authentik/stages/identification/models.py:52 +#: authentik/stages/identification/models.py msgid "" "When a valid username/email has been entered, and this option is enabled, " "the user's username and avatar will be shown. Otherwise, the text that the " @@ -2714,7 +2833,7 @@ msgstr "" "est active, le nom d'utilisateur et l'avatar de l'utilisateur seront " "affichés. Sinon, le texte que l'utilisateur a saisi sera affiché." -#: authentik/stages/identification/models.py:60 +#: authentik/stages/identification/models.py msgid "" "When enabled, the stage will succeed and continue even when incorrect user " "info is entered." @@ -2722,40 +2841,40 @@ msgstr "" "Lorsqu'activé, l'étape réussira et continuera même lorsque les informations " "utilisateurs entrées sont invalides." -#: authentik/stages/identification/models.py:72 +#: authentik/stages/identification/models.py msgid "Optional enrollment flow, which is linked at the bottom of the page." msgstr "Flux d'inscription facultatif, qui sera accessible en bas de page." -#: authentik/stages/identification/models.py:81 +#: authentik/stages/identification/models.py msgid "Optional recovery flow, which is linked at the bottom of the page." msgstr "Flux de récupération facultatif, qui sera accessible en bas de page." -#: authentik/stages/identification/models.py:90 +#: authentik/stages/identification/models.py msgid "Optional passwordless flow, which is linked at the bottom of the page." msgstr "" "Flux sans mot de passe facultatif, qui sera accessible en bas de page." -#: authentik/stages/identification/models.py:94 +#: authentik/stages/identification/models.py msgid "Specify which sources should be shown." msgstr "Spécifie quelles sources doivent être affichées." -#: authentik/stages/identification/models.py:115 +#: authentik/stages/identification/models.py msgid "Identification Stage" msgstr "Étape d'identification" -#: authentik/stages/identification/models.py:116 +#: authentik/stages/identification/models.py msgid "Identification Stages" msgstr "Étapes d'identification" -#: authentik/stages/identification/stage.py:188 +#: authentik/stages/identification/stage.py msgid "Log in" msgstr "Se connecter" -#: authentik/stages/identification/stage.py:189 +#: authentik/stages/identification/stage.py msgid "Continue" msgstr "Continuer" -#: authentik/stages/invitation/models.py:21 +#: authentik/stages/invitation/models.py msgid "" "If this flag is set, this Stage will jump to the next Stage when no " "Invitation is given. By default this Stage will cancel the Flow when no " @@ -2764,57 +2883,57 @@ msgstr "" "Si activé, cette étape passera à l'étape suivante si aucune invitation n'est" " donnée. Par défaut, cette étape annule le flux en l'absence d'invitation." -#: authentik/stages/invitation/models.py:44 +#: authentik/stages/invitation/models.py msgid "Invitation Stage" msgstr "Étape d'invitation" -#: authentik/stages/invitation/models.py:45 +#: authentik/stages/invitation/models.py msgid "Invitation Stages" msgstr "Étapes d'invitation" -#: authentik/stages/invitation/models.py:60 +#: authentik/stages/invitation/models.py msgid "When set, only the configured flow can use this invitation." msgstr "Si activé, seul le flux configuré peut utilisé cette invitation." -#: authentik/stages/invitation/models.py:64 +#: authentik/stages/invitation/models.py msgid "When enabled, the invitation will be deleted after usage." msgstr "Si activée, l'invitation sera supprimée après utilisation." -#: authentik/stages/invitation/models.py:71 +#: authentik/stages/invitation/models.py msgid "Optional fixed data to enforce on user enrollment." msgstr "" "Données statiques optionnelles à forcer lors de l'inscription des " "utilisateurs." -#: authentik/stages/invitation/models.py:84 +#: authentik/stages/invitation/models.py msgid "Invitation" msgstr "Invitation" -#: authentik/stages/invitation/models.py:85 +#: authentik/stages/invitation/models.py msgid "Invitations" msgstr "Invitations" -#: authentik/stages/invitation/stage.py:62 +#: authentik/stages/invitation/stage.py msgid "Invalid invite/invite not found" msgstr "Invitation invalide/invitation introuvable" -#: authentik/stages/password/models.py:20 +#: authentik/stages/password/models.py msgid "User database + standard password" msgstr "Base de données utilisateurs + mots de passe standards" -#: authentik/stages/password/models.py:24 +#: authentik/stages/password/models.py msgid "User database + app passwords" msgstr "Base de données utilisateurs + mots de passes applicatifs" -#: authentik/stages/password/models.py:28 +#: authentik/stages/password/models.py msgid "User database + LDAP password" msgstr "Base de données utilisateurs + mot de passe LDAP" -#: authentik/stages/password/models.py:38 +#: authentik/stages/password/models.py msgid "Selection of backends to test the password against." msgstr "Sélection de backends pour tester le mot de passe." -#: authentik/stages/password/models.py:43 +#: authentik/stages/password/models.py msgid "" "How many attempts a user has before the flow is canceled. To lock the user " "out, use a reputation policy and a user_write stage." @@ -2823,37 +2942,37 @@ msgstr "" "annulé. Pour verrouiller l'utilisateur, utilisez une politique de réputation" " et une étape user_write." -#: authentik/stages/password/models.py:75 +#: authentik/stages/password/models.py msgid "Password Stage" msgstr "Étape de mot de passe" -#: authentik/stages/password/models.py:76 +#: authentik/stages/password/models.py msgid "Password Stages" msgstr "Étapes de mot de passe" -#: authentik/stages/password/stage.py:124 +#: authentik/stages/password/stage.py msgid "Invalid password" msgstr "Mot de passe invalide" -#: authentik/stages/prompt/models.py:43 +#: authentik/stages/prompt/models.py msgid "Text: Simple Text input" msgstr "Texte : simple champ texte" -#: authentik/stages/prompt/models.py:45 +#: authentik/stages/prompt/models.py msgid "Text area: Multiline Text Input." msgstr "Champ texte : saisie de texte multiligne" -#: authentik/stages/prompt/models.py:48 +#: authentik/stages/prompt/models.py msgid "Text (read-only): Simple Text input, but cannot be edited." msgstr "Texte (lecture seule): Texte Simple, mais ne peut être édité." -#: authentik/stages/prompt/models.py:52 +#: authentik/stages/prompt/models.py msgid "Text area (read-only): Multiline Text input, but cannot be edited." msgstr "" "Champ texte (lecture seule) : saise de texte multiligne, mais ne peut pas " "être éditée." -#: authentik/stages/prompt/models.py:58 +#: authentik/stages/prompt/models.py msgid "" "Username: Same as Text input, but checks for and prevents duplicate " "usernames." @@ -2861,11 +2980,11 @@ msgstr "" "Nom d'utilisateur : Identique à la saisie de texte, mais vérifie et empêche " "les noms d'utilisateur en double." -#: authentik/stages/prompt/models.py:60 +#: authentik/stages/prompt/models.py msgid "Email: Text field with Email type." msgstr "Courriel : champ texte de type email" -#: authentik/stages/prompt/models.py:64 +#: authentik/stages/prompt/models.py msgid "" "Password: Masked input, multiple inputs of this type on the same prompt need" " to be identical." @@ -2873,15 +2992,15 @@ msgstr "" "Mot de passe : saisie de texte cachée, plusieurs champ de ce type sur la " "même invite doivent être identiques." -#: authentik/stages/prompt/models.py:71 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a group of radio buttons." msgstr "Champ à choix fixes affiché comme un groupe de boutons radio." -#: authentik/stages/prompt/models.py:73 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a dropdown." msgstr "Champ à choix fixes affiché comme une liste déroulante." -#: authentik/stages/prompt/models.py:80 +#: authentik/stages/prompt/models.py msgid "" "File: File upload for arbitrary files. File content will be available in " "flow context as data-URI" @@ -2889,29 +3008,29 @@ msgstr "" "Fichier : Upload de fichier pour de fichiers arbitraires. Le contenu du " "fichier sera disponible dans le contexte du flux comme un data-URI" -#: authentik/stages/prompt/models.py:85 +#: authentik/stages/prompt/models.py msgid "Separator: Static Separator Line" msgstr "Séparateur : Ligne de séparation statique" -#: authentik/stages/prompt/models.py:86 +#: authentik/stages/prompt/models.py msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "" "Caché : champ caché, peut être utilisé pour insérer des données dans le " "formulaire." -#: authentik/stages/prompt/models.py:87 +#: authentik/stages/prompt/models.py msgid "Static: Static value, displayed as-is." msgstr "Statique : valeur statique, affichée comme telle." -#: authentik/stages/prompt/models.py:89 +#: authentik/stages/prompt/models.py msgid "authentik: Selection of locales authentik supports" msgstr "authentik : sélection des locales prises en charges par authentik" -#: authentik/stages/prompt/models.py:116 +#: authentik/stages/prompt/models.py msgid "Name of the form field, also used to store the value" msgstr "Nom du champ de formulaire, aussi utilisé pour enregistrer la valeur" -#: authentik/stages/prompt/models.py:124 +#: authentik/stages/prompt/models.py msgid "" "Optionally provide a short hint that describes the expected input value. " "When creating a fixed choice field, enable interpreting as expression and " @@ -2921,7 +3040,7 @@ msgstr "" " Lors de la création d'un champ à choix fixes, activer l'interprétation en " "tant qu'expression et renvoyer une liste des choix." -#: authentik/stages/prompt/models.py:132 +#: authentik/stages/prompt/models.py msgid "" "Optionally pre-fill the input with an initial value. When creating a fixed " "choice field, enable interpreting as expression and return a list to return " @@ -2931,53 +3050,53 @@ msgstr "" "création d'un champ à choix fixes, activer l'interprétation en tant " "qu'expression et renvoyer une liste des choix par défaut." -#: authentik/stages/prompt/models.py:321 +#: authentik/stages/prompt/models.py msgid "Prompt" msgstr "Invite" -#: authentik/stages/prompt/models.py:322 +#: authentik/stages/prompt/models.py msgid "Prompts" msgstr "Invites" -#: authentik/stages/prompt/models.py:349 +#: authentik/stages/prompt/models.py msgid "Prompt Stage" msgstr "Étape invite" -#: authentik/stages/prompt/models.py:350 +#: authentik/stages/prompt/models.py msgid "Prompt Stages" msgstr "Étapes invite" -#: authentik/stages/prompt/stage.py:108 +#: authentik/stages/prompt/stage.py msgid "Passwords don't match." msgstr "Les mots de passe ne correspondent pas." -#: authentik/stages/user_delete/models.py:31 +#: authentik/stages/user_delete/models.py msgid "User Delete Stage" msgstr "Étape de suppression utilisateur" -#: authentik/stages/user_delete/models.py:32 +#: authentik/stages/user_delete/models.py msgid "User Delete Stages" msgstr "Étapes de suppression utilisateur" -#: authentik/stages/user_delete/stage.py:18 +#: authentik/stages/user_delete/stage.py msgid "No Pending User." msgstr "Aucun utilisateur en attente." -#: authentik/stages/user_login/models.py:47 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured network" msgstr "Sessions liées créées par cette étape au réseau configuré" -#: authentik/stages/user_login/models.py:52 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured GeoIP location" msgstr "" "Sessions liées créées par cette étape à la localisation GeoIP configurée" -#: authentik/stages/user_login/models.py:55 +#: authentik/stages/user_login/models.py msgid "Terminate all other sessions of the user logging in." msgstr "" "Mettre fin à toutes les autres sessions de l'utilisateur qui se connecte." -#: authentik/stages/user_login/models.py:61 +#: authentik/stages/user_login/models.py msgid "" "Offset the session will be extended by when the user picks the remember me " "option. Default of 0 means that the remember me option will not be shown. " @@ -2988,63 +3107,62 @@ msgstr "" "souvenir de moi ne sera pas proposée. (Format: " "hours=-1;minutes=-2;seconds=-3)" -#: authentik/stages/user_login/models.py:84 +#: authentik/stages/user_login/models.py msgid "User Login Stage" msgstr "Étape de connexion utlisateur" -#: authentik/stages/user_login/models.py:85 +#: authentik/stages/user_login/models.py msgid "User Login Stages" msgstr "Étapes de connexion utilisateur" -#: authentik/stages/user_login/stage.py:85 +#: authentik/stages/user_login/stage.py msgid "No Pending user to login." msgstr "Pas d'utilisateurs en attente à connecter." -#: authentik/stages/user_login/stage.py:112 +#: authentik/stages/user_login/stage.py msgid "Successfully logged in!" msgstr "Connexion réussie !" -#: authentik/stages/user_logout/models.py:30 +#: authentik/stages/user_logout/models.py msgid "User Logout Stage" msgstr "Étape de déconnexion utlisateur" -#: authentik/stages/user_logout/models.py:31 +#: authentik/stages/user_logout/models.py msgid "User Logout Stages" msgstr "Étapes de déconnexion d'utilisateur" -#: authentik/stages/user_write/models.py:31 +#: authentik/stages/user_write/models.py msgid "When set, newly created users are inactive and cannot login." msgstr "" "Si défini, les nouveaux utilisateurs seront inactifs et ne pourront pas se " "connecter." -#: authentik/stages/user_write/models.py:39 +#: authentik/stages/user_write/models.py msgid "Optionally add newly created users to this group." msgstr "Optionnel, ajoute les nouveaux utilisateurs créés à ce groupe." -#: authentik/stages/user_write/models.py:68 +#: authentik/stages/user_write/models.py msgid "User Write Stage" msgstr "Étapes d'écriture utilisateur" -#: authentik/stages/user_write/models.py:69 +#: authentik/stages/user_write/models.py msgid "User Write Stages" msgstr "Étapes d'écriture utilisateur" -#: authentik/stages/user_write/stage.py:141 +#: authentik/stages/user_write/stage.py msgid "No Pending data." msgstr "Aucune donnée en attente." -#: authentik/stages/user_write/stage.py:147 +#: authentik/stages/user_write/stage.py msgid "No user found and can't create new user." msgstr "Utilisateur introuvable et impossible de créer un nouvel utilisateur." -#: authentik/stages/user_write/stage.py:164 -#: authentik/stages/user_write/stage.py:178 +#: authentik/stages/user_write/stage.py msgid "Failed to update user. Please try again later." msgstr "" "Échec de mise à jour de l'utilisateur. Merci de réessayer ultérieurement," -#: authentik/tenants/models.py:29 +#: authentik/tenants/models.py msgid "" "Schema name must start with t_, only contain lowercase letters and numbers " "and be less than 63 characters." @@ -3052,26 +3170,26 @@ msgstr "" "Le nom du schema doit commencer par t_, contenir seulement des lettres " "minuscules et nombre, et être inférieur à 63 caractères." -#: authentik/tenants/models.py:49 +#: authentik/tenants/models.py msgid "Configure how authentik should show avatars for users." msgstr "" "Configurer comment authentik doit afficher les avatars des utilisateurs." -#: authentik/tenants/models.py:53 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their name." msgstr "Activer la possibilité aux utilisateurs de changer leur nom." -#: authentik/tenants/models.py:56 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their email address." msgstr "" "Activer la possibilité aux utilisateurs de changer leur adresse email." -#: authentik/tenants/models.py:59 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their username." msgstr "" "Activer la possibilité aux utilisateurs de changer leur nom d'utilisateur." -#: authentik/tenants/models.py:65 +#: authentik/tenants/models.py msgid "" "Events will be deleted after this duration.(Format: " "weeks=3;days=2;hours=3,seconds=2)." @@ -3079,13 +3197,13 @@ msgstr "" "Les évènements seront supprimés après cet interval. (Format : " "weeks=3;days=2;hours=3,seconds=2)" -#: authentik/tenants/models.py:69 +#: authentik/tenants/models.py msgid "The option configures the footer links on the flow executor pages." msgstr "" "Cette option configure les liens du pied de page sur les pages de " "l'exécuteur de flux." -#: authentik/tenants/models.py:75 +#: authentik/tenants/models.py msgid "" "When enabled, all the events caused by a user will be deleted upon the " "user's deletion." @@ -3093,22 +3211,30 @@ msgstr "" "Lorsqu'activé, tous les évènements causés par un utilisateur seront " "supprimés lors de la suppression de l'utilisateur." -#: authentik/tenants/models.py:81 +#: authentik/tenants/models.py msgid "Globally enable/disable impersonation." msgstr "Activer/désactiver l'appropriation utilisateur de manière globale." -#: authentik/tenants/models.py:104 +#: authentik/tenants/models.py +msgid "Default token duration" +msgstr "Durée par défaut des jetons" + +#: authentik/tenants/models.py +msgid "Default token length" +msgstr "Longueur par défaut des jetons" + +#: authentik/tenants/models.py msgid "Tenant" msgstr "Tenant" -#: authentik/tenants/models.py:105 +#: authentik/tenants/models.py msgid "Tenants" msgstr "Tenants" -#: authentik/tenants/models.py:125 +#: authentik/tenants/models.py msgid "Domain" msgstr "Domaine" -#: authentik/tenants/models.py:126 +#: authentik/tenants/models.py msgid "Domains" msgstr "Domaines" diff --git a/locale/nl/LC_MESSAGES/django.mo b/locale/nl/LC_MESSAGES/django.mo index 67e966ad9a..759171968e 100644 Binary files a/locale/nl/LC_MESSAGES/django.mo and b/locale/nl/LC_MESSAGES/django.mo differ diff --git a/locale/ru/LC_MESSAGES/django.mo b/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..c1e63098b6 Binary files /dev/null and b/locale/ru/LC_MESSAGES/django.mo differ diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000000..e47baeb558 --- /dev/null +++ b/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,3280 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +# Translators: +# Vladimir, 2022 +# Ivan Podgorny, 2023 +# Nicholas Winterhalter, 2023 +# Ренат Шарафутдинов, 2023 +# Stepan Karavaev, 2024 +# Anton Babenko, 2024 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-23 00:07+0000\n" +"PO-Revision-Date: 2022-09-26 16:47+0000\n" +"Last-Translator: Anton Babenko, 2024\n" +"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" + +#: authentik/api/schema.py +msgid "Generic API Error" +msgstr "Общая ошибка API" + +#: authentik/api/schema.py +msgid "Validation Error" +msgstr "Ошибка валидации" + +#: authentik/blueprints/api.py +msgid "Blueprint file does not exist" +msgstr "Файл чертежа не существует" + +#: authentik/blueprints/api.py +#, python-brace-format +msgid "Failed to validate blueprint: {logs}" +msgstr "Ошибка валидации чертежа: {logs}" + +#: authentik/blueprints/api.py +msgid "Either path or content must be set." +msgstr "Путь или содержимое должно быть установлено." + +#: authentik/blueprints/models.py +msgid "Managed by authentik" +msgstr "Управляется authentik" + +#: authentik/blueprints/models.py +msgid "" +"Objects that are managed by authentik. These objects are created and updated" +" automatically. This flag only indicates that an object can be overwritten " +"by migrations. You can still modify the objects via the API, but expect " +"changes to be overwritten in a later update." +msgstr "" +"Объекты управляемые authentik. Эти объекты создаются и обновляются " +"автоматически. Этот флаг указывает на то, что объект может быть переписан " +"миграциями. Несмотря на это Вы можете менять эти объекты через API, но " +"учтите, что изменения могут быть переписаны в будущем обновлении." + +#: authentik/blueprints/models.py +msgid "Blueprint Instance" +msgstr "Экземпляр чертежа" + +#: authentik/blueprints/models.py +msgid "Blueprint Instances" +msgstr "Экземпляры чертежа" + +#: authentik/blueprints/v1/exporter.py +#, python-brace-format +msgid "authentik Export - {date}" +msgstr "authentik Экспорт - {date}" + +#: authentik/blueprints/v1/tasks.py authentik/crypto/tasks.py +#, python-format +msgid "Successfully imported %(count)d files." +msgstr "Удачно импортировано %(count)d файлов." + +#: authentik/brands/models.py +msgid "" +"Domain that activates this brand. Can be a superset, i.e. `a.b` for `aa.b` " +"and `ba.b`" +msgstr "" +"Домен, активирующий данный бренд. Может быть суперсетом, т.е. `a.b` для " +"`aa.b` и `ba.b`." + +#: authentik/brands/models.py +msgid "Web Certificate used by the authentik Core webserver." +msgstr "Web Certificate используемый для authentik Core webserver." + +#: authentik/brands/models.py +msgid "Brand" +msgstr "Бренд" + +#: authentik/brands/models.py +msgid "Brands" +msgstr "Бренды" + +#: authentik/core/api/providers.py +msgid "" +"When not set all providers are returned. When set to true, only backchannel " +"providers are returned. When set to false, backchannel providers are " +"excluded" +msgstr "" +"Если значение не установлено, возвращаются все провайдеры. Если установлено " +"значение true, возвращаются только провайдеры обратного канала. При значении" +" false провайдеры обратного канала исключаются." + +#: authentik/core/api/users.py +msgid "No leading or trailing slashes allowed." +msgstr "Не допускается использование ведущих и завершающих слэшей." + +#: authentik/core/api/users.py +msgid "No empty segments in user path allowed." +msgstr "Пустые сегменты в пользовательском пути не допускаются." + +#: authentik/core/models.py +msgid "name" +msgstr "имя" + +#: authentik/core/models.py +msgid "Users added to this group will be superusers." +msgstr "Добавленные в эту группу пользователи будут супер-пользователями." + +#: authentik/core/models.py +msgid "Group" +msgstr "Группа" + +#: authentik/core/models.py +msgid "Groups" +msgstr "Группы" + +#: authentik/core/models.py +msgid "Add user to group" +msgstr "Добавить пользователя в группу" + +#: authentik/core/models.py +msgid "Remove user from group" +msgstr "Удалить пользователя из группы" + +#: authentik/core/models.py +msgid "User's display name." +msgstr "Отображаемое имя пользователя." + +#: authentik/core/models.py authentik/providers/oauth2/models.py +msgid "User" +msgstr "Пользователь" + +#: authentik/core/models.py +msgid "Users" +msgstr "Пользователи" + +#: authentik/core/models.py +#: authentik/stages/email/templates/email/password_reset.html +msgid "Reset Password" +msgstr "Сбросить пароль" + +#: authentik/core/models.py +msgid "Can impersonate other users" +msgstr "Может выдавать себя за других пользователей" + +#: authentik/core/models.py authentik/rbac/models.py +msgid "Can assign permissions to users" +msgstr "Может назначать разрешения пользователям" + +#: authentik/core/models.py authentik/rbac/models.py +msgid "Can unassign permissions from users" +msgstr "Может убирать разрешения у пользователей" + +#: authentik/core/models.py +msgid "Can preview user data sent to providers" +msgstr "Может просматривать пользовательские данные, отправленные провайдерам" + +#: authentik/core/models.py +msgid "View applications the user has access to" +msgstr "Просмотр приложений, к которым пользователь имеет доступ" + +#: authentik/core/models.py +msgid "" +"Flow used for authentication when the associated application is accessed by " +"an un-authenticated user." +msgstr "" +"Поток, используемый для аутентификации, когда к связанному приложению " +"обращается неаутентифицированный пользователь." + +#: authentik/core/models.py +msgid "Flow used when authorizing this provider." +msgstr "Поток, используемый при авторизации данного провайдера." + +#: authentik/core/models.py +msgid "" +"Accessed from applications; optional backchannel providers for protocols " +"like LDAP and SCIM." +msgstr "" +"Доступ из приложений; дополнительные провайдеры обратных каналов для таких " +"протоколов, как LDAP и SCIM." + +#: authentik/core/models.py +msgid "Application's display Name." +msgstr "Отображаемое имя приложения." + +#: authentik/core/models.py +msgid "Internal application name, used in URLs." +msgstr "Внутреннее имя приложения, используемое в URL-адресах." + +#: authentik/core/models.py +msgid "Open launch URL in a new browser tab or window." +msgstr "Открыть URL-адрес запуска в новой вкладке или окне браузера." + +#: authentik/core/models.py +msgid "Application" +msgstr "Приложение" + +#: authentik/core/models.py +msgid "Applications" +msgstr "Приложения" + +#: authentik/core/models.py +msgid "Use the source-specific identifier" +msgstr "Использование идентификатора, характерного для источника" + +#: authentik/core/models.py +msgid "" +"Link to a user with identical email address. Can have security implications " +"when a source doesn't validate email addresses." +msgstr "" +"Ссылка на пользователя с идентичным адресом электронной почты. Это может " +"иметь последствия для безопасности, если источник не проверяет адреса " +"электронной почты." + +#: authentik/core/models.py +msgid "" +"Use the user's email address, but deny enrollment when the email address " +"already exists." +msgstr "" +"Использовать адрес электронной почты пользователя, но отказывать в " +"регистрации, если такой адрес уже существует." + +#: authentik/core/models.py +msgid "" +"Link to a user with identical username. Can have security implications when " +"a username is used with another source." +msgstr "" +"Ссылка на пользователя с идентичным именем пользователя. Это может иметь " +"последствия для безопасности, если имя пользователя используется с другим " +"источником." + +#: authentik/core/models.py +msgid "" +"Use the user's username, but deny enrollment when the username already " +"exists." +msgstr "" +"Использовать имя пользователя, но отказывать в регистрации, если имя " +"пользователя уже существует." + +#: authentik/core/models.py +msgid "Source's display Name." +msgstr "Отображаемое имя источника." + +#: authentik/core/models.py +msgid "Internal source name, used in URLs." +msgstr "Внутреннее имя источника, используемое в URL-адресах." + +#: authentik/core/models.py +msgid "Flow to use when authenticating existing users." +msgstr "Поток, используемый при аутентификации существующих пользователей." + +#: authentik/core/models.py +msgid "Flow to use when enrolling new users." +msgstr "Поток, используемый при регистрации новых пользователей." + +#: authentik/core/models.py +msgid "" +"How the source determines if an existing user should be authenticated or a " +"new user enrolled." +msgstr "" +"Как источник определяет, следует ли аутентифицировать существующего " +"пользователя или зачислить нового." + +#: authentik/core/models.py +msgid "Token" +msgstr "Токен" + +#: authentik/core/models.py +msgid "Tokens" +msgstr "Токены" + +#: authentik/core/models.py +msgid "View token's key" +msgstr "Просмотр ключа токена " + +#: authentik/core/models.py +msgid "Property Mapping" +msgstr "Сопоставление свойств" + +#: authentik/core/models.py +msgid "Property Mappings" +msgstr "Сопоставление свойств" + +#: authentik/core/models.py +msgid "Authenticated Session" +msgstr "Аутентифицированная Сессия" + +#: authentik/core/models.py +msgid "Authenticated Sessions" +msgstr "Аутентифицированные Сессии" + +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "" +"Request to authenticate with {source} has been denied. Please authenticate " +"with the source you've previously signed up with." +msgstr "" +"Запрос на аутентификацию с помощью {source} был отклонен. Пожалуйста, " +"пройдите аутентификацию с помощью источника, с которым вы регистрировались " +"ранее." + +#: authentik/core/sources/flow_manager.py +msgid "Configured flow does not exist." +msgstr "Настроенный поток не существует." + +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully authenticated with {source}!" +msgstr "Успешная аутентификация с {source}!" + +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully linked {source}!" +msgstr "Успешно связано с {source}!" + +#: authentik/core/sources/flow_manager.py +msgid "Source is not configured for enrollment." +msgstr "Источник не настроен для зачисления." + +#: authentik/core/templates/if/end_session.html +msgid "End session" +msgstr "Завершение сессии" + +#: authentik/core/templates/if/end_session.html +#, python-format +msgid "" +"\n" +"You've logged out of %(application)s.\n" +msgstr "" +"\n" +"Вы вышли из %(application)s.\n" + +#: authentik/core/templates/if/end_session.html +#, python-format +msgid "" +"\n" +" You've logged out of %(application)s. You can go back to the overview to launch another application, or log out of your %(branding_title)s account.\n" +" " +msgstr "" +"\n" +" Вы вышли из %(application)s. Вы можете вернуться к обзору, чтобы запустить другое приложение, или выйти из учетной записи %(branding_title)s.\n" +" " + +#: authentik/core/templates/if/end_session.html +msgid "Go back to overview" +msgstr "Вернуться к обзору" + +#: authentik/core/templates/if/end_session.html +#, python-format +msgid "" +"\n" +" Log out of %(branding_title)s\n" +" " +msgstr "" +"\n" +" Выйти из %(branding_title)s\n" +" " + +#: authentik/core/templates/if/end_session.html +#, python-format +msgid "" +"\n" +" Log back into %(application)s\n" +" " +msgstr "" +"\n" +" Опять войти в %(application)s\n" +" " + +#: authentik/core/templates/if/error.html +msgid "Go home" +msgstr "Домой" + +#: authentik/core/templates/login/base_full.html +msgid "Powered by authentik" +msgstr "Поддерживается authentik" + +#: authentik/core/views/apps.py authentik/providers/oauth2/views/authorize.py +#: authentik/providers/oauth2/views/device_init.py +#: authentik/providers/saml/views/sso.py +#, python-format +msgid "You're about to sign into %(application)s." +msgstr "Вы собираетесь войти в %(application)s." + +#: authentik/crypto/api.py +msgid "Subject-alt name" +msgstr "Альтернативное имя субъекта" + +#: authentik/crypto/builder.py +msgid "rsa" +msgstr "rsa" + +#: authentik/crypto/builder.py +msgid "ecdsa" +msgstr "ecdsa" + +#: authentik/crypto/models.py +msgid "PEM-encoded Certificate data" +msgstr "Данные сертификата, закодированные в формате PEM" + +#: authentik/crypto/models.py +msgid "" +"Optional Private Key. If this is set, you can use this keypair for " +"encryption." +msgstr "" +"Опциональный закрытый ключ. Если этот параметр установлен, вы можете " +"использовать эту пару ключей для шифрования." + +#: authentik/crypto/models.py +msgid "Certificate-Key Pair" +msgstr "Пара сертификат-ключ" + +#: authentik/crypto/models.py +msgid "Certificate-Key Pairs" +msgstr "Пары сертификат-ключ" + +#: authentik/enterprise/api.py +msgid "Enterprise is required to create/update this object." +msgstr "Для создания/обновления этого объекта требуется Enterprise." + +#: authentik/enterprise/models.py +msgid "License" +msgstr "Лицензия" + +#: authentik/enterprise/models.py +msgid "Licenses" +msgstr "Лицензии" + +#: authentik/enterprise/models.py +msgid "License Usage" +msgstr "Использование лицензии" + +#: authentik/enterprise/models.py +msgid "License Usage Records" +msgstr "Записи использования лицензии" + +#: authentik/enterprise/policy.py +msgid "Enterprise required to access this feature." +msgstr "Для доступа к этой функции требуется Enterprise." + +#: authentik/enterprise/policy.py +msgid "Feature only accessible for internal users." +msgstr "Функция доступна только для внутренних пользователей." + +#: authentik/enterprise/providers/google_workspace/models.py +#: authentik/enterprise/providers/microsoft_entra/models.py +#: authentik/providers/scim/models.py authentik/sources/ldap/models.py +msgid "Property mappings used for group creation/updating." +msgstr "Сопоставления свойств, используемые для создания/обновления групп." + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider" +msgstr "Google Workspace Провайдер" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Providers" +msgstr "Google Workspace Провайдеры" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mapping" +msgstr "Сопоставление провайдера Google Workspace" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mappings" +msgstr "Сопоставления провайдера Google Workspace" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider User" +msgstr "Пользователь провайдера Google Workspace" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Users" +msgstr "Пользователи провайдера Google Workspace" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Group" +msgstr "Группа провайдера Google Workspace" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Groups" +msgstr "Группы провайдера Google Workspace" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider" +msgstr "Microsoft Entra Провайдер" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Providers" +msgstr "Microsoft Entra Провайдеры" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mapping" +msgstr "Сопоставление провайдера Microsoft Entra" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mappings" +msgstr "Сопоставления провайдера Microsoft Entra" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider User" +msgstr "Пользователь провайдера Microsoft Entra" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Group" +msgstr "Группа провайдера Microsoft Entra" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Groups" +msgstr "Группы провайдера Microsoft Entra" + +#: authentik/enterprise/providers/rac/models.py +#: authentik/stages/user_login/models.py +msgid "" +"Determines how long a session lasts. Default of 0 means that the sessions " +"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "" +"Определяет время жизни сессии. Значение по умолчанию 0 означает, что сессии " +"будут истекать при закрытии браузера. (Формат: часы=-1;минуты=-2;секунды=-3)" + +#: authentik/enterprise/providers/rac/models.py +msgid "When set to true, connection tokens will be deleted upon disconnect." +msgstr "" +"Если установлено значение true, токены соединения будут удалены при " +"отключении" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Provider" +msgstr "RAC Провайдер" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Providers" +msgstr "RAC Провайдеры" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Endpoint" +msgstr "Точка подключения RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Endpoints" +msgstr "Точки подключения RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Property Mapping" +msgstr "Сопоставление свойств RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Property Mappings" +msgstr "Сопоставления свойств RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection token" +msgstr "Токен соединения RAC" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection tokens" +msgstr "Токены соединения RAC" + +#: authentik/enterprise/providers/rac/views.py +msgid "Maximum connection limit reached." +msgstr "Достигнут максимальный лимит соединений." + +#: authentik/enterprise/providers/rac/views.py +msgid "(You are already connected in another tab/window)" +msgstr "(Вы уже подключены в другой вкладке/окне)" + +#: authentik/enterprise/stages/source/models.py +msgid "" +"Amount of time a user can take to return from the source to continue the " +"flow (Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "" +"Количество времени, в течение которого пользователь может вернуться из " +"источника, чтобы продолжить поток (Формат: hours=-1;minutes=-2;seconds=-3)" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stage" +msgstr "Этап источника" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stages" +msgstr "Этапы источника" + +#: authentik/events/api/tasks.py +#, python-brace-format +msgid "Successfully started task {name}." +msgstr "Задача {name} успешно запущена." + +#: authentik/events/models.py +msgid "Event" +msgstr "Событие" + +#: authentik/events/models.py +msgid "Events" +msgstr "События" + +#: authentik/events/models.py +msgid "authentik inbuilt notifications" +msgstr "Встроенные уведомления authentik" + +#: authentik/events/models.py +msgid "Generic Webhook" +msgstr "Общий вебхук" + +#: authentik/events/models.py +msgid "Slack Webhook (Slack/Discord)" +msgstr "Slack Вебхук (Slack/Discord)" + +#: authentik/events/models.py +msgid "Email" +msgstr "Email" + +#: authentik/events/models.py +msgid "" +"Only send notification once, for example when sending a webhook into a chat " +"channel." +msgstr "" +"Отправлять уведомление только один раз, например, при отправке вебхука в " +"чат-канал." + +#: authentik/events/models.py +msgid "Severity" +msgstr "Серьезность" + +#: authentik/events/models.py +msgid "Dispatched for user" +msgstr "Отправлено пользователю" + +#: authentik/events/models.py +msgid "Event user" +msgstr "События пользователя" + +#: authentik/events/models.py +msgid "Notification Transport" +msgstr "Поставщик уведомлений" + +#: authentik/events/models.py +msgid "Notification Transports" +msgstr "Поставщики уведомлений" + +#: authentik/events/models.py +msgid "Notice" +msgstr "Уведомление" + +#: authentik/events/models.py +msgid "Warning" +msgstr "Предупреждение" + +#: authentik/events/models.py +msgid "Alert" +msgstr "Тревога" + +#: authentik/events/models.py +msgid "Notification" +msgstr "Уведомление" + +#: authentik/events/models.py +msgid "Notifications" +msgstr "Уведомления" + +#: authentik/events/models.py +msgid "" +"Select which transports should be used to notify the user. If none are " +"selected, the notification will only be shown in the authentik UI." +msgstr "" +"Выберите, какие поставщики должны использоваться для уведомления " +"пользователя. Если ни один из них не выбран, уведомление будет отображаться " +"только в пользовательском интерфейсе authentik." + +#: authentik/events/models.py +msgid "Controls which severity level the created notifications will have." +msgstr "Определяет уровень важности создаваемых уведомлений." + +#: authentik/events/models.py +msgid "" +"Define which group of users this notification should be sent and shown to. " +"If left empty, Notification won't ben sent." +msgstr "" +"Определите, какой группе пользователей должно быть отправлено и показано это" +" уведомление. Если оставить пустым, уведомление не будет отправлено." + +#: authentik/events/models.py +msgid "Notification Rule" +msgstr "Правило Уведомления" + +#: authentik/events/models.py +msgid "Notification Rules" +msgstr "Правило Уведомлений" + +#: authentik/events/models.py +msgid "Webhook Mapping" +msgstr "Сопоставление вебхуков" + +#: authentik/events/models.py +msgid "Webhook Mappings" +msgstr "Сопоставления вебхуков" + +#: authentik/events/models.py +msgid "Run task" +msgstr "Запустить задачу" + +#: authentik/events/models.py +msgid "System Task" +msgstr "Системная задача" + +#: authentik/events/models.py +msgid "System Tasks" +msgstr "Системные задачи" + +#: authentik/events/system_tasks.py +msgid "Task has not been run yet." +msgstr "Задача еще не была запущена." + +#: authentik/flows/api/flows.py +#, python-brace-format +msgid "Flow not applicable to current user/request: {messages}" +msgstr "Поток не применим к текущему пользователю/запросу: {messages}" + +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Policy ({type})" +msgstr "Политика ({type})" + +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Binding {order}" +msgstr "Привязка {order}" + +#: authentik/flows/api/flows_diagram.py +msgid "Policy passed" +msgstr "Политика пройдена" + +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Stage ({type})" +msgstr "Этап ({type})" + +#: authentik/flows/api/flows_diagram.py +msgid "Policy denied" +msgstr "Политика отклонена" + +#: authentik/flows/api/flows_diagram.py +msgid "End of the flow" +msgstr "Конец потока" + +#: authentik/flows/api/flows_diagram.py +msgid "Requirement not fulfilled" +msgstr "Требование не выполнено" + +#: authentik/flows/api/flows_diagram.py +msgid "Flow authentication requirement" +msgstr "Требовать аутентификацию потока" + +#: authentik/flows/api/flows_diagram.py +msgid "Requirement fulfilled" +msgstr "Требование выполнено" + +#: authentik/flows/api/flows_diagram.py +msgid "Pre-flow policies" +msgstr "Предварительные политики потока" + +#: authentik/flows/api/flows_diagram.py authentik/flows/models.py +msgid "Flow" +msgstr "Поток" + +#: authentik/flows/exceptions.py +msgid "Flow does not apply to current user." +msgstr "Поток не применяется к текущему пользователю." + +#: authentik/flows/models.py +#, python-brace-format +msgid "Dynamic In-memory stage: {doc}" +msgstr "Динамический этап в памяти: {doc}" + +#: authentik/flows/models.py +msgid "Visible in the URL." +msgstr "Видно в ссылке." + +#: authentik/flows/models.py +msgid "Shown as the Title in Flow pages." +msgstr "Указывается в качестве заголовка на страницах потока." + +#: authentik/flows/models.py +msgid "" +"Decides what this Flow is used for. For example, the Authentication flow is " +"redirect to when an un-authenticated user visits authentik." +msgstr "" +"Определяет, для чего используется данный поток. Например, поток " +"Authentication перенаправляется, когда не прошедший аутентификацию " +"пользователь посещает authentik." + +#: authentik/flows/models.py +msgid "Background shown during execution" +msgstr "Фон, отображаемый во время выполнения" + +#: authentik/flows/models.py +msgid "" +"Enable compatibility mode, increases compatibility with password managers on" +" mobile devices." +msgstr "" +"Включите режим совместимости, чтобы повысить совместимость с менеджерами " +"паролей на мобильных устройствах." + +#: authentik/flows/models.py +msgid "Configure what should happen when a flow denies access to a user." +msgstr "" +"Настройте, что должно происходить, когда поток отказывает пользователю в " +"доступе." + +#: authentik/flows/models.py +msgid "Required level of authentication and authorization to access a flow." +msgstr "Требуемый уровень аутентификации и авторизации для доступа к потоку." + +#: authentik/flows/models.py +msgid "Flows" +msgstr "Потоки" + +#: authentik/flows/models.py +msgid "Can export a Flow" +msgstr "Может экспортировать поток" + +#: authentik/flows/models.py +msgid "Can inspect a Flow's execution" +msgstr "Может проверять выполнение потока" + +#: authentik/flows/models.py +msgid "View Flow's cache metrics" +msgstr "Просмотр показателей кэша потока" + +#: authentik/flows/models.py +msgid "Clear Flow's cache metrics" +msgstr "Очистка показателей кэша потока" + +#: authentik/flows/models.py +msgid "Evaluate policies during the Flow planning process." +msgstr "Оценка политик во время процесса планирования потока." + +#: authentik/flows/models.py +msgid "Evaluate policies when the Stage is present to the user." +msgstr "Оценивайте политики, когда этап предоставлен пользователю." + +#: authentik/flows/models.py +msgid "" +"Configure how the flow executor should handle an invalid response to a " +"challenge. RETRY returns the error message and a similar challenge to the " +"executor. RESTART restarts the flow from the beginning, and " +"RESTART_WITH_CONTEXT restarts the flow while keeping the current context." +msgstr "" +"Настройте, как исполнитель потока должен обрабатывать недопустимый ответ на " +"вызов. RETRY возвращает сообщение об ошибке и аналогичный вызов исполнителю." +" RESTART начинает выполнение потока с самого начала, а RESTART_WITH_CONTEXT " +"перезапускает поток, сохраняя текущий контекст." + +#: authentik/flows/models.py +msgid "Flow Stage Binding" +msgstr "Привязка этапа потока" + +#: authentik/flows/models.py +msgid "Flow Stage Bindings" +msgstr "Привязки этапа потока" + +#: authentik/flows/models.py +msgid "" +"Flow used by an authenticated user to configure this Stage. If empty, user " +"will not be able to configure this stage." +msgstr "" +"Поток, используемый аутентифицированным пользователем для настройки этого " +"Этапа. Если пусто, пользователь не сможет настроить этот этап." + +#: authentik/flows/models.py +msgid "Flow Token" +msgstr "Токен потока" + +#: authentik/flows/models.py +msgid "Flow Tokens" +msgstr "Токены потока" + +#: authentik/flows/views/executor.py +msgid "Invalid next URL" +msgstr "Недопустимый следующий URL-адрес" + +#: authentik/lib/sync/outgoing/tasks.py +msgid "Starting full provider sync" +msgstr "Запуск полной синхронизации провайдера" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of users" +msgstr "Синхронизация %(page)d страницы пользователей" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of groups" +msgstr "Синхронизация %(page)d страницы групп" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-brace-format +msgid "Stopping sync due to error: {error}" +msgstr "Остановка синхронизации из-за ошибки: {error}" + +#: authentik/lib/utils/time.py +#, python-format +msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." +msgstr "%(value)s не соответствует формату 'часов=3;минут=1'." + +#: authentik/lib/validators.py +#, python-brace-format +msgid "The fields {field_names} must be used together." +msgstr "Поля {field_names} должны использоваться вместе." + +#: authentik/outposts/api/service_connections.py +msgid "" +"You can only use an empty kubeconfig when connecting to a local cluster." +msgstr "" +"Вы можете использовать пустой kubeconfig только при подключении к локальному" +" кластеру." + +#: authentik/outposts/api/service_connections.py +msgid "Invalid kubeconfig" +msgstr "Неверный kubeconfig" + +#: authentik/outposts/models.py +msgid "" +"If enabled, use the local connection. Required Docker socket/Kubernetes " +"Integration" +msgstr "" +"Если включено, используется локальное соединение. Требует Docker " +"сокет/Kubernetes интеграции" + +#: authentik/outposts/models.py +msgid "Outpost Service-Connection" +msgstr "Сервисное соединение внешнего компонента" + +#: authentik/outposts/models.py +msgid "Outpost Service-Connections" +msgstr "Сервисные соединения внешнего компонента" + +#: authentik/outposts/models.py +msgid "" +"Can be in the format of 'unix://' when connecting to a local docker " +"daemon, or 'https://:2376' when connecting to a remote system." +msgstr "" +"Может иметь формат 'unix://' при подключении к локальному демону " +"docker или 'https://:2376' при подключении к удаленной системе." + +#: authentik/outposts/models.py +msgid "" +"CA which the endpoint's Certificate is verified against. Can be left empty " +"for no validation." +msgstr "" +"Центр сертификации, по которому проверяется сертификат конечной точки. Можно" +" оставить пустым для отсутствия проверки." + +#: authentik/outposts/models.py +msgid "" +"Certificate/Key used for authentication. Can be left empty for no " +"authentication." +msgstr "" +"Сертификат/ключ, используемый для аутентификации. Можно оставить пустым для " +"отсутствия аутентификации." + +#: authentik/outposts/models.py +msgid "Docker Service-Connection" +msgstr "Сервисное соединение Docker" + +#: authentik/outposts/models.py +msgid "Docker Service-Connections" +msgstr "Сервисные соединения Docker" + +#: authentik/outposts/models.py +msgid "" +"Paste your kubeconfig here. authentik will automatically use the currently " +"selected context." +msgstr "" +"Вставьте сюда свой kubeconfig. authentik будет автоматически использовать " +"текущий выбранный контекст." + +#: authentik/outposts/models.py +msgid "Verify SSL Certificates of the Kubernetes API endpoint" +msgstr "Проверка SSL-сертификатов конечной точки API Kubernetes" + +#: authentik/outposts/models.py +msgid "Kubernetes Service-Connection" +msgstr "Сервисное соединение Kubernetes" + +#: authentik/outposts/models.py +msgid "Kubernetes Service-Connections" +msgstr "Сервисные соединения Kubernetes" + +#: authentik/outposts/models.py +msgid "" +"Select Service-Connection authentik should use to manage this outpost. Leave" +" empty if authentik should not handle the deployment." +msgstr "" +"Выберите сервисное соединение, которое authentik должен использовать для " +"управления этим внешним компонентом. Оставьте пустым, если authentik не " +"должен обрабатывать это развертывание." + +#: authentik/outposts/models.py +msgid "Outpost" +msgstr "Внешний компонент" + +#: authentik/outposts/models.py +msgid "Outposts" +msgstr "Внешние компоненты" + +#: authentik/policies/denied.py +msgid "Access denied" +msgstr "Доступ запрещен" + +#: authentik/policies/dummy/models.py +msgid "Dummy Policy" +msgstr "Фиктивная политика" + +#: authentik/policies/dummy/models.py +msgid "Dummy Policies" +msgstr "Фиктивные политики" + +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py +msgid "" +"Match events created by selected application. When left empty, all " +"applications are matched." +msgstr "" +"Соответствовать событиям, созданным выбранным приложением. Если поле " +"оставить пустым, будут соответствовать все приложения." + +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py +msgid "" +"Match events created by selected model. When left empty, all models are " +"matched. When an app is selected, all the application's models are matched." +msgstr "" +"Соответствовать событиям, созданным выбранной моделью. Когда оставлено " +"пустым, соответствуют все модели. Когда выбрано приложение, соответствуют " +"все модели этого приложения." + +#: authentik/policies/event_matcher/api.py +msgid "At least one criteria must be set." +msgstr "Хотя бы одна критерия должна быть установлена." + +#: authentik/policies/event_matcher/models.py +msgid "" +"Match created events with this action type. When left empty, all action " +"types will be matched." +msgstr "" +"Сопоставлять созданные события с данным типом действия. Если оставить " +"пустым, будут сопоставлены все типы действий." + +#: authentik/policies/event_matcher/models.py +msgid "" +"Matches Event's Client IP (strict matching, for network matching use an " +"Expression Policy)" +msgstr "" +"Сопоставляет IP-адрес клиента события (строгое сопоставление, для сетевого " +"сопоставления используйте политику выражений)" + +#: authentik/policies/event_matcher/models.py +msgid "Event Matcher Policy" +msgstr "Политика сопоставления событий" + +#: authentik/policies/event_matcher/models.py +msgid "Event Matcher Policies" +msgstr "Политики сопоставления событий" + +#: authentik/policies/expiry/models.py +#, python-format +msgid "Password expired %(days)d days ago. Please update your password." +msgstr "Пароль истёк %(days)d дней назад. Пожалуйста, обновите его." + +#: authentik/policies/expiry/models.py +msgid "Password has expired." +msgstr "Пароль истёк." + +#: authentik/policies/expiry/models.py +msgid "Password Expiry Policy" +msgstr "Политика истечения пароля" + +#: authentik/policies/expiry/models.py +msgid "Password Expiry Policies" +msgstr "Политика истечения срока действия пароля" + +#: authentik/policies/expression/models.py +msgid "Expression Policy" +msgstr "Политика выражения" + +#: authentik/policies/expression/models.py +msgid "Expression Policies" +msgstr "Политики выражения" + +#: authentik/policies/models.py +msgid "all, all policies must pass" +msgstr "все, все политики должны пройти" + +#: authentik/policies/models.py +msgid "any, any policy must pass" +msgstr "любая, любая политика должна пройти" + +#: authentik/policies/models.py +msgid "Policy Binding Model" +msgstr "Модель привязки политики" + +#: authentik/policies/models.py +msgid "Policy Binding Models" +msgstr "Модели привязок политик" + +#: authentik/policies/models.py +msgid "Negates the outcome of the policy. Messages are unaffected." +msgstr "Отменяет результат политики. Сообщения не затрагиваются." + +#: authentik/policies/models.py +msgid "Timeout after which Policy execution is terminated." +msgstr "Таймаут, по истечении которого выполнение политики прекращается." + +#: authentik/policies/models.py +msgid "Result if the Policy execution fails." +msgstr "Результат при неудачном выполнении политики." + +#: authentik/policies/models.py +msgid "Policy Binding" +msgstr "Привязка политики" + +#: authentik/policies/models.py +msgid "Policy Bindings" +msgstr "Привязки политик" + +#: authentik/policies/models.py +msgid "" +"When this option is enabled, all executions of this policy will be logged. " +"By default, only execution errors are logged." +msgstr "" +"Если эта опция включена, все выполнения этой политики будут записываться в " +"журнал. По умолчанию в журнал записываются только ошибки выполнения." + +#: authentik/policies/models.py +msgid "Policy" +msgstr "Политика" + +#: authentik/policies/models.py +msgid "Policies" +msgstr "Политики" + +#: authentik/policies/models.py +msgid "View Policy's cache metrics" +msgstr "Просмотр показателей кэша политики" + +#: authentik/policies/models.py +msgid "Clear Policy's cache metrics" +msgstr "Очистка показателей кэша политики" + +#: authentik/policies/password/models.py +msgid "Field key to check, field keys defined in Prompt stages are available." +msgstr "" +"Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса." + +#: authentik/policies/password/models.py +msgid "How many times the password hash is allowed to be on haveibeenpwned" +msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned" + +#: authentik/policies/password/models.py +msgid "" +"If the zxcvbn score is equal or less than this value, the policy will fail." +msgstr "" +"Если показатель zxcvbn равен или меньше этого значения, политика будет " +"провалена." + +#: authentik/policies/password/models.py +msgid "Password not set in context" +msgstr "Пароль не задан в контексте" + +#: authentik/policies/password/models.py +#, python-format +msgid "Password exists on %(count)d online lists." +msgstr "Пароль существует в %(count)d онлайн-списках." + +#: authentik/policies/password/models.py +msgid "Password is too weak." +msgstr "Пароль слишком слабый." + +#: authentik/policies/password/models.py +msgid "Password Policy" +msgstr "Политика пароля" + +#: authentik/policies/password/models.py +msgid "Password Policies" +msgstr "Политики пароля" + +#: authentik/policies/reputation/api.py +msgid "Either IP or Username must be checked" +msgstr "Должен быть проверен либо IP, либо имя пользователя." + +#: authentik/policies/reputation/models.py +msgid "Reputation Policy" +msgstr "Политика репутации" + +#: authentik/policies/reputation/models.py +msgid "Reputation Policies" +msgstr "Политики репутации" + +#: authentik/policies/reputation/models.py +msgid "Reputation Score" +msgstr "Оценка репутации" + +#: authentik/policies/reputation/models.py +msgid "Reputation Scores" +msgstr "Оценка репутации" + +#: authentik/policies/templates/policies/denied.html +msgid "Permission denied" +msgstr "Доступ запрещен" + +#: authentik/policies/templates/policies/denied.html +msgid "User's avatar" +msgstr "Аватар пользователя" + +#: authentik/policies/templates/policies/denied.html +msgid "Not you?" +msgstr "Не вы?" + +#: authentik/policies/templates/policies/denied.html +msgid "Request has been denied." +msgstr "В произведении запроса было отказано." + +#: authentik/policies/templates/policies/denied.html +msgid "Messages:" +msgstr "Сообщения:" + +#: authentik/policies/templates/policies/denied.html +msgid "Explanation:" +msgstr "Объяснение:" + +#: authentik/policies/templates/policies/denied.html +#, python-format +msgid "" +"\n" +" Policy binding '%(name)s' returned result '%(result)s'\n" +" " +msgstr "" +"\n" +" Привязка политики '%(name)s' вернула результат '%(result)s'\n" +" " + +#: authentik/policies/views.py +msgid "Failed to resolve application" +msgstr "Не удалось получить приложение" + +#: authentik/providers/ldap/models.py +msgid "DN under which objects are accessible." +msgstr "DN, под которым доступны объекты." + +#: authentik/providers/ldap/models.py +msgid "" +"Users in this group can do search queries. If not set, every user can " +"execute search queries." +msgstr "" +"Пользователи этой группы могут выполнять поисковые запросы. Если не задано, " +"каждый пользователь может выполнять поисковые запросы." + +#: authentik/providers/ldap/models.py +msgid "" +"The start for uidNumbers, this number is added to the user.pk to make sure " +"that the numbers aren't too low for POSIX users. Default is 2000 to ensure " +"that we don't collide with local users uidNumber" +msgstr "" +"Начало для uidNumbers, это число добавляется в user.pk, чтобы убедиться, что" +" номера не слишком малы для пользователей POSIX. По умолчанию 2000, чтобы не" +" столкнуться с локальными пользователями uidNumber" + +#: authentik/providers/ldap/models.py +msgid "" +"The start for gidNumbers, this number is added to a number generated from " +"the group.pk to make sure that the numbers aren't too low for POSIX groups. " +"Default is 4000 to ensure that we don't collide with local groups or users " +"primary groups gidNumber" +msgstr "" +"Начало для gidNumbers, это число добавляется к числу, сгенерированному из " +"group.pk, чтобы убедиться, что числа не слишком малы для POSIX-групп. По " +"умолчанию 4000, чтобы исключить столкновение с локальными группами или " +"первичными группами пользователей gidNumber" + +#: authentik/providers/ldap/models.py authentik/providers/radius/models.py +msgid "" +"When enabled, code-based multi-factor authentication can be used by " +"appending a semicolon and the TOTP code to the password. This should only be" +" enabled if all users that will bind to this provider have a TOTP device " +"configured, as otherwise a password may incorrectly be rejected if it " +"contains a semicolon." +msgstr "" +"Если эта функция включена, можно использовать многофакторную аутентификацию " +"на основе кода, добавляя к паролю точку с запятой и код TOTP. Эту функцию " +"следует включать только в том случае, если у всех пользователей, которые " +"будут привязываться к этому провайдеру, настроено устройство TOTP, поскольку" +" в противном случае пароль может быть ошибочно отклонен, если он содержит " +"точку с запятой." + +#: authentik/providers/ldap/models.py +msgid "LDAP Provider" +msgstr "LDAP Провайдер" + +#: authentik/providers/ldap/models.py +msgid "LDAP Providers" +msgstr "LDAP Провайдеры" + +#: authentik/providers/oauth2/id_token.py +msgid "Based on the Hashed User ID" +msgstr "На основе хэшированного идентификатора пользователя" + +#: authentik/providers/oauth2/id_token.py +msgid "Based on user ID" +msgstr "На основе идентификатора пользователя" + +#: authentik/providers/oauth2/id_token.py +msgid "Based on user UUID" +msgstr "На основе UUID пользователя" + +#: authentik/providers/oauth2/id_token.py +msgid "Based on the username" +msgstr "На основе имени пользователя" + +#: authentik/providers/oauth2/id_token.py +msgid "Based on the User's Email. This is recommended over the UPN method." +msgstr "" +"На основе электронной почты пользователя. Этот метод рекомендуется " +"использовать вместо метода UPN." + +#: authentik/providers/oauth2/id_token.py +msgid "" +"Based on the User's UPN, only works if user has a 'upn' attribute set. Use " +"this method only if you have different UPN and Mail domains." +msgstr "" +"Основан на UPN пользователя, работает только в том случае, если у " +"пользователя установлен атрибут 'upn'. Используйте этот метод только в том " +"случае, если у вас разные UPN и почтовые домены." + +#: authentik/providers/oauth2/models.py +msgid "Confidential" +msgstr "Конфиденциальный" + +#: authentik/providers/oauth2/models.py +msgid "Public" +msgstr "Публичный" + +#: authentik/providers/oauth2/models.py +msgid "Same identifier is used for all providers" +msgstr "Один и тот же идентификатор применяется для всех поставщиков" + +#: authentik/providers/oauth2/models.py +msgid "Each provider has a different issuer, based on the application slug." +msgstr "" +"У каждого провайдера есть свой эмитент, основанный на идентификаторе " +"приложения." + +#: authentik/providers/oauth2/models.py +msgid "code (Authorization Code Flow)" +msgstr "code (поток кода авторизации)" + +#: authentik/providers/oauth2/models.py +msgid "id_token (Implicit Flow)" +msgstr "id_token (неявный поток)" + +#: authentik/providers/oauth2/models.py +msgid "id_token token (Implicit Flow)" +msgstr "id_token token (неявный поток)" + +#: authentik/providers/oauth2/models.py +msgid "code token (Hybrid Flow)" +msgstr "code token (гибридный поток)" + +#: authentik/providers/oauth2/models.py +msgid "code id_token (Hybrid Flow)" +msgstr "code id_token (гибридный поток)" + +#: authentik/providers/oauth2/models.py +msgid "code id_token token (Hybrid Flow)" +msgstr "code id_token token (гибридный поток)" + +#: authentik/providers/oauth2/models.py +msgid "HS256 (Symmetric Encryption)" +msgstr "HS256 (симметричное шифрование)" + +#: authentik/providers/oauth2/models.py +msgid "RS256 (Asymmetric Encryption)" +msgstr "RS256 (асимметричное шифрование)" + +#: authentik/providers/oauth2/models.py +msgid "ES256 (Asymmetric Encryption)" +msgstr "ES256 (асимметричное шифрование)" + +#: authentik/providers/oauth2/models.py +msgid "Scope used by the client" +msgstr "Область, используемая клиентом" + +#: authentik/providers/oauth2/models.py +msgid "" +"Description shown to the user when consenting. If left empty, the user won't" +" be informed." +msgstr "" +"Описание, показываемое пользователю при получении согласия. Если оставить " +"его пустым, пользователь не будет проинформирован." + +#: authentik/providers/oauth2/models.py +msgid "Scope Mapping" +msgstr "Сопоставление областей" + +#: authentik/providers/oauth2/models.py +msgid "Scope Mappings" +msgstr "Сопоставления областей" + +#: authentik/providers/oauth2/models.py +msgid "Client Type" +msgstr "Тип клиента" + +#: authentik/providers/oauth2/models.py +msgid "" +"Confidential clients are capable of maintaining the confidentiality of their" +" credentials. Public clients are incapable" +msgstr "" +"Конфиденциальные клиенты могут сохранять конфиденциальность своих данных. " +"Публичные клиенты не могут" + +#: authentik/providers/oauth2/models.py +msgid "Client ID" +msgstr "ID клиента" + +#: authentik/providers/oauth2/models.py +msgid "Client Secret" +msgstr "Секрет клиента" + +#: authentik/providers/oauth2/models.py +msgid "Redirect URIs" +msgstr "Ссылка перенаправления" + +#: authentik/providers/oauth2/models.py +msgid "Enter each URI on a new line." +msgstr "Введите каждый URI с новой строки." + +#: authentik/providers/oauth2/models.py +msgid "Include claims in id_token" +msgstr "Включить утверждения в id_token" + +#: authentik/providers/oauth2/models.py +msgid "" +"Include User claims from scopes in the id_token, for applications that don't" +" access the userinfo endpoint." +msgstr "" +"Включить пользовательские утверждения из областей в id_token для приложений," +" которые не обращаются к конечной точке userinfo." + +#: authentik/providers/oauth2/models.py +msgid "" +"Access codes not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "" +"Коды доступа не действуют в текущее время или после него + указанное " +"значение (Формат: hours=1;minutes=2;seconds=3)." + +#: authentik/providers/oauth2/models.py +msgid "" +"Tokens not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "" +"Токены не действительны в текущее время или после него + указанное значение " +"(Формат: hours=1;minutes=2;seconds=3)." + +#: authentik/providers/oauth2/models.py +msgid "" +"Configure what data should be used as unique User Identifier. For most " +"cases, the default should be fine." +msgstr "" +"Настройте, какие данные должны использоваться в качестве уникального " +"идентификатора пользователя. Для большинства случаев подходит значение по " +"умолчанию." + +#: authentik/providers/oauth2/models.py +msgid "Configure how the issuer field of the ID Token should be filled." +msgstr "Настройте, как должно быть заполнено поле эмитента ID-токена." + +#: authentik/providers/oauth2/models.py +msgid "Signing Key" +msgstr "Подписывающий ключ" + +#: authentik/providers/oauth2/models.py +msgid "" +"Key used to sign the tokens. Only required when JWT Algorithm is set to " +"RS256." +msgstr "" +"Ключ, используемый для подписи токенов. Требуется только в том случае, если " +"для алгоритма JWT установлено значение RS256." + +#: authentik/providers/oauth2/models.py +msgid "" +"Any JWT signed by the JWK of the selected source can be used to " +"authenticate." +msgstr "" +"Для аутентификации можно использовать любой JWT, подписанный JWK выбранного " +"источника." + +#: authentik/providers/oauth2/models.py +msgid "OAuth2/OpenID Provider" +msgstr "OAuth2/OpenID Провайдер" + +#: authentik/providers/oauth2/models.py +msgid "OAuth2/OpenID Providers" +msgstr "OAuth2/OpenID Провайдеры" + +#: authentik/providers/oauth2/models.py +msgid "Scopes" +msgstr "Области" + +#: authentik/providers/oauth2/models.py +msgid "Code" +msgstr "Код" + +#: authentik/providers/oauth2/models.py +msgid "Nonce" +msgstr "Nonce" + +#: authentik/providers/oauth2/models.py +msgid "Code Challenge" +msgstr "Запрос" + +#: authentik/providers/oauth2/models.py +msgid "Code Challenge Method" +msgstr "Метод запроса" + +#: authentik/providers/oauth2/models.py +msgid "Authorization Code" +msgstr "Код авторизации" + +#: authentik/providers/oauth2/models.py +msgid "Authorization Codes" +msgstr "Коды авторизации" + +#: authentik/providers/oauth2/models.py +msgid "OAuth2 Access Token" +msgstr "OAuth2 Access токен" + +#: authentik/providers/oauth2/models.py +msgid "OAuth2 Access Tokens" +msgstr "OAuth2 Access токены" + +#: authentik/providers/oauth2/models.py +msgid "ID Token" +msgstr "ID токен" + +#: authentik/providers/oauth2/models.py +msgid "OAuth2 Refresh Token" +msgstr "OAuth2 Refresh токен" + +#: authentik/providers/oauth2/models.py +msgid "OAuth2 Refresh Tokens" +msgstr "OAuth2 Refresh токены" + +#: authentik/providers/oauth2/models.py +msgid "Device Token" +msgstr "Токен устройства" + +#: authentik/providers/oauth2/models.py +msgid "Device Tokens" +msgstr "Токены устройства" + +#: authentik/providers/oauth2/views/authorize.py +#: authentik/providers/saml/views/flows.py +#, python-brace-format +msgid "Redirecting to {app}..." +msgstr "Перенаправление на {app}..." + +#: authentik/providers/oauth2/views/device_init.py +msgid "Invalid code" +msgstr "Неверный код" + +#: authentik/providers/oauth2/views/userinfo.py +msgid "GitHub Compatibility: Access your User Information" +msgstr "Совместимость с GitHub: Доступ к информации о пользователе" + +#: authentik/providers/oauth2/views/userinfo.py +msgid "GitHub Compatibility: Access you Email addresses" +msgstr "Совместимость с GitHub: Доступ к вашим адресам электронной почты" + +#: authentik/providers/oauth2/views/userinfo.py +msgid "GitHub Compatibility: Access your Groups" +msgstr "Совместимость с GitHub: Доступ к вашим группам" + +#: authentik/providers/oauth2/views/userinfo.py +msgid "authentik API Access on behalf of your user" +msgstr "authentik API Access от имени вашего пользователя" + +#: authentik/providers/proxy/api.py +msgid "User and password attributes must be set when basic auth is enabled." +msgstr "" +"Атрибуты \"пользователь\" и \"пароль\" должны быть установлены, если " +"включена базовая аутентификация." + +#: authentik/providers/proxy/api.py +msgid "Internal host cannot be empty when forward auth is disabled." +msgstr "" +"Внутренний хост не может быть пустым, если прямая аутентификация отключена." + +#: authentik/providers/proxy/models.py +msgid "Validate SSL Certificates of upstream servers" +msgstr "Проверка SSL-сертификатов вышестоящих серверов" + +#: authentik/providers/proxy/models.py +msgid "Internal host SSL Validation" +msgstr "Внутренняя валидация SSL хоста" + +#: authentik/providers/proxy/models.py +msgid "" +"Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " +"with internal_host." +msgstr "" +"Включите поддержку forwardAuth в traefik и nginx auth_request. Эксклюзивно с" +" internal_host." + +#: authentik/providers/proxy/models.py +msgid "" +"Regular expressions for which authentication is not required. Each new line " +"is interpreted as a new Regular Expression." +msgstr "" +"Регулярные выражения, для которых не требуется аутентификация. Каждая новая " +"строка интерпретируется как новое Регулярное Выражение." + +#: authentik/providers/proxy/models.py +msgid "" +"When enabled, this provider will intercept the authorization header and " +"authenticate requests based on its value." +msgstr "" +"Если эта опция включена, провайдер будет перехватывать заголовок авторизации" +" и аутентифицировать запросы на основе его значения." + +#: authentik/providers/proxy/models.py +msgid "Set HTTP-Basic Authentication" +msgstr "Настройка базовой аутентификации HTTP" + +#: authentik/providers/proxy/models.py +msgid "" +"Set a custom HTTP-Basic Authentication header based on values from " +"authentik." +msgstr "" +"Установить пользовательский заголовок HTTP-Basic аутентификации на основе " +"значений из authentik." + +#: authentik/providers/proxy/models.py +msgid "HTTP-Basic Username Key" +msgstr "Ключ имени пользователя HTTP-Basic" + +#: authentik/providers/proxy/models.py +msgid "" +"User/Group Attribute used for the user part of the HTTP-Basic Header. If not" +" set, the user's Email address is used." +msgstr "" +"Атрибут User/Group, используемый для пользовательской части заголовка HTTP-" +"Basic. Если он не задан, используется адрес электронной почты пользователя." + +#: authentik/providers/proxy/models.py +msgid "HTTP-Basic Password Key" +msgstr "Ключ пароля HTTP-Basic" + +#: authentik/providers/proxy/models.py +msgid "" +"User/Group Attribute used for the password part of the HTTP-Basic Header." +msgstr "" +"Атрибут пользователя/группы, используемый для части пароля в заголовке HTTP-" +"Basic." + +#: authentik/providers/proxy/models.py +msgid "Proxy Provider" +msgstr "Прокси провайдер" + +#: authentik/providers/proxy/models.py +msgid "Proxy Providers" +msgstr "Прокси провайдеры" + +#: authentik/providers/radius/models.py +msgid "Shared secret between clients and server to hash packets." +msgstr "Общий секрет между клиентами и сервером для хэширования пакетов." + +#: authentik/providers/radius/models.py +msgid "" +"List of CIDRs (comma-separated) that clients can connect from. A more " +"specific CIDR will match before a looser one. Clients connecting from a non-" +"specified CIDR will be dropped." +msgstr "" +"Список CIDR (разделенных запятыми), с которых могут подключаться клиенты. " +"Более конкретный CIDR будет соответствовать более слабому. Клиенты, " +"подключающиеся с неуказанного CIDR, будут отброшены." + +#: authentik/providers/radius/models.py +msgid "Radius Provider" +msgstr "Radius Провайдер" + +#: authentik/providers/radius/models.py +msgid "Radius Providers" +msgstr "Radius Провайдеры" + +#: authentik/providers/saml/api/providers.py +msgid "Invalid XML Syntax" +msgstr "Некорректный синтаксис XML" + +#: authentik/providers/saml/api/providers.py +#, python-brace-format +msgid "Failed to import Metadata: {messages}" +msgstr "Не удалось импортировать метаданные: {messages}" + +#: authentik/providers/saml/models.py +msgid "ACS URL" +msgstr "URL-адрес ACS" + +#: authentik/providers/saml/models.py +msgid "" +"Value of the audience restriction field of the assertion. When left empty, " +"no audience restriction will be added." +msgstr "" +"Значение поля ограничения аудитории в утверждении. Если оставить его пустым," +" ограничение аудитории не будет добавлено." + +#: authentik/providers/saml/models.py +msgid "Also known as EntityID" +msgstr "Также известен как EntityID" + +#: authentik/providers/saml/models.py +msgid "Service Provider Binding" +msgstr "Привязка провайдера услуг" + +#: authentik/providers/saml/models.py +msgid "" +"This determines how authentik sends the response back to the Service " +"Provider." +msgstr "" +"Это определяет, как authentik отправляет ответ обратно провайдеру услуг." + +#: authentik/providers/saml/models.py +msgid "NameID Property Mapping" +msgstr "Сопоставление свойства NameID" + +#: authentik/providers/saml/models.py +msgid "" +"Configure how the NameID value will be created. When left empty, the " +"NameIDPolicy of the incoming request will be considered" +msgstr "" +"Настройте, как будет создаваться значение NameID. Если оставить пустым, " +"будет рассматриваться NameIDPolicy входящего запроса" + +#: authentik/providers/saml/models.py +msgid "" +"Assertion valid not before current time + this value (Format: " +"hours=-1;minutes=-2;seconds=-3)." +msgstr "" +"Утверждение действительно не ранее текущего времени + это значение (Формат: " +"hours=-1;minutes=-2;seconds=-3)." + +#: authentik/providers/saml/models.py +msgid "" +"Assertion not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "" +"Утверждение недействительно в текущее время или после него + указанное " +"значение (Формат: hours=1;minutes=2;seconds=3)." + +#: authentik/providers/saml/models.py +msgid "" +"Session not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "" +"Сессия не действительна по текущему времени или после него + указанное " +"значение (Формат: hours=1;minutes=2;seconds=3)." + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "SHA1" +msgstr "SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "SHA256" +msgstr "SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "SHA384" +msgstr "SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "SHA512" +msgstr "SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "RSA-SHA1" +msgstr "RSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "RSA-SHA256" +msgstr "RSA-SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "RSA-SHA384" +msgstr "RSA-SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "RSA-SHA512" +msgstr "RSA-SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA1" +msgstr "ECDSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA256" +msgstr "ECDSA-SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA384" +msgstr "ECDSA-SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA512" +msgstr "ECDSA-SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "DSA-SHA1" +msgstr "DSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "" +"When selected, incoming assertion's Signatures will be validated against " +"this certificate. To allow unsigned Requests, leave on default." +msgstr "" +"При выборе этого параметра подписи входящих утверждений будут проверяться по" +" этому сертификату. Чтобы разрешить неподписанные запросы, оставьте значение" +" по умолчанию." + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "Verification Certificate" +msgstr "Сертификат проверки" + +#: authentik/providers/saml/models.py +msgid "Keypair used to sign outgoing Responses going to the Service Provider." +msgstr "" +"Пара ключей, используемая для подписи исходящих ответов, направляемых " +"провайдеру услуг." + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "Signing Keypair" +msgstr "Пара ключей для подписи" + +#: authentik/providers/saml/models.py +msgid "Default relay_state value for IDP-initiated logins" +msgstr "Значение relay_state по умолчанию для логинов, инициированных IDP" + +#: authentik/providers/saml/models.py +msgid "SAML Provider" +msgstr "SAML Провайдер" + +#: authentik/providers/saml/models.py +msgid "SAML Providers" +msgstr "SAML Провайдеры" + +#: authentik/providers/saml/models.py +msgid "SAML Property Mapping" +msgstr "Сопоставление свойств SAML" + +#: authentik/providers/saml/models.py +msgid "SAML Property Mappings" +msgstr "Сопоставления свойств SAML" + +#: authentik/providers/saml/models.py +msgid "SAML Provider from Metadata" +msgstr "Провайдер SAML из метаданных" + +#: authentik/providers/saml/models.py +msgid "SAML Providers from Metadata" +msgstr "Провайдеры SAML из метаданных" + +#: authentik/providers/scim/models.py +msgid "Base URL to SCIM requests, usually ends in /v2" +msgstr "Базовый URL для запросов SCIM, обычно заканчивается на /v2" + +#: authentik/providers/scim/models.py +msgid "Authentication token" +msgstr "Токен аутентификации" + +#: authentik/providers/scim/models.py +msgid "SCIM Provider" +msgstr "SCIM Провайдер" + +#: authentik/providers/scim/models.py +msgid "SCIM Providers" +msgstr "SCIM Провайдеры" + +#: authentik/providers/scim/models.py +msgid "SCIM Mapping" +msgstr "Сопоставление SCIM" + +#: authentik/providers/scim/models.py +msgid "SCIM Mappings" +msgstr "Сопоставления SCIM" + +#: authentik/rbac/models.py +msgid "Role" +msgstr "Роль" + +#: authentik/rbac/models.py +msgid "Roles" +msgstr "Роли" + +#: authentik/rbac/models.py +msgid "System permission" +msgstr "Системное разрешение" + +#: authentik/rbac/models.py +msgid "System permissions" +msgstr "Системные разрешения" + +#: authentik/rbac/models.py +msgid "Can view system info" +msgstr "Может просматривать информацию о системе" + +#: authentik/rbac/models.py +msgid "Can access admin interface" +msgstr "Имеет доступ к интерфейсу администратора" + +#: authentik/rbac/models.py +msgid "Can view system settings" +msgstr "Может просматривать системные настройки" + +#: authentik/rbac/models.py +msgid "Can edit system settings" +msgstr "Может изменять системные настройки" + +#: authentik/recovery/management/commands/create_admin_group.py +msgid "Create admin group if the default group gets deleted." +msgstr "" +"Создайте группу администраторов, если группа по умолчанию будет удалена." + +#: authentik/recovery/management/commands/create_recovery_key.py +msgid "Create a Key which can be used to restore access to authentik." +msgstr "" +"Создайте ключ, который можно использовать для восстановления доступа к " +"authentik." + +#: authentik/recovery/views.py +msgid "Used recovery-link to authenticate." +msgstr "Для аутентификации использована ссылка для восстановления " + +#: authentik/sources/ldap/models.py +msgid "Server URI" +msgstr "URI сервера" + +#: authentik/sources/ldap/models.py +msgid "" +"Optionally verify the LDAP Server's Certificate against the CA Chain in this" +" keypair." +msgstr "" +"Опционально проверьте сертификат сервера LDAP по цепочке ЦС в этой паре " +"ключей." + +#: authentik/sources/ldap/models.py +msgid "" +"Client certificate to authenticate against the LDAP Server's Certificate." +msgstr "Сертификат клиента для аутентификации по сертификату сервера LDAP." + +#: authentik/sources/ldap/models.py +msgid "Bind CN" +msgstr "Bind CN" + +#: authentik/sources/ldap/models.py +msgid "Enable Start TLS" +msgstr "Включить StartTLS" + +#: authentik/sources/ldap/models.py +msgid "Use Server URI for SNI verification" +msgstr "Использование URI сервера для проверки SNI" + +#: authentik/sources/ldap/models.py +msgid "Base DN" +msgstr "Base DN" + +#: authentik/sources/ldap/models.py +msgid "Prepended to Base DN for User-queries." +msgstr "Добавляется к Base DN для пользовательских запросов." + +#: authentik/sources/ldap/models.py +msgid "Addition User DN" +msgstr "Дополнение User DN" + +#: authentik/sources/ldap/models.py +msgid "Prepended to Base DN for Group-queries." +msgstr "Добавляется к Base DN для групповых запросов." + +#: authentik/sources/ldap/models.py +msgid "Addition Group DN" +msgstr "Дополнение Group DN" + +#: authentik/sources/ldap/models.py +msgid "Consider Objects matching this filter to be Users." +msgstr "Объекты, соответствующие этому фильтру, считаются пользователями." + +#: authentik/sources/ldap/models.py +msgid "Field which contains members of a group." +msgstr "Поле, в котором содержатся члены группы." + +#: authentik/sources/ldap/models.py +msgid "Consider Objects matching this filter to be Groups." +msgstr "Объекты, соответствующие этому фильтру, считаются группами." + +#: authentik/sources/ldap/models.py +msgid "Field which contains a unique Identifier." +msgstr "Поле, которое содержит уникальный идентификатор." + +#: authentik/sources/ldap/models.py +msgid "Update internal authentik password when login succeeds with LDAP" +msgstr "" +"Обновление пароля внутреннего аутентика при успешном входе в систему с " +"помощью LDAP" + +#: authentik/sources/ldap/models.py +msgid "" +"When a user changes their password, sync it back to LDAP. This can only be " +"enabled on a single LDAP source." +msgstr "" +"При изменении пользовательского пароля синхронизировать его обратно в LDAP. " +"Это можно включить только для одного источника LDAP." + +#: authentik/sources/ldap/models.py +msgid "LDAP Source" +msgstr "Источник LDAP" + +#: authentik/sources/ldap/models.py +msgid "LDAP Sources" +msgstr "Источники LDAP" + +#: authentik/sources/ldap/models.py +msgid "LDAP Property Mapping" +msgstr "Сопоставление свойств LDAP" + +#: authentik/sources/ldap/models.py +msgid "LDAP Property Mappings" +msgstr "Сопоставления свойств LDAP" + +#: authentik/sources/ldap/signals.py +msgid "Password does not match Active Directory Complexity." +msgstr "Пароль не соответствует сложности Active Directory." + +#: authentik/sources/oauth/clients/oauth2.py +msgid "No token received." +msgstr "Токен не был получен." + +#: authentik/sources/oauth/models.py +msgid "Request Token URL" +msgstr "URL-адрес запроса токена" + +#: authentik/sources/oauth/models.py +msgid "" +"URL used to request the initial token. This URL is only required for OAuth " +"1." +msgstr "" +"URL-адрес, используемый для запроса начального токена. Этот URL требуется " +"только для OAuth 1." + +#: authentik/sources/oauth/models.py +msgid "Authorization URL" +msgstr "Ссылка авторизации" + +#: authentik/sources/oauth/models.py +msgid "URL the user is redirect to to conest the flow." +msgstr "" +"URL, на который пользователь перенаправляется для согласования потока." + +#: authentik/sources/oauth/models.py +msgid "Access Token URL" +msgstr "Ссылка Access токена" + +#: authentik/sources/oauth/models.py +msgid "URL used by authentik to retrieve tokens." +msgstr "URL-адрес, используемый authentik для получения токенов." + +#: authentik/sources/oauth/models.py +msgid "Profile URL" +msgstr "Ссылка на профиль" + +#: authentik/sources/oauth/models.py +msgid "URL used by authentik to get user information." +msgstr "" +"URL-адрес, используемый authentik для получения информации о пользователе." + +#: authentik/sources/oauth/models.py +msgid "Additional Scopes" +msgstr "Дополнительные области" + +#: authentik/sources/oauth/models.py +msgid "OAuth Source" +msgstr "Источник OAuth" + +#: authentik/sources/oauth/models.py +msgid "OAuth Sources" +msgstr "Источники OAuth" + +#: authentik/sources/oauth/models.py +msgid "GitHub OAuth Source" +msgstr "Источник GitHub OAuth" + +#: authentik/sources/oauth/models.py +msgid "GitHub OAuth Sources" +msgstr "Источники GitHub OAuth" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Source" +msgstr "Источник GitLab OAuth" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Sources" +msgstr "Источники GitLab OAuth" + +#: authentik/sources/oauth/models.py +msgid "Twitch OAuth Source" +msgstr "Источник Twitch OAuth" + +#: authentik/sources/oauth/models.py +msgid "Twitch OAuth Sources" +msgstr "Источники Twitch OAuth" + +#: authentik/sources/oauth/models.py +msgid "Mailcow OAuth Source" +msgstr "Источник Mailcow OAuth" + +#: authentik/sources/oauth/models.py +msgid "Mailcow OAuth Sources" +msgstr "Источники Mailcow OAuth" + +#: authentik/sources/oauth/models.py +msgid "Twitter OAuth Source" +msgstr "Источник Twitter OAuth" + +#: authentik/sources/oauth/models.py +msgid "Twitter OAuth Sources" +msgstr "Источники Twitter OAuth" + +#: authentik/sources/oauth/models.py +msgid "Facebook OAuth Source" +msgstr "Источник Facebook OAuth" + +#: authentik/sources/oauth/models.py +msgid "Facebook OAuth Sources" +msgstr "Источники Facebook OAuth" + +#: authentik/sources/oauth/models.py +msgid "Discord OAuth Source" +msgstr "Источник Discord OAuth" + +#: authentik/sources/oauth/models.py +msgid "Discord OAuth Sources" +msgstr "Источники Discord OAuth" + +#: authentik/sources/oauth/models.py +msgid "Patreon OAuth Source" +msgstr "Источник Patreon OAuth" + +#: authentik/sources/oauth/models.py +msgid "Patreon OAuth Sources" +msgstr "Источники Patreon OAuth" + +#: authentik/sources/oauth/models.py +msgid "Google OAuth Source" +msgstr "Источник Google OAuth" + +#: authentik/sources/oauth/models.py +msgid "Google OAuth Sources" +msgstr "Источники Google OAuth" + +#: authentik/sources/oauth/models.py +msgid "Azure AD OAuth Source" +msgstr "Источник Azure AD OAuth" + +#: authentik/sources/oauth/models.py +msgid "Azure AD OAuth Sources" +msgstr "Источники Azure AD OAuth" + +#: authentik/sources/oauth/models.py +msgid "OpenID OAuth Source" +msgstr "Источник OpenID OAuth" + +#: authentik/sources/oauth/models.py +msgid "OpenID OAuth Sources" +msgstr "Источники OpenID OAuth" + +#: authentik/sources/oauth/models.py +msgid "Apple OAuth Source" +msgstr "Источник Apple OAuth" + +#: authentik/sources/oauth/models.py +msgid "Apple OAuth Sources" +msgstr "Источники Apple OAuth" + +#: authentik/sources/oauth/models.py +msgid "Okta OAuth Source" +msgstr "Источник Okta OAuth" + +#: authentik/sources/oauth/models.py +msgid "Okta OAuth Sources" +msgstr "Источники Okta OAuth" + +#: authentik/sources/oauth/models.py +msgid "Reddit OAuth Source" +msgstr "Источник Reddit OAuth" + +#: authentik/sources/oauth/models.py +msgid "Reddit OAuth Sources" +msgstr "Источники Reddit OAuth" + +#: authentik/sources/oauth/models.py +msgid "User OAuth Source Connection" +msgstr "Пользовательское подключение к источнику OAuth" + +#: authentik/sources/oauth/models.py +msgid "User OAuth Source Connections" +msgstr "Пользовательские подключения к источнику OAuth" + +#: authentik/sources/oauth/views/callback.py +#, python-brace-format +msgid "Authentication failed: {reason}" +msgstr "Аутентификация не удалась: {reason}" + +#: authentik/sources/plex/models.py +msgid "Client identifier used to talk to Plex." +msgstr "Идентификатор клиента, используемый для связи с Plex." + +#: authentik/sources/plex/models.py +msgid "" +"Which servers a user has to be a member of to be granted access. Empty list " +"allows every server." +msgstr "" +"К каким серверам должен принадлежать пользователь, чтобы получить доступ. " +"Пустой список разрешает доступ к каждому серверу." + +#: authentik/sources/plex/models.py +msgid "Allow friends to authenticate, even if you don't share a server." +msgstr "" +"Разрешить друзьям аутентифицироваться, даже если Вы не разделяете сервер." + +#: authentik/sources/plex/models.py +msgid "Plex token used to check friends" +msgstr "Токен Plex, используемый для проверки друзей" + +#: authentik/sources/plex/models.py +msgid "Plex Source" +msgstr "Источник Plex" + +#: authentik/sources/plex/models.py +msgid "Plex Sources" +msgstr "Источники Plex" + +#: authentik/sources/plex/models.py +msgid "User Plex Source Connection" +msgstr "Пользовательское подключение к источнику Plex" + +#: authentik/sources/plex/models.py +msgid "User Plex Source Connections" +msgstr "Пользовательские подключения к источнику Plex" + +#: authentik/sources/saml/models.py +msgid "Redirect Binding" +msgstr "Привязка переадресации" + +#: authentik/sources/saml/models.py +msgid "POST Binding" +msgstr "Привязка POST" + +#: authentik/sources/saml/models.py +msgid "POST Binding with auto-confirmation" +msgstr "Привязка POST с автоматическим подтверждением" + +#: authentik/sources/saml/models.py +msgid "Flow used before authentication." +msgstr "Поток, используемый перед аутентификацией." + +#: authentik/sources/saml/models.py +msgid "Issuer" +msgstr "Издатель" + +#: authentik/sources/saml/models.py +msgid "Also known as Entity ID. Defaults the Metadata URL." +msgstr "" +"Также известен как ID сущности. По умолчанию используется URL-адрес " +"метаданных." + +#: authentik/sources/saml/models.py +msgid "SSO URL" +msgstr "SSO URL-адрес" + +#: authentik/sources/saml/models.py +msgid "URL that the initial Login request is sent to." +msgstr "" +"URL-адрес, на который отправляется первоначальный запрос на вход в систему." + +#: authentik/sources/saml/models.py +msgid "SLO URL" +msgstr "SLO URL-адрес" + +#: authentik/sources/saml/models.py +msgid "Optional URL if your IDP supports Single-Logout." +msgstr "Необязательный URL-адрес, если ваш IDP поддерживает Single-Logout." + +#: authentik/sources/saml/models.py +msgid "" +"Allows authentication flows initiated by the IdP. This can be a security " +"risk, as no validation of the request ID is done." +msgstr "" +"Разрешает потоки аутентификации, инициированные IdP. Это может представлять " +"угрозу безопасности, так как проверка идентификатора запроса не " +"производится." + +#: authentik/sources/saml/models.py +msgid "" +"NameID Policy sent to the IdP. Can be unset, in which case no Policy is " +"sent." +msgstr "" +"NameID Политика, отправляемая IdP. Может быть не установлена, в этом случае " +"политика не отправляется." + +#: authentik/sources/saml/models.py +msgid "Delete temporary users after" +msgstr "Удалите временных пользователей после" + +#: authentik/sources/saml/models.py +msgid "" +"Time offset when temporary users should be deleted. This only applies if " +"your IDP uses the NameID Format 'transient', and the user doesn't log out " +"manually. (Format: hours=1;minutes=2;seconds=3)." +msgstr "" +"Временной интервал, когда временные пользователи должны быть удалены. " +"Применяется только в том случае, если ваш IDP использует формат NameID " +"'transient', и пользователь не выходит из системы вручную. (Формат: " +"hours=1;minutes=2;seconds=3)." + +#: authentik/sources/saml/models.py +msgid "" +"Keypair used to sign outgoing Responses going to the Identity Provider." +msgstr "" +"Пара ключей, используемая для подписи исходящих ответов, направляемых " +"провайдеру идентификационных данных." + +#: authentik/sources/saml/models.py +msgid "SAML Source" +msgstr "Источник SAML" + +#: authentik/sources/saml/models.py +msgid "SAML Sources" +msgstr "Источники SAML" + +#: authentik/sources/saml/models.py +msgid "User SAML Source Connection" +msgstr "Пользовательское подключение к источнику SAML" + +#: authentik/sources/saml/models.py +msgid "User SAML Source Connections" +msgstr "Пользовательские подключения к источнику SAML" + +#: authentik/sources/scim/models.py +msgid "SCIM Source" +msgstr "Источник SCIM" + +#: authentik/sources/scim/models.py +msgid "SCIM Sources" +msgstr "Источники SCIM" + +#: authentik/stages/authenticator_duo/models.py +msgid "Duo Authenticator Setup Stage" +msgstr "Этап настройки аутентификатора Duo" + +#: authentik/stages/authenticator_duo/models.py +msgid "Duo Authenticator Setup Stages" +msgstr "Этапы настройки аутентификатора Duo" + +#: authentik/stages/authenticator_duo/models.py +msgid "Duo Device" +msgstr "Устройство Duo" + +#: authentik/stages/authenticator_duo/models.py +msgid "Duo Devices" +msgstr "Устройства Duo" + +#: authentik/stages/authenticator_sms/models.py +msgid "" +"When enabled, the Phone number is only used during enrollment to verify the " +"users authenticity. Only a hash of the phone number is saved to ensure it is" +" not reused in the future." +msgstr "" +"Если эта функция включена, номер телефона используется только во время " +"регистрации для проверки подлинности пользователя. Сохраняется только хэш " +"номера телефона, чтобы исключить его повторное использование в будущем." + +#: authentik/stages/authenticator_sms/models.py +msgid "Optionally modify the payload being sent to custom providers." +msgstr "" +"По желанию измените данные, отправляемые пользовательским провайдерам." + +#: authentik/stages/authenticator_sms/models.py +#, python-brace-format +msgid "Use this code to authenticate in authentik: {token}" +msgstr "Используйте этот код для аутентификации в authentik: {token}" + +#: authentik/stages/authenticator_sms/models.py +msgid "SMS Authenticator Setup Stage" +msgstr "Этап настройки SMS-аутентификатора" + +#: authentik/stages/authenticator_sms/models.py +msgid "SMS Authenticator Setup Stages" +msgstr "Этапы настройки SMS-аутентификатора" + +#: authentik/stages/authenticator_sms/models.py +msgid "SMS Device" +msgstr "СМС устройство" + +#: authentik/stages/authenticator_sms/models.py +msgid "SMS Devices" +msgstr "СМС устройства" + +#: authentik/stages/authenticator_sms/stage.py +#: authentik/stages/authenticator_totp/stage.py +msgid "Code does not match" +msgstr "Код не соответствует" + +#: authentik/stages/authenticator_sms/stage.py +msgid "Invalid phone number" +msgstr "Невереый номер телефона" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Authenticator Setup Stage" +msgstr "Этап настройки статического аутентификатора" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Authenticator Setup Stages" +msgstr "Этапы настройки статического аутентификатора" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Device" +msgstr "Статическое устройство" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Devices" +msgstr "Статические устройства" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Token" +msgstr "Статический токен" + +#: authentik/stages/authenticator_static/models.py +msgid "Static Tokens" +msgstr "Статические токены" + +#: authentik/stages/authenticator_totp/models.py +msgid "6 digits, widely compatible" +msgstr "6 цифр, широкая совместимость" + +#: authentik/stages/authenticator_totp/models.py +msgid "8 digits, not compatible with apps like Google Authenticator" +msgstr "8 цифр, не совместим с такими приложениями, как Google Authenticator" + +#: authentik/stages/authenticator_totp/models.py +msgid "TOTP Authenticator Setup Stage" +msgstr "Этап настройки аутентификатора TOTP" + +#: authentik/stages/authenticator_totp/models.py +msgid "TOTP Authenticator Setup Stages" +msgstr "Этапы настройки аутентификатора TOTP" + +#: authentik/stages/authenticator_totp/models.py +msgid "TOTP Device" +msgstr "Устройство TOTP" + +#: authentik/stages/authenticator_totp/models.py +msgid "TOTP Devices" +msgstr "Устройства TOTP" + +#: authentik/stages/authenticator_validate/challenge.py +msgid "" +"Invalid Token. Please ensure the time on your device is accurate and try " +"again." +msgstr "" +"Недействительный токен. Убедитесь, что время на вашем устройстве указано " +"точно, и повторите попытку." + +#: authentik/stages/authenticator_validate/challenge.py +#: authentik/stages/authenticator_webauthn/stage.py +#, python-brace-format +msgid "Invalid device type. Contact your {brand} administrator for help." +msgstr "" +"Неверный тип устройства. Обратитесь за помощью к администратору {brand}." + +#: authentik/stages/authenticator_validate/models.py +msgid "Static" +msgstr "Статический" + +#: authentik/stages/authenticator_validate/models.py +msgid "TOTP" +msgstr "TOTP" + +#: authentik/stages/authenticator_validate/models.py +msgid "WebAuthn" +msgstr "WebAuthn" + +#: authentik/stages/authenticator_validate/models.py +msgid "Duo" +msgstr "Duo" + +#: authentik/stages/authenticator_validate/models.py +msgid "SMS" +msgstr "СМС" + +#: authentik/stages/authenticator_validate/models.py +msgid "" +"Stages used to configure Authenticator when user doesn't have any compatible" +" devices. After this configuration Stage passes, the user is not prompted " +"again." +msgstr "" +"Этапы использованные для конфигурации Аутентификатора когда у пользователя " +"нет совместимых устройств. После этого конфигурационного этапа пользователю " +"больше не запрашивается." + +#: authentik/stages/authenticator_validate/models.py +msgid "Device classes which can be used to authenticate" +msgstr "Классы устройств, которые можно использовать для аутентификации" + +#: authentik/stages/authenticator_validate/models.py +msgid "" +"If any of the user's device has been used within this threshold, this stage " +"will be skipped" +msgstr "" +"Если какое-либо из устройств пользователя использовалось в пределах этого " +"порога, этот этап будет пропущен" + +#: authentik/stages/authenticator_validate/models.py +msgid "Enforce user verification for WebAuthn devices." +msgstr "Обеспечить проверку пользователей для устройств WebAuthn." + +#: authentik/stages/authenticator_validate/models.py +msgid "Authenticator Validation Stage" +msgstr "Этап проверки аутентификатора" + +#: authentik/stages/authenticator_validate/models.py +msgid "Authenticator Validation Stages" +msgstr "Этапы проверки аутентификатора" + +#: authentik/stages/authenticator_validate/stage.py +msgid "No (allowed) MFA authenticator configured." +msgstr "Не сконфигурирован ни один (разрешенный) MFA аутентификатор" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Authenticator Setup Stage" +msgstr "Этап настройки аутентификатора WebAuthn" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Authenticator Setup Stages" +msgstr "Этапы настройки аутентификатора WebAuthn" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device" +msgstr "WebAuthn Устройство" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Devices" +msgstr "WebAuthn Устройства" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device type" +msgstr "Тип устройства WebAuthn" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device types" +msgstr "Типы устройств WebAuthn" + +#: authentik/stages/captcha/models.py +msgid "Public key, acquired your captcha Provider." +msgstr "Открытый ключ, полученный от вашего провайдера капчи." + +#: authentik/stages/captcha/models.py +msgid "Private key, acquired your captcha Provider." +msgstr "Закрытый ключ, полученный от вашего провайдера капчи." + +#: authentik/stages/captcha/models.py +msgid "Captcha Stage" +msgstr "Этап с каптчей" + +#: authentik/stages/captcha/models.py +msgid "Captcha Stages" +msgstr "Этапы с каптчей" + +#: authentik/stages/consent/models.py +msgid "" +"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." +msgstr "" +"Смещение, после которого истекает срок действия согласия. (Формат: " +"hours=1;minutes=2;seconds=3)." + +#: authentik/stages/consent/models.py +msgid "Consent Stage" +msgstr "Этап согласия" + +#: authentik/stages/consent/models.py +msgid "Consent Stages" +msgstr "Этапы согласия" + +#: authentik/stages/consent/models.py +msgid "User Consent" +msgstr "Согласие пользователя" + +#: authentik/stages/consent/models.py +msgid "User Consents" +msgstr "Согласия пользователя" + +#: authentik/stages/deny/models.py +msgid "Deny Stage" +msgstr "Этап отказа" + +#: authentik/stages/deny/models.py +msgid "Deny Stages" +msgstr "Этапы отказа" + +#: authentik/stages/dummy/models.py +msgid "Dummy Stage" +msgstr "Фиктивный этап" + +#: authentik/stages/dummy/models.py +msgid "Dummy Stages" +msgstr "Фиктивные этапы" + +#: authentik/stages/email/models.py +msgid "Password Reset" +msgstr "Сброс пароля" + +#: authentik/stages/email/models.py +msgid "Account Confirmation" +msgstr "Подтверждение аккаунта" + +#: authentik/stages/email/models.py +msgid "" +"When enabled, global Email connection settings will be used and connection " +"settings below will be ignored." +msgstr "" +"Если эта функция включена, будут использоваться глобальные настройки " +"подключения к электронной почте, а настройки подключения, указанные ниже, " +"будут игнорироваться." + +#: authentik/stages/email/models.py +msgid "Activate users upon completion of stage." +msgstr "Активировать пользователей по завершении этапа." + +#: authentik/stages/email/models.py +msgid "Time in minutes the token sent is valid." +msgstr "Время валидности отправленного токена в минутах." + +#: authentik/stages/email/models.py +msgid "Email Stage" +msgstr "Этап электронной почты" + +#: authentik/stages/email/models.py +msgid "Email Stages" +msgstr "Этапы электронной почты" + +#: authentik/stages/email/stage.py +msgid "Exception occurred while rendering E-mail template" +msgstr "Возникло исключение при рендеринге шаблона электронной почты" + +#: authentik/stages/email/stage.py +msgid "Successfully verified Email." +msgstr "Почта успешно подтверждена." + +#: authentik/stages/email/stage.py +msgid "No pending user." +msgstr "Нет ожидающих пользователей." + +#: authentik/stages/email/stage.py +msgid "Email sent." +msgstr "Письмо отправлено." + +#: authentik/stages/email/stage.py +msgid "Email Successfully sent." +msgstr "Письмо успешно отправлено." + +#: authentik/stages/email/templates/email/account_confirmation.html +#: authentik/stages/email/templates/email/account_confirmation.txt +msgid "Welcome!" +msgstr "Добро пожаловать!" + +#: authentik/stages/email/templates/email/account_confirmation.html +msgid "" +"We're excited to have you get started. First, you need to confirm your " +"account. Just press the button below." +msgstr "" +"Мы рады помочь Вам начать. Сперва Вы должны подтвердить свой аккаунт. Просто" +" нажмите на кнопку ниже." + +#: authentik/stages/email/templates/email/account_confirmation.html +msgid "Confirm Account" +msgstr "Подтвердить аккаунт" + +#: authentik/stages/email/templates/email/account_confirmation.html +#, python-format +msgid "" +"\n" +" If that doesn't work, copy and paste the following link in your browser: %(url)s\n" +" " +msgstr "" +"\n" +" Если это не работает, скопируйте и вставьте следующую ссылку в ваш браузер: %(url)s\n" +" " + +#: authentik/stages/email/templates/email/account_confirmation.txt +msgid "" +"We're excited to have you get started. First, you need to confirm your " +"account. Just open the link below." +msgstr "" +"Мы с нетерпением ждем, когда вы приступите к работе. Сначала вам нужно " +"подтвердить свою учетную запись. Просто откройте ссылку ниже." + +#: authentik/stages/email/templates/email/event_notification.html +#, python-format +msgid "" +"\n" +" This email was sent from the notification transport %(name)s.\n" +" " +msgstr "" +"\n" +" Это письмо было отправлено с помощью поставщика уведомления %(name)s.\n" +" " + +#: authentik/stages/email/templates/email/event_notification.txt +msgid "Dear authentik user," +msgstr "Уважаемый пользователь authentik," + +#: authentik/stages/email/templates/email/event_notification.txt +msgid "The following notification was created:" +msgstr "Было создано следующее уведомление:" + +#: authentik/stages/email/templates/email/event_notification.txt +msgid "Additional attributes:" +msgstr "Дополнительные атрибуты:" + +#: authentik/stages/email/templates/email/event_notification.txt +#, python-format +msgid "" +"\n" +"This email was sent from the notification transport %(name)s.\n" +msgstr "" +"\n" +"Это письмо было отправлено с помощью поставщика уведомления %(name)s.\n" + +#: authentik/stages/email/templates/email/password_reset.html +#, python-format +msgid "" +"\n" +" Hi %(username)s,\n" +" " +msgstr "" +"\n" +" Привет %(username)s,\n" +" " + +#: authentik/stages/email/templates/email/password_reset.html +msgid "" +"\n" +" You recently requested to change your password for your authentik account. Use the button below to set a new password.\n" +" " +msgstr "" +"\n" +" Вы недавно запросили изменение пароля для вашей учетной записи authentik. Воспользуйтесь кнопкой ниже, чтобы установить новый пароль.\n" +" " + +#: authentik/stages/email/templates/email/password_reset.html +#, python-format +msgid "" +"\n" +" If you did not request a password change, please ignore this Email. The link above is valid for %(expires)s.\n" +" " +msgstr "" +"\n" +" Если вы не запрашивали смену пароля, проигнорируйте это письмо. Приведенная выше ссылка действительна до %(expires)s.\n" +" " + +#: authentik/stages/email/templates/email/password_reset.txt +#, python-format +msgid "Hi %(username)s," +msgstr "Привет %(username)s," + +#: authentik/stages/email/templates/email/password_reset.txt +msgid "" +"\n" +"You recently requested to change your password for your authentik account. Use the link below to set a new password.\n" +msgstr "" +"\n" +"Вы недавно запросили изменение пароля для вашей учетной записи authentik. Воспользуйтесь приведенной ниже ссылкой, чтобы установить новый пароль.\n" + +#: authentik/stages/email/templates/email/password_reset.txt +#, python-format +msgid "" +"\n" +"If you did not request a password change, please ignore this Email. The link above is valid for %(expires)s.\n" +msgstr "" +"\n" +"Если вы не запрашивали смену пароля, проигнорируйте это письмо. Приведенная выше ссылка действительна до %(expires)s.\n" + +#: authentik/stages/email/templates/email/setup.html +msgid "authentik Test-Email" +msgstr "Тест-почта authentik" + +#: authentik/stages/email/templates/email/setup.html +msgid "" +"\n" +" This is a test email to inform you, that you've successfully configured authentik emails.\n" +" " +msgstr "" +"\n" +" Это тестовое письмо, чтобы сообщить вам, что вы успешно настроили электронную почту для authentik.\n" +" " + +#: authentik/stages/email/templates/email/setup.txt +msgid "" +"\n" +"This is a test email to inform you, that you've successfully configured authentik emails.\n" +msgstr "" +"\n" +"Это тестовое письмо, чтобы сообщить вам, что вы успешно настроили электронную почту для authentik.\n" + +#: authentik/stages/identification/api.py +msgid "When no user fields are selected, at least one source must be selected" +msgstr "" +"Если пользовательские поля не выбраны, необходимо выбрать хотя бы один " +"источник" + +#: authentik/stages/identification/models.py +msgid "" +"Fields of the user object to match against. (Hold shift to select multiple " +"options)" +msgstr "" +"Поля пользовательского объекта для соответствия. (Удерживайте shift, чтобы " +"выбрать несколько вариантов)" + +#: authentik/stages/identification/models.py +msgid "When enabled, user fields are matched regardless of their casing." +msgstr "" +"Когда включено, поля пользователя сопоставляются независимо от регистра." + +#: authentik/stages/identification/models.py +msgid "" +"When a valid username/email has been entered, and this option is enabled, " +"the user's username and avatar will be shown. Otherwise, the text that the " +"user entered will be shown" +msgstr "" +"Если введено правильное имя пользователя/электронная почта и эта опция " +"включена, будет показано имя пользователя и аватар. В противном случае будет" +" показан текст, который ввел пользователь" + +#: authentik/stages/identification/models.py +msgid "" +"When enabled, the stage will succeed and continue even when incorrect user " +"info is entered." +msgstr "" +"При включении этап будет завершаться успешно и продолжаться даже в случае " +"ввода неправильной информации о пользователе." + +#: authentik/stages/identification/models.py +msgid "Optional enrollment flow, which is linked at the bottom of the page." +msgstr "" +"Дополнительный поток регистрации, ссылка на который находится в нижней части" +" страницы." + +#: authentik/stages/identification/models.py +msgid "Optional recovery flow, which is linked at the bottom of the page." +msgstr "" +"Дополнительный поток восстановления доступа, ссылка на который находится в " +"нижней части страницы." + +#: authentik/stages/identification/models.py +msgid "Optional passwordless flow, which is linked at the bottom of the page." +msgstr "" +"Дополнительный беспарольный поток, ссылка на который находится в нижней " +"части страницы." + +#: authentik/stages/identification/models.py +msgid "Specify which sources should be shown." +msgstr "Укажите, какие источники должны отображаться." + +#: authentik/stages/identification/models.py +msgid "Identification Stage" +msgstr "Этап идентификации" + +#: authentik/stages/identification/models.py +msgid "Identification Stages" +msgstr "Этапы идентификации" + +#: authentik/stages/identification/stage.py +msgid "Log in" +msgstr "Войти" + +#: authentik/stages/identification/stage.py +msgid "Continue" +msgstr "Продолжить" + +#: authentik/stages/invitation/models.py +msgid "" +"If this flag is set, this Stage will jump to the next Stage when no " +"Invitation is given. By default this Stage will cancel the Flow when no " +"invitation is given." +msgstr "" +"Если этот флаг установлен, то при отсутствии приглашения этот этап перейдет " +"к следующему этапу. По умолчанию этот этап отменяет поток, если приглашение " +"не получено." + +#: authentik/stages/invitation/models.py +msgid "Invitation Stage" +msgstr "Этап приглашения" + +#: authentik/stages/invitation/models.py +msgid "Invitation Stages" +msgstr "Этапы приглашения" + +#: authentik/stages/invitation/models.py +msgid "When set, only the configured flow can use this invitation." +msgstr "" +"Если установлено, только настроенный поток может использовать это " +"приглашение." + +#: authentik/stages/invitation/models.py +msgid "When enabled, the invitation will be deleted after usage." +msgstr "" +"Если эта опция включена, приглашение будет удалено после использования." + +#: authentik/stages/invitation/models.py +msgid "Optional fixed data to enforce on user enrollment." +msgstr "" +"Необязательные фиксированные данные, которые будут применяться при " +"регистрации пользователя." + +#: authentik/stages/invitation/models.py +msgid "Invitation" +msgstr "Приглашение" + +#: authentik/stages/invitation/models.py +msgid "Invitations" +msgstr "Приглашения" + +#: authentik/stages/invitation/stage.py +msgid "Invalid invite/invite not found" +msgstr "Неверное приглашение/приглашение не найдено" + +#: authentik/stages/password/models.py +msgid "User database + standard password" +msgstr "База данных пользователей + стандартный пароль" + +#: authentik/stages/password/models.py +msgid "User database + app passwords" +msgstr "База данных пользователей + пароли приложения" + +#: authentik/stages/password/models.py +msgid "User database + LDAP password" +msgstr "База данных пользователей + пароль LDAP" + +#: authentik/stages/password/models.py +msgid "Selection of backends to test the password against." +msgstr "Выбор бэкендов для проверки пароля." + +#: authentik/stages/password/models.py +msgid "" +"How many attempts a user has before the flow is canceled. To lock the user " +"out, use a reputation policy and a user_write stage." +msgstr "" +"Количество попыток пользователя до отмены потока. Чтобы заблокировать " +"пользователя, используйте политику репутации и этап user_write." + +#: authentik/stages/password/models.py +msgid "Password Stage" +msgstr "Этап пароля" + +#: authentik/stages/password/models.py +msgid "Password Stages" +msgstr "Этапы пароля" + +#: authentik/stages/password/stage.py +msgid "Invalid password" +msgstr "Неверный пароль" + +#: authentik/stages/prompt/models.py +msgid "Text: Simple Text input" +msgstr "Текст: простой текстовый ввод" + +#: authentik/stages/prompt/models.py +msgid "Text area: Multiline Text Input." +msgstr "Текстовая область: Многострочный текстовый ввод." + +#: authentik/stages/prompt/models.py +msgid "Text (read-only): Simple Text input, but cannot be edited." +msgstr "" +"Текст (только для чтения): Простой текстовый ввод, который нельзя " +"редактировать." + +#: authentik/stages/prompt/models.py +msgid "Text area (read-only): Multiline Text input, but cannot be edited." +msgstr "" +"Текстовая область (только для чтения): Многострочный текстовый ввод, который" +" нельзя редактировать." + +#: authentik/stages/prompt/models.py +msgid "" +"Username: Same as Text input, but checks for and prevents duplicate " +"usernames." +msgstr "" +"Имя пользователя: Аналогично вводу текста, но проверяет и предотвращает " +"дублирование имен пользователей." + +#: authentik/stages/prompt/models.py +msgid "Email: Text field with Email type." +msgstr "Email: Текстовое поле с типом Email." + +#: authentik/stages/prompt/models.py +msgid "" +"Password: Masked input, multiple inputs of this type on the same prompt need" +" to be identical." +msgstr "" +"Пароль: маскируемый ввод, несколько вводов этого типа в одном этапе должны " +"быть идентичными." + +#: authentik/stages/prompt/models.py +msgid "Fixed choice field rendered as a group of radio buttons." +msgstr "Фиксированное поле выбора отображаемое в виде группы радио кнопок." + +#: authentik/stages/prompt/models.py +msgid "Fixed choice field rendered as a dropdown." +msgstr "Фиксированное поле выбора отображаемое в виде выпадающего списка." + +#: authentik/stages/prompt/models.py +msgid "" +"File: File upload for arbitrary files. File content will be available in " +"flow context as data-URI" +msgstr "" +"Файл: загрузка произвольных файлов. Содержимое файла будет доступно в " +"контексте потока как data-URI" + +#: authentik/stages/prompt/models.py +msgid "Separator: Static Separator Line" +msgstr "Разделитель: Статическая разделительная линия" + +#: authentik/stages/prompt/models.py +msgid "Hidden: Hidden field, can be used to insert data into form." +msgstr "" +"Скрытый: Скрытое поле, может быть использовано для вставки данных в форму." + +#: authentik/stages/prompt/models.py +msgid "Static: Static value, displayed as-is." +msgstr "Статический: Статичное значение, отображается как есть." + +#: authentik/stages/prompt/models.py +msgid "authentik: Selection of locales authentik supports" +msgstr "authentik: Выбор локализаций, которые поддерживает authentik" + +#: authentik/stages/prompt/models.py +msgid "Name of the form field, also used to store the value" +msgstr "Имя поля формы, также используемое для хранения значения" + +#: authentik/stages/prompt/models.py +msgid "" +"Optionally provide a short hint that describes the expected input value. " +"When creating a fixed choice field, enable interpreting as expression and " +"return a list to return multiple choices." +msgstr "" +"По желанию предоставьте короткую подсказку, описывающую ожидаемое значение " +"ввода. При создании поля с фиксированным выбором включите интерпретацию как " +"выражения и возвращайте список, чтобы вернуть несколько вариантов." + +#: authentik/stages/prompt/models.py +msgid "" +"Optionally pre-fill the input with an initial value. When creating a fixed " +"choice field, enable interpreting as expression and return a list to return " +"multiple default choices." +msgstr "" +"По желанию предварительно заполните поле ввода начальным значением. При " +"создании поля с фиксированным выбором включите интерпретацию как выражение и" +" возврат списка, чтобы вернуть несколько вариантов по умолчанию." + +#: authentik/stages/prompt/models.py +msgid "Prompt" +msgstr "Запрос" + +#: authentik/stages/prompt/models.py +msgid "Prompts" +msgstr "Запросы" + +#: authentik/stages/prompt/models.py +msgid "Prompt Stage" +msgstr "Этап запроса" + +#: authentik/stages/prompt/models.py +msgid "Prompt Stages" +msgstr "Этапы запроса" + +#: authentik/stages/prompt/stage.py +msgid "Passwords don't match." +msgstr "Пароли не соответствуют." + +#: authentik/stages/user_delete/models.py +msgid "User Delete Stage" +msgstr "Этап удаления пользователя" + +#: authentik/stages/user_delete/models.py +msgid "User Delete Stages" +msgstr "Этапы удаления пользователя" + +#: authentik/stages/user_delete/stage.py +msgid "No Pending User." +msgstr "Нет входящих пользователей." + +#: authentik/stages/user_login/models.py +msgid "Bind sessions created by this stage to the configured network" +msgstr "Привяжите сеансы, созданные на этом этапе, к настроенной сети" + +#: authentik/stages/user_login/models.py +msgid "Bind sessions created by this stage to the configured GeoIP location" +msgstr "" +"Привяжите сеансы, созданные на этом этапе, к настроенному местоположению " +"GeoIP" + +#: authentik/stages/user_login/models.py +msgid "Terminate all other sessions of the user logging in." +msgstr "Завершить все другие сессии заходящего пользователя." + +#: authentik/stages/user_login/models.py +msgid "" +"Offset the session will be extended by when the user picks the remember me " +"option. Default of 0 means that the remember me option will not be shown. " +"(Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "" +"Смещение, на которое будет продлена сессия, когда пользователь выберет опцию" +" \"Запомнить меня\". Значение по умолчанию 0 означает, что опция \"Запомнить" +" меня\" не будет отображаться. (Формат: hours=-1;minutes=-2;seconds=-3)" + +#: authentik/stages/user_login/models.py +msgid "User Login Stage" +msgstr "Этап входа пользователя" + +#: authentik/stages/user_login/models.py +msgid "User Login Stages" +msgstr "Этапы входа пользователя" + +#: authentik/stages/user_login/stage.py +msgid "No Pending user to login." +msgstr "Нет входящих пользователей для входа." + +#: authentik/stages/user_login/stage.py +msgid "Successfully logged in!" +msgstr "Успешный вход в аккаунт!" + +#: authentik/stages/user_logout/models.py +msgid "User Logout Stage" +msgstr "Этап выхода пользователя" + +#: authentik/stages/user_logout/models.py +msgid "User Logout Stages" +msgstr "Этапы выхода пользователя" + +#: authentik/stages/user_write/models.py +msgid "When set, newly created users are inactive and cannot login." +msgstr "" +"Когда установлено, только что созданные пользователи неактивны и не могут " +"войти." + +#: authentik/stages/user_write/models.py +msgid "Optionally add newly created users to this group." +msgstr "По желанию добавьте в эту группу вновь созданных пользователей." + +#: authentik/stages/user_write/models.py +msgid "User Write Stage" +msgstr "Этап записи пользователя" + +#: authentik/stages/user_write/models.py +msgid "User Write Stages" +msgstr "Этапы записи пользователя" + +#: authentik/stages/user_write/stage.py +msgid "No Pending data." +msgstr "Нет входящих данных." + +#: authentik/stages/user_write/stage.py +msgid "No user found and can't create new user." +msgstr "Пользователь не найден и невозможно создать нового пользователя." + +#: authentik/stages/user_write/stage.py +msgid "Failed to update user. Please try again later." +msgstr "Не удалось обновить пользователя. Попробуйте позже." + +#: authentik/tenants/models.py +msgid "" +"Schema name must start with t_, only contain lowercase letters and numbers " +"and be less than 63 characters." +msgstr "" +"Имя схемы должно начинаться с t_, содержать только строчные буквы и цифры и " +"не превышать 63 символов." + +#: authentik/tenants/models.py +msgid "Configure how authentik should show avatars for users." +msgstr "Настройте, как authentik должен показывать аватары для пользователей." + +#: authentik/tenants/models.py +msgid "Enable the ability for users to change their name." +msgstr "Включение возможности изменения пользователями своего имени." + +#: authentik/tenants/models.py +msgid "Enable the ability for users to change their email address." +msgstr "" +"Включение возможности для пользователей изменять свой адрес электронной " +"почты." + +#: authentik/tenants/models.py +msgid "Enable the ability for users to change their username." +msgstr "" +"Включение возможности изменения пользователями своего имени пользователя" + +#: authentik/tenants/models.py +msgid "" +"Events will be deleted after this duration.(Format: " +"weeks=3;days=2;hours=3,seconds=2)." +msgstr "" +"По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; " +"часы=3, секунды=2)." + +#: authentik/tenants/models.py +msgid "The option configures the footer links on the flow executor pages." +msgstr "" +"Опция настраивает ссылки нижнего колонтитула на страницах исполнителя " +"потока." + +#: authentik/tenants/models.py +msgid "" +"When enabled, all the events caused by a user will be deleted upon the " +"user's deletion." +msgstr "" +"Если эта опция включена, все события, вызванные пользователем, будут удалены" +" после его удаления." + +#: authentik/tenants/models.py +msgid "Globally enable/disable impersonation." +msgstr "Глобально включить/отключить имитацию пользователей." + +#: authentik/tenants/models.py +msgid "Default token duration" +msgstr "Срок действия токена по умолчанию" + +#: authentik/tenants/models.py +msgid "Default token length" +msgstr "Длина токена по умолчанию" + +#: authentik/tenants/models.py +msgid "Tenant" +msgstr "Арендатор" + +#: authentik/tenants/models.py +msgid "Tenants" +msgstr "Арендаторы" + +#: authentik/tenants/models.py +msgid "Domain" +msgstr "Домен" + +#: authentik/tenants/models.py +msgid "Domains" +msgstr "Домены" diff --git a/locale/zh-Hans/LC_MESSAGES/django.mo b/locale/zh-Hans/LC_MESSAGES/django.mo index d9e5e2ac31..61d564ee08 100644 Binary files a/locale/zh-Hans/LC_MESSAGES/django.mo and b/locale/zh-Hans/LC_MESSAGES/django.mo differ diff --git a/locale/zh-Hans/LC_MESSAGES/django.po b/locale/zh-Hans/LC_MESSAGES/django.po index b45d30549f..20039287b9 100644 --- a/locale/zh-Hans/LC_MESSAGES/django.po +++ b/locale/zh-Hans/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ # Translators: # Chen Zhikai, 2022 # 刘松, 2022 -# Jens L. , 2024 +# Jens L. , 2024 # deluxghost, 2024 # #, fuzzy @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-23 08:02+0000\n" +"POT-Creation-Date: 2024-05-23 00:07+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n" "Last-Translator: deluxghost, 2024\n" "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" @@ -24,37 +24,32 @@ msgstr "" "Language: zh-Hans\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: authentik/admin/api/tasks.py:127 -#, python-format -msgid "Successfully re-scheduled Task %(name)s!" -msgstr "已成功重新安排任务 %(name)s!" - -#: authentik/api/schema.py:25 +#: authentik/api/schema.py msgid "Generic API Error" msgstr "通用 API 错误" -#: authentik/api/schema.py:33 +#: authentik/api/schema.py msgid "Validation Error" msgstr "校验错误" -#: authentik/blueprints/api.py:43 +#: authentik/blueprints/api.py msgid "Blueprint file does not exist" msgstr "蓝图文件不存在" -#: authentik/blueprints/api.py:54 -#, python-format -msgid "Failed to validate blueprint: %(logs)s" -msgstr "验证蓝图失败:%(logs)s" +#: authentik/blueprints/api.py +#, python-brace-format +msgid "Failed to validate blueprint: {logs}" +msgstr "验证蓝图失败:{logs}" -#: authentik/blueprints/api.py:59 +#: authentik/blueprints/api.py msgid "Either path or content must be set." msgstr "必须设置路径或内容。" -#: authentik/blueprints/models.py:30 +#: authentik/blueprints/models.py msgid "Managed by authentik" msgstr "由 authentik 管理" -#: authentik/blueprints/models.py:32 +#: authentik/blueprints/models.py msgid "" "Objects that are managed by authentik. These objects are created and updated" " automatically. This flag only indicates that an object can be overwritten " @@ -64,248 +59,262 @@ msgstr "" "由 authentik 管理的对象。这些对象会自动创建和更新。此标记仅仅表明对象可以被 Migration 覆盖。您仍然可以通过 API " "修改对象,但这些修改可能会在之后的更新中被覆盖。" -#: authentik/blueprints/models.py:112 +#: authentik/blueprints/models.py msgid "Blueprint Instance" msgstr "蓝图实例" -#: authentik/blueprints/models.py:113 +#: authentik/blueprints/models.py msgid "Blueprint Instances" msgstr "蓝图实例" -#: authentik/blueprints/v1/exporter.py:62 -#, python-format -msgid "authentik Export - %(date)s" -msgstr "authentik 导出 - %(date)s" +#: authentik/blueprints/v1/exporter.py +#, python-brace-format +msgid "authentik Export - {date}" +msgstr "authentik 导出 - {date}" -#: authentik/blueprints/v1/tasks.py:151 authentik/crypto/tasks.py:93 +#: authentik/blueprints/v1/tasks.py authentik/crypto/tasks.py #, python-format msgid "Successfully imported %(count)d files." msgstr "已成功导入 %(count)d 个文件。" -#: authentik/brands/models.py:22 +#: authentik/brands/models.py msgid "" "Domain that activates this brand. Can be a superset, i.e. `a.b` for `aa.b` " "and `ba.b`" msgstr "激活此品牌的域。可以是超集,即 `a.b` 可以同时表示 `aa.b` 和 `ba.b`" -#: authentik/brands/models.py:58 +#: authentik/brands/models.py msgid "Web Certificate used by the authentik Core webserver." msgstr "authentik 核心 Web 服务器使用的 Web 证书。" -#: authentik/brands/models.py:84 +#: authentik/brands/models.py msgid "Brand" msgstr "品牌" -#: authentik/brands/models.py:85 +#: authentik/brands/models.py msgid "Brands" msgstr "品牌" -#: authentik/core/api/providers.py:122 -msgid "SAML Provider from Metadata" -msgstr "来自元数据的 SAML 提供程序" +#: authentik/core/api/providers.py +msgid "" +"When not set all providers are returned. When set to true, only backchannel " +"providers are returned. When set to false, backchannel providers are " +"excluded" +msgstr "如果未设置,则返回所有提供程序。如果启用,仅返回反向通道提供程序。如果禁用,则返回非反向通道提供程序" -#: authentik/core/api/providers.py:123 -msgid "Create a SAML Provider by importing its Metadata." -msgstr "通过导入元数据来创建 SAML 提供程序。" - -#: authentik/core/api/users.py:149 +#: authentik/core/api/users.py msgid "No leading or trailing slashes allowed." msgstr "不允许前缀或后缀斜线。" -#: authentik/core/api/users.py:152 +#: authentik/core/api/users.py msgid "No empty segments in user path allowed." msgstr "不允许用户路径包含空段。" -#: authentik/core/models.py:85 +#: authentik/core/models.py msgid "name" msgstr "名称" -#: authentik/core/models.py:87 +#: authentik/core/models.py msgid "Users added to this group will be superusers." msgstr "添加到该组的用户均为超级用户。" -#: authentik/core/models.py:161 +#: authentik/core/models.py msgid "Group" msgstr "组" -#: authentik/core/models.py:162 +#: authentik/core/models.py msgid "Groups" msgstr "组" -#: authentik/core/models.py:177 +#: authentik/core/models.py +msgid "Add user to group" +msgstr "添加用户到组" + +#: authentik/core/models.py +msgid "Remove user from group" +msgstr "从组中删除用户" + +#: authentik/core/models.py msgid "User's display name." msgstr "用户的显示名称。" -#: authentik/core/models.py:273 authentik/providers/oauth2/models.py:295 +#: authentik/core/models.py authentik/providers/oauth2/models.py msgid "User" msgstr "用户" -#: authentik/core/models.py:274 +#: authentik/core/models.py msgid "Users" msgstr "用户" -#: authentik/core/models.py:276 -#: authentik/stages/email/templates/email/password_reset.html:28 +#: authentik/core/models.py +#: authentik/stages/email/templates/email/password_reset.html msgid "Reset Password" msgstr "重置密码" -#: authentik/core/models.py:277 +#: authentik/core/models.py msgid "Can impersonate other users" msgstr "可以模拟其他用户的身份" -#: authentik/core/models.py:278 authentik/rbac/models.py:54 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can assign permissions to users" msgstr "可以为用户分配权限" -#: authentik/core/models.py:279 authentik/rbac/models.py:55 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can unassign permissions from users" msgstr "可以取消分配用户的权限" -#: authentik/core/models.py:293 +#: authentik/core/models.py +msgid "Can preview user data sent to providers" +msgstr "可以预览发送给提供程序的用户数据" + +#: authentik/core/models.py +msgid "View applications the user has access to" +msgstr "查看用户有权访问的应用程序" + +#: authentik/core/models.py msgid "" "Flow used for authentication when the associated application is accessed by " "an un-authenticated user." msgstr "当关联应用程序被未验证身份的用户访问时,用于身份验证的流程。" -#: authentik/core/models.py:303 +#: authentik/core/models.py msgid "Flow used when authorizing this provider." msgstr "授权此提供程序时使用的流程。" -#: authentik/core/models.py:315 +#: authentik/core/models.py msgid "" "Accessed from applications; optional backchannel providers for protocols " "like LDAP and SCIM." msgstr "从应用程序访问;为类似 LDAP 和 SCIM 的协议提供的可选反向通道提供程序。" -#: authentik/core/models.py:370 +#: authentik/core/models.py msgid "Application's display Name." msgstr "应用的显示名称。" -#: authentik/core/models.py:371 +#: authentik/core/models.py msgid "Internal application name, used in URLs." msgstr "应用的内部名称,在 URL 中使用。" -#: authentik/core/models.py:383 +#: authentik/core/models.py msgid "Open launch URL in a new browser tab or window." msgstr "在新浏览器标签页或窗口中打开启动 URL。" -#: authentik/core/models.py:447 +#: authentik/core/models.py msgid "Application" msgstr "应用程序" -#: authentik/core/models.py:448 +#: authentik/core/models.py msgid "Applications" msgstr "应用程序" -#: authentik/core/models.py:454 +#: authentik/core/models.py msgid "Use the source-specific identifier" msgstr "使用源特定的标识符" -#: authentik/core/models.py:456 +#: authentik/core/models.py msgid "" "Link to a user with identical email address. Can have security implications " "when a source doesn't validate email addresses." msgstr "链接到电子邮件地址相同的用户。当源不验证电子邮件地址时,可能会有安全隐患。" -#: authentik/core/models.py:460 +#: authentik/core/models.py msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." msgstr "使用用户的电子邮件地址,但在电子邮件地址已存在时拒绝注册。" -#: authentik/core/models.py:463 +#: authentik/core/models.py msgid "" "Link to a user with identical username. Can have security implications when " "a username is used with another source." msgstr "链接到用户名相同的用户。当其他源使用相同用户名时,可能会有安全隐患。" -#: authentik/core/models.py:467 +#: authentik/core/models.py msgid "" "Use the user's username, but deny enrollment when the username already " "exists." msgstr "使用用户的用户名,但在用户名已存在时拒绝注册。" -#: authentik/core/models.py:474 +#: authentik/core/models.py msgid "Source's display Name." msgstr "源的显示名称。" -#: authentik/core/models.py:475 +#: authentik/core/models.py msgid "Internal source name, used in URLs." msgstr "源的内部名称,在 URL 中使用。" -#: authentik/core/models.py:494 +#: authentik/core/models.py msgid "Flow to use when authenticating existing users." msgstr "认证已存在用户时所使用的流程。" -#: authentik/core/models.py:503 +#: authentik/core/models.py msgid "Flow to use when enrolling new users." msgstr "新用户注册的流程。" -#: authentik/core/models.py:511 +#: authentik/core/models.py msgid "" "How the source determines if an existing user should be authenticated or a " "new user enrolled." msgstr "源怎样确定应该验证已有用户的身份还是注册新用户。" -#: authentik/core/models.py:683 +#: authentik/core/models.py msgid "Token" msgstr "令牌" -#: authentik/core/models.py:684 +#: authentik/core/models.py msgid "Tokens" msgstr "令牌" -#: authentik/core/models.py:689 +#: authentik/core/models.py msgid "View token's key" msgstr "查看令牌密钥" -#: authentik/core/models.py:725 +#: authentik/core/models.py msgid "Property Mapping" msgstr "属性映射" -#: authentik/core/models.py:726 +#: authentik/core/models.py msgid "Property Mappings" msgstr "属性映射" -#: authentik/core/models.py:763 +#: authentik/core/models.py msgid "Authenticated Session" msgstr "已认证会话" -#: authentik/core/models.py:764 +#: authentik/core/models.py msgid "Authenticated Sessions" msgstr "已认证会话" -#: authentik/core/sources/flow_manager.py:190 -#, python-format +#: authentik/core/sources/flow_manager.py +#, python-brace-format msgid "" -"Request to authenticate with %(source)s has been denied. Please authenticate" -" with the source you've previously signed up with." -msgstr "来自 %(source)s 的身份验证请求被拒绝。请用您注册时使用的方式验证身份。" +"Request to authenticate with {source} has been denied. Please authenticate " +"with the source you've previously signed up with." +msgstr "来自 {source} 的身份验证请求被拒绝。请用您注册时使用的方式验证身份。" -#: authentik/core/sources/flow_manager.py:242 +#: authentik/core/sources/flow_manager.py msgid "Configured flow does not exist." msgstr "配置的流程不存在。" -#: authentik/core/sources/flow_manager.py:272 -#: authentik/core/sources/flow_manager.py:324 -#, python-format -msgid "Successfully authenticated with %(source)s!" -msgstr "成功通过 %(source)s 认证!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully authenticated with {source}!" +msgstr "成功通过 {source} 认证!" -#: authentik/core/sources/flow_manager.py:296 -#, python-format -msgid "Successfully linked %(source)s!" -msgstr "成功链接 %(source)s!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully linked {source}!" +msgstr "成功链接 {source}!" -#: authentik/core/sources/flow_manager.py:315 +#: authentik/core/sources/flow_manager.py msgid "Source is not configured for enrollment." msgstr "源未被配置用于注册。" -#: authentik/core/templates/if/end_session.html:7 +#: authentik/core/templates/if/end_session.html msgid "End session" msgstr "结束会话" -#: authentik/core/templates/if/end_session.html:11 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -314,7 +323,7 @@ msgstr "" "\n" "您已登出 %(application)s。\n" -#: authentik/core/templates/if/end_session.html:19 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -324,11 +333,11 @@ msgstr "" "\n" " 您已成功登出 %(application)s 。现在您可以返回总览页来启动其他应用,或者登出您的 %(branding_title)s 账户。" -#: authentik/core/templates/if/end_session.html:25 +#: authentik/core/templates/if/end_session.html msgid "Go back to overview" msgstr "返回总览" -#: authentik/core/templates/if/end_session.html:29 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -339,7 +348,7 @@ msgstr "" " 登出 %(branding_title)s\n" " " -#: authentik/core/templates/if/end_session.html:36 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -350,344 +359,455 @@ msgstr "" " 重新登录 %(application)s\n" " " -#: authentik/core/templates/if/error.html:18 +#: authentik/core/templates/if/error.html msgid "Go home" msgstr "前往首页" -#: authentik/core/templates/login/base_full.html:75 +#: authentik/core/templates/login/base_full.html msgid "Powered by authentik" msgstr "由 authentik 强力驱动" -#: authentik/core/views/apps.py:53 -#: authentik/providers/oauth2/views/authorize.py:434 -#: authentik/providers/oauth2/views/device_init.py:70 -#: authentik/providers/saml/views/sso.py:70 +#: authentik/core/views/apps.py authentik/providers/oauth2/views/authorize.py +#: authentik/providers/oauth2/views/device_init.py +#: authentik/providers/saml/views/sso.py #, python-format msgid "You're about to sign into %(application)s." msgstr "您即将登录 %(application)s。" -#: authentik/crypto/api.py:179 +#: authentik/crypto/api.py msgid "Subject-alt name" msgstr "替代名称" -#: authentik/crypto/models.py:30 +#: authentik/crypto/builder.py +msgid "rsa" +msgstr "rsa" + +#: authentik/crypto/builder.py +msgid "ecdsa" +msgstr "ecdsa" + +#: authentik/crypto/models.py msgid "PEM-encoded Certificate data" msgstr "PEM 编码的证书数据" -#: authentik/crypto/models.py:33 +#: authentik/crypto/models.py msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." msgstr "可选私钥。如果设置,则可以使用此密钥对来加密。" -#: authentik/crypto/models.py:101 +#: authentik/crypto/models.py msgid "Certificate-Key Pair" msgstr "证书密钥对" -#: authentik/crypto/models.py:102 +#: authentik/crypto/models.py msgid "Certificate-Key Pairs" msgstr "证书密钥对" -#: authentik/enterprise/api.py:33 +#: authentik/enterprise/api.py msgid "Enterprise is required to create/update this object." msgstr "创建/更新此对象需要企业版。" -#: authentik/enterprise/models.py:183 +#: authentik/enterprise/models.py msgid "License" msgstr "许可证" -#: authentik/enterprise/models.py:184 +#: authentik/enterprise/models.py msgid "Licenses" msgstr "许可证" -#: authentik/enterprise/models.py:206 +#: authentik/enterprise/models.py msgid "License Usage" msgstr "许可证使用情况" -#: authentik/enterprise/models.py:207 +#: authentik/enterprise/models.py msgid "License Usage Records" msgstr "许可证使用情况记录" -#: authentik/enterprise/policy.py:18 +#: authentik/enterprise/policy.py msgid "Enterprise required to access this feature." msgstr "访问此功能需要企业版。" -#: authentik/enterprise/policy.py:20 +#: authentik/enterprise/policy.py msgid "Feature only accessible for internal users." msgstr "仅内部用户能访问此功能。" -#: authentik/enterprise/providers/rac/models.py:48 -#: authentik/stages/user_login/models.py:39 +#: authentik/enterprise/providers/google_workspace/models.py +#: authentik/enterprise/providers/microsoft_entra/models.py +#: authentik/providers/scim/models.py authentik/sources/ldap/models.py +msgid "Property mappings used for group creation/updating." +msgstr "用于创建/更新组的属性映射。" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider" +msgstr "Google Workspace 提供程序" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Providers" +msgstr "Google Workspace 提供程序" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mapping" +msgstr "Google Workspace 提供程序映射" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mappings" +msgstr "Google Workspace 提供程序映射" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider User" +msgstr "Google Workspace 提供程序用户" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Users" +msgstr "Google Workspace 提供程序用户" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Group" +msgstr "Google Workspace 提供程序组" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Groups" +msgstr "Google Workspace 提供程序组" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider" +msgstr "Microsoft Entra 提供程序" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Providers" +msgstr "Microsoft Entra 提供程序" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mapping" +msgstr "Microsoft Entra 提供程序映射" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mappings" +msgstr "Microsoft Entra 提供程序映射" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider User" +msgstr "Microsoft Entra 提供程序用户" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Group" +msgstr "Microsoft Entra 提供程序组" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Groups" +msgstr "Microsoft Entra 提供程序组" + +#: authentik/enterprise/providers/rac/models.py +#: authentik/stages/user_login/models.py msgid "" "Determines how long a session lasts. Default of 0 means that the sessions " "lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)" -#: authentik/enterprise/providers/rac/models.py:71 +#: authentik/enterprise/providers/rac/models.py +msgid "When set to true, connection tokens will be deleted upon disconnect." +msgstr "启用时,连接令牌将会在断开连接时被删除。" + +#: authentik/enterprise/providers/rac/models.py msgid "RAC Provider" msgstr "RAC 提供程序" -#: authentik/enterprise/providers/rac/models.py:72 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Providers" msgstr "RAC 提供程序" -#: authentik/enterprise/providers/rac/models.py:100 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoint" msgstr "RAC 端点" -#: authentik/enterprise/providers/rac/models.py:101 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoints" msgstr "RAC 端点" -#: authentik/enterprise/providers/rac/models.py:122 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mapping" msgstr "RAC 属性映射" -#: authentik/enterprise/providers/rac/models.py:123 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mappings" msgstr "RAC 属性映射" -#: authentik/enterprise/providers/rac/views.py:108 +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection token" +msgstr "RAC 连接令牌" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection tokens" +msgstr "RAC 连接令牌" + +#: authentik/enterprise/providers/rac/views.py msgid "Maximum connection limit reached." msgstr "已达到最大连接数。" -#: authentik/enterprise/providers/rac/views.py:112 +#: authentik/enterprise/providers/rac/views.py msgid "(You are already connected in another tab/window)" msgstr "(您已经在另一个标签页/窗口连接了)" -#: authentik/events/models.py:289 +#: authentik/enterprise/stages/source/models.py +msgid "" +"Amount of time a user can take to return from the source to continue the " +"flow (Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "用户从源返回并继续流程可以消耗的时间(格式:hours=-1;minutes=-2;seconds=-3)" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stage" +msgstr "源阶段" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stages" +msgstr "源阶段" + +#: authentik/events/api/tasks.py +#, python-brace-format +msgid "Successfully started task {name}." +msgstr "已成功开始任务 {name}。" + +#: authentik/events/models.py msgid "Event" msgstr "事件" -#: authentik/events/models.py:290 +#: authentik/events/models.py msgid "Events" msgstr "事件" -#: authentik/events/models.py:296 +#: authentik/events/models.py msgid "authentik inbuilt notifications" msgstr "authentik 内置通知" -#: authentik/events/models.py:297 +#: authentik/events/models.py msgid "Generic Webhook" msgstr "通用 Webhook" -#: authentik/events/models.py:298 +#: authentik/events/models.py msgid "Slack Webhook (Slack/Discord)" msgstr "Slack Webhook(Slack/Discord)" -#: authentik/events/models.py:299 +#: authentik/events/models.py msgid "Email" msgstr "电子邮箱" -#: authentik/events/models.py:317 +#: authentik/events/models.py msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." msgstr "仅发送一次通知,例如在向聊天频道发送 Webhook 时。" -#: authentik/events/models.py:382 +#: authentik/events/models.py msgid "Severity" msgstr "严重程度" -#: authentik/events/models.py:387 +#: authentik/events/models.py msgid "Dispatched for user" msgstr "为用户分派" -#: authentik/events/models.py:396 +#: authentik/events/models.py msgid "Event user" msgstr "事件用户" -#: authentik/events/models.py:490 +#: authentik/events/models.py msgid "Notification Transport" msgstr "通知传输" -#: authentik/events/models.py:491 +#: authentik/events/models.py msgid "Notification Transports" msgstr "通知传输" -#: authentik/events/models.py:497 +#: authentik/events/models.py msgid "Notice" msgstr "通知" -#: authentik/events/models.py:498 +#: authentik/events/models.py msgid "Warning" msgstr "警告" -#: authentik/events/models.py:499 +#: authentik/events/models.py msgid "Alert" msgstr "注意" -#: authentik/events/models.py:524 +#: authentik/events/models.py msgid "Notification" msgstr "通知" -#: authentik/events/models.py:525 +#: authentik/events/models.py msgid "Notifications" msgstr "通知" -#: authentik/events/models.py:535 +#: authentik/events/models.py msgid "" "Select which transports should be used to notify the user. If none are " "selected, the notification will only be shown in the authentik UI." msgstr "选择应使用哪些传输方式来通知用户。如果未选择任何内容,则通知将仅显示在 authentik UI 中。" -#: authentik/events/models.py:543 +#: authentik/events/models.py msgid "Controls which severity level the created notifications will have." msgstr "控制被创建的通知的严重性级别。" -#: authentik/events/models.py:548 +#: authentik/events/models.py msgid "" "Define which group of users this notification should be sent and shown to. " "If left empty, Notification won't ben sent." msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" -#: authentik/events/models.py:566 +#: authentik/events/models.py msgid "Notification Rule" msgstr "通知规则" -#: authentik/events/models.py:567 +#: authentik/events/models.py msgid "Notification Rules" msgstr "通知规则" -#: authentik/events/models.py:587 +#: authentik/events/models.py msgid "Webhook Mapping" msgstr "Webhook 映射" -#: authentik/events/models.py:588 +#: authentik/events/models.py msgid "Webhook Mappings" msgstr "Webhook 映射" -#: authentik/events/monitored_tasks.py:207 +#: authentik/events/models.py +msgid "Run task" +msgstr "运行任务" + +#: authentik/events/models.py +msgid "System Task" +msgstr "系统任务" + +#: authentik/events/models.py +msgid "System Tasks" +msgstr "系统任务" + +#: authentik/events/system_tasks.py msgid "Task has not been run yet." msgstr "任务尚未运行。" -#: authentik/flows/api/flows.py:295 -#, python-format -msgid "Flow not applicable to current user/request: %(messages)s" -msgstr "流程不适用于当前用户/请求:%(messages)s" +#: authentik/flows/api/flows.py +#, python-brace-format +msgid "Flow not applicable to current user/request: {messages}" +msgstr "流程不适用于当前用户/请求:{messages}" -#: authentik/flows/api/flows_diagram.py:68 -#: authentik/flows/api/flows_diagram.py:94 -#, python-format -msgid "Policy (%(type)s)" -msgstr "策略(%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Policy ({type})" +msgstr "策略({type})" -#: authentik/flows/api/flows_diagram.py:71 -#, python-format -msgid "Binding %(order)d" -msgstr "绑定 %(order)d" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Binding {order}" +msgstr "绑定 {order}" -#: authentik/flows/api/flows_diagram.py:118 +#: authentik/flows/api/flows_diagram.py msgid "Policy passed" msgstr "策略通过" -#: authentik/flows/api/flows_diagram.py:122 -#, python-format -msgid "Stage (%(type)s)" -msgstr "阶段(%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Stage ({type})" +msgstr "阶段({type})" -#: authentik/flows/api/flows_diagram.py:146 -#: authentik/flows/api/flows_diagram.py:206 +#: authentik/flows/api/flows_diagram.py msgid "Policy denied" msgstr "策略拒绝" -#: authentik/flows/api/flows_diagram.py:156 -#: authentik/flows/api/flows_diagram.py:168 -#: authentik/flows/api/flows_diagram.py:205 -#: authentik/flows/api/flows_diagram.py:227 +#: authentik/flows/api/flows_diagram.py msgid "End of the flow" msgstr "流程结束" -#: authentik/flows/api/flows_diagram.py:169 +#: authentik/flows/api/flows_diagram.py msgid "Requirement not fulfilled" msgstr "需求条件未达成" -#: authentik/flows/api/flows_diagram.py:177 +#: authentik/flows/api/flows_diagram.py msgid "Flow authentication requirement" msgstr "流程身份验证需求" -#: authentik/flows/api/flows_diagram.py:183 +#: authentik/flows/api/flows_diagram.py msgid "Requirement fulfilled" msgstr "需求条件已达成" -#: authentik/flows/api/flows_diagram.py:196 +#: authentik/flows/api/flows_diagram.py msgid "Pre-flow policies" msgstr "流程前置策略" -#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:194 +#: authentik/flows/api/flows_diagram.py authentik/flows/models.py msgid "Flow" msgstr "流程" -#: authentik/flows/exceptions.py:19 +#: authentik/flows/exceptions.py msgid "Flow does not apply to current user." msgstr "流程不应用于当前用户。" -#: authentik/flows/models.py:115 -#, python-format -msgid "Dynamic In-memory stage: %(doc)s" -msgstr "动态内存中阶段:%(doc)s" +#: authentik/flows/models.py +#, python-brace-format +msgid "Dynamic In-memory stage: {doc}" +msgstr "动态内存中阶段:{doc}" -#: authentik/flows/models.py:130 +#: authentik/flows/models.py msgid "Visible in the URL." msgstr "在 URL 中可见。" -#: authentik/flows/models.py:132 +#: authentik/flows/models.py msgid "Shown as the Title in Flow pages." msgstr "显示为流程页面中的标题。" -#: authentik/flows/models.py:139 +#: authentik/flows/models.py msgid "" "Decides what this Flow is used for. For example, the Authentication flow is " "redirect to when an un-authenticated user visits authentik." msgstr "决定此流程的用途。例如,当未经身份验证的用户访问 authentik 时,会重定向到身份验证流程。" -#: authentik/flows/models.py:148 +#: authentik/flows/models.py msgid "Background shown during execution" msgstr "执行时的背景" -#: authentik/flows/models.py:155 +#: authentik/flows/models.py msgid "" "Enable compatibility mode, increases compatibility with password managers on" " mobile devices." msgstr "启用兼容模式,增强与移动设备上密码管理器的兼容性。" -#: authentik/flows/models.py:163 +#: authentik/flows/models.py msgid "Configure what should happen when a flow denies access to a user." msgstr "配置当流程拒绝访问一名用户时应该发生什么。" -#: authentik/flows/models.py:169 +#: authentik/flows/models.py msgid "Required level of authentication and authorization to access a flow." msgstr "需要身份验证和授权等级以访问流程。" -#: authentik/flows/models.py:195 +#: authentik/flows/models.py msgid "Flows" msgstr "流程" -#: authentik/flows/models.py:198 +#: authentik/flows/models.py msgid "Can export a Flow" msgstr "可以导出流程" -#: authentik/flows/models.py:199 +#: authentik/flows/models.py msgid "Can inspect a Flow's execution" msgstr "可以检视流程执行" -#: authentik/flows/models.py:200 +#: authentik/flows/models.py msgid "View Flow's cache metrics" msgstr "查看流程缓存指标" -#: authentik/flows/models.py:201 +#: authentik/flows/models.py msgid "Clear Flow's cache metrics" msgstr "清除流程缓存指标" -#: authentik/flows/models.py:217 +#: authentik/flows/models.py msgid "Evaluate policies during the Flow planning process." msgstr "在流程规划过程中评估策略。" -#: authentik/flows/models.py:221 +#: authentik/flows/models.py msgid "Evaluate policies when the Stage is present to the user." msgstr "在阶段呈现给用户时评估策略。" -#: authentik/flows/models.py:228 +#: authentik/flows/models.py msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -697,62 +817,85 @@ msgstr "" "配置流程执行器应如何处理对质询的无效响应。RETRY 向执行器返回错误消息和类似的质询。RESTART " "从头开始重新启动流程,RESTART_WITH_CONTEXT 在保留当前上下文的同时重新启动流程。" -#: authentik/flows/models.py:251 +#: authentik/flows/models.py msgid "Flow Stage Binding" msgstr "流程阶段绑定" -#: authentik/flows/models.py:252 +#: authentik/flows/models.py msgid "Flow Stage Bindings" msgstr "流程阶段绑定" -#: authentik/flows/models.py:267 +#: authentik/flows/models.py msgid "" "Flow used by an authenticated user to configure this Stage. If empty, user " "will not be able to configure this stage." msgstr "经过身份验证的用户用来配置此阶段的流程。如果为空,用户将无法配置此阶段。" -#: authentik/flows/models.py:307 +#: authentik/flows/models.py msgid "Flow Token" msgstr "流程令牌" -#: authentik/flows/models.py:308 +#: authentik/flows/models.py msgid "Flow Tokens" msgstr "流程令牌" -#: authentik/lib/utils/time.py:27 +#: authentik/flows/views/executor.py +msgid "Invalid next URL" +msgstr "无效的 next URL" + +#: authentik/lib/sync/outgoing/tasks.py +msgid "Starting full provider sync" +msgstr "开始全量提供程序同步" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of users" +msgstr "正在同步用户页面 %(page)d" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of groups" +msgstr "正在同步群组页面 %(page)d" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-brace-format +msgid "Stopping sync due to error: {error}" +msgstr "由于以下错误,同步停止:{error}" + +#: authentik/lib/utils/time.py #, python-format msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." msgstr "%(value)s 的格式不正确,应为 'hours=3;minutes=1'。" -#: authentik/lib/validators.py:16 +#: authentik/lib/validators.py #, python-brace-format msgid "The fields {field_names} must be used together." msgstr "字段 {field_names} 必须一同使用。" -#: authentik/outposts/api/service_connections.py:127 +#: authentik/outposts/api/service_connections.py msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." msgstr "您只能在连接到本地集群时使用空的 kubeconfig。" -#: authentik/outposts/api/service_connections.py:135 +#: authentik/outposts/api/service_connections.py msgid "Invalid kubeconfig" msgstr "无效 kubeconfig " -#: authentik/outposts/models.py:123 +#: authentik/outposts/models.py msgid "" "If enabled, use the local connection. Required Docker socket/Kubernetes " "Integration" msgstr "如果启用,则使用本地连接。需要 Docker Socket / Kubernetes 集成" -#: authentik/outposts/models.py:153 +#: authentik/outposts/models.py msgid "Outpost Service-Connection" msgstr "前哨服务连接" -#: authentik/outposts/models.py:154 +#: authentik/outposts/models.py msgid "Outpost Service-Connections" msgstr "前哨服务连接" -#: authentik/outposts/models.py:162 +#: authentik/outposts/models.py msgid "" "Can be in the format of 'unix://' when connecting to a local docker " "daemon, or 'https://:2376' when connecting to a remote system." @@ -760,271 +903,270 @@ msgstr "" "当连接到本地 Docker " "守护进程时,可以使用“unix://”格式,或者在连接远程系统时,使用“https://:2376”格式。" -#: authentik/outposts/models.py:174 +#: authentik/outposts/models.py msgid "" "CA which the endpoint's Certificate is verified against. Can be left empty " "for no validation." msgstr "验证端点证书所依据的 CA。可以留空,表示不进行验证。" -#: authentik/outposts/models.py:186 +#: authentik/outposts/models.py msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." msgstr "用于身份验证的证书/密钥。可以留空表示不验证。" -#: authentik/outposts/models.py:204 +#: authentik/outposts/models.py msgid "Docker Service-Connection" msgstr "Docker 服务连接" -#: authentik/outposts/models.py:205 +#: authentik/outposts/models.py msgid "Docker Service-Connections" msgstr "Docker 服务连接" -#: authentik/outposts/models.py:213 +#: authentik/outposts/models.py msgid "" "Paste your kubeconfig here. authentik will automatically use the currently " "selected context." msgstr "在这里粘贴您的 kubeconfig。authentik 会自动使用当前选择的上下文。" -#: authentik/outposts/models.py:219 +#: authentik/outposts/models.py msgid "Verify SSL Certificates of the Kubernetes API endpoint" msgstr "验证 Kubernetes API 端点的 SSL 证书" -#: authentik/outposts/models.py:236 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connection" msgstr "Kubernetes 服务连接" -#: authentik/outposts/models.py:237 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connections" msgstr "Kubernetes 服务连接" -#: authentik/outposts/models.py:253 +#: authentik/outposts/models.py msgid "" "Select Service-Connection authentik should use to manage this outpost. Leave" " empty if authentik should not handle the deployment." msgstr "选择 authentik 在管理此前哨时需要使用的服务连接。如果 authentik 不应该处理此部署,则应该留空。" -#: authentik/outposts/models.py:420 +#: authentik/outposts/models.py msgid "Outpost" msgstr "前哨" -#: authentik/outposts/models.py:421 +#: authentik/outposts/models.py msgid "Outposts" msgstr "前哨" -#: authentik/policies/denied.py:24 +#: authentik/policies/denied.py msgid "Access denied" msgstr "访问被拒绝" -#: authentik/policies/dummy/models.py:44 +#: authentik/policies/dummy/models.py msgid "Dummy Policy" msgstr "虚拟策略" -#: authentik/policies/dummy/models.py:45 +#: authentik/policies/dummy/models.py msgid "Dummy Policies" msgstr "虚拟策略" -#: authentik/policies/event_matcher/api.py:20 -#: authentik/policies/event_matcher/models.py:56 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected application. When left empty, all " "applications are matched." msgstr "匹配选定应用程序创建的事件。如果留空,则匹配所有应用程序。" -#: authentik/policies/event_matcher/api.py:29 -#: authentik/policies/event_matcher/models.py:64 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected model. When left empty, all models are " "matched. When an app is selected, all the application's models are matched." msgstr "匹配选定模型创建的事件。如果留空,则匹配所有模型。选择应用程序后,则匹配该应用程序的所有模型。" -#: authentik/policies/event_matcher/api.py:42 +#: authentik/policies/event_matcher/api.py msgid "At least one criteria must be set." msgstr "必须至少设置一项标准。" -#: authentik/policies/event_matcher/models.py:48 +#: authentik/policies/event_matcher/models.py msgid "" "Match created events with this action type. When left empty, all action " "types will be matched." msgstr "将创建的事件与此操作类型匹配。留空时,所有操作类型都将匹配。" -#: authentik/policies/event_matcher/models.py:73 +#: authentik/policies/event_matcher/models.py msgid "" "Matches Event's Client IP (strict matching, for network matching use an " "Expression Policy)" msgstr "匹配事件的客户端 IP(严格匹配,要匹配网段请使用表达式策略)" -#: authentik/policies/event_matcher/models.py:143 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policy" msgstr "事件匹配策略" -#: authentik/policies/event_matcher/models.py:144 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policies" msgstr "事件匹配策略" -#: authentik/policies/expiry/models.py:45 +#: authentik/policies/expiry/models.py #, python-format msgid "Password expired %(days)d days ago. Please update your password." msgstr "密码在 %(days)d 天前过期。请更新您的密码。" -#: authentik/policies/expiry/models.py:49 +#: authentik/policies/expiry/models.py msgid "Password has expired." msgstr "密码已过期。" -#: authentik/policies/expiry/models.py:53 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policy" msgstr "密码过期策略" -#: authentik/policies/expiry/models.py:54 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policies" msgstr "密码过期策略" -#: authentik/policies/expression/models.py:40 +#: authentik/policies/expression/models.py msgid "Expression Policy" msgstr "表达式策略" -#: authentik/policies/expression/models.py:41 +#: authentik/policies/expression/models.py msgid "Expression Policies" msgstr "表达式策略" -#: authentik/policies/models.py:22 +#: authentik/policies/models.py msgid "all, all policies must pass" msgstr "All,必须通过所有策略" -#: authentik/policies/models.py:23 +#: authentik/policies/models.py msgid "any, any policy must pass" msgstr "Any,必须通过任意策略" -#: authentik/policies/models.py:46 +#: authentik/policies/models.py msgid "Policy Binding Model" msgstr "策略绑定模型" -#: authentik/policies/models.py:47 +#: authentik/policies/models.py msgid "Policy Binding Models" msgstr "策略绑定模型" -#: authentik/policies/models.py:86 +#: authentik/policies/models.py msgid "Negates the outcome of the policy. Messages are unaffected." msgstr "反转策略的结果。消息不受影响。" -#: authentik/policies/models.py:89 +#: authentik/policies/models.py msgid "Timeout after which Policy execution is terminated." msgstr "策略执行终止的超时时间。" -#: authentik/policies/models.py:92 +#: authentik/policies/models.py msgid "Result if the Policy execution fails." msgstr "策略执行失败时的结果。" -#: authentik/policies/models.py:145 +#: authentik/policies/models.py msgid "Policy Binding" msgstr "策略绑定" -#: authentik/policies/models.py:146 +#: authentik/policies/models.py msgid "Policy Bindings" msgstr "策略绑定" -#: authentik/policies/models.py:167 +#: authentik/policies/models.py msgid "" "When this option is enabled, all executions of this policy will be logged. " "By default, only execution errors are logged." msgstr "启用此选项后,将记录此策略的所有执行日志。默认情况下,只记录执行错误。" -#: authentik/policies/models.py:189 +#: authentik/policies/models.py msgid "Policy" msgstr "策略" -#: authentik/policies/models.py:190 +#: authentik/policies/models.py msgid "Policies" msgstr "策略" -#: authentik/policies/models.py:193 +#: authentik/policies/models.py msgid "View Policy's cache metrics" msgstr "查看策略缓存指标" -#: authentik/policies/models.py:194 +#: authentik/policies/models.py msgid "Clear Policy's cache metrics" msgstr "清除策略缓存指标" -#: authentik/policies/password/models.py:27 +#: authentik/policies/password/models.py msgid "Field key to check, field keys defined in Prompt stages are available." msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。" -#: authentik/policies/password/models.py:44 +#: authentik/policies/password/models.py msgid "How many times the password hash is allowed to be on haveibeenpwned" msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次" -#: authentik/policies/password/models.py:49 +#: authentik/policies/password/models.py msgid "" "If the zxcvbn score is equal or less than this value, the policy will fail." msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。" -#: authentik/policies/password/models.py:72 +#: authentik/policies/password/models.py msgid "Password not set in context" msgstr "未在上下文中设置密码" -#: authentik/policies/password/models.py:134 +#: authentik/policies/password/models.py #, python-format msgid "Password exists on %(count)d online lists." msgstr "%(count)d 个在线列表中存在密码。" -#: authentik/policies/password/models.py:154 +#: authentik/policies/password/models.py msgid "Password is too weak." msgstr "密码太弱。" -#: authentik/policies/password/models.py:162 +#: authentik/policies/password/models.py msgid "Password Policy" msgstr "密码策略" -#: authentik/policies/password/models.py:163 +#: authentik/policies/password/models.py msgid "Password Policies" msgstr "密码策略" -#: authentik/policies/reputation/api.py:18 +#: authentik/policies/reputation/api.py msgid "Either IP or Username must be checked" msgstr "必须检查 IP 或用户名" -#: authentik/policies/reputation/models.py:67 +#: authentik/policies/reputation/models.py msgid "Reputation Policy" msgstr "信誉策略" -#: authentik/policies/reputation/models.py:68 +#: authentik/policies/reputation/models.py msgid "Reputation Policies" msgstr "信誉策略" -#: authentik/policies/reputation/models.py:96 +#: authentik/policies/reputation/models.py msgid "Reputation Score" msgstr "信誉分数" -#: authentik/policies/reputation/models.py:97 +#: authentik/policies/reputation/models.py msgid "Reputation Scores" msgstr "信誉分数" -#: authentik/policies/templates/policies/denied.html:7 -#: authentik/policies/templates/policies/denied.html:11 +#: authentik/policies/templates/policies/denied.html msgid "Permission denied" msgstr "权限被拒绝" -#: authentik/policies/templates/policies/denied.html:21 +#: authentik/policies/templates/policies/denied.html msgid "User's avatar" msgstr "用户的头像" -#: authentik/policies/templates/policies/denied.html:25 +#: authentik/policies/templates/policies/denied.html msgid "Not you?" msgstr "不是您?" -#: authentik/policies/templates/policies/denied.html:33 +#: authentik/policies/templates/policies/denied.html msgid "Request has been denied." msgstr "请求被拒绝。" -#: authentik/policies/templates/policies/denied.html:44 +#: authentik/policies/templates/policies/denied.html msgid "Messages:" msgstr "消息:" -#: authentik/policies/templates/policies/denied.html:54 +#: authentik/policies/templates/policies/denied.html msgid "Explanation:" msgstr "解释:" -#: authentik/policies/templates/policies/denied.html:58 +#: authentik/policies/templates/policies/denied.html #, python-format msgid "" "\n" @@ -1035,21 +1177,21 @@ msgstr "" " 策略绑定 '%(name)s' 返回结果 '%(result)s'\n" " " -#: authentik/policies/views.py:68 +#: authentik/policies/views.py msgid "Failed to resolve application" msgstr "解析应用程序失败" -#: authentik/providers/ldap/models.py:25 +#: authentik/providers/ldap/models.py msgid "DN under which objects are accessible." msgstr "可访问对象的 DN。" -#: authentik/providers/ldap/models.py:34 +#: authentik/providers/ldap/models.py msgid "" "Users in this group can do search queries. If not set, every user can " "execute search queries." msgstr "该组中的用户可以执行搜索查询。如果未设置,则每个用户都可以执行搜索查询。" -#: authentik/providers/ldap/models.py:53 +#: authentik/providers/ldap/models.py msgid "" "The start for uidNumbers, this number is added to the user.pk to make sure " "that the numbers aren't too low for POSIX users. Default is 2000 to ensure " @@ -1058,7 +1200,7 @@ msgstr "" "起始 uidNumbers,这个数字会被添加到 user.pk 中,以确保对于 POSIX 用户来说,这个数字不会太低。默认值为 " "2000,以确保我们不会与本地用户的 uidNumber 发生冲突" -#: authentik/providers/ldap/models.py:62 +#: authentik/providers/ldap/models.py msgid "" "The start for gidNumbers, this number is added to a number generated from " "the group.pk to make sure that the numbers aren't too low for POSIX groups. " @@ -1068,8 +1210,7 @@ msgstr "" "起始 gidNumbers,这个数字会被添加到从 group.pk 生成的数字中,以确保对于 POSIX 用户来说,这个数字不会太低。默认值为 " "4000,以确保我们不会与本地群组或用户主组的 gidNumber 发生冲突" -#: authentik/providers/ldap/models.py:76 -#: authentik/providers/radius/models.py:34 +#: authentik/providers/ldap/models.py authentik/providers/radius/models.py msgid "" "When enabled, code-based multi-factor authentication can be used by " "appending a semicolon and the TOTP code to the password. This should only be" @@ -1080,958 +1221,950 @@ msgstr "" "启用时,可以通过在密码后添加分号和 TOTP 代码来使用基于代码的多因素身份验证。仅在所有绑定到此提供程序的用户都已配置 TOTP " "设备的情况下才应该启用,否则密码可能会因为包含分号而被错误地拒绝。" -#: authentik/providers/ldap/models.py:108 +#: authentik/providers/ldap/models.py msgid "LDAP Provider" msgstr "LDAP 提供程序" -#: authentik/providers/ldap/models.py:109 +#: authentik/providers/ldap/models.py msgid "LDAP Providers" msgstr "LDAP 提供程序" -#: authentik/providers/oauth2/id_token.py:27 +#: authentik/providers/oauth2/id_token.py msgid "Based on the Hashed User ID" msgstr "基于经过哈希处理的用户 ID" -#: authentik/providers/oauth2/id_token.py:28 +#: authentik/providers/oauth2/id_token.py msgid "Based on user ID" msgstr "基于用户 ID" -#: authentik/providers/oauth2/id_token.py:29 +#: authentik/providers/oauth2/id_token.py msgid "Based on user UUID" msgstr "基于用户 UUID" -#: authentik/providers/oauth2/id_token.py:30 +#: authentik/providers/oauth2/id_token.py msgid "Based on the username" msgstr "基于用户名" -#: authentik/providers/oauth2/id_token.py:33 +#: authentik/providers/oauth2/id_token.py msgid "Based on the User's Email. This is recommended over the UPN method." msgstr "基于用户的电子邮箱。建议在 UPN 方法上使用。" -#: authentik/providers/oauth2/id_token.py:38 +#: authentik/providers/oauth2/id_token.py msgid "" "Based on the User's UPN, only works if user has a 'upn' attribute set. Use " "this method only if you have different UPN and Mail domains." msgstr "基于用户的 UPN,仅当用户设置了 'upn' 属性时才有效。仅当您有不同的 UPN 和 Mail 域时才使用此方法。" -#: authentik/providers/oauth2/models.py:43 +#: authentik/providers/oauth2/models.py msgid "Confidential" msgstr "机密" -#: authentik/providers/oauth2/models.py:44 +#: authentik/providers/oauth2/models.py msgid "Public" msgstr "公开" -#: authentik/providers/oauth2/models.py:66 +#: authentik/providers/oauth2/models.py msgid "Same identifier is used for all providers" msgstr "所有提供程序都使用相同的标识符" -#: authentik/providers/oauth2/models.py:68 +#: authentik/providers/oauth2/models.py msgid "Each provider has a different issuer, based on the application slug." msgstr "根据应用程序 Slug,每个提供程序都有不同的颁发者。" -#: authentik/providers/oauth2/models.py:75 +#: authentik/providers/oauth2/models.py msgid "code (Authorization Code Flow)" msgstr "code(授权码流程)" -#: authentik/providers/oauth2/models.py:76 +#: authentik/providers/oauth2/models.py msgid "id_token (Implicit Flow)" msgstr "id_token(隐式流程)" -#: authentik/providers/oauth2/models.py:77 +#: authentik/providers/oauth2/models.py msgid "id_token token (Implicit Flow)" msgstr "id_token token(隐式流程)" -#: authentik/providers/oauth2/models.py:78 +#: authentik/providers/oauth2/models.py msgid "code token (Hybrid Flow)" msgstr "code token(混合流程)" -#: authentik/providers/oauth2/models.py:79 +#: authentik/providers/oauth2/models.py msgid "code id_token (Hybrid Flow)" msgstr "code id_token(混合流程)" -#: authentik/providers/oauth2/models.py:80 +#: authentik/providers/oauth2/models.py msgid "code id_token token (Hybrid Flow)" msgstr "code id_token token(混合流程)" -#: authentik/providers/oauth2/models.py:86 +#: authentik/providers/oauth2/models.py msgid "HS256 (Symmetric Encryption)" msgstr "HS256(对称加密)" -#: authentik/providers/oauth2/models.py:87 +#: authentik/providers/oauth2/models.py msgid "RS256 (Asymmetric Encryption)" msgstr "RS256(非对称加密)" -#: authentik/providers/oauth2/models.py:88 +#: authentik/providers/oauth2/models.py msgid "ES256 (Asymmetric Encryption)" msgstr "ES256(非对称加密)" -#: authentik/providers/oauth2/models.py:94 +#: authentik/providers/oauth2/models.py msgid "Scope used by the client" msgstr "客户端使用的作用域" -#: authentik/providers/oauth2/models.py:98 +#: authentik/providers/oauth2/models.py msgid "" "Description shown to the user when consenting. If left empty, the user won't" " be informed." msgstr "同意授权时向用户显示的描述。如果留空,则不会告知用户。" -#: authentik/providers/oauth2/models.py:117 +#: authentik/providers/oauth2/models.py msgid "Scope Mapping" msgstr "作用域映射" -#: authentik/providers/oauth2/models.py:118 +#: authentik/providers/oauth2/models.py msgid "Scope Mappings" msgstr "作用域映射" -#: authentik/providers/oauth2/models.py:128 +#: authentik/providers/oauth2/models.py msgid "Client Type" msgstr "客户端类型" -#: authentik/providers/oauth2/models.py:130 +#: authentik/providers/oauth2/models.py msgid "" "Confidential clients are capable of maintaining the confidentiality of their" " credentials. Public clients are incapable" msgstr "机密客户端有能力维护其凭据的机密性。公开客户端无此能力。" -#: authentik/providers/oauth2/models.py:137 +#: authentik/providers/oauth2/models.py msgid "Client ID" msgstr "客户端 ID" -#: authentik/providers/oauth2/models.py:143 +#: authentik/providers/oauth2/models.py msgid "Client Secret" msgstr "客户端密钥" -#: authentik/providers/oauth2/models.py:149 +#: authentik/providers/oauth2/models.py msgid "Redirect URIs" msgstr "重定向 URI" -#: authentik/providers/oauth2/models.py:150 +#: authentik/providers/oauth2/models.py msgid "Enter each URI on a new line." msgstr "每行输入一个 URI。" -#: authentik/providers/oauth2/models.py:155 +#: authentik/providers/oauth2/models.py msgid "Include claims in id_token" msgstr "在 id_token 中包含声明" -#: authentik/providers/oauth2/models.py:157 +#: authentik/providers/oauth2/models.py msgid "" "Include User claims from scopes in the id_token, for applications that don't" " access the userinfo endpoint." msgstr "对于不访问 userinfo 端点的应用程序,将来自作用域的用户声明包含在 id_token 中。" -#: authentik/providers/oauth2/models.py:166 +#: authentik/providers/oauth2/models.py msgid "" "Access codes not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,访问代码无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/oauth2/models.py:174 -#: authentik/providers/oauth2/models.py:182 +#: authentik/providers/oauth2/models.py msgid "" "Tokens not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,令牌无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/oauth2/models.py:191 +#: authentik/providers/oauth2/models.py msgid "" "Configure what data should be used as unique User Identifier. For most " "cases, the default should be fine." msgstr "配置应将哪些数据用作唯一用户标识符。在大多数情况下保持默认值即可。" -#: authentik/providers/oauth2/models.py:198 +#: authentik/providers/oauth2/models.py msgid "Configure how the issuer field of the ID Token should be filled." msgstr "配置如何填写 ID 令牌的颁发者字段。" -#: authentik/providers/oauth2/models.py:203 +#: authentik/providers/oauth2/models.py msgid "Signing Key" msgstr "签名密钥" -#: authentik/providers/oauth2/models.py:207 +#: authentik/providers/oauth2/models.py msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." msgstr "用于签名令牌的密钥。仅当 JWT 算法设置为 RS256 时才需要。" -#: authentik/providers/oauth2/models.py:214 +#: authentik/providers/oauth2/models.py msgid "" "Any JWT signed by the JWK of the selected source can be used to " "authenticate." msgstr "任何由选定来源的 JWK 签发的 JWT 都可以用于身份验证。" -#: authentik/providers/oauth2/models.py:287 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Provider" msgstr "OAuth2/OpenID 提供程序" -#: authentik/providers/oauth2/models.py:288 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Providers" msgstr "OAuth2/OpenID 提供程序" -#: authentik/providers/oauth2/models.py:297 -#: authentik/providers/oauth2/models.py:430 +#: authentik/providers/oauth2/models.py msgid "Scopes" msgstr "作用域" -#: authentik/providers/oauth2/models.py:317 +#: authentik/providers/oauth2/models.py msgid "Code" msgstr "代码" -#: authentik/providers/oauth2/models.py:318 +#: authentik/providers/oauth2/models.py msgid "Nonce" msgstr "Nonce" -#: authentik/providers/oauth2/models.py:319 +#: authentik/providers/oauth2/models.py msgid "Code Challenge" msgstr "代码质询" -#: authentik/providers/oauth2/models.py:321 +#: authentik/providers/oauth2/models.py msgid "Code Challenge Method" msgstr "代码质询方法" -#: authentik/providers/oauth2/models.py:341 +#: authentik/providers/oauth2/models.py msgid "Authorization Code" msgstr "授权代码" -#: authentik/providers/oauth2/models.py:342 +#: authentik/providers/oauth2/models.py msgid "Authorization Codes" msgstr "授权代码" -#: authentik/providers/oauth2/models.py:384 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Token" msgstr "OAuth2 访问令牌" -#: authentik/providers/oauth2/models.py:385 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Tokens" msgstr "OAuth2 访问令牌" -#: authentik/providers/oauth2/models.py:395 +#: authentik/providers/oauth2/models.py msgid "ID Token" msgstr "ID 令牌" -#: authentik/providers/oauth2/models.py:414 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Token" msgstr "OAuth2 刷新令牌" -#: authentik/providers/oauth2/models.py:415 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Tokens" msgstr "OAuth2 刷新令牌" -#: authentik/providers/oauth2/models.py:442 +#: authentik/providers/oauth2/models.py msgid "Device Token" msgstr "设备令牌" -#: authentik/providers/oauth2/models.py:443 +#: authentik/providers/oauth2/models.py msgid "Device Tokens" msgstr "设备令牌" -#: authentik/providers/oauth2/views/authorize.py:489 -#: authentik/providers/saml/views/flows.py:87 -#, python-format -msgid "Redirecting to %(app)s..." -msgstr "正在跳转到 %(app)s…" +#: authentik/providers/oauth2/views/authorize.py +#: authentik/providers/saml/views/flows.py +#, python-brace-format +msgid "Redirecting to {app}..." +msgstr "正在跳转到 {app}…" -#: authentik/providers/oauth2/views/device_init.py:151 +#: authentik/providers/oauth2/views/device_init.py msgid "Invalid code" msgstr "无效代码" -#: authentik/providers/oauth2/views/userinfo.py:55 -#: authentik/providers/oauth2/views/userinfo.py:56 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your User Information" msgstr "GitHub 兼容性:访问您的用户信息" -#: authentik/providers/oauth2/views/userinfo.py:57 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access you Email addresses" msgstr "GitHub 兼容性:访问您的电子邮件地址" -#: authentik/providers/oauth2/views/userinfo.py:58 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your Groups" msgstr "GitHub 兼容性:访问您的组" -#: authentik/providers/oauth2/views/userinfo.py:59 +#: authentik/providers/oauth2/views/userinfo.py msgid "authentik API Access on behalf of your user" msgstr "代表您的用户访问 authentik API" -#: authentik/providers/proxy/api.py:52 +#: authentik/providers/proxy/api.py msgid "User and password attributes must be set when basic auth is enabled." msgstr "启用 Basic Auth 时,必须设置用户和密码属性。" -#: authentik/providers/proxy/api.py:63 +#: authentik/providers/proxy/api.py msgid "Internal host cannot be empty when forward auth is disabled." msgstr "禁用 Forward Auth 时,内部主机不能为空。" -#: authentik/providers/proxy/models.py:54 +#: authentik/providers/proxy/models.py msgid "Validate SSL Certificates of upstream servers" msgstr "验证上游服务器的 SSL 证书" -#: authentik/providers/proxy/models.py:55 +#: authentik/providers/proxy/models.py msgid "Internal host SSL Validation" msgstr "内部主机 SSL 验证" -#: authentik/providers/proxy/models.py:61 +#: authentik/providers/proxy/models.py msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." msgstr "在 traefik 和 nginx auth_request 中启用对 ForwardAuth 的支持。排除 internal_host。" -#: authentik/providers/proxy/models.py:70 +#: authentik/providers/proxy/models.py msgid "" "Regular expressions for which authentication is not required. Each new line " "is interpreted as a new Regular Expression." msgstr "用于描述何处不需要身份验证的正则表达式。每个新行都被解释为一个新的正则表达式。" -#: authentik/providers/proxy/models.py:78 +#: authentik/providers/proxy/models.py msgid "" "When enabled, this provider will intercept the authorization header and " "authenticate requests based on its value." msgstr "启用时,此提供程序将会拦截 Authorization 标头,并基于其值认证请求。" -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py msgid "Set HTTP-Basic Authentication" msgstr "设置 HTTP-Basic 身份验证" -#: authentik/providers/proxy/models.py:86 +#: authentik/providers/proxy/models.py msgid "" "Set a custom HTTP-Basic Authentication header based on values from " "authentik." msgstr "根据来自 authentik 的值设置自定义 HTTP-Basic 身份验证标头。" -#: authentik/providers/proxy/models.py:91 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Username Key" msgstr "HTTP-Basic 用户名密钥" -#: authentik/providers/proxy/models.py:93 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the user part of the HTTP-Basic Header. If not" " set, the user's Email address is used." msgstr "用于 HTTP-Basic 标头用户名部分的用户/组属性。如果未设置,则使用用户的电子邮件地址。" -#: authentik/providers/proxy/models.py:99 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Password Key" msgstr "HTTP-Basic 密码密钥" -#: authentik/providers/proxy/models.py:100 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the password part of the HTTP-Basic Header." msgstr "用于 HTTP-Basic 标头的密码部分的用户/组属性。" -#: authentik/providers/proxy/models.py:154 +#: authentik/providers/proxy/models.py msgid "Proxy Provider" msgstr "代理提供程序" -#: authentik/providers/proxy/models.py:155 +#: authentik/providers/proxy/models.py msgid "Proxy Providers" msgstr "代理提供程序" -#: authentik/providers/radius/models.py:18 +#: authentik/providers/radius/models.py msgid "Shared secret between clients and server to hash packets." msgstr "在客户端和服务端之间共享密钥以哈希数据包。" -#: authentik/providers/radius/models.py:24 +#: authentik/providers/radius/models.py msgid "" "List of CIDRs (comma-separated) that clients can connect from. A more " "specific CIDR will match before a looser one. Clients connecting from a non-" "specified CIDR will be dropped." msgstr "允许客户端连接的 CIDR 列表(逗号分隔)。严格的 CIDR 会在宽松的之前匹配。来自 CIDR 范围外的客户端连接将会被丢弃。" -#: authentik/providers/radius/models.py:60 +#: authentik/providers/radius/models.py msgid "Radius Provider" msgstr "Radius 提供程序" -#: authentik/providers/radius/models.py:61 +#: authentik/providers/radius/models.py msgid "Radius Providers" msgstr "Radius 提供程序" -#: authentik/providers/saml/api/providers.py:258 +#: authentik/providers/saml/api/providers.py msgid "Invalid XML Syntax" msgstr "无效 XML 语法" -#: authentik/providers/saml/api/providers.py:268 -#, python-format -msgid "Failed to import Metadata: %(message)s" -msgstr "导入元数据失败:%(message)s" +#: authentik/providers/saml/api/providers.py +#, python-brace-format +msgid "Failed to import Metadata: {messages}" +msgstr "导入元数据失败:{messages}" -#: authentik/providers/saml/models.py:38 +#: authentik/providers/saml/models.py msgid "ACS URL" msgstr "ACS URL" -#: authentik/providers/saml/models.py:43 +#: authentik/providers/saml/models.py msgid "" "Value of the audience restriction field of the assertion. When left empty, " "no audience restriction will be added." msgstr "断言的 Audience 受限字段的值。留空时,不会添加 Audience 限制。" -#: authentik/providers/saml/models.py:47 +#: authentik/providers/saml/models.py msgid "Also known as EntityID" msgstr "也称为 EntityID" -#: authentik/providers/saml/models.py:51 +#: authentik/providers/saml/models.py msgid "Service Provider Binding" msgstr "服务提供程序绑定" -#: authentik/providers/saml/models.py:53 +#: authentik/providers/saml/models.py msgid "" "This determines how authentik sends the response back to the Service " "Provider." msgstr "确定 authentik 如何将响应发送回服务提供程序。" -#: authentik/providers/saml/models.py:63 +#: authentik/providers/saml/models.py msgid "NameID Property Mapping" msgstr "NameID 属性映射" -#: authentik/providers/saml/models.py:65 +#: authentik/providers/saml/models.py msgid "" "Configure how the NameID value will be created. When left empty, the " "NameIDPolicy of the incoming request will be considered" msgstr "配置如何创建 NameID 值。如果留空,将考虑传入请求的 NameIDPolicy" -#: authentik/providers/saml/models.py:74 +#: authentik/providers/saml/models.py msgid "" "Assertion valid not before current time + this value (Format: " "hours=-1;minutes=-2;seconds=-3)." msgstr "从当前时间经过多久时或之后,断言有效(格式:hours=-1;minutes=-2;seconds=-3)。" -#: authentik/providers/saml/models.py:82 +#: authentik/providers/saml/models.py msgid "" "Assertion not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,断言无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/saml/models.py:91 +#: authentik/providers/saml/models.py msgid "" "Session not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,会话无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA1" msgstr "SHA1" -#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA256" msgstr "SHA256" -#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA384" msgstr "SHA384" -#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA512" msgstr "SHA512" -#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA1" msgstr "RSA-SHA1" -#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA256" msgstr "RSA-SHA256" -#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA384" msgstr "RSA-SHA384" -#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA512" msgstr "RSA-SHA512" -#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA1" +msgstr "ECDSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA256" +msgstr "ECDSA-SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA384" +msgstr "ECDSA-SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA512" +msgstr "ECDSA-SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "DSA-SHA1" msgstr "DSA-SHA1" -#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "" "When selected, incoming assertion's Signatures will be validated against " "this certificate. To allow unsigned Requests, leave on default." msgstr "选中后,传入断言的签名将根据此证书进行验证。要允许未签名的请求,请保留默认值。" -#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Verification Certificate" msgstr "验证证书" -#: authentik/providers/saml/models.py:136 +#: authentik/providers/saml/models.py msgid "Keypair used to sign outgoing Responses going to the Service Provider." msgstr "密钥对,用于签署发送给服务提供程序的传出响应。" -#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Signing Keypair" msgstr "签名密钥对" -#: authentik/providers/saml/models.py:142 +#: authentik/providers/saml/models.py msgid "Default relay_state value for IDP-initiated logins" msgstr "用于 IDP 发起登录的默认 relay_state 值" -#: authentik/providers/saml/models.py:171 +#: authentik/providers/saml/models.py msgid "SAML Provider" msgstr "SAML 提供程序" -#: authentik/providers/saml/models.py:172 +#: authentik/providers/saml/models.py msgid "SAML Providers" msgstr "SAML 提供程序" -#: authentik/providers/saml/models.py:196 +#: authentik/providers/saml/models.py msgid "SAML Property Mapping" msgstr "SAML 属性映射" -#: authentik/providers/saml/models.py:197 +#: authentik/providers/saml/models.py msgid "SAML Property Mappings" msgstr "SAML 属性映射" -#: authentik/providers/scim/models.py:23 +#: authentik/providers/saml/models.py +msgid "SAML Provider from Metadata" +msgstr "来自元数据的 SAML 提供程序" + +#: authentik/providers/saml/models.py +msgid "SAML Providers from Metadata" +msgstr "来自元数据的 SAML 提供程序" + +#: authentik/providers/scim/models.py msgid "Base URL to SCIM requests, usually ends in /v2" msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾" -#: authentik/providers/scim/models.py:24 +#: authentik/providers/scim/models.py msgid "Authentication token" msgstr "身份验证令牌" -#: authentik/providers/scim/models.py:30 authentik/sources/ldap/models.py:98 -msgid "Property mappings used for group creation/updating." -msgstr "用于创建/更新组的属性映射。" - -#: authentik/providers/scim/models.py:72 +#: authentik/providers/scim/models.py msgid "SCIM Provider" msgstr "SCIM 提供程序" -#: authentik/providers/scim/models.py:73 +#: authentik/providers/scim/models.py msgid "SCIM Providers" msgstr "SCIM 提供程序" -#: authentik/providers/scim/models.py:93 +#: authentik/providers/scim/models.py msgid "SCIM Mapping" msgstr "SCIM 映射" -#: authentik/providers/scim/models.py:94 +#: authentik/providers/scim/models.py msgid "SCIM Mappings" msgstr "SCIM 映射" -#: authentik/providers/scim/tasks.py:56 -msgid "Starting full SCIM sync" -msgstr "开始全量 SCIM 同步" - -#: authentik/providers/scim/tasks.py:66 -#, python-format -msgid "Syncing page %(page)d of users" -msgstr "正在同步用户页面 %(page)d" - -#: authentik/providers/scim/tasks.py:70 -#, python-format -msgid "Syncing page %(page)d of groups" -msgstr "正在同步群组页面 %(page)d" - -#: authentik/providers/scim/tasks.py:102 -#, python-format -msgid "Failed to sync user %(user_name)s due to remote error: %(error)s" -msgstr "由于远端错误,同步用户 %(user_name)s 失败:%(error)s" - -#: authentik/providers/scim/tasks.py:113 authentik/providers/scim/tasks.py:154 -#, python-format -msgid "Stopping sync due to error: %(error)s" -msgstr "由于以下错误,同步停止:%(error)s" - -#: authentik/providers/scim/tasks.py:143 -#, python-format -msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" -msgstr "由于远端错误,同步组 %(group_name)s 失败:%(error)s" - -#: authentik/rbac/models.py:51 +#: authentik/rbac/models.py msgid "Role" msgstr "角色" -#: authentik/rbac/models.py:52 +#: authentik/rbac/models.py msgid "Roles" msgstr "角色" -#: authentik/rbac/models.py:66 +#: authentik/rbac/models.py msgid "System permission" msgstr "系统权限" -#: authentik/rbac/models.py:67 +#: authentik/rbac/models.py msgid "System permissions" msgstr "系统权限" -#: authentik/rbac/models.py:69 +#: authentik/rbac/models.py msgid "Can view system info" msgstr "可以查看系统信息" -#: authentik/rbac/models.py:70 -msgid "Can view system tasks" -msgstr "可以查看系统任务" - -#: authentik/rbac/models.py:71 -msgid "Can run system tasks" -msgstr "可以运行系统任务" - -#: authentik/rbac/models.py:72 +#: authentik/rbac/models.py msgid "Can access admin interface" msgstr "可以访问管理员界面" -#: authentik/rbac/models.py:73 +#: authentik/rbac/models.py msgid "Can view system settings" msgstr "可以查看系统设置" -#: authentik/rbac/models.py:74 +#: authentik/rbac/models.py msgid "Can edit system settings" msgstr "可以编辑系统设置" -#: authentik/recovery/management/commands/create_admin_group.py:12 +#: authentik/recovery/management/commands/create_admin_group.py msgid "Create admin group if the default group gets deleted." msgstr "如果默认组被删除,则创建管理员组。" -#: authentik/recovery/management/commands/create_recovery_key.py:16 +#: authentik/recovery/management/commands/create_recovery_key.py msgid "Create a Key which can be used to restore access to authentik." msgstr "创建一个密钥,可用于恢复对 authentik 的访问权限。" -#: authentik/recovery/views.py:24 +#: authentik/recovery/views.py msgid "Used recovery-link to authenticate." msgstr "已使用恢复链接进行身份验证。" -#: authentik/sources/ldap/models.py:41 +#: authentik/sources/ldap/models.py msgid "Server URI" msgstr "服务器 URI" -#: authentik/sources/ldap/models.py:50 +#: authentik/sources/ldap/models.py msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this" " keypair." msgstr "可选,根据此密钥对中的 CA 链验证 LDAP 服务器的证书。" -#: authentik/sources/ldap/models.py:59 +#: authentik/sources/ldap/models.py msgid "" "Client certificate to authenticate against the LDAP Server's Certificate." msgstr "基于 LDAP 服务端证书进行身份验证的客户端证书。" -#: authentik/sources/ldap/models.py:62 +#: authentik/sources/ldap/models.py msgid "Bind CN" msgstr "Bind CN" -#: authentik/sources/ldap/models.py:64 +#: authentik/sources/ldap/models.py msgid "Enable Start TLS" msgstr "启用 Start TLS" -#: authentik/sources/ldap/models.py:65 +#: authentik/sources/ldap/models.py msgid "Use Server URI for SNI verification" msgstr "SNI 验证时使用服务器 URI" -#: authentik/sources/ldap/models.py:67 +#: authentik/sources/ldap/models.py msgid "Base DN" msgstr "Base DN" -#: authentik/sources/ldap/models.py:69 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for User-queries." msgstr "添加到用户查询的 Base DN 起始处。" -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py msgid "Addition User DN" msgstr "额外的用户 DN" -#: authentik/sources/ldap/models.py:74 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for Group-queries." msgstr "添加到组查询的 Base DN 起始处。" -#: authentik/sources/ldap/models.py:75 +#: authentik/sources/ldap/models.py msgid "Addition Group DN" msgstr "额外的组 DN" -#: authentik/sources/ldap/models.py:81 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Users." msgstr "将与此筛选器匹配的对象视为用户。" -#: authentik/sources/ldap/models.py:84 +#: authentik/sources/ldap/models.py msgid "Field which contains members of a group." msgstr "包含组成员的字段。" -#: authentik/sources/ldap/models.py:88 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Groups." msgstr "将与此过滤器匹配的对象视为组。" -#: authentik/sources/ldap/models.py:91 +#: authentik/sources/ldap/models.py msgid "Field which contains a unique Identifier." msgstr "包含唯一标识符的字段。" -#: authentik/sources/ldap/models.py:105 +#: authentik/sources/ldap/models.py +msgid "Update internal authentik password when login succeeds with LDAP" +msgstr "使用 LDAP 登录成功时更新内部 authentik 密码" + +#: authentik/sources/ldap/models.py msgid "" "When a user changes their password, sync it back to LDAP. This can only be " "enabled on a single LDAP source." msgstr "当用户修改密码时,将其同步回 LDAP。仅可在单点 LDAP 源时启用。" -#: authentik/sources/ldap/models.py:248 +#: authentik/sources/ldap/models.py msgid "LDAP Source" msgstr "LDAP 源" -#: authentik/sources/ldap/models.py:249 +#: authentik/sources/ldap/models.py msgid "LDAP Sources" msgstr "LDAP 源" -#: authentik/sources/ldap/models.py:271 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mapping" msgstr "LDAP 属性映射" -#: authentik/sources/ldap/models.py:272 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mappings" msgstr "LDAP 属性映射" -#: authentik/sources/ldap/signals.py:52 +#: authentik/sources/ldap/signals.py msgid "Password does not match Active Directory Complexity." msgstr "密码与 Active Directory 复杂度不匹配。" -#: authentik/sources/oauth/clients/oauth2.py:68 +#: authentik/sources/oauth/clients/oauth2.py msgid "No token received." msgstr "未收到令牌。" -#: authentik/sources/oauth/models.py:24 +#: authentik/sources/oauth/models.py msgid "Request Token URL" msgstr "请求令牌 URL" -#: authentik/sources/oauth/models.py:26 +#: authentik/sources/oauth/models.py msgid "" "URL used to request the initial token. This URL is only required for OAuth " "1." msgstr "用于请求初始令牌的 URL。只有 OAuth 1 才需要此网址。" -#: authentik/sources/oauth/models.py:32 +#: authentik/sources/oauth/models.py msgid "Authorization URL" msgstr "授权 URL" -#: authentik/sources/oauth/models.py:33 +#: authentik/sources/oauth/models.py msgid "URL the user is redirect to to conest the flow." msgstr "为控制流程,使用户被重定向到的 URL" -#: authentik/sources/oauth/models.py:38 +#: authentik/sources/oauth/models.py msgid "Access Token URL" msgstr "访问令牌 URL" -#: authentik/sources/oauth/models.py:39 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to retrieve tokens." msgstr "authentik 用来获取令牌的 URL。" -#: authentik/sources/oauth/models.py:44 +#: authentik/sources/oauth/models.py msgid "Profile URL" msgstr "个人资料 URL" -#: authentik/sources/oauth/models.py:45 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to get user information." msgstr "authentik 用来获取用户信息的 URL。" -#: authentik/sources/oauth/models.py:48 +#: authentik/sources/oauth/models.py msgid "Additional Scopes" msgstr "额外的作用域" -#: authentik/sources/oauth/models.py:107 +#: authentik/sources/oauth/models.py msgid "OAuth Source" msgstr "OAuth 源" -#: authentik/sources/oauth/models.py:108 +#: authentik/sources/oauth/models.py msgid "OAuth Sources" msgstr "OAuth 源" -#: authentik/sources/oauth/models.py:116 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Source" msgstr "GitHub OAuth 源" -#: authentik/sources/oauth/models.py:117 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Sources" msgstr "GitHub OAuth 源" -#: authentik/sources/oauth/models.py:125 +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Source" +msgstr "GitLab OAuth 源" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Sources" +msgstr "GitLab OAuth 源" + +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Source" msgstr "Twitch OAuth 源" -#: authentik/sources/oauth/models.py:126 +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Sources" msgstr "Twitch OAuth 源" -#: authentik/sources/oauth/models.py:134 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Source" msgstr "Mailcow OAuth 源" -#: authentik/sources/oauth/models.py:135 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Sources" msgstr "Mailcow OAuth 源" -#: authentik/sources/oauth/models.py:143 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Source" msgstr "Twitter OAuth 源" -#: authentik/sources/oauth/models.py:144 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Sources" msgstr "Twitter OAuth 源" -#: authentik/sources/oauth/models.py:152 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Source" msgstr "Facebook OAuth 源" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Sources" msgstr "Facebook OAuth 源" -#: authentik/sources/oauth/models.py:161 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Source" msgstr "Discord OAuth 源" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Sources" msgstr "Discord OAuth 源" -#: authentik/sources/oauth/models.py:170 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Source" msgstr "Patreon OAuth 源" -#: authentik/sources/oauth/models.py:171 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Sources" msgstr "Patreon OAuth 源" -#: authentik/sources/oauth/models.py:179 +#: authentik/sources/oauth/models.py msgid "Google OAuth Source" msgstr "Google OAuth 源" -#: authentik/sources/oauth/models.py:180 +#: authentik/sources/oauth/models.py msgid "Google OAuth Sources" msgstr "Google OAuth 源" -#: authentik/sources/oauth/models.py:188 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Source" msgstr "Azure AD OAuth 源" -#: authentik/sources/oauth/models.py:189 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Sources" msgstr "Azure AD OAuth 源" -#: authentik/sources/oauth/models.py:197 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Source" msgstr "OpenID OAuth 源" -#: authentik/sources/oauth/models.py:198 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Sources" msgstr "OpenID OAuth 源" -#: authentik/sources/oauth/models.py:206 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Source" msgstr "Apple OAuth 源" -#: authentik/sources/oauth/models.py:207 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Sources" msgstr "Apple OAuth 源" -#: authentik/sources/oauth/models.py:215 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Source" msgstr "Okta OAuth 源" -#: authentik/sources/oauth/models.py:216 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Sources" msgstr "Okta OAuth 源" -#: authentik/sources/oauth/models.py:224 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Source" msgstr "Reddit OAuth 源" -#: authentik/sources/oauth/models.py:225 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Sources" msgstr "Reddit OAuth 源" -#: authentik/sources/oauth/models.py:247 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connection" msgstr "用户 OAuth 源连接" -#: authentik/sources/oauth/models.py:248 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connections" msgstr "用户 OAuth 源连接" -#: authentik/sources/oauth/views/callback.py:100 -#, python-format -msgid "Authentication failed: %(reason)s" -msgstr "身份验证失败:%(reason)s" +#: authentik/sources/oauth/views/callback.py +#, python-brace-format +msgid "Authentication failed: {reason}" +msgstr "身份验证失败:{reason}" -#: authentik/sources/plex/models.py:37 +#: authentik/sources/plex/models.py msgid "Client identifier used to talk to Plex." msgstr "用来与 Plex 通信的客户端标识符。" -#: authentik/sources/plex/models.py:44 +#: authentik/sources/plex/models.py msgid "" "Which servers a user has to be a member of to be granted access. Empty list " "allows every server." msgstr "用户必须是哪个服务器的成员才能获取权限。空列表允许任何服务器。" -#: authentik/sources/plex/models.py:50 +#: authentik/sources/plex/models.py msgid "Allow friends to authenticate, even if you don't share a server." msgstr "允许好友进行身份验证,即使您不共享服务器。" -#: authentik/sources/plex/models.py:52 +#: authentik/sources/plex/models.py msgid "Plex token used to check friends" msgstr "用于检查好友的 Plex 令牌" -#: authentik/sources/plex/models.py:95 +#: authentik/sources/plex/models.py msgid "Plex Source" msgstr "Plex 源" -#: authentik/sources/plex/models.py:96 +#: authentik/sources/plex/models.py msgid "Plex Sources" msgstr "Plex 源" -#: authentik/sources/plex/models.py:112 +#: authentik/sources/plex/models.py msgid "User Plex Source Connection" msgstr "用户 Plex 源连接" -#: authentik/sources/plex/models.py:113 +#: authentik/sources/plex/models.py msgid "User Plex Source Connections" msgstr "用户 Plex 源连接" -#: authentik/sources/saml/models.py:40 +#: authentik/sources/saml/models.py msgid "Redirect Binding" msgstr "重定向绑定" -#: authentik/sources/saml/models.py:41 +#: authentik/sources/saml/models.py msgid "POST Binding" msgstr "POST 绑定" -#: authentik/sources/saml/models.py:42 +#: authentik/sources/saml/models.py msgid "POST Binding with auto-confirmation" msgstr "带有自动确认功能的 POST 绑定" -#: authentik/sources/saml/models.py:70 +#: authentik/sources/saml/models.py msgid "Flow used before authentication." msgstr "身份验证之前使用的流程。" -#: authentik/sources/saml/models.py:77 +#: authentik/sources/saml/models.py msgid "Issuer" msgstr "颁发者" -#: authentik/sources/saml/models.py:78 +#: authentik/sources/saml/models.py msgid "Also known as Entity ID. Defaults the Metadata URL." msgstr "也称为 Entity ID。 默认为元数据 URL。" -#: authentik/sources/saml/models.py:82 +#: authentik/sources/saml/models.py msgid "SSO URL" msgstr "SSO URL" -#: authentik/sources/saml/models.py:83 +#: authentik/sources/saml/models.py msgid "URL that the initial Login request is sent to." msgstr "初始登录请求发送到的 URL。" -#: authentik/sources/saml/models.py:89 +#: authentik/sources/saml/models.py msgid "SLO URL" msgstr "SLO URL" -#: authentik/sources/saml/models.py:90 +#: authentik/sources/saml/models.py msgid "Optional URL if your IDP supports Single-Logout." msgstr "如果您的 IDP 支持单点登出,则为可选 URL。" -#: authentik/sources/saml/models.py:96 +#: authentik/sources/saml/models.py msgid "" "Allows authentication flows initiated by the IdP. This can be a security " "risk, as no validation of the request ID is done." msgstr "允许由 IdP 启动的身份验证流程。这可能存在安全风险,因为未对请求 ID 进行验证。" -#: authentik/sources/saml/models.py:104 +#: authentik/sources/saml/models.py msgid "" "NameID Policy sent to the IdP. Can be unset, in which case no Policy is " "sent." msgstr "发送给 IdP 的 NameID 策略。可以取消设置,此时不会发送任何策略。" -#: authentik/sources/saml/models.py:115 +#: authentik/sources/saml/models.py msgid "Delete temporary users after" msgstr "多久后删除临时用户" -#: authentik/sources/saml/models.py:118 +#: authentik/sources/saml/models.py msgid "" "Time offset when temporary users should be deleted. This only applies if " "your IDP uses the NameID Format 'transient', and the user doesn't log out " @@ -2040,321 +2173,348 @@ msgstr "" "删除临时用户的时间偏移。这仅适用于您的 IDP 使用 NameID 格式 'transient' " "且用户未手动登出的情况。(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/sources/saml/models.py:142 +#: authentik/sources/saml/models.py msgid "" "Keypair used to sign outgoing Responses going to the Identity Provider." msgstr "密钥对,用于签署发送给身份提供程序的传出响应。" -#: authentik/sources/saml/models.py:226 +#: authentik/sources/saml/models.py msgid "SAML Source" msgstr "SAML 源" -#: authentik/sources/saml/models.py:227 +#: authentik/sources/saml/models.py msgid "SAML Sources" msgstr "SAML 源" -#: authentik/sources/saml/models.py:242 +#: authentik/sources/saml/models.py msgid "User SAML Source Connection" msgstr "用户 SAML 源连接" -#: authentik/sources/saml/models.py:243 +#: authentik/sources/saml/models.py msgid "User SAML Source Connections" msgstr "用户 SAML 源连接" -#: authentik/stages/authenticator_duo/models.py:79 +#: authentik/sources/scim/models.py +msgid "SCIM Source" +msgstr "SCIM 源" + +#: authentik/sources/scim/models.py +msgid "SCIM Sources" +msgstr "SCIM 源" + +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stage" msgstr "Duo 身份验证器设置阶段" -#: authentik/stages/authenticator_duo/models.py:80 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stages" msgstr "Duo 身份验证器设置阶段" -#: authentik/stages/authenticator_duo/models.py:103 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Device" msgstr "Duo 设备" -#: authentik/stages/authenticator_duo/models.py:104 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Devices" msgstr "Duo 设备" -#: authentik/stages/authenticator_sms/models.py:57 +#: authentik/stages/authenticator_sms/models.py msgid "" "When enabled, the Phone number is only used during enrollment to verify the " "users authenticity. Only a hash of the phone number is saved to ensure it is" " not reused in the future." msgstr "启用时,电话号码仅在注册期间用于验证用户的真实性。仅保存电话号码的哈希,以确保将来不会重复使用。" -#: authentik/stages/authenticator_sms/models.py:68 +#: authentik/stages/authenticator_sms/models.py msgid "Optionally modify the payload being sent to custom providers." msgstr "可选地,修改发送到自定义提供程序的载荷。" -#: authentik/stages/authenticator_sms/models.py:81 -#, python-format -msgid "Use this code to authenticate in authentik: %(token)s" -msgstr "使用此代码在 authentik 中验证身份:%(token)s" +#: authentik/stages/authenticator_sms/models.py +#, python-brace-format +msgid "Use this code to authenticate in authentik: {token}" +msgstr "使用此代码在 authentik 中验证身份:{token}" -#: authentik/stages/authenticator_sms/models.py:180 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stage" msgstr "短信身份验证器设置阶段" -#: authentik/stages/authenticator_sms/models.py:181 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stages" msgstr "短信身份验证器设置阶段" -#: authentik/stages/authenticator_sms/models.py:226 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Device" msgstr "短信设备" -#: authentik/stages/authenticator_sms/models.py:227 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Devices" msgstr "短信设备" -#: authentik/stages/authenticator_sms/stage.py:57 -#: authentik/stages/authenticator_totp/stage.py:41 -#: authentik/stages/authenticator_totp/stage.py:44 +#: authentik/stages/authenticator_sms/stage.py +#: authentik/stages/authenticator_totp/stage.py msgid "Code does not match" msgstr "代码不匹配" -#: authentik/stages/authenticator_sms/stage.py:73 +#: authentik/stages/authenticator_sms/stage.py msgid "Invalid phone number" msgstr "无效电话号码" -#: authentik/stages/authenticator_static/models.py:52 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stage" msgstr "静态身份验证器设置阶段" -#: authentik/stages/authenticator_static/models.py:53 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stages" msgstr "静态身份验证器设置阶段" -#: authentik/stages/authenticator_static/models.py:98 +#: authentik/stages/authenticator_static/models.py msgid "Static Device" msgstr "静态设备" -#: authentik/stages/authenticator_static/models.py:99 +#: authentik/stages/authenticator_static/models.py msgid "Static Devices" msgstr "静态设备" -#: authentik/stages/authenticator_static/models.py:129 +#: authentik/stages/authenticator_static/models.py msgid "Static Token" msgstr "静态令牌" -#: authentik/stages/authenticator_static/models.py:130 +#: authentik/stages/authenticator_static/models.py msgid "Static Tokens" msgstr "静态令牌" -#: authentik/stages/authenticator_totp/models.py:25 +#: authentik/stages/authenticator_totp/models.py msgid "6 digits, widely compatible" msgstr "6 位数字,广泛兼容" -#: authentik/stages/authenticator_totp/models.py:26 +#: authentik/stages/authenticator_totp/models.py msgid "8 digits, not compatible with apps like Google Authenticator" msgstr "8 位数字,与 Google 身份验证器等应用不兼容" -#: authentik/stages/authenticator_totp/models.py:62 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stage" msgstr "TOTP 身份验证器设置阶段" -#: authentik/stages/authenticator_totp/models.py:63 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stages" msgstr "TOTP 身份验证器设置阶段" -#: authentik/stages/authenticator_totp/models.py:244 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Device" msgstr "TOTP 设备" -#: authentik/stages/authenticator_totp/models.py:245 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Devices" msgstr "TOTP 设备" -#: authentik/stages/authenticator_validate/challenge.py:123 -msgid "Invalid Token" -msgstr "无效令牌" +#: authentik/stages/authenticator_validate/challenge.py +msgid "" +"Invalid Token. Please ensure the time on your device is accurate and try " +"again." +msgstr "无效的令牌。请确保设备上的时间准确并重试。" -#: authentik/stages/authenticator_validate/models.py:18 +#: authentik/stages/authenticator_validate/challenge.py +#: authentik/stages/authenticator_webauthn/stage.py +#, python-brace-format +msgid "Invalid device type. Contact your {brand} administrator for help." +msgstr "无效的设备类型。请联系您的 {brand} 管理员获得帮助。" + +#: authentik/stages/authenticator_validate/models.py msgid "Static" msgstr "静态" -#: authentik/stages/authenticator_validate/models.py:19 +#: authentik/stages/authenticator_validate/models.py msgid "TOTP" msgstr "TOTP" -#: authentik/stages/authenticator_validate/models.py:20 +#: authentik/stages/authenticator_validate/models.py msgid "WebAuthn" msgstr "WebAuthn" -#: authentik/stages/authenticator_validate/models.py:21 +#: authentik/stages/authenticator_validate/models.py msgid "Duo" msgstr "Duo" -#: authentik/stages/authenticator_validate/models.py:22 +#: authentik/stages/authenticator_validate/models.py msgid "SMS" msgstr "短信" -#: authentik/stages/authenticator_validate/models.py:49 +#: authentik/stages/authenticator_validate/models.py msgid "" "Stages used to configure Authenticator when user doesn't have any compatible" " devices. After this configuration Stage passes, the user is not prompted " "again." msgstr "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。" -#: authentik/stages/authenticator_validate/models.py:56 +#: authentik/stages/authenticator_validate/models.py msgid "Device classes which can be used to authenticate" msgstr "可用于进行身份验证的设备类型" -#: authentik/stages/authenticator_validate/models.py:64 +#: authentik/stages/authenticator_validate/models.py msgid "" "If any of the user's device has been used within this threshold, this stage " "will be skipped" msgstr "如果用户的任意设备在此期限内被使用过,此阶段会被跳过。" -#: authentik/stages/authenticator_validate/models.py:70 +#: authentik/stages/authenticator_validate/models.py msgid "Enforce user verification for WebAuthn devices." msgstr "对 WebAuthn 设备强制用户验证。" -#: authentik/stages/authenticator_validate/models.py:92 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stage" msgstr "身份验证器验证阶段" -#: authentik/stages/authenticator_validate/models.py:93 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stages" msgstr "身份验证器验证阶段" -#: authentik/stages/authenticator_webauthn/models.py:112 +#: authentik/stages/authenticator_validate/stage.py +msgid "No (allowed) MFA authenticator configured." +msgstr "未配置(允许的)MFA 身份验证器。" + +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stage" msgstr "WebAuthn 身份验证器设置阶段" -#: authentik/stages/authenticator_webauthn/models.py:113 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stages" msgstr "WebAuthn 身份验证器设置阶段" -#: authentik/stages/authenticator_webauthn/models.py:151 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Device" msgstr "WebAuthn 设备" -#: authentik/stages/authenticator_webauthn/models.py:152 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Devices" msgstr "WebAuthn 设备" -#: authentik/stages/captcha/models.py:14 +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device type" +msgstr "WebAuthn 设备类型" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device types" +msgstr "WebAuthn 设备类型" + +#: authentik/stages/captcha/models.py msgid "Public key, acquired your captcha Provider." msgstr "公钥,从您的验证码提供商处取得。" -#: authentik/stages/captcha/models.py:15 +#: authentik/stages/captcha/models.py msgid "Private key, acquired your captcha Provider." msgstr "私钥,从您的验证码提供商处取得。" -#: authentik/stages/captcha/models.py:37 +#: authentik/stages/captcha/models.py msgid "Captcha Stage" msgstr "验证码阶段" -#: authentik/stages/captcha/models.py:38 +#: authentik/stages/captcha/models.py msgid "Captcha Stages" msgstr "验证码阶段" -#: authentik/stages/consent/models.py:30 +#: authentik/stages/consent/models.py msgid "" "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "经过多少偏移量后同意授权过期。(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/stages/consent/models.py:50 +#: authentik/stages/consent/models.py msgid "Consent Stage" msgstr "同意授权阶段" -#: authentik/stages/consent/models.py:51 +#: authentik/stages/consent/models.py msgid "Consent Stages" msgstr "同意授权阶段" -#: authentik/stages/consent/models.py:72 +#: authentik/stages/consent/models.py msgid "User Consent" msgstr "用户同意授权" -#: authentik/stages/consent/models.py:73 +#: authentik/stages/consent/models.py msgid "User Consents" msgstr "用户同意授权" -#: authentik/stages/deny/models.py:32 +#: authentik/stages/deny/models.py msgid "Deny Stage" msgstr "拒绝阶段" -#: authentik/stages/deny/models.py:33 +#: authentik/stages/deny/models.py msgid "Deny Stages" msgstr "拒绝阶段" -#: authentik/stages/dummy/models.py:34 +#: authentik/stages/dummy/models.py msgid "Dummy Stage" msgstr "虚拟阶段" -#: authentik/stages/dummy/models.py:35 +#: authentik/stages/dummy/models.py msgid "Dummy Stages" msgstr "虚拟阶段" -#: authentik/stages/email/models.py:26 +#: authentik/stages/email/models.py msgid "Password Reset" msgstr "密码重置" -#: authentik/stages/email/models.py:30 +#: authentik/stages/email/models.py msgid "Account Confirmation" msgstr "账户确认" -#: authentik/stages/email/models.py:59 +#: authentik/stages/email/models.py msgid "" "When enabled, global Email connection settings will be used and connection " "settings below will be ignored." msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。" -#: authentik/stages/email/models.py:74 +#: authentik/stages/email/models.py msgid "Activate users upon completion of stage." msgstr "完成阶段后激活用户。" -#: authentik/stages/email/models.py:78 +#: authentik/stages/email/models.py msgid "Time in minutes the token sent is valid." msgstr "发出令牌的有效时间(单位为分钟)。" -#: authentik/stages/email/models.py:132 +#: authentik/stages/email/models.py msgid "Email Stage" msgstr "电子邮件阶段" -#: authentik/stages/email/models.py:133 +#: authentik/stages/email/models.py msgid "Email Stages" msgstr "电子邮件阶段" -#: authentik/stages/email/stage.py:126 +#: authentik/stages/email/stage.py msgid "Exception occurred while rendering E-mail template" msgstr "渲染电子邮件模板时发生异常" -#: authentik/stages/email/stage.py:140 +#: authentik/stages/email/stage.py msgid "Successfully verified Email." msgstr "已成功验证电子邮件。" -#: authentik/stages/email/stage.py:147 authentik/stages/email/stage.py:173 +#: authentik/stages/email/stage.py msgid "No pending user." msgstr "没有待处理的用户。" -#: authentik/stages/email/stage.py:163 +#: authentik/stages/email/stage.py msgid "Email sent." msgstr "电子邮件已发出。" -#: authentik/stages/email/stage.py:176 +#: authentik/stages/email/stage.py msgid "Email Successfully sent." msgstr "成功发送电子邮件。" -#: authentik/stages/email/templates/email/account_confirmation.html:10 -#: authentik/stages/email/templates/email/account_confirmation.txt:1 +#: authentik/stages/email/templates/email/account_confirmation.html +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "Welcome!" msgstr "欢迎!" -#: authentik/stages/email/templates/email/account_confirmation.html:19 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just press the button below." msgstr "我们很高兴您能开始使用。首先,您需要确认您的账户。只需点击下面的按钮。" -#: authentik/stages/email/templates/email/account_confirmation.html:24 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "Confirm Account" msgstr "确认账户" -#: authentik/stages/email/templates/email/account_confirmation.html:36 +#: authentik/stages/email/templates/email/account_confirmation.html #, python-format msgid "" "\n" @@ -2365,13 +2525,13 @@ msgstr "" " 如果按钮无效,请复制并在浏览器中粘贴以下链接:%(url)s\n" " " -#: authentik/stages/email/templates/email/account_confirmation.txt:3 +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just open the link below." msgstr "我们很高兴您能开始使用。首先,您需要确认您的账户。只需打开下面的链接。" -#: authentik/stages/email/templates/email/event_notification.html:46 +#: authentik/stages/email/templates/email/event_notification.html #, python-format msgid "" "\n" @@ -2382,19 +2542,19 @@ msgstr "" " 此邮件由通知递送 %(name)s 发送。\n" " " -#: authentik/stages/email/templates/email/event_notification.txt:1 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Dear authentik user," msgstr "亲爱的 authentik 用户," -#: authentik/stages/email/templates/email/event_notification.txt:3 +#: authentik/stages/email/templates/email/event_notification.txt msgid "The following notification was created:" msgstr "以下通知已创建:" -#: authentik/stages/email/templates/email/event_notification.txt:8 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Additional attributes:" msgstr "额外属性:" -#: authentik/stages/email/templates/email/event_notification.txt:13 +#: authentik/stages/email/templates/email/event_notification.txt #, python-format msgid "" "\n" @@ -2403,7 +2563,7 @@ msgstr "" "\n" "此邮件由通知递送 %(name)s 发送。\n" -#: authentik/stages/email/templates/email/password_reset.html:10 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2414,7 +2574,7 @@ msgstr "" " %(username)s 您好,\n" " " -#: authentik/stages/email/templates/email/password_reset.html:21 +#: authentik/stages/email/templates/email/password_reset.html msgid "" "\n" " You recently requested to change your password for your authentik account. Use the button below to set a new password.\n" @@ -2424,7 +2584,7 @@ msgstr "" " 您最近请求更改您的 authentik 账户密码。使用下面的按钮设置新密码。\n" " " -#: authentik/stages/email/templates/email/password_reset.html:39 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2435,12 +2595,12 @@ msgstr "" " 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n" " " -#: authentik/stages/email/templates/email/password_reset.txt:1 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "Hi %(username)s," msgstr "您好 %(username)s," -#: authentik/stages/email/templates/email/password_reset.txt:3 +#: authentik/stages/email/templates/email/password_reset.txt msgid "" "\n" "You recently requested to change your password for your authentik account. Use the link below to set a new password.\n" @@ -2448,7 +2608,7 @@ msgstr "" "\n" "您最近请求更改您的 authentik 账户密码。使用下面的链接设置新密码。\n" -#: authentik/stages/email/templates/email/password_reset.txt:7 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "" "\n" @@ -2457,11 +2617,11 @@ msgstr "" "\n" "如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n" -#: authentik/stages/email/templates/email/setup.html:9 +#: authentik/stages/email/templates/email/setup.html msgid "authentik Test-Email" msgstr "authentik 测试电子邮件" -#: authentik/stages/email/templates/email/setup.html:17 +#: authentik/stages/email/templates/email/setup.html msgid "" "\n" " This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2471,7 +2631,7 @@ msgstr "" " 这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n" " " -#: authentik/stages/email/templates/email/setup.txt:2 +#: authentik/stages/email/templates/email/setup.txt msgid "" "\n" "This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2479,263 +2639,263 @@ msgstr "" "\n" "这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n" -#: authentik/stages/identification/api.py:20 +#: authentik/stages/identification/api.py msgid "When no user fields are selected, at least one source must be selected" msgstr "如果未选择用户字段,则至少要选择一个源" -#: authentik/stages/identification/models.py:29 +#: authentik/stages/identification/models.py msgid "" "Fields of the user object to match against. (Hold shift to select multiple " "options)" msgstr "用来匹配的用户对象字段。(按住 Shift 多选)" -#: authentik/stages/identification/models.py:47 +#: authentik/stages/identification/models.py msgid "When enabled, user fields are matched regardless of their casing." msgstr "启用后,无论大小写如何,都将匹配用户字段。" -#: authentik/stages/identification/models.py:52 +#: authentik/stages/identification/models.py msgid "" "When a valid username/email has been entered, and this option is enabled, " "the user's username and avatar will be shown. Otherwise, the text that the " "user entered will be shown" msgstr "如果输入了有效的用户名/电子邮箱,并且启用了此选项,则会显示用户的用户名和头像。否则,将显示用户输入的文本" -#: authentik/stages/identification/models.py:60 +#: authentik/stages/identification/models.py msgid "" "When enabled, the stage will succeed and continue even when incorrect user " "info is entered." msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。" -#: authentik/stages/identification/models.py:72 +#: authentik/stages/identification/models.py msgid "Optional enrollment flow, which is linked at the bottom of the page." msgstr "可选注册流程,链接在页面底部。" -#: authentik/stages/identification/models.py:81 +#: authentik/stages/identification/models.py msgid "Optional recovery flow, which is linked at the bottom of the page." msgstr "可选的恢复流程,链接在页面底部。" -#: authentik/stages/identification/models.py:90 +#: authentik/stages/identification/models.py msgid "Optional passwordless flow, which is linked at the bottom of the page." msgstr "可选的无密码流程,链接在页面底部。" -#: authentik/stages/identification/models.py:94 +#: authentik/stages/identification/models.py msgid "Specify which sources should be shown." msgstr "指定应显示哪些源。" -#: authentik/stages/identification/models.py:115 +#: authentik/stages/identification/models.py msgid "Identification Stage" msgstr "识别阶段" -#: authentik/stages/identification/models.py:116 +#: authentik/stages/identification/models.py msgid "Identification Stages" msgstr "识别阶段" -#: authentik/stages/identification/stage.py:188 +#: authentik/stages/identification/stage.py msgid "Log in" msgstr "登录" -#: authentik/stages/identification/stage.py:189 +#: authentik/stages/identification/stage.py msgid "Continue" msgstr "继续" -#: authentik/stages/invitation/models.py:21 +#: authentik/stages/invitation/models.py msgid "" "If this flag is set, this Stage will jump to the next Stage when no " "Invitation is given. By default this Stage will cancel the Flow when no " "invitation is given." msgstr "如果设置了此标志,则当没有发出邀请时,此阶段将跳转到下一个阶段。默认情况下,当没有发出邀请时,此阶段将取消流程。" -#: authentik/stages/invitation/models.py:44 +#: authentik/stages/invitation/models.py msgid "Invitation Stage" msgstr "邀请阶段" -#: authentik/stages/invitation/models.py:45 +#: authentik/stages/invitation/models.py msgid "Invitation Stages" msgstr "邀请阶段" -#: authentik/stages/invitation/models.py:60 +#: authentik/stages/invitation/models.py msgid "When set, only the configured flow can use this invitation." msgstr "设置时,只有配置的流程可以使用此邀请。" -#: authentik/stages/invitation/models.py:64 +#: authentik/stages/invitation/models.py msgid "When enabled, the invitation will be deleted after usage." msgstr "启用后,邀请将在使用后被删除。" -#: authentik/stages/invitation/models.py:71 +#: authentik/stages/invitation/models.py msgid "Optional fixed data to enforce on user enrollment." msgstr "在用户注册时强制设置的可选固定数据。" -#: authentik/stages/invitation/models.py:84 +#: authentik/stages/invitation/models.py msgid "Invitation" msgstr "邀请" -#: authentik/stages/invitation/models.py:85 +#: authentik/stages/invitation/models.py msgid "Invitations" msgstr "邀请" -#: authentik/stages/invitation/stage.py:62 +#: authentik/stages/invitation/stage.py msgid "Invalid invite/invite not found" msgstr "邀请无效/未找到" -#: authentik/stages/password/models.py:20 +#: authentik/stages/password/models.py msgid "User database + standard password" msgstr "用户数据库 + 标准密码" -#: authentik/stages/password/models.py:24 +#: authentik/stages/password/models.py msgid "User database + app passwords" msgstr "用户数据库 + 应用程序密码" -#: authentik/stages/password/models.py:28 +#: authentik/stages/password/models.py msgid "User database + LDAP password" msgstr "用户数据库 + LDAP 密码" -#: authentik/stages/password/models.py:38 +#: authentik/stages/password/models.py msgid "Selection of backends to test the password against." msgstr "选择用于测试密码的后端。" -#: authentik/stages/password/models.py:43 +#: authentik/stages/password/models.py msgid "" "How many attempts a user has before the flow is canceled. To lock the user " "out, use a reputation policy and a user_write stage." msgstr "在取消流程之前,用户可以尝试多少次。要锁定用户,请使用信誉策略和 user_write 阶段。" -#: authentik/stages/password/models.py:75 +#: authentik/stages/password/models.py msgid "Password Stage" msgstr "密码阶段" -#: authentik/stages/password/models.py:76 +#: authentik/stages/password/models.py msgid "Password Stages" msgstr "密码阶段" -#: authentik/stages/password/stage.py:124 +#: authentik/stages/password/stage.py msgid "Invalid password" msgstr "无效密码" -#: authentik/stages/prompt/models.py:43 +#: authentik/stages/prompt/models.py msgid "Text: Simple Text input" msgstr "文本:简单文本输入" -#: authentik/stages/prompt/models.py:45 +#: authentik/stages/prompt/models.py msgid "Text area: Multiline Text Input." msgstr "文本框:多行文本输入。" -#: authentik/stages/prompt/models.py:48 +#: authentik/stages/prompt/models.py msgid "Text (read-only): Simple Text input, but cannot be edited." msgstr "文本(只读):简单文本输入,但无法编辑。" -#: authentik/stages/prompt/models.py:52 +#: authentik/stages/prompt/models.py msgid "Text area (read-only): Multiline Text input, but cannot be edited." msgstr "文本框(只读):多行文本输入,但无法编辑。" -#: authentik/stages/prompt/models.py:58 +#: authentik/stages/prompt/models.py msgid "" "Username: Same as Text input, but checks for and prevents duplicate " "usernames." msgstr "用户名:与文本输入相同,但检查并防止用户名重复。" -#: authentik/stages/prompt/models.py:60 +#: authentik/stages/prompt/models.py msgid "Email: Text field with Email type." msgstr "电子邮箱:电子邮箱类型的文本字段。" -#: authentik/stages/prompt/models.py:64 +#: authentik/stages/prompt/models.py msgid "" "Password: Masked input, multiple inputs of this type on the same prompt need" " to be identical." msgstr "密码:屏蔽显示输入内容,多个此类型的输入如果在同一个输入项下,则内容需要相同。" -#: authentik/stages/prompt/models.py:71 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a group of radio buttons." msgstr "显示为一组单选按钮的固定选项字段。" -#: authentik/stages/prompt/models.py:73 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a dropdown." msgstr "显示为下拉框的固定选项字段。" -#: authentik/stages/prompt/models.py:80 +#: authentik/stages/prompt/models.py msgid "" "File: File upload for arbitrary files. File content will be available in " "flow context as data-URI" msgstr "文件:任意文件上传。文件内容将在流程上下文中以 data-URI 形式提供" -#: authentik/stages/prompt/models.py:85 +#: authentik/stages/prompt/models.py msgid "Separator: Static Separator Line" msgstr "分隔符:静态分隔线" -#: authentik/stages/prompt/models.py:86 +#: authentik/stages/prompt/models.py msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "隐藏:隐藏字段,可用于将数据插入表单。" -#: authentik/stages/prompt/models.py:87 +#: authentik/stages/prompt/models.py msgid "Static: Static value, displayed as-is." msgstr "静态:静态值,按原样显示。" -#: authentik/stages/prompt/models.py:89 +#: authentik/stages/prompt/models.py msgid "authentik: Selection of locales authentik supports" msgstr "authentik:选择 authentik 支持的语言环境" -#: authentik/stages/prompt/models.py:116 +#: authentik/stages/prompt/models.py msgid "Name of the form field, also used to store the value" msgstr "表单域的名称,也用于存储值" -#: authentik/stages/prompt/models.py:124 +#: authentik/stages/prompt/models.py msgid "" "Optionally provide a short hint that describes the expected input value. " "When creating a fixed choice field, enable interpreting as expression and " "return a list to return multiple choices." msgstr "可选的简短提示,用来描述期望的输入值。在创建固定选项字段时,启用以表达式解释,并返回多个选项的列表。" -#: authentik/stages/prompt/models.py:132 +#: authentik/stages/prompt/models.py msgid "" "Optionally pre-fill the input with an initial value. When creating a fixed " "choice field, enable interpreting as expression and return a list to return " "multiple default choices." msgstr "可选的预设输入初始值。在创建固定选项字段时,启用以表达式解释,并返回多个默认选项的列表。" -#: authentik/stages/prompt/models.py:321 +#: authentik/stages/prompt/models.py msgid "Prompt" msgstr "输入" -#: authentik/stages/prompt/models.py:322 +#: authentik/stages/prompt/models.py msgid "Prompts" msgstr "输入" -#: authentik/stages/prompt/models.py:349 +#: authentik/stages/prompt/models.py msgid "Prompt Stage" msgstr "输入阶段" -#: authentik/stages/prompt/models.py:350 +#: authentik/stages/prompt/models.py msgid "Prompt Stages" msgstr "输入阶段" -#: authentik/stages/prompt/stage.py:108 +#: authentik/stages/prompt/stage.py msgid "Passwords don't match." msgstr "密码不匹配。" -#: authentik/stages/user_delete/models.py:31 +#: authentik/stages/user_delete/models.py msgid "User Delete Stage" msgstr "用户删除阶段" -#: authentik/stages/user_delete/models.py:32 +#: authentik/stages/user_delete/models.py msgid "User Delete Stages" msgstr "用户删除阶段" -#: authentik/stages/user_delete/stage.py:18 +#: authentik/stages/user_delete/stage.py msgid "No Pending User." msgstr "没有待处理的用户。" -#: authentik/stages/user_login/models.py:47 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured network" msgstr "将此阶段创建的会话与配置的网络绑定" -#: authentik/stages/user_login/models.py:52 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured GeoIP location" msgstr "将此阶段创建的会话与配置的 GeoIP 位置绑定" -#: authentik/stages/user_login/models.py:55 +#: authentik/stages/user_login/models.py msgid "Terminate all other sessions of the user logging in." msgstr "终止用户登录的所有其他会话。" -#: authentik/stages/user_login/models.py:61 +#: authentik/stages/user_login/models.py msgid "" "Offset the session will be extended by when the user picks the remember me " "option. Default of 0 means that the remember me option will not be shown. " @@ -2744,113 +2904,120 @@ msgstr "" "当用户选择“记住我”选项时,会话将会延长的时间。默认值 0 " "表示不显示“记住我”选项。(格式:hours=-1;minutes=-2;seconds=-3)" -#: authentik/stages/user_login/models.py:84 +#: authentik/stages/user_login/models.py msgid "User Login Stage" msgstr "用户登录阶段" -#: authentik/stages/user_login/models.py:85 +#: authentik/stages/user_login/models.py msgid "User Login Stages" msgstr "用户登录阶段" -#: authentik/stages/user_login/stage.py:85 +#: authentik/stages/user_login/stage.py msgid "No Pending user to login." msgstr "没有待定用户可以登录。" -#: authentik/stages/user_login/stage.py:112 +#: authentik/stages/user_login/stage.py msgid "Successfully logged in!" msgstr "已成功登录!" -#: authentik/stages/user_logout/models.py:30 +#: authentik/stages/user_logout/models.py msgid "User Logout Stage" msgstr "用户登出阶段" -#: authentik/stages/user_logout/models.py:31 +#: authentik/stages/user_logout/models.py msgid "User Logout Stages" msgstr "用户登出阶段" -#: authentik/stages/user_write/models.py:31 +#: authentik/stages/user_write/models.py msgid "When set, newly created users are inactive and cannot login." msgstr "设置后,新创建的用户将处于未激活状态,且无法登录。" -#: authentik/stages/user_write/models.py:39 +#: authentik/stages/user_write/models.py msgid "Optionally add newly created users to this group." msgstr "可选,将新创建的用户添加到此组。" -#: authentik/stages/user_write/models.py:68 +#: authentik/stages/user_write/models.py msgid "User Write Stage" msgstr "用户写入阶段" -#: authentik/stages/user_write/models.py:69 +#: authentik/stages/user_write/models.py msgid "User Write Stages" msgstr "用户写入阶段" -#: authentik/stages/user_write/stage.py:141 +#: authentik/stages/user_write/stage.py msgid "No Pending data." msgstr "没有待处理的数据。" -#: authentik/stages/user_write/stage.py:147 +#: authentik/stages/user_write/stage.py msgid "No user found and can't create new user." msgstr "未找到用户并且无法创建新用户。" -#: authentik/stages/user_write/stage.py:164 -#: authentik/stages/user_write/stage.py:178 +#: authentik/stages/user_write/stage.py msgid "Failed to update user. Please try again later." msgstr "更新用户失败。请稍后重试。" -#: authentik/tenants/models.py:29 +#: authentik/tenants/models.py msgid "" "Schema name must start with t_, only contain lowercase letters and numbers " "and be less than 63 characters." msgstr "模式名称必须以 t_ 开始,只能包含小写字母和数字,并且少于 63 个字符。" -#: authentik/tenants/models.py:49 +#: authentik/tenants/models.py msgid "Configure how authentik should show avatars for users." msgstr "配置 authentik 应该如何显示用户头像。" -#: authentik/tenants/models.py:53 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their name." msgstr "启用用户修改自己名称的能力。" -#: authentik/tenants/models.py:56 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their email address." msgstr "启用用户修改自己电子邮件地址的能力。" -#: authentik/tenants/models.py:59 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their username." msgstr "启用用户修改自己用户名的能力。" -#: authentik/tenants/models.py:65 +#: authentik/tenants/models.py msgid "" "Events will be deleted after this duration.(Format: " "weeks=3;days=2;hours=3,seconds=2)." msgstr "事件会在多久后被删除。(格式:weeks=3;days=2;hours=3,seconds=2)。" -#: authentik/tenants/models.py:69 +#: authentik/tenants/models.py msgid "The option configures the footer links on the flow executor pages." msgstr "此选项配置流程执行器页面上的页脚链接。" -#: authentik/tenants/models.py:75 +#: authentik/tenants/models.py msgid "" "When enabled, all the events caused by a user will be deleted upon the " "user's deletion." msgstr "启用时,所有由用户造成的事件会在相应用户被删除时一并删除。" -#: authentik/tenants/models.py:81 +#: authentik/tenants/models.py msgid "Globally enable/disable impersonation." msgstr "全局启用/禁用模拟身份。" -#: authentik/tenants/models.py:104 +#: authentik/tenants/models.py +msgid "Default token duration" +msgstr "默认令牌持续时间" + +#: authentik/tenants/models.py +msgid "Default token length" +msgstr "默认令牌长度" + +#: authentik/tenants/models.py msgid "Tenant" msgstr "租户" -#: authentik/tenants/models.py:105 +#: authentik/tenants/models.py msgid "Tenants" msgstr "租户" -#: authentik/tenants/models.py:125 +#: authentik/tenants/models.py msgid "Domain" msgstr "域名" -#: authentik/tenants/models.py:126 +#: authentik/tenants/models.py msgid "Domains" msgstr "域名" diff --git a/locale/zh_CN/LC_MESSAGES/django.mo b/locale/zh_CN/LC_MESSAGES/django.mo index 2d4f243245..4630250f3f 100644 Binary files a/locale/zh_CN/LC_MESSAGES/django.mo and b/locale/zh_CN/LC_MESSAGES/django.mo differ diff --git a/locale/zh_CN/LC_MESSAGES/django.po b/locale/zh_CN/LC_MESSAGES/django.po index 5b3f48dcdb..83e21d55b5 100644 --- a/locale/zh_CN/LC_MESSAGES/django.po +++ b/locale/zh_CN/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ # Translators: # Chen Zhikai, 2022 # 刘松, 2022 -# Jens L. , 2024 +# Jens L. , 2024 # deluxghost, 2024 # #, fuzzy @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-23 08:02+0000\n" +"POT-Creation-Date: 2024-05-23 00:07+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n" "Last-Translator: deluxghost, 2024\n" "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" @@ -24,37 +24,32 @@ msgstr "" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: authentik/admin/api/tasks.py:127 -#, python-format -msgid "Successfully re-scheduled Task %(name)s!" -msgstr "已成功重新安排任务 %(name)s!" - -#: authentik/api/schema.py:25 +#: authentik/api/schema.py msgid "Generic API Error" msgstr "通用 API 错误" -#: authentik/api/schema.py:33 +#: authentik/api/schema.py msgid "Validation Error" msgstr "校验错误" -#: authentik/blueprints/api.py:43 +#: authentik/blueprints/api.py msgid "Blueprint file does not exist" msgstr "蓝图文件不存在" -#: authentik/blueprints/api.py:54 -#, python-format -msgid "Failed to validate blueprint: %(logs)s" -msgstr "验证蓝图失败:%(logs)s" +#: authentik/blueprints/api.py +#, python-brace-format +msgid "Failed to validate blueprint: {logs}" +msgstr "验证蓝图失败:{logs}" -#: authentik/blueprints/api.py:59 +#: authentik/blueprints/api.py msgid "Either path or content must be set." msgstr "必须设置路径或内容。" -#: authentik/blueprints/models.py:30 +#: authentik/blueprints/models.py msgid "Managed by authentik" msgstr "由 authentik 管理" -#: authentik/blueprints/models.py:32 +#: authentik/blueprints/models.py msgid "" "Objects that are managed by authentik. These objects are created and updated" " automatically. This flag only indicates that an object can be overwritten " @@ -64,248 +59,262 @@ msgstr "" "由 authentik 管理的对象。这些对象会自动创建和更新。此标记仅仅表明对象可以被 Migration 覆盖。您仍然可以通过 API " "修改对象,但这些修改可能会在之后的更新中被覆盖。" -#: authentik/blueprints/models.py:112 +#: authentik/blueprints/models.py msgid "Blueprint Instance" msgstr "蓝图实例" -#: authentik/blueprints/models.py:113 +#: authentik/blueprints/models.py msgid "Blueprint Instances" msgstr "蓝图实例" -#: authentik/blueprints/v1/exporter.py:62 -#, python-format -msgid "authentik Export - %(date)s" -msgstr "authentik 导出 - %(date)s" +#: authentik/blueprints/v1/exporter.py +#, python-brace-format +msgid "authentik Export - {date}" +msgstr "authentik 导出 - {date}" -#: authentik/blueprints/v1/tasks.py:151 authentik/crypto/tasks.py:93 +#: authentik/blueprints/v1/tasks.py authentik/crypto/tasks.py #, python-format msgid "Successfully imported %(count)d files." msgstr "已成功导入 %(count)d 个文件。" -#: authentik/brands/models.py:22 +#: authentik/brands/models.py msgid "" "Domain that activates this brand. Can be a superset, i.e. `a.b` for `aa.b` " "and `ba.b`" msgstr "激活此品牌的域。可以是超集,即 `a.b` 可以同时表示 `aa.b` 和 `ba.b`" -#: authentik/brands/models.py:58 +#: authentik/brands/models.py msgid "Web Certificate used by the authentik Core webserver." msgstr "authentik 核心 Web 服务器使用的 Web 证书。" -#: authentik/brands/models.py:84 +#: authentik/brands/models.py msgid "Brand" msgstr "品牌" -#: authentik/brands/models.py:85 +#: authentik/brands/models.py msgid "Brands" msgstr "品牌" -#: authentik/core/api/providers.py:122 -msgid "SAML Provider from Metadata" -msgstr "来自元数据的 SAML 提供程序" +#: authentik/core/api/providers.py +msgid "" +"When not set all providers are returned. When set to true, only backchannel " +"providers are returned. When set to false, backchannel providers are " +"excluded" +msgstr "如果未设置,则返回所有提供程序。如果启用,仅返回反向通道提供程序。如果禁用,则返回非反向通道提供程序" -#: authentik/core/api/providers.py:123 -msgid "Create a SAML Provider by importing its Metadata." -msgstr "通过导入元数据来创建 SAML 提供程序。" - -#: authentik/core/api/users.py:149 +#: authentik/core/api/users.py msgid "No leading or trailing slashes allowed." msgstr "不允许前缀或后缀斜线。" -#: authentik/core/api/users.py:152 +#: authentik/core/api/users.py msgid "No empty segments in user path allowed." msgstr "不允许用户路径包含空段。" -#: authentik/core/models.py:85 +#: authentik/core/models.py msgid "name" msgstr "名称" -#: authentik/core/models.py:87 +#: authentik/core/models.py msgid "Users added to this group will be superusers." msgstr "添加到该组的用户均为超级用户。" -#: authentik/core/models.py:161 +#: authentik/core/models.py msgid "Group" msgstr "组" -#: authentik/core/models.py:162 +#: authentik/core/models.py msgid "Groups" msgstr "组" -#: authentik/core/models.py:177 +#: authentik/core/models.py +msgid "Add user to group" +msgstr "添加用户到组" + +#: authentik/core/models.py +msgid "Remove user from group" +msgstr "从组中删除用户" + +#: authentik/core/models.py msgid "User's display name." msgstr "用户的显示名称。" -#: authentik/core/models.py:273 authentik/providers/oauth2/models.py:295 +#: authentik/core/models.py authentik/providers/oauth2/models.py msgid "User" msgstr "用户" -#: authentik/core/models.py:274 +#: authentik/core/models.py msgid "Users" msgstr "用户" -#: authentik/core/models.py:276 -#: authentik/stages/email/templates/email/password_reset.html:28 +#: authentik/core/models.py +#: authentik/stages/email/templates/email/password_reset.html msgid "Reset Password" msgstr "重置密码" -#: authentik/core/models.py:277 +#: authentik/core/models.py msgid "Can impersonate other users" msgstr "可以模拟其他用户的身份" -#: authentik/core/models.py:278 authentik/rbac/models.py:54 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can assign permissions to users" msgstr "可以为用户分配权限" -#: authentik/core/models.py:279 authentik/rbac/models.py:55 +#: authentik/core/models.py authentik/rbac/models.py msgid "Can unassign permissions from users" msgstr "可以取消分配用户的权限" -#: authentik/core/models.py:293 +#: authentik/core/models.py +msgid "Can preview user data sent to providers" +msgstr "可以预览发送给提供程序的用户数据" + +#: authentik/core/models.py +msgid "View applications the user has access to" +msgstr "查看用户有权访问的应用程序" + +#: authentik/core/models.py msgid "" "Flow used for authentication when the associated application is accessed by " "an un-authenticated user." msgstr "当关联应用程序被未验证身份的用户访问时,用于身份验证的流程。" -#: authentik/core/models.py:303 +#: authentik/core/models.py msgid "Flow used when authorizing this provider." msgstr "授权此提供程序时使用的流程。" -#: authentik/core/models.py:315 +#: authentik/core/models.py msgid "" "Accessed from applications; optional backchannel providers for protocols " "like LDAP and SCIM." msgstr "从应用程序访问;为类似 LDAP 和 SCIM 的协议提供的可选反向通道提供程序。" -#: authentik/core/models.py:370 +#: authentik/core/models.py msgid "Application's display Name." msgstr "应用的显示名称。" -#: authentik/core/models.py:371 +#: authentik/core/models.py msgid "Internal application name, used in URLs." msgstr "应用的内部名称,在 URL 中使用。" -#: authentik/core/models.py:383 +#: authentik/core/models.py msgid "Open launch URL in a new browser tab or window." msgstr "在新浏览器标签页或窗口中打开启动 URL。" -#: authentik/core/models.py:447 +#: authentik/core/models.py msgid "Application" msgstr "应用程序" -#: authentik/core/models.py:448 +#: authentik/core/models.py msgid "Applications" msgstr "应用程序" -#: authentik/core/models.py:454 +#: authentik/core/models.py msgid "Use the source-specific identifier" msgstr "使用源特定的标识符" -#: authentik/core/models.py:456 +#: authentik/core/models.py msgid "" "Link to a user with identical email address. Can have security implications " "when a source doesn't validate email addresses." msgstr "链接到电子邮件地址相同的用户。当源不验证电子邮件地址时,可能会有安全隐患。" -#: authentik/core/models.py:460 +#: authentik/core/models.py msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." msgstr "使用用户的电子邮件地址,但在电子邮件地址已存在时拒绝注册。" -#: authentik/core/models.py:463 +#: authentik/core/models.py msgid "" "Link to a user with identical username. Can have security implications when " "a username is used with another source." msgstr "链接到用户名相同的用户。当其他源使用相同用户名时,可能会有安全隐患。" -#: authentik/core/models.py:467 +#: authentik/core/models.py msgid "" "Use the user's username, but deny enrollment when the username already " "exists." msgstr "使用用户的用户名,但在用户名已存在时拒绝注册。" -#: authentik/core/models.py:474 +#: authentik/core/models.py msgid "Source's display Name." msgstr "源的显示名称。" -#: authentik/core/models.py:475 +#: authentik/core/models.py msgid "Internal source name, used in URLs." msgstr "源的内部名称,在 URL 中使用。" -#: authentik/core/models.py:494 +#: authentik/core/models.py msgid "Flow to use when authenticating existing users." msgstr "认证已存在用户时所使用的流程。" -#: authentik/core/models.py:503 +#: authentik/core/models.py msgid "Flow to use when enrolling new users." msgstr "新用户注册的流程。" -#: authentik/core/models.py:511 +#: authentik/core/models.py msgid "" "How the source determines if an existing user should be authenticated or a " "new user enrolled." msgstr "源怎样确定应该验证已有用户的身份还是注册新用户。" -#: authentik/core/models.py:683 +#: authentik/core/models.py msgid "Token" msgstr "令牌" -#: authentik/core/models.py:684 +#: authentik/core/models.py msgid "Tokens" msgstr "令牌" -#: authentik/core/models.py:689 +#: authentik/core/models.py msgid "View token's key" msgstr "查看令牌密钥" -#: authentik/core/models.py:725 +#: authentik/core/models.py msgid "Property Mapping" msgstr "属性映射" -#: authentik/core/models.py:726 +#: authentik/core/models.py msgid "Property Mappings" msgstr "属性映射" -#: authentik/core/models.py:763 +#: authentik/core/models.py msgid "Authenticated Session" msgstr "已认证会话" -#: authentik/core/models.py:764 +#: authentik/core/models.py msgid "Authenticated Sessions" msgstr "已认证会话" -#: authentik/core/sources/flow_manager.py:190 -#, python-format +#: authentik/core/sources/flow_manager.py +#, python-brace-format msgid "" -"Request to authenticate with %(source)s has been denied. Please authenticate" -" with the source you've previously signed up with." -msgstr "来自 %(source)s 的身份验证请求被拒绝。请用您注册时使用的方式验证身份。" +"Request to authenticate with {source} has been denied. Please authenticate " +"with the source you've previously signed up with." +msgstr "来自 {source} 的身份验证请求被拒绝。请用您注册时使用的方式验证身份。" -#: authentik/core/sources/flow_manager.py:242 +#: authentik/core/sources/flow_manager.py msgid "Configured flow does not exist." msgstr "配置的流程不存在。" -#: authentik/core/sources/flow_manager.py:272 -#: authentik/core/sources/flow_manager.py:324 -#, python-format -msgid "Successfully authenticated with %(source)s!" -msgstr "成功通过 %(source)s 认证!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully authenticated with {source}!" +msgstr "成功通过 {source} 认证!" -#: authentik/core/sources/flow_manager.py:296 -#, python-format -msgid "Successfully linked %(source)s!" -msgstr "成功链接 %(source)s!" +#: authentik/core/sources/flow_manager.py +#, python-brace-format +msgid "Successfully linked {source}!" +msgstr "成功链接 {source}!" -#: authentik/core/sources/flow_manager.py:315 +#: authentik/core/sources/flow_manager.py msgid "Source is not configured for enrollment." msgstr "源未被配置用于注册。" -#: authentik/core/templates/if/end_session.html:7 +#: authentik/core/templates/if/end_session.html msgid "End session" msgstr "结束会话" -#: authentik/core/templates/if/end_session.html:11 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -314,7 +323,7 @@ msgstr "" "\n" "您已登出 %(application)s。\n" -#: authentik/core/templates/if/end_session.html:19 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -324,11 +333,11 @@ msgstr "" "\n" " 您已成功登出 %(application)s 。现在您可以返回总览页来启动其他应用,或者登出您的 %(branding_title)s 账户。" -#: authentik/core/templates/if/end_session.html:25 +#: authentik/core/templates/if/end_session.html msgid "Go back to overview" msgstr "返回总览" -#: authentik/core/templates/if/end_session.html:29 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -339,7 +348,7 @@ msgstr "" " 登出 %(branding_title)s\n" " " -#: authentik/core/templates/if/end_session.html:36 +#: authentik/core/templates/if/end_session.html #, python-format msgid "" "\n" @@ -350,344 +359,455 @@ msgstr "" " 重新登录 %(application)s\n" " " -#: authentik/core/templates/if/error.html:18 +#: authentik/core/templates/if/error.html msgid "Go home" msgstr "前往首页" -#: authentik/core/templates/login/base_full.html:75 +#: authentik/core/templates/login/base_full.html msgid "Powered by authentik" msgstr "由 authentik 强力驱动" -#: authentik/core/views/apps.py:53 -#: authentik/providers/oauth2/views/authorize.py:434 -#: authentik/providers/oauth2/views/device_init.py:70 -#: authentik/providers/saml/views/sso.py:70 +#: authentik/core/views/apps.py authentik/providers/oauth2/views/authorize.py +#: authentik/providers/oauth2/views/device_init.py +#: authentik/providers/saml/views/sso.py #, python-format msgid "You're about to sign into %(application)s." msgstr "您即将登录 %(application)s。" -#: authentik/crypto/api.py:179 +#: authentik/crypto/api.py msgid "Subject-alt name" msgstr "替代名称" -#: authentik/crypto/models.py:30 +#: authentik/crypto/builder.py +msgid "rsa" +msgstr "rsa" + +#: authentik/crypto/builder.py +msgid "ecdsa" +msgstr "ecdsa" + +#: authentik/crypto/models.py msgid "PEM-encoded Certificate data" msgstr "PEM 编码的证书数据" -#: authentik/crypto/models.py:33 +#: authentik/crypto/models.py msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." msgstr "可选私钥。如果设置,则可以使用此密钥对来加密。" -#: authentik/crypto/models.py:101 +#: authentik/crypto/models.py msgid "Certificate-Key Pair" msgstr "证书密钥对" -#: authentik/crypto/models.py:102 +#: authentik/crypto/models.py msgid "Certificate-Key Pairs" msgstr "证书密钥对" -#: authentik/enterprise/api.py:33 +#: authentik/enterprise/api.py msgid "Enterprise is required to create/update this object." msgstr "创建/更新此对象需要企业版。" -#: authentik/enterprise/models.py:183 +#: authentik/enterprise/models.py msgid "License" msgstr "许可证" -#: authentik/enterprise/models.py:184 +#: authentik/enterprise/models.py msgid "Licenses" msgstr "许可证" -#: authentik/enterprise/models.py:206 +#: authentik/enterprise/models.py msgid "License Usage" msgstr "许可证使用情况" -#: authentik/enterprise/models.py:207 +#: authentik/enterprise/models.py msgid "License Usage Records" msgstr "许可证使用情况记录" -#: authentik/enterprise/policy.py:18 +#: authentik/enterprise/policy.py msgid "Enterprise required to access this feature." msgstr "访问此功能需要企业版。" -#: authentik/enterprise/policy.py:20 +#: authentik/enterprise/policy.py msgid "Feature only accessible for internal users." msgstr "仅内部用户能访问此功能。" -#: authentik/enterprise/providers/rac/models.py:48 -#: authentik/stages/user_login/models.py:39 +#: authentik/enterprise/providers/google_workspace/models.py +#: authentik/enterprise/providers/microsoft_entra/models.py +#: authentik/providers/scim/models.py authentik/sources/ldap/models.py +msgid "Property mappings used for group creation/updating." +msgstr "用于创建/更新组的属性映射。" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider" +msgstr "Google Workspace 提供程序" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Providers" +msgstr "Google Workspace 提供程序" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mapping" +msgstr "Google Workspace 提供程序映射" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Mappings" +msgstr "Google Workspace 提供程序映射" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider User" +msgstr "Google Workspace 提供程序用户" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Users" +msgstr "Google Workspace 提供程序用户" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Group" +msgstr "Google Workspace 提供程序组" + +#: authentik/enterprise/providers/google_workspace/models.py +msgid "Google Workspace Provider Groups" +msgstr "Google Workspace 提供程序组" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider" +msgstr "Microsoft Entra 提供程序" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Providers" +msgstr "Microsoft Entra 提供程序" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mapping" +msgstr "Microsoft Entra 提供程序映射" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Mappings" +msgstr "Microsoft Entra 提供程序映射" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider User" +msgstr "Microsoft Entra 提供程序用户" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Group" +msgstr "Microsoft Entra 提供程序组" + +#: authentik/enterprise/providers/microsoft_entra/models.py +msgid "Microsoft Entra Provider Groups" +msgstr "Microsoft Entra 提供程序组" + +#: authentik/enterprise/providers/rac/models.py +#: authentik/stages/user_login/models.py msgid "" "Determines how long a session lasts. Default of 0 means that the sessions " "lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)" -#: authentik/enterprise/providers/rac/models.py:71 +#: authentik/enterprise/providers/rac/models.py +msgid "When set to true, connection tokens will be deleted upon disconnect." +msgstr "启用时,连接令牌将会在断开连接时被删除。" + +#: authentik/enterprise/providers/rac/models.py msgid "RAC Provider" msgstr "RAC 提供程序" -#: authentik/enterprise/providers/rac/models.py:72 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Providers" msgstr "RAC 提供程序" -#: authentik/enterprise/providers/rac/models.py:100 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoint" msgstr "RAC 端点" -#: authentik/enterprise/providers/rac/models.py:101 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Endpoints" msgstr "RAC 端点" -#: authentik/enterprise/providers/rac/models.py:122 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mapping" msgstr "RAC 属性映射" -#: authentik/enterprise/providers/rac/models.py:123 +#: authentik/enterprise/providers/rac/models.py msgid "RAC Property Mappings" msgstr "RAC 属性映射" -#: authentik/enterprise/providers/rac/views.py:108 +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection token" +msgstr "RAC 连接令牌" + +#: authentik/enterprise/providers/rac/models.py +msgid "RAC Connection tokens" +msgstr "RAC 连接令牌" + +#: authentik/enterprise/providers/rac/views.py msgid "Maximum connection limit reached." msgstr "已达到最大连接数。" -#: authentik/enterprise/providers/rac/views.py:112 +#: authentik/enterprise/providers/rac/views.py msgid "(You are already connected in another tab/window)" msgstr "(您已经在另一个标签页/窗口连接了)" -#: authentik/events/models.py:289 +#: authentik/enterprise/stages/source/models.py +msgid "" +"Amount of time a user can take to return from the source to continue the " +"flow (Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "用户从源返回并继续流程可以消耗的时间(格式:hours=-1;minutes=-2;seconds=-3)" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stage" +msgstr "源阶段" + +#: authentik/enterprise/stages/source/models.py +msgid "Source Stages" +msgstr "源阶段" + +#: authentik/events/api/tasks.py +#, python-brace-format +msgid "Successfully started task {name}." +msgstr "已成功开始任务 {name}。" + +#: authentik/events/models.py msgid "Event" msgstr "事件" -#: authentik/events/models.py:290 +#: authentik/events/models.py msgid "Events" msgstr "事件" -#: authentik/events/models.py:296 +#: authentik/events/models.py msgid "authentik inbuilt notifications" msgstr "authentik 内置通知" -#: authentik/events/models.py:297 +#: authentik/events/models.py msgid "Generic Webhook" msgstr "通用 Webhook" -#: authentik/events/models.py:298 +#: authentik/events/models.py msgid "Slack Webhook (Slack/Discord)" msgstr "Slack Webhook(Slack/Discord)" -#: authentik/events/models.py:299 +#: authentik/events/models.py msgid "Email" msgstr "电子邮箱" -#: authentik/events/models.py:317 +#: authentik/events/models.py msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." msgstr "仅发送一次通知,例如在向聊天频道发送 Webhook 时。" -#: authentik/events/models.py:382 +#: authentik/events/models.py msgid "Severity" msgstr "严重程度" -#: authentik/events/models.py:387 +#: authentik/events/models.py msgid "Dispatched for user" msgstr "为用户分派" -#: authentik/events/models.py:396 +#: authentik/events/models.py msgid "Event user" msgstr "事件用户" -#: authentik/events/models.py:490 +#: authentik/events/models.py msgid "Notification Transport" msgstr "通知传输" -#: authentik/events/models.py:491 +#: authentik/events/models.py msgid "Notification Transports" msgstr "通知传输" -#: authentik/events/models.py:497 +#: authentik/events/models.py msgid "Notice" msgstr "通知" -#: authentik/events/models.py:498 +#: authentik/events/models.py msgid "Warning" msgstr "警告" -#: authentik/events/models.py:499 +#: authentik/events/models.py msgid "Alert" msgstr "注意" -#: authentik/events/models.py:524 +#: authentik/events/models.py msgid "Notification" msgstr "通知" -#: authentik/events/models.py:525 +#: authentik/events/models.py msgid "Notifications" msgstr "通知" -#: authentik/events/models.py:535 +#: authentik/events/models.py msgid "" "Select which transports should be used to notify the user. If none are " "selected, the notification will only be shown in the authentik UI." msgstr "选择应使用哪些传输方式来通知用户。如果未选择任何内容,则通知将仅显示在 authentik UI 中。" -#: authentik/events/models.py:543 +#: authentik/events/models.py msgid "Controls which severity level the created notifications will have." msgstr "控制被创建的通知的严重性级别。" -#: authentik/events/models.py:548 +#: authentik/events/models.py msgid "" "Define which group of users this notification should be sent and shown to. " "If left empty, Notification won't ben sent." msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" -#: authentik/events/models.py:566 +#: authentik/events/models.py msgid "Notification Rule" msgstr "通知规则" -#: authentik/events/models.py:567 +#: authentik/events/models.py msgid "Notification Rules" msgstr "通知规则" -#: authentik/events/models.py:587 +#: authentik/events/models.py msgid "Webhook Mapping" msgstr "Webhook 映射" -#: authentik/events/models.py:588 +#: authentik/events/models.py msgid "Webhook Mappings" msgstr "Webhook 映射" -#: authentik/events/monitored_tasks.py:207 +#: authentik/events/models.py +msgid "Run task" +msgstr "运行任务" + +#: authentik/events/models.py +msgid "System Task" +msgstr "系统任务" + +#: authentik/events/models.py +msgid "System Tasks" +msgstr "系统任务" + +#: authentik/events/system_tasks.py msgid "Task has not been run yet." msgstr "任务尚未运行。" -#: authentik/flows/api/flows.py:295 -#, python-format -msgid "Flow not applicable to current user/request: %(messages)s" -msgstr "流程不适用于当前用户/请求:%(messages)s" +#: authentik/flows/api/flows.py +#, python-brace-format +msgid "Flow not applicable to current user/request: {messages}" +msgstr "流程不适用于当前用户/请求:{messages}" -#: authentik/flows/api/flows_diagram.py:68 -#: authentik/flows/api/flows_diagram.py:94 -#, python-format -msgid "Policy (%(type)s)" -msgstr "策略(%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Policy ({type})" +msgstr "策略({type})" -#: authentik/flows/api/flows_diagram.py:71 -#, python-format -msgid "Binding %(order)d" -msgstr "绑定 %(order)d" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Binding {order}" +msgstr "绑定 {order}" -#: authentik/flows/api/flows_diagram.py:118 +#: authentik/flows/api/flows_diagram.py msgid "Policy passed" msgstr "策略通过" -#: authentik/flows/api/flows_diagram.py:122 -#, python-format -msgid "Stage (%(type)s)" -msgstr "阶段(%(type)s)" +#: authentik/flows/api/flows_diagram.py +#, python-brace-format +msgid "Stage ({type})" +msgstr "阶段({type})" -#: authentik/flows/api/flows_diagram.py:146 -#: authentik/flows/api/flows_diagram.py:206 +#: authentik/flows/api/flows_diagram.py msgid "Policy denied" msgstr "策略拒绝" -#: authentik/flows/api/flows_diagram.py:156 -#: authentik/flows/api/flows_diagram.py:168 -#: authentik/flows/api/flows_diagram.py:205 -#: authentik/flows/api/flows_diagram.py:227 +#: authentik/flows/api/flows_diagram.py msgid "End of the flow" msgstr "流程结束" -#: authentik/flows/api/flows_diagram.py:169 +#: authentik/flows/api/flows_diagram.py msgid "Requirement not fulfilled" msgstr "需求条件未达成" -#: authentik/flows/api/flows_diagram.py:177 +#: authentik/flows/api/flows_diagram.py msgid "Flow authentication requirement" msgstr "流程身份验证需求" -#: authentik/flows/api/flows_diagram.py:183 +#: authentik/flows/api/flows_diagram.py msgid "Requirement fulfilled" msgstr "需求条件已达成" -#: authentik/flows/api/flows_diagram.py:196 +#: authentik/flows/api/flows_diagram.py msgid "Pre-flow policies" msgstr "流程前置策略" -#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:194 +#: authentik/flows/api/flows_diagram.py authentik/flows/models.py msgid "Flow" msgstr "流程" -#: authentik/flows/exceptions.py:19 +#: authentik/flows/exceptions.py msgid "Flow does not apply to current user." msgstr "流程不应用于当前用户。" -#: authentik/flows/models.py:115 -#, python-format -msgid "Dynamic In-memory stage: %(doc)s" -msgstr "动态内存中阶段:%(doc)s" +#: authentik/flows/models.py +#, python-brace-format +msgid "Dynamic In-memory stage: {doc}" +msgstr "动态内存中阶段:{doc}" -#: authentik/flows/models.py:130 +#: authentik/flows/models.py msgid "Visible in the URL." msgstr "在 URL 中可见。" -#: authentik/flows/models.py:132 +#: authentik/flows/models.py msgid "Shown as the Title in Flow pages." msgstr "显示为流程页面中的标题。" -#: authentik/flows/models.py:139 +#: authentik/flows/models.py msgid "" "Decides what this Flow is used for. For example, the Authentication flow is " "redirect to when an un-authenticated user visits authentik." msgstr "决定此流程的用途。例如,当未经身份验证的用户访问 authentik 时,会重定向到身份验证流程。" -#: authentik/flows/models.py:148 +#: authentik/flows/models.py msgid "Background shown during execution" msgstr "执行时的背景" -#: authentik/flows/models.py:155 +#: authentik/flows/models.py msgid "" "Enable compatibility mode, increases compatibility with password managers on" " mobile devices." msgstr "启用兼容模式,增强与移动设备上密码管理器的兼容性。" -#: authentik/flows/models.py:163 +#: authentik/flows/models.py msgid "Configure what should happen when a flow denies access to a user." msgstr "配置当流程拒绝访问一名用户时应该发生什么。" -#: authentik/flows/models.py:169 +#: authentik/flows/models.py msgid "Required level of authentication and authorization to access a flow." msgstr "需要身份验证和授权等级以访问流程。" -#: authentik/flows/models.py:195 +#: authentik/flows/models.py msgid "Flows" msgstr "流程" -#: authentik/flows/models.py:198 +#: authentik/flows/models.py msgid "Can export a Flow" msgstr "可以导出流程" -#: authentik/flows/models.py:199 +#: authentik/flows/models.py msgid "Can inspect a Flow's execution" msgstr "可以检视流程执行" -#: authentik/flows/models.py:200 +#: authentik/flows/models.py msgid "View Flow's cache metrics" msgstr "查看流程缓存指标" -#: authentik/flows/models.py:201 +#: authentik/flows/models.py msgid "Clear Flow's cache metrics" msgstr "清除流程缓存指标" -#: authentik/flows/models.py:217 +#: authentik/flows/models.py msgid "Evaluate policies during the Flow planning process." msgstr "在流程规划过程中评估策略。" -#: authentik/flows/models.py:221 +#: authentik/flows/models.py msgid "Evaluate policies when the Stage is present to the user." msgstr "在阶段呈现给用户时评估策略。" -#: authentik/flows/models.py:228 +#: authentik/flows/models.py msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -697,62 +817,85 @@ msgstr "" "配置流程执行器应如何处理对质询的无效响应。RETRY 向执行器返回错误消息和类似的质询。RESTART " "从头开始重新启动流程,RESTART_WITH_CONTEXT 在保留当前上下文的同时重新启动流程。" -#: authentik/flows/models.py:251 +#: authentik/flows/models.py msgid "Flow Stage Binding" msgstr "流程阶段绑定" -#: authentik/flows/models.py:252 +#: authentik/flows/models.py msgid "Flow Stage Bindings" msgstr "流程阶段绑定" -#: authentik/flows/models.py:267 +#: authentik/flows/models.py msgid "" "Flow used by an authenticated user to configure this Stage. If empty, user " "will not be able to configure this stage." msgstr "经过身份验证的用户用来配置此阶段的流程。如果为空,用户将无法配置此阶段。" -#: authentik/flows/models.py:307 +#: authentik/flows/models.py msgid "Flow Token" msgstr "流程令牌" -#: authentik/flows/models.py:308 +#: authentik/flows/models.py msgid "Flow Tokens" msgstr "流程令牌" -#: authentik/lib/utils/time.py:27 +#: authentik/flows/views/executor.py +msgid "Invalid next URL" +msgstr "无效的 next URL" + +#: authentik/lib/sync/outgoing/tasks.py +msgid "Starting full provider sync" +msgstr "开始全量提供程序同步" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of users" +msgstr "正在同步用户页面 %(page)d" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-format +msgid "Syncing page %(page)d of groups" +msgstr "正在同步群组页面 %(page)d" + +#: authentik/lib/sync/outgoing/tasks.py +#, python-brace-format +msgid "Stopping sync due to error: {error}" +msgstr "由于以下错误,同步停止:{error}" + +#: authentik/lib/utils/time.py #, python-format msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." msgstr "%(value)s 的格式不正确,应为 'hours=3;minutes=1'。" -#: authentik/lib/validators.py:16 +#: authentik/lib/validators.py #, python-brace-format msgid "The fields {field_names} must be used together." msgstr "字段 {field_names} 必须一同使用。" -#: authentik/outposts/api/service_connections.py:127 +#: authentik/outposts/api/service_connections.py msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." msgstr "您只能在连接到本地集群时使用空的 kubeconfig。" -#: authentik/outposts/api/service_connections.py:135 +#: authentik/outposts/api/service_connections.py msgid "Invalid kubeconfig" msgstr "无效 kubeconfig " -#: authentik/outposts/models.py:123 +#: authentik/outposts/models.py msgid "" "If enabled, use the local connection. Required Docker socket/Kubernetes " "Integration" msgstr "如果启用,则使用本地连接。需要 Docker Socket / Kubernetes 集成" -#: authentik/outposts/models.py:153 +#: authentik/outposts/models.py msgid "Outpost Service-Connection" msgstr "前哨服务连接" -#: authentik/outposts/models.py:154 +#: authentik/outposts/models.py msgid "Outpost Service-Connections" msgstr "前哨服务连接" -#: authentik/outposts/models.py:162 +#: authentik/outposts/models.py msgid "" "Can be in the format of 'unix://' when connecting to a local docker " "daemon, or 'https://:2376' when connecting to a remote system." @@ -760,271 +903,270 @@ msgstr "" "当连接到本地 Docker " "守护进程时,可以使用“unix://”格式,或者在连接远程系统时,使用“https://:2376”格式。" -#: authentik/outposts/models.py:174 +#: authentik/outposts/models.py msgid "" "CA which the endpoint's Certificate is verified against. Can be left empty " "for no validation." msgstr "验证端点证书所依据的 CA。可以留空,表示不进行验证。" -#: authentik/outposts/models.py:186 +#: authentik/outposts/models.py msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." msgstr "用于身份验证的证书/密钥。可以留空表示不验证。" -#: authentik/outposts/models.py:204 +#: authentik/outposts/models.py msgid "Docker Service-Connection" msgstr "Docker 服务连接" -#: authentik/outposts/models.py:205 +#: authentik/outposts/models.py msgid "Docker Service-Connections" msgstr "Docker 服务连接" -#: authentik/outposts/models.py:213 +#: authentik/outposts/models.py msgid "" "Paste your kubeconfig here. authentik will automatically use the currently " "selected context." msgstr "在这里粘贴您的 kubeconfig。authentik 会自动使用当前选择的上下文。" -#: authentik/outposts/models.py:219 +#: authentik/outposts/models.py msgid "Verify SSL Certificates of the Kubernetes API endpoint" msgstr "验证 Kubernetes API 端点的 SSL 证书" -#: authentik/outposts/models.py:236 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connection" msgstr "Kubernetes 服务连接" -#: authentik/outposts/models.py:237 +#: authentik/outposts/models.py msgid "Kubernetes Service-Connections" msgstr "Kubernetes 服务连接" -#: authentik/outposts/models.py:253 +#: authentik/outposts/models.py msgid "" "Select Service-Connection authentik should use to manage this outpost. Leave" " empty if authentik should not handle the deployment." msgstr "选择 authentik 在管理此前哨时需要使用的服务连接。如果 authentik 不应该处理此部署,则应该留空。" -#: authentik/outposts/models.py:420 +#: authentik/outposts/models.py msgid "Outpost" msgstr "前哨" -#: authentik/outposts/models.py:421 +#: authentik/outposts/models.py msgid "Outposts" msgstr "前哨" -#: authentik/policies/denied.py:24 +#: authentik/policies/denied.py msgid "Access denied" msgstr "访问被拒绝" -#: authentik/policies/dummy/models.py:44 +#: authentik/policies/dummy/models.py msgid "Dummy Policy" msgstr "虚拟策略" -#: authentik/policies/dummy/models.py:45 +#: authentik/policies/dummy/models.py msgid "Dummy Policies" msgstr "虚拟策略" -#: authentik/policies/event_matcher/api.py:20 -#: authentik/policies/event_matcher/models.py:56 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected application. When left empty, all " "applications are matched." msgstr "匹配选定应用程序创建的事件。如果留空,则匹配所有应用程序。" -#: authentik/policies/event_matcher/api.py:29 -#: authentik/policies/event_matcher/models.py:64 +#: authentik/policies/event_matcher/api.py +#: authentik/policies/event_matcher/models.py msgid "" "Match events created by selected model. When left empty, all models are " "matched. When an app is selected, all the application's models are matched." msgstr "匹配选定模型创建的事件。如果留空,则匹配所有模型。选择应用程序后,则匹配该应用程序的所有模型。" -#: authentik/policies/event_matcher/api.py:42 +#: authentik/policies/event_matcher/api.py msgid "At least one criteria must be set." msgstr "必须至少设置一项标准。" -#: authentik/policies/event_matcher/models.py:48 +#: authentik/policies/event_matcher/models.py msgid "" "Match created events with this action type. When left empty, all action " "types will be matched." msgstr "将创建的事件与此操作类型匹配。留空时,所有操作类型都将匹配。" -#: authentik/policies/event_matcher/models.py:73 +#: authentik/policies/event_matcher/models.py msgid "" "Matches Event's Client IP (strict matching, for network matching use an " "Expression Policy)" msgstr "匹配事件的客户端 IP(严格匹配,要匹配网段请使用表达式策略)" -#: authentik/policies/event_matcher/models.py:143 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policy" msgstr "事件匹配策略" -#: authentik/policies/event_matcher/models.py:144 +#: authentik/policies/event_matcher/models.py msgid "Event Matcher Policies" msgstr "事件匹配策略" -#: authentik/policies/expiry/models.py:45 +#: authentik/policies/expiry/models.py #, python-format msgid "Password expired %(days)d days ago. Please update your password." msgstr "密码在 %(days)d 天前过期。请更新您的密码。" -#: authentik/policies/expiry/models.py:49 +#: authentik/policies/expiry/models.py msgid "Password has expired." msgstr "密码已过期。" -#: authentik/policies/expiry/models.py:53 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policy" msgstr "密码过期策略" -#: authentik/policies/expiry/models.py:54 +#: authentik/policies/expiry/models.py msgid "Password Expiry Policies" msgstr "密码过期策略" -#: authentik/policies/expression/models.py:40 +#: authentik/policies/expression/models.py msgid "Expression Policy" msgstr "表达式策略" -#: authentik/policies/expression/models.py:41 +#: authentik/policies/expression/models.py msgid "Expression Policies" msgstr "表达式策略" -#: authentik/policies/models.py:22 +#: authentik/policies/models.py msgid "all, all policies must pass" msgstr "All,必须通过所有策略" -#: authentik/policies/models.py:23 +#: authentik/policies/models.py msgid "any, any policy must pass" msgstr "Any,必须通过任意策略" -#: authentik/policies/models.py:46 +#: authentik/policies/models.py msgid "Policy Binding Model" msgstr "策略绑定模型" -#: authentik/policies/models.py:47 +#: authentik/policies/models.py msgid "Policy Binding Models" msgstr "策略绑定模型" -#: authentik/policies/models.py:86 +#: authentik/policies/models.py msgid "Negates the outcome of the policy. Messages are unaffected." msgstr "反转策略的结果。消息不受影响。" -#: authentik/policies/models.py:89 +#: authentik/policies/models.py msgid "Timeout after which Policy execution is terminated." msgstr "策略执行终止的超时时间。" -#: authentik/policies/models.py:92 +#: authentik/policies/models.py msgid "Result if the Policy execution fails." msgstr "策略执行失败时的结果。" -#: authentik/policies/models.py:145 +#: authentik/policies/models.py msgid "Policy Binding" msgstr "策略绑定" -#: authentik/policies/models.py:146 +#: authentik/policies/models.py msgid "Policy Bindings" msgstr "策略绑定" -#: authentik/policies/models.py:167 +#: authentik/policies/models.py msgid "" "When this option is enabled, all executions of this policy will be logged. " "By default, only execution errors are logged." msgstr "启用此选项后,将记录此策略的所有执行日志。默认情况下,只记录执行错误。" -#: authentik/policies/models.py:189 +#: authentik/policies/models.py msgid "Policy" msgstr "策略" -#: authentik/policies/models.py:190 +#: authentik/policies/models.py msgid "Policies" msgstr "策略" -#: authentik/policies/models.py:193 +#: authentik/policies/models.py msgid "View Policy's cache metrics" msgstr "查看策略缓存指标" -#: authentik/policies/models.py:194 +#: authentik/policies/models.py msgid "Clear Policy's cache metrics" msgstr "清除策略缓存指标" -#: authentik/policies/password/models.py:27 +#: authentik/policies/password/models.py msgid "Field key to check, field keys defined in Prompt stages are available." msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。" -#: authentik/policies/password/models.py:44 +#: authentik/policies/password/models.py msgid "How many times the password hash is allowed to be on haveibeenpwned" msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次" -#: authentik/policies/password/models.py:49 +#: authentik/policies/password/models.py msgid "" "If the zxcvbn score is equal or less than this value, the policy will fail." msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。" -#: authentik/policies/password/models.py:72 +#: authentik/policies/password/models.py msgid "Password not set in context" msgstr "未在上下文中设置密码" -#: authentik/policies/password/models.py:134 +#: authentik/policies/password/models.py #, python-format msgid "Password exists on %(count)d online lists." msgstr "%(count)d 个在线列表中存在密码。" -#: authentik/policies/password/models.py:154 +#: authentik/policies/password/models.py msgid "Password is too weak." msgstr "密码太弱。" -#: authentik/policies/password/models.py:162 +#: authentik/policies/password/models.py msgid "Password Policy" msgstr "密码策略" -#: authentik/policies/password/models.py:163 +#: authentik/policies/password/models.py msgid "Password Policies" msgstr "密码策略" -#: authentik/policies/reputation/api.py:18 +#: authentik/policies/reputation/api.py msgid "Either IP or Username must be checked" msgstr "必须检查 IP 或用户名" -#: authentik/policies/reputation/models.py:67 +#: authentik/policies/reputation/models.py msgid "Reputation Policy" msgstr "信誉策略" -#: authentik/policies/reputation/models.py:68 +#: authentik/policies/reputation/models.py msgid "Reputation Policies" msgstr "信誉策略" -#: authentik/policies/reputation/models.py:96 +#: authentik/policies/reputation/models.py msgid "Reputation Score" msgstr "信誉分数" -#: authentik/policies/reputation/models.py:97 +#: authentik/policies/reputation/models.py msgid "Reputation Scores" msgstr "信誉分数" -#: authentik/policies/templates/policies/denied.html:7 -#: authentik/policies/templates/policies/denied.html:11 +#: authentik/policies/templates/policies/denied.html msgid "Permission denied" msgstr "权限被拒绝" -#: authentik/policies/templates/policies/denied.html:21 +#: authentik/policies/templates/policies/denied.html msgid "User's avatar" msgstr "用户的头像" -#: authentik/policies/templates/policies/denied.html:25 +#: authentik/policies/templates/policies/denied.html msgid "Not you?" msgstr "不是您?" -#: authentik/policies/templates/policies/denied.html:33 +#: authentik/policies/templates/policies/denied.html msgid "Request has been denied." msgstr "请求被拒绝。" -#: authentik/policies/templates/policies/denied.html:44 +#: authentik/policies/templates/policies/denied.html msgid "Messages:" msgstr "消息:" -#: authentik/policies/templates/policies/denied.html:54 +#: authentik/policies/templates/policies/denied.html msgid "Explanation:" msgstr "解释:" -#: authentik/policies/templates/policies/denied.html:58 +#: authentik/policies/templates/policies/denied.html #, python-format msgid "" "\n" @@ -1035,21 +1177,21 @@ msgstr "" " 策略绑定 '%(name)s' 返回结果 '%(result)s'\n" " " -#: authentik/policies/views.py:68 +#: authentik/policies/views.py msgid "Failed to resolve application" msgstr "解析应用程序失败" -#: authentik/providers/ldap/models.py:25 +#: authentik/providers/ldap/models.py msgid "DN under which objects are accessible." msgstr "可访问对象的 DN。" -#: authentik/providers/ldap/models.py:34 +#: authentik/providers/ldap/models.py msgid "" "Users in this group can do search queries. If not set, every user can " "execute search queries." msgstr "该组中的用户可以执行搜索查询。如果未设置,则每个用户都可以执行搜索查询。" -#: authentik/providers/ldap/models.py:53 +#: authentik/providers/ldap/models.py msgid "" "The start for uidNumbers, this number is added to the user.pk to make sure " "that the numbers aren't too low for POSIX users. Default is 2000 to ensure " @@ -1058,7 +1200,7 @@ msgstr "" "起始 uidNumbers,这个数字会被添加到 user.pk 中,以确保对于 POSIX 用户来说,这个数字不会太低。默认值为 " "2000,以确保我们不会与本地用户的 uidNumber 发生冲突" -#: authentik/providers/ldap/models.py:62 +#: authentik/providers/ldap/models.py msgid "" "The start for gidNumbers, this number is added to a number generated from " "the group.pk to make sure that the numbers aren't too low for POSIX groups. " @@ -1068,8 +1210,7 @@ msgstr "" "起始 gidNumbers,这个数字会被添加到从 group.pk 生成的数字中,以确保对于 POSIX 用户来说,这个数字不会太低。默认值为 " "4000,以确保我们不会与本地群组或用户主组的 gidNumber 发生冲突" -#: authentik/providers/ldap/models.py:76 -#: authentik/providers/radius/models.py:34 +#: authentik/providers/ldap/models.py authentik/providers/radius/models.py msgid "" "When enabled, code-based multi-factor authentication can be used by " "appending a semicolon and the TOTP code to the password. This should only be" @@ -1080,958 +1221,950 @@ msgstr "" "启用时,可以通过在密码后添加分号和 TOTP 代码来使用基于代码的多因素身份验证。仅在所有绑定到此提供程序的用户都已配置 TOTP " "设备的情况下才应该启用,否则密码可能会因为包含分号而被错误地拒绝。" -#: authentik/providers/ldap/models.py:108 +#: authentik/providers/ldap/models.py msgid "LDAP Provider" msgstr "LDAP 提供程序" -#: authentik/providers/ldap/models.py:109 +#: authentik/providers/ldap/models.py msgid "LDAP Providers" msgstr "LDAP 提供程序" -#: authentik/providers/oauth2/id_token.py:27 +#: authentik/providers/oauth2/id_token.py msgid "Based on the Hashed User ID" msgstr "基于经过哈希处理的用户 ID" -#: authentik/providers/oauth2/id_token.py:28 +#: authentik/providers/oauth2/id_token.py msgid "Based on user ID" msgstr "基于用户 ID" -#: authentik/providers/oauth2/id_token.py:29 +#: authentik/providers/oauth2/id_token.py msgid "Based on user UUID" msgstr "基于用户 UUID" -#: authentik/providers/oauth2/id_token.py:30 +#: authentik/providers/oauth2/id_token.py msgid "Based on the username" msgstr "基于用户名" -#: authentik/providers/oauth2/id_token.py:33 +#: authentik/providers/oauth2/id_token.py msgid "Based on the User's Email. This is recommended over the UPN method." msgstr "基于用户的电子邮箱。建议在 UPN 方法上使用。" -#: authentik/providers/oauth2/id_token.py:38 +#: authentik/providers/oauth2/id_token.py msgid "" "Based on the User's UPN, only works if user has a 'upn' attribute set. Use " "this method only if you have different UPN and Mail domains." msgstr "基于用户的 UPN,仅当用户设置了 'upn' 属性时才有效。仅当您有不同的 UPN 和 Mail 域时才使用此方法。" -#: authentik/providers/oauth2/models.py:43 +#: authentik/providers/oauth2/models.py msgid "Confidential" msgstr "机密" -#: authentik/providers/oauth2/models.py:44 +#: authentik/providers/oauth2/models.py msgid "Public" msgstr "公开" -#: authentik/providers/oauth2/models.py:66 +#: authentik/providers/oauth2/models.py msgid "Same identifier is used for all providers" msgstr "所有提供程序都使用相同的标识符" -#: authentik/providers/oauth2/models.py:68 +#: authentik/providers/oauth2/models.py msgid "Each provider has a different issuer, based on the application slug." msgstr "根据应用程序 Slug,每个提供程序都有不同的颁发者。" -#: authentik/providers/oauth2/models.py:75 +#: authentik/providers/oauth2/models.py msgid "code (Authorization Code Flow)" msgstr "code(授权码流程)" -#: authentik/providers/oauth2/models.py:76 +#: authentik/providers/oauth2/models.py msgid "id_token (Implicit Flow)" msgstr "id_token(隐式流程)" -#: authentik/providers/oauth2/models.py:77 +#: authentik/providers/oauth2/models.py msgid "id_token token (Implicit Flow)" msgstr "id_token token(隐式流程)" -#: authentik/providers/oauth2/models.py:78 +#: authentik/providers/oauth2/models.py msgid "code token (Hybrid Flow)" msgstr "code token(混合流程)" -#: authentik/providers/oauth2/models.py:79 +#: authentik/providers/oauth2/models.py msgid "code id_token (Hybrid Flow)" msgstr "code id_token(混合流程)" -#: authentik/providers/oauth2/models.py:80 +#: authentik/providers/oauth2/models.py msgid "code id_token token (Hybrid Flow)" msgstr "code id_token token(混合流程)" -#: authentik/providers/oauth2/models.py:86 +#: authentik/providers/oauth2/models.py msgid "HS256 (Symmetric Encryption)" msgstr "HS256(对称加密)" -#: authentik/providers/oauth2/models.py:87 +#: authentik/providers/oauth2/models.py msgid "RS256 (Asymmetric Encryption)" msgstr "RS256(非对称加密)" -#: authentik/providers/oauth2/models.py:88 +#: authentik/providers/oauth2/models.py msgid "ES256 (Asymmetric Encryption)" msgstr "ES256(非对称加密)" -#: authentik/providers/oauth2/models.py:94 +#: authentik/providers/oauth2/models.py msgid "Scope used by the client" msgstr "客户端使用的作用域" -#: authentik/providers/oauth2/models.py:98 +#: authentik/providers/oauth2/models.py msgid "" "Description shown to the user when consenting. If left empty, the user won't" " be informed." msgstr "同意授权时向用户显示的描述。如果留空,则不会告知用户。" -#: authentik/providers/oauth2/models.py:117 +#: authentik/providers/oauth2/models.py msgid "Scope Mapping" msgstr "作用域映射" -#: authentik/providers/oauth2/models.py:118 +#: authentik/providers/oauth2/models.py msgid "Scope Mappings" msgstr "作用域映射" -#: authentik/providers/oauth2/models.py:128 +#: authentik/providers/oauth2/models.py msgid "Client Type" msgstr "客户端类型" -#: authentik/providers/oauth2/models.py:130 +#: authentik/providers/oauth2/models.py msgid "" "Confidential clients are capable of maintaining the confidentiality of their" " credentials. Public clients are incapable" msgstr "机密客户端有能力维护其凭据的机密性。公开客户端无此能力。" -#: authentik/providers/oauth2/models.py:137 +#: authentik/providers/oauth2/models.py msgid "Client ID" msgstr "客户端 ID" -#: authentik/providers/oauth2/models.py:143 +#: authentik/providers/oauth2/models.py msgid "Client Secret" msgstr "客户端密钥" -#: authentik/providers/oauth2/models.py:149 +#: authentik/providers/oauth2/models.py msgid "Redirect URIs" msgstr "重定向 URI" -#: authentik/providers/oauth2/models.py:150 +#: authentik/providers/oauth2/models.py msgid "Enter each URI on a new line." msgstr "每行输入一个 URI。" -#: authentik/providers/oauth2/models.py:155 +#: authentik/providers/oauth2/models.py msgid "Include claims in id_token" msgstr "在 id_token 中包含声明" -#: authentik/providers/oauth2/models.py:157 +#: authentik/providers/oauth2/models.py msgid "" "Include User claims from scopes in the id_token, for applications that don't" " access the userinfo endpoint." msgstr "对于不访问 userinfo 端点的应用程序,将来自作用域的用户声明包含在 id_token 中。" -#: authentik/providers/oauth2/models.py:166 +#: authentik/providers/oauth2/models.py msgid "" "Access codes not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,访问代码无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/oauth2/models.py:174 -#: authentik/providers/oauth2/models.py:182 +#: authentik/providers/oauth2/models.py msgid "" "Tokens not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,令牌无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/oauth2/models.py:191 +#: authentik/providers/oauth2/models.py msgid "" "Configure what data should be used as unique User Identifier. For most " "cases, the default should be fine." msgstr "配置应将哪些数据用作唯一用户标识符。在大多数情况下保持默认值即可。" -#: authentik/providers/oauth2/models.py:198 +#: authentik/providers/oauth2/models.py msgid "Configure how the issuer field of the ID Token should be filled." msgstr "配置如何填写 ID 令牌的颁发者字段。" -#: authentik/providers/oauth2/models.py:203 +#: authentik/providers/oauth2/models.py msgid "Signing Key" msgstr "签名密钥" -#: authentik/providers/oauth2/models.py:207 +#: authentik/providers/oauth2/models.py msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." msgstr "用于签名令牌的密钥。仅当 JWT 算法设置为 RS256 时才需要。" -#: authentik/providers/oauth2/models.py:214 +#: authentik/providers/oauth2/models.py msgid "" "Any JWT signed by the JWK of the selected source can be used to " "authenticate." msgstr "任何由选定来源的 JWK 签发的 JWT 都可以用于身份验证。" -#: authentik/providers/oauth2/models.py:287 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Provider" msgstr "OAuth2/OpenID 提供程序" -#: authentik/providers/oauth2/models.py:288 +#: authentik/providers/oauth2/models.py msgid "OAuth2/OpenID Providers" msgstr "OAuth2/OpenID 提供程序" -#: authentik/providers/oauth2/models.py:297 -#: authentik/providers/oauth2/models.py:430 +#: authentik/providers/oauth2/models.py msgid "Scopes" msgstr "作用域" -#: authentik/providers/oauth2/models.py:317 +#: authentik/providers/oauth2/models.py msgid "Code" msgstr "代码" -#: authentik/providers/oauth2/models.py:318 +#: authentik/providers/oauth2/models.py msgid "Nonce" msgstr "Nonce" -#: authentik/providers/oauth2/models.py:319 +#: authentik/providers/oauth2/models.py msgid "Code Challenge" msgstr "代码质询" -#: authentik/providers/oauth2/models.py:321 +#: authentik/providers/oauth2/models.py msgid "Code Challenge Method" msgstr "代码质询方法" -#: authentik/providers/oauth2/models.py:341 +#: authentik/providers/oauth2/models.py msgid "Authorization Code" msgstr "授权代码" -#: authentik/providers/oauth2/models.py:342 +#: authentik/providers/oauth2/models.py msgid "Authorization Codes" msgstr "授权代码" -#: authentik/providers/oauth2/models.py:384 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Token" msgstr "OAuth2 访问令牌" -#: authentik/providers/oauth2/models.py:385 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Access Tokens" msgstr "OAuth2 访问令牌" -#: authentik/providers/oauth2/models.py:395 +#: authentik/providers/oauth2/models.py msgid "ID Token" msgstr "ID 令牌" -#: authentik/providers/oauth2/models.py:414 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Token" msgstr "OAuth2 刷新令牌" -#: authentik/providers/oauth2/models.py:415 +#: authentik/providers/oauth2/models.py msgid "OAuth2 Refresh Tokens" msgstr "OAuth2 刷新令牌" -#: authentik/providers/oauth2/models.py:442 +#: authentik/providers/oauth2/models.py msgid "Device Token" msgstr "设备令牌" -#: authentik/providers/oauth2/models.py:443 +#: authentik/providers/oauth2/models.py msgid "Device Tokens" msgstr "设备令牌" -#: authentik/providers/oauth2/views/authorize.py:489 -#: authentik/providers/saml/views/flows.py:87 -#, python-format -msgid "Redirecting to %(app)s..." -msgstr "正在跳转到 %(app)s…" +#: authentik/providers/oauth2/views/authorize.py +#: authentik/providers/saml/views/flows.py +#, python-brace-format +msgid "Redirecting to {app}..." +msgstr "正在跳转到 {app}…" -#: authentik/providers/oauth2/views/device_init.py:151 +#: authentik/providers/oauth2/views/device_init.py msgid "Invalid code" msgstr "无效代码" -#: authentik/providers/oauth2/views/userinfo.py:55 -#: authentik/providers/oauth2/views/userinfo.py:56 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your User Information" msgstr "GitHub 兼容性:访问您的用户信息" -#: authentik/providers/oauth2/views/userinfo.py:57 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access you Email addresses" msgstr "GitHub 兼容性:访问您的电子邮件地址" -#: authentik/providers/oauth2/views/userinfo.py:58 +#: authentik/providers/oauth2/views/userinfo.py msgid "GitHub Compatibility: Access your Groups" msgstr "GitHub 兼容性:访问您的组" -#: authentik/providers/oauth2/views/userinfo.py:59 +#: authentik/providers/oauth2/views/userinfo.py msgid "authentik API Access on behalf of your user" msgstr "代表您的用户访问 authentik API" -#: authentik/providers/proxy/api.py:52 +#: authentik/providers/proxy/api.py msgid "User and password attributes must be set when basic auth is enabled." msgstr "启用 Basic Auth 时,必须设置用户和密码属性。" -#: authentik/providers/proxy/api.py:63 +#: authentik/providers/proxy/api.py msgid "Internal host cannot be empty when forward auth is disabled." msgstr "禁用 Forward Auth 时,内部主机不能为空。" -#: authentik/providers/proxy/models.py:54 +#: authentik/providers/proxy/models.py msgid "Validate SSL Certificates of upstream servers" msgstr "验证上游服务器的 SSL 证书" -#: authentik/providers/proxy/models.py:55 +#: authentik/providers/proxy/models.py msgid "Internal host SSL Validation" msgstr "内部主机 SSL 验证" -#: authentik/providers/proxy/models.py:61 +#: authentik/providers/proxy/models.py msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." msgstr "在 traefik 和 nginx auth_request 中启用对 ForwardAuth 的支持。排除 internal_host。" -#: authentik/providers/proxy/models.py:70 +#: authentik/providers/proxy/models.py msgid "" "Regular expressions for which authentication is not required. Each new line " "is interpreted as a new Regular Expression." msgstr "用于描述何处不需要身份验证的正则表达式。每个新行都被解释为一个新的正则表达式。" -#: authentik/providers/proxy/models.py:78 +#: authentik/providers/proxy/models.py msgid "" "When enabled, this provider will intercept the authorization header and " "authenticate requests based on its value." msgstr "启用时,此提供程序将会拦截 Authorization 标头,并基于其值认证请求。" -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py msgid "Set HTTP-Basic Authentication" msgstr "设置 HTTP-Basic 身份验证" -#: authentik/providers/proxy/models.py:86 +#: authentik/providers/proxy/models.py msgid "" "Set a custom HTTP-Basic Authentication header based on values from " "authentik." msgstr "根据来自 authentik 的值设置自定义 HTTP-Basic 身份验证标头。" -#: authentik/providers/proxy/models.py:91 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Username Key" msgstr "HTTP-Basic 用户名密钥" -#: authentik/providers/proxy/models.py:93 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the user part of the HTTP-Basic Header. If not" " set, the user's Email address is used." msgstr "用于 HTTP-Basic 标头用户名部分的用户/组属性。如果未设置,则使用用户的电子邮件地址。" -#: authentik/providers/proxy/models.py:99 +#: authentik/providers/proxy/models.py msgid "HTTP-Basic Password Key" msgstr "HTTP-Basic 密码密钥" -#: authentik/providers/proxy/models.py:100 +#: authentik/providers/proxy/models.py msgid "" "User/Group Attribute used for the password part of the HTTP-Basic Header." msgstr "用于 HTTP-Basic 标头的密码部分的用户/组属性。" -#: authentik/providers/proxy/models.py:154 +#: authentik/providers/proxy/models.py msgid "Proxy Provider" msgstr "代理提供程序" -#: authentik/providers/proxy/models.py:155 +#: authentik/providers/proxy/models.py msgid "Proxy Providers" msgstr "代理提供程序" -#: authentik/providers/radius/models.py:18 +#: authentik/providers/radius/models.py msgid "Shared secret between clients and server to hash packets." msgstr "在客户端和服务端之间共享密钥以哈希数据包。" -#: authentik/providers/radius/models.py:24 +#: authentik/providers/radius/models.py msgid "" "List of CIDRs (comma-separated) that clients can connect from. A more " "specific CIDR will match before a looser one. Clients connecting from a non-" "specified CIDR will be dropped." msgstr "允许客户端连接的 CIDR 列表(逗号分隔)。严格的 CIDR 会在宽松的之前匹配。来自 CIDR 范围外的客户端连接将会被丢弃。" -#: authentik/providers/radius/models.py:60 +#: authentik/providers/radius/models.py msgid "Radius Provider" msgstr "Radius 提供程序" -#: authentik/providers/radius/models.py:61 +#: authentik/providers/radius/models.py msgid "Radius Providers" msgstr "Radius 提供程序" -#: authentik/providers/saml/api/providers.py:258 +#: authentik/providers/saml/api/providers.py msgid "Invalid XML Syntax" msgstr "无效 XML 语法" -#: authentik/providers/saml/api/providers.py:268 -#, python-format -msgid "Failed to import Metadata: %(message)s" -msgstr "导入元数据失败:%(message)s" +#: authentik/providers/saml/api/providers.py +#, python-brace-format +msgid "Failed to import Metadata: {messages}" +msgstr "导入元数据失败:{messages}" -#: authentik/providers/saml/models.py:38 +#: authentik/providers/saml/models.py msgid "ACS URL" msgstr "ACS URL" -#: authentik/providers/saml/models.py:43 +#: authentik/providers/saml/models.py msgid "" "Value of the audience restriction field of the assertion. When left empty, " "no audience restriction will be added." msgstr "断言的 Audience 受限字段的值。留空时,不会添加 Audience 限制。" -#: authentik/providers/saml/models.py:47 +#: authentik/providers/saml/models.py msgid "Also known as EntityID" msgstr "也称为 EntityID" -#: authentik/providers/saml/models.py:51 +#: authentik/providers/saml/models.py msgid "Service Provider Binding" msgstr "服务提供程序绑定" -#: authentik/providers/saml/models.py:53 +#: authentik/providers/saml/models.py msgid "" "This determines how authentik sends the response back to the Service " "Provider." msgstr "确定 authentik 如何将响应发送回服务提供程序。" -#: authentik/providers/saml/models.py:63 +#: authentik/providers/saml/models.py msgid "NameID Property Mapping" msgstr "NameID 属性映射" -#: authentik/providers/saml/models.py:65 +#: authentik/providers/saml/models.py msgid "" "Configure how the NameID value will be created. When left empty, the " "NameIDPolicy of the incoming request will be considered" msgstr "配置如何创建 NameID 值。如果留空,将考虑传入请求的 NameIDPolicy" -#: authentik/providers/saml/models.py:74 +#: authentik/providers/saml/models.py msgid "" "Assertion valid not before current time + this value (Format: " "hours=-1;minutes=-2;seconds=-3)." msgstr "从当前时间经过多久时或之后,断言有效(格式:hours=-1;minutes=-2;seconds=-3)。" -#: authentik/providers/saml/models.py:82 +#: authentik/providers/saml/models.py msgid "" "Assertion not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,断言无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/saml/models.py:91 +#: authentik/providers/saml/models.py msgid "" "Session not valid on or after current time + this value (Format: " "hours=1;minutes=2;seconds=3)." msgstr "从当前时间经过多久时或之后,会话无效(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA1" msgstr "SHA1" -#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA256" msgstr "SHA256" -#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA384" msgstr "SHA384" -#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "SHA512" msgstr "SHA512" -#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA1" msgstr "RSA-SHA1" -#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA256" msgstr "RSA-SHA256" -#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA384" msgstr "RSA-SHA384" -#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "RSA-SHA512" msgstr "RSA-SHA512" -#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA1" +msgstr "ECDSA-SHA1" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA256" +msgstr "ECDSA-SHA256" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA384" +msgstr "ECDSA-SHA384" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py +msgid "ECDSA-SHA512" +msgstr "ECDSA-SHA512" + +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "DSA-SHA1" msgstr "DSA-SHA1" -#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "" "When selected, incoming assertion's Signatures will be validated against " "this certificate. To allow unsigned Requests, leave on default." msgstr "选中后,传入断言的签名将根据此证书进行验证。要允许未签名的请求,请保留默认值。" -#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Verification Certificate" msgstr "验证证书" -#: authentik/providers/saml/models.py:136 +#: authentik/providers/saml/models.py msgid "Keypair used to sign outgoing Responses going to the Service Provider." msgstr "密钥对,用于签署发送给服务提供程序的传出响应。" -#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144 +#: authentik/providers/saml/models.py authentik/sources/saml/models.py msgid "Signing Keypair" msgstr "签名密钥对" -#: authentik/providers/saml/models.py:142 +#: authentik/providers/saml/models.py msgid "Default relay_state value for IDP-initiated logins" msgstr "用于 IDP 发起登录的默认 relay_state 值" -#: authentik/providers/saml/models.py:171 +#: authentik/providers/saml/models.py msgid "SAML Provider" msgstr "SAML 提供程序" -#: authentik/providers/saml/models.py:172 +#: authentik/providers/saml/models.py msgid "SAML Providers" msgstr "SAML 提供程序" -#: authentik/providers/saml/models.py:196 +#: authentik/providers/saml/models.py msgid "SAML Property Mapping" msgstr "SAML 属性映射" -#: authentik/providers/saml/models.py:197 +#: authentik/providers/saml/models.py msgid "SAML Property Mappings" msgstr "SAML 属性映射" -#: authentik/providers/scim/models.py:23 +#: authentik/providers/saml/models.py +msgid "SAML Provider from Metadata" +msgstr "来自元数据的 SAML 提供程序" + +#: authentik/providers/saml/models.py +msgid "SAML Providers from Metadata" +msgstr "来自元数据的 SAML 提供程序" + +#: authentik/providers/scim/models.py msgid "Base URL to SCIM requests, usually ends in /v2" msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾" -#: authentik/providers/scim/models.py:24 +#: authentik/providers/scim/models.py msgid "Authentication token" msgstr "身份验证令牌" -#: authentik/providers/scim/models.py:30 authentik/sources/ldap/models.py:98 -msgid "Property mappings used for group creation/updating." -msgstr "用于创建/更新组的属性映射。" - -#: authentik/providers/scim/models.py:72 +#: authentik/providers/scim/models.py msgid "SCIM Provider" msgstr "SCIM 提供程序" -#: authentik/providers/scim/models.py:73 +#: authentik/providers/scim/models.py msgid "SCIM Providers" msgstr "SCIM 提供程序" -#: authentik/providers/scim/models.py:93 +#: authentik/providers/scim/models.py msgid "SCIM Mapping" msgstr "SCIM 映射" -#: authentik/providers/scim/models.py:94 +#: authentik/providers/scim/models.py msgid "SCIM Mappings" msgstr "SCIM 映射" -#: authentik/providers/scim/tasks.py:56 -msgid "Starting full SCIM sync" -msgstr "开始全量 SCIM 同步" - -#: authentik/providers/scim/tasks.py:66 -#, python-format -msgid "Syncing page %(page)d of users" -msgstr "正在同步用户页面 %(page)d" - -#: authentik/providers/scim/tasks.py:70 -#, python-format -msgid "Syncing page %(page)d of groups" -msgstr "正在同步群组页面 %(page)d" - -#: authentik/providers/scim/tasks.py:102 -#, python-format -msgid "Failed to sync user %(user_name)s due to remote error: %(error)s" -msgstr "由于远端错误,同步用户 %(user_name)s 失败:%(error)s" - -#: authentik/providers/scim/tasks.py:113 authentik/providers/scim/tasks.py:154 -#, python-format -msgid "Stopping sync due to error: %(error)s" -msgstr "由于以下错误,同步停止:%(error)s" - -#: authentik/providers/scim/tasks.py:143 -#, python-format -msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" -msgstr "由于远端错误,同步组 %(group_name)s 失败:%(error)s" - -#: authentik/rbac/models.py:51 +#: authentik/rbac/models.py msgid "Role" msgstr "角色" -#: authentik/rbac/models.py:52 +#: authentik/rbac/models.py msgid "Roles" msgstr "角色" -#: authentik/rbac/models.py:66 +#: authentik/rbac/models.py msgid "System permission" msgstr "系统权限" -#: authentik/rbac/models.py:67 +#: authentik/rbac/models.py msgid "System permissions" msgstr "系统权限" -#: authentik/rbac/models.py:69 +#: authentik/rbac/models.py msgid "Can view system info" msgstr "可以查看系统信息" -#: authentik/rbac/models.py:70 -msgid "Can view system tasks" -msgstr "可以查看系统任务" - -#: authentik/rbac/models.py:71 -msgid "Can run system tasks" -msgstr "可以运行系统任务" - -#: authentik/rbac/models.py:72 +#: authentik/rbac/models.py msgid "Can access admin interface" msgstr "可以访问管理员界面" -#: authentik/rbac/models.py:73 +#: authentik/rbac/models.py msgid "Can view system settings" msgstr "可以查看系统设置" -#: authentik/rbac/models.py:74 +#: authentik/rbac/models.py msgid "Can edit system settings" msgstr "可以编辑系统设置" -#: authentik/recovery/management/commands/create_admin_group.py:12 +#: authentik/recovery/management/commands/create_admin_group.py msgid "Create admin group if the default group gets deleted." msgstr "如果默认组被删除,则创建管理员组。" -#: authentik/recovery/management/commands/create_recovery_key.py:16 +#: authentik/recovery/management/commands/create_recovery_key.py msgid "Create a Key which can be used to restore access to authentik." msgstr "创建一个密钥,可用于恢复对 authentik 的访问权限。" -#: authentik/recovery/views.py:24 +#: authentik/recovery/views.py msgid "Used recovery-link to authenticate." msgstr "已使用恢复链接进行身份验证。" -#: authentik/sources/ldap/models.py:41 +#: authentik/sources/ldap/models.py msgid "Server URI" msgstr "服务器 URI" -#: authentik/sources/ldap/models.py:50 +#: authentik/sources/ldap/models.py msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this" " keypair." msgstr "可选,根据此密钥对中的 CA 链验证 LDAP 服务器的证书。" -#: authentik/sources/ldap/models.py:59 +#: authentik/sources/ldap/models.py msgid "" "Client certificate to authenticate against the LDAP Server's Certificate." msgstr "基于 LDAP 服务端证书进行身份验证的客户端证书。" -#: authentik/sources/ldap/models.py:62 +#: authentik/sources/ldap/models.py msgid "Bind CN" msgstr "Bind CN" -#: authentik/sources/ldap/models.py:64 +#: authentik/sources/ldap/models.py msgid "Enable Start TLS" msgstr "启用 Start TLS" -#: authentik/sources/ldap/models.py:65 +#: authentik/sources/ldap/models.py msgid "Use Server URI for SNI verification" msgstr "SNI 验证时使用服务器 URI" -#: authentik/sources/ldap/models.py:67 +#: authentik/sources/ldap/models.py msgid "Base DN" msgstr "Base DN" -#: authentik/sources/ldap/models.py:69 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for User-queries." msgstr "添加到用户查询的 Base DN 起始处。" -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py msgid "Addition User DN" msgstr "额外的用户 DN" -#: authentik/sources/ldap/models.py:74 +#: authentik/sources/ldap/models.py msgid "Prepended to Base DN for Group-queries." msgstr "添加到组查询的 Base DN 起始处。" -#: authentik/sources/ldap/models.py:75 +#: authentik/sources/ldap/models.py msgid "Addition Group DN" msgstr "额外的组 DN" -#: authentik/sources/ldap/models.py:81 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Users." msgstr "将与此筛选器匹配的对象视为用户。" -#: authentik/sources/ldap/models.py:84 +#: authentik/sources/ldap/models.py msgid "Field which contains members of a group." msgstr "包含组成员的字段。" -#: authentik/sources/ldap/models.py:88 +#: authentik/sources/ldap/models.py msgid "Consider Objects matching this filter to be Groups." msgstr "将与此过滤器匹配的对象视为组。" -#: authentik/sources/ldap/models.py:91 +#: authentik/sources/ldap/models.py msgid "Field which contains a unique Identifier." msgstr "包含唯一标识符的字段。" -#: authentik/sources/ldap/models.py:105 +#: authentik/sources/ldap/models.py +msgid "Update internal authentik password when login succeeds with LDAP" +msgstr "使用 LDAP 登录成功时更新内部 authentik 密码" + +#: authentik/sources/ldap/models.py msgid "" "When a user changes their password, sync it back to LDAP. This can only be " "enabled on a single LDAP source." msgstr "当用户修改密码时,将其同步回 LDAP。仅可在单点 LDAP 源时启用。" -#: authentik/sources/ldap/models.py:248 +#: authentik/sources/ldap/models.py msgid "LDAP Source" msgstr "LDAP 源" -#: authentik/sources/ldap/models.py:249 +#: authentik/sources/ldap/models.py msgid "LDAP Sources" msgstr "LDAP 源" -#: authentik/sources/ldap/models.py:271 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mapping" msgstr "LDAP 属性映射" -#: authentik/sources/ldap/models.py:272 +#: authentik/sources/ldap/models.py msgid "LDAP Property Mappings" msgstr "LDAP 属性映射" -#: authentik/sources/ldap/signals.py:52 +#: authentik/sources/ldap/signals.py msgid "Password does not match Active Directory Complexity." msgstr "密码与 Active Directory 复杂度不匹配。" -#: authentik/sources/oauth/clients/oauth2.py:68 +#: authentik/sources/oauth/clients/oauth2.py msgid "No token received." msgstr "未收到令牌。" -#: authentik/sources/oauth/models.py:24 +#: authentik/sources/oauth/models.py msgid "Request Token URL" msgstr "请求令牌 URL" -#: authentik/sources/oauth/models.py:26 +#: authentik/sources/oauth/models.py msgid "" "URL used to request the initial token. This URL is only required for OAuth " "1." msgstr "用于请求初始令牌的 URL。只有 OAuth 1 才需要此网址。" -#: authentik/sources/oauth/models.py:32 +#: authentik/sources/oauth/models.py msgid "Authorization URL" msgstr "授权 URL" -#: authentik/sources/oauth/models.py:33 +#: authentik/sources/oauth/models.py msgid "URL the user is redirect to to conest the flow." msgstr "为控制流程,使用户被重定向到的 URL" -#: authentik/sources/oauth/models.py:38 +#: authentik/sources/oauth/models.py msgid "Access Token URL" msgstr "访问令牌 URL" -#: authentik/sources/oauth/models.py:39 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to retrieve tokens." msgstr "authentik 用来获取令牌的 URL。" -#: authentik/sources/oauth/models.py:44 +#: authentik/sources/oauth/models.py msgid "Profile URL" msgstr "个人资料 URL" -#: authentik/sources/oauth/models.py:45 +#: authentik/sources/oauth/models.py msgid "URL used by authentik to get user information." msgstr "authentik 用来获取用户信息的 URL。" -#: authentik/sources/oauth/models.py:48 +#: authentik/sources/oauth/models.py msgid "Additional Scopes" msgstr "额外的作用域" -#: authentik/sources/oauth/models.py:107 +#: authentik/sources/oauth/models.py msgid "OAuth Source" msgstr "OAuth 源" -#: authentik/sources/oauth/models.py:108 +#: authentik/sources/oauth/models.py msgid "OAuth Sources" msgstr "OAuth 源" -#: authentik/sources/oauth/models.py:116 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Source" msgstr "GitHub OAuth 源" -#: authentik/sources/oauth/models.py:117 +#: authentik/sources/oauth/models.py msgid "GitHub OAuth Sources" msgstr "GitHub OAuth 源" -#: authentik/sources/oauth/models.py:125 +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Source" +msgstr "GitLab OAuth 源" + +#: authentik/sources/oauth/models.py +msgid "GitLab OAuth Sources" +msgstr "GitLab OAuth 源" + +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Source" msgstr "Twitch OAuth 源" -#: authentik/sources/oauth/models.py:126 +#: authentik/sources/oauth/models.py msgid "Twitch OAuth Sources" msgstr "Twitch OAuth 源" -#: authentik/sources/oauth/models.py:134 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Source" msgstr "Mailcow OAuth 源" -#: authentik/sources/oauth/models.py:135 +#: authentik/sources/oauth/models.py msgid "Mailcow OAuth Sources" msgstr "Mailcow OAuth 源" -#: authentik/sources/oauth/models.py:143 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Source" msgstr "Twitter OAuth 源" -#: authentik/sources/oauth/models.py:144 +#: authentik/sources/oauth/models.py msgid "Twitter OAuth Sources" msgstr "Twitter OAuth 源" -#: authentik/sources/oauth/models.py:152 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Source" msgstr "Facebook OAuth 源" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py msgid "Facebook OAuth Sources" msgstr "Facebook OAuth 源" -#: authentik/sources/oauth/models.py:161 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Source" msgstr "Discord OAuth 源" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py msgid "Discord OAuth Sources" msgstr "Discord OAuth 源" -#: authentik/sources/oauth/models.py:170 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Source" msgstr "Patreon OAuth 源" -#: authentik/sources/oauth/models.py:171 +#: authentik/sources/oauth/models.py msgid "Patreon OAuth Sources" msgstr "Patreon OAuth 源" -#: authentik/sources/oauth/models.py:179 +#: authentik/sources/oauth/models.py msgid "Google OAuth Source" msgstr "Google OAuth 源" -#: authentik/sources/oauth/models.py:180 +#: authentik/sources/oauth/models.py msgid "Google OAuth Sources" msgstr "Google OAuth 源" -#: authentik/sources/oauth/models.py:188 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Source" msgstr "Azure AD OAuth 源" -#: authentik/sources/oauth/models.py:189 +#: authentik/sources/oauth/models.py msgid "Azure AD OAuth Sources" msgstr "Azure AD OAuth 源" -#: authentik/sources/oauth/models.py:197 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Source" msgstr "OpenID OAuth 源" -#: authentik/sources/oauth/models.py:198 +#: authentik/sources/oauth/models.py msgid "OpenID OAuth Sources" msgstr "OpenID OAuth 源" -#: authentik/sources/oauth/models.py:206 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Source" msgstr "Apple OAuth 源" -#: authentik/sources/oauth/models.py:207 +#: authentik/sources/oauth/models.py msgid "Apple OAuth Sources" msgstr "Apple OAuth 源" -#: authentik/sources/oauth/models.py:215 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Source" msgstr "Okta OAuth 源" -#: authentik/sources/oauth/models.py:216 +#: authentik/sources/oauth/models.py msgid "Okta OAuth Sources" msgstr "Okta OAuth 源" -#: authentik/sources/oauth/models.py:224 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Source" msgstr "Reddit OAuth 源" -#: authentik/sources/oauth/models.py:225 +#: authentik/sources/oauth/models.py msgid "Reddit OAuth Sources" msgstr "Reddit OAuth 源" -#: authentik/sources/oauth/models.py:247 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connection" msgstr "用户 OAuth 源连接" -#: authentik/sources/oauth/models.py:248 +#: authentik/sources/oauth/models.py msgid "User OAuth Source Connections" msgstr "用户 OAuth 源连接" -#: authentik/sources/oauth/views/callback.py:100 -#, python-format -msgid "Authentication failed: %(reason)s" -msgstr "身份验证失败:%(reason)s" +#: authentik/sources/oauth/views/callback.py +#, python-brace-format +msgid "Authentication failed: {reason}" +msgstr "身份验证失败:{reason}" -#: authentik/sources/plex/models.py:37 +#: authentik/sources/plex/models.py msgid "Client identifier used to talk to Plex." msgstr "用来与 Plex 通信的客户端标识符。" -#: authentik/sources/plex/models.py:44 +#: authentik/sources/plex/models.py msgid "" "Which servers a user has to be a member of to be granted access. Empty list " "allows every server." msgstr "用户必须是哪个服务器的成员才能获取权限。空列表允许任何服务器。" -#: authentik/sources/plex/models.py:50 +#: authentik/sources/plex/models.py msgid "Allow friends to authenticate, even if you don't share a server." msgstr "允许好友进行身份验证,即使您不共享服务器。" -#: authentik/sources/plex/models.py:52 +#: authentik/sources/plex/models.py msgid "Plex token used to check friends" msgstr "用于检查好友的 Plex 令牌" -#: authentik/sources/plex/models.py:95 +#: authentik/sources/plex/models.py msgid "Plex Source" msgstr "Plex 源" -#: authentik/sources/plex/models.py:96 +#: authentik/sources/plex/models.py msgid "Plex Sources" msgstr "Plex 源" -#: authentik/sources/plex/models.py:112 +#: authentik/sources/plex/models.py msgid "User Plex Source Connection" msgstr "用户 Plex 源连接" -#: authentik/sources/plex/models.py:113 +#: authentik/sources/plex/models.py msgid "User Plex Source Connections" msgstr "用户 Plex 源连接" -#: authentik/sources/saml/models.py:40 +#: authentik/sources/saml/models.py msgid "Redirect Binding" msgstr "重定向绑定" -#: authentik/sources/saml/models.py:41 +#: authentik/sources/saml/models.py msgid "POST Binding" msgstr "POST 绑定" -#: authentik/sources/saml/models.py:42 +#: authentik/sources/saml/models.py msgid "POST Binding with auto-confirmation" msgstr "带有自动确认功能的 POST 绑定" -#: authentik/sources/saml/models.py:70 +#: authentik/sources/saml/models.py msgid "Flow used before authentication." msgstr "身份验证之前使用的流程。" -#: authentik/sources/saml/models.py:77 +#: authentik/sources/saml/models.py msgid "Issuer" msgstr "颁发者" -#: authentik/sources/saml/models.py:78 +#: authentik/sources/saml/models.py msgid "Also known as Entity ID. Defaults the Metadata URL." msgstr "也称为 Entity ID。 默认为元数据 URL。" -#: authentik/sources/saml/models.py:82 +#: authentik/sources/saml/models.py msgid "SSO URL" msgstr "SSO URL" -#: authentik/sources/saml/models.py:83 +#: authentik/sources/saml/models.py msgid "URL that the initial Login request is sent to." msgstr "初始登录请求发送到的 URL。" -#: authentik/sources/saml/models.py:89 +#: authentik/sources/saml/models.py msgid "SLO URL" msgstr "SLO URL" -#: authentik/sources/saml/models.py:90 +#: authentik/sources/saml/models.py msgid "Optional URL if your IDP supports Single-Logout." msgstr "如果您的 IDP 支持单点登出,则为可选 URL。" -#: authentik/sources/saml/models.py:96 +#: authentik/sources/saml/models.py msgid "" "Allows authentication flows initiated by the IdP. This can be a security " "risk, as no validation of the request ID is done." msgstr "允许由 IdP 启动的身份验证流程。这可能存在安全风险,因为未对请求 ID 进行验证。" -#: authentik/sources/saml/models.py:104 +#: authentik/sources/saml/models.py msgid "" "NameID Policy sent to the IdP. Can be unset, in which case no Policy is " "sent." msgstr "发送给 IdP 的 NameID 策略。可以取消设置,此时不会发送任何策略。" -#: authentik/sources/saml/models.py:115 +#: authentik/sources/saml/models.py msgid "Delete temporary users after" msgstr "多久后删除临时用户" -#: authentik/sources/saml/models.py:118 +#: authentik/sources/saml/models.py msgid "" "Time offset when temporary users should be deleted. This only applies if " "your IDP uses the NameID Format 'transient', and the user doesn't log out " @@ -2040,321 +2173,348 @@ msgstr "" "删除临时用户的时间偏移。这仅适用于您的 IDP 使用 NameID 格式 'transient' " "且用户未手动登出的情况。(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/sources/saml/models.py:142 +#: authentik/sources/saml/models.py msgid "" "Keypair used to sign outgoing Responses going to the Identity Provider." msgstr "密钥对,用于签署发送给身份提供程序的传出响应。" -#: authentik/sources/saml/models.py:226 +#: authentik/sources/saml/models.py msgid "SAML Source" msgstr "SAML 源" -#: authentik/sources/saml/models.py:227 +#: authentik/sources/saml/models.py msgid "SAML Sources" msgstr "SAML 源" -#: authentik/sources/saml/models.py:242 +#: authentik/sources/saml/models.py msgid "User SAML Source Connection" msgstr "用户 SAML 源连接" -#: authentik/sources/saml/models.py:243 +#: authentik/sources/saml/models.py msgid "User SAML Source Connections" msgstr "用户 SAML 源连接" -#: authentik/stages/authenticator_duo/models.py:79 +#: authentik/sources/scim/models.py +msgid "SCIM Source" +msgstr "SCIM 源" + +#: authentik/sources/scim/models.py +msgid "SCIM Sources" +msgstr "SCIM 源" + +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stage" msgstr "Duo 身份验证器设置阶段" -#: authentik/stages/authenticator_duo/models.py:80 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Authenticator Setup Stages" msgstr "Duo 身份验证器设置阶段" -#: authentik/stages/authenticator_duo/models.py:103 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Device" msgstr "Duo 设备" -#: authentik/stages/authenticator_duo/models.py:104 +#: authentik/stages/authenticator_duo/models.py msgid "Duo Devices" msgstr "Duo 设备" -#: authentik/stages/authenticator_sms/models.py:57 +#: authentik/stages/authenticator_sms/models.py msgid "" "When enabled, the Phone number is only used during enrollment to verify the " "users authenticity. Only a hash of the phone number is saved to ensure it is" " not reused in the future." msgstr "启用时,电话号码仅在注册期间用于验证用户的真实性。仅保存电话号码的哈希,以确保将来不会重复使用。" -#: authentik/stages/authenticator_sms/models.py:68 +#: authentik/stages/authenticator_sms/models.py msgid "Optionally modify the payload being sent to custom providers." msgstr "可选地,修改发送到自定义提供程序的载荷。" -#: authentik/stages/authenticator_sms/models.py:81 -#, python-format -msgid "Use this code to authenticate in authentik: %(token)s" -msgstr "使用此代码在 authentik 中验证身份:%(token)s" +#: authentik/stages/authenticator_sms/models.py +#, python-brace-format +msgid "Use this code to authenticate in authentik: {token}" +msgstr "使用此代码在 authentik 中验证身份:{token}" -#: authentik/stages/authenticator_sms/models.py:180 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stage" msgstr "短信身份验证器设置阶段" -#: authentik/stages/authenticator_sms/models.py:181 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Authenticator Setup Stages" msgstr "短信身份验证器设置阶段" -#: authentik/stages/authenticator_sms/models.py:226 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Device" msgstr "短信设备" -#: authentik/stages/authenticator_sms/models.py:227 +#: authentik/stages/authenticator_sms/models.py msgid "SMS Devices" msgstr "短信设备" -#: authentik/stages/authenticator_sms/stage.py:57 -#: authentik/stages/authenticator_totp/stage.py:41 -#: authentik/stages/authenticator_totp/stage.py:44 +#: authentik/stages/authenticator_sms/stage.py +#: authentik/stages/authenticator_totp/stage.py msgid "Code does not match" msgstr "代码不匹配" -#: authentik/stages/authenticator_sms/stage.py:73 +#: authentik/stages/authenticator_sms/stage.py msgid "Invalid phone number" msgstr "无效电话号码" -#: authentik/stages/authenticator_static/models.py:52 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stage" msgstr "静态身份验证器设置阶段" -#: authentik/stages/authenticator_static/models.py:53 +#: authentik/stages/authenticator_static/models.py msgid "Static Authenticator Setup Stages" msgstr "静态身份验证器设置阶段" -#: authentik/stages/authenticator_static/models.py:98 +#: authentik/stages/authenticator_static/models.py msgid "Static Device" msgstr "静态设备" -#: authentik/stages/authenticator_static/models.py:99 +#: authentik/stages/authenticator_static/models.py msgid "Static Devices" msgstr "静态设备" -#: authentik/stages/authenticator_static/models.py:129 +#: authentik/stages/authenticator_static/models.py msgid "Static Token" msgstr "静态令牌" -#: authentik/stages/authenticator_static/models.py:130 +#: authentik/stages/authenticator_static/models.py msgid "Static Tokens" msgstr "静态令牌" -#: authentik/stages/authenticator_totp/models.py:25 +#: authentik/stages/authenticator_totp/models.py msgid "6 digits, widely compatible" msgstr "6 位数字,广泛兼容" -#: authentik/stages/authenticator_totp/models.py:26 +#: authentik/stages/authenticator_totp/models.py msgid "8 digits, not compatible with apps like Google Authenticator" msgstr "8 位数字,与 Google 身份验证器等应用不兼容" -#: authentik/stages/authenticator_totp/models.py:62 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stage" msgstr "TOTP 身份验证器设置阶段" -#: authentik/stages/authenticator_totp/models.py:63 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Authenticator Setup Stages" msgstr "TOTP 身份验证器设置阶段" -#: authentik/stages/authenticator_totp/models.py:244 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Device" msgstr "TOTP 设备" -#: authentik/stages/authenticator_totp/models.py:245 +#: authentik/stages/authenticator_totp/models.py msgid "TOTP Devices" msgstr "TOTP 设备" -#: authentik/stages/authenticator_validate/challenge.py:123 -msgid "Invalid Token" -msgstr "无效令牌" +#: authentik/stages/authenticator_validate/challenge.py +msgid "" +"Invalid Token. Please ensure the time on your device is accurate and try " +"again." +msgstr "无效的令牌。请确保设备上的时间准确并重试。" -#: authentik/stages/authenticator_validate/models.py:18 +#: authentik/stages/authenticator_validate/challenge.py +#: authentik/stages/authenticator_webauthn/stage.py +#, python-brace-format +msgid "Invalid device type. Contact your {brand} administrator for help." +msgstr "无效的设备类型。请联系您的 {brand} 管理员获得帮助。" + +#: authentik/stages/authenticator_validate/models.py msgid "Static" msgstr "静态" -#: authentik/stages/authenticator_validate/models.py:19 +#: authentik/stages/authenticator_validate/models.py msgid "TOTP" msgstr "TOTP" -#: authentik/stages/authenticator_validate/models.py:20 +#: authentik/stages/authenticator_validate/models.py msgid "WebAuthn" msgstr "WebAuthn" -#: authentik/stages/authenticator_validate/models.py:21 +#: authentik/stages/authenticator_validate/models.py msgid "Duo" msgstr "Duo" -#: authentik/stages/authenticator_validate/models.py:22 +#: authentik/stages/authenticator_validate/models.py msgid "SMS" msgstr "短信" -#: authentik/stages/authenticator_validate/models.py:49 +#: authentik/stages/authenticator_validate/models.py msgid "" "Stages used to configure Authenticator when user doesn't have any compatible" " devices. After this configuration Stage passes, the user is not prompted " "again." msgstr "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。" -#: authentik/stages/authenticator_validate/models.py:56 +#: authentik/stages/authenticator_validate/models.py msgid "Device classes which can be used to authenticate" msgstr "可用于进行身份验证的设备类型" -#: authentik/stages/authenticator_validate/models.py:64 +#: authentik/stages/authenticator_validate/models.py msgid "" "If any of the user's device has been used within this threshold, this stage " "will be skipped" msgstr "如果用户的任意设备在此期限内被使用过,此阶段会被跳过。" -#: authentik/stages/authenticator_validate/models.py:70 +#: authentik/stages/authenticator_validate/models.py msgid "Enforce user verification for WebAuthn devices." msgstr "对 WebAuthn 设备强制用户验证。" -#: authentik/stages/authenticator_validate/models.py:92 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stage" msgstr "身份验证器验证阶段" -#: authentik/stages/authenticator_validate/models.py:93 +#: authentik/stages/authenticator_validate/models.py msgid "Authenticator Validation Stages" msgstr "身份验证器验证阶段" -#: authentik/stages/authenticator_webauthn/models.py:112 +#: authentik/stages/authenticator_validate/stage.py +msgid "No (allowed) MFA authenticator configured." +msgstr "未配置(允许的)MFA 身份验证器。" + +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stage" msgstr "WebAuthn 身份验证器设置阶段" -#: authentik/stages/authenticator_webauthn/models.py:113 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Authenticator Setup Stages" msgstr "WebAuthn 身份验证器设置阶段" -#: authentik/stages/authenticator_webauthn/models.py:151 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Device" msgstr "WebAuthn 设备" -#: authentik/stages/authenticator_webauthn/models.py:152 +#: authentik/stages/authenticator_webauthn/models.py msgid "WebAuthn Devices" msgstr "WebAuthn 设备" -#: authentik/stages/captcha/models.py:14 +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device type" +msgstr "WebAuthn 设备类型" + +#: authentik/stages/authenticator_webauthn/models.py +msgid "WebAuthn Device types" +msgstr "WebAuthn 设备类型" + +#: authentik/stages/captcha/models.py msgid "Public key, acquired your captcha Provider." msgstr "公钥,从您的验证码提供商处取得。" -#: authentik/stages/captcha/models.py:15 +#: authentik/stages/captcha/models.py msgid "Private key, acquired your captcha Provider." msgstr "私钥,从您的验证码提供商处取得。" -#: authentik/stages/captcha/models.py:37 +#: authentik/stages/captcha/models.py msgid "Captcha Stage" msgstr "验证码阶段" -#: authentik/stages/captcha/models.py:38 +#: authentik/stages/captcha/models.py msgid "Captcha Stages" msgstr "验证码阶段" -#: authentik/stages/consent/models.py:30 +#: authentik/stages/consent/models.py msgid "" "Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." msgstr "经过多少偏移量后同意授权过期。(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/stages/consent/models.py:50 +#: authentik/stages/consent/models.py msgid "Consent Stage" msgstr "同意授权阶段" -#: authentik/stages/consent/models.py:51 +#: authentik/stages/consent/models.py msgid "Consent Stages" msgstr "同意授权阶段" -#: authentik/stages/consent/models.py:72 +#: authentik/stages/consent/models.py msgid "User Consent" msgstr "用户同意授权" -#: authentik/stages/consent/models.py:73 +#: authentik/stages/consent/models.py msgid "User Consents" msgstr "用户同意授权" -#: authentik/stages/deny/models.py:32 +#: authentik/stages/deny/models.py msgid "Deny Stage" msgstr "拒绝阶段" -#: authentik/stages/deny/models.py:33 +#: authentik/stages/deny/models.py msgid "Deny Stages" msgstr "拒绝阶段" -#: authentik/stages/dummy/models.py:34 +#: authentik/stages/dummy/models.py msgid "Dummy Stage" msgstr "虚拟阶段" -#: authentik/stages/dummy/models.py:35 +#: authentik/stages/dummy/models.py msgid "Dummy Stages" msgstr "虚拟阶段" -#: authentik/stages/email/models.py:26 +#: authentik/stages/email/models.py msgid "Password Reset" msgstr "密码重置" -#: authentik/stages/email/models.py:30 +#: authentik/stages/email/models.py msgid "Account Confirmation" msgstr "账户确认" -#: authentik/stages/email/models.py:59 +#: authentik/stages/email/models.py msgid "" "When enabled, global Email connection settings will be used and connection " "settings below will be ignored." msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。" -#: authentik/stages/email/models.py:74 +#: authentik/stages/email/models.py msgid "Activate users upon completion of stage." msgstr "完成阶段后激活用户。" -#: authentik/stages/email/models.py:78 +#: authentik/stages/email/models.py msgid "Time in minutes the token sent is valid." msgstr "发出令牌的有效时间(单位为分钟)。" -#: authentik/stages/email/models.py:132 +#: authentik/stages/email/models.py msgid "Email Stage" msgstr "电子邮件阶段" -#: authentik/stages/email/models.py:133 +#: authentik/stages/email/models.py msgid "Email Stages" msgstr "电子邮件阶段" -#: authentik/stages/email/stage.py:126 +#: authentik/stages/email/stage.py msgid "Exception occurred while rendering E-mail template" msgstr "渲染电子邮件模板时发生异常" -#: authentik/stages/email/stage.py:140 +#: authentik/stages/email/stage.py msgid "Successfully verified Email." msgstr "已成功验证电子邮件。" -#: authentik/stages/email/stage.py:147 authentik/stages/email/stage.py:173 +#: authentik/stages/email/stage.py msgid "No pending user." msgstr "没有待处理的用户。" -#: authentik/stages/email/stage.py:163 +#: authentik/stages/email/stage.py msgid "Email sent." msgstr "电子邮件已发出。" -#: authentik/stages/email/stage.py:176 +#: authentik/stages/email/stage.py msgid "Email Successfully sent." msgstr "成功发送电子邮件。" -#: authentik/stages/email/templates/email/account_confirmation.html:10 -#: authentik/stages/email/templates/email/account_confirmation.txt:1 +#: authentik/stages/email/templates/email/account_confirmation.html +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "Welcome!" msgstr "欢迎!" -#: authentik/stages/email/templates/email/account_confirmation.html:19 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just press the button below." msgstr "我们很高兴您能开始使用。首先,您需要确认您的账户。只需点击下面的按钮。" -#: authentik/stages/email/templates/email/account_confirmation.html:24 +#: authentik/stages/email/templates/email/account_confirmation.html msgid "Confirm Account" msgstr "确认账户" -#: authentik/stages/email/templates/email/account_confirmation.html:36 +#: authentik/stages/email/templates/email/account_confirmation.html #, python-format msgid "" "\n" @@ -2365,13 +2525,13 @@ msgstr "" " 如果按钮无效,请复制并在浏览器中粘贴以下链接:%(url)s\n" " " -#: authentik/stages/email/templates/email/account_confirmation.txt:3 +#: authentik/stages/email/templates/email/account_confirmation.txt msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just open the link below." msgstr "我们很高兴您能开始使用。首先,您需要确认您的账户。只需打开下面的链接。" -#: authentik/stages/email/templates/email/event_notification.html:46 +#: authentik/stages/email/templates/email/event_notification.html #, python-format msgid "" "\n" @@ -2382,19 +2542,19 @@ msgstr "" " 此邮件由通知递送 %(name)s 发送。\n" " " -#: authentik/stages/email/templates/email/event_notification.txt:1 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Dear authentik user," msgstr "亲爱的 authentik 用户," -#: authentik/stages/email/templates/email/event_notification.txt:3 +#: authentik/stages/email/templates/email/event_notification.txt msgid "The following notification was created:" msgstr "以下通知已创建:" -#: authentik/stages/email/templates/email/event_notification.txt:8 +#: authentik/stages/email/templates/email/event_notification.txt msgid "Additional attributes:" msgstr "额外属性:" -#: authentik/stages/email/templates/email/event_notification.txt:13 +#: authentik/stages/email/templates/email/event_notification.txt #, python-format msgid "" "\n" @@ -2403,7 +2563,7 @@ msgstr "" "\n" "此邮件由通知递送 %(name)s 发送。\n" -#: authentik/stages/email/templates/email/password_reset.html:10 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2414,7 +2574,7 @@ msgstr "" " %(username)s 您好,\n" " " -#: authentik/stages/email/templates/email/password_reset.html:21 +#: authentik/stages/email/templates/email/password_reset.html msgid "" "\n" " You recently requested to change your password for your authentik account. Use the button below to set a new password.\n" @@ -2424,7 +2584,7 @@ msgstr "" " 您最近请求更改您的 authentik 账户密码。使用下面的按钮设置新密码。\n" " " -#: authentik/stages/email/templates/email/password_reset.html:39 +#: authentik/stages/email/templates/email/password_reset.html #, python-format msgid "" "\n" @@ -2435,12 +2595,12 @@ msgstr "" " 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n" " " -#: authentik/stages/email/templates/email/password_reset.txt:1 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "Hi %(username)s," msgstr "您好 %(username)s," -#: authentik/stages/email/templates/email/password_reset.txt:3 +#: authentik/stages/email/templates/email/password_reset.txt msgid "" "\n" "You recently requested to change your password for your authentik account. Use the link below to set a new password.\n" @@ -2448,7 +2608,7 @@ msgstr "" "\n" "您最近请求更改您的 authentik 账户密码。使用下面的链接设置新密码。\n" -#: authentik/stages/email/templates/email/password_reset.txt:7 +#: authentik/stages/email/templates/email/password_reset.txt #, python-format msgid "" "\n" @@ -2457,11 +2617,11 @@ msgstr "" "\n" "如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n" -#: authentik/stages/email/templates/email/setup.html:9 +#: authentik/stages/email/templates/email/setup.html msgid "authentik Test-Email" msgstr "authentik 测试电子邮件" -#: authentik/stages/email/templates/email/setup.html:17 +#: authentik/stages/email/templates/email/setup.html msgid "" "\n" " This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2471,7 +2631,7 @@ msgstr "" " 这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n" " " -#: authentik/stages/email/templates/email/setup.txt:2 +#: authentik/stages/email/templates/email/setup.txt msgid "" "\n" "This is a test email to inform you, that you've successfully configured authentik emails.\n" @@ -2479,263 +2639,263 @@ msgstr "" "\n" "这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n" -#: authentik/stages/identification/api.py:20 +#: authentik/stages/identification/api.py msgid "When no user fields are selected, at least one source must be selected" msgstr "如果未选择用户字段,则至少要选择一个源" -#: authentik/stages/identification/models.py:29 +#: authentik/stages/identification/models.py msgid "" "Fields of the user object to match against. (Hold shift to select multiple " "options)" msgstr "用来匹配的用户对象字段。(按住 Shift 多选)" -#: authentik/stages/identification/models.py:47 +#: authentik/stages/identification/models.py msgid "When enabled, user fields are matched regardless of their casing." msgstr "启用后,无论大小写如何,都将匹配用户字段。" -#: authentik/stages/identification/models.py:52 +#: authentik/stages/identification/models.py msgid "" "When a valid username/email has been entered, and this option is enabled, " "the user's username and avatar will be shown. Otherwise, the text that the " "user entered will be shown" msgstr "如果输入了有效的用户名/电子邮箱,并且启用了此选项,则会显示用户的用户名和头像。否则,将显示用户输入的文本" -#: authentik/stages/identification/models.py:60 +#: authentik/stages/identification/models.py msgid "" "When enabled, the stage will succeed and continue even when incorrect user " "info is entered." msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。" -#: authentik/stages/identification/models.py:72 +#: authentik/stages/identification/models.py msgid "Optional enrollment flow, which is linked at the bottom of the page." msgstr "可选注册流程,链接在页面底部。" -#: authentik/stages/identification/models.py:81 +#: authentik/stages/identification/models.py msgid "Optional recovery flow, which is linked at the bottom of the page." msgstr "可选的恢复流程,链接在页面底部。" -#: authentik/stages/identification/models.py:90 +#: authentik/stages/identification/models.py msgid "Optional passwordless flow, which is linked at the bottom of the page." msgstr "可选的无密码流程,链接在页面底部。" -#: authentik/stages/identification/models.py:94 +#: authentik/stages/identification/models.py msgid "Specify which sources should be shown." msgstr "指定应显示哪些源。" -#: authentik/stages/identification/models.py:115 +#: authentik/stages/identification/models.py msgid "Identification Stage" msgstr "识别阶段" -#: authentik/stages/identification/models.py:116 +#: authentik/stages/identification/models.py msgid "Identification Stages" msgstr "识别阶段" -#: authentik/stages/identification/stage.py:188 +#: authentik/stages/identification/stage.py msgid "Log in" msgstr "登录" -#: authentik/stages/identification/stage.py:189 +#: authentik/stages/identification/stage.py msgid "Continue" msgstr "继续" -#: authentik/stages/invitation/models.py:21 +#: authentik/stages/invitation/models.py msgid "" "If this flag is set, this Stage will jump to the next Stage when no " "Invitation is given. By default this Stage will cancel the Flow when no " "invitation is given." msgstr "如果设置了此标志,则当没有发出邀请时,此阶段将跳转到下一个阶段。默认情况下,当没有发出邀请时,此阶段将取消流程。" -#: authentik/stages/invitation/models.py:44 +#: authentik/stages/invitation/models.py msgid "Invitation Stage" msgstr "邀请阶段" -#: authentik/stages/invitation/models.py:45 +#: authentik/stages/invitation/models.py msgid "Invitation Stages" msgstr "邀请阶段" -#: authentik/stages/invitation/models.py:60 +#: authentik/stages/invitation/models.py msgid "When set, only the configured flow can use this invitation." msgstr "设置时,只有配置的流程可以使用此邀请。" -#: authentik/stages/invitation/models.py:64 +#: authentik/stages/invitation/models.py msgid "When enabled, the invitation will be deleted after usage." msgstr "启用后,邀请将在使用后被删除。" -#: authentik/stages/invitation/models.py:71 +#: authentik/stages/invitation/models.py msgid "Optional fixed data to enforce on user enrollment." msgstr "在用户注册时强制设置的可选固定数据。" -#: authentik/stages/invitation/models.py:84 +#: authentik/stages/invitation/models.py msgid "Invitation" msgstr "邀请" -#: authentik/stages/invitation/models.py:85 +#: authentik/stages/invitation/models.py msgid "Invitations" msgstr "邀请" -#: authentik/stages/invitation/stage.py:62 +#: authentik/stages/invitation/stage.py msgid "Invalid invite/invite not found" msgstr "邀请无效/未找到" -#: authentik/stages/password/models.py:20 +#: authentik/stages/password/models.py msgid "User database + standard password" msgstr "用户数据库 + 标准密码" -#: authentik/stages/password/models.py:24 +#: authentik/stages/password/models.py msgid "User database + app passwords" msgstr "用户数据库 + 应用程序密码" -#: authentik/stages/password/models.py:28 +#: authentik/stages/password/models.py msgid "User database + LDAP password" msgstr "用户数据库 + LDAP 密码" -#: authentik/stages/password/models.py:38 +#: authentik/stages/password/models.py msgid "Selection of backends to test the password against." msgstr "选择用于测试密码的后端。" -#: authentik/stages/password/models.py:43 +#: authentik/stages/password/models.py msgid "" "How many attempts a user has before the flow is canceled. To lock the user " "out, use a reputation policy and a user_write stage." msgstr "在取消流程之前,用户可以尝试多少次。要锁定用户,请使用信誉策略和 user_write 阶段。" -#: authentik/stages/password/models.py:75 +#: authentik/stages/password/models.py msgid "Password Stage" msgstr "密码阶段" -#: authentik/stages/password/models.py:76 +#: authentik/stages/password/models.py msgid "Password Stages" msgstr "密码阶段" -#: authentik/stages/password/stage.py:124 +#: authentik/stages/password/stage.py msgid "Invalid password" msgstr "无效密码" -#: authentik/stages/prompt/models.py:43 +#: authentik/stages/prompt/models.py msgid "Text: Simple Text input" msgstr "文本:简单文本输入" -#: authentik/stages/prompt/models.py:45 +#: authentik/stages/prompt/models.py msgid "Text area: Multiline Text Input." msgstr "文本框:多行文本输入。" -#: authentik/stages/prompt/models.py:48 +#: authentik/stages/prompt/models.py msgid "Text (read-only): Simple Text input, but cannot be edited." msgstr "文本(只读):简单文本输入,但无法编辑。" -#: authentik/stages/prompt/models.py:52 +#: authentik/stages/prompt/models.py msgid "Text area (read-only): Multiline Text input, but cannot be edited." msgstr "文本框(只读):多行文本输入,但无法编辑。" -#: authentik/stages/prompt/models.py:58 +#: authentik/stages/prompt/models.py msgid "" "Username: Same as Text input, but checks for and prevents duplicate " "usernames." msgstr "用户名:与文本输入相同,但检查并防止用户名重复。" -#: authentik/stages/prompt/models.py:60 +#: authentik/stages/prompt/models.py msgid "Email: Text field with Email type." msgstr "电子邮箱:电子邮箱类型的文本字段。" -#: authentik/stages/prompt/models.py:64 +#: authentik/stages/prompt/models.py msgid "" "Password: Masked input, multiple inputs of this type on the same prompt need" " to be identical." msgstr "密码:屏蔽显示输入内容,多个此类型的输入如果在同一个输入项下,则内容需要相同。" -#: authentik/stages/prompt/models.py:71 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a group of radio buttons." msgstr "显示为一组单选按钮的固定选项字段。" -#: authentik/stages/prompt/models.py:73 +#: authentik/stages/prompt/models.py msgid "Fixed choice field rendered as a dropdown." msgstr "显示为下拉框的固定选项字段。" -#: authentik/stages/prompt/models.py:80 +#: authentik/stages/prompt/models.py msgid "" "File: File upload for arbitrary files. File content will be available in " "flow context as data-URI" msgstr "文件:任意文件上传。文件内容将在流程上下文中以 data-URI 形式提供" -#: authentik/stages/prompt/models.py:85 +#: authentik/stages/prompt/models.py msgid "Separator: Static Separator Line" msgstr "分隔符:静态分隔线" -#: authentik/stages/prompt/models.py:86 +#: authentik/stages/prompt/models.py msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "隐藏:隐藏字段,可用于将数据插入表单。" -#: authentik/stages/prompt/models.py:87 +#: authentik/stages/prompt/models.py msgid "Static: Static value, displayed as-is." msgstr "静态:静态值,按原样显示。" -#: authentik/stages/prompt/models.py:89 +#: authentik/stages/prompt/models.py msgid "authentik: Selection of locales authentik supports" msgstr "authentik:选择 authentik 支持的语言环境" -#: authentik/stages/prompt/models.py:116 +#: authentik/stages/prompt/models.py msgid "Name of the form field, also used to store the value" msgstr "表单域的名称,也用于存储值" -#: authentik/stages/prompt/models.py:124 +#: authentik/stages/prompt/models.py msgid "" "Optionally provide a short hint that describes the expected input value. " "When creating a fixed choice field, enable interpreting as expression and " "return a list to return multiple choices." msgstr "可选的简短提示,用来描述期望的输入值。在创建固定选项字段时,启用以表达式解释,并返回多个选项的列表。" -#: authentik/stages/prompt/models.py:132 +#: authentik/stages/prompt/models.py msgid "" "Optionally pre-fill the input with an initial value. When creating a fixed " "choice field, enable interpreting as expression and return a list to return " "multiple default choices." msgstr "可选的预设输入初始值。在创建固定选项字段时,启用以表达式解释,并返回多个默认选项的列表。" -#: authentik/stages/prompt/models.py:321 +#: authentik/stages/prompt/models.py msgid "Prompt" msgstr "输入" -#: authentik/stages/prompt/models.py:322 +#: authentik/stages/prompt/models.py msgid "Prompts" msgstr "输入" -#: authentik/stages/prompt/models.py:349 +#: authentik/stages/prompt/models.py msgid "Prompt Stage" msgstr "输入阶段" -#: authentik/stages/prompt/models.py:350 +#: authentik/stages/prompt/models.py msgid "Prompt Stages" msgstr "输入阶段" -#: authentik/stages/prompt/stage.py:108 +#: authentik/stages/prompt/stage.py msgid "Passwords don't match." msgstr "密码不匹配。" -#: authentik/stages/user_delete/models.py:31 +#: authentik/stages/user_delete/models.py msgid "User Delete Stage" msgstr "用户删除阶段" -#: authentik/stages/user_delete/models.py:32 +#: authentik/stages/user_delete/models.py msgid "User Delete Stages" msgstr "用户删除阶段" -#: authentik/stages/user_delete/stage.py:18 +#: authentik/stages/user_delete/stage.py msgid "No Pending User." msgstr "没有待处理的用户。" -#: authentik/stages/user_login/models.py:47 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured network" msgstr "将此阶段创建的会话与配置的网络绑定" -#: authentik/stages/user_login/models.py:52 +#: authentik/stages/user_login/models.py msgid "Bind sessions created by this stage to the configured GeoIP location" msgstr "将此阶段创建的会话与配置的 GeoIP 位置绑定" -#: authentik/stages/user_login/models.py:55 +#: authentik/stages/user_login/models.py msgid "Terminate all other sessions of the user logging in." msgstr "终止用户登录的所有其他会话。" -#: authentik/stages/user_login/models.py:61 +#: authentik/stages/user_login/models.py msgid "" "Offset the session will be extended by when the user picks the remember me " "option. Default of 0 means that the remember me option will not be shown. " @@ -2744,113 +2904,120 @@ msgstr "" "当用户选择“记住我”选项时,会话将会延长的时间。默认值 0 " "表示不显示“记住我”选项。(格式:hours=-1;minutes=-2;seconds=-3)" -#: authentik/stages/user_login/models.py:84 +#: authentik/stages/user_login/models.py msgid "User Login Stage" msgstr "用户登录阶段" -#: authentik/stages/user_login/models.py:85 +#: authentik/stages/user_login/models.py msgid "User Login Stages" msgstr "用户登录阶段" -#: authentik/stages/user_login/stage.py:85 +#: authentik/stages/user_login/stage.py msgid "No Pending user to login." msgstr "没有待定用户可以登录。" -#: authentik/stages/user_login/stage.py:112 +#: authentik/stages/user_login/stage.py msgid "Successfully logged in!" msgstr "已成功登录!" -#: authentik/stages/user_logout/models.py:30 +#: authentik/stages/user_logout/models.py msgid "User Logout Stage" msgstr "用户登出阶段" -#: authentik/stages/user_logout/models.py:31 +#: authentik/stages/user_logout/models.py msgid "User Logout Stages" msgstr "用户登出阶段" -#: authentik/stages/user_write/models.py:31 +#: authentik/stages/user_write/models.py msgid "When set, newly created users are inactive and cannot login." msgstr "设置后,新创建的用户将处于未激活状态,且无法登录。" -#: authentik/stages/user_write/models.py:39 +#: authentik/stages/user_write/models.py msgid "Optionally add newly created users to this group." msgstr "可选,将新创建的用户添加到此组。" -#: authentik/stages/user_write/models.py:68 +#: authentik/stages/user_write/models.py msgid "User Write Stage" msgstr "用户写入阶段" -#: authentik/stages/user_write/models.py:69 +#: authentik/stages/user_write/models.py msgid "User Write Stages" msgstr "用户写入阶段" -#: authentik/stages/user_write/stage.py:141 +#: authentik/stages/user_write/stage.py msgid "No Pending data." msgstr "没有待处理的数据。" -#: authentik/stages/user_write/stage.py:147 +#: authentik/stages/user_write/stage.py msgid "No user found and can't create new user." msgstr "未找到用户并且无法创建新用户。" -#: authentik/stages/user_write/stage.py:164 -#: authentik/stages/user_write/stage.py:178 +#: authentik/stages/user_write/stage.py msgid "Failed to update user. Please try again later." msgstr "更新用户失败。请稍后重试。" -#: authentik/tenants/models.py:29 +#: authentik/tenants/models.py msgid "" "Schema name must start with t_, only contain lowercase letters and numbers " "and be less than 63 characters." msgstr "模式名称必须以 t_ 开始,只能包含小写字母和数字,并且少于 63 个字符。" -#: authentik/tenants/models.py:49 +#: authentik/tenants/models.py msgid "Configure how authentik should show avatars for users." msgstr "配置 authentik 应该如何显示用户头像。" -#: authentik/tenants/models.py:53 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their name." msgstr "启用用户修改自己名称的能力。" -#: authentik/tenants/models.py:56 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their email address." msgstr "启用用户修改自己电子邮件地址的能力。" -#: authentik/tenants/models.py:59 +#: authentik/tenants/models.py msgid "Enable the ability for users to change their username." msgstr "启用用户修改自己用户名的能力。" -#: authentik/tenants/models.py:65 +#: authentik/tenants/models.py msgid "" "Events will be deleted after this duration.(Format: " "weeks=3;days=2;hours=3,seconds=2)." msgstr "事件会在多久后被删除。(格式:weeks=3;days=2;hours=3,seconds=2)。" -#: authentik/tenants/models.py:69 +#: authentik/tenants/models.py msgid "The option configures the footer links on the flow executor pages." msgstr "此选项配置流程执行器页面上的页脚链接。" -#: authentik/tenants/models.py:75 +#: authentik/tenants/models.py msgid "" "When enabled, all the events caused by a user will be deleted upon the " "user's deletion." msgstr "启用时,所有由用户造成的事件会在相应用户被删除时一并删除。" -#: authentik/tenants/models.py:81 +#: authentik/tenants/models.py msgid "Globally enable/disable impersonation." msgstr "全局启用/禁用模拟身份。" -#: authentik/tenants/models.py:104 +#: authentik/tenants/models.py +msgid "Default token duration" +msgstr "默认令牌持续时间" + +#: authentik/tenants/models.py +msgid "Default token length" +msgstr "默认令牌长度" + +#: authentik/tenants/models.py msgid "Tenant" msgstr "租户" -#: authentik/tenants/models.py:105 +#: authentik/tenants/models.py msgid "Tenants" msgstr "租户" -#: authentik/tenants/models.py:125 +#: authentik/tenants/models.py msgid "Domain" msgstr "域名" -#: authentik/tenants/models.py:126 +#: authentik/tenants/models.py msgid "Domains" msgstr "域名" diff --git a/locale/zh_TW/LC_MESSAGES/django.mo b/locale/zh_TW/LC_MESSAGES/django.mo index fa2b1acc63..05a91e0aa2 100644 Binary files a/locale/zh_TW/LC_MESSAGES/django.mo and b/locale/zh_TW/LC_MESSAGES/django.mo differ diff --git a/manage.py b/manage.py index c665dab08d..4c5120225a 100755 --- a/manage.py +++ b/manage.py @@ -4,7 +4,13 @@ import os import sys import warnings +from cryptography.exceptions import InternalError +from cryptography.hazmat.backends.openssl.backend import backend from defusedxml import defuse_stdlib +from django.utils.autoreload import DJANGO_AUTORELOAD_ENV + +from lifecycle.migrate import run_migrations +from lifecycle.wait_for_db import wait_for_db warnings.filterwarnings("ignore", "SelectableGroups dict interface") warnings.filterwarnings( @@ -18,8 +24,25 @@ warnings.filterwarnings( defuse_stdlib() +try: + backend._enable_fips() +except InternalError: + pass + + if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings") + wait_for_db() + if ( + len(sys.argv) > 1 + # Explicitly only run migrate for server and worker + # `bootstrap_tasks` is a special case as that command might be triggered by the `ak` + # script to pre-run certain tasks for an automated install + and sys.argv[1] in ["dev_server", "worker", "bootstrap_tasks"] + # and don't run if this is the child process of a dev_server + and os.environ.get(DJANGO_AUTORELOAD_ENV, None) is None + ): + run_migrations() try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/package.json b/package.json new file mode 100644 index 0000000000..03c2e88dae --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "@goauthentik/authentik", + "version": "1.0.0", + "private": true +} diff --git a/poetry.lock b/poetry.lock index 30229c522e..81319c3e4a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,88 +1,88 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" -version = "3.9.1" +version = "3.9.5" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"}, - {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"}, - {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"}, - {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"}, - {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"}, - {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"}, - {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"}, - {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"}, - {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"}, - {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"}, - {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"}, - {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, ] [package.dependencies] @@ -150,13 +150,13 @@ files = [ [[package]] name = "anyio" -version = "4.2.0" +version = "4.3.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, - {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, ] [package.dependencies] @@ -227,13 +227,13 @@ tests = ["pytest"] [[package]] name = "asgiref" -version = "3.7.2" +version = "3.8.1" description = "ASGI specs, helper code, and adapters" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, - {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, + {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, + {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, ] [package.extras] @@ -250,17 +250,6 @@ files = [ {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, ] -[[package]] -name = "astroid" -version = "3.0.2" -description = "An abstract syntax tree for Python with inference support." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "astroid-3.0.2-py3-none-any.whl", hash = "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c"}, - {file = "astroid-3.0.2.tar.gz", hash = "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91"}, -] - [[package]] name = "attrs" version = "23.2.0" @@ -326,15 +315,51 @@ six = "*" [package.extras] visualize = ["Twisted (>=16.1.1)", "graphviz (>0.5.1)"] +[[package]] +name = "azure-core" +version = "1.30.1" +description = "Microsoft Azure Core Library for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "azure-core-1.30.1.tar.gz", hash = "sha256:26273a254131f84269e8ea4464f3560c731f29c0c1f69ac99010845f239c1a8f"}, + {file = "azure_core-1.30.1-py3-none-any.whl", hash = "sha256:7c5ee397e48f281ec4dd773d67a0a47a0962ed6fa833036057f9ea067f688e74"}, +] + +[package.dependencies] +requests = ">=2.21.0" +six = ">=1.11.0" +typing-extensions = ">=4.6.0" + +[package.extras] +aio = ["aiohttp (>=3.0)"] + +[[package]] +name = "azure-identity" +version = "1.16.0" +description = "Microsoft Azure Identity Library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "azure-identity-1.16.0.tar.gz", hash = "sha256:6ff1d667cdcd81da1ceab42f80a0be63ca846629f518a922f7317a7e3c844e1b"}, + {file = "azure_identity-1.16.0-py3-none-any.whl", hash = "sha256:722fdb60b8fdd55fa44dc378b8072f4b419b56a5e54c0de391f644949f3a826f"}, +] + +[package.dependencies] +azure-core = ">=1.23.0" +cryptography = ">=2.5" +msal = ">=1.24.0" +msal-extensions = ">=0.3.0" + [[package]] name = "bandit" -version = "1.7.7" +version = "1.7.8" description = "Security oriented static analyser for python code." optional = false python-versions = ">=3.8" files = [ - {file = "bandit-1.7.7-py3-none-any.whl", hash = "sha256:17e60786a7ea3c9ec84569fd5aee09936d116cb0cb43151023258340dbffb7ed"}, - {file = "bandit-1.7.7.tar.gz", hash = "sha256:527906bec6088cb499aae31bc962864b4e77569e9d529ee51df3a93b4b8ab28a"}, + {file = "bandit-1.7.8-py3-none-any.whl", hash = "sha256:509f7af645bc0cd8fd4587abc1a038fc795636671ee8204d502b933aee44f381"}, + {file = "bandit-1.7.8.tar.gz", hash = "sha256:36de50f720856ab24a24dbaa5fee2c66050ed97c1477e0a1159deab1775eab6b"}, ] [package.dependencies] @@ -345,6 +370,7 @@ stevedore = ">=1.20.0" [package.extras] baseline = ["GitPython (>=3.1.30)"] +sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] toml = ["tomli (>=1.1.0)"] yaml = ["PyYAML"] @@ -402,33 +428,33 @@ files = [ [[package]] name = "black" -version = "23.12.1" +version = "24.4.2" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, + {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, + {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, + {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, + {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, + {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, + {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, + {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, + {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, + {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, + {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, + {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, + {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, + {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, + {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, + {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, + {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, + {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, + {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, + {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, + {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, + {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, + {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, ] [package.dependencies] @@ -446,17 +472,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.34.15" +version = "1.34.95" description = "The AWS SDK for Python" optional = false -python-versions = ">= 3.8" +python-versions = ">=3.8" files = [ - {file = "boto3-1.34.15-py3-none-any.whl", hash = "sha256:f8f16c2d0ec1dca291857f1c138d5c30e01e40f653443cc2679e2f6ae71b05a6"}, - {file = "boto3-1.34.15.tar.gz", hash = "sha256:2b74c58f475ff0dcf2f3637da9367a9465d29fad971ff5d8dc54ac39554e9022"}, + {file = "boto3-1.34.95-py3-none-any.whl", hash = "sha256:e836b71d79671270fccac0a4d4c8ec239a6b82ea47c399b64675aa597d0ee63b"}, + {file = "boto3-1.34.95.tar.gz", hash = "sha256:decf52f8d5d8a1b10c9ff2a0e96ee207ed79e33d2e53fdf0880a5cbef70785e0"}, ] [package.dependencies] -botocore = ">=1.34.15,<1.35.0" +botocore = ">=1.34.95,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -465,22 +491,22 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.15" +version = "1.34.95" description = "Low-level, data-driven core of boto 3." optional = false -python-versions = ">= 3.8" +python-versions = ">=3.8" files = [ - {file = "botocore-1.34.15-py3-none-any.whl", hash = "sha256:16bcf871e67ef0177593f06e9e5bae4db51c9a9a2e953cb14feeb42d53441a85"}, - {file = "botocore-1.34.15.tar.gz", hash = "sha256:c3c3404962a6d9d5e1634bd70ed53b8eff1ff17ee9d7a6240e9e8c94db48ad6f"}, + {file = "botocore-1.34.95-py3-none-any.whl", hash = "sha256:ead5823e0dd6751ece5498cb979fd9abf190e691c8833bcac6876fd6ca261fa7"}, + {file = "botocore-1.34.95.tar.gz", hash = "sha256:6bd76a2eadb42b91fa3528392e981ad5b4dfdee3968fa5b904278acf6cbf15ff"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" -urllib3 = {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""} +urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} [package.extras] -crt = ["awscrt (==0.19.19)"] +crt = ["awscrt (==0.20.9)"] [[package]] name = "bump2version" @@ -495,59 +521,59 @@ files = [ [[package]] name = "cachetools" -version = "5.3.2" +version = "5.3.3" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, - {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] [[package]] name = "cbor2" -version = "5.5.1" +version = "5.6.3" description = "CBOR (de)serializer with extensive tag support" optional = false python-versions = ">=3.8" files = [ - {file = "cbor2-5.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:37ba4f719384bd4ea317e92a8763ea343e205f3112c8241778fd9dbc64ae1498"}, - {file = "cbor2-5.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:425ae919120b9d05b4794b3e5faf6584fc47a9d61db059d4f00ce16ae93a3f63"}, - {file = "cbor2-5.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c511ff6356d6f4292ced856d5048a24ee61a85634816f29dadf1f089e8cb4f9"}, - {file = "cbor2-5.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6ab54a9282dd99a3a70d0f64706d3b3592e7920564a93101caa74dec322346c"}, - {file = "cbor2-5.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:39d94852dd61bda5b3d2bfe74e7b194a7199937d270f90099beec3e7584f0c9b"}, - {file = "cbor2-5.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65532ba929beebe1c63317ad00c79d4936b60a5c29a3c329d2aa7df4e72ad907"}, - {file = "cbor2-5.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:1206180f66a9ad23e692cf457610c877f186ad303a1264b6c5335015b7bee83e"}, - {file = "cbor2-5.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:42155a20be46312fad2ceb85a408e2d90da059c2d36a65e0b99abca57c5357fd"}, - {file = "cbor2-5.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6f3827ae14c009df9b37790f1da5cd1f9d64f7ffec472a49ebf865c0af6b77e9"}, - {file = "cbor2-5.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bfa417dbb8b4581ad3c2312469899518596551cfb0fe5bdaf8a6921cff69d7e"}, - {file = "cbor2-5.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3317e7dfb4f3180be90bcd853204558d89f119b624c2168153b53dea305e79d"}, - {file = "cbor2-5.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a5770bdf4340de55679efe6c38fc6d64529fda547e7a85eb0217a82717a8235"}, - {file = "cbor2-5.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b5d53826ad0c92fcb004b2a475896610b51e0ca010f6c37d762aae44ab0807b2"}, - {file = "cbor2-5.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc77cac985f7f7a20f2d8b1957d1e79393d7df823f61c7c6173d3a0011c1d770"}, - {file = "cbor2-5.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9e45d5aa8e484b4bf57240d8e7949389f1c9d4073758abb30954386321b55c9d"}, - {file = "cbor2-5.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93b949a66bec40dd0ca87a6d026136fea2cf1660120f921199a47ac8027af253"}, - {file = "cbor2-5.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93d601ca92d917f769370a5e6c3ead62dca6451b2b603915e4fcf300083b9fcd"}, - {file = "cbor2-5.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11876abd50b9f70d114fcdbb0b5a3249ccd7d321465f0350028fd6d2317e114"}, - {file = "cbor2-5.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd77c558decdba2a2a7a463e6346d53781d2163bacf205f77b999f561ba4ac73"}, - {file = "cbor2-5.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efb81920d80410b8e80a4a6a8b06ec9b766be0ae7f3029af8ae4b30914edcfa3"}, - {file = "cbor2-5.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:4bb35f3b1ebd4b7b37628f0cd5c839f3008dec669194a2a4a33d91bab7f8663b"}, - {file = "cbor2-5.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f41e4a439f642954ed728dc18915098b5f2ebec7029eaebe52c06c52b6a9a63a"}, - {file = "cbor2-5.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4eae4d56314f22920a28bf7affefdfc918646877ce3b16220dc6cf38a584aa41"}, - {file = "cbor2-5.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:559a0c1ec8dcedd6142b81727403e0f5a2e8f4c18e8bb3c548107ec39af4e9cb"}, - {file = "cbor2-5.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:537da7bfee97ee44a11b300c034c18e674af6a5dc4718a6fba141037f099c7ec"}, - {file = "cbor2-5.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5c99fd8bbc6bbf3bf4d6b2996594ae633b778b27b0531559487950762c4e1e3f"}, - {file = "cbor2-5.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ee46e6dbc8e2cf302a022fec513d57dba65e9d5ec495bcd1ad97a5dbdbab249"}, - {file = "cbor2-5.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:67e2be461320197495fff55f250b111d4125a0a2d02e6256e41f8598adc3ad3f"}, - {file = "cbor2-5.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4384a56afef0b908b61c8ea3cca3e257a316427ace3411308f51ee301b23adf9"}, - {file = "cbor2-5.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8cc64acc606b7f2a4b673a1d6cde5a9cb1860a6ce27b353e269c9535efbd62c"}, - {file = "cbor2-5.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50019fea3cb07fa9b2b53772a52b4243e87de232591570c4c272b3ebdb419493"}, - {file = "cbor2-5.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a18be0af9241883bc67a036c1f33e3f9956d31337ccd412194bf759bc1095e03"}, - {file = "cbor2-5.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:60e7e0073291096605de27de3ce006148cf9a095199160439555f14f93d044d5"}, - {file = "cbor2-5.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41f7501338228b27dac88c1197928cf8985f6fc775f59be89c6fdaddb4e69658"}, - {file = "cbor2-5.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c85ab7697252af2240e939707c935ea18081ccb580d4b5b9a94b04148ab2c32b"}, - {file = "cbor2-5.5.1-py3-none-any.whl", hash = "sha256:dca639c8ff81b9f0c92faf97324adfdbfb5c2a5bb97f249606c6f5b94c77cc0d"}, - {file = "cbor2-5.5.1.tar.gz", hash = "sha256:f9e192f461a9f8f6082df28c035b006d153904213dc8640bed8a72d72bbc9475"}, + {file = "cbor2-5.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0201d5e8d9ad1557aeb50d35b907c0f170de0ae9ebb484b2894bcee3b2e13b80"}, + {file = "cbor2-5.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eda6965cca276d4c2cebdbee14572dec65b991c5359fc32a793f03f052e35985"}, + {file = "cbor2-5.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14561038b8eaab3fd5e867f09bc43f7525a1405e41ade14066925ea3d42513a8"}, + {file = "cbor2-5.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a3cf6b339a005031e4b8c79b9541856e3b0077ea4c33d7bb6a019885136f53a"}, + {file = "cbor2-5.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4b7636d39de203ee30ac13575ed3e9a0510e993fa1671022b84b9e35e369825f"}, + {file = "cbor2-5.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23847075ce1bcda871c7698e5db0635685995ae470098a5e4c9a26c00f65f21a"}, + {file = "cbor2-5.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:ca15be7142e861fb9f918e0248620b4d4153b9ff14ef6034f7204db5db2924a1"}, + {file = "cbor2-5.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b07ee755ae5b0dfad608dab37364b35895cab5d1222653da1fea32a10330c4b0"}, + {file = "cbor2-5.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9fc063843c14e9e95181faf8d807a53c958d77bb9d360eb4f2344d075ecfed36"}, + {file = "cbor2-5.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c66d4c227c2ed6c63ec5c2d50eb8ec0e1c41c07b452a867544e48ca41d4f0b64"}, + {file = "cbor2-5.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3af60ac82a733bfdfb2b1079c850fefea2621bdb8c8f87f4c5d12802d48a8c55"}, + {file = "cbor2-5.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:acb93292843aa72768f089a135bfeec4c9b745132e8dc22f1b149490fc77cb0a"}, + {file = "cbor2-5.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193d1abdffd52893710d39389daa5c03e1569421cdf53585a28033689aef7aec"}, + {file = "cbor2-5.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:d0c915db92b441f505f8a14a521c9461439ac8e5d959454845eb92f93db0bb3b"}, + {file = "cbor2-5.6.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9eaec8c04618124a6b597fe4471035cb7cb0d5114f43aaf2062821ad480ef57c"}, + {file = "cbor2-5.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d1e5181d4f858237ab4e1a28e21bdcaf31dab2657ab60a8d4a0701a078fe5926"}, + {file = "cbor2-5.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:277997127402710a3abdf4372ac75e8f8bb2e75a303cd789312e515c8ef657dd"}, + {file = "cbor2-5.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:add01e4b4663199940d10f8c8e1d926e70823d1b2f3f981cc097a4764125f110"}, + {file = "cbor2-5.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:adc87485ffd7a4dad481e08e6819eebfcfbafc0918fffcca47aee4cdf8c6de04"}, + {file = "cbor2-5.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea4a0412426155c3b78763449db56cf5c72c48788a37d7e60bd66c844b9c8634"}, + {file = "cbor2-5.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:18b3dee4eddde9761c60298ce21c0cd4e770237978034c5ee1d4242e255683ec"}, + {file = "cbor2-5.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ff6fd1c54b97ee322c0b7180092305ca3b012ff78fddadad97b33490f5f8881f"}, + {file = "cbor2-5.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ac6f10b9d25f2d61c036f86238bf23e3ea0253f98faa8ab00f67228bf3c0ce2a"}, + {file = "cbor2-5.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be74f2cbda547fdd57c83ee5b3470804f02c660db28efcf9d4016f001b66f40"}, + {file = "cbor2-5.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64ea120206f82492a4385bbc5e2639f9b67c8bc7bdc57bffcbe9a8fee8cd6342"}, + {file = "cbor2-5.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c3d2902e1aed155d56cdcae99cd4a9dae843e3fff6978148d2d5d5f9a0b986cd"}, + {file = "cbor2-5.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2d4f95a567e26d8d9d62db234cd089525c52f19e7fdd59152629d9f03bd94b4f"}, + {file = "cbor2-5.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:33efbe7103bac090430d291fca2fe1c444b0ec55c4716e8051b72a81377e8b79"}, + {file = "cbor2-5.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:81e619a2a59ae966cedb5fd3ea8a9487a3d4430824bbeacdcf5f74ad6112cc57"}, + {file = "cbor2-5.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b7755b93d32638f4d79a0fa0744b423787f6faa3c96ccccac68b6dbf1848368"}, + {file = "cbor2-5.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f0e95011ae8460265ef348fe380664fa22c51015fd52344ebd781579fa9552a"}, + {file = "cbor2-5.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7693e53c3ba0b2ad4e46b610f8d69159ffdbcb6ebe75ea1c1f5f40c3283639ca"}, + {file = "cbor2-5.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e3ec251db32516d383fc587874b15f4b5fb4e9049d9436b8696f5767b11c149b"}, + {file = "cbor2-5.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6081c1ab9791d5973a40b95ecb8b04b0fbf9fc04be170d89a3ad77d5964f52d5"}, + {file = "cbor2-5.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:2aba8b75e36c9f84a42a7026271da8fd759035a871c1b799028439059527276b"}, + {file = "cbor2-5.6.3-py3-none-any.whl", hash = "sha256:8a4b7404af6da719092a4ee5953d1930d095b93b684bf99e1ab74512be1910a4"}, + {file = "cbor2-5.6.3.tar.gz", hash = "sha256:e6f0ae2751c2d333a960e0807c0611494eb1245631a167965acbc100509455d3"}, ] [package.extras] @@ -557,13 +583,13 @@ test = ["coverage (>=7)", "hypothesis", "pytest"] [[package]] name = "celery" -version = "5.3.6" +version = "5.4.0" description = "Distributed Task Queue." optional = false python-versions = ">=3.8" files = [ - {file = "celery-5.3.6-py3-none-any.whl", hash = "sha256:9da4ea0118d232ce97dff5ed4974587fb1c0ff5c10042eb15278487cdd27d1af"}, - {file = "celery-5.3.6.tar.gz", hash = "sha256:870cc71d737c0200c397290d730344cc991d13a057534353d124c9380267aab9"}, + {file = "celery-5.4.0-py3-none-any.whl", hash = "sha256:369631eb580cf8c51a82721ec538684994f8277637edde2dfc0dacd73ed97f64"}, + {file = "celery-5.4.0.tar.gz", hash = "sha256:504a19140e8d3029d5acad88330c541d4c3f64c789d85f94756762d8bca7e706"}, ] [package.dependencies] @@ -579,7 +605,7 @@ vine = ">=5.1.0,<6.0" [package.extras] arangodb = ["pyArango (>=2.0.2)"] -auth = ["cryptography (==41.0.5)"] +auth = ["cryptography (==42.0.5)"] azureblockblob = ["azure-storage-blob (>=12.15.0)"] brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] cassandra = ["cassandra-driver (>=3.25.0,<4)"] @@ -589,22 +615,23 @@ couchbase = ["couchbase (>=3.0.0)"] couchdb = ["pycouchdb (==1.14.2)"] django = ["Django (>=2.2.28)"] dynamodb = ["boto3 (>=1.26.143)"] -elasticsearch = ["elastic-transport (<=8.10.0)", "elasticsearch (<=8.11.0)"] +elasticsearch = ["elastic-transport (<=8.13.0)", "elasticsearch (<=8.13.0)"] eventlet = ["eventlet (>=0.32.0)"] +gcs = ["google-cloud-storage (>=2.10.0)"] gevent = ["gevent (>=1.5.0)"] librabbitmq = ["librabbitmq (>=2.0.0)"] memcache = ["pylibmc (==1.6.3)"] mongodb = ["pymongo[srv] (>=4.0.2)"] -msgpack = ["msgpack (==1.0.7)"] -pymemcache = ["python-memcached (==1.59)"] +msgpack = ["msgpack (==1.0.8)"] +pymemcache = ["python-memcached (>=1.61)"] pyro = ["pyro4 (==4.82)"] -pytest = ["pytest-celery (==0.0.0)"] +pytest = ["pytest-celery[all] (>=1.0.0)"] redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"] s3 = ["boto3 (>=1.26.143)"] slmq = ["softlayer-messaging (>=1.0.3)"] solar = ["ephem (==4.1.5)"] sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] -sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.0)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] +sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.4)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] yaml = ["PyYAML (>=3.10)"] zookeeper = ["kazoo (>=1.3.1)"] @@ -612,13 +639,13 @@ zstd = ["zstandard (==0.22.0)"] [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -687,19 +714,19 @@ pycparser = "*" [[package]] name = "channels" -version = "4.0.0" +version = "4.1.0" description = "Brings async, event-driven capabilities to Django 3.2 and up." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "channels-4.0.0-py3-none-any.whl", hash = "sha256:2253334ac76f67cba68c2072273f7e0e67dbdac77eeb7e318f511d2f9a53c5e4"}, - {file = "channels-4.0.0.tar.gz", hash = "sha256:0ce53507a7da7b148eaa454526e0e05f7da5e5d1c23440e4886cf146981d8420"}, + {file = "channels-4.1.0-py3-none-any.whl", hash = "sha256:a3c4419307f582c3f71d67bfb6eff748ae819c2f360b9b141694d84f242baa48"}, + {file = "channels-4.1.0.tar.gz", hash = "sha256:e0ed375719f5c1851861f05ed4ce78b0166f9245ca0ecd836cb77d4bb531489d"}, ] [package.dependencies] -asgiref = ">=3.5.0,<4" +asgiref = ">=3.6.0,<4" daphne = {version = ">=4.0.0", optional = true, markers = "extra == \"daphne\""} -Django = ">=3.2" +Django = ">=4.2" [package.extras] daphne = ["daphne (>=4.0.0)"] @@ -841,13 +868,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "click-didyoumean" -version = "0.3.0" +version = "0.3.1" description = "Enables git-like *did-you-mean* feature in click" optional = false -python-versions = ">=3.6.2,<4.0.0" +python-versions = ">=3.6.2" files = [ - {file = "click-didyoumean-0.3.0.tar.gz", hash = "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"}, - {file = "click_didyoumean-0.3.0-py3-none-any.whl", hash = "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667"}, + {file = "click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c"}, + {file = "click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463"}, ] [package.dependencies] @@ -890,13 +917,13 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] [[package]] name = "codespell" -version = "2.2.6" +version = "2.3.0" description = "Codespell" optional = false python-versions = ">=3.8" files = [ - {file = "codespell-2.2.6-py3-none-any.whl", hash = "sha256:9ee9a3e5df0990604013ac2a9f22fa8e57669c827124a2e961fe8a1da4cacc07"}, - {file = "codespell-2.2.6.tar.gz", hash = "sha256:a8c65d8eb3faa03deabab6b3bbe798bea72e1799c7e9e955d57eca4096abcff9"}, + {file = "codespell-2.3.0-py3-none-any.whl", hash = "sha256:a9c7cef2501c9cfede2110fd6d4e5e62296920efe9abfb84648df866e47f58d1"}, + {file = "codespell-2.3.0.tar.gz", hash = "sha256:360c7d10f75e65f67bad720af7007e1060a5d395670ec11a7ed1fed9dd17471f"}, ] [package.extras] @@ -929,63 +956,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.0" +version = "7.5.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, - {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, - {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, - {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, - {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, - {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, - {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, - {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, - {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, - {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, - {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, - {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, - {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, - {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, + {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, + {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, + {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, + {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, + {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, + {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, + {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, + {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, + {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, + {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, + {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, + {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, ] [package.extras] @@ -993,47 +1020,56 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.7" +version = "42.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, - {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, - {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, - {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, - {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, - {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, - {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, + {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, + {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, + {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, + {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, + {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, + {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, ] [package.dependencies] -cffi = ">=1.12" +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1051,13 +1087,13 @@ dev = ["black", "coveralls", "mypy", "pre-commit", "pylint", "pytest (>=5)", "py [[package]] name = "daphne" -version = "4.0.0" +version = "4.1.2" description = "Django ASGI (HTTP/WebSocket) server" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "daphne-4.0.0-py3-none-any.whl", hash = "sha256:a288ece46012b6b719c37150be67c69ebfca0793a8521bf821533bad983179b2"}, - {file = "daphne-4.0.0.tar.gz", hash = "sha256:cce9afc8f49a4f15d4270b8cfb0e0fe811b770a5cc795474e97e4da287497666"}, + {file = "daphne-4.1.2-py3-none-any.whl", hash = "sha256:618d1322bb4d875342b99dd2a10da2d9aae7ee3645f765965fdc1e658ea5290a"}, + {file = "daphne-4.1.2.tar.gz", hash = "sha256:fcbcace38eb86624ae247c7ffdc8ac12f155d7d19eafac4247381896d6f33761"}, ] [package.dependencies] @@ -1070,29 +1106,33 @@ tests = ["django", "hypothesis", "pytest", "pytest-asyncio"] [[package]] name = "debugpy" -version = "1.8.0" +version = "1.8.1" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, - {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, - {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, - {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, - {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, - {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, - {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, - {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, - {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, - {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, - {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, - {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, - {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, - {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, - {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, - {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, - {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, - {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, ] [[package]] @@ -1118,28 +1158,31 @@ files = [ ] [[package]] -name = "dill" -version = "0.3.7" -description = "serialize all of Python" +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, - {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, ] +[package.dependencies] +wrapt = ">=1.10,<2" + [package.extras] -graph = ["objgraph (>=1.7.2)"] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] name = "django" -version = "5.0.1" +version = "5.0.6" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." optional = false python-versions = ">=3.10" files = [ - {file = "Django-5.0.1-py3-none-any.whl", hash = "sha256:f47a37a90b9bbe2c8ec360235192c7fddfdc832206fcf618bb849b39256affc1"}, - {file = "Django-5.0.1.tar.gz", hash = "sha256:8c8659665bc6e3a44fefe1ab0a291e5a3fb3979f9a8230be29de975e57e8f854"}, + {file = "Django-5.0.6-py3-none-any.whl", hash = "sha256:8363ac062bb4ef7c3f12d078f6fa5d154031d129a15170a1066412af49d30905"}, + {file = "Django-5.0.6.tar.gz", hash = "sha256:ff1b61005004e476e0aeea47c7f79b85864c70124030e95146315396f1e7951f"}, ] [package.dependencies] @@ -1153,17 +1196,17 @@ bcrypt = ["bcrypt"] [[package]] name = "django-filter" -version = "23.5" +version = "24.2" description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django-filter-23.5.tar.gz", hash = "sha256:67583aa43b91fe8c49f74a832d95f4d8442be628fd4c6d65e9f811f5153a4e5c"}, - {file = "django_filter-23.5-py3-none-any.whl", hash = "sha256:99122a201d83860aef4fe77758b69dda913e874cc5e0eaa50a86b0b18d708400"}, + {file = "django-filter-24.2.tar.gz", hash = "sha256:48e5fc1da3ccd6ca0d5f9bb550973518ce977a4edde9d2a8a154a7f4f0b9f96e"}, + {file = "django_filter-24.2-py3-none-any.whl", hash = "sha256:df2ee9857e18d38bed203c8745f62a803fa0f31688c9fe6f8e868120b1848e48"}, ] [package.dependencies] -Django = ">=3.2" +Django = ">=4.2" [[package]] name = "django-guardian" @@ -1181,18 +1224,47 @@ Django = ">=2.2" [[package]] name = "django-model-utils" -version = "4.3.1" +version = "4.5.1" description = "Django model mixins and utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django-model-utils-4.3.1.tar.gz", hash = "sha256:2e2e4f13e4f14613134a9777db7ad4265f59a1d8f1384107bcaa3028fe3c87c1"}, - {file = "django_model_utils-4.3.1-py3-none-any.whl", hash = "sha256:8c0b0177bab909a8635b602d960daa67e80607aa5469217857271a60726d7a4b"}, + {file = "django_model_utils-4.5.1-py3-none-any.whl", hash = "sha256:f1141fc71796242edeffed5ad53a8cc57f00d345eb5a3a63e3f69401cd562ee2"}, + {file = "django_model_utils-4.5.1.tar.gz", hash = "sha256:1220f22d9a467d53a1e0f4cda4857df0b2f757edf9a29955c42461988caa648a"}, ] [package.dependencies] Django = ">=3.2" +[[package]] +name = "django-pgactivity" +version = "1.4.1" +description = "Monitor, kill, and analyze Postgres queries." +optional = false +python-versions = "<4,>=3.8.0" +files = [ + {file = "django_pgactivity-1.4.1-py3-none-any.whl", hash = "sha256:e7affa4dc08e7650092a582375729081362a3103f1148e34e8406ddf114eeb95"}, + {file = "django_pgactivity-1.4.1.tar.gz", hash = "sha256:00da0f0156daa37f5f113c7a6d9378a6f6d111e44f20d3b30b367d5428e18b07"}, +] + +[package.dependencies] +django = ">=3" + +[[package]] +name = "django-pglock" +version = "1.5.1" +description = "Postgres locking routines and lock table access." +optional = false +python-versions = "<4,>=3.8.0" +files = [ + {file = "django_pglock-1.5.1-py3-none-any.whl", hash = "sha256:d3b977922abbaffd43968714b69cdab7453866adf2b0695fb497491748d7bc67"}, + {file = "django_pglock-1.5.1.tar.gz", hash = "sha256:291903d5d877b68558003e1d64d764ebd5590344ba3b7aa1d5127df5947869b1"}, +] + +[package.dependencies] +django = ">=3" +django-pgactivity = ">=1.2,<2" + [[package]] name = "django-prometheus" version = "2.3.1" @@ -1227,13 +1299,13 @@ hiredis = ["redis[hiredis] (>=3,!=4.0.0,!=4.0.1)"] [[package]] name = "django-storages" -version = "1.14.2" +version = "1.14.3" description = "Support for many storage backends in Django" optional = false python-versions = ">=3.7" files = [ - {file = "django-storages-1.14.2.tar.gz", hash = "sha256:51b36af28cc5813b98d5f3dfe7459af638d84428c8df4a03990c7d74d1bea4e5"}, - {file = "django_storages-1.14.2-py3-none-any.whl", hash = "sha256:1db759346b52ada6c2efd9f23d8241ecf518813eb31db9e2589207174f58f6ad"}, + {file = "django-storages-1.14.3.tar.gz", hash = "sha256:95a12836cd998d4c7a4512347322331c662d9114c4344f932f5e9c0fce000608"}, + {file = "django_storages-1.14.3-py3-none-any.whl", hash = "sha256:31f263389e95ce3a1b902fb5f739a7ed32895f7d8b80179fe7453ecc0dfe102e"}, ] [package.dependencies] @@ -1300,41 +1372,43 @@ djangorestframework = "*" [[package]] name = "dnspython" -version = "2.4.2" +version = "2.6.1" description = "DNS toolkit" optional = false -python-versions = ">=3.8,<4.0" +python-versions = ">=3.8" files = [ - {file = "dnspython-2.4.2-py3-none-any.whl", hash = "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8"}, - {file = "dnspython-2.4.2.tar.gz", hash = "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984"}, + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, ] [package.extras] -dnssec = ["cryptography (>=2.6,<42.0)"] -doh = ["h2 (>=4.1.0)", "httpcore (>=0.17.3)", "httpx (>=0.24.1)"] -doq = ["aioquic (>=0.9.20)"] -idna = ["idna (>=2.1,<4.0)"] -trio = ["trio (>=0.14,<0.23)"] -wmi = ["wmi (>=1.5.1,<2.0.0)"] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] [[package]] name = "docker" -version = "7.0.0" +version = "7.1.0" description = "A Python library for the Docker Engine API." optional = false python-versions = ">=3.8" files = [ - {file = "docker-7.0.0-py3-none-any.whl", hash = "sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b"}, - {file = "docker-7.0.0.tar.gz", hash = "sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3"}, + {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, + {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, ] [package.dependencies] -packaging = ">=14.0" pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} requests = ">=2.26.0" urllib3 = ">=1.26.0" [package.extras] +dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"] +docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] ssh = ["paramiko (>=2.4.3)"] websockets = ["websocket-client (>=1.3.0)"] @@ -1363,13 +1437,13 @@ tests = ["black", "django-stubs[compatible-mypy]", "djangorestframework-stubs[co [[package]] name = "drf-spectacular" -version = "0.27.1" +version = "0.27.2" description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "drf-spectacular-0.27.1.tar.gz", hash = "sha256:452e0cff3c12ee057b897508a077562967b9e62717992eeec10e62dbbc7b5a33"}, - {file = "drf_spectacular-0.27.1-py3-none-any.whl", hash = "sha256:0a4cada4b7136a0bf17233476c066c511a048bc6a485ae2140326ac7ba4003b2"}, + {file = "drf-spectacular-0.27.2.tar.gz", hash = "sha256:a199492f2163c4101055075ebdbb037d59c6e0030692fc83a1a8c0fc65929981"}, + {file = "drf_spectacular-0.27.2-py3-none-any.whl", hash = "sha256:b1c04bf8b2fbbeaf6f59414b4ea448c8787aba4d32f76055c3b13335cf7ec37b"}, ] [package.dependencies] @@ -1400,13 +1474,13 @@ files = [ [[package]] name = "duo-client" -version = "5.2.0" +version = "5.3.0" description = "Reference client for Duo Security APIs" optional = false python-versions = "*" files = [ - {file = "duo_client-5.2.0-py3-none-any.whl", hash = "sha256:da3237e34300665c40ba5215f1e6656fec1a0136295917541aa973e7fcbf027e"}, - {file = "duo_client-5.2.0.tar.gz", hash = "sha256:f82361740792b06303f9721e7ba593916080461769396b4f73c0502c0bfcee44"}, + {file = "duo_client-5.3.0-py3-none-any.whl", hash = "sha256:85614bb684cef96285268aef0c1e858df939f6e8a190fb2c707d700bb0215766"}, + {file = "duo_client-5.3.0.tar.gz", hash = "sha256:afa5ef98a42f06965a2702ca41dba9c85c483abd945e0a440f0ec4871b7593bf"}, ] [package.dependencies] @@ -1415,13 +1489,13 @@ six = "*" [[package]] name = "email-validator" -version = "2.1.0.post1" +version = "2.1.1" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" files = [ - {file = "email_validator-2.1.0.post1-py3-none-any.whl", hash = "sha256:c973053efbeddfef924dc0bd93f6e77a1ea7ee0fce935aea7103c7a3d6d2d637"}, - {file = "email_validator-2.1.0.post1.tar.gz", hash = "sha256:a4b0bd1cf55f073b924258d19321b1f3aa74b4b5a71a42c305575dba920e1a44"}, + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, ] [package.dependencies] @@ -1442,6 +1516,23 @@ files = [ [package.dependencies] requests = "*" +[[package]] +name = "fido2" +version = "1.1.3" +description = "FIDO2/WebAuthn library for implementing clients and servers." +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "fido2-1.1.3-py3-none-any.whl", hash = "sha256:6be34c0b9fe85e4911fd2d103cce7ae8ce2f064384a7a2a3bd970b3ef7702931"}, + {file = "fido2-1.1.3.tar.gz", hash = "sha256:26100f226d12ced621ca6198528ce17edf67b78df4287aee1285fee3cd5aa9fc"}, +] + +[package.dependencies] +cryptography = ">=2.6,<35 || >35,<45" + +[package.extras] +pcsc = ["pyscard (>=1.9,<3)"] + [[package]] name = "flower" version = "2.0.1" @@ -1462,13 +1553,13 @@ tornado = ">=5.0.0,<7.0.0" [[package]] name = "freezegun" -version = "1.4.0" +version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" files = [ - {file = "freezegun-1.4.0-py3-none-any.whl", hash = "sha256:55e0fc3c84ebf0a96a5aa23ff8b53d70246479e9a68863f1fcac5a3e52f19dd6"}, - {file = "freezegun-1.4.0.tar.gz", hash = "sha256:10939b0ba0ff5adaecf3b06a5c2f73071d9678e507c5eaedb23c761d56ac774b"}, + {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, + {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, ] [package.dependencies] @@ -1580,15 +1671,56 @@ setuptools = ">=60.0.0" [package.extras] test = ["mocket (>=3.11.1)"] +[[package]] +name = "google-api-core" +version = "2.19.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"}, + {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-api-python-client" +version = "2.130.0" +description = "Google API Client Library for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-api-python-client-2.130.0.tar.gz", hash = "sha256:2bba3122b82a649c677b8a694b8e2bbf2a5fbf3420265caf3343bb88e2e9f0ae"}, + {file = "google_api_python_client-2.130.0-py2.py3-none-any.whl", hash = "sha256:7d45a28d738628715944a9c9d73e8696e7e03ac50b7de87f5e3035cefa94ed3a"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.dev0" +uritemplate = ">=3.0.1,<5" + [[package]] name = "google-auth" -version = "2.26.1" +version = "2.29.0" description = "Google Authentication Library" optional = false python-versions = ">=3.7" files = [ - {file = "google-auth-2.26.1.tar.gz", hash = "sha256:54385acca5c0fbdda510cd8585ba6f3fcb06eeecf8a6ecca39d3ee148b092590"}, - {file = "google_auth-2.26.1-py2.py3-none-any.whl", hash = "sha256:2c8b55e3e564f298122a02ab7b97458ccfcc5617840beb5d0ac757ada92c9780"}, + {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, + {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, ] [package.dependencies] @@ -1603,24 +1735,57 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +optional = false +python-versions = "*" +files = [ + {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, + {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, +] + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + +[[package]] +name = "googleapis-common-protos" +version = "1.63.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, + {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, +] + +[package.dependencies] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + [[package]] name = "gunicorn" -version = "21.2.0" +version = "22.0.0" description = "WSGI HTTP Server for UNIX" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"}, - {file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"}, + {file = "gunicorn-22.0.0-py3-none-any.whl", hash = "sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9"}, + {file = "gunicorn-22.0.0.tar.gz", hash = "sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63"}, ] [package.dependencies] packaging = "*" [package.extras] -eventlet = ["eventlet (>=0.24.1)"] +eventlet = ["eventlet (>=0.24.1,!=0.36.0)"] gevent = ["gevent (>=1.4.0)"] setproctitle = ["setproctitle"] +testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"] tornado = ["tornado (>=0.2)"] [[package]] @@ -1634,6 +1799,67 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, + {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, +] + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + [[package]] name = "httptools" version = "0.6.1" @@ -1682,6 +1908,31 @@ files = [ [package.extras] test = ["Cython (>=0.29.24,<0.30.0)"] +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + [[package]] name = "humanize" version = "4.9.0" @@ -1696,6 +1947,17 @@ files = [ [package.extras] tests = ["freezegun", "pytest", "pytest-cov"] +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + [[package]] name = "hyperlink" version = "21.0.0" @@ -1712,24 +1974,24 @@ idna = ">=2.5" [[package]] name = "idna" -version = "3.6" +version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "importlib-metadata" -version = "7.0.1" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, - {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] @@ -1777,29 +2039,15 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -1846,13 +2094,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.20.0" +version = "4.22.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, - {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, ] [package.dependencies] @@ -1881,13 +2129,13 @@ referencing = ">=0.31.0" [[package]] name = "kombu" -version = "5.3.4" +version = "5.3.7" description = "Messaging library for Python." optional = false python-versions = ">=3.8" files = [ - {file = "kombu-5.3.4-py3-none-any.whl", hash = "sha256:63bb093fc9bb80cfb3a0972336a5cec1fa7ac5f9ef7e8237c6bf8dda9469313e"}, - {file = "kombu-5.3.4.tar.gz", hash = "sha256:0bb2e278644d11dea6272c17974a3dbb9688a949f3bb60aeb5b791329c44fadc"}, + {file = "kombu-5.3.7-py3-none-any.whl", hash = "sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9"}, + {file = "kombu-5.3.7.tar.gz", hash = "sha256:011c4cd9a355c14a1de8d35d257314a1d2456d52b7140388561acac3cf1a97bf"}, ] [package.dependencies] @@ -1904,7 +2152,7 @@ mongodb = ["pymongo (>=4.1.1)"] msgpack = ["msgpack"] pyro = ["pyro4"] qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"] +redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2)"] slmq = ["softlayer-messaging (>=1.0.3)"] sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] @@ -1953,307 +2201,161 @@ pyasn1 = ">=0.4.6" [[package]] name = "lxml" -version = "4.9.4" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722"}, - {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1"}, - {file = "lxml-4.9.4-cp27-cp27m-win32.whl", hash = "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013"}, - {file = "lxml-4.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69"}, - {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2"}, - {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48"}, - {file = "lxml-4.9.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91"}, - {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868"}, - {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7"}, - {file = "lxml-4.9.4-cp310-cp310-win32.whl", hash = "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be"}, - {file = "lxml-4.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5"}, - {file = "lxml-4.9.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979"}, - {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac"}, - {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622"}, - {file = "lxml-4.9.4-cp311-cp311-win32.whl", hash = "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3"}, - {file = "lxml-4.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8"}, - {file = "lxml-4.9.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8"}, - {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229"}, - {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d"}, - {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20"}, - {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10"}, - {file = "lxml-4.9.4-cp312-cp312-win32.whl", hash = "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b"}, - {file = "lxml-4.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56"}, - {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20"}, - {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66"}, - {file = "lxml-4.9.4-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85"}, - {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23"}, - {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745"}, - {file = "lxml-4.9.4-cp36-cp36m-win32.whl", hash = "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be"}, - {file = "lxml-4.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9"}, - {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d"}, - {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02"}, - {file = "lxml-4.9.4-cp37-cp37m-win32.whl", hash = "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e"}, - {file = "lxml-4.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192"}, - {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37"}, - {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9"}, - {file = "lxml-4.9.4-cp38-cp38-win32.whl", hash = "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c"}, - {file = "lxml-4.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46"}, - {file = "lxml-4.9.4-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573"}, - {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847"}, - {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab"}, - {file = "lxml-4.9.4-cp39-cp39-win32.whl", hash = "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec"}, - {file = "lxml-4.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137"}, - {file = "lxml-4.9.4.tar.gz", hash = "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (==0.29.37)"] - -[[package]] -name = "lxml" -version = "5.0.0" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-5.0.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73bfab795d354aaf2f4eb7a5b0db513031734fd371047342d5803834ce19ec18"}, - {file = "lxml-5.0.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cb564bbe55ff0897d9cf1225041a44576d7ae87f06fd60163544c91de2623d3f"}, - {file = "lxml-5.0.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6a5501438dd521bb7e0dde5008c40c7bfcfaafaf86eccb3f9bd27509abb793da"}, - {file = "lxml-5.0.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7ba26a7dc929a1b3487d51bbcb0099afed2fc06e891b82845c8f37a2d7d7fbbd"}, - {file = "lxml-5.0.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:9b59c429e1a2246da86ae237ffc3565efcdc71c281cd38ca8b44d5fb6a3b993a"}, - {file = "lxml-5.0.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:3ffa066db40b0347e48334bd4465de768e295a3525b9a59831228b5f4f93162d"}, - {file = "lxml-5.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8ce8b468ab50f9e944719d1134709ec11fe0d2840891a6cae369e22141b1094c"}, - {file = "lxml-5.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:583c0e15ae06adc81035346ae2abb2e748f0b5197e7740d8af31222db41bbf7b"}, - {file = "lxml-5.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:904d36165848b59c4e04ae5b969072e602bd987485076fca8ec42c6cd7a7aedc"}, - {file = "lxml-5.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ac21aace6712472e77ea9dfc38329f53830c4259ece54c786107105ebb069053"}, - {file = "lxml-5.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f92d73faa0b1a76d1932429d684b7ce95829e93c3eef3715ec9b98ab192c9d31"}, - {file = "lxml-5.0.0-cp310-cp310-win32.whl", hash = "sha256:03290e2f714f2e7431c8430c08b48167f657da7bc689c6248e828ff3c66d5b1b"}, - {file = "lxml-5.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e6cbb68bf70081f036bfc018649cf4b46c4e7eaf7860a277cae92dee2a57f69"}, - {file = "lxml-5.0.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5382612ba2424cea5d2c89e2c29077023d8de88f8d60d5ceff5f76334516df9e"}, - {file = "lxml-5.0.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:07a900735bad9af7be3085480bf384f68ed5580ba465b39a098e6a882c060d6b"}, - {file = "lxml-5.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:980ba47c8db4b9d870014c7040edb230825b79017a6a27aa54cdb6fcc02d8cc0"}, - {file = "lxml-5.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6507c58431dbd95b50654b3313c5ad54f90e54e5f2cdacf733de61eae478eec5"}, - {file = "lxml-5.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:4a45a278518e4308865c1e9dbb2c42ce84fb154efb03adeb16fdae3c1687c7c9"}, - {file = "lxml-5.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:59cea9ba1c675fbd6867ca1078fc717a113e7f5b7644943b74137b7cc55abebf"}, - {file = "lxml-5.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dd39ef87fd1f7bb5c4aa53454936e6135cbfe03fe3744e8218be193f9e4fef16"}, - {file = "lxml-5.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e6bb39d91bf932e7520cb5718ae3c2f498052aca53294d5d59fdd9068fe1a7f2"}, - {file = "lxml-5.0.0-cp311-cp311-win32.whl", hash = "sha256:21af2c3862db6f4f486cddf73ec1157b40d5828876c47cd880edcbad8240ea1b"}, - {file = "lxml-5.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:c1249aa4eaced30b59ecf8b8cae0b1ccede04583c74ca7d10b6f8bbead908b2c"}, - {file = "lxml-5.0.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f30e697b6215e759d0824768b2c5b0618d2dc19abe6c67eeed2b0460f52470d1"}, - {file = "lxml-5.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d1bb64646480c36a4aa1b6a44a5b6e33d0fcbeab9f53f1b39072cd3bb2c6243a"}, - {file = "lxml-5.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4e69c36c8618707a90ed3fb6f48a6cc9254ffcdbf7b259e439a5ae5fbf9c5206"}, - {file = "lxml-5.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9ca498f8554a09fbc3a2f8fc4b23261e07bc27bef99b3df98e2570688033f6fc"}, - {file = "lxml-5.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0326e9b8176ea77269fb39e7af4010906e73e9496a9f8eaf06d253b1b1231ceb"}, - {file = "lxml-5.0.0-cp312-cp312-win32.whl", hash = "sha256:5fb988e15378d6e905ca8f60813950a0c56da9469d0e8e5d8fe785b282684ec5"}, - {file = "lxml-5.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:bb58e8f4b2cfe012cd312239b8d5139995fe8f5945c7c26d5fbbbb1ddb9acd47"}, - {file = "lxml-5.0.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:81509dffd8aba3bdb43e90cbd218c9c068a1f4047d97bc9546b3ac9e3a4ae81d"}, - {file = "lxml-5.0.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e675a4b95208e74c34ac0751cc4bab9170e7728b61601fb0f4746892c2bb7e0b"}, - {file = "lxml-5.0.0-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:405e3760f83a8ba3bdb6e622ec79595cdc20db916ce37377bbcb95b5711fa4ca"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f15844a1b93dcaa09c2b22e22a73384f3ae4502347c3881cfdd674e14ac04e21"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88f559f8beb6b90e41a7faae4aca4c8173a4819874a9bf8e74c8d7c1d51f3162"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e8c63f5c7d87e7044880b01851ac4e863c3349e6f6b6ab456fe218d9346e816d"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:0d277d4717756fe8816f0beeff229cb72f9dd02a43b70e1d3f07c8efadfb9fe1"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8954da15403db1acfc0544b3c3f963a6ef4e428283ab6555e3e298bbbff1cf6"}, - {file = "lxml-5.0.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:aebd8fd378e074b22e79cad329dcccd243c40ff1cafaa512d19276c5bb9554e1"}, - {file = "lxml-5.0.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b6d4e148edee59c2ad38af15810dbcb8b5d7b13e5de3509d8cf3edfe74c0adca"}, - {file = "lxml-5.0.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:70ab4e02f7aa5fb4131c8b222a111ce7676f3767e36084fba3a4e7338dc82dcd"}, - {file = "lxml-5.0.0-cp36-cp36m-win32.whl", hash = "sha256:de1a8b54170024cf1c0c2718c82412bca42cd82e390556e3d8031af9541b416f"}, - {file = "lxml-5.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5b39f63edbe7e018c2ac1cf0259ee0dd2355274e8a3003d404699b040782e55e"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:77b73952534967a4497d9e4f26fbeebfba19950cbc66b7cc3a706214429d8106"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8cc0a951e5616ac626f7036309c41fb9774adcd4aa7db0886463da1ce5b65edb"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:4b9d5b01900a760eb3acf6cef50aead4ef2fa79e7ddb927084244e41dfe37b65"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:173bcead3af5d87c7bca9a030675073ddaad8e0a9f0b04be07cd9390453e7226"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:44fa9afd632210f1eeda51cf284ed8dbab0c7ec8b008dd39ba02818e0e114e69"}, - {file = "lxml-5.0.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fef10f27d6318d2d7c88680e113511ddecf09ee4f9559b3623b73ee89fa8f6cc"}, - {file = "lxml-5.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3663542aee845129a981889c19b366beab0b1dadcf5ca164696aabfe1aa51667"}, - {file = "lxml-5.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7188495c1bf71bfda87d78ed50601e72d252119ce11710d6e71ff36e35fea5a0"}, - {file = "lxml-5.0.0-cp37-cp37m-win32.whl", hash = "sha256:6a2de85deabf939b0af89e2e1ea46bfb1239545e2da6f8ac96522755a388025f"}, - {file = "lxml-5.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ea56825c1e23c9c8ea385a191dac75f9160477057285b88c88736d9305e6118f"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:3f908afd0477cace17f941d1b9cfa10b769fe1464770abe4cfb3d9f35378d0f8"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52a9ab31853d3808e7cf0183b3a5f7e8ffd622ea4aee1deb5252dbeaefd5b40d"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c7fe19abb3d3c55a9e65d289b12ad73b3a31a3f0bda3c539a890329ae9973bd6"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:1ef0793e1e2dd221fce7c142177008725680f7b9e4a184ab108d90d5d3ab69b7"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:581a78f299a9f5448b2c3aea904bfcd17c59bf83016d221d7f93f83633bb2ab2"}, - {file = "lxml-5.0.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:affdd833f82334fdb10fc9a1c7b35cdb5a86d0b672b4e14dd542e1fe7bcea894"}, - {file = "lxml-5.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6bba06d8982be0f0f6432d289a8d104417a0ab9ed04114446c4ceb6d4a40c65d"}, - {file = "lxml-5.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:80209b31dd3908bc5b014f540fd192c97ea52ab179713a730456c5baf7ce80c1"}, - {file = "lxml-5.0.0-cp38-cp38-win32.whl", hash = "sha256:dac2733fe4e159b0aae0439db6813b7b1d23ff96d0b34c0107b87faf79208c4e"}, - {file = "lxml-5.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:ee60f33456ff34b2dd1d048a740a2572798356208e4c494301c931de3a0ab3a2"}, - {file = "lxml-5.0.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:5eff173f0ff408bfa578cbdafd35a7e0ca94d1a9ffe09a8a48e0572d0904d486"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:78d6d8e5b54ed89dc0f0901eaaa579c384ad8d59fa43cc7fb06e9bb89115f8f4"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:71a7cee869578bc17b18050532bb2f0bc682a7b97dda77041741a1bd2febe6c7"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7df433d08d4587dc3932f7fcfc3194519a6824824104854e76441fd3bc000d29"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:793be9b4945c2dfd69828fb5948d7d9569b78e0599e4a2e88d92affeb0ff3aa3"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7cfb6af73602c8d288581df8a225989d7e9d5aab0a174be0e19fcfa800b6797"}, - {file = "lxml-5.0.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bfdc4668ac56687a89ca3eca44231144a2e9d02ba3b877558db74ba20e2bd9fa"}, - {file = "lxml-5.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2992591e2294bb07faf7f5f6d5cb60710c046404f4bfce09fb488b85d2a8f58f"}, - {file = "lxml-5.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4786b0af7511ea614fd86407a52a7bc161aa5772d311d97df2591ed2351de768"}, - {file = "lxml-5.0.0-cp39-cp39-win32.whl", hash = "sha256:016de3b29a262655fc3d2075dc1b2611f84f4c3d97a71d579c883d45e201eee4"}, - {file = "lxml-5.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:52c0acc2f29b0a204efc11a5ed911a74f50a25eb7d7d5069c2b1fd3b3346ce11"}, - {file = "lxml-5.0.0-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:96095bfc0c02072fc89afa67626013a253596ea5118b8a7f4daaae049dafa096"}, - {file = "lxml-5.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:992029258ed719f130d5a9c443d142c32843046f1263f2c492862b2a853be570"}, - {file = "lxml-5.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:db40e85cffd22f7d65dcce30e85af565a66401a6ed22fc0c56ed342cfa4ffc43"}, - {file = "lxml-5.0.0-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:cfa8a4cdc3765574b7fd0c7cfa5fbd1e2108014c9dfd299c679e5152bea9a55e"}, - {file = "lxml-5.0.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:049fef98d02513c34f5babd07569fc1cf1ed14c0f2fbff18fe72597f977ef3c2"}, - {file = "lxml-5.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a85136d0ee18a41c91cc3e2844c683be0e72e6dda4cb58da9e15fcaef3726af7"}, - {file = "lxml-5.0.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:766868f729f3ab84125350f1a0ea2594d8b1628a608a574542a5aff7355b9941"}, - {file = "lxml-5.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:99cad5c912f359e59e921689c04e54662cdd80835d80eeaa931e22612f515df7"}, - {file = "lxml-5.0.0-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:c90c593aa8dd57d5dab0ef6d7d64af894008971d98e6a41b320fdd75258fbc6e"}, - {file = "lxml-5.0.0-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8134d5441d1ed6a682e3de3d7a98717a328dce619ee9c4c8b3b91f0cb0eb3e28"}, - {file = "lxml-5.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f298ac9149037d6a3d5c74991bded39ac46292520b9c7c182cb102486cc87677"}, - {file = "lxml-5.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:894c5f71186b410679aaab5774543fcb9cbabe8893f0b31d11cf28a0740e80be"}, - {file = "lxml-5.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:9cd3d6c2c67d4fdcd795e4945e2ba5434909c96640b4cc09453bd0dc7e8e1bac"}, - {file = "lxml-5.0.0.zip", hash = "sha256:2219cbf790e701acf9a21a31ead75f983e73daf0eceb9da6990212e4d20ebefe"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=3.0.7)"] - -[[package]] -name = "lxml" -version = "5.1.0" +version = "5.2.2" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" files = [ - {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:704f5572ff473a5f897745abebc6df40f22d4133c1e0a1f124e4f2bd3330ff7e"}, - {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d3c0f8567ffe7502d969c2c1b809892dc793b5d0665f602aad19895f8d508da"}, - {file = "lxml-5.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5fcfbebdb0c5d8d18b84118842f31965d59ee3e66996ac842e21f957eb76138c"}, - {file = "lxml-5.1.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f37c6d7106a9d6f0708d4e164b707037b7380fcd0b04c5bd9cae1fb46a856fb"}, - {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2befa20a13f1a75c751f47e00929fb3433d67eb9923c2c0b364de449121f447c"}, - {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22b7ee4c35f374e2c20337a95502057964d7e35b996b1c667b5c65c567d2252a"}, - {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf8443781533b8d37b295016a4b53c1494fa9a03573c09ca5104550c138d5c05"}, - {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82bddf0e72cb2af3cbba7cec1d2fd11fda0de6be8f4492223d4a268713ef2147"}, - {file = "lxml-5.1.0-cp310-cp310-win32.whl", hash = "sha256:b66aa6357b265670bb574f050ffceefb98549c721cf28351b748be1ef9577d93"}, - {file = "lxml-5.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:4946e7f59b7b6a9e27bef34422f645e9a368cb2be11bf1ef3cafc39a1f6ba68d"}, - {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:14deca1460b4b0f6b01f1ddc9557704e8b365f55c63070463f6c18619ebf964f"}, - {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed8c3d2cd329bf779b7ed38db176738f3f8be637bb395ce9629fc76f78afe3d4"}, - {file = "lxml-5.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:436a943c2900bb98123b06437cdd30580a61340fbdb7b28aaf345a459c19046a"}, - {file = "lxml-5.1.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acb6b2f96f60f70e7f34efe0c3ea34ca63f19ca63ce90019c6cbca6b676e81fa"}, - {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af8920ce4a55ff41167ddbc20077f5698c2e710ad3353d32a07d3264f3a2021e"}, - {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cfced4a069003d8913408e10ca8ed092c49a7f6cefee9bb74b6b3e860683b45"}, - {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9e5ac3437746189a9b4121db2a7b86056ac8786b12e88838696899328fc44bb2"}, - {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4c9bda132ad108b387c33fabfea47866af87f4ea6ffb79418004f0521e63204"}, - {file = "lxml-5.1.0-cp311-cp311-win32.whl", hash = "sha256:bc64d1b1dab08f679fb89c368f4c05693f58a9faf744c4d390d7ed1d8223869b"}, - {file = "lxml-5.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5ab722ae5a873d8dcee1f5f45ddd93c34210aed44ff2dc643b5025981908cda"}, - {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9aa543980ab1fbf1720969af1d99095a548ea42e00361e727c58a40832439114"}, - {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6f11b77ec0979f7e4dc5ae081325a2946f1fe424148d3945f943ceaede98adb8"}, - {file = "lxml-5.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a36c506e5f8aeb40680491d39ed94670487ce6614b9d27cabe45d94cd5d63e1e"}, - {file = "lxml-5.1.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f643ffd2669ffd4b5a3e9b41c909b72b2a1d5e4915da90a77e119b8d48ce867a"}, - {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16dd953fb719f0ffc5bc067428fc9e88f599e15723a85618c45847c96f11f431"}, - {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16018f7099245157564d7148165132c70adb272fb5a17c048ba70d9cc542a1a1"}, - {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:82cd34f1081ae4ea2ede3d52f71b7be313756e99b4b5f829f89b12da552d3aa3"}, - {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:19a1bc898ae9f06bccb7c3e1dfd73897ecbbd2c96afe9095a6026016e5ca97b8"}, - {file = "lxml-5.1.0-cp312-cp312-win32.whl", hash = "sha256:13521a321a25c641b9ea127ef478b580b5ec82aa2e9fc076c86169d161798b01"}, - {file = "lxml-5.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:1ad17c20e3666c035db502c78b86e58ff6b5991906e55bdbef94977700c72623"}, - {file = "lxml-5.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:24ef5a4631c0b6cceaf2dbca21687e29725b7c4e171f33a8f8ce23c12558ded1"}, - {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d2900b7f5318bc7ad8631d3d40190b95ef2aa8cc59473b73b294e4a55e9f30f"}, - {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:601f4a75797d7a770daed8b42b97cd1bb1ba18bd51a9382077a6a247a12aa38d"}, - {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4b68c961b5cc402cbd99cca5eb2547e46ce77260eb705f4d117fd9c3f932b95"}, - {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:afd825e30f8d1f521713a5669b63657bcfe5980a916c95855060048b88e1adb7"}, - {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:262bc5f512a66b527d026518507e78c2f9c2bd9eb5c8aeeb9f0eb43fcb69dc67"}, - {file = "lxml-5.1.0-cp36-cp36m-win32.whl", hash = "sha256:e856c1c7255c739434489ec9c8aa9cdf5179785d10ff20add308b5d673bed5cd"}, - {file = "lxml-5.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c7257171bb8d4432fe9d6fdde4d55fdbe663a63636a17f7f9aaba9bcb3153ad7"}, - {file = "lxml-5.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b9e240ae0ba96477682aa87899d94ddec1cc7926f9df29b1dd57b39e797d5ab5"}, - {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a96f02ba1bcd330807fc060ed91d1f7a20853da6dd449e5da4b09bfcc08fdcf5"}, - {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3898ae2b58eeafedfe99e542a17859017d72d7f6a63de0f04f99c2cb125936"}, - {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61c5a7edbd7c695e54fca029ceb351fc45cd8860119a0f83e48be44e1c464862"}, - {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3aeca824b38ca78d9ee2ab82bd9883083d0492d9d17df065ba3b94e88e4d7ee6"}, - {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8f52fe6859b9db71ee609b0c0a70fea5f1e71c3462ecf144ca800d3f434f0764"}, - {file = "lxml-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:d42e3a3fc18acc88b838efded0e6ec3edf3e328a58c68fbd36a7263a874906c8"}, - {file = "lxml-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:eac68f96539b32fce2c9b47eb7c25bb2582bdaf1bbb360d25f564ee9e04c542b"}, - {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ae15347a88cf8af0949a9872b57a320d2605ae069bcdf047677318bc0bba45b1"}, - {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c26aab6ea9c54d3bed716b8851c8bfc40cb249b8e9880e250d1eddde9f709bf5"}, - {file = "lxml-5.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:342e95bddec3a698ac24378d61996b3ee5ba9acfeb253986002ac53c9a5f6f84"}, - {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:725e171e0b99a66ec8605ac77fa12239dbe061482ac854d25720e2294652eeaa"}, - {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d184e0d5c918cff04cdde9dbdf9600e960161d773666958c9d7b565ccc60c45"}, - {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:98f3f020a2b736566c707c8e034945c02aa94e124c24f77ca097c446f81b01f1"}, - {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d48fc57e7c1e3df57be5ae8614bab6d4e7b60f65c5457915c26892c41afc59e"}, - {file = "lxml-5.1.0-cp38-cp38-win32.whl", hash = "sha256:7ec465e6549ed97e9f1e5ed51c657c9ede767bc1c11552f7f4d022c4df4a977a"}, - {file = "lxml-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:b21b4031b53d25b0858d4e124f2f9131ffc1530431c6d1321805c90da78388d1"}, - {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:52427a7eadc98f9e62cb1368a5079ae826f94f05755d2d567d93ee1bc3ceb354"}, - {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a2a2c724d97c1eb8cf966b16ca2915566a4904b9aad2ed9a09c748ffe14f969"}, - {file = "lxml-5.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:843b9c835580d52828d8f69ea4302537337a21e6b4f1ec711a52241ba4a824f3"}, - {file = "lxml-5.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b99f564659cfa704a2dd82d0684207b1aadf7d02d33e54845f9fc78e06b7581"}, - {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8b0c78e7aac24979ef09b7f50da871c2de2def043d468c4b41f512d831e912"}, - {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcf86dfc8ff3e992fed847c077bd875d9e0ba2fa25d859c3a0f0f76f07f0c8d"}, - {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:49a9b4af45e8b925e1cd6f3b15bbba2c81e7dba6dce170c677c9cda547411e14"}, - {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:280f3edf15c2a967d923bcfb1f8f15337ad36f93525828b40a0f9d6c2ad24890"}, - {file = "lxml-5.1.0-cp39-cp39-win32.whl", hash = "sha256:ed7326563024b6e91fef6b6c7a1a2ff0a71b97793ac33dbbcf38f6005e51ff6e"}, - {file = "lxml-5.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8d7b4beebb178e9183138f552238f7e6613162a42164233e2bda00cb3afac58f"}, - {file = "lxml-5.1.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9bd0ae7cc2b85320abd5e0abad5ccee5564ed5f0cc90245d2f9a8ef330a8deae"}, - {file = "lxml-5.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8c1d679df4361408b628f42b26a5d62bd3e9ba7f0c0e7969f925021554755aa"}, - {file = "lxml-5.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2ad3a8ce9e8a767131061a22cd28fdffa3cd2dc193f399ff7b81777f3520e372"}, - {file = "lxml-5.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:304128394c9c22b6569eba2a6d98392b56fbdfbad58f83ea702530be80d0f9df"}, - {file = "lxml-5.1.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d74fcaf87132ffc0447b3c685a9f862ffb5b43e70ea6beec2fb8057d5d2a1fea"}, - {file = "lxml-5.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8cf5877f7ed384dabfdcc37922c3191bf27e55b498fecece9fd5c2c7aaa34c33"}, - {file = "lxml-5.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:877efb968c3d7eb2dad540b6cabf2f1d3c0fbf4b2d309a3c141f79c7e0061324"}, - {file = "lxml-5.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f14a4fb1c1c402a22e6a341a24c1341b4a3def81b41cd354386dcb795f83897"}, - {file = "lxml-5.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:25663d6e99659544ee8fe1b89b1a8c0aaa5e34b103fab124b17fa958c4a324a6"}, - {file = "lxml-5.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8b9f19df998761babaa7f09e6bc169294eefafd6149aaa272081cbddc7ba4ca3"}, - {file = "lxml-5.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e53d7e6a98b64fe54775d23a7c669763451340c3d44ad5e3a3b48a1efbdc96f"}, - {file = "lxml-5.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c3cd1fc1dc7c376c54440aeaaa0dcc803d2126732ff5c6b68ccd619f2e64be4f"}, - {file = "lxml-5.1.0.tar.gz", hash = "sha256:3eea6ed6e6c918e468e693c41ef07f3c3acc310b70ddd9cc72d9ef84bc9564ca"}, + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632"}, + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526"}, + {file = "lxml-5.2.2-cp310-cp310-win32.whl", hash = "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30"}, + {file = "lxml-5.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b"}, + {file = "lxml-5.2.2-cp311-cp311-win32.whl", hash = "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438"}, + {file = "lxml-5.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836"}, + {file = "lxml-5.2.2-cp312-cp312-win32.whl", hash = "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a"}, + {file = "lxml-5.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48"}, + {file = "lxml-5.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264"}, + {file = "lxml-5.2.2-cp36-cp36m-win32.whl", hash = "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3"}, + {file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"}, + {file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"}, + {file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"}, + {file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"}, + {file = "lxml-5.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1"}, + {file = "lxml-5.2.2-cp38-cp38-win32.whl", hash = "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30"}, + {file = "lxml-5.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9"}, + {file = "lxml-5.2.2-cp39-cp39-win32.whl", hash = "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf"}, + {file = "lxml-5.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324"}, + {file = "lxml-5.2.2.tar.gz", hash = "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml-html-clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=3.0.7)"] +source = ["Cython (>=3.0.10)"] [[package]] name = "markdown-it-py" @@ -2281,142 +2383,149 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "maxminddb" -version = "2.5.2" +version = "2.6.1" description = "Reader for the MaxMind DB format" optional = false python-versions = ">=3.8" files = [ - {file = "maxminddb-2.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f5682963a5817066db50f219c33aaa7eb969888211a289a444c42b5dfa0c0f78"}, - {file = "maxminddb-2.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fe6bb1b5ea132fcd9fd7b16c80247f0ba667018d5f9f98cd645b297e3b02fbf"}, - {file = "maxminddb-2.5.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:955a3ec4b161e872cc615b7a09ae9770049e9794e7b3832e3d78905a65c5049d"}, - {file = "maxminddb-2.5.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:29d63e7711e5f95c7c190010e57dca9e262aee8ac300aaf75c3f7ede0b5a5863"}, - {file = "maxminddb-2.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:08a540ec3661f6ca40499c86028e96dca5780e9d471b485dc797859b0b22dd22"}, - {file = "maxminddb-2.5.2-cp310-cp310-win32.whl", hash = "sha256:17fdb691c389a0e956410d5baef9ad082a0aa67dd6aa231d193499e71a104c19"}, - {file = "maxminddb-2.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:d71b48d3dff9150a44e949b28fa5e7251a7a6895a3a77e200ce08410f096f12f"}, - {file = "maxminddb-2.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1409a045eb04cebb297221eab1020c4f05434d02c0961410f6996ef474482998"}, - {file = "maxminddb-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d839c480e4b93bb37bb1cc2777d77e6b2127c006e60b56f748f10571d8b0e471"}, - {file = "maxminddb-2.5.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bca70905515fe50684974a9afaa7db4a4e9fbfdebcb0c2cde9db8e048e0d8145"}, - {file = "maxminddb-2.5.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:67f97cd0c6aac39a51294b04a1e922532125285c24b18a58e2a9c92c7691fa9f"}, - {file = "maxminddb-2.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1a3fab6bea6cc59444e6bad2a4fbf91228f6f51dcb29d09ed091930a475bd8cb"}, - {file = "maxminddb-2.5.2-cp311-cp311-win32.whl", hash = "sha256:a99e3125528ea31e807f80e8c5b65118dc5cc122d0a435f1691a3cc1df55840c"}, - {file = "maxminddb-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:b6adf63695fa5e3d2549f7c2c9d82c6d252edd5c6ba67074637d2cb944143673"}, - {file = "maxminddb-2.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ed504ca9f3c42e8e71bdbe21f5b818139a1448ac15d7bb6ce12cf41e3b7e2067"}, - {file = "maxminddb-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5053231228d7cbf57d98a741b3cbee9efa9e689348dbb56c414e5a4c7f6f1c"}, - {file = "maxminddb-2.5.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7e8688342bab592647313cd2054779bcd35ad85933424ceae9f07e3a9779986"}, - {file = "maxminddb-2.5.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:335ee3140b41d4e751c14f8fae297aa064c7d3f184c9fbb2790336123187c440"}, - {file = "maxminddb-2.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b0203fa2731da45e5461f6e8a0768e85bba8e02137a1598b3fcadf7cbfe8e6f2"}, - {file = "maxminddb-2.5.2-cp312-cp312-win32.whl", hash = "sha256:8b89129de70e1629f200df9dfda4e4f477c26b05c29e0836604a00209c9466d5"}, - {file = "maxminddb-2.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:099f4e27feec4bb9658034a3eb853e746721fc15709030bee4f2f889f4a34185"}, - {file = "maxminddb-2.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:19d8d1e9bbc5281fb4c8112d541d2bd350fd8b5ddfbb43a6951e46df7cd27b9d"}, - {file = "maxminddb-2.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94183a78628cad257183a88ce12a3bb9ffbfe0544bd0c1aafc1f9dc55629dd1b"}, - {file = "maxminddb-2.5.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17de49660372dcccaa23958eccdd1c2464f92f594d027045ad76788db14a5da4"}, - {file = "maxminddb-2.5.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ae05c4f87b1dd9a21d430c52451eef5f3bd5af609d093408db91fe0dc4d8d7d1"}, - {file = "maxminddb-2.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cb718908b9dffa10e02361094158ae68ded5a82c750de89737437999a81bafe"}, - {file = "maxminddb-2.5.2-cp38-cp38-win32.whl", hash = "sha256:e0faa0c4c458eb0eb2f267daa7b106baef72c3c7ebcbece00b9e974fc8321412"}, - {file = "maxminddb-2.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:bac5a29fdc5df9222f7baecbcc4a88b309a66a7d147b34160940c0850ee4b9c5"}, - {file = "maxminddb-2.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c204f53ef7c1d77e9fb0dba415dbb56419f2b08ccaca66cd772e29b3a793c3e7"}, - {file = "maxminddb-2.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae98508a200db6f7ae5985a53039aba8eef7ed71d34b0a0e9c9145c3e6139fc3"}, - {file = "maxminddb-2.5.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e9198d25e252b27d4e9526d5fcd4b78341c23153363a94f1246de5afcd39f6d"}, - {file = "maxminddb-2.5.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b85b008f8e2cf3abfabdc24041549c51c97ea9a8bc46eeeadac8cec7acf9fbf0"}, - {file = "maxminddb-2.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6f50210506e9818162ef6706d3127efb0575dfe2cc98a7236ca2011f1cc3effe"}, - {file = "maxminddb-2.5.2-cp39-cp39-win32.whl", hash = "sha256:2bba43d370a57785f5ef61c10d0b4bf8de58d431da3c4c2ed78bb2ff3d07edbf"}, - {file = "maxminddb-2.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:2e01b09480b97d2ebe6765618fb12a0f52caa17368d6cf1f42481d6740428de7"}, - {file = "maxminddb-2.5.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dd47d13376eaee2e8d1a1fb55d3d6ccdcc995bc931699967f7d5670ec6a454a3"}, - {file = "maxminddb-2.5.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abd626efaba4f0bc867462337f846796da0bb97b82125dbdbc63067947e353b0"}, - {file = "maxminddb-2.5.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ddbe547d83a2e28e81d9f59fd9708d3044ffb2398ee0f8df2e2a2e9cdea6646"}, - {file = "maxminddb-2.5.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:22184fa2514c15f5b39e4e2522f4f73d00afcf5eb7102c473f9376f3c3a03b81"}, - {file = "maxminddb-2.5.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5cb6702fbcc5b209ac3cffacd9cf0a5155feabbeb6fdcf497038be7cb6e52da6"}, - {file = "maxminddb-2.5.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0c3ebfc0af00445089629faffa4c5a1fcc42a1ca5d7dffc42bba314fde20c6d"}, - {file = "maxminddb-2.5.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:461dcf0a4f67aa1c9faea6d52c4060d39559bf68e99a514cf8c1e01af383f90b"}, - {file = "maxminddb-2.5.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e012e889639aab411f5483990188da51c968377f665dcb90584971dbf314d50a"}, - {file = "maxminddb-2.5.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:20596e452d03071db37a72c8ef9236126c04ed342864f68db0adf0d1bc9f642e"}, - {file = "maxminddb-2.5.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ec51b66774b102824c9a3dd4916356283f6a61db1868d4ebcb98bf26486718e"}, - {file = "maxminddb-2.5.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fda0dd512f345cc92492f96c61a0df47efc2e2064c15e8053ab2114b362d64d"}, - {file = "maxminddb-2.5.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:862fcfe226ebda29a537cdce678dc8dc71ca6540ad2483099f80c6a1ee4cdbdd"}, - {file = "maxminddb-2.5.2.tar.gz", hash = "sha256:b3c33e4fc7821ee6c9f40837116e16ab6175863d4a64eee024c5bec686690a87"}, -] - -[package.dependencies] -setuptools = ">=68.2.2" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, + {file = "maxminddb-2.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c8db454446d83b65bd605f6093400897a8698de82ca1c20f37494361ee5b6a7"}, + {file = "maxminddb-2.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f04a217240323caea98adb0eaf0342466656486fc27b18ff53f74414dbaecce"}, + {file = "maxminddb-2.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f40c1a145550a297b8c8743d62b8b1bf9fa572b36fa1df9157ea45fed0da9abc"}, + {file = "maxminddb-2.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:940c349e0937e1123f1ae7f213e4a7e90e972cd4501c5898ec70814e4c472747"}, + {file = "maxminddb-2.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8f9fcd1bb0e016e7a2ff2341920f99932cd0f573e18bc89e9ad168c9cb93392"}, + {file = "maxminddb-2.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a467ebf7cec651001a318aab5c9582f6774886e8d2d86aac77db33e5006ea118"}, + {file = "maxminddb-2.6.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ce8cdf86cbfb569fe7f33dbef283476d7693e002a4b73195996655067f770bd"}, + {file = "maxminddb-2.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d3790e9ee0157a320b0aa7ddf9f33290f33797608beae604b202a24aaf9db17"}, + {file = "maxminddb-2.6.1-cp310-cp310-win32.whl", hash = "sha256:4a75d73d8aaa82718d3553880951d1b7fe8c1cd309a84b992ca7789b832b1de7"}, + {file = "maxminddb-2.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:9ac567627ac141d3e1a797b5696b4e652b1660ddfa6c861f202eed1eb34143ab"}, + {file = "maxminddb-2.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:24f362eb049109f01dda5adba03d703d1a83e73fa95569ea2bc723a7ecbbea2b"}, + {file = "maxminddb-2.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:39be382e82ecf231869e4c3f628f18b21f032b7bc42f980b75f042c16818b991"}, + {file = "maxminddb-2.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:103c7c5740a63d42f1062a99c79712d73106b3b0663c4e6c559f502b673c50c8"}, + {file = "maxminddb-2.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03f59f5c06bb54907e74f8a5d5149032a6e14cb2d990e17e4b0446d18195ede6"}, + {file = "maxminddb-2.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8eb72818e43d2e52e896e72622f41219afe98913eda456ef626fb10a636acca3"}, + {file = "maxminddb-2.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cd4afedf6fab1678e5fac0f0cdeb9be2f77fcc07ae1ebc5abe788aec32dd3de8"}, + {file = "maxminddb-2.6.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bcc9ac85007ab222838974b084f49bb62531669e793a7730260dec2cf6e34bfd"}, + {file = "maxminddb-2.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4774750c744c378653536ad6d5f8e28bcb2566e7e24081e881b00c95b51cad09"}, + {file = "maxminddb-2.6.1-cp311-cp311-win32.whl", hash = "sha256:9b8ef7ed2bbbd8216a0560dd06caafe2fc1d6f9fa18cf46282c6f4a9a3d91b9c"}, + {file = "maxminddb-2.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5555698be89fa568b787570911a2aa5c666c335c12dcc5cd8166f96e3155e210"}, + {file = "maxminddb-2.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0a8b70fcfa0980c0e8501e1506115dbd6f2410436f54161647627430d7cbb66"}, + {file = "maxminddb-2.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5719b58cfbed4464f89afcbdbaf1eb84f9de805f1716f27c671bf11635ce5458"}, + {file = "maxminddb-2.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87989f153ce9a0974c69bb0bf26a3cb339c7dfbbfe3330883075543d8ef70fc5"}, + {file = "maxminddb-2.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa43c3783da55ca2a2ed68b97048b63c86ee1462caf32e5f9bfe038db9dac31f"}, + {file = "maxminddb-2.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3863e6017b96ee3ae1a6bb7ef0c25cd9013b04cccc1fd27880ab6371cdd1d84"}, + {file = "maxminddb-2.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f1481c05b2a7fa909bb48ada037d2c920d7845ea737d9a1e6513ab1c85a64a32"}, + {file = "maxminddb-2.6.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:416f3fddd1add9a421483b26d24abaf2dd355f3a5afd72923681698d345d99d6"}, + {file = "maxminddb-2.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0f5286b5db8065a59cf9e005281c9d74d3839a8cda8e8ee04305d42d5afcc523"}, + {file = "maxminddb-2.6.1-cp312-cp312-win32.whl", hash = "sha256:d44081ec6633a225e051eaf851aa5986aae5f5c8c1f33cf78b3a825c5d0df642"}, + {file = "maxminddb-2.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:f117fe0b5bafee78dbd97606dc60bba2160cfe1968484925174d7aadb7a38f37"}, + {file = "maxminddb-2.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9dd4275749d1d3fb3700df373cd593235ee307f17a3180bad151562e8294a61"}, + {file = "maxminddb-2.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:242e572b3e132146acd0e2633c00564a8e33cf6de54c060778c618070d109054"}, + {file = "maxminddb-2.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d718bb2379d06e8ca3c4aa09f22634e84fe76db44f66845d7c18c1f0e414fd6"}, + {file = "maxminddb-2.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2319e73cad84bb3897a0cfbe8473a87b0e83b7a69b84118be829cc761a4388ac"}, + {file = "maxminddb-2.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a029d2c23b8ad9f4e8316319d79f0d55899aa8e6d69a2bee77d998991256dee0"}, + {file = "maxminddb-2.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9eb6a13e781e2e7a02e88734e29139fb0e5e4024020b146da56202893e425595"}, + {file = "maxminddb-2.6.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:86457125adccf5c248d481fc1cd80e77674afeaf45995aed480a3c7e0e118ddc"}, + {file = "maxminddb-2.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:153ca60a282d5ba1db86eedd27b6bb0e158d0f94682598f9900f20690e01395f"}, + {file = "maxminddb-2.6.1-cp38-cp38-win32.whl", hash = "sha256:21e93c0d094d167bb96ab49c89df2746d78c99228c5273bd7dc6d11385dd63b3"}, + {file = "maxminddb-2.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:ae3c76fbc989eca9b31512ae899528a9dae9092f4c9b7e807ed55b9ff4254ed0"}, + {file = "maxminddb-2.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f11a0899eb671c77dc131c8dd5d6702eb2d7c19952790c87b36ef72d73696bc2"}, + {file = "maxminddb-2.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:db8e0a5c1262d43ba5d0f6efb357ba9e5b65b7f3fc982b77a9f543f222a7fca3"}, + {file = "maxminddb-2.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c5aa6d50a30cc733b57afa80cbb51c004a7beac23a6c6a56e3550992faaeac1"}, + {file = "maxminddb-2.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6edc11c4fb4c1ecbfb28cc5da167f7db415c4fabc1aeff0171b06473057e5fb"}, + {file = "maxminddb-2.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a943e4a0dd59bd6b98ee131f40bdf4efbab8db7667c3dfa9165b1e06ed3b46d"}, + {file = "maxminddb-2.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33859797f89c2949f86a98a0b89dc577a40561643e78084ad44307bbdc40dd76"}, + {file = "maxminddb-2.6.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d45a6a5d964182ff083f2ee545d049517e88f0898ab4df3e119582518cd97b64"}, + {file = "maxminddb-2.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b1090088504c4b45cf1f3ffc32eabd6d5065e56883d910658e5d5f31e80e4be4"}, + {file = "maxminddb-2.6.1-cp39-cp39-win32.whl", hash = "sha256:41af38a328cfa94041135753b7ab2dc08863b22535a4295f6e65f72de0a862b9"}, + {file = "maxminddb-2.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:4a2a1b713ceea188d066ca676c033f334baad4f41bc1d89640c9795d514b6617"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b8e0fa2ec7f58411262ab3edd837d3a1844e6068e128eca222867ad465b97e9d"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2396eb49868c2f078ba566359b66249643409dfca1372b5497cef06bf7965c4a"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16dc122ebaae59922c007bcb9cf2a0621f550392b54f7f5e0171baa111be5a55"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0855c3532063e16c71b9ca7f624d3061f0e6da03a1e4ff7fabf9253a278b3016"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb56115caee4f3beafd2907845dc8f80c633424cbe270a3738f6ba609ff7248e"}, + {file = "maxminddb-2.6.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:17272badaa3e0293858ea9a48fe3e9fe8d6b20cc465a54cd4766d05aeff6ca59"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:58a070a18ca6d17d79002b35351fa9373012a98ad5680c0c49d0794c1286d9d9"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:30d66df204847ab114b84b04adf60e91a1dc1a30ab42a3e41337ed10efb4f2ab"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32571299316c01eecfc364cd5b94cfa2a484ee45b1cb2cd80464d7f666c4be11"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44d546d6f8ac103c13daf965ac1970a6a32a8b2f33bdbc8a280f87383ce7c5cd"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e21d5ccf34eb1eee14d95c616b7628035953ed4d79ff560188014ae7f1aaaf7"}, + {file = "maxminddb-2.6.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6acc873145aade367d39f5c2c013eeba1fc7709c1cca8aa9a46dd25db12958ef"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2ad27b9a06da43f0192e19e772b3fc01b72a6d231d55e665ec675a235533b0c5"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3eb4711af74a6d8e10e28095c2a18a7ab010826d68665757383c140989f7e075"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e973d98f3bf828a94016d3875cb44e17739ad3957282505c16c68d20cf3a70a1"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d78c8e527ea90947d04450709032459221011a2d14cf5ac645ca1f76e8e7f2"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81a1070b61e2fabff936d256490924e49c8b54d3f9fa61f32c0c91b83dc11259"}, + {file = "maxminddb-2.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fc3526c587f53dd32a5191e81f4239bb3ead70f56a97936b3427b72e3a5cc55f"}, + {file = "maxminddb-2.6.1.tar.gz", hash = "sha256:6c5d591f625e03b0a34df0c7ff81580676397b8335e13ece130c6e39e4a3afb9"}, ] [[package]] @@ -2430,152 +2539,361 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "microsoft-kiota-abstractions" +version = "1.3.2" +description = "Core abstractions for kiota generated libraries in Python" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_abstractions-1.3.2-py2.py3-none-any.whl", hash = "sha256:ec4335df425874b1c0171a97c4b5ccdc4a9d076e1ecd3a5c2582af1cacc25016"}, + {file = "microsoft_kiota_abstractions-1.3.2.tar.gz", hash = "sha256:acac0b34b443d3fc10a3a86dd996cdf92248080553a3768a77c23350541f1aa2"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.19.0" +opentelemetry-sdk = ">=1.19.0" +std-uritemplate = ">=0.0.38" + +[[package]] +name = "microsoft-kiota-authentication-azure" +version = "1.0.0" +description = "Authentication provider for Kiota using Azure Identity" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_authentication_azure-1.0.0-py2.py3-none-any.whl", hash = "sha256:289fe002951ae661415a6d3fa7c422c096b739165acb32d786316988120a1b27"}, + {file = "microsoft_kiota_authentication_azure-1.0.0.tar.gz", hash = "sha256:752304f8d94b884cfec12583dd763ec0478805c7f80b29344e78c6d55a97bd01"}, +] + +[package.dependencies] +aiohttp = ">=3.8.0" +azure-core = ">=1.21.1" +microsoft-kiota-abstractions = ">=1.0.0,<2.0.0" +opentelemetry-api = ">=1.20.0" +opentelemetry-sdk = ">=1.20.0" + +[[package]] +name = "microsoft-kiota-http" +version = "1.3.1" +description = "Kiota http request adapter implementation for httpx library" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_http-1.3.1-py2.py3-none-any.whl", hash = "sha256:d62972c6ed4c785f9808a15479a7421abb38a9519b39e6933e5d05555b9fb427"}, + {file = "microsoft_kiota_http-1.3.1.tar.gz", hash = "sha256:09d85310379f88af0a0967925d1fcbe82f2520a9fe6fa1fd50e79af813bc451d"}, +] + +[package.dependencies] +httpx = {version = ">=0.23.0", extras = ["http2"]} +microsoft-kiota_abstractions = ">=1.0.0,<2.0.0" +opentelemetry-api = ">=1.20.0" +opentelemetry-sdk = ">=1.20.0" + +[[package]] +name = "microsoft-kiota-serialization-form" +version = "0.1.0" +description = "Implementation of Kiota Serialization Interfaces for URI-Form encoded serialization" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_serialization_form-0.1.0-py2.py3-none-any.whl", hash = "sha256:5bc76fb2fc67d7c1f878f876d252ea814e4fc38df505099b9b86de52d974380a"}, + {file = "microsoft_kiota_serialization_form-0.1.0.tar.gz", hash = "sha256:663ece0cb1a41fe9ddfc9195aa3f15f219e14d2a1ee51e98c53ad8d795b2785d"}, +] + +[package.dependencies] +microsoft-kiota_abstractions = ">=1.0.0,<2.0.0" +pendulum = ">=3.0.0" + +[[package]] +name = "microsoft-kiota-serialization-json" +version = "1.2.0" +description = "Implementation of Kiota Serialization interfaces for JSON" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_serialization_json-1.2.0-py2.py3-none-any.whl", hash = "sha256:cf68ef323157b3566b043d2282b292479bca6af0ffcf08385c806c812e507a58"}, + {file = "microsoft_kiota_serialization_json-1.2.0.tar.gz", hash = "sha256:89a4ec0128958bc92287db0cf5b6616a9f66ac42f6c7bcfe8894393d2156bed9"}, +] + +[package.dependencies] +microsoft-kiota_abstractions = ">=1.0.0,<2.0.0" +pendulum = ">=3.0.0b1" + +[[package]] +name = "microsoft-kiota-serialization-multipart" +version = "0.1.0" +description = "Implementation of Kiota Serialization Interfaces for Multipart serialization" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_serialization_multipart-0.1.0-py2.py3-none-any.whl", hash = "sha256:ef183902e77807806b8a181cdde53ba5bc04c6c9bdb2f7d80f8bad5d720e0015"}, + {file = "microsoft_kiota_serialization_multipart-0.1.0.tar.gz", hash = "sha256:14e89e92582e6630ddbc70ac67b70bf189dacbfc41a96d3e1d10339e86c8dde5"}, +] + +[package.dependencies] +microsoft-kiota_abstractions = ">=1.0.0,<2.0.0" + +[[package]] +name = "microsoft-kiota-serialization-text" +version = "1.0.0" +description = "Implementation of Kiota Serialization interfaces for text/plain" +optional = false +python-versions = "*" +files = [ + {file = "microsoft_kiota_serialization_text-1.0.0-py2.py3-none-any.whl", hash = "sha256:1d3789e012b603e059a36cc675d1fd08cb81e0dde423d970c0af2eabce9c0d43"}, + {file = "microsoft_kiota_serialization_text-1.0.0.tar.gz", hash = "sha256:c3dd3f409b1c4f4963bd1e41d51b65f7e53e852130bb441d79b77dad88ee76ed"}, +] + +[package.dependencies] +microsoft-kiota_abstractions = ">=1.0.0,<2.0.0" +python-dateutil = ">=2.8.2" + +[[package]] +name = "msal" +version = "1.28.0" +description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." +optional = false +python-versions = ">=3.7" +files = [ + {file = "msal-1.28.0-py3-none-any.whl", hash = "sha256:3064f80221a21cd535ad8c3fafbb3a3582cd9c7e9af0bb789ae14f726a0ca99b"}, + {file = "msal-1.28.0.tar.gz", hash = "sha256:80bbabe34567cb734efd2ec1869b2d98195c927455369d8077b3c542088c5c9d"}, +] + +[package.dependencies] +cryptography = ">=0.6,<45" +PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} +requests = ">=2.0.0,<3" + +[package.extras] +broker = ["pymsalruntime (>=0.13.2,<0.15)"] + +[[package]] +name = "msal-extensions" +version = "1.1.0" +description = "Microsoft Authentication Library extensions (MSAL EX) provides a persistence API that can save your data on disk, encrypted on Windows, macOS and Linux. Concurrent data access will be coordinated by a file lock mechanism." +optional = false +python-versions = ">=3.7" +files = [ + {file = "msal-extensions-1.1.0.tar.gz", hash = "sha256:6ab357867062db7b253d0bd2df6d411c7891a0ee7308d54d1e4317c1d1c54252"}, + {file = "msal_extensions-1.1.0-py3-none-any.whl", hash = "sha256:01be9711b4c0b1a151450068eeb2c4f0997df3bba085ac299de3a66f585e382f"}, +] + +[package.dependencies] +msal = ">=0.4.1,<2.0.0" +packaging = "*" +portalocker = [ + {version = ">=1.0,<3", markers = "platform_system != \"Windows\""}, + {version = ">=1.6,<3", markers = "platform_system == \"Windows\""}, +] + [[package]] name = "msgpack" -version = "1.0.7" +version = "1.0.8" description = "MessagePack serializer" optional = false python-versions = ">=3.8" files = [ - {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862"}, - {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329"}, - {file = "msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681"}, - {file = "msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9"}, - {file = "msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"}, - {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"}, - {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"}, - {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"}, - {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c"}, - {file = "msgpack-1.0.7-cp38-cp38-win32.whl", hash = "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2"}, - {file = "msgpack-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f"}, - {file = "msgpack-1.0.7-cp39-cp39-win32.whl", hash = "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad"}, - {file = "msgpack-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3"}, - {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, + {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, + {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, + {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, + {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, + {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, + {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, + {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, + {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, + {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, + {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] +[[package]] +name = "msgraph-core" +version = "1.0.0" +description = "Core component of the Microsoft Graph Python SDK" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgraph-core-1.0.0.tar.gz", hash = "sha256:f26bcbbb3cd149dd7f1613159e0c2ed862888d61bfd20ef0b08b9408eb670c9d"}, + {file = "msgraph_core-1.0.0-py3-none-any.whl", hash = "sha256:f3de5149e246833b4b03605590d0b4eacf58d9c5a10fd951c37e53f0a345afd5"}, +] + +[package.dependencies] +httpx = {version = ">=0.23.0", extras = ["http2"]} +microsoft-kiota-abstractions = ">=1.0.0,<2.0.0" +microsoft-kiota-authentication-azure = ">=1.0.0,<2.0.0" +microsoft-kiota-http = ">=1.0.0,<2.0.0" + +[package.extras] +dev = ["bumpver", "isort", "mypy", "pylint", "pytest", "yapf"] + +[[package]] +name = "msgraph-sdk" +version = "1.4.0" +description = "The Microsoft Graph Python SDK" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgraph_sdk-1.4.0-py3-none-any.whl", hash = "sha256:24f99082475ea129c3d45e44269bd64a7c6bfef8dda4f8ea692bbc9e47b71b78"}, + {file = "msgraph_sdk-1.4.0.tar.gz", hash = "sha256:715907272c240e579d7669a690504488e25ae15fec904e2918c49ca328dc4a14"}, +] + +[package.dependencies] +azure-identity = ">=1.12.0" +microsoft-kiota-abstractions = ">=1.0.0,<2.0.0" +microsoft-kiota-authentication-azure = ">=1.0.0,<2.0.0" +microsoft-kiota-http = ">=1.0.0,<2.0.0" +microsoft-kiota-serialization-form = ">=0.1.0" +microsoft-kiota-serialization-json = ">=1.0.0,<2.0.0" +microsoft-kiota-serialization-multipart = ">=0.1.0" +microsoft-kiota-serialization-text = ">=1.0.0,<2.0.0" +msgraph-core = ">=1.0.0" + +[package.extras] +dev = ["bumpver", "isort", "mypy", "pylint", "pytest", "yapf"] + [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -2591,15 +2909,18 @@ files = [ [[package]] name = "netaddr" -version = "0.10.1" +version = "1.2.1" description = "A network address manipulation library for Python" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "netaddr-0.10.1-py2.py3-none-any.whl", hash = "sha256:9822305b42ea1020d54fee322d43cee5622b044c07a1f0130b459bb467efcf88"}, - {file = "netaddr-0.10.1.tar.gz", hash = "sha256:f4da4222ca8c3f43c8e18a8263e5426c750a3a837fdfeccf74c68d0408eaa3bf"}, + {file = "netaddr-1.2.1-py3-none-any.whl", hash = "sha256:bd9e9534b0d46af328cf64f0e5a23a5a43fca292df221c85580b27394793496e"}, + {file = "netaddr-1.2.1.tar.gz", hash = "sha256:6eb8fedf0412c6d294d06885c110de945cf4d22d2b510d0404f4e06950857987"}, ] +[package.extras] +nicer-shell = ["ipython"] + [[package]] name = "oauthlib" version = "3.2.2" @@ -2626,6 +2947,48 @@ files = [ {file = "opencontainers-0.0.14.tar.gz", hash = "sha256:fde3b8099b56b5c956415df8933e2227e1914e805a277b844f2f9e52341738f2"}, ] +[[package]] +name = "opentelemetry-api" +version = "1.24.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"}, + {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +importlib-metadata = ">=6.0,<=7.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.24.0" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"}, + {file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"}, +] + +[package.dependencies] +opentelemetry-api = "1.24.0" +opentelemetry-semantic-conventions = "0.45b0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.45b0" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"}, + {file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"}, +] + [[package]] name = "outcome" version = "1.3.0.post0" @@ -2642,13 +3005,13 @@ attrs = ">=19.2.0" [[package]] name = "packaging" -version = "23.2" +version = "24.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] [[package]] @@ -2696,13 +3059,13 @@ files = [ [[package]] name = "pdoc" -version = "14.4.0" +version = "14.5.0" description = "API Documentation for Python Projects" optional = false python-versions = ">=3.8" files = [ - {file = "pdoc-14.4.0-py3-none-any.whl", hash = "sha256:6ea4fe07620b1f7601e2708a307a257636ec206e20b5611640b30f2e3cab47d6"}, - {file = "pdoc-14.4.0.tar.gz", hash = "sha256:c92edc425429ccbe287ace2a027953c24f13de53eab484c1a6d31ca72dd2fda9"}, + {file = "pdoc-14.5.0-py3-none-any.whl", hash = "sha256:9a8a84e19662610c0620fbe9f2e4174e3b090f8b601ed46348786ebb7517c508"}, + {file = "pdoc-14.5.0.tar.gz", hash = "sha256:79f534dc8a6494638dd6056b78e17a654df7ed34cc92646553ce3a7ba5a4fa4a"}, ] [package.dependencies] @@ -2714,44 +3077,163 @@ pygments = ">=2.12.0" dev = ["hypothesis", "mypy", "pdoc-pyo3-sample-library (==1.0.11)", "pygments (>=2.14.0)", "pytest", "pytest-cov", "pytest-timeout", "ruff", "tox", "types-pygments"] [[package]] -name = "platformdirs" -version = "4.1.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "pendulum" +version = "3.0.0" +description = "Python datetimes made easy" optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, + {file = "pendulum-3.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2cf9e53ef11668e07f73190c805dbdf07a1939c3298b78d5a9203a86775d1bfd"}, + {file = "pendulum-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fb551b9b5e6059377889d2d878d940fd0bbb80ae4810543db18e6f77b02c5ef6"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c58227ac260d5b01fc1025176d7b31858c9f62595737f350d22124a9a3ad82d"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60fb6f415fea93a11c52578eaa10594568a6716602be8430b167eb0d730f3332"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b69f6b4dbcb86f2c2fe696ba991e67347bcf87fe601362a1aba6431454b46bde"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:138afa9c373ee450ede206db5a5e9004fd3011b3c6bbe1e57015395cd076a09f"}, + {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:83d9031f39c6da9677164241fd0d37fbfc9dc8ade7043b5d6d62f56e81af8ad2"}, + {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c2308af4033fa534f089595bcd40a95a39988ce4059ccd3dc6acb9ef14ca44a"}, + {file = "pendulum-3.0.0-cp310-none-win_amd64.whl", hash = "sha256:9a59637cdb8462bdf2dbcb9d389518c0263799189d773ad5c11db6b13064fa79"}, + {file = "pendulum-3.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3725245c0352c95d6ca297193192020d1b0c0f83d5ee6bb09964edc2b5a2d508"}, + {file = "pendulum-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6c035f03a3e565ed132927e2c1b691de0dbf4eb53b02a5a3c5a97e1a64e17bec"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597e66e63cbd68dd6d58ac46cb7a92363d2088d37ccde2dae4332ef23e95cd00"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99a0f8172e19f3f0c0e4ace0ad1595134d5243cf75985dc2233e8f9e8de263ca"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:77d8839e20f54706aed425bec82a83b4aec74db07f26acd039905d1237a5e1d4"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde30e8146292b059020fbc8b6f8fd4a60ae7c5e6f0afef937bbb24880bdf01"}, + {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:660434a6fcf6303c4efd36713ca9212c753140107ee169a3fc6c49c4711c2a05"}, + {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dee9e5a48c6999dc1106eb7eea3e3a50e98a50651b72c08a87ee2154e544b33e"}, + {file = "pendulum-3.0.0-cp311-none-win_amd64.whl", hash = "sha256:d4cdecde90aec2d67cebe4042fd2a87a4441cc02152ed7ed8fb3ebb110b94ec4"}, + {file = "pendulum-3.0.0-cp311-none-win_arm64.whl", hash = "sha256:773c3bc4ddda2dda9f1b9d51fe06762f9200f3293d75c4660c19b2614b991d83"}, + {file = "pendulum-3.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:409e64e41418c49f973d43a28afe5df1df4f1dd87c41c7c90f1a63f61ae0f1f7"}, + {file = "pendulum-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a38ad2121c5ec7c4c190c7334e789c3b4624798859156b138fcc4d92295835dc"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde4d0b2024b9785f66b7f30ed59281bd60d63d9213cda0eb0910ead777f6d37"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2c5675769fb6d4c11238132962939b960fcb365436b6d623c5864287faa319"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8af95e03e066826f0f4c65811cbee1b3123d4a45a1c3a2b4fc23c4b0dff893b5"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2165a8f33cb15e06c67070b8afc87a62b85c5a273e3aaa6bc9d15c93a4920d6f"}, + {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ad5e65b874b5e56bd942546ea7ba9dd1d6a25121db1c517700f1c9de91b28518"}, + {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17fe4b2c844bbf5f0ece69cfd959fa02957c61317b2161763950d88fed8e13b9"}, + {file = "pendulum-3.0.0-cp312-none-win_amd64.whl", hash = "sha256:78f8f4e7efe5066aca24a7a57511b9c2119f5c2b5eb81c46ff9222ce11e0a7a5"}, + {file = "pendulum-3.0.0-cp312-none-win_arm64.whl", hash = "sha256:28f49d8d1e32aae9c284a90b6bb3873eee15ec6e1d9042edd611b22a94ac462f"}, + {file = "pendulum-3.0.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d4e2512f4e1a4670284a153b214db9719eb5d14ac55ada5b76cbdb8c5c00399d"}, + {file = "pendulum-3.0.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:3d897eb50883cc58d9b92f6405245f84b9286cd2de6e8694cb9ea5cb15195a32"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e169cc2ca419517f397811bbe4589cf3cd13fca6dc38bb352ba15ea90739ebb"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17c3084a4524ebefd9255513692f7e7360e23c8853dc6f10c64cc184e1217ab"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826d6e258052715f64d05ae0fc9040c0151e6a87aae7c109ba9a0ed930ce4000"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2aae97087872ef152a0c40e06100b3665d8cb86b59bc8471ca7c26132fccd0f"}, + {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ac65eeec2250d03106b5e81284ad47f0d417ca299a45e89ccc69e36130ca8bc7"}, + {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a5346d08f3f4a6e9e672187faa179c7bf9227897081d7121866358af369f44f9"}, + {file = "pendulum-3.0.0-cp37-none-win_amd64.whl", hash = "sha256:235d64e87946d8f95c796af34818c76e0f88c94d624c268693c85b723b698aa9"}, + {file = "pendulum-3.0.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:6a881d9c2a7f85bc9adafcfe671df5207f51f5715ae61f5d838b77a1356e8b7b"}, + {file = "pendulum-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7762d2076b9b1cb718a6631ad6c16c23fc3fac76cbb8c454e81e80be98daa34"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e8e36a8130819d97a479a0e7bf379b66b3b1b520e5dc46bd7eb14634338df8c"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7dc843253ac373358ffc0711960e2dd5b94ab67530a3e204d85c6e8cb2c5fa10"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a78ad3635d609ceb1e97d6aedef6a6a6f93433ddb2312888e668365908c7120"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a137e9e0d1f751e60e67d11fc67781a572db76b2296f7b4d44554761049d6"}, + {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c95984037987f4a457bb760455d9ca80467be792236b69d0084f228a8ada0162"}, + {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d29c6e578fe0f893766c0d286adbf0b3c726a4e2341eba0917ec79c50274ec16"}, + {file = "pendulum-3.0.0-cp38-none-win_amd64.whl", hash = "sha256:deaba8e16dbfcb3d7a6b5fabdd5a38b7c982809567479987b9c89572df62e027"}, + {file = "pendulum-3.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b11aceea5b20b4b5382962b321dbc354af0defe35daa84e9ff3aae3c230df694"}, + {file = "pendulum-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a90d4d504e82ad236afac9adca4d6a19e4865f717034fc69bafb112c320dcc8f"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:825799c6b66e3734227756fa746cc34b3549c48693325b8b9f823cb7d21b19ac"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad769e98dc07972e24afe0cff8d365cb6f0ebc7e65620aa1976fcfbcadc4c6f3"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6fc26907eb5fb8cc6188cc620bc2075a6c534d981a2f045daa5f79dfe50d512"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c717eab1b6d898c00a3e0fa7781d615b5c5136bbd40abe82be100bb06df7a56"}, + {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3ddd1d66d1a714ce43acfe337190be055cdc221d911fc886d5a3aae28e14b76d"}, + {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:822172853d7a9cf6da95d7b66a16c7160cb99ae6df55d44373888181d7a06edc"}, + {file = "pendulum-3.0.0-cp39-none-win_amd64.whl", hash = "sha256:840de1b49cf1ec54c225a2a6f4f0784d50bd47f68e41dc005b7f67c7d5b5f3ae"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b1f74d1e6ffe5d01d6023870e2ce5c2191486928823196f8575dcc786e107b1"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:729e9f93756a2cdfa77d0fc82068346e9731c7e884097160603872686e570f07"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e586acc0b450cd21cbf0db6bae386237011b75260a3adceddc4be15334689a9a"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22e7944ffc1f0099a79ff468ee9630c73f8c7835cd76fdb57ef7320e6a409df4"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fa30af36bd8e50686846bdace37cf6707bdd044e5cb6e1109acbad3277232e04"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:440215347b11914ae707981b9a57ab9c7b6983ab0babde07063c6ee75c0dc6e7"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:314c4038dc5e6a52991570f50edb2f08c339debdf8cea68ac355b32c4174e820"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5acb1d386337415f74f4d1955c4ce8d0201978c162927d07df8eb0692b2d8533"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a789e12fbdefaffb7b8ac67f9d8f22ba17a3050ceaaa635cd1cc4645773a4b1e"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:860aa9b8a888e5913bd70d819306749e5eb488e6b99cd6c47beb701b22bdecf5"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5ebc65ea033ef0281368217fbf59f5cb05b338ac4dd23d60959c7afcd79a60a0"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9fef18ab0386ef6a9ac7bad7e43ded42c83ff7ad412f950633854f90d59afa8"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c134ba2f0571d0b68b83f6972e2307a55a5a849e7dac8505c715c531d2a8795"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:385680812e7e18af200bb9b4a49777418c32422d05ad5a8eb85144c4a285907b"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eec91cd87c59fb32ec49eb722f375bd58f4be790cae11c1b70fac3ee4f00da0"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4386bffeca23c4b69ad50a36211f75b35a4deb6210bdca112ac3043deb7e494a"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dfbcf1661d7146d7698da4b86e7f04814221081e9fe154183e34f4c5f5fa3bf8"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:04a1094a5aa1daa34a6b57c865b25f691848c61583fb22722a4df5699f6bf74c"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5b0ec85b9045bd49dd3a3493a5e7ddfd31c36a2a60da387c419fa04abcaecb23"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0a15b90129765b705eb2039062a6daf4d22c4e28d1a54fa260892e8c3ae6e157"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:bb8f6d7acd67a67d6fedd361ad2958ff0539445ef51cbe8cd288db4306503cd0"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd69b15374bef7e4b4440612915315cc42e8575fcda2a3d7586a0d88192d0c88"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc00f8110db6898360c53c812872662e077eaf9c75515d53ecc65d886eec209a"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83a44e8b40655d0ba565a5c3d1365d27e3e6778ae2a05b69124db9e471255c4a"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1a3604e9fbc06b788041b2a8b78f75c243021e0f512447806a6d37ee5214905d"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:92c307ae7accebd06cbae4729f0ba9fa724df5f7d91a0964b1b972a22baa482b"}, + {file = "pendulum-3.0.0.tar.gz", hash = "sha256:5d034998dea404ec31fae27af6b22cff1708f830a1ed7353be4d1019bb9f584e"}, +] + +[package.dependencies] +python-dateutil = ">=2.6" +tzdata = ">=2020.1" + +[package.extras] +test = ["time-machine (>=2.6.0)"] + +[[package]] +name = "platformdirs" +version = "4.2.1" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, + {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] [[package]] name = "pluggy" -version = "1.3.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "portalocker" +version = "2.8.2" +description = "Wraps the portalocker recipe for easy usage" +optional = false +python-versions = ">=3.8" +files = [ + {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, + {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, +] + +[package.dependencies] +pywin32 = {version = ">=226", markers = "platform_system == \"Windows\""} + +[package.extras] +docs = ["sphinx (>=1.7.1)"] +redis = ["redis"] +tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] + [[package]] name = "prometheus-client" -version = "0.19.0" +version = "0.20.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.19.0-py3-none-any.whl", hash = "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92"}, - {file = "prometheus_client-0.19.0.tar.gz", hash = "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1"}, + {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, + {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, ] [package.extras] @@ -2771,132 +3253,128 @@ files = [ [package.dependencies] wcwidth = "*" +[[package]] +name = "proto-plus" +version = "1.23.0" +description = "Beautiful, Pythonic protocol buffers." +optional = false +python-versions = ">=3.6" +files = [ + {file = "proto-plus-1.23.0.tar.gz", hash = "sha256:89075171ef11988b3fa157f5dbd8b9cf09d65fffee97e29ce403cd8defba19d2"}, + {file = "proto_plus-1.23.0-py3-none-any.whl", hash = "sha256:a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c"}, +] + +[package.dependencies] +protobuf = ">=3.19.0,<5.0.0dev" + +[package.extras] +testing = ["google-api-core[grpc] (>=1.31.5)"] + +[[package]] +name = "protobuf" +version = "4.25.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, +] + [[package]] name = "psycopg" -version = "3.1.17" +version = "3.1.19" description = "PostgreSQL database adapter for Python" optional = false python-versions = ">=3.7" files = [ - {file = "psycopg-3.1.17-py3-none-any.whl", hash = "sha256:96b7b13af6d5a514118b759a66b2799a8a4aa78675fa6bb0d3f7d52d67eff002"}, - {file = "psycopg-3.1.17.tar.gz", hash = "sha256:437e7d7925459f21de570383e2e10542aceb3b9cb972ce957fdd3826ca47edc6"}, + {file = "psycopg-3.1.19-py3-none-any.whl", hash = "sha256:dca5e5521c859f6606686432ae1c94e8766d29cc91f2ee595378c510cc5b0731"}, + {file = "psycopg-3.1.19.tar.gz", hash = "sha256:92d7b78ad82426cdcf1a0440678209faa890c6e1721361c2f8901f0dccd62961"}, ] [package.dependencies] -psycopg-c = {version = "3.1.17", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""} +psycopg-c = {version = "3.1.19", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""} typing-extensions = ">=4.1" tzdata = {version = "*", markers = "sys_platform == \"win32\""} [package.extras] -binary = ["psycopg-binary (==3.1.17)"] -c = ["psycopg-c (==3.1.17)"] -dev = ["black (>=23.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] +binary = ["psycopg-binary (==3.1.19)"] +c = ["psycopg-c (==3.1.19)"] +dev = ["black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"] pool = ["psycopg-pool"] test = ["anyio (>=3.6.2,<4.0)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] [[package]] name = "psycopg-c" -version = "3.1.17" +version = "3.1.19" description = "PostgreSQL database adapter for Python -- C optimisation distribution" optional = false python-versions = ">=3.7" files = [ - {file = "psycopg-c-3.1.17.tar.gz", hash = "sha256:5cc4d544d552b8ab92a9e3a9dbe3b4f46ce0a86338654d26387fc076e0c97977"}, + {file = "psycopg_c-3.1.19.tar.gz", hash = "sha256:8e90f53c430e7d661cb3a9298e2761847212ead1b24c5fb058fc9d0fd9616017"}, ] [[package]] name = "pyasn1" -version = "0.5.1" +version = "0.6.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "pyasn1-0.5.1-py2.py3-none-any.whl", hash = "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58"}, - {file = "pyasn1-0.5.1.tar.gz", hash = "sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c"}, + {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, + {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, ] [[package]] name = "pyasn1-modules" -version = "0.3.0" +version = "0.4.0" description = "A collection of ASN.1-based protocols modules" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, - {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, + {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, + {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, ] [package.dependencies] -pyasn1 = ">=0.4.6,<0.6.0" +pyasn1 = ">=0.4.6,<0.7.0" [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - -[[package]] -name = "pycryptodome" -version = "3.20.0" -description = "Cryptographic library for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"}, - {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pydantic" -version = "2.5.3" +version = "2.7.1" description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"}, - {file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"}, + {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, + {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, ] [package.dependencies] annotated-types = ">=0.4.0" email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""} -pydantic-core = "2.14.6" +pydantic-core = "2.18.2" typing-extensions = ">=4.6.1" [package.extras] @@ -2904,116 +3382,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.14.6" -description = "" +version = "2.18.2" +description = "Core functionality for Pydantic validation and serialization" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"}, - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"}, - {file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"}, - {file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"}, - {file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"}, - {file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"}, - {file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"}, - {file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"}, - {file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"}, - {file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"}, - {file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"}, - {file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"}, - {file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"}, - {file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"}, - {file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"}, - {file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"}, - {file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"}, + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, + {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, + {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, + {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, + {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, + {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, + {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, + {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, + {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, + {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, + {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, + {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, + {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, + {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, ] [package.dependencies] @@ -3062,68 +3514,15 @@ files = [ {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, ] +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + [package.extras] crypto = ["cryptography (>=3.4.0)"] dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] -[[package]] -name = "pylint" -version = "3.0.3" -description = "python code static checker" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "pylint-3.0.3-py3-none-any.whl", hash = "sha256:7a1585285aefc5165db81083c3e06363a27448f6b467b3b0f30dbd0ac1f73810"}, - {file = "pylint-3.0.3.tar.gz", hash = "sha256:58c2398b0301e049609a8429789ec6edf3aabe9b6c5fec916acd18639c16de8b"}, -] - -[package.dependencies] -astroid = ">=3.0.1,<=3.1.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""} -isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pylint-django" -version = "2.5.5" -description = "A Pylint plugin to help Pylint understand the Django web framework" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "pylint_django-2.5.5-py3-none-any.whl", hash = "sha256:5abd5c2228e0e5e2a4cb6d0b4fc1d1cef1e773d0be911412f4dd4fc1a1a440b7"}, - {file = "pylint_django-2.5.5.tar.gz", hash = "sha256:2f339e4bf55776958283395c5139c37700c91bd5ef1d8251ef6ac88b5abbba9b"}, -] - -[package.dependencies] -pylint = ">=2.0,<4" -pylint-plugin-utils = ">=0.8" - -[package.extras] -with-django = ["Django (>=2.2)"] - -[[package]] -name = "pylint-plugin-utils" -version = "0.8.2" -description = "Utilities and helpers for writing Pylint plugins" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "pylint_plugin_utils-0.8.2-py3-none-any.whl", hash = "sha256:ae11664737aa2effbf26f973a9e0b6779ab7106ec0adc5fe104b0907ca04e507"}, - {file = "pylint_plugin_utils-0.8.2.tar.gz", hash = "sha256:d3cebf68a38ba3fba23a873809155562571386d4c1b03e5b4c4cc26c3eee93e4"}, -] - -[package.dependencies] -pylint = ">=1.7" - [[package]] name = "pynacl" version = "1.5.0" @@ -3152,21 +3551,35 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pyopenssl" -version = "23.3.0" +version = "24.1.0" description = "Python wrapper module around the OpenSSL library" optional = false python-versions = ">=3.7" files = [ - {file = "pyOpenSSL-23.3.0-py3-none-any.whl", hash = "sha256:6756834481d9ed5470f4a9393455154bc92fe7a64b7bc6ee2c804e78c52099b2"}, - {file = "pyOpenSSL-23.3.0.tar.gz", hash = "sha256:6b2cba5cc46e822750ec3e5a81ee12819850b11303630d575e98108a079c2b12"}, + {file = "pyOpenSSL-24.1.0-py3-none-any.whl", hash = "sha256:17ed5be5936449c5418d1cd269a1a9e9081bc54c17aed272b45856a3d3dc86ad"}, + {file = "pyOpenSSL-24.1.0.tar.gz", hash = "sha256:cabed4bfaa5df9f1a16c0ef64a0cb65318b5cd077a7eda7d6970131ca2f41a6f"}, ] [package.dependencies] -cryptography = ">=41.0.5,<42" +cryptography = ">=41.0.5,<43" [package.extras] docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx-rtd-theme"] -test = ["flaky", "pretend", "pytest (>=3.0.1)"] +test = ["pretend", "pytest (>=3.0.1)", "pytest-rerunfailures"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyrad" @@ -3197,33 +3610,33 @@ files = [ [[package]] name = "pytest" -version = "7.4.4" +version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" +pluggy = ">=1.5,<2.0" [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-django" -version = "4.7.0" +version = "4.8.0" description = "A Django plugin for pytest." optional = false python-versions = ">=3.8" files = [ - {file = "pytest-django-4.7.0.tar.gz", hash = "sha256:92d6fd46b1d79b54fb6b060bbb39428073396cec717d5f2e122a990d4b6aa5e8"}, - {file = "pytest_django-4.7.0-py3-none-any.whl", hash = "sha256:4e1c79d5261ade2dd58d91208017cd8f62cb4710b56e012ecd361d15d5d662a2"}, + {file = "pytest-django-4.8.0.tar.gz", hash = "sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90"}, + {file = "pytest_django-4.8.0-py3-none-any.whl", hash = "sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7"}, ] [package.dependencies] @@ -3263,27 +3676,27 @@ pytest = "*" [[package]] name = "pytest-timeout" -version = "2.2.0" +version = "2.3.1" description = "pytest plugin to abort hanging tests" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-timeout-2.2.0.tar.gz", hash = "sha256:3b0b95dabf3cb50bac9ef5ca912fa0cfc286526af17afc806824df20c2f72c90"}, - {file = "pytest_timeout-2.2.0-py3-none-any.whl", hash = "sha256:bde531e096466f49398a59f2dde76fa78429a09a12411466f88a07213e220de2"}, + {file = "pytest-timeout-2.3.1.tar.gz", hash = "sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9"}, + {file = "pytest_timeout-2.3.1-py3-none-any.whl", hash = "sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e"}, ] [package.dependencies] -pytest = ">=5.0.0" +pytest = ">=7.0.0" [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -3291,13 +3704,13 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.0.0" +version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" files = [ - {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, - {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, ] [package.extras] @@ -3305,13 +3718,13 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2023.3.post1" +version = "2024.1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] @@ -3362,6 +3775,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3398,13 +3812,13 @@ files = [ [[package]] name = "redis" -version = "5.0.1" +version = "5.0.4" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, - {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, + {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, + {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, ] [package.extras] @@ -3413,13 +3827,13 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" [[package]] name = "referencing" -version = "0.32.1" +version = "0.35.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.32.1-py3-none-any.whl", hash = "sha256:7e4dc12271d8e15612bfe35792f5ea1c40970dadf8624602e33db2758f7ee554"}, - {file = "referencing-0.32.1.tar.gz", hash = "sha256:3c57da0513e9563eb7e203ebe9bb3a1b509b042016433bd1e45a2853466c3dd3"}, + {file = "referencing-0.35.0-py3-none-any.whl", hash = "sha256:8080727b30e364e5783152903672df9b6b091c926a146a759080b62ca3126cd6"}, + {file = "referencing-0.35.0.tar.gz", hash = "sha256:191e936b0c696d0af17ad7430a3dc68e88bc11be6514f4757dc890f04ab05889"}, ] [package.dependencies] @@ -3428,13 +3842,13 @@ rpds-py = ">=0.7.0" [[package]] name = "requests" -version = "2.31.0" +version = "2.32.2" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, + {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, ] [package.dependencies] @@ -3449,32 +3863,30 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-mock" -version = "1.11.0" +version = "1.12.1" description = "Mock out responses from the requests package" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, - {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, + {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, + {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, ] [package.dependencies] -requests = ">=2.3,<3" -six = "*" +requests = ">=2.22,<3" [package.extras] fixture = ["fixtures"] -test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] [[package]] name = "requests-oauthlib" -version = "1.3.1" +version = "2.0.0" description = "OAuthlib authentication support for Requests." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.4" files = [ - {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, - {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, ] [package.dependencies] @@ -3486,13 +3898,13 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] [[package]] name = "rich" -version = "13.7.0" +version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, - {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, ] [package.dependencies] @@ -3504,110 +3916,110 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.16.2" +version = "0.18.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:509b617ac787cd1149600e731db9274ebbef094503ca25158e6f23edaba1ca8f"}, - {file = "rpds_py-0.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:413b9c17388bbd0d87a329d8e30c1a4c6e44e2bb25457f43725a8e6fe4161e9e"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2946b120718eba9af2b4dd103affc1164a87b9e9ebff8c3e4c05d7b7a7e274e2"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35ae5ece284cf36464eb160880018cf6088a9ac5ddc72292a6092b6ef3f4da53"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc6a7620ba7639a3db6213da61312cb4aa9ac0ca6e00dc1cbbdc21c2aa6eb57"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cb6fe8ecdfffa0e711a75c931fb39f4ba382b4b3ccedeca43f18693864fe850"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dace7b26a13353e24613417ce2239491b40a6ad44e5776a18eaff7733488b44"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bdbc5fcb04a7309074de6b67fa9bc4b418ab3fc435fec1f2779a0eced688d04"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f42e25c016927e2a6b1ce748112c3ab134261fc2ddc867e92d02006103e1b1b7"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eab36eae3f3e8e24b05748ec9acc66286662f5d25c52ad70cadab544e034536b"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0474df4ade9a3b4af96c3d36eb81856cb9462e4c6657d4caecfd840d2a13f3c9"}, - {file = "rpds_py-0.16.2-cp310-none-win32.whl", hash = "sha256:84c5a4d1f9dd7e2d2c44097fb09fffe728629bad31eb56caf97719e55575aa82"}, - {file = "rpds_py-0.16.2-cp310-none-win_amd64.whl", hash = "sha256:2bd82db36cd70b3628c0c57d81d2438e8dd4b7b32a6a9f25f24ab0e657cb6c4e"}, - {file = "rpds_py-0.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:adc0c3d6fc6ae35fee3e4917628983f6ce630d513cbaad575b4517d47e81b4bb"}, - {file = "rpds_py-0.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec23fcad480e77ede06cf4127a25fc440f7489922e17fc058f426b5256ee0edb"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07aab64e2808c3ebac2a44f67e9dc0543812b715126dfd6fe4264df527556cb6"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4ebb8b20bd09c5ce7884c8f0388801100f5e75e7f733b1b6613c713371feefc"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3d7e2ea25d3517c6d7e5a1cc3702cffa6bd18d9ef8d08d9af6717fc1c700eed"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f28ac0e8e7242d140f99402a903a2c596ab71550272ae9247ad78f9a932b5698"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19f00f57fdd38db4bb5ad09f9ead1b535332dbf624200e9029a45f1f35527ebb"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da5a4c56953bdbf6d04447c3410309616c54433146ccdb4a277b9cb499bc10e"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec2e1cf025b2c0f48ec17ff3e642661da7ee332d326f2e6619366ce8e221f018"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e0441fb4fdd39a230477b2ca9be90868af64425bfe7b122b57e61e45737a653b"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9f0350ef2fba5f34eb0c9000ea328e51b9572b403d2f7f3b19f24085f6f598e8"}, - {file = "rpds_py-0.16.2-cp311-none-win32.whl", hash = "sha256:5a80e2f83391ad0808b4646732af2a7b67550b98f0cae056cb3b40622a83dbb3"}, - {file = "rpds_py-0.16.2-cp311-none-win_amd64.whl", hash = "sha256:e04e56b4ca7a770593633556e8e9e46579d66ec2ada846b401252a2bdcf70a6d"}, - {file = "rpds_py-0.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5e6caa3809e50690bd92fa490f5c38caa86082c8c3315aa438bce43786d5e90d"}, - {file = "rpds_py-0.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e53b9b25cac9065328901713a7e9e3b12e4f57ef4280b370fbbf6fef2052eef"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af27423662f32d7501a00c5e7342f7dbd1e4a718aea7a239781357d15d437133"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d4dd5fb16eb3825742bad8339d454054261ab59fed2fbac84e1d84d5aae7ba"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e061de3b745fe611e23cd7318aec2c8b0e4153939c25c9202a5811ca911fd733"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b811d182ad17ea294f2ec63c0621e7be92a1141e1012383461872cead87468f"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5552f328eaef1a75ff129d4d0c437bf44e43f9436d3996e8eab623ea0f5fcf73"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dcbe1f8dd179e4d69b70b1f1d9bb6fd1e7e1bdc9c9aad345cdeb332e29d40748"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8aad80645a011abae487d356e0ceb359f4938dfb6f7bcc410027ed7ae4f7bb8b"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6f5549d6ed1da9bfe3631ca9483ae906f21410be2445b73443fa9f017601c6f"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d452817e0d9c749c431a1121d56a777bd7099b720b3d1c820f1725cb40928f58"}, - {file = "rpds_py-0.16.2-cp312-none-win32.whl", hash = "sha256:888a97002e986eca10d8546e3c8b97da1d47ad8b69726dcfeb3e56348ebb28a3"}, - {file = "rpds_py-0.16.2-cp312-none-win_amd64.whl", hash = "sha256:d8dda2a806dfa4a9b795950c4f5cc56d6d6159f7d68080aedaff3bdc9b5032f5"}, - {file = "rpds_py-0.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:071980663c273bf3d388fe5c794c547e6f35ba3335477072c713a3176bf14a60"}, - {file = "rpds_py-0.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:726ac36e8a3bb8daef2fd482534cabc5e17334052447008405daca7ca04a3108"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9e557db6a177470316c82f023e5d571811c9a4422b5ea084c85da9aa3c035fc"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90123853fc8b1747f80b0d354be3d122b4365a93e50fc3aacc9fb4c2488845d6"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a61f659665a39a4d17d699ab3593d7116d66e1e2e3f03ef3fb8f484e91908808"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc97f0640e91d7776530f06e6836c546c1c752a52de158720c4224c9e8053cad"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a54e99a2b9693a37ebf245937fd6e9228b4cbd64b9cc961e1f3391ec6c7391"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4b677d929cf1f6bac07ad76e0f2d5de367e6373351c01a9c0a39f6b21b4a8b"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5ef00873303d678aaf8b0627e111fd434925ca01c657dbb2641410f1cdaef261"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:349cb40897fd529ca15317c22c0eab67f5ac5178b5bd2c6adc86172045210acc"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ddef620e70eaffebed5932ce754d539c0930f676aae6212f8e16cd9743dd365"}, - {file = "rpds_py-0.16.2-cp38-none-win32.whl", hash = "sha256:882ce6e25e585949c3d9f9abd29202367175e0aab3aba0c58c9abbb37d4982ff"}, - {file = "rpds_py-0.16.2-cp38-none-win_amd64.whl", hash = "sha256:f4bd4578e44f26997e9e56c96dedc5f1af43cc9d16c4daa29c771a00b2a26851"}, - {file = "rpds_py-0.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:69ac7ea9897ec201ce68b48582f3eb34a3f9924488a5432a93f177bf76a82a7e"}, - {file = "rpds_py-0.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a9880b4656efe36ccad41edc66789e191e5ee19a1ea8811e0aed6f69851a82f4"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee94cb58c0ba2c62ee108c2b7c9131b2c66a29e82746e8fa3aa1a1effbd3dcf1"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24f7a2eb3866a9e91f4599851e0c8d39878a470044875c49bd528d2b9b88361c"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca57468da2d9a660bcf8961637c85f2fbb2aa64d9bc3f9484e30c3f9f67b1dd7"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccd4e400309e1f34a5095bf9249d371f0fd60f8a3a5c4a791cad7b99ce1fd38d"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80443fe2f7b3ea3934c5d75fb0e04a5dbb4a8e943e5ff2de0dec059202b70a8b"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d6a9f052e72d493efd92a77f861e45bab2f6be63e37fa8ecf0c6fd1a58fedb0"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:35953f4f2b3216421af86fd236b7c0c65935936a94ea83ddbd4904ba60757773"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:981d135c7cdaf6cd8eadae1c950de43b976de8f09d8e800feed307140d3d6d00"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d0dd7ed2f16df2e129496e7fbe59a34bc2d7fc8db443a606644d069eb69cbd45"}, - {file = "rpds_py-0.16.2-cp39-none-win32.whl", hash = "sha256:703d95c75a72e902544fda08e965885525e297578317989fd15a6ce58414b41d"}, - {file = "rpds_py-0.16.2-cp39-none-win_amd64.whl", hash = "sha256:e93ec1b300acf89730cf27975ef574396bc04edecc358e9bd116fb387a123239"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:44627b6ca7308680a70766454db5249105fa6344853af6762eaad4158a2feebe"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3f91df8e6dbb7360e176d1affd5fb0246d2b88d16aa5ebc7db94fd66b68b61da"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d904c5693e08bad240f16d79305edba78276be87061c872a4a15e2c301fa2c0"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:290a81cfbe4673285cdf140ec5cd1658ffbf63ab359f2b352ebe172e7cfa5bf0"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b634c5ec0103c5cbebc24ebac4872b045cccb9456fc59efdcf6fe39775365bd2"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a297a4d08cc67c7466c873c78039d87840fb50d05473db0ec1b7b03d179bf322"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e75e17bd0bb66ee34a707da677e47c14ee51ccef78ed6a263a4cc965a072a1"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f1b9d9260e06ea017feb7172976ab261e011c1dc2f8883c7c274f6b2aabfe01a"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:162d7cd9cd311c1b0ff1c55a024b8f38bd8aad1876b648821da08adc40e95734"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:9b32f742ce5b57201305f19c2ef7a184b52f6f9ba6871cc042c2a61f0d6b49b8"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac08472f41ea77cd6a5dae36ae7d4ed3951d6602833af87532b556c1b4601d63"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:495a14b72bbe217f2695dcd9b5ab14d4f8066a00f5d209ed94f0aca307f85f6e"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d6b6937ae9eac6d6c0ca3c42774d89fa311f55adff3970fb364b34abde6ed3d"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a61226465bda9283686db8f17d02569a98e4b13c637be5a26d44aa1f1e361c2"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5cf6af100ffb5c195beec11ffaa8cf8523057f123afa2944e6571d54da84cdc9"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6df15846ee3fb2e6397fe25d7ca6624af9f89587f3f259d177b556fed6bebe2c"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1be2f033df1b8be8c3167ba3c29d5dca425592ee31e35eac52050623afba5772"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96f957d6ab25a78b9e7fc9749d754b98eac825a112b4e666525ce89afcbd9ed5"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:088396c7c70e59872f67462fcac3ecbded5233385797021976a09ebd55961dfe"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4c46ad6356e1561f2a54f08367d1d2e70a0a1bb2db2282d2c1972c1d38eafc3b"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:47713dc4fce213f5c74ca8a1f6a59b622fc1b90868deb8e8e4d993e421b4b39d"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:f811771019f063bbd0aa7bb72c8a934bc13ebacb4672d712fc1639cfd314cccc"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f19afcfc0dd0dca35694df441e9b0f95bc231b512f51bded3c3d8ca32153ec19"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4b682c5775d6a3d21e314c10124599976809455ee67020e8e72df1769b87bc3"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c647ca87fc0ebe808a41de912e9a1bfef9acb85257e5d63691364ac16b81c1f0"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:302bd4983bbd47063e452c38be66153760112f6d3635c7eeefc094299fa400a9"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf721ede3eb7b829e4a9b8142bd55db0bdc82902720548a703f7e601ee13bdc3"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:358dafc89ce3894c7f486c615ba914609f38277ef67f566abc4c854d23b997fa"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad0f59ee3dc35526039f4bc23642d52d5f6616b5f687d846bfc6d0d6d486db0"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cffa76b385dfe1e38527662a302b19ffb0e7f5cf7dd5e89186d2c94a22dd9d0c"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:83640a5d7cd3bff694747d50436b8b541b5b9b9782b0c8c1688931d6ee1a1f2d"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:ed99b4f7179d2111702020fd7d156e88acd533f5a7d3971353e568b6051d5c97"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4022b9dc620e14f30201a8a73898a873c8e910cb642bcd2f3411123bc527f6ac"}, - {file = "rpds_py-0.16.2.tar.gz", hash = "sha256:781ef8bfc091b19960fc0142a23aedadafa826bc32b433fdfe6fd7f964d7ef44"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] [[package]] @@ -3626,39 +4038,39 @@ pyasn1 = ">=0.1.3" [[package]] name = "ruff" -version = "0.1.14" +version = "0.4.5" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.1.14-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:96f76536df9b26622755c12ed8680f159817be2f725c17ed9305b472a757cdbb"}, - {file = "ruff-0.1.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab3f71f64498c7241123bb5a768544cf42821d2a537f894b22457a543d3ca7a9"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060156ecc572b8f984fd20fd8b0fcb692dd5d837b7606e968334ab7ff0090ab"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a53d8e35313d7b67eb3db15a66c08434809107659226a90dcd7acb2afa55faea"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bea9be712b8f5b4ebed40e1949379cfb2a7d907f42921cf9ab3aae07e6fba9eb"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2270504d629a0b064247983cbc495bed277f372fb9eaba41e5cf51f7ba705a6a"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80258bb3b8909b1700610dfabef7876423eed1bc930fe177c71c414921898efa"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:653230dd00aaf449eb5ff25d10a6e03bc3006813e2cb99799e568f55482e5cae"}, - {file = "ruff-0.1.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b3acc6c4e6928459ba9eb7459dd4f0c4bf266a053c863d72a44c33246bfdbf"}, - {file = "ruff-0.1.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6b3dadc9522d0eccc060699a9816e8127b27addbb4697fc0c08611e4e6aeb8b5"}, - {file = "ruff-0.1.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1c8eca1a47b4150dc0fbec7fe68fc91c695aed798532a18dbb1424e61e9b721f"}, - {file = "ruff-0.1.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:62ce2ae46303ee896fc6811f63d6dabf8d9c389da0f3e3f2bce8bc7f15ef5488"}, - {file = "ruff-0.1.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b2027dde79d217b211d725fc833e8965dc90a16d0d3213f1298f97465956661b"}, - {file = "ruff-0.1.14-py3-none-win32.whl", hash = "sha256:722bafc299145575a63bbd6b5069cb643eaa62546a5b6398f82b3e4403329cab"}, - {file = "ruff-0.1.14-py3-none-win_amd64.whl", hash = "sha256:e3d241aa61f92b0805a7082bd89a9990826448e4d0398f0e2bc8f05c75c63d99"}, - {file = "ruff-0.1.14-py3-none-win_arm64.whl", hash = "sha256:269302b31ade4cde6cf6f9dd58ea593773a37ed3f7b97e793c8594b262466b67"}, - {file = "ruff-0.1.14.tar.gz", hash = "sha256:ad3f8088b2dfd884820289a06ab718cde7d38b94972212cc4ba90d5fbc9955f3"}, + {file = "ruff-0.4.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8f58e615dec58b1a6b291769b559e12fdffb53cc4187160a2fc83250eaf54e96"}, + {file = "ruff-0.4.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:84dd157474e16e3a82745d2afa1016c17d27cb5d52b12e3d45d418bcc6d49264"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f483ad9d50b00e7fd577f6d0305aa18494c6af139bce7319c68a17180087f4"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63fde3bf6f3ad4e990357af1d30e8ba2730860a954ea9282c95fc0846f5f64af"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e3ba4620dee27f76bbcad97067766026c918ba0f2d035c2fc25cbdd04d9c97"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:441dab55c568e38d02bbda68a926a3d0b54f5510095c9de7f95e47a39e0168aa"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1169e47e9c4136c997f08f9857ae889d614c5035d87d38fda9b44b4338909cdf"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:755ac9ac2598a941512fc36a9070a13c88d72ff874a9781493eb237ab02d75df"}, + {file = "ruff-0.4.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4b02a65985be2b34b170025a8b92449088ce61e33e69956ce4d316c0fe7cce0"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:75a426506a183d9201e7e5664de3f6b414ad3850d7625764106f7b6d0486f0a1"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6e1b139b45e2911419044237d90b60e472f57285950e1492c757dfc88259bb06"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a6f29a8221d2e3d85ff0c7b4371c0e37b39c87732c969b4d90f3dad2e721c5b1"}, + {file = "ruff-0.4.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d6ef817124d72b54cc923f3444828ba24fa45c3164bc9e8f1813db2f3d3a8a11"}, + {file = "ruff-0.4.5-py3-none-win32.whl", hash = "sha256:aed8166c18b1a169a5d3ec28a49b43340949e400665555b51ee06f22813ef062"}, + {file = "ruff-0.4.5-py3-none-win_amd64.whl", hash = "sha256:b0b03c619d2b4350b4a27e34fd2ac64d0dabe1afbf43de57d0f9d8a05ecffa45"}, + {file = "ruff-0.4.5-py3-none-win_arm64.whl", hash = "sha256:9d15de3425f53161b3f5a5658d4522e4eee5ea002bf2ac7aa380743dd9ad5fba"}, + {file = "ruff-0.4.5.tar.gz", hash = "sha256:286eabd47e7d4d521d199cab84deca135557e6d1e0f0d01c29e757c3cb151b54"}, ] [[package]] name = "s3transfer" -version = "0.10.0" +version = "0.10.1" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">= 3.8" files = [ - {file = "s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e"}, - {file = "s3transfer-0.10.0.tar.gz", hash = "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b"}, + {file = "s3transfer-0.10.1-py3-none-any.whl", hash = "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d"}, + {file = "s3transfer-0.10.1.tar.gz", hash = "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19"}, ] [package.dependencies] @@ -3667,15 +4079,32 @@ botocore = ">=1.33.2,<2.0a.0" [package.extras] crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] +[[package]] +name = "scim2-filter-parser" +version = "0.5.1" +description = "A customizable parser/transpiler for SCIM2.0 filters." +optional = false +python-versions = ">=3.8" +files = [ + {file = "scim2_filter_parser-0.5.1-py3-none-any.whl", hash = "sha256:09338fd73389606961d1fd90a068c6f4ffe357a9509bc48adc1dbb70afc2821d"}, + {file = "scim2_filter_parser-0.5.1.tar.gz", hash = "sha256:d2b88d11fbf000baca8e6b2057edb9bdf9827c4a34b172d05559b2b9f1994edf"}, +] + +[package.dependencies] +sly = "0.5" + +[package.extras] +django-query = ["django (>=3.2)"] + [[package]] name = "selenium" -version = "4.17.2" +version = "4.21.0" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "selenium-4.17.2-py3-none-any.whl", hash = "sha256:5aee79026c07985dc1b0c909f34084aa996dfe5b307602de9016d7a621a473f2"}, - {file = "selenium-4.17.2.tar.gz", hash = "sha256:d43d6972e516855fb242ef9ce4ce759057b115070e702e7b1c1032fe7b38d87b"}, + {file = "selenium-4.21.0-py3-none-any.whl", hash = "sha256:4770ffe5a5264e609de7dc914be6b89987512040d5a8efb2abb181330d097993"}, + {file = "selenium-4.21.0.tar.gz", hash = "sha256:650dbfa5159895ff00ad16e5ddb6ceecb86b90c7ed2012b3f041f64e6e4904fe"}, ] [package.dependencies] @@ -3687,39 +4116,44 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]} [[package]] name = "sentry-sdk" -version = "1.39.2" +version = "2.3.1" description = "Python client for Sentry (https://sentry.io)" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "sentry-sdk-1.39.2.tar.gz", hash = "sha256:24c83b0b41c887d33328a9166f5950dc37ad58f01c9f2fbff6b87a6f1094170c"}, - {file = "sentry_sdk-1.39.2-py2.py3-none-any.whl", hash = "sha256:acaf597b30258fc7663063b291aa99e58f3096e91fe1e6634f4b79f9c1943e8e"}, + {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, + {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, ] [package.dependencies] certifi = "*" -urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} +urllib3 = ">=1.26.11" [package.extras] aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] arq = ["arq (>=0.23)"] asyncpg = ["asyncpg (>=0.23)"] beam = ["apache-beam (>=2.12)"] bottle = ["bottle (>=0.12.13)"] celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] chalice = ["chalice (>=1.16.0)"] clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] django = ["django (>=1.8)"] falcon = ["falcon (>=1.4)"] fastapi = ["fastapi (>=0.79.0)"] flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] -grpcio = ["grpcio (>=1.21.1)"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] httpx = ["httpx (>=0.16.0)"] huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] opentelemetry = ["opentelemetry-distro (>=0.35b0)"] opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] -pure-eval = ["asttokens", "executing", "pure_eval"] +pure-eval = ["asttokens", "executing", "pure-eval"] pymongo = ["pymongo (>=3.1)"] pyspark = ["pyspark (>=2.4.4)"] quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] @@ -3754,21 +4188,121 @@ idna = ["idna"] mypy = ["idna", "mypy", "types-pyopenssl"] tests = ["coverage[toml] (>=5.0.2)", "pytest"] +[[package]] +name = "setproctitle" +version = "1.3.3" +description = "A Python module to customize the process title" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:897a73208da48db41e687225f355ce993167079eda1260ba5e13c4e53be7f754"}, + {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c331e91a14ba4076f88c29c777ad6b58639530ed5b24b5564b5ed2fd7a95452"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbbd6c7de0771c84b4aa30e70b409565eb1fc13627a723ca6be774ed6b9d9fa3"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c05ac48ef16ee013b8a326c63e4610e2430dbec037ec5c5b58fcced550382b74"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1342f4fdb37f89d3e3c1c0a59d6ddbedbde838fff5c51178a7982993d238fe4f"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc74e84fdfa96821580fb5e9c0b0777c1c4779434ce16d3d62a9c4d8c710df39"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9617b676b95adb412bb69645d5b077d664b6882bb0d37bfdafbbb1b999568d85"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6a249415f5bb88b5e9e8c4db47f609e0bf0e20a75e8d744ea787f3092ba1f2d0"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:38da436a0aaace9add67b999eb6abe4b84397edf4a78ec28f264e5b4c9d53cd5"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:da0d57edd4c95bf221b2ebbaa061e65b1788f1544977288bdf95831b6e44e44d"}, + {file = "setproctitle-1.3.3-cp310-cp310-win32.whl", hash = "sha256:a1fcac43918b836ace25f69b1dca8c9395253ad8152b625064415b1d2f9be4fb"}, + {file = "setproctitle-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:200620c3b15388d7f3f97e0ae26599c0c378fdf07ae9ac5a13616e933cbd2086"}, + {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:334f7ed39895d692f753a443102dd5fed180c571eb6a48b2a5b7f5b3564908c8"}, + {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:950f6476d56ff7817a8fed4ab207727fc5260af83481b2a4b125f32844df513a"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:195c961f54a09eb2acabbfc90c413955cf16c6e2f8caa2adbf2237d1019c7dd8"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f05e66746bf9fe6a3397ec246fe481096664a9c97eb3fea6004735a4daf867fd"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5901a31012a40ec913265b64e48c2a4059278d9f4e6be628441482dd13fb8b5"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64286f8a995f2cd934082b398fc63fca7d5ffe31f0e27e75b3ca6b4efda4e353"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:184239903bbc6b813b1a8fc86394dc6ca7d20e2ebe6f69f716bec301e4b0199d"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:664698ae0013f986118064b6676d7dcd28fefd0d7d5a5ae9497cbc10cba48fa5"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e5119a211c2e98ff18b9908ba62a3bd0e3fabb02a29277a7232a6fb4b2560aa0"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:417de6b2e214e837827067048f61841f5d7fc27926f2e43954567094051aff18"}, + {file = "setproctitle-1.3.3-cp311-cp311-win32.whl", hash = "sha256:6a143b31d758296dc2f440175f6c8e0b5301ced3b0f477b84ca43cdcf7f2f476"}, + {file = "setproctitle-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a680d62c399fa4b44899094027ec9a1bdaf6f31c650e44183b50d4c4d0ccc085"}, + {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d4460795a8a7a391e3567b902ec5bdf6c60a47d791c3b1d27080fc203d11c9dc"}, + {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bdfd7254745bb737ca1384dee57e6523651892f0ea2a7344490e9caefcc35e64"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477d3da48e216d7fc04bddab67b0dcde633e19f484a146fd2a34bb0e9dbb4a1e"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab2900d111e93aff5df9fddc64cf51ca4ef2c9f98702ce26524f1acc5a786ae7"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:088b9efc62d5aa5d6edf6cba1cf0c81f4488b5ce1c0342a8b67ae39d64001120"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6d50252377db62d6a0bb82cc898089916457f2db2041e1d03ce7fadd4a07381"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:87e668f9561fd3a457ba189edfc9e37709261287b52293c115ae3487a24b92f6"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:287490eb90e7a0ddd22e74c89a92cc922389daa95babc833c08cf80c84c4df0a"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe1c49486109f72d502f8be569972e27f385fe632bd8895f4730df3c87d5ac8"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a6ba2494a6449b1f477bd3e67935c2b7b0274f2f6dcd0f7c6aceae10c6c6ba3"}, + {file = "setproctitle-1.3.3-cp312-cp312-win32.whl", hash = "sha256:2df2b67e4b1d7498632e18c56722851ba4db5d6a0c91aaf0fd395111e51cdcf4"}, + {file = "setproctitle-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:f38d48abc121263f3b62943f84cbaede05749047e428409c2c199664feb6abc7"}, + {file = "setproctitle-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:816330675e3504ae4d9a2185c46b573105d2310c20b19ea2b4596a9460a4f674"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f960bc22d8d8e4ac886d1e2e21ccbd283adcf3c43136161c1ba0fa509088e0"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e6e7adff74796ef12753ff399491b8827f84f6c77659d71bd0b35870a17d8f"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53bc0d2358507596c22b02db079618451f3bd720755d88e3cccd840bafb4c41c"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6d20f9541f5f6ac63df553b6d7a04f313947f550eab6a61aa758b45f0d5657"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c1c84beab776b0becaa368254801e57692ed749d935469ac10e2b9b825dbdd8e"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:507e8dc2891021350eaea40a44ddd887c9f006e6b599af8d64a505c0f718f170"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b1067647ac7aba0b44b591936118a22847bda3c507b0a42d74272256a7a798e9"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2e71f6365744bf53714e8bd2522b3c9c1d83f52ffa6324bd7cbb4da707312cd8"}, + {file = "setproctitle-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:7f1d36a1e15a46e8ede4e953abb104fdbc0845a266ec0e99cc0492a4364f8c44"}, + {file = "setproctitle-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9a402881ec269d0cc9c354b149fc29f9ec1a1939a777f1c858cdb09c7a261df"}, + {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ff814dea1e5c492a4980e3e7d094286077054e7ea116cbeda138819db194b2cd"}, + {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:accb66d7b3ccb00d5cd11d8c6e07055a4568a24c95cf86109894dcc0c134cc89"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554eae5a5b28f02705b83a230e9d163d645c9a08914c0ad921df363a07cf39b1"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a911b26264dbe9e8066c7531c0591cfab27b464459c74385b276fe487ca91c12"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2982efe7640c4835f7355fdb4da313ad37fb3b40f5c69069912f8048f77b28c8"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3f4274b80709d8bcab2f9a862973d453b308b97a0b423a501bcd93582852e3"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:af2c67ae4c795d1674a8d3ac1988676fa306bcfa1e23fddb5e0bd5f5635309ca"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:af4061f67fd7ec01624c5e3c21f6b7af2ef0e6bab7fbb43f209e6506c9ce0092"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:37a62cbe16d4c6294e84670b59cf7adcc73faafe6af07f8cb9adaf1f0e775b19"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a83ca086fbb017f0d87f240a8f9bbcf0809f3b754ee01cec928fff926542c450"}, + {file = "setproctitle-1.3.3-cp38-cp38-win32.whl", hash = "sha256:059f4ce86f8cc92e5860abfc43a1dceb21137b26a02373618d88f6b4b86ba9b2"}, + {file = "setproctitle-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ab92e51cd4a218208efee4c6d37db7368fdf182f6e7ff148fb295ecddf264287"}, + {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c7951820b77abe03d88b114b998867c0f99da03859e5ab2623d94690848d3e45"}, + {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc94cf128676e8fac6503b37763adb378e2b6be1249d207630f83fc325d9b11"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f5d9027eeda64d353cf21a3ceb74bb1760bd534526c9214e19f052424b37e42"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e4a8104db15d3462e29d9946f26bed817a5b1d7a47eabca2d9dc2b995991503"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32c41ace41f344d317399efff4cffb133e709cec2ef09c99e7a13e9f3b9483c"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbf16381c7bf7f963b58fb4daaa65684e10966ee14d26f5cc90f07049bfd8c1e"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e18b7bd0898398cc97ce2dfc83bb192a13a087ef6b2d5a8a36460311cb09e775"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69d565d20efe527bd8a9b92e7f299ae5e73b6c0470f3719bd66f3cd821e0d5bd"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ddedd300cd690a3b06e7eac90ed4452348b1348635777ce23d460d913b5b63c3"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:415bfcfd01d1fbf5cbd75004599ef167a533395955305f42220a585f64036081"}, + {file = "setproctitle-1.3.3-cp39-cp39-win32.whl", hash = "sha256:21112fcd2195d48f25760f0eafa7a76510871bbb3b750219310cf88b04456ae3"}, + {file = "setproctitle-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:5a740f05d0968a5a17da3d676ce6afefebeeeb5ce137510901bf6306ba8ee002"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6b9e62ddb3db4b5205c0321dd69a406d8af9ee1693529d144e86bd43bcb4b6c0"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e3b99b338598de0bd6b2643bf8c343cf5ff70db3627af3ca427a5e1a1a90dd9"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ae9a02766dad331deb06855fb7a6ca15daea333b3967e214de12cfae8f0ef5"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:200ede6fd11233085ba9b764eb055a2a191fb4ffb950c68675ac53c874c22e20"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d3a953c50776751e80fe755a380a64cb14d61e8762bd43041ab3f8cc436092f"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e08e232b78ba3ac6bc0d23ce9e2bee8fad2be391b7e2da834fc9a45129eb87"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1da82c3e11284da4fcbf54957dafbf0655d2389cd3d54e4eaba636faf6d117a"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:aeaa71fb9568ebe9b911ddb490c644fbd2006e8c940f21cb9a1e9425bd709574"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:59335d000c6250c35989394661eb6287187854e94ac79ea22315469ee4f4c244"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3ba57029c9c50ecaf0c92bb127224cc2ea9fda057b5d99d3f348c9ec2855ad3"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d876d355c53d975c2ef9c4f2487c8f83dad6aeaaee1b6571453cb0ee992f55f6"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:224602f0939e6fb9d5dd881be1229d485f3257b540f8a900d4271a2c2aa4e5f4"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d7f27e0268af2d7503386e0e6be87fb9b6657afd96f5726b733837121146750d"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5e7266498cd31a4572378c61920af9f6b4676a73c299fce8ba93afd694f8ae7"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33c5609ad51cd99d388e55651b19148ea99727516132fb44680e1f28dd0d1de9"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:eae8988e78192fd1a3245a6f4f382390b61bce6cfcc93f3809726e4c885fa68d"}, + {file = "setproctitle-1.3.3.tar.gz", hash = "sha256:c913e151e7ea01567837ff037a23ca8740192880198b7fbb90b16d181607caae"}, +] + +[package.extras] +test = ["pytest"] + [[package]] name = "setuptools" -version = "69.0.3" +version = "69.5.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, - {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, + {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, + {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -3781,15 +4315,26 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sly" +version = "0.5" +description = "\"SLY - Sly Lex Yacc\"" +optional = false +python-versions = "*" +files = [ + {file = "sly-0.5-py3-none-any.whl", hash = "sha256:20485483259eec7f6ba85ff4d2e96a4e50c6621902667fc2695cc8bc2a3e5133"}, + {file = "sly-0.5.tar.gz", hash = "sha256:251d42015e8507158aec2164f06035df4a82b0314ce6450f457d7125e7649024"}, +] + [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] @@ -3805,29 +4350,39 @@ files = [ [[package]] name = "sqlparse" -version = "0.4.4" +version = "0.5.0" description = "A non-validating SQL parser." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, - {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, + {file = "sqlparse-0.5.0-py3-none-any.whl", hash = "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663"}, + {file = "sqlparse-0.5.0.tar.gz", hash = "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93"}, ] [package.extras] -dev = ["build", "flake8"] +dev = ["build", "hatch"] doc = ["sphinx"] -test = ["pytest", "pytest-cov"] + +[[package]] +name = "std-uritemplate" +version = "0.0.57" +description = "std-uritemplate implementation for Python" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "std_uritemplate-0.0.57-py3-none-any.whl", hash = "sha256:66691cb6ff1d1b3612741053d6f5573ec7eb1c1a33ffb5ca49557e8aa2372aa8"}, + {file = "std_uritemplate-0.0.57.tar.gz", hash = "sha256:f4adc717aec138562e652b95da74fc6815a942231d971314856b81f434c1b94c"}, +] [[package]] name = "stevedore" -version = "5.1.0" +version = "5.2.0" description = "Manage dynamic plugins for Python applications" optional = false python-versions = ">=3.8" files = [ - {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, - {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, + {file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"}, + {file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"}, ] [package.dependencies] @@ -3868,28 +4423,18 @@ typing-extensions = "*" [[package]] name = "tenant-schemas-celery" -version = "2.2.0" +version = "3.0.0" description = "Celery integration for django-tenant-schemas and django-tenants" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tenant-schemas-celery-2.2.0.tar.gz", hash = "sha256:b4fc16959cb98597591afb30f07256f70d8470d97c22c62e3d3af344868cdd6f"}, + {file = "tenant_schemas_celery-3.0.0-py3-none-any.whl", hash = "sha256:ca0f69e78ef698eb4813468231df5a0ab6a660c08e657b65f5ac92e16887eec8"}, + {file = "tenant_schemas_celery-3.0.0.tar.gz", hash = "sha256:6be3ae1a5826f262f0f3dd343c6a85a34a1c59b89e04ae37de018f36562fed55"}, ] [package.dependencies] celery = "*" -[[package]] -name = "tomlkit" -version = "0.12.3" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, - {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, -] - [[package]] name = "tornado" version = "6.4" @@ -3912,17 +4457,17 @@ files = [ [[package]] name = "trio" -version = "0.24.0" +version = "0.25.0" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.8" files = [ - {file = "trio-0.24.0-py3-none-any.whl", hash = "sha256:c3bd3a4e3e3025cd9a2241eae75637c43fe0b9e88b4c97b9161a55b9e54cd72c"}, - {file = "trio-0.24.0.tar.gz", hash = "sha256:ffa09a74a6bf81b84f8613909fb0beaee84757450183a7a2e0b47b455c0cac5d"}, + {file = "trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81"}, + {file = "trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e"}, ] [package.dependencies] -attrs = ">=20.1.0" +attrs = ">=23.2.0" cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} idna = "*" outcome = "*" @@ -3946,13 +4491,13 @@ wsproto = ">=0.14" [[package]] name = "twilio" -version = "8.11.1" +version = "9.0.5" description = "Twilio API client and TwiML generator" optional = false python-versions = ">=3.7.0" files = [ - {file = "twilio-8.11.1-py2.py3-none-any.whl", hash = "sha256:0c079601b972cca25dbe0e259d5c4a01c94795842f6b9f1d02c82269019d7cbb"}, - {file = "twilio-8.11.1.tar.gz", hash = "sha256:6dfafb60e7a89ad19d2fc4055ce2b86215d30fc68d88452fa588897de8608c71"}, + {file = "twilio-9.0.5-py2.py3-none-any.whl", hash = "sha256:5e09e910b9368f50f23cb3c3dd5ba77164d80a81e9d97db955cbac322deb2a4e"}, + {file = "twilio-9.0.5.tar.gz", hash = "sha256:e9b5727943584d25d618fe502f0100fc5283215f31c863f80b5c64581b4702b0"}, ] [package.dependencies] @@ -3963,13 +4508,13 @@ requests = ">=2.0.0" [[package]] name = "twisted" -version = "23.10.0" +version = "24.3.0" description = "An asynchronous networking framework written in Python" optional = false python-versions = ">=3.8.0" files = [ - {file = "twisted-23.10.0-py3-none-any.whl", hash = "sha256:4ae8bce12999a35f7fe6443e7f1893e6fe09588c8d2bed9c35cdce8ff2d5b444"}, - {file = "twisted-23.10.0.tar.gz", hash = "sha256:987847a0790a2c597197613686e2784fd54167df3a55d0fb17c8412305d76ce5"}, + {file = "twisted-24.3.0-py3-none-any.whl", hash = "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63"}, + {file = "twisted-24.3.0.tar.gz", hash = "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae"}, ] [package.dependencies] @@ -3993,7 +4538,7 @@ dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", " gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"] http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"] macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"] -mypy = ["mypy (>=1.5.1,<1.6.0)", "mypy-zope (>=1.0.1,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"] +mypy = ["mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"] osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"] serial = ["pyserial (>=3.0)", "pywin32 (!=226)"] test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"] @@ -4046,24 +4591,24 @@ twisted = ["twisted (>=20.3.0)", "zope.interface (>=5.2.0)"] [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.11.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, + {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] [[package]] name = "tzdata" -version = "2023.4" +version = "2024.1" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" files = [ - {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"}, - {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"}, + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] [[package]] @@ -4090,48 +4635,33 @@ files = [ [[package]] name = "urllib3" -version = "1.26.18" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.dependencies] -certifi = {version = "*", optional = true, markers = "extra == \"secure\""} -cryptography = {version = ">=1.3.4", optional = true, markers = "extra == \"secure\""} -idna = {version = ">=2.0.0", optional = true, markers = "extra == \"secure\""} -pyOpenSSL = {version = ">=0.14", optional = true, markers = "extra == \"secure\""} -PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} -urllib3-secure-extra = {version = "*", optional = true, markers = "extra == \"secure\""} +pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} [package.extras] -brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "urllib3-secure-extra" -version = "0.1.0" -description = "Marker library to detect whether urllib3 was installed with the deprecated [secure] extra" -optional = false -python-versions = "*" -files = [ - {file = "urllib3-secure-extra-0.1.0.tar.gz", hash = "sha256:ee9409cbfeb4b8609047be4c32fb4317870c602767e53fd8a41005ebe6a41dff"}, - {file = "urllib3_secure_extra-0.1.0-py2.py3-none-any.whl", hash = "sha256:f7adcb108b4d12a4b26b99eb60e265d087f435052a76aefa396b6ee85e9a6ef9"}, -] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.27.0" +version = "0.29.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.27.0-py3-none-any.whl", hash = "sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24"}, - {file = "uvicorn-0.27.0.tar.gz", hash = "sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6"}, + {file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"}, + {file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"}, ] [package.dependencies] @@ -4205,38 +4735,43 @@ files = [ [[package]] name = "watchdog" -version = "3.0.0" +version = "4.0.1" description = "Filesystem events monitoring" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, - {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, - {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, - {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, - {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, - {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, - {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, - {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, - {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, + {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, + {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, + {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, + {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, ] [package.extras] @@ -4342,13 +4877,13 @@ files = [ [[package]] name = "webauthn" -version = "2.0.0" +version = "2.1.0" description = "Pythonic WebAuthn" optional = false python-versions = "*" files = [ - {file = "webauthn-2.0.0-py3-none-any.whl", hash = "sha256:644dc68af5caaade06be6a2a2278775e85116e92dd755ad7a49d992d51c82033"}, - {file = "webauthn-2.0.0.tar.gz", hash = "sha256:12cc1759da98668b8242badc37c4129df300f89d89f5c183fac80e7b33c41dfd"}, + {file = "webauthn-2.1.0-py3-none-any.whl", hash = "sha256:9e1cf916e5ed7c01d54a6dfcc19dacbd2b87b81d2648f001b1fcbcb7aa2ff130"}, + {file = "webauthn-2.1.0.tar.gz", hash = "sha256:b196a4246c2818820857ba195c6e6e5398c761117f2269e3d2deab11c7995fc4"}, ] [package.dependencies] @@ -4359,17 +4894,17 @@ pyOpenSSL = ">=23.3.0" [[package]] name = "websocket-client" -version = "1.7.0" +version = "1.8.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" files = [ - {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, - {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, ] [package.extras] -docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] @@ -4454,6 +4989,85 @@ files = [ {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, ] +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + [[package]] name = "wsproto" version = "1.2.0" @@ -4470,24 +5084,69 @@ h11 = ">=0.9.0,<1" [[package]] name = "xmlsec" -version = "1.3.13" +version = "1.3.14" description = "Python bindings for the XML Security Library" optional = false python-versions = ">=3.5" files = [ - {file = "xmlsec-1.3.13-cp310-cp310-win32.whl", hash = "sha256:2174e8c88555383322d8b7d3927490a92ef72ad72a6ddaf4fa1b96a3f27c3e90"}, - {file = "xmlsec-1.3.13-cp310-cp310-win_amd64.whl", hash = "sha256:46d1daf16a8f4430efca5bb9c6a15776f2671f69f48a1941d6bb335e6f8cb29d"}, - {file = "xmlsec-1.3.13-cp35-cp35m-win32.whl", hash = "sha256:d47062c42775a025aa94fb8b15de97c1db86e301e549d3168157e0b1223d51b1"}, - {file = "xmlsec-1.3.13-cp35-cp35m-win_amd64.whl", hash = "sha256:7c7e8ef52688ddaf5b66750cc8d901f61716f46727014ff012f41d8858cedeb0"}, - {file = "xmlsec-1.3.13-cp36-cp36m-win32.whl", hash = "sha256:1725d70ee2bb2cd8dd66c7a7451be02bb59dc8280103db4f68e731f00135b1e0"}, - {file = "xmlsec-1.3.13-cp36-cp36m-win_amd64.whl", hash = "sha256:1f8c41162152d7086fd459926e61bc7cb2d52ffc829e760bf8b2c221a645d568"}, - {file = "xmlsec-1.3.13-cp37-cp37m-win32.whl", hash = "sha256:ff1c61f296e75cba5bac802d0000bfde09143eed946ced1a5162211867c335f8"}, - {file = "xmlsec-1.3.13-cp37-cp37m-win_amd64.whl", hash = "sha256:d249c0a2bf3ff13a231bca6a588e7d276b3f1e2cf09316b542f470a63855799e"}, - {file = "xmlsec-1.3.13-cp38-cp38-win32.whl", hash = "sha256:56cfcf3487b6ad269eb1fb543c04dee2c101f1bc91e06d6cf7bfab9ac486efd8"}, - {file = "xmlsec-1.3.13-cp38-cp38-win_amd64.whl", hash = "sha256:e6626bece0e97a8598b5df28c27bc6f2ae1e97d29dca3c1a4910a7598a4d1d0f"}, - {file = "xmlsec-1.3.13-cp39-cp39-win32.whl", hash = "sha256:091f23765729df6f3b3a55c8a6a96f9c713fa86e76b86a19cdb756aaa6dc0646"}, - {file = "xmlsec-1.3.13-cp39-cp39-win_amd64.whl", hash = "sha256:5162f416179350587c4ff64737af68a846a9b86f95fd465df4e68b589ce56618"}, - {file = "xmlsec-1.3.13.tar.gz", hash = "sha256:916f5d78e8041f6cd9391abba659da8c94a4fef7196d126d40af1ff417f2cf86"}, + {file = "xmlsec-1.3.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4dea6df3ffcb65d0b215678c3a0fe7bbc66785d6eae81291296e372498bad43a"}, + {file = "xmlsec-1.3.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fa1311f7489d050dde9028f5a2b5849c2927bb09c9a93491cb2f28fdc563912"}, + {file = "xmlsec-1.3.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cd9f513cf01dc0c5b9d9f0728714ecde2e7f46b3b6f63de91f4ae32f3008b3"}, + {file = "xmlsec-1.3.14-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77749b338503fb6e151052c664064b34264f4168e2cb0cca1de78b7e5312a783"}, + {file = "xmlsec-1.3.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4af81ce8044862ec865782efd353d22abdcd95b92364eef3c934de57ae6d5852"}, + {file = "xmlsec-1.3.14-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cf35a25be3eb6263b2e0544ba26294651113fab79064f994d347a2ca5973e8e2"}, + {file = "xmlsec-1.3.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:004e8a82e26728bf8a60f8ece1ef3ffafdac30ef538139dfe28870e8503ca64a"}, + {file = "xmlsec-1.3.14-cp310-cp310-win32.whl", hash = "sha256:e6cbc914d77678db0c8bc39e723d994174633d18f9d6be4665ec29cce978a96d"}, + {file = "xmlsec-1.3.14-cp310-cp310-win_amd64.whl", hash = "sha256:4922afa9234d1c5763950b26c328a5320019e55eb6000272a79dfe54fee8e704"}, + {file = "xmlsec-1.3.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7799a9ff3593f9dd43464e18b1a621640bffc40456c47c23383727f937dca7fc"}, + {file = "xmlsec-1.3.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1fe23c2dd5f5dbcb24f40e2c1061e2672a32aabee7cf8ac5337036a485607d72"}, + {file = "xmlsec-1.3.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be3b7a28e54a03b87faf07fb3c6dc3e50a2c79b686718c3ad08300b8bf6bb67"}, + {file = "xmlsec-1.3.14-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e894ad3e7de373f56efc09d6a56f7eae73a8dd4cec8943313134849e9c6607"}, + {file = "xmlsec-1.3.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:204d3c586b8bd6f02a5d4c59850a8157205569d40c32567f49576fa5795d897d"}, + {file = "xmlsec-1.3.14-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6679cec780386d848e7351d4b0de92c4483289ea4f0a2187e216159f939a4c6b"}, + {file = "xmlsec-1.3.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c4d41c83c8a2b8d8030204391ebeb6174fbdb044f0331653c4b5a4ce4150bcc0"}, + {file = "xmlsec-1.3.14-cp311-cp311-win32.whl", hash = "sha256:df4aa0782a53032fd35e18dcd6d328d6126324bfcfdef0cb5c2856f25b4b6f94"}, + {file = "xmlsec-1.3.14-cp311-cp311-win_amd64.whl", hash = "sha256:1072878301cb9243a54679e0520e6a5be2266c07a28b0ecef9e029d05a90ffcd"}, + {file = "xmlsec-1.3.14-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1eb3dcf244a52f796377112d8f238dbb522eb87facffb498425dc8582a84a6bf"}, + {file = "xmlsec-1.3.14-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:330147ce59fbe56a9be5b2085d739c55a569f112576b3f1b33681f87416eaf33"}, + {file = "xmlsec-1.3.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed4034939d8566ccdcd3b4e4f23c63fd807fb8763ae5668d59a19e11640a8242"}, + {file = "xmlsec-1.3.14-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a98eadfcb0c3b23ccceb7a2f245811f8d784bd287640dcfe696a26b9db1e2fc0"}, + {file = "xmlsec-1.3.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ff7b2711557c1087b72b0a1a88d82eafbf2a6d38b97309a6f7101d4a7041c3"}, + {file = "xmlsec-1.3.14-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:774d5d1e45f07f953c1cc14fd055c1063f0725f7248b6b0e681f59fd8638934d"}, + {file = "xmlsec-1.3.14-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bd10ca3201f164482775a7ce61bf7ee9aade2e7d032046044dd0f6f52c91d79d"}, + {file = "xmlsec-1.3.14-cp312-cp312-win32.whl", hash = "sha256:19c86bab1498e4c2e56d8e2c878f461ccb6e56b67fd7522b0c8fda46d8910781"}, + {file = "xmlsec-1.3.14-cp312-cp312-win_amd64.whl", hash = "sha256:d0762f4232bce2c7f6c0af329db8b821b4460bbe123a2528fb5677d03db7a4b5"}, + {file = "xmlsec-1.3.14-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:03ccba7dacf197850de954666af0221c740a5de631a80136362a1559223fab75"}, + {file = "xmlsec-1.3.14-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c12900e1903e289deb84eb893dca88591d6884d3e3cda4fb711b8812118416e8"}, + {file = "xmlsec-1.3.14-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6566434e2e5c58e472362a6187f208601f1627a148683a6f92bd16479f1d9e20"}, + {file = "xmlsec-1.3.14-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2401e162aaab7d9416c3405bac7a270e5f370988a0f1f46f0f29b735edba87e1"}, + {file = "xmlsec-1.3.14-cp36-cp36m-win32.whl", hash = "sha256:ba3b39c493e3b04354615068a3218f30897fcc2f42c6d8986d0c1d63aca87782"}, + {file = "xmlsec-1.3.14-cp36-cp36m-win_amd64.whl", hash = "sha256:4edd8db4df04bbac9c4a5ab4af855b74fe2bf2c248d07cac2e6d92a485f1a685"}, + {file = "xmlsec-1.3.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6dd86f440fec9242515c64f0be93fec8b4289287db1f6de2651eee9995aaecb"}, + {file = "xmlsec-1.3.14-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad1634cabe0915fe2a12e142db0ed2daf5be80cbe3891a2cecbba0750195cc6b"}, + {file = "xmlsec-1.3.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dba457ff87c39cbae3c5020475a728d24bbd9d00376df9af9724cd3bb59ff07a"}, + {file = "xmlsec-1.3.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12d90059308bb0c1b94bde065784e6852999d08b91bcb2048c17e62b954acb07"}, + {file = "xmlsec-1.3.14-cp37-cp37m-win32.whl", hash = "sha256:ce4e165a1436697e5e39587c4fba24db4545a5c9801e0d749f1afd09ad3ab901"}, + {file = "xmlsec-1.3.14-cp37-cp37m-win_amd64.whl", hash = "sha256:7e8e0171916026cbe8e2022c959558d02086655fd3c3466f2bc0451b09cf9ee8"}, + {file = "xmlsec-1.3.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c42735cc68fdb4c6065cf0a0701dfff3a12a1734c63a36376349af9a5481f27b"}, + {file = "xmlsec-1.3.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:38e035bf48300b7dbde2dd01d3b8569f8584fc9c73809be13886e6b6c77b74fb"}, + {file = "xmlsec-1.3.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73eabf5ef58189d81655058cf328c1dfa9893d89f1bff5fc941481f08533f338"}, + {file = "xmlsec-1.3.14-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bddd2a2328b4e08c8a112e06cf2cd2b4d281f4ad94df15b4cef18f06cdc49d78"}, + {file = "xmlsec-1.3.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fed3bc7943681c9ed4d2221600ab440f060d8d1a8f92f346f2b41effe175b8"}, + {file = "xmlsec-1.3.14-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:147934bd39dfd840663fb6b920ea9201455fa886427975713f1b42d9f20b9b29"}, + {file = "xmlsec-1.3.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e732a75fcb6b84872b168f972fbbf3749baf76308635f14015d1d35ed0c5719c"}, + {file = "xmlsec-1.3.14-cp38-cp38-win32.whl", hash = "sha256:b109cdf717257fd4daa77c1d3ec8a3fb2a81318a6d06a36c55a8a53ae381ae5e"}, + {file = "xmlsec-1.3.14-cp38-cp38-win_amd64.whl", hash = "sha256:b7ba2ea38e3d9efa520b14f3c0b7d99a7c055244ae5ba8bc9f4ca73b18f3a215"}, + {file = "xmlsec-1.3.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1b9b5de6bc69fdec23147e5f712cb05dc86df105462f254f140d743cc680cc7b"}, + {file = "xmlsec-1.3.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:82ac81deb7d7bf5cc8a748148948e5df5386597ff43fb92ec651cc5c7addb0e7"}, + {file = "xmlsec-1.3.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bae37b2920115cf00759ee9fb7841cbdebcef3a8a92734ab93ae8fa41ac581d"}, + {file = "xmlsec-1.3.14-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4fac2a787ae3b9fb761f9aec6b9f10f2d1c1b87abb574ebd8ff68435bdc97e3d"}, + {file = "xmlsec-1.3.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34c61ec0c0e70fda710290ae74b9efe1928d9242ed82c4eecf97aa696cff68e6"}, + {file = "xmlsec-1.3.14-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:995e87acecc263a2f6f2aa3cc204268f651cac8f4d7a2047f11b2cd49979cc38"}, + {file = "xmlsec-1.3.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2f84a1c509c52773365645a87949081ee9ea9c535cd452048cc8ca4ad3b45666"}, + {file = "xmlsec-1.3.14-cp39-cp39-win32.whl", hash = "sha256:7882963e9cb9c0bd0e8c2715a29159a366417ff4a30d8baf42b05bc5cf249446"}, + {file = "xmlsec-1.3.14-cp39-cp39-win_amd64.whl", hash = "sha256:a487c3d144f791c32f5e560aa27a705fba23171728b8a8511f36de053ff6bc93"}, + {file = "xmlsec-1.3.14.tar.gz", hash = "sha256:934f804f2f895bcdb86f1eaee236b661013560ee69ec108d29cdd6e5f292a2d9"}, ] [package.dependencies] @@ -4598,62 +5257,62 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.17.0" +version = "3.18.1" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, + {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, + {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [[package]] name = "zope-interface" -version = "6.1" +version = "6.3" description = "Interfaces for Python" optional = false python-versions = ">=3.7" files = [ - {file = "zope.interface-6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:43b576c34ef0c1f5a4981163b551a8781896f2a37f71b8655fd20b5af0386abb"}, - {file = "zope.interface-6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:67be3ca75012c6e9b109860820a8b6c9a84bfb036fbd1076246b98e56951ca92"}, - {file = "zope.interface-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b9bc671626281f6045ad61d93a60f52fd5e8209b1610972cf0ef1bbe6d808e3"}, - {file = "zope.interface-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe81def9cf3e46f16ce01d9bfd8bea595e06505e51b7baf45115c77352675fd"}, - {file = "zope.interface-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dc998f6de015723196a904045e5a2217f3590b62ea31990672e31fbc5370b41"}, - {file = "zope.interface-6.1-cp310-cp310-win_amd64.whl", hash = "sha256:239a4a08525c080ff833560171d23b249f7f4d17fcbf9316ef4159f44997616f"}, - {file = "zope.interface-6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ffdaa5290422ac0f1688cb8adb1b94ca56cee3ad11f29f2ae301df8aecba7d1"}, - {file = "zope.interface-6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34c15ca9248f2e095ef2e93af2d633358c5f048c49fbfddf5fdfc47d5e263736"}, - {file = "zope.interface-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b012d023b4fb59183909b45d7f97fb493ef7a46d2838a5e716e3155081894605"}, - {file = "zope.interface-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97806e9ca3651588c1baaebb8d0c5ee3db95430b612db354c199b57378312ee8"}, - {file = "zope.interface-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddbab55a2473f1d3b8833ec6b7ac31e8211b0aa608df5ab09ce07f3727326de"}, - {file = "zope.interface-6.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0da79117952a9a41253696ed3e8b560a425197d4e41634a23b1507efe3273f1"}, - {file = "zope.interface-6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8bb9c990ca9027b4214fa543fd4025818dc95f8b7abce79d61dc8a2112b561a"}, - {file = "zope.interface-6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b51b64432eed4c0744241e9ce5c70dcfecac866dff720e746d0a9c82f371dfa7"}, - {file = "zope.interface-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa6fd016e9644406d0a61313e50348c706e911dca29736a3266fc9e28ec4ca6d"}, - {file = "zope.interface-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c8cf55261e15590065039696607f6c9c1aeda700ceee40c70478552d323b3ff"}, - {file = "zope.interface-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e30506bcb03de8983f78884807e4fd95d8db6e65b69257eea05d13d519b83ac0"}, - {file = "zope.interface-6.1-cp312-cp312-win_amd64.whl", hash = "sha256:e33e86fd65f369f10608b08729c8f1c92ec7e0e485964670b4d2633a4812d36b"}, - {file = "zope.interface-6.1-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:2f8d89721834524a813f37fa174bac074ec3d179858e4ad1b7efd4401f8ac45d"}, - {file = "zope.interface-6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13b7d0f2a67eb83c385880489dbb80145e9d344427b4262c49fbf2581677c11c"}, - {file = "zope.interface-6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef43ee91c193f827e49599e824385ec7c7f3cd152d74cb1dfe02cb135f264d83"}, - {file = "zope.interface-6.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e441e8b7d587af0414d25e8d05e27040d78581388eed4c54c30c0c91aad3a379"}, - {file = "zope.interface-6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f89b28772fc2562ed9ad871c865f5320ef761a7fcc188a935e21fe8b31a38ca9"}, - {file = "zope.interface-6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70d2cef1bf529bff41559be2de9d44d47b002f65e17f43c73ddefc92f32bf00f"}, - {file = "zope.interface-6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ad54ed57bdfa3254d23ae04a4b1ce405954969c1b0550cc2d1d2990e8b439de1"}, - {file = "zope.interface-6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef467d86d3cfde8b39ea1b35090208b0447caaabd38405420830f7fd85fbdd56"}, - {file = "zope.interface-6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6af47f10cfc54c2ba2d825220f180cc1e2d4914d783d6fc0cd93d43d7bc1c78b"}, - {file = "zope.interface-6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9559138690e1bd4ea6cd0954d22d1e9251e8025ce9ede5d0af0ceae4a401e43"}, - {file = "zope.interface-6.1-cp38-cp38-win_amd64.whl", hash = "sha256:964a7af27379ff4357dad1256d9f215047e70e93009e532d36dcb8909036033d"}, - {file = "zope.interface-6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:387545206c56b0315fbadb0431d5129c797f92dc59e276b3ce82db07ac1c6179"}, - {file = "zope.interface-6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57d0a8ce40ce440f96a2c77824ee94bf0d0925e6089df7366c2272ccefcb7941"}, - {file = "zope.interface-6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ebc4d34e7620c4f0da7bf162c81978fce0ea820e4fa1e8fc40ee763839805f3"}, - {file = "zope.interface-6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a804abc126b33824a44a7aa94f06cd211a18bbf31898ba04bd0924fbe9d282d"}, - {file = "zope.interface-6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f294a15f7723fc0d3b40701ca9b446133ec713eafc1cc6afa7b3d98666ee1ac"}, - {file = "zope.interface-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a41f87bb93b8048fe866fa9e3d0c51e27fe55149035dcf5f43da4b56732c0a40"}, - {file = "zope.interface-6.1.tar.gz", hash = "sha256:2fdc7ccbd6eb6b7df5353012fbed6c3c5d04ceaca0038f75e601060e95345309"}, + {file = "zope.interface-6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f32010ffb87759c6a3ad1c65ed4d2e38e51f6b430a1ca11cee901ec2b42e021"}, + {file = "zope.interface-6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e78a183a3c2f555c2ad6aaa1ab572d1c435ba42f1dc3a7e8c82982306a19b785"}, + {file = "zope.interface-6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa0491a9f154cf8519a02026dc85a416192f4cb1efbbf32db4a173ba28b289a"}, + {file = "zope.interface-6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e32f02b3f26204d9c02c3539c802afc3eefb19d601a0987836ed126efb1f21"}, + {file = "zope.interface-6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c40df4aea777be321b7e68facb901bc67317e94b65d9ab20fb96e0eb3c0b60a1"}, + {file = "zope.interface-6.3-cp310-cp310-win_amd64.whl", hash = "sha256:46034be614d1f75f06e7dcfefba21d609b16b38c21fc912b01a99cb29e58febb"}, + {file = "zope.interface-6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:600101f43a7582d5b9504a7c629a1185a849ce65e60fca0f6968dfc4b76b6d39"}, + {file = "zope.interface-6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d6b229f5e1a6375f206455cc0a63a8e502ed190fe7eb15e94a312dc69d40299"}, + {file = "zope.interface-6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10cde8dc6b2fd6a1d0b5ca4be820063e46ddba417ab82bcf55afe2227337b130"}, + {file = "zope.interface-6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40aa8c8e964d47d713b226c5baf5f13cdf3a3169c7a2653163b17ff2e2334d10"}, + {file = "zope.interface-6.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d165d7774d558ea971cb867739fb334faf68fc4756a784e689e11efa3becd59e"}, + {file = "zope.interface-6.3-cp311-cp311-win_amd64.whl", hash = "sha256:69dedb790530c7ca5345899a1b4cb837cc53ba669051ea51e8c18f82f9389061"}, + {file = "zope.interface-6.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8d407e0fd8015f6d5dfad481309638e1968d70e6644e0753f229154667dd6cd5"}, + {file = "zope.interface-6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:72d5efecad16c619a97744a4f0b67ce1bcc88115aa82fcf1dc5be9bb403bcc0b"}, + {file = "zope.interface-6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:567d54c06306f9c5b6826190628d66753b9f2b0422f4c02d7c6d2b97ebf0a24e"}, + {file = "zope.interface-6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483e118b1e075f1819b3c6ace082b9d7d3a6a5eb14b2b375f1b80a0868117920"}, + {file = "zope.interface-6.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb78c12c1ad3a20c0d981a043d133299117b6854f2e14893b156979ed4e1d2c"}, + {file = "zope.interface-6.3-cp312-cp312-win_amd64.whl", hash = "sha256:ad4524289d8dbd6fb5aa17aedb18f5643e7d48358f42c007a5ee51a2afc2a7c5"}, + {file = "zope.interface-6.3-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:a56fe1261230093bfeedc1c1a6cd6f3ec568f9b07f031c9a09f46b201f793a85"}, + {file = "zope.interface-6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014bb94fe6bf1786da1aa044eadf65bc6437bcb81c451592987e5be91e70a91e"}, + {file = "zope.interface-6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22e8a218e8e2d87d4d9342aa973b7915297a08efbebea5b25900c73e78ed468e"}, + {file = "zope.interface-6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f95bebd0afe86b2adc074df29edb6848fc4d474ff24075e2c263d698774e108d"}, + {file = "zope.interface-6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:d0e7321557c702bd92dac3c66a2f22b963155fdb4600133b6b29597f62b71b12"}, + {file = "zope.interface-6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:187f7900b63845dcdef1be320a523dbbdba94d89cae570edc2781eb55f8c2f86"}, + {file = "zope.interface-6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a058e6cf8d68a5a19cb5449f42a404f0d6c2778b897e6ce8fadda9cea308b1b0"}, + {file = "zope.interface-6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8fa0fb05083a1a4216b4b881fdefa71c5d9a106e9b094cd4399af6b52873e91"}, + {file = "zope.interface-6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a37fb395a703e39b11b00b9e921c48f82b6e32cc5851ad5d0618cd8876b5"}, + {file = "zope.interface-6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b0c4c90e5eefca2c3e045d9f9ed9f1e2cdbe70eb906bff6b247e17119ad89a1"}, + {file = "zope.interface-6.3-cp38-cp38-win_amd64.whl", hash = "sha256:5683aa8f2639016fd2b421df44301f10820e28a9b96382a6e438e5c6427253af"}, + {file = "zope.interface-6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c3cfb272bcb83650e6695d49ae0d14dd06dc694789a3d929f23758557a23d92"}, + {file = "zope.interface-6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:01a0b3dd012f584afcf03ed814bce0fc40ed10e47396578621509ac031be98bf"}, + {file = "zope.interface-6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4137025731e824eee8d263b20682b28a0bdc0508de9c11d6c6be54163e5b7c83"}, + {file = "zope.interface-6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c8731596198198746f7ce2a4487a0edcbc9ea5e5918f0ab23c4859bce56055c"}, + {file = "zope.interface-6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf34840e102d1d0b2d39b1465918d90b312b1119552cebb61a242c42079817b9"}, + {file = "zope.interface-6.3-cp39-cp39-win_amd64.whl", hash = "sha256:a1adc14a2a9d5e95f76df625a9b39f4709267a483962a572e3f3001ef90ea6e6"}, + {file = "zope.interface-6.3.tar.gz", hash = "sha256:f83d6b4b22262d9a826c3bd4b2fbfafe1d0000f085ef8e44cd1328eea274ae6a"}, ] [package.dependencies] @@ -4677,4 +5336,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "~3.12" -content-hash = "872b759c19aa026742ef493c1b13a5f01dc5baab84efe7385163c4bf428b8f8f" +content-hash = "112c777b6cf6bec7583f3994cd1fa0165d046d09a2f378990ba6bb626f9739ca" diff --git a/proxy.Dockerfile b/proxy.Dockerfile index a0c67f64df..f1ad9d459b 100644 --- a/proxy.Dockerfile +++ b/proxy.Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # Stage 1: Build website -FROM --platform=${BUILDPLATFORM} docker.io/node:21 as web-builder +FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder ENV NODE_ENV=production WORKDIR /static @@ -17,7 +17,7 @@ COPY web . RUN npm run build-proxy # Stage 2: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.6-bookworm AS builder +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.22-fips-bookworm AS builder ARG TARGETOS ARG TARGETARCH @@ -28,20 +28,26 @@ ARG GOARCH=$TARGETARCH WORKDIR /go/src/goauthentik.io +RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ + dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu + RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \ --mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \ --mount=type=bind,target=/go/src/goauthentik.io/gen-go-api,src=./gen-go-api \ --mount=type=cache,target=/go/pkg/mod \ go mod download -ENV CGO_ENABLED=0 COPY . . RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \ - GOARM="${TARGETVARIANT#v}" go build -o /go/proxy ./cmd/proxy + if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \ + CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \ + go build -o /go/proxy ./cmd/proxy # Stage 3: Run -FROM gcr.io/distroless/static-debian11:debug +FROM ghcr.io/goauthentik/fips-debian:bookworm-slim-fips ARG GIT_BUILD_HASH ENV GIT_BUILD_HASH=$GIT_BUILD_HASH @@ -64,4 +70,6 @@ EXPOSE 9000 9300 9443 USER 1000 +ENV GOFIPS=1 + ENTRYPOINT ["/proxy"] diff --git a/pyproject.toml b/pyproject.toml index d7bc55313d..809721751a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,19 +1,8 @@ -[tool.pyright] -ignore = ["**/migrations/**", "**/node_modules/**"] -reportMissingTypeStubs = false -strictParameterNoneValue = true -strictDictionaryInference = true -strictListInference = true -reportOptionalMemberAccess = false -reportOptionalContextManager = false -# rest_framework's serializer's `validated_data` is typed as optional None -reportOptionalSubscript = false -# Sadly pyright still has issues with enums, and they fall under general type issues -# so we have to disable those for now -reportGeneralTypeIssues = false -verboseOutput = false -pythonVersion = "3.12" -pythonPlatform = "All" +[tool.poetry] +name = "authentik" +version = "2024.4.2" +description = "" +authors = ["authentik Team "] [tool.black] line-length = 100 @@ -25,14 +14,30 @@ line-length = 100 target-version = "py312" exclude = ["**/migrations/**", "**/node_modules/**"] -[tool.isort] -multi_line_output = 3 -include_trailing_comma = true -force_grid_wrap = 0 -use_parentheses = true -line_length = 100 -src_paths = ["authentik", "tests", "lifecycle"] -force_to_top = "*" +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # isort + "I", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # django + "DJ", + # pylint + "PL", +] +ignore = [ + "DJ001" # Avoid using `null=True` on string-based fields, +] +[tool.ruff.lint.pylint] +max-args = 7 +max-branches = 18 +max-returns = 10 [tool.coverage.run] source = ["authentik"] @@ -67,56 +72,16 @@ exclude_lines = [ ] show_missing = true -[tool.pylint.basic] -good-names = ["pk", "id", "i", "j", "k", "_", "bar"] - -[tool.pylint.master] -disable = [ - "arguments-differ", - "locally-disabled", - "too-many-ancestors", - "too-few-public-methods", - "import-outside-toplevel", - "signature-differs", - "similarities", - "cyclic-import", - "protected-access", - "unused-argument", - "raise-missing-from", - "fixme", - # To preserve django's translation function we need to use %-formatting - "consider-using-f-string", -] - -load-plugins = ["pylint_django", "pylint.extensions.bad_builtin"] -django-settings-module = "authentik.root.settings" -extension-pkg-whitelist = ["lxml", "xmlsec"] - -# Allow constants to be shorter than normal (and lowercase, for settings.py) -const-rgx = "[a-zA-Z0-9_]{1,40}$" - -ignored-modules = ["binascii", "socket", "zlib"] -generated-members = ["xmlsec.constants.*", "xmlsec.tree.*", "xmlsec.template.*"] -ignore = ["migrations", "tests"] -max-attributes = 12 -max-branches = 20 - [tool.pytest.ini_options] DJANGO_SETTINGS_MODULE = "authentik.root.settings" python_files = ["tests.py", "test_*.py", "*_tests.py"] junit_family = "xunit2" -addopts = "-p no:celery --junitxml=unittest.xml -vv --full-trace --doctest-modules" +addopts = "-p no:celery -p authentik.root.test_plugin --junitxml=unittest.xml -vv --full-trace --doctest-modules --import-mode=importlib" filterwarnings = [ "ignore:defusedxml.lxml is no longer supported and will be removed in a future release.:DeprecationWarning", "ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning", ] -[tool.poetry] -name = "authentik" -version = "2023.10.6" -description = "" -authors = ["authentik Team "] - [tool.poetry.dependencies] argon2-cffi = "*" celery = "*" @@ -124,6 +89,7 @@ channels = { version = "*", extras = ["daphne"] } channels-redis = "*" codespell = "*" colorama = "*" +cryptography = "*" dacite = "*" deepmerge = "*" defusedxml = "*" @@ -131,43 +97,43 @@ django = "*" django-filter = "*" django-guardian = "*" django-model-utils = "*" +django-pglock = "*" django-prometheus = "*" django-redis = "*" django-storages = { extras = ["s3"], version = "*" } # See https://github.com/django-tenants/django-tenants/pull/997 django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch="authentik-fixes" } -djangorestframework = "*" +djangorestframework = "3.14.0" djangorestframework-guardian = "*" docker = "*" drf-spectacular = "*" dumb-init = "*" duo-client = "*" facebook-sdk = "*" +fido2 = "*" flower = "*" geoip2 = "*" +google-api-python-client = "*" gunicorn = "*" +jsonpatch = "*" kubernetes = "*" ldap3 = "*" -lxml = [ - # 5.0.0 works with libxml2 2.11.x, which is standard on brew - { version = "5.0.0", platform = "darwin" }, - # 4.9.x works with previous libxml2 versions, which is what we get on linux - { version = "4.9.4", platform = "linux" }, -] -jsonpatch = "*" +lxml = "*" +msgraph-sdk = "*" opencontainers = { extras = ["reggie"], version = "*" } packaging = "*" paramiko = "*" psycopg = { extras = ["c"], version = "*" } -pycryptodome = "*" pydantic = "*" pydantic-scim = "*" pyjwt = "*" python = "~3.12" pyyaml = "*" requests-oauthlib = "*" +scim2-filter-parser = "*" sentry-sdk = "*" service_identity = "*" +setproctitle = "*" structlog = "*" swagger-spec-validator = "*" tenant-schemas-celery = "*" @@ -175,7 +141,7 @@ twilio = "*" twisted = "*" ua-parser = "*" # Pinned because of botocore https://github.com/orgs/python-poetry/discussions/7937 -urllib3 = { extras = ["secure"], version = "<2" } +urllib3 = { extras = ["secure"], version = "<3" } uvicorn = { extras = ["standard"], version = "*" } watchdog = "*" webauthn = "*" @@ -194,8 +160,6 @@ drf-jsonschema-serializer = "*" freezegun = "*" importlib-metadata = "*" pdoc = "*" -pylint = "*" -pylint-django = "*" pyrad = "*" pytest = "*" pytest-django = "*" diff --git a/rac.Dockerfile b/rac.Dockerfile index e59c22d05e..2ce3d9d7ed 100644 --- a/rac.Dockerfile +++ b/rac.Dockerfile @@ -1,24 +1,37 @@ # syntax=docker/dockerfile:1 # Stage 1: Build -FROM docker.io/golang:1.21.6-bookworm AS builder +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.22-fips-bookworm AS builder + +ARG TARGETOS +ARG TARGETARCH +ARG TARGETVARIANT + +ARG GOOS=$TARGETOS +ARG GOARCH=$TARGETARCH WORKDIR /go/src/goauthentik.io +RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ + dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu + RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \ --mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \ --mount=type=bind,target=/go/src/goauthentik.io/gen-go-api,src=./gen-go-api \ --mount=type=cache,target=/go/pkg/mod \ go mod download -ENV CGO_ENABLED=0 COPY . . RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \ + if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \ + CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \ go build -o /go/rac ./cmd/rac # Stage 2: Run -FROM ghcr.io/beryju/guacd:1.5.3 +FROM ghcr.io/beryju/guacd:1.5.5-fips ARG GIT_BUILD_HASH ENV GIT_BUILD_HASH=$GIT_BUILD_HASH @@ -35,4 +48,6 @@ HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/rac", "healthch USER 1000 +ENV GOFIPS=1 + ENTRYPOINT ["/rac"] diff --git a/radius.Dockerfile b/radius.Dockerfile index 5113a7eeb2..f1e0f8dceb 100644 --- a/radius.Dockerfile +++ b/radius.Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # Stage 1: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.6-bookworm AS builder +FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.22-fips-bookworm AS builder ARG TARGETOS ARG TARGETARCH @@ -12,20 +12,26 @@ ARG GOARCH=$TARGETARCH WORKDIR /go/src/goauthentik.io +RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \ + dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu + RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \ --mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \ --mount=type=bind,target=/go/src/goauthentik.io/gen-go-api,src=./gen-go-api \ --mount=type=cache,target=/go/pkg/mod \ go mod download -ENV CGO_ENABLED=0 COPY . . RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \ --mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \ - GOARM="${TARGETVARIANT#v}" go build -o /go/radius ./cmd/radius + if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \ + CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \ + go build -o /go/radius ./cmd/radius # Stage 2: Run -FROM gcr.io/distroless/static-debian11:debug +FROM ghcr.io/goauthentik/fips-debian:bookworm-slim-fips ARG GIT_BUILD_HASH ENV GIT_BUILD_HASH=$GIT_BUILD_HASH @@ -44,4 +50,6 @@ EXPOSE 1812/udp 9300 USER 1000 +ENV GOFIPS=1 + ENTRYPOINT ["/radius"] diff --git a/schema.yml b/schema.yml index c4f1e8484c..63fe3e299b 100644 --- a/schema.yml +++ b/schema.yml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: title: authentik - version: 2023.10.6 + version: 2024.4.2 description: Making authentication simple. contact: email: hello@goauthentik.io @@ -2658,6 +2658,10 @@ paths: operationId: core_applications_list description: Custom list method that checks Policy based access instead of guardian parameters: + - in: query + name: for_user + schema: + type: integer - in: query name: group schema: @@ -2931,8 +2935,6 @@ paths: schema: $ref: '#/components/schemas/PolicyTestResult' description: '' - '404': - description: for_user user not found '400': content: application/json: @@ -3609,6 +3611,11 @@ paths: schema: type: string description: Attributes + - in: query + name: include_users + schema: + type: boolean + default: true - in: query name: is_superuser schema: @@ -3726,6 +3733,11 @@ paths: format: uuid description: A UUID string identifying this Group. required: true + - in: query + name: include_users + schema: + type: boolean + default: true tags: - core security: @@ -4004,11 +4016,6 @@ paths: - app_password - recovery - verification - description: |- - * `verification` - Intent Verification - * `api` - Intent Api - * `recovery` - Intent Recovery - * `app_password` - Intent App Password - in: query name: managed schema: @@ -4674,6 +4681,11 @@ paths: format: uuid explode: true style: form + - in: query + name: include_groups + schema: + type: boolean + default: true - in: query name: is_active schema: @@ -4729,11 +4741,6 @@ paths: - internal - internal_service_account - service_account - description: |- - * `internal` - Internal - * `external` - External - * `service_account` - Service Account - * `internal_service_account` - Internal Service Account explode: true style: form - in: query @@ -5007,8 +5014,8 @@ paths: $ref: '#/components/schemas/GenericError' description: '' /core/users/{id}/recovery/: - get: - operationId: core_users_recovery_retrieve + post: + operationId: core_users_recovery_create description: Create a temporary link that a user can use to recover their accounts parameters: - in: path @@ -5028,12 +5035,6 @@ paths: schema: $ref: '#/components/schemas/Link' description: '' - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/Link' - description: '' '400': content: application/json: @@ -5047,8 +5048,8 @@ paths: $ref: '#/components/schemas/GenericError' description: '' /core/users/{id}/recovery_email/: - get: - operationId: core_users_recovery_email_retrieve + post: + operationId: core_users_recovery_email_create description: Create a temporary link that a user can use to recover their accounts parameters: - in: query @@ -5069,8 +5070,6 @@ paths: responses: '204': description: Successfully sent recover email - '404': - description: Bad request '400': content: application/json: @@ -6512,10 +6511,6 @@ paths: - alert - notice - warning - description: |- - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert - in: query name: user schema: @@ -6791,12 +6786,9 @@ paths: - alert - notice - warning - description: |- + description: |+ Controls which severity level the created notifications will have. - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert tags: - events security: @@ -7075,11 +7067,6 @@ paths: - successful - unknown - warning - description: |- - * `unknown` - Unknown - * `successful` - Successful - * `warning` - Warning - * `error` - Error - in: query name: uid schema: @@ -7191,11 +7178,6 @@ paths: - local - webhook - webhook_slack - description: |- - * `local` - authentik inbuilt notifications - * `webhook` - Generic Webhook - * `webhook_slack` - Slack Webhook (Slack/Discord) - * `email` - Email - in: query name: name schema: @@ -7529,12 +7511,9 @@ paths: - restart - restart_with_context - retry - description: |- + description: |+ Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. - * `retry` - Retry - * `restart` - Restart - * `restart_with_context` - Restart With Context - in: query name: order schema: @@ -7578,9 +7557,6 @@ paths: enum: - all - any - description: |- - * `all` - all, all policies must pass - * `any` - any, any policy must pass - in: query name: re_evaluate_policies schema: @@ -7964,12 +7940,9 @@ paths: - continue - message - message_continue - description: |- + description: |+ Configure what should happen when a flow denies access to a user. - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue - in: query name: designation schema: @@ -7982,16 +7955,9 @@ paths: - recovery - stage_configuration - unenrollment - description: |- + description: |+ Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration - in: query name: flow_uuid schema: @@ -10194,7 +10160,7 @@ paths: /outposts/service_connections/all/types/: get: operationId: outposts_service_connections_all_types_list - description: Get all creatable service connection types + description: Get all creatable types tags: - outposts security: @@ -11028,7 +10994,7 @@ paths: /policies/all/types/: get: operationId: policies_all_types_list - description: Get all creatable policy types + description: Get all creatable types tags: - policies security: @@ -11692,36 +11658,9 @@ paths: - system_task_execution - update_available - user_write - description: |- + description: |+ Match created events with this action type. When left empty, all action types will be matched. - * `login` - Login - * `login_failed` - Login Failed - * `logout` - Logout - * `user_write` - User Write - * `suspicious_request` - Suspicious Request - * `password_set` - Password Set - * `secret_view` - Secret View - * `secret_rotate` - Secret Rotate - * `invitation_used` - Invite Used - * `authorize_application` - Authorize Application - * `source_linked` - Source Linked - * `impersonation_started` - Impersonation Started - * `impersonation_ended` - Impersonation Ended - * `flow_execution` - Flow Execution - * `policy_execution` - Policy Execution - * `policy_exception` - Policy Exception - * `property_mapping_exception` - Property Mapping Exception - * `system_task_execution` - System Task Execution - * `system_task_exception` - System Task Exception - * `system_exception` - System Exception - * `configuration_error` - Configuration Error - * `model_created` - Model Created - * `model_updated` - Model Updated - * `model_deleted` - Model Deleted - * `email_sent` - Email Sent - * `update_available` - Update Available - * `custom_` - Custom Prefix - in: query name: app schema: @@ -13554,8 +13493,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PolicyTestRequest' - required: true + $ref: '#/components/schemas/PropertyMappingTestRequest' security: - authentik: [] responses: @@ -13613,7 +13551,7 @@ paths: /propertymappings/all/types/: get: operationId: propertymappings_all_types_list - description: Get all creatable property-mapping types + description: Get all creatable types tags: - propertymappings security: @@ -14198,6 +14136,578 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /propertymappings/provider/google_workspace/: + get: + operationId: propertymappings_provider_google_workspace_list + description: GoogleWorkspaceProviderMapping Viewset + parameters: + - in: query + name: expression + schema: + type: string + - in: query + name: managed + schema: + type: array + items: + type: string + explode: true + style: form + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: pm_uuid + schema: + type: string + format: uuid + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedGoogleWorkspaceProviderMappingList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: propertymappings_provider_google_workspace_create + description: GoogleWorkspaceProviderMapping Viewset + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMappingRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /propertymappings/provider/google_workspace/{pm_uuid}/: + get: + operationId: propertymappings_provider_google_workspace_retrieve + description: GoogleWorkspaceProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: propertymappings_provider_google_workspace_update + description: GoogleWorkspaceProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Mapping. + required: true + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMappingRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: propertymappings_provider_google_workspace_partial_update + description: GoogleWorkspaceProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Mapping. + required: true + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedGoogleWorkspaceProviderMappingRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: propertymappings_provider_google_workspace_destroy + description: GoogleWorkspaceProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /propertymappings/provider/google_workspace/{pm_uuid}/used_by/: + get: + operationId: propertymappings_provider_google_workspace_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /propertymappings/provider/microsoft_entra/: + get: + operationId: propertymappings_provider_microsoft_entra_list + description: MicrosoftEntraProviderMapping Viewset + parameters: + - in: query + name: expression + schema: + type: string + - in: query + name: managed + schema: + type: array + items: + type: string + explode: true + style: form + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: pm_uuid + schema: + type: string + format: uuid + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedMicrosoftEntraProviderMappingList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: propertymappings_provider_microsoft_entra_create + description: MicrosoftEntraProviderMapping Viewset + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMappingRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /propertymappings/provider/microsoft_entra/{pm_uuid}/: + get: + operationId: propertymappings_provider_microsoft_entra_retrieve + description: MicrosoftEntraProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: propertymappings_provider_microsoft_entra_update + description: MicrosoftEntraProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Mapping. + required: true + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMappingRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: propertymappings_provider_microsoft_entra_partial_update + description: MicrosoftEntraProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Mapping. + required: true + tags: + - propertymappings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedMicrosoftEntraProviderMappingRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderMapping' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: propertymappings_provider_microsoft_entra_destroy + description: MicrosoftEntraProviderMapping Viewset + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /propertymappings/provider/microsoft_entra/{pm_uuid}/used_by/: + get: + operationId: propertymappings_provider_microsoft_entra_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /propertymappings/rac/: get: operationId: propertymappings_rac_list @@ -15346,9 +15856,12 @@ paths: schema: type: boolean - in: query - name: backchannel_only + name: backchannel schema: type: boolean + description: When not set all providers are returned. When set to true, only + backchannel providers are returned. When set to false, backchannel providers + are excluded - name: ordering required: false in: query @@ -15498,7 +16011,7 @@ paths: /providers/all/types/: get: operationId: providers_all_types_list - description: Get all creatable provider types + description: Get all creatable types tags: - providers security: @@ -15524,6 +16037,874 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /providers/google_workspace/: + get: + operationId: providers_google_workspace_list + description: GoogleWorkspaceProvider Viewset + parameters: + - in: query + name: delegated_subject + schema: + type: string + - in: query + name: exclude_users_service_account + schema: + type: boolean + - in: query + name: filter_group + schema: + type: string + format: uuid + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedGoogleWorkspaceProviderList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_google_workspace_create + description: GoogleWorkspaceProvider Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace/{id}/: + get: + operationId: providers_google_workspace_retrieve + description: GoogleWorkspaceProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_google_workspace_update + description: GoogleWorkspaceProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_google_workspace_partial_update + description: GoogleWorkspaceProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedGoogleWorkspaceProviderRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_google_workspace_destroy + description: GoogleWorkspaceProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace/{id}/sync/status/: + get: + operationId: providers_google_workspace_sync_status_retrieve + description: Get provider's sync status + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SyncStatus' + description: '' + '404': + description: Task not found + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace/{id}/used_by/: + get: + operationId: providers_google_workspace_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Google Workspace Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_groups/: + get: + operationId: providers_google_workspace_groups_list + description: GoogleWorkspaceProviderGroup Viewset + parameters: + - in: query + name: group__group_uuid + schema: + type: string + format: uuid + - in: query + name: group__name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: provider__id + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedGoogleWorkspaceProviderGroupList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_google_workspace_groups_create + description: GoogleWorkspaceProviderGroup Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroupRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_groups/{id}/: + get: + operationId: providers_google_workspace_groups_retrieve + description: GoogleWorkspaceProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_google_workspace_groups_update + description: GoogleWorkspaceProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Group. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroupRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_google_workspace_groups_partial_update + description: GoogleWorkspaceProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Group. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedGoogleWorkspaceProviderGroupRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_google_workspace_groups_destroy + description: GoogleWorkspaceProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_groups/{id}/used_by/: + get: + operationId: providers_google_workspace_groups_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_users/: + get: + operationId: providers_google_workspace_users_list + description: GoogleWorkspaceProviderUser Viewset + parameters: + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: provider__id + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: user__id + schema: + type: integer + - in: query + name: user__username + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedGoogleWorkspaceProviderUserList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_google_workspace_users_create + description: GoogleWorkspaceProviderUser Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUserRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_users/{id}/: + get: + operationId: providers_google_workspace_users_retrieve + description: GoogleWorkspaceProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_google_workspace_users_update + description: GoogleWorkspaceProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider User. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUserRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_google_workspace_users_partial_update + description: GoogleWorkspaceProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider User. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedGoogleWorkspaceProviderUserRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GoogleWorkspaceProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_google_workspace_users_destroy + description: GoogleWorkspaceProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/google_workspace_users/{id}/used_by/: + get: + operationId: providers_google_workspace_users_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Google Workspace Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /providers/ldap/: get: operationId: providers_ldap_list @@ -15830,6 +17211,870 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /providers/microsoft_entra/: + get: + operationId: providers_microsoft_entra_list + description: MicrosoftEntraProvider Viewset + parameters: + - in: query + name: exclude_users_service_account + schema: + type: boolean + - in: query + name: filter_group + schema: + type: string + format: uuid + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedMicrosoftEntraProviderList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_microsoft_entra_create + description: MicrosoftEntraProvider Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra/{id}/: + get: + operationId: providers_microsoft_entra_retrieve + description: MicrosoftEntraProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_microsoft_entra_update + description: MicrosoftEntraProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_microsoft_entra_partial_update + description: MicrosoftEntraProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedMicrosoftEntraProviderRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProvider' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_microsoft_entra_destroy + description: MicrosoftEntraProvider Viewset + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra/{id}/sync/status/: + get: + operationId: providers_microsoft_entra_sync_status_retrieve + description: Get provider's sync status + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SyncStatus' + description: '' + '404': + description: Task not found + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra/{id}/used_by/: + get: + operationId: providers_microsoft_entra_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Microsoft Entra Provider. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_groups/: + get: + operationId: providers_microsoft_entra_groups_list + description: MicrosoftEntraProviderGroup Viewset + parameters: + - in: query + name: group__group_uuid + schema: + type: string + format: uuid + - in: query + name: group__name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: provider__id + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedMicrosoftEntraProviderGroupList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_microsoft_entra_groups_create + description: MicrosoftEntraProviderGroup Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroupRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_groups/{id}/: + get: + operationId: providers_microsoft_entra_groups_retrieve + description: MicrosoftEntraProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_microsoft_entra_groups_update + description: MicrosoftEntraProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Group. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroupRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_microsoft_entra_groups_partial_update + description: MicrosoftEntraProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Group. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedMicrosoftEntraProviderGroupRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_microsoft_entra_groups_destroy + description: MicrosoftEntraProviderGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_groups/{id}/used_by/: + get: + operationId: providers_microsoft_entra_groups_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider Group. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_users/: + get: + operationId: providers_microsoft_entra_users_list + description: MicrosoftEntraProviderUser Viewset + parameters: + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: provider__id + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: user__id + schema: + type: integer + - in: query + name: user__username + schema: + type: string + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedMicrosoftEntraProviderUserList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: providers_microsoft_entra_users_create + description: MicrosoftEntraProviderUser Viewset + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUserRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_users/{id}/: + get: + operationId: providers_microsoft_entra_users_retrieve + description: MicrosoftEntraProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: providers_microsoft_entra_users_update + description: MicrosoftEntraProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider User. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUserRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: providers_microsoft_entra_users_partial_update + description: MicrosoftEntraProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider User. + required: true + tags: + - providers + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedMicrosoftEntraProviderUserRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MicrosoftEntraProviderUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: providers_microsoft_entra_users_destroy + description: MicrosoftEntraProviderUser Viewset + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /providers/microsoft_entra_users/{id}/used_by/: + get: + operationId: providers_microsoft_entra_users_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this Microsoft Entra Provider User. + required: true + tags: + - providers + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /providers/oauth2/: get: operationId: providers_oauth2_list @@ -15864,11 +18109,9 @@ paths: enum: - confidential - public - description: |- + description: |+ Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable - * `confidential` - Confidential - * `public` - Public - in: query name: include_claims_in_id_token schema: @@ -15880,11 +18123,9 @@ paths: enum: - global - per_provider - description: |- + description: |+ Configure how the issuer field of the ID Token should be filled. - * `global` - Same identifier is used for all providers - * `per_provider` - Each provider has a different issuer, based on the application slug. - in: query name: name schema: @@ -15946,15 +18187,9 @@ paths: - user_upn - user_username - user_uuid - description: |- + description: |+ Configure what data should be used as unique User Identifier. For most cases, the default should be fine. - * `hashed_user_id` - Based on the Hashed User ID - * `user_id` - Based on user ID - * `user_uuid` - Based on user UUID - * `user_username` - Based on the username - * `user_email` - Based on the User's Email. This is recommended over the UPN method. - * `user_upn` - Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. tags: - providers security: @@ -16155,6 +18390,10 @@ paths: operationId: providers_oauth2_preview_user_retrieve description: Preview user data for provider parameters: + - in: query + name: for_user + schema: + type: integer - in: path name: id schema: @@ -17175,11 +19414,6 @@ paths: - http://www.w3.org/2001/04/xmldsig-more#sha384 - http://www.w3.org/2001/04/xmlenc#sha256 - http://www.w3.org/2001/04/xmlenc#sha512 - description: |- - * `http://www.w3.org/2000/09/xmldsig#sha1` - SHA1 - * `http://www.w3.org/2001/04/xmlenc#sha256` - SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#sha384` - SHA384 - * `http://www.w3.org/2001/04/xmlenc#sha512` - SHA512 - in: query name: is_backchannel schema: @@ -17241,15 +19475,13 @@ paths: enum: - http://www.w3.org/2000/09/xmldsig#dsa-sha1 - http://www.w3.org/2000/09/xmldsig#rsa-sha1 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha384 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 - description: |- - * `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - RSA-SHA1 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256` - RSA-SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384` - RSA-SHA384 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512` - RSA-SHA512 - * `http://www.w3.org/2000/09/xmldsig#dsa-sha1` - DSA-SHA1 - in: query name: signing_kp schema: @@ -17263,11 +19495,9 @@ paths: enum: - post - redirect - description: |- + description: |+ This determines how authentik sends the response back to the Service Provider. - * `redirect` - Redirect - * `post` - Post - in: query name: verification_kp schema: @@ -17522,6 +19752,10 @@ paths: operationId: providers_saml_preview_user_retrieve description: Preview user data for provider parameters: + - in: query + name: for_user + schema: + type: integer - in: path name: id schema: @@ -17849,7 +20083,7 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' - /providers/scim/{id}/sync_status/: + /providers/scim/{id}/sync/status/: get: operationId: providers_scim_sync_status_retrieve description: Get provider's sync status @@ -17869,7 +20103,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/SCIMSyncStatus' + $ref: '#/components/schemas/SyncStatus' description: '' '404': description: Task not found @@ -17921,6 +20155,252 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /rac/connection_tokens/: + get: + operationId: rac_connection_tokens_list + description: ConnectionToken Viewset + parameters: + - in: query + name: endpoint + schema: + type: string + format: uuid + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: provider + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: session__user + schema: + type: integer + tags: + - rac + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedConnectionTokenList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /rac/connection_tokens/{connection_token_uuid}/: + get: + operationId: rac_connection_tokens_retrieve + description: ConnectionToken Viewset + parameters: + - in: path + name: connection_token_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this RAC Connection token. + required: true + tags: + - rac + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionToken' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: rac_connection_tokens_update + description: ConnectionToken Viewset + parameters: + - in: path + name: connection_token_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this RAC Connection token. + required: true + tags: + - rac + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionTokenRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionToken' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: rac_connection_tokens_partial_update + description: ConnectionToken Viewset + parameters: + - in: path + name: connection_token_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this RAC Connection token. + required: true + tags: + - rac + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedConnectionTokenRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionToken' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: rac_connection_tokens_destroy + description: ConnectionToken Viewset + parameters: + - in: path + name: connection_token_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this RAC Connection token. + required: true + tags: + - rac + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /rac/connection_tokens/{connection_token_uuid}/used_by/: + get: + operationId: rac_connection_tokens_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: connection_token_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this RAC Connection token. + required: true + tags: + - rac + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /rac/endpoints/: get: operationId: rac_endpoints_list @@ -18333,7 +20813,11 @@ paths: - authentik_policies_expression.expressionpolicy - authentik_policies_password.passwordpolicy - authentik_policies_reputation.reputationpolicy + - authentik_providers_google_workspace.googleworkspaceprovider + - authentik_providers_google_workspace.googleworkspaceprovidermapping - authentik_providers_ldap.ldapprovider + - authentik_providers_microsoft_entra.microsoftentraprovider + - authentik_providers_microsoft_entra.microsoftentraprovidermapping - authentik_providers_oauth2.oauth2provider - authentik_providers_oauth2.scopemapping - authentik_providers_proxy.proxyprovider @@ -18354,6 +20838,7 @@ paths: - authentik_sources_plex.plexsourceconnection - authentik_sources_saml.samlsource - authentik_sources_saml.usersamlsourceconnection + - authentik_sources_scim.scimsource - authentik_stages_authenticator_duo.authenticatorduostage - authentik_stages_authenticator_duo.duodevice - authentik_stages_authenticator_sms.authenticatorsmsstage @@ -18363,7 +20848,7 @@ paths: - authentik_stages_authenticator_totp.authenticatortotpstage - authentik_stages_authenticator_totp.totpdevice - authentik_stages_authenticator_validate.authenticatorvalidatestage - - authentik_stages_authenticator_webauthn.authenticatewebauthnstage + - authentik_stages_authenticator_webauthn.authenticatorwebauthnstage - authentik_stages_authenticator_webauthn.webauthndevice - authentik_stages_captcha.captchastage - authentik_stages_consent.consentstage @@ -18377,86 +20862,12 @@ paths: - authentik_stages_password.passwordstage - authentik_stages_prompt.prompt - authentik_stages_prompt.promptstage + - authentik_stages_source.sourcestage - authentik_stages_user_delete.userdeletestage - authentik_stages_user_login.userloginstage - authentik_stages_user_logout.userlogoutstage - authentik_stages_user_write.userwritestage - authentik_tenants.domain - description: |- - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping required: true - in: query name: object_pk @@ -18621,7 +21032,11 @@ paths: - authentik_policies_expression.expressionpolicy - authentik_policies_password.passwordpolicy - authentik_policies_reputation.reputationpolicy + - authentik_providers_google_workspace.googleworkspaceprovider + - authentik_providers_google_workspace.googleworkspaceprovidermapping - authentik_providers_ldap.ldapprovider + - authentik_providers_microsoft_entra.microsoftentraprovider + - authentik_providers_microsoft_entra.microsoftentraprovidermapping - authentik_providers_oauth2.oauth2provider - authentik_providers_oauth2.scopemapping - authentik_providers_proxy.proxyprovider @@ -18642,6 +21057,7 @@ paths: - authentik_sources_plex.plexsourceconnection - authentik_sources_saml.samlsource - authentik_sources_saml.usersamlsourceconnection + - authentik_sources_scim.scimsource - authentik_stages_authenticator_duo.authenticatorduostage - authentik_stages_authenticator_duo.duodevice - authentik_stages_authenticator_sms.authenticatorsmsstage @@ -18651,7 +21067,7 @@ paths: - authentik_stages_authenticator_totp.authenticatortotpstage - authentik_stages_authenticator_totp.totpdevice - authentik_stages_authenticator_validate.authenticatorvalidatestage - - authentik_stages_authenticator_webauthn.authenticatewebauthnstage + - authentik_stages_authenticator_webauthn.authenticatorwebauthnstage - authentik_stages_authenticator_webauthn.webauthndevice - authentik_stages_captcha.captchastage - authentik_stages_consent.consentstage @@ -18665,86 +21081,12 @@ paths: - authentik_stages_password.passwordstage - authentik_stages_prompt.prompt - authentik_stages_prompt.promptstage + - authentik_stages_source.sourcestage - authentik_stages_user_delete.userdeletestage - authentik_stages_user_login.userloginstage - authentik_stages_user_logout.userlogoutstage - authentik_stages_user_write.userwritestage - authentik_tenants.domain - description: |- - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping required: true - in: query name: object_pk @@ -19668,7 +22010,7 @@ paths: /sources/all/types/: get: operationId: sources_all_types_list - description: Get all creatable source types + description: Get all creatable types tags: - sources security: @@ -19787,6 +22129,10 @@ paths: description: Number of results to return per page. schema: type: integer + - in: query + name: password_login_update_internal_password + schema: + type: boolean - in: query name: peer_certificate schema: @@ -20082,7 +22428,7 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' - /sources/ldap/{slug}/sync_status/: + /sources/ldap/{slug}/sync/status/: get: operationId: sources_ldap_sync_status_retrieve description: Get source's sync status @@ -20102,7 +22448,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/LDAPSyncStatus' + $ref: '#/components/schemas/SyncStatus' description: '' '400': content: @@ -20221,9 +22567,6 @@ paths: enum: - all - any - description: |- - * `all` - all, all policies must pass - * `any` - any, any policy must pass - in: query name: profile_url schema: @@ -20256,14 +22599,9 @@ paths: - identifier - username_deny - username_link - description: |- + description: |+ How the source determines if an existing user should be authenticated or a new user enrolled. - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. tags: - sources security: @@ -20587,9 +22925,6 @@ paths: enum: - all - any - description: |- - * `all` - all, all policies must pass - * `any` - any, any policy must pass - name: search required: false in: query @@ -20610,14 +22945,9 @@ paths: - identifier - username_deny - username_link - description: |- + description: |+ How the source determines if an existing user should be authenticated or a new user enrolled. - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. tags: - sources security: @@ -20930,10 +23260,6 @@ paths: - POST - POST_AUTO - REDIRECT - description: |- - * `REDIRECT` - Redirect Binding - * `POST` - POST Binding - * `POST_AUTO` - POST Binding with auto-confirmation - in: query name: digest_algorithm schema: @@ -20943,11 +23269,6 @@ paths: - http://www.w3.org/2001/04/xmldsig-more#sha384 - http://www.w3.org/2001/04/xmlenc#sha256 - http://www.w3.org/2001/04/xmlenc#sha512 - description: |- - * `http://www.w3.org/2000/09/xmldsig#sha1` - SHA1 - * `http://www.w3.org/2001/04/xmlenc#sha256` - SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#sha384` - SHA384 - * `http://www.w3.org/2001/04/xmlenc#sha512` - SHA512 - in: query name: enabled schema: @@ -20979,14 +23300,9 @@ paths: - urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName - urn:oasis:names:tc:SAML:2.0:nameid-format:persistent - urn:oasis:names:tc:SAML:2.0:nameid-format:transient - description: |- + description: |+ NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. - * `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` - Email - * `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` - Persistent - * `urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName` - X509 - * `urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName` - Windows - * `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient - name: ordering required: false in: query @@ -21012,9 +23328,6 @@ paths: enum: - all - any - description: |- - * `all` - all, all policies must pass - * `any` - any, any policy must pass - in: query name: pre_authentication_flow schema: @@ -21033,15 +23346,13 @@ paths: enum: - http://www.w3.org/2000/09/xmldsig#dsa-sha1 - http://www.w3.org/2000/09/xmldsig#rsa-sha1 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha384 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 - description: |- - * `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - RSA-SHA1 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256` - RSA-SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384` - RSA-SHA384 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512` - RSA-SHA512 - * `http://www.w3.org/2000/09/xmldsig#dsa-sha1` - DSA-SHA1 - in: query name: signing_kp schema: @@ -21073,14 +23384,9 @@ paths: - identifier - username_deny - username_link - description: |- + description: |+ How the source determines if an existing user should be authenticated or a new user enrolled. - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. - in: query name: verification_kp schema: @@ -21351,6 +23657,819 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /sources/scim/: + get: + operationId: sources_scim_list + description: SCIMSource Viewset + parameters: + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: slug + schema: + type: string + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSCIMSourceList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: sources_scim_create + description: SCIMSource Viewset + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSource' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim/{slug}/: + get: + operationId: sources_scim_retrieve + description: SCIMSource Viewset + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSource' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: sources_scim_update + description: SCIMSource Viewset + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSource' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: sources_scim_partial_update + description: SCIMSource Viewset + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedSCIMSourceRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSource' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: sources_scim_destroy + description: SCIMSource Viewset + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim/{slug}/used_by/: + get: + operationId: sources_scim_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_groups/: + get: + operationId: sources_scim_groups_list + description: SCIMSourceGroup Viewset + parameters: + - in: query + name: group__group_uuid + schema: + type: string + format: uuid + - in: query + name: group__name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: source__slug + schema: + type: string + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSCIMSourceGroupList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: sources_scim_groups_create + description: SCIMSourceGroup Viewset + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroupRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_groups/{id}/: + get: + operationId: sources_scim_groups_retrieve + description: SCIMSourceGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source group. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: sources_scim_groups_update + description: SCIMSourceGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source group. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroupRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: sources_scim_groups_partial_update + description: SCIMSourceGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source group. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedSCIMSourceGroupRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceGroup' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: sources_scim_groups_destroy + description: SCIMSourceGroup Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source group. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_groups/{id}/used_by/: + get: + operationId: sources_scim_groups_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source group. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_users/: + get: + operationId: sources_scim_users_list + description: SCIMSourceUser Viewset + parameters: + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: source__slug + schema: + type: string + - in: query + name: user__id + schema: + type: integer + - in: query + name: user__username + schema: + type: string + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSCIMSourceUserList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: sources_scim_users_create + description: SCIMSourceUser Viewset + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUserRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_users/{id}/: + get: + operationId: sources_scim_users_retrieve + description: SCIMSourceUser Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source user. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: sources_scim_users_update + description: SCIMSourceUser Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source user. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUserRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: sources_scim_users_partial_update + description: SCIMSourceUser Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source user. + required: true + tags: + - sources + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedSCIMSourceUserRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SCIMSourceUser' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: sources_scim_users_destroy + description: SCIMSourceUser Viewset + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source user. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /sources/scim_users/{id}/used_by/: + get: + operationId: sources_scim_users_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: string + description: A unique value identifying this scim source user. + required: true + tags: + - sources + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /sources/user_connections/all/: get: operationId: sources_user_connections_all_list @@ -22525,7 +25644,7 @@ paths: /stages/all/types/: get: operationId: stages_all_types_list - description: Get all creatable stage types + description: Get all creatable types tags: - stages security: @@ -22985,9 +26104,6 @@ paths: enum: - basic - bearer - description: |- - * `basic` - Basic - * `bearer` - Bearer - in: query name: configure_flow schema: @@ -23035,9 +26151,6 @@ paths: enum: - generic - twilio - description: |- - * `twilio` - Twilio - * `generic` - Generic - name: search required: false in: query @@ -23597,9 +26710,6 @@ paths: enum: - '6' - '8' - description: |- - * `6` - 6 digits, widely compatible - * `8` - 8 digits, not compatible with apps like Google Authenticator - in: query name: friendly_name schema: @@ -23899,10 +27009,6 @@ paths: - configure - deny - skip - description: |- - * `skip` - Skip - * `deny` - Deny - * `configure` - Configure - name: ordering required: false in: query @@ -24166,7 +27272,7 @@ paths: /stages/authenticator/webauthn/: get: operationId: stages_authenticator_webauthn_list - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset parameters: - in: query name: authenticator_attachment @@ -24176,14 +27282,20 @@ paths: enum: - cross-platform - platform - description: |- - * `platform` - Platform - * `cross-platform` - Cross Platform - in: query name: configure_flow schema: type: string format: uuid + - in: query + name: device_type_restrictions + schema: + type: array + items: + type: string + format: uuid + explode: true + style: form - in: query name: friendly_name schema: @@ -24218,10 +27330,6 @@ paths: - discouraged - preferred - required - description: |- - * `discouraged` - Discouraged - * `preferred` - Preferred - * `required` - Required - name: search required: false in: query @@ -24241,10 +27349,6 @@ paths: - discouraged - preferred - required - description: |- - * `required` - Required - * `preferred` - Preferred - * `discouraged` - Discouraged tags: - stages security: @@ -24254,7 +27358,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PaginatedAuthenticateWebAuthnStageList' + $ref: '#/components/schemas/PaginatedAuthenticatorWebAuthnStageList' description: '' '400': content: @@ -24270,14 +27374,14 @@ paths: description: '' post: operationId: stages_authenticator_webauthn_create - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset tags: - stages requestBody: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStageRequest' + $ref: '#/components/schemas/AuthenticatorWebAuthnStageRequest' required: true security: - authentik: [] @@ -24286,7 +27390,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStage' + $ref: '#/components/schemas/AuthenticatorWebAuthnStage' description: '' '400': content: @@ -24303,7 +27407,7 @@ paths: /stages/authenticator/webauthn/{stage_uuid}/: get: operationId: stages_authenticator_webauthn_retrieve - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset parameters: - in: path name: stage_uuid @@ -24321,7 +27425,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStage' + $ref: '#/components/schemas/AuthenticatorWebAuthnStage' description: '' '400': content: @@ -24337,7 +27441,7 @@ paths: description: '' put: operationId: stages_authenticator_webauthn_update - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset parameters: - in: path name: stage_uuid @@ -24352,7 +27456,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStageRequest' + $ref: '#/components/schemas/AuthenticatorWebAuthnStageRequest' required: true security: - authentik: [] @@ -24361,7 +27465,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStage' + $ref: '#/components/schemas/AuthenticatorWebAuthnStage' description: '' '400': content: @@ -24377,7 +27481,7 @@ paths: description: '' patch: operationId: stages_authenticator_webauthn_partial_update - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset parameters: - in: path name: stage_uuid @@ -24392,7 +27496,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PatchedAuthenticateWebAuthnStageRequest' + $ref: '#/components/schemas/PatchedAuthenticatorWebAuthnStageRequest' security: - authentik: [] responses: @@ -24400,7 +27504,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthenticateWebAuthnStage' + $ref: '#/components/schemas/AuthenticatorWebAuthnStage' description: '' '400': content: @@ -24416,7 +27520,7 @@ paths: description: '' delete: operationId: stages_authenticator_webauthn_destroy - description: AuthenticateWebAuthnStage Viewset + description: AuthenticatorWebAuthnStage Viewset parameters: - in: path name: stage_uuid @@ -24481,6 +27585,106 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /stages/authenticator/webauthn_device_types/: + get: + operationId: stages_authenticator_webauthn_device_types_list + description: WebAuthnDeviceType Viewset + parameters: + - in: query + name: aaguid + schema: + type: string + format: uuid + - in: query + name: description + schema: + type: string + - in: query + name: icon + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: search + required: false + in: query + description: A search term. + schema: + type: string + tags: + - stages + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedWebAuthnDeviceTypeList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /stages/authenticator/webauthn_device_types/{aaguid}/: + get: + operationId: stages_authenticator_webauthn_device_types_retrieve + description: WebAuthnDeviceType Viewset + parameters: + - in: path + name: aaguid + schema: + type: string + format: uuid + description: A UUID string identifying this WebAuthn Device type. + required: true + tags: + - stages + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/WebAuthnDeviceType' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /stages/captcha/: get: operationId: stages_captcha_list @@ -24771,10 +27975,6 @@ paths: - always_require - expiring - permanent - description: |- - * `always_require` - Always Require - * `permanent` - Permanent - * `expiring` - Expiring - in: query name: name schema: @@ -27157,25 +30357,6 @@ paths: - text_area_read_only - text_read_only - username - description: |- - * `text` - Text: Simple Text input - * `text_area` - Text area: Multiline Text Input. - * `text_read_only` - Text (read-only): Simple Text input, but cannot be edited. - * `text_area_read_only` - Text area (read-only): Multiline Text input, but cannot be edited. - * `username` - Username: Same as Text input, but checks for and prevents duplicate usernames. - * `email` - Email: Text field with Email type. - * `password` - Password: Masked input, multiple inputs of this type on the same prompt need to be identical. - * `number` - Number - * `checkbox` - Checkbox - * `radio-button-group` - Fixed choice field rendered as a group of radio buttons. - * `dropdown` - Fixed choice field rendered as a dropdown. - * `date` - Date - * `date-time` - Date Time - * `file` - File: File upload for arbitrary files. File content will be available in flow context as data-URI - * `separator` - Separator: Static Separator Line - * `hidden` - Hidden: Hidden field, can be used to insert data into form. - * `static` - Static: Static value, displayed as-is. - * `ak-locale` - authentik: Selection of locales authentik supports tags: - stages security: @@ -27737,6 +30918,289 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /stages/source/: + get: + operationId: stages_source_list + description: SourceStage Viewset + parameters: + - in: query + name: name + schema: + type: string + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: page + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page_size + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - in: query + name: resume_timeout + schema: + type: string + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: source + schema: + type: string + format: uuid + - in: query + name: stage_uuid + schema: + type: string + format: uuid + tags: + - stages + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSourceStageList' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + post: + operationId: stages_source_create + description: SourceStage Viewset + tags: + - stages + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStageRequest' + required: true + security: + - authentik: [] + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStage' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /stages/source/{stage_uuid}/: + get: + operationId: stages_source_retrieve + description: SourceStage Viewset + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Source Stage. + required: true + tags: + - stages + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStage' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + put: + operationId: stages_source_update + description: SourceStage Viewset + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Source Stage. + required: true + tags: + - stages + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStageRequest' + required: true + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStage' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + patch: + operationId: stages_source_partial_update + description: SourceStage Viewset + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Source Stage. + required: true + tags: + - stages + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedSourceStageRequest' + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SourceStage' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + delete: + operationId: stages_source_destroy + description: SourceStage Viewset + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Source Stage. + required: true + tags: + - stages + security: + - authentik: [] + responses: + '204': + description: No response body + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' + /stages/source/{stage_uuid}/used_by/: + get: + operationId: stages_source_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Source Stage. + required: true + tags: + - stages + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /stages/user_delete/: get: operationId: stages_user_delete_list @@ -28025,13 +31489,9 @@ paths: - bind_continent_country - bind_continent_country_city - no_binding - description: |- + description: |+ Bind sessions created by this stage to the configured GeoIP location - * `no_binding` - No Binding - * `bind_continent` - Bind Continent - * `bind_continent_country` - Bind Continent Country - * `bind_continent_country_city` - Bind Continent Country City - in: query name: name schema: @@ -28045,13 +31505,9 @@ paths: - bind_asn_network - bind_asn_network_ip - no_binding - description: |- + description: |+ Bind sessions created by this stage to the configured network - * `no_binding` - No Binding - * `bind_asn` - Bind Asn - * `bind_asn_network` - Bind Asn Network - * `bind_asn_network_ip` - Bind Asn Network Ip - name: ordering required: false in: query @@ -28658,10 +32114,6 @@ paths: - always_create - create_when_required - never_create - description: |- - * `never_create` - Never Create - * `create_when_required` - Create When Required - * `always_create` - Always Create - in: query name: user_path_template schema: @@ -28675,11 +32127,6 @@ paths: - internal - internal_service_account - service_account - description: |- - * `internal` - Internal - * `external` - External - * `service_account` - Service Account - * `internal_service_account` - Internal Service Account tags: - stages security: @@ -29443,6 +32890,11 @@ components: - pending_user - pending_user_avatar - type + AlgEnum: + enum: + - rsa + - ecdsa + type: string App: type: object description: Serialize Application info @@ -29460,7 +32912,6 @@ components: - authentik.admin - authentik.api - authentik.crypto - - authentik.events - authentik.flows - authentik.outposts - authentik.policies.dummy @@ -29482,6 +32933,7 @@ components: - authentik.sources.oauth - authentik.sources.plex - authentik.sources.saml + - authentik.sources.scim - authentik.stages.authenticator - authentik.stages.authenticator_duo - authentik.stages.authenticator_sms @@ -29507,64 +32959,15 @@ components: - authentik.core - authentik.enterprise - authentik.enterprise.audit + - authentik.enterprise.providers.google_workspace + - authentik.enterprise.providers.microsoft_entra - authentik.enterprise.providers.rac + - authentik.enterprise.stages.source + - authentik.events type: string - description: |- - * `authentik.tenants` - authentik Tenants - * `authentik.admin` - authentik Admin - * `authentik.api` - authentik API - * `authentik.crypto` - authentik Crypto - * `authentik.events` - authentik Events - * `authentik.flows` - authentik Flows - * `authentik.outposts` - authentik Outpost - * `authentik.policies.dummy` - authentik Policies.Dummy - * `authentik.policies.event_matcher` - authentik Policies.Event Matcher - * `authentik.policies.expiry` - authentik Policies.Expiry - * `authentik.policies.expression` - authentik Policies.Expression - * `authentik.policies.password` - authentik Policies.Password - * `authentik.policies.reputation` - authentik Policies.Reputation - * `authentik.policies` - authentik Policies - * `authentik.providers.ldap` - authentik Providers.LDAP - * `authentik.providers.oauth2` - authentik Providers.OAuth2 - * `authentik.providers.proxy` - authentik Providers.Proxy - * `authentik.providers.radius` - authentik Providers.Radius - * `authentik.providers.saml` - authentik Providers.SAML - * `authentik.providers.scim` - authentik Providers.SCIM - * `authentik.rbac` - authentik RBAC - * `authentik.recovery` - authentik Recovery - * `authentik.sources.ldap` - authentik Sources.LDAP - * `authentik.sources.oauth` - authentik Sources.OAuth - * `authentik.sources.plex` - authentik Sources.Plex - * `authentik.sources.saml` - authentik Sources.SAML - * `authentik.stages.authenticator` - authentik Stages.Authenticator - * `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo - * `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS - * `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static - * `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP - * `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate - * `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn - * `authentik.stages.captcha` - authentik Stages.Captcha - * `authentik.stages.consent` - authentik Stages.Consent - * `authentik.stages.deny` - authentik Stages.Deny - * `authentik.stages.dummy` - authentik Stages.Dummy - * `authentik.stages.email` - authentik Stages.Email - * `authentik.stages.identification` - authentik Stages.Identification - * `authentik.stages.invitation` - authentik Stages.User Invitation - * `authentik.stages.password` - authentik Stages.Password - * `authentik.stages.prompt` - authentik Stages.Prompt - * `authentik.stages.user_delete` - authentik Stages.User Delete - * `authentik.stages.user_login` - authentik Stages.User Login - * `authentik.stages.user_logout` - authentik Stages.User Logout - * `authentik.stages.user_write` - authentik Stages.User Write - * `authentik.brands` - authentik Brands - * `authentik.blueprints` - authentik Blueprints - * `authentik.core` - authentik Core - * `authentik.enterprise` - authentik Enterprise - * `authentik.enterprise.audit` - authentik Enterprise.Audit - * `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC AppleChallengeResponseRequest: type: object - description: Pseudo class for plex response + description: Pseudo class for apple response properties: component: type: string @@ -29712,103 +33115,11 @@ components: - static - prompt type: string - description: |- - * `static` - Static - * `prompt` - Prompt AuthTypeEnum: enum: - basic - bearer type: string - description: |- - * `basic` - Basic - * `bearer` - Bearer - AuthenticateWebAuthnStage: - type: object - description: AuthenticateWebAuthnStage Serializer - properties: - pk: - type: string - format: uuid - readOnly: true - title: Stage uuid - name: - type: string - component: - type: string - description: Get object type so that we know how to edit the object - readOnly: true - verbose_name: - type: string - description: Return object's verbose_name - readOnly: true - verbose_name_plural: - type: string - description: Return object's plural verbose_name - readOnly: true - meta_model_name: - type: string - description: Return internal model name - readOnly: true - flow_set: - type: array - items: - $ref: '#/components/schemas/FlowSet' - configure_flow: - type: string - format: uuid - nullable: true - description: Flow used by an authenticated user to configure this Stage. - If empty, user will not be able to configure this stage. - friendly_name: - type: string - nullable: true - user_verification: - $ref: '#/components/schemas/UserVerificationEnum' - authenticator_attachment: - allOf: - - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' - nullable: true - resident_key_requirement: - $ref: '#/components/schemas/ResidentKeyRequirementEnum' - required: - - component - - meta_model_name - - name - - pk - - verbose_name - - verbose_name_plural - AuthenticateWebAuthnStageRequest: - type: object - description: AuthenticateWebAuthnStage Serializer - properties: - name: - type: string - minLength: 1 - flow_set: - type: array - items: - $ref: '#/components/schemas/FlowSetRequest' - configure_flow: - type: string - format: uuid - nullable: true - description: Flow used by an authenticated user to configure this Stage. - If empty, user will not be able to configure this stage. - friendly_name: - type: string - nullable: true - minLength: 1 - user_verification: - $ref: '#/components/schemas/UserVerificationEnum' - authenticator_attachment: - allOf: - - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' - nullable: true - resident_key_requirement: - $ref: '#/components/schemas/ResidentKeyRequirementEnum' - required: - - name AuthenticatedSession: type: object description: AuthenticatedSession Serializer @@ -29938,6 +33249,7 @@ components: expires: type: string format: date-time + nullable: true required: - asn - current @@ -29954,20 +33266,11 @@ components: - require_superuser - require_outpost type: string - description: |- - * `none` - None - * `require_authenticated` - Require Authenticated - * `require_unauthenticated` - Require Unauthenticated - * `require_superuser` - Require Superuser - * `require_outpost` - Require Outpost AuthenticatorAttachmentEnum: enum: - platform - cross-platform type: string - description: |- - * `platform` - Platform - * `cross-platform` - Cross Platform AuthenticatorDuoChallenge: type: object description: Duo Challenge @@ -30589,12 +33892,17 @@ components: webauthn_user_verification: allOf: - $ref: '#/components/schemas/UserVerificationEnum' - description: |- - Enforce user verification for WebAuthn devices. - - * `required` - Required - * `preferred` - Preferred - * `discouraged` - Discouraged + description: Enforce user verification for WebAuthn devices. + webauthn_allowed_device_types: + type: array + items: + type: string + format: uuid + webauthn_allowed_device_types_obj: + type: array + items: + $ref: '#/components/schemas/WebAuthnDeviceType' + readOnly: true required: - component - meta_model_name @@ -30602,6 +33910,7 @@ components: - pk - verbose_name - verbose_name_plural + - webauthn_allowed_device_types_obj AuthenticatorValidateStageRequest: type: object description: AuthenticatorValidateStage Serializer @@ -30636,12 +33945,12 @@ components: webauthn_user_verification: allOf: - $ref: '#/components/schemas/UserVerificationEnum' - description: |- - Enforce user verification for WebAuthn devices. - - * `required` - Required - * `preferred` - Preferred - * `discouraged` - Discouraged + description: Enforce user verification for WebAuthn devices. + webauthn_allowed_device_types: + type: array + items: + type: string + format: uuid required: - name AuthenticatorValidationChallenge: @@ -30742,6 +34051,108 @@ components: additionalProperties: {} required: - response + AuthenticatorWebAuthnStage: + type: object + description: AuthenticatorWebAuthnStage Serializer + properties: + pk: + type: string + format: uuid + readOnly: true + title: Stage uuid + name: + type: string + component: + type: string + description: Get object type so that we know how to edit the object + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSet' + configure_flow: + type: string + format: uuid + nullable: true + description: Flow used by an authenticated user to configure this Stage. + If empty, user will not be able to configure this stage. + friendly_name: + type: string + nullable: true + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' + authenticator_attachment: + allOf: + - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' + nullable: true + resident_key_requirement: + $ref: '#/components/schemas/ResidentKeyRequirementEnum' + device_type_restrictions: + type: array + items: + type: string + format: uuid + device_type_restrictions_obj: + type: array + items: + $ref: '#/components/schemas/WebAuthnDeviceType' + readOnly: true + required: + - component + - device_type_restrictions_obj + - meta_model_name + - name + - pk + - verbose_name + - verbose_name_plural + AuthenticatorWebAuthnStageRequest: + type: object + description: AuthenticatorWebAuthnStage Serializer + properties: + name: + type: string + minLength: 1 + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSetRequest' + configure_flow: + type: string + format: uuid + nullable: true + description: Flow used by an authenticated user to configure this Stage. + If empty, user will not be able to configure this stage. + friendly_name: + type: string + nullable: true + minLength: 1 + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' + authenticator_attachment: + allOf: + - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' + nullable: true + resident_key_requirement: + $ref: '#/components/schemas/ResidentKeyRequirementEnum' + device_type_restrictions: + type: array + items: + type: string + format: uuid + required: + - name AutoSubmitChallengeResponseRequest: type: object description: Pseudo class for autosubmit response @@ -30785,20 +34196,12 @@ components: - authentik.core.auth.TokenBackend - authentik.sources.ldap.auth.LDAPBackend type: string - description: |- - * `authentik.core.auth.InbuiltBackend` - User database + standard password - * `authentik.core.auth.TokenBackend` - User database + app passwords - * `authentik.sources.ldap.auth.LDAPBackend` - User database + LDAP password BindingTypeEnum: enum: - REDIRECT - POST - POST_AUTO type: string - description: |- - * `REDIRECT` - Redirect Binding - * `POST` - POST Binding - * `POST_AUTO` - POST Binding with auto-confirmation BlueprintFile: type: object properties: @@ -30888,12 +34291,6 @@ components: - orphaned - unknown type: string - description: |- - * `successful` - Successful - * `warning` - Warning - * `error` - Error - * `orphaned` - Orphaned - * `unknown` - Unknown Brand: type: object description: Brand Serializer @@ -31017,13 +34414,6 @@ components: - can_debug - is_enterprise type: string - description: |- - * `can_save_media` - Can Save Media - * `can_geo_ip` - Can Geo Ip - * `can_asn` - Can Asn - * `can_impersonate` - Can Impersonate - * `can_debug` - Can Debug - * `is_enterprise` - Is Enterprise CaptchaChallenge: type: object description: Site public key @@ -31164,6 +34554,10 @@ components: type: string validity_days: type: integer + alg: + allOf: + - $ref: '#/components/schemas/AlgEnum' + default: rsa required: - common_name - validity_days @@ -31263,10 +34657,6 @@ components: - shell - redirect type: string - description: |- - * `native` - NATIVE - * `shell` - SHELL - * `redirect` - REDIRECT ChallengeTypes: oneOf: - $ref: '#/components/schemas/AccessDeniedChallenge' @@ -31323,9 +34713,6 @@ components: - confidential - public type: string - description: |- - * `confidential` - Confidential - * `public` - Public Config: type: object description: Serialize authentik Config into DRF Object @@ -31351,6 +34738,53 @@ components: - cache_timeout_reputation - capabilities - error_reporting + ConnectionToken: + type: object + description: ConnectionToken Serializer + properties: + pk: + type: string + format: uuid + title: Connection token uuid + provider: + type: integer + provider_obj: + allOf: + - $ref: '#/components/schemas/RACProvider' + readOnly: true + endpoint: + type: string + format: uuid + endpoint_obj: + allOf: + - $ref: '#/components/schemas/Endpoint' + readOnly: true + user: + allOf: + - $ref: '#/components/schemas/GroupMember' + readOnly: true + required: + - endpoint + - endpoint_obj + - provider + - provider_obj + - user + ConnectionTokenRequest: + type: object + description: ConnectionToken Serializer + properties: + pk: + type: string + format: uuid + title: Connection token uuid + provider: + type: integer + endpoint: + type: string + format: uuid + required: + - endpoint + - provider ConsentChallenge: type: object description: Challenge info for consent screens @@ -31465,10 +34899,6 @@ components: - permanent - expiring type: string - description: |- - * `always_require` - Always Require - * `permanent` - Permanent - * `expiring` - Expiring ConsentStageRequest: type: object description: ConsentStage Serializer @@ -31512,12 +34942,6 @@ components: - sidebar_left - sidebar_right type: string - description: |- - * `stacked` - STACKED - * `content_left` - CONTENT_LEFT - * `content_right` - CONTENT_RIGHT - * `sidebar_left` - SIDEBAR_LEFT - * `sidebar_right` - SIDEBAR_RIGHT Coordinate: type: object description: Coordinates for diagrams @@ -31582,10 +35006,6 @@ components: - message - continue type: string - description: |- - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue DenyStage: type: object description: DenyStage Serializer @@ -31715,12 +35135,6 @@ components: - duo - sms type: string - description: |- - * `static` - Static - * `totp` - TOTP - * `webauthn` - WebAuthn - * `duo` - Duo - * `sms` - SMS DigestAlgorithmEnum: enum: - http://www.w3.org/2000/09/xmldsig#sha1 @@ -31728,19 +35142,11 @@ components: - http://www.w3.org/2001/04/xmldsig-more#sha384 - http://www.w3.org/2001/04/xmlenc#sha512 type: string - description: |- - * `http://www.w3.org/2000/09/xmldsig#sha1` - SHA1 - * `http://www.w3.org/2001/04/xmlenc#sha256` - SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#sha384` - SHA384 - * `http://www.w3.org/2001/04/xmlenc#sha512` - SHA512 DigitsEnum: enum: - '6' - '8' type: string - description: |- - * `6` - 6 digits, widely compatible - * `8` - 8 digits, not compatible with apps like Google Authenticator DockerServiceConnection: type: object description: DockerServiceConnection Serializer @@ -31880,7 +35286,10 @@ components: type: array items: $ref: '#/components/schemas/ErrorDetail' + name: + type: string required: + - name - type DummyChallengeResponseRequest: type: object @@ -32060,10 +35469,6 @@ components: - waiting - invalid type: string - description: |- - * `success` - Success - * `waiting` - Waiting - * `invalid` - Invalid EmailChallenge: type: object description: Email challenge @@ -32402,34 +35807,6 @@ components: - update_available - custom_ type: string - description: |- - * `login` - Login - * `login_failed` - Login Failed - * `logout` - Logout - * `user_write` - User Write - * `suspicious_request` - Suspicious Request - * `password_set` - Password Set - * `secret_view` - Secret View - * `secret_rotate` - Secret Rotate - * `invitation_used` - Invite Used - * `authorize_application` - Authorize Application - * `source_linked` - Source Linked - * `impersonation_started` - Impersonation Started - * `impersonation_ended` - Impersonation Ended - * `flow_execution` - Flow Execution - * `policy_execution` - Policy Execution - * `policy_exception` - Policy Exception - * `property_mapping_exception` - Property Mapping Exception - * `system_task_execution` - System Task Execution - * `system_task_exception` - System Task Exception - * `system_exception` - System Exception - * `configuration_error` - Configuration Error - * `model_created` - Model Created - * `model_updated` - Model Updated - * `model_deleted` - Model Deleted - * `email_sent` - Email Sent - * `update_available` - Update Available - * `custom_` - Custom Prefix EventMatcherPolicy: type: object description: Event Matcher Policy Serializer @@ -32469,36 +35846,8 @@ components: allOf: - $ref: '#/components/schemas/EventActions' nullable: true - description: |- - Match created events with this action type. When left empty, all action types will be matched. - - * `login` - Login - * `login_failed` - Login Failed - * `logout` - Logout - * `user_write` - User Write - * `suspicious_request` - Suspicious Request - * `password_set` - Password Set - * `secret_view` - Secret View - * `secret_rotate` - Secret Rotate - * `invitation_used` - Invite Used - * `authorize_application` - Authorize Application - * `source_linked` - Source Linked - * `impersonation_started` - Impersonation Started - * `impersonation_ended` - Impersonation Ended - * `flow_execution` - Flow Execution - * `policy_execution` - Policy Execution - * `policy_exception` - Policy Exception - * `property_mapping_exception` - Property Mapping Exception - * `system_task_execution` - System Task Execution - * `system_task_exception` - System Task Exception - * `system_exception` - System Exception - * `configuration_error` - Configuration Error - * `model_created` - Model Created - * `model_updated` - Model Updated - * `model_deleted` - Model Deleted - * `email_sent` - Email Sent - * `update_available` - Update Available - * `custom_` - Custom Prefix + description: Match created events with this action type. When left empty, + all action types will be matched. client_ip: type: string nullable: true @@ -32508,142 +35857,15 @@ components: allOf: - $ref: '#/components/schemas/AppEnum' nullable: true - description: |- - Match events created by selected application. When left empty, all applications are matched. - - * `authentik.tenants` - authentik Tenants - * `authentik.admin` - authentik Admin - * `authentik.api` - authentik API - * `authentik.crypto` - authentik Crypto - * `authentik.events` - authentik Events - * `authentik.flows` - authentik Flows - * `authentik.outposts` - authentik Outpost - * `authentik.policies.dummy` - authentik Policies.Dummy - * `authentik.policies.event_matcher` - authentik Policies.Event Matcher - * `authentik.policies.expiry` - authentik Policies.Expiry - * `authentik.policies.expression` - authentik Policies.Expression - * `authentik.policies.password` - authentik Policies.Password - * `authentik.policies.reputation` - authentik Policies.Reputation - * `authentik.policies` - authentik Policies - * `authentik.providers.ldap` - authentik Providers.LDAP - * `authentik.providers.oauth2` - authentik Providers.OAuth2 - * `authentik.providers.proxy` - authentik Providers.Proxy - * `authentik.providers.radius` - authentik Providers.Radius - * `authentik.providers.saml` - authentik Providers.SAML - * `authentik.providers.scim` - authentik Providers.SCIM - * `authentik.rbac` - authentik RBAC - * `authentik.recovery` - authentik Recovery - * `authentik.sources.ldap` - authentik Sources.LDAP - * `authentik.sources.oauth` - authentik Sources.OAuth - * `authentik.sources.plex` - authentik Sources.Plex - * `authentik.sources.saml` - authentik Sources.SAML - * `authentik.stages.authenticator` - authentik Stages.Authenticator - * `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo - * `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS - * `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static - * `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP - * `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate - * `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn - * `authentik.stages.captcha` - authentik Stages.Captcha - * `authentik.stages.consent` - authentik Stages.Consent - * `authentik.stages.deny` - authentik Stages.Deny - * `authentik.stages.dummy` - authentik Stages.Dummy - * `authentik.stages.email` - authentik Stages.Email - * `authentik.stages.identification` - authentik Stages.Identification - * `authentik.stages.invitation` - authentik Stages.User Invitation - * `authentik.stages.password` - authentik Stages.Password - * `authentik.stages.prompt` - authentik Stages.Prompt - * `authentik.stages.user_delete` - authentik Stages.User Delete - * `authentik.stages.user_login` - authentik Stages.User Login - * `authentik.stages.user_logout` - authentik Stages.User Logout - * `authentik.stages.user_write` - authentik Stages.User Write - * `authentik.brands` - authentik Brands - * `authentik.blueprints` - authentik Blueprints - * `authentik.core` - authentik Core - * `authentik.enterprise` - authentik Enterprise - * `authentik.enterprise.audit` - authentik Enterprise.Audit - * `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + description: Match events created by selected application. When left empty, + all applications are matched. model: allOf: - $ref: '#/components/schemas/ModelEnum' nullable: true - description: |- - Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. - - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + description: Match events created by selected model. When left empty, all + models are matched. When an app is selected, all the application's models + are matched. required: - bound_to - component @@ -32667,36 +35889,8 @@ components: allOf: - $ref: '#/components/schemas/EventActions' nullable: true - description: |- - Match created events with this action type. When left empty, all action types will be matched. - - * `login` - Login - * `login_failed` - Login Failed - * `logout` - Logout - * `user_write` - User Write - * `suspicious_request` - Suspicious Request - * `password_set` - Password Set - * `secret_view` - Secret View - * `secret_rotate` - Secret Rotate - * `invitation_used` - Invite Used - * `authorize_application` - Authorize Application - * `source_linked` - Source Linked - * `impersonation_started` - Impersonation Started - * `impersonation_ended` - Impersonation Ended - * `flow_execution` - Flow Execution - * `policy_execution` - Policy Execution - * `policy_exception` - Policy Exception - * `property_mapping_exception` - Property Mapping Exception - * `system_task_execution` - System Task Execution - * `system_task_exception` - System Task Exception - * `system_exception` - System Exception - * `configuration_error` - Configuration Error - * `model_created` - Model Created - * `model_updated` - Model Updated - * `model_deleted` - Model Deleted - * `email_sent` - Email Sent - * `update_available` - Update Available - * `custom_` - Custom Prefix + description: Match created events with this action type. When left empty, + all action types will be matched. client_ip: type: string nullable: true @@ -32707,142 +35901,15 @@ components: allOf: - $ref: '#/components/schemas/AppEnum' nullable: true - description: |- - Match events created by selected application. When left empty, all applications are matched. - - * `authentik.tenants` - authentik Tenants - * `authentik.admin` - authentik Admin - * `authentik.api` - authentik API - * `authentik.crypto` - authentik Crypto - * `authentik.events` - authentik Events - * `authentik.flows` - authentik Flows - * `authentik.outposts` - authentik Outpost - * `authentik.policies.dummy` - authentik Policies.Dummy - * `authentik.policies.event_matcher` - authentik Policies.Event Matcher - * `authentik.policies.expiry` - authentik Policies.Expiry - * `authentik.policies.expression` - authentik Policies.Expression - * `authentik.policies.password` - authentik Policies.Password - * `authentik.policies.reputation` - authentik Policies.Reputation - * `authentik.policies` - authentik Policies - * `authentik.providers.ldap` - authentik Providers.LDAP - * `authentik.providers.oauth2` - authentik Providers.OAuth2 - * `authentik.providers.proxy` - authentik Providers.Proxy - * `authentik.providers.radius` - authentik Providers.Radius - * `authentik.providers.saml` - authentik Providers.SAML - * `authentik.providers.scim` - authentik Providers.SCIM - * `authentik.rbac` - authentik RBAC - * `authentik.recovery` - authentik Recovery - * `authentik.sources.ldap` - authentik Sources.LDAP - * `authentik.sources.oauth` - authentik Sources.OAuth - * `authentik.sources.plex` - authentik Sources.Plex - * `authentik.sources.saml` - authentik Sources.SAML - * `authentik.stages.authenticator` - authentik Stages.Authenticator - * `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo - * `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS - * `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static - * `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP - * `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate - * `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn - * `authentik.stages.captcha` - authentik Stages.Captcha - * `authentik.stages.consent` - authentik Stages.Consent - * `authentik.stages.deny` - authentik Stages.Deny - * `authentik.stages.dummy` - authentik Stages.Dummy - * `authentik.stages.email` - authentik Stages.Email - * `authentik.stages.identification` - authentik Stages.Identification - * `authentik.stages.invitation` - authentik Stages.User Invitation - * `authentik.stages.password` - authentik Stages.Password - * `authentik.stages.prompt` - authentik Stages.Prompt - * `authentik.stages.user_delete` - authentik Stages.User Delete - * `authentik.stages.user_login` - authentik Stages.User Login - * `authentik.stages.user_logout` - authentik Stages.User Logout - * `authentik.stages.user_write` - authentik Stages.User Write - * `authentik.brands` - authentik Brands - * `authentik.blueprints` - authentik Blueprints - * `authentik.core` - authentik Core - * `authentik.enterprise` - authentik Enterprise - * `authentik.enterprise.audit` - authentik Enterprise.Audit - * `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + description: Match events created by selected application. When left empty, + all applications are matched. model: allOf: - $ref: '#/components/schemas/ModelEnum' nullable: true - description: |- - Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. - - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + description: Match events created by selected model. When left empty, all + models are matched. When an app is selected, all the application's models + are matched. required: - name EventRequest: @@ -32901,6 +35968,7 @@ components: expires: type: string format: date-time + nullable: true scope: type: array items: @@ -33119,16 +36187,8 @@ components: designation: allOf: - $ref: '#/components/schemas/FlowDesignationEnum' - description: |- - Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration + description: Decides what this Flow is used for. For example, the Authentication + flow is redirect to when an un-authenticated user visits authentik. background: type: string description: |- @@ -33166,23 +36226,13 @@ components: denied_action: allOf: - $ref: '#/components/schemas/DeniedActionEnum' - description: |- - Configure what should happen when a flow denies access to a user. - - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue + description: Configure what should happen when a flow denies access to a + user. authentication: allOf: - $ref: '#/components/schemas/AuthenticationEnum' - description: |- - Required level of authentication and authorization to access a flow. - - * `none` - None - * `require_authenticated` - Require Authenticated - * `require_unauthenticated` - Require Unauthenticated - * `require_superuser` - Require Superuser - * `require_outpost` - Require Outpost + description: Required level of authentication and authorization to access + a flow. required: - background - cache_count @@ -33248,14 +36298,6 @@ components: - recovery - stage_configuration type: string - description: |- - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration FlowDiagram: type: object description: response of the flow's diagram action @@ -33300,8 +36342,7 @@ components: logs: type: array items: - type: object - additionalProperties: {} + $ref: '#/components/schemas/LogEvent' readOnly: true success: type: boolean @@ -33358,12 +36399,6 @@ components: - sidebar_left - sidebar_right type: string - description: |- - * `stacked` - Stacked - * `content_left` - Content Left - * `content_right` - Content Right - * `sidebar_left` - Sidebar Left - * `sidebar_right` - Sidebar Right FlowRequest: type: object description: Flow Serializer @@ -33384,16 +36419,8 @@ components: designation: allOf: - $ref: '#/components/schemas/FlowDesignationEnum' - description: |- - Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration + description: Decides what this Flow is used for. For example, the Authentication + flow is redirect to when an un-authenticated user visits authentik. policy_engine_mode: $ref: '#/components/schemas/PolicyEngineMode' compatibility_mode: @@ -33405,23 +36432,13 @@ components: denied_action: allOf: - $ref: '#/components/schemas/DeniedActionEnum' - description: |- - Configure what should happen when a flow denies access to a user. - - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue + description: Configure what should happen when a flow denies access to a + user. authentication: allOf: - $ref: '#/components/schemas/AuthenticationEnum' - description: |- - Required level of authentication and authorization to access a flow. - - * `none` - None - * `require_authenticated` - Require Authenticated - * `require_unauthenticated` - Require Unauthenticated - * `require_superuser` - Require Superuser - * `require_outpost` - Require Outpost + description: Required level of authentication and authorization to access + a flow. required: - designation - name @@ -33453,16 +36470,8 @@ components: designation: allOf: - $ref: '#/components/schemas/FlowDesignationEnum' - description: |- - Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration + description: Decides what this Flow is used for. For example, the Authentication + flow is redirect to when an un-authenticated user visits authentik. background: type: string description: |- @@ -33484,12 +36493,8 @@ components: denied_action: allOf: - $ref: '#/components/schemas/DeniedActionEnum' - description: |- - Configure what should happen when a flow denies access to a user. - - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue + description: Configure what should happen when a flow denies access to a + user. required: - background - designation @@ -33519,16 +36524,8 @@ components: designation: allOf: - $ref: '#/components/schemas/FlowDesignationEnum' - description: |- - Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration + description: Decides what this Flow is used for. For example, the Authentication + flow is redirect to when an un-authenticated user visits authentik. policy_engine_mode: $ref: '#/components/schemas/PolicyEngineMode' compatibility_mode: @@ -33540,12 +36537,8 @@ components: denied_action: allOf: - $ref: '#/components/schemas/DeniedActionEnum' - description: |- - Configure what should happen when a flow denies access to a user. - - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue + description: Configure what should happen when a flow denies access to a + user. required: - designation - name @@ -33589,12 +36582,10 @@ components: invalid_response_action: allOf: - $ref: '#/components/schemas/InvalidResponseActionEnum' - description: |- - Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. - - * `retry` - Retry - * `restart` - Restart - * `restart_with_context` - Restart With Context + description: Configure how the flow executor should handle an invalid response + to a challenge. RETRY returns the error message and a similar challenge + to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT + restarts the flow while keeping the current context. required: - order - pk @@ -33627,12 +36618,10 @@ components: invalid_response_action: allOf: - $ref: '#/components/schemas/InvalidResponseActionEnum' - description: |- - Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. - - * `retry` - Retry - * `restart` - Restart - * `restart_with_context` - Restart With Context + description: Configure how the flow executor should handle an invalid response + to a challenge. RETRY returns the error message and a similar challenge + to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT + restarts the flow while keeping the current context. required: - order - stage @@ -33667,11 +36656,248 @@ components: - bind_continent_country - bind_continent_country_city type: string - description: |- - * `no_binding` - No Binding - * `bind_continent` - Bind Continent - * `bind_continent_country` - Bind Continent Country - * `bind_continent_country_city` - Bind Continent Country City + GoogleWorkspaceProvider: + type: object + description: GoogleWorkspaceProvider Serializer + properties: + pk: + type: integer + readOnly: true + title: ID + name: + type: string + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + component: + type: string + description: Get object component so that we know how to edit the object + readOnly: true + assigned_backchannel_application_slug: + type: string + description: Internal application name, used in URLs. + readOnly: true + assigned_backchannel_application_name: + type: string + description: Application's display Name. + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + delegated_subject: + type: string + format: email + maxLength: 254 + credentials: {} + scopes: + type: string + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + default_group_email_domain: + type: string + required: + - assigned_backchannel_application_name + - assigned_backchannel_application_slug + - component + - credentials + - default_group_email_domain + - delegated_subject + - meta_model_name + - name + - pk + - verbose_name + - verbose_name_plural + GoogleWorkspaceProviderGroup: + type: object + description: GoogleWorkspaceProviderGroup Serializer + properties: + id: + type: string + format: uuid + readOnly: true + group: + type: string + format: uuid + group_obj: + allOf: + - $ref: '#/components/schemas/UserGroup' + readOnly: true + required: + - group + - group_obj + - id + GoogleWorkspaceProviderGroupRequest: + type: object + description: GoogleWorkspaceProviderGroup Serializer + properties: + group: + type: string + format: uuid + required: + - group + GoogleWorkspaceProviderMapping: + type: object + description: GoogleWorkspaceProviderMapping Serializer + properties: + pk: + type: string + format: uuid + readOnly: true + title: Pm uuid + managed: + type: string + nullable: true + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + expression: + type: string + component: + type: string + description: Get object's component so that we know how to edit the object + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + required: + - component + - expression + - meta_model_name + - name + - pk + - verbose_name + - verbose_name_plural + GoogleWorkspaceProviderMappingRequest: + type: object + description: GoogleWorkspaceProviderMapping Serializer + properties: + managed: + type: string + nullable: true + minLength: 1 + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + minLength: 1 + expression: + type: string + minLength: 1 + required: + - expression + - name + GoogleWorkspaceProviderRequest: + type: object + description: GoogleWorkspaceProvider Serializer + properties: + name: + type: string + minLength: 1 + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + delegated_subject: + type: string + format: email + minLength: 1 + maxLength: 254 + credentials: {} + scopes: + type: string + minLength: 1 + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + default_group_email_domain: + type: string + minLength: 1 + required: + - credentials + - default_group_email_domain + - delegated_subject + - name + GoogleWorkspaceProviderUser: + type: object + description: GoogleWorkspaceProviderUser Serializer + properties: + id: + type: string + format: uuid + readOnly: true + user: + type: integer + user_obj: + allOf: + - $ref: '#/components/schemas/GroupMember' + readOnly: true + required: + - id + - user + - user_obj + GoogleWorkspaceProviderUserRequest: + type: object + description: GoogleWorkspaceProviderUser Serializer + properties: + user: + type: integer + required: + - user Group: type: object description: Group Serializer @@ -33707,6 +36933,7 @@ components: items: $ref: '#/components/schemas/GroupMember' readOnly: true + nullable: true attributes: type: object additionalProperties: {} @@ -33859,6 +37086,8 @@ components: type: boolean application_pre: type: string + flow_designation: + $ref: '#/components/schemas/FlowDesignationEnum' enroll_url: type: string recovery_url: @@ -33874,6 +37103,7 @@ components: show_source_labels: type: boolean required: + - flow_designation - password_fields - primary_action - show_source_labels @@ -34060,21 +37290,12 @@ components: - recovery - app_password type: string - description: |- - * `verification` - Intent Verification - * `api` - Intent Api - * `recovery` - Intent Recovery - * `app_password` - Intent App Password InvalidResponseActionEnum: enum: - retry - restart - restart_with_context type: string - description: |- - * `retry` - Retry - * `restart` - Restart - * `restart_with_context` - Restart With Context Invitation: type: object description: Invitation Serializer @@ -34091,6 +37312,7 @@ components: expires: type: string format: date-time + nullable: true fixed_data: type: object additionalProperties: {} @@ -34127,6 +37349,7 @@ components: expires: type: string format: date-time + nullable: true fixed_data: type: object additionalProperties: {} @@ -34206,9 +37429,6 @@ components: - global - per_provider type: string - description: |- - * `global` - Same identifier is used for all providers - * `per_provider` - Each provider has a different issuer, based on the application slug. KubernetesServiceConnection: type: object description: KubernetesServiceConnection Serializer @@ -34276,9 +37496,6 @@ components: - direct - cached type: string - description: |- - * `direct` - Direct - * `cached` - Cached LDAPDebug: type: object properties: @@ -34673,14 +37890,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. managed: type: string nullable: true @@ -34694,10 +37905,6 @@ components: type: string icon: type: string - nullable: true - description: |- - Get the URL to the Icon. If the name is /static or - starts with http it is returned as-is readOnly: true server_uri: type: string @@ -34744,6 +37951,10 @@ components: object_uniqueness_field: type: string description: Field which contains a unique Identifier. + password_login_update_internal_password: + type: boolean + description: Update internal authentik password when login succeeds with + LDAP sync_users: type: boolean sync_users_password: @@ -34820,14 +38031,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -34885,6 +38090,10 @@ components: type: string minLength: 1 description: Field which contains a unique Identifier. + password_login_update_internal_password: + type: boolean + description: Update internal authentik password when login succeeds with + LDAP sync_users: type: boolean sync_users_password: @@ -34913,21 +38122,6 @@ components: - name - server_uri - slug - LDAPSyncStatus: - type: object - description: LDAP Source sync status - properties: - is_running: - type: boolean - readOnly: true - tasks: - type: array - items: - $ref: '#/components/schemas/SystemTask' - readOnly: true - required: - - is_running - - tasks License: type: object description: License Serializer @@ -35022,6 +38216,39 @@ components: type: string required: - link + LogEvent: + type: object + description: Single log message with all context logged. + properties: + timestamp: + type: string + format: date-time + log_level: + $ref: '#/components/schemas/LogLevelEnum' + logger: + type: string + event: + type: string + attributes: + type: object + additionalProperties: {} + required: + - attributes + - event + - log_level + - logger + - timestamp + LogLevelEnum: + enum: + - critical + - exception + - error + - warn + - warning + - info + - debug + - notset + type: string LoginChallengeTypes: oneOf: - $ref: '#/components/schemas/RedirectChallenge' @@ -35082,15 +38309,246 @@ components: required: - labels - name + MicrosoftEntraProvider: + type: object + description: MicrosoftEntraProvider Serializer + properties: + pk: + type: integer + readOnly: true + title: ID + name: + type: string + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + component: + type: string + description: Get object component so that we know how to edit the object + readOnly: true + assigned_backchannel_application_slug: + type: string + description: Internal application name, used in URLs. + readOnly: true + assigned_backchannel_application_name: + type: string + description: Application's display Name. + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + client_id: + type: string + client_secret: + type: string + tenant_id: + type: string + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + required: + - assigned_backchannel_application_name + - assigned_backchannel_application_slug + - client_id + - client_secret + - component + - meta_model_name + - name + - pk + - tenant_id + - verbose_name + - verbose_name_plural + MicrosoftEntraProviderGroup: + type: object + description: MicrosoftEntraProviderGroup Serializer + properties: + id: + type: string + format: uuid + readOnly: true + group: + type: string + format: uuid + group_obj: + allOf: + - $ref: '#/components/schemas/UserGroup' + readOnly: true + required: + - group + - group_obj + - id + MicrosoftEntraProviderGroupRequest: + type: object + description: MicrosoftEntraProviderGroup Serializer + properties: + group: + type: string + format: uuid + required: + - group + MicrosoftEntraProviderMapping: + type: object + description: MicrosoftEntraProviderMapping Serializer + properties: + pk: + type: string + format: uuid + readOnly: true + title: Pm uuid + managed: + type: string + nullable: true + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + expression: + type: string + component: + type: string + description: Get object's component so that we know how to edit the object + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + required: + - component + - expression + - meta_model_name + - name + - pk + - verbose_name + - verbose_name_plural + MicrosoftEntraProviderMappingRequest: + type: object + description: MicrosoftEntraProviderMapping Serializer + properties: + managed: + type: string + nullable: true + minLength: 1 + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + minLength: 1 + expression: + type: string + minLength: 1 + required: + - expression + - name + MicrosoftEntraProviderRequest: + type: object + description: MicrosoftEntraProvider Serializer + properties: + name: + type: string + minLength: 1 + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + client_id: + type: string + minLength: 1 + client_secret: + type: string + minLength: 1 + tenant_id: + type: string + minLength: 1 + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + required: + - client_id + - client_secret + - name + - tenant_id + MicrosoftEntraProviderUser: + type: object + description: MicrosoftEntraProviderUser Serializer + properties: + id: + type: string + format: uuid + readOnly: true + user: + type: integer + user_obj: + allOf: + - $ref: '#/components/schemas/GroupMember' + readOnly: true + required: + - id + - user + - user_obj + MicrosoftEntraProviderUserRequest: + type: object + description: MicrosoftEntraProviderUser Serializer + properties: + user: + type: integer + required: + - user ModelEnum: enum: - authentik_tenants.domain - authentik_crypto.certificatekeypair - - authentik_events.event - - authentik_events.notificationtransport - - authentik_events.notification - - authentik_events.notificationrule - - authentik_events.notificationwebhookmapping - authentik_flows.flow - authentik_flows.flowstagebinding - authentik_outposts.dockerserviceconnection @@ -35121,6 +38579,7 @@ components: - authentik_sources_plex.plexsourceconnection - authentik_sources_saml.samlsource - authentik_sources_saml.usersamlsourceconnection + - authentik_sources_scim.scimsource - authentik_stages_authenticator_duo.authenticatorduostage - authentik_stages_authenticator_duo.duodevice - authentik_stages_authenticator_sms.authenticatorsmsstage @@ -35130,7 +38589,7 @@ components: - authentik_stages_authenticator_totp.authenticatortotpstage - authentik_stages_authenticator_totp.totpdevice - authentik_stages_authenticator_validate.authenticatorvalidatestage - - authentik_stages_authenticator_webauthn.authenticatewebauthnstage + - authentik_stages_authenticator_webauthn.authenticatorwebauthnstage - authentik_stages_authenticator_webauthn.webauthndevice - authentik_stages_captcha.captchastage - authentik_stages_consent.consentstage @@ -35155,85 +38614,20 @@ components: - authentik_core.application - authentik_core.token - authentik_enterprise.license + - authentik_providers_google_workspace.googleworkspaceprovider + - authentik_providers_google_workspace.googleworkspaceprovidermapping + - authentik_providers_microsoft_entra.microsoftentraprovider + - authentik_providers_microsoft_entra.microsoftentraprovidermapping - authentik_providers_rac.racprovider - authentik_providers_rac.endpoint - authentik_providers_rac.racpropertymapping + - authentik_stages_source.sourcestage + - authentik_events.event + - authentik_events.notificationtransport + - authentik_events.notification + - authentik_events.notificationrule + - authentik_events.notificationwebhookmapping type: string - description: |- - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping NameIdPolicyEnum: enum: - urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress @@ -35242,12 +38636,6 @@ components: - urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName - urn:oasis:names:tc:SAML:2.0:nameid-format:transient type: string - description: |- - * `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` - Email - * `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` - Persistent - * `urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName` - X509 - * `urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName` - Windows - * `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient NetworkBindingEnum: enum: - no_binding @@ -35255,21 +38643,12 @@ components: - bind_asn_network - bind_asn_network_ip type: string - description: |- - * `no_binding` - No Binding - * `bind_asn` - Bind Asn - * `bind_asn_network` - Bind Asn Network - * `bind_asn_network_ip` - Bind Asn Network Ip NotConfiguredActionEnum: enum: - skip - deny - configure type: string - description: |- - * `skip` - Skip - * `deny` - Deny - * `configure` - Configure Notification: type: object description: Notification Serializer @@ -35329,12 +38708,8 @@ components: severity: allOf: - $ref: '#/components/schemas/SeverityEnum' - description: |- - Controls which severity level the created notifications will have. - - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert + description: Controls which severity level the created notifications will + have. group: type: string format: uuid @@ -35367,12 +38742,8 @@ components: severity: allOf: - $ref: '#/components/schemas/SeverityEnum' - description: |- - Controls which severity level the created notifications will have. - - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert + description: Controls which severity level the created notifications will + have. group: type: string format: uuid @@ -35420,11 +38791,6 @@ components: - webhook_slack - email type: string - description: |- - * `local` - authentik inbuilt notifications - * `webhook` - Generic Webhook - * `webhook_slack` - Slack Webhook (Slack/Discord) - * `email` - Email NotificationTransportRequest: type: object description: NotificationTransport Serializer @@ -35547,11 +38913,8 @@ components: client_type: allOf: - $ref: '#/components/schemas/ClientTypeEnum' - description: |- - Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable - - * `confidential` - Confidential - * `public` - Public + description: Confidential clients are capable of maintaining the confidentiality + of their credentials. Public clients are incapable client_id: type: string maxLength: 255 @@ -35586,23 +38949,12 @@ components: sub_mode: allOf: - $ref: '#/components/schemas/SubModeEnum' - description: |- - Configure what data should be used as unique User Identifier. For most cases, the default should be fine. - - * `hashed_user_id` - Based on the Hashed User ID - * `user_id` - Based on user ID - * `user_uuid` - Based on user UUID - * `user_username` - Based on the username - * `user_email` - Based on the User's Email. This is recommended over the UPN method. - * `user_upn` - Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. + description: Configure what data should be used as unique User Identifier. + For most cases, the default should be fine. issuer_mode: allOf: - $ref: '#/components/schemas/IssuerModeEnum' - description: |- - Configure how the issuer field of the ID Token should be filled. - - * `global` - Same identifier is used for all providers - * `per_provider` - Each provider has a different issuer, based on the application slug. + description: Configure how the issuer field of the ID Token should be filled. jwks_sources: type: array items: @@ -35648,11 +39000,8 @@ components: client_type: allOf: - $ref: '#/components/schemas/ClientTypeEnum' - description: |- - Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable - - * `confidential` - Confidential - * `public` - Public + description: Confidential clients are capable of maintaining the confidentiality + of their credentials. Public clients are incapable client_id: type: string minLength: 1 @@ -35691,23 +39040,12 @@ components: sub_mode: allOf: - $ref: '#/components/schemas/SubModeEnum' - description: |- - Configure what data should be used as unique User Identifier. For most cases, the default should be fine. - - * `hashed_user_id` - Based on the Hashed User ID - * `user_id` - Based on user ID - * `user_uuid` - Based on user UUID - * `user_username` - Based on the username - * `user_email` - Based on the User's Email. This is recommended over the UPN method. - * `user_upn` - Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. + description: Configure what data should be used as unique User Identifier. + For most cases, the default should be fine. issuer_mode: allOf: - $ref: '#/components/schemas/IssuerModeEnum' - description: |- - Configure how the issuer field of the ID Token should be filled. - - * `global` - Same identifier is used for all providers - * `per_provider` - Each provider has a different issuer, based on the application slug. + description: Configure how the issuer field of the ID Token should be filled. jwks_sources: type: array items: @@ -35860,14 +39198,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. managed: type: string nullable: true @@ -35882,9 +39214,6 @@ components: icon: type: string nullable: true - description: |- - Get the URL to the Icon. If the name is /static or - starts with http it is returned as-is readOnly: true provider_type: $ref: '#/components/schemas/ProviderTypeEnum' @@ -35971,14 +39300,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -35987,26 +39310,22 @@ components: request_token_url: type: string nullable: true - minLength: 1 description: URL used to request the initial token. This URL is only required for OAuth 1. maxLength: 255 authorization_url: type: string nullable: true - minLength: 1 description: URL the user is redirect to to conest the flow. maxLength: 255 access_token_url: type: string nullable: true - minLength: 1 description: URL used by authentik to retrieve tokens. maxLength: 255 profile_url: type: string nullable: true - minLength: 1 description: URL used by authentik to get user information. maxLength: 255 consumer_key: @@ -36075,6 +39394,12 @@ components: - token_endpoint - token_endpoint_auth_methods_supported - userinfo_endpoint + OutgoingSyncDeleteAction: + enum: + - do_nothing + - delete + - suspend + type: string Outpost: type: object description: Outpost Serializer @@ -36155,6 +39480,18 @@ components: version: type: string readOnly: true + golang_version: + type: string + readOnly: true + openssl_enabled: + type: boolean + readOnly: true + openssl_version: + type: string + readOnly: true + fips_enabled: + type: boolean + readOnly: true version_should: type: string readOnly: true @@ -36173,8 +39510,12 @@ components: required: - build_hash - build_hash_should + - fips_enabled + - golang_version - hostname - last_seen + - openssl_enabled + - openssl_version - uid - version - version_outdated @@ -36222,11 +39563,6 @@ components: - radius - rac type: string - description: |- - * `proxy` - Proxy - * `ldap` - Ldap - * `radius` - Radius - * `rac` - Rac PaginatedApplicationList: type: object properties: @@ -36239,18 +39575,6 @@ components: required: - pagination - results - PaginatedAuthenticateWebAuthnStageList: - type: object - properties: - pagination: - $ref: '#/components/schemas/Pagination' - results: - type: array - items: - $ref: '#/components/schemas/AuthenticateWebAuthnStage' - required: - - pagination - - results PaginatedAuthenticatedSessionList: type: object properties: @@ -36323,6 +39647,18 @@ components: required: - pagination - results + PaginatedAuthenticatorWebAuthnStageList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/AuthenticatorWebAuthnStage' + required: + - pagination + - results PaginatedBlueprintInstanceList: type: object properties: @@ -36371,6 +39707,18 @@ components: required: - pagination - results + PaginatedConnectionTokenList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/ConnectionToken' + required: + - pagination + - results PaginatedConsentStageList: type: object properties: @@ -36575,6 +39923,54 @@ components: required: - pagination - results + PaginatedGoogleWorkspaceProviderGroupList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/GoogleWorkspaceProviderGroup' + required: + - pagination + - results + PaginatedGoogleWorkspaceProviderList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/GoogleWorkspaceProvider' + required: + - pagination + - results + PaginatedGoogleWorkspaceProviderMappingList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/GoogleWorkspaceProviderMapping' + required: + - pagination + - results + PaginatedGoogleWorkspaceProviderUserList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/GoogleWorkspaceProviderUser' + required: + - pagination + - results PaginatedGroupList: type: object properties: @@ -36695,6 +40091,54 @@ components: required: - pagination - results + PaginatedMicrosoftEntraProviderGroupList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/MicrosoftEntraProviderGroup' + required: + - pagination + - results + PaginatedMicrosoftEntraProviderList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/MicrosoftEntraProvider' + required: + - pagination + - results + PaginatedMicrosoftEntraProviderMappingList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/MicrosoftEntraProviderMapping' + required: + - pagination + - results + PaginatedMicrosoftEntraProviderUserList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/MicrosoftEntraProviderUser' + required: + - pagination + - results PaginatedNotificationList: type: object properties: @@ -37103,6 +40547,42 @@ components: required: - pagination - results + PaginatedSCIMSourceGroupList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/SCIMSourceGroup' + required: + - pagination + - results + PaginatedSCIMSourceList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/SCIMSource' + required: + - pagination + - results + PaginatedSCIMSourceUserList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/SCIMSourceUser' + required: + - pagination + - results PaginatedSMSDeviceList: type: object properties: @@ -37151,6 +40631,18 @@ components: required: - pagination - results + PaginatedSourceStageList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/SourceStage' + required: + - pagination + - results PaginatedStageList: type: object properties: @@ -37379,6 +40871,18 @@ components: required: - pagination - results + PaginatedWebAuthnDeviceTypeList: + type: object + properties: + pagination: + $ref: '#/components/schemas/Pagination' + results: + type: array + items: + $ref: '#/components/schemas/WebAuthnDeviceType' + required: + - pagination + - results Pagination: type: object properties: @@ -37784,35 +41288,6 @@ components: $ref: '#/components/schemas/PolicyEngineMode' group: type: string - PatchedAuthenticateWebAuthnStageRequest: - type: object - description: AuthenticateWebAuthnStage Serializer - properties: - name: - type: string - minLength: 1 - flow_set: - type: array - items: - $ref: '#/components/schemas/FlowSetRequest' - configure_flow: - type: string - format: uuid - nullable: true - description: Flow used by an authenticated user to configure this Stage. - If empty, user will not be able to configure this stage. - friendly_name: - type: string - nullable: true - minLength: 1 - user_verification: - $ref: '#/components/schemas/UserVerificationEnum' - authenticator_attachment: - allOf: - - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' - nullable: true - resident_key_requirement: - $ref: '#/components/schemas/ResidentKeyRequirementEnum' PatchedAuthenticatorDuoStageRequest: type: object description: AuthenticatorDuoStage Serializer @@ -37981,12 +41456,46 @@ components: webauthn_user_verification: allOf: - $ref: '#/components/schemas/UserVerificationEnum' - description: |- - Enforce user verification for WebAuthn devices. - - * `required` - Required - * `preferred` - Preferred - * `discouraged` - Discouraged + description: Enforce user verification for WebAuthn devices. + webauthn_allowed_device_types: + type: array + items: + type: string + format: uuid + PatchedAuthenticatorWebAuthnStageRequest: + type: object + description: AuthenticatorWebAuthnStage Serializer + properties: + name: + type: string + minLength: 1 + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSetRequest' + configure_flow: + type: string + format: uuid + nullable: true + description: Flow used by an authenticated user to configure this Stage. + If empty, user will not be able to configure this stage. + friendly_name: + type: string + nullable: true + minLength: 1 + user_verification: + $ref: '#/components/schemas/UserVerificationEnum' + authenticator_attachment: + allOf: + - $ref: '#/components/schemas/AuthenticatorAttachmentEnum' + nullable: true + resident_key_requirement: + $ref: '#/components/schemas/ResidentKeyRequirementEnum' + device_type_restrictions: + type: array + items: + type: string + format: uuid PatchedBlueprintInstanceRequest: type: object description: Info about a single blueprint instance file @@ -38095,6 +41604,19 @@ components: writeOnly: true description: Optional Private Key. If this is set, you can use this keypair for encryption. + PatchedConnectionTokenRequest: + type: object + description: ConnectionToken Serializer + properties: + pk: + type: string + format: uuid + title: Connection token uuid + provider: + type: integer + endpoint: + type: string + format: uuid PatchedConsentStageRequest: type: object description: ConsentStage Serializer @@ -38306,36 +41828,8 @@ components: allOf: - $ref: '#/components/schemas/EventActions' nullable: true - description: |- - Match created events with this action type. When left empty, all action types will be matched. - - * `login` - Login - * `login_failed` - Login Failed - * `logout` - Logout - * `user_write` - User Write - * `suspicious_request` - Suspicious Request - * `password_set` - Password Set - * `secret_view` - Secret View - * `secret_rotate` - Secret Rotate - * `invitation_used` - Invite Used - * `authorize_application` - Authorize Application - * `source_linked` - Source Linked - * `impersonation_started` - Impersonation Started - * `impersonation_ended` - Impersonation Ended - * `flow_execution` - Flow Execution - * `policy_execution` - Policy Execution - * `policy_exception` - Policy Exception - * `property_mapping_exception` - Property Mapping Exception - * `system_task_execution` - System Task Execution - * `system_task_exception` - System Task Exception - * `system_exception` - System Exception - * `configuration_error` - Configuration Error - * `model_created` - Model Created - * `model_updated` - Model Updated - * `model_deleted` - Model Deleted - * `email_sent` - Email Sent - * `update_available` - Update Available - * `custom_` - Custom Prefix + description: Match created events with this action type. When left empty, + all action types will be matched. client_ip: type: string nullable: true @@ -38346,142 +41840,15 @@ components: allOf: - $ref: '#/components/schemas/AppEnum' nullable: true - description: |- - Match events created by selected application. When left empty, all applications are matched. - - * `authentik.tenants` - authentik Tenants - * `authentik.admin` - authentik Admin - * `authentik.api` - authentik API - * `authentik.crypto` - authentik Crypto - * `authentik.events` - authentik Events - * `authentik.flows` - authentik Flows - * `authentik.outposts` - authentik Outpost - * `authentik.policies.dummy` - authentik Policies.Dummy - * `authentik.policies.event_matcher` - authentik Policies.Event Matcher - * `authentik.policies.expiry` - authentik Policies.Expiry - * `authentik.policies.expression` - authentik Policies.Expression - * `authentik.policies.password` - authentik Policies.Password - * `authentik.policies.reputation` - authentik Policies.Reputation - * `authentik.policies` - authentik Policies - * `authentik.providers.ldap` - authentik Providers.LDAP - * `authentik.providers.oauth2` - authentik Providers.OAuth2 - * `authentik.providers.proxy` - authentik Providers.Proxy - * `authentik.providers.radius` - authentik Providers.Radius - * `authentik.providers.saml` - authentik Providers.SAML - * `authentik.providers.scim` - authentik Providers.SCIM - * `authentik.rbac` - authentik RBAC - * `authentik.recovery` - authentik Recovery - * `authentik.sources.ldap` - authentik Sources.LDAP - * `authentik.sources.oauth` - authentik Sources.OAuth - * `authentik.sources.plex` - authentik Sources.Plex - * `authentik.sources.saml` - authentik Sources.SAML - * `authentik.stages.authenticator` - authentik Stages.Authenticator - * `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo - * `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS - * `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static - * `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP - * `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate - * `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn - * `authentik.stages.captcha` - authentik Stages.Captcha - * `authentik.stages.consent` - authentik Stages.Consent - * `authentik.stages.deny` - authentik Stages.Deny - * `authentik.stages.dummy` - authentik Stages.Dummy - * `authentik.stages.email` - authentik Stages.Email - * `authentik.stages.identification` - authentik Stages.Identification - * `authentik.stages.invitation` - authentik Stages.User Invitation - * `authentik.stages.password` - authentik Stages.Password - * `authentik.stages.prompt` - authentik Stages.Prompt - * `authentik.stages.user_delete` - authentik Stages.User Delete - * `authentik.stages.user_login` - authentik Stages.User Login - * `authentik.stages.user_logout` - authentik Stages.User Logout - * `authentik.stages.user_write` - authentik Stages.User Write - * `authentik.brands` - authentik Brands - * `authentik.blueprints` - authentik Blueprints - * `authentik.core` - authentik Core - * `authentik.enterprise` - authentik Enterprise - * `authentik.enterprise.audit` - authentik Enterprise.Audit - * `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + description: Match events created by selected application. When left empty, + all applications are matched. model: allOf: - $ref: '#/components/schemas/ModelEnum' nullable: true - description: |- - Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. - - * `authentik_tenants.domain` - Domain - * `authentik_crypto.certificatekeypair` - Certificate-Key Pair - * `authentik_events.event` - Event - * `authentik_events.notificationtransport` - Notification Transport - * `authentik_events.notification` - Notification - * `authentik_events.notificationrule` - Notification Rule - * `authentik_events.notificationwebhookmapping` - Webhook Mapping - * `authentik_flows.flow` - Flow - * `authentik_flows.flowstagebinding` - Flow Stage Binding - * `authentik_outposts.dockerserviceconnection` - Docker Service-Connection - * `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection - * `authentik_outposts.outpost` - Outpost - * `authentik_policies_dummy.dummypolicy` - Dummy Policy - * `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy - * `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy - * `authentik_policies_expression.expressionpolicy` - Expression Policy - * `authentik_policies_password.passwordpolicy` - Password Policy - * `authentik_policies_reputation.reputationpolicy` - Reputation Policy - * `authentik_policies.policybinding` - Policy Binding - * `authentik_providers_ldap.ldapprovider` - LDAP Provider - * `authentik_providers_oauth2.scopemapping` - Scope Mapping - * `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider - * `authentik_providers_proxy.proxyprovider` - Proxy Provider - * `authentik_providers_radius.radiusprovider` - Radius Provider - * `authentik_providers_saml.samlprovider` - SAML Provider - * `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping - * `authentik_providers_scim.scimprovider` - SCIM Provider - * `authentik_providers_scim.scimmapping` - SCIM Mapping - * `authentik_rbac.role` - Role - * `authentik_sources_ldap.ldapsource` - LDAP Source - * `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping - * `authentik_sources_oauth.oauthsource` - OAuth Source - * `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection - * `authentik_sources_plex.plexsource` - Plex Source - * `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection - * `authentik_sources_saml.samlsource` - SAML Source - * `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection - * `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage - * `authentik_stages_authenticator_duo.duodevice` - Duo Device - * `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage - * `authentik_stages_authenticator_sms.smsdevice` - SMS Device - * `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage - * `authentik_stages_authenticator_static.staticdevice` - Static Device - * `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage - * `authentik_stages_authenticator_totp.totpdevice` - TOTP Device - * `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage - * `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage - * `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device - * `authentik_stages_captcha.captchastage` - Captcha Stage - * `authentik_stages_consent.consentstage` - Consent Stage - * `authentik_stages_consent.userconsent` - User Consent - * `authentik_stages_deny.denystage` - Deny Stage - * `authentik_stages_dummy.dummystage` - Dummy Stage - * `authentik_stages_email.emailstage` - Email Stage - * `authentik_stages_identification.identificationstage` - Identification Stage - * `authentik_stages_invitation.invitationstage` - Invitation Stage - * `authentik_stages_invitation.invitation` - Invitation - * `authentik_stages_password.passwordstage` - Password Stage - * `authentik_stages_prompt.prompt` - Prompt - * `authentik_stages_prompt.promptstage` - Prompt Stage - * `authentik_stages_user_delete.userdeletestage` - User Delete Stage - * `authentik_stages_user_login.userloginstage` - User Login Stage - * `authentik_stages_user_logout.userlogoutstage` - User Logout Stage - * `authentik_stages_user_write.userwritestage` - User Write Stage - * `authentik_brands.brand` - Brand - * `authentik_blueprints.blueprintinstance` - Blueprint Instance - * `authentik_core.group` - Group - * `authentik_core.user` - User - * `authentik_core.application` - Application - * `authentik_core.token` - Token - * `authentik_enterprise.license` - License - * `authentik_providers_rac.racprovider` - RAC Provider - * `authentik_providers_rac.endpoint` - RAC Endpoint - * `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + description: Match events created by selected model. When left empty, all + models are matched. When an app is selected, all the application's models + are matched. PatchedEventRequest: type: object description: Event Serializer @@ -38535,16 +41902,8 @@ components: designation: allOf: - $ref: '#/components/schemas/FlowDesignationEnum' - description: |- - Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. - - * `authentication` - Authentication - * `authorization` - Authorization - * `invalidation` - Invalidation - * `enrollment` - Enrollment - * `unenrollment` - Unrenollment - * `recovery` - Recovery - * `stage_configuration` - Stage Configuration + description: Decides what this Flow is used for. For example, the Authentication + flow is redirect to when an un-authenticated user visits authentik. policy_engine_mode: $ref: '#/components/schemas/PolicyEngineMode' compatibility_mode: @@ -38556,23 +41915,13 @@ components: denied_action: allOf: - $ref: '#/components/schemas/DeniedActionEnum' - description: |- - Configure what should happen when a flow denies access to a user. - - * `message_continue` - Message Continue - * `message` - Message - * `continue` - Continue + description: Configure what should happen when a flow denies access to a + user. authentication: allOf: - $ref: '#/components/schemas/AuthenticationEnum' - description: |- - Required level of authentication and authorization to access a flow. - - * `none` - None - * `require_authenticated` - Require Authenticated - * `require_unauthenticated` - Require Unauthenticated - * `require_superuser` - Require Superuser - * `require_outpost` - Require Outpost + description: Required level of authentication and authorization to access + a flow. PatchedFlowStageBindingRequest: type: object description: FlowStageBinding Serializer @@ -38598,12 +41947,82 @@ components: invalid_response_action: allOf: - $ref: '#/components/schemas/InvalidResponseActionEnum' - description: |- - Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. - - * `retry` - Retry - * `restart` - Restart - * `restart_with_context` - Restart With Context + description: Configure how the flow executor should handle an invalid response + to a challenge. RETRY returns the error message and a similar challenge + to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT + restarts the flow while keeping the current context. + PatchedGoogleWorkspaceProviderGroupRequest: + type: object + description: GoogleWorkspaceProviderGroup Serializer + properties: + group: + type: string + format: uuid + PatchedGoogleWorkspaceProviderMappingRequest: + type: object + description: GoogleWorkspaceProviderMapping Serializer + properties: + managed: + type: string + nullable: true + minLength: 1 + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + minLength: 1 + expression: + type: string + minLength: 1 + PatchedGoogleWorkspaceProviderRequest: + type: object + description: GoogleWorkspaceProvider Serializer + properties: + name: + type: string + minLength: 1 + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + delegated_subject: + type: string + format: email + minLength: 1 + maxLength: 254 + credentials: {} + scopes: + type: string + minLength: 1 + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + default_group_email_domain: + type: string + minLength: 1 + PatchedGoogleWorkspaceProviderUserRequest: + type: object + description: GoogleWorkspaceProviderUser Serializer + properties: + user: + type: integer PatchedGroupRequest: type: object description: Group Serializer @@ -38704,6 +42123,7 @@ components: expires: type: string format: date-time + nullable: true fixed_data: type: object additionalProperties: {} @@ -38865,14 +42285,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -38930,6 +42344,10 @@ components: type: string minLength: 1 description: Field which contains a unique Identifier. + password_login_update_internal_password: + type: boolean + description: Update internal authentik password when login succeeds with + LDAP sync_users: type: boolean sync_users_password: @@ -38960,6 +42378,75 @@ components: key: type: string minLength: 1 + PatchedMicrosoftEntraProviderGroupRequest: + type: object + description: MicrosoftEntraProviderGroup Serializer + properties: + group: + type: string + format: uuid + PatchedMicrosoftEntraProviderMappingRequest: + type: object + description: MicrosoftEntraProviderMapping Serializer + properties: + managed: + type: string + nullable: true + minLength: 1 + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + name: + type: string + minLength: 1 + expression: + type: string + minLength: 1 + PatchedMicrosoftEntraProviderRequest: + type: object + description: MicrosoftEntraProvider Serializer + properties: + name: + type: string + minLength: 1 + property_mappings: + type: array + items: + type: string + format: uuid + property_mappings_group: + type: array + items: + type: string + format: uuid + description: Property mappings used for group creation/updating. + client_id: + type: string + minLength: 1 + client_secret: + type: string + minLength: 1 + tenant_id: + type: string + minLength: 1 + exclude_users_service_account: + type: boolean + filter_group: + type: string + format: uuid + nullable: true + user_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + group_delete_action: + $ref: '#/components/schemas/OutgoingSyncDeleteAction' + PatchedMicrosoftEntraProviderUserRequest: + type: object + description: MicrosoftEntraProviderUser Serializer + properties: + user: + type: integer PatchedNotificationRequest: type: object description: Notification Serializer @@ -38986,12 +42473,8 @@ components: severity: allOf: - $ref: '#/components/schemas/SeverityEnum' - description: |- - Controls which severity level the created notifications will have. - - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert + description: Controls which severity level the created notifications will + have. group: type: string format: uuid @@ -39053,11 +42536,8 @@ components: client_type: allOf: - $ref: '#/components/schemas/ClientTypeEnum' - description: |- - Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable - - * `confidential` - Confidential - * `public` - Public + description: Confidential clients are capable of maintaining the confidentiality + of their credentials. Public clients are incapable client_id: type: string minLength: 1 @@ -39096,23 +42576,12 @@ components: sub_mode: allOf: - $ref: '#/components/schemas/SubModeEnum' - description: |- - Configure what data should be used as unique User Identifier. For most cases, the default should be fine. - - * `hashed_user_id` - Based on the Hashed User ID - * `user_id` - Based on user ID - * `user_uuid` - Based on user UUID - * `user_username` - Based on the username - * `user_email` - Based on the User's Email. This is recommended over the UPN method. - * `user_upn` - Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. + description: Configure what data should be used as unique User Identifier. + For most cases, the default should be fine. issuer_mode: allOf: - $ref: '#/components/schemas/IssuerModeEnum' - description: |- - Configure how the issuer field of the ID Token should be filled. - - * `global` - Same identifier is used for all providers - * `per_provider` - Each provider has a different issuer, based on the application slug. + description: Configure how the issuer field of the ID Token should be filled. jwks_sources: type: array items: @@ -39152,14 +42621,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -39168,26 +42631,22 @@ components: request_token_url: type: string nullable: true - minLength: 1 description: URL used to request the initial token. This URL is only required for OAuth 1. maxLength: 255 authorization_url: type: string nullable: true - minLength: 1 description: URL the user is redirect to to conest the flow. maxLength: 255 access_token_url: type: string nullable: true - minLength: 1 description: URL used by authentik to retrieve tokens. maxLength: 255 profile_url: type: string nullable: true - minLength: 1 description: URL used by authentik to get user information. maxLength: 255 consumer_key: @@ -39393,14 +42852,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -39578,12 +43031,8 @@ components: mode: allOf: - $ref: '#/components/schemas/ProxyMode' - description: |- - Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. - - * `proxy` - Proxy - * `forward_single` - Forward Single - * `forward_domain` - Forward Domain + description: Enable support for forwardAuth in traefik and nginx auth_request. + Exclusive with internal_host. intercept_header_auth: type: boolean description: When enabled, this provider will intercept the authorization @@ -39657,6 +43106,9 @@ components: minLength: 1 description: 'Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)' + delete_token_on_disconnect: + type: boolean + description: When set to true, connection tokens will be deleted upon disconnect. PatchedRadiusProviderRequest: type: object description: RadiusProvider Serializer @@ -39827,11 +43279,8 @@ components: allOf: - $ref: '#/components/schemas/SpBindingEnum' title: Service Provider Binding - description: |- - This determines how authentik sends the response back to the Service Provider. - - * `redirect` - Redirect - * `post` - Post + description: This determines how authentik sends the response back to the + Service Provider. default_relay_state: type: string description: Default relay_state value for IDP-initiated logins @@ -39866,14 +43315,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -39903,14 +43346,8 @@ components: name_id_policy: allOf: - $ref: '#/components/schemas/NameIdPolicyEnum' - description: |- - NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. - - * `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` - Email - * `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` - Persistent - * `urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName` - X509 - * `urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName` - Windows - * `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient + description: NameID Policy sent to the IdP. Can be unset, in which case + no Policy is sent. binding_type: $ref: '#/components/schemas/BindingTypeEnum' verification_kp: @@ -39989,6 +43426,57 @@ components: type: string format: uuid nullable: true + PatchedSCIMSourceGroupRequest: + type: object + description: SCIMSourceGroup Serializer + properties: + id: + type: string + minLength: 1 + group: + type: string + format: uuid + source: + type: string + format: uuid + attributes: {} + PatchedSCIMSourceRequest: + type: object + description: SCIMSource Serializer + properties: + name: + type: string + minLength: 1 + description: Source's display Name. + slug: + type: string + minLength: 1 + description: Internal source name, used in URLs. + maxLength: 50 + pattern: ^[-a-zA-Z0-9_]+$ + enabled: + type: boolean + user_matching_mode: + allOf: + - $ref: '#/components/schemas/UserMatchingModeEnum' + description: How the source determines if an existing user should be authenticated + or a new user enrolled. + user_path_template: + type: string + minLength: 1 + PatchedSCIMSourceUserRequest: + type: object + description: SCIMSourceUser Serializer + properties: + id: + type: string + minLength: 1 + user: + type: integer + source: + type: string + format: uuid + attributes: {} PatchedSMSDeviceRequest: type: object description: Serializer for sms authenticator devices @@ -40060,6 +43548,34 @@ components: description: Fields to show in the user directory. user_directory_attributes: description: Attributes to show in the user directory. + default_token_duration: + type: string + minLength: 1 + description: Default token duration + default_token_length: + type: integer + maximum: 2147483647 + minimum: 1 + description: Default token length + PatchedSourceStageRequest: + type: object + description: SourceStage Serializer + properties: + name: + type: string + minLength: 1 + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSetRequest' + source: + type: string + format: uuid + resume_timeout: + type: string + minLength: 1 + description: 'Amount of time a user can take to return from the source to + continue the flow (Format: hours=-1;minutes=-2;seconds=-3)' PatchedStaticDeviceRequest: type: object description: Serializer for static authenticator devices @@ -40118,6 +43634,7 @@ components: expires: type: string format: date-time + nullable: true expiring: type: boolean PatchedUserDeleteStageRequest: @@ -40159,23 +43676,12 @@ components: network_binding: allOf: - $ref: '#/components/schemas/NetworkBindingEnum' - description: |- - Bind sessions created by this stage to the configured network - - * `no_binding` - No Binding - * `bind_asn` - Bind Asn - * `bind_asn_network` - Bind Asn Network - * `bind_asn_network_ip` - Bind Asn Network Ip + description: Bind sessions created by this stage to the configured network geoip_binding: allOf: - $ref: '#/components/schemas/GeoipBindingEnum' - description: |- - Bind sessions created by this stage to the configured GeoIP location - - * `no_binding` - No Binding - * `bind_continent` - Bind Continent - * `bind_continent_country` - Bind Continent Country - * `bind_continent_country_city` - Bind Continent Country City + description: Bind sessions created by this stage to the configured GeoIP + location PatchedUserLogoutStageRequest: type: object description: UserLogoutStage Serializer @@ -40416,14 +43922,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. managed: type: string nullable: true @@ -40437,10 +43937,6 @@ components: type: string icon: type: string - nullable: true - description: |- - Get the URL to the Icon. If the name is /static or - starts with http it is returned as-is readOnly: true client_id: type: string @@ -40537,14 +44033,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -40724,9 +44214,6 @@ components: - all - any type: string - description: |- - * `all` - all, all policies must pass - * `any` - any, any policy must pass PolicyRequest: type: object description: Policy Serializer @@ -40765,8 +44252,7 @@ components: log_messages: type: array items: - type: object - additionalProperties: {} + $ref: '#/components/schemas/LogEvent' readOnly: true required: - log_messages @@ -40998,25 +44484,6 @@ components: - static - ak-locale type: string - description: |- - * `text` - Text: Simple Text input - * `text_area` - Text area: Multiline Text Input. - * `text_read_only` - Text (read-only): Simple Text input, but cannot be edited. - * `text_area_read_only` - Text area (read-only): Multiline Text input, but cannot be edited. - * `username` - Username: Same as Text input, but checks for and prevents duplicate usernames. - * `email` - Email: Text field with Email type. - * `password` - Password: Masked input, multiple inputs of this type on the same prompt need to be identical. - * `number` - Number - * `checkbox` - Checkbox - * `radio-button-group` - Fixed choice field rendered as a group of radio buttons. - * `dropdown` - Fixed choice field rendered as a dropdown. - * `date` - Date - * `date-time` - Date Time - * `file` - File: File upload for arbitrary files. File content will be available in flow context as data-URI - * `separator` - Separator: Static Separator Line - * `hidden` - Hidden: Hidden field, can be used to insert data into form. - * `static` - Static: Static value, displayed as-is. - * `ak-locale` - authentik: Selection of locales authentik supports PropertyMapping: type: object description: PropertyMapping Serializer @@ -41073,6 +44540,18 @@ components: readOnly: true required: - preview + PropertyMappingTestRequest: + type: object + description: Test property mapping execution for a user/group with context + properties: + user: + type: integer + context: + type: object + additionalProperties: {} + group: + type: string + format: uuid PropertyMappingTestResult: type: object description: Result of a Property-mapping test @@ -41092,10 +44571,6 @@ components: - vnc - ssh type: string - description: |- - * `rdp` - Rdp - * `vnc` - Vnc - * `ssh` - Ssh Provider: type: object description: Provider Serializer @@ -41170,12 +44645,11 @@ components: - twilio - generic type: string - description: |- - * `twilio` - Twilio - * `generic` - Generic ProviderModelEnum: enum: + - authentik_providers_google_workspace.googleworkspaceprovider - authentik_providers_ldap.ldapprovider + - authentik_providers_microsoft_entra.microsoftentraprovider - authentik_providers_oauth2.oauth2provider - authentik_providers_proxy.proxyprovider - authentik_providers_rac.racprovider @@ -41183,14 +44657,6 @@ components: - authentik_providers_saml.samlprovider - authentik_providers_scim.scimprovider type: string - description: |- - * `authentik_providers_ldap.ldapprovider` - authentik_providers_ldap.ldapprovider - * `authentik_providers_oauth2.oauth2provider` - authentik_providers_oauth2.oauth2provider - * `authentik_providers_proxy.proxyprovider` - authentik_providers_proxy.proxyprovider - * `authentik_providers_rac.racprovider` - authentik_providers_rac.racprovider - * `authentik_providers_radius.radiusprovider` - authentik_providers_radius.radiusprovider - * `authentik_providers_saml.samlprovider` - authentik_providers_saml.samlprovider - * `authentik_providers_scim.scimprovider` - authentik_providers_scim.scimprovider ProviderRequest: type: object description: Provider Serializer @@ -41224,6 +44690,7 @@ components: - discord - facebook - github + - gitlab - google - mailcow - okta @@ -41232,30 +44699,12 @@ components: - twitch - twitter type: string - description: |- - * `apple` - Apple - * `openidconnect` - OpenID Connect - * `azuread` - Azure AD - * `discord` - Discord - * `facebook` - Facebook - * `github` - GitHub - * `google` - Google - * `mailcow` - Mailcow - * `okta` - Okta - * `patreon` - Patreon - * `reddit` - Reddit - * `twitch` - Twitch - * `twitter` - Twitter ProxyMode: enum: - proxy - forward_single - forward_domain type: string - description: |- - * `proxy` - Proxy - * `forward_single` - Forward Single - * `forward_domain` - Forward Domain ProxyOutpostConfig: type: object description: Proxy provider serializer for outposts @@ -41313,12 +44762,8 @@ components: mode: allOf: - $ref: '#/components/schemas/ProxyMode' - description: |- - Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. - - * `proxy` - Proxy - * `forward_single` - Forward Single - * `forward_domain` - Forward Domain + description: Enable support for forwardAuth in traefik and nginx auth_request. + Exclusive with internal_host. cookie_domain: type: string access_token_validity: @@ -41451,12 +44896,8 @@ components: mode: allOf: - $ref: '#/components/schemas/ProxyMode' - description: |- - Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. - - * `proxy` - Proxy - * `forward_single` - Forward Single - * `forward_domain` - Forward Domain + description: Enable support for forwardAuth in traefik and nginx auth_request. + Exclusive with internal_host. intercept_header_auth: type: boolean description: When enabled, this provider will intercept the authorization @@ -41561,12 +45002,8 @@ components: mode: allOf: - $ref: '#/components/schemas/ProxyMode' - description: |- - Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. - - * `proxy` - Proxy - * `forward_single` - Forward Single - * `forward_domain` - Forward Domain + description: Enable support for forwardAuth in traefik and nginx auth_request. + Exclusive with internal_host. intercept_header_auth: type: boolean description: When enabled, this provider will intercept the authorization @@ -41734,6 +45171,9 @@ components: type: string description: 'Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)' + delete_token_on_disconnect: + type: boolean + description: When set to true, connection tokens will be deleted upon disconnect. required: - assigned_application_name - assigned_application_slug @@ -41775,6 +45215,9 @@ components: minLength: 1 description: 'Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)' + delete_token_on_disconnect: + type: boolean + description: When set to true, connection tokens will be deleted upon disconnect. required: - authorization_flow - name @@ -42071,10 +45514,6 @@ components: - preferred - required type: string - description: |- - * `discouraged` - Discouraged - * `preferred` - Preferred - * `required` - Required Role: type: object description: Role serializer @@ -42351,11 +45790,8 @@ components: allOf: - $ref: '#/components/schemas/SpBindingEnum' title: Service Provider Binding - description: |- - This determines how authentik sends the response back to the Service Provider. - - * `redirect` - Redirect - * `post` - Post + description: This determines how authentik sends the response back to the + Service Provider. default_relay_state: type: string description: Default relay_state value for IDP-initiated logins @@ -42498,11 +45934,8 @@ components: allOf: - $ref: '#/components/schemas/SpBindingEnum' title: Service Provider Binding - description: |- - This determines how authentik sends the response back to the Service Provider. - - * `redirect` - Redirect - * `post` - Post + description: This determines how authentik sends the response back to the + Service Provider. default_relay_state: type: string description: Default relay_state value for IDP-initiated logins @@ -42560,14 +45993,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. managed: type: string nullable: true @@ -42581,10 +46008,6 @@ components: type: string icon: type: string - nullable: true - description: |- - Get the URL to the Icon. If the name is /static or - starts with http it is returned as-is readOnly: true pre_authentication_flow: type: string @@ -42611,14 +46034,8 @@ components: name_id_policy: allOf: - $ref: '#/components/schemas/NameIdPolicyEnum' - description: |- - NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. - - * `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` - Email - * `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` - Persistent - * `urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName` - X509 - * `urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName` - Windows - * `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient + description: NameID Policy sent to the IdP. Can be unset, in which case + no Policy is sent. binding_type: $ref: '#/components/schemas/BindingTypeEnum' verification_kp: @@ -42688,14 +46105,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 @@ -42725,14 +46136,8 @@ components: name_id_policy: allOf: - $ref: '#/components/schemas/NameIdPolicyEnum' - description: |- - NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. - - * `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` - Email - * `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` - Persistent - * `urn:oasis:names:tc:SAML:2.0:nameid-format:X509SubjectName` - X509 - * `urn:oasis:names:tc:SAML:2.0:nameid-format:WindowsDomainQualifiedName` - Windows - * `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient + description: NameID Policy sent to the IdP. Can be unset, in which case + no Policy is sent. binding_type: $ref: '#/components/schemas/BindingTypeEnum' verification_kp: @@ -42936,21 +46341,181 @@ components: - name - token - url - SCIMSyncStatus: + SCIMSource: type: object - description: SCIM Provider sync status + description: SCIMSource Serializer properties: - is_running: - type: boolean + pk: + type: string + format: uuid readOnly: true - tasks: - type: array - items: - $ref: '#/components/schemas/SystemTask' + title: Pbm uuid + name: + type: string + description: Source's display Name. + slug: + type: string + description: Internal source name, used in URLs. + maxLength: 50 + pattern: ^[-a-zA-Z0-9_]+$ + enabled: + type: boolean + component: + type: string + description: Get object component so that we know how to edit the object + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + user_matching_mode: + allOf: + - $ref: '#/components/schemas/UserMatchingModeEnum' + description: How the source determines if an existing user should be authenticated + or a new user enrolled. + managed: + type: string + nullable: true + title: Managed by authentik + description: Objects that are managed by authentik. These objects are created + and updated automatically. This flag only indicates that an object can + be overwritten by migrations. You can still modify the objects via the + API, but expect changes to be overwritten in a later update. + readOnly: true + user_path_template: + type: string + root_url: + type: string + description: Get Root URL + readOnly: true + token_obj: + allOf: + - $ref: '#/components/schemas/Token' readOnly: true required: - - is_running - - tasks + - component + - managed + - meta_model_name + - name + - pk + - root_url + - slug + - token_obj + - verbose_name + - verbose_name_plural + SCIMSourceGroup: + type: object + description: SCIMSourceGroup Serializer + properties: + id: + type: string + group: + type: string + format: uuid + group_obj: + allOf: + - $ref: '#/components/schemas/UserGroup' + readOnly: true + source: + type: string + format: uuid + attributes: {} + required: + - group + - group_obj + - id + - source + SCIMSourceGroupRequest: + type: object + description: SCIMSourceGroup Serializer + properties: + id: + type: string + minLength: 1 + group: + type: string + format: uuid + source: + type: string + format: uuid + attributes: {} + required: + - group + - id + - source + SCIMSourceRequest: + type: object + description: SCIMSource Serializer + properties: + name: + type: string + minLength: 1 + description: Source's display Name. + slug: + type: string + minLength: 1 + description: Internal source name, used in URLs. + maxLength: 50 + pattern: ^[-a-zA-Z0-9_]+$ + enabled: + type: boolean + user_matching_mode: + allOf: + - $ref: '#/components/schemas/UserMatchingModeEnum' + description: How the source determines if an existing user should be authenticated + or a new user enrolled. + user_path_template: + type: string + minLength: 1 + required: + - name + - slug + SCIMSourceUser: + type: object + description: SCIMSourceUser Serializer + properties: + id: + type: string + user: + type: integer + user_obj: + allOf: + - $ref: '#/components/schemas/GroupMember' + readOnly: true + source: + type: string + format: uuid + attributes: {} + required: + - id + - source + - user + - user_obj + SCIMSourceUserRequest: + type: object + description: SCIMSourceUser Serializer + properties: + id: + type: string + minLength: 1 + user: + type: integer + source: + type: string + format: uuid + attributes: {} + required: + - id + - source + - user SMSDevice: type: object description: Serializer for sms authenticator devices @@ -43192,6 +46757,14 @@ components: description: Fields to show in the user directory. user_directory_attributes: description: Attributes to show in the user directory. + default_token_duration: + type: string + description: Default token duration + default_token_length: + type: integer + maximum: 2147483647 + minimum: 1 + description: Default token length SettingsRequest: type: object description: Settings Serializer @@ -43227,16 +46800,21 @@ components: description: Fields to show in the user directory. user_directory_attributes: description: Attributes to show in the user directory. + default_token_duration: + type: string + minLength: 1 + description: Default token duration + default_token_length: + type: integer + maximum: 2147483647 + minimum: 1 + description: Default token length SeverityEnum: enum: - notice - warning - alert type: string - description: |- - * `notice` - Notice - * `warning` - Warning - * `alert` - Alert ShellChallenge: type: object description: challenge type to render HTML as-is @@ -43265,14 +46843,12 @@ components: - http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha384 - http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384 + - http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512 - http://www.w3.org/2000/09/xmldsig#dsa-sha1 type: string - description: |- - * `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - RSA-SHA1 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256` - RSA-SHA256 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384` - RSA-SHA384 - * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512` - RSA-SHA512 - * `http://www.w3.org/2000/09/xmldsig#dsa-sha1` - DSA-SHA1 Source: type: object description: Source Serializer @@ -43323,14 +46899,8 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. managed: type: string nullable: true @@ -43390,20 +46960,82 @@ components: user_matching_mode: allOf: - $ref: '#/components/schemas/UserMatchingModeEnum' - description: |- - How the source determines if an existing user should be authenticated or a new user enrolled. - - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. + description: How the source determines if an existing user should be authenticated + or a new user enrolled. user_path_template: type: string minLength: 1 required: - name - slug + SourceStage: + type: object + description: SourceStage Serializer + properties: + pk: + type: string + format: uuid + readOnly: true + title: Stage uuid + name: + type: string + component: + type: string + description: Get object type so that we know how to edit the object + readOnly: true + verbose_name: + type: string + description: Return object's verbose_name + readOnly: true + verbose_name_plural: + type: string + description: Return object's plural verbose_name + readOnly: true + meta_model_name: + type: string + description: Return internal model name + readOnly: true + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSet' + source: + type: string + format: uuid + resume_timeout: + type: string + description: 'Amount of time a user can take to return from the source to + continue the flow (Format: hours=-1;minutes=-2;seconds=-3)' + required: + - component + - meta_model_name + - name + - pk + - source + - verbose_name + - verbose_name_plural + SourceStageRequest: + type: object + description: SourceStage Serializer + properties: + name: + type: string + minLength: 1 + flow_set: + type: array + items: + $ref: '#/components/schemas/FlowSetRequest' + source: + type: string + format: uuid + resume_timeout: + type: string + minLength: 1 + description: 'Amount of time a user can take to return from the source to + continue the flow (Format: hours=-1;minutes=-2;seconds=-3)' + required: + - name + - source SourceType: type: object description: Serializer for SourceType @@ -43453,9 +47085,6 @@ components: - redirect - post type: string - description: |- - * `redirect` - Redirect - * `post` - Post Stage: type: object description: Stage Serializer @@ -43602,13 +47231,21 @@ components: - user_email - user_upn type: string - description: |- - * `hashed_user_id` - Based on the Hashed User ID - * `user_id` - Based on user ID - * `user_uuid` - Based on user UUID - * `user_username` - Based on the username - * `user_email` - Based on the User's Email. This is recommended over the UPN method. - * `user_upn` - Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. + SyncStatus: + type: object + description: Provider sync status + properties: + is_running: + type: boolean + readOnly: true + tasks: + type: array + items: + $ref: '#/components/schemas/SystemTask' + readOnly: true + required: + - is_running + - tasks SystemInfo: type: object description: Get system information. @@ -43633,8 +47270,6 @@ components: properties: python_version: type: string - gunicorn_version: - type: string environment: type: string architecture: @@ -43643,10 +47278,18 @@ components: type: string uname: type: string + openssl_version: + type: string + openssl_fips_mode: + type: boolean + authentik_version: + type: string required: - architecture + - authentik_version - environment - - gunicorn_version + - openssl_fips_mode + - openssl_version - platform - python_version - uname @@ -43698,24 +47341,27 @@ components: start_timestamp: type: string format: date-time - description: Timestamp when the task started readOnly: true finish_timestamp: type: string format: date-time - description: Timestamp when the task finished readOnly: true duration: type: number format: double - description: Get the duration a task took to run readOnly: true status: $ref: '#/components/schemas/SystemTaskStatusEnum' messages: type: array items: - type: string + $ref: '#/components/schemas/LogEvent' + expires: + type: string + format: date-time + nullable: true + expiring: + type: boolean required: - description - duration @@ -43733,11 +47379,6 @@ components: - warning - error type: string - description: |- - * `unknown` - UNKNOWN - * `successful` - SUCCESSFUL - * `warning` - WARNING - * `error` - ERROR TOTPDevice: type: object description: Serializer for totp authenticator devices @@ -43866,6 +47507,7 @@ components: expires: type: string format: date-time + nullable: true expiring: type: boolean required: @@ -43891,6 +47533,7 @@ components: expires: type: string format: date-time + nullable: true scope: type: array items: @@ -43935,6 +47578,7 @@ components: expires: type: string format: date-time + nullable: true expiring: type: boolean required: @@ -43995,6 +47639,8 @@ components: type: string model_name: type: string + icon_url: + type: string requires_enterprise: type: boolean default: false @@ -44009,10 +47655,6 @@ components: - light - dark type: string - description: |- - * `automatic` - Automatic - * `light` - Light - * `dark` - Dark UsedBy: type: object description: A list of all objects referencing the queried object @@ -44040,11 +47682,6 @@ components: - set_null - set_default type: string - description: |- - * `cascade` - CASCADE - * `cascade_many` - CASCADE_MANY - * `set_null` - SET_NULL - * `set_default` - SET_DEFAULT User: type: object description: User Serializer @@ -44081,6 +47718,7 @@ components: items: $ref: '#/components/schemas/UserGroup' readOnly: true + nullable: true email: type: string format: email @@ -44088,6 +47726,7 @@ components: maxLength: 254 avatar: type: string + description: User's avatar, either a http/https URL or a data URI readOnly: true attributes: type: object @@ -44181,6 +47820,9 @@ components: expires: type: string format: date-time + nullable: true + expiring: + type: boolean user: $ref: '#/components/schemas/User' application: @@ -44198,10 +47840,6 @@ components: - create_when_required - always_create type: string - description: |- - * `never_create` - Never Create - * `create_when_required` - Create When Required - * `always_create` - Always Create UserDeleteStage: type: object description: UserDeleteStage Serializer @@ -44297,10 +47935,6 @@ components: - username - upn type: string - description: |- - * `email` - E Mail - * `username` - Username - * `upn` - Upn UserGroup: type: object description: Simplified Group Serializer for user's groups @@ -44327,6 +47961,7 @@ components: parent_name: type: string readOnly: true + nullable: true attributes: type: object additionalProperties: {} @@ -44438,23 +48073,12 @@ components: network_binding: allOf: - $ref: '#/components/schemas/NetworkBindingEnum' - description: |- - Bind sessions created by this stage to the configured network - - * `no_binding` - No Binding - * `bind_asn` - Bind Asn - * `bind_asn_network` - Bind Asn Network - * `bind_asn_network_ip` - Bind Asn Network Ip + description: Bind sessions created by this stage to the configured network geoip_binding: allOf: - $ref: '#/components/schemas/GeoipBindingEnum' - description: |- - Bind sessions created by this stage to the configured GeoIP location - - * `no_binding` - No Binding - * `bind_continent` - Bind Continent - * `bind_continent_country` - Bind Continent Country - * `bind_continent_country_city` - Bind Continent Country City + description: Bind sessions created by this stage to the configured GeoIP + location required: - component - meta_model_name @@ -44490,23 +48114,12 @@ components: network_binding: allOf: - $ref: '#/components/schemas/NetworkBindingEnum' - description: |- - Bind sessions created by this stage to the configured network - - * `no_binding` - No Binding - * `bind_asn` - Bind Asn - * `bind_asn_network` - Bind Asn Network - * `bind_asn_network_ip` - Bind Asn Network Ip + description: Bind sessions created by this stage to the configured network geoip_binding: allOf: - $ref: '#/components/schemas/GeoipBindingEnum' - description: |- - Bind sessions created by this stage to the configured GeoIP location - - * `no_binding` - No Binding - * `bind_continent` - Bind Continent - * `bind_continent_country` - Bind Continent Country - * `bind_continent_country_city` - Bind Continent Country City + description: Bind sessions created by this stage to the configured GeoIP + location required: - name UserLogoutStage: @@ -44568,12 +48181,6 @@ components: - username_link - username_deny type: string - description: |- - * `identifier` - Use the source-specific identifier - * `email_link` - Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses. - * `email_deny` - Use the user's email address, but deny enrollment when the email address already exists. - * `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source. - * `username_deny` - Use the user's username, but deny enrollment when the username already exists. UserMetrics: type: object description: User Metrics @@ -44797,6 +48404,7 @@ components: maxLength: 254 avatar: type: string + description: User's avatar, either a http/https URL or a data URI readOnly: true uid: type: string @@ -44922,21 +48530,12 @@ components: - service_account - internal_service_account type: string - description: |- - * `internal` - Internal - * `external` - External - * `service_account` - Service Account - * `internal_service_account` - Internal Service Account UserVerificationEnum: enum: - required - preferred - discouraged type: string - description: |- - * `required` - Required - * `preferred` - Preferred - * `discouraged` - Discouraged UserWriteStage: type: object description: UserWriteStage Serializer @@ -45039,6 +48638,10 @@ components: type: string description: Get latest version from cache readOnly: true + version_latest_valid: + type: boolean + description: Check if latest version is valid + readOnly: true build_hash: type: string description: Get build hash, if version is not latest or released @@ -45052,6 +48655,7 @@ components: - outdated - version_current - version_latest + - version_latest_valid WebAuthnDevice: type: object description: Serializer for WebAuthn authenticator devices @@ -45067,8 +48671,18 @@ components: type: string format: date-time readOnly: true + device_type: + allOf: + - $ref: '#/components/schemas/WebAuthnDeviceType' + readOnly: true + nullable: true + aaguid: + type: string + readOnly: true required: + - aaguid - created_on + - device_type - name - pk WebAuthnDeviceRequest: @@ -45081,6 +48695,31 @@ components: maxLength: 200 required: - name + WebAuthnDeviceType: + type: object + description: WebAuthnDeviceType Serializer + properties: + aaguid: + type: string + format: uuid + description: + type: string + required: + - aaguid + - description + WebAuthnDeviceTypeRequest: + type: object + description: WebAuthnDeviceType Serializer + properties: + aaguid: + type: string + format: uuid + description: + type: string + minLength: 1 + required: + - aaguid + - description Workers: type: object properties: @@ -45090,7 +48729,9 @@ components: - count modelRequest: oneOf: + - $ref: '#/components/schemas/GoogleWorkspaceProviderRequest' - $ref: '#/components/schemas/LDAPProviderRequest' + - $ref: '#/components/schemas/MicrosoftEntraProviderRequest' - $ref: '#/components/schemas/OAuth2ProviderRequest' - $ref: '#/components/schemas/ProxyProviderRequest' - $ref: '#/components/schemas/RACProviderRequest' @@ -45100,7 +48741,9 @@ components: discriminator: propertyName: provider_model mapping: + authentik_providers_google_workspace.googleworkspaceprovider: '#/components/schemas/GoogleWorkspaceProviderRequest' authentik_providers_ldap.ldapprovider: '#/components/schemas/LDAPProviderRequest' + authentik_providers_microsoft_entra.microsoftentraprovider: '#/components/schemas/MicrosoftEntraProviderRequest' authentik_providers_oauth2.oauth2provider: '#/components/schemas/OAuth2ProviderRequest' authentik_providers_proxy.proxyprovider: '#/components/schemas/ProxyProviderRequest' authentik_providers_rac.racprovider: '#/components/schemas/RACProviderRequest' @@ -45109,9 +48752,7 @@ components: authentik_providers_scim.scimprovider: '#/components/schemas/SCIMProviderRequest' securitySchemes: authentik: - type: apiKey - in: header - name: Authorization + type: http scheme: bearer servers: - url: /api/v3/ diff --git a/scripts/api-py-config.yaml b/scripts/api-py-config.yaml new file mode 100644 index 0000000000..95dcf5597b --- /dev/null +++ b/scripts/api-py-config.yaml @@ -0,0 +1,4 @@ +additionalProperties: + packageName: authentik_client + projectName: authentik-client + infoName: authentik Team diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml index 7e269c5967..2e1f9cbf3e 100644 --- a/scripts/docker-compose.yml +++ b/scripts/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.7" - services: postgresql: container_name: postgres diff --git a/scripts/generate_config.py b/scripts/generate_config.py index 379ec18736..2fb164aa90 100644 --- a/scripts/generate_config.py +++ b/scripts/generate_config.py @@ -1,4 +1,5 @@ """Generate config for development""" + from yaml import safe_dump from authentik.lib.generators import generate_id @@ -11,6 +12,9 @@ with open("local.env.yml", "w", encoding="utf-8") as _config: "secret_key": generate_id(), "postgresql": { "user": "postgres", + "read_replicas": { + "0": {}, + }, }, "outposts": { "container_image_base": "ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s", diff --git a/scripts/npm_version.py b/scripts/npm_version.py index 2c0d3a9e2d..8ce53d8ace 100644 --- a/scripts/npm_version.py +++ b/scripts/npm_version.py @@ -1,4 +1,5 @@ """Helper script to generate an NPM Version""" + from time import time from authentik import __version__ diff --git a/tests/e2e/docker-compose.yml b/tests/e2e/docker-compose.yml index 4787f8a71c..ec0e57558a 100644 --- a/tests/e2e/docker-compose.yml +++ b/tests/e2e/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: chrome: - image: docker.io/selenium/standalone-chrome:110.0 + image: docker.io/selenium/standalone-chrome:122.0 volumes: - /dev/shm:/dev/shm network_mode: host diff --git a/tests/e2e/test_flows_authenticators.py b/tests/e2e/test_flows_authenticators.py index 80e55b6a6a..ec0327bb7a 100644 --- a/tests/e2e/test_flows_authenticators.py +++ b/tests/e2e/test_flows_authenticators.py @@ -1,4 +1,5 @@ """test flow with otp stages""" + from base64 import b32decode from time import sleep from urllib.parse import parse_qs, urlparse diff --git a/tests/e2e/test_flows_enroll.py b/tests/e2e/test_flows_enroll.py index ddf9959cc4..95ae6a8396 100644 --- a/tests/e2e/test_flows_enroll.py +++ b/tests/e2e/test_flows_enroll.py @@ -1,4 +1,5 @@ """Test Enroll flow""" + from time import sleep from selenium.webdriver.common.by import By @@ -40,7 +41,9 @@ class TestFlowsEnroll(SeleniumTestCase): interface_user = self.get_shadow_root("ak-interface-user") wait = WebDriverWait(interface_user, self.wait_timeout) - wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, ".pf-c-page__header"))) + wait.until( + ec.presence_of_element_located((By.CSS_SELECTOR, "ak-interface-user-presentation")) + ) self.driver.get(self.if_user_url("/settings")) user = User.objects.get(username="foo") @@ -93,7 +96,9 @@ class TestFlowsEnroll(SeleniumTestCase): # We're now logged in wait = WebDriverWait(self.get_shadow_root("ak-interface-user"), self.wait_timeout) - wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, ".pf-c-page__header"))) + wait.until( + ec.presence_of_element_located((By.CSS_SELECTOR, "ak-interface-user-presentation")) + ) self.driver.get(self.if_user_url("/settings")) self.assert_user(User.objects.get(username="foo")) @@ -124,6 +129,7 @@ class TestFlowsEnroll(SeleniumTestCase): prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click() # Second prompt stage + sleep(1) flow_executor = self.get_shadow_root("ak-flow-executor") prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor) wait = WebDriverWait(prompt_stage, self.wait_timeout) diff --git a/tests/e2e/test_flows_login.py b/tests/e2e/test_flows_login.py index aa477a519a..51c8281f88 100644 --- a/tests/e2e/test_flows_login.py +++ b/tests/e2e/test_flows_login.py @@ -1,4 +1,5 @@ """test default login flow""" + from authentik.blueprints.tests import apply_blueprint from tests.e2e.utils import SeleniumTestCase, retry diff --git a/tests/e2e/test_flows_recovery.py b/tests/e2e/test_flows_recovery.py index ddddd9140c..ae867c2fa9 100644 --- a/tests/e2e/test_flows_recovery.py +++ b/tests/e2e/test_flows_recovery.py @@ -1,4 +1,5 @@ """Test recovery flow""" + from time import sleep from selenium.webdriver.common.by import By @@ -100,7 +101,9 @@ class TestFlowsRecovery(SeleniumTestCase): # We're now logged in wait = WebDriverWait(self.get_shadow_root("ak-interface-user"), self.wait_timeout) - wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, ".pf-c-page__header"))) + wait.until( + ec.presence_of_element_located((By.CSS_SELECTOR, "ak-interface-user-presentation")) + ) self.driver.get(self.if_user_url("/settings")) self.assert_user(user) diff --git a/tests/e2e/test_flows_stage_setup.py b/tests/e2e/test_flows_stage_setup.py index f0c791ffe6..a82b2b7a28 100644 --- a/tests/e2e/test_flows_stage_setup.py +++ b/tests/e2e/test_flows_stage_setup.py @@ -1,4 +1,5 @@ """test stage setup flows (password change)""" + from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys diff --git a/tests/e2e/test_provider_ldap.py b/tests/e2e/test_provider_ldap.py index 72f5131031..465c6e68fc 100644 --- a/tests/e2e/test_provider_ldap.py +++ b/tests/e2e/test_provider_ldap.py @@ -1,4 +1,5 @@ """LDAP and Outpost e2e tests""" + from dataclasses import asdict from time import sleep @@ -70,7 +71,7 @@ class TestProviderLDAP(SeleniumTestCase): # Wait until outpost healthcheck succeeds healthcheck_retries = 0 - while healthcheck_retries < 50: + while healthcheck_retries < 50: # noqa: PLR2004 if len(outpost.state) > 0: state = outpost.state[0] if state.last_seen: diff --git a/tests/e2e/test_provider_oauth2_github.py b/tests/e2e/test_provider_oauth2_github.py index 5095421a8c..64eecd032d 100644 --- a/tests/e2e/test_provider_oauth2_github.py +++ b/tests/e2e/test_provider_oauth2_github.py @@ -1,6 +1,7 @@ """test OAuth Provider flow""" + from time import sleep -from typing import Any, Optional +from typing import Any from docker.types import Healthcheck from selenium.webdriver.common.by import By @@ -24,7 +25,7 @@ class TestProviderOAuth2Github(SeleniumTestCase): self.client_secret = generate_key() super().setUp() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: """Setup client grafana container which we test OAuth against""" return { "image": "grafana/grafana:7.1.0", diff --git a/tests/e2e/test_provider_oauth2_grafana.py b/tests/e2e/test_provider_oauth2_grafana.py index fa8f12d1d3..0bdd167560 100644 --- a/tests/e2e/test_provider_oauth2_grafana.py +++ b/tests/e2e/test_provider_oauth2_grafana.py @@ -1,6 +1,7 @@ """test OAuth2 OpenID Provider flow""" + from time import sleep -from typing import Any, Optional +from typing import Any from docker.types import Healthcheck from selenium.webdriver.common.by import By @@ -32,7 +33,7 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): self.app_slug = generate_id(20) super().setUp() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "grafana/grafana:7.1.0", "detach": True, diff --git a/tests/e2e/test_provider_oidc.py b/tests/e2e/test_provider_oidc.py index c14a498a61..5af7e3f2a9 100644 --- a/tests/e2e/test_provider_oidc.py +++ b/tests/e2e/test_provider_oidc.py @@ -1,4 +1,5 @@ """test OAuth2 OpenID Provider flow""" + from json import loads from time import sleep diff --git a/tests/e2e/test_provider_oidc_implicit.py b/tests/e2e/test_provider_oidc_implicit.py index 37dff0aa32..9d35c2cc43 100644 --- a/tests/e2e/test_provider_oidc_implicit.py +++ b/tests/e2e/test_provider_oidc_implicit.py @@ -1,4 +1,5 @@ """test OAuth2 OpenID Provider flow""" + from json import loads from time import sleep diff --git a/tests/e2e/test_provider_proxy.py b/tests/e2e/test_provider_proxy.py index e91e806660..bb4844dcae 100644 --- a/tests/e2e/test_provider_proxy.py +++ b/tests/e2e/test_provider_proxy.py @@ -1,9 +1,10 @@ """Proxy and Outpost e2e tests""" + from base64 import b64encode from dataclasses import asdict from sys import platform from time import sleep -from typing import Any, Optional +from typing import Any from unittest.case import skip, skipUnless from channels.testing import ChannelsLiveServerTestCase @@ -31,7 +32,7 @@ class TestProviderProxy(SeleniumTestCase): self.output_container_logs(self.proxy_container) self.proxy_container.kill() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "traefik/whoami:latest", "detach": True, @@ -100,7 +101,7 @@ class TestProviderProxy(SeleniumTestCase): # Wait until outpost healthcheck succeeds healthcheck_retries = 0 - while healthcheck_retries < 50: + while healthcheck_retries < 50: # noqa: PLR2004 if len(outpost.state) > 0: state = outpost.state[0] if state.last_seen: @@ -170,7 +171,7 @@ class TestProviderProxy(SeleniumTestCase): # Wait until outpost healthcheck succeeds healthcheck_retries = 0 - while healthcheck_retries < 50: + while healthcheck_retries < 50: # noqa: PLR2004 if len(outpost.state) > 0: state = outpost.state[0] if state.last_seen: @@ -211,7 +212,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase): @reconcile_app("authentik_crypto") def test_proxy_connectivity(self): """Test proxy connectivity over websocket""" - outpost_connection_discovery() # pylint: disable=no-value-for-parameter + outpost_connection_discovery() proxy: ProxyProvider = ProxyProvider.objects.create( name=generate_id(), authorization_flow=Flow.objects.get( @@ -237,7 +238,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase): # Wait until outpost healthcheck succeeds healthcheck_retries = 0 - while healthcheck_retries < 50: + while healthcheck_retries < 50: # noqa: PLR2004 if len(outpost.state) > 0: state = outpost.state[0] if state.last_seen and state.version: diff --git a/tests/e2e/test_provider_radius.py b/tests/e2e/test_provider_radius.py index b4856e034e..f67f6a1885 100644 --- a/tests/e2e/test_provider_radius.py +++ b/tests/e2e/test_provider_radius.py @@ -1,4 +1,5 @@ """Radius e2e tests""" + from dataclasses import asdict from time import sleep @@ -65,7 +66,7 @@ class TestProviderRadius(SeleniumTestCase): # Wait until outpost healthcheck succeeds healthcheck_retries = 0 - while healthcheck_retries < 50: + while healthcheck_retries < 50: # noqa: PLR2004 if len(outpost.state) > 0: state = outpost.state[0] if state.last_seen: diff --git a/tests/e2e/test_provider_saml.py b/tests/e2e/test_provider_saml.py index eefb2c45e1..27c7c94fc4 100644 --- a/tests/e2e/test_provider_saml.py +++ b/tests/e2e/test_provider_saml.py @@ -1,4 +1,5 @@ """test SAML Provider flow""" + from json import loads from time import sleep diff --git a/tests/e2e/test_source_ldap_samba.py b/tests/e2e/test_source_ldap_samba.py index 7711389128..fb9aa6d12a 100644 --- a/tests/e2e/test_source_ldap_samba.py +++ b/tests/e2e/test_source_ldap_samba.py @@ -1,5 +1,6 @@ """test LDAP Source""" -from typing import Any, Optional + +from typing import Any from django.db.models import Q from ldap3.core.exceptions import LDAPSessionTerminatedByServerError @@ -22,7 +23,7 @@ class TestSourceLDAPSamba(SeleniumTestCase): self.admin_password = generate_key() super().setUp() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "ghcr.io/beryju/test-samba-dc:latest", "detach": True, @@ -127,6 +128,7 @@ class TestSourceLDAPSamba(SeleniumTestCase): base_dn="dc=test,dc=goauthentik,dc=io", additional_user_dn="ou=users", additional_group_dn="ou=groups", + password_login_update_internal_password=True, ) source.property_mappings.set( LDAPPropertyMapping.objects.filter( diff --git a/tests/e2e/test_source_oauth_oauth1.py b/tests/e2e/test_source_oauth_oauth1.py index 97152321f8..1da92a4c3e 100644 --- a/tests/e2e/test_source_oauth_oauth1.py +++ b/tests/e2e/test_source_oauth_oauth1.py @@ -1,6 +1,7 @@ """test OAuth Source""" + from time import sleep -from typing import Any, Optional +from typing import Any from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys @@ -59,7 +60,7 @@ class TestSourceOAuth1(SeleniumTestCase): self.source_slug = generate_id() super().setUp() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "ghcr.io/beryju/oauth1-test-server:v1.1", "detach": True, diff --git a/tests/e2e/test_source_oauth_oauth2.py b/tests/e2e/test_source_oauth_oauth2.py index 17a26279e5..5986de7c47 100644 --- a/tests/e2e/test_source_oauth_oauth2.py +++ b/tests/e2e/test_source_oauth_oauth2.py @@ -1,7 +1,8 @@ """test OAuth Source""" + from pathlib import Path from time import sleep -from typing import Any, Optional +from typing import Any from docker.models.containers import Container from docker.types import Healthcheck @@ -68,7 +69,7 @@ class TestSourceOAuth2(SeleniumTestCase): with open(CONFIG_PATH, "w+", encoding="utf8") as _file: safe_dump(config, _file) - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "ghcr.io/dexidp/dex:v2.28.1", "detach": True, diff --git a/tests/e2e/test_source_saml.py b/tests/e2e/test_source_saml.py index 2051b56a16..433ca42527 100644 --- a/tests/e2e/test_source_saml.py +++ b/tests/e2e/test_source_saml.py @@ -1,9 +1,9 @@ """test SAML Source""" + from time import sleep -from typing import Any, Optional +from typing import Any from docker.types import Healthcheck -from guardian.utils import get_anonymous_user from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as ec @@ -77,7 +77,7 @@ class TestSourceSAML(SeleniumTestCase): self.slug = generate_id() super().setUp() - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: return { "image": "kristophjunge/test-saml-idp:1.15", "detach": True, @@ -161,7 +161,7 @@ class TestSourceSAML(SeleniumTestCase): self.assert_user( User.objects.exclude(username="akadmin") .exclude(username__startswith="ak-outpost") - .exclude(pk=get_anonymous_user().pk) + .exclude_anonymous() .exclude(pk=self.user.pk) .first() ) @@ -244,7 +244,7 @@ class TestSourceSAML(SeleniumTestCase): self.assert_user( User.objects.exclude(username="akadmin") .exclude(username__startswith="ak-outpost") - .exclude(pk=get_anonymous_user().pk) + .exclude_anonymous() .exclude(pk=self.user.pk) .first() ) @@ -314,7 +314,7 @@ class TestSourceSAML(SeleniumTestCase): self.assert_user( User.objects.exclude(username="akadmin") .exclude(username__startswith="ak-outpost") - .exclude(pk=get_anonymous_user().pk) + .exclude_anonymous() .exclude(pk=self.user.pk) .first() ) diff --git a/tests/e2e/test_source_scim.py b/tests/e2e/test_source_scim.py new file mode 100644 index 0000000000..26d406fc60 --- /dev/null +++ b/tests/e2e/test_source_scim.py @@ -0,0 +1,80 @@ +"""test SCIM Source""" + +from pprint import pformat +from time import sleep +from typing import Any + +from docker.types import Healthcheck + +from authentik.lib.generators import generate_id +from authentik.lib.utils.http import get_http_session +from authentik.sources.scim.models import SCIMSource +from tests.e2e.utils import SeleniumTestCase, retry + +TEST_POLL_MAX = 25 + + +class TestSourceSCIM(SeleniumTestCase): + """test SCIM Source flow""" + + def setUp(self): + self.slug = generate_id() + super().setUp() + + def get_container_specs(self) -> dict[str, Any] | None: + return { + "image": ( + "ghcr.io/suvera/scim2-compliance-test-utility@sha256:eca913bb73" + "c46892cd1fb2dfd2fef1c5881e6abc5cb0eec7e92fb78c1b933ece" + ), + "detach": True, + "ports": {"8080": "8080"}, + "auto_remove": True, + "healthcheck": Healthcheck( + test=["CMD", "curl", "http://localhost:8080"], + interval=5 * 1_000 * 1_000_000, + start_period=1 * 1_000 * 1_000_000, + ), + } + + @retry() + def test_scim_conformance(self): + source = SCIMSource.objects.create( + name=generate_id(), + slug=generate_id(), + ) + session = get_http_session() + test_launch = session.post( + "http://localhost:8080/test/run", + data={ + "endPoint": self.live_server_url + f"/source/scim/{source.slug}/v2", + "username": "foo", + "password": source.token.key, + "jwtToken": None, + "usersCheck": 1, + "groupsCheck": 1, + "checkIndResLocation": 1, + }, + ) + self.assertEqual(test_launch.status_code, 200) + test_id = test_launch.json()["id"] + attempt = 0 + while attempt <= TEST_POLL_MAX: + test_status = session.get( + "http://localhost:8080/test/status", + params={"runId": test_id}, + ) + self.assertEqual(test_status.status_code, 200) + body = test_status.json() + if any([data["title"] == "--DONE--" for data in body["data"]]): + break + attempt += 1 + sleep(1) + for test in body["data"]: + # Workaround, the test expects DELETE requests to return 204 and have + # the content type set to the JSON SCIM one, which is not what most HTTP servers do + if test["requestMethod"] == "DELETE" and test["responseCode"] == 204: # noqa: PLR2004 + continue + if test["title"] == "--DONE--": + break + self.assertTrue(test["success"], pformat(test)) diff --git a/tests/e2e/utils.py b/tests/e2e/utils.py index fdf742845b..616ed95a60 100644 --- a/tests/e2e/utils.py +++ b/tests/e2e/utils.py @@ -1,12 +1,14 @@ """authentik e2e testing utilities""" + import json import os import socket +from collections.abc import Callable from functools import lru_cache, wraps from os import environ from sys import stderr from time import sleep -from typing import Any, Callable, Optional +from typing import Any from django.apps import apps from django.contrib.staticfiles.testing import StaticLiveServerTestCase @@ -65,7 +67,7 @@ class DockerTestCase: return container sleep(1) attempt += 1 - if attempt >= 30: + if attempt >= 30: # noqa: PLR2004 self.failureException("Container failed to start") @@ -73,7 +75,7 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase): """StaticLiveServerTestCase which automatically creates a Webdriver instance""" host = get_local_ip() - container: Optional[Container] = None + container: Container | None = None wait_timeout: int user: User @@ -113,17 +115,19 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase): self.wait_for_container(container) return container - def output_container_logs(self, container: Optional[Container] = None): + def output_container_logs(self, container: Container | None = None): """Output the container logs to our STDOUT""" _container = container or self.container if IS_CI: - print(f"::group::Container logs - {_container.image.tags[0]}") + image = _container.image + tags = image.tags[0] if len(image.tags) > 0 else str(image) + print(f"::group::Container logs - {tags}") for log in _container.logs().decode().split("\n"): print(log) if IS_CI: print("::endgroup::") - def get_container_specs(self) -> Optional[dict[str, Any]]: + def get_container_specs(self) -> dict[str, Any] | None: """Optionally get container specs which will launched on setup, wait for the container to be healthy, and deleted again on tearDown""" return None @@ -177,7 +181,7 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase): return f"{self.live_server_url}/if/user/#{view}" def get_shadow_root( - self, selector: str, container: Optional[WebElement | WebDriver] = None + self, selector: str, container: WebElement | WebDriver | None = None ) -> WebElement: """Get shadow root element's inner shadowRoot""" if not container: @@ -244,12 +248,12 @@ def retry(max_retires=RETRIES, exceptions=None): nonlocal count try: return func(self, *args, **kwargs) - # pylint: disable=catching-non-exception + except tuple(exceptions) as exc: count += 1 if count > max_retires: logger.debug("Exceeded retry count", exc=exc, test=self) - # pylint: disable=raising-non-exception + raise exc logger.debug("Retrying on error", exc=exc, test=self) self.tearDown() diff --git a/tests/integration/test_outpost_docker.py b/tests/integration/test_outpost_docker.py index 99daf19159..7fd6dfd3fd 100644 --- a/tests/integration/test_outpost_docker.py +++ b/tests/integration/test_outpost_docker.py @@ -1,4 +1,5 @@ """outpost tests""" + from shutil import rmtree from tempfile import mkdtemp @@ -53,7 +54,7 @@ class OutpostDockerTests(DockerTestCase, ChannelsLiveServerTestCase): self.ssl_folder = mkdtemp() self.container = self._start_container(self.ssl_folder) # Ensure that local connection have been created - outpost_connection_discovery() # pylint: disable=no-value-for-parameter + outpost_connection_discovery() self.provider: ProxyProvider = ProxyProvider.objects.create( name="test", internal_host="http://localhost", diff --git a/tests/integration/test_outpost_kubernetes.py b/tests/integration/test_outpost_kubernetes.py index 58a1195dda..099eddc87a 100644 --- a/tests/integration/test_outpost_kubernetes.py +++ b/tests/integration/test_outpost_kubernetes.py @@ -1,4 +1,5 @@ """outpost tests""" + from unittest.mock import MagicMock, patch import pytest @@ -9,6 +10,7 @@ from kubernetes.client.exceptions import OpenApiException from authentik.core.tests.utils import create_test_flow from authentik.lib.config import CONFIG from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler +from authentik.outposts.controllers.k8s.service import ServiceReconciler from authentik.outposts.controllers.k8s.triggers import NeedsUpdate from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType from authentik.outposts.tasks import outpost_connection_discovery @@ -22,7 +24,7 @@ class OutpostKubernetesTests(TestCase): def setUp(self): super().setUp() # Ensure that local connection have been created - outpost_connection_discovery() # pylint: disable=no-value-for-parameter + outpost_connection_discovery() self.provider: ProxyProvider = ProxyProvider.objects.create( name="test", internal_host="http://localhost", @@ -90,6 +92,35 @@ class OutpostKubernetesTests(TestCase): deployment_reconciler.delete(deployment_reconciler.get_reference_object()) + @pytest.mark.timeout(120) + def test_service_reconciler(self): + """test that service requires update""" + controller = ProxyKubernetesController(self.outpost, self.service_connection) + service_reconciler = ServiceReconciler(controller) + + self.assertIsNotNone(service_reconciler.retrieve()) + + config = self.outpost.config + config.kubernetes_service_type = "NodePort" + config.kubernetes_json_patches = { + "service": [ + { + "op": "add", + "path": "/spec/ipFamilyPolicy", + "value": "PreferDualStack", + } + ] + } + self.outpost.config = config + + with self.assertRaises(NeedsUpdate): + service_reconciler.reconcile( + service_reconciler.retrieve(), + service_reconciler.get_reference_object(), + ) + + service_reconciler.delete(service_reconciler.get_reference_object()) + @pytest.mark.timeout(120) def test_controller_rename(self): """test that objects get deleted and re-created with new names""" diff --git a/tests/integration/test_proxy_docker.py b/tests/integration/test_proxy_docker.py index 7ba027cdd8..9aefccf39d 100644 --- a/tests/integration/test_proxy_docker.py +++ b/tests/integration/test_proxy_docker.py @@ -1,4 +1,5 @@ """outpost tests""" + from shutil import rmtree from tempfile import mkdtemp @@ -53,7 +54,7 @@ class TestProxyDocker(DockerTestCase, ChannelsLiveServerTestCase): self.ssl_folder = mkdtemp() self.container = self._start_container(self.ssl_folder) # Ensure that local connection have been created - outpost_connection_discovery() # pylint: disable=no-value-for-parameter + outpost_connection_discovery() self.provider: ProxyProvider = ProxyProvider.objects.create( name="test", internal_host="http://localhost", diff --git a/tests/integration/test_proxy_kubernetes.py b/tests/integration/test_proxy_kubernetes.py index 935c0c134d..477beb3851 100644 --- a/tests/integration/test_proxy_kubernetes.py +++ b/tests/integration/test_proxy_kubernetes.py @@ -1,5 +1,4 @@ """Test Controllers""" -from typing import Optional import pytest import yaml @@ -20,19 +19,13 @@ LOGGER = get_logger() class TestProxyKubernetes(TestCase): """Test Controllers""" - controller: Optional[KubernetesController] + controller: KubernetesController | None def setUp(self): # Ensure that local connection have been created - outpost_connection_discovery() # pylint: disable=no-value-for-parameter + outpost_connection_discovery() self.controller = None - def tearDown(self) -> None: - if self.controller: - for log in self.controller.down_with_logs(): - LOGGER.info(log) - return super().tearDown() - @pytest.mark.timeout(120) def test_kubernetes_controller_static(self): """Test Kubernetes Controller""" diff --git a/tests/wdio/package-lock.json b/tests/wdio/package-lock.json index 6dec90b85f..d9bb6ece92 100644 --- a/tests/wdio/package-lock.json +++ b/tests/wdio/package-lock.json @@ -5,22 +5,25 @@ "packages": { "": { "name": "@goauthentik/web-tests", + "dependencies": { + "chromedriver": "^125.0.2" + }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "@wdio/cli": "^8.29.0", - "@wdio/local-runner": "^8.29.0", - "@wdio/mocha-framework": "^8.29.0", - "@wdio/spec-reporter": "^8.29.0", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", + "@wdio/cli": "^8.37.0", + "@wdio/local-runner": "^8.37.0", + "@wdio/mocha-framework": "^8.37.0", + "@wdio/spec-reporter": "^8.37.0", + "eslint": "^8.57.0", "eslint-config-google": "^0.14.0", - "eslint-plugin-sonarjs": "^0.23.0", + "eslint-plugin-sonarjs": "^0.25.1", "npm-run-all": "^4.1.5", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "ts-node": "^10.9.2", - "typescript": "^5.3.3", - "wdio-wait-for": "^3.0.10" + "typescript": "^5.4.5", + "wdio-wait-for": "^3.0.11" }, "engines": { "node": ">=20" @@ -382,22 +385,22 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -418,9 +421,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -652,12 +655,12 @@ } }, "node_modules/@ljharb/through": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz", - "integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", + "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.5" }, "engines": { "node": ">= 0.4" @@ -786,11 +789,15 @@ "node": ">=14.16" } }, + "node_modules/@testim/chrome-version": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", + "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==" + }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "4.3.0", @@ -882,21 +889,24 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.7.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", - "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==", - "dev": true + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", + "devOptional": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -939,23 +949,22 @@ "version": "2.10.1", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.1.tgz", "integrity": "sha512-CHzgNU3qYBnp/O4S3yv2tXPlvMTq0YWSTVg2/JYLqWZGHwwgJGAwd00poay/11asPq8wLFwHzubyInqHIFmmiw==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -964,15 +973,15 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -981,26 +990,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1009,16 +1018,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1026,25 +1035,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1053,12 +1062,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1066,13 +1075,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1081,7 +1090,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1118,41 +1127,41 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1166,9 +1175,9 @@ "dev": true }, "node_modules/@vitest/snapshot": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.1.tgz", - "integrity": "sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.2.tgz", + "integrity": "sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -1180,19 +1189,19 @@ } }, "node_modules/@wdio/cli": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.29.0.tgz", - "integrity": "sha512-BOdX4qsos3gd4KS3DH17fE+Q7enAtVjiq372WHxFgAjXb4p95/ERGvfNKFWPrtsGwNQ7xOuxAajdW8kmGdXmuQ==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.37.0.tgz", + "integrity": "sha512-Sf7TMOBHYjoMKFfL5O0lrRXFRhOr8uGJ4k/3dxsFMOmi3L/3IPsBvi3/A0fAMSNI/OxKPRW5KjA+0u+EyTmrlg==", "dev": true, "dependencies": { "@types/node": "^20.1.1", "@vitest/snapshot": "^1.2.1", - "@wdio/config": "8.29.0", - "@wdio/globals": "8.29.0", + "@wdio/config": "8.37.0", + "@wdio/globals": "8.37.0", "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.24.12", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", + "@wdio/protocols": "8.32.0", + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", "async-exit-hook": "^2.0.1", "chalk": "^5.2.0", "chokidar": "^3.5.3", @@ -1205,9 +1214,9 @@ "lodash.flattendeep": "^4.4.0", "lodash.pickby": "^4.6.0", "lodash.union": "^4.6.0", - "read-pkg-up": "^10.0.0", + "read-pkg-up": "10.0.0", "recursive-readdir": "^2.2.3", - "webdriverio": "8.29.0", + "webdriverio": "8.37.0", "yargs": "^17.7.2" }, "bin": { @@ -1230,14 +1239,14 @@ } }, "node_modules/@wdio/config": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.29.0.tgz", - "integrity": "sha512-MxrKSBCd8req5vtfFbqM24j+dVAQOM57hHerm4pLwP1QW/vDLdrD6sP2swp7DIndxkedkofO3DzR1RVgEiEryw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.37.0.tgz", + "integrity": "sha512-1zNWhZY+z8rTQorXOZmpGE/rjE7wt2up8z0VQNupRQMhhDk5y9JgOgRRNTwLfcNv5HYRbj0LnChHh/4EGc5Nfw==", "dev": true, "dependencies": { "@wdio/logger": "8.28.0", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", "decamelize": "^6.0.0", "deepmerge-ts": "^5.0.0", "glob": "^10.2.2", @@ -1248,29 +1257,29 @@ } }, "node_modules/@wdio/globals": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.29.0.tgz", - "integrity": "sha512-xQaU8JEvbCgYXFL96w+yjgbxcXppyuqEgXEWZV/v0oRnff1lWpcaQUO9RriAt/tM4OpCVgKvwG1D4ap3wsCIFw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.37.0.tgz", + "integrity": "sha512-6CXixrTNda6iccpBX1RlEYAXaGejZJWhOZ5bGmiFl1Ca8FLksI5fwZMFaNwq8OcgvBLIRVf8K97xU5SUfBw8aQ==", "dev": true, "engines": { "node": "^16.13 || >=18" }, "optionalDependencies": { - "expect-webdriverio": "^4.9.3", - "webdriverio": "8.29.0" + "expect-webdriverio": "^4.11.2", + "webdriverio": "8.37.0" } }, "node_modules/@wdio/local-runner": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.29.0.tgz", - "integrity": "sha512-AYKhTu7bLWQvz0RvjKfRSvOVRxjxL9zDcXG3ySTkiLkDBVDAlr9FCDDcwV7kkHnE87ph2mlsBwetLPad6JF6PQ==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.37.0.tgz", + "integrity": "sha512-CQ0BFrUoT7a40jfdBognViz13hMEmPUjhdGO9ZVSvb9ztO2ujpWojf2bUGsRwkccBF4ysXrHBdhjpRZ5izyg/Q==", "dev": true, "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "8.28.0", "@wdio/repl": "8.24.12", - "@wdio/runner": "8.29.0", - "@wdio/types": "8.29.0", + "@wdio/runner": "8.37.0", + "@wdio/types": "8.37.0", "async-exit-hook": "^2.0.1", "split2": "^4.1.0", "stream-buffers": "^3.0.2" @@ -1307,16 +1316,16 @@ } }, "node_modules/@wdio/mocha-framework": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.29.0.tgz", - "integrity": "sha512-C/KRcmohxXOjyi67kUF2diLmj0D6k0zJuiiEUyl1qeWmtZ4Wo6gNjIL+7AxR7x9uXcdH1+2+eJd4BR7hvzVU5A==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.37.0.tgz", + "integrity": "sha512-fTLhg/X7Lq3DIWKKmmus06mULDjyf8+N9ebG4ydSbSnW4p4im4HB+SguHgg7drX499I5nC6ZQw6sbQ3SHeB3fQ==", "dev": true, "dependencies": { "@types/mocha": "^10.0.0", "@types/node": "^20.1.0", "@wdio/logger": "8.28.0", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", "mocha": "^10.0.0" }, "engines": { @@ -1324,9 +1333,9 @@ } }, "node_modules/@wdio/protocols": { - "version": "8.24.12", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.24.12.tgz", - "integrity": "sha512-QnVj3FkapmVD3h2zoZk+ZQ8gevSj9D9MiIQIy8eOnY4FAneYZ9R9GvoW+mgNcCZO8S8++S/jZHetR8n+8Q808g==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.32.0.tgz", + "integrity": "sha512-inLJRrtIGdTz/YPbcsvpSvPlYQFTVtF3OYBwAXhG2FiP1ZwE1CQNLP/xgRGye1ymdGCypGkexRqIx3KBGm801Q==", "dev": true }, "node_modules/@wdio/repl": { @@ -1342,14 +1351,14 @@ } }, "node_modules/@wdio/reporter": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.29.0.tgz", - "integrity": "sha512-CtxcHtVCGM76pxwuXJ+0FH48dPWka9kJ7SZZ8SIGdzBX59saLuPMDzdXTENpcefb/8/jxAulZDWtc11/hylJOw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.37.0.tgz", + "integrity": "sha512-NmrFgF4Y1UCiTzDC9HOyZEsH8FBMFFKO3ZtSiDyKC6DrNGdDaRIzfypjO5RxqPgmc1DhTrpDaVnu+q/OffczSg==", "dev": true, "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "8.28.0", - "@wdio/types": "8.29.0", + "@wdio/types": "8.37.0", "diff": "^5.0.0", "object-inspect": "^1.12.0" }, @@ -1358,35 +1367,35 @@ } }, "node_modules/@wdio/runner": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.29.0.tgz", - "integrity": "sha512-GNIo7EsrPHutabl+gGWM3d1sLybnlZ16mBfB1M1S7tpaci1nwll41xnzaikMoRh5Q/FRDVfHRe74bT1sYhqH0w==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.37.0.tgz", + "integrity": "sha512-AGcqKtO1NGvrHkHqrnTvpNDAKqDgxOEnNUGKBia6a3NG88vu10SSdtN0gX17nnVFaJvRLNq4AlGiSC20ZLovdw==", "dev": true, "dependencies": { - "@types/node": "^20.1.0", - "@wdio/config": "8.29.0", - "@wdio/globals": "8.29.0", + "@types/node": "^20.11.28", + "@wdio/config": "8.37.0", + "@wdio/globals": "8.37.0", "@wdio/logger": "8.28.0", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", - "deepmerge-ts": "^5.0.0", - "expect-webdriverio": "^4.9.3", - "gaze": "^1.1.2", - "webdriver": "8.29.0", - "webdriverio": "8.29.0" + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", + "deepmerge-ts": "^5.1.0", + "expect-webdriverio": "^4.12.0", + "gaze": "^1.1.3", + "webdriver": "8.37.0", + "webdriverio": "8.37.0" }, "engines": { "node": "^16.13 || >=18" } }, "node_modules/@wdio/spec-reporter": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.29.0.tgz", - "integrity": "sha512-usOGAmuJ7GY1a/yU9RzGhkO2a8uQ5L2P/ZYCyie597SLco01sl0i/W41ZHltkhNAj8S/TANrQQ6uJg5jRa1LYA==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.37.0.tgz", + "integrity": "sha512-fzTckUnluPjMXVGYqKLdDU3mjqSY0Us1Bh8LHMn+OS0/86rD86OufgC9R65QwDl5aTGToMEwenEdjrSyyQ5jlw==", "dev": true, "dependencies": { - "@wdio/reporter": "8.29.0", - "@wdio/types": "8.29.0", + "@wdio/reporter": "8.37.0", + "@wdio/types": "8.37.0", "chalk": "^5.1.2", "easy-table": "^1.2.0", "pretty-ms": "^7.0.0" @@ -1408,9 +1417,9 @@ } }, "node_modules/@wdio/types": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.29.0.tgz", - "integrity": "sha512-jNOmYRHAfGBxx3a9ojnt0mWeiePT5zfafsvW2tdbwH0FyLG/S0tzJN7nB2g3ErG6xaRTf93SZu12Z4lytHDd+w==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.37.0.tgz", + "integrity": "sha512-36kmSlZcVhsMlbhaSCQUfL51iG81FlbzW4Dfkz4903cDkxmh64bgxydZbRB5aPLnJzzR7tI3chIME8zSVZFR8w==", "dev": true, "dependencies": { "@types/node": "^20.1.0" @@ -1420,18 +1429,18 @@ } }, "node_modules/@wdio/utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.29.0.tgz", - "integrity": "sha512-NiJ8FqbzdxvBD+YvqAh4c+IJdwxjqpf/LgfGZH8hiFApJb9pfdSlOoaY9jKxEJBJMgENaDaDaOIyuUzN/+X6tw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.37.0.tgz", + "integrity": "sha512-2YtT8fH8mfMuDeEXKtFgxxBBoIGezSKysKAydtV9sICg4ZJM5CSsSzhfGaszC2qgOv3WHaBsfgg0Nljp1g2Y5A==", "dev": true, "dependencies": { "@puppeteer/browsers": "^1.6.0", "@wdio/logger": "8.28.0", - "@wdio/types": "8.29.0", + "@wdio/types": "8.37.0", "decamelize": "^6.0.0", "deepmerge-ts": "^5.1.0", "edgedriver": "^5.3.5", - "geckodriver": "^4.2.0", + "geckodriver": "^4.3.1", "get-port": "^7.0.0", "import-meta-resolve": "^4.0.0", "locate-app": "^2.1.0", @@ -1443,6 +1452,18 @@ "node": "^16.13 || >=18" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -1477,7 +1498,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -1560,30 +1580,30 @@ } }, "node_modules/archiver": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.1.tgz", - "integrity": "sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.0.tgz", + "integrity": "sha512-R9HM9egs8FfktSqUqyjlKmvF4U+CWNqm/2tlROV+lOFg79MLdT67ae1l3hU47pGy8twSXxHoiefMCh43w0BriQ==", "dev": true, "dependencies": { - "archiver-utils": "^4.0.1", + "archiver-utils": "^5.0.0", "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", - "zip-stream": "^5.0.1" + "zip-stream": "^6.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" } }, "node_modules/archiver-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz", - "integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.1.tgz", + "integrity": "sha512-MMAoLdMvT/nckofX1tCLrf7uJce4jTNkiT6smA2u57AOImc1nce7mR3EDujxL5yv6/MnILuQH4sAsPtDS8kTvg==", "dev": true, "dependencies": { - "glob": "^8.0.0", + "glob": "^10.0.0", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash": "^4.17.15", @@ -1591,47 +1611,56 @@ "readable-stream": "^3.6.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/archiver/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "balanced-match": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/archiver-utils/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/archiver/node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/archiver-utils/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/arg": { @@ -1702,7 +1731,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -1725,6 +1753,11 @@ "node": ">=0.12.0" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1737,6 +1770,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", @@ -1773,7 +1816,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -1882,7 +1924,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } @@ -1945,13 +1986,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2037,6 +2083,53 @@ "fsevents": "~2.3.2" } }, + "node_modules/chromedriver": { + "version": "125.0.2", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-125.0.2.tgz", + "integrity": "sha512-H2mIy3r//bIGVouQQrp2UzS93cjGCV2f+I6qNimAOyIiWkaKCiLEuDMQnuC21rewo/UuyOA8CDqa4a7RIT/8EQ==", + "hasInstallScript": true, + "dependencies": { + "@testim/chrome-version": "^1.1.4", + "axios": "^1.6.7", + "compare-versions": "^6.1.0", + "extract-zip": "^2.0.1", + "proxy-agent": "^6.4.0", + "proxy-from-env": "^1.1.0", + "tcp-port-used": "^1.0.2" + }, + "bin": { + "chromedriver": "bin/chromedriver" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chromedriver/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/chromedriver/node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/chromium-bidi": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", @@ -2077,9 +2170,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "engines": { "node": ">=6" @@ -2197,6 +2290,17 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", @@ -2206,19 +2310,64 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/compare-versions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==" + }, "node_modules/compress-commons": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz", - "integrity": "sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.1.tgz", + "integrity": "sha512-l7occIJn8YwlCEbWUCrG6gPms9qnJTCZSaznCa5HaV+yJMH4kM8BDc7q9NyoQuoiB2O6jKgTcTeY462qw6MyHw==", "dev": true, "dependencies": { "crc-32": "^1.2.0", - "crc32-stream": "^5.0.0", + "crc32-stream": "^6.0.0", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/concat-map": { @@ -2246,16 +2395,56 @@ } }, "node_modules/crc32-stream": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.0.tgz", - "integrity": "sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", "dev": true, "dependencies": { "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" + } + }, + "node_modules/crc32-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/create-require": { @@ -2353,7 +2542,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2408,8 +2596,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deepmerge-ts": { "version": "5.1.0", @@ -2442,14 +2629,15 @@ } }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -2476,7 +2664,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -2486,6 +2673,14 @@ "node": ">= 14" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2496,15 +2691,15 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1249869", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1249869.tgz", - "integrity": "sha512-Ctp4hInA0BEavlUoRy9mhGq0i+JSo/AwVyX2EFgZmV1kYB+Zq+EMBAn52QWu6FbRr10hRb6pBl420upbp4++vg==", + "version": "0.0.1302984", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1302984.tgz", + "integrity": "sha512-Rgh2Sk5fUSCtEx4QGH9iwTyECdFPySG2nlz5J8guGh2Wlha6uzSOCq/DCEC8faHlLaMPZJMuZ4ovgcX4LvOkKA==", "dev": true }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -2674,9 +2869,9 @@ } }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -2698,7 +2893,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -2765,6 +2959,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", @@ -2818,7 +3021,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -2839,23 +3041,22 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "optional": true, "engines": { "node": ">=0.10.0" } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -2913,12 +3114,12 @@ } }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz", - "integrity": "sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.1.tgz", + "integrity": "sha512-5IOKvj/GMBNqjxBdItfotfRHo7w48496GOu1hxdeXuD0mB1JBlDCViiLHETDTfA8pDAVSBimBEQoetRXYceQEw==", "dev": true, "engines": { - "node": ">=14" + "node": ">=16" }, "peerDependencies": { "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" @@ -3106,7 +3307,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3143,7 +3343,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -3152,11 +3351,28 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -3197,12 +3413,12 @@ } }, "node_modules/expect-webdriverio": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-4.9.3.tgz", - "integrity": "sha512-ASHsFc/QaK5ipF4ct3e8hd3elm8wNXk/Qa3EemtYDmfUQ4uzwqDf75m/QFQpwVNCjEpkNP7Be/6X9kz7bN0P9Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-4.12.1.tgz", + "integrity": "sha512-jTfyC2bJbPNw4c8MlEwZNX7SjtPbZ73ysJvr/OGKA9mSKC+toyjU2eMNzHlt9WZO5+wl0RDS1dR7VxHXeu7+zA==", "dev": true, "dependencies": { - "@vitest/snapshot": "^1.2.1", + "@vitest/snapshot": "^1.2.2", "expect": "^29.7.0", "jest-matcher-utils": "^29.7.0", "lodash.isequal": "^4.5.0" @@ -3211,9 +3427,9 @@ "node": ">=16 || >=18 || >=20" }, "optionalDependencies": { - "@wdio/globals": "^8.27.0", - "@wdio/logger": "^8.24.12", - "webdriverio": "^8.27.0" + "@wdio/globals": "^8.29.3", + "@wdio/logger": "^8.28.0", + "webdriverio": "^8.29.3" } }, "node_modules/external-editor": { @@ -3234,7 +3450,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -3254,7 +3469,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -3318,7 +3532,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -3374,6 +3587,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3473,6 +3698,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3498,6 +3742,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -3523,7 +3780,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -3613,10 +3869,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -3658,17 +3917,17 @@ } }, "node_modules/geckodriver": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.2.1.tgz", - "integrity": "sha512-4m/CRk0OI8MaANRuFIahvOxYTSjlNAO2p9JmE14zxueknq6cdtB5M9UGRQ8R9aMV0bLGNVHHDnDXmoXdOwJfWg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.3.1.tgz", + "integrity": "sha512-ol7JLsj55o5k+z7YzeSy2mdJROXMAxIa+uzr3A1yEMr5HISqQOTslE3ZeARcxR4jpAY3fxmHM+sq32qbe/eXfA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@wdio/logger": "^8.11.0", + "@wdio/logger": "^8.24.12", "decamelize": "^6.0.0", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.1", + "https-proxy-agent": "^7.0.2", + "node-fetch": "^3.3.2", "tar-fs": "^3.0.4", "unzipper": "^0.10.14", "which": "^4.0.0" @@ -3690,15 +3949,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3748,7 +4011,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", - "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^5.0.1", @@ -3763,7 +4025,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", - "dev": true, "engines": { "node": ">= 14" } @@ -3968,8 +4229,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -4014,12 +4274,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4064,6 +4324,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -4086,10 +4358,9 @@ "dev": true }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -4112,10 +4383,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dev": true, + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -4290,10 +4560,17 @@ } }, "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "engines": { + "node": ">=8" + } }, "node_modules/is-array-buffer": { "version": "3.0.2", @@ -4576,17 +4853,22 @@ } }, "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -4599,6 +4881,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -5126,9 +5421,9 @@ "dev": true }, "node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -5150,7 +5445,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -5238,9 +5532,9 @@ } }, "node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -5427,18 +5721,6 @@ "node": ">=8" } }, - "node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-symbols/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5546,6 +5828,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -5865,8 +6166,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mute-stream": { "version": "1.0.0", @@ -5905,7 +6205,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -6160,7 +6459,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -6278,18 +6576,6 @@ "node": ">=8" } }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ora/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6366,7 +6652,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", - "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -6385,7 +6670,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", - "dev": true, "dependencies": { "degenerator": "^5.0.0", "ip": "^1.1.8", @@ -6496,8 +6780,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -6542,9 +6825,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -6597,6 +6880,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -6643,14 +6935,12 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -6875,14 +7165,14 @@ } }, "node_modules/read-pkg-up": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", - "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.0.0.tgz", + "integrity": "sha512-jgmKiS//w2Zs+YbX039CorlkOp8FIVbSAN8r8GJHDsGlmNPXo+VeHkqAwCiQVTTx5/LwLZTcEw59z3DvcLbr0g==", "dev": true, "dependencies": { "find-up": "^6.3.0", - "read-pkg": "^8.1.0", - "type-fest": "^4.2.0" + "read-pkg": "^8.0.0", + "type-fest": "^3.12.0" }, "engines": { "node": ">=16" @@ -6980,9 +7270,9 @@ } }, "node_modules/read-pkg-up/node_modules/parse-json": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.0.tgz", - "integrity": "sha512-ihtdrgbqdONYD156Ap6qTcaGcGdkdAxodO1wLqQ/j7HP1u2sFYppINiq4jyC8F+Nm+4fVufylCV00QmkTHkSUg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.21.4", @@ -6998,18 +7288,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/parse-json/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/read-pkg-up/node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -7037,10 +7315,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.3.1.tgz", - "integrity": "sha512-pphNW/msgOUSkJbH58x8sqpq8uQj6b0ZKGxEsLKMUnGorRcDjrUaLS+39+/ub41JNTwrrMyJcUB8+YZs3mbwqw==", + "node_modules/read-pkg-up/node_modules/read-pkg/node_modules/type-fest": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz", + "integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==", "dev": true, "engines": { "node": ">=16" @@ -7049,6 +7327,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/read-pkg-up/node_modules/yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", @@ -7507,6 +7797,23 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -7596,7 +7903,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -7606,7 +7912,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -7620,7 +7925,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -7631,10 +7935,9 @@ } }, "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" }, "node_modules/source-map": { "version": "0.5.7", @@ -8008,6 +8311,31 @@ "streamx": "^2.15.0" } }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -8200,8 +8528,7 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/type-check": { "version": "0.4.0", @@ -8293,9 +8620,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -8330,11 +8657,16 @@ "through": "^2.3.8" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -8536,9 +8868,9 @@ } }, "node_modules/wdio-wait-for": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.10.tgz", - "integrity": "sha512-YMWfI0BYgEviGDB9+rDUuHDZNVk8pHeae0cvaqk3Wx/2LijwJi4xkRP01uYC/hM7RBB7QJFBmjrXczVSqtJOGw==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.11.tgz", + "integrity": "sha512-kck1TeQeIzI9fdP8efy7izzdkBiOZJR8lMOkKpxYp2/k7r2F2+8SHWBGPt1TfSiehKHLsIalB7G1RzJKF+PqDA==", "dev": true, "engines": { "node": "^16.13 || >=18" @@ -8554,18 +8886,18 @@ } }, "node_modules/webdriver": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.29.0.tgz", - "integrity": "sha512-6vWTaj7beboU83LU5XyfLGiwoG8rcFSKeEOxVO9VjBp8c9QML9K21ODrlsgJKHhPiKQp0epnjwWedJgr57LkRA==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.37.0.tgz", + "integrity": "sha512-B2PxFdSpwkVczqerTmu0wUSURxozmk1rs/RUm5FVrsH/qKtKQjkbg21yZr5epoZAwiCYw+F3HaPGChGL74XR8w==", "dev": true, "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "8.29.0", + "@wdio/config": "8.37.0", "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.24.12", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", + "@wdio/protocols": "8.32.0", + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", "deepmerge-ts": "^5.1.0", "got": "^12.6.1", "ky": "^0.33.0", @@ -8576,23 +8908,23 @@ } }, "node_modules/webdriverio": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.29.0.tgz", - "integrity": "sha512-/04fUBQ8lrn+5wMaMqMsSenuqpCIe+9bAUTEQnyd0u04LJ+foeSGtv/jYbNZLhrQA2CfiwW6ozsEQnHO9pBFcg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.37.0.tgz", + "integrity": "sha512-GaL+12fiAdkFJyx4n30tfaJUpPwVELgEsfwumeQLFcqU3ERrM5W1c1QvEzE03oMT4/5NgzPy0lIwcec9pftRWg==", "dev": true, "dependencies": { "@types/node": "^20.1.0", - "@wdio/config": "8.29.0", + "@wdio/config": "8.37.0", "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.24.12", + "@wdio/protocols": "8.32.0", "@wdio/repl": "8.24.12", - "@wdio/types": "8.29.0", - "@wdio/utils": "8.29.0", - "archiver": "^6.0.0", + "@wdio/types": "8.37.0", + "@wdio/utils": "8.37.0", + "archiver": "^7.0.0", "aria-query": "^5.0.0", "css-shorthand-properties": "^1.1.1", "css-value": "^0.0.1", - "devtools-protocol": "^0.0.1249869", + "devtools-protocol": "^0.0.1302984", "grapheme-splitter": "^1.0.2", "import-meta-resolve": "^4.0.0", "is-plain-obj": "^4.1.0", @@ -8604,7 +8936,7 @@ "resq": "^1.9.1", "rgb2hex": "0.2.5", "serialize-error": "^11.0.1", - "webdriver": "8.29.0" + "webdriver": "8.37.0" }, "engines": { "node": "^16.13 || >=18" @@ -8839,8 +9171,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.14.2", @@ -8954,7 +9285,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -8982,17 +9312,57 @@ } }, "node_modules/zip-stream": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.1.tgz", - "integrity": "sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.0.tgz", + "integrity": "sha512-X0WFquRRDtL9HR9hc1OrabOP/VKJEX7gAr2geayt3b7dLgXgSXI6ucC4CphLQP/aQt2GyHIYgmXxtC+dVdghAQ==", "dev": true, "dependencies": { - "archiver-utils": "^4.0.1", - "compress-commons": "^5.0.1", - "readable-stream": "^3.6.0" + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.0", + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } } } diff --git a/tests/wdio/package.json b/tests/wdio/package.json index 14005ef621..1ffc08aa09 100644 --- a/tests/wdio/package.json +++ b/tests/wdio/package.json @@ -4,20 +4,20 @@ "type": "module", "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "@wdio/cli": "^8.29.0", - "@wdio/local-runner": "^8.29.0", - "@wdio/mocha-framework": "^8.29.0", - "@wdio/spec-reporter": "^8.29.0", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", + "@wdio/cli": "^8.37.0", + "@wdio/local-runner": "^8.37.0", + "@wdio/mocha-framework": "^8.37.0", + "@wdio/spec-reporter": "^8.37.0", + "eslint": "^8.57.0", "eslint-config-google": "^0.14.0", - "eslint-plugin-sonarjs": "^0.23.0", + "eslint-plugin-sonarjs": "^0.25.1", "npm-run-all": "^4.1.5", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "ts-node": "^10.9.2", - "typescript": "^5.3.3", - "wdio-wait-for": "^3.0.10" + "typescript": "^5.4.5", + "wdio-wait-for": "^3.0.11" }, "scripts": { "wdio": "wdio run ./wdio.conf.ts", @@ -30,5 +30,8 @@ }, "engines": { "node": ">=20" + }, + "dependencies": { + "chromedriver": "^125.0.2" } } diff --git a/tests/wdio/wdio.conf.ts b/tests/wdio/wdio.conf.ts index 525cfb00d3..027aff64ff 100644 --- a/tests/wdio/wdio.conf.ts +++ b/tests/wdio/wdio.conf.ts @@ -61,6 +61,9 @@ export const config: Options.Testrunner = { capabilities: [ { "browserName": "chrome", + "wdio:chromedriverOptions": { + binary: "./node_modules/.bin/chromedriver", + }, "goog:chromeOptions": { args: ["--disable-infobars", "--window-size=1280,800"].concat( (function () { diff --git a/web/.eslintignore b/web/.eslintignore index 773a27bf1f..0e13fb6712 100644 --- a/web/.eslintignore +++ b/web/.eslintignore @@ -6,3 +6,4 @@ dist coverage src/locale-codes.ts storybook-static/ +src/locales/** diff --git a/web/.eslintrc.json b/web/.eslintrc.json index fdae375c68..cf7447670c 100644 --- a/web/.eslintrc.json +++ b/web/.eslintrc.json @@ -13,7 +13,8 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, - "sourceType": "module" + "sourceType": "module", + "project": true }, "plugins": ["@typescript-eslint", "lit", "custom-elements"], "ignorePatterns": ["authentik-live-tests/**"], @@ -31,6 +32,7 @@ "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" } - ] + ], + "no-console": ["error", { "allow": ["debug", "warn", "error"] }] } } diff --git a/web/.gitignore b/web/.gitignore index f11bf366de..5fcf655367 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -109,5 +109,3 @@ temp/ # End of https://www.gitignore.io/api/node api/** storybook-static/ -scripts/*.mjs -scripts/*.js diff --git a/web/.prettierignore b/web/.prettierignore index 51b2d6c4b9..d9aec48258 100644 --- a/web/.prettierignore +++ b/web/.prettierignore @@ -11,3 +11,4 @@ src/locales/ storybook-static/ # Prettier breaks the tsconfig file tsconfig.json +.storybook/css-import-maps* diff --git a/web/.storybook/css-import-maps.ts b/web/.storybook/css-import-maps.ts index 3941f30c73..5415a2b272 100644 --- a/web/.storybook/css-import-maps.ts +++ b/web/.storybook/css-import-maps.ts @@ -27,8 +27,10 @@ const rawCssImportMaps = [ 'import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css";', 'import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";', 'import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";', + 'import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";', 'import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";', 'import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";', + 'import PFDualListSelector from "@patternfly/patternfly/components/DualListSelector/dual-list-selector.css";', 'import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";', 'import PFExpandableSection from "@patternfly/patternfly/components/ExpandableSection/expandable-section.css";', 'import PFFAIcons from "@patternfly/patternfly/base/patternfly-fa-icons.css";', @@ -69,10 +71,8 @@ const rawCssImportMaps = [ 'import styles from "./LibraryPageImpl.css";', ]; -const cssImportMaps = rawCssImportMaps.reduce( - (acc, line) => ({ ...acc, [line]: line.replace(/\.css/, ".css?inline") }), - {}, -); +const cssImportMaps = rawCssImportMaps.reduce((acc, line) => ( +{...acc, [line]: line.replace(/\.css/, ".css?inline")}), {}); export { cssImportMaps }; export default cssImportMaps; diff --git a/web/.storybook/preview.ts b/web/.storybook/preview.ts index 08bd2119e4..258afd2152 100644 --- a/web/.storybook/preview.ts +++ b/web/.storybook/preview.ts @@ -1,7 +1,7 @@ import type { Preview } from "@storybook/web-components"; import "@goauthentik/common/styles/authentik.css"; -import "@goauthentik/common/styles/theme-dark.css"; +// import "@goauthentik/common/styles/theme-dark.css"; import "@patternfly/patternfly/components/Brand/brand.css"; import "@patternfly/patternfly/components/Page/page.css"; // .storybook/preview.js diff --git a/web/authentik/sources/discord.svg b/web/authentik/sources/discord.svg index 9084f5046f..71120e06fb 100644 --- a/web/authentik/sources/discord.svg +++ b/web/authentik/sources/discord.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/web/authentik/sources/ldap.png b/web/authentik/sources/ldap.png new file mode 100644 index 0000000000..8fda3be56a Binary files /dev/null and b/web/authentik/sources/ldap.png differ diff --git a/web/authentik/sources/proxy.svg b/web/authentik/sources/proxy.svg new file mode 100644 index 0000000000..13c6c0883a --- /dev/null +++ b/web/authentik/sources/proxy.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/web/authentik/sources/rac.svg b/web/authentik/sources/rac.svg new file mode 100644 index 0000000000..6b78fd3968 --- /dev/null +++ b/web/authentik/sources/rac.svg @@ -0,0 +1 @@ +desktop diff --git a/web/authentik/sources/radius.svg b/web/authentik/sources/radius.svg new file mode 100644 index 0000000000..9aca0e6b97 --- /dev/null +++ b/web/authentik/sources/radius.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/web/authentik/sources/saml.png b/web/authentik/sources/saml.png new file mode 100644 index 0000000000..81185a3304 Binary files /dev/null and b/web/authentik/sources/saml.png differ diff --git a/web/authentik/sources/scim.png b/web/authentik/sources/scim.png new file mode 100644 index 0000000000..1c337bcb7f Binary files /dev/null and b/web/authentik/sources/scim.png differ diff --git a/web/build.mjs b/web/build.mjs new file mode 100644 index 0000000000..c64f5f2070 --- /dev/null +++ b/web/build.mjs @@ -0,0 +1,151 @@ +import * as chokidar from "chokidar"; +import esbuild from "esbuild"; +import fs from "fs"; +import { globSync } from "glob"; +import path from "path"; +import { cwd } from "process"; +import process from "process"; +import { fileURLToPath } from "url"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); + +// eslint-disable-next-line no-undef +const isProdBuild = process.env.NODE_ENV === "production"; + +// eslint-disable-next-line no-undef +const apiBasePath = process.env.AK_API_BASE_PATH || ""; + +const definitions = { + "process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"), + "process.env.CWD": JSON.stringify(cwd()), + "process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath), +}; + +// All is magic is just to make sure the assets are copied into the right places. This is a very stripped down version +// of what the rollup-copy-plugin does, without any of the features we don't use, and using globSync instead of globby +// since we already had globSync lying around thanks to Typescript. If there's a third argument in an array entry, it's +// used to replace the internal path before concatenating it all together as the destination target. + +const otherFiles = [ + ["node_modules/@patternfly/patternfly/patternfly.min.css", "."], + ["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"], + ["src/custom.css", "."], + ["src/common/styles/**", "."], + ["src/assets/images/**", "./assets/images"], + ["./icons/*", "./assets/icons"], +]; + +const isFile = (filePath) => fs.statSync(filePath).isFile(); +function nameCopyTarget(src, dest, strip) { + const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base); + return [src, target]; +} + +for (const [source, rawdest, strip] of otherFiles) { + const matchedPaths = globSync(source); + const dest = path.join("dist", rawdest); + const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip)); + for (const [src, dest] of copyTargets) { + if (isFile(src)) { + fs.mkdirSync(path.dirname(dest), { recursive: true }); + fs.copyFileSync(src, dest); + } + } +} + +// This starts the definitions used for esbuild: Our targets, our arguments, the function for running a build, and three +// options for building: watching, building, and building the proxy. +// Ordered by largest to smallest interface to build even faster +const interfaces = [ + ["admin/AdminInterface/AdminInterface.ts", "admin"], + ["user/UserInterface.ts", "user"], + ["flow/FlowInterface.ts", "flow"], + ["standalone/api-browser/index.ts", "standalone/api-browser"], + ["enterprise/rac/index.ts", "enterprise/rac"], + ["standalone/loading/index.ts", "standalone/loading"], + ["polyfill/poly.ts", "."], +]; + +const baseArgs = { + bundle: true, + write: true, + sourcemap: true, + minify: isProdBuild, + splitting: true, + treeShaking: true, + external: ["*.woff", "*.woff2"], + tsconfig: "./tsconfig.json", + loader: { ".css": "text", ".md": "text" }, + define: definitions, + format: "esm", +}; + +async function buildOneSource(source, dest) { + const DIST = path.join(__dirname, "./dist", dest); + console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`); + + try { + const start = Date.now(); + await esbuild.build({ + ...baseArgs, + entryPoints: [`./src/${source}`], + outdir: DIST, + }); + const end = Date.now(); + console.log( + `[${new Date(end).toISOString()}] Finished build for target ${source} in ${ + Date.now() - start + }ms`, + ); + } catch (exc) { + console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`); + } +} + +async function buildAuthentik(interfaces) { + await Promise.allSettled(interfaces.map(([source, dest]) => buildOneSource(source, dest))); +} + +let timeoutId = null; +function debouncedBuild() { + if (timeoutId !== null) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(() => { + console.clear(); + buildAuthentik(interfaces); + }, 250); +} + +if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) { + console.log(`Build the authentikUI + +options: + -w, --watch: Build all ${interfaces.length} interfaces + -p, --proxy: Build only the polyfills and the loading application + -h, --help: This help message +`); + process.exit(0); +} + +if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) { + console.log("Watching ./src for changes"); + chokidar.watch("./src").on("all", (event, path) => { + if (!["add", "change", "unlink"].includes(event)) { + return; + } + if (!/(\.css|\.ts|\.js)$/.test(path)) { + return; + } + debouncedBuild(); + }); +} else if (process.argv.length > 2 && (process.argv[2] === "-p" || process.argv[2] === "--proxy")) { + // There's no watch-for-proxy, sorry. + await buildAuthentik( + interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)), + ); + process.exit(0); +} else { + // And the fallback: just build it. + await buildAuthentik(interfaces); +} diff --git a/web/docs/Changelog.md b/web/docs/Changelog.md new file mode 100644 index 0000000000..cba5b39992 --- /dev/null +++ b/web/docs/Changelog.md @@ -0,0 +1,17 @@ +### 2024-03-26T09:25:06-0700 + +Split the tsconfig file into a base and build variant. + +Lesson: This lesson is stored here and not in a comment in tsconfig.json because +JSON doesn't like comments. Doug Crockford's purity requirement has doomed an +entire generation to keeping its human-facing meta somewhere other than in the +file where it belongs. + +Lesson: The `extend` command of tsconfig has an unexpected behavior. It is +neither a merge or a replace, but some mixture of the two. The buildfile's +`compilerOptions` is not a full replacement; instead, each of _its_ top-level +fields is a replacement for what is found in the basefile. So while you don't +need to include _everything_ in a `compilerOptions` field if you want to change +one thing, if you want to modify _one_ path in `compilerOptions.path`, you must +include the entire `compilerOptions.path` collection in your buildfile. +g diff --git a/web/package-lock.json b/web/package-lock.json index f50b28cb9c..9a3f790b76 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -9,109 +9,111 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "@codemirror/lang-html": "^6.4.8", - "@codemirror/lang-javascript": "^6.2.1", - "@codemirror/lang-python": "^6.1.3", - "@codemirror/lang-xml": "^6.0.2", - "@codemirror/legacy-modes": "^6.3.3", + "@codemirror/lang-html": "^6.4.9", + "@codemirror/lang-javascript": "^6.2.2", + "@codemirror/lang-python": "^6.1.6", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/legacy-modes": "^6.4.0", "@codemirror/theme-one-dark": "^6.1.2", - "@formatjs/intl-listformat": "^7.5.5", - "@fortawesome/fontawesome-free": "^6.5.1", - "@goauthentik/api": "^2023.10.6-1706113408", - "@lit-labs/context": "^0.4.0", + "@formatjs/intl-listformat": "^7.5.7", + "@fortawesome/fontawesome-free": "^6.5.2", + "@goauthentik/api": "^2024.4.2-1716550354", "@lit-labs/task": "^3.1.0", - "@lit/localize": "^0.11.4", - "@open-wc/lit-helpers": "^0.6.0", - "@patternfly/elements": "^2.4.0", + "@lit/context": "^1.1.1", + "@lit/localize": "^0.12.1", + "@lit/reactive-element": "^2.0.4", + "@open-wc/lit-helpers": "^0.7.0", + "@patternfly/elements": "^3.0.1", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.95.0", + "@sentry/browser": "^8.4.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", - "chart.js": "^4.4.1", + "chart.js": "^4.4.3", "chartjs-adapter-moment": "^1.0.1", "codemirror": "^6.0.1", "construct-style-sheets-polyfill": "^3.1.0", - "core-js": "^3.35.1", - "country-flag-icons": "^1.5.9", + "core-js": "^3.37.1", + "country-flag-icons": "^1.5.11", "fuse.js": "^7.0.0", "guacamole-common-js": "^1.5.0", - "lit": "^2.8.0", - "mermaid": "^10.7.0", + "lit": "^3.1.3", + "md-front-matter": "^1.0.4", + "mermaid": "^10.9.1", "rapidoc": "^9.3.4", - "style-mod": "^4.1.0", + "showdown": "^2.1.0", + "style-mod": "^4.1.2", + "ts-pattern": "^5.1.2", "webcomponent-qr-code": "^1.2.0", - "yaml": "^2.3.4" + "yaml": "^2.4.2" }, "devDependencies": { - "@babel/core": "^7.23.7", + "@babel/core": "^7.24.5", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.23.7", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-runtime": "^7.23.7", - "@babel/preset-env": "^7.23.8", - "@babel/preset-typescript": "^7.23.3", + "@babel/plugin-proposal-decorators": "^7.24.1", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", + "@babel/plugin-transform-runtime": "^7.24.3", + "@babel/preset-env": "^7.24.5", + "@babel/preset-typescript": "^7.24.1", "@hcaptcha/types": "^1.0.3", - "@jackfranklin/rollup-plugin-markdown": "^0.4.0", "@jeysal/storybook-addon-css-user-preferences": "^0.2.0", - "@lit/localize-tools": "^0.7.1", - "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-node-resolve": "^15.2.3", + "@lit/localize-tools": "^0.7.2", "@rollup/plugin-replace": "^5.0.5", - "@rollup/plugin-terser": "^0.4.4", - "@rollup/plugin-typescript": "^11.1.6", - "@spotlightjs/spotlight": "^1.2.7", - "@storybook/addon-essentials": "^7.6.10", - "@storybook/addon-links": "^7.6.10", - "@storybook/api": "^7.6.10", - "@storybook/blocks": "^7.6.4", - "@storybook/manager-api": "^7.6.10", - "@storybook/web-components": "^7.6.10", - "@storybook/web-components-vite": "^7.6.10", + "@spotlightjs/spotlight": "^1.2.17", + "@storybook/addon-essentials": "^8.1.3", + "@storybook/addon-links": "^8.1.3", + "@storybook/api": "^7.6.17", + "@storybook/blocks": "^8.0.8", + "@storybook/manager-api": "^8.1.3", + "@storybook/web-components": "^8.1.3", + "@storybook/web-components-vite": "^8.1.3", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/chart.js": "^2.9.41", "@types/codemirror": "5.60.15", - "@types/grecaptcha": "^3.0.7", + "@types/grecaptcha": "^3.0.9", "@types/guacamole-common-js": "1.5.2", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@types/showdown": "^2.0.6", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "babel-plugin-macros": "^3.1.0", "babel-plugin-tsconfig-paths": "^1.0.3", + "chokidar": "^3.6.0", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "esbuild": "^0.21.3", + "eslint": "^8.57.0", "eslint-config-google": "^0.14.0", "eslint-plugin-custom-elements": "0.0.8", "eslint-plugin-lit": "^1.11.0", - "eslint-plugin-sonarjs": "^0.23.0", - "eslint-plugin-storybook": "^0.6.15", + "eslint-plugin-sonarjs": "^0.25.1", + "eslint-plugin-storybook": "^0.8.0", + "github-slugger": "^2.0.0", + "glob": "^10.4.0", "lit-analyzer": "^2.0.3", "npm-run-all": "^4.1.5", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "pseudolocale": "^2.0.0", - "pyright": "=1.1.338", "react": "^18.2.0", - "react-dom": "^18.2.0", - "rollup": "^4.9.6", - "rollup-plugin-copy": "^3.5.0", - "rollup-plugin-cssimport": "^1.0.3", + "react-dom": "^18.3.1", "rollup-plugin-modify": "^3.0.0", "rollup-plugin-postcss-lit": "^2.1.0", - "storybook": "^7.6.10", - "storybook-addon-mock": "^4.3.0", + "storybook": "^8.1.3", + "storybook-addon-mock": "^5.0.0", "ts-lit-plugin": "^2.0.2", "tslib": "^2.6.2", - "turnstile-types": "^1.2.0", - "typescript": "^5.3.3", - "vite-tsconfig-paths": "^4.3.1" + "turnstile-types": "^1.2.1", + "typescript": "^5.4.5", + "vite-tsconfig-paths": "^4.3.2" }, "engines": { "node": ">=20" }, "optionalDependencies": { - "@esbuild/darwin-arm64": "^0.19.12", + "@esbuild/darwin-arm64": "^0.21.3", "@esbuild/linux-amd64": "^0.18.11", - "@esbuild/linux-arm64": "^0.19.12" + "@esbuild/linux-arm64": "^0.21.3", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -119,18 +121,20 @@ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -140,6 +144,7 @@ "version": "0.0.30", "resolved": "https://registry.npmjs.org/@apitools/openapi-parser/-/openapi-parser-0.0.30.tgz", "integrity": "sha512-e8KttEjBSozuSO7IVeFTRvzqgsbxwFtGbwc1Yi/u8EgzDqtVpTOgZ5qfSwtzAdKNkx0x+oi+s/1imCAju0lhTA==", + "license": "MIT", "dependencies": { "swagger-client": "^3.18.5" } @@ -149,6 +154,7 @@ "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", "integrity": "sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==", "dev": true, + "license": "MIT", "dependencies": { "default-browser-id": "3.0.0" }, @@ -157,43 +163,43 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", - "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.7", - "@babel/parser": "^7.23.6", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -208,42 +214,15 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -255,6 +234,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -279,6 +259,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.23.5", "@babel/helper-validator-option": "^7.23.5", @@ -291,19 +272,19 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", - "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "semver": "^6.3.1" }, "engines": { @@ -318,6 +299,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", @@ -331,9 +313,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", - "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", + "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -351,6 +333,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -360,6 +343,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.22.15", "@babel/types": "^7.23.0" @@ -373,6 +357,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -381,40 +366,40 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -428,6 +413,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -436,9 +422,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -462,13 +448,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -479,12 +465,12 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -495,6 +481,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -503,30 +490,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -537,6 +524,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -556,58 +544,38 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz", - "integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -616,13 +584,29 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz", + "integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", + "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -632,14 +616,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", + "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/plugin-transform-optional-chaining": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -649,13 +633,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", + "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -668,8 +652,8 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -682,14 +666,14 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.7.tgz", - "integrity": "sha512-b1s5JyeMvqj7d9m9KhJNHKc18gEJiSyVzVX3bwbiPalQBQpuvfPh6lA9F7Kk/dWH0TIiXRpB9yicwijY6buPng==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.1.tgz", + "integrity": "sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.23.7", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-decorators": "^7.23.3" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-decorators": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -703,6 +687,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" }, @@ -727,6 +712,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -750,12 +736,12 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.23.3.tgz", - "integrity": "sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.1.tgz", + "integrity": "sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -789,12 +775,12 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", - "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -804,12 +790,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -819,12 +805,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", + "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -838,6 +824,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -858,12 +845,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -889,6 +876,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -937,6 +925,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -949,6 +938,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -964,6 +954,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -975,12 +966,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -994,6 +985,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1006,12 +998,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1021,13 +1013,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", - "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", + "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, @@ -1039,13 +1031,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { @@ -1056,12 +1048,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1071,12 +1063,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz", + "integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1086,13 +1078,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1102,13 +1094,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1119,18 +1111,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz", + "integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-split-export-declaration": "^7.24.5", "globals": "^11.1.0" }, "engines": { @@ -1141,13 +1133,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1157,12 +1149,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz", + "integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1172,13 +1164,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", + "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1188,12 +1180,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", + "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1203,12 +1195,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", + "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1219,13 +1211,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", + "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1235,12 +1227,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", + "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1251,13 +1243,13 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", - "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz", + "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-flow": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1267,12 +1259,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -1283,14 +1275,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1300,12 +1292,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", + "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1316,12 +1308,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1331,12 +1323,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", + "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1347,12 +1339,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1362,13 +1354,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", + "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1378,13 +1370,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -1395,14 +1387,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", - "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", + "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { @@ -1413,13 +1405,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", + "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1433,6 +1425,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -1445,12 +1438,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", + "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1460,12 +1453,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1476,12 +1469,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", + "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1492,16 +1485,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz", + "integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1511,13 +1503,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1527,12 +1519,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", + "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1543,12 +1535,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz", + "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, @@ -1560,12 +1552,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz", + "integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1575,13 +1567,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1591,14 +1583,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1609,12 +1601,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1624,12 +1616,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", + "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1640,12 +1632,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", + "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1655,16 +1647,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz", - "integrity": "sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", + "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, "engines": { @@ -1675,12 +1667,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1690,12 +1682,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -1706,12 +1698,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", + "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1721,12 +1713,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1736,12 +1728,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz", + "integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1751,15 +1743,15 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.3.tgz", - "integrity": "sha512-ogV0yWnq38CFwH20l2Afz0dfKuZBx9o/Y2Rmh5vuSS0YD1hswgEgTfyTzuSrT2q9btmHRSqYoSfwFUVaC1M1Jw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz", + "integrity": "sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1769,12 +1761,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", + "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1784,13 +1776,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", + "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1800,13 +1792,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", + "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1816,13 +1808,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", + "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1832,26 +1824,27 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.8.tgz", - "integrity": "sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", + "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", + "@babel/compat-data": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.1", + "@babel/plugin-syntax-import-attributes": "^7.24.1", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1863,58 +1856,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.7", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.3", - "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.1", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.24.1", + "@babel/plugin-transform-block-scoped-functions": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.5", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.5", + "@babel/plugin-transform-computed-properties": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.5", + "@babel/plugin-transform-dotall-regex": "^7.24.1", + "@babel/plugin-transform-duplicate-keys": "^7.24.1", + "@babel/plugin-transform-dynamic-import": "^7.24.1", + "@babel/plugin-transform-exponentiation-operator": "^7.24.1", + "@babel/plugin-transform-export-namespace-from": "^7.24.1", + "@babel/plugin-transform-for-of": "^7.24.1", + "@babel/plugin-transform-function-name": "^7.24.1", + "@babel/plugin-transform-json-strings": "^7.24.1", + "@babel/plugin-transform-literals": "^7.24.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-member-expression-literals": "^7.24.1", + "@babel/plugin-transform-modules-amd": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-modules-systemjs": "^7.24.1", + "@babel/plugin-transform-modules-umd": "^7.24.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-new-target": "^7.24.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", + "@babel/plugin-transform-object-super": "^7.24.1", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.24.5", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", + "@babel/plugin-transform-property-literals": "^7.24.1", + "@babel/plugin-transform-regenerator": "^7.24.1", + "@babel/plugin-transform-reserved-words": "^7.24.1", + "@babel/plugin-transform-shorthand-properties": "^7.24.1", + "@babel/plugin-transform-spread": "^7.24.1", + "@babel/plugin-transform-sticky-regex": "^7.24.1", + "@babel/plugin-transform-template-literals": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.5", + "@babel/plugin-transform-unicode-escapes": "^7.24.1", + "@babel/plugin-transform-unicode-property-regex": "^7.24.1", + "@babel/plugin-transform-unicode-regex": "^7.24.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -1926,14 +1919,14 @@ } }, "node_modules/@babel/preset-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", - "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.1.tgz", + "integrity": "sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-flow-strip-types": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-transform-flow-strip-types": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1947,6 +1940,7 @@ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -1957,16 +1951,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -2116,13 +2110,15 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/runtime": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", - "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", "dev": true, + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2131,9 +2127,10 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.15.tgz", - "integrity": "sha512-SAj8oKi8UogVi6eXQXKNPu8qZ78Yzy7zawrlTr0M+IuW/g8Qe9gVDhGcF9h1S69OyACpYoLxEzpjs1M15sI5wQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.0.tgz", + "integrity": "sha512-HxiRMOncx3ly6f3fcZ1GVKf+/EROcI9qwPgmij8Czqy6Okm/0T37T4y2ZIlLUuEUFjtM7NRsfdCO8Y3tAiJZew==", + "license": "MIT", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -2143,34 +2140,35 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2178,13 +2176,13 @@ } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2194,16 +2192,18 @@ "node_modules/@braintree/sanitize-url": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==" + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "license": "MIT" }, "node_modules/@codemirror/autocomplete": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz", - "integrity": "sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.13.0.tgz", + "integrity": "sha512-SuDrho1klTINfbcMPnyro1ZxU9xJtwDMtb62R8TjL/tOl71IoOsvBo1a9x+hDvHhIzkTcJHy2VC+rmpGgYkRSw==", + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.6.0", + "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" }, "peerDependencies": { @@ -2214,20 +2214,22 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.5.tgz", - "integrity": "sha512-dSi7ow2P2YgPBZflR9AJoaTHvqmeGIgkhignYMd5zK5y6DANTvxKxp6eMEpIDUJkRAaOY/TFZ4jP1ADIO/GLVA==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", + "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.2.0", + "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" + "@lezer/common": "^1.1.0" } }, "node_modules/@codemirror/lang-css": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz", "integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==", + "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", @@ -2237,9 +2239,9 @@ } }, "node_modules/@codemirror/lang-html": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.8.tgz", - "integrity": "sha512-tE2YK7wDlb9ZpAH6mpTPiYm6rhfdQKVDa5r9IwIFlwwgvVaKsCfuKKZoJGWsmMZIf3FQAuJ5CHMPLymOtg1hXw==", + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", + "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", @@ -2253,9 +2255,10 @@ } }, "node_modules/@codemirror/lang-javascript": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.1.tgz", - "integrity": "sha512-jlFOXTejVyiQCW3EQwvKH0m99bUYIw40oPmFjSX2VS78yzfe0HELZ+NEo9Yfo1MkGRpGlj3Gnu4rdxV1EnAs5A==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", + "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", + "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", @@ -2267,52 +2270,57 @@ } }, "node_modules/@codemirror/lang-python": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.3.tgz", - "integrity": "sha512-S9w2Jl74hFlD5nqtUMIaXAq9t5WlM0acCkyuQWUUSvZclk1sV+UfnpFiZzuZSG+hfEaOmxKR5UxY/Uxswn7EhQ==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", + "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", "@lezer/python": "^1.1.4" } }, "node_modules/@codemirror/lang-xml": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz", - "integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/xml": "^1.0.0" } }, "node_modules/@codemirror/language": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.0.tgz", - "integrity": "sha512-nFu311/0ne/qGuGCL3oKuktBgzVOaxCHZPZv1tLSZkNjPYxxvkjSbzno3MlErG2tgw1Yw1yF8BxMCegeMXqpiw==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz", + "integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==", + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "node_modules/@codemirror/legacy-modes": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.3.3.tgz", - "integrity": "sha512-X0Z48odJ0KIoh/HY8Ltz75/4tDYc9msQf1E/2trlxFaFFhgjpVHjZ/BCXe1Lk7s4Gd67LL/CeEEHNI+xHOiESg==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.0.tgz", + "integrity": "sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==", "dependencies": { "@codemirror/language": "^6.0.0" } }, "node_modules/@codemirror/lint": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.1.tgz", - "integrity": "sha512-2Hx945qKX7FBan5/gUdTM8fsMYrNG9clIgEcPXestbLVFAUyQYFAuju/5BMNf/PwgpVaX5pvRm4+ovjbp9D9gQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz", + "integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==", + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -2320,9 +2328,10 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.2.tgz", - "integrity": "sha512-WRihpqd0l9cEh9J3IZe45Yi+Z5MfTsEXnyc3V7qXHP4ZYtIYpGOn+EJ7fyLIkyAm/8S6QIr7/mMISfAadf8zCg==", + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -2330,14 +2339,16 @@ } }, "node_modules/@codemirror/state": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", - "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", + "license": "MIT" }, "node_modules/@codemirror/theme-one-dark": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -2346,11 +2357,12 @@ } }, "node_modules/@codemirror/view": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.18.1.tgz", - "integrity": "sha512-xcsXcMkIMd7l3WZEWoc4ljteAiqzxb5gVerRxk5132p5cLix6rTydWTQjsj2oxORepfsrwy1fC4r20iMa9plrg==", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.0.tgz", + "integrity": "sha512-XnMGOm6qXB8znzCko0N7k97qZayVdvqpA0JebxA5fHtgBjC/XlCPhH9TK92TahsoCKMPQlaTCUep06Dwj/+GXQ==", + "license": "MIT", "dependencies": { - "@codemirror/state": "^6.1.4", + "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } @@ -2360,6 +2372,7 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -2370,6 +2383,7 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -2379,14 +2393,31 @@ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "dev": true, + "license": "MIT", "peerDependencies": { "react": ">=16.8.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.3.tgz", + "integrity": "sha512-yTgnwQpFVYfvvo4SvRFB0SwrW8YjOxEoT7wfMT7Ol5v7v5LDNvSGo67aExmxOb87nQNeWPVvaGBNfQ7BXcrZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.3.tgz", + "integrity": "sha512-bviJOLMgurLJtF1/mAoJLxDZDL6oU5/ztMHnJQRejbJrSc9FFu0QoUoFhvi6qSKJEw9y5oGyvr9fuDtzJ30rNQ==", "cpu": [ "arm" ], @@ -2400,9 +2431,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.3.tgz", + "integrity": "sha512-c+ty9necz3zB1Y+d/N+mC6KVVkGUUOcm4ZmT5i/Fk5arOaY3i6CA3P5wo/7+XzV8cb4GrI/Zjp8NuOQ9Lfsosw==", "cpu": [ "arm64" ], @@ -2416,9 +2447,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.3.tgz", + "integrity": "sha512-JReHfYCRK3FVX4Ra+y5EBH1b9e16TV2OxrPAvzMsGeES0X2Ndm9ImQRI4Ket757vhc5XBOuGperw63upesclRw==", "cpu": [ "x64" ], @@ -2432,9 +2463,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.3.tgz", + "integrity": "sha512-U3fuQ0xNiAkXOmQ6w5dKpEvXQRSpHOnbw7gEfHCRXPeTKW9sBzVck6C5Yneb8LfJm0l6le4NQfkNPnWMSlTFUQ==", "cpu": [ "arm64" ], @@ -2447,9 +2478,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.3.tgz", + "integrity": "sha512-3m1CEB7F07s19wmaMNI2KANLcnaqryJxO1fXHUV5j1rWn+wMxdUYoPyO2TnAbfRZdi7ADRwJClmOwgT13qlP3Q==", "cpu": [ "x64" ], @@ -2463,9 +2494,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.3.tgz", + "integrity": "sha512-fsNAAl5pU6wmKHq91cHWQT0Fz0vtyE1JauMzKotrwqIKAswwP5cpHUCxZNSTuA/JlqtScq20/5KZ+TxQdovU/g==", "cpu": [ "arm64" ], @@ -2479,9 +2510,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.3.tgz", + "integrity": "sha512-tci+UJ4zP5EGF4rp8XlZIdq1q1a/1h9XuronfxTMCNBslpCtmk97Q/5qqy1Mu4zIc0yswN/yP/BLX+NTUC1bXA==", "cpu": [ "x64" ], @@ -2495,9 +2526,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.3.tgz", + "integrity": "sha512-f6kz2QpSuyHHg01cDawj0vkyMwuIvN62UAguQfnNVzbge2uWLhA7TCXOn83DT0ZvyJmBI943MItgTovUob36SQ==", "cpu": [ "arm" ], @@ -2511,9 +2542,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.3.tgz", + "integrity": "sha512-vvG6R5g5ieB4eCJBQevyDMb31LMHthLpXTc2IGkFnPWS/GzIFDnaYFp558O+XybTmYrVjxnryru7QRleJvmZ6Q==", "cpu": [ "arm64" ], @@ -2526,9 +2557,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.3.tgz", + "integrity": "sha512-HjCWhH7K96Na+66TacDLJmOI9R8iDWDDiqe17C7znGvvE4sW1ECt9ly0AJ3dJH62jHyVqW9xpxZEU1jKdt+29A==", "cpu": [ "ia32" ], @@ -2542,9 +2573,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.3.tgz", + "integrity": "sha512-BGpimEccmHBZRcAhdlRIxMp7x9PyJxUtj7apL2IuoG9VxvU/l/v1z015nFs7Si7tXUwEsvjc1rOJdZCn4QTU+Q==", "cpu": [ "loong64" ], @@ -2558,9 +2589,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.3.tgz", + "integrity": "sha512-5rMOWkp7FQGtAH3QJddP4w3s47iT20hwftqdm7b+loe95o8JU8ro3qZbhgMRy0VuFU0DizymF1pBKkn3YHWtsw==", "cpu": [ "mips64el" ], @@ -2574,9 +2605,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.3.tgz", + "integrity": "sha512-h0zj1ldel89V5sjPLo5H1SyMzp4VrgN1tPkN29TmjvO1/r0MuMRwJxL8QY05SmfsZRs6TF0c/IDH3u7XYYmbAg==", "cpu": [ "ppc64" ], @@ -2590,9 +2621,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.3.tgz", + "integrity": "sha512-dkAKcTsTJ+CRX6bnO17qDJbLoW37npd5gSNtSzjYQr0svghLJYGYB0NF1SNcU1vDcjXLYS5pO4qOW4YbFama4A==", "cpu": [ "riscv64" ], @@ -2606,9 +2637,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.3.tgz", + "integrity": "sha512-vnD1YUkovEdnZWEuMmy2X2JmzsHQqPpZElXx6dxENcIwTu+Cu5ERax6+Ke1QsE814Zf3c6rxCfwQdCTQ7tPuXA==", "cpu": [ "s390x" ], @@ -2622,9 +2653,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.3.tgz", + "integrity": "sha512-IOXOIm9WaK7plL2gMhsWJd+l2bfrhfilv0uPTptoRoSb2p09RghhQQp9YY6ZJhk/kqmeRt6siRdMSLLwzuT0KQ==", "cpu": [ "x64" ], @@ -2638,9 +2669,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.3.tgz", + "integrity": "sha512-uTgCwsvQ5+vCQnqM//EfDSuomo2LhdWhFPS8VL8xKf+PKTCrcT/2kPPoWMTs22aB63MLdGMJiE3f1PHvCDmUOw==", "cpu": [ "x64" ], @@ -2654,9 +2685,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.3.tgz", + "integrity": "sha512-vNAkR17Ub2MgEud2Wag/OE4HTSI6zlb291UYzHez/psiKarp0J8PKGDnAhMBcHFoOHMXHfExzmjMojJNbAStrQ==", "cpu": [ "x64" ], @@ -2670,9 +2701,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.3.tgz", + "integrity": "sha512-W8H9jlGiSBomkgmouaRoTXo49j4w4Kfbl6I1bIdO/vT0+0u4f20ko3ELzV3hPI6XV6JNBVX+8BC+ajHkvffIJA==", "cpu": [ "x64" ], @@ -2686,9 +2717,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.3.tgz", + "integrity": "sha512-EjEomwyLSCg8Ag3LDILIqYCZAq/y3diJ04PnqGRgq8/4O3VNlXyMd54j/saShaN4h5o5mivOjAzmU6C3X4v0xw==", "cpu": [ "arm64" ], @@ -2702,9 +2733,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.3.tgz", + "integrity": "sha512-WGiE/GgbsEwR33++5rzjiYsKyHywE8QSZPF7Rfx9EBfK3Qn3xyR6IjyCr5Uk38Kg8fG4/2phN7sXp4NPWd3fcw==", "cpu": [ "ia32" ], @@ -2718,9 +2749,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.3.tgz", + "integrity": "sha512-xRxC0jaJWDLYvcUvjQmHCJSfMrgmUuvsoXgDeU/wTorQ1ngDdUBuFtgY3W1Pc5sprGAvZBtWdJX7RPg/iZZUqA==", "cpu": [ "x64" ], @@ -2738,6 +2769,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -2749,10 +2781,11 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -2762,6 +2795,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -2784,13 +2818,26 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -2806,6 +2853,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2813,11 +2861,25 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2826,10 +2888,11 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -2841,29 +2904,33 @@ "dev": true }, "node_modules/@floating-ui/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", - "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.1.1" + "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.2.tgz", - "integrity": "sha512-6ArmenS6qJEWmwzczWyhvrXRdI/rI78poBcW0h/456+onlabit+2G+QxHx5xTOX60NBJQXjsCLFbW2CmsXpUog==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.4.1", - "@floating-ui/utils": "^0.1.1" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz", - "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@floating-ui/dom": "^1.5.1" + "@floating-ui/dom": "^1.6.1" }, "peerDependencies": { "react": ">=16.8.0", @@ -2871,25 +2938,26 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.2.tgz", - "integrity": "sha512-ou3elfqG/hZsbmF4bxeJhPHIf3G2pm0ujc39hYEZrfVqt7Vk/Zji6CXc3W0pmYM8BW1g40U+akTl9DKZhFhInQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==", + "license": "MIT" }, "node_modules/@formatjs/ecma402-abstract": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.2.tgz", - "integrity": "sha512-+QoPW4csYALsQIl8GbN14igZzDbuwzcpWrku9nyMXlaqAlwRBgl5V+p0vWMGFqHOw37czNXaP/lEk4wbLgcmtA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz", + "integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==", "dependencies": { "@formatjs/intl-localematcher": "0.5.4", "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-listformat": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.5.tgz", - "integrity": "sha512-XoI52qrU6aBGJC9KJddqnacuBbPlb/bXFN+lIFVFhQ1RnFHpzuFrlFdjD9am2O7ZSYsyqzYRpkVcXeT1GHkwDQ==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.7.tgz", + "integrity": "sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==", "dependencies": { - "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/ecma402-abstract": "2.0.0", "@formatjs/intl-localematcher": "0.5.4", "tslib": "^2.4.0" } @@ -2903,44 +2971,71 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", - "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz", + "integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@goauthentik/api": { - "version": "2023.10.6-1706113408", - "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.6-1706113408.tgz", - "integrity": "sha512-KHP4VM/W8FsQQ9jqhsiiWdEzMCoAqaq/ajcu5Qnq4m/jVCWUkgnUrRK7BheD6DtAqKXGTESzsXfqTyA4upOwSw==" + "version": "2024.4.2-1716550354", + "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.4.2-1716550354.tgz", + "integrity": "sha512-U7RdRxyK1e/rcprG1onVT8yUynhhuAhu4JgqtwrWRxTdZBmH1gcQrMrNzipkPseJRMFAHRbv1esxa7uRgP/Y7w==" }, "node_modules/@hcaptcha/types": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@hcaptcha/types/-/types-1.0.3.tgz", "integrity": "sha512-1mbU6eSGawRrqeahRrOzZo/SVLI6oZ5/azuBpSyVrRRR96CnS3fOVDWfzxpngfxKD0/I9Rwu6c/3ITqD8rXeTQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -2950,10 +3045,11 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -3051,265 +3147,12 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jackfranklin/rollup-plugin-markdown": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@jackfranklin/rollup-plugin-markdown/-/rollup-plugin-markdown-0.4.0.tgz", - "integrity": "sha512-9B8F/K9mzmD6cpIx1EttIVJBsHv2I1JCPYr01yxI4ibY8419wFeQ7yOykwFYNVN7wjkb+BMsct/eXnPQjt36pg==", - "dev": true, - "dependencies": { - "@types/showdown": "^2.0.0", - "gray-matter": "^4.0.2", - "rollup-pluginutils": "^2.8.2", - "showdown": "^2.1.0" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jeysal/storybook-addon-css-user-preferences": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@jeysal/storybook-addon-css-user-preferences/-/storybook-addon-css-user-preferences-0.2.0.tgz", "integrity": "sha512-XMavNKAEVO3BzcyU8cDeZzehPu64D9GXbs2OxZBlMWBiQ1RrySmRaPdvzh7t+0umLUrnYCcJwSxgAM3mBx1znw==", "dev": true, + "license": "CC0-1.0", "peerDependencies": { "@storybook/addons": "^6.4.0 || ^7", "@storybook/api": "^6.4.0 || ^7", @@ -3329,33 +3172,36 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -3365,6 +3211,9 @@ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -3374,13 +3223,15 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3390,116 +3241,132 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", - "dev": true + "dev": true, + "license": "Apache-2.0", + "peer": true }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", + "license": "MIT" }, "node_modules/@lezer/common": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.4.tgz", - "integrity": "sha512-lZHlk8p67x4aIDtJl6UQrXSOP6oi7dQR3W/geFVrENdA1JDaAJWldnVqVjPMJupbTKbzDfFcePfKttqVidS/dg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", + "license": "MIT" }, "node_modules/@lezer/css": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.3.tgz", - "integrity": "sha512-SjSM4pkQnQdJDVc80LYzEaMiNy9txsFbI7HsMgeVF28NdLaAdHNtQ+kB/QqDUzRBV/75NTXjJ/R5IdC8QQGxMg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz", + "integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==", + "license": "MIT", "dependencies": { + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "node_modules/@lezer/highlight": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz", - "integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", + "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", + "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/html": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.6.tgz", - "integrity": "sha512-Kk9HJARZTc0bAnMQUqbtuhFVsB4AnteR2BFUWfZV7L/x1H0aAKz6YabrfJ2gk/BEgjh9L3hg5O4y2IDZRBdzuQ==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz", + "integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==", + "license": "MIT", "dependencies": { - "@lezer/common": "^1.0.0", + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "node_modules/@lezer/javascript": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.7.tgz", - "integrity": "sha512-OVWlK0YEi7HM+9JRWtRkir8qvcg0/kVYg2TAMHlVtl6DU1C9yK1waEOLBMztZsV/axRJxsqfJKhzYz+bxZme5g==", + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz", + "integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==", + "license": "MIT", "dependencies": { + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.0" } }, "node_modules/@lezer/lr": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.10.tgz", - "integrity": "sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", + "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", + "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/python": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.8.tgz", - "integrity": "sha512-1T/XsmeF57ijrjpC0Zmrf9YeO5mn2zC1XeSNrOnc0KB+6PgxJ5m7kWKt0CnwyS74oHQXbJxUUL+QDQJR26c1Gw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.11.tgz", + "integrity": "sha512-C3QeLCcdAKJDUOsYjfFP6a1wdn8jhUNX200bgFm8TpKH1eM2PlgYQS5ugw6E38qGeEx7CP21I1Q52SoybXt0OQ==", + "license": "MIT", "dependencies": { + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "node_modules/@lezer/xml": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.2.tgz", - "integrity": "sha512-dlngsWceOtQBMuBPw5wtHpaxdPJ71aVntqjbpGkFtWsp4WtQmCnuTjQGocviymydN6M18fhj6UQX3oiEtSuY7w==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.5.tgz", + "integrity": "sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==", + "license": "MIT", "dependencies": { + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, - "node_modules/@lit-labs/context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@lit-labs/context/-/context-0.4.1.tgz", - "integrity": "sha512-o+uKepgEPoYAVaPvSASoDiUWKdcf7neyhFcm9dvtiLgptKoINZD1vW7GbbH/2hPtxLxgcmVfZ9NDCXNDQeHTHQ==", - "dependencies": { - "@lit/reactive-element": "^1.5.0", - "lit": "^2.7.0" - } - }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz", - "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==", + "license": "BSD-3-Clause" }, "node_modules/@lit-labs/task": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-3.1.0.tgz", "integrity": "sha512-zMlcUtZeHDT83IiT2+CJBSoFvWDLnPEezhOCgqjxW4DmRHlbgd7jdft97T6dw4S4RvIETfI7OOyvubCV/EzTlg==", + "license": "BSD-3-Clause", "dependencies": { "@lit/task": "^1.0.0" } }, - "node_modules/@lit/localize": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/@lit/localize/-/localize-0.11.4.tgz", - "integrity": "sha512-RRIwIX2tAm3+DuEndoXSJrFjGrAK5cb5IXo5K6jcJ6sbgD829B8rSqHC5MaKVUmXTVLIR1bk5IZOZDf9wFereA==", + "node_modules/@lit/context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.1.tgz", + "integrity": "sha512-q/Rw7oWSJidUP43f/RUPwqZ6f5VlY8HzinTWxL/gW1Hvm2S5q2hZvV+qM8WFcC+oLNNknc3JKsd5TwxLk1hbdg==", "dependencies": { - "@lit/reactive-element": "^1.4.0", - "lit": "^2.3.0" + "@lit/reactive-element": "^1.6.2 || ^2.0.0" + } + }, + "node_modules/@lit/localize": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@lit/localize/-/localize-0.12.1.tgz", + "integrity": "sha512-uuF6OO6fjqomCf3jXsJ5cTGf1APYuN88S4Gvo/fjt9YkG4OMaMvpEUqd5oWhyzrJfY+HcenAbLJNi2Cq3H7gdg==", + "dependencies": { + "lit": "^2.0.0 || ^3.0.0" } }, "node_modules/@lit/localize-tools": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@lit/localize-tools/-/localize-tools-0.7.1.tgz", - "integrity": "sha512-qqJw501aEPF1j9QQmiVC25yU1By1DKEUIFgjszIierwr5jJzfVtGTj67D8UU0hF3vA2yAaWxcl4eooM1Yr0zKQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@lit/localize-tools/-/localize-tools-0.7.2.tgz", + "integrity": "sha512-d5tehVao3Hz1DlTq6jy7TUYrCeyFi/E4BkzWr8MuAMjIM8aoKCR9s3cUw6m++8ZIiqGm2z7+6aHaPc/p1FGHyA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lit/localize": "^0.12.0", "@parse5/tools": "^0.3.0", @@ -3507,82 +3374,20 @@ "fast-glob": "^3.2.7", "fs-extra": "^10.0.0", "jsonschema": "^1.4.0", - "lit": "^2.0.0 || ^3.0.0", + "lit": "^3.1.2", "minimist": "^1.2.5", "parse5": "^7.1.1", "source-map-support": "^0.5.19", - "typescript": "~5.2.0" + "typescript": "~5.3.3" }, "bin": { "lit-localize": "bin/lit-localize.js" } }, - "node_modules/@lit/localize-tools/node_modules/@lit/localize": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@lit/localize/-/localize-0.12.0.tgz", - "integrity": "sha512-DrzF1nBhwyLEXDoUuVm4bCUzB1U9IgXlV+SkR7KEx4YpbaHSUuKw69ZJ5lMHJVuvbxdh23D8VeVwqs0mGF9jeQ==", - "dev": true, - "dependencies": { - "@lit/reactive-element": "^2.0.0", - "lit": "^3.0.0" - } - }, - "node_modules/@lit/localize-tools/node_modules/@lit/reactive-element": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.0.tgz", - "integrity": "sha512-wn+2+uDcs62ROBmVAwssO4x5xue/uKD3MGGZOXL2sMxReTRIT0JXKyMXeu7gh0aJ4IJNEIG/3aOnUaQvM7BMzQ==", - "dev": true, - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.1.2-pre.0" - } - }, - "node_modules/@lit/localize-tools/node_modules/lit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.0.0.tgz", - "integrity": "sha512-nQ0teRzU1Kdj++VdmttS2WvIen8M79wChJ6guRKIIym2M3Ansg3Adj9O6yuQh2IpjxiUXlNuS81WKlQ4iL3BmA==", - "dev": true, - "dependencies": { - "@lit/reactive-element": "^2.0.0", - "lit-element": "^4.0.0", - "lit-html": "^3.0.0" - } - }, - "node_modules/@lit/localize-tools/node_modules/lit-element": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.0.tgz", - "integrity": "sha512-N6+f7XgusURHl69DUZU6sTBGlIN+9Ixfs3ykkNDfgfTkDYGGOWwHAYBhDqVswnFGyWgQYR2KiSpu4J76Kccs/A==", - "dev": true, - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.1.2-pre.0", - "@lit/reactive-element": "^2.0.0", - "lit-html": "^3.0.0" - } - }, - "node_modules/@lit/localize-tools/node_modules/lit-html": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.0.0.tgz", - "integrity": "sha512-DNJIE8dNY0dQF2Gs0sdMNUppMQT2/CvV4OVnSdg7BXAsGqkVwsE5bqQ04POfkYH5dBIuGnJYdFz5fYYyNnOxiA==", - "dev": true, - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, - "node_modules/@lit/localize-tools/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/@lit/localize-tools/node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3593,35 +3398,36 @@ } }, "node_modules/@lit/reactive-element": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", - "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.0.0" + "@lit-labs/ssr-dom-shim": "^1.2.0" } }, "node_modules/@lit/task": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.0.tgz", "integrity": "sha512-7jocGBh3yGlo3kKxQggZph2txK4X5GYNWp2FAsmV9u2spzUypwrzRzXe8I72icAb02B00+k2nlvxVcrQB6vyrw==", + "license": "BSD-3-Clause", "dependencies": { "@lit/reactive-element": "^1.0.0 || ^2.0.0" } }, "node_modules/@mdx-js/react": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", - "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dev": true, "dependencies": { - "@types/mdx": "^2.0.0", - "@types/react": ">=16" + "@types/mdx": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" }, "peerDependencies": { + "@types/react": ">=16", "react": ">=16" } }, @@ -3641,6 +3447,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -3654,6 +3461,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -3663,6 +3471,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -3672,11 +3481,12 @@ } }, "node_modules/@open-wc/lit-helpers": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@open-wc/lit-helpers/-/lit-helpers-0.6.0.tgz", - "integrity": "sha512-9F0Rw18Lupp8hehF299yYozN4cFMTnHeCVNtz0k18/eUkcUUb6DCWerL/ASJ9lZ4bLA/YUPmrkdgZz/xe9cKeg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@open-wc/lit-helpers/-/lit-helpers-0.7.0.tgz", + "integrity": "sha512-4NBlx5ve0EvZplCRJbESm0MdMbRCw16alP2y76KAAAwzmFFXXrUj5hFwhw55+sSg5qaRRx6sY+s7usKgnNo3TQ==", + "license": "MIT", "peerDependencies": { - "lit": "^2.0.0" + "lit": "^2.0.0 || ^3.0.0" } }, "node_modules/@parse5/tools": { @@ -3684,60 +3494,43 @@ "resolved": "https://registry.npmjs.org/@parse5/tools/-/tools-0.3.0.tgz", "integrity": "sha512-zxRyTHkqb7WQMV8kTNBKWb1BeOFUKXBXTBWuxg9H9hfvQB3IwP6Iw2U75Ia5eyRxPNltmY7E8YAlz6zWwUnjKg==", "dev": true, + "license": "MIT", "dependencies": { "parse5": "^7.0.0" } }, - "node_modules/@parse5/tools/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/@patternfly/elements": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-2.4.0.tgz", - "integrity": "sha512-mA6I76R8aHdBKRX+IbaVuD24OnYUBsjStDwGVq7ytopA0XUKx12xTwgRZGNM7wKBBFYbNKpIxxuaanQSLZTGIQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-3.0.1.tgz", + "integrity": "sha512-vrnpPF1LSuuCRMDsHU6ZUIrAworWPiY+ZtCQ+jv0HQw63ET1X81lmBDCt3o5wKhwswAW08ke6sIDLsZiF2vKJw==", "dependencies": { + "@lit/context": "^1.1.0", "@patternfly/icons": "^1.0.2", - "@patternfly/pfe-core": "^2.4.0", - "lit": "2.6.1", - "tslib": "^2.4.1" - } - }, - "node_modules/@patternfly/elements/node_modules/lit": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.6.1.tgz", - "integrity": "sha512-DT87LD64f8acR7uVp7kZfhLRrHkfC/N4BVzAtnw9Yg8087mbBJ//qedwdwX0kzDbxgPccWRW6mFwGbRQIxy0pw==", - "dependencies": { - "@lit/reactive-element": "^1.6.0", - "lit-element": "^3.2.0", - "lit-html": "^2.6.0" + "@patternfly/pfe-core": "^3.0.0", + "lit": "^3.1.2", + "tslib": "^2.6.2" } }, "node_modules/@patternfly/icons": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@patternfly/icons/-/icons-1.0.2.tgz", - "integrity": "sha512-/faOTZsKkTPxuCDcWZbunknjUhJIjjN0h+OicNiFWxTq/saLp366cLhdgNf8A46oeGR/21aQTYVXTqcQA1yvOg==" + "integrity": "sha512-/faOTZsKkTPxuCDcWZbunknjUhJIjjN0h+OicNiFWxTq/saLp366cLhdgNf8A46oeGR/21aQTYVXTqcQA1yvOg==", + "license": "MIT" }, "node_modules/@patternfly/patternfly": { "version": "4.224.5", "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.224.5.tgz", - "integrity": "sha512-io0huj+LCP5FgDZJDaLv1snxktTYs8iCFz/W1VDRneYoebNHLmGfQdF7Yn8bS6PF7qmN6oJKEBlq3AjmmE8vdA==" + "integrity": "sha512-io0huj+LCP5FgDZJDaLv1snxktTYs8iCFz/W1VDRneYoebNHLmGfQdF7Yn8bS6PF7qmN6oJKEBlq3AjmmE8vdA==", + "license": "MIT" }, "node_modules/@patternfly/pfe-core": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@patternfly/pfe-core/-/pfe-core-2.4.1.tgz", - "integrity": "sha512-ZqN4Zk2ysrnHp84hKvUr54xeSwtzqM3qRPpMzdd2fa58htYnPfhow4TQ8LH9vArLxPzEAB3Hrfql0VW1bk5PXw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@patternfly/pfe-core/-/pfe-core-3.0.0.tgz", + "integrity": "sha512-zxJ2dksvTsurQ74EHlNWv03P1HH/ZO+axX0XPyjDdkOWpbyL4UDK6x5VXDRRtiZ3CrRs7VX3RbBfB5EQ1gBZ5A==", "dependencies": { - "@floating-ui/dom": "^1.2.6", - "lit": "^2.7.2" + "@floating-ui/dom": "^1.6.3", + "@lit/context": "^1.1.0", + "lit": "^3.1.2" } }, "node_modules/@pkgjs/parseargs": { @@ -3755,6 +3548,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10" } @@ -3764,6 +3559,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" } @@ -3773,6 +3569,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-primitive": "1.0.3" @@ -3797,6 +3595,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", @@ -3824,6 +3624,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -3842,6 +3643,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -3855,11 +3657,128 @@ } } }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -3878,6 +3797,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -3906,6 +3827,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -3924,6 +3846,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", @@ -3950,6 +3874,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-layout-effect": "1.0.1" @@ -3969,6 +3894,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@floating-ui/react-dom": "^2.0.0", @@ -4002,6 +3929,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-primitive": "1.0.3" @@ -4021,11 +3950,37 @@ } } }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-primitive": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-slot": "1.0.2" @@ -4050,6 +4005,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -4082,6 +4039,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.1", @@ -4126,6 +4085,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-primitive": "1.0.3" @@ -4150,6 +4111,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1" @@ -4169,6 +4131,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", "integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -4195,6 +4159,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz", "integrity": "sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -4225,6 +4191,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.0.4.tgz", "integrity": "sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -4255,6 +4223,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -4273,6 +4242,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.1" @@ -4292,6 +4262,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.1" @@ -4311,6 +4282,7 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -4329,6 +4301,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -4347,6 +4321,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/rect": "1.0.1" @@ -4366,6 +4342,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-layout-effect": "1.0.1" @@ -4385,6 +4363,8 @@ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-primitive": "1.0.3" @@ -4409,86 +4389,12 @@ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.13.10" } }, - "node_modules/@rollup/plugin-babel": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", - "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@rollup/pluginutils": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - }, - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.7", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", - "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "glob": "^8.0.3", - "is-reference": "1.2.1", - "magic-string": "^0.30.3" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", - "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, "node_modules/@rollup/plugin-replace": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.5.tgz", @@ -4510,54 +4416,6 @@ } } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dev": true, - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-typescript": { - "version": "11.1.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", - "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.1.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.14.0||^3.0.0||^4.0.0", - "tslib": "*", - "typescript": ">=3.7.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - }, - "tslib": { - "optional": true - } - } - }, "node_modules/@rollup/pluginutils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", @@ -4581,9 +4439,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", - "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz", + "integrity": "sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==", "cpu": [ "arm" ], @@ -4591,12 +4449,13 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", - "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz", + "integrity": "sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==", "cpu": [ "arm64" ], @@ -4604,25 +4463,25 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", - "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", - "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz", + "integrity": "sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==", "cpu": [ "x64" ], @@ -4630,12 +4489,13 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", - "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz", + "integrity": "sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==", "cpu": [ "arm" ], @@ -4643,25 +4503,25 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", - "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", - "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz", + "integrity": "sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==", "cpu": [ "arm64" ], @@ -4669,12 +4529,27 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz", + "integrity": "sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==", + "cpu": [ + "ppc64le" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", - "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz", + "integrity": "sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==", "cpu": [ "riscv64" ], @@ -4682,25 +4557,39 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz", + "integrity": "sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", - "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", - "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz", + "integrity": "sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==", "cpu": [ "x64" ], @@ -4708,12 +4597,13 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", - "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz", + "integrity": "sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==", "cpu": [ "arm64" ], @@ -4721,12 +4611,13 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", - "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz", + "integrity": "sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==", "cpu": [ "ia32" ], @@ -4734,12 +4625,13 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", - "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz", + "integrity": "sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==", "cpu": [ "x64" ], @@ -4747,151 +4639,159 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, - "node_modules/@sentry-internal/feedback": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.95.0.tgz", - "integrity": "sha512-UWNUUg+OrhV58/ChQNY0yLCCYdEI2cIYVwq1riZ+AFU9Z2ZyCxEoSRVLh7c5tnCPLbKAPR+VvlEsSjMqucAKnA==", + "node_modules/@sentry-internal/browser-utils": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.4.0.tgz", + "integrity": "sha512-Mfm3TK3KUlghhuKM3rjTeD4D5kAiB7iVNFoaDJIJBVKa67M9BvlNTnNJMDi7+9rV4RuLQYxXn0p5HEZJFYp3Zw==", "dependencies": { - "@sentry/core": "7.95.0", - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" + "@sentry/core": "8.4.0", + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" }, "engines": { - "node": ">=12" + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.4.0.tgz", + "integrity": "sha512-1/WshI2X9seZAQXrOiv6/LU08fbSSvJU0b1ZWMhn+onb/FWPomsL/UN0WufCYA65S5JZGdaWC8fUcJxWC8PATQ==", + "dependencies": { + "@sentry/core": "8.4.0", + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.4.0.tgz", + "integrity": "sha512-RSzQwCF/QTi5/5XAuj0VJImAhu4MheeHYvAbr/PuMSF4o1j89gBA7e3boA4u8633IqUeu5w3S5sb6jVrKaVifg==", + "dependencies": { + "@sentry-internal/browser-utils": "8.4.0", + "@sentry/core": "8.4.0", + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" + }, + "engines": { + "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.95.0.tgz", - "integrity": "sha512-nK+VYLnhlxLnnEUPMnzN8BSCFXPy2dQ5OVFO+fiTNPlGCbxsq8O9SnkX6E+u1oPLSA/151s2B3VxIasR8bXJAQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.4.0.tgz", + "integrity": "sha512-g+U4IPQdODCg7fQQVNvH6ix05Tl1mOQXXRexgtp+tXdys4sHQSBUYraJYZy+mY3OGnLRgKFqELM0fnffJSpuyQ==", "dependencies": { - "@sentry/core": "7.95.0", - "@sentry/replay": "7.95.0", - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" + "@sentry-internal/replay": "8.4.0", + "@sentry/core": "8.4.0", + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@sentry-internal/tracing": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.95.0.tgz", - "integrity": "sha512-YKiLPMnEgTsTh7u/W1Zep9HtV1rJqAetqJ4ekaIxyUUB6ppi6V00MacSjb01o++fwlNNDYFxNpJlgQqNPqsCNA==", - "dependencies": { - "@sentry/core": "7.95.0", - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" - }, - "engines": { - "node": ">=8" + "node": ">=14.18" } }, "node_modules/@sentry/browser": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.95.0.tgz", - "integrity": "sha512-J+bAryc/7StRZSeaJByLTnEslWu7uXaZ1zERQF17sZbRxvbyaYbAO7cqSUKZ1gK3p9QfrkqzNl7xA8thg4FtHQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.4.0.tgz", + "integrity": "sha512-hmXeIZBdN0A6yCuoMTcigGxLl42nbeb205fXtouwE7Maa0qM2HM+Ijq0sHzbhxR3zU0JXDtcJh1k6wtJOREJ3g==", "dependencies": { - "@sentry-internal/feedback": "7.95.0", - "@sentry-internal/replay-canvas": "7.95.0", - "@sentry-internal/tracing": "7.95.0", - "@sentry/core": "7.95.0", - "@sentry/replay": "7.95.0", - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" + "@sentry-internal/browser-utils": "8.4.0", + "@sentry-internal/feedback": "8.4.0", + "@sentry-internal/replay": "8.4.0", + "@sentry-internal/replay-canvas": "8.4.0", + "@sentry/core": "8.4.0", + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" }, "engines": { - "node": ">=8" + "node": ">=14.18" } }, "node_modules/@sentry/core": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.95.0.tgz", - "integrity": "sha512-z+ffO6jK/ZUxnRbBGmnj5sOouKZ4mvRY0KJa33kbyqcmeiJKrN81M7Ecj1IJUCamo/6RqX0GCwDDxgUPZZZBwA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.4.0.tgz", + "integrity": "sha512-0eACPlJvKloFIlcT1c/vjGnvqxLxpGyGuSsU7uonrkmBqIRwLYXWtR4PoHapysKtjPVoHAn9au50ut6ymC2V8Q==", "dependencies": { - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" + "@sentry/types": "8.4.0", + "@sentry/utils": "8.4.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/replay": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.95.0.tgz", - "integrity": "sha512-WAAEvWCXoNC7hfPI1fNoxODB9UzUYhXtscrWIm89Mn3AAi8haayVNNiUWKVj6+Vpt87C+/sb9UsERwdPWpl/Sw==", - "dependencies": { - "@sentry-internal/tracing": "7.95.0", - "@sentry/core": "7.95.0", - "@sentry/types": "7.95.0", - "@sentry/utils": "7.95.0" - }, - "engines": { - "node": ">=12" + "node": ">=14.18" } }, "node_modules/@sentry/types": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.95.0.tgz", - "integrity": "sha512-ouU7NsEcrwmcnXHMNBGmKZEmKMzmgPGoBydZn1gukCI67Ci71fAYpPNrbtmjai6+jtsY21o45rVLqExru2sdfw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.4.0.tgz", + "integrity": "sha512-mHUaaYEQCNukzYsTLp4rP2NNO17vUf+oSGS6qmhrsGqmGNICKw2CIwJlPPGeAkq9Y4tiUOye2m5OT1xsOtxLIw==", "engines": { - "node": ">=8" + "node": ">=14.18" } }, "node_modules/@sentry/utils": { - "version": "7.95.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.95.0.tgz", - "integrity": "sha512-0zget8AOaQWLIEA9cTx/qiQQYpx2x0UfnaW5xRmQg12QGTSngo/cUm9O04zuHw5gpBBGG0ocMDHxwwr+UCCBiw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-oDF0RVWW0AyEnsP1x4McHUvQSAxJgx3G6wM9Sb4wc1F8rwsHnCtGHc+WRZ5Gd2AXC5EGkfbg5919+1ku/L4Dww==", "dependencies": { - "@sentry/types": "7.95.0" + "@sentry/types": "8.4.0" }, "engines": { - "node": ">=8" + "node": ">=14.18" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/@spotlightjs/overlay": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-1.3.0.tgz", - "integrity": "sha512-ZBh75oGv12HQ132QtW9qXIkDLHvDZDm7ex4bKzHu61pNfWy3+hIFKUbIftzg0oMdmacFOE3pO0MSjUwmtvzEUA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-1.8.3.tgz", + "integrity": "sha512-6b5tBspOOEd6Gj0l4xgdUwR4Ydn2dNX9lqJ/WSzIu1lqkI96w2lqf69IGzEo6jb9aPtfTtu8nx5K2SD6JXH2SA==", "dev": true }, "node_modules/@spotlightjs/sidecar": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@spotlightjs/sidecar/-/sidecar-1.3.4.tgz", - "integrity": "sha512-uWnmjh3K+2YPpnNu4g6KsXxq/HGmVTL6lHO9C2pYBw6KPPqRHGoZmML6ea8HSJdWmW+jEKmYHS8sjvIQOj2nvA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@spotlightjs/sidecar/-/sidecar-1.4.0.tgz", + "integrity": "sha512-onj/phrNtDI8a79zc8jfxJ5BITQk5klO4xSoQXxiYeQWTZcegVeO8VftOVfWPBnMY/axnh+ltxJm/cHaV5SP6Q==", "dev": true, + "license": "Apache-2.0", "bin": { "spotlight-sidecar": "server.js" } }, "node_modules/@spotlightjs/spotlight": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-1.2.7.tgz", - "integrity": "sha512-w2YF0r7y9Jm1B3CsOgXcnZW3IEiiO3YjdvYQ6FSArvOD/WaCEMNXe9wfsHWqgk3+tE0Pw+JDpXUeqlskDojHVw==", + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-1.2.17.tgz", + "integrity": "sha512-91qtnLspMl2e1olBTeWoZcupwwTzQs8clQgTF8wv2Ib18zce7YYLvWpnDhNIVNQlbKIjGhYum6UY/KCfUCXQYg==", "dev": true, "dependencies": { - "@spotlightjs/overlay": "1.3.0", - "@spotlightjs/sidecar": "1.3.4" + "@spotlightjs/overlay": "1.8.3", + "@spotlightjs/sidecar": "1.4.0" }, "bin": { "spotlight-sidecar": "bin/run.js" } }, "node_modules/@storybook/addon-actions": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.6.10.tgz", - "integrity": "sha512-pcKmf0H/caGzKDy8cz1adNSjv+KOBWLJ11RzGExrWm+Ad5ACifwlsQPykJ3TQ/21sTd9IXVrE9uuq4LldEnPbg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.1.3.tgz", + "integrity": "sha512-XG6clFT/lPOHEm/tHdWO3E5G28HIock2272BZNr15+DqVTRYyGRhuFQKxPb+CdRWCpT1VQnWS+L9S1+95wDlJw==", "dev": true, "dependencies": { - "@storybook/core-events": "7.6.10", + "@storybook/core-events": "8.1.3", "@storybook/global": "^5.0.0", "@types/uuid": "^9.0.1", "dequal": "^2.0.2", @@ -4903,10 +4803,24 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/addon-actions/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/addon-backgrounds": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.10.tgz", - "integrity": "sha512-kGzsN1QkfyI8Cz7TErEx9OCB3PMzpCFGLd/iy7FreXwbMbeAQ3/9fYgKUsNOYgOhuTz7S09koZUWjS/WJuZGFA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.1.3.tgz", + "integrity": "sha512-XBCDugJWCzJOMhkFPVFCtGCtABYr1LDUot9xfOWPwQbshGwsdSf++TcayUbJKI5MJRuNYmnG4V0YYoRxVkDDVA==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0", @@ -4919,12 +4833,13 @@ } }, "node_modules/@storybook/addon-controls": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.6.10.tgz", - "integrity": "sha512-LjwCQRMWq1apLtFwDi6U8MI6ITUr+KhxJucZ60tfc58RgB2v8ayozyDAonFEONsx9YSR1dNIJ2Z/e2rWTBJeYA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.1.3.tgz", + "integrity": "sha512-3/w5/AVrA+U3A5VtYmqJoj2kCu6qVLB6ycsusxsAlRKkXTRO5HvbK1Ndm8oPNaKaJT4W22VIVem6SyVMiNq4Kw==", "dev": true, "dependencies": { - "@storybook/blocks": "7.6.10", + "@storybook/blocks": "8.1.3", + "dequal": "^2.0.2", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" }, @@ -4934,58 +4849,125 @@ } }, "node_modules/@storybook/addon-docs": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.6.10.tgz", - "integrity": "sha512-GtyQ9bMx1AOOtl6ZS9vwK104HFRK+tqzxddRRxhXkpyeKu3olm9aMgXp35atE/3fJSqyyDm2vFtxxH8mzBA20A==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.1.3.tgz", + "integrity": "sha512-oASBnWOT9bUXo3rWDH8Ph8xWvi7cia1Bn/aoA2YlkJIC9R99FLQbEeKOJgcANWBC05YnLF75k4AOZOLqLPMVxQ==", "dev": true, "dependencies": { - "@jest/transform": "^29.3.1", - "@mdx-js/react": "^2.1.5", - "@storybook/blocks": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/components": "7.6.10", - "@storybook/csf-plugin": "7.6.10", - "@storybook/csf-tools": "7.6.10", + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/components": "8.1.3", + "@storybook/csf-plugin": "8.1.3", + "@storybook/csf-tools": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/mdx2-csf": "^1.0.0", - "@storybook/node-logger": "7.6.10", - "@storybook/postinstall": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/react-dom-shim": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/node-logger": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/react-dom-shim": "8.1.3", + "@storybook/theming": "8.1.3", + "@storybook/types": "8.1.3", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "fs-extra": "^11.1.0", - "remark-external-links": "^8.0.0", - "remark-slug": "^6.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", "ts-dedent": "^2.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/components": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.1.3.tgz", + "integrity": "sha512-g9HB3CZvhDWoh1UJ4FiRRHDgZtKmh8H38zCK9xzyySxD9V7f9BobBChb3Xqlou3YCk5MqlGqudIg+xtHqNBPrg==", + "dev": true, + "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-slot": "^1.0.2", + "@storybook/client-logger": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@storybook/theming": "8.1.3", + "@storybook/types": "8.1.3", + "memoizerific": "^1.11.3", + "util-deprecate": "^1.0.2" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/addon-docs/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -4994,6 +4976,49 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/theming": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.1.3.tgz", + "integrity": "sha512-BXtD5pna4eAAxNbzZUijP6W25IFVhvANG5P96xYM+OH+5OMSdLpDANnG2qWcZumwX5JFd74KqOIuV8yIO0AYXQ==", + "dev": true, + "dependencies": { + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@storybook/client-logger": "8.1.3", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-docs/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/addon-docs/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -5009,53 +5034,93 @@ } }, "node_modules/@storybook/addon-essentials": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.6.10.tgz", - "integrity": "sha512-cjbuCCK/3dtUity0Uqi5LwbkgfxqCCE5x5mXZIk9lTMeDz5vB9q6M5nzncVDy8F8przF3NbDLLgxKlt8wjiICg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.1.3.tgz", + "integrity": "sha512-Ziv7jEM7f37JNDkd7+x5UCZWBHv7HgQ2LuUEV7mv5FtBbT+9ors/155PfzBLOpDjGQytVKiHuwChsbBvfIqdJg==", "dev": true, "dependencies": { - "@storybook/addon-actions": "7.6.10", - "@storybook/addon-backgrounds": "7.6.10", - "@storybook/addon-controls": "7.6.10", - "@storybook/addon-docs": "7.6.10", - "@storybook/addon-highlight": "7.6.10", - "@storybook/addon-measure": "7.6.10", - "@storybook/addon-outline": "7.6.10", - "@storybook/addon-toolbars": "7.6.10", - "@storybook/addon-viewport": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/manager-api": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview-api": "7.6.10", + "@storybook/addon-actions": "8.1.3", + "@storybook/addon-backgrounds": "8.1.3", + "@storybook/addon-controls": "8.1.3", + "@storybook/addon-docs": "8.1.3", + "@storybook/addon-highlight": "8.1.3", + "@storybook/addon-measure": "8.1.3", + "@storybook/addon-outline": "8.1.3", + "@storybook/addon-toolbars": "8.1.3", + "@storybook/addon-viewport": "8.1.3", + "@storybook/core-common": "8.1.3", + "@storybook/manager-api": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/preview-api": "8.1.3", "ts-dedent": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-essentials/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-essentials/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-essentials/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/addon-essentials/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -5064,10 +5129,25 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/addon-essentials/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/addon-highlight": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.6.10.tgz", - "integrity": "sha512-dIuS5QmoT1R+gFOcf6CoBa6D9UR5/wHCfPqPRH8dNNcCLtIGSHWQ4v964mS5OCq1Huj7CghmR15lOUk7SaYwUA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.1.3.tgz", + "integrity": "sha512-X+sTpav2GDOY5M9M+n4nFrPMAtnZYxjh4gULl1IAWDcDt2zgiu5wqB6tWtz+qmLla8jdwkdpb5GmuEYuayngDQ==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -5078,12 +5158,12 @@ } }, "node_modules/@storybook/addon-links": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.6.10.tgz", - "integrity": "sha512-s/WkSYHpr2pb9p57j6u/xDBg3TKJhBq55YMl0GB5gXgkRPIeuGbPhGJhm2yTGVFLvXgr/aHHnOxb/R/W8PiRhA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.1.3.tgz", + "integrity": "sha512-WwXrSDmtpjDJvUMMKbQSio7w5yVu51Gndamf/EkkRXGMauBAm7rW5M/S1Rky3ZPhHt9a6ByI51GpGMDrNFLoRQ==", "dev": true, "dependencies": { - "@storybook/csf": "^0.1.2", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", "ts-dedent": "^2.0.0" }, @@ -5092,7 +5172,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" }, "peerDependenciesMeta": { "react": { @@ -5101,9 +5181,9 @@ } }, "node_modules/@storybook/addon-measure": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.6.10.tgz", - "integrity": "sha512-OVfTI56+kc4hLWfZ/YPV3WKj/aA9e4iKXYxZyPdhfX4Z8TgZdD1wv9Z6e8DKS0H5kuybYrHKHaID5ki6t7qz3w==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.1.3.tgz", + "integrity": "sha512-i5A9RDKh6Bg3j+9S3fjZQtBe827Svemz0VFe00efaUrCj9tuNPRD/ggFiToUa4Q+qtqT8K1mLeg6IsTfl6LR8A==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0", @@ -5115,9 +5195,9 @@ } }, "node_modules/@storybook/addon-outline": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.6.10.tgz", - "integrity": "sha512-RVJrEoPArhI6zAIMNl1Gz0zrj84BTfEWYYz0yDWOTVgvN411ugsoIk1hw0671MOneXJ2RcQ9MFIeV/v6AVDQYg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.1.3.tgz", + "integrity": "sha512-4kz2WfxwRUBOaNuESlFbJs3WHjHhIAvMRikVzzZLbY0U3gM5Tz5LnjuPw/oIGts/+bXb6/S4vwO8o3xO1Ghnzg==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0", @@ -5129,9 +5209,9 @@ } }, "node_modules/@storybook/addon-toolbars": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.6.10.tgz", - "integrity": "sha512-PaXY/oj9yxF7/H0CNdQKcioincyCkfeHpISZriZbZqhyqsjn3vca7RFEmsB88Q+ou6rMeqyA9st+6e2cx/Ct6A==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.1.3.tgz", + "integrity": "sha512-cJmYRp8thYcaFXp/81nAODH4xePkkhmr+pSevKyHInUWL/L0/ZiE7DMHPsFABj7QKqbuy1dn8WqIRgYDjKDCYg==", "dev": true, "funding": { "type": "opencollective", @@ -5139,9 +5219,9 @@ } }, "node_modules/@storybook/addon-viewport": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.6.10.tgz", - "integrity": "sha512-+bA6juC/lH4vEhk+w0rXakaG8JgLG4MOYrIudk5vJKQaC6X58LIM9N4kzIS2KSExRhkExXBPrWsnMfCo7uxmKg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.1.3.tgz", + "integrity": "sha512-zronhXim/TjSYqA63m7r9plqP+QX4p6jWLkc5y6mkqLY/pIaMnvFg4aCA6Nv1HL96krU9WvT96AIqbIsXNlTTg==", "dev": true, "dependencies": { "memoizerific": "^1.11.3" @@ -5152,62 +5232,16 @@ } }, "node_modules/@storybook/addons": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.4.2.tgz", - "integrity": "sha512-3snQVlTIKgzk6apNZc9sHr+0n4riiQkKGUkoHS8B1G90qj/9OyRnkDq55A7mJ9CxskqIjei5Q+hlko87g0jDsA==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.6.17.tgz", + "integrity": "sha512-Ok18Y698Ccyg++MoUNJNHY0cXUvo8ETFIRLJk1g9ElJ70j6kPgNnzW2pAtZkBNmswHtofZ7pT156cj96k/LgfA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@storybook/manager-api": "7.4.2", - "@storybook/preview-api": "7.4.2", - "@storybook/types": "7.4.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addons/node_modules/@storybook/channels": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.4.2.tgz", - "integrity": "sha512-Q95KnV+fTGaAV3S875+d5LlGg+bdC3bUnki3engODDS4ViSRHJ1bnXnqxKmAaS3O/52geIyWWR766YvwHw3avw==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "7.4.2", - "@storybook/core-events": "7.4.2", - "@storybook/global": "^5.0.0", - "qs": "^6.10.0", - "telejson": "^7.2.0", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addons/node_modules/@storybook/client-logger": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.4.2.tgz", - "integrity": "sha512-LC8tYrYSJwF4DHRdNYh6y8hSvccwUIv5/WOZKJDmKx7mcEm6HsVuUu16C9jsl7iy6IqJYxgVz1va3WS6852E+A==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addons/node_modules/@storybook/core-events": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.4.2.tgz", - "integrity": "sha512-WCEBw+Ew8DrccnB0hpP9TXadreoOlMnWCyuXU2XrvmK/vde009leWQIsLs1rY+L17zDVuogBms62AxrDDJmMpw==", - "dev": true, - "dependencies": { - "ts-dedent": "^2.0.0" + "@storybook/manager-api": "7.6.17", + "@storybook/preview-api": "7.6.17", + "@storybook/types": "7.6.17" }, "funding": { "type": "opencollective", @@ -5215,23 +5249,23 @@ } }, "node_modules/@storybook/addons/node_modules/@storybook/manager-api": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.4.2.tgz", - "integrity": "sha512-gKPG0At9AGhF32iwjiba+ILqswc3ZFj9ZIu5HjGEmaoiOfqI6TayuHoptup0QxkI/Hx8f9mNkHCwR9COrmb69w==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.17.tgz", + "integrity": "sha512-IJIV1Yc6yw1dhCY4tReHCfBnUKDqEBnMyHp3mbXpsaHxnxJZrXO45WjRAZIKlQKhl/Ge1CrnznmHRCmYgqmrWg==", "dev": true, + "peer": true, "dependencies": { - "@storybook/channels": "7.4.2", - "@storybook/client-logger": "7.4.2", - "@storybook/core-events": "7.4.2", - "@storybook/csf": "^0.1.0", + "@storybook/channels": "7.6.17", + "@storybook/client-logger": "7.6.17", + "@storybook/core-events": "7.6.17", + "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/router": "7.4.2", - "@storybook/theming": "7.4.2", - "@storybook/types": "7.4.2", + "@storybook/router": "7.6.17", + "@storybook/theming": "7.6.17", + "@storybook/types": "7.6.17", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", - "semver": "^7.3.7", "store2": "^2.14.2", "telejson": "^7.2.0", "ts-dedent": "^2.0.0" @@ -5239,108 +5273,74 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@storybook/addons/node_modules/@storybook/router": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.4.2.tgz", - "integrity": "sha512-TFpMrmliklWNSrF84kGnh3WcLZciqIvaAjhxahqD+kx070KLqjxrsiny7UC6PUUYZdjLkbR9m8n3SFdXAVKgLw==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.17.tgz", + "integrity": "sha512-GnyC0j6Wi5hT4qRhSyT8NPtJfGmf82uZw97LQRWeyYu5gWEshUdM7aj40XlNiScd5cZDp0owO1idduVF2k2l2A==", "dev": true, + "peer": true, "dependencies": { - "@storybook/client-logger": "7.4.2", + "@storybook/client-logger": "7.6.17", "memoizerific": "^1.11.3", "qs": "^6.10.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@storybook/addons/node_modules/@storybook/theming": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.4.2.tgz", - "integrity": "sha512-wVmxZHVCqDoZgUOXTS4HRV4UClLtCydRNOEuUZ7X08QIPSA1FVL3gEpTQJfgCsyBX/cwSSofAMUbzAGEVNo+9g==", - "dev": true, - "dependencies": { - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.4.2", - "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addons/node_modules/@storybook/types": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.4.2.tgz", - "integrity": "sha512-OOJ2TeS3Zzc6spHbdH+JXml0q4IHuYt9axmXAv1/pkhqHjA5072pyUacmlYNQeihpQOOsKLiCQUQlvtMy9fTnQ==", - "dev": true, - "dependencies": { - "@storybook/channels": "7.4.2", - "@types/babel__core": "^7.0.0", - "@types/express": "^4.7.0", - "file-system-cache": "2.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addons/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/addons/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/addons/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@storybook/api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.6.10.tgz", - "integrity": "sha512-28qfs7sdzcnKfGBVnWuKgqAPe++NLrMjL6cp/rxuRlAtGyl0Q3eC9jj1ggOm4SFVTu6NoFzTuTXFUEbskZVk1Q==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.6.17.tgz", + "integrity": "sha512-l92PI+5XL4zB/o4IBWFCKQWTXvPg9hR45DCJqlPHrLZStiR6Xj1mbrtOjUlgIOH+nYb/SZFZqO53hhrs7X4Nvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/client-logger": "7.6.17", + "@storybook/manager-api": "7.6.17" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/api/node_modules/@storybook/manager-api": { + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.17.tgz", + "integrity": "sha512-IJIV1Yc6yw1dhCY4tReHCfBnUKDqEBnMyHp3mbXpsaHxnxJZrXO45WjRAZIKlQKhl/Ge1CrnznmHRCmYgqmrWg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/manager-api": "7.6.10" + "@storybook/channels": "7.6.17", + "@storybook/client-logger": "7.6.17", + "@storybook/core-events": "7.6.17", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/router": "7.6.17", + "@storybook/theming": "7.6.17", + "@storybook/types": "7.6.17", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "store2": "^2.14.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/api/node_modules/@storybook/router": { + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.17.tgz", + "integrity": "sha512-GnyC0j6Wi5hT4qRhSyT8NPtJfGmf82uZw97LQRWeyYu5gWEshUdM7aj40XlNiScd5cZDp0owO1idduVF2k2l2A==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.17", + "memoizerific": "^1.11.3", + "qs": "^6.10.0" }, "funding": { "type": "opencollective", @@ -5348,27 +5348,28 @@ } }, "node_modules/@storybook/blocks": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.6.10.tgz", - "integrity": "sha512-oSIukGC3yuF8pojABC/HLu5tv2axZvf60TaUs8eDg7+NiiKhzYSPoMQxs5uMrKngl+EJDB92ESgWT9vvsfvIPg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.1.3.tgz", + "integrity": "sha512-Ul8rsUcgsnizsYuWVgoybP4pGeqq5FV0jcwA00muXWs3ubPYKrKrhLhfjxkb8gi+7YikpbinPKWmlrQK1Fn3MQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/components": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", - "@storybook/docs-tools": "7.6.10", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/components": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/docs-tools": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/icons": "^1.2.5", + "@storybook/manager-api": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/theming": "8.1.3", + "@storybook/types": "8.1.3", "@types/lodash": "^4.14.167", "color-convert": "^2.0.1", "dequal": "^2.0.2", "lodash": "^4.17.21", - "markdown-to-jsx": "^7.1.8", + "markdown-to-jsx": "7.3.2", "memoizerific": "^1.11.3", "polished": "^4.2.2", "react-colorful": "^5.1.2", @@ -5382,28 +5383,106 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/blocks/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/blocks/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/blocks/node_modules/@storybook/components": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.1.3.tgz", + "integrity": "sha512-g9HB3CZvhDWoh1UJ4FiRRHDgZtKmh8H38zCK9xzyySxD9V7f9BobBChb3Xqlou3YCk5MqlGqudIg+xtHqNBPrg==", + "dev": true, + "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-slot": "^1.0.2", + "@storybook/client-logger": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@storybook/theming": "8.1.3", + "@storybook/types": "8.1.3", + "memoizerific": "^1.11.3", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/blocks/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/blocks/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -5412,25 +5491,66 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/blocks/node_modules/@storybook/theming": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.1.3.tgz", + "integrity": "sha512-BXtD5pna4eAAxNbzZUijP6W25IFVhvANG5P96xYM+OH+5OMSdLpDANnG2qWcZumwX5JFd74KqOIuV8yIO0AYXQ==", + "dev": true, + "dependencies": { + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@storybook/client-logger": "8.1.3", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/blocks/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/builder-manager": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.10.tgz", - "integrity": "sha512-f+YrjZwohGzvfDtH8BHzqM3xW0p4vjjg9u7uzRorqUiNIAAKHpfNrZ/WvwPlPYmrpAHt4xX/nXRJae4rFSygPw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-8.1.3.tgz", + "integrity": "sha512-VIYgF6PreiteJMGlz716P27yyL/JF1dR7M2htVJij5IP2X6HUgyzFXScElKljX9fETq7vig+UZWksZ2M2Q9dYg==", "dev": true, "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.6.10", - "@storybook/manager": "7.6.10", - "@storybook/node-logger": "7.6.10", + "@storybook/core-common": "8.1.3", + "@storybook/manager": "8.1.3", + "@storybook/node-logger": "8.1.3", "@types/ejs": "^3.1.1", - "@types/find-cache-dir": "^3.2.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", - "ejs": "^3.1.8", - "esbuild": "^0.18.0", + "ejs": "^3.1.10", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", - "find-cache-dir": "^3.0.0", "fs-extra": "^11.1.0", "process": "^0.11.10", "util": "^0.12.4" @@ -5440,6 +5560,412 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-manager/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, "node_modules/@storybook/builder-manager/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -5455,27 +5981,28 @@ } }, "node_modules/@storybook/builder-vite": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-7.6.10.tgz", - "integrity": "sha512-qxe19axiNJVdIKj943e1ucAmADwU42fTGgMSdBzzrvfH3pSOmx2057aIxRzd8YtBRnj327eeqpgCHYIDTunMYQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-8.1.3.tgz", + "integrity": "sha512-REfjbsBCMgYLszeyOwmDsI9o0vJSeZ3xnCPBp4DphEX4i889t+jTTxavB4yiDSaK+ALqE8Hk3wfn6AQyIWEuCg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/csf-plugin": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-common": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf-plugin": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/preview": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/types": "8.1.3", "@types/find-cache-dir": "^3.2.1", "browser-assert": "^1.2.1", - "es-module-lexer": "^0.9.3", + "es-module-lexer": "^1.5.0", "express": "^4.17.3", "find-cache-dir": "^3.0.0", "fs-extra": "^11.1.0", "magic-string": "^0.30.0", - "rollup": "^2.25.0 || ^3.3.0" + "ts-dedent": "^2.0.0" }, "funding": { "type": "opencollective", @@ -5484,7 +6011,7 @@ "peerDependencies": { "@preact/preset-vite": "*", "typescript": ">= 4.3.x", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0", + "vite": "^4.0.0 || ^5.0.0", "vite-plugin-glimmerx": "*" }, "peerDependenciesMeta": { @@ -5499,24 +6026,68 @@ } } }, - "node_modules/@storybook/builder-vite/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "node_modules/@storybook/builder-vite/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/preview-api": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -5525,6 +6096,21 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/builder-vite/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -5539,30 +6125,15 @@ "node": ">=14.14" } }, - "node_modules/@storybook/builder-vite/node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/@storybook/channels": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.10.tgz", - "integrity": "sha512-ITCLhFuDBKgxetuKnWwYqMUWlU7zsfH3gEKZltTb+9/2OAWR7ez0iqU7H6bXP1ridm0DCKkt2UMWj2mmr9iQqg==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.17.tgz", + "integrity": "sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==", "dev": true, + "license": "MIT", "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/client-logger": "7.6.17", + "@storybook/core-events": "7.6.17", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -5574,23 +6145,22 @@ } }, "node_modules/@storybook/cli": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.10.tgz", - "integrity": "sha512-pK1MEseMm73OMO2OVoSz79QWX8ymxgIGM8IeZTCo9gImiVRChMNDFYcv8yPWkjuyesY8c15CoO48aR7pdA1OjQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-8.1.3.tgz", + "integrity": "sha512-eqzjy7YOIF0WkeUPT5Mv+WKibk3z+IfP0voTKIWzYKAqZ8sD36NQV/lE7bHy0JAPw+rfw1Fq0gMOiFVcx3ZaUQ==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", "@ndelangen/get-tarball": "^3.0.7", - "@storybook/codemod": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/core-server": "7.6.10", - "@storybook/csf-tools": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/telemetry": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/codemod": "8.1.3", + "@storybook/core-common": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/core-server": "8.1.3", + "@storybook/csf-tools": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/telemetry": "8.1.3", + "@storybook/types": "8.1.3", "@types/semver": "^7.3.4", "@yarnpkg/fslib": "2.10.3", "@yarnpkg/libzip": "2.3.0", @@ -5600,25 +6170,22 @@ "detect-indent": "^6.1.0", "envinfo": "^7.7.3", "execa": "^5.0.0", - "express": "^4.17.3", "find-up": "^5.0.0", "fs-extra": "^11.1.0", "get-npm-tarball-url": "^2.0.3", - "get-port": "^5.1.1", "giget": "^1.0.0", - "globby": "^11.0.2", + "globby": "^14.0.1", "jscodeshift": "^0.15.1", "leven": "^3.1.0", "ora": "^5.4.1", - "prettier": "^2.8.0", + "prettier": "^3.1.1", "prompts": "^2.4.0", - "puppeteer-core": "^2.1.1", "read-pkg-up": "^7.0.1", "semver": "^7.3.7", "strip-json-comments": "^3.0.1", "tempy": "^1.0.1", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" }, "bin": { "getstorybook": "bin/index.js", @@ -5629,6 +6196,65 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/cli/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/cli/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5683,6 +6309,26 @@ "node": ">=14.14" } }, + "node_modules/@storybook/cli/node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/cli/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5692,41 +6338,23 @@ "node": ">=8" } }, - "node_modules/@storybook/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@storybook/cli/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/cli/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@storybook/cli/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -5734,6 +6362,18 @@ "node": ">=10" } }, + "node_modules/@storybook/cli/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/cli/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5746,17 +6386,12 @@ "node": ">=8" } }, - "node_modules/@storybook/cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@storybook/client-logger": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.10.tgz", - "integrity": "sha512-U7bbpu21ntgePMz/mKM18qvCSWCUGCUlYru8mgVlXLCKqFqfTeP887+CsPEQf29aoE3cLgDrxqbRJ1wxX9kL9A==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.17.tgz", + "integrity": "sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==", "dev": true, + "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0" }, @@ -5766,59 +6401,150 @@ } }, "node_modules/@storybook/codemod": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.10.tgz", - "integrity": "sha512-pzFR0nocBb94vN9QCJLC3C3dP734ZigqyPmd0ZCDj9Xce2ytfHK3v1lKB6TZWzKAZT8zztauECYxrbo4LVuagw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.1.3.tgz", + "integrity": "sha512-U21HQICKKm/xsfLKEODDphJJiBkzq5wFZzKN2DyMPd3vOfLpCWcaPsO9Pi5IX1cekyCz2o+phYt2r9aSRQUbOg==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/types": "^7.23.0", - "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/types": "7.6.10", + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/csf": "^0.1.7", + "@storybook/csf-tools": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/types": "8.1.3", "@types/cross-spawn": "^6.0.2", "cross-spawn": "^7.0.3", - "globby": "^11.0.2", + "globby": "^14.0.1", "jscodeshift": "^0.15.1", "lodash": "^4.17.21", - "prettier": "^2.8.0", - "recast": "^0.23.1" + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/codemod/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/@storybook/codemod/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@storybook/components": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.10.tgz", - "integrity": "sha512-H5hF8pxwtbt0LxV24KMMsPlbYG9Oiui3ObvAQkvGu6q62EYxRPeNSrq3GBI5XEbI33OJY9bT24cVaZx18dXqwQ==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.17.tgz", + "integrity": "sha512-lbh7GynMidA+CZcJnstVku6Nhs+YkqjYaZ+mKPugvlVhGVWv0DaaeQFVuZ8cJtUGJ/5FFU4Y+n+gylYUHkGBMA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@radix-ui/react-select": "^1.2.2", "@radix-ui/react-toolbar": "^1.0.4", - "@storybook/client-logger": "7.6.10", + "@storybook/client-logger": "7.6.17", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/theming": "7.6.17", + "@storybook/types": "7.6.17", "memoizerific": "^1.11.3", "use-resize-observer": "^9.1.0", "util-deprecate": "^1.0.2" @@ -5832,62 +6558,23 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@storybook/core-client": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.10.tgz", - "integrity": "sha512-DjnzSzSNDmZyxyg6TxugzWQwOsW+n/iWVv6sHNEvEd5STr0mjuJjIEELmv58LIr5Lsre5+LEddqHsyuLyt8ubg==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/preview-api": "7.6.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", - "dev": true, - "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", - "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", - "@types/qs": "^6.9.5", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, "node_modules/@storybook/core-common": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.10.tgz", - "integrity": "sha512-K3YWqjCKMnpvYsWNjOciwTH6zWbuuZzmOiipziZaVJ+sB1XYmH52Y3WGEm07TZI8AYK9DRgwA13dR/7W0nw72Q==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-8.1.3.tgz", + "integrity": "sha512-VLG2Kg6oX0msq/Gjo+Pveqg7oLnJBClzms43/nwh6oxjJ/TFehRi3DyLjLqL+Nj726LI5lQetFZZyrsHudVskg==", "dev": true, "dependencies": { - "@storybook/core-events": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/types": "7.6.10", - "@types/find-cache-dir": "^3.2.1", - "@types/node": "^18.0.0", - "@types/node-fetch": "^2.6.4", - "@types/pretty-hrtime": "^1.0.0", + "@storybook/core-events": "8.1.3", + "@storybook/csf-tools": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/types": "8.1.3", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", - "esbuild": "^0.18.0", + "cross-spawn": "^7.0.3", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0", "esbuild-register": "^3.5.0", + "execa": "^5.0.0", "file-system-cache": "2.3.0", "find-cache-dir": "^3.0.0", "find-up": "^5.0.0", @@ -5898,8 +6585,433 @@ "node-fetch": "^2.0.0", "picomatch": "^2.3.0", "pkg-dir": "^5.0.0", + "prettier-fallback": "npm:prettier@^3", "pretty-hrtime": "^1.0.3", "resolve-from": "^5.0.0", + "semver": "^7.3.7", + "tempy": "^1.0.1", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core-common/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-common/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-common/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", "ts-dedent": "^2.0.0" }, "funding": { @@ -5907,13 +7019,19 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/core-common/node_modules/@types/node": { - "version": "18.19.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.8.tgz", - "integrity": "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==", + "node_modules/@storybook/core-common/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/core-common/node_modules/ansi-styles": { @@ -5931,15 +7049,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@storybook/core-common/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@storybook/core-common/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5956,6 +7065,44 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@storybook/core-common/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, "node_modules/@storybook/core-common/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -5970,28 +7117,6 @@ "node": ">=14.14" } }, - "node_modules/@storybook/core-common/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@storybook/core-common/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6001,19 +7126,16 @@ "node": ">=8" } }, - "node_modules/@storybook/core-common/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@storybook/core-common/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, "node_modules/@storybook/core-common/node_modules/supports-color": { @@ -6029,10 +7151,11 @@ } }, "node_modules/@storybook/core-events": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.10.tgz", - "integrity": "sha512-yccDH67KoROrdZbRKwxgTswFMAco5nlCyxszCDASCLygGSV2Q2e+YuywrhchQl3U6joiWi3Ps1qWu56NeNafag==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.17.tgz", + "integrity": "sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==", "dev": true, + "license": "MIT", "dependencies": { "ts-dedent": "^2.0.0" }, @@ -6042,27 +7165,31 @@ } }, "node_modules/@storybook/core-server": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.10.tgz", - "integrity": "sha512-2icnqJkn3vwq0eJPP0rNaHd7IOvxYf5q4lSVl2AWTxo/Ae19KhokI6j/2vvS2XQJMGQszwshlIwrZUNsj5p0yw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-8.1.3.tgz", + "integrity": "sha512-bOHbLI5atDFBOsFc5M0V0ikURVw+Kx/jRXGO5dnc6kr5SwW+ZfWooy1hiFKHRnI8hmVpGXcS6YqTHkUbcrAWgA==", "dev": true, "dependencies": { "@aw-web-design/x-default-browser": "1.4.126", + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.6.10", - "@storybook/channels": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.10", - "@storybook/docs-mdx": "^0.1.0", + "@storybook/builder-manager": "8.1.3", + "@storybook/channels": "8.1.3", + "@storybook/core-common": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/csf-tools": "8.1.3", + "@storybook/docs-mdx": "3.1.0-next.0", "@storybook/global": "^5.0.0", - "@storybook/manager": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/telemetry": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/manager": "8.1.3", + "@storybook/manager-api": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/telemetry": "8.1.3", + "@storybook/types": "8.1.3", "@types/detect-port": "^1.3.0", + "@types/diff": "^5.0.9", "@types/node": "^18.0.0", "@types/pretty-hrtime": "^1.0.0", "@types/semver": "^7.3.4", @@ -6071,10 +7198,11 @@ "cli-table3": "^0.6.1", "compression": "^1.7.4", "detect-port": "^1.3.0", + "diff": "^5.2.0", "express": "^4.17.3", "fs-extra": "^11.1.0", - "globby": "^11.0.2", - "ip": "^2.0.0", + "globby": "^14.0.1", + "ip": "^2.0.1", "lodash": "^4.17.21", "open": "^8.4.0", "pretty-hrtime": "^1.0.3", @@ -6094,24 +7222,68 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/core-server/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "node_modules/@storybook/core-server/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/preview-api": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -6120,10 +7292,25 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/core-server/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/core-server/node_modules/@types/node": { - "version": "18.19.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.8.tgz", - "integrity": "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -6174,6 +7361,26 @@ "node": ">=14.14" } }, + "node_modules/@storybook/core-server/node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/core-server/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6183,26 +7390,23 @@ "node": ">=8" } }, - "node_modules/@storybook/core-server/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@storybook/core-server/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@storybook/core-server/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -6210,6 +7414,18 @@ "node": ">=10" } }, + "node_modules/@storybook/core-server/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/core-server/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6222,28 +7438,22 @@ "node": ">=8" } }, - "node_modules/@storybook/core-server/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@storybook/csf": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.2.tgz", - "integrity": "sha512-ePrvE/pS1vsKR9Xr+o+YwdqNgHUyXvg+1Xjx0h9LrVx7Zq4zNe06pd63F5EvzTbCbJsHj7GHr9tkiaqm7U8WRA==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.7.tgz", + "integrity": "sha512-53JeLZBibjQxi0Ep+/AJTfxlofJlxy1jXcSKENlnKxHjWEYyHQCumMP5yTFjf7vhNnMjEpV3zx6t23ssFiGRyw==", "dev": true, "dependencies": { "type-fest": "^2.19.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.6.10.tgz", - "integrity": "sha512-Sc+zZg/BnPH2X28tthNaQBnDiFfO0QmfjVoOx0fGYM9SvY3P5ehzWwp5hMRBim6a/twOTzePADtqYL+t6GMqqg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.1.3.tgz", + "integrity": "sha512-ONKhnz2j3zSa2RseBWypabTniRcs77ZWBdTrxnBqQap55tRMOAS/uCG+bgGgWlzwDskX35Kmd7XGkVOEngWSDQ==", "dev": true, "dependencies": { - "@storybook/csf-tools": "7.6.10", + "@storybook/csf-tools": "8.1.3", "unplugin": "^1.3.1" }, "funding": { @@ -6252,19 +7462,19 @@ } }, "node_modules/@storybook/csf-tools": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.10.tgz", - "integrity": "sha512-TnDNAwIALcN6SA4l00Cb67G02XMOrYU38bIpFJk5VMDX2dvgPjUtJNBuLmEbybGcOt7nPyyFIHzKcY5FCVGoWA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-8.1.3.tgz", + "integrity": "sha512-22h6Uv7w29v8HjoFsJvAkBci9POVH0aQhlfZ4NNYkiMbgD4X4HWeD2wqob6fTKpVWP3tDaNS9FfCWHxQXFE+ag==", "dev": true, "dependencies": { - "@babel/generator": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", - "@storybook/csf": "^0.1.2", - "@storybook/types": "7.6.10", + "@babel/generator": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "@storybook/csf": "^0.1.7", + "@storybook/types": "8.1.3", "fs-extra": "^11.1.0", - "recast": "^0.23.1", + "recast": "^0.23.5", "ts-dedent": "^2.0.0" }, "funding": { @@ -6272,6 +7482,65 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/csf-tools/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/csf-tools/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/csf-tools/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/csf-tools/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/csf-tools/node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -6287,20 +7556,21 @@ } }, "node_modules/@storybook/docs-mdx": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", - "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", + "version": "3.1.0-next.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-3.1.0-next.0.tgz", + "integrity": "sha512-t4syFIeSyufieNovZbLruPt2DmRKpbwL4fERCZ1MifWDRIORCKLc4NCEHy+IqvIqd71/SJV2k4B51nF7vlJfmQ==", "dev": true }, "node_modules/@storybook/docs-tools": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.10.tgz", - "integrity": "sha512-UgbikducoXzqQHf2TozO0f2rshaeBNnShVbL5Ai4oW7pDymBmrfzdjGbF/milO7yxNKcoIByeoNmu384eBamgQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-8.1.3.tgz", + "integrity": "sha512-EQIgzO5KdvEck0/20lR/znq1xCC7O1HvKd+yIkZ4bEGn2XnqWk8rmReKSOMI476rb3sn1CMIntT2BRsBUOfTOw==", "dev": true, "dependencies": { - "@storybook/core-common": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/core-common": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/types": "8.1.3", "@types/doctrine": "^0.0.3", "assert": "^2.1.0", "doctrine": "^3.0.0", @@ -6311,24 +7581,68 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/docs-tools/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "node_modules/@storybook/docs-tools/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/docs-tools/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/docs-tools/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/docs-tools/node_modules/@storybook/preview-api": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -6337,16 +7651,45 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/docs-tools/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/global": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/icons": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", + "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } }, "node_modules/@storybook/manager": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.10.tgz", - "integrity": "sha512-Co3sLCbNYY6O4iH2ggmRDLCPWLj03JE5s/DOG8OVoXc6vBwTc/Qgiyrsxxp6BHQnPpM0mxL6aKAxE3UjsW/Nog==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-8.1.3.tgz", + "integrity": "sha512-hmfQJJNLSqlM+jfcCXo5wnhUIugTsCxv6a+2UnRAt2AnF6J746QaV0npMThw1QG/7fi/ofaRY8hPGxgCN9uHRA==", "dev": true, "funding": { "type": "opencollective", @@ -6354,19 +7697,20 @@ } }, "node_modules/@storybook/manager-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.10.tgz", - "integrity": "sha512-8eGVpRlpunuFScDtc7nxpPJf/4kJBAAZlNdlhmX09j8M3voX6GpcxabBamSEX5pXZqhwxQCshD4IbqBmjvadlw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.1.3.tgz", + "integrity": "sha512-2OpbHK0a3Tak+Wba0ZW/b17C62hdXMFa++rzGT7KzFcVmzg8Nx464wVx2hlrNxjlfBJkHoT723irAiAwmIl2Pg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", - "@storybook/router": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/icons": "^1.2.5", + "@storybook/router": "8.1.3", + "@storybook/theming": "8.1.3", + "@storybook/types": "8.1.3", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", @@ -6379,26 +7723,97 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/mdx2-csf": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", - "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", - "dev": true - }, - "node_modules/@storybook/node-logger": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.10.tgz", - "integrity": "sha512-ZBuqrv4bjJzKXyfRGFkVIi+z6ekn6rOPoQao4KmsfLNQAUUsEdR8Baw/zMnnU417zw5dSEaZdpuwx75SCQAeOA==", + "node_modules/@storybook/manager-api/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/postinstall": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.6.10.tgz", - "integrity": "sha512-SMdXtednPCy3+SRJ7oN1OPN1oVFhj3ih+ChOEX8/kZ5J3nfmV3wLPtsZvFGUCf0KWQEP1xL+1Urv48mzMKcV/w==", + "node_modules/@storybook/manager-api/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/manager-api/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/manager-api/node_modules/@storybook/theming": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.1.3.tgz", + "integrity": "sha512-BXtD5pna4eAAxNbzZUijP6W25IFVhvANG5P96xYM+OH+5OMSdLpDANnG2qWcZumwX5JFd74KqOIuV8yIO0AYXQ==", + "dev": true, + "dependencies": { + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@storybook/client-logger": "8.1.3", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-api/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/node-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-8.1.3.tgz", + "integrity": "sha512-MpQ7Zl5n58zbFr1Yu3qgInGENoScEnfqsCxipMhj57b5SWJJ7NoOdSAWznjFFffo8NoaqxldHscuaQfzPBN9hA==", "dev": true, "funding": { "type": "opencollective", @@ -6406,9 +7821,9 @@ } }, "node_modules/@storybook/preview": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.6.10.tgz", - "integrity": "sha512-F07BzVXTD3byq+KTWtvsw3pUu3fQbyiBNLFr2CnfU4XSdLKja5lDt8VqDQq70TayVQOf5qfUTzRd4M6pQkjw1w==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-8.1.3.tgz", + "integrity": "sha512-04Aet1jrsSMuJ/pm21GJBmSAaJdPhy/fhir50jKiQTwBMgM19G0HQ1IUMHgcy85fh/DWg1/h4pxVodvWvdIZfQ==", "dev": true, "funding": { "type": "opencollective", @@ -6416,17 +7831,19 @@ } }, "node_modules/@storybook/preview-api": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.4.2.tgz", - "integrity": "sha512-ihTHRYzI/sI6bD215aYppiWF+1u38TrlsNjFYJ/Grftbti5d40g5wCwvAXK41SxJNYpk6CRtfvNKOwbEAC33gg==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.17.tgz", + "integrity": "sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@storybook/channels": "7.4.2", - "@storybook/client-logger": "7.4.2", - "@storybook/core-events": "7.4.2", - "@storybook/csf": "^0.1.0", + "@storybook/channels": "7.6.17", + "@storybook/client-logger": "7.6.17", + "@storybook/core-events": "7.6.17", + "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.4.2", + "@storybook/types": "7.6.17", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", @@ -6441,28 +7858,39 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/preview-api/node_modules/@storybook/channels": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.4.2.tgz", - "integrity": "sha512-Q95KnV+fTGaAV3S875+d5LlGg+bdC3bUnki3engODDS4ViSRHJ1bnXnqxKmAaS3O/52geIyWWR766YvwHw3avw==", + "node_modules/@storybook/react-dom-shim": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.1.3.tgz", + "integrity": "sha512-CTyxH/ssU5KRbUwi3ws2NWEnMS6rjat0AYyhcskdPiPU59Qm24TrSpLqO+Rgzln8w7EDFsty3lLpcPNYs+BKlQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/router": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-8.1.3.tgz", + "integrity": "sha512-CVEMpRD+PDVb+oZ3Sd0SV4P9vBJhYDgYiO9Km9X1jV6iyg/CXIALlo5Rd9pT+/U8IdqI2QX3bkZBUgCFDff67w==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.4.2", - "@storybook/core-events": "7.4.2", - "@storybook/global": "^5.0.0", - "qs": "^6.10.0", - "telejson": "^7.2.0", - "tiny-invariant": "^1.3.1" + "@storybook/client-logger": "8.1.3", + "memoizerific": "^1.11.3", + "qs": "^6.10.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/preview-api/node_modules/@storybook/client-logger": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.4.2.tgz", - "integrity": "sha512-LC8tYrYSJwF4DHRdNYh6y8hSvccwUIv5/WOZKJDmKx7mcEm6HsVuUu16C9jsl7iy6IqJYxgVz1va3WS6852E+A==", + "node_modules/@storybook/router/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -6472,73 +7900,15 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/preview-api/node_modules/@storybook/core-events": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.4.2.tgz", - "integrity": "sha512-WCEBw+Ew8DrccnB0hpP9TXadreoOlMnWCyuXU2XrvmK/vde009leWQIsLs1rY+L17zDVuogBms62AxrDDJmMpw==", - "dev": true, - "dependencies": { - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/preview-api/node_modules/@storybook/types": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.4.2.tgz", - "integrity": "sha512-OOJ2TeS3Zzc6spHbdH+JXml0q4IHuYt9axmXAv1/pkhqHjA5072pyUacmlYNQeihpQOOsKLiCQUQlvtMy9fTnQ==", - "dev": true, - "dependencies": { - "@storybook/channels": "7.4.2", - "@types/babel__core": "^7.0.0", - "@types/express": "^4.7.0", - "file-system-cache": "2.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/react-dom-shim": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.10.tgz", - "integrity": "sha512-M+N/h6ximacaFdIDjMN2waNoWwApeVYTpFeoDppiFTvdBTXChyIuiPgYX9QSg7gDz92OaA52myGOot4wGvXVzg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/router": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.10.tgz", - "integrity": "sha512-G/H4Jn2+y8PDe8Zbq4DVxF/TPn0/goSItdILts39JENucHiuGBCjKjSWGBe1rkwKi1tUbB3yhxJVrLagxFEPpQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "7.6.10", - "memoizerific": "^1.11.3", - "qs": "^6.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, "node_modules/@storybook/telemetry": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.10.tgz", - "integrity": "sha512-p3mOSUtIyy2tF1z6pQXxNh1JzYFcAm97nUgkwLzF07GfEdVAPM+ftRSLFbD93zVvLEkmLTlsTiiKaDvOY/lQWg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-8.1.3.tgz", + "integrity": "sha512-edFj0AJ3DEF8Z6Ym6ue7N8U9HZ2khAfXIcpk6RDgL/8FrpAZKC96XSEBMSnem3BLHxMi2bddQH1UTU6rKXrfBA==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/csf-tools": "7.6.10", + "@storybook/client-logger": "8.1.3", + "@storybook/core-common": "8.1.3", + "@storybook/csf-tools": "8.1.3", "chalk": "^4.1.0", "detect-package-manager": "^2.0.1", "fetch-retry": "^5.0.2", @@ -6550,6 +7920,19 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/telemetry/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/telemetry/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6617,13 +8000,14 @@ } }, "node_modules/@storybook/theming": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.6.10.tgz", - "integrity": "sha512-f5tuy7yV3TOP3fIboSqpgLHy0wKayAw/M8HxX0jVET4Z4fWlFK0BiHJabQ+XEdAfQM97XhPFHB2IPbwsqhCEcQ==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.6.17.tgz", + "integrity": "sha512-ZbaBt3KAbmBtfjNqgMY7wPMBshhSJlhodyMNQypv+95xLD/R+Az6aBYbpVAOygLaUQaQk4ar7H/Ww6lFIoiFbA==", "dev": true, + "license": "MIT", "dependencies": { "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.6.10", + "@storybook/client-logger": "7.6.17", "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3" }, @@ -6637,12 +8021,13 @@ } }, "node_modules/@storybook/types": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.10.tgz", - "integrity": "sha512-hcS2HloJblaMpCAj2axgGV+53kgSRYPT0a1PG1IHsZaYQILfHSMmBqM8XzXXYTsgf9250kz3dqFX1l0n3EqMlQ==", + "version": "7.6.17", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.17.tgz", + "integrity": "sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==", "dev": true, + "license": "MIT", "dependencies": { - "@storybook/channels": "7.6.10", + "@storybook/channels": "7.6.17", "@types/babel__core": "^7.0.0", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" @@ -6653,23 +8038,22 @@ } }, "node_modules/@storybook/web-components": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-7.6.10.tgz", - "integrity": "sha512-zXRGXVu6tNhToUyz2AIx66tWgXlZ8xvrktZ3R/55cBi/N+x5jn4HLwT5FiCnEkNG6CTD8g+O97uym5+9ExxyyQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-8.1.3.tgz", + "integrity": "sha512-eYB7np3TDRtmthihjPggFkOB249CnlJt+pF7uGMkvPyT8+djU0h7iY3Fe0JOcRe/V1OIZXXUFWHxAvWs/y5nAw==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/core-client": "7.6.10", - "@storybook/docs-tools": "7.6.10", + "@storybook/client-logger": "8.1.3", + "@storybook/docs-tools": "8.1.3", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/manager-api": "8.1.3", + "@storybook/preview-api": "8.1.3", + "@storybook/types": "8.1.3", "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", @@ -6680,19 +8064,123 @@ } }, "node_modules/@storybook/web-components-vite": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-7.6.10.tgz", - "integrity": "sha512-COaUlqKX/MD1uCTOCngG2/zubS5YUdNycFtwB5OGhr37T6YRTyTjtFBZyGm8m6JUqL8ktLG44P32v0cMyu2sBw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-8.1.3.tgz", + "integrity": "sha512-KhkZtNbBNWKx+uBFgWK/rrA37dKxRFzhk+Z1bH9wZc+vf12zUOsOWjZ4ViCSJNizDg+NESgwEmuSVvFrhx6dNg==", "dev": true, "dependencies": { - "@storybook/builder-vite": "7.6.10", - "@storybook/core-server": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/web-components": "7.6.10", + "@storybook/builder-vite": "8.1.3", + "@storybook/core-server": "8.1.3", + "@storybook/node-logger": "8.1.3", + "@storybook/types": "8.1.3", + "@storybook/web-components": "8.1.3", "magic-string": "^0.30.0" }, "engines": { - "node": "^14.18 || >=16" + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components-vite/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components-vite/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components-vite/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components-vite/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components/node_modules/@storybook/channels": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.1.3.tgz", + "integrity": "sha512-iDoHFX3ty7vhSXegFRevJkQ6cV+QQ1JjDnoXK/SHeloMT26sn5gPtetn3ET9+6ZoFkU05Pf5d0DoywVOfumfcg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components/node_modules/@storybook/client-logger": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.1.3.tgz", + "integrity": "sha512-dX1jZ+HhJ8hVhAKHQ8gs/FalHjIGo5j1Xk+2UqdsGjLoBlwHIHfHzkVbzrc/gCxxXL0juisk7BzbXaz7lME0KA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/web-components/node_modules/@storybook/core-events": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.1.3.tgz", + "integrity": "sha512-eOs4HRrsEZz2FZFlMGwPuH9CGYBK8fkUS7mcHNPv8CqoHV8d3ErvDax8zA/KGRj3S6kWJ4PzI9IGuiDVvwuxhA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.7", + "ts-dedent": "^2.0.0" }, "funding": { "type": "opencollective", @@ -6700,23 +8188,23 @@ } }, "node_modules/@storybook/web-components/node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.1.3.tgz", + "integrity": "sha512-2eyNVr5wLzglE7KABdXu4nu+rPjJ8gVDP9TiovgU1MHhE5rX8qbKmJ47ymWSfJT1DMvH2dPISh4/wRK3WVNjmw==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/csf": "^0.1.2", + "@storybook/channels": "8.1.3", + "@storybook/client-logger": "8.1.3", + "@storybook/core-events": "8.1.3", + "@storybook/csf": "^0.1.7", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "@storybook/types": "8.1.3", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -6725,369 +8213,777 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/web-components/node_modules/@storybook/types": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.1.3.tgz", + "integrity": "sha512-2uUC1z7heMceRPHQ4KCcZwwKjtW2YiToUODsEw0YOq6NC/Q9elZta1FABSG0Bq7XM08EiAgjyc7P9CZPJ2QxUQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.1.3", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@swagger-api/apidom-ast": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.76.2.tgz", - "integrity": "sha512-yLSeI3KtfpR7tI/misqTeasFonssj9GGhCOJfSHBuRAZkrPCJf0eU8vh3pL7YPa8lqFWcPT+z/arZoMcC9VLnQ==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.96.0.tgz", + "integrity": "sha512-JaXro7IH2yPHomA/t6R1wj551GmKl/qjRkQ1729l7umssmubO2yprAbH8GEF5SqtTEicihXF2DlwgUMs/+YyNg==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-error": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-error": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", "unraw": "^3.0.0" } }, + "node_modules/@swagger-api/apidom-ast/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-core": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.76.2.tgz", - "integrity": "sha512-366dJJM7DFONlO3nUQfQRMJpJzZjPpWZldbHJZCcvy+aCyrNYI3Waauas7fm29UXRliPirGrd9e/ZsnW3Jimag==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.96.0.tgz", + "integrity": "sha512-FOZqbH/2H5f7UiTvN2b7O5r0MCCUiICimhNVi5bbaf3ATWFDpL7AKtGFd3EmW8Er8ajpcxI13iZpoBFPtUtnsQ==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@types/ramda": "~0.29.3", + "@swagger-api/apidom-ast": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@types/ramda": "~0.29.6", "minim": "~0.23.8", - "ramda": "~0.29.0", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", "short-unique-id": "^5.0.2", "stampit": "^4.3.2" } }, + "node_modules/@swagger-api/apidom-core/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-error": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.76.2.tgz", - "integrity": "sha512-QxoWL+qGzwftqXSJaYLZ1Nrdtro+U1zX5Q4OLK+Ggg8Hi6Kn1SGXcHhn4JZ9J1rwrP85XCabilL3z9mhdebqWg==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.96.0.tgz", + "integrity": "sha512-dDaGOUVx5pp/mm0c6Y5aBIXVMvVdL3jP6SnnPCGXq20AqkDNDyihJU28VsBrPjl05/tMV4IAHW26qQAMztvahA==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" + "@babel/runtime-corejs3": "^7.20.7" } }, "node_modules/@swagger-api/apidom-json-pointer": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.76.2.tgz", - "integrity": "sha512-2XCgA4bn8vB1VMDbSiP+6SHUTiBxx1EVLW2pgqFolhLPMdiI/QBVmoW+jEkvTPo4d5gwj/vP5WDs5QnnC9VwEA==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.96.0.tgz", + "integrity": "sha512-AesKhx3PhicgrIbal4X5MLgX5s/Lom50AlYy9r4sFAu8ke3H+IIvGoJ5so2X6UcJJ17CURiEks+oAEM2pMnBUA==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-json-pointer/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-ns-api-design-systems": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.76.2.tgz", - "integrity": "sha512-ct83R5Pvc08jeOuGShO4N0ty7VO8f46WedTDCbzT4edMRhd9Xdr5UFxkwWDuliy4uLzl9ZayHygSxfnyZKQb8g==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.96.0.tgz", + "integrity": "sha512-TTZAIiOAZz6NXtGiTQ/XIHE6VuRlqI25ehzM3GDXur+r74/rPmzGH9E0CEzfj+bprd2QXCrus50pqwyGMPJd9Q==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-api-design-systems/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" } }, "node_modules/@swagger-api/apidom-ns-asyncapi-2": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.76.2.tgz", - "integrity": "sha512-ffV2AhF7jTBbYl2vX0nYSDufs70CmC/kNMWHkgwR2Vq86lgadUc6S/NK/djpWY8+oAU3EYmHwTqu07hpSOUb4A==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.96.0.tgz", + "integrity": "sha512-I+1Bc+U0U/yaYEBNmEe58tr/ca7HMJiN2DHXFKcuZrub27Anwp389LxrknkeMoeb1PBTcJqRis4fVXiQF06EJQ==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-json-schema-draft-7": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-json-schema-draft-7": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-asyncapi-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.76.2.tgz", - "integrity": "sha512-0Y32CQE6tIt4IPsoCzWAUskZSyGkfw87IIsH5Bcm3D1qIlAhPAokQbe1212MmZoLVUvqrXDqZHXnOxxMaHZvYw==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.96.0.tgz", + "integrity": "sha512-bEQI/u15L6NLF7IW3DHEstJW64f8DSYqDR4vHdgrJ/GyA/c+N4K1St1LhKfA+WuBs7DX3JNKNZ3APAkq5gqWTA==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.76.2", - "@swagger-api/apidom-core": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-ast": "^0.96.0", + "@swagger-api/apidom-core": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", "stampit": "^4.3.2" } }, + "node_modules/@swagger-api/apidom-ns-json-schema-draft-4/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.76.2.tgz", - "integrity": "sha512-i6nZtj3ie6SP1LhRtBeZNJuBppWkuC/+AsVfUzXkH5pM+3B7Puklc77hHdLtmvUTpd/iRBdlfsklvBVXJYPtUA==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.96.0.tgz", + "integrity": "sha512-F6AsqMQjQd9NlR8AJd3fpsV1nFPAGgsw9g7DyY8uhbj77wUfoYhQTiTexBnq4GlhbXref4SQjnGZvi6AWwV3vw==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", "stampit": "^4.3.2" } }, + "node_modules/@swagger-api/apidom-ns-json-schema-draft-6/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.76.2.tgz", - "integrity": "sha512-Klyfi/1XkJVUZa1nJP87HPMjklmB3IxE+TSD27aZIEi7GKASu96euan0gflZaegexUBA9hsAngk98USbdpHpgQ==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.96.0.tgz", + "integrity": "sha512-9yTNy4zDpoaTuCYsmliHh12ScyXgLyUuegXRVEE0ca0G0MqkVWIN5Si3EYnGIK5THGbz3c+NP1caHI8sl0+QMw==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@swagger-api/apidom-ns-json-schema-draft-6": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-ns-json-schema-draft-6": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", "stampit": "^4.3.2" } }, + "node_modules/@swagger-api/apidom-ns-json-schema-draft-7/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-ns-openapi-2": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.96.0.tgz", + "integrity": "sha512-Q85DT8OMkvP9cm8+CmHHZxBS1+uu/GJVZ0ypwW60aDysUkBNcbcEexCRvlGxF5QBr7sx2sQS+86qPusU4oMFmA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.1.1", + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-openapi-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-ns-openapi-3-0": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.76.2.tgz", - "integrity": "sha512-tV7dfbAZjX4HHul6JzmWsipMIVHCX5fAsBwLTltq8qmF9X9m6kZwg7fb4pD+cGK2KVlZl/ucDDDIQLDRWpOAog==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.96.0.tgz", + "integrity": "sha512-xiO+u/VtKRNi/KD8rkqcezUXY6JxVcPEpEIiTWkjy6LwamNu01futS/bsn6CnTN5ZbGO+Ikm5GQyYtlruy5fTw==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-openapi-3-0/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" } }, "node_modules/@swagger-api/apidom-ns-openapi-3-1": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.76.2.tgz", - "integrity": "sha512-Mb9VhVacoWvQcBqxO4j0eweyM6PGupAOt7XcOL5CzID0dOU+P4BbAv6kHD++0bTqRgXk1O31HkS/yPJmPaTCrw==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.96.0.tgz", + "integrity": "sha512-B9fviQaokRZhds3+rSYMHYI8pen/MAShRbfRlQRLvDEXnOy+Fo7cV8lbBbaG35ldnLPG2rHl0LS0qhyJd8z3Eg==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.76.2", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-ast": "^0.96.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-openapi-3-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-ns-workflows-1": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-0.96.0.tgz", + "integrity": "sha512-PaVIcCFuZfVcVOsuk2Vk9p1EmMgkx5OYXGG0QlsJI94OiJiLPxJBUYCELYtKFwbjCPKqbe2T7uyyVEEAo8OyJQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.1.1", + "ts-mixer": "^6.0.3" + } + }, + "node_modules/@swagger-api/apidom-ns-workflows-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" } }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.76.2.tgz", - "integrity": "sha512-mJ4HLVIR9YHgWu0SiHykFQ9Sz1f3eV5Wqhrff8sH2Qll+4QSSdOOs0tW4Gp56F0HIcrU66uvrrTy1tpkO943aw==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.96.0.tgz", + "integrity": "sha512-nmOc5f37Jcu8W1KNUnWPEUPHBhlInlxA+gzCcKG/3kyedKm+Oh8x4fDqhaW/MXUiWuI6K0QZ8MTxaYUqez2ztA==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-api-design-systems": "^0.76.2", - "@swagger-api/apidom-parser-adapter-json": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-api-design-systems": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.76.2.tgz", - "integrity": "sha512-ot0F8Pw9/oWce6daDK+3srhNad/Iva/OlkVtN0S9cR58Zcn8p1F3s6RcN7ZG97i8EdBuyQj6Bm0jzXnOX+lvtQ==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.96.0.tgz", + "integrity": "sha512-2Mv320Cmhs8u79GykuxbwhRUgy1MoOcEmeyLjHPftpEZI7BrsSQn9CbN/J/5tga5Z8Un/KgU9YffN/XSvLhOKg==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-api-design-systems": "^0.76.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-api-design-systems": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.76.2.tgz", - "integrity": "sha512-FK06pb4w5E8RQ65Nh1FHHM8aWzPL7fHr2HeuXZkbSeKu4j0xyzwYkxZVGwZJOT6YPJR0Yrkb/2rD89CNXsLctA==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.96.0.tgz", + "integrity": "sha512-ABfbr8ho6s4Edu6P1kNF8WTIPSlzGQ45T36Vg/AvPpmMoKOjZPeUKqs10Nw7Eoe91LJvdm8PlofNG19o8aRFsA==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.76.2", - "@swagger-api/apidom-parser-adapter-json": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.76.2.tgz", - "integrity": "sha512-7TGhZgHZ9nmBJnFA7YhDWbNDbKoUOGVkBqx563ExHr2FewaohiQ/wagXAhKZzOK+HS+KHvob09uROtqOWGdIew==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.96.0.tgz", + "integrity": "sha512-6xJedcLukkO/ZvUZnMPxZ5t/pcIjVOSzzysTNNcDKEsI4oNfoV2YjT315m+fUM/79W6e+aA9IlKygzj0s6ysVg==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.76.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-json": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.76.2.tgz", - "integrity": "sha512-vbH7EcldZ/gSK9FnGUW1cpibM5+hiJPQcoyLmzLZe8YBxX73qzd2WAd77v+uI56eO9Z0G4KMCRCF9PDZT/tz5Q==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.96.0.tgz", + "integrity": "sha512-k/XdEKP2+LJupwLvKtxkM6Ol7pYei3XinvhTsU+F1u8VQUpYTOHMVQ3vC5p/wtISOq+7Q0zHR0QANHVMbOudQg==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.76.2", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-ast": "^0.96.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", "tree-sitter": "=0.20.4", - "tree-sitter-json": "=0.20.0", + "tree-sitter-json": "=0.20.2", "web-tree-sitter": "=0.20.3" } }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.76.2.tgz", - "integrity": "sha512-Kqcq5QUgz1TcCuPaL+zU+wmdAEo7YM0LR5jyWQo3FAT3BhAsmeVv2wRZMiz9RMDrPyxzHzbJhjMZxCqL8r2G0g==", + "node_modules/@swagger-api/apidom-parser-adapter-json/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.96.0.tgz", + "integrity": "sha512-bReqp5ncvgxD+nkX8cj7ILE0Xp3Vzocei96CMtwn1OU6FGSIu8IfjfJ0qSDavSJMxxhMXuCW85U+oZ+j9BzMLQ==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.76.2", - "@swagger-api/apidom-parser-adapter-json": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.96.0.tgz", + "integrity": "sha512-T07rPrjUBCCFuh3Xr7CGu+pjphokioMaxuAvQqtn7XgRCBbL76XFONlS1OSl3WATtrW7Sq+yxN5R3/f5C9evgA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.0.0" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.76.2.tgz", - "integrity": "sha512-kfZ4BBxww5afiIIeFT6l0/Kuob72dnYAP+Qnmp2zQB3GQUTilKqv+ddj4blCF19n8RGNERVv2RDHLTZhjg+1AA==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.96.0.tgz", + "integrity": "sha512-ovbpHrFuN6l2zJdUOmjF5y6wIZB13SanhvQpaOIALW8J9KYxkjhQH+h3lceYKUdTWfrdPkmmV150DAlcOy2alQ==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.76.2", - "@swagger-api/apidom-parser-adapter-json": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.96.0.tgz", + "integrity": "sha512-wJmq0/jQVzjxMqJMGWL8u/HyeVaaa7ImQcGe4z+eOR2vhLji0qbNu3S1WSP+n5OAhotHWAMfhHHZkoi0y+O5kQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.0.0" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.76.2.tgz", - "integrity": "sha512-spXabhd0sgX87QaYUDou22KduSL5GHCmLNuPDpPykYelB/zZnE8aPsrjBMIgK9CPZoQCDoWYYmtRTPfJjKwf3Q==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.96.0.tgz", + "integrity": "sha512-7Q82o/6XbiX9o+pqDC4iRr8onsx2HZoo6O54FA0YGc2nW9V5vEWXDZxp76psPlQA6oShkOT3ehd/wjz7ERUysA==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.76.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, + "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.76.2.tgz", - "integrity": "sha512-KIEg9QWeiMMKQ9VtftK+1Rc7irKQjj0VTsoEtraun9N2MWLVt7g+xZKqbqtQ4/ovv5J8JBHE+hFGLdm2qZalsg==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.96.0.tgz", + "integrity": "sha512-T2Z1X8iuxTkx8nhFKaW2RbJlytWqetXTzqMvCfjZsvFI9iyi1fVKeIkPNa06mFvGPWTeNuzd1tJOjZZjS/ljNA==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.76.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, - "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.76.2.tgz", - "integrity": "sha512-nmEDYOfqeB8yCHbQ5yEQkJ09zIDOeX61KXTUktP4yErm96WVjIUk5YTTAkO7QbAEND9JHE+BAnS25cBC8BxFFA==", + "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-0.96.0.tgz", + "integrity": "sha512-DY2CaEmM0VQ1nbNJAU1HHyHbCSPKRihhVx+5BTd1L4l8/092e0wXbNip0xLxH8jgJaOkAU85I8DXTIanlPsSvg==", + "license": "Apache-2.0", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.76.2", - "@swagger-api/apidom-core": "^0.76.2", - "@swagger-api/apidom-error": "^0.76.2", - "@types/ramda": "~0.29.3", - "ramda": "~0.29.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-workflows-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.0.0" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-0.96.0.tgz", + "integrity": "sha512-Mj55ejT5TncLzANHw9VvopnN+xPjAeBhyw7Vt6FlDnPRJXpFwffhMmHZJo78N3gbwggM9gKPJsJLLjnW57Rt8Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-ns-workflows-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", + "ramda-adjunct": "^4.0.0" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": { + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.96.0.tgz", + "integrity": "sha512-FI8uQEAU191TVz/cartkQO5uu+Psv+YxrCo7d/JrY5JsODIo+PuLfoTuOHM3rnZckWGCIgCIo2LWX4A58nEpiQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.20.7", + "@swagger-api/apidom-ast": "^0.96.0", + "@swagger-api/apidom-core": "^0.96.0", + "@swagger-api/apidom-error": "^0.96.0", + "@types/ramda": "~0.29.6", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", "tree-sitter": "=0.20.4", "tree-sitter-yaml": "=0.5.0", "web-tree-sitter": "=0.20.3" } }, + "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@swagger-api/apidom-reference": { - "version": "0.76.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.76.2.tgz", - "integrity": "sha512-O1qX6Tql+B18Em/ERyqCzuhcvOG3JeRq4QIHfebzS3lNxpxX6si/z0DrL5K1azBldmnXx7UGqt/fvwq8GQJmIA==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.96.0.tgz", + "integrity": "sha512-hzEP3yX8ruoqDK3nmhIycdktzlA80vp2NBKmsgbCg3d+pnYjcSBWIkCp4922yxTNnrYbpQgioWIQ0sUJukjjEw==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.76.2", - "@types/ramda": "~0.29.3", + "@swagger-api/apidom-core": "^0.96.0", + "@types/ramda": "~0.29.6", "axios": "^1.4.0", "minimatch": "^7.4.3", "process": "^0.11.10", - "ramda": "~0.29.0", + "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", "stampit": "^4.3.2" }, "optionalDependencies": { - "@swagger-api/apidom-error": "^0.76.2", - "@swagger-api/apidom-json-pointer": "^0.76.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.76.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.76.2", - "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.76.2", - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.76.2", - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.76.2", - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.76.2", - "@swagger-api/apidom-parser-adapter-json": "^0.76.2", - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.76.2", - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.76.2", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.76.2", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.76.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.76.2" - } - }, - "node_modules/@swagger-api/apidom-reference/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" + "@swagger-api/apidom-error": "^0.96.0", + "@swagger-api/apidom-json-pointer": "^0.96.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.96.0", + "@swagger-api/apidom-ns-openapi-2": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.96.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.96.0", + "@swagger-api/apidom-ns-workflows-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.96.0", + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.96.0", + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-json": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-json-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.96.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-workflows-json-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^0.96.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.96.0" } }, "node_modules/@swagger-api/apidom-reference/node_modules/minimatch": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7098,11 +8994,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@swagger-api/apidom-reference/node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@babel/generator": "7.17.7", "@babel/parser": "^7.20.5", @@ -7126,6 +9033,7 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -7135,11 +9043,65 @@ "node": ">=6.9.0" } }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -7153,15 +9115,17 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -7171,38 +9135,42 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -7213,6 +9181,7 @@ "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.41.tgz", "integrity": "sha512-3dvkDvueckY83UyUXtJMalYoH6faOLkWQoaTlJgB4Djde3oORmNP0Jw85HtzTuXyliUHcdp704s0mZFQKio/KQ==", "dev": true, + "license": "MIT", "dependencies": { "moment": "^2.10.2" } @@ -7222,15 +9191,17 @@ "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz", "integrity": "sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==", "dev": true, + "license": "MIT", "dependencies": { "@types/tern": "*" } }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -7245,42 +9216,54 @@ } }, "node_modules/@types/d3-scale": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.4.tgz", - "integrity": "sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "license": "MIT", "dependencies": { "@types/d3-time": "*" } }, "node_modules/@types/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", + "license": "MIT" }, "node_modules/@types/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==", + "license": "MIT" }, "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/detect-port": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.3.tgz", - "integrity": "sha512-bV/jQlAJ/nPY3XqSatkGpu+nGzou+uSwrH1cROhn+jBFg47yaNH+blW4C7p9KhopC7QxCv/6M86s37k8dMk0Yg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", + "integrity": "sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/diff": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.1.tgz", + "integrity": "sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==", "dev": true }, "node_modules/@types/doctrine": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.3.tgz", "integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ejs": { "version": "3.1.5", @@ -7292,19 +9275,22 @@ "version": "1.39.10", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.10.tgz", "integrity": "sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -7313,10 +9299,11 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.36", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", - "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -7330,229 +9317,181 @@ "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", "dev": true }, - "node_modules/@types/fs-extra": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", - "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/grecaptcha": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/grecaptcha/-/grecaptcha-3.0.7.tgz", - "integrity": "sha512-ah5GDQfsiK3dnkaCbYcDFZXkZCG3o90VRu9hzXHnSe4kACrRB1KUI/ZyWHvYmqm1W5Tl8B5YxxT98uGTlkbf2Q==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/grecaptcha/-/grecaptcha-3.0.9.tgz", + "integrity": "sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==", "dev": true }, "node_modules/@types/guacamole-common-js": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/guacamole-common-js/-/guacamole-common-js-1.5.2.tgz", "integrity": "sha512-S01txydRyBscHyV8giYNdrfU7dzwUkLb8prQPP68/YCpY/gMtcL9e7BXGpQttj4XpelSUVkA++TjllalZ0AHjg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } }, "node_modules/@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } + "license": "MIT" }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.14.198", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz", - "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==", - "dev": true + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/mdast": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", - "integrity": "sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "license": "MIT", "dependencies": { "@types/unist": "^2" } }, "node_modules/@types/mdx": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", - "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", "dev": true }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/mime-types": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", - "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", - "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==", - "dev": true - }, - "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "20.11.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", + "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" + "undici-types": "~5.26.4" } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/pretty-hrtime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", - "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "dev": true, + "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", - "dev": true + "version": "6.9.12", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", + "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/ramda": { - "version": "0.29.3", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.3.tgz", - "integrity": "sha512-Yh/RHkjN0ru6LVhSQtTkCRo6HXkfL9trot/2elzM/yXLJmbLm2v6kJc8yftTnwv1zvUob6TEtqI2cYjdqG3U0Q==", + "version": "0.29.11", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.11.tgz", + "integrity": "sha512-jm1+PmNOpE7aPS+mMcuB4a72VkCXUJqPSaQRu2YqR8MbsFfaowYXgKxc7bluYdDpRHNXT5Z+xu+Lgr3/ml6wSA==", + "license": "MIT", "dependencies": { - "types-ramda": "^0.29.4" + "types-ramda": "^0.29.9" } }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "version": "18.2.61", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.61.tgz", + "integrity": "sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA==", "dev": true, + "license": "MIT", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true - }, "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "dev": true + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "dev": true, + "license": "MIT" }, "node_modules/@types/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", - "dev": true + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -7560,62 +9499,51 @@ } }, "node_modules/@types/showdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.1.tgz", - "integrity": "sha512-xdnAw2nFqomkaL0QdtEk0t7yz26UkaVPl4v1pYJvtE1T0fmfQEH3JaxErEhGByEAl3zUZrkNBlneuJp0WJGqEA==", - "dev": true + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.6.tgz", + "integrity": "sha512-pTvD/0CIeqe4x23+YJWlX2gArHa8G0J0Oh6GKaVXV7TAeickpkkZiNOgFcFcmLQ5lB/K0qBJL1FtRYltBfbGCQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/tern": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", - "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*" } }, "node_modules/@types/trusted-types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", - "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" }, "node_modules/@types/unist": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz", - "integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==" + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "license": "MIT" }, "node_modules/@types/uuid": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", - "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7624,15 +9552,15 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -7645,6 +9573,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -7653,10 +9582,11 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -7671,29 +9601,30 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -7702,16 +9633,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7719,25 +9650,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -7746,12 +9677,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7759,13 +9690,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7774,7 +9705,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7786,15 +9717,6 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7807,25 +9729,10 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -7844,28 +9751,28 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { @@ -7881,9 +9788,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -7902,16 +9809,16 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7922,24 +9829,28 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@vscode/web-custom-data": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/@vscode/web-custom-data/-/web-custom-data-0.4.8.tgz", - "integrity": "sha512-rRiEeEX49wipCeGZo65mQJUEuCY3IXd6bet90eY6cMMQ9jBe2g3Njw/2ctbaxuACPnEKXTdW0dB7umxDln3Rzg==", - "dev": true + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@vscode/web-custom-data/-/web-custom-data-0.4.9.tgz", + "integrity": "sha512-QeCJFISE/RiTG0NECX6DYmVRPVb0jdyaUrhY0JqNMv9ruUYtYqxxQfv3PSjogb+zNghmwgXLSYuQKk6G+Xnaig==", + "dev": true, + "license": "MIT" }, "node_modules/@webcomponents/webcomponentsjs": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.8.0.tgz", - "integrity": "sha512-loGD63sacRzOzSJgQnB9ZAhaQGkN7wl2Zuw7tsphI5Isa0irijrRo6EnJii/GgjGefIFO8AIO7UivzRhFaEk9w==" + "integrity": "sha512-loGD63sacRzOzSJgQnB9ZAhaQGkN7wl2Zuw7tsphI5Isa0irijrRo6EnJii/GgjGefIFO8AIO7UivzRhFaEk9w==", + "license": "BSD-3-Clause" }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -7964,6 +9875,7 @@ "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@yarnpkg/libzip": "^2.3.0", "tslib": "^1.13.0" @@ -7976,13 +9888,15 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/@yarnpkg/libzip": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@types/emscripten": "^1.39.6", "tslib": "^1.13.0" @@ -7995,13 +9909,15 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -8011,10 +9927,11 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -8027,6 +9944,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -8068,24 +9986,17 @@ "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -8099,6 +10010,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8115,6 +10027,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8124,6 +10037,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -8136,6 +10050,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -8144,13 +10059,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -8163,22 +10080,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } + "license": "MIT" }, "node_modules/aria-hidden": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -8187,13 +10097,17 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8203,29 +10117,33 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -8240,6 +10158,7 @@ "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "is-nan": "^1.3.2", @@ -8253,6 +10172,7 @@ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.1" }, @@ -8266,22 +10186,21 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -8290,28 +10209,16 @@ } }, "node_modules/axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -8321,27 +10228,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -8353,13 +10245,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", - "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", + "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.4", + "@babel/helper-define-polyfill-provider": "^0.6.1", "semver": "^6.3.1" }, "peerDependencies": { @@ -8367,25 +10259,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", - "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4", - "core-js-compat": "^3.33.1" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", - "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", + "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4" + "@babel/helper-define-polyfill-provider": "^0.6.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -8396,6 +10288,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-tsconfig-paths/-/babel-plugin-tsconfig-paths-1.0.3.tgz", "integrity": "sha512-eBTjzXpx0CXO2gooYPyIU1joS/eK1Vk2+oLhJDwRwIgh2+2kD/j649eYNtHjFKuXr36/4Y0ytPORLyiey7MLRA==", "dev": true, + "license": "ISC", "peerDependencies": { "@babel/core": "^7.9.0" } @@ -8403,12 +10296,14 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/base64-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -8430,13 +10325,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/better-opn": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", "dev": true, + "license": "MIT", "dependencies": { "open": "^8.0.4" }, @@ -8445,10 +10342,11 @@ } }, "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "dev": true, + "license": "Unlicense", "engines": { "node": ">=0.6" } @@ -8458,6 +10356,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8467,6 +10366,7 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "devOptional": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -8492,19 +10392,21 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -8512,7 +10414,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -8526,6 +10428,7 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -8535,6 +10438,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -8543,13 +10447,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/body-parser/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -8565,6 +10471,7 @@ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", "dev": true, + "license": "MIT", "dependencies": { "big-integer": "^1.6.44" }, @@ -8573,13 +10480,12 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -8587,6 +10493,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -8616,9 +10523,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -8634,9 +10541,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -8647,15 +10555,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -8674,54 +10573,43 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8732,23 +10620,15 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001568", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz", - "integrity": "sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==", + "version": "1.0.30001593", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001593.tgz", + "integrity": "sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==", "dev": true, "funding": [ { @@ -8763,13 +10643,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -8783,42 +10665,39 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/chart.js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", - "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", + "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", "dependencies": { "@kurkle/color": "^0.3.0" }, "engines": { - "pnpm": ">=7" + "pnpm": ">=8" } }, "node_modules/chartjs-adapter-moment": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz", "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==", + "license": "MIT", "peerDependencies": { "chart.js": ">=3.0.0", "moment": "^2.10.2" } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -8831,6 +10710,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -8840,6 +10722,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -8856,25 +10739,10 @@ "node": ">=10" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/citty": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", - "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "dev": true, "dependencies": { "consola": "^3.2.3" @@ -8885,6 +10753,7 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -8918,6 +10787,7 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -8933,6 +10803,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -8965,22 +10836,11 @@ "node": ">=6" } }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/codemirror": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -8996,6 +10856,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -9007,18 +10868,14 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9030,6 +10887,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", "engines": { "node": ">= 10" } @@ -9038,13 +10896,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -9057,6 +10917,7 @@ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -9075,6 +10936,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -9083,58 +10945,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } + "license": "MIT" }, "node_modules/consola": { "version": "3.2.3", @@ -9148,13 +10967,15 @@ "node_modules/construct-style-sheets-polyfill": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz", - "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==" + "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==", + "license": "MIT" }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -9180,27 +11001,30 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -9209,12 +11033,13 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-js": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz", - "integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -9222,12 +11047,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", - "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", + "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", "dev": true, "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -9235,10 +11060,11 @@ } }, "node_modules/core-js-pure": { - "version": "3.32.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.32.2.tgz", - "integrity": "sha512-Y2rxThOuNywTjnX/PgA5vWM6CZ9QB9sz9oGeCixV8MqXZO70z/5SHzf9EeBrEBK0PN36DnEBBu9O/aGWzKuMZQ==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.36.0.tgz", + "integrity": "sha512-cN28qmhRNgbMZZMc/RFu5w8pK9VJzpb2rJVR/lHuZJKwmXnoWOpXmMkxqBB514igkp1Hu8WGROsiOAzUcKdHOQ==", "hasInstallScript": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -9254,6 +11080,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", "dependencies": { "layout-base": "^1.0.0" } @@ -9263,6 +11090,7 @@ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -9279,25 +11107,28 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/country-flag-icons": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.9.tgz", - "integrity": "sha512-9jrjv2w7kRbqNtdtMdK2j3gmDIZzd5l9L2pZiQjF9J0mUcB+NKIGDNADTDHBEp8EQtjOkCOcciJGGSOpERdXPQ==" + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.11.tgz", + "integrity": "sha512-B+mvFywunkRJs270k7kCBjhogvIA0uNn6GAXv6m2cPn3rrwqZzZVr2gBWcz+Cz7OGVWlcbERlYRIX0S6OGr8Bw==" }, "node_modules/crelt": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.1" }, @@ -9311,19 +11142,12 @@ "yarn": ">=1" } }, - "node_modules/cross-fetch": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", - "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", - "dependencies": { - "node-fetch": "^2.6.12" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9338,20 +11162,23 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.26.0.tgz", - "integrity": "sha512-IV+crL+KBcrCnVVUCZW+zRRRFUZQcrtdOPXki+o4CFUWLdAEYvuZLcBSJC9EBK++suamERKzeY7roq2hdovV3w==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.28.1.tgz", + "integrity": "sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg==", + "license": "MIT", "dependencies": { "heap": "^0.2.6", "lodash": "^4.17.21" @@ -9364,6 +11191,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", "dependencies": { "cose-base": "^1.0.0" }, @@ -9371,34 +11199,11 @@ "cytoscape": "^3.2.0" } }, - "node_modules/cytoscape-fcose": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", - "dependencies": { - "cose-base": "^2.2.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/cose-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", - "dependencies": { - "layout-base": "^2.0.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/layout-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" - }, "node_modules/d3": { "version": "7.8.5", "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "license": "ISC", "dependencies": { "d3-array": "3", "d3-axis": "3", @@ -9439,6 +11244,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", "dependencies": { "internmap": "1 - 2" }, @@ -9450,6 +11256,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9458,6 +11265,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", @@ -9473,6 +11281,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", "dependencies": { "d3-path": "1 - 3" }, @@ -9484,6 +11293,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9492,6 +11302,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", "dependencies": { "d3-array": "^3.2.0" }, @@ -9503,6 +11314,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", "dependencies": { "delaunator": "5" }, @@ -9514,6 +11326,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9522,6 +11335,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" @@ -9534,6 +11348,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", "dependencies": { "commander": "7", "iconv-lite": "0.6", @@ -9558,6 +11373,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -9569,6 +11385,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", "engines": { "node": ">=12" } @@ -9577,6 +11394,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", "dependencies": { "d3-dsv": "1 - 3" }, @@ -9588,6 +11406,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", @@ -9601,6 +11420,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9609,6 +11429,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "license": "ISC", "dependencies": { "d3-array": "2.5.0 - 3" }, @@ -9620,6 +11441,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9628,6 +11450,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3" }, @@ -9639,6 +11462,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9647,6 +11471,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9655,6 +11480,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9663,6 +11489,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9671,6 +11498,7 @@ "version": "0.12.3", "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" @@ -9680,6 +11508,7 @@ "version": "2.12.1", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", "dependencies": { "internmap": "^1.0.0" } @@ -9687,12 +11516,14 @@ "node_modules/d3-sankey/node_modules/d3-path": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" }, "node_modules/d3-sankey/node_modules/d3-shape": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", "dependencies": { "d3-path": "1" } @@ -9700,12 +11531,14 @@ "node_modules/d3-sankey/node_modules/internmap": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" }, "node_modules/d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", @@ -9721,6 +11554,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" @@ -9733,6 +11567,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9741,6 +11576,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", "dependencies": { "d3-path": "^3.1.0" }, @@ -9752,6 +11588,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", "dependencies": { "d3-array": "2 - 3" }, @@ -9763,6 +11600,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", "dependencies": { "d3-time": "1 - 3" }, @@ -9774,6 +11612,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -9782,6 +11621,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", @@ -9800,6 +11640,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", @@ -9815,6 +11656,7 @@ "version": "7.0.10", "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "license": "MIT", "dependencies": { "d3": "^7.8.2", "lodash-es": "^4.17.21" @@ -9827,14 +11669,16 @@ "dev": true }, "node_modules/dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -9851,6 +11695,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "license": "MIT", "dependencies": { "character-entities": "^2.0.0" }, @@ -9863,6 +11708,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "optional": true, "dependencies": { "mimic-response": "^3.1.0" @@ -9878,6 +11724,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", "optional": true, "engines": { "node": ">=4.0.0" @@ -9887,12 +11734,14 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9902,6 +11751,7 @@ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", "dev": true, + "license": "MIT", "dependencies": { "bplist-parser": "^0.2.0", "untildify": "^4.0.0" @@ -9925,21 +11775,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -9961,6 +11831,7 @@ "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, + "license": "MIT", "dependencies": { "globby": "^11.0.1", "graceful-fs": "^4.2.4", @@ -9979,17 +11850,19 @@ } }, "node_modules/delaunator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", "dependencies": { - "robust-predicates": "^3.0.0" + "robust-predicates": "^3.0.2" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -9999,6 +11872,7 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10007,6 +11881,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -10016,6 +11891,7 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -10034,6 +11910,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "license": "Apache-2.0", "optional": true, "engines": { "node": ">=8" @@ -10043,7 +11920,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/detect-package-manager": { "version": "2.0.1", @@ -10062,6 +11940,7 @@ "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", "dev": true, + "license": "MIT", "dependencies": { "address": "^1.0.1", "debug": "4" @@ -10076,6 +11955,7 @@ "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-4.1.0.tgz", "integrity": "sha512-qTBmfQoXvhKO75D/05C8m+fteQmn4U46FWYiLhXtZQInzitXLWY0EQ/2oKnpAz9g2lQWW8jYcLcT+hPJGT+kig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.2", "leven": "^3.1.0", @@ -10086,9 +11966,10 @@ } }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -10098,6 +11979,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -10110,6 +11992,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -10118,20 +12001,22 @@ } }, "node_modules/dompurify": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.5.tgz", - "integrity": "sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.9.tgz", + "integrity": "sha512-uyb4NDIvQ3hRn6NiC+SIFaP4mJ/MdXlvtunaqK9Bn6dD3RuB/1S/gasEjDHD8eiaqdSael2vBv+hOs7Y+jhYOQ==", + "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { @@ -10139,6 +12024,7 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -10195,12 +12081,13 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -10213,27 +12100,31 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.610", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.610.tgz", - "integrity": "sha512-mqi2oL1mfeHYtOdCxbPQYV/PL7YrQlxbvFEZ0Ee8GbDdShimqt2/S6z2RWqysuvlwdOrQdqvE0KZrBTipAeJzg==", - "dev": true + "version": "1.4.690", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.690.tgz", + "integrity": "sha512-+2OAGjUx68xElQhydpcbqH50hE8Vs2K6TkAeLhICYfndb67CVH0UsZaijmRUE3rHlIxU1u0jxwhgVe6fK3YANA==", + "dev": true, + "license": "ISC" }, "node_modules/elkjs": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.1.tgz", - "integrity": "sha512-JWKDyqAdltuUcyxaECtYG6H4sqysXSLeoXuGUBfRNESMTkj+w+qdb0jya8Z/WI0jVd03WQtCGhS6FOFtlhD5FQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.2.tgz", + "integrity": "sha512-2Y/RaA1pdgSHpY0YG4TYuYCD2wh97CRvu22eLG3Kz0pgQ/6KbIFTxsTnDc4MH/6hFlg2L/9qXrDMG0nMjP63iw==", + "license": "EPL-2.0" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10243,6 +12134,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "devOptional": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } @@ -10252,6 +12144,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -10260,9 +12153,9 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -10276,55 +12169,59 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -10333,21 +12230,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", + "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==", "dev": true }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -10358,6 +12277,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -10371,9 +12291,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.3.tgz", + "integrity": "sha512-Kgq0/ZsAPzKrbOjCQcjoSmPoWhlcVnGAUo7jvaLHoxW1Drto0KGkR1xBNg2Cp43b9ImvxmPEJZ9xkfcnqPsfBw==", "dev": true, "hasInstallScript": true, "bin": { @@ -10383,28 +12303,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.21.3", + "@esbuild/android-arm": "0.21.3", + "@esbuild/android-arm64": "0.21.3", + "@esbuild/android-x64": "0.21.3", + "@esbuild/darwin-arm64": "0.21.3", + "@esbuild/darwin-x64": "0.21.3", + "@esbuild/freebsd-arm64": "0.21.3", + "@esbuild/freebsd-x64": "0.21.3", + "@esbuild/linux-arm": "0.21.3", + "@esbuild/linux-arm64": "0.21.3", + "@esbuild/linux-ia32": "0.21.3", + "@esbuild/linux-loong64": "0.21.3", + "@esbuild/linux-mips64el": "0.21.3", + "@esbuild/linux-ppc64": "0.21.3", + "@esbuild/linux-riscv64": "0.21.3", + "@esbuild/linux-s390x": "0.21.3", + "@esbuild/linux-x64": "0.21.3", + "@esbuild/netbsd-x64": "0.21.3", + "@esbuild/openbsd-x64": "0.21.3", + "@esbuild/sunos-x64": "0.21.3", + "@esbuild/win32-arm64": "0.21.3", + "@esbuild/win32-ia32": "0.21.3", + "@esbuild/win32-x64": "0.21.3" } }, "node_modules/esbuild-plugin-alias": { @@ -10418,6 +12339,7 @@ "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -10425,43 +12347,12 @@ "esbuild": ">=0.12 <1" } }, - "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -10470,28 +12361,31 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -10541,6 +12435,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" }, @@ -10553,6 +12448,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-custom-elements/-/eslint-plugin-custom-elements-0.0.8.tgz", "integrity": "sha512-726XMAabRLKKm6/yjvYfvY4MKBwX9C4x8yPjj/ap470KhSIBHm+xHbm3P7cKlsFz/4cxq6YrBeSwKmwlacF1jg==", "dev": true, + "license": "MIT", "peerDependencies": { "eslint": ">=4.19.0" } @@ -10562,6 +12458,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.11.0.tgz", "integrity": "sha512-jVqy2juQTAtOzj1ILf+ZW5GpDobXlSw0kvpP2zu2r8ZbW7KISt7ikj1Gw9DhNeirEU1UlSJR0VIWpdr4lzjayw==", "dev": true, + "license": "MIT", "dependencies": { "parse5": "^6.0.1", "parse5-htmlparser2-tree-adapter": "^6.0.1", @@ -10574,31 +12471,39 @@ "eslint": ">= 5" } }, + "node_modules/eslint-plugin-lit/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz", - "integrity": "sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.1.tgz", + "integrity": "sha512-5IOKvj/GMBNqjxBdItfotfRHo7w48496GOu1hxdeXuD0mB1JBlDCViiLHETDTfA8pDAVSBimBEQoetRXYceQEw==", "dev": true, "engines": { - "node": ">=14" + "node": ">=16" }, "peerDependencies": { "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/eslint-plugin-storybook": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.15.tgz", - "integrity": "sha512-lAGqVAJGob47Griu29KXYowI4G7KwMoJDOkEip8ujikuDLxU+oWJ1l0WL6F2oDO4QiyUFXvtDkEkISMOPzo+7w==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", + "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", "dev": true, + "license": "MIT", "dependencies": { "@storybook/csf": "^0.0.1", - "@typescript-eslint/utils": "^5.45.0", - "requireindex": "^1.1.0", + "@typescript-eslint/utils": "^5.62.0", + "requireindex": "^1.2.0", "ts-dedent": "^2.2.0" }, "engines": { - "node": "12.x || 14.x || >= 16" + "node": ">= 18" }, "peerDependencies": { "eslint": ">=6" @@ -10609,6 +12514,7 @@ "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.15" } @@ -10618,6 +12524,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" @@ -10635,6 +12542,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10648,6 +12556,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", @@ -10675,6 +12584,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -10701,6 +12611,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" @@ -10718,6 +12629,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10731,6 +12643,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -10740,6 +12653,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -10748,10 +12662,11 @@ } }, "node_modules/eslint-plugin-storybook/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -10766,13 +12681,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -10789,6 +12706,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10801,6 +12719,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -10815,13 +12734,26 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10838,6 +12770,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10846,10 +12779,11 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -10865,6 +12799,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10874,6 +12809,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -10881,11 +12817,25 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -10898,6 +12848,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -10910,6 +12861,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -10927,6 +12879,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -10940,6 +12893,7 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -10952,6 +12906,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -10964,6 +12919,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -10979,6 +12935,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -10988,6 +12945,7 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10997,6 +12955,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -11019,23 +12978,24 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", "optional": true, "engines": { "node": ">=6" } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -11071,6 +13031,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -11079,13 +13040,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/express/node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -11114,67 +13077,22 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "dependencies": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - } - }, - "node_modules/extract-zip/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + ], + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -11191,6 +13109,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -11201,47 +13120,33 @@ "node_modules/fast-json-patch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fetch-retry": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", @@ -11253,6 +13158,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -11265,6 +13171,7 @@ "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", "dev": true, + "license": "MIT", "dependencies": { "fs-extra": "11.1.1", "ramda": "0.29.0" @@ -11275,6 +13182,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -11293,15 +13201,6 @@ "minimatch": "^5.0.1" } }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -11319,6 +13218,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -11331,6 +13231,7 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -11349,6 +13250,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -11357,13 +13259,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -11381,6 +13285,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -11394,6 +13299,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -11406,6 +13312,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -11421,6 +13328,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -11433,6 +13341,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -11445,6 +13354,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -11457,38 +13367,40 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" }, "node_modules/flow-parser": { - "version": "0.227.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.227.0.tgz", - "integrity": "sha512-nOygtGKcX/siZK/lFzpfdHEfOkfGcTW7rNroR1Zsz6T/JxSahPALXVt5qVHq/fgvMJuv096BTKbgxN3PzVBaDA==", + "version": "0.236.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.236.0.tgz", + "integrity": "sha512-0OEk9Gr+Yj7wjDW2KgaNYUypKau71jAfFyeLQF5iVtxqc6uJHag/MT7pmaEApf4qM7u86DkBcd4ualddYMfbLw==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -11509,6 +13421,7 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } @@ -11518,6 +13431,7 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -11534,6 +13448,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -11542,10 +13457,10 @@ } }, "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -11555,28 +13470,12 @@ "node": ">= 6" } }, - "node_modules/form-data-encoder": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.9.0.tgz", - "integrity": "sha512-rahaRMkN8P8d/tgK/BLPX+WBVM27NbvdXBxqQujBtkDAIFspaRqN7Od7lfdGQA6KAD+f82fYCLBq1ipvcu8qLw==" - }, - "node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", - "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" - }, - "engines": { - "node": ">= 12.20" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -11586,6 +13485,7 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -11594,13 +13494,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -11644,14 +13546,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -11661,15 +13564,20 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -11688,6 +13596,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11696,6 +13605,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "license": "Apache-2.0", "engines": { "node": ">=10" } @@ -11705,6 +13615,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -11714,19 +13625,25 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11737,6 +13654,7 @@ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11750,32 +13668,12 @@ "node": ">=12.17" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11784,13 +13682,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -11800,18 +13700,18 @@ } }, "node_modules/giget": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", - "integrity": "sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", "dev": true, "dependencies": { - "citty": "^0.1.5", + "citty": "^0.1.6", "consola": "^3.2.3", - "defu": "^6.1.3", - "node-fetch-native": "^1.6.1", - "nypm": "^0.3.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", "ohash": "^1.1.3", - "pathe": "^1.1.1", + "pathe": "^1.1.2", "tar": "^6.2.0" }, "bin": { @@ -11822,28 +13722,33 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT", "optional": true }, "node_modules/github-slugger": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", - "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true, + "license": "ISC" }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.0.tgz", + "integrity": "sha512-+K6CicMIL11UEbC3gH/MVxgGG4gJDMu9tPD+nH+d6W3+y2fYuDSbpa2b+EGyvCGvSN/PT/7daJTH25NknJkcIQ==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -11854,6 +13759,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -11865,27 +13771,31 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/globals": { @@ -11893,6 +13803,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -11902,6 +13813,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.1.3" }, @@ -11917,6 +13829,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -11936,13 +13849,14 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -11954,33 +13868,21 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } + "license": "MIT" }, "node_modules/guacamole-common-js": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/guacamole-common-js/-/guacamole-common-js-1.5.0.tgz", - "integrity": "sha512-zxztif3GGhKbg1RgOqwmqot8kXgv2HmHFg1EvWwd4q7UfEKvBcYZ0f+7G8HzvU+FUxF0Psqm9Kl5vCbgfrRgJg==" + "integrity": "sha512-zxztif3GGhKbg1RgOqwmqot8kXgv2HmHFg1EvWwd4q7UfEKvBcYZ0f+7G8HzvU+FUxF0Psqm9Kl5vCbgfrRgJg==", + "license": "Apache 2.0" }, "node_modules/gunzip-maybe": { "version": "1.4.2", @@ -12004,6 +13906,7 @@ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -12020,17 +13923,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -12057,6 +13949,7 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12066,26 +13959,28 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12097,6 +13992,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12105,12 +14001,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -12119,22 +14016,76 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/heap": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "license": "MIT" }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -12146,24 +14097,12 @@ "node": ">= 0.8" } }, - "node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "dependencies": { - "agent-base": "5", - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -12173,6 +14112,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -12197,13 +14137,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -12213,6 +14155,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -12229,6 +14172,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12238,6 +14182,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -12247,6 +14192,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12256,6 +14202,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -12265,22 +14212,25 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "devOptional": true + "devOptional": true, + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC", "optional": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -12291,6 +14241,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -12300,32 +14251,38 @@ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true, + "license": "MIT" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-arguments": { @@ -12333,6 +14290,7 @@ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12345,14 +14303,17 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12362,13 +14323,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -12381,6 +14344,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -12393,6 +14357,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12427,26 +14392,12 @@ "node": ">=4" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12455,12 +14406,13 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12471,6 +14423,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12492,6 +14445,7 @@ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -12502,20 +14456,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12525,6 +14471,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12534,6 +14481,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12549,6 +14497,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -12574,17 +14523,12 @@ "node": ">=8" } }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -12597,10 +14541,11 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12613,6 +14558,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -12622,6 +14568,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12637,6 +14584,7 @@ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -12646,26 +14594,21 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { - "@types/estree": "*" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/is-regex": { @@ -12673,6 +14616,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12685,12 +14629,16 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12701,6 +14649,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -12713,6 +14662,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12728,6 +14678,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -12739,12 +14690,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12770,6 +14722,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -12782,6 +14735,7 @@ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, @@ -12793,13 +14747,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", @@ -12810,35 +14766,10 @@ "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", + "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -12854,9 +14785,9 @@ } }, "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", + "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", "dev": true, "dependencies": { "async": "^3.2.3", @@ -12886,6 +14817,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -12911,6 +14852,18 @@ "node": ">=8" } }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jake/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12927,173 +14880,20 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "license": "MIT" }, "node_modules/jscodeshift": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.1.tgz", - "integrity": "sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", "dev": true, "dependencies": { "@babel/core": "^7.23.0", @@ -13181,22 +14981,12 @@ "node": ">=8" } }, - "node_modules/jscodeshift/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -13208,37 +14998,43 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -13251,6 +15047,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -13263,23 +15060,48 @@ "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, + "node_modules/katex": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/khroma": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz", - "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" }, "node_modules/kind-of": { "version": "6.0.3", @@ -13295,6 +15117,7 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -13302,13 +15125,15 @@ "node_modules/layout-base": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" }, "node_modules/lazy-universal-dotenv": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "app-root-dir": "^1.0.2", "dotenv": "^16.0.0", @@ -13323,6 +15148,7 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -13332,6 +15158,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -13344,16 +15171,17 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lit": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", - "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz", + "integrity": "sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==", "dependencies": { - "@lit/reactive-element": "^1.6.0", - "lit-element": "^3.3.0", - "lit-html": "^2.8.0" + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2" } }, "node_modules/lit-analyzer": { @@ -13361,6 +15189,7 @@ "resolved": "https://registry.npmjs.org/lit-analyzer/-/lit-analyzer-2.0.3.tgz", "integrity": "sha512-XiAjnwVipNrKav7r3CSEZpWt+mwYxrhPRVC7h8knDmn/HWTzzWJvPe+mwBcL2brn4xhItAMzZhFC8tzzqHKmiQ==", "dev": true, + "license": "MIT", "dependencies": { "@vscode/web-custom-data": "^0.4.2", "chalk": "^2.4.2", @@ -13380,22 +15209,51 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lit-element": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz", "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==", + "license": "BSD-3-Clause", "dependencies": { "@lit-labs/ssr-dom-shim": "^1.1.0", "@lit/reactive-element": "^1.3.0", "lit-html": "^2.8.0" } }, + "node_modules/lit-element/node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, "node_modules/lit-html": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/lit/node_modules/lit-element": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.4.tgz", + "integrity": "sha512-98CvgulX6eCPs6TyAIQoJZBCQPo80rgXR+dVBs61cstJXqtI+USQZAbA4gFHh6L/mxBx9MrgPLHLsUgDUHAcCQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit/node_modules/lit-html": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.2.tgz", + "integrity": "sha512-3OBZSUrPnAHoKJ9AMjRL/m01YJxQMf+TMHanNtTHG68ubjnZxK0RFl102DPzsw4mWnHibfZIBJm3LWCZ/LmMvg==", "dependencies": { "@types/trusted-types": "^2.0.2" } @@ -13405,6 +15263,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", @@ -13420,6 +15279,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, + "license": "MIT", "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -13433,6 +15293,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -13446,30 +15307,35 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.deburr": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", "integrity": "sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -13544,6 +15410,7 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -13556,15 +15423,17 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -13577,6 +15446,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -13587,20 +15457,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/map-or-similar": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/markdown-to-jsx": { "version": "7.3.2", @@ -13618,6 +15480,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -13625,23 +15488,35 @@ "node": ">= 12" } }, - "node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, + "node_modules/md-front-matter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/md-front-matter/-/md-front-matter-1.0.4.tgz", + "integrity": "sha512-8t0csLzqjg+DcTR8sHVyuJDFztzkQd97vtBe2qP3SFnRkl++ygoPpk0rDDtx0dA5eWU5Rw1+e81v1Lx1FuRdpg==", "dependencies": { - "unist-util-visit": "^2.0.0" + "js-yaml": "^4.1.0" + } + }, + "node_modules/md-front-matter/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/md-front-matter/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/mdast-util-from-markdown": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "license": "MIT", "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", @@ -13665,6 +15540,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "license": "MIT", "dependencies": { "@types/mdast": "^3.0.0" }, @@ -13678,6 +15554,7 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13687,6 +15564,7 @@ "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", "dev": true, + "license": "MIT", "dependencies": { "map-or-similar": "^1.5.0" } @@ -13704,7 +15582,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge-source-map": { "version": "1.0.4", @@ -13728,34 +15607,36 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/mermaid": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.7.0.tgz", - "integrity": "sha512-PsvGupPCkN1vemAAjScyw4pw34p4/0dZkSrqvAB26hUvJulOWGIwt35FZWmT9wPIi4r0QLa5X0PB4YLIGn0/YQ==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.1.tgz", + "integrity": "sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==", "dependencies": { "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.23.0", + "cytoscape": "^3.28.1", "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.1.0", "d3": "^7.4.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", "dayjs": "^1.11.7", "dompurify": "^3.0.5", "elkjs": "^0.9.0", + "katex": "^0.16.9", "khroma": "^2.0.0", "lodash-es": "^4.17.21", "mdast-util-from-markdown": "^1.3.0", @@ -13771,6 +15652,7 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13789,6 +15671,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -13823,6 +15706,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-factory-destination": "^1.0.0", @@ -13856,6 +15740,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", @@ -13876,6 +15761,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", @@ -13897,6 +15783,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-types": "^1.0.0" @@ -13916,6 +15803,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", @@ -13937,6 +15825,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", @@ -13958,6 +15847,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" @@ -13977,6 +15867,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^1.0.0" } @@ -13995,6 +15886,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", @@ -14015,6 +15907,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-types": "^1.0.0" @@ -14034,6 +15927,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^1.0.0" } @@ -14052,6 +15946,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^1.0.0", @@ -14072,7 +15967,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-html-tag-name": { "version": "1.2.0", @@ -14087,7 +15983,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-normalize-identifier": { "version": "1.1.0", @@ -14103,6 +16000,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^1.0.0" } @@ -14121,6 +16019,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-types": "^1.0.0" } @@ -14139,6 +16038,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-encode": "^1.0.0", @@ -14159,6 +16059,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-symbol": "^1.0.0", @@ -14179,7 +16080,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-types": { "version": "1.1.0", @@ -14194,13 +16096,15 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -14214,6 +16118,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -14225,6 +16130,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14233,6 +16139,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -14245,6 +16152,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -14253,6 +16161,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -14265,6 +16174,7 @@ "version": "0.23.8", "resolved": "https://registry.npmjs.org/minim/-/minim-0.23.8.tgz", "integrity": "sha512-bjdr2xW1dBCMsMGGsUeqM4eFI60m94+szhxWys+B1ztIt6gWSfeGBdSVCIawezeHYLYn0j6zrsXdQS/JllBzww==", + "license": "MIT", "dependencies": { "lodash": "^4.15.0" }, @@ -14273,15 +16183,19 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -14289,6 +16203,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "devOptional": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14298,6 +16213,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=8" } @@ -14334,36 +16250,39 @@ "dev": true }, "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, "bin": { "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/mock-xmlhttprequest": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/mock-xmlhttprequest/-/mock-xmlhttprequest-8.2.0.tgz", - "integrity": "sha512-agEokniRxw/MhrmIl9Ytn5wuj6kK+pu4KaGPV2fGEKStHXH9HIzYPChth2Jb/MB3TMX0ER1F1QMsvMA3BBe3qA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/mock-xmlhttprequest/-/mock-xmlhttprequest-8.3.0.tgz", + "integrity": "sha512-yjNaP8HskE7GhO0D12kB35+OvCnNAh2fJnD1/mC5Y3WW8WcozJnC23w+8UoU+dmVR4x1KpAB8PPtybY9wI16Ew==", "dev": true, + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -14372,6 +16291,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "license": "MIT", "engines": { "node": ">=4" } @@ -14379,7 +16299,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" }, "node_modules/mutexify": { "version": "1.4.0", @@ -14391,9 +16312,10 @@ } }, "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "license": "MIT", "optional": true }, "node_modules/nanobench": { @@ -14490,19 +16412,22 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "license": "MIT", "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14511,18 +16436,21 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-abi": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.47.0.tgz", - "integrity": "sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", + "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", + "license": "MIT", "optional": true, "dependencies": { "semver": "^7.3.5" @@ -14535,6 +16463,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -14544,9 +16473,10 @@ } }, "node_modules/node-abi/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "license": "ISC", "optional": true, "dependencies": { "lru-cache": "^6.0.0" @@ -14562,8 +16492,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, "node_modules/node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -14576,6 +16513,28 @@ "node": ">= 0.10.5" } }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -14590,6 +16549,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } @@ -14598,6 +16558,8 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -14613,34 +16575,48 @@ } } }, - "node_modules/node-fetch-native": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.1.tgz", - "integrity": "sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==", - "dev": true + "node_modules/node-fetch-commonjs": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch-commonjs/-/node-fetch-commonjs-3.3.2.tgz", + "integrity": "sha512-VBlAiynj3VMLrotgwOS3OyECFxas5y7ltLcK4t41lMUZeaK15Ym4QRkqN0EQKAFL42q9i21EPKjzLUPfltR72A==", + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", "dev": true }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/non-layered-tidy-tree-layout": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -14653,6 +16629,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -14662,6 +16639,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14671,6 +16649,7 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", @@ -14691,11 +16670,23 @@ "node": ">= 4" } }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/npm-run-all/node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -14707,11 +16698,25 @@ "node": ">=4.8" } }, + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/npm-run-all/node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14721,6 +16726,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -14730,6 +16736,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -14742,6 +16749,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14751,6 +16759,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -14763,6 +16772,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -14771,15 +16781,16 @@ } }, "node_modules/nypm": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.4.tgz", - "integrity": "sha512-1JLkp/zHBrkS3pZ692IqOaIKSYHmQXgqfELk6YTOfVBnwealAmPA1q2kKK7PHJAHSMBozerThEFZXP3G6o7Ukg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.8.tgz", + "integrity": "sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==", "dev": true, "dependencies": { - "citty": "^0.1.5", + "citty": "^0.1.6", + "consola": "^3.2.3", "execa": "^8.0.1", - "pathe": "^1.1.1", - "ufo": "^1.3.2" + "pathe": "^1.1.2", + "ufo": "^1.4.0" }, "bin": { "nypm": "dist/cli.mjs" @@ -14857,9 +16868,9 @@ } }, "node_modules/nypm/node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -14927,26 +16938,29 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -14960,18 +16974,20 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -14993,6 +17009,7 @@ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -15005,6 +17022,7 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -15014,6 +17032,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "devOptional": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -15023,6 +17042,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -15038,6 +17058,7 @@ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, + "license": "MIT", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -15055,6 +17076,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, + "license": "MIT", "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -15154,6 +17176,16 @@ "ospec": "bin/ospec" } }, + "node_modules/ospec/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/ospec/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -15174,11 +17206,24 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ospec/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -15194,6 +17239,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -15209,6 +17255,7 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -15224,6 +17271,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -15239,6 +17287,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -15251,6 +17300,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -15265,25 +17315,41 @@ } }, "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "dev": true, + "license": "MIT", "dependencies": { "parse5": "^6.0.1" } }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true, + "license": "MIT" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -15293,6 +17359,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -15302,6 +17369,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15311,6 +17379,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -15319,28 +17388,29 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -15350,13 +17420,15 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -15378,23 +17450,19 @@ "through2": "^2.0.3" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -15407,6 +17475,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, + "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, @@ -15419,6 +17488,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15437,6 +17507,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^5.0.0" }, @@ -15445,10 +17516,11 @@ } }, "node_modules/polished": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", - "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.17.8" }, @@ -15456,10 +17528,20 @@ "node": ">=10" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -15479,16 +17561,17 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "license": "MIT", "optional": true, "dependencies": { "detect-libc": "^2.0.0", @@ -15516,14 +17599,32 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-fallback": { + "name": "prettier", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -15540,6 +17641,7 @@ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -15548,6 +17650,7 @@ "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -15556,6 +17659,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -15566,20 +17670,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -15593,6 +17689,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -15604,6 +17701,7 @@ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -15615,13 +17713,15 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/pseudolocale": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pseudolocale/-/pseudolocale-2.0.0.tgz", "integrity": "sha512-g1K9tCQYY4e3UGtnW8qs3kGWAOONxt7i5wuOFvf3N1EIIRhiLVIhZ9AM/ZyGTxsp231JbFywJU/EbJ5ZoqnZdg==", "dev": true, + "license": "MIT", "dependencies": { "commander": "^10.0.0" }, @@ -15637,6 +17737,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } @@ -15646,6 +17747,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "devOptional": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -15677,109 +17779,22 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/puppeteer-core": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", - "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", - "dev": true, - "dependencies": { - "@types/mime-types": "^2.1.0", - "debug": "^4.1.0", - "extract-zip": "^1.6.6", - "https-proxy-agent": "^4.0.0", - "mime": "^2.0.3", - "mime-types": "^2.1.25", - "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", - "rimraf": "^2.6.1", - "ws": "^6.1.0" - }, - "engines": { - "node": ">=8.16.0" - } - }, - "node_modules/puppeteer-core/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/puppeteer-core/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/puppeteer-core/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/pyright": { - "version": "1.1.338", - "resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.338.tgz", - "integrity": "sha512-cY4p/LZjC3E1m6If48n19vZgBOUASIOX6zMTavIo2o2JlJRd6/+gy+aYaMdmljVF2mVP8NG6OuKiGxERSdpQOw==", - "dev": true, - "bin": { - "pyright": "index.js", - "pyright-langserver": "langserver.index.js" - }, - "engines": { - "node": ">=12.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/qrjs": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/qrjs/-/qrjs-0.2.0.tgz", - "integrity": "sha512-6tOePfihDByEXDULYlT/FmV27m5rX6IehCeZ82LouBD5kzSNqNXuVog8m1KGuGNyQovVOb0nKOB2ybHRRRgKJw==" + "integrity": "sha512-6tOePfihDByEXDULYlT/FmV27m5rX6IehCeZ82LouBD5kzSNqNXuVog8m1KGuGNyQovVOb0nKOB2ybHRRRgKJw==", + "license": "MIT" }, "node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -15808,7 +17823,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/queue-tick": { "version": "1.0.1", @@ -15820,6 +17836,7 @@ "version": "0.29.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/ramda" @@ -15829,6 +17846,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ramda-adjunct/-/ramda-adjunct-4.1.1.tgz", "integrity": "sha512-BnCGsZybQZMDGram9y7RiryoRHS5uwx8YeGuUeDKuZuvK38XO6JJfmK85BwRWAKFA6pZ5nZBO/HBFtExVaf31w==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.3" }, @@ -15840,20 +17858,12 @@ "ramda": ">= 0.29.0" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -15862,6 +17872,7 @@ "version": "9.3.4", "resolved": "https://registry.npmjs.org/rapidoc/-/rapidoc-9.3.4.tgz", "integrity": "sha512-kqNuOSmjlf12SpSfPQaIMuehj7w8JWFFr9/l2zieG7/gCJr1NG2XL920uoqNlXzku1DO8NeHRkSXCmyaZxEOew==", + "license": "MIT", "dependencies": { "@apitools/openapi-parser": "0.0.30", "base64-arraybuffer": "^1.0.2", @@ -15875,11 +17886,30 @@ "node": ">=10.21.0" } }, + "node_modules/rapidoc/node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, + "node_modules/rapidoc/node_modules/lit": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", + "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==", + "dependencies": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.3.0", + "lit-html": "^2.8.0" + } + }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -15895,6 +17925,7 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -15903,6 +17934,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "optional": true, "dependencies": { "deep-extend": "^0.6.0", @@ -15918,15 +17950,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dev": true, "dependencies": { "loose-envify": "^1.1.0" @@ -15940,35 +17973,38 @@ "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", "dev": true, + "license": "MIT", "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dev": true, "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^18.3.1" } }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", "dev": true, + "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.3", "react-style-singleton": "^2.2.1", @@ -15990,10 +18026,11 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", - "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.5.tgz", + "integrity": "sha512-3cqjOqg6s0XbOjWvmasmqHch+RLxIEk2r/70rzGXuz3iIGQsQheEQyqYCBb5EECoD01Vo2SIbDqW4paLeLTASw==", "dev": true, + "license": "MIT", "dependencies": { "react-style-singleton": "^2.2.1", "tslib": "^2.0.0" @@ -16016,6 +18053,7 @@ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", "dev": true, + "license": "MIT", "dependencies": { "get-nonce": "^1.0.0", "invariant": "^2.2.4", @@ -16039,6 +18077,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, + "license": "MIT", "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", @@ -16053,6 +18092,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -16070,6 +18110,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -16083,6 +18124,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -16095,6 +18137,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -16110,6 +18153,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -16122,6 +18166,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -16137,6 +18182,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -16146,6 +18192,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -16155,6 +18202,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^3.0.0" }, @@ -16167,6 +18215,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "devOptional": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -16181,6 +18230,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -16189,15 +18239,16 @@ } }, "node_modules/recast": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.4.tgz", - "integrity": "sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.5.tgz", + "integrity": "sha512-M67zIddJiwXdfPQRYKJ0qZO1SLdH1I0hYeb0wzxA+pNOvAZiQHulWzuk+fYsEWRQ8VfZrgjyucqsCOtCyM01/A==", "dev": true, + "license": "MIT", "dependencies": { - "assert": "^2.0.0", "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" }, "engines": { @@ -16208,13 +18259,15 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, + "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, @@ -16223,9 +18276,10 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -16237,14 +18291,16 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -16258,6 +18314,7 @@ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -16275,6 +18332,7 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -16291,52 +18349,46 @@ "jsesc": "bin/jsesc" } }, - "node_modules/remark-external-links": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", - "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", "dev": true, "dependencies": { - "extend": "^3.0.0", - "is-absolute-url": "^3.0.0", - "mdast-util-definitions": "^4.0.0", - "space-separated-tokens": "^1.0.0", - "unist-util-visit": "^2.0.0" + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-slug": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", - "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", "dev": true, "dependencies": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^2.0.0" + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-slug/node_modules/mdast-util-to-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", - "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "license": "MIT", "engines": { "node": ">=0.10" } @@ -16346,6 +18398,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16355,15 +18408,17 @@ "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.5" } }, "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -16381,6 +18436,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -16403,6 +18459,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -16413,6 +18470,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -16423,11 +18481,23 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -16443,16 +18513,31 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", - "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz", + "integrity": "sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "1.0.5" }, @@ -16464,131 +18549,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.6", - "@rollup/rollup-android-arm64": "4.9.6", - "@rollup/rollup-darwin-arm64": "4.9.6", - "@rollup/rollup-darwin-x64": "4.9.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", - "@rollup/rollup-linux-arm64-gnu": "4.9.6", - "@rollup/rollup-linux-arm64-musl": "4.9.6", - "@rollup/rollup-linux-riscv64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-musl": "4.9.6", - "@rollup/rollup-win32-arm64-msvc": "4.9.6", - "@rollup/rollup-win32-ia32-msvc": "4.9.6", - "@rollup/rollup-win32-x64-msvc": "4.9.6", + "@rollup/rollup-android-arm-eabi": "4.14.0", + "@rollup/rollup-android-arm64": "4.14.0", + "@rollup/rollup-darwin-arm64": "4.14.0", + "@rollup/rollup-darwin-x64": "4.14.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.0", + "@rollup/rollup-linux-arm64-gnu": "4.14.0", + "@rollup/rollup-linux-arm64-musl": "4.14.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.0", + "@rollup/rollup-linux-riscv64-gnu": "4.14.0", + "@rollup/rollup-linux-s390x-gnu": "4.14.0", + "@rollup/rollup-linux-x64-gnu": "4.14.0", + "@rollup/rollup-linux-x64-musl": "4.14.0", + "@rollup/rollup-win32-arm64-msvc": "4.14.0", + "@rollup/rollup-win32-ia32-msvc": "4.14.0", + "@rollup/rollup-win32-x64-msvc": "4.14.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup-plugin-copy": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", - "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", - "dev": true, - "dependencies": { - "@types/fs-extra": "^8.0.1", - "colorette": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "10.0.1", - "is-plain-object": "^3.0.0" - }, - "engines": { - "node": ">=8.3" - } - }, - "node_modules/rollup-plugin-copy/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/rollup-plugin-copy/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup-plugin-copy/node_modules/globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rollup-plugin-copy/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/rollup-plugin-copy/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/rollup-plugin-cssimport": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rollup-plugin-cssimport/-/rollup-plugin-cssimport-1.0.3.tgz", - "integrity": "sha512-55LVDOedJJjknwvPUk2503Sbo5L5NGIBb/N6lgYwPboOBpbhhNOsT3c3ellmz86FwVjUnYyP8Cd/4GapzimI2Q==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1" - } - }, - "node_modules/rollup-plugin-cssimport/node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/rollup-plugin-modify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-modify/-/rollup-plugin-modify-3.0.0.tgz", @@ -16618,20 +18596,47 @@ "transform-ast": "^2.4.4" } }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz", + "integrity": "sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } + "optional": true, + "os": [ + "darwin" + ], + "peer": true }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz", + "integrity": "sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz", + "integrity": "sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true }, "node_modules/run-parallel": { "version": "1.2.0", @@ -16652,6 +18657,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -16659,12 +18665,14 @@ "node_modules/rw": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "license": "MIT", "dependencies": { "mri": "^1.1.0" }, @@ -16673,13 +18681,14 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -16694,18 +18703,23 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16713,35 +18727,24 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dev": true, "dependencies": { "loose-envify": "^1.1.0" } }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -16751,6 +18754,7 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -16775,6 +18779,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -16783,28 +18788,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } + "license": "MIT" }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -16815,11 +18814,45 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -16838,6 +18871,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -16850,6 +18884,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -16859,14 +18894,16 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/short-unique-id": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.0.2.tgz", - "integrity": "sha512-4wZq1VLV4hsEx8guP5bN7XnY8UDsVXtdUDWFMP1gvEieAXolq5fWGKpuua21PRXaLn3OybTKFQNm7JGcHSWu/Q==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.0.3.tgz", + "integrity": "sha512-yhniEILouC0s4lpH0h7rJsfylZdca10W9mDJRAFh3EpcSUanCHGb0R7kcFOIUCZYSAPo0PUD5ZxWQdW0T4xaug==", + "license": "Apache-2.0", "bin": { "short-unique-id": "bin/short-unique-id", "suid": "bin/short-unique-id" @@ -16876,7 +18913,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", - "dev": true, + "license": "MIT", "dependencies": { "commander": "^9.0.0" }, @@ -16892,19 +18929,24 @@ "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || >=14" } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16914,7 +18956,8 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/simple-concat": { "version": "1.0.1", @@ -16934,6 +18977,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "optional": true }, "node_modules/simple-get": { @@ -16954,6 +18998,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "optional": true, "dependencies": { "decompress-response": "^6.0.0", @@ -16965,36 +19010,33 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/smob": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.0.tgz", - "integrity": "sha512-MqR3fVulhjWuRNSMydnTlweu38UhQ0HXM4buStD/S3mc/BzX3CuM9OmhyQpmtYCvoYdl5ris6TI0ZqH355Ymqg==", - "dev": true - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "peer": true, "engines": { @@ -17006,6 +19048,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -17019,9 +19062,9 @@ "dev": true }, "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "dev": true, "funding": { "type": "github", @@ -17033,66 +19076,67 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/stampit": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz", - "integrity": "sha512-pE2org1+ZWQBnIxRPrBM2gVupkuDD0TTNIo1H6GdT/vO82NXli2z8lRE8cu/nBIHrcOCXFBAHpb9ZldrB2/qOA==" + "integrity": "sha512-pE2org1+ZWQBnIxRPrBM2gVupkuDD0TTNIo1H6GdT/vO82NXli2z8lRE8cu/nBIHrcOCXFBAHpb9ZldrB2/qOA==", + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/store2": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", - "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", - "dev": true + "version": "2.14.3", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.3.tgz", + "integrity": "sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg==", + "dev": true, + "license": "MIT" }, "node_modules/storybook": { - "version": "7.6.10", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.10.tgz", - "integrity": "sha512-ypFeGhQTUBBfqSUVZYh7wS5ghn3O2wILCiQc4459SeUpvUn+skcqw/TlrwGSoF5EWjDA7gtRrWDxO3mnlPt5Cw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.1.3.tgz", + "integrity": "sha512-djsH1nPnX3G84hWR/HmofrfiZ8mN7dyP7uDYkR8O2rd/pfZ3fMI6iaKKWL73Z+WGAiK2Ax9oSmaZSGwgS6k3Rg==", "dev": true, "dependencies": { - "@storybook/cli": "7.6.10" + "@storybook/cli": "8.1.3" }, "bin": { "sb": "index.js", @@ -17104,23 +19148,23 @@ } }, "node_modules/storybook-addon-mock": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/storybook-addon-mock/-/storybook-addon-mock-4.3.0.tgz", - "integrity": "sha512-N4Yepagkom0t5jk6ur3wrtGVeOYTlGx9LX6jg8iRhFbhrpfcbr+6XhmAQSE/3FiNQXwHiwdo1Az8MvlzwymcUA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/storybook-addon-mock/-/storybook-addon-mock-5.0.0.tgz", + "integrity": "sha512-AGhfdAsksusJgh/VNcaGbXe1gJIVx8RKuPYMCkmCRyeMAEZggrWcU7nIADZWUJuD477mKUkaBP7I54p+3527Xg==", "dev": true, "dependencies": { - "@storybook/addons": "^7.4.2", - "@storybook/blocks": "^7.4.2", - "@storybook/channels": "^7.4.2", - "@storybook/components": "^7.4.2", - "@storybook/core-events": "^7.4.2", - "@storybook/manager-api": "^7.4.2", - "@storybook/theming": "^7.4.2", + "@storybook/blocks": "^8.0.8", + "@storybook/channels": "^8.0.8", + "@storybook/components": "^8.0.8", + "@storybook/core-events": "^8.0.8", + "@storybook/manager-api": "^8.0.8", + "@storybook/preview-api": "^8.0.8", + "@storybook/theming": "^8.0.8", "mock-xmlhttprequest": "^8.1.0", "path-to-regexp": "^6.2.1", "polished": "^4.2.2", "prop-types": "^15.8.1", - "storybook": "^7.4.2", + "storybook": "^8.0.8", "whatwg-fetch": "^3.6.19" }, "peerDependencies": { @@ -17136,11 +19180,149 @@ } } }, + "node_modules/storybook-addon-mock/node_modules/@storybook/channels": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.8.tgz", + "integrity": "sha512-L3EGVkabv3fweXnykD/GlNUDO5HtwlIfSovC7BF4MmP7662j2/eqlZrJxDojGtbv11XHjWp/UJHUIfKpcHXYjQ==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.0.8", + "@storybook/core-events": "8.0.8", + "@storybook/global": "^5.0.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/client-logger": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.8.tgz", + "integrity": "sha512-a4BKwl9NLFcuRgMyI7S4SsJeLFK0LCQxIy76V6YyrE1DigoXz4nA4eQxdjLf7JVvU0EZFmNSfbVL/bXzzWKNXA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/components": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.0.8.tgz", + "integrity": "sha512-EpBExH4kHWQJSfA8QXJJ5AsLRUGi5X/zWY7ffiYW8rtnBmEnk3T9FpmnyJlY1A8sdd3b1wQ07JGBDHfL1mdELw==", + "dev": true, + "dependencies": { + "@radix-ui/react-slot": "^1.0.2", + "@storybook/client-logger": "8.0.8", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@storybook/theming": "8.0.8", + "@storybook/types": "8.0.8", + "memoizerific": "^1.11.3", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/core-events": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.8.tgz", + "integrity": "sha512-PtuvR7vS4glDEdCfKB4f1k3Vs1C3rTWP2DNbF+IjjPhNLMBznCdzTAPcz+NUIBvpjjGnhKwWikJ0yj931YjSVg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/preview-api": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.8.tgz", + "integrity": "sha512-khgw2mNiBrSZS3KNGQPzjneL3Csh3BOq0yLAtJpT7CRSrI/YjlE7jjcTkKzoxW+UCgvNTnLvsowcuzu82e69fA==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.8", + "@storybook/client-logger": "8.0.8", + "@storybook/core-events": "8.0.8", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.0.8", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/theming": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.0.8.tgz", + "integrity": "sha512-43hkNz7yo8Bl97AO2WbxIGprUqMhUZyK9g8383bd30gSxy9nfND/bdSdcgmA8IokDn8qp37Q4QmxtUZdhjMzZQ==", + "dev": true, + "dependencies": { + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@storybook/client-logger": "8.0.8", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook-addon-mock/node_modules/@storybook/types": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.8.tgz", + "integrity": "sha512-NGsgCsXnWlaZmHenHDgHGs21zhweZACkqTNsEQ7hvsiF08QeiKAdgJLQg3YeGK73h9mFDRP9djprUtJYab6vnQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.8", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/storybook-addon-mock/node_modules/path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/stream-shift": { "version": "1.0.3", @@ -17153,6 +19335,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "devOptional": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -17175,13 +19358,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -17211,6 +19396,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", "integrity": "sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -17228,6 +19414,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -17245,6 +19432,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -17259,6 +19447,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -17273,6 +19462,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -17298,24 +19488,17 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -17325,6 +19508,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -17333,20 +19517,23 @@ } }, "node_modules/style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "license": "MIT" }, "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==", + "license": "MIT" }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -17359,6 +19546,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -17367,38 +19555,39 @@ } }, "node_modules/swagger-client": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.20.2.tgz", - "integrity": "sha512-fjOI/ut7uCeT7CHHNNIa1WIT9SnzKxyoaVnysyuarVpSodpOq6D2loZStBGU4mwpXF+KvatCw2qQk9Ub6fRzZw==", + "version": "3.25.4", + "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.25.4.tgz", + "integrity": "sha512-pq9Zs6yf6Giy5JLnkUSeH+y1AQrhomDCkmVYpMY5Rkx6u70jnyiuRWwkGW6cgsPY+/8N38jRGieoWzJYPPGIuA==", + "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.22.15", - "@swagger-api/apidom-core": ">=0.76.2 <1.0.0", - "@swagger-api/apidom-json-pointer": ">=0.76.2 <1.0.0", - "@swagger-api/apidom-ns-openapi-3-1": ">=0.76.2 <1.0.0", - "@swagger-api/apidom-reference": ">=0.76.2 <1.0.0", - "cookie": "~0.5.0", - "cross-fetch": "^3.1.5", + "@swagger-api/apidom-core": ">=0.90.0 <1.0.0", + "@swagger-api/apidom-error": ">=0.90.0 <1.0.0", + "@swagger-api/apidom-json-pointer": ">=0.90.0 <1.0.0", + "@swagger-api/apidom-ns-openapi-3-1": ">=0.90.0 <1.0.0", + "@swagger-api/apidom-reference": ">=0.90.0 <1.0.0", + "cookie": "~0.6.0", "deepmerge": "~4.3.0", "fast-json-patch": "^3.0.0-1", - "form-data-encoder": "^1.4.3", - "formdata-node": "^4.0.0", "is-plain-object": "^5.0.0", "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "node-abort-controller": "^3.1.1", + "node-fetch-commonjs": "^3.3.2", "qs": "^6.10.2", - "traverse": "~0.6.6", - "url": "~0.11.0" + "traverse": "~0.6.6" } }, "node_modules/swagger-client/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/swagger-client/node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -17407,6 +19596,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -17418,12 +19608,14 @@ "version": "2.0.17", "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause", + "peer": true }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -17442,6 +19634,7 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "devOptional": true, + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -17453,13 +19646,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "devOptional": true + "devOptional": true, + "license": "ISC" }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "devOptional": true, + "license": "MIT", "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -17471,18 +19666,6 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -17494,6 +19677,7 @@ "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", "dev": true, + "license": "MIT", "dependencies": { "memoizerific": "^1.11.3" } @@ -17515,10 +19699,21 @@ "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/temp/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -17539,6 +19734,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/temp/node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -17556,6 +19763,7 @@ "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", "dev": true, + "license": "MIT", "dependencies": { "del": "^6.0.0", "is-stream": "^2.0.0", @@ -17575,6 +19783,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -17583,10 +19792,13 @@ } }, "node_modules/terser": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", - "integrity": "sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==", + "version": "5.28.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", + "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -17604,47 +19816,17 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through2": { "version": "2.0.5", @@ -17687,22 +19869,18 @@ } }, "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==", - "dev": true - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -17712,6 +19890,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -17720,16 +19899,18 @@ } }, "node_modules/tocbot": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.21.1.tgz", - "integrity": "sha512-IfajhBTeg0HlMXu1f+VMbPef05QpDTsZ9X2Yn1+8npdaXsXg/+wrm9Ze1WG5OS1UDC3qJ5EQN/XOZ3gfXjPFCw==", - "dev": true + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.25.0.tgz", + "integrity": "sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA==", + "dev": true, + "license": "MIT" }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } @@ -17737,7 +19918,9 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" }, "node_modules/transform-ast": { "version": "2.4.4", @@ -17754,6 +19937,12 @@ "nanobench": "^2.1.1" } }, + "node_modules/transform-ast/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, "node_modules/transform-ast/node_modules/magic-string": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.23.2.tgz", @@ -17764,9 +19953,13 @@ } }, "node_modules/traverse": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", - "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", + "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17776,6 +19969,7 @@ "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.20.4.tgz", "integrity": "sha512-rjfR5dc4knG3jnJNN/giJ9WOoN1zL/kZyrS0ILh+eqq8RNcIbiXA63JsMEgluug0aNvfQvK4BfCErN1vIzvKog==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "nan": "^2.17.0", @@ -17783,13 +19977,14 @@ } }, "node_modules/tree-sitter-json": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.0.tgz", - "integrity": "sha512-PteOLH+Tx6Bz4ZA/d40/DbkiSXXRM/gKahhHI8hQ1lWNfFvdknnz9k3Mz84ol5srRyLboJ8wp8GSkhZ6ht9EGQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.2.tgz", + "integrity": "sha512-eUxrowp4F1QEGk/i7Sa+Xl8Crlfp7J0AXxX1QdJEQKQYMWhgMbCIgyQvpO3Q0P9oyTrNQxRLlRipDS44a8EtRw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { - "nan": "^2.14.1" + "nan": "^2.18.0" } }, "node_modules/tree-sitter-yaml": { @@ -17797,18 +19992,20 @@ "resolved": "https://registry.npmjs.org/tree-sitter-yaml/-/tree-sitter-yaml-0.5.0.tgz", "integrity": "sha512-POJ4ZNXXSWIG/W4Rjuyg36MkUD4d769YRUGKRqN+sVaj/VCo6Dh6Pkssn1Rtewd5kybx+jT1BWMyWN0CijXnMA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "nan": "^2.14.0" } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -17818,6 +20015,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", "engines": { "node": ">=6.10" } @@ -17827,26 +20025,40 @@ "resolved": "https://registry.npmjs.org/ts-lit-plugin/-/ts-lit-plugin-2.0.2.tgz", "integrity": "sha512-DPXlVxhjWHxg8AyBLcfSYt2JXgpANV1ssxxwjY98o26gD8MzeiM68HFW9c2VeDd1CjoR3w7B/6/uKxwBQe+ioA==", "dev": true, + "license": "MIT", "dependencies": { "lit-analyzer": "^2.0.1", "web-component-analyzer": "^2.0.0" } }, + "node_modules/ts-mixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", + "license": "MIT" + }, + "node_modules/ts-pattern": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.1.2.tgz", + "integrity": "sha512-u+ElKUIWnqisjpRBhv6Y89yNq7Pmz6xL0v7pTSckrVZ0+5Vf32oh/3jmxWl80rAOGcnbBa7fCyeqNdP4yXzWWg==" + }, "node_modules/ts-simple-type": { "version": "2.0.0-next.0", "resolved": "https://registry.npmjs.org/ts-simple-type/-/ts-simple-type-2.0.0-next.0.tgz", "integrity": "sha512-A+hLX83gS+yH6DtzNAhzZbPfU+D9D8lHlTSd7GeoMRBjOt3GRylDqLTYbdmjA4biWvq2xSfpqfIDj2l0OA/BVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ts-toolbelt": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==" + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "license": "Apache-2.0" }, "node_modules/tsconfck": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.0.1.tgz", - "integrity": "sha512-7ppiBlF3UEddCLeI1JRx5m2Ryq+xk4JrZuq4EuYXykipebaq1dV0Fhgr1hb7CkmHt32QSgOZlcqVLEtHBG4/mg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.0.3.tgz", + "integrity": "sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==", "dev": true, "bin": { "tsconfck": "bin/tsconfck.js" @@ -17866,13 +20078,15 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -17887,12 +20101,14 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", "optional": true, "dependencies": { "safe-buffer": "^5.0.1" @@ -17902,9 +20118,9 @@ } }, "node_modules/turnstile-types": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/turnstile-types/-/turnstile-types-1.2.0.tgz", - "integrity": "sha512-cTtNEtCYpcXeXR5AOD0YR0xZpXk1iZeTOuXT5vAGNowGGdgapC+k6m/lOVSkmDOUopZmPtmu311XeULIro4gUA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/turnstile-types/-/turnstile-types-1.2.1.tgz", + "integrity": "sha512-PZFcUDFvPvmmwb885JA/N+8Pg5xNWw/UGMABRb/vI9P8cZ4pLDCpBDzgw7oKQ67DYvboTxNhfTAu93gjX4uNbQ==", "dev": true }, "node_modules/type-check": { @@ -17912,6 +20128,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -17924,6 +20141,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -17936,6 +20154,7 @@ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -17945,29 +20164,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -17977,16 +20199,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -17996,37 +20220,39 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, "node_modules/types-ramda": { - "version": "0.29.4", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.4.tgz", - "integrity": "sha512-XO/820iRsCDwqLjE8XE+b57cVGPyk1h+U9lBGpDWvbEky+NQChvHVwaKM05WnW1c5z3EVQh8NhXFmh2E/1YazQ==", + "version": "0.29.9", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.9.tgz", + "integrity": "sha512-B+VbLtW68J4ncG/rccKaYDhlirKlVH/Izh2JZUfaPJv+3Tl2jbbgYsB1pvole1vXKSgaPlAe/wgEdOnMdAu52A==", + "license": "MIT", "dependencies": { "ts-toolbelt": "^9.6.0" } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -18037,9 +20263,9 @@ } }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", "dev": true }, "node_modules/uglify-js": { @@ -18047,6 +20273,7 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true, + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -18060,6 +20287,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -18074,13 +20302,15 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -18090,6 +20320,7 @@ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, + "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -18103,6 +20334,7 @@ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -18112,15 +20344,29 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, + "license": "MIT", "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -18129,19 +20375,29 @@ } }, "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-is/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, "node_modules/unist-util-stringify-position": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0" }, @@ -18151,14 +20407,14 @@ } }, "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dev": true, "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -18166,24 +20422,37 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dev": true, "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-visit-parents/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/unist-util-visit/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -18193,32 +20462,36 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/unplugin": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.4.0.tgz", - "integrity": "sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.8.0.tgz", + "integrity": "sha512-yGEQsodWICmgt7asHF7QzqDZYeEP9h14vyd9Lul98UnYf29pLZZLwI09z2QdTjwU/FCkum1SRvsK7cx232X8NA==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "chokidar": "^3.5.3", + "acorn": "^8.11.3", + "chokidar": "^3.6.0", "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.5.0" + "webpack-virtual-modules": "^0.6.1" } }, "node_modules/unraw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unraw/-/unraw-3.0.0.tgz", - "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==" + "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==", + "license": "MIT" }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -18242,6 +20515,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -18258,29 +20532,17 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/url": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.2.tgz", - "integrity": "sha512-7yIgNnrST44S7PJ5+jXbdIupfU1nWUdQJBFBeJRclPXiWgCvrSq5Frw8lr/i//n5sqDfzoKmBymMS81l4U/7cg==", - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/use-callback-ref": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", - "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", + "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -18302,6 +20564,8 @@ "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "@juggle/resize-observer": "^3.3.1" }, @@ -18315,6 +20579,7 @@ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", "dev": true, + "license": "MIT", "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" @@ -18337,6 +20602,7 @@ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -18349,21 +20615,28 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -18372,6 +20645,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "license": "MIT", "dependencies": { "dequal": "^2.0.0", "diff": "^5.0.0", @@ -18389,6 +20663,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -18398,6 +20673,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -18408,20 +20684,21 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/vite": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", - "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", + "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", "dev": true, "peer": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.32", - "rollup": "^4.2.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -18469,14 +20746,14 @@ } }, "node_modules/vite-tsconfig-paths": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.1.tgz", - "integrity": "sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", + "integrity": "sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==", "dev": true, "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", - "tsconfck": "^3.0.1" + "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" @@ -18487,10 +20764,27 @@ } } }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", - "integrity": "sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -18505,9 +20799,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.9.tgz", - "integrity": "sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -18522,9 +20816,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.9.tgz", - "integrity": "sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -18539,9 +20833,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.9.tgz", - "integrity": "sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -18556,9 +20850,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.9.tgz", - "integrity": "sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -18573,9 +20867,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.9.tgz", - "integrity": "sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -18590,9 +20884,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.9.tgz", - "integrity": "sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -18607,9 +20901,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.9.tgz", - "integrity": "sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -18624,9 +20918,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.9.tgz", - "integrity": "sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -18641,9 +20935,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.9.tgz", - "integrity": "sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -18658,9 +20952,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.9.tgz", - "integrity": "sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -18675,9 +20969,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.9.tgz", - "integrity": "sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -18692,9 +20986,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.9.tgz", - "integrity": "sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -18709,9 +21003,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.9.tgz", - "integrity": "sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -18726,9 +21020,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.9.tgz", - "integrity": "sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -18743,9 +21037,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.9.tgz", - "integrity": "sha512-JUjpystGFFmNrEHQnIVG8hKwvA2DN5o7RqiO1CVX8EN/F/gkCjkUMgVn6hzScpwnJtl2mPR6I9XV1oW8k9O+0A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -18760,9 +21054,9 @@ } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.9.tgz", - "integrity": "sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -18777,9 +21071,9 @@ } }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.9.tgz", - "integrity": "sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -18794,9 +21088,9 @@ } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.9.tgz", - "integrity": "sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -18811,9 +21105,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.9.tgz", - "integrity": "sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -18828,9 +21122,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.9.tgz", - "integrity": "sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -18845,9 +21139,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz", - "integrity": "sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -18862,9 +21156,9 @@ } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.9.tgz", - "integrity": "sha512-U9CHtKSy+EpPsEBa+/A2gMs/h3ylBC0H0KSqIg7tpztHerLi6nrrcoUJAkNCEPumx8yJ+Byic4BVwHgRbN0TBg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "peer": true, @@ -18875,28 +21169,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.9", - "@esbuild/android-arm64": "0.19.9", - "@esbuild/android-x64": "0.19.9", - "@esbuild/darwin-arm64": "0.19.9", - "@esbuild/darwin-x64": "0.19.9", - "@esbuild/freebsd-arm64": "0.19.9", - "@esbuild/freebsd-x64": "0.19.9", - "@esbuild/linux-arm": "0.19.9", - "@esbuild/linux-arm64": "0.19.9", - "@esbuild/linux-ia32": "0.19.9", - "@esbuild/linux-loong64": "0.19.9", - "@esbuild/linux-mips64el": "0.19.9", - "@esbuild/linux-ppc64": "0.19.9", - "@esbuild/linux-riscv64": "0.19.9", - "@esbuild/linux-s390x": "0.19.9", - "@esbuild/linux-x64": "0.19.9", - "@esbuild/netbsd-x64": "0.19.9", - "@esbuild/openbsd-x64": "0.19.9", - "@esbuild/sunos-x64": "0.19.9", - "@esbuild/win32-arm64": "0.19.9", - "@esbuild/win32-ia32": "0.19.9", - "@esbuild/win32-x64": "0.19.9" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/vscode-css-languageservice": { @@ -18904,6 +21199,7 @@ "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-4.3.0.tgz", "integrity": "sha512-BkQAMz4oVHjr0oOAz5PdeE72txlLQK7NIwzmclfr+b6fj6I8POwB+VoXvrZLTbWt9hWRgfvgiQRkh5JwrjPJ5A==", "dev": true, + "license": "MIT", "dependencies": { "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "3.16.0-next.2", @@ -18916,6 +21212,7 @@ "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-3.1.0.tgz", "integrity": "sha512-QAyRHI98bbEIBCqTzZVA0VblGU40na0txggongw5ZgTj9UVsVk5XbLT16O9OTcbqBGSqn0oWmFDNjK/XGIDcqg==", "dev": true, + "license": "MIT", "dependencies": { "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "3.16.0-next.2", @@ -18924,48 +21221,45 @@ } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", - "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==", - "dev": true + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "dev": true, + "license": "MIT" }, "node_modules/vscode-languageserver-types": { "version": "3.16.0-next.2", "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz", "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vscode-nls": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vscode-uri": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -18988,6 +21282,7 @@ "resolved": "https://registry.npmjs.org/web-component-analyzer/-/web-component-analyzer-2.0.0.tgz", "integrity": "sha512-UEvwfpD+XQw99sLKiH5B1T4QwpwNyWJxp59cnlRwFfhUW6JsQpw5jMeMwi7580sNou8YL3kYoS7BWLm+yJ/jVQ==", "dev": true, + "license": "MIT", "dependencies": { "fast-glob": "^3.2.2", "ts-simple-type": "2.0.0-next.0", @@ -19004,6 +21299,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19013,28 +21309,32 @@ } }, "node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 8" } }, "node_modules/web-tree-sitter": { "version": "0.20.3", "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.3.tgz", "integrity": "sha512-zKGJW9r23y3BcJusbgvnOH2OYAW40MXAOi9bi3Gcc7T4Gms9WWgXF8m6adsJWpGJEhgOzCrfiz1IzKowJWrtYw==", + "license": "MIT", "optional": true }, "node_modules/web-worker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", + "license": "Apache-2.0" }, "node_modules/webcomponent-qr-code": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/webcomponent-qr-code/-/webcomponent-qr-code-1.2.0.tgz", "integrity": "sha512-1qEJ70HpiO0GbPy9T6XCtHn+RyI3awtpU88BBPQkhefwuRKg408X6z7mJeQxBnKkFQSv3ZWwmlgMvIjIO3RGOg==", + "license": "MIT", "dependencies": { "qrjs": "^0.2.0" } @@ -19042,33 +21342,40 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/webpack-virtual-modules": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", - "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", - "dev": true + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", + "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", + "dev": true, + "license": "MIT" }, "node_modules/whatwg-fetch": { - "version": "3.6.19", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", - "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==", - "dev": true + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "dev": true, + "license": "MIT" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -19079,6 +21386,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -19094,6 +21402,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -19106,16 +21415,17 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -19128,13 +21438,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -19185,6 +21497,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -19199,26 +21512,26 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "devOptional": true + "devOptional": true, + "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "dependencies": { + "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "signal-exit": "^3.0.2" } }, "node_modules/ws": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", - "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -19239,6 +21552,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml-but-prettier/-/xml-but-prettier-1.0.1.tgz", "integrity": "sha512-C2CJaadHrZTqESlH03WOyw0oZTtoy2uEg6dSDF6YRg+9GnYNub53RRemLpnvtbHDFelxMx4LajiFsYeR6XJHgQ==", + "license": "MIT", "dependencies": { "repeat-string": "^1.5.2" } @@ -19248,6 +21562,7 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4" } @@ -19257,6 +21572,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -19265,12 +21581,16 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", + "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -19280,6 +21600,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -19298,25 +21619,17 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/web/package.json b/web/package.json index 0d11070284..765f7bceb4 100644 --- a/web/package.json +++ b/web/package.json @@ -5,135 +5,133 @@ "license": "MIT", "scripts": { "extract-locales": "lit-localize extract", - "build-locales": "run-s build-locales:build", + "build-locales": "node scripts/build-locales.mjs", "build-locales:build": "lit-localize build", "build-locales:repair": "prettier --write ./src/locale-codes.ts", - "rollup:build": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c ./rollup.config.mjs", - "rollup:build-proxy": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c ./rollup.proxy.mjs", - "rollup:watch": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c -w", - "build": "run-s build-locales rollup:build", - "build-proxy": "run-s build-locales rollup:build-proxy", - "watch": "run-s build-locales rollup:watch", - "lint": "eslint . --max-warnings 0 --fix", - "lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[M?][M?]' | cut -c8- | grep -E '\\.(ts|js|tsx|jsx)$') ", - "lint:spelling": "codespell -D - -D ../.github/codespell-dictionary.txt -I ../.github/codespell-words.txt -S './src/locales/**' ./src -s", + "esbuild:build": "node build.mjs", + "esbuild:build-proxy": "node build.mjs --proxy", + "esbuild:watch": "node build.mjs --watch", + "build": "run-s build-locales esbuild:build", + "build-proxy": "run-s build-locales esbuild:build-proxy", + "watch": "run-s build-locales esbuild:watch", + "lint": "cross-env NODE_OPTIONS='--max_old_space_size=65536' eslint . --max-warnings 0 --fix", + "lint:precommit": "cross-env NODE_OPTIONS='--max_old_space_size=65536' node scripts/eslint-precommit.mjs", + "lint:spelling": "node scripts/check-spelling.mjs", "lit-analyse": "lit-analyzer src", - "precommit": "run-s tsc lit-analyse lint:precommit lint:spelling prettier", + "precommit": "npm-run-all --parallel tsc lit-analyse lint:spelling --sequential lint:precommit prettier", "prequick": "run-s tsc:execute lit-analyse lint:precommit lint:spelling", "prettier-check": "prettier --check .", "prettier": "prettier --write .", - "pseudolocalize:build-extract-script": "cd scripts && tsc --esModuleInterop --module es2020 --moduleResolution 'node' pseudolocalize.ts && mv pseudolocalize.js pseudolocalize.mjs", - "pseudolocalize:extract": "node scripts/pseudolocalize.mjs", - "pseudolocalize": "run-s pseudolocalize:build-extract-script pseudolocalize:extract", + "pseudolocalize": "node scripts/pseudolocalize.mjs", "tsc:execute": "tsc --noEmit -p .", "tsc": "run-s build-locales tsc:execute", "storybook": "storybook dev -p 6006", - "storybook:build": "cross-env NODE_OPTIONS='--max_old_space_size=4096' storybook build", - "storybook:build-import-map": "run-s storybook:build-import-map-script storybook:run-import-map-script", - "storybook:build-import-map-script": "cd scripts && tsc --esModuleInterop --module es2020 --target es2020 --moduleResolution 'node' build-storybook-import-maps.ts && mv build-storybook-import-maps.js build-storybook-import-maps.mjs", - "storybook:run-import-map-script": "node scripts/build-storybook-import-maps.mjs" + "storybook:build": "cross-env NODE_OPTIONS='--max_old_space_size=8192' storybook build", + "storybook:build-import-map": "node scripts/build-storybook-import-maps.mjs" }, "dependencies": { - "@codemirror/lang-html": "^6.4.8", - "@codemirror/lang-javascript": "^6.2.1", - "@codemirror/lang-python": "^6.1.3", - "@codemirror/lang-xml": "^6.0.2", - "@codemirror/legacy-modes": "^6.3.3", + "@codemirror/lang-html": "^6.4.9", + "@codemirror/lang-javascript": "^6.2.2", + "@codemirror/lang-python": "^6.1.6", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/legacy-modes": "^6.4.0", "@codemirror/theme-one-dark": "^6.1.2", - "@formatjs/intl-listformat": "^7.5.5", - "@fortawesome/fontawesome-free": "^6.5.1", - "@goauthentik/api": "^2023.10.6-1706113408", - "@lit-labs/context": "^0.4.0", + "@formatjs/intl-listformat": "^7.5.7", + "@fortawesome/fontawesome-free": "^6.5.2", + "@goauthentik/api": "^2024.4.2-1716550354", "@lit-labs/task": "^3.1.0", - "@lit/localize": "^0.11.4", - "@open-wc/lit-helpers": "^0.6.0", - "@patternfly/elements": "^2.4.0", + "@lit/context": "^1.1.1", + "@lit/localize": "^0.12.1", + "@lit/reactive-element": "^2.0.4", + "@open-wc/lit-helpers": "^0.7.0", + "@patternfly/elements": "^3.0.1", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.95.0", + "@sentry/browser": "^8.4.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", - "chart.js": "^4.4.1", + "chart.js": "^4.4.3", "chartjs-adapter-moment": "^1.0.1", "codemirror": "^6.0.1", "construct-style-sheets-polyfill": "^3.1.0", - "core-js": "^3.35.1", - "country-flag-icons": "^1.5.9", + "core-js": "^3.37.1", + "country-flag-icons": "^1.5.11", "fuse.js": "^7.0.0", "guacamole-common-js": "^1.5.0", - "lit": "^2.8.0", - "mermaid": "^10.7.0", + "lit": "^3.1.3", + "md-front-matter": "^1.0.4", + "mermaid": "^10.9.1", "rapidoc": "^9.3.4", - "style-mod": "^4.1.0", + "showdown": "^2.1.0", + "style-mod": "^4.1.2", + "ts-pattern": "^5.1.2", "webcomponent-qr-code": "^1.2.0", - "yaml": "^2.3.4" + "yaml": "^2.4.2" }, "devDependencies": { - "@babel/core": "^7.23.7", + "@babel/core": "^7.24.5", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.23.7", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-runtime": "^7.23.7", - "@babel/preset-env": "^7.23.8", - "@babel/preset-typescript": "^7.23.3", + "@babel/plugin-proposal-decorators": "^7.24.1", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", + "@babel/plugin-transform-runtime": "^7.24.3", + "@babel/preset-env": "^7.24.5", + "@babel/preset-typescript": "^7.24.1", "@hcaptcha/types": "^1.0.3", - "@jackfranklin/rollup-plugin-markdown": "^0.4.0", "@jeysal/storybook-addon-css-user-preferences": "^0.2.0", - "@lit/localize-tools": "^0.7.1", - "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-node-resolve": "^15.2.3", + "@lit/localize-tools": "^0.7.2", "@rollup/plugin-replace": "^5.0.5", - "@rollup/plugin-terser": "^0.4.4", - "@rollup/plugin-typescript": "^11.1.6", - "@spotlightjs/spotlight": "^1.2.7", - "@storybook/addon-essentials": "^7.6.10", - "@storybook/addon-links": "^7.6.10", - "@storybook/api": "^7.6.10", - "@storybook/blocks": "^7.6.4", - "@storybook/manager-api": "^7.6.10", - "@storybook/web-components": "^7.6.10", - "@storybook/web-components-vite": "^7.6.10", + "@spotlightjs/spotlight": "^1.2.17", + "@storybook/addon-essentials": "^8.1.3", + "@storybook/addon-links": "^8.1.3", + "@storybook/api": "^7.6.17", + "@storybook/blocks": "^8.0.8", + "@storybook/manager-api": "^8.1.3", + "@storybook/web-components": "^8.1.3", + "@storybook/web-components-vite": "^8.1.3", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/chart.js": "^2.9.41", "@types/codemirror": "5.60.15", - "@types/grecaptcha": "^3.0.7", + "@types/grecaptcha": "^3.0.9", "@types/guacamole-common-js": "1.5.2", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@types/showdown": "^2.0.6", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "babel-plugin-macros": "^3.1.0", "babel-plugin-tsconfig-paths": "^1.0.3", + "chokidar": "^3.6.0", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "esbuild": "^0.21.3", + "eslint": "^8.57.0", "eslint-config-google": "^0.14.0", "eslint-plugin-custom-elements": "0.0.8", "eslint-plugin-lit": "^1.11.0", - "eslint-plugin-sonarjs": "^0.23.0", - "eslint-plugin-storybook": "^0.6.15", + "eslint-plugin-sonarjs": "^0.25.1", + "eslint-plugin-storybook": "^0.8.0", + "github-slugger": "^2.0.0", + "glob": "^10.4.0", "lit-analyzer": "^2.0.3", "npm-run-all": "^4.1.5", - "prettier": "^3.2.4", + "prettier": "^3.2.5", "pseudolocale": "^2.0.0", - "pyright": "=1.1.338", "react": "^18.2.0", - "react-dom": "^18.2.0", - "rollup": "^4.9.6", - "rollup-plugin-copy": "^3.5.0", - "rollup-plugin-cssimport": "^1.0.3", + "react-dom": "^18.3.1", "rollup-plugin-modify": "^3.0.0", "rollup-plugin-postcss-lit": "^2.1.0", - "storybook": "^7.6.10", - "storybook-addon-mock": "^4.3.0", + "storybook": "^8.1.3", + "storybook-addon-mock": "^5.0.0", "ts-lit-plugin": "^2.0.2", "tslib": "^2.6.2", - "turnstile-types": "^1.2.0", - "typescript": "^5.3.3", - "vite-tsconfig-paths": "^4.3.1" + "turnstile-types": "^1.2.1", + "typescript": "^5.4.5", + "vite-tsconfig-paths": "^4.3.2" }, "optionalDependencies": { - "@esbuild/darwin-arm64": "^0.19.12", + "@esbuild/darwin-arm64": "^0.21.3", "@esbuild/linux-amd64": "^0.18.11", - "@esbuild/linux-arm64": "^0.19.12" + "@esbuild/linux-arm64": "^0.21.3", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0" }, "engines": { "node": ">=20" diff --git a/web/rollup.config.mjs b/web/rollup.config.mjs deleted file mode 100644 index c4139e13e4..0000000000 --- a/web/rollup.config.mjs +++ /dev/null @@ -1,192 +0,0 @@ -import markdown from "@jackfranklin/rollup-plugin-markdown"; -import babel from "@rollup/plugin-babel"; -import commonjs from "@rollup/plugin-commonjs"; -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import replace from "@rollup/plugin-replace"; -import terser from "@rollup/plugin-terser"; -import { cwd } from "process"; -import copy from "rollup-plugin-copy"; -import cssimport from "rollup-plugin-cssimport"; - -// https://github.com/d3/d3-interpolate/issues/58 -const IGNORED_WARNINGS = /Circular dependency(.*d3-[interpolate|selection])|(.*@lit\/localize.*)/; - -const extensions = [".js", ".jsx", ".ts", ".tsx"]; - -export const resources = [ - { - src: "node_modules/@patternfly/patternfly/patternfly.min.css", - dest: "dist/", - }, - { src: "src/common/styles/*", dest: "dist/" }, - { src: "src/custom.css", dest: "dist/" }, - - { - src: "node_modules/@patternfly/patternfly/assets/*", - dest: "dist/assets/", - }, - { src: "src/assets/*", dest: "dist/assets" }, - { src: "./icons/*", dest: "dist/assets/icons" }, -]; - -// eslint-disable-next-line no-undef -export const isProdBuild = process.env.NODE_ENV === "production"; -// eslint-disable-next-line no-undef -export const apiBasePath = process.env.AK_API_BASE_PATH || ""; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function manualChunks(id) { - if (id.endsWith(".md")) { - return "docs"; - } - if (id.includes("@goauthentik/api")) { - return "api"; - } - if (id.includes("locales")) { - const parts = id.split("/"); - const file = parts[parts.length - 1]; - return "locale-" + file.replace(".ts", ""); - } - if (id.includes("node_modules")) { - if (id.includes("codemirror")) { - return "vendor-cm"; - } - return "vendor"; - } -} - -export const defaultOptions = { - plugins: [ - cssimport(), - markdown(), - nodeResolve({ extensions, browser: true }), - commonjs(), - babel({ - extensions, - babelHelpers: "runtime", - include: ["src/**/*"], - }), - replace({ - "process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"), - "process.env.CWD": JSON.stringify(cwd()), - "process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath), - "preventAssignment": true, - }), - isProdBuild && terser(), - ].filter((p) => p), - watch: { - clearScreen: false, - }, - preserveEntrySignatures: "strict", - cache: true, - context: "window", - onwarn: function (warning, warn) { - if (IGNORED_WARNINGS.test(warning)) { - return; - } - if (warning.code === "UNRESOLVED_IMPORT") { - throw Object.assign(new Error(), warning); - } - warn(warning); - }, -}; - -// Polyfills (imported first) -export const POLY = { - input: "./src/polyfill/poly.ts", - output: [ - { - format: "iife", - file: "dist/poly.js", - sourcemap: true, - }, - ], - cache: true, - plugins: [ - cssimport(), - nodeResolve({ browser: true }), - commonjs(), - isProdBuild && terser(), - copy({ - targets: [...resources], - copyOnce: false, - }), - ].filter((p) => p), -}; - -export const standalone = ["api-browser", "loading"].map((input) => { - return { - input: `./src/standalone/${input}`, - output: [ - { - format: "es", - dir: `dist/standalone/${input}`, - sourcemap: true, - manualChunks: manualChunks, - }, - ], - ...defaultOptions, - }; -}); - -export const enterprise = ["rac"].map((input) => { - return { - input: `./src/enterprise/${input}`, - output: [ - { - format: "es", - dir: `dist/enterprise/${input}`, - sourcemap: true, - manualChunks: manualChunks, - }, - ], - ...defaultOptions, - }; -}); - -export default [ - POLY, - // Standalone - ...standalone, - // Flow interface - { - input: "./src/flow/FlowInterface.ts", - output: [ - { - format: "es", - dir: "dist/flow", - sourcemap: true, - manualChunks: manualChunks, - }, - ], - ...defaultOptions, - }, - // Admin interface - { - input: "./src/admin/AdminInterface/AdminInterface.ts", - output: [ - { - format: "es", - dir: "dist/admin", - sourcemap: true, - manualChunks: manualChunks, - }, - ], - ...defaultOptions, - }, - // User interface - { - input: "./src/user/UserInterface.ts", - output: [ - { - format: "es", - dir: "dist/user", - sourcemap: true, - manualChunks: manualChunks, - }, - ], - ...defaultOptions, - }, - // Enterprise - ...enterprise, -]; diff --git a/web/rollup.proxy.mjs b/web/rollup.proxy.mjs deleted file mode 100644 index feef356040..0000000000 --- a/web/rollup.proxy.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { POLY, standalone } from "./rollup.config.mjs"; - -export default [POLY, ...standalone]; diff --git a/web/scripts/build-locales.mjs b/web/scripts/build-locales.mjs new file mode 100644 index 0000000000..de8febbefa --- /dev/null +++ b/web/scripts/build-locales.mjs @@ -0,0 +1,67 @@ +import { spawnSync } from "child_process"; +import fs from "fs"; +import path from "path"; +import process from "process"; + +const localizeRules = JSON.parse(fs.readFileSync("./lit-localize.json", "utf-8")); + +function compareXlfAndSrc(loc) { + const xlf = path.join("./xliff", `${loc}.xlf`); + const src = path.join("./src/locales", `${loc}.ts`); + + // Returns false if: the expected XLF file doesn't exist, The expected + // generated file doesn't exist, or the XLF file is newer (has a higher date) + // than the generated file. The missing XLF file is important enough it + // generates a unique error message and halts the build. + + try { + var xlfStat = fs.statSync(xlf); + } catch (_error) { + console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`); + process.exit(1); + } + + try { + var srcStat = fs.statSync(src); + } catch (_error) { + return false; + } + + // if the xlf is newer (greater) than src, it's out of date. + if (xlfStat.mtimeMs > srcStat.mtimeMs) { + return false; + } + return true; +} + +// For all the expected files, find out if any aren't up-to-date. + +const upToDate = localizeRules.targetLocales.reduce( + (acc, loc) => acc && compareXlfAndSrc(loc), + true, +); + +if (!upToDate) { + const status = spawnSync("npm", ["run", "build-locales:build"], { encoding: "utf8" }); + + // Count all the missing message warnings + const counts = status.stderr.split("\n").reduce((acc, line) => { + const match = /^([\w-]+) message/.exec(line); + if (!match) { + return acc; + } + acc.set(match[1], (acc.get(match[1]) || 0) + 1); + return acc; + }, new Map()); + + const locales = Array.from(counts.keys()); + locales.sort(); + + const report = locales + .map((locale) => `Locale '${locale}' has ${counts.get(locale)} missing translations`) + .join("\n"); + + console.log(`Translation tables rebuilt.\n${report}\n`); +} + +console.log("Locale ./src is up-to-date"); diff --git a/web/scripts/build-storybook-import-maps.ts b/web/scripts/build-storybook-import-maps.mjs similarity index 79% rename from web/scripts/build-storybook-import-maps.ts rename to web/scripts/build-storybook-import-maps.mjs index 6789fda74e..dbf94c200a 100644 --- a/web/scripts/build-storybook-import-maps.ts +++ b/web/scripts/build-storybook-import-maps.mjs @@ -5,13 +5,12 @@ import { fileURLToPath } from "url"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); // eslint-disable-next-line @typescript-eslint/no-explicit-any -function* walkFilesystem(dir: string): Generator { +function* walkFilesystem(dir) { const openeddir = fs.opendirSync(dir); if (!openeddir) { return; } - - let d: fs.Dirent | null; + let d; while ((d = openeddir?.readSync())) { if (!d) { break; @@ -24,13 +23,14 @@ function* walkFilesystem(dir: string): Generator { } const import_re = /^(import \w+ from .*\.css)";/; -function extractImportLinesFromFile(path: string) { + +function extractImportLinesFromFile(path) { const source = fs.readFileSync(path, { encoding: "utf8", flag: "r" }); const lines = source?.split("\n") ?? []; return lines.filter((l) => import_re.test(l)); } -function createOneImportLine(line: string) { +function createOneImportLine(line) { const importMatch = import_re.exec(line); if (!importMatch) { throw new Error("How did an unmatchable line get here?"); @@ -43,15 +43,16 @@ function createOneImportLine(line: string) { } const isSourceFile = /\.ts$/; + function getTheSourceFiles() { return Array.from(walkFilesystem(path.join(__dirname, "..", "src"))).filter((path) => isSourceFile.test(path), ); } -function getTheImportLines(importPaths: string[]) { - const importLines: string[] = importPaths.reduce( - (acc: string[], path) => [...acc, extractImportLinesFromFile(path)].flat(), +function getTheImportLines(importPaths) { + const importLines = importPaths.reduce( + (acc, path) => [...acc, extractImportLinesFromFile(path)].flat(), [], ); const uniqueImportLines = new Set(importLines); @@ -63,8 +64,7 @@ function getTheImportLines(importPaths: string[]) { const importPaths = getTheSourceFiles(); const importLines = getTheImportLines(importPaths); -const outputFile = ` -// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND. +const outputFile = `// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND. // // This file is generated by the build-storybook-import-maps script in the UI's base directory. // This is a *hack* to work around an inconsistency in the way rollup, vite, and storybook @@ -77,8 +77,10 @@ const rawCssImportMaps = [ ${importLines.map(createOneImportLine).join("\n")} ]; -const cssImportMaps = rawCssImportMaps.reduce((acc, line) => ( -{...acc, [line]: line.replace(/\\.css/, ".css?inline")}), {}); +const cssImportMaps = rawCssImportMaps.reduce( + (acc, line) => ({ ...acc, [line]: line.replace(/\\.css/, ".css?inline") }), + {}, +); export { cssImportMaps }; export default cssImportMaps; diff --git a/web/scripts/check-spelling.mjs b/web/scripts/check-spelling.mjs new file mode 100644 index 0000000000..0633515956 --- /dev/null +++ b/web/scripts/check-spelling.mjs @@ -0,0 +1,15 @@ +import { execSync } from "child_process"; +import path from "path"; + +const projectRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf8" }).replace( + "\n", + "", +); +const cmd = [ + "codespell -D -", + `-D ${path.join(projectRoot, ".github/codespell-dictionary.txt")}`, + `-I ${path.join(projectRoot, ".github/codespell-words.txt")}`, + "-S './src/locales/**' ./src -s", +].join(" "); + +console.log(execSync(cmd, { encoding: "utf8" })); diff --git a/web/scripts/eslint-precommit.mjs b/web/scripts/eslint-precommit.mjs new file mode 100644 index 0000000000..c65f953e21 --- /dev/null +++ b/web/scripts/eslint-precommit.mjs @@ -0,0 +1,76 @@ +import { execFileSync } from "child_process"; +import { ESLint } from "eslint"; +import path from "path"; +import process from "process"; + +// Code assumes this script is in the './web/scripts' folder. +const projectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], { + encoding: "utf8", +}).replace("\n", ""); +process.chdir(path.join(projectRoot, "./web")); + +const eslintConfig = { + overrideConfig: { + env: { + browser: true, + es2021: true, + }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:lit/recommended", + "plugin:custom-elements/recommended", + "plugin:storybook/recommended", + "plugin:sonarjs/recommended", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 12, + sourceType: "module", + }, + plugins: ["@typescript-eslint", "lit", "custom-elements", "sonarjs"], + rules: { + "indent": "off", + "linebreak-style": ["error", "unix"], + "quotes": ["error", "double", { avoidEscape: true }], + "semi": ["error", "always"], + "@typescript-eslint/ban-ts-comment": "off", + "sonarjs/cognitive-complexity": ["error", 9], + "sonarjs/no-duplicate-string": "off", + "sonarjs/no-nested-template-literals": "off", + }, + }, +}; + +const porcelainV1 = /^(..)\s+(.*$)/; +const gitStatus = execFileSync("git", ["status", "--porcelain", "."], { encoding: "utf8" }); + +const statuses = gitStatus.split("\n").reduce((acc, line) => { + const match = porcelainV1.exec(line.replace("\n")); + if (!match) { + return acc; + } + const [status, path] = Array.from(match).slice(1, 3); + return [...acc, [status, path.split("\x00")[0]]]; +}, []); + +const isModified = /^(M|\?|\s)(M|\?|\s)/; +const modified = (s) => isModified.test(s); + +const isCheckable = /\.(ts|js|mjs)$/; +const checkable = (s) => isCheckable.test(s); + +const updated = statuses.reduce( + (acc, [status, filename]) => + modified(status) && checkable(filename) ? [...acc, path.join(projectRoot, filename)] : acc, + [], +); + +const eslint = new ESLint(eslintConfig); +const results = await eslint.lintFiles(updated); +const formatter = await eslint.loadFormatter("stylish"); +const resultText = formatter.format(results); +const errors = results.reduce((acc, result) => acc + result.errorCount, 0); + +console.log(resultText); +process.exit(errors > 1 ? 1 : 0); diff --git a/web/scripts/pseudolocalize.ts b/web/scripts/pseudolocalize.mjs similarity index 62% rename from web/scripts/pseudolocalize.ts rename to web/scripts/pseudolocalize.mjs index 308632ff94..d0495f15c8 100644 --- a/web/scripts/pseudolocalize.ts +++ b/web/scripts/pseudolocalize.mjs @@ -4,16 +4,12 @@ import pseudolocale from "pseudolocale"; import { fileURLToPath } from "url"; import { makeFormatter } from "@lit/localize-tools/lib/formatters/index.js"; -import type { Message, ProgramMessage } from "@lit/localize-tools/lib/messages.d.ts"; import { sortProgramMessages } from "@lit/localize-tools/lib/messages.js"; import { TransformLitLocalizer } from "@lit/localize-tools/lib/modes/transform.js"; -import type { Config } from "@lit/localize-tools/lib/types/config.d.ts"; -import type { Locale } from "@lit/localize-tools/lib/types/locale.d.ts"; -import type { TransformOutputConfig } from "@lit/localize-tools/lib/types/modes.d.ts"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); -const pseudoLocale: Locale = "pseudo-LOCALE" as Locale; -const targetLocales: Locale[] = [pseudoLocale]; +const pseudoLocale = "pseudo-LOCALE"; +const targetLocales = [pseudoLocale]; const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize.json"), "utf-8")); // Need to make some internal specifications to satisfy the transformer. It doesn't actually matter @@ -21,27 +17,28 @@ const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize // is in their common parent class, but I had to pick one. Everything else here is just pure // exploitation of the lit/localize-tools internals. -const config: Config = { +const config = { ...baseConfig, baseDir: path.join(__dirname, ".."), targetLocales, output: { - ...baseConfig, + ...baseConfig.output, mode: "transform", }, - resolve: (path: string) => path, -} as Config; + resolve: (path) => path, +}; -const pseudoMessagify = (message: ProgramMessage) => ({ +const pseudoMessagify = (message) => ({ name: message.name, contents: message.contents.map((content) => typeof content === "string" ? pseudolocale(content, { prepend: "", append: "" }) : content, ), }); -const localizer = new TransformLitLocalizer(config as Config & { output: TransformOutputConfig }); -const { messages } = localizer.extractSourceMessages(); +const localizer = new TransformLitLocalizer(config); +const messages = localizer.extractSourceMessages().messages; const translations = messages.map(pseudoMessagify); const sorted = sortProgramMessages([...messages]); const formatter = makeFormatter(config); -formatter.writeOutput(sorted, new Map([[pseudoLocale, translations]])); + +formatter.writeOutput(sorted, new Map([[pseudoLocale, translations]])); diff --git a/web/src/admin/AdminInterface/AdminInterface.ts b/web/src/admin/AdminInterface/AdminInterface.ts index 0f1a59ccd0..dab187f8d9 100644 --- a/web/src/admin/AdminInterface/AdminInterface.ts +++ b/web/src/admin/AdminInterface/AdminInterface.ts @@ -7,7 +7,7 @@ import { import { configureSentry } from "@goauthentik/common/sentry"; import { me } from "@goauthentik/common/users"; import { WebsocketClient } from "@goauthentik/common/ws"; -import { Interface } from "@goauthentik/elements/Interface"; +import { EnterpriseAwareInterface } from "@goauthentik/elements/Interface"; import "@goauthentik/elements/ak-locale-context"; import "@goauthentik/elements/enterprise/EnterpriseStatusBanner"; import "@goauthentik/elements/messages/MessageContainer"; @@ -33,7 +33,7 @@ import { AdminApi, SessionUser, UiThemeEnum, Version } from "@goauthentik/api"; import "./AdminSidebar"; @customElement("ak-interface-admin") -export class AdminInterface extends Interface { +export class AdminInterface extends EnterpriseAwareInterface { @property({ type: Boolean }) notificationDrawerOpen = getURLParam("notificationDrawerOpen", false); diff --git a/web/src/admin/AdminInterface/AdminSidebar.ts b/web/src/admin/AdminInterface/AdminSidebar.ts index eb860dd5b6..b4c0d7edc9 100644 --- a/web/src/admin/AdminInterface/AdminSidebar.ts +++ b/web/src/admin/AdminInterface/AdminSidebar.ts @@ -122,7 +122,7 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) { ["/events/log", msg("Logs"), [`^/events/log/(?${UUID_REGEX})$`]], ["/events/rules", msg("Notification Rules")], ["/events/transports", msg("Notification Transports")]]], - [null, msg("Customisation"), null, [ + [null, msg("Customization"), null, [ ["/policy/policies", msg("Policies")], ["/core/property-mappings", msg("Property Mappings")], ["/blueprints/instances", msg("Blueprints")], @@ -166,7 +166,7 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) { ${this.renderNewVersionMessage()} ${this.renderImpersonationMessage()} ${map(sidebarContent, renderOneSidebarItem)} - ${this.renderEnterpriseMessage()} + ${this.renderEnterpriseMenu()} `; } @@ -199,7 +199,7 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) { : nothing; } - renderEnterpriseMessage() { + renderEnterpriseMenu() { return this.can(CapabilitiesEnum.IsEnterprise) ? html` diff --git a/web/src/admin/admin-overview/AdminOverviewPage.ts b/web/src/admin/admin-overview/AdminOverviewPage.ts index 9b79f5334d..d24d17814d 100644 --- a/web/src/admin/admin-overview/AdminOverviewPage.ts +++ b/web/src/admin/admin-overview/AdminOverviewPage.ts @@ -19,6 +19,7 @@ import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFDivider from "@patternfly/patternfly/components/Divider/divider.css"; import PFList from "@patternfly/patternfly/components/List/list.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; @@ -41,15 +42,12 @@ export class AdminOverviewPage extends AKElement { PFPage, PFContent, PFList, + PFDivider, css` - .row-divider { - margin-top: -4px; - margin-bottom: -4px; + .pf-l-grid__item { + height: 100%; } - .graph-container { - height: 20em; - } - .big-graph-container { + .pf-l-grid__item.big-graph-container { height: 35em; } .card-container { @@ -81,10 +79,10 @@ export class AdminOverviewPage extends AKElement {
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
{ --pf-c-card__title--FontSize: var(--pf-global--FontSize--md); --pf-c-card__title--FontWeight: var(--pf-global--FontWeight--bold); } + * { + word-break: break-all; + } `, ); } @@ -71,7 +75,8 @@ export class RecentEventsCard extends Table { html` ${item.app}`, EventUser(item), - html`${item.created?.toLocaleString()}`, + html`
${getRelativeTime(item.created)}
+ ${item.created.toLocaleString()}`, html`
${item.clientIp || msg("-")}
${EventGeo(item)}`, html`${item.brand?.name || msg("-")}`, diff --git a/web/src/admin/admin-overview/cards/VersionStatusCard.ts b/web/src/admin/admin-overview/cards/VersionStatusCard.ts index 01689aede7..a8c94cc377 100644 --- a/web/src/admin/admin-overview/cards/VersionStatusCard.ts +++ b/web/src/admin/admin-overview/cards/VersionStatusCard.ts @@ -31,9 +31,15 @@ export class VersionStatusCard extends AdminStatusCard { message: html`${msg(str`${value.versionLatest} is available!`)}`, }); } + if (value.versionLatestValid) { + return Promise.resolve({ + icon: "fa fa-check-circle pf-m-success", + message: html`${msg("Up-to-date!")}`, + }); + } return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success", - message: html`${msg("Up-to-date!")}`, + icon: "fa fa-question-circle", + message: html`${msg("Latest version unknown")}`, }); } diff --git a/web/src/admin/admin-overview/charts/AdminLoginAuthorizeChart.ts b/web/src/admin/admin-overview/charts/AdminLoginAuthorizeChart.ts index 9cf8760ba1..a70140567a 100644 --- a/web/src/admin/admin-overview/charts/AdminLoginAuthorizeChart.ts +++ b/web/src/admin/admin-overview/charts/AdminLoginAuthorizeChart.ts @@ -1,8 +1,8 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKChart, RGBAColor } from "@goauthentik/elements/charts/Chart"; -import { ChartData, Tick } from "chart.js"; +import { ChartData } from "chart.js"; -import { msg, str } from "@lit/localize"; +import { msg } from "@lit/localize"; import { customElement } from "lit/decorators.js"; import { AdminApi, LoginMetrics } from "@goauthentik/api"; @@ -13,13 +13,6 @@ export class AdminLoginAuthorizeChart extends AKChart { return new AdminApi(DEFAULT_CONFIG).adminMetricsRetrieve(); } - timeTickCallback(tickValue: string | number, index: number, ticks: Tick[]): string { - const valueStamp = ticks[index]; - const delta = Date.now() - valueStamp.value; - const ago = Math.round(delta / 1000 / 3600 / 24); - return msg(str`${ago} day(s) ago`); - } - getChartData(data: LoginMetrics): ChartData { return { datasets: [ diff --git a/web/src/admin/admin-overview/charts/OutpostStatusChart.ts b/web/src/admin/admin-overview/charts/OutpostStatusChart.ts index 586379f033..136863c6da 100644 --- a/web/src/admin/admin-overview/charts/OutpostStatusChart.ts +++ b/web/src/admin/admin-overview/charts/OutpostStatusChart.ts @@ -1,4 +1,4 @@ -import { SyncStatus } from "@goauthentik/admin/admin-overview/charts/SyncStatusChart"; +import { SummarizedSyncStatus } from "@goauthentik/admin/admin-overview/charts/SyncStatusChart"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKChart } from "@goauthentik/elements/charts/Chart"; import "@goauthentik/elements/forms/ConfirmationForm"; @@ -10,7 +10,7 @@ import { customElement } from "lit/decorators.js"; import { OutpostsApi } from "@goauthentik/api"; @customElement("ak-admin-status-chart-outpost") -export class OutpostStatusChart extends AKChart { +export class OutpostStatusChart extends AKChart { getChartType(): string { return "doughnut"; } @@ -26,16 +26,16 @@ export class OutpostStatusChart extends AKChart { }; } - async apiRequest(): Promise { + async apiRequest(): Promise { const api = new OutpostsApi(DEFAULT_CONFIG); const outposts = await api.outpostsInstancesList({}); - const outpostStats: SyncStatus[] = []; + const outpostStats: SummarizedSyncStatus[] = []; await Promise.all( outposts.results.map(async (element) => { const health = await api.outpostsInstancesHealthList({ uuid: element.pk || "", }); - const singleStats: SyncStatus = { + const singleStats: SummarizedSyncStatus = { unsynced: 0, healthy: 0, failed: 0, @@ -59,7 +59,7 @@ export class OutpostStatusChart extends AKChart { return outpostStats; } - getChartData(data: SyncStatus[]): ChartData { + getChartData(data: SummarizedSyncStatus[]): ChartData { return { labels: [msg("Healthy outposts"), msg("Outdated outposts"), msg("Unhealthy outposts")], datasets: data.map((d) => { diff --git a/web/src/admin/admin-overview/charts/SyncStatusChart.ts b/web/src/admin/admin-overview/charts/SyncStatusChart.ts index 147e056ad7..6c8887fb2b 100644 --- a/web/src/admin/admin-overview/charts/SyncStatusChart.ts +++ b/web/src/admin/admin-overview/charts/SyncStatusChart.ts @@ -1,14 +1,15 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKChart } from "@goauthentik/elements/charts/Chart"; import "@goauthentik/elements/forms/ConfirmationForm"; +import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { ChartData, ChartOptions } from "chart.js"; import { msg } from "@lit/localize"; import { customElement } from "lit/decorators.js"; -import { ProvidersApi, SourcesApi, SystemTaskStatusEnum } from "@goauthentik/api"; +import { ProvidersApi, SourcesApi, SyncStatus, SystemTaskStatusEnum } from "@goauthentik/api"; -export interface SyncStatus { +export interface SummarizedSyncStatus { healthy: number; failed: number; unsynced: number; @@ -17,7 +18,7 @@ export interface SyncStatus { } @customElement("ak-admin-status-chart-sync") -export class LDAPSyncStatusChart extends AKChart { +export class SyncStatusChart extends AKChart { getChartType(): string { return "doughnut"; } @@ -33,99 +34,104 @@ export class LDAPSyncStatusChart extends AKChart { }; } - async ldapStatus(): Promise { - const api = new SourcesApi(DEFAULT_CONFIG); - const sources = await api.sourcesLdapList({}); + async fetchStatus( + listObjects: () => Promise>, + fetchSyncStatus: (element: T) => Promise, + label: string, + ): Promise { + const objects = await listObjects(); const metrics: { [key: string]: number } = { healthy: 0, failed: 0, unsynced: 0, }; await Promise.all( - sources.results.map(async (element) => { + objects.results.map(async (element) => { + // Each source should have 3 successful tasks, so the worst task overwrites + let objectKey = "healthy"; try { - const health = await api.sourcesLdapSyncStatusRetrieve({ - slug: element.slug, - }); - - health.tasks.forEach((task) => { + const status = await fetchSyncStatus(element); + status.tasks.forEach((task) => { if (task.status !== SystemTaskStatusEnum.Successful) { - metrics.failed += 1; + objectKey = "failed"; } const now = new Date().getTime(); const maxDelta = 3600000; // 1 hour - if (!health || now - task.finishTimestamp.getTime() > maxDelta) { - metrics.unsynced += 1; - } else { - metrics.healthy += 1; + if (!status || now - task.finishTimestamp.getTime() > maxDelta) { + objectKey = "unsynced"; } }); - if (health.tasks.length < 1) { - metrics.unsynced += 1; - } } catch { - metrics.unsynced += 1; + objectKey = "unsynced"; } + metrics[objectKey] += 1; }), ); return { healthy: metrics.healthy, failed: metrics.failed, - unsynced: sources.pagination.count === 0 ? 1 : metrics.unsynced, - total: sources.pagination.count, - label: msg("LDAP Source"), + unsynced: objects.pagination.count === 0 ? 1 : metrics.unsynced, + total: objects.pagination.count, + label: label, }; } - async scimStatus(): Promise { - const api = new ProvidersApi(DEFAULT_CONFIG); - const providers = await api.providersScimList({}); - const metrics: { [key: string]: number } = { - healthy: 0, - failed: 0, - unsynced: 0, - }; - await Promise.all( - providers.results.map(async (element) => { - // Each source should have 3 successful tasks, so the worst task overwrites - let sourceKey = "healthy"; - try { - const health = await api.providersScimSyncStatusRetrieve({ + async apiRequest(): Promise { + const statuses = [ + await this.fetchStatus( + () => { + return new ProvidersApi(DEFAULT_CONFIG).providersScimList(); + }, + (element) => { + return new ProvidersApi(DEFAULT_CONFIG).providersScimSyncStatusRetrieve({ id: element.pk, }); - health.tasks.forEach((task) => { - if (task.status !== SystemTaskStatusEnum.Successful) { - sourceKey = "failed"; - } - const now = new Date().getTime(); - const maxDelta = 3600000; // 1 hour - if (!health || now - task.finishTimestamp.getTime() > maxDelta) { - sourceKey = "unsynced"; - } + }, + msg("SCIM Provider"), + ), + await this.fetchStatus( + () => { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceList(); + }, + (element) => { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersGoogleWorkspaceSyncStatusRetrieve({ + id: element.pk, }); - } catch { - sourceKey = "unsynced"; - } - metrics[sourceKey] += 1; - }), - ); - return { - healthy: metrics.healthy, - failed: metrics.failed, - unsynced: providers.pagination.count === 0 ? 1 : metrics.unsynced, - total: providers.pagination.count, - label: msg("SCIM Provider"), - }; + }, + msg("Google Workspace Provider"), + ), + await this.fetchStatus( + () => { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraList(); + }, + (element) => { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersMicrosoftEntraSyncStatusRetrieve({ + id: element.pk, + }); + }, + msg("Microsoft Entra Provider"), + ), + await this.fetchStatus( + () => { + return new SourcesApi(DEFAULT_CONFIG).sourcesLdapList(); + }, + (element) => { + return new SourcesApi(DEFAULT_CONFIG).sourcesLdapSyncStatusRetrieve({ + slug: element.slug, + }); + }, + msg("LDAP Source"), + ), + ]; + this.centerText = statuses.reduce((total, el) => (total += el.total), 0).toString(); + return statuses; } - async apiRequest(): Promise { - const ldapStatus = await this.ldapStatus(); - const scimStatus = await this.scimStatus(); - this.centerText = (ldapStatus.total + scimStatus.total).toString(); - return [ldapStatus, scimStatus]; - } - - getChartData(data: SyncStatus[]): ChartData { + getChartData(data: SummarizedSyncStatus[]): ChartData { return { labels: [msg("Healthy"), msg("Failed"), msg("Unsynced / N/A")], datasets: data.map((d) => { diff --git a/web/src/admin/admin-settings/AdminSettingsForm.ts b/web/src/admin/admin-settings/AdminSettingsForm.ts index d7d05c725c..d1dd3f8d2a 100644 --- a/web/src/admin/admin-settings/AdminSettingsForm.ts +++ b/web/src/admin/admin-settings/AdminSettingsForm.ts @@ -1,5 +1,6 @@ -import { first } from "@goauthentik/app/common/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { first } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-number-input"; import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-text-input"; import "@goauthentik/elements/CodeMirror"; @@ -22,25 +23,36 @@ import { AdminApi, Settings, SettingsRequest } from "@goauthentik/api"; @customElement("ak-admin-settings-form") export class AdminSettingsForm extends Form { - @property({ attribute: false }) - set settings(value: Settings) { + // + // Custom property accessors in Lit 2 require a manual call to requestUpdate(). See: + // https://lit.dev/docs/v2/components/properties/#accessors-custom + // + set settings(value: Settings | undefined) { this._settings = value; + this.requestUpdate(); + } + + @property({ type: Object }) + get settings() { + return this._settings; } private _settings?: Settings; + static get styles(): CSSResult[] { + return super.styles.concat(PFList); + } + getSuccessMessage(): string { return msg("Successfully updated settings."); } async send(data: SettingsRequest): Promise { - return new AdminApi(DEFAULT_CONFIG).adminSettingsUpdate({ + const result = await new AdminApi(DEFAULT_CONFIG).adminSettingsUpdate({ settingsRequest: data, }); - } - - static get styles(): CSSResult[] { - return super.styles.concat(PFList); + this.dispatchEvent(new CustomEvent("ak-admin-setting-changed")); + return result; } renderForm(): TemplateResult { @@ -52,59 +64,52 @@ export class AdminSettingsForm extends Form { .bighelp=${html`

${msg( - "Configure how authentik should show avatars for users. The following values can be set:", + "Configure how authentik should show avatars for users. The following values can be set:" )}

  • none: - ${msg( - "Disables per-user avatars and just shows a 1x1 pixel transparent picture", - )} + ${msg("Disables per-user avatars and just shows a 1x1 pixel transparent picture")}
  • - gravatar: - ${msg("Uses gravatar with the user's email address")} + gravatar: ${msg("Uses gravatar with the user's email address")}
  • - initials: - ${msg("Generated avatars based on the user's name")} + initials: ${msg("Generated avatars based on the user's name")}
  • ${msg( - "Any URL: If you want to use images hosted on another server, you can set any URL. Additionally, these placeholders can be used:", + "Any URL: If you want to use images hosted on another server, you can set any URL. Additionally, these placeholders can be used:" )}
    • %(username)s: ${msg("The user's username")}
    • - %(mail_hash)s: - ${msg("The email address, md5 hashed")} + %(mail_hash)s: ${msg("The email address, md5 hashed")}
    • - %(upn)s: - ${msg("The user's UPN, if set (otherwise an empty string)")} + %(upn)s: ${msg("The user's UPN, if set (otherwise an empty string)")}
  • ${msg( - html`An attribute path like - attributes.something.avatar, which can be used in - combination with the file field to allow users to upload custom - avatars for themselves.`, + html`An attribute path like attributes.something.avatar, which can be used + in combination with the file field to allow users to upload custom avatars for + themselves.` )}

${msg( - "Multiple values can be set, comma-separated, and authentik will fallback to the next mode when no avatar could be found.", + "Multiple values can be set, comma-separated, and authentik will fallback to the next mode when no avatar could be found." )} ${msg( - html`For example, setting this to gravatar,initials will - attempt to get an avatar from Gravatar, and if the user has not - configured on there, it will fallback to a generated avatar.`, + html`For example, setting this to gravatar,initials will attempt to get an + avatar from Gravatar, and if the user has not configured on there, it will fallback to a + generated avatar.` )}

`} @@ -141,14 +146,10 @@ export class AdminSettingsForm extends Form { ${msg("Duration after which events will be deleted from the database.")}

- ${msg( - 'When using an external logging solution for archiving, this can be set to "minutes=5".', - )} + ${msg('When using an external logging solution for archiving, this can be set to "minutes=5".')}

- ${msg( - "This setting only affects new Events, as the expiration is saved per-event.", - )} + ${msg("This setting only affects new Events, as the expiration is saved per-event.")}

`} > @@ -160,7 +161,7 @@ export class AdminSettingsForm extends Form { >

${msg( - "This option configures the footer links on the flow executor pages. It must be a valid YAML or JSON list and can be used as follows:", + "This option configures the footer links on the flow executor pages. It must be a valid YAML or JSON list and can be used as follows:" )} [{"name": "Link Name","href":"https://goauthentik.io"}]

@@ -169,9 +170,7 @@ export class AdminSettingsForm extends Form { name="gdprCompliance" label=${msg("GDPR compliance")} ?checked="${this._settings?.gdprCompliance}" - help=${msg( - "When enabled, all the events caused by a user will be deleted upon the user's deletion.", - )} + help=${msg("When enabled, all the events caused by a user will be deleted upon the user's deletion.")} > { help=${msg("Globally enable/disable impersonation.")} > - + ${msg( - "This option configures what user fields are shown in the user directory. It must be a valid JSON list and can be used as follows, with all possible values included:", + "This option configures what user fields are shown in the user directory. It must be a valid JSON list and can be used as follows, with all possible values included:" )} ["name", "username", "email", "avatars", "groups"]

- +

${msg( - "This option configures what user attributes are shown in the user directory. It must be a valid JSON list and can be used as follows:", + "This option configures what user attributes are shown in the user directory. It must be a valid JSON list and can be used as follows:" )} [{"attribute": "phone_number", "display_name": "Phone"}]

+ ${msg("Default duration for generated tokens")}

+ `} + > +
+ `; } } diff --git a/web/src/admin/admin-settings/AdminSettingsPage.ts b/web/src/admin/admin-settings/AdminSettingsPage.ts index c6c8e9997e..07113a543b 100644 --- a/web/src/admin/admin-settings/AdminSettingsPage.ts +++ b/web/src/admin/admin-settings/AdminSettingsPage.ts @@ -14,8 +14,8 @@ import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { html, nothing } from "lit"; +import { customElement, query, state } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; @@ -32,7 +32,7 @@ import { AdminApi, Settings } from "@goauthentik/api"; @customElement("ak-admin-settings") export class AdminSettingsPage extends AKElement { - static get styles(): CSSResult[] { + static get styles() { return [ PFBase, PFButton, @@ -46,41 +46,46 @@ export class AdminSettingsPage extends AKElement { PFBanner, ]; } - @property({ attribute: false }) + + @query("ak-admin-settings-form#form") + form?: AdminSettingsForm; + + @state() settings?: Settings; - loadSettings(): void { - new AdminApi(DEFAULT_CONFIG).adminSettingsRetrieve().then((settings) => { + constructor() { + super(); + AdminSettingsPage.fetchSettings().then((settings) => { this.settings = settings; }); + this.save = this.save.bind(this); + this.reset = this.reset.bind(this); + this.addEventListener("ak-admin-setting-changed", this.handleUpdate.bind(this)); } - firstUpdated(): void { - this.loadSettings(); + static async fetchSettings() { + return await new AdminApi(DEFAULT_CONFIG).adminSettingsRetrieve(); } - async save(): Promise { - const form = this.shadowRoot?.querySelector("ak-admin-settings-form"); - if (!form) { + async handleUpdate() { + this.settings = await AdminSettingsPage.fetchSettings(); + } + + async save() { + if (!this.form) { return; } - await form.submit(new Event("submit")); - this.resetForm(); + await this.form.submit(new Event("submit")); + this.settings = await AdminSettingsPage.fetchSettings(); } - resetForm(): void { - const form = this.shadowRoot?.querySelector("ak-admin-settings-form"); - if (!form) { - return; - } - this.loadSettings(); - form.settings = this.settings!; - form.resetForm(); + async reset() { + this.form?.resetForm(); } - render(): TemplateResult { + render() { if (!this.settings) { - return html``; + return nothing; } return html` @@ -93,18 +98,10 @@ export class AdminSettingsPage extends AKElement {
diff --git a/web/src/admin/applications/ApplicationCheckAccessForm.ts b/web/src/admin/applications/ApplicationCheckAccessForm.ts index 7f1c18e17d..7a2e1f7dab 100644 --- a/web/src/admin/applications/ApplicationCheckAccessForm.ts +++ b/web/src/admin/applications/ApplicationCheckAccessForm.ts @@ -1,5 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import "@goauthentik/components/ak-status-label"; +import "@goauthentik/elements/events/LogViewer"; import { Form } from "@goauthentik/elements/forms/Form"; import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/SearchSelect"; @@ -83,28 +84,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
- ${(this.result?.logMessages || []).length > 0 - ? this.result?.logMessages?.map((m) => { - return html`
-
- ${m.log_level} -
-
-
- ${m.event} -
-
-
`; - }) - : html`
-
- ${msg("No log messages.")} -
-
`} +
diff --git a/web/src/admin/applications/ApplicationListPage.ts b/web/src/admin/applications/ApplicationListPage.ts index fd8306c3f6..84718ef2f0 100644 --- a/web/src/admin/applications/ApplicationListPage.ts +++ b/web/src/admin/applications/ApplicationListPage.ts @@ -1,15 +1,14 @@ import "@goauthentik/admin/applications/ApplicationForm"; -import { PFSize } from "@goauthentik/app/elements/Spinner"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PFSize } from "@goauthentik/common/enums.js"; import { uiConfig } from "@goauthentik/common/ui/config"; import "@goauthentik/components/ak-app-icon"; -import MDApplication from "@goauthentik/docs/core/applications.md"; +import MDApplication from "@goauthentik/docs/applications/index.md"; import "@goauthentik/elements/Markdown"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; -// import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; import { TablePage } from "@goauthentik/elements/table/TablePage"; @@ -25,6 +24,22 @@ import { Application, CoreApi } from "@goauthentik/api"; import "./ApplicationWizardHint"; +export const applicationListStyle = css` + /* Fix alignment issues with images in tables */ + .pf-c-table tbody > tr > * { + vertical-align: middle; + } + tr td:first-child { + width: auto; + min-width: 0px; + text-align: center; + vertical-align: middle; + } + .pf-c-sidebar.pf-m-gutter > .pf-c-sidebar__main > * + * { + margin-left: calc(var(--pf-c-sidebar__main--child--MarginLeft) / 2); + } +`; + @customElement("ak-application-list") export class ApplicationListPage extends TablePage { searchEnabled(): boolean { @@ -43,6 +58,7 @@ export class ApplicationListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; @@ -58,24 +74,7 @@ export class ApplicationListPage extends TablePage { } static get styles(): CSSResult[] { - return super.styles.concat( - PFCard, - css` - /* Fix alignment issues with images in tables */ - .pf-c-table tbody > tr > * { - vertical-align: middle; - } - tr td:first-child { - width: auto; - min-width: 0px; - text-align: center; - vertical-align: middle; - } - .pf-c-sidebar.pf-m-gutter > .pf-c-sidebar__main > * + * { - margin-left: calc(var(--pf-c-sidebar__main--child--MarginLeft) / 2); - } - `, - ); + return super.styles.concat(PFCard, applicationListStyle); } columns(): TableColumn[] { @@ -94,13 +93,10 @@ export class ApplicationListPage extends TablePage { } renderSidebarAfter(): TemplateResult { - // Rendering the wizard with .open here, as if we set the attribute in - // renderObjectCreate() it'll open two wizards, since that function gets called twice - return html`
- +
`; diff --git a/web/src/admin/applications/ApplicationViewPage.ts b/web/src/admin/applications/ApplicationViewPage.ts index 84ea2f207a..19db71df55 100644 --- a/web/src/admin/applications/ApplicationViewPage.ts +++ b/web/src/admin/applications/ApplicationViewPage.ts @@ -2,9 +2,8 @@ import "@goauthentik/admin/applications/ApplicationAuthorizeChart"; import "@goauthentik/admin/applications/ApplicationCheckAccessForm"; import "@goauthentik/admin/applications/ApplicationForm"; import "@goauthentik/admin/policies/BoundPoliciesList"; -import { PFSize } from "@goauthentik/app/elements/Spinner"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PFSize } from "@goauthentik/common/enums.js"; import "@goauthentik/components/ak-app-icon"; import "@goauthentik/components/events/ObjectChangelog"; import { AKElement } from "@goauthentik/elements/Base"; @@ -12,9 +11,10 @@ import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -37,37 +37,11 @@ import { @customElement("ak-application-view") export class ApplicationViewPage extends AKElement { - @property() - set applicationSlug(value: string) { - new CoreApi(DEFAULT_CONFIG) - .coreApplicationsRetrieve({ - slug: value, - }) - .then((app) => { - this.application = app; - if ( - app.providerObj && - [ - "authentik_providers_proxy.proxyprovider", - "authentik_providers_ldap.ldapprovider", - ].includes(app.providerObj.metaModelName) - ) { - new OutpostsApi(DEFAULT_CONFIG) - .outpostsInstancesList({ - providersByPk: [app.provider || 0], - pageSize: 1, - }) - .then((outposts) => { - if (outposts.pagination.count < 1) { - this.missingOutpost = true; - } - }); - } - }); - } + @property({ type: String }) + applicationSlug?: string; - @property({ attribute: false }) - application!: Application; + @state() + application?: Application; @state() missingOutpost = false; @@ -86,6 +60,40 @@ export class ApplicationViewPage extends AKElement { ]; } + fetchIsMissingOutpost(providersByPk: Array) { + new OutpostsApi(DEFAULT_CONFIG) + .outpostsInstancesList({ + providersByPk, + pageSize: 1, + }) + .then((outposts) => { + if (outposts.pagination.count < 1) { + this.missingOutpost = true; + } + }); + } + + fetchApplication(slug: string) { + new CoreApi(DEFAULT_CONFIG).coreApplicationsRetrieve({ slug }).then((app) => { + this.application = app; + if ( + app.providerObj && + [ + RbacPermissionsAssignedByUsersListModelEnum.ProvidersProxyProxyprovider.toString(), + RbacPermissionsAssignedByUsersListModelEnum.ProvidersLdapLdapprovider.toString(), + ].includes(app.providerObj.metaModelName) + ) { + this.fetchIsMissingOutpost([app.provider || 0]); + } + }); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("applicationSlug") && this.applicationSlug) { + this.fetchApplication(this.applicationSlug); + } + } + render(): TemplateResult { return html` { } @property({ type: Boolean }) - backchannelOnly = false; + backchannel?: boolean; @property() confirm!: (selectedItems: Provider[]) => Promise; @@ -34,7 +34,7 @@ export class ProviderSelectModal extends TableModal { page: page, pageSize: (await uiConfig()).pagination.perPage, search: this.search || "", - backchannelOnly: this.backchannelOnly, + backchannel: this.backchannel, }); } diff --git a/web/src/admin/applications/components/ak-backchannel-input.ts b/web/src/admin/applications/components/ak-backchannel-input.ts index 06fccc32b1..0554317ab3 100644 --- a/web/src/admin/applications/components/ak-backchannel-input.ts +++ b/web/src/admin/applications/components/ak-backchannel-input.ts @@ -20,8 +20,9 @@ export class AkBackchannelProvidersInput extends AKElement { // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in // general. + protected createRenderRoot() { - return this; + return this as HTMLElement; } @property({ type: String }) @@ -61,9 +62,9 @@ export class AkBackchannelProvidersInput extends AKElement { >`; return html` - +
- +
- ${this.help ? html`

${this.help}

` : nothing} + ${this.help ? html`

${this.help}

` : nothing} `; } diff --git a/web/src/admin/applications/components/ak-provider-search-input.ts b/web/src/admin/applications/components/ak-provider-search-input.ts index 552cb0764a..57752f85df 100644 --- a/web/src/admin/applications/components/ak-provider-search-input.ts +++ b/web/src/admin/applications/components/ak-provider-search-input.ts @@ -15,6 +15,7 @@ const doGroupBy = (items: Provider[]) => groupBy(items, (item) => item.verboseNa async function fetch(query?: string) { const args: ProvidersAllListRequest = { ordering: "name", + backchannel: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/applications/wizard/BasePanel.ts b/web/src/admin/applications/wizard/BasePanel.ts index 1b2db5bd40..1f4bf37161 100644 --- a/web/src/admin/applications/wizard/BasePanel.ts +++ b/web/src/admin/applications/wizard/BasePanel.ts @@ -4,7 +4,7 @@ import { KeyUnknown, serializeForm } from "@goauthentik/elements/forms/Form"; import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement"; import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; -import { consume } from "@lit-labs/context"; +import { consume } from "@lit/context"; import { query } from "@lit/reactive-element/decorators.js"; import { styles as AwadStyles } from "./BasePanel.css"; diff --git a/web/src/admin/applications/wizard/ContextIdentity.ts b/web/src/admin/applications/wizard/ContextIdentity.ts index 629b65cd84..ab71861b70 100644 --- a/web/src/admin/applications/wizard/ContextIdentity.ts +++ b/web/src/admin/applications/wizard/ContextIdentity.ts @@ -1,4 +1,4 @@ -import { createContext } from "@lit-labs/context"; +import { createContext } from "@lit/context"; import { ApplicationWizardState } from "./types"; diff --git a/web/src/admin/applications/wizard/ak-application-wizard.ts b/web/src/admin/applications/wizard/ak-application-wizard.ts index 50cf750d7d..1e33124fec 100644 --- a/web/src/admin/applications/wizard/ak-application-wizard.ts +++ b/web/src/admin/applications/wizard/ak-application-wizard.ts @@ -1,7 +1,7 @@ import { AkWizard } from "@goauthentik/components/ak-wizard-main/AkWizard"; import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter"; -import { ContextProvider } from "@lit-labs/context"; +import { ContextProvider } from "@lit/context"; import { msg } from "@lit/localize"; import { customElement, state } from "lit/decorators.js"; diff --git a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts index 2c04429152..b0f1dfa83a 100644 --- a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts +++ b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts @@ -1,3 +1,5 @@ +import "@goauthentik/admin/common/ak-license-notice"; + import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -8,6 +10,7 @@ import type { ModelRequest, OAuth2ProviderRequest, ProxyProviderRequest, + RACProviderRequest, RadiusProviderRequest, SAMLProviderRequest, SCIMProviderRequest, @@ -19,150 +22,155 @@ type ProviderRenderer = () => TemplateResult; type ModelConverter = (provider: OneOfProvider) => ModelRequest; -/** - * There's an internal key and an API key because "Proxy" has three different subtypes. - */ -// prettier-ignore -type ProviderType = [ - string, // internal key used by the wizard to distinguish between providers - string, // Name of the provider - string, // Description - ProviderRenderer, // Function that returns the provider's wizard panel as a TemplateResult - ProviderModelEnumType, // key used by the API to distinguish between providers - ModelConverter, // Handler that takes a generic provider and returns one specifically typed to its panel -]; +type ProviderNoteProvider = () => TemplateResult | undefined; +type ProviderNote = ProviderNoteProvider | undefined; export type LocalTypeCreate = TypeCreate & { formName: string; modelName: ProviderModelEnumType; converter: ModelConverter; + note?: ProviderNote; + renderer: ProviderRenderer; }; -// prettier-ignore -const _providerModelsTable: ProviderType[] = [ - [ - "oauth2provider", - msg("OAuth2/OIDC (Open Authorization/OpenID Connect)"), - msg("Modern applications, APIs and Single-page applications."), - () => +export const providerModelsList: LocalTypeCreate[] = [ + { + formName: "oauth2provider", + name: msg("OAuth2/OIDC (Open Authorization/OpenID Connect)"), + description: msg("Modern applications, APIs and Single-page applications."), + renderer: () => html``, - ProviderModelEnum.Oauth2Oauth2provider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.Oauth2Oauth2provider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.Oauth2Oauth2provider, ...(provider as OAuth2ProviderRequest), }), - ], - [ - "ldapprovider", - msg("LDAP (Lightweight Directory Access Protocol)"), - msg("Provide an LDAP interface for applications and users to authenticate against."), - () => + component: "", + iconUrl: "/static/authentik/sources/openidconnect.svg", + }, + { + formName: "ldapprovider", + name: msg("LDAP (Lightweight Directory Access Protocol)"), + description: msg( + "Provide an LDAP interface for applications and users to authenticate against.", + ), + renderer: () => html``, - ProviderModelEnum.LdapLdapprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.LdapLdapprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.LdapLdapprovider, ...(provider as LDAPProviderRequest), }), - ], - [ - "proxyprovider-proxy", - msg("Transparent Reverse Proxy"), - msg("For transparent reverse proxies with required authentication"), - () => + component: "", + iconUrl: "/static/authentik/sources/ldap.png", + }, + { + formName: "proxyprovider-proxy", + name: msg("Transparent Reverse Proxy"), + description: msg("For transparent reverse proxies with required authentication"), + renderer: () => html``, - ProviderModelEnum.ProxyProxyprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.ProxyProxyprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.ProxyProxyprovider, ...(provider as ProxyProviderRequest), mode: ProxyMode.Proxy, }), - ], - [ - "proxyprovider-forwardsingle", - msg("Forward Auth (Single Application)"), - msg("For nginx's auth_request or traefik's forwardAuth"), - () => + component: "", + iconUrl: "/static/authentik/sources/proxy.svg", + }, + { + formName: "proxyprovider-forwardsingle", + name: msg("Forward Auth (Single Application)"), + description: msg("For nginx's auth_request or traefik's forwardAuth"), + renderer: () => html``, - ProviderModelEnum.ProxyProxyprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.ProxyProxyprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.ProxyProxyprovider, ...(provider as ProxyProviderRequest), mode: ProxyMode.ForwardSingle, }), - ], - [ - "proxyprovider-forwarddomain", - msg("Forward Auth (Domain Level)"), - msg("For nginx's auth_request or traefik's forwardAuth per root domain"), - () => + component: "", + iconUrl: "/static/authentik/sources/proxy.svg", + }, + { + formName: "proxyprovider-forwarddomain", + name: msg("Forward Auth (Domain Level)"), + description: msg("For nginx's auth_request or traefik's forwardAuth per root domain"), + renderer: () => html``, - ProviderModelEnum.ProxyProxyprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.ProxyProxyprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.ProxyProxyprovider, ...(provider as ProxyProviderRequest), mode: ProxyMode.ForwardDomain, }), - ], - [ - "samlprovider", - msg("SAML (Security Assertion Markup Language)"), - msg("Configure SAML provider manually"), - () => + component: "", + iconUrl: "/static/authentik/sources/proxy.svg", + }, + { + formName: "racprovider", + name: msg("Remote Access Provider"), + description: msg("Remotely access computers/servers via RDP/SSH/VNC"), + renderer: () => + html``, + modelName: ProviderModelEnum.RacRacprovider, + converter: (provider: OneOfProvider) => ({ + providerModel: ProviderModelEnum.RacRacprovider, + ...(provider as RACProviderRequest), + }), + note: () => html``, + requiresEnterprise: true, + component: "", + iconUrl: "/static/authentik/sources/rac.svg", + }, + { + formName: "samlprovider", + name: msg("SAML (Security Assertion Markup Language)"), + description: msg("Configure SAML provider manually"), + renderer: () => html``, - ProviderModelEnum.SamlSamlprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.SamlSamlprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.SamlSamlprovider, ...(provider as SAMLProviderRequest), }), - ], - [ - "radiusprovider", - msg("RADIUS (Remote Authentication Dial-In User Service)"), - msg("Configure RADIUS provider manually"), - () => + component: "", + iconUrl: "/static/authentik/sources/saml.png", + }, + { + formName: "radiusprovider", + name: msg("RADIUS (Remote Authentication Dial-In User Service)"), + description: msg("Configure RADIUS provider manually"), + renderer: () => html``, - ProviderModelEnum.RadiusRadiusprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.RadiusRadiusprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.RadiusRadiusprovider, ...(provider as RadiusProviderRequest), }), - ], - [ - "scimprovider", - msg("SCIM (System for Cross-domain Identity Management)"), - msg("Configure SCIM provider manually"), - () => + component: "", + iconUrl: "/static/authentik/sources/radius.svg", + }, + { + formName: "scimprovider", + name: msg("SCIM (System for Cross-domain Identity Management)"), + description: msg("Configure SCIM provider manually"), + renderer: () => html``, - ProviderModelEnum.ScimScimprovider, - (provider: OneOfProvider) => ({ + modelName: ProviderModelEnum.ScimScimprovider, + converter: (provider: OneOfProvider) => ({ providerModel: ProviderModelEnum.ScimScimprovider, ...(provider as SCIMProviderRequest), }), - ], + component: "", + iconUrl: "/static/authentik/sources/scim.png", + }, ]; -function mapProviders([ - formName, - name, - description, - _, - modelName, - converter, -]: ProviderType): LocalTypeCreate { - return { - formName, - name, - description, - component: "", - modelName, - converter, - }; -} - -export const providerModelsList = _providerModelsTable.map(mapProviders); - export const providerRendererList = new Map( - _providerModelsTable.map(([modelName, _0, _1, renderer]) => [modelName, renderer]), + providerModelsList.map((tc) => [tc.formName, tc.renderer]), ); export default providerModelsList; diff --git a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts index e13e11ecae..9c89baf94f 100644 --- a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts +++ b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts @@ -1,61 +1,43 @@ import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-text-input"; -import "@goauthentik/elements/forms/FormGroup"; +import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; +import { TypeCreateWizardPageLayouts } from "@goauthentik/elements/wizard/TypeCreateWizardPage"; import { msg } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { html } from "lit"; -import { map } from "lit/directives/map.js"; import BasePanel from "../BasePanel"; -import providerModelsList from "./ak-application-wizard-authentication-method-choice.choices"; import type { LocalTypeCreate } from "./ak-application-wizard-authentication-method-choice.choices"; +import providerModelsList from "./ak-application-wizard-authentication-method-choice.choices"; @customElement("ak-application-wizard-authentication-method-choice") -export class ApplicationWizardAuthenticationMethodChoice extends BasePanel { - constructor() { - super(); - this.handleChoice = this.handleChoice.bind(this); - this.renderProvider = this.renderProvider.bind(this); - } - - handleChoice(ev: InputEvent) { - const target = ev.target as HTMLInputElement; - this.dispatchWizardUpdate({ - update: { - ...this.wizard, - providerModel: target.value, - errors: {}, - }, - status: this.valid ? "valid" : "invalid", - }); - } - - renderProvider(type: LocalTypeCreate) { - const method = this.wizard.providerModel; - - return html`
- - - ${type.description} -
`; - } - +export class ApplicationWizardAuthenticationMethodChoice extends WithLicenseSummary(BasePanel) { render() { + const selectedTypes = providerModelsList.filter( + (t) => t.formName === this.wizard.providerModel, + ); return providerModelsList.length > 0 ? html`
- ${map(providerModelsList, this.renderProvider)} + 0 ? selectedTypes[0] : undefined} + @select=${(ev: CustomEvent) => { + this.dispatchWizardUpdate({ + update: { + ...this.wizard, + providerModel: ev.detail.formName, + errors: {}, + }, + status: this.valid ? "valid" : "invalid", + }); + }} + >
` : html``; } diff --git a/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts b/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts index 2258aa7b27..c3c7f9d336 100644 --- a/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts +++ b/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts @@ -1,5 +1,5 @@ -import { EVENT_REFRESH } from "@goauthentik/app/common/constants"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-text-input"; @@ -9,7 +9,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { msg } from "@lit/localize"; import { customElement, state } from "@lit/reactive-element/decorators.js"; -import { TemplateResult, css, html, nothing } from "lit"; +import { PropertyValues, TemplateResult, css, html, nothing } from "lit"; import { classMap } from "lit/directives/class-map.js"; import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css"; @@ -94,8 +94,7 @@ export class ApplicationWizardCommitApplication extends BasePanel { response?: TransactionApplicationResponse; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - willUpdate(_changedProperties: Map) { + willUpdate(_changedProperties: PropertyValues) { if (this.commitState === idleState) { this.response = undefined; this.commitState = runningState; diff --git a/web/src/admin/applications/wizard/methods/ak-application-wizard-authentication-method.ts b/web/src/admin/applications/wizard/methods/ak-application-wizard-authentication-method.ts index 9b7e813bfc..28139bc465 100644 --- a/web/src/admin/applications/wizard/methods/ak-application-wizard-authentication-method.ts +++ b/web/src/admin/applications/wizard/methods/ak-application-wizard-authentication-method.ts @@ -7,12 +7,11 @@ import "./oauth/ak-application-wizard-authentication-by-oauth"; import "./proxy/ak-application-wizard-authentication-for-forward-domain-proxy"; import "./proxy/ak-application-wizard-authentication-for-reverse-proxy"; import "./proxy/ak-application-wizard-authentication-for-single-forward-proxy"; +import "./rac/ak-application-wizard-authentication-for-rac"; import "./radius/ak-application-wizard-authentication-by-radius"; import "./saml/ak-application-wizard-authentication-by-saml-configuration"; import "./scim/ak-application-wizard-authentication-by-scim"; -// prettier-ignore - @customElement("ak-application-wizard-authentication-method") export class ApplicationWizardApplicationDetails extends BasePanel { render() { diff --git a/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts b/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts index 90d0f75806..2be3f8f104 100644 --- a/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts +++ b/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts @@ -183,7 +183,6 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel { { + this.propertyMappings = propertyMappings; + }); + } + + render() { + const provider = this.wizard.provider as RACProvider | undefined; + const selected = new Set(Array.from(provider?.propertyMappings ?? [])); + const errors = this.wizard.errors.provider; + + return html`${msg("Configure Remote Access Provider Provider")} +
+ + + + +

+ ${msg("Flow used when authorizing this provider.")} +

+
+ + + + + ${msg("Protocol settings")} +
+ + +

+ ${msg("Hold control/command to select multiple items.")} +

+
+
+
+
`; + } +} + +export default ApplicationWizardAuthenticationByRAC; diff --git a/web/src/admin/applications/wizard/methods/saml/SamlProviderOptions.ts b/web/src/admin/applications/wizard/methods/saml/SamlProviderOptions.ts index a1b6d44a27..cf6181f7e3 100644 --- a/web/src/admin/applications/wizard/methods/saml/SamlProviderOptions.ts +++ b/web/src/admin/applications/wizard/methods/saml/SamlProviderOptions.ts @@ -29,5 +29,9 @@ export const signatureAlgorithmOptions = toOptions([ ["RSA-SHA256", SignatureAlgorithmEnum._200104XmldsigMorersaSha256, true], ["RSA-SHA384", SignatureAlgorithmEnum._200104XmldsigMorersaSha384], ["RSA-SHA512", SignatureAlgorithmEnum._200104XmldsigMorersaSha512], + ["ECDSA-SHA1", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha1], + ["ECDSA-SHA256", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha256], + ["ECDSA-SHA384", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha384], + ["ECDSA-SHA512", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha512], ["DSA-SHA1", SignatureAlgorithmEnum._200009XmldsigdsaSha1], ]); diff --git a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts b/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts index 82024157ec..05a27cd735 100644 --- a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts +++ b/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts @@ -194,7 +194,6 @@ export class ApplicationWizardProviderSamlConfiguration extends BaseProviderPane diff --git a/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts b/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts index 2bc8596e27..088cf7992a 100644 --- a/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts +++ b/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts @@ -123,7 +123,6 @@ export class ApplicationWizardAuthenticationBySCIM extends BaseProviderPanel {
| Partial | Partial + | Partial | Partial | Partial | Partial diff --git a/web/src/admin/blueprints/BlueprintListPage.ts b/web/src/admin/blueprints/BlueprintListPage.ts index 188bb4be58..6eb24aa2ee 100644 --- a/web/src/admin/blueprints/BlueprintListPage.ts +++ b/web/src/admin/blueprints/BlueprintListPage.ts @@ -2,6 +2,7 @@ import "@goauthentik/admin/blueprints/BlueprintForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/SpinnerButton"; @@ -58,6 +59,7 @@ export class BlueprintListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; @property() order = "name"; @@ -143,7 +145,8 @@ export class BlueprintListPage extends TablePage { html`
${item.name}
${description ? html`${description}` : html``}`, html`${BlueprintStatus(item)}`, - html`${item.lastApplied.toLocaleString()}`, + html`
${getRelativeTime(item.lastApplied)}
+ ${item.lastApplied.toLocaleString()}`, html``, html` ${msg("Update")} diff --git a/web/src/admin/brands/BrandListPage.ts b/web/src/admin/brands/BrandListPage.ts index 5db55f9148..9aa0e23c23 100644 --- a/web/src/admin/brands/BrandListPage.ts +++ b/web/src/admin/brands/BrandListPage.ts @@ -30,10 +30,11 @@ export class BrandListPage extends TablePage { return msg("Configure visual settings and defaults for different domains."); } pageIcon(): string { - return "pf-icon pf-icon-brand"; + return "pf-icon pf-icon-tenant"; } checkbox = true; + clearOnRefresh = true; @property() order = "domain"; @@ -50,6 +51,7 @@ export class BrandListPage extends TablePage { columns(): TableColumn[] { return [ new TableColumn(msg("Domain"), "domain"), + new TableColumn(msg("Brand name"), "branding_title"), new TableColumn(msg("Default?"), "default"), new TableColumn(msg("Actions")), ]; @@ -83,6 +85,7 @@ export class BrandListPage extends TablePage { row(item: Brand): TemplateResult[] { return [ html`${item.domain}`, + html`${item.brandingTitle}`, html``, html` ${msg("Update")} diff --git a/web/src/admin/common/ak-core-group-search.ts b/web/src/admin/common/ak-core-group-search.ts index a5812a7339..9a54124e27 100644 --- a/web/src/admin/common/ak-core-group-search.ts +++ b/web/src/admin/common/ak-core-group-search.ts @@ -12,6 +12,7 @@ import { CoreApi, CoreGroupsListRequest, Group } from "@goauthentik/api"; async function fetchObjects(query?: string): Promise { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/common/ak-license-notice.ts b/web/src/admin/common/ak-license-notice.ts new file mode 100644 index 0000000000..4cc978ac4f --- /dev/null +++ b/web/src/admin/common/ak-license-notice.ts @@ -0,0 +1,23 @@ +import "@goauthentik/elements/Alert"; +import { AKElement } from "@goauthentik/elements/Base"; +import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; + +import { msg } from "@lit/localize"; +import { html, nothing } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +@customElement("ak-license-notice") +export class AkLicenceNotice extends WithLicenseSummary(AKElement) { + @property() + notice = msg("Enterprise only"); + + render() { + return this.hasEnterpriseLicense + ? nothing + : html` + + ${this.notice} + + `; + } +} diff --git a/web/src/admin/crypto/CertificateGenerateForm.ts b/web/src/admin/crypto/CertificateGenerateForm.ts index 85f2fde9ec..ada0625e76 100644 --- a/web/src/admin/crypto/CertificateGenerateForm.ts +++ b/web/src/admin/crypto/CertificateGenerateForm.ts @@ -6,7 +6,12 @@ import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; -import { CertificateGenerationRequest, CertificateKeyPair, CryptoApi } from "@goauthentik/api"; +import { + AlgEnum, + CertificateGenerationRequest, + CertificateKeyPair, + CryptoApi, +} from "@goauthentik/api"; @customElement("ak-crypto-certificate-generate-form") export class CertificateKeyPairForm extends Form { @@ -40,6 +45,29 @@ export class CertificateKeyPairForm extends Form { ?required=${true} > - `; + + + + +

+ ${msg("Algorithm used to generate the private key.")} +

+
`; } } diff --git a/web/src/admin/crypto/CertificateKeyPairListPage.ts b/web/src/admin/crypto/CertificateKeyPairListPage.ts index c76feff3a5..fd71112273 100644 --- a/web/src/admin/crypto/CertificateKeyPairListPage.ts +++ b/web/src/admin/crypto/CertificateKeyPairListPage.ts @@ -29,6 +29,7 @@ import { export class CertificateKeyPairListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/enterprise/EnterpriseLicenseForm.ts b/web/src/admin/enterprise/EnterpriseLicenseForm.ts index ebce9938db..025df416b1 100644 --- a/web/src/admin/enterprise/EnterpriseLicenseForm.ts +++ b/web/src/admin/enterprise/EnterpriseLicenseForm.ts @@ -1,4 +1,5 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants"; import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; @@ -34,14 +35,19 @@ export class EnterpriseLicenseForm extends ModelForm { } async send(data: License): Promise { - return this.instance - ? new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicensePartialUpdate({ - licenseUuid: this.instance.licenseUuid || "", - patchedLicenseRequest: data, - }) - : new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseCreate({ - licenseRequest: data, - }); + return ( + this.instance + ? new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicensePartialUpdate({ + licenseUuid: this.instance.licenseUuid || "", + patchedLicenseRequest: data, + }) + : new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseCreate({ + licenseRequest: data, + }) + ).then((data) => { + window.dispatchEvent(new CustomEvent(EVENT_REFRESH_ENTERPRISE)); + return data; + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts index 0d2f16cf3f..324ebca257 100644 --- a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts +++ b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts @@ -1,6 +1,7 @@ import "@goauthentik/admin/enterprise/EnterpriseLicenseForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import { PFColor } from "@goauthentik/elements/Label"; import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/buttons/SpinnerButton"; @@ -35,6 +36,7 @@ import { @customElement("ak-enterprise-license-list") export class EnterpriseLicenseListPage extends TablePage { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; @@ -73,6 +75,9 @@ export class EnterpriseLicenseListPage extends TablePage { .pf-m-no-padding-bottom { padding-bottom: 0; } + .install-id { + word-break: break-all; + } `, ); } @@ -148,30 +153,11 @@ export class EnterpriseLicenseListPage extends TablePage { renderSectionBefore(): TemplateResult { return html` -
- ${msg("Enterprise is in preview.")} - ${msg("Send us feedback!")} -
-
-
${msg("Get a license")}
-
- ${this.installID - ? html` ${msg("Go to Customer Portal")}` - : html``} -
-
- + ${this.renderGetLicenseCard()} { subtext=${msg("Cumulative license expiry")} > ${this.summary?.hasLicense - ? this.summary.latestValid.toLocaleString() + ? html`
${getRelativeTime(this.summary.latestValid)}
+ ${this.summary.latestValid.toLocaleString()}` : "-"}
@@ -246,6 +233,43 @@ export class EnterpriseLicenseListPage extends TablePage { ]; } + renderGetLicenseCard() { + const renderSpinner = () => + html`
+ +
`; + + const installURL = (installID: string) => + [ + "https://customers.goauthentik.io/from_authentik/purchase/?install_id=", + encodeURIComponent(installID), + "&authentik_url=", + encodeURI(window.location.origin), + ].join(""); + + const renderCard = (installID: string) => html` +
${msg("Your Install ID")}
+
${installID}
+ + + `; + + return html`
+ ${this.installID ? renderCard(this.installID) : renderSpinner()} +
`; + } + renderObjectCreate(): TemplateResult { return html` diff --git a/web/src/admin/events/EventListPage.ts b/web/src/admin/events/EventListPage.ts index e005eb03a5..e4e1c7efc4 100644 --- a/web/src/admin/events/EventListPage.ts +++ b/web/src/admin/events/EventListPage.ts @@ -4,6 +4,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; import { actionToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-event-info"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; @@ -82,9 +83,9 @@ export class EventListPage extends TablePage { html`
${actionToLabel(item.action)}
${item.app}`, EventUser(item), - html`${item.created?.toLocaleString()}`, + html`
${getRelativeTime(item.created)}
+ ${item.created.toLocaleString()}`, html`
${item.clientIp || msg("-")}
- ${EventGeo(item)}`, html`${item.brand?.name || msg("-")}`, html` @@ -96,7 +97,7 @@ export class EventListPage extends TablePage { } renderExpanded(item: Event): TemplateResult { - return html` + return html`
diff --git a/web/src/admin/events/EventViewPage.ts b/web/src/admin/events/EventViewPage.ts index b3c57f2c4c..ddf29fbfbb 100644 --- a/web/src/admin/events/EventViewPage.ts +++ b/web/src/admin/events/EventViewPage.ts @@ -2,13 +2,14 @@ import { EventGeo, EventUser } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; import { actionToLabel } from "@goauthentik/common/labels"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-event-info"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/PageHeader"; import { msg, str } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import PFCard from "@patternfly/patternfly/components/Card/card.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; @@ -17,28 +18,32 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import { EventsApi } from "@goauthentik/api"; +import { EventToJSON, EventsApi } from "@goauthentik/api"; @customElement("ak-event-view") export class EventViewPage extends AKElement { - @property() - set eventID(value: string) { - new EventsApi(DEFAULT_CONFIG) - .eventsEventsRetrieve({ - eventUuid: value, - }) - .then((ev) => { - this.event = ev as EventWithContext; - }); - } + @property({ type: String }) + eventID?: string; - @property({ attribute: false }) + @state() event!: EventWithContext; static get styles(): CSSResult[] { return [PFBase, PFGrid, PFDescriptionList, PFPage, PFContent, PFCard]; } + fetchEvent(eventUuid: string) { + new EventsApi(DEFAULT_CONFIG).eventsEventsRetrieve({ eventUuid }).then((ev) => { + this.event = ev as EventWithContext; + }); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("eventID") && this.eventID) { + this.fetchEvent(this.eventID); + } + } + render(): TemplateResult { if (!this.event) { return html` @@ -99,7 +104,8 @@ export class EventViewPage extends AKElement {
- ${this.event.created?.toLocaleString()} +
${getRelativeTime(this.event.created)}
+ ${this.event.created.toLocaleString()}
@@ -137,7 +143,7 @@ export class EventViewPage extends AKElement {
${msg("Raw event info")}
-
${JSON.stringify(this.event, null, 4)}
+
${JSON.stringify(EventToJSON(this.event), null, 4)}
diff --git a/web/src/admin/events/EventVolumeChart.ts b/web/src/admin/events/EventVolumeChart.ts index da1710af02..623aa03456 100644 --- a/web/src/admin/events/EventVolumeChart.ts +++ b/web/src/admin/events/EventVolumeChart.ts @@ -1,5 +1,5 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { AKChart } from "@goauthentik/app/elements/charts/Chart"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { AKChart } from "@goauthentik/elements/charts/Chart"; import { ChartData } from "chart.js"; import { msg } from "@lit/localize"; diff --git a/web/src/admin/events/RuleForm.ts b/web/src/admin/events/RuleForm.ts index ed392a1ca3..7ee190047a 100644 --- a/web/src/admin/events/RuleForm.ts +++ b/web/src/admin/events/RuleForm.ts @@ -69,6 +69,7 @@ export class RuleForm extends ModelForm { .fetchObjects=${async (query?: string): Promise => { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/events/RuleListPage.ts b/web/src/admin/events/RuleListPage.ts index e997903b17..7afe34104e 100644 --- a/web/src/admin/events/RuleListPage.ts +++ b/web/src/admin/events/RuleListPage.ts @@ -27,6 +27,7 @@ import { export class RuleListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/events/TransportListPage.ts b/web/src/admin/events/TransportListPage.ts index c36c21af99..ffa4f6263d 100644 --- a/web/src/admin/events/TransportListPage.ts +++ b/web/src/admin/events/TransportListPage.ts @@ -38,6 +38,7 @@ export class TransportListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/events/utils.ts b/web/src/admin/events/utils.ts index ac41a10294..89999d39d6 100644 --- a/web/src/admin/events/utils.ts +++ b/web/src/admin/events/utils.ts @@ -1,5 +1,5 @@ -import { truncate } from "@goauthentik/app/common/utils"; import { EventWithContext } from "@goauthentik/common/events"; +import { truncate } from "@goauthentik/common/utils"; import { KeyUnknown } from "@goauthentik/elements/forms/Form"; import { msg, str } from "@lit/localize"; diff --git a/web/src/admin/flows/BoundStagesList.ts b/web/src/admin/flows/BoundStagesList.ts index 65eb7ec56a..316d4ca577 100644 --- a/web/src/admin/flows/BoundStagesList.ts +++ b/web/src/admin/flows/BoundStagesList.ts @@ -21,6 +21,9 @@ import { FlowStageBinding, FlowsApi } from "@goauthentik/api"; export class BoundStagesList extends Table { expandable = true; checkbox = true; + clearOnRefresh = true; + + order = "order"; @property() target?: string; @@ -28,7 +31,7 @@ export class BoundStagesList extends Table { async apiEndpoint(page: number): Promise> { return new FlowsApi(DEFAULT_CONFIG).flowsBindingsList({ target: this.target || "", - ordering: "order", + ordering: this.order, page: page, pageSize: (await uiConfig()).pagination.perPage, }); @@ -36,8 +39,8 @@ export class BoundStagesList extends Table { columns(): TableColumn[] { return [ - new TableColumn(msg("Order")), - new TableColumn(msg("Name")), + new TableColumn(msg("Order"), "order"), + new TableColumn(msg("Name"), "stage__name"), new TableColumn(msg("Type")), new TableColumn(msg("Actions")), ]; diff --git a/web/src/admin/flows/FlowImportForm.ts b/web/src/admin/flows/FlowImportForm.ts index 310269ff88..8aa5a551c3 100644 --- a/web/src/admin/flows/FlowImportForm.ts +++ b/web/src/admin/flows/FlowImportForm.ts @@ -1,6 +1,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { SentryIgnoredError } from "@goauthentik/common/errors"; import "@goauthentik/components/ak-status-label"; +import "@goauthentik/elements/events/LogViewer"; import { Form } from "@goauthentik/elements/forms/Form"; import "@goauthentik/elements/forms/HorizontalFormElement"; @@ -55,28 +56,7 @@ export class FlowImportForm extends Form {
- ${(this.result?.logs || []).length > 0 - ? this.result?.logs?.map((m) => { - return html`
-
- ${m.log_level} -
-
-
- ${m.event} -
-
-
`; - }) - : html`
-
- ${msg("No log messages.")} -
-
`} +
diff --git a/web/src/admin/flows/FlowListPage.ts b/web/src/admin/flows/FlowListPage.ts index 5bcc6205d4..1e264dc92e 100644 --- a/web/src/admin/flows/FlowListPage.ts +++ b/web/src/admin/flows/FlowListPage.ts @@ -37,6 +37,7 @@ export class FlowListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "slug"; diff --git a/web/src/admin/flows/FlowViewPage.ts b/web/src/admin/flows/FlowViewPage.ts index c760821e50..e7c42c1d6c 100644 --- a/web/src/admin/flows/FlowViewPage.ts +++ b/web/src/admin/flows/FlowViewPage.ts @@ -1,19 +1,19 @@ import "@goauthentik/admin/flows/BoundStagesList"; import "@goauthentik/admin/flows/FlowDiagram"; import "@goauthentik/admin/flows/FlowForm"; +import { DesignationToLabel } from "@goauthentik/admin/flows/utils"; import "@goauthentik/admin/policies/BoundPoliciesList"; -import { DesignationToLabel } from "@goauthentik/app/admin/flows/utils"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { AndNext, DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import "@goauthentik/components/events/ObjectChangelog"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, css, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFCard from "@patternfly/patternfly/components/Card/card.css"; @@ -32,18 +32,10 @@ import { @customElement("ak-flow-view") export class FlowViewPage extends AKElement { - @property() - set flowSlug(value: string) { - new FlowsApi(DEFAULT_CONFIG) - .flowsInstancesRetrieve({ - slug: value, - }) - .then((flow) => { - this.flow = flow; - }); - } + @property({ type: String }) + flowSlug?: string; - @property({ attribute: false }) + @state() flow!: Flow; static get styles(): CSSResult[] { @@ -57,6 +49,18 @@ export class FlowViewPage extends AKElement { `); } + fetchFlow(slug: string) { + new FlowsApi(DEFAULT_CONFIG).flowsInstancesRetrieve({ slug }).then((flow) => { + this.flow = flow; + }); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("flowSlug") && this.flowSlug) { + this.fetchFlow(this.flowSlug); + } + } + render(): TemplateResult { if (!this.flow) { return html``; diff --git a/web/src/admin/groups/GroupForm.ts b/web/src/admin/groups/GroupForm.ts index b55cafb566..c8be5f65bd 100644 --- a/web/src/admin/groups/GroupForm.ts +++ b/web/src/admin/groups/GroupForm.ts @@ -3,6 +3,8 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; import "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; +import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; +import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; import "@goauthentik/elements/chips/Chip"; import "@goauthentik/elements/chips/ChipGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; @@ -12,22 +14,17 @@ import YAML from "yaml"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; -import { customElement, state } from "lit/decorators.js"; +import { customElement } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; -import { - CoreApi, - CoreGroupsListRequest, - Group, - PaginatedRoleList, - RbacApi, -} from "@goauthentik/api"; +import { CoreApi, CoreGroupsListRequest, Group, RbacApi, Role } from "@goauthentik/api"; + +export function rbacRolePair(item: Role): DualSelectPair { + return [item.pk, html`
${item.name}
`, item.name]; +} @customElement("ak-group-form") export class GroupForm extends ModelForm { - @state() - roles?: PaginatedRoleList; - static get styles(): CSSResult[] { return super.styles.concat(css` .pf-c-button.pf-m-control { @@ -42,6 +39,7 @@ export class GroupForm extends ModelForm { loadInstance(pk: string): Promise { return new CoreApi(DEFAULT_CONFIG).coreGroupsRetrieve({ groupUuid: pk, + includeUsers: false, }); } @@ -51,12 +49,6 @@ export class GroupForm extends ModelForm { : msg("Successfully created group."); } - async load(): Promise { - this.roles = await new RbacApi(DEFAULT_CONFIG).rbacRolesList({ - ordering: "name", - }); - } - async send(data: Group): Promise { if (this.instance?.pk) { return new CoreApi(DEFAULT_CONFIG).coreGroupsPartialUpdate({ @@ -127,24 +119,29 @@ export class GroupForm extends ModelForm { - + => { + return new RbacApi(DEFAULT_CONFIG) + .rbacRolesList({ + page: page, + search: search, + }) + .then((results) => { + return { + pagination: results.pagination, + options: results.results.map(rbacRolePair), + }; + }); + }} + .selected=${(this.instance?.rolesObj ?? []).map(rbacRolePair)} + available-label="${msg("Available Roles")}" + selected-label="${msg("Selected Roles")}" + >

${msg( "Select roles to grant this groups' users' permissions from the selected roles.", )}

-

- ${msg("Hold control/command to select multiple items.")} -

{ checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } @@ -41,6 +42,7 @@ export class GroupListPage extends TablePage { page: page, pageSize: (await uiConfig()).pagination.perPage, search: this.search || "", + includeUsers: false, }); } diff --git a/web/src/admin/groups/GroupViewPage.ts b/web/src/admin/groups/GroupViewPage.ts index cd95a14e35..438d083be2 100644 --- a/web/src/admin/groups/GroupViewPage.ts +++ b/web/src/admin/groups/GroupViewPage.ts @@ -1,6 +1,5 @@ import "@goauthentik/admin/groups/GroupForm"; -import "@goauthentik/app/admin/groups/RelatedUserList"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; +import "@goauthentik/admin/groups/RelatedUserList"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/ak-status-label"; @@ -12,6 +11,7 @@ import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; @@ -37,6 +37,7 @@ export class GroupViewPage extends AKElement { new CoreApi(DEFAULT_CONFIG) .coreGroupsRetrieve({ groupUuid: id, + includeUsers: false, }) .then((group) => { this.group = group; @@ -199,7 +200,6 @@ export class GroupViewPage extends AKElement {
- { page: page, pageSize: (await uiConfig()).pagination.perPage, search: this.search || "", + includeGroups: false, }); } @@ -49,7 +50,10 @@ export class MemberSelectTable extends TableModal { html`
${item.username}
${item.name}`, html` `, - html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`, + html`${item.lastLogin + ? html`
${getRelativeTime(item.lastLogin)}
+ ${item.lastLogin.toLocaleString()}` + : msg("-")}`, ]; } diff --git a/web/src/admin/groups/RelatedGroupList.ts b/web/src/admin/groups/RelatedGroupList.ts index 19adf12767..e1c253fd1a 100644 --- a/web/src/admin/groups/RelatedGroupList.ts +++ b/web/src/admin/groups/RelatedGroupList.ts @@ -87,6 +87,7 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> { @customElement("ak-group-related-list") export class RelatedGroupList extends Table { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } @@ -104,6 +105,7 @@ export class RelatedGroupList extends Table { pageSize: (await uiConfig()).pagination.perPage, search: this.search || "", membersByPk: this.targetUser ? [this.targetUser.pk] : [], + includeUsers: false, }); } @@ -124,6 +126,7 @@ export class RelatedGroupList extends Table { actionSubtext=${msg( str`Are you sure you want to remove user ${this.targetUser?.username} from the following groups?`, )} + buttonLabel=${msg("Remove")} .objects=${this.selectedElements} .delete=${(item: Group) => { if (!this.targetUser) return; diff --git a/web/src/admin/groups/RelatedUserList.ts b/web/src/admin/groups/RelatedUserList.ts index 91feb6cd40..fd502e6736 100644 --- a/web/src/admin/groups/RelatedUserList.ts +++ b/web/src/admin/groups/RelatedUserList.ts @@ -3,11 +3,11 @@ import "@goauthentik/admin/users/UserActiveForm"; import "@goauthentik/admin/users/UserForm"; import "@goauthentik/admin/users/UserPasswordForm"; import "@goauthentik/admin/users/UserResetEmailForm"; -import { me } from "@goauthentik/app/common/users"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { MessageLevel } from "@goauthentik/common/messages"; import { uiConfig } from "@goauthentik/common/ui/config"; -import { first } from "@goauthentik/common/utils"; +import { me } from "@goauthentik/common/users"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; import { @@ -113,6 +113,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> { export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Table)) { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; @@ -144,6 +145,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl type: this.hideServiceAccounts ? [CoreUsersListTypeEnum.External, CoreUsersListTypeEnum.Internal] : undefined, + includeGroups: false, }); this.me = await me(); return users; @@ -163,6 +165,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl return html`${item.name}
`, html``, - html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`, + html`${item.lastLogin + ? html`
${getRelativeTime(item.lastLogin)}
+ ${item.lastLogin.toLocaleString()}` + : msg("-")}`, html` ${msg("Update")} ${msg("Update User")} @@ -301,7 +307,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl class="pf-m-secondary" .apiRequest=${() => { return new CoreApi(DEFAULT_CONFIG) - .coreUsersRecoveryRetrieve({ + .coreUsersRecoveryCreate({ id: item.pk, }) .then((rec) => { diff --git a/web/src/admin/outposts/OutpostForm.ts b/web/src/admin/outposts/OutpostForm.ts index 7c6c9dda57..d5791caded 100644 --- a/web/src/admin/outposts/OutpostForm.ts +++ b/web/src/admin/outposts/OutpostForm.ts @@ -3,16 +3,20 @@ import { docLink } from "@goauthentik/common/global"; import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; +import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; +import { DataProvider, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; +import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { map } from "lit/directives/map.js"; import { Outpost, @@ -20,14 +24,70 @@ import { OutpostTypeEnum, OutpostsApi, OutpostsServiceConnectionsAllListRequest, - PaginatedLDAPProviderList, - PaginatedProxyProviderList, - PaginatedRACProviderList, - PaginatedRadiusProviderList, ProvidersApi, ServiceConnection, } from "@goauthentik/api"; +interface ProviderBase { + pk: number; + name: string; + assignedBackchannelApplicationName?: string; + assignedApplicationName?: string; +} + +const api = () => new ProvidersApi(DEFAULT_CONFIG); +const providerListArgs = (page: number, search = "") => ({ + ordering: "name", + applicationIsnull: false, + pageSize: 20, + search: search.trim(), + page, +}); + +const dualSelectPairMaker = (item: ProviderBase): DualSelectPair => { + const label = item.assignedBackchannelApplicationName + ? item.assignedBackchannelApplicationName + : item.assignedApplicationName; + return [ + `${item.pk}`, + html`
${label}
+
${item.name}
`, + label, + ]; +}; + +const provisionMaker = (results: PaginatedResponse) => ({ + pagination: results.pagination, + options: results.results.map(dualSelectPairMaker), +}); + +const proxyListFetch = async (page: number, search = "") => + provisionMaker(await api().providersProxyList(providerListArgs(page, search))); + +const ldapListFetch = async (page: number, search = "") => + provisionMaker(await api().providersLdapList(providerListArgs(page, search))); + +const radiusListFetch = async (page: number, search = "") => + provisionMaker(await api().providersRadiusList(providerListArgs(page, search))); + +const racListProvider = async (page: number, search = "") => + provisionMaker(await api().providersRacList(providerListArgs(page, search))); + +function providerProvider(type: OutpostTypeEnum): DataProvider { + switch (type) { + case OutpostTypeEnum.Proxy: + return proxyListFetch; + case OutpostTypeEnum.Ldap: + return ldapListFetch; + case OutpostTypeEnum.Radius: + return radiusListFetch; + case OutpostTypeEnum.Rac: + return racListProvider; + default: + throw new Error(`Unrecognized OutputType: ${type}`); + } +} + @customElement("ak-outpost-form") export class OutpostForm extends ModelForm { @property() @@ -37,12 +97,7 @@ export class OutpostForm extends ModelForm { embedded = false; @state() - providers?: - | PaginatedProxyProviderList - | PaginatedLDAPProviderList - | PaginatedRadiusProviderList - | PaginatedRACProviderList; - + providers?: DataProvider; defaultConfig?: OutpostDefaultConfig; async loadInstance(pk: string): Promise { @@ -57,34 +112,7 @@ export class OutpostForm extends ModelForm { this.defaultConfig = await new OutpostsApi( DEFAULT_CONFIG, ).outpostsInstancesDefaultSettingsRetrieve(); - switch (this.type) { - case OutpostTypeEnum.Proxy: - this.providers = await new ProvidersApi(DEFAULT_CONFIG).providersProxyList({ - ordering: "name", - applicationIsnull: false, - }); - break; - case OutpostTypeEnum.Ldap: - this.providers = await new ProvidersApi(DEFAULT_CONFIG).providersLdapList({ - ordering: "name", - applicationIsnull: false, - }); - break; - case OutpostTypeEnum.Radius: - this.providers = await new ProvidersApi(DEFAULT_CONFIG).providersRadiusList({ - ordering: "name", - applicationIsnull: false, - }); - break; - case OutpostTypeEnum.Rac: - this.providers = await new ProvidersApi(DEFAULT_CONFIG).providersRacList({ - ordering: "name", - applicationIsnull: false, - }); - break; - case OutpostTypeEnum.UnknownDefaultOpenApi: - this.providers = undefined; - } + this.providers = providerProvider(this.type); } getSuccessMessage(): string { @@ -107,6 +135,13 @@ export class OutpostForm extends ModelForm { } renderForm(): TemplateResult { + const typeOptions = [ + [OutpostTypeEnum.Proxy, msg("Proxy")], + [OutpostTypeEnum.Ldap, msg("LDAP")], + [OutpostTypeEnum.Radius, msg("Radius")], + [OutpostTypeEnum.Rac, msg("RAC")], + ]; + return html` { this.load(); }} > - - - - + ${map( + typeOptions, + ([instanceType, label]) => + html` `, + )} @@ -200,48 +221,38 @@ export class OutpostForm extends ModelForm { ?required=${!this.embedded} name="providers" > - -

- ${msg("You can only select providers that match the type of the outpost.")} -

-

- ${msg("Hold control/command to select multiple items.")} -

+
${msg("Advanced settings")} - - -

- ${msg("Set custom attributes using YAML or JSON.")} -

-

- ${msg("See more here:")}  - ${msg("Documentation")} -

-
+
+ + +

+ ${msg("Set custom attributes using YAML or JSON.")} +

+

+ ${msg("See more here:")}  + ${msg("Documentation")} +

+
+
`; } } diff --git a/web/src/admin/outposts/OutpostHealth.ts b/web/src/admin/outposts/OutpostHealth.ts index 1a97101751..2b0203748e 100644 --- a/web/src/admin/outposts/OutpostHealth.ts +++ b/web/src/admin/outposts/OutpostHealth.ts @@ -34,10 +34,12 @@ export class OutpostHealthElement extends AKElement { } let versionString = this.outpostHealth.version; if (this.outpostHealth.buildHash) { - versionString = `${versionString} (build ${this.outpostHealth.buildHash.substring( - 0, - 8, - )})`; + versionString = msg( + str`${versionString} (build ${this.outpostHealth.buildHash.substring(0, 8)})`, + ); + } + if (this.outpostHealth.fipsEnabled) { + versionString = msg(str`${versionString} (FIPS)`); } return html`
diff --git a/web/src/admin/outposts/OutpostListPage.ts b/web/src/admin/outposts/OutpostListPage.ts index 3183555851..5928e5ebb0 100644 --- a/web/src/admin/outposts/OutpostListPage.ts +++ b/web/src/admin/outposts/OutpostListPage.ts @@ -4,9 +4,9 @@ import "@goauthentik/admin/outposts/OutpostForm"; import "@goauthentik/admin/outposts/OutpostHealth"; import "@goauthentik/admin/outposts/OutpostHealthSimple"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PFSize } from "@goauthentik/common/enums.js"; import { uiConfig } from "@goauthentik/common/ui/config"; import { PFColor } from "@goauthentik/elements/Label"; -import { PFSize } from "@goauthentik/elements/Spinner"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; @@ -107,6 +107,7 @@ export class OutpostListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/outposts/ServiceConnectionListPage.ts b/web/src/admin/outposts/ServiceConnectionListPage.ts index a212358f56..e4bea38813 100644 --- a/web/src/admin/outposts/ServiceConnectionListPage.ts +++ b/web/src/admin/outposts/ServiceConnectionListPage.ts @@ -39,6 +39,7 @@ export class OutpostServiceConnectionListPage extends TablePage> { const connections = await new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList( diff --git a/web/src/admin/outposts/ServiceConnectionWizard.ts b/web/src/admin/outposts/ServiceConnectionWizard.ts index 5f221fee31..4feed47476 100644 --- a/web/src/admin/outposts/ServiceConnectionWizard.ts +++ b/web/src/admin/outposts/ServiceConnectionWizard.ts @@ -4,73 +4,24 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import type { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { CSSResult, TemplateResult, html } from "lit"; -import { property } from "lit/decorators.js"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { OutpostsApi, TypeCreate } from "@goauthentik/api"; -@customElement("ak-service-connection-wizard-initial") -export class InitialServiceConnectionWizardPage extends WizardPage { - @property({ attribute: false }) - connectionTypes: TypeCreate[] = []; - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFButton, PFRadio]; - } - sidebarLabel = () => msg("Select type"); - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - render(): TemplateResult { - return html`
- ${this.connectionTypes.map((type) => { - return html`
- { - this.host.steps = [ - "initial", - `type-${type.component}-${type.modelName}`, - ]; - this.host.isValid = true; - }} - /> - - ${type.description} -
`; - })} -
`; - } -} - @customElement("ak-service-connection-wizard") export class ServiceConnectionWizard extends AKElement { static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + return [PFBase, PFButton]; } @property() @@ -79,6 +30,9 @@ export class ServiceConnectionWizard extends AKElement { @property({ attribute: false }) connectionTypes: TypeCreate[] = []; + @query("ak-wizard") + wizard?: Wizard; + firstUpdated(): void { new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllTypesList().then((types) => { this.connectionTypes = types; @@ -92,11 +46,19 @@ export class ServiceConnectionWizard extends AKElement { header=${msg("New outpost integration")} description=${msg("Create a new outpost integration.")} > - ) => { + if (!this.wizard) return; + this.wizard.steps = [ + "initial", + `type-${ev.detail.component}-${ev.detail.modelName}`, + ]; + this.wizard.isValid = true; + }} > - + ${this.connectionTypes.map((type) => { return html` { policyOnly = false; checkbox = true; + clearOnRefresh = true; + + order = "order"; async apiEndpoint(page: number): Promise> { return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({ target: this.target || "", - ordering: "order", + ordering: this.order, page: page, pageSize: (await uiConfig()).pagination.perPage, }); diff --git a/web/src/admin/policies/PolicyBindingForm.ts b/web/src/admin/policies/PolicyBindingForm.ts index c98d0082b2..de711f4139 100644 --- a/web/src/admin/policies/PolicyBindingForm.ts +++ b/web/src/admin/policies/PolicyBindingForm.ts @@ -179,6 +179,7 @@ export class PolicyBindingForm extends ModelForm { .fetchObjects=${async (query?: string): Promise => { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/policies/PolicyListPage.ts b/web/src/admin/policies/PolicyListPage.ts index 9a1dda2158..b792df2110 100644 --- a/web/src/admin/policies/PolicyListPage.ts +++ b/web/src/admin/policies/PolicyListPage.ts @@ -44,6 +44,7 @@ export class PolicyListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/policies/PolicyTestForm.ts b/web/src/admin/policies/PolicyTestForm.ts index 50771abbdb..6e57301676 100644 --- a/web/src/admin/policies/PolicyTestForm.ts +++ b/web/src/admin/policies/PolicyTestForm.ts @@ -3,6 +3,7 @@ import { first } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; +import "@goauthentik/elements/events/LogViewer"; import { Form } from "@goauthentik/elements/forms/Form"; import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/SearchSelect"; @@ -85,28 +86,7 @@ export class PolicyTestForm extends Form {
- ${(this.result?.logMessages || []).length > 0 - ? this.result?.logMessages?.map((m) => { - return html`
-
- ${m.log_level} -
-
-
- ${m.event} -
-
-
`; - }) - : html`
-
- ${msg("No log messages.")} -
-
`} +
diff --git a/web/src/admin/policies/PolicyWizard.ts b/web/src/admin/policies/PolicyWizard.ts index c1a36fe53a..c66e953249 100644 --- a/web/src/admin/policies/PolicyWizard.ts +++ b/web/src/admin/policies/PolicyWizard.ts @@ -10,80 +10,24 @@ import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; import { FormWizardPage } from "@goauthentik/elements/wizard/FormWizardPage"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import type { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { CSSResult, TemplateResult, html } from "lit"; -import { property } from "lit/decorators.js"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { PoliciesApi, Policy, PolicyBinding, TypeCreate } from "@goauthentik/api"; -@customElement("ak-policy-wizard-initial") -export class InitialPolicyWizardPage extends WizardPage { - @property({ attribute: false }) - policyTypes: TypeCreate[] = []; - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFButton, PFRadio]; - } - sidebarLabel = () => msg("Select type"); - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - render(): TemplateResult { - return html`
- ${this.policyTypes.map((type) => { - return html`
- { - const idx = this.host.steps.indexOf("initial") + 1; - // Exclude all current steps starting with type-, - // this happens when the user selects a type and then goes back - this.host.steps = this.host.steps.filter( - (step) => !step.startsWith("type-"), - ); - this.host.steps.splice( - idx, - 0, - `type-${type.component}-${type.modelName}`, - ); - this.host.isValid = true; - }} - /> - - ${type.description} -
`; - })} -
`; - } -} - @customElement("ak-policy-wizard") export class PolicyWizard extends AKElement { static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + return [PFBase, PFButton]; } @property() @@ -98,6 +42,9 @@ export class PolicyWizard extends AKElement { @property({ attribute: false }) policyTypes: TypeCreate[] = []; + @query("ak-wizard") + wizard?: Wizard; + firstUpdated(): void { new PoliciesApi(DEFAULT_CONFIG).policiesAllTypesList().then((types) => { this.policyTypes = types; @@ -111,8 +58,26 @@ export class PolicyWizard extends AKElement { header=${msg("New policy")} description=${msg("Create a new policy.")} > - - + ) => { + if (!this.wizard) return; + const idx = this.wizard.steps.indexOf("initial") + 1; + // Exclude all current steps starting with type-, + // this happens when the user selects a type and then goes back + this.wizard.steps = this.wizard.steps.filter( + (step) => !step.startsWith("type-"), + ); + this.wizard.steps.splice( + idx, + 0, + `type-${ev.detail.component}-${ev.detail.modelName}`, + ); + this.wizard.isValid = true; + }} + > + ${this.policyTypes.map((type) => { return html` { order = "identifier"; checkbox = true; + clearOnRefresh = true; async apiEndpoint(page: number): Promise> { return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({ @@ -91,7 +93,8 @@ export class ReputationListPage extends TablePage { : html``} ${item.ip}`, html`${item.score}`, - html`${item.updated.toLocaleString()}`, + html`
${getRelativeTime(item.updated)}
+ ${item.updated.toLocaleString()}`, html` { + loadInstance(pk: string): Promise { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderGoogleWorkspaceRetrieve({ + pmUuid: pk, + }); + } + + async send(data: GoogleWorkspaceProviderMapping): Promise { + if (this.instance) { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderGoogleWorkspaceUpdate({ + pmUuid: this.instance.pk, + googleWorkspaceProviderMappingRequest: data, + }); + } else { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderGoogleWorkspaceCreate({ + googleWorkspaceProviderMappingRequest: data, + }); + } + } + + renderForm(): TemplateResult { + return html` + + + + + +

+ ${msg("Expression using Python.")} + + ${msg("See documentation for a list of all variables.")} + +

+
`; + } +} diff --git a/web/src/admin/property-mappings/PropertyMappingLDAPForm.ts b/web/src/admin/property-mappings/PropertyMappingLDAPForm.ts index 0b5afe81b0..4647a3e70a 100644 --- a/web/src/admin/property-mappings/PropertyMappingLDAPForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingLDAPForm.ts @@ -23,7 +23,7 @@ export class PropertyMappingLDAPForm extends BasePropertyMappingForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsLdapUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, lDAPPropertyMappingRequest: data, }); } else { diff --git a/web/src/admin/property-mappings/PropertyMappingListPage.ts b/web/src/admin/property-mappings/PropertyMappingListPage.ts index 18521f5e47..be9eb3ed66 100644 --- a/web/src/admin/property-mappings/PropertyMappingListPage.ts +++ b/web/src/admin/property-mappings/PropertyMappingListPage.ts @@ -1,4 +1,6 @@ +import "@goauthentik/admin/property-mappings/PropertyMappingGoogleWorkspaceForm"; import "@goauthentik/admin/property-mappings/PropertyMappingLDAPForm"; +import "@goauthentik/admin/property-mappings/PropertyMappingMicrosoftEntraForm"; import "@goauthentik/admin/property-mappings/PropertyMappingNotification"; import "@goauthentik/admin/property-mappings/PropertyMappingRACForm"; import "@goauthentik/admin/property-mappings/PropertyMappingSAMLForm"; @@ -41,6 +43,7 @@ export class PropertyMappingListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/property-mappings/PropertyMappingMicrosoftEntraForm.ts b/web/src/admin/property-mappings/PropertyMappingMicrosoftEntraForm.ts new file mode 100644 index 0000000000..c517616f8b --- /dev/null +++ b/web/src/admin/property-mappings/PropertyMappingMicrosoftEntraForm.ts @@ -0,0 +1,72 @@ +import { BasePropertyMappingForm } from "@goauthentik/admin/property-mappings/BasePropertyMappingForm"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { docLink } from "@goauthentik/common/global"; +import "@goauthentik/elements/CodeMirror"; +import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; +import "@goauthentik/elements/forms/HorizontalFormElement"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; + +import { MicrosoftEntraProviderMapping, PropertymappingsApi } from "@goauthentik/api"; + +@customElement("ak-property-mapping-microsoft-entra-form") +export class PropertyMappingMicrosoftEntraForm extends BasePropertyMappingForm { + loadInstance(pk: string): Promise { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderMicrosoftEntraRetrieve({ + pmUuid: pk, + }); + } + + async send(data: MicrosoftEntraProviderMapping): Promise { + if (this.instance) { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderMicrosoftEntraUpdate({ + pmUuid: this.instance.pk, + microsoftEntraProviderMappingRequest: data, + }); + } else { + return new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderMicrosoftEntraCreate({ + microsoftEntraProviderMappingRequest: data, + }); + } + } + + renderForm(): TemplateResult { + return html` + + + + + +

+ ${msg("Expression using Python.")} + + ${msg("See documentation for a list of all variables.")} + +

+
`; + } +} diff --git a/web/src/admin/property-mappings/PropertyMappingNotification.ts b/web/src/admin/property-mappings/PropertyMappingNotification.ts index 9991d2a32f..fe88b1a8c1 100644 --- a/web/src/admin/property-mappings/PropertyMappingNotification.ts +++ b/web/src/admin/property-mappings/PropertyMappingNotification.ts @@ -29,7 +29,7 @@ export class PropertyMappingNotification extends ModelForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsNotificationUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, notificationWebhookMappingRequest: data, }); } else { diff --git a/web/src/admin/property-mappings/PropertyMappingRACForm.ts b/web/src/admin/property-mappings/PropertyMappingRACForm.ts index 72e2bb0906..23609c7bb7 100644 --- a/web/src/admin/property-mappings/PropertyMappingRACForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingRACForm.ts @@ -1,4 +1,3 @@ -import { first } from "@goauthentik/app/common/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { docLink } from "@goauthentik/common/global"; import "@goauthentik/elements/CodeMirror"; @@ -6,6 +5,8 @@ import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; +import "@goauthentik/elements/forms/Radio"; +import type { RadioOption } from "@goauthentik/elements/forms/Radio"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -14,6 +15,23 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { PropertymappingsApi, RACPropertyMapping } from "@goauthentik/api"; +export const staticSettingOptions: RadioOption[] = [ + { + label: msg("Unconfigured"), + value: undefined, + default: true, + description: html`${msg("This option will not be changed by this mapping.")}`, + }, + { + label: msg("Enabled"), + value: "true", + }, + { + label: msg("Disabled"), + value: "false", + }, +]; + @customElement("ak-property-mapping-rac-form") export class PropertyMappingLDAPForm extends ModelForm { loadInstance(pk: string): Promise { @@ -33,7 +51,7 @@ export class PropertyMappingLDAPForm extends ModelForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsRacUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, rACPropertyMappingRequest: data, }); } else { @@ -58,7 +76,6 @@ export class PropertyMappingLDAPForm extends ModelForm ${msg("RDP settings")}
- - + + + - - + + + - - + + + - - + + +
diff --git a/web/src/admin/property-mappings/PropertyMappingSAMLForm.ts b/web/src/admin/property-mappings/PropertyMappingSAMLForm.ts index 101455c84c..9371bb5caa 100644 --- a/web/src/admin/property-mappings/PropertyMappingSAMLForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingSAMLForm.ts @@ -23,7 +23,7 @@ export class PropertyMappingSAMLForm extends BasePropertyMappingForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, sAMLPropertyMappingRequest: data, }); } else { diff --git a/web/src/admin/property-mappings/PropertyMappingSCIMForm.ts b/web/src/admin/property-mappings/PropertyMappingSCIMForm.ts index 30993cbbd5..51bcfc65d3 100644 --- a/web/src/admin/property-mappings/PropertyMappingSCIMForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingSCIMForm.ts @@ -23,7 +23,7 @@ export class PropertyMappingSCIMForm extends BasePropertyMappingForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScimUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, sCIMMappingRequest: data, }); } else { diff --git a/web/src/admin/property-mappings/PropertyMappingScopeForm.ts b/web/src/admin/property-mappings/PropertyMappingScopeForm.ts index 3df60889f8..6403e0c6ec 100644 --- a/web/src/admin/property-mappings/PropertyMappingScopeForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingScopeForm.ts @@ -23,7 +23,7 @@ export class PropertyMappingScopeForm extends BasePropertyMappingForm { if (this.instance) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeUpdate({ - pmUuid: this.instance.pk || "", + pmUuid: this.instance.pk, scopeMappingRequest: data, }); } else { diff --git a/web/src/admin/property-mappings/PropertyMappingTestForm.ts b/web/src/admin/property-mappings/PropertyMappingTestForm.ts index e81af9a0c8..ff348f5530 100644 --- a/web/src/admin/property-mappings/PropertyMappingTestForm.ts +++ b/web/src/admin/property-mappings/PropertyMappingTestForm.ts @@ -14,16 +14,18 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { CoreApi, + CoreGroupsListRequest, CoreUsersListRequest, - PolicyTestRequest, + Group, PropertyMapping, + PropertyMappingTestRequest, PropertyMappingTestResult, PropertymappingsApi, User, } from "@goauthentik/api"; @customElement("ak-property-mapping-test-form") -export class PolicyTestForm extends Form { +export class PolicyTestForm extends Form { @property({ attribute: false }) mapping?: PropertyMapping; @@ -31,17 +33,17 @@ export class PolicyTestForm extends Form { result?: PropertyMappingTestResult; @property({ attribute: false }) - request?: PolicyTestRequest; + request?: PropertyMappingTestRequest; getSuccessMessage(): string { return msg("Successfully sent test-request."); } - async send(data: PolicyTestRequest): Promise { + async send(data: PropertyMappingTestRequest): Promise { this.request = data; const result = await new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllTestCreate({ pmUuid: this.mapping?.pk || "", - policyTestRequest: data, + propertyMappingTestRequest: data, formatResult: true, }); return (this.result = result); @@ -84,12 +86,14 @@ export class PolicyTestForm extends Form { user: this.request?.user || 0, context: { ldap: { - name: "test-user", - objectSid: "S-1-5-21-2611707862-2219215769-354220275-1137", - objectClass: "person", displayName: "authentik test user", - sAMAccountName: "sAMAccountName", distinguishedName: "cn=user,ou=users,dc=goauthentik,dc=io", + givenName: "test", + name: "test-user", + objectClass: "person", + objectSid: "S-1-5-21-2611707862-2219215769-354220275-1137", + sAMAccountName: "sAMAccountName", + sn: "user", }, }, }; @@ -120,7 +124,7 @@ export class PolicyTestForm extends Form { } renderForm(): TemplateResult { - return html` + return html` => { const args: CoreUsersListRequest = { @@ -142,7 +146,31 @@ export class PolicyTestForm extends Form { return user?.pk; }} .selected=${(user: User): boolean => { - return this.request?.user.toString() === user.pk.toString(); + return this.request?.user?.toString() === user.pk.toString(); + }} + > + + + + => { + const args: CoreGroupsListRequest = { + ordering: "name", + }; + if (query !== undefined) { + args.search = query; + } + const groups = await new CoreApi(DEFAULT_CONFIG).coreGroupsList(args); + return groups.results; + }} + .renderElement=${(group: Group): string => { + return group.name; + }} + .value=${(group: Group | undefined): string | undefined => { + return group?.pk; + }} + .selected=${(group: Group): boolean => { + return this.request?.group?.toString() === group.pk.toString(); }} > diff --git a/web/src/admin/property-mappings/PropertyMappingWizard.ts b/web/src/admin/property-mappings/PropertyMappingWizard.ts index 59b62c39c9..a8ceea2760 100644 --- a/web/src/admin/property-mappings/PropertyMappingWizard.ts +++ b/web/src/admin/property-mappings/PropertyMappingWizard.ts @@ -5,104 +5,39 @@ import "@goauthentik/admin/property-mappings/PropertyMappingSAMLForm"; import "@goauthentik/admin/property-mappings/PropertyMappingScopeForm"; import "@goauthentik/admin/property-mappings/PropertyMappingTestForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; -import "@goauthentik/elements/Alert"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import type { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; -import { CSSResult, TemplateResult, html, nothing } from "lit"; -import { property, state } from "lit/decorators.js"; +import { TemplateResult, html } from "lit"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import { EnterpriseApi, LicenseSummary, PropertymappingsApi, TypeCreate } from "@goauthentik/api"; - -@customElement("ak-property-mapping-wizard-initial") -export class InitialPropertyMappingWizardPage extends WizardPage { - @property({ attribute: false }) - mappingTypes: TypeCreate[] = []; - - @property({ attribute: false }) - enterprise?: LicenseSummary; - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFButton, PFRadio]; - } - sidebarLabel = () => msg("Select type"); - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - render(): TemplateResult { - return html`
- ${this.mappingTypes.map((type) => { - return html`
- { - this.host.steps = [ - "initial", - `type-${type.component}-${type.modelName}`, - ]; - this.host.isValid = true; - }} - ?disabled=${type.requiresEnterprise ? this.enterprise?.hasLicense : false} - /> - - ${type.description} - ${type.requiresEnterprise && !this.enterprise?.hasLicense - ? html` - - ${msg("Provider require enterprise.")} - ${msg("Learn more")} - - ` - : nothing} -
`; - })} -
`; - } -} +import { PropertymappingsApi, TypeCreate } from "@goauthentik/api"; @customElement("ak-property-mapping-wizard") export class PropertyMappingWizard extends AKElement { - static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + static get styles() { + return [PFBase, PFButton]; } @property({ attribute: false }) mappingTypes: TypeCreate[] = []; - @state() - enterprise?: LicenseSummary; + @query("ak-wizard") + wizard?: Wizard; async firstUpdated(): Promise { this.mappingTypes = await new PropertymappingsApi( DEFAULT_CONFIG, ).propertymappingsAllTypesList(); - this.enterprise = await new EnterpriseApi( - DEFAULT_CONFIG, - ).enterpriseLicenseSummaryRetrieve(); } render(): TemplateResult { @@ -112,12 +47,19 @@ export class PropertyMappingWizard extends AKElement { header=${msg("New property mapping")} description=${msg("Create a new property mapping.")} > - ) => { + if (!this.wizard) return; + this.wizard.steps = [ + "initial", + `type-${ev.detail.component}-${ev.detail.modelName}`, + ]; + this.wizard.isValid = true; + }} > - + ${this.mappingTypes.map((type) => { return html` { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/providers/ProviderViewPage.ts b/web/src/admin/providers/ProviderViewPage.ts index 5cebd14dd9..a1e2a4ce2e 100644 --- a/web/src/admin/providers/ProviderViewPage.ts +++ b/web/src/admin/providers/ProviderViewPage.ts @@ -1,4 +1,6 @@ +import "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderViewPage"; import "@goauthentik/admin/providers/ldap/LDAPProviderViewPage"; +import "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderViewPage"; import "@goauthentik/admin/providers/oauth2/OAuth2ProviderViewPage"; import "@goauthentik/admin/providers/proxy/ProxyProviderViewPage"; import "@goauthentik/admin/providers/rac/RACProviderViewPage"; @@ -70,6 +72,14 @@ export class ProviderViewPage extends AKElement { return html``; + case "ak-provider-google-workspace-form": + return html``; + case "ak-provider-microsoft-entra-form": + return html``; default: return html`

Invalid provider type ${this.provider?.component}

`; } diff --git a/web/src/admin/providers/ProviderWizard.ts b/web/src/admin/providers/ProviderWizard.ts index 7f19b4d024..8e39b8c346 100644 --- a/web/src/admin/providers/ProviderWizard.ts +++ b/web/src/admin/providers/ProviderWizard.ts @@ -1,110 +1,32 @@ +import "@goauthentik/admin/common/ak-license-notice"; import "@goauthentik/admin/providers/ldap/LDAPProviderForm"; import "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm"; import "@goauthentik/admin/providers/proxy/ProxyProviderForm"; import "@goauthentik/admin/providers/saml/SAMLProviderForm"; import "@goauthentik/admin/providers/saml/SAMLProviderImportForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; -import "@goauthentik/elements/Alert"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; -import { paramURL } from "@goauthentik/elements/router/RouterOutlet"; import "@goauthentik/elements/wizard/FormWizardPage"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; +import { TypeCreateWizardPageLayouts } from "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import type { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; -import { CSSResult, TemplateResult, html, nothing } from "lit"; -import { property, state } from "lit/decorators.js"; +import { CSSResult, TemplateResult, html } from "lit"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFHint from "@patternfly/patternfly/components/Hint/hint.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import { EnterpriseApi, LicenseSummary, ProvidersApi, TypeCreate } from "@goauthentik/api"; - -@customElement("ak-provider-wizard-initial") -export class InitialProviderWizardPage extends WizardPage { - @property({ attribute: false }) - providerTypes: TypeCreate[] = []; - - @property({ attribute: false }) - enterprise?: LicenseSummary; - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFHint, PFButton, PFRadio]; - } - sidebarLabel = () => msg("Select type"); - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - renderHint(): TemplateResult { - return html`
-
${msg("Try the new application wizard")}
-
- ${msg( - "The new application wizard greatly simplifies the steps required to create applications and providers.", - )} -
- -
-
`; - } - - render(): TemplateResult { - return html`
- ${this.providerTypes.map((type) => { - return html`
- { - this.host.steps = ["initial", `type-${type.component}`]; - this.host.isValid = true; - }} - ?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false} - /> - - ${type.description} - ${type.requiresEnterprise && !this.enterprise?.hasLicense - ? html` - - ${msg("Provider require enterprise.")} - ${msg("Learn more")} - - ` - : nothing} -
`; - })} -
`; - } -} +import { ProvidersApi, TypeCreate } from "@goauthentik/api"; @customElement("ak-provider-wizard") export class ProviderWizard extends AKElement { static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + return [PFBase, PFButton]; } @property() @@ -113,19 +35,16 @@ export class ProviderWizard extends AKElement { @property({ attribute: false }) providerTypes: TypeCreate[] = []; - @state() - enterprise?: LicenseSummary; - @property({ attribute: false }) finalHandler: () => Promise = () => { return Promise.resolve(); }; + @query("ak-wizard") + wizard?: Wizard; + async firstUpdated(): Promise { this.providerTypes = await new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList(); - this.enterprise = await new EnterpriseApi( - DEFAULT_CONFIG, - ).enterpriseLicenseSummaryRetrieve(); } render(): TemplateResult { @@ -138,12 +57,17 @@ export class ProviderWizard extends AKElement { return this.finalHandler(); }} > - ) => { + if (!this.wizard) return; + this.wizard.steps = ["initial", `type-${ev.detail.component}`]; + this.wizard.isValid = true; + }} > - + ${this.providerTypes.map((type) => { return html` { + loadInstance(pk: number): Promise { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceRetrieve({ + id: pk, + }); + } + + async load(): Promise { + this.propertyMappings = await new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderGoogleWorkspaceList({ + ordering: "managed", + }); + } + + propertyMappings?: PaginatedGoogleWorkspaceProviderMappingList; + + async send(data: GoogleWorkspaceProvider): Promise { + if (this.instance) { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceUpdate({ + id: this.instance.pk, + googleWorkspaceProviderRequest: data, + }); + } else { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceCreate({ + googleWorkspaceProviderRequest: data, + }); + } + } + + renderForm(): TemplateResult { + return html` + + + + ${msg("Protocol settings")} +
+ + +

+ ${msg("Google Cloud credentials file.")} +

+
+ + +

+ ${msg( + "Email address of the user the actions of authentik will be delegated to.", + )} +

+
+ + +

+ ${msg( + "Default domain that is used to generate a group's email address. Can be customized using property mappings.", + )} +

+
+ + + + +
+
+ + ${msg("User filtering")} +
+ + + + + => { + const args: CoreGroupsListRequest = { + ordering: "name", + includeUsers: false, + }; + if (query !== undefined) { + args.search = query; + } + const groups = await new CoreApi(DEFAULT_CONFIG).coreGroupsList( + args, + ); + return groups.results; + }} + .renderElement=${(group: Group): string => { + return group.name; + }} + .value=${(group: Group | undefined): string | undefined => { + return group ? group.pk : undefined; + }} + .selected=${(group: Group): boolean => { + return group.pk === this.instance?.filterGroup; + }} + ?blankable=${true} + > + +

+ ${msg("Only sync users within the selected group.")} +

+
+
+
+ + ${msg("Attribute mapping")} +
+ + +

+ ${msg("Property mappings used to user mapping.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

+
+ + +

+ ${msg("Property mappings used to group creation.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

+
+
+
`; + } +} diff --git a/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderGroupList.ts b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderGroupList.ts new file mode 100644 index 0000000000..474922c8bd --- /dev/null +++ b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderGroupList.ts @@ -0,0 +1,42 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { GoogleWorkspaceProviderGroup, ProvidersApi } from "@goauthentik/api"; + +@customElement("ak-provider-google-workspace-groups-list") +export class GoogleWorkspaceProviderGroupList extends Table { + @property({ type: Number }) + providerId?: number; + + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceGroupsList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + providerId: this.providerId, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Name")), new TableColumn(msg("ID"))]; + } + + row(item: GoogleWorkspaceProviderGroup): TemplateResult[] { + return [ + html` +
${item.groupObj.name}
+
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderUserList.ts b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderUserList.ts new file mode 100644 index 0000000000..d8bf35b249 --- /dev/null +++ b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderUserList.ts @@ -0,0 +1,43 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { GoogleWorkspaceProviderUser, ProvidersApi } from "@goauthentik/api"; + +@customElement("ak-provider-google-workspace-users-list") +export class GoogleWorkspaceProviderUserList extends Table { + @property({ type: Number }) + providerId?: number; + + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceUsersList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + providerId: this.providerId, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Username")), new TableColumn(msg("ID"))]; + } + + row(item: GoogleWorkspaceProviderUser): TemplateResult[] { + return [ + html` +
${item.userObj.username}
+ ${item.userObj.name} +
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderViewPage.ts b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderViewPage.ts new file mode 100644 index 0000000000..4ca5b16a90 --- /dev/null +++ b/web/src/admin/providers/google_workspace/GoogleWorkspaceProviderViewPage.ts @@ -0,0 +1,223 @@ +import "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderForm"; +import "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderGroupList"; +import "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderUserList"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import "@goauthentik/components/events/ObjectChangelog"; +import { AKElement } from "@goauthentik/elements/Base"; +import "@goauthentik/elements/Markdown"; +import "@goauthentik/elements/SyncStatusCard"; +import "@goauthentik/elements/Tabs"; +import "@goauthentik/elements/buttons/ActionButton"; +import "@goauthentik/elements/buttons/ModalButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; + +import { msg } from "@lit/localize"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; + +import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFList from "@patternfly/patternfly/components/List/list.css"; +import PFPage from "@patternfly/patternfly/components/Page/page.css"; +import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; +import PFStack from "@patternfly/patternfly/layouts/Stack/stack.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { + GoogleWorkspaceProvider, + ProvidersApi, + RbacPermissionsAssignedByUsersListModelEnum, + SyncStatus, +} from "@goauthentik/api"; + +@customElement("ak-provider-google-workspace-view") +export class GoogleWorkspaceProviderViewPage extends AKElement { + @property({ type: Number }) + providerID?: number; + + @state() + provider?: GoogleWorkspaceProvider; + + @state() + syncState?: SyncStatus; + + static get styles(): CSSResult[] { + return [ + PFBase, + PFButton, + PFBanner, + PFForm, + PFFormControl, + PFStack, + PFList, + PFGrid, + PFPage, + PFContent, + PFCard, + PFDescriptionList, + ]; + } + + constructor() { + super(); + this.addEventListener(EVENT_REFRESH, () => { + if (!this.provider?.pk) return; + this.providerID = this.provider?.pk; + }); + } + + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG) + .providersGoogleWorkspaceRetrieve({ id }) + .then((prov) => (this.provider = prov)); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + + render(): TemplateResult { + if (!this.provider) { + return html``; + } + return html` +
{ + new ProvidersApi(DEFAULT_CONFIG) + .providersGoogleWorkspaceSyncStatusRetrieve({ + id: this.provider?.pk || 0, + }) + .then((state) => { + this.syncState = state; + }) + .catch(() => { + this.syncState = undefined; + }); + }} + > + ${this.renderTabOverview()} +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+ +
+
+ +
`; + } + + renderTabOverview(): TemplateResult { + if (!this.provider) { + return html``; + } + return html`
+ ${msg("Google Workspace Provider is in preview.")} + ${msg("Send us feedback!")} +
+ ${!this.provider?.assignedBackchannelApplicationName + ? html`
+ ${msg( + "Warning: Provider is not assigned to an application as backchannel provider.", + )} +
` + : html``} +
+
+
+
+
+
+ ${msg("Name")} +
+
+
+ ${this.provider.name} +
+
+
+
+
+ +
+
+ { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersGoogleWorkspaceSyncStatusRetrieve({ + id: this.provider?.pk || 0, + }); + }} + .triggerSync=${() => { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersGoogleWorkspacePartialUpdate({ + id: this.provider?.pk || 0, + patchedGoogleWorkspaceProviderRequest: {}, + }); + }} + > +
+
`; + } +} diff --git a/web/src/admin/providers/ldap/LDAPProviderForm.ts b/web/src/admin/providers/ldap/LDAPProviderForm.ts index db426cc1a4..5af4329243 100644 --- a/web/src/admin/providers/ldap/LDAPProviderForm.ts +++ b/web/src/admin/providers/ldap/LDAPProviderForm.ts @@ -35,7 +35,7 @@ export class LDAPProviderFormPage extends WithBrandConfig(BaseProviderForm { if (this.instance) { return new ProvidersApi(DEFAULT_CONFIG).providersLdapUpdate({ - id: this.instance.pk || 0, + id: this.instance.pk, lDAPProviderRequest: data, }); } else { @@ -78,6 +78,7 @@ export class LDAPProviderFormPage extends WithBrandConfig(BaseProviderForm => { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/providers/ldap/LDAPProviderViewPage.ts b/web/src/admin/providers/ldap/LDAPProviderViewPage.ts index 08eb030211..39c77166e3 100644 --- a/web/src/admin/providers/ldap/LDAPProviderViewPage.ts +++ b/web/src/admin/providers/ldap/LDAPProviderViewPage.ts @@ -1,6 +1,5 @@ import "@goauthentik/admin/providers/RelatedApplicationButton"; import "@goauthentik/admin/providers/ldap/LDAPProviderForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { me } from "@goauthentik/common/users"; @@ -10,9 +9,10 @@ import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -37,21 +37,10 @@ import { @customElement("ak-provider-ldap-view") export class LDAPProviderViewPage extends AKElement { - @property() - set args(value: { [key: string]: number }) { - this.providerID = value.id; - } - @property({ type: Number }) - set providerID(value: number) { - new ProvidersApi(DEFAULT_CONFIG) - .providersLdapRetrieve({ - id: value, - }) - .then((prov) => (this.provider = prov)); - } + providerID?: number; - @property({ attribute: false }) + @state() provider?: LDAPProvider; @state() @@ -84,6 +73,18 @@ export class LDAPProviderViewPage extends AKElement { }); } + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG) + .providersLdapRetrieve({ id }) + .then((prov) => (this.provider = prov)); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + render(): TemplateResult { if (!this.provider) { return html``; diff --git a/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderFormPage.ts b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderFormPage.ts new file mode 100644 index 0000000000..5943cdb127 --- /dev/null +++ b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderFormPage.ts @@ -0,0 +1,287 @@ +import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { first } from "@goauthentik/common/utils"; +import "@goauthentik/elements/forms/FormGroup"; +import "@goauthentik/elements/forms/HorizontalFormElement"; +import "@goauthentik/elements/forms/Radio"; +import "@goauthentik/elements/forms/SearchSelect"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; + +import { + CoreApi, + CoreGroupsListRequest, + Group, + MicrosoftEntraProvider, + OutgoingSyncDeleteAction, + PaginatedMicrosoftEntraProviderMappingList, + PropertymappingsApi, + ProvidersApi, +} from "@goauthentik/api"; + +@customElement("ak-provider-microsoft-entra-form") +export class MicrosoftEntraProviderFormPage extends BaseProviderForm { + loadInstance(pk: number): Promise { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraRetrieve({ + id: pk, + }); + } + + async load(): Promise { + this.propertyMappings = await new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderMicrosoftEntraList({ + ordering: "managed", + }); + } + + propertyMappings?: PaginatedMicrosoftEntraProviderMappingList; + + async send(data: MicrosoftEntraProvider): Promise { + if (this.instance) { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraUpdate({ + id: this.instance.pk, + microsoftEntraProviderRequest: data, + }); + } else { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraCreate({ + microsoftEntraProviderRequest: data, + }); + } + } + + renderForm(): TemplateResult { + return html` + + + + ${msg("Protocol settings")} +
+ + +

+ ${msg("Client ID for the app registration.")} +

+
+ + +

+ ${msg("Client secret for the app registration.")} +

+
+ + +

+ ${msg("ID of the tenant accounts will be synced into.")} +

+
+ + + + +
+
+ + ${msg("User filtering")} +
+ + + + + => { + const args: CoreGroupsListRequest = { + ordering: "name", + includeUsers: false, + }; + if (query !== undefined) { + args.search = query; + } + const groups = await new CoreApi(DEFAULT_CONFIG).coreGroupsList( + args, + ); + return groups.results; + }} + .renderElement=${(group: Group): string => { + return group.name; + }} + .value=${(group: Group | undefined): string | undefined => { + return group ? group.pk : undefined; + }} + .selected=${(group: Group): boolean => { + return group.pk === this.instance?.filterGroup; + }} + ?blankable=${true} + > + +

+ ${msg("Only sync users within the selected group.")} +

+
+
+
+ + ${msg("Attribute mapping")} +
+ + +

+ ${msg("Property mappings used to user mapping.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

+
+ + +

+ ${msg("Property mappings used to group creation.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

+
+
+
`; + } +} diff --git a/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderGroupList.ts b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderGroupList.ts new file mode 100644 index 0000000000..6760ead66e --- /dev/null +++ b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderGroupList.ts @@ -0,0 +1,42 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { MicrosoftEntraProviderGroup, ProvidersApi } from "@goauthentik/api"; + +@customElement("ak-provider-microsoft-entra-groups-list") +export class MicrosoftEntraProviderGroupList extends Table { + @property({ type: Number }) + providerId?: number; + + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraGroupsList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + providerId: this.providerId, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Name")), new TableColumn(msg("ID"))]; + } + + row(item: MicrosoftEntraProviderGroup): TemplateResult[] { + return [ + html` +
${item.groupObj.name}
+
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderUserList.ts b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderUserList.ts new file mode 100644 index 0000000000..aadb8abc9c --- /dev/null +++ b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderUserList.ts @@ -0,0 +1,43 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { MicrosoftEntraProviderUser, ProvidersApi } from "@goauthentik/api"; + +@customElement("ak-provider-microsoft-entra-users-list") +export class MicrosoftEntraProviderUserList extends Table { + @property({ type: Number }) + providerId?: number; + + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraUsersList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + providerId: this.providerId, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Username")), new TableColumn(msg("ID"))]; + } + + row(item: MicrosoftEntraProviderUser): TemplateResult[] { + return [ + html` +
${item.userObj.username}
+ ${item.userObj.name} +
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderViewPage.ts b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderViewPage.ts new file mode 100644 index 0000000000..c92c944639 --- /dev/null +++ b/web/src/admin/providers/microsoft_entra/MicrosoftEntraProviderViewPage.ts @@ -0,0 +1,224 @@ +import "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderFormPage"; +import "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderGroupList"; +import "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderUserList"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import "@goauthentik/components/events/ObjectChangelog"; +import { AKElement } from "@goauthentik/elements/Base"; +import "@goauthentik/elements/Markdown"; +import "@goauthentik/elements/Tabs"; +import "@goauthentik/elements/buttons/ActionButton"; +import "@goauthentik/elements/buttons/ModalButton"; +import "@goauthentik/elements/events/LogViewer"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; + +import { msg } from "@lit/localize"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; + +import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFList from "@patternfly/patternfly/components/List/list.css"; +import PFPage from "@patternfly/patternfly/components/Page/page.css"; +import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; +import PFStack from "@patternfly/patternfly/layouts/Stack/stack.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { + MicrosoftEntraProvider, + ProvidersApi, + RbacPermissionsAssignedByUsersListModelEnum, + SyncStatus, +} from "@goauthentik/api"; + +@customElement("ak-provider-microsoft-entra-view") +export class MicrosoftEntraProviderViewPage extends AKElement { + @property({ type: Number }) + providerID?: number; + + @state() + provider?: MicrosoftEntraProvider; + + @state() + syncState?: SyncStatus; + + static get styles(): CSSResult[] { + return [ + PFBase, + PFButton, + PFBanner, + PFForm, + PFFormControl, + PFStack, + PFList, + PFGrid, + PFPage, + PFContent, + PFCard, + PFDescriptionList, + ]; + } + + constructor() { + super(); + this.addEventListener(EVENT_REFRESH, () => { + if (!this.provider?.pk) return; + this.providerID = this.provider?.pk; + }); + } + + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG) + .providersMicrosoftEntraRetrieve({ id }) + .then((prov) => (this.provider = prov)); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + + render(): TemplateResult { + if (!this.provider) { + return html``; + } + return html` +
{ + new ProvidersApi(DEFAULT_CONFIG) + .providersMicrosoftEntraSyncStatusRetrieve({ + id: this.provider?.pk || 0, + }) + .then((state) => { + this.syncState = state; + }) + .catch(() => { + this.syncState = undefined; + }); + }} + > + ${this.renderTabOverview()} +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+ +
+
+ +
`; + } + + renderTabOverview(): TemplateResult { + if (!this.provider) { + return html``; + } + return html`
+ ${msg("Microsoft Entra Provider is in preview.")} + ${msg("Send us feedback!")} +
+ ${!this.provider?.assignedBackchannelApplicationName + ? html`
+ ${msg( + "Warning: Provider is not assigned to an application as backchannel provider.", + )} +
` + : html``} +
+
+
+
+
+
+ ${msg("Name")} +
+
+
+ ${this.provider.name} +
+
+
+
+
+ +
+ +
+ { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersMicrosoftEntraSyncStatusRetrieve({ + id: this.provider?.pk || 0, + }); + }} + .triggerSync=${() => { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersMicrosoftEntraPartialUpdate({ + id: this.provider?.pk || 0, + patchedMicrosoftEntraProviderRequest: {}, + }); + }} + > +
+
`; + } +} diff --git a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts index 74f3acbeb8..81f0605cbc 100644 --- a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts +++ b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts @@ -146,7 +146,7 @@ export class OAuth2ProviderFormPage extends BaseProviderForm { async send(data: OAuth2Provider): Promise { if (this.instance) { return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Update({ - id: this.instance.pk || 0, + id: this.instance.pk, oAuth2ProviderRequest: data, }); } else { diff --git a/web/src/admin/providers/oauth2/OAuth2ProviderViewPage.ts b/web/src/admin/providers/oauth2/OAuth2ProviderViewPage.ts index afe5dfd582..6c3bcc4cc8 100644 --- a/web/src/admin/providers/oauth2/OAuth2ProviderViewPage.ts +++ b/web/src/admin/providers/oauth2/OAuth2ProviderViewPage.ts @@ -2,7 +2,7 @@ import "@goauthentik/admin/providers/RelatedApplicationButton"; import "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; -import { convertToTitle } from "@goauthentik/common/utils"; +import renderDescriptionList from "@goauthentik/components/DescriptionList"; import "@goauthentik/components/events/ObjectChangelog"; import MDProviderOAuth2 from "@goauthentik/docs/providers/oauth2/index.md"; import { AKElement } from "@goauthentik/elements/Base"; @@ -22,6 +22,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFCard from "@patternfly/patternfly/components/Card/card.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; +import PFDivider from "@patternfly/patternfly/components/Divider/divider.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css"; @@ -29,13 +30,29 @@ import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { + ClientTypeEnum, + CoreApi, + CoreUsersListRequest, OAuth2Provider, OAuth2ProviderSetupURLs, PropertyMappingPreview, ProvidersApi, RbacPermissionsAssignedByUsersListModelEnum, + User, } from "@goauthentik/api"; +export function TypeToLabel(type?: ClientTypeEnum): string { + if (!type) return ""; + switch (type) { + case ClientTypeEnum.Confidential: + return msg("Confidential"); + case ClientTypeEnum.Public: + return msg("Public"); + case ClientTypeEnum.UnknownDefaultOpenApi: + return msg("Unknown type"); + } +} + @customElement("ak-provider-oauth2-view") export class OAuth2ProviderViewPage extends AKElement { @property({ type: Number }) @@ -58,6 +75,9 @@ export class OAuth2ProviderViewPage extends AKElement { @state() preview?: PropertyMappingPreview; + @state() + previewUser?: User; + static get styles(): CSSResult[] { return [ PFBase, @@ -70,6 +90,7 @@ export class OAuth2ProviderViewPage extends AKElement { PFForm, PFFormControl, PFBanner, + PFDivider, ]; } @@ -81,6 +102,15 @@ export class OAuth2ProviderViewPage extends AKElement { }); } + fetchPreview(): void { + new ProvidersApi(DEFAULT_CONFIG) + .providersOauth2PreviewUserRetrieve({ + id: this.provider?.pk || 0, + forUser: this.previewUser?.pk, + }) + .then((preview) => (this.preview = preview)); + } + render(): TemplateResult { if (!this.provider) { return html``; @@ -105,11 +135,7 @@ export class OAuth2ProviderViewPage extends AKElement { slot="page-preview" data-tab-title="${msg("Preview")}" @activate=${() => { - new ProvidersApi(DEFAULT_CONFIG) - .providersOauth2PreviewUserRetrieve({ - id: this.provider?.pk || 0, - }) - .then((preview) => (this.preview = preview)); + this.fetchPreview(); }} > ${this.renderTabPreview()} @@ -149,7 +175,7 @@ export class OAuth2ProviderViewPage extends AKElement {
`}
@@ -184,7 +210,7 @@ export class OAuth2ProviderViewPage extends AKElement {
- ${convertToTitle(this.provider.clientType || "")} + ${TypeToLabel(this.provider.clientType)}
@@ -229,7 +255,7 @@ export class OAuth2ProviderViewPage extends AKElement {
-
+
@@ -258,7 +284,7 @@ export class OAuth2ProviderViewPage extends AKElement { value="${this.providerUrls?.issuer || msg("-")}" />
-
+
@@ -352,8 +380,50 @@ export class OAuth2ProviderViewPage extends AKElement { class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter" >
-
- ${msg("Example JWT payload (for currently authenticated user)")} +
${msg("JWT payload")}
+
+ ${renderDescriptionList( + [ + [ + msg("Preview for user"), + html` + => { + const args: CoreUsersListRequest = { + ordering: "username", + }; + if (query !== undefined) { + args.search = query; + } + const users = await new CoreApi( + DEFAULT_CONFIG, + ).coreUsersList(args); + return users.results; + }} + .renderElement=${(user: User): string => { + return user.username; + }} + .renderDescription=${(user: User): TemplateResult => { + return html`${user.name}`; + }} + .value=${(user: User | undefined): number | undefined => { + return user?.pk; + }} + .selected=${(user: User): boolean => { + return user.pk === this.previewUser?.pk; + }} + ?blankable=${true} + @ak-change=${(ev: CustomEvent) => { + this.previewUser = ev.detail.value; + this.fetchPreview(); + }} + > + + `, + ], + ], + { horizontal: true }, + )}
${this.preview diff --git a/web/src/admin/providers/proxy/ProxyProviderForm.ts b/web/src/admin/providers/proxy/ProxyProviderForm.ts index ddd5545725..d05c433912 100644 --- a/web/src/admin/providers/proxy/ProxyProviderForm.ts +++ b/web/src/admin/providers/proxy/ProxyProviderForm.ts @@ -72,7 +72,7 @@ export class ProxyProviderFormPage extends BaseProviderForm { } if (this.instance) { return new ProvidersApi(DEFAULT_CONFIG).providersProxyUpdate({ - id: this.instance.pk || 0, + id: this.instance.pk, proxyProviderRequest: data, }); } else { diff --git a/web/src/admin/providers/proxy/ProxyProviderViewPage.ts b/web/src/admin/providers/proxy/ProxyProviderViewPage.ts index bdce041940..e4488af237 100644 --- a/web/src/admin/providers/proxy/ProxyProviderViewPage.ts +++ b/web/src/admin/providers/proxy/ProxyProviderViewPage.ts @@ -1,6 +1,5 @@ import "@goauthentik/admin/providers/RelatedApplicationButton"; import "@goauthentik/admin/providers/proxy/ProxyProviderForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { convertToSlug } from "@goauthentik/common/utils"; @@ -22,11 +21,12 @@ import { Replacer } from "@goauthentik/elements/Markdown"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; @@ -75,21 +75,10 @@ export function isForward(mode: ProxyMode): boolean { @customElement("ak-provider-proxy-view") export class ProxyProviderViewPage extends AKElement { - @property() - set args(value: { [key: string]: number }) { - this.providerID = value.id; - } - @property({ type: Number }) - set providerID(value: number) { - new ProvidersApi(DEFAULT_CONFIG) - .providersProxyRetrieve({ - id: value, - }) - .then((prov) => (this.provider = prov)); - } + providerID?: number; - @property({ attribute: false }) + @state() provider?: ProxyProvider; static get styles(): CSSResult[] { @@ -116,35 +105,54 @@ export class ProxyProviderViewPage extends AKElement { }); } + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG) + .providersProxyRetrieve({ id }) + .then((prov) => (this.provider = prov)); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + renderConfig(): TemplateResult { const serves = [ { label: msg("Nginx (Ingress)"), md: MDNginxIngress, + meta: "providers/proxy/_nginx_ingress.md", }, { label: msg("Nginx (Proxy Manager)"), md: MDNginxPM, + meta: "providers/proxy/_nginx_proxy_manager.md", }, { label: msg("Nginx (standalone)"), md: MDNginxStandalone, + meta: "providers/proxy/_nginx_standalone.md", }, { label: msg("Traefik (Ingress)"), md: MDTraefikIngress, + meta: "providers/proxy/_traefik_ingress.md", }, { label: msg("Traefik (Compose)"), md: MDTraefikCompose, + meta: "providers/proxy/_traefik_compose.md", }, { label: msg("Traefik (Standalone)"), md: MDTraefikStandalone, + meta: "providers/proxy/_traefik_standalone.md", }, { label: msg("Caddy (Standalone)"), md: MDCaddyStandalone, + meta: "providers/proxy/_caddy_standalone.md", }, ]; const replacers: Replacer[] = [ @@ -182,7 +190,11 @@ export class ProxyProviderViewPage extends AKElement { data-tab-title="${server.label}" class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" > - + `; })}`; @@ -248,7 +260,10 @@ export class ProxyProviderViewPage extends AKElement {
- +
`; diff --git a/web/src/admin/providers/rac/ConnectionTokenList.ts b/web/src/admin/providers/rac/ConnectionTokenList.ts new file mode 100644 index 0000000000..d9d4fbf830 --- /dev/null +++ b/web/src/admin/providers/rac/ConnectionTokenList.ts @@ -0,0 +1,98 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/forms/DeleteBulkForm"; +import "@goauthentik/elements/forms/ModalForm"; +import { PaginatedResponse, Table } from "@goauthentik/elements/table/Table"; +import { TableColumn } from "@goauthentik/elements/table/Table"; +import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; + +import { ConnectionToken, RACProvider, RacApi } from "@goauthentik/api"; + +@customElement("ak-rac-connection-token-list") +export class ConnectionTokenListPage extends Table { + checkbox = true; + clearOnRefresh = true; + + searchEnabled(): boolean { + return true; + } + + @property() + order = "name"; + + @property({ attribute: false }) + provider?: RACProvider; + + @property({ type: Number }) + userId?: number; + + static get styles(): CSSResult[] { + return super.styles.concat(PFDescriptionList); + } + + async apiEndpoint(page: number): Promise> { + return new RacApi(DEFAULT_CONFIG).racConnectionTokensList({ + ordering: this.order, + page: page, + pageSize: (await uiConfig()).pagination.perPage, + search: this.search || "", + provider: this.provider?.pk, + sessionUser: this.userId, + }); + } + + renderToolbarSelected(): TemplateResult { + const disabled = this.selectedElements.length < 1; + return html` { + return [ + { key: msg("Endpoint"), value: item.endpointObj.name }, + { key: msg("User"), value: item.user.username }, + ]; + }} + .usedBy=${(item: ConnectionToken) => { + return new RacApi(DEFAULT_CONFIG).racConnectionTokensUsedByList({ + connectionTokenUuid: item.pk || "", + }); + }} + .delete=${(item: ConnectionToken) => { + return new RacApi(DEFAULT_CONFIG).racConnectionTokensDestroy({ + connectionTokenUuid: item.pk || "", + }); + }} + > + + `; + } + + columns(): TableColumn[] { + if (this.provider) { + return [ + new TableColumn(msg("Endpoint"), "endpoint__name"), + new TableColumn(msg("User"), "session__user"), + ]; + } + return [ + new TableColumn(msg("Provider"), "provider__name"), + new TableColumn(msg("Endpoint"), "endpoint__name"), + ]; + } + + row(item: ConnectionToken): TemplateResult[] { + if (this.provider) { + return [html`${item.endpointObj.name}`, html`${item.user.username}`]; + } + return [html`${item.providerObj.name}`, html`${item.endpointObj.name}`]; + } +} diff --git a/web/src/admin/providers/rac/EndpointForm.ts b/web/src/admin/providers/rac/EndpointForm.ts index 0f23f4fca8..c14feee462 100644 --- a/web/src/admin/providers/rac/EndpointForm.ts +++ b/web/src/admin/providers/rac/EndpointForm.ts @@ -1,5 +1,5 @@ -import { first } from "@goauthentik/app/common/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { first } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-radio-input"; import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/forms/FormGroup"; @@ -123,11 +123,7 @@ export class EndpointForm extends ModelForm { )}

- + + + + + + + ${msg("Delete authorization on disconnect")} + +

+ ${msg( + "When enabled, connection authorizations will be deleted when a client disconnects. This will force clients with flaky internet connections to re-authorize the endpoint.", + )} +

+
${msg("Protocol settings")}
diff --git a/web/src/admin/providers/saml/SAMLProviderViewPage.ts b/web/src/admin/providers/saml/SAMLProviderViewPage.ts index de5e3505b1..df9f16ef96 100644 --- a/web/src/admin/providers/saml/SAMLProviderViewPage.ts +++ b/web/src/admin/providers/saml/SAMLProviderViewPage.ts @@ -1,9 +1,9 @@ import "@goauthentik/admin/providers/RelatedApplicationButton"; import "@goauthentik/admin/providers/saml/SAMLProviderForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { MessageLevel } from "@goauthentik/common/messages"; +import renderDescriptionList from "@goauthentik/components/DescriptionList"; import "@goauthentik/components/events/ObjectChangelog"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/CodeMirror"; @@ -14,9 +14,10 @@ import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/SpinnerButton"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -34,11 +35,14 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { CertificateKeyPair, + CoreApi, + CoreUsersListRequest, CryptoApi, ProvidersApi, RbacPermissionsAssignedByUsersListModelEnum, SAMLMetadata, SAMLProvider, + User, } from "@goauthentik/api"; interface SAMLPreviewAttribute { @@ -51,37 +55,10 @@ interface SAMLPreviewAttribute { @customElement("ak-provider-saml-view") export class SAMLProviderViewPage extends AKElement { - @property() - set args(value: { [key: string]: number }) { - this.providerID = value.id; - } - @property({ type: Number }) - set providerID(value: number) { - new ProvidersApi(DEFAULT_CONFIG) - .providersSamlRetrieve({ - id: value, - }) - .then((prov) => { - this.provider = prov; - if (prov.signingKp) { - new CryptoApi(DEFAULT_CONFIG) - .cryptoCertificatekeypairsRetrieve({ - kpUuid: prov.signingKp, - }) - .then((kp) => (this.signer = kp)); - } - if (prov.verificationKp) { - new CryptoApi(DEFAULT_CONFIG) - .cryptoCertificatekeypairsRetrieve({ - kpUuid: prov.verificationKp, - }) - .then((kp) => (this.verifier = kp)); - } - }); - } + providerID?: number; - @property({ attribute: false }) + @state() provider?: SAMLProvider; @state() @@ -96,6 +73,9 @@ export class SAMLProviderViewPage extends AKElement { @state() verifier?: CertificateKeyPair; + @state() + previewUser?: User; + static get styles(): CSSResult[] { return [ PFBase, @@ -120,6 +100,47 @@ export class SAMLProviderViewPage extends AKElement { }); } + fetchPreview(): void { + new ProvidersApi(DEFAULT_CONFIG) + .providersSamlPreviewUserRetrieve({ + id: this.provider?.pk || 0, + forUser: this.previewUser?.pk, + }) + .then((preview) => { + this.preview = preview.preview as SAMLPreviewAttribute; + }); + } + + fetchCertificate(kpUuid: string) { + return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsRetrieve({ kpUuid }); + } + + fetchSigningCertificate(kpUuid: string) { + this.fetchCertificate(kpUuid).then((kp) => (this.signer = kp)); + } + + fetchVerificationCertificate(kpUuid: string) { + this.fetchCertificate(kpUuid).then((kp) => (this.verifier = kp)); + } + + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG).providersSamlRetrieve({ id }).then((prov) => { + this.provider = prov; + if (this.provider.signingKp) { + this.fetchSigningCertificate(this.provider.signingKp); + } + if (this.provider.verificationKp) { + this.fetchVerificationCertificate(this.provider.verificationKp); + } + }); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + renderRelatedObjects(): TemplateResult { const relatedObjects = []; if (this.provider?.assignedApplicationName) { @@ -203,13 +224,7 @@ export class SAMLProviderViewPage extends AKElement { slot="page-preview" data-tab-title="${msg("Preview")}" @activate=${() => { - new ProvidersApi(DEFAULT_CONFIG) - .providersSamlPreviewUserRetrieve({ - id: this.provider?.pk || 0, - }) - .then((preview) => { - this.preview = preview.preview as SAMLPreviewAttribute; - }); + this.fetchPreview(); }} > ${this.renderTabPreview()} @@ -494,6 +509,47 @@ export class SAMLProviderViewPage extends AKElement { >
${msg("Example SAML attributes")}
+
+ ${renderDescriptionList([ + [ + "Preview for user", + html` + => { + const args: CoreUsersListRequest = { + ordering: "username", + }; + if (query !== undefined) { + args.search = query; + } + const users = await new CoreApi( + DEFAULT_CONFIG, + ).coreUsersList(args); + return users.results; + }} + .renderElement=${(user: User): string => { + return user.username; + }} + .renderDescription=${(user: User): TemplateResult => { + return html`${user.name}`; + }} + .value=${(user: User | undefined): number | undefined => { + return user?.pk; + }} + .selected=${(user: User): boolean => { + return user.pk === this.previewUser?.pk; + }} + ?blankable=${true} + @ak-change=${(ev: CustomEvent) => { + this.previewUser = ev.detail.value; + this.fetchPreview(); + }} + > + + `, + ], + ])} +
diff --git a/web/src/admin/providers/scim/SCIMProviderForm.ts b/web/src/admin/providers/scim/SCIMProviderForm.ts index e505c4b23a..afcba41b35 100644 --- a/web/src/admin/providers/scim/SCIMProviderForm.ts +++ b/web/src/admin/providers/scim/SCIMProviderForm.ts @@ -42,7 +42,7 @@ export class SCIMProviderFormPage extends BaseProviderForm { async send(data: SCIMProvider): Promise { if (this.instance) { return new ProvidersApi(DEFAULT_CONFIG).providersScimUpdate({ - id: this.instance.pk || 0, + id: this.instance.pk, sCIMProviderRequest: data, }); } else { @@ -119,6 +119,7 @@ export class SCIMProviderFormPage extends BaseProviderForm { .fetchObjects=${async (query?: string): Promise => { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; @@ -151,7 +152,6 @@ export class SCIMProviderFormPage extends BaseProviderForm {
diff --git a/web/src/admin/providers/scim/SCIMProviderViewPage.ts b/web/src/admin/providers/scim/SCIMProviderViewPage.ts index a9faa772f0..5e852946b2 100644 --- a/web/src/admin/providers/scim/SCIMProviderViewPage.ts +++ b/web/src/admin/providers/scim/SCIMProviderViewPage.ts @@ -1,17 +1,18 @@ import "@goauthentik/admin/providers/scim/SCIMProviderForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/events/ObjectChangelog"; import MDSCIMProvider from "@goauthentik/docs/providers/scim/index.md"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Markdown"; +import "@goauthentik/elements/SyncStatusCard"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/ModalButton"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; -import { msg, str } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { msg } from "@lit/localize"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; @@ -31,31 +32,15 @@ import { ProvidersApi, RbacPermissionsAssignedByUsersListModelEnum, SCIMProvider, - SCIMSyncStatus, - SystemTaskStatusEnum, } from "@goauthentik/api"; @customElement("ak-provider-scim-view") export class SCIMProviderViewPage extends AKElement { - @property() - set args(value: { [key: string]: number }) { - this.providerID = value.id; - } - @property({ type: Number }) - set providerID(value: number) { - new ProvidersApi(DEFAULT_CONFIG) - .providersScimRetrieve({ - id: value, - }) - .then((prov) => (this.provider = prov)); - } - - @property({ attribute: false }) - provider?: SCIMProvider; + providerID?: number; @state() - syncState?: SCIMSyncStatus; + provider?: SCIMProvider; static get styles(): CSSResult[] { return [ @@ -82,27 +67,24 @@ export class SCIMProviderViewPage extends AKElement { }); } + fetchProvider(id: number) { + new ProvidersApi(DEFAULT_CONFIG) + .providersScimRetrieve({ id }) + .then((prov) => (this.provider = prov)); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("providerID") && this.providerID) { + this.fetchProvider(this.providerID); + } + } + render(): TemplateResult { if (!this.provider) { return html``; } return html` -
{ - new ProvidersApi(DEFAULT_CONFIG) - .providersScimSyncStatusRetrieve({ - id: this.provider?.pk || 0, - }) - .then((state) => { - this.syncState = state; - }) - .catch(() => { - this.syncState = undefined; - }); - }} - > +
${this.renderTabOverview()}
`; } - renderSyncStatus(): TemplateResult { - if (!this.syncState) { - return html`${msg("No sync status.")}`; - } - if (this.syncState.isRunning) { - return html`${msg("Sync currently running.")}`; - } - if (this.syncState.tasks.length < 1) { - return html`${msg("Not synced yet.")}`; - } - return html` -
    - ${this.syncState.tasks.map((task) => { - let header = ""; - if (task.status === SystemTaskStatusEnum.Warning) { - header = msg("Task finished with warnings"); - } else if (task.status === SystemTaskStatusEnum.Error) { - header = msg("Task finished with errors"); - } else { - header = msg(str`Last sync: ${task.finishTimestamp.toLocaleString()}`); - } - return html`
  • -

    ${task.name}

    -
      -
    • ${header}
    • - ${task.messages.map((m) => { - return html`
    • ${m}
    • `; - })} -
    -
  • `; - })} -
- `; - } - renderTabOverview(): TemplateResult { if (!this.provider) { return html``; @@ -218,38 +165,30 @@ export class SCIMProviderViewPage extends AKElement {
-
-
-

${msg("Sync status")}

-
-
${this.renderSyncStatus()}
- +
+ { + return new ProvidersApi( + DEFAULT_CONFIG, + ).providersScimSyncStatusRetrieve({ + id: this.provider?.pk || 0, + }); + }} + .triggerSync=${() => { + return new ProvidersApi(DEFAULT_CONFIG).providersScimPartialUpdate({ + id: this.provider?.pk || 0, + patchedSCIMProviderRequest: {}, + }); + }} + >
- +
`; diff --git a/web/src/admin/roles/RolePermissionGlobalTable.ts b/web/src/admin/roles/RoleAssignedGlobalPermissionsTable.ts similarity index 85% rename from web/src/admin/roles/RolePermissionGlobalTable.ts rename to web/src/admin/roles/RoleAssignedGlobalPermissionsTable.ts index 9a302c19c0..3663f8272e 100644 --- a/web/src/admin/roles/RolePermissionGlobalTable.ts +++ b/web/src/admin/roles/RoleAssignedGlobalPermissionsTable.ts @@ -1,8 +1,8 @@ import "@goauthentik/admin/roles/RolePermissionForm"; -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { groupBy } from "@goauthentik/app/common/utils"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/ModalForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -11,8 +11,8 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { Permission, RbacApi } from "@goauthentik/api"; -@customElement("ak-role-permissions-global-table") -export class RolePermissionGlobalTable extends Table { +@customElement("ak-role-assigned-global-permissions-table") +export class RoleAssignedGlobalPermissionsTable extends Table { @property() roleUuid?: string; @@ -21,6 +21,7 @@ export class RolePermissionGlobalTable extends Table { } checkbox = true; + clearOnRefresh = true; order = "content_type__app_label,content_type__model"; @@ -84,6 +85,10 @@ export class RolePermissionGlobalTable extends Table { } row(item: Permission): TemplateResult[] { - return [html`${item.modelVerbose}`, html`${item.name}`, html`✓`]; + return [ + html`${item.modelVerbose}`, + html`${item.name}`, + html``, + ]; } } diff --git a/web/src/admin/roles/RolePermissionObjectTable.ts b/web/src/admin/roles/RoleAssignedObjectPermissionTable.ts similarity index 89% rename from web/src/admin/roles/RolePermissionObjectTable.ts rename to web/src/admin/roles/RoleAssignedObjectPermissionTable.ts index 44bdf11830..de0d459cd1 100644 --- a/web/src/admin/roles/RolePermissionObjectTable.ts +++ b/web/src/admin/roles/RoleAssignedObjectPermissionTable.ts @@ -1,7 +1,7 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { groupBy } from "@goauthentik/app/common/utils"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/DeleteBulkForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; @@ -10,8 +10,8 @@ import { customElement, property } from "lit/decorators.js"; import { ExtraRoleObjectPermission, ModelEnum, RbacApi } from "@goauthentik/api"; -@customElement("ak-role-permissions-object-table") -export class RolePermissionObjectTable extends Table { +@customElement("ak-role-assigned-object-permissions-table") +export class RoleAssignedObjectPermissionTable extends Table { @property() roleUuid?: string; @@ -20,6 +20,7 @@ export class RolePermissionObjectTable extends Table } checkbox = true; + clearOnRefresh = true; apiEndpoint(page: number): Promise> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsRolesList({ @@ -89,7 +90,7 @@ export class RolePermissionObjectTable extends Table >
${item.objectPk}
`}`, - html`✓`, + html``, ]; } } diff --git a/web/src/admin/roles/RoleListPage.ts b/web/src/admin/roles/RoleListPage.ts index 328acb1864..26da56f632 100644 --- a/web/src/admin/roles/RoleListPage.ts +++ b/web/src/admin/roles/RoleListPage.ts @@ -21,6 +21,7 @@ import { RbacApi, Role } from "@goauthentik/api"; @customElement("ak-role-list") export class RoleListPage extends TablePage { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } diff --git a/web/src/admin/roles/RoleViewPage.ts b/web/src/admin/roles/RoleViewPage.ts index 8cc2e5d081..10622f7294 100644 --- a/web/src/admin/roles/RoleViewPage.ts +++ b/web/src/admin/roles/RoleViewPage.ts @@ -1,21 +1,20 @@ import "@goauthentik/admin/groups/RelatedGroupList"; -import "@goauthentik/app/admin/roles/RolePermissionGlobalTable"; -import "@goauthentik/app/admin/roles/RolePermissionObjectTable"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; +import "@goauthentik/admin/roles/RoleForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { renderDescriptionList } from "@goauthentik/components/DescriptionList"; import "@goauthentik/components/events/ObjectChangelog"; import "@goauthentik/components/events/UserEvents"; import { AKElement } from "@goauthentik/elements/Base"; -import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/Tabs"; +import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg, str } from "@lit/localize"; -import { CSSResult, TemplateResult, css, html } from "lit"; +import { css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; -import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFCard from "@patternfly/patternfly/components/Card/card.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; @@ -43,7 +42,7 @@ export class RoleViewPage extends AKElement { @state() _role?: Role; - static get styles(): CSSResult[] { + static get styles() { return [ PFBase, PFPage, @@ -53,7 +52,6 @@ export class RoleViewPage extends AKElement { PFContent, PFCard, PFDescriptionList, - PFBanner, css` .pf-c-description-list__description ak-action-button { margin-right: 6px; @@ -74,7 +72,7 @@ export class RoleViewPage extends AKElement { }); } - render(): TemplateResult { + render() { return html` + + ${msg("Update")} + ${msg("Update Role")} + + + +
`; + } + + renderBody() { if (!this._role) { - return html``; + return nothing; } - return html`
- ${msg("RBAC is in preview.")} - ${msg("Send us feedback!")} -
- -
-
-
-
${msg("Role Info")}
-
-
-
-
- ${msg("Name")} -
-
-
- ${this._role.name} -
-
-
-
-
-
-
-
- ${msg("Assigned global permissions")} -
-
- -
-
-
-
- ${msg("Assigned object permissions")} -
-
- -
+ + return html` +
+
+
+
${msg("Role Info")}
+
+ ${renderDescriptionList([ + [msg("Name"), this._role.name], + [msg("Edit"), this.renderUpdateControl(this._role)], + ])}
-
- -
`; +
+
${msg("Changelog")}
+
+ + +
+
+
+
+ +
`; } } diff --git a/web/src/admin/sources/SourceListPage.ts b/web/src/admin/sources/SourceListPage.ts index 5e627e7c90..6d33d0fcb0 100644 --- a/web/src/admin/sources/SourceListPage.ts +++ b/web/src/admin/sources/SourceListPage.ts @@ -39,6 +39,7 @@ export class SourceListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/sources/SourceViewPage.ts b/web/src/admin/sources/SourceViewPage.ts index d0050fdf98..ad51af0fa9 100644 --- a/web/src/admin/sources/SourceViewPage.ts +++ b/web/src/admin/sources/SourceViewPage.ts @@ -2,6 +2,7 @@ import "@goauthentik/admin/sources/ldap/LDAPSourceViewPage"; import "@goauthentik/admin/sources/oauth/OAuthSourceViewPage"; import "@goauthentik/admin/sources/plex/PlexSourceViewPage"; import "@goauthentik/admin/sources/saml/SAMLSourceViewPage"; +import "@goauthentik/admin/sources/scim/SCIMSourceViewPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; @@ -51,6 +52,10 @@ export class SourceViewPage extends AKElement { return html``; + case "ak-source-scim-form": + return html``; default: return html`

Invalid source type ${this.source.component}

`; } diff --git a/web/src/admin/sources/SourceWizard.ts b/web/src/admin/sources/SourceWizard.ts index 9719b7d59a..1901dbcb6a 100644 --- a/web/src/admin/sources/SourceWizard.ts +++ b/web/src/admin/sources/SourceWizard.ts @@ -2,82 +2,37 @@ import "@goauthentik/admin/sources/ldap/LDAPSourceForm"; import "@goauthentik/admin/sources/oauth/OAuthSourceForm"; import "@goauthentik/admin/sources/plex/PlexSourceForm"; import "@goauthentik/admin/sources/saml/SAMLSourceForm"; +import "@goauthentik/admin/sources/scim/SCIMSourceForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; +import { TypeCreateWizardPageLayouts } from "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import type { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { CSSResult, TemplateResult, html } from "lit"; -import { property } from "lit/decorators.js"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { SourcesApi, TypeCreate } from "@goauthentik/api"; -@customElement("ak-source-wizard-initial") -export class InitialSourceWizardPage extends WizardPage { - @property({ attribute: false }) - sourceTypes: TypeCreate[] = []; - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFButton, PFRadio]; - } - sidebarLabel = () => msg("Select type"); - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - render(): TemplateResult { - return html` - ${this.sourceTypes.map((type) => { - return html`
- { - this.host.steps = [ - "initial", - `type-${type.component}-${type.modelName}`, - ]; - this.host.isValid = true; - }} - /> - - ${type.description} -
`; - })} - `; - } -} - @customElement("ak-source-wizard") export class SourceWizard extends AKElement { static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + return [PFBase, PFButton]; } @property({ attribute: false }) sourceTypes: TypeCreate[] = []; + @query("ak-wizard") + wizard?: Wizard; + firstUpdated(): void { new SourcesApi(DEFAULT_CONFIG).sourcesAllTypesList().then((types) => { this.sourceTypes = types; @@ -91,8 +46,20 @@ export class SourceWizard extends AKElement { header=${msg("New source")} description=${msg("Create a new source.")} > - - + ) => { + if (!this.wizard) return; + this.wizard.steps = [ + "initial", + `type-${ev.detail.component}-${ev.detail.modelName}`, + ]; + this.wizard.isValid = true; + }} + > + ${this.sourceTypes.map((type) => { return html` { ${msg("Enabled")}
+ + +

+ ${msg( + "When the user logs in to authentik using this source password backend, update their credentials in authentik.", + )} +

+
-
-
-

${msg("Sync status")}

-
-
${this.renderSyncStatus()}
- +
+ { + return new SourcesApi(DEFAULT_CONFIG).sourcesLdapSyncStatusRetrieve( + { + slug: this.source?.slug, + }, + ); + }} + .triggerSync=${() => { + return new SourcesApi(DEFAULT_CONFIG).sourcesLdapPartialUpdate({ + slug: this.source?.slug || "", + patchedLDAPSourceRequest: {}, + }); + }} + >
diff --git a/web/src/admin/sources/oauth/OAuthSourceForm.ts b/web/src/admin/sources/oauth/OAuthSourceForm.ts index bb5124d098..b63f8b92e1 100644 --- a/web/src/admin/sources/oauth/OAuthSourceForm.ts +++ b/web/src/admin/sources/oauth/OAuthSourceForm.ts @@ -15,7 +15,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/SearchSelect"; import { msg } from "@lit/localize"; -import { TemplateResult, html } from "lit"; +import { PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -40,22 +40,8 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm { - this.providerType = type[0]; - }); - } - get modelName(): string | undefined { - return this._modelName; - } + modelName?: string; @property({ attribute: false }) providerType: SourceType | null = null; @@ -97,6 +83,22 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm { + this.providerType = type[0]; + }); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("modelName")) { + this.fetchProviderType(this.modelName); + } + } + renderUrlOptions(): TemplateResult { if (!this.providerType?.urlsCustomizable) { return html``; @@ -106,7 +108,6 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm

${msg("URL the user is redirect to to consent the authorization.")}

- +

${msg("URL used by authentik to retrieve tokens.")}

- +

${msg("URL used by authentik to get user information.")} diff --git a/web/src/admin/sources/oauth/OAuthSourceViewPage.ts b/web/src/admin/sources/oauth/OAuthSourceViewPage.ts index f70c13038e..0d4d1035d1 100644 --- a/web/src/admin/sources/oauth/OAuthSourceViewPage.ts +++ b/web/src/admin/sources/oauth/OAuthSourceViewPage.ts @@ -1,7 +1,6 @@ import "@goauthentik/admin/policies/BoundPoliciesList"; import "@goauthentik/admin/sources/oauth/OAuthSourceDiagram"; import "@goauthentik/admin/sources/oauth/OAuthSourceForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/events/ObjectChangelog"; @@ -10,6 +9,7 @@ import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; @@ -44,6 +44,8 @@ export function ProviderToLabel(provider?: ProviderTypeEnum): string { return "Facebook"; case ProviderTypeEnum.Github: return "GitHub"; + case ProviderTypeEnum.Gitlab: + return "GitLab"; case ProviderTypeEnum.Google: return "Google"; case ProviderTypeEnum.Mailcow: diff --git a/web/src/admin/sources/plex/PlexSourceViewPage.ts b/web/src/admin/sources/plex/PlexSourceViewPage.ts index 88287a8b2f..a1bf00c4bb 100644 --- a/web/src/admin/sources/plex/PlexSourceViewPage.ts +++ b/web/src/admin/sources/plex/PlexSourceViewPage.ts @@ -1,6 +1,5 @@ import "@goauthentik/admin/policies/BoundPoliciesList"; import "@goauthentik/admin/sources/plex/PlexSourceForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/events/ObjectChangelog"; @@ -9,6 +8,7 @@ import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; diff --git a/web/src/admin/sources/saml/SAMLSourceViewPage.ts b/web/src/admin/sources/saml/SAMLSourceViewPage.ts index 61abaf5946..4f5d39e104 100644 --- a/web/src/admin/sources/saml/SAMLSourceViewPage.ts +++ b/web/src/admin/sources/saml/SAMLSourceViewPage.ts @@ -1,6 +1,5 @@ import "@goauthentik/admin/policies/BoundPoliciesList"; import "@goauthentik/admin/sources/saml/SAMLSourceForm"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/components/events/ObjectChangelog"; @@ -10,6 +9,7 @@ import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; diff --git a/web/src/admin/sources/scim/SCIMSourceForm.ts b/web/src/admin/sources/scim/SCIMSourceForm.ts new file mode 100644 index 0000000000..1dbe38f1bb --- /dev/null +++ b/web/src/admin/sources/scim/SCIMSourceForm.ts @@ -0,0 +1,86 @@ +import { placeholderHelperText } from "@goauthentik/admin/helperText"; +import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { first } from "@goauthentik/common/utils"; +import "@goauthentik/elements/forms/FormGroup"; +import "@goauthentik/elements/forms/HorizontalFormElement"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; + +import { SCIMSource, SCIMSourceRequest, SourcesApi } from "@goauthentik/api"; + +@customElement("ak-source-scim-form") +export class SCIMSourceForm extends BaseSourceForm { + async loadInstance(pk: string): Promise { + return new SourcesApi(DEFAULT_CONFIG) + .sourcesScimRetrieve({ + slug: pk, + }) + .then((source) => { + return source; + }); + } + + async send(data: SCIMSource): Promise { + if (this.instance?.slug) { + return new SourcesApi(DEFAULT_CONFIG).sourcesScimPartialUpdate({ + slug: this.instance.slug, + patchedSCIMSourceRequest: data, + }); + } else { + return new SourcesApi(DEFAULT_CONFIG).sourcesScimCreate({ + sCIMSourceRequest: data as unknown as SCIMSourceRequest, + }); + } + } + + renderForm(): TemplateResult { + return html`

+ + + + + + + +
+ + +
+
+ + ${msg("Advanced protocol settings")} +
+ + +

${placeholderHelperText}

+
+
+
+
`; + } +} diff --git a/web/src/admin/sources/scim/SCIMSourceGroups.ts b/web/src/admin/sources/scim/SCIMSourceGroups.ts new file mode 100644 index 0000000000..46e14c7c33 --- /dev/null +++ b/web/src/admin/sources/scim/SCIMSourceGroups.ts @@ -0,0 +1,51 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { SCIMSourceGroup, SourcesApi } from "@goauthentik/api"; + +@customElement("ak-source-scim-groups-list") +export class SCIMSourceGroupList extends Table { + @property() + sourceSlug?: string; + + expandable = true; + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new SourcesApi(DEFAULT_CONFIG).sourcesScimGroupsList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + sourceSlug: this.sourceSlug, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Name")), new TableColumn(msg("ID"))]; + } + + renderExpanded(item: SCIMSourceGroup): TemplateResult { + return html` +
+
${JSON.stringify(item.attributes, null, 4)}
+
+ `; + } + + row(item: SCIMSourceGroup): TemplateResult[] { + return [ + html` +
${item.groupObj.name}
+
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/sources/scim/SCIMSourceUsers.ts b/web/src/admin/sources/scim/SCIMSourceUsers.ts new file mode 100644 index 0000000000..1e753c39cf --- /dev/null +++ b/web/src/admin/sources/scim/SCIMSourceUsers.ts @@ -0,0 +1,52 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { SCIMSourceUser, SourcesApi } from "@goauthentik/api"; + +@customElement("ak-source-scim-users-list") +export class SCIMSourceUserList extends Table { + @property() + sourceSlug?: string; + + expandable = true; + searchEnabled(): boolean { + return true; + } + + async apiEndpoint(page: number): Promise> { + return new SourcesApi(DEFAULT_CONFIG).sourcesScimUsersList({ + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + sourceSlug: this.sourceSlug, + }); + } + + columns(): TableColumn[] { + return [new TableColumn(msg("Username")), new TableColumn(msg("ID"))]; + } + + renderExpanded(item: SCIMSourceUser): TemplateResult { + return html` +
+
${JSON.stringify(item.attributes, null, 4)}
+
+ `; + } + + row(item: SCIMSourceUser): TemplateResult[] { + return [ + html` +
${item.userObj.username}
+ ${item.userObj.name} +
`, + html`${item.id}`, + ]; + } +} diff --git a/web/src/admin/sources/scim/SCIMSourceViewPage.ts b/web/src/admin/sources/scim/SCIMSourceViewPage.ts new file mode 100644 index 0000000000..9e11ef46be --- /dev/null +++ b/web/src/admin/sources/scim/SCIMSourceViewPage.ts @@ -0,0 +1,215 @@ +import "@goauthentik/admin/sources/scim/SCIMSourceForm"; +import "@goauthentik/admin/sources/scim/SCIMSourceGroups"; +import "@goauthentik/admin/sources/scim/SCIMSourceUsers"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import "@goauthentik/components/events/ObjectChangelog"; +import { AKElement } from "@goauthentik/elements/Base"; +import "@goauthentik/elements/Tabs"; +import "@goauthentik/elements/buttons/ActionButton"; +import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/buttons/TokenCopyButton"; +import "@goauthentik/elements/forms/ModalForm"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFPage from "@patternfly/patternfly/components/Page/page.css"; +import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { + RbacPermissionsAssignedByUsersListModelEnum, + SCIMSource, + SourcesApi, +} from "@goauthentik/api"; + +@customElement("ak-source-scim-view") +export class SCIMSourceViewPage extends AKElement { + @property({ type: String }) + set sourceSlug(value: string) { + new SourcesApi(DEFAULT_CONFIG) + .sourcesScimRetrieve({ + slug: value, + }) + .then((source) => { + this.source = source; + }); + } + + @property({ attribute: false }) + source?: SCIMSource; + + static get styles(): CSSResult[] { + return [ + PFBase, + PFPage, + PFButton, + PFForm, + PFFormControl, + PFGrid, + PFContent, + PFCard, + PFDescriptionList, + PFBanner, + ]; + } + + constructor() { + super(); + this.addEventListener(EVENT_REFRESH, () => { + if (!this.source?.pk) return; + this.sourceSlug = this.source?.slug; + }); + } + + render(): TemplateResult { + if (!this.source) { + return html``; + } + return html` +
+
+ ${msg("SCIM Source is in preview.")} + ${msg("Send us feedback!")} +
+
+
+
+
+
+
+ ${msg("Name")} +
+
+
+ ${this.source.name} +
+
+
+
+
+ ${msg("Slug")} +
+
+
+ ${this.source.slug} +
+
+
+
+
+ +
+
+
+
+
+
+ + +
+
+ +
+ + ${msg("Click to copy token")} + +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ +
+
+
+
+ +
+
+ +
`; + } +} diff --git a/web/src/admin/stages/StageListPage.ts b/web/src/admin/stages/StageListPage.ts index fb28cf42dc..32d80bfe0c 100644 --- a/web/src/admin/stages/StageListPage.ts +++ b/web/src/admin/stages/StageListPage.ts @@ -5,7 +5,7 @@ import "@goauthentik/admin/stages/authenticator_sms/AuthenticatorSMSStageForm"; import "@goauthentik/admin/stages/authenticator_static/AuthenticatorStaticStageForm"; import "@goauthentik/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm"; import "@goauthentik/admin/stages/authenticator_validate/AuthenticatorValidateStageForm"; -import "@goauthentik/admin/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm"; +import "@goauthentik/admin/stages/authenticator_webauthn/AuthenticatorWebAuthnStageForm"; import "@goauthentik/admin/stages/captcha/CaptchaStageForm"; import "@goauthentik/admin/stages/consent/ConsentStageForm"; import "@goauthentik/admin/stages/deny/DenyStageForm"; @@ -15,6 +15,7 @@ import "@goauthentik/admin/stages/identification/IdentificationStageForm"; import "@goauthentik/admin/stages/invitation/InvitationStageForm"; import "@goauthentik/admin/stages/password/PasswordStageForm"; import "@goauthentik/admin/stages/prompt/PromptStageForm"; +import "@goauthentik/admin/stages/source/SourceStageForm"; import "@goauthentik/admin/stages/user_delete/UserDeleteStageForm"; import "@goauthentik/admin/stages/user_login/UserLoginStageForm"; import "@goauthentik/admin/stages/user_logout/UserLogoutStageForm"; @@ -55,6 +56,7 @@ export class StageListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/stages/StageWizard.ts b/web/src/admin/stages/StageWizard.ts index 3ace712e4d..0e5d483d0d 100644 --- a/web/src/admin/stages/StageWizard.ts +++ b/web/src/admin/stages/StageWizard.ts @@ -1,10 +1,11 @@ +import "@goauthentik/admin/common/ak-license-notice"; import { StageBindingForm } from "@goauthentik/admin/flows/StageBindingForm"; import "@goauthentik/admin/stages/authenticator_duo/AuthenticatorDuoStageForm"; import "@goauthentik/admin/stages/authenticator_sms/AuthenticatorSMSStageForm"; import "@goauthentik/admin/stages/authenticator_static/AuthenticatorStaticStageForm"; import "@goauthentik/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm"; import "@goauthentik/admin/stages/authenticator_validate/AuthenticatorValidateStageForm"; -import "@goauthentik/admin/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm"; +import "@goauthentik/admin/stages/authenticator_webauthn/AuthenticatorWebAuthnStageForm"; import "@goauthentik/admin/stages/captcha/CaptchaStageForm"; import "@goauthentik/admin/stages/consent/ConsentStageForm"; import "@goauthentik/admin/stages/deny/DenyStageForm"; @@ -14,6 +15,7 @@ import "@goauthentik/admin/stages/identification/IdentificationStageForm"; import "@goauthentik/admin/stages/invitation/InvitationStageForm"; import "@goauthentik/admin/stages/password/PasswordStageForm"; import "@goauthentik/admin/stages/prompt/PromptStageForm"; +import "@goauthentik/admin/stages/source/SourceStageForm"; import "@goauthentik/admin/stages/user_delete/UserDeleteStageForm"; import "@goauthentik/admin/stages/user_login/UserLoginStageForm"; import "@goauthentik/admin/stages/user_logout/UserLogoutStageForm"; @@ -23,80 +25,24 @@ import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/wizard/FormWizardPage"; import { FormWizardPage } from "@goauthentik/elements/wizard/FormWizardPage"; +import "@goauthentik/elements/wizard/TypeCreateWizardPage"; import "@goauthentik/elements/wizard/Wizard"; -import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; +import { Wizard } from "@goauthentik/elements/wizard/Wizard"; import { msg, str } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { CSSResult, TemplateResult, html } from "lit"; -import { property } from "lit/decorators.js"; +import { property, query } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { FlowStageBinding, Stage, StagesApi, TypeCreate } from "@goauthentik/api"; -@customElement("ak-stage-wizard-initial") -export class InitialStageWizardPage extends WizardPage { - @property({ attribute: false }) - stageTypes: TypeCreate[] = []; - sidebarLabel = () => msg("Select type"); - - static get styles(): CSSResult[] { - return [PFBase, PFForm, PFButton, PFRadio]; - } - - activeCallback: () => Promise = async () => { - this.host.isValid = false; - this.shadowRoot - ?.querySelectorAll("input[type=radio]") - .forEach((radio) => { - if (radio.checked) { - radio.dispatchEvent(new CustomEvent("change")); - } - }); - }; - - render(): TemplateResult { - return html`
- ${this.stageTypes.map((type) => { - return html`
- { - const idx = this.host.steps.indexOf("initial") + 1; - // Exclude all current steps starting with type-, - // this happens when the user selects a type and then goes back - this.host.steps = this.host.steps.filter( - (step) => !step.startsWith("type-"), - ); - this.host.steps.splice( - idx, - 0, - `type-${type.component}-${type.modelName}`, - ); - this.host.isValid = true; - }} - /> - - ${type.description} -
`; - })} -
`; - } -} - @customElement("ak-stage-wizard") export class StageWizard extends AKElement { static get styles(): CSSResult[] { - return [PFBase, PFButton, PFRadio]; + return [PFBase, PFButton]; } @property() @@ -111,6 +57,9 @@ export class StageWizard extends AKElement { @property({ attribute: false }) stageTypes: TypeCreate[] = []; + @query("ak-wizard") + wizard?: Wizard; + firstUpdated(): void { new StagesApi(DEFAULT_CONFIG).stagesAllTypesList().then((types) => { this.stageTypes = types; @@ -124,8 +73,26 @@ export class StageWizard extends AKElement { header=${msg("New stage")} description=${msg("Create a new stage.")} > - - + ) => { + if (!this.wizard) return; + const idx = this.wizard.steps.indexOf("initial") + 1; + // Exclude all current steps starting with type-, + // this happens when the user selects a type and then goes back + this.wizard.steps = this.wizard.steps.filter( + (step) => !step.startsWith("type-"), + ); + this.wizard.steps.splice( + idx, + 0, + `type-${ev.detail.component}-${ev.detail.modelName}`, + ); + this.wizard.isValid = true; + }} + > + ${this.stageTypes.map((type) => { return html` + const authenticators = [ + [DeviceClassesEnum.Static, msg("Static Tokens")], + [DeviceClassesEnum.Totp, msg("TOTP Authenticators")], + [DeviceClassesEnum.Webauthn, msg("WebAuthn Authenticators")], + [DeviceClassesEnum.Duo, msg("Duo Authenticators")], + [DeviceClassesEnum.Sms, msg("SMS-based Authenticators")], + ]; + + return html` + ${msg( "Stage used to validate any authenticator. This stage should be used during authentication or authorization flows.", )} @@ -84,44 +97,19 @@ export class AuthenticatorValidateStageForm extends BaseStageForm - + authenticator[0]) + .filter((name) => + this.isDeviceClassSelected(name as DeviceClassesEnum), + )} + >

${msg("Device classes which can be used to authenticate.")}

-

- ${msg("Hold control/command to select multiple items.")} -

${msg( - "If any of the devices user of the types selected above have been used within this duration, this stage will be skipped.", + "If the user has successfully authenticated with a device in the classes listed above within this configured duration, this stage will be skipped.", )}

@@ -183,33 +171,6 @@ export class AuthenticatorValidateStageForm extends BaseStageForm
- - - - ${this.showConfigurationStages ? html` -
`; + + + ${msg("WebAuthn-specific settings")} +
+ + + + + + => { + return new StagesApi(DEFAULT_CONFIG) + .stagesAuthenticatorWebauthnDeviceTypesList({ + page: page, + search: search, + }) + .then((results) => { + return { + pagination: results.pagination, + options: results.results.map(deviceTypeRestrictionPair), + }; + }); + }} + .selected=${(this.instance?.webauthnAllowedDeviceTypesObj ?? []).map( + deviceTypeRestrictionPair, + )} + available-label="${msg("Available Device types")}" + selected-label="${msg("Selected Device types")}" + > +

+ ${msg( + "Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.", + )} +

+ + ${ + /* TODO: Remove this after 2024.6..or maybe later? */ + msg( + "This restriction only applies to devices created in authentik 2024.4 or later.", + ) + } + +
+
+
+ `; } } diff --git a/web/src/admin/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts b/web/src/admin/stages/authenticator_webauthn/AuthenticatorWebAuthnStageForm.ts similarity index 78% rename from web/src/admin/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts rename to web/src/admin/stages/authenticator_webauthn/AuthenticatorWebAuthnStageForm.ts index d8464b6f3d..104d31047f 100644 --- a/web/src/admin/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts +++ b/web/src/admin/stages/authenticator_webauthn/AuthenticatorWebAuthnStageForm.ts @@ -1,7 +1,10 @@ import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; +import { deviceTypeRestrictionPair } from "@goauthentik/admin/stages/authenticator_webauthn/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; +import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; +import { DataProvision } from "@goauthentik/elements/ak-dual-select/types"; import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/SearchSelect"; @@ -11,8 +14,8 @@ import { TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; import { - AuthenticateWebAuthnStage, AuthenticatorAttachmentEnum, + AuthenticatorWebAuthnStage, Flow, FlowsApi, FlowsInstancesListDesignationEnum, @@ -23,25 +26,25 @@ import { } from "@goauthentik/api"; @customElement("ak-stage-authenticator-webauthn-form") -export class AuthenticateWebAuthnStageForm extends BaseStageForm { - loadInstance(pk: string): Promise { - return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnRetrieve({ +export class AuthenticatorWebAuthnStageForm extends BaseStageForm { + async loadInstance(pk: string): Promise { + return await new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnRetrieve({ stageUuid: pk, }); } - async send(data: AuthenticateWebAuthnStage): Promise { + async send(data: AuthenticatorWebAuthnStage): Promise { if (data.authenticatorAttachment?.toString() === "") { data.authenticatorAttachment = null; } if (this.instance) { return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnUpdate({ stageUuid: this.instance.pk || "", - authenticateWebAuthnStageRequest: data, + authenticatorWebAuthnStageRequest: data, }); } else { return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnCreate({ - authenticateWebAuthnStageRequest: data, + authenticatorWebAuthnStageRequest: data, }); } } @@ -164,6 +167,36 @@ export class AuthenticateWebAuthnStageForm extends BaseStageForm
+ + => { + return new StagesApi(DEFAULT_CONFIG) + .stagesAuthenticatorWebauthnDeviceTypesList({ + page: page, + search: search, + }) + .then((results) => { + return { + pagination: results.pagination, + options: results.results.map(deviceTypeRestrictionPair), + }; + }); + }} + .selected=${(this.instance?.deviceTypeRestrictionsObj ?? []).map( + deviceTypeRestrictionPair, + )} + available-label="${msg("Available Device types")}" + selected-label="${msg("Selected Device types")}" + > +

+ ${msg( + "Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.", + )} +

+
${label}
+
${item.aaguid}
`, + label, + ]; +} diff --git a/web/src/admin/stages/identification/IdentificationStageForm.ts b/web/src/admin/stages/identification/IdentificationStageForm.ts index cc064adf1c..75db877160 100644 --- a/web/src/admin/stages/identification/IdentificationStageForm.ts +++ b/web/src/admin/stages/identification/IdentificationStageForm.ts @@ -2,12 +2,13 @@ import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first, groupBy } from "@goauthentik/common/utils"; +import "@goauthentik/elements/ak-checkbox-group/ak-checkbox-group.js"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/SearchSelect"; import { msg } from "@lit/localize"; -import { TemplateResult, html } from "lit"; +import { TemplateResult, css, html } from "lit"; import { customElement } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -24,6 +25,17 @@ import { @customElement("ak-stage-identification-form") export class IdentificationStageForm extends BaseStageForm { + static get styles() { + return [ + ...super.styles, + css` + ak-checkbox-group::part(checkbox-group) { + padding-top: var(--pf-c-form--m-horizontal__group-label--md--PaddingTop); + } + `, + ]; + } + loadInstance(pk: string): Promise { return new StagesApi(DEFAULT_CONFIG).stagesIdentificationRetrieve({ stageUuid: pk, @@ -60,6 +72,12 @@ export class IdentificationStageForm extends BaseStageForm } renderForm(): TemplateResult { + const userSelectFields = [ + { name: UserFieldsEnum.Username, label: msg("Username") }, + { name: UserFieldsEnum.Email, label: msg("Email") }, + { name: UserFieldsEnum.Upn, label: msg("UPN") }, + ]; + return html` ${msg("Let the user identify themselves with their username or Email address.")} @@ -75,34 +93,18 @@ export class IdentificationStageForm extends BaseStageForm ${msg("Stage-specific settings")}
- + name) + .filter((name) => this.isUserFieldSelected(name))} + >

${msg( "Fields a user can identify themselves with. If no fields are selected, the user will only be able to use sources.", )}

-

- ${msg("Hold control/command to select multiple items.")} -

name="sources" >

${msg( diff --git a/web/src/admin/stages/invitation/InvitationListPage.ts b/web/src/admin/stages/invitation/InvitationListPage.ts index 1eb1367361..c673282a78 100644 --- a/web/src/admin/stages/invitation/InvitationListPage.ts +++ b/web/src/admin/stages/invitation/InvitationListPage.ts @@ -51,6 +51,7 @@ export class InvitationListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "expires"; diff --git a/web/src/admin/stages/password/PasswordStageForm.ts b/web/src/admin/stages/password/PasswordStageForm.ts index 939f929315..2732f8c749 100644 --- a/web/src/admin/stages/password/PasswordStageForm.ts +++ b/web/src/admin/stages/password/PasswordStageForm.ts @@ -54,6 +54,21 @@ export class PasswordStageForm extends BaseStageForm { } renderForm(): TemplateResult { + const backends = [ + { + name: BackendsEnum.CoreAuthInbuiltBackend, + label: msg("User database + standard password"), + }, + { + name: BackendsEnum.CoreAuthTokenBackend, + label: msg("User database + app passwords"), + }, + { + name: BackendsEnum.SourcesLdapAuthLdapBackend, + label: msg("User database + LDAP password"), + }, + ]; + return html` ${msg("Validate the user's password against the selected backend(s).")} @@ -73,32 +88,13 @@ export class PasswordStageForm extends BaseStageForm { ?required=${true} name="backends" > - + name) + .filter((name) => this.isBackendSelected(name))} + >

${msg("Selection of backends to test the password against.")}

diff --git a/web/src/admin/stages/prompt/PromptForm.ts b/web/src/admin/stages/prompt/PromptForm.ts index 386ae7004f..234d0a8bb0 100644 --- a/web/src/admin/stages/prompt/PromptForm.ts +++ b/web/src/admin/stages/prompt/PromptForm.ts @@ -11,6 +11,7 @@ import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { map } from "lit/directives/map.js"; import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; @@ -121,120 +122,35 @@ export class PromptForm extends ModelForm { } renderTypes(): TemplateResult { - return html` - - - - - - - - - - - - - - - - - - - `; + // prettier-ignore + const promptTypesWithLabels = [ + [PromptTypeEnum.Text, msg("Text: Simple Text input")], + [PromptTypeEnum.TextArea, msg("Text Area: Multiline text input")], + [PromptTypeEnum.TextReadOnly, msg("Text (read-only): Simple Text input, but cannot be edited.")], + [PromptTypeEnum.TextAreaReadOnly, msg("Text Area (read-only): Multiline text input, but cannot be edited.")], + [PromptTypeEnum.Username, msg("Username: Same as Text input, but checks for and prevents duplicate usernames.")], + [PromptTypeEnum.Email, msg("Email: Text field with Email type.")], + [PromptTypeEnum.Password, msg("Password: Masked input, multiple inputs of this type on the same prompt need to be identical.")], + [PromptTypeEnum.Number, msg("Number")], + [PromptTypeEnum.Checkbox, msg("Checkbox")], + [PromptTypeEnum.RadioButtonGroup, msg("Radio Button Group (fixed choice)")], + [PromptTypeEnum.Dropdown, msg("Dropdown (fixed choice)")], + [PromptTypeEnum.Date, msg("Date")], + [PromptTypeEnum.DateTime, msg("Date Time")], + [PromptTypeEnum.File, msg("File")], + [PromptTypeEnum.Separator, msg("Separator: Static Separator Line")], + [PromptTypeEnum.Hidden, msg("Hidden: Hidden field, can be used to insert data into form.")], + [PromptTypeEnum.Static, msg("Static: Static value, displayed as-is.")], + [PromptTypeEnum.AkLocale, msg("authentik: Locale: Displays a list of locales authentik supports.")], + ]; + const currentType = this.instance?.type; + return html` ${map( + promptTypesWithLabels, + ([promptType, label]) => + html``, + )}`; } renderForm(): TemplateResult { diff --git a/web/src/admin/stages/prompt/PromptListPage.ts b/web/src/admin/stages/prompt/PromptListPage.ts index c2b84a689b..3b3a7869ee 100644 --- a/web/src/admin/stages/prompt/PromptListPage.ts +++ b/web/src/admin/stages/prompt/PromptListPage.ts @@ -33,6 +33,7 @@ export class PromptListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/stages/source/SourceStageForm.ts b/web/src/admin/stages/source/SourceStageForm.ts new file mode 100644 index 0000000000..bfb4d5e40a --- /dev/null +++ b/web/src/admin/stages/source/SourceStageForm.ts @@ -0,0 +1,103 @@ +import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import "@goauthentik/elements/forms/HorizontalFormElement"; +import "@goauthentik/elements/forms/SearchSelect/index"; +import "@goauthentik/elements/utils/TimeDeltaHelp"; + +import { msg } from "@lit/localize"; +import { TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; + +import { + Source, + SourceStage, + SourcesAllListRequest, + SourcesApi, + StagesApi, +} from "@goauthentik/api"; + +@customElement("ak-stage-source-form") +export class SourceStageForm extends BaseStageForm { + loadInstance(pk: string): Promise { + return new StagesApi(DEFAULT_CONFIG).stagesSourceRetrieve({ + stageUuid: pk, + }); + } + + async send(data: SourceStage): Promise { + if (this.instance) { + return new StagesApi(DEFAULT_CONFIG).stagesSourceUpdate({ + stageUuid: this.instance.pk || "", + sourceStageRequest: data, + }); + } else { + return new StagesApi(DEFAULT_CONFIG).stagesSourceCreate({ + sourceStageRequest: data, + }); + } + } + + renderForm(): TemplateResult { + return html` + ${msg( + "Inject an OAuth or SAML Source into the flow execution. This allows for additional user verification, or to dynamically access different sources for different user identifiers (username, email address, etc).", + )} + + + + + => { + const args: SourcesAllListRequest = { + ordering: "name", + }; + if (query !== undefined) { + args.search = query; + } + const users = await new SourcesApi(DEFAULT_CONFIG).sourcesAllList(args); + return users.results; + }} + .renderElement=${(source: Source): string => { + return source.name; + }} + .renderDescription=${(source: Source): TemplateResult => { + return html`${source.verboseName}`; + }} + .value=${(source: Source | undefined): string | undefined => { + return source?.pk; + }} + .selected=${(source: Source): boolean => { + return source.pk === this.instance?.source; + }} + > + + + + +

+ ${msg( + "Amount of time a user can take to return from the source to continue the flow.", + )} +

+ +
+ `; + } +} diff --git a/web/src/admin/stages/user_write/UserWriteStageForm.ts b/web/src/admin/stages/user_write/UserWriteStageForm.ts index 08b436f9bb..4f2d285e93 100644 --- a/web/src/admin/stages/user_write/UserWriteStageForm.ts +++ b/web/src/admin/stages/user_write/UserWriteStageForm.ts @@ -110,10 +110,7 @@ export class UserWriteStageForm extends BaseStageForm { ${msg("Mark newly created users as inactive.")}

- + { .fetchObjects=${async (query?: string): Promise => { const args: CoreGroupsListRequest = { ordering: "name", + includeUsers: false, }; if (query !== undefined) { args.search = query; diff --git a/web/src/admin/system-tasks/SystemTaskListPage.ts b/web/src/admin/system-tasks/SystemTaskListPage.ts index 82dc9171f0..9947bc0d7c 100644 --- a/web/src/admin/system-tasks/SystemTaskListPage.ts +++ b/web/src/admin/system-tasks/SystemTaskListPage.ts @@ -1,9 +1,11 @@ -import { uiConfig } from "@goauthentik/app/common/ui/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import { PFColor } from "@goauthentik/elements/Label"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/SpinnerButton"; +import "@goauthentik/elements/events/LogViewer"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; import { TablePage } from "@goauthentik/elements/table/TablePage"; @@ -31,6 +33,10 @@ export class SystemTaskListPage extends TablePage { expandable = true; + searchEnabled(): boolean { + return true; + } + @property() order = "name"; @@ -84,15 +90,34 @@ export class SystemTaskListPage extends TablePage {
+
+
+ ${msg("Expiry")} +
+
+
+ ${item.expiring + ? html` + + ${getRelativeTime(item.expires || new Date())} + + ` + : msg("-")} +
+
+
${msg("Messages")}
- ${item.messages.map((m) => { - return html`
  • ${m}
  • `; - })} +
    @@ -105,9 +130,10 @@ export class SystemTaskListPage extends TablePage { row(item: SystemTask): TemplateResult[] { return [ - html`${item.name}${item.uid ? `:${item.uid}` : ""}`, + html`
    ${item.name}${item.uid ? `:${item.uid}` : ""}
    `, html`${item.description}`, - html`${item.finishTimestamp.toLocaleString()}`, + html`
    ${getRelativeTime(item.finishTimestamp)}
    + ${item.finishTimestamp.toLocaleString()}`, this.taskStatus(item), html` { } checkbox = true; + clearOnRefresh = true; @property() order = "expires"; @@ -110,7 +112,10 @@ export class TokenListPage extends TablePage { : html``}`, html`${item.userObj?.username}`, html``, - html`${item.expiring ? item.expires?.toLocaleString() : msg("-")}`, + html`${item.expires && item.expiring + ? html`
    ${getRelativeTime(item.expires)}
    + ${item.expires.toLocaleString()}` + : msg("-")}`, html`${intentToLabel(item.intent ?? IntentEnum.Api)}`, html` ${!item.managed diff --git a/web/src/admin/users/GroupSelectModal.ts b/web/src/admin/users/GroupSelectModal.ts index eac99d4aeb..015c8658fa 100644 --- a/web/src/admin/users/GroupSelectModal.ts +++ b/web/src/admin/users/GroupSelectModal.ts @@ -38,6 +38,7 @@ export class GroupSelectModal extends TableModal { page: page, pageSize: (await uiConfig()).pagination.perPage, search: this.search || "", + includeUsers: false, }); } diff --git a/web/src/admin/users/UserApplicationTable.ts b/web/src/admin/users/UserApplicationTable.ts new file mode 100644 index 0000000000..c5af92624d --- /dev/null +++ b/web/src/admin/users/UserApplicationTable.ts @@ -0,0 +1,79 @@ +import { applicationListStyle } from "@goauthentik/admin/applications/ApplicationListPage"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PFSize } from "@goauthentik/common/enums.js"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import "@goauthentik/components/ak-app-icon"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; +import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import { Application, CoreApi, User } from "@goauthentik/api"; + +@customElement("ak-user-application-table") +export class UserApplicationTable extends Table { + @property({ attribute: false }) + user?: User; + + static get styles(): CSSResult[] { + return super.styles.concat(applicationListStyle); + } + + async apiEndpoint(page: number): Promise> { + return new CoreApi(DEFAULT_CONFIG).coreApplicationsList({ + forUser: this.user?.pk, + page: page, + pageSize: (await uiConfig()).pagination.perPage, + ordering: this.order, + search: this.search || "", + }); + } + + columns(): TableColumn[] { + return [ + new TableColumn(""), + new TableColumn(msg("Name"), "name"), + new TableColumn(msg("Group"), "group"), + new TableColumn(msg("Provider")), + new TableColumn(msg("Provider Type")), + new TableColumn(msg("Actions")), + ]; + } + + row(item: Application): TemplateResult[] { + return [ + html``, + html` +
    ${item.name}
    + ${item.metaPublisher ? html`${item.metaPublisher}` : html``} +
    `, + html`${item.group || msg("-")}`, + item.provider + ? html` + ${item.providerObj?.name} + ` + : html`-`, + html`${item.providerObj?.verboseName || msg("-")}`, + html` + ${msg("Update")} + ${msg("Update Application")} + + + + + ${item.launchUrl + ? html` + + + + ` + : html``}`, + ]; + } +} diff --git a/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts b/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts index 99f171c816..e1fdf58ec8 100644 --- a/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts +++ b/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts @@ -1,9 +1,9 @@ import "@goauthentik/admin/users/UserPermissionForm"; -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { groupBy } from "@goauthentik/app/common/utils"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; @@ -19,6 +19,7 @@ export class UserAssignedGlobalPermissionsTable extends Table { userId?: number; checkbox = true; + clearOnRefresh = true; apiEndpoint(page: number): Promise> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsList({ @@ -83,6 +84,10 @@ export class UserAssignedGlobalPermissionsTable extends Table { } row(item: Permission): TemplateResult[] { - return [html`${item.modelVerbose}`, html`${item.name}`, html`✓`]; + return [ + html`${item.modelVerbose}`, + html`${item.name}`, + html``, + ]; } } diff --git a/web/src/admin/users/UserAssignedObjectPermissionsTable.ts b/web/src/admin/users/UserAssignedObjectPermissionsTable.ts index 8e63ae8bb2..2137fc09ab 100644 --- a/web/src/admin/users/UserAssignedObjectPermissionsTable.ts +++ b/web/src/admin/users/UserAssignedObjectPermissionsTable.ts @@ -1,7 +1,7 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { groupBy } from "@goauthentik/app/common/utils"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/DeleteBulkForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; @@ -16,6 +16,7 @@ export class UserAssignedObjectPermissionsTable extends Table> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsUsersList({ @@ -85,7 +86,7 @@ export class UserAssignedObjectPermissionsTable extends Table
    ${item.objectPk}
    `}`, - html`✓`, + html``, ]; } } diff --git a/web/src/admin/users/UserDevicesTable.ts b/web/src/admin/users/UserDevicesTable.ts index 06ead21dfd..9f02e7fcd6 100644 --- a/web/src/admin/users/UserDevicesTable.ts +++ b/web/src/admin/users/UserDevicesTable.ts @@ -16,6 +16,7 @@ export class UserDeviceTable extends Table { userId?: number; checkbox = true; + clearOnRefresh = true; async apiEndpoint(): Promise> { return new AuthenticatorsApi(DEFAULT_CONFIG) diff --git a/web/src/admin/users/UserForm.ts b/web/src/admin/users/UserForm.ts index 061fd6f56a..f8b0b00e39 100644 --- a/web/src/admin/users/UserForm.ts +++ b/web/src/admin/users/UserForm.ts @@ -128,6 +128,14 @@ export class UserForm extends ModelForm { "Service accounts should be used for machine-to-machine authentication or other automations.", )}`, }, + { + label: "Internal Service account", + value: UserTypeEnum.InternalServiceAccount, + disabled: true, + description: html`${msg( + "Internal Service accounts are created and managed by authentik and cannot be created manually.", + )}`, + }, ]} .value=${this.instance?.type} > diff --git a/web/src/admin/users/UserListPage.ts b/web/src/admin/users/UserListPage.ts index 4f68955605..4dfa67f4b8 100644 --- a/web/src/admin/users/UserListPage.ts +++ b/web/src/admin/users/UserListPage.ts @@ -4,12 +4,13 @@ import "@goauthentik/admin/users/UserActiveForm"; import "@goauthentik/admin/users/UserForm"; import "@goauthentik/admin/users/UserPasswordForm"; import "@goauthentik/admin/users/UserResetEmailForm"; -import { me } from "@goauthentik/app/common/users"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PFSize } from "@goauthentik/common/enums.js"; import { userTypeToLabel } from "@goauthentik/common/labels"; import { MessageLevel } from "@goauthentik/common/messages"; import { DefaultUIConfig, uiConfig } from "@goauthentik/common/ui/config"; -import { first } from "@goauthentik/common/utils"; +import { me } from "@goauthentik/common/users"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import { rootInterface } from "@goauthentik/elements/Base"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; @@ -17,7 +18,6 @@ import { CapabilitiesEnum, WithCapabilitiesConfig, } from "@goauthentik/elements/Interface/capabilitiesProvider"; -import { PFSize } from "@goauthentik/elements/Spinner"; import "@goauthentik/elements/TreeView"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/forms/DeleteBulkForm"; @@ -42,7 +42,7 @@ import { CoreApi, ResponseError, SessionUser, User, UserPath } from "@goauthenti export const requestRecoveryLink = (user: User) => new CoreApi(DEFAULT_CONFIG) - .coreUsersRecoveryRetrieve({ + .coreUsersRecoveryCreate({ id: user.pk, }) .then((rec) => @@ -94,6 +94,7 @@ const recoveryButtonStyles = css` export class UserListPage extends WithBrandConfig(WithCapabilitiesConfig(TablePage)) { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; @@ -145,6 +146,7 @@ export class UserListPage extends WithBrandConfig(WithCapabilitiesConfig(TablePa search: this.search || "", pathStartswith: getURLParam("path", ""), isActive: this.hideDeactivated ? true : undefined, + includeGroups: false, }); this.userPaths = await new CoreApi(DEFAULT_CONFIG).coreUsersPathsRetrieve({ search: this.search, @@ -158,6 +160,7 @@ export class UserListPage extends WithBrandConfig(WithCapabilitiesConfig(TablePa new TableColumn(msg("Name"), "username"), new TableColumn(msg("Active"), "is_active"), new TableColumn(msg("Last login"), "last_login"), + new TableColumn(msg("Type"), "type"), new TableColumn(msg("Actions")), ]; } @@ -245,11 +248,15 @@ export class UserListPage extends WithBrandConfig(WithCapabilitiesConfig(TablePa this.can(CapabilitiesEnum.CanImpersonate) && item.pk !== this.me?.user.pk; return [ html` -
    ${item.username}
    - ${item.name === "" ? msg("") : item.name}
     ${userTypeToLabel(item.type)}`, +
    ${item.username}
    + ${item.name === "" ? msg("") : item.name} + `, html``, - html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`, + html`${item.lastLogin + ? html`
    ${getRelativeTime(item.lastLogin)}
    + ${item.lastLogin.toLocaleString()}` + : msg("-")}`, + html`${userTypeToLabel(item.type)}`, html` ${msg("Update")} ${msg("Update User")} diff --git a/web/src/admin/users/UserResetEmailForm.ts b/web/src/admin/users/UserResetEmailForm.ts index bd450a57bd..a11f17d440 100644 --- a/web/src/admin/users/UserResetEmailForm.ts +++ b/web/src/admin/users/UserResetEmailForm.ts @@ -10,7 +10,7 @@ import { customElement, property } from "lit/decorators.js"; import { CoreApi, - CoreUsersRecoveryEmailRetrieveRequest, + CoreUsersRecoveryEmailCreateRequest, Stage, StagesAllListRequest, StagesApi, @@ -18,7 +18,7 @@ import { } from "@goauthentik/api"; @customElement("ak-user-reset-email-form") -export class UserResetEmailForm extends Form { +export class UserResetEmailForm extends Form { @property({ attribute: false }) user!: User; @@ -26,9 +26,9 @@ export class UserResetEmailForm extends Form { + async send(data: CoreUsersRecoveryEmailCreateRequest): Promise { data.id = this.user.pk; - return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryEmailRetrieve(data); + return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryEmailCreate(data); } renderForm(): TemplateResult { diff --git a/web/src/admin/users/UserViewPage.ts b/web/src/admin/users/UserViewPage.ts index ddc9e92ba7..f5188d12be 100644 --- a/web/src/admin/users/UserViewPage.ts +++ b/web/src/admin/users/UserViewPage.ts @@ -1,19 +1,20 @@ import "@goauthentik/admin/groups/RelatedGroupList"; +import "@goauthentik/admin/providers/rac/ConnectionTokenList"; import "@goauthentik/admin/users/UserActiveForm"; +import "@goauthentik/admin/users/UserApplicationTable"; import "@goauthentik/admin/users/UserChart"; import "@goauthentik/admin/users/UserForm"; -import "@goauthentik/admin/users/UserPasswordForm"; -import "@goauthentik/app/admin/users/UserAssignedGlobalPermissionsTable"; -import "@goauthentik/app/admin/users/UserAssignedObjectPermissionsTable"; import { renderRecoveryEmailRequest, requestRecoveryLink, -} from "@goauthentik/app/admin/users/UserListPage"; -import { me } from "@goauthentik/app/common/users"; -import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; +} from "@goauthentik/admin/users/UserListPage"; +import "@goauthentik/admin/users/UserPasswordForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { PFSize } from "@goauthentik/common/enums.js"; import { userTypeToLabel } from "@goauthentik/common/labels"; +import { me } from "@goauthentik/common/users"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/DescriptionList"; import { type DescriptionPair, @@ -26,17 +27,19 @@ import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/CodeMirror"; import { WithCapabilitiesConfig } from "@goauthentik/elements/Interface/capabilitiesProvider"; import "@goauthentik/elements/PageHeader"; -import { PFSize } from "@goauthentik/elements/Spinner"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/forms/ModalForm"; -import "@goauthentik/elements/oauth/UserRefreshList"; +import "@goauthentik/elements/oauth/UserAccessTokenList"; +import "@goauthentik/elements/oauth/UserRefreshTokenList"; +import "@goauthentik/elements/rbac/ObjectPermissionsPage"; import "@goauthentik/elements/user/SessionList"; import "@goauthentik/elements/user/UserConsentList"; +import "@goauthentik/elements/user/sources/SourceSettings"; import { msg, str } from "@lit/localize"; -import { css, html, nothing } from "lit"; +import { TemplateResult, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; @@ -148,7 +151,10 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) { [msg("Username"), user.username], [msg("Name"), user.name], [msg("Email"), user.email || "-"], - [msg("Last login"), user.lastLogin?.toLocaleString()], + [msg("Last login"), user.lastLogin + ? html`
    ${getRelativeTime(user.lastLogin)}
    + ${user.lastLogin.toLocaleString()}` + : html`${msg("-")}`], [msg("Active"), html``], [msg("Type"), userTypeToLabel(user.type)], [msg("Superuser"), html``], @@ -227,48 +233,125 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) { renderRecoveryButtons(user: User) { return html`
    - - ${msg("Update password")} - ${msg("Update password")} - - - - requestRecoveryLink(user)} - > - - ${msg("Create Recovery Link")} - - - ${user.email ? renderRecoveryEmailRequest(user) : nothing} -
    - + + ${msg("Update password")} + ${msg("Update password")} + + + + requestRecoveryLink(user)} + > + + ${msg("Create Recovery Link")} + + + ${user.email ? renderRecoveryEmailRequest(user) : nothing} +
    `; + } + + renderTabCredentialsToken(user: User): TemplateResult { + return html` + +
    +
    +
    + + +
    -
    - + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + `; } + renderTabApplications(user: User): TemplateResult { + return html`
    +
    + +
    +
    `; + } + renderBody() { if (!this.user) { return nothing; @@ -326,18 +409,6 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) { -
    -
    -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    +
    + ${this.renderTabCredentialsToken(this.user)}
    -
    -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    + ${this.renderTabApplications(this.user)}
    -
    -
    - ${msg("RBAC is in preview.")} - ${msg("Send us feedback!")} -
    -
    -
    -
    -
    - ${msg("Assigned global permissions")} -
    -
    - - -
    -
    -
    -
    - ${msg("Assigned object permissions")} -
    -
    - - -
    -
    -
    -
    -
    + `; } } diff --git a/web/src/assets/images/flow_background.jpg b/web/src/assets/images/flow_background.jpg index 769d1f41c7..643337c052 100644 Binary files a/web/src/assets/images/flow_background.jpg and b/web/src/assets/images/flow_background.jpg differ diff --git a/web/src/common/api/config.ts b/web/src/common/api/config.ts index dd1a2c1b75..52b2f8f55c 100644 --- a/web/src/common/api/config.ts +++ b/web/src/common/api/config.ts @@ -3,7 +3,7 @@ import { EventMiddleware, LoggingMiddleware, } from "@goauthentik/common/api/middleware"; -import { EVENT_LOCALE_REQUEST, EVENT_REFRESH, VERSION } from "@goauthentik/common/constants"; +import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants"; import { globalAK } from "@goauthentik/common/global"; import { Config, Configuration, CoreApi, CurrentBrand, RootApi } from "@goauthentik/api"; @@ -86,13 +86,4 @@ export function AndNext(url: string): string { return `?next=${encodeURIComponent(url)}`; } -window.addEventListener(EVENT_REFRESH, () => { - // Upon global refresh, disregard whatever was pre-hydrated and - // actually load info from API - globalConfigPromise = undefined; - globalBrandPromise = undefined; - config(); - brand(); -}); - console.debug(`authentik(early): version ${VERSION}, apiBase ${DEFAULT_CONFIG.basePath}`); diff --git a/web/src/common/constants.ts b/web/src/common/constants.ts index 03ee1393a3..8d8a1631bf 100644 --- a/web/src/common/constants.ts +++ b/web/src/common/constants.ts @@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success"; export const ERROR_CLASS = "pf-m-danger"; export const PROGRESS_CLASS = "pf-m-in-progress"; export const CURRENT_CLASS = "pf-m-current"; -export const VERSION = "2023.10.6"; +export const VERSION = "2024.4.2"; export const TITLE_DEFAULT = "authentik"; export const ROUTE_SEPARATOR = ";"; @@ -19,6 +19,7 @@ export const EVENT_LOCALE_REQUEST = "ak-locale-request"; export const EVENT_REQUEST_POST = "ak-request-post"; export const EVENT_MESSAGE = "ak-message"; export const EVENT_THEME_CHANGE = "ak-theme-change"; +export const EVENT_REFRESH_ENTERPRISE = "ak-refresh-enterprise"; export const WS_MSG_TYPE_MESSAGE = "message"; export const WS_MSG_TYPE_REFRESH = "refresh"; diff --git a/web/src/common/enums.ts b/web/src/common/enums.ts new file mode 100644 index 0000000000..5087054228 --- /dev/null +++ b/web/src/common/enums.ts @@ -0,0 +1,6 @@ +export enum PFSize { + Small = "pf-m-sm", + Medium = "pf-m-md", + Large = "pf-m-lg", + XLarge = "pf-m-xl", +} diff --git a/web/src/common/errors.ts b/web/src/common/errors.ts index ad6156bfad..6d71b27704 100644 --- a/web/src/common/errors.ts +++ b/web/src/common/errors.ts @@ -16,7 +16,7 @@ export async function parseAPIError(error: Error): Promise { if (!(error instanceof ResponseError)) { return error; } - if (error.response.status < 400 && error.response.status > 499) { + if (error.response.status < 400 || error.response.status > 499) { return error; } const body = await error.response.json(); diff --git a/web/src/common/helpers/plex.ts b/web/src/common/helpers/plex.ts index 6e9639934b..c3735af5bd 100644 --- a/web/src/common/helpers/plex.ts +++ b/web/src/common/helpers/plex.ts @@ -55,9 +55,7 @@ export class PlexAPIClient { ): Promise<{ authUrl: string; pin: PlexPinResponse }> { const headers = { ...DEFAULT_HEADERS, - ...{ - "X-Plex-Client-Identifier": clientIdentifier, - }, + "X-Plex-Client-Identifier": clientIdentifier, }; const pinResponse = await fetch("https://plex.tv/api/v2/pins.json?strong=true", { method: "POST", @@ -75,9 +73,7 @@ export class PlexAPIClient { static async pinStatus(clientIdentifier: string, id: number): Promise { const headers = { ...DEFAULT_HEADERS, - ...{ - "X-Plex-Client-Identifier": clientIdentifier, - }, + "X-Plex-Client-Identifier": clientIdentifier, }; const pinResponse = await fetch(`https://plex.tv/api/v2/pins/${id}`, { headers: headers, diff --git a/web/src/common/helpers/webauthn.ts b/web/src/common/helpers/webauthn.ts index c10edff170..13a9894503 100644 --- a/web/src/common/helpers/webauthn.ts +++ b/web/src/common/helpers/webauthn.ts @@ -38,7 +38,7 @@ export function transformCredentialCreateOptions( // Because json can't contain raw bytes, the server base64-encodes the User ID // So to get the base64 encoded byte array, we first need to convert it to a regular // string, then a byte array, re-encode it and wrap that in an array. - const stringId = decodeURIComponent(escape(window.atob(userId))); + const stringId = decodeURIComponent(window.atob(userId)); user.id = u8arr(b64enc(u8arr(stringId))); const challenge = u8arr(credentialCreateOptions.challenge.toString()); diff --git a/web/src/common/sentry.ts b/web/src/common/sentry.ts index 290b4715f1..0778cbce66 100644 --- a/web/src/common/sentry.ts +++ b/web/src/common/sentry.ts @@ -2,7 +2,14 @@ import { config } from "@goauthentik/common/api/config"; import { VERSION } from "@goauthentik/common/constants"; import { SentryIgnoredError } from "@goauthentik/common/errors"; import { me } from "@goauthentik/common/users"; -import * as Sentry from "@sentry/browser"; +import { + ErrorEvent, + EventHint, + browserTracingIntegration, + init, + setTag, + setUser, +} from "@sentry/browser"; import { CapabilitiesEnum, Config, ResponseError } from "@goauthentik/api"; @@ -12,7 +19,7 @@ export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities"; export async function configureSentry(canDoPpi = false): Promise { const cfg = await config(); if (cfg.errorReporting.enabled) { - Sentry.init({ + init({ dsn: cfg.errorReporting.sentryDsn, ignoreErrors: [ /network/gi, @@ -27,7 +34,7 @@ export async function configureSentry(canDoPpi = false): Promise { ], release: `authentik@${VERSION}`, integrations: [ - new Sentry.BrowserTracing({ + browserTracingIntegration({ shouldCreateSpanForRequest: (url: string) => { return url.startsWith(window.location.host); }, @@ -35,10 +42,10 @@ export async function configureSentry(canDoPpi = false): Promise { ], tracesSampleRate: cfg.errorReporting.tracesSampleRate, environment: cfg.errorReporting.environment, - beforeSend: async ( - event: Sentry.Event, - hint: Sentry.EventHint | undefined, - ): Promise => { + beforeSend: ( + event: ErrorEvent, + hint: EventHint, + ): ErrorEvent | PromiseLike | null => { if (!hint) { return event; } @@ -54,12 +61,9 @@ export async function configureSentry(canDoPpi = false): Promise { return event; }, }); - Sentry.setTag(TAG_SENTRY_CAPABILITIES, cfg.capabilities.join(",")); + setTag(TAG_SENTRY_CAPABILITIES, cfg.capabilities.join(",")); if (window.location.pathname.includes("if/")) { - Sentry.setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface()}`); - Sentry.configureScope((scope) => - scope.setTransactionName(`authentik.web.if.${currentInterface()}`), - ); + setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface()}`); } if (cfg.capabilities.includes(CapabilitiesEnum.CanDebug)) { const Spotlight = await import("@spotlightjs/spotlight"); @@ -68,7 +72,7 @@ export async function configureSentry(canDoPpi = false): Promise { } if (cfg.errorReporting.sendPii && canDoPpi) { me().then((user) => { - Sentry.setUser({ email: user.user.email }); + setUser({ email: user.user.email }); console.debug("authentik/config: Sentry with PII enabled."); }); } else { diff --git a/web/src/common/styles/authentik.css b/web/src/common/styles/authentik.css index 4ccabd8edd..790c4c4e10 100644 --- a/web/src/common/styles/authentik.css +++ b/web/src/common/styles/authentik.css @@ -150,3 +150,7 @@ html > form > input { margin-top: 13rem; } } + +.pf-c-data-list { + padding-inline-start: 0; +} diff --git a/web/src/common/styles/theme-dark.css b/web/src/common/styles/theme-dark.css index 764f66dd09..1841ee6135 100644 --- a/web/src/common/styles/theme-dark.css +++ b/web/src/common/styles/theme-dark.css @@ -187,6 +187,9 @@ input[type="date"]::-webkit-calendar-picker-indicator { .pf-c-select__menu-item.pf-m-focus { --pf-c-select__menu-item--focus--BackgroundColor: var(--ak-dark-background-light-ish); } +.pf-c-button:disabled { + color: var(--ak-dark-background-lighter); +} .pf-c-button.pf-m-plain:hover { color: var(--ak-dark-foreground); } @@ -292,6 +295,7 @@ input[type="date"]::-webkit-calendar-picker-indicator { } /* data list */ .pf-c-data-list { + padding-inline-start: 0; border-top-color: var(--ak-dark-background-lighter); } .pf-c-data-list__item { @@ -328,3 +332,7 @@ input[type="date"]::-webkit-calendar-picker-indicator { .pf-c-tree-view__content:focus-within { --pf-c-tree-view__node--hover--BackgroundColor: var(--ak-dark-background-light-ish); } +/* stepper */ +.pf-c-progress-stepper__step-title { + --pf-c-progress-stepper__step-title--Color: var(--ak-dark-foreground); +} diff --git a/web/src/common/users.ts b/web/src/common/users.ts index 2930475725..29c218a021 100644 --- a/web/src/common/users.ts +++ b/web/src/common/users.ts @@ -18,7 +18,7 @@ export function me(): Promise { if (!user.user.settings || !("locale" in user.user.settings)) { return user; } - const locale = user.user.settings.locale; + const locale: string | undefined = user.user.settings.locale; if (locale && locale !== "") { console.debug( `authentik/locale: Activating user's configured locale '${locale}'`, diff --git a/web/src/common/utils.ts b/web/src/common/utils.ts index 2b88f43ddf..7c5dfff92a 100644 --- a/web/src/common/utils.ts +++ b/web/src/common/utils.ts @@ -25,12 +25,6 @@ export function convertToSlug(text: string): string { .replace(/[^\w-]+/g, ""); } -export function convertToTitle(text: string): string { - return text.replace(/\w\S*/g, function (txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); -} - /** * Truncate a string based on maximum word count */ @@ -84,14 +78,6 @@ export function first(...args: Array): T { throw new SentryIgnoredError(`No compatible arg given: ${args}`); } -export function hexEncode(buf: Uint8Array): string { - return Array.from(buf) - .map(function (x) { - return ("0" + x.toString(16)).substr(-2); - }) - .join(""); -} - // Taken from python's string module export const ascii_lowercase = "abcdefghijklmnopqrstuvwxyz"; export const ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -125,6 +111,21 @@ export function dateTimeLocal(date: Date): string { return `${parts[0]}:${parts[1]}`; } +export function dateToUTC(date: Date): Date { + // Sigh...so our API is UTC/can take TZ info in the ISO format as it should. + // datetime-local fields (which is almost the only date-time input we use) + // can return its value as a UTC timestamp...however the generated API client + // _requires_ a Date object, only to then convert it to an ISO string anyways + // JS Dates don't include timezone info in the ISO string, so that just sends + // the local time as UTC...which is wrong + // Instead we have to do this, convert the given date to a UTC timestamp, + // then subtract the timezone offset to create an "invalid" date (correct time&date) + // but it still "thinks" it's in local TZ + const timestamp = date.getTime(); + const offset = -1 * (new Date().getTimezoneOffset() * 60000); + return new Date(timestamp - offset); +} + // Lit is extremely well-typed with regard to CSS, and Storybook's `build` does not currently have a // coherent way of importing CSS-as-text into CSSStyleSheet. It works well when Storybook is running // in `dev,` but in `build` it fails. Storied components will have to map their textual CSS imports @@ -137,7 +138,7 @@ const isCSSResult = (v: unknown): v is CSSResult => // prettier-ignore export const _adaptCSS = (sheet: AdaptableStylesheet): CSSStyleSheet => - (typeof sheet === "string" ? css([sheet] as unknown as TemplateStringsArray, ...[]).styleSheet + (typeof sheet === "string" ? css([sheet] as unknown as TemplateStringsArray, []).styleSheet : isCSSResult(sheet) ? sheet.styleSheet : sheet) as CSSStyleSheet; @@ -149,3 +150,25 @@ export function adaptCSS(sheet: AdaptableStylesheet[]): CSSStyleSheet[]; export function adaptCSS(sheet: AdaptableStylesheet | AdaptableStylesheet[]): AdaptedStylesheets { return Array.isArray(sheet) ? sheet.map(_adaptCSS) : _adaptCSS(sheet); } + +const _timeUnits = new Map([ + ["year", 24 * 60 * 60 * 1000 * 365], + ["month", (24 * 60 * 60 * 1000 * 365) / 12], + ["day", 24 * 60 * 60 * 1000], + ["hour", 60 * 60 * 1000], + ["minute", 60 * 1000], + ["second", 1000], +]); + +export function getRelativeTime(d1: Date, d2: Date = new Date()): string { + const rtf = new Intl.RelativeTimeFormat("default", { numeric: "auto" }); + const elapsed = d1.getTime() - d2.getTime(); + + // "Math.abs" accounts for both "past" & "future" scenarios + for (const [key, value] of _timeUnits) { + if (Math.abs(elapsed) > value || key == "second") { + return rtf.format(Math.round(elapsed / value), key); + } + } + return rtf.format(Math.round(elapsed / 1000), "second"); +} diff --git a/web/src/components/DescriptionList.ts b/web/src/components/DescriptionList.ts index cfeee4640f..31dfc1416d 100644 --- a/web/src/components/DescriptionList.ts +++ b/web/src/components/DescriptionList.ts @@ -1,3 +1,5 @@ +import { first } from "@goauthentik/common/utils"; + import { TemplateResult, html, nothing } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { map } from "lit/directives/map.js"; @@ -7,10 +9,10 @@ export type DescriptionPair = [string, DescriptionDesc]; export type DescriptionRecord = { term: string; desc: DescriptionDesc }; interface DescriptionConfig { - horizontal: boolean; - compact: boolean; - twocolumn: boolean; - threecolumn: boolean; + horizontal?: boolean; + compact?: boolean; + twocolumn?: boolean; + threecolumn?: boolean; } const isDescriptionRecordCollection = (v: Array): v is DescriptionRecord[] => @@ -78,10 +80,10 @@ export function renderDescriptionList( ) { const checkedTerms = alignTermType(terms); const classes = classMap({ - "pf-m-horizontal": config.horizontal, - "pf-m-compact": config.compact, - "pf-m-2-col-on-lg": config.twocolumn, - "pf-m-3-col-on-lg": config.threecolumn, + "pf-m-horizontal": first(config.horizontal, false), + "pf-m-compact": first(config.compact, false), + "pf-m-2-col-on-lg": first(config.twocolumn, false), + "pf-m-3-col-on-lg": first(config.threecolumn, false), }); return html` diff --git a/web/src/components/ak-app-icon.ts b/web/src/components/ak-app-icon.ts index fcdb9d8930..7237ffc914 100644 --- a/web/src/components/ak-app-icon.ts +++ b/web/src/components/ak-app-icon.ts @@ -1,5 +1,5 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; -import { PFSize } from "@goauthentik/app/elements/Spinner"; +import { PFSize } from "@goauthentik/common/enums.js"; +import { AKElement } from "@goauthentik/elements/Base"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; diff --git a/web/src/components/ak-event-info.ts b/web/src/components/ak-event-info.ts index 7283f1fbbc..af1bcc3045 100644 --- a/web/src/components/ak-event-info.ts +++ b/web/src/components/ak-event-info.ts @@ -1,10 +1,10 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { VERSION } from "@goauthentik/common/constants"; +import { PFSize } from "@goauthentik/common/enums.js"; import { EventContext, EventModel, EventWithContext } from "@goauthentik/common/events"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Expand"; import "@goauthentik/elements/Spinner"; -import { PFSize } from "@goauthentik/elements/Spinner"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; @@ -18,6 +18,7 @@ import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList import PFList from "@patternfly/patternfly/components/List/list.css"; import PFTable from "@patternfly/patternfly/components/Table/table.css"; import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css"; +import PFSplit from "@patternfly/patternfly/layouts/Split/split.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { EventActions, FlowsApi } from "@goauthentik/api"; @@ -81,6 +82,7 @@ export class EventInfo extends AKElement { PFCard, PFTable, PFList, + PFSplit, PFDescriptionList, css` code { @@ -246,11 +248,17 @@ export class EventInfo extends AKElement { renderModelChanged() { const diff = this.event.context.diff as unknown as { - [key: string]: { new_value: unknown; previous_value: unknown }; + [key: string]: { + new_value: unknown; + previous_value: unknown; + add?: unknown[]; + remove?: unknown[]; + clear?: boolean; + }; }; let diffBody = html``; if (diff) { - diffBody = html`
    + diffBody = html`
    ${msg("Changes made:")}
    @@ -262,16 +270,36 @@ export class EventInfo extends AKElement { ${Object.keys(diff).map((key) => { + const value = diff[key]; + const previousCol = value.previous_value + ? JSON.stringify(value.previous_value, null, 4) + : msg("-"); + let newCol = html``; + if (value.add || value.remove) { + newCol = html`
      + ${(value.add || value.remove)?.map((item) => { + let itemLabel = ""; + if (value.add) { + itemLabel = msg(str`Added ID ${item}`); + } else if (value.remove) { + itemLabel = msg(str`Removed ID ${item}`); + } + return html`
    • ${itemLabel}
    • `; + })} +
    `; + } else if (value.clear) { + newCol = html`${msg("Cleared")}`; + } else { + newCol = html`
    +${JSON.stringify(value.new_value, null, 4)}
    `; + } return html` - + `; })} @@ -280,8 +308,8 @@ ${JSON.stringify(diff[key].previous_value, null, 4)}`; } return html` -
    -
    +
    +
    ${msg("Affected model:")}
    ${this.getModelInfo(this.event.context?.model as EventModel)} diff --git a/web/src/components/ak-hint/ak-hint-actions.ts b/web/src/components/ak-hint/ak-hint-actions.ts index 8af341965b..eaf33b2f8e 100644 --- a/web/src/components/ak-hint/ak-hint-actions.ts +++ b/web/src/components/ak-hint/ak-hint-actions.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import { css, html } from "lit"; import { customElement } from "lit/decorators.js"; diff --git a/web/src/components/ak-hint/ak-hint-body.ts b/web/src/components/ak-hint/ak-hint-body.ts index f5c122eb50..4261c0a302 100644 --- a/web/src/components/ak-hint/ak-hint-body.ts +++ b/web/src/components/ak-hint/ak-hint-body.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import { css, html } from "lit"; import { customElement } from "lit/decorators.js"; diff --git a/web/src/components/ak-hint/ak-hint-footer.ts b/web/src/components/ak-hint/ak-hint-footer.ts index a08197d114..14461a814e 100644 --- a/web/src/components/ak-hint/ak-hint-footer.ts +++ b/web/src/components/ak-hint/ak-hint-footer.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import { css, html } from "lit"; import { customElement } from "lit/decorators.js"; diff --git a/web/src/components/ak-hint/ak-hint-title.ts b/web/src/components/ak-hint/ak-hint-title.ts index accc881d0a..abcb9d596c 100644 --- a/web/src/components/ak-hint/ak-hint-title.ts +++ b/web/src/components/ak-hint/ak-hint-title.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import { css, html } from "lit"; import { customElement } from "lit/decorators.js"; diff --git a/web/src/components/ak-hint/ak-hint.ts b/web/src/components/ak-hint/ak-hint.ts index 731dbe0ca0..b818fae20d 100644 --- a/web/src/components/ak-hint/ak-hint.ts +++ b/web/src/components/ak-hint/ak-hint.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import { css, html } from "lit"; import { customElement } from "lit/decorators.js"; diff --git a/web/src/components/ak-multi-select.ts b/web/src/components/ak-multi-select.ts index 9efddd079e..c7b9601a33 100644 --- a/web/src/components/ak-multi-select.ts +++ b/web/src/components/ak-multi-select.ts @@ -1,5 +1,5 @@ -import "@goauthentik/app/elements/forms/HorizontalFormElement"; import { AKElement } from "@goauthentik/elements/Base"; +import "@goauthentik/elements/forms/HorizontalFormElement"; import { TemplateResult, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; diff --git a/web/src/components/ak-wizard-main/AkWizard.ts b/web/src/components/ak-wizard-main/AkWizard.ts index 48e827c70b..a393020b17 100644 --- a/web/src/components/ak-wizard-main/AkWizard.ts +++ b/web/src/components/ak-wizard-main/AkWizard.ts @@ -1,4 +1,4 @@ -import "@goauthentik/app/components/ak-wizard-main/ak-wizard-frame"; +import "@goauthentik/components/ak-wizard-main/ak-wizard-frame"; import { AKElement } from "@goauthentik/elements/Base"; import { msg } from "@lit/localize"; diff --git a/web/src/components/ak-wizard-main/ak-wizard-frame.ts b/web/src/components/ak-wizard-main/ak-wizard-frame.ts index 01a37af28e..3ec746fed5 100644 --- a/web/src/components/ak-wizard-main/ak-wizard-frame.ts +++ b/web/src/components/ak-wizard-main/ak-wizard-frame.ts @@ -3,7 +3,7 @@ import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; import { msg } from "@lit/localize"; import { customElement, property, query } from "@lit/reactive-element/decorators.js"; -import { TemplateResult, html, nothing } from "lit"; +import { TemplateResult, css, html, nothing } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { map } from "lit/directives/map.js"; @@ -31,7 +31,15 @@ import { type WizardButton, WizardStepLabel } from "./types"; @customElement("ak-wizard-frame") export class AkWizardFrame extends CustomEmitterElement(ModalButton) { static get styles() { - return [...super.styles, PFWizard]; + return [ + ...super.styles, + PFWizard, + css` + .pf-c-modal-box { + height: 75%; + } + `, + ]; } /** @@ -84,7 +92,7 @@ export class AkWizardFrame extends CustomEmitterElement(ModalButton) { ${this.renderHeader()}
    - ${this.renderNavigation()} + ${this.renderNavigation()} ${this.renderMainSection()}
    ${this.renderFooter()} diff --git a/web/src/components/events/ObjectChangelog.ts b/web/src/components/events/ObjectChangelog.ts index 9901b1b1e1..1e2fb80812 100644 --- a/web/src/components/events/ObjectChangelog.ts +++ b/web/src/components/events/ObjectChangelog.ts @@ -1,8 +1,9 @@ -import { EventGeo, EventUser } from "@goauthentik/app/admin/events/utils"; -import { actionToLabel } from "@goauthentik/app/common/labels"; +import { EventGeo, EventUser } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; +import { actionToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-event-info"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/Dropdown"; @@ -12,7 +13,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { msg } from "@lit/localize"; -import { TemplateResult, html } from "lit"; +import { PropertyValues, TemplateResult, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { Event, EventsApi } from "@goauthentik/api"; @@ -30,27 +31,18 @@ export class ObjectChangelog extends Table { @property() targetModelApp?: string; - private _targetModelName = ""; - @property() - set targetModelName(value: string) { - this._targetModelName = value; - this.fetch(); - } - - get targetModelName(): string { - return this._targetModelName; - } + targetModelName = ""; async apiEndpoint(page: number): Promise> { - let modelName = this._targetModelName; + let modelName = this.targetModelName; let appName = this.targetModelApp; - if (this._targetModelName.indexOf(".") !== -1) { - const parts = this._targetModelName.split("."); + if (this.targetModelName.indexOf(".") !== -1) { + const parts = this.targetModelName.split(".", 1); appName = parts[0]; modelName = parts[1]; } - if (this._targetModelName === "") { + if (this.targetModelName === "") { return Promise.reject(); } return new EventsApi(DEFAULT_CONFIG).eventsEventsList({ @@ -73,11 +65,18 @@ export class ObjectChangelog extends Table { ]; } + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("targetModelName") && this.targetModelName) { + this.fetch(); + } + } + row(item: EventWithContext): TemplateResult[] { return [ html`${actionToLabel(item.action)}`, EventUser(item), - html`${item.created?.toLocaleString()}`, + html`
    ${getRelativeTime(item.created)}
    + ${item.created.toLocaleString()}`, html`
    ${item.clientIp || msg("-")}
    ${EventGeo(item)}`, diff --git a/web/src/components/events/UserEvents.ts b/web/src/components/events/UserEvents.ts index c753d48fcb..55fdb867d7 100644 --- a/web/src/components/events/UserEvents.ts +++ b/web/src/components/events/UserEvents.ts @@ -1,8 +1,9 @@ -import { EventUser } from "@goauthentik/app/admin/events/utils"; +import { EventUser } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; import { actionToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-event-info"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/Dropdown"; @@ -48,7 +49,8 @@ export class UserEvents extends Table { return [ html`${actionToLabel(item.action)}`, EventUser(item), - html`${item.created?.toLocaleString()}`, + html`
    ${getRelativeTime(item.created)}
    + ${item.created.toLocaleString()}`, html`${item.clientIp || msg("-")}`, ]; } diff --git a/web/src/components/stories/ak-search-select.stories.ts b/web/src/components/stories/ak-search-select.stories.ts index 0f0e5edc2b..a2bd77f378 100644 --- a/web/src/components/stories/ak-search-select.stories.ts +++ b/web/src/components/stories/ak-search-select.stories.ts @@ -1,4 +1,4 @@ -import { groupBy } from "@goauthentik/app/common/utils"; +import { groupBy } from "@goauthentik/common/utils"; import { convertToSlug as slugify } from "@goauthentik/common/utils.js"; import "@goauthentik/elements/forms/SearchSelect/ak-search-select"; import { SearchSelect } from "@goauthentik/elements/forms/SearchSelect/ak-search-select"; diff --git a/web/src/elements/Alert.ts b/web/src/elements/Alert.ts index e75d2c3936..139c504203 100644 --- a/web/src/elements/Alert.ts +++ b/web/src/elements/Alert.ts @@ -17,6 +17,8 @@ export enum Level { export class Alert extends AKElement { @property({ type: Boolean }) inline = false; + @property({ type: Boolean }) + plain = false; @property() level: Level = Level.Warning; @@ -26,7 +28,11 @@ export class Alert extends AKElement { } render(): TemplateResult { - return html`
    + return html`
    diff --git a/web/src/elements/AuthentikContexts.ts b/web/src/elements/AuthentikContexts.ts index 3a0f1dd1b8..df38f6fcf5 100644 --- a/web/src/elements/AuthentikContexts.ts +++ b/web/src/elements/AuthentikContexts.ts @@ -1,9 +1,15 @@ -import { createContext } from "@lit-labs/context"; +import { createContext } from "@lit/context"; -import type { Config, CurrentBrand } from "@goauthentik/api"; +import type { Config, CurrentBrand, LicenseSummary, SessionUser } from "@goauthentik/api"; export const authentikConfigContext = createContext(Symbol("authentik-config-context")); +export const authentikUserContext = createContext(Symbol("authentik-user-context")); + +export const authentikEnterpriseContext = createContext( + Symbol("authentik-enterprise-context"), +); + export const authentikBrandContext = createContext(Symbol("authentik-brand-context")); export default authentikConfigContext; diff --git a/web/src/elements/Base.ts b/web/src/elements/Base.ts index 3e251ce124..5bef84b12d 100644 --- a/web/src/elements/Base.ts +++ b/web/src/elements/Base.ts @@ -4,15 +4,13 @@ import { adaptCSS } from "@goauthentik/common/utils"; import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet"; import { localized } from "@lit/localize"; -import { LitElement } from "lit"; +import { LitElement, ReactiveElement } from "lit"; import AKGlobal from "@goauthentik/common/styles/authentik.css"; import ThemeDark from "@goauthentik/common/styles/theme-dark.css"; import { Config, CurrentBrand, UiThemeEnum } from "@goauthentik/api"; -import { AdoptedStyleSheetsElement } from "./types"; - type AkInterface = HTMLElement & { getTheme: () => Promise; brand?: CurrentBrand; @@ -59,18 +57,22 @@ export class AKElement extends LitElement { super(); } - protected createRenderRoot(): ShadowRoot | Element { - const root = super.createRenderRoot() as ShadowRoot; - let styleRoot: AdoptedStyleSheetsElement = root; - if ("ShadyDOM" in window) { - styleRoot = document; - } + setInitialStyles(root: DocumentOrShadowRoot) { + const styleRoot: DocumentOrShadowRoot = ( + "ShadyDOM" in window ? document : root + ) as DocumentOrShadowRoot; styleRoot.adoptedStyleSheets = adaptCSS([ ...styleRoot.adoptedStyleSheets, ensureCSSStyleSheet(AKGlobal), ]); this._initTheme(styleRoot); this._initCustomCSS(styleRoot); + } + + protected createRenderRoot() { + this.fixElementStyles(); + const root = super.createRenderRoot(); + this.setInitialStyles(root as unknown as DocumentOrShadowRoot); return root; } @@ -78,7 +80,14 @@ export class AKElement extends LitElement { return rootInterface()?.getTheme() || UiThemeEnum.Automatic; } - async _initTheme(root: AdoptedStyleSheetsElement): Promise { + fixElementStyles() { + // Ensure all style sheets being passed are really style sheets. + (this.constructor as typeof ReactiveElement).elementStyles = ( + this.constructor as typeof ReactiveElement + ).elementStyles.map(ensureCSSStyleSheet); + } + + async _initTheme(root: DocumentOrShadowRoot): Promise { // Early activate theme based on media query to prevent light flash // when dark is preferred this._activateTheme( @@ -90,7 +99,7 @@ export class AKElement extends LitElement { this._applyTheme(root, await this.getTheme()); } - private async _initCustomCSS(root: AdoptedStyleSheetsElement): Promise { + private async _initCustomCSS(root: DocumentOrShadowRoot): Promise { const sheets = await fetchCustomCSS(); sheets.map((css) => { if (css === "") { @@ -102,7 +111,7 @@ export class AKElement extends LitElement { }); } - _applyTheme(root: AdoptedStyleSheetsElement, theme?: UiThemeEnum): void { + _applyTheme(root: DocumentOrShadowRoot, theme?: UiThemeEnum): void { if (!theme) { theme = UiThemeEnum.Automatic; } @@ -137,7 +146,7 @@ export class AKElement extends LitElement { return undefined; } - _activateTheme(root: AdoptedStyleSheetsElement, theme: UiThemeEnum) { + _activateTheme(root: DocumentOrShadowRoot, theme: UiThemeEnum) { if (theme === this._activeTheme) { return; } diff --git a/web/src/elements/EmptyState.ts b/web/src/elements/EmptyState.ts index f419d4e2fe..8842badea2 100644 --- a/web/src/elements/EmptyState.ts +++ b/web/src/elements/EmptyState.ts @@ -1,7 +1,8 @@ +import { PFSize } from "@goauthentik/common/enums.js"; import { AKElement } from "@goauthentik/elements/Base"; -import { PFSize } from "@goauthentik/elements/Spinner"; +import "@goauthentik/elements/Spinner"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css"; @@ -23,7 +24,17 @@ export class EmptyState extends AKElement { header = ""; static get styles(): CSSResult[] { - return [PFBase, PFEmptyState, PFTitle]; + return [ + PFBase, + PFEmptyState, + PFTitle, + css` + i.pf-c-empty-state__icon { + height: var(--pf-global--icon--FontSize--2xl); + line-height: var(--pf-global--icon--FontSize--2xl); + } + `, + ]; } render(): TemplateResult { diff --git a/web/src/elements/Interface/BrandContextController.ts b/web/src/elements/Interface/BrandContextController.ts new file mode 100644 index 0000000000..ac3106ed58 --- /dev/null +++ b/web/src/elements/Interface/BrandContextController.ts @@ -0,0 +1,51 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { authentikBrandContext } from "@goauthentik/elements/AuthentikContexts"; +import type { ReactiveElementHost } from "@goauthentik/elements/types.js"; + +import { ContextProvider } from "@lit/context"; +import type { ReactiveController } from "lit"; + +import type { CurrentBrand } from "@goauthentik/api"; +import { CoreApi } from "@goauthentik/api"; + +import type { AkInterface } from "./Interface"; + +export class BrandContextController implements ReactiveController { + host!: ReactiveElementHost; + + context!: ContextProvider<{ __context__: CurrentBrand | undefined }>; + + constructor(host: ReactiveElementHost) { + this.host = host; + this.context = new ContextProvider(this.host, { + context: authentikBrandContext, + initialValue: undefined, + }); + this.fetch = this.fetch.bind(this); + this.fetch(); + } + + fetch() { + new CoreApi(DEFAULT_CONFIG).coreBrandsCurrentRetrieve().then((brand) => { + this.context.setValue(brand); + this.host.brand = brand; + }); + } + + hostConnected() { + window.addEventListener(EVENT_REFRESH, this.fetch); + } + + hostDisconnected() { + window.removeEventListener(EVENT_REFRESH, this.fetch); + } + + hostUpdate() { + // If the Interface changes its brand information for some reason, + // we should notify all users of the context of that change. doesn't + if (this.host.brand !== this.context.value) { + this.context.setValue(this.host.brand); + } + } +} diff --git a/web/src/elements/Interface/ConfigContextController.ts b/web/src/elements/Interface/ConfigContextController.ts new file mode 100644 index 0000000000..c626a7a9c9 --- /dev/null +++ b/web/src/elements/Interface/ConfigContextController.ts @@ -0,0 +1,56 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { globalAK } from "@goauthentik/common/global"; +import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts"; +import type { ReactiveElementHost } from "@goauthentik/elements/types.js"; + +import { ContextProvider } from "@lit/context"; +import type { ReactiveController } from "lit"; + +import type { Config } from "@goauthentik/api"; +import { RootApi } from "@goauthentik/api"; + +import type { AkInterface } from "./Interface"; + +export class ConfigContextController implements ReactiveController { + host!: ReactiveElementHost; + + context!: ContextProvider<{ __context__: Config | undefined }>; + + constructor(host: ReactiveElementHost) { + this.host = host; + this.context = new ContextProvider(this.host, { + context: authentikConfigContext, + initialValue: undefined, + }); + // Pre-hydrate from template-embedded config + this.context.setValue(globalAK().config); + this.host.config = globalAK().config; + this.fetch = this.fetch.bind(this); + this.fetch(); + } + + fetch() { + new RootApi(DEFAULT_CONFIG).rootConfigRetrieve().then((config) => { + this.context.setValue(config); + this.host.config = config; + }); + } + + hostConnected() { + window.addEventListener(EVENT_REFRESH, this.fetch); + } + + hostDisconnected() { + window.removeEventListener(EVENT_REFRESH, this.fetch); + } + + hostUpdate() { + // If the Interface changes its config information, we should notify all + // users of the context of that change, without creating an infinite + // loop of resets. + if (this.host.config !== this.context.value) { + this.context.setValue(this.host.config); + } + } +} diff --git a/web/src/elements/Interface/EnterpriseContextController.ts b/web/src/elements/Interface/EnterpriseContextController.ts new file mode 100644 index 0000000000..f0cc1ac2a8 --- /dev/null +++ b/web/src/elements/Interface/EnterpriseContextController.ts @@ -0,0 +1,52 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants"; +import { authentikEnterpriseContext } from "@goauthentik/elements/AuthentikContexts"; +import type { ReactiveElementHost } from "@goauthentik/elements/types.js"; + +import { ContextProvider } from "@lit/context"; +import type { ReactiveController } from "lit"; + +import type { LicenseSummary } from "@goauthentik/api"; +import { EnterpriseApi } from "@goauthentik/api"; + +import type { AkEnterpriseInterface } from "./Interface"; + +export class EnterpriseContextController implements ReactiveController { + host!: ReactiveElementHost; + + context!: ContextProvider<{ __context__: LicenseSummary | undefined }>; + + constructor(host: ReactiveElementHost) { + this.host = host; + this.context = new ContextProvider(this.host, { + context: authentikEnterpriseContext, + initialValue: undefined, + }); + this.fetch = this.fetch.bind(this); + this.fetch(); + } + + fetch() { + new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve().then((enterprise) => { + this.context.setValue(enterprise); + this.host.licenseSummary = enterprise; + }); + } + + hostConnected() { + window.addEventListener(EVENT_REFRESH_ENTERPRISE, this.fetch); + } + + hostDisconnected() { + window.removeEventListener(EVENT_REFRESH_ENTERPRISE, this.fetch); + } + + hostUpdate() { + // If the Interface changes its config information, we should notify all + // users of the context of that change, without creating an infinite + // loop of resets. + if (this.host.licenseSummary !== this.context.value) { + this.context.setValue(this.host.licenseSummary); + } + } +} diff --git a/web/src/elements/Interface/Interface.ts b/web/src/elements/Interface/Interface.ts index ed4e57c9ae..8bedbe16e7 100644 --- a/web/src/elements/Interface/Interface.ts +++ b/web/src/elements/Interface/Interface.ts @@ -1,79 +1,58 @@ -import { brand, config } from "@goauthentik/common/api/config"; import { UIConfig, uiConfig } from "@goauthentik/common/ui/config"; -import { - authentikBrandContext, - authentikConfigContext, -} from "@goauthentik/elements/AuthentikContexts"; -import type { AdoptedStyleSheetsElement } from "@goauthentik/elements/types"; +import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js"; import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet"; -import { ContextProvider } from "@lit-labs/context"; import { state } from "lit/decorators.js"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import { Config, CurrentBrand, UiThemeEnum } from "@goauthentik/api"; +import type { Config, CurrentBrand, LicenseSummary } from "@goauthentik/api"; +import { UiThemeEnum } from "@goauthentik/api"; import { AKElement } from "../Base"; +import { BrandContextController } from "./BrandContextController"; +import { ConfigContextController } from "./ConfigContextController"; +import { EnterpriseContextController } from "./EnterpriseContextController"; -type AkInterface = HTMLElement & { +export type AkInterface = HTMLElement & { getTheme: () => Promise; brand?: CurrentBrand; uiConfig?: UIConfig; config?: Config; }; +const brandContext = Symbol("brandContext"); +const configContext = Symbol("configContext"); +const modalController = Symbol("modalController"); + export class Interface extends AKElement implements AkInterface { @state() uiConfig?: UIConfig; - _configContext = new ContextProvider(this, { - context: authentikConfigContext, - initialValue: undefined, - }); + [brandContext]!: BrandContextController; - _config?: Config; + [configContext]!: ConfigContextController; + + [modalController]!: ModalOrchestrationController; @state() - set config(c: Config) { - this._config = c; - this._configContext.setValue(c); - this.requestUpdate(); - } - - get config(): Config | undefined { - return this._config; - } - - _brandContext = new ContextProvider(this, { - context: authentikBrandContext, - initialValue: undefined, - }); - - _brand?: CurrentBrand; + config?: Config; @state() - set brand(c: CurrentBrand) { - this._brand = c; - this._brandContext.setValue(c); - this.requestUpdate(); - } - - get brand(): CurrentBrand | undefined { - return this._brand; - } + brand?: CurrentBrand; constructor() { super(); document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)]; - brand().then((brand) => (this.brand = brand)); - config().then((config) => (this.config = config)); + this[brandContext] = new BrandContextController(this); + this[configContext] = new ConfigContextController(this); + this[modalController] = new ModalOrchestrationController(this); this.dataset.akInterfaceRoot = "true"; } - _activateTheme(root: AdoptedStyleSheetsElement, theme: UiThemeEnum): void { + _activateTheme(root: DocumentOrShadowRoot, theme: UiThemeEnum): void { super._activateTheme(root, theme); - super._activateTheme(document, theme); + super._activateTheme(document as unknown as DocumentOrShadowRoot, theme); } async getTheme(): Promise { @@ -83,3 +62,21 @@ export class Interface extends AKElement implements AkInterface { return this.uiConfig.theme?.base || UiThemeEnum.Automatic; } } + +export type AkEnterpriseInterface = AkInterface & { + licenseSummary?: LicenseSummary; +}; + +const enterpriseContext = Symbol("enterpriseContext"); + +export class EnterpriseAwareInterface extends Interface { + [enterpriseContext]!: EnterpriseContextController; + + @state() + licenseSummary?: LicenseSummary; + + constructor() { + super(); + this[enterpriseContext] = new EnterpriseContextController(this); + } +} diff --git a/web/src/elements/Interface/authentikConfigProvider.ts b/web/src/elements/Interface/authentikConfigProvider.ts index 5b2027fd0c..79f1c960bb 100644 --- a/web/src/elements/Interface/authentikConfigProvider.ts +++ b/web/src/elements/Interface/authentikConfigProvider.ts @@ -1,13 +1,11 @@ import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts"; +import type { Constructor } from "@goauthentik/elements/types.js"; -import { consume } from "@lit-labs/context"; +import { consume } from "@lit/context"; import type { LitElement } from "lit"; import type { Config } from "@goauthentik/api"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Constructor = new (...args: any[]) => T; - export function WithAuthentikConfig>( superclass: T, subscribe = true, diff --git a/web/src/elements/Interface/brandProvider.ts b/web/src/elements/Interface/brandProvider.ts index 242764bf78..912466d963 100644 --- a/web/src/elements/Interface/brandProvider.ts +++ b/web/src/elements/Interface/brandProvider.ts @@ -1,14 +1,12 @@ import { authentikBrandContext } from "@goauthentik/elements/AuthentikContexts"; +import type { AbstractConstructor } from "@goauthentik/elements/types.js"; -import { consume } from "@lit-labs/context"; +import { consume } from "@lit/context"; import type { LitElement } from "lit"; import type { CurrentBrand } from "@goauthentik/api"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Constructor = abstract new (...args: any[]) => T; - -export function WithBrandConfig>( +export function WithBrandConfig>( superclass: T, subscribe = true, ) { diff --git a/web/src/elements/Interface/capabilitiesProvider.ts b/web/src/elements/Interface/capabilitiesProvider.ts index 4026538803..c8841d880b 100644 --- a/web/src/elements/Interface/capabilitiesProvider.ts +++ b/web/src/elements/Interface/capabilitiesProvider.ts @@ -1,14 +1,12 @@ import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts"; +import type { AbstractConstructor } from "@goauthentik/elements/types.js"; -import { consume } from "@lit-labs/context"; +import { consume } from "@lit/context"; import type { LitElement } from "lit"; import { CapabilitiesEnum } from "@goauthentik/api"; import { Config } from "@goauthentik/api"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Constructor = abstract new (...args: any[]) => T; - // Using a unique, lexically scoped, and locally static symbol as the field name for the context // means that it's inaccessible to any child class looking for it. It's one of the strongest privacy // guarantees in JavaScript. @@ -45,7 +43,7 @@ class WCC { * */ -export function WithCapabilitiesConfig>( +export function WithCapabilitiesConfig>( superclass: T, subscribe = true, ) { diff --git a/web/src/elements/Interface/index.ts b/web/src/elements/Interface/index.ts index e7d946cf62..df771286eb 100644 --- a/web/src/elements/Interface/index.ts +++ b/web/src/elements/Interface/index.ts @@ -1,4 +1,4 @@ -import { Interface } from "./Interface"; +import { EnterpriseAwareInterface, Interface } from "./Interface"; -export { Interface }; +export { Interface, EnterpriseAwareInterface }; export default Interface; diff --git a/web/src/elements/Interface/licenseSummaryProvider.ts b/web/src/elements/Interface/licenseSummaryProvider.ts new file mode 100644 index 0000000000..4a73ffab6d --- /dev/null +++ b/web/src/elements/Interface/licenseSummaryProvider.ts @@ -0,0 +1,23 @@ +import { authentikEnterpriseContext } from "@goauthentik/elements/AuthentikContexts"; +import { Constructor } from "@goauthentik/elements/types.js"; + +import { consume } from "@lit/context"; +import type { LitElement } from "lit"; + +import type { LicenseSummary } from "@goauthentik/api"; + +export function WithLicenseSummary>( + superclass: T, + subscribe = true, +) { + abstract class WithEnterpriseProvider extends superclass { + @consume({ context: authentikEnterpriseContext, subscribe }) + public licenseSummary!: LicenseSummary; + + get hasEnterpriseLicense() { + return this.licenseSummary?.hasLicense; + } + } + + return WithEnterpriseProvider; +} diff --git a/web/src/elements/Markdown.ts b/web/src/elements/Markdown.ts index 4ee60b9c41..896acfa861 100644 --- a/web/src/elements/Markdown.ts +++ b/web/src/elements/Markdown.ts @@ -2,8 +2,10 @@ import { docLink } from "@goauthentik/common/global"; import "@goauthentik/elements/Alert"; import { Level } from "@goauthentik/elements/Alert"; import { AKElement } from "@goauthentik/elements/Base"; +import { matter } from "md-front-matter"; +import * as showdown from "showdown"; -import { CSSResult, TemplateResult, css, html } from "lit"; +import { CSSResult, PropertyValues, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; @@ -11,22 +13,28 @@ import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFList from "@patternfly/patternfly/components/List/list.css"; export interface MarkdownDocument { - html: string; - metadata: { [key: string]: string }; - filename: string; path: string; } export type Replacer = (input: string, md: MarkdownDocument) => string; +const isRelativeLink = /href="(\.[^"]*)"/gm; +const isFile = /[^/]+\.md/; + @customElement("ak-markdown") export class Markdown extends AKElement { - @property({ attribute: false }) - md?: MarkdownDocument; + @property() + md: string = ""; + + @property() + meta: string = ""; @property({ attribute: false }) replacers: Replacer[] = []; + docHtml = ""; + docTitle = ""; + defaultReplacers: Replacer[] = [ this.replaceAdmonitions, this.replaceList, @@ -45,8 +53,10 @@ export class Markdown extends AKElement { ]; } + converter = new showdown.Converter({ metadata: true, tables: true }); + replaceAdmonitions(input: string): string { - const admonitionStart = /:::(\w+)/gm; + const admonitionStart = /:::(\w+)(|\s*$)/gm; const admonitionEnd = /:::/gm; return ( input @@ -62,31 +72,35 @@ export class Markdown extends AKElement { } replaceRelativeLinks(input: string, md: MarkdownDocument): string { - const relativeLink = /href=".(.*)"/gm; - const cwd = process.env.CWD as string; - // cwd will point to $root/web, but the docs are in $root/website/docs - let relPath = md.path.replace(cwd + "site", ""); - if (md.filename === "index.md") { - relPath = relPath.replace("index.md", ""); - } - const baseURL = docLink(""); - const fullURL = `${baseURL}${relPath}.$1`; - return input.replace(relativeLink, `href="${fullURL}" target="_blank"`); + const baseName = md.path.replace(isFile, ""); + const baseUrl = docLink(""); + return input.replace(isRelativeLink, (_match, path) => { + const pathName = path.replace(".md", ""); + const link = `docs/${baseName}${pathName}`; + const url = new URL(link, baseUrl).toString(); + return `href="${url}" _target="blank"`; + }); } - render(): TemplateResult { - if (!this.md) { - return html``; + willUpdate(properties: PropertyValues) { + if (properties.has("md") || properties.has("meta")) { + const parsedContent = matter(this.md); + const parsedHTML = this.converter.makeHtml(parsedContent.content); + const replacers = [...this.defaultReplacers, ...this.replacers]; + this.docTitle = parsedContent?.data?.title ?? ""; + this.docHtml = replacers.reduce( + (html, replacer) => replacer(html, { path: this.meta }), + parsedHTML, + ); } - let finalHTML = this.md.html; - const replacers = [...this.defaultReplacers, ...this.replacers]; - replacers.forEach((r) => { - if (!this.md) { - return; - } - finalHTML = r(finalHTML, this.md); - }); - return html`${this.md?.metadata.title ? html`

    ${this.md.metadata.title}

    ` : html``} - ${unsafeHTML(finalHTML)}`; + } + + render() { + if (!this.md) { + return nothing; + } + + return html`${this.docTitle ? html`

    ${this.docTitle}

    ` : nothing} + ${unsafeHTML(this.docHtml)}`; } } diff --git a/web/src/elements/PageHeader.ts b/web/src/elements/PageHeader.ts index d7d7df9f0e..34ddd511b7 100644 --- a/web/src/elements/PageHeader.ts +++ b/web/src/elements/PageHeader.ts @@ -14,7 +14,7 @@ import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; +import { customElement, property } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; @@ -35,29 +35,11 @@ export class PageHeader extends WithBrandConfig(AKElement) { hasNotifications = false; @property() - set header(value: string) { - const currentIf = currentInterface(); - let title = this.brand?.brandingTitle || TITLE_DEFAULT; - if (currentIf === "admin") { - title = `${msg("Admin")} - ${title}`; - } - if (value !== "") { - title = `${value} - ${title}`; - } - document.title = title; - this._header = value; - } - - get header(): string { - return this._header; - } + header = ""; @property() description?: string; - @state() - _header = ""; - static get styles(): CSSResult[] { return [ PFBase, @@ -125,6 +107,25 @@ export class PageHeader extends WithBrandConfig(AKElement) { }); } + setTitle(header?: string) { + const currentIf = currentInterface(); + let title = this.brand?.brandingTitle || TITLE_DEFAULT; + if (currentIf === "admin") { + title = `${msg("Admin")} - ${title}`; + } + // Prepend the header to the title + if (header !== undefined && header !== "") { + title = `${header} - ${title}`; + } + document.title = title; + } + + willUpdate() { + // Always update title, even if there's no header value set, + // as in that case we still need to return to the generic title + this.setTitle(this.header); + } + renderIcon(): TemplateResult { if (this.icon) { if (this.iconImage && !this.icon.startsWith("fa://")) { diff --git a/web/src/elements/Spinner.ts b/web/src/elements/Spinner.ts index 7483aff276..afdbbd527a 100644 --- a/web/src/elements/Spinner.ts +++ b/web/src/elements/Spinner.ts @@ -1,3 +1,4 @@ +import { PFSize } from "@goauthentik/common/enums.js"; import { AKElement } from "@goauthentik/elements/Base"; import { msg } from "@lit/localize"; @@ -6,13 +7,6 @@ import { customElement, property } from "lit/decorators.js"; import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css"; -export enum PFSize { - Small = "pf-m-sm", - Medium = "pf-m-md", - Large = "pf-m-lg", - XLarge = "pf-m-xl", -} - @customElement("ak-spinner") export class Spinner extends AKElement { @property() diff --git a/web/src/elements/SyncStatusCard.ts b/web/src/elements/SyncStatusCard.ts new file mode 100644 index 0000000000..9009322027 --- /dev/null +++ b/web/src/elements/SyncStatusCard.ts @@ -0,0 +1,119 @@ +import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { getRelativeTime } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-status-label"; +import { AKElement } from "@goauthentik/elements/Base"; +import "@goauthentik/elements/EmptyState"; +import "@goauthentik/elements/events/LogViewer"; + +import { msg, str } from "@lit/localize"; +import { CSSResult, TemplateResult, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; + +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { SyncStatus, SystemTask, SystemTaskStatusEnum } from "@goauthentik/api"; + +@customElement("ak-sync-status-card") +export class SyncStatusCard extends AKElement { + @state() + syncState?: SyncStatus; + + @state() + loading = false; + + @property({ attribute: false }) + fetch!: () => Promise; + + @property({ attribute: false }) + triggerSync!: () => Promise; + + static get styles(): CSSResult[] { + return [PFBase, PFCard]; + } + + firstUpdated() { + this.loading = true; + this.fetch().then((status) => { + this.syncState = status; + this.loading = false; + }); + } + + renderSyncTask(task: SystemTask): TemplateResult { + return html`
  • + ${(this.syncState?.tasks || []).length > 1 ? html`${task.name}` : nothing} + + ${msg( + str`Finished ${getRelativeTime(task.finishTimestamp)} (${task.finishTimestamp.toLocaleString()})`, + )} + +
  • `; + } + + renderSyncStatus(): TemplateResult { + if (this.loading) { + return html``; + } + if (!this.syncState) { + return html`${msg("No sync status.")}`; + } + if (this.syncState.isRunning) { + return html`${msg("Sync currently running.")}`; + } + if (this.syncState.tasks.length < 1) { + return html`${msg("Not synced yet.")}`; + } + return html` +
      + ${this.syncState.tasks.map((task) => { + return this.renderSyncTask(task); + })} +
    + `; + } + + render(): TemplateResult { + return html`
    +
    ${msg("Sync status")}
    +
    ${this.renderSyncStatus()}
    + +
    `; + } +} diff --git a/web/src/elements/TreeView.ts b/web/src/elements/TreeView.ts index 115a1045ad..408a1bd131 100644 --- a/web/src/elements/TreeView.ts +++ b/web/src/elements/TreeView.ts @@ -50,7 +50,7 @@ export class TreeViewNode extends AKElement { return pathItems.reverse().join(this.separator); } - protected createRenderRoot(): Element { + protected createRenderRoot() { return this; } @@ -171,8 +171,7 @@ export class TreeView extends AKElement { } return item; } else { - const child = this.createNode(path, parentItem.childItems[idx], level + 1); - return child; + return this.createNode(path, parentItem.childItems[idx], level + 1); } } diff --git a/web/src/elements/ak-checkbox-group/ak-checkbox-group.stories.ts b/web/src/elements/ak-checkbox-group/ak-checkbox-group.stories.ts new file mode 100644 index 0000000000..11ec69e094 --- /dev/null +++ b/web/src/elements/ak-checkbox-group/ak-checkbox-group.stories.ts @@ -0,0 +1,112 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta } from "@storybook/web-components"; + +import { TemplateResult, html } from "lit"; + +import "./ak-checkbox-group"; +import { CheckboxGroup as AkCheckboxGroup } from "./ak-checkbox-group"; + +const metadata: Meta = { + title: "Elements / Checkbox Group", + component: "ak-checkbox-group", + parameters: { + docs: { + description: { + component: "A stylized value control for check buttons", + }, + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
    + + + ${testItem} + +
      +
      `; + +const testOptions = [ + { label: "Option One: funky", name: "funky" }, + { label: "Option Two: invalid", name: "invalid" }, + { label: "Option Three: weird", name: "weird" }, +]; + +export const CheckboxGroup = () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const displayChange = (ev: any) => { + document.getElementById("check-message-pad")!.innerHTML = ` +

      Values selected on target: ${ev.target.value.join(", ")}

      +

      Values sent in event: ${ev.detail.join(", ")}

      +

      Values present as data-ak-control: ${JSON.stringify(ev.target.json, null)}

      `; + }; + + return container( + html`

      + Evented example. Intercept the input event and display the value seen in + the event target. +

      + + `, + ); +}; + +type FDType = [string, string | FormDataEntryValue]; + +export const FormCheckboxGroup = () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const displayChange = (ev: any) => { + ev.preventDefault(); + const formData = new FormData(ev.target); + + const valList = Array.from(formData) + .map(([_key, val]: FDType) => val) + .join(", "); + + const fdList = Array.from(formData) + .map( + ([key, val]: FDType) => + `${encodeURIComponent(key)}=${encodeURIComponent(val as string)}`, + ) + .join("&"); + + document.getElementById("check-message-pad")!.innerHTML = ` +

      Values as seen in \`form.formData\`: ${valList}

      +

      Values as seen in x-form-encoded format: ${fdList}

      `; + }; + + return container( + html`

      + FormData example. This variant emits the same events and exhibits the same behavior + as the above, but instead of monitoring for 'change' events on the checkbox group, + we monitor for the user pressing the 'submit' button. What is displayed is the + values as understood by the <form> object, via its internal \`formData\` + field, to demonstrate that this component works with forms as if it were a native + form element. +

      + +
      + + + `, + ); +}; diff --git a/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts b/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts new file mode 100644 index 0000000000..addb13395a --- /dev/null +++ b/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts @@ -0,0 +1,227 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { msg } from "@lit/localize"; +import { PropertyValues } from "@lit/reactive-element/reactive-element"; +import { TemplateResult, css, html } from "lit"; +import { customElement, property, queryAll, state } from "lit/decorators.js"; +import { map } from "lit/directives/map.js"; + +import PFCheck from "@patternfly/patternfly/components/Check/check.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +type CheckboxKv = { name: string; label: string | TemplateResult }; +type CheckboxPr = [string, string | TemplateResult]; +export type CheckboxPair = CheckboxKv | CheckboxPr; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const isCheckboxPr = (t: any): t is CheckboxPr => Array.isArray(t); +function* kvToPairs(items: CheckboxPair[]): Iterable { + for (const item of items) { + yield isCheckboxPr(item) ? item : [item.name, item.label]; + } +} + +const AkElementWithCustomEvents = CustomEmitterElement(AKElement); + +/** + * @element ak-checkbox-group + * + * @class CheckboxGroup + * + * @description + * CheckboxGroup renders a collection of checkboxes in a linear list. Multiple + * checkboxes may be picked. + * + * @attr {options} - An array of either `[string, string | TemplateResult]` or + * `{ name: string, label: string | TemplateResult }`. The first value or + * `name` field must be a valid HTML identifier compatible with the HTML + * `name` attribute. + * + * @attr {value} - An array of `name` values corresponding to the options that + * are selected when the element is rendered. + * + * @attr {name} - The name of this element as it will appear in any
      + * transaction + * + * @attr {required} - If true, and if name is set, and no values are chosen, + * will automatically fail a form `submit` event, providing a warning + * message for any labeling. Note: if `name` is not set, this has no effect, + * and a warn() will appear on the console. + * + * @event {input} - Fired when the component's value has changed. Current value + * as an array of `name` will be in the `Event.detail` field. + * + * @event {change} - Fired when the component's value has changed. Current value + * as an array of `name` will be in the `Event.detail` field. + * + * @csspart checkbox - The div containing the checkbox item and the label + * @csspart label - the label + * @csspart input - the input item + * @csspart checkbox-group - the wrapper div with flexbox control + * + * ## Bigger hit area + * + * Providing properly formatted names for selections allows the element to + * associate the label with the event, so the entire horizontal area from + * checkbox to end-of-label will be the hit area. + * + * ## FormAssociated compliance + * + * If a component is a parent, this component will correctly send its + * values to the form for `x-form-encoded` data; multiples will appear in the + * form of `name=value1&name=value2` format, and must be unpacked into an array + * correctly on the server side according to the CGI (common gateway interface) + * protocol. + * + */ + +@customElement("ak-checkbox-group") +export class CheckboxGroup extends AkElementWithCustomEvents { + static get styles() { + return [ + PFBase, + PFForm, + PFCheck, + css` + .pf-c-form__group-control { + padding-top: calc( + var(--pf-c-form--m-horizontal__group-label--md--PaddingTop) * 1.3 + ); + } + `, + ]; + } + + static get formAssociated() { + return true; + } + + @property({ type: Array }) + options: CheckboxPair[] = []; + + @property({ type: Array }) + value: string[] = []; + + @property({ type: String }) + name?: string; + + @property({ type: Boolean }) + required = false; + + @queryAll('input[type="checkbox"]') + checkboxes!: NodeListOf; + + @state() + values: string[] = []; + + internals?: ElementInternals; + doneFirstUpdate = false; + + json() { + return this.values; + } + + private get formValue() { + if (this.name === undefined) { + throw new Error("This cannot be called without having the name set."); + } + const name = this.name; + const entries = new FormData(); + this.values.forEach((v) => entries.append(name, v)); + return entries; + } + + constructor() { + super(); + this.onClick = this.onClick.bind(this); + this.dataset.akControl = "true"; + } + + onClick(ev: Event) { + ev.stopPropagation(); + this.values = Array.from(this.checkboxes) + .filter((checkbox) => checkbox.checked) + .map((checkbox) => checkbox.name); + this.dispatchCustomEvent("change", this.values); + this.dispatchCustomEvent("input", this.values); + if (this.internals) { + this.internals.setValidity({}); + if (this.required && this.values.length === 0) { + this.internals.setValidity( + { + valueMissing: true, + }, + msg("A selection is required"), + this, + ); + } + this.internals.setFormValue(this.formValue); + } + // Doing a write-back so anyone examining the checkbox.value field will get something + // meaningful. Doesn't do anything for anyone, usually, but it's nice to have. + this.value = this.values; + } + + willUpdate(changed: PropertyValues) { + if (changed.has("value") && !this.doneFirstUpdate) { + this.doneFirstUpdate = true; + this.values = this.value; + } + } + + connectedCallback() { + super.connectedCallback(); + if (this.name && !this.internals) { + this.internals = this.attachInternals(); + } + if (this.internals && this.name) { + this.internals.ariaRequired = this.required ? "true" : "false"; + } + if (this.required && !this.internals) { + console.warn( + "Setting `required` on ak-checkbox-group has no effect when the `name` attribute is unset", + ); + } + // These are necessary to prevent the input components' own events from + // leaking out. This helps maintain the illusion that this component + // behaves similarly to the multiple selection behavior of, well, + // + +
      `; + }; + + return html`
      + ${map(kvToPairs(this.options), renderOne)} +
      `; + } +} diff --git a/web/src/elements/ak-dual-select/ak-dual-select-provider.ts b/web/src/elements/ak-dual-select/ak-dual-select-provider.ts new file mode 100644 index 0000000000..15f274460a --- /dev/null +++ b/web/src/elements/ak-dual-select/ak-dual-select-provider.ts @@ -0,0 +1,150 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { debounce } from "@goauthentik/elements/utils/debounce"; +import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { msg } from "@lit/localize"; +import { PropertyValues, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { createRef, ref } from "lit/directives/ref.js"; +import type { Ref } from "lit/directives/ref.js"; + +import type { Pagination } from "@goauthentik/api"; + +import "./ak-dual-select"; +import { AkDualSelect } from "./ak-dual-select"; +import type { DataProvider, DualSelectPair } from "./types"; + +/** + * @element ak-dual-select-provider + * + * A top-level component that understands how the authentik pagination interface works, + * and can provide new pages based upon navigation requests. This is the interface + * between authentik and the generic ak-dual-select component; aside from knowing that + * the Pagination object "looks like Django," the interior components don't know anything + * about authentik at all and could be dropped into Gravity unchanged.) + * + */ + +@customElement("ak-dual-select-provider") +export class AkDualSelectProvider extends CustomListenerElement(AKElement) { + /** A function that takes a page and returns the DualSelectPair[] collection with which to update + * the "Available" pane. + */ + @property({ type: Object }) + provider!: DataProvider; + + @property({ type: Array }) + selected: DualSelectPair[] = []; + + @property({ attribute: "available-label" }) + availableLabel = msg("Available options"); + + @property({ attribute: "selected-label" }) + selectedLabel = msg("Selected options"); + + /** The remote lists are debounced by definition. This is the interval for the debounce. */ + @property({ attribute: "search-delay", type: Number }) + searchDelay = 250; + + @state() + private options: DualSelectPair[] = []; + + private dualSelector: Ref = createRef(); + + private isLoading = false; + + private doneFirstUpdate = false; + private internalSelected: DualSelectPair[] = []; + + private pagination?: Pagination; + + constructor() { + super(); + setTimeout(() => this.fetch(1), 0); + // Notify AkForElementHorizontal how to handle this thing. + this.dataset.akControl = "true"; + this.onNav = this.onNav.bind(this); + this.onChange = this.onChange.bind(this); + this.onSearch = this.onSearch.bind(this); + this.addCustomListener("ak-pagination-nav-to", this.onNav); + this.addCustomListener("ak-dual-select-change", this.onChange); + this.addCustomListener("ak-dual-select-search", this.onSearch); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("selected") && !this.doneFirstUpdate) { + this.doneFirstUpdate = true; + this.internalSelected = this.selected; + } + + if (changedProperties.has("searchDelay")) { + this.doSearch = debounce( + AkDualSelectProvider.prototype.doSearch.bind(this), + this.searchDelay, + ); + } + + if (changedProperties.has("provider")) { + this.pagination = undefined; + this.fetch(); + } + } + + async fetch(page?: number, search = "") { + if (this.isLoading) { + return; + } + this.isLoading = true; + const goto = page ?? this.pagination?.current ?? 1; + const data = await this.provider(goto, search); + this.pagination = data.pagination; + this.options = data.options; + this.isLoading = false; + } + + onNav(event: Event) { + if (!(event instanceof CustomEvent)) { + throw new Error(`Expecting a CustomEvent for navigation, received ${event} instead`); + } + this.fetch(event.detail); + } + + onChange(event: Event) { + if (!(event instanceof CustomEvent)) { + throw new Error(`Expecting a CustomEvent for change, received ${event} instead`); + } + this.internalSelected = event.detail.value; + this.selected = this.internalSelected; + } + + onSearch(event: Event) { + if (!(event instanceof CustomEvent)) { + throw new Error(`Expecting a CustomEvent for change, received ${event} instead`); + } + this.doSearch(event.detail); + } + + doSearch(search: string) { + this.pagination = undefined; + this.fetch(undefined, search); + } + + get value() { + return this.dualSelector.value!.selected.map(([k, _]) => k); + } + + json() { + return this.value; + } + + render() { + return html``; + } +} diff --git a/web/src/elements/ak-dual-select/ak-dual-select.ts b/web/src/elements/ak-dual-select/ak-dual-select.ts new file mode 100644 index 0000000000..41799d56de --- /dev/null +++ b/web/src/elements/ak-dual-select/ak-dual-select.ts @@ -0,0 +1,353 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { + CustomEmitterElement, + CustomListenerElement, +} from "@goauthentik/elements/utils/eventEmitter"; + +import { msg, str } from "@lit/localize"; +import { PropertyValues, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { createRef, ref } from "lit/directives/ref.js"; +import type { Ref } from "lit/directives/ref.js"; +import { unsafeHTML } from "lit/directives/unsafe-html.js"; + +import { globalVariables, mainStyles } from "./components/styles.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import "./components/ak-dual-select-available-pane"; +import { AkDualSelectAvailablePane } from "./components/ak-dual-select-available-pane"; +import "./components/ak-dual-select-controls"; +import "./components/ak-dual-select-selected-pane"; +import { AkDualSelectSelectedPane } from "./components/ak-dual-select-selected-pane"; +import "./components/ak-pagination"; +import "./components/ak-search-bar"; +import { + EVENT_ADD_ALL, + EVENT_ADD_ONE, + EVENT_ADD_SELECTED, + EVENT_DELETE_ALL, + EVENT_REMOVE_ALL, + EVENT_REMOVE_ONE, + EVENT_REMOVE_SELECTED, +} from "./constants"; +import type { BasePagination, DualSelectPair, SearchbarEvent } from "./types"; + +function alphaSort([_k1, v1, s1]: DualSelectPair, [_k2, v2, s2]: DualSelectPair) { + const [l, r] = [s1 !== undefined ? s1 : v1, s2 !== undefined ? s2 : v2]; + return l < r ? -1 : l > r ? 1 : 0; +} + +function mapDualPairs(pairs: DualSelectPair[]) { + return new Map(pairs.map(([k, v, _]) => [k, v])); +} + +const styles = [PFBase, PFButton, globalVariables, mainStyles]; + +/** + * @element ak-dual-select + * + * A master (but independent) component that shows two lists-- one of "available options" and one of + * "selected options". The Available Options panel supports pagination if it receives a valid and + * active pagination object (based on Django's pagination object) from the invoking component. + * + * @fires ak-dual-select-change - A custom change event with the current `selected` list. + */ + +const keyfinder = + (key: string) => + ([k]: DualSelectPair) => + k === key; + +@customElement("ak-dual-select") +export class AkDualSelect extends CustomEmitterElement(CustomListenerElement(AKElement)) { + static get styles() { + return styles; + } + + /* The list of options to *currently* show. Note that this is not *all* the options, only the + * currently shown list of options from a pagination collection. */ + @property({ type: Array }) + options: DualSelectPair[] = []; + + /* The list of options selected. This is the *entire* list and will not be paginated. */ + @property({ type: Array }) + selected: DualSelectPair[] = []; + + @property({ type: Object }) + pages?: BasePagination; + + @property({ attribute: "available-label" }) + availableLabel = msg("Available options"); + + @property({ attribute: "selected-label" }) + selectedLabel = msg("Selected options"); + + @state() + selectedFilter: string = ""; + + availablePane: Ref = createRef(); + + selectedPane: Ref = createRef(); + + selectedKeys: Set = new Set(); + + constructor() { + super(); + this.handleMove = this.handleMove.bind(this); + this.handleSearch = this.handleSearch.bind(this); + [ + EVENT_ADD_ALL, + EVENT_ADD_SELECTED, + EVENT_DELETE_ALL, + EVENT_REMOVE_ALL, + EVENT_REMOVE_SELECTED, + EVENT_ADD_ONE, + EVENT_REMOVE_ONE, + ].forEach((eventName: string) => { + this.addCustomListener(eventName, (event: Event) => this.handleMove(eventName, event)); + }); + this.addCustomListener("ak-dual-select-move", () => { + this.requestUpdate(); + }); + this.addCustomListener("ak-search", this.handleSearch); + } + + willUpdate(changedProperties: PropertyValues) { + if (changedProperties.has("selected")) { + this.selectedKeys = new Set(this.selected.map(([key, _]) => key)); + } + // Pagination invalidates available moveables. + if (changedProperties.has("options") && this.availablePane.value) { + this.availablePane.value.clearMove(); + } + } + + handleMove(eventName: string, event: Event) { + if (!(event instanceof CustomEvent)) { + throw new Error(`Expected move event here, got ${eventName}`); + } + + switch (eventName) { + case EVENT_ADD_SELECTED: { + this.addSelected(); + break; + } + case EVENT_REMOVE_SELECTED: { + this.removeSelected(); + break; + } + case EVENT_ADD_ALL: { + this.addAllVisible(); + break; + } + case EVENT_REMOVE_ALL: { + this.removeAllVisible(); + break; + } + case EVENT_DELETE_ALL: { + this.removeAll(); + break; + } + case EVENT_ADD_ONE: { + this.addOne(event.detail); + break; + } + case EVENT_REMOVE_ONE: { + this.removeOne(event.detail); + break; + } + + default: + throw new Error( + `AkDualSelect.handleMove received unknown event type: ${eventName}`, + ); + } + this.dispatchCustomEvent("ak-dual-select-change", { value: this.value }); + event.stopPropagation(); + } + + addSelected() { + if (this.availablePane.value!.moveable.length === 0) { + return; + } + this.selected = this.availablePane.value!.moveable.reduce( + (acc, key) => { + const value = this.options.find(keyfinder(key)); + return value && !acc.find(keyfinder(value[0])) ? [...acc, value] : acc; + }, + [...this.selected], + ); + // This is where the information gets... lossy. Dammit. + this.availablePane.value!.clearMove(); + } + + addOne(key: string) { + const requested = this.options.find(keyfinder(key)); + if (requested && !this.selected.find(keyfinder(requested[0]))) { + this.selected = [...this.selected, requested]; + } + } + + // These are the *currently visible* options; the parent node is responsible for paginating and + // updating the list of currently visible options; + addAllVisible() { + // Create a new array of all current options and selected, and de-dupe. + const selected = mapDualPairs([...this.options, ...this.selected]); + this.selected = Array.from(selected.entries()); + this.availablePane.value!.clearMove(); + } + + removeSelected() { + if (this.selectedPane.value!.moveable.length === 0) { + return; + } + const deselected = new Set(this.selectedPane.value!.moveable); + this.selected = this.selected.filter(([key]) => !deselected.has(key)); + this.selectedPane.value!.clearMove(); + } + + removeOne(key: string) { + this.selected = this.selected.filter(([k]) => k !== key); + } + + removeAllVisible() { + // Remove all the items from selected that are in the *currently visible* options list + const options = new Set(this.options.map(([k, _]) => k)); + this.selected = this.selected.filter(([k]) => !options.has(k)); + this.selectedPane.value!.clearMove(); + } + + removeAll() { + this.selected = []; + this.selectedPane.value!.clearMove(); + } + + handleSearch(event: SearchbarEvent) { + switch (event.detail.source) { + case "ak-dual-list-available-search": + return this.handleAvailableSearch(event.detail.value); + case "ak-dual-list-selected-search": + return this.handleSelectedSearch(event.detail.value); + } + event.stopPropagation(); + } + + handleAvailableSearch(value: string) { + this.dispatchCustomEvent("ak-dual-select-search", value); + } + + handleSelectedSearch(value: string) { + this.selectedFilter = value; + this.selectedPane.value!.clearMove(); + } + + get value() { + return this.selected; + } + + get canAddAll() { + // False unless any visible option cannot be found in the selected list, so can still be + // added. + const allMoved = + this.options.length === + this.options.filter(([key, _]) => this.selectedKeys.has(key)).length; + + return this.options.length > 0 && !allMoved; + } + + get canRemoveAll() { + // False if no visible option can be found in the selected list + return ( + this.options.length > 0 && !!this.options.find(([key, _]) => this.selectedKeys.has(key)) + ); + } + + get needPagination() { + return (this.pages?.next ?? 0) > 0 || (this.pages?.previous ?? 0) > 0; + } + + render() { + const selected = + this.selectedFilter === "" + ? this.selected + : this.selected.filter(([_k, v, s]) => { + const value = s !== undefined ? s : v; + if (typeof value !== "string") { + throw new Error("Filter only works when there's a string comparator"); + } + return value.toLowerCase().includes(this.selectedFilter.toLowerCase()); + }); + + const availableCount = this.availablePane.value?.toMove.size ?? 0; + const selectedCount = this.selectedPane.value?.toMove.size ?? 0; + const selectedTotal = selected.length; + const availableStatus = + availableCount > 0 ? msg(str`${availableCount} item(s) marked to add.`) : " "; + const selectedTotalStatus = msg(str`${selectedTotal} item(s) selected.`); + const selectedCountStatus = + selectedCount > 0 ? " " + msg(str`${selectedCount} item(s) marked to remove.`) : ""; + const selectedStatus = `${selectedTotalStatus} ${selectedCountStatus}`; + + return html` +
      +
      +
      +
      +
      + ${this.availableLabel} +
      +
      +
      + +
      + ${unsafeHTML(availableStatus)} +
      + + ${this.needPagination + ? html`` + : nothing} +
      + 0} + ?remove-active=${(this.selectedPane.value?.moveable.length ?? 0) > 0} + ?add-all-active=${this.canAddAll} + ?remove-all-active=${this.canRemoveAll} + ?delete-all-active=${this.selected.length !== 0} + enable-select-all + enable-delete-all + > +
      +
      +
      +
      + ${this.selectedLabel} +
      +
      +
      + +
      + ${unsafeHTML(selectedStatus)} +
      + + +
      +
      + `; + } +} diff --git a/web/src/elements/ak-dual-select/components/ak-dual-select-available-pane.ts b/web/src/elements/ak-dual-select/components/ak-dual-select-available-pane.ts new file mode 100644 index 0000000000..b8f58aab9b --- /dev/null +++ b/web/src/elements/ak-dual-select/components/ak-dual-select-available-pane.ts @@ -0,0 +1,159 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { classMap } from "lit/directives/class-map.js"; +import { map } from "lit/directives/map.js"; + +import { availablePaneStyles, listStyles } from "./styles.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFDualListSelector from "@patternfly/patternfly/components/DualListSelector/dual-list-selector.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { EVENT_ADD_ONE } from "../constants"; +import type { DualSelectPair } from "../types"; + +const styles = [PFBase, PFButton, PFDualListSelector, listStyles, availablePaneStyles]; + +const hostAttributes = [ + ["aria-labelledby", "dual-list-selector-available-pane-status"], + ["aria-multiselectable", "true"], + ["role", "listbox"], +]; + +/** + * @element ak-dual-select-available-panel + * + * The "available options" or "left" pane in a dual-list multi-select. It receives from its parent a + * list of options to show *now*, the list of all "selected" options, and maintains an internal list + * of objects selected to move. "selected" options are marked with a checkmark to show they're + * already in the "selected" collection and would be pointless to move. + * + * @fires ak-dual-select-available-move-changed - When the list of "to move" entries changed. + * Includes the current * `toMove` content. + * + * @fires ak-dual-select-add-one - Double-click with the element clicked on. + * + * It is not expected that the `ak-dual-select-available-move-changed` event will be used; instead, + * the attribute will be read by the parent when a control is clicked. + * + */ +@customElement("ak-dual-select-available-pane") +export class AkDualSelectAvailablePane extends CustomEmitterElement(AKElement) { + static get styles() { + return styles; + } + + /* The array of key/value pairs this pane is currently showing */ + @property({ type: Array }) + readonly options: DualSelectPair[] = []; + + /* A set (set being easy for lookups) of keys with all the pairs selected, so that the ones + * currently being shown that have already been selected can be marked and their clicks ignored. + * + */ + @property({ type: Object }) + readonly selected: Set = new Set(); + + /* This is the only mutator for this object. It collects the list of objects the user has + * clicked on *in this pane*. It is explicitly marked as "public" to emphasize that the parent + * orchestrator for the dual-select widget can and will access it to get the list of keys to be + * moved (removed) if the user so requests. + * + */ + @state() + public toMove: Set = new Set(); + + constructor() { + super(); + this.onClick = this.onClick.bind(this); + this.onMove = this.onMove.bind(this); + } + + connectedCallback() { + super.connectedCallback(); + hostAttributes.forEach(([attr, value]) => { + if (!this.hasAttribute(attr)) { + this.setAttribute(attr, value); + } + }); + } + + clearMove() { + this.toMove = new Set(); + } + + onClick(key: string) { + if (this.selected.has(key)) { + return; + } + if (this.toMove.has(key)) { + this.toMove.delete(key); + } else { + this.toMove.add(key); + } + this.dispatchCustomEvent( + "ak-dual-select-available-move-changed", + Array.from(this.toMove.values()).sort(), + ); + this.dispatchCustomEvent("ak-dual-select-move"); + // Necessary because updating a map won't trigger a state change + this.requestUpdate(); + } + + onMove(key: string) { + this.toMove.delete(key); + this.dispatchCustomEvent(EVENT_ADD_ONE, key); + this.requestUpdate(); + } + + get moveable() { + return Array.from(this.toMove.values()); + } + + // DO NOT use `Array.map()` instead of Lit's `map()` function. Lit's `map()` is object-aware and + // will not re-arrange or reconstruct the list automatically if the actual sources do not + // change; this allows the available pane to illustrate selected items with the checkmark + // without causing the list to scroll back up to the top. + + render() { + return html` +
      +
        + ${map(this.options, ([key, label]) => { + const selected = classMap({ + "pf-m-selected": this.toMove.has(key), + }); + return html`
      • this.onClick(key)} + @dblclick=${() => this.onMove(key)} + role="option" + data-ak-key=${key} + tabindex="-1" + > +
        + + + ${label}${this.selected.has(key) + ? html`` + : nothing} +
        +
      • `; + })} +
      +
      + `; + } +} + +export default AkDualSelectAvailablePane; diff --git a/web/src/elements/ak-dual-select/components/ak-dual-select-controls.ts b/web/src/elements/ak-dual-select/components/ak-dual-select-controls.ts new file mode 100644 index 0000000000..32d3761760 --- /dev/null +++ b/web/src/elements/ak-dual-select/components/ak-dual-select-controls.ts @@ -0,0 +1,165 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { msg } from "@lit/localize"; +import { css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { + EVENT_ADD_ALL, + EVENT_ADD_SELECTED, + EVENT_DELETE_ALL, + EVENT_REMOVE_ALL, + EVENT_REMOVE_SELECTED, +} from "../constants"; + +const styles = [ + PFBase, + PFButton, + css` + :host { + align-self: center; + padding-right: var(--pf-c-dual-list-selector__controls--PaddingRight); + padding-left: var(--pf-c-dual-list-selector__controls--PaddingLeft); + } + .pf-c-dual-list-selector { + max-width: 4rem; + } + .ak-dual-list-selector__controls { + display: grid; + justify-content: center; + align-content: center; + height: 100%; + } + `, +]; + +/** + * @element ak-dual-select-controls + * + * The "control box" for a dual-list multi-select. It's controlled by the parent orchestrator as to + * whether or not any of its controls are enabled. It sends a variety of messages to the parent + * orchestrator which will then reconcile the "available" and "selected" panes at need. + * + */ + +@customElement("ak-dual-select-controls") +export class AkDualSelectControls extends CustomEmitterElement(AKElement) { + static get styles() { + return styles; + } + + /* Set to true if any *visible* elements can be added to the selected list + */ + @property({ attribute: "add-active", type: Boolean }) + addActive = false; + + /* Set to true if any elements can be removed from the selected list (essentially, + * if the selected list is not empty) + */ + @property({ attribute: "remove-active", type: Boolean }) + removeActive = false; + + /* Set to true if *all* the currently visible elements can be moved + * into the selected list (essentially, if any visible elements are + * not currently selected) + */ + @property({ attribute: "add-all-active", type: Boolean }) + addAllActive = false; + + /* Set to true if *any* of the elements currently visible in the available + * pane are available to be moved to the selected list, enabling that + * all of those specific elements be moved out of the selected list + */ + @property({ attribute: "remove-all-active", type: Boolean }) + removeAllActive = false; + + /* if deleteAll is enabled, set to true to show that there are elements in the + * selected list that can be deleted. + */ + @property({ attribute: "delete-all-active", type: Boolean }) + enableDeleteAll = false; + + /* Set to true if you want the `...AllActive` buttons made available. */ + @property({ attribute: "enable-select-all", type: Boolean }) + selectAll = false; + + /* Set to true if you want the `ClearAllSelected` button made available */ + @property({ attribute: "enable-delete-all", type: Boolean }) + deleteAll = false; + + constructor() { + super(); + this.onClick = this.onClick.bind(this); + } + + onClick(eventName: string) { + this.dispatchCustomEvent(eventName); + } + + renderButton(label: string, event: string, active: boolean, direction: string) { + return html` +
      + +
      +
      `; + } + + render() { + return html` +
      + ${this.renderButton( + msg("Add"), + EVENT_ADD_SELECTED, + this.addActive, + "fa-angle-right", + )} + ${this.selectAll + ? html` + ${this.renderButton( + msg("Add All Available"), + EVENT_ADD_ALL, + this.addAllActive, + "fa-angle-double-right", + )} + ${this.renderButton( + msg("Remove All Available"), + EVENT_REMOVE_ALL, + this.removeAllActive, + "fa-angle-double-left", + )} + ` + : nothing} + ${this.renderButton( + msg("Remove"), + EVENT_REMOVE_SELECTED, + this.removeActive, + "fa-angle-left", + )} + ${this.deleteAll + ? html`${this.renderButton( + msg("Remove All"), + EVENT_DELETE_ALL, + this.enableDeleteAll, + "fa-times", + )}` + : nothing} +
      + `; + } +} + +export default AkDualSelectControls; diff --git a/web/src/elements/ak-dual-select/components/ak-dual-select-selected-pane.ts b/web/src/elements/ak-dual-select/components/ak-dual-select-selected-pane.ts new file mode 100644 index 0000000000..981bef2fd2 --- /dev/null +++ b/web/src/elements/ak-dual-select/components/ak-dual-select-selected-pane.ts @@ -0,0 +1,139 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { classMap } from "lit/directives/class-map.js"; +import { map } from "lit/directives/map.js"; + +import { listStyles, selectedPaneStyles } from "./styles.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFDualListSelector from "@patternfly/patternfly/components/DualListSelector/dual-list-selector.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { EVENT_REMOVE_ONE } from "../constants"; +import type { DualSelectPair } from "../types"; + +const styles = [PFBase, PFButton, PFDualListSelector, listStyles, selectedPaneStyles]; + +const hostAttributes = [ + ["aria-labelledby", "dual-list-selector-selected-pane-status"], + ["aria-multiselectable", "true"], + ["role", "listbox"], +]; + +/** + * @element ak-dual-select-available-panel + * + * The "selected options" or "right" pane in a dual-list multi-select. It receives from its parent + * a list of the selected options, and maintains an internal list of objects selected to move. + * + * @fires ak-dual-select-selected-move-changed - When the list of "to move" entries changed. + * Includes the current `toMove` content. + * + * @fires ak-dual-select-remove-one - Double-click with the element clicked on. + * + * It is not expected that the `ak-dual-select-selected-move-changed` will be used; instead, the + * attribute will be read by the parent when a control is clicked. + * + */ +@customElement("ak-dual-select-selected-pane") +export class AkDualSelectSelectedPane extends CustomEmitterElement(AKElement) { + static get styles() { + return styles; + } + + /* The array of key/value pairs that are in the selected list. ALL of them. */ + @property({ type: Array }) + readonly selected: DualSelectPair[] = []; + + /* + * This is the only mutator for this object. It collects the list of objects the user has + * clicked on *in this pane*. It is explicitly marked as "public" to emphasize that the parent + * orchestrator for the dual-select widget can and will access it to get the list of keys to be + * moved (removed) if the user so requests. + * + */ + @state() + public toMove: Set = new Set(); + + constructor() { + super(); + this.onClick = this.onClick.bind(this); + this.onMove = this.onMove.bind(this); + } + + connectedCallback() { + super.connectedCallback(); + hostAttributes.forEach(([attr, value]) => { + if (!this.hasAttribute(attr)) { + this.setAttribute(attr, value); + } + }); + } + + clearMove() { + this.toMove = new Set(); + } + + onClick(key: string) { + if (this.toMove.has(key)) { + this.toMove.delete(key); + } else { + this.toMove.add(key); + } + this.dispatchCustomEvent( + "ak-dual-select-selected-move-changed", + Array.from(this.toMove.values()).sort(), + ); + this.dispatchCustomEvent("ak-dual-select-move"); + // Necessary because updating a map won't trigger a state change + this.requestUpdate(); + } + + onMove(key: string) { + this.toMove.delete(key); + this.dispatchCustomEvent(EVENT_REMOVE_ONE, key); + this.requestUpdate(); + } + + get moveable() { + return Array.from(this.toMove.values()); + } + + render() { + return html` +
      +
        + ${map(this.selected, ([key, label]) => { + const selected = classMap({ + "pf-m-selected": this.toMove.has(key), + }); + return html`
      • this.onClick(key)} + @dblclick=${() => this.onMove(key)} + role="option" + data-ak-key=${key} + tabindex="-1" + > +
        + + + ${label} +
        +
      • `; + })} +
      +
      + `; + } +} + +export default AkDualSelectSelectedPane; diff --git a/web/src/elements/ak-dual-select/components/ak-pagination.ts b/web/src/elements/ak-dual-select/components/ak-pagination.ts new file mode 100644 index 0000000000..21065549ee --- /dev/null +++ b/web/src/elements/ak-dual-select/components/ak-pagination.ts @@ -0,0 +1,94 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { msg, str } from "@lit/localize"; +import { css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import type { BasePagination } from "../types"; + +const styles = [ + PFBase, + PFButton, + PFPagination, + css` + :host([theme="dark"]) .pf-c-pagination__nav-control .pf-c-button { + color: var(--pf-c-button--m-plain--disabled--Color); + --pf-c-button--disabled--Color: var(--pf-c-button--m-plain--Color); + } + :host([theme="dark"]) .pf-c-pagination__nav-control .pf-c-button:disabled { + color: var(--pf-c-button--disabled--Color); + } + `, +]; + +@customElement("ak-pagination") +export class AkPagination extends CustomEmitterElement(AKElement) { + static get styles() { + return styles; + } + + @property({ attribute: false }) + pages?: BasePagination; + + constructor() { + super(); + this.onClick = this.onClick.bind(this); + } + + onClick(nav: number | undefined) { + this.dispatchCustomEvent("ak-pagination-nav-to", nav ?? 0); + } + + render() { + return this.pages + ? html`
      +
      +
      +
      + + ${msg( + str`${this.pages?.startIndex} - ${this.pages?.endIndex} of ${this.pages?.count}`, + )} + +
      +
      + +
      +
      ` + : nothing; + } +} + +export default AkPagination; diff --git a/web/src/elements/ak-dual-select/components/ak-search-bar.ts b/web/src/elements/ak-dual-select/components/ak-search-bar.ts new file mode 100644 index 0000000000..dafc149941 --- /dev/null +++ b/web/src/elements/ak-dual-select/components/ak-search-bar.ts @@ -0,0 +1,69 @@ +import { AKElement } from "@goauthentik/elements/Base"; +import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; + +import { html } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { createRef, ref } from "lit/directives/ref.js"; +import type { Ref } from "lit/directives/ref.js"; + +import { globalVariables, searchStyles } from "./search.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import type { SearchbarEvent } from "../types"; + +const styles = [PFBase, globalVariables, searchStyles]; + +@customElement("ak-search-bar") +export class AkSearchbar extends CustomEmitterElement(AKElement) { + static get styles() { + return styles; + } + + @property({ type: String, reflect: true }) + value = ""; + + /** + * If you're using more than one search, this token can help listeners distinguishing between + * those searches. Lit's own helpers sometimes erase the source and current targets. + */ + @property({ type: String }) + name = ""; + + input: Ref = createRef(); + + constructor() { + super(); + this.onChange = this.onChange.bind(this); + } + + onChange(_event: Event) { + if (this.input.value) { + this.value = this.input.value.value; + } + this.dispatchCustomEvent("ak-search", { + source: this.name, + value: this.value, + }); + } + + render() { + return html` +
      +
      + +
      +
      + `; + } +} + +export default AkSearchbar; diff --git a/web/src/elements/ak-dual-select/components/search.css.ts b/web/src/elements/ak-dual-select/components/search.css.ts new file mode 100644 index 0000000000..1fa11fdf6c --- /dev/null +++ b/web/src/elements/ak-dual-select/components/search.css.ts @@ -0,0 +1,190 @@ +import { css } from "lit"; + +// The `host` information for the Patternfly dual list selector came with some default settings that +// we do not want in a web component. By isolating what we *really* use into this collection here, +// we get all the benefits of Patternfly without having to wrestle without also having to counteract +// those default settings. + +export const globalVariables = css` + :host { + --pf-c-text-input-group--BackgroundColor: var(--pf-global--BackgroundColorg--100); + --pf-c-text-input-group--Color: var(--pf-global--Color--dark-100); + + --pf-c-text-input-group__text--before--BorderWidth: var(--pf-global--BorderWidth--sm); + --pf-c-text-input-group__text--before--BorderColor: var(--pf-global--BorderColor--300); + + --pf-c-text-input-group__text--after--BorderBottomWidth: var(--pf-global--BorderWidth--sm); + --pf-c-text-input-group__text--after--BorderBottomColor: var(--pf-global--BorderColor--200); + + --pf-c-text-input-group--hover__text--after--BorderBottomColor: var( + --pf-global--primary-color--100 + ); + --pf-c-text-input-group__text--focus-within--after--BorderBottomWidth: var( + --pf-global--BorderWidth--md + ); + --pf-c-text-input-group__text--focus-within--after--BorderBottomColor: var( + --pf-global--primary-color--100 + ); + --pf-c-text-input-group__main--first-child--not--text-input--MarginLeft: var( + --pf-global--spacer--sm + ); + --pf-c-text-input-group__main--m-icon__text-input--PaddingLeft: var( + --pf-global--spacer--xl + ); + --pf-c-text-input-group__main--RowGap: var(--pf-global--spacer--xs); + --pf-c-text-input-group__main--ColumnGap: var(--pf-global--spacer--sm); + --pf-c-text-input-group--c-chip-group__main--PaddingTop: var(--pf-global--spacer--xs); + --pf-c-text-input-group--c-chip-group__main--PaddingRight: var(--pf-global--spacer--xs); + --pf-c-text-input-group--c-chip-group__main--PaddingBottom: var(--pf-global--spacer--xs); + --pf-c-text-input-group__text-input--PaddingTop: var(--pf-global--spacer--form-element); + --pf-c-text-input-group__text-input--PaddingRight: var(--pf-global--spacer--sm); + --pf-c-text-input-group__text-input--PaddingBottom: var(--pf-global--spacer--form-element); + --pf-c-text-input-group__text-input--PaddingLeft: var(--pf-global--spacer--sm); + --pf-c-text-input-group__text-input--MinWidth: 12ch; + --pf-c-text-input-group__text-input--m-hint--Color: var(--pf-global--Color--dark-200); + --pf-c-text-input-group--placeholder--Color: var(--pf-global--Color--dark-200); + --pf-c-text-input-group__icon--Left: var(--pf-global--spacer--sm); + --pf-c-text-input-group__icon--Color: var(--pf-global--Color--200); + --pf-c-text-input-group__text--hover__icon--Color: var(--pf-global--Color--100); + --pf-c-text-input-group__icon--TranslateY: -50%; + --pf-c-text-input-group__utilities--MarginRight: var(--pf-global--spacer--sm); + --pf-c-text-input-group__utilities--MarginLeft: var(--pf-global--spacer--xs); + --pf-c-text-input-group__utilities--child--MarginLeft: var(--pf-global--spacer--xs); + --pf-c-text-input-group__utilities--c-button--PaddingRight: var(--pf-global--spacer--xs); + --pf-c-text-input-group__utilities--c-button--PaddingLeft: var(--pf-global--spacer--xs); + --pf-c-text-input-group--m-disabled--Color: var(--pf-global--disabled-color--100); + --pf-c-text-input-group--m-disabled--BackgroundColor: var(--pf-global--disabled-color--300); + } + + :host([theme="dark"]) { + --pf-c-text-input-group--BackgroundColor: var(--ak-dark-background-light); + --pf-c-text-input-group--Color: var(--ak-dark-foreground); + + --pf-c-text-input-group__text--before--BorderColor: var(--ak-dark-background-lighter); + --pf-c-text-input-group__text--before--BorderWidth: 0; + + --pf-c-text-input-group--m-disabled--Color: var(--pf-global--disabled-color--300); + --pf-c-text-input-group--m-disabled--BackgroundColor: var(--pf-global--disabled-color--200); + + --pf-c-text-input-group__text--before--BorderBottomColor: var( + --pf-global--BorderColor--200 + ); + } +`; + +export const searchStyles = css` + i.fa, + i.fas, + i.far, + i.fal, + i.fab { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + } + + i.fa-search:before { + content: "\f002"; + } + + .fa, + .fas { + position: relative; + font-family: "Font Awesome 5 Free"; + font-weight: 900; + } + + i.fa-fw { + text-align: center; + width: 1.25em; + } + + .pf-c-text-input-group { + position: relative; + display: flex; + width: 100%; + color: var(--pf-c-text-input-group--Color, inherit); + background-color: var(--pf-c-text-input-group--BackgroundColor); + } + + .pf-c-text-input-group__main { + display: flex; + flex: 1; + flex-wrap: wrap; + gap: var(--pf-c-text-input-group__main--RowGap) + var(--pf-c-text-input-group__main--ColumnGap); + min-width: 0; + } + + .pf-c-text-input-group__main.pf-m-icon { + --pf-c-text-input-group__text-input--PaddingLeft: var( + --pf-c-text-input-group__main--m-icon__text-input--PaddingLeft + ); + } + .pf-c-text-input-group__text { + display: inline-grid; + grid-template-columns: 1fr; + grid-template-areas: "text-input"; + flex: 1; + z-index: 0; + } + + .pf-c-text-input-group__text::before { + border-width: var(--pf-c-text-input-group__text--before--BorderWidth); + border-color: var(--pf-c-text-input-group__text--before--BorderColor); + border-bottom-color: var(--pf-c-text-input-group__text--after--BorderBottomColor); + border-bottom-width: var(--pf-c-text-input-group__text--after--BorderBottomWidth); + border-style: solid; + } + + .pf-c-text-input-group__text::after { + border-bottom: var(--pf-c-text-input-group__text--after--BorderBottomWidth) solid + var(--pf-c-text-input-group__text--after--BorderBottomColor); + } + + .pf-c-text-input-group__text::before, + .pf-c-text-input-group__text::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + pointer-events: none; + content: ""; + z-index: 2; + } + + .pf-c-text-input-group__icon { + z-index: 4; + position: absolute; + top: 50%; + left: var(--pf-c-text-input-group__icon--Left); + color: var(--pf-c-text-input-group__icon--Color); + transform: translateY(var(--pf-c-text-input-group__icon--TranslateY)); + } + + .pf-c-text-input-group__text-input, + .pf-c-text-input-group__text-input.pf-m-hint { + grid-area: text-input; + } + + .pf-c-text-input-group__text-input { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + position: relative; + width: 100%; + color: var(--pf-c-text-input-group--Color); + background-color: var(--pf-c-text-input-group--BackgroundColor); + min-width: var(--pf-c-text-input-group__text-input--MinWidth); + padding: var(--pf-c-text-input-group__text-input--PaddingTop) + var(--pf-c-text-input-group__text-input--PaddingRight) + var(--pf-c-text-input-group__text-input--PaddingBottom) + var(--pf-c-text-input-group__text-input--PaddingLeft); + border: 0; + } +`; diff --git a/web/src/elements/ak-dual-select/components/styles.css.ts b/web/src/elements/ak-dual-select/components/styles.css.ts new file mode 100644 index 0000000000..94959d059c --- /dev/null +++ b/web/src/elements/ak-dual-select/components/styles.css.ts @@ -0,0 +1,219 @@ +import { css } from "lit"; + +// The `host` information for the Patternfly dual list selector came with some default settings that +// we do not want in a web component. By isolating what we *really* use into this collection here, +// we get all the benefits of Patternfly without having to wrestle without also having to counteract +// those default settings. + +export const globalVariables = css` + :host { + --pf-c-dual-list-selector--GridTemplateColumns--pane--MinMax--min: 12.5rem; + --pf-c-dual-list-selector--GridTemplateColumns--pane--MinMax--max: 28.125rem; + --pf-c-dual-list-selector__header--MarginBottom: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__title-text--FontWeight: var(--pf-global--FontWeight--bold); + --pf-c-dual-list-selector__tools--MarginBottom: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__tools-filter--tools-actions--MarginLeft: var( + --pf-global--spacer--sm + ); + --pf-c-dual-list-selector__menu--BorderWidth: var(--pf-global--BorderWidth--sm); + --pf-c-dual-list-selector__menu--BorderColor: var(--pf-global--BorderColor--100); + --pf-c-dual-list-selector__menu--MinHeight: 12.5rem; + --pf-c-dual-list-selector__menu--MaxHeight: 20rem; + --pf-c-dual-list-selector__list-item-row--FontSize: var(--pf-global--FontSize--sm); + --pf-c-dual-list-selector__list-item-row--BackgroundColor: transparent; + --pf-c-dual-list-selector__list-item-row--hover--BackgroundColor: var( + --pf-global--BackgroundColor--light-300 + ); + --pf-c-dual-list-selector__list-item-row--focus-within--BackgroundColor: var( + --pf-global--BackgroundColor--light-300 + ); + --pf-c-dual-list-selector__list-item-row--m-selected--BackgroundColor: var( + --pf-global--BackgroundColor--light-300 + ); + --pf-c-dual-list-selector__list-item--m-ghost-row--BackgroundColor: var( + --pf-global--BackgroundColor--100 + ); + --pf-c-dual-list-selector__list-item--m-ghost-row--Opacity: 0.4; + --pf-c-dual-list-selector__item--PaddingTop: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item--PaddingRight: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__item--PaddingBottom: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item--PaddingLeft: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__item--m-expandable--PaddingLeft: 0; + --pf-c-dual-list-selector__item--indent--base: calc( + var(--pf-global--spacer--md) + var(--pf-global--spacer--sm) + + var(--pf-c-dual-list-selector__list-item-row--FontSize) + ); + --pf-c-dual-list-selector__item--nested-indent--base: calc( + var(--pf-c-dual-list-selector__item--indent--base) - var(--pf-global--spacer--md) + ); + --pf-c-dual-list-selector__draggable--item--PaddingLeft: var(--pf-global--spacer--xs); + --pf-c-dual-list-selector__item-text--Color: var(--pf-global--Color--100); + --pf-c-dual-list-selector__list-item-row--m-selected__text--Color: var( + --pf-global--active-color--100 + ); + --pf-c-dual-list-selector__list-item-row--m-selected__text--FontWeight: var( + --pf-global--FontWeight--bold + ); + --pf-c-dual-list-selector__list-item--m-disabled__item-text--Color: var( + --pf-global--disabled-color--100 + ); + --pf-c-dual-list-selector__status--MarginBottom: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__status-text--FontSize: var(--pf-global--FontSize--sm); + --pf-c-dual-list-selector__status-text--Color: var(--pf-global--Color--200); + --pf-c-dual-list-selector__controls--PaddingRight: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__controls--PaddingLeft: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__item-toggle--PaddingTop: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item-toggle--PaddingRight: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item-toggle--PaddingBottom: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item-toggle--PaddingLeft: var(--pf-global--spacer--md); + --pf-c-dual-list-selector__item-toggle--MarginTop: calc(var(--pf-global--spacer--sm) * -1); + --pf-c-dual-list-selector__item-toggle--MarginBottom: calc( + var(--pf-global--spacer--sm) * -1 + ); + --pf-c-dual-list-selector__list__list__item-toggle--Left: 0; + --pf-c-dual-list-selector__list__list__item-toggle--TranslateX: -100%; + --pf-c-dual-list-selector__item-check--MarginRight: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item-count--Marginleft: var(--pf-global--spacer--sm); + --pf-c-dual-list-selector__item--c-badge--m-read--BackgroundColor: var( + --pf-global--disabled-color--200 + ); + --pf-c-dual-list-selector__item-toggle-icon--Rotate: 0; + --pf-c-dual-list-selector__list-item--m-expanded__item-toggle-icon--Rotate: 90deg; + --pf-c-dual-list-selector__item-toggle-icon--Transition: var(--pf-global--Transition); + --pf-c-dual-list-selector__item-toggle-icon--MinWidth: var( + --pf-c-dual-list-selector__list-item-row--FontSize + ); + --pf-c-dual-list-selector__list-item--m-disabled__item-toggle-icon--Color: var( + --pf-global--disabled-color--200 + ); + + /* Unique to authentik */ + --pf-c-dual-list-selector--selection-desc--FontSize: var(--pf-global--FontSize--xs); + --pf-c-dual-list-selector--selection-desc--Color: var(--pf-global--Color--dark-200); + --pf-c-dual-list-selector__status--top-padding: var(--pf-global--spacer--xs); + --pf-c-dual-list-panels__gap: var(--pf-global--spacer--xs); + } + + :host([theme="dark"]) { + --pf-c-dual-list-selector__menu--BorderColor: var(--ak-dark-background-lighter); + --pf-c-dual-list-selector__item-text--Color: var(--ak-dark-foreground); + --pf-c-dual-list-selector__list-item-row--BackgroundColor: var( + --ak-dark-background-light-ish + ); + --pf-c-dual-list-selector__list-item-row--hover--BackgroundColor: var( + --ak-dark-background-lighter; + ); + --pf-c-dual-list-selector__list-item-row--hover--BackgroundColor: var( + --pf-global--BackgroundColor--400 + ); + } +`; + +export const mainStyles = css` + :host { + --pf-c-dual-list-selector--GridTemplateColumns--pane--MinMax--min: 12.5rem; + --pf-c-dual-list-selector--GridTemplateColumns--pane--MinMax--max: 28.125rem; + } + :host { + display: block grid; + } + + .pf-c-dual-list-selector__title-text { + font-weight: var(--pf-c-dual-list-selector__title-text--FontWeight); + } + + .pf-c-dual-list-selector__status { + padding-top: var(--pf-c-dual-list-selector__status--top-padding); + } + + .pf-c-dual-list-selector__status-text { + font-size: var(--pf-c-dual-list-selector__status-text--FontSize); + color: var(--pf-c-dual-list-selector__status-text--Color); + } + + .ak-dual-list-selector { + display: grid; + grid-template-columns: minmax(0, 1fr) min-content minmax(0, 1fr); + } + + .ak-available-pane, + .ak-selected-pane { + display: grid; + grid-template-rows: auto auto auto 1fr auto; + gap: var(--pf-c-dual-list-panels__gap); + max-width: 100%; + overflow: hidden; + } + + ak-dual-select-controls { + height: 100%; + } +`; + +export const listStyles = css` + :host { + display: block; + overflow: hidden; + max-width: 100%; + } + + .pf-c-dual-list-selector__menu { + max-width: 100%; + height: 100%; + } + + .pf-c-dual-list-selector__list { + max-width: 100%; + display: block; + } + + .pf-c-dual-list-selector__item { + padding: 0.25rem; + width: auto; + } + + .pf-c-dual-list-selector__item-text { + user-select: none; + flex-grow: 0; + } + + .pf-c-dual-list-selector__item-text .selection-main { + color: var(--pf-c-dual-list-selector__item-text--Color); + } + + .pf-c-dual-list-selector__item-text .selection-main:hover { + color: var(--pf-c-dual-list-selector__item-text--Color); + } + + .pf-c-dual-list-selector__item-text .selection-desc { + font-size: var(--pf-c-dual-list-selector--selection-desc--FontSize); + color: var(--pf-c-dual-list-selector--selection-desc--Color); + } +`; + +export const selectedPaneStyles = css` + input[type="checkbox"][readonly] { + pointer-events: none; + } +`; + +export const availablePaneStyles = css` + .pf-c-dual-list-selector__item-text { + display: grid; + grid-template-columns: 1fr auto; + } + + .pf-c-dual-list-selector__item-text .pf-c-dual-list-selector__item-text-selected-indicator { + display: grid; + justify-content: center; + align-content: center; + } + + .pf-c-dual-list-selector__item-text i { + display: inline-block; + padding-left: 1rem; + font-weight: 200; + color: var(--pf-c-dual-list-selector--selection-desc--Color); + font-size: var(--pf-global--FontSize--xs); + } +`; diff --git a/web/src/elements/ak-dual-select/constants.ts b/web/src/elements/ak-dual-select/constants.ts new file mode 100644 index 0000000000..8e7db5369d --- /dev/null +++ b/web/src/elements/ak-dual-select/constants.ts @@ -0,0 +1,7 @@ +export const EVENT_ADD_SELECTED = "ak-dual-select-add"; +export const EVENT_REMOVE_SELECTED = "ak-dual-select-remove"; +export const EVENT_ADD_ALL = "ak-dual-select-add-all"; +export const EVENT_REMOVE_ALL = "ak-dual-select-remove-all"; +export const EVENT_DELETE_ALL = "ak-dual-select-remove-everything"; +export const EVENT_ADD_ONE = "ak-dual-select-add-one"; +export const EVENT_REMOVE_ONE = "ak-dual-select-remove-one"; diff --git a/web/src/elements/ak-dual-select/index.ts b/web/src/elements/ak-dual-select/index.ts new file mode 100644 index 0000000000..a5b14dabc3 --- /dev/null +++ b/web/src/elements/ak-dual-select/index.ts @@ -0,0 +1,7 @@ +import { AkDualSelect } from "./ak-dual-select"; +import "./ak-dual-select"; +import { AkDualSelectProvider } from "./ak-dual-select-provider"; +import "./ak-dual-select-provider"; + +export { AkDualSelect, AkDualSelectProvider }; +export default AkDualSelect; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select-available-pane.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select-available-pane.stories.ts new file mode 100644 index 0000000000..e0f9a0b0e0 --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select-available-pane.stories.ts @@ -0,0 +1,115 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; +import { slug } from "github-slugger"; + +import { TemplateResult, html } from "lit"; + +import "../components/ak-dual-select-available-pane"; +import { AkDualSelectAvailablePane } from "../components/ak-dual-select-available-pane"; +import "./sb-host-provider"; + +const metadata: Meta = { + title: "Elements / Dual Select / Available Items Pane", + component: "ak-dual-select-available-pane", + parameters: { + docs: { + description: { + component: "The vertical panel separating two dual-select elements.", + }, + }, + }, + argTypes: { + options: { + type: "string", + description: "An array of [key, label] pairs of what to show", + }, + selected: { + type: "string", + description: "An array of [key] of what has already been selected", + }, + toMove: { + type: "string", + description: "An array of items which are to be moved to the receiving pane.", + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
      + + + ${testItem} +

      Messages received from the button:

      +
        +
        `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleMoveChanged = (result: any) => { + const target = document.querySelector("#action-button-message-pad"); + target!.innerHTML = ""; + result.detail.forEach((key: string) => { + target!.append(new DOMParser().parseFromString(`
      • ${key}
      • `, "text/xml").firstChild!); + }); +}; + +window.addEventListener("ak-dual-select-available-move-changed", handleMoveChanged); + +type Story = StoryObj; + +const goodForYou = [ + "Apple", + "Arrowroot", + "Artichoke", + "Arugula", + "Asparagus", + "Avocado", + "Bamboo", + "Banana", + "Basil", + "Beet Root", + "Blackberry", + "Blueberry", + "Bok Choy", + "Broccoli", + "Brussels sprouts", + "Cabbage", + "Cantaloupes", + "Carrot", + "Cauliflower", +]; + +const goodForYouPairs = goodForYou.map((key) => [slug(key), key]); + +export const Default: Story = { + render: () => + container( + html` `, + ), +}; + +const someSelected = new Set([ + goodForYouPairs[2][0], + goodForYouPairs[8][0], + goodForYouPairs[14][0], +]); + +export const SomeSelected: Story = { + render: () => + container( + html` `, + ), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select-controls.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select-controls.stories.ts new file mode 100644 index 0000000000..ad89d535bc --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select-controls.stories.ts @@ -0,0 +1,101 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; + +import { TemplateResult, html } from "lit"; + +import "../components/ak-dual-select-controls"; +import { AkDualSelectControls } from "../components/ak-dual-select-controls"; + +const metadata: Meta = { + title: "Elements / Dual Select / Control Panel", + component: "ak-dual-select-controls", + parameters: { + docs: { + description: { + component: "The vertical panel separating two dual-select elements.", + }, + }, + }, + argTypes: { + addActive: { + type: "boolean", + description: + "Highlighted if the sample panel has something to move to the result panel.", + }, + removeActive: { + type: "boolean", + description: + "Highlighted if the result panel has something to move to the sample panel.", + }, + selectAll: { + type: "boolean", + description: "Enable if you want both the 'move all visible' buttons.", + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
        + + + ${testItem} +

        Messages received from the button:

        +
          +
          `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const displayMessage = (result: any) => { + const doc = new DOMParser().parseFromString(`
        • Event: ${result}
        • `, "text/xml"); + const target = document.querySelector("#action-button-message-pad"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + target!.appendChild(doc.firstChild!); +}; + +window.addEventListener("ak-dual-select-add", () => displayMessage("add")); +window.addEventListener("ak-dual-select-remove", () => displayMessage("remove")); +window.addEventListener("ak-dual-select-add-all", () => displayMessage("add all")); +window.addEventListener("ak-dual-select-remove-all", () => displayMessage("remove all")); + +type Story = StoryObj; + +export const Default: Story = { + render: () => container(html` `), +}; + +export const AddActive: Story = { + render: () => container(html` `), +}; + +export const RemoveActive: Story = { + render: () => + container(html` `), +}; + +export const AddAllActive: Story = { + render: () => + container( + html` `, + ), +}; + +export const RemoveAllActive: Story = { + render: () => + container( + html` `, + ), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select-master.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select-master.stories.ts new file mode 100644 index 0000000000..2c66139805 --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select-master.stories.ts @@ -0,0 +1,156 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; +import { slug } from "github-slugger"; + +import { LitElement, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; + +import { Pagination } from "@goauthentik/api"; + +import "../ak-dual-select"; +import { AkDualSelect } from "../ak-dual-select"; +import type { DualSelectPair } from "../types"; + +const goodForYouRaw = ` +Apple, Arrowroot, Artichoke, Arugula, Asparagus, Avocado, Bamboo, Banana, Basil, Beet Root, +Blackberry, Blueberry, Bok Choy, Broccoli, Brussels sprouts, Cabbage, Cantaloupes, Carrot, +Cauliflower, Celery, Chayote, Chives, Cilantro, Coconut, Collard Greens, Corn, Cucumber, Daikon, +Date, Dill, Eggplant, Endive, Fennel, Fig, Garbanzo Bean, Garlic, Ginger, Gourds, Grape, Guava, +Honeydew, Horseradish, Iceberg Lettuce, Jackfruit, Jicama, Kale, Kangkong, Kiwi, Kohlrabi, Leek, +Lentils, Lychee, Macadamia, Mango, Mushroom, Mustard, Nectarine, Okra, Onion, Papaya, Parsley, +Parsley root, Parsnip, Passion Fruit, Peach, Pear, Peas, Peppers, Persimmon, Pimiento, Pineapple, +Plum, Plum, Pomegranate, Potato, Pumpkin, Radicchio, Radish, Raspberry, Rhubarb, Romaine Lettuce, +Rosemary, Rutabaga, Shallot, Soybeans, Spinach, Squash, Strawberries, Sweet potato, Swiss Chard, +Thyme, Tomatillo, Tomato, Turnip, Waterchestnut, Watercress, Watermelon, Yams +`; + +const keyToPair = (key: string): DualSelectPair => [slug(key), key]; +const goodForYou: DualSelectPair[] = goodForYouRaw + .split("\n") + .join(" ") + .split(",") + .map((a: string) => a.trim()) + .map(keyToPair); + +const metadata: Meta = { + title: "Elements / Dual Select / Dual Select With Pagination", + component: "ak-dual-select", + parameters: { + docs: { + description: { + component: "The three-panel assembly", + }, + }, + }, + argTypes: { + options: { + type: "string", + description: "An array of [key, label] pairs of what to show", + }, + selected: { + type: "string", + description: "An array of [key] of what has already been selected", + }, + pages: { + type: "string", + description: "An authentik pagination object.", + }, + }, +}; + +export default metadata; + +@customElement("ak-sb-fruity") +export class AkSbFruity extends LitElement { + @property({ type: Array }) + options: DualSelectPair[] = goodForYou; + + @property({ attribute: "page-length", type: Number }) + pageLength = 20; + + @state() + page: Pagination; + + constructor() { + super(); + this.page = { + count: this.options.length, + current: 1, + startIndex: 1, + endIndex: this.options.length > this.pageLength ? this.pageLength : this.options.length, + next: this.options.length > this.pageLength ? 2 : 0, + previous: 0, + totalPages: Math.ceil(this.options.length / this.pageLength), + }; + this.onNavigation = this.onNavigation.bind(this); + this.addEventListener("ak-pagination-nav-to", this.onNavigation); + } + + onNavigation(evt: Event) { + const current: number = (evt as CustomEvent).detail; + const index = current - 1; + if (index * this.pageLength > this.options.length) { + console.warn( + `Attempted to index from ${index} for options length ${this.options.length}`, + ); + return; + } + const endCount = this.pageLength * (index + 1); + const endIndex = Math.min(endCount, this.options.length); + + this.page = { + ...this.page, + current, + startIndex: this.pageLength * index + 1, + endIndex, + next: (index + 1) * this.pageLength > this.options.length ? 0 : current + 1, + previous: index, + }; + } + + get pageoptions() { + return this.options.slice( + this.pageLength * (this.page.current - 1), + this.pageLength * this.page.current, + ); + } + + render() { + return html``; + } +} + +const container = (testItem: TemplateResult) => + html`
          + + + ${testItem} +

          Messages received from the button:

          +
          +
          `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleMoveChanged = (result: any) => { + const target = document.querySelector("#action-button-message-pad"); + target!.innerHTML = ""; + // @ts-ignore + target!.append(result.detail.value.map(([k, _]) => k).join(", ")); +}; + +window.addEventListener("change", handleMoveChanged); + +type Story = StoryObj; + +export const Default: Story = { + render: () => container(html` `), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select-search.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select-search.stories.ts new file mode 100644 index 0000000000..49bf52fc54 --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select-search.stories.ts @@ -0,0 +1,70 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { debounce } from "@goauthentik/elements/utils/debounce"; +import { Meta, StoryObj } from "@storybook/web-components"; + +import { TemplateResult, html } from "lit"; + +import "../components/ak-search-bar"; +import { AkSearchbar } from "../components/ak-search-bar"; + +const metadata: Meta = { + title: "Elements / Dual Select / Search Bar", + component: "ak-dual-select-search", + parameters: { + docs: { + description: { + component: "A search input bar", + }, + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
          + + + ${testItem} +

          Messages received from the button:

          +
          +
          +
          `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const displayMessage = (result: any) => { + const doc = new DOMParser().parseFromString(`

          Content: ${result}

          `, "text/xml"); + const target = document.querySelector("#action-button-message-pad"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + target!.replaceChildren(doc.firstChild!); +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const displayMessage2 = (result: any) => { + console.debug("Huh."); + const doc = new DOMParser().parseFromString(`

          Behavior: ${result}

          `, "text/xml"); + const target = document.querySelector("#action-button-message-pad-2"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + target!.replaceChildren(doc.firstChild!); +}; + +const displayMessage2b = debounce(displayMessage2, 250); + +window.addEventListener("input", (event: Event) => { + const message = (event.target as HTMLInputElement | undefined)?.value ?? "-- undefined --"; + displayMessage(message); + displayMessage2b(message); +}); + +type Story = StoryObj; + +export const Default: Story = { + render: () => container(html` `), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select-selected-pane.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select-selected-pane.stories.ts new file mode 100644 index 0000000000..4dc6ef9c3b --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select-selected-pane.stories.ts @@ -0,0 +1,96 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; +import { slug } from "github-slugger"; + +import { TemplateResult, html } from "lit"; + +import "../components/ak-dual-select-selected-pane"; +import { AkDualSelectSelectedPane } from "../components/ak-dual-select-selected-pane"; +import "./sb-host-provider"; + +const metadata: Meta = { + title: "Elements / Dual Select / Selected Items Pane", + component: "ak-dual-select-selected-pane", + parameters: { + docs: { + description: { + component: "The vertical panel separating two dual-select elements.", + }, + }, + }, + argTypes: { + // @ts-ignore + options: { + type: "string", + description: "An array of [key, label] pairs of what to show", + }, + toMove: { + type: "string", + description: "An array of items which are to be moved to the receiving pane.", + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
          + + + ${testItem} +

          Messages received from the button:

          +
            +
            `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleMoveChanged = (result: any) => { + const target = document.querySelector("#action-button-message-pad"); + target!.innerHTML = ""; + result.detail.forEach((key: string) => { + target!.append(new DOMParser().parseFromString(`
          • ${key}
          • `, "text/xml").firstChild!); + }); +}; + +window.addEventListener("ak-dual-select-selected-move-changed", handleMoveChanged); + +type Story = StoryObj; + +const goodForYou = [ + "Apple", + "Arrowroot", + "Artichoke", + "Arugula", + "Asparagus", + "Avocado", + "Bamboo", + "Banana", + "Basil", + "Beet Root", + "Blackberry", + "Blueberry", + "Bok Choy", + "Broccoli", + "Brussels sprouts", + "Cabbage", + "Cantaloupes", + "Carrot", + "Cauliflower", +]; + +const goodForYouPairs = goodForYou.map((key) => [slug(key), key]); + +export const Default: Story = { + render: () => + container( + html` `, + ), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-dual-select.stories.ts b/web/src/elements/ak-dual-select/stories/ak-dual-select.stories.ts new file mode 100644 index 0000000000..67c0cb3d03 --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-dual-select.stories.ts @@ -0,0 +1,93 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; +import { slug } from "github-slugger"; + +import { TemplateResult, html } from "lit"; + +import "../ak-dual-select"; +import { AkDualSelect } from "../ak-dual-select"; + +const metadata: Meta = { + title: "Elements / Dual Select / Dual Select", + component: "ak-dual-select", + parameters: { + docs: { + description: { + component: "The three-panel assembly", + }, + }, + }, + argTypes: { + options: { + type: "string", + description: "An array of [key, label] pairs of what to show", + }, + selected: { + type: "string", + description: "An array of [key] of what has already been selected", + }, + pages: { + type: "string", + description: "An authentik pagination object.", + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
            + + + ${testItem} +

            Messages received from the button:

            +
              +
              `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleMoveChanged = (result: any) => { + const target = document.querySelector("#action-button-message-pad"); + target!.innerHTML = ""; + result.detail.value.forEach((key: string) => { + target!.append(new DOMParser().parseFromString(`
            • ${key}
            • `, "text/xml").firstChild!); + }); +}; + +window.addEventListener("change", handleMoveChanged); + +type Story = StoryObj; + +const goodForYou = [ + "Apple", + "Arrowroot", + "Artichoke", + "Arugula", + "Asparagus", + "Avocado", + "Bamboo", + "Banana", + "Basil", + "Beet Root", + "Blackberry", + "Blueberry", + "Bok Choy", + "Broccoli", + "Brussels sprouts", + "Cabbage", + "Cantaloupes", + "Carrot", + "Cauliflower", +]; + +const goodForYouPairs = goodForYou.map((key) => [slug(key), key]); + +export const Default: Story = { + render: () => container(html` `), +}; diff --git a/web/src/elements/ak-dual-select/stories/ak-pagination.stories.ts b/web/src/elements/ak-dual-select/stories/ak-pagination.stories.ts new file mode 100644 index 0000000000..0ecbe68af9 --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/ak-pagination.stories.ts @@ -0,0 +1,83 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta, StoryObj } from "@storybook/web-components"; + +import { TemplateResult, html } from "lit"; + +import "../components/ak-pagination"; +import { AkPagination } from "../components/ak-pagination"; + +const metadata: Meta = { + title: "Elements / Dual Select / Pagination Control", + component: "ak-pagination", + parameters: { + docs: { + description: { + component: "The Pagination Control", + }, + }, + }, + argTypes: { + pages: { + type: "string", + description: "An authentik Pagination struct", + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
              + + + ${testItem} +

              Messages received from the button:

              +
                +
                `; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleMoveChanged = (result: any) => { + console.debug(result); + const target = document.querySelector("#action-button-message-pad"); + target!.append( + new DOMParser().parseFromString( + `
              • Request to move to page ${result.detail}
              • `, + "text/xml", + ).firstChild!, + ); +}; + +window.addEventListener("ak-pagination-nav-to", handleMoveChanged); + +type Story = StoryObj; + +const pages = { + count: 44, + startIndex: 1, + endIndex: 20, + next: 2, + previous: 0, +}; + +export const Default: Story = { + render: () => container(html` `), +}; + +const morePages = { + count: 86, + startIndex: 21, + endIndex: 40, + next: 3, + previous: 1, +}; + +export const More: Story = { + render: () => container(html` `), +}; diff --git a/web/src/elements/ak-dual-select/stories/sb-host-provider.ts b/web/src/elements/ak-dual-select/stories/sb-host-provider.ts new file mode 100644 index 0000000000..985d9083dc --- /dev/null +++ b/web/src/elements/ak-dual-select/stories/sb-host-provider.ts @@ -0,0 +1,22 @@ +import { LitElement, html } from "lit"; +import { customElement } from "lit/decorators.js"; + +import { globalVariables } from "../components/styles.css"; + +/** + * @element sb-dual-select-host-provider + * + * A *very simple* wrapper which provides the CSS Custom Properties used by the components when + * being displayed in Storybook or Vite. Not needed for the parent widget since it provides these by itself. + */ + +@customElement("sb-dual-select-host-provider") +export class SbHostProvider extends LitElement { + static get styles() { + return globalVariables; + } + + render() { + return html``; + } +} diff --git a/web/src/elements/ak-dual-select/types.ts b/web/src/elements/ak-dual-select/types.ts new file mode 100644 index 0000000000..2e7cea13a0 --- /dev/null +++ b/web/src/elements/ak-dual-select/types.ts @@ -0,0 +1,26 @@ +import { TemplateResult } from "lit"; + +import { Pagination } from "@goauthentik/api"; + +// Key, Label (string or TemplateResult), (optional) string to sort by. If the sort string is +// missing, it will use the label, which doesn't always work for TemplateResults). +export type DualSelectPair = [string, string | TemplateResult, string?]; + +export type BasePagination = Pick< + Pagination, + "startIndex" | "endIndex" | "count" | "previous" | "next" +>; + +export type DataProvision = { + pagination: Pagination; + options: DualSelectPair[]; +}; + +export type DataProvider = (page: number, search?: string) => Promise; + +export interface SearchbarEvent extends CustomEvent { + detail: { + source: string; + value: string; + }; +} diff --git a/web/src/elements/ak-locale-context/ak-locale-context.ts b/web/src/elements/ak-locale-context/ak-locale-context.ts index 912d6b711a..c01c9c29fc 100644 --- a/web/src/elements/ak-locale-context/ak-locale-context.ts +++ b/web/src/elements/ak-locale-context/ak-locale-context.ts @@ -1,18 +1,15 @@ -import { EVENT_LOCALE_CHANGE } from "@goauthentik/common/constants"; -import { EVENT_LOCALE_REQUEST } from "@goauthentik/common/constants"; -import { customEvent, isCustomEvent } from "@goauthentik/elements/utils/customEvents"; +import { EVENT_LOCALE_CHANGE, EVENT_LOCALE_REQUEST } from "@goauthentik/common/constants"; +import { customEvent } from "@goauthentik/elements/utils/customEvents"; import { LitElement, html } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { WithBrandConfig } from "../Interface/brandProvider"; import { initializeLocalization } from "./configureLocale"; import type { LocaleGetter, LocaleSetter } from "./configureLocale"; -import { - DEFAULT_LOCALE, - autoDetectLanguage, - getBestMatchLocale, - localeCodeFromUrl, -} from "./helpers"; +import { DEFAULT_LOCALE, autoDetectLanguage, getBestMatchLocale } from "./helpers"; + +const LocaleContextBase = WithBrandConfig(LitElement); /** * A component to manage your locale settings. @@ -28,7 +25,7 @@ import { * @fires ak-locale-change - When a valid locale has been swapped in */ @customElement("ak-locale-context") -export class LocaleContext extends LitElement { +export class LocaleContext extends LocaleContextBase { /// @attribute The text representation of the current locale */ @property({ attribute: true, type: String }) locale = DEFAULT_LOCALE; @@ -59,38 +56,28 @@ export class LocaleContext extends LitElement { connectedCallback() { super.connectedCallback(); - const localeRequest = autoDetectLanguage(this.locale); - this.updateLocale(localeRequest); - window.addEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler); + this.updateLocale(); + window.addEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler as EventListener); } disconnectedCallback() { - window.removeEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler); + window.removeEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler as EventListener); super.disconnectedCallback(); } - updateLocaleHandler(ev: Event) { - if (!isCustomEvent(ev)) { - console.warn(`Received a non-custom event at EVENT_LOCALE_REQUEST: ${ev}`); - return; - } + updateLocaleHandler(ev: CustomEvent<{ locale: string }>) { console.debug("authentik/locale: Locale update request received."); this.updateLocale(ev.detail.locale); } - updateLocale(code: string) { - const urlCode = localeCodeFromUrl(this.param); - const requestedLocale = urlCode ? urlCode : code; - const locale = getBestMatchLocale(requestedLocale); + updateLocale(requestedLocale: string | undefined = undefined) { + const localeRequest = autoDetectLanguage(requestedLocale, this.brand?.defaultLocale); + const locale = getBestMatchLocale(localeRequest); if (!locale) { - console.warn(`authentik/locale: failed to find locale for code ${code}`); + console.warn(`authentik/locale: failed to find locale for code ${localeRequest}`); return; } locale.locale().then(() => { - console.debug(`authentik/locale: Loaded locale '${code}'`); - if (this.getLocale() === code) { - return; - } console.debug(`Setting Locale to ... ${locale.label()} (${locale.code})`); this.setLocale(locale.code).then(() => { window.setTimeout(this.notifyApplication, 0); diff --git a/web/src/elements/ak-locale-context/configureLocale.ts b/web/src/elements/ak-locale-context/configureLocale.ts index 21f244668e..ddf47c85b1 100644 --- a/web/src/elements/ak-locale-context/configureLocale.ts +++ b/web/src/elements/ak-locale-context/configureLocale.ts @@ -1,7 +1,6 @@ -import { sourceLocale, targetLocales } from "@goauthentik/app/locale-codes"; - import { configureLocalization } from "@lit/localize"; +import { sourceLocale, targetLocales } from "../../locale-codes"; import { getBestMatchLocale } from "./helpers"; type LocaleGetter = ReturnType["getLocale"]; diff --git a/web/src/elements/ak-locale-context/context.ts b/web/src/elements/ak-locale-context/context.ts index 9c9903bb33..e63b67e7dc 100644 --- a/web/src/elements/ak-locale-context/context.ts +++ b/web/src/elements/ak-locale-context/context.ts @@ -1,4 +1,4 @@ -import { createContext } from "@lit-labs/context"; +import { createContext } from "@lit/context"; export const localeContext = createContext("locale"); export default localeContext; diff --git a/web/src/elements/ak-locale-context/helpers.ts b/web/src/elements/ak-locale-context/helpers.ts index 51ef765095..751371485a 100644 --- a/web/src/elements/ak-locale-context/helpers.ts +++ b/web/src/elements/ak-locale-context/helpers.ts @@ -45,12 +45,13 @@ export function localeCodeFromUrl(param = "locale") { const isLocaleCandidate = (v: unknown): v is string => typeof v === "string" && v !== "" && v !== TOMBSTONE; -export function autoDetectLanguage(requestedCode?: string): string { +export function autoDetectLanguage(userReq = TOMBSTONE, brandReq = TOMBSTONE): string { const localeCandidates: string[] = [ - globalAK()?.locale ?? TOMBSTONE, localeCodeFromUrl("locale"), - requestedCode ?? TOMBSTONE, + userReq, window.navigator?.language ?? TOMBSTONE, + brandReq, + globalAK()?.locale ?? TOMBSTONE, DEFAULT_LOCALE, ].filter(isLocaleCandidate); diff --git a/web/src/elements/buttons/ModalButton.ts b/web/src/elements/buttons/ModalButton.ts index dfc594e2ce..1fb4a059af 100644 --- a/web/src/elements/buttons/ModalButton.ts +++ b/web/src/elements/buttons/ModalButton.ts @@ -1,5 +1,9 @@ +import { PFSize } from "@goauthentik/common/enums.js"; import { AKElement } from "@goauthentik/elements/Base"; -import { PFSize } from "@goauthentik/elements/Spinner"; +import { + ModalHideEvent, + ModalShowEvent, +} from "@goauthentik/elements/controllers/ModalOrchestrationController.js"; import { CSSResult, TemplateResult, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; @@ -65,22 +69,9 @@ export class ModalButton extends AKElement { ]; } - firstUpdated(): void { - if (this.handlerBound) return; - window.addEventListener("keyup", this.keyUpHandler); - this.handlerBound = true; - } - - keyUpHandler = (e: KeyboardEvent): void => { - if (e.code === "Escape") { - this.resetForms(); - this.open = false; - } - }; - - disconnectedCallback(): void { - super.disconnectedCallback(); - window.removeEventListener("keyup", this.keyUpHandler); + closeModal() { + this.resetForms(); + this.open = false; } resetForms(): void { @@ -93,6 +84,7 @@ export class ModalButton extends AKElement { onClick(): void { this.open = true; + this.dispatchEvent(new ModalShowEvent(this)); this.querySelectorAll("*").forEach((child) => { if ("requestUpdate" in child) { (child as AKElement).requestUpdate(); @@ -119,8 +111,7 @@ export class ModalButton extends AKElement { >
                +
                `; } } diff --git a/web/src/elements/cards/AggregatePromiseCard.ts b/web/src/elements/cards/AggregatePromiseCard.ts index 481edb2592..f3ea049210 100644 --- a/web/src/elements/cards/AggregatePromiseCard.ts +++ b/web/src/elements/cards/AggregatePromiseCard.ts @@ -1,4 +1,4 @@ -import { PFSize } from "@goauthentik/elements/Spinner"; +import { PFSize } from "@goauthentik/common/enums.js"; import "@goauthentik/elements/Spinner"; import { AggregateCard } from "@goauthentik/elements/cards/AggregateCard"; diff --git a/web/src/elements/charts/Chart.ts b/web/src/elements/charts/Chart.ts index 0501db22a2..4a12b376c0 100644 --- a/web/src/elements/charts/Chart.ts +++ b/web/src/elements/charts/Chart.ts @@ -1,4 +1,5 @@ import { EVENT_REFRESH, EVENT_THEME_CHANGE } from "@goauthentik/common/constants"; +import { getRelativeTime } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; import { @@ -18,7 +19,7 @@ import { ArcElement, BarElement } from "chart.js"; import { LinearScale, TimeScale } from "chart.js"; import "chartjs-adapter-moment"; -import { msg, str } from "@lit/localize"; +import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; import { property, state } from "lit/decorators.js"; @@ -161,14 +162,13 @@ export abstract class AKChart extends AKElement { timeTickCallback(tickValue: string | number, index: number, ticks: Tick[]): string { const valueStamp = ticks[index]; - const delta = Date.now() - valueStamp.value; - const ago = Math.round(delta / 1000 / 3600); - return msg(str`${ago} hour(s) ago`); + return getRelativeTime(new Date(valueStamp.value)); } getOptions(): ChartOptions { return { maintainAspectRatio: false, + responsive: true, scales: { x: { type: "time", diff --git a/web/src/elements/controllers/ModalOrchestrationController.ts b/web/src/elements/controllers/ModalOrchestrationController.ts new file mode 100644 index 0000000000..3119ee95cb --- /dev/null +++ b/web/src/elements/controllers/ModalOrchestrationController.ts @@ -0,0 +1,122 @@ +import { bound } from "@goauthentik/elements/decorators/bound.js"; + +import { LitElement, ReactiveController, ReactiveControllerHost } from "lit"; + +type ReactiveElementHost = Partial & LitElement; + +type ModalElement = LitElement & { closeModal(): void | boolean }; + +export class ModalShowEvent extends Event { + modal: ModalElement; + constructor(modal: ModalElement) { + super("ak-modal-show", { bubbles: true, composed: true }); + this.modal = modal; + } +} + +export class ModalHideEvent extends Event { + modal: ModalElement; + constructor(modal: ModalElement) { + super("ak-modal-hide", { bubbles: true, composed: true }); + this.modal = modal; + } +} + +declare global { + interface GlobalEventHandlersEventMap { + "ak-modal-show": ModalShowEvent; + "ak-modal-hide": ModalHideEvent; + } +} + +const modalIsLive = (modal: ModalElement) => modal.isConnected && modal.checkVisibility(); + +/** + * class ModalOrchetrationController + * + * A top-level controller that listens for requests from modals to be added to + * the management list, such that the *topmost* modal will be closed (and all + * references to it eliminated) whenever the user presses the Escape key. + * Can also take ModalHideEvent requests and automatically close the modal + * sending the event. + * + * Both events that this responds to expect a reference to the modal to be part + * of the event payload. + * + * If the `.closeModal()` method on the target modal returns `false` + * *explicitly*, it will abort cleanup and the stack will keep the record that + * the modal is still open. This allows `.closeModal()` to return `undefined` + * and still behave correctly. + */ + +export class ModalOrchestrationController implements ReactiveController { + host!: ReactiveElementHost; + + knownModals: ModalElement[] = []; + + constructor(host: ReactiveElementHost) { + this.host = host; + host.addController(this); + } + + hostConnected() { + window.addEventListener("keyup", this.handleKeyup); + window.addEventListener("ak-modal-show", this.addModal); + window.addEventListener("ak-modal-hide", this.closeModal); + } + + hostDisconnected() { + window.removeEventListener("keyup", this.handleKeyup); + window.removeEventListener("ak-modal-show", this.addModal); + window.removeEventListener("ak-modal-hide", this.closeModal); + } + + @bound + addModal(e: ModalShowEvent) { + this.knownModals = [...this.knownModals, e.modal]; + } + + scheduleCleanup(modal: ModalElement) { + setTimeout(() => { + this.knownModals = this.knownModals.filter((m) => modalIsLive(m) && modal !== m); + }, 0); + } + + @bound + closeModal(e: ModalHideEvent) { + const modal = e.modal; + if (!modalIsLive(modal)) { + return; + } + if (modal.closeModal() !== false) { + this.scheduleCleanup(modal); + } + } + + removeTopmostModal() { + let checking = true; + while (checking) { + const modal = this.knownModals.pop(); + if (!modal) { + break; + } + if (!modalIsLive(modal)) { + continue; + } + + if (modal.closeModal() !== false) { + this.scheduleCleanup(modal); + } + checking = false; + break; + } + } + + @bound + handleKeyup(e: KeyboardEvent) { + // The latter handles Firefox 37 and earlier. + if (e.key === "Escape" || e.key === "Esc") { + this.removeTopmostModal(); + } + } +} diff --git a/web/src/elements/decorators/bound.ts b/web/src/elements/decorators/bound.ts new file mode 100644 index 0000000000..52adbee68b --- /dev/null +++ b/web/src/elements/decorators/bound.ts @@ -0,0 +1,31 @@ +// Automatically binds a method to the `this` instance during instantiation. +// Uses the Typescript Experimental Decorator syntax, so we may be living with +// that for a long time. + +// MDN is *not* very helpful. The type for a PropertyDescriptor is kept in +// typescript/lib/lib.es5.d.ts, but the description of what everything in +// a descriptor does isn't specified in MDN in its own page, only in +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty + +// This decorator feels awkward. It gets a new instance of the method every time +// you reference the field. I wonder if there would be a way to create a lookup +// table; once you'd bound the method you could reuse that bound method for that +// instance, instead of throwing it away? + +export function bound( + target: unknown, + key: string, + descriptor: PropertyDescriptor, +): PropertyDescriptor { + if (typeof descriptor?.value !== "function") { + throw new Error("Only methods can be @bound."); + } + return { + configurable: true, + get() { + const method = descriptor.value.bind(this); + Object.defineProperty(this, key, { value: method, configurable: true, writable: true }); + return method; + }, + }; +} diff --git a/web/src/elements/enterprise/EnterpriseStatusBanner.ts b/web/src/elements/enterprise/EnterpriseStatusBanner.ts index 09d376759e..b3360fb59a 100644 --- a/web/src/elements/enterprise/EnterpriseStatusBanner.ts +++ b/web/src/elements/enterprise/EnterpriseStatusBanner.ts @@ -1,19 +1,14 @@ -import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { AKElement } from "@goauthentik/elements/Base"; +import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; +import { customElement, property } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; -import { EnterpriseApi, LicenseSummary } from "@goauthentik/api"; - @customElement("ak-enterprise-status") -export class EnterpriseStatusBanner extends AKElement { - @state() - summary?: LicenseSummary; - +export class EnterpriseStatusBanner extends WithLicenseSummary(AKElement) { @property() interface: "admin" | "user" | "" = ""; @@ -21,12 +16,10 @@ export class EnterpriseStatusBanner extends AKElement { return [PFBanner]; } - async firstUpdated(): Promise { - this.summary = await new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve(); - } - renderBanner(): TemplateResult { - return html`
                + return html`
                ${msg("Warning: The current user count has exceeded the configured licenses.")} ${msg("Click here for more info.")}
                `; @@ -35,12 +28,12 @@ export class EnterpriseStatusBanner extends AKElement { render(): TemplateResult { switch (this.interface.toLowerCase()) { case "admin": - if (this.summary?.showAdminWarning || this.summary?.readOnly) { + if (this.licenseSummary?.showAdminWarning || this.licenseSummary?.readOnly) { return this.renderBanner(); } break; case "user": - if (this.summary?.showUserWarning || this.summary?.readOnly) { + if (this.licenseSummary?.showUserWarning || this.licenseSummary?.readOnly) { return this.renderBanner(); } break; diff --git a/web/src/elements/events/LogViewer.ts b/web/src/elements/events/LogViewer.ts new file mode 100644 index 0000000000..c49eb559c8 --- /dev/null +++ b/web/src/elements/events/LogViewer.ts @@ -0,0 +1,114 @@ +import { getRelativeTime } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-status-label"; +import "@goauthentik/elements/EmptyState"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; + +import { LogEvent, LogLevelEnum } from "@goauthentik/api"; + +@customElement("ak-log-viewer") +export class LogViewer extends Table { + @property({ attribute: false }) + logs?: LogEvent[] = []; + + expandable = true; + paginated = false; + + static get styles(): CSSResult[] { + return super.styles.concat(PFDescriptionList); + } + + async apiEndpoint(_page: number): Promise> { + return { + pagination: { + next: 0, + previous: 0, + count: this.logs?.length || 0, + current: 1, + totalPages: 1, + startIndex: 1, + endIndex: this.logs?.length || 0, + }, + results: this.logs || [], + }; + } + + renderEmpty(): TemplateResult { + return super.renderEmpty( + html` `, + ); + } + + renderExpanded(item: LogEvent): TemplateResult { + return html`
                `; + } + + renderToolbarContainer(): TemplateResult { + return html``; + } + + columns(): TableColumn[] { + return [ + new TableColumn(msg("Time")), + new TableColumn(msg("Level")), + new TableColumn(msg("Event")), + new TableColumn(msg("Logger")), + ]; + } + + statusForItem(item: LogEvent): string { + switch (item.logLevel) { + case LogLevelEnum.Critical: + case LogLevelEnum.Error: + case LogLevelEnum.Exception: + return "error"; + case LogLevelEnum.Warn: + case LogLevelEnum.Warning: + return "warning"; + default: + return "info"; + } + } + + row(item: LogEvent): TemplateResult[] { + return [ + html`${getRelativeTime(item.timestamp)}`, + html``, + html`${item.event}`, + html`${item.logger}`, + ]; + } +} diff --git a/web/src/elements/forms/DeleteBulkForm.ts b/web/src/elements/forms/DeleteBulkForm.ts index 693184b715..c76f2e9e24 100644 --- a/web/src/elements/forms/DeleteBulkForm.ts +++ b/web/src/elements/forms/DeleteBulkForm.ts @@ -1,6 +1,6 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { PFSize } from "@goauthentik/common/enums.js"; import { MessageLevel } from "@goauthentik/common/messages"; -import { PFSize } from "@goauthentik/elements/Spinner"; import { ModalButton } from "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/SpinnerButton"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; @@ -131,6 +131,15 @@ export class DeleteBulkForm extends ModalButton { @property() actionSubtext?: string; + @property() + buttonLabel = msg("Delete"); + + /** + * Action shown in messages, for example `deleted` or `removed` + */ + @property() + action = msg("deleted"); + @property({ attribute: false }) metadata: (item: T) => BulkDeleteMetadata = (item: T) => { const rec = item as Record; @@ -222,7 +231,7 @@ export class DeleteBulkForm extends ModalButton { }} class="pf-m-danger" > - ${msg("Delete")}   { diff --git a/web/src/elements/forms/Form.ts b/web/src/elements/forms/Form.ts index d465a24350..7f08433ea9 100644 --- a/web/src/elements/forms/Form.ts +++ b/web/src/elements/forms/Form.ts @@ -1,10 +1,10 @@ -import { PreventFormSubmit } from "@goauthentik/app/elements/forms/helpers"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { MessageLevel } from "@goauthentik/common/messages"; -import { camelToSnake, convertToSlug } from "@goauthentik/common/utils"; +import { camelToSnake, convertToSlug, dateToUTC } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement"; import { SearchSelect } from "@goauthentik/elements/forms/SearchSelect"; +import { PreventFormSubmit } from "@goauthentik/elements/forms/helpers"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; import { CSSResult, TemplateResult, css, html } from "lit"; @@ -69,7 +69,6 @@ export function serializeForm( return; } - // TODO: Tighten up the typing so that we can handle both. if ("akControl" in element.dataset) { assignValue(element, (element as unknown as AkControlElement).json(), json); return; @@ -79,6 +78,12 @@ export function serializeForm( if (element.hidden || !inputElement) { return; } + + if ("akControl" in inputElement.dataset) { + assignValue(element, (inputElement as unknown as AkControlElement).json(), json); + return; + } + // Skip elements that are writeOnly where the user hasn't clicked on the value if (element.writeOnly && !element.writeOnlyActivated) { return; @@ -99,7 +104,7 @@ export function serializeForm( inputElement.tagName.toLowerCase() === "input" && inputElement.type === "datetime-local" ) { - assignValue(inputElement, new Date(inputElement.valueAsNumber), json); + assignValue(inputElement, dateToUTC(new Date(inputElement.valueAsNumber)), json); } else if ( inputElement.tagName.toLowerCase() === "input" && "type" in inputElement.dataset && @@ -107,7 +112,7 @@ export function serializeForm( ) { // Workaround for Firefox <93, since 92 and older don't support // datetime-local fields - assignValue(inputElement, new Date(inputElement.value), json); + assignValue(inputElement, dateToUTC(new Date(inputElement.value)), json); } else if ( inputElement.tagName.toLowerCase() === "input" && inputElement.type === "checkbox" diff --git a/web/src/elements/forms/HorizontalFormElement.ts b/web/src/elements/forms/HorizontalFormElement.ts index 9d00327daf..c5973d9f19 100644 --- a/web/src/elements/forms/HorizontalFormElement.ts +++ b/web/src/elements/forms/HorizontalFormElement.ts @@ -36,6 +36,22 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; * */ +const isAkControl = (el: unknown): boolean => + el instanceof HTMLElement && + "dataset" in el && + el.dataset instanceof DOMStringMap && + "akControl" in el.dataset; + +const nameables = new Set([ + "input", + "textarea", + "select", + "ak-codemirror", + "ak-chip-group", + "ak-search-select", + "ak-radio", +]); + @customElement("ak-form-element-horizontal") export class HorizontalFormElement extends AKElement { static get styles(): CSSResult[] { @@ -112,19 +128,18 @@ export class HorizontalFormElement extends AKElement { }); } this.querySelectorAll("*").forEach((input) => { - switch (input.tagName.toLowerCase()) { - case "input": - case "textarea": - case "select": - case "ak-codemirror": - case "ak-chip-group": - case "ak-search-select": - case "ak-radio": - input.setAttribute("name", this.name); - break; - default: - return; + if (isAkControl(input) && !input.getAttribute("name")) { + input.setAttribute("name", this.name); + // This is fine; writeOnly won't apply to anything built this way. + return; } + + if (nameables.has(input.tagName.toLowerCase())) { + input.setAttribute("name", this.name); + } else { + return; + } + if (this.writeOnly && !this.writeOnlyActivated) { const i = input as HTMLInputElement; i.setAttribute("hidden", "true"); diff --git a/web/src/elements/forms/ModalForm.ts b/web/src/elements/forms/ModalForm.ts index 1930b7d752..e107729abd 100644 --- a/web/src/elements/forms/ModalForm.ts +++ b/web/src/elements/forms/ModalForm.ts @@ -2,6 +2,7 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants"; import "@goauthentik/elements/LoadingOverlay"; import { ModalButton } from "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/SpinnerButton"; +import { ModalHideEvent } from "@goauthentik/elements/controllers/ModalOrchestrationController.js"; import { Form } from "@goauthentik/elements/forms/Form"; import { msg } from "@lit/localize"; @@ -36,15 +37,15 @@ export class ModalForm extends ModalButton { if (this.closeAfterSuccessfulSubmit) { this.open = false; form?.resetForm(); + this.dispatchEvent( + new CustomEvent(EVENT_REFRESH, { + bubbles: true, + composed: true, + }), + ); } this.loading = false; this.locked = false; - this.dispatchEvent( - new CustomEvent(EVENT_REFRESH, { - bubbles: true, - composed: true, - }), - ); }) .catch((exc) => { this.loading = false; @@ -92,8 +93,7 @@ export class ModalForm extends ModalButton { : html``} { - this.resetForms(); - this.open = false; + this.dispatchEvent(new ModalHideEvent(this)); }} class="pf-m-secondary" > diff --git a/web/src/elements/forms/Radio.ts b/web/src/elements/forms/Radio.ts index 27fbdf0b91..7730b87f77 100644 --- a/web/src/elements/forms/Radio.ts +++ b/web/src/elements/forms/Radio.ts @@ -14,8 +14,9 @@ import { randomId } from "../utils/randomId"; export interface RadioOption { label: string; description?: TemplateResult; - default: boolean; + default?: boolean; value: T; + disabled?: boolean; } @customElement("ak-radio") @@ -77,6 +78,9 @@ export class Radio extends CustomEmitterElement(AKElement) { // This is a controlled input. Stop the native event from escaping or affecting the // value. We'll do that ourselves. ev.stopPropagation(); + if (option.disabled) { + return; + } this.value = option.value; this.dispatchCustomEvent("change", { value: option.value }); this.dispatchCustomEvent("input", { value: option.value }); @@ -93,6 +97,7 @@ export class Radio extends CustomEmitterElement(AKElement) { name="${this.name}" id=${elId} .checked=${option.value === this.value} + .disabled=${option.disabled} /> ${option.description diff --git a/web/src/elements/forms/SearchSelect/ak-search-select.ts b/web/src/elements/forms/SearchSelect/ak-search-select.ts index 94fb1a1db9..5077f713c9 100644 --- a/web/src/elements/forms/SearchSelect/ak-search-select.ts +++ b/web/src/elements/forms/SearchSelect/ak-search-select.ts @@ -1,8 +1,8 @@ -import { APIErrorTypes, parseAPIError } from "@goauthentik/app/common/errors"; -import { PreventFormSubmit } from "@goauthentik/app/elements/forms/helpers"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { APIErrorTypes, parseAPIError } from "@goauthentik/common/errors"; import { ascii_letters, digits, groupBy, randomString } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; +import { PreventFormSubmit } from "@goauthentik/elements/forms/helpers"; import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet"; import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; @@ -175,6 +175,9 @@ export class SearchSelect extends CustomEmitterElement(AKElement) { super.connectedCallback(); this.dropdownContainer = document.createElement("div"); this.dropdownContainer.dataset["managedBy"] = "ak-search-select"; + if (this.name) { + this.dropdownContainer.dataset["managedFor"] = this.name; + } document.body.append(this.dropdownContainer); this.updateData(); this.addEventListener(EVENT_REFRESH, this.updateData); diff --git a/web/src/elements/forms/helpers.ts b/web/src/elements/forms/helpers.ts index 50a4c3002b..afc0432de4 100644 --- a/web/src/elements/forms/helpers.ts +++ b/web/src/elements/forms/helpers.ts @@ -1,4 +1,4 @@ -import { HorizontalFormElement } from "@goauthentik/app/elements/forms/HorizontalFormElement"; +import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement"; export class PreventFormSubmit { // Stub class which can be returned by form elements to prevent the form from submitting diff --git a/web/src/elements/notifications/APIDrawer.ts b/web/src/elements/notifications/APIDrawer.ts index 8f93bd8d2e..20b56f17df 100644 --- a/web/src/elements/notifications/APIDrawer.ts +++ b/web/src/elements/notifications/APIDrawer.ts @@ -25,8 +25,11 @@ export class APIDrawer extends AKElement { PFContent, PFDropdown, css` + :host { + --header-height: 114px; + } .pf-c-notification-drawer__header { - height: 114px; + height: var(--header-height); align-items: center; } .pf-c-notification-drawer__header-action, @@ -41,6 +44,9 @@ export class APIDrawer extends AKElement { .pf-c-notification-drawer__body { overflow-x: hidden; } + .pf-c-notification-drawer__list { + max-height: calc(100vh - var(--header-height)); + } `, ]; } diff --git a/web/src/elements/notifications/NotificationDrawer.ts b/web/src/elements/notifications/NotificationDrawer.ts index e15cf73072..77c5b549f2 100644 --- a/web/src/elements/notifications/NotificationDrawer.ts +++ b/web/src/elements/notifications/NotificationDrawer.ts @@ -3,9 +3,11 @@ import { EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_REFRESH } from "@goauthentik/co import { actionToLabel } from "@goauthentik/common/labels"; import { MessageLevel } from "@goauthentik/common/messages"; import { me } from "@goauthentik/common/users"; +import { getRelativeTime } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; +import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; @@ -132,7 +134,9 @@ export class NotificationDrawer extends AKElement {

                ${item.body}

                ${item.created?.toLocaleString()} + ${getRelativeTime(item.created!)} + `; } diff --git a/web/src/elements/oauth/UserAccessTokenList.ts b/web/src/elements/oauth/UserAccessTokenList.ts new file mode 100644 index 0000000000..95fed88f09 --- /dev/null +++ b/web/src/elements/oauth/UserAccessTokenList.ts @@ -0,0 +1,97 @@ +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-status-label"; +import "@goauthentik/elements/forms/DeleteBulkForm"; +import { PaginatedResponse } from "@goauthentik/elements/table/Table"; +import { Table, TableColumn } from "@goauthentik/elements/table/Table"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css"; + +import { ExpiringBaseGrantModel, Oauth2Api, TokenModel } from "@goauthentik/api"; + +@customElement("ak-user-oauth-access-token-list") +export class UserOAuthAccessTokenList extends Table { + expandable = true; + + @property({ type: Number }) + userId?: number; + + static get styles(): CSSResult[] { + return super.styles.concat(PFFlex); + } + + async apiEndpoint(page: number): Promise> { + return new Oauth2Api(DEFAULT_CONFIG).oauth2AccessTokensList({ + user: this.userId, + ordering: "expires", + page: page, + pageSize: (await uiConfig()).pagination.perPage, + }); + } + + checkbox = true; + order = "-expires"; + + columns(): TableColumn[] { + return [ + new TableColumn(msg("Provider"), "provider"), + new TableColumn(msg("Revoked?"), "revoked"), + new TableColumn(msg("Expires"), "expires"), + new TableColumn(msg("Scopes"), "scope"), + ]; + } + + renderExpanded(item: TokenModel): TemplateResult { + return html`
                + + `; + } + + renderToolbarSelected(): TemplateResult { + const disabled = this.selectedElements.length < 1; + return html` { + return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensUsedByList({ + id: item.pk, + }); + }} + .delete=${(item: ExpiringBaseGrantModel) => { + return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensDestroy({ + id: item.pk, + }); + }} + > + + `; + } + + row(item: TokenModel): TemplateResult[] { + return [ + html` ${item.provider?.name} `, + html``, + html`${item.expires + ? html`
                ${getRelativeTime(item.expires)}
                + ${item.expires.toLocaleString()}` + : msg("-")}`, + html`${item.scope.join(", ")}`, + ]; + } +} diff --git a/web/src/elements/oauth/UserRefreshList.ts b/web/src/elements/oauth/UserRefreshTokenList.ts similarity index 88% rename from web/src/elements/oauth/UserRefreshList.ts rename to web/src/elements/oauth/UserRefreshTokenList.ts index 2c5915f745..741a938a76 100644 --- a/web/src/elements/oauth/UserRefreshList.ts +++ b/web/src/elements/oauth/UserRefreshTokenList.ts @@ -1,5 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import "@goauthentik/elements/forms/DeleteBulkForm"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; @@ -13,8 +14,8 @@ import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css"; import { ExpiringBaseGrantModel, Oauth2Api, TokenModel } from "@goauthentik/api"; -@customElement("ak-user-oauth-refresh-list") -export class UserOAuthRefreshList extends Table { +@customElement("ak-user-oauth-refresh-token-list") +export class UserOAuthRefreshTokenList extends Table { expandable = true; @property({ type: Number }) @@ -34,6 +35,7 @@ export class UserOAuthRefreshList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { @@ -86,7 +88,10 @@ export class UserOAuthRefreshList extends Table { return [ html` ${item.provider?.name} `, html``, - html`${item.expires?.toLocaleString()}`, + html`${item.expires + ? html`
                ${getRelativeTime(item.expires)}
                + ${item.expires.toLocaleString()}` + : msg("-")}`, html`${item.scope.join(", ")}`, ]; } diff --git a/web/src/elements/rbac/ObjectPermissionModal.ts b/web/src/elements/rbac/ObjectPermissionModal.ts index e50be6b829..72dda84d53 100644 --- a/web/src/elements/rbac/ObjectPermissionModal.ts +++ b/web/src/elements/rbac/ObjectPermissionModal.ts @@ -1,4 +1,4 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; +import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/ModalForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/rbac/ObjectPermissionsPage"; @@ -38,6 +38,7 @@ export class ObjectPermissionsPageForm extends ModelForm { .model=${this.model} .objectPk=${this.objectPk} slot="form" + .embedded=${true} > `; } diff --git a/web/src/elements/rbac/ObjectPermissionsPage.ts b/web/src/elements/rbac/ObjectPermissionsPage.ts index a9ebd4d7aa..39443e1a20 100644 --- a/web/src/elements/rbac/ObjectPermissionsPage.ts +++ b/web/src/elements/rbac/ObjectPermissionsPage.ts @@ -1,10 +1,14 @@ -import { AKElement } from "@goauthentik/app/elements/Base"; -import "@goauthentik/app/elements/rbac/RoleObjectPermissionTable"; -import "@goauthentik/app/elements/rbac/UserObjectPermissionTable"; +import "@goauthentik/admin/roles/RoleAssignedGlobalPermissionsTable"; +import "@goauthentik/admin/roles/RoleAssignedObjectPermissionTable"; +import "@goauthentik/admin/users/UserAssignedGlobalPermissionsTable"; +import "@goauthentik/admin/users/UserAssignedObjectPermissionsTable"; +import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Tabs"; +import "@goauthentik/elements/rbac/RoleObjectPermissionTable"; +import "@goauthentik/elements/rbac/UserObjectPermissionTable"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; @@ -24,20 +28,26 @@ export class ObjectPermissionPage extends AKElement { objectPk?: string | number; @property({ type: Boolean }) - showBanner = true; + embedded = false; - static get styles(): CSSResult[] { + static get styles() { return [PFBase, PFGrid, PFPage, PFCard, PFBanner]; } - render(): TemplateResult { - return html`${this.showBanner + render() { + return html`${!this.embedded ? html`
                ${msg("RBAC is in preview.")} ${msg("Send us feedback!")}
                ` - : html``} - + : nothing} + + ${this.model === RbacPermissionsAssignedByUsersListModelEnum.CoreUser + ? this.renderCoreUser() + : nothing} + ${this.model === RbacPermissionsAssignedByUsersListModelEnum.RbacRole + ? this.renderRbacRole() + : nothing}
                -
                User Object Permissions
                +
                ${msg("User Object Permissions")}
                +
                + ${msg("Permissions set on users which affect this object.")} +
                -
                Role Object Permissions
                +
                ${msg("Role Object Permissions")}
                +
                + ${msg("Permissions set on roles which affect this object.")} +
                `; } + + renderCoreUser() { + return html` +
                +
                +
                +
                ${msg("Assigned global permissions")}
                +
                + ${msg( + "Permissions assigned to this user which affect all object instances of a given type.", + )} +
                +
                + + +
                +
                +
                +
                +
                +
                +
                +
                ${msg("Assigned object permissions")}
                +
                + ${msg( + "Permissions assigned to this user affecting specific object instances.", + )} +
                +
                + + +
                +
                +
                +
                + `; + } + + renderRbacRole() { + return html` +
                +
                +
                +
                ${msg("Assigned global permissions")}
                +
                + ${msg( + "Permissions assigned to this role which affect all object instances of a given type.", + )} +
                +
                + + +
                +
                +
                +
                +
                +
                +
                +
                ${msg("Assigned object permissions")}
                +
                + ${msg( + "Permissions assigned to this user affecting specific object instances.", + )} +
                +
                + + +
                +
                +
                +
                + `; + } } diff --git a/web/src/elements/rbac/PermissionSelectModal.ts b/web/src/elements/rbac/PermissionSelectModal.ts index 648d88f170..e705f81a09 100644 --- a/web/src/elements/rbac/PermissionSelectModal.ts +++ b/web/src/elements/rbac/PermissionSelectModal.ts @@ -1,6 +1,6 @@ -import { groupBy } from "@goauthentik/app/common/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/buttons/SpinnerButton"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; @@ -67,7 +67,7 @@ export class PermissionSelectModal extends TableModal { renderModalInner(): TemplateResult { return html`
                -

                ${msg("Select permissions to grant")}

                +

                ${msg("Select permissions to assign")}

                ${this.renderTable()}
                diff --git a/web/src/elements/rbac/RoleObjectPermissionTable.ts b/web/src/elements/rbac/RoleObjectPermissionTable.ts index ee3c2161b4..6f335ae8b0 100644 --- a/web/src/elements/rbac/RoleObjectPermissionTable.ts +++ b/web/src/elements/rbac/RoleObjectPermissionTable.ts @@ -1,8 +1,8 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; import "@goauthentik/elements/rbac/RoleObjectPermissionForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; @@ -29,6 +29,7 @@ export class RoleAssignedObjectPermissionTable extends Table> { const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByRolesList({ @@ -109,20 +110,13 @@ export class RoleAssignedObjectPermissionTable extends Table { const granted = item.permissions.filter((uperm) => uperm.codename === perm.codename).length > 0; - baseRow.push(html` - { - console.log(granted); - }} - class="pf-m-link" - > - ${granted - ? html`` - : html`X`} - - `); + baseRow.push( + html`${granted + ? html`` + : html``} `, + ); }); return baseRow; } diff --git a/web/src/elements/rbac/UserObjectPermissionForm.ts b/web/src/elements/rbac/UserObjectPermissionForm.ts index 3b3b664024..98a99de9c3 100644 --- a/web/src/elements/rbac/UserObjectPermissionForm.ts +++ b/web/src/elements/rbac/UserObjectPermissionForm.ts @@ -93,19 +93,24 @@ export class UserObjectPermissionForm extends ModelForm > - ${this.modelPermissions?.results.map((perm) => { - return html` - - `; - })} + ${perm.name} + + `; + })} `; } } diff --git a/web/src/elements/rbac/UserObjectPermissionTable.ts b/web/src/elements/rbac/UserObjectPermissionTable.ts index a746447cc8..34ff6d9f7e 100644 --- a/web/src/elements/rbac/UserObjectPermissionTable.ts +++ b/web/src/elements/rbac/UserObjectPermissionTable.ts @@ -1,8 +1,8 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { PaginatedResponse, Table, TableColumn } from "@goauthentik/app/elements/table/Table"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; import "@goauthentik/elements/rbac/UserObjectPermissionForm"; +import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; @@ -29,6 +29,7 @@ export class UserAssignedObjectPermissionTable extends Table> { const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByUsersList({ @@ -44,7 +45,7 @@ export class UserAssignedObjectPermissionTable extends Table { - return !value.codename.startsWith("add_"); + return value.codename !== `add_${this.model?.split(".")[1]}`; }); this.modelPermissions = modelPermissions; return perms; @@ -112,13 +113,15 @@ export class UserAssignedObjectPermissionTable extends Table ${item.username} `]; this.modelPermissions?.results.forEach((perm) => { - let cell = html`X`; + let cell = html``; if (item.permissions.filter((uperm) => uperm.codename === perm.codename).length > 0) { cell = html``; + >`; } else if (item.isSuperuser) { - cell = html``; + cell = html``; } baseRow.push(cell); }); diff --git a/web/src/elements/router/RouterOutlet.ts b/web/src/elements/router/RouterOutlet.ts index 8aa54e0137..9d5687085c 100644 --- a/web/src/elements/router/RouterOutlet.ts +++ b/web/src/elements/router/RouterOutlet.ts @@ -91,7 +91,7 @@ export class RouterOutlet extends AKElement { let matchedRoute: RouteMatch | null = null; this.routes.some((route) => { const match = route.url.exec(activeUrl); - if (match != null) { + if (match !== null) { matchedRoute = new RouteMatch(route); matchedRoute.arguments = match.groups || {}; matchedRoute.fullUrl = activeUrl; diff --git a/web/src/elements/sidebar/SidebarItem.ts b/web/src/elements/sidebar/SidebarItem.ts index 26cdb975e4..1d38671a44 100644 --- a/web/src/elements/sidebar/SidebarItem.ts +++ b/web/src/elements/sidebar/SidebarItem.ts @@ -208,7 +208,7 @@ export class SidebarItem extends AKElement { } renderWithLabel() { - html` + return html` diff --git a/web/src/elements/table/Table.ts b/web/src/elements/table/Table.ts index 82fb9f5aef..588dc01df4 100644 --- a/web/src/elements/table/Table.ts +++ b/web/src/elements/table/Table.ts @@ -1,5 +1,5 @@ -import { APIErrorTypes, parseAPIError } from "@goauthentik/app/common/errors"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; +import { APIErrorTypes, parseAPIError } from "@goauthentik/common/errors"; import { groupBy } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; @@ -119,11 +119,19 @@ export abstract class Table extends AKElement implements TableLike { @property({ type: Number }) page = getURLParam("tablePage", 1); + /** @prop + * + * Set if your `selectedElements` use of the selection box is to enable bulk-delete, so that + * stale data is cleared out when the API returns a new list minus the deleted entries. + */ + @property({ attribute: "clear-on-refresh", type: Boolean, reflect: true }) + clearOnRefresh = false; + @property({ type: String }) order?: string; @property({ type: String }) - search: string = getURLParam("search", ""); + search: string = ""; @property({ type: Boolean }) checkbox = false; @@ -172,15 +180,27 @@ export abstract class Table extends AKElement implements TableLike { .pf-c-table tbody .pf-c-table__check input { margin-top: calc(var(--pf-c-table__check--input--MarginTop) + 1px); } + .pf-c-toolbar__content { + row-gap: var(--pf-global--spacer--sm); + } + .pf-c-toolbar__item .pf-c-input-group { + padding: 0 var(--pf-global--spacer--sm); + } `, ]; } constructor() { super(); - this.addEventListener(EVENT_REFRESH, () => { - this.fetch(); + this.addEventListener(EVENT_REFRESH, async () => { + await this.fetch(); + if (this.clearOnRefresh) { + this.selectedElements = []; + } }); + if (this.searchEnabled()) { + this.search = getURLParam("search", ""); + } } public groupBy(items: T[]): [string, T[]][] { diff --git a/web/src/elements/table/TableModal.ts b/web/src/elements/table/TableModal.ts index 341951fe6b..50311d8aef 100644 --- a/web/src/elements/table/TableModal.ts +++ b/web/src/elements/table/TableModal.ts @@ -1,6 +1,7 @@ +import { PFSize } from "@goauthentik/common/enums.js"; import { AKElement } from "@goauthentik/elements/Base"; -import { PFSize } from "@goauthentik/elements/Spinner"; import { MODAL_BUTTON_STYLES } from "@goauthentik/elements/buttons/ModalButton"; +import { ModalShowEvent } from "@goauthentik/elements/controllers/ModalOrchestrationController.js"; import { Table } from "@goauthentik/elements/table/Table"; import { CSSResult } from "lit"; @@ -44,16 +45,6 @@ export abstract class TableModal extends Table { ); } - constructor() { - super(); - window.addEventListener("keyup", (e) => { - if (e.code === "Escape") { - this.resetForms(); - this.open = false; - } - }); - } - public async fetch(): Promise { if (!this.open) { return; @@ -61,6 +52,11 @@ export abstract class TableModal extends Table { return super.fetch(); } + closeModal() { + this.resetForms(); + this.open = false; + } + resetForms(): void { this.querySelectorAll("[slot=form]").forEach((form) => { if ("resetForm" in form) { @@ -71,6 +67,7 @@ export abstract class TableModal extends Table { onClick(): void { this.open = true; + this.dispatchEvent(new ModalShowEvent(this)); this.querySelectorAll("*").forEach((child) => { if ("requestUpdate" in child) { (child as AKElement).requestUpdate(); diff --git a/web/src/elements/types.ts b/web/src/elements/types.ts index 4273ab6f9f..c0247b1e91 100644 --- a/web/src/elements/types.ts +++ b/web/src/elements/types.ts @@ -1,3 +1,11 @@ -export interface AdoptedStyleSheetsElement { - adoptedStyleSheets: readonly CSSStyleSheet[]; -} +import { AKElement } from "@goauthentik/elements/Base"; + +import { ReactiveControllerHost } from "lit"; + +export type ReactiveElementHost = Partial & T; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type Constructor = new (...args: any[]) => T; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type AbstractConstructor = abstract new (...args: any[]) => T; diff --git a/web/src/elements/user/SessionList.ts b/web/src/elements/user/SessionList.ts index b0861763d0..01c4d900c0 100644 --- a/web/src/elements/user/SessionList.ts +++ b/web/src/elements/user/SessionList.ts @@ -1,8 +1,10 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/DeleteBulkForm"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table"; +import getUnicodeFlagIcon from "country-flag-icons/unicode"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -25,11 +27,13 @@ export class AuthenticatedSessionList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { return [ new TableColumn(msg("Last IP"), "last_ip"), + new TableColumn(msg("Last used"), "last_used"), new TableColumn(msg("Expires"), "expires"), ]; } @@ -65,10 +69,17 @@ export class AuthenticatedSessionList extends Table { row(item: AuthenticatedSession): TemplateResult[] { return [ html`
                - ${item.current ? html`${msg("(Current session)")} ` : html``}${item.lastIp} + ${item.geoIp?.country + ? html`${getUnicodeFlagIcon(item.geoIp.country)} ` + : html``} + ${item.current ? html`${msg("(Current session)")} ` : html``} + ${item.lastIp}
                ${item.userAgent.userAgent?.family}, ${item.userAgent.os?.family}`, - html`${item.expires?.toLocaleString()}`, + html`
                ${getRelativeTime(item.lastUsed)}
                + ${item.lastUsed?.toLocaleString()}`, + html`
                ${getRelativeTime(item.expires || new Date())}
                + ${item.expires?.toLocaleString()}`, ]; } } diff --git a/web/src/elements/user/UserConsentList.ts b/web/src/elements/user/UserConsentList.ts index 56a59ebe10..638e96521e 100644 --- a/web/src/elements/user/UserConsentList.ts +++ b/web/src/elements/user/UserConsentList.ts @@ -1,5 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/DeleteBulkForm"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { Table, TableColumn } from "@goauthentik/elements/table/Table"; @@ -25,6 +26,7 @@ export class UserConsentList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { @@ -60,7 +62,10 @@ export class UserConsentList extends Table { row(item: UserConsent): TemplateResult[] { return [ html`${item.application.name}`, - html`${item.expires?.toLocaleString()}`, + html`${item.expires && item.expiring + ? html`
                ${getRelativeTime(item.expires)}
                + ${item.expires.toLocaleString()}` + : msg("-")}`, html`${item.permissions || "-"}`, ]; } diff --git a/web/src/user/user-settings/BaseUserSettings.ts b/web/src/elements/user/sources/BaseUserSettings.ts similarity index 100% rename from web/src/user/user-settings/BaseUserSettings.ts rename to web/src/elements/user/sources/BaseUserSettings.ts diff --git a/web/src/user/user-settings/sources/SourceSettings.ts b/web/src/elements/user/sources/SourceSettings.ts similarity index 68% rename from web/src/user/user-settings/sources/SourceSettings.ts rename to web/src/elements/user/sources/SourceSettings.ts index 203eef9f3d..e1b26d3247 100644 --- a/web/src/user/user-settings/sources/SourceSettings.ts +++ b/web/src/elements/user/sources/SourceSettings.ts @@ -1,18 +1,16 @@ -import { renderSourceIcon } from "@goauthentik/app/admin/sources/utils"; +import { renderSourceIcon } from "@goauthentik/admin/sources/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; -import { me } from "@goauthentik/common/users"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; -import "@goauthentik/user/user-settings/sources/SourceSettingsOAuth"; -import "@goauthentik/user/user-settings/sources/SourceSettingsPlex"; -import "@goauthentik/user/user-settings/sources/SourceSettingsSAML"; +import "@goauthentik/elements/user/sources/SourceSettingsOAuth"; +import "@goauthentik/elements/user/sources/SourceSettingsPlex"; +import "@goauthentik/elements/user/sources/SourceSettingsSAML"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; -import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css"; import { PaginatedUserSourceConnectionList, SourcesApi, UserSetting } from "@goauthentik/api"; @@ -25,10 +23,15 @@ export class UserSourceSettingsPage extends AKElement { @property({ attribute: false }) connections?: PaginatedUserSourceConnectionList; + @property({ type: Number }) + userId?: number; + + @property({ type: Boolean }) + canConnect = true; + static get styles(): CSSResult[] { return [ PFDataList, - PFContent, css` .pf-c-data-list__cell { display: flex; @@ -57,10 +60,9 @@ export class UserSourceSettingsPage extends AKElement { } async firstUpdated(): Promise { - const user = await me(); this.sourceSettings = await new SourcesApi(DEFAULT_CONFIG).sourcesAllUserSettingsList(); this.connections = await new SourcesApi(DEFAULT_CONFIG).sourcesUserConnectionsAllList({ - user: user.user.pk, + user: this.userId, }); } @@ -79,29 +81,26 @@ export class UserSourceSettingsPage extends AKElement { switch (source.component) { case "ak-user-settings-source-oauth": return html` `; case "ak-user-settings-source-plex": return html` `; case "ak-user-settings-source-saml": return html` `; default: @@ -112,23 +111,17 @@ export class UserSourceSettingsPage extends AKElement { } render(): TemplateResult { - return html`
                -

                - ${msg( - "Connect your user account to the services listed below, to allow you to login using the service instead of traditional credentials.", - )} -

                -
                -
                  - ${this.sourceSettings - ? html` - ${this.sourceSettings.length < 1 - ? html`` - : html` - ${this.sourceSettings.map((source) => { - return html`
                • + return html`
                    + ${this.sourceSettings + ? html` + ${this.sourceSettings.length < 1 + ? html`` + : html` + ${this.sourceSettings.map((source) => { + return html`
                  • +
                    ${renderSourceIcon( @@ -141,12 +134,13 @@ export class UserSourceSettingsPage extends AKElement { ${this.renderSourceSettings(source)}
                    -
                  • `; - })} - `} - ` - : html` - `} -
                  `; +
                + `; + })} + `} + ` + : html` + `} + `; } } diff --git a/web/src/user/user-settings/sources/SourceSettingsOAuth.ts b/web/src/elements/user/sources/SourceSettingsOAuth.ts similarity index 82% rename from web/src/user/user-settings/sources/SourceSettingsOAuth.ts rename to web/src/elements/user/sources/SourceSettingsOAuth.ts index 2461b487f9..39eda5daca 100644 --- a/web/src/user/user-settings/sources/SourceSettingsOAuth.ts +++ b/web/src/elements/user/sources/SourceSettingsOAuth.ts @@ -3,12 +3,11 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { MessageLevel } from "@goauthentik/common/messages"; import "@goauthentik/elements/Spinner"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; -import { BaseUserSettings } from "@goauthentik/user/user-settings/BaseUserSettings"; +import { BaseUserSettings } from "@goauthentik/elements/user/sources/BaseUserSettings"; import { msg, str } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { ifDefined } from "lit/directives/if-defined.js"; import { SourcesApi } from "@goauthentik/api"; @@ -57,13 +56,16 @@ export class SourceSettingsOAuth extends BaseUserSettings { ${msg("Disconnect")} `; } - return html` - ${msg("Connect")} - `; + if (this.configureUrl) { + return html` + ${msg("Connect")} + `; + } + return html`${msg("-")}`; } } diff --git a/web/src/user/user-settings/sources/SourceSettingsPlex.ts b/web/src/elements/user/sources/SourceSettingsPlex.ts similarity index 90% rename from web/src/user/user-settings/sources/SourceSettingsPlex.ts rename to web/src/elements/user/sources/SourceSettingsPlex.ts index a1c23cf57a..5d3370b70a 100644 --- a/web/src/user/user-settings/sources/SourceSettingsPlex.ts +++ b/web/src/elements/user/sources/SourceSettingsPlex.ts @@ -4,7 +4,7 @@ import { PlexAPIClient, popupCenterScreen } from "@goauthentik/common/helpers/pl import { MessageLevel } from "@goauthentik/common/messages"; import "@goauthentik/elements/Spinner"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; -import { BaseUserSettings } from "@goauthentik/user/user-settings/BaseUserSettings"; +import { BaseUserSettings } from "@goauthentik/elements/user/sources/BaseUserSettings"; import { msg, str } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -77,8 +77,11 @@ export class SourceSettingsPlex extends BaseUserSettings { ${msg("Disconnect")} `; } - return html``; + if (this.configureUrl) { + return html``; + } + return html`${msg("-")}`; } } diff --git a/web/src/user/user-settings/sources/SourceSettingsSAML.ts b/web/src/elements/user/sources/SourceSettingsSAML.ts similarity index 82% rename from web/src/user/user-settings/sources/SourceSettingsSAML.ts rename to web/src/elements/user/sources/SourceSettingsSAML.ts index da88645c3e..df13a5eaaa 100644 --- a/web/src/user/user-settings/sources/SourceSettingsSAML.ts +++ b/web/src/elements/user/sources/SourceSettingsSAML.ts @@ -3,12 +3,11 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { MessageLevel } from "@goauthentik/common/messages"; import "@goauthentik/elements/Spinner"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; -import { BaseUserSettings } from "@goauthentik/user/user-settings/BaseUserSettings"; +import { BaseUserSettings } from "@goauthentik/elements/user/sources/BaseUserSettings"; import { msg, str } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { ifDefined } from "lit/directives/if-defined.js"; import { SourcesApi } from "@goauthentik/api"; @@ -57,13 +56,16 @@ export class SourceSettingsSAML extends BaseUserSettings { ${msg("Disconnect")} `; } - return html` - ${msg("Connect")} - `; + if (this.configureUrl) { + return html` + ${msg("Connect")} + `; + } + return html`${msg("-")}`; } } diff --git a/web/src/elements/utils/debounce.ts b/web/src/elements/utils/debounce.ts new file mode 100644 index 0000000000..ab9ac90a81 --- /dev/null +++ b/web/src/elements/utils/debounce.ts @@ -0,0 +1,13 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type Callback = (...args: any[]) => any; +export function debounce(callback: F, wait: number) { + let timeout: ReturnType; + return (...args: Parameters) => { + // @ts-ignore + const context: T = this satisfies object; + if (timeout !== undefined) { + clearTimeout(timeout); + } + timeout = setTimeout(() => callback.apply(context, args), wait); + }; +} diff --git a/web/src/elements/utils/ensureCSSStyleSheet.ts b/web/src/elements/utils/ensureCSSStyleSheet.ts index 26f2ff8989..d809ca69b6 100644 --- a/web/src/elements/utils/ensureCSSStyleSheet.ts +++ b/web/src/elements/utils/ensureCSSStyleSheet.ts @@ -1,4 +1,35 @@ -import { CSSResult } from "lit"; +import { CSSResult, unsafeCSS } from "lit"; -export const ensureCSSStyleSheet = (css: CSSStyleSheet | CSSResult): CSSStyleSheet => - css instanceof CSSResult ? css.styleSheet! : css; +const supportsAdoptingStyleSheets: boolean = + window.ShadowRoot && + (window.ShadyCSS === undefined || window.ShadyCSS.nativeShadow) && + "adoptedStyleSheets" in Document.prototype && + "replace" in CSSStyleSheet.prototype; + +function stringToStylesheet(css: string) { + if (supportsAdoptingStyleSheets) { + const sheet = unsafeCSS(css).styleSheet; + if (sheet === undefined) { + throw new Error( + `CSS processing error: undefined stylesheet from string. Source: ${css}`, + ); + } + return sheet; + } + + const sheet = new CSSStyleSheet(); + sheet.replaceSync(css); + return sheet; +} + +function cssResultToStylesheet(css: CSSResult) { + const sheet = css.styleSheet; + return sheet ? sheet : stringToStylesheet(css.toString()); +} + +export const ensureCSSStyleSheet = (css: string | CSSStyleSheet | CSSResult): CSSStyleSheet => + css instanceof CSSResult + ? cssResultToStylesheet(css) + : typeof css === "string" + ? stringToStylesheet(css) + : css; diff --git a/web/src/elements/utils/eventEmitter.ts b/web/src/elements/utils/eventEmitter.ts index 54b4728257..1a3555eb24 100644 --- a/web/src/elements/utils/eventEmitter.ts +++ b/web/src/elements/utils/eventEmitter.ts @@ -9,22 +9,26 @@ export const isCustomEvent = (v: any): v is CustomEvent => export function CustomEmitterElement>(superclass: T) { return class EmmiterElementHandler extends superclass { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - dispatchCustomEvent(eventName: string, detail: any = {}, options = {}) { + dispatchCustomEvent( + eventName: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + detail: any = {}, + options = {}, + ) { const fullDetail = typeof detail === "object" && !Array.isArray(detail) ? { - target: this, ...detail, } : detail; + this.dispatchEvent( new CustomEvent(eventName, { composed: true, bubbles: true, ...options, detail: fullDetail, - }), + }) as F, ); } }; diff --git a/web/src/elements/wizard/TypeCreateWizardPage.ts b/web/src/elements/wizard/TypeCreateWizardPage.ts new file mode 100644 index 0000000000..567edd579d --- /dev/null +++ b/web/src/elements/wizard/TypeCreateWizardPage.ts @@ -0,0 +1,146 @@ +import "@goauthentik/admin/common/ak-license-notice"; +import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; +import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; + +import { msg, str } from "@lit/localize"; +import { CSSResult, TemplateResult, css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; +import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { TypeCreate } from "@goauthentik/api"; + +export enum TypeCreateWizardPageLayouts { + list = "list", + grid = "grid", +} + +@customElement("ak-wizard-page-type-create") +export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) { + @property({ attribute: false }) + types: TypeCreate[] = []; + + @property({ attribute: false }) + selectedType?: TypeCreate; + + @property({ type: String }) + layout: TypeCreateWizardPageLayouts = TypeCreateWizardPageLayouts.list; + + static get styles(): CSSResult[] { + return [ + PFBase, + PFForm, + PFGrid, + PFRadio, + PFCard, + css` + .pf-c-card__header-main img { + max-height: 2em; + min-height: 2em; + } + :host([theme="dark"]) .pf-c-card__header-main img { + filter: invert(1); + } + `, + ]; + } + + sidebarLabel = () => msg("Select type"); + + activeCallback: () => Promise = async () => { + this.host.isValid = false; + if (this.selectedType) { + this.selectDispatch(this.selectedType); + } + }; + + private selectDispatch(type: TypeCreate) { + this.dispatchEvent( + new CustomEvent("select", { + detail: type, + bubbles: true, + composed: true, + }), + ); + } + + renderGrid(): TemplateResult { + return html`
                + ${this.types.map((type, idx) => { + const requiresEnterprise = type.requiresEnterprise && !this.hasEnterpriseLicense; + return html`
                { + if (requiresEnterprise) { + return; + } + this.selectDispatch(type); + this.selectedType = type; + }} + > + ${type.iconUrl + ? html`
                +
                + ${msg(str`${type.name} +
                +
                ` + : nothing} +
                ${type.name}
                +
                ${type.description}
                + ${requiresEnterprise + ? html` ` + : nothing} +
                `; + })} +
                `; + } + + renderList(): TemplateResult { + return html`
                + ${this.types.map((type) => { + const requiresEnterprise = type.requiresEnterprise && !this.hasEnterpriseLicense; + return html`
                + { + this.selectDispatch(type); + }} + ?disabled=${requiresEnterprise} + /> + + ${type.description} + ${requiresEnterprise + ? html`` + : nothing} + +
                `; + })} + `; + } + + render(): TemplateResult { + switch (this.layout) { + case TypeCreateWizardPageLayouts.grid: + return this.renderGrid(); + case TypeCreateWizardPageLayouts.list: + return this.renderList(); + } + } +} diff --git a/web/src/elements/wizard/Wizard.ts b/web/src/elements/wizard/Wizard.ts index 95fc88a8ca..27f9e7f409 100644 --- a/web/src/elements/wizard/Wizard.ts +++ b/web/src/elements/wizard/Wizard.ts @@ -5,7 +5,7 @@ import { WizardPage } from "@goauthentik/elements/wizard/WizardPage"; import { msg } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { property } from "@lit/reactive-element/decorators/property.js"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, TemplateResult, css, html } from "lit"; import { state } from "lit/decorators.js"; import PFWizard from "@patternfly/patternfly/components/Wizard/wizard.css"; @@ -36,7 +36,14 @@ export class Wizard extends ModalButton { isValid = false; static get styles(): CSSResult[] { - return super.styles.concat(PFWizard); + return super.styles.concat( + PFWizard, + css` + .pf-c-modal-box { + height: 75%; + } + `, + ); } @state() diff --git a/web/src/enterprise/rac/index.ts b/web/src/enterprise/rac/index.ts index 87163cc46a..b2900957cc 100644 --- a/web/src/enterprise/rac/index.ts +++ b/web/src/enterprise/rac/index.ts @@ -1,4 +1,4 @@ -import { TITLE_DEFAULT } from "@goauthentik/app/common/constants"; +import { TITLE_DEFAULT } from "@goauthentik/common/constants"; import { Interface } from "@goauthentik/elements/Interface"; import "@goauthentik/elements/LoadingOverlay"; import Guacamole from "guacamole-common-js"; diff --git a/web/src/flow/FlowExecutor.ts b/web/src/flow/FlowExecutor.ts index 6d7a02b4f7..8c1a2afb76 100644 --- a/web/src/flow/FlowExecutor.ts +++ b/web/src/flow/FlowExecutor.ts @@ -15,10 +15,10 @@ import "@goauthentik/flow/sources/apple/AppleLoginInit"; import "@goauthentik/flow/sources/plex/PlexLoginInit"; import "@goauthentik/flow/stages/FlowErrorStage"; import "@goauthentik/flow/stages/RedirectStage"; -import { StageHost } from "@goauthentik/flow/stages/base"; +import { StageHost, SubmitOptions } from "@goauthentik/flow/stages/base"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, css, html, nothing } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; import { until } from "lit/directives/until.js"; @@ -32,9 +32,11 @@ import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { + CapabilitiesEnum, ChallengeChoices, ChallengeTypes, ContextualFlowInfo, + FetchError, FlowChallengeResponseRequest, FlowErrorChallenge, FlowLayoutEnum, @@ -72,24 +74,8 @@ export class FlowExecutor extends Interface implements StageHost { @state() inspectorOpen = false; - _flowInfo?: ContextualFlowInfo; - @state() - set flowInfo(value: ContextualFlowInfo | undefined) { - this._flowInfo = value; - if (!value) { - return; - } - this.shadowRoot - ?.querySelectorAll(".pf-c-background-image") - .forEach((bg) => { - bg.style.setProperty("--ak-flow-background", `url('${value?.background}')`); - }); - } - - get flowInfo(): ContextualFlowInfo | undefined { - return this._flowInfo; - } + flowInfo?: ContextualFlowInfo; ws: WebsocketClient; @@ -178,7 +164,7 @@ export class FlowExecutor extends Interface implements StageHost { super(); this.ws = new WebsocketClient(); if (window.location.search.includes("inspector")) { - this.inspectorOpen = !this.inspectorOpen; + this.inspectorOpen = true; } this.addEventListener(EVENT_FLOW_INSPECTOR_TOGGLE, () => { this.inspectorOpen = !this.inspectorOpen; @@ -189,12 +175,17 @@ export class FlowExecutor extends Interface implements StageHost { return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic; } - async submit(payload?: FlowChallengeResponseRequest): Promise { + async submit( + payload?: FlowChallengeResponseRequest, + options?: SubmitOptions, + ): Promise { if (!payload) return Promise.reject(); if (!this.challenge) return Promise.reject(); - // @ts-ignore + // @ts-expect-error payload.component = this.challenge.component; - this.loading = true; + if (!options?.invisible) { + this.loading = true; + } try { const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({ flowSlug: this.flowSlug, @@ -213,12 +204,9 @@ export class FlowExecutor extends Interface implements StageHost { if (this.challenge.flowInfo) { this.flowInfo = this.challenge.flowInfo; } - if (this.challenge.responseErrors) { - return false; - } - return true; + return !this.challenge.responseErrors; } catch (exc: unknown) { - this.errorMessage(exc as Error | ResponseError); + this.errorMessage(exc as Error | ResponseError | FetchError); return false; } finally { this.loading = false; @@ -227,6 +215,9 @@ export class FlowExecutor extends Interface implements StageHost { async firstUpdated(): Promise { configureSentry(); + if (this.config?.capabilities.includes(CapabilitiesEnum.CanDebug)) { + this.inspectorOpen = true; + } this.loading = true; try { const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorGet({ @@ -247,15 +238,17 @@ export class FlowExecutor extends Interface implements StageHost { } } catch (exc: unknown) { // Catch JSON or Update errors - this.errorMessage(exc as Error | ResponseError); + this.errorMessage(exc as Error | ResponseError | FetchError); } finally { this.loading = false; } } - async errorMessage(error: Error | ResponseError): Promise { + async errorMessage(error: Error | ResponseError | FetchError): Promise { let body = ""; - if (error instanceof ResponseError) { + if (error instanceof FetchError) { + body = msg("Request failed. Please try again later."); + } else if (error instanceof ResponseError) { body = await error.response.text(); } else if (error instanceof Error) { body = error.message; @@ -269,6 +262,24 @@ export class FlowExecutor extends Interface implements StageHost { this.challenge = challenge as ChallengeTypes; } + setShadowStyles(value: ContextualFlowInfo) { + if (!value) { + return; + } + this.shadowRoot + ?.querySelectorAll(".pf-c-background-image") + .forEach((bg) => { + bg.style.setProperty("--ak-flow-background", `url('${value?.background}')`); + }); + } + + // DOM post-processing has to happen after the render. + updated(changedProperties: PropertyValues) { + if (changedProperties.has("flowInfo") && this.flowInfo !== undefined) { + this.setShadowStyles(this.flowInfo); + } + } + async renderChallengeNativeElement(): Promise { switch (this.challenge?.component) { case "ak-stage-access-denied": @@ -407,7 +418,8 @@ export class FlowExecutor extends Interface implements StageHost { async renderChallenge(): Promise { if (!this.challenge) { - return html``; + return html` + `; } switch (this.challenge.type) { case ChallengeChoices.Redirect: @@ -423,14 +435,16 @@ export class FlowExecutor extends Interface implements StageHost { return await this.renderChallengeNativeElement(); default: console.debug(`authentik/flows: unexpected data type ${this.challenge.type}`); - break; + return html``; } - return html``; } renderChallengeWrapper(): TemplateResult { const logo = html``; if (!this.challenge) { return html`${logo} @@ -505,7 +519,7 @@ export class FlowExecutor extends Interface implements StageHost { ? html`
              • ${msg("Background image")}
              • diff --git a/web/src/flow/FlowInspector.ts b/web/src/flow/FlowInspector.ts index 377fc4ad9c..643bf36bfd 100644 --- a/web/src/flow/FlowInspector.ts +++ b/web/src/flow/FlowInspector.ts @@ -37,6 +37,10 @@ export class FlowInspector extends AKElement { PFDescriptionList, PFProgressStepper, css` + .pf-c-drawer__body { + min-height: 100vh; + max-height: 100vh; + } code.break { word-break: break-all; } @@ -45,9 +49,6 @@ export class FlowInspector extends AKElement { overflow-x: hidden; white-space: break-spaces; } - .pf-c-notification-drawer__body { - overflow-x: hidden; - } `, ]; } @@ -113,6 +114,7 @@ export class FlowInspector extends AKElement { return this.renderAccessDenied(); } if (!this.state) { + this.advanceHandler(); return html` `; } diff --git a/web/src/flow/sources/plex/PlexLoginInit.ts b/web/src/flow/sources/plex/PlexLoginInit.ts index 7ac10a648d..aea8689a53 100644 --- a/web/src/flow/sources/plex/PlexLoginInit.ts +++ b/web/src/flow/sources/plex/PlexLoginInit.ts @@ -10,6 +10,7 @@ import { TemplateResult, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFDivider from "@patternfly/patternfly/components/Divider/divider.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css"; @@ -32,7 +33,7 @@ export class PlexLoginInit extends BaseStage< authUrl?: string; static get styles(): CSSResult[] { - return [PFBase, PFLogin, PFForm, PFFormControl, PFButton, PFTitle]; + return [PFBase, PFLogin, PFForm, PFFormControl, PFButton, PFTitle, PFDivider]; } async firstUpdated(): Promise { @@ -76,7 +77,7 @@ export class PlexLoginInit extends BaseStage< header=${msg("Waiting for authentication...")} >
                -
                +

                ${msg("If no Plex popup opens, click the button below.")}

                - - + + ${this.challenge.errorMessage + ? html` +
                +

                ${this.challenge.errorMessage}

                +
                + ` + : nothing} +
                diff --git a/web/src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts b/web/src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts index 2a8cd82c89..eb28ddd7a9 100644 --- a/web/src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts +++ b/web/src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts @@ -5,7 +5,7 @@ import "@goauthentik/flow/FormStatic"; import { BaseStage } from "@goauthentik/flow/stages/base"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -32,14 +32,16 @@ export class AuthenticatorDuoStage extends BaseStage< return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton]; } - firstUpdated(): void { - const i = setInterval(() => { - this.checkEnrollStatus().then((shouldStop) => { - if (shouldStop) { - clearInterval(i); - } - }); - }, 3000); + updated(changedProperties: PropertyValues) { + if (changedProperties.has("challenge") && this.challenge !== undefined) { + const i = setInterval(() => { + this.checkEnrollStatus().then((shouldStop) => { + if (shouldStop) { + clearInterval(i); + } + }); + }, 3000); + } } async checkEnrollStatus(): Promise { diff --git a/web/src/flow/stages/authenticator_static/AuthenticatorStaticStage.ts b/web/src/flow/stages/authenticator_static/AuthenticatorStaticStage.ts index a9975e8737..ffa8a439d8 100644 --- a/web/src/flow/stages/authenticator_static/AuthenticatorStaticStage.ts +++ b/web/src/flow/stages/authenticator_static/AuthenticatorStaticStage.ts @@ -40,6 +40,7 @@ export class AuthenticatorStaticStage extends BaseStage< columns: 2; -webkit-columns: 2; -moz-columns: 2; + column-width: 1em; margin-left: var(--pf-global--spacer--xs); } ul li { diff --git a/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts new file mode 100644 index 0000000000..24a4f4a4a8 --- /dev/null +++ b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts @@ -0,0 +1,58 @@ +import type { StoryObj } from "@storybook/web-components"; + +import { html } from "lit"; + +import "@patternfly/patternfly/components/Login/login.css"; + +import { AuthenticatorTOTPChallenge, ChallengeChoices, UiThemeEnum } from "@goauthentik/api"; + +import "../../../stories/flow-interface"; +import "./AuthenticatorTOTPStage"; + +export default { + title: "Flow / Stages / AuthenticatorTOTPStage", +}; + +export const LoadingNoChallenge = () => { + return html` + + `; +}; + +export const Challenge: StoryObj = { + render: ({ theme, challenge }) => { + return html` + `; + }, + args: { + theme: "automatic", + challenge: { + type: ChallengeChoices.Native, + pendingUser: "foo", + pendingUserAvatar: "https://picsum.photos/64", + configUrl: "", + } as AuthenticatorTOTPChallenge, + }, + argTypes: { + theme: { + options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark], + control: { + type: "select", + }, + }, + }, +}; diff --git a/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts index 38030c10a0..074adb29ca 100644 --- a/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts +++ b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts @@ -106,6 +106,11 @@ export class AuthenticatorTOTPStage extends BaseStage<
                +

                + ${msg( + "Please scan the QR code above using the Microsoft Authenticator, Google Authenticator, or other authenticator apps on your device, and enter the code the device displays below to finish setting up the MFA device.", + )} +

                { - return this.host?.submit(payload) || Promise.resolve(); + submit( + payload: AuthenticatorValidationChallengeResponseRequest, + options?: SubmitOptions, + ): Promise { + return this.host?.submit(payload, options) || Promise.resolve(); } static get styles(): CSSResult[] { @@ -253,23 +255,7 @@ export class AuthenticatorValidateStage ? this.renderDeviceChallenge() : html``; } } diff --git a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts index 23d9e68f34..b4257d7642 100644 --- a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts +++ b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts @@ -1,20 +1,10 @@ import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/forms/FormElement"; -import "@goauthentik/flow/FormStatic"; -import { AuthenticatorValidateStage } from "@goauthentik/flow/stages/authenticator_validate/AuthenticatorValidateStage"; -import { BaseStage } from "@goauthentik/flow/stages/base"; +import { BaseDeviceStage } from "@goauthentik/flow/stages/authenticator_validate/base"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { ifDefined } from "lit/directives/if-defined.js"; - -import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; -import PFLogin from "@patternfly/patternfly/components/Login/login.css"; -import PFTitle from "@patternfly/patternfly/components/Title/title.css"; -import PFBase from "@patternfly/patternfly/patternfly-base.css"; +import { PropertyValues, TemplateResult, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import { AuthenticatorValidationChallenge, @@ -23,7 +13,7 @@ import { } from "@goauthentik/api"; @customElement("ak-stage-authenticator-validate-duo") -export class AuthenticatorValidateStageWebDuo extends BaseStage< +export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage< AuthenticatorValidationChallenge, AuthenticatorValidationChallengeResponseRequest > { @@ -33,14 +23,26 @@ export class AuthenticatorValidateStageWebDuo extends BaseStage< @property({ type: Boolean }) showBackButton = false; - static get styles(): CSSResult[] { - return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton]; - } + @state() + authenticating = false; - firstUpdated(): void { - this.host?.submit({ - duo: this.deviceChallenge?.deviceUid, - }); + updated(changedProperties: PropertyValues) { + if (changedProperties.has("challenge") && this.challenge !== undefined) { + this.authenticating = true; + this.host + ?.submit( + { + duo: this.deviceChallenge?.deviceUid, + }, + { invisible: true }, + ) + .then(() => { + this.authenticating = false; + }) + .catch(() => { + this.authenticating = false; + }); + } } render(): TemplateResult { @@ -49,56 +51,25 @@ export class AuthenticatorValidateStageWebDuo extends BaseStage< `; } const errors = this.challenge.responseErrors?.duo || []; + const errorMessage = errors.map((err) => err.string); return html` -
                - -
                `; + +
                ${this.renderReturnToDevicePicker()}
                + +
                `; } } diff --git a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts index 12e9b0a601..711ea0db4d 100644 --- a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts +++ b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts @@ -3,21 +3,12 @@ import { transformAssertionForServer, transformCredentialRequestOptions, } from "@goauthentik/common/helpers/webauthn"; -import { AuthenticatorValidateStage } from "@goauthentik/flow/stages/authenticator_validate/AuthenticatorValidateStage"; -import { BaseStage } from "@goauthentik/flow/stages/base"; +import "@goauthentik/elements/EmptyState"; +import { BaseDeviceStage } from "@goauthentik/flow/stages/authenticator_validate/base"; -import { msg, str } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; - -import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; -import PFLogin from "@patternfly/patternfly/components/Login/login.css"; -import PFTitle from "@patternfly/patternfly/components/Title/title.css"; -import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css"; -import PFBase from "@patternfly/patternfly/patternfly-base.css"; +import { msg } from "@lit/localize"; +import { PropertyValues, TemplateResult, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; import { AuthenticatorValidationChallenge, @@ -26,7 +17,7 @@ import { } from "@goauthentik/api"; @customElement("ak-stage-authenticator-validate-webauthn") -export class AuthenticatorValidateStageWebAuthn extends BaseStage< +export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage< AuthenticatorValidationChallenge, AuthenticatorValidationChallengeResponseRequest > { @@ -34,25 +25,15 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage< deviceChallenge?: DeviceChallenge; @property() - authenticateMessage?: string; + errorMessage?: string; @property({ type: Boolean }) showBackButton = false; - transformedCredentialRequestOptions?: PublicKeyCredentialRequestOptions; + @state() + authenticating = false; - static get styles(): CSSResult[] { - return [ - PFBase, - PFLogin, - PFEmptyState, - PFBullseye, - PFForm, - PFFormControl, - PFTitle, - PFButton, - ]; - } + transformedCredentialRequestOptions?: PublicKeyCredentialRequestOptions; async authenticate(): Promise { // request the authenticator to create an assertion signature using the @@ -64,10 +45,10 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage< publicKey: this.transformedCredentialRequestOptions, }); if (!assertion) { - throw new Error(msg("Assertions is empty")); + throw new Error("Assertions is empty"); } } catch (err) { - throw new Error(msg(str`Error when creating credential: ${err}`)); + throw new Error(`Error when creating credential: ${err}`); } // we now have an authentication assertion! encode the byte arrays contained @@ -78,77 +59,73 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage< // post the assertion to the server for verification. try { - await this.host?.submit({ - webauthn: transformedAssertionForServer, - }); + await this.host?.submit( + { + webauthn: transformedAssertionForServer, + }, + { + invisible: true, + }, + ); } catch (err) { - throw new Error(msg(str`Error when validating assertion on server: ${err}`)); + throw new Error(`Error when validating assertion on server: ${err}`); } } - firstUpdated(): void { - // convert certain members of the PublicKeyCredentialRequestOptions into - // byte arrays as expected by the spec. - const credentialRequestOptions = this.deviceChallenge - ?.challenge as PublicKeyCredentialRequestOptions; - this.transformedCredentialRequestOptions = - transformCredentialRequestOptions(credentialRequestOptions); - this.authenticateWrapper(); + updated(changedProperties: PropertyValues) { + if (changedProperties.has("challenge") && this.challenge !== undefined) { + // convert certain members of the PublicKeyCredentialRequestOptions into + // byte arrays as expected by the spec. + const credentialRequestOptions = this.deviceChallenge + ?.challenge as PublicKeyCredentialRequestOptions; + this.transformedCredentialRequestOptions = + transformCredentialRequestOptions(credentialRequestOptions); + this.authenticateWrapper(); + } } async authenticateWrapper(): Promise { - if (this.host.loading) { + if (this.authenticating) { return; } - this.host.loading = true; + this.authenticating = true; this.authenticate() - .catch((e) => { - console.error(e); - this.authenticateMessage = e.toString(); + .catch((e: Error) => { + console.warn("authentik/flows/authenticator_validate/webauthn: failed to auth", e); + this.errorMessage = msg("Authentication failed. Please try again."); }) .finally(() => { - this.host.loading = false; + this.authenticating = false; }); } render(): TemplateResult { return html` -
                - -
                `; + ` + : nothing} + ${this.renderReturnToDevicePicker()} +
                + + `; } } diff --git a/web/src/flow/stages/authenticator_validate/base.ts b/web/src/flow/stages/authenticator_validate/base.ts new file mode 100644 index 0000000000..821014a931 --- /dev/null +++ b/web/src/flow/stages/authenticator_validate/base.ts @@ -0,0 +1,65 @@ +import { AuthenticatorValidateStage } from "@goauthentik/flow/stages/authenticator_validate/AuthenticatorValidateStage"; +import { BaseStage, FlowInfoChallenge, PendingUserChallenge } from "@goauthentik/flow/stages/base"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, css, html } from "lit"; +import { property } from "lit/decorators.js"; + +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFLogin from "@patternfly/patternfly/components/Login/login.css"; +import PFTitle from "@patternfly/patternfly/components/Title/title.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +import { DeviceChallenge } from "@goauthentik/api"; + +export class BaseDeviceStage< + Tin extends FlowInfoChallenge & PendingUserChallenge, + Tout, +> extends BaseStage { + @property({ attribute: false }) + deviceChallenge?: DeviceChallenge; + + @property({ type: Boolean }) + showBackButton = false; + + static get styles(): CSSResult[] { + return [ + PFBase, + PFLogin, + PFForm, + PFFormControl, + PFTitle, + PFButton, + css` + .pf-c-form__group.pf-m-action { + display: flex; + gap: 16px; + margin-top: 0; + margin-bottom: calc(var(--pf-c-form__group--m-action--MarginTop) / 2); + flex-direction: column; + } + `, + ]; + } + + submit(payload: Tin): Promise { + return this.host?.submit(payload) || Promise.resolve(); + } + + renderReturnToDevicePicker(): TemplateResult { + if (!this.showBackButton) { + return html``; + } + return html``; + } +} diff --git a/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts b/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts index dd056da66b..b2eb9e12c3 100644 --- a/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts +++ b/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts @@ -4,12 +4,13 @@ import { transformCredentialCreateOptions, transformNewAssertionForServer, } from "@goauthentik/common/helpers/webauthn"; -import { PFSize } from "@goauthentik/elements/Spinner"; +import "@goauthentik/elements/EmptyState"; import { BaseStage } from "@goauthentik/flow/stages/base"; import { msg, str } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css"; @@ -41,7 +42,24 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage< publicKeyCredentialCreateOptions?: PublicKeyCredentialCreationOptions; static get styles(): CSSResult[] { - return [PFBase, PFLogin, PFFormControl, PFForm, PFTitle, PFButton]; + return [ + PFBase, + PFLogin, + PFFormControl, + PFForm, + PFTitle, + PFButton, + // FIXME: this is technically duplicate with ../authenticator_validate/base.ts + css` + .pf-c-form__group.pf-m-action { + display: flex; + gap: 16px; + margin-top: 0; + margin-bottom: calc(var(--pf-c-form__group--m-action--MarginTop) / 2); + flex-direction: column; + } + `, + ]; } async register(): Promise { @@ -69,9 +87,14 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage< // post the transformed credential data to the server for validation // and storing the public key try { - await this.host?.submit({ - response: newAssertionForServer, - }); + await this.host?.submit( + { + response: newAssertionForServer, + }, + { + invisible: true, + }, + ); } catch (err) { throw new Error(msg(str`Server validation of credential failed: ${err}`)); } @@ -84,62 +107,70 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage< this.registerRunning = true; this.register() .catch((e) => { - console.error(e); - this.registerMessage = e.toString(); + console.warn("authentik/flows/authenticator_webauthn: failed to register", e); + this.registerMessage = msg("Failed to register. Please try again."); }) .finally(() => { this.registerRunning = false; }); } - firstUpdated(): void { - // convert certain members of the PublicKeyCredentialCreateOptions into - // byte arrays as expected by the spec. - this.publicKeyCredentialCreateOptions = transformCredentialCreateOptions( - this.challenge?.registration as PublicKeyCredentialCreationOptions, - this.challenge?.registration.user.id, - ); - this.registerWrapper(); + updated(changedProperties: PropertyValues) { + if (changedProperties.has("challenge") && this.challenge !== undefined) { + // convert certain members of the PublicKeyCredentialCreateOptions into + // byte arrays as expected by the spec. + this.publicKeyCredentialCreateOptions = transformCredentialCreateOptions( + this.challenge?.registration as PublicKeyCredentialCreationOptions, + this.challenge?.registration.user.id, + ); + this.registerWrapper(); + } } render(): TemplateResult { return html` - -
                - -
                `; + ${msg("Retry registration")} + ` + : nothing} + + + `; } } diff --git a/web/src/flow/stages/base.ts b/web/src/flow/stages/base.ts index 0400a81b5c..5606527d46 100644 --- a/web/src/flow/stages/base.ts +++ b/web/src/flow/stages/base.ts @@ -1,16 +1,22 @@ import { AKElement } from "@goauthentik/elements/Base"; import { KeyUnknown } from "@goauthentik/elements/forms/Form"; +import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { property } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; -import { CurrentBrand, ErrorDetail } from "@goauthentik/api"; +import { ContextualFlowInfo, CurrentBrand, ErrorDetail } from "@goauthentik/api"; + +export interface SubmitOptions { + invisible: boolean; +} export interface StageHost { challenge?: unknown; flowSlug?: string; loading: boolean; - submit(payload: unknown): Promise; + submit(payload: unknown, options?: SubmitOptions): Promise; readonly brand?: CurrentBrand; } @@ -26,7 +32,21 @@ export function readFileAsync(file: Blob) { }); } -export class BaseStage extends AKElement { +// Challenge which contains flow info +export interface FlowInfoChallenge { + flowInfo?: ContextualFlowInfo; +} + +// Challenge which has a pending user +export interface PendingUserChallenge { + pendingUser?: string; + pendingUserAvatar?: string; +} + +export class BaseStage< + Tin extends FlowInfoChallenge & PendingUserChallenge, + Tout, +> extends AKElement { host!: StageHost; @property({ attribute: false }) @@ -68,6 +88,31 @@ export class BaseStage extends AKElement { `; } + renderUserInfo(): TemplateResult { + if (!this.challenge.pendingUser || !this.challenge.pendingUserAvatar) { + return html``; + } + return html` + + + + + `; + } + cleanup(): void { // Method that can be overridden by stages return; diff --git a/web/src/flow/stages/captcha/CaptchaStage.stories.ts b/web/src/flow/stages/captcha/CaptchaStage.stories.ts new file mode 100644 index 0000000000..668eaf1b59 --- /dev/null +++ b/web/src/flow/stages/captcha/CaptchaStage.stories.ts @@ -0,0 +1,119 @@ +import type { StoryObj } from "@storybook/web-components"; + +import { html } from "lit"; + +import "@patternfly/patternfly/components/Login/login.css"; + +import { CaptchaChallenge, ChallengeChoices, UiThemeEnum } from "@goauthentik/api"; + +import "../../../stories/flow-interface"; +import "./CaptchaStage"; + +export default { + title: "Flow / Stages / CaptchaStage", +}; + +export const LoadingNoChallenge = () => { + return html` + + `; +}; + +export const ChallengeGoogleReCaptcha: StoryObj = { + render: ({ theme, challenge }) => { + return html` + `; + }, + args: { + theme: "automatic", + challenge: { + type: ChallengeChoices.Native, + pendingUser: "foo", + pendingUserAvatar: "https://picsum.photos/64", + jsUrl: "https://www.google.com/recaptcha/api.js", + siteKey: "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI", + } as CaptchaChallenge, + }, + argTypes: { + theme: { + options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark], + control: { + type: "select", + }, + }, + }, +}; + +export const ChallengeHCaptcha: StoryObj = { + render: ({ theme, challenge }) => { + return html` + `; + }, + args: { + theme: "automatic", + challenge: { + type: ChallengeChoices.Native, + pendingUser: "foo", + pendingUserAvatar: "https://picsum.photos/64", + jsUrl: "https://js.hcaptcha.com/1/api.js", + siteKey: "10000000-ffff-ffff-ffff-000000000001", + } as CaptchaChallenge, + }, + argTypes: { + theme: { + options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark], + control: { + type: "select", + }, + }, + }, +}; + +export const ChallengeTurnstile: StoryObj = { + render: ({ theme, challenge }) => { + return html` + `; + }, + args: { + theme: "automatic", + challenge: { + type: ChallengeChoices.Native, + pendingUser: "foo", + pendingUserAvatar: "https://picsum.photos/64", + jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js", + siteKey: "1x00000000000000000000BB", + } as CaptchaChallenge, + }, + argTypes: { + theme: { + options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark], + control: { + type: "select", + }, + }, + }, +}; diff --git a/web/src/flow/stages/captcha/CaptchaStage.ts b/web/src/flow/stages/captcha/CaptchaStage.ts index 753bda99c0..199961b836 100644 --- a/web/src/flow/stages/captcha/CaptchaStage.ts +++ b/web/src/flow/stages/captcha/CaptchaStage.ts @@ -1,14 +1,12 @@ /// import "@goauthentik/elements/EmptyState"; -import { PFSize } from "@goauthentik/elements/Spinner"; import "@goauthentik/elements/forms/FormElement"; import "@goauthentik/flow/FormStatic"; -import "@goauthentik/flow/stages/access_denied/AccessDeniedStage"; import { BaseStage } from "@goauthentik/flow/stages/base"; import type { TurnstileObject } from "turnstile-types"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, PropertyValues, TemplateResult, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -25,6 +23,8 @@ interface TurnstileWindow extends Window { turnstile: TurnstileObject; } +const captchaContainerID = "captcha-container"; + @customElement("ak-stage-captcha") export class CaptchaStage extends BaseStage { static get styles(): CSSResult[] { @@ -36,50 +36,71 @@ export class CaptchaStage extends BaseStage { - console.debug("authentik/stages/captcha: script loaded"); - let found = false; - let lastError = undefined; - this.handlers.forEach((handler) => { - let handlerFound = false; - try { - console.debug(`authentik/stages/captcha[${handler.name}]: trying handler`); - handlerFound = handler.apply(this, [captchaContainer]); - if (handlerFound) { - console.debug( - `authentik/stages/captcha[${handler.name}]: handler succeeded`, - ); - found = true; - } - } catch (exc) { - console.debug( - `authentik/stages/captcha[${handler.name}]: handler failed: ${exc}`, - ); - if (handlerFound) { - lastError = exc; - } - } - }); - if (!found && lastError) { - this.error = (lastError as Error).toString(); - } - }; - document.head.appendChild(script); + @state() + captchaInteractive: boolean = true; + + @state() + captchaContainer: HTMLDivElement; + + @state() + scriptElement?: HTMLScriptElement; + + constructor() { + super(); + this.captchaContainer = document.createElement("div"); + this.captchaContainer.id = captchaContainerID; } - handleGReCaptcha(container: HTMLDivElement): boolean { + updated(changedProperties: PropertyValues) { + if (changedProperties.has("challenge") && this.challenge !== undefined) { + this.scriptElement = document.createElement("script"); + this.scriptElement.src = this.challenge.jsUrl; + this.scriptElement.async = true; + this.scriptElement.defer = true; + this.scriptElement.dataset.akCaptchaScript = "true"; + this.scriptElement.onload = () => { + console.debug("authentik/stages/captcha: script loaded"); + let found = false; + let lastError = undefined; + this.handlers.forEach((handler) => { + let handlerFound = false; + try { + console.debug(`authentik/stages/captcha[${handler.name}]: trying handler`); + handlerFound = handler.apply(this); + if (handlerFound) { + console.debug( + `authentik/stages/captcha[${handler.name}]: handler succeeded`, + ); + found = true; + } + } catch (exc) { + console.debug( + `authentik/stages/captcha[${handler.name}]: handler failed: ${exc}`, + ); + if (handlerFound) { + lastError = exc; + } + } + }); + if (!found && lastError) { + this.error = (lastError as Error).toString(); + } + }; + document.head + .querySelectorAll("[data-ak-captcha-script=true]") + .forEach((el) => el.remove()); + document.head.appendChild(this.scriptElement); + } + } + + handleGReCaptcha(): boolean { if (!Object.hasOwn(window, "grecaptcha")) { return false; } + this.captchaInteractive = false; + document.body.appendChild(this.captchaContainer); grecaptcha.ready(() => { - const captchaId = grecaptcha.render(container, { + const captchaId = grecaptcha.render(this.captchaContainer, { sitekey: this.challenge.siteKey, callback: (token) => { this.host?.submit({ @@ -93,11 +114,13 @@ export class CaptchaStage extends BaseStage { @@ -110,11 +133,13 @@ export class CaptchaStage extends BaseStage { this.host?.submit({ @@ -125,6 +150,19 @@ export class CaptchaStage extends BaseStage `; + } + if (this.captchaInteractive) { + return html`${this.captchaContainer}`; + } + return html``; + } + render(): TemplateResult { if (!this.challenge) { return html` @@ -146,12 +184,7 @@ export class CaptchaStage extends BaseStage - ${this.error - ? html` - ` - : html`
                - -
                `} + ${this.renderBody()}
                diff --git a/web/src/flow/stages/dummy/DummyStage.ts b/web/src/flow/stages/dummy/DummyStage.ts index 7fb5895a17..6f11b9e83b 100644 --- a/web/src/flow/stages/dummy/DummyStage.ts +++ b/web/src/flow/stages/dummy/DummyStage.ts @@ -2,7 +2,7 @@ import "@goauthentik/elements/EmptyState"; import "@goauthentik/flow/FormStatic"; import { BaseStage } from "@goauthentik/flow/stages/base"; -import { msg } from "@lit/localize"; +import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; @@ -36,6 +36,7 @@ export class DummyStage extends BaseStage +

                ${msg(str`Stage name: ${this.challenge.name}`)}

                `; } renderInput(): TemplateResult { let type: "text" | "email" = "text"; if (!this.challenge?.userFields || this.challenge.userFields.length === 0) { - return html`

                ${msg("Select one of the sources below to login.")}

                `; + return html`

                ${msg("Select one of the options below to continue.")}

                `; } const fields = (this.challenge?.userFields || []).sort(); // Check if the field should be *only* email to set the input type @@ -220,7 +223,16 @@ export class IdentificationStage extends BaseStage< [UserFieldsEnum.Upn]: msg("UPN"), }; const label = OR_LIST_FORMATTERS.format(fields.map((f) => uiFields[f])); - return html` + ${msg( + "Enter the email associated with your account, and we'll send you a link to reset your password.", + )} +

                + ` + : nothing} + ` - : html``} + : nothing} ${"non_field_errors" in (this.challenge?.responseErrors || {}) ? this.renderNonFieldErrors(this.challenge?.responseErrors?.non_field_errors || []) - : html``} + : nothing}
                ${this.challenge.passwordlessUrl - ? html`${msg("Or")} - ` - : html``}`; + ? html`${msg("Or")}` + : nothing}`; } render(): TemplateResult { @@ -296,8 +300,20 @@ export class IdentificationStage extends BaseStage< ? html`

                ${msg(str`Login to continue to ${this.challenge.applicationPre}.`)}

                ` - : html``} + : nothing} ${this.renderInput()} + ${this.challenge.passwordlessUrl + ? html` + + ` + : nothing}
                diff --git a/web/src/stories/flow-interface.ts b/web/src/stories/flow-interface.ts index 3975e29f7a..7dbe53ae35 100644 --- a/web/src/stories/flow-interface.ts +++ b/web/src/stories/flow-interface.ts @@ -1,4 +1,4 @@ -import { FlowExecutor } from "@goauthentik/app/flow/FlowExecutor"; +import { FlowExecutor } from "@goauthentik/flow/FlowExecutor"; import { customElement, property } from "lit/decorators.js"; diff --git a/web/src/stories/interface.ts b/web/src/stories/interface.ts index 1eafc62048..ec15e6ad83 100644 --- a/web/src/stories/interface.ts +++ b/web/src/stories/interface.ts @@ -1,4 +1,4 @@ -import { Interface } from "@goauthentik/app/elements/Interface"; +import { Interface } from "@goauthentik/elements/Interface"; import { customElement, property } from "lit/decorators.js"; diff --git a/web/src/user/LibraryApplication/RACLaunchEndpointModal.ts b/web/src/user/LibraryApplication/RACLaunchEndpointModal.ts index 40f5668f7b..cf643aeaaa 100644 --- a/web/src/user/LibraryApplication/RACLaunchEndpointModal.ts +++ b/web/src/user/LibraryApplication/RACLaunchEndpointModal.ts @@ -1,6 +1,6 @@ -import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; -import { PaginatedResponse, TableColumn } from "@goauthentik/app/elements/table/Table"; -import { TableModal } from "@goauthentik/app/elements/table/TableModal"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { PaginatedResponse, TableColumn } from "@goauthentik/elements/table/Table"; +import { TableModal } from "@goauthentik/elements/table/TableModal"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; diff --git a/web/src/user/LibraryApplication/index.ts b/web/src/user/LibraryApplication/index.ts index 35f60804fb..30475dd981 100644 --- a/web/src/user/LibraryApplication/index.ts +++ b/web/src/user/LibraryApplication/index.ts @@ -1,4 +1,4 @@ -import { PFSize } from "@goauthentik/app/elements/Spinner"; +import { PFSize } from "@goauthentik/common/enums.js"; import { truncateWords } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-app-icon"; import { AKElement, rootInterface } from "@goauthentik/elements/Base"; diff --git a/web/src/user/LibraryPage/ApplicationEmptyState.ts b/web/src/user/LibraryPage/ApplicationEmptyState.ts index 11871c1396..bcd62611aa 100644 --- a/web/src/user/LibraryPage/ApplicationEmptyState.ts +++ b/web/src/user/LibraryPage/ApplicationEmptyState.ts @@ -1,5 +1,4 @@ import { docLink } from "@goauthentik/common/global"; -import { adaptCSS } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import { paramURL } from "@goauthentik/elements/router/RouterOutlet"; @@ -20,23 +19,23 @@ import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css"; * administrator, provide a link to the "Create a new application" page. */ -const styles = adaptCSS([ - PFBase, - PFEmptyState, - PFButton, - PFContent, - PFSpacing, - css` - .cta { - display: inline-block; - font-weight: bold; - } - `, -]); - @customElement("ak-library-application-empty-list") export class LibraryPageApplicationEmptyList extends AKElement { - static styles = styles; + static get styles() { + return [ + PFBase, + PFEmptyState, + PFButton, + PFContent, + PFSpacing, + css` + .cta { + display: inline-block; + font-weight: bold; + } + `, + ]; + } @property({ attribute: "isadmin", type: Boolean }) isAdmin = false; diff --git a/web/src/user/LibraryPage/ApplicationList.ts b/web/src/user/LibraryPage/ApplicationList.ts index 7b680d8cac..c51acce659 100644 --- a/web/src/user/LibraryPage/ApplicationList.ts +++ b/web/src/user/LibraryPage/ApplicationList.ts @@ -31,22 +31,22 @@ const LAYOUTS = new Map([ ], ]); -const styles = [ - PFBase, - PFEmptyState, - PFContent, - PFGrid, - css` - .app-group-header { - margin-bottom: 1em; - margin-top: 1.2em; - } - `, -]; - @customElement("ak-library-application-list") export class LibraryPageApplicationList extends AKElement { - static styles = styles; + static get styles() { + return [ + PFBase, + PFEmptyState, + PFContent, + PFGrid, + css` + .app-group-header { + margin-bottom: 1em; + margin-top: 1.2em; + } + `, + ]; + } @property({ attribute: true }) layout = "row" as LayoutType; diff --git a/web/src/user/LibraryPage/ApplicationSearch.ts b/web/src/user/LibraryPage/ApplicationSearch.ts index b780e2ef54..7e6f40f53a 100644 --- a/web/src/user/LibraryPage/ApplicationSearch.ts +++ b/web/src/user/LibraryPage/ApplicationSearch.ts @@ -18,24 +18,29 @@ import { customEvent } from "./helpers"; @customElement("ak-library-list-search") export class LibraryPageApplicationList extends AKElement { - static styles = [ - PFBase, - PFDisplay, - css` - input { - width: 30ch; - box-sizing: border-box; - border: 0; - border-bottom: 1px solid; - border-bottom-color: var(--ak-accent); - background-color: transparent; - font-size: 1.5rem; - } - input:focus { - outline: 0; - } - `, - ]; + static get styles() { + return [ + PFBase, + PFDisplay, + css` + input { + width: 30ch; + box-sizing: border-box; + border: 0; + border-bottom: 1px solid; + border-bottom-color: var(--ak-accent); + background-color: transparent; + font-size: 1.5rem; + } + input:focus { + outline: 0; + } + :host([theme="dark"]) input { + color: var(--ak-dark-foreground) !important; + } + `, + ]; + } @property({ attribute: false }) set apps(value: Application[]) { diff --git a/web/src/user/LibraryPage/LibraryPage.ts b/web/src/user/LibraryPage/LibraryPage.ts index cdd54f8f72..01ab26c718 100644 --- a/web/src/user/LibraryPage/LibraryPage.ts +++ b/web/src/user/LibraryPage/LibraryPage.ts @@ -2,7 +2,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { me } from "@goauthentik/common/users"; import { AKElement, rootInterface } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; -import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { localized, msg } from "@lit/localize"; import { html } from "lit"; @@ -25,6 +24,8 @@ import type { PageUIConfig } from "./types"; * */ +const coreApi = () => new CoreApi(DEFAULT_CONFIG); + @localized() @customElement("ak-library") export class LibraryPage extends AKElement { @@ -35,15 +36,13 @@ export class LibraryPage extends AKElement { isAdmin = false; @state() - apps!: PaginatedResponse; + apps: Application[] = []; @state() uiConfig: PageUIConfig; constructor() { super(); - const applicationListFetch = new CoreApi(DEFAULT_CONFIG).coreApplicationsList({}); - const meFetch = me(); const uiConfig = rootInterface()?.uiConfig; if (!uiConfig) { throw new Error("Could not retrieve uiConfig. Reason: unknown. Check logs."); @@ -55,22 +54,41 @@ export class LibraryPage extends AKElement { searchEnabled: uiConfig.enabledFeatures.search, }; - Promise.allSettled([applicationListFetch, meFetch]).then( - ([applicationListStatus, meStatus]) => { - if (meStatus.status === "rejected") { - throw new Error( - `Could not determine status of user. Reason: ${meStatus.reason}`, - ); + Promise.all([this.fetchApplications(), me()]).then(([applications, meStatus]) => { + this.isAdmin = meStatus.user.isSuperuser; + this.apps = applications; + this.ready = true; + }); + } + + async fetchApplications(): Promise { + const applicationListParams = (page = 1) => ({ + ordering: "name", + page, + pageSize: 100, + }); + + const applicationListFetch = await coreApi().coreApplicationsList(applicationListParams(1)); + const pageCount = applicationListFetch.pagination.totalPages; + if (pageCount === 1) { + return applicationListFetch.results; + } + + const applicationLaterPages = await Promise.allSettled( + Array.from({ length: pageCount - 1 }).map((_a, idx) => + coreApi().coreApplicationsList(applicationListParams(idx + 2)), + ), + ); + + return applicationLaterPages.reduce( + function (acc, result) { + if (result.status === "rejected") { + const reason = JSON.stringify(result.reason, null, 2); + throw new Error(`Could not retrieve list of applications. Reason: ${reason}`); } - if (applicationListStatus.status === "rejected") { - throw new Error( - `Could not retrieve list of applications. Reason: ${applicationListStatus.reason}`, - ); - } - this.isAdmin = meStatus.value.user.isSuperuser; - this.apps = applicationListStatus.value; - this.ready = true; + return [...acc, ...result.value.results]; }, + [...applicationListFetch.results], ); } diff --git a/web/src/user/LibraryPage/LibraryPageImpl.ts b/web/src/user/LibraryPage/LibraryPageImpl.ts index 79fc8d609f..1892e499f9 100644 --- a/web/src/user/LibraryPage/LibraryPageImpl.ts +++ b/web/src/user/LibraryPage/LibraryPageImpl.ts @@ -1,7 +1,6 @@ import { groupBy } from "@goauthentik/common/utils"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; -import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import "@goauthentik/user/LibraryApplication"; import { msg } from "@lit/localize"; @@ -35,13 +34,15 @@ import type { AppGroupList, PageUIConfig } from "./types"; @customElement("ak-library-impl") export class LibraryPage extends AKElement { - static styles = styles; + static get styles() { + return styles; + } @property({ attribute: "isadmin", type: Boolean }) isAdmin = false; - @property({ attribute: false }) - apps!: PaginatedResponse; + @property({ attribute: false, type: Array }) + apps!: Application[]; @property({ attribute: false }) uiConfig!: PageUIConfig; @@ -64,7 +65,7 @@ export class LibraryPage extends AKElement { connectedCallback() { super.connectedCallback(); - this.filteredApps = this.apps?.results; + this.filteredApps = this.apps; if (this.filteredApps === undefined) { throw new Error( "Application.results should never be undefined when passed to the Library Page.", @@ -87,7 +88,7 @@ export class LibraryPage extends AKElement { event.stopPropagation(); const apps = event.detail.apps; this.selectedApp = undefined; - this.filteredApps = this.apps.results; + this.filteredApps = this.apps; if (apps.length > 0) { this.selectedApp = apps[0]; this.filteredApps = event.detail.apps; @@ -130,7 +131,7 @@ export class LibraryPage extends AKElement { } renderSearch() { - return html``; + return html``; } render() { diff --git a/web/src/user/UserInterface.ts b/web/src/user/UserInterface.ts index cce5f60d1e..9769ae0617 100644 --- a/web/src/user/UserInterface.ts +++ b/web/src/user/UserInterface.ts @@ -5,11 +5,11 @@ import { EVENT_WS_MESSAGE, } from "@goauthentik/common/constants"; import { configureSentry } from "@goauthentik/common/sentry"; -import { UserDisplay } from "@goauthentik/common/ui/config"; +import { UIConfig, UserDisplay } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; -import { first } from "@goauthentik/common/utils"; import { WebsocketClient } from "@goauthentik/common/ws"; -import { Interface } from "@goauthentik/elements/Interface"; +import { AKElement } from "@goauthentik/elements/Base"; +import { EnterpriseAwareInterface } from "@goauthentik/elements/Interface"; import "@goauthentik/elements/ak-locale-context"; import "@goauthentik/elements/buttons/ActionButton"; import "@goauthentik/elements/enterprise/EnterpriseStatusBanner"; @@ -23,9 +23,10 @@ import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand"; import "@goauthentik/elements/sidebar/SidebarItem"; import { ROUTES } from "@goauthentik/user/Routes"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; +import { match } from "ts-pattern"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, css, html } from "lit"; +import { css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css"; @@ -38,25 +39,86 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; -import { CoreApi, EventsApi, SessionUser } from "@goauthentik/api"; +import { CoreApi, CurrentBrand, EventsApi, SessionUser } from "@goauthentik/api"; -@customElement("ak-interface-user") -export class UserInterface extends Interface { - @property({ type: Boolean }) - notificationDrawerOpen = getURLParam("notificationDrawerOpen", false); +const customStyles = css` + .pf-c-page__main, + .pf-c-drawer__content, + .pf-c-page__drawer { + z-index: auto !important; + background-color: transparent !important; + } + .pf-c-page__header { + background-color: transparent !important; + box-shadow: none !important; + color: black !important; + } + :host([theme="dark"]) .pf-c-page__header { + color: var(--ak-dark-foreground) !important; + } + :host([theme="light"]) .pf-c-page__header-tools-item .fas, + :host([theme="light"]) .pf-c-notification-badge__count, + :host([theme="light"]) .pf-c-page__header-tools-group .pf-c-button { + color: var(--ak-global--Color--100) !important; + } + .pf-c-page { + background-color: transparent; + } + .display-none { + display: none; + } + .pf-c-brand { + min-height: 32px; + height: 32px; + } + .has-notifications { + color: #2b9af3; + } + .background-wrapper { + height: 100vh; + width: 100%; + position: fixed; + z-index: -1; + top: 0; + left: 0; + background-color: var(--pf-c-page--BackgroundColor) !important; + } + .background-default-slant { + background-color: white; /*var(--ak-accent);*/ + clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 5vw)); + height: 50vh; + } + :host([theme="dark"]) .background-default-slant { + background-color: black; + } + ak-locale-context { + display: flex; + flex-direction: column; + } + .pf-c-drawer__main { + min-height: calc(100vh - 76px); + max-height: calc(100vh - 76px); + } +`; - @property({ type: Boolean }) - apiDrawerOpen = getURLParam("apiDrawerOpen", false); +// ___ _ _ _ +// | _ \_ _ ___ ___ ___ _ _| |_ __ _| |_(_)___ _ _ +// | _/ '_/ -_|_- { - this.notificationDrawerOpen = !this.notificationDrawerOpen; - updateURLParams({ - notificationDrawerOpen: this.notificationDrawerOpen, - }); - }); - window.addEventListener(EVENT_API_DRAWER_TOGGLE, () => { - this.apiDrawerOpen = !this.apiDrawerOpen; - updateURLParams({ - apiDrawerOpen: this.apiDrawerOpen, - }); - }); - window.addEventListener(EVENT_WS_MESSAGE, () => { - this.firstUpdated(); - }); - configureSentry(true); + @property({ type: Object }) + uiConfig!: UIConfig; + + @property({ type: Object }) + me!: SessionUser; + + @property({ type: Boolean, reflect: true }) + notificationDrawerOpen = false; + + @property({ type: Boolean, reflect: true }) + apiDrawerOpen = false; + + @property({ type: Number }) + notificationsCount = 0; + + @property({ type: Object }) + brand!: CurrentBrand; + + get userDisplayName() { + return match(this.uiConfig.navbar.userDisplay) + .with(UserDisplay.username, () => this.me.user.username) + .with(UserDisplay.name, () => this.me.user.name) + .with(UserDisplay.email, () => this.me.user.email || "") + .otherwise(() => this.me.user.username); } async firstUpdated(): Promise { @@ -157,31 +170,27 @@ export class UserInterface extends Interface { this.notificationsCount = notifications.pagination.count; } - render(): TemplateResult { - if (!this.uiConfig || !this.me) { - return html``; - } - let userDisplay = ""; - switch (this.uiConfig.navbar.userDisplay) { - case UserDisplay.username: - userDisplay = this.me.user.username; - break; - case UserDisplay.name: - userDisplay = this.me.user.name; - break; - case UserDisplay.email: - userDisplay = this.me.user.email || ""; - break; - default: - userDisplay = this.me.user.username; - } - const canAccessUserDirectory = - this.me.user.isSuperuser || - this.me.user.systemPermissions.includes("can_view_user_directory"); - const canAccessAdmin = + get canAccessAdmin() { + return ( this.me.user.isSuperuser || // TODO: somehow add `access_admin_interface` to the API schema - this.me.user.systemPermissions.includes("access_admin_interface"); + this.me.user.systemPermissions.includes("access_admin_interface") + ); + } + + get isFullyConfigured() { + return !!(this.uiConfig && this.me && this.brand); + } + + render() { + // The `!` in the field definitions above only re-assure typescript and eslint that the + // values *should* be available, not that they *are*. Thus this contract check; it asserts + // that the contract we promised is being honored, and the rest of the code that depends on + // `!` being truthful is not being lied to. + if (!this.isFullyConfigured) { + throw new Error("ak-interface-user-presentation misused; no valid values passed"); + } + return html`
                @@ -195,17 +204,16 @@ export class UserInterface extends Interface { ${(this.brand?.brandingTitle, DefaultBrand.brandingTitle)}
                + <<<<<<< HEAD ${this.uiConfig.enabledFeatures.apiDrawer - ? html`
                + ? html`
                ` : html``} ${this.uiConfig.enabledFeatures.notificationDrawer - ? html`
                + ? html`
                ` : html``} - ${canAccessUserDirectory - ? html` ` - : html``} ${this.uiConfig.enabledFeatures.settings ? html` ` : html``} + ======= ${this.renderApiDrawerTrigger()} + + ${this.renderNotificationDrawerTrigger()} + + ${this.renderSettings()} >>>>>>> main - ${canAccessAdmin - ? html` - ${msg("Admin interface")} - ` - : html``} + ${this.renderAdminInterfaceLink()}
                - ${this.me.original - ? html`  -
                -
                - { - return new CoreApi(DEFAULT_CONFIG) - .coreUsersImpersonateEndRetrieve() - .then(() => { - window.location.reload(); - }); - }} - > - ${msg("Stop impersonation")} - -
                -
                ` - : html``} + ${this.renderImpersonation()}
                -
                - ${userDisplay} +
                + ${this.userDisplayName}
                - ${msg( + ${msg(
                @@ -368,16 +313,13 @@ export class UserInterface extends Interface {
                @@ -386,4 +328,211 @@ export class UserInterface extends Interface {
                `; } + + renderApiDrawerTrigger() { + if (!this.uiConfig.enabledFeatures.apiDrawer) { + return nothing; + } + + const onClick = (ev: Event) => { + ev.stopPropagation(); + this.dispatchEvent(new Event(EVENT_API_DRAWER_TOGGLE, { bubbles: true, composed: true })); + }; + + return html`
                + +
                `; + } + + renderNotificationDrawerTrigger() { + if (!this.uiConfig.enabledFeatures.notificationDrawer) { + return nothing; + } + + const onClick = (ev: Event) => { + ev.stopPropagation(); + this.dispatchEvent(new Event(EVENT_NOTIFICATION_DRAWER_TOGGLE, { bubbles: true, composed: true })); + }; + + return html`
                + +
                `; + } + + renderSettings() { + if (!this.uiConfig.enabledFeatures.settings) { + return nothing; + } + + return html` `; + } + + renderAdminInterfaceLink() { + if (!this.canAccessAdmin) { + return nothing; + } + + return html` + ${msg("Admin interface")} + `; + } + + renderUserDirectory() { + const canAccessUserDirectory = + this.me.user.isSuperuser || this.me.user.systemPermissions.includes("can_view_user_directory"); + + if (!canAccessUserDirectory) { + return nothing; + } + + return html` `; + } + + renderImpersonation() { + if (!this.me.original) { + return nothing; + } + + const onClick = () => { + return new CoreApi(DEFAULT_CONFIG).coreUsersImpersonateEndRetrieve().then(() => { + window.location.reload(); + }); + }; + + return html`  +
                +
                + + ${msg("Stop impersonation")} + +
                +
                `; + } +} + +// ___ _ +// | _ )_ _ __(_)_ _ ___ ______ +// | _ \ || (_-< | ' \/ -_|_-<_-< +// |___/\_,_/__/_|_||_\___/__/__/ +// +// +@customElement("ak-interface-user") +export class UserInterface extends EnterpriseAwareInterface { + @property({ type: Boolean }) + notificationDrawerOpen = getURLParam("notificationDrawerOpen", false); + + @state() + apiDrawerOpen = getURLParam("apiDrawerOpen", false); + + ws: WebsocketClient; + + @state() + notificationsCount = 0; + + @state() + me?: SessionUser; + + constructor() { + super(); + this.ws = new WebsocketClient(); + this.fetchConfigurationDetails(); + configureSentry(true); + this.toggleNotificationDrawer = this.toggleNotificationDrawer.bind(this); + this.toggleApiDrawer = this.toggleApiDrawer.bind(this); + this.fetchConfigurationDetails = this.fetchConfigurationDetails.bind(this); + } + + connectedCallback() { + super.connectedCallback(); + window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, this.toggleNotificationDrawer); + window.addEventListener(EVENT_API_DRAWER_TOGGLE, this.toggleApiDrawer); + window.addEventListener(EVENT_WS_MESSAGE, this.fetchConfigurationDetails); + } + + disconnectedCallback() { + window.removeEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, this.toggleNotificationDrawer); + window.removeEventListener(EVENT_API_DRAWER_TOGGLE, this.toggleApiDrawer); + window.removeEventListener(EVENT_WS_MESSAGE, this.fetchConfigurationDetails); + super.disconnectedCallback(); + } + + toggleNotificationDrawer() { + this.notificationDrawerOpen = !this.notificationDrawerOpen; + updateURLParams({ + notificationDrawerOpen: this.notificationDrawerOpen, + }); + } + + toggleApiDrawer() { + this.apiDrawerOpen = !this.apiDrawerOpen; + updateURLParams({ + apiDrawerOpen: this.apiDrawerOpen, + }); + } + + fetchConfigurationDetails() { + me().then((me: SessionUser) => { + this.me = me; + new EventsApi(DEFAULT_CONFIG) + .eventsNotificationsList({ + seen: false, + ordering: "-created", + pageSize: 1, + user: this.me.user.pk, + }) + .then((notifications) => { + this.notificationsCount = notifications.pagination.count; + }); + }); + } + + get isFullyConfigured() { + return !!(this.uiConfig && this.me); + } + + render() { + if (!this.isFullyConfigured) { + return nothing; + } + + return html``; + } } diff --git a/web/src/user/user-settings/UserSettingsPage.ts b/web/src/user/user-settings/UserSettingsPage.ts index 9506731728..8e016da8ee 100644 --- a/web/src/user/user-settings/UserSettingsPage.ts +++ b/web/src/user/user-settings/UserSettingsPage.ts @@ -4,11 +4,11 @@ import { AKElement, rootInterface } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/user/SessionList"; import "@goauthentik/elements/user/UserConsentList"; +import "@goauthentik/elements/user/sources/SourceSettings"; import { UserInterface } from "@goauthentik/user/UserInterface"; import "@goauthentik/user/user-settings/details/UserPassword"; import "@goauthentik/user/user-settings/details/UserSettingsFlowExecutor"; import "@goauthentik/user/user-settings/mfa/MFADevicesPage"; -import "@goauthentik/user/user-settings/sources/SourceSettings"; import "@goauthentik/user/user-settings/tokens/UserTokenList"; import { localized, msg } from "@lit/localize"; @@ -156,9 +156,14 @@ export class UserSettingsPage extends AKElement { class="pf-c-page__main-section pf-m-no-padding-mobile" >
                -
                - +
                + ${msg( + "Connect your user account to the services listed below, to allow you to login using the service instead of traditional credentials.", + )}
                + ()?.me?.user.pk)} + >
                + ${msg("Open settings")} `; diff --git a/web/src/user/user-settings/mfa/MFADevicesPage.ts b/web/src/user/user-settings/mfa/MFADevicesPage.ts index 5b26d152e8..86578c920e 100644 --- a/web/src/user/user-settings/mfa/MFADevicesPage.ts +++ b/web/src/user/user-settings/mfa/MFADevicesPage.ts @@ -25,6 +25,7 @@ export class MFADevicesPage extends Table { userSettings?: UserSetting[]; checkbox = true; + clearOnRefresh = true; async apiEndpoint(): Promise> { const devices = await new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAllList(); diff --git a/web/src/user/user-settings/tokens/UserTokenForm.ts b/web/src/user/user-settings/tokens/UserTokenForm.ts index 78ce3413df..d0fce872f2 100644 --- a/web/src/user/user-settings/tokens/UserTokenForm.ts +++ b/web/src/user/user-settings/tokens/UserTokenForm.ts @@ -1,4 +1,5 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { dateTimeLocal } from "@goauthentik/common/utils"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; @@ -28,6 +29,7 @@ export class UserTokenForm extends ModelForm { async send(data: Token): Promise { if (this.instance) { + data.intent = this.instance.intent; return new CoreApi(DEFAULT_CONFIG).coreTokensUpdate({ identifier: this.instance.identifier, tokenRequest: data, @@ -41,6 +43,11 @@ export class UserTokenForm extends ModelForm { } renderForm(): TemplateResult { + const now = new Date(); + const expiringDate = this.instance?.expires + ? new Date(this.instance.expires.getTime()) + : new Date(now.getTime() + 30 * 60000); + return html` { value="${ifDefined(this.instance?.description)}" class="pf-c-form-control" /> - `; + + ${this.intent == IntentEnum.AppPassword + ? html` + + ` + : html``}`; } } diff --git a/web/src/user/user-settings/tokens/UserTokenList.ts b/web/src/user/user-settings/tokens/UserTokenList.ts index 82cadeee14..9cc8e588ea 100644 --- a/web/src/user/user-settings/tokens/UserTokenList.ts +++ b/web/src/user/user-settings/tokens/UserTokenList.ts @@ -2,6 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { intentToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; +import { getRelativeTime } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-status-label"; import "@goauthentik/elements/buttons/Dropdown"; import "@goauthentik/elements/buttons/ModalButton"; @@ -29,6 +30,7 @@ export class UserTokenList extends Table { expandable = true; checkbox = true; + clearOnRefresh = true; @property() order = "expires"; @@ -107,7 +109,14 @@ export class UserTokenList extends Table {
                - ${item.expiring ? item.expires?.toLocaleString() : msg("-")} + ${item.expiring + ? html` + ${getRelativeTime(item.expires!)} + ` + : msg("-")}
                @@ -151,7 +160,11 @@ export class UserTokenList extends Table { ${msg("Update")} ${msg("Update Token")} - +
                @@ -107,9 +107,7 @@ Templates are rendered using Django's templating engine. The following variables
                ${key}
                -
                -${JSON.stringify(diff[key].previous_value, null, 4)}
                -
                -
                ${JSON.stringify(diff[key].new_value, null, 4)}
                +
                ${previousCol}
                ${newCol}
                +
                +
                +
                +
                + ${msg("Timestamp")} +
                +
                +
                + ${item.timestamp.toLocaleString()} +
                +
                +
                +
                +
                + ${msg("Attributes")} +
                +
                +
                +
                ${JSON.stringify(item.attributes, null, 4)}
                +
                +
                +
                +
                +
                +
                +
                +
                +
                +

                ${msg("ID Token")}

                +
                ${item.idToken}
                +
                +
                +
                +
                - {% blocktrans with username=user.username %} Hi {{ username }}, {% - endblocktrans %} + {% blocktrans with username=user.username %} Hi {{ username }}, + {% endblocktrans %}
                diff --git a/website/docs/flow/stages/identification/index.md b/website/docs/flow/stages/identification/index.md index 3b9d647412..ad05f23901 100644 --- a/website/docs/flow/stages/identification/index.md +++ b/website/docs/flow/stages/identification/index.md @@ -12,7 +12,7 @@ Select which fields the user can use to identify themselves. Multiple fields can - Email - UPN - UPN will attempt to identify the user based on the `upn` attribute, which can be imported with an [LDAP Source](/integrations/sources/ldap/) + UPN will attempt to identify the user based on the `upn` attribute, which can be imported with an [LDAP Source](/docs/sources/ldap/) ## Password stage @@ -25,14 +25,14 @@ These fields specify if and which flows are linked on the form. The enrollment f ## Pretend user exists :::info -Requires authentik 2024.1 +Requires authentik 2024.2 ::: When enabled, any user identifier will be accepted as valid (as long as they match the correct format, i.e. when [User fields](#user-fields) is set to only allow Emails, then the identifier still needs to be an Email). The stage will succeed and the flow will continue to the next stage. Stages like the [Password stage](../password/index.md) and [Email stage](../email/index.mdx) are aware of this "pretend" user and will behave the same as if the user would exist. ## Source settings -Some sources (like the [OAuth Source](../../../../integrations/sources/oauth/) and [SAML Source](../../../../integrations/sources/saml/)) require user interaction. To make these sources available to users, they can be selected in the Identification stage settings, which will show them below the selected [user field](#user-fields). +Some sources (like the [OAuth Source](../../../../docs/sources/oauth/) and [SAML Source](../../../../docs/sources/saml/)) require user interaction. To make these sources available to users, they can be selected in the Identification stage settings, which will show them below the selected [user field](#user-fields). By default, sources are only shown with their icon, which can be changed with the _Show sources' labels_ option. diff --git a/website/docs/flow/stages/source/index.md b/website/docs/flow/stages/source/index.md new file mode 100644 index 0000000000..e9fe848abb --- /dev/null +++ b/website/docs/flow/stages/source/index.md @@ -0,0 +1,57 @@ +--- +title: Source stage +--- + +Enterprise +authentik 2024.4+ + +--- + +The source stage injects an [OAuth](../../../../docs/sources/oauth/) or [SAML](../../../../docs/sources/saml/) Source into the flow execution. This allows for additional user verification, or to dynamically access different sources for different user identifiers (username, email address, etc). + +```mermaid +sequenceDiagram + participant u as User + participant ak as authentik + participant eidp as External IDP + + u->>ak: User initiates flow + ak->>u: User reaches Source Stage + + u->>eidp: User is redirected to external IDP + eidp->>ak: User has authenticated with external IDP + + alt User is connected to external IDP (auth) + ak->>u: Source's authentication flow is started + u->>ak: User finishes source's authentication flow + else User has not been connected to external IDP (enroll) + ak->>u: Source's enrollment flow is started + u->>ak: User finishes source's enrollment flow + end + + ak->>u: Execution of the previous flow is resumed +``` + +### Considerations + +It is very important that the configured source's authentication and enrollment flows (when set; they can be left unselected to prevent authentication or enrollment with the source) do **not** have a [User login stage](../user_login/index.md) bound to them. + +This is because the Source stage works by appending a [dynamic in-memory](../../../core/terminology.md#dynamic-in-memory-stage) stage to the source's flow, so having a [User login stage](../user_login/index.md) bound will cause the source's flow to not resume the original flow it was started from, and instead directly authenticating the pending user. + +### Example use case + +This stage can be used to leverage an external OAuth/SAML identity provider. + +For example, you can authenticate users by routing them through a custom device-health solution. + +Another use case is to route users to authenticate with your legacy (Okta, etc) IdP and then use the returned identity and attributes within authentik as part of an authorization flow, for example as part of an IdP migration. For authentication/enrollment this is also possible with an [OAuth](../../../../docs/sources/oauth/)/[SAML](../../../../docs/sources/saml/) source by itself. + +### Options + +#### Source + +The source the user is redirected to. Must be a web-based source, such as [OAuth](../../../../docs/sources/oauth/) or [SAML](../../../../docs/sources/saml/). Sources like [LDAP](../../../../docs/sources/ldap/) are _not_ compatible. + +#### Resume timeout + +Because the execution of the current flow is suspended before the user is redirected to the configured source, this option configures how long the suspended flow is saved. If this timeout is exceeded, upon return from the configured source, the suspended flow will restart from the beginning. diff --git a/website/docs/flow/stages/user_login/index.md b/website/docs/flow/stages/user_login/index.md index 92d655093b..a9f00bb5bc 100644 --- a/website/docs/flow/stages/user_login/index.md +++ b/website/docs/flow/stages/user_login/index.md @@ -39,8 +39,6 @@ When configured, all sessions authenticated by this stage will be bound to the s Sessions which break this binding will be terminated on use. The created [`logout`](../../../events/index.md#logout) event will contain additional data related to what caused the binding to be broken: ```json - -Context { "asn": { "asn": 6805, @@ -65,7 +63,7 @@ Context }, "ip": { "previous": "1.2.3.4", - "new": "5.6.7.8", + "new": "5.6.7.8" }, "http_request": { "args": {}, diff --git a/website/docs/index.mdx b/website/docs/index.mdx index 25afbf72ea..75539721d0 100755 --- a/website/docs/index.mdx +++ b/website/docs/index.mdx @@ -3,25 +3,25 @@ title: Welcome to authentik slug: / --- -## About authentik technical documentation +## About authentik documentation -Our tech docs cover the typical topics, from installation to configuration, adding providers, defining policies and creating login flows, event monitoring, security, and attributes. [Enterprise](./enterprise) version documentation is included here, within our standard tech docs. +Our tech docs cover the typical topics, from installation to configuration, adding providers, defining policies and creating login flows, event monitoring, security, and attributes. [Enterprise](./enterprise/index.md) version documentation is included here, within our standard tech docs. -- For information about integrating a specific application or software into authentik, refer to our [Integrations](../integrations) section, accessible from the top menu-bar. +- For information about integrating a specific application or software into authentik, refer to our Integrations section, accessible from the top menu bar. -- For developer-focused documentation, such as using our APIs and blueprints, setting up your development environment, translations, or how to contribute, refer to the [Developer](../developer-docs) area, accessible from the top menu-bar. +- For developer-focused documentation, such as using our APIs and blueprints, setting up your development environment, translations, or how to contribute, refer to the [Developer](../developer-docs) area, accessible from the top menu bar. ## What is authentik? authentik is an open-source Identity Provider, focused on flexibility and versatility. With authentik, site administrators, application developers, and security engineers have a dependable and secure solution for authentication in almost any type of environment. There are robust recovery actions available for the users and applications, including user profile and password management. You can quickly edit, deactivate, or even impersonate a user profile, and set a new password for new users or reset an existing password. -You can use authentik in an existing environment to add support for new protocols, so introducing authentik to your current tech stack doesn't present re-architecting challenges. We already support all of the major providers, such as OAuth2, SAML, LDAP, and SCIM, so you can pick the protocol that you need for each application. +You can use authentik in an existing environment to add support for new protocols, so introducing authentik to your current tech stack doesn't present re-architecting challenges. We support all of the major providers, such as OAuth2, SAML, LDAP, and SCIM, so you can pick the protocol that you need for each application. The authentik product provides the following consoles: - **Admin interface**: a visual tool for the creation and management of users and groups, tokens and credentials, application integrations, events, and the Flows that define standard and customizable login and authentication processes. Easy-to-read visual dashboards display system status, recent logins and authentication events, and application usage. -- **User interface**: this console view in authentik displays all of the applications and integrations in which you have implemented authentik. Click on the app that you want to access to open it, or drill down to edit its configuration in the admin interface +- **User interface**: this console view in authentik displays all of the applications and integrations in which you have implemented authentik. Click on the app that you want to access to open it, or drill down to edit its configuration in the admin interface. - **Flows**: [_Flows_](./flow) are the steps by which the various _Stages_ of a login and authentication process occurs. A stage represents a single verification or logic step in the sign-on process. authentik allows for the customization and exact definition of these flows. @@ -29,11 +29,11 @@ The authentik product provides the following consoles: Refer to the installation steps in either [Docker-compose](installation/docker-compose) or [Kubernetes](installation/kubernetes). -For more information about configuration, Beta versions, and additional installation options, see our main [Installation](installation) section. +For more information about configuration, beta versions, and additional installation options, see our main [Installation](installation) section. ## Screenshots -authentik can use Light or Dark mode for the Admin interface, User interface and the flow interface. +authentik can use Light or Dark mode for the Admin interface, User interface and the Flow interface. import "react-before-after-slider-component/dist/build.css"; import ReactBeforeSliderComponent from "react-before-after-slider-component"; diff --git a/website/docs/installation/air-gapped.md b/website/docs/installation/air-gapped.md deleted file mode 100644 index dc98f65904..0000000000 --- a/website/docs/installation/air-gapped.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Air-gapped environments ---- - -## Outbound connections - -By default, authentik creates outbound connections to the following URLs: - -- https://version.goauthentik.io: Periodic update check -- https://goauthentik.io: Anonymous analytics on startup -- https://secure.gravatar.com: Avatars for users -- https://authentik.error-reporting.a7k.io: Error reporting - -To disable these outbound connections, set the following in your `.env` file: - -``` -AUTHENTIK_DISABLE_UPDATE_CHECK=true -AUTHENTIK_ERROR_REPORTING__ENABLED=false -AUTHENTIK_DISABLE_STARTUP_ANALYTICS=true -AUTHENTIK_AVATARS=initials -``` - -For a Helm-based install, set the following in your values.yaml file: - -```yaml -authentik: - avatars: none - error_reporting: - enabled: false - disable_update_check: true - disable_startup_analytics: true -``` - -## Container images - -Container images can be pulled from the following URLs: - -- ghcr.io/goauthentik/server (https://ghcr.io) -- beryju/authentik (https://index.docker.io) diff --git a/website/docs/installation/air-gapped.mdx b/website/docs/installation/air-gapped.mdx new file mode 100644 index 0000000000..45ef8a4362 --- /dev/null +++ b/website/docs/installation/air-gapped.mdx @@ -0,0 +1,68 @@ +--- +title: Air-gapped environments +--- + +## Outbound connections + +By default, authentik creates outbound connections to the following URLs: + +- https://version.goauthentik.io: Periodic update check +- https://goauthentik.io: Anonymous analytics on startup +- https://secure.gravatar.com: Avatars for users +- https://authentik.error-reporting.a7k.io: Error reporting + +To disable these outbound connections, set the following in your `.env` file: + +## Configuration options + +To see a list of all configuration options, see [here](./configuration.mdx). + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + +Add the following block to your `.env` file: + +```shell +AUTHENTIK_DISABLE_STARTUP_ANALYTICS=true +AUTHENTIK_DISABLE_UPDATE_CHECK=true +AUTHENTIK_ERROR_REPORTING__ENABLED=false +``` + +Afterwards, run the upgrade commands from the latest release notes. + + + +Add the following block to your `values.yml` file: + +```yaml +authentik: + error_reporting: + enabled: false + disable_update_check: true + disable_startup_analytics: true +``` + +Afterwards, run the upgrade commands from the latest release notes. + + + + +## Settings + +In addition to the configuration options above, the following [System settings](../core/settings.md) need to also be adjusted: + +- **Avatars**: By default this setting uses [Gravatar](https://secure.gravatar.com/). The option can be set to a combination of any of the other options, for example `initials` + +## Container images + +Container images can be pulled from the following URLs: + +- ghcr.io/goauthentik/server (https://ghcr.io) +- beryju/authentik (https://index.docker.io) diff --git a/website/docs/installation/beta.mdx b/website/docs/installation/beta.mdx index 6f02522670..6a548934d7 100644 --- a/website/docs/installation/beta.mdx +++ b/website/docs/installation/beta.mdx @@ -64,8 +64,8 @@ Next, run the upgrade commands below. ```shell -docker-compose pull -docker-compose up -d +docker compose pull +docker compose up -d ``` diff --git a/website/docs/installation/configuration.mdx b/website/docs/installation/configuration.mdx index 13646e92a2..c58d99e02a 100644 --- a/website/docs/installation/configuration.mdx +++ b/website/docs/installation/configuration.mdx @@ -25,7 +25,7 @@ import TabItem from "@theme/TabItem"; If you are using Docker Compose, edit your .env file to append any keys that you want to add, and then run the following command to apply them: ``` - docker-compose up -d + docker compose up -d ``` @@ -49,7 +49,7 @@ To check if your config has been applied correctly, you can run the following co ``` - docker-compose run --rm worker dump_config + docker compose run --rm worker dump_config ``` @@ -72,11 +72,31 @@ To check if your config has been applied correctly, you can run the following co - `AUTHENTIK_POSTGRESQL__PASSWORD`: Database password, defaults to the environment variable `POSTGRES_PASSWORD` - `AUTHENTIK_POSTGRESQL__USE_PGBOUNCER`: Adjust configuration to support connection to PgBouncer - `AUTHENTIK_POSTGRESQL__USE_PGPOOL`: Adjust configuration to support connection to Pgpool -- `AUTHENTIK_POSTGRESQL__SSLMODE`: Strictness of ssl verification. Defaults to `verify-ca` +- `AUTHENTIK_POSTGRESQL__SSLMODE`: Strictness of ssl verification. Defaults to `"verify-ca"` - `AUTHENTIK_POSTGRESQL__SSLROOTCERT`: CA root for server ssl verification - `AUTHENTIK_POSTGRESQL__SSLCERT`: Path to x509 client certificate to authenticate to server - `AUTHENTIK_POSTGRESQL__SSLKEY`: Path to private key of `SSLCERT` certificate +All PostgreSQL settings, apart from `USE_PGBOUNCER` and `USE_PGPOOL`, support hot-reloading. Adding and removing read replicas doesn't support hot-reloading. + +### Read replicas + +Additional databases used only for read operations can be configured. Increase the number (by default `0`) in the following configuration settings for each read replica. + +If read replicas are configured, the main database is not used for reads. If you'd like the main database to be included for reads, add it as a read replica. + +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__HOST`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__NAME`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__USER`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PORT`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PASSWORD`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLMODE`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLROOTCERT`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLCERT`: same as above +- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLKEY`: same as above + +Note that `USE_PGBOUNCER` and `USE_PGPOOL` are inherited from the main database configuration and are _not_ overridable on read replicas. + ## Redis Settings - `AUTHENTIK_REDIS__HOST`: Redis server host when not using configuration URL @@ -85,7 +105,8 @@ To check if your config has been applied correctly, you can run the following co - `AUTHENTIK_REDIS__USERNAME`: Redis server username when not using configuration URL - `AUTHENTIK_REDIS__PASSWORD`: Redis server password when not using configuration URL - `AUTHENTIK_REDIS__TLS`: Redis server connection using TLS when not using configuration URL -- `AUTHENTIK_REDIS__TLS_REQS`: Redis server TLS connection requirements when not using configuration URL +- `AUTHENTIK_REDIS__TLS_REQS`: Redis server TLS connection requirements when not using configuration URL. Defaults to `"none"`. Allowed values are `"none"` and `"required"`. +- `AUTHENTIK_REDIS__TLS_CA_CERT`: Path to the Redis server TLS CA root when not using configuration URL. Defaults to `null`. ## Result Backend Settings @@ -110,7 +131,7 @@ To check if your config has been applied correctly, you can run the following co ## Broker Settings - `AUTHENTIK_BROKER__URL`: Broker configuration URL, defaults to Redis using [the respective settings](#redis-settings) -- `AUTHENTIK_BROKER__TRANSPORT_OPTIONS`: Base64 encoded broker transport options +- `AUTHENTIK_BROKER__TRANSPORT_OPTIONS`: Base64-encoded broker transport options :::info `AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION` only applies to the cache expiry, see [`AUTHENTIK_REPUTATION__EXPIRY`](#authentik_reputation__expiry) to control how long reputation is persisted for. @@ -134,29 +155,33 @@ To check if your config has been applied correctly, you can run the following co These settings affect where media files are stored. Those files include applications and sources icons. By default, they are stored on disk in the `/media` directory of the authentik container. S3 storage is also supported. -- `AUTHENTIK_STORAGE_MEDIA_BACKEND`: Where to store files. Valid values are `file` and `s3`. For `file` storage, files are stored in a `/media` directory in the container. For `s3`, see below. -- `AUTHENTIK_STORAGE_MEDIA_S3_REGION`: S3 region where the bucket has been created. May be omitted depending on which S3 provider you use. No default. -- `AUTHENTIK_STORAGE_MEDIA_S3_USE__SSL`: Whether to use HTTPS when talking to the S3 storage providers. Defaults to `true`. -- `AUTHENTIK_STORAGE_MEDIA_S3_ENDPOINT`: Endpoint to use to talk to the S3 storage provider. Override the previous region and use_ssl settings. Must be a valid URL in the form of `https://s3.provider`. No default. -- `AUTHENTIK_STORAGE_MEDIA_S3_SESSION__PROFILE`: Profile to use when using AWS SDK authentication. No default. Supports hot-reloading. -- `AUTHENTIK_STORAGE_MEDIA_S3_ACCESS__KEY`: Access key to authenticate to S3. May be omitted if using AWS SDK authentication. Supports hot-reloading. -- `AUTHENTIK_STORAGE_MEDIA_S3_SECRET__KEY`: Secret key to authenticate to S3. May be omitted if using AWS SDK authentication. Supports hot-reloading. -- `AUTHENTIK_STORAGE_MEDIA_S3_SECURITY__TOKEN`: Security token to authenticate to S3. May be omitted. Supports hot-reloading. -- `AUTHENTIK_STORAGE_MEDIA_S3_BUCKET__NAME`: Name of the bucket to use to store files. -- `AUTHENTIK_STORAGE_MEDIA_S3_CUSTOM__DOMAIN`: Domain to use to create URLs for users. Mainly useful for non-AWS providers. May include a port. Must include the bucket. Example: `s3.company:8080/authentik-media`. -- `AUTHENTIK_STORAGE_MEDIA_S3_SECURE__URLS`: Whether URLS created for users use `http` or `https`. Defaults to `true`. +- `AUTHENTIK_STORAGE__MEDIA__BACKEND`: Where to store files. Valid values are `file` and `s3`. For `file` storage, files are stored in a `/media` directory in the container. For `s3`, see below. +- `AUTHENTIK_STORAGE__MEDIA__S3__REGION`: S3 region where the bucket has been created. May be omitted depending on which S3 provider you use. No default. +- `AUTHENTIK_STORAGE__MEDIA__S3__USE_SSL`: Whether to use HTTPS when talking to the S3 storage providers. Defaults to `true`. +- `AUTHENTIK_STORAGE__MEDIA__S3__ENDPOINT`: Endpoint to use to talk to the S3 storage provider. Override the previous region and use_ssl settings. Must be a valid URL in the form of `https://s3.provider`. No default. +- `AUTHENTIK_STORAGE__MEDIA__S3__SESSION_PROFILE`: Profile to use when using AWS SDK authentication. No default. Supports hot-reloading. +- `AUTHENTIK_STORAGE__MEDIA__S3__ACCESS_KEY`: Access key to authenticate to S3. May be omitted if using AWS SDK authentication. Supports hot-reloading. +- `AUTHENTIK_STORAGE__MEDIA__S3__SECRET_KEY`: Secret key to authenticate to S3. May be omitted if using AWS SDK authentication. Supports hot-reloading. +- `AUTHENTIK_STORAGE__MEDIA__S3__SECURITY_TOKEN`: Security token to authenticate to S3. May be omitted. Supports hot-reloading. +- `AUTHENTIK_STORAGE__MEDIA__S3__BUCKET_NAME`: Name of the bucket to use to store files. +- `AUTHENTIK_STORAGE__MEDIA__S3__CUSTOM_DOMAIN`: Domain to use to create URLs for users. Mainly useful for non-AWS providers. May include a port. Must include the bucket. Example: `s3.company:8080/authentik-media`. +- `AUTHENTIK_STORAGE__MEDIA__S3__SECURE_URLS`: Whether URLs created use HTTPS (set to `true` by default) or HTTP. ## authentik Settings ### `AUTHENTIK_SECRET_KEY` -Secret key used for cookie signing and unique user IDs, don't change this after the first install. +Secret key used for cookie signing. Changing this will invalidate active sessions. + +:::caution +Prior to 2023.6.0 the secret key was also used for unique user IDs. When running a pre-2023.6.0 version of authentik the key should _not_ be changed after the first install. +::: ### `AUTHENTIK_LOG_LEVEL` -Log level for the server and worker containers. Possible values: debug, info, warning, error +Log level for the server and worker containers. Possible values: `debug`, `info`, `warning`, `error`. -Starting with 2021.12.3, you can also set the log level to _trace_. This has no affect on the core authentik server, but shows additional messages for the embedded outpost. +Starting with 2021.12.3, you can also set the log level to `trace`. This has no effect on the core authentik server, but shows additional messages for the embedded outpost. :::danger Setting the log level to `trace` will include sensitive details in logs, so it shouldn't be used in most cases. @@ -188,7 +213,7 @@ Disable the inbuilt update-checker. Defaults to `false`. Enable error reporting. Defaults to `false`. - Error reports are sent to https://sentry.io, and are used for debugging and general feedback. Anonymous performance data is also sent. + Error reports are sent to https://sentry.io and are used for debugging and general feedback. Anonymous performance data is also sent. - `AUTHENTIK_ERROR_REPORTING__SENTRY_DSN` @@ -202,8 +227,7 @@ Disable the inbuilt update-checker. Defaults to `false`. The environment tag associated with all data sent to Sentry. Defaults to `customer`. - When error reporting has been enabled to aid in debugging issues, this should be set to a unique - value, such as an e-mail address. + When error reporting has been enabled to aid in debugging issues, this should be set to a unique value, such as an email address. - `AUTHENTIK_ERROR_REPORTING__SEND_PII` @@ -269,89 +293,6 @@ Disable the inbuilt update-checker. Defaults to `false`. - Kubeconfig - Existence of a docker socket -### `AUTHENTIK_AVATARS` - -Configure how authentik should show avatars for users. Following values can be set: - -Default: `gravatar,initials` - -- `none`: Disables per-user avatars and just shows a 1x1 pixel transparent picture -- `gravatar`: Uses gravatar with the user's email address -- `initials`: Generated avatars based on the user's name -- Any URL: If you want to use images hosted on another server, you can set any URL. - - Additionally, these placeholders can be used: - - - `%(username)s`: The user's username - - `%(mail_hash)s`: The email address, md5 hashed - - `%(upn)s`: The user's UPN, if set (otherwise an empty string) - -Starting with authentik 2022.8, you can also use an attribute path like `attributes.something.avatar`, which can be used in combination with the file field to allow users to upload custom avatars for themselves. - -Starting with authentik 2023.2, multiple modes can be set, and authentik will fallback to the next mode when no avatar could be found. For example, setting this to `gravatar,initials` will attempt to get an avatar from Gravatar, and if the user has not configured on there, it will fallback to a generated avatar. - -### `AUTHENTIK_DEFAULT_USER_CHANGE_NAME` - -:::info -Requires authentik 2021.12.5 -::: - -Enable the ability for users to change their name, defaults to `true`. - -### `AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL` - -:::info -Requires authentik 2021.12.1 -::: - -Enable the ability for users to change their Email address, defaults to `false`. - -### `AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME` - -:::info -Requires authentik 2021.12.1 -::: - -Enable the ability for users to change their Usernames, defaults to `false`. - -### `AUTHENTIK_GDPR_COMPLIANCE` - -:::info -Requires authentik 2021.12.1 -::: - -When enabled, all the events caused by a user will be deleted upon the user's deletion. Defaults to `true`. - -### `AUTHENTIK_DEFAULT_TOKEN_LENGTH` - -:::info -Requires authentik 2022.4.1 -::: - -Configure the length of generated tokens. Defaults to 60. - -### `AUTHENTIK_IMPERSONATION` - -:::info -Requires authentik 2022.4.2 -::: - -Globally enable/disable impersonation. Defaults to `true`. - -### `AUTHENTIK_FOOTER_LINKS` - -:::info -Requires authentik 2021.12.1 -::: - -This option configures the footer links on the flow executor pages. - -The setting can be used as follows: - -``` -AUTHENTIK_FOOTER_LINKS='[{"name": "Link Name","href":"https://goauthentik.io"}]' -``` - ### `AUTHENTIK_LDAP__TASK_TIMEOUT_HOURS` :::info @@ -392,6 +333,14 @@ Configure how long reputation scores should be saved for in seconds. Note that t Defaults to `86400`. +### `AUTHENTIK_SESSION_STORAGE` + +:::info +Requires authentik 2024.4 +::: + +Configure if the sessions are stored in the cache or the database. Defaults to `cache`. Allowed values are `cache` and `db`. Note that changing this value will invalidate all previous sessions. + ### `AUTHENTIK_WEB__WORKERS` :::info @@ -400,8 +349,7 @@ Requires authentik 2022.9 Configure how many gunicorn worker processes should be started (see https://docs.gunicorn.org/en/stable/design.html). -If running in Kubernetes, the default value is set to 2 and should in most cases not be changed, as scaling can be done with multiple pods running the web server. -Otherwise, authentik will use 1 worker for each 4 CPU cores + 1 as a value below 2 workers is not recommended. +Defaults to 2. A value below 2 workers is not recommended. In environments where scaling with multiple replicas of the authentik server is not possible, this number can be increased to handle higher loads. ### `AUTHENTIK_WEB__THREADS` @@ -423,9 +371,17 @@ Configure Celery worker concurrency for authentik worker (see https://docs.celer Defaults to 2. +## System settings + +:::info +Requires authentik 2024.2 +::: + +Additional settings are configurable using the Admin interface, under **System** -> **Settings** or using the API. + ## Custom python settings -To modify additional settings further than the options above allow, you can create a custom python file and mount it to `/data/user_settings.py`. This file will be loaded on startup by both the server and the worker. All default settings are [here](https://github.com/goauthentik/authentik/blob/main/authentik/root/settings.py) +To modify additional settings further than the options above allow, you can create a custom Python file and mount it to `/data/user_settings.py`. This file will be loaded on startup by both the server and the worker. All default settings are [here](https://github.com/goauthentik/authentik/blob/main/authentik/root/settings.py) :::caution Using these custom settings is not supported and can prevent your authentik instance from starting. Use with caution. diff --git a/website/docs/installation/docker-compose.md b/website/docs/installation/docker-compose.mdx similarity index 58% rename from website/docs/installation/docker-compose.md rename to website/docs/installation/docker-compose.mdx index 372510d8e3..2704598b28 100644 --- a/website/docs/installation/docker-compose.md +++ b/website/docs/installation/docker-compose.mdx @@ -2,42 +2,61 @@ title: Docker Compose installation --- -This installation method is for test-setups and small-scale production setups. +This installation method is for test setups and small-scale production setups. ## Requirements - A host with at least 2 CPU cores and 2 GB of RAM - Docker -- Docker Compose +- Docker Compose (Compose v2 is recommended, see [here](https://docs.docker.com/compose/migrate/) for instructions on how to upgrade) ## Video - + ## Preparation To download the latest `docker-compose.yml` open your terminal and navigate to the directory of your choice. Run the following command: +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +{/* prettier-ignore */} + + + ```shell + wget https://goauthentik.io/docker-compose.yml + ``` + + + ```shell + curl -O https://goauthentik.io/docker-compose.yml + ``` + + + +If this is a fresh authentik installation, you need to generate a password and a secret key. Use a secure password generator of your choice such as pwgen, or you can use `openssl` as below. + +Run the following commands to generate a password and secret key and write them to your `.env` file: + +{/* prettier-ignore */} ```shell -wget https://goauthentik.io/docker-compose.yml +echo "PG_PASS=$(openssl rand 36 | base64)" >> .env +echo "AUTHENTIK_SECRET_KEY=$(openssl rand 60 | base64)" >> .env ``` -If this is a fresh authentik installation, you need to generate a password and a secret key. If you don't already have a password generator installed, you can run this command to install **pwgen**, a popular generator: - -```shell -# You can also use openssl instead: `openssl rand -base64 36` -sudo apt-get install -y pwgen -``` - -Next, run the following commands to generate a password and secret key and write them to your `.env` file: - -```shell -echo "PG_PASS=$(pwgen -s 40 1)" >> .env -echo "AUTHENTIK_SECRET_KEY=$(pwgen -s 50 1)" >> .env -# Because of a PostgreSQL limitation, only passwords up to 99 chars are supported -# See https://www.postgresql.org/message-id/09512C4F-8CB9-4021-B455-EF4C4F0D55A0@amazon.com -``` +:::info +Because of a PostgreSQL limitation, only passwords up to 99 chars are supported. See: https://www.postgresql.org/message-id/09512C4F-8CB9-4021-B455-EF4C4F0D55A0@amazon.com +::: To enable error reporting, run the following command: @@ -76,7 +95,7 @@ COMPOSE_PORT_HTTP=80 COMPOSE_PORT_HTTPS=443 ``` -See [Configuration](../installation/configuration) to change the internal ports. Be sure to run `docker-compose up -d` to rebuild with the new port numbers. +See [Configuration](../installation/configuration) to change the internal ports. Be sure to run `docker compose up -d` to rebuild with the new port numbers. ## Startup @@ -87,17 +106,17 @@ Do not update or mount `/etc/timezone` or `/etc/localtime` in the authentik cont This will not give any advantages. It will cause problems with OAuth and SAML authentication, e.g. [see this GitHub issue](https://github.com/goauthentik/authentik/issues/3005). ::: -Afterwards, run these commands to finish: +Afterward, run these commands to finish: ```shell -docker-compose pull -docker-compose up -d +docker compose pull +docker compose up -d ``` The `docker-compose.yml` file statically references the latest version available at the time of downloading the compose file. Each time you upgrade to a newer version of authentik, you download a new `docker-compose.yml` file, which points to the latest available version. For more information, refer to the **Upgrading** section in the [Release Notes](../releases). To start the initial setup, navigate to `http://:9000/if/flow/initial-setup/`. -There you are prompted to set a password for the akadmin user (the default user). +There you are prompted to set a password for the `akadmin` user (the default user). -An explanation about what each service in the docker compose file does, see [Architecture](../core/architecture.md). +For an explanation about what each service in the docker compose file does, see [Architecture](../core/architecture.md). diff --git a/website/docs/installation/kubernetes.md b/website/docs/installation/kubernetes.md index 0fdae2fca2..abb0a26a3b 100644 --- a/website/docs/installation/kubernetes.md +++ b/website/docs/installation/kubernetes.md @@ -21,9 +21,9 @@ You can also [view a video walk-through](https://www.youtube.com/watch?v=O1qUbrk Start by generating passwords for the database and cache. You can use either of the following commands: -``` +```shell pwgen -s 50 1 -openssl rand -base64 36 +openssl rand 60 | base64 ``` ### Set Values @@ -32,7 +32,7 @@ Create a `values.yaml` file with a minimum of these settings: ```yaml authentik: - secret_key: "PleaseGenerateA50CharKey" + secret_key: "PleaseGenerateASecureKey" # This sends anonymous usage-data, stack traces on errors and # performance data to sentry.io, and is fully opt-in error_reporting: @@ -40,20 +40,18 @@ authentik: postgresql: password: "ThisIsNotASecurePassword" -ingress: - # Specify kubernetes ingress controller class name - ingressClassName: nginx | traefik | kong - enabled: true - hosts: - # Specify external host name - - host: authentik.domain.tld - paths: - - path: "/" - pathType: Prefix +server: + ingress: + # Specify kubernetes ingress controller class name + ingressClassName: nginx | traefik | kong + enabled: true + hosts: + - authentik.domain.tld postgresql: enabled: true - postgresqlPassword: "ThisIsNotASecurePassword" + auth: + password: "ThisIsNotASecurePassword" redis: enabled: true ``` @@ -62,9 +60,9 @@ See all configurable values on [ArtifactHub](https://artifacthub.io/packages/hel ### Install authentik Helm Chart -Now, execute the following commands to install authentik +Now, execute the following commands to install authentik: -``` +```shell helm repo add authentik https://charts.goauthentik.io helm repo update helm upgrade --install authentik authentik/authentik -f values.yaml @@ -74,7 +72,7 @@ During the installation process, the database migrations will be applied automat ### Accessing authentik -Once the installation is complete, access authentik at `https:///if/flow/initial-setup/`. Here, you can set a password for the default akadmin user. +After the installation is complete, access authentik at `https:///if/flow/initial-setup/`. Here, you can set a password for the default `akadmin` user. ### Optional step: Configure global email credentials @@ -89,17 +87,17 @@ email: # -- SMTP Server emails are sent from, fully optional host: "" port: 587 - # -- SMTP credentials, when left empty, no authentication will be done + # -- SMTP credentials. When left empty, no authentication will be done. username: "" - # -- SMTP credentials, when left empty, no authentication will be done + # -- SMTP credentials. When left empty, no authentication will be done. password: "" - # -- Enable either use_tls or use_ssl, they can't be enabled at the same time. + # -- Enable either use_tls or use_ssl. They can't be enabled at the same time. use_tls: false - # -- Enable either use_tls or use_ssl, they can't be enabled at the same time. + # -- Enable either use_tls or use_ssl. They can't be enabled at the same time. use_ssl: false - # -- Connection timeout + # -- Connection timeout in seconds timeout: 30 - # -- Email from address, can either be in the format "foo@bar.baz" or "authentik " + # -- Email 'from' address can either be in the format "foo@bar.baz" or "authentik " from: "" ``` diff --git a/website/docs/installation/monitoring.md b/website/docs/installation/monitoring.md index a3d03bc702..07940efa8e 100644 --- a/website/docs/installation/monitoring.md +++ b/website/docs/installation/monitoring.md @@ -2,11 +2,11 @@ title: Monitoring --- -authentik can be easily monitored multiple ways. +authentik can be easily monitored in multiple ways. ## Server monitoring -Configure your monitoring software to send requests to `/-/health/live/`, which will return a HTTP 204 response as long as authentik is running. You can also send HTTP requests to `/-/health/ready/`, which will return HTTP 204 if both PostgreSQL and Redis connections can be/have been established correctly. +Configure your monitoring software to send requests to `/-/health/live/`, which will return a `HTTP 204` response as long as authentik is running. You can also send HTTP requests to `/-/health/ready/`, which will return `HTTP 204` if both PostgreSQL and Redis connections can be/have been established correctly. ## Worker monitoring @@ -14,11 +14,11 @@ The worker container can be monitored by running `ak healthcheck` in the worker ## Outpost monitoring -Both kinds of outpost (proxy and LDAP) listen on a separate port (9300), and can be monitored by sending HTTP requests to `/outpost.goauthentik.io/ping`. +Both kinds of outpost (proxy and LDAP) listen on a separate port (9300) and can be monitored by sending HTTP requests to `/outpost.goauthentik.io/ping`. --- -Both docker-compose and Kubernetes deployments use these methods by default to determine when authentik is ready after starting, and to only route traffic to healthy instances, and unhealthy instances are restarted +Both Docker Compose and Kubernetes deployments use these methods by default to determine when authentik is ready after starting, and to only route traffic to healthy instances; unhealthy instances are restarted. ## Metrics diff --git a/website/docs/installation/reverse-proxy.md b/website/docs/installation/reverse-proxy.md index c7931690ba..6dd6ecbba7 100644 --- a/website/docs/installation/reverse-proxy.md +++ b/website/docs/installation/reverse-proxy.md @@ -6,9 +6,9 @@ title: Reverse-proxy Since authentik uses WebSockets to communicate with Outposts, it does not support HTTP/1.0 reverse-proxies. The HTTP/1.0 specification does not officially support WebSockets or protocol upgrades, though some clients may allow it. ::: -If you want to access authentik behind a reverse-proxy, there are a few headers that must be passed upstream: +If you want to access authentik behind a reverse proxy, there are a few headers that must be passed upstream: -- `X-Forwarded-Proto`: Tells authentik and Proxy Providers if they are being served over a HTTPS connection. +- `X-Forwarded-Proto`: Tells authentik and Proxy Providers if they are being served over an HTTPS connection. - `X-Forwarded-For`: Without this, authentik will not know the IP addresses of clients. - `Host`: Required for various security checks, WebSocket handshake, and Outpost and Proxy Provider communication. - `Connection: Upgrade` and `Upgrade: WebSocket`: Required to upgrade protocols for requests to the WebSocket endpoints under HTTP/1.1. @@ -56,7 +56,7 @@ server { proxy_http_version 1.1; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; + proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade_keepalive; } diff --git a/website/docs/installation/storage-s3.md b/website/docs/installation/storage-s3.md index bbe536369f..7b2ff80de2 100644 --- a/website/docs/installation/storage-s3.md +++ b/website/docs/installation/storage-s3.md @@ -6,9 +6,9 @@ title: S3 storage setup First, create a user on your S3 storage provider and get access credentials for S3, hereafter referred as `access_key` and `secret_key`. -You'll also need to know which endpoint authentik is going to use to access the S3 API, hereafter referred as `https://s3.provider`. +You will also need to know which endpoint authentik is going to use to access the S3 API, hereafter referred as `https://s3.provider`. -The bucket in which authentik is going to store files is going to be called `authentik-media`. You may need to change this name depending on your S3 provider limitations. Also, we're suffixing the bucket name with `-media` as authentik currently only stores media files, but may use other buckets in the future. +The bucket in which authentik is going to store files is going to be called `authentik-media`. You may need to change this name depending on your S3 provider limitations. Also, we are suffixing the bucket name with `-media` as authentik currently only stores media files, but may use other buckets in the future. The domain used to access authentik is going to be referred to as `authentik.company`. @@ -18,7 +18,7 @@ You will also need the AWS CLI. #### Bucket creation -Let's create the bucket in which authentik is going to store files: +Create the bucket in which authentik is going to store files: ```bash AWS_ACCESS_KEY_ID=access_key AWS_SECRET_ACCESS_KEY=secret_key aws s3api --endpoint-url=https://s3.provider create-bucket --bucket=authentik-media --acl=private @@ -30,7 +30,7 @@ The bucket ACL is set to private, although that is not strictly necessary, as an #### CORS policy -Next, let's associate a CORS policy to the bucket, to allow the authentik web interface to show images stored in the bucket. +Next, associate a CORS policy to the bucket to allow the authentik web interface to show images stored in the bucket. First, save the following file locally as `cors.json`: @@ -49,7 +49,7 @@ First, save the following file locally as `cors.json`: If authentik is accessed from multiple domains, you can add them to the `AllowedOrigins` list. -Let's apply that policy to the bucket: +Apply that policy to the bucket: ```bash AWS_ACCESS_KEY_ID=access_key AWS_SECRET_ACCESS_KEY=secret_key aws s3api --endpoint-url=https://s3.provider put-bucket-cors --bucket=authentik-media --cors-configuration=file://cors.json @@ -60,28 +60,28 @@ AWS_ACCESS_KEY_ID=access_key AWS_SECRET_ACCESS_KEY=secret_key aws s3api --endpoi Add the following to your `.env` file: ```env -AUTHENTIK_STORAGE_MEDIA_BACKEND=s3 -AUTHENTIK_STORAGE_MEDIA_S3_ACCESS__KEY=access_key -AUTHENTIK_STORAGE_MEDIA_S3_SECRET__KEY=secret_key -AUTHENTIK_STORAGE_MEDIA_S3_BUCKET__NAME=authentik-media +AUTHENTIK_STORAGE__MEDIA__BACKEND=s3 +AUTHENTIK_STORAGE__MEDIA__S3__ACCESS_KEY=access_key +AUTHENTIK_STORAGE__MEDIA__S3__SECRET_KEY=secret_key +AUTHENTIK_STORAGE__MEDIA__S3__BUCKET_NAME=authentik-media ``` -If you're using AWS S3 as your S3 provider, add the following: +If you are using AWS S3 as your S3 provider, add the following: ```env -AUTHENTIK_STORAGE_MEDIA_S3_REGION=us-east-1 # Use the region of the bucket +AUTHENTIK_STORAGE__MEDIA__S3__REGION=us-east-1 # Use the region of the bucket ``` -If you're not using AWS S3 as your S3 provider, add the following: +If you are not using AWS S3 as your S3 provider, add the following: ```env -AUTHENTIK_STORAGE_MEDIA_S3_ENDPOINT=https://s3.provider -AUTHENTIK_STORAGE_MEDIA_S3_CUSTOM__DOMAIN=s3.provider/authentik-media +AUTHENTIK_STORAGE__MEDIA__S3__ENDPOINT=https://s3.provider +AUTHENTIK_STORAGE__MEDIA__S3__CUSTOM_DOMAIN=s3.provider/authentik-media ``` The `ENDPOINT` setting specifies how authentik talks to the S3 provider. -The `CUSTOM__DOMAIN` setting specifies how URLs are constructed to be shown on the web interface. For example, an object stored at `application-icons/application.png` with a `CUSTOM__DOMAIN` setting of `s3.provider/authentik-media` will result in a URL of `https://s3.provider/authentik-media/application-icons/application.png`. You can also use subdomains for your buckets depending on what your S3 provider offers: `authentik-media.s3.provider`. Whether HTTPS is used is controlled by the `AUTHENTIK_STORAGE_MEDIA_S3_SECURE__URLS` which defaults to true. +The `CUSTOM_DOMAIN` setting specifies how URLs are constructed to be shown on the web interface. For example, an object stored at `application-icons/application.png` with a `CUSTOM__DOMAIN` setting of `s3.provider/authentik-media` will result in a URL of `https://s3.provider/authentik-media/application-icons/application.png`. You can also use subdomains for your buckets depending on what your S3 provider offers: `authentik-media.s3.provider`. Whether HTTPS is used is controlled by `AUTHENTIK_STORAGE__MEDIA__S3__SECURE_URLS`, which defaults to true. For more control over settings, refer to the [configuration reference](./configuration.mdx#media-storage-settings) @@ -94,11 +94,11 @@ The following section assumes that the local storage path is `/media` and the bu Follow the setup steps above, and then migrate the files from your local directory to s3: ```bash -aws s3 sync /media s3://authentik-media +aws s3 sync /media s3://authentik-media/media ``` #### From s3 to file ```bash -aws s3 sync s3://authentik-media /media +aws s3 sync s3://authentik-media/media /media ``` diff --git a/website/docs/interfaces/_global/customcss.mdx b/website/docs/interfaces/_global/customcss.mdx index 9ff4685149..af3168eaa2 100644 --- a/website/docs/interfaces/_global/customcss.mdx +++ b/website/docs/interfaces/_global/customcss.mdx @@ -15,8 +15,6 @@ import TabItem from "@theme/TabItem"; Create a `docker-compose.override.yml` file and add this block to mount the custom CSS file: ```yaml -version: "3.2" - services: server: volumes: diff --git a/website/docs/outposts/_config.md b/website/docs/outposts/_config.md index ce013b6254..97b3dd52fa 100644 --- a/website/docs/outposts/_config.md +++ b/website/docs/outposts/_config.md @@ -43,7 +43,7 @@ kubernetes_replicas: 1 kubernetes_namespace: authentik # Any additional annotations to add to the ingress object, for example cert-manager kubernetes_ingress_annotations: {} -# Name of the secret that is used for TLS connections +# Name of the secret that is used for TLS connections, leave empty to disable TLS kubernetes_ingress_secret_name: authentik-outpost-tls # Service kind created, can be set to LoadBalancer for LDAP outposts for example kubernetes_service_type: ClusterIP diff --git a/website/docs/outposts/embedded/embedded.mdx b/website/docs/outposts/embedded/embedded.mdx index 00da2c1987..05acea0f6d 100644 --- a/website/docs/outposts/embedded/embedded.mdx +++ b/website/docs/outposts/embedded/embedded.mdx @@ -8,7 +8,7 @@ The embedded outpost runs in the main `server` container, and is managed by auth You can access the embedded outpost on the same ports as authentik itself, 9000 and 9443. -The embedded outpost cannot be disabled, if it doesn't make sense to use it in your deployment you can simply ignore it. +If the embedded outpost doesn't make sense for your deployment, you can simply ignore it. ### Configuration diff --git a/website/docs/outposts/index.mdx b/website/docs/outposts/index.mdx index b5ffe1c254..269a9b7b86 100644 --- a/website/docs/outposts/index.mdx +++ b/website/docs/outposts/index.mdx @@ -1,31 +1,59 @@ --- -title: Overview +title: Outposts --- -An outpost is a single deployment of an authentik component, which can be deployed in a completely separate environment: +An outpost is a single deployment of an authentik component, essentially a service, that can be deployed anywhere that allows for a connection to the authentik API. + +An outpost is required if you use any of the following types of providers with your application: - [LDAP Provider](../providers/ldap/index.md) - [Proxy Provider](../providers/proxy/index.md) - [RADIUS Provider](../providers/radius/index.md) - [RAC Provider](../providers/rac/index.md) -![](outposts.png) +These types of providers use an outpost for increased flexibility and speed. Instead of the provider logic being implemented in authentik Core, these providers use an outpost to handle the logic, which provides improved performance. -Upon creation, a service account and a token is generated. The service account only has permissions to read the outpost and provider configuration. This token is used by the Outpost to connect to authentik. +An additional advantage of using an outpost is that outposts, like authentik itself, do not require access to the wider internet. Transactions between the application, the provider, and the outpost occur via the authentik API, and support single sign-on operations in firewalled or airgapped deployments and offline connections to remote machines that are not on the internet. -authentik can manage the deployment, updating and general lifecycle of an Outpost. To communicate with the underlying platforms on which the outpost is deployed, authentik has several built-in integrations. +An outpost is given permissions to access the authentik API using a service account and token, both of which are auto-generated when you create a new outpost. The outpost is granted rights to only the application/provider pairs configured (and other necessary related objects such as certificates). -- If you've deployed authentik on docker-compose, authentik automatically creates an integration for the local docker socket (See [Docker](./integrations/docker.md)). -- If you've deployed authentik on Kubernetes, with `kubernetesIntegration` set to true (default), authentik automatically creates an integrations for the local Kubernetes Cluster (See [Kubernetes](./integrations/kubernetes.md)). +Any change made to the outpost's associated app or provider immediately triggers an event to update the configuration data stored on the outpost, via websockets. Websockets are used also by the outpost to send healthchecks to the authentik Core. -To deploy an outpost with these integrations, simply select them during the creation of an Outpost. A background task is started, which creates the container/deployment. You can see that Status on the System Tasks page. +## Create and configure an outpost + + 1. To create a new outpost, log in to authentik as an administrator, and open to the Admin interface. + + 2. Navigate to **Applications --> Outposts** and then click **Create**. + +![](outpost-create.png) + + 3. Define the following values: + + - **Name**: a name for the new outpost + - **Type**: select the provider type (Proxy, LDAP, Radius, RAC) + - **Integration** (_optional_): select either your [Docker or Kubernetes connection](#more-about-outpost-integrations) + - **Applications**: select the applications that you want the outpost to serve + - **Advanced settings** (*optional*): For further optional configuration settings, refer to [Configuration](#configuration) below. + + 4. Click **Create** to save your new outpost settings and close the modal. + +Upon creation, a service account and a token is generated. The service account only has permissions to read the outpost and provider configuration. This token is used by the outpost to connect to authentik. + +### More about outpost integrations + +authentik can manage the deployment, updating, and general lifecycle of an outpost. To communicate with the underlying platforms on which the outpost is deployed, authentik has several built-in integrations. + +- If you've deployed authentik on Docker Compose, authentik automatically creates an integration for the local docker socket (See [Docker](./integrations/docker.md)). +- If you've deployed authentik on Kubernetes, with `kubernetesIntegration` set to true (default), authentik automatically creates an integrations for the local Kubernetes Cluster (see [Kubernetes](./integrations/kubernetes.md)). + +To deploy an outpost with these integrations, select them during the creation of an outpost. A background task is started, which creates the container/deployment. The outpost deployment can be monitored from the **Dashboards -> System Tasks** page in the Admin interface. To deploy an outpost manually, see: - [Kubernetes](./manual-deploy-kubernetes.md) -- [docker-compose](./manual-deploy-docker-compose.md) +- [Docker Compose](./manual-deploy-docker-compose.md) -## Configuration +### Configuration Outposts fetch their configuration from authentik. Below are all the options you can set, and how they influence the outpost. @@ -33,8 +61,8 @@ import Configuration from "./_config.md"; -## Metrics +## Prometheus Metrics -Each authentik outpost has a Prometheus metrics endpoint accessible under port `:9300/metrics`. This endpoint is not mapped via docker, as the endpoint doesn't have any authentication. +Each authentik outpost has a Prometheus metrics endpoint accessible under port `:9300/metrics`. This endpoint is not mapped via Docker, as the endpoint doesn't have any authentication. For the embedded outpost, the metrics of the outpost and the metrics of the core authentik server are both returned under the same endpoint. diff --git a/website/docs/outposts/integrations/kubernetes.md b/website/docs/outposts/integrations/kubernetes.md index f50d48a505..14016bdb3b 100644 --- a/website/docs/outposts/integrations/kubernetes.md +++ b/website/docs/outposts/integrations/kubernetes.md @@ -22,7 +22,7 @@ The following outpost settings are used: - `kubernetes_replicas`: Replica count for the deployment of the outpost - `kubernetes_namespace`: Namespace to deploy in, defaults to the same namespace authentik is deployed in (if available) - `kubernetes_ingress_annotations`: Any additional annotations to add to the ingress object, for example cert-manager -- `kubernetes_ingress_secret_name`: Name of the secret that is used for TLS connections +- `kubernetes_ingress_secret_name`: Name of the secret that is used for TLS connections, can be empty to disable TLS config - `kubernetes_ingress_class_name`: Optionally set the ingress class used for the generated ingress, requires authentik 2022.11.0 - `kubernetes_service_type`: Service kind created, can be set to LoadBalancer for LDAP outposts for example - `kubernetes_disabled_components`: Disable any components of the kubernetes integration, can be any of diff --git a/website/docs/outposts/manual-deploy-docker-compose.md b/website/docs/outposts/manual-deploy-docker-compose.md index d1e8419740..09369637cf 100644 --- a/website/docs/outposts/manual-deploy-docker-compose.md +++ b/website/docs/outposts/manual-deploy-docker-compose.md @@ -9,8 +9,6 @@ You can also run the outpost in a separate docker-compose project, you just have ### Proxy outpost ```yaml -version: "3.5" - services: authentik_proxy: image: ghcr.io/goauthentik/proxy @@ -33,8 +31,6 @@ services: ### LDAP outpost ```yaml -version: "3.5" - services: authentik_ldap: image: ghcr.io/goauthentik/ldap @@ -50,3 +46,21 @@ services: AUTHENTIK_INSECURE: "false" AUTHENTIK_TOKEN: token-generated-by-authentik ``` + +### RADIUS outpost + +```yaml +services: + radius_outpost: + image: ghcr.io/goauthentik/radius + # Optionally specify which networks the container should be + # might be needed to reach the core authentik server + # networks: + # - foo + ports: + - 1812:1812/udp + environment: + AUTHENTIK_HOST: https://your-authentik.tld + AUTHENTIK_INSECURE: "false" + AUTHENTIK_TOKEN: token-generated-by-authentik +``` diff --git a/website/docs/outposts/outpost-create.png b/website/docs/outposts/outpost-create.png new file mode 100644 index 0000000000..8aba0fe958 Binary files /dev/null and b/website/docs/outposts/outpost-create.png differ diff --git a/website/docs/outposts/outposts.png b/website/docs/outposts/outposts.png deleted file mode 100644 index ab9c2b24ee..0000000000 Binary files a/website/docs/outposts/outposts.png and /dev/null differ diff --git a/website/docs/policies/expression.mdx b/website/docs/policies/expression.mdx index aaf8506080..68aa595fe4 100644 --- a/website/docs/policies/expression.mdx +++ b/website/docs/policies/expression.mdx @@ -59,6 +59,12 @@ import Objects from "../expressions/_objects.md"; return context["geoip"].country.iso_code == "US" ``` +- `asn`: ASN object, see [GeoIP](https://geoip2.readthedocs.io/en/latest/#geoip2.models.ASN) + + ```python + return context["asn"].autonomous_system_number == 64496 + ``` + - `ak_is_sso_flow`: Boolean which is true if request was initiated by authenticating through an external provider. - `ak_client_ip`: Client's IP Address or 255.255.255.255 if no IP Address could be extracted. Can be [compared](#comparing-ip-addresses), for example diff --git a/website/docs/policies/index.md b/website/docs/policies/index.md index 25bb7f36a6..502a1e1114 100644 --- a/website/docs/policies/index.md +++ b/website/docs/policies/index.md @@ -1,5 +1,5 @@ --- -title: Overview +title: Policies --- ## Event-matcher policy diff --git a/website/docs/policies/working_with_policies/unique_email.md b/website/docs/policies/working_with_policies/unique_email.md new file mode 100644 index 0000000000..068d7d5268 --- /dev/null +++ b/website/docs/policies/working_with_policies/unique_email.md @@ -0,0 +1,19 @@ +--- +title: Ensure unique email addresses +--- + +Due to the database design of authentik, email addresses are by default not required to be unique. This behavior can however be changed by policies. + +The snippet below can be used as the expression in policies both with enrollment flows, where the policy should be bound to any stage before the [User write](../../flow/stages/user_write.md) stage, or with the [Prompt stage](../../flow/stages/prompt/index.md). + +```python +from authentik.core.models import User + +# Ensure this matches the *Field Key* value of the prompt +field_name = "email" +email = request.context["prompt_data"][field_name] +if User.objects.filter(email=email).exists(): + ak_message("Email address in use") + return False +return True +``` diff --git a/website/docs/policies/working_with_policies/whitelist_email.md b/website/docs/policies/working_with_policies/whitelist_email.md index 3cb3f0e7a0..e184cd4e50 100644 --- a/website/docs/policies/working_with_policies/whitelist_email.md +++ b/website/docs/policies/working_with_policies/whitelist_email.md @@ -2,8 +2,7 @@ title: Whitelist email domains --- -To add specific email addresses to an allow list for signing in through SSO or directly with default policy customization, -follow these steps: +To add specific email addresses to an allow list for signing in through SSO or directly with default policy customization, follow these steps: 1. In the Admin interface, navigate to **Customization > Policies** and modify the default policy named `default-source-enrollment-if-sso`. @@ -11,13 +10,12 @@ follow these steps: ```python allowed_domains = ["example.net", "example.com"] -current_domain =request.context["prompt_data"]["email"].split("@")[1] -if current_domain in allowed_domains: - email = request.context["prompt_data"]["email"] - request.context["prompt_data"]["username"] = email - return ak_is_sso_flow -else: - return ak_message("Access denied for this email domain") + +current_domain = request.context["prompt_data"]["email"].split("@")[1] +if current_domain not in allowed_domains: + ak_message("Access denied for this email domain") + return False +return ak_is_sso_flow ``` This configuration specifies the `allowed_domains` list of domains for logging in through SSO, such as Google OAuth2. If your email is not in the available domains, you will receive a 'Permission Denied' message on the login screen. diff --git a/website/docs/providers/entra/add-entra-provider.md b/website/docs/providers/entra/add-entra-provider.md new file mode 100644 index 0000000000..be7656bd87 --- /dev/null +++ b/website/docs/providers/entra/add-entra-provider.md @@ -0,0 +1,66 @@ +--- +title: Add an Entra ID provider +--- + +Enterprise + +--- + +For more information about using an Entra ID provider, see the [Overview](./index.md) documentation. + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +## Prerequisites + +To create an Entra ID provider provider in authentik, you must have already [configured Entra ID](./setup-entra.md) to integrate with authentik. You will need to obtain from Entra three values: the Application (client) ID, the Directory (tenant) ID, and the Client secret. When adding an Entra ID provider in authentik, you must provide these values. + +:::info +As detailed in the steps below, when you add an Entra ID provider in authentik you must define the **Backchannel provider** using the name of the Entra ID provider that you created in authentik. If you have also configured Entra ID to log in using authentik, then this configuration can be done on the same app. +::: + +### Create the Entra ID provider in authentik + +1. Log in as an admin to authentik, and go to the Admin interface. +2. In the Admin interface, navigate to **Applications -> Providers**. +3. Click **Create**, and in the **New provider** modal box select **Microsoft Entra Provider** as the type and click **Next**. +4. Define the following fields: + + - **Name**: define a descriptive name, such as "Entra provider". + + - **Protocol settings** + + - **Client ID**: enter the Client ID that you [copied from your Entra app](./setup-entra.md). + - **Client Secret**: enter the secret from Entra. + - **Tenant ID**: enter the Tenant ID from Entra. + - **User deletion action**: determines what authentik will do when a user is deleted from the Entra ID system. + - **Group deletion action**: determines what authentik will do when a group is deleted from the Entra ID system. + + **User filtering** + + - **Exclude service accounts**: set whether to include or exclude service accounts. + - **Group**: select any specific groups to enforce that filtering (for all actions) is done only for the selected groups. + + **Attribute mapping** + + - **User Property Mappings**: select any applicable mappings, or use the default. + - **Group Property Mappings**: select any applicable mappings, or use the default. + +5. Click **Finish**. + +### Create an Entra ID application in authentik + +1. Log in as an admin to authentik, and go to the Admin interface. +2. In the Admin interface, navigate to **Applications -> Applications**. +3. Click **Create**, and in the **Create Application** modal box define the following fields: + + - **Name**: provide a descriptive name. + - **Slug**: enter the name of the app as you want it to appear in the URL. + - **Group**: optionally, chose a group; apps in the same group are displayed together on the **My applications** page. + - **Provider**: when _not_ used in conjunction with the Entra ID SAML configuration this field should be left empty. + - **Backchannel Providers**: this field is required for Entra ID. Select the name of the Entra ID provider that you created in the steps above. + - **Policy engine mode**: select **any** or **all** to set your policy mode. + - **UI settings**: leave these fields empty for Entra ID. + +4. Click **Create**. diff --git a/website/docs/providers/entra/index.md b/website/docs/providers/entra/index.md new file mode 100644 index 0000000000..6703fa91d7 --- /dev/null +++ b/website/docs/providers/entra/index.md @@ -0,0 +1,50 @@ +--- +title: Microsoft Entra ID provider +--- + +Enterprise + +--- + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +With the Microsoft Entra ID provider, authentik serves as the single source of truth for all users and groups. Configuring Entra ID as a provider allows for auto-discovery of user and group accounts, on-going synchronization of user data such as email address, name, and status, and integrated data mapping of field names and values. + +- For instructions to configure your Entra ID tenant to integrate with authentik, refer to [Configure Entra ID](./setup-entra). +- For instructions to add Entra ID as a provider in authentik, refer to [Create a Entra ID provider](./add-entra-provider). + +## About using Entra ID with authentik + +The following sections discuss how Entra ID operates with authentik. + +### Discovery + +When first creating and configuring the provider, authentik will run a discovery process and query your Entra ID for all users and groups, and attempt to match them with their respective counterparts in authentik. This discovery takes into consideration any **User filtering** options configured in the provider, such as only linking to authentik users in a specific group or excluding service accounts. + +This discovery happens every time before a full sync is started. + +### Synchronization + +There are two types of synchronization: a direct sync and a full sync. + +A _direct sync_ happens when a user or group is created, updated or deleted in authentik, or when a user is added to or removed from a group. When one of these events happens, the direct sync automatically forwards those changes to Entra ID. + +The _full sync_ happens when the provider is initially created and when it is saved. The full sync goes through all users and groups matching the **User filtering** options set and will create/update them in Entra ID. After the initial sync, authentik will run a full sync every four hours to ensure the consistency of users and groups. + +During either sync, if a user or group was created in authentik and a matching user/group exists in Entra ID, authentik will automatically link them together. Furthermore, users present in authentik but not in Entra ID will be created and and linked. + +When a property mapping has an invalid expression, it will cause the sync to stop to prevent errors from being spammed. To handle any kind of network interruptions, authentik will detect transient request failures and retry any sync tasks. + +### Customization for data mapping + +There are a couple of considerations in regard to how authentik data is mapped to Entra ID user/group data by default. + +- For users, authentik only saves the full display name, not separate first and family names. +- By default, authentik synchs a user’s email, a user’s name, and their active status between Entra ID and authentik. For groups, the name is synced. + +Refer to Microsoft documentation for further details. + +- https://learn.microsoft.com/en-us/graph/api/user-post-users?view=graph-rest-1.0&tabs=http#request-body +- https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=http#request-body diff --git a/website/docs/providers/entra/setup-entra.md b/website/docs/providers/entra/setup-entra.md new file mode 100644 index 0000000000..70b4a588b0 --- /dev/null +++ b/website/docs/providers/entra/setup-entra.md @@ -0,0 +1,31 @@ +--- +title: Configure Entra ID +--- + +Enterprise + +--- + +The configuration of your Microsoft Entra ID environment must be completed before you [add the new provider](./add-entra-provider.md) in authentik. + +For detailed instructions, refer to Microsoft Entra ID documentation. + +## Configure Entra ID + +1. Log into the Azure portal and on the Home page, under Azure services, click on or search for **App registrations**. +2. On the **App registrations** page, click **New registration**. +3. On the **Register an application** page, define the **Name** of the app, and under **Supported account types** select **Accounts in this organizational directory only**. Leave **Redirect URI** empty. +4. Click **Register**. + The app's detail page displays. +5. On the app detail page, copy both the **Application (client) ID** and the **Directory (tenant) ID** values and store in a temporary place. These values will be needed when you [create the Entra ID provider](./add-entra-provider) in authentik. +6. Next, click on **Certificates and Secrets** in the near-left navigation pane and create a new secret. +7. On the **Certificates and Secrets** page, on the **Client secrets** tab, copy the **Value** of the secret and store it in a temporary place. Like with the client ID and the tenant ID, this secret will be needed when you [create the Entra ID provider](./add-entra-provider) in authentik. +8. Next, click on **API permissions** in the near-left navigation pane. +9. Click on **Add a permission** and add the following permissions by selecting **Microsoft Graph** and then **Application Permissions**: + - `Group.Create` + - `Group.ReadWrite.All` + - `GroupMember.ReadWrite.All` + - `User.Read` + - `User.ReadWrite.All` + +Now you are ready to [add Entra ID as a provider](./add-entra-provider.md) in authentik. diff --git a/website/docs/providers/gws/add-gws-provider.md b/website/docs/providers/gws/add-gws-provider.md new file mode 100644 index 0000000000..88821617d5 --- /dev/null +++ b/website/docs/providers/gws/add-gws-provider.md @@ -0,0 +1,67 @@ +--- +title: Create a Google Workspace provider +--- + +Enterprise + +--- + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +For more information about using a Google Workspace provider, see the [Overview](./index.md) documentation. + +## Prerequisites + +To create a Google Workspace provider in authentik, you must have already [configured Google Workspace](./setup-gws.md) to integrate with authentik. + +:::info +When adding the Google Workspace provider in authentik, you must define the **Backchannel provider** using the name of the Google Workspace provider that you created in authentik. If you have also configured Google Workspace to log in using authentik following [these](../../../integrations/services/google/), then this configuration can be done on the same app. +::: + +### Create the Google Workspace provider in authentik + +1. Log in as an admin to authentik, and go to the Admin interface. + +2. In the Admin interface, navigate to **Applications -> Providers**. + +3. Click **Create**, and select **Google Workspace Provider**, and in the **New provider** modal box, define the following fields: + + - **Name**: define a descriptive name, such as "GWS provider". + + - **Protocol settings** + + - **Credentials**: paste the contents of the JSON file you downloaded earlier. + - **Delegated Subject**: enter the email address of the user all of authentik's actions should be delegated to + - **Default group email domain**: enter a default domain which will be used to generate the domain for groups synced from authentik. + - **User deletion action**: determines what authentik will do when a user is deleted from authentik. + - **Group deletion action**: determines what authentik will do when a group is deleted from authentik. + + - **User filtering** + + - **Exclude service accounts**: set whether to include or exclude service accounts. + - **Group**: select any specific groups to enforce that filtering (for all actions) is done only for the selected groups. + + - **Attribute mapping** + + - **User Property Mappings**: select any applicable mappings, or use the default. + - **Group Property Mappings**: select any applicable mappings, or use the default. + +4. Click **Finish**. + +### Create a Google Workspace application in authentik + +1. Log in as an admin to authentik, and go to the Admin interface. +2. In the Admin interface, navigate to **Applications -> Applications**. + :::info + If you have also configured Google Workspace to log in using authentik following [these](../../../integrations/services/google/), then this configuration can be done on the same app by adding this new provider as a backchannel provider on the existing app instead of creating a new app. + ::: +3. Click **Create**, and in the **New provider** modal box, and define the following fields: + + - **Slug**: enter the name of the app as you want it to appear in the URL. + - **Provider**: when _not_ used in conjunction with the Google SAML configuration should be left empty. + - **Backchannel Providers**: this field is required for Google Workspace. Select the name of the Google Workspace provider that you created in the steps above. + - **UI settings**: leave these fields empty for Google Workspace. + +4. Click **Finish**. diff --git a/website/docs/providers/gws/index.md b/website/docs/providers/gws/index.md new file mode 100644 index 0000000000..c774cc89bb --- /dev/null +++ b/website/docs/providers/gws/index.md @@ -0,0 +1,53 @@ +--- +title: Google Workspace provider +--- + +Enterprise + +--- + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +With the Google Workspace provider, authentik serves as the single source of truth for all users and groups, when using Google products like Gmail. + +- For instructions to configure your Google Workspace to integrate with authentik, refer to [Configure Google Workspace](./setup-gws). +- For instructions to add Google Workspace as a provider, refer to [Create a Google Workspace provider](./add-gws-provider). + +## About using Google Workspace with authentik + +The following sections discuss how Google Workspace operates with authentik. + +### Discovery + +When first creating the provider and setting it up correctly, the provider will run a discovery and query your google workspace for all users and groups, and attempt to match them with their respective counterparts in authentik. + +This matching is done by email address for users as google uses that as their primary identifier, and using group names for groups. This discovery also takes into consideration any **User filtering** options configured in the provider, such as only linking to authentik users in a specific group or excluding service accounts. This discovery happens every time before a full sync is started. + +### Synchronization + +There are two types of synchronization: a direct sync and a full sync. + +A _direct sync_ happens when a user or group is created, updated or deleted in authentik, or when a user is added to or removed from a group. When one of these events happens, the direct sync automatically forwards those changes to Google Workspace. + +The _full sync_ happens when the provider is initially created and when it is saved. The full sync goes through all users and groups matching the **User filtering** options set and will create/update them in Google Workspace. After the initial sync, authentik will run a full sync every four hours to ensure the consistency of users and groups. + +During the full sync, if a user or group was created in authentik and a matching user/group exists in Google Workspace, authentik will automatically link them together. Furthermore, users present in authentik but not in Google Workspace will be created and and linked. + +When a property mapping has an invalid expression, it will cause the sync to stop to prevent errors from being spammed. To handle any kind of network interruptions, authentik will detect transient request failures and retry any sync tasks. + +### Customization for data mapping + +There are a couple of considerations in regard to how authentik data is mapped to google workspace user/group data by default. + +- For users, authentik only saves the full display name, while Google requires given/family name separately, and as such authentik attempts to separate the full name automatically with the default User property mapping. + +- For groups, Google groups require an email address. Thus in authentik the provider configuration has an option **Default group email domain**, which will be used in conjunction with the group’s name to generate an email address. This can be customized with a property mapping. + +- By default, authentik maps a user’s email, a user’s name, and their active status. For groups, the name is synced. + +Refer to Google documentation for further details on which fields data can be mapped to: + +- https://developers.google.com/admin-sdk/directory/reference/rest/v1/users#User +- https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups#Group diff --git a/website/docs/providers/gws/setup-gws.md b/website/docs/providers/gws/setup-gws.md new file mode 100644 index 0000000000..50d2209336 --- /dev/null +++ b/website/docs/providers/gws/setup-gws.md @@ -0,0 +1,69 @@ +--- +title: Configure Google Workspace +--- + +Enterprise + +--- + +The configuration and set up of your Google Workspace must be completed before you [add the new provider](./add-gws-provider.md) in authentik. + +## Overview of steps + +The main steps to set up your Google workspace are as follows: + +1. [Create your Google Cloud Project](#create-a-google-cloud-project) +2. [Create a service account](#create-a-service-account) +3. [Set credentials for the service account](#set-credentials-for-the-service-account) +4. [Define access and scope in the Admin Console](#set-credentials-for-the-service-account) +5. [Select email address for the Delegated Subject](#select-email-address-for-the-delegated-subject) + +For detailed instructions, refer to Google documentation. + +### Create a Google cloud project + +1. Open the Google Cloud Console (https://cloud.google.com/cloud-console). +2. In upper left, click the drop-down box to open the **Select a project** modal box, and then select **New Project**. +3. Create a new project and give it a name like "authentik GWS" +4. Use the search bar at the top of your new project page to search for "API Library". +5. On the **API Library** page, use the search bar again to find "Admin SDK API". +6. On the **Admin SDK API** page, click **Enable**. + +### Create a service account + +1. After the new Admin SDK API is enabled (it might take a few minutes), return to the Google Cloud console home page (click on **Google Cloud** in upper left). +2. Use the search bar to find and navigate to the **IAM** page. +3. On the **IAM** page, click **Service Accounts** in the left navigation pane. +4. At the top of the **Service Accounts** page, click **Create Service Account**. + +- Under **Service account details** page, define the **Name** and **Description** for the new service account, and then click **Create and Continue**. +- Under **Grant this service account access to project** you do not need to define a role, so click **Continue**. +- Under **Grant users access to project** you do not need to define a role, so click **Done** to complete the creation of the service account. + +### Set credentials for the service account + +1. On the **Service accounts** page, click the account that you just created. +2. Click the **Keys** tab at top of the page, the click **Add Key -> Create new key**. +3. In the Create modal box, select JSON as the key type, and then click **Create**. + A pop-up displays with the private key, and the key is saved to your computer as a JSON file. + Later, when you create your authentik provider for Google Workspace, you will add this key in the **Credentials** field. +4. On the service account page, click the **Details** tab, and expand the **Advanced settings** area. +5. Copy the **Client ID** (under **Domain-wide delegation**), and then click **View Google Workspace Admin Console**. +6. Log in to the Admin Console, and then navigate to **Security -> Access and data control -> API controls**. +7. On the **API controls** page, click **Manage Domain Wide Delegation**. +8. On the **Domain Wide Delegation** page, click **Add new**. +9. In the **Add a new client ID** modal box, paste in the Client ID that you copied from the Admin console earlier (the value from the downloaded JSON file) and paste in the following scope documents: + - `https://www.googleapis.com/auth/admin.directory.user` + - `https://www.googleapis.com/auth/admin.directory.group` + - `https://www.googleapis.com/auth/admin.directory.group.member` + - `https://www.googleapis.com/auth/admin.directory.domain.readonly` + +### Select email address for the Delegated Subject + +The Delegated Subject email address is a required field when creating the provider in authentik. + +1. Open to the main Admin console page, and navigate to **Directory -> Users**. +2. You can either select an existing user's email address or **Add new user** and define the user and email address to use as the Delegated Subject. +3. Save this email address to enter into authentik when you are creating the Google Workspace provider. + +Now that you have configured your Google Workspace, you are ready to [add it as a provider in authentik](./add-gws-provider.md). diff --git a/website/docs/providers/index.mdx b/website/docs/providers/index.mdx new file mode 100644 index 0000000000..99790ab300 --- /dev/null +++ b/website/docs/providers/index.mdx @@ -0,0 +1,20 @@ +--- +title: Providers +slug: /providers +--- + +import DocCardList from "@theme/DocCardList"; + +A Provider is an authentication method, a service that is used by authentik to authenticate the user for the associated application. Common Providers are OpenID Connect (OIDC)/OAuth2, LDAP, SAML, and generic proxy provider, and others. + +Providers are the "other half" of [applications](../applications/index.md). They typically exist in a 1-to-1 relationship; each application needs a provider and every provider can be used with one application. + +Applications can use additional providers to augment the functionality of the main provider. For more information, see [Backchannel providers](../applications/manage_apps.md#backchannel-providers). + +You can create a new provider in the Admin interface, or you can use the [Application wizard](../applications/manage_apps.md#instructions) to create a new application and its provider at the same time. + +Refer to the documentation for each provider: + + + +You can also create a SAML provider by uploading an SP metadata XML file that contains the service provider's configuration data. SAML metadata is used to share configuration information between the Identity Provider (IdP) and the Service Provider (SP). An SP metadata XML file typically contains the SP certificate, the entity ID, the Assertion Consumer Service URL (ACS URL), and a log out URL (SingleLogoutService). diff --git a/website/docs/providers/ldap/generic_setup.md b/website/docs/providers/ldap/generic_setup.md index 4c1fa24d0f..6e1ba90747 100644 --- a/website/docs/providers/ldap/generic_setup.md +++ b/website/docs/providers/ldap/generic_setup.md @@ -74,18 +74,17 @@ Test connectivity by using ldapsearch. :::info ldapsearch can be installed on Linux system with these commands -``` +```shell sudo apt-get install ldap-utils -y # Debian-based systems sudo yum install openldap-clients -y # CentOS-based systems ``` ::: -``` +```shell ldapsearch \ -x \ - -h \ - -p 389 \ # Production should use SSL 636 + -H ldap://: \ # In production it is recommended to use SSL, which also requires `ldaps://` as the protocol and the SSL port -D 'cn=ldapservice,ou=users,DC=ldap,DC=goauthentik,DC=io' \ -w '' \ -b 'DC=ldap,DC=goauthentik,DC=io' \ diff --git a/website/docs/providers/oauth2/client_credentials.md b/website/docs/providers/oauth2/client_credentials.md index a0018795de..95ca1c5695 100644 --- a/website/docs/providers/oauth2/client_credentials.md +++ b/website/docs/providers/oauth2/client_credentials.md @@ -23,6 +23,10 @@ password=my-token This will return a JSON response with an `access_token`, which is a signed JWT token. This token can be sent along requests to other hosts, which can then validate the JWT based on the signing key configured in authentik. +Starting with authentik 2024.4, it is also possible to encode the username and token of the user to authenticate with, separated with a colon, into a base64 string and pass it as `client_secret` value. + +In addition to that, with authentik 2024.4 it is also possible to pass the configured `client_secret` value, which will automatically generate a service account user for which the JWT token will be issued. + ### JWT-authentication Starting with authentik 2022.4, you can authenticate and get a token using an existing JWT. diff --git a/website/docs/providers/oauth2/index.md b/website/docs/providers/oauth2/index.md index 90ce757787..556f865f50 100644 --- a/website/docs/providers/oauth2/index.md +++ b/website/docs/providers/oauth2/index.md @@ -38,7 +38,7 @@ To access the user's email address, a scope of `user:email` is required. To acce This grant is used to convert an authorization code to an access token (and optionally refresh token). The authorization code is retrieved through the Authorization flow, and can only be used once, and expires quickly. :::info -Starting with authentik 2024.1, applications only receive an access token. To receive a refresh token, applications must be allowed to request the `offline_access` scope in authentik and also be configured to request the scope. +Starting with authentik 2024.2, applications only receive an access token. To receive a refresh token, both applications and authentik must be configured to request the `offline_access` scope. In authentik this can be done by selecting the `offline_access` Scope mapping in the provider settings. ::: ### `refresh_token`: @@ -46,7 +46,7 @@ Starting with authentik 2024.1, applications only receive an access token. To re Refresh tokens can be used as long-lived tokens to access user data, and further renew the refresh token down the road. :::info -Starting with authentik 2024.1, this grant requires the `offline_access` scope. +Starting with authentik 2024.2, this grant requires the `offline_access` scope. ::: ### `client_credentials`: diff --git a/website/docs/providers/proxy/_envoy_istio.md b/website/docs/providers/proxy/_envoy_istio.md index c72e8f1e3d..4aaf21a036 100644 --- a/website/docs/providers/proxy/_envoy_istio.md +++ b/website/docs/providers/proxy/_envoy_istio.md @@ -20,6 +20,9 @@ spec: headersToUpstreamOnAllow: - set-cookie - x-authentik-* + # Add authorization headers to the allow list if you need proxy providers which + # send a custom HTTP-Basic Authentication header based on values from authentik + # - authorization includeRequestHeadersInCheck: - cookie ``` diff --git a/website/docs/providers/proxy/_nginx_proxy_manager.md b/website/docs/providers/proxy/_nginx_proxy_manager.md index 3667cf9679..58a12c2ac3 100644 --- a/website/docs/providers/proxy/_nginx_proxy_manager.md +++ b/website/docs/providers/proxy/_nginx_proxy_manager.md @@ -1,6 +1,10 @@ -For Nginx Proxy Manager you can use this snippet - ``` +# Upgrade WebSocket if requested, otherwise use keepalive +map $http_upgrade $connection_upgrade_keepalive { + default upgrade; + '' ''; +} + # Increase buffer size for large headers # This is needed only if you get 'upstream sent too big header while reading response # header from upstream' error when trying to access an application protected by goauthentik @@ -16,6 +20,9 @@ location / { # Set any other headers your application might need # proxy_set_header Host $host; # proxy_set_header ... + # Support for websocket + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade_keepalive; ############################## # authentik-specific config diff --git a/website/docs/providers/proxy/_nginx_standalone.md b/website/docs/providers/proxy/_nginx_standalone.md index c7cace7fa3..780274b6fd 100644 --- a/website/docs/providers/proxy/_nginx_standalone.md +++ b/website/docs/providers/proxy/_nginx_standalone.md @@ -1,4 +1,10 @@ ``` +# Upgrade WebSocket if requested, otherwise use keepalive +map $http_upgrade $connection_upgrade_keepalive { + default upgrade; + '' ''; +} + server { # SSL and VHost configuration listen 443 ssl http2; @@ -18,6 +24,9 @@ server { # proxy_pass http://localhost:5000; # proxy_set_header Host $host; # proxy_set_header ... + # Support for websocket + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade_keepalive; ############################## # authentik-specific config diff --git a/website/docs/providers/proxy/_traefik_compose.md b/website/docs/providers/proxy/_traefik_compose.md index 146d12aedf..f749224ef9 100644 --- a/website/docs/providers/proxy/_traefik_compose.md +++ b/website/docs/providers/proxy/_traefik_compose.md @@ -1,8 +1,7 @@ ```yaml -version: "3.7" services: traefik: - image: traefik:v2.2 + image: traefik:v3.0 container_name: traefik volumes: - /var/run/docker.sock:/var/run/docker.sock diff --git a/website/docs/providers/proxy/forward_auth.mdx b/website/docs/providers/proxy/forward_auth.mdx index 0ebe032cf4..822a71132a 100644 --- a/website/docs/providers/proxy/forward_auth.mdx +++ b/website/docs/providers/proxy/forward_auth.mdx @@ -36,6 +36,5 @@ There are, however, also some downsides, mainly the fact that you **can't** rest For configuration templates for each web server, refer to the following: import DocCardList from "@theme/DocCardList"; -import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; - + diff --git a/website/docs/providers/rac/how-to-rac.md b/website/docs/providers/rac/how-to-rac.md new file mode 100644 index 0000000000..75ec0cdcd6 --- /dev/null +++ b/website/docs/providers/rac/how-to-rac.md @@ -0,0 +1,86 @@ +--- +title: Create a Remote Access Control (RAC) provider +--- + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +The RAC provider is a highly flexible feature for accessing remote machines. This document provides instructions for the basic creation and configuration of a RAC provider within a defined scenario. + +Fow more information about using a RAC provider, see the [Overview](./index.md) documentation. You can also view our video on YouTube for setting up RAC. + + + +## Prereqisites + +The RAC provider requires the deployment of the [RAC Outpost](../../outposts/). + +## Overview workflow to create a RAC provider + +The typical workflow to create and configure a RAC provider is to 1. create app/provider, 2. create property mappings (that define the access credentials to each remote machine), 3. create an endpoint for each remote machine you want to connect to. + +Depending on whether you are connecting using RDP, SSH, or VNC, the exact configuration choices might differ, but the overall workflow applies to all RAC connections. + +### Step 1. Create an application and RAC provider + +The first step is to create the RAC app and provider. + +1. Log in as an admin to authentik, and go to the Admin interface. + +2. In the Admin interface, navigate to **Applications -> Applications**. + +3. Click **Create with Wizard**. Follow the [instructions](../../applications/manage_apps.md#instructions) to create your RAC application and provider. + +### Step 2. Create RAC property mapping + +Next, you need to add a property mapping for each of the remote machines you want to access. Property mappings allow you to pass information to external applications, and with RAC they are used to pass the host name, IP address, and access credentials for the remote machines. + +1. In the Admin interface, navigate to **Customization -> Property Mappings**. + +2. On the **Property Mappings** page, click **Create**. + +3. On the **New property mapping** modal, set the following: + + - **Select Type**: RAC Property Mappings + - **Create RAC Property Mapping**: + - **Name**s: define a name for the property mapping, perhaps include the type of connection (RDP, SSH, VNC) + - **General settings**: + - **Username**: the username for the remote machine + - **Password**: the password for the remote machine + - **RDP settings**: + - **Ignore server certificate: select **Enabled\*\* (Depending on the setup of your RDP Server, it might be required to enable this setting.) + - **Enable wallpaper**: optional + - **Enable font smoothing**: optional + - **Enable full window dragging**: optional + - Advanced settings: + - **Expressions**: optional, using Python you can define custom [expressions](../../property-mappings/expression.mdx). + +4. Click **Finish** to save your settings and close the modal. + +### Step 3. Create Endpoints for the Provider + +Finally, you need to create an endpoint for each remote machine. Endpoints are defined within providers; connections between the remote machine and authentik are enabled through communication between the provider's endpoint and the remote machine. + +1. In the Admin interface navigate to **Applications -> Providers**. + +2. Select the RAC provider you created in Step 1 above. + +3. On the Provider page, under **Endpoints**, click **Create**. + +4. On the **Create Endpoint** modal, provide the following settings: + + - **Name**: define a name for the endpoint, perhaps include the type of connection (RDP, SSH, VNC) + - **Protocol**: select the appropriate protocol + - **Host**: the host name or IP address of the system you are connecting to. + - **Maximum concurrent connections**: select a value or use `-1` to disable the limitation. + - **Property mapping**: select either the property mapping that you created in Step 2, or use one of the default settings. + - **Advance settings**: optional + +5. Click **Create** to save your settings and close the modal. + +### Access the remote machine + +To verify your configuration and access the remote machine, go to the **User interface** of your authentik instance. On the **My applications** page click the **Remote Access** application. authentik connects you to a secure shell on the remote machine, in your web browser. + +If you defined multiple endpoints, they are each displayed; click the endpoint for the remote machine that you want to access. diff --git a/website/docs/providers/rac/index.md b/website/docs/providers/rac/index.md index 67e3b74da0..3b94a40414 100644 --- a/website/docs/providers/rac/index.md +++ b/website/docs/providers/rac/index.md @@ -1,5 +1,5 @@ --- -title: Remote Access (RAC) Provider +title: Remote Access Control (RAC) Provider --- Enterprise @@ -7,22 +7,40 @@ title: Remote Access (RAC) Provider --- :::info -This feature is in technical preview, so please report any Bugs you run into on [GitHub](https://github.com/goauthentik/authentik/issues) +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). ::: -The Remote access provider allows users to access Windows/macOS/Linux machines via [RDP](https://en.wikipedia.org/wiki/Remote_Desktop_Protocol)/[SSH](https://en.wikipedia.org/wiki/Secure_Shell)/[VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing). - :::info -This provider requires the deployment of the [RAC Outpost](../../outposts/) +This provider requires the deployment of the [RAC Outpost](../../outposts/). ::: -## Endpoints +## About the Remote Access Control (RAC) Provider -Unlike other providers, where one provider-application pair must be created for each resource you wish to access, the RAC provider handles this slightly differently. For each machine (computer/server) that should be accessible, an _Endpoint_ object must be created within an RAC provider. +The RAC provider allows users to access remote Windows, macOS, and Linux machines via [RDP](https://en.wikipedia.org/wiki/Remote_Desktop_Protocol)/[SSH](https://en.wikipedia.org/wiki/Secure_Shell)/[VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing). Just like other providers in authentik, the RAC provider is associated with an application that appears on a user's **My applications** page. -The _Endpoint_ object specifies the hostname/IP of the machine to connect to, as well as the protocol to use. Additionally it is possible to bind policies to _endpoint_ objects to restrict access. Users must have access to both the application the RAC Provider is using as well as the individual endpoint. +:::info +Note that with RAC, you create a single application and associated provider that serves to connect with _all remote machines_ that you want to configure for access via RAC. +::: -Configuration like credentials can be specified through _settings_, which can be specified on different levels and are all merged together when connecting: +For instructions on creating a RAC provider, refer to the [Managing RAC providers](./how-to-rac.md) documentation. You can also view our [video on YouTube](https://www.youtube.com/watch?v=9wahIBRV6Ts) for setting up a RAC. + +There are several components used with a RAC provider; let's take a closer look at the high-level configuration layout of these components and how they are managed using endpoints and connections. + +![](./rac-v3.png) + +The provider-application pair, the authentik server, and the authentik API are typical to all configurations. With RAC, there are some new components, namely the endpoints, the outpost, and of course the target remote machines. + +When a user starts the RAC application, the app communicates with the authentik server, which then connects to an instance of the outpost (the exact instance is selected dynamically based on connection load). After the outpost is selected, then the authentik server sends the outpost the instructions (based on the data you defined in the endpoint) required to connect to the remote machine. + +After the connection to the remote machine is made, the outpost sends a message back to the authentik server (via websockets), and the web browser opens the websocket connection to the remote machine. + +### Endpoints + +Unlike other providers, where one provider-application pair must be created for each resource you wish to access, the RAC provider handles this slightly differently. For each remote machine (computer/server) that should be accessible, you create an _Endpoint_ object within a single RAC provider. (And as mentioned above, a single provider-application pair is used for all remote connections.) + +The _Endpoint_ object specifies the hostname/IP of the machine to connect to, as well as the protocol to use. Additionally it is possible to bind policies to _endpoint_ objects to restrict access. Users must have access to both the application that the RAC Provider is using as well as the individual endpoint. + +Configuration details such as credentials can be specified through _settings_, which can be specified on different levels and are all merged together when connecting: 1. Provider settings 2. Endpoint settings @@ -30,9 +48,9 @@ Configuration like credentials can be specified through _settings_, which can be 4. Provider property mapping settings 5. Endpoint property mapping settings -## Connections +### Connections -Each connection is authorized through the policies bound to the application and the endpoint, and additional verification can be done with the authorization flow. +Each connection is authorized through authentik Policy objects that are bound to the application and the endpoint. Additional verification can be done with the authorization flow. Additionally it is possible to modify the connection settings through the authorization flow. Configuration set in `connection_settings` in the flow plan context will be merged with other settings as shown above. diff --git a/website/docs/providers/rac/rac-v3.png b/website/docs/providers/rac/rac-v3.png new file mode 100644 index 0000000000..109c7a915a Binary files /dev/null and b/website/docs/providers/rac/rac-v3.png differ diff --git a/website/docs/providers/scim/index.md b/website/docs/providers/scim/index.md index 51fb4d8681..c770bc60fa 100644 --- a/website/docs/providers/scim/index.md +++ b/website/docs/providers/scim/index.md @@ -12,6 +12,10 @@ When configuring SCIM, you'll get an endpoint and a token from the application t The token given by the application will be sent with all outgoing SCIM requests to authenticate them. +:::info +When adding the SCIM provider, you must define the **Backchannel provider using the name of the SCIM provider that you created in authentik. Do NOT add any value in the **Provider** field (doing so will cause the provider to display as an application on the user interface, under **My apps\*\*, which is not supported for SCIM). +::: + ### Syncing Data is synchronized in multiple ways: diff --git a/website/docs/releases/2021/v2021.1.md b/website/docs/releases/2021/v2021.1.md index d0a8d258f4..414a445f66 100644 --- a/website/docs/releases/2021/v2021.1.md +++ b/website/docs/releases/2021/v2021.1.md @@ -10,7 +10,7 @@ slug: "/releases/2021.1" In previous versions, you had to configure email connection details per [Email Stage](../../flow/stages/email/index.mdx). Now, you can (and should) configure global settings. - This is documented under the [docker-compose](../../installation/docker-compose.md) and [Kubernetes](../../installation/kubernetes.md) sections. + This is documented under the [docker-compose](../../installation/docker-compose.mdx) and [Kubernetes](../../installation/kubernetes.md) sections. - New notification system diff --git a/website/docs/releases/2022/v2022.5.md b/website/docs/releases/2022/v2022.5.md index 5b7ca6c2f8..f218259fc1 100644 --- a/website/docs/releases/2022/v2022.5.md +++ b/website/docs/releases/2022/v2022.5.md @@ -7,7 +7,7 @@ slug: "/releases/2022.5" - Twitter Source has been migrated to OAuth2 - This requires some reconfiguration on both Twitter's and authentik's side. Check out the new Twitter integration docs [here](../../integrations/sources/twitter/) + This requires some reconfiguration on both Twitter's and authentik's side. Check out the new Twitter integration docs [here](../../docs/sources/twitter/) - OAuth Provider: Redirect URIs are now checked using regular expressions diff --git a/website/docs/releases/2023/v2023.10.md b/website/docs/releases/2023/v2023.10.md index b5dc6ccb78..fe2bd54a22 100644 --- a/website/docs/releases/2023/v2023.10.md +++ b/website/docs/releases/2023/v2023.10.md @@ -43,7 +43,7 @@ This release does not introduce any new requirements. To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: -``` +```shell wget -O docker-compose.yml https://goauthentik.io/version/2023.10/docker-compose.yml docker-compose up -d ``` @@ -193,6 +193,18 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2023.10 - sources/oauth: fix missing get_user_id for OIDC-like sources (Azure AD) (#7970) - web/flows: fix device picker incorrect foreground color (cherry-pick #8067) (#8069) +## Fixed in 2023.10.7 + +- providers/oauth2: fix fix [CVE-2024-23647](../../security/CVE-2024-23647.md) (cherry-pick #8345) (#8347) +- rbac: fix invitations listing with restricted permissions (cherry-pick #8227) (#8229) +- root: fix listen trusted_proxy_cidrs config loading from environment (#8075) +- root: fix redis config not being updated to match previous change +- sources/oauth: fix azure_ad user_id and add test and fallback (cherry-pick #8146) (#8152) +- sources/oauth: fix URLs being overwritten by OIDC urls (cherry-pick #8147) (#8156) +- sources/oauth: revert azure_ad profile URL change (cherry-pick #8139) (#8141) +- stages/authenticator_validate: use friendly_name for stage selector when enrolling (cherry-pick #8255) (#8256) +- web/flows: fix icon for generic oauth source with dark theme (cherry-pick #8148) (#8151) + ## API Changes #### What's New diff --git a/website/docs/releases/2023/v2023.2.md b/website/docs/releases/2023/v2023.2.md index 963dbf4387..3de017157b 100644 --- a/website/docs/releases/2023/v2023.2.md +++ b/website/docs/releases/2023/v2023.2.md @@ -21,7 +21,7 @@ slug: "/releases/2023.2" - Generated avatars, multiple avatar modes - authentik now supports multiple avatar modes, and will use the next configured mode when a mode doesn't have an avatar. For example, the new default configuration attempts to use gravatar, but if the user's email does not have a gravatar setup, it will instead use the new generated avatars. See [Configuration](../../installation/configuration.mdx#authentik_avatars) + authentik now supports multiple avatar modes, and will use the next configured mode when a mode doesn't have an avatar. For example, the new default configuration attempts to use gravatar, but if the user's email does not have a gravatar setup, it will instead use the new generated avatars. See [Configuration](../../core/settings.md#avatars) ## Upgrading diff --git a/website/docs/releases/2023/v2023.5.md b/website/docs/releases/2023/v2023.5.md index 047bb1818d..802a125d44 100644 --- a/website/docs/releases/2023/v2023.5.md +++ b/website/docs/releases/2023/v2023.5.md @@ -41,7 +41,7 @@ This release does not introduce any new requirements. To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: -``` +```shell wget -O docker-compose.yml https://goauthentik.io/version/2023.5/docker-compose.yml docker-compose up -d ``` diff --git a/website/docs/releases/2023/v2023.6.md b/website/docs/releases/2023/v2023.6.md index 74971855ec..cc0fe34fda 100644 --- a/website/docs/releases/2023/v2023.6.md +++ b/website/docs/releases/2023/v2023.6.md @@ -27,7 +27,7 @@ This release does not introduce any new requirements. To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: -``` +```shell wget -O docker-compose.yml https://goauthentik.io/version/2023.6/docker-compose.yml docker-compose up -d ``` diff --git a/website/docs/releases/2023/v2023.8.md b/website/docs/releases/2023/v2023.8.md index 4a64d9c483..2a62ca456c 100644 --- a/website/docs/releases/2023/v2023.8.md +++ b/website/docs/releases/2023/v2023.8.md @@ -39,7 +39,7 @@ This release changes the PostgreSQL dependency to require Version 12 or later, w To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: -``` +```shell wget -O docker-compose.yml https://goauthentik.io/version/2023.8/docker-compose.yml docker-compose up -d ``` @@ -167,6 +167,10 @@ image: - providers/oauth2: fix [CVE-2024-21637](../../security/CVE-2024-21637.md), Reported by [@lauritzh](https://github.com/lauritzh) (#8104) +## Fixed in 2023.8.7 + +- providers/oauth2: fix fix [CVE-2024-23647](../../security/CVE-2024-23647.md) (cherry-pick #8345) (#8347) + ## API Changes #### What's New diff --git a/website/docs/releases/2024/v2024.1.md b/website/docs/releases/2024/v2024.1.md deleted file mode 100644 index 4552ee0cfb..0000000000 --- a/website/docs/releases/2024/v2024.1.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: Release 2024.1 -slug: /releases/2024.1 ---- - -## Breaking changes - -- Tenants have been renamed to brands - - The API endpoints associated with brands have also been renamed. - - Blueprints using `authentik_tenants.tenant` will need to be changed to use `authentik_brands.brand`. - -- The following config options have been moved from the config file and can now be set using the admin interface (under **System** -> **Settings**) or the API: - - - `AUTHENTIK_AVATARS` - - `AUTHENTIK_DEFAULT_USER_CHANGE_NAME` - - `AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL` - - `AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME` - - `AUTHENTIK_GDPR_COMPLIANCE` - - `AUTHENTIK_IMPERSONATION` - - `AUTHENTIK_FOOTER_LINKS` - - `AUTHENTIK_REPUTATION__EXPIRY` - - When upgrading to 2024.1, the currently configured options will be automatically migrated to the database, and can be removed from the `.env` or helm values file afterwards. - -- Required `offline_access` scope for Refresh tokens - - The OAuth2 provider ships with a new default scope called `offline_access`, which must be requested by applications that need a refresh token. Previously, authentik would always issue a refresh token for the _Authorization code_ and _Device code_ OAuth grants. - - Applications which require will need their configuration update to include the `offline_access` scope mapping. - -- The event retention settings configured in brands (previously tenants, see above) has been removed and is now a system settings, managed in the admin interface or via the API (see above). - - There is no built-in migration path for this change. If you set something other than the default (`days=365`), you will need to update the setting in the admin interface. - -- authentik now uses PostgreSQL schemas other than `public`. - - If you have a custom PostgreSQL deployment, please ensure that the authentik user is allowed to create schemas. Usually, if the authentik user is owner of the database, it already can. - -- Removal of deprecated metrics - - - `authentik_outpost_flow_timing_get` -> `authentik_outpost_flow_timing_get_seconds` - - `authentik_outpost_flow_timing_post` -> `authentik_outpost_flow_timing_post_seconds` - - `authentik_outpost_ldap_requests` -> `authentik_outpost_ldap_request_duration_seconds` - - `authentik_outpost_ldap_requests_rejected` -> `authentik_outpost_ldap_requests_rejected_total` - - `authentik_outpost_proxy_requests` -> `authentik_outpost_proxy_request_duration_seconds` - - `authentik_outpost_proxy_upstream_time` -> `authentik_outpost_proxy_upstream_response_duration_seconds` - - `authentik_outpost_radius_requests` -> `authentik_outpost_radius_request_duration_seconds` - - `authentik_outpost_radius_requests_rejected` -> `authentik_outpost_radius_requests_rejected_total` - - `authentik_main_requests` -> `authentik_main_request_duration_seconds` - -- Icons are now in a `public/` subfolder - - If your media folder is `/media`, icons are now stored in `/media/public`. authentik will automatically migrate the icons upon upgrading. - -- The shorthand parameter for `--stage`, `-s` for the `ak test_email` command has been changed to `-S` - -- User sessions will be invalidated after this upgrade. As such, users will need to log back in. - -- The Helm Chart has a number of breaking changes. Find out more in the [chart release notes](https://github.com/goauthentik/helm/releases/tag/authentik-2024.1.0). - -## New features - -- Tenancy Enterprise - - :::warning - This feature is in early preview. Use at your own risk. - ::: - - It allows for authentik operators to manage several authentik installations without having to deploy additional instances. - -- Audit log Enterprise - - authentik instances which have a valid enterprise license installed will log changes made to models including which fields were changed with previous and new values of the fields. The values are censored if they are sensitive (for example a password hash), however a hash of the changed value will still be logged. - -- "Pretend user exists" option for Identification stage - - Previously the identification stage would only continue if a user matching the user identifier exists. While this was the intended functionality, this release adds an option to continue to the next stage even if no matching user was found. "Pretend" users cannot authenticate nor receive emails, and don't exist in the database. **This feature is enabled by default.** - -- S3 file storage - - Media files can now be stored on S3. Follow the [setup guide](../../installation/storage-s3.md) to get started. - -## Upgrading - -This release does not introduce any new requirements. - -### docker-compose - -To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: - -``` -wget -O docker-compose.yml https://goauthentik.io/version/2024.1/docker-compose.yml -docker-compose up -d -``` - -The `-O` flag retains the downloaded file's name, overwriting any existing local file with the same name. - -### Kubernetes - -Upgrade the Helm Chart to the new version, using the following commands: - -```shell -helm repo update -helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.1 -``` - -## Minor changes/fixes - - - -## API Changes - - diff --git a/website/docs/releases/2024/v2024.2.md b/website/docs/releases/2024/v2024.2.md new file mode 100644 index 0000000000..e38a31e5bc --- /dev/null +++ b/website/docs/releases/2024/v2024.2.md @@ -0,0 +1,10189 @@ +--- +title: Release 2024.2 +slug: /releases/2024.2 +--- + +## Highlights + +- **Remote Access Control** Enterprise Access machines over RDP, SSH, and VNC from authentik + +- **Audit logging** Enterprise See what fields were changed when objects are updated + +- **Session location and network binding** Increase security by preventing session theft + +- **Wizard to simplify creating applications and providers** + +## Breaking changes + +### Manual action is required + +- **Tenants have been renamed to brands** + + Tenants, which were previously used to change branding configuration, default flows, and several other settings have been renamed to _brands_. The term "Brands" more accurately reflect their usage; to configure branding, logos, colors, and overall login flow behavior. + + Existing _tenant_ objects will automatically be renamed to _brand_ objects. The API endpoints associated with _brands_ have also been renamed. + + Blueprints using `authentik_tenants.tenant` will need to be changed to use `authentik_brands.brand`. + + For more information, refer to the [documentation for _brands_](../../core/brands.md). + + Also, **the event retention settings configured in brands (previously tenants, see above) has been removed and is now a system setting**, managed in the Admin interface or via the API (see below). + + **There is no built-in migration path for this change.** If you set something other than the default (`days=365`), you will need to update the setting in the admin interface. + +- **Helm chart breaking changes** + + The Helm Chart has a number of breaking changes. Find out more in the [chart release notes](https://github.com/goauthentik/helm/releases/tag/authentik-2024.2.0). + +### Manual action may be required + +- **Required `offline_access` scope for Refresh tokens** + + The OAuth2 provider ships with a new default scope called `offline_access`, which must be requested by applications that need a refresh token. Previously, authentik would always issue a refresh token for the _Authorization code_ and _Device code_ OAuth grants. + + Applications that require a refresh token will need their configuration to be updated to include the `offline_access` scope mapping. + +- **Database requirement changes** + + authentik now uses PostgreSQL schemas other than `public`. + + If you have a custom PostgreSQL deployment, please ensure that the authentik user is allowed to create schemas. Usually, if the authentik user is owner of the database, it already can. + +- **Redis and cache configuration options have been improved** + + Thank you @PKizzle for this contribution! + + Cache settings have been moved from the `redis` top-level config key to their own `cache` top-level config key. + + Settings have also been added to configure the Redis instance/database used for tasks and websockets separately from cache. See [here](../../installation/configuration.mdx#redis-settings). + + Typically, _no changes to the configuration are required_. + +- **Configuration options migrated to the Admin interface** + + The following config options have been moved from the config file and can now be set using the Admin interface (under **System** -> **Settings**) or the API: + + - `AUTHENTIK_AVATARS` + - `AUTHENTIK_DEFAULT_USER_CHANGE_NAME` + - `AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL` + - `AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME` + - `AUTHENTIK_GDPR_COMPLIANCE` + - `AUTHENTIK_IMPERSONATION` + - `AUTHENTIK_FOOTER_LINKS` + - `AUTHENTIK_REPUTATION__EXPIRY` + + When upgrading to 2024.2, the currently configured options will be automatically migrated to the database, and can be removed from the `.env` or helm values file afterwards. + +- **Icons are now in a `public/` subfolder** + + If your media folder is `/media`, icons are now stored in `/media/public`. authentik will automatically migrate the icons upon upgrading. + + Note that even though that folder is named `public`, the files stored here are not automatically public. This is due to the naming of the default PostgreSQL schema. + +- **User sessions will be invalidated after this upgrade.** + + As such, users will need to log back in. Immediately after the upgrade completes, users are logged out automatically and are then prompted to log in again. This only occurs once. + +- **Removal of deprecated metrics** + + These metrics were renamed because they did not adhere to Prometheus best practices. The old metrics were kept for backwards compatibility and have now been removed. + + - `authentik_outpost_flow_timing_get` -> `authentik_outpost_flow_timing_get_seconds` + - `authentik_outpost_flow_timing_post` -> `authentik_outpost_flow_timing_post_seconds` + - `authentik_outpost_ldap_requests` -> `authentik_outpost_ldap_request_duration_seconds` + - `authentik_outpost_ldap_requests_rejected` -> `authentik_outpost_ldap_requests_rejected_total` + - `authentik_outpost_proxy_requests` -> `authentik_outpost_proxy_request_duration_seconds` + - `authentik_outpost_proxy_upstream_time` -> `authentik_outpost_proxy_upstream_response_duration_seconds` + - `authentik_outpost_radius_requests` -> `authentik_outpost_radius_request_duration_seconds` + - `authentik_outpost_radius_requests_rejected` -> `authentik_outpost_radius_requests_rejected_total` + - `authentik_main_requests` -> `authentik_main_request_duration_seconds` + +- The shorthand parameter for `--stage`, `-s` for the `ak test_email` command has been changed to `-S` + +## New features + +- **New provider: Remote Access Control** Enterprise + + The Remote Access Control provider allows you to remotely connect to remote machines over RDP, SSH and VNC through authentik. As such, you can use the same policy engine and customization options that are possible with other providers using the same user and admin interface. + +- **Audit logging** Enterprise + + authentik instances that have a valid enterprise license installed will log any changes made to models, including which fields were changed with previous and new values of the fields. The values are censored if they are sensitive (for example a password hash), however a hash of the changed value will still be logged. + +- **Session location and network binding** + + Sessions for any users can now be bound to a specific geolocation (Continent, Country, City) or network (Autonomous System, subnet, IP address). If the session is accessed from a location/network that is different than that from which it was initially created, the session will be terminated. + + Configuration steps are available [here](../../flow/stages/user_login/index.md#network-bindinggeoip-binding). + +- **S3 file storage** + + Media files can now be stored on S3. Follow the [setup guide](../../installation/storage-s3.md) to get started. + +- **_Pretend user exists_ option for Identification stage** + + Previously the Identification stage would only continue if a user matching the user identifier exists. While this was the intended functionality, this release adds an option to continue to the next stage even if no matching user was found. "Pretend" users cannot authenticate nor receive emails, and don't exist in the database. + + **This feature is enabled by default.** + +### UX features + +- **Simplified workflow for creating applications and providers** + + Applications and providers can now be created at the same time using the **Application Wizard**, found on the **Applications** -> **Applications** page of the Admin interface. The new wizard removes the previous requirement of first creating the provider, then the application, and then manually linking the two together. + +- **Ability to select more than 20 providers in an outpost** + + We have introduced a new way of selecting providers in the outpost configuration form, which allows for more than 20 providers to be selected for a single outpost. + + This dual-list multiselect prompt is only available for outposts for now, but we plan on extending it to other forms. + +- **Attribute preview per user** + + You can now preview attributes transmitted to SAML and OAuth applications for a specific user. + +- **Display applications a user has access to** + + An administrator can now see all applications a user has access to on the user's page in the Admin interface. + +### Other noteworthy features + +- **New graph for event volume** + + In the **Events** -> **Log** page in the Admin interface, you can see a graph of the event volume matching the search query over the last 7 days. + +- **Flows can now be restricted to outposts** + + You can now restrict a flow to be used only by an outpost using the **Require Outpost** setting on the flow. This would mainly be used for LDAP flows. + +- **System tasks improvements** + + You can now search through system tasks. We have also improved the task duration calculation and display. + +- **LDAP provider: allow overriding gidNumber** + + Previously, the `gidNumber` attribute on a user was set to the same as `uidNumber`. You can now override this behaviour. + +- **LDAP source: new command to check connectivity** + + Examples on how to use are available [here](../..//troubleshooting/ldap_source.md). + +--- + +## Upgrading + +This release does not introduce any new requirements, but contains some breaking changes, see above. + +### docker-compose + +To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: + +```shell +wget -O docker-compose.yml https://goauthentik.io/version/2024.2/docker-compose.yml +docker compose up -d +``` + +The `-O` flag retains the downloaded file's name, overwriting any existing local file with the same name. + +### Kubernetes + +Upgrade the Helm Chart to the new version, using the following commands: + +```shell +helm repo update +helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.2 +``` + +## Minor changes/fixes + +- blueprints: improve file change handler (#7813) +- blueprints: only watch for fs events we're interested in (#7810) +- core: fix PropertyMapping context not being available in request context +- core: fix pagination in applications list being ignored (#8512) +- core: fix worker beat toggle inverted (#7508) +- core: optimise user list endpoint (#8353) +- core: show all applications a user can access in admin interface (#8343) +- core: use correct .evaluate implementation for testing PropertyMappings (#8459) +- core: use correct .evaluate implementation for testing PropertyMappings (#8459) +- enterprise/providers/rac: add alert that enterprise is required for RAC (#8057) +- enterprise/providers/rac: add option to limit concurrent connections to endpoint (#8053) +- enterprise/providers/rac: connection token management (#8467) +- enterprise/providers/rac: create authorize_application event when creating token (#8050) +- enterprise/providers/rac: fix maximum_connections set to -1 not being effective (#8456) +- enterprise/providers/rac: fix maximum_connections set to -1 not being effective (#8456) +- enterprise/providers: Add RAC (#7291) +- enterprise: add full audit log (#8177) +- enterprise: fix system task missing set_status (#8455) +- enterprise: rework license summary caching (#8501) +- enterrpise: exclude inactive users from license (#8294) +- events: add ASN Database reader (#7793) +- events: add better fallback for sanitize_item to ensure everything can be saved as JSON (#7694) +- events: add graph for event volume (#7639) +- events: fix SystemTask timestamps and scheduling (#8435) +- events: include user agent in events (#7693) +- events: migrate SystemTasks to DB (#8159) +- flows: add "require outpost" authentication_requirement (#7921) +- internal: remove deprecated metrics (#7540) +- internal: remove special route for /outpost.goauthentik.io (#7539) +- outposts/ldap: allow overriding gidNumber for a user (#8003) +- outposts/ldap: avoid nil ptr deref in MemorySearcher (#7767) +- outposts/proxy: better Redis error message (#8044) +- outposts: disable deployment and secret reconciler for embedded outpost in code instead of in config (#8021)(#8024) +- outposts: fix Outpost reconcile not re-assigning managed attribute (#8014) +- providers/oauth2: fix CVE-2024-21637 (#8104) +- providers/oauth2: fix missing nonce in id_token (#8072) +- providers/oauth2: fix missing nonce in token endpoint not being saved (#8073) +- providers/oauth2: offline access (#8026) +- providers/oauth2: remember session_id from initial token (#7976) +- providers/oauth2: set auth_via for token and other endpoints (#7417) +- providers/proxy: Fix duplicate cookies when using file system store. (#7541) +- providers/proxy: fix closed redis client (#7385) +- providers/proxy: use access token (#8022) +- providers/rac: fix property mapping without enterprise (#8144) +- providers/scim: change familyName default (#7904) +- providers/scim: fix missing schemas attribute for User and Group (#7477) +- providers/scim: set timeout based on page and page count (#7941) +- providers/scim: use lock for sync (#7948) +- providers: allow previewing mappings for other users (#8297) +- rbac: fix error when looking up permissions for now uninstalled apps (#8068) +- rbac: fix invitations listing with restricted permissions (#8227) +- root: Multi-tenancy (#7590) +- root: Restructure broker / cache / channel / result configuration (#7097) +- root: bump python deps (django 5) (#7862) +- root: fix listen trusted_proxy_cidrs config loading from environment (#8075) +- root: fix redis config not being updated to match previous change +- root: fix system check warnings (#8277) +- root: include ca-certificates in container (#7763) +- root: make test database name configurable (#7591) +- root: simplify task signal imports (#8454) +- security: fix CVE-2023-48228 (#7666) +- security: fix CVE-2024-23647 (#8345) +- sources/ldap: add check command to verify ldap connectivity (#7263) +- sources/ldap: clean-up certs written from db (#7617) +- sources/ldap: fix Issue with changing passwords with eDirectory (#7997) +- sources/oauth: fix OAuth source type serializer (#8140) +- sources/oauth: fix URLs being overwritten by OIDC urls (#8147) +- sources/oauth: fix azure_ad user_id and add test and fallback (#8146) +- sources/oauth: fix missing get_user_id for OIDC-like sources (Azure AD) (#7970) +- sources/oauth: fix patreon (#7454) +- sources/oauth: revert azure_ad profile URL change (#8139) +- stages/authenticator_totp: fix API validation error due to choices (#7608) +- stages/authenticator_validate: fix error when using pretend_user (#8447) +- stages/authenticator_validate: fix error when using pretend_user (#8447) +- stages/authenticator_validate: use friendly_name for stage selector when enrolling (#8255) +- stages/email: fix duplicate querystring encoding (#7386) +- stages/email: improve error handling for incorrect template syntax (#7758) +- stages/email: prevent authentik emails from being marked as spam (also add text template support) (#7949) +- stages/email: use uuid for email confirmation token instead of username (#7581) +- stages/identification: add option to pretend user exists (#7610) +- stages/user_login: only set last_ip in session if a binding is given (#8074) +- stages/user_login: session binding (#7881) +- web/admin: add RAC Provider to the list of providers understood by the wizard (#8149) +- web/admin: always show oidc well-known URL fields when they're set (#7560) +- web/admin: contextually add user to group when creating user from group page (#7586) +- web/admin: fix admins not able to delete MFA devices (#7660) +- web/admin: fix chart label on dashboard user page (#7434) +- web/admin: fix footer links not being parsed on settings page (#8289) +- web/admin: fix html error on oauth2 provider page (#7384) +- web/admin: fix incorrectly encoded chars in translation (#7580) +- web/admin: hide expiry time if item is set to not expire (#8457) +- web/admin: hide expiry time if item is set to not expire (#8457) +- web/admin: revamped rbac and user settings tabs (#8299) +- web/admin: revise wizard form handling (#7331) +- web/admin: show connected services on user view page, fix styling (#8416) +- web/components: improve error handling in ak-search-select (#8228) +- web/elements: keep selected elements in table when fetching (#7519) +- web/flows: attempt to fix bitwareden android compatibility (#7455) +- web/flows: don't auto-redirect to first source when passwordless is configured (#7579) +- web/flows: fix device picker incorrect foreground color (#8067) +- web/flows: fix icon for generic oauth source with dark theme (#8148) +- web/flows: fix logo height (#7834) +- web/flows: show logo in card (#7824) +- web/flows: use aria-invalid attribute to better show invalid input fields (#7661) +- web/user: fix search not updating selected app in user interface (#7825) +- web: clear "blanked" placeholder when present (#15) (#5948) +- web: clear out selecteds list after an API event to ensure a fresh copy of the policies-to-delete list (#8125) +- web: dark/light theme fixes (#7872) +- web: fix broken backchannel selector (#7480) +- web: fix labels on group view page (#7677) +- web: fix overflow glitch on ak-page-header (#7883) +- web: provide dual-list multiselect with pagination (#8004) + +## Fixed in 2024.2.1 + +- brands: fix context processor when request doesn't have a tenant (cherry-pick #8643) (#8646) +- ci: fix missing tags from release (cherry-pick #8645) (#8647) +- core: bump cbor2 from 5.5.1 to 5.6.2 (#8607) +- core: bump cryptography from 42.0.0 to 42.0.2 (#8553) +- core: bump cryptography from 42.0.2 to 42.0.4 (#8629) +- events: sanitize args and kwargs saved in system tasks (cherry-pick #8644) (#8648) +- stages/authenticator_validate: fix error with get_webauthn_challenge_without_user (cherry-pick #8625) (#8626) + +## Fixed in 2024.2.2 + +- core: fix blueprint export (cherry-pick #8695) (#8696) +- enterprise: fix read_only activating when no license is installed (cherry-pick #8697) (#8698) +- enterprise: force license usage update after change to license (cherry-pick #8723) (#8725) +- flows: fix mismatched redirect behaviour for invalid and valid flows (cherry-pick #8794) (#8796) +- providers/oauth2: fix inconsistent `sub` value when setting via mapping (cherry-pick #8677) (#8682) +- providers/oauth2: fix offline_access requests when prompt doesn't include consent (cherry-pick #8731) (#8732) +- providers/oauth2: fix validation ordering (cherry-pick #8793) (#8795) +- root: ensure consistent install_id (cherry-pick #8775) (#8776) +- root: fix container build (cherry-pick #8727) (#8728) +- stages/authenticator_webauthn: fix error when enrolling new device (cherry-pick #8738) (#8740) +- web/admin: don't mark property mappings as required anywhere (cherry-pick #8752) (#8755) +- web/admin: don't mark remaining property mappings as required (cherry-pick #8772) (#8773) + +## Fixed in 2024.2.3 + +- api: capabilities: properly set can_save_media when s3 is enabled (cherry-pick #8896) (#8897) +- enterprise: only check for valid license existing for creating Enterprise objects (cherry-pick #8813) (#8822) +- enterprise/rac: fix connection token management (cherry-pick #8909) (#8912) +- events: discard notification if user has empty email (cherry-pick #8938) (#8951) +- events: fix incorrect user logged when using API token authentication (#9302) +- lifecycle: migrate: ensure template schema exists before migrating (cherry-pick #8952) (#9022) +- stages/email: Disable autoescape for text templates (cherry-pick #8812) (#8824) +- stages/email: fix issue when sending emails to users with same display as email (cherry-pick #8850) (#8852) +- stages/user_write: ensure user data is json-serializable (cherry-pick #8926) (#8928) +- tenants: really ensure default tenant cannot be deleted (cherry-pick #8875) (#8876) + +## API Changes + +#### What's New + +--- + +##### `GET` /admin/settings/ + +##### `PUT` /admin/settings/ + +##### `PATCH` /admin/settings/ + +##### `GET` /core/brands/ + +##### `POST` /core/brands/ + +##### `GET` /core/brands/{brand_uuid}/ + +##### `PUT` /core/brands/{brand_uuid}/ + +##### `DELETE` /core/brands/{brand_uuid}/ + +##### `PATCH` /core/brands/{brand_uuid}/ + +##### `GET` /core/brands/{brand_uuid}/used_by/ + +##### `GET` /core/brands/current/ + +##### `GET` /events/events/volume/ + +##### `GET` /events/system_tasks/ + +##### `GET` /events/system_tasks/{uuid}/ + +##### `POST` /events/system_tasks/{uuid}/run/ + +##### `GET` /propertymappings/rac/ + +##### `POST` /propertymappings/rac/ + +##### `GET` /propertymappings/rac/{pm_uuid}/ + +##### `PUT` /propertymappings/rac/{pm_uuid}/ + +##### `DELETE` /propertymappings/rac/{pm_uuid}/ + +##### `PATCH` /propertymappings/rac/{pm_uuid}/ + +##### `GET` /propertymappings/rac/{pm_uuid}/used_by/ + +##### `GET` /providers/rac/ + +##### `POST` /providers/rac/ + +##### `GET` /providers/rac/{id}/ + +##### `PUT` /providers/rac/{id}/ + +##### `DELETE` /providers/rac/{id}/ + +##### `PATCH` /providers/rac/{id}/ + +##### `GET` /providers/rac/{id}/used_by/ + +##### `GET` /rac/connection_tokens/ + +##### `GET` /rac/connection_tokens/{connection_token_uuid}/ + +##### `PUT` /rac/connection_tokens/{connection_token_uuid}/ + +##### `DELETE` /rac/connection_tokens/{connection_token_uuid}/ + +##### `PATCH` /rac/connection_tokens/{connection_token_uuid}/ + +##### `GET` /rac/connection_tokens/{connection_token_uuid}/used_by/ + +##### `GET` /rac/endpoints/ + +##### `POST` /rac/endpoints/ + +##### `GET` /rac/endpoints/{pbm_uuid}/ + +##### `PUT` /rac/endpoints/{pbm_uuid}/ + +##### `DELETE` /rac/endpoints/{pbm_uuid}/ + +##### `PATCH` /rac/endpoints/{pbm_uuid}/ + +##### `GET` /rac/endpoints/{pbm_uuid}/used_by/ + +#### What's Deleted + +--- + +##### `GET` /admin/system_tasks/ + +##### `GET` /admin/system_tasks/{id}/ + +##### `POST` /admin/system_tasks/{id}/retry/ + +#### What's Changed + +--- + +##### `GET` /admin/system/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `brand` + - `embedded_outpost_disabled` + + New optional properties: + + - `tenant` + + * Added property `brand` (string) + + > Currently active brand + + * Added property `embedded_outpost_disabled` (boolean) + + > Whether the embedded outpost is disabled + + * Deleted property `tenant` (string) + > Currently active tenant + +##### `POST` /admin/system/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `brand` + - `embedded_outpost_disabled` + + New optional properties: + + - `tenant` + + * Added property `brand` (string) + + > Currently active brand + + * Added property `embedded_outpost_disabled` (boolean) + + > Whether the embedded outpost is disabled + + * Deleted property `tenant` (string) + > Currently active tenant + +##### `GET` /core/applications/{slug}/check_access/ + +###### Return Type: + +Deleted response : **404 Not Found** + +> for_user user not found + +##### `GET` /core/authenticated_sessions/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `asn` + + * Added property `asn` (object) + + > Get ASN Data + + - Property `asn` (integer) + + - Property `as_org` (string) + + - Property `network` (string) + + * Changed property `geo_ip` (object) + > Get GeoIP Data + +##### `GET` /events/events/actions/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /managed/blueprints/{instance_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `PUT` /managed/blueprints/{instance_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `PATCH` /managed/blueprints/{instance_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `POST` /managed/blueprints/{instance_uuid}/apply/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `GET` /outposts/service_connections/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /outposts/service_connections/kubernetes/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +##### `PUT` /outposts/service_connections/kubernetes/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +##### `PATCH` /outposts/service_connections/kubernetes/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +##### `GET` /policies/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /policies/event_matcher/{policy_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + + - Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `PUT` /policies/event_matcher/{policy_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + + - Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `PATCH` /policies/event_matcher/{policy_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + + - Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `GET` /policies/reputation/scores/{reputation_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `ip_asn_data` (object) + + - Changed property `ip_geo_data` (object -> object) + +##### `GET` /propertymappings/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /providers/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /providers/oauth2/{id}/preview_user/ + +###### Parameters: + +Added: `for_user` in `query` + +##### `GET` /providers/saml/{id}/preview_user/ + +###### Parameters: + +Added: `for_user` in `query` + +##### `GET` /providers/scim/{id}/sync_status/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `is_running` + - `tasks` + + New optional properties: + + - `messages` + - `status` + - `task_description` + - `task_duration` + - `task_finish_timestamp` + - `task_name` + + * Added property `is_running` (boolean) + + * Added property `tasks` (array) + + Items (object): > Serialize TaskInfo and TaskResult + + - Property `uuid` (string) + + - Property `name` (string) + + - Property `full_name` (string) + + > Get full name with UID + + - Property `uid` (string) + + - Property `description` (string) + + - Property `start_timestamp` (string) + + - Property `finish_timestamp` (string) + + - Property `duration` (number) + + - Property `status` (string) + + > - `unknown` - UNKNOWN + > - `successful` - SUCCESSFUL + > - `warning` - WARNING + > - `error` - ERROR + + Enum values: + + - `unknown` + - `successful` + - `warning` + - `error` + + - Property `messages` (array) + + Items (string): + + * Deleted property `task_name` (string) + + * Deleted property `task_description` (string) + + * Deleted property `task_finish_timestamp` (string) + + * Deleted property `task_duration` (integer) + + > Get the duration a task took to run + + * Deleted property `status` (object) + + * Deleted property `messages` (array) + +##### `GET` /schema/ + +###### Parameters: + +Changed: `lang` in `query` + +##### `GET` /sources/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /sources/ldap/{slug}/sync_status/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + +##### `GET` /sources/oauth/source_types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + +##### `GET` /stages/all/types/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /stages/email/templates/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > Types of an object that can be created + + - Added property `requires_enterprise` (boolean) + +##### `GET` /authenticators/duo/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /authenticators/sms/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /authenticators/static/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /authenticators/totp/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /authenticators/webauthn/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/applications/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/authenticated_sessions/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatedSession Serializer + + New required properties: + + - `asn` + + * Added property `asn` (object) + + > Get ASN Data + + * Changed property `geo_ip` (object) + > Get GeoIP Data + +##### `GET` /core/authenticated_sessions/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/groups/{group_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/tokens/{identifier}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PUT` /core/tokens/{identifier}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PATCH` /core/tokens/{identifier}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/tokens/{identifier}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/user_consent/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/users/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PUT` /core/users/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PATCH` /core/users/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/users/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /crypto/certificatekeypairs/{kp_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /enterprise/license/{license_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /events/events/{event_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `PUT` /events/events/{event_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `brand` (object) + +- Deleted property `tenant` (object) + +- Changed property `user` (object -> object) + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `PATCH` /events/events/{event_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `brand` (object) + +- Deleted property `tenant` (object) + +- Changed property `user` (object -> object) + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `GET` /events/notifications/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /events/rules/{pbm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /events/transports/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /flows/bindings/{fsb_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /flows/instances/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /flows/instances/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + +- Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /flows/instances/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + +- Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /flows/instances/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `POST` /managed/blueprints/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `GET` /managed/blueprints/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Info about a single blueprint instance file + + - Changed property `context` (object -> object) + + - Changed property `metadata` (object -> object) + +##### `GET` /managed/blueprints/{instance_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /oauth2/access_tokens/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /oauth2/authorization_codes/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /oauth2/refresh_tokens/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /outposts/instances/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +##### `PUT` /outposts/instances/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +##### `PATCH` /outposts/instances/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +##### `GET` /outposts/instances/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /outposts/service_connections/all/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /outposts/service_connections/docker/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `POST` /outposts/service_connections/kubernetes/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +##### `GET` /outposts/service_connections/kubernetes/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > KubernetesServiceConnection Serializer + + - Changed property `kubeconfig` (object -> object) + > Paste your kubeconfig here. authentik will automatically use the currently selected context. + +##### `GET` /outposts/service_connections/kubernetes/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/all/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PUT` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `PATCH` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /policies/bindings/{policy_binding_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/dummy/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `POST` /policies/event_matcher/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + + - Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `GET` /policies/event_matcher/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Event Matcher Policy Serializer + + - Changed property `app` (string) + + > - `authentik.tenants` - authentik Tenants + > - `authentik.admin` - authentik Admin + > - `authentik.api` - authentik API + > - `authentik.crypto` - authentik Crypto + > - `authentik.flows` - authentik Flows + > - `authentik.outposts` - authentik Outpost + > - `authentik.policies.dummy` - authentik Policies.Dummy + > - `authentik.policies.event_matcher` - authentik Policies.Event Matcher + > - `authentik.policies.expiry` - authentik Policies.Expiry + > - `authentik.policies.expression` - authentik Policies.Expression + > - `authentik.policies.password` - authentik Policies.Password + > - `authentik.policies.reputation` - authentik Policies.Reputation + > - `authentik.policies` - authentik Policies + > - `authentik.providers.ldap` - authentik Providers.LDAP + > - `authentik.providers.oauth2` - authentik Providers.OAuth2 + > - `authentik.providers.proxy` - authentik Providers.Proxy + > - `authentik.providers.radius` - authentik Providers.Radius + > - `authentik.providers.saml` - authentik Providers.SAML + > - `authentik.providers.scim` - authentik Providers.SCIM + > - `authentik.rbac` - authentik RBAC + > - `authentik.recovery` - authentik Recovery + > - `authentik.sources.ldap` - authentik Sources.LDAP + > - `authentik.sources.oauth` - authentik Sources.OAuth + > - `authentik.sources.plex` - authentik Sources.Plex + > - `authentik.sources.saml` - authentik Sources.SAML + > - `authentik.stages.authenticator` - authentik Stages.Authenticator + > - `authentik.stages.authenticator_duo` - authentik Stages.Authenticator.Duo + > - `authentik.stages.authenticator_sms` - authentik Stages.Authenticator.SMS + > - `authentik.stages.authenticator_static` - authentik Stages.Authenticator.Static + > - `authentik.stages.authenticator_totp` - authentik Stages.Authenticator.TOTP + > - `authentik.stages.authenticator_validate` - authentik Stages.Authenticator.Validate + > - `authentik.stages.authenticator_webauthn` - authentik Stages.Authenticator.WebAuthn + > - `authentik.stages.captcha` - authentik Stages.Captcha + > - `authentik.stages.consent` - authentik Stages.Consent + > - `authentik.stages.deny` - authentik Stages.Deny + > - `authentik.stages.dummy` - authentik Stages.Dummy + > - `authentik.stages.email` - authentik Stages.Email + > - `authentik.stages.identification` - authentik Stages.Identification + > - `authentik.stages.invitation` - authentik Stages.User Invitation + > - `authentik.stages.password` - authentik Stages.Password + > - `authentik.stages.prompt` - authentik Stages.Prompt + > - `authentik.stages.user_delete` - authentik Stages.User Delete + > - `authentik.stages.user_login` - authentik Stages.User Login + > - `authentik.stages.user_logout` - authentik Stages.User Logout + > - `authentik.stages.user_write` - authentik Stages.User Write + > - `authentik.brands` - authentik Brands + > - `authentik.blueprints` - authentik Blueprints + > - `authentik.core` - authentik Core + > - `authentik.enterprise` - authentik Enterprise + > - `authentik.enterprise.audit` - authentik Enterprise.Audit + > - `authentik.enterprise.providers.rac` - authentik Enterprise.Providers.RAC + > - `authentik.events` - authentik Events + + Added enum values: + + - `authentik.brands` + - `authentik.enterprise.audit` + - `authentik.enterprise.providers.rac` + + - Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `GET` /policies/event_matcher/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/expression/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/password/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/password_expiry/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/reputation/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /policies/reputation/scores/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Reputation Serializer + + - Added property `ip_asn_data` (object) + + - Changed property `ip_geo_data` (object -> object) + +##### `GET` /policies/reputation/scores/{reputation_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/all/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/ldap/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/notification/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/saml/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/scim/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /propertymappings/scope/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/all/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/ldap/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/oauth2/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/proxy/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/radius/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/saml/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /providers/scim/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `POST` /rbac/permissions/assigned_by_roles/{uuid}/assign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `PATCH` /rbac/permissions/assigned_by_roles/{uuid}/unassign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `POST` /rbac/permissions/assigned_by_users/{id}/assign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `PATCH` /rbac/permissions/assigned_by_users/{id}/unassign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + > - `authentik_tenants.domain` - Domain + > - `authentik_crypto.certificatekeypair` - Certificate-Key Pair + > - `authentik_flows.flow` - Flow + > - `authentik_flows.flowstagebinding` - Flow Stage Binding + > - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection + > - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection + > - `authentik_outposts.outpost` - Outpost + > - `authentik_policies_dummy.dummypolicy` - Dummy Policy + > - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy + > - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy + > - `authentik_policies_expression.expressionpolicy` - Expression Policy + > - `authentik_policies_password.passwordpolicy` - Password Policy + > - `authentik_policies_reputation.reputationpolicy` - Reputation Policy + > - `authentik_policies.policybinding` - Policy Binding + > - `authentik_providers_ldap.ldapprovider` - LDAP Provider + > - `authentik_providers_oauth2.scopemapping` - Scope Mapping + > - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider + > - `authentik_providers_proxy.proxyprovider` - Proxy Provider + > - `authentik_providers_radius.radiusprovider` - Radius Provider + > - `authentik_providers_saml.samlprovider` - SAML Provider + > - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping + > - `authentik_providers_scim.scimprovider` - SCIM Provider + > - `authentik_providers_scim.scimmapping` - SCIM Mapping + > - `authentik_rbac.role` - Role + > - `authentik_sources_ldap.ldapsource` - LDAP Source + > - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping + > - `authentik_sources_oauth.oauthsource` - OAuth Source + > - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection + > - `authentik_sources_plex.plexsource` - Plex Source + > - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection + > - `authentik_sources_saml.samlsource` - SAML Source + > - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection + > - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage + > - `authentik_stages_authenticator_duo.duodevice` - Duo Device + > - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage + > - `authentik_stages_authenticator_sms.smsdevice` - SMS Device + > - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage + > - `authentik_stages_authenticator_static.staticdevice` - Static Device + > - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage + > - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device + > - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage + > - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage + > - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device + > - `authentik_stages_captcha.captchastage` - Captcha Stage + > - `authentik_stages_consent.consentstage` - Consent Stage + > - `authentik_stages_consent.userconsent` - User Consent + > - `authentik_stages_deny.denystage` - Deny Stage + > - `authentik_stages_dummy.dummystage` - Dummy Stage + > - `authentik_stages_email.emailstage` - Email Stage + > - `authentik_stages_identification.identificationstage` - Identification Stage + > - `authentik_stages_invitation.invitationstage` - Invitation Stage + > - `authentik_stages_invitation.invitation` - Invitation + > - `authentik_stages_password.passwordstage` - Password Stage + > - `authentik_stages_prompt.prompt` - Prompt + > - `authentik_stages_prompt.promptstage` - Prompt Stage + > - `authentik_stages_user_delete.userdeletestage` - User Delete Stage + > - `authentik_stages_user_login.userloginstage` - User Login Stage + > - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage + > - `authentik_stages_user_write.userwritestage` - User Write Stage + > - `authentik_brands.brand` - Brand + > - `authentik_blueprints.blueprintinstance` - Blueprint Instance + > - `authentik_core.group` - Group + > - `authentik_core.user` - User + > - `authentik_core.application` - Application + > - `authentik_core.token` - Token + > - `authentik_enterprise.license` - License + > - `authentik_providers_rac.racprovider` - RAC Provider + > - `authentik_providers_rac.endpoint` - RAC Endpoint + > - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping + > - `authentik_events.event` - Event + > - `authentik_events.notificationtransport` - Notification Transport + > - `authentik_events.notification` - Notification + > - `authentik_events.notificationrule` - Notification Rule + > - `authentik_events.notificationwebhookmapping` - Webhook Mapping + + Added enum values: + + - `authentik_tenants.domain` + - `authentik_brands.brand` + - `authentik_providers_rac.racprovider` + - `authentik_providers_rac.endpoint` + - `authentik_providers_rac.racpropertymapping` + Removed enum values: + + - `authentik_policies_reputation.reputation` + - `authentik_providers_oauth2.authorizationcode` + - `authentik_providers_oauth2.accesstoken` + - `authentik_providers_oauth2.refreshtoken` + - `authentik_tenants.tenant` + +##### `GET` /rbac/roles/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /root/config/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `capabilities` (array) + + Changed items (string): > _ `can_save_media` - Can Save Media > _ `can_geo_ip` - Can Geo Ip > _ `can_asn` - Can Asn > _ `can_impersonate` - Can Impersonate > _ `can_debug` - Can Debug > _ `is_enterprise` - Is Enterprise + + Added enum value: + + - `can_asn` + +##### `GET` /sources/all/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/ldap/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `connectivity` + + * Added property `connectivity` (object) + > Get cached source connectivity + +##### `PUT` /sources/ldap/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `connectivity` + + * Added property `connectivity` (object) + > Get cached source connectivity + +##### `PATCH` /sources/ldap/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `connectivity` + + * Added property `connectivity` (object) + > Get cached source connectivity + +##### `GET` /sources/ldap/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/oauth/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (object) + + > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + + - Changed property `oidc_jwks` (object -> object) + + - Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +##### `PUT` /sources/oauth/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `oidc_jwks` (object -> object) + +- Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (object) + + > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + + - Changed property `oidc_jwks` (object -> object) + + - Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +##### `PATCH` /sources/oauth/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `oidc_jwks` (object -> object) + +- Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (object) + + > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + + - Changed property `oidc_jwks` (object -> object) + + - Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +##### `GET` /sources/oauth/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/plex/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/saml/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/user_connections/all/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/user_connections/oauth/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/user_connections/plex/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /sources/user_connections/saml/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/all/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/duo/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/sms/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/static/{stage_uuid}/used_by/ + +###### Parameters: + +Changed: `stage_uuid` in `path` + +> A UUID string identifying this Static Authenticator Setup Stage. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/totp/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/validate/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/authenticator/webauthn/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/captcha/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/consent/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/deny/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/dummy/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/email/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/identification/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/invitation/invitations/{invite_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/invitation/stages/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/password/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/prompt/prompts/{prompt_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/prompt/stages/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/user_delete/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/user_login/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/user_logout/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /stages/user_write/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + + > - `cascade` - CASCADE + > - `cascade_many` - CASCADE_MANY + > - `set_null` - SET_NULL + > - `set_default` - SET_DEFAULT + + Added enum values: + + - `cascade` + - `cascade_many` + - `set_null` + - `set_default` + Removed enum values: + + - `CASCADE` + - `CASCADE_MANY` + - `SET_NULL` + - `SET_DEFAULT` + +##### `GET` /core/applications/ + +###### Parameters: + +Added: `for_user` in `query` + +##### `POST` /core/tokens/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Token Serializer + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/user_consent/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `expiring` (boolean) + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `POST` /core/users/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/users/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /core/users/me/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer for information a user can retrieve about themselves + + - Changed property `avatar` (string) + + > User's avatar, either a http/https URL or a data URI + + - Changed property `settings` (object) + > Get user settings with brand and group settings applied + +##### `POST` /events/events/ + +###### Request: + +Changed content type : `application/json` + +- Added property `brand` (object) + +- Deleted property `tenant` (object) + +- Changed property `user` (object -> object) + +- Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `GET` /events/events/ + +###### Parameters: + +Added: `brand_name` in `query` + +> Brand name + +Deleted: `tenant_name` in `query` + +> Tenant name + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `GET` /events/notifications/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `PUT` /events/notifications/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `PATCH` /events/notifications/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `GET` /flows/bindings/{fsb_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /flows/bindings/{fsb_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /flows/bindings/{fsb_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /flows/instances/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + +- Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /flows/instances/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /oauth2/access_tokens/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /oauth2/authorization_codes/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /oauth2/refresh_tokens/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `POST` /outposts/instances/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +##### `GET` /outposts/instances/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Outpost Serializer + + - Changed property `type` (string) + + > - `proxy` - Proxy + > - `ldap` - Ldap + > - `radius` - Radius + > - `rac` - Rac + + Added enum value: + + - `rac` + +##### `POST` /policies/bindings/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /policies/bindings/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PolicyBinding Serializer + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /rbac/permissions/assigned_by_roles/ + +###### Parameters: + +Changed: `model` in `query` + +> - `authentik_tenants.domain` - Domain +> - `authentik_crypto.certificatekeypair` - Certificate-Key Pair +> - `authentik_flows.flow` - Flow +> - `authentik_flows.flowstagebinding` - Flow Stage Binding +> - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection +> - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection +> - `authentik_outposts.outpost` - Outpost +> - `authentik_policies_dummy.dummypolicy` - Dummy Policy +> - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy +> - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy +> - `authentik_policies_expression.expressionpolicy` - Expression Policy +> - `authentik_policies_password.passwordpolicy` - Password Policy +> - `authentik_policies_reputation.reputationpolicy` - Reputation Policy +> - `authentik_policies.policybinding` - Policy Binding +> - `authentik_providers_ldap.ldapprovider` - LDAP Provider +> - `authentik_providers_oauth2.scopemapping` - Scope Mapping +> - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider +> - `authentik_providers_proxy.proxyprovider` - Proxy Provider +> - `authentik_providers_radius.radiusprovider` - Radius Provider +> - `authentik_providers_saml.samlprovider` - SAML Provider +> - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping +> - `authentik_providers_scim.scimprovider` - SCIM Provider +> - `authentik_providers_scim.scimmapping` - SCIM Mapping +> - `authentik_rbac.role` - Role +> - `authentik_sources_ldap.ldapsource` - LDAP Source +> - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping +> - `authentik_sources_oauth.oauthsource` - OAuth Source +> - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection +> - `authentik_sources_plex.plexsource` - Plex Source +> - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection +> - `authentik_sources_saml.samlsource` - SAML Source +> - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection +> - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage +> - `authentik_stages_authenticator_duo.duodevice` - Duo Device +> - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage +> - `authentik_stages_authenticator_sms.smsdevice` - SMS Device +> - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage +> - `authentik_stages_authenticator_static.staticdevice` - Static Device +> - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage +> - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device +> - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage +> - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage +> - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device +> - `authentik_stages_captcha.captchastage` - Captcha Stage +> - `authentik_stages_consent.consentstage` - Consent Stage +> - `authentik_stages_consent.userconsent` - User Consent +> - `authentik_stages_deny.denystage` - Deny Stage +> - `authentik_stages_dummy.dummystage` - Dummy Stage +> - `authentik_stages_email.emailstage` - Email Stage +> - `authentik_stages_identification.identificationstage` - Identification Stage +> - `authentik_stages_invitation.invitationstage` - Invitation Stage +> - `authentik_stages_invitation.invitation` - Invitation +> - `authentik_stages_password.passwordstage` - Password Stage +> - `authentik_stages_prompt.prompt` - Prompt +> - `authentik_stages_prompt.promptstage` - Prompt Stage +> - `authentik_stages_user_delete.userdeletestage` - User Delete Stage +> - `authentik_stages_user_login.userloginstage` - User Login Stage +> - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage +> - `authentik_stages_user_write.userwritestage` - User Write Stage +> - `authentik_brands.brand` - Brand +> - `authentik_blueprints.blueprintinstance` - Blueprint Instance +> - `authentik_core.group` - Group +> - `authentik_core.user` - User +> - `authentik_core.application` - Application +> - `authentik_core.token` - Token +> - `authentik_enterprise.license` - License +> - `authentik_providers_rac.racprovider` - RAC Provider +> - `authentik_providers_rac.endpoint` - RAC Endpoint +> - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping +> - `authentik_events.event` - Event +> - `authentik_events.notificationtransport` - Notification Transport +> - `authentik_events.notification` - Notification +> - `authentik_events.notificationrule` - Notification Rule +> - `authentik_events.notificationwebhookmapping` - Webhook Mapping + +##### `GET` /rbac/permissions/assigned_by_users/ + +###### Parameters: + +Changed: `model` in `query` + +> - `authentik_tenants.domain` - Domain +> - `authentik_crypto.certificatekeypair` - Certificate-Key Pair +> - `authentik_flows.flow` - Flow +> - `authentik_flows.flowstagebinding` - Flow Stage Binding +> - `authentik_outposts.dockerserviceconnection` - Docker Service-Connection +> - `authentik_outposts.kubernetesserviceconnection` - Kubernetes Service-Connection +> - `authentik_outposts.outpost` - Outpost +> - `authentik_policies_dummy.dummypolicy` - Dummy Policy +> - `authentik_policies_event_matcher.eventmatcherpolicy` - Event Matcher Policy +> - `authentik_policies_expiry.passwordexpirypolicy` - Password Expiry Policy +> - `authentik_policies_expression.expressionpolicy` - Expression Policy +> - `authentik_policies_password.passwordpolicy` - Password Policy +> - `authentik_policies_reputation.reputationpolicy` - Reputation Policy +> - `authentik_policies.policybinding` - Policy Binding +> - `authentik_providers_ldap.ldapprovider` - LDAP Provider +> - `authentik_providers_oauth2.scopemapping` - Scope Mapping +> - `authentik_providers_oauth2.oauth2provider` - OAuth2/OpenID Provider +> - `authentik_providers_proxy.proxyprovider` - Proxy Provider +> - `authentik_providers_radius.radiusprovider` - Radius Provider +> - `authentik_providers_saml.samlprovider` - SAML Provider +> - `authentik_providers_saml.samlpropertymapping` - SAML Property Mapping +> - `authentik_providers_scim.scimprovider` - SCIM Provider +> - `authentik_providers_scim.scimmapping` - SCIM Mapping +> - `authentik_rbac.role` - Role +> - `authentik_sources_ldap.ldapsource` - LDAP Source +> - `authentik_sources_ldap.ldappropertymapping` - LDAP Property Mapping +> - `authentik_sources_oauth.oauthsource` - OAuth Source +> - `authentik_sources_oauth.useroauthsourceconnection` - User OAuth Source Connection +> - `authentik_sources_plex.plexsource` - Plex Source +> - `authentik_sources_plex.plexsourceconnection` - User Plex Source Connection +> - `authentik_sources_saml.samlsource` - SAML Source +> - `authentik_sources_saml.usersamlsourceconnection` - User SAML Source Connection +> - `authentik_stages_authenticator_duo.authenticatorduostage` - Duo Authenticator Setup Stage +> - `authentik_stages_authenticator_duo.duodevice` - Duo Device +> - `authentik_stages_authenticator_sms.authenticatorsmsstage` - SMS Authenticator Setup Stage +> - `authentik_stages_authenticator_sms.smsdevice` - SMS Device +> - `authentik_stages_authenticator_static.authenticatorstaticstage` - Static Authenticator Setup Stage +> - `authentik_stages_authenticator_static.staticdevice` - Static Device +> - `authentik_stages_authenticator_totp.authenticatortotpstage` - TOTP Authenticator Setup Stage +> - `authentik_stages_authenticator_totp.totpdevice` - TOTP Device +> - `authentik_stages_authenticator_validate.authenticatorvalidatestage` - Authenticator Validation Stage +> - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` - WebAuthn Authenticator Setup Stage +> - `authentik_stages_authenticator_webauthn.webauthndevice` - WebAuthn Device +> - `authentik_stages_captcha.captchastage` - Captcha Stage +> - `authentik_stages_consent.consentstage` - Consent Stage +> - `authentik_stages_consent.userconsent` - User Consent +> - `authentik_stages_deny.denystage` - Deny Stage +> - `authentik_stages_dummy.dummystage` - Dummy Stage +> - `authentik_stages_email.emailstage` - Email Stage +> - `authentik_stages_identification.identificationstage` - Identification Stage +> - `authentik_stages_invitation.invitationstage` - Invitation Stage +> - `authentik_stages_invitation.invitation` - Invitation +> - `authentik_stages_password.passwordstage` - Password Stage +> - `authentik_stages_prompt.prompt` - Prompt +> - `authentik_stages_prompt.promptstage` - Prompt Stage +> - `authentik_stages_user_delete.userdeletestage` - User Delete Stage +> - `authentik_stages_user_login.userloginstage` - User Login Stage +> - `authentik_stages_user_logout.userlogoutstage` - User Logout Stage +> - `authentik_stages_user_write.userwritestage` - User Write Stage +> - `authentik_brands.brand` - Brand +> - `authentik_blueprints.blueprintinstance` - Blueprint Instance +> - `authentik_core.group` - Group +> - `authentik_core.user` - User +> - `authentik_core.application` - Application +> - `authentik_core.token` - Token +> - `authentik_enterprise.license` - License +> - `authentik_providers_rac.racprovider` - RAC Provider +> - `authentik_providers_rac.endpoint` - RAC Endpoint +> - `authentik_providers_rac.racpropertymapping` - RAC Property Mapping +> - `authentik_events.event` - Event +> - `authentik_events.notificationtransport` - Notification Transport +> - `authentik_events.notification` - Notification +> - `authentik_events.notificationrule` - Notification Rule +> - `authentik_events.notificationwebhookmapping` - Webhook Mapping + +##### `POST` /sources/ldap/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + New required properties: + + - `connectivity` + + * Added property `connectivity` (object) + > Get cached source connectivity + +##### `GET` /sources/ldap/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > LDAP Source Serializer + + New required properties: + + - `connectivity` + + * Added property `connectivity` (object) + > Get cached source connectivity + +##### `POST` /sources/oauth/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `oidc_jwks` (object -> object) + +- Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `type` (object) + + > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + + - Changed property `oidc_jwks` (object -> object) + + - Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +##### `GET` /sources/oauth/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > OAuth Source Serializer + + - Changed property `type` (object) + + > Serializer for SourceType + + New required properties: + + - `verbose_name` + + New optional properties: + + - `slug` + + * Added property `verbose_name` (string) + + * Deleted property `slug` (string) + + - Changed property `oidc_jwks` (object -> object) + + - Changed property `provider_type` (string) + > - `apple` - Apple + > - `openidconnect` - OpenID Connect + > - `azuread` - Azure AD + > - `discord` - Discord + > - `facebook` - Facebook + > - `github` - GitHub + > - `google` - Google + > - `mailcow` - Mailcow + > - `okta` - Okta + > - `patreon` - Patreon + > - `reddit` - Reddit + > - `twitch` - Twitch + > - `twitter` - Twitter + +##### `GET` /stages/all/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/duo/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/duo/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/duo/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/sms/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/sms/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/sms/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `DELETE` /stages/authenticator/static/{stage_uuid}/ + +###### Parameters: + +Changed: `stage_uuid` in `path` + +> A UUID string identifying this Static Authenticator Setup Stage. + +##### `GET` /stages/authenticator/static/{stage_uuid}/ + +###### Parameters: + +Changed: `stage_uuid` in `path` + +> A UUID string identifying this Static Authenticator Setup Stage. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/static/{stage_uuid}/ + +###### Parameters: + +Changed: `stage_uuid` in `path` + +> A UUID string identifying this Static Authenticator Setup Stage. + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/static/{stage_uuid}/ + +###### Parameters: + +Changed: `stage_uuid` in `path` + +> A UUID string identifying this Static Authenticator Setup Stage. + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/totp/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/totp/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/totp/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/validate/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/validate/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/validate/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/captcha/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/captcha/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/captcha/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/consent/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/consent/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/consent/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/deny/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/deny/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/deny/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/dummy/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/dummy/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/dummy/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/email/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/email/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/email/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/identification/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/identification/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/identification/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/invitation/invitations/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/invitation/invitations/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Invitation Serializer + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `authentication` (string) + + > - `none` - None + > - `require_authenticated` - Require Authenticated + > - `require_unauthenticated` - Require Unauthenticated + > - `require_superuser` - Require Superuser + > - `require_outpost` - Require Outpost + + Added enum value: + + - `require_outpost` + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/invitation/stages/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/invitation/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/invitation/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/password/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/password/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/password/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/prompt/stages/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/prompt/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/prompt/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_delete/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/user_delete/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/user_delete/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_login/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + + Enum values: + + - `no_binding` + - `bind_asn` + - `bind_asn_network` + - `bind_asn_network_ip` + + - Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + + Enum values: + + - `no_binding` + - `bind_continent` + - `bind_continent_country` + - `bind_continent_country_city` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/user_login/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + +- Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + + - Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/user_login/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + +- Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + + - Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_logout/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/user_logout/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/user_logout/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_write/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/user_write/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/user_write/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /core/transactional/applications/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `provider_model` (string) + + > - `authentik_providers_ldap.ldapprovider` - authentik_providers_ldap.ldapprovider + > - `authentik_providers_oauth2.oauth2provider` - authentik_providers_oauth2.oauth2provider + > - `authentik_providers_proxy.proxyprovider` - authentik_providers_proxy.proxyprovider + > - `authentik_providers_rac.racprovider` - authentik_providers_rac.racprovider + > - `authentik_providers_radius.radiusprovider` - authentik_providers_radius.radiusprovider + > - `authentik_providers_saml.samlprovider` - authentik_providers_saml.samlprovider + > - `authentik_providers_scim.scimprovider` - authentik_providers_scim.scimprovider + + Added enum value: + + - `authentik_providers_rac.racprovider` + +- Changed property `provider` (object) + + Added 'authentik_providers_rac.racprovider' provider_model: + + - Property `name` (string) + + - Property `authentication_flow` (string) + + > Flow used for authentication when the associated application is accessed by an un-authenticated user. + + - Property `authorization_flow` (string) + + > Flow used when authorizing this provider. + + - Property `property_mappings` (array) + + Items (string): + + - Property `settings` (object) + + - Property `connection_expiry` (string) + + > Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3) + + - Property `delete_token_on_disconnect` (boolean) + > When set to true, connection tokens will be deleted upon disconnect. + +##### `GET` /core/user_consent/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserConsent Serializer + + - Added property `expiring` (boolean) + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /events/notifications/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Notification Serializer + + - Changed property `event` (object) + + > Event Serializer + + - Added property `brand` (object) + + - Deleted property `tenant` (object) + + - Changed property `user` (object -> object) + + - Changed property `context` (object -> object) + +##### `POST` /flows/bindings/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /flows/bindings/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > FlowStageBinding Serializer + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /flows/inspector/{flow_slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `plans` (array) + + Changed items (object): > Serializer for an active FlowPlan + + - Changed property `current_stage` (object) + + > FlowStageBinding Serializer + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /oauth2/access_tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and RefreshToken + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /oauth2/authorization_codes/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and ExpiringBaseGrant + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /oauth2/refresh_tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and RefreshToken + + - Changed property `user` (object) + + > User Serializer + + - Changed property `avatar` (string) + > User's avatar, either a http/https URL or a data URI + +##### `GET` /stages/all/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/duo/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/duo/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorDuoStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/sms/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/sms/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorSMSStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/static/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/static/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorStaticStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/totp/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/totp/ + +###### Parameters: + +Changed: `digits` in `query` + +> - `6` - 6 digits, widely compatible +> - `8` - 8 digits, not compatible with apps like Google Authenticator + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorTOTPStage Serializer + + - Changed property `digits` (integer -> string) + + > - `6` - 6 digits, widely compatible + > - `8` - 8 digits, not compatible with apps like Google Authenticator + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/validate/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/validate/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorValidateStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/authenticator/webauthn/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/authenticator/webauthn/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticateWebAuthnStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/captcha/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/captcha/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > CaptchaStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/consent/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/consent/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > ConsentStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/deny/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/deny/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > DenyStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/dummy/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/dummy/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > DummyStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/email/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/email/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > EmailStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/identification/ + +###### Request: + +Changed content type : `application/json` + +- Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/identification/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > IdentificationStage Serializer + + - Added property `pretend_user_exists` (boolean) + + > When enabled, the stage will succeed and continue even when incorrect user info is entered. + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/invitation/stages/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/invitation/stages/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > InvitationStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/password/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/password/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PasswordStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/prompt/prompts/{prompt_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PUT` /stages/prompt/prompts/{prompt_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `PATCH` /stages/prompt/prompts/{prompt_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/prompt/prompts/preview/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/prompt/stages/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/prompt/stages/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PromptStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/user_delete/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_delete/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserDeleteStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/user_login/ + +###### Request: + +Changed content type : `application/json` + +- Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + +- Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + + - Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_login/ + +###### Parameters: + +Added: `geoip_binding` in `query` + +> Bind sessions created by this stage to the configured GeoIP location +> +> - `no_binding` - No Binding +> - `bind_continent` - Bind Continent +> - `bind_continent_country` - Bind Continent Country +> - `bind_continent_country_city` - Bind Continent Country City + +Added: `network_binding` in `query` + +> Bind sessions created by this stage to the configured network +> +> - `no_binding` - No Binding +> - `bind_asn` - Bind Asn +> - `bind_asn_network` - Bind Asn Network +> - `bind_asn_network_ip` - Bind Asn Network Ip + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserLoginStage Serializer + + - Added property `network_binding` (object) + + > Bind sessions created by this stage to the configured network + > + > - `no_binding` - No Binding + > - `bind_asn` - Bind Asn + > - `bind_asn_network` - Bind Asn Network + > - `bind_asn_network_ip` - Bind Asn Network Ip + + - Added property `geoip_binding` (object) + + > Bind sessions created by this stage to the configured GeoIP location + > + > - `no_binding` - No Binding + > - `bind_continent` - Bind Continent + > - `bind_continent_country` - Bind Continent Country + > - `bind_continent_country_city` - Bind Continent Country City + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/user_logout/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_logout/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserLogoutStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/user_write/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/user_write/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserWriteStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `POST` /stages/prompt/prompts/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right + +##### `GET` /stages/prompt/prompts/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Prompt Serializer + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `layout` (string) + > - `stacked` - Stacked + > - `content_left` - Content Left + > - `content_right` - Content Right + > - `sidebar_left` - Sidebar Left + > - `sidebar_right` - Sidebar Right diff --git a/website/docs/releases/2024/v2024.4.md b/website/docs/releases/2024/v2024.4.md new file mode 100644 index 0000000000..3139f9ba9d --- /dev/null +++ b/website/docs/releases/2024/v2024.4.md @@ -0,0 +1,10699 @@ +--- +title: Release 2024.4 +slug: /releases/2024.4 +--- + +## Highlights + +- **OAuth/SAML as authentication factor** Enterprise Use an external provider as part of an MFA authentication flow, including custom implementations + +- **SCIM Source** Preview Provision users and groups in authentik using an SCIM API + +- **Configurable WebAuthn device restrictions** Configure which types of WebAuthn devices can be used to enroll and validate for different authorization levels. + +- **Performance improvements** The API Endpoints to list Users, Groups, and Events have been optimized by 94%, 41% and 53% respectively + +## Breaking changes + +### Manual action may be required + +- **Configuration options migrated to the Admin interface** + + The following config options have been moved from the config file and can now be set using the Admin interface (under **System** -> **Settings**) or the API: + + - `AUTHENTIK_DEFAULT_TOKEN_LENGTH` + + When upgrading to 2024.4, the currently configured options will be automatically migrated to the database, and can be removed from the `.env` or helm values file afterwards. + +## New features + +- **Source stage** Enterprise + + The source stage allows for an inclusion of a source as part of a flow. This can be used to link a user to a source as part of their authentication/enrollment, or it can be used as an external multi-factor to provide device health attestation for example. + + For details refer to [Source stage](../../flow/stages/source/index.md) + +- **SCIM Source** Preview + + Provision users and groups in authentik using an SCIM API. + + For details refer to [SCIM Source](../../../docs/sources/scim/) + +- **Configurable WebAuthn device restrictions** + + Configure which types of WebAuthn devices can be used to enroll and validate for different authorization levels. + + For details refer to [WebAuthn authenticator setup stage](../../flow/stages/authenticator_webauthn/index.md) + +- **Revamped UI for log messages** + + Log messages from several API endpoints are now shown with much greater detail, which helps with implementing custom policies and property mappings. + +- **Python API Client** + + There's now an official API Client for Python: https://pypi.org/project/authentik-client/. This API Client can be used to create/update/delete objects within authentik as well as using the Flow executor to authenticate. + +- **Configure LDAP sources to not store hashed password in authentik** + + When authentik is configured to federate with an LDAP source, upon authentication, authentik hashed the password and stored it in its own database. This allows authentication to function when LDAP is unreachable. Admins can now configure this behavior for when this is not desirable. + + For details refer to [LDAP Source](../../../docs/sources/ldap/) + +- **Configurable app password token expiring** + + Thanks @jmdilly for contributing this feature! + + Admins can now configure the default token duration (which defaults to `minutes=30`) in the admin interface as specified above. This value can also be overridden per-user with the `goauthentik.io/user/token-maximum-lifetime` attribute. + +## Upgrading + +This release does not introduce any new requirements. + +### docker-compose + +To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: + +```shell +wget -O docker-compose.yml https://goauthentik.io/version/2024.4/docker-compose.yml +docker compose up -d +``` + +The `-O` flag retains the downloaded file's name, overwriting any existing local file with the same name. + +### Kubernetes + +Upgrade the Helm Chart to the new version, using the following commands: + +```shell +helm repo update +helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.4 +``` + +## Minor changes/fixes + +- admin: Handle latest version unknown in admin dashboard (#8858) +- api: capabilities: properly set can_save_media when s3 is enabled (#8896) +- api: fix authentication schema (#9238) +- blueprints: fix default username field in user-settings flow (#9136) +- blueprints: fix schema generation for PrimaryKeyRelated fields with non-int PK (#9140) +- blueprints: only create default brand if no other default brand exists (#9222) +- blueprints: use reconcile decorator instead of relying on function name prefix (#8483) +- brands: add indexes to brand domain and default (#9343) +- brands: fix context processor when request doesn't have a tenant (#8643) +- core: add user settable token durations (#7410) +- core: cache user application list under policies (#8895) +- core: delegated group member management (#9254) +- core: fix api schema for users and groups (#9298) +- core: fix blueprint export (#8695) +- core: optionally don't return groups' users and users' groups by default (#9179) +- core: replace authentik_signals_ignored_fields with audit_ignore (#9291) +- core: rework recovery API to return better error messages (#8655) +- enterprise/rac: fix connection token management (#8909) +- enterprise: fix audit middleware import (#9177) +- enterprise: fix read_only activating when no license is installed (#8697) +- enterprise: force license usage update after change to license (#8723) +- enterprise: only check for valid license existing for creating Enterprise objects (#8813) +- enterprise: use tenant uuid instead of install_id when tenants are enabled (#8823) +- events: add context manager to ignore/modify audit events being written (#9181) +- events: add indexes (#9272) +- events: discard notification if user has empty email (#8938) +- events: fix incorrect user logged when using API token authentication (#9302) +- events: fix log_capture (#9075) +- events: rework log messages returned from API and their rendering (#8770) +- events: sanitize args and kwargs saved in system tasks (#8644) +- flows: fix mismatched redirect behaviour for invalid and valid flows (#8794) +- internal: add tests to go flow executor (#9219) +- internal: cleanup static file serving setup code (#8965) +- lib: cache gravatar connection status (#9248) +- lifecycle: gunicorn: fix app preload (#9274) +- lifecycle: migrate: ensure template schema exists before migrating (#8952) +- outposts: improved set secret answers for flow execution (#8013) +- outposts/proxy: Fix invalid redirect on external hosts containing path components (#8915) +- outposts: Enhance config options for k8s outposts (#7363) +- providers/oauth2: fix inconsistent `sub` value when setting via mapping (#8677) +- providers/oauth2: fix interactive device flow (#9076) +- providers/oauth2: fix offline_access requests when prompt doesn't include consent (#8731) +- providers/oauth2: fix refresh_token grant returning incorrect id_token (#9275) +- providers/oauth2: fix validation ordering (#8793) +- providers/oauth2: improve conformance with client_credentials standard (#8471) +- providers/scim: allow custom user and group schemas (#9255) +- rbac: fix permission decorator for global permissions (#8591) +- root: cherry-pick version bump +- root: early spring clean for linting (#8498) +- root: ensure consistent install_id (#8775) +- root: expose session storage configuration (#9337) +- root: fix app settings load order (#8569) +- root: generate python client (#9107) +- root: make redis settings more consistent (#9335) +- root: move database calls from ready() to dedicated startup signal (#9081) +- root: support redis username (#8935) +- sources/ldap: add ability to disable password write on login (#8377) +- sources/ldap: fix default blueprint for mapping user DN to path (#9355) +- sources/oauth: add gitlab type [AUTH-323] (#8195) +- sources/oauth: make URLs not required, only check when no OIDC URLs are defined (#9182) +- sources/scim: cleanup service account when source is deleted (#9319) +- sources/scim: service account should be internal (#9321) +- sources: add SCIM source (#3051) +- stages/authenticator_validate: add ability to limit webauthn device types (#9180) +- stages/authenticator_validate: fix error with get_webauthn_challenge_without_user (#8625) +- stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#9268) +- stages/authenticator_webauthn: add MDS support (#9114) +- stages/authenticator_webauthn: fix attestation value (#9333) +- stages/authenticator_webauthn: fix error when enrolling new device (#8738) +- stages/email: Disable autoescape for text templates (#8812) +- stages/email: fix issue when sending emails to users with same display as email (#8850) +- stages/prompt: fix username field throwing error with existing user (#9342) +- stages/user_write: ensure user data is json-serializable (#8926) +- stages: source stage (#8330) +- tenants: really ensure default tenant cannot be deleted (#8875) +- web/admin: allow custom sorting for bound\* tables (#9080) +- web/admin: don't mark LDAP group property mappings as required (#8772) +- web/admin: don't mark property mappings as required anywhere (#8752) +- web/admin: fix SAML Provider preview (#9192) +- web/admin: fix document title for admin interface (#9362) +- web/admin: fix error in admin interface due to un-hydrated context (#9336) +- web/admin: fix log viewer empty state (#9315) +- web/admin: fix markdown table rendering (#8908) +- web/admin: fix user_write stage's user type input (#9344) +- web/admin: group form dual select (#9354) +- web/admin: remove enterprise preview banner (#8991) +- web/admin: rework captcha stage (#9256) +- web/admin: small fixes (#9002) +- web/flows: fix form input rendering issue (#9297) +- web/flows: general ux improvements (#8558) +- web/flows: fix passwordless hidden without input (#9273) +- web/flows: fix webauthn retry (#8599) +- web/flows: improve authenticator styling (#8560) +- web/flows: update flow background (#9305) +- web: a few minor bugfixes and lintfixes (#9044) +- web: ak-checkbox-group for short, static, multi-select events (#9138) +- web: change "delete" verb to "remove" for one-to-many relationships (#8535) +- web: clean up UserInterface in prep for OAuth and Silo Projects (#8278) +- web: clean up and remove redundant alias '@goauthentik/app' (#8889) +- web: consistent style declarations internally (#9077) +- web: fix save & reset behavior on System ➲ Settings page. (#8528) +- web: improve build speeds even moar!!!!!! (#8954) +- web: maintenance: split tsconfig into “base” and “build” variants. (#9036) +- web: manage stacked modals with a stack (#9193) +- web: move context controllers into reactive controller plugins (#8996) +- web: preserve selected list when provider updates (#9200) +- web: provide InstallID on EnterpriseListPage (#8898) +- web: replace rollup with esbuild (#8699) +- web: restore sourcemaps (#9300) +- web: spell customization with a Z (#8596) +- web: upgrade to lit 3 (#8781) + +## Fixed in 2024.4.1 + +- core: fix logic for token expiration (cherry-pick #9426) (#9428) +- lifecycle: always try custom redis URL (cherry-pick #9441) (#9458) +- sources/oauth: ensure all UI sources return a valid source (cherry-pick #9401) (#9406) +- sources/scim: fix service account user path (cherry-pick #9463) (#9470) +- stages/identification: don't check source component (cherry-pick #9410) (#9420) +- web/admin: fix disabled button color with dark theme (cherry-pick #9465) (#9468) +- web/admin: show user internal service account as disabled (cherry-pick #9464) (#9467) +- web/common: fix locale detection for user-set locale (cherry-pick #9436) (#9439) +- web: Add resolved and integrity fields back to package-lock.json (cherry-pick #9419) (#9421) +- web: markdown: display markdown even when frontmatter is missing (cherry-pick #9404) (#9405) + +## Fixed in 2024.4.2 + +- core: fix source_flow_manager saving user-source connection too early (cherry-pick #9559) (#9578) +- core: fix task clean_expiring_models removing valid sessions with using database storage (cherry-pick #9598) (#9601) +- core: only prefetch related objects when required (cherry-pick #9476) (#9510) +- enterprise/audit: fix audit logging with m2m relations (cherry-pick #9571) (#9572) +- events: ensure all models' `__str__` can be called without any further lookups (cherry-pick #9480) (#9485) +- flows: fix execute API endpoint (cherry-pick #9478) (#9481) +- lifecycle: close database connection after migrating (cherry-pick #9516) (#9531) +- providers/saml: fix ECDSA support (cherry-pick #9537) (#9544) +- providers/scim: fix SCIM ID incorrectly used as primary key (cherry-pick #9557) (#9579) +- providers/scim: fix Sync task's time_limit not set correctly (cherry-pick #9546) (#9553) +- sources/oauth: fix OAuth2 Client sending token request incorrectly (cherry-pick #9474) (#9475) +- sources/scim: fix duplicate groups and invalid schema (cherry-pick #9466) (#9606) +- tenants: fix scheduled tasks not running on default tenant (cherry-pick #9583) (#9586) +- web/flows: fix error when enrolling multiple WebAuthn devices consecutively (cherry-pick #9545) (#9547) +- web/flows: fix missing fallback for flow logo (cherry-pick #9487) (#9492) +- web: Add missing integrity hashes to package-lock.json (#9527) + +## API Changes + +#### What's New + +--- + +##### `GET` /sources/scim/ + +##### `POST` /sources/scim/ + +##### `GET` /sources/scim/{slug}/ + +##### `PUT` /sources/scim/{slug}/ + +##### `DELETE` /sources/scim/{slug}/ + +##### `PATCH` /sources/scim/{slug}/ + +##### `GET` /sources/scim/{slug}/used_by/ + +##### `GET` /sources/scim_groups/ + +##### `POST` /sources/scim_groups/ + +##### `GET` /sources/scim_groups/{id}/ + +##### `PUT` /sources/scim_groups/{id}/ + +##### `DELETE` /sources/scim_groups/{id}/ + +##### `PATCH` /sources/scim_groups/{id}/ + +##### `GET` /sources/scim_groups/{id}/used_by/ + +##### `GET` /sources/scim_users/ + +##### `POST` /sources/scim_users/ + +##### `GET` /sources/scim_users/{id}/ + +##### `PUT` /sources/scim_users/{id}/ + +##### `DELETE` /sources/scim_users/{id}/ + +##### `PATCH` /sources/scim_users/{id}/ + +##### `GET` /sources/scim_users/{id}/used_by/ + +##### `GET` /stages/authenticator/webauthn_device_types/ + +##### `GET` /stages/authenticator/webauthn_device_types/{aaguid}/ + +##### `GET` /stages/source/ + +##### `POST` /stages/source/ + +##### `GET` /stages/source/{stage_uuid}/ + +##### `PUT` /stages/source/{stage_uuid}/ + +##### `DELETE` /stages/source/{stage_uuid}/ + +##### `PATCH` /stages/source/{stage_uuid}/ + +##### `GET` /stages/source/{stage_uuid}/used_by/ + +##### `POST` /core/users/{id}/recovery/ + +##### `POST` /core/users/{id}/recovery_email/ + +#### What's Deleted + +--- + +##### `GET` /core/users/{id}/recovery/ + +##### `GET` /core/users/{id}/recovery_email/ + +#### What's Changed + +--- + +##### `GET` /admin/apps/ + +##### `GET` /admin/models/ + +##### `GET` /admin/settings/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `default_token_duration` (string) + + > Default token duration + + - Added property `default_token_length` (integer) + > Default token length + +##### `PUT` /admin/settings/ + +###### Request: + +Changed content type : `application/json` + +- Added property `default_token_duration` (string) + + > Default token duration + +- Added property `default_token_length` (integer) + > Default token length + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `default_token_duration` (string) + + > Default token duration + + - Added property `default_token_length` (integer) + > Default token length + +##### `PATCH` /admin/settings/ + +###### Request: + +Changed content type : `application/json` + +- Added property `default_token_duration` (string) + + > Default token duration + +- Added property `default_token_length` (integer) + > Default token length + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `default_token_duration` (string) + + > Default token duration + + - Added property `default_token_length` (integer) + > Default token length + +##### `GET` /admin/system/ + +##### `POST` /admin/system/ + +##### `GET` /admin/version/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `version_latest_valid` + + * Added property `version_latest_valid` (boolean) + > Check if latest version is valid + +##### `GET` /admin/workers/ + +##### `GET` /authenticators/admin/all/ + +##### `GET` /authenticators/admin/duo/{id}/ + +##### `PUT` /authenticators/admin/duo/{id}/ + +##### `DELETE` /authenticators/admin/duo/{id}/ + +##### `PATCH` /authenticators/admin/duo/{id}/ + +##### `GET` /authenticators/admin/sms/{id}/ + +##### `PUT` /authenticators/admin/sms/{id}/ + +##### `DELETE` /authenticators/admin/sms/{id}/ + +##### `PATCH` /authenticators/admin/sms/{id}/ + +##### `GET` /authenticators/admin/totp/{id}/ + +##### `PUT` /authenticators/admin/totp/{id}/ + +##### `DELETE` /authenticators/admin/totp/{id}/ + +##### `PATCH` /authenticators/admin/totp/{id}/ + +##### `GET` /authenticators/admin/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + - Property `aaguid` (string) + + - Property `description` (string) + + * Added property `aaguid` (string) + +##### `PUT` /authenticators/admin/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `DELETE` /authenticators/admin/webauthn/{id}/ + +##### `PATCH` /authenticators/admin/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `GET` /authenticators/all/ + +##### `GET` /authenticators/duo/{id}/ + +##### `PUT` /authenticators/duo/{id}/ + +##### `DELETE` /authenticators/duo/{id}/ + +##### `PATCH` /authenticators/duo/{id}/ + +##### `GET` /authenticators/sms/{id}/ + +##### `PUT` /authenticators/sms/{id}/ + +##### `DELETE` /authenticators/sms/{id}/ + +##### `PATCH` /authenticators/sms/{id}/ + +##### `GET` /authenticators/totp/{id}/ + +##### `PUT` /authenticators/totp/{id}/ + +##### `DELETE` /authenticators/totp/{id}/ + +##### `PATCH` /authenticators/totp/{id}/ + +##### `GET` /authenticators/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `PUT` /authenticators/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `DELETE` /authenticators/webauthn/{id}/ + +##### `PATCH` /authenticators/webauthn/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `GET` /core/applications/{slug}/check_access/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `log_messages` (array) + + Changed items (object): > Single log message with all context logged. + + New required properties: + + - `attributes` + - `event` + - `log_level` + - `logger` + - `timestamp` + + * Added property `timestamp` (string) + + * Added property `log_level` (string) + + Enum values: + + - `critical` + - `exception` + - `error` + - `warn` + - `warning` + - `info` + - `debug` + - `notset` + + * Added property `logger` (string) + + * Added property `event` (string) + + * Added property `attributes` (object) + +##### `GET` /core/applications/{slug}/metrics/ + +##### `POST` /core/applications/{slug}/set_icon/ + +##### `POST` /core/applications/{slug}/set_icon_url/ + +##### `GET` /core/authenticated_sessions/{uuid}/ + +##### `DELETE` /core/authenticated_sessions/{uuid}/ + +##### `GET` /core/brands/{brand_uuid}/ + +##### `PUT` /core/brands/{brand_uuid}/ + +##### `DELETE` /core/brands/{brand_uuid}/ + +##### `PATCH` /core/brands/{brand_uuid}/ + +##### `POST` /core/groups/{group_uuid}/add_user/ + +##### `POST` /core/groups/{group_uuid}/remove_user/ + +##### `POST` /core/tokens/{identifier}/set_key/ + +##### `GET` /core/tokens/{identifier}/view_key/ + +##### `POST` /core/users/{id}/impersonate/ + +##### `POST` /core/users/{id}/set_password/ + +##### `GET` /core/users/impersonate_end/ + +##### `GET` /core/users/paths/ + +##### `POST` /core/users/service_account/ + +##### `GET` /crypto/certificatekeypairs/{kp_uuid}/ + +##### `PUT` /crypto/certificatekeypairs/{kp_uuid}/ + +##### `DELETE` /crypto/certificatekeypairs/{kp_uuid}/ + +##### `PATCH` /crypto/certificatekeypairs/{kp_uuid}/ + +##### `GET` /crypto/certificatekeypairs/{kp_uuid}/view_certificate/ + +##### `GET` /crypto/certificatekeypairs/{kp_uuid}/view_private_key/ + +##### `POST` /crypto/certificatekeypairs/generate/ + +##### `GET` /enterprise/license/{license_uuid}/ + +##### `PUT` /enterprise/license/{license_uuid}/ + +##### `DELETE` /enterprise/license/{license_uuid}/ + +##### `PATCH` /enterprise/license/{license_uuid}/ + +##### `GET` /enterprise/license/forecast/ + +##### `GET` /enterprise/license/get_install_id/ + +##### `GET` /enterprise/license/summary/ + +##### `GET` /events/events/actions/ + +##### `GET` /events/events/per_month/ + +##### `GET` /events/events/top_per_user/ + +##### `GET` /events/events/volume/ + +##### `POST` /events/notifications/mark_all_seen/ + +##### `POST` /events/system_tasks/{uuid}/run/ + +##### `POST` /events/transports/{uuid}/test/ + +##### `GET` /flows/instances/{slug}/diagram/ + +##### `GET` /flows/instances/{slug}/execute/ + +##### `GET` /flows/instances/{slug}/export/ + +##### `POST` /flows/instances/{slug}/set_background/ + +##### `POST` /flows/instances/{slug}/set_background_url/ + +##### `POST` /flows/instances/cache_clear/ + +##### `GET` /flows/instances/cache_info/ + +##### `POST` /flows/instances/import/ + +###### Return Type: + +Changed response : **204 No Content** + +- Changed content type : `application/json` + + - Changed property `logs` (array) + + Changed items (object): > Single log message with all context logged. + + New required properties: + + - `attributes` + - `event` + - `log_level` + - `logger` + - `timestamp` + + * Added property `timestamp` (string) + + * Added property `log_level` (string) + + * Added property `logger` (string) + + * Added property `event` (string) + + * Added property `attributes` (object) + +Changed response : **400 Bad Request** + +- Changed content type : `application/json` + + - Changed property `logs` (array) + + Changed items (object): > Single log message with all context logged. + + New required properties: + + - `attributes` + - `event` + - `log_level` + - `logger` + - `timestamp` + + * Added property `timestamp` (string) + + * Added property `log_level` (string) + + * Added property `logger` (string) + + * Added property `event` (string) + + * Added property `attributes` (object) + +##### `GET` /managed/blueprints/{instance_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `status` (string) + +##### `PUT` /managed/blueprints/{instance_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `status` (string) + +##### `DELETE` /managed/blueprints/{instance_uuid}/ + +##### `PATCH` /managed/blueprints/{instance_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `status` (string) + +##### `POST` /managed/blueprints/{instance_uuid}/apply/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `status` (string) + +##### `GET` /managed/blueprints/available/ + +##### `GET` /outposts/instances/{uuid}/health/ + +##### `GET` /outposts/instances/default_settings/ + +##### `GET` /outposts/proxy/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `GET` /outposts/radius/{id}/ + +##### `GET` /outposts/service_connections/all/{uuid}/ + +##### `DELETE` /outposts/service_connections/all/{uuid}/ + +##### `GET` /outposts/service_connections/all/{uuid}/state/ + +##### `GET` /outposts/service_connections/all/types/ + +##### `GET` /outposts/service_connections/docker/{uuid}/ + +##### `PUT` /outposts/service_connections/docker/{uuid}/ + +##### `DELETE` /outposts/service_connections/docker/{uuid}/ + +##### `PATCH` /outposts/service_connections/docker/{uuid}/ + +##### `GET` /outposts/service_connections/kubernetes/{uuid}/ + +##### `PUT` /outposts/service_connections/kubernetes/{uuid}/ + +##### `DELETE` /outposts/service_connections/kubernetes/{uuid}/ + +##### `PATCH` /outposts/service_connections/kubernetes/{uuid}/ + +##### `GET` /policies/all/{policy_uuid}/ + +##### `DELETE` /policies/all/{policy_uuid}/ + +##### `POST` /policies/all/{policy_uuid}/test/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `log_messages` (array) + + Changed items (object): > Single log message with all context logged. + + New required properties: + + - `attributes` + - `event` + - `log_level` + - `logger` + - `timestamp` + + * Added property `timestamp` (string) + + * Added property `log_level` (string) + + * Added property `logger` (string) + + * Added property `event` (string) + + * Added property `attributes` (object) + +##### `POST` /policies/all/cache_clear/ + +##### `GET` /policies/all/cache_info/ + +##### `GET` /policies/all/types/ + +##### `GET` /policies/dummy/{policy_uuid}/ + +##### `PUT` /policies/dummy/{policy_uuid}/ + +##### `DELETE` /policies/dummy/{policy_uuid}/ + +##### `PATCH` /policies/dummy/{policy_uuid}/ + +##### `GET` /policies/event_matcher/{policy_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + + - Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + + - Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `PUT` /policies/event_matcher/{policy_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + +- Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + +- Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + + - Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + + - Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `DELETE` /policies/event_matcher/{policy_uuid}/ + +##### `PATCH` /policies/event_matcher/{policy_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + +- Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + +- Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + + - Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + + - Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `GET` /policies/expression/{policy_uuid}/ + +##### `PUT` /policies/expression/{policy_uuid}/ + +##### `DELETE` /policies/expression/{policy_uuid}/ + +##### `PATCH` /policies/expression/{policy_uuid}/ + +##### `GET` /policies/password/{policy_uuid}/ + +##### `PUT` /policies/password/{policy_uuid}/ + +##### `DELETE` /policies/password/{policy_uuid}/ + +##### `PATCH` /policies/password/{policy_uuid}/ + +##### `GET` /policies/password_expiry/{policy_uuid}/ + +##### `PUT` /policies/password_expiry/{policy_uuid}/ + +##### `DELETE` /policies/password_expiry/{policy_uuid}/ + +##### `PATCH` /policies/password_expiry/{policy_uuid}/ + +##### `GET` /policies/reputation/{policy_uuid}/ + +##### `PUT` /policies/reputation/{policy_uuid}/ + +##### `DELETE` /policies/reputation/{policy_uuid}/ + +##### `PATCH` /policies/reputation/{policy_uuid}/ + +##### `GET` /policies/reputation/scores/{reputation_uuid}/ + +##### `DELETE` /policies/reputation/scores/{reputation_uuid}/ + +##### `GET` /propertymappings/all/{pm_uuid}/ + +##### `DELETE` /propertymappings/all/{pm_uuid}/ + +##### `POST` /propertymappings/all/{pm_uuid}/test/ + +##### `GET` /propertymappings/all/types/ + +##### `GET` /propertymappings/ldap/{pm_uuid}/ + +##### `PUT` /propertymappings/ldap/{pm_uuid}/ + +##### `DELETE` /propertymappings/ldap/{pm_uuid}/ + +##### `PATCH` /propertymappings/ldap/{pm_uuid}/ + +##### `GET` /propertymappings/notification/{pm_uuid}/ + +##### `PUT` /propertymappings/notification/{pm_uuid}/ + +##### `DELETE` /propertymappings/notification/{pm_uuid}/ + +##### `PATCH` /propertymappings/notification/{pm_uuid}/ + +##### `GET` /propertymappings/rac/{pm_uuid}/ + +##### `PUT` /propertymappings/rac/{pm_uuid}/ + +##### `DELETE` /propertymappings/rac/{pm_uuid}/ + +##### `PATCH` /propertymappings/rac/{pm_uuid}/ + +##### `GET` /propertymappings/saml/{pm_uuid}/ + +##### `PUT` /propertymappings/saml/{pm_uuid}/ + +##### `DELETE` /propertymappings/saml/{pm_uuid}/ + +##### `PATCH` /propertymappings/saml/{pm_uuid}/ + +##### `GET` /propertymappings/scim/{pm_uuid}/ + +##### `PUT` /propertymappings/scim/{pm_uuid}/ + +##### `DELETE` /propertymappings/scim/{pm_uuid}/ + +##### `PATCH` /propertymappings/scim/{pm_uuid}/ + +##### `GET` /propertymappings/scope/{pm_uuid}/ + +##### `PUT` /propertymappings/scope/{pm_uuid}/ + +##### `DELETE` /propertymappings/scope/{pm_uuid}/ + +##### `PATCH` /propertymappings/scope/{pm_uuid}/ + +##### `GET` /providers/all/{id}/ + +##### `DELETE` /providers/all/{id}/ + +##### `GET` /providers/all/types/ + +##### `GET` /providers/oauth2/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +##### `PUT` /providers/oauth2/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + +- Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + +- Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +##### `DELETE` /providers/oauth2/{id}/ + +##### `PATCH` /providers/oauth2/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + +- Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + +- Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +##### `GET` /providers/oauth2/{id}/preview_user/ + +##### `GET` /providers/oauth2/{id}/setup_urls/ + +##### `GET` /providers/proxy/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `PUT` /providers/proxy/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `DELETE` /providers/proxy/{id}/ + +##### `PATCH` /providers/proxy/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `GET` /providers/rac/{id}/ + +##### `PUT` /providers/rac/{id}/ + +##### `DELETE` /providers/rac/{id}/ + +##### `PATCH` /providers/rac/{id}/ + +##### `GET` /providers/radius/{id}/ + +##### `PUT` /providers/radius/{id}/ + +##### `DELETE` /providers/radius/{id}/ + +##### `PATCH` /providers/radius/{id}/ + +##### `GET` /providers/saml/{id}/metadata/ + +##### `GET` /providers/saml/{id}/preview_user/ + +##### `POST` /providers/saml/import_metadata/ + +##### `GET` /providers/scim/{id}/ + +##### `PUT` /providers/scim/{id}/ + +##### `DELETE` /providers/scim/{id}/ + +##### `PATCH` /providers/scim/{id}/ + +##### `GET` /rbac/permissions/{id}/ + +##### `GET` /rbac/roles/{uuid}/ + +##### `PUT` /rbac/roles/{uuid}/ + +##### `DELETE` /rbac/roles/{uuid}/ + +##### `PATCH` /rbac/roles/{uuid}/ + +##### `GET` /schema/ + +##### `POST` /sources/all/{slug}/set_icon/ + +##### `POST` /sources/all/{slug}/set_icon_url/ + +##### `GET` /sources/all/types/ + +##### `GET` /sources/all/user_settings/ + +##### `GET` /sources/ldap/{slug}/debug/ + +##### `GET` /sources/oauth/source_types/ + +##### `POST` /sources/plex/redeem_token_authenticated/ + +##### `GET` /sources/saml/{slug}/metadata/ + +##### `GET` /stages/all/types/ + +##### `GET` /stages/all/user_settings/ + +##### `POST` /stages/authenticator/duo/{stage_uuid}/import_device_manual/ + +##### `POST` /stages/authenticator/duo/{stage_uuid}/import_devices_automatic/ + +##### `GET` /stages/email/templates/ + +##### `GET` /admin/metrics/ + +##### `POST` /authenticators/admin/duo/ + +##### `GET` /authenticators/admin/duo/ + +##### `POST` /authenticators/admin/sms/ + +##### `GET` /authenticators/admin/sms/ + +##### `DELETE` /authenticators/admin/static/{id}/ + +##### `GET` /authenticators/admin/static/{id}/ + +##### `PUT` /authenticators/admin/static/{id}/ + +##### `PATCH` /authenticators/admin/static/{id}/ + +##### `POST` /authenticators/admin/totp/ + +##### `GET` /authenticators/admin/totp/ + +##### `POST` /authenticators/admin/webauthn/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `GET` /authenticators/admin/webauthn/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for WebAuthn authenticator devices + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `GET` /authenticators/duo/ + +##### `GET` /authenticators/duo/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /authenticators/sms/ + +##### `GET` /authenticators/sms/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /authenticators/static/{id}/ + +##### `GET` /authenticators/static/{id}/ + +##### `PUT` /authenticators/static/{id}/ + +##### `PATCH` /authenticators/static/{id}/ + +##### `GET` /authenticators/static/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /authenticators/totp/ + +##### `GET` /authenticators/totp/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /authenticators/webauthn/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for WebAuthn authenticator devices + + New required properties: + + - `aaguid` + - `device_type` + + * Added property `device_type` (object) + + * Added property `aaguid` (string) + +##### `GET` /authenticators/webauthn/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /core/applications/{slug}/ + +##### `GET` /core/applications/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /core/applications/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /core/applications/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `policy_engine_mode` (string) + +##### `GET` /core/applications/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /core/authenticated_sessions/ + +##### `GET` /core/authenticated_sessions/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /core/brands/ + +##### `GET` /core/brands/ + +##### `GET` /core/brands/{brand_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /core/brands/current/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `ui_theme` (string) + +##### `DELETE` /core/groups/{group_uuid}/ + +##### `GET` /core/groups/{group_uuid}/ + +##### `PUT` /core/groups/{group_uuid}/ + +##### `PATCH` /core/groups/{group_uuid}/ + +##### `GET` /core/groups/{group_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /core/tokens/{identifier}/ + +##### `GET` /core/tokens/{identifier}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `intent` (string) + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `PUT` /core/tokens/{identifier}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `intent` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `intent` (string) + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `PATCH` /core/tokens/{identifier}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `intent` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `intent` (string) + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /core/tokens/{identifier}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /core/user_consent/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /core/users/{id}/ + +##### `GET` /core/users/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `PUT` /core/users/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `PATCH` /core/users/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `GET` /core/users/{id}/metrics/ + +##### `GET` /core/users/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /crypto/certificatekeypairs/ + +##### `GET` /crypto/certificatekeypairs/ + +##### `GET` /crypto/certificatekeypairs/{kp_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /enterprise/license/ + +##### `GET` /enterprise/license/ + +##### `GET` /enterprise/license/{license_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /events/events/{event_uuid}/ + +##### `GET` /events/events/{event_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + +##### `PUT` /events/events/{event_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + +##### `PATCH` /events/events/{event_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `action` (string) + +##### `GET` /events/notifications/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /events/rules/{pbm_uuid}/ + +##### `GET` /events/rules/{pbm_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +##### `PUT` /events/rules/{pbm_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +##### `PATCH` /events/rules/{pbm_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +##### `GET` /events/rules/{pbm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /events/system_tasks/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `messages` (array) + + Changed items (string -> object): > Single log message with all context logged. + + - Changed property `status` (string) + +##### `DELETE` /events/transports/{uuid}/ + +##### `GET` /events/transports/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + +##### `PUT` /events/transports/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + +##### `PATCH` /events/transports/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + +##### `GET` /events/transports/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /flows/bindings/{fsb_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /flows/instances/{slug}/ + +##### `GET` /flows/instances/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /flows/instances/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + +- Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + +- Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + +- Changed property `policy_engine_mode` (string) + +- Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /flows/instances/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + +- Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + +- Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + +- Changed property `policy_engine_mode` (string) + +- Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /flows/instances/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /managed/blueprints/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `status` (string) + +##### `GET` /managed/blueprints/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Info about a single blueprint instance file + + - Changed property `status` (string) + +##### `GET` /managed/blueprints/{instance_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /oauth2/access_tokens/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /oauth2/authorization_codes/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /oauth2/refresh_tokens/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /outposts/instances/{uuid}/ + +##### `GET` /outposts/instances/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `PUT` /outposts/instances/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `PATCH` /outposts/instances/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `GET` /outposts/instances/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /outposts/ldap/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `search_mode` (string) + +##### `GET` /outposts/proxy/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Proxy provider serializer for outposts + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `GET` /outposts/radius/ + +##### `GET` /outposts/service_connections/all/ + +##### `GET` /outposts/service_connections/all/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /outposts/service_connections/docker/ + +##### `GET` /outposts/service_connections/docker/ + +##### `GET` /outposts/service_connections/docker/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /outposts/service_connections/kubernetes/ + +##### `GET` /outposts/service_connections/kubernetes/ + +##### `GET` /outposts/service_connections/kubernetes/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /policies/all/ + +##### `GET` /policies/all/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /policies/bindings/{policy_binding_uuid}/ + +##### `GET` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `PUT` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `PATCH` /policies/bindings/{policy_binding_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /policies/bindings/{policy_binding_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/dummy/ + +##### `GET` /policies/dummy/ + +##### `GET` /policies/dummy/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/event_matcher/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + +- Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + +- Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + + - Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + + - Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `GET` /policies/event_matcher/ + +###### Parameters: + +Changed: `action` in `query` + +> Match created events with this action type. When left empty, all action types will be matched. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Event Matcher Policy Serializer + + - Changed property `action` (string) + + > Match created events with this action type. When left empty, all action types will be matched. + + - Changed property `app` (string) + + > Match events created by selected application. When left empty, all applications are matched. + + Added enum values: + + - `authentik.sources.scim` + - `authentik.enterprise.stages.source` + + - Changed property `model` (string) + + > Match events created by selected model. When left empty, all models are matched. When an app is selected, all the application's models are matched. + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `GET` /policies/event_matcher/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/expression/ + +##### `GET` /policies/expression/ + +##### `GET` /policies/expression/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/password/ + +##### `GET` /policies/password/ + +##### `GET` /policies/password/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/password_expiry/ + +##### `GET` /policies/password_expiry/ + +##### `GET` /policies/password_expiry/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /policies/reputation/ + +##### `GET` /policies/reputation/ + +##### `GET` /policies/reputation/{policy_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /policies/reputation/scores/ + +##### `GET` /policies/reputation/scores/{reputation_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /propertymappings/all/ + +##### `GET` /propertymappings/all/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/ldap/ + +##### `GET` /propertymappings/ldap/ + +##### `GET` /propertymappings/ldap/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/notification/ + +##### `GET` /propertymappings/notification/ + +##### `GET` /propertymappings/notification/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/rac/ + +##### `GET` /propertymappings/rac/ + +##### `GET` /propertymappings/rac/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/saml/ + +##### `GET` /propertymappings/saml/ + +##### `GET` /propertymappings/saml/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/scim/ + +##### `GET` /propertymappings/scim/ + +##### `GET` /propertymappings/scim/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /propertymappings/scope/ + +##### `GET` /propertymappings/scope/ + +##### `GET` /propertymappings/scope/{pm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /providers/all/ + +##### `GET` /providers/all/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /providers/ldap/{id}/ + +##### `GET` /providers/ldap/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `search_mode` (string) + +##### `PUT` /providers/ldap/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `search_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `search_mode` (string) + +##### `PATCH` /providers/ldap/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `search_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `search_mode` (string) + +##### `GET` /providers/ldap/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /providers/oauth2/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + +- Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + +- Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +##### `GET` /providers/oauth2/ + +###### Parameters: + +Changed: `client_type` in `query` + +> Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + +Changed: `issuer_mode` in `query` + +> Configure how the issuer field of the ID Token should be filled. + +Changed: `sub_mode` in `query` + +> Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + +##### `GET` /providers/oauth2/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /providers/proxy/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `GET` /providers/proxy/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > ProxyProvider Serializer + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + +##### `GET` /providers/proxy/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /providers/rac/ + +##### `GET` /providers/rac/ + +##### `GET` /providers/rac/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /providers/radius/ + +##### `GET` /providers/radius/ + +##### `GET` /providers/radius/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /providers/saml/{id}/ + +##### `GET` /providers/saml/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `PUT` /providers/saml/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `PATCH` /providers/saml/{id}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /providers/saml/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /providers/scim/ + +##### `GET` /providers/scim/ + +##### `GET` /providers/scim/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /rac/connection_tokens/{connection_token_uuid}/ + +###### Parameters: + +Changed: `connection_token_uuid` in `path` + +> A UUID string identifying this RAC Connection token. + +##### `GET` /rac/connection_tokens/{connection_token_uuid}/ + +###### Parameters: + +Changed: `connection_token_uuid` in `path` + +> A UUID string identifying this RAC Connection token. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New optional properties: + + - `pk` + + * Changed property `pk` (string) + + * Changed property `endpoint` (string) + + * Changed property `endpoint_obj` (object) + + > Endpoint Serializer + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `PUT` /rac/connection_tokens/{connection_token_uuid}/ + +###### Parameters: + +Changed: `connection_token_uuid` in `path` + +> A UUID string identifying this RAC Connection token. + +###### Request: + +Changed content type : `application/json` + +New required properties: + +- `endpoint` + +* Added property `pk` (string) + +* Added property `endpoint` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New optional properties: + + - `pk` + + * Changed property `pk` (string) + + * Changed property `endpoint` (string) + + * Changed property `endpoint_obj` (object) + + > Endpoint Serializer + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `PATCH` /rac/connection_tokens/{connection_token_uuid}/ + +###### Parameters: + +Changed: `connection_token_uuid` in `path` + +> A UUID string identifying this RAC Connection token. + +###### Request: + +Changed content type : `application/json` + +- Added property `pk` (string) + +- Added property `endpoint` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New optional properties: + + - `pk` + + * Changed property `pk` (string) + + * Changed property `endpoint` (string) + + * Changed property `endpoint_obj` (object) + + > Endpoint Serializer + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `GET` /rac/connection_tokens/{connection_token_uuid}/used_by/ + +###### Parameters: + +Changed: `connection_token_uuid` in `path` + +> A UUID string identifying this RAC Connection token. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /rac/endpoints/{pbm_uuid}/ + +##### `GET` /rac/endpoints/{pbm_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `PUT` /rac/endpoints/{pbm_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `protocol` (string) + +- Changed property `auth_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `PATCH` /rac/endpoints/{pbm_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `protocol` (string) + +- Changed property `auth_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `GET` /rac/endpoints/{pbm_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /rbac/permissions/ + +##### `POST` /rbac/permissions/assigned_by_roles/{uuid}/assign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `PATCH` /rbac/permissions/assigned_by_roles/{uuid}/unassign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `POST` /rbac/permissions/assigned_by_users/{id}/assign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `PATCH` /rbac/permissions/assigned_by_users/{id}/unassign/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `model` (string) + + Added enum values: + + - `authentik_sources_scim.scimsource` + - `authentik_stages_authenticator_webauthn.authenticatorwebauthnstage` + - `authentik_stages_source.sourcestage` + Removed enum value: + + - `authentik_stages_authenticator_webauthn.authenticatewebauthnstage` + +##### `GET` /rbac/permissions/roles/ + +##### `GET` /rbac/permissions/users/ + +##### `POST` /rbac/roles/ + +##### `GET` /rbac/roles/ + +##### `GET` /rbac/roles/{uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /root/config/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `capabilities` (array) + + Changed items (string): + +##### `DELETE` /sources/all/{slug}/ + +##### `GET` /sources/all/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/all/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/ldap/{slug}/ + +##### `GET` /sources/ldap/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/ldap/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/ldap/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/ldap/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/oauth/{slug}/ + +##### `GET` /sources/oauth/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + + - Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +##### `PUT` /sources/oauth/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +- Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + + - Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +##### `PATCH` /sources/oauth/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +- Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + + - Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +##### `GET` /sources/oauth/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/plex/{slug}/ + +##### `GET` /sources/plex/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/plex/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/plex/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/plex/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/saml/{slug}/ + +##### `GET` /sources/saml/{slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + + - Changed property `policy_engine_mode` (string) + + - Changed property `binding_type` (string) + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `PUT` /sources/saml/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + +- Changed property `policy_engine_mode` (string) + +- Changed property `binding_type` (string) + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + + - Changed property `policy_engine_mode` (string) + + - Changed property `binding_type` (string) + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `PATCH` /sources/saml/{slug}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + +- Changed property `policy_engine_mode` (string) + +- Changed property `binding_type` (string) + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + + - Changed property `policy_engine_mode` (string) + + - Changed property `binding_type` (string) + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /sources/saml/{slug}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/user_connections/all/{id}/ + +##### `GET` /sources/user_connections/all/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/user_connections/all/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/user_connections/all/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/all/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/user_connections/oauth/{id}/ + +##### `GET` /sources/user_connections/oauth/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/user_connections/oauth/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/user_connections/oauth/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/oauth/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/user_connections/plex/{id}/ + +##### `GET` /sources/user_connections/plex/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/user_connections/plex/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/user_connections/plex/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/plex/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /sources/user_connections/saml/{id}/ + +##### `GET` /sources/user_connections/saml/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PUT` /sources/user_connections/saml/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `PATCH` /sources/user_connections/saml/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/saml/{id}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/all/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /stages/authenticator/duo/{stage_uuid}/enrollment_status/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `duo_response` (string) + +##### `GET` /stages/authenticator/duo/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/authenticator/sms/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/authenticator/static/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/authenticator/totp/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/authenticator/validate/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/authenticator/webauthn/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/captcha/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/consent/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/deny/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/dummy/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/email/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/identification/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `DELETE` /stages/invitation/invitations/{invite_uuid}/ + +##### `GET` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/invitation/invitations/{invite_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/invitation/invitations/{invite_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/invitation/stages/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/password/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/prompt/prompts/{prompt_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/prompt/stages/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/user_delete/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/user_login/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/user_logout/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `GET` /stages/user_write/{stage_uuid}/used_by/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Changed items (object): > A list of all objects referencing the queried object + + - Changed property `action` (string) + +##### `POST` /authenticators/admin/static/ + +##### `GET` /authenticators/admin/static/ + +##### `GET` /authenticators/static/ + +##### `POST` /core/applications/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `policy_engine_mode` (string) + +##### `GET` /core/applications/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Application Serializer + + - Changed property `policy_engine_mode` (string) + +##### `POST` /core/groups/ + +##### `GET` /core/groups/ + +###### Parameters: + +Added: `include_users` in `query` + +##### `POST` /core/tokens/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `intent` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `intent` (string) + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /core/tokens/ + +###### Parameters: + +Changed: `intent` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Token Serializer + + - Changed property `intent` (string) + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `DELETE` /core/user_consent/{id}/ + +##### `GET` /core/user_consent/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + + - Changed property `application` (object) + + > Application Serializer + + - Changed property `policy_engine_mode` (string) + +##### `POST` /core/users/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `GET` /core/users/ + +###### Parameters: + +Added: `include_groups` in `query` + +Changed: `type` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > User Serializer + + - Changed property `type` (string) + +##### `GET` /core/users/me/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user` (object) + + > User Serializer for information a user can retrieve about themselves + + - Changed property `type` (string) + +##### `POST` /events/events/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `action` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `action` (string) + +##### `GET` /events/events/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Event Serializer + + - Changed property `action` (string) + +##### `DELETE` /events/notifications/{uuid}/ + +##### `GET` /events/notifications/{uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + + - Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +##### `PUT` /events/notifications/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + + - Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +##### `PATCH` /events/notifications/{uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + + - Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +##### `POST` /events/rules/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +##### `GET` /events/rules/ + +###### Parameters: + +Changed: `severity` in `query` + +> Controls which severity level the created notifications will have. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > NotificationRule Serializer + + - Changed property `severity` (string) + > Controls which severity level the created notifications will have. + +##### `GET` /events/system_tasks/ + +###### Parameters: + +Changed: `status` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serialize TaskInfo and TaskResult + + - Changed property `messages` (array) + + Changed items (string -> object): > Single log message with all context logged. + + - Changed property `status` (string) + +##### `POST` /events/transports/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + +##### `GET` /events/transports/ + +###### Parameters: + +Changed: `mode` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > NotificationTransport Serializer + + - Changed property `mode` (string) + +##### `DELETE` /flows/bindings/{fsb_uuid}/ + +##### `GET` /flows/bindings/{fsb_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `PUT` /flows/bindings/{fsb_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `PATCH` /flows/bindings/{fsb_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `POST` /flows/instances/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + +- Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + +- Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + +- Changed property `policy_engine_mode` (string) + +- Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /flows/instances/ + +###### Parameters: + +Changed: `denied_action` in `query` + +> Configure what should happen when a flow denies access to a user. + +Changed: `designation` in `query` + +> Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /oauth2/access_tokens/{id}/ + +##### `GET` /oauth2/access_tokens/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `DELETE` /oauth2/authorization_codes/{id}/ + +##### `GET` /oauth2/authorization_codes/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `DELETE` /oauth2/refresh_tokens/{id}/ + +##### `GET` /oauth2/refresh_tokens/{id}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `POST` /outposts/instances/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `type` (string) + +##### `GET` /outposts/instances/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Outpost Serializer + + - Changed property `type` (string) + +##### `GET` /outposts/ldap/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > LDAPProvider Serializer + + - Changed property `search_mode` (string) + +##### `POST` /policies/bindings/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /policies/bindings/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PolicyBinding Serializer + + - Changed property `user_obj` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `POST` /providers/ldap/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `search_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `search_mode` (string) + +##### `GET` /providers/ldap/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > LDAPProvider Serializer + + - Changed property `search_mode` (string) + +##### `POST` /providers/saml/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /providers/saml/ + +###### Parameters: + +Changed: `digest_algorithm` in `query` + +Changed: `signature_algorithm` in `query` + +Changed: `sp_binding` in `query` + +> This determines how authentik sends the response back to the Service Provider. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > SAMLProvider Serializer + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /providers/scim/{id}/sync_status/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `tasks` (array) + + Changed items (object): > Serialize TaskInfo and TaskResult + + - Changed property `messages` (array) + + Changed items (string -> object): > Single log message with all context logged. + + - Changed property `status` (string) + +##### `GET` /rac/connection_tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > ConnectionToken Serializer + + New optional properties: + + - `pk` + + * Changed property `pk` (string) + + * Changed property `endpoint` (string) + + * Changed property `endpoint_obj` (object) + + > Endpoint Serializer + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `POST` /rac/endpoints/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `protocol` (string) + +- Changed property `auth_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `GET` /rac/endpoints/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Endpoint Serializer + + - Changed property `protocol` (string) + + - Changed property `auth_mode` (string) + +##### `GET` /rbac/permissions/assigned_by_roles/ + +###### Parameters: + +Changed: `model` in `query` + +##### `GET` /rbac/permissions/assigned_by_users/ + +###### Parameters: + +Changed: `model` in `query` + +##### `GET` /sources/all/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `POST` /sources/ldap/ + +###### Request: + +Changed content type : `application/json` + +- Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/ldap/ + +###### Parameters: + +Added: `password_login_update_internal_password` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > LDAP Source Serializer + + - Added property `password_login_update_internal_password` (boolean) + + > Update internal authentik password when login succeeds with LDAP + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/ldap/{slug}/sync_status/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `tasks` (array) + + Changed items (object): > Serialize TaskInfo and TaskResult + + - Changed property `messages` (array) + + Changed items (string -> object): > Single log message with all context logged. + + - Changed property `status` (string) + +##### `POST` /sources/oauth/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +- Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + + - Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +##### `GET` /sources/oauth/ + +###### Parameters: + +Changed: `policy_engine_mode` in `query` + +Changed: `user_matching_mode` in `query` + +> How the source determines if an existing user should be authenticated or a new user enrolled. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > OAuth Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + + - Changed property `provider_type` (string) + + Added enum value: + + - `gitlab` + +##### `POST` /sources/plex/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/plex/ + +###### Parameters: + +Changed: `policy_engine_mode` in `query` + +Changed: `user_matching_mode` in `query` + +> How the source determines if an existing user should be authenticated or a new user enrolled. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Plex Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `POST` /sources/plex/redeem_token/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `flow_info` (object) + + > Contextual flow information for a challenge + + - Changed property `layout` (string) + +##### `POST` /sources/saml/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + +- Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + +- Changed property `policy_engine_mode` (string) + +- Changed property `binding_type` (string) + +- Changed property `digest_algorithm` (string) + +- Changed property `signature_algorithm` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + + - Changed property `policy_engine_mode` (string) + + - Changed property `binding_type` (string) + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /sources/saml/ + +###### Parameters: + +Changed: `binding_type` in `query` + +Changed: `digest_algorithm` in `query` + +Changed: `name_id_policy` in `query` + +> NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + +Changed: `policy_engine_mode` in `query` + +Changed: `signature_algorithm` in `query` + +Changed: `user_matching_mode` in `query` + +> How the source determines if an existing user should be authenticated or a new user enrolled. + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > SAMLSource Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `name_id_policy` (string) + + > NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. + + - Changed property `policy_engine_mode` (string) + + - Changed property `binding_type` (string) + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + +##### `GET` /sources/user_connections/all/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > OAuth Source Serializer + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `POST` /sources/user_connections/oauth/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/oauth/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > OAuth Source Serializer + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `POST` /sources/user_connections/plex/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/plex/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Plex Source connection Serializer + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `POST` /sources/user_connections/saml/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `GET` /sources/user_connections/saml/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > SAML Source Serializer + + - Changed property `source` (object) + + > Source Serializer + + - Changed property `user_matching_mode` (string) + + > How the source determines if an existing user should be authenticated or a new user enrolled. + + - Changed property `policy_engine_mode` (string) + +##### `DELETE` /stages/all/{stage_uuid}/ + +##### `GET` /stages/all/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/duo/{stage_uuid}/ + +##### `GET` /stages/authenticator/duo/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/duo/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/duo/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/sms/{stage_uuid}/ + +##### `GET` /stages/authenticator/sms/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (string) + + - Changed property `auth_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/sms/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `provider` (string) + +- Changed property `auth_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (string) + + - Changed property `auth_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/sms/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `provider` (string) + +- Changed property `auth_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `provider` (string) + + - Changed property `auth_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/static/{stage_uuid}/ + +##### `GET` /stages/authenticator/static/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/static/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/static/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/totp/{stage_uuid}/ + +##### `GET` /stages/authenticator/totp/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/totp/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/totp/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `digits` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/validate/{stage_uuid}/ + +##### `GET` /stages/authenticator/validate/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `webauthn_allowed_device_types_obj` + + * Added property `webauthn_allowed_device_types` (array) + + Items (string): + + * Added property `webauthn_allowed_device_types_obj` (array) + + Items (object): > WebAuthnDeviceType Serializer + + * Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + + * Changed property `not_configured_action` (string) + + * Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/validate/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `webauthn_allowed_device_types` (array) + +- Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + +- Changed property `not_configured_action` (string) + +- Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `webauthn_allowed_device_types_obj` + + * Added property `webauthn_allowed_device_types` (array) + + * Added property `webauthn_allowed_device_types_obj` (array) + + * Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + + * Changed property `not_configured_action` (string) + + * Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/validate/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `webauthn_allowed_device_types` (array) + +- Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + +- Changed property `not_configured_action` (string) + +- Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `webauthn_allowed_device_types_obj` + + * Added property `webauthn_allowed_device_types` (array) + + * Added property `webauthn_allowed_device_types_obj` (array) + + * Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + + * Changed property `not_configured_action` (string) + + * Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/authenticator/webauthn/{stage_uuid}/ + +##### `GET` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `device_type_restrictions_obj` + + * Added property `device_type_restrictions` (array) + + * Added property `device_type_restrictions_obj` (array) + + * Changed property `authenticator_attachment` (string) + + * Changed property `user_verification` (string) + + * Changed property `resident_key_requirement` (string) + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `device_type_restrictions` (array) + +- Changed property `authenticator_attachment` (string) + +- Changed property `user_verification` (string) + +- Changed property `resident_key_requirement` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `device_type_restrictions_obj` + + * Added property `device_type_restrictions` (array) + + * Added property `device_type_restrictions_obj` (array) + + * Changed property `authenticator_attachment` (string) + + * Changed property `user_verification` (string) + + * Changed property `resident_key_requirement` (string) + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/authenticator/webauthn/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Added property `device_type_restrictions` (array) + +- Changed property `authenticator_attachment` (string) + +- Changed property `user_verification` (string) + +- Changed property `resident_key_requirement` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + New required properties: + + - `device_type_restrictions_obj` + + * Added property `device_type_restrictions` (array) + + * Added property `device_type_restrictions_obj` (array) + + * Changed property `authenticator_attachment` (string) + + * Changed property `user_verification` (string) + + * Changed property `resident_key_requirement` (string) + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/captcha/{stage_uuid}/ + +##### `GET` /stages/captcha/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/captcha/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/captcha/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/consent/{stage_uuid}/ + +##### `GET` /stages/consent/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/consent/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/consent/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/deny/{stage_uuid}/ + +##### `GET` /stages/deny/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/deny/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/deny/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/dummy/{stage_uuid}/ + +##### `GET` /stages/dummy/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/dummy/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/dummy/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/email/{stage_uuid}/ + +##### `GET` /stages/email/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/email/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/email/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/identification/{stage_uuid}/ + +##### `GET` /stages/identification/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/identification/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/identification/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/invitation/invitations/ + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/invitation/invitations/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Invitation Serializer + + - Changed property `flow_obj` (object) + + > Flow Serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `authentication` (string) + + > Required level of authentication and authorization to access a flow. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/invitation/stages/{stage_uuid}/ + +##### `GET` /stages/invitation/stages/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/invitation/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/invitation/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/password/{stage_uuid}/ + +##### `GET` /stages/password/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/password/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/password/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/prompt/stages/{stage_uuid}/ + +##### `GET` /stages/prompt/stages/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/prompt/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/prompt/stages/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/user_delete/{stage_uuid}/ + +##### `GET` /stages/user_delete/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/user_delete/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/user_delete/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/user_login/{stage_uuid}/ + +##### `GET` /stages/user_login/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + + - Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/user_login/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + +- Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + + - Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/user_login/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + +- Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + + - Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/user_logout/{stage_uuid}/ + +##### `GET` /stages/user_logout/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/user_logout/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/user_logout/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/user_write/{stage_uuid}/ + +##### `GET` /stages/user_write/{stage_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_creation_mode` (string) + + - Changed property `user_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/user_write/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_creation_mode` (string) + +- Changed property `user_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_creation_mode` (string) + + - Changed property `user_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/user_write/{stage_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_creation_mode` (string) + +- Changed property `user_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `user_creation_mode` (string) + + - Changed property `user_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /core/transactional/applications/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `provider_model` (string) + +- Changed property `app` (object) + + > Application Serializer + + - Changed property `policy_engine_mode` (string) + +- Changed property `provider` (object) + + Updated `authentik_providers_oauth2.oauth2provider` provider_model: + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + Updated `authentik_providers_proxy.proxyprovider` provider_model: + + - Changed property `mode` (string) + > Enable support for forwardAuth in traefik and nginx auth_request. Exclusive with internal_host. + + Updated `authentik_providers_saml.samlprovider` provider_model: + + - Changed property `sp_binding` (string) + + > This determines how authentik sends the response back to the Service Provider. + + - Changed property `digest_algorithm` (string) + + - Changed property `signature_algorithm` (string) + + Updated `authentik_providers_ldap.ldapprovider` provider_model: + + - Changed property `search_mode` (string) + +##### `GET` /core/user_consent/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserConsent Serializer + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + + - Changed property `application` (object) + + > Application Serializer + + - Changed property `policy_engine_mode` (string) + +##### `GET` /events/notifications/ + +###### Parameters: + +Changed: `severity` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Notification Serializer + + - Changed property `severity` (string) + + - Changed property `event` (object) + + > Event Serializer + + - Changed property `action` (string) + +##### `POST` /flows/bindings/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + +- Changed property `policy_engine_mode` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `GET` /flows/bindings/ + +###### Parameters: + +Changed: `invalid_response_action` in `query` + +> Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + +Changed: `policy_engine_mode` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > FlowStageBinding Serializer + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `GET` /flows/executor/{flow_slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Updated `ak-stage-dummy` component: + New required properties: + + - `name` + + * Added property `name` (string) + + Updated `ak-provider-oauth2-device-code` component: + + - Changed property `type` (string) + + - Changed property `flow_info` (object) + + > Contextual flow information for a challenge + + - Changed property `layout` (string) + + Updated `ak-stage-prompt` component: + + - Changed property `fields` (array) + + Changed items (object): > Serializer for a single Prompt field + + - Changed property `type` (string) + + Updated `ak-stage-identification` component: + New required properties: + + - `flow_designation` + + * Added property `flow_designation` (string) + + Enum values: + + - `authentication` + - `authorization` + - `invalidation` + - `enrollment` + - `unenrollment` + - `recovery` + - `stage_configuration` + +##### `POST` /flows/executor/{flow_slug}/ + +###### Request: + +Changed content type : `application/json` + +Updated `ak-source-oauth-apple` component: + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + Updated `ak-stage-dummy` component: + New required properties: + + - `name` + + * Added property `name` (string) + + Updated `ak-provider-oauth2-device-code` component: + + - Changed property `type` (string) + + - Changed property `flow_info` (object) + + > Contextual flow information for a challenge + + - Changed property `layout` (string) + + Updated `ak-stage-prompt` component: + + - Changed property `fields` (array) + + Changed items (object): > Serializer for a single Prompt field + + - Changed property `type` (string) + + Updated `ak-stage-identification` component: + New required properties: + + - `flow_designation` + + * Added property `flow_designation` (string) + +##### `GET` /flows/inspector/{flow_slug}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `plans` (array) + + Changed items (object): > Serializer for an active FlowPlan + + - Changed property `next_planned_stage` (object) + + > FlowStageBinding Serializer + + - Changed property `invalid_response_action` (string) + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `current_stage` (object) + + > FlowStageBinding Serializer + + - Changed property `invalid_response_action` (string) + + > Configure how the flow executor should handle an invalid response to a challenge. RETRY returns the error message and a similar challenge to the executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT restarts the flow while keeping the current context. + + - Changed property `policy_engine_mode` (string) + + - Changed property `stage_obj` (object) + + > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `layout` (string) + +##### `GET` /oauth2/access_tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and RefreshToken + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /oauth2/authorization_codes/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and ExpiringBaseGrant + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /oauth2/refresh_tokens/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Serializer for BaseGrantModel and RefreshToken + + - Changed property `provider` (object) + + > OAuth2Provider Serializer + + - Changed property `client_type` (string) + + > Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable + + - Changed property `sub_mode` (string) + + > Configure what data should be used as unique User Identifier. For most cases, the default should be fine. + + - Changed property `issuer_mode` (string) + > Configure how the issuer field of the ID Token should be filled. + + - Changed property `user` (object) + + > User Serializer + + - Changed property `type` (string) + +##### `GET` /stages/all/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/duo/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/duo/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorDuoStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/sms/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `provider` (string) + +- Changed property `auth_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `provider` (string) + + - Changed property `auth_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/sms/ + +###### Parameters: + +Changed: `auth_type` in `query` + +Changed: `provider` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorSMSStage Serializer + + - Changed property `provider` (string) + + - Changed property `auth_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/static/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/static/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorStaticStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/totp/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `digits` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `digits` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/totp/ + +###### Parameters: + +Changed: `digits` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorTOTPStage Serializer + + - Changed property `digits` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/validate/ + +###### Request: + +Changed content type : `application/json` + +- Added property `webauthn_allowed_device_types` (array) + +- Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + +- Changed property `not_configured_action` (string) + +- Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + New required properties: + + - `webauthn_allowed_device_types_obj` + + * Added property `webauthn_allowed_device_types` (array) + + * Added property `webauthn_allowed_device_types_obj` (array) + + * Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + + * Changed property `not_configured_action` (string) + + * Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/validate/ + +###### Parameters: + +Changed: `not_configured_action` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorValidateStage Serializer + + New required properties: + + - `webauthn_allowed_device_types_obj` + + * Added property `webauthn_allowed_device_types` (array) + + * Added property `webauthn_allowed_device_types_obj` (array) + + * Changed property `webauthn_user_verification` (string) + + > Enforce user verification for WebAuthn devices. + + * Changed property `not_configured_action` (string) + + * Changed property `device_classes` (array) + + > Device classes which can be used to authenticate + + Changed items (string): + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/authenticator/webauthn/ + +###### Request: + +Changed content type : `application/json` + +- Added property `device_type_restrictions` (array) + +- Changed property `authenticator_attachment` (string) + +- Changed property `user_verification` (string) + +- Changed property `resident_key_requirement` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + New required properties: + + - `device_type_restrictions_obj` + + * Added property `device_type_restrictions` (array) + + * Added property `device_type_restrictions_obj` (array) + + * Changed property `authenticator_attachment` (string) + + * Changed property `user_verification` (string) + + * Changed property `resident_key_requirement` (string) + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/authenticator/webauthn/ + +###### Parameters: + +Added: `device_type_restrictions` in `query` + +Changed: `authenticator_attachment` in `query` + +Changed: `resident_key_requirement` in `query` + +Changed: `user_verification` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > AuthenticatorWebAuthnStage Serializer + + New required properties: + + - `device_type_restrictions_obj` + + * Added property `device_type_restrictions` (array) + + * Added property `device_type_restrictions_obj` (array) + + * Changed property `authenticator_attachment` (string) + + * Changed property `user_verification` (string) + + * Changed property `resident_key_requirement` (string) + + * Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/captcha/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/captcha/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > CaptchaStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/consent/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `mode` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `mode` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/consent/ + +###### Parameters: + +Changed: `mode` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > ConsentStage Serializer + + - Changed property `mode` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/deny/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/deny/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > DenyStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/dummy/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/dummy/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > DummyStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/email/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/email/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > EmailStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/identification/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/identification/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > IdentificationStage Serializer + + - Changed property `user_fields` (array) + + > Fields of the user object to match against. (Hold shift to select multiple options) + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/invitation/stages/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/invitation/stages/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > InvitationStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/password/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/password/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PasswordStage Serializer + + - Changed property `backends` (array) + + > Selection of backends to test the password against. + + Changed items (string): + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `DELETE` /stages/prompt/prompts/{prompt_uuid}/ + +##### `GET` /stages/prompt/prompts/{prompt_uuid}/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PUT` /stages/prompt/prompts/{prompt_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `PATCH` /stages/prompt/prompts/{prompt_uuid}/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/prompt/prompts/preview/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `flow_info` (object) + + > Contextual flow information for a challenge + + - Changed property `layout` (string) + + - Changed property `fields` (array) + + Changed items (object): > Serializer for a single Prompt field + + - Changed property `type` (string) + +##### `POST` /stages/prompt/stages/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/prompt/stages/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > PromptStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/user_delete/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/user_delete/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserDeleteStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/user_login/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + +- Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + + - Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/user_login/ + +###### Parameters: + +Changed: `geoip_binding` in `query` + +> Bind sessions created by this stage to the configured GeoIP location + +Changed: `network_binding` in `query` + +> Bind sessions created by this stage to the configured network + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserLoginStage Serializer + + - Changed property `network_binding` (string) + + > Bind sessions created by this stage to the configured network + + - Changed property `geoip_binding` (string) + + > Bind sessions created by this stage to the configured GeoIP location + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/user_logout/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/user_logout/ + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserLogoutStage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/user_write/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `user_creation_mode` (string) + +- Changed property `user_type` (string) + +- Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `user_creation_mode` (string) + + - Changed property `user_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/user_write/ + +###### Parameters: + +Changed: `user_creation_mode` in `query` + +Changed: `user_type` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > UserWriteStage Serializer + + - Changed property `user_creation_mode` (string) + + - Changed property `user_type` (string) + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `POST` /stages/prompt/prompts/ + +###### Request: + +Changed content type : `application/json` + +- Changed property `type` (string) + +- Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +###### Return Type: + +Changed response : **201 Created** + +- Changed content type : `application/json` + + - Changed property `type` (string) + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) + +##### `GET` /stages/prompt/prompts/ + +###### Parameters: + +Changed: `type` in `query` + +###### Return Type: + +Changed response : **200 OK** + +- Changed content type : `application/json` + + - Changed property `results` (array) + + Changed items (object): > Prompt Serializer + + - Changed property `type` (string) + + - Changed property `promptstage_set` (array) + + Changed items (object): > Stage Serializer + + - Changed property `flow_set` (array) + + Changed items (object): > Stripped down flow serializer + + - Changed property `designation` (string) + + > Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik. + + - Changed property `denied_action` (string) + + > Configure what should happen when a flow denies access to a user. + + - Changed property `policy_engine_mode` (string) + + - Changed property `layout` (string) diff --git a/website/docs/releases/_template.md b/website/docs/releases/_template.md index 03877e90ea..9496266f28 100644 --- a/website/docs/releases/_template.md +++ b/website/docs/releases/_template.md @@ -3,6 +3,12 @@ title: Release xxxx.x slug: "/releases/xxxx.x" --- +:::::note +xxxx.x has not been released yet! We're publishing these release notes as a preview of what's to come, and for our awesome beta testers trying out release candidates. + +To try out the release candidate, replace your Docker image tag with the latest release candidate number, such as xxxx.x.0-rc1. You can find the latest one in [the latest releases on GitHub](https://github.com/goauthentik/authentik/releases). If you don't find any, it means we haven't released one yet. +::::: + ## New features @@ -15,9 +21,9 @@ This release does not introduce any new requirements. To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: -``` +```shell wget -O docker-compose.yml https://goauthentik.io/version/xxxx.x/docker-compose.yml -docker-compose up -d +docker compose up -d ``` The `-O` flag retains the downloaded file's name, overwriting any existing local file with the same name. diff --git a/website/docs/releases/old/v0.10.md b/website/docs/releases/old/v0.10.md index 762268dd3c..e101731ceb 100644 --- a/website/docs/releases/old/v0.10.md +++ b/website/docs/releases/old/v0.10.md @@ -42,7 +42,7 @@ By default, the new compose file uses a fixed version to prevent unintended upda Before updating the file, stop all containers. Then download the file, pull the new containers and start the database. -``` +```shell docker-compose down docker-compose pull docker-compose up --no-start diff --git a/website/docs/releases/old/v0.13.md b/website/docs/releases/old/v0.13.md index 881da79eb2..d778d19a94 100644 --- a/website/docs/releases/old/v0.13.md +++ b/website/docs/releases/old/v0.13.md @@ -39,7 +39,7 @@ The only manual change you have to do is replace the `PASSBOOK_` prefix in your Additionally, the database name and username have to be changed, so add this block to your `.env` file: -``` +```shell PG_USER=passbook PG_DB=passbook ``` @@ -50,7 +50,7 @@ Afterwards, you can simply run `docker-compose up -d` and then the normal upgrad The helm repository changes from passbook to authentik. To update your repository, execute these commands: -``` +```shell helm repo remove passbook helm repo add authentik https://docker.beryju.org/chartrepo/authentik ``` @@ -68,7 +68,7 @@ postgresql: Afterwards you can upgrade as usual from the new repository: -``` +```shell helm upgrade authentik authentik/authentik --devel -f values.yaml ``` diff --git a/website/docs/releases/old/v0.9.md b/website/docs/releases/old/v0.9.md index cbc2cca678..6972e80891 100644 --- a/website/docs/releases/old/v0.9.md +++ b/website/docs/releases/old/v0.9.md @@ -9,14 +9,14 @@ To export data from your old instance, run this command: - docker-compose -``` +```shell docker-compose exec server ./manage.py dumpdata -o /tmp/authentik_dump.json authentik_core.User authentik_core.Group authentik_crypto.CertificateKeyPair authentik_audit.Event otp_totp.totpdevice otp_static.staticdevice otp_static.statictoken docker cp authentik_server_1:/tmp/authentik_dump.json authentik_dump.json ``` - kubernetes -``` +```shell kubectl exec -it authentik-web-... -- ./manage.py dumpdata -o /tmp/authentik_dump.json authentik_core.User authentik_core.Group authentik_crypto.CertificateKeyPair authentik_audit.Event otp_totp.totpdevice otp_static.staticdevice otp_static.statictoken kubectl cp authentik-web-...:/tmp/authentik_dump.json authentik_dump.json ``` @@ -25,14 +25,14 @@ After that, create a new authentik instance in a different namespace (kubernetes - docker-compose -``` +```shell docker cp authentik_dump.json new_authentik_server_1:/tmp/authentik_dump.json docker-compose exec server ./manage.py loaddata /tmp/authentik_dump.json ``` - kubernetes -``` +```shell kubectl cp authentik_dump.json authentik-web-...:/tmp/authentik_dump.json kubectl exec -it authentik-web-... -- ./manage.py loaddata /tmp/authentik_dump.json ``` diff --git a/website/docs/security/2023-06-cure53.md b/website/docs/security/2023-06-cure53.md index 55d65d12df..b9d312743a 100644 --- a/website/docs/security/2023-06-cure53.md +++ b/website/docs/security/2023-06-cure53.md @@ -1,6 +1,6 @@ # 2023-06 Cure53 Code audit -In May/June of 2023, we've had a Pentest conducted by [Cure53](https://cure53.de). The following security updates, 2023.4.2 and 2023.5.3 were released as a response to the found issues. +In May/June of 2023, we had a pentest conducted by [Cure53](https://cure53.de). The following security updates, 2023.4.2 and 2023.5.3 were released as a response to the found issues. From the [complete report](https://cure53.de/pentest-report_authentik.pdf), these are the points we're addressing with this update: @@ -44,23 +44,24 @@ Related to ATH-01-003, it was possible to insert unintended diagrams into genera ## Additional info -In addition to the points above, several of the findings are classified as intended features (such as the expression policies), however these are points where we do also see room for improvement that we will address in the future. +In addition to the points above, several of the findings are classified as intended features (such as the expression policies). However, we have published additional [hardening documentation](./security-hardening.md) to provide guidance for further measures that can be taken to limit any possible risks associated with these features. ### ATH-01-002: Stored XSS in help text of prompt module (Medium) -Prompt help texts can use HTML to add markup, which also includes the option to include JavaScript. This is only possible to configure for superusers, and in the future we're planning to add an additional toggle to limit this. +Prompt help texts can use HTML to add markup, which also includes the option to include JavaScript. This is only possible to configure for superusers. To mitigate the risk of a rogue superuser creating a stage with a malicious script, requests to the `/api/v3/stages/captcha*` and `/api/v3/managed/blueprints*` endpoints can be blocked. With these restrictions in place, Captcha stages can only be edited using Blueprints on the file system. It is also recommended to use the RBAC system to restrict which users can edit these objects. ### ATH-01-006: Arbitrary code execution via expressions (Critical) -This is the intended function of expression policies/property mappings, which also requires superuser permissions to edit. We're planning to also add a toggle to limit the functions that can be executed to the ones provided by authentik, and prevent the importing of modules. +This is the intended function of expression policies/property mappings, which also requires superuser permissions to edit. To mitigate the risk of a rogue superuser creating a malicious expression, requests to the `/api/v3/policies/expression*`, `/api/v3/propertymappings*`, and ` /api/v3/managed/blueprints*` endpoints can be blocked. With these restrictions in place, expression can only be edited using Blueprints on the file system. It is also recommended to use the RBAC system to restrict which users can edit these objects. ### ATH-01-007: SSRF via blueprints feature for fetching manifests (Medium) -Blueprints can be fetched via OCI registries, which could be potentially used for server-side request forgery. This can only be accessed by superusers, and we're planning to add an option to limit the resolved IP ranges this functionality can connect to. +Superusers can fetch blueprints via OCI registries, which could be potentially used for server-side request forgery. To mitigate the risk of a rogue superuser sending malicious requests, requests to the `/api/v3/managed/blueprints*` endpoint can be blocked. With these restrictions in +place, blueprints can only be edited using YAML files on the file system. It is also recommended to use the RBAC system to restrict which users can edit these objects. ### ATH-01-013: XSS via CAPTCHA JavaScript URL (Medium) -Similar to ATH-01-002, any arbitrary JavaScript can be loaded using the Captcha stage. This is also limited to superusers. +Similar to ATH-01-002, any arbitrary JavaScript can be loaded using the Captcha stage. This is also limited to superusers. In order to prevent potential exploitation, it is recommended to limit the setting to allow-listed JavaScript URLs only. ### ATH-01-011: Weak default configs in logout/change password flows (Info) diff --git a/website/docs/security/CVE-2024-23647.md b/website/docs/security/CVE-2024-23647.md new file mode 100644 index 0000000000..837b535c82 --- /dev/null +++ b/website/docs/security/CVE-2024-23647.md @@ -0,0 +1,27 @@ +# CVE-2024-23647 + +_Reported by [@pieterphilippaerts](https://github.com/pieterphilippaerts)_ + +## PKCE downgrade attack in authentik + +## Summary + +PKCE is a very important countermeasure in OAuth2 , both for public and confidential clients. It protects against CSRF attacks and code injection attacks. Because of this bug, an attacker can circumvent the protection PKCE offers. + +## Patches + +authentik 2023.8.7 and 2023.10.7 fix this issue. + +## Details + +There is a bug in our implementation of PKCE that allows an attacker to circumvent the protection that PKCE offers. PKCE adds the `code_challenge’ parameter to the authorization request and adds the `code_verifier’ parameter to the token request. We recently fixed a downgrade attack (in v2023.8.5 and 2023.10.4) where if the attacker removed the `code_verifier’ parameter in the token request, authentik would allow the request to pass, thus circumventing PKCE’s protection. However, in the latest version of the software, another downgrade scenario is still possible: if the attacker removes the `code_challenge’ parameter from the authorization request, authentik will also not do the PKCE check. + +Note that this type of downgrade enables an attacker to perform a code injection attack, even if the OAuth client is using PKCE (which is supposed to protect against code injection attacks). To start the attack, the attacker must initiate the authorization process without that `code_challenge’ parameter in the authorization request. But this is easy to do (just use a phishing site or email to trick the user into clicking on a link that the attacker controls – the authorization link without that `code_challenge’ parameter). + +The OAuth BCP (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics) explicitly mentions this particular attack in section 2.1.1: “Authorization servers MUST mitigate PKCE Downgrade Attacks by ensuring that a token request containing a code_verifier parameter is accepted only if a code_challenge parameter was present in the authorization request, see Section 4.8.2 for details.” + +## For more information + +If you have any questions or comments about this advisory: + +- Email us at [security@goauthentik.io](mailto:security@goauthentik.io) diff --git a/website/docs/security/security-hardening.md b/website/docs/security/security-hardening.md new file mode 100644 index 0000000000..8df3d876c0 --- /dev/null +++ b/website/docs/security/security-hardening.md @@ -0,0 +1,38 @@ +--- +title: Hardening authentik +--- + +While authentik is secure out of the box, you can take steps to further increase the security of an authentik instance. As everyone knows, there is a consequential tradeoff between security and convenience. All of these hardening practices have an impact on the user experience and should only be applied knowing this tradeoff. + +### Expressions + +[Expressions](../property-mappings/expression.mdx) allow super-users and other highly privileged users to create custom logic within authentik to modify its behaviour. Editing/creating these expressions is, by default, limited to super-users and any related events are fully logged. + +However, for further hardening, it is possible to prevent any user (even super-users) from using expressions to create or edit any objects. To do so, configure your deployment to block API requests to these endpoints: + +- `/api/v3/policies/expression*` +- `/api/v3/propertymappings*` +- `/api/v3/managed/blueprints*` + +With these restrictions in place, expressions can only be edited using [Blueprints on the file system](https://docs.goauthentik.io/developer-docs/blueprints/#storage---file). Take care to restrict access to the file system itself. + +### Blueprints + +Blueprints allow for templating and managing the authentik configuration as code. Just like expressions, they can only be created/edited by super-users or users with specific permissions assigned to them. However, because they interact with the authentik API on a lower level, they can create other objects. + +To prevent any user from creating/editing blueprints, block API requests to this endpoint: + +- `/api/v3/managed/blueprints*` + +With these restrictions in place, Blueprints can only be edited via [the file system](https://docs.goauthentik.io/developer-docs/blueprints/#storage---file). + +### CAPTCHA Stage + +The CAPTCHA stage allows for additional verification of a user while authenticating or authorising an application. Because the CAPTCHA stage supports multiple different CAPTCHA providers, such as Google’s reCAPTCHA and Cloudflare’s Turnstile, the URL for the JavaScript snippet can be modified. Depending on the threat model, this could be exploited by a malicious internal actor. + +To prevent any user from creating/editing CAPTCHA stages block API requests to these endpoints: + +- `/api/v3/stages/captcha*` +- `/api/v3/managed/blueprints*` + +With these restrictions in place, CAPTCHA stages can only be edited using [Blueprints on the file system](https://docs.goauthentik.io/developer-docs/blueprints/#storage---file). diff --git a/website/integrations/sources/active-directory/01_user_create.png b/website/docs/sources/active-directory/01_user_create.png similarity index 100% rename from website/integrations/sources/active-directory/01_user_create.png rename to website/docs/sources/active-directory/01_user_create.png diff --git a/website/integrations/sources/active-directory/02_delegate.png b/website/docs/sources/active-directory/02_delegate.png similarity index 100% rename from website/integrations/sources/active-directory/02_delegate.png rename to website/docs/sources/active-directory/02_delegate.png diff --git a/website/integrations/sources/active-directory/03_additional_perms.png b/website/docs/sources/active-directory/03_additional_perms.png similarity index 100% rename from website/integrations/sources/active-directory/03_additional_perms.png rename to website/docs/sources/active-directory/03_additional_perms.png diff --git a/website/integrations/sources/active-directory/10_ak_status.png b/website/docs/sources/active-directory/10_ak_status.png similarity index 100% rename from website/integrations/sources/active-directory/10_ak_status.png rename to website/docs/sources/active-directory/10_ak_status.png diff --git a/website/integrations/sources/active-directory/11_ak_stage.png b/website/docs/sources/active-directory/11_ak_stage.png similarity index 100% rename from website/integrations/sources/active-directory/11_ak_stage.png rename to website/docs/sources/active-directory/11_ak_stage.png diff --git a/website/integrations/sources/active-directory/index.md b/website/docs/sources/active-directory/index.md similarity index 98% rename from website/integrations/sources/active-directory/index.md rename to website/docs/sources/active-directory/index.md index b9da89333d..3c474e8388 100644 --- a/website/integrations/sources/active-directory/index.md +++ b/website/docs/sources/active-directory/index.md @@ -19,7 +19,7 @@ The following placeholders will be used: ![](./01_user_create.png) -3. Give the User a password, generated using for example `pwgen 64 1` or `openssl rand -base64 36`. +3. Give the User a password, generated using for example `pwgen 64 1` or `openssl rand 36 | base64`. 4. Open the Delegation of Control Wizard by right-clicking the domain and selecting "All Tasks". diff --git a/website/integrations/sources/apple/app_id.png b/website/docs/sources/apple/app_id.png similarity index 100% rename from website/integrations/sources/apple/app_id.png rename to website/docs/sources/apple/app_id.png diff --git a/website/integrations/sources/apple/app_service_config.png b/website/docs/sources/apple/app_service_config.png similarity index 100% rename from website/integrations/sources/apple/app_service_config.png rename to website/docs/sources/apple/app_service_config.png diff --git a/website/integrations/sources/apple/index.md b/website/docs/sources/apple/index.md similarity index 97% rename from website/integrations/sources/apple/index.md rename to website/docs/sources/apple/index.md index a2120f65ed..29744e33f2 100644 --- a/website/integrations/sources/apple/index.md +++ b/website/docs/sources/apple/index.md @@ -69,5 +69,5 @@ The following placeholders will be used: Save, and you now have Apple as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: diff --git a/website/integrations/sources/apple/key.png b/website/docs/sources/apple/key.png similarity index 100% rename from website/integrations/sources/apple/key.png rename to website/docs/sources/apple/key.png diff --git a/website/integrations/sources/apple/service_id.png b/website/docs/sources/apple/service_id.png similarity index 100% rename from website/integrations/sources/apple/service_id.png rename to website/docs/sources/apple/service_id.png diff --git a/website/integrations/sources/azure-ad/aad_01.png b/website/docs/sources/azure-ad/aad_01.png similarity index 100% rename from website/integrations/sources/azure-ad/aad_01.png rename to website/docs/sources/azure-ad/aad_01.png diff --git a/website/integrations/sources/azure-ad/authentik_01.png b/website/docs/sources/azure-ad/authentik_01.png similarity index 100% rename from website/integrations/sources/azure-ad/authentik_01.png rename to website/docs/sources/azure-ad/authentik_01.png diff --git a/website/docs/sources/azure-ad/index.md b/website/docs/sources/azure-ad/index.md new file mode 100644 index 0000000000..5530d0c523 --- /dev/null +++ b/website/docs/sources/azure-ad/index.md @@ -0,0 +1,113 @@ +--- +title: Azure AD +--- + +Support level: Community + +## Preparation + +The following placeholders will be used: + +- `authentik.company` is the FQDN of the authentik install. + +## Azure setup + +1. Navigate to [portal.azure.com](https://portal.azure.com), and open the _App registration_ service +2. Register a new application + + Under _Supported account types_, select whichever account type applies to your use-case. + + ![](./aad_01.png) + +3. Take note of the _Application (client) ID_ value. + + If you selected _Single tenant_ in the _Supported account types_ prompt, also note the _Directory (tenant) ID_ value. + +4. Navigate to _Certificates & secrets_ in the sidebar, and to the _Client secrets_ tab. +5. Add a new secret, with an identifier of your choice, and select any expiration. Currently the secret in authentik has to be rotated manually or via API, so it is recommended to choose at least 12 months. +6. Note the secret's value in the _Value_ column. + +## authentik Setup + +In authentik, create a new _Azure AD OAuth Source_ in Resources -> Sources. + +Use the following settings: + +- Name: `Azure AD` +- Slug: `azure-ad` (this must match the URL being used above) +- Consumer key: `*Application (client) ID* value from above` +- Consumer secret: `*Value* of the secret from above` + +If you kept the default _Supported account types_ selection of _Single tenant_, then you must change the URL below as well: + +- OIDC Well-known URL: `https://login.microsoftonline.com/*Directory (tenant) ID* from above/v2.0/.well-known/openid-configuration` + +![](./authentik_01.png) + +Save, and you now have Azure AD as a source. + +:::note +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). +::: + +### Automatic user enrollment and attribute mapping + +Using the following process you can auto-enroll your users without interaction, and directly control the mapping Azure attribute to authentik. +attribute. + +1. Create a new _Expression Policy_ (see [here](../../../docs/policies/) for details). +2. Use _azure-ad-mapping_ as the name. +3. Add the following code and adjust to your needs. + +```python +# save existing prompt data +current_prompt_data = context.get('prompt_data', {}) +# make sure we are used in an oauth flow +if 'oauth_userinfo' not in context: + ak_logger.warning(f"Missing expected oauth_userinfo in context. Context{context}") + return False +oauth_data = context['oauth_userinfo'] +# map fields directly to user left hand are the field names provided by +# the microsoft graph api on the right the user field names as used by authentik +required_fields_map = { + 'name': 'username', + 'upn': 'email', + 'given_name': 'name' +} +missing_fields = set(required_fields_map.keys()) - set(oauth_data.keys()) +if missing_fields: + ak_logger.warning(f"Missing expected fields. Missing fields {missing_fields}.") + return False +for oauth_field, user_field in required_fields_map.items(): + current_prompt_data[user_field] = oauth_data[oauth_field] +# Define fields that should be mapped as extra user attributes +attributes_map = { + 'upn': 'upn', + 'family_name': 'sn', + 'name': 'name' +} +missing_attributes = set(attributes_map.keys()) - set(oauth_data.keys()) +if missing_attributes: + ak_logger.warning(f"Missing attributes: {missing_attributes}.") + return False +# again make sure not to overwrite existing data +current_attributes = current_prompt_data.get('attributes', {}) +for oauth_field, user_field in attributes_map.items(): + current_attributes[user_field] = oauth_data[oauth_field] +current_prompt_data['attributes'] = current_attributes +context['prompt_data'] = current_prompt_data +return True +``` + +4. Create a new enrollment flow _azure-ad-enrollment_ (see [here](../../../docs/flow/) for details). +5. Add the policy _default-source-enrollment-if-sso_ to the flow. To do so open the newly created flow. + Click on the tab **Policy/Group/User Bindings**. Click on **Bind existing policy** and choose _default-source-enrollment-if-sso_ + from the list. +6. Bind the stages _default-source-enrollment-write_ (order 0) and _default-source-enrollment-login_ (order 10) to the flow. +7. Bind the policy _azure-ad-mapping_ to the stage _default-source-enrollment-write_. To do so open the flow _azure-ad-enrollment_ + open the tab **Stage Bindings**, open the dropdown menu for the stage _default-source-enrollment-write_ and click on **Bind existing policy** + Select _azure-ad-mapping_. +8. Open the source _azure-ad_. Click on edit. +9. Open **Flow settings** and choose _azure-ad-enrollment_ as enrollment flow. + +Try to login with a **_new_** user. You should see no prompts and the user should have the correct information. diff --git a/website/integrations/sources/discord/discord1.png b/website/docs/sources/discord/discord1.png similarity index 100% rename from website/integrations/sources/discord/discord1.png rename to website/docs/sources/discord/discord1.png diff --git a/website/integrations/sources/discord/discord2.png b/website/docs/sources/discord/discord2.png similarity index 100% rename from website/integrations/sources/discord/discord2.png rename to website/docs/sources/discord/discord2.png diff --git a/website/integrations/sources/discord/discord3.png b/website/docs/sources/discord/discord3.png similarity index 100% rename from website/integrations/sources/discord/discord3.png rename to website/docs/sources/discord/discord3.png diff --git a/website/integrations/sources/discord/discord4.png b/website/docs/sources/discord/discord4.png similarity index 100% rename from website/integrations/sources/discord/discord4.png rename to website/docs/sources/discord/discord4.png diff --git a/website/docs/sources/discord/index.md b/website/docs/sources/discord/index.md new file mode 100644 index 0000000000..da79ea8507 --- /dev/null +++ b/website/docs/sources/discord/index.md @@ -0,0 +1,362 @@ +--- +title: Discord +--- + +Support level: authentik + +Allows users to authenticate using their Discord credentials + +## Preparation + +The following placeholders will be used: + +- `authentik.company` is the FQDN of the authentik install. + +## Discord + +1. Create an application in the Discord Developer Portal (This is Free) https://discord.com/developers/applications + +![New Application Button](discord1.png) + +2. Name the Application + +![Name App](discord2.png) + +3. Select **OAuth2** from the left Menu + +4. Copy the **Client ID** and _save it for later_ + +5. **Click to Reveal** the Client Secret and _save it for later_ + +6. Click **Add Redirect** and add https://authentik.company/source/oauth/callback/discord/ + +Here is an example of a completed OAuth2 screen for Discord. + +![](discord3.png) + +## authentik + +8. Under _Directory -> Federation & Social login_ Click **Create Discord OAuth Source** + +9. **Name:** Choose a name (For the example I used Discord) +10. **Slug:** discord (You can choose a different slug, if you do you will need to update the Discord redirect URLand point it to the correct slug.) +11. **Consumer Key:** Client ID from step 4 +12. **Consumer Secret:** Client Secret from step 5 + +Here is an example of a complete authentik Discord OAuth Source + +![](discord4.png) + +Save, and you now have Discord as a source. + +:::note +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). +::: + +### Checking for membership of a Discord Guild + +:::info +Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds` scope added under the 'Protocol settings'. +::: + +Create a new 'Expression Policy' with the content below, adjusting the variables where required: + +```python +# To get the guild ID number for the parameters, open Discord, go to Settings > Advanced and enable developer mode. +# Right-click on the server/guild title and select "Copy ID" to get the guild ID. + +ACCEPTED_GUILD_ID = "123456789123456789" +GUILD_NAME_STRING = "The desired server/guild name in the error message." + +# Only change below here if you know what you are doing. + +# Ensure flow is only run during OAuth logins via Discord +if context['source'].provider_type != "discord": + return True + +# Get the user-source connection object from the context, and get the access token +connection = context.get("goauthentik.io/sources/connection") +if not connection: + return False +access_token = connection.access_token + +guilds = requests.get( + "https://discord.com/api/users/@me/guilds", + headers= { + "Authorization": f"Bearer {access_token}", + } +).json() + +user_matched = any(ACCEPTED_GUILD_ID == g["id"] for g in guilds) +if not user_matched: + ak_message(f"User is not a member of {GUILD_NAME_STRING}.") +return user_matched +``` + +Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source. + +### Checking for membership of a Discord Guild role + +:::info +Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds guilds.members.read` scopes added under the 'Protocol settings'. +::: + +Create a new 'Expression Policy' with the content below, adjusting the variables where required: + +```python +# To get the role and guild ID numbers for the parameters, open Discord, go to Settings > Advanced and +# enable developer mode. +# Right-click on the server/guild title and select "Copy ID" to get the guild ID. +# Right-click on the server/guild title and select server settings > roles, right click on the role and click +# "Copy ID" to get the role ID. + +ACCEPTED_ROLE_ID = "123456789123456789" +ACCEPTED_GUILD_ID = "123456789123456789" +GUILD_NAME_STRING = "The desired server/guild name in the error message." +ROLE_NAME_STRING = "The desired role name in the error message." + +# Only change below here if you know what you are doing. +GUILD_API_URL = f"https://discord.com/api/users/@me/guilds/{ACCEPTED_GUILD_ID}/member" + +# Ensure flow is only run during OAuth logins via Discord +if context['source'].provider_type != "discord": + return True + +# Get the user-source connection object from the context, and get the access token +connection = context.get("goauthentik.io/sources/connection") +if not connection: + return False +access_token = connection.access_token + +guild_member_object = requests.get( + GUILD_API_URL, + headers= { + "Authorization": f"Bearer {access_token}", + } +).json() + +# The response for JSON errors is held within guild_member_object['code'] +# See: https://discord.com/developers/docs/topics/opcodes-and-status-codes#json +# If the user isn't in the queried guild, it gives the somewhat misleading code = 10004. +if "code" in guild_member_object: + if guild_member_object['code'] == 10004: + ak_message(f"User is not a member of {GUILD_NAME_STRING}.") + else: + ak_create_event("discord_error", source=context['source'], code=guild_member_object['code']) + ak_message("Discord API error, try again later.") + # Policy does not match if there is any error. + return False + +user_matched = any(ACCEPTED_ROLE_ID == g for g in guild_member_object["roles"]) +if not user_matched: + ak_message(f"User is not a member of the {ROLE_NAME_STRING} role in {GUILD_NAME_STRING}.") +return user_matched +``` + +Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source. + +### Syncing Discord roles to authentik groups + +:::info +Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds.members.read` scopes added under the 'Protocol settings'. +::: + +Create a new 'Expression Policy' with the content below, adjusting the variables where required. + +#### Sync on enrollment + +```python +# To get the role and guild ID numbers for the parameters, open Discord, go to Settings > Advanced and +# enable developer mode. +# Right-click on the server/guild title and select "Copy ID" to get the guild ID. +# Right-click on the server/guild title and select server settings > roles, right click on the role and click +# "Copy ID" to get the role ID. + +from authentik.core.models import Group + +GUILD_ID = "" +MAPPED_ROLES = { + "": Group.objects.get_or_create(name="")[0], + "": Group.objects.get_or_create(name="")[0], + # You can add mapped roles by copying the above line and adjusting to your needs +} + +# Only change below here if you know what you are doing. +GUILD_API_URL = "https://discord.com/api/users/@me/guilds/{guild_id}/member" + +# Ensure flow is only run during OAuth logins via Discord +if context["source"].provider_type != "discord": + return True + +# Get the user-source connection object from the context, and get the access token +connection = context.get("goauthentik.io/sources/connection") +if not connection: + return False +access_token = connection.access_token + +guild_member_info = requests.get( + GUILD_API_URL.format(guild_id=GUILD_ID), + headers={"Authorization": "Bearer " + access_token}, +).json() + +# Ensure user is a member of the guild +if "code" in guild_member_info: + if guild_member_info["code"] == 10004: + ak_message("User is not a member of the guild") + else: + ak_create_event( + "discord_error", source=context["source"], code=guild_member_info["code"] + ) + ak_message("Discord API error, try again later.") + return False + +# Add all mapped roles the user has in the guild +groups_to_add = [] +for role_id in MAPPED_ROLES: + if role_id in guild_member_info["roles"]: + groups_to_add.append(MAPPED_ROLES[role_id]) + +request.context["flow_plan"].context["groups"] = groups_to_add +return True + +``` + +Now bind this policy to the chosen enrollment flows for the Discord OAuth source. + +#### Sync on authentication + +```python +# To get the role and guild ID numbers for the parameters, open Discord, go to Settings > Advanced and +# enable developer mode. +# Right-click on the server/guild title and select "Copy ID" to get the guild ID. +# Right-click on the server/guild title and select server settings > roles, right click on the role and click +# "Copy ID" to get the role ID. + +from authentik.core.models import Group + +GUILD_ID = "" +MAPPED_ROLES = { + "": Group.objects.get_or_create(name="")[0], + "": Group.objects.get_or_create(name="")[0], + # You can add mapped roles by copying the above line and adjusting to your needs +} + +# Only change below here if you know what you are doing. +GUILD_API_URL = "https://discord.com/api/users/@me/guilds/{guild_id}/member" + +# Ensure flow is only run during OAuth logins via Discord +if context["source"].provider_type != "discord": + return True + +# Get the user-source connection object from the context, and get the access token +connection = context.get("goauthentik.io/sources/connection") +if not connection: + return False +access_token = connection.access_token + +guild_member_info = requests.get( + GUILD_API_URL.format(guild_id=GUILD_ID), + headers={"Authorization": "Bearer " + access_token}, +).json() + +# Ensure user is a member of the guild +if "code" in guild_member_info: + if guild_member_info["code"] == 10004: + ak_message("User is not a member of the guild") + else: + ak_create_event( + "discord_error", source=context["source"], code=guild_member_info["code"] + ) + ak_message("Discord API error, try again later.") + return False + +# Get the user's current roles and remove all roles we want to remap +new_groups = [ + role for role in request.user.ak_groups.all() if role not in MAPPED_ROLES.values() +] + +# Add back mapped roles which the user has in the guild +for role_id in MAPPED_ROLES: + if role_id in guild_member_info["roles"]: + new_groups.append(MAPPED_ROLES[role_id]) + +# Update user's groups +request.user.ak_groups.set(new_groups) +request.user.save() + +return True + +``` + +Now bind this policy to the chosen authentication flows for the Discord OAuth source. + +### Store OAuth info in attribute and create avatar attribute from Discord avatar + +:::info +Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds.members.read` scopes added under the 'Protocol settings'. +::: + +:::info +In order to use the created attribute in authentik you will have to set authentik configuration arguments found at: https://docs.goauthentik.io/docs/core/settings#avatars +::: + +Create a new 'Expression Policy' with the content below, adjusting the variables where required: + +```python +import base64 +import requests + +AVATAR_SIZE = "64" # Valid values: 16,32,64,128,256,512,1024 + +# Only change below here if you know what you are doing. +AVATAR_URL = "https://cdn.discordapp.com/avatars/{id}/{avatar}.png?site={avatar_size}" +AVATAR_STREAM_CONTENT = "data:image/png;base64,{base64_string}" # Converts base64 image into html syntax usable with authentik's avatar attributes feature + + +def get_as_base64(url): + """Returns the base64 content of the url""" + return base64.b64encode(requests.get(url).content) + + +def get_avatar_from_avatar_url(url): + """Returns an authentik-avatar-attributes-compatible string from an image url""" + cut_url = f"{url}?size=64" + return AVATAR_STREAM_CONTENT.format( + base64_string=(get_as_base64(cut_url).decode("utf-8")) + ) + + +# Ensure flow is only run during OAuth logins via Discord +if context["source"].provider_type != "discord": + return True + +user = request.user +userinfo = request.context["oauth_userinfo"] + +# Assigns the discord attributes to the user +user.attributes["discord"] = { + "id": userinfo["id"], + "username": userinfo["username"], + "discriminator": userinfo["discriminator"], + "email": userinfo["email"], + "avatar": userinfo["avatar"], + "avatar_url": ( + AVATAR_URL.format( + id=userinfo["id"], avatar=userinfo["avatar"], avatar_size=AVATAR_SIZE + ) + if userinfo["avatar"] + else None + ), +} + +# If the user has an avatar, assign it to the user +avatar_url = user.attributes["discord"].get("avatar_url", None) +if avatar_url is not None: + user.attributes["avatar"] = get_avatar_from_avatar_url(avatar_url) + +user.save() +return True + +``` + +Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source. diff --git a/website/integrations/sources/freeipa/01_user_create.png b/website/docs/sources/freeipa/01_user_create.png similarity index 100% rename from website/integrations/sources/freeipa/01_user_create.png rename to website/docs/sources/freeipa/01_user_create.png diff --git a/website/integrations/sources/freeipa/02_user_roles.png b/website/docs/sources/freeipa/02_user_roles.png similarity index 100% rename from website/integrations/sources/freeipa/02_user_roles.png rename to website/docs/sources/freeipa/02_user_roles.png diff --git a/website/integrations/sources/freeipa/03_add_user_role.png b/website/docs/sources/freeipa/03_add_user_role.png similarity index 100% rename from website/integrations/sources/freeipa/03_add_user_role.png rename to website/docs/sources/freeipa/03_add_user_role.png diff --git a/website/integrations/sources/freeipa/04_source_settings_1.png b/website/docs/sources/freeipa/04_source_settings_1.png similarity index 100% rename from website/integrations/sources/freeipa/04_source_settings_1.png rename to website/docs/sources/freeipa/04_source_settings_1.png diff --git a/website/integrations/sources/freeipa/05_source_settings_2.png b/website/docs/sources/freeipa/05_source_settings_2.png similarity index 100% rename from website/integrations/sources/freeipa/05_source_settings_2.png rename to website/docs/sources/freeipa/05_source_settings_2.png diff --git a/website/integrations/sources/freeipa/06_sync_source.png b/website/docs/sources/freeipa/06_sync_source.png similarity index 100% rename from website/integrations/sources/freeipa/06_sync_source.png rename to website/docs/sources/freeipa/06_sync_source.png diff --git a/website/integrations/sources/freeipa/07_password_stage.png b/website/docs/sources/freeipa/07_password_stage.png similarity index 100% rename from website/integrations/sources/freeipa/07_password_stage.png rename to website/docs/sources/freeipa/07_password_stage.png diff --git a/website/integrations/sources/freeipa/index.md b/website/docs/sources/freeipa/index.md similarity index 97% rename from website/integrations/sources/freeipa/index.md rename to website/docs/sources/freeipa/index.md index 1805113b77..b49d7e8a40 100644 --- a/website/integrations/sources/freeipa/index.md +++ b/website/docs/sources/freeipa/index.md @@ -16,7 +16,7 @@ The following placeholders will be used: 1. Log into FreeIPA. -2. Create a user in FreeIPA, matching your naming scheme. Provide a strong password, example generation methods: `pwgen 64 1` or `openssl rand -base64 36`. Once done click `Add and Edit`. +2. Create a user in FreeIPA, matching your naming scheme. Provide a strong password, example generation methods: `pwgen 64 1` or `openssl rand 36 | base64`. After you are done click **Add and Edit**. ![](./01_user_create.png) diff --git a/website/integrations/sources/github/github_org_membership.png b/website/docs/sources/github/github_org_membership.png similarity index 100% rename from website/integrations/sources/github/github_org_membership.png rename to website/docs/sources/github/github_org_membership.png diff --git a/website/integrations/sources/github/githubdeveloper1.png b/website/docs/sources/github/githubdeveloper1.png similarity index 100% rename from website/integrations/sources/github/githubdeveloper1.png rename to website/docs/sources/github/githubdeveloper1.png diff --git a/website/integrations/sources/github/githubdeveloperexample.png b/website/docs/sources/github/githubdeveloperexample.png similarity index 100% rename from website/integrations/sources/github/githubdeveloperexample.png rename to website/docs/sources/github/githubdeveloperexample.png diff --git a/website/integrations/sources/github/githubexample2.png b/website/docs/sources/github/githubexample2.png similarity index 100% rename from website/integrations/sources/github/githubexample2.png rename to website/docs/sources/github/githubexample2.png diff --git a/website/integrations/sources/github/index.md b/website/docs/sources/github/index.md similarity index 97% rename from website/integrations/sources/github/index.md rename to website/docs/sources/github/index.md index 3b4e5978ea..cf84d71a91 100644 --- a/website/integrations/sources/github/index.md +++ b/website/docs/sources/github/index.md @@ -47,7 +47,7 @@ Here is an example of a complete authentik Github OAuth Source Save, and you now have Github as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: ### Checking for membership of a GitHub Organisation diff --git a/website/integrations/sources/google/authentiksource.png b/website/docs/sources/google/authentiksource.png similarity index 100% rename from website/integrations/sources/google/authentiksource.png rename to website/docs/sources/google/authentiksource.png diff --git a/website/integrations/sources/google/googledeveloper1.png b/website/docs/sources/google/googledeveloper1.png similarity index 100% rename from website/integrations/sources/google/googledeveloper1.png rename to website/docs/sources/google/googledeveloper1.png diff --git a/website/integrations/sources/google/googledeveloper2.png b/website/docs/sources/google/googledeveloper2.png similarity index 100% rename from website/integrations/sources/google/googledeveloper2.png rename to website/docs/sources/google/googledeveloper2.png diff --git a/website/integrations/sources/google/googledeveloper3.png b/website/docs/sources/google/googledeveloper3.png similarity index 100% rename from website/integrations/sources/google/googledeveloper3.png rename to website/docs/sources/google/googledeveloper3.png diff --git a/website/integrations/sources/google/googledeveloper4.png b/website/docs/sources/google/googledeveloper4.png similarity index 100% rename from website/integrations/sources/google/googledeveloper4.png rename to website/docs/sources/google/googledeveloper4.png diff --git a/website/integrations/sources/google/googledeveloper5.png b/website/docs/sources/google/googledeveloper5.png similarity index 100% rename from website/integrations/sources/google/googledeveloper5.png rename to website/docs/sources/google/googledeveloper5.png diff --git a/website/integrations/sources/google/googledeveloper6.png b/website/docs/sources/google/googledeveloper6.png similarity index 100% rename from website/integrations/sources/google/googledeveloper6.png rename to website/docs/sources/google/googledeveloper6.png diff --git a/website/integrations/sources/google/index.md b/website/docs/sources/google/index.md similarity index 95% rename from website/integrations/sources/google/index.md rename to website/docs/sources/google/index.md index 188e95ef4d..8fd9557b20 100644 --- a/website/integrations/sources/google/index.md +++ b/website/docs/sources/google/index.md @@ -79,7 +79,7 @@ Here is an example of a complete authentik Google OAuth Source Save, and you now have Google as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: ## Username mapping @@ -99,4 +99,4 @@ return False Afterwards, edit the source's enrollment flow (by default _default-source-enrollment_), expand the policies bound to the first stage (_default-source-enrollment-prompt_), and bind the policy created above. Make sure the newly created policy comes before _default-source-enrollment-if-username_. Afterwards, any new logins will automatically have their google email address used as their username. -This can be combined with disallowing users from changing their usernames, see [Configuration](../../../docs/installation/configuration#authentik_default_user_change_username). +This can be combined with disallowing users from changing their usernames, see [Configuration](../../../docs/core/settings#allow-users-to-change-username). diff --git a/website/docs/sources/index.md b/website/docs/sources/index.md new file mode 100644 index 0000000000..6fefa3f7e6 --- /dev/null +++ b/website/docs/sources/index.md @@ -0,0 +1,26 @@ +--- +title: Sources +slug: /sources +--- + +Sources allow you to connect authentik to an external user directory. Sources can also be used with social login providers such as Facebook, Twitter, or GitHub. + +### Find your source + +Sources are in three general categories: + +- **Directory synchronization** (Active Directory, FreeIPA) +- **Protocols** (LDAP, OAuth, SAML, and SCIM) +- **Social logins** (Apple, Discord, Twitch, Twitter, and many others) + +For instructions to add a specific source, refer to the documentation links in the left navigation pane. + +### Add Sources to Default Login Page + +To have sources show on the default login screen you will need to add them to the flow. The process below assumes that you have not created or renamed the default stages and flows. + +1. In the Admin interface, navigate to the **Flows** section. +2. Click on **default-authentication-flow**. +3. Click the **Stage Bindings** tab. +4. Chose **Edit Stage** for the _default-authentication-identification_ stage. +5. Under **Sources** you should see the additional sources that you have configured. Click all applicable sources to have them displayed on the Login page. diff --git a/website/docs/sources/ldap/index.md b/website/docs/sources/ldap/index.md new file mode 100644 index 0000000000..1f87aae2f1 --- /dev/null +++ b/website/docs/sources/ldap/index.md @@ -0,0 +1,92 @@ +--- +title: LDAP Source +--- + +Sources allow you to connect authentik to an existing user directory. This source allows you to import users and groups from an LDAP Server. + +:::info +For Active Directory, follow the [Active Directory Integration](../active-directory/) + +For FreeIPA, follow the [FreeIPA Integration](../freeipa/) +::: + +## Configuration options for LDAP sources + +To create or edit a source in authentik, open the Admin interface and navigate to **Directory -> Ferderation and Social login**. There you can create a new LDAP source, or edit an existing one, using the following settings. + +- **Enabled**: Toggle this option on to allow authentik to use the defined LDAP source. + +- **Update internal password on login**: When the user logs in to authentik using the LDAP password backend, the password is stored as a hashed value in authentik. Toggle off (default setting) if you do not want to store the hashed passwords in authentik. + +- **Synch User**: Enable or disable user synchronization between authentik and the LDAP source. + +- **User password writeback**: Enable this option if you want to write password changes that are made in authentik back to LDAP. + +- **Synch groups**: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. + +- **Sync parent group**: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. + +#### Connection settings + +- **Server URI**: URI to your LDAP server/Domain Controller. You can specify multiple servers by separating URIs with a comma, like `ldap://ldap1.company,ldap://ldap2.company`. When using a DNS entry with multiple Records, authentik will select a random entry when first connecting. + + - **Enable StartTLS**: Enables StartTLS functionality. To use LDAPS instead, use port `636`. + - **Use Server URI for SNI verification**: this setting is required for servers using TLS 1.3+ + +- **TLS Verification Certificate**: Specify a keypair to validate the remote certificate. + +- **TLS Client authentication**: Client certificate keypair to authenticate against the LDAP Server's Certificate. + +- **Bind CN**: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`. + +- **Bind password**: Password used during the bind process. + +- **Base DN**: Base DN (distinguished name) used for all LDAP queries. + +#### LDAP Attribute mapping + +- **User Property mappings** and **Group Property Mappings**: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping). + +#### Additional Settings + +- **Group**: Parent group for all the groups imported from LDAP. + +- **User path**: Path template for all new users created. + +- **Addition User DN**: Prepended to the base DN for user queries. + +- **Addition Group DN**: Prepended to the base DN for group queries. + +- **User object filter**: Consider objects matching this filter to be users. + +- **Group object filter**: Consider objects matching this filter to be groups. + +- **Group membership field**: This field contains the user's group memberships. + +- **Object uniqueness field**: This field contains a unique identifier. + +## Property mappings + +LDAP property mappings can be used to convert the raw LDAP response into an authentik user/group. + +By default, authentik ships with [pre-configured mappings](../../property-mappings/index.md#ldap-property-mapping) for the most common LDAP setups. These mappings can be found on the LDAP Source Configuration page in the Admin interface. + +You can assign the value of a mapping to any user attribute, or save it as a custom attribute by prefixing the object field with `attribute.` Keep in mind though, data types from the LDAP server will be carried over. This means that with some implementations, where fields are stored as array in LDAP, they will be saved as array in authentik. To prevent this, use the built-in `list_flatten` function. + +## Password login + +By default, authentik doesn't update the password it stores for a user when they log in using their LDAP credentials. That means that if the LDAP server is not reachable by authentik, users will not be able to log in. This behavior can be turned on with the **Update internal password on login** setting on the LDAP source. + +:::note +Sources created prior to the 2024.2 release have this setting turned on by default. +::: + +Be aware of the following security considerations when turning on this functionality: + +- Updating the LDAP password does not invalid the password stored in authentik, however for LDAP Servers like FreeIPA and Active Directory, authentik will lock its internal password during the next LDAP sync. For other LDAP servers, the old passwords will still be valid indefinitely. +- Logging in via LDAP credentials overwrites the password stored in authentik if users have different passwords in LDAP and authentik. +- Custom security measures used to secure the password in LDAP may differ from the ones used in authentik. Depending on threat model and security requirements this could lead to unknowingly being non-compliant. + +## Troubleshooting + +To troubleshoot LDAP sources and their synchronization, see [LDAP Troubleshooting](../../../docs/troubleshooting/ldap_source). diff --git a/website/integrations/sources/mailcow/index.md b/website/docs/sources/mailcow/index.md similarity index 95% rename from website/integrations/sources/mailcow/index.md rename to website/docs/sources/mailcow/index.md index edcade2dd2..baffde79c8 100644 --- a/website/integrations/sources/mailcow/index.md +++ b/website/docs/sources/mailcow/index.md @@ -50,5 +50,5 @@ Here is an example of a complete authentik Mailcow OAuth Source Save, and you now have Mailcow as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: diff --git a/website/integrations/sources/mailcow/mailcow1.png b/website/docs/sources/mailcow/mailcow1.png similarity index 100% rename from website/integrations/sources/mailcow/mailcow1.png rename to website/docs/sources/mailcow/mailcow1.png diff --git a/website/integrations/sources/mailcow/mailcow2.png b/website/docs/sources/mailcow/mailcow2.png similarity index 100% rename from website/integrations/sources/mailcow/mailcow2.png rename to website/docs/sources/mailcow/mailcow2.png diff --git a/website/integrations/sources/mailcow/mailcow3.png b/website/docs/sources/mailcow/mailcow3.png similarity index 100% rename from website/integrations/sources/mailcow/mailcow3.png rename to website/docs/sources/mailcow/mailcow3.png diff --git a/website/integrations/sources/mailcow/mailcow4.png b/website/docs/sources/mailcow/mailcow4.png similarity index 100% rename from website/integrations/sources/mailcow/mailcow4.png rename to website/docs/sources/mailcow/mailcow4.png diff --git a/website/integrations/sources/mailcow/mailcow5.png b/website/docs/sources/mailcow/mailcow5.png similarity index 100% rename from website/integrations/sources/mailcow/mailcow5.png rename to website/docs/sources/mailcow/mailcow5.png diff --git a/website/integrations/sources/oauth/index.md b/website/docs/sources/oauth/index.md similarity index 95% rename from website/integrations/sources/oauth/index.md rename to website/docs/sources/oauth/index.md index 4a0014c469..12aec5bc07 100644 --- a/website/integrations/sources/oauth/index.md +++ b/website/docs/sources/oauth/index.md @@ -1,11 +1,7 @@ --- -title: OAuth +title: OAuth Source --- -:::note -All Integration-specific Sources are documented in the Integrations Section -::: - This source allows users to enroll themselves with an external OAuth-based Identity Provider. The generic provider expects the endpoint to return OpenID-Connect compatible information. Vendor-specific implementations have their own OAuth Source. - Policies: Allow/Forbid users from linking their accounts with this provider. diff --git a/website/integrations/sources/plex/index.md b/website/docs/sources/plex/index.md similarity index 90% rename from website/integrations/sources/plex/index.md rename to website/docs/sources/plex/index.md index 088b8d75a2..590f9df4d6 100644 --- a/website/integrations/sources/plex/index.md +++ b/website/docs/sources/plex/index.md @@ -23,5 +23,5 @@ Add _Plex_ as a _source_ Save, and you now have Plex as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: diff --git a/website/integrations/sources/saml/index.md b/website/docs/sources/saml/index.md similarity index 99% rename from website/integrations/sources/saml/index.md rename to website/docs/sources/saml/index.md index 7bc9453450..8b33e0c906 100644 --- a/website/integrations/sources/saml/index.md +++ b/website/docs/sources/saml/index.md @@ -1,5 +1,5 @@ --- -title: SAML +title: SAML Source --- This source allows authentik to act as a SAML Service Provider. Just like the SAML Provider, it supports signed requests. Vendor-specific documentation can be found in the Integrations Section. diff --git a/website/docs/sources/scim/index.md b/website/docs/sources/scim/index.md new file mode 100644 index 0000000000..5ef94ea12b --- /dev/null +++ b/website/docs/sources/scim/index.md @@ -0,0 +1,29 @@ +--- +title: SCIM Source +--- + +:::info +This feature is in technical preview, so please report any bugs on [GitHub](https://github.com/goauthentik/authentik/issues). +::: + +The SCIM source allows other applications to directly create users and groups within authentik. SCIM provides predefined schema for users and groups, with a RESTful API, to enable automatic user provisioning and deprovisioning, SCIM is supported by applications such as Microsoft Entra ID, Google Workspace, and Okta. + +The base SCIM URL is in the format of `https://authentik.company/source/scim//v2`. Authentication is done via Bearer tokens that are generated by authentik. When an SCIM source is created, a service account is created and a matching token is provided. + +## First steps + +To set up an SCIM source, log in as an administrator into authentik. Navigate to **Directory->Federation & Social login**, and click on **Create**. Select the **SCIM Source** type in the wizard, and give the source a name. + +After the source is created, click on the name of the source in the list, and you will see the **SCIM Base URL** which is used by the SCIM client. Use the **Click to copy token** button to copy the token which is used by the client to authenticate SCIM requests. + +## Supported Options & Resource types + +### `/v2/Users` + +Endpoint to list, create, update and delete users. + +### `/v2/Groups` + +Endpoint to list, create, update and delete groups. + +There is also the `/v2/ServiceProviderConfig` and `/v2/ResourceTypes`, which is used by SCIM-enabled applications to find out which features authentik supports. diff --git a/website/integrations/sources/twitch/index.md b/website/docs/sources/twitch/index.md similarity index 95% rename from website/integrations/sources/twitch/index.md rename to website/docs/sources/twitch/index.md index 7d4bc9b56b..577bc973c1 100644 --- a/website/integrations/sources/twitch/index.md +++ b/website/docs/sources/twitch/index.md @@ -56,5 +56,5 @@ Here is an example of a complete authentik Twitch OAuth Source Save, and you now have Twitch as a source. :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: diff --git a/website/integrations/sources/twitch/twitch1.png b/website/docs/sources/twitch/twitch1.png similarity index 100% rename from website/integrations/sources/twitch/twitch1.png rename to website/docs/sources/twitch/twitch1.png diff --git a/website/integrations/sources/twitch/twitch2.png b/website/docs/sources/twitch/twitch2.png similarity index 100% rename from website/integrations/sources/twitch/twitch2.png rename to website/docs/sources/twitch/twitch2.png diff --git a/website/integrations/sources/twitch/twitch3.png b/website/docs/sources/twitch/twitch3.png similarity index 100% rename from website/integrations/sources/twitch/twitch3.png rename to website/docs/sources/twitch/twitch3.png diff --git a/website/integrations/sources/twitch/twitch4.png b/website/docs/sources/twitch/twitch4.png similarity index 100% rename from website/integrations/sources/twitch/twitch4.png rename to website/docs/sources/twitch/twitch4.png diff --git a/website/integrations/sources/twitch/twitch5.png b/website/docs/sources/twitch/twitch5.png similarity index 100% rename from website/integrations/sources/twitch/twitch5.png rename to website/docs/sources/twitch/twitch5.png diff --git a/website/integrations/sources/twitter/index.md b/website/docs/sources/twitter/index.md similarity index 95% rename from website/integrations/sources/twitter/index.md rename to website/docs/sources/twitter/index.md index 8adca1344d..e6b778836f 100644 --- a/website/integrations/sources/twitter/index.md +++ b/website/docs/sources/twitter/index.md @@ -44,5 +44,5 @@ You will need to create a new project, and OAuth credentials in the Twitter Deve 5. **Consumer Secret:** Your Client Secret from step 25 :::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). +For more details on how-to have the new source display on the Login Page see [here](../index.md#add-sources-to-default-login-page). ::: diff --git a/website/integrations/sources/twitter/twitter1.png b/website/docs/sources/twitter/twitter1.png similarity index 100% rename from website/integrations/sources/twitter/twitter1.png rename to website/docs/sources/twitter/twitter1.png diff --git a/website/integrations/sources/twitter/twitter2.png b/website/docs/sources/twitter/twitter2.png similarity index 100% rename from website/integrations/sources/twitter/twitter2.png rename to website/docs/sources/twitter/twitter2.png diff --git a/website/docs/troubleshooting/emails.md b/website/docs/troubleshooting/emails.md index b3909a49b2..6a6dd9146c 100644 --- a/website/docs/troubleshooting/emails.md +++ b/website/docs/troubleshooting/emails.md @@ -8,7 +8,7 @@ Some hosting providers block outgoing SMTP ports, in which case you'll have to h To test if an email stage, or the global email settings are configured correctly, you can run the following command: -``` +```shell ak test_email [-S ] ``` @@ -16,12 +16,12 @@ If you omit the `-S` parameter, the email will be sent using the global settings To run this command with docker-compose, use -``` -docker-compose exec worker ak test_email [...] +```shell +docker compose exec worker ak test_email [...] ``` To run this command with Kubernetes, use -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak test_email [...] ``` diff --git a/website/docs/troubleshooting/forward_auth/general.mdx b/website/docs/troubleshooting/forward_auth/general.mdx index 80c23651ce..e03feb2748 100644 --- a/website/docs/troubleshooting/forward_auth/general.mdx +++ b/website/docs/troubleshooting/forward_auth/general.mdx @@ -29,7 +29,7 @@ Add the following block to your `.env` file: AUTHENTIK_LOG_LEVEL=trace ``` -Afterwards, run `docker-compose up -d`. +Afterwards, run `docker compose up -d`. diff --git a/website/docs/troubleshooting/ldap_source.md b/website/docs/troubleshooting/ldap_source.md index ee3f843efd..9b322cc45c 100644 --- a/website/docs/troubleshooting/ldap_source.md +++ b/website/docs/troubleshooting/ldap_source.md @@ -4,24 +4,24 @@ title: Troubleshooting LDAP Synchronization To troubleshoot LDAP sources, you can run the command below to run a synchronization in the foreground and see any errors or warnings that might happen directly -``` -docker-compose run --rm worker ldap_sync *slug of the source* +```shell +docker compose run --rm worker ldap_sync *slug of the source* ``` or, for Kubernetes, run -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak ldap_sync *slug of the source* ``` Starting with authentik 2023.10, you can also run command below to explicitly check the connectivity to the configured LDAP Servers: -``` -docker-compose run --rm worker ldap_check_connection *slug of the source* +```shell +docker compose run --rm worker ldap_check_connection *slug of the source* ``` or, for Kubernetes, run -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak ldap_check_connection *slug of the source* ``` diff --git a/website/docs/troubleshooting/login.md b/website/docs/troubleshooting/login.md index 58930706d9..49b40371c5 100644 --- a/website/docs/troubleshooting/login.md +++ b/website/docs/troubleshooting/login.md @@ -10,19 +10,19 @@ This recovery key will give whoever has the link direct access to your instances To create the key, run the following command: -``` -docker-compose run --rm server create_recovery_key 10 akadmin +```shell +docker compose run --rm server create_recovery_key 10 akadmin ``` For Kubernetes, run -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak create_recovery_key 10 akadmin ``` or, for CLI, run -``` +```shell ak create_recovery_key 10 akadmin ``` diff --git a/website/docs/troubleshooting/missing_admin_group.md b/website/docs/troubleshooting/missing_admin_group.md index a1e612dfdd..7fe015ba19 100644 --- a/website/docs/troubleshooting/missing_admin_group.md +++ b/website/docs/troubleshooting/missing_admin_group.md @@ -6,12 +6,12 @@ If all of the Admin groups have been deleted, or misconfigured during sync, you Run the following command, where _username_ is the user you want to add to the newly created group: -``` -docker-compose run --rm server create_admin_group username +```shell +docker compose run --rm server create_admin_group username ``` or, for Kubernetes, run -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak create_admin_group username ``` diff --git a/website/docs/troubleshooting/missing_permission.md b/website/docs/troubleshooting/missing_permission.md index 8257208d7f..d9c0ad5878 100644 --- a/website/docs/troubleshooting/missing_permission.md +++ b/website/docs/troubleshooting/missing_permission.md @@ -8,13 +8,13 @@ The error should be temporary and not occur after initial installation. If it does, you can run the following command to ensure all permissions exist: -``` -docker-compose run --rm worker repair_permissions +```shell +docker compose run --rm worker repair_permissions ``` or, for Kubernetes, run -``` +```shell kubectl exec -it deployment/authentik-worker -c authentik -- ak repair_permissions ``` diff --git a/website/docs/troubleshooting/postgres/upgrade_kubernetes.md b/website/docs/troubleshooting/postgres/upgrade_kubernetes.md index 5aac942357..be47140813 100644 --- a/website/docs/troubleshooting/postgres/upgrade_kubernetes.md +++ b/website/docs/troubleshooting/postgres/upgrade_kubernetes.md @@ -27,7 +27,7 @@ cd /bitnami/postgresql/ # Set the postgres password based on the `POSTGRES_POSTGRES_PASSWORD` environment variable export PGPASSWORD=$POSTGRES_POSTGRES_PASSWORD # Dump the authentik database into an sql file -pg_dump -U postgres $POSTGRES_DB > dump-11.sql +pg_dump -U $POSTGRES_USER $POSTGRES_DB > dump-11.sql ``` ### Stop PostgreSQL and start the upgrade @@ -88,7 +88,7 @@ Run the following commands to restore the data: cd /bitnami/postgresql/ # Set the Postgres password based on the `POSTGRES_POSTGRES_PASSWORD` environment variable. export PGPASSWORD=$POSTGRES_POSTGRES_PASSWORD -psql -U postgres $POSTGRES_DB < dump-11.sql +psql -U $POSTGRES_USER $POSTGRES_DB < dump-11.sql ``` After the last command finishes, all of the data is restored, and you can restart authentik. diff --git a/website/docs/user-group-role/access-control/flow-page.png b/website/docs/user-group-role/access-control/flow-page.png index fcf4e8318b..8b2636353f 100644 Binary files a/website/docs/user-group-role/access-control/flow-page.png and b/website/docs/user-group-role/access-control/flow-page.png differ diff --git a/website/docs/user-group-role/access-control/index.mdx b/website/docs/user-group-role/access-control/index.mdx index 720a494248..4ab437ad16 100644 --- a/website/docs/user-group-role/access-control/index.mdx +++ b/website/docs/user-group-role/access-control/index.mdx @@ -3,7 +3,6 @@ title: About access control --- import DocCardList from "@theme/DocCardList"; -import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; To comply with important regulations such as PCI-DSS, HIPAA, SOC 2, and GDPR, it's necessary to have the ability to control which users have access to specific areas of the system, what [permissions](./permissions.md) they have globally and on certain objects, and a way to monitor [events](../../events) related to user activity. @@ -13,4 +12,4 @@ RBAC is a way of ensuring the well-known [principal of least privilege](https:// To learn more about access control with authentik, refer to these topics: - + diff --git a/website/docs/user-group-role/access-control/manage_permissions.md b/website/docs/user-group-role/access-control/manage_permissions.md index c4a924c38a..1bbc995869 100644 --- a/website/docs/user-group-role/access-control/manage_permissions.md +++ b/website/docs/user-group-role/access-control/manage_permissions.md @@ -3,28 +3,26 @@ title: "Manage permissions" description: "Learn how to use global and object permissions in authentik." --- -Refer to the following topics for instructions to view and manage permissions. +Refer to the following topics for instructions to view and manage permissions. To learn more about the concepts and fundamanetals of authentik permissions, refer to [About Permissions](../access-control/permissions.md). ## View permissions You can view all permissions that are assigned to a user, group, role, flow, or stage. -### View user, group, and role permissions +### View user and role permissions -To view _object_ permissions for a specific user, role, or group: +To view _object_ permissions for a specific user or role: 1. Go to the Admin interface and navigate to **Directory**. -2. Select either **Users**, **Groups**, or **Roles** -3. Select a specific user/group/role by clicking on the name (this opens the details page). -4. Click the **Assigned Permissions** tab at the top of the page (to the right of the **Permissions** tab). -5. Scroll down to see both the global and object-level permissions. - -:::info -Note that groups do not have global permissions. -::: +2. Select either **Users** or **Roles** +3. Select a specific user/role by clicking on the name (this opens the details page). +4. Click the **Permissions** tab at the top of the page +5. Select the **Assigned global permissions** sub-tab to see global permissions and the **Assigned object permissions** sub-tab to see the object-level permissions. ### View flow permissions +\_These instructions apply to all objects that have a detail page, which can be accessed by clicking on the name in the list page.\_\_ + 1. Go to the Admin interface and navigate to **Flows and Stages -> Flows**. 2. Click the name of the flow (this opens the details page). 3. Click the **Permissions** tab at the top of the page. @@ -32,9 +30,11 @@ Note that groups do not have global permissions. ### View stage permissions -1. Go to the Admin interface and navigate to **Flows and Stages -> Stagess**. -2. On the row for the specific stage whose permissions you want to view, click the lock icon. -3. On the **Update Permissions** tab, you can view the assigned permissions using the **User Object Permissions** and the **Role Object Permissions** tabs. +\_These instructions apply to all objects that **do not** have a detail page.\_\_ + +1. Go to the Admin interface and navigate to **Flows and Stages -> Stages**. +2. On the row for the specific stage whose permissions you want to view, click the **lock icon**. +3. On the **Update Permissions** window, you can view the assigned permissions using the **User Object Permissions** and the **Role Object Permissions** tabs. ## Manage permissions @@ -48,21 +48,25 @@ To assign or remove _object_ permissions for a specific user: 2. Select a specific user by clicking on the user's name. 3. Click the **Permissions** tab at the top of the page. 4. To assign or remove permissions that another _user_ has on this specific user: - 1. Click the **User Object Permissions** tab, click **Assign to new user**. + 1. Click the **User Object Permissions** tab, and then click **Assign to new user**. 2. In the **User** drop-down, select the user object. 3. Use the toggles to set which permissions on that selected user object you want to grant to (or remove from) the specific user. 4. Click **Assign** to save your settings and close the modal. 5. To assign or remove permissions that another _role_ has on this specific user: - Click the **Role Object Permissions** tab, click **Assign to new role**. 2. In the **User** drop-down, select the user object. 3. Use the toggles to set which permissions you want to grant to (or remove from) the selected role. 4. Click **Assign** to save your settings and close the modal. + 1. Click the **Role Object Permissions** tab, and then click **Assign to new role**. + 2. In the **User** drop-down, select the user object. + 3. Use the toggles to set which permissions you want to grant to (or remove from) the selected role. + 4. Click **Assign** to save your settings and close the modal. To assign or remove _global_ permissions for a user: 1. Go to the Admin interface and navigate to **Directory -> Users**. 2. Select a specific user the clicking on the user's name. -3. Click the **Assigned Permissions** tab at the top of the page (to the right of the **Permissions** tab). -4. In the **Assigned Global Permissions** area, click **Assign Permission**. -5. In the **Assign permissions to user** modal, click the plus sign (**+**) and then click the checkbox beside each permission that you want to assign to the user. To remove permissions, deselect the checkbox. -6. Click **Add**, and then click **Assign** to save your changes and close the modal. +3. Click the **Permissions** tab at the top of the page. +4. Click **Assigned Global Permissions** to the left. +5. In the **Assign permissions** area, click **Assign Permission**. +6. In the **Assign permission to user** modal box, click the plus sign (**+**) and then click the checkbox beside each permission that you want to assign to the user. To remove permissions, deselect the checkbox. +7. Click **Add**, and then click **Assign** to save your changes and close the modal. ### Assign or remove permissions on a specific group @@ -74,15 +78,18 @@ Also there are no global permissions for groups. To assign or remove _object_ permissions on a specific group by users and roles: 1. Go to the Admin interface and navigate to **Directory -> Groups**. -2. Select a specific group by clicking the the group's name. +2. Select a specific group by clicking the group's name. 3. Click the **Permissions** tab at the top of the page. To assign or remove permissions that another _user_ has on this specific group: - 1. Click the **User Object Permissions** tab, click **Assign to new user**. + 1. Click **User Object Permissions** to the left, and then click **Assign to new user**. 2. In the **User** drop-down, select the user object. 3. Use the toggles to set which permissions on that selected group you want to grant to (or remove from) the specific user. 4. Click **Assign** to save your settings and close the modal. 4. To assign or remove permissions that another _role_ has on this specific group: - Click the **Role Object Permissions** tab, click **Assign to new role**. 2. In the **Role** drop-down, select the role. 3. Use the toggles to set which permissions you want to grant to (or remove from ) the selected role. 4. Click **Assign** to save your settings and close the modal. + 1. Click **Role Object Permissions** to the left, and then click **Assign to new role**. + 2. In the **Role** drop-down, select the role. + 3. Use the toggles to set which permissions you want to grant to (or remove from ) the selected role. + 4. Click **Assign** to save your settings and close the modal. ### Assign or remove permissions for a specific role @@ -91,16 +98,23 @@ To assign or remove _object_ permissions for a specific role: 1. Go to the Admin interface and navigate to **Directory -> Roles**. 2. Select a specific role the clicking on the role's name. 3. Click the **Permissions** tab at the top of the page. - To assign or remove permissions that another _user_ has on this specific role: 1. Click the **User Object Permissions** tab, click **Assign to new user**. 2. In the **User** drop-down, select the user object. 3. Use the toggles to set which permissions on that role you want to grant to (or remove from) the selected user. 4. Click **Assign** to save your settings and close the modal. + To assign or remove permissions that another _user_ has on this specific role: + 1. Click **User Object Permissions** to the left, and then click **Assign to new user**. + 2. In the **User** drop-down, select the user object. + 3. Use the toggles to set which permissions on that role you want to grant to (or remove from) the selected user. + 4. Click **Assign** to save your settings and close the modal. 4. To assign or remove permissions that another _role_ has on this specific group: - Click the **Role Object Permissions** tab, click **Assign to new role**. 2. In the **Role** drop-down, select the role. 3. Use the toggles to set which permissions you want to grant to (or remove from) the selected role. 4. Click **Assign** to save your settings and close the modal. + 1. Click **Role Object Permissions** to the left, and then click **Assign to new role**. + 2. In the **Role** drop-down, select the role. + 3. Use the toggles to set which permissions you want to grant to (or remove from) the selected role. + 4. Click **Assign** to save your settings and close the modal. To assign or remove _global_ permissions for a role: 1. Go to the Admin interface and navigate to **Directory -> Roles**. 2. Select a specific role by clicking on the role's name. -3. The **Overview** tab at the top of the page displays all assigned global permissions for the role. -4. In the **Assigned Global Permissions** area, click **Assign Permission**. +3. Click the **Permissions** tab at the top of the page. +4. Click **Assigned Global Permissions** to the left, and then click **Assign Permission**. 5. In the **Assign permissions to role** modal, click the plus sign (**+**) and then click the checkbox beside each permission that you want to assign to the role. To remove permissions, deselect the checkbox. 6. Click **Assign** to save your changes and close the modal. @@ -114,5 +128,5 @@ To assign or remove _global_ permissions for a role: ### Assign or remove stage permissions 1. Go to the Admin interface and navigate to **Flows and Stages -> Stagess**. -2. On the row for the specific stage that you want to manage permissions, click the lock icon. -3. On the **Update Permissions** tab, you can add or remove the assigned permissions using the **User Object Permissions** and the **Role Object Permissions** tabs. +2. On the row for the specific stage that you want to manage permissions, click the **lock icon**. +3. On the **Update Permissions** modal window, you can add or remove the assigned permissions using the **User Object Permissions** and the **Role Object Permissions** tabs. diff --git a/website/docs/user-group-role/access-control/permissions.md b/website/docs/user-group-role/access-control/permissions.md index 57c0f7ae87..a20d53e5ef 100644 --- a/website/docs/user-group-role/access-control/permissions.md +++ b/website/docs/user-group-role/access-control/permissions.md @@ -6,9 +6,11 @@ description: "Learn about global and object permissions in authentik." Permissions are the central components in all access control systems, the lowest-level components, the controlling pieces of access data. Permissions are assigned to (or removed from!) to define exactly WHO can do WHAT to WHICH part of the overall software system. :::info -Note that global and object permissions only apply to objects within authentik, and not to who can access certain applications (which are access-controlled using [policies](../../policies/index.md). +Note that global and object permissions only apply to objects within authentik, and not to who can access certain applications (which are access-controlled using [policies](../../policies/index.md)). ::: +For instructions to add, remove, and manage permissions, refer to [Manage Permissions](../access-control/manage_permissions.md). + ## Fundamentals of authentik permissions There are two main types of permissions in authentik: @@ -29,16 +31,16 @@ Object permissions have two categories: - **_User_ object permissions**: defines WHO (which user) can change the **_object_** - **_Role_ object permissions**: defines which ROLE can change the **_object_** -Object permissions are assigned, as the name indicates, to an object (users, [groups](../groups/index.mdx), roles, flows, and stages), and the assigned permissions state exactly what a user or role can do TO the object (i.e. what permissions does the user or role have on that object). +Object permissions are assigned, as the name indicates, to an object ([users](../user/index.mdx), [groups](../groups/index.mdx), [roles](../roles/index.mdx), [flows](../../flow/index.md), and stages), and the assigned permissions state exactly what a user or role can do TO the object (i.e. what permissions does the user or role have on that object). -When working with object permissions, it is important to understand that when you are viewing the page for an object the permissions table shows which users or roles have permissions ON that object. Those permissions describe what those users or roles can do TO the object detailed on the page. +When working with object permissions it is important to understand that when you are viewing the page for an object, the permissions table shows which users or roles have permissions ON that specific object. Those permissions describe what those users or roles can do TO the object detailed on the page. -For example, the UI below shows a user page for the user named Peter. +For example, the Admin interface UI shown below shows a user page for the user named Peter. ![](./user-page.png) -You can see in the **User Object Permissions** table that another user, roberto, has permissions on Peter (that is, on the user object Peter). +You can see in the **User Object Permissions** table that the Admin user (`akadmin`) and one other user (roberto) has permissions on Peter (that is, on the user object named Peter). -Looking at another example, with a flow object called `default-recovery-flow` you can see that the Admin user (akadmin) has all object permissions on the flow, but roberto only has a few permissions on that flow. +Looking at another example, with a flow object called `default-recovery-flow`, you can see that the Admin user (akadmin) has all object permissions on the flow, but roberto only has a few permissions on that flow. ![](./flow-page.png) diff --git a/website/docs/user-group-role/access-control/user-page.png b/website/docs/user-group-role/access-control/user-page.png index 904062b974..942ade2f73 100644 Binary files a/website/docs/user-group-role/access-control/user-page.png and b/website/docs/user-group-role/access-control/user-page.png differ diff --git a/website/docs/user-group-role/groups/manage_groups.md b/website/docs/user-group-role/groups/manage_groups.md index 990bcaaf32..7ff56ceb44 100644 --- a/website/docs/user-group-role/groups/manage_groups.md +++ b/website/docs/user-group-role/groups/manage_groups.md @@ -34,12 +34,23 @@ To delete a group, follow these steps: 2. Select the checkbox beside the name of the group that you want to delete. 3. Click **Delete**. -## Assign, modify, or remove permissions for a group - -You can grant a group specific global or object-level permissions. Any user who is a member of a group inherits all of the group's permissions. - -For more information, review ["Permissions"](../access-control/permissions.md). - ## Assign a role to a group You can assign a role to a group, and then all users in the group inherit the permissions assigned to that role. For instructions and more information, see ["Assign a role to a group"](../roles/manage_roles.md#assign-a-role-to-a-group). + +## Delegating group member management + +:::info +Requires authentik 2024.4 +::: + +To give a specific Role or User the ability to manage group members, the following permissions need to be granted on the matching Group object: + +- Can view group +- Can add user to group +- Can remove user from group +- Can access admin interface (for managing a group's user within the authentik Admin interface) + +In addition, the permission "Can view User" needs to be assigned, either globally or on specific users that should be manageable. + +These permissions can be assigned to a [Role](../roles/index.mdx) or directly to a [User](../user/index.mdx). diff --git a/website/docs/user-group-role/roles/index.mdx b/website/docs/user-group-role/roles/index.mdx index 19d179780d..ddda83ee7f 100644 --- a/website/docs/user-group-role/roles/index.mdx +++ b/website/docs/user-group-role/roles/index.mdx @@ -3,7 +3,6 @@ title: About roles --- import DocCardList from "@theme/DocCardList"; -import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; Roles are a way to simplify the assignment of permissions. Roles are also the backbone of role-based access control (RBAC), an industry standard for managing [access control](../access-control). In authentik, RBAC is how you manage access to system components and specific objects such as flows, stages, users, etc. @@ -17,4 +16,4 @@ The easiest workflow for setting up these new users involves [creating a role](. To learn more about working with roles in authentik, refer to the following topics: - + diff --git a/website/docs/user-group-role/user/index.mdx b/website/docs/user-group-role/user/index.mdx index 9f15e85ffb..7c1bec394d 100644 --- a/website/docs/user-group-role/user/index.mdx +++ b/website/docs/user-group-role/user/index.mdx @@ -3,10 +3,9 @@ title: About users --- import DocCardList from "@theme/DocCardList"; -import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; In authentik you can create and manage users with fine-tuned access control, session and event details, group membership, super-user rights, impersonation, and password management and recovery. To learn more about working with users in authentik, refer to the following topics: - + diff --git a/website/docs/user-group-role/user/invitations.md b/website/docs/user-group-role/user/invitations.md index e3e58f42e9..bbb8736b26 100644 --- a/website/docs/user-group-role/user/invitations.md +++ b/website/docs/user-group-role/user/invitations.md @@ -17,7 +17,7 @@ The fastest way to create an invitation is to use our pre-defined `default-enrol To download the `default-enrollment-flow` file, run this command: -``` +```shell wget https://goauthentik.io/blueprints/example/flows-enrollment-2-stage.yaml ``` diff --git a/website/docs/user-group-role/user/user_basic_operations.md b/website/docs/user-group-role/user/user_basic_operations.md index 3955b53043..04328dcd41 100644 --- a/website/docs/user-group-role/user/user_basic_operations.md +++ b/website/docs/user-group-role/user/user_basic_operations.md @@ -4,9 +4,11 @@ title: Manage users The following topics are for the basic management of users: how to create, modify, delete or deactivate users, and using a recovery email. +[Policies](../../policies/index.md) can be used to further manage how users are authenticated. For example, by default authentik does not require email addresses be unique, but you can use a policy to [enforce unique email addresses](../../policies/working_with_policies/unique_email.md). + ### Create a user -> If you want to automate user creation, you can do that either by [invitations](./invitations.md), [`user_write` stage](../../flow/stages/user_write), or [using the API](/developer-docs/api/browser). +> If you want to automate user creation, you can do that either by [invitations](./invitations.md), [`user_write` stage](../../flow/stages/user_write), or [using the API](/developer-docs/api/reference/core-users-create). 1. In the Admin interface of your authentik instance, select **Directory > Users** in the left side menu. 2. Select the folder where you want to create a user. diff --git a/website/docs/user-group-role/user/user_ref.md b/website/docs/user-group-role/user/user_ref.md index 88d8a3af5c..6d0993978d 100644 --- a/website/docs/user-group-role/user/user_ref.md +++ b/website/docs/user-group-role/user/user_ref.md @@ -70,6 +70,14 @@ Optional flag, when set to false, Tokens created by the user will not expire. Only applies when the token creation is triggered by the user with this attribute set. Additionally, the flag does not apply to superusers. +### `goauthentik.io/user/token-maximum-lifetime`: + +Optional flag, when set, defines the maximum lifetime of user-created tokens. Defaults to the system setting if not set. + +Only applies when `goauthentik.io/user/token-expires` set to true. + +Format is string of format `days=10;hours=1;minute=3;seconds=5`. + ### `goauthentik.io/user/debug`: See [Troubleshooting access problems](../../troubleshooting/access), when set, the user gets a more detailed explanation of access decisions. @@ -85,11 +93,11 @@ underneath `additionalHeaders`: #### Example: -``` +```yaml additionalHeaders: - REMOTE-USER: joe.smith - REMOTE-EMAIL: joe@jsmith.com - REMOTE-NAME: Joseph + REMOTE-USER: joe.smith + REMOTE-EMAIL: joe@jsmith.com + REMOTE-NAME: Joseph ``` These headers will now be passed to the application when the user logs in. Most applications will need to be configured to accept these headers. Some examples of applications that can accept additional headers from an authentik Proxy Provider are [Grafana](https://grafana.com/docs/grafana/latest/auth/auth-proxy/) and [Tandoor Recipes](https://docs.tandoor.dev/features/authentication/). diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index aca3c94552..d59a752334 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -1,19 +1,18 @@ -const fs = require("fs").promises; import type { Config } from "@docusaurus/types"; import type * as Preset from "@docusaurus/preset-classic"; +import { themes as prismThemes } from "prism-react-renderer"; +import type * as OpenApiPlugin from "docusaurus-plugin-openapi-docs"; module.exports = async function (): Promise { const remarkGithub = (await import("remark-github")).default; const defaultBuildUrl = (await import("remark-github")).defaultBuildUrl; - const footerEmail = await fs.readFile("src/footer.html", { - encoding: "utf-8", - }); return { title: "authentik", tagline: "Bring all of your authentication into a unified platform.", - url: "https://goauthentik.io", + url: "https://docs.goauthentik.io", baseUrl: "/", onBrokenLinks: "throw", + onBrokenAnchors: "throw", favicon: "img/icon.png", organizationName: "Authentik Security Inc.", projectName: "authentik", @@ -23,9 +22,16 @@ module.exports = async function (): Promise { logo: { alt: "authentik logo", src: "img/icon_left_brand.svg", + href: "https://goauthentik.io/", + target: "_self", }, items: [ - { to: "blog", label: "Blog", position: "left" }, + { + to: "https://goauthentik.io/blog", + label: "Blog", + position: "left", + target: "_self", + }, { to: "docs/", label: "Docs", @@ -42,9 +48,10 @@ module.exports = async function (): Promise { position: "left", }, { - to: "pricing/", + to: "https://goauthentik.io/pricing/", label: "Pricing", position: "left", + target: "_self", }, { href: "https://github.com/goauthentik/authentik", @@ -61,68 +68,7 @@ module.exports = async function (): Promise { ], }, footer: { - links: [ - { - title: "Subscribe to authentik News", - items: [ - { - html: footerEmail, - }, - ], - }, - { - title: "Documentation", - items: [ - { - label: "Documentation", - to: "docs/", - }, - { - label: "Integrations", - to: "integrations/", - }, - { - label: "Developer Documentation", - to: "developer-docs/", - }, - { - label: "Installations", - to: "docs/installation/", - }, - ], - }, - { - title: "More", - items: [ - { - to: "jobs/", - label: "Jobs", - position: "left", - }, - { - label: "GitHub", - href: "https://github.com/goauthentik/authentik", - }, - { - label: "Discord", - href: "https://goauthentik.io/discord", - }, - ], - }, - { - title: "Legal", - items: [ - { - to: "legal/terms", - label: "Terms & Conditions", - }, - { - to: "legal/privacy-policy", - label: "Privacy policy", - }, - ], - }, - ], + links: [], copyright: `Copyright © ${new Date().getFullYear()} Authentik Security Inc. Built with Docusaurus.`, }, tableOfContents: { @@ -137,6 +83,8 @@ module.exports = async function (): Promise { indexName: "goauthentik", }, prism: { + theme: prismThemes.oneLight, + darkTheme: prismThemes.oneDark, additionalLanguages: ["python", "diff", "json"], }, }, @@ -146,7 +94,7 @@ module.exports = async function (): Promise { { docs: { id: "docs", - sidebarPath: require.resolve("./sidebars.js"), + sidebarPath: "./sidebars.js", editUrl: "https://github.com/goauthentik/authentik/edit/main/website/", remarkPlugins: [ @@ -156,7 +104,8 @@ module.exports = async function (): Promise { repository: "goauthentik/authentik", // Only replace issues and PR links buildUrl: function (values) { - return values.type === "issue" + return values.type === "issue" || + values.type === "mention" ? defaultBuildUrl(values) : false; }, @@ -167,15 +116,6 @@ module.exports = async function (): Promise { theme: { customCss: require.resolve("./src/css/custom.css"), }, - gtag: { - trackingID: "G-9MVR9WZFZH", - anonymizeIP: true, - }, - blog: { - showReadingTime: true, - blogSidebarTitle: "All our posts", - blogSidebarCount: "ALL", - }, } satisfies Preset.Options, ], ], @@ -186,7 +126,7 @@ module.exports = async function (): Promise { id: "docsIntegrations", path: "integrations", routeBasePath: "integrations", - sidebarPath: require.resolve("./sidebarsIntegrations.js"), + sidebarPath: "./sidebarsIntegrations.js", editUrl: "https://github.com/goauthentik/authentik/edit/main/website/", }, @@ -197,25 +137,33 @@ module.exports = async function (): Promise { id: "docsDevelopers", path: "developer-docs", routeBasePath: "developer-docs", - sidebarPath: require.resolve("./sidebarsDev.js"), + sidebarPath: "./sidebarsDev.js", + docItemComponent: "@theme/ApiItem", editUrl: "https://github.com/goauthentik/authentik/edit/main/website/", }, ], + [ + "docusaurus-plugin-openapi-docs", + { + id: "api", + docsPluginId: "docsDevelopers", + config: { + authentik: { + specPath: "static/schema.yaml", + outputDir: "developer-docs/api/reference/", + hideSendButton: true, + sidebarOptions: { + groupPathsBy: "tag", + }, + } satisfies OpenApiPlugin.Options, + }, + }, + ], ], markdown: { mermaid: true, }, - themes: ["@docusaurus/theme-mermaid"], - scripts: [ - { - src: "https://goauthentik.io/js/script.js", - async: true, - "data-domain": "goauthentik.io", - }, - { - src: "https://boards.greenhouse.io/embed/job_board/js?for=authentiksecurity", - }, - ], + themes: ["docusaurus-theme-openapi-docs"], }; }; diff --git a/website/docusaurus.docs-only.ts b/website/docusaurus.docs-only.ts deleted file mode 100644 index 04c05682cf..0000000000 --- a/website/docusaurus.docs-only.ts +++ /dev/null @@ -1,129 +0,0 @@ -const config = require("./docusaurus.config"); -import type { Config } from "@docusaurus/types"; - -module.exports = async function (): Promise { - const remarkGithub = (await import("remark-github")).default; - const defaultBuildUrl = (await import("remark-github")).defaultBuildUrl; - const mainConfig = await config(); - return { - title: "authentik", - tagline: "Making authentication simple.", - url: "https://goauthentik.io", - baseUrl: "/if/help/", - onBrokenLinks: "ignore", - favicon: "img/icon.png", - organizationName: "BeryJu", - projectName: "authentik", - themeConfig: { - navbar: { - logo: { - alt: "authentik logo", - src: "img/icon_left_brand.svg", - }, - items: [ - { - to: "docs/", - activeBasePath: "docs", - label: "Docs", - position: "left", - }, - { - to: "integrations/", - activeBasePath: "integrations", - label: "Integrations", - position: "left", - }, - { - to: "developer-docs/", - activeBasePath: "developer-docs", - label: "Developer Docs", - position: "left", - }, - { - href: "https://github.com/goauthentik/authentik", - label: "GitHub", - position: "right", - }, - { - href: "https://goauthentik.io/discord", - label: "Discord", - position: "right", - }, - ], - }, - footer: { - links: [], - copyright: mainConfig.themeConfig.footer.copyright, - }, - colorMode: mainConfig.themeConfig.colorMode, - tableOfContents: mainConfig.themeConfig.tableOfContents, - prims: mainConfig.themeConfig.prism, - }, - presets: [ - [ - "@docusaurus/preset-classic", - { - docs: { - id: "docs", - sidebarPath: require.resolve("./sidebars.js"), - editUrl: - "https://github.com/goauthentik/authentik/edit/main/website/", - remarkPlugins: [ - [ - remarkGithub, - { - repository: "goauthentik/authentik", - // Only replace issues and PR links - buildUrl: function (values) { - return values.type === "issue" - ? defaultBuildUrl(values) - : false; - }, - }, - ], - ], - }, - pages: false, - theme: { - customCss: require.resolve("./src/css/custom.css"), - }, - }, - ], - ], - plugins: [ - [ - "@docusaurus/plugin-content-docs", - { - id: "docsIntegrations", - path: "integrations", - routeBasePath: "integrations", - sidebarPath: require.resolve("./sidebarsIntegrations.js"), - editUrl: - "https://github.com/goauthentik/authentik/edit/main/website/", - }, - ], - [ - "@docusaurus/plugin-content-docs", - { - id: "docsDevelopers", - path: "developer-docs", - routeBasePath: "developer-docs", - sidebarPath: require.resolve("./sidebarsDev.js"), - editUrl: - "https://github.com/goauthentik/authentik/edit/main/website/", - }, - ], - [ - "@docusaurus/plugin-client-redirects", - { - redirects: [ - { - to: "/docs/", - from: ["/"], - }, - ], - }, - ], - ], - }; -}; diff --git a/website/integrations/_template/service.md b/website/integrations/_template/service.md index 58a9a1019d..7d49bae2e8 100644 --- a/website/integrations/_template/service.md +++ b/website/integrations/_template/service.md @@ -4,11 +4,11 @@ title: Service Name Support level: Community -## What is Service Name +## What is Service-Name > Insert a quick overview of what Service Name is and what it does > -> -- https://service.name +> -- https://service.xyz ## Preparation @@ -17,10 +17,18 @@ The following placeholders will be used: - `service.company` is the FQDN of the Service install. (Remove this for SaaS) - `authentik.company` is the FQDN of the authentik install. -## Service Configuration +## Service configuration Insert Service configuration -## authentik Configuration +1. Write first step here... + +2. Continue with steps.... + +## authentik configuration Insert authentik configuration + +1. Write first step here... + +2. Continue with steps.... diff --git a/website/integrations/apps-logo.png b/website/integrations/apps-logo.png new file mode 100644 index 0000000000..cc0ba49b13 Binary files /dev/null and b/website/integrations/apps-logo.png differ diff --git a/website/integrations/index.mdx b/website/integrations/index.mdx new file mode 100644 index 0000000000..acb13d7d88 --- /dev/null +++ b/website/integrations/index.mdx @@ -0,0 +1,20 @@ +--- +title: Integrations overview +slug: / +--- + +There are two main types of integrations with authentik: **Applications** and **Sources**. + +## Applications + +authentik integrates with many applications. For a full list, and to learn more about adding documentation for a new application, refer to the [Applications](../integrations/services/index.mdx) documentation. + +![](./apps-logo.png) + +## Sources + +In addition to applications, authentik also integrates with external sources, including federated directories like Active Directory and through protocols such as LDAP, OAuth, SAML, and SCIM sources. Sources are a way for authentik to use external credentials for authentication and verification. Sources in authentik can also be used for social logins, using external providers such as Facebook, Twitter, etc. + +To learn more, refer to the [Sources](../docs/sources) documentation. + +![](./sources-logo.png) diff --git a/website/integrations/services/fortigate-admin/index.md b/website/integrations/services/fortigate-admin/index.md new file mode 100644 index 0000000000..cbcec271a3 --- /dev/null +++ b/website/integrations/services/fortigate-admin/index.md @@ -0,0 +1,105 @@ +--- +title: FortiGate Admin Login +--- + +Support level: Community + +## What is FortiGate + +> FortiGate is a firewall from FortiNet. It is a NGFW with layer7 inspection and able to become a part of a FortiNet security fabric. +> -- https://www.fortinet.com/products/next-generation-firewall +> +> This guide explains how to setup a FortiGate to use authentik as SAML provider for Admin Login. It does not cover how to setup SSLVPN logins, that is a different configuration. + +## Preparation + +The following placeholders will be used: + +- `fgt.company` is the FQDN of the FortiGate install. +- `authentik.company` is the FQDN of the authentik install. +- `fgt.mapping` is the name of the SAML Property Mapping. +- `ak.cert` = The authentik self-signed certificate you use for the service provider. + +> [!IMPORTANT] +> If you have changed the port of the admin login from 443 to anything else you have to append it behind `fgt.company`. So f.e. `fgt.company:10443`. + +## Custom Property Mapping + +Create a new SAML Property Mapping under the Customization settings. + +- `fgt.mapping` is the value for the Name. +- `username` is the value for the SAML Attribute Name. +- `return request.user.email` is the value for the Expression. + +Create an application and SAML provider in authentik, and note the slug, because this will be used later. Create a SAML provider with the following parameters: + +Provider: + +- ACS URL: `https://fgt.company/saml/?acs` +- Issuer: `https://authentik.company` +- Service Provider Binding: Post +- Audience: `https://fgt.company/metadata/` +- Signing Certificate: `ak.cert` +- Property mappings: `fgt.mapping` + +You can of course adjust durations. + +Application: + +- Name: `Fortigate` +- Slug: `fortigate` +- Launch URL: `https://fgt.company/` + +## FortiGate Configuration + +Navigate to `https://fgt.company/ng/system/certificate` and Import the Certificate `ak.cert` to the FortiGate. +Then navigate to `https://fgt.company/fabric-connector/edit/security-fabric-connection` and select `Single Sign-On Settings` to configure SAML. + +- Select `Service Provider (SP)` under Mode to enable SAML authentication. +- Set the `SP Address` to the FortiGate FQDN `fgt.company`. (This gives you the URLs to configure in authentik) +- Set the `Default Login Page` to either `Normal` or `Single-Sign On`. (Normal allows both local and SAML authentication vs only SAML SSO.) + +FortiGate creates a new user by default if one does not exist, so you will need to set the Default Admin Profile to the permissions you want any new users to have. (I have created a `no_permissions` profile to assign by default.) + +Under `SP Details` set the **SP entity ID** to `https`. Note it for later use (this is your Audience value of the authentik SP-provider). + +> [!IMPORTANT] +> On both `IdP Login and Logout URL` change the `` to your own from the authentik application you have created. + +- Set `IdP Type` to `Custom` +- Set `IdP entity ID` to `https://authentik.company` +- Set `IdP Login URL` to `https://authentik.company/application/saml//sso/binding/redirect/` +- Set `IdP Logout URL` to `https://authentik.company/application/saml//slo/binding/redirect/` +- Set `IdP Certificate` to `ak.cert` + +## Troubleshooting + +These are just suggestions of what **could** be the cause of an issue and how to enable debug on the FortiGate. + +**Enabling debug on the FortiGate** +You can use the following commands on the FortiGate to enable debugging: + +1. Debug saml daemon + This will provide all possible output from the SAML daemon. + `diag debug application samld -1` + +2. Enable debug timestamps (optional) + `diagnose debug console timestamp enable` + +3. Enabling debug output + Before you can see any output you need to enable the debug mode. + `diagnose debug enable` + +4. If you used SSO Login only instead of Normal and you are not able to log in again, you can try one of the following methods: + +**Method 1**: +Open this URL (`https://fgt.company/saml/?acs`) in a browser and choose `Login Locally`. + +**Method 2**: +Open the CLI and set the login page back to normal. + +```bash +config system saml + set default-login-page normal +end +``` diff --git a/website/integrations/services/fortigate-ssl/index.md b/website/integrations/services/fortigate-ssl/index.md new file mode 100644 index 0000000000..62a4ada185 --- /dev/null +++ b/website/integrations/services/fortigate-ssl/index.md @@ -0,0 +1,238 @@ +--- +title: FortiGate SSLVPN +--- + +Support level: Community + +## FortiGate SSLVPN + +> FortiGate is a firewall from FortiNet. It is a NGFW with layer7 inspection and able to become a part of a FortiNet security fabric. +> -- https://www.fortinet.com/products/next-generation-firewall +> +> This guide explains how to setup a FortiGate to use authentik with a SAML provider for SSLVPN authentication. It does not cover how to setup SAML for admin logins, that is a different configuration. If you need to setup SAML for admin logins see the FortiGate admin guide. +> +> This guide has been created using the following software versions. Instructions may differ between versions. +> +> - Fortigate: 7.2.8 +> - authentik: 2024.2.2 + +## Assumptions + +- You know how to configure an SSLVPN in a FortiGate. +- You already have a certificate for signing and encryption uploaded to both authentik and the FortiGate. +- You already have a working SSLVPN (either portal or tunnel) and is just changing authentication from what you are using today to authentik SAML. + +The following placeholders will be used: + +- `saml.sp.name` = The name that will be the SAML SP configuration in the FortiGate +- `fgt.cert` = Fortigate certificate for signing and encrypting +- `service.company` = This is the FQDN of the firewall, if your sslvpn portal is not on TCP port 443, then add the port like: fortigate.mydomain.tld:10233 +- `authentik.company` = This is the FQDN of your authentik installation +- `app.slug.name` = The application slug that you decided upon +- `ak.cert` = The authentik remote certificate you have uploaded before starting the guide. +- `fgt.user.group` = This will be the name of the user group in your Fortigate that you will use in your SSLVPN portal mapping and Firewall rules +- `ak.user.group` = This is the user group name that you will use in authentik if you plan on limiting access to the sslvpn via groups. + +## FortiGate configuration + +### Preparation + +- Decide on an application name (slug) e.g. fgtsslvpn that you will use in authentik later. + +### Setup SAML SP + +1. SSH to the Fortigate (If you are using vdom change to the correct vdom). +2. Copy the config below to your preferred editor and change the placeholders to your settings, then paste it into the Fortigate. + +> [!NOTE] +> Some are https and some are http, that is on purpose, and as described by FortiNet. + +``` +config user saml + edit "saml.sp.name" + set cert "fgt.cert" + set entity-id "http://service.company/remote/saml/metadata/" + set single-sign-on-url "https://service.company/remote/saml/login" + set single-logout-url "https://service.company/remote/saml/logout" + set idp-entity-id "https://authentik.company" + set idp-single-sign-on-url "https://authentik.company/application/saml/app.slug.name/sso/binding/redirect/" + set idp-single-logout-url "https://authentik.company/application/saml/app.slug.name/slo/binding/redirect/" + set idp-cert "ak.cert" + set user-name "http://schemas.goauthentik.io/2021/02/saml/username" + set group-name "http://schemas.xmlsoap.org/claims/Group" + set digest-method sha256 + next +end +``` + +### Add the SAML single sign-on to a user group + +This will limit who can login via authentik SAML. It will match on `ak.user.group` which is the group you will set up in authentik later, and only allow users of that group to login. In essence it provides the same functionality as returning a user-group via Radius, and matching on the user group. + +``` +config user group + edit "fgt.user.group" + set member "saml.sp.name" + config match + edit 1 + set server-name "saml.sp.name" + set group-name "ak.user.group" + next + end + next +end +``` + +> [!IMPORTANT] +> If you created a new firewall group, instead of using an existing sslvpn firewall group, then remember to map it to a portal in the 'SSL-VPN Settings' page, and add the `fgt.user.group` to firewall rules, or you will be redirected back to authentik with a logout immediately upon each login attempt. + +Next get the metadata from the FortiGate to help us with the SAML configuration in authentik. Copy all the output from the command below and save it in a xml file named `fgt-metadata.xml`. You will upload that to authentik later, to facilitate auto-configuration. + +``` +diag vpn ssl saml-metadata saml.sp.name +``` + +## authentik setup + +It's time to log in to authentik and set up the provider and application. + +## Provider section + +Let's set up the provider using the SAML metadata from the FortiGate. + +### Setup the provider using metadata + +- Go to **Applications -> Providers**. +- Click **Create**. +- Select **SAML Provider from Metadata** at the bottom. + - Name: Name it something appropriate e.g. FGT SSL SAML Provider + - Authorization flow: default-provider-authorization-implicit-consent (Authorize Application) + - Metadata: upload the fgt-metadata.xml you created previously +- Click **Finish**. + +### Validate and change settings for provider + +- Click the Edit icon to the right of the provider you just created, under the **Actions** column.. + - Authentication flow = default-authentication-flow (Welcome to authentik!) + - ACS URL = https://service.company/remote/saml/login + - Issuer = https://authentik.company + - Service Provider Binding = POST + - Audience = http://service.company/remote/saml/metadata/ + - Signing certificate = ak.cert + - Verification Certificate = Should already be filled with the certificate from the metadata you uploaded. + - Property mapping: + - authentik default SAML Mapping: Username + - authentik default SAML Mapping: Groups + - Named Property Mapping: Empty (------) + - Assertion valid not before = minutes=5 + - Assertion valid not on or after = minutes=5 + - Session valid not on or after = (Set how long you want the user's session to be valid) + - Default relay state = empty + - Digest algorithm = sha256 + - Signature algorithm = sha256 + +## Application section + +Lets create the application and link it to the provider. + +### Create user group + +This is the user group that you matched on in the FortiGate "firewall group" above. + +- Go to **Directory -> Groups**. +- Click **Create**. +- Name = `ak.user.group`. +- Open ak.user.group and add the users whom should have access to the sslvpn. +- Save the group. + +### Create the application + +> [!NOTE] +> The Launch URL = blank://blank will prevent authentik from displaying it on the user's login page in authentik. + +- Go to **Applications -> Applications**. +- Name = Whatever you fancy e.g. FGT-SSLVPN +- Slug = app.slug.name +- Group = empty (------) +- Provider = The provider you created before e.g. "FGT SSL SAML Provider" +- Backchannel Provider = empty (-----) +- Policy engine mode = any +- Launch URL = blank://blank +- Open in new tab = disabled +- icon = None +- Publisher = None +- Description = None +- Click **Save**. + +### Limiting the access based on authentik group + +- Open the application again +- Click on "Policy / Group / User Binding" +- Click **Bind existing policy**. +- Click on **Group** in the tabs at the top. +- In the **Group** drop-down menu, select `ak.user.group`. +- Make sure that **Enabled** is chosen. +- Order = 10 +- Timeout = 30 +- Failure result = Don't pass +- Click **Create**. + +You should now be able to log in by selecting SSO login either on the portal or in FortiClient, depending on your portal configuration. + +> [!NOTE] +> If you are using FortiClient remember to set the sslvpn profile to use single sign-on either creating a manual profile or editing the profile in your EMS. + +## Troubleshooting + +These are just suggestions of what **could** be the cause of an issue and how to enable debug on the FortiGate. + +> [!CAUTION] +> Debugging can generate heavy load on a FortiGate firewall, so make sure your firewall is not already struggling with performance before you enable debugging, and remember to disabled it again when you are done. +> +> You can disable the debug with these commands. +> `diag debug disable` > `diag debug reset` + +### Enabling debug output + +Before you can see any output you need to enable the debug mode. +`diagnose debug enable` + +### Debug saml daemon + +This will provide all possible output from the SAML daemon. +`diag debug application samld -1` + +### Debug sslvpn (optional) + +This will provide insight into what happens when you use FortiClient, usually combined with `salmd debug`. +`diag debug application sslvpn -1` + +### Debug https daemon (optional) + +This can be used to see what calls are made when using the SSLVPN portal. Note this will also catch any admins working on the firewall and can get a bit messy.\ +`diag debug application httpsd -1` + +### Enable debug timestamps (optional) + +Provides timestamp on the debug output lines\ +`diagnose debug console timestamp enable` + +### Error: Assertion failed with url + +This could be caused by a time difference between SP and IDP + +### Error: Assertion failed with 'coin' + +You have not set the audience in the SAML provider settings + +### Error: Redirection loop + +This could be caused by the `fgt.user.group` not being added to any firewall rules. + +### Error: Redirected to logout page on authentik when logging in + +User group `fgt.user.group` is not mapped to any portals ( Fortigate settings page 'SSL-VPN Settings'), and your default catch all does not allow access to either portal or tunnel. + +### Error: authentik page shows "missing post data" + +An error message about missing data is displayed by authentik. This error means you have used the wrong `idp-single-sign-on-url` and most likely the wrong `idp-single-logout-url` in the FortiGate SAML SP configuration. These should be the redirect URLs from authentik's provider configuration and not the post URLs. diff --git a/website/integrations/services/freshrss/index.md b/website/integrations/services/freshrss/index.md index cf5af2f027..606c07f895 100644 --- a/website/integrations/services/freshrss/index.md +++ b/website/integrations/services/freshrss/index.md @@ -18,29 +18,32 @@ The following placeholders will be used: - `port` is the port on which the FreshRSS install is running (usually 443) - `authentik.company` is the FQDN of the authentik install. -## authentik Configuration +## authentik configuration -In Authentik, create an _OAuth2/OpenID Provider_ under _Applications > Providers_. +1. Create an **OAuth2/OpenID Provider** under **Applications** > **Providers** using the following settings: -** Protocol Settings ** -_Client Type_ : _Confidential_ + - **Name**: FreshRSS + - **Authorization flow**: default-provider-authorization-explicit-consent + - **Protocol Settings**: + - **Client Type**: Confidential + - **Client ID**: Either create your own Client ID or use the auto-populated ID + - **Client Secret**: Either create your own Client Secret or use the auto-populated secret + :::note + Take note of the `Client ID` and `Client Secret`, you'll need them later. + ::: + - **Redirect URIs/Origins**: + - `https://freshrss.company/i/oidc/` + - `https://freshrss.company:port/i/oidc` + - **Signing Key**: Any of your signing keys + - Leave everything else as default -:::note -Take note of the `Client ID` and `Client Secret`, you'll need them later. -::: +2. Create an **Application** under **Applications** > **Applications** using the following settings: + - **Name**: FreshRSS + - **Slug**: freshrss + - **Provider**: FreshRSS _(the provider you created in step 1)_ + - Leave everything else as default -_Redirect URIs/Origins_ : - -- `https://freshrss.company/i/oidc/` -- `https://freshrss.company:port/i/oidc` - -_Signing Key_ : Any of your signing keys - -Then click _Finish_ to create your provider. - -Then create an _Application_, note its slug, and assign it to the provider you've just created. - -## FreshRSS Configuration +## FreshRSS configuration :::info This integration only works with the Docker or Kubernetes install of FreshRSS, using [FreshRSS docker image](https://hub.docker.com/r/freshrss/freshrss/), on x86_64 systems and without the Alpine version of the image. More information can be found on [this issue on FreshRSS GitHub](https://github.com/FreshRSS/FreshRSS/issues/5722) diff --git a/website/integrations/services/gitea/index.md b/website/integrations/services/gitea/index.md index e6ba01c99c..f73f9b9e66 100644 --- a/website/integrations/services/gitea/index.md +++ b/website/integrations/services/gitea/index.md @@ -132,6 +132,10 @@ Click `Update` and the configuration authentik is done. #### Configure Gitea to use the new claims +:::note +Gitea must set `ENABLE_AUTO_REGISTRATION: true`. +::: + Navigate to the _Authentication Sources_ page at https://gitea.company/admin/auths and edit the **authentik** Authentication Source. Change the following fields diff --git a/website/integrations/services/github-enterprise-cloud/index.md b/website/integrations/services/github-enterprise-cloud/index.md index bb8bb52d43..08f696675a 100644 --- a/website/integrations/services/github-enterprise-cloud/index.md +++ b/website/integrations/services/github-enterprise-cloud/index.md @@ -11,7 +11,7 @@ title: GitHub Enterprise Cloud > -- https://docs.github.com/en/enterprise-cloud@latest/admin/overview/about-github-for-enterprises :::note -GitHub Enterprise Cloud EMU (Enterprise Managed Users) are not compatible with authentik. GitHub currently only permits SAML/OIDC for EMU organizations with Okta and/or Azure AD. +GitHub Enterprise Cloud EMU (Enterprise Managed Users) are not compatible with authentik. GitHub currently only permits SAML/OIDC for EMU organizations with Okta and/or Microsoft Entra ID (Azure AD). ::: ## Preparation diff --git a/website/integrations/services/gitlab/index.md b/website/integrations/services/gitlab/index.md index f2ec3b88a6..9f5e05cc1f 100644 --- a/website/integrations/services/gitlab/index.md +++ b/website/integrations/services/gitlab/index.md @@ -47,7 +47,7 @@ gitlab_rails['omniauth_providers'] = [ assertion_consumer_service_url: 'https://gitlab.company/users/auth/saml/callback', # Shown when navigating to certificates in authentik idp_cert_fingerprint: '4E:1E:CD:67:4A:67:5A:E9:6A:D0:3C:E6:DD:7A:F2:44:2E:76:00:6A', - idp_sso_target_url: 'https://authentik.company/application/saml//sso/binding/redirect/', + idp_sso_target_url: 'https://authentik.company/application/saml//sso/binding/redirect/', issuer: 'https://gitlab.company', name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', attribute_statements: { diff --git a/website/integrations/services/glitchtip/index.md b/website/integrations/services/glitchtip/index.md new file mode 100644 index 0000000000..8191226699 --- /dev/null +++ b/website/integrations/services/glitchtip/index.md @@ -0,0 +1,54 @@ +--- +title: Glitchtip +--- + +Support level: Community + +## What is Glitchtip + +> Bugs are inevitable in web development. The important thing is to catch them when they appear. With GlitchTip, you can rest easy knowing that if your web app throws an error or goes down, you will be notified immediately. GlitchTip combines error tracking and uptime monitoring in one open-source package to keep you and your team fully up-to-date on the status of your projects. +> +> -- https://glitchtip.com/documentation + +## Preparation + +The following placeholders will be used: + +- `glitchtip.company` is the FQDN of the Glitchtip install. +- `authentik.company` is the FQDN of the authentik install. + +## authentik configuration + +Create an OAuth2/OpenID provider with the following parameters: + +- Client Type: `Confidential` +- Redirect URIs: `https://glitchtip.company/auth/authentik` + +Note the Client ID and Client Secret values. + +Create an application, using the provider you've created above. Note the slug of the application you've created. + +## Glitchtip configuration + +Configuration of OpenID Connect providers in Glitchtip is done using Django Admin. + +1. Create a superuser using the `manage.py` script: + +``` +sudo docker exec -it glitchtip-web-1 ./manage.py createsuperuser +``` + +2. Go to `https://glitchtip.company/admin/socialaccount/socialapp/` and log in with the newly-created superuser. + +3. Click **Add Social Application** and enter the following details: + +- Provider: `OpenID Connect` +- Provider ID: `authentik` (should match the Redirect URI configured above) +- Provider Name: Whatever you want to appear on GlitchTip's log in button +- Client ID: <Client ID from authentik> +- Secret key: <Client Secret from authentik> +- Key: leave blank +- Settings: `{"server_url": "https://authentik.company/application/o//"}` + The URL should match the **OpenID Configuration Issuer** URL for the authentik provider. + +This will add a **Log in with Authentik** button to the GlitchTip log in page. To add an authentik account to an existing GlitchTip account, log in using the username/password, click _Profile_, then click _Add Account_ in the _Social Auth Accounts_ section. diff --git a/website/integrations/services/globalprotect/index.md b/website/integrations/services/globalprotect/index.md new file mode 100644 index 0000000000..94a3af6468 --- /dev/null +++ b/website/integrations/services/globalprotect/index.md @@ -0,0 +1,71 @@ +--- +title: GlobalProtect +--- + +Support level: Community + +## What is GlobalProtect + +> GlobalProtect enables you to use Palo Alto Networks next-gen firewalls or Prisma Access to secure your mobile workforce. +> +> Palo Alto Networks GlobalProtect platform is a paid enterprise product. +> +> -- https://docs.paloaltonetworks.com/globalprotect + +## Preparation + +The following placeholders will be used: + +- `gp.company` is the FQDN of the GlobalProtect portal. +- `authentik.company` is the FQDN of the authentik install. + +:::caution +A trusted web certificate is required to be bound to the GlobalProtect Portal. This can be signed by a trusted internal Root Certificate Authority (CA); however, a self signed certificate, a certificate outside of its validity, or a non-standard confirming certificate (such as a lifespan not trusted by modern browsers) will error out on SAML authentication. +::: + +## authentik configuration + +1. In the Admin interface of authentik, under _Providers_, create a SAML provider with these settings: + +- ACS URL: `https://gp.company:443/SAML20/SP/ACS` (Note the absence of the trailing slash, and the inclusion of the web interface port) +- Issuer: `https://authentik.company/application/saml/fgm/sso/binding/redirect/` +- Service Provider Binding: Post +- You can of course use a custom signing certificate, and adjust durations. + +2. Select the newly created Provider and download the metadata using the tool on the 'Overview' tab. + +3. In the Admin interface of authentik, under _Application_, create an application with these settings: + +- Launch URL: `blank://blank` (This setting hides the application, while still granting access) +- Use the _Provider_ and _Slug_ previously set in the first step. + +4. Set the bindings appropriately to those who will be allowed to authenticate. + +## GlobalProtect configuration + +1. Navigate to the GlobalProtect configuration device (Firewall or Panorama). + +2. Navigate to 'SAML Identity Provider' on the Device tab and choose the 'import' option. + +- Provide a name for the profile. +- Import the metadata file downloaded earlier. (This will automatically install the authentik signing certificate to the system upon commit.) +- Select 'Validate Identity Provider Certificate' if desired. + +3. Navigate to 'Authentication Profile' on the Device tab and add a new profile. + +- Type: SAML +- IdP Server Profile: The profile just created +- Certificate for Signing Requests: None (Optionally configure authentik for mutual SAML signature) +- Certificate Profile: None (Optionally configure profile to validate the authentik signing cert) +- Username Attribute: `username` + +4. Chose 'Advanced' within the profile and add 'all'. This will have only authentik control the authorization. + +5. Navigate to the 'GlobalProtect Portal Configuration' and chose the portal for SAML access. + +- Under 'Authentication' select the 'Authentication Profile' to the one just created. Leave all other settings as default. +- Optionally chose to require client access via separately issued client cert as well. If not using a client cert, select 'Yes (User Credentials OR Client Certificate Required)'. + +6. Make the same exact changes to the 'GlobalProtect Gateway Configuration'. + +7. Commit the changes to the firewall. diff --git a/website/integrations/services/gravitee/index.md b/website/integrations/services/gravitee/index.md index 9e16190f9c..f43606c225 100644 --- a/website/integrations/services/gravitee/index.md +++ b/website/integrations/services/gravitee/index.md @@ -18,43 +18,44 @@ The following placeholders will be used: - `gravitee.company` is the FQDN of the Gravitee install. - `authentik.company` is the FQDN of the authentik install. -- `applicationName` is the Application name you set. -### Step 1 - authentik +## authentik configuration -In authentik, under _Providers_, create an _OAuth2/OpenID Provider_ with these settings: +1. Create an **OAuth2/OpenID Provider** under **Applications** > **Providers** using the following settings: + :::note + Only settings that have been modified from default have been listed. + ::: - **Name**: Gravitee - **Protocol Settings**: - **Client ID**: Either create your own Client ID or use the auto-populated ID - **Client Secret**: Either create your own Client Secret or use the auto-populated secret + :::note + Take note of the `Client ID` and `Client Secret` as they are required when configuring Gravitee + ::: - **Redirect URIs/Origins**: - https://gravitee.company/user/login - https://gravitee.company/console/ # Make sure to add the trailing / at the end, at the time of writing it does not work without it + :::note + Be sure to add the trailing `/` at the end of the `https://gravitee.company/console/` URI, at the time of writing Gravitee does not work without this. + ::: + +2. Create an **Application** under **Applications** > **Applications** using the following settings: + - **Name**: Gravitee + - **Slug**: gravitee + - **Provider**: Gravitee (the provider you created in step 1) +3. Open the new provider you've just created. +4. Make a note of the following URLs: + - **Authorize URL** + - **Token URL** + - **Userinfo URL** + - **Logout URL** + +## Gravitee configuration + +In the Gravitee Management Console, navigate to _Organizations_ (gravitee.company/console/#!/organization/settings/identities) , under **Console** > **Authentication**. Click _Add an identity provider_, select _OpenID Connect_, and fill in the following: :::note Only settings that have been modified from default have been listed. ::: -**Protocol Settings** - -- Name: applicationName -- Client ID: Copy and Save this for Later -- Client Secret: Copy and Save this for later -- Redirect URIs/Origins: - -``` -https://gravitee.company/user/login -https://gravitee.company/console/ # Make sure to add the trailing / at the end, at the time of writing it does not work without it -``` - -Now, under _Applications_, create an application with the name `applicationName` and select the provider you've created above. - -### Step 2 - Gravitee - -In the Gravitee Management Console, head to _Organizations_(gravitee.company/console/#!/organization/settings/identities) , under _Console_, _Authentication_, click _Add an identity provider_, select _OpenID Connect_, and fill in the following: - -:::note -Only settings that have been modified from default have been listed. -::: - -- Allow portal authentication to use this identity provider: enable this -- Client ID: Client ID from step 1 -- Client Secret: Client Secret from step 1 -- Token Endpoint: `https://authentik.company/application/o/token/` -- Authorize Endpoint: `https://authentik.company/application/o/authorize/` -- Userinfo Endpoint: `https://authentik.company/application/o/userinfo/` -- Userinfo Logout Endpoint: `https://authentik.company/if/session-end/applicationName/` -- Scopes: `email openid profile` +- **Allow portal authentication to use this identity provider**: enable this +- **Client ID**: Enter the Client ID from authentik that you noted in step 1 +- **Client Secret**: Enter the Client Secret from authentik that you noted in step 1 +- **Token Endpoint**: Populate this field with the **Token URL** +- **Authorize Endpoint**: Populate this field with the **Authorize URL** +- **Userinfo Endpoint**: Populate this field with the **Userinfo URL** +- **Userinfo Logout Endpoint**: Populate this field with the **Logout URL** +- **Scopes**: `email openid profile` diff --git a/website/integrations/services/home-assistant/index.md b/website/integrations/services/home-assistant/index.md index 836eb2e4be..4abf98ec06 100644 --- a/website/integrations/services/home-assistant/index.md +++ b/website/integrations/services/home-assistant/index.md @@ -1,10 +1,10 @@ --- -title: Home-Assistant +title: Home Assistant --- Support level: Community -## What is Home-Assistant +## What is Home Assistant > Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. > @@ -13,54 +13,57 @@ title: Home-Assistant :::caution You might run into CSRF errors, this is caused by a technology Home-assistant uses and not authentik, see [this GitHub issue](https://github.com/goauthentik/authentik/issues/884#issuecomment-851542477). ::: +:::note +For Home Assistant to work with authentik, a custom integration needs to be installed for Home Assistant. +::: ## Preparation The following placeholders will be used: -- `hass.company` is the FQDN of the Home-Assistant install. +- `hass.company` is the FQDN of the Home Assistant install. - `authentik.company` is the FQDN of the authentik install. -## Home-Assistant +## authentik configuration -This guide requires https://github.com/BeryJu/hass-auth-header, which can be installed as described in the Readme. +1. Create a **Proxy Provider** under **Applications** > **Providers** using the following settings: -Afterwards, make sure the `trusted_proxies` setting contains the IP(s) of the Host(s) authentik is running on. + - **Name**: Home Assistant + - **Authentication flow**: default-authentication-flow + - **Authorization flow**: default-provider-authorization-explicit-consent + - **External Host**: Set this to the external URL you will be accessing Home Assistant from + - **Internal Host**: `http://hass.company:8123` -Use this configuration to match on the user's authentik username. +2. Create an **Application** under **Applications** > **Applications** using the following settings: -```yaml -auth_header: - username_header: X-authentik-username -``` + - **Name**: Home Assistant + - **Slug**: homeassistant + - **Provider**: Home Assistant (the provider you created in step 1) -If this is not the case, you can simply add an additional header for your user, which contains the Home-Assistant Name and authenticate based on that. +3. Create an outpost deployment for the provider you've created above, as described [here](../../../docs/outposts/). Deploy this Outpost either on the same host or a different host that can access Home Assistant. The outpost will connect to authentik and configure itself. -For example add this to your user's properties and set the Header to `X-ak-hass-user`. +## Home Assistant configuration -```yaml -additionalHeaders: - X-ak-hass-user: some other name -``` - -## authentik - -Create a Proxy Provider with the following values - -- Internal host - - If Home-Assistant is running in docker, and you're deploying the authentik proxy on the same host, set the value to `http://homeassistant:8123`, where Home-Assistant is the name of your container. - - If Home-Assistant is running on a different server than where you are deploying the authentik proxy, set the value to `http://hass.company:8123`. - -- External host - - Set this to the external URL you will be accessing Home-Assistant from. - -Create an application in authentik and select the provider you've created above. - -## Deployment - -Create an outpost deployment for the provider you've created above, as described [here](../../../docs/outposts/). Deploy this Outpost either on the same host or a different host that can access Home-Assistant. - -The outpost will connect to authentik and configure itself. +1. Configure [trusted_proxies](https://www.home-assistant.io/integrations/http/#trusted_proxies) for the HTTP integration with the IP(s) of the Host(s) authentik is running on. +2. If you don't already have it set up, https://github.com/BeryJu/hass-auth-header, using the installation guide. +3. There are two ways to configure the custom component. + 1. To match on the user's authentik username, use the following configuration: + ```yaml + auth_header: + username_header: X-authentik-username + ``` + 2. Alternatively, you can associate an existing Home Assistant username to an authentik username. + 1. Within authentik, navigate to **Directory** > **Users**. + 2. Select **Edit** for the user then add the following configuration to the **Attributes** section. Be sure to replace `hassusername` with the Home Assistant username. + :::note + This configuration will add an additional header for the authentik user which will contain the Home Assistant username and allow Home Assistant to authenticate based on that. + ::: + ```yaml + additionalHeaders: + X-ak-hass-user: hassusername + ``` + 3. Then configure the Home Assistant custom component to use this header: + ```yaml + auth_header: + username_header: X-ak-hass-user + ``` diff --git a/website/integrations/services/immich/index.md b/website/integrations/services/immich/index.md index 88554d302f..37aa27aef9 100644 --- a/website/integrations/services/immich/index.md +++ b/website/integrations/services/immich/index.md @@ -19,15 +19,20 @@ The following placeholders will be used: ## authentik configuration -1. Create a new OAuth2/OpenID Provider using the following settings: +1. Create a new OAuth2/OpenID Provider under **Applications** > **Providers** using the following settings: - **Name**: Immich - **Authentication flow**: default-authentication-flow - **Authorization flow**: default-provider-authorization-explicit-consent - **Client type**: Confidential - - **Client ID**: Either create your own Client ID or make a note of the auto-populated one - - **Client Secret**: Either create your own Client Secret or make a note of the auto-populated one + - **Client ID**: Either create your own Client ID or use the auto-populated ID + - **Client Secret**: Either create your own Client Secret or use the auto-populated secret + :::note + Take note of the `Client ID` and `Client Secret` as they are required when configuring Immich. + ::: - **Redirect URIs/Origins (RegEx)**: - _Please note that the following URIs are just examples. Be sure to include all of the domains / URLs that you will use to access Immich._ + :::note + Please note that the following URIs are just examples. Be sure to include all of the domains / URLs that you will use to access Immich. + ::: - app.immich:/ - https://immich.company/auth/login - https://immich.company/user-settings @@ -36,7 +41,7 @@ The following placeholders will be used: 2. Open the new provider you've just created. 3. Make a note of the **OpenID Configuration Issuer**. -## Immich Configuration +## Immich configuration Immich documentation can be found here: https://immich.app/docs/administration/oauth diff --git a/website/integrations/services/index.mdx b/website/integrations/services/index.mdx index 3f91095cdc..6701df79ea 100644 --- a/website/integrations/services/index.mdx +++ b/website/integrations/services/index.mdx @@ -1,25 +1,30 @@ --- title: Applications -slug: / --- import DocCardList from "@theme/DocCardList"; -import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; -Below is a list of all applications that are known to work with authentik. +Below is a list of all applications that are known to work with authentik. All app integrations will have one of these badges: -All integrations will have a combination of these badges: +- Support level: Community The integration + is community maintained. -- Support level: Community +- Support level: Vendor The integration + is supported by the vendor. - The integration is community maintained. +- Support level: authentik The integration + is regularly tested by the authentik team. -- Support level: Vendor +### Add a new application - The integration is supported by the vendor. +To add documentation for a new application (with support level Community or Vendor), please use the integration template [`service.md`](https://github.com/goauthentik/authentik/blob/main/website/integrations/_template/service.md) file from our GitHub repo. You can download the template file using the following command: -- Support level: authentik +```shell +wget https://raw.githubusercontent.com/goauthentik/authentik/main/website/integrations/_template/service.md +``` - The integration is regularly tested by the authentik team. +Don't forget to edit the `sidebarsIntegrations.js` file to add your new integration to the lefthand navigation bar. - +## Integration categories + + diff --git a/website/integrations/services/jenkins/index.md b/website/integrations/services/jenkins/index.md index a8b4388ab4..2652745d6c 100644 --- a/website/integrations/services/jenkins/index.md +++ b/website/integrations/services/jenkins/index.md @@ -20,7 +20,7 @@ The following placeholders will be used: Create an OAuth2/OpenID provider with the following parameters: - **Client Type**: `Confidential` -- Scopes: OpenID, Email and Profile +- **Scopes**: OpenID, Email and Profile - **Signing Key**: Select any available key Note the Client ID and Client Secret values for the provider. diff --git a/website/integrations/services/netbox/index.md b/website/integrations/services/netbox/index.md index 5f934f745d..75a3166366 100644 --- a/website/integrations/services/netbox/index.md +++ b/website/integrations/services/netbox/index.md @@ -43,6 +43,7 @@ REMOTE_AUTH_BACKEND='social_core.backends.open_id_connect.OpenIdConnectAuth' SOCIAL_AUTH_OIDC_ENDPOINT='https://authentik.company/application/o//' SOCIAL_AUTH_OIDC_KEY='' SOCIAL_AUTH_OIDC_SECRET='' +SOCIAL_AUTH_OIDC_SCOPE = ["openid", "profile", "email", "roles"] LOGOUT_REDIRECT_URL='https://authentik.company/application/o//end-session/' ``` @@ -59,6 +60,7 @@ from os import environ SOCIAL_AUTH_OIDC_ENDPOINT = environ.get('SOCIAL_AUTH_OIDC_ENDPOINT') SOCIAL_AUTH_OIDC_KEY = environ.get('SOCIAL_AUTH_OIDC_KEY') SOCIAL_AUTH_OIDC_SECRET = environ.get('SOCIAL_AUTH_OIDC_SECRET') +SOCIAL_AUTH_OIDC_SCOPE = ["openid", "profile", "email", "roles"] LOGOUT_REDIRECT_URL = environ.get('LOGOUT_REDIRECT_URL') @@ -81,8 +83,13 @@ LOGOUT_REDIRECT_URL = environ.get('LOGOUT_REDIRECT_URL') To manage groups in NetBox custom social auth pipelines are required. To create them you have to create the `custom_pipeline.py` file in the NetBox directory with the following content. +:::info +From Netbox version 4.0.0 Netbox add the custom `Group` models. The following code is compatible with Netbox 4.0.0 and above. For Netbox versions below 4.0.0, the import statement and group adding / deleting of user lines must be changed. +::: + ```python -from django.contrib.auth.models import Group +# from django.contrib.auth.models import Group # For Netbox < 4.0.0 +from netbox.authentication import Group # For Netbox >= 4.0.0 class AuthFailed(Exception): pass @@ -96,7 +103,8 @@ def add_groups(response, user, backend, *args, **kwargs): # Add all groups from oAuth token for group in groups: group, created = Group.objects.get_or_create(name=group) - group.user_set.add(user) + # group.user_set.add(user) # For Netbox < 4.0.0 + user.groups.add(group) # For Netbox >= 4.0.0 def remove_groups(response, user, backend, *args, **kwargs): try: @@ -114,7 +122,8 @@ def remove_groups(response, user, backend, *args, **kwargs): # Delete non oAuth token groups for delete_group in delete_groups: group = Group.objects.get(name=delete_group) - group.user_set.remove(user) + # group.user_set.remove(user) # For Netbox < 4.0.0 + user.groups.remove(group) # For Netbox >= 4.0.0 def set_roles(response, user, backend, *args, **kwargs): diff --git a/website/integrations/services/nextcloud/index.md b/website/integrations/services/nextcloud/index.md index 139932056f..43ad940a1f 100644 --- a/website/integrations/services/nextcloud/index.md +++ b/website/integrations/services/nextcloud/index.md @@ -51,9 +51,9 @@ authentik already provides some default _scopes_ with _claims_ inside them, such ##### Custom profile scope -If you do not need storage quota or group information in Nextcloud [skip to the next step](#provider-and-application). +If you do not need storage quota, group information, or to manage already existing users in Nextcloud [skip to the next step](#provider-and-application). -However, if you want to be able to control how much storage users in Nextcloud can use, as well as which users are recognized as Nextcloud administrators, you would need to make this information available in Nextcloud. To achieve this you would need to create a custom `profile` scope. To do so, go to _Customisation_ -> _Property mappings_. Create a _Scope mapping_ with the following parameters: +However, if you want to be able to control how much storage users in Nextcloud can use, as well as which users are recognized as Nextcloud administrators, you would need to make this information available in Nextcloud. To achieve this you would need to create a custom `profile` scope. To do so, go to _Customization_ -> _Property mappings_. Create a _Scope mapping_ with the following parameters: - Name: Nextcloud Profile - Scope name: profile @@ -74,7 +74,10 @@ return { "name": request.user.name, "groups": groups, # To set a quota set the "nextcloud_quota" property in the user's attributes - "quota": user.group_attributes().get("nextcloud_quota", None) + "quota": user.group_attributes().get("nextcloud_quota", None), + # To connect an already existing user, set the "nextcloud_user_id" property in the + # user's attributes to the username of the corresponding user on Nextcloud. + "user_id": user.attributes.get("nextcloud_user_id", str(user.uuid)), } ``` @@ -84,6 +87,13 @@ To set a quota set the "nextcloud_quota" property in the user's attributes. This If set to a value, for example `1 GB`, user(s) will have 1GB storage quota. If the attribute is not set, user(s) will have unlimited storage. ::: +:::note +To connect to an already existing Nextcloud user, set the "nextcloud_user_id" property in the user's attributes. This must be set for each individual user. + +The value of `nextcloud_user_id` must match the field `username` of the user on the Nextcloud instance. On Nextcloud, go to _Users_ to see the username of the user you are trying to connect to (Under user's `Display name`). +If set to a value, for example `goauthentik`, it will try to connect to the `goauthentik` user on the Nextcloud instance. Otherwise, the user's UUID will be used. +::: + ##### Provider and Application Create a provider for Nextcloud. In the Admin Interface, go to _Applications_ -> _Providers_. Create an _OAuth2/OpenID Provider_ with the following parameters: @@ -98,14 +108,14 @@ Create a provider for Nextcloud. In the Admin Interface, go to _Applications_ -> - `Nextcloud Profile` (or `authentik default Oauth Mapping profile` if you skipped the [custom profile scope](#custom-profile-scope) section) - Subject mode: Based on the User's UUID :::danger - Nextcloud will use the UUID as username. However, mapping the subject mode to authentik usernames is **not recommended** due to their mutable nature. This can lead to security issues such as user impersonation. If you still wish to map the subject mode to an username, [disable username changing](../../../docs/installation/configuration#authentik_default_user_change_username) in authentik and set this to `Based on the User's username`. + Nextcloud will use the UUID as username. However, mapping the subject mode to authentik usernames is **not recommended** due to their mutable nature. This can lead to security issues such as user impersonation. If you still wish to map the subject mode to an username, [disable username changing](../../../docs/core/settings#allow-users-to-change-username) in authentik and set this to `Based on the User's username`. ::: - Include claims in ID token: ✔️ Before continuing, make sure to take note of your `client ID` and `secret ID`. Don't worry you can go back to see/change them at any time. -:::warning -Currently there is a bug in the Nextcloud OIDC app, that is [limiting the size of the secret ID](https://github.com/nextcloud/user_oidc/issues/405) token to 64 characters. Since authentik uses 128 characters for a secret ID by default, you will need to trim it down to 64 characters in order to be able to set it in Nextcloud. Don't worry, 64 characters is still sufficiently long and should not compromise security. +:::note +There were an issue in the Nextcloud OIDC app that was [limiting the size of the secret ID](https://github.com/nextcloud/user_oidc/issues/405) token to 64 characters. This issue was fixed in December 2023, so make sure you update to the latest version of the [OpenID Connect user backend](https://apps.nextcloud.com/apps/user_oidc) application. ::: :::note @@ -129,7 +139,7 @@ Add a new provider using the `+` button and set the following values: ::: - Scope: `email`, `profile` (you can safely omit `openid` if you prefer) - Attribute mappings: - - User ID mapping: sub + - User ID mapping: sub (or `user_id` if you need to connect to an already existing Nextcloud user) - Display name mapping: name - Email mapping: email - Quota mapping: quota (leave empty if you have skipped the [custom profile scope](#custom-profile-scope) section) @@ -137,7 +147,10 @@ Add a new provider using the `+` button and set the following values: :::tip You need to enable the "Use group provisioning" checkmark to be able to write to this field ::: -- Use unique user ID: If you only have one provider you can uncheck this if you prefer. +- Use unique user ID: If you only have one provider you can deselect this if you prefer. This will affect your Federated Cloud ID, which you can check under _Personal settings_ -> _Sharing_ -> _Federated Cloud_. If the box is selected, nextcloud will pick a hashed value here (`437218904321784903214789023@nextcloud.instance` for example). Otherwise, it will use the mapped user ID (`@nextcloud.instance`). + :::tip + To avoid your federated cloud id being a hash value, deselect **Use unique user ID** and use `user_id` in the **User ID mapping** field. + ::: At this stage you should be able to login with SSO. @@ -233,7 +246,7 @@ Set the following values: - Attribute to map the UID to: `http://schemas.goauthentik.io/2021/02/saml/uid` :::danger - Nextcloud uses the UID attribute as username. However, mapping it to authentik usernames is **not recommended** due to their mutable nature. This can lead to security issues such as user impersonation. If you still wish to map the UID to an username, [disable username changing](../../../docs/installation/configuration#authentik_default_user_change_username) in authentik and set the UID attribute to "http://schemas.goauthentik.io/2021/02/saml/username". + Nextcloud uses the UID attribute as username. However, mapping it to authentik usernames is **not recommended** due to their mutable nature. This can lead to security issues such as user impersonation. If you still wish to map the UID to an username, [disable username changing](../../../docs/core/settings#allow-users-to-change-username) in authentik and set the UID attribute to "http://schemas.goauthentik.io/2021/02/saml/username". ::: - Optional display name of the identity provider (default: "SSO & SAML log in"): `authentik` - Identifier of the IdP entity (must be a URI): `https://authentik.company` @@ -286,7 +299,7 @@ Create a custom SAML Property Mapping: - Set the _Expression_ to: ```python -for group in user.ak_groups.all(): +for group in request.user.all_groups(): yield group.name if ak_is_group_member(request.user, name=""): yield "admin" diff --git a/website/integrations/services/opnsense/index.md b/website/integrations/services/opnsense/index.md index e2aa81ab7a..05a9a99b1f 100644 --- a/website/integrations/services/opnsense/index.md +++ b/website/integrations/services/opnsense/index.md @@ -11,7 +11,7 @@ title: OPNsense > -- https://opnsense.org/ :::note -This is based on authentik 2022.4.1 and OPNsense 22.1.6-amd64 installed using https://docs.opnsense.org/manual/install.html. Instructions may differ between versions. +This is based on authentik 2024.2.2 and OPNsense 24.1.3_1-amd64 installed using https://docs.opnsense.org/manual/install.html. Instructions may differ between versions. ::: ## Preparation @@ -25,7 +25,7 @@ The following placeholders will be used: ### Step 1 In authentik, go and 'Create Service account' (under _Directory/Users_) for OPNsense to use as the LDAP Binder, leaving 'Create group' ticked as we'll need that group for the provider. -In this example, we'll use `opnsense` as the Service account's username +In this example, we'll use `opnsense-user` as the Service account's username :::note Take note of the password for this user as you'll need to give it to OPNsense in _Step 4_. @@ -92,6 +92,10 @@ In OPNsense, go to _System/Settings/Administration_ and under _Authentication_ a ![](./opnsense2.png) +### Step 7 + +You can now either import users, or synchronize from Authentik LDAP. See https://docs.opnsense.org/manual/how-tos/user-ldap.html for more. + ## Notes :::note diff --git a/website/integrations/services/outline/index.md b/website/integrations/services/outline/index.md new file mode 100644 index 0000000000..1ebdc00a7e --- /dev/null +++ b/website/integrations/services/outline/index.md @@ -0,0 +1,48 @@ +--- +title: Outline +--- + +Support level: Community + +## What is Outline + +> Your team's knowledge base. +> Lost in a mess of Docs? Never quite sure who has access? Colleagues requesting the same information repeatedly in chat? It’s time to get your team’s knowledge organized. +> +> -- https://www.getoutline.com + +## Preparation + +The following placeholders will be used: + +- `outline.company` is the FQDN of the Outline install. +- `authentik.company` is the FQDN of the authentik install. + +## authentik configuration + +1. Create an OAuth2/OpenID provider with the following parameters: + +- Client Type: `Confidential` +- Scopes: OpenID, Email and Profile +- Signing Key: Select any available key +- Redirect URIs: `https://outline.company/auth/oidc.callback` + +2. Note the Client ID and Client Secret values. + +## Outline configuration + +You need to set the following `env` variables for Docker-based installations. + +1. Set the following values: + +```yaml +OIDC_CLIENT_ID= +OIDC_CLIENT_SECRET= +OIDC_AUTH_URI=https://authentik.company/application/o/authorize/ +OIDC_TOKEN_URI=https://authentik.company/application/o/token/ +OIDC_USERINFO_URI=https://authentik.company/application/o/userinfo/ +OIDC_LOGOUT_URI=https://authentik.company/application/o/wiki/end-session/ +OIDC_USERNAME_CLAIM=preferred_username +OIDC_DISPLAY_NAME=authentik +OIDC_SCOPES=openid profile email +``` diff --git a/website/integrations/services/paperless-ng/index.md b/website/integrations/services/paperless-ng/index.md index c482ab6397..eed82187c1 100644 --- a/website/integrations/services/paperless-ng/index.md +++ b/website/integrations/services/paperless-ng/index.md @@ -36,7 +36,7 @@ PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=HTTP_X_AUTHENTIK_USERNAME Authentik automatically sets this header when we use a proxy outpost. Now restart your container: -`docker-compose down && docker-compose up -d` +`docker compose down && docker compose up -d` ## authentik diff --git a/website/integrations/services/paperless-ngx/index.md b/website/integrations/services/paperless-ngx/index.md new file mode 100644 index 0000000000..2d5f03823f --- /dev/null +++ b/website/integrations/services/paperless-ngx/index.md @@ -0,0 +1,69 @@ +--- +title: Paperless-ngx +--- + +Support level: Community + +## What is Paperless-ngx + +> Paperless-ngx is an application that indexes your scanned documents and allows you to easily search for documents and store metadata alongside your documents. It was a fork from paperless-ngx, in turn a fork from the original Paperless, neither of which are maintained any longer. +> +> -- https://github.com/paperless-ngx/paperless-ngx + +## Preparation + +The following placeholders will be used: + +- `paperless.company` is the FQDN of the Paperless-ngx install. +- `authentik.company` is the FQDN of the authentik install. + +## authentik Configuration + +### Step 1 - OAuth2/OpenID Provider + +Create a OAuth2/OpenID Provider (under Applications/Providers) with these settings: + + Name : Paperless + Redirect URI: https://paperless.company/accounts/oidc/authentik/login/callback/ + +### Step 2 - Application + +Create an application (under Resources/Applications) with these settings: + + Name: Paperless + Slug: paperless + Provider: Paperless + +## Paperless Configuration + +Add the following environment variables to your Paperless-ngx setup. If you are using Docker Compose, then add the following to your docker-compose.yml file: + +```yaml +PAPERLESS_APPS: allauth.socialaccount.providers.openid_connect +PAPERLESS_SOCIALACCOUNT_PROVIDERS: > + { + "openid_connect": { + "APPS": [ + { + "provider_id": "authentik", + "name": "Authentik", + "client_id": "< Client ID >", + "secret": "< Client Secret >, + "settings": { + "server_url": "https://authentik.company/application/o/paperless/.well-known/openid-configuration" + } + } + ], + "OAUTH_PKCE_ENABLED": "True" + } + } +``` + +Now restart your container: +`docker compose down && docker compose up -d` + +## Finished + +Now you can access Paperless-ngx by logging in with authentik. + +To add authentik authentication to an existing user, log in to Paperless with local authentication, click the profile icon in the top-right, click My Profile, then Connect new social account. diff --git a/website/integrations/services/pfsense/index.md b/website/integrations/services/pfsense/index.md index dd4003d2e1..5e28830c5a 100644 --- a/website/integrations/services/pfsense/index.md +++ b/website/integrations/services/pfsense/index.md @@ -70,6 +70,7 @@ Change the following fields - Port value: 389 - Transport: Standard TCP - Base DN: `DC=ldap,DC=goauthentik,DC=io` +- Search Scope: Subtree - Authentication containers: `OU=users,DC=ldap,DC=goauthentik,DC=io` - Bind anonymous: **unticked** - Bind credentials: @@ -128,6 +129,7 @@ Change the following fields - Transport: SSL/TLS Encrypted - Peer Certificate Authority: `pfSense CA` - Base DN: `DC=ldap,DC=goauthentik,DC=io` +- Search Scope: Subtree - Authentication containers: `OU=users,DC=ldap,DC=goauthentik,DC=io` - Bind anonymous: **unticked** - Bind credentials: diff --git a/website/integrations/services/portainer/index.md b/website/integrations/services/portainer/index.md index 73c7a81759..c574d8a847 100644 --- a/website/integrations/services/portainer/index.md +++ b/website/integrations/services/portainer/index.md @@ -44,8 +44,8 @@ In Portainer, under _Settings_, _Authentication_, Select _OAuth_ and _Custom_ - Client Secret: Client Secret from step 1 - Authorization URL: `https://authentik.company/application/o/authorize/` - Access Token URL: `https://authentik.company/application/o/token/` -- Redirect URL: `https://portainer.company` - Resource URL: `https://authentik.company/application/o/userinfo/` +- Redirect URL: `https://portainer.company/` - Logout URL: `https://authentik.company/application/o/portainer/end-session/` - User Identifier: `preferred_username` (Or `email` if you want to use email addresses as identifiers) - Scopes: `email openid profile` diff --git a/website/integrations/services/portainer/port1.png b/website/integrations/services/portainer/port1.png index 3ab5dad1af..5cf095ef22 100644 Binary files a/website/integrations/services/portainer/port1.png and b/website/integrations/services/portainer/port1.png differ diff --git a/website/integrations/services/powerdns-admin/index.md b/website/integrations/services/powerdns-admin/index.md index ff4f78e07c..6189816d42 100644 --- a/website/integrations/services/powerdns-admin/index.md +++ b/website/integrations/services/powerdns-admin/index.md @@ -60,7 +60,6 @@ You must mount the certificate selected in authentik as a file in the Docker con ### docker-compose ```yaml -version: "3.3" services: powerdns-admin: image: powerdnsadmin/pda-legacy:latest diff --git a/website/integrations/services/proxmox-ve/index.md b/website/integrations/services/proxmox-ve/index.md index be076c6686..be118deff0 100644 --- a/website/integrations/services/proxmox-ve/index.md +++ b/website/integrations/services/proxmox-ve/index.md @@ -33,7 +33,7 @@ Under _Providers_, create an OAuth2/OpenID provider with these settings: Create an application which uses this provider. Optionally apply access restrictions to the application. -Set the Launch URL to `https://promox.company:8006`. +Set the Launch URL to `https://proxmox.company:8006`. ## Proxmox VE Setup diff --git a/website/integrations/services/sharepoint-se/index.md b/website/integrations/services/sharepoint-se/index.md index 1ec2435985..b13cb9cba9 100644 --- a/website/integrations/services/sharepoint-se/index.md +++ b/website/integrations/services/sharepoint-se/index.md @@ -79,7 +79,7 @@ Additional information from Microsoft documentation: From the authentik Admin Dashboard: -1. Open **Customisation > Property Mappings** page from the sidebar. +1. Open **Customization > Property Mappings** page from the sidebar. 2. Click **Create** from the property mapping list command bar. 3. Within the new property mapping form, select **Scope Mapping**. 4. Click **Next** and enter the following values: @@ -102,7 +102,7 @@ return { From the authentik Admin Dashboard: -1. Open **Customisation > Property Mappings** page from the sidebar. +1. Open **Customization > Property Mappings** page from the sidebar. 2. Click **Create** from the property mapping list command bar. 3. Within the new property mapping form, select **Scope Mapping**. 4. Click **Next** and enter the following values: diff --git a/website/integrations/services/skyhigh/index.md b/website/integrations/services/skyhigh/index.md index e220933f14..58c6121e5f 100644 --- a/website/integrations/services/skyhigh/index.md +++ b/website/integrations/services/skyhigh/index.md @@ -10,10 +10,6 @@ title: Skyhigh Security > > -- https://www.skyhighsecurity.com/en-us/about.html -:::note -We were among the first to recognize the cloud’s potential and knew that protecting data in this new hybrid world required an entirely new approach. We make managing your web and unifying your data policies easy to create and enforce, giving you a single console to provide visibility across all of your infrastructure. -::: - ## Multiple Integration Points Skyhigh has multiple points for SAML integration: diff --git a/website/integrations/services/snipe-it/index.md b/website/integrations/services/snipe-it/index.md index 12c8c60ece..cd39930e58 100644 --- a/website/integrations/services/snipe-it/index.md +++ b/website/integrations/services/snipe-it/index.md @@ -115,7 +115,7 @@ You must sync your LDAP database with Snipe-IT. Go to People on the sidebar menu ## authentik Property Mapping -To create a policy mapping, go to _Customisation/Property Mappings_, click `Create` then `LDAP Property Mapping`. Name is 'sn' and set Object field to sn: +To create a policy mapping, go to _Customization/Property Mappings_, click `Create` then `LDAP Property Mapping`. Name is 'sn' and set Object field to sn: ```ini def getLastName(): diff --git a/website/integrations/services/synology-dsm/index.md b/website/integrations/services/synology-dsm/index.md new file mode 100644 index 0000000000..12f1c8186f --- /dev/null +++ b/website/integrations/services/synology-dsm/index.md @@ -0,0 +1,60 @@ +--- +title: Synology DSM (DiskStation Manager) +--- + +Support level: Community + +## What is Synology DSM + +> Synology Inc. is a Taiwanese corporation that specializes in network-attached storage (NAS) appliances. Synology's line of NAS is known as the DiskStation for desktop models, FlashStation for all-flash models, and RackStation for rack-mount models. Synology's products are distributed worldwide and localized in several languages. +> +> -- https://www.synology.com/en-global/dsm + +:::caution +This is tested with DSM 7.1 or newer. +::: + +## Preparation + +The following placeholders will be used: + +- `synology.company` is the FQDN of the Synology DSM server. +- `authentik.company` is the FQDN of the authentik install. + +## authentik configuration + +### Step 1 + +In the Admin interface of authentik, under _Providers_, create an OAuth2/OpenID provider with these settings: + +- Name: synology +- Redirect URI: `https://synology.company/#/signin` (Note the absence of the trailing slash, and the inclusion of the webinterface port) +- Signing Key: Select any available key +- Subject mode: Based on the Users's Email (Matching on username could work, but not if you have duplicates due to e.g. a LDAP connection) +- Take note of the 'Client ID' and 'Client secret' + +### Step 2 + +Create an application which uses this provider. Optionally apply access restrictions to the application. + +## Synology DSM configuration + +To configure Synology DSM to utilize authentik as an OpenID Connect 1.0 Provider: + +1. In the DSM Control Panel, navigate to **Domain/LDAP** -> **SSO Client**. +2. Check the **Enable OpenID Connect SSO service** checkbox in the **OpenID Connect SSO Service** section. +3. Configure the following values: + +- Profile: OIDC +- Name: authentik +- Well Known URL: Copy this from the 'OpenID Configuration URL' in the authentik provider (URL ends with '/.well-known/openid-configuration') +- Application ID: The 'Client ID' from the authentik provider +- Application Key: The 'Client secret' from the authentik provider +- Redirect URL: https://synology.company/#/signin (This should match the 'Redirect URI' in authentik exactly) +- Authorization Scope: openid profile email +- Username Claim: preferred_username +- Save the settings. + +## See also: + +[Synology DSM SSO Client Documentation](https://kb.synology.com/en-af/DSM/help/DSM/AdminCenter/file_directory_service_sso?version=7) diff --git a/website/integrations/services/truecommand/index.md b/website/integrations/services/truecommand/index.md index 0e3c013477..6cea09215f 100644 --- a/website/integrations/services/truecommand/index.md +++ b/website/integrations/services/truecommand/index.md @@ -36,7 +36,7 @@ Under _Advanced protocol settings_, set NameID Property to _authentik default SA The following custom property mappings are required. -Under _Customisation_, select _Property Mappings_, then _Create_. Select _SAML Property Mapping_. +Under _Customization_, select _Property Mappings_, then _Create_. Select _SAML Property Mapping_. ### Username diff --git a/website/integrations/services/wekan/index.mdx b/website/integrations/services/wekan/index.mdx index f615a6a6f5..94d9afb3cd 100644 --- a/website/integrations/services/wekan/index.mdx +++ b/website/integrations/services/wekan/index.mdx @@ -49,8 +49,8 @@ environment: OAUTH2_ENABLED=true OAUTH2_USERINFO_ENDPOINT=/application/o/userinfo/ OAUTH2_TOKEN_ENDPOINT=/application/o/token/ OAUTH2_SECRET= - OAUTH2_ID_MAP=preferred_username - OAUTH2_USERNAME_MAP=preferred_username + OAUTH2_ID_MAP=sub + OAUTH2_USERNAME_MAP=email OAUTH2_FULLNAME_MAP=given_name OAUTH2_EMAIL_MAP=email ``` @@ -70,8 +70,8 @@ edit `.env` and add the following: OAUTH2_USERINFO_ENDPOINT='/application/o/userinfo/' OAUTH2_TOKEN_ENDPOINT='/application/o/token/' OAUTH2_SECRET='' - OAUTH2_ID_MAP='preferred_username' - OAUTH2_USERNAME_MAP='preferred_username' + OAUTH2_ID_MAP='sub' + OAUTH2_USERNAME_MAP='email' OAUTH2_FULLNAME_MAP='given_name' OAUTH2_EMAIL_MAP='email' ``` diff --git a/website/integrations/services/xen-orchestra/index.md b/website/integrations/services/xen-orchestra/index.md new file mode 100644 index 0000000000..a248ed6cf4 --- /dev/null +++ b/website/integrations/services/xen-orchestra/index.md @@ -0,0 +1,69 @@ +--- +title: Xen Orchestra +--- + +Support level: Community + +## What is Xen Orchestra + +> Xen Orchestra provides a user friendly web interface for every Xen based hypervisor (XenServer, xcp-ng, etc.). +> +> -- https://xen-orchestra.com/ + +:::note +Xen Orchestra offers authentication plugins for OpenID Connect, SAML and LDAP. This guide is using the OpenID Connect plugin. +If you are using the Xen Orchestra Appliance, the OIDC Plugin should be present. If you are using Xen Orchestra compiled from sources, make sure the plugin `auth-oidc` is installed. +::: + +## Preparation + +The following placeholders will be used: + +- `xenorchestra.company` is the FQDN of the Xen Orchestra instance. +- `authentik.company` is the FQDN of the authentik install. + +## authentik configuration + +### 1. Provider + +Under _Providers_, create an OAuth2/OpenID provider with these settings: + +- Name: Provider for XenOrchestra +- Authorization Flow: Select one of the available Flows. +- Client type: Confidential +- Redirect URIs/Origins: `https://xenorchestra.company/signin/oidc/callback` + +Take note of the Client ID and the Client Secret, because we need them for the configuration of Xen Orchestra. + +### 2. Application + +Create an application with the following details: + +- Slug: `xenorchestra` (If you want to choose a different slug, your URLs for the Xen Orchestra Configuration may vary.) +- Provider: Select the one we have created in Step 1 +- Set the Launch URL to `https://xenorchestra.company/` + +Optionally apply access restrictions to the application. + +## Xen Orchestra configuration + +Xen Orchestra allows the configuration of the OpenID Connect authentication in the plugin-section. +All of the URLs mentioned below can be copied & pasted from authentik (_Applications -> Providers -> *the provider created earlier*_). + +1. Navigate to Settings -> Plugins +2. Scroll to **auth-oidc** and click on the **+** icon on the right hand side. +3. Configure the auth-oidc plugin with the following configuration values: + +- Set the `Auto-discovery URL` to `https://authentik.company/application/o/xenorchestra/.well-known/openid-configuration`. +- Set the `Client identifier (key)` to the Client ID from your notes. +- Set the `Client secret` to the Client Secret from your notes. +- Check the `Fill information (optional)`-Checkbox to open the advanced menu. +- Set the `Username field` to `username` +- Set the `Scopes` to `openid profile email` + +4. Enable the `auth-oidc`-Plugin by toggling the switch above the configuration. +5. You should be able to login with OIDC. + +:::note +The first time a user signs in, Xen Orchesta will create a new user with the same username used in authentik. If you want to map the users by their e-mail-address instead of their username, you have to set the `Username field` to `email` in the Xen Orchestra plugin configuration. +::: diff --git a/website/integrations/services/zammad/index.md b/website/integrations/services/zammad/index.md index e558072065..7e0db33ff9 100644 --- a/website/integrations/services/zammad/index.md +++ b/website/integrations/services/zammad/index.md @@ -22,7 +22,7 @@ The following placeholders will be used: ### Step 1 - Property Mappings -Create two Mappings (under _Customisation/Property Mappings_) with these settings: +Create two Mappings (under _Customization/Property Mappings_) with these settings: #### name mapping diff --git a/website/integrations/sources-logo.png b/website/integrations/sources-logo.png new file mode 100644 index 0000000000..52fa993834 Binary files /dev/null and b/website/integrations/sources-logo.png differ diff --git a/website/integrations/sources/azure-ad/index.md b/website/integrations/sources/azure-ad/index.md deleted file mode 100644 index 7c9088a6bc..0000000000 --- a/website/integrations/sources/azure-ad/index.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Azure AD ---- - -Support level: Community - -## Preparation - -The following placeholders will be used: - -- `authentik.company` is the FQDN of the authentik install. - -## Azure setup - -1. Navigate to [portal.azure.com](https://portal.azure.com), and open the _App registration_ service -2. Register a new application - - Under _Supported account types_, select whichever account type applies to your use-case. - - ![](./aad_01.png) - -3. Take note of the _Application (client) ID_ value. - - If you selected _Single tenant_ in the _Supported account types_ prompt, also note the _Directory (tenant) ID_ value. - -4. Navigate to _Certificates & secrets_ in the sidebar, and to the _Client secrets_ tab. -5. Add a new secret, with an identifier of your choice, and select any expiration. Currently the secret in authentik has to be rotated manually or via API, so it is recommended to choose at least 12 months. -6. Note the secret's value in the _Value_ column. - -## authentik Setup - -In authentik, create a new _Azure AD OAuth Source_ in Resources -> Sources. - -Use the following settings: - -- Name: `Azure AD` -- Slug: `azure-ad` (this must match the URL being used above) -- Consumer key: `*Application (client) ID* value from above` -- Consumer secret: `*Value* of the secret from above` - -If you kept the default _Supported account types_ selection of _Single tenant_, then you must change the URL below as well: - -- OIDC Well-known URL: `https://login.microsoftonline.com/*Directory (tenant) ID* from above/v2.0/.well-known/openid-configuration` - -![](./authentik_01.png) - -Save, and you now have Azure AD as a source. - -:::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). -::: diff --git a/website/integrations/sources/discord/index.md b/website/integrations/sources/discord/index.md deleted file mode 100644 index 1f673040df..0000000000 --- a/website/integrations/sources/discord/index.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: Discord ---- - -Support level: authentik - -Allows users to authenticate using their Discord credentials - -## Preparation - -The following placeholders will be used: - -- `authentik.company` is the FQDN of the authentik install. - -## Discord - -1. Create an application in the Discord Developer Portal (This is Free) https://discord.com/developers/applications - -![New Application Button](discord1.png) - -2. Name the Application - -![Name App](discord2.png) - -3. Select **OAuth2** from the left Menu - -4. Copy the **Client ID** and _save it for later_ - -5. **Click to Reveal** the Client Secret and _save it for later_ - -6. Click **Add Redirect** and add https://authentik.company/source/oauth/callback/discord/ - -Here is an example of a completed OAuth2 screen for Discord. - -![](discord3.png) - -## authentik - -8. Under _Directory -> Federation & Social login_ Click **Create Discord OAuth Source** - -9. **Name:** Choose a name (For the example I used Discord) -10. **Slug:** discord (You can choose a different slug, if you do you will need to update the Discord redirect URLand point it to the correct slug.) -11. **Consumer Key:** Client ID from step 4 -12. **Consumer Secret:** Client Secret from step 5 - -Here is an example of a complete authentik Discord OAuth Source - -![](discord4.png) - -Save, and you now have Discord as a source. - -:::note -For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page). -::: - -### Checking for membership of a Discord Guild - -:::info -Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds` scope added under the 'Protocol settings'. -::: - -Create a new 'Expression Policy' with the content below, adjusting the variables where required: - -```python -# To get the guild ID number for the parameters, open Discord, go to Settings > Advanced and enable developer mode. -# Right-click on the server/guild title and select "Copy ID" to get the guild ID. - -ACCEPTED_GUILD_ID = "123456789123456789" -GUILD_NAME_STRING = "The desired server/guild name in the error message." - -# Only change below here if you know what you are doing. - -# Ensure flow is only run during OAuth logins via Discord -if context['source'].provider_type != "discord": - return True - -# Get the user-source connection object from the context, and get the access token -connection = context.get("goauthentik.io/sources/connection") -if not connection: - return False -access_token = connection.access_token - -guilds = requests.get( - "https://discord.com/api/users/@me/guilds", - headers= { - "Authorization": f"Bearer {access_token}", - } -).json() - -user_matched = any(ACCEPTED_GUILD_ID == g["id"] for g in guilds) -if not user_matched: - ak_message(f"User is not a member of {GUILD_NAME_STRING}.") -return user_matched -``` - -Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source. - -### Checking for membership of a Discord Guild role - -:::info -Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds guilds.members.read` scopes added under the 'Protocol settings'. -::: - -Create a new 'Expression Policy' with the content below, adjusting the variables where required: - -```python -# To get the role and guild ID numbers for the parameters, open Discord, go to Settings > Advanced and -# enable developer mode. -# Right-click on the server/guild title and select "Copy ID" to get the guild ID. -# Right-click on the server/guild title and select server settings > roles, right click on the role and click -# "Copy ID" to get the role ID. - -ACCEPTED_ROLE_ID = "123456789123456789" -ACCEPTED_GUILD_ID = "123456789123456789" -GUILD_NAME_STRING = "The desired server/guild name in the error message." -ROLE_NAME_STRING = "The desired role name in the error message." - -# Only change below here if you know what you are doing. -GUILD_API_URL = f"https://discord.com/api/users/@me/guilds/{ACCEPTED_GUILD_ID}/member" - -# Ensure flow is only run during OAuth logins via Discord -if context['source'].provider_type != "discord": - return True - -# Get the user-source connection object from the context, and get the access token -connection = context.get("goauthentik.io/sources/connection") -if not connection: - return False -access_token = connection.access_token - -guild_member_object = requests.get( - GUILD_API_URL, - headers= { - "Authorization": f"Bearer {access_token}", - } -).json() - -# The response for JSON errors is held within guild_member_object['code'] -# See: https://discord.com/developers/docs/topics/opcodes-and-status-codes#json -# If the user isn't in the queried guild, it gives the somewhat misleading code = 10004. -if "code" in guild_member_object: - if guild_member_object['code'] == 10004: - ak_message(f"User is not a member of {GUILD_NAME_STRING}.") - else: - ak_create_event("discord_error", source=context['source'], code=guild_member_object['code']) - ak_message("Discord API error, try again later.") - # Policy does not match if there is any error. - return False - -user_matched = any(ACCEPTED_ROLE_ID == g for g in guild_member_object["roles"]) -if not user_matched: - ak_message(f"User is not a member of the {ROLE_NAME_STRING} role in {GUILD_NAME_STRING}.") -return user_matched -``` - -Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source. diff --git a/website/integrations/sources/general.md b/website/integrations/sources/general.md deleted file mode 100644 index f42b60433a..0000000000 --- a/website/integrations/sources/general.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: General -slug: general ---- - -Sources allow you to connect authentik to an existing user directory. They can also be used for social logins, using external providers such as Facebook, Twitter, etc. - -### Add Sources to Default Login Page - -To have sources show on the default login screen you will need to add them. This is assuming you have not created or renamed the default stages and flows. - -1. Access the **Flows** section -2. Click on **default-authentication-flow** -3. Click the **Stage Bindings** tab -4. Chose **Edit Stage** for the _default-authentication-identification_ stage -5. Under **Sources** you should see the additional sources you have configured. Click all applicable sources to have them displayed on the Login Page diff --git a/website/integrations/sources/ldap/index.md b/website/integrations/sources/ldap/index.md deleted file mode 100644 index f64e70a070..0000000000 --- a/website/integrations/sources/ldap/index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: LDAP ---- - -Sources allow you to connect authentik to an existing user directory. They can also be used for social logins, using external providers such as Facebook, Twitter, etc. - -## LDAP Source - -This source allows you to import users and groups from an LDAP Server. - -:::info -For Active Directory, follow the [Active Directory Integration](../active-directory/) - -For FreeIPA, follow the [FreeIPA Integration](../freeipa/) -::: - -- Server URI: URI to your LDAP server/Domain Controller. - - You can specify multiple servers by separating URIs with a comma, like `ldap://ldap1.company,ldap://ldap2.company`. - - When using a DNS entry with multiple Records, authentik will select a random entry when first connecting. - -- Bind CN: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`. -- Bind password: Password used during the bind process. -- Enable StartTLS: Enables StartTLS functionality. To use LDAPS instead, use port `636`. -- Base DN: Base DN used for all LDAP queries. -- Addition User DN: Prepended to the base DN for user queries. -- Addition Group DN: Prepended to the base DN for group queries. -- User object filter: Consider objects matching this filter to be users. -- Group object filter: Consider objects matching this filter to be groups. -- User group membership field: This field contains the user's group memberships. -- Object uniqueness field: This field contains a unique identifier. -- Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. -- Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. -- Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping) - -## Property mappings - -LDAP property mappings can be used to convert the raw LDAP response into an authentik user/group. - -By default, authentik ships with some pre-configured mappings for the most common LDAP setups. - -You can assign the value of a mapping to any user attribute, or save it as a custom attribute by prefixing the object field with `attribute.` Keep in mind though, data types from the LDAP server will be carried over. This means that with some implementations, where fields are stored as array in LDAP, they will be saved as array in authentik. To prevent this, use the built-in `list_flatten` function. - -## Troubleshooting - -To troubleshoot LDAP sources and their synchronization, see [LDAP Troubleshooting](../../../docs/troubleshooting/ldap_source) diff --git a/website/netlify.toml b/website/netlify.toml index bf3fd1a387..bd9144cb4c 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -1,6 +1,6 @@ [[redirects]] - from = "/discord" - to = "https://discord.gg/jg33eMhnj6" + from = "/blog/*" + to = "https://goauthentik.io/blog/:splat" # Migration from docs to separate directory [[redirects]] @@ -29,39 +29,6 @@ status = 301 force = true -# Container registry -[[redirects]] - from = "/v2" - to = "/.netlify/functions/oci-proxy" - status = 200 - force = true - -[[redirects]] - from = "/v2/*" - to = "https://ghcr.io/v2/goauthentik/:splat" - status = 200 - force = true - -[[redirects]] - from = "/version/*" - to = "https://raw.githubusercontent.com/goauthentik/authentik/version-:splat" - -[[redirects]] - from = "/js/script.js" - to = "https://plausible.a7k.io/js/plausible.outbound-links.js" - status = 200 - force = true - -[[redirects]] - from = "/api/event" - to = "https://plausible.a7k.io/api/event" - status = 200 - force = true - -[[redirects]] - from = "/community/show_setup" - to = "https://docs.google.com/forms/d/1g5W3kz-7EJ3zay8S3C5aN2vIdZQuzT_MJljb6yv80_I" - [[headers]] for = "/*" [headers.values] @@ -71,3 +38,15 @@ command = "npm run watch" targetPort = 3000 publish = "build" + +# Moving doc files +[[redirects]] + from = "/docs/core/applications" + to = "/docs/applications" + status = 302 + +# Moved Sources from Integrations to Docs +[[redirects]] + from = "/integrations/sources/*" + to = "/docs/sources/:splat" + status = 302 diff --git a/website/netlify/functions/oci-proxy.js b/website/netlify/functions/oci-proxy.js deleted file mode 100644 index 54ac0b807f..0000000000 --- a/website/netlify/functions/oci-proxy.js +++ /dev/null @@ -1,78 +0,0 @@ -const config = { - namespace: "goauthentik/", - registryTokenEndpoint: "https://ghcr.io/token", - registryService: "ghcr.io", -}; - -async function getToken(event) { - const fetch = await import("node-fetch"); - const querystring = await import("querystring"); - let scope = event.queryStringParameters["scope"]; - let tokenParams = { - service: config.registryService, - }; - delete event.headers.host; - let forwardHeaders = event.headers; - if (scope && scope.includes(":")) { - const repo = scope.split(":")[1]; - console.debug(`oci-proxy[token]: original scope: ${scope}`); - scope = `repository:${config.namespace}${repo}:pull`; - console.debug(`oci-proxy[token]: rewritten scope: ${scope}`); - tokenParams["scope"] = scope; - // We only need to forward headers for authentication requests - forwardHeaders = {}; - } else { - console.debug(`oci-proxy[token]: no scope`); - // For non-scoped requests, we need to forward some URL parameters - ["account", "client_id", "offline_token", "token"].forEach((param) => { - tokenParams[param] = event.queryStringParameters[param]; - }); - } - const tokenUrl = `${config.registryTokenEndpoint}?${querystring.stringify( - tokenParams, - )}`; - console.debug(`oci-proxy[token]: final URL to fetch: ${tokenUrl}`); - const tokenRes = await fetch.default(tokenUrl, { - headers: forwardHeaders, - }); - const tokenResult = await tokenRes.text(); - console.debug(`oci-proxy[token]: Status ${tokenRes.status}`); - return { - statusCode: tokenRes.status, - body: tokenResult, - }; -} - -exports.handler = async function (event, context) { - console.debug(`oci-proxy: URL ${event.httpMethod} ${event.rawUrl}`); - if (event.queryStringParameters.hasOwnProperty("token")) { - console.debug("oci-proxy: handler=token proxy"); - return await getToken(event); - } - if ( - event.headers.authorization && - event.headers.authorization.startsWith("Bearer ") - ) { - console.debug("oci-proxy: authenticated root handler, returning 200"); - return { - statusCode: 200, - headers: { - "Docker-Distribution-API-Version": "registry/2.0", - "content-type": "application/json", - }, - body: JSON.stringify({}), - }; - } - console.debug( - "oci-proxy: root handler, returning 401 with www-authenticate", - ); - return { - statusCode: 401, - headers: { - "www-authenticate": `Bearer realm="https://${event.headers.host}/v2?token",service="${event.headers.host}",scope="repository:user/image:pull"`, - "Docker-Distribution-API-Version": "registry/2.0", - "content-type": "application/json", - }, - body: JSON.stringify({}), - }; -}; diff --git a/website/package-lock.json b/website/package-lock.json index c0969221f6..64c00ffaec 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1,41 +1,42 @@ { - "name": "@goauthentik/website", + "name": "@goauthentik/website-docs", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@goauthentik/website", + "name": "@goauthentik/website-docs", "version": "0.0.0", "license": "MIT", "dependencies": { - "@docusaurus/core": "^3.1.0", - "@docusaurus/plugin-client-redirects": "^3.1.0", - "@docusaurus/plugin-content-docs": "^3.1.0", - "@docusaurus/preset-classic": "^3.1.0", - "@docusaurus/theme-common": "^3.1.0", - "@docusaurus/theme-mermaid": "^3.1.0", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.1.0", + "@docusaurus/core": "^3.3.2", + "@docusaurus/plugin-client-redirects": "^3.3.2", + "@docusaurus/plugin-content-docs": "^3.3.2", + "@docusaurus/preset-classic": "^3.3.2", + "@docusaurus/theme-common": "^3.3.2", + "@docusaurus/theme-mermaid": "^3.3.2", + "@mdx-js/react": "^3.0.1", + "clsx": "^2.1.1", "disqus-react": "^1.1.5", - "postcss": "^8.4.33", + "docusaurus-plugin-openapi-docs": "^3.0.0-beta.10", + "docusaurus-theme-openapi-docs": "^3.0.0-beta.10", + "postcss": "^8.4.38", "prism-react-renderer": "^2.3.1", - "rapidoc": "^9.3.4", - "react": "^18.2.0", + "react": "^18.3.1", "react-before-after-slider-component": "^1.1.8", - "react-dom": "^18.2.0", + "react-dom": "^18.3.1", "react-feather": "^2.0.10", "react-toggle": "^4.1.3", - "react-tooltip": "^5.26.0", + "react-tooltip": "^5.26.4", "remark-github": "^12.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/tsconfig": "3.1.0", - "@docusaurus/types": "3.1.0", - "@types/react": "^18.2.48", - "prettier": "3.2.4", - "typescript": "~5.3.3" + "@docusaurus/module-type-aliases": "^3.3.2", + "@docusaurus/tsconfig": "^3.3.2", + "@docusaurus/types": "^3.3.2", + "@types/react": "^18.3.3", + "prettier": "3.2.5", + "typescript": "~5.4.5" }, "engines": { "node": ">=20" @@ -83,74 +84,74 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", - "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", + "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.3" } }, "node_modules/@algolia/cache-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", - "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==" + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", + "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", - "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", + "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.3" } }, "node_modules/@algolia/client-account": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", - "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", + "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-analytics": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", - "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", + "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", - "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", + "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", "dependencies": { - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-personalization": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", - "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", + "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-search": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", - "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", + "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/events": { @@ -159,47 +160,65 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/logger-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", - "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==" + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", + "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==" }, "node_modules/@algolia/logger-console": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", - "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", + "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", "dependencies": { - "@algolia/logger-common": "4.22.1" + "@algolia/logger-common": "4.23.3" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", + "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", - "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", + "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.3" } }, "node_modules/@algolia/requester-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", - "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==" + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", + "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", - "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", + "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.3" } }, "node_modules/@algolia/transporter": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", - "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", + "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", "dependencies": { - "@algolia/cache-common": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/requester-common": "4.22.1" + "@algolia/cache-common": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/requester-common": "4.23.3" } }, "node_modules/@ampproject/remapping": { @@ -214,94 +233,38 @@ "node": ">=6.0.0" } }, - "node_modules/@apitools/openapi-parser": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@apitools/openapi-parser/-/openapi-parser-0.0.30.tgz", - "integrity": "sha512-e8KttEjBSozuSO7IVeFTRvzqgsbxwFtGbwc1Yi/u8EgzDqtVpTOgZ5qfSwtzAdKNkx0x+oi+s/1imCAju0lhTA==", + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.1.tgz", + "integrity": "sha512-DxjgKBCoyReu4p5HMvpmgSOfRhhBcuf5V5soDDRgOTZMwsA4KSFzol1abFZgiCTE11L2kKGca5Md9GwDdXVBwQ==", "dependencies": { - "swagger-client": "^3.18.5" + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "engines": { "node": ">=6.9.0" } @@ -344,13 +307,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", - "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dependencies": { - "@babel/types": "^7.23.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -380,13 +343,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -514,26 +477,26 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -554,9 +517,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "engines": { "node": ">=6.9.0" } @@ -594,11 +557,11 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -616,36 +579,36 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "engines": { "node": ">=6.9.0" } @@ -664,26 +627,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", - "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.5", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -754,9 +718,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1616,11 +1580,11 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", - "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.1.tgz", + "integrity": "sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2073,32 +2037,32 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", - "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2106,12 +2070,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", - "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2141,18 +2105,18 @@ } }, "node_modules/@docsearch/css": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", - "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==" + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==" }, "node_modules/@docsearch/react": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", - "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", "dependencies": { "@algolia/autocomplete-core": "1.9.3", "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.5.2", + "@docsearch/css": "3.6.0", "algoliasearch": "^4.19.1" }, "peerDependencies": { @@ -2177,9 +2141,9 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.1.0.tgz", - "integrity": "sha512-GWudMGYA9v26ssbAWJNfgeDZk+lrudUTclLPRsmxiknEBk7UMp7Rglonhqbsf3IKHOyHkMU4Fr5jFyg5SBx9jQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.3.2.tgz", + "integrity": "sha512-PzKMydKI3IU1LmeZQDi+ut5RSuilbXnA8QdowGeJEgU8EJjmx3rBHNT1LxQxOVqNEwpWi/csLwd9bn7rUjggPA==", "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2191,15 +2155,12 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", - "@slorber/static-site-generator-webpack-plugin": "^4.0.7", - "@svgr/webpack": "^6.5.1", + "@docusaurus/cssnano-preset": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "autoprefixer": "^10.4.14", "babel-loader": "^9.1.3", "babel-plugin-dynamic-import-node": "^2.3.3", @@ -2213,12 +2174,13 @@ "copy-webpack-plugin": "^11.0.0", "core-js": "^3.31.1", "css-loader": "^6.8.1", - "css-minimizer-webpack-plugin": "^4.2.2", - "cssnano": "^5.1.15", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", "del": "^6.1.1", "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", + "eval": "^0.1.8", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "html-minifier-terser": "^7.2.0", @@ -2227,12 +2189,13 @@ "leven": "^3.1.0", "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", "postcss": "^8.4.26", "postcss-loader": "^7.3.3", "prompts": "^2.4.2", "react-dev-utils": "^12.0.1", "react-helmet-async": "^1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", "react-loadable-ssr-addon-v5-slorber": "^1.0.1", "react-router": "^5.3.4", "react-router-config": "^5.1.1", @@ -2263,13 +2226,13 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.1.0.tgz", - "integrity": "sha512-ned7qsgCqSv/e7KyugFNroAfiszuxLwnvMW7gmT2Ywxb/Nyt61yIw7KHyAZCMKglOalrqnYA4gMhLUCK/mVePA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.3.2.tgz", + "integrity": "sha512-+5+epLk/Rp4vFML4zmyTATNc3Is+buMAL6dNjrMWahdJCJlMWMPd/8YfU+2PA57t8mlSbhLJ7vAZVy54cd1vRQ==", "dependencies": { - "cssnano-preset-advanced": "^5.3.10", - "postcss": "^8.4.26", - "postcss-sort-media-queries": "^4.4.1", + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", "tslib": "^2.6.0" }, "engines": { @@ -2277,9 +2240,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.1.0.tgz", - "integrity": "sha512-p740M+HCst1VnKKzL60Hru9xfG4EUYJDarjlEC4hHeBy9+afPmY3BNPoSHx9/8zxuYfUlv/psf7I9NvRVdmdvg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.3.2.tgz", + "integrity": "sha512-Ldu38GJ4P8g4guN7d7pyCOJ7qQugG7RVyaxrK8OnxuTlaImvQw33aDRwaX2eNmX8YK6v+//Z502F4sOZbHHCHQ==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -2289,15 +2252,13 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.1.0.tgz", - "integrity": "sha512-D7onDz/3mgBonexWoQXPw3V2E5Bc4+jYRf9gGUUK+KoQwU8xMDaDkUUfsr7t6UBa/xox9p5+/3zwLuXOYMzGSg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.3.2.tgz", + "integrity": "sha512-AFRxj/aOk3/mfYDPxE3wTbrjeayVRvNSZP7mgMuUlrb2UlPRbSVAFX1k2RbgAJrnTSwMgb92m2BhJgYRfptN3g==", "dependencies": { - "@babel/parser": "^7.22.7", - "@babel/traverse": "^7.22.8", - "@docusaurus/logger": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/logger": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -2329,18 +2290,17 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.1.0.tgz", - "integrity": "sha512-XUl7Z4PWlKg4l6KF05JQ3iDHQxnPxbQUqTNKvviHyuHdlalOFv6qeDAm7IbzyQPJD5VA6y4dpRbTWSqP9ClwPg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.3.2.tgz", + "integrity": "sha512-b/XB0TBJah5yKb4LYuJT4buFvL0MGAb0+vJDrJtlYMguRtsEBkf2nWl5xP7h4Dlw6ol0hsHrCYzJ50kNIOEclw==", "dependencies": { - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.1.0", + "@docusaurus/types": "3.3.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, "peerDependencies": { "react": "*", @@ -2348,15 +2308,15 @@ } }, "node_modules/@docusaurus/plugin-client-redirects": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.1.0.tgz", - "integrity": "sha512-CuFbdciMGvtGYiIPSOpj5idsHOQUcqZWTLCmZV3ePhviekm4dRZm1+QK/BxigmSTL5ICJMGbtOQnz7bgFSWHqg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.3.2.tgz", + "integrity": "sha512-W8ueb5PaQ06oanatL+CzE3GjqeRBTzv3MSFqEQlBa8BqLyOomc1uHsWgieE3glHsckU4mUZ6sHnOfesAtYnnew==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "eta": "^2.2.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21", @@ -2371,17 +2331,17 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.1.0.tgz", - "integrity": "sha512-iMa6WBaaEdYuxckvJtLcq/HQdlA4oEbCXf/OFfsYJCCULcDX7GDZpKxLF3X1fLsax3sSm5bmsU+CA0WD+R1g3A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.3.2.tgz", + "integrity": "sha512-fJU+dmqp231LnwDJv+BHVWft8pcUS2xVPZdeYH6/ibH1s2wQ/sLcmUrGWyIv/Gq9Ptj8XWjRPMghlxghuPPoxg==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -2402,17 +2362,18 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.1.0.tgz", - "integrity": "sha512-el5GxhT8BLrsWD0qGa8Rq+Ttb/Ni6V3DGT2oAPio0qcs/mUAxeyXEAmihkvmLCnAgp6xD27Ce7dISZ5c6BXeqA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.3.2.tgz", + "integrity": "sha512-Dm1ri2VlGATTN3VGk1ZRqdRXWa1UlFubjaEL6JaxaK7IIFqN/Esjpl+Xw10R33loHcRww/H76VdEeYayaL76eg==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/module-type-aliases": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -2431,15 +2392,15 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.1.0.tgz", - "integrity": "sha512-9gntYQFpk+93+Xl7gYczJu8I9uWoyRLnRwS0+NUFcs9iZtHKsdqKWPRrONC9elfN3wJ9ORwTbcVzsTiB8jvYlg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.3.2.tgz", + "integrity": "sha512-EKc9fQn5H2+OcGER8x1aR+7URtAGWySUgULfqE/M14+rIisdrBstuEZ4lUPDRrSIexOVClML82h2fDS+GSb8Ew==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2453,13 +2414,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.1.0.tgz", - "integrity": "sha512-AbvJwCVRbmQ8w9d8QXbF4Iq/ui0bjPZNYFIhtducGFnm2YQRN1mraK8mCEQb0Aq0T8SqRRvSfC/far4n/s531w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.3.2.tgz", + "integrity": "sha512-oBIBmwtaB+YS0XlmZ3gCO+cMbsGvIYuAKkAopoCh0arVjtlyPbejzPrHuCoRHB9G7abjNZw7zoONOR8+8LM5+Q==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" @@ -2473,13 +2434,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.1.0.tgz", - "integrity": "sha512-zvUOMzu9Uhz0ciqnSbtnp/5i1zEYlzarQrOXG90P3Is3efQI43p2YLW/rzSGdLb5MfQo2HvKT6Q5+tioMO045Q==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.3.2.tgz", + "integrity": "sha512-jXhrEIhYPSClMBK6/IA8qf1/FBoxqGXZvg7EuBax9HaK9+kL3L0TJIlatd8jQJOMtds8mKw806TOCc3rtEad1A==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "tslib": "^2.6.0" }, "engines": { @@ -2491,13 +2452,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.1.0.tgz", - "integrity": "sha512-0txshvaY8qIBdkk2UATdVcfiCLGq3KAUfuRQD2cRNgO39iIf4/ihQxH9NXcRTwKs4Q5d9yYHoix3xT6pFuEYOg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.3.2.tgz", + "integrity": "sha512-vcrKOHGbIDjVnNMrfbNpRQR1x6Jvcrb48kVzpBAOsKbj9rXZm/idjVAXRaewwobHdOrJkfWS/UJoxzK8wyLRBQ==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2510,13 +2471,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.1.0.tgz", - "integrity": "sha512-zOWPEi8kMyyPtwG0vhyXrdbLs8fIZmY5vlbi9lUU+v8VsroO5iHmfR2V3SMsrsfOanw5oV/ciWqbxezY00qEZg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.3.2.tgz", + "integrity": "sha512-ldkR58Fdeks0vC+HQ+L+bGFSJsotQsipXD+iKXQFvkOfmPIV6QbHRd7IIcm5b6UtwOiK33PylNS++gjyLUmaGw==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "tslib": "^2.6.0" }, "engines": { @@ -2528,16 +2489,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.1.0.tgz", - "integrity": "sha512-TkR5vGBpUooEB9SoW42thahqqwKzfHrQQhkB+JrEGERsl4bKODSuJNle4aA4h6LSkg4IyfXOW8XOI0NIPWb9Cg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.3.2.tgz", + "integrity": "sha512-/ZI1+bwZBhAgC30inBsHe3qY9LOZS+79fRGkNdTcGHRMcdAp6Vw2pCd1gzlxd/xU+HXsNP6cLmTOrggmRp3Ujg==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2551,23 +2512,23 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.1.0.tgz", - "integrity": "sha512-xGLQRFmmT9IinAGUDVRYZ54Ys28USNbA3OTXQXnSJLPr1rCY7CYnHI4XoOnKWrNnDiAI4ruMzunXWyaElUYCKQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.3.2.tgz", + "integrity": "sha512-1SDS7YIUN1Pg3BmD6TOTjhB7RSBHJRpgIRKx9TpxqyDrJ92sqtZhomDc6UYoMMLQNF2wHFZZVGFjxJhw2VpL+Q==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/plugin-content-blog": "3.1.0", - "@docusaurus/plugin-content-docs": "3.1.0", - "@docusaurus/plugin-content-pages": "3.1.0", - "@docusaurus/plugin-debug": "3.1.0", - "@docusaurus/plugin-google-analytics": "3.1.0", - "@docusaurus/plugin-google-gtag": "3.1.0", - "@docusaurus/plugin-google-tag-manager": "3.1.0", - "@docusaurus/plugin-sitemap": "3.1.0", - "@docusaurus/theme-classic": "3.1.0", - "@docusaurus/theme-common": "3.1.0", - "@docusaurus/theme-search-algolia": "3.1.0", - "@docusaurus/types": "3.1.0" + "@docusaurus/core": "3.3.2", + "@docusaurus/plugin-content-blog": "3.3.2", + "@docusaurus/plugin-content-docs": "3.3.2", + "@docusaurus/plugin-content-pages": "3.3.2", + "@docusaurus/plugin-debug": "3.3.2", + "@docusaurus/plugin-google-analytics": "3.3.2", + "@docusaurus/plugin-google-gtag": "3.3.2", + "@docusaurus/plugin-google-tag-manager": "3.3.2", + "@docusaurus/plugin-sitemap": "3.3.2", + "@docusaurus/theme-classic": "3.3.2", + "@docusaurus/theme-common": "3.3.2", + "@docusaurus/theme-search-algolia": "3.3.2", + "@docusaurus/types": "3.3.2" }, "engines": { "node": ">=18.0" @@ -2577,35 +2538,23 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/react-loadable": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", - "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", - "dependencies": { - "@types/react": "*", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": "*" - } - }, "node_modules/@docusaurus/theme-classic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.1.0.tgz", - "integrity": "sha512-/+jMl2Z9O8QQxves5AtHdt91gWsEZFgOV3La/6eyKEd7QLqQUtM5fxEJ40rq9NKYjqCd1HzZ9egIMeJoWwillw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.3.2.tgz", + "integrity": "sha512-gepHFcsluIkPb4Im9ukkiO4lXrai671wzS3cKQkY9BXQgdVwsdPf/KS0Vs4Xlb0F10fTz+T3gNjkxNEgSN9M0A==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/plugin-content-blog": "3.1.0", - "@docusaurus/plugin-content-docs": "3.1.0", - "@docusaurus/plugin-content-pages": "3.1.0", - "@docusaurus/theme-common": "3.1.0", - "@docusaurus/theme-translations": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/module-type-aliases": "3.3.2", + "@docusaurus/plugin-content-blog": "3.3.2", + "@docusaurus/plugin-content-docs": "3.3.2", + "@docusaurus/plugin-content-pages": "3.3.2", + "@docusaurus/theme-common": "3.3.2", + "@docusaurus/theme-translations": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -2629,17 +2578,17 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.1.0.tgz", - "integrity": "sha512-YGwEFALLIbF5ocW/Fy6Ae7tFWUOugEN3iwxTx8UkLAcLqYUboDSadesYtVBmRCEB4FVA2qoP7YaW3lu3apUPPw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.3.2.tgz", + "integrity": "sha512-kXqSaL/sQqo4uAMQ4fHnvRZrH45Xz2OdJ3ABXDS7YVGPSDTBC8cLebFrRR4YF9EowUHto1UC/EIklJZQMG/usA==", "dependencies": { - "@docusaurus/mdx-loader": "3.1.0", - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/plugin-content-blog": "3.1.0", - "@docusaurus/plugin-content-docs": "3.1.0", - "@docusaurus/plugin-content-pages": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-common": "3.1.0", + "@docusaurus/mdx-loader": "3.3.2", + "@docusaurus/module-type-aliases": "3.3.2", + "@docusaurus/plugin-content-blog": "3.3.2", + "@docusaurus/plugin-content-docs": "3.3.2", + "@docusaurus/plugin-content-pages": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2658,15 +2607,15 @@ } }, "node_modules/@docusaurus/theme-mermaid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.1.0.tgz", - "integrity": "sha512-63y08fvRWIe9satRV1e/Dps9he+sPjQ+kwl4ccQQEzkM2nxeAgWwk8WzpbVhm1Pf02N/11y0C6FcvFqn4dERHA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.3.2.tgz", + "integrity": "sha512-JY6q7owe5S5iH2N9oTjNDkqmuPW/+4j/zrX46Xag4RYOzt+WtMkeJilbzak8QGG8I2wDJXjUvX7Lu/jWuDAwUg==", "dependencies": { - "@docusaurus/core": "3.1.0", - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/theme-common": "3.1.0", - "@docusaurus/types": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/module-type-aliases": "3.3.2", + "@docusaurus/theme-common": "3.3.2", + "@docusaurus/types": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "mermaid": "^10.4.0", "tslib": "^2.6.0" }, @@ -2679,18 +2628,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.1.0.tgz", - "integrity": "sha512-8cJH0ZhPsEDjq3jR3I+wHmWzVY2bXMQJ59v2QxUmsTZxbWA4u+IzccJMIJx4ooFl9J6iYynwYsFuHxyx/KUmfQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.3.2.tgz", + "integrity": "sha512-qLkfCl29VNBnF1MWiL9IyOQaHxUvicZp69hISyq/xMsNvFKHFOaOfk9xezYod2Q9xx3xxUh9t/QPigIei2tX4w==", "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.1.0", - "@docusaurus/logger": "3.1.0", - "@docusaurus/plugin-content-docs": "3.1.0", - "@docusaurus/theme-common": "3.1.0", - "@docusaurus/theme-translations": "3.1.0", - "@docusaurus/utils": "3.1.0", - "@docusaurus/utils-validation": "3.1.0", + "@docusaurus/core": "3.3.2", + "@docusaurus/logger": "3.3.2", + "@docusaurus/plugin-content-docs": "3.3.2", + "@docusaurus/theme-common": "3.3.2", + "@docusaurus/theme-translations": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-validation": "3.3.2", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -2709,9 +2658,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.1.0.tgz", - "integrity": "sha512-DApE4AbDI+WBajihxB54L4scWQhVGNZAochlC9fkbciPuFAgdRBD3NREb0rgfbKexDC/rioppu/WJA0u8tS+yA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.3.2.tgz", + "integrity": "sha512-bPuiUG7Z8sNpGuTdGnmKl/oIPeTwKr0AXLGu9KaP6+UFfRZiyWbWE87ti97RrevB2ffojEdvchNujparR3jEZQ==", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2721,15 +2670,15 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.1.0.tgz", - "integrity": "sha512-PE6fSuj5gJy5sNC1OO+bYAU1/xZH5YqddGjhrNu3/T7OAUroqkMZfVl13Tz70CjYB8no4OWcraqSkObAeNdIcQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.3.2.tgz", + "integrity": "sha512-2MQXkLoWqgOSiqFojNEq8iPtFBHGQqd1b/SQMoe+v3GgHmk/L6YTTO/hMcHhWb1hTFmbkei++IajSfD3RlZKvw==", "dev": true }, "node_modules/@docusaurus/types": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", - "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.3.2.tgz", + "integrity": "sha512-5p201S7AZhliRxTU7uMKtSsoC8mgPA9bs9b5NQg1IRdRxJfflursXNVsgc3PcMqiUTul/v1s3k3rXXFlRE890w==", "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", @@ -2747,12 +2696,13 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.1.0.tgz", - "integrity": "sha512-LgZfp0D+UBqAh7PZ//MUNSFBMavmAPku6Si9x8x3V+S318IGCNJ6hUr2O29UO0oLybEWUjD5Jnj9IUN6XyZeeg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.3.2.tgz", + "integrity": "sha512-f4YMnBVymtkSxONv4Y8js3Gez9IgHX+Lcg6YRMOjVbq8sgCcdYK1lf6SObAuz5qB/mxiSK7tW0M9aaiIaUSUJg==", "dependencies": { - "@docusaurus/logger": "3.1.0", - "@svgr/webpack": "^6.5.1", + "@docusaurus/logger": "3.3.2", + "@docusaurus/utils-common": "3.3.2", + "@svgr/webpack": "^8.1.0", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", @@ -2763,6 +2713,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", + "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", "shelljs": "^0.8.5", "tslib": "^2.6.0", @@ -2782,9 +2733,9 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.1.0.tgz", - "integrity": "sha512-SfvnRLHoZ9bwTw67knkSs7IcUR0GY2SaGkpdB/J9pChrDiGhwzKNUhcieoPyPYrOWGRPk3rVNYtoy+Bc7psPAw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.3.2.tgz", + "integrity": "sha512-QWFTLEkPYsejJsLStgtmetMFIA3pM8EPexcZ4WZ7b++gO5jGVH7zsipREnCHzk6+eDgeaXfkR6UPaTt86bp8Og==", "dependencies": { "tslib": "^2.6.0" }, @@ -2801,12 +2752,13 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.1.0.tgz", - "integrity": "sha512-dFxhs1NLxPOSzmcTk/eeKxLY5R+U4cua22g9MsAMiRWcwFKStZ2W3/GDY0GmnJGqNS8QAQepJrxQoyxXkJNDeg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.3.2.tgz", + "integrity": "sha512-itDgFs5+cbW9REuC7NdXals4V6++KifgVMzoGOOOSIifBQw+8ULhy86u5e1lnptVL0sv8oAjq2alO7I40GR7pA==", "dependencies": { - "@docusaurus/logger": "3.1.0", - "@docusaurus/utils": "3.1.0", + "@docusaurus/logger": "3.3.2", + "@docusaurus/utils": "3.3.2", + "@docusaurus/utils-common": "3.3.2", "joi": "^17.9.2", "js-yaml": "^4.1.0", "tslib": "^2.6.0" @@ -2815,35 +2767,32 @@ "node": ">=18.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", - "engines": { - "node": ">=14" - } + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==" }, "node_modules/@floating-ui/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", - "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", "dependencies": { - "@floating-ui/utils": "^0.1.3" + "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", - "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.2.tgz", + "integrity": "sha512-xymkSSowKdGqo0SRr2Mp4czH5A8o2Pum35PAD0ftb3gCcPacWzwhvtUeUqmVXm9EVtm2hThD/lRrFNcahMOaSQ==", "dependencies": { - "@floating-ui/core": "^1.4.2", - "@floating-ui/utils": "^0.1.3" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/utils": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", - "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, "node_modules/@hapi/hoek": { "version": "9.3.0", @@ -2858,6 +2807,57 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@hookform/error-message": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.1.tgz", + "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-hook-form": "^7.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2886,13 +2886,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2907,9 +2907,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -2929,32 +2929,24 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz", - "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==" - }, - "node_modules/@lit/reactive-element": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", - "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.0.0" - } - }, "node_modules/@mdx-js/mdx": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.0.tgz", @@ -2990,9 +2982,9 @@ } }, "node_modules/@mdx-js/react": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", - "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dependencies": { "@types/mdx": "^2.0.0" }, @@ -3037,6 +3029,176 @@ "node": ">= 8" } }, + "node_modules/@paloaltonetworks/openapi-to-postmanv2": { + "version": "3.1.0-hotfix.1", + "resolved": "https://registry.npmjs.org/@paloaltonetworks/openapi-to-postmanv2/-/openapi-to-postmanv2-3.1.0-hotfix.1.tgz", + "integrity": "sha512-0bdaPCEyQbnUo4xpOu7EzxXXkDx4BAXqc8QSbVBlzlVB5KoTLJiKKB4c3fa4BXbK+3u/OqfLbeNCebc2EC8ngA==", + "dependencies": { + "@paloaltonetworks/postman-collection": "^4.1.0", + "ajv": "8.1.0", + "ajv-formats": "2.1.1", + "async": "3.2.1", + "commander": "2.20.3", + "js-yaml": "3.14.1", + "json-schema-merge-allof": "0.8.1", + "lodash": "4.17.21", + "oas-resolver-browser": "2.5.2", + "path-browserify": "1.0.1", + "yaml": "1.10.2" + }, + "bin": { + "openapi2postmanv2": "bin/openapi2postmanv2.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@paloaltonetworks/openapi-to-postmanv2/node_modules/ajv": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", + "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@paloaltonetworks/openapi-to-postmanv2/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@paloaltonetworks/openapi-to-postmanv2/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/@paloaltonetworks/openapi-to-postmanv2/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@paloaltonetworks/postman-code-generators": { + "version": "1.1.15-patch.2", + "resolved": "https://registry.npmjs.org/@paloaltonetworks/postman-code-generators/-/postman-code-generators-1.1.15-patch.2.tgz", + "integrity": "sha512-tRnAKtV4M8wLxcVnAx6ZCjCqbrR1xiqJNQkf1A71K8UxEP3N/+EspT82N5c0555w02oYFk21ViHuzuhm4gaGLw==", + "hasInstallScript": true, + "dependencies": { + "@paloaltonetworks/postman-collection": "^4.1.0", + "async": "^3.2.4", + "path": "^0.12.7", + "shelljs": "^0.8.5" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@paloaltonetworks/postman-code-generators/node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/@paloaltonetworks/postman-collection": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@paloaltonetworks/postman-collection/-/postman-collection-4.1.1.tgz", + "integrity": "sha512-9JHHkkD8Xb4rvdKob7TDPRfqfmdG3KU0aO5gJyyjvMFbOVysam5I0d8/9HPOuJXWkUHGo3Sn+ov2Fcm2bnJ52Q==", + "dependencies": { + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.34", + "postman-url-encoder": "3.0.5", + "semver": "7.3.5", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@paloaltonetworks/postman-collection/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -3079,6 +3241,49 @@ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==" }, + "node_modules/@redocly/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/config": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.2.0.tgz", + "integrity": "sha512-r0TqTPVXrxdvhpbOntWnJofOx0rC7u+A+tfC0KFwMtw38QCNb3pwodVjeLa7MT5Uu+fcPxfO119yLBj0QHvBuQ==" + }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -3123,25 +3328,12 @@ "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", - "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", - "dependencies": { - "eval": "^0.1.8", - "p-map": "^4.0.0", - "webpack-sources": "^3.2.2" - }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", "engines": { "node": ">=14" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", - "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", - "engines": { - "node": ">=10" }, "funding": { "type": "github", @@ -3182,11 +3374,11 @@ } }, "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", - "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3197,11 +3389,11 @@ } }, "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", - "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3212,11 +3404,11 @@ } }, "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", - "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3227,11 +3419,11 @@ } }, "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", - "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3242,9 +3434,9 @@ } }, "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", - "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", "engines": { "node": ">=12" }, @@ -3257,21 +3449,21 @@ } }, "node_modules/@svgr/babel-preset": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", - "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", - "@svgr/babel-plugin-remove-jsx-attribute": "*", - "@svgr/babel-plugin-remove-jsx-empty-expression": "*", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", - "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", - "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", - "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", - "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3282,18 +3474,18 @@ } }, "node_modules/@svgr/core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", - "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dependencies": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.1" + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3301,15 +3493,15 @@ } }, "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", - "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", "dependencies": { - "@babel/types": "^7.20.0", + "@babel/types": "^7.21.3", "entities": "^4.4.0" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3317,37 +3509,37 @@ } }, "node_modules/@svgr/plugin-jsx": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", - "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", "dependencies": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/hast-util-to-babel-ast": "^6.5.1", + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", "svg-parser": "^2.0.4" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "@svgr/core": "^6.0.0" + "@svgr/core": "*" } }, "node_modules/@svgr/plugin-svgo": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", - "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", "dependencies": { - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "svgo": "^2.8.0" + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", @@ -3358,447 +3550,27 @@ } }, "node_modules/@svgr/webpack": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", - "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", "dependencies": { - "@babel/core": "^7.19.6", - "@babel/plugin-transform-react-constant-elements": "^7.18.12", - "@babel/preset-env": "^7.19.4", + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@svgr/core": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", - "@svgr/plugin-svgo": "^6.5.1" + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { "type": "github", "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@swagger-api/apidom-ast": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.82.2.tgz", - "integrity": "sha512-k41OHMe5FftHFJhj5LH+Y44BA4/ddoVH4vUv36tW+fU3qkC350VmkdMVglD0BhwZA9S8OpCSz4xmRfbyOGHirw==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-error": "^0.82.1", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", - "unraw": "^3.0.0" - } - }, - "node_modules/@swagger-api/apidom-core": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.82.2.tgz", - "integrity": "sha512-RVPpIA+qti1t116K3dhieofGvembdP3j7THs8+d0j3AMvz2/DK6+2uwLb2EptOAOAqWgIf/fycgwGBoo8/PyuQ==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@types/ramda": "~0.29.6", - "minim": "~0.23.8", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "short-unique-id": "^5.0.2", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-error": { - "version": "0.82.1", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.82.1.tgz", - "integrity": "sha512-nL/7kDBtwf7JQqSWet1Bl0fMaCjxvyC5sKyNRGO1KzkB2XJp2DPOXsoXgPjnCvAG5ksgIa0LNyxUr+6hKbB19g==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7" - } - }, - "node_modules/@swagger-api/apidom-json-pointer": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.82.2.tgz", - "integrity": "sha512-AQ9etS31kNDOVwpy7K9n9dvBYFmnbV7f/9zwrU/WElYdJzWVORxvCfTb7QjVjgQrZg+X387aHaI1LHqs1DE2Kg==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-ns-api-design-systems": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.82.2.tgz", - "integrity": "sha512-gXejkdl4yrTd+rYYTV/QfJNj0pmz6dmTAptFcNA8Z3b+Zcx6aQTrVVgSwdWMjus349oi71MpS30cX7zW9/7HOA==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-ns-openapi-3-1": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-asyncapi-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.82.2.tgz", - "integrity": "sha512-rTq0jJFG1007JX73dxmkcN5I74Ii98V/hQ1GLu06apU4Cahka0sFj4DevVTrHOF26WYZNpZpqeFeXpPFeNmugA==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-json-schema-draft-7": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.82.2.tgz", - "integrity": "sha512-cQxENlN8ZGCSHVgoVgZZ2kxPyUxae8tKG6b11Etx7XnTuGVwC5etD3kz2tQYSp8ovR7vVq0f5Fqz4T0enPRXnw==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.82.2", - "@swagger-api/apidom-core": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.82.2.tgz", - "integrity": "sha512-vK3cVSqXdfOJiUnuV979Yj4AE4LXCf7VEZJtw4pJiXL3M7J9tH6kbmSsJP3G+QWjC6nvqvKJvAMcOT8Odi54RA==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.82.2.tgz", - "integrity": "sha512-fU4cZaeT8zh8vAFSrxH9Jp27oYJnx+FRFq8kopgKdznsdc3rSmWILR95Su2+qdgg+maIGo4qFB4KmWgAvrq6mw==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-ns-json-schema-draft-6": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.82.2.tgz", - "integrity": "sha512-X6KGhcPCZZy0EgWHOpfdwgemhb6xwYGRnNxn8cIKO4R3TdYtys75gNgrdB/PDa31sBA/KHiF20+ieeV8I/QFtg==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-0": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.82.2.tgz", - "integrity": "sha512-u5MhdP1F+l8HpBhpBHMCGsBNtFGrgi6/ImDqXtjjzTx1syWce2GHjPnQMHup+HelK/IvXbTkSS5oQx+hbKJEvA==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-ns-openapi-3-1": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.82.2.tgz", - "integrity": "sha512-7f+mVam2zrdpXWSaWeaHkg+9vle2Pk3WuCLzT1SujbqdahN6znGi1jr6ScrO9SyaJOBPCRLr/mRMY+BBgyCW7g==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.82.2", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.82.2.tgz", - "integrity": "sha512-5guFWa2C+nikr25Nflq5yrmjMgXpBc8gbdxznVixPsf4mbT5xo95IJfgpPFCK6mkmvyWmLqmn8p2A2HJ6XFdNQ==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-api-design-systems": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.82.2.tgz", - "integrity": "sha512-50khPt7Kh3ZzX7PKDrlAdAjmsu3titfrEL1cChiuWIK4IOo8uZ1/QANgl5pzSiPhaaYvm7yxp3Vps2U3reqUJg==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-api-design-systems": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.82.2.tgz", - "integrity": "sha512-uEVIrlPWXZBNyAknGJHLfKmv8xh0swVnArQ9nEMNRQRdJ6//UNAJ60WISWZO5obN585kYu7YZxVOm+w76UHO3w==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.82.2.tgz", - "integrity": "sha512-YozqvIBbGHEuP/Stpvk90n1HktvdZa4lxl6gX6fTAPMifBW+koijvmzfWgDYb57tEg8Hs2CXLxBV+tNiGWxkaA==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-json": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.82.2.tgz", - "integrity": "sha512-BHBouBvYaFYiwkz52lSOYwG/kPYzISEhDepGuODdH+zFzSXCHiiFIikejs1I2BXpng8+WDJ3K2erf7N0YIgReA==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.82.2", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", - "tree-sitter": "=0.20.4", - "tree-sitter-json": "=0.20.1", - "web-tree-sitter": "=0.20.3" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.82.2.tgz", - "integrity": "sha512-uPKojZoU5Mov0vbVqYy6kPRpK89WhpKB4qUWRC7+qOUar1KdVzrkAhiPFvXt/wCVVagM4ZtH4Ph8ccUAzwDtcw==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.82.2.tgz", - "integrity": "sha512-eCNUyP7tc6AfVBH76YhwrFMj5hoJu68fz/VKOcT+SQTEVsAcdrTBEcWt25WWHb/UZHRVZgRNNKZhJ7UlPpVm/Q==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.82.2.tgz", - "integrity": "sha512-gllEHM85QTXYAQRszHyrbK/h0KD5xgFKuWHApUs63SLmT9LRuBCNo6fzIrifKOONFazlZoHH/KOezEykADEKnQ==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.82.2.tgz", - "integrity": "sha512-j4gygyyrDN3Ptpg9WGdBTi30OfxjaIA25PIiCqx3V9qBBod8npg9okVZ59j4k7qbBOwAPD08SFyZMPYpy1EV8g==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.82.2.tgz", - "integrity": "sha512-A9bUOA2J+s0BhEs0gxVpOiiw+rPEsvrvw9mvb2Ub+hQ13G6A9t4OI37PfWXcjRKYT2xvbil8/t8iSh9olzTjtw==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.82.2.tgz", - "integrity": "sha512-CV1LPNyf8RDRUvqKSHhWfWwMEWsf0rGKzhwpMPGzKtwfubgl79/e6gc8LkhRa/ij/cAkQ7bcVdEK5qFoRuOFeQ==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.0.0" - } - }, - "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.82.2.tgz", - "integrity": "sha512-0bS6fZ3cCI30BYRL/slRlShijaqye9z504w77CmiiPSrBrbu4ZW7SsgSN+zvzh8nY6sUs7cCMQz/6PK7gVIYQQ==", - "optional": true, - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.82.2", - "@swagger-api/apidom-core": "^0.82.2", - "@swagger-api/apidom-error": "^0.82.1", - "@types/ramda": "~0.29.6", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2", - "tree-sitter": "=0.20.4", - "tree-sitter-yaml": "=0.5.0", - "web-tree-sitter": "=0.20.3" - } - }, - "node_modules/@swagger-api/apidom-reference": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.82.2.tgz", - "integrity": "sha512-QWD3WuSwcPwhPvMz+c9JdEpUbV5sTw8PyVvRGkgH8vr+fWbSBnY0pOUg1ST4qdQKSZnhwVaKB8a1zQTsFtRYBw==", - "dependencies": { - "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.82.2", - "@types/ramda": "~0.29.6", - "axios": "^1.4.0", - "minimatch": "^7.4.3", - "process": "^0.11.10", - "ramda": "~0.29.0", - "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" - }, - "optionalDependencies": { - "@swagger-api/apidom-error": "^0.82.1", - "@swagger-api/apidom-json-pointer": "^0.82.2", - "@swagger-api/apidom-ns-asyncapi-2": "^0.82.2", - "@swagger-api/apidom-ns-openapi-2": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-0": "^0.82.2", - "@swagger-api/apidom-ns-openapi-3-1": "^0.82.2", - "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.82.2", - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.82.2", - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-json": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-json-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.82.2", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.82.2", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.82.2" - } - }, - "node_modules/@swagger-api/apidom-reference/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@swagger-api/apidom-reference/node_modules/minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -3957,6 +3729,15 @@ "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -3981,30 +3762,30 @@ } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", - "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==" + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/mdast": { "version": "4.0.2", @@ -4050,6 +3831,11 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==" }, + "node_modules/@types/parse5": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", + "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" + }, "node_modules/@types/prismjs": { "version": "1.26.2", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.2.tgz", @@ -4065,29 +3851,31 @@ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==" }, - "node_modules/@types/ramda": { - "version": "0.29.7", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.7.tgz", - "integrity": "sha512-IUl6U95qwlQtVvZkSX4ODj08oJVtPyWMFRtPVNqhxc2rt+Bh7lCzTrGMYMZ7dmRKcAjtot3xrPnYGwsjdt8gzQ==", - "dependencies": { - "types-ramda": "^0.29.5" - } - }, "node_modules/@types/range-parser": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==" }, "node_modules/@types/react": { - "version": "18.2.48", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", - "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, + "node_modules/@types/react-redux": { + "version": "7.1.33", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", + "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/react-router": { "version": "5.1.20", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", @@ -4130,11 +3918,6 @@ "@types/node": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", - "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==" - }, "node_modules/@types/send": { "version": "0.17.3", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", @@ -4170,11 +3953,6 @@ "@types/node": "*" } }, - "node_modules/@types/trusted-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.5.tgz", - "integrity": "sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==" - }, "node_modules/@types/unist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.1.tgz", @@ -4189,17 +3967,17 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.29", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", - "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", - "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==" + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", @@ -4347,6 +4125,17 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -4476,30 +4265,31 @@ } }, "node_modules/algoliasearch": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", - "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", + "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", "dependencies": { - "@algolia/cache-browser-local-storage": "4.22.1", - "@algolia/cache-common": "4.22.1", - "@algolia/cache-in-memory": "4.22.1", - "@algolia/client-account": "4.22.1", - "@algolia/client-analytics": "4.22.1", - "@algolia/client-common": "4.22.1", - "@algolia/client-personalization": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/logger-console": "4.22.1", - "@algolia/requester-browser-xhr": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/requester-node-http": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-account": "4.23.3", + "@algolia/client-analytics": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-personalization": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/recommend": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/algoliasearch-helper": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.1.tgz", - "integrity": "sha512-qxAHVjjmT7USVvrM8q6gZGaJlCK1fl4APfdAA7o8O6iXEc68G0xMNrzRkxoB/HmhhvyHnoteS/iMTiHiTcQQcg==", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.19.0.tgz", + "integrity": "sha512-AaSb5DZDMZmDQyIy6lf4aL0OZGgyIdqvLIIvSuVQOIOqfhrYSY7TvotIFI2x0Q3cP3xUpTd7lI1astUC4aXBJw==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4566,6 +4356,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -4601,6 +4396,33 @@ "node": ">=8" } }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/astring": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", @@ -4609,10 +4431,10 @@ "astring": "bin/astring" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "node_modules/async": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", + "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -4623,9 +4445,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "funding": [ { "type": "opencollective", @@ -4641,8 +4463,8 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -4658,14 +4480,18 @@ "postcss": "^8.1.0" } }, - "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/babel-loader": { @@ -4750,14 +4576,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -4798,48 +4616,18 @@ "node": ">=8" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4847,7 +4635,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4888,20 +4676,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/bonjour-service": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", @@ -4959,10 +4733,123 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "dependencies": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -4978,8 +4865,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -5018,6 +4905,16 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -5074,18 +4971,28 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5126,9 +5033,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001579", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", - "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "version": "1.0.30001603", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001603.tgz", + "integrity": "sha512-iL2iSS0eDILMb9n5yKQoTBim9jMZ0Yrk8g0N9K7UzYyWnfIKzXBZD5ngpM37ZcL/cv0Mli8XtVMRYMQAfFpi5Q==", "funding": [ { "type": "opencollective", @@ -5212,6 +5119,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/cheerio": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", @@ -5274,12 +5189,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "optional": true - }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -5302,6 +5211,15 @@ "node": ">=8" } }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/classnames": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", @@ -5377,6 +5295,53 @@ "node": ">=8" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -5402,9 +5367,9 @@ } }, "node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { "node": ">=6" } @@ -5452,17 +5417,6 @@ "node": ">=10" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -5539,6 +5493,27 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5584,6 +5559,16 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" + }, "node_modules/content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -5606,9 +5591,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -5738,18 +5723,67 @@ } }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "node_modules/cross-spawn": { @@ -5765,6 +5799,32 @@ "node": ">= 8" } }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -5791,11 +5851,11 @@ } }, "node_modules/css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", "engines": { - "node": "^10 || ^12 || >=14" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { "postcss": "^8.0.9" @@ -5827,16 +5887,16 @@ } }, "node_modules/css-minimizer-webpack-plugin": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", - "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", "dependencies": { - "cssnano": "^5.1.8", - "jest-worker": "^29.1.2", - "postcss": "^8.4.17", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" }, "engines": { "node": ">= 14.15.0" @@ -5869,14 +5929,6 @@ } } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -5893,23 +5945,15 @@ } }, "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, "node_modules/css-what": { @@ -5935,108 +5979,128 @@ } }, "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/cssnano" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/cssnano-preset-advanced": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz", - "integrity": "sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", "dependencies": { - "autoprefixer": "^10.4.12", - "cssnano-preset-default": "^5.2.14", - "postcss-discard-unused": "^5.1.0", - "postcss-merge-idents": "^5.1.1", - "postcss-reduce-idents": "^5.2.0", - "postcss-zindex": "^5.1.0" + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", "dependencies": { - "css-tree": "^1.1.2" + "css-tree": "~2.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" } }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", @@ -6532,6 +6596,14 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decode-named-character-reference": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", @@ -6594,16 +6666,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { @@ -6659,14 +6734,6 @@ "robust-predicates": "^3.0.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6683,6 +6750,15 @@ "node": ">=6" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -6692,15 +6768,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -6768,6 +6835,21 @@ "node": ">=0.3.1" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6804,6 +6886,500 @@ "node": ">=6" } }, + "node_modules/docusaurus-plugin-openapi-docs": { + "version": "3.0.0-beta.10", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-3.0.0-beta.10.tgz", + "integrity": "sha512-BtMBH4TzCiMM0WbO2ZAMXSuL7Ge9yyASZhAycb5vX+KSUnUgp47/Ex2f6/evBfaadnr6vXYEr1UBT1fSiJYh5w==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.5.4", + "@docusaurus/plugin-content-docs": "^3.0.1", + "@docusaurus/utils": "^3.0.1", + "@docusaurus/utils-validation": "^3.0.1", + "@paloaltonetworks/openapi-to-postmanv2": "3.1.0-hotfix.1", + "@paloaltonetworks/postman-collection": "^4.1.0", + "@redocly/openapi-core": "^1.10.5", + "chalk": "^4.1.2", + "clsx": "^1.1.1", + "fs-extra": "^9.0.1", + "json-pointer": "^0.6.2", + "json-schema-merge-allof": "^0.8.1", + "json5": "^2.2.3", + "lodash": "^4.17.20", + "mustache": "^4.2.0", + "slugify": "^1.6.5", + "swagger2openapi": "^7.0.8", + "xml-formatter": "^2.6.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/@redocly/openapi-core": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.12.0.tgz", + "integrity": "sha512-2Jfxv3iIk1JUwLSnLyewJ8GAsoxubROVieg13Sjo79TjuWaUBuI49j8GZqC08ljENqyEIp0JHReDjhKs4Snrhg==", + "dependencies": { + "@redocly/ajv": "^8.11.0", + "@redocly/config": "^0.2.0", + "colorette": "^1.2.0", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "lodash.isequal": "^4.5.0", + "minimatch": "^5.0.1", + "node-fetch": "^2.6.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=14.19.0", + "npm": ">=7.0.0" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/docusaurus-plugin-openapi-docs/node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/docusaurus-plugin-sass": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.5.tgz", + "integrity": "sha512-Z+D0fLFUKcFpM+bqSUmqKIU+vO+YF1xoEQh5hoFreg2eMf722+siwXDD+sqtwU8E4MvVpuvsQfaHwODNlxJAEg==", + "dependencies": { + "sass-loader": "^10.1.1" + }, + "peerDependencies": { + "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha", + "sass": "^1.30.0" + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/docusaurus-plugin-sass/node_modules/sass-loader": { + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.5.2.tgz", + "integrity": "sha512-vMUoSNOUKJILHpcNCCyD23X34gve1TS7Rjd9uXHeKqhvBG39x6XbswFDtpbTElj6XdMFezoWhkh5vtKudf2cgQ==", + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/docusaurus-theme-openapi-docs": { + "version": "3.0.0-beta.10", + "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-3.0.0-beta.10.tgz", + "integrity": "sha512-8oUMMZSrRJ9EssrjWwbM9aYuHOt1AAm6wQDzWr8k6VvefGvVAibg4Y9PK7GeZ243lJikq9s45KqUA0SMwsm+Fg==", + "dependencies": { + "@docusaurus/theme-common": "^3.0.1", + "@hookform/error-message": "^2.0.1", + "@paloaltonetworks/postman-code-generators": "1.1.15-patch.2", + "@paloaltonetworks/postman-collection": "^4.1.0", + "@reduxjs/toolkit": "^1.7.1", + "clsx": "^1.1.1", + "copy-text-to-clipboard": "^3.1.0", + "crypto-js": "^4.1.1", + "docusaurus-plugin-openapi-docs": "^3.0.0-beta.10", + "docusaurus-plugin-sass": "^0.2.3", + "file-saver": "^2.0.5", + "lodash": "^4.17.20", + "node-polyfill-webpack-plugin": "^2.0.1", + "prism-react-renderer": "^2.3.0", + "react-hook-form": "^7.43.8", + "react-live": "^4.0.0", + "react-magic-dropzone": "^1.0.1", + "react-markdown": "^8.0.1", + "react-modal": "^3.15.1", + "react-redux": "^7.2.0", + "rehype-raw": "^6.1.1", + "sass": "^1.58.1", + "sass-loader": "^13.3.2", + "webpack": "^5.61.0", + "xml-formatter": "^2.6.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/hast-util-from-parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", + "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "hastscript": "^7.0.0", + "property-information": "^6.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/hast-util-raw": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", + "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/parse5": "^6.0.0", + "hast-util-from-parse5": "^7.0.0", + "hast-util-to-parse5": "^7.0.0", + "html-void-elements": "^2.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/hast-util-to-parse5": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", + "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/rehype-raw": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz", + "integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==", + "dependencies": { + "@types/hast": "^2.0.0", + "hast-util-raw": "^7.2.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/vfile-location": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", + "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", + "dependencies": { + "@types/unist": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/docusaurus-theme-openapi-docs/node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -6825,6 +7401,17 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/domain-browser": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.23.0.tgz", + "integrity": "sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -6915,15 +7502,34 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.637", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz", - "integrity": "sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==" + "version": "1.4.722", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.722.tgz", + "integrity": "sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ==" }, "node_modules/elkjs": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" }, + "node_modules/elliptic": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -6959,15 +7565,6 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "optional": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", @@ -6999,11 +7596,35 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==" }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==" + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -7141,16 +7762,13 @@ } }, "node_modules/estree-util-value-to-estree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.0.1.tgz", - "integrity": "sha512-b2tdzTurEIbwRh+mKrEcaWfu1wgb8J1hVsgREg7FFiecWwK/PhO8X0kyc+0bIcKNtD4sqxIdNoRy6/p/TvECEA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.1.tgz", + "integrity": "sha512-5mvUrF2suuv5f5cGDnDphIy4/gW86z82kl5qG6mM9z04SEQI4FB5Apmaw/TGEf3l55nLtMs5s51dmhUzvAHQCA==", "dependencies": { "@types/estree": "^1.0.0", "is-plain-obj": "^4.0.0" }, - "engines": { - "node": ">=16.0.0" - }, "funding": { "url": "https://github.com/sponsors/remcohaszing" } @@ -7215,6 +7833,14 @@ "node": ">= 0.8" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -7228,6 +7854,15 @@ "node": ">=0.8.x" } }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -7250,26 +7885,22 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "optional": true, - "engines": { - "node": ">=6" - } + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -7334,20 +7965,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7392,16 +8009,16 @@ "node": ">=8.6.0" } }, - "node_modules/fast-json-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -7516,6 +8133,19 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -7535,6 +8165,14 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", + "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==", + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -7604,9 +8242,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -7622,6 +8260,45 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==" + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", @@ -7742,19 +8419,6 @@ "node": ">=6" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -7799,12 +8463,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "optional": true - }, "node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -7857,16 +8515,28 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7887,12 +8557,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "optional": true - }, "node_modules/github-slugger": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", @@ -8130,11 +8794,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8162,6 +8826,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-yarn": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", @@ -8173,6 +8851,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -8216,9 +8915,9 @@ } }, "node_modules/hast-util-raw": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", - "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.2.tgz", + "integrity": "sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -8377,6 +9076,16 @@ "value-equal": "^1.0.1" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -8636,6 +9345,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/http-reasons": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", + "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==" + }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==" + }, "node_modules/http2-wrapper": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", @@ -8648,6 +9367,11 @@ "node": ">=10.19.0" } }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -8728,6 +9452,11 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -8853,6 +9582,21 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8869,6 +9613,39 @@ "node": ">=8" } }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-ci": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", @@ -8938,6 +9715,20 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -8973,6 +9764,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-npm": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", @@ -9070,6 +9876,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -9112,6 +9932,23 @@ "node": ">=0.10.0" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -9176,6 +10013,14 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9213,6 +10058,35 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-pointer": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "dependencies": { + "foreach": "^2.0.4" + } + }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -9269,6 +10143,14 @@ "node": ">=6" } }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, "node_modules/latest-version": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", @@ -9306,11 +10188,14 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -9318,32 +10203,12 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/lit": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", - "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==", - "dependencies": { - "@lit/reactive-element": "^1.6.0", - "lit-element": "^3.3.0", - "lit-html": "^2.8.0" - } - }, - "node_modules/lit-element": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz", - "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.1.0", - "@lit/reactive-element": "^1.3.0", - "lit-html": "^2.8.0" - } - }, - "node_modules/lit-html": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", - "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", - "dependencies": { - "@types/trusted-types": "^2.0.2" + "node_modules/liquid-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", + "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", + "engines": { + "node": ">=4" } }, "node_modules/loader-runner": { @@ -9411,6 +10276,11 @@ "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -9498,15 +10368,80 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "bin": { - "marked": "bin/marked.js" + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" }, - "engines": { - "node": ">= 12" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/mdast-util-definitions/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/mdast-util-directive": { @@ -9655,9 +10590,9 @@ } }, "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9888,9 +10823,9 @@ } }, "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/media-typer": { "version": "0.3.0", @@ -10550,9 +11485,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -10599,9 +11534,9 @@ } }, "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -10667,9 +11602,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -10739,9 +11674,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -10840,9 +11775,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -10921,9 +11856,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12075,6 +13010,23 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -12094,6 +13046,14 @@ "node": ">= 0.6" } }, + "node_modules/mime-format": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", + "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", + "dependencies": { + "charset": "^1.0.0" + } + }, "node_modules/mime-types": { "version": "2.1.18", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", @@ -12142,22 +13102,16 @@ "webpack": "^5.0.0" } }, - "node_modules/minim": { - "version": "0.23.8", - "resolved": "https://registry.npmjs.org/minim/-/minim-0.23.8.tgz", - "integrity": "sha512-bjdr2xW1dBCMsMGGsUeqM4eFI60m94+szhxWys+B1ztIt6gWSfeGBdSVCIawezeHYLYn0j6zrsXdQS/JllBzww==", - "dependencies": { - "lodash": "^4.15.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -12177,11 +13131,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "optional": true + "node_modules/minipass": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.0.tgz", + "integrity": "sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, "node_modules/mri": { "version": "1.2.0", @@ -12216,11 +13172,23 @@ "multicast-dns": "cli.js" } }, - "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "optional": true + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } }, "node_modules/nanoid": { "version": "3.3.7", @@ -12239,12 +13207,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "optional": true - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -12267,41 +13229,6 @@ "tslib": "^2.0.3" } }, - "node_modules/node-abi": { - "version": "3.51.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", - "integrity": "sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==", - "optional": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -12316,20 +13243,34 @@ "node": ">=18" } }, - "node_modules/node-fetch-commonjs": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch-commonjs/-/node-fetch-commonjs-3.3.2.tgz", - "integrity": "sha512-VBlAiynj3VMLrotgwOS3OyECFxas5y7ltLcK4t41lMUZeaK15Ym4QRkqN0EQKAFL42q9i21EPKjzLUPfltR72A==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "4.x || >=6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" } }, "node_modules/node-forge": { @@ -12340,6 +13281,75 @@ "node": ">= 6.13.0" } }, + "node_modules/node-polyfill-webpack-plugin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-2.0.1.tgz", + "integrity": "sha512-ZUMiCnZkP1LF0Th2caY6J/eKKoA0TefpoVa68m/LQU1I/mE8rGt4fNYGgNuCcK+aG8P8P43nbeJ2RqJMOL/Y1A==", + "dependencies": { + "assert": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "domain-browser": "^4.22.0", + "events": "^3.3.0", + "filter-obj": "^2.0.2", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^4.0.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.12", + "tty-browserify": "^0.0.1", + "type-fest": "^2.14.0", + "url": "^0.11.0", + "util": "^0.12.4", + "vm-browserify": "^1.1.2" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": ">=5" + } + }, + "node_modules/node-polyfill-webpack-plugin/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/node-polyfill-webpack-plugin/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -12366,17 +13376,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -12404,6 +13403,233 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver-browser": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/oas-resolver-browser/-/oas-resolver-browser-2.5.2.tgz", + "integrity": "sha512-L3ugWyBHOpKLT+lb+pFXCOpk3byh6usis5T9u9mfu92jH5bR6YK8MA2bebUTIjY7I4415PzDeZcmcc+i7X05MA==", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "path-browserify": "^1.0.1", + "reftools": "^1.1.6", + "yaml": "^1.10.0", + "yargs": "^15.3.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver-browser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/oas-resolver-browser/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/oas-resolver-browser/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/oas-resolver-browser/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oas-resolver-browser/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/oas-resolver-browser/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oas-resolver-browser/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -12420,6 +13646,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -12515,6 +13756,11 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -12602,6 +13848,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -12622,6 +13873,22 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-entities": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", @@ -12708,6 +13975,20 @@ "tslib": "^2.0.3" } }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -12742,6 +14023,29 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -12758,6 +14062,34 @@ "node": ">=8" } }, + "node_modules/path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/path/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -12784,6 +14116,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", @@ -12865,10 +14205,26 @@ "node": ">=4" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "funding": [ { "type": "opencollective", @@ -12886,112 +14242,115 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", "dependencies": { - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0" }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, "peerDependencies": { "postcss": "^8.2.2" } }, "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", "dependencies": { - "browserslist": "^4.21.4", + "browserslist": "^4.23.0", "caniuse-api": "^3.0.0", - "colord": "^2.9.1", + "colord": "^2.9.3", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", "dependencies": { - "browserslist": "^4.21.4", + "browserslist": "^4.23.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-discard-unused": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", - "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "postcss-selector-parser": "^6.0.16" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-loader": { @@ -13015,136 +14374,111 @@ "webpack": "^5.0.0" } }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/postcss-merge-idents": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", - "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", "dependencies": { - "cssnano-utils": "^3.1.0", + "cssnano-utils": "^4.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", "dependencies": { "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" + "stylehacks": "^6.1.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", "dependencies": { - "browserslist": "^4.21.4", + "browserslist": "^4.23.0", "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "postcss-selector-parser": "^6.0.16" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-modules-extract-imports": { @@ -13203,192 +14537,191 @@ } }, "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", "dependencies": { - "browserslist": "^4.21.4", + "browserslist": "^4.23.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", "dependencies": { - "normalize-url": "^6.0.1", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", "dependencies": { - "cssnano-utils": "^3.1.0", + "cssnano-utils": "^4.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-reduce-idents": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", - "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", "dependencies": { - "browserslist": "^4.21.4", + "browserslist": "^4.23.0", "caniuse-api": "^3.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -13398,46 +14731,46 @@ } }, "node_modules/postcss-sort-media-queries": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", - "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", "dependencies": { - "sort-css-media-queries": "2.1.0" + "sort-css-media-queries": "2.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "postcss": "^8.4.16" + "postcss": "^8.4.23" } }, "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", "dependencies": { "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" + "svgo": "^3.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >= 18" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "postcss-selector-parser": "^6.0.16" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/postcss-value-parser": { @@ -13446,46 +14779,39 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss-zindex": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", - "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, - "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "optional": true, + "node_modules/postman-url-encoder": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", + "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" + "punycode": "^2.1.1" }, "engines": { "node": ">=10" } }, + "node_modules/postman-url-encoder/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -13603,21 +14929,24 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "optional": true, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -13638,9 +14967,9 @@ } }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { "side-channel": "^1.0.4" }, @@ -13651,6 +14980,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -13689,30 +15026,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ramda": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", - "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, - "node_modules/ramda-adjunct": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ramda-adjunct/-/ramda-adjunct-4.1.1.tgz", - "integrity": "sha512-BnCGsZybQZMDGram9y7RiryoRHS5uwx8YeGuUeDKuZuvK38XO6JJfmK85BwRWAKFA6pZ5nZBO/HBFtExVaf31w==", - "engines": { - "node": ">=0.10.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda-adjunct" - }, - "peerDependencies": { - "ramda": ">= 0.29.0" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -13721,6 +15034,15 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -13729,27 +15051,10 @@ "node": ">= 0.6" } }, - "node_modules/rapidoc": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/rapidoc/-/rapidoc-9.3.4.tgz", - "integrity": "sha512-kqNuOSmjlf12SpSfPQaIMuehj7w8JWFFr9/l2zieG7/gCJr1NG2XL920uoqNlXzku1DO8NeHRkSXCmyaZxEOew==", - "dependencies": { - "@apitools/openapi-parser": "0.0.30", - "base64-arraybuffer": "^1.0.2", - "buffer": "^6.0.3", - "lit": "^2.6.1", - "marked": "^4.2.12", - "prismjs": "^1.29.0", - "xml-but-prettier": "^1.0.1" - }, - "engines": { - "node": ">=10.21.0" - } - }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -13802,9 +15107,9 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { "loose-envify": "^1.1.0" }, @@ -13940,15 +15245,15 @@ } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^18.3.1" } }, "node_modules/react-error-overlay": { @@ -13988,15 +15293,30 @@ "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-hook-form": { + "version": "7.51.4", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.4.tgz", + "integrity": "sha512-V14i8SEkh+V1gs6YtD0hdHYnoL4tp/HX/A45wWQN15CYr9bFRmmRdYStSO5L65lCCZRF+kYiSKhm9alqbcdiVA==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz", - "integrity": "sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.4.0.tgz", + "integrity": "sha512-wh6F6uJyYAmQ4fK0e8dSQMEWuvTs2Wr3el3sLD9bambX1+pSWUVXIz1RFaoy3TI1mZ0FqdpKq9YgbgTTgyrmXA==", "engines": { "node": ">=14" }, @@ -14004,14 +15324,36 @@ "react": "^16.13.1 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-live": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/react-live/-/react-live-4.1.6.tgz", + "integrity": "sha512-2oq3MADi3rupqZcdoHMrV9p+Eg/92BDds278ZuoOz8d68qw6ct0xZxX89MRxeChrnFHy1XPr8BVknDJNJNdvVw==", + "dependencies": { + "prism-react-renderer": "^2.0.6", + "sucrase": "^3.31.0", + "use-editable": "^2.3.3" + }, + "engines": { + "node": ">= 0.12.0", + "npm": ">= 2.0.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/react-loadable": { "name": "@docusaurus/react-loadable", - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", - "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "dependencies": { - "@types/react": "*", - "prop-types": "^15.6.2" + "@types/react": "*" }, "peerDependencies": { "react": "*" @@ -14032,6 +15374,683 @@ "webpack": ">=4.41.1 || 5.x" } }, + "node_modules/react-magic-dropzone": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-magic-dropzone/-/react-magic-dropzone-1.0.1.tgz", + "integrity": "sha512-0BIROPARmXHpk4AS3eWBOsewxoM5ndk2psYP/JmbCq8tz3uR2LIV1XiroZ9PKrmDRMctpW+TvsBCtWasuS8vFA==" + }, + "node_modules/react-markdown": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz", + "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/prop-types": "^15.0.0", + "@types/unist": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^2.0.0", + "prop-types": "^15.0.0", + "property-information": "^6.0.0", + "react-is": "^18.0.0", + "remark-parse": "^10.0.0", + "remark-rehype": "^10.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unified": "^10.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/react-markdown/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/react-markdown/node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/react-markdown/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/react-markdown/node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/mdast-util-from-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/mdast-util-to-hast": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-definitions": "^5.0.0", + "micromark-util-sanitize-uri": "^1.1.0", + "trim-lines": "^3.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-factory-whitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-combine-extensions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-decode-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/react-markdown/node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/react-markdown/node_modules/micromark-util-normalize-identifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-subtokenize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/react-markdown/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/react-markdown/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/react-markdown/node_modules/remark-parse": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/remark-rehype": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", + "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-to-hast": "^12.1.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-markdown/node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + } + }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, "node_modules/react-router": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", @@ -14094,11 +16113,11 @@ } }, "node_modules/react-tooltip": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.26.0.tgz", - "integrity": "sha512-UBbwy3fo1KYDwRCOWwM6AEfQsk9shgVfNkXFqgwS33QHplzg7xao/7mX/6wd+lE6KSZzhUNTkB5TNk9SMaBV/A==", + "version": "5.26.4", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.26.4.tgz", + "integrity": "sha512-5WyDrsfw1+6qNVSr3IjqElqJ+cCwE8+44b+HpJ8qRLv7v0a3mcKf8wvv+NfgALFS6QpksGFqTLV2JQ60c+okZQ==", "dependencies": { - "@floating-ui/dom": "^1.0.0", + "@floating-ui/dom": "^1.6.1", "classnames": "^2.3.0" }, "peerDependencies": { @@ -14157,6 +16176,30 @@ "node": ">=6.0.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -14498,12 +16541,12 @@ "entities": "^2.0.0" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, "node_modules/require-from-string": { @@ -14522,11 +16565,21 @@ "node": "*" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -14606,6 +16659,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", @@ -14695,15 +16757,67 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sass": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.76.0.tgz", + "integrity": "sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", + "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, "node_modules/sax": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { "loose-envify": "^1.1.0" } @@ -14966,25 +17080,49 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -15044,23 +17182,66 @@ "node": ">=4" } }, - "node_modules/short-unique-id": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.0.3.tgz", - "integrity": "sha512-yhniEILouC0s4lpH0h7rJsfylZdca10W9mDJRAFh3EpcSUanCHGb0R7kcFOIUCZYSAPo0PUD5ZxWQdW0T4xaug==", - "bin": { - "short-unique-id": "bin/short-unique-id", - "suid": "bin/short-unique-id" + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -15071,51 +17252,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "optional": true, - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", @@ -15176,6 +17312,15 @@ "node": ">=8" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -15195,9 +17340,9 @@ } }, "node_modules/sort-css-media-queries": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", - "integrity": "sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", "engines": { "node": ">= 6.3.0" } @@ -15211,9 +17356,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -15288,17 +17433,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" - }, - "node_modules/stampit": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz", - "integrity": "sha512-pE2org1+ZWQBnIxRPrBM2gVupkuDD0TTNIo1H6GdT/vO82NXli2z8lRE8cu/nBIHrcOCXFBAHpb9ZldrB2/qOA==" - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -15312,6 +17446,26 @@ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz", "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==" }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -15336,6 +17490,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -15398,6 +17571,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -15434,24 +17619,96 @@ } }, "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^14 || ^16 || >=18.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "postcss": "^8.4.31" } }, "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/supports-color": { "version": "7.2.0", @@ -15481,23 +17738,27 @@ "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" }, "bin": { "svgo": "bin/svgo" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" } }, "node_modules/svgo/node_modules/commander": { @@ -15508,89 +17769,30 @@ "node": ">= 10" } }, - "node_modules/svgo/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" }, "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/svgo/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/swagger-client": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.24.4.tgz", - "integrity": "sha512-+Km936Ofep9y4OjKGb/pVWmvGVdFKM0YXffZuCxj3czEgKnkNAm1AIgQxr6Za5sGvlh/E1vEIRL4otZ6BIe8hA==", - "dependencies": { - "@babel/runtime-corejs3": "^7.22.15", - "@swagger-api/apidom-core": ">=0.82.2 <1.0.0", - "@swagger-api/apidom-json-pointer": ">=0.82.2 <1.0.0", - "@swagger-api/apidom-ns-openapi-3-1": ">=0.82.2 <1.0.0", - "@swagger-api/apidom-reference": ">=0.82.2 <1.0.0", - "cookie": "~0.5.0", - "deepmerge": "~4.3.0", - "fast-json-patch": "^3.0.0-1", - "is-plain-object": "^5.0.0", - "js-yaml": "^4.1.0", - "node-abort-controller": "^3.1.1", - "node-fetch-commonjs": "^3.3.1", - "qs": "^6.10.2", - "traverse": "~0.6.6", - "undici": "^5.24.0" + "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, "node_modules/tapable": { @@ -15601,34 +17803,6 @@ "node": ">=6" } }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "optional": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "optional": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/terser": { "version": "5.24.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", @@ -15761,11 +17935,41 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tiny-invariant": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", @@ -15823,44 +18027,10 @@ "node": ">=6" } }, - "node_modules/traverse": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", - "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tree-sitter": { - "version": "0.20.4", - "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.20.4.tgz", - "integrity": "sha512-rjfR5dc4knG3jnJNN/giJ9WOoN1zL/kZyrS0ILh+eqq8RNcIbiXA63JsMEgluug0aNvfQvK4BfCErN1vIzvKog==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "nan": "^2.17.0", - "prebuild-install": "^7.1.1" - } - }, - "node_modules/tree-sitter-json": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.1.tgz", - "integrity": "sha512-482hf7J+aBwhksSw8yWaqI8nyP1DrSwnS4IMBShsnkFWD3SE8oalHnsEik59fEVi3orcTCUtMzSjZx+0Tpa6Vw==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "nan": "^2.18.0" - } - }, - "node_modules/tree-sitter-yaml": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/tree-sitter-yaml/-/tree-sitter-yaml-0.5.0.tgz", - "integrity": "sha512-POJ4ZNXXSWIG/W4Rjuyg36MkUD4d769YRUGKRqN+sVaj/VCo6Dh6Pkssn1Rtewd5kybx+jT1BWMyWN0CijXnMA==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "nan": "^2.14.0" - } + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/trim-lines": { "version": "3.0.1", @@ -15888,27 +18058,20 @@ "node": ">=6.10" } }, - "node_modules/ts-toolbelt": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==" + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" }, "node_modules/type-fest": { "version": "2.19.0", @@ -15960,18 +18123,10 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/types-ramda": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.5.tgz", - "integrity": "sha512-u+bAYXHDPJR+amB0qMrMU/NXRB2PG8QqpO2v6j7yK/0mPZhlaaZj++ynYjnVpkPEpCkZEGxNpWY3X7qyLCGE3w==", - "dependencies": { - "ts-toolbelt": "^9.6.0" - } - }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15980,17 +18135,6 @@ "node": ">=14.17" } }, - "node_modules/undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -16072,6 +18216,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -16176,11 +18329,6 @@ "node": ">= 0.8" } }, - "node_modules/unraw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unraw/-/unraw-3.0.0.tgz", - "integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==" - }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -16296,6 +18444,15 @@ "node": ">=6" } }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -16386,6 +18543,40 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/url/node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/use-editable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/use-editable/-/use-editable-2.3.3.tgz", + "integrity": "sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA==", + "peerDependencies": { + "react": ">= 16.8.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16449,6 +18640,38 @@ "node": ">=6" } }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, "node_modules/value-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", @@ -16502,6 +18725,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -16531,25 +18767,16 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/web-tree-sitter": { - "version": "0.20.3", - "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.3.tgz", - "integrity": "sha512-zKGJW9r23y3BcJusbgvnOH2OYAW40MXAOi9bi3Gcc7T4Gms9WWgXF8m6adsJWpGJEhgOzCrfiz1IzKowJWrtYw==", - "optional": true - }, "node_modules/web-worker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "node_modules/webpack": { "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", @@ -16635,9 +18862,9 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -16884,6 +19111,15 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -16898,6 +19134,29 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -16933,6 +19192,41 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -17016,12 +19310,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/xml-but-prettier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml-but-prettier/-/xml-but-prettier-1.0.1.tgz", - "integrity": "sha512-C2CJaadHrZTqESlH03WOyw0oZTtoy2uEg6dSDF6YRg+9GnYNub53RRemLpnvtbHDFelxMx4LajiFsYeR6XJHgQ==", + "node_modules/xml-formatter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-2.6.1.tgz", + "integrity": "sha512-dOiGwoqm8y22QdTNI7A+N03tyVfBlQ0/oehAzxIZtwnFAHGeSlrfjF73YQvzSsa/Kt6+YZasKsrdu6OIpuBggw==", "dependencies": { - "repeat-string": "^1.5.2" + "xml-parser-xo": "^3.2.0" + }, + "engines": { + "node": ">= 10" } }, "node_modules/xml-js": { @@ -17035,6 +19332,30 @@ "xml-js": "bin/cli.js" } }, + "node_modules/xml-parser-xo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-3.2.0.tgz", + "integrity": "sha512-8LRU6cq+d7mVsoDaMhnkkt3CTtAs4153p49fRo+HIB3I1FD1o5CeXRjRH29sQevIfVJIcPjKSsPU/+Ujhq09Rg==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -17048,6 +19369,54 @@ "node": ">= 6" } }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", diff --git a/website/package.json b/website/package.json index 6594c3a25f..5f511fe4ed 100644 --- a/website/package.json +++ b/website/package.json @@ -1,13 +1,13 @@ { - "name": "@goauthentik/website", + "name": "@goauthentik/website-docs", "version": "0.0.0", "private": true, "license": "MIT", "scripts": { "docusaurus": "docusaurus", - "watch": "docusaurus start", - "build": "cp ../docker-compose.yml static/docker-compose.yml && cp ../schema.yml static/schema.yaml && docusaurus build", - "build-docs-only": "docusaurus build --config docusaurus.docs-only.ts --out-dir help", + "watch": "docusaurus gen-api-docs all && docusaurus start", + "build": "cp ../docker-compose.yml static/docker-compose.yml && cp ../schema.yml static/schema.yaml && docusaurus gen-api-docs all && docusaurus build", + "build-bundled": "cp ../schema.yml static/schema.yaml && docusaurus gen-api-docs all && docusaurus build", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "serve": "docusaurus serve", @@ -16,24 +16,25 @@ "test": "node --test" }, "dependencies": { - "@docusaurus/core": "^3.1.0", - "@docusaurus/plugin-client-redirects": "^3.1.0", - "@docusaurus/plugin-content-docs": "^3.1.0", - "@docusaurus/preset-classic": "^3.1.0", - "@docusaurus/theme-common": "^3.1.0", - "@docusaurus/theme-mermaid": "^3.1.0", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.1.0", + "@docusaurus/core": "^3.3.2", + "@docusaurus/plugin-client-redirects": "^3.3.2", + "@docusaurus/plugin-content-docs": "^3.3.2", + "@docusaurus/preset-classic": "^3.3.2", + "@docusaurus/theme-common": "^3.3.2", + "@docusaurus/theme-mermaid": "^3.3.2", + "@mdx-js/react": "^3.0.1", + "clsx": "^2.1.1", "disqus-react": "^1.1.5", - "postcss": "^8.4.33", + "docusaurus-plugin-openapi-docs": "^3.0.0-beta.10", + "docusaurus-theme-openapi-docs": "^3.0.0-beta.10", + "postcss": "^8.4.38", "prism-react-renderer": "^2.3.1", - "rapidoc": "^9.3.4", + "react": "^18.3.1", "react-before-after-slider-component": "^1.1.8", - "react-dom": "^18.2.0", + "react-dom": "^18.3.1", "react-feather": "^2.0.10", "react-toggle": "^4.1.3", - "react-tooltip": "^5.26.0", - "react": "^18.2.0", + "react-tooltip": "^5.26.4", "remark-github": "^12.0.0" }, "browserslist": { @@ -49,12 +50,12 @@ ] }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.1.0", - "@docusaurus/tsconfig": "3.1.0", - "@docusaurus/types": "3.1.0", - "@types/react": "^18.2.48", - "prettier": "3.2.4", - "typescript": "~5.3.3" + "@docusaurus/module-type-aliases": "^3.3.2", + "@docusaurus/tsconfig": "^3.3.2", + "@docusaurus/types": "^3.3.2", + "@types/react": "^18.3.3", + "prettier": "3.2.5", + "typescript": "~5.4.5" }, "engines": { "node": ">=20" diff --git a/website/sidebars.js b/website/sidebars.js index 94018e89c5..80e50cb852 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -32,15 +32,15 @@ const docsSidebar = { }, { type: "category", - label: "Core Concepts", + label: "Core Concepts & Tasks", collapsed: true, items: [ "core/terminology", - "core/applications", "core/brands", "core/certificates", "core/geoip", "core/architecture", + "core/settings", ], }, { @@ -57,10 +57,56 @@ const docsSidebar = { "enterprise/entsupport", ], }, + { + type: "category", + label: "Applications", + link: { + type: "doc", + id: "applications/index", + }, + items: ["applications/manage_apps"], + }, { type: "category", label: "Providers", + link: { + type: "doc", + id: "providers/index", + }, items: [ + { + type: "category", + label: "Google Workspace Provider", + link: { + type: "doc", + id: "providers/gws/index", + }, + items: [ + "providers/gws/setup-gws", + "providers/gws/add-gws-provider", + ], + }, + { + type: "category", + label: "LDAP Provider", + link: { + type: "doc", + id: "providers/ldap/index", + }, + items: ["providers/ldap/generic_setup"], + }, + { + type: "category", + label: "Microsoft Entra ID Provider", + link: { + type: "doc", + id: "providers/entra/index", + }, + items: [ + "providers/entra/setup-entra", + "providers/entra/add-entra-provider", + ], + }, { type: "category", label: "OAuth2 Provider", @@ -101,17 +147,60 @@ const docsSidebar = { }, ], }, + "providers/scim/index", { type: "category", - label: "LDAP Provider", + label: "RAC (Remote Access Control) Provider", link: { type: "doc", - id: "providers/ldap/index", + id: "providers/rac/index", }, - items: ["providers/ldap/generic_setup"], + items: ["providers/rac/how-to-rac"], + }, + ], + }, + { + type: "category", + label: "Sources", + collapsed: true, + link: { + type: "doc", + id: "sources/index", + }, + items: [ + { + type: "category", + label: "Directory synchronization", + items: [ + "sources/active-directory/index", + "sources/freeipa/index", + ], + }, + { + type: "category", + label: "Protocols", + items: [ + "sources/ldap/index", + "sources/oauth/index", + "sources/saml/index", + "sources/scim/index", + ], + }, + { + type: "category", + label: "Social Logins", + items: [ + "sources/apple/index", + "sources/azure-ad/index", + "sources/discord/index", + "sources/github/index", + "sources/google/index", + "sources/mailcow/index", + "sources/twitch/index", + "sources/plex/index", + "sources/twitter/index", + ], }, - "providers/scim/index", - "providers/rac/index", ], }, { @@ -192,6 +281,7 @@ const docsSidebar = { "flow/stages/invitation/index", "flow/stages/password/index", "flow/stages/prompt/index", + "flow/stages/source/index", "flow/stages/user_delete", "flow/stages/user_login/index", "flow/stages/user_logout", @@ -209,13 +299,16 @@ const docsSidebar = { { type: "category", label: "Working with policies", - items: ["policies/working_with_policies/whitelist_email"], link: { type: "generated-index", title: "Working with policies", slug: "policies/working_with_policies", description: "Overview of policies configuration", }, + items: [ + "policies/working_with_policies/whitelist_email", + "policies/working_with_policies/unique_email", + ], }, "policies/expression", ], @@ -318,13 +411,15 @@ const docsSidebar = { description: "Release notes for recent authentik versions", }, items: [ + "releases/2024/v2024.4", + "releases/2024/v2024.2", "releases/2023/v2023.10", - "releases/2023/v2023.8", - "releases/2023/v2023.6", { type: "category", label: "Previous versions", items: [ + "releases/2023/v2023.8", + "releases/2023/v2023.6", "releases/2023/v2023.5", "releases/2023/v2023.4", "releases/2023/v2023.3", @@ -408,7 +503,9 @@ const docsSidebar = { slug: "security", }, items: [ + "security/security-hardening", "security/policy", + "security/CVE-2024-23647", "security/CVE-2024-21637", "security/CVE-2023-48228", "security/GHSA-rjvp-29xq-f62w", @@ -421,17 +518,6 @@ const docsSidebar = { "security/CVE-2022-46172", ], }, - { - type: "category", - label: "Advanced topics", - link: { - type: "generated-index", - title: "Advanced topics", - slug: "advanced", - description: "Documentation for advanced features", - }, - items: ["advanced/tenancy"], - }, ], }; diff --git a/website/sidebarsDev.js b/website/sidebarsDev.js index a5043d56bc..26ccbc99d2 100644 --- a/website/sidebarsDev.js +++ b/website/sidebarsDev.js @@ -1,6 +1,7 @@ const docsSidebar = require("./sidebars.js"); const generateVersionDropdown = require("./src/utils.js").generateVersionDropdown; +const apiReference = require("./developer-docs/api/reference/sidebar"); module.exports = { docs: [ @@ -46,7 +47,12 @@ module.exports = { "api/flow-executor", "api/making-schema-changes", "api/websocket", - "api/browser", + { + type: "category", + label: "Reference", + items: apiReference, + }, + "api/clients", ], }, { diff --git a/website/sidebarsIntegrations.js b/website/sidebarsIntegrations.js index 3735e3b32c..a690339102 100644 --- a/website/sidebarsIntegrations.js +++ b/website/sidebarsIntegrations.js @@ -8,9 +8,14 @@ module.exports = { type: "html", value: generateVersionDropdown(docsSidebar), }, + { + type: "doc", + id: "index", + }, { type: "category", label: "Applications", + collapsed: false, link: { type: "doc", id: "services/index", @@ -29,7 +34,9 @@ module.exports = { "services/mobilizon/index", "services/nextcloud/index", "services/onlyoffice/index", + "services/outline/index", "services/paperless-ng/index", + "services/paperless-ngx/index", "services/rocketchat/index", "services/roundcube/index", "services/sharepoint-se/index", @@ -62,6 +69,7 @@ module.exports = { "services/portainer/index", "services/proxmox-ve/index", "services/rancher/index", + "services/xen-orchestra/index", "services/vmware-vcenter/index", ], }, @@ -72,20 +80,18 @@ module.exports = { "services/apache-guacamole/index", "services/argocd/index", "services/awx-tower/index", - "services/firezone/index", - "services/fortimanager/index", + "services/globalprotect/index", "services/harbor/index", "services/hashicorp-vault/index", "services/jenkins/index", "services/minio/index", "services/netbox/index", - "services/opnsense/index", - "services/pfsense/index", "services/pgadmin/index", "services/phpipam/index", "services/powerdns-admin/index", "services/proftpd/index", "services/qnap-nas/index", + "services/synology-dsm/index", "services/skyhigh/index", "services/snipe-it/index", "services/sssd/index", @@ -94,6 +100,18 @@ module.exports = { "services/zammad/index", ], }, + { + type: "category", + label: "Networking", + items: [ + "services/firezone/index", + "services/fortigate-admin/index", + "services/fortigate-ssl/index", + "services/fortimanager/index", + "services/opnsense/index", + "services/pfsense/index", + ], + }, { type: "category", label: "Miscellaneous", @@ -114,6 +132,7 @@ module.exports = { type: "category", label: "Monitoring", items: [ + "services/glitchtip/index", "services/grafana/index", "services/sentry/index", "services/ubuntu-landscape/index", @@ -142,51 +161,5 @@ module.exports = { }, ], }, - { - type: "category", - label: "Federation & Social login", - link: { - type: "generated-index", - title: "Sources", - slug: "sources", - description: - "Sources of users which can be federated with authentik", - }, - items: [ - { - type: "category", - label: "Directory synchronization", - items: [ - "sources/active-directory/index", - "sources/freeipa/index", - ], - }, - "sources/general", - { - type: "category", - label: "Protocols", - items: [ - "sources/ldap/index", - "sources/oauth/index", - "sources/saml/index", - ], - }, - { - type: "category", - label: "Social Logins", - items: [ - "sources/apple/index", - "sources/azure-ad/index", - "sources/discord/index", - "sources/github/index", - "sources/google/index", - "sources/mailcow/index", - "sources/twitch/index", - "sources/plex/index", - "sources/twitter/index", - ], - }, - ], - }, ], }; diff --git a/website/src/components/APIBrowser/index.tsx b/website/src/components/APIBrowser/index.tsx deleted file mode 100644 index 25c43b743c..0000000000 --- a/website/src/components/APIBrowser/index.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import BrowserOnly from "@docusaurus/BrowserOnly"; -import { useColorMode } from "@docusaurus/theme-common"; - -export function APIBrowser() { - const context = useDocusaurusContext(); - const { siteConfig = {} } = context; - const { colorMode, setColorMode } = useColorMode(); - let bg = "#1b1b1d"; - if (colorMode === "light") { - bg = "#fff"; - } - return ( - - {() => { - require("rapidoc"); - return ( - - ); - }} - - ); -} - -export default APIBrowser; diff --git a/website/src/components/Comparison/index.tsx b/website/src/components/Comparison/index.tsx deleted file mode 100644 index c46934c885..0000000000 --- a/website/src/components/Comparison/index.tsx +++ /dev/null @@ -1,600 +0,0 @@ -import React from "react"; -import { Check, X, AlertTriangle } from "react-feather"; -import "./style.css"; -import "react-tooltip/dist/react-tooltip.css"; -import { Tooltip } from "react-tooltip"; - -export default function Comparison() { - const tooltipAvailableThirdParty = "Available as a third-party extension"; - const tooltipPlanned = "Planned as a future feature"; - const tooltipRequiresLicense = - "Requires additional licenses/not included in base tier"; - const tooltipRequiresProductAADS = - "Requires additional product: Azure AD Domain Services"; - const tooltipRequiresProductWAP = - "Requires additional product: Web Application Proxy"; - return ( - <> -
                -

                Why authentik?

                -
                -
                -
                - {% blocktrans %} - You recently requested to change your password for you authentik account. Use the button below to set a new password. - {% endblocktrans %} + {% trans 'You recently requested to change your password for you authentik account. Use the button below to set a new password.' %}
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                authentikKeycloakMicrosoft ADFSMicrosoft Azure ADOktaDuoAuthelia
                Protocol Support (as a provider)
                SAML2 - - - - - - - - - - - - - -
                OAuth2 and OIDC - - - - - - - - - - - - - -
                SCIM - - - - - - - - - - - - - -
                LDAP - - - - - - - - - - - - - -
                RADIUS - - - - - - - - - - - - - -
                Federation support
                SAML2 - - - - - - - - - - - - - -
                OAuth2 and OIDC - - - - - - - - - - - - - -
                OAuth1 - - - - - - - - - - - - - -
                LDAP - - - - - - - - - - - - - -
                SCIM - - - - - - - - - - - - - -
                Use-cases
                Authentication - - - - - - - - - - - - - -
                Enrollment - - - - - - - - - - - - - -
                Self-service - - - - - - - - - - - - - -
                Features
                MFA - - - - - - - - - - - - - -
                - Conditional Access - - - - - - - - - - - - - - -
                - Open-source/Source available - - - - - - - - - - - - - - -
                - Application Proxy - - - - - - - - - - - - - - -
                - Device authentication/authorization - - - - - - - - - - - - - - -
                - -
                -
                - - ); -} diff --git a/website/src/components/Comparison/style.css b/website/src/components/Comparison/style.css deleted file mode 100644 index c24a80a10c..0000000000 --- a/website/src/components/Comparison/style.css +++ /dev/null @@ -1,155 +0,0 @@ -.header { - text-align: center; - padding: 2rem 0; -} - -table { - display: table; -} - -.table-responsive { - overflow-x: auto; -} -/** -* comparison -* -* Comparison table used in both the performance and correctness tables. -*/ - -table.comparison { - width: 100%; -} - -table.comparison [title], -table.comparison [title] { - text-decoration: underline; - text-decoration-style: dotted; -} - -table.comparison th, -table.comparison td, -table.comparison tr { - border: 0px none; - white-space: nowrap; -} - -table.comparison th { - padding-left: 0; - padding-right: 0; -} - -table.comparison tr th.authentik { - color: var(--ifm-color-primary); -} - -table.comparison thead.group tr { - border-top: 1px; - border-bottom: 1px; - border-bottom-color: var(--ifm-table-head-color); - border-top-style: solid; - border-bottom-style: solid; -} - -table.comparison thead.group th:first-child { - padding: 10px; - text-align: left; - font-weight: 800; -} - -table.comparison tr td { - padding-left: 10px; - min-width: 90px; - text-align: center; -} - -table.comparison tr td:first-child { - font-weight: bold; - text-align: left; - white-space: nowrap; - width: 25%; -} - -table.comparison tr td.description { - font-weight: normal; - min-width: 250px; - padding-top: 0; - vertical-align: top; - white-space: normal; -} - -table.comparison tr td.description .label { - color: var(--ifm-heading-color); - font-weight: bold; -} - -table.comparison tr td.description .text { - color: var(--ifm-color-emphasis-600); -} - -table.comparison tr td.description .links { - font-size: 0.9em; - margin-top: var(--ifm-spacing-vertical); -} - -table.comparison tr td.result { - background-color: var(--ifm-panel-background-color); -} - -table.comparison tr td.result.failed { - color: var(--ifm-color-danger); -} - -table.comparison tr td.result.lost { - background: var(--ifm-color-emphasis-1000); - color: transparent; -} - -table.comparison tr td.result.not-applicable { - background: var(--ifm-color-emphasis-1000); - color: rgba(var(--ifm-background-color-rgb), 0.5); -} - -table.comparison tr td.result.passed { - color: var(--ifm-color-success); -} - -table.comparison tr td.result.warning { - color: var(--ifm-color-warning); -} - -table.comparison tr td.result.authentik { - background: var(--ifm-color-primary); - color: var(--ifm-color-secondary); -} - -table.comparison tr td.bar { - padding: 0; - vertical-align: bottom; -} - -table.comparison tr td.bar .place { - font-size: 0.9em; -} - -table.comparison tr td.bar .measurement { - font-weight: bold; -} - -table.comparison tr td.bar .bar { - background: var(--ifm-color-emphasis-1000); - margin: 0 auto; -} - -table.comparison tr td.bar.authentik { - color: var(--ifm-color-primary); -} - -table.comparison tr td.bar.authentik .bar { - background: var(--ifm-color-primary); -} - -@media (max-width: 996px) { - table.comparison td.description { - display: none; - } -} diff --git a/website/src/components/NewsBar/index.tsx b/website/src/components/NewsBar/index.tsx deleted file mode 100644 index 374f6def94..0000000000 --- a/website/src/components/NewsBar/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from "react"; -import sidebar from "../../../sidebars"; -import "./style.css"; -import useBaseUrl from "@docusaurus/useBaseUrl"; - -interface ItemLink { - label: string; - link: string; -} - -export function getReleases(): ItemLink[] { - const docs = sidebar.docs; - const releaseCategory = docs.filter( - (doc) => doc.link?.slug === "releases", - )[0]; - // @ts-ignore - const releaseItems = releaseCategory.items!.filter( - (release) => typeof release === "string", - ); - const releaseVersion: ItemLink[] = releaseItems.map((relUrl: string) => { - const [_, year, version] = relUrl.split("/"); - const url = useBaseUrl(`docs/releases/${version.replace("v", "")}`); - return { - label: `authentik ${version} released!`, - link: url, - }; - }); - return releaseVersion; -} - -export function NewsBar() { - return ( -
                - News -
                - {getReleases().map((version) => { - return ( - - {version.label} - - ); - })} -
                -
                - ); -} diff --git a/website/src/components/NewsBar/style.css b/website/src/components/NewsBar/style.css deleted file mode 100644 index c5657bc5bf..0000000000 --- a/website/src/components/NewsBar/style.css +++ /dev/null @@ -1,27 +0,0 @@ -.news-bar-container { - display: flex; - flex-direction: row; - width: 100%; - font-size: 1.25rem; - font-weight: 800; -} - -.news-bar-container .items { - display: flex; - flex-direction: row; - justify-content: space-around; - width: 100%; -} - -.news-bar-container .items a { - color: var(--ifm-color-secondary-contrast-background); - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; - -webkit-transition: all 0.1s ease-in; - transition: all 0.1s ease-in; -} - -.news-bar-container .items a:hover { - color: var(--ifm-color-primary); - text-decoration: none; -} diff --git a/website/src/components/PricingQuestions/Card.tsx b/website/src/components/PricingQuestions/Card.tsx deleted file mode 100644 index 41dd93738b..0000000000 --- a/website/src/components/PricingQuestions/Card.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useState } from "react"; - -interface CardProps { - title: string; - body: string; -} - -const Card = ({ title, body }: CardProps): JSX.Element => { - const [isActive, setIsActive] = useState(false); - - return ( -
                -
                setIsActive((state) => !state)} - > -
                -
                - {title} -
                -
                - {isActive && ( -
                - {} -
                - )} -
                -
                - ); -}; - -export default Card; diff --git a/website/src/components/TextSlide/index.tsx b/website/src/components/TextSlide/index.tsx deleted file mode 100644 index 2384388cf2..0000000000 --- a/website/src/components/TextSlide/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react"; -import styles from "./style.module.css"; -import clsx from "clsx"; - -export function TextSlide({ words }) { - return ( -
                -
                {words[0]}
                -
                {words[1]}
                -
                {words[2]}
                -
                - ); -} diff --git a/website/src/components/TextSlide/style.module.css b/website/src/components/TextSlide/style.module.css deleted file mode 100644 index c583d4e616..0000000000 --- a/website/src/components/TextSlide/style.module.css +++ /dev/null @@ -1,47 +0,0 @@ -.slider { - --height: 1.25em; -} - -.slider { - height: var(--height); - overflow: hidden; -} - -.sliderEntry:first-of-type { - animation: slide 5s linear infinite; -} - -.sliderEntry { - height: var(--height); - padding: 0px 15px; - text-align: center; - margin-bottom: var(--height); - box-sizing: border-box; -} - -@keyframes slide { - 0% { - margin-top: calc(-6 * var(--height)); - } - 5% { - /* For stopping effect */ - margin-top: calc(-4 * var(--height)); - } - 33% { - margin-top: calc(-4 * var(--height)); - } - 38% { - /* For stopping effect */ - margin-top: calc(-2 * var(--height)); - } - 66% { - margin-top: calc(-2 * var(--height)); - } - 71% { - /* For stopping effect */ - margin-top: 0px; - } - 100% { - margin-top: 0px; - } -} diff --git a/website/src/components/Waitlist/index.jsx b/website/src/components/Waitlist/index.jsx deleted file mode 100644 index 16253686b2..0000000000 --- a/website/src/components/Waitlist/index.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from "react"; -import styles from "./style.module.css"; -import clsx from "clsx"; - -export function WaitListForm(props) { - return ( -
                -
                -

                Join the waitlist

                -

                - Sign up to be notified once authentik Enterprise becomes - ready! -

                - -
                -
                -
                -
                -

                - -

                - - - - -
                -
                -
                -
                -
                -
                - ); -} diff --git a/website/src/components/Waitlist/style.module.css b/website/src/components/Waitlist/style.module.css deleted file mode 100644 index 7bfd4a8777..0000000000 --- a/website/src/components/Waitlist/style.module.css +++ /dev/null @@ -1,6 +0,0 @@ -.emailInput { - width: 100%; - line-height: 2rem; - margin-bottom: 2rem; - padding: 0.5rem 1rem; -} diff --git a/website/src/css/custom.css b/website/src/css/custom.css index aec8cb4ef3..beb7ca2f28 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -37,24 +37,6 @@ stroke: var(--white); } -.hero--primary { - background: radial-gradient( - circle, - rgba(47, 6, 75, 1) 0%, - var(--ifm-color-primary) 50% - ); - padding-bottom: 5.3rem !important; - /* fix aliasing at the edge */ - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 3vw)); - clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 3vw)); -} - -.before-after-slider img { - max-width: none; -} - .header-github-link:hover { opacity: 0.6; } diff --git a/website/src/footer.html b/website/src/footer.html deleted file mode 100644 index 7a75dac1cc..0000000000 --- a/website/src/footer.html +++ /dev/null @@ -1,109 +0,0 @@ - - - -
                -
                -
                -
                - * indicates required -
                -
                - - - -
                -
                - - -
                - - -
                -
                -
                -
                - -
                - - - diff --git a/website/src/pages/api/index.jsx b/website/src/pages/api/index.jsx deleted file mode 100644 index 5ba633bdbc..0000000000 --- a/website/src/pages/api/index.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import Head from "@docusaurus/Head"; -import BrowserOnly from "@docusaurus/BrowserOnly"; - -function APIPage() { - return ( - - - - - - {() => { - window.location.pathname = "/developer-docs/api/"; - }} - - - ); -} -export default APIPage; diff --git a/website/src/pages/api/v3.jsx b/website/src/pages/api/v3.jsx deleted file mode 100644 index 8ea7046505..0000000000 --- a/website/src/pages/api/v3.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import Head from "@docusaurus/Head"; -import BrowserOnly from "@docusaurus/BrowserOnly"; - -function APIPage() { - return ( - - - - - - {() => { - window.location.pathname = "/developer-docs/api/"; - }} - - - ); -} -export default APIPage; diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx deleted file mode 100644 index 08afbf646e..0000000000 --- a/website/src/pages/index.jsx +++ /dev/null @@ -1,283 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import Layout from "@theme/Layout"; -import Link from "@docusaurus/Link"; -import Head from "@docusaurus/Head"; -import BrowserOnly from "@docusaurus/BrowserOnly"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import styles from "./styles.module.css"; -import Comparison from "../components/Comparison"; -import "react-before-after-slider-component/dist/build.css"; -import { NewsBar } from "../components/NewsBar"; -import { TextSlide } from "../components/TextSlide"; - -function Feature({ imageUrl, title, description }) { - const imgUrl = useBaseUrl(imageUrl); - return ( -
                - {imgUrl && ( -
                - {title} -
                - )} -

                {title}

                -

                {description}

                -
                - ); -} - -function Home() { - const context = useDocusaurusContext(); - const { siteConfig = {} } = context; - return ( - - - - -
                -
                -
                -
                -

                -
                Replace
                - -
                with a unified platform.
                -

                -

                - Unify your external users and team members in a - single platform -

                -
                - - Get Started - - - Reasons to switch - -
                -
                -
                - authentik logo -
                -
                -
                -
                -
                -
                -
                -
                - - A single platform for all your identity - needs. Engineers have overview and - control of the identity environment from - a single interface. - - } - /> - - Available source code ensures a - continuous high level of security - through independent industry experts - using and testing the code. - - } - /> - - A straightforward pricing model for all - the features. No more guessing if a - feature is included in your subscription - or not. Covers B2B and B2C use cases. - - } - /> - - Build your workflows in authentik as you - need them, without limitations. And if - that's not enough, everything else can - be done through the API. - - } - /> -
                -
                -
                -
                - -
                -
                -
                -
                -
                - - {() => { - const ReactBeforeSliderComponent = require("react-before-after-slider-component"); - return ( - - ); - }} - -
                -
                -

                What is authentik?

                -

                - authentik is an open-source Identity - Provider focused on flexibility and - versatility. You can use authentik in an - existing environment to add support for new - protocols, implement sign-up/recovery/etc. - in your application so you don't have to - deal with it, and many other things. -

                -
                -
                -
                -
                -

                Utmost flexibility

                -

                - You can adopt authentik to your environment, - regardless of your requirements. Need an - Active-Directory integrated SSO Provider? Do - you want to implement a custom enrollment - process for your customers? Are you - developing an application and don't want to - deal with User verification and recovery? - authentik can do all of that, and more! -

                -
                -
                - - {() => { - const ReactBeforeSliderComponent = require("react-before-after-slider-component"); - return ( - - ); - }} - -
                -
                -
                -
                -
                -
                - -
                -
                -
                -
                -

                Try authentik now!

                -
                - - Get Started - - - Learn about enterprise - -
                -
                -
                -
                -
                - ); -} - -export default Home; diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx new file mode 100644 index 0000000000..dba1b8dfa1 --- /dev/null +++ b/website/src/pages/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import clsx from "clsx"; +import Layout from "@theme/Layout"; +import BrowserOnly from "@docusaurus/BrowserOnly"; + +function Home() { + return ( + + + {() => { + window.location.href = "/docs"; + }} + +
                +
                +

                authentik Documentation

                +
                +
                +
                + ); +} + +export default Home; diff --git a/website/src/pages/jobs/index.jsx b/website/src/pages/jobs/index.jsx deleted file mode 100644 index 1f4138f1ec..0000000000 --- a/website/src/pages/jobs/index.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import { useColorMode } from "@docusaurus/theme-common"; -import { useEffect } from "react"; - -function JobBoardWrapper() { - const context = useDocusaurusContext(); - const { siteConfig = {} } = context; - return ( - - - - ); -} - -function JobBoard() { - const { colorMode, setColorMode } = useColorMode(); - if (colorMode !== "light") { - setColorMode("light"); - } - useEffect(() => { - Grnhse.Iframe.load(); - }, []); - return
                ; -} - -export default JobBoardWrapper; diff --git a/website/src/pages/legal/privacy-policy.md b/website/src/pages/legal/privacy-policy.md deleted file mode 100644 index 02f7fc292c..0000000000 --- a/website/src/pages/legal/privacy-policy.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Authentik Security Inc. Privacy policy ---- - -# Authentik Security Inc. Privacy policy - -Last updated January 7, 2024 - -## Privacy Policy - -Effective as of January 7, 2024. - -Authentik Security Inc. (**"authentik," "we", "us"** or **"our"**) provides security software that allow our customers to securely access a variety of applications and services. This Privacy Policy describes how Authentik processes personal information that we collect through our digital or online properties or services that link to this Privacy Policy (collectively, the "Service"). - -Our products and services are intended for business customers. This Privacy Policy does not apply to information that we process on behalf of our business customers while providing the Service, which is governed by our agreements with those business customers. If you have concerns regarding personal information that we process on behalf of a business, please direct your concerns to them. - -## Personal information we collect - -**Information you provide to us**. Personal information you may provide to us through the Service or otherwise includes: - -- **Contact data**, such as your first and last name, salutation, email address, physical address, professional title and company name, and phone number. -- **Communications data** based on our exchanges with you, including when you contact us through the Service, social media, or otherwise. -- **Marketing data**, such as your preferences for receiving our marketing communications and details about your engagement with them. -- **Other data** not specifically listed here, which we will use as described in this Privacy Policy or as otherwise disclosed at the time of collection. - -**Automatic data collection**. We, our service providers, and our business partners may automatically log information about you, your computer or mobile device, and your interaction over time with the Service, our communications and other online services, such as: - -- **Device data**, such as your computer or mobile device’s operating system type and version, manufacturer and model, browser type, screen resolution, RAM and disk size, CPU usage, device type (e.g., phone, tablet), IP address, unique identifiers (including identifiers used for advertising purposes), language settings, mobile device carrier, radio/network information (e.g., Wi-Fi, LTE, 3G), and general location information such as city, state or geographic area. -- **Online activity data**, such as pages or screens you viewed, how long you spent on a page or screen, the website you visited before browsing to the Service, navigation paths between pages or screens, information about your activity on a page or screen, access times and duration of access, and whether you have opened our emails or clicked links within them. -- **Communication interaction data** such as your interactions with our email, text or other communications (e.g., whether you open and/or forward emails) – we may do this through use of pixel tags (which are also known as clear GIFs), which may be embedded invisibly in our emails. - -For more information concerning our automatic collection of data, please see the Tracking technologies section below. - -## Tracking Technologies - -**Cookies and other technologies**. Some of the automatic collection described above is facilitated by the following technologies: - -- **Cookies**, which are small text files that websites store on user devices and that allow web servers to record users’ web browsing activities and remember their submissions, preferences, and login status as they navigate a site. Cookies used on our sites include both "session cookies" that are deleted when a session ends, "persistent cookies" that remain longer, "first party" cookies that we place and "third party" cookies that our third-party business partners and service providers place. -- **Local storage technologies**, like HTML5, that provide cookie-equivalent functionality but can store larger amounts of data on your device outside of your browser in connection with specific applications. -- **Web beacons**, also known as pixel tags or clear GIFs, which are used to demonstrate that a webpage or email was accessed or opened, or that certain content was viewed or clicked. - -For information concerning your choices with respect to the use of tracking technologies, see the Your choices section, below. - -## How we use your personal information - -We may use your personal information for the following purposes or as otherwise described at the time of collection: - -**Service delivery and operations**. We may use your personal information to: - -- provide the Service; -- enable security features of the Service; -- communicate with you about the Service, including by sending Service-related announcements, updates, security alerts, and support and administrative messages; -- provide support for the Service, and respond to your requests, questions and feedback. - -**Marketing**. We, our service providers and our third-party partners may collect and use your personal information for marketing purposes, such as to send you direct marketing communications and may personalize these messages based on your needs and interests. You may opt-out of our marketing communications as described in the Opt-out of marketing section below. - -**Compliance and protection**. We may use your personal information to: - -- comply with applicable laws, lawful requests, and legal process, such as to respond to subpoenas, investigations or requests from government authorities; -- protect our, your or others’ rights, privacy, safety or property (including by making and defending legal claims); -- audit our internal processes for compliance with legal and contractual requirements or our internal policies; -- enforce the terms and conditions that govern the Service; and -- prevent, identify, investigate and deter fraudulent, harmful, unauthorized, unethical or illegal activity, including cyberattacks and identity theft. - -**Cookies and other technologies**. In addition to the other uses included in this section, we may use the Cookies and other technologies described above for the following purposes: - -- **Technical operation**. To allow the technical operation of the Service, such as by remembering your selections and preferences as you navigate the site, and whether you are logged in when you visit password protected areas of the Service. -- **Functionality**. To enhance the performance and functionality of our services. -- **Analytics**. To help us understand user activity on the Service, including which pages are most and least visited and how visitors move around the Service, as well as user interactions with our emails. For example, we use Google Analytics for this purpose. You can learn more about Google Analytics and how to prevent the use of Google Analytics relating to your use of our sites here: https://tools.google.com/dlpage/gaoptout?hl=en. - -**To create aggregated, de-identified and/or anonymized data**. We may create aggregated, de-identified and/or anonymized data from your personal information and other individuals whose personal information we collect. We make personal information into de-identified and/or anonymized data by removing information that makes the data identifiable to you and we will not attempt to reidentify any such data. We may use this aggregated, de-identified and/or anonymized data and share it with third parties for our lawful business purposes, to the extent that such uses and sharing are in compliance with applicable laws, including to analyze and improve the Service and promote our business. - -## How we share your personal information - -We may share your personal information with the following parties and as otherwise described in this Privacy Policy, in other applicable notices, or at the time of collection. - -**Affiliates**. Our corporate parent, subsidiaries, and affiliates. - -**Service providers**. Third parties that provide services on our behalf or help us operate the Service or our business (such as hosting, information technology, customer support, email delivery, marketing, consumer research and website analytics). - -**Professional advisors**. Professional advisors, such as lawyers, auditors, bankers and insurers, where necessary in the course of the professional services that they render to us. - -**Authorities and others**. Law enforcement, government authorities, and private parties, as we believe in good faith to be necessary or appropriate for the Compliance and protection purposes described above. - -**Business transferees**. We may disclose personal information in the context of actual or prospective business transactions (e.g., investments in Authentik, financing of Authentik, public stock offerings, or the sale, transfer or merger of all or part of our business, assets or shares), for example, we may need to share certain personal information with prospective counterparties and their advisers. We may also disclose your personal information to an acquirer, successor, or assignee of Authentik as part of any merger, acquisition, sale of assets, or similar transaction, and/or in the event of an insolvency, bankruptcy, or receivership in which personal information is transferred to one or more third parties as one of our business assets. - -## Your choices - -**Opt-out of communications**. You may opt-out of marketing-related emails by following the opt-out or unsubscribe instructions at the bottom of the email, or by contacting us. Please note that if you choose to opt-out of marketing-related emails, you may continue to receive service-related and other non-marketing emails. - -**Cookies and other technologies**. Most browsers let you remove or reject cookies. To do this, follow the instructions in your browser settings. Many browsers accept cookies by default until you change your settings. Please note that if you set your browser to disable cookies, the Service may not work properly. For more information about cookies, including how to see what cookies have been set on your browser and how to manage and delete them, visit www.allaboutcookies.org. You can also configure your device to prevent images from loading to prevent web beacons from functioning. - -**Blocking images/clear gifs**: Most browsers and devices allow you to configure your device to prevent images from loading. To do this, follow the instructions in your particular browser or device settings. - -**Do Not Track**. Some Internet browsers may be configured to send "Do Not Track" signals to the online services that you visit. We currently do not respond to "Do Not Track" signals. To find out more about "Do Not Track," please visit http://www.allaboutdnt.com. - -**Declining to provide information**. We need to collect personal information to provide certain services. If you do not provide the information we identify as required or mandatory, we may not be able to provide those services. - -## Other sites and services - -The Service may contain links to websites, mobile applications, and other online services operated by third parties. In addition, our content may be integrated into web pages or other online services that are not associated with us. These links and integrations are not an endorsement of, or representation that we are affiliated with, any third party. We do not control websites, mobile applications or online services operated by third parties, and we are not responsible for their actions. We encourage you to read the privacy policies of the other websites, mobile applications and online services you use. - -## Security - -We employ technical, organizational and physical safeguards designed to protect the personal information we collect. However, security risk is inherent in all internet and information technologies and we cannot guarantee the security of your personal information. - -## International data transfer - -We are headquartered in the United States and may use service providers that operate in other countries. Your personal information may be transferred to the United States or other locations where privacy laws may not be as protective as those in your state, province, or country. - -## Children - -The Service is not intended for use by anyone under 16 years of age. If you are a parent or guardian of a child from whom you believe we have collected personal information in a manner prohibited by law, please contact us. If we learn that we have collected personal information through the Service from a child without the consent of the child’s parent or guardian as required by law, we will comply with applicable legal requirements to delete the information. - -## Changes to this Privacy Policy - -We reserve the right to modify this Privacy Policy at any time. If we make material changes to this Privacy Policy, we will notify you by updating the date of this Privacy Policy and posting it on the Service or other appropriate means. Any modifications to this Privacy Policy will be effective upon our posting the modified version (or as otherwise indicated at the time of posting). In all cases, your use of the Service after the effective date of any modified Privacy Policy indicates your acknowledging that the modified Privacy Policy applies to your interactions with the Service and our business. - -## How to contact us - -- **Email**: hello@goauthentik.io -- **Mail**: 548 Market Street, PMB 70148, San Francisco, CA 94104-5401 diff --git a/website/src/pages/legal/terms.md b/website/src/pages/legal/terms.md deleted file mode 100644 index 9d59097ddd..0000000000 --- a/website/src/pages/legal/terms.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Authentik Security Inc. Subscription Terms ---- - -# Authentik Subscription Terms - -By signing this agreement, you and any entity that you represent ("Customer") are unconditionally consenting to be bound by and are becoming a party to these Authentik Subscription Terms ("Agreement") as of the date of Customer's first download of the Licensed Materials (the "Effective Date"). - -Customer's continued use of the software or any Licensed Materials provided by Authentik Security Inc. (a Delaware corporation with its principal offices located on Market St in San Francisco CA) or one of its affiliates and/or subsidiaries, as specified on an order form or quote ("Authentik") shall also constitute assent to the terms of this agreement. - -If these terms are considered an offer, acceptance is expressly limited to these terms. If you are executing this agreement on behalf of an organization, you represent that you have the authority to do so. - -## 1. LICENSE AND SUPPORT - -1.1 Subject to the terms and conditions of this Agreement, Authentik hereby grants to Customer and its Affiliates (as defined below) a limited, non-exclusive, non-transferable, non-sublicensable license for Customer’s and its Affiliates’ employees and contractors to (1) internally (a) use, reproduce, modify, prepare derivative works based upon, and display the code of Authentik Enterprise Edition ("Authentik EE") at the tier level selected by Customer or set forth on a Quote (as defined below), if applicable with the specifications generally promulgated by Authentik from time to time (the “Software”) solely (i) for its internal use in connection with the development of Customer’s and/or its Affiliates’ own software, and (ii) by the number of Hosts (defined below) for which Customer has paid Authentik; and (b) use the documentation, training materials or other materials supplied by Authentik (the “Other Authentik Materials”); and (2) modify the Software and publish patches to the Software. - -Notwithstanding anything to the contrary, Customer agrees that Authentik and/or its licensors (as applicable) retain all right, title and interest in and to all Software incorporated in such modifications and/or patches, and all such Software may only be used, copied, modified, displayed, distributed, or otherwise exploited in full compliance with this Agreement, and with a valid Authentik Enterprise Edition subscription for the correct number of Hosts. - -The Software and Other Authentik Materials are collectively referred to herein as the “Licensed Materials.” - -“Affiliate” means any entity(ies) controlling, controlled by, and/or under common control with a party hereto, where “control” means the ownership of more than 50% of the voting securities in such entity. - -"User" means each individual end-user (person or machine) of Customer and/or its Affiliates (including, without limitation, employees, agents or consultants thereof) with access to the Licensed Materials hereunder. - -"Host" means each individual machine (real or virtual, including servers, containers, workstations, smartphones, POS, industrial controls, gateways, sensors, IoT endpoints, or any other physical or simulated computing interface or machine) of Customer and/or its Affiliates (including, without limitation, employees, agents or consultants thereof) with access to Licensed Materials hereunder. - -1.2 Subject to the terms hereof, Authentik will provide reasonable support to Customer for the Licensed Materials as set forth at https://goauthentik.io, for the support plan selected and paid for by Customer. Notwithstanding anything to the contrary, in the event that Customer does not reasonably comply with written specifications or instructions from Authentik’s service engineers regarding any support issue or request (including without limitation, failure to make backups of Customer’s Licensed Materials) (each, a “Support Issue”), Authentik may terminate its support obligations to Customer with respect to such Support Issue upon fifteen (15) days’ written notice if Customer does not cure such noncompliance within the notice period. - -1.2.1 Authentik will use reasonable commercial efforts to respond to support questions by phone or email during the next business day. The number of support questions is not limited. - -## 2. RESTRICTIONS AND RESPONSIBILITIES - -2.1 Except as expressly authorized in Section 1.1, Customer will not, and will not permit any third party to: use the Licensed Materials for any purpose other than as specifically authorized in Section 1, or in such a manner that would enable any unlicensed person to access the Licensed Materials; use the Licensed Materials or any other Authentik software for timesharing or service bureau purposes or for any purpose other than its and its Affiliates’ own internal use (including without limitation, sublicensing, distributing, selling, reselling any of the foregoing); except as expressly permitted herein; use the Licensed Materials in connection with any high risk or strict liability activity (including, without limitation, space travel, firefighting, police operations, power plant operation, military operations, rescue operations, hospital and medical operations or the like); use the Licensed Materials or software other than in accordance with this Agreement and in compliance with all applicable laws and regulations (including but not limited to any privacy laws, and laws and regulations concerning intellectual property, consumer and child protection, obscenity or defamation); or use the Licensed Materials in any manner that (1) is harmful, fraudulent, deceptive, threatening, abusive, harassing, tortious, defamatory, vulgar, obscene, or libelous (including without limitation, accessing any computer, computer system, network, software, or data without authorization, breaching the security of another user or system, and/or attempting to circumvent any Host or User authentication or security process), (2) impersonates any person or entity, including without limitation any employee or representative of Authentik, or (3) contains a virus, trojan horse, worm, time bomb, unsolicited bulk, commercial, or “spam” message, or other harmful computer code, file, or program (including without limitation, password guessing programs, decoders, password gatherers, keystroke loggers, cracking tools, packet sniffers, and/or encryption circumvention programs). - -2.2 Customer will cooperate with Authentik in connection with the performance of this Agreement by making available such personnel and information as may be reasonably required, and taking such other actions as Authentik may reasonably request. Customer will also cooperate with Authentik in establishing a password or other procedures for verifying that only designated employees of Customer have access to any administrative functions of the Licensed Materials. Customer shall maintain during the term of this Agreement and through the end of the third year after the date on which the final payment is made under this Agreement, books, records, contracts and accounts relating to the payments due Authentik under this Agreement (collectively, the “Customer Records”). Authentik may, at its sole expense, upon 30 days’ prior written notice to Customer and during Customer’s normal business hours and subject to industry-standard confidentiality obligations, hire an independent third party auditor to audit the Customer Records only to verify the amounts payable under this Agreement. If an audit reveals underpayment, then Customer shall promptly pay the deficiency to Authentik plus late fees pursuant to Section 5.2. Authentik shall bear the cost of an audit unless the audit reveals underpayment by more than 5% for the audited period, in which case Customer shall promptly pay Authentik for the reasonable costs of the audit. - -2.3 Customer will be responsible for maintaining the security of Customer’s account, passwords (including but not limited to administrative and User passwords and credentials for Hosts like e) and files, and for all uses of Customer account with or without Customer’s knowledge or consent. - -## 3. CONFIDENTIALITY - -3.1 Each party (the “Receiving Party”) understands that the other party (the “Disclosing Party”) has disclosed or may disclose information relating to the Disclosing Party’s technology or business (hereinafter referred to as “Proprietary Information” of the Disclosing Party). Without limiting the foregoing, the Licensed Materials are Authentik Proprietary Information. - -3.2 The Receiving Party agrees: (i) not to divulge to any third person any such Proprietary Information, (ii) to give access to such Proprietary Information solely to those employees with a need to have access thereto for purposes of this Agreement, and (iii) to take the same security precautions to protect against disclosure or unauthorized use of such Proprietary Information that the party takes with its own proprietary information, but in no event will a party apply less than reasonable precautions to protect such Proprietary Information. The Disclosing Party agrees that the foregoing will not apply with respect to any information that the Receiving Party can document (a) is or becomes generally available to the public without any action by, or involvement of, the Receiving Party, or (b) was in its possession or known by it prior to receipt from the Disclosing Party, or (c) was rightfully disclosed to it without restriction by a third party, or (d) was independently developed without use of any Proprietary Information of the Disclosing Party. Nothing in this Agreement will prevent the Receiving Party from disclosing Proprietary Information pursuant to any judicial or governmental order, provided that the Receiving Party gives the Disclosing Party reasonable prior notice of such disclosure to contest such order. In any event, Authentik may collect data with respect to and report on the aggregate response rate and other aggregate measures of the Licensed Materials’ performance and Customer’s usage of the Licensed Materials; provided that Authentik will not identify Customer as the source of any such data without Customer’s prior written consent. For the avoidance of doubt, use of a third party to host the data collected shall not be deemed a disclosure. - -3.3 Each party acknowledges and agrees that the other may suffer irreparable damage in the event of a breach of the terms of Sections 1.1, 2.1 or 3.2 of this Agreement and that such party will be entitled to seek injunctive relief (without the necessity of posting a bond) in the event of any such breach. - -3.4 Both parties will have the right to disclose the existence of the relationship between the parties, but not the terms and conditions of this Agreement, unless such disclosure of the Agreement terms is approved in writing by both Parties prior to such disclosure, or is included in a filing required to be made by a party with a governmental authority (provided such party will use reasonable efforts to obtain confidential treatment or a protective order) or is made on a confidential basis as reasonably necessary to potential investors or acquirers. - -## 4. INTELLECTUAL PROPERTY RIGHTS - -4.1 Except as expressly set forth herein, Authentik alone (and its licensors, where applicable) will retain all intellectual property rights relating to the Licensed Materials and any suggestions, ideas, enhancement requests, feedback, code, or other recommendations provided by Customer, its Affiliates or any third party relating to the Licensed Materials, which are hereby assigned to Authentik. This Agreement is not a sale and does not convey to Customer any rights of ownership in or related to the Licensed Materials, or any intellectual property rights. - -4.2 Customer shall not remove, alter or obscure any of Authentik’s (or its licensors’) copyright notices, proprietary legends, trademark or service mark attributions, patent markings or other indicia of Authentik’s (or its licensors’) ownership or contribution from the Licensed Materials. Additionally, Customer agrees to reproduce and include Authentik’s (and its licensors’) proprietary and copyright notices on any copies of the Licensed Materials, or on any portion thereof, including reproduction of the copyright notice. Notwithstanding anything to the contrary herein, certain components of the Licensed Materials, including without limitation, any component of the Licensed Materials distributed by Authentik as part of the Authentik Community Edition, are licensed by third parties pursuant to the terms of certain third party licenses described in such source code annotations. - -4.3 Customer and its licensors shall (and Customer hereby represents and warrants that they do) have and retain all right, title and interest (including, without limitation, sole ownership of) all software, information, content and data provided by or on behalf of Customer or made available or otherwise distributed through use of the Licensed Materials (“Content”) and the intellectual property rights with respect to that Content. If Authentik receives any notice or claim that any Content, or Customer’s activities hereunder (including without limitation, with respect to any Content), infringes or violates the rights of a third party or any applicable law or regulation (a “Claim”), Customer will indemnify, defend and hold Authentik harmless from all liability, damages, settlements, attorney fees and other costs and expenses in connection with any such Claim, as incurred. The immediately foregoing indemnity obligations are expressly conditioned on Authentik providing Customer with prompt notice of, and reasonable cooperation and sole control over the defense and/or settlement of the applicable Claim. Subject to the foregoing, Authentik may participate in the defense and/or settlement of any applicable Claim with counsel of its choosing at its own expense. - -4.4 Authentik will defend, indemnify and hold Customer harmless from liability and other amounts paid or payable to unaffiliated third parties resulting from (i) the infringement or violation of any intellectual property or proprietary rights by the Licensed Materials or (ii) the violation of applicable law or regulation by Authentik in performance of its obligations hereunder, provided Authentik is promptly notified of any and all threats, claims and proceedings related thereto and given reasonable assistance and the opportunity to assume sole control over defense and settlement thereof. Subject to the foregoing, Customer may participate in the defense and/or settlement of any claim that is indemnifiable by Authentik with counsel of its choosing at its own expense. The foregoing obligations do not apply with respect to portions or components of the Licensed Materials (i) not created by Authentik, (ii) that are modified after delivery by Authentik, (iii) combined with other products, processes or materials where the alleged infringement relates to such combination, (iv) where Customer continues allegedly infringing activity after being notified thereof or after being informed of modifications that would have avoided the alleged infringement, or (v) where Customer’s use of the Licensed Materials is not strictly in accordance with this Agreement and all related documentation. - -## 5. PAYMENT OF FEES - -5.1 Unless and until Authentik and Customer have executed a quote document specifically referencing this Agreement with respect to amounts due on account of the Licensed Materials (a “Quote”, which is hereby incorporated by reference, if applicable), and unless Customer’s subscription to (and payment with respect to) the Licensed Materials has been made on Customer’s behalf by a reseller, Customer will pay Authentik the applicable fees as set forth at https://goauthentik.io (the “Pricing”) for the Licensed Materials selected and/or used by Customer (the “Fees”) without any right of set-off or deduction. On each anniversary of the Effective Date, Authentik will invoice Customer (or its reseller, if applicable) with respect to any and all additional Customer Hosts of the Licensed Materials beyond those for whom Customer has pre-paid, as of such date (and for whom the Fees due pursuant to such invoice will be the then-current per-year Host fee with respect to the year just ended, and the then current per-year Host fee with respect to all subsequent years, unless otherwise agreed in writing by both parties (collectively, a “True-Up”)). For Customers that have pre-paid all Fees for multi-year subscriptions for Licensed Materials pursuant to a Quote, on each anniversary of the Effective Date during the term of this Agreement, (i) a new license key will be provided, and (ii) a True-Up will be conducted. All additional Hosts purchased shall be co-terminated through the end of the original Subscription period. - -5.2 All payments will be made in accordance with the payment schedule and the method of payment set forth in the Pricing. If not otherwise specified, (a) Authentik will invoice Customer with respect to Fees up-front, for each term of the Customer's subscription (as applicable), and (b) payments will be due within thirty (30) days of Customer's receipt of correct invoice. Except as expressly set forth in this Agreement, all Fees paid and/or due hereunder (including any prepaid amounts) are non-refundable, including without limitation if this Agreement is terminated in accordance with Section 6 below. If Customer terminates this Agreement pursuant to Section 6.2 within 45 calendar days from receipt of the initial invoice for the Licensed Materials, Authentik will refund all Fees paid hereunder. - -5.3 Any unpaid fees are subject to a finance charge of one percent (1.0%) per month, or the maximum permitted by law, whichever is lower, plus all expenses of collection, including reasonable attorneys’ fees. Fees under this Agreement are exclusive of all taxes, including national, state or provincial and local use, sales, value-added, property and similar taxes, if any. Customer agrees to pay such taxes (excluding US taxes based on Authentik's net income) unless Customer has provided Authentik with a valid exemption certificate. In the case of any withholding requirements, Customer will pay any required withholding itself and will not reduce the amount paid to Authentik on account thereof. - -## 6. TERMINATION - -6.1 This Agreement shall continue until terminated in accordance with this Section 6. Either party may terminate this Agreement upon 15 days’ written notice to the other party hereto in the event that Customer has no then-current subscription and license key with respect to the Licensed Materials. - -6.2 Customer may terminate this Agreement at any time upon written notice to Authentik. Either party may terminate this Agreement immediately upon 15 days’ written notice to the other party in the event of any material breach of this Agreement (including without limitation, any breach of Section 2.2 and/or failure to pay any amounts when due hereunder) by such party where such material breach is not cured during such notice period. - -6.3 Either party may terminate this Agreement, without notice, (i) upon the institution by or against the other party of insolvency, receivership or bankruptcy proceedings (provided such proceedings are not dismissed within one hundred twenty (120) days of such institution), (ii) upon the other party's making an assignment for the benefit of creditors, or (iii) upon the other party's dissolution or ceasing to do business without a successor. - -6.4 Customer’s rights to the Licensed Materials, and any licenses granted hereunder, shall terminate upon any termination of this Agreement. In the event that Customer terminates this Agreement pursuant to the second sentence of Section 6.2 above, Authentik will refund to Customer a pro-rated portion of pre-paid Fees for Services not actually received by Customer as of the date of such termination. The following Sections will survive any termination of this Agreement: 2 through 6 (except for Section 4.3), and 8 through 11. - -## 7. WARRANTY; CUSTOMER SOFTWARE SECURITY - -Authentik represents and warrants that (i) it has all rights and licenses necessary for it to perform its obligations hereunder, and (ii) it will not knowingly include, in any Authentik software released to the public and provided to Customer hereunder, any computer code or other computer instructions, devices or techniques, including without limitation those known as disabling devices, trojans, or time bombs, that are intentionally designed to disrupt, disable, harm, infect, defraud, damage, or otherwise impede in any manner, the operation of a network, computer program or computer system or any component thereof, including its security or user data. If, at any time, Authentik fails to comply with the warranty in this Section, Customer may promptly notify Authentik in writing of any such noncompliance. Authentik will, within thirty (30) days of receipt of such written notification, either correct the noncompliance or provide Customer with a plan for correcting the noncompliance. If the noncompliance is not corrected or if a reasonably acceptable plan for correcting them is not established during such period, Customer may terminate this Agreement as its sole and exclusive remedy for such noncompliance. - -## 8. WARRANTY DISCLAIMER - -EXCEPT AS EXPRESSLY STATED HEREIN, THE LICENSED MATERIALS, SOFTWARE AND AUTHENTIK PROPRIETARY INFORMATION AND ANYTHING PROVIDED IN CONNECTION WITH THIS AGREEMENT ARE PROVIDED "AS-IS," WITHOUT ANY WARRANTIES OF ANY KIND. AUTHENTIK AND ITS LICENSORS HEREBY DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. - -## 9. LIMITATION OF LIABILITY - -EXCEPT WITH RESPECT TO BREACH(ES) OF SECTION 1.1 AND/OR 2.1, IN NO EVENT WILL EITHER PARTY OR THEIR LICENSORS BE LIABLE FOR ANY INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF THE LICENSED MATERIALS OR ANYTHING PROVIDED IN CONNECTION WITH THIS AGREEMENT, ANY DELAY OR INABILITY TO USE THE LICENSED MATERIALS OR ANYTHING PROVIDED IN CONNECTION WITH THIS AGREEMENT OR OTHERWISE ARISING FROM THIS AGREEMENT, INCLUDING WITHOUT LIMITATION, LOSS OF REVENUE OR ANTICIPATED PROFITS OR LOST BUSINESS OR LOST SALES, WHETHER BASED IN CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY, OR OTHERWISE, EVEN IF SUCH PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES. EXCEPT WITH RESPECT TO BREACH(ES) OF SECTION 1.1 AND/OR 2.1, THE TOTAL LIABILITY OF EACH PARTY AND ITS LICENSORS, WHETHER BASED IN CONTRACT, TORT (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, WILL NOT EXCEED, IN THE AGGREGATE, THE GREATER OF (i) ONE THOUSAND DOLLARS ($1,000), OR (ii) THE FEES PAID TO AUTHENTIK HEREUNDER IN ONE YEAR PERIOD ENDING ON THE DATE THAT A CLAIM OR DEMAND IS FIRST ASSERTED. THE FOREGOING LIMITATIONS WILL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. - -## 10. U.S. GOVERNMENT MATTERS - -Notwithstanding anything else, Customer may not provide to any person or export or re-export or allow the export or re-export of the Licensed Materials or any software or anything related thereto or any direct product thereof (collectively “Controlled Subject Matter”), in violation of any restrictions, laws or regulations of the United States Department of Commerce, the United States Department of Treasury Office of Foreign Assets Control, or any other United States or foreign agency or authority. Without limiting the foregoing Customer acknowledges and agrees that the Controlled Subject Matter will not be used or transferred or otherwise exported or re-exported to countries as to which the United States maintains an embargo (collectively, “Embargoed Countries”), or to or by a national or resident thereof, or any person or entity on the U.S. Department of Treasury’s List of Specially Designated Nationals or the U.S. Department of Commerce’s Table of Denial Orders (collectively, “Designated Nationals”). The lists of Embargoed Countries and Designated Nationals are subject to change without notice. Use of the Licensed Materials is representation and warranty that neither the User nor Host is located in, under the control of, or a national or resident of an Embargoed Country or Designated National. The Controlled Subject Matter may use or include encryption technology that is subject to licensing requirements under the U.S. Export Administration Regulations. As defined in FAR section 2.101, any software and documentation provided by Authentik are “commercial items” and according to DFAR section 252.2277014(a)(1) and (5) are deemed to be “commercial computer software” and “commercial computer software documentation.” Consistent with DFAR section 227.7202 and FAR section 12.212, any use modification, reproduction, release, performance, display, or disclosure of such commercial software or commercial software documentation by the U.S. Government will be governed solely by the terms of this Agreement and will be prohibited except to the extent expressly permitted by the terms of this Agreement. - -## 11. MISCELLANEOUS - -If any provision of this Agreement is found to be unenforceable or invalid, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement will otherwise remain in full force and effect and enforceable. This Agreement is not assignable, transferable or sublicensable by either party without the other party’s prior written consent, not to be unreasonably withheld or delayed; provided that either party may transfer and/or assign this Agreement to a successor in the event of a sale of all or substantially all of its business or assets to which this Agreement relates. Both parties agree that this Agreement is the complete and exclusive statement of the mutual understanding of the parties and supersedes and cancels all previous written and oral agreements, communications and other understandings relating to the subject matter of this Agreement, and that all waivers and modifications must be in a writing signed or otherwise agreed to by each party, except as otherwise provided herein. No agency, partnership, joint venture, or employment is created as a result of this Agreement and neither party has any authority of any kind to bind the other in any respect whatsoever. In any action or proceeding to enforce rights under this Agreement, the prevailing party will be entitled to recover costs and attorneys’ fees. All notices under this Agreement will be in writing and will be deemed to have been duly given when received, if personally delivered; when receipt is electronically confirmed, if transmitted by facsimile or e-mail; and upon receipt, if sent by certified or registered mail (return receipt requested), postage prepaid. Authentik will not be liable for any loss resulting from a cause over which it does not have direct control. This Agreement will be governed by the laws of the State of California, U.S.A. without regard to its conflict of laws provisions. The federal and state courts sitting in San Francisco County, California, U.S.A. will have proper and exclusive jurisdiction and venue with respect to any disputes arising from or related to the subject matter of this Agreement. - -## 12. DATA PRIVACY - -Customer shall ensure that any and all information or data, including without limitation, personal data, used by Customer in connection with the Agreement (“Customer Data”) is collected, processed, transferred and used in full compliance with Applicable Data Protection Laws (as defined below) and that it has all obtained all necessary authorizations and consents from any data subjects to process Customer Data. Customer shall adopt and maintain appropriate organizational, technical and security measures prior to any such collection, processing or transfer in order to protect against unauthorized access to or use of Customer Data. Customer shall immediately inform Authentik upon becoming aware of any breach within the meaning of Applicable Data Protection Law relating to Customer Data (a “Security Incident”) and to cooperate with Authentik in any investigation thereof and in the implementation of any measures reasonably required to be taken in response thereto. If required by Applicable Data Protection Laws, the parties will enter into standard contractual clauses under GDPR (as defined below) for the transfer of any Customer Data outside of the European Union. For purposes hereof: (a) “Applicable Data Protection Laws” means any applicable laws, statutes or regulations as may be amended, extended or re-enacted from time to time which relate to personal data including without limitation (i) prior to 25 May 2018, the EU Data Protection Directive 95/46/EC as transposed into EU Member State law; (ii) from and after 25 May 2018, GDPR and any EU Member State laws implementing the GDPR; and (iii) the e-Privacy Directive 2002/58/EC, as amended and as transposed into EU Member State law and any legislation replacing the e-Privacy Directive and (b) “GDPR” means the Regulation (EU) 2016/679 of the European Parliament and of the Counsel of 27 April 2016 on the protection of natural persons with regard to the processing of personal data and on the free movement of such data, - -[THE REMAINDER OF THIS PAGE INTENTIONALLY LEFT BLANK] - -**IN WITNESS WHEREOF,** the parties have executed this Agreement as of the Effective Date. - -_This work, "authentik Subscription Terms", is a derivative of "[Fleet Subscription Terms](https://fleetdm.com/legal/terms)", by [Fleet Device Management Inc.](https://fleetdm.com/handbook/company), used under CC BY-SA 4.0. "authentik Subscription Terms" is licensed under CC BY-SA 4.0 by Authentik Security Inc._ - -[![License: CC BY-SA 4.0](https://licensebuttons.net/l/by-sa/4.0/80x15.png)](https://creativecommons.org/licenses/by-sa/4.0/) diff --git a/website/src/pages/pricing/index.jsx b/website/src/pages/pricing/index.jsx deleted file mode 100644 index dd8a11d70f..0000000000 --- a/website/src/pages/pricing/index.jsx +++ /dev/null @@ -1,177 +0,0 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import Link from "@docusaurus/Link"; -import Card from "../../components/PricingQuestions/Card"; -import useBaseUrl from "@docusaurus/useBaseUrl"; - -export default function pricingPage() { - const commonFeatures = [ -
              • - Supports{" "} - - OAuth2/OpenID Connect - -
              • , -
              • - Supports SAML -
              • , -
              • - Supports LDAP -
              • , -
              • - Supports SCIM -
              • , -
              • - Supports Radius -
              • , -
              • - Supports Proxy -
              • , -
              • Advanced policy engine
              • , - ]; - const enterpriseFeatures = [ -
              • Long-term-support releases
              • , -
              • Enterprise support plan
              • , -
              • Web-based RDP/SSH access (planned)
              • , -
              • Push-notification MFA (planned)
              • , -
              • Desktop authentication (planned)
              • , -
              • AI-based risk assessment (planned)
              • , - ]; - return ( - -
                -
                -

                Pricing

                - -
                -
                -
                -
                -

                Open Source

                -
                -
                -
                  -
                • Open source
                • -
                • Self-hosted
                • - {commonFeatures} -
                -
                -
                -

                Free, forever

                - - Get Started - -
                -
                -
                -
                -
                -
                -

                Enterprise Self-Hosted

                -
                -
                -
                  -
                • Source-available
                • -
                • Self-hosted
                • - {commonFeatures} - {enterpriseFeatures} -
                -
                -
                -

                - $5 /internal user/month -

                -

                - $0.02{" "} - /external user/month -

                - - Get Started - -
                -
                -
                -
                -
                -
                -

                Enterprise Cloud

                -
                -
                -
                  -
                • Hosted and Managed by authentik
                • -
                • Source-available
                • - {commonFeatures} - {enterpriseFeatures} -
                • - Easily shift to self-hosted if - needed -
                • -
                -
                -
                -

                - $5 /internal user/month -

                -

                - $0.02{" "} - /external user/month -

                - - Join waitlist - -
                -
                -
                -
                -
                -
                - -
                -
                -
                -
                -

                - Frequently Asked Questions -

                -
                - - - - - -
                -
                -
                -
                -
                -
                - ); -} diff --git a/website/src/pages/pricing/waitlist/cloud.jsx b/website/src/pages/pricing/waitlist/cloud.jsx deleted file mode 100644 index 00ffcb3307..0000000000 --- a/website/src/pages/pricing/waitlist/cloud.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; -import { WaitListForm } from "../../../components/Waitlist"; -import Layout from "@theme/Layout"; - -export default function waitlistCloud() { - return ( - - - - ); -} diff --git a/website/src/pages/styles.module.css b/website/src/pages/styles.module.css deleted file mode 100644 index 1ab0bb255f..0000000000 --- a/website/src/pages/styles.module.css +++ /dev/null @@ -1,99 +0,0 @@ -/* stylelint-disable docusaurus/copyright-header */ -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; - overflow-wrap: normal; - color: var(--white); -} - -.headerRow { - margin-bottom: -10rem; -} - -.heroImage { - flex-direction: column; - justify-items: center; - --ifm-col-width: 45%; -} - -.heroImage > img { - filter: drop-shadow(5px 5px 25px rgba(0, 0, 0, 0.6)); -} - -@media (max-width: 996px) { - .headerRow { - margin-bottom: 0; - } - .hiddenOnMobile { - display: none; - } - .heroBanner { - padding: 2rem; - } -} - -.ak_hero__title { - font-size: 1.75rem; -} - -@media (min-width: 388px) { - .ak_hero__title { - font-size: 2rem; - } -} - -@media (min-width: 520px) { - .ak_hero__title { - font-size: 3rem; - } -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; - align-items: center; - flex-wrap: wrap; -} - -.buttons > * { - margin: 0.25rem; -} - -.features { - display: flex; - align-items: center; - padding: 2rem 0; - width: 100%; - flex-direction: column; -} - -.row { - padding-bottom: 2rem; -} - -.rowFullWidth { - width: 100%; - padding: 1rem 3rem; -} - -.rowDark { - background-color: var(--ifm-color-secondary-contrast-foreground); - color: var(--ifm-color-secondary-contrast-background); -} - -.rowAuthentik { - color: var(--white); - background-color: var(--ifm-color-primary); -} - -.newsBar { - margin-bottom: 4rem; -} - -.footerCTA { - padding: 3rem; - text-align: center; -} diff --git a/website/src/pages/terraform-provider.jsx b/website/src/pages/terraform-provider.jsx deleted file mode 100644 index e930a8a564..0000000000 --- a/website/src/pages/terraform-provider.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import Head from "@docusaurus/Head"; -import BrowserOnly from "@docusaurus/BrowserOnly"; - -function TerraformProviderPage() { - return ( - - - - - - {() => { - window.location.assign( - "https://registry.terraform.io/providers/goauthentik/authentik/latest/docs", - ); - }} - - - ); -} -export default TerraformProviderPage; diff --git a/website/src/theme/BlogPostPage/index.js b/website/src/theme/BlogPostPage/index.js deleted file mode 100644 index e232b0d925..0000000000 --- a/website/src/theme/BlogPostPage/index.js +++ /dev/null @@ -1,76 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import { - HtmlClassNameProvider, - ThemeClassNames, -} from "@docusaurus/theme-common"; -import { - BlogPostProvider, - useBlogPost, -} from "@docusaurus/theme-common/internal"; -import BlogLayout from "@theme/BlogLayout"; -import BlogPostItem from "@theme/BlogPostItem"; -import BlogPostPaginator from "@theme/BlogPostPaginator"; -import BlogPostPageMetadata from "@theme/BlogPostPage/Metadata"; -import TOC from "@theme/TOC"; -import { DiscussionEmbed } from "disqus-react"; - -function BlogPostPageContent({ sidebar, children }) { - const { metadata, toc } = useBlogPost(); - const { nextItem, prevItem, frontMatter } = metadata; - const { - hide_table_of_contents: hideTableOfContents, - toc_min_heading_level: tocMinHeadingLevel, - toc_max_heading_level: tocMaxHeadingLevel, - } = frontMatter; - return ( - 0 ? ( - - ) : undefined - } - > - {children} - - {(nextItem || prevItem) && ( - - )} - - ); -} -export default function BlogPostPage(props) { - const BlogPostContent = props.content; - const title = props.content.frontMatter.title.substring(0, 200); - const fmtId = title.replace(/^\//, "").replaceAll(/[\s\/]/gi, "-"); - const disqusId = fmtId == "" ? "main" : fmtId; - return ( - - - - - - - - - - - ); -} diff --git a/website/static/img/landing_login_card.png b/website/static/img/landing_login_card.png deleted file mode 100644 index b070b60744..0000000000 Binary files a/website/static/img/landing_login_card.png and /dev/null differ diff --git a/website/static/img/landing_screen_admin_dark.jpg b/website/static/img/landing_screen_admin_dark.jpg deleted file mode 100644 index f0b8099834..0000000000 Binary files a/website/static/img/landing_screen_admin_dark.jpg and /dev/null differ diff --git a/website/static/img/landing_screen_admin_light.jpg b/website/static/img/landing_screen_admin_light.jpg deleted file mode 100644 index 209d000697..0000000000 Binary files a/website/static/img/landing_screen_admin_light.jpg and /dev/null differ diff --git a/website/static/img/landing_screen_apps_dark.jpg b/website/static/img/landing_screen_apps_dark.jpg deleted file mode 100644 index 86715724af..0000000000 Binary files a/website/static/img/landing_screen_apps_dark.jpg and /dev/null differ diff --git a/website/static/img/landing_screen_apps_light.jpg b/website/static/img/landing_screen_apps_light.jpg deleted file mode 100644 index a2fe6feba5..0000000000 Binary files a/website/static/img/landing_screen_apps_light.jpg and /dev/null differ diff --git a/website/static/img/screen_admin_dark.jpg b/website/static/img/screen_admin_dark.jpg index 1b047b2a0e..def47e174c 100644 Binary files a/website/static/img/screen_admin_dark.jpg and b/website/static/img/screen_admin_dark.jpg differ diff --git a/website/static/img/screen_admin_light.jpg b/website/static/img/screen_admin_light.jpg index 472502b520..e7a51abeb4 100644 Binary files a/website/static/img/screen_admin_light.jpg and b/website/static/img/screen_admin_light.jpg differ diff --git a/website/static/img/screen_apps_dark.jpg b/website/static/img/screen_apps_dark.jpg index 9f7569860d..c6d59dd188 100644 Binary files a/website/static/img/screen_apps_dark.jpg and b/website/static/img/screen_apps_dark.jpg differ diff --git a/website/static/img/screen_apps_light.jpg b/website/static/img/screen_apps_light.jpg index dfa28df848..325e5660fe 100644 Binary files a/website/static/img/screen_apps_light.jpg and b/website/static/img/screen_apps_light.jpg differ diff --git a/website/static/img/screen_flow_dark.jpg b/website/static/img/screen_flow_dark.jpg index e1a4085a50..c38ed2ebe1 100644 Binary files a/website/static/img/screen_flow_dark.jpg and b/website/static/img/screen_flow_dark.jpg differ diff --git a/website/static/img/screen_flow_light.jpg b/website/static/img/screen_flow_light.jpg index 451f56e931..42b98a95cd 100644 Binary files a/website/static/img/screen_flow_light.jpg and b/website/static/img/screen_flow_light.jpg differ