diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3507fd785..816e6ddc0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.9 + rev: v0.7.0 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/alembic/gafaelfawr.yaml b/alembic/gafaelfawr.yaml index c8e938698..cf983da7a 100644 --- a/alembic/gafaelfawr.yaml +++ b/alembic/gafaelfawr.yaml @@ -31,3 +31,8 @@ knownScopes: # A minimal mapping sufficient for Gafaelfawr to start. groupMapping: {} + +# A minimal metrics configuration so that Gafaelfawr will start. +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/changelog.d/20240814_105528_rra_DM_45518.md b/changelog.d/20240814_105528_rra_DM_45518.md index b3f58b647..f80810a40 100644 --- a/changelog.d/20240814_105528_rra_DM_45518.md +++ b/changelog.d/20240814_105528_rra_DM_45518.md @@ -1,6 +1,6 @@ ### New features -- Add support for exporting metrics to an OpenTelemetry collector. The initial set of metrics is limited to login metrics, token delegation, and counts of active sessions and user tokens. +- Add support for exporting metrics to Kafka using the new event metrics support in [Safir](https://safir.lsst.io/). The initial set of events is limited to login metrics, authentications to services, and counts of active sessions and user tokens. ### Bug fixes diff --git a/docs/_rst_epilog.rst b/docs/_rst_epilog.rst index cc619dbb7..1bed28c39 100644 --- a/docs/_rst_epilog.rst +++ b/docs/_rst_epilog.rst @@ -3,13 +3,13 @@ .. _Keycloak: https://www.keycloak.org/ .. _Kopf: https://kopf.readthedocs.io/en/stable/ .. _mypy: https://mypy.readthedocs.io/en/stable/ -.. _OpenTelemetry: https://opentelemetry.io/ .. _Phalanx: https://phalanx.lsst.io/ .. _pre-commit: https://pre-commit.com .. _pytest: https://docs.pytest.org/en/latest/ .. _RFC 2307bis: https://datatracker.ietf.org/doc/html/draft-howard-rfc2307bis-02 .. _Ruff: https://docs.astral.sh/ruff/ .. _Safir: https://safir.lsst.io/ +.. _Sasquatch: https://sasquatch.lsst.io/ .. _scriv: https://scriv.readthedocs.io/en/latest/ .. _semver: https://semver.org/ .. _structlog: https://www.structlog.org/en/stable/ diff --git a/docs/dev/internals.rst b/docs/dev/internals.rst index f7f9a571f..4b5d81c65 100644 --- a/docs/dev/internals.rst +++ b/docs/dev/internals.rst @@ -29,6 +29,9 @@ Python internal API .. automodapi:: gafaelfawr.dependencies.return_url :include-all-objects: +.. automodapi:: gafaelfawr.events + :include-all-objects: + .. automodapi:: gafaelfawr.exceptions :include-all-objects: @@ -38,9 +41,6 @@ Python internal API .. automodapi:: gafaelfawr.keypair :include-all-objects: -.. automodapi:: gafaelfawr.metrics - :include-all-objects: - .. automodapi:: gafaelfawr.middleware.state :include-all-objects: diff --git a/docs/documenteer.toml b/docs/documenteer.toml index ffb638af4..532d57f33 100644 --- a/docs/documenteer.toml +++ b/docs/documenteer.toml @@ -1,6 +1,6 @@ [project] title = "Gafaelfawr" -copyright = "2020-2022 Association of Universities for Research in Astronomy, Inc. (AURA)" +copyright = "2020-2024 Association of Universities for Research in Astronomy, Inc. (AURA)" [project.openapi] openapi_path = "_static/openapi.json" @@ -33,6 +33,8 @@ nitpick_ignore = [ # are generated from the type signatures and can't be avoided. These are # intentionally listed specifically because I've caught documentation bugs # by having Sphinx complain about a new symbol. + ["py:class", "dataclasses_avroschema.pydantic.main.AvroBaseModel"], + ["py:class", "dataclasses_avroschema.main.AvroModel"], ["py:class", "fastapi.applications.FastAPI"], ["py:class", "fastapi.datastructures.DefaultPlaceholder"], ["py:class", "fastapi.exceptions.HTTPException"], @@ -84,7 +86,6 @@ bonsai = "https://bonsai.readthedocs.io/en/latest" cryptography = "https://cryptography.io/en/latest" jwt = "https://pyjwt.readthedocs.io/en/latest" kopf = "https://kopf.readthedocs.io/en/stable" -opentelemetry = "https://opentelemetry-python.readthedocs.io/en/latest" python = "https://docs.python.org/3" redis = "https://redis-py.readthedocs.io/en/stable" safir = "https://safir.lsst.io" diff --git a/docs/user-guide/helm.rst b/docs/user-guide/helm.rst index 2d9dd6697..46d7bd66c 100644 --- a/docs/user-guide/helm.rst +++ b/docs/user-guide/helm.rst @@ -619,17 +619,39 @@ See :ref:`client-ips` for more details. Metrics ======== -Gafaelfawr can export metrics to an OpenTelemetry_ collector. -Currently, it only supports the insecure gRPC mechanism for sending metrics, and therefore should use a collector within the same Kubernetes cluster. - -To enable metrics collection and reporting, set the URL of the metrics collector: +Gafaelfawr can export events and metrics to Sasquatch_, the metrics system for Rubin Observatory. +Metrics reporting is disabled by default. +To enable it, set ``config.metrics.metricsEvents.disable`` to false: .. code-block:: yaml config: - metricsUrl: "http://telegraf.telegraf:4317" + metrics: + metricsEvents: + disable: false + +Gafaelfawr will then use the Kafka user ``gafaelfawr`` to authenticate to Kafka and push various events. +For a list of all of the events Gafaelfawr exports, see :doc:`metrics`. + +There are some additional configuration settings, which normally will not need to be changed: + +``config.metrics.metricsEvents.appName`` + Name of the application under which to log metrics. + Default: ``gafaelfawr`` + +``config.metrics.metricsEvents.topicPrefix`` + The prefix for events topics. + Generally the only reason to change this is if you're experimenting with new events in a development environment. + Default: ``lsst.square.metrics.events`` + +``config.metrics.schemaManager.registryUrl`` + URL to the Confluent-compatible Kafka schema registry, used to register the schemas for events during startup. + Default: Use the Sasquatch schema registry in the local cluster. -For a list of all of the metrics Gafaelfawr exports, see :doc:`metrics`. +``config.metrics.schemaManager.suffix`` + Suffix to add to all registered subjects. + This avoids conflicts with existing registered schemas and may be useful when experimenting with possible event schema changes that are not backwards-compatible. + Default: no suffix .. _slack-alerts: diff --git a/docs/user-guide/metrics.rst b/docs/user-guide/metrics.rst index 70800e691..db5d2806a 100644 --- a/docs/user-guide/metrics.rst +++ b/docs/user-guide/metrics.rst @@ -2,51 +2,49 @@ Metrics ####### -Gafaelfawr optionally supports exporting metrics to an OpenTelemetry_ collector. +Gafaelfawr optionally supports exporting events to Sasquatch_. To enable this support, see :ref:`config-metrics`. -All metrics are logged with a service name of ``gafaelfawr``. +By default, metrics are logged with an application name of ``gafaelfawr`` and a topic prefix of ``lsst.square.metrics.events``. -If metrics collection is enabled, the following metrics will currently be logged. -More metrics will likely be added in the future. +If event exporting is enabled, the following events will currently be logged. +More events will likely be added in the future. Frontend metrics ================ -The following metrics are logged with the meter name of ``frontend``: +The following events are logged by the Gafaelfawr frontend: -login.attempts (counter) - Count of times Gafaelfawr sends a user to the identity provider to authenticate, not including duplicate redirects when the user already has an authentication in progress. +auth + A user was successfully authenticated to a service. + The username is present as the ``username`` tag. + The service name is present as the ``service`` tag, if known. + +login_attempt + Gafaelfawr sent a user to the identity provider to authenticate, not including duplicate redirects when the user already has an authentication in progress. Duplicates are suppressed by not counting redirects if the ``state`` attribute of the user's cookie is already set. -login.enrollment (counter) - Count of the times Gafaelfawr redirects a user to the enrollment flow. +login_enrollment + Gafaelfawr redirected a user to the enrollment flow. -login.failures (counter) - Count of the times a login fails at the Gafaelfawr end, meaning that either something went wrong in Gafaelfawr itself, with the request to the remote authentication service, or via an error reported by the remote authentication service. +login_failure + A login failed at the Gafaelfawr end, meaning that either something went wrong in Gafaelfawr itself, with the request to the remote authentication service, or via an error reported by the remote authentication service. This does not count cases where the authentication service never returns the user to us. It also does not count redirects to the enrollment flow. -login.successes (counter) - Count of the times Gafaelfawr successfully authenticates a user and creates a new session. - The username will be attached as the ``username`` attribute. - -login.success_time (gauge) - Total elapsed time in floating point seconds from when Gafaelfawr redirected the user for authentication to when the user successfully authenticated. - The username will be attached as the ``username`` attribute. - -request.auth (counter) - Count of successful authentication attempts to a service. - Currently, this only counts authentications to a service that requests delegated tokens. - The username is attached as the ``username`` attribute and the service name is attached as the ``service`` attribute. +login_successe + Gafaelfawr successfully authenticated a user and created a new session. + The username is present as the ``username`` tag. + The length of time from initial redirect to successful authentication is present as the ``elapsed`` field, as a float number of seconds. State metrics ============= -The following metrics are logged by the Gafaelfawr maintenance cron job with the meter name of ``state``. +The following metrics are logged by the Gafaelfawr maintenance cron job. +These are also logged as events, since current Rubin Observatory infrastructure only supports events, but they are actually metrics and will switch to a metrics system once one is available. -sessions.active_users (gauge) - Number of users with unexpired sessions. +active_user_sessions + Number of users with unexpired sessions, sent in the ``count`` field. -user_tokens.active - Number of active (unexpired) user tokens. +active_user_tokens + Number of active (unexpired) user tokens, sent in the ``count`` field. diff --git a/pyproject.toml b/pyproject.toml index 34b3d0786..8aa4baf5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,17 +38,16 @@ dependencies = [ "kopf", "kubernetes-asyncio", "jinja2", - "opentelemetry-api", - "opentelemetry-exporter-otlp-proto-grpc", - "opentelemetry-sdk", "pydantic>2", - "pydantic-settings", + "pydantic-settings!=2.6.0", "pyjwt", "pyyaml", "redis>=4.2.0", - "safir[db,kubernetes]>=6.4.0", + "safir[db,kubernetes] @ git+https://github.com/lsst-sqre/safir@tickets/DM-46821#subdirectory=safir", "sqlalchemy>=2.0.0", "structlog", + # Temporary constraint to avoid faststream bug. + "anyio!=4.6.2.post1", ] dynamic = ["version"] diff --git a/requirements/dev.txt b/requirements/dev.txt index 42937771f..42ed51e5b 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -10,9 +10,9 @@ annotated-types==0.7.0 \ # via # -c requirements/main.txt # pydantic -anyio==4.6.2.post1 \ - --hash=sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c \ - --hash=sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d +anyio==4.6.1 \ + --hash=sha256:0632863c9044798a494a05cab0b159dfad6a3f064094863a45878320eb4e8ed2 \ + --hash=sha256:936e6613a08e8f71a300cfffca1c1c0806335607247696ac45f9b32c63bfb9aa # via # -c requirements/main.txt # httpx @@ -660,11 +660,10 @@ imagesize==1.4.1 \ --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a # via sphinx -importlib-metadata==8.4.0 \ - --hash=sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1 \ - --hash=sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5 +importlib-metadata==8.5.0 \ + --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ + --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 # via - # -c requirements/main.txt # jupyter-cache # myst-nb iniconfig==2.0.0 \ @@ -700,12 +699,15 @@ jsonschema==4.23.0 \ --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 # via + # -c requirements/main.txt # nbformat # sphinxcontrib-redoc jsonschema-specifications==2024.10.1 \ --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf - # via jsonschema + # via + # -c requirements/main.txt + # jsonschema jupyter-cache==1.0.0 \ --hash=sha256:594b1c4e29b488b36547e12477645f489dbdc62cc939b2408df5679f79245078 \ --hash=sha256:d0fa7d7533cd5798198d8889318269a8c1382ed3b22f622c09a9356521f48687 @@ -898,6 +900,7 @@ packaging==24.1 \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via + # -c requirements/main.txt # ipykernel # pydata-sphinx-theme # pytest @@ -923,24 +926,24 @@ prompt-toolkit==3.0.48 \ --hash=sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90 \ --hash=sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e # via ipython -psutil==6.0.0 \ - --hash=sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35 \ - --hash=sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0 \ - --hash=sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c \ - --hash=sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1 \ - --hash=sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 \ - --hash=sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c \ - --hash=sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd \ - --hash=sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3 \ - --hash=sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0 \ - --hash=sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2 \ - --hash=sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6 \ - --hash=sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d \ - --hash=sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c \ - --hash=sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 \ - --hash=sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 \ - --hash=sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14 \ - --hash=sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0 +psutil==6.1.0 \ + --hash=sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047 \ + --hash=sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc \ + --hash=sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e \ + --hash=sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747 \ + --hash=sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e \ + --hash=sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a \ + --hash=sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b \ + --hash=sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76 \ + --hash=sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca \ + --hash=sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688 \ + --hash=sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e \ + --hash=sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38 \ + --hash=sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85 \ + --hash=sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be \ + --hash=sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942 \ + --hash=sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a \ + --hash=sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0 # via ipykernel ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \ --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ @@ -1345,6 +1348,7 @@ referencing==0.35.1 \ --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de # via + # -c requirements/main.txt # jsonschema # jsonschema-specifications requests==2.32.3 \ @@ -1465,6 +1469,7 @@ rpds-py==0.20.0 \ --hash=sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a \ --hash=sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8 # via + # -c requirements/main.txt # jsonschema # referencing scriv==1.5.1 \ @@ -1479,9 +1484,9 @@ selenium-wire==5.1.0 \ --hash=sha256:b1cd4eae44d9959381abe3bb186472520d063c658e279f98555def3d4e6dd29b \ --hash=sha256:fbf930d9992f8b6d24bb16b3e6221bab596a41f6ae7548270b7d5a92f3402622 # via -r requirements/dev.in -setuptools==75.1.0 \ - --hash=sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2 \ - --hash=sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538 +setuptools==75.2.0 \ + --hash=sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec \ + --hash=sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8 # via # documenteer # sphinxcontrib-bibtex @@ -1628,36 +1633,63 @@ sphinxext-rediraffe==0.2.7 \ --hash=sha256:9e430a52d4403847f4ffb3a8dd6dfc34a9fe43525305131f52ed899743a5fd8c # via documenteer sqlalchemy==2.0.36 \ + --hash=sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763 \ --hash=sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436 \ + --hash=sha256:07b441f7d03b9a66299ce7ccf3ef2900abc81c0db434f42a5694a37bd73870f2 \ --hash=sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588 \ --hash=sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e \ --hash=sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959 \ --hash=sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d \ --hash=sha256:28120ef39c92c2dd60f2721af9328479516844c6b550b077ca450c7d7dc68575 \ + --hash=sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908 \ --hash=sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8 \ + --hash=sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8 \ + --hash=sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545 \ --hash=sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7 \ --hash=sha256:4557e1f11c5f653ebfdd924f3f9d5ebfc718283b0b9beebaa5dd6b77ec290971 \ + --hash=sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855 \ --hash=sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c \ + --hash=sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71 \ + --hash=sha256:50aae840ebbd6cdd41af1c14590e5741665e5272d2fee999306673a1bb1fdb4d \ + --hash=sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb \ + --hash=sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72 \ --hash=sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f \ + --hash=sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5 \ + --hash=sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346 \ + --hash=sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24 \ --hash=sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e \ --hash=sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5 \ + --hash=sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08 \ --hash=sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793 \ --hash=sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88 \ + --hash=sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686 \ + --hash=sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b \ --hash=sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2 \ --hash=sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28 \ + --hash=sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d \ --hash=sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5 \ --hash=sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a \ --hash=sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a \ + --hash=sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3 \ + --hash=sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf \ --hash=sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5 \ + --hash=sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef \ + --hash=sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689 \ --hash=sha256:b81ee3d84803fd42d0b154cb6892ae57ea6b7c55d8359a02379965706c7efe6c \ + --hash=sha256:be9812b766cad94a25bc63bec11f88c4ad3629a0cec1cd5d4ba48dc23860486b \ --hash=sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07 \ --hash=sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa \ --hash=sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06 \ --hash=sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1 \ + --hash=sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff \ + --hash=sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa \ --hash=sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687 \ + --hash=sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4 \ --hash=sha256:f942a799516184c855e1a32fbc7b29d7e571b52612647866d4ec1c3242578fcb \ --hash=sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44 \ - --hash=sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e + --hash=sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c \ + --hash=sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e \ + --hash=sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53 # via # -c requirements/main.txt # -r requirements/dev.in @@ -1705,9 +1737,9 @@ traitlets==5.14.3 \ # matplotlib-inline # nbclient # nbformat -trio==0.26.2 \ - --hash=sha256:0346c3852c15e5c7d40ea15972c4805689ef2cb8b5206f794c9c19450119f3a4 \ - --hash=sha256:c5237e8133eb0a1d72f09a971a55c28ebe69e351c783fc64bc37db8db8bbe1d0 +trio==0.27.0 \ + --hash=sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831 \ + --hash=sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884 # via # selenium # trio-websocket @@ -1807,9 +1839,7 @@ wsproto==1.2.0 \ zipp==3.20.2 \ --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 - # via - # -c requirements/main.txt - # importlib-metadata + # via importlib-metadata zstandard==0.23.0 \ --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ diff --git a/requirements/main.txt b/requirements/main.txt index b9dcac2dd..aba87981f 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -1,5 +1,9 @@ # This file was autogenerated by uv via the following command: # uv pip compile --generate-hashes --universal --output-file requirements/main.txt pyproject.toml +aiofiles==23.2.1 \ + --hash=sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107 \ + --hash=sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a + # via python-schema-registry-client aiohappyeyeballs==2.4.3 \ --hash=sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586 \ --hash=sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572 @@ -99,6 +103,39 @@ aiohttp==3.10.10 \ # via # kopf # kubernetes-asyncio +aiokafka==0.11.0 \ + --hash=sha256:0973a245b8b9daf8ef6814253a80a700f1f54d2da7d88f6fe479f46e0fd83053 \ + --hash=sha256:0d80590c4ef0ba546a299cee22ea27c3360c14241ec43a8e6904653f7b22d328 \ + --hash=sha256:0e957b42ae959365efbb45c9b5de38032c573608553c3670ad8695cc210abec9 \ + --hash=sha256:1d519bf9875ac867fb19d55de3750833b1eb6379a08de29a68618e24e6a49fc0 \ + --hash=sha256:1f8ae91f0373830e4664376157fe61b611ca7e573d8a559b151aef5bf53df46c \ + --hash=sha256:224db2447f6c1024198d8342e7099198f90401e2fa29c0762afbc51eadf5c490 \ + --hash=sha256:230170ce2e8a0eb852e2e8b78b08ce2e29b77dfe2c51bd56f5ab4be0f332a63b \ + --hash=sha256:3711fa64ee8640dcd4cb640f1030f9439d02e85acd57010d09053017092d8cc2 \ + --hash=sha256:38e1917e706c1158d5e1f612d1fc1b40f706dc46c534e73ab4de8ae2868a31be \ + --hash=sha256:419dd28c8ed6e926061bdc60929af08a6b52f1721e1179d9d21cc72ae28fd6f6 \ + --hash=sha256:4e0cc080a7f4c659ee4e1baa1c32adedcccb105a52156d4909f357d76fac0dc1 \ + --hash=sha256:516e1d68d9a377860b2e17453580afe304605bc71894f684d3e7b6618f6f939f \ + --hash=sha256:55a07a39d82c595223a17015ea738d152544cee979d3d6d822707a082465621c \ + --hash=sha256:560839ae6bc13e71025d71e94df36980f5c6e36a64916439e598b6457267a37f \ + --hash=sha256:59f4b935589ebb244620afad8bf3320e3bc86879a8b1c692ad06bd324f6c6127 \ + --hash=sha256:6ef3e7c8a923e502caa4d24041f2be778fd7f9ee4587bf0bcb4f74cac05122fa \ + --hash=sha256:702aec15b63bad5e4476294bcb1cb177559149fce3e59335794f004c279cbd6a \ + --hash=sha256:73584be8ba7906e3f33ca0f08f6af21a9ae31b86c6b635b93db3b1e6f452657b \ + --hash=sha256:807f699cf916369b1a512e4f2eaec714398c202d8803328ef8711967d99a56ce \ + --hash=sha256:818a6f8e44b02113b9e795bee6029c8a4e525ab38f29d7adb0201f3fec74c808 \ + --hash=sha256:8ba981956243767b37c929845c398fda2a2e35a4034d218badbe2b62e6f98f96 \ + --hash=sha256:926f93fb6a39891fd4364494432b479c0602f9cac708778d4a262a2c2e20d3b4 \ + --hash=sha256:9a478a14fd23fd1ffe9c7a21238d818b5f5e0626f7f06146b687f3699298391b \ + --hash=sha256:acfd0a5d0aec762ba73eeab73b23edce14f315793f063b6a4b223b6f79e36bb8 \ + --hash=sha256:d59fc7aec088c9ffc02d37e61591f053459bd11912cf04c70ac4f7e60405667d \ + --hash=sha256:d724b6fc484e453b373052813e4e543fc028a22c3fbda10e13b6829740000b8a \ + --hash=sha256:eaafe134de57b184f3c030e1a11051590caff7953c8bf58048eefd8d828e39d7 \ + --hash=sha256:eac78a009b713e28b5b4c4daae9d062acbf2b7980e5734467643a810134583b5 \ + --hash=sha256:ee0c61a2dcabbe4474ff237d708f9bd663dd2317e03a9cb7239a212c9ee05b12 \ + --hash=sha256:f1c85f66eb3564c5e74d8e4c25df4ac1fd94f1a6f6e66f005aafa6f791bde215 \ + --hash=sha256:f2def07fe1720c4fe37c0309e355afa9ff4a28e0aabfe847be0692461ac69352 + # via safir aiosignal==1.3.1 \ --hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \ --hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17 @@ -113,13 +150,20 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.6.2.post1 \ - --hash=sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c \ - --hash=sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d +anyio==4.6.1 \ + --hash=sha256:0632863c9044798a494a05cab0b159dfad6a3f064094863a45878320eb4e8ed2 \ + --hash=sha256:936e6613a08e8f71a300cfffca1c1c0806335607247696ac45f9b32c63bfb9aa # via + # gafaelfawr (pyproject.toml) + # fast-depends + # faststream # httpx # starlette # watchfiles +async-timeout==4.0.3 \ + --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ + --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 + # via aiokafka asyncpg==0.29.0 \ --hash=sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9 \ --hash=sha256:000c996c53c04770798053e1730d34e30cb645ad95a63265aec82da9093d88e7 \ @@ -168,7 +212,10 @@ asyncpg==0.29.0 \ attrs==24.2.0 \ --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 - # via aiohttp + # via + # aiohttp + # jsonschema + # referencing bonsai==1.5.3 \ --hash=sha256:07384477ea5f437682b3208bcfd871ebde7e782c8750cebfb18654618aca19a4 \ --hash=sha256:082fe4ddeea8a9c6e1d5495b883ba1ddb02dbbc5d819ddc26d036998b36d6da6 \ @@ -194,6 +241,10 @@ cachetools==5.5.0 \ # via # gafaelfawr (pyproject.toml) # google-auth +casefy==0.1.7 \ + --hash=sha256:6accce985a64b9edb2a610a29ac489d78fac80e52ff8f2d137e294f2f92b8027 \ + --hash=sha256:ab05ff1c67f2a8e62d9f8986fa9a849416d61ac5413ec57d1f827b4f36589cf6 + # via dataclasses-avroschema certifi==2024.8.30 \ --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 @@ -424,19 +475,62 @@ cryptography==43.0.1 \ # gafaelfawr (pyproject.toml) # pyjwt # safir -deprecated==1.2.14 \ - --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ - --hash=sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3 - # via - # opentelemetry-api - # opentelemetry-exporter-otlp-proto-grpc - # opentelemetry-semantic-conventions +dacite==1.8.1 \ + --hash=sha256:cc31ad6fdea1f49962ea42db9421772afe01ac5442380d9a99fcf3d188c61afe + # via dataclasses-avroschema +dataclasses-avroschema==0.63.7 \ + --hash=sha256:316c27ddf3cf7016912f121f201b6616d821ce2fc84baaa2e9188b3eab56d7af \ + --hash=sha256:439645ecae74da98de15dfaf25e0e76d0b954c357af2544f63dbce550858d9e6 + # via safir +fast-depends==2.4.12 \ + --hash=sha256:9393e6de827f7afa0141e54fa9553b737396aaf06bd0040e159d1f790487b16d \ + --hash=sha256:9e5d110ddc962329e46c9b35e5fe65655984247a13ee3ca5a33186db7d2d75c2 + # via faststream fastapi==0.115.2 \ --hash=sha256:3995739e0b09fa12f984bce8fa9ae197b35d433750d3d312422d846e283697ee \ --hash=sha256:61704c71286579cc5a598763905928f24ee98bfcc07aabe84cfefb98812bbc86 # via # gafaelfawr (pyproject.toml) # safir +fastavro==1.9.7 \ + --hash=sha256:0b2f9bafa167cb4d1c3dd17565cb5bf3d8c0759e42620280d1760f1e778e07fc \ + --hash=sha256:13e11c6cb28626da85290933027cd419ce3f9ab8e45410ef24ce6b89d20a1f6c \ + --hash=sha256:17de68aae8c2525f5631d80f2b447a53395cdc49134f51b0329a5497277fc2d2 \ + --hash=sha256:1d09227d1f48f13281bd5ceac958650805aef9a4ef4f95810128c1f9be1df736 \ + --hash=sha256:2af559f30383b79cf7d020a6b644c42ffaed3595f775fe8f3d7f80b1c43dfdc5 \ + --hash=sha256:2db993ae6cdc63e25eadf9f93c9e8036f9b097a3e61d19dca42536dcc5c4d8b3 \ + --hash=sha256:2fcce036c6aa06269fc6a0428050fcb6255189997f5e1a728fc461e8b9d3e26b \ + --hash=sha256:3b683693c8a85ede496ebebe115be5d7870c150986e34a0442a20d88d7771224 \ + --hash=sha256:4e1289b731214a7315884c74b2ec058b6e84380ce9b18b8af5d387e64b18fc44 \ + --hash=sha256:536f5644737ad21d18af97d909dba099b9e7118c237be7e4bd087c7abde7e4f0 \ + --hash=sha256:56304401d2f4f69f5b498bdd1552c13ef9a644d522d5de0dc1d789cf82f47f73 \ + --hash=sha256:58f76a5c9a312fbd37b84e49d08eb23094d36e10d43bc5df5187bc04af463feb \ + --hash=sha256:6312fa99deecc319820216b5e1b1bd2d7ebb7d6f221373c74acfddaee64e8e60 \ + --hash=sha256:7313def3aea3dacface0a8b83f6d66e49a311149aa925c89184a06c1ef99785d \ + --hash=sha256:76d9d96f98052615ab465c63ba8b76ed59baf2e3341b7b169058db104cbe2aa0 \ + --hash=sha256:7c911366c625d0a997eafe0aa83ffbc6fd00d8fd4543cb39a97c6f3b8120ea87 \ + --hash=sha256:912283ed48578a103f523817fdf0c19b1755cea9b4a6387b73c79ecb8f8f84fc \ + --hash=sha256:919f3549e07a8a8645a2146f23905955c35264ac809f6c2ac18142bc5b9b6022 \ + --hash=sha256:9be089be8c00f68e343bbc64ca6d9a13e5e5b0ba8aa52bcb231a762484fb270e \ + --hash=sha256:9de1fa832a4d9016724cd6facab8034dc90d820b71a5d57c7e9830ffe90f31e4 \ + --hash=sha256:b525c363e267ed11810aaad8fbdbd1c3bd8837d05f7360977d72a65ab8c6e1fa \ + --hash=sha256:b6b2ccdc78f6afc18c52e403ee68c00478da12142815c1bd8a00973138a166d0 \ + --hash=sha256:cc811fb4f7b5ae95f969cda910241ceacf82e53014c7c7224df6f6e0ca97f52f \ + --hash=sha256:d576eccfd60a18ffa028259500df67d338b93562c6700e10ef68bbd88e499731 \ + --hash=sha256:e87d04b235b29f7774d226b120da2ca4e60b9e6fdf6747daef7f13f218b3517a \ + --hash=sha256:eac69666270a76a3a1d0444f39752061195e79e146271a568777048ffbd91a27 \ + --hash=sha256:ec2e96bdabd58427fe683329b3d79f42c7b4f4ff6b3644664a345a655ac2c0a1 \ + --hash=sha256:ec8499dc276c2d2ef0a68c0f1ad11782b2b956a921790a36bf4c18df2b8d4020 \ + --hash=sha256:edc28ab305e3c424de5ac5eb87b48d1e07eddb6aa08ef5948fcda33cc4d995ce \ + --hash=sha256:ee9bf23c157bd7dcc91ea2c700fa3bd924d9ec198bb428ff0b47fa37fe160659 \ + --hash=sha256:fb8749e419a85f251bf1ac87d463311874972554d25d4a0b19f6bdc56036d7cf + # via + # dataclasses-avroschema + # python-schema-registry-client +faststream==0.5.27 \ + --hash=sha256:1e363a869d3494643d798e362ce711aa2ad9eb923f40c025a1ab924690cb14b2 \ + --hash=sha256:4ed3d934580ea4337a807ee2bea18e87b81cd00cc19da8c195c2f6445158d3a8 + # via safir frozenlist==1.4.1 \ --hash=sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7 \ --hash=sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98 \ @@ -549,7 +643,6 @@ googleapis-common-protos==1.65.0 \ # via # google-api-core # grpcio-status - # opentelemetry-exporter-otlp-proto-grpc greenlet==3.1.1 \ --hash=sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e \ --hash=sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7 \ @@ -625,69 +718,68 @@ greenlet==3.1.1 \ --hash=sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79 \ --hash=sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f # via sqlalchemy -grpcio==1.66.2 \ - --hash=sha256:02697eb4a5cbe5a9639f57323b4c37bcb3ab2d48cec5da3dc2f13334d72790dd \ - --hash=sha256:03b0b307ba26fae695e067b94cbb014e27390f8bc5ac7a3a39b7723fed085604 \ - --hash=sha256:05bc2ceadc2529ab0b227b1310d249d95d9001cd106aa4d31e8871ad3c428d73 \ - --hash=sha256:06de8ec0bd71be123eec15b0e0d457474931c2c407869b6c349bd9bed4adbac3 \ - --hash=sha256:0be4e0490c28da5377283861bed2941d1d20ec017ca397a5df4394d1c31a9b50 \ - --hash=sha256:12fda97ffae55e6526825daf25ad0fa37483685952b5d0f910d6405c87e3adb6 \ - --hash=sha256:1caa38fb22a8578ab8393da99d4b8641e3a80abc8fd52646f1ecc92bcb8dee34 \ - --hash=sha256:2018b053aa15782db2541ca01a7edb56a0bf18c77efed975392583725974b249 \ - --hash=sha256:20657d6b8cfed7db5e11b62ff7dfe2e12064ea78e93f1434d61888834bc86d75 \ - --hash=sha256:2335c58560a9e92ac58ff2bc5649952f9b37d0735608242973c7a8b94a6437d8 \ - --hash=sha256:31fd163105464797a72d901a06472860845ac157389e10f12631025b3e4d0453 \ - --hash=sha256:38b68498ff579a3b1ee8f93a05eb48dc2595795f2f62716e797dc24774c1aaa8 \ - --hash=sha256:3b00efc473b20d8bf83e0e1ae661b98951ca56111feb9b9611df8efc4fe5d55d \ - --hash=sha256:3ed71e81782966ffead60268bbda31ea3f725ebf8aa73634d5dda44f2cf3fb9c \ - --hash=sha256:45a3d462826f4868b442a6b8fdbe8b87b45eb4f5b5308168c156b21eca43f61c \ - --hash=sha256:49f0ca7ae850f59f828a723a9064cadbed90f1ece179d375966546499b8a2c9c \ - --hash=sha256:4e504572433f4e72b12394977679161d495c4c9581ba34a88d843eaf0f2fbd39 \ - --hash=sha256:4ea1d062c9230278793820146c95d038dc0f468cbdd172eec3363e42ff1c7d01 \ - --hash=sha256:563588c587b75c34b928bc428548e5b00ea38c46972181a4d8b75ba7e3f24231 \ - --hash=sha256:6001e575b8bbd89eee11960bb640b6da6ae110cf08113a075f1e2051cc596cae \ - --hash=sha256:66a0cd8ba6512b401d7ed46bb03f4ee455839957f28b8d61e7708056a806ba6a \ - --hash=sha256:6851de821249340bdb100df5eacfecfc4e6075fa85c6df7ee0eb213170ec8e5d \ - --hash=sha256:728bdf36a186e7f51da73be7f8d09457a03061be848718d0edf000e709418987 \ - --hash=sha256:73e3b425c1e155730273f73e419de3074aa5c5e936771ee0e4af0814631fb30a \ - --hash=sha256:73fc8f8b9b5c4a03e802b3cd0c18b2b06b410d3c1dcbef989fdeb943bd44aff7 \ - --hash=sha256:78fa51ebc2d9242c0fc5db0feecc57a9943303b46664ad89921f5079e2e4ada7 \ - --hash=sha256:7b2c86457145ce14c38e5bf6bdc19ef88e66c5fee2c3d83285c5aef026ba93b3 \ - --hash=sha256:7d69ce1f324dc2d71e40c9261d3fdbe7d4c9d60f332069ff9b2a4d8a257c7b2b \ - --hash=sha256:802d84fd3d50614170649853d121baaaa305de7b65b3e01759247e768d691ddf \ - --hash=sha256:80fd702ba7e432994df208f27514280b4b5c6843e12a48759c9255679ad38db8 \ - --hash=sha256:8ac475e8da31484efa25abb774674d837b343afb78bb3bcdef10f81a93e3d6bf \ - --hash=sha256:950da58d7d80abd0ea68757769c9db0a95b31163e53e5bb60438d263f4bed7b7 \ - --hash=sha256:99a641995a6bc4287a6315989ee591ff58507aa1cbe4c2e70d88411c4dcc0839 \ - --hash=sha256:9c3a99c519f4638e700e9e3f83952e27e2ea10873eecd7935823dab0c1c9250e \ - --hash=sha256:9c509a4f78114cbc5f0740eb3d7a74985fd2eff022971bc9bc31f8bc93e66a3b \ - --hash=sha256:a18e20d8321c6400185b4263e27982488cb5cdd62da69147087a76a24ef4e7e3 \ - --hash=sha256:a917d26e0fe980b0ac7bfcc1a3c4ad6a9a4612c911d33efb55ed7833c749b0ee \ - --hash=sha256:a9539f01cb04950fd4b5ab458e64a15f84c2acc273670072abe49a3f29bbad54 \ - --hash=sha256:ad2efdbe90c73b0434cbe64ed372e12414ad03c06262279b104a029d1889d13e \ - --hash=sha256:b672abf90a964bfde2d0ecbce30f2329a47498ba75ce6f4da35a2f4532b7acbc \ - --hash=sha256:bbd27c24a4cc5e195a7f56cfd9312e366d5d61b86e36d46bbe538457ea6eb8dd \ - --hash=sha256:c400ba5675b67025c8a9f48aa846f12a39cf0c44df5cd060e23fda5b30e9359d \ - --hash=sha256:c408f5ef75cfffa113cacd8b0c0e3611cbfd47701ca3cdc090594109b9fcbaed \ - --hash=sha256:c806852deaedee9ce8280fe98955c9103f62912a5b2d5ee7e3eaa284a6d8d8e7 \ - --hash=sha256:ce89f5876662f146d4c1f695dda29d4433a5d01c8681fbd2539afff535da14d4 \ - --hash=sha256:d25a14af966438cddf498b2e338f88d1c9706f3493b1d73b93f695c99c5f0e2a \ - --hash=sha256:d8d4732cc5052e92cea2f78b233c2e2a52998ac40cd651f40e398893ad0d06ec \ - --hash=sha256:d9a9724a156c8ec6a379869b23ba3323b7ea3600851c91489b871e375f710bc8 \ - --hash=sha256:e636ce23273683b00410f1971d209bf3689238cf5538d960adc3cdfe80dd0dbd \ - --hash=sha256:e88264caad6d8d00e7913996030bac8ad5f26b7411495848cc218bd3a9040b6c \ - --hash=sha256:f145cc21836c332c67baa6fc81099d1d27e266401565bf481948010d6ea32d46 \ - --hash=sha256:fb57870449dfcfac428afbb5a877829fcb0d6db9d9baa1148705739e9083880e \ - --hash=sha256:fb70487c95786e345af5e854ffec8cb8cc781bcc5df7930c4fbb7feaa72e1cdf \ - --hash=sha256:fe96281713168a3270878255983d2cb1a97e034325c8c2c25169a69289d3ecfa \ - --hash=sha256:ff1f7882e56c40b0d33c4922c15dfa30612f05fb785074a012f7cda74d1c3679 +grpcio==1.67.0 \ + --hash=sha256:014dfc020e28a0d9be7e93a91f85ff9f4a87158b7df9952fe23cc42d29d31e1e \ + --hash=sha256:0892dd200ece4822d72dd0952f7112c542a487fc48fe77568deaaa399c1e717d \ + --hash=sha256:0bb94e66cd8f0baf29bd3184b6aa09aeb1a660f9ec3d85da615c5003154bc2bf \ + --hash=sha256:0c69bf11894cad9da00047f46584d5758d6ebc9b5950c0dc96fec7e0bce5cde9 \ + --hash=sha256:15c05a26a0f7047f720da41dc49406b395c1470eef44ff7e2c506a47ac2c0591 \ + --hash=sha256:16724ffc956ea42967f5758c2f043faef43cb7e48a51948ab593570570d1e68b \ + --hash=sha256:227316b5631260e0bef8a3ce04fa7db4cc81756fea1258b007950b6efc90c05d \ + --hash=sha256:2b7183c80b602b0ad816315d66f2fb7887614ead950416d60913a9a71c12560d \ + --hash=sha256:2f55c1e0e2ae9bdd23b3c63459ee4c06d223b68aeb1961d83c48fb63dc29bc03 \ + --hash=sha256:30d47dbacfd20cbd0c8be9bfa52fdb833b395d4ec32fe5cff7220afc05d08571 \ + --hash=sha256:323741b6699cd2b04a71cb38f502db98f90532e8a40cb675393d248126a268af \ + --hash=sha256:3840994689cc8cbb73d60485c594424ad8adb56c71a30d8948d6453083624b52 \ + --hash=sha256:391df8b0faac84d42f5b8dfc65f5152c48ed914e13c522fd05f2aca211f8bfad \ + --hash=sha256:42199e704095b62688998c2d84c89e59a26a7d5d32eed86d43dc90e7a3bd04aa \ + --hash=sha256:54d16383044e681f8beb50f905249e4e7261dd169d4aaf6e52eab67b01cbbbe2 \ + --hash=sha256:5a1e03c3102b6451028d5dc9f8591131d6ab3c8a0e023d94c28cb930ed4b5f81 \ + --hash=sha256:62492bd534979e6d7127b8a6b29093161a742dee3875873e01964049d5250a74 \ + --hash=sha256:662c8e105c5e5cee0317d500eb186ed7a93229586e431c1bf0c9236c2407352c \ + --hash=sha256:682968427a63d898759474e3b3178d42546e878fdce034fd7474ef75143b64e3 \ + --hash=sha256:74b900566bdf68241118f2918d312d3bf554b2ce0b12b90178091ea7d0a17b3d \ + --hash=sha256:77196216d5dd6f99af1c51e235af2dd339159f657280e65ce7e12c1a8feffd1d \ + --hash=sha256:7f200aca719c1c5dc72ab68be3479b9dafccdf03df530d137632c534bb6f1ee3 \ + --hash=sha256:7fc1d2b9fd549264ae585026b266ac2db53735510a207381be509c315b4af4e8 \ + --hash=sha256:82e5bd4b67b17c8c597273663794a6a46a45e44165b960517fe6d8a2f7f16d23 \ + --hash=sha256:8c9a35b8bc50db35ab8e3e02a4f2a35cfba46c8705c3911c34ce343bd777813a \ + --hash=sha256:985b2686f786f3e20326c4367eebdaed3e7aa65848260ff0c6644f817042cb15 \ + --hash=sha256:9d75641a2fca9ae1ae86454fd25d4c298ea8cc195dbc962852234d54a07060ad \ + --hash=sha256:a4e95e43447a02aa603abcc6b5e727d093d161a869c83b073f50b9390ecf0fa8 \ + --hash=sha256:a6b9a5c18863fd4b6624a42e2712103fb0f57799a3b29651c0e5b8119a519d65 \ + --hash=sha256:aa8d025fae1595a207b4e47c2e087cb88d47008494db258ac561c00877d4c8f8 \ + --hash=sha256:ac11ecb34a86b831239cc38245403a8de25037b448464f95c3315819e7519772 \ + --hash=sha256:ae6de510f670137e755eb2a74b04d1041e7210af2444103c8c95f193340d17ee \ + --hash=sha256:b2a44e572fb762c668e4812156b81835f7aba8a721b027e2d4bb29fb50ff4d33 \ + --hash=sha256:b6eb68493a05d38b426604e1dc93bfc0137c4157f7ab4fac5771fd9a104bbaa6 \ + --hash=sha256:b9bca3ca0c5e74dea44bf57d27e15a3a3996ce7e5780d61b7c72386356d231db \ + --hash=sha256:bd79929b3bb96b54df1296cd3bf4d2b770bd1df6c2bdf549b49bab286b925cdc \ + --hash=sha256:c4c425f440fb81f8d0237c07b9322fc0fb6ee2b29fbef5f62a322ff8fcce240d \ + --hash=sha256:cb204a742997277da678611a809a8409657b1398aaeebf73b3d9563b7d154c13 \ + --hash=sha256:cf51d28063338608cd8d3cd64677e922134837902b70ce00dad7f116e3998210 \ + --hash=sha256:cfd9306511fdfc623a1ba1dc3bc07fbd24e6cfbe3c28b4d1e05177baa2f99617 \ + --hash=sha256:cff8e54d6a463883cda2fab94d2062aad2f5edd7f06ae3ed030f2a74756db365 \ + --hash=sha256:d01793653248f49cf47e5695e0a79805b1d9d4eacef85b310118ba1dfcd1b955 \ + --hash=sha256:d4ea4509d42c6797539e9ec7496c15473177ce9abc89bc5c71e7abe50fc25737 \ + --hash=sha256:d90cfdafcf4b45a7a076e3e2a58e7bc3d59c698c4f6470b0bb13a4d869cf2273 \ + --hash=sha256:e090b2553e0da1c875449c8e75073dd4415dd71c9bde6a406240fdf4c0ee467c \ + --hash=sha256:e91d154689639932305b6ea6f45c6e46bb51ecc8ea77c10ef25aa77f75443ad4 \ + --hash=sha256:eef1dce9d1a46119fd09f9a992cf6ab9d9178b696382439446ca5f399d7b96fe \ + --hash=sha256:efe32b45dd6d118f5ea2e5deaed417d8a14976325c93812dd831908522b402c9 \ + --hash=sha256:f4d613fbf868b2e2444f490d18af472ccb47660ea3df52f068c9c8801e1f3e85 \ + --hash=sha256:f55f077685f61f0fbd06ea355142b71e47e4a26d2d678b3ba27248abfe67163a \ + --hash=sha256:f623c57a5321461c84498a99dddf9d13dac0e40ee056d884d6ec4ebcab647a78 \ + --hash=sha256:f6bd2ab135c64a4d1e9e44679a616c9bc944547357c830fafea5c3caa3de5153 \ + --hash=sha256:f95e15db43e75a534420e04822df91f645664bf4ad21dfaad7d51773c80e6bb4 \ + --hash=sha256:fd6bc27861e460fe28e94226e3673d46e294ca4673d46b224428d197c5935e69 \ + --hash=sha256:fe89295219b9c9e47780a0f1c75ca44211e706d1c598242249fe717af3385ec8 # via # google-api-core # grpcio-status - # opentelemetry-exporter-otlp-proto-grpc -grpcio-status==1.62.3 \ - --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ - --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 +grpcio-status==1.67.0 \ + --hash=sha256:0e79e2e01ba41a6ca6ed9d7a825323c511fe1653a646f8014c7e3c8132527acc \ + --hash=sha256:c3e5a86fa007e9e263cd5f988a8a907484da4caab582874ea2a4a6092734046b # via google-api-core h11==0.14.0 \ --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ @@ -699,56 +791,57 @@ httpcore==1.0.6 \ --hash=sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f \ --hash=sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f # via httpx -httptools==0.6.2 \ - --hash=sha256:0238f07780782c018e9801d8f5f5aea3a4680a1af132034b444f677718c6fe88 \ - --hash=sha256:052f7f50e4a38f069478143878371ed17937f268349bcd68f6f7a9de9fcfce21 \ - --hash=sha256:054bdee08e4f7c15c186f6e7dbc8f0cf974b8dd1832b5f17f988faf8b12815c9 \ - --hash=sha256:1099f73952e18c718ccaaf7a97ae58c94a91839c3d247c6184326f85a2eda7b4 \ - --hash=sha256:10d28e5597d4349390c640232c9366ddc15568114f56724fe30a53de9686b6ab \ - --hash=sha256:1b7bc59362143dc2d02896dde94004ef54ff1989ceedf4b389ad3b530f312364 \ - --hash=sha256:1bb67d47f045f56e9a5da4deccf710bdde21212e4b1f4776b7a542449f6a7682 \ - --hash=sha256:2d5c33d98b2311ddbe06e92b12b14de334dcfbe64ebcbb2c7a34b5c6036db512 \ - --hash=sha256:2e9d225b178a6cc700c23cf2f5daf85a10f93f1db7c34e9ee4ee0bbc29ad458a \ - --hash=sha256:352a496244360deb1c1d108391d76cd6f3dd9f53ccf975a082e74c6761af30c9 \ - --hash=sha256:3f0246ca7f78fa8e3902ddb985b9f55509d417a862f4634a8fa63a7a496266c8 \ - --hash=sha256:406f7dc5d9db68cd9ac638d14c74d077085f76b45f704d3ec38d43b842b3cb44 \ - --hash=sha256:41965586b02715c3d83dd9153001f654e5b621de0c5255f5ef0635485212d0c0 \ - --hash=sha256:4502620722b453c2c6306fad392c515dcb804dfa9c6d3b90d8926a07a7a01109 \ - --hash=sha256:4d6e0ba155a1b3159551ac6b4551eb20028617e2e4bb71f2c61efed0756e6825 \ - --hash=sha256:5141ccc9dbd8cdc59d1e93e318d405477a940dc6ebadcb8d9f8da17d2812d353 \ - --hash=sha256:53cd2d776700bf0ed0e6fb203d716b041712ea4906479031cc5ac5421ecaa7d2 \ - --hash=sha256:56bcd9ba0adf16edb4e3e45b8b9346f5b3b2372402e953d54c84b345d0f691e0 \ - --hash=sha256:76dcb8f5c866f1537ccbaad01ebb3611890d281ef8d25e050d1cc3d90fba6b3d \ - --hash=sha256:77e22c33123ce11231ff2773d8905e20b45d77a69459def7481283b72a583955 \ - --hash=sha256:78f920a75c1dbcb5a48a495f384d73ceb41e437a966c318eb7e56f1c1ad1df3e \ - --hash=sha256:7da016a0dab1fcced89dfff8537033c5dc200015e14023368f3f4a69e39b8716 \ - --hash=sha256:8d80878cb40ebf88a48839ff7206ceb62e4b54327e0c2f9f15ee12edbd8b907e \ - --hash=sha256:8fdb4634040d1dbde7e0b373e19668cdb61c0ee8690d3b4064ac748d85365bca \ - --hash=sha256:93b1839d54b80a06a51a31b90d024a1770e250d00de57e7ae069bafba932f398 \ - --hash=sha256:9ddaf99e362ae4169f6a8b3508f3487264e0a1b1e58c0b07b86407bc9ecee831 \ - --hash=sha256:ad44569b0f508e046ffe85b4a547d5b68d1548fd90767df69449cc28021ee709 \ - --hash=sha256:ae694efefcb61317c79b2fa1caebc122060992408e389bb00889567e463a47f1 \ - --hash=sha256:b57cb8a4a8a8ffdaf0395326ef3b9c1aba36e58a421438fc04c002a1f511db63 \ - --hash=sha256:b73cda1326738eab5d60640ca0b87ac4e4db09a099423c41b59a5681917e8d1d \ - --hash=sha256:c30902f9b9da0d74668b6f71d7b57081a4879d9a5ea93d5922dbe15b15b3b24a \ - --hash=sha256:c3e45d004531330030f7d07abe4865bc17963b9989bc1941cebbf7224010fb82 \ - --hash=sha256:c7a5715b1f46e9852442f496c0df2f8c393cc8f293f5396d2c8d95cac852fb51 \ - --hash=sha256:c92d2b7c1a914ab2f66454961eeaf904f4fe7529b93ff537619d22c18b82d070 \ - --hash=sha256:cf61238811a75335751b4b17f8b221a35f93f2d57489296742adf98412d2a568 \ - --hash=sha256:d25f8fdbc6cc6561353c7a384d76295e6a85a4945115b8bc347855db150e8c77 \ - --hash=sha256:d49b14fcc9b12a52da8667587efa124a18e1a3eb63bbbcabf9882f4008d171d6 \ - --hash=sha256:ddaf38943dbb32333a182c894b6092a68b56c5e36d0c54ba3761d28119b15447 \ - --hash=sha256:ddc328c2a2daf2cf4bdc7bbc8a458dc4c840637223d4b8e01bce2168cc79fd23 \ - --hash=sha256:e350a887adb38ac65c93c2f395b60cf482baca61fd396ed8d6fd313dbcce6fac \ - --hash=sha256:efc9d039b6b8a36b182bc60774bb5d456b8ff9ec44cf97719f2f38bb1dcdd546 \ - --hash=sha256:f0481154c91725f7e7b729a535190388be6c7cbae3bbf0e793343ca386282312 \ - --hash=sha256:f4f2fea370361a90cb9330610a95303587eda9d1e69930dbbee9978eac1d5946 +httptools==0.6.4 \ + --hash=sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a \ + --hash=sha256:0e563e54979e97b6d13f1bbc05a96109923e76b901f786a5eae36e99c01237bd \ + --hash=sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2 \ + --hash=sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17 \ + --hash=sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8 \ + --hash=sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3 \ + --hash=sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5 \ + --hash=sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da \ + --hash=sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0 \ + --hash=sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721 \ + --hash=sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636 \ + --hash=sha256:40dc6a8e399e15ea525305a2ddba998b0af5caa2566bcd79dcbe8948181eeaff \ + --hash=sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0 \ + --hash=sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071 \ + --hash=sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c \ + --hash=sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4 \ + --hash=sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1 \ + --hash=sha256:703c346571fa50d2e9856a37d7cd9435a25e7fd15e236c397bf224afaa355fe9 \ + --hash=sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44 \ + --hash=sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083 \ + --hash=sha256:85797e37e8eeaa5439d33e556662cc370e474445d5fab24dcadc65a8ffb04003 \ + --hash=sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959 \ + --hash=sha256:94978a49b8f4569ad607cd4946b759d90b285e39c0d4640c6b36ca7a3ddf2efc \ + --hash=sha256:aafe0f1918ed07b67c1e838f950b1c1fabc683030477e60b335649b8020e1076 \ + --hash=sha256:ab9ba8dcf59de5181f6be44a77458e45a578fc99c31510b8c65b7d5acc3cf490 \ + --hash=sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660 \ + --hash=sha256:b799de31416ecc589ad79dd85a0b2657a8fe39327944998dea368c1d4c9e55e6 \ + --hash=sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c \ + --hash=sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50 \ + --hash=sha256:d1ffd262a73d7c28424252381a5b854c19d9de5f56f075445d33919a637e3547 \ + --hash=sha256:d3f0d369e7ffbe59c4b6116a44d6a8eb4783aae027f2c0b366cf0aa964185dba \ + --hash=sha256:d54efd20338ac52ba31e7da78e4a72570cf729fac82bc31ff9199bedf1dc7440 \ + --hash=sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988 \ + --hash=sha256:db353d22843cf1028f43c3651581e4bb49374d85692a85f95f7b9a130e1b2cab \ + --hash=sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970 \ + --hash=sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1 \ + --hash=sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2 \ + --hash=sha256:df959752a0c2748a65ab5387d08287abf6779ae9165916fe053e68ae1fbdc47f \ + --hash=sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81 \ + --hash=sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069 \ + --hash=sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975 \ + --hash=sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f \ + --hash=sha256:fc411e1c0a7dcd2f902c7c48cf079947a7e65b5485dea9decb82b9105ca71a43 # via uvicorn httpx==0.27.2 \ --hash=sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0 \ --hash=sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2 # via # gafaelfawr (pyproject.toml) + # python-schema-registry-client # safir idna==3.10 \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ @@ -758,10 +851,10 @@ idna==3.10 \ # httpx # requests # yarl -importlib-metadata==8.4.0 \ - --hash=sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1 \ - --hash=sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5 - # via opentelemetry-api +inflection==0.5.1 \ + --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ + --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 + # via dataclasses-avroschema iso8601==2.1.0 \ --hash=sha256:6b1d3829ee8921c4301998c909f7829fa9ed3cbdac0d3b16af2d743aed1ba8df \ --hash=sha256:aac4145c4dcb66ad8b648a02830f5e2ff6c24af20f4f482689be402db2429242 @@ -770,6 +863,14 @@ jinja2==3.1.4 \ --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \ --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d # via gafaelfawr (pyproject.toml) +jsonschema==4.23.0 \ + --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ + --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 + # via python-schema-registry-client +jsonschema-specifications==2024.10.1 \ + --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ + --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf + # via jsonschema kopf==1.37.2 \ --hash=sha256:aa7a5470dd7655adae1aebe8426fc050ce7f21e13d49a3b88ef209176527e28f \ --hash=sha256:f551db1772b0583e82d33bd1f95eec631000f686965500bb066ef3f5b47960a0 @@ -945,38 +1046,10 @@ multidict==6.1.0 \ # via # aiohttp # yarl -opentelemetry-api==1.27.0 \ - --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ - --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 - # via - # gafaelfawr (pyproject.toml) - # opentelemetry-exporter-otlp-proto-grpc - # opentelemetry-sdk - # opentelemetry-semantic-conventions -opentelemetry-exporter-otlp-proto-common==1.27.0 \ - --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ - --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a - # via opentelemetry-exporter-otlp-proto-grpc -opentelemetry-exporter-otlp-proto-grpc==1.27.0 \ - --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ - --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f - # via gafaelfawr (pyproject.toml) -opentelemetry-proto==1.27.0 \ - --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ - --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace - # via - # opentelemetry-exporter-otlp-proto-common - # opentelemetry-exporter-otlp-proto-grpc -opentelemetry-sdk==1.27.0 \ - --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ - --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f - # via - # gafaelfawr (pyproject.toml) - # opentelemetry-exporter-otlp-proto-grpc -opentelemetry-semantic-conventions==0.48b0 \ - --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ - --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f - # via opentelemetry-sdk +packaging==24.1 \ + --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ + --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 + # via aiokafka propcache==0.2.0 \ --hash=sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9 \ --hash=sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763 \ @@ -1083,24 +1156,23 @@ proto-plus==1.24.0 \ # via # google-api-core # google-cloud-firestore -protobuf==4.25.5 \ - --hash=sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41 \ - --hash=sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea \ - --hash=sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8 \ - --hash=sha256:7a183f592dc80aa7c8da7ad9e55091c4ffc9497b3054452d629bb85fa27c2a45 \ - --hash=sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584 \ - --hash=sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d \ - --hash=sha256:98d8d8aa50de6a2747efd9cceba361c9034050ecce3e09136f90de37ddba66e1 \ - --hash=sha256:abe32aad8561aa7cc94fc7ba4fdef646e576983edb94a73381b03c53728a626f \ - --hash=sha256:b0234dd5a03049e4ddd94b93400b67803c823cfc405689688f59b34e0742381a \ - --hash=sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173 \ - --hash=sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331 +protobuf==5.28.2 \ + --hash=sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132 \ + --hash=sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f \ + --hash=sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece \ + --hash=sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0 \ + --hash=sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f \ + --hash=sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0 \ + --hash=sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276 \ + --hash=sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7 \ + --hash=sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3 \ + --hash=sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36 \ + --hash=sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d # via # google-api-core # google-cloud-firestore # googleapis-common-protos # grpcio-status - # opentelemetry-proto # proto-plus pyasn1==0.6.1 \ --hash=sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629 \ @@ -1121,6 +1193,7 @@ pydantic==2.9.2 \ --hash=sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12 # via # gafaelfawr (pyproject.toml) + # fast-depends # fastapi # pydantic-settings # safir @@ -1220,7 +1293,9 @@ pydantic-core==2.23.4 \ pydantic-settings==2.5.2 \ --hash=sha256:2c912e55fd5794a59bf8c832b9de832dcfdf4778d79ff79b708744eed499a907 \ --hash=sha256:f90b139682bee4d2065273d5185d71d37ea46cfe57e1b5ae184fc6a0b2484ca0 - # via gafaelfawr (pyproject.toml) + # via + # gafaelfawr (pyproject.toml) + # safir pyjwt==2.9.0 \ --hash=sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850 \ --hash=sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c @@ -1230,7 +1305,9 @@ pyjwt==2.9.0 \ python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 - # via kubernetes-asyncio + # via + # dataclasses-avroschema + # kubernetes-asyncio python-dotenv==1.0.1 \ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a @@ -1245,6 +1322,10 @@ python-multipart==0.0.12 \ --hash=sha256:045e1f98d719c1ce085ed7f7e1ef9d8ccc8c02ba02b5566d5f7521410ced58cb \ --hash=sha256:43dcf96cf65888a9cd3423544dd0d75ac10f7aa0c3c28a175bbcd00c9ce1aebf # via gafaelfawr (pyproject.toml) +python-schema-registry-client==2.6.0 \ + --hash=sha256:a0688a9cd6e2a616a79fb46a6615c531cd5f9e2a5145f5c95932f792417731cb \ + --hash=sha256:e5495899c2bf4fd33bc6689a2068a3423dc94875677f3fd343b6e492a7877ba0 + # via safir pyyaml==6.0.2 \ --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ @@ -1308,17 +1389,128 @@ redis==5.1.1 \ --hash=sha256:f6c997521fedbae53387307c5d0bf784d9acc28d9f1d058abeac566ec4dbed72 \ --hash=sha256:f8ea06b7482a668c6475ae202ed8d9bcaa409f6e87fb77ed1043d912afd62e24 # via gafaelfawr (pyproject.toml) +referencing==0.35.1 \ + --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ + --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de + # via + # jsonschema + # jsonschema-specifications requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via google-api-core +rpds-py==0.20.0 \ + --hash=sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c \ + --hash=sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585 \ + --hash=sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5 \ + --hash=sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6 \ + --hash=sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef \ + --hash=sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2 \ + --hash=sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29 \ + --hash=sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318 \ + --hash=sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b \ + --hash=sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399 \ + --hash=sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739 \ + --hash=sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee \ + --hash=sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174 \ + --hash=sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a \ + --hash=sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344 \ + --hash=sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2 \ + --hash=sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03 \ + --hash=sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5 \ + --hash=sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22 \ + --hash=sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e \ + --hash=sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96 \ + --hash=sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91 \ + --hash=sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752 \ + --hash=sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075 \ + --hash=sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253 \ + --hash=sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee \ + --hash=sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad \ + --hash=sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5 \ + --hash=sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce \ + --hash=sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7 \ + --hash=sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b \ + --hash=sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8 \ + --hash=sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57 \ + --hash=sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3 \ + --hash=sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec \ + --hash=sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209 \ + --hash=sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921 \ + --hash=sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045 \ + --hash=sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074 \ + --hash=sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580 \ + --hash=sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7 \ + --hash=sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5 \ + --hash=sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3 \ + --hash=sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0 \ + --hash=sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24 \ + --hash=sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139 \ + --hash=sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db \ + --hash=sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc \ + --hash=sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789 \ + --hash=sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f \ + --hash=sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2 \ + --hash=sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c \ + --hash=sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232 \ + --hash=sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6 \ + --hash=sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c \ + --hash=sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29 \ + --hash=sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489 \ + --hash=sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94 \ + --hash=sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751 \ + --hash=sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2 \ + --hash=sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda \ + --hash=sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9 \ + --hash=sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51 \ + --hash=sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c \ + --hash=sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8 \ + --hash=sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989 \ + --hash=sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511 \ + --hash=sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1 \ + --hash=sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2 \ + --hash=sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150 \ + --hash=sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c \ + --hash=sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965 \ + --hash=sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f \ + --hash=sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58 \ + --hash=sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b \ + --hash=sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f \ + --hash=sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d \ + --hash=sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821 \ + --hash=sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de \ + --hash=sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121 \ + --hash=sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855 \ + --hash=sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272 \ + --hash=sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60 \ + --hash=sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02 \ + --hash=sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1 \ + --hash=sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140 \ + --hash=sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879 \ + --hash=sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940 \ + --hash=sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364 \ + --hash=sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4 \ + --hash=sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e \ + --hash=sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420 \ + --hash=sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5 \ + --hash=sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24 \ + --hash=sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c \ + --hash=sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf \ + --hash=sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f \ + --hash=sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e \ + --hash=sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab \ + --hash=sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08 \ + --hash=sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92 \ + --hash=sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a \ + --hash=sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8 + # via + # jsonschema + # referencing rsa==4.9 \ --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 # via google-auth -safir==6.4.0 \ - --hash=sha256:ba7af071eab0d198e6e15a2117028566f3f4237e02e2278e8bfc2633a7c68228 \ - --hash=sha256:f38c3f1d7d76d304984b572288826510e5c7a0e1f965b2eabdd7f3bace07c48a +safir @ git+https://github.com/lsst-sqre/safir@242c68f05b74b6d3460334e63d4c8b31845b359d#subdirectory=safir # via gafaelfawr (pyproject.toml) safir-logging==6.4.0 \ --hash=sha256:4031a430d738b8fe5bfd29125dce6cbf4e4949879307ba4146648afa3d24cd0a \ @@ -1337,36 +1529,63 @@ sniffio==1.3.1 \ # anyio # httpx sqlalchemy==2.0.36 \ + --hash=sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763 \ --hash=sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436 \ + --hash=sha256:07b441f7d03b9a66299ce7ccf3ef2900abc81c0db434f42a5694a37bd73870f2 \ --hash=sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588 \ --hash=sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e \ --hash=sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959 \ --hash=sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d \ --hash=sha256:28120ef39c92c2dd60f2721af9328479516844c6b550b077ca450c7d7dc68575 \ + --hash=sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908 \ --hash=sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8 \ + --hash=sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8 \ + --hash=sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545 \ --hash=sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7 \ --hash=sha256:4557e1f11c5f653ebfdd924f3f9d5ebfc718283b0b9beebaa5dd6b77ec290971 \ + --hash=sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855 \ --hash=sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c \ + --hash=sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71 \ + --hash=sha256:50aae840ebbd6cdd41af1c14590e5741665e5272d2fee999306673a1bb1fdb4d \ + --hash=sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb \ + --hash=sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72 \ --hash=sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f \ + --hash=sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5 \ + --hash=sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346 \ + --hash=sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24 \ --hash=sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e \ --hash=sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5 \ + --hash=sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08 \ --hash=sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793 \ --hash=sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88 \ + --hash=sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686 \ + --hash=sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b \ --hash=sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2 \ --hash=sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28 \ + --hash=sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d \ --hash=sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5 \ --hash=sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a \ --hash=sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a \ + --hash=sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3 \ + --hash=sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf \ --hash=sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5 \ + --hash=sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef \ + --hash=sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689 \ --hash=sha256:b81ee3d84803fd42d0b154cb6892ae57ea6b7c55d8359a02379965706c7efe6c \ + --hash=sha256:be9812b766cad94a25bc63bec11f88c4ad3629a0cec1cd5d4ba48dc23860486b \ --hash=sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07 \ --hash=sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa \ --hash=sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06 \ --hash=sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1 \ + --hash=sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff \ + --hash=sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa \ --hash=sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687 \ + --hash=sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4 \ --hash=sha256:f942a799516184c855e1a32fbc7b29d7e571b52612647866d4ec1c3242578fcb \ --hash=sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44 \ - --hash=sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e + --hash=sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c \ + --hash=sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e \ + --hash=sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53 # via # gafaelfawr (pyproject.toml) # alembic @@ -1389,10 +1608,12 @@ typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via + # aiokafka # alembic + # dataclasses-avroschema # fastapi + # faststream # kopf - # opentelemetry-sdk # pydantic # pydantic-core # sqlalchemy @@ -1622,179 +1843,87 @@ websockets==13.1 \ --hash=sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee \ --hash=sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6 # via uvicorn -wrapt==1.16.0 \ - --hash=sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc \ - --hash=sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81 \ - --hash=sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 \ - --hash=sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e \ - --hash=sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca \ - --hash=sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0 \ - --hash=sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb \ - --hash=sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487 \ - --hash=sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40 \ - --hash=sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c \ - --hash=sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060 \ - --hash=sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202 \ - --hash=sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41 \ - --hash=sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9 \ - --hash=sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b \ - --hash=sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664 \ - --hash=sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d \ - --hash=sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362 \ - --hash=sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00 \ - --hash=sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc \ - --hash=sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1 \ - --hash=sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267 \ - --hash=sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956 \ - --hash=sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966 \ - --hash=sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 \ - --hash=sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228 \ - --hash=sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72 \ - --hash=sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d \ - --hash=sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292 \ - --hash=sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0 \ - --hash=sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0 \ - --hash=sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36 \ - --hash=sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c \ - --hash=sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5 \ - --hash=sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f \ - --hash=sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73 \ - --hash=sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b \ - --hash=sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2 \ - --hash=sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593 \ - --hash=sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39 \ - --hash=sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 \ - --hash=sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf \ - --hash=sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf \ - --hash=sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 \ - --hash=sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c \ - --hash=sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c \ - --hash=sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f \ - --hash=sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440 \ - --hash=sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465 \ - --hash=sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136 \ - --hash=sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b \ - --hash=sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8 \ - --hash=sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3 \ - --hash=sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8 \ - --hash=sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6 \ - --hash=sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e \ - --hash=sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f \ - --hash=sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c \ - --hash=sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e \ - --hash=sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8 \ - --hash=sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2 \ - --hash=sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020 \ - --hash=sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35 \ - --hash=sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d \ - --hash=sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3 \ - --hash=sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537 \ - --hash=sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809 \ - --hash=sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d \ - --hash=sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a \ - --hash=sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4 - # via deprecated -yarl==1.15.2 \ - --hash=sha256:0545de8c688fbbf3088f9e8b801157923be4bf8e7b03e97c2ecd4dfa39e48e0e \ - --hash=sha256:076b1ed2ac819933895b1a000904f62d615fe4533a5cf3e052ff9a1da560575c \ - --hash=sha256:0afad2cd484908f472c8fe2e8ef499facee54a0a6978be0e0cff67b1254fd747 \ - --hash=sha256:0ccaa1bc98751fbfcf53dc8dfdb90d96e98838010fc254180dd6707a6e8bb179 \ - --hash=sha256:0d3105efab7c5c091609abacad33afff33bdff0035bece164c98bcf5a85ef90a \ - --hash=sha256:0e1af74a9529a1137c67c887ed9cde62cff53aa4d84a3adbec329f9ec47a3936 \ - --hash=sha256:136f9db0f53c0206db38b8cd0c985c78ded5fd596c9a86ce5c0b92afb91c3a19 \ - --hash=sha256:156ececdf636143f508770bf8a3a0498de64da5abd890c7dbb42ca9e3b6c05b8 \ - --hash=sha256:15c87339490100c63472a76d87fe7097a0835c705eb5ae79fd96e343473629ed \ - --hash=sha256:1695497bb2a02a6de60064c9f077a4ae9c25c73624e0d43e3aa9d16d983073c2 \ - --hash=sha256:173563f3696124372831007e3d4b9821746964a95968628f7075d9231ac6bb33 \ - --hash=sha256:173866d9f7409c0fb514cf6e78952e65816600cb888c68b37b41147349fe0057 \ - --hash=sha256:23ec1d3c31882b2a8a69c801ef58ebf7bae2553211ebbddf04235be275a38548 \ - --hash=sha256:243fbbbf003754fe41b5bdf10ce1e7f80bcc70732b5b54222c124d6b4c2ab31c \ - --hash=sha256:28c6cf1d92edf936ceedc7afa61b07e9d78a27b15244aa46bbcd534c7458ee1b \ - --hash=sha256:2aa738e0282be54eede1e3f36b81f1e46aee7ec7602aa563e81e0e8d7b67963f \ - --hash=sha256:2cf441c4b6e538ba0d2591574f95d3fdd33f1efafa864faa077d9636ecc0c4e9 \ - --hash=sha256:30c3ff305f6e06650a761c4393666f77384f1cc6c5c0251965d6bfa5fbc88f7f \ - --hash=sha256:31561a5b4d8dbef1559b3600b045607cf804bae040f64b5f5bca77da38084a8a \ - --hash=sha256:32b66be100ac5739065496c74c4b7f3015cef792c3174982809274d7e51b3e04 \ - --hash=sha256:3433da95b51a75692dcf6cc8117a31410447c75a9a8187888f02ad45c0a86c50 \ - --hash=sha256:34a2d76a1984cac04ff8b1bfc939ec9dc0914821264d4a9c8fd0ed6aa8d4cfd2 \ - --hash=sha256:353665775be69bbfc6d54c8d134bfc533e332149faeddd631b0bc79df0897f46 \ - --hash=sha256:38d0124fa992dbacd0c48b1b755d3ee0a9f924f427f95b0ef376556a24debf01 \ - --hash=sha256:3c56ec1eacd0a5d35b8a29f468659c47f4fe61b2cab948ca756c39b7617f0aa5 \ - --hash=sha256:3db817b4e95eb05c362e3b45dafe7144b18603e1211f4a5b36eb9522ecc62bcf \ - --hash=sha256:3e52474256a7db9dcf3c5f4ca0b300fdea6c21cca0148c8891d03a025649d935 \ - --hash=sha256:416f2e3beaeae81e2f7a45dc711258be5bdc79c940a9a270b266c0bec038fb84 \ - --hash=sha256:435aca062444a7f0c884861d2e3ea79883bd1cd19d0a381928b69ae1b85bc51d \ - --hash=sha256:4388c72174868884f76affcdd3656544c426407e0043c89b684d22fb265e04a5 \ - --hash=sha256:43ebdcc120e2ca679dba01a779333a8ea76b50547b55e812b8b92818d604662c \ - --hash=sha256:458c0c65802d816a6b955cf3603186de79e8fdb46d4f19abaec4ef0a906f50a7 \ - --hash=sha256:533a28754e7f7439f217550a497bb026c54072dbe16402b183fdbca2431935a9 \ - --hash=sha256:553dad9af802a9ad1a6525e7528152a015b85fb8dbf764ebfc755c695f488367 \ - --hash=sha256:5838f2b79dc8f96fdc44077c9e4e2e33d7089b10788464609df788eb97d03aad \ - --hash=sha256:5b48388ded01f6f2429a8c55012bdbd1c2a0c3735b3e73e221649e524c34a58d \ - --hash=sha256:5bc0df728e4def5e15a754521e8882ba5a5121bd6b5a3a0ff7efda5d6558ab3d \ - --hash=sha256:63eab904f8630aed5a68f2d0aeab565dcfc595dc1bf0b91b71d9ddd43dea3aea \ - --hash=sha256:66f629632220a4e7858b58e4857927dd01a850a4cef2fb4044c8662787165cf7 \ - --hash=sha256:670eb11325ed3a6209339974b276811867defe52f4188fe18dc49855774fa9cf \ - --hash=sha256:69d5856d526802cbda768d3e6246cd0d77450fa2a4bc2ea0ea14f0d972c2894b \ - --hash=sha256:6e840553c9c494a35e449a987ca2c4f8372668ee954a03a9a9685075228e5036 \ - --hash=sha256:711bdfae4e699a6d4f371137cbe9e740dc958530cb920eb6f43ff9551e17cfbc \ - --hash=sha256:74abb8709ea54cc483c4fb57fb17bb66f8e0f04438cff6ded322074dbd17c7ec \ - --hash=sha256:75119badf45f7183e10e348edff5a76a94dc19ba9287d94001ff05e81475967b \ - --hash=sha256:766dcc00b943c089349d4060b935c76281f6be225e39994c2ccec3a2a36ad627 \ - --hash=sha256:78e6fdc976ec966b99e4daa3812fac0274cc28cd2b24b0d92462e2e5ef90d368 \ - --hash=sha256:81dadafb3aa124f86dc267a2168f71bbd2bfb163663661ab0038f6e4b8edb810 \ - --hash=sha256:82d5161e8cb8f36ec778fd7ac4d740415d84030f5b9ef8fe4da54784a1f46c94 \ - --hash=sha256:833547179c31f9bec39b49601d282d6f0ea1633620701288934c5f66d88c3e50 \ - --hash=sha256:856b7f1a7b98a8c31823285786bd566cf06226ac4f38b3ef462f593c608a9bd6 \ - --hash=sha256:8657d3f37f781d987037f9cc20bbc8b40425fa14380c87da0cb8dfce7c92d0fb \ - --hash=sha256:93bed8a8084544c6efe8856c362af08a23e959340c87a95687fdbe9c9f280c8b \ - --hash=sha256:954dde77c404084c2544e572f342aef384240b3e434e06cecc71597e95fd1ce7 \ - --hash=sha256:98f68df80ec6ca3015186b2677c208c096d646ef37bbf8b49764ab4a38183931 \ - --hash=sha256:99e12d2bf587b44deb74e0d6170fec37adb489964dbca656ec41a7cd8f2ff178 \ - --hash=sha256:9a13a07532e8e1c4a5a3afff0ca4553da23409fad65def1b71186fb867eeae8d \ - --hash=sha256:9c1e3ff4b89cdd2e1a24c214f141e848b9e0451f08d7d4963cb4108d4d798f1f \ - --hash=sha256:9ce2e0f6123a60bd1a7f5ae3b2c49b240c12c132847f17aa990b841a417598a2 \ - --hash=sha256:9fcda20b2de7042cc35cf911702fa3d8311bd40055a14446c1e62403684afdc5 \ - --hash=sha256:a32d58f4b521bb98b2c0aa9da407f8bd57ca81f34362bcb090e4a79e9924fefc \ - --hash=sha256:a39c36f4218a5bb668b4f06874d676d35a035ee668e6e7e3538835c703634b84 \ - --hash=sha256:a5cafb02cf097a82d74403f7e0b6b9df3ffbfe8edf9415ea816314711764a27b \ - --hash=sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172 \ - --hash=sha256:a880372e2e5dbb9258a4e8ff43f13888039abb9dd6d515f28611c54361bc5644 \ - --hash=sha256:ace4cad790f3bf872c082366c9edd7f8f8f77afe3992b134cfc810332206884f \ - --hash=sha256:af8ff8d7dc07ce873f643de6dfbcd45dc3db2c87462e5c387267197f59e6d776 \ - --hash=sha256:b47a6000a7e833ebfe5886b56a31cb2ff12120b1efd4578a6fcc38df16cc77bd \ - --hash=sha256:b71862a652f50babab4a43a487f157d26b464b1dedbcc0afda02fd64f3809d04 \ - --hash=sha256:b7f227ca6db5a9fda0a2b935a2ea34a7267589ffc63c8045f0e4edb8d8dcf956 \ - --hash=sha256:bc8936d06cd53fddd4892677d65e98af514c8d78c79864f418bbf78a4a2edde4 \ - --hash=sha256:bed1b5dbf90bad3bfc19439258c97873eab453c71d8b6869c136346acfe497e7 \ - --hash=sha256:c45817e3e6972109d1a2c65091504a537e257bc3c885b4e78a95baa96df6a3f8 \ - --hash=sha256:c68e820879ff39992c7f148113b46efcd6ec765a4865581f2902b3c43a5f4bbb \ - --hash=sha256:c77494a2f2282d9bbbbcab7c227a4d1b4bb829875c96251f66fb5f3bae4fb053 \ - --hash=sha256:c998d0558805860503bc3a595994895ca0f7835e00668dadc673bbf7f5fbfcbe \ - --hash=sha256:ccad2800dfdff34392448c4bf834be124f10a5bc102f254521d931c1c53c455a \ - --hash=sha256:cd126498171f752dd85737ab1544329a4520c53eed3997f9b08aefbafb1cc53b \ - --hash=sha256:ce44217ad99ffad8027d2fde0269ae368c86db66ea0571c62a000798d69401fb \ - --hash=sha256:d1ac2bc069f4a458634c26b101c2341b18da85cb96afe0015990507efec2e417 \ - --hash=sha256:d417a4f6943112fae3924bae2af7112562285848d9bcee737fc4ff7cbd450e6c \ - --hash=sha256:d538df442c0d9665664ab6dd5fccd0110fa3b364914f9c85b3ef9b7b2e157980 \ - --hash=sha256:ded1b1803151dd0f20a8945508786d57c2f97a50289b16f2629f85433e546d47 \ - --hash=sha256:e2e93b88ecc8f74074012e18d679fb2e9c746f2a56f79cd5e2b1afcf2a8a786b \ - --hash=sha256:e4ca3b9f370f218cc2a0309542cab8d0acdfd66667e7c37d04d617012485f904 \ - --hash=sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8 \ - --hash=sha256:e52f77a0cd246086afde8815039f3e16f8d2be51786c0a39b57104c563c5cbb0 \ - --hash=sha256:eaea112aed589131f73d50d570a6864728bd7c0c66ef6c9154ed7b59f24da611 \ - --hash=sha256:ed20a4bdc635f36cb19e630bfc644181dd075839b6fc84cac51c0f381ac472e2 \ - --hash=sha256:eedc3f247ee7b3808ea07205f3e7d7879bc19ad3e6222195cd5fbf9988853e4d \ - --hash=sha256:f0e1844ad47c7bd5d6fa784f1d4accc5f4168b48999303a868fe0f8597bde715 \ - --hash=sha256:f4fe99ce44128c71233d0d72152db31ca119711dfc5f2c82385ad611d8d7f897 \ - --hash=sha256:f8cfd847e6b9ecf9f2f2531c8427035f291ec286c0a4944b0a9fce58c6446046 \ - --hash=sha256:f9ca0e6ce7774dc7830dc0cc4bb6b3eec769db667f230e7c770a628c1aa5681b \ - --hash=sha256:fa2bea05ff0a8fb4d8124498e00e02398f06d23cdadd0fe027d84a3f7afde31e \ - --hash=sha256:fbbb63bed5fcd70cd3dd23a087cd78e4675fb5a2963b8af53f945cbbca79ae16 \ - --hash=sha256:fbda058a9a68bec347962595f50546a8a4a34fd7b0654a7b9697917dc2bf810d \ - --hash=sha256:ffd591e22b22f9cb48e472529db6a47203c41c2c5911ff0a52e85723196c0d75 +yarl==1.15.4 \ + --hash=sha256:07019a9de859c5a29916defd1e8c7557de6491a10bf50c49ff5284e6aedf5313 \ + --hash=sha256:0c96eaa30030e1cfafe533f3da8983812281235b7c50ef2a6c78ceca7aea1a0b \ + --hash=sha256:0d0f16c87c62b7a94b389ddf6a8c9d081265d788875c39f3a80108c4856eea7b \ + --hash=sha256:0e07e4b17b648c880e8e42bf1ac0a730bde114961646ae1c2ec4433f0c11ca94 \ + --hash=sha256:1005921b30f4f39bf893946df6173567ff650307babb5ec04bbf64342a1f62c1 \ + --hash=sha256:115346433fad2084ee3a1a925ccc0659990aa42e208ca54c278830a150a3caf3 \ + --hash=sha256:11b207061f28b4b6d980239b22ab0ecfadc47846b5a3b8e79f27fcc019d02cf9 \ + --hash=sha256:1ceb677fb583971351627eac70eec6763fbc889761828da7a276681b5e39742d \ + --hash=sha256:1e7468f31de61a82817f918743e5229fce774f73fad58487cdf88eef4f06d864 \ + --hash=sha256:20acf84bd1ce530065f8e957e4a5878fda4bc5f18cb02659828210e1519de54e \ + --hash=sha256:21fabe58042f3e567b4edc75b2cf44cea02f228e41ac09d73de126bf685fe883 \ + --hash=sha256:3198da7d7c34e29fc8c823e0c3ce6c7274aac35760de557c2017489c7d98fc5a \ + --hash=sha256:35a6b69cc44bda002705d6138346bf0a0234cbb7c26c3bf192513eb946aee6f9 \ + --hash=sha256:3896bf15284dd23acab1f2e7fceb350d8da6f6f2436b922f7ec6b3de685d34ca \ + --hash=sha256:3a79c0a8bbb046add85663af85e9993b691bf20c2a109518bd35e0ce77edfe42 \ + --hash=sha256:4076bfd8f1621449b19b9826848ed51bf0f2d1d38e82647c312c0730d8778903 \ + --hash=sha256:40c18f96696549e73b92dc12619f07019cbf5faefc1612608f967c144816e493 \ + --hash=sha256:46491b3e058de7b484e1c9fb20aa8441f06d6c9a18395d711c1c2a9ad6707d6a \ + --hash=sha256:48334a6c8afee93097eb17c0a094234dac2d88da076c8cf372e09e2a5dcc4b66 \ + --hash=sha256:4851618679ca70b863ba2e7109be5f09f8fd7715ec505bd42e5a947dcfde3a45 \ + --hash=sha256:49190eb2ece70313742b0ea51520340288a059674da1f39eefb589d598d9453e \ + --hash=sha256:49f886e8dcf591275c6e20915b516fd81647857566b0c0158c52df1e468849c9 \ + --hash=sha256:4a706db0c3b7e4578ff34ed2b1d2507b08fd491346ffc64468786fdf1151d938 \ + --hash=sha256:4ac85e760543129a1912a82438fc8075223e35eaa2d457d61cd83c27d00d17be \ + --hash=sha256:4f66a0eda48844508736e47ed476d8fdd7cdbf16a4053b5d439509a25f708504 \ + --hash=sha256:4feab2dcb725eb5b4835207ecf3d370ff7ce930b253cba5e681646cb80d64c2c \ + --hash=sha256:527c68f48a91d953691291d3bce0209293aa5ad13ff05286ddb506791c331818 \ + --hash=sha256:551205388d1da18a9975302c9a274ba24788f53bb9bb86187496ebf9e938916e \ + --hash=sha256:590e2d733a82ecf004c5c531cbef0d6be328e93adec960024eb213f10cb9503e \ + --hash=sha256:59db8e6888d5302b8dbca0c1026ddabe99d81d67cdc101941519e13ffc9050fe \ + --hash=sha256:60165b8bc260f453321004b193770a66cc1b1a5c57c07d4b8dcc96839e7ad578 \ + --hash=sha256:65a0168691373e08d869d48b62c8bed0af0cdaef19c76e11ad73b43901bbdb5a \ + --hash=sha256:65e0467f90f2acf3bc83bbfeedece8f1fd84df8add1a54e9600ed7b7b5debdb0 \ + --hash=sha256:691a3b498fdebef63308e8967bb598cfd326c56d628da82b799dd181bace4503 \ + --hash=sha256:69f628d2da1489b27959f4d63fdb326781fe484944dce94abbf919e416c54abe \ + --hash=sha256:6e100c6c7d9e9d469009fd55cc4d7ad168d67d40758865c50da713f7ada491e5 \ + --hash=sha256:6f8136bde8dfa4477c6a85c79a366581b4a505b51a52b669318fb631d3f4f638 \ + --hash=sha256:76259901cf1ac3db65e7e6dff04775b626d0715f9b51d92b447351144c756a82 \ + --hash=sha256:7694f109867ee428c21b85ae19fd31d164c691eb45cc95c561cfdeba237a12e3 \ + --hash=sha256:77390496f2f32437a721c854897f889abefae0f3009daf90a2f703508d96c920 \ + --hash=sha256:787532f00543a21b8f4ec3050b4e01b8fe437797903c0156a0b03dfca5e1ba6c \ + --hash=sha256:7d5226c70af3ad9569ccc4ccc04ab65be79eeb22c87d7ae789c89e62ef76bbd6 \ + --hash=sha256:83e7154aa0d17f5c93d27ac01088fd9ab6673e7bab1acbd07cd7a865b980c045 \ + --hash=sha256:84937d00e2ea03616c40977de20189fa13a9213e5744a3c6afa0e7dd9141d69c \ + --hash=sha256:8721f8bedaa722c3c483cc06a1399cbfdb280eadf443aa5d324b0203cef2a75f \ + --hash=sha256:8b569f4f511b59518ba6719feb5b8bf0a5d4115e6ac903c89e10a8a9ac656017 \ + --hash=sha256:8de5328d91859b461899497980d4cc8269e84e2d18640f6ac643886fda9000bf \ + --hash=sha256:9060589d0acad1fca048861fa9ee3e8ed060f67894fa885969648ab6e9e99a54 \ + --hash=sha256:98d8dc1e8133f86d916125deca9780d791b22645f0d62bafe1452d1cd5eac631 \ + --hash=sha256:9fe17744d60fc404ac61f824118e1e15ce3c2e92eced9b8e22f3c7847acafbf2 \ + --hash=sha256:a0c5e271058d148d730219ca4f33c5d841c6bd46e05b0da60fea7b516906ccd3 \ + --hash=sha256:ab79cc13307065a0b3ef087f09f0509996fc605d35d6642bb28e5d85b2648e1e \ + --hash=sha256:ab9ccf26cb3fa32747ba2a637a189d2d42386a2fc4afc10dbc7f85922dd23b0f \ + --hash=sha256:adb6b5d07d17c32f9d34c9dd4a693637a72323cfcb1f8a52d57033ab2dd21e99 \ + --hash=sha256:b2bdb038b3f5c284e3919218c580dedc95f592c417a358361450b9519b22f7a8 \ + --hash=sha256:c23a442973dba3646811c284fce3dddd7fe5c2bd674ac73a122198e8218d6115 \ + --hash=sha256:c30115cecaf25fdcb67cc71c669d08425207f62d7a2f6d5416057c1460529216 \ + --hash=sha256:c33ea7c55a73be343f02361795caf52a187357ea07708fb1cae6661ee1d689c8 \ + --hash=sha256:ccbeaf5b18b173b9d78e332e017b30ba8bedcf03cdce1d13490b82a3f421bc98 \ + --hash=sha256:ccd6774aa7bebdf9ca608bb0839318757a71b8e0d2cf7b10c002bc8790bd343e \ + --hash=sha256:d886de2ea81f513ba2d6820451d33b767a97c37867ba688d42e164b2dbca1362 \ + --hash=sha256:db64a20e78969fc66665d2e5fc96cb4f4dc80f2137d8fed4b5a650ad569bb60f \ + --hash=sha256:db818e33599f7b2e4c6507f2b2c24f45ff539a1b6e4e09163bb6f3cfb4616ca7 \ + --hash=sha256:dce1c56beef74d9c799a6ed94001693232a1402138292353a8ce302b64f457d9 \ + --hash=sha256:de38b0b5b86e57efb129d179854e78b65cb8e294a8c75560877869c43aa2415a \ + --hash=sha256:de479e30abd2dfd49fdad3bd6953f2d930a45380be5143c0c9f7a1215cffc8cc \ + --hash=sha256:df09c80f4bc2bc2efde309af383c3fe8fd8c51fe0519edb350b9c9e0af43ffa4 \ + --hash=sha256:df6b254e55c8ac2362afaa651e3e53453aa19a095570792346245773b434176e \ + --hash=sha256:e58c5d07b1f78dd4cb180c5b3b82465cd281aaeee8aafea0e5d72a4b97922cb1 \ + --hash=sha256:e5cc288111c450c0a54a74475591b206d3b1cb47dc71bb6200f6be8b1337184c \ + --hash=sha256:eee724176b5bc50ee64905f559345448119b860a30b9489bd7a073f61baf925f \ + --hash=sha256:f16d1940c0cbc342f1d29d6212a006d172be616d2942c5c41966e8a3ce4c3be1 \ + --hash=sha256:f25906e4a72d9833e81717c39a39dee7297ff5cb44957d06d177a2ab8ef2ef7f \ + --hash=sha256:f3294ce265011547630a59c20085fcb6af8cc5fa1fa44a203251f7d86cd5d913 \ + --hash=sha256:f337486742c700b102d640830aab3faf2848bed966b479a39e6783edd4ab1c6c \ + --hash=sha256:f51c9d173e5fa4b12d06ddca09a41cabbdeb660471dbe55432423eec095709ab \ + --hash=sha256:f68025d6ba1816428b7de615c80f61cb03d5b7061158d4ced7696657a64aa59c \ + --hash=sha256:f74f6ffdc633aefecbc80282242a5395058db9d1247fa7dd2f070ef84dc82583 \ + --hash=sha256:f864b412557e69a6b953d62c01a0ed0ee342666298aa7f2a29af526bfa80f6e9 \ + --hash=sha256:f923e94e93a37fd990e8336e0b9bedea533e7cbed14e0c572bf9357ef2a70681 \ + --hash=sha256:faa3dd7f4620ab5e5da7a0789d0aac78a9ad0376f102409d442ec5a4179e200a \ + --hash=sha256:fd2bb86f40962d53a91def15a2f7684c62e081a7b96ec74ed0259c34b15973b9 # via aiohttp -zipp==3.20.2 \ - --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ - --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 - # via importlib-metadata diff --git a/requirements/tox.txt b/requirements/tox.txt index a9b054b0a..273a9dd39 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -160,6 +160,7 @@ packaging==24.1 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via # -c requirements/dev.txt + # -c requirements/main.txt # pyproject-api # tox # tox-uv @@ -209,9 +210,9 @@ requests==2.32.3 \ # -c requirements/dev.txt # -c requirements/main.txt # docker -tox==4.22.0 \ - --hash=sha256:03734d9a9ac138cd1a898a372fb1b8079e2728618ae06dc37cbf3686cfb56eea \ - --hash=sha256:acc6c627cb3316585238d55d2b633e132fea1bdb01b9d93b56bce7caea6ae73d +tox==4.23.0 \ + --hash=sha256:46da40afb660e46238c251280eb910bdaf00b390c7557c8e4bb611f422e9db12 \ + --hash=sha256:a6bd7d54231d755348d3c3a7b450b5bf6563833716d1299a1619587a1b77a3bf # via # -r requirements/tox.in # tox-docker @@ -232,25 +233,25 @@ urllib3==2.2.3 \ # -c requirements/main.txt # docker # requests -uv==0.4.22 \ - --hash=sha256:062a57ac3aab9a7d41e1b6a66948d563bf47478c719894661ea2c5ed6485a146 \ - --hash=sha256:0904c141f9fd7088d7837fb7ac5e43191236ed9cf8edf824ed838bdc77da7406 \ - --hash=sha256:0ff4ff91a25ed633f4d2556777e1b317262c01f71e8f72dfbc540e97e7eb5392 \ - --hash=sha256:455538b910db65f20a70cf806c5e65cc1d80ea7f40a116ba1c3d4bd1dab933d9 \ - --hash=sha256:48232daa35ebd3e963eea236cf33915a8b0c8a3673d5da35d764f8b1fec0b1b2 \ - --hash=sha256:52605e291f7ab1daca682b7a92b926c2f70e1fc86caaa37cbd56b64587730ea2 \ - --hash=sha256:527d785dafa5bf8fa4aba42188787a4b25c11d005a5f4bd8afda6e8c2c231e1b \ - --hash=sha256:63156e306f860d9fa2bb1d7c9af30053b88276004b2790cd9bbf20cc83ce988b \ - --hash=sha256:7041bf9d2d5d391cebca7778207eb88a96537ff2e93df2ff9f41d6c4057252c3 \ - --hash=sha256:71f3faaa94f60d362a6984fdf7675d6d2d244139de91a7d46e2367caf950951e \ - --hash=sha256:765dac79e5c8e2924efbd4663d4e03f5d7689f1baa98223b298fe4292610a25a \ - --hash=sha256:7be7adf47158c456031b2b78742a432260b5c22e9a86784fa57e7a208b0c3206 \ - --hash=sha256:956c4f0a9eddb8e18003bc39d114c78f6d6b4ba2683a262af043770abee44f2e \ - --hash=sha256:9cf96ddcb6ea2743e4c44fa22b08a4f2fd09cc9c5e228e8ab04b0cd08371c868 \ - --hash=sha256:af70ea49389397d0f6ff43827f73e0e71db0fc45cdf50c7dcff8318d726c8224 \ - --hash=sha256:c96eb12d1bdb1a826cba3c38273604629ac51e723d705aed17ae282650d030f0 \ - --hash=sha256:d9a242b3360c3a62e248053b3a6f618dc59cb5c56f4e30748433a19a002e4bf5 \ - --hash=sha256:e18c42cc99bc2a3f91d43aeb2df61a6d259114fca50dd3818879e9ee12064f7f +uv==0.4.23 \ + --hash=sha256:14a38cb947acffe6bb6c9e4922c2ac3b2d7ec4353e28f59d8fd1f10bc695cf73 \ + --hash=sha256:1663219972c92cdd2a24ab0437284c4fcaac483814e3399e1cafa231c47b0c46 \ + --hash=sha256:1fc6c3b475eaf8057a9592c23d495293f8837b13a9f564f46fccfca4ff7fc0a8 \ + --hash=sha256:23269724349a1831881319e5f2854a5b8260f444ecb2528ac44ffe039a091ac4 \ + --hash=sha256:2f19527992f7d557fd3faec281b43005f1e8c9ebdf07f90bef229d510e002ca0 \ + --hash=sha256:59f1c41baa13646ac64b780b801afd0a451173d38eca03cfd6f98802bfc296b1 \ + --hash=sha256:677b53b1fdbb7211dbe92f7adf8e543fa56061e5edea0ceb724c36ce1df5f35c \ + --hash=sha256:7065dabbb58c44525516bc807bcc279867bd81ae548afa58375bada23db1afd7 \ + --hash=sha256:8a416cb239e6be6c246da6803bf957a32a81fed21fda2fb32d012e5caa1e0b4f \ + --hash=sha256:8b09215f5d388610bc35352dd5938f19a0d7a70a0ab98b9db00d5cd26c751d57 \ + --hash=sha256:8f1a74620f9a7180e3a263bcbf6efb30630819cbd100d266c1760007fcd151c3 \ + --hash=sha256:a403d1231102302a484aab871b1adf42df5623712ce3705a7cb23c41f79611c8 \ + --hash=sha256:a57d00795900550e358d10aff4f56347ee228bcbe4b9f870fb3b7e74c82f634d \ + --hash=sha256:a9f35ee982170590bb45921af18043b6ac379d9019f46c435bcb8293111c9e80 \ + --hash=sha256:ae11724cd14841627a504801949db0f3dfd5060bf9c5861aa1a4eba5d69b2b3f \ + --hash=sha256:c62292ed01170e72157e74e2f24cc535445fc6fbad54b09699344c66393fe41d \ + --hash=sha256:cbb9754f18d0796337a1756e628f0faa74c215ffb139a35bf490ab07fa626ca8 \ + --hash=sha256:f09efd74a3510b797a01ca8e56a007da7d7210b2620d53d67f425324ef079dfb # via tox-uv virtualenv==20.26.6 \ --hash=sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48 \ diff --git a/src/gafaelfawr/cli.py b/src/gafaelfawr/cli.py index b47352f0c..d5c235d0b 100644 --- a/src/gafaelfawr/cli.py +++ b/src/gafaelfawr/cli.py @@ -28,10 +28,10 @@ is_database_initialized, ) from .dependencies.config import config_dependency +from .events import StateEvents from .factory import Factory from .keypair import RSAKeyPair from .main import create_openapi -from .metrics import StateMetrics from .models.token import Token from .schema import Base @@ -261,10 +261,12 @@ async def maintenance(*, config_path: Path | None) -> None: await token_service.expire_tokens() logger.info("Truncating token history") await token_service.truncate_history() - if config.metrics_url: - metrics = StateMetrics(config.metrics_url) - async with factory.session.begin(): - await token_service.gather_state_metrics(metrics) + event_manager = config.metrics.make_manager() + await event_manager.initialize() + events = StateEvents() + await events.initialize(event_manager) + async with factory.session.begin(): + await token_service.gather_state_metrics(events) await engine.dispose() logger.debug("Finished background maintenance") diff --git a/src/gafaelfawr/config.py b/src/gafaelfawr/config.py index 3c6ba2577..b9b1eb2c6 100644 --- a/src/gafaelfawr/config.py +++ b/src/gafaelfawr/config.py @@ -29,7 +29,6 @@ import yaml from pydantic import ( AliasChoices, - AnyHttpUrl, BaseModel, ConfigDict, Field, @@ -48,6 +47,7 @@ SettingsConfigDict, ) from safir.logging import LogLevel, configure_logging +from safir.metrics import MetricsConfiguration from safir.pydantic import EnvAsyncPostgresDsn, EnvRedisDsn, HumanTimedelta from .constants import MINIMUM_LIFETIME, SCOPE_REGEX, USERNAME_REGEX @@ -819,14 +819,9 @@ class Config(EnvFirstSettings): description="Python logging level", ) - metrics_url: AnyHttpUrl | None = Field( - None, - title="Metrics collector URL", - description=( - "If set, report metrics using the OpenTelemetry protocol to this" - " URL. Normally this will be a cluster-internal URL of a telegraf" - " instance. The metrics will be sent using insecure gRPC." - ), + metrics: MetricsConfiguration = Field( + title="Metrics configuration", + description="Configuration for reporting metrics to Kafka", ) proxies: list[IPv4Network | IPv6Network] | None = Field( diff --git a/src/gafaelfawr/dependencies/context.py b/src/gafaelfawr/dependencies/context.py index 187c25e95..adab1d71b 100644 --- a/src/gafaelfawr/dependencies/context.py +++ b/src/gafaelfawr/dependencies/context.py @@ -10,15 +10,15 @@ from typing import Annotated, Any from fastapi import Depends, HTTPException, Request -from opentelemetry.sdk.metrics.export import MetricReader from safir.dependencies.db_session import db_session_dependency from safir.dependencies.logger import logger_dependency +from safir.metrics import EventManager from sqlalchemy.ext.asyncio import async_scoped_session from structlog.stdlib import BoundLogger from ..config import Config +from ..events import FrontendEvents from ..factory import Factory, ProcessContext -from ..metrics import FrontendMetrics from ..models.state import State __all__ = [ @@ -50,8 +50,8 @@ class RequestContext: logger: BoundLogger """The request logger, rebound with discovered context.""" - metrics: FrontendMetrics | None - """Frontend metrics, if metrics are enabled.""" + events: FrontendEvents + """Frontend events publishers.""" session: async_scoped_session """The database session.""" @@ -92,8 +92,7 @@ class ContextDependency: def __init__(self) -> None: self._config: Config | None = None - self._metric_reader: MetricReader | None = None - self._metrics: FrontendMetrics | None = None + self._events: FrontendEvents | None = None self._process_context: ProcessContext | None = None async def __call__( @@ -106,7 +105,7 @@ async def __call__( logger: Annotated[BoundLogger, Depends(logger_dependency)], ) -> RequestContext: """Create a per-request context and return it.""" - if not self._config or not self._process_context: + if not self._config or not self._process_context or not self._events: raise RuntimeError("ContextDependency not initialized") if request.client and request.client.host: ip_address = request.client.host @@ -123,7 +122,7 @@ async def __call__( ip_address=ip_address, config=self._config, logger=logger, - metrics=self._metrics, + events=self._events, session=session, factory=Factory(self._process_context, session, logger), ) @@ -136,14 +135,18 @@ def process_context(self) -> ProcessContext: return self._process_context async def aclose(self) -> None: - """Clean up the per-process configuration.""" + """Clean up the per-process configuration. + + This also invalidates the events publishers until `initialize` is + called again. + """ if self._process_context: await self._process_context.aclose() self._config = None self._process_context = None async def initialize( - self, config: Config, metric_reader: MetricReader | None = None + self, config: Config, event_manager: EventManager ) -> None: """Initialize the process-wide shared context. @@ -151,14 +154,14 @@ async def initialize( ---------- config Gafaelfawr configuration. + event_manager + Global event manager. """ if self._process_context: await self._process_context.aclose() self._config = config - if config.metrics_url: - self._metrics = FrontendMetrics( - config.metrics_url, metric_reader=self._metric_reader - ) + self._events = FrontendEvents() + await self._events.initialize(event_manager) self._process_context = await ProcessContext.from_config(config) diff --git a/src/gafaelfawr/events.py b/src/gafaelfawr/events.py new file mode 100644 index 000000000..df81183a1 --- /dev/null +++ b/src/gafaelfawr/events.py @@ -0,0 +1,176 @@ +"""Metrics implementation for Gafaelfawr.""" + +from __future__ import annotations + +from pydantic import Field +from safir.dependencies.metrics import EventMaker +from safir.metrics import EventManager, EventPayload + +__all__ = [ + "ActiveUserSessionsEvent", + "ActiveUserTokensEvent", + "AuthEvent", + "FrontendEvents", + "LoginAttemptEvent", + "LoginEnrollmentEvent", + "LoginFailureEvent", + "LoginSuccessEvent", + "StateEvents", +] + + +class ActiveUserSessionsEvent(EventPayload): + """Current count of the number of active user sessions. + + These correspond to unexpired ``session`` tokens, which in turn correspond + to unexpired user browser session cookies. + + Notes + ----- + This is really a proper metric that is measured periodically, not an + event. For now, Gafaelfawr uses the event system to log this metric since + that's the system we have in place. If we later have a proper metrics + system for storing measurements, this should move to that. + """ + + count: int = Field( + ..., + title="Active user sessions", + description="Number of unexpired user session tokens", + ) + + +class ActiveUserTokensEvent(EventPayload): + """Current count of the number of active ``user`` tokens. + + Notes + ----- + This is really a proper metric that is measured periodically, not an + event. For now, Gafaelfawr uses the event system to log this metric since + that's the system we have in place. If we later have a proper metrics + system for storing measurements, this should move to that. + """ + + count: int = Field( + ..., + title="Active user tokens", + description="Number of unexpired user tokens", + ) + + +class StateEvents(EventMaker): + """Event publishers for metrics about the current Gafaelfawr state. + + Attributes + ---------- + active_user_sessions + Event publisher for the count of active user sessions. + active_user_tokens + Event publisher for the count of active user tokens. + """ + + async def initialize(self, manager: EventManager) -> None: + self.active_user_sessions = await manager.create_publisher( + "active_user_sessions", ActiveUserSessionsEvent + ) + self.active_user_tokens = await manager.create_publisher( + "active_user_tokens", ActiveUserTokensEvent + ) + + +class AuthEvent(EventPayload): + """An authentication to a service. + + Authentications from mobu bot users are not logged via this event. + """ + + username: str = Field( + ..., title="Username", description="Username of authenticated user" + ) + + service: str | None = Field( + None, + title="Service", + description="Service to which the user was authenticated", + ) + + +class LoginAttemptEvent(EventPayload): + """User attempted to log in and was directed to the identity provider. + + Records instances where Gafaelfawr sends the user to the identity provider + for authentication. This does not include duplicate redirects when the + given user already has an authentication in progress. + """ + + +class LoginEnrollmentEvent(EventPayload): + """Authenticated but unknown user redirected to the enrollment flow.""" + + +class LoginFailureEvent(EventPayload): + """User authentication failed. + + A login fails at the Gafaelfawr end, meaning that either something went + wrong in Gafaelfawr itself, with the request to the remote authentication + service, or via an error reported by the remote authentication service. + This does not count cases where the authentication service never returns + the user to us. + """ + + +class LoginSuccessEvent(EventPayload): + """User successfully authenticated. + + A user returned successfully from the identity provider after + authenticating. + """ + + username: str = Field( + ..., title="Username", description="Username of authenticated user" + ) + + elapsed_ms: int | None = Field( + None, + title="Duration of login process (ms)", + description=( + "How long it took the user to complete the login process in" + " milliseconds" + ), + ) + + +class FrontendEvents(EventMaker): + """Event publishers for Gafaelfawr frontend events. + + Attributes + ---------- + auth + Event publisher for each user authentication to a service. + Authentications from mobu bot users are not logged as events. + login_attempt + Event publisher for when an unauthenticated user is redirected to the + authentication provider. + login_enrollment + Event publisher for when an authenticated but unknown user is + redirected to the enrollment flow. + login_failure + Event publisher for authentications that fail in Gafaelfawr. + login_success + Event publisher for login successes. + """ + + async def initialize(self, manager: EventManager) -> None: + self.auth = await manager.create_publisher("auth", AuthEvent) + self.login_attempt = await manager.create_publisher( + "login_attempt", LoginAttemptEvent + ) + self.login_enrollment = await manager.create_publisher( + "login_enrollment", LoginEnrollmentEvent + ) + self.login_failure = await manager.create_publisher( + "login_failure", LoginFailureEvent + ) + self.login_success = await manager.create_publisher( + "login_success", LoginSuccessEvent + ) diff --git a/src/gafaelfawr/handlers/ingress.py b/src/gafaelfawr/handlers/ingress.py index 3d569db1b..009b5f797 100644 --- a/src/gafaelfawr/handlers/ingress.py +++ b/src/gafaelfawr/handlers/ingress.py @@ -26,6 +26,7 @@ from ..constants import MINIMUM_LIFETIME from ..dependencies.auth import AuthenticateRead from ..dependencies.context import RequestContext, context_dependency +from ..events import AuthEvent from ..exceptions import ( ExternalUserInfoError, InsufficientScopeError, @@ -358,11 +359,11 @@ async def get_auth( headers = await build_success_headers(context, auth_config, token_data) for key, value in headers: response.headers.append(key, value) - if context.metrics and not is_mobu_bot_user(token_data.username): - attrs = {"username": token_data.username} - if auth_config.service: - attrs["service"] = auth_config.service - context.metrics.request_auth.add(1, attrs) + if not is_mobu_bot_user(token_data.username): + event = AuthEvent( + username=token_data.username, service=auth_config.service + ) + await context.events.auth.publish(event) return {"status": "ok"} diff --git a/src/gafaelfawr/handlers/login.py b/src/gafaelfawr/handlers/login.py index a07a8e0f3..be7e00fd3 100644 --- a/src/gafaelfawr/handlers/login.py +++ b/src/gafaelfawr/handlers/login.py @@ -2,7 +2,7 @@ import base64 import os -from datetime import UTC, datetime +from datetime import UTC, datetime, timedelta from enum import Enum from typing import Annotated @@ -13,6 +13,12 @@ from ..dependencies.context import RequestContext, context_dependency from ..dependencies.return_url import return_url_with_header +from ..events import ( + LoginAttemptEvent, + LoginEnrollmentEvent, + LoginFailureEvent, + LoginSuccessEvent, +) from ..exceptions import ( FirestoreError, InvalidReturnURLError, @@ -114,7 +120,7 @@ async def get_login( """ if code: if not state: - return _error_user(context, LoginError.STATE_MISSING) + return await _error_user(context, LoginError.STATE_MISSING) return await handle_provider_return(code, state, context) else: return await redirect_to_provider(return_url, context) @@ -182,8 +188,7 @@ async def redirect_to_provider( state = base64.urlsafe_b64encode(os.urandom(16)).decode() context.state.state = state context.state.login_start = datetime.now(tz=UTC) - if context.metrics: - context.metrics.login_attempts.add(1) + await context.events.login_attempt.publish(LoginAttemptEvent()) # Get the authentication provider URL send the user there. provider = context.factory.create_provider() @@ -228,12 +233,13 @@ async def handle_provider_return( if context.config.oidc and context.config.oidc.enrollment_url: url = str(context.config.oidc.enrollment_url) context.logger.info("Redirecting user to enrollment URL", url=url) - if context.metrics: - context.metrics.login_enrollment.add(1) + await context.events.login_enrollment.publish( + LoginEnrollmentEvent() + ) headers = {"Cache-Control": "no-cache, no-store"} return RedirectResponse(url, headers=headers) else: - return _error_user(context, LoginError.NOT_ENROLLED, str(e)) + return await _error_user(context, LoginError.NOT_ENROLLED, str(e)) except FirestoreError as e: return await _error_system(context, LoginError.FIRESTORE_FAILED, e) except ProviderWebError as e: @@ -243,13 +249,13 @@ async def handle_provider_return( except NoScopesError as e: provider = context.factory.create_provider() await provider.logout(context.state) - return _error_user(context, LoginError.GROUPS_MISSING, str(e)) + return await _error_user(context, LoginError.GROUPS_MISSING, str(e)) except ProviderError as e: return await _error_system(context, LoginError.PROVIDER_FAILED, e) except PermissionDeniedError as e: provider = context.factory.create_provider() await provider.logout(context.state) - return _error_user(context, LoginError.INVALID_USERNAME, str(e)) + return await _error_user(context, LoginError.INVALID_USERNAME, str(e)) async def _construct_token( @@ -328,8 +334,7 @@ async def _error_system( context.state.state = None context.state.return_url = None context.state.login_start = None - if context.metrics: - context.metrics.login_failures.add(1) + await context.events.login_failure.publish(LoginFailureEvent()) return templates.TemplateResponse( context.request, "login-error.html", @@ -344,7 +349,7 @@ async def _error_system( ) -def _error_user( +async def _error_user( context: RequestContext, error: LoginError, details: str | None = None ) -> Response: """Generate an error page for a user login failure. @@ -374,8 +379,7 @@ def _error_user( context.state.state = None context.state.return_url = None context.state.login_start = None - if context.metrics: - context.metrics.login_failures.add(1) + await context.events.login_failure.publish(LoginFailureEvent()) return templates.TemplateResponse( context.request, "login-error.html", @@ -435,14 +439,14 @@ async def _construct_login_response( """ return_url = context.state.return_url if not return_url: - return _error_user(context, LoginError.RETURN_URL_MISSING) + return await _error_user(context, LoginError.RETURN_URL_MISSING) context.rebind_logger(return_url=return_url) if not context.state.state: msg = "Login state missing, redirecting without authentication" context.logger.info(msg) return RedirectResponse(return_url) if state != context.state.state: - return _error_user(context, LoginError.STATE_INVALID) + return await _error_user(context, LoginError.STATE_INVALID) # Retrieve the user identity and authorization information based on the # reply from the authentication provider, and construct a token. @@ -450,14 +454,12 @@ async def _construct_login_response( user_info = await provider.create_user_info(code, state, context.state) token = await _construct_token(context, user_info) - # Record login metrics if configured. - if context.metrics: - attrs = {"username": user_info.username} - if context.state.login_start: - now = datetime.now(tz=UTC) - elapsed = (now - context.state.login_start).total_seconds() - context.metrics.login_success_time.set(elapsed, attrs) - context.metrics.login_successes.add(1, attrs) + # Record login event. + event = LoginSuccessEvent(username=user_info.username) + if context.state.login_start: + elapsed = datetime.now(tz=UTC) - context.state.login_start + event.elapsed_ms = int(elapsed / timedelta(microseconds=1000)) + await context.events.login_success.publish(event) # Store the token, record metrics, clear the login state, and send the # user back to what they were doing. diff --git a/src/gafaelfawr/main.py b/src/gafaelfawr/main.py index 06f9c9e02..263b3dcc3 100644 --- a/src/gafaelfawr/main.py +++ b/src/gafaelfawr/main.py @@ -13,7 +13,6 @@ from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.staticfiles import StaticFiles -from opentelemetry.sdk.metrics.export import MetricReader from safir.database import create_database_engine, is_database_current from safir.dependencies.db_session import db_session_dependency from safir.dependencies.http_client import http_client_dependency @@ -38,7 +37,6 @@ def create_app( *, load_config: bool = True, extra_startup: Coroutine[None, None, None] | None = None, - metric_reader: MetricReader | None = None, validate_schema: bool = True, ) -> FastAPI: """Create the FastAPI application. @@ -58,10 +56,6 @@ def create_app( extra_startup If provided, an additional coroutine to run as part of the startup section of the lifespan context manager, used by the test suite. - metric_reader - Override the metric reader with the provided object. This is used by - the test suite to store metrics in memory where they can be queried - and checked. validate_schema If set to `True`, verify, with Alembic, that the schema is up to date and raise `~gafaelfawr.exceptions.DatabaseSchemaError` if it is not. @@ -84,7 +78,9 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: if not await is_database_current(engine, logger): raise DatabaseSchemaError("Database schema out of date") await engine.dispose() - await context_dependency.initialize(config, metric_reader) + event_manager = config.metrics.make_manager() + await event_manager.initialize() + await context_dependency.initialize(config, event_manager) await db_session_dependency.initialize( config.database_url, config.database_password ) @@ -96,6 +92,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: await http_client_dependency.aclose() await db_session_dependency.aclose() await context_dependency.aclose() + await event_manager.aclose() app = FastAPI( title="Gafaelfawr", diff --git a/src/gafaelfawr/metrics.py b/src/gafaelfawr/metrics.py deleted file mode 100644 index 604652d5d..000000000 --- a/src/gafaelfawr/metrics.py +++ /dev/null @@ -1,210 +0,0 @@ -"""Metrics implementation for Gafaelfawr.""" - -from __future__ import annotations - -from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( - OTLPMetricExporter, -) -from opentelemetry.sdk.metrics import MeterProvider -from opentelemetry.sdk.metrics.export import ( - MetricReader, - PeriodicExportingMetricReader, -) -from opentelemetry.sdk.resources import SERVICE_NAME, Resource -from pydantic import AnyHttpUrl - -__all__ = [ - "FrontendMetrics", - "GafaelfawrMetrics", - "StateMetrics", -] - - -class GafaelfawrMetrics: - """Base class for OpenTelemetry instruments for Gafaelfawr. - - Gafaelfawr has several different containers of metrics instruments used by - its different components. This base class contains the shared code common - to all of them, such as initializing the metrics exporter. Only one - subclass of this class should be instantiated in a given process. (This is - not enforced.) - - Parameters - ---------- - url - URL to the OpenTelemetry collector to which to send metrics. - meter_name - Name of the meter, which should correspond to the component of - Gafaelfawr that logs these metrics. - metric_reader - If provided, do not collect and send metrics to the OpenTelemetry - collector, and instead use the provided metric reader. This is used by - the test suite to disable the OpenTelemetry exporter in favor of an - in-memory metrics reader that can be queried by the test suite. - - Attributes - ---------- - meter - Meter that should be used to create instruments. - """ - - def __init__( - self, - url: AnyHttpUrl | str, - meter_name: str, - metric_reader: MetricReader | None = None, - ) -> None: - resource = Resource(attributes={SERVICE_NAME: "gafaelfawr"}) - if not metric_reader: - exporter = OTLPMetricExporter(str(url), insecure=True) - metric_reader = PeriodicExportingMetricReader(exporter) - provider = MeterProvider([metric_reader], resource) - self.meter = provider.get_meter(meter_name) - - -class FrontendMetrics(GafaelfawrMetrics): - """Metric instruments for the Gafaelfawr frontend. - - Parameters - ---------- - url - URL to the OpenTelemetry collector to which to send metrics. - metric_reader - If provided, do not collect and send metrics to the OpenTelemetry - collector, and instead use the provided metric reader. This is used by - the test suite to disable the OpenTelemetry exporter in favor of an - in-memory metrics reader that can be queried by the test suite. - - Attributes - ---------- - login_attempts - Count of times Gafaelfawr sends the user to the identity provider for - authentication. This does not include duplicate redirects when the - given user already has an authentication in progress. - login_enrollment - Count of the number of Gafaelfawr redirects an authenticated but - unknown user to the enrollment flow. - login_failures - Count of the times a login fails at the Gafaelfawr end, meaning that - either something went wrong in Gafaelfawr itself, with the request to - the remote authentication service, or via an error reported by the - remote authentication service. This does not count cases where the - authentication service never returns the user to us. - login_success_time - How long it takes for the user to go through the login process. The - authenticated username must be included as the ``username`` attribute. - login_successes - Count of times the user returns successfully from the identity - provider after authenticating. The authenticated username must be - included as the ``username`` attribute. - request_auth - An authenticated request to a service. Currently this is only logged - when a token is delegated to the service due to limitations in the - Gafaelfawr design. The authenticated username must be included as the - ``username`` attribute and the service name must be included as the - ``service`` attribute. - """ - - def __init__( - self, url: AnyHttpUrl | str, metric_reader: MetricReader | None = None - ) -> None: - super().__init__(url, "frontend", metric_reader) - self.login_attempts = self.meter.create_counter( - "login.attempts", - unit="1", - description=( - "Count of times Gafaelfawr sends the user to the identity" - " provider to authenticate, not including duplicate redirects" - " when the given user already has an authentication in" - " progress." - ), - ) - self.login_enrollment = self.meter.create_counter( - "login.enrollment", - unit="1", - description=( - "Count of times Gafaelfawr redirects a user to the enrollment" - " flow." - ), - ) - self.login_failures = self.meter.create_counter( - "login.failures", - unit="1", - description=( - "Count of the times a login fails at the Gafaelfawr end," - " meaning that either something went wrong in Gafaelfawr" - " itself, with the request to the remote authentication" - " service, or via an error reported by the remote" - " authentication service. This does not count cases where" - " the authentication service never returns the user to us." - ), - ) - self.login_success_time = self.meter.create_gauge( - "login.success_time", - unit="s", - description=( - "How long it takes for the user to go through the login" - " process. The authenticated username is included as an" - " attribute." - ), - ) - self.login_successes = self.meter.create_counter( - "login.successes", - unit="1", - description=( - "Count of times the user returns successfully from the" - " identity provider after authenticating. The authenticated" - " username is included as an attribute." - ), - ) - self.request_auth = self.meter.create_counter( - "request.auth", - unit="1", - description=( - "An authenticated request to an underlying service. Currently" - " this is only logged for requests that delegate an internal" - " token to the service, since those are the only ones for" - " which Gafaelfawr knows the service name. Attributes are the" - " service name and the authenticated username." - ), - ) - - -class StateMetrics(GafaelfawrMetrics): - """Metric instruments based on stored state. - - Collects metrics determined from the current stored state. These are - gathered and reported by the maintenance cron job. - - Parameters - ---------- - url - URL to the OpenTelemetry collector to which to send metrics. - metric_reader - If provided, do not collect and send metrics to the OpenTelemetry - collector, and instead use the provided metric reader. This is used by - the test suite to disable the OpenTelemetry exporter in favor of an - in-memory metrics reader that can be queried by the test suite. - - Attributes - ---------- - sessions_active_users - Total number of unexpired user sessions (unexpired session tokens). - user_tokens_active - Total number of unexpired user tokens. - """ - - def __init__( - self, url: AnyHttpUrl | str, metric_reader: MetricReader | None = None - ) -> None: - super().__init__(url, "state", metric_reader) - self.sessions_active_users = self.meter.create_gauge( - "sessions.active_users", - unit="1", - description="Number of users with unexpired user sessions", - ) - self.user_tokens_active = self.meter.create_gauge( - "user_tokens.active", - unit="1", - description="Number of unexpired user tokens", - ) diff --git a/src/gafaelfawr/services/token.py b/src/gafaelfawr/services/token.py index df8ef9e57..468ab60ef 100644 --- a/src/gafaelfawr/services/token.py +++ b/src/gafaelfawr/services/token.py @@ -16,13 +16,17 @@ MINIMUM_LIFETIME, USERNAME_REGEX, ) +from ..events import ( + ActiveUserSessionsEvent, + ActiveUserTokensEvent, + StateEvents, +) from ..exceptions import ( InvalidExpiresError, InvalidIPAddressError, InvalidScopesError, PermissionDeniedError, ) -from ..metrics import StateMetrics from ..models.history import ( HistoryCursor, PaginatedHistory, @@ -607,18 +611,22 @@ async def expire_tokens(self) -> None: ) await self._token_change_store.add(history_entry) - async def gather_state_metrics(self, metrics: StateMetrics) -> None: + async def gather_state_metrics(self, events: StateEvents) -> None: """Gather metrics from the stored state and record them. Parameters ---------- - metrics - Collection of metric instruments. + events + Publishers for state events. """ session_count = await self._token_db_store.count_unique_sessions() - metrics.sessions_active_users.set(session_count) + await events.active_user_sessions.publish( + ActiveUserSessionsEvent(count=session_count) + ) token_count = await self._token_db_store.count_user_tokens() - metrics.user_tokens_active.set(token_count) + await events.active_user_tokens.publish( + ActiveUserTokensEvent(count=token_count) + ) async def get_change_history( self, diff --git a/tests/conftest.py b/tests/conftest.py index 515bc6e38..241209542 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,7 +14,6 @@ from cryptography.fernet import Fernet from fastapi import FastAPI from httpx import ASGITransport, AsyncClient -from opentelemetry.sdk.metrics.export import InMemoryMetricReader, MetricReader from safir.database import ( create_database_engine, initialize_database, @@ -61,16 +60,14 @@ def environment(monkeypatch: pytest.MonkeyPatch) -> None: @pytest_asyncio.fixture async def app( - empty_database: None, - metric_reader: MetricReader, - mock_slack: MockSlackWebhook | None, + empty_database: None, mock_slack: MockSlackWebhook | None ) -> AsyncIterator[FastAPI]: """Return a configured test application. Wraps the application in a lifespan manager so that startup and shutdown events are sent during test execution. """ - app = create_app(metric_reader=metric_reader, validate_schema=False) + app = create_app(validate_schema=False) async with LifespanManager(app): yield app @@ -92,7 +89,8 @@ def config(monkeypatch: pytest.MonkeyPatch) -> Config: The fixture always configures Gafealfawr for GitHub authentication, but it sets up the environment variables with secrets for other providers and - user information sources so that the test case can switch later. + user information sources so that the test case can switch later. Metrics + are always disabled. Notes ----- @@ -175,17 +173,6 @@ async def factory( yield factory -@pytest.fixture -def metric_reader() -> InMemoryMetricReader: - """Return an internal metric reader used by tests. - - This is passed to the application and other relevant places that create - metrics so that the metrics will be stored in memory, can be checked by - the test suite, and don't attempt to send metrics to a remote service. - """ - return InMemoryMetricReader() - - @pytest.fixture def mock_firestore(tmp_path: Path) -> Iterator[MockFirestore]: """Configure Firestore UID/GID assignment and mock the Firestore API.""" diff --git a/tests/data/config/bad-admin.yaml b/tests/data/config/bad-admin.yaml index e9ce36d0d..115659eb1 100644 --- a/tests/data/config/bad-admin.yaml +++ b/tests/data/config/bad-admin.yaml @@ -12,3 +12,6 @@ knownScopes: "user:token": "Can create and modify user tokens" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/bad-groups.yaml b/tests/data/config/bad-groups.yaml index 784bcf3fc..3a9ec8dd7 100644 --- a/tests/data/config/bad-groups.yaml +++ b/tests/data/config/bad-groups.yaml @@ -11,3 +11,6 @@ knownScopes: "user:token": "Can create and modify user tokens" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/bad-lifetime.yaml b/tests/data/config/bad-lifetime.yaml index 8a2c1ab94..d746ff137 100644 --- a/tests/data/config/bad-lifetime.yaml +++ b/tests/data/config/bad-lifetime.yaml @@ -13,3 +13,6 @@ knownScopes: github: clientId: "some-github-client-id" tokenLifetime: "8m" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/bad-log-level.yaml b/tests/data/config/bad-log-level.yaml index b2f75b6a7..c04057c8d 100644 --- a/tests/data/config/bad-log-level.yaml +++ b/tests/data/config/bad-log-level.yaml @@ -16,3 +16,6 @@ knownScopes: "user:token": "Can create and modify user tokens" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/bad-scope.yaml b/tests/data/config/bad-scope.yaml index a0aaaeccb..19640bf46 100644 --- a/tests/data/config/bad-scope.yaml +++ b/tests/data/config/bad-scope.yaml @@ -13,3 +13,6 @@ knownScopes: "foo bar": "An invalid scope" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/both-providers.yaml b/tests/data/config/both-providers.yaml index 24e2613b7..cf6b33017 100644 --- a/tests/data/config/both-providers.yaml +++ b/tests/data/config/both-providers.yaml @@ -25,3 +25,6 @@ oidc: - "voPerson" issuer: "https://upstream.example.com/" audience: "https://test.example.com/" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/cilogon-test.yaml b/tests/data/config/cilogon-test.yaml index 2069a4627..232fa222d 100644 --- a/tests/data/config/cilogon-test.yaml +++ b/tests/data/config/cilogon-test.yaml @@ -28,3 +28,7 @@ oidc: loginParams: {} scopes: ["openid"] usernameClaim: "uid" + +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/cilogon.yaml b/tests/data/config/cilogon.yaml index decb0b7d2..fcdfd4a48 100644 --- a/tests/data/config/cilogon.yaml +++ b/tests/data/config/cilogon.yaml @@ -26,3 +26,7 @@ oidc: loginParams: {} scopes: ["openid"] usernameClaim: "uid" + +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/github-oidc-server.yaml b/tests/data/config/github-oidc-server.yaml index 41e460d03..f076e0cbf 100644 --- a/tests/data/config/github-oidc-server.yaml +++ b/tests/data/config/github-oidc-server.yaml @@ -23,3 +23,6 @@ oidcServer: "foo": ["dp0.3", "dp0.2"] github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/github-quota.yaml b/tests/data/config/github-quota.yaml index fe8966e75..3448a2235 100644 --- a/tests/data/config/github-quota.yaml +++ b/tests/data/config/github-quota.yaml @@ -29,3 +29,6 @@ quota: notebook: cpu: 0.0 memory: 4.0 +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/github.yaml b/tests/data/config/github.yaml index feea4b30b..27b041169 100644 --- a/tests/data/config/github.yaml +++ b/tests/data/config/github.yaml @@ -42,3 +42,7 @@ firestore: {} oidcServer: keyId: "gafaelfawr" quota: {} + +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/missing-scope.yaml b/tests/data/config/missing-scope.yaml index 031566404..367d9c904 100644 --- a/tests/data/config/missing-scope.yaml +++ b/tests/data/config/missing-scope.yaml @@ -10,3 +10,6 @@ knownScopes: "admin:token": "Can create and modify tokens for any user" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/no-provider.yaml b/tests/data/config/no-provider.yaml index 3525e011b..e363dab97 100644 --- a/tests/data/config/no-provider.yaml +++ b/tests/data/config/no-provider.yaml @@ -12,3 +12,6 @@ knownScopes: "exec:test": "test description" "read:all": "can read everything" "user:token": "Can create and modify user tokens" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-claims.yaml b/tests/data/config/oidc-claims.yaml index e0dbaf062..107ebe8c5 100644 --- a/tests/data/config/oidc-claims.yaml +++ b/tests/data/config/oidc-claims.yaml @@ -29,3 +29,6 @@ oidc: issuer: "https://upstream.example.com/" audience: "https://test.example.com/" usernameClaim: "username" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-enrollment.yaml b/tests/data/config/oidc-enrollment.yaml index d46d2e41a..876b1e911 100644 --- a/tests/data/config/oidc-enrollment.yaml +++ b/tests/data/config/oidc-enrollment.yaml @@ -29,3 +29,6 @@ oidc: - "voPerson" issuer: "https://upstream.example.com/" audience: "https://test.example.com/" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-firestore.yaml b/tests/data/config/oidc-firestore.yaml index 2223327b0..eebde7c37 100644 --- a/tests/data/config/oidc-firestore.yaml +++ b/tests/data/config/oidc-firestore.yaml @@ -28,3 +28,6 @@ oidc: tokenUrl: "https://upstream.example.com/token" issuer: "https://upstream.example.com/" audience: "https://test.example.com/" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-no-attrs.yaml b/tests/data/config/oidc-no-attrs.yaml index 44b187aef..ef36e25bb 100644 --- a/tests/data/config/oidc-no-attrs.yaml +++ b/tests/data/config/oidc-no-attrs.yaml @@ -31,3 +31,6 @@ oidc: - "voPerson" issuer: "https://upstream.example.com/" audience: "https://test.example.com/" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-no-memberdn.yaml b/tests/data/config/oidc-no-memberdn.yaml index 195104a56..cd4d0e468 100644 --- a/tests/data/config/oidc-no-memberdn.yaml +++ b/tests/data/config/oidc-no-memberdn.yaml @@ -33,3 +33,6 @@ oidc: - "voPerson" issuer: "https://upstream.example.com/" audience: "https://test.example.com/" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc-subdomain.yaml b/tests/data/config/oidc-subdomain.yaml index 8f233b5d1..45e5dba06 100644 --- a/tests/data/config/oidc-subdomain.yaml +++ b/tests/data/config/oidc-subdomain.yaml @@ -23,3 +23,6 @@ ldap: url: "ldaps://ldap.example.com/" groupBaseDn: "dc=example,dc=com" userBaseDn: "ou=people,dc=example,dc=com" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/oidc.yaml b/tests/data/config/oidc.yaml index 7bd162c3d..06fb7c075 100644 --- a/tests/data/config/oidc.yaml +++ b/tests/data/config/oidc.yaml @@ -38,3 +38,7 @@ errorFooter: | # Ensure that the configuration parser correctly discards empty or partial # configurations that should not be used. github: {} + +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/scope-mismatch.yaml b/tests/data/config/scope-mismatch.yaml index af716cfe4..e67d00443 100644 --- a/tests/data/config/scope-mismatch.yaml +++ b/tests/data/config/scope-mismatch.yaml @@ -13,3 +13,6 @@ knownScopes: "user:token": "Can create and modify user tokens" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/data/config/selenium.yaml b/tests/data/config/selenium.yaml index 1eb3cd9d2..b9177395c 100644 --- a/tests/data/config/selenium.yaml +++ b/tests/data/config/selenium.yaml @@ -15,3 +15,6 @@ knownScopes: "user:token": "Can create and modify user tokens" github: clientId: "some-github-client-id" +metrics: + enabled: false + appName: "gafaelfawr" diff --git a/tests/services/token_test.py b/tests/services/token_test.py index f49058230..f90774034 100644 --- a/tests/services/token_test.py +++ b/tests/services/token_test.py @@ -8,20 +8,19 @@ import pytest from cryptography.fernet import Fernet -from opentelemetry.sdk.metrics.export import InMemoryMetricReader from pydantic import ValidationError from safir.datetime import current_datetime from safir.testing.slack import MockSlackWebhook from gafaelfawr.config import Config from gafaelfawr.constants import CHANGE_HISTORY_RETENTION +from gafaelfawr.events import StateEvents from gafaelfawr.exceptions import ( InvalidExpiresError, InvalidScopesError, PermissionDeniedError, ) from gafaelfawr.factory import Factory -from gafaelfawr.metrics import StateMetrics from gafaelfawr.models.history import TokenChange, TokenChangeHistoryEntry from gafaelfawr.models.token import ( AdminTokenRequest, @@ -1810,9 +1809,7 @@ async def test_audit(factory: Factory) -> None: @pytest.mark.asyncio -async def test_state_metrics( - factory: Factory, metric_reader: InMemoryMetricReader -) -> None: +async def test_state_metrics(config: Config, factory: Factory) -> None: token_service = factory.create_token_service() await create_session_token(factory, username="someone") await create_session_token(factory, username="someone") @@ -1826,6 +1823,10 @@ async def test_state_metrics( ip_address="127.0.0.1", ) - metrics = StateMetrics("https://telegraf.example.com", metric_reader) + event_manager = config.metrics.make_manager() + await event_manager.initialize() + events = StateEvents() + await events.initialize(event_manager) async with factory.session.begin(): - await token_service.gather_state_metrics(metrics) + await token_service.gather_state_metrics(events) + await event_manager.aclose() diff --git a/tests/support/config.py b/tests/support/config.py index 3553024dd..655b3b8de 100644 --- a/tests/support/config.py +++ b/tests/support/config.py @@ -124,8 +124,8 @@ async def reconfigure( ) -> Config: """Change the test application configuration. - This cannot be used to change the database URL because sessions will not - be recreated or the database reinitialized. + This cannot be used to change the database URL because the database will + not be reinitialized. Parameters ---------- @@ -144,8 +144,11 @@ async def reconfigure( Config The new configuration. """ + await context_dependency.aclose() config = configure(filename, monkeypatch, oidc_clients=oidc_clients) - await context_dependency.initialize(config) + event_manager = config.metrics.make_manager() + await event_manager.initialize() + await context_dependency.initialize(config, event_manager) if factory: factory.set_context(context_dependency.process_context) return config diff --git a/ui/package-lock.json b/ui/package-lock.json index 2f53027ca..48364432b 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -2609,9 +2609,9 @@ } }, "node_modules/@lezer/common": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.2.tgz", - "integrity": "sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", + "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==" }, "node_modules/@lezer/lr": { "version": "1.4.2", @@ -4135,9 +4135,9 @@ } }, "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "version": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", "dependencies": { "undici-types": "~6.19.2" } @@ -4216,16 +4216,16 @@ "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", - "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", + "integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/type-utils": "8.9.0", - "@typescript-eslint/utils": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/type-utils": "8.10.0", + "@typescript-eslint/utils": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -4249,15 +4249,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", - "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz", + "integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4" }, "engines": { @@ -4277,13 +4277,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", - "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz", + "integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0" + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4294,13 +4294,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", - "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz", + "integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.9.0", - "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/typescript-estree": "8.10.0", + "@typescript-eslint/utils": "8.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -4318,9 +4318,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", - "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz", + "integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4331,13 +4331,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", - "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz", + "integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/visitor-keys": "8.9.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/visitor-keys": "8.10.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4395,15 +4395,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", - "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz", + "integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.9.0", - "@typescript-eslint/types": "8.9.0", - "@typescript-eslint/typescript-estree": "8.9.0" + "@typescript-eslint/scope-manager": "8.10.0", + "@typescript-eslint/types": "8.10.0", + "@typescript-eslint/typescript-estree": "8.10.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4417,12 +4417,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", - "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz", + "integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/types": "8.10.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4618,9 +4618,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "bin": { "acorn": "bin/acorn" }, @@ -5123,9 +5123,9 @@ } }, "node_modules/axe-core": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", - "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.1.tgz", + "integrity": "sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==", "engines": { "node": ">=4" } @@ -5792,9 +5792,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001668", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", - "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", "funding": [ { "type": "opencollective", @@ -7391,9 +7391,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.38", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.38.tgz", - "integrity": "sha512-VbeVexmZ1IFh+5EfrYz1I0HTzHVIlJa112UEWhciPyeOcKJGeTv6N8WnG4wsQB81DGCaVEGhpSb6o6a8WYFXXg==" + "version": "1.5.41", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", + "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -12500,9 +12500,9 @@ "integrity": "sha512-YTzGAJOo/B6hkodeT5SKKHpOhAzjMfkUCCXjLJwjWk2F4/InIg+HbdH9kmT7bKpleDuqLZDTRy2OdNtAj0IVyQ==" }, "node_modules/node-abi": { - "version": "3.70.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.70.0.tgz", - "integrity": "sha512-xMTIZdvAyzGyxwOwxXv/8V/f/KAqKWNCeNIIFu2doEtQp9wvMUTam036At/iVtJqum6n5ljbAhUmXAUOhyivSA==", + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", "dependencies": { "semver": "^7.3.5" }, @@ -13300,9 +13300,9 @@ "integrity": "sha512-rxJOljMuWtYlvREBmd6TZYanfcPhNUKtGDZBjBBS8WG1dpN2iwPsRJZgQqN/OtJuiQckdRFOfzogqJClTrsi7g==" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -14397,9 +14397,9 @@ } }, "node_modules/react-datepicker": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.4.0.tgz", - "integrity": "sha512-vSSok4DTZ9/Os8O4HjZLxh4SZVFU6dQvoCX6mfbNdBqMsBBdzftrvMz0Nb4UUVVbgj9o8PfX84K3/31oPrTqmg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.5.0.tgz", + "integrity": "sha512-6MzeamV8cWSOcduwePHfGqY40acuGlS1cG//ePHT6bVbLxWyqngaStenfH03n1wbzOibFggF66kWaBTb1SbTtQ==", "dependencies": { "@floating-ui/react": "^0.26.23", "clsx": "^2.1.1", @@ -16234,9 +16234,9 @@ } }, "node_modules/terser": { - "version": "5.34.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", - "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2",