diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e67862d..6ccb301 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: # Commitizen enforces semantic and conventional commit messages. - repo: https://github.com/commitizen-tools/commitizen - rev: v4.8.2 + rev: v4.13.9 hooks: - id: commitizen name: Check conventional commit message @@ -23,7 +23,7 @@ repos: # Enable a whole bunch of useful helper hooks, too. # See https://pre-commit.com/hooks.html for more hooks. - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-case-conflict - id: check-merge-conflict @@ -43,7 +43,7 @@ repos: # Check and prettify the configuration files. - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.14.0 + rev: v2.16.0 hooks: - id: pretty-format-yaml args: [--autofix] @@ -57,7 +57,7 @@ repos: # Sort imports. - repo: https://github.com/pycqa/isort - rev: 6.0.1 + rev: 8.0.1 hooks: - id: isort name: Sort import statements @@ -67,25 +67,25 @@ repos: # Add Black code formatters. - repo: https://github.com/ambv/black - rev: 25.1.0 + rev: 26.3.1 hooks: - id: black name: Format code files: ^backend/ args: [--config, backend/develop.toml] - repo: https://github.com/asottile/blacken-docs - rev: 1.19.1 + rev: 1.20.0 hooks: - id: blacken-docs name: Format code in docstrings files: ^backend/ types: [text, python] args: [--line-length, '120'] - additional_dependencies: [black==25.1.0] + additional_dependencies: [black==26.3.1] # Upgrade and rewrite Python idioms. - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.2 hooks: - id: pyupgrade name: Upgrade code idioms @@ -95,13 +95,13 @@ repos: # Similar to pylint, with a few more/different checks. For more available # extensions: https://github.com/DmytroLitvinov/awesome-flake8-extensions - repo: https://github.com/pycqa/flake8 - rev: 7.2.0 + rev: 7.3.0 hooks: - id: flake8 name: Check flake8 issues files: ^backend/src/template_jobs/|^backend/tests/ types: [text, python] - additional_dependencies: [flake8-bugbear==24.12.12, flake8-builtins==2.5.0, flake8-comprehensions==3.16.0, flake8-docstrings==1.7.0, flake8-logging==1.7.0, flake8-mutable==1.2.0, flake8-noqa==1.4.0, flake8-print==5.0.0, flake8-pyi==25.5.0, flake8-pytest-style==2.1.0, flake8-rst-docstrings==0.3.1, pep8-naming==0.15.1] + additional_dependencies: [flake8-bugbear==25.11.29, flake8-builtins==3.1.0, flake8-comprehensions==3.17.0, flake8-docstrings==1.7.0, flake8-logging==1.8.0, flake8-mutable==1.2.0, flake8-noqa==1.4.0, flake8-print==5.0.0, flake8-pyi==25.5.0, flake8-pytest-style==2.2.0, flake8-rst-docstrings==0.4.0, pep8-naming==0.15.1] args: [--config, backend/.flake8] # Run Pylint from the local repo to make sure venv packages @@ -129,7 +129,7 @@ repos: # Check for potential security issues. - repo: https://github.com/PyCQA/bandit - rev: 1.8.3 + rev: 1.9.4 hooks: - id: bandit name: Check for security issues diff --git a/backend/alembic-requirements.txt b/backend/alembic-requirements.txt index fe9da0f..c4c7b52 100644 --- a/backend/alembic-requirements.txt +++ b/backend/alembic-requirements.txt @@ -1,256 +1,278 @@ # https://pip.pypa.io/en/stable/reference/requirements-file-format/ -alembic==1.15.2 \ - --hash=sha256:2e76bd916d547f6900ec4bb5a90aeac1485d2c92536923d0b138c02b126edc53 \ - --hash=sha256:1c72391bbdeffccfe317eefba686cb9a3c078005478885413b95c3b26c57a8a7 -greenlet==3.2.2 \ - --hash=sha256:c49e9f7c6f625507ed83a7485366b46cbe325717c60837f7244fc99ba16ba9d6 \ - --hash=sha256:c3cc1a3ed00ecfea8932477f729a9f616ad7347a5e55d50929efa50a86cb7be7 \ - --hash=sha256:7c9896249fbef2c615853b890ee854f22c671560226c9221cfd27c995db97e5c \ - --hash=sha256:7409796591d879425997a518138889d8d17e63ada7c99edc0d7a1c22007d4907 \ - --hash=sha256:7791dcb496ec53d60c7f1c78eaa156c21f402dda38542a00afc3e20cae0f480f \ - --hash=sha256:d8009ae46259e31bc73dc183e402f548e980c96f33a6ef58cc2e7865db012e13 \ - --hash=sha256:fd9fb7c941280e2c837b603850efc93c999ae58aae2b40765ed682a6907ebbc5 \ - --hash=sha256:00cd814b8959b95a546e47e8d589610534cfb71f19802ea8a2ad99d95d702057 \ - --hash=sha256:d0cb7d47199001de7658c213419358aa8937df767936506db0db7ce1a71f4a2f \ - --hash=sha256:dcb9cebbf3f62cb1e5afacae90761ccce0effb3adaa32339a0670fe7805d8068 \ - --hash=sha256:bf3fc9145141250907730886b031681dfcc0de1c158f3cc51c092223c0f381ce \ - --hash=sha256:efcdfb9df109e8a3b475c016f60438fcd4be68cd13a365d42b35914cdab4bb2b \ - --hash=sha256:4bd139e4943547ce3a56ef4b8b1b9479f9e40bb47e72cc906f0f66b9d0d5cab3 \ - --hash=sha256:71566302219b17ca354eb274dfd29b8da3c268e41b646f330e324e3967546a74 \ - --hash=sha256:3091bc45e6b0c73f225374fefa1536cd91b1e987377b12ef5b19129b07d93ebe \ - --hash=sha256:44671c29da26539a5f142257eaba5110f71887c24d40df3ac87f1117df589e0e \ - --hash=sha256:c23ea227847c9dbe0b3910f5c0dd95658b607137614eb821e6cbaecd60d81cc6 \ - --hash=sha256:0a16fb934fcabfdfacf21d79e6fed81809d8cd97bc1be9d9c89f0e4567143d7b \ - --hash=sha256:df4d1509efd4977e6a844ac96d8be0b9e5aa5d5c77aa27ca9f4d3f92d3fcf330 \ - --hash=sha256:da956d534a6d1b9841f95ad0f18ace637668f680b1339ca4dcfb2c1837880a0b \ - --hash=sha256:9c7b15fb9b88d9ee07e076f5a683027bc3befd5bb5d25954bb633c385d8b737e \ - --hash=sha256:752f0e79785e11180ebd2e726c8a88109ded3e2301d40abced2543aa5d164275 \ - --hash=sha256:9ae572c996ae4b5e122331e12bbb971ea49c08cc7c232d1bd43150800a2d6c65 \ - --hash=sha256:02f5972ff02c9cf615357c17ab713737cccfd0eaf69b951084a9fd43f39833d3 \ - --hash=sha256:4fefc7aa68b34b9224490dfda2e70ccf2131368493add64b4ef2d372955c207e \ - --hash=sha256:a31ead8411a027c2c4759113cf2bd473690517494f3d6e4bf67064589afcd3c5 \ - --hash=sha256:b24c7844c0a0afc3ccbeb0b807adeefb7eff2b5599229ecedddcfeb0ef333bec \ - --hash=sha256:3ab7194ee290302ca15449f601036007873028712e92ca15fc76597a0aeb4c59 \ - --hash=sha256:2dc5c43bb65ec3669452af0ab10729e8fdc17f87a1f2ad7ec65d4aaaefabf6bf \ - --hash=sha256:decb0658ec19e5c1f519faa9a160c0fc85a41a7e6654b3ce1b44b939f8bf1325 \ - --hash=sha256:6fadd183186db360b61cb34e81117a096bff91c072929cd1b529eb20dd46e6c5 \ - --hash=sha256:1919cbdc1c53ef739c94cf2985056bcc0838c1f217b57647cbf4578576c63825 \ - --hash=sha256:3885f85b61798f4192d544aac7b25a04ece5fe2704670b4ab73c2d2c14ab740d \ - --hash=sha256:85f3e248507125bf4af607a26fd6cb8578776197bd4b66e35229cdf5acf1dfbf \ - --hash=sha256:1e76106b6fc55fa3d6fe1c527f95ee65e324a13b62e243f77b48317346559708 \ - --hash=sha256:ba30e88607fb6990544d84caf3c706c4b48f629e18853fc6a646f82db9629418 \ - --hash=sha256:055916fafad3e3388d27dd68517478933a97edc2fc54ae79d3bec827de2c64c4 \ - --hash=sha256:2593283bf81ca37d27d110956b79e8723f9aa50c4bcdc29d3c0543d4743d2763 \ - --hash=sha256:89c69e9a10670eb7a66b8cef6354c24671ba241f46152dd3eed447f79c29fb5b \ - --hash=sha256:02a98600899ca1ca5d3a2590974c9e3ec259503b2d6ba6527605fcd74e08e207 \ - --hash=sha256:b50a8c5c162469c3209e5ec92ee4f95c8231b11db6a04db09bbe338176723bb8 \ - --hash=sha256:45f9f4853fb4cc46783085261c9ec4706628f3b57de3e68bae03e8f8b3c0de51 \ - --hash=sha256:fe46d4f8e94e637634d54477b0cfabcf93c53f29eedcbdeecaf2af32029b4421 \ - --hash=sha256:9ea5231428af34226c05f927e16fc7f6fa5e39e3ad3cd24ffa48ba53a47f4240 \ - --hash=sha256:1e4747712c4365ef6765708f948acc9c10350719ca0545e362c24ab973017370 \ - --hash=sha256:782743700ab75716650b5238a4759f840bb2dcf7bff56917e9ffdf9f1f23ec59 \ - --hash=sha256:354f67445f5bed6604e493a06a9a49ad65675d3d03477d38a4db4a427e9aad0e \ - --hash=sha256:3aeca9848d08ce5eb653cf16e15bb25beeab36e53eb71cc32569f5f3afb2a3aa \ - --hash=sha256:8cb8553ee954536500d88a1a2f58fcb867e45125e600e80f586ade399b3f8819 \ - --hash=sha256:1592a615b598643dbfd566bac8467f06c8c8ab6e56f069e573832ed1d5d528cc \ - --hash=sha256:1f72667cc341c95184f1c68f957cb2d4fc31eef81646e8e59358a10ce6689457 \ - --hash=sha256:a8fa80665b1a29faf76800173ff5325095f3e66a78e62999929809907aca5659 \ - --hash=sha256:6629311595e3fe7304039c67f00d145cd1d38cf723bb5b99cc987b23c1433d61 \ - --hash=sha256:eeb27bece45c0c2a5842ac4c5a1b5c2ceaefe5711078eed4e8043159fa05c834 \ - --hash=sha256:ad053d34421a2debba45aa3cc39acf454acbcd025b3fc1a9f8a0dee237abd485 +alembic==1.18.4 \ + --hash=sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a \ + --hash=sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc +greenlet==3.3.2 \ + --hash=sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d \ + --hash=sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13 \ + --hash=sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e \ + --hash=sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7 \ + --hash=sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f \ + --hash=sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef \ + --hash=sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca \ + --hash=sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f \ + --hash=sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86 \ + --hash=sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f \ + --hash=sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55 \ + --hash=sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2 \ + --hash=sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358 \ + --hash=sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99 \ + --hash=sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be \ + --hash=sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5 \ + --hash=sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd \ + --hash=sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd \ + --hash=sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd \ + --hash=sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac \ + --hash=sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb \ + --hash=sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070 \ + --hash=sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79 \ + --hash=sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395 \ + --hash=sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f \ + --hash=sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643 \ + --hash=sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4 \ + --hash=sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986 \ + --hash=sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92 \ + --hash=sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd \ + --hash=sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab \ + --hash=sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a \ + --hash=sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b \ + --hash=sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124 \ + --hash=sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327 \ + --hash=sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab \ + --hash=sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082 \ + --hash=sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9 \ + --hash=sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9 \ + --hash=sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506 \ + --hash=sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce \ + --hash=sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5 \ + --hash=sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54 \ + --hash=sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4 \ + --hash=sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff \ + --hash=sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf \ + --hash=sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4 \ + --hash=sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727 \ + --hash=sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e \ + --hash=sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a \ + --hash=sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492 \ + --hash=sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71 \ + --hash=sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2 Mako==1.3.10 \ --hash=sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59 \ --hash=sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28 -MarkupSafe==3.0.2 \ - --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \ - --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \ - --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \ - --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \ - --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \ - --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \ - --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \ - --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \ - --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 \ - --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \ - --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \ - --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \ - --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \ - --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \ - --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \ - --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \ - --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \ - --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ - --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \ - --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \ - --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ - --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ - --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ - --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ - --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ - --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ - --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ - --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ - --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ - --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ - --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ - --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ - --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ - --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ - --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ - --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ - --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ - --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ - --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ - --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ - --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ - --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ - --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ - --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ - --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ - --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ - --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ - --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ - --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ - --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ - --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \ - --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \ - --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \ - --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \ - --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \ - --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \ - --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \ - --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \ - --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \ - --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \ - --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 -psycopg==3.2.9 \ - --hash=sha256:01a8dadccdaac2123c916208c96e06631641c0566b22005493f09663c7a8d3b6 \ - --hash=sha256:2fbb46fcd17bc81f993f28c47f1ebea38d66ae97cc2dbc3cad73b37cefbff700 -psycopg-binary==3.2.9 \ - --hash=sha256:528239bbf55728ba0eacbd20632342867590273a9bacedac7538ebff890f1093 \ - --hash=sha256:e4978c01ca4c208c9d6376bd585e2c0771986b76ff7ea518f6d2b51faece75e8 \ - --hash=sha256:1ed2bab85b505d13e66a914d0f8cdfa9475c16d3491cf81394e0748b77729af2 \ - --hash=sha256:799fa1179ab8a58d1557a95df28b492874c8f4135101b55133ec9c55fc9ae9d7 \ - --hash=sha256:bb37ac3955d19e4996c3534abfa4f23181333974963826db9e0f00731274b695 \ - --hash=sha256:001e986656f7e06c273dd4104e27f4b4e0614092e544d950c7c938d822b1a894 \ - --hash=sha256:fa5c80d8b4cbf23f338db88a7251cef8bb4b68e0f91cf8b6ddfa93884fdbb0c1 \ - --hash=sha256:39a127e0cf9b55bd4734a8008adf3e01d1fd1cb36339c6a9e2b2cbb6007c50ee \ - --hash=sha256:fb7599e436b586e265bea956751453ad32eb98be6a6e694252f4691c31b16edb \ - --hash=sha256:5d2c9fe14fe42b3575a0b4e09b081713e83b762c8dc38a3771dd3265f8f110e7 \ - --hash=sha256:7e4660fad2807612bb200de7262c88773c3483e85d981324b3c647176e41fdc8 \ - --hash=sha256:2504e9fd94eabe545d20cddcc2ff0da86ee55d76329e1ab92ecfcc6c0a8156c4 \ - --hash=sha256:093a0c079dd6228a7f3c3d82b906b41964eaa062a9a8c19f45ab4984bf4e872b \ - --hash=sha256:387c87b51d72442708e7a853e7e7642717e704d59571da2f3b29e748be58c78a \ - --hash=sha256:d9ac10a2ebe93a102a326415b330fff7512f01a9401406896e78a81d75d6eddc \ - --hash=sha256:72fdbda5b4c2a6a72320857ef503a6589f56d46821592d4377c8c8604810342b \ - --hash=sha256:f34e88940833d46108f949fdc1fcfb74d6b5ae076550cd67ab59ef47555dba95 \ - --hash=sha256:a3e0f89fe35cb03ff1646ab663dabf496477bab2a072315192dbaa6928862891 \ - --hash=sha256:6afb3e62f2a3456f2180a4eef6b03177788df7ce938036ff7f09b696d418d186 \ - --hash=sha256:cc19ed5c7afca3f6b298bfc35a6baa27adb2019670d15c32d0bb8f780f7d560d \ - --hash=sha256:bc75f63653ce4ec764c8f8c8b0ad9423e23021e1c34a84eb5f4ecac8538a4a4a \ - --hash=sha256:3db3ba3c470801e94836ad78bf11fd5fab22e71b0c77343a1ee95d693879937a \ - --hash=sha256:be7d650a434921a6b1ebe3fff324dbc2364393eb29d7672e638ce3e21076974e \ - --hash=sha256:6a76b4722a529390683c0304501f238b365a46b1e5fb6b7249dbc0ad6fea51a0 \ - --hash=sha256:96a551e4683f1c307cfc3d9a05fec62c00a7264f320c9962a67a543e3ce0d8ff \ - --hash=sha256:61d0a6ceed8f08c75a395bc28cb648a81cf8dee75ba4650093ad1a24a51c8724 \ - --hash=sha256:ad280bbd409bf598683dda82232f5215cfc5f2b1bf0854e409b4d0c44a113b1d \ - --hash=sha256:76eddaf7fef1d0994e3d536ad48aa75034663d3a07f6f7e3e601105ae73aeff6 \ - --hash=sha256:52e239cd66c4158e412318fbe028cd94b0ef21b0707f56dcb4bdc250ee58fd40 \ - --hash=sha256:08bf9d5eabba160dd4f6ad247cf12f229cc19d2458511cab2eb9647f42fa6795 \ - --hash=sha256:1b2cf018168cad87580e67bdde38ff5e51511112f1ce6ce9a8336871f465c19a \ - --hash=sha256:14f64d1ac6942ff089fc7e926440f7a5ced062e2ed0949d7d2d680dc5c00e2d4 \ - --hash=sha256:7a838852e5afb6b4126f93eb409516a8c02a49b788f4df8b6469a40c2157fa21 \ - --hash=sha256:98bbe35b5ad24a782c7bf267596638d78aa0e87abc7837bdac5b2a2ab954179e \ - --hash=sha256:72691a1615ebb42da8b636c5ca9f2b71f266be9e172f66209a361c175b7842c5 \ - --hash=sha256:25ab464bfba8c401f5536d5aa95f0ca1dd8257b5202eede04019b4415f491351 \ - --hash=sha256:0e8aeefebe752f46e3c4b769e53f1d4ad71208fe1150975ef7662c22cca80fab \ - --hash=sha256:b7e4e4dd177a8665c9ce86bc9caae2ab3aa9360b7ce7ec01827ea1baea9ff748 \ - --hash=sha256:7fc2915949e5c1ea27a851f7a472a7da7d0a40d679f0a31e42f1022f3c562e87 \ - --hash=sha256:a1fa38a4687b14f517f049477178093c39c2a10fdcced21116f47c017516498f \ - --hash=sha256:5be8292d07a3ab828dc95b5ee6b69ca0a5b2e579a577b39671f4f5b47116dfd2 \ - --hash=sha256:778588ca9897b6c6bab39b0d3034efff4c5438f5e3bd52fda3914175498202f9 \ - --hash=sha256:f0d5b3af045a187aedbd7ed5fc513bd933a97aaff78e61c3745b330792c4345b \ - --hash=sha256:2290bc146a1b6a9730350f695e8b670e1d1feb8446597bed0bbe7c3c30e0abcb \ - --hash=sha256:4df22ec17390ec5ccb38d211fb251d138d37a43344492858cea24de8efa15003 \ - --hash=sha256:eac3a6e926421e976c1c2653624e1294f162dc67ac55f9addbe8f7b8d08ce603 \ - --hash=sha256:cf789be42aea5752ee396d58de0538d5fcb76795c85fb03ab23620293fb81b6f \ - --hash=sha256:e0f05b9dafa5670a7503abc715af081dbbb176a8e6770de77bccaeb9024206c5 \ - --hash=sha256:b2d7a6646d41228e9049978be1f3f838b557a1bde500b919906d54c4390f5086 \ - --hash=sha256:a4d76e28df27ce25dc19583407f5c6c6c2ba33b443329331ab29b6ef94c8736d \ - --hash=sha256:418f52b77b715b42e8ec43ee61ca74abc6765a20db11e8576e7f6586488a266f \ - --hash=sha256:1f1736d5b21f69feefeef8a75e8d3bf1f0a1e17c165a7488c3111af9d6936e91 \ - --hash=sha256:5918c0fab50df764812f3ca287f0d716c5c10bedde93d4da2cefc9d40d03f3aa \ - --hash=sha256:7b617b81f08ad8def5edd110de44fd6d326f969240cc940c6f6b3ef21fe9c59f \ - --hash=sha256:587a3f19954d687a14e0c8202628844db692dbf00bba0e6d006659bf1ca91cbe \ - --hash=sha256:791759138380df21d356ff991265fde7fe5997b0c924a502847a9f9141e68786 \ - --hash=sha256:95315b8c8ddfa2fdcb7fe3ddea8a595c1364524f512160c604e3be368be9dd07 \ - --hash=sha256:18ac08475c9b971237fcc395b0a6ee4e8580bb5cf6247bc9b8461644bef5d9f4 \ - --hash=sha256:ac2c04b6345e215e65ca6aef5c05cc689a960b16674eaa1f90a8f86dfaee8c04 \ - --hash=sha256:4c1ab25e3134774f1e476d4bb9050cdec25f10802e63e92153906ae934578734 \ - --hash=sha256:4bfec4a73e8447d8fe8854886ffa78df2b1c279a7592241c2eb393d4499a17e2 \ - --hash=sha256:166acc57af5d2ff0c0c342aed02e69a0cd5ff216cae8820c1059a6f3b7cf5f78 \ - --hash=sha256:413f9e46259fe26d99461af8e1a2b4795a4e27cc8ac6f7919ec19bcee8945074 \ - --hash=sha256:354dea21137a316b6868ee41c2ae7cce001e104760cf4eab3ec85627aed9b6cd \ - --hash=sha256:24ddb03c1ccfe12d000d950c9aba93a7297993c4e3905d9f2c9795bb0764d523 -SQLAlchemy==2.0.41 \ - --hash=sha256:b1f09b6821406ea1f94053f346f28f8215e293344209129a9c0fcc3578598d7b \ - --hash=sha256:1936af879e3db023601196a1684d28e12f19ccf93af01bf3280a3262c4b6b4e5 \ - --hash=sha256:b2ac41acfc8d965fb0c464eb8f44995770239668956dc4cdf502d1b1ffe0d747 \ - --hash=sha256:81c24e0c0fde47a9723c81d5806569cddef103aebbf79dbc9fcbb617153dea30 \ - --hash=sha256:23a8825495d8b195c4aa9ff1c430c28f2c821e8c5e2d98089228af887e5d7e29 \ - --hash=sha256:60c578c45c949f909a4026b7807044e7e564adf793537fc762b2489d522f3d11 \ - --hash=sha256:118c16cd3f1b00c76d69343e38602006c9cfb9998fa4f798606d28d63f23beda \ - --hash=sha256:7492967c3386df69f80cf67efd665c0f667cee67032090fe01d7d74b0e19bb08 \ - --hash=sha256:6375cd674fe82d7aa9816d1cb96ec592bac1726c11e0cafbf40eeee9a4516b5f \ - --hash=sha256:9f8c9fdd15a55d9465e590a402f42082705d66b05afc3ffd2d2eb3c6ba919560 \ - --hash=sha256:32f9dc8c44acdee06c8fc6440db9eae8b4af8b01e4b1aee7bdd7241c22edff4f \ - --hash=sha256:90c11ceb9a1f482c752a71f203a81858625d8df5746d787a4786bca4ffdf71c6 \ - --hash=sha256:911cc493ebd60de5f285bcae0491a60b4f2a9f0f5c270edd1c4dbaef7a38fc04 \ - --hash=sha256:03968a349db483936c249f4d9cd14ff2c296adfa1290b660ba6516f973139582 \ - --hash=sha256:293cd444d82b18da48c9f71cd7005844dbbd06ca19be1ccf6779154439eec0b8 \ - --hash=sha256:3d3549fc3e40667ec7199033a4e40a2f669898a00a7b18a931d3efb4c7900504 \ - --hash=sha256:81f413674d85cfd0dfcd6512e10e0f33c19c21860342a4890c3a2b59479929f9 \ - --hash=sha256:598d9ebc1e796431bbd068e41e4de4dc34312b7aa3292571bb3674a0cb415dd1 \ - --hash=sha256:a104c5694dfd2d864a6f91b0956eb5d5883234119cb40010115fd45a16da5e70 \ - --hash=sha256:6145afea51ff0af7f2564a05fa95eb46f542919e6523729663a5d285ecb3cf5e \ - --hash=sha256:b46fa6eae1cd1c20e6e6f44e19984d438b6b2d8616d21d783d150df714f44078 \ - --hash=sha256:41836fe661cc98abfae476e14ba1906220f92c4e528771a8a3ae6a151242d2ae \ - --hash=sha256:a8808d5cf866c781150d36a3c8eb3adccfa41a8105d031bf27e92c251e3969d6 \ - --hash=sha256:5b14e97886199c1f52c14629c11d90c11fbb09e9334fa7bb5f6d068d9ced0ce0 \ - --hash=sha256:4eeb195cdedaf17aab6b247894ff2734dcead6c08f748e617bfe05bd5a218443 \ - --hash=sha256:d4ae769b9c1c7757e4ccce94b0641bc203bbdf43ba7a2413ab2523d8d047d8dc \ - --hash=sha256:a62448526dd9ed3e3beedc93df9bb6b55a436ed1474db31a2af13b313a70a7e1 \ - --hash=sha256:dc56c9788617b8964ad02e8fcfeed4001c1f8ba91a9e1f31483c0dffb207002a \ - --hash=sha256:c153265408d18de4cc5ded1941dcd8315894572cddd3c58df5d5b5705b3fa28d \ - --hash=sha256:4f67766965996e63bb46cfbf2ce5355fc32d9dd3b8ad7e536a920ff9ee422e23 \ - --hash=sha256:bfc9064f6658a3d1cadeaa0ba07570b83ce6801a1314985bf98ec9b95d74e15f \ - --hash=sha256:82ca366a844eb551daff9d2e6e7a9e5e76d2612c8564f58db6c19a726869c1df \ - --hash=sha256:6854175807af57bdb6425e47adbce7d20a4d79bbfd6f6d6519cd10bb7109a7f8 \ - --hash=sha256:05132c906066142103b83d9c250b60508af556982a385d96c4eaa9fb9720ac2b \ - --hash=sha256:8b4af17bda11e907c51d10686eda89049f9ce5669b08fbe71a29747f1e876036 \ - --hash=sha256:c0b0e5e1b5d9f3586601048dd68f392dc0cc99a59bb5faf18aab057ce00d00b2 \ - --hash=sha256:0b3dbf1e7e9bc95f4bac5e2fb6d3fb2f083254c3fdd20a1789af965caf2d2348 \ - --hash=sha256:1e3f196a0c59b0cae9a0cd332eb1a4bda4696e863f4f1cf84ab0347992c548c2 \ - --hash=sha256:6ab60a5089a8f02009f127806f777fca82581c49e127f08413a66056bd9166dd \ - --hash=sha256:90144d3b0c8b139408da50196c5cad2a6909b51b23df1f0538411cd23ffa45d3 \ - --hash=sha256:023b3ee6169969beea3bb72312e44d8b7c27c75b347942d943cf49397b7edeb5 \ - --hash=sha256:725875a63abf7c399d4548e686debb65cdc2549e1825437096a0af1f7e374814 \ - --hash=sha256:81965cc20848ab06583506ef54e37cf15c83c7e619df2ad16807c03100745dea \ - --hash=sha256:dd5ec3aa6ae6e4d5b5de9357d2133c07be1aff6405b136dad753a16afb6717dd \ - --hash=sha256:ff8e80c4c4932c10493ff97028decfdb622de69cae87e0f127a7ebe32b4069c6 \ - --hash=sha256:4d44522480e0bf34c3d63167b8cfa7289c1c54264c2950cc5fc26e7850967e45 \ - --hash=sha256:81eedafa609917040d39aa9332e25881a8e7a0862495fcdf2023a9667209deda \ - --hash=sha256:9a420a91913092d1e20c86a2f5f1fc85c1a8924dbcaf5e0586df8aceb09c9cc2 \ - --hash=sha256:906e6b0d7d452e9a98e5ab8507c0da791856b2380fdee61b765632bb8698026f \ - --hash=sha256:a373a400f3e9bac95ba2a06372c4fd1412a7cee53c37fc6c05f829bf672b8769 \ - --hash=sha256:087b6b52de812741c27231b5a3586384d60c353fbd0e2f81405a814b5591dc8b \ - --hash=sha256:34ea30ab3ec98355235972dadc497bb659cc75f8292b760394824fab9cf39826 \ - --hash=sha256:8280856dd7c6a68ab3a164b4a4b1c51f7691f6d04af4d4ca23d6ecf2261b7923 \ - --hash=sha256:b50eab9994d64f4a823ff99a0ed28a6903224ddbe7fef56a6dd865eec9243440 \ - --hash=sha256:5e22575d169529ac3e0a120cf050ec9daa94b6a9597993d1702884f6954a7d71 \ - --hash=sha256:57df5dc6fdb5ed1a88a1ed2195fd31927e705cad62dedd86b46972752a80f576 \ - --hash=sha256:edba70118c4be3c2b1f90754d308d0b79c6fe2c0fdc52d8ddf603916f83f4db9 -typing_extensions==4.14.0 \ - --hash=sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af \ - --hash=sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4 +MarkupSafe==3.0.3 \ + --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ + --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ + --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ + --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ + --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ + --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ + --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ + --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ + --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ + --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ + --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ + --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ + --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ + --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ + --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ + --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ + --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ + --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ + --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ + --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ + --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ + --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ + --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ + --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ + --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ + --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ + --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ + --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ + --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ + --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ + --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ + --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ + --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ + --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ + --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ + --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ + --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ + --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ + --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ + --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ + --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ + --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ + --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ + --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ + --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ + --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ + --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ + --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ + --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ + --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ + --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ + --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ + --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ + --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ + --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ + --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ + --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ + --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ + --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ + --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ + --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ + --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ + --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ + --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ + --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ + --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ + --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 \ + --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ + --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ + --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ + --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ + --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ + --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ + --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ + --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ + --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ + --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ + --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ + --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ + --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ + --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ + --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ + --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ + --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ + --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ + --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ + --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ + --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ + --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 +psycopg==3.3.3 \ + --hash=sha256:f96525a72bcfade6584ab17e89de415ff360748c766f0106959144dcbb38c698 \ + --hash=sha256:5e9a47458b3c1583326513b2556a2a9473a1001a56c9efe9e587245b43148dd9 +psycopg-binary==3.3.3 \ + --hash=sha256:b3385b58b2fe408a13d084c14b8dcf468cd36cbbe774408250facc128f9fa75c \ + --hash=sha256:1bef235a50a80f6aba05147002bc354559657cb6386dbd04d8e1c97d1d7cbe84 \ + --hash=sha256:97c839717bf8c8df3f6d983a20949c4fb22e2a34ee172e3e427ede363feda27b \ + --hash=sha256:48e500cf1c0984dacf1f28ea482c3cdbb4c2288d51c336c04bc64198ab21fc51 \ + --hash=sha256:eb36a08859b9432d94ea6b26ec41a2f98f83f14868c91321d0c1e11f672eeae7 \ + --hash=sha256:0dde92cfde09293fb63b3f547919ba7d73bd2654573c03502b3263dd0218e44e \ + --hash=sha256:78c9ce98caaf82ac8484d269791c1b403d7598633e0e4e2fa1097baae244e2f1 \ + --hash=sha256:d593612758d0041cb13cb0003f7f8d3fabb7ad9319e651e78afae49b1cf5860e \ + --hash=sha256:f24e8e17035200a465c178e9ea945527ad0738118694184c450f1192a452ff25 \ + --hash=sha256:e7b607f0e14f2a4cf7e78a05ebd13df6144acfba87cb90842e70d3f125d9f53f \ + --hash=sha256:b27d3a23c79fa59557d2cc63a7e8bb4c7e022c018558eda36f9d7c4e6b99a6e0 \ + --hash=sha256:a89bb9ee11177b2995d87186b1d9fa892d8ea725e85eab28c6525e4cc14ee048 \ + --hash=sha256:9f7d0cf072c6fbac3795b08c98ef9ea013f11db609659dcfc6b1f6cc31f9e181 \ + --hash=sha256:90eecd93073922f085967f3ed3a98ba8c325cbbc8c1a204e300282abd2369e13 \ + --hash=sha256:dac7ee2f88b4d7bb12837989ca354c38d400eeb21bce3b73dac02622f0a3c8d6 \ + --hash=sha256:b62cf8784eb6d35beaee1056d54caf94ec6ecf2b7552395e305518ab61eb8fd2 \ + --hash=sha256:a39f34c9b18e8f6794cca17bfbcd64572ca2482318db644268049f8c738f35a6 \ + --hash=sha256:883d68d48ca9ff3cb3d10c5fdebea02c79b48eecacdddbf7cce6e7cdbdc216b8 \ + --hash=sha256:cab7bc3d288d37a80aa8c0820033250c95e40b1c2b5c57cf59827b19c2a8b69d \ + --hash=sha256:56c767007ca959ca32f796b42379fc7e1ae2ed085d29f20b05b3fc394f3715cc \ + --hash=sha256:da2f331a01af232259a21573a01338530c6016dcfad74626c01330535bcd8628 \ + --hash=sha256:19f93235ece6dbfc4036b5e4f6d8b13f0b8f2b3eeb8b0bd2936d406991bcdd40 \ + --hash=sha256:6698dbab5bcef8fdb570fc9d35fd9ac52041771bfcfe6fd0fc5f5c4e36f1e99d \ + --hash=sha256:329ff393441e75f10b673ae99ab45276887993d49e65f141da20d915c05aafd8 \ + --hash=sha256:eb072949b8ebf4082ae24289a2b0fd724da9adc8f22743409d6fd718ddb379df \ + --hash=sha256:263a24f39f26e19ed7fc982d7859a36f17841b05bebad3eb47bb9cd2dd785351 \ + --hash=sha256:5152d50798c2fa5bd9b68ec68eb68a1b71b95126c1d70adaa1a08cd5eefdc23d \ + --hash=sha256:9d6a1e56dd267848edb824dbeb08cf5bac649e02ee0b03ba883ba3f4f0bd54f2 \ + --hash=sha256:73eaaf4bb04709f545606c1db2f65f4000e8a04cdbf3e00d165a23004692093e \ + --hash=sha256:162e5675efb4704192411eaf8e00d07f7960b679cd3306e7efb120bb8d9456cc \ + --hash=sha256:fab6b5e37715885c69f5d091f6ff229be71e235f272ebaa35158d5a46fd548a0 \ + --hash=sha256:a4aab31bd6d1057f287c96c0effca3a25584eb9cc702f282ecb96ded7814e830 \ + --hash=sha256:59aa31fe11a0e1d1bcc2ce37ed35fe2ac84cd65bb9036d049b1a1c39064d0f14 \ + --hash=sha256:05f32239aec25c5fb15f7948cffdc2dc0dac098e48b80a140e4ba32b572a2e7d \ + --hash=sha256:7c84f9d214f2d1de2fafebc17fa68ac3f6561a59e291553dfc45ad299f4898c1 \ + --hash=sha256:e77957d2ba17cada11be09a5066d93026cdb61ada7c8893101d7fe1c6e1f3925 \ + --hash=sha256:42961609ac07c232a427da7c87a468d3c82fee6762c220f38e37cfdacb2b178d \ + --hash=sha256:ae07a3114313dd91fce686cab2f4c44af094398519af0e0f854bc707e1aeedf1 \ + --hash=sha256:d257c58d7b36a621dcce1d01476ad8b60f12d80eb1406aee4cf796f88b2ae482 \ + --hash=sha256:07c7211f9327d522c9c47560cae00a4ecf6687f4e02d779d035dd3177b41cb12 \ + --hash=sha256:8e7e9eca9b363dbedeceeadd8be97149d2499081f3c52d141d7cd1f395a91f83 \ + --hash=sha256:cb85b1d5702877c16f28d7b92ba030c1f49ebcc9b87d03d8c10bf45a2f1c7508 \ + --hash=sha256:4d4606c84d04b80f9138d72f1e28c6c02dc5ae0c7b8f3f8aaf89c681ce1cd1b1 \ + --hash=sha256:74eae563166ebf74e8d950ff359be037b85723d99ca83f57d9b244a871d6c13b \ + --hash=sha256:497852c5eaf1f0c2d88ab74a64a8097c099deac0c71de1cbcf18659a8a04a4b2 \ + --hash=sha256:258d1ea53464d29768bf25930f43291949f4c7becc706f6e220c515a63a24edd \ + --hash=sha256:111c59897a452196116db12e7f608da472fbff000693a21040e35fc978b23430 \ + --hash=sha256:17bb6600e2455993946385249a3c3d0af52cd70c1c1cdbf712e9d696d0b0bf1b \ + --hash=sha256:642050398583d61c9856210568eb09a8e4f2fe8224bf3be21b67a370e677eead \ + --hash=sha256:533efe6dc3a7cba5e2a84e38970786bb966306863e45f3db152007e9f48638a6 \ + --hash=sha256:5958dbf28b77ce2033482f6cb9ef04d43f5d8f4b7636e6963d5626f000efb23e \ + --hash=sha256:a6af77b6626ce92b5817bf294b4d45ec1a6161dba80fc2d82cdffdd6814fd023 \ + --hash=sha256:47f06fcbe8542b4d96d7392c476a74ada521c5aebdb41c3c0155f6595fc14c8d \ + --hash=sha256:e7800e6c6b5dc4b0ca7cc7370f770f53ac83886b76afda0848065a674231e856 \ + --hash=sha256:165f22ab5a9513a3d7425ffb7fcc7955ed8ccaeef6d37e369d6cc1dff1582383 +SQLAlchemy==2.0.48 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 +typing_extensions==4.15.0 \ + --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 \ + --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 diff --git a/backend/alembic/versions/7ce2fd1a52c8_initial_database_setup.py b/backend/alembic/versions/7ce2fd1a52c8_initial_database_setup.py index 6cfe898..f373564 100644 --- a/backend/alembic/versions/7ce2fd1a52c8_initial_database_setup.py +++ b/backend/alembic/versions/7ce2fd1a52c8_initial_database_setup.py @@ -44,15 +44,11 @@ def upgrade() -> None: # # Install them into the default `public` schema such that they can be accessed from # both our own `api` and `auth` and `data` schemas. - op.execute( - sa.text( - """ - create extension pgcrypto; - create extension pgjwt; - create extension byteamagic; - """ - ) - ) + op.execute(sa.text(""" + create extension pgcrypto; + create extension pgjwt; + create extension byteamagic; + """)) # Public `api` schema where the API related views and functions live. We configure # this schema for PostgREST as the one for which REST endpoints are constructed. @@ -74,41 +70,29 @@ def upgrade() -> None: # The `anonymous` role PostgREST switches to if no auth header was passed along # with a request. # TODO What about granting usage on `auth` schema? See functions below. - op.execute( - sa.text( - """ - create role anonymous nologin noinherit; -- TODO Other settings? - grant anonymous to authenticator; - grant usage on schema auth, api to anonymous; - grant execute on function public.crypt, public.gen_salt(text), public.sign, public.url_encode, public.algorithm_sign, public.hmac(text, text, text) to anonymous; - """ - ) - ) + op.execute(sa.text(""" + create role anonymous nologin noinherit; -- TODO Other settings? + grant anonymous to authenticator; + grant usage on schema auth, api to anonymous; + grant execute on function public.crypt, public.gen_salt(text), public.sign, public.url_encode, public.algorithm_sign, public.hmac(text, text, text) to anonymous; + """)) # The `apiuser` role PostgREST switches to if JWT auth was successful. # See also: https://postgrest.org/en/stable/references/auth.html#jwt-based-user-impersonation - op.execute( - sa.text( - """ - create role apiuser nologin noinherit; -- TODO Other settings? - grant apiuser to authenticator; - grant usage on schema auth, api, data to apiuser; - grant execute on function public.crypt, public.gen_salt(text), public.byteamagic_mime to apiuser; - """ - ) - ) + op.execute(sa.text(""" + create role apiuser nologin noinherit; -- TODO Other settings? + grant apiuser to authenticator; + grant usage on schema auth, api, data to apiuser; + grant execute on function public.crypt, public.gen_salt(text), public.byteamagic_mime to apiuser; + """)) # The `dramatiq` role is *not* used by PostgREST! Instead, async Dramatiq workers # that need to access the db to fetch and write back data use this role. These # workers are trusted because we built them ourselves. - op.execute( - sa.text( - """ - create role dramatiq login password 'dramatiq' noinherit; -- TODO Other settings? - grant usage on schema data to dramatiq; - """ - ) - ) + op.execute(sa.text(""" + create role dramatiq login password 'dramatiq' noinherit; -- TODO Other settings? + grant usage on schema data to dramatiq; + """)) # The `user` table in the private `auth` schema contains all users in the system. In the # future we might add more roles (e.g. admin, or one role per user account). Furthermore, @@ -117,71 +101,51 @@ def upgrade() -> None: # Lastly we add an insert/update trigger function to hash the password and store that hash. # See also: https://postgrest.org/en/stable/how-tos/sql-user-management.html#storing-users-and-passwords # TODO See also: https://github.com/PostgREST/postgrest/discussions/3696#discussioncomment-10408092 - op.execute( - sa.text( - """ - create table auth.user ( - id bigserial primary key, - created_at timestamp with time zone default now(), - email text unique not null, -- TODO CHECK constraint for email format. - password text not null, -- This is the hash, not the clear text password. - role text not null default 'apiuser' check (role = 'apiuser'), -- TODO FK to known roles? - first_name text, - last_name text - ) - """ - ) - ) - - op.execute( - sa.text( - """ - grant select, insert on auth.user to anonymous; -- TODO Limit select columns! - grant usage on auth.user_id_seq to anonymous; - grant select, update(first_name, last_name) on auth.user to apiuser; -- TODO Limit select columns! - grant select on auth.user to dramatiq; -- TODO Limit select columns! - """ + op.execute(sa.text(""" + create table auth.user ( + id bigserial primary key, + created_at timestamp with time zone default now(), + email text unique not null, -- TODO CHECK constraint for email format. + password text not null, -- This is the hash, not the clear text password. + role text not null default 'apiuser' check (role = 'apiuser'), -- TODO FK to known roles? + first_name text, + last_name text ) - ) - - op.execute( - sa.text( - """ - alter table auth.user enable row level security; - create policy user_email_policy on auth.user to anonymous, apiuser - using ( - current_role = 'anonymous' - or email = (select current_setting('request.jwt.claims', true)::json->>'email') - ); - """ - ) - ) - - op.execute( - sa.text( - """ - create function auth.encrypt_password() returns trigger language plpgsql as $$ - begin - if new.password is not null then - new.password = crypt(new.password, gen_salt('bf')); -- TODO min 8 chars, other rules? - end if; - return new; - end; - $$ - """ - ) - ) - - op.execute( - sa.text( - """ - create trigger encrypt_password - before insert or update on auth.user - for each row - execute procedure auth.encrypt_password(); - """ - ) - ) + """)) + + op.execute(sa.text(""" + grant select, insert on auth.user to anonymous; -- TODO Limit select columns! + grant usage on auth.user_id_seq to anonymous; + grant select, update(first_name, last_name) on auth.user to apiuser; -- TODO Limit select columns! + grant select on auth.user to dramatiq; -- TODO Limit select columns! + """)) + + op.execute(sa.text(""" + alter table auth.user enable row level security; + create policy user_email_policy on auth.user to anonymous, apiuser + using ( + current_role = 'anonymous' + or email = (select current_setting('request.jwt.claims', true)::json->>'email') + ); + """)) + + op.execute(sa.text(""" + create function auth.encrypt_password() returns trigger language plpgsql as $$ + begin + if new.password is not null then + new.password = crypt(new.password, gen_salt('bf')); -- TODO min 8 chars, other rules? + end if; + return new; + end; + $$ + """)) + + op.execute(sa.text(""" + create trigger encrypt_password + before insert or update on auth.user + for each row + execute procedure auth.encrypt_password(); + """)) # The `dramatiq_queue` table implements a message queue of messages for the async framework # Dramatiq. Messages are inserted and trigger a Postgres notification that the Dramatiq broker @@ -191,168 +155,136 @@ def upgrade() -> None: # users are associated with the now-deleted message. # See also: https://gitlab.com/dalibo/dramatiq-pg # See also: https://www.postgresql.org/docs/current/sql-notify.html - op.execute( - sa.text( - """ - create table data.dramatiq_queue( - message_id uuid primary key, - user_id bigint references auth.user(id), - queue_name text not null, - state text not null check (state in ('queued', 'consumed', 'rejected', 'done')), - mtime timestamp with time zone, - message jsonb, - result jsonb, - result_ttl timestamp with time zone - ) -- TODO Consider `without oids` as Dramatiq-PG uses. - """ - ) - ) - - op.execute( - sa.text( - """ - grant select, insert on data.dramatiq_queue to apiuser; - grant all privileges on table data.dramatiq_queue to dramatiq; - """ - ) - ) - - op.execute( - sa.text( - """ - alter table data.dramatiq_queue enable row level security; - create policy user_message_policy on data.dramatiq_queue to apiuser, dramatiq - using ( - current_role = 'dramatiq' - or user_id = ( - select id - from auth.user - where email = (select current_setting('request.jwt.claims', true)::json->>'email') - ) - ); - """ - ) - ) + op.execute(sa.text(""" + create table data.dramatiq_queue( + message_id uuid primary key, + user_id bigint references auth.user(id), + queue_name text not null, + state text not null check (state in ('queued', 'consumed', 'rejected', 'done')), + mtime timestamp with time zone, + message jsonb, + result jsonb, + result_ttl timestamp with time zone + ) -- TODO Consider `without oids` as Dramatiq-PG uses. + """)) + + op.execute(sa.text(""" + grant select, insert on data.dramatiq_queue to apiuser; + grant all privileges on table data.dramatiq_queue to dramatiq; + """)) + + op.execute(sa.text(""" + alter table data.dramatiq_queue enable row level security; + create policy user_message_policy on data.dramatiq_queue to apiuser, dramatiq + using ( + current_role = 'dramatiq' + or user_id = ( + select id + from auth.user + where email = (select current_setting('request.jwt.claims', true)::json->>'email') + ) + ); + """)) # The public `profile` view presents some columns from the `auth.user` table. An auth'ed # user can view and update only some of the columns of the underlying table. - op.execute( - sa.text( - """ - create view api.profile with (security_invoker = true) as - select email, first_name, last_name, created_at from auth.user - """ - ) - ) + op.execute(sa.text(""" + create view api.profile with (security_invoker = true) as + select email, first_name, last_name, created_at from auth.user + """)) op.execute(sa.text("grant select, update(first_name, last_name) on api.profile to apiuser")) # - op.execute( - sa.text( - """ - create view api.job with (security_invoker = true) as - select message_id as job_id, state, result from data.dramatiq_queue - """ - ) - ) + op.execute(sa.text(""" + create view api.job with (security_invoker = true) as + select message_id as job_id, state, result from data.dramatiq_queue + """)) op.execute(sa.text("grant select on api.job to apiuser")) # Public API function to sign up a new user: insert a row into the private `auth.user` table. # TODO How do we return a 201 here? Should this function return any payload at all? - op.execute( - sa.text( - """ - create function api.signup(email text, password text) returns record language plpgsql as $$ - declare - ret record; - begin - insert into auth.user as u (email, password) - values (signup.email, signup.password) - returning u.created_at, u.email into ret; - return ret; - end; - $$ - """ - ) - ) + op.execute(sa.text(""" + create function api.signup(email text, password text) returns record language plpgsql as $$ + declare + ret record; + begin + insert into auth.user as u (email, password) + values (signup.email, signup.password) + returning u.created_at, u.email into ret; + return ret; + end; + $$ + """)) op.execute(sa.text("grant execute on function api.signup to anonymous")) # Public API function to log in an existing user: return the JWT for the user which allows PostgREST # to impersonate the `apiuser` and therewith get access to the resources. - op.execute( - sa.text( - """ - create function api.login(email text, password text) returns record language plpgsql as $$ - declare - role_ text; - token record; - begin - select role - from auth.user - where auth.user.email = login.email - and auth.user.password = crypt(login.password, auth.user.password) - into role_; - if not found then - raise invalid_password using message = 'invalid user or password'; - end if; - select sign(row_to_json(r), current_setting('app.jwt_secret')) as token - from ( - select role_ as role, login.email as email, extract(epoch from now())::integer + 60*60 as exp - ) r - into token; - return token; - end; - $$ - """ - ) - ) + op.execute(sa.text(""" + create function api.login(email text, password text) returns record language plpgsql as $$ + declare + role_ text; + token record; + begin + select role + from auth.user + where auth.user.email = login.email + and auth.user.password = crypt(login.password, auth.user.password) + into role_; + if not found then + raise invalid_password using message = 'invalid user or password'; + end if; + select sign(row_to_json(r), current_setting('app.jwt_secret')) as token + from ( + select role_ as role, login.email as email, extract(epoch from now())::integer + 60*60 as exp + ) r + into token; + return token; + end; + $$ + """)) op.execute(sa.text("grant execute on function api.login to anonymous")) # Public API function to create & send a message to the async Dramatiq workers. - op.execute( - sa.text( - """ - create function api.job() returns record language sql as $$ - with "user" as ( - select id from auth.user where email = current_setting('request.jwt.claims', true)::json->>'email' - ), - message as ( - select - 'job_q' as queue_name, -- Dramatiq message queue name. - 'job' as actor_name, -- Dramatiq actor function. - jsonb_build_array() as args, -- Positional args for function. - jsonb_build_object() as kwargs, -- Keyword args for function. - jsonb_build_object() as options, -- Additional Dramatiq broker options. - gen_random_uuid() as message_id, - extract(epoch from now())::bigint as message_timestamp - ), - enque as ( - insert into data.dramatiq_queue (user_id, message_id, queue_name, state, mtime, message) - select - u.id, - m.message_id, - m.queue_name, - 'queued', - to_timestamp(m.message_timestamp), - (select to_json(message) from message) - from message m, "user" u - returning queue_name, message_id - ), - notify as ( + op.execute(sa.text(""" + create function api.job() returns record language sql as $$ + with "user" as ( + select id from auth.user where email = current_setting('request.jwt.claims', true)::json->>'email' + ), + message as ( + select + 'job_q' as queue_name, -- Dramatiq message queue name. + 'job' as actor_name, -- Dramatiq actor function. + jsonb_build_array() as args, -- Positional args for function. + jsonb_build_object() as kwargs, -- Keyword args for function. + jsonb_build_object() as options, -- Additional Dramatiq broker options. + gen_random_uuid() as message_id, + extract(epoch from now())::bigint as message_timestamp + ), + enque as ( + insert into data.dramatiq_queue (user_id, message_id, queue_name, state, mtime, message) select - message_id, - pg_notify('dramatiq.' || queue_name || '.enqueue', jsonb_build_object('message_id', message_id)::text) - from enque - ) - select message_id as job_id from notify - $$ - """ - ) - ) + u.id, + m.message_id, + m.queue_name, + 'queued', + to_timestamp(m.message_timestamp), + (select to_json(message) from message) + from message m, "user" u + returning queue_name, message_id + ), + notify as ( + select + message_id, + pg_notify('dramatiq.' || queue_name || '.enqueue', jsonb_build_object('message_id', message_id)::text) + from enque + ) + select message_id as job_id from notify + $$ + """)) op.execute(sa.text("grant execute on function api.job to apiuser")) diff --git a/backend/develop-requirements.txt b/backend/develop-requirements.txt index 0863376..75de40c 100644 --- a/backend/develop-requirements.txt +++ b/backend/develop-requirements.txt @@ -1,36 +1,38 @@ # https://pip.pypa.io/en/stable/reference/requirements-file-format/ # Generate Software Bill of Materials (SBOM). -cyclonedx-bom >=4.0.0,<5.0.0 +cyclonedx-bom >=7.0.0,<8.0.0 # Package build too. flit >=3.2.0,<4.0.0 # Check the Python code. -mypy >=1.0.0,<1.15 -perflint >=0.8.0,<1.0.0 +mypy >=1.0.0,<1.20.0 +# perflint >=0.8.0,<1.0.0 # https://github.com/tonybaloney/perflint/issues/60 pip-audit >=2.4.4,<3.0.0 -pylint >=3.0.0,<3.4.0 +pylint >=4.0.0,<4.1.0 -# Testing. Note that the `custom_exit_code` and `env` plugins may currently be unmaintained. +# Testing. coverage ==7.6.12; python_version<"3.14" # https://github.com/pypi/warehouse/pull/17872#issuecomment-2845932281 -faker ==35.0.0 -hypothesis >=6.21.0,<6.122.8 -pytest >=7.2.0,<9.0.0 -pytest-cases ==3.8.6 +faker ==40.12.0 +hypothesis >=6.0.0,<7.0.0 +pytest >=9.0.0,<10.0.0 +requests ==2.33.* +types-requests ==2.33.* + +# Plugins for pytest. Note that the `custom_exit_code` plugin may currently be unmaintained. +pytest-cases ==3.10.1 pytest-custom_exit_code ==0.3.0 pytest-cov ==6.1.1 # Uses: coverage[toml] >=7.5 -pytest-doctestplus ==1.3.0 -pytest-env ==1.1.5 -pytest-docker ==3.2.1 +pytest-doctestplus ==1.7.1 +pytest-env ==1.6.0 +pytest-docker ==3.2.5 pytest-order ==1.3.0 -requests ==2.32.* -types-requests ==2.32.* # Sphinx is used to generate documentation from Python docstrings and reStructured text. -sphinx >=5.1.1,<9.0.0 +sphinx >=9.0.0,<10.0.0 # Alembic for managing the db migrations. This should match the version from the alembic-requirements.txt # file, though that can't be used because it forces hash checking which, in turn, collides with the # editable installation of the backend package for development. Ah so. -alembic ==1.15.2 +alembic ==1.18.4 diff --git a/backend/docker/Dockerfile.alembic b/backend/docker/Dockerfile.alembic index 5d12a30..9d8141c 100644 --- a/backend/docker/Dockerfile.alembic +++ b/backend/docker/Dockerfile.alembic @@ -1,5 +1,5 @@ # https://hub.docker.com/_/python/ -FROM python:3.13-alpine3.22@sha256:e5fa639e49b85986c4481e28faa2564b45aa8021413f31026c3856e5911618b1 +FROM python:3.13-alpine3.23@sha256:bb1f2fdb1065c85468775c9d680dcd344f6442a2d1181ef7916b60a623f11d40 # Copy over the migrations and configuration. RUN mkdir -p /alembic/alembic diff --git a/backend/docker/Dockerfile.dramatiq b/backend/docker/Dockerfile.dramatiq index adcc88d..992a26d 100644 --- a/backend/docker/Dockerfile.dramatiq +++ b/backend/docker/Dockerfile.dramatiq @@ -1,5 +1,5 @@ # https://hub.docker.com/_/python/ -FROM python:3.13-alpine3.22@sha256:e5fa639e49b85986c4481e28faa2564b45aa8021413f31026c3856e5911618b1 +FROM python:3.13-alpine3.23@sha256:bb1f2fdb1065c85468775c9d680dcd344f6442a2d1181ef7916b60a623f11d40 # Copy over the distribution files in Simple Repository (PEP 503) format. RUN mkdir -p /tmp/dist/simple-index/ @@ -10,4 +10,4 @@ COPY dist/template_jobs-*-requirements.txt /tmp/dist/requirements.txt RUN python -m pip install --extra-index-url file:///tmp/dist/simple-index/ --require-hashes --requirement /tmp/dist/requirements.txt # Entrypoint to the container starts up Dramatiq consumers. -ENTRYPOINT dramatiq --processes ${DRAMATIQ_PROCESSES} --threads ${DRAMATIQ_THREADS} --verbose template_jobs.broker +ENTRYPOINT ["dramatiq", "--processes", "${DRAMATIQ_PROCESSES}", "--threads", "${DRAMATIQ_THREADS}", "--verbose", "template_jobs.broker"] diff --git a/backend/docker/Dockerfile.pg b/backend/docker/Dockerfile.pg index b043217..541b838 100644 --- a/backend/docker/Dockerfile.pg +++ b/backend/docker/Dockerfile.pg @@ -1,10 +1,10 @@ # https://hub.docker.com/_/alpine -FROM alpine:3.22.2@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412 AS build +FROM alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 AS build # https://pkgs.alpinelinux.org/packages RUN apk update && \ apk add git curl gcc openssl make && \ - apk add postgresql17-dev file-dev libpq-dev + apk add postgresql18-dev file-dev libpq-dev # https://github.com/michelp/pgjwt RUN cd /tmp && \ @@ -17,10 +17,10 @@ RUN cd /tmp && \ cd pg_byteamagic && make install # https://hub.docker.com/_/postgres -FROM postgres:17.6-alpine3.22@sha256:ef257d85f76e48da1c64832459b59fcaba1a4dac97bf5d7450c77753542eee94 +FROM postgres:18.3-alpine3.23@sha256:4da1a4828be12604092fa55311276f08f9224a74a62dcb4708bd7439e2a03911 RUN apk update && \ apk add libmagic -COPY --from=build /usr/share/postgresql17/extension/byteamagic* /usr/share/postgresql17/extension/pgflake* /usr/share/postgresql17/extension/pgjwt* /usr/local/share/postgresql/extension/ -COPY --from=build /usr/lib/postgresql17/byteamagic* /usr/lib/postgresql17/pgflake* /usr/lib/postgresql17/bitcode /usr/local/lib/postgresql/ +COPY --from=build /usr/share/postgresql18/extension/byteamagic* /usr/share/postgresql18/extension/pgflake* /usr/share/postgresql18/extension/pgjwt* /usr/local/share/postgresql/extension/ +COPY --from=build /usr/lib/postgresql18/byteamagic* /usr/lib/postgresql18/pgflake* /usr/lib/postgresql18/bitcode /usr/local/lib/postgresql/ diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 1b482cd..2c6ca7f 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -9,14 +9,15 @@ name = "template_jobs" requires-python = ">=3.13.0,<3.14.0" authors = [{name = "Jens Troeger", email = "jens.troeger@light-speed.de"}] maintainers = [{name = "Jens Troeger", email = "jens.troeger@light-speed.de"}] -dynamic = ["version", "description"] +dynamic = ["version"] license = {file = "LICENSE.md"} readme = "README.md" +description = "An opinionated template of a full-stack web application." dependencies = [ "dramatiq ==1.18.0", "dramatiq-pg ==0.12.0", - "sqlalchemy[postgresql-psycopg2binary] ==2.0.41", - "greenlet ==3.2.3", # Remove with SQLA 2.1, see also https://github.com/sqlalchemy/sqlalchemy/issues/7714 + "sqlalchemy[postgresql-psycopg2binary] ==2.0.48", + "greenlet ==3.3.2", # Remove with SQLA 2.1, see also https://github.com/sqlalchemy/sqlalchemy/issues/7714 ] keywords = [] # https://pypi.org/classifiers/ diff --git a/infra/_base-services.yaml b/infra/_base-services.yaml index 841dbd4..e4d7338 100644 --- a/infra/_base-services.yaml +++ b/infra/_base-services.yaml @@ -15,7 +15,7 @@ services: # https://hub.docker.com/r/postgrest/postgrest postgrest: - image: postgrest/postgrest:v14.0@sha256:f8176256ad55a794a61ee6d76d00121635fac4d63bb3d51594e5ed6790f91c72 + image: postgrest/postgrest:v14.7@sha256:8b53afca2e239bc90a0facdb880710232886c38dae5743a57d66056e96d5596a ports: - 3000:3000 environment: @@ -37,7 +37,7 @@ services: # https://hub.docker.com/r/swaggerapi/swagger-ui/ swagger-ui: - image: swaggerapi/swagger-ui:v5.29.5@sha256:be10a20c795c09059cb1024a15b9649a08b949e9604c7fc316d9a88fa7eacdcd + image: swaggerapi/swagger-ui:v5.32.1@sha256:74e37eb854b2cec5a8bcfdc4b0604a0354fbbf7209b68c3357d3221286bcb1dc ports: - 3001:8080 environment: