diff --git a/docs/dev/internals.rst b/docs/dev/internals.rst index 0eabd3b4b..94db04a03 100644 --- a/docs/dev/internals.rst +++ b/docs/dev/internals.rst @@ -52,19 +52,19 @@ Python internal API :include-all-objects: :inherited-members: -.. automodapi:: gafaelfawr.models.history +.. automodapi:: gafaelfawr.models.enums :include-all-objects: :inherited-members: -.. automodapi:: gafaelfawr.models.kubernetes +.. automodapi:: gafaelfawr.models.history :include-all-objects: :inherited-members: -.. automodapi:: gafaelfawr.models.ldap +.. automodapi:: gafaelfawr.models.kubernetes :include-all-objects: :inherited-members: -.. automodapi:: gafaelfawr.models.link +.. automodapi:: gafaelfawr.models.ldap :include-all-objects: :inherited-members: diff --git a/pyproject.toml b/pyproject.toml index 56928fbb1..3ae79d7c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ "pyjwt", "pyyaml", "redis>=4.2.0", - "safir[db,kubernetes]>=6.5.1", + "safir[db,kubernetes]>=8.0.0", "sentry-sdk[fastapi]", "sqlalchemy>=2.0.0", "structlog", diff --git a/requirements/dev.txt b/requirements/dev.txt index eea19da95..3ebcd3106 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -404,69 +404,69 @@ comm==0.2.2 \ --hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \ --hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3 # via ipykernel -coverage==7.6.7 \ - --hash=sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433 \ - --hash=sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529 \ - --hash=sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671 \ - --hash=sha256:108bb458827765d538abcbf8288599fee07d2743357bdd9b9dad456c287e121e \ - --hash=sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42 \ - --hash=sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99 \ - --hash=sha256:2bc3e45c16564cc72de09e37413262b9f99167803e5e48c6156bccdfb22c8327 \ - --hash=sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8 \ - --hash=sha256:34d23e28ccb26236718a3a78ba72744212aa383141961dd6825f6595005c8b06 \ - --hash=sha256:37a15573f988b67f7348916077c6d8ad43adb75e478d0910957394df397d2874 \ - --hash=sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4 \ - --hash=sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354 \ - --hash=sha256:3c6b24007c4bcd0b19fac25763a7cac5035c735ae017e9a349b927cfc88f31c1 \ - --hash=sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab \ - --hash=sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3 \ - --hash=sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b \ - --hash=sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37 \ - --hash=sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd \ - --hash=sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f \ - --hash=sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b \ - --hash=sha256:623e6965dcf4e28a3debaa6fcf4b99ee06d27218f46d43befe4db1c70841551c \ - --hash=sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b \ - --hash=sha256:6cf96ceaa275f071f1bea3067f8fd43bec184a25a962c754024c973af871e1b7 \ - --hash=sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3 \ - --hash=sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808 \ - --hash=sha256:796c9b107d11d2d69e1849b2dfe41730134b526a49d3acb98ca02f4985eeff7a \ - --hash=sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76 \ - --hash=sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469 \ - --hash=sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55 \ - --hash=sha256:850cfd2d6fc26f8346f422920ac204e1d28814e32e3a58c19c91980fa74d8289 \ - --hash=sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc \ - --hash=sha256:90746521206c88bdb305a4bf3342b1b7316ab80f804d40c536fc7d329301ee13 \ - --hash=sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2 \ - --hash=sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30 \ - --hash=sha256:987a8e3da7da4eed10a20491cf790589a8e5e07656b6dc22d3814c4d88faf163 \ - --hash=sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d \ - --hash=sha256:a1ab9763d291a17b527ac6fd11d1a9a9c358280adb320e9c2672a97af346ac2c \ - --hash=sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1 \ - --hash=sha256:acbb8af78f8f91b3b51f58f288c0994ba63c646bc1a8a22ad072e4e7e0a49f1c \ - --hash=sha256:ad32a981bcdedb8d2ace03b05e4fd8dace8901eec64a532b00b15217d3677dd2 \ - --hash=sha256:aee9cf6b0134d6f932d219ce253ef0e624f4fa588ee64830fcba193269e4daa3 \ - --hash=sha256:af05bbba896c4472a29408455fe31b3797b4d8648ed0a2ccac03e074a77e2314 \ - --hash=sha256:b6cce5c76985f81da3769c52203ee94722cd5d5889731cd70d31fee939b74bf0 \ - --hash=sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384 \ - --hash=sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb \ - --hash=sha256:c296263093f099da4f51b3dff1eff5d4959b527d4f2f419e16508c5da9e15e8c \ - --hash=sha256:c973b2fe4dc445cb865ab369df7521df9c27bf40715c837a113edaa2aa9faf45 \ - --hash=sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a \ - --hash=sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24 \ - --hash=sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8 \ - --hash=sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec \ - --hash=sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56 \ - --hash=sha256:e25bacb53a8c7325e34d45dddd2f2fbae0dbc230d0e2642e264a64e17322a777 \ - --hash=sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b \ - --hash=sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f \ - --hash=sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a \ - --hash=sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d \ - --hash=sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9 \ - --hash=sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413 \ - --hash=sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c \ - --hash=sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b \ - --hash=sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c +coverage==7.6.8 \ + --hash=sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5 \ + --hash=sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf \ + --hash=sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb \ + --hash=sha256:13618bed0c38acc418896005732e565b317aa9e98d855a0e9f211a7ffc2d6638 \ + --hash=sha256:13690e923a3932e4fad4c0ebfb9cb5988e03d9dcb4c5150b5fcbf58fd8bddfc4 \ + --hash=sha256:177f01eeaa3aee4a5ffb0d1439c5952b53d5010f86e9d2667963e632e30082cc \ + --hash=sha256:193e3bffca48ad74b8c764fb4492dd875038a2f9925530cb094db92bb5e47bed \ + --hash=sha256:1defe91d41ce1bd44b40fabf071e6a01a5aa14de4a31b986aa9dfd1b3e3e414a \ + --hash=sha256:1f188a2402f8359cf0c4b1fe89eea40dc13b52e7b4fd4812450da9fcd210181d \ + --hash=sha256:202a2d645c5a46b84992f55b0a3affe4f0ba6b4c611abec32ee88358db4bb649 \ + --hash=sha256:24eda3a24a38157eee639ca9afe45eefa8d2420d49468819ac5f88b10de84f4c \ + --hash=sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b \ + --hash=sha256:379c111d3558272a2cae3d8e57e6b6e6f4fe652905692d54bad5ea0ca37c5ad4 \ + --hash=sha256:37cda8712145917105e07aab96388ae76e787270ec04bcb9d5cc786d7cbb8443 \ + --hash=sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83 \ + --hash=sha256:3985b9be361d8fb6b2d1adc9924d01dec575a1d7453a14cccd73225cb79243ee \ + --hash=sha256:3988665ee376abce49613701336544041f2117de7b7fbfe91b93d8ff8b151c8e \ + --hash=sha256:3ac47fa29d8d41059ea3df65bd3ade92f97ee4910ed638e87075b8e8ce69599e \ + --hash=sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3 \ + --hash=sha256:3ea8bb1ab9558374c0ab591783808511d135a833c3ca64a18ec927f20c4030f0 \ + --hash=sha256:3fe47da3e4fda5f1abb5709c156eca207eacf8007304ce3019eb001e7a7204cb \ + --hash=sha256:428ac484592f780e8cd7b6b14eb568f7c85460c92e2a37cb0c0e5186e1a0d076 \ + --hash=sha256:44e6c85bbdc809383b509d732b06419fb4544dca29ebe18480379633623baafb \ + --hash=sha256:4674f0daa1823c295845b6a740d98a840d7a1c11df00d1fd62614545c1583787 \ + --hash=sha256:4be32da0c3827ac9132bb488d331cb32e8d9638dd41a0557c5569d57cf22c9c1 \ + --hash=sha256:4db3ed6a907b555e57cc2e6f14dc3a4c2458cdad8919e40b5357ab9b6db6c43e \ + --hash=sha256:5c52a036535d12590c32c49209e79cabaad9f9ad8aa4cbd875b68c4d67a9cbce \ + --hash=sha256:629a1ba2115dce8bf75a5cce9f2486ae483cb89c0145795603d6554bdc83e801 \ + --hash=sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764 \ + --hash=sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365 \ + --hash=sha256:63c19702db10ad79151a059d2d6336fe0c470f2e18d0d4d1a57f7f9713875dcf \ + --hash=sha256:644ec81edec0f4ad17d51c838a7d01e42811054543b76d4ba2c5d6af741ce2a6 \ + --hash=sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71 \ + --hash=sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002 \ + --hash=sha256:716a78a342679cd1177bc8c2fe957e0ab91405bd43a17094324845200b2fddf4 \ + --hash=sha256:74610105ebd6f33d7c10f8907afed696e79c59e3043c5f20eaa3a46fddf33b4c \ + --hash=sha256:768939f7c4353c0fac2f7c37897e10b1414b571fd85dd9fc49e6a87e37a2e0d8 \ + --hash=sha256:86cffe9c6dfcfe22e28027069725c7f57f4b868a3f86e81d1c62462764dc46d4 \ + --hash=sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146 \ + --hash=sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc \ + --hash=sha256:912e95017ff51dc3d7b6e2be158dedc889d9a5cc3382445589ce554f1a34c0ea \ + --hash=sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4 \ + --hash=sha256:9e89d5c8509fbd6c03d0dd1972925b22f50db0792ce06324ba069f10787429ad \ + --hash=sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28 \ + --hash=sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451 \ + --hash=sha256:b39e6011cd06822eb964d038d5dff5da5d98652b81f5ecd439277b32361a3a50 \ + --hash=sha256:bd55f8fc8fa494958772a2a7302b0354ab16e0b9272b3c3d83cdb5bec5bd1779 \ + --hash=sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63 \ + --hash=sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e \ + --hash=sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc \ + --hash=sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022 \ + --hash=sha256:d7ad66e8e50225ebf4236368cc43c37f59d5e6728f15f6e258c8639fa0dd8e6d \ + --hash=sha256:d82ab6816c3277dc962cfcdc85b1efa0e5f50fb2c449432deaf2398a2928ab94 \ + --hash=sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b \ + --hash=sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d \ + --hash=sha256:e19122296822deafce89a0c5e8685704c067ae65d45e79718c92df7b3ec3d331 \ + --hash=sha256:e44961e36cb13c495806d4cac67640ac2866cb99044e210895b506c26ee63d3a \ + --hash=sha256:e4c81ed2820b9023a9a90717020315e63b17b18c274a332e3b6437d7ff70abe0 \ + --hash=sha256:e683e6ecc587643f8cde8f5da6768e9d165cd31edf39ee90ed7034f9ca0eefee \ + --hash=sha256:f39e2f3530ed1626c66e7493be7a8423b023ca852aacdc91fb30162c350d2a92 \ + --hash=sha256:f56f49b2553d7dd85fd86e029515a221e5c1f8cb3d9c38b470bc38bde7b8445a \ + --hash=sha256:fb9fc32399dca861584d96eccd6c980b69bbcd7c228d06fb74fe53e007aa8ef9 # via # -r requirements/dev.in # pytest-cov @@ -501,33 +501,33 @@ cryptography==43.0.3 \ # via # -c requirements/main.txt # pyopenssl -debugpy==1.8.8 \ - --hash=sha256:09cc7b162586ea2171eea055985da2702b0723f6f907a423c9b2da5996ad67ba \ - --hash=sha256:0cc94186340be87b9ac5a707184ec8f36547fb66636d1029ff4f1cc020e53996 \ - --hash=sha256:143ef07940aeb8e7316de48f5ed9447644da5203726fca378f3a6952a50a9eae \ - --hash=sha256:19ffbd84e757a6ca0113574d1bf5a2298b3947320a3e9d7d8dc3377f02d9f864 \ - --hash=sha256:26b461123a030e82602a750fb24d7801776aa81cd78404e54ab60e8b5fecdad5 \ - --hash=sha256:3a9c013077a3a0000e83d97cf9cc9328d2b0bbb31f56b0e99ea3662d29d7a6a2 \ - --hash=sha256:4b93e4832fd4a759a0c465c967214ed0c8a6e8914bced63a28ddb0dd8c5f078b \ - --hash=sha256:535f4fb1c024ddca5913bb0eb17880c8f24ba28aa2c225059db145ee557035e9 \ - --hash=sha256:53709d4ec586b525724819dc6af1a7703502f7e06f34ded7157f7b1f963bb854 \ - --hash=sha256:5c0e5a38c7f9b481bf31277d2f74d2109292179081f11108e668195ef926c0f9 \ - --hash=sha256:5c6e885dbf12015aed73770f29dec7023cb310d0dc2ba8bfbeb5c8e43f80edc9 \ - --hash=sha256:64674e95916e53c2e9540a056e5f489e0ad4872645399d778f7c598eacb7b7f9 \ - --hash=sha256:705cd123a773d184860ed8dae99becd879dfec361098edbefb5fc0d3683eb804 \ - --hash=sha256:890fd16803f50aa9cb1a9b9b25b5ec321656dd6b78157c74283de241993d086f \ - --hash=sha256:90244598214bbe704aa47556ec591d2f9869ff9e042e301a2859c57106649add \ - --hash=sha256:a6531d952b565b7cb2fbd1ef5df3d333cf160b44f37547a4e7cf73666aca5d8d \ - --hash=sha256:b01f4a5e5c5fb1d34f4ccba99a20ed01eabc45a4684f4948b5db17a319dfb23f \ - --hash=sha256:c399023146e40ae373753a58d1be0a98bf6397fadc737b97ad612886b53df318 \ - --hash=sha256:d4483836da2a533f4b1454dffc9f668096ac0433de855f0c22cdce8c9f7e10c4 \ - --hash=sha256:e59b1607c51b71545cb3496876544f7186a7a27c00b436a62f285603cc68d1c6 \ - --hash=sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091 \ - --hash=sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f \ - --hash=sha256:eea8821d998ebeb02f0625dd0d76839ddde8cbf8152ebbe289dd7acf2cdc6b98 \ - --hash=sha256:f3cbf1833e644a3100eadb6120f25be8a532035e8245584c4f7532937edc652a \ - --hash=sha256:f95651bdcbfd3b27a408869a53fbefcc2bcae13b694daee5f1365b1b83a00113 \ - --hash=sha256:ffe94dd5e9a6739a75f0b85316dc185560db3e97afa6b215628d1b6a17561cb2 +debugpy==1.8.9 \ + --hash=sha256:1339e14c7d980407248f09824d1b25ff5c5616651689f1e0f0e51bdead3ea13e \ + --hash=sha256:17c5e0297678442511cf00a745c9709e928ea4ca263d764e90d233208889a19e \ + --hash=sha256:1efbb3ff61487e2c16b3e033bc8595aea578222c08aaf3c4bf0f93fadbd662ee \ + --hash=sha256:365e556a4772d7d0d151d7eb0e77ec4db03bcd95f26b67b15742b88cacff88e9 \ + --hash=sha256:3d9755e77a2d680ce3d2c5394a444cf42be4a592caaf246dbfbdd100ffcf7ae5 \ + --hash=sha256:3e59842d6c4569c65ceb3751075ff8d7e6a6ada209ceca6308c9bde932bcef11 \ + --hash=sha256:472a3994999fe6c0756945ffa359e9e7e2d690fb55d251639d07208dbc37caea \ + --hash=sha256:54a7e6d3014c408eb37b0b06021366ee985f1539e12fe49ca2ee0d392d9ceca5 \ + --hash=sha256:5e565fc54b680292b418bb809f1386f17081d1346dca9a871bf69a8ac4071afe \ + --hash=sha256:62d22dacdb0e296966d7d74a7141aaab4bec123fa43d1a35ddcb39bf9fd29d70 \ + --hash=sha256:66eeae42f3137eb428ea3a86d4a55f28da9bd5a4a3d369ba95ecc3a92c1bba53 \ + --hash=sha256:6953b335b804a41f16a192fa2e7851bdcfd92173cbb2f9f777bb934f49baab65 \ + --hash=sha256:7c4d65d03bee875bcb211c76c1d8f10f600c305dbd734beaed4077e902606fee \ + --hash=sha256:7e646e62d4602bb8956db88b1e72fe63172148c1e25c041e03b103a25f36673c \ + --hash=sha256:7e8b079323a56f719977fde9d8115590cb5e7a1cba2fcee0986ef8817116e7c1 \ + --hash=sha256:8138efff315cd09b8dcd14226a21afda4ca582284bf4215126d87342bba1cc66 \ + --hash=sha256:8e99c0b1cc7bf86d83fb95d5ccdc4ad0586d4432d489d1f54e4055bcc795f693 \ + --hash=sha256:957363d9a7a6612a37458d9a15e72d03a635047f946e5fceee74b50d52a9c8e2 \ + --hash=sha256:957ecffff80d47cafa9b6545de9e016ae8c9547c98a538ee96ab5947115fb3dd \ + --hash=sha256:ada7fb65102a4d2c9ab62e8908e9e9f12aed9d76ef44880367bc9308ebe49a0f \ + --hash=sha256:b74a49753e21e33e7cf030883a92fa607bddc4ede1aa4145172debc637780040 \ + --hash=sha256:c36856343cbaa448171cba62a721531e10e7ffb0abff838004701454149bc037 \ + --hash=sha256:cc37a6c9987ad743d9c3a14fa1b1a14b7e4e6041f9dd0c8abf8895fe7a97b899 \ + --hash=sha256:cfe1e6c6ad7178265f74981edf1154ffce97b69005212fbc90ca22ddfe3d017e \ + --hash=sha256:e46b420dc1bea64e5bbedd678148be512442bc589b0111bd799367cde051e71a \ + --hash=sha256:ff54ef77ad9f5c425398efb150239f6fe8e20c53ae2f68367eba7ece1e96226d # via ipykernel decorator==5.1.1 \ --hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \ @@ -1017,115 +1017,115 @@ pycparser==2.22 \ # via # -c requirements/main.txt # cffi -pydantic==2.10.0 \ - --hash=sha256:0aca0f045ff6e2f097f1fe89521115335f15049eeb8a7bef3dafe4b19a74e289 \ - --hash=sha256:5e7807ba9201bdf61b1b58aa6eb690916c40a47acfb114b1b4fef3e7fd5b30fc +pydantic==2.10.2 \ + --hash=sha256:2bc2d7f17232e0841cbba4641e65ba1eb6fafb3a08de3a091ff3ce14a197c4fa \ + --hash=sha256:cfb96e45951117c3024e6b67b25cdc33a3cb7b2fa62e239f7af1378358a1d99e # via # -c requirements/main.txt # autodoc-pydantic # documenteer # pydantic-settings -pydantic-core==2.27.0 \ - --hash=sha256:0aa4d1b2eba9a325897308b3124014a142cdccb9f3e016f31d3ebee6b5ea5e75 \ - --hash=sha256:0d06b667e53320332be2bf6f9461f4a9b78092a079b8ce8634c9afaa7e10cd9f \ - --hash=sha256:153017e3d6cd3ce979de06d84343ca424bb6092727375eba1968c8b4693c6ecb \ - --hash=sha256:15e350efb67b855cd014c218716feea4986a149ed1f42a539edd271ee074a196 \ - --hash=sha256:185ef205256cd8b38431205698531026979db89a79587725c1e55c59101d64e9 \ - --hash=sha256:1da0c98a85a6c6ed702d5556db3b09c91f9b0b78de37b7593e2de8d03238807a \ - --hash=sha256:225bfff5d425c34e1fd562cef52d673579d59b967d9de06178850c4802af9039 \ - --hash=sha256:24f984fc7762ed5f806d9e8c4c77ea69fdb2afd987b4fd319ef06c87595a8c55 \ - --hash=sha256:25a7fd4de38f7ff99a37e18fa0098c3140286451bc823d1746ba80cec5b433a1 \ - --hash=sha256:2883b260f7a93235488699d39cbbd94fa7b175d3a8063fbfddd3e81ad9988cb2 \ - --hash=sha256:2a51ce96224eadd1845150b204389623c8e129fde5a67a84b972bd83a85c6c40 \ - --hash=sha256:2be0ad541bb9f059954ccf8877a49ed73877f862529575ff3d54bf4223e4dd61 \ - --hash=sha256:31a2cae5f059329f9cfe3d8d266d3da1543b60b60130d186d9b6a3c20a346361 \ - --hash=sha256:333c840a1303d1474f491e7be0b718226c730a39ead0f7dab2c7e6a2f3855555 \ - --hash=sha256:33d14369739c5d07e2e7102cdb0081a1fa46ed03215e07f097b34e020b83b1ae \ - --hash=sha256:35380671c3c921fe8adf31ad349dc6f7588b7e928dbe44e1093789734f607399 \ - --hash=sha256:359e7951f04ad35111b5ddce184db3391442345d0ab073aa63a95eb8af25a5ef \ - --hash=sha256:36aa167f69d8807ba7e341d67ea93e50fcaaf6bc433bb04939430fa3dab06f31 \ - --hash=sha256:395e3e1148fa7809016231f8065f30bb0dc285a97b4dc4360cd86e17bab58af7 \ - --hash=sha256:3e8d89c276234579cd3d095d5fa2a44eb10db9a218664a17b56363cddf226ff3 \ - --hash=sha256:3eb8849445c26b41c5a474061032c53e14fe92a11a5db969f722a2716cd12206 \ - --hash=sha256:3fd8bc2690e7c39eecdf9071b6a889ce7b22b72073863940edc2a0a23750ca90 \ - --hash=sha256:400bf470e4327e920883b51e255617dfe4496d4e80c3fea0b5a5d0bf2c404dd4 \ - --hash=sha256:4148dc9184ab79e356dc00a4199dc0ee8647973332cb385fc29a7cced49b9f9c \ - --hash=sha256:433689845288f9a1ee5714444e65957be26d30915f7745091ede4a83cfb2d7bb \ - --hash=sha256:43b61989068de9ce62296cde02beffabcadb65672207fc51e7af76dca75e6636 \ - --hash=sha256:4523c4009c3f39d948e01962223c9f5538602e7087a628479b723c939fab262d \ - --hash=sha256:483c2213a609e7db2c592bbc015da58b6c75af7360ca3c981f178110d9787bcf \ - --hash=sha256:49633583eb7dc5cba61aaf7cdb2e9e662323ad394e543ee77af265736bcd3eaa \ - --hash=sha256:4b51f964fcbb02949fc546022e56cdb16cda457af485e9a3e8b78ac2ecf5d77e \ - --hash=sha256:4bf1340ae507f6da6360b24179c2083857c8ca7644aab65807023cf35404ea8d \ - --hash=sha256:4fb49cfdb53af5041aba909be00cccfb2c0d0a2e09281bf542371c5fd36ad04c \ - --hash=sha256:510b11e9c3b1a852876d1ccd8d5903684336d635214148637ceb27366c75a467 \ - --hash=sha256:513cb14c0cc31a4dfd849a4674b20c46d87b364f997bbcb02282306f5e187abf \ - --hash=sha256:58560828ee0951bb125c6f2862fbc37f039996d19ceb6d8ff1905abf7da0bf3d \ - --hash=sha256:58ab0d979c969983cdb97374698d847a4acffb217d543e172838864636ef10d9 \ - --hash=sha256:5982048129f40b082c2654de10c0f37c67a14f5ff9d37cf35be028ae982f26df \ - --hash=sha256:5ab325fc86fbc077284c8d7f996d904d30e97904a87d6fb303dce6b3de7ebba9 \ - --hash=sha256:5cc822ab90a70ea3a91e6aed3afac570b276b1278c6909b1d384f745bd09c714 \ - --hash=sha256:5f2b19b8d6fca432cb3acf48cf5243a7bf512988029b6e6fd27e9e8c0a204d85 \ - --hash=sha256:5fc72fbfebbf42c0856a824b8b0dc2b5cd2e4a896050281a21cfa6fed8879cb1 \ - --hash=sha256:6354e18a9be37bfa124d6b288a87fb30c673745806c92956f1a25e3ae6e76b96 \ - --hash=sha256:678f66462058dd978702db17eb6a3633d634f7aa0deaea61e0a674152766d3fc \ - --hash=sha256:68950bc08f9735306322bfc16a18391fcaac99ded2509e1cc41d03ccb6013cfe \ - --hash=sha256:68ef5377eb582fa4343c9d0b57a5b094046d447b4c73dd9fbd9ffb216f829e7d \ - --hash=sha256:6b4c19525c3538fbc0bbda6229f9682fb8199ce9ac37395880e6952798e00373 \ - --hash=sha256:6bb69bf3b6500f195c3deb69c1205ba8fc3cb21d1915f1f158a10d6b1ef29b6a \ - --hash=sha256:6e19401742ed7b69e51d8e4df3c03ad5ec65a83b36244479fd70edde2828a5d9 \ - --hash=sha256:6f4a53af9e81d757756508b57cae1cf28293f0f31b9fa2bfcb416cc7fb230f9d \ - --hash=sha256:6fda87808429c520a002a85d6e7cdadbf58231d60e96260976c5b8f9a12a8e13 \ - --hash=sha256:78f841523729e43e3928a364ec46e2e3f80e6625a4f62aca5c345f3f626c6e8a \ - --hash=sha256:7a6ebfac28fd51890a61df36ef202adbd77d00ee5aca4a3dadb3d9ed49cfb929 \ - --hash=sha256:7b0202ebf2268954090209a84f9897345719e46a57c5f2c9b7b250ca0a9d3e63 \ - --hash=sha256:8117839a9bdbba86e7f9df57018fe3b96cec934c3940b591b0fd3fbfb485864a \ - --hash=sha256:82e1ad4ca170e8af4c928b67cff731b6296e6a0a0981b97b2eb7c275cc4e15bd \ - --hash=sha256:836a4bfe0cc6d36dc9a9cc1a7b391265bf6ce9d1eb1eac62ac5139f5d8d9a6fa \ - --hash=sha256:84af1cf7bfdcbc6fcf5a5f70cc9896205e0350306e4dd73d54b6a18894f79386 \ - --hash=sha256:84e35afd9e10b2698e6f2f32256678cb23ca6c1568d02628033a837638b3ed12 \ - --hash=sha256:884f1806609c2c66564082540cffc96868c5571c7c3cf3a783f63f2fb49bd3cd \ - --hash=sha256:8a150392102c402c538190730fda06f3bce654fc498865579a9f2c1d2b425833 \ - --hash=sha256:8e21d927469d04b39386255bf00d0feedead16f6253dcc85e9e10ddebc334084 \ - --hash=sha256:8e96ca781e0c01e32115912ebdf7b3fb0780ce748b80d7d28a0802fa9fbaf44e \ - --hash=sha256:8ee4c2a75af9fe21269a4a0898c5425afb01af1f5d276063f57e2ae1bc64e191 \ - --hash=sha256:91bc66f878557313c2a6bcf396e7befcffe5ab4354cfe4427318968af31143c3 \ - --hash=sha256:951e71da6c89d354572098bada5ba5b5dc3a9390c933af8a614e37755d3d1840 \ - --hash=sha256:99b2863c1365f43f74199c980a3d40f18a218fbe683dd64e470199db426c4d6a \ - --hash=sha256:9a8fbf506fde1529a1e3698198fe64bfbe2e0c09557bc6a7dcf872e7c01fec40 \ - --hash=sha256:9ce048deb1e033e7a865ca384770bccc11d44179cf09e5193a535c4c2f497bdc \ - --hash=sha256:9fe94d9d2a2b4edd7a4b22adcd45814b1b59b03feb00e56deb2e89747aec7bfe \ - --hash=sha256:a291d0b4243a259c8ea7e2b84eb9ccb76370e569298875a7c5e3e71baf49057a \ - --hash=sha256:a5c022bb0d453192426221605efc865373dde43b17822a264671c53b068ac20c \ - --hash=sha256:abb4785894936d7682635726613c44578c420a096729f1978cd061a7e72d5275 \ - --hash=sha256:b872c86d8d71827235c7077461c502feb2db3f87d9d6d5a9daa64287d75e4fa0 \ - --hash=sha256:bf37b72834e7239cf84d4a0b2c050e7f9e48bced97bad9bdf98d26b8eb72e846 \ - --hash=sha256:c0c431e4be5c1a0c6654e0c31c661cd89e0ca956ef65305c3c3fd96f4e72ca39 \ - --hash=sha256:c5726eec789ee38f2c53b10b1821457b82274f81f4f746bb1e666d8741fcfadb \ - --hash=sha256:c6fcb3fa3855d583aa57b94cf146f7781d5d5bc06cb95cb3afece33d31aac39b \ - --hash=sha256:c86679f443e7085ea55a7376462553996c688395d18ef3f0d3dbad7838f857a2 \ - --hash=sha256:c91e3c04f5191fd3fb68764bddeaf02025492d5d9f23343b283870f6ace69708 \ - --hash=sha256:c921ad596ff1a82f9c692b0758c944355abc9f0de97a4c13ca60ffc6d8dc15d4 \ - --hash=sha256:c9ed88b398ba7e3bad7bd64d66cc01dcde9cfcb7ec629a6fd78a82fa0b559d78 \ - --hash=sha256:cd2ac6b919f7fed71b17fe0b4603c092a4c9b5bae414817c9c81d3c22d1e1bcc \ - --hash=sha256:d28ca7066d6cdd347a50d8b725dc10d9a1d6a1cce09836cf071ea6a2d4908be0 \ - --hash=sha256:d29e235ce13c91902ef3efc3d883a677655b3908b1cbc73dee816e5e1f8f7739 \ - --hash=sha256:d8b5ee4ae9170e2775d495b81f414cc20268041c42571530513496ba61e94ba3 \ - --hash=sha256:db72e40628967f6dc572020d04b5f800d71264e0531c6da35097e73bdf38b003 \ - --hash=sha256:df45c4073bed486ea2f18757057953afed8dd77add7276ff01bccb79982cf46c \ - --hash=sha256:dfa5f5c0a4c8fced1422dc2ca7eefd872d5d13eb33cf324361dbf1dbfba0a9fe \ - --hash=sha256:e015833384ca3e1a0565a79f5d953b0629d9138021c27ad37c92a9fa1af7623c \ - --hash=sha256:e15315691fe2253eb447503153acef4d7223dfe7e7702f9ed66539fcd0c43801 \ - --hash=sha256:e65466b31be1070b4a5b7dbfbd14b247884cb8e8b79c64fb0f36b472912dbaea \ - --hash=sha256:e7820bb0d65e3ce1e3e70b6708c2f66143f55912fa02f4b618d0f08b61575f12 \ - --hash=sha256:e851a051f7260e6d688267eb039c81f05f23a19431bd7dfa4bf5e3cb34c108cd \ - --hash=sha256:e9f9feee7f334b72ceae46313333d002b56f325b5f04271b4ae2aadd9e993ae4 \ - --hash=sha256:eb40f828bc2f73f777d1eb8fee2e86cd9692a4518b63b6b5aa8af915dfd3207b \ - --hash=sha256:eb704155e73b833801c247f39d562229c0303f54770ca14fb1c053acb376cf10 \ - --hash=sha256:edb1bfd45227dec8d50bc7c7d86463cd8728bcc574f9b07de7369880de4626a3 \ - --hash=sha256:ee7d9d5537daf6d5c74a83b38a638cc001b648096c1cae8ef695b0c919d9d379 \ - --hash=sha256:f57783fbaf648205ac50ae7d646f27582fc706be3977e87c3c124e7a92407b10 \ - --hash=sha256:ff63a92f6e249514ef35bc795de10745be0226eaea06eb48b4bbeaa0c8850a4a +pydantic-core==2.27.1 \ + --hash=sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9 \ + --hash=sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b \ + --hash=sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c \ + --hash=sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529 \ + --hash=sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc \ + --hash=sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854 \ + --hash=sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d \ + --hash=sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278 \ + --hash=sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a \ + --hash=sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c \ + --hash=sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f \ + --hash=sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27 \ + --hash=sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f \ + --hash=sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac \ + --hash=sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2 \ + --hash=sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97 \ + --hash=sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a \ + --hash=sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919 \ + --hash=sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9 \ + --hash=sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4 \ + --hash=sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c \ + --hash=sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131 \ + --hash=sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5 \ + --hash=sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd \ + --hash=sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089 \ + --hash=sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107 \ + --hash=sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6 \ + --hash=sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60 \ + --hash=sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf \ + --hash=sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5 \ + --hash=sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08 \ + --hash=sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05 \ + --hash=sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2 \ + --hash=sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e \ + --hash=sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c \ + --hash=sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17 \ + --hash=sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62 \ + --hash=sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23 \ + --hash=sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be \ + --hash=sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067 \ + --hash=sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02 \ + --hash=sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f \ + --hash=sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235 \ + --hash=sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840 \ + --hash=sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5 \ + --hash=sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807 \ + --hash=sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16 \ + --hash=sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c \ + --hash=sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864 \ + --hash=sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e \ + --hash=sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a \ + --hash=sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35 \ + --hash=sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737 \ + --hash=sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a \ + --hash=sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3 \ + --hash=sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52 \ + --hash=sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05 \ + --hash=sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31 \ + --hash=sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89 \ + --hash=sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de \ + --hash=sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6 \ + --hash=sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36 \ + --hash=sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c \ + --hash=sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154 \ + --hash=sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb \ + --hash=sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e \ + --hash=sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd \ + --hash=sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3 \ + --hash=sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f \ + --hash=sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78 \ + --hash=sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960 \ + --hash=sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618 \ + --hash=sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08 \ + --hash=sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4 \ + --hash=sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c \ + --hash=sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c \ + --hash=sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330 \ + --hash=sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8 \ + --hash=sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792 \ + --hash=sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025 \ + --hash=sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9 \ + --hash=sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f \ + --hash=sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01 \ + --hash=sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337 \ + --hash=sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4 \ + --hash=sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f \ + --hash=sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd \ + --hash=sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51 \ + --hash=sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab \ + --hash=sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc \ + --hash=sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676 \ + --hash=sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381 \ + --hash=sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed \ + --hash=sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb \ + --hash=sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967 \ + --hash=sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073 \ + --hash=sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae \ + --hash=sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c \ + --hash=sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206 \ + --hash=sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b # via # -c requirements/main.txt # pydantic @@ -1516,9 +1516,9 @@ scriv==1.5.1 \ --hash=sha256:30ae9ff8d144f8e0cf394c4e1d379542f1b3823767642955b54ec40dc00b32b6 \ --hash=sha256:a3adc657733b4124fcb54527a5f3daab0d3c300de82d0fd2b9b297b243151b78 # via -r requirements/dev.in -selenium==4.26.1 \ - --hash=sha256:1db3f3a0cd5bb07624fa8a3905a6fdde1595a42185a0617077c361dc53d104fb \ - --hash=sha256:7640f3f08ae7f4e450f895678e8a10a55eb4e4ca18311ed675ecc4684b96b683 +selenium==4.27.1 \ + --hash=sha256:5296c425a75ff1b44d0d5199042b36a6d1ef76c04fb775b97b40be739a9caae2 \ + --hash=sha256:b89b1f62b5cfe8025868556fe82360d6b649d464f75d2655cb966c8f8447ea18 # via selenium-wire selenium-wire==5.1.0 \ --hash=sha256:b1cd4eae44d9959381abe3bb186472520d063c658e279f98555def3d4e6dd29b \ @@ -1750,18 +1750,18 @@ tomlkit==0.13.2 \ --hash=sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde \ --hash=sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79 # via documenteer -tornado==6.4.1 \ - --hash=sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8 \ - --hash=sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f \ - --hash=sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4 \ - --hash=sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 \ - --hash=sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14 \ - --hash=sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842 \ - --hash=sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9 \ - --hash=sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698 \ - --hash=sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 \ - --hash=sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d \ - --hash=sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 +tornado==6.4.2 \ + --hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \ + --hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \ + --hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \ + --hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \ + --hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \ + --hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \ + --hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \ + --hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \ + --hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \ + --hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \ + --hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1 # via # ipykernel # jupyter-client diff --git a/requirements/main.txt b/requirements/main.txt index 8b48246b0..b52d880aa 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -1199,116 +1199,116 @@ pycparser==2.22 ; platform_python_implementation != 'PyPy' \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc # via cffi -pydantic==2.10.0 \ - --hash=sha256:0aca0f045ff6e2f097f1fe89521115335f15049eeb8a7bef3dafe4b19a74e289 \ - --hash=sha256:5e7807ba9201bdf61b1b58aa6eb690916c40a47acfb114b1b4fef3e7fd5b30fc +pydantic==2.10.2 \ + --hash=sha256:2bc2d7f17232e0841cbba4641e65ba1eb6fafb3a08de3a091ff3ce14a197c4fa \ + --hash=sha256:cfb96e45951117c3024e6b67b25cdc33a3cb7b2fa62e239f7af1378358a1d99e # via # gafaelfawr (pyproject.toml) # fast-depends # fastapi # pydantic-settings # safir -pydantic-core==2.27.0 \ - --hash=sha256:0aa4d1b2eba9a325897308b3124014a142cdccb9f3e016f31d3ebee6b5ea5e75 \ - --hash=sha256:0d06b667e53320332be2bf6f9461f4a9b78092a079b8ce8634c9afaa7e10cd9f \ - --hash=sha256:153017e3d6cd3ce979de06d84343ca424bb6092727375eba1968c8b4693c6ecb \ - --hash=sha256:15e350efb67b855cd014c218716feea4986a149ed1f42a539edd271ee074a196 \ - --hash=sha256:185ef205256cd8b38431205698531026979db89a79587725c1e55c59101d64e9 \ - --hash=sha256:1da0c98a85a6c6ed702d5556db3b09c91f9b0b78de37b7593e2de8d03238807a \ - --hash=sha256:225bfff5d425c34e1fd562cef52d673579d59b967d9de06178850c4802af9039 \ - --hash=sha256:24f984fc7762ed5f806d9e8c4c77ea69fdb2afd987b4fd319ef06c87595a8c55 \ - --hash=sha256:25a7fd4de38f7ff99a37e18fa0098c3140286451bc823d1746ba80cec5b433a1 \ - --hash=sha256:2883b260f7a93235488699d39cbbd94fa7b175d3a8063fbfddd3e81ad9988cb2 \ - --hash=sha256:2a51ce96224eadd1845150b204389623c8e129fde5a67a84b972bd83a85c6c40 \ - --hash=sha256:2be0ad541bb9f059954ccf8877a49ed73877f862529575ff3d54bf4223e4dd61 \ - --hash=sha256:31a2cae5f059329f9cfe3d8d266d3da1543b60b60130d186d9b6a3c20a346361 \ - --hash=sha256:333c840a1303d1474f491e7be0b718226c730a39ead0f7dab2c7e6a2f3855555 \ - --hash=sha256:33d14369739c5d07e2e7102cdb0081a1fa46ed03215e07f097b34e020b83b1ae \ - --hash=sha256:35380671c3c921fe8adf31ad349dc6f7588b7e928dbe44e1093789734f607399 \ - --hash=sha256:359e7951f04ad35111b5ddce184db3391442345d0ab073aa63a95eb8af25a5ef \ - --hash=sha256:36aa167f69d8807ba7e341d67ea93e50fcaaf6bc433bb04939430fa3dab06f31 \ - --hash=sha256:395e3e1148fa7809016231f8065f30bb0dc285a97b4dc4360cd86e17bab58af7 \ - --hash=sha256:3e8d89c276234579cd3d095d5fa2a44eb10db9a218664a17b56363cddf226ff3 \ - --hash=sha256:3eb8849445c26b41c5a474061032c53e14fe92a11a5db969f722a2716cd12206 \ - --hash=sha256:3fd8bc2690e7c39eecdf9071b6a889ce7b22b72073863940edc2a0a23750ca90 \ - --hash=sha256:400bf470e4327e920883b51e255617dfe4496d4e80c3fea0b5a5d0bf2c404dd4 \ - --hash=sha256:4148dc9184ab79e356dc00a4199dc0ee8647973332cb385fc29a7cced49b9f9c \ - --hash=sha256:433689845288f9a1ee5714444e65957be26d30915f7745091ede4a83cfb2d7bb \ - --hash=sha256:43b61989068de9ce62296cde02beffabcadb65672207fc51e7af76dca75e6636 \ - --hash=sha256:4523c4009c3f39d948e01962223c9f5538602e7087a628479b723c939fab262d \ - --hash=sha256:483c2213a609e7db2c592bbc015da58b6c75af7360ca3c981f178110d9787bcf \ - --hash=sha256:49633583eb7dc5cba61aaf7cdb2e9e662323ad394e543ee77af265736bcd3eaa \ - --hash=sha256:4b51f964fcbb02949fc546022e56cdb16cda457af485e9a3e8b78ac2ecf5d77e \ - --hash=sha256:4bf1340ae507f6da6360b24179c2083857c8ca7644aab65807023cf35404ea8d \ - --hash=sha256:4fb49cfdb53af5041aba909be00cccfb2c0d0a2e09281bf542371c5fd36ad04c \ - --hash=sha256:510b11e9c3b1a852876d1ccd8d5903684336d635214148637ceb27366c75a467 \ - --hash=sha256:513cb14c0cc31a4dfd849a4674b20c46d87b364f997bbcb02282306f5e187abf \ - --hash=sha256:58560828ee0951bb125c6f2862fbc37f039996d19ceb6d8ff1905abf7da0bf3d \ - --hash=sha256:58ab0d979c969983cdb97374698d847a4acffb217d543e172838864636ef10d9 \ - --hash=sha256:5982048129f40b082c2654de10c0f37c67a14f5ff9d37cf35be028ae982f26df \ - --hash=sha256:5ab325fc86fbc077284c8d7f996d904d30e97904a87d6fb303dce6b3de7ebba9 \ - --hash=sha256:5cc822ab90a70ea3a91e6aed3afac570b276b1278c6909b1d384f745bd09c714 \ - --hash=sha256:5f2b19b8d6fca432cb3acf48cf5243a7bf512988029b6e6fd27e9e8c0a204d85 \ - --hash=sha256:5fc72fbfebbf42c0856a824b8b0dc2b5cd2e4a896050281a21cfa6fed8879cb1 \ - --hash=sha256:6354e18a9be37bfa124d6b288a87fb30c673745806c92956f1a25e3ae6e76b96 \ - --hash=sha256:678f66462058dd978702db17eb6a3633d634f7aa0deaea61e0a674152766d3fc \ - --hash=sha256:68950bc08f9735306322bfc16a18391fcaac99ded2509e1cc41d03ccb6013cfe \ - --hash=sha256:68ef5377eb582fa4343c9d0b57a5b094046d447b4c73dd9fbd9ffb216f829e7d \ - --hash=sha256:6b4c19525c3538fbc0bbda6229f9682fb8199ce9ac37395880e6952798e00373 \ - --hash=sha256:6bb69bf3b6500f195c3deb69c1205ba8fc3cb21d1915f1f158a10d6b1ef29b6a \ - --hash=sha256:6e19401742ed7b69e51d8e4df3c03ad5ec65a83b36244479fd70edde2828a5d9 \ - --hash=sha256:6f4a53af9e81d757756508b57cae1cf28293f0f31b9fa2bfcb416cc7fb230f9d \ - --hash=sha256:6fda87808429c520a002a85d6e7cdadbf58231d60e96260976c5b8f9a12a8e13 \ - --hash=sha256:78f841523729e43e3928a364ec46e2e3f80e6625a4f62aca5c345f3f626c6e8a \ - --hash=sha256:7a6ebfac28fd51890a61df36ef202adbd77d00ee5aca4a3dadb3d9ed49cfb929 \ - --hash=sha256:7b0202ebf2268954090209a84f9897345719e46a57c5f2c9b7b250ca0a9d3e63 \ - --hash=sha256:8117839a9bdbba86e7f9df57018fe3b96cec934c3940b591b0fd3fbfb485864a \ - --hash=sha256:82e1ad4ca170e8af4c928b67cff731b6296e6a0a0981b97b2eb7c275cc4e15bd \ - --hash=sha256:836a4bfe0cc6d36dc9a9cc1a7b391265bf6ce9d1eb1eac62ac5139f5d8d9a6fa \ - --hash=sha256:84af1cf7bfdcbc6fcf5a5f70cc9896205e0350306e4dd73d54b6a18894f79386 \ - --hash=sha256:84e35afd9e10b2698e6f2f32256678cb23ca6c1568d02628033a837638b3ed12 \ - --hash=sha256:884f1806609c2c66564082540cffc96868c5571c7c3cf3a783f63f2fb49bd3cd \ - --hash=sha256:8a150392102c402c538190730fda06f3bce654fc498865579a9f2c1d2b425833 \ - --hash=sha256:8e21d927469d04b39386255bf00d0feedead16f6253dcc85e9e10ddebc334084 \ - --hash=sha256:8e96ca781e0c01e32115912ebdf7b3fb0780ce748b80d7d28a0802fa9fbaf44e \ - --hash=sha256:8ee4c2a75af9fe21269a4a0898c5425afb01af1f5d276063f57e2ae1bc64e191 \ - --hash=sha256:91bc66f878557313c2a6bcf396e7befcffe5ab4354cfe4427318968af31143c3 \ - --hash=sha256:951e71da6c89d354572098bada5ba5b5dc3a9390c933af8a614e37755d3d1840 \ - --hash=sha256:99b2863c1365f43f74199c980a3d40f18a218fbe683dd64e470199db426c4d6a \ - --hash=sha256:9a8fbf506fde1529a1e3698198fe64bfbe2e0c09557bc6a7dcf872e7c01fec40 \ - --hash=sha256:9ce048deb1e033e7a865ca384770bccc11d44179cf09e5193a535c4c2f497bdc \ - --hash=sha256:9fe94d9d2a2b4edd7a4b22adcd45814b1b59b03feb00e56deb2e89747aec7bfe \ - --hash=sha256:a291d0b4243a259c8ea7e2b84eb9ccb76370e569298875a7c5e3e71baf49057a \ - --hash=sha256:a5c022bb0d453192426221605efc865373dde43b17822a264671c53b068ac20c \ - --hash=sha256:abb4785894936d7682635726613c44578c420a096729f1978cd061a7e72d5275 \ - --hash=sha256:b872c86d8d71827235c7077461c502feb2db3f87d9d6d5a9daa64287d75e4fa0 \ - --hash=sha256:bf37b72834e7239cf84d4a0b2c050e7f9e48bced97bad9bdf98d26b8eb72e846 \ - --hash=sha256:c0c431e4be5c1a0c6654e0c31c661cd89e0ca956ef65305c3c3fd96f4e72ca39 \ - --hash=sha256:c5726eec789ee38f2c53b10b1821457b82274f81f4f746bb1e666d8741fcfadb \ - --hash=sha256:c6fcb3fa3855d583aa57b94cf146f7781d5d5bc06cb95cb3afece33d31aac39b \ - --hash=sha256:c86679f443e7085ea55a7376462553996c688395d18ef3f0d3dbad7838f857a2 \ - --hash=sha256:c91e3c04f5191fd3fb68764bddeaf02025492d5d9f23343b283870f6ace69708 \ - --hash=sha256:c921ad596ff1a82f9c692b0758c944355abc9f0de97a4c13ca60ffc6d8dc15d4 \ - --hash=sha256:c9ed88b398ba7e3bad7bd64d66cc01dcde9cfcb7ec629a6fd78a82fa0b559d78 \ - --hash=sha256:cd2ac6b919f7fed71b17fe0b4603c092a4c9b5bae414817c9c81d3c22d1e1bcc \ - --hash=sha256:d28ca7066d6cdd347a50d8b725dc10d9a1d6a1cce09836cf071ea6a2d4908be0 \ - --hash=sha256:d29e235ce13c91902ef3efc3d883a677655b3908b1cbc73dee816e5e1f8f7739 \ - --hash=sha256:d8b5ee4ae9170e2775d495b81f414cc20268041c42571530513496ba61e94ba3 \ - --hash=sha256:db72e40628967f6dc572020d04b5f800d71264e0531c6da35097e73bdf38b003 \ - --hash=sha256:df45c4073bed486ea2f18757057953afed8dd77add7276ff01bccb79982cf46c \ - --hash=sha256:dfa5f5c0a4c8fced1422dc2ca7eefd872d5d13eb33cf324361dbf1dbfba0a9fe \ - --hash=sha256:e015833384ca3e1a0565a79f5d953b0629d9138021c27ad37c92a9fa1af7623c \ - --hash=sha256:e15315691fe2253eb447503153acef4d7223dfe7e7702f9ed66539fcd0c43801 \ - --hash=sha256:e65466b31be1070b4a5b7dbfbd14b247884cb8e8b79c64fb0f36b472912dbaea \ - --hash=sha256:e7820bb0d65e3ce1e3e70b6708c2f66143f55912fa02f4b618d0f08b61575f12 \ - --hash=sha256:e851a051f7260e6d688267eb039c81f05f23a19431bd7dfa4bf5e3cb34c108cd \ - --hash=sha256:e9f9feee7f334b72ceae46313333d002b56f325b5f04271b4ae2aadd9e993ae4 \ - --hash=sha256:eb40f828bc2f73f777d1eb8fee2e86cd9692a4518b63b6b5aa8af915dfd3207b \ - --hash=sha256:eb704155e73b833801c247f39d562229c0303f54770ca14fb1c053acb376cf10 \ - --hash=sha256:edb1bfd45227dec8d50bc7c7d86463cd8728bcc574f9b07de7369880de4626a3 \ - --hash=sha256:ee7d9d5537daf6d5c74a83b38a638cc001b648096c1cae8ef695b0c919d9d379 \ - --hash=sha256:f57783fbaf648205ac50ae7d646f27582fc706be3977e87c3c124e7a92407b10 \ - --hash=sha256:ff63a92f6e249514ef35bc795de10745be0226eaea06eb48b4bbeaa0c8850a4a +pydantic-core==2.27.1 \ + --hash=sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9 \ + --hash=sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b \ + --hash=sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c \ + --hash=sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529 \ + --hash=sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc \ + --hash=sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854 \ + --hash=sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d \ + --hash=sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278 \ + --hash=sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a \ + --hash=sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c \ + --hash=sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f \ + --hash=sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27 \ + --hash=sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f \ + --hash=sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac \ + --hash=sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2 \ + --hash=sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97 \ + --hash=sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a \ + --hash=sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919 \ + --hash=sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9 \ + --hash=sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4 \ + --hash=sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c \ + --hash=sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131 \ + --hash=sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5 \ + --hash=sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd \ + --hash=sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089 \ + --hash=sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107 \ + --hash=sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6 \ + --hash=sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60 \ + --hash=sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf \ + --hash=sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5 \ + --hash=sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08 \ + --hash=sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05 \ + --hash=sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2 \ + --hash=sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e \ + --hash=sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c \ + --hash=sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17 \ + --hash=sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62 \ + --hash=sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23 \ + --hash=sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be \ + --hash=sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067 \ + --hash=sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02 \ + --hash=sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f \ + --hash=sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235 \ + --hash=sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840 \ + --hash=sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5 \ + --hash=sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807 \ + --hash=sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16 \ + --hash=sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c \ + --hash=sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864 \ + --hash=sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e \ + --hash=sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a \ + --hash=sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35 \ + --hash=sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737 \ + --hash=sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a \ + --hash=sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3 \ + --hash=sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52 \ + --hash=sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05 \ + --hash=sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31 \ + --hash=sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89 \ + --hash=sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de \ + --hash=sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6 \ + --hash=sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36 \ + --hash=sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c \ + --hash=sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154 \ + --hash=sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb \ + --hash=sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e \ + --hash=sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd \ + --hash=sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3 \ + --hash=sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f \ + --hash=sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78 \ + --hash=sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960 \ + --hash=sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618 \ + --hash=sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08 \ + --hash=sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4 \ + --hash=sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c \ + --hash=sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c \ + --hash=sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330 \ + --hash=sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8 \ + --hash=sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792 \ + --hash=sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025 \ + --hash=sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9 \ + --hash=sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f \ + --hash=sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01 \ + --hash=sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337 \ + --hash=sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4 \ + --hash=sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f \ + --hash=sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd \ + --hash=sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51 \ + --hash=sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab \ + --hash=sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc \ + --hash=sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676 \ + --hash=sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381 \ + --hash=sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed \ + --hash=sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb \ + --hash=sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967 \ + --hash=sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073 \ + --hash=sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae \ + --hash=sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c \ + --hash=sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206 \ + --hash=sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b # via # pydantic # safir @@ -1519,9 +1519,9 @@ rsa==4.9 \ --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 # via google-auth -safir==7.0.0 \ - --hash=sha256:a43143ec1a8b569a27b0731c96393b91df1f0a8a7e811efe9e59f303087dc679 \ - --hash=sha256:b781c5d3a7db07d91be2dffcf5842406b0b40d75a130c167b1527147c754dddc +safir==8.0.0 \ + --hash=sha256:2a08fda7117060f1049ca2082080456442baf18120194c6670a4d228933a338e \ + --hash=sha256:f3a19fb4a28ce956ea50297281c6a0e468c786b047ad3ac577162528a98f03d9 # via gafaelfawr (pyproject.toml) safir-logging==6.5.1 \ --hash=sha256:b056306de26627e29bd6a6d04b1144456a1319ec0e15a67ebbc12b43362a27cd \ @@ -1686,90 +1686,78 @@ uvloop==0.21.0 ; platform_python_implementation != 'PyPy' and sys_platform != 'c --hash=sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816 \ --hash=sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2 # via uvicorn -watchfiles==0.24.0 \ - --hash=sha256:01550ccf1d0aed6ea375ef259706af76ad009ef5b0203a3a4cce0f6024f9b68a \ - --hash=sha256:01def80eb62bd5db99a798d5e1f5f940ca0a05986dcfae21d833af7a46f7ee22 \ - --hash=sha256:07cdef0c84c03375f4e24642ef8d8178e533596b229d32d2bbd69e5128ede02a \ - --hash=sha256:083dc77dbdeef09fa44bb0f4d1df571d2e12d8a8f985dccde71ac3ac9ac067a0 \ - --hash=sha256:1cf1f6dd7825053f3d98f6d33f6464ebdd9ee95acd74ba2c34e183086900a827 \ - --hash=sha256:21ab23fdc1208086d99ad3f69c231ba265628014d4aed31d4e8746bd59e88cd1 \ - --hash=sha256:2dadf8a8014fde6addfd3c379e6ed1a981c8f0a48292d662e27cabfe4239c83c \ - --hash=sha256:2e28d91ef48eab0afb939fa446d8ebe77e2f7593f5f463fd2bb2b14132f95b6e \ - --hash=sha256:2efec17819b0046dde35d13fb8ac7a3ad877af41ae4640f4109d9154ed30a188 \ - --hash=sha256:30bbd525c3262fd9f4b1865cb8d88e21161366561cd7c9e1194819e0a33ea86b \ - --hash=sha256:316449aefacf40147a9efaf3bd7c9bdd35aaba9ac5d708bd1eb5763c9a02bef5 \ - --hash=sha256:327763da824817b38ad125dcd97595f942d720d32d879f6c4ddf843e3da3fe90 \ - --hash=sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef \ - --hash=sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b \ - --hash=sha256:3770e260b18e7f4e576edca4c0a639f704088602e0bc921c5c2e721e3acb8d15 \ - --hash=sha256:3d2e3ab79a1771c530233cadfd277fcc762656d50836c77abb2e5e72b88e3a48 \ - --hash=sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e \ - --hash=sha256:43e3e37c15a8b6fe00c1bce2473cfa8eb3484bbeecf3aefbf259227e487a03df \ - --hash=sha256:449f43f49c8ddca87c6b3980c9284cab6bd1f5c9d9a2b00012adaaccd5e7decd \ - --hash=sha256:4933a508d2f78099162da473841c652ad0de892719043d3f07cc83b33dfd9d91 \ - --hash=sha256:49d617df841a63b4445790a254013aea2120357ccacbed00253f9c2b5dc24e2d \ - --hash=sha256:49fb58bcaa343fedc6a9e91f90195b20ccb3135447dc9e4e2570c3a39565853e \ - --hash=sha256:4a7fa2bc0efef3e209a8199fd111b8969fe9db9c711acc46636686331eda7dd4 \ - --hash=sha256:4abf4ad269856618f82dee296ac66b0cd1d71450fc3c98532d93798e73399b7a \ - --hash=sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370 \ - --hash=sha256:4d28cea3c976499475f5b7a2fec6b3a36208656963c1a856d328aeae056fc5c1 \ - --hash=sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea \ - --hash=sha256:54ca90a9ae6597ae6dc00e7ed0a040ef723f84ec517d3e7ce13e63e4bc82fa04 \ - --hash=sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896 \ - --hash=sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f \ - --hash=sha256:632676574429bee8c26be8af52af20e0c718cc7f5f67f3fb658c71928ccd4f7f \ - --hash=sha256:6509ed3f467b79d95fc62a98229f79b1a60d1b93f101e1c61d10c95a46a84f43 \ - --hash=sha256:6bdcfa3cd6fdbdd1a068a52820f46a815401cbc2cb187dd006cb076675e7b735 \ - --hash=sha256:7138eff8baa883aeaa074359daabb8b6c1e73ffe69d5accdc907d62e50b1c0da \ - --hash=sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a \ - --hash=sha256:73bde715f940bea845a95247ea3e5eb17769ba1010efdc938ffcb967c634fa61 \ - --hash=sha256:78470906a6be5199524641f538bd2c56bb809cd4bf29a566a75051610bc982c3 \ - --hash=sha256:7ae3e208b31be8ce7f4c2c0034f33406dd24fbce3467f77223d10cd86778471c \ - --hash=sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f \ - --hash=sha256:82ae557a8c037c42a6ef26c494d0631cacca040934b101d001100ed93d43f361 \ - --hash=sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855 \ - --hash=sha256:8360f7314a070c30e4c976b183d1d8d1585a4a50c5cb603f431cebcbb4f66327 \ - --hash=sha256:85d5f0c7771dcc7a26c7a27145059b6bb0ce06e4e751ed76cdf123d7039b60b5 \ - --hash=sha256:88bcd4d0fe1d8ff43675360a72def210ebad3f3f72cabfeac08d825d2639b4ab \ - --hash=sha256:9301c689051a4857d5b10777da23fafb8e8e921bcf3abe6448a058d27fb67633 \ - --hash=sha256:951088d12d339690a92cef2ec5d3cfd957692834c72ffd570ea76a6790222777 \ - --hash=sha256:95cf3b95ea665ab03f5a54765fa41abf0529dbaf372c3b83d91ad2cfa695779b \ - --hash=sha256:96619302d4374de5e2345b2b622dc481257a99431277662c30f606f3e22f42be \ - --hash=sha256:999928c6434372fde16c8f27143d3e97201160b48a614071261701615a2a156f \ - --hash=sha256:9a60e2bf9dc6afe7f743e7c9b149d1fdd6dbf35153c78fe3a14ae1a9aee3d98b \ - --hash=sha256:9f895d785eb6164678ff4bb5cc60c5996b3ee6df3edb28dcdeba86a13ea0465e \ - --hash=sha256:a2a9891723a735d3e2540651184be6fd5b96880c08ffe1a98bae5017e65b544b \ - --hash=sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366 \ - --hash=sha256:aa0fd7248cf533c259e59dc593a60973a73e881162b1a2f73360547132742823 \ - --hash=sha256:acbfa31e315a8f14fe33e3542cbcafc55703b8f5dcbb7c1eecd30f141df50db3 \ - --hash=sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1 \ - --hash=sha256:b3ef2c69c655db63deb96b3c3e587084612f9b1fa983df5e0c3379d41307467f \ - --hash=sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418 \ - --hash=sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886 \ - --hash=sha256:b74fdffce9dfcf2dc296dec8743e5b0332d15df19ae464f0e249aa871fc1c571 \ - --hash=sha256:b995bfa6bf01a9e09b884077a6d37070464b529d8682d7691c2d3b540d357a0c \ - --hash=sha256:bd82010f8ab451dabe36054a1622870166a67cf3fce894f68895db6f74bbdc94 \ - --hash=sha256:bdcd5538e27f188dd3c804b4a8d5f52a7fc7f87e7fd6b374b8e36a4ca03db428 \ - --hash=sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234 \ - --hash=sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6 \ - --hash=sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968 \ - --hash=sha256:d337193bbf3e45171c8025e291530fb7548a93c45253897cd764a6a71c937ed9 \ - --hash=sha256:d3dcb774e3568477275cc76554b5a565024b8ba3a0322f77c246bc7111c5bb9c \ - --hash=sha256:d64ba08db72e5dfd5c33be1e1e687d5e4fcce09219e8aee893a4862034081d4e \ - --hash=sha256:d7a2e3b7f5703ffbd500dabdefcbc9eafeff4b9444bbdd5d83d79eedf8428fab \ - --hash=sha256:d831ee0a50946d24a53821819b2327d5751b0c938b12c0653ea5be7dea9c82ec \ - --hash=sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444 \ - --hash=sha256:e5171ef898299c657685306d8e1478a45e9303ddcd8ac5fed5bd52ad4ae0b69b \ - --hash=sha256:e94e98c7cb94cfa6e071d401ea3342767f28eb5a06a58fafdc0d2a4974f4f35c \ - --hash=sha256:ec39698c45b11d9694a1b635a70946a5bad066b593af863460a8e600f0dff1ca \ - --hash=sha256:ed9aba6e01ff6f2e8285e5aa4154e2970068fe0fc0998c4380d0e6278222269b \ - --hash=sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18 \ - --hash=sha256:ee82c98bed9d97cd2f53bdb035e619309a098ea53ce525833e26b93f673bc318 \ - --hash=sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07 \ - --hash=sha256:f7d9b87c4c55e3ea8881dfcbf6d61ea6775fffed1fedffaa60bd047d3c08c430 \ - --hash=sha256:f83df90191d67af5a831da3a33dd7628b02a95450e168785586ed51e6d28943c \ - --hash=sha256:fca9433a45f18b7c779d2bae7beeec4f740d28b788b117a48368d95a3233ed83 \ - --hash=sha256:fd92bbaa2ecdb7864b7600dcdb6f2f1db6e0346ed425fbd01085be04c63f0b05 +watchfiles==1.0.0 \ + --hash=sha256:06d828fe2adc4ac8a64b875ca908b892a3603d596d43e18f7948f3fef5fc671c \ + --hash=sha256:074c7618cd6c807dc4eaa0982b4a9d3f8051cd0b72793511848fd64630174b17 \ + --hash=sha256:09551237645d6bff3972592f2aa5424df9290e7a2e15d63c5f47c48cde585935 \ + --hash=sha256:0fc3bf0effa2d8075b70badfdd7fb839d7aa9cea650d17886982840d71fdeabf \ + --hash=sha256:12ab123135b2f42517f04e720526d41448667ae8249e651385afb5cda31fedc0 \ + --hash=sha256:13a4f9ee0cd25682679eea5c14fc629e2eaa79aab74d963bc4e21f43b8ea1877 \ + --hash=sha256:1d19df28f99d6a81730658fbeb3ade8565ff687f95acb59665f11502b441be5f \ + --hash=sha256:1e176b6b4119b3f369b2b4e003d53a226295ee862c0962e3afd5a1c15680b4e3 \ + --hash=sha256:1ee5edc939f53466b329bbf2e58333a5461e6c7b50c980fa6117439e2c18b42d \ + --hash=sha256:1f73c2147a453315d672c1ad907abe6d40324e34a185b51e15624bc793f93cc6 \ + --hash=sha256:1ff236d7a3f4b0a42f699a22fc374ba526bc55048a70cbb299661158e1bb5e1f \ + --hash=sha256:245fab124b9faf58430da547512d91734858df13f2ddd48ecfa5e493455ffccb \ + --hash=sha256:28babb38cf2da8e170b706c4b84aa7e4528a6fa4f3ee55d7a0866456a1662041 \ + --hash=sha256:28fb64b5843d94e2c2483f7b024a1280662a44409bedee8f2f51439767e2d107 \ + --hash=sha256:29cf884ad4285d23453c702ed03d689f9c0e865e3c85d20846d800d4787de00f \ + --hash=sha256:2a825ba4b32c214e3855b536eb1a1f7b006511d8e64b8215aac06eb680642d84 \ + --hash=sha256:2ac778a460ea22d63c7e6fb0bc0f5b16780ff0b128f7f06e57aaec63bd339285 \ + --hash=sha256:2c2696611182c85eb0e755b62b456f48debff484b7306b56f05478b843ca8ece \ + --hash=sha256:2d9c0518fabf4a3f373b0a94bb9e4ea7a1df18dec45e26a4d182aa8918dee855 \ + --hash=sha256:2de52b499e1ab037f1a87cb8ebcb04a819bf087b1015a4cf6dcf8af3c2a2613e \ + --hash=sha256:37566c844c9ce3b5deb964fe1a23378e575e74b114618d211fbda8f59d7b5dab \ + --hash=sha256:3d94fd83ed54266d789f287472269c0def9120a2022674990bd24ad989ebd7a0 \ + --hash=sha256:48051d1c504448b2fcda71c5e6e3610ae45de6a0b8f5a43b961f250be4bdf5a8 \ + --hash=sha256:487d15927f1b0bd24e7df921913399bb1ab94424c386bea8b267754d698f8f0e \ + --hash=sha256:4a3b33c3aefe9067ebd87846806cd5fc0b017ab70d628aaff077ab9abf4d06b3 \ + --hash=sha256:4ff9c7e84e8b644a8f985c42bcc81457240316f900fc72769aaedec9d088055a \ + --hash=sha256:533a7cbfe700e09780bb31c06189e39c65f06c7f447326fee707fd02f9a6e945 \ + --hash=sha256:53ae447f06f8f29f5ab40140f19abdab822387a7c426a369eb42184b021e97eb \ + --hash=sha256:550109001920a993a4383b57229c717fa73627d2a4e8fcb7ed33c7f1cddb0c85 \ + --hash=sha256:5bbd0311588c2de7f9ea5cf3922ccacfd0ec0c1922870a2be503cc7df1ca8be7 \ + --hash=sha256:5dccfc70480087567720e4e36ec381bba1ed68d7e5f368fe40c93b3b1eba0105 \ + --hash=sha256:5f75cd42e7e2254117cf37ff0e68c5b3f36c14543756b2da621408349bd9ca7c \ + --hash=sha256:648e2b6db53eca6ef31245805cd528a16f56fa4cc15aeec97795eaf713c11435 \ + --hash=sha256:774ef36b16b7198669ce655d4f75b4c3d370e7f1cbdfb997fb10ee98717e2058 \ + --hash=sha256:8a2127cd68950787ee36753e6d401c8ea368f73beaeb8e54df5516a06d1ecd82 \ + --hash=sha256:90004553be36427c3d06ec75b804233f8f816374165d5225b93abd94ba6e7234 \ + --hash=sha256:905f69aad276639eff3893759a07d44ea99560e67a1cf46ff389cd62f88872a2 \ + --hash=sha256:9122b8fdadc5b341315d255ab51d04893f417df4e6c1743b0aac8bf34e96e025 \ + --hash=sha256:9272fdbc0e9870dac3b505bce1466d386b4d8d6d2bacf405e603108d50446940 \ + --hash=sha256:936f362e7ff28311b16f0b97ec51e8f2cc451763a3264640c6ed40fb252d1ee4 \ + --hash=sha256:947ccba18a38b85c366dafeac8df2f6176342d5992ca240a9d62588b214d731f \ + --hash=sha256:95dc785bc284552d044e561b8f4fe26d01ab5ca40d35852a6572d542adfeb4bc \ + --hash=sha256:95de85c254f7fe8cbdf104731f7f87f7f73ae229493bebca3722583160e6b152 \ + --hash=sha256:9b4fb98100267e6a5ebaff6aaa5d20aea20240584647470be39fe4823012ac96 \ + --hash=sha256:9c01446626574561756067f00b37e6b09c8622b0fc1e9fdbc7cbcea328d4e514 \ + --hash=sha256:9c9a8d8fd97defe935ef8dd53d562e68942ad65067cd1c54d6ed8a088b1d931d \ + --hash=sha256:9e1d9284cc84de7855fcf83472e51d32daf6f6cecd094160192628bc3fee1b78 \ + --hash=sha256:a0abf173975eb9dd17bb14c191ee79999e650997cc644562f91df06060610e62 \ + --hash=sha256:a2218e78e2c6c07b1634a550095ac2a429026b2d5cbcd49a594f893f2bb8c936 \ + --hash=sha256:a5a7a06cfc65e34fd0a765a7623c5ba14707a0870703888e51d3d67107589817 \ + --hash=sha256:b2bca898c1dc073912d3db7fa6926cc08be9575add9e84872de2c99c688bac4e \ + --hash=sha256:b46e15c34d4e401e976d6949ad3a74d244600d5c4b88c827a3fdf18691a46359 \ + --hash=sha256:b551c465a59596f3d08170bd7e1c532c7260dd90ed8135778038e13c5d48aa81 \ + --hash=sha256:b555a93c15bd2c71081922be746291d776d47521a00703163e5fbe6d2a402399 \ + --hash=sha256:bc338ce9f8846543d428260fa0f9a716626963148edc937d71055d01d81e1525 \ + --hash=sha256:bedf84835069f51c7b026b3ca04e2e747ea8ed0a77c72006172c72d28c9f69fc \ + --hash=sha256:c3d258d78341d5d54c0c804a5b7faa66cd30ba50b2756a7161db07ce15363b8d \ + --hash=sha256:c83a6d33a9eda0af6a7470240d1af487807adc269704fe76a4972dd982d16236 \ + --hash=sha256:c9a13ac46b545a7d0d50f7641eefe47d1597e7d1783a5d89e09d080e6dff44b0 \ + --hash=sha256:cf517701a4a872417f4e02a136e929537743461f9ec6cdb8184d9a04f4843545 \ + --hash=sha256:d2b39aa8edd9e5f56f99a2a2740a251dc58515398e9ed5a4b3e5ff2827060755 \ + --hash=sha256:d3572d4c34c4e9c33d25b3da47d9570d5122f8433b9ac6519dca49c2740d23cd \ + --hash=sha256:d562a6114ddafb09c33246c6ace7effa71ca4b6a2324a47f4b09b6445ea78941 \ + --hash=sha256:e1ed613ee107269f66c2df631ec0fc8efddacface85314d392a4131abe299f00 \ + --hash=sha256:e3750434c83b61abb3163b49c64b04180b85b4dabb29a294513faec57f2ffdb7 \ + --hash=sha256:eba98901a2eab909dbd79681190b9049acc650f6111fde1845484a4450761e98 \ + --hash=sha256:f159ac795785cde4899e0afa539f4c723fb5dd336ce5605bc909d34edd00b79b \ + --hash=sha256:f8c4f3a1210ed099a99e6a710df4ff2f8069411059ffe30fa5f9467ebed1256b \ + --hash=sha256:fa13d604fcb9417ae5f2e3de676e66aa97427d888e83662ad205bed35a313176 \ + --hash=sha256:fbd0ab7a9943bbddb87cbc2bf2f09317e74c77dc55b1f5657f81d04666c25269 \ + --hash=sha256:ffd98a299b0a74d1b704ef0ed959efb753e656a4e0425c14e46ae4c3cbdd2919 # via uvicorn websockets==14.1 \ --hash=sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59 \ diff --git a/requirements/tox.txt b/requirements/tox.txt index 30fc3bab0..181444ef1 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -253,7 +253,7 @@ uv==0.5.4 \ --hash=sha256:f511faf719b797ef0f14688f1abe20b3fd126209cf58512354d1813249745119 \ --hash=sha256:f806af0ee451a81099c449c4cff0e813056fdf7dd264f3d3a8fd321b17ff9efc # via tox-uv -virtualenv==20.27.1 \ - --hash=sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba \ - --hash=sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4 +virtualenv==20.28.0 \ + --hash=sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0 \ + --hash=sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa # via tox diff --git a/src/gafaelfawr/exceptions.py b/src/gafaelfawr/exceptions.py index 45f54319f..5d367b701 100644 --- a/src/gafaelfawr/exceptions.py +++ b/src/gafaelfawr/exceptions.py @@ -26,7 +26,6 @@ "InvalidCSRFError", "InvalidClientError", "InvalidClientIdError", - "InvalidCursorError", "InvalidDelegateToError", "InvalidExpiresError", "InvalidGrantError", @@ -113,15 +112,6 @@ def __init__(self, message: str) -> None: super().__init__(message, ErrorLocation.header, ["X-CSRF-Token"]) -class InvalidCursorError(InputValidationError): - """The provided cursor was invalid.""" - - error = "invalid_cursor" - - def __init__(self, message: str) -> None: - super().__init__(message, ErrorLocation.query, ["cursor"]) - - class InvalidDelegateToError(InputValidationError): """The ``delegate_to`` parameter was set to an invalid value.""" diff --git a/src/gafaelfawr/handlers/api.py b/src/gafaelfawr/handlers/api.py index 1c2c293cc..3881ca53d 100644 --- a/src/gafaelfawr/handlers/api.py +++ b/src/gafaelfawr/handlers/api.py @@ -28,22 +28,24 @@ from ..exceptions import ExternalUserInfoError, NotFoundError from ..models.admin import Admin from ..models.auth import APIConfig, APILoginResponse, Scope -from ..models.history import TokenChangeHistoryEntry +from ..models.enums import TokenType +from ..models.history import TokenChangeHistoryCursor, TokenChangeHistoryEntry from ..models.token import ( AdminTokenRequest, NewToken, TokenData, TokenInfo, - TokenType, UserTokenModifyRequest, UserTokenRequest, ) from ..models.userinfo import UserInfo from ..util import random_128_bits +router = APIRouter(route_class=SlackRouteErrorHandler) +"""Router for API routes.""" + __all__ = ["router"] -router = APIRouter(route_class=SlackRouteErrorHandler) authenticate_read = AuthenticateRead() authenticate_write = AuthenticateWrite() authenticate_admin_read = AuthenticateRead( @@ -246,9 +248,12 @@ async def get_admin_token_change_history( response: Response, ) -> list[dict[str, Any]]: token_service = context.factory.create_token_service() + parsed_cursor = None + if cursor: + parsed_cursor = TokenChangeHistoryCursor.from_str(cursor) results = await token_service.get_change_history( auth_data, - cursor=cursor, + cursor=parsed_cursor, limit=limit, since=since, until=until, @@ -471,9 +476,12 @@ async def get_user_token_change_history( response: Response, ) -> list[dict[str, Any]]: token_service = context.factory.create_token_service() + parsed_cursor = None + if cursor: + parsed_cursor = TokenChangeHistoryCursor.from_str(cursor) results = await token_service.get_change_history( auth_data, - cursor=cursor, + cursor=parsed_cursor, username=username, limit=limit, since=since, diff --git a/src/gafaelfawr/handlers/oidc.py b/src/gafaelfawr/handlers/oidc.py index d74125823..0f562a14c 100644 --- a/src/gafaelfawr/handlers/oidc.py +++ b/src/gafaelfawr/handlers/oidc.py @@ -17,6 +17,7 @@ from ..dependencies.context import RequestContext, context_dependency from ..exceptions import InvalidRequestError, InvalidTokenError, OAuthError from ..models.auth import AuthType +from ..models.enums import TokenType from ..models.oidc import ( JWKS, OIDCConfig, @@ -24,7 +25,7 @@ OIDCScope, OIDCTokenReply, ) -from ..models.token import TokenData, TokenType +from ..models.token import TokenData __all__ = ["router"] diff --git a/src/gafaelfawr/models/enums.py b/src/gafaelfawr/models/enums.py new file mode 100644 index 000000000..b86020d60 --- /dev/null +++ b/src/gafaelfawr/models/enums.py @@ -0,0 +1,64 @@ +"""Enums used in Gafaelfawr models. + +Notes +----- +These are kept in a separate module because some models need to import ORM +objects in order to define pagination cursors, but ORM objects often refer to +enums for column definitions. +""" + +from __future__ import annotations + +from enum import Enum + +__all__ = [ + "AdminChange", + "TokenChange", + "TokenType", +] + + +class AdminChange(Enum): + """Type of change made to a token admin.""" + + add = "add" + remove = "remove" + + +class TokenChange(Enum): + """Type of change made to a token.""" + + create = "create" + revoke = "revoke" + expire = "expire" + edit = "edit" + + +class TokenType(Enum): + """The class of token.""" + + session = "session" + """An interactive user web session.""" + + user = "user" + """A user-generated token that may be used programmatically.""" + + notebook = "notebook" + """The token delegated to a Jupyter notebook for the user.""" + + internal = "internal" + """Service-to-service token chained from a user request. + + A service-to-service token used for internal sub-calls made as part of + processing a user request. + """ + + service = "service" + """Service-to-service token independent of a user request. + + A service-to-service token used for internal calls initiated by + services, unrelated to a user request. + """ + + oidc = "oidc" + """Access token for an OpenID Connect client.""" diff --git a/src/gafaelfawr/models/history.py b/src/gafaelfawr/models/history.py index a89050fee..482d75b9d 100644 --- a/src/gafaelfawr/models/history.py +++ b/src/gafaelfawr/models/history.py @@ -3,41 +3,38 @@ from __future__ import annotations from dataclasses import dataclass -from datetime import UTC, datetime -from enum import Enum +from datetime import datetime # noqa: F401: needed for docs from typing import Any, Generic, Self, TypeVar -from urllib.parse import parse_qs, urlencode from pydantic import BaseModel, Field, field_validator +from safir.database import DatetimeIdCursor, PaginatedList, PaginationCursor from safir.datetime import current_datetime -from starlette.datastructures import URL +from sqlalchemy.orm import InstrumentedAttribute -from ..exceptions import InvalidCursorError from ..pydantic import Timestamp +from ..schema import TokenChangeHistory from ..util import normalize_ip_address, normalize_scopes -from .token import TokenType +from .enums import AdminChange, TokenChange, TokenType + +# Not used directly but needed to prevent documentation build errors because +# Sphinx cannot understand that this inherited type variable is defined in +# Safir. +C = TypeVar("C", bound="PaginationCursor") +"""Type of a cursor for a paginated list.""" E = TypeVar("E", bound="BaseModel") """Type of a history entry in a paginated list.""" __all__ = [ - "AdminChange", "AdminHistoryEntry", "E", - "HistoryCursor", "PaginatedHistory", - "TokenChange", + "TokenChangeHistoryCursor", "TokenChangeHistoryEntry", + "TokenChangeHistoryRecord", ] -class AdminChange(Enum): - """Type of change made to a token admin.""" - - add = "add" - remove = "remove" - - class AdminHistoryEntry(BaseModel): """A record of a change to the token administrators.""" @@ -81,129 +78,6 @@ class AdminHistoryEntry(BaseModel): ) -@dataclass -class HistoryCursor: - """Pagination cursor for history entries.""" - - time: datetime - """Time position.""" - - id: int - """Unique ID position.""" - - previous: bool = False - """Whether to search backwards instead of forwards.""" - - @classmethod - def from_str(cls, cursor: str) -> Self: - """Build cursor from the string serialization form. - - Parameters - ---------- - cursor - Serialized form of the cursor. - - Returns - ------- - HistoryCursor - The cursor represented as an object. - - Raises - ------ - InvalidCursorError - Raised if the cursor is not valid. - """ - previous = cursor.startswith("p") - if previous: - cursor = cursor[1:] - try: - time, id = cursor.split("_") - return cls( - time=datetime.fromtimestamp(int(time), tz=UTC), - id=int(id), - previous=previous, - ) - except Exception as e: - raise InvalidCursorError(f"Invalid cursor: {e!s}") from e - - @classmethod - def invert(cls, cursor: HistoryCursor) -> Self: - """Return the inverted cursor (going the opposite direction). - - Parameters - ---------- - cursor - Cursor to invert. - - Returns - ------- - HistoryCursor - The inverted cursor. - """ - return cls( - time=cursor.time, id=cursor.id, previous=not cursor.previous - ) - - def __str__(self) -> str: - """Serialize to a string.""" - previous = "p" if self.previous else "" - timestamp = str(int(self.time.timestamp())) - return f"{previous}{timestamp}_{self.id!s}" - - -@dataclass -class PaginatedHistory(Generic[E]): - """Encapsulates paginated history entries with pagination information. - - Holds a paginated list of a generic type, complete with a count and - cursors. Can hold any type of entry, but uses a `HistoryCursor`, so - implicitly requires the type be one that is meaningfully paginated by that - type of cursor. - """ - - entries: list[E] - """The history entries.""" - - count: int - """Total available entries.""" - - next_cursor: HistoryCursor | None = None - """Cursor for the next batch of entries.""" - - prev_cursor: HistoryCursor | None = None - """Cursor for the previous batch of entries.""" - - def link_header(self, base_url: URL) -> str: - """Construct an RFC 8288 ``Link`` header for a paginated result. - - Parameters - ---------- - base_url - The starting URL of the current group of entries. - """ - first_url = base_url.remove_query_params("cursor") - header = f' <{first_url!s}>; rel="first"' - params = parse_qs(first_url.query) - if self.next_cursor: - params["cursor"] = [str(self.next_cursor)] - next_url = first_url.replace(query=urlencode(params, doseq=True)) - header += f', <{next_url!s}>; rel="next"' - if self.prev_cursor: - params["cursor"] = [str(self.prev_cursor)] - prev_url = first_url.replace(query=urlencode(params, doseq=True)) - header += f', <{prev_url!s}>; rel="prev"' - return header - - -class TokenChange(Enum): - """Type of change made to a token.""" - - create = "create" - revoke = "revoke" - expire = "expire" - edit = "edit" - - class TokenChangeHistoryEntry(BaseModel): """A record of a change to a token.""" @@ -312,9 +186,9 @@ class TokenChangeHistoryEntry(BaseModel): # automatic validation, but the corresponding query takes either an IP # address or a CIDR block (so can't use the same type), and all of the # type conversions and calcuations made for ugly code, particularly since - # the underlying database layer wants a string. It turned out to be - # easier to manually validate the query and to otherwise store and - # manipulate strings. + # the underlying database layer wants a string. It turned out to be easier + # to manually validate the query and to otherwise store and manipulate + # strings. # # We don't gain very much from the Pydantic validation since these entries # are created either in code or sourced from a trusted database. @@ -377,3 +251,45 @@ def model_dump_reduced(self) -> dict[str, Any]: del v["old_token_name"] return v + + +class TokenChangeHistoryRecord(TokenChangeHistoryEntry): + """A token change history entry populated from the database. + + This model adds the unique row ID, which is not part of the public API but + which is required for cursors to work correctly. + """ + + id: int = Field( + ..., + title="Unique ID", + description="Database unique row ID, not included in the API", + exclude=True, + ) + + +@dataclass +class PaginatedHistory(PaginatedList, Generic[E]): + """A paginated list of history entries, including total count.""" + + count: int | None = None + """Total count of entries.""" + + +@dataclass +class TokenChangeHistoryCursor(DatetimeIdCursor[TokenChangeHistoryRecord]): + """Pagination cursor for token history entries.""" + + @staticmethod + def id_column() -> InstrumentedAttribute: + return TokenChangeHistory.id + + @staticmethod + def time_column() -> InstrumentedAttribute: + return TokenChangeHistory.event_time + + @classmethod + def from_entry( + cls, entry: TokenChangeHistoryRecord, *, reverse: bool = False + ) -> Self: + return cls(id=entry.id, time=entry.event_time, previous=reverse) diff --git a/src/gafaelfawr/models/link.py b/src/gafaelfawr/models/link.py deleted file mode 100644 index 131544832..000000000 --- a/src/gafaelfawr/models/link.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Representation for a ``Link`` HTTP header.""" - -from __future__ import annotations - -import re -from dataclasses import dataclass -from typing import Self - -__all__ = ["LinkData"] - -_LINK_REGEX = r' *<(?P[^>]+)>; rel="(?P[^"]+)"' -"""Matches a component of a valid ``Link`` header.""" - - -@dataclass -class LinkData: - """Holds the data returned in an RFC 8288 ``Link`` header.""" - - prev_url: str | None - """The URL of the previous page, or `None` for the first page.""" - - next_url: str | None - """The URL of the next page, or `None` for the last page.""" - - first_url: str | None - """The URL of the first page.""" - - @classmethod - def from_header(cls, header: str | None) -> Self: - """Parse an RFC 8288 ``Link`` with pagination URLs. - - Parameters - ---------- - header - The contents of an RFC 8288 ``Link`` header. - - Returns - ------- - LinkData - The parsed form of that header. - """ - links = {} - if header: - elements = header.split(",") - for element in elements: - match = re.match(_LINK_REGEX, element) - if match and match.group("type") in ("prev", "next", "first"): - links[match.group("type")] = match.group("target") - - return cls( - prev_url=links.get("prev"), - next_url=links.get("next"), - first_url=links.get("first"), - ) diff --git a/src/gafaelfawr/models/token.py b/src/gafaelfawr/models/token.py index dda909f5a..d21a28fd4 100644 --- a/src/gafaelfawr/models/token.py +++ b/src/gafaelfawr/models/token.py @@ -3,7 +3,6 @@ from __future__ import annotations from datetime import datetime -from enum import Enum from typing import Any, Self from pydantic import BaseModel, Field, ValidationInfo, field_validator @@ -13,6 +12,7 @@ from ..exceptions import InvalidTokenError from ..pydantic import Timestamp from ..util import normalize_scopes, random_128_bits +from .enums import TokenType from .userinfo import Group __all__ = [ @@ -22,7 +22,6 @@ "TokenBase", "TokenData", "TokenInfo", - "TokenType", "TokenUserInfo", "UserTokenModifyRequest", "UserTokenRequest", @@ -108,36 +107,6 @@ def __str__(self) -> str: return f"gt-{self.key}.{self.secret}" -class TokenType(Enum): - """The class of token.""" - - session = "session" - """An interactive user web session.""" - - user = "user" - """A user-generated token that may be used programmatically.""" - - notebook = "notebook" - """The token delegated to a Jupyter notebook for the user.""" - - internal = "internal" - """Service-to-service token chained from a user request. - - A service-to-service token used for internal sub-calls made as part of - processing a user request. - """ - - service = "service" - """Service-to-service token independent of a user request. - - A service-to-service token used for internal calls initiated by - services, unrelated to a user request. - """ - - oidc = "oidc" - """Access token for an OpenID Connect client.""" - - class TokenBase(BaseModel): """Base information about a token common to several representations. diff --git a/src/gafaelfawr/providers/github.py b/src/gafaelfawr/providers/github.py index e8d16f311..4b001cba3 100644 --- a/src/gafaelfawr/providers/github.py +++ b/src/gafaelfawr/providers/github.py @@ -8,13 +8,13 @@ from httpx import AsyncClient, HTTPError from pydantic import ValidationError +from safir.database import PaginationLinkData from structlog.stdlib import BoundLogger from ..config import GitHubConfig from ..constants import USERNAME_REGEX from ..exceptions import GitHubError, GitHubWebError, PermissionDeniedError from ..models.github import GitHubTeam, GitHubUserInfo -from ..models.link import LinkData from ..models.state import State from ..models.token import TokenUserInfo from ..models.userinfo import Group @@ -388,7 +388,7 @@ async def _get_user_teams( # If the data was paginated, there will be a Link header with a next # URL. Retrieve each page until we run out of Link headers. - link_data = LinkData.from_header(r.headers.get("Link")) + link_data = PaginationLinkData.from_header(r.headers.get("Link")) while link_data.next_url: next_url = link_data.next_url if not next_url.startswith(self._TEAMS_URL): @@ -404,7 +404,7 @@ async def _get_user_teams( ) r.raise_for_status() teams_data.extend(r.json()) - link_data = LinkData.from_header(r.headers.get("Link")) + link_data = PaginationLinkData.from_header(r.headers.get("Link")) return [ GitHubTeam( diff --git a/src/gafaelfawr/schema/admin_history.py b/src/gafaelfawr/schema/admin_history.py index b364d328e..fdedd1570 100644 --- a/src/gafaelfawr/schema/admin_history.py +++ b/src/gafaelfawr/schema/admin_history.py @@ -12,7 +12,7 @@ from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Mapped, mapped_column -from ..models.history import AdminChange +from ..models.enums import AdminChange from .base import SchemaBase __all__ = ["AdminHistory"] diff --git a/src/gafaelfawr/schema/token.py b/src/gafaelfawr/schema/token.py index 657848546..caa8c7218 100644 --- a/src/gafaelfawr/schema/token.py +++ b/src/gafaelfawr/schema/token.py @@ -7,7 +7,7 @@ from sqlalchemy import Index, String, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column -from ..models.token import TokenType +from ..models.enums import TokenType from .base import SchemaBase __all__ = ["Token"] diff --git a/src/gafaelfawr/schema/token_auth_history.py b/src/gafaelfawr/schema/token_auth_history.py index c5e16165b..0a39b1269 100644 --- a/src/gafaelfawr/schema/token_auth_history.py +++ b/src/gafaelfawr/schema/token_auth_history.py @@ -8,7 +8,7 @@ from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Mapped, mapped_column -from ..models.token import TokenType +from ..models.enums import TokenType from .base import SchemaBase __all__ = ["TokenAuthHistory"] diff --git a/src/gafaelfawr/schema/token_change_history.py b/src/gafaelfawr/schema/token_change_history.py index f3844b8bd..d2f7f765d 100644 --- a/src/gafaelfawr/schema/token_change_history.py +++ b/src/gafaelfawr/schema/token_change_history.py @@ -8,8 +8,7 @@ from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Mapped, mapped_column -from ..models.history import TokenChange -from ..models.token import TokenType +from ..models.enums import TokenChange, TokenType from .base import SchemaBase __all__ = ["TokenChangeHistory"] diff --git a/src/gafaelfawr/services/admin.py b/src/gafaelfawr/services/admin.py index 2c1a87cf6..96199872b 100644 --- a/src/gafaelfawr/services/admin.py +++ b/src/gafaelfawr/services/admin.py @@ -10,7 +10,8 @@ from ..exceptions import DuplicateAdminError, PermissionDeniedError from ..models.admin import Admin -from ..models.history import AdminChange, AdminHistoryEntry +from ..models.enums import AdminChange +from ..models.history import AdminHistoryEntry from ..storage.admin import AdminStore from ..storage.history import AdminHistoryStore diff --git a/src/gafaelfawr/services/health.py b/src/gafaelfawr/services/health.py index 69a1a830d..f93d720c3 100644 --- a/src/gafaelfawr/services/health.py +++ b/src/gafaelfawr/services/health.py @@ -4,7 +4,7 @@ from sqlalchemy.ext.asyncio import async_scoped_session -from ..models.token import TokenType +from ..models.enums import TokenType from ..storage.token import TokenDatabaseStore, TokenRedisStore from .userinfo import UserInfoService diff --git a/src/gafaelfawr/services/kubernetes.py b/src/gafaelfawr/services/kubernetes.py index 9156089a3..fcd03fb74 100644 --- a/src/gafaelfawr/services/kubernetes.py +++ b/src/gafaelfawr/services/kubernetes.py @@ -21,13 +21,14 @@ KubernetesError, PermissionDeniedError, ) +from ..models.enums import TokenType from ..models.kubernetes import ( GafaelfawrIngress, GafaelfawrIngressScopesBase, GafaelfawrServiceToken, KubernetesResourceStatus, ) -from ..models.token import AdminTokenRequest, Token, TokenData, TokenType +from ..models.token import AdminTokenRequest, Token, TokenData from ..storage.kubernetes import ( KubernetesIngressStorage, KubernetesTokenStorage, diff --git a/src/gafaelfawr/services/token.py b/src/gafaelfawr/services/token.py index 1e6756993..dea9d6499 100644 --- a/src/gafaelfawr/services/token.py +++ b/src/gafaelfawr/services/token.py @@ -28,18 +28,18 @@ InvalidScopesError, PermissionDeniedError, ) +from ..models.enums import TokenChange, TokenType from ..models.history import ( - HistoryCursor, PaginatedHistory, - TokenChange, + TokenChangeHistoryCursor, TokenChangeHistoryEntry, + TokenChangeHistoryRecord, ) from ..models.token import ( AdminTokenRequest, Token, TokenData, TokenInfo, - TokenType, TokenUserInfo, ) from ..storage.admin import AdminStore @@ -661,7 +661,7 @@ async def get_change_history( self, auth_data: TokenData, *, - cursor: str | None = None, + cursor: TokenChangeHistoryCursor | None = None, limit: int | None = None, since: datetime | None = None, until: datetime | None = None, @@ -671,7 +671,7 @@ async def get_change_history( token: str | None = None, token_type: TokenType | None = None, ip_or_cidr: str | None = None, - ) -> PaginatedHistory[TokenChangeHistoryEntry]: + ) -> PaginatedHistory[TokenChangeHistoryRecord]: """Retrieve the change history of a token. Parameters @@ -709,8 +709,6 @@ async def get_change_history( Raises ------ - InvalidCursorError - Raised if the provided cursor was invalid. InvalidIPAddressError Raised if the provided argument was syntactically invalid for both an IP address and a CIDR block. @@ -719,7 +717,7 @@ async def get_change_history( self._validate_ip_or_cidr(ip_or_cidr) async with self._session.begin(): return await self._token_change_store.list( - cursor=HistoryCursor.from_str(cursor) if cursor else None, + cursor=cursor, limit=limit, since=since, until=until, diff --git a/src/gafaelfawr/services/token_cache.py b/src/gafaelfawr/services/token_cache.py index 60ba2add5..3ceb379c5 100644 --- a/src/gafaelfawr/services/token_cache.py +++ b/src/gafaelfawr/services/token_cache.py @@ -11,8 +11,9 @@ from ..cache import InternalTokenCache, NotebookTokenCache from ..config import Config -from ..models.history import TokenChange, TokenChangeHistoryEntry -from ..models.token import Token, TokenData, TokenType +from ..models.enums import TokenChange, TokenType +from ..models.history import TokenChangeHistoryEntry +from ..models.token import Token, TokenData from ..storage.history import TokenChangeHistoryStore from ..storage.token import TokenDatabaseStore, TokenRedisStore diff --git a/src/gafaelfawr/storage/history.py b/src/gafaelfawr/storage/history.py index 0085d5e94..afce140f3 100644 --- a/src/gafaelfawr/storage/history.py +++ b/src/gafaelfawr/storage/history.py @@ -4,18 +4,19 @@ from datetime import datetime -from safir.database import datetime_from_db, datetime_to_db -from sqlalchemy import and_, delete, func, or_, select +from safir.database import PaginatedQueryRunner, datetime_to_db +from sqlalchemy import delete, or_, select from sqlalchemy.ext.asyncio import async_scoped_session from sqlalchemy.sql import Select, text +from ..models.enums import TokenType from ..models.history import ( AdminHistoryEntry, - HistoryCursor, PaginatedHistory, + TokenChangeHistoryCursor, TokenChangeHistoryEntry, + TokenChangeHistoryRecord, ) -from ..models.token import TokenType from ..schema import AdminHistory, TokenChangeHistory __all__ = ["AdminHistoryStore", "TokenChangeHistoryStore"] @@ -57,6 +58,9 @@ class TokenChangeHistoryStore: def __init__(self, session: async_scoped_session) -> None: self._session = session + self._paginated_runner = PaginatedQueryRunner( + TokenChangeHistoryRecord, TokenChangeHistoryCursor + ) async def add(self, entry: TokenChangeHistoryEntry) -> None: """Record a change to a token. @@ -96,7 +100,7 @@ async def delete(self, *, older_than: datetime) -> None: async def list( self, *, - cursor: HistoryCursor | None = None, + cursor: TokenChangeHistoryCursor | None = None, limit: int | None = None, since: datetime | None = None, until: datetime | None = None, @@ -106,7 +110,7 @@ async def list( token: str | None = None, token_type: TokenType | None = None, ip_or_cidr: str | None = None, - ) -> PaginatedHistory[TokenChangeHistoryEntry]: + ) -> PaginatedHistory[TokenChangeHistoryRecord]: """Return all changes to a specific token. Parameters @@ -138,11 +142,10 @@ async def list( Returns ------- - list of TokenChangeHistoryEntry + PaginatedHistory of TokenChangeHistoryEntry List of change history entries, which may be empty. """ stmt = select(TokenChangeHistory) - if since: since = datetime_to_db(since) stmt = stmt.where(TokenChangeHistory.event_time >= since) @@ -167,134 +170,18 @@ async def list( if ip_or_cidr: stmt = self._apply_ip_or_cidr_filter(stmt, ip_or_cidr) - # Shunt the complicated case of a paginated query to a separate - # function to keep the logic more transparent. - if cursor or limit: - return await self._paginated_query(stmt, cursor, limit) - - # Perform the query and return the results. - stmt = stmt.order_by( - TokenChangeHistory.event_time.desc(), TokenChangeHistory.id.desc() - ) - result = await self._session.scalars(stmt) - entries = result.all() - return PaginatedHistory[TokenChangeHistoryEntry]( - entries=[ - TokenChangeHistoryEntry.model_validate(e, from_attributes=True) - for e in entries - ], - count=len(entries), - prev_cursor=None, - next_cursor=None, + # Perform the paginated query. + result = await self._paginated_runner.query_object( + self._session, stmt, cursor=cursor, limit=limit ) - - async def _paginated_query( - self, - stmt: Select, - cursor: HistoryCursor | None = None, - limit: int | None = None, - ) -> PaginatedHistory[TokenChangeHistoryEntry]: - """Run a paginated query (one with a limit or a cursor).""" - limited_stmt = stmt - - # Apply the cursor, if there is one. - if cursor: - limited_stmt = self._apply_cursor(limited_stmt, cursor) - - # When retrieving a previous set of results using a previous - # cursor, we have to reverse the sort algorithm so that the cursor - # boundary can be applied correctly. We'll then later reverse the - # result set to return it in proper forward-sorted order. - if cursor and cursor.previous: - limited_stmt = limited_stmt.order_by( - TokenChangeHistory.event_time, TokenChangeHistory.id - ) - else: - limited_stmt = limited_stmt.order_by( - TokenChangeHistory.event_time.desc(), - TokenChangeHistory.id.desc(), - ) - - # Grab one more element than the query limit so that we know whether - # to create a cursor (because there are more elements) and what the - # cursor value should be (for forward cursors). - if limit: - limited_stmt = limited_stmt.limit(limit + 1) - - # Execute the query twice, once to get the next bach of results and - # once to get the count of all entries without pagination. - result = await self._session.scalars(limited_stmt) - entries = list(result.all()) - count_stmt = select(func.count()).select_from(stmt.subquery()) - count = await self._session.scalar(count_stmt) or 0 - - # Calculate the cursors, remove the extra element we asked for, and - # reverse the results again if we did a reverse sort because we were - # using a previous cursor. - prev_cursor = None - next_cursor = None - if cursor and cursor.previous: - if limit: - next_cursor = HistoryCursor.invert(cursor) - if len(entries) > limit: - prev_cursor = self._build_prev_cursor(entries[limit - 1]) - entries = entries[:limit] - entries.reverse() - elif limit: - if cursor: - prev_cursor = HistoryCursor.invert(cursor) - if len(entries) > limit: - next_cursor = self._build_next_cursor(entries[limit]) - entries = entries[:limit] - - # Return the results. - return PaginatedHistory[TokenChangeHistoryEntry]( - entries=[ - TokenChangeHistoryEntry.model_validate(e, from_attributes=True) - for e in entries - ], + count = await self._paginated_runner.query_count(self._session, stmt) + return PaginatedHistory[TokenChangeHistoryRecord]( + entries=result.entries, + next_cursor=result.next_cursor, + prev_cursor=result.prev_cursor, count=count, - prev_cursor=prev_cursor, - next_cursor=next_cursor, ) - @staticmethod - def _apply_cursor(stmt: Select, cursor: HistoryCursor) -> Select: - """Apply a cursor to a query.""" - time = datetime_to_db(cursor.time) - if cursor.previous: - return stmt.where( - or_( - TokenChangeHistory.event_time > time, - and_( - TokenChangeHistory.event_time == time, - TokenChangeHistory.id > cursor.id, - ), - ) - ) - else: - return stmt.where( - or_( - TokenChangeHistory.event_time < time, - and_( - TokenChangeHistory.event_time == time, - TokenChangeHistory.id <= cursor.id, - ), - ) - ) - - @staticmethod - def _build_next_cursor(entry: TokenChangeHistory) -> HistoryCursor: - """Construct a next cursor for entries >= the given entry.""" - next_time = datetime_from_db(entry.event_time) - return HistoryCursor(time=next_time, id=entry.id) - - @staticmethod - def _build_prev_cursor(entry: TokenChangeHistory) -> HistoryCursor: - """Construct a prev cursor for entries before the given entry.""" - prev_time = datetime_from_db(entry.event_time) - return HistoryCursor(time=prev_time, id=entry.id, previous=True) - def _apply_ip_or_cidr_filter( self, stmt: Select, ip_or_cidr: str ) -> Select: diff --git a/src/gafaelfawr/storage/token.py b/src/gafaelfawr/storage/token.py index 16a891455..889448efe 100644 --- a/src/gafaelfawr/storage/token.py +++ b/src/gafaelfawr/storage/token.py @@ -13,7 +13,8 @@ from structlog.stdlib import BoundLogger from ..exceptions import DuplicateTokenNameError -from ..models.token import Token, TokenData, TokenInfo, TokenType +from ..models.enums import TokenType +from ..models.token import Token, TokenData, TokenInfo from ..schema.subtoken import Subtoken from ..schema.token import Token as SQLToken diff --git a/tests/cli_test.py b/tests/cli_test.py index 3c15f5ca9..5d603999c 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -31,9 +31,10 @@ from gafaelfawr.exceptions import InvalidGrantError from gafaelfawr.factory import Factory from gafaelfawr.models.admin import Admin -from gafaelfawr.models.history import TokenChange, TokenChangeHistoryEntry +from gafaelfawr.models.enums import TokenChange, TokenType +from gafaelfawr.models.history import TokenChangeHistoryEntry from gafaelfawr.models.oidc import OIDCAuthorizationCode, OIDCScope -from gafaelfawr.models.token import Token, TokenData, TokenType, TokenUserInfo +from gafaelfawr.models.token import Token, TokenData, TokenUserInfo from gafaelfawr.schema import SchemaBase from gafaelfawr.storage.history import TokenChangeHistoryStore from gafaelfawr.storage.token import TokenDatabaseStore diff --git a/tests/conftest.py b/tests/conftest.py index cb7edbddb..91cc4b5a9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,8 +25,9 @@ from gafaelfawr.factory import Factory from gafaelfawr.keypair import RSAKeyPair from gafaelfawr.main import create_app +from gafaelfawr.models.enums import TokenType from gafaelfawr.models.state import State -from gafaelfawr.models.token import Token, TokenType +from gafaelfawr.models.token import Token from .pages.tokens import TokensPage from .support.config import config_path, configure diff --git a/tests/handlers/api_history_test.py b/tests/handlers/api_history_test.py index 9d5415f08..35a2f9b25 100644 --- a/tests/handlers/api_history_test.py +++ b/tests/handlers/api_history_test.py @@ -11,20 +11,15 @@ import pytest from httpx import AsyncClient -from safir.database import datetime_to_db +from safir.database import PaginationLinkData, datetime_to_db from safir.datetime import current_datetime from safir.testing.slack import MockSlackWebhook from sqlalchemy import select from gafaelfawr.factory import Factory +from gafaelfawr.models.enums import TokenType from gafaelfawr.models.history import TokenChangeHistoryEntry -from gafaelfawr.models.link import LinkData -from gafaelfawr.models.token import ( - AdminTokenRequest, - TokenData, - TokenType, - TokenUserInfo, -) +from gafaelfawr.models.token import AdminTokenRequest, TokenData, TokenUserInfo from gafaelfawr.schema import TokenChangeHistory from ..support.constants import TEST_HOSTNAME @@ -224,7 +219,7 @@ async def check_pagination( # Check the Link contents, except for the next URL, which we'll check # by using it to retrieve the next data. - link_data = LinkData.from_header(r.headers["Link"]) + link_data = PaginationLinkData.from_header(r.headers["Link"]) assert link_data.first_url == f"https://{TEST_HOSTNAME}{first_url}" if end == 5: assert not link_data.prev_url @@ -234,7 +229,7 @@ async def check_pagination( assert r.status_code == 200 assert r.json() == prev_data assert r.headers["X-Total-Count"] == str(len(history)) - prev_link_data = LinkData.from_header(r.headers["Link"]) + prev_link_data = PaginationLinkData.from_header(r.headers["Link"]) assert prev_link_data.first_url == link_data.first_url assert prev_link_data.next_url == url @@ -260,7 +255,7 @@ async def check_pagination( assert r.status_code == 200 assert r.headers["X-Total-Count"] == str(len(history)) backwards_data = r.json() + backwards_data - link_data = LinkData.from_header(r.headers["Link"]) + link_data = PaginationLinkData.from_header(r.headers["Link"]) assert all_data == backwards_data diff --git a/tests/handlers/cadc_test.py b/tests/handlers/cadc_test.py index 88810737d..08a2254bf 100644 --- a/tests/handlers/cadc_test.py +++ b/tests/handlers/cadc_test.py @@ -10,12 +10,8 @@ from gafaelfawr.config import Config from gafaelfawr.factory import Factory -from gafaelfawr.models.token import ( - AdminTokenRequest, - Token, - TokenData, - TokenType, -) +from gafaelfawr.models.enums import TokenType +from gafaelfawr.models.token import AdminTokenRequest, Token, TokenData @pytest.mark.asyncio diff --git a/tests/models/token_test.py b/tests/models/token_test.py index 200234975..015e08ae7 100644 --- a/tests/models/token_test.py +++ b/tests/models/token_test.py @@ -6,7 +6,8 @@ from pydantic import ValidationError from gafaelfawr.exceptions import InvalidTokenError -from gafaelfawr.models.token import AdminTokenRequest, Token, TokenType +from gafaelfawr.models.enums import TokenType +from gafaelfawr.models.token import AdminTokenRequest, Token def test_token() -> None: diff --git a/tests/operator/tokens_test.py b/tests/operator/tokens_test.py index af4bf63f9..49f0adbc0 100644 --- a/tests/operator/tokens_test.py +++ b/tests/operator/tokens_test.py @@ -20,17 +20,13 @@ from gafaelfawr.constants import KUBERNETES_TIMER_DELAY from gafaelfawr.factory import Factory +from gafaelfawr.models.enums import TokenType from gafaelfawr.models.kubernetes import ( GafaelfawrServiceTokenSpec, KubernetesResourceStatus, StatusReason, ) -from gafaelfawr.models.token import ( - AdminTokenRequest, - Token, - TokenData, - TokenType, -) +from gafaelfawr.models.token import AdminTokenRequest, Token, TokenData from gafaelfawr.services.token import TokenService from ..support.kubernetes import ( diff --git a/tests/pages/tokens.py b/tests/pages/tokens.py index 7e6946389..911f76db4 100644 --- a/tests/pages/tokens.py +++ b/tests/pages/tokens.py @@ -6,7 +6,7 @@ from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement -from gafaelfawr.models.token import TokenType +from gafaelfawr.models.enums import TokenType from .base import BaseElement, BaseModal, BasePage diff --git a/tests/selenium/tokens_test.py b/tests/selenium/tokens_test.py index 2bde047f5..c66e1620e 100644 --- a/tests/selenium/tokens_test.py +++ b/tests/selenium/tokens_test.py @@ -9,8 +9,9 @@ from seleniumwire import webdriver from gafaelfawr.constants import COOKIE_NAME +from gafaelfawr.models.enums import TokenType from gafaelfawr.models.state import State -from gafaelfawr.models.token import Token, TokenType +from gafaelfawr.models.token import Token from ..pages.tokens import TokenDataPage, TokensPage from ..support.selenium import SeleniumConfig diff --git a/tests/services/oidc_test.py b/tests/services/oidc_test.py index d77431a27..4d513f1bd 100644 --- a/tests/services/oidc_test.py +++ b/tests/services/oidc_test.py @@ -21,13 +21,14 @@ UnsupportedGrantTypeError, ) from gafaelfawr.factory import Factory +from gafaelfawr.models.enums import TokenType from gafaelfawr.models.oidc import ( OIDCAuthorization, OIDCAuthorizationCode, OIDCScope, OIDCToken, ) -from gafaelfawr.models.token import Token, TokenType +from gafaelfawr.models.token import Token from ..support.config import build_oidc_client, reconfigure from ..support.tokens import create_session_token diff --git a/tests/services/token_cache_test.py b/tests/services/token_cache_test.py index 7eb026337..0b8ec5be4 100644 --- a/tests/services/token_cache_test.py +++ b/tests/services/token_cache_test.py @@ -11,7 +11,8 @@ from gafaelfawr.config import Config from gafaelfawr.factory import Factory -from gafaelfawr.models.token import Token, TokenData, TokenType +from gafaelfawr.models.enums import TokenType +from gafaelfawr.models.token import Token, TokenData from gafaelfawr.storage.token import TokenRedisStore from ..support.tokens import create_session_token diff --git a/tests/services/token_test.py b/tests/services/token_test.py index 07fbc1b76..05475d912 100644 --- a/tests/services/token_test.py +++ b/tests/services/token_test.py @@ -21,13 +21,16 @@ PermissionDeniedError, ) from gafaelfawr.factory import Factory -from gafaelfawr.models.history import TokenChange, TokenChangeHistoryEntry +from gafaelfawr.models.enums import TokenChange, TokenType +from gafaelfawr.models.history import ( + TokenChangeHistoryEntry, + TokenChangeHistoryRecord, +) from gafaelfawr.models.token import ( AdminTokenRequest, Token, TokenData, TokenInfo, - TokenType, TokenUserInfo, ) from gafaelfawr.models.userinfo import Group @@ -87,7 +90,8 @@ async def test_session_token(config: Config, factory: Factory) -> None: data, token=token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=1, token=token.key, username=data.username, token_type=TokenType.session, @@ -168,7 +172,8 @@ async def test_user_token(factory: Factory) -> None: data, token=user_token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=2, token=user_token.key, username=data.username, token_type=TokenType.user, @@ -244,7 +249,8 @@ async def test_notebook_token(config: Config, factory: Factory) -> None: data, token=token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=2, token=token.key, username=data.username, token_type=TokenType.notebook, @@ -393,7 +399,8 @@ async def test_internal_token(config: Config, factory: Factory) -> None: data, token=internal_token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=2, token=internal_token.key, username=data.username, token_type=TokenType.internal, @@ -658,7 +665,8 @@ async def test_token_from_admin_request(factory: Factory) -> None: admin_data, token=token.key, username=request.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=3, token=token.key, username=request.username, token_type=TokenType.user, @@ -696,7 +704,8 @@ async def test_token_from_admin_request(factory: Factory) -> None: admin_data, token=token.key, username=request.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=4, token=token.key, username=request.username, token_type=TokenType.service, @@ -828,7 +837,8 @@ async def test_modify(factory: Factory) -> None: data, token=user_token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=5, token=user_token.key, username=data.username, token_type=TokenType.user, @@ -841,7 +851,8 @@ async def test_modify(factory: Factory) -> None: ip_address="127.0.4.5", event_time=history.entries[0].event_time, ), - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=4, token=user_token.key, username=data.username, token_type=TokenType.user, @@ -855,7 +866,8 @@ async def test_modify(factory: Factory) -> None: ip_address="192.168.0.4", event_time=history.entries[1].event_time, ), - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=3, token=user_token.key, username=data.username, token_type=TokenType.user, @@ -868,7 +880,8 @@ async def test_modify(factory: Factory) -> None: ip_address="127.0.0.1", event_time=history.entries[2].event_time, ), - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=2, token=user_token.key, username=data.username, token_type=TokenType.user, @@ -911,7 +924,8 @@ async def test_delete(factory: Factory) -> None: data, token=token.key, username=data.username ) assert history.entries == [ - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=3, token=token.key, username=data.username, token_type=TokenType.user, @@ -923,7 +937,8 @@ async def test_delete(factory: Factory) -> None: ip_address="127.0.0.1", event_time=history.entries[0].event_time, ), - TokenChangeHistoryEntry( + TokenChangeHistoryRecord( + id=2, token=token.key, username=data.username, token_type=TokenType.user, @@ -1497,7 +1512,7 @@ async def test_expire_tokens(factory: Factory) -> None: username=token_data.username, token=token_data.token.key, ) - assert history.entries == [ + assert [e.model_dump() for e in history.entries] == [ TokenChangeHistoryEntry( token=token_data.token.key, username=token_data.username, @@ -1510,7 +1525,7 @@ async def test_expire_tokens(factory: Factory) -> None: actor="", action=TokenChange.expire, event_time=history.entries[0].event_time, - ) + ).model_dump() ] async with factory.session.begin(): @@ -1568,7 +1583,8 @@ async def test_truncate_history(factory: Factory) -> None: history = await token_service.get_change_history( auth_data=session_token_data, username="other-user" ) - assert history.entries == [new_entry] + expected = [new_entry.model_dump()] + assert [e.model_dump() for e in history.entries] == expected @pytest.mark.asyncio diff --git a/tests/support/tokens.py b/tests/support/tokens.py index b6cf1c76a..2c3b1ce07 100644 --- a/tests/support/tokens.py +++ b/tests/support/tokens.py @@ -8,8 +8,9 @@ from sqlalchemy.ext.asyncio import async_scoped_session from gafaelfawr.factory import Factory -from gafaelfawr.models.history import TokenChange, TokenChangeHistoryEntry -from gafaelfawr.models.token import Token, TokenData, TokenType, TokenUserInfo +from gafaelfawr.models.enums import TokenChange, TokenType +from gafaelfawr.models.history import TokenChangeHistoryEntry +from gafaelfawr.models.token import Token, TokenData, TokenUserInfo from gafaelfawr.models.userinfo import Group from gafaelfawr.storage.history import TokenChangeHistoryStore from gafaelfawr.storage.token import TokenDatabaseStore diff --git a/ui/package-lock.json b/ui/package-lock.json index a9fd06686..24fdee8bd 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -4168,11 +4168,11 @@ } }, "node_modules/@types/node": { - "version": "22.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", - "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", + "version": "22.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", + "integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/parse-json": { @@ -4240,16 +4240,16 @@ "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", - "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", + "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/type-utils": "8.15.0", - "@typescript-eslint/utils": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/type-utils": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -4273,15 +4273,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", - "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", + "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/typescript-estree": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4" }, "engines": { @@ -4301,13 +4301,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", - "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", + "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0" + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4318,13 +4318,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", - "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", + "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.15.0", - "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/utils": "8.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -4345,9 +4345,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", - "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", + "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4358,13 +4358,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", - "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", + "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4422,15 +4422,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", - "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", + "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/typescript-estree": "8.15.0" + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4449,12 +4449,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", - "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", + "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/types": "8.16.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5163,9 +5163,9 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -5427,9 +5427,9 @@ } }, "node_modules/bare-stream": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.2.tgz", - "integrity": "sha512-EFZHSIBkDgSHIwj2l2QZfP4U5OcD4xFAOwhSb/vlr9PIqyGJGvB/nfClJbcnh3EY4jtPE4zsb5ztae96bVF79A==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.4.2.tgz", + "integrity": "sha512-XZ4ln/KV4KT+PXdIWTKjsLY+quqCaEtqqtgGJVPw9AoM73By03ij64YjepK0aQvHSWDb6AfAZwqKaFu68qkrdA==", "optional": true, "dependencies": { "streamx": "^2.20.0" @@ -5825,9 +5825,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001683", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001683.tgz", - "integrity": "sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==", + "version": "1.0.30001684", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", + "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", "funding": [ { "type": "opencollective", @@ -7380,9 +7380,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.63", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", - "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==" + "version": "1.5.65", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", + "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -7670,13 +7670,13 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -11054,11 +11054,14 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", + "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12236,9 +12239,9 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -13859,9 +13862,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -14505,17 +14508,17 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", + "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", + "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" + "gopd": "^1.0.1", + "which-builtin-type": "^1.1.4" }, "engines": { "node": ">= 0.4" @@ -14582,14 +14585,14 @@ } }, "node_modules/regexpu-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", - "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", - "regjsparser": "^0.11.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -14628,9 +14631,9 @@ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" }, "node_modules/regjsparser": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", - "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dependencies": { "jsesc": "~3.0.2" }, @@ -16252,9 +16255,9 @@ "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==" }, "node_modules/ts-api-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", - "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.2.tgz", + "integrity": "sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==", "dev": true, "engines": { "node": ">=16" @@ -16396,16 +16399,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -16415,16 +16419,16 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -16494,9 +16498,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", @@ -16956,15 +16960,16 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", - "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", + "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", "dependencies": { + "call-bind": "^1.0.7", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", + "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.1.4", "is-weakref": "^1.0.2",