diff --git a/CHANGELOG.md b/CHANGELOG.md index cd88d7366..b77b04061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Release (2026-MM-DD) - `core`: + - [v0.4.0](core/CHANGELOG.md#v040) + - **Feature:** Add `KeyAuth.close()` to stop the background token refresh thread and its worker, so a discarded instance no longer keeps running and requesting tokens - [v0.3.1](core/CHANGELOG.md#v031) - **Fix:** Refresh access tokens five minutes before expiration instead of after, and wait for in-progress refreshes before authorizing requests - `alb`: diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index b41b2470c..e671d6cd4 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.4.0 +- **Feature:** Add `KeyAuth.close()` to stop the background token refresh thread and its worker, so a discarded instance (for example after key rotation) no longer keeps running and requesting tokens + ## v0.3.1 - **Fix:** Refresh access tokens five minutes before expiration instead of after, and wait for in-progress refreshes before authorizing requests diff --git a/core/pyproject.toml b/core/pyproject.toml index 0bac65e7b..18350e95b 100644 --- a/core/pyproject.toml +++ b/core/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stackit-core" -version = "v0.3.1" +version = "v0.4.0" description = "Core functionality for the STACKIT SDK for Python" authors = [{ name = "STACKIT Developer Tools", email = "developer-tools@stackit.cloud" }] requires-python = ">=3.10,<4.0" diff --git a/core/src/stackit/core/auth_methods/key_auth.py b/core/src/stackit/core/auth_methods/key_auth.py index 6f24eaff2..14a3cdd16 100644 --- a/core/src/stackit/core/auth_methods/key_auth.py +++ b/core/src/stackit/core/auth_methods/key_auth.py @@ -54,6 +54,8 @@ class KeyAuth(AuthBase): executor: ThreadPoolExecutor refresh_future: Optional[futures.Future] service_account_key: ServiceAccountKey + _stop: threading.Event + _refresh_thread: Optional[threading.Thread] def __init__( self, @@ -66,6 +68,8 @@ def __init__( self.executor = ThreadPoolExecutor(max_workers=1) self.access_token = None self.refresh_future = None + self._stop = threading.Event() + self._refresh_thread = None self.__create_initial_token() self.__fetch_token_from_endpoint() self.__start_token_refresh_task() @@ -92,6 +96,24 @@ def __call__(self, r: Request) -> Request: r.headers["Authorization"] = f"Bearer {self.access_token}" return r + def close(self) -> None: + """Stop the background token refresh and release its worker. + + Call this when the instance is no longer needed, for example after + replacing it during key rotation in a long-running process. Without it + the refresh thread keeps running and keeps requesting tokens. When it + returns, no refresh is running and none will start. Safe to call more + than once. + """ + # Set under the lock so the refresh loop cannot submit after shutdown. + with self.lock: + self._stop.set() + atexit.unregister(self.__shutdown) + thread = self._refresh_thread + if thread is not None and thread is not threading.current_thread(): + thread.join() + self.executor.shutdown(wait=True, cancel_futures=True) + def __create_initial_token(self) -> None: payload = { "iss": self.service_account_key.credentials.issuer, @@ -126,9 +148,10 @@ def __fetch_token_from_endpoint(self) -> None: def __start_token_refresh_task(self): def token_refresh_task(): - while True: - time.sleep(self.TOKEN_EXPIRY_CHECK_INTERVAL.total_seconds()) + while not self._stop.wait(self.TOKEN_EXPIRY_CHECK_INTERVAL.total_seconds()): with self.lock: + if self._stop.is_set(): + return if self.refresh_future is not None and self.refresh_future.done(): self.refresh_future.result() if self.__is_token_expired(self.access_token) and ( @@ -139,6 +162,7 @@ def token_refresh_task(): thread = threading.Thread(target=token_refresh_task) thread.daemon = True thread.start() + self._refresh_thread = thread def __refresh_token(self): with self.lock: @@ -156,6 +180,8 @@ def __refresh_token(self): last_exception = None for _ in range(self.MAX_REFRESH_RETRIES): + if self._stop.is_set(): + return try: response = requests.post(self.token_endpoint, data=body, timeout=self.timeout) response.raise_for_status() diff --git a/core/tests/core/test_auth.py b/core/tests/core/test_auth.py index d73009f10..3e9aa45b3 100644 --- a/core/tests/core/test_auth.py +++ b/core/tests/core/test_auth.py @@ -2,6 +2,9 @@ from pathlib import Path, PurePath from threading import Event, Lock, Thread +import time +from datetime import timedelta + import pytest import json import jwt @@ -308,6 +311,7 @@ def test_call_propagates_token_refresh_failure(self, refresh_already_failed): auth.refresh_token = jwt.encode({"exp": 4_000_000_000}, "x" * 32, algorithm="HS256") auth.token_endpoint = KeyAuth.DEFAULT_TOKEN_ENDPOINT auth.refresh_future = None + auth._stop = Event() original_token = auth.access_token request = Request("GET", "https://example.com") refresh_error = requests.RequestException("refresh failed") @@ -382,3 +386,90 @@ def result(self): assert not call_thread.is_alive() assert request.headers["Authorization"] == f"Bearer {fresh_token}" + + +class TestKeyAuthClose: + """A discarded KeyAuth must be able to stop its background token refresh.""" + + @staticmethod + def _make_auth(service_account_key_file_json, mock_post, access_token): + service_account_key = ServiceAccountKey.model_validate_json(service_account_key_file_json) + service_account_key.credentials.private_key = "test-private-key" + response = Mock() + response.raise_for_status.return_value = None + response.json.return_value = { + "access_token": access_token, + "refresh_token": jwt.encode({"exp": 4102444800}, "secret", algorithm="HS256"), + } + mock_post.return_value = response + return KeyAuth(service_account_key) + + def test_close_stops_the_refresh_thread_and_further_token_requests(self, service_account_key_file_json): + def set_initial_token(auth): + auth.initial_token = "test-initial-token" + + expired = jwt.encode({"exp": 1}, "secret", algorithm="HS256") + with ( + patch.object(KeyAuth, "_KeyAuth__create_initial_token", new=set_initial_token), + patch.object(KeyAuth, "TOKEN_EXPIRY_CHECK_INTERVAL", timedelta(milliseconds=10)), + patch("requests.post") as mock_post, + ): + # An access token that is always expired keeps the refresh loop busy. + auth = self._make_auth(service_account_key_file_json, mock_post, expired) + thread = auth._refresh_thread + assert thread is not None and thread.is_alive() + + auth.close() + + assert not thread.is_alive() + requests_after_close = mock_post.call_count + time.sleep(0.1) # ten refresh intervals + assert mock_post.call_count == requests_after_close + + def test_close_waits_for_a_refresh_in_progress(self, service_account_key_file_json): + def set_initial_token(auth): + auth.initial_token = "test-initial-token" + + expired = jwt.encode({"exp": 1}, "secret", algorithm="HS256") + refresh_started = Event() + with ( + patch.object(KeyAuth, "_KeyAuth__create_initial_token", new=set_initial_token), + patch.object(KeyAuth, "TOKEN_EXPIRY_CHECK_INTERVAL", timedelta(milliseconds=10)), + patch("requests.post") as mock_post, + ): + auth = self._make_auth(service_account_key_file_json, mock_post, expired) + initial_response = mock_post.return_value + + def slow_refresh(*args, **kwargs): + refresh_started.set() + time.sleep(0.2) + return initial_response + + mock_post.side_effect = slow_refresh + assert refresh_started.wait(timeout=5) + + auth.close() + + assert auth.refresh_future is not None and auth.refresh_future.done() + requests_after_close = mock_post.call_count + time.sleep(0.1) + assert mock_post.call_count == requests_after_close + + def test_close_is_idempotent(self, service_account_key_file_json): + def set_initial_token(auth): + auth.initial_token = "test-initial-token" + + valid = jwt.encode({"exp": 4102444800}, "secret", algorithm="HS256") + with ( + patch.object(KeyAuth, "_KeyAuth__create_initial_token", new=set_initial_token), + patch("requests.post") as mock_post, + patch("stackit.core.auth_methods.key_auth.atexit") as mock_atexit, + ): + auth = self._make_auth(service_account_key_file_json, mock_post, valid) + + auth.close() + auth.close() + + assert not auth._refresh_thread.is_alive() + assert auth.executor._shutdown + mock_atexit.unregister.assert_called_with(auth._KeyAuth__shutdown) diff --git a/core/uv.lock b/core/uv.lock index 59c9b39f5..d89822b6a 100644 --- a/core/uv.lock +++ b/core/uv.lock @@ -998,7 +998,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { editable = "." } dependencies = [ { name = "cryptography" }, diff --git a/services/alb/uv.lock b/services/alb/uv.lock index 06a74dd07..dbf2c3466 100644 --- a/services/alb/uv.lock +++ b/services/alb/uv.lock @@ -1071,7 +1071,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/albwaf/uv.lock b/services/albwaf/uv.lock index 93afcc31c..3568caa14 100644 --- a/services/albwaf/uv.lock +++ b/services/albwaf/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1071,7 +1071,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/authorization/uv.lock b/services/authorization/uv.lock index 2b11f3ab9..56856106f 100644 --- a/services/authorization/uv.lock +++ b/services/authorization/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1071,7 +1071,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/automation/uv.lock b/services/automation/uv.lock index 51065ddd9..7a95cd302 100644 --- a/services/automation/uv.lock +++ b/services/automation/uv.lock @@ -486,7 +486,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1182,7 +1182,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/cdn/uv.lock b/services/cdn/uv.lock index 0fcb8df92..b83bcc386 100644 --- a/services/cdn/uv.lock +++ b/services/cdn/uv.lock @@ -1071,7 +1071,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/certificates/uv.lock b/services/certificates/uv.lock index 64b06960a..7467ad569 100644 --- a/services/certificates/uv.lock +++ b/services/certificates/uv.lock @@ -1072,7 +1072,7 @@ dev = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/cost/uv.lock b/services/cost/uv.lock index d27805c2f..43480a31b 100644 --- a/services/cost/uv.lock +++ b/services/cost/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/dns/uv.lock b/services/dns/uv.lock index fae03b903..1af6db30c 100644 --- a/services/dns/uv.lock +++ b/services/dns/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/dremio/uv.lock b/services/dremio/uv.lock index 77fb83dbc..7d9effad3 100644 --- a/services/dremio/uv.lock +++ b/services/dremio/uv.lock @@ -489,7 +489,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1095,7 +1095,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/edge/uv.lock b/services/edge/uv.lock index ea1773bc8..c0c94c01a 100644 --- a/services/edge/uv.lock +++ b/services/edge/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/git/uv.lock b/services/git/uv.lock index c2bc2b25d..2d3d3cfcf 100644 --- a/services/git/uv.lock +++ b/services/git/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/iaas/uv.lock b/services/iaas/uv.lock index f9fb85feb..432a89688 100644 --- a/services/iaas/uv.lock +++ b/services/iaas/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/intake/uv.lock b/services/intake/uv.lock index 465b0c0e5..cfdce7ae3 100644 --- a/services/intake/uv.lock +++ b/services/intake/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/kms/uv.lock b/services/kms/uv.lock index c0c9b18a6..7d893556c 100644 --- a/services/kms/uv.lock +++ b/services/kms/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/loadbalancer/uv.lock b/services/loadbalancer/uv.lock index 2d8c73a88..616249c95 100644 --- a/services/loadbalancer/uv.lock +++ b/services/loadbalancer/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/logme/uv.lock b/services/logme/uv.lock index c5635e63e..63002023c 100644 --- a/services/logme/uv.lock +++ b/services/logme/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/logs/uv.lock b/services/logs/uv.lock index eef5e301b..f53524b91 100644 --- a/services/logs/uv.lock +++ b/services/logs/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/mariadb/uv.lock b/services/mariadb/uv.lock index 874a51983..1426a7854 100644 --- a/services/mariadb/uv.lock +++ b/services/mariadb/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/modelexperiments/uv.lock b/services/modelexperiments/uv.lock index 628a40716..bc053dbe0 100644 --- a/services/modelexperiments/uv.lock +++ b/services/modelexperiments/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/modelserving/uv.lock b/services/modelserving/uv.lock index 1cde4b8a5..5a9e72650 100644 --- a/services/modelserving/uv.lock +++ b/services/modelserving/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/mongodbflex/uv.lock b/services/mongodbflex/uv.lock index 74e320b9b..fa69e4771 100644 --- a/services/mongodbflex/uv.lock +++ b/services/mongodbflex/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/objectstorage/uv.lock b/services/objectstorage/uv.lock index 35f38aadf..ecc444a3a 100644 --- a/services/objectstorage/uv.lock +++ b/services/objectstorage/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/observability/uv.lock b/services/observability/uv.lock index bc307ea48..5efd5e10b 100644 --- a/services/observability/uv.lock +++ b/services/observability/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/opensearch/uv.lock b/services/opensearch/uv.lock index bdfb41ae5..dc1862818 100644 --- a/services/opensearch/uv.lock +++ b/services/opensearch/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/postgresflex/uv.lock b/services/postgresflex/uv.lock index 8c13cf537..f4936e99d 100644 --- a/services/postgresflex/uv.lock +++ b/services/postgresflex/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/rabbitmq/uv.lock b/services/rabbitmq/uv.lock index 1493eadb5..3c522806d 100644 --- a/services/rabbitmq/uv.lock +++ b/services/rabbitmq/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/redis/uv.lock b/services/redis/uv.lock index 5788a1a0b..66b0fbe07 100644 --- a/services/redis/uv.lock +++ b/services/redis/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/resourcemanager/uv.lock b/services/resourcemanager/uv.lock index 93a9a963b..20d6f311c 100644 --- a/services/resourcemanager/uv.lock +++ b/services/resourcemanager/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/runcommand/uv.lock b/services/runcommand/uv.lock index fe0e11c84..582521303 100644 --- a/services/runcommand/uv.lock +++ b/services/runcommand/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/scf/uv.lock b/services/scf/uv.lock index 7d58434c1..adf8f2adf 100644 --- a/services/scf/uv.lock +++ b/services/scf/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/secretsmanager/uv.lock b/services/secretsmanager/uv.lock index 1ba485e26..cd45ee1dc 100644 --- a/services/secretsmanager/uv.lock +++ b/services/secretsmanager/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/serverbackup/uv.lock b/services/serverbackup/uv.lock index 01176895e..c80f79760 100644 --- a/services/serverbackup/uv.lock +++ b/services/serverbackup/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/serverupdate/uv.lock b/services/serverupdate/uv.lock index 9329b51f5..5e9c3dabf 100644 --- a/services/serverupdate/uv.lock +++ b/services/serverupdate/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/serviceaccount/uv.lock b/services/serviceaccount/uv.lock index be1b66b7d..755051a52 100644 --- a/services/serviceaccount/uv.lock +++ b/services/serviceaccount/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/serviceenablement/uv.lock b/services/serviceenablement/uv.lock index 4c0813612..e89cb3377 100644 --- a/services/serviceenablement/uv.lock +++ b/services/serviceenablement/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/sfs/uv.lock b/services/sfs/uv.lock index 6e0cb3410..ea24c310d 100644 --- a/services/sfs/uv.lock +++ b/services/sfs/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/ske/uv.lock b/services/ske/uv.lock index 2cec1e4ff..7ad20cec6 100644 --- a/services/ske/uv.lock +++ b/services/ske/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/sqlserverflex/uv.lock b/services/sqlserverflex/uv.lock index 9b72fe075..1af7b3c60 100644 --- a/services/sqlserverflex/uv.lock +++ b/services/sqlserverflex/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/stackitmarketplace/uv.lock b/services/stackitmarketplace/uv.lock index 19cb79c4a..40507ebc1 100644 --- a/services/stackitmarketplace/uv.lock +++ b/services/stackitmarketplace/uv.lock @@ -413,7 +413,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/telemetrylink/uv.lock b/services/telemetrylink/uv.lock index bd093d20c..caf801cc4 100644 --- a/services/telemetrylink/uv.lock +++ b/services/telemetrylink/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/telemetryrouter/uv.lock b/services/telemetryrouter/uv.lock index 80859b4e0..95bfa548c 100644 --- a/services/telemetryrouter/uv.lock +++ b/services/telemetryrouter/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/ufw/uv.lock b/services/ufw/uv.lock index 62a341081..ff8fa3d3e 100644 --- a/services/ufw/uv.lock +++ b/services/ufw/uv.lock @@ -1130,7 +1130,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/valkey/uv.lock b/services/valkey/uv.lock index 90c7f631b..03f7338e3 100644 --- a/services/valkey/uv.lock +++ b/services/valkey/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" }, diff --git a/services/vpn/uv.lock b/services/vpn/uv.lock index 56ec5692a..66b0bbdfb 100644 --- a/services/vpn/uv.lock +++ b/services/vpn/uv.lock @@ -1019,7 +1019,7 @@ wheels = [ [[package]] name = "stackit-core" -version = "0.3.1" +version = "0.4.0" source = { directory = "../../core" } dependencies = [ { name = "cryptography" },