From 59c5e7189111127f59397fed5e6996b7d75a804e Mon Sep 17 00:00:00 2001 From: Mika Hietanen Date: Fri, 26 Sep 2025 12:13:04 +0300 Subject: [PATCH 1/3] deps: bump django-csp to 4.0 Refs: PT-1961 --- requirements.in | 2 +- requirements.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.in b/requirements.in index 618c6d9b..82c2cb03 100644 --- a/requirements.in +++ b/requirements.in @@ -3,7 +3,7 @@ django-admin-list-filter-dropdown django-axes django-auditlog django-cors-headers -django-csp +django-csp~=4.0 django-environ django-filter django-graphql-jwt diff --git a/requirements.txt b/requirements.txt index f0621820..7242f4e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -302,9 +302,9 @@ django-cors-headers==4.7.0 \ --hash=sha256:6fdf31bf9c6d6448ba09ef57157db2268d515d94fc5c89a0a1028e1fc03ee52b \ --hash=sha256:f1c125dcd58479fe7a67fe2499c16ee38b81b397463cf025f0e2c42937421070 # via -r requirements.in -django-csp==3.8 \ - --hash=sha256:19b2978b03fcd73517d7d67acbc04fbbcaec0facc3e83baa502965892d1e0719 \ - --hash=sha256:ef0f1a9f7d8da68ae6e169c02e9ac661c0ecf04db70e0d1d85640512a68471c0 +django-csp==4.0 \ + --hash=sha256:b27010bb702eb20a3dad329178df2b61a2b82d338b70fbdc13c3a3bd28712833 \ + --hash=sha256:d5a0a05463a6b75a4f1fc1828c58c89af8db9364d09fc6e12f122b4d7f3d00dc # via -r requirements.in django-environ==0.12.0 \ --hash=sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a \ From d530e16f44a90a0d37716c2bee95af0423e40f5e Mon Sep 17 00:00:00 2001 From: Mika Hietanen Date: Fri, 26 Sep 2025 12:16:26 +0300 Subject: [PATCH 2/3] feat: migrate to django-csp 4.0 Use constants from django-csp-library directly. Refs: PT-1961 --- notification_importers/admin.py | 8 ++++-- palvelutarjotin/consts.py | 13 --------- palvelutarjotin/settings.py | 49 ++++++++++++++------------------- palvelutarjotin/urls.py | 8 ++++-- 4 files changed, 31 insertions(+), 47 deletions(-) diff --git a/notification_importers/admin.py b/notification_importers/admin.py index efb20443..d7f91358 100644 --- a/notification_importers/admin.py +++ b/notification_importers/admin.py @@ -1,6 +1,7 @@ import importlib import logging +from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE from csp.decorators import csp_update from django.conf import settings from django.contrib import admin, messages @@ -11,8 +12,6 @@ from django_ilmoitin.admin import NotificationTemplateAdmin from django_ilmoitin.models import NotificationTemplate -from palvelutarjotin.consts import CSP - from .notification_importer import ( AbstractNotificationImporter, NotificationImporterException, @@ -113,7 +112,10 @@ def _send_error_message(self, request, message): # Acecpt CSP_UNSAFE_INLINE for the changeform view to allow # the preview template to work correctly. @csp_update( - SCRIPT_SRC=settings.CSP_SCRIPT_SRC + [CSP.UNSAFE_INLINE], + { + "script-src": settings.CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"] + + [CSP_UNSAFE_INLINE], + } ) def changeform_view(self, request, object_id=None, form_url="", extra_context=None): return super().changeform_view( diff --git a/palvelutarjotin/consts.py b/palvelutarjotin/consts.py index 128929a9..3bacdfee 100644 --- a/palvelutarjotin/consts.py +++ b/palvelutarjotin/consts.py @@ -25,16 +25,3 @@ INVALID_TOKEN_ERROR = "INVALID_TOKEN_ERROR" INVALID_STUDY_GROUP_UNIT_INFO_ERROR = "INVALID_STUDY_GROUP_UNIT_INFO_ERROR" QUEUEING_NOT_ALLOWED_ERROR = "QUEUEING_NOT_ALLOWED_ERROR" - - -class CSP: - """The “special” source values of 'self', 'unsafe-inline', 'unsafe-eval', 'none' - and hash-source ('sha256-...') must be quoted! e.g.: CSP_DEFAULT_SRC = ("'self'",). - Without quotes they will not work as intended. - Ref. https://django-csp.readthedocs.io/en/stable/configuration.html. - """ - - SELF = "'self'" - NONE = "'none'" - UNSAFE_INLINE = "'unsafe-inline'" - UNSAFE_EVAL = "'unsafe-eval'" diff --git a/palvelutarjotin/settings.py b/palvelutarjotin/settings.py index b913562e..d35f66a4 100644 --- a/palvelutarjotin/settings.py +++ b/palvelutarjotin/settings.py @@ -5,12 +5,13 @@ import environ import sentry_sdk +from csp.constants import SELF as CSP_SELF +from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE from django.core.exceptions import ImproperlyConfigured from django.utils.translation import gettext_lazy as _ from sentry_sdk.integrations.django import DjangoIntegration from palvelutarjotin import __version__ -from palvelutarjotin.consts import CSP checkout_dir = environ.Path(__file__) - 2 assert os.path.exists(checkout_dir("manage.py")) @@ -268,33 +269,25 @@ CORS_ALLOWED_ORIGIN_REGEXES = env.list("CORS_ALLOWED_ORIGIN_REGEXES") CORS_ALLOW_ALL_ORIGINS = env.bool("CORS_ALLOW_ALL_ORIGINS") -# Configure the default CSP rule for different source types -CSP_DEFAULT_SRC = [CSP.SELF] - -# CSP_STYLE_SRC includes 'unsafe-inline' for inline styles added by `django-helusers`. -CSP_STYLE_SRC = [ - CSP.SELF, - CSP.UNSAFE_INLINE, - "cdn.jsdelivr.net", - "blob:", -] - -CSP_SCRIPT_SRC = [ - CSP.SELF, - "cdn.jsdelivr.net", # /graphql/ endpoint - "blob:", -] - -CSP_FONT_SRC = [ - CSP.SELF, - "data:", # /graphql/ endpoint uses "data:font/woff2" -] - -CSP_IMG_SRC = [ - CSP.SELF, - "blob:", - "data:", -] +# Configure default CSP rules for different source types +CSP_BLOB = "blob:" +CSP_DATA = "data:" +CSP_CDN = "cdn.jsdelivr.net" + +CONTENT_SECURITY_POLICY = { + "DIRECTIVES": { + "default-src": [CSP_SELF], + "font-src": [CSP_SELF, CSP_DATA], # /graphql/ endpoint uses "data:font/woff2" + "img-src": [CSP_SELF, CSP_BLOB, CSP_DATA], + "script-src": [CSP_SELF, CSP_CDN, CSP_BLOB], # /graphql/ endpoint + "style-src": [ + CSP_SELF, + CSP_UNSAFE_INLINE, + CSP_CDN, + CSP_BLOB, + ], # 'unsafe-inline' needed for `django-helusers`. + } +} AUTHENTICATION_BACKENDS = [ "axes.backends.AxesBackend", diff --git a/palvelutarjotin/urls.py b/palvelutarjotin/urls.py index 0dae8d68..17d50ebb 100644 --- a/palvelutarjotin/urls.py +++ b/palvelutarjotin/urls.py @@ -1,3 +1,4 @@ +from csp.constants import UNSAFE_INLINE as CSP_UNSAFE_INLINE from csp.decorators import csp_update from django.conf import settings from django.conf.urls.static import static @@ -15,7 +16,6 @@ from common.utils import get_api_version from custom_health_checks.views import HealthCheckJSONView from palvelutarjotin import __version__ -from palvelutarjotin.consts import CSP from palvelutarjotin.views import SentryGraphQLView admin.site.index_title = " ".join([gettext("Kultus API"), get_api_version()]) @@ -25,8 +25,10 @@ # Add unsafe-inline to enable GraphiQL interface at /graphql/ @csp_update( - SCRIPT_SRC=settings.CSP_SCRIPT_SRC - + ([CSP.UNSAFE_INLINE] if IS_GRAPHIQL_ENABLED else []) + { + "script-src": settings.CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"] + + ([CSP_UNSAFE_INLINE] if IS_GRAPHIQL_ENABLED else []), + } ) @csrf_exempt def graphql_view(request, *args, **kwargs): From 2ee5a0583821fa27867682db88a0f23b99bd6054 Mon Sep 17 00:00:00 2001 From: Mika Hietanen Date: Fri, 26 Sep 2025 12:17:26 +0300 Subject: [PATCH 3/3] chore: update dev-requirements and pre-commit Refs: PT-1961 --- .pre-commit-config.yaml | 2 +- requirements-dev.txt | 305 +++++++++++++++++++++++----------------- 2 files changed, 178 insertions(+), 129 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0cb58988..438c94a3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: # the ruff's version line, it is used by test_pre_commit_ruff_version.py # test case in order not to have to add a YAML library dependency just # to test this version: - rev: v0.12.12 # ruff-pre-commit version + rev: v0.13.2 # ruff-pre-commit version hooks: # Run the linter - id: ruff diff --git a/requirements-dev.txt b/requirements-dev.txt index 6175a831..329dce7a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --allow-unsafe --generate-hashes --strip-extras requirements-dev.in +# pip-compile --allow-unsafe --cert=None --client-cert=None --generate-hashes --index-url=None --pip-args=None --strip-extras requirements-dev.in # build==1.3.0 \ --hash=sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397 \ @@ -185,74 +185,115 @@ charset-normalizer==3.4.1 \ # via # -c requirements.txt # requests -click==8.2.1 \ - --hash=sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202 \ - --hash=sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b +click==8.3.0 \ + --hash=sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc \ + --hash=sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4 # via pip-tools -coverage==7.6.12 \ - --hash=sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95 \ - --hash=sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9 \ - --hash=sha256:06097c7abfa611c91edb9e6920264e5be1d6ceb374efb4986f38b09eed4cb2fe \ - --hash=sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0 \ - --hash=sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924 \ - --hash=sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574 \ - --hash=sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702 \ - --hash=sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3 \ - --hash=sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b \ - --hash=sha256:1a936309a65cc5ca80fa9f20a442ff9e2d06927ec9a4f54bcba9c14c066323f2 \ - --hash=sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea \ - --hash=sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f \ - --hash=sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3 \ - --hash=sha256:220fa6c0ad7d9caef57f2c8771918324563ef0d8272c94974717c3909664e674 \ - --hash=sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9 \ - --hash=sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0 \ - --hash=sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e \ - --hash=sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef \ - --hash=sha256:3688b99604a24492bcfe1c106278c45586eb819bf66a654d8a9a1433022fb2eb \ - --hash=sha256:3a1e465f398c713f1b212400b4e79a09829cd42aebd360362cd89c5bdc44eb87 \ - --hash=sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1 \ - --hash=sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2 \ - --hash=sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703 \ - --hash=sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e \ - --hash=sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd \ - --hash=sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3 \ - --hash=sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4 \ - --hash=sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45 \ - --hash=sha256:676f92141e3c5492d2a1596d52287d0d963df21bf5e55c8b03075a60e1ddf8aa \ - --hash=sha256:69e62c5034291c845fc4df7f8155e8544178b6c774f97a99e2734b05eb5bed31 \ - --hash=sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8 \ - --hash=sha256:78f5243bb6b1060aed6213d5107744c19f9571ec76d54c99cc15938eb69e0e86 \ - --hash=sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6 \ - --hash=sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288 \ - --hash=sha256:7e39e845c4d764208e7b8f6a21c541ade741e2c41afabdfa1caa28687a3c98cf \ - --hash=sha256:8161d9fbc7e9fe2326de89cd0abb9f3599bccc1287db0aba285cb68d204ce929 \ - --hash=sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc \ - --hash=sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985 \ - --hash=sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3 \ - --hash=sha256:aa6f302a3a0b5f240ee201297fff0bbfe2fa0d415a94aeb257d8b461032389bd \ - --hash=sha256:ace9048de91293e467b44bce0f0381345078389814ff6e18dbac8fdbf896360e \ - --hash=sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879 \ - --hash=sha256:b01a840ecc25dce235ae4c1b6a0daefb2a203dba0e6e980637ee9c2f6ee0df57 \ - --hash=sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a \ - --hash=sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad \ - --hash=sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba \ - --hash=sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d \ - --hash=sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750 \ - --hash=sha256:cec6b9ce3bd2b7853d4a4563801292bfee40b030c05a3d29555fd2a8ee9bd68c \ - --hash=sha256:d1a987778b9c71da2fc8948e6f2656da6ef68f59298b7e9786849634c35d2c3c \ - --hash=sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f \ - --hash=sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015 \ - --hash=sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558 \ - --hash=sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f \ - --hash=sha256:e7575ab65ca8399c8c4f9a7d61bbd2d204c8b8e447aab9d355682205c9dd948d \ - --hash=sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d \ - --hash=sha256:ea31689f05043d520113e0552f039603c4dd71fa4c287b64cb3606140c66f425 \ - --hash=sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3 \ - --hash=sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953 \ - --hash=sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827 \ - --hash=sha256:f25d8b92a4e31ff1bd873654ec367ae811b3a943583e05432ea29264782dc32c \ - --hash=sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f \ - --hash=sha256:f973643ef532d4f9be71dd88cf7588936685fdb576d93a79fe9f65bc337d9d73 +coverage==7.10.7 \ + --hash=sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9 \ + --hash=sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880 \ + --hash=sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999 \ + --hash=sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1 \ + --hash=sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13 \ + --hash=sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b \ + --hash=sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82 \ + --hash=sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973 \ + --hash=sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f \ + --hash=sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681 \ + --hash=sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0 \ + --hash=sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541 \ + --hash=sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32 \ + --hash=sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17 \ + --hash=sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a \ + --hash=sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40 \ + --hash=sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd \ + --hash=sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6 \ + --hash=sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7 \ + --hash=sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb \ + --hash=sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f \ + --hash=sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d \ + --hash=sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe \ + --hash=sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c \ + --hash=sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807 \ + --hash=sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab \ + --hash=sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2 \ + --hash=sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546 \ + --hash=sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e \ + --hash=sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65 \ + --hash=sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396 \ + --hash=sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431 \ + --hash=sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb \ + --hash=sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699 \ + --hash=sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0 \ + --hash=sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f \ + --hash=sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a \ + --hash=sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235 \ + --hash=sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911 \ + --hash=sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23 \ + --hash=sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87 \ + --hash=sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699 \ + --hash=sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a \ + --hash=sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b \ + --hash=sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256 \ + --hash=sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a \ + --hash=sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417 \ + --hash=sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0 \ + --hash=sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a \ + --hash=sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360 \ + --hash=sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0 \ + --hash=sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b \ + --hash=sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb \ + --hash=sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2 \ + --hash=sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d \ + --hash=sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a \ + --hash=sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e \ + --hash=sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69 \ + --hash=sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14 \ + --hash=sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d \ + --hash=sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f \ + --hash=sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2 \ + --hash=sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c \ + --hash=sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0 \ + --hash=sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399 \ + --hash=sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59 \ + --hash=sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63 \ + --hash=sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b \ + --hash=sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2 \ + --hash=sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e \ + --hash=sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0 \ + --hash=sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520 \ + --hash=sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df \ + --hash=sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c \ + --hash=sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b \ + --hash=sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2 \ + --hash=sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f \ + --hash=sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61 \ + --hash=sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a \ + --hash=sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59 \ + --hash=sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c \ + --hash=sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf \ + --hash=sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07 \ + --hash=sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6 \ + --hash=sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e \ + --hash=sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594 \ + --hash=sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49 \ + --hash=sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843 \ + --hash=sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14 \ + --hash=sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3 \ + --hash=sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1 \ + --hash=sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698 \ + --hash=sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15 \ + --hash=sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d \ + --hash=sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5 \ + --hash=sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e \ + --hash=sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0 \ + --hash=sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b \ + --hash=sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239 \ + --hash=sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba \ + --hash=sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4 \ + --hash=sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260 \ + --hash=sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a \ + --hash=sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3 # via pytest-cov cryptography==44.0.2 \ --hash=sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390 \ @@ -293,21 +334,21 @@ cryptography==44.0.2 \ # via # -c requirements.txt # -r requirements-dev.in -distlib==0.3.9 \ - --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ - --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 +distlib==0.4.0 \ + --hash=sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16 \ + --hash=sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d # via virtualenv -filelock==3.18.0 \ - --hash=sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2 \ - --hash=sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de +filelock==3.19.1 \ + --hash=sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58 \ + --hash=sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d # via virtualenv -freezegun==1.5.1 \ - --hash=sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9 \ - --hash=sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1 +freezegun==1.5.5 \ + --hash=sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a \ + --hash=sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2 # via -r requirements-dev.in -identify==2.6.9 \ - --hash=sha256:c98b4322da415a8e5a70ff6e51fbc2d2932c015532d77e9f8537b4ba7813b150 \ - --hash=sha256:d40dfe3142a1421d8518e3d3985ef5ac42890683e32306ad614a29490abeb6bf +identify==2.6.14 \ + --hash=sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e \ + --hash=sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a # via pre-commit idna==3.10 \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ @@ -315,9 +356,9 @@ idna==3.10 \ # via # -c requirements.txt # requests -iniconfig==2.0.0 \ - --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ - --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 +iniconfig==2.1.0 \ + --hash=sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7 \ + --hash=sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760 # via pytest nodeenv==1.9.1 \ --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ @@ -338,17 +379,19 @@ pip-tools==7.5.0 \ --hash=sha256:30639f50961bb09f49d22f4389e8d7d990709677c094ce1114186b1f2e9b5821 \ --hash=sha256:69758e4e5a65f160e315d74db46246fdbb30d549f1ed0c4236d057122c9b0f18 # via -r requirements-dev.in -platformdirs==4.3.6 \ - --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ - --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb +platformdirs==4.4.0 \ + --hash=sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85 \ + --hash=sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf # via virtualenv -pluggy==1.5.0 \ - --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ - --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 - # via pytest -pre-commit==4.1.0 \ - --hash=sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4 \ - --hash=sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b +pluggy==1.6.0 \ + --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ + --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 + # via + # pytest + # pytest-cov +pre-commit==4.3.0 \ + --hash=sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8 \ + --hash=sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16 # via -r requirements-dev.in pycparser==2.22 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ @@ -356,27 +399,33 @@ pycparser==2.22 \ # via # -c requirements.txt # cffi +pygments==2.19.2 \ + --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ + --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b + # via + # -c requirements.txt + # pytest pyproject-hooks==1.2.0 \ --hash=sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8 \ --hash=sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913 # via # build # pip-tools -pytest==8.3.5 \ - --hash=sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820 \ - --hash=sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845 +pytest==8.4.2 \ + --hash=sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01 \ + --hash=sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79 # via # -r requirements-dev.in # pytest-cov # pytest-django # syrupy -pytest-cov==6.0.0 \ - --hash=sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35 \ - --hash=sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0 +pytest-cov==7.0.0 \ + --hash=sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1 \ + --hash=sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861 # via -r requirements-dev.in -pytest-django==4.10.0 \ - --hash=sha256:1091b20ea1491fd04a310fc9aaff4c01b4e8450e3b157687625e16a6b5f3a366 \ - --hash=sha256:57c74ef3aa9d89cae5a5d73fbb69a720a62673ade7ff13b9491872409a3f5918 +pytest-django==4.11.1 \ + --hash=sha256:1b63773f648aa3d8541000c26929c1ea63934be1cfa674c76436966d73fe6a10 \ + --hash=sha256:a949141a1ee103cb0e7a20f1451d355f83f5e4a5d07bdd4dcfdd1fd0ff227991 # via -r requirements-dev.in python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ @@ -453,30 +502,30 @@ requests-mock==1.12.1 \ --hash=sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563 \ --hash=sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401 # via -r requirements-dev.in -responses==0.25.7 \ - --hash=sha256:8ebae11405d7a5df79ab6fd54277f6f2bc29b2d002d0dd2d5c632594d1ddcedb \ - --hash=sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c +responses==0.25.8 \ + --hash=sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c \ + --hash=sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4 # via -r requirements-dev.in -ruff==0.12.12 \ - --hash=sha256:01543c137fd3650d322922e8b14cc133b8ea734617c4891c5a9fccf4bfc9aa92 \ - --hash=sha256:0c0945246f5ad776cb8925e36af2438e66188d2b57d9cf2eed2c382c58b371e5 \ - --hash=sha256:173be2bfc142af07a01e3a759aba6f7791aa47acf3604f610b1c36db888df7b1 \ - --hash=sha256:26a1b5a2bf7dd2c47e3b46d077cd9c0fc3b93e6c6cc9ed750bd312ae9dc302ee \ - --hash=sha256:2a8199cab4ce4d72d158319b63370abf60991495fb733db96cd923a34c52d093 \ - --hash=sha256:2afc2fa864197634e549d87fb1e7b6feb01df0a80fd510d6489e1ce8c0b1cc45 \ - --hash=sha256:42a67d16e5b1ffc6d21c5f67851e0e769517fb57a8ebad1d0781b30888aa704e \ - --hash=sha256:59f909c0fdd8f1dcdbfed0b9569b8bf428cf144bec87d9de298dcd4723f5bee8 \ - --hash=sha256:5f12856123b0ad0147d90b3961f5c90e7427f9acd4b40050705499c98983f489 \ - --hash=sha256:7acd6045e87fac75a0b0cdedacf9ab3e1ad9d929d149785903cff9bb69ad9727 \ - --hash=sha256:968e77094b1d7a576992ac078557d1439df678a34c6fe02fd979f973af167577 \ - --hash=sha256:9ac93d87047e765336f0c18eacad51dad0c1c33c9df7484c40f98e1d773876f5 \ - --hash=sha256:a0fbafe8c58e37aae28b84a80ba1817f2ea552e9450156018a478bf1fa80f4e4 \ - --hash=sha256:abf4073688d7d6da16611f2f126be86523a8ec4343d15d276c614bda8ec44edb \ - --hash=sha256:b216ec0a0674e4b1214dcc998a5088e54eaf39417327b19ffefba1c4a1e4971e \ - --hash=sha256:b86cd3415dbe31b3b46a71c598f4c4b2f550346d1ccf6326b347cc0c8fd063d6 \ - --hash=sha256:b9c456fb2fc8e1282affa932c9e40f5ec31ec9cbb66751a316bd131273b57c23 \ - --hash=sha256:de1c4b916d98ab289818e55ce481e2cacfaad7710b01d1f990c497edf217dafc \ - --hash=sha256:e99620bf01884e5f38611934c09dd194eb665b0109104acae3ba6102b600fd0d +ruff==0.13.2 \ + --hash=sha256:17d95fb32218357c89355f6f6f9a804133e404fc1f65694372e02a557edf8585 \ + --hash=sha256:1887c230c2c9d65ed1b4e4cfe4d255577ea28b718ae226c348ae68df958191aa \ + --hash=sha256:1dbc875cf3720c64b3990fef8939334e74cb0ca65b8dbc61d1f439201a38101b \ + --hash=sha256:3196bc13ab2110c176b9a4ae5ff7ab676faaa1964b330a1383ba20e1e19645f2 \ + --hash=sha256:3796345842b55f033a78285e4f1641078f902020d8450cade03aad01bffd81c3 \ + --hash=sha256:4f8f9e3cd6714358238cd6626b9d43026ed19c0c018376ac1ef3c3a04ffb42d8 \ + --hash=sha256:50e2d52acb8de3804fc5f6e2fa3ae9bdc6812410a9e46837e673ad1f90a18736 \ + --hash=sha256:5b939a1b2a960e9742e9a347e5bbc9b3c3d2c716f86c6ae273d9cbd64f193f22 \ + --hash=sha256:5bcb10276b69b3cfea3a102ca119ffe5c6ba3901e20e60cf9efb53fa417633c3 \ + --hash=sha256:6ae3f469b5465ba6d9721383ae9d49310c19b452a161b57507764d7ef15f4b07 \ + --hash=sha256:7c2a0b7c1e87795fec3404a485096bcd790216c7c146a922d121d8b9c8f1aaac \ + --hash=sha256:aed130b2fde049cea2019f55deb939103123cdd191105f97a0599a3e753d61b0 \ + --hash=sha256:afa721017aa55a555b2ff7944816587f1cb813c2c0a882d158f59b832da1660d \ + --hash=sha256:c6ed79584a8f6cbe2e5d7dbacf7cc1ee29cbdb5df1172e77fbdadc8bb85a1f89 \ + --hash=sha256:c75e9d2a2fafd1fdd895d0e7e24b44355984affdde1c412a6f6d3f6e16b22d46 \ + --hash=sha256:cb12fffd32fb16d32cef4ed16d8c7cdc27ed7c944eaa98d99d01ab7ab0b710ff \ + --hash=sha256:cceac74e7bbc53ed7d15d1042ffe7b6577bf294611ad90393bf9b2a0f0ec7cb6 \ + --hash=sha256:da711b14c530412c827219312b7d7fbb4877fb31150083add7e8c5336549cea7 \ + --hash=sha256:ff7e4dda12e683e9709ac89e2dd436abf31a4d8a8fc3d89656231ed808e231d2 # via -r requirements-dev.in six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ @@ -495,9 +544,9 @@ urllib3==2.5.0 \ # -c requirements.txt # requests # responses -virtualenv==20.29.3 \ - --hash=sha256:3e3d00f5807e83b234dfb6122bf37cfadf4be216c53a49ac059d02414f819170 \ - --hash=sha256:95e39403fcf3940ac45bc717597dba16110b74506131845d9b687d5e73d947ac +virtualenv==20.34.0 \ + --hash=sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026 \ + --hash=sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a # via pre-commit wheel==0.45.1 \ --hash=sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729 \