pulp-python 3.31.2__py3-none-any.whl → 3.32.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ class PulpPythonPluginAppConfig(PulpPluginAppConfig):
12
12
 
13
13
  name = "pulp_python.app"
14
14
  label = "python"
15
- version = "3.31.2"
15
+ version = "3.32.1"
16
16
  python_package_name = "pulp-python"
17
17
  domain_compatible = True
18
18
 
@@ -0,0 +1,33 @@
1
+ from pulpcore.plugin.cache import CacheKeys, SyncContentCache
2
+ from pulpcore.plugin.util import cache_key
3
+
4
+ MEDIA_TYPE_KEY = "media_type"
5
+
6
+
7
+ class PythonApiCache(SyncContentCache):
8
+ """
9
+ Cache for the Simple API.
10
+
11
+ Keys on the negotiated media type so HTML and JSON are cached separately,
12
+ including when the same Accept header is used with `?format=json`.
13
+ """
14
+
15
+ def __init__(self, base_key=None):
16
+ keys = (CacheKeys.path, CacheKeys.method, MEDIA_TYPE_KEY)
17
+ super().__init__(base_key=base_key, keys=keys)
18
+
19
+ def make_key(self, request):
20
+ all_keys = {
21
+ CacheKeys.path: request.path,
22
+ CacheKeys.method: request.method,
23
+ MEDIA_TYPE_KEY: getattr(request, "accepted_media_type", "") or "",
24
+ }
25
+ return ":".join(all_keys[k] for k in self.keys)
26
+
27
+
28
+ def find_base_path_cached(request, cached):
29
+ """
30
+ Resolve the distribution base_path for use as the Redis cache base_key.
31
+ """
32
+ path = request.resolver_match.kwargs["path"]
33
+ return cache_key(path)
@@ -1,3 +1,4 @@
1
+ import hashlib
1
2
  import logging
2
3
  from datetime import datetime, timedelta, timezone
3
4
  from itertools import chain
@@ -15,9 +16,11 @@ from django.http.response import (
15
16
  HttpResponseBadRequest,
16
17
  HttpResponseForbidden,
17
18
  HttpResponseNotFound,
18
- StreamingHttpResponse,
19
19
  )
20
20
  from django.shortcuts import redirect
21
+ from django.utils.decorators import method_decorator
22
+ from django.views.decorators.cache import cache_control
23
+ from django.views.decorators.http import condition
21
24
  from drf_spectacular.utils import extend_schema
22
25
  from dynaconf import settings
23
26
  from packaging.utils import canonicalize_name
@@ -31,6 +34,7 @@ from pulpcore.plugin.util import get_domain, get_url
31
34
  from pulpcore.plugin.viewsets import OperationPostponedResponse
32
35
 
33
36
  from pulp_python.app import tasks
37
+ from pulp_python.app.cache import PythonApiCache, find_base_path_cached
34
38
  from pulp_python.app.models import (
35
39
  PackageProvenance,
36
40
  PythonDistribution,
@@ -65,6 +69,17 @@ PYPI_SIMPLE_V1_HTML = "application/vnd.pypi.simple.v1+html"
65
69
  PYPI_SIMPLE_V1_JSON = "application/vnd.pypi.simple.v1+json"
66
70
 
67
71
 
72
+ def _etag_func(request, path, **kwargs):
73
+ """Compute unquoted ETag for the condition decorator. Returns None if no repo."""
74
+ try:
75
+ distro = PyPIMixin.get_distribution(path)
76
+ repo_ver = PyPIMixin.get_repository_version(distro)
77
+ except Http404:
78
+ return None
79
+ raw = f"{repo_ver.number}:{repo_ver.pulp_created.isoformat()}"
80
+ return hashlib.sha256(raw.encode()).hexdigest()[:16]
81
+
82
+
68
83
  class PyPISimpleHTMLRenderer(TemplateHTMLRenderer):
69
84
  media_type = PYPI_SIMPLE_V1_HTML
70
85
 
@@ -298,6 +313,9 @@ class SimpleView(PackageUploadMixin, ViewSet):
298
313
  )
299
314
 
300
315
  @extend_schema(summary="Get index simple page")
316
+ @method_decorator(cache_control(max_age=600, public=True))
317
+ @method_decorator(condition(etag_func=_etag_func))
318
+ @PythonApiCache(base_key=find_base_path_cached)
301
319
  def list(self, request, path):
302
320
  """Gets the simple api html page for the index."""
303
321
  repo_version, content = self.get_rvc()
@@ -316,9 +334,9 @@ class SimpleView(PackageUploadMixin, ViewSet):
316
334
  index_data = write_simple_index_json(names)
317
335
  return Response(index_data, headers=headers)
318
336
  else:
319
- index_data = write_simple_index(names, streamed=True)
337
+ index_data = write_simple_index(names)
320
338
  kwargs = {"content_type": media_type, "headers": headers}
321
- return StreamingHttpResponse(index_data, **kwargs)
339
+ return HttpResponse(index_data, **kwargs)
322
340
 
323
341
  def pull_through_package_simple(self, package, path, remote):
324
342
  """Gets the package's simple page from remote."""
@@ -355,6 +373,9 @@ class SimpleView(PackageUploadMixin, ViewSet):
355
373
  }
356
374
 
357
375
  @extend_schema(operation_id="pypi_simple_package_read", summary="Get package simple page")
376
+ @method_decorator(cache_control(max_age=600, public=True))
377
+ @method_decorator(condition(etag_func=_etag_func))
378
+ @PythonApiCache(base_key=find_base_path_cached)
358
379
  def retrieve(self, request, path, package):
359
380
  """Retrieves the simple api html/json page for a package."""
360
381
  repo_ver, content = self.get_rvc()
@@ -7,11 +7,8 @@ from pulpcore.tests.functional.utils import BindingsNamespace
7
7
 
8
8
  from pulp_python.tests.functional.constants import (
9
9
  PYTHON_EGG_FILENAME,
10
- PYTHON_EGG_URL,
11
10
  PYTHON_FIXTURE_URL,
12
11
  PYTHON_URL,
13
- PYTHON_WHEEL_FILENAME,
14
- PYTHON_WHEEL_URL,
15
12
  PYTHON_XS_PROJECT_SPECIFIER,
16
13
  )
17
14
 
@@ -239,12 +236,17 @@ def get_href(item):
239
236
 
240
237
  @pytest.fixture(scope="session")
241
238
  def python_package_dist_directory(tmp_path_factory, http_get):
242
- """Creates a temp dir to hold package distros for uploading."""
243
- dist_dir = tmp_path_factory.mktemp("dist")
244
- egg_file = dist_dir / PYTHON_EGG_FILENAME
245
- wheel_file = dist_dir / PYTHON_WHEEL_FILENAME
246
- with open(egg_file, "wb") as f:
247
- f.write(http_get(PYTHON_EGG_URL))
248
- with open(wheel_file, "wb") as f:
249
- f.write(http_get(PYTHON_WHEEL_URL))
250
- yield dist_dir, egg_file, wheel_file
239
+ """Returns a factory that downloads packages into a temp directory."""
240
+
241
+ def _download(*urls):
242
+ dist_dir = tmp_path_factory.mktemp("dist")
243
+ paths = []
244
+ for url in urls:
245
+ filename = url.rsplit("/", 1)[-1]
246
+ path = dist_dir / filename
247
+ with open(path, "wb") as f:
248
+ f.write(http_get(url))
249
+ paths.append(path)
250
+ return (dist_dir, *paths)
251
+
252
+ return _download
@@ -1,7 +1,5 @@
1
1
  import json
2
- import shutil
3
2
  import subprocess
4
- from pathlib import Path
5
3
  from urllib.parse import urljoin
6
4
 
7
5
  import pytest
@@ -10,6 +8,8 @@ from pypi_simple import PyPISimple
10
8
 
11
9
  from pulpcore.tests.functional.utils import PulpTaskError
12
10
 
11
+ from pulp_python.tests.functional.constants import PYTHON_FIXTURES_URL
12
+
13
13
 
14
14
  @pytest.fixture(scope="session")
15
15
  def twine_package():
@@ -207,24 +207,22 @@ def test_attestation_twine_upload(
207
207
  python_content_summary,
208
208
  python_empty_repo_distro,
209
209
  python_package_dist_directory,
210
+ http_get,
210
211
  monitor_task,
211
212
  ):
212
213
  """Tests that packages with attestations can be properly uploaded through Twine."""
214
+ packages_url = urljoin(PYTHON_FIXTURES_URL, "packages/")
215
+ filenames = ("twine-6.2.0.tar.gz", "twine-6.2.0-py3-none-any.whl")
216
+ dist_dir = python_package_dist_directory(*(urljoin(packages_url, f) for f in filenames))[0]
217
+
218
+ for filename in filenames:
219
+ provenance = json.loads(http_get(urljoin(packages_url, f"{filename}.provenance.json")))
220
+ attestation = provenance["attestation_bundles"][0]["attestations"][0]
221
+ with open(dist_dir / f"{filename}.publish.attestation", "w") as f:
222
+ json.dump(attestation, f)
223
+
213
224
  repo, distro = python_empty_repo_distro()
