diff --git a/.fpm b/.fpm index 546ce641cf..062ba199b1 100644 --- a/.fpm +++ b/.fpm @@ -1,5 +1,5 @@ -s dir --name defguard ---description "defguard core service" +--description "Defguard Core service" --url "https://defguard.net/" ---maintainer "teonite" +--maintainer "Defguard" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c03b43890d..1939c92b14 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -107,7 +107,7 @@ jobs: - name: Install Rust stable uses: actions-rs/toolchain@v1 with: - toolchain: 1.89.0 + toolchain: 1.89.0 # "stable" causes rust-lld: error on aarch64-linux target: ${{ matrix.target }} override: true @@ -172,26 +172,6 @@ jobs: fpm_args: "defguard-${{ github.ref_name }}-${{ matrix.target }}=/usr/bin/defguard defguard.service=/usr/lib/systemd/system/defguard.service .env-template=/etc/defguard/core.conf" fpm_opts: "--architecture ${{ matrix.arch }} --debug --output-type deb --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-${{ matrix.target }}.deb" - - name: Run `packer init` - if: matrix.build == 'linux' && matrix.arch == 'amd64' - id: init - run: "packer init ./images/ami/core.pkr.hcl" - - - name: Build AMI images for multiple regions - if: matrix.build == 'linux' && matrix.arch == 'amd64' - run: | - regions=(us-east-1 eu-west-1 ap-northeast-1 eu-central-1) - for region in "${regions[@]}"; do - echo "Building AMI for region: $region" - echo "Running packer validate for $region..." - packer validate --var "package_version=${{ env.VERSION }}" --var "region=$region" ./images/ami/core.pkr.hcl - echo "Building AMI image for $region..." - packer build -color=false -on-error=abort --var "package_version=${{ env.VERSION }}" --var "region=$region" ./images/ami/core.pkr.hcl - done - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - name: Upload DEB if: matrix.build == 'linux' uses: actions/upload-release-asset@v1.0.2 @@ -216,6 +196,7 @@ jobs: COMPONENT=$([[ "${{ github.ref_name }}" == *"-"* ]] && echo "pre-release" || echo "release") # if tag contain "-" assume it's pre-release. deb-s3 upload -l --bucket=apt.defguard.net --access-key-id=${{ secrets.AWS_ACCESS_KEY_APT }} --secret-access-key=${{ secrets.AWS_SECRET_KEY_APT }} --s3-region=eu-north-1 --no-fail-if-exists --codename=trixie --component="$COMPONENT" defguard-${{ env.VERSION }}-${{ matrix.target }}.deb + - name: Build RPM package if: matrix.build == 'linux' uses: defGuard/fpm-action@main @@ -239,7 +220,7 @@ jobs: uses: defGuard/fpm-action@main with: fpm_args: "defguard-${{ github.ref_name }}-${{ matrix.target }}=/usr/local/bin/defguard defguard.service.freebsd=/usr/local/etc/rc.d/defguard" - fpm_opts: "--architecture ${{ matrix.arch }} --debug --output-type freebsd --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}_${{ matrix.target }}.pkg --freebsd-osversion '*'" + fpm_opts: "--architecture ${{ matrix.arch }} --debug --output-type freebsd --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}_${{ matrix.target }}.pkg --freebsd-osversion '*' --depends openssl" - name: Upload FreeBSD if: matrix.build == 'freebsd' @@ -253,16 +234,14 @@ jobs: asset_content_type: application/octet-stream apt-sign: - needs: + needs: - build-binaries runs-on: - self-hosted - Linux - X64 - strategy: - fail-fast: false steps: - - name: Sign APT repository on trixie + - name: Sign APT repository run: | export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_APT }} export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY_APT }} @@ -272,15 +251,15 @@ jobs: for DIST in trixie; do aws s3 cp s3://apt.defguard.net/dists/${DIST}/Release . - + curl -X POST "${{ secrets.DEFGUARD_SIGNING_URL }}?signature_type=both" \ -H "Authorization: Bearer ${{ secrets.DEFGUARD_SIGNING_API_KEY }}" \ -F "file=@Release" \ -o response.json - + cat response.json | jq -r '.files["Release.gpg"].content' | base64 --decode > Release.gpg cat response.json | jq -r '.files.Release.content' | base64 --decode > InRelease - + aws s3 cp Release.gpg s3://apt.defguard.net/dists/${DIST}/ --acl public-read aws s3 cp InRelease s3://apt.defguard.net/dists/${DIST}/ --acl public-read diff --git a/.sqlx/query-9f98a138560451105b104fc7a4d3d29e22e58f33e902c06bbf6163ee48ae802a.json b/.sqlx/query-14302b1c6c7d72d6e6f38c80538040b9fa3479c919f1ace2a787470690be9de3.json similarity index 91% rename from .sqlx/query-9f98a138560451105b104fc7a4d3d29e22e58f33e902c06bbf6163ee48ae802a.json rename to .sqlx/query-14302b1c6c7d72d6e6f38c80538040b9fa3479c919f1ace2a787470690be9de3.json index f847621f43..8ba998d2cb 100644 --- a/.sqlx/query-9f98a138560451105b104fc7a4d3d29e22e58f33e902c06bbf6163ee48ae802a.json +++ b/.sqlx/query-14302b1c6c7d72d6e6f38c80538040b9fa3479c919f1ace2a787470690be9de3.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, \"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\" \"directory_sync_user_behavior: _\",\"directory_sync_admin_behavior\" \"directory_sync_admin_behavior: _\",\"directory_sync_target\" \"directory_sync_target: _\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\" \"directory_sync_group_match: _\",\"jumpcloud_api_key\" FROM \"openidprovider\" WHERE id = $1", + "query": "SELECT id, \"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\" \"directory_sync_user_behavior: _\",\"directory_sync_admin_behavior\" \"directory_sync_admin_behavior: _\",\"directory_sync_target\" \"directory_sync_target: _\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\" \"directory_sync_group_match: _\",\"jumpcloud_api_key\",\"prefetch_users\" FROM \"openidprovider\" WHERE id = $1", "describe": { "columns": [ { @@ -125,6 +125,11 @@ "ordinal": 17, "name": "jumpcloud_api_key", "type_info": "Text" + }, + { + "ordinal": 18, + "name": "prefetch_users", + "type_info": "Bool" } ], "parameters": { @@ -150,8 +155,9 @@ true, true, false, - true + true, + false ] }, - "hash": "9f98a138560451105b104fc7a4d3d29e22e58f33e902c06bbf6163ee48ae802a" + "hash": "14302b1c6c7d72d6e6f38c80538040b9fa3479c919f1ace2a787470690be9de3" } diff --git a/.sqlx/query-06bbd4a7662ea9ec62a0138efa9acb62c4bd9b646846740333d8ae3d154d1d77.json b/.sqlx/query-558fb8aa5e223f6fc273c1431410dabb2ca9c2a831cacb7ebc8d696020b0556c.json similarity index 92% rename from .sqlx/query-06bbd4a7662ea9ec62a0138efa9acb62c4bd9b646846740333d8ae3d154d1d77.json rename to .sqlx/query-558fb8aa5e223f6fc273c1431410dabb2ca9c2a831cacb7ebc8d696020b0556c.json index dec553bccb..bfd59988cf 100644 --- a/.sqlx/query-06bbd4a7662ea9ec62a0138efa9acb62c4bd9b646846740333d8ae3d154d1d77.json +++ b/.sqlx/query-558fb8aa5e223f6fc273c1431410dabb2ca9c2a831cacb7ebc8d696020b0556c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, base_url, client_id, client_secret, display_name, google_service_account_key, google_service_account_email, admin_email, directory_sync_enabled,\n directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", directory_sync_target \"directory_sync_target: DirectorySyncTarget\", okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key FROM openidprovider WHERE name = $1", + "query": "SELECT id, name, base_url, client_id, client_secret, display_name, google_service_account_key, google_service_account_email, admin_email, directory_sync_enabled,\n directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", directory_sync_target \"directory_sync_target: DirectorySyncTarget\", okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key, prefetch_users FROM openidprovider WHERE name = $1", "describe": { "columns": [ { @@ -125,6 +125,11 @@ "ordinal": 17, "name": "jumpcloud_api_key", "type_info": "Text" + }, + { + "ordinal": 18, + "name": "prefetch_users", + "type_info": "Bool" } ], "parameters": { @@ -150,8 +155,9 @@ true, true, false, - true + true, + false ] }, - "hash": "06bbd4a7662ea9ec62a0138efa9acb62c4bd9b646846740333d8ae3d154d1d77" + "hash": "558fb8aa5e223f6fc273c1431410dabb2ca9c2a831cacb7ebc8d696020b0556c" } diff --git a/.sqlx/query-d4d76206a3eeb48f4c3e06e53e781bab2a0e2020e33653ef34ab1ea7df67a0cb.json b/.sqlx/query-796ef2b0b73f5689a592497320b98ddb54a2a673a531cb882aadea3d5aa25d66.json similarity index 90% rename from .sqlx/query-d4d76206a3eeb48f4c3e06e53e781bab2a0e2020e33653ef34ab1ea7df67a0cb.json rename to .sqlx/query-796ef2b0b73f5689a592497320b98ddb54a2a673a531cb882aadea3d5aa25d66.json index e28198163d..528c633238 100644 --- a/.sqlx/query-d4d76206a3eeb48f4c3e06e53e781bab2a0e2020e33653ef34ab1ea7df67a0cb.json +++ b/.sqlx/query-796ef2b0b73f5689a592497320b98ddb54a2a673a531cb882aadea3d5aa25d66.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE openidprovider SET name = $1, base_url = $2, client_id = $3, client_secret = $4, display_name = $5, google_service_account_key = $6, google_service_account_email = $7, admin_email = $8, directory_sync_enabled = $9, directory_sync_interval = $10, directory_sync_user_behavior = $11, directory_sync_admin_behavior = $12, directory_sync_target = $13, okta_private_jwk = $14, okta_dirsync_client_id = $15, directory_sync_group_match = $16, jumpcloud_api_key = $17 WHERE id = $18", + "query": "UPDATE openidprovider SET name = $1, base_url = $2, client_id = $3, client_secret = $4, display_name = $5, google_service_account_key = $6, google_service_account_email = $7, admin_email = $8, directory_sync_enabled = $9, directory_sync_interval = $10, directory_sync_user_behavior = $11, directory_sync_admin_behavior = $12, directory_sync_target = $13, okta_private_jwk = $14, okta_dirsync_client_id = $15, directory_sync_group_match = $16, jumpcloud_api_key = $17, prefetch_users = $18 WHERE id = $19", "describe": { "columns": [], "parameters": { @@ -55,10 +55,11 @@ "Text", "TextArray", "Text", + "Bool", "Int8" ] }, "nullable": [] }, - "hash": "d4d76206a3eeb48f4c3e06e53e781bab2a0e2020e33653ef34ab1ea7df67a0cb" + "hash": "796ef2b0b73f5689a592497320b98ddb54a2a673a531cb882aadea3d5aa25d66" } diff --git a/.sqlx/query-dce467a600d7b0e51d1b75dd5978c56cc1e6b0c6fbf1907cce4bbe0a1bde88ff.json b/.sqlx/query-c6ebb402f91d242754872addc3604fb6ffac7e6fdd0d9428070cecb68c666cd8.json similarity index 85% rename from .sqlx/query-dce467a600d7b0e51d1b75dd5978c56cc1e6b0c6fbf1907cce4bbe0a1bde88ff.json rename to .sqlx/query-c6ebb402f91d242754872addc3604fb6ffac7e6fdd0d9428070cecb68c666cd8.json index 8902fca66f..7994ebf797 100644 --- a/.sqlx/query-dce467a600d7b0e51d1b75dd5978c56cc1e6b0c6fbf1907cce4bbe0a1bde88ff.json +++ b/.sqlx/query-c6ebb402f91d242754872addc3604fb6ffac7e6fdd0d9428070cecb68c666cd8.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO \"openidprovider\" (\"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\",\"directory_sync_admin_behavior\",\"directory_sync_target\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\",\"jumpcloud_api_key\") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17) RETURNING id", + "query": "INSERT INTO \"openidprovider\" (\"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\",\"directory_sync_admin_behavior\",\"directory_sync_target\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\",\"jumpcloud_api_key\",\"prefetch_users\") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18) RETURNING id", "describe": { "columns": [ { @@ -60,12 +60,13 @@ "Text", "Text", "TextArray", - "Text" + "Text", + "Bool" ] }, "nullable": [ false ] }, - "hash": "dce467a600d7b0e51d1b75dd5978c56cc1e6b0c6fbf1907cce4bbe0a1bde88ff" + "hash": "c6ebb402f91d242754872addc3604fb6ffac7e6fdd0d9428070cecb68c666cd8" } diff --git a/.sqlx/query-187b82f0cc866ff2f1049aa57d9477cbad81d77c2db2b67dca90de198721b483.json b/.sqlx/query-c8e9800861c7bc853235858650be8ad3d3d19b0c4f0e69b9002a6a1fbd46a324.json similarity index 90% rename from .sqlx/query-187b82f0cc866ff2f1049aa57d9477cbad81d77c2db2b67dca90de198721b483.json rename to .sqlx/query-c8e9800861c7bc853235858650be8ad3d3d19b0c4f0e69b9002a6a1fbd46a324.json index 3576fdb99b..5c80f34900 100644 --- a/.sqlx/query-187b82f0cc866ff2f1049aa57d9477cbad81d77c2db2b67dca90de198721b483.json +++ b/.sqlx/query-c8e9800861c7bc853235858650be8ad3d3d19b0c4f0e69b9002a6a1fbd46a324.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE \"openidprovider\" SET \"name\" = $2,\"base_url\" = $3,\"client_id\" = $4,\"client_secret\" = $5,\"display_name\" = $6,\"google_service_account_key\" = $7,\"google_service_account_email\" = $8,\"admin_email\" = $9,\"directory_sync_enabled\" = $10,\"directory_sync_interval\" = $11,\"directory_sync_user_behavior\" = $12,\"directory_sync_admin_behavior\" = $13,\"directory_sync_target\" = $14,\"okta_private_jwk\" = $15,\"okta_dirsync_client_id\" = $16,\"directory_sync_group_match\" = $17,\"jumpcloud_api_key\" = $18 WHERE id = $1", + "query": "UPDATE \"openidprovider\" SET \"name\" = $2,\"base_url\" = $3,\"client_id\" = $4,\"client_secret\" = $5,\"display_name\" = $6,\"google_service_account_key\" = $7,\"google_service_account_email\" = $8,\"admin_email\" = $9,\"directory_sync_enabled\" = $10,\"directory_sync_interval\" = $11,\"directory_sync_user_behavior\" = $12,\"directory_sync_admin_behavior\" = $13,\"directory_sync_target\" = $14,\"okta_private_jwk\" = $15,\"okta_dirsync_client_id\" = $16,\"directory_sync_group_match\" = $17,\"jumpcloud_api_key\" = $18,\"prefetch_users\" = $19 WHERE id = $1", "describe": { "columns": [], "parameters": { @@ -55,10 +55,11 @@ "Text", "Text", "TextArray", - "Text" + "Text", + "Bool" ] }, "nullable": [] }, - "hash": "187b82f0cc866ff2f1049aa57d9477cbad81d77c2db2b67dca90de198721b483" + "hash": "c8e9800861c7bc853235858650be8ad3d3d19b0c4f0e69b9002a6a1fbd46a324" } diff --git a/.sqlx/query-07ac05be4850e0154414090784fc40392f423c16cd326716994fcb1f45c84eee.json b/.sqlx/query-d8db674150231de0063227000a8b39f45c6da9836f93b67307787851a1804f13.json similarity index 92% rename from .sqlx/query-07ac05be4850e0154414090784fc40392f423c16cd326716994fcb1f45c84eee.json rename to .sqlx/query-d8db674150231de0063227000a8b39f45c6da9836f93b67307787851a1804f13.json index 5a629b4c9f..29d36e4226 100644 --- a/.sqlx/query-07ac05be4850e0154414090784fc40392f423c16cd326716994fcb1f45c84eee.json +++ b/.sqlx/query-d8db674150231de0063227000a8b39f45c6da9836f93b67307787851a1804f13.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, \"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\" \"directory_sync_user_behavior: _\",\"directory_sync_admin_behavior\" \"directory_sync_admin_behavior: _\",\"directory_sync_target\" \"directory_sync_target: _\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\" \"directory_sync_group_match: _\",\"jumpcloud_api_key\" FROM \"openidprovider\"", + "query": "SELECT id, \"name\",\"base_url\",\"client_id\",\"client_secret\",\"display_name\",\"google_service_account_key\",\"google_service_account_email\",\"admin_email\",\"directory_sync_enabled\",\"directory_sync_interval\",\"directory_sync_user_behavior\" \"directory_sync_user_behavior: _\",\"directory_sync_admin_behavior\" \"directory_sync_admin_behavior: _\",\"directory_sync_target\" \"directory_sync_target: _\",\"okta_private_jwk\",\"okta_dirsync_client_id\",\"directory_sync_group_match\" \"directory_sync_group_match: _\",\"jumpcloud_api_key\",\"prefetch_users\" FROM \"openidprovider\"", "describe": { "columns": [ { @@ -125,6 +125,11 @@ "ordinal": 17, "name": "jumpcloud_api_key", "type_info": "Text" + }, + { + "ordinal": 18, + "name": "prefetch_users", + "type_info": "Bool" } ], "parameters": { @@ -148,8 +153,9 @@ true, true, false, - true + true, + false ] }, - "hash": "07ac05be4850e0154414090784fc40392f423c16cd326716994fcb1f45c84eee" + "hash": "d8db674150231de0063227000a8b39f45c6da9836f93b67307787851a1804f13" } diff --git a/.sqlx/query-6c3bbaa998dbb9d0b3771c546b014818139cdfac6ed6c15603f6e6806c63ac6f.json b/.sqlx/query-e28b02ccc616d67fcb1a1aa940ea35be58cb652e8287a6f5028421656048b58a.json similarity index 92% rename from .sqlx/query-6c3bbaa998dbb9d0b3771c546b014818139cdfac6ed6c15603f6e6806c63ac6f.json rename to .sqlx/query-e28b02ccc616d67fcb1a1aa940ea35be58cb652e8287a6f5028421656048b58a.json index 8b48d798c8..f59dbf3807 100644 --- a/.sqlx/query-6c3bbaa998dbb9d0b3771c546b014818139cdfac6ed6c15603f6e6806c63ac6f.json +++ b/.sqlx/query-e28b02ccc616d67fcb1a1aa940ea35be58cb652e8287a6f5028421656048b58a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, base_url, client_id, client_secret, display_name, google_service_account_key, google_service_account_email, admin_email, directory_sync_enabled, directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", directory_sync_target \"directory_sync_target: DirectorySyncTarget\", okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key FROM openidprovider LIMIT 1", + "query": "SELECT id, name, base_url, client_id, client_secret, display_name, google_service_account_key, google_service_account_email, admin_email, directory_sync_enabled, directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", directory_sync_target \"directory_sync_target: DirectorySyncTarget\", okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key, prefetch_users FROM openidprovider LIMIT 1", "describe": { "columns": [ { @@ -125,6 +125,11 @@ "ordinal": 17, "name": "jumpcloud_api_key", "type_info": "Text" + }, + { + "ordinal": 18, + "name": "prefetch_users", + "type_info": "Bool" } ], "parameters": { @@ -148,8 +153,9 @@ true, true, false, - true + true, + false ] }, - "hash": "6c3bbaa998dbb9d0b3771c546b014818139cdfac6ed6c15603f6e6806c63ac6f" + "hash": "e28b02ccc616d67fcb1a1aa940ea35be58cb652e8287a6f5028421656048b58a" } diff --git a/Cargo.lock b/Cargo.lock index 2ae9c31040..a0722d94d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -76,9 +67,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -113,9 +104,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -143,22 +134,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -167,6 +158,15 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "ar_archive_writer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +dependencies = [ + "object", +] + [[package]] name = "arbitrary" version = "1.4.2" @@ -284,9 +284,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e529aee37b5c8206bb4bf4c44797127566d72f76952c970bd3d1e85de8f4e2" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ "axum-core", "bytes", @@ -328,9 +328,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ac7a6beb1182c7e30253ee75c3e918080bfb83f5a3023bcdf7209d85fd147e6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -347,9 +347,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86d701cd16f401888ebe9c3214dc838c7ef27a405d5726196765a913603b5dd" +checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96" dependencies = [ "axum", "axum-core", @@ -372,21 +372,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link 0.2.0", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -425,9 +410,9 @@ checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "base64urlsafedata" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5913e643e4dfb43d5908e9e6f1386f8e0dfde086ecef124a6450c6195d89160" +checksum = "215ee31f8a88f588c349ce2d20108b2ed96089b96b9c2b03775dc35dd72938e8" dependencies = [ "base64 0.21.7", "pastey", @@ -463,11 +448,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -509,6 +494,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "blowfish" version = "0.9.1" @@ -521,9 +515,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "serde", @@ -531,9 +525,9 @@ dependencies = [ [[package]] name = "buffer-redux" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8acf87c5b9f5897cd3ebb9a327f420e0cae9dd4e5c1d2e36f2c84c571a58f1" +checksum = "431a9cc8d7efa49bc326729264537f5e60affce816c66edf434350778c9f4f54" dependencies = [ "memchr", ] @@ -552,9 +546,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" dependencies = [ "serde", ] @@ -580,9 +574,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.39" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ "find-msvc-tools", "jobserver", @@ -601,9 +595,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -622,7 +616,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -675,9 +669,9 @@ checksum = "bba18ee93d577a8428902687bcc2b6b45a56b1981a1f6d779731c86cc4c5db18" [[package]] name = "clap" -version = "4.5.48" +version = "4.5.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8" dependencies = [ "clap_builder", "clap_derive", @@ -685,9 +679,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.48" +version = "4.5.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1" dependencies = [ "anstream", "anstyle", @@ -697,9 +691,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", @@ -709,9 +703,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cmac" @@ -923,9 +917,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1113,7 +1107,7 @@ dependencies = [ [[package]] name = "defguard_common" -version = "1.5.2" +version = "1.6.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -1184,7 +1178,7 @@ dependencies = [ "secrecy", "semver", "serde", - "serde_cbor_2", + "serde_cbor_2 0.12.0-dev", "serde_json", "serde_qs", "serde_urlencoded", @@ -1329,9 +1323,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", "serde_core", @@ -1440,6 +1434,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.10.0", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1462,9 +1466,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1636,7 +1640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -1686,9 +1690,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "fixedbitset" @@ -1698,9 +1702,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "libz-rs-sys", @@ -1909,21 +1913,21 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] @@ -1937,19 +1941,13 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "git2" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", "libgit2-sys", "log", @@ -1958,9 +1956,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -1975,7 +1973,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "ignore", "walkdir", ] @@ -2003,7 +2001,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.11.4", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2016,6 +2014,17 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2114,11 +2123,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2212,9 +2221,9 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", @@ -2281,9 +2290,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ "base64 0.22.1", "bytes", @@ -2331,9 +2340,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -2344,9 +2353,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -2357,11 +2366,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2372,42 +2380,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2453,9 +2457,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.23" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" dependencies = [ "crossbeam-deque", "globset", @@ -2480,9 +2484,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown 0.16.0", @@ -2499,17 +2503,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2527,9 +2520,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -2537,9 +2530,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2571,15 +2564,15 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -2685,9 +2678,9 @@ dependencies = [ [[package]] name = "lettre" -version = "0.11.18" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cb54db6ff7a89efac87dba5baeac57bb9ccd726b49a9b6f21fb92b3966aaf56" +checksum = "9e13e10e8818f8b2a60f52cb127041d388b89f3a96a62be9ceaffa22262fef7f" dependencies = [ "async-trait", "base64 0.22.1", @@ -2713,9 +2706,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.176" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libgit2-sys" @@ -2741,7 +2734,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", "redox_syscall", ] @@ -2767,9 +2760,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" dependencies = [ "cc", "libc", @@ -2785,23 +2778,22 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -2926,17 +2918,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -2976,6 +2969,18 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -3003,11 +3008,11 @@ checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3022,11 +3027,10 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", @@ -3087,9 +3091,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -3097,9 +3101,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -3136,11 +3140,170 @@ dependencies = [ "url", ] +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.10.0", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + [[package]] name = "object" -version = "0.37.3" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -3174,9 +3337,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opaque-debug" @@ -3217,11 +3380,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -3249,9 +3412,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -3280,14 +3443,18 @@ dependencies = [ [[package]] name = "os_info" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" +checksum = "7c39b5918402d564846d5aba164c09a66cc88d232179dfd3e3c619a25a268392" dependencies = [ + "android_system_properties", "log", - "plist", + "nix", + "objc2", + "objc2-foundation", + "objc2-ui-kit", "serde", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3336,9 +3503,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3346,15 +3513,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -3402,12 +3569,12 @@ checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -3427,20 +3594,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 2.0.17", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -3448,9 +3614,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", @@ -3461,9 +3627,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ "pest", "sha2", @@ -3476,7 +3642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "indexmap 2.11.4", + "indexmap 2.12.0", ] [[package]] @@ -3658,19 +3824,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plist" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" -dependencies = [ - "base64 0.22.1", - "indexmap 2.11.4", - "quick-xml", - "serde", - "time", -] - [[package]] name = "polyval" version = "0.6.2" @@ -3685,9 +3838,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -3743,9 +3896,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -3812,10 +3965,11 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "psm" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" dependencies = [ + "ar_archive_writer", "cc", ] @@ -3835,7 +3989,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "getopts", "memchr", "pulldown-cmark-escape", @@ -3850,22 +4004,13 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "pulldown-cmark-to-cmark" -version = "21.0.0" +version = "21.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +checksum = "8246feae3db61428fd0bb94285c690b460e4517d83152377543ca802357785f1" dependencies = [ "pulldown-cmark", ] -[[package]] -name = "quick-xml" -version = "0.38.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" -dependencies = [ - "memchr", -] - [[package]] name = "quinn" version = "0.11.9" @@ -3893,7 +4038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring", @@ -3923,9 +4068,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -4004,16 +4149,16 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -4038,9 +4183,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.3" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -4050,9 +4195,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -4061,15 +4206,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64 0.22.1", "bytes", @@ -4150,9 +4295,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" dependencies = [ "const-oid", "digest", @@ -4171,9 +4316,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.7.2" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a" +checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -4182,9 +4327,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.7.2" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c" +checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2" dependencies = [ "proc-macro2", "quote", @@ -4195,9 +4340,9 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "8.7.2" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594" +checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475" dependencies = [ "globset", "sha2", @@ -4215,12 +4360,6 @@ dependencies = [ "trim-in-place", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -4251,18 +4390,18 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "log", "once_cell", @@ -4275,9 +4414,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -4287,9 +4426,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "web-time", "zeroize", @@ -4297,9 +4436,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.6" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -4333,7 +4472,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -4350,9 +4489,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" dependencies = [ "dyn-clone", "ref-cast", @@ -4397,7 +4536,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -4410,7 +4549,7 @@ version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4473,7 +4612,17 @@ version = "0.12.0-dev" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b46d75f449e01f1eddbe9b00f432d616fbbd899b809c837d0fbc380496a0dd55" dependencies = [ - "half", + "half 1.8.3", + "serde", +] + +[[package]] +name = "serde_cbor_2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aec2709de9078e077090abd848e967abab63c9fb3fdb5d4799ad359d8d482c" +dependencies = [ + "half 2.7.1", "serde", ] @@ -4504,7 +4653,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.11.4", + "indexmap 2.12.0", "itoa", "ryu", "serde_core", @@ -4568,19 +4717,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" +checksum = "10574371d41b0d9b2cff89418eda27da52bcaff2cc8741db26382a77c29131f1" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.4", + "indexmap 2.12.0", "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", + "schemars 1.1.0", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -4588,9 +4736,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" +checksum = "08a72d8216842fdd57820dc78d840bef99248e35fb2554ff923319e60f2d686b" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -4604,7 +4752,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "itoa", "ryu", "serde", @@ -4795,12 +4943,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4854,7 +5002,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink", - "indexmap 2.11.4", + "indexmap 2.12.0", "ipnetwork", "log", "memchr", @@ -4919,7 +5067,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.9.4", + "bitflags 2.10.0", "byteorder", "bytes", "chrono", @@ -4963,7 +5111,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.9.4", + "bitflags 2.10.0", "byteorder", "chrono", "crc", @@ -5064,15 +5212,15 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stacker" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" +checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" dependencies = [ "cc", "cfg-if", @@ -5172,9 +5320,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -5207,7 +5355,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -5235,10 +5383,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -5254,9 +5402,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9d851b45e865f178319da0abdbfe6acbc4328759ff18dafc3a41c16b4cd2ee" +checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722" dependencies = [ "chrono", "chrono-tz", @@ -5271,7 +5419,7 @@ dependencies = [ "serde", "serde_json", "slug", - "unic-segment", + "unicode-segmentation", ] [[package]] @@ -5367,9 +5515,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -5392,28 +5540,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -5454,9 +5599,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -5467,20 +5612,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.6" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "toml_datetime", "toml_parser", "winnow", @@ -5488,9 +5633,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] @@ -5599,7 +5744,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.11.4", + "indexmap 2.12.0", "pin-project-lite", "slab", "sync_wrapper", @@ -5616,7 +5761,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "bytes", "futures-core", "futures-util", @@ -5746,9 +5891,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uaparser" @@ -5770,56 +5915,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -dependencies = [ - "unic-ucd-segment", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" version = "2.8.1" @@ -5834,30 +5929,36 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -5923,7 +6024,7 @@ version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "serde", "serde_json", "utoipa-gen", @@ -5973,7 +6074,7 @@ version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "wasm-bindgen", @@ -6061,15 +6162,6 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -6087,9 +6179,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -6098,25 +6190,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -6127,9 +6205,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6137,22 +6215,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -6172,9 +6250,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -6204,9 +6282,9 @@ dependencies = [ [[package]] name = "webauthn-attestation-ca" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e43534efe4e8f56c4eb1615a27e24d2ff29281385c843cf9f16ac1077dbdc" +checksum = "f77a2892ec44032e6c48dad9aad1b05fada09c346ada11d8d32db119b4b4f205" dependencies = [ "base64urlsafedata", "openssl", @@ -6218,9 +6296,9 @@ dependencies = [ [[package]] name = "webauthn-authenticator-rs" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720d11d7d7408e6c7cf65ab4d79b1f96c2a531df4e469e12656d6b814bdcd1b1" +checksum = "45f8fe3811c8d6c6830d263452670a608fd4dcdfc481349bd4d1e6a46d6c7a0f" dependencies = [ "async-stream", "async-trait", @@ -6236,7 +6314,7 @@ dependencies = [ "openssl-sys", "serde", "serde_bytes", - "serde_cbor_2", + "serde_cbor_2 0.13.0", "serde_json", "thiserror 1.0.69", "tokio", @@ -6251,9 +6329,9 @@ dependencies = [ [[package]] name = "webauthn-rs" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1f861a94557baeb0cf711e3e55d623c46b68f4aab7aa932562f785b8b5f1ab" +checksum = "eb7c3a2f9c8bddd524e47bbd427bcf3a28aa074de55d74470b42a91a41937b8e" dependencies = [ "base64urlsafedata", "serde", @@ -6265,9 +6343,9 @@ dependencies = [ [[package]] name = "webauthn-rs-core" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269c210cd5f183aaca860bb5733187d1dd110ebed54640f8fc1aca31a04aa4dc" +checksum = "19f1d80f3146382529fe70a3ab5d0feb2413a015204ed7843f9377cd39357fc4" dependencies = [ "base64 0.21.7", "base64urlsafedata", @@ -6279,7 +6357,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "serde", - "serde_cbor_2", + "serde_cbor_2 0.13.0", "serde_json", "thiserror 1.0.69", "tracing", @@ -6292,9 +6370,9 @@ dependencies = [ [[package]] name = "webauthn-rs-proto" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144dbee9abb4bfad78fd283a2613f0312a0ed5955051b7864cfc98679112ae60" +checksum = "9e786894f89facb9aaf1c5f6559670236723c98382e045521c76f3d5ca5047bd" dependencies = [ "base64 0.21.7", "base64urlsafedata", @@ -6305,9 +6383,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] @@ -6328,27 +6406,27 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] name = "windows-core" -version = "0.62.1" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.0", - "windows-result 0.4.0", - "windows-strings 0.5.0", + "windows-link 0.2.1", + "windows-result", + "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -6357,9 +6435,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.2" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -6374,55 +6452,37 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-registry" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" -dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-result" -version = "0.3.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", + "windows-result", + "windows-strings", ] [[package]] name = "windows-result" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" -dependencies = [ - "windows-link 0.2.0", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -6458,16 +6518,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.4", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -6503,19 +6563,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.4" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.0", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -6532,9 +6592,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -6550,9 +6610,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -6568,9 +6628,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -6580,9 +6640,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -6598,9 +6658,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -6616,9 +6676,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -6634,9 +6694,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -6652,9 +6712,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -6673,9 +6733,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -6726,11 +6786,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -6738,9 +6797,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -6811,9 +6870,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -6822,9 +6881,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -6833,9 +6892,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", @@ -6851,7 +6910,7 @@ dependencies = [ "arbitrary", "crc32fast", "flate2", - "indexmap 2.11.4", + "indexmap 2.12.0", "memchr", "zopfli", ] @@ -6864,9 +6923,9 @@ checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" [[package]] name = "zopfli" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" dependencies = [ "bumpalo", "crc32fast", diff --git a/crates/defguard_common/Cargo.toml b/crates/defguard_common/Cargo.toml index 2bc3053fcf..1855788cb0 100644 --- a/crates/defguard_common/Cargo.toml +++ b/crates/defguard_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "defguard_common" -version = "1.5.2" +version = "1.6.0" edition.workspace = true license-file.workspace = true homepage.workspace = true diff --git a/crates/defguard_core/src/db/models/wireguard.rs b/crates/defguard_core/src/db/models/wireguard.rs index 83f1b9966c..33c26e4989 100644 --- a/crates/defguard_core/src/db/models/wireguard.rs +++ b/crates/defguard_core/src/db/models/wireguard.rs @@ -162,7 +162,7 @@ impl From for ProtoServiceLocationMode { } /// Stores configuration required to setup a WireGuard network -#[derive(Clone, Debug, Deserialize, Eq, Hash, Model, PartialEq, Serialize, ToSchema)] +#[derive(Clone, Deserialize, Eq, Hash, Model, PartialEq, Serialize, ToSchema)] #[table(wireguard_network)] pub struct WireguardNetwork { pub id: I, @@ -207,6 +207,29 @@ impl fmt::Display for WireguardNetwork { } } +impl fmt::Debug for WireguardNetwork { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WireguardNetwork") + .field("id", &self.id) + .field("name", &self.name) + .field("address", &self.address) + .field("port", &self.port) + .field("pubkey", &self.pubkey) + .field("prvkey", &"***") + .field("endpoint", &self.endpoint) + .field("dns", &self.dns) + .field("allowed_ips", &self.allowed_ips) + .field("connected_at", &self.connected_at) + .field("acl_enabled", &self.acl_enabled) + .field("acl_default_allow", &self.acl_default_allow) + .field("keepalive_interval", &self.keepalive_interval) + .field("peer_disconnect_threshold", &self.peer_disconnect_threshold) + .field("location_mfa_mode", &self.location_mfa_mode) + .field("service_location_mode", &self.service_location_mode) + .finish() + } +} + #[cfg(test)] impl Default for WireguardNetwork { fn default() -> Self { @@ -384,18 +407,22 @@ impl WireguardNetwork { &self, device_count: usize, ) -> Result<(), WireguardNetworkError> { - debug!("Checking if {device_count} devices can fit in network {self}"); - let network_size = self.address[0].size(); - // include address, network, and broadcast in the calculation - match network_size { - NetworkSize::V4(size) => { - if device_count as u32 > size { - return Err(WireguardNetworkError::NetworkTooSmall); + debug!("Checking if {device_count} devices can fit in networks used by location {self}"); + // if given location uses multiple subnets validate devices can fit them all + for subnet in &self.address { + debug!("Checking if {device_count} devices can fit in network {subnet}"); + let network_size = subnet.size(); + // include address, network, and broadcast in the calculation + match network_size { + NetworkSize::V4(size) => { + if device_count as u32 > size { + return Err(WireguardNetworkError::NetworkTooSmall); + } } - } - NetworkSize::V6(size) => { - if device_count as u128 > size { - return Err(WireguardNetworkError::NetworkTooSmall); + NetworkSize::V6(size) => { + if device_count as u128 > size { + return Err(WireguardNetworkError::NetworkTooSmall); + } } } } diff --git a/crates/defguard_core/src/enterprise/db/models/openid_provider.rs b/crates/defguard_core/src/enterprise/db/models/openid_provider.rs index 7143b062b3..7a3ef88604 100644 --- a/crates/defguard_core/src/enterprise/db/models/openid_provider.rs +++ b/crates/defguard_core/src/enterprise/db/models/openid_provider.rs @@ -115,6 +115,9 @@ pub struct OpenIdProvider { // The groups to sync from the directory, exact match pub directory_sync_group_match: Vec, pub jumpcloud_api_key: Option, + // Fetch all users from directory and create them in Defguard + // TODO: currently only supported for Microsoft + pub prefetch_users: bool, } impl OpenIdProvider { @@ -137,6 +140,7 @@ impl OpenIdProvider { okta_dirsync_client_id: Option, directory_sync_group_match: Vec, jumpcloud_api_key: Option, + prefetch_users: bool, ) -> Self { Self { id: NoId, @@ -157,6 +161,7 @@ impl OpenIdProvider { okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key, + prefetch_users, } } @@ -169,8 +174,9 @@ impl OpenIdProvider { directory_sync_interval = $10, directory_sync_user_behavior = $11, \ directory_sync_admin_behavior = $12, directory_sync_target = $13, \ okta_private_jwk = $14, okta_dirsync_client_id = $15, \ - directory_sync_group_match = $16, jumpcloud_api_key = $17 \ - WHERE id = $18", + directory_sync_group_match = $16, jumpcloud_api_key = $17, \ + prefetch_users = $18 \ + WHERE id = $19", self.name, self.base_url, self.client_id, @@ -188,6 +194,7 @@ impl OpenIdProvider { self.okta_dirsync_client_id, &self.directory_sync_group_match, self.jumpcloud_api_key, + self.prefetch_users, provider.id, ) .execute(pool) @@ -215,7 +222,7 @@ impl OpenIdProvider { directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", \ directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", \ directory_sync_target \"directory_sync_target: DirectorySyncTarget\", \ - okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key \ + okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key, prefetch_users \ FROM openidprovider WHERE name = $1", name ) @@ -234,7 +241,7 @@ impl OpenIdProvider { directory_sync_interval, directory_sync_user_behavior \"directory_sync_user_behavior: DirectorySyncUserBehavior\", \ directory_sync_admin_behavior \"directory_sync_admin_behavior: DirectorySyncUserBehavior\", \ directory_sync_target \"directory_sync_target: DirectorySyncTarget\", \ - okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key \ + okta_private_jwk, okta_dirsync_client_id, directory_sync_group_match, jumpcloud_api_key, prefetch_users \ FROM openidprovider LIMIT 1" ) .fetch_optional(executor) diff --git a/crates/defguard_core/src/enterprise/directory_sync/google.rs b/crates/defguard_core/src/enterprise/directory_sync/google.rs index 4f7a5139fa..642af28e62 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/google.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/google.rs @@ -106,6 +106,8 @@ impl From for DirectoryUser { email: val.primary_email, active: !val.suspended, id: None, + // TODO: currently not supported for Google + user_details: None, } } } diff --git a/crates/defguard_core/src/enterprise/directory_sync/jumpcloud.rs b/crates/defguard_core/src/enterprise/directory_sync/jumpcloud.rs index aad95011ae..93d8f78280 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/jumpcloud.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/jumpcloud.rs @@ -39,6 +39,8 @@ impl From for DirectoryUser { email: user.email, active: user.activated && !user.account_locked && user.state == UserState::Activated, id: Some(user.id), + // TODO: currently not supported for Jumpcloud + user_details: None, } } } diff --git a/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs b/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs index 48ebef13a5..7e02645e7f 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/microsoft.rs @@ -6,7 +6,7 @@ use super::{ DirectoryGroup, DirectorySync, DirectorySyncError, DirectoryUser, REQUEST_PAGINATION_SLOWDOWN, make_get_request, parse_response, }; -use crate::enterprise::directory_sync::REQUEST_TIMEOUT; +use crate::enterprise::directory_sync::{DirectoryUserDetails, REQUEST_TIMEOUT}; pub(crate) struct MicrosoftDirectorySync { access_token: Option, @@ -26,7 +26,8 @@ const MICROSOFT_DEFAULT_SCOPE: &str = "https://graph.microsoft.com/.default"; const GRANT_TYPE: &str = "client_credentials"; const MAX_RESULTS: &str = "200"; const MAX_REQUESTS: usize = 50; -const USER_QUERY_FIELDS: &str = "accountEnabled,displayName,mail,otherMails"; +const USER_QUERY_FIELDS: &str = + "accountEnabled,displayName,mail,otherMails,id,givenName,surname,mobilePhone,businessPhones"; const USER_SEARCH_URL: &str = "https://graph.microsoft.com/v1.0/users?$select=id&$filter=mail eq '{email}'"; const USER_SEARCH_URL_FALLBACK: &str = @@ -103,6 +104,7 @@ impl From for Vec { #[derive(Debug, Serialize, Deserialize)] struct User { + id: String, #[serde(rename = "displayName")] display_name: String, mail: Option, @@ -110,6 +112,13 @@ struct User { account_enabled: bool, #[serde(rename = "otherMails")] other_mails: Vec, + #[serde(rename = "givenName")] + given_name: Option, + surname: Option, + #[serde(rename = "mobilePhone")] + mobile_phone: Option, + #[serde(rename = "businessPhones")] + business_phones: Vec, } #[derive(Debug, Serialize, Deserialize, Default)] @@ -125,11 +134,26 @@ impl From for Vec { .value .into_iter() .filter_map(|user| { +// check if additional user detail data is available +let user_details = if let ( Some(first_name), Some(last_name)) = ( user.given_name, user.surname) { + // get a phone number if any is available + // prefer mobile phone + let phone_number = match user.mobile_phone { + Some(mobile_phone) => Some(mobile_phone), + None => user.business_phones.into_iter().next() + }; + Some(DirectoryUserDetails { last_name, first_name, phone_number }) +} else { + debug!("User {} doesn't have all required user details and will be skipped if user creation is required", user.display_name); + None +}; + + if let Some(email) = user.mail { - Some(DirectoryUser { email, active: user.account_enabled, id: None }) + Some(DirectoryUser { email, active: user.account_enabled, id: Some(user.id), user_details }) } else if let Some(email) = user.other_mails.into_iter().next() { warn!("User {} doesn't have a primary email address set, his first additional email address will be used: {email}", user.display_name); - Some(DirectoryUser { email, active: user.account_enabled, id: None }) + Some(DirectoryUser { email, active: user.account_enabled, id: Some(user.id), user_details }) } else { warn!("User {} doesn't have any email address and will be skipped in synchronization.", user.display_name); None @@ -621,18 +645,33 @@ mod tests { mail: Some("email@email.com".to_string()), account_enabled: true, other_mails: vec![], + id: "user1-id".into(), + given_name: Some("User".into()), + surname: Some("One".into()), + mobile_phone: Some("555555555".into()), + business_phones: vec![], }, User { display_name: "User 2".to_string(), mail: None, account_enabled: true, other_mails: vec!["email2@email.com".to_string()], + id: "user2-id".into(), + given_name: Some("User".into()), + surname: Some("Two".into()), + mobile_phone: None, + business_phones: vec![], }, User { display_name: "User 3".to_string(), mail: None, account_enabled: true, other_mails: vec![], + id: "user3-id".into(), + given_name: Some("User".into()), + surname: Some("Three".into()), + mobile_phone: None, + business_phones: vec![], }, ], }; @@ -653,18 +692,33 @@ mod tests { mail: Some("email@email.com".to_string()), account_enabled: true, other_mails: vec![], + id: "user1-id".into(), + given_name: Some("User".into()), + surname: None, + mobile_phone: None, + business_phones: vec![], }, User { display_name: "User 2".to_string(), mail: None, account_enabled: true, other_mails: vec!["email2@email.com".to_string()], + id: "user2-id".into(), + given_name: None, + surname: None, + mobile_phone: Some("555555555".into()), + business_phones: vec![], }, User { display_name: "User 3".to_string(), mail: None, account_enabled: true, other_mails: vec![], + id: "user3-id".into(), + given_name: Some("User".into()), + surname: Some("Three".into()), + mobile_phone: Some("555555555".into()), + business_phones: vec![], }, ], }; diff --git a/crates/defguard_core/src/enterprise/directory_sync/mod.rs b/crates/defguard_core/src/enterprise/directory_sync/mod.rs index 70ddd638ce..b37fccba56 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/mod.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/mod.rs @@ -1,12 +1,13 @@ use std::{ collections::{HashMap, HashSet}, + fmt::Debug, time::Duration, }; -use defguard_common::db::Id; +use defguard_common::db::{Id, models::Settings}; use paste::paste; use reqwest::header::AUTHORIZATION; -use sqlx::{PgPool, error::Error as SqlxError}; +use sqlx::{PgConnection, PgPool, error::Error as SqlxError}; use thiserror::Error; use tokio::sync::broadcast::Sender; @@ -20,8 +21,10 @@ use crate::{ db::{GatewayEvent, Group, User}, enterprise::{ db::models::openid_provider::DirectorySyncUserBehavior, + handlers::openid_login::prune_username, ldap::utils::{ldap_add_users_to_groups, ldap_delete_users, ldap_remove_users_from_groups}, }, + handlers::user::check_username, }; const REQUEST_TIMEOUT: Duration = Duration::from_secs(10); @@ -55,6 +58,8 @@ pub enum DirectorySyncError { NetworkUpdateError(String), #[error("Failed to update user state: {0}")] UserUpdateError(String), + #[error("Failed to create user: {0}")] + UserCreateError(String), #[error("Failed to find user: {0}")] UserNotFound(String), #[error( @@ -100,6 +105,16 @@ pub struct DirectoryUser { pub email: String, // Users may be disabled/suspended in the directory pub active: bool, + // Currently only supported for Microsoft Entra + user_details: Option, +} + +// additional user details required for user creation +#[derive(Debug, Serialize, Deserialize)] +pub struct DirectoryUserDetails { + last_name: String, + first_name: String, + phone_number: Option, } #[trait_variant::make(Send)] @@ -594,71 +609,127 @@ async fn sync_all_users_state( .await? .ok_or(DirectorySyncError::NotConfigured)?; + // prepare relevant settings let user_behavior = settings.directory_sync_user_behavior; let admin_behavior = settings.directory_sync_admin_behavior; + let prefetch_users = settings.prefetch_users; - let emails = all_users - .iter() - .map(|u| u.email.as_str()) - .collect::>(); - let missing_users = User::exclude(&mut *transaction, &emails) - .await? - .into_iter() - .collect::>>(); + // split directory users into separate lists for active and inactive users + let (active_directory_users, inactive_directory_users): (Vec<_>, Vec<_>) = + all_users.iter().partition(|user| user.active); - let disabled_users_emails = all_users + // prepare a list of user emails for matching users between directory and Defguard + let all_directory_emails = all_users .iter() - .filter(|u| !u.active) .map(|u| u.email.as_str()) .collect::>(); - let users_to_disable = - User::find_many_by_emails(&mut *transaction, &disabled_users_emails).await?; - - let enabled_users_emails = all_users - .iter() - .filter(|u| u.active) - .map(|u| u.email.as_str()) - .collect::>(); - let users_to_enable = - User::find_many_by_emails(&mut *transaction, &enabled_users_emails).await?; - - debug!( - "There are {} disabled users in the directory, disabling them in Defguard...", - users_to_disable.len() - ); + // setup Vecs for tracking user updates let mut modified_users = Vec::new(); let mut deleted_users = Vec::new(); + let mut created_users = Vec::new(); - for mut user in users_to_disable { - if user.is_active { - debug!( - "Disabling user {} because they are disabled in the directory", - user.email - ); - user.disable(&mut transaction, wg_tx).await.map_err(|err| { - DirectorySyncError::UserUpdateError(format!( - "Failed to disable user {} during directory synchronization: {err}", - user.email - )) - })?; - modified_users.push(user); - } else { - debug!("User {} is already disabled, skipping", user.email); + sync_inactive_directory_users( + &mut transaction, + &inactive_directory_users, + &mut modified_users, + wg_tx, + ) + .await?; + + sync_active_directory_users( + &mut transaction, + &active_directory_users, + &mut modified_users, + ) + .await?; + + // TODO: prefetching users is currently only supported for Microsoft Entra + if prefetch_users && ["Microsoft", "Test"].contains(&settings.name.as_str()) { + // get emails of all directory users who already exist in Defguard + let existing_users = + User::find_many_by_emails(&mut *transaction, &all_directory_emails).await?; + let existing_user_emails: Vec<&str> = existing_users + .iter() + .map(|user| user.email.as_str()) + .collect(); + + // find all directory users not present in Defguard + let missing_defguard_users: Vec<_> = all_users + .iter() + .filter(|user| !existing_user_emails.contains(&user.email.as_str())) + .collect(); + + let core_settings = Settings::get_current_settings(); + + // create missing users + for directory_user in missing_defguard_users { + match &directory_user.user_details { + None => { + error!( + "Missing directory user details for user {directory_user:?}. Unable to create missing Defguard user." + ); + } + Some(details) => { + debug!( + "User {directory_user:?} exists in directory but not in Defguard. Creating new Defguard user.", + ); + + // Extract the username from the email address + let email = directory_user.email.clone(); + let username = + email + .split('@') + .next() + .ok_or(DirectorySyncError::UserCreateError(format!( + "Failed to extract username from email address {email}" + )))?; + let username = prune_username(username, core_settings.openid_username_handling); + check_username(&username).map_err(|err| { + DirectorySyncError::UserCreateError(format!( + "Username {username} validation failed: {err:?}" + )) + })?; + + // Check if user with the same username already exists (usernames are unique). + if User::find_by_username(pool, &username).await?.is_some() { + return Err(DirectorySyncError::UserCreateError(format!( + "User with username {username} already exists" + ))); + } + + let mut user = User::new( + username, + None, + details.last_name.clone(), + details.first_name.clone(), + directory_user.email.clone(), + details.phone_number.clone(), + ); + user.openid_sub = directory_user.id.clone(); + let new_user = user.save(&mut *transaction).await?; + created_users.push(new_user); + } + } } } - debug!("Done processing disabled users"); + + // get all users present in Defguard but not in directory + let missing_directory_users = User::exclude(&mut *transaction, &all_directory_emails) + .await? + .into_iter() + .collect::>>(); debug!( "There are {} users missing from the directory but present in Defguard, \ deciding what to do next based on the following settings: user action: {}, admin action: {}", - missing_users.len(), + missing_directory_users.len(), user_behavior, admin_behavior ); // Keep the admin count to prevent deleting the last admin let mut admin_count = User::find_admins(&mut *transaction).await?.len(); - for mut user in missing_users { + for mut user in missing_directory_users { if user.is_admin(&mut *transaction).await? { match admin_behavior { DirectorySyncUserBehavior::Keep => { @@ -770,8 +841,90 @@ async fn sync_all_users_state( } debug!("Done processing missing users"); + transaction.commit().await?; + + // trigger LDAP sync + ldap_delete_users(deleted_users.iter().collect::>(), pool).await; + Box::pin(ldap_update_users_state( + modified_users.iter_mut().collect::>(), + pool, + )) + .await; + Box::pin(ldap_update_users_state( + created_users.iter_mut().collect::>(), + pool, + )) + .await; + + info!("Syncing all users' state with the directory done"); + + Ok(()) +} + +async fn sync_inactive_directory_users( + transaction: &mut PgConnection, + inactive_directory_users: &[&DirectoryUser], + modified_users: &mut Vec>, + wg_tx: &Sender, +) -> Result<(), DirectorySyncError> { + // find all active Defguard users disabled in directory + let disabled_users_emails = inactive_directory_users + .iter() + .map(|u| u.email.as_str()) + .collect::>(); + let users_to_disable: Vec> = + User::find_many_by_emails(&mut *transaction, &disabled_users_emails) + .await? + .into_iter() + .filter(|user| user.is_active) + .collect(); + + debug!( + "There are {} active Defguard users disabled in the directory. Disabling them in Defguard...", + users_to_disable.len() + ); + + for mut user in users_to_disable { + if user.is_active { + debug!( + "Disabling user {} because they are disabled in the directory", + user.email + ); + user.disable(transaction, wg_tx).await.map_err(|err| { + DirectorySyncError::UserUpdateError(format!( + "Failed to disable user {} during directory synchronization: {err}", + user.email + )) + })?; + modified_users.push(user); + } else { + debug!("User {} is already disabled, skipping", user.email); + } + } + debug!("Done processing disabled directory users"); + + Ok(()) +} + +async fn sync_active_directory_users( + transaction: &mut PgConnection, + active_directory_users: &[&DirectoryUser], + modified_users: &mut Vec>, +) -> Result<(), DirectorySyncError> { + // find all inactive Defguard users enabled in directory + let enabled_users_emails = active_directory_users + .iter() + .map(|u| u.email.as_str()) + .collect::>(); + let users_to_enable: Vec> = + User::find_many_by_emails(&mut *transaction, &enabled_users_emails) + .await? + .into_iter() + .filter(|user| !user.is_active) + .collect(); + debug!( - "There are {} enabled users in the directory, enabling them in Defguard if they were previously disabled", + "There are {} inactive Defguard users enabled in the directory. Enabling them in Defguard...", users_to_enable.len() ); for mut user in users_to_enable { @@ -787,17 +940,7 @@ async fn sync_all_users_state( user.save(&mut *transaction).await?; modified_users.push(user); } - debug!("Done processing enabled users"); - transaction.commit().await?; - - ldap_delete_users(deleted_users.iter().collect::>(), pool).await; - Box::pin(ldap_update_users_state( - modified_users.iter_mut().collect::>(), - pool, - )) - .await; - - info!("Syncing all users' state with the directory done"); + debug!("Done processing active directory users"); Ok(()) } diff --git a/crates/defguard_core/src/enterprise/directory_sync/okta.rs b/crates/defguard_core/src/enterprise/directory_sync/okta.rs index bbc168fe16..569f4ee473 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/okta.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/okta.rs @@ -96,6 +96,8 @@ impl From for DirectoryUser { email: val.profile.email, active: ACTIVE_STATUS.contains(&val.status.as_str()), id: None, + // TODO: currently not supported for Okta + user_details: None, } } } diff --git a/crates/defguard_core/src/enterprise/directory_sync/testprovider.rs b/crates/defguard_core/src/enterprise/directory_sync/testprovider.rs index fc74bdebfd..b73d5abbed 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/testprovider.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/testprovider.rs @@ -53,16 +53,31 @@ impl DirectorySync for TestProviderDirectorySync { email: "testuser@email.com".into(), active: true, id: Some("testuser-id".into()), + user_details: Some(crate::enterprise::directory_sync::DirectoryUserDetails { + last_name: "User".into(), + first_name: "Test".into(), + phone_number: None, + }), }, DirectoryUser { email: "testuserdisabled@email.com".into(), active: false, id: Some("testuserdisabled-id".into()), + user_details: Some(crate::enterprise::directory_sync::DirectoryUserDetails { + last_name: "UserDisabled".into(), + first_name: "Test".into(), + phone_number: None, + }), }, DirectoryUser { email: "testuser2@email.com".into(), active: true, id: Some("testuser2-id".into()), + user_details: Some(crate::enterprise::directory_sync::DirectoryUserDetails { + last_name: "User2".into(), + first_name: "Test".into(), + phone_number: None, + }), }, ]) } diff --git a/crates/defguard_core/src/enterprise/directory_sync/tests.rs b/crates/defguard_core/src/enterprise/directory_sync/tests.rs index e0d1a5496c..9bac17d281 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/tests.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/tests.rs @@ -40,6 +40,7 @@ mod test { user_behavior: DirectorySyncUserBehavior, admin_behavior: DirectorySyncUserBehavior, target: DirectorySyncTarget, + prefetch_users: bool, ) -> OpenIdProvider { Settings::init_defaults(pool).await.unwrap(); initialize_current_settings(pool).await.unwrap(); @@ -86,6 +87,7 @@ mod test { None, vec![], None, + prefetch_users, ) .save(pool) .await @@ -146,6 +148,7 @@ mod test { DirectorySyncUserBehavior::Keep, DirectorySyncUserBehavior::Keep, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -185,6 +188,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Keep, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -231,6 +235,7 @@ mod test { DirectorySyncUserBehavior::Keep, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -283,6 +288,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; User::init_admin_user(&pool, config.default_admin_password.expose_secret()) @@ -353,6 +359,7 @@ mod test { DirectorySyncUserBehavior::Disable, DirectorySyncUserBehavior::Keep, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -435,6 +442,7 @@ mod test { DirectorySyncUserBehavior::Keep, DirectorySyncUserBehavior::Disable, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -512,6 +520,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -568,6 +577,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -596,6 +606,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::Users, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -620,6 +631,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let network = get_test_network(&pool).await; @@ -675,6 +687,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::Groups, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -702,6 +715,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -748,6 +762,7 @@ mod test { DirectorySyncUserBehavior::Delete, DirectorySyncUserBehavior::Delete, DirectorySyncTarget::All, + false, ) .await; let mut client = DirectorySyncClient::build(&pool).await.unwrap(); @@ -774,4 +789,72 @@ mod test { let user = User::find_by_username(&pool, "defguard").await.unwrap(); assert!(user.is_none()); } + + #[sqlx::test] + async fn test_users_no_prefetch(_: PgPoolOptions, options: PgConnectOptions) { + let pool = setup_pool(options).await; + + let config = DefGuardConfig::new_test_config(); + let _ = SERVER_CONFIG.set(config.clone()); + let (wg_tx, mut wg_rx) = broadcast::channel::(16); + + // disable prefetching users + make_test_provider( + &pool, + DirectorySyncUserBehavior::Keep, + DirectorySyncUserBehavior::Keep, + DirectorySyncTarget::All, + false, + ) + .await; + let mut client = DirectorySyncClient::build(&pool).await.unwrap(); + client.prepare().await.unwrap(); + + // no users in Defguard before sync + let defguard_users = User::all(&pool).await.unwrap(); + assert!(defguard_users.is_empty()); + + do_directory_sync(&pool, &wg_tx).await.unwrap(); + + // no users in Defguard after sync + let defguard_users = User::all(&pool).await.unwrap(); + assert!(defguard_users.is_empty()); + + // No events + assert!(wg_rx.try_recv().is_err()); + } + + #[sqlx::test] + async fn test_users_prefetch(_: PgPoolOptions, options: PgConnectOptions) { + let pool = setup_pool(options).await; + + let config = DefGuardConfig::new_test_config(); + let _ = SERVER_CONFIG.set(config.clone()); + let (wg_tx, mut wg_rx) = broadcast::channel::(16); + + // enable prefetching users + make_test_provider( + &pool, + DirectorySyncUserBehavior::Keep, + DirectorySyncUserBehavior::Keep, + DirectorySyncTarget::All, + true, + ) + .await; + let mut client = DirectorySyncClient::build(&pool).await.unwrap(); + client.prepare().await.unwrap(); + + // no users in Defguard before sync + let defguard_users = User::all(&pool).await.unwrap(); + assert!(defguard_users.is_empty()); + + do_directory_sync(&pool, &wg_tx).await.unwrap(); + + // all active directory users were synced + let defguard_users = User::all(&pool).await.unwrap(); + assert_eq!(defguard_users.len(), 3); + + // No events + assert!(wg_rx.try_recv().is_err()); + } } diff --git a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs index b03d904df9..6e5e8d032d 100644 --- a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs +++ b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs @@ -11,7 +11,7 @@ use crate::{ events::{BidiRequestContext, BidiStreamEvent, BidiStreamEventType, DesktopClientMfaEvent}, grpc::{ client_mfa::{ClientLoginSession, ClientMfaServer}, - utils::parse_client_info, + utils::parse_client_ip_agent, }, }; @@ -66,7 +66,7 @@ impl ClientMfaServer { return Err(Status::invalid_argument("invalid MFA method")); } - let (ip, _user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let (ip, _user_agent) = parse_client_ip_agent(&info).map_err(Status::internal)?; let context = BidiRequestContext::new( user.id, user.username.clone(), diff --git a/crates/defguard_core/src/enterprise/grpc/polling.rs b/crates/defguard_core/src/enterprise/grpc/polling.rs index ecce3ec2f3..8e04e9a411 100644 --- a/crates/defguard_core/src/enterprise/grpc/polling.rs +++ b/crates/defguard_core/src/enterprise/grpc/polling.rs @@ -1,5 +1,5 @@ use defguard_common::db::Id; -use defguard_proto::proxy::{InstanceInfoRequest, InstanceInfoResponse}; +use defguard_proto::proxy::{DeviceInfo, InstanceInfoRequest, InstanceInfoResponse}; use sqlx::PgPool; use tonic::Status; @@ -47,7 +47,11 @@ impl PollingServer { /// Prepares instance info for polling requests. Enterprise only. #[instrument(skip_all)] - pub async fn info(&self, request: InstanceInfoRequest) -> Result { + pub async fn info( + &self, + request: InstanceInfoRequest, + device_info: Option, + ) -> Result { trace!("Polling info start"); let token = self.validate_session(&request.token).await?; let Some(device) = Device::find_by_id(&self.pool, token.device_id) @@ -82,7 +86,8 @@ impl PollingServer { } // Build and return polling info. - let device_config = build_device_config_response(&self.pool, device, None).await?; + let device_config = + build_device_config_response(&self.pool, device, None, device_info).await?; Ok(InstanceInfoResponse { device_config: Some(device_config), diff --git a/crates/defguard_core/src/enterprise/handlers/openid_providers.rs b/crates/defguard_core/src/enterprise/handlers/openid_providers.rs index 565e573913..01cef376e6 100644 --- a/crates/defguard_core/src/enterprise/handlers/openid_providers.rs +++ b/crates/defguard_core/src/enterprise/handlers/openid_providers.rs @@ -43,6 +43,7 @@ pub struct AddProviderData { pub directory_sync_group_match: Option, pub username_handling: OpenidUsernameHandling, pub jumpcloud_api_key: Option, + pub prefetch_users: bool, } #[derive(Deserialize, Serialize)] @@ -160,6 +161,7 @@ pub async fn add_openid_provider( provider_data.okta_dirsync_client_id, group_match, provider_data.jumpcloud_api_key, + provider_data.prefetch_users, ) .upsert(&appstate.pool) .await?; diff --git a/crates/defguard_core/src/enterprise/ldap/hash.rs b/crates/defguard_core/src/enterprise/ldap/hash.rs index ddb6d4c8d6..86aec6fa7a 100644 --- a/crates/defguard_core/src/enterprise/ldap/hash.rs +++ b/crates/defguard_core/src/enterprise/ldap/hash.rs @@ -2,6 +2,7 @@ use base64::Engine; use defguard_common::hex::to_lower_hex; use md4::Md4; use rand::{RngCore, rngs::OsRng}; +#[allow(deprecated)] use sha1::{ Digest, Sha1, digest::generic_array::{GenericArray, sequence::Concat}, @@ -18,6 +19,7 @@ pub fn salted_sha1_hash(password: &str) -> String { pass.extend_from_slice(&salt); let checksum = Sha1::digest(pass); + #[allow(deprecated)] let checksum = checksum.concat(GenericArray::from(salt)); format!( diff --git a/crates/defguard_core/src/grpc/client_mfa.rs b/crates/defguard_core/src/grpc/client_mfa.rs index ea1e6482d6..f688a41a48 100644 --- a/crates/defguard_core/src/grpc/client_mfa.rs +++ b/crates/defguard_core/src/grpc/client_mfa.rs @@ -32,7 +32,7 @@ use crate::{ }, enterprise::{db::models::openid_provider::OpenIdProvider, is_enterprise_enabled}, events::{BidiRequestContext, BidiStreamEvent, BidiStreamEventType, DesktopClientMfaEvent}, - grpc::utils::parse_client_info, + grpc::utils::parse_client_ip_agent, handlers::mail::send_email_mfa_code_email, }; @@ -395,7 +395,7 @@ impl ClientMfaServer { } = session; // Prepare event context - let (ip, _user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let (ip, _user_agent) = parse_client_ip_agent(&info).map_err(Status::internal)?; let context = BidiRequestContext::new( user.id, user.username.clone(), diff --git a/crates/defguard_core/src/grpc/client_version.rs b/crates/defguard_core/src/grpc/client_version.rs new file mode 100644 index 0000000000..d8bc7be95e --- /dev/null +++ b/crates/defguard_core/src/grpc/client_version.rs @@ -0,0 +1,386 @@ +use base64::{Engine, prelude::BASE64_STANDARD}; +use defguard_proto::proxy::{ClientPlatformInfo, DeviceInfo}; +use prost::Message; +use semver::Version; + +pub(crate) fn parse_client_version_platform( + info: Option<&DeviceInfo>, +) -> (Option, Option) { + let Some(info) = info else { + debug!("Device information is missing from the request"); + return (None, None); + }; + + let version = info.version.as_ref().map_or_else( + || None, + |v| { + Version::parse(v).map_or_else( + |_| { + error!("Invalid version string: {v}"); + None + }, + Some, + ) + }, + ); + + let platform = info.platform.as_ref().and_then(|p| { + let binary = BASE64_STANDARD + .decode(p) + .map_err(|e| { + error!("Failed to decode base64 platform string: {e}"); + e + }) + .ok()?; + let platform_info = ClientPlatformInfo::decode(&*binary) + .map_err(|e| { + error!("Failed to decode ClientPlatformInfo from bytes: {e}"); + e + }) + .ok()?; + Some(platform_info) + }); + + (version, platform) +} + +/// Represents a client feature that may have minimum version and OS family requirements. +#[derive(Debug)] +pub(crate) enum ClientFeature { + ServiceLocations, +} + +impl ClientFeature { + const fn min_version(&self) -> Option { + match self { + Self::ServiceLocations => Some(Version::new(1, 6, 0)), + } + } + + fn required_os_family(&self) -> Option> { + match self { + Self::ServiceLocations => Some(vec!["windows"]), + } + } + + pub(crate) fn is_supported_by_device(&self, info: Option<&DeviceInfo>) -> bool { + let (version, platform) = parse_client_version_platform(info); + + // No minimum version = matches all + let version_matches = self.min_version().is_none_or(|min_version| { + // No version info = does not match + version + .as_ref() + .is_some_and(|version| version >= &min_version) + }); + + if !version_matches { + debug!( + "Client version {version:?} does not meet minimum version {:?} for feature {self:?}", + self.min_version() + ); + } + + // No required OS family = matches all + let platform_matches = self.required_os_family().is_none_or(|platforms| { + platforms.iter().any(|p| { + platform + .as_ref() + .is_some_and(|platform| platform.os_family.eq_ignore_ascii_case(p)) + }) + }); + + if !platform_matches { + debug!( + "Client OS {:?} does not meet required OS {:?} for feature {self:?}", + platform.as_ref().map(|p| &p.os_family), + self.required_os_family() + ); + } + + version_matches && platform_matches + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // Helper function to create DeviceInfo + fn create_device_info( + version: Option, + platform: Option, + ) -> DeviceInfo { + let platform = platform.map(|p| { + let mut buf = Vec::new(); + p.encode(&mut buf).unwrap(); + BASE64_STANDARD.encode(&buf) + }); + + DeviceInfo { + version, + platform, + ..Default::default() + } + } + + #[test] + fn test_parse_client_version_platform() { + // Test with valid version and platform + let info = create_device_info( + Some("1.5.0".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_some()); + assert_eq!(version.unwrap(), Version::new(1, 5, 0)); + assert!(platform.is_some()); + assert_eq!(platform.unwrap().os_family, "windows"); + + // Test with no DeviceInfo + let (version, platform) = parse_client_version_platform(None); + assert!(version.is_none()); + assert!(platform.is_none()); + + // Test with invalid version string + let info = create_device_info( + Some("invalid.version".to_string()), + Some(ClientPlatformInfo { + os_family: "linux".to_string(), + os_type: "Ubuntu".to_string(), + version: "22.04".to_string(), + ..Default::default() + }), + ); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_none()); + assert!(platform.is_some()); + + // Test with missing version field + let info = create_device_info( + None, + Some(ClientPlatformInfo { + os_family: "linux".to_string(), + os_type: "Ubuntu".to_string(), + version: "22.04".to_string(), + ..Default::default() + }), + ); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_none()); + assert!(platform.is_some()); + + // Test with missing platform field + let info = create_device_info(Some("1.5.0".to_string()), None); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_some()); + assert!(platform.is_none()); + + // Test with both fields missing + let info = create_device_info(None, None); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_none()); + assert!(platform.is_none()); + + // Test with pre-release version + let info = create_device_info( + Some("1.5.0-alpha1".to_string()), + Some(ClientPlatformInfo { + os_family: "macos".to_string(), + os_type: "macOS".to_string(), + version: "14.0".to_string(), + ..Default::default() + }), + ); + let (version, platform) = parse_client_version_platform(Some(&info)); + assert!(version.is_some()); + assert_eq!(version.unwrap(), Version::parse("1.5.0-alpha1").unwrap()); + assert!(platform.is_some()); + } + + #[test] + fn test_client_feature_is_supported_by_device() { + // Test ServiceLocations feature with supported version and OS + let info = create_device_info( + Some("1.6.0".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should be supported on Windows with version 1.6.0" + ); + + // Test with exact minimum version + let info = create_device_info( + Some("1.6.0".to_string()), + Some(ClientPlatformInfo { + os_family: "Windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should be supported at minimum version" + ); + + // Test with higher version + let info = create_device_info( + Some("2.0.0".to_string()), + Some(ClientPlatformInfo { + os_family: "WINDOWS".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should be supported with higher version" + ); + + // Test with version below minimum + let info = create_device_info( + Some("1.5.9".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported below minimum version" + ); + + // Test with wrong OS family (linux) + let info = create_device_info( + Some("1.6.0".to_string()), + Some(ClientPlatformInfo { + os_family: "linux".to_string(), + os_type: "Ubuntu".to_string(), + version: "22.04".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported on Linux" + ); + + // Test with wrong OS family (macos) + let info = create_device_info( + Some("1.6.0".to_string()), + Some(ClientPlatformInfo { + os_family: "macos".to_string(), + os_type: "macOS".to_string(), + version: "14.0".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported on macOS" + ); + + // Test with no DeviceInfo + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(None), + "ServiceLocations should not be supported without device info" + ); + + // Test with missing version + let info = create_device_info( + None, + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported without version info" + ); + + // Test with missing platform + let info = create_device_info(Some("1.6.0".to_string()), None); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported without platform info" + ); + + // Test with invalid version string + let info = create_device_info( + Some("invalid".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported with invalid version" + ); + + // Test case insensitivity of OS family matching + let info = create_device_info( + Some("1.6.0".to_string()), + Some(ClientPlatformInfo { + os_family: "WiNdOwS".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should be supported with mixed-case OS family" + ); + + // Test with pre-release version above minimum + let info = create_device_info( + Some("1.7.0-alpha1".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should be supported with pre-release version above minimum" + ); + + // Test with pre-release version below minimum + let info = create_device_info( + Some("1.5.0-alpha1".to_string()), + Some(ClientPlatformInfo { + os_family: "windows".to_string(), + os_type: "Windows".to_string(), + version: "11".to_string(), + ..Default::default() + }), + ); + assert!( + !ClientFeature::ServiceLocations.is_supported_by_device(Some(&info)), + "ServiceLocations should not be supported with pre-release version below minimum" + ); + } +} diff --git a/crates/defguard_core/src/grpc/enrollment.rs b/crates/defguard_core/src/grpc/enrollment.rs index 639ee3cf7e..c7a43069ba 100644 --- a/crates/defguard_core/src/grpc/enrollment.rs +++ b/crates/defguard_core/src/grpc/enrollment.rs @@ -43,7 +43,10 @@ use crate::{ limits::update_counts, }, events::{BidiRequestContext, BidiStreamEvent, BidiStreamEventType, EnrollmentEvent}, - grpc::utils::{build_device_config_response, new_polling_token, parse_client_info}, + grpc::{ + client_version::ClientFeature, + utils::{build_device_config_response, new_polling_token, parse_client_ip_agent}, + }, handlers::{ mail::{ send_email_mfa_activation_email, send_mfa_configured_email, send_new_device_added_email, @@ -289,7 +292,7 @@ impl EnrollmentServer { })?; // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&info).map_err(Status::internal)?; let context = BidiRequestContext::new(user_id, username, ip, user_agent); self.emit_event(context, EnrollmentEvent::EnrollmentStarted) .map_err(|err| { @@ -479,7 +482,7 @@ impl EnrollmentServer { info!("User {} activated", user.username); // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&req_device_info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&req_device_info).map_err(Status::internal)?; let context = BidiRequestContext::new(user.id, user.username.clone(), ip, user_agent); self.emit_event(context, EnrollmentEvent::EnrollmentCompleted) .map_err(|err| { @@ -806,6 +809,16 @@ impl EnrollmentServer { Status::internal("unexpected error") })?; + // Don't send them service locations if they don't support it + let configs = configs + .into_iter() + .filter(|config| { + config.service_location_mode == ServiceLocationMode::Disabled + || ClientFeature::ServiceLocations + .is_supported_by_device(req_device_info.as_ref()) + }) + .collect::>(); + let template_locations: Vec = configs .iter() .map(|c| TemplateLocation { @@ -854,7 +867,7 @@ impl EnrollmentServer { }; // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&req_device_info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&req_device_info).map_err(Status::internal)?; let context = BidiRequestContext::new(user.id, user.username.clone(), ip, user_agent); self.emit_event(context, EnrollmentEvent::EnrollmentDeviceAdded { device }) .map_err(|err| { @@ -870,6 +883,7 @@ impl EnrollmentServer { pub async fn get_network_info( &self, request: ExistingDevice, + device_info: Option, ) -> Result { debug!("Getting network info for device: {:?}", request.pubkey); let token = self.validate_session(request.token.as_ref()).await?; @@ -896,7 +910,7 @@ impl EnrollmentServer { } let token = new_polling_token(&self.pool, &device).await?; - build_device_config_response(&self.pool, device, Some(token)).await + build_device_config_response(&self.pool, device, Some(token), device_info).await } // TODO: Add events diff --git a/crates/defguard_core/src/grpc/gateway/mod.rs b/crates/defguard_core/src/grpc/gateway/mod.rs index 1fd5ad6f3a..ff119fc0fc 100644 --- a/crates/defguard_core/src/grpc/gateway/mod.rs +++ b/crates/defguard_core/src/grpc/gateway/mod.rs @@ -239,25 +239,18 @@ impl GatewayServer { Ok(self.grpc_event_tx.send(event)?) } - /// Helper method to fetch `Device` info from DB and return appropriate errors - async fn fetch_device_from_db(&self, public_key: &str) -> Result, Status> { - let device = match Device::find_by_pubkey(&self.pool, public_key).await { - Ok(Some(device)) => device, - Ok(None) => { - error!("Device with public key {public_key} not found"); - return Err(Status::new( - Code::Internal, - format!("Device with public key {public_key} not found"), - )); - } - Err(err) => { + /// Helper method to fetch `Device` info from DB by pubkey and return appropriate errors + async fn fetch_device_from_db(&self, public_key: &str) -> Result>, Status> { + let device = Device::find_by_pubkey(&self.pool, public_key) + .await + .map_err(|err| { error!("Failed to retrieve device with public key {public_key}: {err}",); - return Err(Status::new( + Status::new( Code::Internal, format!("Failed to retrieve device with public key {public_key}: {err}",), - )); - } - }; + ) + })?; + Ok(device) } @@ -825,8 +818,17 @@ impl gateway_service_server::GatewayService for GatewayServer { // fetch device from DB // TODO: fetch only when device has changed and use client state otherwise - let device = self.fetch_device_from_db(&public_key).await?; - // copy for easier reference later + let device = match self.fetch_device_from_db(&public_key).await? { + Some(device) => device, + None => { + warn!( + "Received stats update for a device which does not exist: {public_key}, skipping." + ); + continue; + } + }; + + // copy device ID for easier reference later let device_id = device.id; // fetch user and location from DB for activity log diff --git a/crates/defguard_core/src/grpc/mod.rs b/crates/defguard_core/src/grpc/mod.rs index 85cf800d95..96dbd24e69 100644 --- a/crates/defguard_core/src/grpc/mod.rs +++ b/crates/defguard_core/src/grpc/mod.rs @@ -69,6 +69,7 @@ static VERSION_ZERO: Version = Version::new(0, 0, 0); mod auth; pub(crate) mod client_mfa; +pub mod client_version; pub mod enrollment; pub mod gateway; mod interceptor; @@ -234,7 +235,11 @@ async fn handle_proxy_message_loop( } // rpc GetNetworkInfo (ExistingDevice) returns (DeviceConfigResponse) Some(core_request::Payload::ExistingDevice(request)) => { - match context.enrollment_server.get_network_info(request).await { + match context + .enrollment_server + .get_network_info(request, received.device_info) + .await + { Ok(response_payload) => { Some(core_response::Payload::DeviceConfig(response_payload)) } @@ -345,7 +350,11 @@ async fn handle_proxy_message_loop( } // rpc LocationInfo (LocationInfoRequest) returns (LocationInfoResponse) Some(core_request::Payload::InstanceInfo(request)) => { - match context.polling_server.info(request).await { + match context + .polling_server + .info(request, received.device_info) + .await + { Ok(response_payload) => { Some(core_response::Payload::InstanceInfo(response_payload)) } diff --git a/crates/defguard_core/src/grpc/password_reset.rs b/crates/defguard_core/src/grpc/password_reset.rs index 0c1957e713..4e8b35e6d4 100644 --- a/crates/defguard_core/src/grpc/password_reset.rs +++ b/crates/defguard_core/src/grpc/password_reset.rs @@ -14,7 +14,7 @@ use crate::{ }, enterprise::ldap::utils::ldap_change_password, events::{BidiRequestContext, BidiStreamEvent, BidiStreamEventType, PasswordResetEvent}, - grpc::utils::parse_client_info, + grpc::utils::parse_client_ip_agent, handlers::{ mail::{send_password_reset_email, send_password_reset_success_email}, user::check_password_strength, @@ -169,7 +169,7 @@ impl PasswordResetServer { ); // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&req_device_info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&req_device_info).map_err(Status::internal)?; let context = BidiRequestContext::new(user.id, user.username, ip, user_agent); self.emit_event(context, PasswordResetEvent::PasswordResetRequested) .map_err(|err| { @@ -235,7 +235,7 @@ impl PasswordResetServer { user.username ); // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&info).map_err(Status::internal)?; let context = BidiRequestContext::new(user.id, user.username, ip, user_agent); self.emit_event(context, PasswordResetEvent::PasswordResetStarted) .map_err(|err| { @@ -308,7 +308,7 @@ impl PasswordResetServer { )?; // Prepare event context and push the event - let (ip, user_agent) = parse_client_info(&req_device_info).map_err(Status::internal)?; + let (ip, user_agent) = parse_client_ip_agent(&req_device_info).map_err(Status::internal)?; let context = BidiRequestContext::new(user.id, user.username, ip, user_agent); self.emit_event(context, PasswordResetEvent::PasswordResetCompleted) .map_err(|err| { diff --git a/crates/defguard_core/src/grpc/utils.rs b/crates/defguard_core/src/grpc/utils.rs index 1f7ffec69a..b82e91fa1c 100644 --- a/crates/defguard_core/src/grpc/utils.rs +++ b/crates/defguard_core/src/grpc/utils.rs @@ -24,6 +24,7 @@ use crate::{ enterprise::db::models::{ enterprise_settings::EnterpriseSettings, openid_provider::OpenIdProvider, }, + grpc::client_version::ClientFeature, }; // Create a new token for configuration polling. @@ -72,6 +73,7 @@ pub(crate) async fn build_device_config_response( pool: &PgPool, device: Device, token: Option, + device_info: Option, ) -> Result { let settings = Settings::get_current_settings(); @@ -122,15 +124,17 @@ pub(crate) async fn build_device_config_response( ); Status::internal(format!("unexpected error: {err}")) })?; - if network.should_prevent_service_location_usage() { + + if network.service_location_mode != ServiceLocationMode::Disabled { error!( - "Tried to use service location {} with disabled enterprise features.", - network.name + "Network device {} tried to fetch config for service location {}, which is unsupported.", + device.name, network.name ); return Err(Status::permission_denied( - "service location mode is not available", + "service location mode is not available for network devices", )); } + // DEPRECATED(1.5): superseeded by location_mfa_mode let mfa_enabled = network.location_mfa_mode == LocationMfaMode::Internal; let config = @@ -182,6 +186,15 @@ pub(crate) async fn build_device_config_response( ); continue; } + if network.service_location_mode != ServiceLocationMode::Disabled + && !ClientFeature::ServiceLocations.is_supported_by_device(device_info.as_ref()) + { + info!( + "Device {} does not support service locations feature, skipping sending network {} configuration to device {}.", + device.name, network.name, device.name + ); + continue; + } // DEPRECATED(1.5): superseeded by location_mfa_mode let mfa_enabled = network.location_mfa_mode == LocationMfaMode::Internal; if let Some(wireguard_network_device) = wireguard_network_device { @@ -218,7 +231,7 @@ pub(crate) async fn build_device_config_response( info!( "User {}({}) device {}({}) automatically fetched the newest configuration.", - user.username, user.id, device.name, device.id, + user.username, user.id, device.name, device.id ); Ok(DeviceConfigResponse { @@ -238,7 +251,7 @@ pub(crate) async fn build_device_config_response( } /// Parses `DeviceInfo` returning client IP address and user agent. -pub(crate) fn parse_client_info(info: &Option) -> Result<(IpAddr, String), String> { +pub(crate) fn parse_client_ip_agent(info: &Option) -> Result<(IpAddr, String), String> { let Some(info) = info else { error!("Missing DeviceInfo in proxy request"); return Err("missing device info".to_string()); diff --git a/crates/defguard_core/src/handlers/mod.rs b/crates/defguard_core/src/handlers/mod.rs index c83fed9a13..93263db869 100644 --- a/crates/defguard_core/src/handlers/mod.rs +++ b/crates/defguard_core/src/handlers/mod.rs @@ -330,6 +330,7 @@ pub struct StartEnrollmentRequest { #[serde(default)] pub send_enrollment_notification: bool, pub email: Option, + pub token_expiration_time: Option, } #[derive(Deserialize, Serialize, ToSchema)] diff --git a/crates/defguard_core/src/handlers/user.rs b/crates/defguard_core/src/handlers/user.rs index d59920919c..128522ddd4 100644 --- a/crates/defguard_core/src/handlers/user.rs +++ b/crates/defguard_core/src/handlers/user.rs @@ -5,6 +5,7 @@ use axum::{ http::StatusCode, }; use defguard_mail::{Mail, templates}; +use humantime::parse_duration; use serde_json::json; use super::{ @@ -428,13 +429,24 @@ pub async fn start_enrollment( debug!("Create a new database transaction to save a new enrollment token into the database."); let mut transaction = appstate.pool.begin().await?; + // try to parse token expiration time if provided let config = server_config(); + let token_expiration_time_seconds = match data.token_expiration_time { + Some(time) => parse_duration(&time) + .map_err(|err| { + error!("Failed to parse token expiration time {time}: {err}"); + WebError::BadRequest("Failed to parse token expiration time".to_owned()) + })? + .as_secs(), + None => config.enrollment_token_timeout.as_secs(), + }; + let enrollment_token = user .start_enrollment( &mut transaction, &session.user, data.email, - config.enrollment_token_timeout.as_secs(), + token_expiration_time_seconds, config.enrollment_url.clone(), data.send_enrollment_notification, appstate.mail_tx.clone(), diff --git a/crates/defguard_core/src/handlers/wireguard.rs b/crates/defguard_core/src/handlers/wireguard.rs index 4aa617b107..9410134bdd 100644 --- a/crates/defguard_core/src/handlers/wireguard.rs +++ b/crates/defguard_core/src/handlers/wireguard.rs @@ -96,6 +96,29 @@ impl WireguardNetworkData { .map_or(Vec::new(), |ips| parse_network_address_list(ips)) } + pub(crate) fn parse_addresses(&self) -> Result, WebError> { + // first parse the addresses + let subnets = parse_address_list(self.address.as_ref()); + + // check if address list is not empty + if subnets.is_empty() { + return Err(WebError::BadRequest( + "Must provide at least one valid network address".to_owned(), + )); + } + + // check if any subnet has an invalid /0 netmask + for subnet in &subnets { + if subnet.prefix() == 0 { + return Err(WebError::BadRequest(format!( + "{subnet} is not a valid address" + ))); + } + } + + Ok(subnets) + } + pub(crate) async fn validate_location_mfa_mode<'e, E: sqlx::PgExecutor<'e>>( &self, executor: E, @@ -281,6 +304,8 @@ pub(crate) async fn modify_network( let mut network = find_network(network_id, &appstate.pool).await?; // store network before mods let before = network.clone(); + network.address = data.parse_addresses()?; + network.allowed_ips = data.parse_allowed_ips(); network.name = data.name; @@ -290,7 +315,6 @@ pub(crate) async fn modify_network( network.endpoint = data.endpoint; network.port = data.port; network.dns = data.dns; - network.address = parse_address_list(&data.address); network.keepalive_interval = data.keepalive_interval; network.peer_disconnect_threshold = data.peer_disconnect_threshold; network.acl_enabled = data.acl_enabled; diff --git a/crates/defguard_core/src/version.rs b/crates/defguard_core/src/version.rs index e61142618e..849c232337 100644 --- a/crates/defguard_core/src/version.rs +++ b/crates/defguard_core/src/version.rs @@ -9,7 +9,7 @@ use defguard_version::{ComponentInfo, Version, is_version_lower}; use serde::Serialize; use tonic::{Status, service::Interceptor}; -const MIN_PROXY_VERSION: Version = Version::new(1, 5, 0); +const MIN_PROXY_VERSION: Version = Version::new(1, 6, 0); pub const MIN_GATEWAY_VERSION: Version = Version::new(1, 5, 0); static OUTDATED_COMPONENT_LIFETIME: TimeDelta = TimeDelta::hours(1); diff --git a/crates/defguard_core/tests/integration/api/enrollment.rs b/crates/defguard_core/tests/integration/api/enrollment.rs index 5b42f7376c..5ca0c8eea5 100644 --- a/crates/defguard_core/tests/integration/api/enrollment.rs +++ b/crates/defguard_core/tests/integration/api/enrollment.rs @@ -1,3 +1,4 @@ +use chrono::Duration; use defguard_core::{ db::{User, models::enrollment::Token}, handlers::{AddUserData, Auth}, @@ -218,6 +219,94 @@ async fn test_request_enrollment(_: PgPoolOptions, options: PgConnectOptions) { assert!(token.used_at.is_none()); } +#[sqlx::test] +async fn test_enrollment_token_expiration_time(_: PgPoolOptions, options: PgConnectOptions) { + let pool = setup_pool(options).await; + + let (client, pool) = make_client_with_db(pool).await; + + let auth = Auth::new("admin", "pass123"); + let response = client.post("/api/v1/auth").json(&auth).send().await; + assert_eq!(response.status(), StatusCode::OK); + + // create user without password + let new_user = AddUserData { + username: "adumbledore".into(), + last_name: "Dumbledore".into(), + first_name: "Albus".into(), + email: "a.dumbledore@hogwart.edu.uk".into(), + phone: Some("1234".into()), + password: None, + }; + let response = client.post("/api/v1/user").json(&new_user).send().await; + assert_eq!(response.status(), StatusCode::CREATED); + + let user = User::find_by_username(&pool, &new_user.username) + .await + .unwrap() + .unwrap(); + + // verify enrollment token was not created + let tokens = Token::fetch_all(&pool).await.unwrap(); + assert_eq!(tokens.len(), 0); + + // request enrollment + let response = client + .post(format!("/api/v1/user/{}/start_enrollment", user.username)) + .json(&json!({"email": user.email, "send_enrollment_notification": false})) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + + // verify enrollment token was created with default expiration time (24h) + let tokens = Token::fetch_all(&pool).await.unwrap(); + assert_eq!(tokens.len(), 1); + let token = tokens.first().unwrap(); + assert_eq!(token.expires_at, token.created_at + Duration::hours(24)); + + // request enrollment with different expiration time + let response = client + .post(format!("/api/v1/user/{}/start_enrollment", user.username)) + .json(&json!({"email": user.email, "send_enrollment_notification": false, "token_expiration_time": "3d"})) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + + // verify enrollment token was created with default expiration time (24h) + let tokens = Token::fetch_all(&pool).await.unwrap(); + assert_eq!(tokens.len(), 1); + let token = tokens.first().unwrap(); + assert_eq!(token.expires_at, token.created_at + Duration::hours(72)); + + // request enrollment with different expiration time + let response = client + .post(format!("/api/v1/user/{}/start_enrollment", user.username)) + .json(&json!({"email": user.email, "send_enrollment_notification": false, "token_expiration_time": "1w"})) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + + // verify enrollment token was created with default expiration time (24h) + let tokens = Token::fetch_all(&pool).await.unwrap(); + assert_eq!(tokens.len(), 1); + let token = tokens.first().unwrap(); + assert_eq!(token.expires_at, token.created_at + Duration::days(7)); + + // request enrollment with different expiration time + let response = client + .post(format!("/api/v1/user/{}/start_enrollment", user.username)) + .json(&json!({"email": user.email, "send_enrollment_notification": false, "token_expiration_time": "2h"})) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + + // verify enrollment token was created with default expiration time (24h) + let tokens = Token::fetch_all(&pool).await.unwrap(); + assert_eq!(tokens.len(), 1); + let token = tokens.first().unwrap(); + assert_eq!(token.expires_at, token.created_at + Duration::hours(2)); +} + #[sqlx::test] async fn test_enrollment_pending_unset_for_desktop_client( _: PgPoolOptions, diff --git a/crates/defguard_core/tests/integration/api/openid_login.rs b/crates/defguard_core/tests/integration/api/openid_login.rs index c08353e428..923633fe1a 100644 --- a/crates/defguard_core/tests/integration/api/openid_login.rs +++ b/crates/defguard_core/tests/integration/api/openid_login.rs @@ -53,6 +53,7 @@ async fn test_openid_providers(_: PgPoolOptions, options: PgConnectOptions) { directory_sync_group_match: None, username_handling: OpenidUsernameHandling::PruneEmailDomain, jumpcloud_api_key: None, + prefetch_users: false, }; let response = client @@ -153,6 +154,7 @@ async fn test_openid_login(_: PgPoolOptions, options: PgConnectOptions) { directory_sync_group_match: None, username_handling: OpenidUsernameHandling::PruneEmailDomain, jumpcloud_api_key: None, + prefetch_users: false, }; let response = client .post("/api/v1/openid/provider") diff --git a/crates/defguard_core/tests/integration/api/wireguard.rs b/crates/defguard_core/tests/integration/api/wireguard.rs index 02d7a73f36..36c5ac4e2b 100644 --- a/crates/defguard_core/tests/integration/api/wireguard.rs +++ b/crates/defguard_core/tests/integration/api/wireguard.rs @@ -193,6 +193,7 @@ async fn test_location_mfa_mode_validation_create(_: PgPoolOptions, options: PgC directory_sync_group_match: None, username_handling: OpenidUsernameHandling::PruneEmailDomain, jumpcloud_api_key: None, + prefetch_users: false, }; let response = client @@ -288,6 +289,7 @@ async fn test_location_mfa_mode_validation_modify(_: PgPoolOptions, options: PgC directory_sync_group_match: None, username_handling: OpenidUsernameHandling::PruneEmailDomain, jumpcloud_api_key: None, + prefetch_users: false, }; let response = client @@ -838,3 +840,142 @@ async fn test_device_pubkey(_: PgPoolOptions, options: PgConnectOptions) { let devices: Vec> = response.json().await; assert_eq!(devices.len(), 1); } + +#[sqlx::test] +async fn test_network_size_validation(_: PgPoolOptions, options: PgConnectOptions) { + let pool = setup_pool(options).await; + + let (client, _client_state) = make_test_client(pool).await; + + let auth = Auth::new("admin", "pass123"); + let response = &client.post("/api/v1/auth").json(&auth).send().await; + assert_eq!(response.status(), StatusCode::OK); + + // create network + let network = json!({ + "name": "network", + "address": "10.1.1.1/24", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.1.1.0/24", + "dns": "1.1.1.1", + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + }); + let response = client.post("/api/v1/network").json(&network).send().await; + assert_eq!(response.status(), StatusCode::CREATED); + + // network details + let response = client.get("/api/v1/network/1").send().await; + assert_eq!(response.status(), StatusCode::OK); + let network_from_details: WireguardNetwork = response.json().await; + + // create devices + let device = json!({ + "name": "device1", + "wireguard_pubkey": "LQKsT6/3HWKuJmMulH63R8iK+5sI8FyYEL6WDIi6lQU=", + }); + let response = client + .post("/api/v1/device/admin") + .json(&device) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + let device = json!({ + "name": "device2", + "wireguard_pubkey": "ZqDlG4LQZRO9v57Sd27AHdtTLxegbMp5oVThjYrg21I=", + }); + let response = client + .post("/api/v1/device/admin") + .json(&device) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + let device = json!({ + "name": "device3", + "wireguard_pubkey": "o/8q3kmv5nnbrcb/7aceQWGE44a0yI707wObXRyyWGU=", + }); + let response = client + .post("/api/v1/device/admin") + .json(&device) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + + // try to add subnet with not enough IPs + let network = json!({ + "id": network_from_details.id, + "name": "network", + "address": "10.1.1.1/24,10.2.1.1/30", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.1.1.0/24", + "dns": "1.1.1.1", + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + }); + let response = client + .put(format!("/api/v1/network/{}", network_from_details.id)) + .json(&network) + .send() + .await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // try to add subnet with invalid mask + let network = json!({ + "id": network_from_details.id, + "name": "network", + "address": "10.2.0.1/24,10.1.1.1/0", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.1.1.0/24", + "dns": "1.1.1.1", + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + }); + let response = client + .put(format!("/api/v1/network/{}", network_from_details.id)) + .json(&network) + .send() + .await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // try to add no network + let network = json!({ + "id": network_from_details.id, + "name": "network", + "address": "", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.1.1.0/24", + "dns": "1.1.1.1", + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + }); + let response = client + .put(format!("/api/v1/network/{}", network_from_details.id)) + .json(&network) + .send() + .await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); +} diff --git a/crates/defguard_core/tests/integration/grpc/gateway.rs b/crates/defguard_core/tests/integration/grpc/gateway.rs index 3f35c2007c..d27fca1e72 100644 --- a/crates/defguard_core/tests/integration/grpc/gateway.rs +++ b/crates/defguard_core/tests/integration/grpc/gateway.rs @@ -558,3 +558,117 @@ async fn test_gateway_version_validation(_: PgPoolOptions, options: PgConnectOpt let status = response.err().unwrap(); assert_eq!(status.code(), Code::FailedPrecondition); } + +// https://github.com/DefGuard/defguard/issues/1671 +#[sqlx::test] +async fn test_device_pubkey_change(_: PgPoolOptions, options: PgConnectOptions) { + let pool = setup_pool(options).await; + let (mut test_server, mut gateway, test_location, test_user) = + setup_test_server(pool.clone()).await; + + // initial client map is empty + { + let client_map = test_server.get_client_map(); + assert!(client_map.is_empty()) + } + + // connect stats stream + let stats_tx = gateway.setup_stats_update_stream().await; + let mut update_id = 1; + + // add user device + let device_pubkey = "wYOt6ImBaQ3BEMQ3Xf5P5fTnbqwOvjcqYkkSBt+1xOg="; + let mut test_device = Device::new( + "test device".into(), + device_pubkey.into(), + test_user.id, + DeviceType::User, + None, + true, + ) + .save(&pool) + .await + .unwrap(); + + // send stats update for existing device + stats_tx + .send(StatsUpdate { + id: update_id, + payload: Some(Payload::PeerStats(PeerStats { + public_key: device_pubkey.into(), + endpoint: "1.2.3.4:1234".into(), + latest_handshake: Utc::now().timestamp() as u64, + ..Default::default() + })), + }) + .expect("failed to send stats update"); + + // wait for event to be emitted + sleep(Duration::from_millis(100)).await; + let grpc_event = test_server + .grpc_event_rx + .try_recv() + .expect("failed to receive gRPC event"); + assert_matches!( + grpc_event, + GrpcEvent::ClientConnected { + context: _, + location, + device + } if ((location.id == test_location.id) & (device.id == test_device.id)) + ); + + // change device pubkey + let new_device_pubkey = "TJG2T6rhndZtk06KnIIOlD6hhd7wpVkBss8sfyvMCAA="; + test_device.wireguard_pubkey = new_device_pubkey.to_owned(); + test_device.save(&pool).await.unwrap(); + + // send stats update with old pubkey + update_id += 1; + stats_tx + .send(StatsUpdate { + id: update_id, + payload: Some(Payload::PeerStats(PeerStats { + public_key: device_pubkey.into(), + endpoint: "1.2.3.4:1234".into(), + latest_handshake: Utc::now().timestamp() as u64, + ..Default::default() + })), + }) + .expect("failed to send stats update"); + + // no event should be emitted + sleep(Duration::from_millis(100)).await; + assert_err_eq!(test_server.grpc_event_rx.try_recv(), TryRecvError::Empty); + + // send stats update with new pubkey + update_id += 1; + stats_tx + .send(StatsUpdate { + id: update_id, + payload: Some(Payload::PeerStats(PeerStats { + public_key: new_device_pubkey.into(), + endpoint: "1.2.3.4:1234".into(), + latest_handshake: Utc::now().timestamp() as u64, + ..Default::default() + })), + }) + .expect("failed to send stats update"); + + // wait for event + // FIXME: ideally this should not be emitted; we'll fix it once we implement a more robust VPN session logic + sleep(Duration::from_millis(100)).await; + let grpc_event = test_server + .grpc_event_rx + .try_recv() + .expect("failed to receive gRPC event"); + + assert_matches!( + grpc_event, + GrpcEvent::ClientConnected { + context: _, + location, + device + } if ((location.id == test_location.id) & (device.id == test_device.id)) + ); +} diff --git a/deny.toml b/deny.toml index b40c3db21b..4bbfa288c1 100644 --- a/deny.toml +++ b/deny.toml @@ -72,12 +72,6 @@ feature-depth = 1 ignore = [ { id = "RUSTSEC-2023-0071", reason = "https://github.com/RustCrypto/RSA/issues/19" }, { id = "RUSTSEC-2024-0436", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0098", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0104", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0074", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0080", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0075", reason = "Unmaintained dependency of tera" }, - { id = "RUSTSEC-2025-0081", reason = "Unmaintained dependency of tera" }, ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. @@ -95,6 +89,7 @@ ignore = [ allow = [ "MIT", "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", "MPL-2.0", "BSD-3-Clause", "Unicode-3.0", diff --git a/docker-compose.e2e.yaml b/docker-compose.e2e.yaml index 7009e3ee17..c3fa1d0393 100644 --- a/docker-compose.e2e.yaml +++ b/docker-compose.e2e.yaml @@ -24,7 +24,7 @@ services: - db db: - image: postgres:17-alpine + image: public.ecr.aws/docker/library/postgres:17-alpine environment: POSTGRES_DB: defguard POSTGRES_USER: defguard diff --git a/flake.lock b/flake.lock index 6b2f9bdad5..3de9f99f55 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1758035966, - "narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=", + "lastModified": 1763283776, + "narHash": "sha256-Y7TDFPK4GlqrKrivOcsHG8xSGqQx3A6c+i7novT85Uk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b", + "rev": "50a96edd8d0db6cc8db57dab6bb6d6ee1f3dc49a", "type": "github" }, "original": { @@ -48,11 +48,11 @@ ] }, "locked": { - "lastModified": 1758204348, - "narHash": "sha256-jkz/NihbcEwy1EHDv/6g0HEqkpyIWCnQ1siGrhHEtFM=", + "lastModified": 1763347184, + "narHash": "sha256-6QH8hpCYJxifvyHEYg+Da0BotUn03BwLIvYo3JAxuqQ=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "067b3536e55341f579385ce8593cdcc9d022972b", + "rev": "08895cce80433978d5bfd668efa41c5e24578cbd", "type": "github" }, "original": { diff --git a/images/ami/core.pkr.hcl b/images/ami/core.pkr.hcl deleted file mode 100644 index 477cfea388..0000000000 --- a/images/ami/core.pkr.hcl +++ /dev/null @@ -1,62 +0,0 @@ -packer { - required_plugins { - amazon = { - version = ">= 1.2.8" - source = "github.com/hashicorp/amazon" - } - } -} - -variable "package_version" { - type = string -} - -variable "region" { - type = string - default = "eu-north-1" -} - -variable "instance_type" { - type = string - default = "t3.micro" -} - -source "amazon-ebs" "defguard-core" { - ami_name = "defguard-core-${var.package_version}-amd64" - instance_type = var.instance_type - region = var.region - source_ami_filter { - filters = { - name = "debian-13-amd64-*" - root-device-type = "ebs" - virtualization-type = "hvm" - } - most_recent = true - owners = ["136693071363"] - } - ssh_username = "admin" -} - -build { - name = "defguard-core" - sources = [ - "source.amazon-ebs.defguard-core" - ] - - provisioner "file" { - source = "defguard-${var.package_version}-x86_64-unknown-linux-gnu.deb" - destination = "/tmp/defguard-core.deb" - } - - provisioner "shell" { - script = "./images/ami/core.sh" - } - - provisioner "shell" { - inline = ["rm /home/admin/.ssh/authorized_keys"] - } - - provisioner "shell" { - inline = ["sudo rm /root/.ssh/authorized_keys"] - } -} diff --git a/images/ami/core.sh b/images/ami/core.sh deleted file mode 100644 index 1203c711ae..0000000000 --- a/images/ami/core.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -e - -echo "Updating apt repositories..." -sudo apt update - -echo "Installing Defguard package..." -sudo dpkg -i /tmp/defguard-core.deb - -echo "Cleaning up..." -sudo rm -f /tmp/defguard-core.deb - -echo "Defguard installation completed successfully." diff --git a/migrations/20251103105138_openid_directory_sync_prefetch_users.down.sql b/migrations/20251103105138_openid_directory_sync_prefetch_users.down.sql new file mode 100644 index 0000000000..84539f0ec4 --- /dev/null +++ b/migrations/20251103105138_openid_directory_sync_prefetch_users.down.sql @@ -0,0 +1 @@ +ALTER TABLE openidprovider DROP COLUMN prefetch_users; diff --git a/migrations/20251103105138_openid_directory_sync_prefetch_users.up.sql b/migrations/20251103105138_openid_directory_sync_prefetch_users.up.sql new file mode 100644 index 0000000000..5e93a274fd --- /dev/null +++ b/migrations/20251103105138_openid_directory_sync_prefetch_users.up.sql @@ -0,0 +1 @@ +ALTER TABLE openidprovider ADD COLUMN prefetch_users BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/proto b/proto index fee706013b..96249ebde0 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit fee706013b3bb5452c3c4dbf35bd973d0637ff25 +Subproject commit 96249ebde0556f4ae8c47eebc6015efb04ed0104 diff --git a/web/package.json b/web/package.json index 72f2c3acba..d3d9ddbd62 100644 --- a/web/package.json +++ b/web/package.json @@ -50,17 +50,17 @@ "@react-rxjs/core": "^0.10.8", "@stablelib/base64": "^2.0.1", "@stablelib/x25519": "^2.0.1", - "@tanstack/query-core": "^5.90.2", - "@tanstack/react-query": "^5.90.2", + "@tanstack/query-core": "^5.90.9", + "@tanstack/react-query": "^5.90.9", "@tanstack/react-virtual": "3.13.12", "@tanstack/virtual-core": "3.13.12", "@use-gesture/react": "^10.3.1", - "axios": "^1.12.2", + "axios": "^1.13.2", "byte-size": "^9.0.1", "classnames": "^2.5.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", - "dayjs": "^1.11.18", + "dayjs": "^1.11.19", "deepmerge-ts": "^7.1.5", "detect-browser": "^5.3.0", "dice-coefficient": "^2.1.1", @@ -70,7 +70,7 @@ "fuse.js": "^7.1.0", "get-text-width": "^1.0.3", "hex-rgb": "^5.0.0", - "html-react-parser": "^5.2.6", + "html-react-parser": "^5.2.8", "humanize-duration": "^3.33.1", "ipaddr.js": "^2.2.0", "itertools": "^2.5.0", @@ -78,28 +78,28 @@ "lodash-es": "^4.17.21", "merge-refs": "^2.0.0", "millify": "^6.1.0", - "motion": "^12.23.22", + "motion": "^12.23.24", "numbro": "^2.5.0", "qrcode": "^1.5.4", "qs": "^6.14.0", "radash": "^12.1.1", - "react": "^19.1.1", + "react": "^19.2.0", "react-click-away-listener": "^2.4.0", - "react-datepicker": "^8.7.0", - "react-dom": "^19.1.1", - "react-hook-form": "^7.63.0", + "react-datepicker": "^8.9.0", + "react-dom": "^19.2.0", + "react-hook-form": "^7.66.0", "react-idle-timer": "^5.7.2", "react-intersection-observer": "^9.16.0", - "react-is": "^19.1.1", + "react-is": "^19.2.0", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", "react-qr-code": "^2.0.18", "react-resize-detector": "^12.3.0", - "react-router": "^6.30.1", - "react-router-dom": "^6.30.1", + "react-router": "^6.30.2", + "react-router-dom": "^6.30.2", "react-tracked": "^2.0.1", "react-virtualized-auto-sizer": "^1.0.26", - "recharts": "^3.2.1", + "recharts": "^3.4.1", "rehype-external-links": "^3.0.0", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", @@ -107,12 +107,12 @@ "scheduler": "^0.26.0", "text-case": "^1.2.9", "typesafe-i18n": "^5.26.2", - "use-breakpoint": "^4.0.6", + "use-breakpoint": "^4.0.10", "zod": "^3.25.76", "zustand": "^5.0.8" }, "devDependencies": { - "@babel/core": "^7.28.4", + "@babel/core": "^7.28.5", "@biomejs/biome": "2.2.2", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", @@ -122,24 +122,24 @@ "@types/file-saver": "^2.0.7", "@types/humanize-duration": "^3.27.4", "@types/lodash-es": "^4.17.12", - "@types/node": "^24.5.2", + "@types/node": "^24.10.1", "@types/qs": "^6.14.0", - "@types/react": "^19.1.13", - "@types/react-dom": "^19.1.9", + "@types/react": "^19.2.4", + "@types/react-dom": "^19.2.3", "@types/react-router-dom": "^5.3.3", - "@vitejs/plugin-react-swc": "^4.1.0", - "autoprefixer": "^10.4.21", + "@vitejs/plugin-react-swc": "^4.2.2", + "autoprefixer": "^10.4.22", "concurrently": "^9.2.1", - "dotenv": "^17.2.2", - "esbuild": "^0.25.10", - "globals": "^16.4.0", + "dotenv": "^17.2.3", + "esbuild": "^0.25.12", + "globals": "^16.5.0", "postcss": "^8.5.6", "prettier": "^3.6.2", "sass": "~1.70.0", "standard-version": "^9.5.0", "type-fest": "^4.41.0", - "typescript": "~5.9.2", - "vite": "^7.1.7", + "typescript": "~5.9.3", + "vite": "^7.2.2", "vite-plugin-package-version": "^1.1.0" } } diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index a8738b8914..af6ae57457 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -10,19 +10,19 @@ importers: dependencies: '@floating-ui/react': specifier: ^0.27.16 - version: 0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@github/webauthn-json': specifier: ^2.1.1 version: 2.1.1 '@hookform/resolvers': specifier: ^5.2.2 - version: 5.2.2(react-hook-form@7.63.0(react@19.1.1)) + version: 5.2.2(react-hook-form@7.66.0(react@19.2.0)) '@react-hook/resize-observer': specifier: ^2.0.2 - version: 2.0.2(react@19.1.1) + version: 2.0.2(react@19.2.0) '@react-rxjs/core': specifier: ^0.10.8 - version: 0.10.8(react@19.1.1)(rxjs@7.8.2) + version: 0.10.8(react@19.2.0)(rxjs@7.8.2) '@stablelib/base64': specifier: ^2.0.1 version: 2.0.1 @@ -30,23 +30,23 @@ importers: specifier: ^2.0.1 version: 2.0.1 '@tanstack/query-core': - specifier: ^5.90.2 - version: 5.90.2 + specifier: ^5.90.9 + version: 5.90.9 '@tanstack/react-query': - specifier: ^5.90.2 - version: 5.90.2(react@19.1.1) + specifier: ^5.90.9 + version: 5.90.9(react@19.2.0) '@tanstack/react-virtual': specifier: 3.13.12 - version: 3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 3.13.12(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/virtual-core': specifier: 3.13.12 version: 3.13.12 '@use-gesture/react': specifier: ^10.3.1 - version: 10.3.1(react@19.1.1) + version: 10.3.1(react@19.2.0) axios: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.13.2 + version: 1.13.2 byte-size: specifier: ^9.0.1 version: 9.0.1 @@ -60,8 +60,8 @@ importers: specifier: ^4.1.0 version: 4.1.0 dayjs: - specifier: ^1.11.18 - version: 1.11.18 + specifier: ^1.11.19 + version: 1.11.19 deepmerge-ts: specifier: ^7.1.5 version: 7.1.5 @@ -90,8 +90,8 @@ importers: specifier: ^5.0.0 version: 5.0.0 html-react-parser: - specifier: ^5.2.6 - version: 5.2.6(@types/react@19.1.13)(react@19.1.1) + specifier: ^5.2.8 + version: 5.2.8(@types/react@19.2.4)(react@19.2.0) humanize-duration: specifier: ^3.33.1 version: 3.33.1 @@ -109,13 +109,13 @@ importers: version: 4.17.21 merge-refs: specifier: ^2.0.0 - version: 2.0.0(@types/react@19.1.13) + version: 2.0.0(@types/react@19.2.4) millify: specifier: ^6.1.0 version: 6.1.0 motion: - specifier: ^12.23.22 - version: 12.23.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: ^12.23.24 + version: 12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) numbro: specifier: ^2.5.0 version: 2.5.0 @@ -129,56 +129,56 @@ importers: specifier: ^12.1.1 version: 12.1.1 react: - specifier: ^19.1.1 - version: 19.1.1 + specifier: ^19.2.0 + version: 19.2.0 react-click-away-listener: specifier: ^2.4.0 - version: 2.4.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 2.4.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-datepicker: - specifier: ^8.7.0 - version: 8.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: ^8.9.0 + version: 8.9.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: - specifier: ^19.1.1 - version: 19.1.1(react@19.1.1) + specifier: ^19.2.0 + version: 19.2.0(react@19.2.0) react-hook-form: - specifier: ^7.63.0 - version: 7.63.0(react@19.1.1) + specifier: ^7.66.0 + version: 7.66.0(react@19.2.0) react-idle-timer: specifier: ^5.7.2 - version: 5.7.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 5.7.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-intersection-observer: specifier: ^9.16.0 - version: 9.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 9.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-is: - specifier: ^19.1.1 - version: 19.1.1 + specifier: ^19.2.0 + version: 19.2.0 react-loading-skeleton: specifier: ^3.5.0 - version: 3.5.0(react@19.1.1) + version: 3.5.0(react@19.2.0) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.1.13)(react@19.1.1) + version: 10.1.0(@types/react@19.2.4)(react@19.2.0) react-qr-code: specifier: ^2.0.18 - version: 2.0.18(react@19.1.1) + version: 2.0.18(react@19.2.0) react-resize-detector: specifier: ^12.3.0 - version: 12.3.0(react@19.1.1) + version: 12.3.0(react@19.2.0) react-router: - specifier: ^6.30.1 - version: 6.30.1(react@19.1.1) + specifier: ^6.30.2 + version: 6.30.2(react@19.2.0) react-router-dom: - specifier: ^6.30.1 - version: 6.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: ^6.30.2 + version: 6.30.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-tracked: specifier: ^2.0.1 - version: 2.0.1(react@19.1.1)(scheduler@0.26.0) + version: 2.0.1(react@19.2.0)(scheduler@0.26.0) react-virtualized-auto-sizer: specifier: ^1.0.26 - version: 1.0.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 1.0.26(react-dom@19.2.0(react@19.2.0))(react@19.2.0) recharts: - specifier: ^3.2.1 - version: 3.2.1(@types/react@19.1.13)(react-dom@19.1.1(react@19.1.1))(react-is@19.1.1)(react@19.1.1)(redux@5.0.1) + specifier: ^3.4.1 + version: 3.4.1(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react-is@19.2.0)(react@19.2.0)(redux@5.0.1) rehype-external-links: specifier: ^3.0.0 version: 3.0.0 @@ -199,20 +199,20 @@ importers: version: 1.2.9 typesafe-i18n: specifier: ^5.26.2 - version: 5.26.2(typescript@5.9.2) + version: 5.26.2(typescript@5.9.3) use-breakpoint: - specifier: ^4.0.6 - version: 4.0.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: ^4.0.10 + version: 4.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0) zod: specifier: ^3.25.76 version: 3.25.76 zustand: specifier: ^5.0.8 - version: 5.0.8(@types/react@19.1.13)(immer@10.1.3)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) + version: 5.0.8(@types/react@19.2.4)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) devDependencies: '@babel/core': - specifier: ^7.28.4 - version: 7.28.4 + specifier: ^7.28.5 + version: 7.28.5 '@biomejs/biome': specifier: 2.2.2 version: 2.2.2 @@ -224,10 +224,10 @@ importers: version: 3.0.4 '@hookform/devtools': specifier: ^4.4.0 - version: 4.4.0(@types/react@19.1.13)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 4.4.0(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-query-devtools': specifier: ^5.90.2 - version: 5.90.2(@tanstack/react-query@5.90.2(react@19.1.1))(react@19.1.1) + version: 5.90.2(@tanstack/react-query@5.90.9(react@19.2.0))(react@19.2.0) '@types/byte-size': specifier: ^8.1.2 version: 8.1.2 @@ -241,38 +241,38 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/node': - specifier: ^24.5.2 - version: 24.5.2 + specifier: ^24.10.1 + version: 24.10.1 '@types/qs': specifier: ^6.14.0 version: 6.14.0 '@types/react': - specifier: ^19.1.13 - version: 19.1.13 + specifier: ^19.2.4 + version: 19.2.4 '@types/react-dom': - specifier: ^19.1.9 - version: 19.1.9(@types/react@19.1.13) + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.4) '@types/react-router-dom': specifier: ^5.3.3 version: 5.3.3 '@vitejs/plugin-react-swc': - specifier: ^4.1.0 - version: 4.1.0(vite@7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)) + specifier: ^4.2.2 + version: 4.2.2(vite@7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)) autoprefixer: - specifier: ^10.4.21 - version: 10.4.21(postcss@8.5.6) + specifier: ^10.4.22 + version: 10.4.22(postcss@8.5.6) concurrently: specifier: ^9.2.1 version: 9.2.1 dotenv: - specifier: ^17.2.2 - version: 17.2.2 + specifier: ^17.2.3 + version: 17.2.3 esbuild: - specifier: ^0.25.10 - version: 0.25.10 + specifier: ^0.25.12 + version: 0.25.12 globals: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^16.5.0 + version: 16.5.0 postcss: specifier: ^8.5.6 version: 8.5.6 @@ -289,14 +289,14 @@ importers: specifier: ^4.41.0 version: 4.41.0 typescript: - specifier: ~5.9.2 - version: 5.9.2 + specifier: ~5.9.3 + version: 5.9.3 vite: - specifier: ^7.1.7 - version: 7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) + specifier: ^7.2.2 + version: 7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) vite-plugin-package-version: specifier: ^1.1.0 - version: 1.1.0(vite@7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)) + version: 1.1.0(vite@7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)) packages: @@ -304,16 +304,16 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.4': - resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.4': - resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.3': - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -338,8 +338,8 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': @@ -350,8 +350,8 @@ packages: resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.4': - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -363,12 +363,12 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': - resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} '@biomejs/biome@2.2.2': @@ -488,158 +488,158 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.25.10': - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.10': - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.10': - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.10': - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.10': - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.10': - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.10': - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.10': - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.10': - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.10': - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.10': - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.10': - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.10': - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.10': - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.10': - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.10': - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.10': - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.10': - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.10': - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.10': - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.10': - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.10': - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.10': - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.10': - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.10': - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.10': - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -725,8 +725,8 @@ packages: react: '>=16.8.0' rxjs: '>=7' - '@reduxjs/toolkit@2.9.0': - resolution: {integrity: sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog==} + '@reduxjs/toolkit@2.10.1': + resolution: {integrity: sha512-/U17EXQ9Do9Yx4DlNGU6eVNfZvFJfYpUtRRdLf19PbPjdWBxNlxGZXywQZ1p1Nz8nMkWplTI7iD/23m07nolDA==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18 || ^19 react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 @@ -736,120 +736,120 @@ packages: react-redux: optional: true - '@remix-run/router@1.23.0': - resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==} + '@remix-run/router@1.23.1': + resolution: {integrity: sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==} engines: {node: '>=14.0.0'} - '@rolldown/pluginutils@1.0.0-beta.35': - resolution: {integrity: sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==} + '@rolldown/pluginutils@1.0.0-beta.47': + resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==} - '@rollup/rollup-android-arm-eabi@4.52.2': - resolution: {integrity: sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==} + '@rollup/rollup-android-arm-eabi@4.53.2': + resolution: {integrity: sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.52.2': - resolution: {integrity: sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==} + '@rollup/rollup-android-arm64@4.53.2': + resolution: {integrity: sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.52.2': - resolution: {integrity: sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==} + '@rollup/rollup-darwin-arm64@4.53.2': + resolution: {integrity: sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.52.2': - resolution: {integrity: sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==} + '@rollup/rollup-darwin-x64@4.53.2': + resolution: {integrity: sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.52.2': - resolution: {integrity: sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==} + '@rollup/rollup-freebsd-arm64@4.53.2': + resolution: {integrity: sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.52.2': - resolution: {integrity: sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==} + '@rollup/rollup-freebsd-x64@4.53.2': + resolution: {integrity: sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.52.2': - resolution: {integrity: sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': + resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.52.2': - resolution: {integrity: sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==} + '@rollup/rollup-linux-arm-musleabihf@4.53.2': + resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.52.2': - resolution: {integrity: sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==} + '@rollup/rollup-linux-arm64-gnu@4.53.2': + resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.52.2': - resolution: {integrity: sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==} + '@rollup/rollup-linux-arm64-musl@4.53.2': + resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.52.2': - resolution: {integrity: sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==} + '@rollup/rollup-linux-loong64-gnu@4.53.2': + resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.52.2': - resolution: {integrity: sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==} + '@rollup/rollup-linux-ppc64-gnu@4.53.2': + resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.52.2': - resolution: {integrity: sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==} + '@rollup/rollup-linux-riscv64-gnu@4.53.2': + resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.52.2': - resolution: {integrity: sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==} + '@rollup/rollup-linux-riscv64-musl@4.53.2': + resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.52.2': - resolution: {integrity: sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==} + '@rollup/rollup-linux-s390x-gnu@4.53.2': + resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.52.2': - resolution: {integrity: sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==} + '@rollup/rollup-linux-x64-gnu@4.53.2': + resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.52.2': - resolution: {integrity: sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==} + '@rollup/rollup-linux-x64-musl@4.53.2': + resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.52.2': - resolution: {integrity: sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==} + '@rollup/rollup-openharmony-arm64@4.53.2': + resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.52.2': - resolution: {integrity: sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==} + '@rollup/rollup-win32-arm64-msvc@4.53.2': + resolution: {integrity: sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.52.2': - resolution: {integrity: sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==} + '@rollup/rollup-win32-ia32-msvc@4.53.2': + resolution: {integrity: sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.52.2': - resolution: {integrity: sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==} + '@rollup/rollup-win32-x64-gnu@4.53.2': + resolution: {integrity: sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.52.2': - resolution: {integrity: sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==} + '@rollup/rollup-win32-x64-msvc@4.53.2': + resolution: {integrity: sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==} cpu: [x64] os: [win32] @@ -888,68 +888,68 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@swc/core-darwin-arm64@1.13.19': - resolution: {integrity: sha512-NxDyte9tCJSJ8+R62WDtqwg8eI57lubD52sHyGOfezpJBOPr36bUSGGLyO3Vod9zTGlOu2CpkuzA/2iVw92u1g==} + '@swc/core-darwin-arm64@1.15.2': + resolution: {integrity: sha512-Ghyz4RJv4zyXzrUC1B2MLQBbppIB5c4jMZJybX2ebdEQAvryEKp3gq1kBksCNsatKGmEgXul88SETU19sMWcrw==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.13.19': - resolution: {integrity: sha512-+w5DYrJndSygFFRDcuPYmx5BljD6oYnAohZ15K1L6SfORHp/BTSIbgSFRKPoyhjuIkDiq3W0um8RoMTOBAcQjQ==} + '@swc/core-darwin-x64@1.15.2': + resolution: {integrity: sha512-7n/PGJOcL2QoptzL42L5xFFfXY5rFxLHnuz1foU+4ruUTG8x2IebGhtwVTpaDN8ShEv2UZObBlT1rrXTba15Zw==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.13.19': - resolution: {integrity: sha512-7LlfgpdwwYq2q7himNkAAFo4q6jysMLFNoBH6GRP7WL29NcSsl5mPMJjmYZymK+sYq/9MTVieDTQvChzYDsapw==} + '@swc/core-linux-arm-gnueabihf@1.15.2': + resolution: {integrity: sha512-ZUQVCfRJ9wimuxkStRSlLwqX4TEDmv6/J+E6FicGkQ6ssLMWoKDy0cAo93HiWt/TWEee5vFhFaSQYzCuBEGO6A==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.13.19': - resolution: {integrity: sha512-ml3I6Lm2marAQ3UC/TS9t/yILBh/eDSVHAdPpikp652xouWAVW1znUeV6bBSxe1sSZIenv+p55ubKAWq/u84sQ==} + '@swc/core-linux-arm64-gnu@1.15.2': + resolution: {integrity: sha512-GZh3pYBmfnpQ+JIg+TqLuz+pM+Mjsk5VOzi8nwKn/m+GvQBsxD5ectRtxuWUxMGNG8h0lMy4SnHRqdK3/iJl7A==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.13.19': - resolution: {integrity: sha512-M/otFc3/rWWkbF6VgbOXVzUKVoE7MFcphTaStxJp4bwb7oP5slYlxMZN51Dk/OTOfvCDo9pTAFDKNyixbkXMDQ==} + '@swc/core-linux-arm64-musl@1.15.2': + resolution: {integrity: sha512-5av6VYZZeneiYIodwzGMlnyVakpuYZryGzFIbgu1XP8wVylZxduEzup4eP8atiMDFmIm+s4wn8GySJmYqeJC0A==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.13.19': - resolution: {integrity: sha512-NoMUKaOJEdouU4tKF88ggdDHFiRRING+gYLxDqnTfm+sUXaizB5OGBRzvSVDYSXQb1SuUuChnXFPFzwTWbt3ZQ==} + '@swc/core-linux-x64-gnu@1.15.2': + resolution: {integrity: sha512-1nO/UfdCLuT/uE/7oB3EZgTeZDCIa6nL72cFEpdegnqpJVNDI6Qb8U4g/4lfVPkmHq2lvxQ0L+n+JdgaZLhrRA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.13.19': - resolution: {integrity: sha512-r6krlZwyu8SBaw24QuS1lau2I9q8M+eJV6ITz0rpb6P1Bx0elf9ii5Bhh8ddmIqXXH8kOGSjC/dwcdHbZqAhgw==} + '@swc/core-linux-x64-musl@1.15.2': + resolution: {integrity: sha512-Ksfrb0Tx310kr+TLiUOvB/I80lyZ3lSOp6cM18zmNRT/92NB4mW8oX2Jo7K4eVEI2JWyaQUAFubDSha2Q+439A==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.13.19': - resolution: {integrity: sha512-awcZSIuxyVn0Dw28VjMvgk1qiDJ6CeQwHkZNUjg2UxVlq23zE01NMMp+zkoGFypmLG9gaGmJSzuoqvk/WCQ5tw==} + '@swc/core-win32-arm64-msvc@1.15.2': + resolution: {integrity: sha512-IzUb5RlMUY0r1A9IuJrQ7Tbts1wWb73/zXVXT8VhewbHGoNlBKE0qUhKMED6Tv4wDF+pmbtUJmKXDthytAvLmg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.13.19': - resolution: {integrity: sha512-H5d+KO7ISoLNgYvTbOcCQjJZNM3R7yaYlrMAF13lUr6GSiOUX+92xtM31B+HvzAWI7HtvVe74d29aC1b1TpXFA==} + '@swc/core-win32-ia32-msvc@1.15.2': + resolution: {integrity: sha512-kCATEzuY2LP9AlbU2uScjcVhgnCAkRdu62vbce17Ro5kxEHxYWcugkveyBRS3AqZGtwAKYbMAuNloer9LS/hpw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.13.19': - resolution: {integrity: sha512-qNoyCpXvv2O3JqXKanRIeoMn03Fho/As+N4Fhe7u0FsYh4VYqGQah4DGDzEP/yjl4Gx1IElhqLGDhCCGMwWaDw==} + '@swc/core-win32-x64-msvc@1.15.2': + resolution: {integrity: sha512-iJaHeYCF4jTn7OEKSa3KRiuVFIVYts8jYjNmCdyz1u5g8HRyTDISD76r8+ljEOgm36oviRQvcXaw6LFp1m0yyA==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.13.19': - resolution: {integrity: sha512-V1r4wFdjaZIUIZZrV2Mb/prEeu03xvSm6oatPxsvnXKF9lNh5Jtk9QvUdiVfD9rrvi7bXrAVhg9Wpbmv/2Fl1g==} + '@swc/core@1.15.2': + resolution: {integrity: sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -963,8 +963,8 @@ packages: '@swc/types@0.1.25': resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} - '@tanstack/query-core@5.90.2': - resolution: {integrity: sha512-k/TcR3YalnzibscALLwxeiLUub6jN5EDLwKDiO7q5f4ICEoptJ+n9+7vcEFy5/x/i6Q+Lb/tXrsKCggf5uQJXQ==} + '@tanstack/query-core@5.90.9': + resolution: {integrity: sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw==} '@tanstack/query-devtools@5.90.1': resolution: {integrity: sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ==} @@ -975,8 +975,8 @@ packages: '@tanstack/react-query': ^5.90.2 react: ^18 || ^19 - '@tanstack/react-query@5.90.2': - resolution: {integrity: sha512-CLABiR+h5PYfOWr/z+vWFt5VsOA2ekQeRQBFSKlcoW6Ndx/f8rfyVmq4LbgOM4GG2qtxAxjLYLOpCNTYm4uKzw==} + '@tanstack/react-query@5.90.9': + resolution: {integrity: sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==} peerDependencies: react: ^18 || ^19 @@ -1055,8 +1055,8 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@24.5.2': - resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==} + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1067,10 +1067,10 @@ packages: '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} - '@types/react-dom@19.1.9': - resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: - '@types/react': ^19.0.0 + '@types/react': ^19.2.0 '@types/react-router-dom@5.3.3': resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} @@ -1078,8 +1078,8 @@ packages: '@types/react-router@5.1.20': resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} - '@types/react@19.1.13': - resolution: {integrity: sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==} + '@types/react@19.2.4': + resolution: {integrity: sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1101,8 +1101,8 @@ packages: peerDependencies: react: '>= 16.8.0' - '@vitejs/plugin-react-swc@4.1.0': - resolution: {integrity: sha512-Ff690TUck0Anlh7wdIcnsVMhofeEVgm44Y4OYdeeEEPSKyZHzDI9gfVBvySEhDfXtBp8tLCbfsVKPWEMEjq8/g==} + '@vitejs/plugin-react-swc@4.2.2': + resolution: {integrity: sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4 || ^5 || ^6 || ^7 @@ -1145,15 +1145,15 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - autoprefixer@10.4.21: - resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + autoprefixer@10.4.22: + resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 - axios@1.12.2: - resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} @@ -1165,8 +1165,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.7: - resolution: {integrity: sha512-bxxN2M3a4d1CRoQC//IqsR5XrLh0IJ8TCv2x6Y9N0nckNz/rTjZB3//GGscZziZOxmjP55rzxg/ze7usFI9FqQ==} + baseline-browser-mapping@2.8.28: + resolution: {integrity: sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==} hasBin: true bignumber.js@9.3.1: @@ -1183,8 +1183,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.26.2: - resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==} + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1220,8 +1220,8 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - caniuse-lite@1.0.30001745: - resolution: {integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==} + caniuse-lite@1.0.30001754: + resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1388,8 +1388,8 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.0: + resolution: {integrity: sha512-si++xzRAY9iPp60roQiFta7OFbhrgvcthrhlNAGeQptSY25uJjkfUV8OArC3KLocB8JT8ohz+qgxWCmz8RhjIg==} d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} @@ -1445,8 +1445,8 @@ packages: dateformat@3.0.3: resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} - dayjs@1.11.18: - resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -1521,8 +1521,8 @@ packages: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} - dotenv@17.2.2: - resolution: {integrity: sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==} + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} dotgitignore@2.1.0: @@ -1533,8 +1533,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.224: - resolution: {integrity: sha512-kWAoUu/bwzvnhpdZSIc6KUyvkI1rbRXMT0Eq8pKReyOyaPZcctMli+EgvcN1PAvwVc7Tdo4Fxi2PsLNDU05mdg==} + electron-to-chromium@1.5.252: + resolution: {integrity: sha512-53uTpjtRgS7gjIxZ4qCgFdNO2q+wJt/Z8+xAvxbCqXPJrY6h7ighUkadQmNMXH96crtpa6gPFNP7BF4UBGDuaA==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1566,11 +1566,11 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-toolkit@1.39.10: - resolution: {integrity: sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==} + es-toolkit@1.41.0: + resolution: {integrity: sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA==} - esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -1654,11 +1654,11 @@ packages: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} - fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - framer-motion@12.23.22: - resolution: {integrity: sha512-ZgGvdxXCw55ZYvhoZChTlG6pUuehecgvEAJz0BHoC5pQKW1EC5xf1Mul1ej5+ai+pVY0pylyFfdl45qnM1/GsA==} + framer-motion@12.23.24: + resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -1728,8 +1728,8 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - globals@16.4.0: - resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} gopd@1.2.0: @@ -1812,8 +1812,8 @@ packages: html-dom-parser@5.1.1: resolution: {integrity: sha512-+o4Y4Z0CLuyemeccvGN4bAO20aauB2N9tFEAep5x4OW34kV4PTarBHm6RL02afYt2BMKcr0D2Agep8S3nJPIBg==} - html-react-parser@5.2.6: - resolution: {integrity: sha512-qcpPWLaSvqXi+TndiHbCa+z8qt0tVzjMwFGFBAa41ggC+ZA5BHaMIeMJla9g3VSp4SmiZb9qyQbmbpHYpIfPOg==} + html-react-parser@5.2.8: + resolution: {integrity: sha512-09WaI81tbpwhXWeMe1m9VptZVJUcigo0l59zVt+2HUIQT7+baU38/oNhllj6MKhOuGXqh0nrlwOgxbxbm6xXHw==} peerDependencies: '@types/react': 0.14 || 15 || 16 || 17 || 18 || 19 react: 0.14 || 15 || 16 || 17 || 18 || 19 @@ -1833,8 +1833,8 @@ packages: humanize-duration@3.33.1: resolution: {integrity: sha512-hwzSCymnRdFx9YdRkQQ0OYequXiVAV6ZGQA2uzocwB0F4309Ke6pO8dg0P8LHhRQJyVjGteRTAA/zNfEcpXn8A==} - immer@10.1.3: - resolution: {integrity: sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==} + immer@10.2.0: + resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} immutable@4.3.7: resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} @@ -1853,8 +1853,8 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - inline-style-parser@0.2.4: - resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + inline-style-parser@0.2.6: + resolution: {integrity: sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg==} internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} @@ -2158,14 +2158,14 @@ packages: resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} engines: {node: '>=0.10.0'} - motion-dom@12.23.21: - resolution: {integrity: sha512-5xDXx/AbhrfgsQmSE7YESMn4Dpo6x5/DTZ4Iyy4xqDvVHWvFVoV+V2Ri2S/ksx+D40wrZ7gPYiMWshkdoqNgNQ==} + motion-dom@12.23.23: + resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} motion-utils@12.23.6: resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} - motion@12.23.22: - resolution: {integrity: sha512-iSq6X9vLHbeYwmHvhK//+U74ROaPnZmBuy60XZzqNl0QtZkWfoZyMDHYnpKuWFv0sNMqHgED8aCXk94LCoQPGg==} + motion@12.23.24: + resolution: {integrity: sha512-Rc5E7oe2YZ72N//S3QXGzbnXgqNrTESv8KKxABR20q2FLch9gHLo0JLyYo2hZ238bZ9Gx6cWhj9VO0IgwbMjCw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -2192,8 +2192,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - node-releases@2.0.21: - resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -2381,19 +2381,19 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-datepicker@8.7.0: - resolution: {integrity: sha512-r5OJbiLWc3YiVNy69Kau07/aVgVGsFVMA6+nlqCV7vyQ8q0FUOnJ+wAI4CgVxHejG3i5djAEiebrF8/Eip4rIw==} + react-datepicker@8.9.0: + resolution: {integrity: sha512-yoRsGxjqVRjk8iUBssrW9jcinTeyP9mAfTpuzdKvlESOUjdrY0sfDTzIZWJAn38jvNcxW1dnDmW1CinjiFdxYQ==} peerDependencies: react: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom@19.1.1: - resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: - react: ^19.1.1 + react: ^19.2.0 - react-hook-form@7.63.0: - resolution: {integrity: sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==} + react-hook-form@7.66.0: + resolution: {integrity: sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -2416,8 +2416,8 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-is@19.1.1: - resolution: {integrity: sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==} + react-is@19.2.0: + resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==} react-loading-skeleton@3.5.0: resolution: {integrity: sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==} @@ -2455,15 +2455,15 @@ packages: peerDependencies: react: ^18.0.0 || ^19.0.0 - react-router-dom@6.30.1: - resolution: {integrity: sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==} + react-router-dom@6.30.2: + resolution: {integrity: sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.30.1: - resolution: {integrity: sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==} + react-router@6.30.2: + resolution: {integrity: sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -2485,8 +2485,8 @@ packages: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 - react@19.1.1: - resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} read-pkg-up@3.0.0: @@ -2516,8 +2516,8 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - recharts@3.2.1: - resolution: {integrity: sha512-0JKwHRiFZdmLq/6nmilxEZl3pqb4T+aKkOkOi/ZISRZwfBhVMgInxzlYU9D4KnCH3KINScLy68m/OvMXoYGZUw==} + recharts@3.4.1: + resolution: {integrity: sha512-35kYg6JoOgwq8sE4rhYkVWwa6aAIgOtT+Ob0gitnShjwUwZmhrmy7Jco/5kJNF4PnLXgt9Hwq+geEMS+WrjU1g==} engines: {node: '>=18'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2565,13 +2565,13 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} hasBin: true - rollup@4.52.2: - resolution: {integrity: sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==} + rollup@4.53.2: + resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2592,6 +2592,9 @@ packages: scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -2600,8 +2603,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -2698,11 +2701,11 @@ packages: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} - style-to-js@1.1.17: - resolution: {integrity: sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==} + style-to-js@1.1.19: + resolution: {integrity: sha512-Ev+SgeqiNGT1ufsXyVC5RrJRXdrkRJ1Gol9Qw7Pb72YCKJXrBvP0ckZhBeVSrw2m06DJpei2528uIpjMb4TsoQ==} - style-to-object@1.0.9: - resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==} + style-to-object@1.0.12: + resolution: {integrity: sha512-ddJqYnoT4t97QvN2C95bCgt+m7AAgXjVnkk/jxAfmp7EAB8nnqqZYEbMd3em7/vEomDb2LAQKAy1RFfv41mdNw==} stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} @@ -2723,8 +2726,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tabbable@6.3.0: + resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==} terser@5.37.0: resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==} @@ -2860,8 +2863,8 @@ packages: peerDependencies: typescript: '>=3.5.1' - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -2870,14 +2873,14 @@ packages: engines: {node: '>=0.8.0'} hasBin: true - undici-types@7.12.0: - resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - unist-util-is@6.0.0: - resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} @@ -2885,20 +2888,20 @@ packages: unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - unist-util-visit-parents@6.0.1: - resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - use-breakpoint@4.0.6: - resolution: {integrity: sha512-1s7vUjf36eeZYTgY1KkmPNXrTbKJVRA9cjBFQdYjK8+pDr0qJgH6/cuX5qQ2zcfkqxN5LieVd/DTVK6ofnwRTQ==} + use-breakpoint@4.0.10: + resolution: {integrity: sha512-rnUpZwCQCTtexbpM8S5aiJrfIx6NTvt0WwATiH4hCBN6gQNgkYPFoFt6g/3pAuyqU9D9tLKwXfsVqEWMBnwo6A==} peerDependencies: react: '>=18' react-dom: '>=18' @@ -2915,8 +2918,8 @@ packages: peerDependencies: react: '>=16.13' - use-sync-external-store@1.5.0: - resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2947,8 +2950,8 @@ packages: peerDependencies: vite: '>=2.0.0-beta.69' - vite@7.1.7: - resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==} + vite@7.2.2: + resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3086,23 +3089,23 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.4': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.28.4': + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -3112,19 +3115,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.3': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.26.2 + browserslist: 4.28.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -3132,59 +3135,59 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 - '@babel/parser@7.28.4': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/traverse@7.28.4': + '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.4': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 '@biomejs/biome@2.2.2': optionalDependencies: @@ -3259,19 +3262,19 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.1.13)(react@19.1.1)': + '@emotion/react@11.14.0(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.1) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 19.1.1 + react: 19.2.0 optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 transitivePeerDependencies: - supports-color @@ -3281,111 +3284,111 @@ snapshots: '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 '@emotion/utils': 1.4.2 - csstype: 3.1.3 + csstype: 3.2.0 '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(react@19.1.1)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.4)(react@19.2.0))(@types/react@19.2.4)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.1.13)(react@19.1.1) + '@emotion/react': 11.14.0(@types/react@19.2.4)(react@19.2.0) '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.1) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) '@emotion/utils': 1.4.2 - react: 19.1.1 + react: 19.2.0 optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 transitivePeerDependencies: - supports-color '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.1.1)': + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 '@emotion/utils@1.4.2': {} '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.10': + '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.10': + '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.25.10': + '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-x64@0.25.10': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.25.10': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-x64@0.25.10': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.25.10': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.25.10': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/linux-arm64@0.25.10': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm@0.25.10': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-ia32@0.25.10': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-loong64@0.25.10': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.25.10': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ppc64@0.25.10': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.25.10': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-s390x@0.25.10': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-x64@0.25.10': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.25.10': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.25.10': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.10': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.25.10': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.25.10': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/sunos-x64@0.25.10': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-arm64@0.25.10': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-ia32@0.25.10': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-x64@0.25.10': + '@esbuild/win32-x64@0.25.12': optional: true '@floating-ui/core@1.7.3': @@ -3397,44 +3400,44 @@ snapshots: '@floating-ui/core': 1.7.3 '@floating-ui/utils': 0.2.10 - '@floating-ui/react-dom@2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@floating-ui/react-dom@2.1.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@floating-ui/dom': 1.7.4 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - '@floating-ui/react@0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@floating-ui/react@0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@floating-ui/utils': 0.2.10 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - tabbable: 6.2.0 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + tabbable: 6.3.0 '@floating-ui/utils@0.2.10': {} '@github/webauthn-json@2.1.1': {} - '@hookform/devtools@4.4.0(@types/react@19.1.13)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@hookform/devtools@4.4.0(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@emotion/react': 11.14.0(@types/react@19.1.13)(react@19.1.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.13)(react@19.1.1))(@types/react@19.1.13)(react@19.1.1) + '@emotion/react': 11.14.0(@types/react@19.2.4)(react@19.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.4)(react@19.2.0))(@types/react@19.2.4)(react@19.2.0) '@types/lodash': 4.17.20 - little-state-machine: 4.8.1(react@19.1.1) + little-state-machine: 4.8.1(react@19.2.0) lodash: 4.17.21 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - react-simple-animate: 3.5.3(react-dom@19.1.1(react@19.1.1)) - use-deep-compare-effect: 1.8.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-simple-animate: 3.5.3(react-dom@19.2.0(react@19.2.0)) + use-deep-compare-effect: 1.8.1(react@19.2.0) uuid: 8.3.2 transitivePeerDependencies: - '@types/react' - supports-color - '@hookform/resolvers@5.2.2(react-hook-form@7.63.0(react@19.1.1))': + '@hookform/resolvers@5.2.2(react-hook-form@7.66.0(react@19.2.0))': dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.63.0(react@19.1.1) + react-hook-form: 7.66.0(react@19.2.0) '@hutson/parse-repository-url@3.0.2': {} @@ -3463,107 +3466,107 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@react-hook/latest@1.0.3(react@19.1.1)': + '@react-hook/latest@1.0.3(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-hook/passive-layout-effect@1.2.1(react@19.1.1)': + '@react-hook/passive-layout-effect@1.2.1(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-hook/resize-observer@2.0.2(react@19.1.1)': + '@react-hook/resize-observer@2.0.2(react@19.2.0)': dependencies: - '@react-hook/latest': 1.0.3(react@19.1.1) - '@react-hook/passive-layout-effect': 1.2.1(react@19.1.1) - react: 19.1.1 + '@react-hook/latest': 1.0.3(react@19.2.0) + '@react-hook/passive-layout-effect': 1.2.1(react@19.2.0) + react: 19.2.0 - '@react-rxjs/core@0.10.8(react@19.1.1)(rxjs@7.8.2)': + '@react-rxjs/core@0.10.8(react@19.2.0)(rxjs@7.8.2)': dependencies: '@rx-state/core': 0.1.4(rxjs@7.8.2) - react: 19.1.1 + react: 19.2.0 rxjs: 7.8.2 - use-sync-external-store: 1.5.0(react@19.1.1) + use-sync-external-store: 1.6.0(react@19.2.0) - '@reduxjs/toolkit@2.9.0(react-redux@9.2.0(@types/react@19.1.13)(react@19.1.1)(redux@5.0.1))(react@19.1.1)': + '@reduxjs/toolkit@2.10.1(react-redux@9.2.0(@types/react@19.2.4)(react@19.2.0)(redux@5.0.1))(react@19.2.0)': dependencies: '@standard-schema/spec': 1.0.0 '@standard-schema/utils': 0.3.0 - immer: 10.1.3 + immer: 10.2.0 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) reselect: 5.1.1 optionalDependencies: - react: 19.1.1 - react-redux: 9.2.0(@types/react@19.1.13)(react@19.1.1)(redux@5.0.1) + react: 19.2.0 + react-redux: 9.2.0(@types/react@19.2.4)(react@19.2.0)(redux@5.0.1) - '@remix-run/router@1.23.0': {} + '@remix-run/router@1.23.1': {} - '@rolldown/pluginutils@1.0.0-beta.35': {} + '@rolldown/pluginutils@1.0.0-beta.47': {} - '@rollup/rollup-android-arm-eabi@4.52.2': + '@rollup/rollup-android-arm-eabi@4.53.2': optional: true - '@rollup/rollup-android-arm64@4.52.2': + '@rollup/rollup-android-arm64@4.53.2': optional: true - '@rollup/rollup-darwin-arm64@4.52.2': + '@rollup/rollup-darwin-arm64@4.53.2': optional: true - '@rollup/rollup-darwin-x64@4.52.2': + '@rollup/rollup-darwin-x64@4.53.2': optional: true - '@rollup/rollup-freebsd-arm64@4.52.2': + '@rollup/rollup-freebsd-arm64@4.53.2': optional: true - '@rollup/rollup-freebsd-x64@4.52.2': + '@rollup/rollup-freebsd-x64@4.53.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.52.2': + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.52.2': + '@rollup/rollup-linux-arm-musleabihf@4.53.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.52.2': + '@rollup/rollup-linux-arm64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.52.2': + '@rollup/rollup-linux-arm64-musl@4.53.2': optional: true - '@rollup/rollup-linux-loong64-gnu@4.52.2': + '@rollup/rollup-linux-loong64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.52.2': + '@rollup/rollup-linux-ppc64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.52.2': + '@rollup/rollup-linux-riscv64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.52.2': + '@rollup/rollup-linux-riscv64-musl@4.53.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.52.2': + '@rollup/rollup-linux-s390x-gnu@4.53.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.52.2': + '@rollup/rollup-linux-x64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-x64-musl@4.52.2': + '@rollup/rollup-linux-x64-musl@4.53.2': optional: true - '@rollup/rollup-openharmony-arm64@4.52.2': + '@rollup/rollup-openharmony-arm64@4.53.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.52.2': + '@rollup/rollup-win32-arm64-msvc@4.53.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.52.2': + '@rollup/rollup-win32-ia32-msvc@4.53.2': optional: true - '@rollup/rollup-win32-x64-gnu@4.52.2': + '@rollup/rollup-win32-x64-gnu@4.53.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.52.2': + '@rollup/rollup-win32-x64-msvc@4.53.2': optional: true '@rx-state/core@0.1.4(rxjs@7.8.2)': @@ -3601,51 +3604,51 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@swc/core-darwin-arm64@1.13.19': + '@swc/core-darwin-arm64@1.15.2': optional: true - '@swc/core-darwin-x64@1.13.19': + '@swc/core-darwin-x64@1.15.2': optional: true - '@swc/core-linux-arm-gnueabihf@1.13.19': + '@swc/core-linux-arm-gnueabihf@1.15.2': optional: true - '@swc/core-linux-arm64-gnu@1.13.19': + '@swc/core-linux-arm64-gnu@1.15.2': optional: true - '@swc/core-linux-arm64-musl@1.13.19': + '@swc/core-linux-arm64-musl@1.15.2': optional: true - '@swc/core-linux-x64-gnu@1.13.19': + '@swc/core-linux-x64-gnu@1.15.2': optional: true - '@swc/core-linux-x64-musl@1.13.19': + '@swc/core-linux-x64-musl@1.15.2': optional: true - '@swc/core-win32-arm64-msvc@1.13.19': + '@swc/core-win32-arm64-msvc@1.15.2': optional: true - '@swc/core-win32-ia32-msvc@1.13.19': + '@swc/core-win32-ia32-msvc@1.15.2': optional: true - '@swc/core-win32-x64-msvc@1.13.19': + '@swc/core-win32-x64-msvc@1.15.2': optional: true - '@swc/core@1.13.19': + '@swc/core@1.15.2': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.13.19 - '@swc/core-darwin-x64': 1.13.19 - '@swc/core-linux-arm-gnueabihf': 1.13.19 - '@swc/core-linux-arm64-gnu': 1.13.19 - '@swc/core-linux-arm64-musl': 1.13.19 - '@swc/core-linux-x64-gnu': 1.13.19 - '@swc/core-linux-x64-musl': 1.13.19 - '@swc/core-win32-arm64-msvc': 1.13.19 - '@swc/core-win32-ia32-msvc': 1.13.19 - '@swc/core-win32-x64-msvc': 1.13.19 + '@swc/core-darwin-arm64': 1.15.2 + '@swc/core-darwin-x64': 1.15.2 + '@swc/core-linux-arm-gnueabihf': 1.15.2 + '@swc/core-linux-arm64-gnu': 1.15.2 + '@swc/core-linux-arm64-musl': 1.15.2 + '@swc/core-linux-x64-gnu': 1.15.2 + '@swc/core-linux-x64-musl': 1.15.2 + '@swc/core-win32-arm64-msvc': 1.15.2 + '@swc/core-win32-ia32-msvc': 1.15.2 + '@swc/core-win32-x64-msvc': 1.15.2 '@swc/counter@0.1.3': {} @@ -3653,26 +3656,26 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@tanstack/query-core@5.90.2': {} + '@tanstack/query-core@5.90.9': {} '@tanstack/query-devtools@5.90.1': {} - '@tanstack/react-query-devtools@5.90.2(@tanstack/react-query@5.90.2(react@19.1.1))(react@19.1.1)': + '@tanstack/react-query-devtools@5.90.2(@tanstack/react-query@5.90.9(react@19.2.0))(react@19.2.0)': dependencies: '@tanstack/query-devtools': 5.90.1 - '@tanstack/react-query': 5.90.2(react@19.1.1) - react: 19.1.1 + '@tanstack/react-query': 5.90.9(react@19.2.0) + react: 19.2.0 - '@tanstack/react-query@5.90.2(react@19.1.1)': + '@tanstack/react-query@5.90.9(react@19.2.0)': dependencies: - '@tanstack/query-core': 5.90.2 - react: 19.1.1 + '@tanstack/query-core': 5.90.9 + react: 19.2.0 - '@tanstack/react-virtual@3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@tanstack/react-virtual@3.13.12(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@tanstack/virtual-core': 3.13.12 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) '@tanstack/virtual-core@3.13.12': {} @@ -3736,9 +3739,9 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@24.5.2': + '@types/node@24.10.1': dependencies: - undici-types: 7.12.0 + undici-types: 7.16.0 '@types/normalize-package-data@2.4.4': {} @@ -3746,24 +3749,24 @@ snapshots: '@types/qs@6.14.0': {} - '@types/react-dom@19.1.9(@types/react@19.1.13)': + '@types/react-dom@19.2.3(@types/react@19.2.4)': dependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 19.1.13 + '@types/react': 19.2.4 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 19.1.13 + '@types/react': 19.2.4 - '@types/react@19.1.13': + '@types/react@19.2.4': dependencies: - csstype: 3.1.3 + csstype: 3.2.0 '@types/unist@2.0.11': {} @@ -3775,16 +3778,16 @@ snapshots: '@use-gesture/core@10.3.1': {} - '@use-gesture/react@10.3.1(react@19.1.1)': + '@use-gesture/react@10.3.1(react@19.2.0)': dependencies: '@use-gesture/core': 10.3.1 - react: 19.1.1 + react: 19.2.0 - '@vitejs/plugin-react-swc@4.1.0(vite@7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1))': + '@vitejs/plugin-react-swc@4.2.2(vite@7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1))': dependencies: - '@rolldown/pluginutils': 1.0.0-beta.35 - '@swc/core': 1.13.19 - vite: 7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) + '@rolldown/pluginutils': 1.0.0-beta.47 + '@swc/core': 1.15.2 + vite: 7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - '@swc/helpers' @@ -3819,17 +3822,17 @@ snapshots: asynckit@0.4.0: {} - autoprefixer@10.4.21(postcss@8.5.6): + autoprefixer@10.4.22(postcss@8.5.6): dependencies: - browserslist: 4.26.2 - caniuse-lite: 1.0.30001745 - fraction.js: 4.3.7 + browserslist: 4.28.0 + caniuse-lite: 1.0.30001754 + fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 - axios@1.12.2: + axios@1.13.2: dependencies: follow-redirects: 1.15.11 form-data: 4.0.4 @@ -3841,13 +3844,13 @@ snapshots: dependencies: '@babel/runtime': 7.28.4 cosmiconfig: 7.1.0 - resolve: 1.22.10 + resolve: 1.22.11 bail@2.0.2: {} balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.7: {} + baseline-browser-mapping@2.8.28: {} bignumber.js@9.3.1: {} @@ -3862,13 +3865,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.26.2: + browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.8.7 - caniuse-lite: 1.0.30001745 - electron-to-chromium: 1.5.224 - node-releases: 2.0.21 - update-browserslist-db: 1.1.3(browserslist@4.26.2) + baseline-browser-mapping: 2.8.28 + caniuse-lite: 1.0.30001754 + electron-to-chromium: 1.5.252 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.28.0) buffer-from@1.1.2: {} @@ -3894,7 +3897,7 @@ snapshots: camelcase@5.3.1: {} - caniuse-lite@1.0.30001745: {} + caniuse-lite@1.0.30001754: {} ccount@2.0.1: {} @@ -4121,7 +4124,7 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - csstype@3.1.3: {} + csstype@3.2.0: {} d3-array@3.2.4: dependencies: @@ -4167,7 +4170,7 @@ snapshots: dateformat@3.0.3: {} - dayjs@1.11.18: {} + dayjs@1.11.19: {} debug@4.4.3: dependencies: @@ -4230,7 +4233,7 @@ snapshots: dependencies: is-obj: 2.0.0 - dotenv@17.2.2: {} + dotenv@17.2.3: {} dotgitignore@2.1.0: dependencies: @@ -4243,7 +4246,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.224: {} + electron-to-chromium@1.5.252: {} emoji-regex@8.0.0: {} @@ -4270,36 +4273,36 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - es-toolkit@1.39.10: {} + es-toolkit@1.41.0: {} - esbuild@0.25.10: + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -4361,17 +4364,17 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 - fraction.js@4.3.7: {} + fraction.js@5.3.4: {} - framer-motion@12.23.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + framer-motion@12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - motion-dom: 12.23.21 + motion-dom: 12.23.23 motion-utils: 12.23.6 tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) fsevents@2.3.3: optional: true @@ -4437,7 +4440,7 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@16.4.0: {} + globals@16.5.0: {} gopd@1.2.0: {} @@ -4523,7 +4526,7 @@ snapshots: mdast-util-mdxjs-esm: 2.0.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 - style-to-js: 1.1.17 + style-to-js: 1.1.19 unist-util-position: 5.0.0 vfile-message: 4.0.3 transitivePeerDependencies: @@ -4568,15 +4571,15 @@ snapshots: domhandler: 5.0.3 htmlparser2: 10.0.0 - html-react-parser@5.2.6(@types/react@19.1.13)(react@19.1.1): + html-react-parser@5.2.8(@types/react@19.2.4)(react@19.2.0): dependencies: domhandler: 5.0.3 html-dom-parser: 5.1.1 - react: 19.1.1 + react: 19.2.0 react-property: 2.0.2 - style-to-js: 1.1.17 + style-to-js: 1.1.19 optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 html-url-attributes@3.0.1: {} @@ -4591,7 +4594,7 @@ snapshots: humanize-duration@3.33.1: {} - immer@10.1.3: {} + immer@10.2.0: {} immutable@4.3.7: {} @@ -4606,7 +4609,7 @@ snapshots: ini@1.3.8: {} - inline-style-parser@0.2.4: {} + inline-style-parser@0.2.6: {} internmap@2.0.3: {} @@ -4682,9 +4685,9 @@ snapshots: lines-and-columns@1.2.4: {} - little-state-machine@4.8.1(react@19.1.1): + little-state-machine@4.8.1(react@19.2.0): dependencies: - react: 19.1.1 + react: 19.2.0 load-json-file@4.0.0: dependencies: @@ -4796,7 +4799,7 @@ snapshots: mdast-util-phrasing@4.1.0: dependencies: '@types/mdast': 4.0.4 - unist-util-is: 6.0.0 + unist-util-is: 6.0.1 mdast-util-to-hast@13.2.0: dependencies: @@ -4840,9 +4843,9 @@ snapshots: type-fest: 0.18.1 yargs-parser: 20.2.9 - merge-refs@2.0.0(@types/react@19.1.13): + merge-refs@2.0.0(@types/react@19.2.4): optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 micromark-core-commonmark@2.0.3: dependencies: @@ -5003,20 +5006,20 @@ snapshots: modify-values@1.0.1: {} - motion-dom@12.23.21: + motion-dom@12.23.23: dependencies: motion-utils: 12.23.6 motion-utils@12.23.6: {} - motion@12.23.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + motion@12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - framer-motion: 12.23.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + framer-motion: 12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) ms@2.1.3: {} @@ -5026,12 +5029,12 @@ snapshots: neo-async@2.6.2: {} - node-releases@2.0.21: {} + node-releases@2.0.27: {} normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.10 + resolve: 1.22.11 semver: 5.7.2 validate-npm-package-license: 3.0.4 @@ -5039,7 +5042,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -5184,57 +5187,57 @@ snapshots: radash@12.1.1: {} - react-click-away-listener@2.4.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-click-away-listener@2.4.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - react-datepicker@8.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-datepicker@8.9.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@floating-ui/react': 0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@floating-ui/react': 0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0) clsx: 2.1.1 date-fns: 4.1.0 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - react-dom@19.1.1(react@19.1.1): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.1.1 - scheduler: 0.26.0 + react: 19.2.0 + scheduler: 0.27.0 - react-hook-form@7.63.0(react@19.1.1): + react-hook-form@7.66.0(react@19.2.0): dependencies: - react: 19.1.1 + react: 19.2.0 - react-idle-timer@5.7.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-idle-timer@5.7.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - react-intersection-observer@9.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-intersection-observer@9.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.1.1 + react: 19.2.0 optionalDependencies: - react-dom: 19.1.1(react@19.1.1) + react-dom: 19.2.0(react@19.2.0) react-is@16.13.1: {} - react-is@19.1.1: {} + react-is@19.2.0: {} - react-loading-skeleton@3.5.0(react@19.1.1): + react-loading-skeleton@3.5.0(react@19.2.0): dependencies: - react: 19.1.1 + react: 19.2.0 - react-markdown@10.1.0(@types/react@19.1.13)(react@19.1.1): + react-markdown@10.1.0(@types/react@19.2.4)(react@19.2.0): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.1.13 + '@types/react': 19.2.4 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 mdast-util-to-hast: 13.2.0 - react: 19.1.1 + react: 19.2.0 remark-parse: 11.0.0 remark-rehype: 11.1.2 unified: 11.0.5 @@ -5245,55 +5248,55 @@ snapshots: react-property@2.0.2: {} - react-qr-code@2.0.18(react@19.1.1): + react-qr-code@2.0.18(react@19.2.0): dependencies: prop-types: 15.8.1 qr.js: 0.0.0 - react: 19.1.1 + react: 19.2.0 - react-redux@9.2.0(@types/react@19.1.13)(react@19.1.1)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.4)(react@19.2.0)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 - react: 19.1.1 - use-sync-external-store: 1.5.0(react@19.1.1) + react: 19.2.0 + use-sync-external-store: 1.6.0(react@19.2.0) optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.2.4 redux: 5.0.1 - react-resize-detector@12.3.0(react@19.1.1): + react-resize-detector@12.3.0(react@19.2.0): dependencies: - es-toolkit: 1.39.10 - react: 19.1.1 + es-toolkit: 1.41.0 + react: 19.2.0 - react-router-dom@6.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-router-dom@6.30.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@remix-run/router': 1.23.0 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - react-router: 6.30.1(react@19.1.1) + '@remix-run/router': 1.23.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-router: 6.30.2(react@19.2.0) - react-router@6.30.1(react@19.1.1): + react-router@6.30.2(react@19.2.0): dependencies: - '@remix-run/router': 1.23.0 - react: 19.1.1 + '@remix-run/router': 1.23.1 + react: 19.2.0 - react-simple-animate@3.5.3(react-dom@19.1.1(react@19.1.1)): + react-simple-animate@3.5.3(react-dom@19.2.0(react@19.2.0)): dependencies: - react-dom: 19.1.1(react@19.1.1) + react-dom: 19.2.0(react@19.2.0) - react-tracked@2.0.1(react@19.1.1)(scheduler@0.26.0): + react-tracked@2.0.1(react@19.2.0)(scheduler@0.26.0): dependencies: proxy-compare: 3.0.1 - react: 19.1.1 + react: 19.2.0 scheduler: 0.26.0 - use-context-selector: 2.0.0(react@19.1.1)(scheduler@0.26.0) + use-context-selector: 2.0.0(react@19.2.0)(scheduler@0.26.0) - react-virtualized-auto-sizer@1.0.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + react-virtualized-auto-sizer@1.0.26(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - react@19.1.1: {} + react@19.2.0: {} read-pkg-up@3.0.0: dependencies: @@ -5339,21 +5342,21 @@ snapshots: dependencies: picomatch: 2.3.1 - recharts@3.2.1(@types/react@19.1.13)(react-dom@19.1.1(react@19.1.1))(react-is@19.1.1)(react@19.1.1)(redux@5.0.1): + recharts@3.4.1(@types/react@19.2.4)(react-dom@19.2.0(react@19.2.0))(react-is@19.2.0)(react@19.2.0)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.9.0(react-redux@9.2.0(@types/react@19.1.13)(react@19.1.1)(redux@5.0.1))(react@19.1.1) + '@reduxjs/toolkit': 2.10.1(react-redux@9.2.0(@types/react@19.2.4)(react@19.2.0)(redux@5.0.1))(react@19.2.0) clsx: 2.1.1 decimal.js-light: 2.5.1 - es-toolkit: 1.39.10 + es-toolkit: 1.41.0 eventemitter3: 5.0.1 - immer: 10.1.3 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - react-is: 19.1.1 - react-redux: 9.2.0(@types/react@19.1.13)(react@19.1.1)(redux@5.0.1) + immer: 10.2.0 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-is: 19.2.0 + react-redux: 9.2.0(@types/react@19.2.4)(react@19.2.0)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 - use-sync-external-store: 1.5.0(react@19.1.1) + use-sync-external-store: 1.6.0(react@19.2.0) victory-vendor: 37.3.6 transitivePeerDependencies: - '@types/react' @@ -5415,38 +5418,38 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.10: + resolve@1.22.11: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup@4.52.2: + rollup@4.53.2: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.2 - '@rollup/rollup-android-arm64': 4.52.2 - '@rollup/rollup-darwin-arm64': 4.52.2 - '@rollup/rollup-darwin-x64': 4.52.2 - '@rollup/rollup-freebsd-arm64': 4.52.2 - '@rollup/rollup-freebsd-x64': 4.52.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.2 - '@rollup/rollup-linux-arm-musleabihf': 4.52.2 - '@rollup/rollup-linux-arm64-gnu': 4.52.2 - '@rollup/rollup-linux-arm64-musl': 4.52.2 - '@rollup/rollup-linux-loong64-gnu': 4.52.2 - '@rollup/rollup-linux-ppc64-gnu': 4.52.2 - '@rollup/rollup-linux-riscv64-gnu': 4.52.2 - '@rollup/rollup-linux-riscv64-musl': 4.52.2 - '@rollup/rollup-linux-s390x-gnu': 4.52.2 - '@rollup/rollup-linux-x64-gnu': 4.52.2 - '@rollup/rollup-linux-x64-musl': 4.52.2 - '@rollup/rollup-openharmony-arm64': 4.52.2 - '@rollup/rollup-win32-arm64-msvc': 4.52.2 - '@rollup/rollup-win32-ia32-msvc': 4.52.2 - '@rollup/rollup-win32-x64-gnu': 4.52.2 - '@rollup/rollup-win32-x64-msvc': 4.52.2 + '@rollup/rollup-android-arm-eabi': 4.53.2 + '@rollup/rollup-android-arm64': 4.53.2 + '@rollup/rollup-darwin-arm64': 4.53.2 + '@rollup/rollup-darwin-x64': 4.53.2 + '@rollup/rollup-freebsd-arm64': 4.53.2 + '@rollup/rollup-freebsd-x64': 4.53.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.2 + '@rollup/rollup-linux-arm-musleabihf': 4.53.2 + '@rollup/rollup-linux-arm64-gnu': 4.53.2 + '@rollup/rollup-linux-arm64-musl': 4.53.2 + '@rollup/rollup-linux-loong64-gnu': 4.53.2 + '@rollup/rollup-linux-ppc64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-musl': 4.53.2 + '@rollup/rollup-linux-s390x-gnu': 4.53.2 + '@rollup/rollup-linux-x64-gnu': 4.53.2 + '@rollup/rollup-linux-x64-musl': 4.53.2 + '@rollup/rollup-openharmony-arm64': 4.53.2 + '@rollup/rollup-win32-arm64-msvc': 4.53.2 + '@rollup/rollup-win32-ia32-msvc': 4.53.2 + '@rollup/rollup-win32-x64-gnu': 4.53.2 + '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 rxjs@7.8.2: @@ -5465,11 +5468,13 @@ snapshots: scheduler@0.26.0: {} + scheduler@0.27.0: {} + semver@5.7.2: {} semver@6.3.1: {} - semver@7.7.2: {} + semver@7.7.3: {} set-blocking@2.0.0: {} @@ -5552,7 +5557,7 @@ snapshots: figures: 3.2.0 find-up: 5.0.0 git-semver-tags: 4.1.1 - semver: 7.7.2 + semver: 7.7.3 stringify-package: 1.0.1 yargs: 16.2.0 @@ -5587,13 +5592,13 @@ snapshots: dependencies: min-indent: 1.0.1 - style-to-js@1.1.17: + style-to-js@1.1.19: dependencies: - style-to-object: 1.0.9 + style-to-object: 1.0.12 - style-to-object@1.0.9: + style-to-object@1.0.12: dependencies: - inline-style-parser: 0.2.4 + inline-style-parser: 0.2.6 stylis@4.2.0: {} @@ -5611,7 +5616,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tabbable@6.2.0: {} + tabbable@6.3.0: {} terser@5.37.0: dependencies: @@ -5758,16 +5763,16 @@ snapshots: typedarray@0.0.6: {} - typesafe-i18n@5.26.2(typescript@5.9.2): + typesafe-i18n@5.26.2(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 - typescript@5.9.2: {} + typescript@5.9.3: {} uglify-js@3.19.3: optional: true - undici-types@7.12.0: {} + undici-types@7.16.0: {} unified@11.0.5: dependencies: @@ -5779,7 +5784,7 @@ snapshots: trough: 2.2.0 vfile: 6.0.3 - unist-util-is@6.0.0: + unist-util-is@6.0.1: dependencies: '@types/unist': 3.0.3 @@ -5791,42 +5796,42 @@ snapshots: dependencies: '@types/unist': 3.0.3 - unist-util-visit-parents@6.0.1: + unist-util-visit-parents@6.0.2: dependencies: '@types/unist': 3.0.3 - unist-util-is: 6.0.0 + unist-util-is: 6.0.1 unist-util-visit@5.0.0: dependencies: '@types/unist': 3.0.3 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 - update-browserslist-db@1.1.3(browserslist@4.26.2): + update-browserslist-db@1.1.4(browserslist@4.28.0): dependencies: - browserslist: 4.26.2 + browserslist: 4.28.0 escalade: 3.2.0 picocolors: 1.1.1 - use-breakpoint@4.0.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + use-breakpoint@4.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) - use-context-selector@2.0.0(react@19.1.1)(scheduler@0.26.0): + use-context-selector@2.0.0(react@19.2.0)(scheduler@0.26.0): dependencies: - react: 19.1.1 + react: 19.2.0 scheduler: 0.26.0 - use-deep-compare-effect@1.8.1(react@19.1.1): + use-deep-compare-effect@1.8.1(react@19.2.0): dependencies: '@babel/runtime': 7.28.4 dequal: 2.0.3 - react: 19.1.1 + react: 19.2.0 - use-sync-external-store@1.5.0(react@19.1.1): + use-sync-external-store@1.6.0(react@19.2.0): dependencies: - react: 19.1.1 + react: 19.2.0 util-deprecate@1.0.2: {} @@ -5869,20 +5874,20 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-package-version@1.1.0(vite@7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)): + vite-plugin-package-version@1.1.0(vite@7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1)): dependencies: - vite: 7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) + vite: 7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1) - vite@7.1.7(@types/node@24.5.2)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1): + vite@7.2.2(@types/node@24.10.1)(jiti@2.4.2)(sass@1.70.0)(terser@5.37.0)(yaml@2.6.1): dependencies: - esbuild: 0.25.10 + esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.2 + rollup: 4.53.2 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.5.2 + '@types/node': 24.10.1 fsevents: 2.3.3 jiti: 2.4.2 sass: 1.70.0 @@ -5969,11 +5974,11 @@ snapshots: zod@3.25.76: {} - zustand@5.0.8(@types/react@19.1.13)(immer@10.1.3)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)): + zustand@5.0.8(@types/react@19.2.4)(immer@10.2.0)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)): optionalDependencies: - '@types/react': 19.1.13 - immer: 10.1.3 - react: 19.1.1 - use-sync-external-store: 1.5.0(react@19.1.1) + '@types/react': 19.2.4 + immer: 10.2.0 + react: 19.2.0 + use-sync-external-store: 1.6.0(react@19.2.0) zwitch@2.0.4: {} diff --git a/web/src/i18n/en/index.ts b/web/src/i18n/en/index.ts index 76f8484653..f4b94015e6 100644 --- a/web/src/i18n/en/index.ts +++ b/web/src/i18n/en/index.ts @@ -1388,6 +1388,10 @@ Licensing information: [https://docs.defguard.net/enterprise/license](https://do enable_directory_sync: { label: 'Enable directory synchronization', }, + prefetch_users: { + label: 'Prefetch users', + helper: 'Fetch users from external provider and create user accounts in Defguard without waiting for them to log in', + }, sync_target: { label: 'Synchronize', helper: diff --git a/web/src/i18n/i18n-types.ts b/web/src/i18n/i18n-types.ts index e934c44085..2313f93c1c 100644 --- a/web/src/i18n/i18n-types.ts +++ b/web/src/i18n/i18n-types.ts @@ -3416,6 +3416,16 @@ type RootTranslation = { */ label: string } + prefetch_users: { + /** + * P​r​e​f​e​t​c​h​ ​u​s​e​r​s + */ + label: string + /** + * F​e​t​c​h​ ​u​s​e​r​s​ ​f​r​o​m​ ​e​x​t​e​r​n​a​l​ ​p​r​o​v​i​d​e​r​ ​a​n​d​ ​c​r​e​a​t​e​ ​u​s​e​r​ ​a​c​c​o​u​n​t​s​ ​i​n​ ​D​e​f​g​u​a​r​d​ ​w​i​t​h​o​u​t​ ​w​a​i​t​i​n​g​ ​f​o​r​ ​t​h​e​m​ ​t​o​ ​l​o​g​ ​i​n + */ + helper: string + } sync_target: { /** * S​y​n​c​h​r​o​n​i​z​e @@ -10141,6 +10151,16 @@ export type TranslationFunctions = { */ label: () => LocalizedString } + prefetch_users: { + /** + * Prefetch users + */ + label: () => LocalizedString + /** + * Fetch users from external provider and create user accounts in Defguard without waiting for them to log in + */ + helper: () => LocalizedString + } sync_target: { /** * Synchronize diff --git a/web/src/pages/settings/components/OpenIdSettings/components/DirectorySyncSettings.tsx b/web/src/pages/settings/components/OpenIdSettings/components/DirectorySyncSettings.tsx index a859fbbfca..d60e136342 100644 --- a/web/src/pages/settings/components/OpenIdSettings/components/DirectorySyncSettings.tsx +++ b/web/src/pages/settings/components/OpenIdSettings/components/DirectorySyncSettings.tsx @@ -5,10 +5,10 @@ import { useMemo, useState } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; import { useI18nContext } from '../../../../../i18n/i18n-react'; +import { FormCheckBox } from '../../../../../shared/defguard-ui/components/Form/FormCheckBox/FormCheckBox'; import { FormInput } from '../../../../../shared/defguard-ui/components/Form/FormInput/FormInput'; import { FormSelect } from '../../../../../shared/defguard-ui/components/Form/FormSelect/FormSelect'; import { Helper } from '../../../../../shared/defguard-ui/components/Layout/Helper/Helper'; -import { LabeledCheckbox } from '../../../../../shared/defguard-ui/components/Layout/LabeledCheckbox/LabeledCheckbox'; import SvgIconDownload from '../../../../../shared/defguard-ui/components/svg/IconDownload'; import { titleCase } from '../../../../../shared/utils/titleCase'; import { SUPPORTED_SYNC_PROVIDERS } from './SupportedProviders'; @@ -80,16 +80,11 @@ export const DirsyncSettings = ({ isLoading }: { isLoading: boolean }) => {
{showDirsync ? ( <> -
- {/* FIXME: Really buggy when using the controller, investigate why */} - setValue('directory_sync_enabled', val)} - // controller={{ control, name: 'directory_sync_enabled' }} - /> -
+ { disabled={isLoading} /> {providerName === 'Microsoft' ? ( - {parse(localLL.form.labels.group_match.helper())} - } - required={false} - > + <> +
+ + {localLL.form.labels.prefetch_users.helper()} +
+ {parse(localLL.form.labels.group_match.helper())} + } + required={false} + /> + ) : null} {providerName === 'Okta' ? ( <> diff --git a/web/src/pages/settings/components/OpenIdSettings/components/OpenIdSettingsForm.tsx b/web/src/pages/settings/components/OpenIdSettings/components/OpenIdSettingsForm.tsx index ec3215c2b4..992c57a543 100644 --- a/web/src/pages/settings/components/OpenIdSettings/components/OpenIdSettingsForm.tsx +++ b/web/src/pages/settings/components/OpenIdSettings/components/OpenIdSettingsForm.tsx @@ -102,6 +102,7 @@ export const OpenIdSettingsForm = () => { google_service_account_email: z.string(), google_service_account_key: z.string(), directory_sync_enabled: z.boolean(), + prefetch_users: z.boolean(), directory_sync_interval: z.number().min(60, LL.form.error.invalid()), directory_sync_user_behavior: z.enum(['keep', 'disable', 'delete']), directory_sync_admin_behavior: z.enum(['keep', 'disable', 'delete']), @@ -175,6 +176,7 @@ export const OpenIdSettingsForm = () => { google_service_account_email: '', google_service_account_key: '', directory_sync_enabled: false, + prefetch_users: false, directory_sync_interval: 600, directory_sync_user_behavior: 'keep', directory_sync_admin_behavior: 'keep', diff --git a/web/src/pages/settings/components/OpenIdSettings/components/style.scss b/web/src/pages/settings/components/OpenIdSettings/components/style.scss index 017b6c9d4e..0e9f73a849 100644 --- a/web/src/pages/settings/components/OpenIdSettings/components/style.scss +++ b/web/src/pages/settings/components/OpenIdSettings/components/style.scss @@ -76,8 +76,14 @@ justify-content: flex-end; } - .labeled-checkbox { - padding-bottom: var(--spacing-s); + #directory-sync-settings { + & > .form-checkbox { + padding-bottom: var(--spacing-s); + } + + .helper-row { + padding-bottom: var(--spacing-s); + } } } diff --git a/web/src/shared/validators.ts b/web/src/shared/validators.ts index 4bc73aa9df..77df62d88a 100644 --- a/web/src/shared/validators.ts +++ b/web/src/shared/validators.ts @@ -69,6 +69,9 @@ export const validateIpOrDomainList = ( // Returns false when invalid export const validateIPv4 = (ip: string, allowMask = false): boolean => { if (allowMask) { + if (ip.endsWith('/0')) { + return false; + } if (ip.includes('/')) { return ipaddr.IPv4.isValidCIDR(ip); } @@ -78,6 +81,9 @@ export const validateIPv4 = (ip: string, allowMask = false): boolean => { export const validateIPv6 = (ip: string, allowMask = false): boolean => { if (allowMask) { + if (ip.endsWith('/0')) { + return false; + } if (ip.includes('/')) { return ipaddr.IPv6.isValidCIDR(ip); }