214
225
  url = urljoin(distro.base_url, "legacy/")
215
- dist_dir, _, _ = python_package_dist_directory
216
-
217
- # Copy attestation files from test assets to dist_dir
218
- assets_dir = Path(__file__).parent.parent / "assets"
219
- attestation_files = [
220
- "shelf-reader-0.1.tar.gz.publish.attestation",
221
- "shelf_reader-0.1-py2-none-any.whl.publish.attestation",
222
- ]
223
- for attestation_file in attestation_files:
224
- src = assets_dir / attestation_file
225
- dst = dist_dir / attestation_file
226
- shutil.copy2(src, dst)
227
-
228
226
  username, password = "admin", "password"
229
227
  subprocess.run(
230
228
  (
@@ -245,7 +243,7 @@ def test_attestation_twine_upload(
245
243
  tasks = pulpcore_bindings.TasksApi.list(reserved_resources=repo.pulp_href).results
246
244
  for task in reversed(tasks):
247
245
  t = monitor_task(task.pulp_href)
248
- repo_ver_href = t.created_resources[0]
246
+ repo_ver_href = [r for r in t.created_resources if "versions" in r][0]
249
247
 
250
248
  assert repo_ver_href.endswith("versions/2/")
251
249
  summary = python_content_summary(repository_version=repo_ver_href)
@@ -11,10 +11,13 @@ from pulp_python.tests.functional.constants import (
11
11
  PYPI_SIMPLE_V1_JSON,
12
12
  PYTHON_EGG_FILENAME,
13
13
  PYTHON_EGG_SHA256,
14
+ PYTHON_EGG_URL,
15
+ PYTHON_FIXTURES_URL,
14
16
  PYTHON_MD_PROJECT_SPECIFIER,
15
17
  PYTHON_MD_PYPI_SUMMARY,
16
18
  PYTHON_WHEEL_FILENAME,
17
19
  PYTHON_WHEEL_SHA256,
20
+ PYTHON_WHEEL_URL,
18
21
  SHELF_PYTHON_JSON,
19
22
  TWINE_WHEEL_FILENAME,
20
23
  TWINE_WHEEL_URL,
@@ -70,7 +73,7 @@ def test_package_upload(
70
73
  ):
71
74
  """Tests that packages can be uploaded."""
72
75
  repo, distro = python_empty_repo_distro()
73
- dist_dir, egg_file, wheel_file = python_package_dist_directory
76
+ dist_dir, egg_file, wheel_file = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
74
77
  url = urljoin(distro.base_url, "legacy/")
75
78
  response = requests.post(
76
79
  url,
@@ -100,7 +103,7 @@ def test_package_upload_session(
100
103
  """Tests that multiple uploads will be broken up into multiple tasks."""
101
104
  repo, distro = python_empty_repo_distro()
102
105
  url = urljoin(distro.base_url, "legacy/")
103
- dist_dir, egg_file, wheel_file = python_package_dist_directory
106
+ dist_dir, egg_file, wheel_file = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
104
107
  session = requests.Session()
105
108
  response = session.post(
106
109
  url,
@@ -130,7 +133,7 @@ def test_package_upload_simple(
130
133
  """Tests that the package upload endpoint exposed at `/simple/` works."""
131
134
  repo, distro = python_empty_repo_distro()
132
135
  url = urljoin(distro.base_url, "simple/")
133
- dist_dir, egg_file, wheel_file = python_package_dist_directory
136
+ dist_dir, egg_file, wheel_file = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
134
137
  response = requests.post(
135
138
  url,
136
139
  data={"sha256_digest": PYTHON_EGG_SHA256},
@@ -156,7 +159,7 @@ def test_package_upload_with_metadata(
156
159
  """
157
160
  repo, distro = python_empty_repo_distro()
158
161
  url = urljoin(distro.base_url, "simple/")
159
- dist_dir, egg_file, wheel_file = python_package_dist_directory
162
+ dist_dir, egg_file, wheel_file = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
160
163
  response = requests.post(
161
164
  url,
162
165
  data={"sha256_digest": PYTHON_WHEEL_SHA256},
@@ -183,9 +186,14 @@ def test_twine_upload(
183
186
  monitor_task,
184
187
  ):
185
188
  """Tests that packages can be properly uploaded through Twine."""
189
+ packages_url = urljoin(PYTHON_FIXTURES_URL, "packages/")
190
+ dist_dir, _, _ = python_package_dist_directory(
191
+ urljoin(packages_url, "pytz-2023.3.tar.gz"),
192
+ urljoin(packages_url, "pytz-2023.3-py2.py3-none-any.whl"),
193
+ )
194
+
186
195
  repo, distro = python_empty_repo_distro()
187
196
  url = urljoin(distro.base_url, "legacy/")
188
- dist_dir, _, _ = python_package_dist_directory
189
197
  username, password = "admin", "password"
190
198
  subprocess.run(
191
199
  (
@@ -205,7 +213,7 @@ def test_twine_upload(
205
213
  tasks = pulpcore_bindings.TasksApi.list(reserved_resources=repo.pulp_href).results
206
214
  for task in reversed(tasks):
207
215
  t = monitor_task(task.pulp_href)
208
- repo_ver_href = t.created_resources[-1]
216
+ repo_ver_href = [r for r in t.created_resources if "versions" in r][0]
209
217
  summary = python_content_summary(repository_version=repo_ver_href)
210
218
  assert summary.present["python.python"]["count"] == 2
211
219
 
@@ -245,8 +253,9 @@ def test_simple_redirect_with_publications(
245
253
  assert response.url == str(urljoin(pulp_content_url, f"{distro.base_path}/simple/"))
246
254
 
247
255
 
248
- @pytest.mark.parallel
249
- def test_pypi_json(python_remote_factory, python_repo_with_sync, python_distribution_factory):
256
+ def test_pypi_json(
257
+ delete_orphans_pre, python_remote_factory, python_repo_with_sync, python_distribution_factory
258
+ ):
250
259
  """Checks the data of `pypi/{package_name}/json` endpoint."""
251
260
  remote = python_remote_factory(policy="immediate")
252
261
  repo = python_repo_with_sync(remote)
@@ -260,8 +269,8 @@ def test_pypi_json(python_remote_factory, python_repo_with_sync, python_distribu
260
269
  assert_pypi_json(response.json())
261
270
 
262
271
 
263
- @pytest.mark.parallel
264
272
  def test_pypi_json_content_app(
273
+ delete_orphans_pre,
265
274
  python_remote_factory,
266
275
  python_repo_with_sync,
267
276
  python_publication_factory,
@@ -0,0 +1,141 @@
1
+ from urllib.parse import urljoin
2
+
3
+ import pytest
4
+ import requests
5
+
6
+ from pulp_python.tests.functional.constants import (
7
+ PYPI_SIMPLE_V1_HTML,
8
+ PYPI_SIMPLE_V1_JSON,
9
+ PYPI_TEXT_HTML,
10
+ PYTHON_SM_PROJECT_SPECIFIER,
11
+ )
12
+
13
+
14
+ @pytest.fixture
15
+ def skip_without_cache(pulp_settings):
16
+ """
17
+ Skip test if server-side caching is not enabled.
18
+ """
19
+ if not pulp_settings.CACHE_ENABLED:
20
+ pytest.skip("CACHE_ENABLED is not set")
21
+
22
+
23
+ @pytest.fixture
24
+ def synced_distro(
25
+ skip_without_cache,
26
+ python_remote_factory,
27
+ python_repo_with_sync,
28
+ python_distribution_factory,
29
+ ):
30
+ """
31
+ Sync a repo and create a distribution for cache tests.
32
+ """
33
+ remote = python_remote_factory(includes=PYTHON_SM_PROJECT_SPECIFIER)
34
+ repo = python_repo_with_sync(remote)
35
+ return python_distribution_factory(repository=repo)
36
+
37
+
38
+ @pytest.mark.parallel
39
+ def test_simple_cache_hit_miss_and_headers(synced_distro):
40
+ """
41
+ First request is a MISS, second is a HIT. Cache headers are present and stable.
42
+ """
43
+ index_url = urljoin(synced_distro.base_url, "simple/")
44
+ detail_url = f"{index_url}aiohttp"
45
+
46
+ for url in [index_url, detail_url]:
47
+ r1 = requests.get(url)
48
+ assert r1.status_code == 200
49
+ assert r1.headers["X-PULP-CACHE"] == "MISS"
50
+ assert r1.headers["Cache-Control"] == "max-age=600, public"
51
+ assert r1.headers["ETag"].startswith('"') and r1.headers["ETag"].endswith('"')
52
+
53
+ r2 = requests.get(url)
54
+ assert r2.status_code == 200
55
+ assert r2.headers["X-PULP-CACHE"] == "HIT"
56
+ assert r2.headers["Cache-Control"] == r1.headers["Cache-Control"]
57
+ assert r2.headers["ETag"] == r1.headers["ETag"]
58
+
59
+
60
+ @pytest.mark.parallel
61
+ def test_simple_cache_separate_accept_headers(synced_distro):
62
+ """
63
+ HTML and JSON responses are cached separately by negotiated media type.
64
+ """
65
+ url = urljoin(synced_distro.base_url, "simple/")
66
+
67
+ for header in [PYPI_SIMPLE_V1_HTML, PYPI_SIMPLE_V1_JSON]:
68
+ r = requests.get(url, headers={"Accept": header})
69
+ assert r.status_code == 200
70
+ assert r.headers["X-PULP-CACHE"] == "MISS"
71
+
72
+ for header in [PYPI_SIMPLE_V1_HTML, PYPI_SIMPLE_V1_JSON]:
73
+ r = requests.get(url, headers={"Accept": header})
74
+ assert r.status_code == 200
75
+ assert r.headers["X-PULP-CACHE"] == "HIT"
76
+
77
+
78
+ @pytest.mark.parallel
79
+ def test_simple_cache_format_json_does_not_poison_html(synced_distro):
80
+ """
81
+ A ?format=json response must not poison a later request with the same Accept.
82
+
83
+ Clients like uv/pip send an Accept that allows both JSON and HTML. DRF's
84
+ ?format=json overrides negotiation to JSON, while the same Accept without
85
+ that query param selects HTML. Caching must key on the negotiated type so
86
+ the JSON entry is not served (and re-rendered) for the HTML request.
87
+ """
88
+ url = f"{urljoin(synced_distro.base_url, 'simple/')}aiohttp"
89
+ # pip/uv-style Accept: JSON preferred, HTML still acceptable
90
+ headers = {
91
+ "Accept": (f"{PYPI_SIMPLE_V1_JSON}, {PYPI_SIMPLE_V1_HTML};q=0.1, {PYPI_TEXT_HTML};q=0.01")
92
+ }
93
+
94
+ r_json = requests.get(url, headers=headers, params={"format": "json"})
95
+ assert r_json.status_code == 200
96
+ assert PYPI_SIMPLE_V1_JSON in r_json.headers["Content-Type"]
97
+ assert r_json.headers["X-PULP-CACHE"] == "MISS"
98
+ assert r_json.json()["name"] == "aiohttp"
99
+
100
+ r_html = requests.get(url, headers=headers)
101
+ assert r_html.status_code == 200
102
+ assert PYPI_TEXT_HTML in r_html.headers["Content-Type"]
103
+ assert r_html.headers["X-PULP-CACHE"] == "MISS"
104
+ assert b"<a href=" in r_html.content
105
+
106
+ r_html_hit = requests.get(url, headers=headers)
107
+ assert r_html_hit.status_code == 200
108
+ assert r_html_hit.headers["X-PULP-CACHE"] == "HIT"
109
+ assert PYPI_TEXT_HTML in r_html_hit.headers["Content-Type"]
110
+
111
+ r_json_hit = requests.get(url, headers=headers, params={"format": "json"})
112
+ assert r_json_hit.status_code == 200
113
+ assert r_json_hit.headers["X-PULP-CACHE"] == "HIT"
114
+ assert PYPI_SIMPLE_V1_JSON in r_json_hit.headers["Content-Type"]
115
+
116
+
117
+ @pytest.mark.parallel
118
+ def test_simple_cache_etag_conditional_request(synced_distro):
119
+ """
120
+ Matching If-None-Match returns 304, non-matching returns 200.
121
+ """
122
+ url = urljoin(synced_distro.base_url, "simple/")
123
+
124
+ r1 = requests.get(url)
125
+ assert r1.status_code == 200
126
+ etag = r1.headers["ETag"]
127
+ cache_control = r1.headers["Cache-Control"]
128
+
129
+ r2 = requests.get(url, headers={"If-None-Match": etag})
130
+ assert r2.status_code == 304
131
+ assert r2.headers["ETag"] == etag
132
+ assert r2.headers["Cache-Control"] == cache_control
133
+ assert "X-PULP-CACHE" not in r2.headers
134
+ assert len(r2.content) == 0
135
+
136
+ r3 = requests.get(url, headers={"If-None-Match": '"old"'})
137
+ assert r3.status_code == 200
138
+ assert r3.headers["ETag"] == etag
139
+ assert r3.headers["Cache-Control"] == cache_control
140
+ assert r3.headers["X-PULP-CACHE"] == "HIT"
141
+ assert len(r3.content) > 0
@@ -82,7 +82,7 @@ def test_synchronous_package_upload_with_metadata(
82
82
  def test_legacy_upload_invalid_protocol_version(
83
83
  python_empty_repo_distro, python_package_dist_directory
84
84
  ):
85
- _, egg_file, _ = python_package_dist_directory
85
+ _, egg_file, _ = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
86
86
  _, distro = python_empty_repo_distro()
87
87
  url = urljoin(distro.base_url, "legacy/")
88
88
  with open(egg_file, "rb") as f:
@@ -108,7 +108,7 @@ def test_legacy_upload_invalid_protocol_version(
108
108
 
109
109
  @pytest.mark.parallel
110
110
  def test_legacy_upload_invalid_filetype(python_empty_repo_distro, python_package_dist_directory):
111
- _, egg_file, wheel_file = python_package_dist_directory
111
+ _, egg_file, wheel_file = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
112
112
  _, distro = python_empty_repo_distro()
113
113
  url = urljoin(distro.base_url, "legacy/")
114
114
  with open(egg_file, "rb") as f:
@@ -140,7 +140,7 @@ def test_legacy_upload_invalid_filetype(python_empty_repo_distro, python_package
140
140
  def test_legacy_upload_invalid_metadata_version(
141
141
  python_empty_repo_distro, python_package_dist_directory
142
142
  ):
143
- _, egg_file, _ = python_package_dist_directory
143
+ _, egg_file, _ = python_package_dist_directory(PYTHON_EGG_URL, PYTHON_WHEEL_URL)
144
144
  _, distro = python_empty_repo_distro()
145
145
  url = urljoin(distro.base_url, "legacy/")
146
146
  with open(egg_file, "rb") as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulp-python
3
- Version: 3.31.2
3
+ Version: 3.32.1
4
4
  Summary: pulp-python plugin for the Pulp Project
5
5
  Author-email: Pulp Team <pulp-list@redhat.com>
6
6
  Project-URL: Homepage, https://pulpproject.org
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: >=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: pulpcore<3.115,>=3.105.0
23
+ Requires-Dist: pulpcore<3.130,>=3.105.0
24
24
  Requires-Dist: pkginfo<1.13.0,>=1.12.0
25
25
  Requires-Dist: bandersnatch<6.7,>=6.6.0
26
26
  Requires-Dist: pypi-simple<2.0,>=1.8.0
@@ -1,6 +1,7 @@
1
1
  pulp_python/__init__.py,sha256=GIuTLoBTc-07dSLJUh8xrZPRz8x-jJ61pfR0J1IjnzI,65
2
- pulp_python/pytest_plugin.py,sha256=LNnLjOkeEu2X4gJi614bHVmbsHyEwooHYIeecr96Qy4,8606
3
- pulp_python/app/__init__.py,sha256=Sxuni7NCBKiQ9nYqBToQB56-Q_DWCCPnQoqqzDiM1KU,2490
2
+ pulp_python/pytest_plugin.py,sha256=8Ko-O87JGPC79h8-Ecw2gJLxa6q1Ng8wD6WxbinOnVs,8573
3
+ pulp_python/app/__init__.py,sha256=iwdj2oF4-hKr7-1-FR2-qyjZQjEL5ZTRgv-cKfDFsjs,2490
4
+ pulp_python/app/cache.py,sha256=Zl2nb4uKyPYp5a3FBrdRZ_-cXfofNMQmIRaQ6dUZZ1g,1037
4
5
  pulp_python/app/exceptions.py,sha256=mPNcWyuzF0XeOPybm-G6oDKtRqvfj4jyp41iaYqcqkA,1314
5
6
  pulp_python/app/global_access_conditions.py,sha256=MZJtyoVsr-4hRaty6mKDqh3caOHd5UKJjEWLV2crOLs,1080
6
7
  pulp_python/app/modelresource.py,sha256=4SFAdqk6lozi_cZz4uqDIqhqPAZF-7l5jJwPn-xGZFs,1249
@@ -41,7 +42,7 @@ pulp_python/app/migrations/0022_pythonblocklistentry.py,sha256=EbtjZuN65myTAHVWr
41
42
  pulp_python/app/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
43
  pulp_python/app/pypi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
44
  pulp_python/app/pypi/serializers.py,sha256=rE0Cci2IMg4NbNWlVdo-8zPaJCAUq2Re57q_T3jMt0Y,5030
44
- pulp_python/app/pypi/views.py,sha256=F55Zp4GPAQDVk936Szu2ECge8p1-5A160iqzrMDTZGc,21668
45
+ pulp_python/app/pypi/views.py,sha256=guGJeH9D4HZ5cG4YaByjwIr-1CrC2ziD7YkM_gPgH_U,22616
45
46
  pulp_python/app/tasks/__init__.py,sha256=lTFpVvpDKbqv9RC0b2RYU8Bo6svDjrA-djt16pADFr8,284
46
47
  pulp_python/app/tasks/publish.py,sha256=bjsJzqJbLu7TF5rLb-UsZMmlNnc_LKw-sdHX9Gcatbw,4334
47
48
  pulp_python/app/tasks/repair.py,sha256=5InzdbjW8y3AC4Vj2PsNLm3wGGTr8D3LcfPw_WA2Fks,12257
@@ -56,7 +57,7 @@ pulp_python/tests/functional/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
56
57
  pulp_python/tests/functional/constants.py,sha256=4e_zssE9G1bSNNJxYo7VgwvojUL_NocG5mUH996KBJs,13969
57
58
  pulp_python/tests/functional/utils.py,sha256=GWnXrsQGZd0Ngewa_9yce58Qc3z7FbrlRvqao_8ZML0,5901
58
59
  pulp_python/tests/functional/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- pulp_python/tests/functional/api/test_attestations.py,sha256=tvRSsHyQVkoAp-Myoo_Y_7gz-HyNR8EA8G1yvik3dEg,10358
60
+ pulp_python/tests/functional/api/test_attestations.py,sha256=7tXJY4b48ww8Sdc37VoGwXppUb69TxyXA0gfPHb6DCQ,10501
60
61
  pulp_python/tests/functional/api/test_auto_publish.py,sha256=uCIt4LsO61oMk3bDs3LMQDJI8zkKqvY0b1uX16bTxzM,1747
61
62
  pulp_python/tests/functional/api/test_blocklist.py,sha256=IWzlazoQbrfyHNq9bNAa9FcbShWqzC2Zhq8qrN7HBwg,5994
62
63
  pulp_python/tests/functional/api/test_consume_content.py,sha256=-7b6KOrIT3NLSUafeu1tzXEXRPddDbS5VeMHxMIy2n8,999
@@ -67,20 +68,19 @@ pulp_python/tests/functional/api/test_domains.py,sha256=uEA7dIBXaXah3WQ6g6xSIjdX
67
68
  pulp_python/tests/functional/api/test_download_content.py,sha256=5IuaHXyLakPkjm5sLTxtTl7Dq0yl7N36HpObnIa0Sks,4950
68
69
  pulp_python/tests/functional/api/test_export_import.py,sha256=rHns9wdaeP-vtfW_qoGHU9EVuJ4YuWE0-rjl_8otAgU,4530
69
70
  pulp_python/tests/functional/api/test_full_mirror.py,sha256=eU5HzgBBFOnX1q4m8ELx-t-I3U4TWXL-LNrlc2BcWVc,12045
70
- pulp_python/tests/functional/api/test_pypi_apis.py,sha256=mhST0GV-uDrVPsBWYRGaJx1pp9htzbYiUGuIGOI0s_s,13218
71
+ pulp_python/tests/functional/api/test_pypi_apis.py,sha256=iZnoSN2wCczXh14KJDH8pSDTygjs0kgZsYIcIYS5TP8,13647
71
72
  pulp_python/tests/functional/api/test_pypi_simple_api.py,sha256=tOUl8WXgJkMoxGyLbA-WorCxIRKfGWM-27_dK_Jc0Q4,7171
72
73
  pulp_python/tests/functional/api/test_rbac.py,sha256=-xNWqvKKU-v1uC6tCRGBK0aWaff25K9C-AfzQkdHhhI,10513
73
74
  pulp_python/tests/functional/api/test_repair.py,sha256=4FR7jx_LA2K-pnRJXKkhq-1uUoWXST1leZ9XdyhGM2U,12909
75
+ pulp_python/tests/functional/api/test_simple_cache.py,sha256=kJ9mwJKf9A-RthLzPZi0rjRQlygEkWsV6jAaAR8aYgc,4944
74
76
  pulp_python/tests/functional/api/test_sync.py,sha256=TTHR1CpZeRoD97RKxj2pZPsP0OS9ibYKGPOh1WfKISg,13801
75
- pulp_python/tests/functional/api/test_upload.py,sha256=PZ0HK7UU9gvxNaRlB_EAY1-pcghDtx22DMGk5C1oM2I,5879
77
+ pulp_python/tests/functional/api/test_upload.py,sha256=f21Li9agJ5fdBqErVg1j6v5FDVdazB5mNClmGOjLUq8,5981
76
78
  pulp_python/tests/functional/api/test_vulnerability_report.py,sha256=Rv492Wrvu1FY7O_moo9DTB6OkI-OZURj_fuTKbENLh8,1730
77
- pulp_python/tests/functional/assets/shelf-reader-0.1.tar.gz.publish.attestation,sha256=_Ygrz7523z55s4uPmQWYxF29jr0NqJxVm_d-Z8KvrZ0,10363
78
- pulp_python/tests/functional/assets/shelf_reader-0.1-py2-none-any.whl.publish.attestation,sha256=muTQ8dqYSSdx76DlaPjB1REcNIS-aak-Na0TkASxu8M,10426
79
79
  pulp_python/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  pulp_python/tests/unit/test_models.py,sha256=TBI0yKsrdbnJSPeBFfxSqhXK7zaNvR6qg5JehGH3Pds,229
81
- pulp_python-3.31.2.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
82
- pulp_python-3.31.2.dist-info/METADATA,sha256=baT0dVyozWQL7UQh3iIuFCMtqGNoEAEf1lAqhq4_F_0,1744
83
- pulp_python-3.31.2.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
84
- pulp_python-3.31.2.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
85
- pulp_python-3.31.2.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
86
- pulp_python-3.31.2.dist-info/RECORD,,
81
+ pulp_python-3.32.1.dist-info/licenses/LICENSE,sha256=2ylvL381vKOhdO-w6zkrOxe9lLNBhRQpo9_0EbHC_HM,18046
82
+ pulp_python-3.32.1.dist-info/METADATA,sha256=L3MSixYuk-rR8Xw7sm3-iXNiVPPx__1IQ_-7mWTBN2o,1744
83
+ pulp_python-3.32.1.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
84
+ pulp_python-3.32.1.dist-info/entry_points.txt,sha256=HvqLEXjw_dS5jqAwnE5JiRZFE6f-y5SRtitKLPml2To,115
85
+ pulp_python-3.32.1.dist-info/top_level.txt,sha256=X0hXgXc_bpbiKqVrkt8jD5_QEiQviKbHDwveQcOcJjo,12
86
+ pulp_python-3.32.1.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- {"version":1,"verification_material":{"certificate":"MIIIMzCCB7igAwIBAgIUKrdo9OfFJy6MuUewIeE/ILWw/tswCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUxMjA0MjAzMjM5WhcNMjUxMjA0MjA0MjM5WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEleubASHneG8xQmJ/HacfPp63RpBRb71lTUW3uqc/dxFttAkIu11LtR5Y1aRa7h/uFP6e9B/3WAV11xiu29vxRqOCBtcwggbTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUcDHutpRx316lThqpRMpz2kw+/f4wHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwgaUGA1UdEQEB/wSBmjCBl4aBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg3OTU4NmMxZGVhZDhiODhmYmZhOWE3ODgyZGExMTZkZWNmNjc0YTQyMC0GCisGAQQBg78wAQQEH0V4dHJlbWVseSBkYW5nZXJvdXMgT0lEQyBiZWFjb24wSQYKKwYBBAGDvzABBQQ7c2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24wHQYKKwYBBAGDvzABBgQPcmVmcy9oZWFkcy9tYWluMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTCBpgYKKwYBBAGDvzABCQSBlwyBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg3OTU4NmMxZGVhZDhiODhmYmZhOWE3ODgyZGExMTZkZWNmNjc0YTQyMB0GCisGAQQBg78wAQsEDwwNZ2l0aHViLWhvc3RlZDBeBgorBgEEAYO/MAEMBFAMTmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbjA4BgorBgEEAYO/MAENBCoMKDc5NTg2YzFkZWFkOGI4OGZiZmE5YTc4ODJkYTExNmRlY2Y2NzRhNDIwHwYKKwYBBAGDvzABDgQRDA9yZWZzL2hlYWRzL21haW4wGQYKKwYBBAGDvzABDwQLDAk2MzI1OTY4OTcwNwYKKwYBBAGDvzABEAQpDCdodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UwGQYKKwYBBAGDvzABEQQLDAkxMzE4MDQ1NjMwgaYGCisGAQQBg78wARIEgZcMgZRodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24vLmdpdGh1Yi93b3JrZmxvd3MvZXh0cmVtZWx5LWRhbmdlcm91cy1vaWRjLWJlYWNvbi55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoNzk1ODZjMWRlYWQ4Yjg4ZmJmYTlhNzg4MmRhMTE2ZGVjZjY3NGE0MjAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMIGCBgorBgEEAYO/MAEVBHQMcmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi9hY3Rpb25zL3J1bnMvMTk5NDMwMzAxOTkvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzCBigYKKwYBBAHWeQIEAgR8BHoAeAB2ACswvNxoiMni4dgmKV50H0g5MZYC8pwzy15DQP6yrIZ6AAABmusRH1wAAAQDAEcwRQIgMjrB10EwMTKAWmjTMab2AX1YMg1lWJp7xV3yhBx7GyYCIQC5zr44ZzUSPnJ3Gtm6k8M1CBoIzDYWzwBIoRAdh5NE3TAKBggqhkjOPQQDAwNpADBmAjEAgyfhSQno+h3UugP0A6V0A8b++q1IV4hYm4dVfi6skZKkEYMFbs0ocMWqWlJg8PaFAjEAt7+HDiWOfa3MxLPnIdzeEPz4kbgXZqKQDMHY5m1ZG976bnJBwttMAbAEXhELfyHl","transparency_entries":[{"logIndex":"51125016","logId":{"keyId":"0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY="},"kindVersion":{"kind":"dsse","version":"0.0.1"},"integratedTime":"1764880360","inclusionPromise":{"signedEntryTimestamp":"MEUCIQC48Y/s6Rv+IoXoftvGOhM3sccchkODD/YqwIKJgwJAiAIgWkva5KEaCl3P78T21oElOTbq9cOxurz//9N9giFPDWw="},"inclusionProof":{"logIndex":"19442604","rootHash":"EdmMTYTkzJL0XRtufY9DMHS2axO0Vg6jO4eVM/Cetd4=","treeSize":"19442605","hashes":["k5UsnMaUY0kOQlFg0Za5deoskYSOUTFQ2Jzl3upcbX0=","F8+CGCoMNj9Jb1Csuk4bxbAWW35iktydoLKPPLk6Hb8=","P6IFMwnZlp99wiunjusnNW+K5V06iOEtzfoD9MtHCSU=","V4//f/ISXnSeJjUckmcLLzwS38XjXwMjrMAw6B3hKfg=","baLnSFGPpXZDhE38YKkGPW9P35RXQTaZlgDJ2i/u5xA=","YPKEUUZB3AVufkBQm5r7wLJeJMECETlxWoHo3+sKnHE=","VEcYk6UKGgyx1fCjyU6cfCPViC8OZFBjvHz8fco4eGM=","tf738kZ3YKyYiskKppTF5etATmFZgyY6H1ktyC0leCA=","gXQKVsGeO2E9oDbviE7+SuHFG5g7UH35dYGHc9JSz8s=","6kC2DcsZfB5F/TmenKHUzDr2UH6XK//Ch6hC8PZWJ5c=","JA9P8Q8v916uA/xomSrsiXeVBiyxxQAD5Mer9MBIYzA=","BrjYsYvo65dTDWKO8aY0s+9WaWHlVdZuOEzsBHLHe8U="],"checkpoint":{"envelope":"rekor.sigstage.dev - 8202293616175992157\n19442605\nEdmMTYTkzJL0XRtufY9DMHS2axO0Vg6jO4eVM/Cetd4=\n\n— rekor.sigstage.dev 0y8wozBFAiAPcLZnrw7rn8sFhxqGjp5q58EtMUibZptS8W1Mk6CcAAIhAJ6c+pCBCCe4+K1+zxuUsofR9Y56J5pTBvqvfGceJI/l\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZW52ZWxvcGVIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiYzJkZjczOTEzMzgyZmVkM2MzNTU5ODRjOTdiN2Y2NTc5YTYxZmVmZDAwOWMxYmM3M2M2ODE0ODk3ZjMxNDY3MyJ9LCJwYXlsb2FkSGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjRkMjdjMTZjMTI3ZDM4ZGE2NDU3MGVmMmY3Mjc2MjIwOWVjMzlkMmU0NjhiYjQ0YTU5NjE1MjhlOTMyNDNjNWQifSwic2lnbmF0dXJlcyI6W3sic2lnbmF0dXJlIjoiTUVZQ0lRQ2hSUGN1N2w5QXBIbTAxNlE3bnpob3pxaHkvYXVBV1NiWWc5MUpxQzluYlFJaEFOdGtFV01hV2RHS0dUZHVNZW4yQ081eDhPY1N0UStyazlnWVFWeDk1YU9VIiwidmVyaWZpZXIiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VsTmVrTkRRamRwWjBGM1NVSkJaMGxWUzNKa2J6bFBaa1pLZVRaTmRWVmxkMGxsUlM5SlRGZDNMM1J6ZDBObldVbExiMXBKZW1vd1JVRjNUWGNLVG5wRlZrMUNUVWRCTVZWRlEyaE5UV015Ykc1ak0xSjJZMjFWZFZwSFZqSk5ValIzU0VGWlJGWlJVVVJGZUZaNllWZGtlbVJIT1hsYVV6RndZbTVTYkFwamJURnNXa2RzYUdSSFZYZElhR05PVFdwVmVFMXFRVEJOYWtGNlRXcE5OVmRvWTA1TmFsVjRUV3BCTUUxcVFUQk5hazAxVjJwQlFVMUdhM2RGZDFsSUNrdHZXa2w2YWpCRFFWRlpTVXR2V2tsNmFqQkVRVkZqUkZGblFVVnNaWFZpUVZOSWJtVkhPSGhSYlVvdlNHRmpabEJ3TmpOU2NFSlNZamN4YkZSVlZ6TUtkWEZqTDJSNFJuUjBRV3RKZFRFeFRIUlNOVmt4WVZKaE4yZ3ZkVVpRTm1VNVFpOHpWMEZXTVRGNGFYVXlPWFo0VW5GUFEwSjBZM2RuWjJKVVRVRTBSd3BCTVZWa1JIZEZRaTkzVVVWQmQwbElaMFJCVkVKblRsWklVMVZGUkVSQlMwSm5aM0pDWjBWR1FsRmpSRUY2UVdSQ1owNVdTRkUwUlVablVWVmpSRWgxQ25Sd1VuZ3pNVFpzVkdoeGNGSk5jSG95YTNjckwyWTBkMGgzV1VSV1VqQnFRa0puZDBadlFWVmpXVmwzY0doU09GbHRMelU1T1dJd1FsSndMMWd2TDNJS1lqWjNkMmRoVlVkQk1WVmtSVkZGUWk5M1UwSnRha05DYkRSaFFteEhhREJrU0VKNlQyazRkbG95YkRCaFNGWnBURzFPZG1KVE9YcGhWMlI2WkVjNWVRcGFVekZxWWpJMWJXSXpTblJaVnpWcVdsTTViR1ZJVW5sYVZ6RnNZa2hyZEZwSFJuVmFNbFo1WWpOV2VreFlRakZaYlhod1dYa3hkbUZYVW1wTVYwcHNDbGxYVG5aaWFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsc1pVaFNlVnBYTVd4aVNHdDBXa2RHZFZveVZubGlNMVo2VEZjNWNGcEhUWFFLV1cxV2FGa3lPWFZNYm14MFlrVkNlVnBYV25wTU1taHNXVmRTZWt3eU1XaGhWelIzVDFGWlMwdDNXVUpDUVVkRWRucEJRa0ZSVVhKaFNGSXdZMGhOTmdwTWVUa3dZakowYkdKcE5XaFpNMUp3WWpJMWVreHRaSEJrUjJneFdXNVdlbHBZU21waU1qVXdXbGMxTUV4dFRuWmlWRUZtUW1kdmNrSm5SVVZCV1U4dkNrMUJSVU5DUWtZellqTktjbHB0ZUhaa01UbHJZVmhPZDFsWVVtcGhSRUV5UW1kdmNrSm5SVVZCV1U4dlRVRkZSRUpEWnpOUFZGVTBUbTFOZUZwSFZtZ0tXa1JvYVU5RWFHMVpiVnBvVDFkRk0wOUVaM2xhUjBWNFRWUmFhMXBYVG0xT2FtTXdXVlJSZVUxRE1FZERhWE5IUVZGUlFtYzNPSGRCVVZGRlNEQldOQXBrU0Vwc1lsZFdjMlZUUW10WlZ6VnVXbGhLZG1SWVRXZFVNR3hGVVhsQ2FWcFhSbXBpTWpSM1UxRlpTMHQzV1VKQ1FVZEVkbnBCUWtKUlVUZGpNbXh1Q21NelVuWmpiVlYwV1RJNWRWcHRPWGxpVjBaMVdUSlZkbHBZYURCamJWWjBXbGQ0TlV4WFVtaGliV1JzWTIwNU1XTjVNWGRrVjBwellWZE5kR0l5YkdzS1dYa3hhVnBYUm1waU1qUjNTRkZaUzB0M1dVSkNRVWRFZG5wQlFrSm5VVkJqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxRWMwZERhWE5IUVZGUlFncG5OemgzUVZGblJVeFJkM0poU0ZJd1kwaE5Oa3g1T1RCaU1uUnNZbWsxYUZrelVuQmlNalY2VEcxa2NHUkhhREZaYmxaNldsaEthbUl5TlRCYVZ6VXdDa3h0VG5aaVZFTkNjR2RaUzB0M1dVSkNRVWRFZG5wQlFrTlJVMEpzZDNsQ2JFZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZtbE1iVTUyWWxNNWVtRlhaSG9LWkVjNWVWcFRNV3BpTWpWdFlqTktkRmxYTldwYVV6bHNaVWhTZVZwWE1XeGlTR3QwV2tkR2RWb3lWbmxpTTFaNlRGaENNVmx0ZUhCWmVURjJZVmRTYWdwTVYwcHNXVmRPZG1KcE9IVmFNbXd3WVVoV2FVd3paSFpqYlhSdFlrYzVNMk41T1d4bFNGSjVXbGN4YkdKSWEzUmFSMFoxV2pKV2VXSXpWbnBNVnpsd0NscEhUWFJaYlZab1dUSTVkVXh1YkhSaVJVSjVXbGRhZWt3eWFHeFpWMUo2VERJeGFHRlhOSGRQUVZsTFMzZFpRa0pCUjBSMmVrRkNRMmRSY1VSRFp6TUtUMVJWTkU1dFRYaGFSMVpvV2tSb2FVOUVhRzFaYlZwb1QxZEZNMDlFWjNsYVIwVjRUVlJhYTFwWFRtMU9hbU13V1ZSUmVVMUNNRWREYVhOSFFWRlJRZ3BuTnpoM1FWRnpSVVIzZDA1YU1td3dZVWhXYVV4WGFIWmpNMUpzV2tSQ1pVSm5iM0pDWjBWRlFWbFBMMDFCUlUxQ1JrRk5WRzFvTUdSSVFucFBhVGgyQ2xveWJEQmhTRlpwVEcxT2RtSlRPWHBoVjJSNlpFYzVlVnBUTVdwaU1qVnRZak5LZEZsWE5XcGFVemxzWlVoU2VWcFhNV3hpU0d0MFdrZEdkVm95Vm5rS1lqTldla3hZUWpGWmJYaHdXWGt4ZG1GWFVtcE1WMHBzV1ZkT2RtSnFRVFJDWjI5eVFtZEZSVUZaVHk5TlFVVk9Ra052VFV0RVl6Vk9WR2N5V1hwR2F3cGFWMFpyVDBkSk5FOUhXbWxhYlVVMVdWUmpORTlFU210WlZFVjRUbTFTYkZreVdUSk9lbEpvVGtSSmQwaDNXVXRMZDFsQ1FrRkhSSFo2UVVKRVoxRlNDa1JCT1hsYVYxcDZUREpvYkZsWFVucE1NakZvWVZjMGQwZFJXVXRMZDFsQ1FrRkhSSFo2UVVKRWQxRk1SRUZyTWsxNlNURlBWRmswVDFSamQwNTNXVXNLUzNkWlFrSkJSMFIyZWtGQ1JVRlJjRVJEWkc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFpqTW14dVl6TlNkbU50VlhSWk1qbDFXbTA1ZVFwaVYwWjFXVEpWZDBkUldVdExkMWxDUWtGSFJIWjZRVUpGVVZGTVJFRnJlRTE2UlRSTlJGRXhUbXBOZDJkaFdVZERhWE5IUVZGUlFtYzNPSGRCVWtsRkNtZGFZMDFuV2xKdlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5XcGlNakIyWXpKc2JtTXpVblpqYlZWMFdUSTVkVnB0T1hsaVYwWjFXVEpWZGxwWWFEQUtZMjFXZEZwWGVEVk1WMUpvWW0xa2JHTnRPVEZqZVRGM1pGZEtjMkZYVFhSaU1teHJXWGt4YVZwWFJtcGlNalIyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbHBZYURCamJWWjBXbGQ0TlV4WFVtaGliV1JzWTIwNU1XTjVNWFpoVjFKcVRGZEtiRmxYVG5aaWFUVTFZbGQ0UVdOdFZtMWplVGx2Q2xwWFJtdGplVGwwV1Zkc2RVMUVaMGREYVhOSFFWRlJRbWMzT0hkQlVrMUZTMmQzYjA1NmF6RlBSRnBxVFZkU2JGbFhVVFJaYW1jMFdtMUtiVmxVYkdnS1RucG5ORTF0VW1oTlZFVXlXa2RXYWxwcVdUTk9SMFV3VFdwQmFFSm5iM0pDWjBWRlFWbFBMMDFCUlZWQ1FrMU5SVmhrZG1OdGRHMWlSemt6V0RKU2NBcGpNMEpvWkVkT2IwMUpSME5DWjI5eVFtZEZSVUZaVHk5TlFVVldRa2hSVFdOdGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hwaFYyUjZDbVJIT1hsYVV6RnFZakkxYldJelNuUlpWelZxV2xNNWJHVklVbmxhVnpGc1lraHJkRnBIUm5WYU1sWjVZak5XZWt4WVFqRlpiWGh3V1hreGRtRlhVbW9LVEZkS2JGbFhUblppYVRsb1dUTlNjR0l5TlhwTU0wb3hZbTVOZGsxVWF6Vk9SRTEzVFhwQmVFOVVhM1paV0ZJd1dsY3hkMlJJVFhaTlZFRlhRbWR2Y2dwQ1owVkZRVmxQTDAxQlJWZENRV2ROUW01Q01WbHRlSEJaZWtOQ2FXZFpTMHQzV1VKQ1FVaFhaVkZKUlVGblVqaENTRzlCWlVGQ01rRkRjM2QyVG5odkNtbE5ibWswWkdkdFMxWTFNRWd3WnpWTldsbERPSEIzZW5reE5VUlJVRFo1Y2tsYU5rRkJRVUp0ZFhOU1NERjNRVUZCVVVSQlJXTjNVbEZKWjAxcWNrSUtNVEJGZDAxVVMwRlhiV3BVVFdGaU1rRllNVmxOWnpGc1YwcHdOM2hXTTNsb1FuZzNSM2xaUTBsUlF6VjZjalEwV25wVlUxQnVTak5IZEcwMmF6aE5NUXBEUW05SmVrUlpWM3AzUWtsdlVrRmthRFZPUlROVVFVdENaMmR4YUd0cVQxQlJVVVJCZDA1d1FVUkNiVUZxUlVGbmVXWm9VMUZ1Ynl0b00xVjFaMUF3Q2tFMlZqQkJPR0lySzNFeFNWWTBhRmx0TkdSV1ptazJjMnRhUzJ0RldVMUdZbk13YjJOTlYzRlhiRXBuT0ZCaFJrRnFSVUYwTnl0SVJHbFhUMlpoTTAwS2VFeFFia2xrZW1WRlVIbzBhMkpuV0ZweFMxRkVUVWhaTlcweFdrYzVOelppYmtwQ2QzUjBUVUZpUVVWWWFFVk1abmxJYkFvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PSJ9XX19"}]},"envelope":{"statement":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoic2hlbGYtcmVhZGVyLTAuMS50YXIuZ3oiLCJkaWdlc3QiOnsic2hhMjU2IjoiMDRjZmQ4YmI0Zjg0M2UzNWQ1MWJmZGVmMjAzNTEwOWJkZWE4MzFiNTVhNTdjM2U2YTE1NGQxNGJlMTE2Mzk4YyJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2RvY3MucHlwaS5vcmcvYXR0ZXN0YXRpb25zL3B1Ymxpc2gvdjEiLCJwcmVkaWNhdGUiOm51bGx9","signature":"MEYCIQChRPcu7l9ApHm016Q7nzhozqhy/auAWSbYg91JqC9nbQIhANtkEWMaWdGKGTduMen2CO5x8OcStQ+rk9gYQVx95aOU"}}
@@ -1 +0,0 @@
1
- {"version":1,"verification_material":{"certificate":"MIIIMzCCB7igAwIBAgIUKrdo9OfFJy6MuUewIeE/ILWw/tswCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUxMjA0MjAzMjM5WhcNMjUxMjA0MjA0MjM5WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEleubASHneG8xQmJ/HacfPp63RpBRb71lTUW3uqc/dxFttAkIu11LtR5Y1aRa7h/uFP6e9B/3WAV11xiu29vxRqOCBtcwggbTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUcDHutpRx316lThqpRMpz2kw+/f4wHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwgaUGA1UdEQEB/wSBmjCBl4aBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg3OTU4NmMxZGVhZDhiODhmYmZhOWE3ODgyZGExMTZkZWNmNjc0YTQyMC0GCisGAQQBg78wAQQEH0V4dHJlbWVseSBkYW5nZXJvdXMgT0lEQyBiZWFjb24wSQYKKwYBBAGDvzABBQQ7c2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24wHQYKKwYBBAGDvzABBgQPcmVmcy9oZWFkcy9tYWluMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTCBpgYKKwYBBAGDvzABCQSBlwyBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg3OTU4NmMxZGVhZDhiODhmYmZhOWE3ODgyZGExMTZkZWNmNjc0YTQyMB0GCisGAQQBg78wAQsEDwwNZ2l0aHViLWhvc3RlZDBeBgorBgEEAYO/MAEMBFAMTmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbjA4BgorBgEEAYO/MAENBCoMKDc5NTg2YzFkZWFkOGI4OGZiZmE5YTc4ODJkYTExNmRlY2Y2NzRhNDIwHwYKKwYBBAGDvzABDgQRDA9yZWZzL2hlYWRzL21haW4wGQYKKwYBBAGDvzABDwQLDAk2MzI1OTY4OTcwNwYKKwYBBAGDvzABEAQpDCdodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UwGQYKKwYBBAGDvzABEQQLDAkxMzE4MDQ1NjMwgaYGCisGAQQBg78wARIEgZcMgZRodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24vLmdpdGh1Yi93b3JrZmxvd3MvZXh0cmVtZWx5LWRhbmdlcm91cy1vaWRjLWJlYWNvbi55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoNzk1ODZjMWRlYWQ4Yjg4ZmJmYTlhNzg4MmRhMTE2ZGVjZjY3NGE0MjAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMIGCBgorBgEEAYO/MAEVBHQMcmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi9hY3Rpb25zL3J1bnMvMTk5NDMwMzAxOTkvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzCBigYKKwYBBAHWeQIEAgR8BHoAeAB2ACswvNxoiMni4dgmKV50H0g5MZYC8pwzy15DQP6yrIZ6AAABmusRH1wAAAQDAEcwRQIgMjrB10EwMTKAWmjTMab2AX1YMg1lWJp7xV3yhBx7GyYCIQC5zr44ZzUSPnJ3Gtm6k8M1CBoIzDYWzwBIoRAdh5NE3TAKBggqhkjOPQQDAwNpADBmAjEAgyfhSQno+h3UugP0A6V0A8b++q1IV4hYm4dVfi6skZKkEYMFbs0ocMWqWlJg8PaFAjEAt7+HDiWOfa3MxLPnIdzeEPz4kbgXZqKQDMHY5m1ZG976bnJBwttMAbAEXhELfyHl","transparency_entries":[{"logIndex":"51125015","logId":{"keyId":"0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY="},"kindVersion":{"kind":"dsse","version":"0.0.1"},"integratedTime":"1764880359","inclusionPromise":{"signedEntryTimestamp":"MEUCIQCiibbwwQHoLxvH9C1/P8Lve6IUoBU/6Rcs1ShGqGoyqQIgBngTOdjZiPEaBMzkNTGRDkGKDAO8FVlClua3dB+VczU="},"inclusionProof":{"logIndex":"19442603","rootHash":"WveYvRUsyPpMgj5BTpatQytFwmxXNIAtg3r3T0Erwzc=","treeSize":"19442604","hashes":["u9GSDHFTk49/HwIcxCnZ46wrLt8BhbE4ghHA15/zujs=","4+9oEq/UTGK6dNePTKcKp7D/uIuzi/1MCP3/QyYOtWg=","F8+CGCoMNj9Jb1Csuk4bxbAWW35iktydoLKPPLk6Hb8=","P6IFMwnZlp99wiunjusnNW+K5V06iOEtzfoD9MtHCSU=","V4//f/ISXnSeJjUckmcLLzwS38XjXwMjrMAw6B3hKfg=","baLnSFGPpXZDhE38YKkGPW9P35RXQTaZlgDJ2i/u5xA=","YPKEUUZB3AVufkBQm5r7wLJeJMECETlxWoHo3+sKnHE=","VEcYk6UKGgyx1fCjyU6cfCPViC8OZFBjvHz8fco4eGM=","tf738kZ3YKyYiskKppTF5etATmFZgyY6H1ktyC0leCA=","gXQKVsGeO2E9oDbviE7+SuHFG5g7UH35dYGHc9JSz8s=","6kC2DcsZfB5F/TmenKHUzDr2UH6XK//Ch6hC8PZWJ5c=","JA9P8Q8v916uA/xomSrsiXeVBiyxxQAD5Mer9MBIYzA=","BrjYsYvo65dTDWKO8aY0s+9WaWHlVdZuOEzsBHLHe8U="],"checkpoint":{"envelope":"rekor.sigstage.dev - 8202293616175992157\n19442604\nWveYvRUsyPpMgj5BTpatQytFwmxXNIAtg3r3T0Erwzc=\n\n— rekor.sigstage.dev 0y8wozBEAiBLrKviMibkIK4/qPxYL29tvR5IlL8BTQKpjRpzoORIEAIgaXw4XKDTCbaHka5VBOwwH6PuT70TIC2vxO6ukgQrVqI=\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZW52ZWxvcGVIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjNhNzJhYjFkM2FhNWY5ZjlhMzUzMTQzNjE4NTBiZTRkMTg3NGI0OWZhODUwYmExYTY4OWM4MDIzY2UwYWFhZiJ9LCJwYXlsb2FkSGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6ImJjNWM2OTczMDRhYTU0MmE0YTZlMjkyYmExYzg4OWRhMWVhZWE0NmJkYTlhN2JlMmI4MmY1NjIzNTUzMTNlN2UifSwic2lnbmF0dXJlcyI6W3sic2lnbmF0dXJlIjoiTUVRQ0lEekoyZWZRUy9xSG5Bd1B4KzVnV2NOSlhHNmtIbndJMmpvMXlycmxzUlhNQWlBNDg2QzBoK3pGOEY3aUNJbjAyTGJzSFpwSGdHZnhDWFkraGU2QU1aUU5IQT09IiwidmVyaWZpZXIiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VsTmVrTkRRamRwWjBGM1NVSkJaMGxWUzNKa2J6bFBaa1pLZVRaTmRWVmxkMGxsUlM5SlRGZDNMM1J6ZDBObldVbExiMXBKZW1vd1JVRjNUWGNLVG5wRlZrMUNUVWRCTVZWRlEyaE5UV015Ykc1ak0xSjJZMjFWZFZwSFZqSk5ValIzU0VGWlJGWlJVVVJGZUZaNllWZGtlbVJIT1hsYVV6RndZbTVTYkFwamJURnNXa2RzYUdSSFZYZElhR05PVFdwVmVFMXFRVEJOYWtGNlRXcE5OVmRvWTA1TmFsVjRUV3BCTUUxcVFUQk5hazAxVjJwQlFVMUdhM2RGZDFsSUNrdHZXa2w2YWpCRFFWRlpTVXR2V2tsNmFqQkVRVkZqUkZGblFVVnNaWFZpUVZOSWJtVkhPSGhSYlVvdlNHRmpabEJ3TmpOU2NFSlNZamN4YkZSVlZ6TUtkWEZqTDJSNFJuUjBRV3RKZFRFeFRIUlNOVmt4WVZKaE4yZ3ZkVVpRTm1VNVFpOHpWMEZXTVRGNGFYVXlPWFo0VW5GUFEwSjBZM2RuWjJKVVRVRTBSd3BCTVZWa1JIZEZRaTkzVVVWQmQwbElaMFJCVkVKblRsWklVMVZGUkVSQlMwSm5aM0pDWjBWR1FsRmpSRUY2UVdSQ1owNVdTRkUwUlVablVWVmpSRWgxQ25Sd1VuZ3pNVFpzVkdoeGNGSk5jSG95YTNjckwyWTBkMGgzV1VSV1VqQnFRa0puZDBadlFWVmpXVmwzY0doU09GbHRMelU1T1dJd1FsSndMMWd2TDNJS1lqWjNkMmRoVlVkQk1WVmtSVkZGUWk5M1UwSnRha05DYkRSaFFteEhhREJrU0VKNlQyazRkbG95YkRCaFNGWnBURzFPZG1KVE9YcGhWMlI2WkVjNWVRcGFVekZxWWpJMWJXSXpTblJaVnpWcVdsTTViR1ZJVW5sYVZ6RnNZa2hyZEZwSFJuVmFNbFo1WWpOV2VreFlRakZaYlhod1dYa3hkbUZYVW1wTVYwcHNDbGxYVG5aaWFUaDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsc1pVaFNlVnBYTVd4aVNHdDBXa2RHZFZveVZubGlNMVo2VEZjNWNGcEhUWFFLV1cxV2FGa3lPWFZNYm14MFlrVkNlVnBYV25wTU1taHNXVmRTZWt3eU1XaGhWelIzVDFGWlMwdDNXVUpDUVVkRWRucEJRa0ZSVVhKaFNGSXdZMGhOTmdwTWVUa3dZakowYkdKcE5XaFpNMUp3WWpJMWVreHRaSEJrUjJneFdXNVdlbHBZU21waU1qVXdXbGMxTUV4dFRuWmlWRUZtUW1kdmNrSm5SVVZCV1U4dkNrMUJSVU5DUWtZellqTktjbHB0ZUhaa01UbHJZVmhPZDFsWVVtcGhSRUV5UW1kdmNrSm5SVVZCV1U4dlRVRkZSRUpEWnpOUFZGVTBUbTFOZUZwSFZtZ0tXa1JvYVU5RWFHMVpiVnBvVDFkRk0wOUVaM2xhUjBWNFRWUmFhMXBYVG0xT2FtTXdXVlJSZVUxRE1FZERhWE5IUVZGUlFtYzNPSGRCVVZGRlNEQldOQXBrU0Vwc1lsZFdjMlZUUW10WlZ6VnVXbGhLZG1SWVRXZFVNR3hGVVhsQ2FWcFhSbXBpTWpSM1UxRlpTMHQzV1VKQ1FVZEVkbnBCUWtKUlVUZGpNbXh1Q21NelVuWmpiVlYwV1RJNWRWcHRPWGxpVjBaMVdUSlZkbHBZYURCamJWWjBXbGQ0TlV4WFVtaGliV1JzWTIwNU1XTjVNWGRrVjBwellWZE5kR0l5YkdzS1dYa3hhVnBYUm1waU1qUjNTRkZaUzB0M1dVSkNRVWRFZG5wQlFrSm5VVkJqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxRWMwZERhWE5IUVZGUlFncG5OemgzUVZGblJVeFJkM0poU0ZJd1kwaE5Oa3g1T1RCaU1uUnNZbWsxYUZrelVuQmlNalY2VEcxa2NHUkhhREZaYmxaNldsaEthbUl5TlRCYVZ6VXdDa3h0VG5aaVZFTkNjR2RaUzB0M1dVSkNRVWRFZG5wQlFrTlJVMEpzZDNsQ2JFZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZtbE1iVTUyWWxNNWVtRlhaSG9LWkVjNWVWcFRNV3BpTWpWdFlqTktkRmxYTldwYVV6bHNaVWhTZVZwWE1XeGlTR3QwV2tkR2RWb3lWbmxpTTFaNlRGaENNVmx0ZUhCWmVURjJZVmRTYWdwTVYwcHNXVmRPZG1KcE9IVmFNbXd3WVVoV2FVd3paSFpqYlhSdFlrYzVNMk41T1d4bFNGSjVXbGN4YkdKSWEzUmFSMFoxV2pKV2VXSXpWbnBNVnpsd0NscEhUWFJaYlZab1dUSTVkVXh1YkhSaVJVSjVXbGRhZWt3eWFHeFpWMUo2VERJeGFHRlhOSGRQUVZsTFMzZFpRa0pCUjBSMmVrRkNRMmRSY1VSRFp6TUtUMVJWTkU1dFRYaGFSMVpvV2tSb2FVOUVhRzFaYlZwb1QxZEZNMDlFWjNsYVIwVjRUVlJhYTFwWFRtMU9hbU13V1ZSUmVVMUNNRWREYVhOSFFWRlJRZ3BuTnpoM1FWRnpSVVIzZDA1YU1td3dZVWhXYVV4WGFIWmpNMUpzV2tSQ1pVSm5iM0pDWjBWRlFWbFBMMDFCUlUxQ1JrRk5WRzFvTUdSSVFucFBhVGgyQ2xveWJEQmhTRlpwVEcxT2RtSlRPWHBoVjJSNlpFYzVlVnBUTVdwaU1qVnRZak5LZEZsWE5XcGFVemxzWlVoU2VWcFhNV3hpU0d0MFdrZEdkVm95Vm5rS1lqTldla3hZUWpGWmJYaHdXWGt4ZG1GWFVtcE1WMHBzV1ZkT2RtSnFRVFJDWjI5eVFtZEZSVUZaVHk5TlFVVk9Ra052VFV0RVl6Vk9WR2N5V1hwR2F3cGFWMFpyVDBkSk5FOUhXbWxhYlVVMVdWUmpORTlFU210WlZFVjRUbTFTYkZreVdUSk9lbEpvVGtSSmQwaDNXVXRMZDFsQ1FrRkhSSFo2UVVKRVoxRlNDa1JCT1hsYVYxcDZUREpvYkZsWFVucE1NakZvWVZjMGQwZFJXVXRMZDFsQ1FrRkhSSFo2UVVKRWQxRk1SRUZyTWsxNlNURlBWRmswVDFSamQwNTNXVXNLUzNkWlFrSkJSMFIyZWtGQ1JVRlJjRVJEWkc5a1NGSjNZM3B2ZGt3eVpIQmtSMmd4V1drMWFtSXlNSFpqTW14dVl6TlNkbU50VlhSWk1qbDFXbTA1ZVFwaVYwWjFXVEpWZDBkUldVdExkMWxDUWtGSFJIWjZRVUpGVVZGTVJFRnJlRTE2UlRSTlJGRXhUbXBOZDJkaFdVZERhWE5IUVZGUlFtYzNPSGRCVWtsRkNtZGFZMDFuV2xKdlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5XcGlNakIyWXpKc2JtTXpVblpqYlZWMFdUSTVkVnB0T1hsaVYwWjFXVEpWZGxwWWFEQUtZMjFXZEZwWGVEVk1WMUpvWW0xa2JHTnRPVEZqZVRGM1pGZEtjMkZYVFhSaU1teHJXWGt4YVZwWFJtcGlNalIyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbHBZYURCamJWWjBXbGQ0TlV4WFVtaGliV1JzWTIwNU1XTjVNWFpoVjFKcVRGZEtiRmxYVG5aaWFUVTFZbGQ0UVdOdFZtMWplVGx2Q2xwWFJtdGplVGwwV1Zkc2RVMUVaMGREYVhOSFFWRlJRbWMzT0hkQlVrMUZTMmQzYjA1NmF6RlBSRnBxVFZkU2JGbFhVVFJaYW1jMFdtMUtiVmxVYkdnS1RucG5ORTF0VW1oTlZFVXlXa2RXYWxwcVdUTk9SMFV3VFdwQmFFSm5iM0pDWjBWRlFWbFBMMDFCUlZWQ1FrMU5SVmhrZG1OdGRHMWlSemt6V0RKU2NBcGpNMEpvWkVkT2IwMUpSME5DWjI5eVFtZEZSVUZaVHk5TlFVVldRa2hSVFdOdGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hwaFYyUjZDbVJIT1hsYVV6RnFZakkxYldJelNuUlpWelZxV2xNNWJHVklVbmxhVnpGc1lraHJkRnBIUm5WYU1sWjVZak5XZWt4WVFqRlpiWGh3V1hreGRtRlhVbW9LVEZkS2JGbFhUblppYVRsb1dUTlNjR0l5TlhwTU0wb3hZbTVOZGsxVWF6Vk9SRTEzVFhwQmVFOVVhM1paV0ZJd1dsY3hkMlJJVFhaTlZFRlhRbWR2Y2dwQ1owVkZRVmxQTDAxQlJWZENRV2ROUW01Q01WbHRlSEJaZWtOQ2FXZFpTMHQzV1VKQ1FVaFhaVkZKUlVGblVqaENTRzlCWlVGQ01rRkRjM2QyVG5odkNtbE5ibWswWkdkdFMxWTFNRWd3WnpWTldsbERPSEIzZW5reE5VUlJVRFo1Y2tsYU5rRkJRVUp0ZFhOU1NERjNRVUZCVVVSQlJXTjNVbEZKWjAxcWNrSUtNVEJGZDAxVVMwRlhiV3BVVFdGaU1rRllNVmxOWnpGc1YwcHdOM2hXTTNsb1FuZzNSM2xaUTBsUlF6VjZjalEwV25wVlUxQnVTak5IZEcwMmF6aE5NUXBEUW05SmVrUlpWM3AzUWtsdlVrRmthRFZPUlROVVFVdENaMmR4YUd0cVQxQlJVVVJCZDA1d1FVUkNiVUZxUlVGbmVXWm9VMUZ1Ynl0b00xVjFaMUF3Q2tFMlZqQkJPR0lySzNFeFNWWTBhRmx0TkdSV1ptazJjMnRhUzJ0RldVMUdZbk13YjJOTlYzRlhiRXBuT0ZCaFJrRnFSVUYwTnl0SVJHbFhUMlpoTTAwS2VFeFFia2xrZW1WRlVIbzBhMkpuV0ZweFMxRkVUVWhaTlcweFdrYzVOelppYmtwQ2QzUjBUVUZpUVVWWWFFVk1abmxJYkFvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PSJ9XX19"}]},"envelope":{"statement":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoic2hlbGZfcmVhZGVyLTAuMS1weTItbm9uZS1hbnkud2hsIiwiZGlnZXN0Ijp7InNoYTI1NiI6IjJlY2ViMTY0M2MxMGM1ZTRhNjU5NzBiYWY2M2JkZTQzYjc5Y2JkYWM3ZGU4MWRhZTg1M2NlNDdhYjA1MTk3ZTkifX1dLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9kb2NzLnB5cGkub3JnL2F0dGVzdGF0aW9ucy9wdWJsaXNoL3YxIiwicHJlZGljYXRlIjpudWxsfQ==","signature":"MEQCIDzJ2efQS/qHnAwPx+5gWcNJXG6kHnwI2jo1yrrlsRXMAiA486C0h+zF8F7iCIn02LbsHZpHgGfxCXY+he6AMZQNHA=="}}